| 1 | --- a/fs/fuse/dev.c |
| 2 | +++ b/fs/fuse/dev.c |
| 3 | @@ -533,6 +533,11 @@ static void fuse_copy_finish(struct fuse |
| 4 | } |
| 5 | } |
| 6 | |
| 7 | +#ifdef DCACHE_BUG |
| 8 | +extern void (*fuse_flush_cache_all)(void); |
| 9 | +extern void (*fuse_flush_cache_page)(struct vm_area_struct *vma, unsigned long page, unsigned long pfn); |
| 10 | +#endif |
| 11 | + |
| 12 | /* |
| 13 | * Get another pagefull of userspace buffer, and map it to kernel |
| 14 | * address space, and lock request |
| 15 | @@ -541,6 +546,9 @@ static int fuse_copy_fill(struct fuse_co |
| 16 | { |
| 17 | unsigned long offset; |
| 18 | int err; |
| 19 | +#ifdef DCACHE_BUG |
| 20 | + struct vm_area_struct *vma; |
| 21 | +#endif |
| 22 | |
| 23 | unlock_request(cs->fc, cs->req); |
| 24 | fuse_copy_finish(cs); |
| 25 | @@ -552,14 +560,22 @@ static int fuse_copy_fill(struct fuse_co |
| 26 | cs->nr_segs--; |
| 27 | } |
| 28 | down_read(¤t->mm->mmap_sem); |
| 29 | +#ifndef DCACHE_BUG |
| 30 | err = get_user_pages(current, current->mm, cs->addr, 1, cs->write, 0, |
| 31 | &cs->pg, NULL); |
| 32 | +#else |
| 33 | + err = get_user_pages(current, current->mm, cs->addr, 1, cs->write, 0, |
| 34 | + &cs->pg, &vma); |
| 35 | +#endif |
| 36 | up_read(¤t->mm->mmap_sem); |
| 37 | if (err < 0) |
| 38 | return err; |
| 39 | BUG_ON(err != 1); |
| 40 | offset = cs->addr % PAGE_SIZE; |
| 41 | cs->mapaddr = kmap_atomic(cs->pg, KM_USER0); |
| 42 | +#ifdef DCACHE_BUG |
| 43 | + fuse_flush_cache_page(vma, cs->addr, page_to_pfn(cs->pg)); |
| 44 | +#endif |
| 45 | cs->buf = cs->mapaddr + offset; |
| 46 | cs->len = min(PAGE_SIZE - offset, cs->seglen); |
| 47 | cs->seglen -= cs->len; |
| 48 | @@ -573,6 +589,11 @@ static int fuse_copy_do(struct fuse_copy |
| 49 | { |
| 50 | unsigned ncpy = min(*size, cs->len); |
| 51 | if (val) { |
| 52 | +#ifdef DCACHE_BUG |
| 53 | + // patch from mailing list, it is very important, otherwise, |
| 54 | + // can't mount, or ls mount point will hang |
| 55 | + fuse_flush_cache_all(); |
| 56 | +#endif |
| 57 | if (cs->write) |
| 58 | memcpy(cs->buf, *val, ncpy); |
| 59 | else |
| 60 | --- a/fs/fuse/fuse_i.h |
| 61 | +++ b/fs/fuse/fuse_i.h |
| 62 | @@ -8,6 +8,7 @@ |
| 63 | |
| 64 | #ifndef _FS_FUSE_I_H |
| 65 | #define _FS_FUSE_I_H |
| 66 | +#define DCACHE_BUG |
| 67 | |
| 68 | #include <linux/fuse.h> |
| 69 | #include <linux/fs.h> |
| 70 | --- a/fs/fuse/inode.c |
| 71 | +++ b/fs/fuse/inode.c |
| 72 | @@ -1201,6 +1201,10 @@ static int __init fuse_init(void) |
| 73 | printk(KERN_INFO "fuse init (API version %i.%i)\n", |
| 74 | FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION); |
| 75 | |
| 76 | +#ifdef DCACHE_BUG |
| 77 | +printk("fuse init: DCACHE_BUG enabled\n"); |
| 78 | +#endif |
| 79 | + |
| 80 | INIT_LIST_HEAD(&fuse_conn_list); |
| 81 | res = fuse_fs_init(); |
| 82 | if (res) |
| 83 | |