dir.c (8cbdf1e6f6876b37d2a0d96fd15ea9f90f7d51c1) dir.c (6f9f11806af8ad3a107714a3ece56c1c4fafd047)
1/*
2 FUSE: Filesystem in Userspace
3 Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
4
5 This program can be distributed under the terms of the GNU GPL.
6 See the file COPYING.
7*/
8
9#include "fuse_i.h"
10
11#include <linux/pagemap.h>
12#include <linux/file.h>
13#include <linux/gfp.h>
14#include <linux/sched.h>
15#include <linux/namei.h>
16
1/*
2 FUSE: Filesystem in Userspace
3 Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
4
5 This program can be distributed under the terms of the GNU GPL.
6 See the file COPYING.
7*/
8
9#include "fuse_i.h"
10
11#include <linux/pagemap.h>
12#include <linux/file.h>
13#include <linux/gfp.h>
14#include <linux/sched.h>
15#include <linux/namei.h>
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,
18 unsigned long nsec)
19{
20 struct timespec ts = {sec, nsec};
21 return jiffies + timespec_to_jiffies(&ts);
22}
23
26static inline unsigned long time_to_jiffies(unsigned long sec,
27 unsigned long nsec)
28{
29 struct timespec ts = {sec, nsec};
30 return jiffies + timespec_to_jiffies(&ts);
31}
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)
25{
26 entry->d_time = time_to_jiffies(o->entry_valid, o->entry_valid_nsec);
27 if (entry->d_inode)
28 get_fuse_inode(entry->d_inode)->i_time =
29 time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
30}
31
37static void fuse_change_timeout(struct dentry *entry, struct fuse_entry_out *o)
38{
39 entry->d_time = time_to_jiffies(o->entry_valid, o->entry_valid_nsec);
40 if (entry->d_inode)
41 get_fuse_inode(entry->d_inode)->i_time =
42 time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
43}
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)
33{
34 get_fuse_inode(inode)->i_time = jiffies - 1;
35}
36
49void fuse_invalidate_attr(struct inode *inode)
50{
51 get_fuse_inode(inode)->i_time = jiffies - 1;
52}
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)
38{
39 entry->d_time = jiffies - 1;
40}
41
62static void fuse_invalidate_entry_cache(struct dentry *entry)
63{
64 entry->d_time = jiffies - 1;
65}
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)
43{
44 d_invalidate(entry);
45 fuse_invalidate_entry_cache(entry);
46}
47
48static void fuse_lookup_init(struct fuse_req *req, struct inode *dir,
49 struct dentry *entry,

--- 5 unchanged lines hidden (view full) ---

55 req->in.numargs = 1;
56 req->in.args[0].size = entry->d_name.len + 1;
57 req->in.args[0].value = entry->d_name.name;
58 req->out.numargs = 1;
59 req->out.args[0].size = sizeof(struct fuse_entry_out);
60 req->out.args[0].value = outarg;
61}
62
71static void fuse_invalidate_entry(struct dentry *entry)
72{
73 d_invalidate(entry);
74 fuse_invalidate_entry_cache(entry);
75}
76
77static void fuse_lookup_init(struct fuse_req *req, struct inode *dir,
78 struct dentry *entry,

--- 5 unchanged lines hidden (view full) ---

84 req->in.numargs = 1;
85 req->in.args[0].size = entry->d_name.len + 1;
86 req->in.args[0].value = entry->d_name.name;
87 req->out.numargs = 1;
88 req->out.args[0].size = sizeof(struct fuse_entry_out);
89 req->out.args[0].value = outarg;
90}
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)
64{
65 struct inode *inode = entry->d_inode;
66
67 if (inode && is_bad_inode(inode))
68 return 0;
69 else if (time_after(jiffies, entry->d_time)) {
70 int err;
71 struct fuse_entry_out outarg;
72 struct fuse_conn *fc;
73 struct fuse_req *req;
74
101static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
102{
103 struct inode *inode = entry->d_inode;
104
105 if (inode && is_bad_inode(inode))
106 return 0;
107 else if (time_after(jiffies, entry->d_time)) {
108 int err;
109 struct fuse_entry_out outarg;
110 struct fuse_conn *fc;
111 struct fuse_req *req;
112
113 /* Doesn't hurt to "reset" the validity timeout */
75 fuse_invalidate_entry_cache(entry);
76 if (!inode)
77 return 0;
78
79 fc = get_fuse_conn(inode);
80 req = fuse_get_request(fc);
81 if (!req)
82 return 0;

--- 14 unchanged lines hidden (view full) ---

97 return 0;
98
99 fuse_change_attributes(inode, &outarg.attr);
100 fuse_change_timeout(entry, &outarg);
101 }
102 return 1;
103}
104
114 fuse_invalidate_entry_cache(entry);
115 if (!inode)
116 return 0;
117
118 fc = get_fuse_conn(inode);
119 req = fuse_get_request(fc);
120 if (!req)
121 return 0;

--- 14 unchanged lines hidden (view full) ---

136 return 0;
137
138 fuse_change_attributes(inode, &outarg.attr);
139 fuse_change_timeout(entry, &outarg);
140 }
141 return 1;
142}
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)
106{
107 if (S_ISDIR(inode->i_mode)) {
148static int dir_alias(struct inode *inode)
149{
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);
110 if (alias) {
111 dput(alias);
112 return 1;
113 }
114 }
115 return 0;
116}

