blob: 385235ac137d4b80d355855ae22facfb1865c864 [file] [log] [blame]
Miklos Szeredie5e55582005-09-09 13:10:28 -07001/*
2 FUSE: Filesystem in Userspace
Miklos Szeredi1729a162008-11-26 12:03:54 +01003 Copyright (C) 2001-2008 Miklos Szeredi <miklos@szeredi.hu>
Miklos Szeredie5e55582005-09-09 13:10:28 -07004
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>
Miklos Szeredie5e55582005-09-09 13:10:28 -070013#include <linux/sched.h>
14#include <linux/namei.h>
Miklos Szeredi07e77dc2010-12-07 20:16:56 +010015#include <linux/slab.h>
Miklos Szeredie5e55582005-09-09 13:10:28 -070016
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070017#if BITS_PER_LONG >= 64
18static inline void fuse_dentry_settime(struct dentry *entry, u64 time)
19{
20 entry->d_time = time;
21}
22
23static inline u64 fuse_dentry_time(struct dentry *entry)
24{
25 return entry->d_time;
26}
27#else
28/*
29 * On 32 bit archs store the high 32 bits of time in d_fsdata
30 */
31static void fuse_dentry_settime(struct dentry *entry, u64 time)
32{
33 entry->d_time = time;
34 entry->d_fsdata = (void *) (unsigned long) (time >> 32);
35}
36
37static u64 fuse_dentry_time(struct dentry *entry)
38{
39 return (u64) entry->d_time +
40 ((u64) (unsigned long) entry->d_fsdata << 32);
41}
42#endif
43
Miklos Szeredi6f9f1182006-01-06 00:19:39 -080044/*
45 * FUSE caches dentries and attributes with separate timeout. The
46 * time in jiffies until the dentry/attributes are valid is stored in
47 * dentry->d_time and fuse_inode->i_time respectively.
48 */
49
50/*
51 * Calculate the time in jiffies until a dentry/attributes are valid
52 */
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070053static u64 time_to_jiffies(unsigned long sec, unsigned long nsec)
Miklos Szeredie5e55582005-09-09 13:10:28 -070054{
Miklos Szeredi685d16d2006-07-30 03:04:08 -070055 if (sec || nsec) {
56 struct timespec ts = {sec, nsec};
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070057 return get_jiffies_64() + timespec_to_jiffies(&ts);
Miklos Szeredi685d16d2006-07-30 03:04:08 -070058 } else
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070059 return 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -070060}
61
Miklos Szeredi6f9f1182006-01-06 00:19:39 -080062/*
63 * Set dentry and possibly attribute timeouts from the lookup/mk*
64 * replies
65 */
Miklos Szeredi1fb69e72007-10-18 03:06:58 -070066static void fuse_change_entry_timeout(struct dentry *entry,
67 struct fuse_entry_out *o)
Miklos Szeredi0aa7c692006-01-06 00:19:34 -080068{
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070069 fuse_dentry_settime(entry,
70 time_to_jiffies(o->entry_valid, o->entry_valid_nsec));
Miklos Szeredi1fb69e72007-10-18 03:06:58 -070071}
72
73static u64 attr_timeout(struct fuse_attr_out *o)
74{
75 return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
76}
77
78static u64 entry_attr_timeout(struct fuse_entry_out *o)
79{
80 return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -080081}
82
Miklos Szeredi6f9f1182006-01-06 00:19:39 -080083/*
84 * Mark the attributes as stale, so that at the next call to
85 * ->getattr() they will be fetched from userspace
86 */
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -080087void fuse_invalidate_attr(struct inode *inode)
88{
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070089 get_fuse_inode(inode)->i_time = 0;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -080090}
91
Miklos Szeredi6f9f1182006-01-06 00:19:39 -080092/*
93 * Just mark the entry as stale, so that a next attempt to look it up
94 * will result in a new lookup call to userspace
95 *
96 * This is called when a dentry is about to become negative and the
97 * timeout is unknown (unlink, rmdir, rename and in some cases
98 * lookup)
99 */
Miklos Szeredidbd561d2008-07-25 01:49:00 -0700100void fuse_invalidate_entry_cache(struct dentry *entry)
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800101{
Miklos Szeredi0a0898c2006-07-30 03:04:10 -0700102 fuse_dentry_settime(entry, 0);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800103}
104
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800105/*
106 * Same as fuse_invalidate_entry_cache(), but also try to remove the
107 * dentry from the hash
108 */
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800109static void fuse_invalidate_entry(struct dentry *entry)
110{
111 d_invalidate(entry);
112 fuse_invalidate_entry_cache(entry);
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800113}
114
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700115static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_req *req,
116 u64 nodeid, struct qstr *name,
Miklos Szeredie5e55582005-09-09 13:10:28 -0700117 struct fuse_entry_out *outarg)
118{
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700119 memset(outarg, 0, sizeof(struct fuse_entry_out));
Miklos Szeredie5e55582005-09-09 13:10:28 -0700120 req->in.h.opcode = FUSE_LOOKUP;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700121 req->in.h.nodeid = nodeid;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700122 req->in.numargs = 1;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700123 req->in.args[0].size = name->len + 1;
124 req->in.args[0].value = name->name;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700125 req->out.numargs = 1;
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700126 if (fc->minor < 9)
127 req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
128 else
129 req->out.args[0].size = sizeof(struct fuse_entry_out);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700130 req->out.args[0].value = outarg;
131}
132
Miklos Szeredi5c5c5e52008-04-30 00:54:43 -0700133u64 fuse_get_attr_version(struct fuse_conn *fc)
Miklos Szeredi7dca9fd2007-11-28 16:21:59 -0800134{
135 u64 curr_version;
136
137 /*
138 * The spin lock isn't actually needed on 64bit archs, but we
139 * don't yet care too much about such optimizations.
140 */
141 spin_lock(&fc->lock);
142 curr_version = fc->attr_version;
143 spin_unlock(&fc->lock);
144
145 return curr_version;
146}
147
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800148/*
149 * Check whether the dentry is still valid
150 *
151 * If the entry validity timeout has expired and the dentry is
152 * positive, try to redo the lookup. If the lookup results in a
153 * different inode, then let the VFS invalidate the dentry and redo
154 * the lookup once more. If the lookup results in the same inode,
155 * then refresh the attributes, timeouts and mark the dentry valid.
156 */
Al Viro0b728e12012-06-10 16:03:43 -0400157static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700158{
Nick Piggin34286d62011-01-07 17:49:57 +1100159 struct inode *inode;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800160
Miklos Szeredie7c0a162011-03-21 13:58:06 +0100161 inode = ACCESS_ONCE(entry->d_inode);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800162 if (inode && is_bad_inode(inode))
Miklos Szeredie5e55582005-09-09 13:10:28 -0700163 return 0;
Miklos Szeredi0a0898c2006-07-30 03:04:10 -0700164 else if (fuse_dentry_time(entry) < get_jiffies_64()) {
Miklos Szeredie5e55582005-09-09 13:10:28 -0700165 int err;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700166 struct fuse_entry_out outarg;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800167 struct fuse_conn *fc;
168 struct fuse_req *req;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100169 struct fuse_forget_link *forget;
Miklos Szeredie956edd2006-10-17 00:10:12 -0700170 struct dentry *parent;
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700171 u64 attr_version;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800172
Miklos Szeredi50322fe2006-02-28 16:59:03 -0800173 /* For negative dentries, always do a fresh lookup */
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800174 if (!inode)
175 return 0;
176
Al Viro0b728e12012-06-10 16:03:43 -0400177 if (flags & LOOKUP_RCU)
Miklos Szeredie7c0a162011-03-21 13:58:06 +0100178 return -ECHILD;
179
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800180 fc = get_fuse_conn(inode);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700181 req = fuse_get_req(fc);
182 if (IS_ERR(req))
Miklos Szeredie5e55582005-09-09 13:10:28 -0700183 return 0;
184
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100185 forget = fuse_alloc_forget();
186 if (!forget) {
Miklos Szeredi2d510132006-11-25 11:09:20 -0800187 fuse_put_request(fc, req);
188 return 0;
189 }
190
Miklos Szeredi7dca9fd2007-11-28 16:21:59 -0800191 attr_version = fuse_get_attr_version(fc);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700192
Miklos Szeredie956edd2006-10-17 00:10:12 -0700193 parent = dget_parent(entry);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700194 fuse_lookup_init(fc, req, get_node_id(parent->d_inode),
195 &entry->d_name, &outarg);
Tejun Heob93f8582008-11-26 12:03:55 +0100196 fuse_request_send(fc, req);
Miklos Szeredie956edd2006-10-17 00:10:12 -0700197 dput(parent);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700198 err = req->out.h.error;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800199 fuse_put_request(fc, req);
Miklos Szeredi50322fe2006-02-28 16:59:03 -0800200 /* Zero nodeid is same as -ENOENT */
201 if (!err && !outarg.nodeid)
202 err = -ENOENT;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700203 if (!err) {
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800204 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700205 if (outarg.nodeid != get_node_id(inode)) {
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100206 fuse_queue_forget(fc, forget, outarg.nodeid, 1);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700207 return 0;
208 }
Miklos Szeredi8da5ff22006-10-17 00:10:08 -0700209 spin_lock(&fc->lock);
Miklos Szeredi1729a162008-11-26 12:03:54 +0100210 fi->nlookup++;
Miklos Szeredi8da5ff22006-10-17 00:10:08 -0700211 spin_unlock(&fc->lock);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700212 }
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100213 kfree(forget);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700214 if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700215 return 0;
216
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700217 fuse_change_attributes(inode, &outarg.attr,
218 entry_attr_timeout(&outarg),
219 attr_version);
220 fuse_change_entry_timeout(entry, &outarg);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700221 }
222 return 1;
223}
224
Miklos Szeredi8bfc0162006-01-16 22:14:28 -0800225static int invalid_nodeid(u64 nodeid)
Miklos Szeredi2827d0b22005-11-28 13:44:16 -0800226{
227 return !nodeid || nodeid == FUSE_ROOT_ID;
228}
229
Al Viro42695902009-02-20 05:59:13 +0000230const struct dentry_operations fuse_dentry_operations = {
Miklos Szeredie5e55582005-09-09 13:10:28 -0700231 .d_revalidate = fuse_dentry_revalidate,
232};
233
Timo Savolaa5bfffac2007-04-08 16:04:00 -0700234int fuse_valid_type(int m)
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800235{
236 return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) ||
237 S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m);
238}
239
Miklos Szeredid2a85162006-10-17 00:10:11 -0700240/*
241 * Add a directory inode to a dentry, ensuring that no other dentry
242 * refers to this inode. Called with fc->inst_mutex.
243 */
Miklos Szeredi0de62562008-07-25 01:48:59 -0700244static struct dentry *fuse_d_add_directory(struct dentry *entry,
245 struct inode *inode)
Miklos Szeredid2a85162006-10-17 00:10:11 -0700246{
247 struct dentry *alias = d_find_alias(inode);
Miklos Szeredi0de62562008-07-25 01:48:59 -0700248 if (alias && !(alias->d_flags & DCACHE_DISCONNECTED)) {
Miklos Szeredid2a85162006-10-17 00:10:11 -0700249 /* This tries to shrink the subtree below alias */
250 fuse_invalidate_entry(alias);
251 dput(alias);
Al Virob3d9b7a2012-06-09 13:51:19 -0400252 if (!hlist_empty(&inode->i_dentry))
Miklos Szeredi0de62562008-07-25 01:48:59 -0700253 return ERR_PTR(-EBUSY);
254 } else {
255 dput(alias);
Miklos Szeredid2a85162006-10-17 00:10:11 -0700256 }
Miklos Szeredi0de62562008-07-25 01:48:59 -0700257 return d_splice_alias(inode, entry);
Miklos Szeredid2a85162006-10-17 00:10:11 -0700258}
259
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700260int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name,
261 struct fuse_entry_out *outarg, struct inode **inode)
262{
263 struct fuse_conn *fc = get_fuse_conn_super(sb);
264 struct fuse_req *req;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100265 struct fuse_forget_link *forget;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700266 u64 attr_version;
267 int err;
268
269 *inode = NULL;
270 err = -ENAMETOOLONG;
271 if (name->len > FUSE_NAME_MAX)
272 goto out;
273
274 req = fuse_get_req(fc);
275 err = PTR_ERR(req);
276 if (IS_ERR(req))
277 goto out;
278
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100279 forget = fuse_alloc_forget();
280 err = -ENOMEM;
281 if (!forget) {
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700282 fuse_put_request(fc, req);
283 goto out;
284 }
285
286 attr_version = fuse_get_attr_version(fc);
287
288 fuse_lookup_init(fc, req, nodeid, name, outarg);
Tejun Heob93f8582008-11-26 12:03:55 +0100289 fuse_request_send(fc, req);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700290 err = req->out.h.error;
291 fuse_put_request(fc, req);
292 /* Zero nodeid is same as -ENOENT, but with valid timeout */
293 if (err || !outarg->nodeid)
294 goto out_put_forget;
295
296 err = -EIO;
297 if (!outarg->nodeid)
298 goto out_put_forget;
299 if (!fuse_valid_type(outarg->attr.mode))
300 goto out_put_forget;
301
302 *inode = fuse_iget(sb, outarg->nodeid, outarg->generation,
303 &outarg->attr, entry_attr_timeout(outarg),
304 attr_version);
305 err = -ENOMEM;
306 if (!*inode) {
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100307 fuse_queue_forget(fc, forget, outarg->nodeid, 1);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700308 goto out;
309 }
310 err = 0;
311
312 out_put_forget:
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100313 kfree(forget);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700314 out:
315 return err;
316}
317
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800318static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
Al Viro00cd8dd2012-06-10 17:13:09 -0400319 unsigned int flags)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700320{
321 int err;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700322 struct fuse_entry_out outarg;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700323 struct inode *inode;
Miklos Szeredi0de62562008-07-25 01:48:59 -0700324 struct dentry *newent;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700325 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700326 bool outarg_valid = true;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700327
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700328 err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name,
329 &outarg, &inode);
330 if (err == -ENOENT) {
331 outarg_valid = false;
332 err = 0;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800333 }
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700334 if (err)
335 goto out_err;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800336
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700337 err = -EIO;
338 if (inode && get_node_id(inode) == FUSE_ROOT_ID)
339 goto out_iput;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700340
Miklos Szeredid2a85162006-10-17 00:10:11 -0700341 if (inode && S_ISDIR(inode->i_mode)) {
342 mutex_lock(&fc->inst_mutex);
Miklos Szeredi0de62562008-07-25 01:48:59 -0700343 newent = fuse_d_add_directory(entry, inode);
Miklos Szeredid2a85162006-10-17 00:10:11 -0700344 mutex_unlock(&fc->inst_mutex);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700345 err = PTR_ERR(newent);
346 if (IS_ERR(newent))
347 goto out_iput;
348 } else {
Miklos Szeredi0de62562008-07-25 01:48:59 -0700349 newent = d_splice_alias(inode, entry);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700350 }
Miklos Szeredid2a85162006-10-17 00:10:11 -0700351
Miklos Szeredi0de62562008-07-25 01:48:59 -0700352 entry = newent ? newent : entry;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700353 if (outarg_valid)
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700354 fuse_change_entry_timeout(entry, &outarg);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800355 else
356 fuse_invalidate_entry_cache(entry);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700357
Miklos Szeredi0de62562008-07-25 01:48:59 -0700358 return newent;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700359
360 out_iput:
361 iput(inode);
362 out_err:
363 return ERR_PTR(err);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700364}
365
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800366/*
367 * Atomic create+open operation
368 *
369 * If the filesystem doesn't support this, then fall back to separate
370 * 'mknod' + 'open' requests.
371 */
Al Virod9585272012-06-22 12:39:14 +0400372static int fuse_create_open(struct inode *dir, struct dentry *entry,
Al Viro30d90492012-06-22 12:40:19 +0400373 struct file *file, unsigned flags,
Al Virod9585272012-06-22 12:39:14 +0400374 umode_t mode, int *opened)
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800375{
376 int err;
377 struct inode *inode;
378 struct fuse_conn *fc = get_fuse_conn(dir);
379 struct fuse_req *req;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100380 struct fuse_forget_link *forget;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200381 struct fuse_create_in inarg;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800382 struct fuse_open_out outopen;
383 struct fuse_entry_out outentry;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800384 struct fuse_file *ff;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800385
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100386 forget = fuse_alloc_forget();
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200387 err = -ENOMEM;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100388 if (!forget)
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200389 goto out_err;
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700390
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700391 req = fuse_get_req(fc);
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700392 err = PTR_ERR(req);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700393 if (IS_ERR(req))
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700394 goto out_put_forget_req;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800395
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700396 err = -ENOMEM;
Tejun Heoacf99432008-11-26 12:03:55 +0100397 ff = fuse_file_alloc(fc);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800398 if (!ff)
399 goto out_put_request;
400
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200401 if (!fc->dont_mask)
402 mode &= ~current_umask();
403
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800404 flags &= ~O_NOCTTY;
405 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700406 memset(&outentry, 0, sizeof(outentry));
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800407 inarg.flags = flags;
408 inarg.mode = mode;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200409 inarg.umask = current_umask();
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800410 req->in.h.opcode = FUSE_CREATE;
411 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800412 req->in.numargs = 2;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200413 req->in.args[0].size = fc->minor < 12 ? sizeof(struct fuse_open_in) :
414 sizeof(inarg);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800415 req->in.args[0].value = &inarg;
416 req->in.args[1].size = entry->d_name.len + 1;
417 req->in.args[1].value = entry->d_name.name;
418 req->out.numargs = 2;
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700419 if (fc->minor < 9)
420 req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
421 else
422 req->out.args[0].size = sizeof(outentry);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800423 req->out.args[0].value = &outentry;
424 req->out.args[1].size = sizeof(outopen);
425 req->out.args[1].value = &outopen;
Tejun Heob93f8582008-11-26 12:03:55 +0100426 fuse_request_send(fc, req);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800427 err = req->out.h.error;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200428 if (err)
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800429 goto out_free_ff;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800430
431 err = -EIO;
Miklos Szeredi2827d0b22005-11-28 13:44:16 -0800432 if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid))
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800433 goto out_free_ff;
434
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700435 fuse_put_request(fc, req);
Miklos Szeredic7b71432009-04-28 16:56:37 +0200436 ff->fh = outopen.fh;
437 ff->nodeid = outentry.nodeid;
438 ff->open_flags = outopen.open_flags;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800439 inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700440 &outentry.attr, entry_attr_timeout(&outentry), 0);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800441 if (!inode) {
442 flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
Miklos Szeredi8b0797a2009-04-28 16:56:39 +0200443 fuse_sync_release(ff, flags);
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100444 fuse_queue_forget(fc, forget, outentry.nodeid, 1);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200445 err = -ENOMEM;
446 goto out_err;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800447 }
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100448 kfree(forget);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800449 d_instantiate(entry, inode);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700450 fuse_change_entry_timeout(entry, &outentry);
Miklos Szeredi0952b2a2008-02-06 01:38:38 -0800451 fuse_invalidate_attr(dir);
Al Viro30d90492012-06-22 12:40:19 +0400452 err = finish_open(file, entry, generic_file_open, opened);
453 if (err) {
Miklos Szeredi8b0797a2009-04-28 16:56:39 +0200454 fuse_sync_release(ff, flags);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200455 } else {
456 file->private_data = fuse_file_get(ff);
457 fuse_finish_open(inode, file);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800458 }
Al Virod9585272012-06-22 12:39:14 +0400459 return err;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800460
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200461out_free_ff:
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800462 fuse_file_free(ff);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200463out_put_request:
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800464 fuse_put_request(fc, req);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200465out_put_forget_req:
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100466 kfree(forget);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200467out_err:
Al Virod9585272012-06-22 12:39:14 +0400468 return err;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200469}
470
471static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t);
Al Virod9585272012-06-22 12:39:14 +0400472static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
Al Viro30d90492012-06-22 12:40:19 +0400473 struct file *file, unsigned flags,
Al Virod9585272012-06-22 12:39:14 +0400474 umode_t mode, int *opened)
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200475{
476 int err;
477 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200478 struct dentry *res = NULL;
479
480 if (d_unhashed(entry)) {
Al Viro00cd8dd2012-06-10 17:13:09 -0400481 res = fuse_lookup(dir, entry, 0);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200482 if (IS_ERR(res))
Al Virod9585272012-06-22 12:39:14 +0400483 return PTR_ERR(res);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200484
485 if (res)
486 entry = res;
487 }
488
489 if (!(flags & O_CREAT) || entry->d_inode)
490 goto no_open;
491
492 /* Only creates */
Al Viro47237682012-06-10 05:01:45 -0400493 *opened |= FILE_CREATED;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200494
495 if (fc->no_create)
496 goto mknod;
497
Al Viro30d90492012-06-22 12:40:19 +0400498 err = fuse_create_open(dir, entry, file, flags, mode, opened);
Al Virod9585272012-06-22 12:39:14 +0400499 if (err == -ENOSYS) {
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200500 fc->no_create = 1;
501 goto mknod;
502 }
503out_dput:
504 dput(res);
Al Virod9585272012-06-22 12:39:14 +0400505 return err;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200506
507mknod:
508 err = fuse_mknod(dir, entry, mode, 0);
Al Virod9585272012-06-22 12:39:14 +0400509 if (err)
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200510 goto out_dput;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200511no_open:
Al Viroe45198a2012-06-10 06:48:09 -0400512 return finish_no_open(file, res);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800513}
514
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800515/*
516 * Code shared between mknod, mkdir, symlink and link
517 */
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700518static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
519 struct inode *dir, struct dentry *entry,
Al Viro541af6a2011-07-26 03:17:33 -0400520 umode_t mode)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700521{
522 struct fuse_entry_out outarg;
523 struct inode *inode;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700524 int err;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100525 struct fuse_forget_link *forget;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800526
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100527 forget = fuse_alloc_forget();
528 if (!forget) {
Miklos Szeredi2d510132006-11-25 11:09:20 -0800529 fuse_put_request(fc, req);
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100530 return -ENOMEM;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800531 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700532
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700533 memset(&outarg, 0, sizeof(outarg));
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700534 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700535 req->out.numargs = 1;
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700536 if (fc->minor < 9)
537 req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
538 else
539 req->out.args[0].size = sizeof(outarg);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700540 req->out.args[0].value = &outarg;
Tejun Heob93f8582008-11-26 12:03:55 +0100541 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700542 err = req->out.h.error;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800543 fuse_put_request(fc, req);
544 if (err)
545 goto out_put_forget_req;
546
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800547 err = -EIO;
548 if (invalid_nodeid(outarg.nodeid))
Miklos Szeredi2d510132006-11-25 11:09:20 -0800549 goto out_put_forget_req;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800550
551 if ((outarg.attr.mode ^ mode) & S_IFMT)
Miklos Szeredi2d510132006-11-25 11:09:20 -0800552 goto out_put_forget_req;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800553
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700554 inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700555 &outarg.attr, entry_attr_timeout(&outarg), 0);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700556 if (!inode) {
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100557 fuse_queue_forget(fc, forget, outarg.nodeid, 1);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700558 return -ENOMEM;
559 }
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100560 kfree(forget);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700561
Miklos Szeredid2a85162006-10-17 00:10:11 -0700562 if (S_ISDIR(inode->i_mode)) {
563 struct dentry *alias;
564 mutex_lock(&fc->inst_mutex);
565 alias = d_find_alias(inode);
566 if (alias) {
567 /* New directory must have moved since mkdir */
568 mutex_unlock(&fc->inst_mutex);
569 dput(alias);
570 iput(inode);
571 return -EBUSY;
572 }
573 d_instantiate(entry, inode);
574 mutex_unlock(&fc->inst_mutex);
575 } else
576 d_instantiate(entry, inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700577
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700578 fuse_change_entry_timeout(entry, &outarg);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700579 fuse_invalidate_attr(dir);
580 return 0;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800581
Miklos Szeredi2d510132006-11-25 11:09:20 -0800582 out_put_forget_req:
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100583 kfree(forget);
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800584 return err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700585}
586
Al Viro1a67aaf2011-07-26 01:52:52 -0400587static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700588 dev_t rdev)
589{
590 struct fuse_mknod_in inarg;
591 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700592 struct fuse_req *req = fuse_get_req(fc);
593 if (IS_ERR(req))
594 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700595
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200596 if (!fc->dont_mask)
597 mode &= ~current_umask();
598
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700599 memset(&inarg, 0, sizeof(inarg));
600 inarg.mode = mode;
601 inarg.rdev = new_encode_dev(rdev);
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200602 inarg.umask = current_umask();
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700603 req->in.h.opcode = FUSE_MKNOD;
604 req->in.numargs = 2;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200605 req->in.args[0].size = fc->minor < 12 ? FUSE_COMPAT_MKNOD_IN_SIZE :
606 sizeof(inarg);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700607 req->in.args[0].value = &inarg;
608 req->in.args[1].size = entry->d_name.len + 1;
609 req->in.args[1].value = entry->d_name.name;
610 return create_new_entry(fc, req, dir, entry, mode);
611}
612
Al Viro4acdaf22011-07-26 01:42:34 -0400613static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700614 struct nameidata *nd)
615{
616 return fuse_mknod(dir, entry, mode, 0);
617}
618
Al Viro18bb1db2011-07-26 01:41:39 -0400619static int fuse_mkdir(struct inode *dir, struct dentry *entry, umode_t mode)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700620{
621 struct fuse_mkdir_in inarg;
622 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700623 struct fuse_req *req = fuse_get_req(fc);
624 if (IS_ERR(req))
625 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700626
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200627 if (!fc->dont_mask)
628 mode &= ~current_umask();
629
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700630 memset(&inarg, 0, sizeof(inarg));
631 inarg.mode = mode;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200632 inarg.umask = current_umask();
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700633 req->in.h.opcode = FUSE_MKDIR;
634 req->in.numargs = 2;
635 req->in.args[0].size = sizeof(inarg);
636 req->in.args[0].value = &inarg;
637 req->in.args[1].size = entry->d_name.len + 1;
638 req->in.args[1].value = entry->d_name.name;
639 return create_new_entry(fc, req, dir, entry, S_IFDIR);
640}
641
642static int fuse_symlink(struct inode *dir, struct dentry *entry,
643 const char *link)
644{
645 struct fuse_conn *fc = get_fuse_conn(dir);
646 unsigned len = strlen(link) + 1;
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700647 struct fuse_req *req = fuse_get_req(fc);
648 if (IS_ERR(req))
649 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700650
651 req->in.h.opcode = FUSE_SYMLINK;
652 req->in.numargs = 2;
653 req->in.args[0].size = entry->d_name.len + 1;
654 req->in.args[0].value = entry->d_name.name;
655 req->in.args[1].size = len;
656 req->in.args[1].value = link;
657 return create_new_entry(fc, req, dir, entry, S_IFLNK);
658}
659
660static int fuse_unlink(struct inode *dir, struct dentry *entry)
661{
662 int err;
663 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700664 struct fuse_req *req = fuse_get_req(fc);
665 if (IS_ERR(req))
666 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700667
668 req->in.h.opcode = FUSE_UNLINK;
669 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700670 req->in.numargs = 1;
671 req->in.args[0].size = entry->d_name.len + 1;
672 req->in.args[0].value = entry->d_name.name;
Tejun Heob93f8582008-11-26 12:03:55 +0100673 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700674 err = req->out.h.error;
675 fuse_put_request(fc, req);
676 if (!err) {
677 struct inode *inode = entry->d_inode;
Miklos Szerediac45d612012-03-05 15:48:11 +0100678 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700679
Miklos Szerediac45d612012-03-05 15:48:11 +0100680 spin_lock(&fc->lock);
681 fi->attr_version = ++fc->attr_version;
682 drop_nlink(inode);
683 spin_unlock(&fc->lock);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700684 fuse_invalidate_attr(inode);
685 fuse_invalidate_attr(dir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800686 fuse_invalidate_entry_cache(entry);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700687 } else if (err == -EINTR)
688 fuse_invalidate_entry(entry);
689 return err;
690}
691
692static int fuse_rmdir(struct inode *dir, struct dentry *entry)
693{
694 int err;
695 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700696 struct fuse_req *req = fuse_get_req(fc);
697 if (IS_ERR(req))
698 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700699
700 req->in.h.opcode = FUSE_RMDIR;
701 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700702 req->in.numargs = 1;
703 req->in.args[0].size = entry->d_name.len + 1;
704 req->in.args[0].value = entry->d_name.name;
Tejun Heob93f8582008-11-26 12:03:55 +0100705 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700706 err = req->out.h.error;
707 fuse_put_request(fc, req);
708 if (!err) {
Dave Hansence71ec32006-09-30 23:29:06 -0700709 clear_nlink(entry->d_inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700710 fuse_invalidate_attr(dir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800711 fuse_invalidate_entry_cache(entry);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700712 } else if (err == -EINTR)
713 fuse_invalidate_entry(entry);
714 return err;
715}
716
717static int fuse_rename(struct inode *olddir, struct dentry *oldent,
718 struct inode *newdir, struct dentry *newent)
719{
720 int err;
721 struct fuse_rename_in inarg;
722 struct fuse_conn *fc = get_fuse_conn(olddir);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700723 struct fuse_req *req = fuse_get_req(fc);
Sage Weile4eaac02011-05-24 13:06:07 -0700724
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700725 if (IS_ERR(req))
726 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700727
728 memset(&inarg, 0, sizeof(inarg));
729 inarg.newdir = get_node_id(newdir);
730 req->in.h.opcode = FUSE_RENAME;
731 req->in.h.nodeid = get_node_id(olddir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700732 req->in.numargs = 3;
733 req->in.args[0].size = sizeof(inarg);
734 req->in.args[0].value = &inarg;
735 req->in.args[1].size = oldent->d_name.len + 1;
736 req->in.args[1].value = oldent->d_name.name;
737 req->in.args[2].size = newent->d_name.len + 1;
738 req->in.args[2].value = newent->d_name.name;
Tejun Heob93f8582008-11-26 12:03:55 +0100739 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700740 err = req->out.h.error;
741 fuse_put_request(fc, req);
742 if (!err) {
Miklos Szeredi08b63302007-11-28 16:22:03 -0800743 /* ctime changes */
744 fuse_invalidate_attr(oldent->d_inode);
745
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700746 fuse_invalidate_attr(olddir);
747 if (olddir != newdir)
748 fuse_invalidate_attr(newdir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800749
750 /* newent will end up negative */
Miklos Szeredi5219f342009-11-04 10:24:52 +0100751 if (newent->d_inode) {
752 fuse_invalidate_attr(newent->d_inode);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800753 fuse_invalidate_entry_cache(newent);
Miklos Szeredi5219f342009-11-04 10:24:52 +0100754 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700755 } else if (err == -EINTR) {
756 /* If request was interrupted, DEITY only knows if the
757 rename actually took place. If the invalidation
758 fails (e.g. some process has CWD under the renamed
759 directory), then there can be inconsistency between
760 the dcache and the real filesystem. Tough luck. */
761 fuse_invalidate_entry(oldent);
762 if (newent->d_inode)
763 fuse_invalidate_entry(newent);
764 }
765
766 return err;
767}
768
769static int fuse_link(struct dentry *entry, struct inode *newdir,
770 struct dentry *newent)
771{
772 int err;
773 struct fuse_link_in inarg;
774 struct inode *inode = entry->d_inode;
775 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700776 struct fuse_req *req = fuse_get_req(fc);
777 if (IS_ERR(req))
778 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700779
780 memset(&inarg, 0, sizeof(inarg));
781 inarg.oldnodeid = get_node_id(inode);
782 req->in.h.opcode = FUSE_LINK;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700783 req->in.numargs = 2;
784 req->in.args[0].size = sizeof(inarg);
785 req->in.args[0].value = &inarg;
786 req->in.args[1].size = newent->d_name.len + 1;
787 req->in.args[1].value = newent->d_name.name;
788 err = create_new_entry(fc, req, newdir, newent, inode->i_mode);
789 /* Contrary to "normal" filesystems it can happen that link
790 makes two "logical" inodes point to the same "physical"
791 inode. We invalidate the attributes of the old one, so it
792 will reflect changes in the backing inode (link count,
793 etc.)
794 */
Miklos Szerediac45d612012-03-05 15:48:11 +0100795 if (!err) {
796 struct fuse_inode *fi = get_fuse_inode(inode);
797
798 spin_lock(&fc->lock);
799 fi->attr_version = ++fc->attr_version;
800 inc_nlink(inode);
801 spin_unlock(&fc->lock);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700802 fuse_invalidate_attr(inode);
Miklos Szerediac45d612012-03-05 15:48:11 +0100803 } else if (err == -EINTR) {
804 fuse_invalidate_attr(inode);
805 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700806 return err;
807}
808
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700809static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
810 struct kstat *stat)
811{
Miklos Szeredi203627b2012-05-10 19:49:38 +0400812 unsigned int blkbits;
813
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700814 stat->dev = inode->i_sb->s_dev;
815 stat->ino = attr->ino;
816 stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
817 stat->nlink = attr->nlink;
818 stat->uid = attr->uid;
819 stat->gid = attr->gid;
820 stat->rdev = inode->i_rdev;
821 stat->atime.tv_sec = attr->atime;
822 stat->atime.tv_nsec = attr->atimensec;
823 stat->mtime.tv_sec = attr->mtime;
824 stat->mtime.tv_nsec = attr->mtimensec;
825 stat->ctime.tv_sec = attr->ctime;
826 stat->ctime.tv_nsec = attr->ctimensec;
827 stat->size = attr->size;
828 stat->blocks = attr->blocks;
Miklos Szeredi203627b2012-05-10 19:49:38 +0400829
830 if (attr->blksize != 0)
831 blkbits = ilog2(attr->blksize);
832 else
833 blkbits = inode->i_sb->s_blocksize_bits;
834
835 stat->blksize = 1 << blkbits;
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700836}
837
Miklos Szeredic79e3222007-10-18 03:06:59 -0700838static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
839 struct file *file)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700840{
841 int err;
Miklos Szeredic79e3222007-10-18 03:06:59 -0700842 struct fuse_getattr_in inarg;
843 struct fuse_attr_out outarg;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700844 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700845 struct fuse_req *req;
846 u64 attr_version;
847
848 req = fuse_get_req(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700849 if (IS_ERR(req))
850 return PTR_ERR(req);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700851
Miklos Szeredi7dca9fd2007-11-28 16:21:59 -0800852 attr_version = fuse_get_attr_version(fc);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700853
Miklos Szeredic79e3222007-10-18 03:06:59 -0700854 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700855 memset(&outarg, 0, sizeof(outarg));
Miklos Szeredic79e3222007-10-18 03:06:59 -0700856 /* Directories have separate file-handle space */
857 if (file && S_ISREG(inode->i_mode)) {
858 struct fuse_file *ff = file->private_data;
859
860 inarg.getattr_flags |= FUSE_GETATTR_FH;
861 inarg.fh = ff->fh;
862 }
Miklos Szeredie5e55582005-09-09 13:10:28 -0700863 req->in.h.opcode = FUSE_GETATTR;
864 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredic79e3222007-10-18 03:06:59 -0700865 req->in.numargs = 1;
866 req->in.args[0].size = sizeof(inarg);
867 req->in.args[0].value = &inarg;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700868 req->out.numargs = 1;
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700869 if (fc->minor < 9)
870 req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
871 else
872 req->out.args[0].size = sizeof(outarg);
Miklos Szeredic79e3222007-10-18 03:06:59 -0700873 req->out.args[0].value = &outarg;
Tejun Heob93f8582008-11-26 12:03:55 +0100874 fuse_request_send(fc, req);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700875 err = req->out.h.error;
876 fuse_put_request(fc, req);
877 if (!err) {
Miklos Szeredic79e3222007-10-18 03:06:59 -0700878 if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
Miklos Szeredie5e55582005-09-09 13:10:28 -0700879 make_bad_inode(inode);
880 err = -EIO;
881 } else {
Miklos Szeredic79e3222007-10-18 03:06:59 -0700882 fuse_change_attributes(inode, &outarg.attr,
883 attr_timeout(&outarg),
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700884 attr_version);
885 if (stat)
Miklos Szeredic79e3222007-10-18 03:06:59 -0700886 fuse_fillattr(inode, &outarg.attr, stat);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700887 }
888 }
889 return err;
890}
891
Miklos Szeredibcb4be82007-11-28 16:21:59 -0800892int fuse_update_attributes(struct inode *inode, struct kstat *stat,
893 struct file *file, bool *refreshed)
894{
895 struct fuse_inode *fi = get_fuse_inode(inode);
896 int err;
897 bool r;
898
899 if (fi->i_time < get_jiffies_64()) {
900 r = true;
901 err = fuse_do_getattr(inode, stat, file);
902 } else {
903 r = false;
904 err = 0;
905 if (stat) {
906 generic_fillattr(inode, stat);
907 stat->mode = fi->orig_i_mode;
Pavel Shilovsky45c72cd2012-05-10 19:49:38 +0400908 stat->ino = fi->orig_ino;
Miklos Szeredibcb4be82007-11-28 16:21:59 -0800909 }
910 }
911
912 if (refreshed != NULL)
913 *refreshed = r;
914
915 return err;
916}
917
John Muir3b463ae2009-05-31 11:13:57 -0400918int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid,
John Muir451d0f52011-12-06 21:50:06 +0100919 u64 child_nodeid, struct qstr *name)
John Muir3b463ae2009-05-31 11:13:57 -0400920{
921 int err = -ENOTDIR;
922 struct inode *parent;
923 struct dentry *dir;
924 struct dentry *entry;
925
926 parent = ilookup5(sb, parent_nodeid, fuse_inode_eq, &parent_nodeid);
927 if (!parent)
928 return -ENOENT;
929
930 mutex_lock(&parent->i_mutex);
931 if (!S_ISDIR(parent->i_mode))
932 goto unlock;
933
934 err = -ENOENT;
935 dir = d_find_alias(parent);
936 if (!dir)
937 goto unlock;
938
939 entry = d_lookup(dir, name);
940 dput(dir);
941 if (!entry)
942 goto unlock;
943
944 fuse_invalidate_attr(parent);
945 fuse_invalidate_entry(entry);
John Muir451d0f52011-12-06 21:50:06 +0100946
947 if (child_nodeid != 0 && entry->d_inode) {
948 mutex_lock(&entry->d_inode->i_mutex);
949 if (get_node_id(entry->d_inode) != child_nodeid) {
950 err = -ENOENT;
951 goto badentry;
952 }
953 if (d_mountpoint(entry)) {
954 err = -EBUSY;
955 goto badentry;
956 }
957 if (S_ISDIR(entry->d_inode->i_mode)) {
958 shrink_dcache_parent(entry);
959 if (!simple_empty(entry)) {
960 err = -ENOTEMPTY;
961 goto badentry;
962 }
963 entry->d_inode->i_flags |= S_DEAD;
964 }
965 dont_mount(entry);
966 clear_nlink(entry->d_inode);
967 err = 0;
968 badentry:
969 mutex_unlock(&entry->d_inode->i_mutex);
970 if (!err)
971 d_delete(entry);
972 } else {
973 err = 0;
974 }
John Muir3b463ae2009-05-31 11:13:57 -0400975 dput(entry);
John Muir3b463ae2009-05-31 11:13:57 -0400976
977 unlock:
978 mutex_unlock(&parent->i_mutex);
979 iput(parent);
980 return err;
981}
982
Miklos Szeredi87729a52005-09-09 13:10:34 -0700983/*
984 * Calling into a user-controlled filesystem gives the filesystem
985 * daemon ptrace-like capabilities over the requester process. This
986 * means, that the filesystem daemon is able to record the exact
987 * filesystem operations performed, and can also control the behavior
988 * of the requester process in otherwise impossible ways. For example
989 * it can delay the operation for arbitrary length of time allowing
990 * DoS against the requester.
991 *
992 * For this reason only those processes can call into the filesystem,
993 * for which the owner of the mount has ptrace privilege. This
994 * excludes processes started by other users, suid or sgid processes.
995 */
Miklos Szeredie57ac682007-10-18 03:06:58 -0700996int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task)
Miklos Szeredi87729a52005-09-09 13:10:34 -0700997{
David Howellsc69e8d92008-11-14 10:39:19 +1100998 const struct cred *cred;
999 int ret;
1000
Miklos Szeredi87729a52005-09-09 13:10:34 -07001001 if (fc->flags & FUSE_ALLOW_OTHER)
1002 return 1;
1003
David Howellsc69e8d92008-11-14 10:39:19 +11001004 rcu_read_lock();
1005 ret = 0;
1006 cred = __task_cred(task);
1007 if (cred->euid == fc->user_id &&
1008 cred->suid == fc->user_id &&
1009 cred->uid == fc->user_id &&
1010 cred->egid == fc->group_id &&
1011 cred->sgid == fc->group_id &&
1012 cred->gid == fc->group_id)
1013 ret = 1;
1014 rcu_read_unlock();
Miklos Szeredi87729a52005-09-09 13:10:34 -07001015
David Howellsc69e8d92008-11-14 10:39:19 +11001016 return ret;
Miklos Szeredi87729a52005-09-09 13:10:34 -07001017}
1018
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001019static int fuse_access(struct inode *inode, int mask)
1020{
1021 struct fuse_conn *fc = get_fuse_conn(inode);
1022 struct fuse_req *req;
1023 struct fuse_access_in inarg;
1024 int err;
1025
1026 if (fc->no_access)
1027 return 0;
1028
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001029 req = fuse_get_req(fc);
1030 if (IS_ERR(req))
1031 return PTR_ERR(req);
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001032
1033 memset(&inarg, 0, sizeof(inarg));
Al Viroe6305c42008-07-15 21:03:57 -04001034 inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC);
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001035 req->in.h.opcode = FUSE_ACCESS;
1036 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001037 req->in.numargs = 1;
1038 req->in.args[0].size = sizeof(inarg);
1039 req->in.args[0].value = &inarg;
Tejun Heob93f8582008-11-26 12:03:55 +01001040 fuse_request_send(fc, req);
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001041 err = req->out.h.error;
1042 fuse_put_request(fc, req);
1043 if (err == -ENOSYS) {
1044 fc->no_access = 1;
1045 err = 0;
1046 }
1047 return err;
1048}
1049
Al Viro10556cb2011-06-20 19:28:19 -04001050static int fuse_perm_getattr(struct inode *inode, int mask)
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001051{
Al Viro10556cb2011-06-20 19:28:19 -04001052 if (mask & MAY_NOT_BLOCK)
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001053 return -ECHILD;
1054
1055 return fuse_do_getattr(inode, NULL, NULL);
1056}
1057
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001058/*
1059 * Check permission. The two basic access models of FUSE are:
1060 *
1061 * 1) Local access checking ('default_permissions' mount option) based
1062 * on file mode. This is the plain old disk filesystem permission
1063 * modell.
1064 *
1065 * 2) "Remote" access checking, where server is responsible for
1066 * checking permission in each inode operation. An exception to this
1067 * is if ->permission() was invoked from sys_access() in which case an
1068 * access request is sent. Execute permission is still checked
1069 * locally based on file mode.
1070 */
Al Viro10556cb2011-06-20 19:28:19 -04001071static int fuse_permission(struct inode *inode, int mask)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001072{
1073 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi244f6382007-10-16 23:31:02 -07001074 bool refreshed = false;
1075 int err = 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001076
Miklos Szeredi87729a52005-09-09 13:10:34 -07001077 if (!fuse_allow_task(fc, current))
Miklos Szeredie5e55582005-09-09 13:10:28 -07001078 return -EACCES;
Miklos Szeredi244f6382007-10-16 23:31:02 -07001079
1080 /*
Miklos Szeredie8e96152007-10-16 23:31:06 -07001081 * If attributes are needed, refresh them before proceeding
Miklos Szeredi244f6382007-10-16 23:31:02 -07001082 */
Miklos Szeredie8e96152007-10-16 23:31:06 -07001083 if ((fc->flags & FUSE_DEFAULT_PERMISSIONS) ||
1084 ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001085 struct fuse_inode *fi = get_fuse_inode(inode);
1086
1087 if (fi->i_time < get_jiffies_64()) {
1088 refreshed = true;
1089
Al Viro10556cb2011-06-20 19:28:19 -04001090 err = fuse_perm_getattr(inode, mask);
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001091 if (err)
1092 return err;
1093 }
Miklos Szeredi244f6382007-10-16 23:31:02 -07001094 }
1095
1096 if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
Al Viro2830ba72011-06-20 19:16:29 -04001097 err = generic_permission(inode, mask);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001098
1099 /* If permission is denied, try to refresh file
1100 attributes. This is also needed, because the root
1101 node will at first have no permissions */
Miklos Szeredi244f6382007-10-16 23:31:02 -07001102 if (err == -EACCES && !refreshed) {
Al Viro10556cb2011-06-20 19:28:19 -04001103 err = fuse_perm_getattr(inode, mask);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001104 if (!err)
Al Viro2830ba72011-06-20 19:16:29 -04001105 err = generic_permission(inode, mask);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001106 }
1107
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001108 /* Note: the opposite of the above test does not
1109 exist. So if permissions are revoked this won't be
1110 noticed immediately, only after the attribute
1111 timeout has expired */
Eric Paris9cfcac82010-07-23 11:43:51 -04001112 } else if (mask & (MAY_ACCESS | MAY_CHDIR)) {
Al Viro10556cb2011-06-20 19:28:19 -04001113 if (mask & MAY_NOT_BLOCK)
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001114 return -ECHILD;
1115
Miklos Szeredie8e96152007-10-16 23:31:06 -07001116 err = fuse_access(inode, mask);
1117 } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
1118 if (!(inode->i_mode & S_IXUGO)) {
1119 if (refreshed)
1120 return -EACCES;
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001121
Al Viro10556cb2011-06-20 19:28:19 -04001122 err = fuse_perm_getattr(inode, mask);
Miklos Szeredie8e96152007-10-16 23:31:06 -07001123 if (!err && !(inode->i_mode & S_IXUGO))
1124 return -EACCES;
1125 }
Miklos Szeredie5e55582005-09-09 13:10:28 -07001126 }
Miklos Szeredi244f6382007-10-16 23:31:02 -07001127 return err;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001128}
1129
1130static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
1131 void *dstbuf, filldir_t filldir)
1132{
1133 while (nbytes >= FUSE_NAME_OFFSET) {
1134 struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
1135 size_t reclen = FUSE_DIRENT_SIZE(dirent);
1136 int over;
1137 if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
1138 return -EIO;
1139 if (reclen > nbytes)
1140 break;
1141
1142 over = filldir(dstbuf, dirent->name, dirent->namelen,
1143 file->f_pos, dirent->ino, dirent->type);
1144 if (over)
1145 break;
1146
1147 buf += reclen;
1148 nbytes -= reclen;
1149 file->f_pos = dirent->off;
1150 }
1151
1152 return 0;
1153}
1154
Miklos Szeredie5e55582005-09-09 13:10:28 -07001155static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
1156{
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001157 int err;
1158 size_t nbytes;
1159 struct page *page;
Josef Sipek7706a9d2006-12-08 02:37:02 -08001160 struct inode *inode = file->f_path.dentry->d_inode;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001161 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi248d86e2006-01-06 00:19:39 -08001162 struct fuse_req *req;
1163
1164 if (is_bad_inode(inode))
1165 return -EIO;
1166
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001167 req = fuse_get_req(fc);
1168 if (IS_ERR(req))
1169 return PTR_ERR(req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001170
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001171 page = alloc_page(GFP_KERNEL);
1172 if (!page) {
1173 fuse_put_request(fc, req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001174 return -ENOMEM;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001175 }
Miklos Szeredif4975c62009-04-02 14:25:34 +02001176 req->out.argpages = 1;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001177 req->num_pages = 1;
1178 req->pages[0] = page;
Miklos Szeredi2106cb12009-04-28 16:56:37 +02001179 fuse_read_fill(req, file, file->f_pos, PAGE_SIZE, FUSE_READDIR);
Tejun Heob93f8582008-11-26 12:03:55 +01001180 fuse_request_send(fc, req);
Miklos Szeredi361b1eb52006-01-16 22:14:45 -08001181 nbytes = req->out.args[0].size;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001182 err = req->out.h.error;
1183 fuse_put_request(fc, req);
1184 if (!err)
1185 err = parse_dirfile(page_address(page), nbytes, file, dstbuf,
1186 filldir);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001187
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001188 __free_page(page);
Miklos Szeredib36c31b2005-09-09 13:10:38 -07001189 fuse_invalidate_attr(inode); /* atime changed */
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001190 return err;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001191}
1192
1193static char *read_link(struct dentry *dentry)
1194{
1195 struct inode *inode = dentry->d_inode;
1196 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001197 struct fuse_req *req = fuse_get_req(fc);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001198 char *link;
1199
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001200 if (IS_ERR(req))
David Howellse231c2e2008-02-07 00:15:26 -08001201 return ERR_CAST(req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001202
1203 link = (char *) __get_free_page(GFP_KERNEL);
1204 if (!link) {
1205 link = ERR_PTR(-ENOMEM);
1206 goto out;
1207 }
1208 req->in.h.opcode = FUSE_READLINK;
1209 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001210 req->out.argvar = 1;
1211 req->out.numargs = 1;
1212 req->out.args[0].size = PAGE_SIZE - 1;
1213 req->out.args[0].value = link;
Tejun Heob93f8582008-11-26 12:03:55 +01001214 fuse_request_send(fc, req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001215 if (req->out.h.error) {
1216 free_page((unsigned long) link);
1217 link = ERR_PTR(req->out.h.error);
1218 } else
1219 link[req->out.args[0].size] = '\0';
1220 out:
1221 fuse_put_request(fc, req);
Miklos Szeredib36c31b2005-09-09 13:10:38 -07001222 fuse_invalidate_attr(inode); /* atime changed */
Miklos Szeredie5e55582005-09-09 13:10:28 -07001223 return link;
1224}
1225
1226static void free_link(char *link)
1227{
1228 if (!IS_ERR(link))
1229 free_page((unsigned long) link);
1230}
1231
1232static void *fuse_follow_link(struct dentry *dentry, struct nameidata *nd)
1233{
1234 nd_set_link(nd, read_link(dentry));
1235 return NULL;
1236}
1237
1238static void fuse_put_link(struct dentry *dentry, struct nameidata *nd, void *c)
1239{
1240 free_link(nd_get_link(nd));
1241}
1242
1243static int fuse_dir_open(struct inode *inode, struct file *file)
1244{
Miklos Szeredi91fe96b2009-04-28 16:56:37 +02001245 return fuse_open_common(inode, file, true);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001246}
1247
1248static int fuse_dir_release(struct inode *inode, struct file *file)
1249{
Miklos Szeredi8b0797a2009-04-28 16:56:39 +02001250 fuse_release_common(file, FUSE_RELEASEDIR);
1251
1252 return 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001253}
1254
Josef Bacik02c24a82011-07-16 20:44:56 -04001255static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end,
1256 int datasync)
Miklos Szeredi82547982005-09-09 13:10:38 -07001257{
Josef Bacik02c24a82011-07-16 20:44:56 -04001258 return fuse_fsync_common(file, start, end, datasync, 1);
Miklos Szeredi82547982005-09-09 13:10:38 -07001259}
1260
Miklos Szeredib18da0c2011-12-13 11:58:49 +01001261static long fuse_dir_ioctl(struct file *file, unsigned int cmd,
1262 unsigned long arg)
1263{
1264 struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1265
1266 /* FUSE_IOCTL_DIR only supported for API version >= 7.18 */
1267 if (fc->minor < 18)
1268 return -ENOTTY;
1269
1270 return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR);
1271}
1272
1273static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd,
1274 unsigned long arg)
1275{
1276 struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1277
1278 if (fc->minor < 18)
1279 return -ENOTTY;
1280
1281 return fuse_ioctl_common(file, cmd, arg,
1282 FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR);
1283}
1284
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001285static bool update_mtime(unsigned ivalid)
1286{
1287 /* Always update if mtime is explicitly set */
1288 if (ivalid & ATTR_MTIME_SET)
1289 return true;
1290
1291 /* If it's an open(O_TRUNC) or an ftruncate(), don't update */
1292 if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
1293 return false;
1294
1295 /* In all other cases update */
1296 return true;
1297}
1298
Miklos Szeredibefc6492005-11-07 00:59:52 -08001299static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001300{
1301 unsigned ivalid = iattr->ia_valid;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001302
1303 if (ivalid & ATTR_MODE)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001304 arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001305 if (ivalid & ATTR_UID)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001306 arg->valid |= FATTR_UID, arg->uid = iattr->ia_uid;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001307 if (ivalid & ATTR_GID)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001308 arg->valid |= FATTR_GID, arg->gid = iattr->ia_gid;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001309 if (ivalid & ATTR_SIZE)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001310 arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001311 if (ivalid & ATTR_ATIME) {
1312 arg->valid |= FATTR_ATIME;
Miklos Szeredibefc6492005-11-07 00:59:52 -08001313 arg->atime = iattr->ia_atime.tv_sec;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001314 arg->atimensec = iattr->ia_atime.tv_nsec;
1315 if (!(ivalid & ATTR_ATIME_SET))
1316 arg->valid |= FATTR_ATIME_NOW;
1317 }
1318 if ((ivalid & ATTR_MTIME) && update_mtime(ivalid)) {
1319 arg->valid |= FATTR_MTIME;
Miklos Szeredibefc6492005-11-07 00:59:52 -08001320 arg->mtime = iattr->ia_mtime.tv_sec;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001321 arg->mtimensec = iattr->ia_mtime.tv_nsec;
1322 if (!(ivalid & ATTR_MTIME_SET))
1323 arg->valid |= FATTR_MTIME_NOW;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001324 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001325}
1326
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001327/*
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001328 * Prevent concurrent writepages on inode
1329 *
1330 * This is done by adding a negative bias to the inode write counter
1331 * and waiting for all pending writes to finish.
1332 */
1333void fuse_set_nowrite(struct inode *inode)
1334{
1335 struct fuse_conn *fc = get_fuse_conn(inode);
1336 struct fuse_inode *fi = get_fuse_inode(inode);
1337
1338 BUG_ON(!mutex_is_locked(&inode->i_mutex));
1339
1340 spin_lock(&fc->lock);
1341 BUG_ON(fi->writectr < 0);
1342 fi->writectr += FUSE_NOWRITE;
1343 spin_unlock(&fc->lock);
1344 wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE);
1345}
1346
1347/*
1348 * Allow writepages on inode
1349 *
1350 * Remove the bias from the writecounter and send any queued
1351 * writepages.
1352 */
1353static void __fuse_release_nowrite(struct inode *inode)
1354{
1355 struct fuse_inode *fi = get_fuse_inode(inode);
1356
1357 BUG_ON(fi->writectr != FUSE_NOWRITE);
1358 fi->writectr = 0;
1359 fuse_flush_writepages(inode);
1360}
1361
1362void fuse_release_nowrite(struct inode *inode)
1363{
1364 struct fuse_conn *fc = get_fuse_conn(inode);
1365
1366 spin_lock(&fc->lock);
1367 __fuse_release_nowrite(inode);
1368 spin_unlock(&fc->lock);
1369}
1370
1371/*
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001372 * Set attributes, and at the same time refresh them.
1373 *
1374 * Truncation is slightly complicated, because the 'truncate' request
1375 * may fail, in which case we don't want to touch the mapping.
Miklos Szeredi9ffbb912006-10-17 00:10:06 -07001376 * vmtruncate() doesn't allow for this case, so do the rlimit checking
1377 * and the actual truncation by hand.
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001378 */
Miklos Szeredi49d49142007-10-18 03:07:00 -07001379static int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
1380 struct file *file)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001381{
1382 struct inode *inode = entry->d_inode;
1383 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001384 struct fuse_req *req;
1385 struct fuse_setattr_in inarg;
1386 struct fuse_attr_out outarg;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001387 bool is_truncate = false;
1388 loff_t oldsize;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001389 int err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001390
Miklos Szeredie57ac682007-10-18 03:06:58 -07001391 if (!fuse_allow_task(fc, current))
1392 return -EACCES;
1393
Christoph Hellwigdb78b872010-06-04 11:30:03 +02001394 if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS))
1395 attr->ia_valid |= ATTR_FORCE;
1396
1397 err = inode_change_ok(inode, attr);
1398 if (err)
1399 return err;
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001400
Miklos Szeredi8d56add2011-02-25 14:44:58 +01001401 if (attr->ia_valid & ATTR_OPEN) {
1402 if (fc->atomic_o_trunc)
1403 return 0;
1404 file = NULL;
1405 }
Miklos Szeredi6ff958e2007-10-18 03:07:02 -07001406
Christoph Hellwig2c27c652010-06-04 11:30:04 +02001407 if (attr->ia_valid & ATTR_SIZE)
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001408 is_truncate = true;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001409
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001410 req = fuse_get_req(fc);
1411 if (IS_ERR(req))
1412 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001413
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001414 if (is_truncate)
1415 fuse_set_nowrite(inode);
1416
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001417 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -07001418 memset(&outarg, 0, sizeof(outarg));
Miklos Szeredibefc6492005-11-07 00:59:52 -08001419 iattr_to_fattr(attr, &inarg);
Miklos Szeredi49d49142007-10-18 03:07:00 -07001420 if (file) {
1421 struct fuse_file *ff = file->private_data;
1422 inarg.valid |= FATTR_FH;
1423 inarg.fh = ff->fh;
1424 }
Miklos Szeredif3332112007-10-18 03:07:04 -07001425 if (attr->ia_valid & ATTR_SIZE) {
1426 /* For mandatory locking in truncate */
1427 inarg.valid |= FATTR_LOCKOWNER;
1428 inarg.lock_owner = fuse_lock_owner_id(fc, current->files);
1429 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001430 req->in.h.opcode = FUSE_SETATTR;
1431 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001432 req->in.numargs = 1;
1433 req->in.args[0].size = sizeof(inarg);
1434 req->in.args[0].value = &inarg;
1435 req->out.numargs = 1;
Miklos Szeredi0e9663e2007-10-18 03:07:05 -07001436 if (fc->minor < 9)
1437 req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
1438 else
1439 req->out.args[0].size = sizeof(outarg);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001440 req->out.args[0].value = &outarg;
Tejun Heob93f8582008-11-26 12:03:55 +01001441 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001442 err = req->out.h.error;
1443 fuse_put_request(fc, req);
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001444 if (err) {
1445 if (err == -EINTR)
1446 fuse_invalidate_attr(inode);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001447 goto error;
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001448 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001449
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001450 if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
1451 make_bad_inode(inode);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001452 err = -EIO;
1453 goto error;
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001454 }
1455
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001456 spin_lock(&fc->lock);
1457 fuse_change_attributes_common(inode, &outarg.attr,
1458 attr_timeout(&outarg));
1459 oldsize = inode->i_size;
1460 i_size_write(inode, outarg.attr.size);
1461
1462 if (is_truncate) {
1463 /* NOTE: this may release/reacquire fc->lock */
1464 __fuse_release_nowrite(inode);
1465 }
1466 spin_unlock(&fc->lock);
1467
1468 /*
1469 * Only call invalidate_inode_pages2() after removing
1470 * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock.
1471 */
1472 if (S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
npiggin@suse.dec08d3b02009-08-21 02:35:06 +10001473 truncate_pagecache(inode, oldsize, outarg.attr.size);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001474 invalidate_inode_pages2(inode->i_mapping);
1475 }
1476
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001477 return 0;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001478
1479error:
1480 if (is_truncate)
1481 fuse_release_nowrite(inode);
1482
1483 return err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001484}
1485
Miklos Szeredi49d49142007-10-18 03:07:00 -07001486static int fuse_setattr(struct dentry *entry, struct iattr *attr)
1487{
1488 if (attr->ia_valid & ATTR_FILE)
1489 return fuse_do_setattr(entry, attr, attr->ia_file);
1490 else
1491 return fuse_do_setattr(entry, attr, NULL);
1492}
1493
Miklos Szeredie5e55582005-09-09 13:10:28 -07001494static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
1495 struct kstat *stat)
1496{
1497 struct inode *inode = entry->d_inode;
Miklos Szeredi244f6382007-10-16 23:31:02 -07001498 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi244f6382007-10-16 23:31:02 -07001499
1500 if (!fuse_allow_task(fc, current))
1501 return -EACCES;
1502
Miklos Szeredibcb4be82007-11-28 16:21:59 -08001503 return fuse_update_attributes(inode, stat, NULL, NULL);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001504}
1505
Miklos Szeredi92a87802005-09-09 13:10:31 -07001506static int fuse_setxattr(struct dentry *entry, const char *name,
1507 const void *value, size_t size, int flags)
1508{
1509 struct inode *inode = entry->d_inode;
1510 struct fuse_conn *fc = get_fuse_conn(inode);
1511 struct fuse_req *req;
1512 struct fuse_setxattr_in inarg;
1513 int err;
1514
Miklos Szeredi92a87802005-09-09 13:10:31 -07001515 if (fc->no_setxattr)
1516 return -EOPNOTSUPP;
1517
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001518 req = fuse_get_req(fc);
1519 if (IS_ERR(req))
1520 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001521
1522 memset(&inarg, 0, sizeof(inarg));
1523 inarg.size = size;
1524 inarg.flags = flags;
1525 req->in.h.opcode = FUSE_SETXATTR;
1526 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001527 req->in.numargs = 3;
1528 req->in.args[0].size = sizeof(inarg);
1529 req->in.args[0].value = &inarg;
1530 req->in.args[1].size = strlen(name) + 1;
1531 req->in.args[1].value = name;
1532 req->in.args[2].size = size;
1533 req->in.args[2].value = value;
Tejun Heob93f8582008-11-26 12:03:55 +01001534 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001535 err = req->out.h.error;
1536 fuse_put_request(fc, req);
1537 if (err == -ENOSYS) {
1538 fc->no_setxattr = 1;
1539 err = -EOPNOTSUPP;
1540 }
1541 return err;
1542}
1543
1544static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
1545 void *value, size_t size)
1546{
1547 struct inode *inode = entry->d_inode;
1548 struct fuse_conn *fc = get_fuse_conn(inode);
1549 struct fuse_req *req;
1550 struct fuse_getxattr_in inarg;
1551 struct fuse_getxattr_out outarg;
1552 ssize_t ret;
1553
1554 if (fc->no_getxattr)
1555 return -EOPNOTSUPP;
1556
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001557 req = fuse_get_req(fc);
1558 if (IS_ERR(req))
1559 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001560
1561 memset(&inarg, 0, sizeof(inarg));
1562 inarg.size = size;
1563 req->in.h.opcode = FUSE_GETXATTR;
1564 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001565 req->in.numargs = 2;
1566 req->in.args[0].size = sizeof(inarg);
1567 req->in.args[0].value = &inarg;
1568 req->in.args[1].size = strlen(name) + 1;
1569 req->in.args[1].value = name;
1570 /* This is really two different operations rolled into one */
1571 req->out.numargs = 1;
1572 if (size) {
1573 req->out.argvar = 1;
1574 req->out.args[0].size = size;
1575 req->out.args[0].value = value;
1576 } else {
1577 req->out.args[0].size = sizeof(outarg);
1578 req->out.args[0].value = &outarg;
1579 }
Tejun Heob93f8582008-11-26 12:03:55 +01001580 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001581 ret = req->out.h.error;
1582 if (!ret)
1583 ret = size ? req->out.args[0].size : outarg.size;
1584 else {
1585 if (ret == -ENOSYS) {
1586 fc->no_getxattr = 1;
1587 ret = -EOPNOTSUPP;
1588 }
1589 }
1590 fuse_put_request(fc, req);
1591 return ret;
1592}
1593
1594static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
1595{
1596 struct inode *inode = entry->d_inode;
1597 struct fuse_conn *fc = get_fuse_conn(inode);
1598 struct fuse_req *req;
1599 struct fuse_getxattr_in inarg;
1600 struct fuse_getxattr_out outarg;
1601 ssize_t ret;
1602
Miklos Szeredie57ac682007-10-18 03:06:58 -07001603 if (!fuse_allow_task(fc, current))
1604 return -EACCES;
1605
Miklos Szeredi92a87802005-09-09 13:10:31 -07001606 if (fc->no_listxattr)
1607 return -EOPNOTSUPP;
1608
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001609 req = fuse_get_req(fc);
1610 if (IS_ERR(req))
1611 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001612
1613 memset(&inarg, 0, sizeof(inarg));
1614 inarg.size = size;
1615 req->in.h.opcode = FUSE_LISTXATTR;
1616 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001617 req->in.numargs = 1;
1618 req->in.args[0].size = sizeof(inarg);
1619 req->in.args[0].value = &inarg;
1620 /* This is really two different operations rolled into one */
1621 req->out.numargs = 1;
1622 if (size) {
1623 req->out.argvar = 1;
1624 req->out.args[0].size = size;
1625 req->out.args[0].value = list;
1626 } else {
1627 req->out.args[0].size = sizeof(outarg);
1628 req->out.args[0].value = &outarg;
1629 }
Tejun Heob93f8582008-11-26 12:03:55 +01001630 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001631 ret = req->out.h.error;
1632 if (!ret)
1633 ret = size ? req->out.args[0].size : outarg.size;
1634 else {
1635 if (ret == -ENOSYS) {
1636 fc->no_listxattr = 1;
1637 ret = -EOPNOTSUPP;
1638 }
1639 }
1640 fuse_put_request(fc, req);
1641 return ret;
1642}
1643
1644static int fuse_removexattr(struct dentry *entry, const char *name)
1645{
1646 struct inode *inode = entry->d_inode;
1647 struct fuse_conn *fc = get_fuse_conn(inode);
1648 struct fuse_req *req;
1649 int err;
1650
1651 if (fc->no_removexattr)
1652 return -EOPNOTSUPP;
1653
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001654 req = fuse_get_req(fc);
1655 if (IS_ERR(req))
1656 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001657
1658 req->in.h.opcode = FUSE_REMOVEXATTR;
1659 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001660 req->in.numargs = 1;
1661 req->in.args[0].size = strlen(name) + 1;
1662 req->in.args[0].value = name;
Tejun Heob93f8582008-11-26 12:03:55 +01001663 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001664 err = req->out.h.error;
1665 fuse_put_request(fc, req);
1666 if (err == -ENOSYS) {
1667 fc->no_removexattr = 1;
1668 err = -EOPNOTSUPP;
1669 }
1670 return err;
1671}
1672
Arjan van de Ven754661f2007-02-12 00:55:38 -08001673static const struct inode_operations fuse_dir_inode_operations = {
Miklos Szeredie5e55582005-09-09 13:10:28 -07001674 .lookup = fuse_lookup,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001675 .mkdir = fuse_mkdir,
1676 .symlink = fuse_symlink,
1677 .unlink = fuse_unlink,
1678 .rmdir = fuse_rmdir,
1679 .rename = fuse_rename,
1680 .link = fuse_link,
1681 .setattr = fuse_setattr,
1682 .create = fuse_create,
Miklos Szeredic8ccbe02012-06-05 15:10:22 +02001683 .atomic_open = fuse_atomic_open,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001684 .mknod = fuse_mknod,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001685 .permission = fuse_permission,
1686 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001687 .setxattr = fuse_setxattr,
1688 .getxattr = fuse_getxattr,
1689 .listxattr = fuse_listxattr,
1690 .removexattr = fuse_removexattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001691};
1692
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -08001693static const struct file_operations fuse_dir_operations = {
Miklos Szeredib6aeade2005-09-09 13:10:30 -07001694 .llseek = generic_file_llseek,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001695 .read = generic_read_dir,
1696 .readdir = fuse_readdir,
1697 .open = fuse_dir_open,
1698 .release = fuse_dir_release,
Miklos Szeredi82547982005-09-09 13:10:38 -07001699 .fsync = fuse_dir_fsync,
Miklos Szeredib18da0c2011-12-13 11:58:49 +01001700 .unlocked_ioctl = fuse_dir_ioctl,
1701 .compat_ioctl = fuse_dir_compat_ioctl,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001702};
1703
Arjan van de Ven754661f2007-02-12 00:55:38 -08001704static const struct inode_operations fuse_common_inode_operations = {
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001705 .setattr = fuse_setattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001706 .permission = fuse_permission,
1707 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001708 .setxattr = fuse_setxattr,
1709 .getxattr = fuse_getxattr,
1710 .listxattr = fuse_listxattr,
1711 .removexattr = fuse_removexattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001712};
1713
Arjan van de Ven754661f2007-02-12 00:55:38 -08001714static const struct inode_operations fuse_symlink_inode_operations = {
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001715 .setattr = fuse_setattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001716 .follow_link = fuse_follow_link,
1717 .put_link = fuse_put_link,
1718 .readlink = generic_readlink,
1719 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001720 .setxattr = fuse_setxattr,
1721 .getxattr = fuse_getxattr,
1722 .listxattr = fuse_listxattr,
1723 .removexattr = fuse_removexattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001724};
1725
1726void fuse_init_common(struct inode *inode)
1727{
1728 inode->i_op = &fuse_common_inode_operations;
1729}
1730
1731void fuse_init_dir(struct inode *inode)
1732{
1733 inode->i_op = &fuse_dir_inode_operations;
1734 inode->i_fop = &fuse_dir_operations;
1735}
1736
1737void fuse_init_symlink(struct inode *inode)
1738{
1739 inode->i_op = &fuse_symlink_inode_operations;
1740}