blob: dc5e64893375ffcf2caa1dba652d0ac0fb66863c [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
Feng Shuo4582a4a2013-01-15 11:23:28 +080017static bool fuse_use_readdirplus(struct inode *dir, struct file *filp)
18{
19 struct fuse_conn *fc = get_fuse_conn(dir);
20 struct fuse_inode *fi = get_fuse_inode(dir);
21
22 if (!fc->do_readdirplus)
23 return false;
24 if (test_and_clear_bit(FUSE_I_ADVISE_RDPLUS, &fi->state))
25 return true;
26 if (filp->f_pos == 0)
27 return true;
28 return false;
29}
30
31static void fuse_advise_use_readdirplus(struct inode *dir)
32{
33 struct fuse_inode *fi = get_fuse_inode(dir);
34
35 set_bit(FUSE_I_ADVISE_RDPLUS, &fi->state);
36}
37
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070038#if BITS_PER_LONG >= 64
39static inline void fuse_dentry_settime(struct dentry *entry, u64 time)
40{
41 entry->d_time = time;
42}
43
44static inline u64 fuse_dentry_time(struct dentry *entry)
45{
46 return entry->d_time;
47}
48#else
49/*
50 * On 32 bit archs store the high 32 bits of time in d_fsdata
51 */
52static void fuse_dentry_settime(struct dentry *entry, u64 time)
53{
54 entry->d_time = time;
55 entry->d_fsdata = (void *) (unsigned long) (time >> 32);
56}
57
58static u64 fuse_dentry_time(struct dentry *entry)
59{
60 return (u64) entry->d_time +
61 ((u64) (unsigned long) entry->d_fsdata << 32);
62}
63#endif
64
Miklos Szeredi6f9f1182006-01-06 00:19:39 -080065/*
66 * FUSE caches dentries and attributes with separate timeout. The
67 * time in jiffies until the dentry/attributes are valid is stored in
68 * dentry->d_time and fuse_inode->i_time respectively.
69 */
70
71/*
72 * Calculate the time in jiffies until a dentry/attributes are valid
73 */
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070074static u64 time_to_jiffies(unsigned long sec, unsigned long nsec)
Miklos Szeredie5e55582005-09-09 13:10:28 -070075{
Miklos Szeredi685d16d2006-07-30 03:04:08 -070076 if (sec || nsec) {
77 struct timespec ts = {sec, nsec};
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070078 return get_jiffies_64() + timespec_to_jiffies(&ts);
Miklos Szeredi685d16d2006-07-30 03:04:08 -070079 } else
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070080 return 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -070081}
82
Miklos Szeredi6f9f1182006-01-06 00:19:39 -080083/*
84 * Set dentry and possibly attribute timeouts from the lookup/mk*
85 * replies
86 */
Miklos Szeredi1fb69e72007-10-18 03:06:58 -070087static void fuse_change_entry_timeout(struct dentry *entry,
88 struct fuse_entry_out *o)
Miklos Szeredi0aa7c692006-01-06 00:19:34 -080089{
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070090 fuse_dentry_settime(entry,
91 time_to_jiffies(o->entry_valid, o->entry_valid_nsec));
Miklos Szeredi1fb69e72007-10-18 03:06:58 -070092}
93
94static u64 attr_timeout(struct fuse_attr_out *o)
95{
96 return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
97}
98
99static u64 entry_attr_timeout(struct fuse_entry_out *o)
100{
101 return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800102}
103
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800104/*
105 * Mark the attributes as stale, so that at the next call to
106 * ->getattr() they will be fetched from userspace
107 */
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800108void fuse_invalidate_attr(struct inode *inode)
109{
Miklos Szeredi0a0898c2006-07-30 03:04:10 -0700110 get_fuse_inode(inode)->i_time = 0;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800111}
112
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800113/*
114 * Just mark the entry as stale, so that a next attempt to look it up
115 * will result in a new lookup call to userspace
116 *
117 * This is called when a dentry is about to become negative and the
118 * timeout is unknown (unlink, rmdir, rename and in some cases
119 * lookup)
120 */
Miklos Szeredidbd561d2008-07-25 01:49:00 -0700121void fuse_invalidate_entry_cache(struct dentry *entry)
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800122{
Miklos Szeredi0a0898c2006-07-30 03:04:10 -0700123 fuse_dentry_settime(entry, 0);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800124}
125
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800126/*
127 * Same as fuse_invalidate_entry_cache(), but also try to remove the
128 * dentry from the hash
129 */
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800130static void fuse_invalidate_entry(struct dentry *entry)
131{
132 d_invalidate(entry);
133 fuse_invalidate_entry_cache(entry);
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800134}
135
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700136static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_req *req,
137 u64 nodeid, struct qstr *name,
Miklos Szeredie5e55582005-09-09 13:10:28 -0700138 struct fuse_entry_out *outarg)
139{
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700140 memset(outarg, 0, sizeof(struct fuse_entry_out));
Miklos Szeredie5e55582005-09-09 13:10:28 -0700141 req->in.h.opcode = FUSE_LOOKUP;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700142 req->in.h.nodeid = nodeid;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700143 req->in.numargs = 1;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700144 req->in.args[0].size = name->len + 1;
145 req->in.args[0].value = name->name;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700146 req->out.numargs = 1;
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700147 if (fc->minor < 9)
148 req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
149 else
150 req->out.args[0].size = sizeof(struct fuse_entry_out);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700151 req->out.args[0].value = outarg;
152}
153
Miklos Szeredi5c5c5e52008-04-30 00:54:43 -0700154u64 fuse_get_attr_version(struct fuse_conn *fc)
Miklos Szeredi7dca9fd2007-11-28 16:21:59 -0800155{
156 u64 curr_version;
157
158 /*
159 * The spin lock isn't actually needed on 64bit archs, but we
160 * don't yet care too much about such optimizations.
161 */
162 spin_lock(&fc->lock);
163 curr_version = fc->attr_version;
164 spin_unlock(&fc->lock);
165
166 return curr_version;
167}
168
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800169/*
170 * Check whether the dentry is still valid
171 *
172 * If the entry validity timeout has expired and the dentry is
173 * positive, try to redo the lookup. If the lookup results in a
174 * different inode, then let the VFS invalidate the dentry and redo
175 * the lookup once more. If the lookup results in the same inode,
176 * then refresh the attributes, timeouts and mark the dentry valid.
177 */
Al Viro0b728e12012-06-10 16:03:43 -0400178static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700179{
Nick Piggin34286d62011-01-07 17:49:57 +1100180 struct inode *inode;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800181
Miklos Szeredie7c0a162011-03-21 13:58:06 +0100182 inode = ACCESS_ONCE(entry->d_inode);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800183 if (inode && is_bad_inode(inode))
Miklos Szeredie5e55582005-09-09 13:10:28 -0700184 return 0;
Miklos Szeredi0a0898c2006-07-30 03:04:10 -0700185 else if (fuse_dentry_time(entry) < get_jiffies_64()) {
Miklos Szeredie5e55582005-09-09 13:10:28 -0700186 int err;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700187 struct fuse_entry_out outarg;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800188 struct fuse_conn *fc;
189 struct fuse_req *req;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100190 struct fuse_forget_link *forget;
Miklos Szeredie956edd2006-10-17 00:10:12 -0700191 struct dentry *parent;
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700192 u64 attr_version;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800193
Miklos Szeredi50322fe2006-02-28 16:59:03 -0800194 /* For negative dentries, always do a fresh lookup */
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800195 if (!inode)
196 return 0;
197
Al Viro0b728e12012-06-10 16:03:43 -0400198 if (flags & LOOKUP_RCU)
Miklos Szeredie7c0a162011-03-21 13:58:06 +0100199 return -ECHILD;
200
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800201 fc = get_fuse_conn(inode);
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400202 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700203 if (IS_ERR(req))
Miklos Szeredie5e55582005-09-09 13:10:28 -0700204 return 0;
205
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100206 forget = fuse_alloc_forget();
207 if (!forget) {
Miklos Szeredi2d510132006-11-25 11:09:20 -0800208 fuse_put_request(fc, req);
209 return 0;
210 }
211
Miklos Szeredi7dca9fd2007-11-28 16:21:59 -0800212 attr_version = fuse_get_attr_version(fc);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700213
Miklos Szeredie956edd2006-10-17 00:10:12 -0700214 parent = dget_parent(entry);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700215 fuse_lookup_init(fc, req, get_node_id(parent->d_inode),
216 &entry->d_name, &outarg);
Tejun Heob93f8582008-11-26 12:03:55 +0100217 fuse_request_send(fc, req);
Miklos Szeredie956edd2006-10-17 00:10:12 -0700218 dput(parent);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700219 err = req->out.h.error;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800220 fuse_put_request(fc, req);
Miklos Szeredi50322fe2006-02-28 16:59:03 -0800221 /* Zero nodeid is same as -ENOENT */
222 if (!err && !outarg.nodeid)
223 err = -ENOENT;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700224 if (!err) {
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800225 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700226 if (outarg.nodeid != get_node_id(inode)) {
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100227 fuse_queue_forget(fc, forget, outarg.nodeid, 1);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700228 return 0;
229 }
Miklos Szeredi8da5ff22006-10-17 00:10:08 -0700230 spin_lock(&fc->lock);
Miklos Szeredi1729a162008-11-26 12:03:54 +0100231 fi->nlookup++;
Miklos Szeredi8da5ff22006-10-17 00:10:08 -0700232 spin_unlock(&fc->lock);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700233 }
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100234 kfree(forget);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700235 if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700236 return 0;
237
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700238 fuse_change_attributes(inode, &outarg.attr,
239 entry_attr_timeout(&outarg),
240 attr_version);
241 fuse_change_entry_timeout(entry, &outarg);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700242 }
Feng Shuo4582a4a2013-01-15 11:23:28 +0800243 fuse_advise_use_readdirplus(inode);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700244 return 1;
245}
246
Miklos Szeredi8bfc0162006-01-16 22:14:28 -0800247static int invalid_nodeid(u64 nodeid)
Miklos Szeredi2827d0b22005-11-28 13:44:16 -0800248{
249 return !nodeid || nodeid == FUSE_ROOT_ID;
250}
251
Al Viro42695902009-02-20 05:59:13 +0000252const struct dentry_operations fuse_dentry_operations = {
Miklos Szeredie5e55582005-09-09 13:10:28 -0700253 .d_revalidate = fuse_dentry_revalidate,
254};
255
Timo Savolaa5bfffac2007-04-08 16:04:00 -0700256int fuse_valid_type(int m)
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800257{
258 return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) ||
259 S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m);
260}
261
Miklos Szeredid2a85162006-10-17 00:10:11 -0700262/*
263 * Add a directory inode to a dentry, ensuring that no other dentry
264 * refers to this inode. Called with fc->inst_mutex.
265 */
Miklos Szeredi0de62562008-07-25 01:48:59 -0700266static struct dentry *fuse_d_add_directory(struct dentry *entry,
267 struct inode *inode)
Miklos Szeredid2a85162006-10-17 00:10:11 -0700268{
269 struct dentry *alias = d_find_alias(inode);
Miklos Szeredi0de62562008-07-25 01:48:59 -0700270 if (alias && !(alias->d_flags & DCACHE_DISCONNECTED)) {
Miklos Szeredid2a85162006-10-17 00:10:11 -0700271 /* This tries to shrink the subtree below alias */
272 fuse_invalidate_entry(alias);
273 dput(alias);
Al Virob3d9b7a2012-06-09 13:51:19 -0400274 if (!hlist_empty(&inode->i_dentry))
Miklos Szeredi0de62562008-07-25 01:48:59 -0700275 return ERR_PTR(-EBUSY);
276 } else {
277 dput(alias);
Miklos Szeredid2a85162006-10-17 00:10:11 -0700278 }
Miklos Szeredi0de62562008-07-25 01:48:59 -0700279 return d_splice_alias(inode, entry);
Miklos Szeredid2a85162006-10-17 00:10:11 -0700280}
281
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700282int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name,
283 struct fuse_entry_out *outarg, struct inode **inode)
284{
285 struct fuse_conn *fc = get_fuse_conn_super(sb);
286 struct fuse_req *req;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100287 struct fuse_forget_link *forget;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700288 u64 attr_version;
289 int err;
290
291 *inode = NULL;
292 err = -ENAMETOOLONG;
293 if (name->len > FUSE_NAME_MAX)
294 goto out;
295
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400296 req = fuse_get_req_nopages(fc);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700297 err = PTR_ERR(req);
298 if (IS_ERR(req))
299 goto out;
300
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100301 forget = fuse_alloc_forget();
302 err = -ENOMEM;
303 if (!forget) {
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700304 fuse_put_request(fc, req);
305 goto out;
306 }
307
308 attr_version = fuse_get_attr_version(fc);
309
310 fuse_lookup_init(fc, req, nodeid, name, outarg);
Tejun Heob93f8582008-11-26 12:03:55 +0100311 fuse_request_send(fc, req);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700312 err = req->out.h.error;
313 fuse_put_request(fc, req);
314 /* Zero nodeid is same as -ENOENT, but with valid timeout */
315 if (err || !outarg->nodeid)
316 goto out_put_forget;
317
318 err = -EIO;
319 if (!outarg->nodeid)
320 goto out_put_forget;
321 if (!fuse_valid_type(outarg->attr.mode))
322 goto out_put_forget;
323
324 *inode = fuse_iget(sb, outarg->nodeid, outarg->generation,
325 &outarg->attr, entry_attr_timeout(outarg),
326 attr_version);
327 err = -ENOMEM;
328 if (!*inode) {
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100329 fuse_queue_forget(fc, forget, outarg->nodeid, 1);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700330 goto out;
331 }
332 err = 0;
333
334 out_put_forget:
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100335 kfree(forget);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700336 out:
337 return err;
338}
339
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800340static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
Al Viro00cd8dd2012-06-10 17:13:09 -0400341 unsigned int flags)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700342{
343 int err;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700344 struct fuse_entry_out outarg;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700345 struct inode *inode;
Miklos Szeredi0de62562008-07-25 01:48:59 -0700346 struct dentry *newent;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700347 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700348 bool outarg_valid = true;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700349
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700350 err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name,
351 &outarg, &inode);
352 if (err == -ENOENT) {
353 outarg_valid = false;
354 err = 0;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800355 }
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700356 if (err)
357 goto out_err;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800358
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700359 err = -EIO;
360 if (inode && get_node_id(inode) == FUSE_ROOT_ID)
361 goto out_iput;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700362
Miklos Szeredid2a85162006-10-17 00:10:11 -0700363 if (inode && S_ISDIR(inode->i_mode)) {
364 mutex_lock(&fc->inst_mutex);
Miklos Szeredi0de62562008-07-25 01:48:59 -0700365 newent = fuse_d_add_directory(entry, inode);
Miklos Szeredid2a85162006-10-17 00:10:11 -0700366 mutex_unlock(&fc->inst_mutex);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700367 err = PTR_ERR(newent);
368 if (IS_ERR(newent))
369 goto out_iput;
370 } else {
Miklos Szeredi0de62562008-07-25 01:48:59 -0700371 newent = d_splice_alias(inode, entry);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700372 }
Miklos Szeredid2a85162006-10-17 00:10:11 -0700373
Miklos Szeredi0de62562008-07-25 01:48:59 -0700374 entry = newent ? newent : entry;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700375 if (outarg_valid)
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700376 fuse_change_entry_timeout(entry, &outarg);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800377 else
378 fuse_invalidate_entry_cache(entry);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700379
Feng Shuo4582a4a2013-01-15 11:23:28 +0800380 fuse_advise_use_readdirplus(dir);
Miklos Szeredi0de62562008-07-25 01:48:59 -0700381 return newent;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700382
383 out_iput:
384 iput(inode);
385 out_err:
386 return ERR_PTR(err);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700387}
388
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800389/*
390 * Atomic create+open operation
391 *
392 * If the filesystem doesn't support this, then fall back to separate
393 * 'mknod' + 'open' requests.
394 */
Al Virod9585272012-06-22 12:39:14 +0400395static int fuse_create_open(struct inode *dir, struct dentry *entry,
Al Viro30d90492012-06-22 12:40:19 +0400396 struct file *file, unsigned flags,
Al Virod9585272012-06-22 12:39:14 +0400397 umode_t mode, int *opened)
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800398{
399 int err;
400 struct inode *inode;
401 struct fuse_conn *fc = get_fuse_conn(dir);
402 struct fuse_req *req;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100403 struct fuse_forget_link *forget;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200404 struct fuse_create_in inarg;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800405 struct fuse_open_out outopen;
406 struct fuse_entry_out outentry;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800407 struct fuse_file *ff;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800408
Miklos Szerediaf109bc2012-08-15 13:01:24 +0200409 /* Userspace expects S_IFREG in create mode */
410 BUG_ON((mode & S_IFMT) != S_IFREG);
411
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100412 forget = fuse_alloc_forget();
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200413 err = -ENOMEM;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100414 if (!forget)
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200415 goto out_err;
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700416
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400417 req = fuse_get_req_nopages(fc);
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700418 err = PTR_ERR(req);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700419 if (IS_ERR(req))
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700420 goto out_put_forget_req;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800421
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700422 err = -ENOMEM;
Tejun Heoacf99432008-11-26 12:03:55 +0100423 ff = fuse_file_alloc(fc);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800424 if (!ff)
425 goto out_put_request;
426
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200427 if (!fc->dont_mask)
428 mode &= ~current_umask();
429
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800430 flags &= ~O_NOCTTY;
431 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700432 memset(&outentry, 0, sizeof(outentry));
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800433 inarg.flags = flags;
434 inarg.mode = mode;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200435 inarg.umask = current_umask();
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800436 req->in.h.opcode = FUSE_CREATE;
437 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800438 req->in.numargs = 2;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200439 req->in.args[0].size = fc->minor < 12 ? sizeof(struct fuse_open_in) :
440 sizeof(inarg);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800441 req->in.args[0].value = &inarg;
442 req->in.args[1].size = entry->d_name.len + 1;
443 req->in.args[1].value = entry->d_name.name;
444 req->out.numargs = 2;
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700445 if (fc->minor < 9)
446 req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
447 else
448 req->out.args[0].size = sizeof(outentry);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800449 req->out.args[0].value = &outentry;
450 req->out.args[1].size = sizeof(outopen);
451 req->out.args[1].value = &outopen;
Tejun Heob93f8582008-11-26 12:03:55 +0100452 fuse_request_send(fc, req);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800453 err = req->out.h.error;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200454 if (err)
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800455 goto out_free_ff;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800456
457 err = -EIO;
Miklos Szeredi2827d0b22005-11-28 13:44:16 -0800458 if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid))
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800459 goto out_free_ff;
460
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700461 fuse_put_request(fc, req);
Miklos Szeredic7b71432009-04-28 16:56:37 +0200462 ff->fh = outopen.fh;
463 ff->nodeid = outentry.nodeid;
464 ff->open_flags = outopen.open_flags;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800465 inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700466 &outentry.attr, entry_attr_timeout(&outentry), 0);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800467 if (!inode) {
468 flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
Miklos Szeredi8b0797a2009-04-28 16:56:39 +0200469 fuse_sync_release(ff, flags);
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100470 fuse_queue_forget(fc, forget, outentry.nodeid, 1);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200471 err = -ENOMEM;
472 goto out_err;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800473 }
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100474 kfree(forget);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800475 d_instantiate(entry, inode);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700476 fuse_change_entry_timeout(entry, &outentry);
Miklos Szeredi0952b2a2008-02-06 01:38:38 -0800477 fuse_invalidate_attr(dir);
Al Viro30d90492012-06-22 12:40:19 +0400478 err = finish_open(file, entry, generic_file_open, opened);
479 if (err) {
Miklos Szeredi8b0797a2009-04-28 16:56:39 +0200480 fuse_sync_release(ff, flags);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200481 } else {
482 file->private_data = fuse_file_get(ff);
483 fuse_finish_open(inode, file);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800484 }
Al Virod9585272012-06-22 12:39:14 +0400485 return err;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800486
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200487out_free_ff:
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800488 fuse_file_free(ff);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200489out_put_request:
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800490 fuse_put_request(fc, req);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200491out_put_forget_req:
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100492 kfree(forget);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200493out_err:
Al Virod9585272012-06-22 12:39:14 +0400494 return err;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200495}
496
497static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t);
Al Virod9585272012-06-22 12:39:14 +0400498static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
Al Viro30d90492012-06-22 12:40:19 +0400499 struct file *file, unsigned flags,
Al Virod9585272012-06-22 12:39:14 +0400500 umode_t mode, int *opened)
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200501{
502 int err;
503 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200504 struct dentry *res = NULL;
505
506 if (d_unhashed(entry)) {
Al Viro00cd8dd2012-06-10 17:13:09 -0400507 res = fuse_lookup(dir, entry, 0);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200508 if (IS_ERR(res))
Al Virod9585272012-06-22 12:39:14 +0400509 return PTR_ERR(res);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200510
511 if (res)
512 entry = res;
513 }
514
515 if (!(flags & O_CREAT) || entry->d_inode)
516 goto no_open;
517
518 /* Only creates */
Al Viro47237682012-06-10 05:01:45 -0400519 *opened |= FILE_CREATED;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200520
521 if (fc->no_create)
522 goto mknod;
523
Al Viro30d90492012-06-22 12:40:19 +0400524 err = fuse_create_open(dir, entry, file, flags, mode, opened);
Al Virod9585272012-06-22 12:39:14 +0400525 if (err == -ENOSYS) {
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200526 fc->no_create = 1;
527 goto mknod;
528 }
529out_dput:
530 dput(res);
Al Virod9585272012-06-22 12:39:14 +0400531 return err;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200532
533mknod:
534 err = fuse_mknod(dir, entry, mode, 0);
Al Virod9585272012-06-22 12:39:14 +0400535 if (err)
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200536 goto out_dput;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200537no_open:
Al Viroe45198a2012-06-10 06:48:09 -0400538 return finish_no_open(file, res);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800539}
540
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800541/*
542 * Code shared between mknod, mkdir, symlink and link
543 */
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700544static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
545 struct inode *dir, struct dentry *entry,
Al Viro541af6a2011-07-26 03:17:33 -0400546 umode_t mode)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700547{
548 struct fuse_entry_out outarg;
549 struct inode *inode;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700550 int err;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100551 struct fuse_forget_link *forget;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800552
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100553 forget = fuse_alloc_forget();
554 if (!forget) {
Miklos Szeredi2d510132006-11-25 11:09:20 -0800555 fuse_put_request(fc, req);
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100556 return -ENOMEM;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800557 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700558
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700559 memset(&outarg, 0, sizeof(outarg));
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700560 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700561 req->out.numargs = 1;
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700562 if (fc->minor < 9)
563 req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
564 else
565 req->out.args[0].size = sizeof(outarg);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700566 req->out.args[0].value = &outarg;
Tejun Heob93f8582008-11-26 12:03:55 +0100567 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700568 err = req->out.h.error;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800569 fuse_put_request(fc, req);
570 if (err)
571 goto out_put_forget_req;
572
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800573 err = -EIO;
574 if (invalid_nodeid(outarg.nodeid))
Miklos Szeredi2d510132006-11-25 11:09:20 -0800575 goto out_put_forget_req;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800576
577 if ((outarg.attr.mode ^ mode) & S_IFMT)
Miklos Szeredi2d510132006-11-25 11:09:20 -0800578 goto out_put_forget_req;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800579
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700580 inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700581 &outarg.attr, entry_attr_timeout(&outarg), 0);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700582 if (!inode) {
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100583 fuse_queue_forget(fc, forget, outarg.nodeid, 1);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700584 return -ENOMEM;
585 }
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100586 kfree(forget);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700587
Miklos Szeredid2a85162006-10-17 00:10:11 -0700588 if (S_ISDIR(inode->i_mode)) {
589 struct dentry *alias;
590 mutex_lock(&fc->inst_mutex);
591 alias = d_find_alias(inode);
592 if (alias) {
593 /* New directory must have moved since mkdir */
594 mutex_unlock(&fc->inst_mutex);
595 dput(alias);
596 iput(inode);
597 return -EBUSY;
598 }
599 d_instantiate(entry, inode);
600 mutex_unlock(&fc->inst_mutex);
601 } else
602 d_instantiate(entry, inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700603
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700604 fuse_change_entry_timeout(entry, &outarg);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700605 fuse_invalidate_attr(dir);
606 return 0;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800607
Miklos Szeredi2d510132006-11-25 11:09:20 -0800608 out_put_forget_req:
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100609 kfree(forget);
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800610 return err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700611}
612
Al Viro1a67aaf2011-07-26 01:52:52 -0400613static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700614 dev_t rdev)
615{
616 struct fuse_mknod_in inarg;
617 struct fuse_conn *fc = get_fuse_conn(dir);
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400618 struct fuse_req *req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700619 if (IS_ERR(req))
620 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700621
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200622 if (!fc->dont_mask)
623 mode &= ~current_umask();
624
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700625 memset(&inarg, 0, sizeof(inarg));
626 inarg.mode = mode;
627 inarg.rdev = new_encode_dev(rdev);
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200628 inarg.umask = current_umask();
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700629 req->in.h.opcode = FUSE_MKNOD;
630 req->in.numargs = 2;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200631 req->in.args[0].size = fc->minor < 12 ? FUSE_COMPAT_MKNOD_IN_SIZE :
632 sizeof(inarg);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700633 req->in.args[0].value = &inarg;
634 req->in.args[1].size = entry->d_name.len + 1;
635 req->in.args[1].value = entry->d_name.name;
636 return create_new_entry(fc, req, dir, entry, mode);
637}
638
Al Viro4acdaf22011-07-26 01:42:34 -0400639static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode,
Al Viroebfc3b42012-06-10 18:05:36 -0400640 bool excl)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700641{
642 return fuse_mknod(dir, entry, mode, 0);
643}
644
Al Viro18bb1db2011-07-26 01:41:39 -0400645static int fuse_mkdir(struct inode *dir, struct dentry *entry, umode_t mode)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700646{
647 struct fuse_mkdir_in inarg;
648 struct fuse_conn *fc = get_fuse_conn(dir);
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400649 struct fuse_req *req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700650 if (IS_ERR(req))
651 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700652
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200653 if (!fc->dont_mask)
654 mode &= ~current_umask();
655
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700656 memset(&inarg, 0, sizeof(inarg));
657 inarg.mode = mode;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200658 inarg.umask = current_umask();
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700659 req->in.h.opcode = FUSE_MKDIR;
660 req->in.numargs = 2;
661 req->in.args[0].size = sizeof(inarg);
662 req->in.args[0].value = &inarg;
663 req->in.args[1].size = entry->d_name.len + 1;
664 req->in.args[1].value = entry->d_name.name;
665 return create_new_entry(fc, req, dir, entry, S_IFDIR);
666}
667
668static int fuse_symlink(struct inode *dir, struct dentry *entry,
669 const char *link)
670{
671 struct fuse_conn *fc = get_fuse_conn(dir);
672 unsigned len = strlen(link) + 1;
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400673 struct fuse_req *req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700674 if (IS_ERR(req))
675 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700676
677 req->in.h.opcode = FUSE_SYMLINK;
678 req->in.numargs = 2;
679 req->in.args[0].size = entry->d_name.len + 1;
680 req->in.args[0].value = entry->d_name.name;
681 req->in.args[1].size = len;
682 req->in.args[1].value = link;
683 return create_new_entry(fc, req, dir, entry, S_IFLNK);
684}
685
686static int fuse_unlink(struct inode *dir, struct dentry *entry)
687{
688 int err;
689 struct fuse_conn *fc = get_fuse_conn(dir);
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400690 struct fuse_req *req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700691 if (IS_ERR(req))
692 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700693
694 req->in.h.opcode = FUSE_UNLINK;
695 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700696 req->in.numargs = 1;
697 req->in.args[0].size = entry->d_name.len + 1;
698 req->in.args[0].value = entry->d_name.name;
Tejun Heob93f8582008-11-26 12:03:55 +0100699 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700700 err = req->out.h.error;
701 fuse_put_request(fc, req);
702 if (!err) {
703 struct inode *inode = entry->d_inode;
Miklos Szerediac45d612012-03-05 15:48:11 +0100704 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700705
Miklos Szerediac45d612012-03-05 15:48:11 +0100706 spin_lock(&fc->lock);
707 fi->attr_version = ++fc->attr_version;
708 drop_nlink(inode);
709 spin_unlock(&fc->lock);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700710 fuse_invalidate_attr(inode);
711 fuse_invalidate_attr(dir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800712 fuse_invalidate_entry_cache(entry);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700713 } else if (err == -EINTR)
714 fuse_invalidate_entry(entry);
715 return err;
716}
717
718static int fuse_rmdir(struct inode *dir, struct dentry *entry)
719{
720 int err;
721 struct fuse_conn *fc = get_fuse_conn(dir);
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400722 struct fuse_req *req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700723 if (IS_ERR(req))
724 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700725
726 req->in.h.opcode = FUSE_RMDIR;
727 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700728 req->in.numargs = 1;
729 req->in.args[0].size = entry->d_name.len + 1;
730 req->in.args[0].value = entry->d_name.name;
Tejun Heob93f8582008-11-26 12:03:55 +0100731 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700732 err = req->out.h.error;
733 fuse_put_request(fc, req);
734 if (!err) {
Dave Hansence71ec32006-09-30 23:29:06 -0700735 clear_nlink(entry->d_inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700736 fuse_invalidate_attr(dir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800737 fuse_invalidate_entry_cache(entry);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700738 } else if (err == -EINTR)
739 fuse_invalidate_entry(entry);
740 return err;
741}
742
743static int fuse_rename(struct inode *olddir, struct dentry *oldent,
744 struct inode *newdir, struct dentry *newent)
745{
746 int err;
747 struct fuse_rename_in inarg;
748 struct fuse_conn *fc = get_fuse_conn(olddir);
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400749 struct fuse_req *req = fuse_get_req_nopages(fc);
Sage Weile4eaac02011-05-24 13:06:07 -0700750
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700751 if (IS_ERR(req))
752 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700753
754 memset(&inarg, 0, sizeof(inarg));
755 inarg.newdir = get_node_id(newdir);
756 req->in.h.opcode = FUSE_RENAME;
757 req->in.h.nodeid = get_node_id(olddir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700758 req->in.numargs = 3;
759 req->in.args[0].size = sizeof(inarg);
760 req->in.args[0].value = &inarg;
761 req->in.args[1].size = oldent->d_name.len + 1;
762 req->in.args[1].value = oldent->d_name.name;
763 req->in.args[2].size = newent->d_name.len + 1;
764 req->in.args[2].value = newent->d_name.name;
Tejun Heob93f8582008-11-26 12:03:55 +0100765 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700766 err = req->out.h.error;
767 fuse_put_request(fc, req);
768 if (!err) {
Miklos Szeredi08b63302007-11-28 16:22:03 -0800769 /* ctime changes */
770 fuse_invalidate_attr(oldent->d_inode);
771
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700772 fuse_invalidate_attr(olddir);
773 if (olddir != newdir)
774 fuse_invalidate_attr(newdir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800775
776 /* newent will end up negative */
Miklos Szeredi5219f342009-11-04 10:24:52 +0100777 if (newent->d_inode) {
778 fuse_invalidate_attr(newent->d_inode);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800779 fuse_invalidate_entry_cache(newent);
Miklos Szeredi5219f342009-11-04 10:24:52 +0100780 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700781 } else if (err == -EINTR) {
782 /* If request was interrupted, DEITY only knows if the
783 rename actually took place. If the invalidation
784 fails (e.g. some process has CWD under the renamed
785 directory), then there can be inconsistency between
786 the dcache and the real filesystem. Tough luck. */
787 fuse_invalidate_entry(oldent);
788 if (newent->d_inode)
789 fuse_invalidate_entry(newent);
790 }
791
792 return err;
793}
794
795static int fuse_link(struct dentry *entry, struct inode *newdir,
796 struct dentry *newent)
797{
798 int err;
799 struct fuse_link_in inarg;
800 struct inode *inode = entry->d_inode;
801 struct fuse_conn *fc = get_fuse_conn(inode);
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400802 struct fuse_req *req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700803 if (IS_ERR(req))
804 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700805
806 memset(&inarg, 0, sizeof(inarg));
807 inarg.oldnodeid = get_node_id(inode);
808 req->in.h.opcode = FUSE_LINK;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700809 req->in.numargs = 2;
810 req->in.args[0].size = sizeof(inarg);
811 req->in.args[0].value = &inarg;
812 req->in.args[1].size = newent->d_name.len + 1;
813 req->in.args[1].value = newent->d_name.name;
814 err = create_new_entry(fc, req, newdir, newent, inode->i_mode);
815 /* Contrary to "normal" filesystems it can happen that link
816 makes two "logical" inodes point to the same "physical"
817 inode. We invalidate the attributes of the old one, so it
818 will reflect changes in the backing inode (link count,
819 etc.)
820 */
Miklos Szerediac45d612012-03-05 15:48:11 +0100821 if (!err) {
822 struct fuse_inode *fi = get_fuse_inode(inode);
823
824 spin_lock(&fc->lock);
825 fi->attr_version = ++fc->attr_version;
826 inc_nlink(inode);
827 spin_unlock(&fc->lock);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700828 fuse_invalidate_attr(inode);
Miklos Szerediac45d612012-03-05 15:48:11 +0100829 } else if (err == -EINTR) {
830 fuse_invalidate_attr(inode);
831 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700832 return err;
833}
834
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700835static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
836 struct kstat *stat)
837{
Miklos Szeredi203627b2012-05-10 19:49:38 +0400838 unsigned int blkbits;
839
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700840 stat->dev = inode->i_sb->s_dev;
841 stat->ino = attr->ino;
842 stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
843 stat->nlink = attr->nlink;
Eric W. Biederman499dcf22012-02-07 16:26:03 -0800844 stat->uid = make_kuid(&init_user_ns, attr->uid);
845 stat->gid = make_kgid(&init_user_ns, attr->gid);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700846 stat->rdev = inode->i_rdev;
847 stat->atime.tv_sec = attr->atime;
848 stat->atime.tv_nsec = attr->atimensec;
849 stat->mtime.tv_sec = attr->mtime;
850 stat->mtime.tv_nsec = attr->mtimensec;
851 stat->ctime.tv_sec = attr->ctime;
852 stat->ctime.tv_nsec = attr->ctimensec;
853 stat->size = attr->size;
854 stat->blocks = attr->blocks;
Miklos Szeredi203627b2012-05-10 19:49:38 +0400855
856 if (attr->blksize != 0)
857 blkbits = ilog2(attr->blksize);
858 else
859 blkbits = inode->i_sb->s_blocksize_bits;
860
861 stat->blksize = 1 << blkbits;
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700862}
863
Miklos Szeredic79e3222007-10-18 03:06:59 -0700864static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
865 struct file *file)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700866{
867 int err;
Miklos Szeredic79e3222007-10-18 03:06:59 -0700868 struct fuse_getattr_in inarg;
869 struct fuse_attr_out outarg;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700870 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700871 struct fuse_req *req;
872 u64 attr_version;
873
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400874 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700875 if (IS_ERR(req))
876 return PTR_ERR(req);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700877
Miklos Szeredi7dca9fd2007-11-28 16:21:59 -0800878 attr_version = fuse_get_attr_version(fc);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700879
Miklos Szeredic79e3222007-10-18 03:06:59 -0700880 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700881 memset(&outarg, 0, sizeof(outarg));
Miklos Szeredic79e3222007-10-18 03:06:59 -0700882 /* Directories have separate file-handle space */
883 if (file && S_ISREG(inode->i_mode)) {
884 struct fuse_file *ff = file->private_data;
885
886 inarg.getattr_flags |= FUSE_GETATTR_FH;
887 inarg.fh = ff->fh;
888 }
Miklos Szeredie5e55582005-09-09 13:10:28 -0700889 req->in.h.opcode = FUSE_GETATTR;
890 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredic79e3222007-10-18 03:06:59 -0700891 req->in.numargs = 1;
892 req->in.args[0].size = sizeof(inarg);
893 req->in.args[0].value = &inarg;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700894 req->out.numargs = 1;
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700895 if (fc->minor < 9)
896 req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
897 else
898 req->out.args[0].size = sizeof(outarg);
Miklos Szeredic79e3222007-10-18 03:06:59 -0700899 req->out.args[0].value = &outarg;
Tejun Heob93f8582008-11-26 12:03:55 +0100900 fuse_request_send(fc, req);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700901 err = req->out.h.error;
902 fuse_put_request(fc, req);
903 if (!err) {
Miklos Szeredic79e3222007-10-18 03:06:59 -0700904 if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
Miklos Szeredie5e55582005-09-09 13:10:28 -0700905 make_bad_inode(inode);
906 err = -EIO;
907 } else {
Miklos Szeredic79e3222007-10-18 03:06:59 -0700908 fuse_change_attributes(inode, &outarg.attr,
909 attr_timeout(&outarg),
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700910 attr_version);
911 if (stat)
Miklos Szeredic79e3222007-10-18 03:06:59 -0700912 fuse_fillattr(inode, &outarg.attr, stat);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700913 }
914 }
915 return err;
916}
917
Miklos Szeredibcb4be82007-11-28 16:21:59 -0800918int fuse_update_attributes(struct inode *inode, struct kstat *stat,
919 struct file *file, bool *refreshed)
920{
921 struct fuse_inode *fi = get_fuse_inode(inode);
922 int err;
923 bool r;
924
925 if (fi->i_time < get_jiffies_64()) {
926 r = true;
927 err = fuse_do_getattr(inode, stat, file);
928 } else {
929 r = false;
930 err = 0;
931 if (stat) {
932 generic_fillattr(inode, stat);
933 stat->mode = fi->orig_i_mode;
Pavel Shilovsky45c72cd2012-05-10 19:49:38 +0400934 stat->ino = fi->orig_ino;
Miklos Szeredibcb4be82007-11-28 16:21:59 -0800935 }
936 }
937
938 if (refreshed != NULL)
939 *refreshed = r;
940
941 return err;
942}
943
John Muir3b463ae2009-05-31 11:13:57 -0400944int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid,
John Muir451d0f52011-12-06 21:50:06 +0100945 u64 child_nodeid, struct qstr *name)
John Muir3b463ae2009-05-31 11:13:57 -0400946{
947 int err = -ENOTDIR;
948 struct inode *parent;
949 struct dentry *dir;
950 struct dentry *entry;
951
952 parent = ilookup5(sb, parent_nodeid, fuse_inode_eq, &parent_nodeid);
953 if (!parent)
954 return -ENOENT;
955
956 mutex_lock(&parent->i_mutex);
957 if (!S_ISDIR(parent->i_mode))
958 goto unlock;
959
960 err = -ENOENT;
961 dir = d_find_alias(parent);
962 if (!dir)
963 goto unlock;
964
965 entry = d_lookup(dir, name);
966 dput(dir);
967 if (!entry)
968 goto unlock;
969
970 fuse_invalidate_attr(parent);
971 fuse_invalidate_entry(entry);
John Muir451d0f52011-12-06 21:50:06 +0100972
973 if (child_nodeid != 0 && entry->d_inode) {
974 mutex_lock(&entry->d_inode->i_mutex);
975 if (get_node_id(entry->d_inode) != child_nodeid) {
976 err = -ENOENT;
977 goto badentry;
978 }
979 if (d_mountpoint(entry)) {
980 err = -EBUSY;
981 goto badentry;
982 }
983 if (S_ISDIR(entry->d_inode->i_mode)) {
984 shrink_dcache_parent(entry);
985 if (!simple_empty(entry)) {
986 err = -ENOTEMPTY;
987 goto badentry;
988 }
989 entry->d_inode->i_flags |= S_DEAD;
990 }
991 dont_mount(entry);
992 clear_nlink(entry->d_inode);
993 err = 0;
994 badentry:
995 mutex_unlock(&entry->d_inode->i_mutex);
996 if (!err)
997 d_delete(entry);
998 } else {
999 err = 0;
1000 }
John Muir3b463ae2009-05-31 11:13:57 -04001001 dput(entry);
John Muir3b463ae2009-05-31 11:13:57 -04001002
1003 unlock:
1004 mutex_unlock(&parent->i_mutex);
1005 iput(parent);
1006 return err;
1007}
1008
Miklos Szeredi87729a52005-09-09 13:10:34 -07001009/*
1010 * Calling into a user-controlled filesystem gives the filesystem
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001011 * daemon ptrace-like capabilities over the current process. This
Miklos Szeredi87729a52005-09-09 13:10:34 -07001012 * means, that the filesystem daemon is able to record the exact
1013 * filesystem operations performed, and can also control the behavior
1014 * of the requester process in otherwise impossible ways. For example
1015 * it can delay the operation for arbitrary length of time allowing
1016 * DoS against the requester.
1017 *
1018 * For this reason only those processes can call into the filesystem,
1019 * for which the owner of the mount has ptrace privilege. This
1020 * excludes processes started by other users, suid or sgid processes.
1021 */
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001022int fuse_allow_current_process(struct fuse_conn *fc)
Miklos Szeredi87729a52005-09-09 13:10:34 -07001023{
David Howellsc69e8d92008-11-14 10:39:19 +11001024 const struct cred *cred;
David Howellsc69e8d92008-11-14 10:39:19 +11001025
Miklos Szeredi87729a52005-09-09 13:10:34 -07001026 if (fc->flags & FUSE_ALLOW_OTHER)
1027 return 1;
1028
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001029 cred = current_cred();
Eric W. Biederman499dcf22012-02-07 16:26:03 -08001030 if (uid_eq(cred->euid, fc->user_id) &&
1031 uid_eq(cred->suid, fc->user_id) &&
1032 uid_eq(cred->uid, fc->user_id) &&
1033 gid_eq(cred->egid, fc->group_id) &&
1034 gid_eq(cred->sgid, fc->group_id) &&
1035 gid_eq(cred->gid, fc->group_id))
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001036 return 1;
Miklos Szeredi87729a52005-09-09 13:10:34 -07001037
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001038 return 0;
Miklos Szeredi87729a52005-09-09 13:10:34 -07001039}
1040
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001041static int fuse_access(struct inode *inode, int mask)
1042{
1043 struct fuse_conn *fc = get_fuse_conn(inode);
1044 struct fuse_req *req;
1045 struct fuse_access_in inarg;
1046 int err;
1047
1048 if (fc->no_access)
1049 return 0;
1050
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001051 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001052 if (IS_ERR(req))
1053 return PTR_ERR(req);
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001054
1055 memset(&inarg, 0, sizeof(inarg));
Al Viroe6305c42008-07-15 21:03:57 -04001056 inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC);
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001057 req->in.h.opcode = FUSE_ACCESS;
1058 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001059 req->in.numargs = 1;
1060 req->in.args[0].size = sizeof(inarg);
1061 req->in.args[0].value = &inarg;
Tejun Heob93f8582008-11-26 12:03:55 +01001062 fuse_request_send(fc, req);
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001063 err = req->out.h.error;
1064 fuse_put_request(fc, req);
1065 if (err == -ENOSYS) {
1066 fc->no_access = 1;
1067 err = 0;
1068 }
1069 return err;
1070}
1071
Al Viro10556cb2011-06-20 19:28:19 -04001072static int fuse_perm_getattr(struct inode *inode, int mask)
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001073{
Al Viro10556cb2011-06-20 19:28:19 -04001074 if (mask & MAY_NOT_BLOCK)
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001075 return -ECHILD;
1076
1077 return fuse_do_getattr(inode, NULL, NULL);
1078}
1079
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001080/*
1081 * Check permission. The two basic access models of FUSE are:
1082 *
1083 * 1) Local access checking ('default_permissions' mount option) based
1084 * on file mode. This is the plain old disk filesystem permission
1085 * modell.
1086 *
1087 * 2) "Remote" access checking, where server is responsible for
1088 * checking permission in each inode operation. An exception to this
1089 * is if ->permission() was invoked from sys_access() in which case an
1090 * access request is sent. Execute permission is still checked
1091 * locally based on file mode.
1092 */
Al Viro10556cb2011-06-20 19:28:19 -04001093static int fuse_permission(struct inode *inode, int mask)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001094{
1095 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi244f6382007-10-16 23:31:02 -07001096 bool refreshed = false;
1097 int err = 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001098
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001099 if (!fuse_allow_current_process(fc))
Miklos Szeredie5e55582005-09-09 13:10:28 -07001100 return -EACCES;
Miklos Szeredi244f6382007-10-16 23:31:02 -07001101
1102 /*
Miklos Szeredie8e96152007-10-16 23:31:06 -07001103 * If attributes are needed, refresh them before proceeding
Miklos Szeredi244f6382007-10-16 23:31:02 -07001104 */
Miklos Szeredie8e96152007-10-16 23:31:06 -07001105 if ((fc->flags & FUSE_DEFAULT_PERMISSIONS) ||
1106 ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001107 struct fuse_inode *fi = get_fuse_inode(inode);
1108
1109 if (fi->i_time < get_jiffies_64()) {
1110 refreshed = true;
1111
Al Viro10556cb2011-06-20 19:28:19 -04001112 err = fuse_perm_getattr(inode, mask);
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001113 if (err)
1114 return err;
1115 }
Miklos Szeredi244f6382007-10-16 23:31:02 -07001116 }
1117
1118 if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
Al Viro2830ba72011-06-20 19:16:29 -04001119 err = generic_permission(inode, mask);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001120
1121 /* If permission is denied, try to refresh file
1122 attributes. This is also needed, because the root
1123 node will at first have no permissions */
Miklos Szeredi244f6382007-10-16 23:31:02 -07001124 if (err == -EACCES && !refreshed) {
Al Viro10556cb2011-06-20 19:28:19 -04001125 err = fuse_perm_getattr(inode, mask);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001126 if (!err)
Al Viro2830ba72011-06-20 19:16:29 -04001127 err = generic_permission(inode, mask);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001128 }
1129
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001130 /* Note: the opposite of the above test does not
1131 exist. So if permissions are revoked this won't be
1132 noticed immediately, only after the attribute
1133 timeout has expired */
Eric Paris9cfcac82010-07-23 11:43:51 -04001134 } else if (mask & (MAY_ACCESS | MAY_CHDIR)) {
Al Viro10556cb2011-06-20 19:28:19 -04001135 if (mask & MAY_NOT_BLOCK)
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001136 return -ECHILD;
1137
Miklos Szeredie8e96152007-10-16 23:31:06 -07001138 err = fuse_access(inode, mask);
1139 } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
1140 if (!(inode->i_mode & S_IXUGO)) {
1141 if (refreshed)
1142 return -EACCES;
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001143
Al Viro10556cb2011-06-20 19:28:19 -04001144 err = fuse_perm_getattr(inode, mask);
Miklos Szeredie8e96152007-10-16 23:31:06 -07001145 if (!err && !(inode->i_mode & S_IXUGO))
1146 return -EACCES;
1147 }
Miklos Szeredie5e55582005-09-09 13:10:28 -07001148 }
Miklos Szeredi244f6382007-10-16 23:31:02 -07001149 return err;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001150}
1151
1152static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
1153 void *dstbuf, filldir_t filldir)
1154{
1155 while (nbytes >= FUSE_NAME_OFFSET) {
1156 struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
1157 size_t reclen = FUSE_DIRENT_SIZE(dirent);
1158 int over;
1159 if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
1160 return -EIO;
1161 if (reclen > nbytes)
1162 break;
1163
1164 over = filldir(dstbuf, dirent->name, dirent->namelen,
1165 file->f_pos, dirent->ino, dirent->type);
1166 if (over)
1167 break;
1168
1169 buf += reclen;
1170 nbytes -= reclen;
1171 file->f_pos = dirent->off;
1172 }
1173
1174 return 0;
1175}
1176
Anand V. Avati0b05b182012-08-19 08:53:23 -04001177static int fuse_direntplus_link(struct file *file,
1178 struct fuse_direntplus *direntplus,
1179 u64 attr_version)
1180{
1181 int err;
1182 struct fuse_entry_out *o = &direntplus->entry_out;
1183 struct fuse_dirent *dirent = &direntplus->dirent;
1184 struct dentry *parent = file->f_path.dentry;
1185 struct qstr name = QSTR_INIT(dirent->name, dirent->namelen);
1186 struct dentry *dentry;
1187 struct dentry *alias;
1188 struct inode *dir = parent->d_inode;
1189 struct fuse_conn *fc;
1190 struct inode *inode;
1191
1192 if (!o->nodeid) {
1193 /*
1194 * Unlike in the case of fuse_lookup, zero nodeid does not mean
1195 * ENOENT. Instead, it only means the userspace filesystem did
1196 * not want to return attributes/handle for this entry.
1197 *
1198 * So do nothing.
1199 */
1200 return 0;
1201 }
1202
1203 if (name.name[0] == '.') {
1204 /*
1205 * We could potentially refresh the attributes of the directory
1206 * and its parent?
1207 */
1208 if (name.len == 1)
1209 return 0;
1210 if (name.name[1] == '.' && name.len == 2)
1211 return 0;
1212 }
1213 fc = get_fuse_conn(dir);
1214
1215 name.hash = full_name_hash(name.name, name.len);
1216 dentry = d_lookup(parent, &name);
1217 if (dentry && dentry->d_inode) {
1218 inode = dentry->d_inode;
1219 if (get_node_id(inode) == o->nodeid) {
1220 struct fuse_inode *fi;
1221 fi = get_fuse_inode(inode);
1222 spin_lock(&fc->lock);
1223 fi->nlookup++;
1224 spin_unlock(&fc->lock);
1225
1226 /*
1227 * The other branch to 'found' comes via fuse_iget()
1228 * which bumps nlookup inside
1229 */
1230 goto found;
1231 }
1232 err = d_invalidate(dentry);
1233 if (err)
1234 goto out;
1235 dput(dentry);
1236 dentry = NULL;
1237 }
1238
1239 dentry = d_alloc(parent, &name);
1240 err = -ENOMEM;
1241 if (!dentry)
1242 goto out;
1243
1244 inode = fuse_iget(dir->i_sb, o->nodeid, o->generation,
1245 &o->attr, entry_attr_timeout(o), attr_version);
1246 if (!inode)
1247 goto out;
1248
1249 alias = d_materialise_unique(dentry, inode);
1250 err = PTR_ERR(alias);
1251 if (IS_ERR(alias))
1252 goto out;
1253 if (alias) {
1254 dput(dentry);
1255 dentry = alias;
1256 }
1257
1258found:
1259 fuse_change_attributes(inode, &o->attr, entry_attr_timeout(o),
1260 attr_version);
1261
1262 fuse_change_entry_timeout(dentry, o);
1263
1264 err = 0;
1265out:
1266 if (dentry)
1267 dput(dentry);
1268 return err;
1269}
1270
1271static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file,
1272 void *dstbuf, filldir_t filldir, u64 attr_version)
1273{
1274 struct fuse_direntplus *direntplus;
1275 struct fuse_dirent *dirent;
1276 size_t reclen;
1277 int over = 0;
1278 int ret;
1279
1280 while (nbytes >= FUSE_NAME_OFFSET_DIRENTPLUS) {
1281 direntplus = (struct fuse_direntplus *) buf;
1282 dirent = &direntplus->dirent;
1283 reclen = FUSE_DIRENTPLUS_SIZE(direntplus);
1284
1285 if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
1286 return -EIO;
1287 if (reclen > nbytes)
1288 break;
1289
1290 if (!over) {
1291 /* We fill entries into dstbuf only as much as
1292 it can hold. But we still continue iterating
1293 over remaining entries to link them. If not,
1294 we need to send a FORGET for each of those
1295 which we did not link.
1296 */
1297 over = filldir(dstbuf, dirent->name, dirent->namelen,
1298 file->f_pos, dirent->ino,
1299 dirent->type);
1300 file->f_pos = dirent->off;
1301 }
1302
1303 buf += reclen;
1304 nbytes -= reclen;
1305
1306 ret = fuse_direntplus_link(file, direntplus, attr_version);
1307 if (ret)
1308 fuse_force_forget(file, direntplus->entry_out.nodeid);
1309 }
1310
1311 return 0;
1312}
1313
Miklos Szeredie5e55582005-09-09 13:10:28 -07001314static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
1315{
Feng Shuo4582a4a2013-01-15 11:23:28 +08001316 int plus, err;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001317 size_t nbytes;
1318 struct page *page;
Josef Sipek7706a9d2006-12-08 02:37:02 -08001319 struct inode *inode = file->f_path.dentry->d_inode;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001320 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi248d86e2006-01-06 00:19:39 -08001321 struct fuse_req *req;
Anand V. Avati0b05b182012-08-19 08:53:23 -04001322 u64 attr_version = 0;
Miklos Szeredi248d86e2006-01-06 00:19:39 -08001323
1324 if (is_bad_inode(inode))
1325 return -EIO;
1326
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001327 req = fuse_get_req(fc, 1);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001328 if (IS_ERR(req))
1329 return PTR_ERR(req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001330
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001331 page = alloc_page(GFP_KERNEL);
1332 if (!page) {
1333 fuse_put_request(fc, req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001334 return -ENOMEM;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001335 }
Feng Shuo4582a4a2013-01-15 11:23:28 +08001336
1337 plus = fuse_use_readdirplus(inode, file);
Miklos Szeredif4975c62009-04-02 14:25:34 +02001338 req->out.argpages = 1;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001339 req->num_pages = 1;
1340 req->pages[0] = page;
Maxim Patlasov85f40ae2012-10-26 19:49:33 +04001341 req->page_descs[0].length = PAGE_SIZE;
Feng Shuo4582a4a2013-01-15 11:23:28 +08001342 if (plus) {
Anand V. Avati0b05b182012-08-19 08:53:23 -04001343 attr_version = fuse_get_attr_version(fc);
1344 fuse_read_fill(req, file, file->f_pos, PAGE_SIZE,
1345 FUSE_READDIRPLUS);
1346 } else {
1347 fuse_read_fill(req, file, file->f_pos, PAGE_SIZE,
1348 FUSE_READDIR);
1349 }
Tejun Heob93f8582008-11-26 12:03:55 +01001350 fuse_request_send(fc, req);
Miklos Szeredi361b1eb52006-01-16 22:14:45 -08001351 nbytes = req->out.args[0].size;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001352 err = req->out.h.error;
1353 fuse_put_request(fc, req);
Anand V. Avati0b05b182012-08-19 08:53:23 -04001354 if (!err) {
Feng Shuo4582a4a2013-01-15 11:23:28 +08001355 if (plus) {
Anand V. Avati0b05b182012-08-19 08:53:23 -04001356 err = parse_dirplusfile(page_address(page), nbytes,
1357 file, dstbuf, filldir,
1358 attr_version);
1359 } else {
1360 err = parse_dirfile(page_address(page), nbytes, file,
1361 dstbuf, filldir);
1362 }
1363 }
Miklos Szeredie5e55582005-09-09 13:10:28 -07001364
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001365 __free_page(page);
Miklos Szeredib36c31b2005-09-09 13:10:38 -07001366 fuse_invalidate_attr(inode); /* atime changed */
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001367 return err;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001368}
1369
1370static char *read_link(struct dentry *dentry)
1371{
1372 struct inode *inode = dentry->d_inode;
1373 struct fuse_conn *fc = get_fuse_conn(inode);
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001374 struct fuse_req *req = fuse_get_req_nopages(fc);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001375 char *link;
1376
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001377 if (IS_ERR(req))
David Howellse231c2e2008-02-07 00:15:26 -08001378 return ERR_CAST(req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001379
1380 link = (char *) __get_free_page(GFP_KERNEL);
1381 if (!link) {
1382 link = ERR_PTR(-ENOMEM);
1383 goto out;
1384 }
1385 req->in.h.opcode = FUSE_READLINK;
1386 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001387 req->out.argvar = 1;
1388 req->out.numargs = 1;
1389 req->out.args[0].size = PAGE_SIZE - 1;
1390 req->out.args[0].value = link;
Tejun Heob93f8582008-11-26 12:03:55 +01001391 fuse_request_send(fc, req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001392 if (req->out.h.error) {
1393 free_page((unsigned long) link);
1394 link = ERR_PTR(req->out.h.error);
1395 } else
1396 link[req->out.args[0].size] = '\0';
1397 out:
1398 fuse_put_request(fc, req);
Miklos Szeredib36c31b2005-09-09 13:10:38 -07001399 fuse_invalidate_attr(inode); /* atime changed */
Miklos Szeredie5e55582005-09-09 13:10:28 -07001400 return link;
1401}
1402
1403static void free_link(char *link)
1404{
1405 if (!IS_ERR(link))
1406 free_page((unsigned long) link);
1407}
1408
1409static void *fuse_follow_link(struct dentry *dentry, struct nameidata *nd)
1410{
1411 nd_set_link(nd, read_link(dentry));
1412 return NULL;
1413}
1414
1415static void fuse_put_link(struct dentry *dentry, struct nameidata *nd, void *c)
1416{
1417 free_link(nd_get_link(nd));
1418}
1419
1420static int fuse_dir_open(struct inode *inode, struct file *file)
1421{
Miklos Szeredi91fe96b2009-04-28 16:56:37 +02001422 return fuse_open_common(inode, file, true);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001423}
1424
1425static int fuse_dir_release(struct inode *inode, struct file *file)
1426{
Miklos Szeredi8b0797a2009-04-28 16:56:39 +02001427 fuse_release_common(file, FUSE_RELEASEDIR);
1428
1429 return 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001430}
1431
Josef Bacik02c24a82011-07-16 20:44:56 -04001432static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end,
1433 int datasync)
Miklos Szeredi82547982005-09-09 13:10:38 -07001434{
Josef Bacik02c24a82011-07-16 20:44:56 -04001435 return fuse_fsync_common(file, start, end, datasync, 1);
Miklos Szeredi82547982005-09-09 13:10:38 -07001436}
1437
Miklos Szeredib18da0c2011-12-13 11:58:49 +01001438static long fuse_dir_ioctl(struct file *file, unsigned int cmd,
1439 unsigned long arg)
1440{
1441 struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1442
1443 /* FUSE_IOCTL_DIR only supported for API version >= 7.18 */
1444 if (fc->minor < 18)
1445 return -ENOTTY;
1446
1447 return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR);
1448}
1449
1450static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd,
1451 unsigned long arg)
1452{
1453 struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1454
1455 if (fc->minor < 18)
1456 return -ENOTTY;
1457
1458 return fuse_ioctl_common(file, cmd, arg,
1459 FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR);
1460}
1461
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001462static bool update_mtime(unsigned ivalid)
1463{
1464 /* Always update if mtime is explicitly set */
1465 if (ivalid & ATTR_MTIME_SET)
1466 return true;
1467
1468 /* If it's an open(O_TRUNC) or an ftruncate(), don't update */
1469 if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
1470 return false;
1471
1472 /* In all other cases update */
1473 return true;
1474}
1475
Miklos Szeredibefc6492005-11-07 00:59:52 -08001476static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001477{
1478 unsigned ivalid = iattr->ia_valid;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001479
1480 if (ivalid & ATTR_MODE)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001481 arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001482 if (ivalid & ATTR_UID)
Eric W. Biederman499dcf22012-02-07 16:26:03 -08001483 arg->valid |= FATTR_UID, arg->uid = from_kuid(&init_user_ns, iattr->ia_uid);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001484 if (ivalid & ATTR_GID)
Eric W. Biederman499dcf22012-02-07 16:26:03 -08001485 arg->valid |= FATTR_GID, arg->gid = from_kgid(&init_user_ns, iattr->ia_gid);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001486 if (ivalid & ATTR_SIZE)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001487 arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001488 if (ivalid & ATTR_ATIME) {
1489 arg->valid |= FATTR_ATIME;
Miklos Szeredibefc6492005-11-07 00:59:52 -08001490 arg->atime = iattr->ia_atime.tv_sec;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001491 arg->atimensec = iattr->ia_atime.tv_nsec;
1492 if (!(ivalid & ATTR_ATIME_SET))
1493 arg->valid |= FATTR_ATIME_NOW;
1494 }
1495 if ((ivalid & ATTR_MTIME) && update_mtime(ivalid)) {
1496 arg->valid |= FATTR_MTIME;
Miklos Szeredibefc6492005-11-07 00:59:52 -08001497 arg->mtime = iattr->ia_mtime.tv_sec;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001498 arg->mtimensec = iattr->ia_mtime.tv_nsec;
1499 if (!(ivalid & ATTR_MTIME_SET))
1500 arg->valid |= FATTR_MTIME_NOW;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001501 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001502}
1503
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001504/*
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001505 * Prevent concurrent writepages on inode
1506 *
1507 * This is done by adding a negative bias to the inode write counter
1508 * and waiting for all pending writes to finish.
1509 */
1510void fuse_set_nowrite(struct inode *inode)
1511{
1512 struct fuse_conn *fc = get_fuse_conn(inode);
1513 struct fuse_inode *fi = get_fuse_inode(inode);
1514
1515 BUG_ON(!mutex_is_locked(&inode->i_mutex));
1516
1517 spin_lock(&fc->lock);
1518 BUG_ON(fi->writectr < 0);
1519 fi->writectr += FUSE_NOWRITE;
1520 spin_unlock(&fc->lock);
1521 wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE);
1522}
1523
1524/*
1525 * Allow writepages on inode
1526 *
1527 * Remove the bias from the writecounter and send any queued
1528 * writepages.
1529 */
1530static void __fuse_release_nowrite(struct inode *inode)
1531{
1532 struct fuse_inode *fi = get_fuse_inode(inode);
1533
1534 BUG_ON(fi->writectr != FUSE_NOWRITE);
1535 fi->writectr = 0;
1536 fuse_flush_writepages(inode);
1537}
1538
1539void fuse_release_nowrite(struct inode *inode)
1540{
1541 struct fuse_conn *fc = get_fuse_conn(inode);
1542
1543 spin_lock(&fc->lock);
1544 __fuse_release_nowrite(inode);
1545 spin_unlock(&fc->lock);
1546}
1547
1548/*
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001549 * Set attributes, and at the same time refresh them.
1550 *
1551 * Truncation is slightly complicated, because the 'truncate' request
1552 * may fail, in which case we don't want to touch the mapping.
Miklos Szeredi9ffbb912006-10-17 00:10:06 -07001553 * vmtruncate() doesn't allow for this case, so do the rlimit checking
1554 * and the actual truncation by hand.
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001555 */
Miklos Szeredi49d49142007-10-18 03:07:00 -07001556static int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
1557 struct file *file)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001558{
1559 struct inode *inode = entry->d_inode;
1560 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001561 struct fuse_req *req;
1562 struct fuse_setattr_in inarg;
1563 struct fuse_attr_out outarg;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001564 bool is_truncate = false;
1565 loff_t oldsize;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001566 int err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001567
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001568 if (!fuse_allow_current_process(fc))
Miklos Szeredie57ac682007-10-18 03:06:58 -07001569 return -EACCES;
1570
Christoph Hellwigdb78b872010-06-04 11:30:03 +02001571 if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS))
1572 attr->ia_valid |= ATTR_FORCE;
1573
1574 err = inode_change_ok(inode, attr);
1575 if (err)
1576 return err;
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001577
Miklos Szeredi8d56add2011-02-25 14:44:58 +01001578 if (attr->ia_valid & ATTR_OPEN) {
1579 if (fc->atomic_o_trunc)
1580 return 0;
1581 file = NULL;
1582 }
Miklos Szeredi6ff958e2007-10-18 03:07:02 -07001583
Christoph Hellwig2c27c652010-06-04 11:30:04 +02001584 if (attr->ia_valid & ATTR_SIZE)
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001585 is_truncate = true;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001586
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001587 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001588 if (IS_ERR(req))
1589 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001590
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001591 if (is_truncate)
1592 fuse_set_nowrite(inode);
1593
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001594 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -07001595 memset(&outarg, 0, sizeof(outarg));
Miklos Szeredibefc6492005-11-07 00:59:52 -08001596 iattr_to_fattr(attr, &inarg);
Miklos Szeredi49d49142007-10-18 03:07:00 -07001597 if (file) {
1598 struct fuse_file *ff = file->private_data;
1599 inarg.valid |= FATTR_FH;
1600 inarg.fh = ff->fh;
1601 }
Miklos Szeredif3332112007-10-18 03:07:04 -07001602 if (attr->ia_valid & ATTR_SIZE) {
1603 /* For mandatory locking in truncate */
1604 inarg.valid |= FATTR_LOCKOWNER;
1605 inarg.lock_owner = fuse_lock_owner_id(fc, current->files);
1606 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001607 req->in.h.opcode = FUSE_SETATTR;
1608 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001609 req->in.numargs = 1;
1610 req->in.args[0].size = sizeof(inarg);
1611 req->in.args[0].value = &inarg;
1612 req->out.numargs = 1;
Miklos Szeredi0e9663e2007-10-18 03:07:05 -07001613 if (fc->minor < 9)
1614 req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
1615 else
1616 req->out.args[0].size = sizeof(outarg);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001617 req->out.args[0].value = &outarg;
Tejun Heob93f8582008-11-26 12:03:55 +01001618 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001619 err = req->out.h.error;
1620 fuse_put_request(fc, req);
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001621 if (err) {
1622 if (err == -EINTR)
1623 fuse_invalidate_attr(inode);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001624 goto error;
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001625 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001626
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001627 if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
1628 make_bad_inode(inode);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001629 err = -EIO;
1630 goto error;
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001631 }
1632
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001633 spin_lock(&fc->lock);
1634 fuse_change_attributes_common(inode, &outarg.attr,
1635 attr_timeout(&outarg));
1636 oldsize = inode->i_size;
1637 i_size_write(inode, outarg.attr.size);
1638
1639 if (is_truncate) {
1640 /* NOTE: this may release/reacquire fc->lock */
1641 __fuse_release_nowrite(inode);
1642 }
1643 spin_unlock(&fc->lock);
1644
1645 /*
1646 * Only call invalidate_inode_pages2() after removing
1647 * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock.
1648 */
1649 if (S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
npiggin@suse.dec08d3b02009-08-21 02:35:06 +10001650 truncate_pagecache(inode, oldsize, outarg.attr.size);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001651 invalidate_inode_pages2(inode->i_mapping);
1652 }
1653
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001654 return 0;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001655
1656error:
1657 if (is_truncate)
1658 fuse_release_nowrite(inode);
1659
1660 return err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001661}
1662
Miklos Szeredi49d49142007-10-18 03:07:00 -07001663static int fuse_setattr(struct dentry *entry, struct iattr *attr)
1664{
1665 if (attr->ia_valid & ATTR_FILE)
1666 return fuse_do_setattr(entry, attr, attr->ia_file);
1667 else
1668 return fuse_do_setattr(entry, attr, NULL);
1669}
1670
Miklos Szeredie5e55582005-09-09 13:10:28 -07001671static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
1672 struct kstat *stat)
1673{
1674 struct inode *inode = entry->d_inode;
Miklos Szeredi244f6382007-10-16 23:31:02 -07001675 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi244f6382007-10-16 23:31:02 -07001676
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001677 if (!fuse_allow_current_process(fc))
Miklos Szeredi244f6382007-10-16 23:31:02 -07001678 return -EACCES;
1679
Miklos Szeredibcb4be82007-11-28 16:21:59 -08001680 return fuse_update_attributes(inode, stat, NULL, NULL);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001681}
1682
Miklos Szeredi92a87802005-09-09 13:10:31 -07001683static int fuse_setxattr(struct dentry *entry, const char *name,
1684 const void *value, size_t size, int flags)
1685{
1686 struct inode *inode = entry->d_inode;
1687 struct fuse_conn *fc = get_fuse_conn(inode);
1688 struct fuse_req *req;
1689 struct fuse_setxattr_in inarg;
1690 int err;
1691
Miklos Szeredi92a87802005-09-09 13:10:31 -07001692 if (fc->no_setxattr)
1693 return -EOPNOTSUPP;
1694
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001695 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001696 if (IS_ERR(req))
1697 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001698
1699 memset(&inarg, 0, sizeof(inarg));
1700 inarg.size = size;
1701 inarg.flags = flags;
1702 req->in.h.opcode = FUSE_SETXATTR;
1703 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001704 req->in.numargs = 3;
1705 req->in.args[0].size = sizeof(inarg);
1706 req->in.args[0].value = &inarg;
1707 req->in.args[1].size = strlen(name) + 1;
1708 req->in.args[1].value = name;
1709 req->in.args[2].size = size;
1710 req->in.args[2].value = value;
Tejun Heob93f8582008-11-26 12:03:55 +01001711 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001712 err = req->out.h.error;
1713 fuse_put_request(fc, req);
1714 if (err == -ENOSYS) {
1715 fc->no_setxattr = 1;
1716 err = -EOPNOTSUPP;
1717 }
1718 return err;
1719}
1720
1721static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
1722 void *value, size_t size)
1723{
1724 struct inode *inode = entry->d_inode;
1725 struct fuse_conn *fc = get_fuse_conn(inode);
1726 struct fuse_req *req;
1727 struct fuse_getxattr_in inarg;
1728 struct fuse_getxattr_out outarg;
1729 ssize_t ret;
1730
1731 if (fc->no_getxattr)
1732 return -EOPNOTSUPP;
1733
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001734 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001735 if (IS_ERR(req))
1736 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001737
1738 memset(&inarg, 0, sizeof(inarg));
1739 inarg.size = size;
1740 req->in.h.opcode = FUSE_GETXATTR;
1741 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001742 req->in.numargs = 2;
1743 req->in.args[0].size = sizeof(inarg);
1744 req->in.args[0].value = &inarg;
1745 req->in.args[1].size = strlen(name) + 1;
1746 req->in.args[1].value = name;
1747 /* This is really two different operations rolled into one */
1748 req->out.numargs = 1;
1749 if (size) {
1750 req->out.argvar = 1;
1751 req->out.args[0].size = size;
1752 req->out.args[0].value = value;
1753 } else {
1754 req->out.args[0].size = sizeof(outarg);
1755 req->out.args[0].value = &outarg;
1756 }
Tejun Heob93f8582008-11-26 12:03:55 +01001757 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001758 ret = req->out.h.error;
1759 if (!ret)
1760 ret = size ? req->out.args[0].size : outarg.size;
1761 else {
1762 if (ret == -ENOSYS) {
1763 fc->no_getxattr = 1;
1764 ret = -EOPNOTSUPP;
1765 }
1766 }
1767 fuse_put_request(fc, req);
1768 return ret;
1769}
1770
1771static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
1772{
1773 struct inode *inode = entry->d_inode;
1774 struct fuse_conn *fc = get_fuse_conn(inode);
1775 struct fuse_req *req;
1776 struct fuse_getxattr_in inarg;
1777 struct fuse_getxattr_out outarg;
1778 ssize_t ret;
1779
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001780 if (!fuse_allow_current_process(fc))
Miklos Szeredie57ac682007-10-18 03:06:58 -07001781 return -EACCES;
1782
Miklos Szeredi92a87802005-09-09 13:10:31 -07001783 if (fc->no_listxattr)
1784 return -EOPNOTSUPP;
1785
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001786 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001787 if (IS_ERR(req))
1788 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001789
1790 memset(&inarg, 0, sizeof(inarg));
1791 inarg.size = size;
1792 req->in.h.opcode = FUSE_LISTXATTR;
1793 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001794 req->in.numargs = 1;
1795 req->in.args[0].size = sizeof(inarg);
1796 req->in.args[0].value = &inarg;
1797 /* This is really two different operations rolled into one */
1798 req->out.numargs = 1;
1799 if (size) {
1800 req->out.argvar = 1;
1801 req->out.args[0].size = size;
1802 req->out.args[0].value = list;
1803 } else {
1804 req->out.args[0].size = sizeof(outarg);
1805 req->out.args[0].value = &outarg;
1806 }
Tejun Heob93f8582008-11-26 12:03:55 +01001807 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001808 ret = req->out.h.error;
1809 if (!ret)
1810 ret = size ? req->out.args[0].size : outarg.size;
1811 else {
1812 if (ret == -ENOSYS) {
1813 fc->no_listxattr = 1;
1814 ret = -EOPNOTSUPP;
1815 }
1816 }
1817 fuse_put_request(fc, req);
1818 return ret;
1819}
1820
1821static int fuse_removexattr(struct dentry *entry, const char *name)
1822{
1823 struct inode *inode = entry->d_inode;
1824 struct fuse_conn *fc = get_fuse_conn(inode);
1825 struct fuse_req *req;
1826 int err;
1827
1828 if (fc->no_removexattr)
1829 return -EOPNOTSUPP;
1830
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001831 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001832 if (IS_ERR(req))
1833 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001834
1835 req->in.h.opcode = FUSE_REMOVEXATTR;
1836 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001837 req->in.numargs = 1;
1838 req->in.args[0].size = strlen(name) + 1;
1839 req->in.args[0].value = name;
Tejun Heob93f8582008-11-26 12:03:55 +01001840 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001841 err = req->out.h.error;
1842 fuse_put_request(fc, req);
1843 if (err == -ENOSYS) {
1844 fc->no_removexattr = 1;
1845 err = -EOPNOTSUPP;
1846 }
1847 return err;
1848}
1849
Arjan van de Ven754661f2007-02-12 00:55:38 -08001850static const struct inode_operations fuse_dir_inode_operations = {
Miklos Szeredie5e55582005-09-09 13:10:28 -07001851 .lookup = fuse_lookup,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001852 .mkdir = fuse_mkdir,
1853 .symlink = fuse_symlink,
1854 .unlink = fuse_unlink,
1855 .rmdir = fuse_rmdir,
1856 .rename = fuse_rename,
1857 .link = fuse_link,
1858 .setattr = fuse_setattr,
1859 .create = fuse_create,
Miklos Szeredic8ccbe02012-06-05 15:10:22 +02001860 .atomic_open = fuse_atomic_open,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001861 .mknod = fuse_mknod,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001862 .permission = fuse_permission,
1863 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001864 .setxattr = fuse_setxattr,
1865 .getxattr = fuse_getxattr,
1866 .listxattr = fuse_listxattr,
1867 .removexattr = fuse_removexattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001868};
1869
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -08001870static const struct file_operations fuse_dir_operations = {
Miklos Szeredib6aeade2005-09-09 13:10:30 -07001871 .llseek = generic_file_llseek,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001872 .read = generic_read_dir,
1873 .readdir = fuse_readdir,
1874 .open = fuse_dir_open,
1875 .release = fuse_dir_release,
Miklos Szeredi82547982005-09-09 13:10:38 -07001876 .fsync = fuse_dir_fsync,
Miklos Szeredib18da0c2011-12-13 11:58:49 +01001877 .unlocked_ioctl = fuse_dir_ioctl,
1878 .compat_ioctl = fuse_dir_compat_ioctl,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001879};
1880
Arjan van de Ven754661f2007-02-12 00:55:38 -08001881static const struct inode_operations fuse_common_inode_operations = {
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001882 .setattr = fuse_setattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001883 .permission = fuse_permission,
1884 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001885 .setxattr = fuse_setxattr,
1886 .getxattr = fuse_getxattr,
1887 .listxattr = fuse_listxattr,
1888 .removexattr = fuse_removexattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001889};
1890
Arjan van de Ven754661f2007-02-12 00:55:38 -08001891static const struct inode_operations fuse_symlink_inode_operations = {
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001892 .setattr = fuse_setattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001893 .follow_link = fuse_follow_link,
1894 .put_link = fuse_put_link,
1895 .readlink = generic_readlink,
1896 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001897 .setxattr = fuse_setxattr,
1898 .getxattr = fuse_getxattr,
1899 .listxattr = fuse_listxattr,
1900 .removexattr = fuse_removexattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001901};
1902
1903void fuse_init_common(struct inode *inode)
1904{
1905 inode->i_op = &fuse_common_inode_operations;
1906}
1907
1908void fuse_init_dir(struct inode *inode)
1909{
1910 inode->i_op = &fuse_dir_inode_operations;
1911 inode->i_fop = &fuse_dir_operations;
1912}
1913
1914void fuse_init_symlink(struct inode *inode)
1915{
1916 inode->i_op = &fuse_symlink_inode_operations;
1917}