--- 48 unchanged lines hidden (view full) ---

165 entry->d_op = &fuse_dentry_operations;
166 if (!err)
167 fuse_change_timeout(entry, &outarg);
168 else
169 fuse_invalidate_entry_cache(entry);
170 return NULL;
171}
172
151 struct dentry *alias = d_find_alias(inode);
152 if (alias) {
153 dput(alias);
154 return 1;
155 }
156 }
157 return 0;
158}

--- 48 unchanged lines hidden (view full) ---

207 entry->d_op = &fuse_dentry_operations;
208 if (!err)
209 fuse_change_timeout(entry, &outarg);
210 else
211 fuse_invalidate_entry_cache(entry);
212 return NULL;
213}
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,
174 struct nameidata *nd)
175{
176 int err;
177 struct inode *inode;
178 struct fuse_conn *fc = get_fuse_conn(dir);
179 struct fuse_req *req;
180 struct fuse_open_in inarg;

--- 50 unchanged lines hidden (view full) ---

231 goto out_free_ff;
232
233 inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
234 &outentry.attr);
235 err = -ENOMEM;
236 if (!inode) {
237 flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
238 ff->fh = outopen.fh;
221static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
222 struct nameidata *nd)
223{
224 int err;
225 struct inode *inode;
226 struct fuse_conn *fc = get_fuse_conn(dir);
227 struct fuse_req *req;
228 struct fuse_open_in inarg;

--- 50 unchanged lines hidden (view full) ---

279 goto out_free_ff;
280
281 inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
282 &outentry.attr);
283 err = -ENOMEM;
284 if (!inode) {
285 flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
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);
240 goto out_put_request;
241 }
242 fuse_put_request(fc, req);
243 d_instantiate(entry, inode);
244 fuse_change_timeout(entry, &outentry);
245 file = lookup_instantiate_filp(nd, entry, generic_file_open);
246 if (IS_ERR(file)) {

--- 7 unchanged lines hidden (view full) ---

254 out_free_ff:
255 fuse_file_free(ff);
256 out_put_request:
257 fuse_put_request(fc, req);
258 out:
259 return err;
260}
261
290 fuse_send_release(fc, ff, outentry.nodeid, NULL, flags, 0);
291 goto out_put_request;
292 }
293 fuse_put_request(fc, req);
294 d_instantiate(entry, inode);
295 fuse_change_timeout(entry, &outentry);
296 file = lookup_instantiate_filp(nd, entry, generic_file_open);
297 if (IS_ERR(file)) {

--- 7 unchanged lines hidden (view full) ---

305 out_free_ff:
306 fuse_file_free(ff);
307 out_put_request:
308 fuse_put_request(fc, req);
309 out:
310 return err;
311}
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,
263 struct inode *dir, struct dentry *entry,
264 int mode)
265{
266 struct fuse_entry_out outarg;
267 struct inode *inode;
268 int err;
269

--- 301 unchanged lines hidden (view full) ---

571 task->egid == fc->group_id &&
572 task->sgid == fc->group_id &&
573 task->gid == fc->group_id)
574 return 1;
575
576 return 0;
577}
578
316static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
317 struct inode *dir, struct dentry *entry,
318 int mode)
319{
320 struct fuse_entry_out outarg;
321 struct inode *inode;
322 int err;
323

--- 301 unchanged lines hidden (view full) ---

625 task->egid == fc->group_id &&
626 task->sgid == fc->group_id &&
627 task->gid == fc->group_id)
628 return 1;
629
630 return 0;
631}
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)
580{
581 struct inode *inode = entry->d_inode;
582 struct fuse_inode *fi = get_fuse_inode(inode);
583 struct fuse_conn *fc = get_fuse_conn(inode);
584
585 if (!fuse_allow_task(fc, current))
586 return -EACCES;

--- 31 unchanged lines hidden (view full) ---

618 fuse_put_request(fc, req);
619 if (err == -ENOSYS) {
620 fc->no_access = 1;
621 err = 0;
622 }
623 return err;
624}
625
642static int fuse_revalidate(struct dentry *entry)
643{
644 struct inode *inode = entry->d_inode;
645 struct fuse_inode *fi = get_fuse_inode(inode);
646 struct fuse_conn *fc = get_fuse_conn(inode);
647
648 if (!fuse_allow_task(fc, current))
649 return -EACCES;

--- 31 unchanged lines hidden (view full) ---

681 fuse_put_request(fc, req);
682 if (err == -ENOSYS) {
683 fc->no_access = 1;
684 err = 0;
685 }
686 return err;
687}
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)
627{
628 struct fuse_conn *fc = get_fuse_conn(inode);
629
630 if (!fuse_allow_task(fc, current))
631 return -EACCES;
632 else if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
633 int err = generic_permission(inode, mask, NULL);
634
635 /* If permission is denied, try to refresh file
636 attributes. This is also needed, because the root
637 node will at first have no permissions */
638 if (err == -EACCES) {
639 err = fuse_do_getattr(inode);
640 if (!err)
641 err = generic_permission(inode, mask, NULL);
642 }
643
702static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
703{
704 struct fuse_conn *fc = get_fuse_conn(inode);
705
706 if (!fuse_allow_task(fc, current))
707 return -EACCES;
708 else if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
709 int err = generic_permission(inode, mask, NULL);
710
711 /* If permission is denied, try to refresh file
712 attributes. This is also needed, because the root
713 node will at first have no permissions */
714 if (err == -EACCES) {
715 err = fuse_do_getattr(inode);
716 if (!err)
717 err = generic_permission(inode, mask, NULL);
718 }
719
644 /* FIXME: Need some mechanism to revoke permissions:
645 currently if the filesystem suddenly changes the
646 file mode, we will not be informed about it, and
647 continue to allow access to the file/directory.
720 /* Note: the opposite of the above test does not
721 exist. So if permissions are revoked this won't be
722 noticed immediately, only after the attribute
723 timeout has expired */
648
724
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
653 return err;
654 } else {
655 int mode = inode->i_mode;
656 if ((mask & MAY_EXEC) && !S_ISDIR(mode) && !(mode & S_IXUGO))
657 return -EACCES;
658
659 if (nd && (nd->flags & LOOKUP_ACCESS))
660 return fuse_access(inode, mask);

--- 150 unchanged lines hidden (view full) ---

811 }
812 if (ivalid & ATTR_FILE) {
813 struct fuse_file *ff = iattr->ia_file->private_data;
814 arg->valid |= FATTR_FH;
815 arg->fh = ff->fh;
816 }
817}
818
725 return err;
726 } else {
727 int mode = inode->i_mode;
728 if ((mask & MAY_EXEC) && !S_ISDIR(mode) && !(mode & S_IXUGO))
729 return -EACCES;
730
731 if (nd && (nd->flags & LOOKUP_ACCESS))
732 return fuse_access(inode, mask);

--- 150 unchanged lines hidden (view full) ---

883 }
884 if (ivalid & ATTR_FILE) {
885 struct fuse_file *ff = iattr->ia_file->private_data;
886 arg->valid |= FATTR_FH;
887 arg->fh = ff->fh;
888 }
889}
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)
820{
821 struct inode *inode = entry->d_inode;
822 struct fuse_conn *fc = get_fuse_conn(inode);
823 struct fuse_inode *fi = get_fuse_inode(inode);
824 struct fuse_req *req;
825 struct fuse_setattr_in inarg;
826 struct fuse_attr_out outarg;

--- 305 unchanged lines hidden ---
900static int fuse_setattr(struct dentry *entry, struct iattr *attr)
901{
902 struct inode *inode = entry->d_inode;
903 struct fuse_conn *fc = get_fuse_conn(inode);
904 struct fuse_inode *fi = get_fuse_inode(inode);
905 struct fuse_req *req;
906 struct fuse_setattr_in inarg;
907 struct fuse_attr_out outarg;

--- 305 unchanged lines hidden ---