aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse
diff options
context:
space:
mode:
Diffstat (limited to 'fs/fuse')
-rw-r--r--fs/fuse/dir.c99
-rw-r--r--fs/fuse/file.c4
2 files changed, 69 insertions, 34 deletions
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 334e0b18a014..8964cf3999b2 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -154,7 +154,7 @@ u64 fuse_get_attr_version(struct fuse_conn *fc)
154 * the lookup once more. If the lookup results in the same inode, 154 * the lookup once more. If the lookup results in the same inode,
155 * then refresh the attributes, timeouts and mark the dentry valid. 155 * then refresh the attributes, timeouts and mark the dentry valid.
156 */ 156 */
157static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd) 157static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
158{ 158{
159 struct inode *inode; 159 struct inode *inode;
160 160
@@ -174,7 +174,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
174 if (!inode) 174 if (!inode)
175 return 0; 175 return 0;
176 176
177 if (nd && (nd->flags & LOOKUP_RCU)) 177 if (flags & LOOKUP_RCU)
178 return -ECHILD; 178 return -ECHILD;
179 179
180 fc = get_fuse_conn(inode); 180 fc = get_fuse_conn(inode);
@@ -249,7 +249,7 @@ static struct dentry *fuse_d_add_directory(struct dentry *entry,
249 /* This tries to shrink the subtree below alias */ 249 /* This tries to shrink the subtree below alias */
250 fuse_invalidate_entry(alias); 250 fuse_invalidate_entry(alias);
251 dput(alias); 251 dput(alias);
252 if (!list_empty(&inode->i_dentry)) 252 if (!hlist_empty(&inode->i_dentry))
253 return ERR_PTR(-EBUSY); 253 return ERR_PTR(-EBUSY);
254 } else { 254 } else {
255 dput(alias); 255 dput(alias);
@@ -316,7 +316,7 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name,
316} 316}
317 317
318static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, 318static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
319 struct nameidata *nd) 319 unsigned int flags)
320{ 320{
321 int err; 321 int err;
322 struct fuse_entry_out outarg; 322 struct fuse_entry_out outarg;
@@ -370,7 +370,8 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
370 * 'mknod' + 'open' requests. 370 * 'mknod' + 'open' requests.
371 */ 371 */
372static int fuse_create_open(struct inode *dir, struct dentry *entry, 372static int fuse_create_open(struct inode *dir, struct dentry *entry,
373 umode_t mode, struct nameidata *nd) 373 struct file *file, unsigned flags,
374 umode_t mode, int *opened)
374{ 375{
375 int err; 376 int err;
376 struct inode *inode; 377 struct inode *inode;
@@ -381,15 +382,11 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry,
381 struct fuse_open_out outopen; 382 struct fuse_open_out outopen;
382 struct fuse_entry_out outentry; 383 struct fuse_entry_out outentry;
383 struct fuse_file *ff; 384 struct fuse_file *ff;
384 struct file *file;
385 int flags = nd->intent.open.flags;
386
387 if (fc->no_create)
388 return -ENOSYS;
389 385
390 forget = fuse_alloc_forget(); 386 forget = fuse_alloc_forget();
387 err = -ENOMEM;
391 if (!forget) 388 if (!forget)
392 return -ENOMEM; 389 goto out_err;
393 390
394 req = fuse_get_req(fc); 391 req = fuse_get_req(fc);
395 err = PTR_ERR(req); 392 err = PTR_ERR(req);
@@ -428,11 +425,8 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry,
428 req->out.args[1].value = &outopen; 425 req->out.args[1].value = &outopen;
429 fuse_request_send(fc, req); 426 fuse_request_send(fc, req);
430 err = req->out.h.error; 427 err = req->out.h.error;
431 if (err) { 428 if (err)
432 if (err == -ENOSYS)
433 fc->no_create = 1;
434 goto out_free_ff; 429 goto out_free_ff;
435 }
436 430
437 err = -EIO; 431 err = -EIO;
438 if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid)) 432 if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid))
@@ -448,28 +442,74 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry,
448 flags &= ~(O_CREAT | O_EXCL | O_TRUNC); 442 flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
449 fuse_sync_release(ff, flags); 443 fuse_sync_release(ff, flags);
450 fuse_queue_forget(fc, forget, outentry.nodeid, 1); 444 fuse_queue_forget(fc, forget, outentry.nodeid, 1);
451 return -ENOMEM; 445 err = -ENOMEM;
446 goto out_err;
452 } 447 }
453 kfree(forget); 448 kfree(forget);
454 d_instantiate(entry, inode); 449 d_instantiate(entry, inode);
455 fuse_change_entry_timeout(entry, &outentry); 450 fuse_change_entry_timeout(entry, &outentry);
456 fuse_invalidate_attr(dir); 451 fuse_invalidate_attr(dir);
457 file = lookup_instantiate_filp(nd, entry, generic_file_open); 452 err = finish_open(file, entry, generic_file_open, opened);
458 if (IS_ERR(file)) { 453 if (err) {
459 fuse_sync_release(ff, flags); 454 fuse_sync_release(ff, flags);
460 return PTR_ERR(file); 455 } else {
456 file->private_data = fuse_file_get(ff);
457 fuse_finish_open(inode, file);
461 } 458 }
462 file->private_data = fuse_file_get(ff); 459 return err;
463 fuse_finish_open(inode, file);
464 return 0;
465 460
466 out_free_ff: 461out_free_ff:
467 fuse_file_free(ff); 462 fuse_file_free(ff);
468 out_put_request: 463out_put_request:
469 fuse_put_request(fc, req); 464 fuse_put_request(fc, req);
470 out_put_forget_req: 465out_put_forget_req:
471 kfree(forget); 466 kfree(forget);
467out_err:
468 return err;
469}
470
471static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t);
472static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
473 struct file *file, unsigned flags,
474 umode_t mode, int *opened)
475{
476 int err;
477 struct fuse_conn *fc = get_fuse_conn(dir);
478 struct dentry *res = NULL;
479
480 if (d_unhashed(entry)) {
481 res = fuse_lookup(dir, entry, 0);
482 if (IS_ERR(res))
483 return PTR_ERR(res);
484
485 if (res)
486 entry = res;
487 }
488
489 if (!(flags & O_CREAT) || entry->d_inode)
490 goto no_open;
491
492 /* Only creates */
493 *opened |= FILE_CREATED;
494
495 if (fc->no_create)
496 goto mknod;
497
498 err = fuse_create_open(dir, entry, file, flags, mode, opened);
499 if (err == -ENOSYS) {
500 fc->no_create = 1;
501 goto mknod;
502 }
503out_dput:
504 dput(res);
472 return err; 505 return err;
506
507mknod:
508 err = fuse_mknod(dir, entry, mode, 0);
509 if (err)
510 goto out_dput;
511no_open:
512 return finish_no_open(file, res);
473} 513}
474 514
475/* 515/*
@@ -571,14 +611,8 @@ static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode,
571} 611}
572 612
573static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode, 613static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode,
574 struct nameidata *nd) 614 bool excl)
575{ 615{
576 if (nd) {
577 int err = fuse_create_open(dir, entry, mode, nd);
578 if (err != -ENOSYS)
579 return err;
580 /* Fall back on mknod */
581 }
582 return fuse_mknod(dir, entry, mode, 0); 616 return fuse_mknod(dir, entry, mode, 0);
583} 617}
584 618
@@ -1646,6 +1680,7 @@ static const struct inode_operations fuse_dir_inode_operations = {
1646 .link = fuse_link, 1680 .link = fuse_link,
1647 .setattr = fuse_setattr, 1681 .setattr = fuse_setattr,
1648 .create = fuse_create, 1682 .create = fuse_create,
1683 .atomic_open = fuse_atomic_open,
1649 .mknod = fuse_mknod, 1684 .mknod = fuse_mknod,
1650 .permission = fuse_permission, 1685 .permission = fuse_permission,
1651 .getattr = fuse_getattr, 1686 .getattr = fuse_getattr,
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 2eed3acfb6a6..aba15f1b7ad2 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -947,9 +947,8 @@ static ssize_t fuse_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
947 return err; 947 return err;
948 948
949 count = ocount; 949 count = ocount;
950 950 sb_start_write(inode->i_sb);
951 mutex_lock(&inode->i_mutex); 951 mutex_lock(&inode->i_mutex);
952 vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE);
953 952
954 /* We can write back this queue in page reclaim */ 953 /* We can write back this queue in page reclaim */
955 current->backing_dev_info = mapping->backing_dev_info; 954 current->backing_dev_info = mapping->backing_dev_info;
@@ -1007,6 +1006,7 @@ static ssize_t fuse_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
1007out: 1006out:
1008 current->backing_dev_info = NULL; 1007 current->backing_dev_info = NULL;
1009 mutex_unlock(&inode->i_mutex); 1008 mutex_unlock(&inode->i_mutex);
1009 sb_end_write(inode->i_sb);
1010 1010
1011 return written ? written : err; 1011 return written ? written : err;
1012} 1012}