blob: 25c6cfe988010cae09a7832545a0441ba5ea92c8 [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
Al Viro8d3af7f2013-05-18 03:03:58 -040017static bool fuse_use_readdirplus(struct inode *dir, struct dir_context *ctx)
Feng Shuo4582a4a2013-01-15 11:23:28 +080018{
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;
Eric Wong634734b2013-02-06 22:29:01 +000024 if (!fc->readdirplus_auto)
25 return true;
Feng Shuo4582a4a2013-01-15 11:23:28 +080026 if (test_and_clear_bit(FUSE_I_ADVISE_RDPLUS, &fi->state))
27 return true;
Al Viro8d3af7f2013-05-18 03:03:58 -040028 if (ctx->pos == 0)
Feng Shuo4582a4a2013-01-15 11:23:28 +080029 return true;
30 return false;
31}
32
33static void fuse_advise_use_readdirplus(struct inode *dir)
34{
35 struct fuse_inode *fi = get_fuse_inode(dir);
36
37 set_bit(FUSE_I_ADVISE_RDPLUS, &fi->state);
38}
39
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070040#if BITS_PER_LONG >= 64
41static inline void fuse_dentry_settime(struct dentry *entry, u64 time)
42{
43 entry->d_time = time;
44}
45
46static inline u64 fuse_dentry_time(struct dentry *entry)
47{
48 return entry->d_time;
49}
50#else
51/*
52 * On 32 bit archs store the high 32 bits of time in d_fsdata
53 */
54static void fuse_dentry_settime(struct dentry *entry, u64 time)
55{
56 entry->d_time = time;
57 entry->d_fsdata = (void *) (unsigned long) (time >> 32);
58}
59
60static u64 fuse_dentry_time(struct dentry *entry)
61{
62 return (u64) entry->d_time +
63 ((u64) (unsigned long) entry->d_fsdata << 32);
64}
65#endif
66
Miklos Szeredi6f9f1182006-01-06 00:19:39 -080067/*
68 * FUSE caches dentries and attributes with separate timeout. The
69 * time in jiffies until the dentry/attributes are valid is stored in
70 * dentry->d_time and fuse_inode->i_time respectively.
71 */
72
73/*
74 * Calculate the time in jiffies until a dentry/attributes are valid
75 */
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070076static u64 time_to_jiffies(unsigned long sec, unsigned long nsec)
Miklos Szeredie5e55582005-09-09 13:10:28 -070077{
Miklos Szeredi685d16d2006-07-30 03:04:08 -070078 if (sec || nsec) {
79 struct timespec ts = {sec, nsec};
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070080 return get_jiffies_64() + timespec_to_jiffies(&ts);
Miklos Szeredi685d16d2006-07-30 03:04:08 -070081 } else
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070082 return 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -070083}
84
Miklos Szeredi6f9f1182006-01-06 00:19:39 -080085/*
86 * Set dentry and possibly attribute timeouts from the lookup/mk*
87 * replies
88 */
Miklos Szeredi1fb69e72007-10-18 03:06:58 -070089static void fuse_change_entry_timeout(struct dentry *entry,
90 struct fuse_entry_out *o)
Miklos Szeredi0aa7c692006-01-06 00:19:34 -080091{
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070092 fuse_dentry_settime(entry,
93 time_to_jiffies(o->entry_valid, o->entry_valid_nsec));
Miklos Szeredi1fb69e72007-10-18 03:06:58 -070094}
95
96static u64 attr_timeout(struct fuse_attr_out *o)
97{
98 return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
99}
100
101static u64 entry_attr_timeout(struct fuse_entry_out *o)
102{
103 return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800104}
105
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800106/*
107 * Mark the attributes as stale, so that at the next call to
108 * ->getattr() they will be fetched from userspace
109 */
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800110void fuse_invalidate_attr(struct inode *inode)
111{
Miklos Szeredi0a0898c2006-07-30 03:04:10 -0700112 get_fuse_inode(inode)->i_time = 0;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800113}
114
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800115/*
116 * Just mark the entry as stale, so that a next attempt to look it up
117 * will result in a new lookup call to userspace
118 *
119 * This is called when a dentry is about to become negative and the
120 * timeout is unknown (unlink, rmdir, rename and in some cases
121 * lookup)
122 */
Miklos Szeredidbd561d2008-07-25 01:49:00 -0700123void fuse_invalidate_entry_cache(struct dentry *entry)
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800124{
Miklos Szeredi0a0898c2006-07-30 03:04:10 -0700125 fuse_dentry_settime(entry, 0);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800126}
127
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800128/*
129 * Same as fuse_invalidate_entry_cache(), but also try to remove the
130 * dentry from the hash
131 */
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800132static void fuse_invalidate_entry(struct dentry *entry)
133{
134 d_invalidate(entry);
135 fuse_invalidate_entry_cache(entry);
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800136}
137
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700138static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_req *req,
139 u64 nodeid, struct qstr *name,
Miklos Szeredie5e55582005-09-09 13:10:28 -0700140 struct fuse_entry_out *outarg)
141{
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700142 memset(outarg, 0, sizeof(struct fuse_entry_out));
Miklos Szeredie5e55582005-09-09 13:10:28 -0700143 req->in.h.opcode = FUSE_LOOKUP;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700144 req->in.h.nodeid = nodeid;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700145 req->in.numargs = 1;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700146 req->in.args[0].size = name->len + 1;
147 req->in.args[0].value = name->name;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700148 req->out.numargs = 1;
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700149 if (fc->minor < 9)
150 req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
151 else
152 req->out.args[0].size = sizeof(struct fuse_entry_out);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700153 req->out.args[0].value = outarg;
154}
155
Miklos Szeredi5c5c5e52008-04-30 00:54:43 -0700156u64 fuse_get_attr_version(struct fuse_conn *fc)
Miklos Szeredi7dca9fd2007-11-28 16:21:59 -0800157{
158 u64 curr_version;
159
160 /*
161 * The spin lock isn't actually needed on 64bit archs, but we
162 * don't yet care too much about such optimizations.
163 */
164 spin_lock(&fc->lock);
165 curr_version = fc->attr_version;
166 spin_unlock(&fc->lock);
167
168 return curr_version;
169}
170
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800171/*
172 * Check whether the dentry is still valid
173 *
174 * If the entry validity timeout has expired and the dentry is
175 * positive, try to redo the lookup. If the lookup results in a
176 * different inode, then let the VFS invalidate the dentry and redo
177 * the lookup once more. If the lookup results in the same inode,
178 * then refresh the attributes, timeouts and mark the dentry valid.
179 */
Al Viro0b728e12012-06-10 16:03:43 -0400180static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700181{
Nick Piggin34286d62011-01-07 17:49:57 +1100182 struct inode *inode;
Miklos Szeredi28420da2013-06-03 14:40:22 +0200183 struct dentry *parent;
184 struct fuse_conn *fc;
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200185 int ret;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800186
Miklos Szeredie7c0a162011-03-21 13:58:06 +0100187 inode = ACCESS_ONCE(entry->d_inode);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800188 if (inode && is_bad_inode(inode))
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200189 goto invalid;
Miklos Szeredi0a0898c2006-07-30 03:04:10 -0700190 else if (fuse_dentry_time(entry) < get_jiffies_64()) {
Miklos Szeredie5e55582005-09-09 13:10:28 -0700191 int err;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700192 struct fuse_entry_out outarg;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800193 struct fuse_req *req;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100194 struct fuse_forget_link *forget;
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700195 u64 attr_version;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800196
Miklos Szeredi50322fe2006-02-28 16:59:03 -0800197 /* For negative dentries, always do a fresh lookup */
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800198 if (!inode)
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200199 goto invalid;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800200
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200201 ret = -ECHILD;
Al Viro0b728e12012-06-10 16:03:43 -0400202 if (flags & LOOKUP_RCU)
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200203 goto out;
Miklos Szeredie7c0a162011-03-21 13:58:06 +0100204
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800205 fc = get_fuse_conn(inode);
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400206 req = fuse_get_req_nopages(fc);
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200207 ret = PTR_ERR(req);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700208 if (IS_ERR(req))
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200209 goto out;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700210
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100211 forget = fuse_alloc_forget();
212 if (!forget) {
Miklos Szeredi2d510132006-11-25 11:09:20 -0800213 fuse_put_request(fc, req);
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200214 ret = -ENOMEM;
215 goto out;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800216 }
217
Miklos Szeredi7dca9fd2007-11-28 16:21:59 -0800218 attr_version = fuse_get_attr_version(fc);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700219
Miklos Szeredie956edd2006-10-17 00:10:12 -0700220 parent = dget_parent(entry);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700221 fuse_lookup_init(fc, req, get_node_id(parent->d_inode),
222 &entry->d_name, &outarg);
Tejun Heob93f8582008-11-26 12:03:55 +0100223 fuse_request_send(fc, req);
Miklos Szeredie956edd2006-10-17 00:10:12 -0700224 dput(parent);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700225 err = req->out.h.error;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800226 fuse_put_request(fc, req);
Miklos Szeredi50322fe2006-02-28 16:59:03 -0800227 /* Zero nodeid is same as -ENOENT */
228 if (!err && !outarg.nodeid)
229 err = -ENOENT;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700230 if (!err) {
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800231 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700232 if (outarg.nodeid != get_node_id(inode)) {
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100233 fuse_queue_forget(fc, forget, outarg.nodeid, 1);
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200234 goto invalid;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700235 }
Miklos Szeredi8da5ff22006-10-17 00:10:08 -0700236 spin_lock(&fc->lock);
Miklos Szeredi1729a162008-11-26 12:03:54 +0100237 fi->nlookup++;
Miklos Szeredi8da5ff22006-10-17 00:10:08 -0700238 spin_unlock(&fc->lock);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700239 }
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100240 kfree(forget);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700241 if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT)
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200242 goto invalid;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700243
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700244 fuse_change_attributes(inode, &outarg.attr,
245 entry_attr_timeout(&outarg),
246 attr_version);
247 fuse_change_entry_timeout(entry, &outarg);
Miklos Szeredi28420da2013-06-03 14:40:22 +0200248 } else if (inode) {
249 fc = get_fuse_conn(inode);
250 if (fc->readdirplus_auto) {
251 parent = dget_parent(entry);
252 fuse_advise_use_readdirplus(parent->d_inode);
253 dput(parent);
254 }
Miklos Szeredie5e55582005-09-09 13:10:28 -0700255 }
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200256 ret = 1;
257out:
258 return ret;
259
260invalid:
261 ret = 0;
262 goto out;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700263}
264
Miklos Szeredi8bfc0162006-01-16 22:14:28 -0800265static int invalid_nodeid(u64 nodeid)
Miklos Szeredi2827d0b22005-11-28 13:44:16 -0800266{
267 return !nodeid || nodeid == FUSE_ROOT_ID;
268}
269
Al Viro42695902009-02-20 05:59:13 +0000270const struct dentry_operations fuse_dentry_operations = {
Miklos Szeredie5e55582005-09-09 13:10:28 -0700271 .d_revalidate = fuse_dentry_revalidate,
272};
273
Timo Savolaa5bfffac2007-04-08 16:04:00 -0700274int fuse_valid_type(int m)
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800275{
276 return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) ||
277 S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m);
278}
279
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700280int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name,
281 struct fuse_entry_out *outarg, struct inode **inode)
282{
283 struct fuse_conn *fc = get_fuse_conn_super(sb);
284 struct fuse_req *req;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100285 struct fuse_forget_link *forget;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700286 u64 attr_version;
287 int err;
288
289 *inode = NULL;
290 err = -ENAMETOOLONG;
291 if (name->len > FUSE_NAME_MAX)
292 goto out;
293
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400294 req = fuse_get_req_nopages(fc);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700295 err = PTR_ERR(req);
296 if (IS_ERR(req))
297 goto out;
298
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100299 forget = fuse_alloc_forget();
300 err = -ENOMEM;
301 if (!forget) {
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700302 fuse_put_request(fc, req);
303 goto out;
304 }
305
306 attr_version = fuse_get_attr_version(fc);
307
308 fuse_lookup_init(fc, req, nodeid, name, outarg);
Tejun Heob93f8582008-11-26 12:03:55 +0100309 fuse_request_send(fc, req);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700310 err = req->out.h.error;
311 fuse_put_request(fc, req);
312 /* Zero nodeid is same as -ENOENT, but with valid timeout */
313 if (err || !outarg->nodeid)
314 goto out_put_forget;
315
316 err = -EIO;
317 if (!outarg->nodeid)
318 goto out_put_forget;
319 if (!fuse_valid_type(outarg->attr.mode))
320 goto out_put_forget;
321
322 *inode = fuse_iget(sb, outarg->nodeid, outarg->generation,
323 &outarg->attr, entry_attr_timeout(outarg),
324 attr_version);
325 err = -ENOMEM;
326 if (!*inode) {
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100327 fuse_queue_forget(fc, forget, outarg->nodeid, 1);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700328 goto out;
329 }
330 err = 0;
331
332 out_put_forget:
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100333 kfree(forget);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700334 out:
335 return err;
336}
337
Miklos Szeredi5835f332013-09-05 11:44:42 +0200338static struct dentry *fuse_materialise_dentry(struct dentry *dentry,
339 struct inode *inode)
340{
341 struct dentry *newent;
342
343 if (inode && S_ISDIR(inode->i_mode)) {
344 struct fuse_conn *fc = get_fuse_conn(inode);
345
346 mutex_lock(&fc->inst_mutex);
347 newent = d_materialise_unique(dentry, inode);
348 mutex_unlock(&fc->inst_mutex);
349 } else {
350 newent = d_materialise_unique(dentry, inode);
351 }
352
353 return newent;
354}
355
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800356static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
Al Viro00cd8dd2012-06-10 17:13:09 -0400357 unsigned int flags)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700358{
359 int err;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700360 struct fuse_entry_out outarg;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700361 struct inode *inode;
Miklos Szeredi0de62562008-07-25 01:48:59 -0700362 struct dentry *newent;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700363 bool outarg_valid = true;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700364
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700365 err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name,
366 &outarg, &inode);
367 if (err == -ENOENT) {
368 outarg_valid = false;
369 err = 0;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800370 }
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700371 if (err)
372 goto out_err;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800373
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700374 err = -EIO;
375 if (inode && get_node_id(inode) == FUSE_ROOT_ID)
376 goto out_iput;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700377
Miklos Szeredi5835f332013-09-05 11:44:42 +0200378 newent = fuse_materialise_dentry(entry, inode);
379 err = PTR_ERR(newent);
380 if (IS_ERR(newent))
381 goto out_err;
Miklos Szeredid2a85162006-10-17 00:10:11 -0700382
Miklos Szeredi0de62562008-07-25 01:48:59 -0700383 entry = newent ? newent : entry;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700384 if (outarg_valid)
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700385 fuse_change_entry_timeout(entry, &outarg);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800386 else
387 fuse_invalidate_entry_cache(entry);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700388
Feng Shuo4582a4a2013-01-15 11:23:28 +0800389 fuse_advise_use_readdirplus(dir);
Miklos Szeredi0de62562008-07-25 01:48:59 -0700390 return newent;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700391
392 out_iput:
393 iput(inode);
394 out_err:
395 return ERR_PTR(err);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700396}
397
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800398/*
399 * Atomic create+open operation
400 *
401 * If the filesystem doesn't support this, then fall back to separate
402 * 'mknod' + 'open' requests.
403 */
Al Virod9585272012-06-22 12:39:14 +0400404static int fuse_create_open(struct inode *dir, struct dentry *entry,
Al Viro30d90492012-06-22 12:40:19 +0400405 struct file *file, unsigned flags,
Al Virod9585272012-06-22 12:39:14 +0400406 umode_t mode, int *opened)
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800407{
408 int err;
409 struct inode *inode;
410 struct fuse_conn *fc = get_fuse_conn(dir);
411 struct fuse_req *req;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100412 struct fuse_forget_link *forget;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200413 struct fuse_create_in inarg;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800414 struct fuse_open_out outopen;
415 struct fuse_entry_out outentry;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800416 struct fuse_file *ff;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800417
Miklos Szerediaf109bc2012-08-15 13:01:24 +0200418 /* Userspace expects S_IFREG in create mode */
419 BUG_ON((mode & S_IFMT) != S_IFREG);
420
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100421 forget = fuse_alloc_forget();
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200422 err = -ENOMEM;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100423 if (!forget)
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200424 goto out_err;
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700425
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400426 req = fuse_get_req_nopages(fc);
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700427 err = PTR_ERR(req);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700428 if (IS_ERR(req))
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700429 goto out_put_forget_req;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800430
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700431 err = -ENOMEM;
Tejun Heoacf99432008-11-26 12:03:55 +0100432 ff = fuse_file_alloc(fc);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800433 if (!ff)
434 goto out_put_request;
435
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200436 if (!fc->dont_mask)
437 mode &= ~current_umask();
438
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800439 flags &= ~O_NOCTTY;
440 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700441 memset(&outentry, 0, sizeof(outentry));
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800442 inarg.flags = flags;
443 inarg.mode = mode;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200444 inarg.umask = current_umask();
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800445 req->in.h.opcode = FUSE_CREATE;
446 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800447 req->in.numargs = 2;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200448 req->in.args[0].size = fc->minor < 12 ? sizeof(struct fuse_open_in) :
449 sizeof(inarg);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800450 req->in.args[0].value = &inarg;
451 req->in.args[1].size = entry->d_name.len + 1;
452 req->in.args[1].value = entry->d_name.name;
453 req->out.numargs = 2;
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700454 if (fc->minor < 9)
455 req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
456 else
457 req->out.args[0].size = sizeof(outentry);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800458 req->out.args[0].value = &outentry;
459 req->out.args[1].size = sizeof(outopen);
460 req->out.args[1].value = &outopen;
Tejun Heob93f8582008-11-26 12:03:55 +0100461 fuse_request_send(fc, req);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800462 err = req->out.h.error;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200463 if (err)
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800464 goto out_free_ff;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800465
466 err = -EIO;
Miklos Szeredi2827d0b22005-11-28 13:44:16 -0800467 if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid))
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800468 goto out_free_ff;
469
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700470 fuse_put_request(fc, req);
Miklos Szeredic7b71432009-04-28 16:56:37 +0200471 ff->fh = outopen.fh;
472 ff->nodeid = outentry.nodeid;
473 ff->open_flags = outopen.open_flags;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800474 inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700475 &outentry.attr, entry_attr_timeout(&outentry), 0);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800476 if (!inode) {
477 flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
Miklos Szeredi8b0797a2009-04-28 16:56:39 +0200478 fuse_sync_release(ff, flags);
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100479 fuse_queue_forget(fc, forget, outentry.nodeid, 1);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200480 err = -ENOMEM;
481 goto out_err;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800482 }
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100483 kfree(forget);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800484 d_instantiate(entry, inode);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700485 fuse_change_entry_timeout(entry, &outentry);
Miklos Szeredi0952b2a2008-02-06 01:38:38 -0800486 fuse_invalidate_attr(dir);
Al Viro30d90492012-06-22 12:40:19 +0400487 err = finish_open(file, entry, generic_file_open, opened);
488 if (err) {
Miklos Szeredi8b0797a2009-04-28 16:56:39 +0200489 fuse_sync_release(ff, flags);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200490 } else {
491 file->private_data = fuse_file_get(ff);
492 fuse_finish_open(inode, file);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800493 }
Al Virod9585272012-06-22 12:39:14 +0400494 return err;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800495
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200496out_free_ff:
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800497 fuse_file_free(ff);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200498out_put_request:
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800499 fuse_put_request(fc, req);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200500out_put_forget_req:
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100501 kfree(forget);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200502out_err:
Al Virod9585272012-06-22 12:39:14 +0400503 return err;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200504}
505
506static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t);
Al Virod9585272012-06-22 12:39:14 +0400507static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
Al Viro30d90492012-06-22 12:40:19 +0400508 struct file *file, unsigned flags,
Al Virod9585272012-06-22 12:39:14 +0400509 umode_t mode, int *opened)
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200510{
511 int err;
512 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200513 struct dentry *res = NULL;
514
515 if (d_unhashed(entry)) {
Al Viro00cd8dd2012-06-10 17:13:09 -0400516 res = fuse_lookup(dir, entry, 0);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200517 if (IS_ERR(res))
Al Virod9585272012-06-22 12:39:14 +0400518 return PTR_ERR(res);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200519
520 if (res)
521 entry = res;
522 }
523
524 if (!(flags & O_CREAT) || entry->d_inode)
525 goto no_open;
526
527 /* Only creates */
Al Viro47237682012-06-10 05:01:45 -0400528 *opened |= FILE_CREATED;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200529
530 if (fc->no_create)
531 goto mknod;
532
Al Viro30d90492012-06-22 12:40:19 +0400533 err = fuse_create_open(dir, entry, file, flags, mode, opened);
Al Virod9585272012-06-22 12:39:14 +0400534 if (err == -ENOSYS) {
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200535 fc->no_create = 1;
536 goto mknod;
537 }
538out_dput:
539 dput(res);
Al Virod9585272012-06-22 12:39:14 +0400540 return err;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200541
542mknod:
543 err = fuse_mknod(dir, entry, mode, 0);
Al Virod9585272012-06-22 12:39:14 +0400544 if (err)
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200545 goto out_dput;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200546no_open:
Al Viroe45198a2012-06-10 06:48:09 -0400547 return finish_no_open(file, res);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800548}
549
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800550/*
551 * Code shared between mknod, mkdir, symlink and link
552 */
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700553static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
554 struct inode *dir, struct dentry *entry,
Al Viro541af6a2011-07-26 03:17:33 -0400555 umode_t mode)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700556{
557 struct fuse_entry_out outarg;
558 struct inode *inode;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700559 int err;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100560 struct fuse_forget_link *forget;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800561
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100562 forget = fuse_alloc_forget();
563 if (!forget) {
Miklos Szeredi2d510132006-11-25 11:09:20 -0800564 fuse_put_request(fc, req);
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100565 return -ENOMEM;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800566 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700567
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700568 memset(&outarg, 0, sizeof(outarg));
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700569 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700570 req->out.numargs = 1;
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700571 if (fc->minor < 9)
572 req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
573 else
574 req->out.args[0].size = sizeof(outarg);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700575 req->out.args[0].value = &outarg;
Tejun Heob93f8582008-11-26 12:03:55 +0100576 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700577 err = req->out.h.error;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800578 fuse_put_request(fc, req);
579 if (err)
580 goto out_put_forget_req;
581
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800582 err = -EIO;
583 if (invalid_nodeid(outarg.nodeid))
Miklos Szeredi2d510132006-11-25 11:09:20 -0800584 goto out_put_forget_req;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800585
586 if ((outarg.attr.mode ^ mode) & S_IFMT)
Miklos Szeredi2d510132006-11-25 11:09:20 -0800587 goto out_put_forget_req;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800588
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700589 inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700590 &outarg.attr, entry_attr_timeout(&outarg), 0);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700591 if (!inode) {
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100592 fuse_queue_forget(fc, forget, outarg.nodeid, 1);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700593 return -ENOMEM;
594 }
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100595 kfree(forget);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700596
Miklos Szeredid2a85162006-10-17 00:10:11 -0700597 if (S_ISDIR(inode->i_mode)) {
598 struct dentry *alias;
599 mutex_lock(&fc->inst_mutex);
600 alias = d_find_alias(inode);
601 if (alias) {
602 /* New directory must have moved since mkdir */
603 mutex_unlock(&fc->inst_mutex);
604 dput(alias);
605 iput(inode);
606 return -EBUSY;
607 }
608 d_instantiate(entry, inode);
609 mutex_unlock(&fc->inst_mutex);
610 } else
611 d_instantiate(entry, inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700612
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700613 fuse_change_entry_timeout(entry, &outarg);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700614 fuse_invalidate_attr(dir);
615 return 0;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800616
Miklos Szeredi2d510132006-11-25 11:09:20 -0800617 out_put_forget_req:
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100618 kfree(forget);
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800619 return err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700620}
621
Al Viro1a67aaf2011-07-26 01:52:52 -0400622static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700623 dev_t rdev)
624{
625 struct fuse_mknod_in inarg;
626 struct fuse_conn *fc = get_fuse_conn(dir);
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400627 struct fuse_req *req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700628 if (IS_ERR(req))
629 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700630
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200631 if (!fc->dont_mask)
632 mode &= ~current_umask();
633
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700634 memset(&inarg, 0, sizeof(inarg));
635 inarg.mode = mode;
636 inarg.rdev = new_encode_dev(rdev);
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200637 inarg.umask = current_umask();
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700638 req->in.h.opcode = FUSE_MKNOD;
639 req->in.numargs = 2;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200640 req->in.args[0].size = fc->minor < 12 ? FUSE_COMPAT_MKNOD_IN_SIZE :
641 sizeof(inarg);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700642 req->in.args[0].value = &inarg;
643 req->in.args[1].size = entry->d_name.len + 1;
644 req->in.args[1].value = entry->d_name.name;
645 return create_new_entry(fc, req, dir, entry, mode);
646}
647
Al Viro4acdaf22011-07-26 01:42:34 -0400648static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode,
Al Viroebfc3b42012-06-10 18:05:36 -0400649 bool excl)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700650{
651 return fuse_mknod(dir, entry, mode, 0);
652}
653
Al Viro18bb1db2011-07-26 01:41:39 -0400654static int fuse_mkdir(struct inode *dir, struct dentry *entry, umode_t mode)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700655{
656 struct fuse_mkdir_in inarg;
657 struct fuse_conn *fc = get_fuse_conn(dir);
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400658 struct fuse_req *req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700659 if (IS_ERR(req))
660 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700661
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200662 if (!fc->dont_mask)
663 mode &= ~current_umask();
664
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700665 memset(&inarg, 0, sizeof(inarg));
666 inarg.mode = mode;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200667 inarg.umask = current_umask();
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700668 req->in.h.opcode = FUSE_MKDIR;
669 req->in.numargs = 2;
670 req->in.args[0].size = sizeof(inarg);
671 req->in.args[0].value = &inarg;
672 req->in.args[1].size = entry->d_name.len + 1;
673 req->in.args[1].value = entry->d_name.name;
674 return create_new_entry(fc, req, dir, entry, S_IFDIR);
675}
676
677static int fuse_symlink(struct inode *dir, struct dentry *entry,
678 const char *link)
679{
680 struct fuse_conn *fc = get_fuse_conn(dir);
681 unsigned len = strlen(link) + 1;
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400682 struct fuse_req *req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700683 if (IS_ERR(req))
684 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700685
686 req->in.h.opcode = FUSE_SYMLINK;
687 req->in.numargs = 2;
688 req->in.args[0].size = entry->d_name.len + 1;
689 req->in.args[0].value = entry->d_name.name;
690 req->in.args[1].size = len;
691 req->in.args[1].value = link;
692 return create_new_entry(fc, req, dir, entry, S_IFLNK);
693}
694
695static int fuse_unlink(struct inode *dir, struct dentry *entry)
696{
697 int err;
698 struct fuse_conn *fc = get_fuse_conn(dir);
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400699 struct fuse_req *req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700700 if (IS_ERR(req))
701 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700702
703 req->in.h.opcode = FUSE_UNLINK;
704 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700705 req->in.numargs = 1;
706 req->in.args[0].size = entry->d_name.len + 1;
707 req->in.args[0].value = entry->d_name.name;
Tejun Heob93f8582008-11-26 12:03:55 +0100708 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700709 err = req->out.h.error;
710 fuse_put_request(fc, req);
711 if (!err) {
712 struct inode *inode = entry->d_inode;
Miklos Szerediac45d612012-03-05 15:48:11 +0100713 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700714
Miklos Szerediac45d612012-03-05 15:48:11 +0100715 spin_lock(&fc->lock);
716 fi->attr_version = ++fc->attr_version;
Miklos Szeredidfca7ce2013-02-04 15:57:42 +0100717 /*
718 * If i_nlink == 0 then unlink doesn't make sense, yet this can
719 * happen if userspace filesystem is careless. It would be
720 * difficult to enforce correct nlink usage so just ignore this
721 * condition here
722 */
723 if (inode->i_nlink > 0)
724 drop_nlink(inode);
Miklos Szerediac45d612012-03-05 15:48:11 +0100725 spin_unlock(&fc->lock);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700726 fuse_invalidate_attr(inode);
727 fuse_invalidate_attr(dir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800728 fuse_invalidate_entry_cache(entry);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700729 } else if (err == -EINTR)
730 fuse_invalidate_entry(entry);
731 return err;
732}
733
734static int fuse_rmdir(struct inode *dir, struct dentry *entry)
735{
736 int err;
737 struct fuse_conn *fc = get_fuse_conn(dir);
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400738 struct fuse_req *req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700739 if (IS_ERR(req))
740 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700741
742 req->in.h.opcode = FUSE_RMDIR;
743 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700744 req->in.numargs = 1;
745 req->in.args[0].size = entry->d_name.len + 1;
746 req->in.args[0].value = entry->d_name.name;
Tejun Heob93f8582008-11-26 12:03:55 +0100747 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700748 err = req->out.h.error;
749 fuse_put_request(fc, req);
750 if (!err) {
Dave Hansence71ec32006-09-30 23:29:06 -0700751 clear_nlink(entry->d_inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700752 fuse_invalidate_attr(dir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800753 fuse_invalidate_entry_cache(entry);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700754 } else if (err == -EINTR)
755 fuse_invalidate_entry(entry);
756 return err;
757}
758
759static int fuse_rename(struct inode *olddir, struct dentry *oldent,
760 struct inode *newdir, struct dentry *newent)
761{
762 int err;
763 struct fuse_rename_in inarg;
764 struct fuse_conn *fc = get_fuse_conn(olddir);
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400765 struct fuse_req *req = fuse_get_req_nopages(fc);
Sage Weile4eaac02011-05-24 13:06:07 -0700766
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700767 if (IS_ERR(req))
768 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700769
770 memset(&inarg, 0, sizeof(inarg));
771 inarg.newdir = get_node_id(newdir);
772 req->in.h.opcode = FUSE_RENAME;
773 req->in.h.nodeid = get_node_id(olddir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700774 req->in.numargs = 3;
775 req->in.args[0].size = sizeof(inarg);
776 req->in.args[0].value = &inarg;
777 req->in.args[1].size = oldent->d_name.len + 1;
778 req->in.args[1].value = oldent->d_name.name;
779 req->in.args[2].size = newent->d_name.len + 1;
780 req->in.args[2].value = newent->d_name.name;
Tejun Heob93f8582008-11-26 12:03:55 +0100781 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700782 err = req->out.h.error;
783 fuse_put_request(fc, req);
784 if (!err) {
Miklos Szeredi08b63302007-11-28 16:22:03 -0800785 /* ctime changes */
786 fuse_invalidate_attr(oldent->d_inode);
787
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700788 fuse_invalidate_attr(olddir);
789 if (olddir != newdir)
790 fuse_invalidate_attr(newdir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800791
792 /* newent will end up negative */
Miklos Szeredi5219f342009-11-04 10:24:52 +0100793 if (newent->d_inode) {
794 fuse_invalidate_attr(newent->d_inode);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800795 fuse_invalidate_entry_cache(newent);
Miklos Szeredi5219f342009-11-04 10:24:52 +0100796 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700797 } else if (err == -EINTR) {
798 /* If request was interrupted, DEITY only knows if the
799 rename actually took place. If the invalidation
800 fails (e.g. some process has CWD under the renamed
801 directory), then there can be inconsistency between
802 the dcache and the real filesystem. Tough luck. */
803 fuse_invalidate_entry(oldent);
804 if (newent->d_inode)
805 fuse_invalidate_entry(newent);
806 }
807
808 return err;
809}
810
811static int fuse_link(struct dentry *entry, struct inode *newdir,
812 struct dentry *newent)
813{
814 int err;
815 struct fuse_link_in inarg;
816 struct inode *inode = entry->d_inode;
817 struct fuse_conn *fc = get_fuse_conn(inode);
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400818 struct fuse_req *req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700819 if (IS_ERR(req))
820 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700821
822 memset(&inarg, 0, sizeof(inarg));
823 inarg.oldnodeid = get_node_id(inode);
824 req->in.h.opcode = FUSE_LINK;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700825 req->in.numargs = 2;
826 req->in.args[0].size = sizeof(inarg);
827 req->in.args[0].value = &inarg;
828 req->in.args[1].size = newent->d_name.len + 1;
829 req->in.args[1].value = newent->d_name.name;
830 err = create_new_entry(fc, req, newdir, newent, inode->i_mode);
831 /* Contrary to "normal" filesystems it can happen that link
832 makes two "logical" inodes point to the same "physical"
833 inode. We invalidate the attributes of the old one, so it
834 will reflect changes in the backing inode (link count,
835 etc.)
836 */
Miklos Szerediac45d612012-03-05 15:48:11 +0100837 if (!err) {
838 struct fuse_inode *fi = get_fuse_inode(inode);
839
840 spin_lock(&fc->lock);
841 fi->attr_version = ++fc->attr_version;
842 inc_nlink(inode);
843 spin_unlock(&fc->lock);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700844 fuse_invalidate_attr(inode);
Miklos Szerediac45d612012-03-05 15:48:11 +0100845 } else if (err == -EINTR) {
846 fuse_invalidate_attr(inode);
847 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700848 return err;
849}
850
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700851static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
852 struct kstat *stat)
853{
Miklos Szeredi203627b2012-05-10 19:49:38 +0400854 unsigned int blkbits;
855
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700856 stat->dev = inode->i_sb->s_dev;
857 stat->ino = attr->ino;
858 stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
859 stat->nlink = attr->nlink;
Eric W. Biederman499dcf22012-02-07 16:26:03 -0800860 stat->uid = make_kuid(&init_user_ns, attr->uid);
861 stat->gid = make_kgid(&init_user_ns, attr->gid);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700862 stat->rdev = inode->i_rdev;
863 stat->atime.tv_sec = attr->atime;
864 stat->atime.tv_nsec = attr->atimensec;
865 stat->mtime.tv_sec = attr->mtime;
866 stat->mtime.tv_nsec = attr->mtimensec;
867 stat->ctime.tv_sec = attr->ctime;
868 stat->ctime.tv_nsec = attr->ctimensec;
869 stat->size = attr->size;
870 stat->blocks = attr->blocks;
Miklos Szeredi203627b2012-05-10 19:49:38 +0400871
872 if (attr->blksize != 0)
873 blkbits = ilog2(attr->blksize);
874 else
875 blkbits = inode->i_sb->s_blocksize_bits;
876
877 stat->blksize = 1 << blkbits;
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700878}
879
Miklos Szeredic79e3222007-10-18 03:06:59 -0700880static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
881 struct file *file)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700882{
883 int err;
Miklos Szeredic79e3222007-10-18 03:06:59 -0700884 struct fuse_getattr_in inarg;
885 struct fuse_attr_out outarg;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700886 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700887 struct fuse_req *req;
888 u64 attr_version;
889
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400890 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700891 if (IS_ERR(req))
892 return PTR_ERR(req);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700893
Miklos Szeredi7dca9fd2007-11-28 16:21:59 -0800894 attr_version = fuse_get_attr_version(fc);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700895
Miklos Szeredic79e3222007-10-18 03:06:59 -0700896 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700897 memset(&outarg, 0, sizeof(outarg));
Miklos Szeredic79e3222007-10-18 03:06:59 -0700898 /* Directories have separate file-handle space */
899 if (file && S_ISREG(inode->i_mode)) {
900 struct fuse_file *ff = file->private_data;
901
902 inarg.getattr_flags |= FUSE_GETATTR_FH;
903 inarg.fh = ff->fh;
904 }
Miklos Szeredie5e55582005-09-09 13:10:28 -0700905 req->in.h.opcode = FUSE_GETATTR;
906 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredic79e3222007-10-18 03:06:59 -0700907 req->in.numargs = 1;
908 req->in.args[0].size = sizeof(inarg);
909 req->in.args[0].value = &inarg;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700910 req->out.numargs = 1;
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700911 if (fc->minor < 9)
912 req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
913 else
914 req->out.args[0].size = sizeof(outarg);
Miklos Szeredic79e3222007-10-18 03:06:59 -0700915 req->out.args[0].value = &outarg;
Tejun Heob93f8582008-11-26 12:03:55 +0100916 fuse_request_send(fc, req);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700917 err = req->out.h.error;
918 fuse_put_request(fc, req);
919 if (!err) {
Miklos Szeredic79e3222007-10-18 03:06:59 -0700920 if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
Miklos Szeredie5e55582005-09-09 13:10:28 -0700921 make_bad_inode(inode);
922 err = -EIO;
923 } else {
Miklos Szeredic79e3222007-10-18 03:06:59 -0700924 fuse_change_attributes(inode, &outarg.attr,
925 attr_timeout(&outarg),
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700926 attr_version);
927 if (stat)
Miklos Szeredic79e3222007-10-18 03:06:59 -0700928 fuse_fillattr(inode, &outarg.attr, stat);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700929 }
930 }
931 return err;
932}
933
Miklos Szeredibcb4be82007-11-28 16:21:59 -0800934int fuse_update_attributes(struct inode *inode, struct kstat *stat,
935 struct file *file, bool *refreshed)
936{
937 struct fuse_inode *fi = get_fuse_inode(inode);
938 int err;
939 bool r;
940
941 if (fi->i_time < get_jiffies_64()) {
942 r = true;
943 err = fuse_do_getattr(inode, stat, file);
944 } else {
945 r = false;
946 err = 0;
947 if (stat) {
948 generic_fillattr(inode, stat);
949 stat->mode = fi->orig_i_mode;
Pavel Shilovsky45c72cd2012-05-10 19:49:38 +0400950 stat->ino = fi->orig_ino;
Miklos Szeredibcb4be82007-11-28 16:21:59 -0800951 }
952 }
953
954 if (refreshed != NULL)
955 *refreshed = r;
956
957 return err;
958}
959
John Muir3b463ae2009-05-31 11:13:57 -0400960int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid,
John Muir451d0f52011-12-06 21:50:06 +0100961 u64 child_nodeid, struct qstr *name)
John Muir3b463ae2009-05-31 11:13:57 -0400962{
963 int err = -ENOTDIR;
964 struct inode *parent;
965 struct dentry *dir;
966 struct dentry *entry;
967
968 parent = ilookup5(sb, parent_nodeid, fuse_inode_eq, &parent_nodeid);
969 if (!parent)
970 return -ENOENT;
971
972 mutex_lock(&parent->i_mutex);
973 if (!S_ISDIR(parent->i_mode))
974 goto unlock;
975
976 err = -ENOENT;
977 dir = d_find_alias(parent);
978 if (!dir)
979 goto unlock;
980
981 entry = d_lookup(dir, name);
982 dput(dir);
983 if (!entry)
984 goto unlock;
985
986 fuse_invalidate_attr(parent);
987 fuse_invalidate_entry(entry);
John Muir451d0f52011-12-06 21:50:06 +0100988
989 if (child_nodeid != 0 && entry->d_inode) {
990 mutex_lock(&entry->d_inode->i_mutex);
991 if (get_node_id(entry->d_inode) != child_nodeid) {
992 err = -ENOENT;
993 goto badentry;
994 }
995 if (d_mountpoint(entry)) {
996 err = -EBUSY;
997 goto badentry;
998 }
999 if (S_ISDIR(entry->d_inode->i_mode)) {
1000 shrink_dcache_parent(entry);
1001 if (!simple_empty(entry)) {
1002 err = -ENOTEMPTY;
1003 goto badentry;
1004 }
1005 entry->d_inode->i_flags |= S_DEAD;
1006 }
1007 dont_mount(entry);
1008 clear_nlink(entry->d_inode);
1009 err = 0;
1010 badentry:
1011 mutex_unlock(&entry->d_inode->i_mutex);
1012 if (!err)
1013 d_delete(entry);
1014 } else {
1015 err = 0;
1016 }
John Muir3b463ae2009-05-31 11:13:57 -04001017 dput(entry);
John Muir3b463ae2009-05-31 11:13:57 -04001018
1019 unlock:
1020 mutex_unlock(&parent->i_mutex);
1021 iput(parent);
1022 return err;
1023}
1024
Miklos Szeredi87729a52005-09-09 13:10:34 -07001025/*
1026 * Calling into a user-controlled filesystem gives the filesystem
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001027 * daemon ptrace-like capabilities over the current process. This
Miklos Szeredi87729a52005-09-09 13:10:34 -07001028 * means, that the filesystem daemon is able to record the exact
1029 * filesystem operations performed, and can also control the behavior
1030 * of the requester process in otherwise impossible ways. For example
1031 * it can delay the operation for arbitrary length of time allowing
1032 * DoS against the requester.
1033 *
1034 * For this reason only those processes can call into the filesystem,
1035 * for which the owner of the mount has ptrace privilege. This
1036 * excludes processes started by other users, suid or sgid processes.
1037 */
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001038int fuse_allow_current_process(struct fuse_conn *fc)
Miklos Szeredi87729a52005-09-09 13:10:34 -07001039{
David Howellsc69e8d92008-11-14 10:39:19 +11001040 const struct cred *cred;
David Howellsc69e8d92008-11-14 10:39:19 +11001041
Miklos Szeredi87729a52005-09-09 13:10:34 -07001042 if (fc->flags & FUSE_ALLOW_OTHER)
1043 return 1;
1044
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001045 cred = current_cred();
Eric W. Biederman499dcf22012-02-07 16:26:03 -08001046 if (uid_eq(cred->euid, fc->user_id) &&
1047 uid_eq(cred->suid, fc->user_id) &&
1048 uid_eq(cred->uid, fc->user_id) &&
1049 gid_eq(cred->egid, fc->group_id) &&
1050 gid_eq(cred->sgid, fc->group_id) &&
1051 gid_eq(cred->gid, fc->group_id))
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001052 return 1;
Miklos Szeredi87729a52005-09-09 13:10:34 -07001053
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001054 return 0;
Miklos Szeredi87729a52005-09-09 13:10:34 -07001055}
1056
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001057static int fuse_access(struct inode *inode, int mask)
1058{
1059 struct fuse_conn *fc = get_fuse_conn(inode);
1060 struct fuse_req *req;
1061 struct fuse_access_in inarg;
1062 int err;
1063
1064 if (fc->no_access)
1065 return 0;
1066
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001067 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001068 if (IS_ERR(req))
1069 return PTR_ERR(req);
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001070
1071 memset(&inarg, 0, sizeof(inarg));
Al Viroe6305c42008-07-15 21:03:57 -04001072 inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC);
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001073 req->in.h.opcode = FUSE_ACCESS;
1074 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001075 req->in.numargs = 1;
1076 req->in.args[0].size = sizeof(inarg);
1077 req->in.args[0].value = &inarg;
Tejun Heob93f8582008-11-26 12:03:55 +01001078 fuse_request_send(fc, req);
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001079 err = req->out.h.error;
1080 fuse_put_request(fc, req);
1081 if (err == -ENOSYS) {
1082 fc->no_access = 1;
1083 err = 0;
1084 }
1085 return err;
1086}
1087
Al Viro10556cb2011-06-20 19:28:19 -04001088static int fuse_perm_getattr(struct inode *inode, int mask)
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001089{
Al Viro10556cb2011-06-20 19:28:19 -04001090 if (mask & MAY_NOT_BLOCK)
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001091 return -ECHILD;
1092
1093 return fuse_do_getattr(inode, NULL, NULL);
1094}
1095
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001096/*
1097 * Check permission. The two basic access models of FUSE are:
1098 *
1099 * 1) Local access checking ('default_permissions' mount option) based
1100 * on file mode. This is the plain old disk filesystem permission
1101 * modell.
1102 *
1103 * 2) "Remote" access checking, where server is responsible for
1104 * checking permission in each inode operation. An exception to this
1105 * is if ->permission() was invoked from sys_access() in which case an
1106 * access request is sent. Execute permission is still checked
1107 * locally based on file mode.
1108 */
Al Viro10556cb2011-06-20 19:28:19 -04001109static int fuse_permission(struct inode *inode, int mask)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001110{
1111 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi244f6382007-10-16 23:31:02 -07001112 bool refreshed = false;
1113 int err = 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001114
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001115 if (!fuse_allow_current_process(fc))
Miklos Szeredie5e55582005-09-09 13:10:28 -07001116 return -EACCES;
Miklos Szeredi244f6382007-10-16 23:31:02 -07001117
1118 /*
Miklos Szeredie8e96152007-10-16 23:31:06 -07001119 * If attributes are needed, refresh them before proceeding
Miklos Szeredi244f6382007-10-16 23:31:02 -07001120 */
Miklos Szeredie8e96152007-10-16 23:31:06 -07001121 if ((fc->flags & FUSE_DEFAULT_PERMISSIONS) ||
1122 ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001123 struct fuse_inode *fi = get_fuse_inode(inode);
1124
1125 if (fi->i_time < get_jiffies_64()) {
1126 refreshed = true;
1127
Al Viro10556cb2011-06-20 19:28:19 -04001128 err = fuse_perm_getattr(inode, mask);
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001129 if (err)
1130 return err;
1131 }
Miklos Szeredi244f6382007-10-16 23:31:02 -07001132 }
1133
1134 if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
Al Viro2830ba72011-06-20 19:16:29 -04001135 err = generic_permission(inode, mask);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001136
1137 /* If permission is denied, try to refresh file
1138 attributes. This is also needed, because the root
1139 node will at first have no permissions */
Miklos Szeredi244f6382007-10-16 23:31:02 -07001140 if (err == -EACCES && !refreshed) {
Al Viro10556cb2011-06-20 19:28:19 -04001141 err = fuse_perm_getattr(inode, mask);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001142 if (!err)
Al Viro2830ba72011-06-20 19:16:29 -04001143 err = generic_permission(inode, mask);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001144 }
1145
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001146 /* Note: the opposite of the above test does not
1147 exist. So if permissions are revoked this won't be
1148 noticed immediately, only after the attribute
1149 timeout has expired */
Eric Paris9cfcac82010-07-23 11:43:51 -04001150 } else if (mask & (MAY_ACCESS | MAY_CHDIR)) {
Al Viro10556cb2011-06-20 19:28:19 -04001151 if (mask & MAY_NOT_BLOCK)
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001152 return -ECHILD;
1153
Miklos Szeredie8e96152007-10-16 23:31:06 -07001154 err = fuse_access(inode, mask);
1155 } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
1156 if (!(inode->i_mode & S_IXUGO)) {
1157 if (refreshed)
1158 return -EACCES;
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001159
Al Viro10556cb2011-06-20 19:28:19 -04001160 err = fuse_perm_getattr(inode, mask);
Miklos Szeredie8e96152007-10-16 23:31:06 -07001161 if (!err && !(inode->i_mode & S_IXUGO))
1162 return -EACCES;
1163 }
Miklos Szeredie5e55582005-09-09 13:10:28 -07001164 }
Miklos Szeredi244f6382007-10-16 23:31:02 -07001165 return err;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001166}
1167
1168static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
Al Viro8d3af7f2013-05-18 03:03:58 -04001169 struct dir_context *ctx)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001170{
1171 while (nbytes >= FUSE_NAME_OFFSET) {
1172 struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
1173 size_t reclen = FUSE_DIRENT_SIZE(dirent);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001174 if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
1175 return -EIO;
1176 if (reclen > nbytes)
1177 break;
1178
Al Viro8d3af7f2013-05-18 03:03:58 -04001179 if (!dir_emit(ctx, dirent->name, dirent->namelen,
1180 dirent->ino, dirent->type))
Miklos Szeredie5e55582005-09-09 13:10:28 -07001181 break;
1182
1183 buf += reclen;
1184 nbytes -= reclen;
Al Viro8d3af7f2013-05-18 03:03:58 -04001185 ctx->pos = dirent->off;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001186 }
1187
1188 return 0;
1189}
1190
Anand V. Avati0b05b182012-08-19 08:53:23 -04001191static int fuse_direntplus_link(struct file *file,
1192 struct fuse_direntplus *direntplus,
1193 u64 attr_version)
1194{
1195 int err;
1196 struct fuse_entry_out *o = &direntplus->entry_out;
1197 struct fuse_dirent *dirent = &direntplus->dirent;
1198 struct dentry *parent = file->f_path.dentry;
1199 struct qstr name = QSTR_INIT(dirent->name, dirent->namelen);
1200 struct dentry *dentry;
1201 struct dentry *alias;
1202 struct inode *dir = parent->d_inode;
1203 struct fuse_conn *fc;
1204 struct inode *inode;
1205
1206 if (!o->nodeid) {
1207 /*
1208 * Unlike in the case of fuse_lookup, zero nodeid does not mean
1209 * ENOENT. Instead, it only means the userspace filesystem did
1210 * not want to return attributes/handle for this entry.
1211 *
1212 * So do nothing.
1213 */
1214 return 0;
1215 }
1216
1217 if (name.name[0] == '.') {
1218 /*
1219 * We could potentially refresh the attributes of the directory
1220 * and its parent?
1221 */
1222 if (name.len == 1)
1223 return 0;
1224 if (name.name[1] == '.' && name.len == 2)
1225 return 0;
1226 }
Miklos Szeredia28ef452013-07-17 14:53:53 +02001227
1228 if (invalid_nodeid(o->nodeid))
1229 return -EIO;
1230 if (!fuse_valid_type(o->attr.mode))
1231 return -EIO;
1232
Anand V. Avati0b05b182012-08-19 08:53:23 -04001233 fc = get_fuse_conn(dir);
1234
1235 name.hash = full_name_hash(name.name, name.len);
1236 dentry = d_lookup(parent, &name);
Niels de Vos53ce9a32013-07-17 14:53:53 +02001237 if (dentry) {
Anand V. Avati0b05b182012-08-19 08:53:23 -04001238 inode = dentry->d_inode;
Niels de Vos53ce9a32013-07-17 14:53:53 +02001239 if (!inode) {
1240 d_drop(dentry);
Miklos Szeredia28ef452013-07-17 14:53:53 +02001241 } else if (get_node_id(inode) != o->nodeid ||
1242 ((o->attr.mode ^ inode->i_mode) & S_IFMT)) {
Niels de Vos53ce9a32013-07-17 14:53:53 +02001243 err = d_invalidate(dentry);
1244 if (err)
1245 goto out;
Miklos Szeredia28ef452013-07-17 14:53:53 +02001246 } else if (is_bad_inode(inode)) {
1247 err = -EIO;
1248 goto out;
Niels de Vos53ce9a32013-07-17 14:53:53 +02001249 } else {
Anand V. Avati0b05b182012-08-19 08:53:23 -04001250 struct fuse_inode *fi;
1251 fi = get_fuse_inode(inode);
1252 spin_lock(&fc->lock);
1253 fi->nlookup++;
1254 spin_unlock(&fc->lock);
1255
Miklos Szeredifa2b7212013-07-17 14:53:53 +02001256 fuse_change_attributes(inode, &o->attr,
1257 entry_attr_timeout(o),
1258 attr_version);
1259
Anand V. Avati0b05b182012-08-19 08:53:23 -04001260 /*
1261 * The other branch to 'found' comes via fuse_iget()
1262 * which bumps nlookup inside
1263 */
1264 goto found;
1265 }
Anand V. Avati0b05b182012-08-19 08:53:23 -04001266 dput(dentry);
Anand V. Avati0b05b182012-08-19 08:53:23 -04001267 }
1268
1269 dentry = d_alloc(parent, &name);
1270 err = -ENOMEM;
1271 if (!dentry)
1272 goto out;
1273
1274 inode = fuse_iget(dir->i_sb, o->nodeid, o->generation,
1275 &o->attr, entry_attr_timeout(o), attr_version);
1276 if (!inode)
1277 goto out;
1278
Miklos Szeredi5835f332013-09-05 11:44:42 +02001279 alias = fuse_materialise_dentry(dentry, inode);
1280 err = PTR_ERR(alias);
1281 if (IS_ERR(alias))
1282 goto out;
Miklos Szeredi29149412013-07-17 14:53:53 +02001283
Anand V. Avati0b05b182012-08-19 08:53:23 -04001284 if (alias) {
1285 dput(dentry);
1286 dentry = alias;
1287 }
1288
1289found:
Anand V. Avati0b05b182012-08-19 08:53:23 -04001290 fuse_change_entry_timeout(dentry, o);
1291
1292 err = 0;
1293out:
Miklos Szeredic7263bc2013-07-17 14:53:54 +02001294 dput(dentry);
Anand V. Avati0b05b182012-08-19 08:53:23 -04001295 return err;
1296}
1297
1298static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file,
Al Viro8d3af7f2013-05-18 03:03:58 -04001299 struct dir_context *ctx, u64 attr_version)
Anand V. Avati0b05b182012-08-19 08:53:23 -04001300{
1301 struct fuse_direntplus *direntplus;
1302 struct fuse_dirent *dirent;
1303 size_t reclen;
1304 int over = 0;
1305 int ret;
1306
1307 while (nbytes >= FUSE_NAME_OFFSET_DIRENTPLUS) {
1308 direntplus = (struct fuse_direntplus *) buf;
1309 dirent = &direntplus->dirent;
1310 reclen = FUSE_DIRENTPLUS_SIZE(direntplus);
1311
1312 if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
1313 return -EIO;
1314 if (reclen > nbytes)
1315 break;
1316
1317 if (!over) {
1318 /* We fill entries into dstbuf only as much as
1319 it can hold. But we still continue iterating
1320 over remaining entries to link them. If not,
1321 we need to send a FORGET for each of those
1322 which we did not link.
1323 */
Al Viro8d3af7f2013-05-18 03:03:58 -04001324 over = !dir_emit(ctx, dirent->name, dirent->namelen,
1325 dirent->ino, dirent->type);
1326 ctx->pos = dirent->off;
Anand V. Avati0b05b182012-08-19 08:53:23 -04001327 }
1328
1329 buf += reclen;
1330 nbytes -= reclen;
1331
1332 ret = fuse_direntplus_link(file, direntplus, attr_version);
1333 if (ret)
1334 fuse_force_forget(file, direntplus->entry_out.nodeid);
1335 }
1336
1337 return 0;
1338}
1339
Al Viro8d3af7f2013-05-18 03:03:58 -04001340static int fuse_readdir(struct file *file, struct dir_context *ctx)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001341{
Feng Shuo4582a4a2013-01-15 11:23:28 +08001342 int plus, err;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001343 size_t nbytes;
1344 struct page *page;
Al Viro496ad9a2013-01-23 17:07:38 -05001345 struct inode *inode = file_inode(file);
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001346 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi248d86e2006-01-06 00:19:39 -08001347 struct fuse_req *req;
Anand V. Avati0b05b182012-08-19 08:53:23 -04001348 u64 attr_version = 0;
Miklos Szeredi248d86e2006-01-06 00:19:39 -08001349
1350 if (is_bad_inode(inode))
1351 return -EIO;
1352
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001353 req = fuse_get_req(fc, 1);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001354 if (IS_ERR(req))
1355 return PTR_ERR(req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001356
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001357 page = alloc_page(GFP_KERNEL);
1358 if (!page) {
1359 fuse_put_request(fc, req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001360 return -ENOMEM;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001361 }
Feng Shuo4582a4a2013-01-15 11:23:28 +08001362
Al Viro8d3af7f2013-05-18 03:03:58 -04001363 plus = fuse_use_readdirplus(inode, ctx);
Miklos Szeredif4975c62009-04-02 14:25:34 +02001364 req->out.argpages = 1;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001365 req->num_pages = 1;
1366 req->pages[0] = page;
Maxim Patlasov85f40ae2012-10-26 19:49:33 +04001367 req->page_descs[0].length = PAGE_SIZE;
Feng Shuo4582a4a2013-01-15 11:23:28 +08001368 if (plus) {
Anand V. Avati0b05b182012-08-19 08:53:23 -04001369 attr_version = fuse_get_attr_version(fc);
Al Viro8d3af7f2013-05-18 03:03:58 -04001370 fuse_read_fill(req, file, ctx->pos, PAGE_SIZE,
Anand V. Avati0b05b182012-08-19 08:53:23 -04001371 FUSE_READDIRPLUS);
1372 } else {
Al Viro8d3af7f2013-05-18 03:03:58 -04001373 fuse_read_fill(req, file, ctx->pos, PAGE_SIZE,
Anand V. Avati0b05b182012-08-19 08:53:23 -04001374 FUSE_READDIR);
1375 }
Tejun Heob93f8582008-11-26 12:03:55 +01001376 fuse_request_send(fc, req);
Miklos Szeredi361b1eb52006-01-16 22:14:45 -08001377 nbytes = req->out.args[0].size;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001378 err = req->out.h.error;
1379 fuse_put_request(fc, req);
Anand V. Avati0b05b182012-08-19 08:53:23 -04001380 if (!err) {
Feng Shuo4582a4a2013-01-15 11:23:28 +08001381 if (plus) {
Anand V. Avati0b05b182012-08-19 08:53:23 -04001382 err = parse_dirplusfile(page_address(page), nbytes,
Al Viro8d3af7f2013-05-18 03:03:58 -04001383 file, ctx,
Anand V. Avati0b05b182012-08-19 08:53:23 -04001384 attr_version);
1385 } else {
1386 err = parse_dirfile(page_address(page), nbytes, file,
Al Viro8d3af7f2013-05-18 03:03:58 -04001387 ctx);
Anand V. Avati0b05b182012-08-19 08:53:23 -04001388 }
1389 }
Miklos Szeredie5e55582005-09-09 13:10:28 -07001390
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001391 __free_page(page);
Miklos Szeredib36c31b2005-09-09 13:10:38 -07001392 fuse_invalidate_attr(inode); /* atime changed */
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001393 return err;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001394}
1395
1396static char *read_link(struct dentry *dentry)
1397{
1398 struct inode *inode = dentry->d_inode;
1399 struct fuse_conn *fc = get_fuse_conn(inode);
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001400 struct fuse_req *req = fuse_get_req_nopages(fc);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001401 char *link;
1402
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001403 if (IS_ERR(req))
David Howellse231c2e2008-02-07 00:15:26 -08001404 return ERR_CAST(req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001405
1406 link = (char *) __get_free_page(GFP_KERNEL);
1407 if (!link) {
1408 link = ERR_PTR(-ENOMEM);
1409 goto out;
1410 }
1411 req->in.h.opcode = FUSE_READLINK;
1412 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001413 req->out.argvar = 1;
1414 req->out.numargs = 1;
1415 req->out.args[0].size = PAGE_SIZE - 1;
1416 req->out.args[0].value = link;
Tejun Heob93f8582008-11-26 12:03:55 +01001417 fuse_request_send(fc, req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001418 if (req->out.h.error) {
1419 free_page((unsigned long) link);
1420 link = ERR_PTR(req->out.h.error);
1421 } else
1422 link[req->out.args[0].size] = '\0';
1423 out:
1424 fuse_put_request(fc, req);
Miklos Szeredib36c31b2005-09-09 13:10:38 -07001425 fuse_invalidate_attr(inode); /* atime changed */
Miklos Szeredie5e55582005-09-09 13:10:28 -07001426 return link;
1427}
1428
1429static void free_link(char *link)
1430{
1431 if (!IS_ERR(link))
1432 free_page((unsigned long) link);
1433}
1434
1435static void *fuse_follow_link(struct dentry *dentry, struct nameidata *nd)
1436{
1437 nd_set_link(nd, read_link(dentry));
1438 return NULL;
1439}
1440
1441static void fuse_put_link(struct dentry *dentry, struct nameidata *nd, void *c)
1442{
1443 free_link(nd_get_link(nd));
1444}
1445
1446static int fuse_dir_open(struct inode *inode, struct file *file)
1447{
Miklos Szeredi91fe96b2009-04-28 16:56:37 +02001448 return fuse_open_common(inode, file, true);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001449}
1450
1451static int fuse_dir_release(struct inode *inode, struct file *file)
1452{
Miklos Szeredi8b0797a2009-04-28 16:56:39 +02001453 fuse_release_common(file, FUSE_RELEASEDIR);
1454
1455 return 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001456}
1457
Josef Bacik02c24a82011-07-16 20:44:56 -04001458static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end,
1459 int datasync)
Miklos Szeredi82547982005-09-09 13:10:38 -07001460{
Josef Bacik02c24a82011-07-16 20:44:56 -04001461 return fuse_fsync_common(file, start, end, datasync, 1);
Miklos Szeredi82547982005-09-09 13:10:38 -07001462}
1463
Miklos Szeredib18da0c2011-12-13 11:58:49 +01001464static long fuse_dir_ioctl(struct file *file, unsigned int cmd,
1465 unsigned long arg)
1466{
1467 struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1468
1469 /* FUSE_IOCTL_DIR only supported for API version >= 7.18 */
1470 if (fc->minor < 18)
1471 return -ENOTTY;
1472
1473 return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR);
1474}
1475
1476static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd,
1477 unsigned long arg)
1478{
1479 struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1480
1481 if (fc->minor < 18)
1482 return -ENOTTY;
1483
1484 return fuse_ioctl_common(file, cmd, arg,
1485 FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR);
1486}
1487
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001488static bool update_mtime(unsigned ivalid)
1489{
1490 /* Always update if mtime is explicitly set */
1491 if (ivalid & ATTR_MTIME_SET)
1492 return true;
1493
1494 /* If it's an open(O_TRUNC) or an ftruncate(), don't update */
1495 if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
1496 return false;
1497
1498 /* In all other cases update */
1499 return true;
1500}
1501
Miklos Szeredibefc6492005-11-07 00:59:52 -08001502static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001503{
1504 unsigned ivalid = iattr->ia_valid;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001505
1506 if (ivalid & ATTR_MODE)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001507 arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001508 if (ivalid & ATTR_UID)
Eric W. Biederman499dcf22012-02-07 16:26:03 -08001509 arg->valid |= FATTR_UID, arg->uid = from_kuid(&init_user_ns, iattr->ia_uid);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001510 if (ivalid & ATTR_GID)
Eric W. Biederman499dcf22012-02-07 16:26:03 -08001511 arg->valid |= FATTR_GID, arg->gid = from_kgid(&init_user_ns, iattr->ia_gid);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001512 if (ivalid & ATTR_SIZE)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001513 arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001514 if (ivalid & ATTR_ATIME) {
1515 arg->valid |= FATTR_ATIME;
Miklos Szeredibefc6492005-11-07 00:59:52 -08001516 arg->atime = iattr->ia_atime.tv_sec;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001517 arg->atimensec = iattr->ia_atime.tv_nsec;
1518 if (!(ivalid & ATTR_ATIME_SET))
1519 arg->valid |= FATTR_ATIME_NOW;
1520 }
1521 if ((ivalid & ATTR_MTIME) && update_mtime(ivalid)) {
1522 arg->valid |= FATTR_MTIME;
Miklos Szeredibefc6492005-11-07 00:59:52 -08001523 arg->mtime = iattr->ia_mtime.tv_sec;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001524 arg->mtimensec = iattr->ia_mtime.tv_nsec;
1525 if (!(ivalid & ATTR_MTIME_SET))
1526 arg->valid |= FATTR_MTIME_NOW;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001527 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001528}
1529
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001530/*
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001531 * Prevent concurrent writepages on inode
1532 *
1533 * This is done by adding a negative bias to the inode write counter
1534 * and waiting for all pending writes to finish.
1535 */
1536void fuse_set_nowrite(struct inode *inode)
1537{
1538 struct fuse_conn *fc = get_fuse_conn(inode);
1539 struct fuse_inode *fi = get_fuse_inode(inode);
1540
1541 BUG_ON(!mutex_is_locked(&inode->i_mutex));
1542
1543 spin_lock(&fc->lock);
1544 BUG_ON(fi->writectr < 0);
1545 fi->writectr += FUSE_NOWRITE;
1546 spin_unlock(&fc->lock);
1547 wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE);
1548}
1549
1550/*
1551 * Allow writepages on inode
1552 *
1553 * Remove the bias from the writecounter and send any queued
1554 * writepages.
1555 */
1556static void __fuse_release_nowrite(struct inode *inode)
1557{
1558 struct fuse_inode *fi = get_fuse_inode(inode);
1559
1560 BUG_ON(fi->writectr != FUSE_NOWRITE);
1561 fi->writectr = 0;
1562 fuse_flush_writepages(inode);
1563}
1564
1565void fuse_release_nowrite(struct inode *inode)
1566{
1567 struct fuse_conn *fc = get_fuse_conn(inode);
1568
1569 spin_lock(&fc->lock);
1570 __fuse_release_nowrite(inode);
1571 spin_unlock(&fc->lock);
1572}
1573
1574/*
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001575 * Set attributes, and at the same time refresh them.
1576 *
1577 * Truncation is slightly complicated, because the 'truncate' request
1578 * may fail, in which case we don't want to touch the mapping.
Miklos Szeredi9ffbb912006-10-17 00:10:06 -07001579 * vmtruncate() doesn't allow for this case, so do the rlimit checking
1580 * and the actual truncation by hand.
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001581 */
Maxim Patlasovefb9fa92012-12-18 14:05:08 +04001582int fuse_do_setattr(struct inode *inode, struct iattr *attr,
1583 struct file *file)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001584{
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001585 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001586 struct fuse_req *req;
1587 struct fuse_setattr_in inarg;
1588 struct fuse_attr_out outarg;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001589 bool is_truncate = false;
1590 loff_t oldsize;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001591 int err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001592
Christoph Hellwigdb78b872010-06-04 11:30:03 +02001593 if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS))
1594 attr->ia_valid |= ATTR_FORCE;
1595
1596 err = inode_change_ok(inode, attr);
1597 if (err)
1598 return err;
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001599
Miklos Szeredi8d56add2011-02-25 14:44:58 +01001600 if (attr->ia_valid & ATTR_OPEN) {
1601 if (fc->atomic_o_trunc)
1602 return 0;
1603 file = NULL;
1604 }
Miklos Szeredi6ff958e2007-10-18 03:07:02 -07001605
Christoph Hellwig2c27c652010-06-04 11:30:04 +02001606 if (attr->ia_valid & ATTR_SIZE)
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001607 is_truncate = true;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001608
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001609 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001610 if (IS_ERR(req))
1611 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001612
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001613 if (is_truncate)
1614 fuse_set_nowrite(inode);
1615
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001616 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -07001617 memset(&outarg, 0, sizeof(outarg));
Miklos Szeredibefc6492005-11-07 00:59:52 -08001618 iattr_to_fattr(attr, &inarg);
Miklos Szeredi49d49142007-10-18 03:07:00 -07001619 if (file) {
1620 struct fuse_file *ff = file->private_data;
1621 inarg.valid |= FATTR_FH;
1622 inarg.fh = ff->fh;
1623 }
Miklos Szeredif3332112007-10-18 03:07:04 -07001624 if (attr->ia_valid & ATTR_SIZE) {
1625 /* For mandatory locking in truncate */
1626 inarg.valid |= FATTR_LOCKOWNER;
1627 inarg.lock_owner = fuse_lock_owner_id(fc, current->files);
1628 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001629 req->in.h.opcode = FUSE_SETATTR;
1630 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001631 req->in.numargs = 1;
1632 req->in.args[0].size = sizeof(inarg);
1633 req->in.args[0].value = &inarg;
1634 req->out.numargs = 1;
Miklos Szeredi0e9663e2007-10-18 03:07:05 -07001635 if (fc->minor < 9)
1636 req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
1637 else
1638 req->out.args[0].size = sizeof(outarg);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001639 req->out.args[0].value = &outarg;
Tejun Heob93f8582008-11-26 12:03:55 +01001640 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001641 err = req->out.h.error;
1642 fuse_put_request(fc, req);
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001643 if (err) {
1644 if (err == -EINTR)
1645 fuse_invalidate_attr(inode);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001646 goto error;
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001647 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001648
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001649 if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
1650 make_bad_inode(inode);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001651 err = -EIO;
1652 goto error;
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001653 }
1654
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001655 spin_lock(&fc->lock);
1656 fuse_change_attributes_common(inode, &outarg.attr,
1657 attr_timeout(&outarg));
1658 oldsize = inode->i_size;
1659 i_size_write(inode, outarg.attr.size);
1660
1661 if (is_truncate) {
1662 /* NOTE: this may release/reacquire fc->lock */
1663 __fuse_release_nowrite(inode);
1664 }
1665 spin_unlock(&fc->lock);
1666
1667 /*
1668 * Only call invalidate_inode_pages2() after removing
1669 * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock.
1670 */
1671 if (S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
npiggin@suse.dec08d3b02009-08-21 02:35:06 +10001672 truncate_pagecache(inode, oldsize, outarg.attr.size);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001673 invalidate_inode_pages2(inode->i_mapping);
1674 }
1675
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001676 return 0;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001677
1678error:
1679 if (is_truncate)
1680 fuse_release_nowrite(inode);
1681
1682 return err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001683}
1684
Miklos Szeredi49d49142007-10-18 03:07:00 -07001685static int fuse_setattr(struct dentry *entry, struct iattr *attr)
1686{
Maxim Patlasovefb9fa92012-12-18 14:05:08 +04001687 struct inode *inode = entry->d_inode;
1688
1689 if (!fuse_allow_current_process(get_fuse_conn(inode)))
1690 return -EACCES;
1691
Miklos Szeredi49d49142007-10-18 03:07:00 -07001692 if (attr->ia_valid & ATTR_FILE)
Maxim Patlasovefb9fa92012-12-18 14:05:08 +04001693 return fuse_do_setattr(inode, attr, attr->ia_file);
Miklos Szeredi49d49142007-10-18 03:07:00 -07001694 else
Maxim Patlasovefb9fa92012-12-18 14:05:08 +04001695 return fuse_do_setattr(inode, attr, NULL);
Miklos Szeredi49d49142007-10-18 03:07:00 -07001696}
1697
Miklos Szeredie5e55582005-09-09 13:10:28 -07001698static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
1699 struct kstat *stat)
1700{
1701 struct inode *inode = entry->d_inode;
Miklos Szeredi244f6382007-10-16 23:31:02 -07001702 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi244f6382007-10-16 23:31:02 -07001703
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001704 if (!fuse_allow_current_process(fc))
Miklos Szeredi244f6382007-10-16 23:31:02 -07001705 return -EACCES;
1706
Miklos Szeredibcb4be82007-11-28 16:21:59 -08001707 return fuse_update_attributes(inode, stat, NULL, NULL);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001708}
1709
Miklos Szeredi92a87802005-09-09 13:10:31 -07001710static int fuse_setxattr(struct dentry *entry, const char *name,
1711 const void *value, size_t size, int flags)
1712{
1713 struct inode *inode = entry->d_inode;
1714 struct fuse_conn *fc = get_fuse_conn(inode);
1715 struct fuse_req *req;
1716 struct fuse_setxattr_in inarg;
1717 int err;
1718
Miklos Szeredi92a87802005-09-09 13:10:31 -07001719 if (fc->no_setxattr)
1720 return -EOPNOTSUPP;
1721
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001722 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001723 if (IS_ERR(req))
1724 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001725
1726 memset(&inarg, 0, sizeof(inarg));
1727 inarg.size = size;
1728 inarg.flags = flags;
1729 req->in.h.opcode = FUSE_SETXATTR;
1730 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001731 req->in.numargs = 3;
1732 req->in.args[0].size = sizeof(inarg);
1733 req->in.args[0].value = &inarg;
1734 req->in.args[1].size = strlen(name) + 1;
1735 req->in.args[1].value = name;
1736 req->in.args[2].size = size;
1737 req->in.args[2].value = value;
Tejun Heob93f8582008-11-26 12:03:55 +01001738 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001739 err = req->out.h.error;
1740 fuse_put_request(fc, req);
1741 if (err == -ENOSYS) {
1742 fc->no_setxattr = 1;
1743 err = -EOPNOTSUPP;
1744 }
1745 return err;
1746}
1747
1748static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
1749 void *value, size_t size)
1750{
1751 struct inode *inode = entry->d_inode;
1752 struct fuse_conn *fc = get_fuse_conn(inode);
1753 struct fuse_req *req;
1754 struct fuse_getxattr_in inarg;
1755 struct fuse_getxattr_out outarg;
1756 ssize_t ret;
1757
1758 if (fc->no_getxattr)
1759 return -EOPNOTSUPP;
1760
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001761 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001762 if (IS_ERR(req))
1763 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001764
1765 memset(&inarg, 0, sizeof(inarg));
1766 inarg.size = size;
1767 req->in.h.opcode = FUSE_GETXATTR;
1768 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001769 req->in.numargs = 2;
1770 req->in.args[0].size = sizeof(inarg);
1771 req->in.args[0].value = &inarg;
1772 req->in.args[1].size = strlen(name) + 1;
1773 req->in.args[1].value = name;
1774 /* This is really two different operations rolled into one */
1775 req->out.numargs = 1;
1776 if (size) {
1777 req->out.argvar = 1;
1778 req->out.args[0].size = size;
1779 req->out.args[0].value = value;
1780 } else {
1781 req->out.args[0].size = sizeof(outarg);
1782 req->out.args[0].value = &outarg;
1783 }
Tejun Heob93f8582008-11-26 12:03:55 +01001784 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001785 ret = req->out.h.error;
1786 if (!ret)
1787 ret = size ? req->out.args[0].size : outarg.size;
1788 else {
1789 if (ret == -ENOSYS) {
1790 fc->no_getxattr = 1;
1791 ret = -EOPNOTSUPP;
1792 }
1793 }
1794 fuse_put_request(fc, req);
1795 return ret;
1796}
1797
1798static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
1799{
1800 struct inode *inode = entry->d_inode;
1801 struct fuse_conn *fc = get_fuse_conn(inode);
1802 struct fuse_req *req;
1803 struct fuse_getxattr_in inarg;
1804 struct fuse_getxattr_out outarg;
1805 ssize_t ret;
1806
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001807 if (!fuse_allow_current_process(fc))
Miklos Szeredie57ac682007-10-18 03:06:58 -07001808 return -EACCES;
1809
Miklos Szeredi92a87802005-09-09 13:10:31 -07001810 if (fc->no_listxattr)
1811 return -EOPNOTSUPP;
1812
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001813 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001814 if (IS_ERR(req))
1815 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001816
1817 memset(&inarg, 0, sizeof(inarg));
1818 inarg.size = size;
1819 req->in.h.opcode = FUSE_LISTXATTR;
1820 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001821 req->in.numargs = 1;
1822 req->in.args[0].size = sizeof(inarg);
1823 req->in.args[0].value = &inarg;
1824 /* This is really two different operations rolled into one */
1825 req->out.numargs = 1;
1826 if (size) {
1827 req->out.argvar = 1;
1828 req->out.args[0].size = size;
1829 req->out.args[0].value = list;
1830 } else {
1831 req->out.args[0].size = sizeof(outarg);
1832 req->out.args[0].value = &outarg;
1833 }
Tejun Heob93f8582008-11-26 12:03:55 +01001834 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001835 ret = req->out.h.error;
1836 if (!ret)
1837 ret = size ? req->out.args[0].size : outarg.size;
1838 else {
1839 if (ret == -ENOSYS) {
1840 fc->no_listxattr = 1;
1841 ret = -EOPNOTSUPP;
1842 }
1843 }
1844 fuse_put_request(fc, req);
1845 return ret;
1846}
1847
1848static int fuse_removexattr(struct dentry *entry, const char *name)
1849{
1850 struct inode *inode = entry->d_inode;
1851 struct fuse_conn *fc = get_fuse_conn(inode);
1852 struct fuse_req *req;
1853 int err;
1854
1855 if (fc->no_removexattr)
1856 return -EOPNOTSUPP;
1857
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001858 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001859 if (IS_ERR(req))
1860 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001861
1862 req->in.h.opcode = FUSE_REMOVEXATTR;
1863 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001864 req->in.numargs = 1;
1865 req->in.args[0].size = strlen(name) + 1;
1866 req->in.args[0].value = name;
Tejun Heob93f8582008-11-26 12:03:55 +01001867 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001868 err = req->out.h.error;
1869 fuse_put_request(fc, req);
1870 if (err == -ENOSYS) {
1871 fc->no_removexattr = 1;
1872 err = -EOPNOTSUPP;
1873 }
1874 return err;
1875}
1876
Arjan van de Ven754661f2007-02-12 00:55:38 -08001877static const struct inode_operations fuse_dir_inode_operations = {
Miklos Szeredie5e55582005-09-09 13:10:28 -07001878 .lookup = fuse_lookup,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001879 .mkdir = fuse_mkdir,
1880 .symlink = fuse_symlink,
1881 .unlink = fuse_unlink,
1882 .rmdir = fuse_rmdir,
1883 .rename = fuse_rename,
1884 .link = fuse_link,
1885 .setattr = fuse_setattr,
1886 .create = fuse_create,
Miklos Szeredic8ccbe02012-06-05 15:10:22 +02001887 .atomic_open = fuse_atomic_open,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001888 .mknod = fuse_mknod,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001889 .permission = fuse_permission,
1890 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001891 .setxattr = fuse_setxattr,
1892 .getxattr = fuse_getxattr,
1893 .listxattr = fuse_listxattr,
1894 .removexattr = fuse_removexattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001895};
1896
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -08001897static const struct file_operations fuse_dir_operations = {
Miklos Szeredib6aeade2005-09-09 13:10:30 -07001898 .llseek = generic_file_llseek,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001899 .read = generic_read_dir,
Al Viro8d3af7f2013-05-18 03:03:58 -04001900 .iterate = fuse_readdir,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001901 .open = fuse_dir_open,
1902 .release = fuse_dir_release,
Miklos Szeredi82547982005-09-09 13:10:38 -07001903 .fsync = fuse_dir_fsync,
Miklos Szeredib18da0c2011-12-13 11:58:49 +01001904 .unlocked_ioctl = fuse_dir_ioctl,
1905 .compat_ioctl = fuse_dir_compat_ioctl,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001906};
1907
Arjan van de Ven754661f2007-02-12 00:55:38 -08001908static const struct inode_operations fuse_common_inode_operations = {
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001909 .setattr = fuse_setattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001910 .permission = fuse_permission,
1911 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001912 .setxattr = fuse_setxattr,
1913 .getxattr = fuse_getxattr,
1914 .listxattr = fuse_listxattr,
1915 .removexattr = fuse_removexattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001916};
1917
Arjan van de Ven754661f2007-02-12 00:55:38 -08001918static const struct inode_operations fuse_symlink_inode_operations = {
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001919 .setattr = fuse_setattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001920 .follow_link = fuse_follow_link,
1921 .put_link = fuse_put_link,
1922 .readlink = generic_readlink,
1923 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001924 .setxattr = fuse_setxattr,
1925 .getxattr = fuse_getxattr,
1926 .listxattr = fuse_listxattr,
1927 .removexattr = fuse_removexattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001928};
1929
1930void fuse_init_common(struct inode *inode)
1931{
1932 inode->i_op = &fuse_common_inode_operations;
1933}
1934
1935void fuse_init_dir(struct inode *inode)
1936{
1937 inode->i_op = &fuse_dir_inode_operations;
1938 inode->i_fop = &fuse_dir_operations;
1939}
1940
1941void fuse_init_symlink(struct inode *inode)
1942{
1943 inode->i_op = &fuse_symlink_inode_operations;
1944}