aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse
diff options
context:
space:
mode:
Diffstat (limited to 'fs/fuse')
-rw-r--r--fs/fuse/dir.c159
-rw-r--r--fs/fuse/file.c21
-rw-r--r--fs/fuse/fuse_i.h3
-rw-r--r--fs/fuse/inode.c15
4 files changed, 134 insertions, 64 deletions
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 8605155db1..c71a6c092a 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -138,6 +138,8 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
138 struct fuse_entry_out outarg; 138 struct fuse_entry_out outarg;
139 struct fuse_conn *fc; 139 struct fuse_conn *fc;
140 struct fuse_req *req; 140 struct fuse_req *req;
141 struct fuse_req *forget_req;
142 struct dentry *parent;
141 143
142 /* Doesn't hurt to "reset" the validity timeout */ 144 /* Doesn't hurt to "reset" the validity timeout */
143 fuse_invalidate_entry_cache(entry); 145 fuse_invalidate_entry_cache(entry);
@@ -151,21 +153,33 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
151 if (IS_ERR(req)) 153 if (IS_ERR(req))
152 return 0; 154 return 0;
153 155
154 fuse_lookup_init(req, entry->d_parent->d_inode, entry, &outarg); 156 forget_req = fuse_get_req(fc);
157 if (IS_ERR(forget_req)) {
158 fuse_put_request(fc, req);
159 return 0;
160 }
161
162 parent = dget_parent(entry);
163 fuse_lookup_init(req, parent->d_inode, entry, &outarg);
155 request_send(fc, req); 164 request_send(fc, req);
165 dput(parent);
156 err = req->out.h.error; 166 err = req->out.h.error;
167 fuse_put_request(fc, req);
157 /* Zero nodeid is same as -ENOENT */ 168 /* Zero nodeid is same as -ENOENT */
158 if (!err && !outarg.nodeid) 169 if (!err && !outarg.nodeid)
159 err = -ENOENT; 170 err = -ENOENT;
160 if (!err) { 171 if (!err) {
161 struct fuse_inode *fi = get_fuse_inode(inode); 172 struct fuse_inode *fi = get_fuse_inode(inode);
162 if (outarg.nodeid != get_node_id(inode)) { 173 if (outarg.nodeid != get_node_id(inode)) {
163 fuse_send_forget(fc, req, outarg.nodeid, 1); 174 fuse_send_forget(fc, forget_req,
175 outarg.nodeid, 1);
164 return 0; 176 return 0;
165 } 177 }
178 spin_lock(&fc->lock);
166 fi->nlookup ++; 179 fi->nlookup ++;
180 spin_unlock(&fc->lock);
167 } 181 }
168 fuse_put_request(fc, req); 182 fuse_put_request(fc, forget_req);
169 if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT) 183 if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT)
170 return 0; 184 return 0;
171 185
@@ -175,22 +189,6 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
175 return 1; 189 return 1;
176} 190}
177 191
178/*
179 * Check if there's already a hashed alias of this directory inode.
180 * If yes, then lookup and mkdir must not create a new alias.
181 */
182static int dir_alias(struct inode *inode)
183{
184 if (S_ISDIR(inode->i_mode)) {
185 struct dentry *alias = d_find_alias(inode);
186 if (alias) {
187 dput(alias);
188 return 1;
189 }
190 }
191 return 0;
192}
193
194static int invalid_nodeid(u64 nodeid) 192static int invalid_nodeid(u64 nodeid)
195{ 193{
196 return !nodeid || nodeid == FUSE_ROOT_ID; 194 return !nodeid || nodeid == FUSE_ROOT_ID;
@@ -206,6 +204,24 @@ static int valid_mode(int m)
206 S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m); 204 S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m);
207} 205}
208 206
207/*
208 * Add a directory inode to a dentry, ensuring that no other dentry
209 * refers to this inode. Called with fc->inst_mutex.
210 */
211static int fuse_d_add_directory(struct dentry *entry, struct inode *inode)
212{
213 struct dentry *alias = d_find_alias(inode);
214 if (alias) {
215 /* This tries to shrink the subtree below alias */
216 fuse_invalidate_entry(alias);
217 dput(alias);
218 if (!list_empty(&inode->i_dentry))
219 return -EBUSY;
220 }
221 d_add(entry, inode);
222 return 0;
223}
224
209static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, 225static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
210 struct nameidata *nd) 226 struct nameidata *nd)
211{ 227{
@@ -214,6 +230,7 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
214 struct inode *inode = NULL; 230 struct inode *inode = NULL;
215 struct fuse_conn *fc = get_fuse_conn(dir); 231 struct fuse_conn *fc = get_fuse_conn(dir);
216 struct fuse_req *req; 232 struct fuse_req *req;
233 struct fuse_req *forget_req;
217 234
218 if (entry->d_name.len > FUSE_NAME_MAX) 235 if (entry->d_name.len > FUSE_NAME_MAX)
219 return ERR_PTR(-ENAMETOOLONG); 236 return ERR_PTR(-ENAMETOOLONG);
@@ -222,9 +239,16 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
222 if (IS_ERR(req)) 239 if (IS_ERR(req))
223 return ERR_PTR(PTR_ERR(req)); 240 return ERR_PTR(PTR_ERR(req));
224 241
242 forget_req = fuse_get_req(fc);
243 if (IS_ERR(forget_req)) {
244 fuse_put_request(fc, req);
245 return ERR_PTR(PTR_ERR(forget_req));
246 }
247
225 fuse_lookup_init(req, dir, entry, &outarg); 248 fuse_lookup_init(req, dir, entry, &outarg);
226 request_send(fc, req); 249 request_send(fc, req);
227 err = req->out.h.error; 250 err = req->out.h.error;
251 fuse_put_request(fc, req);
228 /* Zero nodeid is same as -ENOENT, but with valid timeout */ 252 /* Zero nodeid is same as -ENOENT, but with valid timeout */
229 if (!err && outarg.nodeid && 253 if (!err && outarg.nodeid &&
230 (invalid_nodeid(outarg.nodeid) || !valid_mode(outarg.attr.mode))) 254 (invalid_nodeid(outarg.nodeid) || !valid_mode(outarg.attr.mode)))
@@ -233,19 +257,25 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
233 inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, 257 inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
234 &outarg.attr); 258 &outarg.attr);
235 if (!inode) { 259 if (!inode) {
236 fuse_send_forget(fc, req, outarg.nodeid, 1); 260 fuse_send_forget(fc, forget_req, outarg.nodeid, 1);
237 return ERR_PTR(-ENOMEM); 261 return ERR_PTR(-ENOMEM);
238 } 262 }
239 } 263 }
240 fuse_put_request(fc, req); 264 fuse_put_request(fc, forget_req);
241 if (err && err != -ENOENT) 265 if (err && err != -ENOENT)
242 return ERR_PTR(err); 266 return ERR_PTR(err);
243 267
244 if (inode && dir_alias(inode)) { 268 if (inode && S_ISDIR(inode->i_mode)) {
245 iput(inode); 269 mutex_lock(&fc->inst_mutex);
246 return ERR_PTR(-EIO); 270 err = fuse_d_add_directory(entry, inode);
247 } 271 mutex_unlock(&fc->inst_mutex);
248 d_add(entry, inode); 272 if (err) {
273 iput(inode);
274 return ERR_PTR(err);
275 }
276 } else
277 d_add(entry, inode);
278
249 entry->d_op = &fuse_dentry_operations; 279 entry->d_op = &fuse_dentry_operations;
250 if (!err) 280 if (!err)
251 fuse_change_timeout(entry, &outarg); 281 fuse_change_timeout(entry, &outarg);
@@ -375,6 +405,13 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
375 struct fuse_entry_out outarg; 405 struct fuse_entry_out outarg;
376 struct inode *inode; 406 struct inode *inode;
377 int err; 407 int err;
408 struct fuse_req *forget_req;
409
410 forget_req = fuse_get_req(fc);
411 if (IS_ERR(forget_req)) {
412 fuse_put_request(fc, req);
413 return PTR_ERR(forget_req);
414 }
378 415
379 req->in.h.nodeid = get_node_id(dir); 416 req->in.h.nodeid = get_node_id(dir);
380 req->out.numargs = 1; 417 req->out.numargs = 1;
@@ -382,37 +419,47 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
382 req->out.args[0].value = &outarg; 419 req->out.args[0].value = &outarg;
383 request_send(fc, req); 420 request_send(fc, req);
384 err = req->out.h.error; 421 err = req->out.h.error;
385 if (err) { 422 fuse_put_request(fc, req);
386 fuse_put_request(fc, req); 423 if (err)
387 return err; 424 goto out_put_forget_req;
388 } 425
389 err = -EIO; 426 err = -EIO;
390 if (invalid_nodeid(outarg.nodeid)) 427 if (invalid_nodeid(outarg.nodeid))
391 goto out_put_request; 428 goto out_put_forget_req;
392 429
393 if ((outarg.attr.mode ^ mode) & S_IFMT) 430 if ((outarg.attr.mode ^ mode) & S_IFMT)
394 goto out_put_request; 431 goto out_put_forget_req;
395 432
396 inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, 433 inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
397 &outarg.attr); 434 &outarg.attr);
398 if (!inode) { 435 if (!inode) {
399 fuse_send_forget(fc, req, outarg.nodeid, 1); 436 fuse_send_forget(fc, forget_req, outarg.nodeid, 1);
400 return -ENOMEM; 437 return -ENOMEM;
401 } 438 }
402 fuse_put_request(fc, req); 439 fuse_put_request(fc, forget_req);
403 440
404 if (dir_alias(inode)) { 441 if (S_ISDIR(inode->i_mode)) {
405 iput(inode); 442 struct dentry *alias;
406 return -EIO; 443 mutex_lock(&fc->inst_mutex);
407 } 444 alias = d_find_alias(inode);
445 if (alias) {
446 /* New directory must have moved since mkdir */
447 mutex_unlock(&fc->inst_mutex);
448 dput(alias);
449 iput(inode);
450 return -EBUSY;
451 }
452 d_instantiate(entry, inode);
453 mutex_unlock(&fc->inst_mutex);
454 } else
455 d_instantiate(entry, inode);
408 456
409 d_instantiate(entry, inode);
410 fuse_change_timeout(entry, &outarg); 457 fuse_change_timeout(entry, &outarg);
411 fuse_invalidate_attr(dir); 458 fuse_invalidate_attr(dir);
412 return 0; 459 return 0;
413 460
414 out_put_request: 461 out_put_forget_req:
415 fuse_put_request(fc, req); 462 fuse_put_request(fc, forget_req);
416 return err; 463 return err;
417} 464}
418 465
@@ -935,14 +982,30 @@ static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg)
935 } 982 }
936} 983}
937 984
985static void fuse_vmtruncate(struct inode *inode, loff_t offset)
986{
987 struct fuse_conn *fc = get_fuse_conn(inode);
988 int need_trunc;
989
990 spin_lock(&fc->lock);
991 need_trunc = inode->i_size > offset;
992 i_size_write(inode, offset);
993 spin_unlock(&fc->lock);
994
995 if (need_trunc) {
996 struct address_space *mapping = inode->i_mapping;
997 unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
998 truncate_inode_pages(mapping, offset);
999 }
1000}
1001
938/* 1002/*
939 * Set attributes, and at the same time refresh them. 1003 * Set attributes, and at the same time refresh them.
940 * 1004 *
941 * Truncation is slightly complicated, because the 'truncate' request 1005 * Truncation is slightly complicated, because the 'truncate' request
942 * may fail, in which case we don't want to touch the mapping. 1006 * may fail, in which case we don't want to touch the mapping.
943 * vmtruncate() doesn't allow for this case. So do the rlimit 1007 * vmtruncate() doesn't allow for this case, so do the rlimit checking
944 * checking by hand and call vmtruncate() only after the file has 1008 * and the actual truncation by hand.
945 * actually been truncated.
946 */ 1009 */
947static int fuse_setattr(struct dentry *entry, struct iattr *attr) 1010static int fuse_setattr(struct dentry *entry, struct iattr *attr)
948{ 1011{
@@ -993,12 +1056,8 @@ static int fuse_setattr(struct dentry *entry, struct iattr *attr)
993 make_bad_inode(inode); 1056 make_bad_inode(inode);
994 err = -EIO; 1057 err = -EIO;
995 } else { 1058 } else {
996 if (is_truncate) { 1059 if (is_truncate)
997 loff_t origsize = i_size_read(inode); 1060 fuse_vmtruncate(inode, outarg.attr.size);
998 i_size_write(inode, outarg.attr.size);
999 if (origsize > outarg.attr.size)
1000 vmtruncate(inode, outarg.attr.size);
1001 }
1002 fuse_change_attributes(inode, &outarg.attr); 1061 fuse_change_attributes(inode, &outarg.attr);
1003 fi->i_time = time_to_jiffies(outarg.attr_valid, 1062 fi->i_time = time_to_jiffies(outarg.attr_valid,
1004 outarg.attr_valid_nsec); 1063 outarg.attr_valid_nsec);
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 183626868e..763a50daf1 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -397,14 +397,14 @@ static int fuse_readpages(struct file *file, struct address_space *mapping,
397 397
398 err = -EIO; 398 err = -EIO;
399 if (is_bad_inode(inode)) 399 if (is_bad_inode(inode))
400 goto clean_pages_up; 400 goto out;
401 401
402 data.file = file; 402 data.file = file;
403 data.inode = inode; 403 data.inode = inode;
404 data.req = fuse_get_req(fc); 404 data.req = fuse_get_req(fc);
405 err = PTR_ERR(data.req); 405 err = PTR_ERR(data.req);
406 if (IS_ERR(data.req)) 406 if (IS_ERR(data.req))
407 goto clean_pages_up; 407 goto out;
408 408
409 err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data); 409 err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data);
410 if (!err) { 410 if (!err) {
@@ -413,10 +413,7 @@ static int fuse_readpages(struct file *file, struct address_space *mapping,
413 else 413 else
414 fuse_put_request(fc, data.req); 414 fuse_put_request(fc, data.req);
415 } 415 }
416 return err; 416out:
417
418clean_pages_up:
419 put_pages_list(pages);
420 return err; 417 return err;
421} 418}
422 419
@@ -481,8 +478,10 @@ static int fuse_commit_write(struct file *file, struct page *page,
481 err = -EIO; 478 err = -EIO;
482 if (!err) { 479 if (!err) {
483 pos += count; 480 pos += count;
484 if (pos > i_size_read(inode)) 481 spin_lock(&fc->lock);
482 if (pos > inode->i_size)
485 i_size_write(inode, pos); 483 i_size_write(inode, pos);
484 spin_unlock(&fc->lock);
486 485
487 if (offset == 0 && to == PAGE_CACHE_SIZE) { 486 if (offset == 0 && to == PAGE_CACHE_SIZE) {
488 clear_page_dirty(page); 487 clear_page_dirty(page);
@@ -586,8 +585,12 @@ static ssize_t fuse_direct_io(struct file *file, const char __user *buf,
586 } 585 }
587 fuse_put_request(fc, req); 586 fuse_put_request(fc, req);
588 if (res > 0) { 587 if (res > 0) {
589 if (write && pos > i_size_read(inode)) 588 if (write) {
590 i_size_write(inode, pos); 589 spin_lock(&fc->lock);
590 if (pos > inode->i_size)
591 i_size_write(inode, pos);
592 spin_unlock(&fc->lock);
593 }
591 *ppos = pos; 594 *ppos = pos;
592 } 595 }
593 fuse_invalidate_attr(inode); 596 fuse_invalidate_attr(inode);
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 69c7750d55..91edb8932d 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -239,6 +239,9 @@ struct fuse_conn {
239 /** Lock protecting accessess to members of this structure */ 239 /** Lock protecting accessess to members of this structure */
240 spinlock_t lock; 240 spinlock_t lock;
241 241
242 /** Mutex protecting against directory alias creation */
243 struct mutex inst_mutex;
244
242 /** Refcount */ 245 /** Refcount */
243 atomic_t count; 246 atomic_t count;
244 247
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 7d0a9aee01..fc42035703 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
110void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr) 110void 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)
130static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr) 133static 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
397void fuse_conn_put(struct fuse_conn *fc) 400void 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
403struct fuse_conn *fuse_conn_get(struct fuse_conn *fc) 408struct fuse_conn *fuse_conn_get(struct fuse_conn *fc)