diff options
Diffstat (limited to 'fs/fuse/inode.c')
-rw-r--r-- | fs/fuse/inode.c | 49 |
1 files changed, 39 insertions, 10 deletions
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index c4fcfd59cd80..7d01c68852a8 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
@@ -59,7 +59,11 @@ static struct inode *fuse_alloc_inode(struct super_block *sb) | |||
59 | fi->nodeid = 0; | 59 | fi->nodeid = 0; |
60 | fi->nlookup = 0; | 60 | fi->nlookup = 0; |
61 | fi->attr_version = 0; | 61 | fi->attr_version = 0; |
62 | fi->writectr = 0; | ||
62 | INIT_LIST_HEAD(&fi->write_files); | 63 | INIT_LIST_HEAD(&fi->write_files); |
64 | INIT_LIST_HEAD(&fi->queued_writes); | ||
65 | INIT_LIST_HEAD(&fi->writepages); | ||
66 | init_waitqueue_head(&fi->page_waitq); | ||
63 | fi->forget_req = fuse_request_alloc(); | 67 | fi->forget_req = fuse_request_alloc(); |
64 | if (!fi->forget_req) { | 68 | if (!fi->forget_req) { |
65 | kmem_cache_free(fuse_inode_cachep, inode); | 69 | kmem_cache_free(fuse_inode_cachep, inode); |
@@ -73,6 +77,7 @@ static void fuse_destroy_inode(struct inode *inode) | |||
73 | { | 77 | { |
74 | struct fuse_inode *fi = get_fuse_inode(inode); | 78 | struct fuse_inode *fi = get_fuse_inode(inode); |
75 | BUG_ON(!list_empty(&fi->write_files)); | 79 | BUG_ON(!list_empty(&fi->write_files)); |
80 | BUG_ON(!list_empty(&fi->queued_writes)); | ||
76 | if (fi->forget_req) | 81 | if (fi->forget_req) |
77 | fuse_request_free(fi->forget_req); | 82 | fuse_request_free(fi->forget_req); |
78 | kmem_cache_free(fuse_inode_cachep, inode); | 83 | kmem_cache_free(fuse_inode_cachep, inode); |
@@ -109,7 +114,7 @@ static int fuse_remount_fs(struct super_block *sb, int *flags, char *data) | |||
109 | return 0; | 114 | return 0; |
110 | } | 115 | } |
111 | 116 | ||
112 | static void fuse_truncate(struct address_space *mapping, loff_t offset) | 117 | void fuse_truncate(struct address_space *mapping, loff_t offset) |
113 | { | 118 | { |
114 | /* See vmtruncate() */ | 119 | /* See vmtruncate() */ |
115 | unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1); | 120 | unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1); |
@@ -117,19 +122,12 @@ static void fuse_truncate(struct address_space *mapping, loff_t offset) | |||
117 | unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1); | 122 | unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1); |
118 | } | 123 | } |
119 | 124 | ||
120 | 125 | void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr, | |
121 | void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr, | 126 | u64 attr_valid) |
122 | u64 attr_valid, u64 attr_version) | ||
123 | { | 127 | { |
124 | struct fuse_conn *fc = get_fuse_conn(inode); | 128 | struct fuse_conn *fc = get_fuse_conn(inode); |
125 | struct fuse_inode *fi = get_fuse_inode(inode); | 129 | struct fuse_inode *fi = get_fuse_inode(inode); |
126 | loff_t oldsize; | ||
127 | 130 | ||
128 | spin_lock(&fc->lock); | ||
129 | if (attr_version != 0 && fi->attr_version > attr_version) { | ||
130 | spin_unlock(&fc->lock); | ||
131 | return; | ||
132 | } | ||
133 | fi->attr_version = ++fc->attr_version; | 131 | fi->attr_version = ++fc->attr_version; |
134 | fi->i_time = attr_valid; | 132 | fi->i_time = attr_valid; |
135 | 133 | ||
@@ -159,6 +157,22 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr, | |||
159 | fi->orig_i_mode = inode->i_mode; | 157 | fi->orig_i_mode = inode->i_mode; |
160 | if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS)) | 158 | if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS)) |
161 | inode->i_mode &= ~S_ISVTX; | 159 | inode->i_mode &= ~S_ISVTX; |
160 | } | ||
161 | |||
162 | void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr, | ||
163 | u64 attr_valid, u64 attr_version) | ||
164 | { | ||
165 | struct fuse_conn *fc = get_fuse_conn(inode); | ||
166 | struct fuse_inode *fi = get_fuse_inode(inode); | ||
167 | loff_t oldsize; | ||
168 | |||
169 | spin_lock(&fc->lock); | ||
170 | if (attr_version != 0 && fi->attr_version > attr_version) { | ||
171 | spin_unlock(&fc->lock); | ||
172 | return; | ||
173 | } | ||
174 | |||
175 | fuse_change_attributes_common(inode, attr, attr_valid); | ||
162 | 176 | ||
163 | oldsize = inode->i_size; | 177 | oldsize = inode->i_size; |
164 | i_size_write(inode, attr->size); | 178 | i_size_write(inode, attr->size); |
@@ -468,6 +482,8 @@ static struct fuse_conn *new_conn(struct super_block *sb) | |||
468 | atomic_set(&fc->num_waiting, 0); | 482 | atomic_set(&fc->num_waiting, 0); |
469 | fc->bdi.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE; | 483 | fc->bdi.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE; |
470 | fc->bdi.unplug_io_fn = default_unplug_io_fn; | 484 | fc->bdi.unplug_io_fn = default_unplug_io_fn; |
485 | /* fuse does it's own writeback accounting */ | ||
486 | fc->bdi.capabilities = BDI_CAP_NO_ACCT_WB; | ||
471 | fc->dev = sb->s_dev; | 487 | fc->dev = sb->s_dev; |
472 | err = bdi_init(&fc->bdi); | 488 | err = bdi_init(&fc->bdi); |
473 | if (err) | 489 | if (err) |
@@ -475,6 +491,19 @@ static struct fuse_conn *new_conn(struct super_block *sb) | |||
475 | err = bdi_register_dev(&fc->bdi, fc->dev); | 491 | err = bdi_register_dev(&fc->bdi, fc->dev); |
476 | if (err) | 492 | if (err) |
477 | goto error_bdi_destroy; | 493 | goto error_bdi_destroy; |
494 | /* | ||
495 | * For a single fuse filesystem use max 1% of dirty + | ||
496 | * writeback threshold. | ||
497 | * | ||
498 | * This gives about 1M of write buffer for memory maps on a | ||
499 | * machine with 1G and 10% dirty_ratio, which should be more | ||
500 | * than enough. | ||
501 | * | ||
502 | * Privileged users can raise it by writing to | ||
503 | * | ||
504 | * /sys/class/bdi/<bdi>/max_ratio | ||
505 | */ | ||
506 | bdi_set_max_ratio(&fc->bdi, 1); | ||
478 | fc->reqctr = 0; | 507 | fc->reqctr = 0; |
479 | fc->blocked = 1; | 508 | fc->blocked = 1; |
480 | fc->attr_version = 1; | 509 | fc->attr_version = 1; |