diff options
Diffstat (limited to 'fs/fuse/inode.c')
-rw-r--r-- | fs/fuse/inode.c | 52 |
1 files changed, 44 insertions, 8 deletions
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 5448f625ab56..fd0735715c14 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
@@ -109,20 +109,25 @@ static int fuse_remount_fs(struct super_block *sb, int *flags, char *data) | |||
109 | return 0; | 109 | return 0; |
110 | } | 110 | } |
111 | 111 | ||
112 | static void fuse_truncate(struct address_space *mapping, loff_t offset) | ||
113 | { | ||
114 | /* See vmtruncate() */ | ||
115 | unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1); | ||
116 | truncate_inode_pages(mapping, offset); | ||
117 | unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1); | ||
118 | } | ||
119 | |||
112 | void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr) | 120 | void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr) |
113 | { | 121 | { |
114 | struct fuse_conn *fc = get_fuse_conn(inode); | 122 | struct fuse_conn *fc = get_fuse_conn(inode); |
115 | if (S_ISREG(inode->i_mode) && i_size_read(inode) != attr->size) | 123 | struct fuse_inode *fi = get_fuse_inode(inode); |
116 | invalidate_mapping_pages(inode->i_mapping, 0, -1); | 124 | loff_t oldsize; |
117 | 125 | ||
118 | inode->i_ino = attr->ino; | 126 | inode->i_ino = attr->ino; |
119 | inode->i_mode = (inode->i_mode & S_IFMT) + (attr->mode & 07777); | 127 | inode->i_mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777); |
120 | inode->i_nlink = attr->nlink; | 128 | inode->i_nlink = attr->nlink; |
121 | inode->i_uid = attr->uid; | 129 | inode->i_uid = attr->uid; |
122 | inode->i_gid = attr->gid; | 130 | inode->i_gid = attr->gid; |
123 | spin_lock(&fc->lock); | ||
124 | i_size_write(inode, attr->size); | ||
125 | spin_unlock(&fc->lock); | ||
126 | inode->i_blocks = attr->blocks; | 131 | inode->i_blocks = attr->blocks; |
127 | inode->i_atime.tv_sec = attr->atime; | 132 | inode->i_atime.tv_sec = attr->atime; |
128 | inode->i_atime.tv_nsec = attr->atimensec; | 133 | inode->i_atime.tv_nsec = attr->atimensec; |
@@ -130,6 +135,26 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr) | |||
130 | inode->i_mtime.tv_nsec = attr->mtimensec; | 135 | inode->i_mtime.tv_nsec = attr->mtimensec; |
131 | inode->i_ctime.tv_sec = attr->ctime; | 136 | inode->i_ctime.tv_sec = attr->ctime; |
132 | inode->i_ctime.tv_nsec = attr->ctimensec; | 137 | inode->i_ctime.tv_nsec = attr->ctimensec; |
138 | |||
139 | /* | ||
140 | * Don't set the sticky bit in i_mode, unless we want the VFS | ||
141 | * to check permissions. This prevents failures due to the | ||
142 | * check in may_delete(). | ||
143 | */ | ||
144 | fi->orig_i_mode = inode->i_mode; | ||
145 | if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS)) | ||
146 | inode->i_mode &= ~S_ISVTX; | ||
147 | |||
148 | spin_lock(&fc->lock); | ||
149 | oldsize = inode->i_size; | ||
150 | i_size_write(inode, attr->size); | ||
151 | spin_unlock(&fc->lock); | ||
152 | |||
153 | if (S_ISREG(inode->i_mode) && oldsize != attr->size) { | ||
154 | if (attr->size < oldsize) | ||
155 | fuse_truncate(inode->i_mapping, attr->size); | ||
156 | invalidate_inode_pages2(inode->i_mapping); | ||
157 | } | ||
133 | } | 158 | } |
134 | 159 | ||
135 | static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr) | 160 | static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr) |
@@ -232,6 +257,7 @@ static void fuse_put_super(struct super_block *sb) | |||
232 | kill_fasync(&fc->fasync, SIGIO, POLL_IN); | 257 | kill_fasync(&fc->fasync, SIGIO, POLL_IN); |
233 | wake_up_all(&fc->waitq); | 258 | wake_up_all(&fc->waitq); |
234 | wake_up_all(&fc->blocked_waitq); | 259 | wake_up_all(&fc->blocked_waitq); |
260 | wake_up_all(&fc->reserved_req_waitq); | ||
235 | mutex_lock(&fuse_mutex); | 261 | mutex_lock(&fuse_mutex); |
236 | list_del(&fc->entry); | 262 | list_del(&fc->entry); |
237 | fuse_ctl_remove_conn(fc); | 263 | fuse_ctl_remove_conn(fc); |
@@ -401,6 +427,7 @@ static int fuse_show_options(struct seq_file *m, struct vfsmount *mnt) | |||
401 | static struct fuse_conn *new_conn(void) | 427 | static struct fuse_conn *new_conn(void) |
402 | { | 428 | { |
403 | struct fuse_conn *fc; | 429 | struct fuse_conn *fc; |
430 | int err; | ||
404 | 431 | ||
405 | fc = kzalloc(sizeof(*fc), GFP_KERNEL); | 432 | fc = kzalloc(sizeof(*fc), GFP_KERNEL); |
406 | if (fc) { | 433 | if (fc) { |
@@ -409,6 +436,7 @@ static struct fuse_conn *new_conn(void) | |||
409 | atomic_set(&fc->count, 1); | 436 | atomic_set(&fc->count, 1); |
410 | init_waitqueue_head(&fc->waitq); | 437 | init_waitqueue_head(&fc->waitq); |
411 | init_waitqueue_head(&fc->blocked_waitq); | 438 | init_waitqueue_head(&fc->blocked_waitq); |
439 | init_waitqueue_head(&fc->reserved_req_waitq); | ||
412 | INIT_LIST_HEAD(&fc->pending); | 440 | INIT_LIST_HEAD(&fc->pending); |
413 | INIT_LIST_HEAD(&fc->processing); | 441 | INIT_LIST_HEAD(&fc->processing); |
414 | INIT_LIST_HEAD(&fc->io); | 442 | INIT_LIST_HEAD(&fc->io); |
@@ -416,10 +444,17 @@ static struct fuse_conn *new_conn(void) | |||
416 | atomic_set(&fc->num_waiting, 0); | 444 | atomic_set(&fc->num_waiting, 0); |
417 | fc->bdi.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE; | 445 | fc->bdi.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE; |
418 | fc->bdi.unplug_io_fn = default_unplug_io_fn; | 446 | fc->bdi.unplug_io_fn = default_unplug_io_fn; |
447 | err = bdi_init(&fc->bdi); | ||
448 | if (err) { | ||
449 | kfree(fc); | ||
450 | fc = NULL; | ||
451 | goto out; | ||
452 | } | ||
419 | fc->reqctr = 0; | 453 | fc->reqctr = 0; |
420 | fc->blocked = 1; | 454 | fc->blocked = 1; |
421 | get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key)); | 455 | get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key)); |
422 | } | 456 | } |
457 | out: | ||
423 | return fc; | 458 | return fc; |
424 | } | 459 | } |
425 | 460 | ||
@@ -429,6 +464,7 @@ void fuse_conn_put(struct fuse_conn *fc) | |||
429 | if (fc->destroy_req) | 464 | if (fc->destroy_req) |
430 | fuse_request_free(fc->destroy_req); | 465 | fuse_request_free(fc->destroy_req); |
431 | mutex_destroy(&fc->inst_mutex); | 466 | mutex_destroy(&fc->inst_mutex); |
467 | bdi_destroy(&fc->bdi); | ||
432 | kfree(fc); | 468 | kfree(fc); |
433 | } | 469 | } |
434 | } | 470 | } |
@@ -446,6 +482,7 @@ static struct inode *get_root_inode(struct super_block *sb, unsigned mode) | |||
446 | 482 | ||
447 | attr.mode = mode; | 483 | attr.mode = mode; |
448 | attr.ino = FUSE_ROOT_ID; | 484 | attr.ino = FUSE_ROOT_ID; |
485 | attr.nlink = 1; | ||
449 | return fuse_iget(sb, 1, 0, &attr); | 486 | return fuse_iget(sb, 1, 0, &attr); |
450 | } | 487 | } |
451 | 488 | ||
@@ -683,8 +720,7 @@ static inline void unregister_fuseblk(void) | |||
683 | static decl_subsys(fuse, NULL, NULL); | 720 | static decl_subsys(fuse, NULL, NULL); |
684 | static decl_subsys(connections, NULL, NULL); | 721 | static decl_subsys(connections, NULL, NULL); |
685 | 722 | ||
686 | static void fuse_inode_init_once(void *foo, struct kmem_cache *cachep, | 723 | static void fuse_inode_init_once(struct kmem_cache *cachep, void *foo) |
687 | unsigned long flags) | ||
688 | { | 724 | { |
689 | struct inode * inode = foo; | 725 | struct inode * inode = foo; |
690 | 726 | ||