aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/fuse/dir.c')
-rw-r--r--fs/fuse/dir.c99
1 files changed, 90 insertions, 9 deletions
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 4c127f2bc814..fead7f49e2ca 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -14,6 +14,15 @@
14#include <linux/sched.h> 14#include <linux/sched.h>
15#include <linux/namei.h> 15#include <linux/namei.h>
16 16
17/*
18 * FUSE caches dentries and attributes with separate timeout. The
19 * time in jiffies until the dentry/attributes are valid is stored in
20 * dentry->d_time and fuse_inode->i_time respectively.
21 */
22
23/*
24 * Calculate the time in jiffies until a dentry/attributes are valid
25 */
17static inline unsigned long time_to_jiffies(unsigned long sec, 26static inline unsigned long time_to_jiffies(unsigned long sec,
18 unsigned long nsec) 27 unsigned long nsec)
19{ 28{
@@ -21,6 +30,10 @@ static inline unsigned long time_to_jiffies(unsigned long sec,
21 return jiffies + timespec_to_jiffies(&ts); 30 return jiffies + timespec_to_jiffies(&ts);
22} 31}
23 32
33/*
34 * Set dentry and possibly attribute timeouts from the lookup/mk*
35 * replies
36 */
24static void fuse_change_timeout(struct dentry *entry, struct fuse_entry_out *o) 37static void fuse_change_timeout(struct dentry *entry, struct fuse_entry_out *o)
25{ 38{
26 entry->d_time = time_to_jiffies(o->entry_valid, o->entry_valid_nsec); 39 entry->d_time = time_to_jiffies(o->entry_valid, o->entry_valid_nsec);
@@ -29,16 +42,32 @@ static void fuse_change_timeout(struct dentry *entry, struct fuse_entry_out *o)
29 time_to_jiffies(o->attr_valid, o->attr_valid_nsec); 42 time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
30} 43}
31 44
45/*
46 * Mark the attributes as stale, so that at the next call to
47 * ->getattr() they will be fetched from userspace
48 */
32void fuse_invalidate_attr(struct inode *inode) 49void fuse_invalidate_attr(struct inode *inode)
33{ 50{
34 get_fuse_inode(inode)->i_time = jiffies - 1; 51 get_fuse_inode(inode)->i_time = jiffies - 1;
35} 52}
36 53
54/*
55 * Just mark the entry as stale, so that a next attempt to look it up
56 * will result in a new lookup call to userspace
57 *
58 * This is called when a dentry is about to become negative and the
59 * timeout is unknown (unlink, rmdir, rename and in some cases
60 * lookup)
61 */
37static void fuse_invalidate_entry_cache(struct dentry *entry) 62static void fuse_invalidate_entry_cache(struct dentry *entry)
38{ 63{
39 entry->d_time = jiffies - 1; 64 entry->d_time = jiffies - 1;
40} 65}
41 66
67/*
68 * Same as fuse_invalidate_entry_cache(), but also try to remove the
69 * dentry from the hash
70 */
42static void fuse_invalidate_entry(struct dentry *entry) 71static void fuse_invalidate_entry(struct dentry *entry)
43{ 72{
44 d_invalidate(entry); 73 d_invalidate(entry);
@@ -60,6 +89,15 @@ static void fuse_lookup_init(struct fuse_req *req, struct inode *dir,
60 req->out.args[0].value = outarg; 89 req->out.args[0].value = outarg;
61} 90}
62 91
92/*
93 * Check whether the dentry is still valid
94 *
95 * If the entry validity timeout has expired and the dentry is
96 * positive, try to redo the lookup. If the lookup results in a
97 * different inode, then let the VFS invalidate the dentry and redo
98 * the lookup once more. If the lookup results in the same inode,
99 * then refresh the attributes, timeouts and mark the dentry valid.
100 */
63static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd) 101static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
64{ 102{
65 struct inode *inode = entry->d_inode; 103 struct inode *inode = entry->d_inode;
@@ -72,6 +110,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
72 struct fuse_conn *fc; 110 struct fuse_conn *fc;
73 struct fuse_req *req; 111 struct fuse_req *req;
74 112
113 /* Doesn't hurt to "reset" the validity timeout */
75 fuse_invalidate_entry_cache(entry); 114 fuse_invalidate_entry_cache(entry);
76 if (!inode) 115 if (!inode)
77 return 0; 116 return 0;
@@ -102,10 +141,13 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
102 return 1; 141 return 1;
103} 142}
104 143
144/*
145 * Check if there's already a hashed alias of this directory inode.
146 * If yes, then lookup and mkdir must not create a new alias.
147 */
105static int dir_alias(struct inode *inode) 148static int dir_alias(struct inode *inode)
106{ 149{
107 if (S_ISDIR(inode->i_mode)) { 150 if (S_ISDIR(inode->i_mode)) {
108 /* Don't allow creating an alias to a directory */
109 struct dentry *alias = d_find_alias(inode); 151 struct dentry *alias = d_find_alias(inode);
110 if (alias) { 152 if (alias) {
111 dput(alias); 153 dput(alias);
@@ -170,6 +212,12 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
170 return NULL; 212 return NULL;
171} 213}
172 214
215/*
216 * Atomic create+open operation
217 *
218 * If the filesystem doesn't support this, then fall back to separate
219 * 'mknod' + 'open' requests.
220 */
173static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode, 221static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
174 struct nameidata *nd) 222 struct nameidata *nd)
175{ 223{
@@ -236,6 +284,9 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
236 if (!inode) { 284 if (!inode) {
237 flags &= ~(O_CREAT | O_EXCL | O_TRUNC); 285 flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
238 ff->fh = outopen.fh; 286 ff->fh = outopen.fh;
287 /* Special release, with inode = NULL, this will
288 trigger a 'forget' request when the release is
289 complete */
239 fuse_send_release(fc, ff, outentry.nodeid, NULL, flags, 0); 290 fuse_send_release(fc, ff, outentry.nodeid, NULL, flags, 0);
240 goto out_put_request; 291 goto out_put_request;
241 } 292 }
@@ -259,6 +310,9 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
259 return err; 310 return err;
260} 311}
261 312
313/*
314 * Code shared between mknod, mkdir, symlink and link
315 */
262static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req, 316static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
263 struct inode *dir, struct dentry *entry, 317 struct inode *dir, struct dentry *entry,
264 int mode) 318 int mode)
@@ -576,6 +630,15 @@ static int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task)
576 return 0; 630 return 0;
577} 631}
578 632
633/*
634 * Check whether the inode attributes are still valid
635 *
636 * If the attribute validity timeout has expired, then fetch the fresh
637 * attributes with a 'getattr' request
638 *
639 * I'm not sure why cached attributes are never returned for the root
640 * inode, this is probably being too cautious.
641 */
579static int fuse_revalidate(struct dentry *entry) 642static int fuse_revalidate(struct dentry *entry)
580{ 643{
581 struct inode *inode = entry->d_inode; 644 struct inode *inode = entry->d_inode;
@@ -623,6 +686,19 @@ static int fuse_access(struct inode *inode, int mask)
623 return err; 686 return err;
624} 687}
625 688
689/*
690 * Check permission. The two basic access models of FUSE are:
691 *
692 * 1) Local access checking ('default_permissions' mount option) based
693 * on file mode. This is the plain old disk filesystem permission
694 * modell.
695 *
696 * 2) "Remote" access checking, where server is responsible for
697 * checking permission in each inode operation. An exception to this
698 * is if ->permission() was invoked from sys_access() in which case an
699 * access request is sent. Execute permission is still checked
700 * locally based on file mode.
701 */
626static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd) 702static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
627{ 703{
628 struct fuse_conn *fc = get_fuse_conn(inode); 704 struct fuse_conn *fc = get_fuse_conn(inode);
@@ -641,14 +717,10 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
641 err = generic_permission(inode, mask, NULL); 717 err = generic_permission(inode, mask, NULL);
642 } 718 }
643 719
644 /* FIXME: Need some mechanism to revoke permissions: 720 /* Note: the opposite of the above test does not
645 currently if the filesystem suddenly changes the 721 exist. So if permissions are revoked this won't be
646 file mode, we will not be informed about it, and 722 noticed immediately, only after the attribute
647 continue to allow access to the file/directory. 723 timeout has expired */
648
649 This is actually not so grave, since the user can
650 simply keep access to the file/directory anyway by
651 keeping it open... */
652 724
653 return err; 725 return err;
654 } else { 726 } else {
@@ -816,6 +888,15 @@ static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg)
816 } 888 }
817} 889}
818 890
891/*
892 * Set attributes, and at the same time refresh them.
893 *
894 * Truncation is slightly complicated, because the 'truncate' request
895 * may fail, in which case we don't want to touch the mapping.
896 * vmtruncate() doesn't allow for this case. So do the rlimit
897 * checking by hand and call vmtruncate() only after the file has
898 * actually been truncated.
899 */
819static int fuse_setattr(struct dentry *entry, struct iattr *attr) 900static int fuse_setattr(struct dentry *entry, struct iattr *attr)
820{ 901{
821 struct inode *inode = entry->d_inode; 902 struct inode *inode = entry->d_inode;