diff options
Diffstat (limited to 'fs/fuse/inode.c')
-rw-r--r-- | fs/fuse/inode.c | 15 |
1 files changed, 10 insertions, 5 deletions
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 7d0a9aee01f2..fc4203570370 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
@@ -109,6 +109,7 @@ static int fuse_remount_fs(struct super_block *sb, int *flags, char *data) | |||
109 | 109 | ||
110 | void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr) | 110 | void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr) |
111 | { | 111 | { |
112 | struct fuse_conn *fc = get_fuse_conn(inode); | ||
112 | if (S_ISREG(inode->i_mode) && i_size_read(inode) != attr->size) | 113 | if (S_ISREG(inode->i_mode) && i_size_read(inode) != attr->size) |
113 | invalidate_inode_pages(inode->i_mapping); | 114 | invalidate_inode_pages(inode->i_mapping); |
114 | 115 | ||
@@ -117,7 +118,9 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr) | |||
117 | inode->i_nlink = attr->nlink; | 118 | inode->i_nlink = attr->nlink; |
118 | inode->i_uid = attr->uid; | 119 | inode->i_uid = attr->uid; |
119 | inode->i_gid = attr->gid; | 120 | inode->i_gid = attr->gid; |
121 | spin_lock(&fc->lock); | ||
120 | i_size_write(inode, attr->size); | 122 | i_size_write(inode, attr->size); |
123 | spin_unlock(&fc->lock); | ||
121 | inode->i_blocks = attr->blocks; | 124 | inode->i_blocks = attr->blocks; |
122 | inode->i_atime.tv_sec = attr->atime; | 125 | inode->i_atime.tv_sec = attr->atime; |
123 | inode->i_atime.tv_nsec = attr->atimensec; | 126 | inode->i_atime.tv_nsec = attr->atimensec; |
@@ -130,7 +133,7 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr) | |||
130 | static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr) | 133 | static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr) |
131 | { | 134 | { |
132 | inode->i_mode = attr->mode & S_IFMT; | 135 | inode->i_mode = attr->mode & S_IFMT; |
133 | i_size_write(inode, attr->size); | 136 | inode->i_size = attr->size; |
134 | if (S_ISREG(inode->i_mode)) { | 137 | if (S_ISREG(inode->i_mode)) { |
135 | fuse_init_common(inode); | 138 | fuse_init_common(inode); |
136 | fuse_init_file_inode(inode); | 139 | fuse_init_file_inode(inode); |
@@ -169,7 +172,6 @@ struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid, | |||
169 | struct inode *inode; | 172 | struct inode *inode; |
170 | struct fuse_inode *fi; | 173 | struct fuse_inode *fi; |
171 | struct fuse_conn *fc = get_fuse_conn_super(sb); | 174 | struct fuse_conn *fc = get_fuse_conn_super(sb); |
172 | int retried = 0; | ||
173 | 175 | ||
174 | retry: | 176 | retry: |
175 | inode = iget5_locked(sb, nodeid, fuse_inode_eq, fuse_inode_set, &nodeid); | 177 | inode = iget5_locked(sb, nodeid, fuse_inode_eq, fuse_inode_set, &nodeid); |
@@ -183,16 +185,16 @@ struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid, | |||
183 | fuse_init_inode(inode, attr); | 185 | fuse_init_inode(inode, attr); |
184 | unlock_new_inode(inode); | 186 | unlock_new_inode(inode); |
185 | } else if ((inode->i_mode ^ attr->mode) & S_IFMT) { | 187 | } else if ((inode->i_mode ^ attr->mode) & S_IFMT) { |
186 | BUG_ON(retried); | ||
187 | /* Inode has changed type, any I/O on the old should fail */ | 188 | /* Inode has changed type, any I/O on the old should fail */ |
188 | make_bad_inode(inode); | 189 | make_bad_inode(inode); |
189 | iput(inode); | 190 | iput(inode); |
190 | retried = 1; | ||
191 | goto retry; | 191 | goto retry; |
192 | } | 192 | } |
193 | 193 | ||
194 | fi = get_fuse_inode(inode); | 194 | fi = get_fuse_inode(inode); |
195 | spin_lock(&fc->lock); | ||
195 | fi->nlookup ++; | 196 | fi->nlookup ++; |
197 | spin_unlock(&fc->lock); | ||
196 | fuse_change_attributes(inode, attr); | 198 | fuse_change_attributes(inode, attr); |
197 | return inode; | 199 | return inode; |
198 | } | 200 | } |
@@ -377,6 +379,7 @@ static struct fuse_conn *new_conn(void) | |||
377 | fc = kzalloc(sizeof(*fc), GFP_KERNEL); | 379 | fc = kzalloc(sizeof(*fc), GFP_KERNEL); |
378 | if (fc) { | 380 | if (fc) { |
379 | spin_lock_init(&fc->lock); | 381 | spin_lock_init(&fc->lock); |
382 | mutex_init(&fc->inst_mutex); | ||
380 | atomic_set(&fc->count, 1); | 383 | atomic_set(&fc->count, 1); |
381 | init_waitqueue_head(&fc->waitq); | 384 | init_waitqueue_head(&fc->waitq); |
382 | init_waitqueue_head(&fc->blocked_waitq); | 385 | init_waitqueue_head(&fc->blocked_waitq); |
@@ -396,8 +399,10 @@ static struct fuse_conn *new_conn(void) | |||
396 | 399 | ||
397 | void fuse_conn_put(struct fuse_conn *fc) | 400 | void fuse_conn_put(struct fuse_conn *fc) |
398 | { | 401 | { |
399 | if (atomic_dec_and_test(&fc->count)) | 402 | if (atomic_dec_and_test(&fc->count)) { |
403 | mutex_destroy(&fc->inst_mutex); | ||
400 | kfree(fc); | 404 | kfree(fc); |
405 | } | ||
401 | } | 406 | } |
402 | 407 | ||
403 | struct fuse_conn *fuse_conn_get(struct fuse_conn *fc) | 408 | struct fuse_conn *fuse_conn_get(struct fuse_conn *fc) |