blob: 131d14b604ef79bb94d100ded46b7ea36cd999b0 [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 Szeredi8cbdf1e2006-01-06 00:19:38 -0800185
Miklos Szeredie7c0a162011-03-21 13:58:06 +0100186 inode = ACCESS_ONCE(entry->d_inode);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800187 if (inode && is_bad_inode(inode))
Miklos Szeredie5e55582005-09-09 13:10:28 -0700188 return 0;
Miklos Szeredi0a0898c2006-07-30 03:04:10 -0700189 else if (fuse_dentry_time(entry) < get_jiffies_64()) {
Miklos Szeredie5e55582005-09-09 13:10:28 -0700190 int err;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700191 struct fuse_entry_out outarg;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800192 struct fuse_req *req;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100193 struct fuse_forget_link *forget;
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700194 u64 attr_version;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800195
Miklos Szeredi50322fe2006-02-28 16:59:03 -0800196 /* For negative dentries, always do a fresh lookup */
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800197 if (!inode)
198 return 0;
199
Al Viro0b728e12012-06-10 16:03:43 -0400200 if (flags & LOOKUP_RCU)
Miklos Szeredie7c0a162011-03-21 13:58:06 +0100201 return -ECHILD;
202
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800203 fc = get_fuse_conn(inode);
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400204 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700205 if (IS_ERR(req))
Miklos Szeredie5e55582005-09-09 13:10:28 -0700206 return 0;
207
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100208 forget = fuse_alloc_forget();
209 if (!forget) {
Miklos Szeredi2d510132006-11-25 11:09:20 -0800210 fuse_put_request(fc, req);
211 return 0;
212 }
213
Miklos Szeredi7dca9fd2007-11-28 16:21:59 -0800214 attr_version = fuse_get_attr_version(fc);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700215
Miklos Szeredie956edd2006-10-17 00:10:12 -0700216 parent = dget_parent(entry);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700217 fuse_lookup_init(fc, req, get_node_id(parent->d_inode),
218 &entry->d_name, &outarg);
Tejun Heob93f8582008-11-26 12:03:55 +0100219 fuse_request_send(fc, req);
Miklos Szeredie956edd2006-10-17 00:10:12 -0700220 dput(parent);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700221 err = req->out.h.error;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800222 fuse_put_request(fc, req);
Miklos Szeredi50322fe2006-02-28 16:59:03 -0800223 /* Zero nodeid is same as -ENOENT */
224 if (!err && !outarg.nodeid)
225 err = -ENOENT;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700226 if (!err) {
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800227 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700228 if (outarg.nodeid != get_node_id(inode)) {
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100229 fuse_queue_forget(fc, forget, outarg.nodeid, 1);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700230 return 0;
231 }
Miklos Szeredi8da5ff22006-10-17 00:10:08 -0700232 spin_lock(&fc->lock);
Miklos Szeredi1729a162008-11-26 12:03:54 +0100233 fi->nlookup++;
Miklos Szeredi8da5ff22006-10-17 00:10:08 -0700234 spin_unlock(&fc->lock);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700235 }
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100236 kfree(forget);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700237 if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700238 return 0;
239
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700240 fuse_change_attributes(inode, &outarg.attr,
241 entry_attr_timeout(&outarg),
242 attr_version);
243 fuse_change_entry_timeout(entry, &outarg);
Miklos Szeredi28420da2013-06-03 14:40:22 +0200244 } else if (inode) {
245 fc = get_fuse_conn(inode);
246 if (fc->readdirplus_auto) {
247 parent = dget_parent(entry);
248 fuse_advise_use_readdirplus(parent->d_inode);
249 dput(parent);
250 }
Miklos Szeredie5e55582005-09-09 13:10:28 -0700251 }
252 return 1;
253}
254
Miklos Szeredi8bfc0162006-01-16 22:14:28 -0800255static int invalid_nodeid(u64 nodeid)
Miklos Szeredi2827d0b22005-11-28 13:44:16 -0800256{
257 return !nodeid || nodeid == FUSE_ROOT_ID;
258}
259
Al Viro42695902009-02-20 05:59:13 +0000260const struct dentry_operations fuse_dentry_operations = {
Miklos Szeredie5e55582005-09-09 13:10:28 -0700261 .d_revalidate = fuse_dentry_revalidate,
262};
263
Timo Savolaa5bfffa2007-04-08 16:04:00 -0700264int fuse_valid_type(int m)
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800265{
266 return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) ||
267 S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m);
268}
269
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700270int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name,
271 struct fuse_entry_out *outarg, struct inode **inode)
272{
273 struct fuse_conn *fc = get_fuse_conn_super(sb);
274 struct fuse_req *req;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100275 struct fuse_forget_link *forget;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700276 u64 attr_version;
277 int err;
278
279 *inode = NULL;
280 err = -ENAMETOOLONG;
281 if (name->len > FUSE_NAME_MAX)
282 goto out;
283
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400284 req = fuse_get_req_nopages(fc);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700285 err = PTR_ERR(req);
286 if (IS_ERR(req))
287 goto out;
288
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100289 forget = fuse_alloc_forget();
290 err = -ENOMEM;
291 if (!forget) {
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700292 fuse_put_request(fc, req);
293 goto out;
294 }
295
296 attr_version = fuse_get_attr_version(fc);
297
298 fuse_lookup_init(fc, req, nodeid, name, outarg);
Tejun Heob93f8582008-11-26 12:03:55 +0100299 fuse_request_send(fc, req);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700300 err = req->out.h.error;
301 fuse_put_request(fc, req);
302 /* Zero nodeid is same as -ENOENT, but with valid timeout */
303 if (err || !outarg->nodeid)
304 goto out_put_forget;
305
306 err = -EIO;
307 if (!outarg->nodeid)
308 goto out_put_forget;
309 if (!fuse_valid_type(outarg->attr.mode))
310 goto out_put_forget;
311
312 *inode = fuse_iget(sb, outarg->nodeid, outarg->generation,
313 &outarg->attr, entry_attr_timeout(outarg),
314 attr_version);
315 err = -ENOMEM;
316 if (!*inode) {
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100317 fuse_queue_forget(fc, forget, outarg->nodeid, 1);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700318 goto out;
319 }
320 err = 0;
321
322 out_put_forget:
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100323 kfree(forget);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700324 out:
325 return err;
326}
327
Miklos Szeredi5835f332013-09-05 11:44:42 +0200328static struct dentry *fuse_materialise_dentry(struct dentry *dentry,
329 struct inode *inode)
330{
331 struct dentry *newent;
332
333 if (inode && S_ISDIR(inode->i_mode)) {
334 struct fuse_conn *fc = get_fuse_conn(inode);
335
336 mutex_lock(&fc->inst_mutex);
337 newent = d_materialise_unique(dentry, inode);
338 mutex_unlock(&fc->inst_mutex);
339 } else {
340 newent = d_materialise_unique(dentry, inode);
341 }
342
343 return newent;
344}
345
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800346static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
Al Viro00cd8dd2012-06-10 17:13:09 -0400347 unsigned int flags)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700348{
349 int err;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700350 struct fuse_entry_out outarg;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700351 struct inode *inode;
Miklos Szeredi0de62562008-07-25 01:48:59 -0700352 struct dentry *newent;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700353 bool outarg_valid = true;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700354
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700355 err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name,
356 &outarg, &inode);
357 if (err == -ENOENT) {
358 outarg_valid = false;
359 err = 0;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800360 }
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700361 if (err)
362 goto out_err;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800363
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700364 err = -EIO;
365 if (inode && get_node_id(inode) == FUSE_ROOT_ID)
366 goto out_iput;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700367
Miklos Szeredi5835f332013-09-05 11:44:42 +0200368 newent = fuse_materialise_dentry(entry, inode);
369 err = PTR_ERR(newent);
370 if (IS_ERR(newent))
371 goto out_err;
Miklos Szeredid2a85162006-10-17 00:10:11 -0700372
Miklos Szeredi0de62562008-07-25 01:48:59 -0700373 entry = newent ? newent : entry;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700374 if (outarg_valid)
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700375 fuse_change_entry_timeout(entry, &outarg);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800376 else
377 fuse_invalidate_entry_cache(entry);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700378
Feng Shuo4582a4a2013-01-15 11:23:28 +0800379 fuse_advise_use_readdirplus(dir);
Miklos Szeredi0de62562008-07-25 01:48:59 -0700380 return newent;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700381
382 out_iput:
383 iput(inode);
384 out_err:
385 return ERR_PTR(err);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700386}
387
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800388/*
389 * Atomic create+open operation
390 *
391 * If the filesystem doesn't support this, then fall back to separate
392 * 'mknod' + 'open' requests.
393 */
Al Virod9585272012-06-22 12:39:14 +0400394static int fuse_create_open(struct inode *dir, struct dentry *entry,
Al Viro30d90492012-06-22 12:40:19 +0400395 struct file *file, unsigned flags,
Al Virod9585272012-06-22 12:39:14 +0400396 umode_t mode, int *opened)
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800397{
398 int err;
399 struct inode *inode;
400 struct fuse_conn *fc = get_fuse_conn(dir);
401 struct fuse_req *req;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100402 struct fuse_forget_link *forget;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200403 struct fuse_create_in inarg;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800404 struct fuse_open_out outopen;
405 struct fuse_entry_out outentry;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800406 struct fuse_file *ff;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800407
Miklos Szerediaf109bc2012-08-15 13:01:24 +0200408 /* Userspace expects S_IFREG in create mode */
409 BUG_ON((mode & S_IFMT) != S_IFREG);
410
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100411 forget = fuse_alloc_forget();
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200412 err = -ENOMEM;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100413 if (!forget)
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200414 goto out_err;
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700415
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400416 req = fuse_get_req_nopages(fc);
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700417 err = PTR_ERR(req);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700418 if (IS_ERR(req))
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700419 goto out_put_forget_req;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800420
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700421 err = -ENOMEM;
Tejun Heoacf99432008-11-26 12:03:55 +0100422 ff = fuse_file_alloc(fc);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800423 if (!ff)
424 goto out_put_request;
425
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200426 if (!fc->dont_mask)
427 mode &= ~current_umask();
428
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800429 flags &= ~O_NOCTTY;
430 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700431 memset(&outentry, 0, sizeof(outentry));
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800432 inarg.flags = flags;
433 inarg.mode = mode;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200434 inarg.umask = current_umask();
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800435 req->in.h.opcode = FUSE_CREATE;
436 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800437 req->in.numargs = 2;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200438 req->in.args[0].size = fc->minor < 12 ? sizeof(struct fuse_open_in) :
439 sizeof(inarg);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800440 req->in.args[0].value = &inarg;
441 req->in.args[1].size = entry->d_name.len + 1;
442 req->in.args[1].value = entry->d_name.name;
443 req->out.numargs = 2;
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700444 if (fc->minor < 9)
445 req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
446 else
447 req->out.args[0].size = sizeof(outentry);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800448 req->out.args[0].value = &outentry;
449 req->out.args[1].size = sizeof(outopen);
450 req->out.args[1].value = &outopen;
Tejun Heob93f8582008-11-26 12:03:55 +0100451 fuse_request_send(fc, req);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800452 err = req->out.h.error;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200453 if (err)
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800454 goto out_free_ff;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800455
456 err = -EIO;
Miklos Szeredi2827d0b22005-11-28 13:44:16 -0800457 if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid))
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800458 goto out_free_ff;
459
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700460 fuse_put_request(fc, req);
Miklos Szeredic7b71432009-04-28 16:56:37 +0200461 ff->fh = outopen.fh;
462 ff->nodeid = outentry.nodeid;
463 ff->open_flags = outopen.open_flags;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800464 inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700465 &outentry.attr, entry_attr_timeout(&outentry), 0);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800466 if (!inode) {
467 flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
Miklos Szeredi8b0797a2009-04-28 16:56:39 +0200468 fuse_sync_release(ff, flags);
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100469 fuse_queue_forget(fc, forget, outentry.nodeid, 1);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200470 err = -ENOMEM;
471 goto out_err;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800472 }
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100473 kfree(forget);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800474 d_instantiate(entry, inode);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700475 fuse_change_entry_timeout(entry, &outentry);
Miklos Szeredi0952b2a2008-02-06 01:38:38 -0800476 fuse_invalidate_attr(dir);
Al Viro30d90492012-06-22 12:40:19 +0400477 err = finish_open(file, entry, generic_file_open, opened);
478 if (err) {
Miklos Szeredi8b0797a2009-04-28 16:56:39 +0200479 fuse_sync_release(ff, flags);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200480 } else {
481 file->private_data = fuse_file_get(ff);
482 fuse_finish_open(inode, file);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800483 }
Al Virod9585272012-06-22 12:39:14 +0400484 return err;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800485
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200486out_free_ff:
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800487 fuse_file_free(ff);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200488out_put_request:
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800489 fuse_put_request(fc, req);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200490out_put_forget_req:
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100491 kfree(forget);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200492out_err:
Al Virod9585272012-06-22 12:39:14 +0400493 return err;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200494}
495
496static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t);
Al Virod9585272012-06-22 12:39:14 +0400497static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
Al Viro30d90492012-06-22 12:40:19 +0400498 struct file *file, unsigned flags,
Al Virod9585272012-06-22 12:39:14 +0400499 umode_t mode, int *opened)
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200500{
501 int err;
502 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200503 struct dentry *res = NULL;
504
505 if (d_unhashed(entry)) {
Al Viro00cd8dd2012-06-10 17:13:09 -0400506 res = fuse_lookup(dir, entry, 0);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200507 if (IS_ERR(res))
Al Virod9585272012-06-22 12:39:14 +0400508 return PTR_ERR(res);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200509
510 if (res)
511 entry = res;
512 }
513
514 if (!(flags & O_CREAT) || entry->d_inode)
515 goto no_open;
516
517 /* Only creates */
Al Viro47237682012-06-10 05:01:45 -0400518 *opened |= FILE_CREATED;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200519
520 if (fc->no_create)
521 goto mknod;
522
Al Viro30d90492012-06-22 12:40:19 +0400523 err = fuse_create_open(dir, entry, file, flags, mode, opened);
Al Virod9585272012-06-22 12:39:14 +0400524 if (err == -ENOSYS) {
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200525 fc->no_create = 1;
526 goto mknod;
527 }
528out_dput:
529 dput(res);
Al Virod9585272012-06-22 12:39:14 +0400530 return err;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200531
532mknod:
533 err = fuse_mknod(dir, entry, mode, 0);
Al Virod9585272012-06-22 12:39:14 +0400534 if (err)
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200535 goto out_dput;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200536no_open:
Al Viroe45198a2012-06-10 06:48:09 -0400537 return finish_no_open(file, res);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800538}
539
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800540/*
541 * Code shared between mknod, mkdir, symlink and link
542 */
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700543static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
544 struct inode *dir, struct dentry *entry,
Al Viro541af6a2011-07-26 03:17:33 -0400545 umode_t mode)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700546{
547 struct fuse_entry_out outarg;
548 struct inode *inode;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700549 int err;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100550 struct fuse_forget_link *forget;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800551
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100552 forget = fuse_alloc_forget();
553 if (!forget) {
Miklos Szeredi2d510132006-11-25 11:09:20 -0800554 fuse_put_request(fc, req);
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100555 return -ENOMEM;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800556 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700557
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700558 memset(&outarg, 0, sizeof(outarg));
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700559 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700560 req->out.numargs = 1;
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700561 if (fc->minor < 9)
562 req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
563 else
564 req->out.args[0].size = sizeof(outarg);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700565 req->out.args[0].value = &outarg;
Tejun Heob93f8582008-11-26 12:03:55 +0100566 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700567 err = req->out.h.error;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800568 fuse_put_request(fc, req);
569 if (err)
570 goto out_put_forget_req;
571
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800572 err = -EIO;
573 if (invalid_nodeid(outarg.nodeid))
Miklos Szeredi2d510132006-11-25 11:09:20 -0800574 goto out_put_forget_req;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800575
576 if ((outarg.attr.mode ^ mode) & S_IFMT)
Miklos Szeredi2d510132006-11-25 11:09:20 -0800577 goto out_put_forget_req;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800578
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700579 inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700580 &outarg.attr, entry_attr_timeout(&outarg), 0);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700581 if (!inode) {
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100582 fuse_queue_forget(fc, forget, outarg.nodeid, 1);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700583 return -ENOMEM;
584 }
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100585 kfree(forget);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700586
Miklos Szeredid2a85162006-10-17 00:10:11 -0700587 if (S_ISDIR(inode->i_mode)) {
588 struct dentry *alias;
589 mutex_lock(&fc->inst_mutex);
590 alias = d_find_alias(inode);
591 if (alias) {
592 /* New directory must have moved since mkdir */
593 mutex_unlock(&fc->inst_mutex);
594 dput(alias);
595 iput(inode);
596 return -EBUSY;
597 }
598 d_instantiate(entry, inode);
599 mutex_unlock(&fc->inst_mutex);
600 } else
601 d_instantiate(entry, inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700602
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700603 fuse_change_entry_timeout(entry, &outarg);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700604 fuse_invalidate_attr(dir);
605 return 0;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800606
Miklos Szeredi2d510132006-11-25 11:09:20 -0800607 out_put_forget_req:
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100608 kfree(forget);
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800609 return err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700610}
611
Al Viro1a67aaf2011-07-26 01:52:52 -0400612static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700613 dev_t rdev)
614{
615 struct fuse_mknod_in inarg;
616 struct fuse_conn *fc = get_fuse_conn(dir);
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400617 struct fuse_req *req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700618 if (IS_ERR(req))
619 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700620
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200621 if (!fc->dont_mask)
622 mode &= ~current_umask();
623
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700624 memset(&inarg, 0, sizeof(inarg));
625 inarg.mode = mode;
626 inarg.rdev = new_encode_dev(rdev);
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200627 inarg.umask = current_umask();
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700628 req->in.h.opcode = FUSE_MKNOD;
629 req->in.numargs = 2;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200630 req->in.args[0].size = fc->minor < 12 ? FUSE_COMPAT_MKNOD_IN_SIZE :
631 sizeof(inarg);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700632 req->in.args[0].value = &inarg;
633 req->in.args[1].size = entry->d_name.len + 1;
634 req->in.args[1].value = entry->d_name.name;
635 return create_new_entry(fc, req, dir, entry, mode);
636}
637
Al Viro4acdaf22011-07-26 01:42:34 -0400638static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode,
Al Viroebfc3b42012-06-10 18:05:36 -0400639 bool excl)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700640{
641 return fuse_mknod(dir, entry, mode, 0);
642}
643
Al Viro18bb1db2011-07-26 01:41:39 -0400644static int fuse_mkdir(struct inode *dir, struct dentry *entry, umode_t mode)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700645{
646 struct fuse_mkdir_in inarg;
647 struct fuse_conn *fc = get_fuse_conn(dir);
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400648 struct fuse_req *req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700649 if (IS_ERR(req))
650 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700651
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200652 if (!fc->dont_mask)
653 mode &= ~current_umask();
654
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700655 memset(&inarg, 0, sizeof(inarg));
656 inarg.mode = mode;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200657 inarg.umask = current_umask();
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700658 req->in.h.opcode = FUSE_MKDIR;
659 req->in.numargs = 2;
660 req->in.args[0].size = sizeof(inarg);
661 req->in.args[0].value = &inarg;
662 req->in.args[1].size = entry->d_name.len + 1;
663 req->in.args[1].value = entry->d_name.name;
664 return create_new_entry(fc, req, dir, entry, S_IFDIR);
665}
666
667static int fuse_symlink(struct inode *dir, struct dentry *entry,
668 const char *link)
669{
670 struct fuse_conn *fc = get_fuse_conn(dir);
671 unsigned len = strlen(link) + 1;
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400672 struct fuse_req *req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700673 if (IS_ERR(req))
674 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700675
676 req->in.h.opcode = FUSE_SYMLINK;
677 req->in.numargs = 2;
678 req->in.args[0].size = entry->d_name.len + 1;
679 req->in.args[0].value = entry->d_name.name;
680 req->in.args[1].size = len;
681 req->in.args[1].value = link;
682 return create_new_entry(fc, req, dir, entry, S_IFLNK);
683}
684
685static int fuse_unlink(struct inode *dir, struct dentry *entry)
686{
687 int err;
688 struct fuse_conn *fc = get_fuse_conn(dir);
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400689 struct fuse_req *req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700690 if (IS_ERR(req))
691 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700692
693 req->in.h.opcode = FUSE_UNLINK;
694 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700695 req->in.numargs = 1;
696 req->in.args[0].size = entry->d_name.len + 1;
697 req->in.args[0].value = entry->d_name.name;
Tejun Heob93f8582008-11-26 12:03:55 +0100698 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700699 err = req->out.h.error;
700 fuse_put_request(fc, req);
701 if (!err) {
702 struct inode *inode = entry->d_inode;
Miklos Szerediac45d612012-03-05 15:48:11 +0100703 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700704
Miklos Szerediac45d612012-03-05 15:48:11 +0100705 spin_lock(&fc->lock);
706 fi->attr_version = ++fc->attr_version;
Miklos Szeredidfca7ce2013-02-04 15:57:42 +0100707 /*
708 * If i_nlink == 0 then unlink doesn't make sense, yet this can
709 * happen if userspace filesystem is careless. It would be
710 * difficult to enforce correct nlink usage so just ignore this
711 * condition here
712 */
713 if (inode->i_nlink > 0)
714 drop_nlink(inode);
Miklos Szerediac45d612012-03-05 15:48:11 +0100715 spin_unlock(&fc->lock);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700716 fuse_invalidate_attr(inode);
717 fuse_invalidate_attr(dir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800718 fuse_invalidate_entry_cache(entry);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700719 } else if (err == -EINTR)
720 fuse_invalidate_entry(entry);
721 return err;
722}
723
724static int fuse_rmdir(struct inode *dir, struct dentry *entry)
725{
726 int err;
727 struct fuse_conn *fc = get_fuse_conn(dir);
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400728 struct fuse_req *req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700729 if (IS_ERR(req))
730 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700731
732 req->in.h.opcode = FUSE_RMDIR;
733 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700734 req->in.numargs = 1;
735 req->in.args[0].size = entry->d_name.len + 1;
736 req->in.args[0].value = entry->d_name.name;
Tejun Heob93f8582008-11-26 12:03:55 +0100737 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700738 err = req->out.h.error;
739 fuse_put_request(fc, req);
740 if (!err) {
Dave Hansence71ec32006-09-30 23:29:06 -0700741 clear_nlink(entry->d_inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700742 fuse_invalidate_attr(dir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800743 fuse_invalidate_entry_cache(entry);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700744 } else if (err == -EINTR)
745 fuse_invalidate_entry(entry);
746 return err;
747}
748
749static int fuse_rename(struct inode *olddir, struct dentry *oldent,
750 struct inode *newdir, struct dentry *newent)
751{
752 int err;
753 struct fuse_rename_in inarg;
754 struct fuse_conn *fc = get_fuse_conn(olddir);
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400755 struct fuse_req *req = fuse_get_req_nopages(fc);
Sage Weile4eaac02011-05-24 13:06:07 -0700756
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700757 if (IS_ERR(req))
758 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700759
760 memset(&inarg, 0, sizeof(inarg));
761 inarg.newdir = get_node_id(newdir);
762 req->in.h.opcode = FUSE_RENAME;
763 req->in.h.nodeid = get_node_id(olddir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700764 req->in.numargs = 3;
765 req->in.args[0].size = sizeof(inarg);
766 req->in.args[0].value = &inarg;
767 req->in.args[1].size = oldent->d_name.len + 1;
768 req->in.args[1].value = oldent->d_name.name;
769 req->in.args[2].size = newent->d_name.len + 1;
770 req->in.args[2].value = newent->d_name.name;
Tejun Heob93f8582008-11-26 12:03:55 +0100771 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700772 err = req->out.h.error;
773 fuse_put_request(fc, req);
774 if (!err) {
Miklos Szeredi08b63302007-11-28 16:22:03 -0800775 /* ctime changes */
776 fuse_invalidate_attr(oldent->d_inode);
777
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700778 fuse_invalidate_attr(olddir);
779 if (olddir != newdir)
780 fuse_invalidate_attr(newdir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800781
782 /* newent will end up negative */
Miklos Szeredi5219f342009-11-04 10:24:52 +0100783 if (newent->d_inode) {
784 fuse_invalidate_attr(newent->d_inode);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800785 fuse_invalidate_entry_cache(newent);
Miklos Szeredi5219f342009-11-04 10:24:52 +0100786 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700787 } else if (err == -EINTR) {
788 /* If request was interrupted, DEITY only knows if the
789 rename actually took place. If the invalidation
790 fails (e.g. some process has CWD under the renamed
791 directory), then there can be inconsistency between
792 the dcache and the real filesystem. Tough luck. */
793 fuse_invalidate_entry(oldent);
794 if (newent->d_inode)
795 fuse_invalidate_entry(newent);
796 }
797
798 return err;
799}
800
801static int fuse_link(struct dentry *entry, struct inode *newdir,
802 struct dentry *newent)
803{
804 int err;
805 struct fuse_link_in inarg;
806 struct inode *inode = entry->d_inode;
807 struct fuse_conn *fc = get_fuse_conn(inode);
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400808 struct fuse_req *req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700809 if (IS_ERR(req))
810 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700811
812 memset(&inarg, 0, sizeof(inarg));
813 inarg.oldnodeid = get_node_id(inode);
814 req->in.h.opcode = FUSE_LINK;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700815 req->in.numargs = 2;
816 req->in.args[0].size = sizeof(inarg);
817 req->in.args[0].value = &inarg;
818 req->in.args[1].size = newent->d_name.len + 1;
819 req->in.args[1].value = newent->d_name.name;
820 err = create_new_entry(fc, req, newdir, newent, inode->i_mode);
821 /* Contrary to "normal" filesystems it can happen that link
822 makes two "logical" inodes point to the same "physical"
823 inode. We invalidate the attributes of the old one, so it
824 will reflect changes in the backing inode (link count,
825 etc.)
826 */
Miklos Szerediac45d612012-03-05 15:48:11 +0100827 if (!err) {
828 struct fuse_inode *fi = get_fuse_inode(inode);
829
830 spin_lock(&fc->lock);
831 fi->attr_version = ++fc->attr_version;
832 inc_nlink(inode);
833 spin_unlock(&fc->lock);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700834 fuse_invalidate_attr(inode);
Miklos Szerediac45d612012-03-05 15:48:11 +0100835 } else if (err == -EINTR) {
836 fuse_invalidate_attr(inode);
837 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700838 return err;
839}
840
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700841static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
842 struct kstat *stat)
843{
Miklos Szeredi203627b2012-05-10 19:49:38 +0400844 unsigned int blkbits;
845
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700846 stat->dev = inode->i_sb->s_dev;
847 stat->ino = attr->ino;
848 stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
849 stat->nlink = attr->nlink;
Eric W. Biederman499dcf22012-02-07 16:26:03 -0800850 stat->uid = make_kuid(&init_user_ns, attr->uid);
851 stat->gid = make_kgid(&init_user_ns, attr->gid);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700852 stat->rdev = inode->i_rdev;
853 stat->atime.tv_sec = attr->atime;
854 stat->atime.tv_nsec = attr->atimensec;
855 stat->mtime.tv_sec = attr->mtime;
856 stat->mtime.tv_nsec = attr->mtimensec;
857 stat->ctime.tv_sec = attr->ctime;
858 stat->ctime.tv_nsec = attr->ctimensec;
859 stat->size = attr->size;
860 stat->blocks = attr->blocks;
Miklos Szeredi203627b2012-05-10 19:49:38 +0400861
862 if (attr->blksize != 0)
863 blkbits = ilog2(attr->blksize);
864 else
865 blkbits = inode->i_sb->s_blocksize_bits;
866
867 stat->blksize = 1 << blkbits;
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700868}
869
Miklos Szeredic79e3222007-10-18 03:06:59 -0700870static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
871 struct file *file)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700872{
873 int err;
Miklos Szeredic79e3222007-10-18 03:06:59 -0700874 struct fuse_getattr_in inarg;
875 struct fuse_attr_out outarg;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700876 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700877 struct fuse_req *req;
878 u64 attr_version;
879
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400880 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700881 if (IS_ERR(req))
882 return PTR_ERR(req);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700883
Miklos Szeredi7dca9fd2007-11-28 16:21:59 -0800884 attr_version = fuse_get_attr_version(fc);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700885
Miklos Szeredic79e3222007-10-18 03:06:59 -0700886 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700887 memset(&outarg, 0, sizeof(outarg));
Miklos Szeredic79e3222007-10-18 03:06:59 -0700888 /* Directories have separate file-handle space */
889 if (file && S_ISREG(inode->i_mode)) {
890 struct fuse_file *ff = file->private_data;
891
892 inarg.getattr_flags |= FUSE_GETATTR_FH;
893 inarg.fh = ff->fh;
894 }
Miklos Szeredie5e55582005-09-09 13:10:28 -0700895 req->in.h.opcode = FUSE_GETATTR;
896 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredic79e3222007-10-18 03:06:59 -0700897 req->in.numargs = 1;
898 req->in.args[0].size = sizeof(inarg);
899 req->in.args[0].value = &inarg;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700900 req->out.numargs = 1;
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700901 if (fc->minor < 9)
902 req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
903 else
904 req->out.args[0].size = sizeof(outarg);
Miklos Szeredic79e3222007-10-18 03:06:59 -0700905 req->out.args[0].value = &outarg;
Tejun Heob93f8582008-11-26 12:03:55 +0100906 fuse_request_send(fc, req);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700907 err = req->out.h.error;
908 fuse_put_request(fc, req);
909 if (!err) {
Miklos Szeredic79e3222007-10-18 03:06:59 -0700910 if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
Miklos Szeredie5e55582005-09-09 13:10:28 -0700911 make_bad_inode(inode);
912 err = -EIO;
913 } else {
Miklos Szeredic79e3222007-10-18 03:06:59 -0700914 fuse_change_attributes(inode, &outarg.attr,
915 attr_timeout(&outarg),
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700916 attr_version);
917 if (stat)
Miklos Szeredic79e3222007-10-18 03:06:59 -0700918 fuse_fillattr(inode, &outarg.attr, stat);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700919 }
920 }
921 return err;
922}
923
Miklos Szeredibcb4be82007-11-28 16:21:59 -0800924int fuse_update_attributes(struct inode *inode, struct kstat *stat,
925 struct file *file, bool *refreshed)
926{
927 struct fuse_inode *fi = get_fuse_inode(inode);
928 int err;
929 bool r;
930
931 if (fi->i_time < get_jiffies_64()) {
932 r = true;
933 err = fuse_do_getattr(inode, stat, file);
934 } else {
935 r = false;
936 err = 0;
937 if (stat) {
938 generic_fillattr(inode, stat);
939 stat->mode = fi->orig_i_mode;
Pavel Shilovsky45c72cd2012-05-10 19:49:38 +0400940 stat->ino = fi->orig_ino;
Miklos Szeredibcb4be82007-11-28 16:21:59 -0800941 }
942 }
943
944 if (refreshed != NULL)
945 *refreshed = r;
946
947 return err;
948}
949
John Muir3b463ae2009-05-31 11:13:57 -0400950int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid,
John Muir451d0f52011-12-06 21:50:06 +0100951 u64 child_nodeid, struct qstr *name)
John Muir3b463ae2009-05-31 11:13:57 -0400952{
953 int err = -ENOTDIR;
954 struct inode *parent;
955 struct dentry *dir;
956 struct dentry *entry;
957
958 parent = ilookup5(sb, parent_nodeid, fuse_inode_eq, &parent_nodeid);
959 if (!parent)
960 return -ENOENT;
961
962 mutex_lock(&parent->i_mutex);
963 if (!S_ISDIR(parent->i_mode))
964 goto unlock;
965
966 err = -ENOENT;
967 dir = d_find_alias(parent);
968 if (!dir)
969 goto unlock;
970
971 entry = d_lookup(dir, name);
972 dput(dir);
973 if (!entry)
974 goto unlock;
975
976 fuse_invalidate_attr(parent);
977 fuse_invalidate_entry(entry);
John Muir451d0f52011-12-06 21:50:06 +0100978
979 if (child_nodeid != 0 && entry->d_inode) {
980 mutex_lock(&entry->d_inode->i_mutex);
981 if (get_node_id(entry->d_inode) != child_nodeid) {
982 err = -ENOENT;
983 goto badentry;
984 }
985 if (d_mountpoint(entry)) {
986 err = -EBUSY;
987 goto badentry;
988 }
989 if (S_ISDIR(entry->d_inode->i_mode)) {
990 shrink_dcache_parent(entry);
991 if (!simple_empty(entry)) {
992 err = -ENOTEMPTY;
993 goto badentry;
994 }
995 entry->d_inode->i_flags |= S_DEAD;
996 }
997 dont_mount(entry);
998 clear_nlink(entry->d_inode);
999 err = 0;
1000 badentry:
1001 mutex_unlock(&entry->d_inode->i_mutex);
1002 if (!err)
1003 d_delete(entry);
1004 } else {
1005 err = 0;
1006 }
John Muir3b463ae2009-05-31 11:13:57 -04001007 dput(entry);
John Muir3b463ae2009-05-31 11:13:57 -04001008
1009 unlock:
1010 mutex_unlock(&parent->i_mutex);
1011 iput(parent);
1012 return err;
1013}
1014
Miklos Szeredi87729a52005-09-09 13:10:34 -07001015/*
1016 * Calling into a user-controlled filesystem gives the filesystem
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001017 * daemon ptrace-like capabilities over the current process. This
Miklos Szeredi87729a52005-09-09 13:10:34 -07001018 * means, that the filesystem daemon is able to record the exact
1019 * filesystem operations performed, and can also control the behavior
1020 * of the requester process in otherwise impossible ways. For example
1021 * it can delay the operation for arbitrary length of time allowing
1022 * DoS against the requester.
1023 *
1024 * For this reason only those processes can call into the filesystem,
1025 * for which the owner of the mount has ptrace privilege. This
1026 * excludes processes started by other users, suid or sgid processes.
1027 */
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001028int fuse_allow_current_process(struct fuse_conn *fc)
Miklos Szeredi87729a52005-09-09 13:10:34 -07001029{
David Howellsc69e8d92008-11-14 10:39:19 +11001030 const struct cred *cred;
David Howellsc69e8d92008-11-14 10:39:19 +11001031
Miklos Szeredi87729a52005-09-09 13:10:34 -07001032 if (fc->flags & FUSE_ALLOW_OTHER)
1033 return 1;
1034
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001035 cred = current_cred();
Eric W. Biederman499dcf22012-02-07 16:26:03 -08001036 if (uid_eq(cred->euid, fc->user_id) &&
1037 uid_eq(cred->suid, fc->user_id) &&
1038 uid_eq(cred->uid, fc->user_id) &&
1039 gid_eq(cred->egid, fc->group_id) &&
1040 gid_eq(cred->sgid, fc->group_id) &&
1041 gid_eq(cred->gid, fc->group_id))
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001042 return 1;
Miklos Szeredi87729a52005-09-09 13:10:34 -07001043
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001044 return 0;
Miklos Szeredi87729a52005-09-09 13:10:34 -07001045}
1046
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001047static int fuse_access(struct inode *inode, int mask)
1048{
1049 struct fuse_conn *fc = get_fuse_conn(inode);
1050 struct fuse_req *req;
1051 struct fuse_access_in inarg;
1052 int err;
1053
1054 if (fc->no_access)
1055 return 0;
1056
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001057 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001058 if (IS_ERR(req))
1059 return PTR_ERR(req);
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001060
1061 memset(&inarg, 0, sizeof(inarg));
Al Viroe6305c42008-07-15 21:03:57 -04001062 inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC);
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001063 req->in.h.opcode = FUSE_ACCESS;
1064 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001065 req->in.numargs = 1;
1066 req->in.args[0].size = sizeof(inarg);
1067 req->in.args[0].value = &inarg;
Tejun Heob93f8582008-11-26 12:03:55 +01001068 fuse_request_send(fc, req);
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001069 err = req->out.h.error;
1070 fuse_put_request(fc, req);
1071 if (err == -ENOSYS) {
1072 fc->no_access = 1;
1073 err = 0;
1074 }
1075 return err;
1076}
1077
Al Viro10556cb2011-06-20 19:28:19 -04001078static int fuse_perm_getattr(struct inode *inode, int mask)
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001079{
Al Viro10556cb2011-06-20 19:28:19 -04001080 if (mask & MAY_NOT_BLOCK)
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001081 return -ECHILD;
1082
1083 return fuse_do_getattr(inode, NULL, NULL);
1084}
1085
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001086/*
1087 * Check permission. The two basic access models of FUSE are:
1088 *
1089 * 1) Local access checking ('default_permissions' mount option) based
1090 * on file mode. This is the plain old disk filesystem permission
1091 * modell.
1092 *
1093 * 2) "Remote" access checking, where server is responsible for
1094 * checking permission in each inode operation. An exception to this
1095 * is if ->permission() was invoked from sys_access() in which case an
1096 * access request is sent. Execute permission is still checked
1097 * locally based on file mode.
1098 */
Al Viro10556cb2011-06-20 19:28:19 -04001099static int fuse_permission(struct inode *inode, int mask)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001100{
1101 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi244f6382007-10-16 23:31:02 -07001102 bool refreshed = false;
1103 int err = 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001104
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001105 if (!fuse_allow_current_process(fc))
Miklos Szeredie5e55582005-09-09 13:10:28 -07001106 return -EACCES;
Miklos Szeredi244f6382007-10-16 23:31:02 -07001107
1108 /*
Miklos Szeredie8e96152007-10-16 23:31:06 -07001109 * If attributes are needed, refresh them before proceeding
Miklos Szeredi244f6382007-10-16 23:31:02 -07001110 */
Miklos Szeredie8e96152007-10-16 23:31:06 -07001111 if ((fc->flags & FUSE_DEFAULT_PERMISSIONS) ||
1112 ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001113 struct fuse_inode *fi = get_fuse_inode(inode);
1114
1115 if (fi->i_time < get_jiffies_64()) {
1116 refreshed = true;
1117
Al Viro10556cb2011-06-20 19:28:19 -04001118 err = fuse_perm_getattr(inode, mask);
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001119 if (err)
1120 return err;
1121 }
Miklos Szeredi244f6382007-10-16 23:31:02 -07001122 }
1123
1124 if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
Al Viro2830ba72011-06-20 19:16:29 -04001125 err = generic_permission(inode, mask);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001126
1127 /* If permission is denied, try to refresh file
1128 attributes. This is also needed, because the root
1129 node will at first have no permissions */
Miklos Szeredi244f6382007-10-16 23:31:02 -07001130 if (err == -EACCES && !refreshed) {
Al Viro10556cb2011-06-20 19:28:19 -04001131 err = fuse_perm_getattr(inode, mask);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001132 if (!err)
Al Viro2830ba72011-06-20 19:16:29 -04001133 err = generic_permission(inode, mask);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001134 }
1135
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001136 /* Note: the opposite of the above test does not
1137 exist. So if permissions are revoked this won't be
1138 noticed immediately, only after the attribute
1139 timeout has expired */
Eric Paris9cfcac82010-07-23 11:43:51 -04001140 } else if (mask & (MAY_ACCESS | MAY_CHDIR)) {
Al Viro10556cb2011-06-20 19:28:19 -04001141 if (mask & MAY_NOT_BLOCK)
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001142 return -ECHILD;
1143
Miklos Szeredie8e96152007-10-16 23:31:06 -07001144 err = fuse_access(inode, mask);
1145 } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
1146 if (!(inode->i_mode & S_IXUGO)) {
1147 if (refreshed)
1148 return -EACCES;
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001149
Al Viro10556cb2011-06-20 19:28:19 -04001150 err = fuse_perm_getattr(inode, mask);
Miklos Szeredie8e96152007-10-16 23:31:06 -07001151 if (!err && !(inode->i_mode & S_IXUGO))
1152 return -EACCES;
1153 }
Miklos Szeredie5e55582005-09-09 13:10:28 -07001154 }
Miklos Szeredi244f6382007-10-16 23:31:02 -07001155 return err;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001156}
1157
1158static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
Al Viro8d3af7f2013-05-18 03:03:58 -04001159 struct dir_context *ctx)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001160{
1161 while (nbytes >= FUSE_NAME_OFFSET) {
1162 struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
1163 size_t reclen = FUSE_DIRENT_SIZE(dirent);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001164 if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
1165 return -EIO;
1166 if (reclen > nbytes)
1167 break;
1168
Al Viro8d3af7f2013-05-18 03:03:58 -04001169 if (!dir_emit(ctx, dirent->name, dirent->namelen,
1170 dirent->ino, dirent->type))
Miklos Szeredie5e55582005-09-09 13:10:28 -07001171 break;
1172
1173 buf += reclen;
1174 nbytes -= reclen;
Al Viro8d3af7f2013-05-18 03:03:58 -04001175 ctx->pos = dirent->off;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001176 }
1177
1178 return 0;
1179}
1180
Anand V. Avati0b05b182012-08-19 08:53:23 -04001181static int fuse_direntplus_link(struct file *file,
1182 struct fuse_direntplus *direntplus,
1183 u64 attr_version)
1184{
1185 int err;
1186 struct fuse_entry_out *o = &direntplus->entry_out;
1187 struct fuse_dirent *dirent = &direntplus->dirent;
1188 struct dentry *parent = file->f_path.dentry;
1189 struct qstr name = QSTR_INIT(dirent->name, dirent->namelen);
1190 struct dentry *dentry;
1191 struct dentry *alias;
1192 struct inode *dir = parent->d_inode;
1193 struct fuse_conn *fc;
1194 struct inode *inode;
1195
1196 if (!o->nodeid) {
1197 /*
1198 * Unlike in the case of fuse_lookup, zero nodeid does not mean
1199 * ENOENT. Instead, it only means the userspace filesystem did
1200 * not want to return attributes/handle for this entry.
1201 *
1202 * So do nothing.
1203 */
1204 return 0;
1205 }
1206
1207 if (name.name[0] == '.') {
1208 /*
1209 * We could potentially refresh the attributes of the directory
1210 * and its parent?
1211 */
1212 if (name.len == 1)
1213 return 0;
1214 if (name.name[1] == '.' && name.len == 2)
1215 return 0;
1216 }
Miklos Szeredia28ef452013-07-17 14:53:53 +02001217
1218 if (invalid_nodeid(o->nodeid))
1219 return -EIO;
1220 if (!fuse_valid_type(o->attr.mode))
1221 return -EIO;
1222
Anand V. Avati0b05b182012-08-19 08:53:23 -04001223 fc = get_fuse_conn(dir);
1224
1225 name.hash = full_name_hash(name.name, name.len);
1226 dentry = d_lookup(parent, &name);
Niels de Vos53ce9a32013-07-17 14:53:53 +02001227 if (dentry) {
Anand V. Avati0b05b182012-08-19 08:53:23 -04001228 inode = dentry->d_inode;
Niels de Vos53ce9a32013-07-17 14:53:53 +02001229 if (!inode) {
1230 d_drop(dentry);
Miklos Szeredia28ef452013-07-17 14:53:53 +02001231 } else if (get_node_id(inode) != o->nodeid ||
1232 ((o->attr.mode ^ inode->i_mode) & S_IFMT)) {
Niels de Vos53ce9a32013-07-17 14:53:53 +02001233 err = d_invalidate(dentry);
1234 if (err)
1235 goto out;
Miklos Szeredia28ef452013-07-17 14:53:53 +02001236 } else if (is_bad_inode(inode)) {
1237 err = -EIO;
1238 goto out;
Niels de Vos53ce9a32013-07-17 14:53:53 +02001239 } else {
Anand V. Avati0b05b182012-08-19 08:53:23 -04001240 struct fuse_inode *fi;
1241 fi = get_fuse_inode(inode);
1242 spin_lock(&fc->lock);
1243 fi->nlookup++;
1244 spin_unlock(&fc->lock);
1245
Miklos Szeredifa2b7212013-07-17 14:53:53 +02001246 fuse_change_attributes(inode, &o->attr,
1247 entry_attr_timeout(o),
1248 attr_version);
1249
Anand V. Avati0b05b182012-08-19 08:53:23 -04001250 /*
1251 * The other branch to 'found' comes via fuse_iget()
1252 * which bumps nlookup inside
1253 */
1254 goto found;
1255 }
Anand V. Avati0b05b182012-08-19 08:53:23 -04001256 dput(dentry);
Anand V. Avati0b05b182012-08-19 08:53:23 -04001257 }
1258
1259 dentry = d_alloc(parent, &name);
1260 err = -ENOMEM;
1261 if (!dentry)
1262 goto out;
1263
1264 inode = fuse_iget(dir->i_sb, o->nodeid, o->generation,
1265 &o->attr, entry_attr_timeout(o), attr_version);
1266 if (!inode)
1267 goto out;
1268
Miklos Szeredi5835f332013-09-05 11:44:42 +02001269 alias = fuse_materialise_dentry(dentry, inode);
1270 err = PTR_ERR(alias);
1271 if (IS_ERR(alias))
1272 goto out;
Miklos Szeredi29149412013-07-17 14:53:53 +02001273
Anand V. Avati0b05b182012-08-19 08:53:23 -04001274 if (alias) {
1275 dput(dentry);
1276 dentry = alias;
1277 }
1278
1279found:
Anand V. Avati0b05b182012-08-19 08:53:23 -04001280 fuse_change_entry_timeout(dentry, o);
1281
1282 err = 0;
1283out:
Miklos Szeredic7263bc2013-07-17 14:53:54 +02001284 dput(dentry);
Anand V. Avati0b05b182012-08-19 08:53:23 -04001285 return err;
1286}
1287
1288static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file,
Al Viro8d3af7f2013-05-18 03:03:58 -04001289 struct dir_context *ctx, u64 attr_version)
Anand V. Avati0b05b182012-08-19 08:53:23 -04001290{
1291 struct fuse_direntplus *direntplus;
1292 struct fuse_dirent *dirent;
1293 size_t reclen;
1294 int over = 0;
1295 int ret;
1296
1297 while (nbytes >= FUSE_NAME_OFFSET_DIRENTPLUS) {
1298 direntplus = (struct fuse_direntplus *) buf;
1299 dirent = &direntplus->dirent;
1300 reclen = FUSE_DIRENTPLUS_SIZE(direntplus);
1301
1302 if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
1303 return -EIO;
1304 if (reclen > nbytes)
1305 break;
1306
1307 if (!over) {
1308 /* We fill entries into dstbuf only as much as
1309 it can hold. But we still continue iterating
1310 over remaining entries to link them. If not,
1311 we need to send a FORGET for each of those
1312 which we did not link.
1313 */
Al Viro8d3af7f2013-05-18 03:03:58 -04001314 over = !dir_emit(ctx, dirent->name, dirent->namelen,
1315 dirent->ino, dirent->type);
1316 ctx->pos = dirent->off;
Anand V. Avati0b05b182012-08-19 08:53:23 -04001317 }
1318
1319 buf += reclen;
1320 nbytes -= reclen;
1321
1322 ret = fuse_direntplus_link(file, direntplus, attr_version);
1323 if (ret)
1324 fuse_force_forget(file, direntplus->entry_out.nodeid);
1325 }
1326
1327 return 0;
1328}
1329
Al Viro8d3af7f2013-05-18 03:03:58 -04001330static int fuse_readdir(struct file *file, struct dir_context *ctx)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001331{
Feng Shuo4582a4a2013-01-15 11:23:28 +08001332 int plus, err;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001333 size_t nbytes;
1334 struct page *page;
Al Viro496ad9a2013-01-23 17:07:38 -05001335 struct inode *inode = file_inode(file);
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001336 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi248d86e2006-01-06 00:19:39 -08001337 struct fuse_req *req;
Anand V. Avati0b05b182012-08-19 08:53:23 -04001338 u64 attr_version = 0;
Miklos Szeredi248d86e2006-01-06 00:19:39 -08001339
1340 if (is_bad_inode(inode))
1341 return -EIO;
1342
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001343 req = fuse_get_req(fc, 1);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001344 if (IS_ERR(req))
1345 return PTR_ERR(req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001346
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001347 page = alloc_page(GFP_KERNEL);
1348 if (!page) {
1349 fuse_put_request(fc, req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001350 return -ENOMEM;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001351 }
Feng Shuo4582a4a2013-01-15 11:23:28 +08001352
Al Viro8d3af7f2013-05-18 03:03:58 -04001353 plus = fuse_use_readdirplus(inode, ctx);
Miklos Szeredif4975c62009-04-02 14:25:34 +02001354 req->out.argpages = 1;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001355 req->num_pages = 1;
1356 req->pages[0] = page;
Maxim Patlasov85f40ae2012-10-26 19:49:33 +04001357 req->page_descs[0].length = PAGE_SIZE;
Feng Shuo4582a4a2013-01-15 11:23:28 +08001358 if (plus) {
Anand V. Avati0b05b182012-08-19 08:53:23 -04001359 attr_version = fuse_get_attr_version(fc);
Al Viro8d3af7f2013-05-18 03:03:58 -04001360 fuse_read_fill(req, file, ctx->pos, PAGE_SIZE,
Anand V. Avati0b05b182012-08-19 08:53:23 -04001361 FUSE_READDIRPLUS);
1362 } else {
Al Viro8d3af7f2013-05-18 03:03:58 -04001363 fuse_read_fill(req, file, ctx->pos, PAGE_SIZE,
Anand V. Avati0b05b182012-08-19 08:53:23 -04001364 FUSE_READDIR);
1365 }
Tejun Heob93f8582008-11-26 12:03:55 +01001366 fuse_request_send(fc, req);
Miklos Szeredi361b1eb52006-01-16 22:14:45 -08001367 nbytes = req->out.args[0].size;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001368 err = req->out.h.error;
1369 fuse_put_request(fc, req);
Anand V. Avati0b05b182012-08-19 08:53:23 -04001370 if (!err) {
Feng Shuo4582a4a2013-01-15 11:23:28 +08001371 if (plus) {
Anand V. Avati0b05b182012-08-19 08:53:23 -04001372 err = parse_dirplusfile(page_address(page), nbytes,
Al Viro8d3af7f2013-05-18 03:03:58 -04001373 file, ctx,
Anand V. Avati0b05b182012-08-19 08:53:23 -04001374 attr_version);
1375 } else {
1376 err = parse_dirfile(page_address(page), nbytes, file,
Al Viro8d3af7f2013-05-18 03:03:58 -04001377 ctx);
Anand V. Avati0b05b182012-08-19 08:53:23 -04001378 }
1379 }
Miklos Szeredie5e55582005-09-09 13:10:28 -07001380
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001381 __free_page(page);
Miklos Szeredib36c31b2005-09-09 13:10:38 -07001382 fuse_invalidate_attr(inode); /* atime changed */
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001383 return err;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001384}
1385
1386static char *read_link(struct dentry *dentry)
1387{
1388 struct inode *inode = dentry->d_inode;
1389 struct fuse_conn *fc = get_fuse_conn(inode);
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001390 struct fuse_req *req = fuse_get_req_nopages(fc);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001391 char *link;
1392
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001393 if (IS_ERR(req))
David Howellse231c2e2008-02-07 00:15:26 -08001394 return ERR_CAST(req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001395
1396 link = (char *) __get_free_page(GFP_KERNEL);
1397 if (!link) {
1398 link = ERR_PTR(-ENOMEM);
1399 goto out;
1400 }
1401 req->in.h.opcode = FUSE_READLINK;
1402 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001403 req->out.argvar = 1;
1404 req->out.numargs = 1;
1405 req->out.args[0].size = PAGE_SIZE - 1;
1406 req->out.args[0].value = link;
Tejun Heob93f8582008-11-26 12:03:55 +01001407 fuse_request_send(fc, req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001408 if (req->out.h.error) {
1409 free_page((unsigned long) link);
1410 link = ERR_PTR(req->out.h.error);
1411 } else
1412 link[req->out.args[0].size] = '\0';
1413 out:
1414 fuse_put_request(fc, req);
Miklos Szeredib36c31b2005-09-09 13:10:38 -07001415 fuse_invalidate_attr(inode); /* atime changed */
Miklos Szeredie5e55582005-09-09 13:10:28 -07001416 return link;
1417}
1418
1419static void free_link(char *link)
1420{
1421 if (!IS_ERR(link))
1422 free_page((unsigned long) link);
1423}
1424
1425static void *fuse_follow_link(struct dentry *dentry, struct nameidata *nd)
1426{
1427 nd_set_link(nd, read_link(dentry));
1428 return NULL;
1429}
1430
1431static void fuse_put_link(struct dentry *dentry, struct nameidata *nd, void *c)
1432{
1433 free_link(nd_get_link(nd));
1434}
1435
1436static int fuse_dir_open(struct inode *inode, struct file *file)
1437{
Miklos Szeredi91fe96b2009-04-28 16:56:37 +02001438 return fuse_open_common(inode, file, true);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001439}
1440
1441static int fuse_dir_release(struct inode *inode, struct file *file)
1442{
Miklos Szeredi8b0797a2009-04-28 16:56:39 +02001443 fuse_release_common(file, FUSE_RELEASEDIR);
1444
1445 return 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001446}
1447
Josef Bacik02c24a82011-07-16 20:44:56 -04001448static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end,
1449 int datasync)
Miklos Szeredi82547982005-09-09 13:10:38 -07001450{
Josef Bacik02c24a82011-07-16 20:44:56 -04001451 return fuse_fsync_common(file, start, end, datasync, 1);
Miklos Szeredi82547982005-09-09 13:10:38 -07001452}
1453
Miklos Szeredib18da0c2011-12-13 11:58:49 +01001454static long fuse_dir_ioctl(struct file *file, unsigned int cmd,
1455 unsigned long arg)
1456{
1457 struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1458
1459 /* FUSE_IOCTL_DIR only supported for API version >= 7.18 */
1460 if (fc->minor < 18)
1461 return -ENOTTY;
1462
1463 return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR);
1464}
1465
1466static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd,
1467 unsigned long arg)
1468{
1469 struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1470
1471 if (fc->minor < 18)
1472 return -ENOTTY;
1473
1474 return fuse_ioctl_common(file, cmd, arg,
1475 FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR);
1476}
1477
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001478static bool update_mtime(unsigned ivalid)
1479{
1480 /* Always update if mtime is explicitly set */
1481 if (ivalid & ATTR_MTIME_SET)
1482 return true;
1483
1484 /* If it's an open(O_TRUNC) or an ftruncate(), don't update */
1485 if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
1486 return false;
1487
1488 /* In all other cases update */
1489 return true;
1490}
1491
Miklos Szeredibefc6492005-11-07 00:59:52 -08001492static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001493{
1494 unsigned ivalid = iattr->ia_valid;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001495
1496 if (ivalid & ATTR_MODE)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001497 arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001498 if (ivalid & ATTR_UID)
Eric W. Biederman499dcf22012-02-07 16:26:03 -08001499 arg->valid |= FATTR_UID, arg->uid = from_kuid(&init_user_ns, iattr->ia_uid);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001500 if (ivalid & ATTR_GID)
Eric W. Biederman499dcf22012-02-07 16:26:03 -08001501 arg->valid |= FATTR_GID, arg->gid = from_kgid(&init_user_ns, iattr->ia_gid);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001502 if (ivalid & ATTR_SIZE)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001503 arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001504 if (ivalid & ATTR_ATIME) {
1505 arg->valid |= FATTR_ATIME;
Miklos Szeredibefc6492005-11-07 00:59:52 -08001506 arg->atime = iattr->ia_atime.tv_sec;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001507 arg->atimensec = iattr->ia_atime.tv_nsec;
1508 if (!(ivalid & ATTR_ATIME_SET))
1509 arg->valid |= FATTR_ATIME_NOW;
1510 }
1511 if ((ivalid & ATTR_MTIME) && update_mtime(ivalid)) {
1512 arg->valid |= FATTR_MTIME;
Miklos Szeredibefc6492005-11-07 00:59:52 -08001513 arg->mtime = iattr->ia_mtime.tv_sec;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001514 arg->mtimensec = iattr->ia_mtime.tv_nsec;
1515 if (!(ivalid & ATTR_MTIME_SET))
1516 arg->valid |= FATTR_MTIME_NOW;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001517 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001518}
1519
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001520/*
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001521 * Prevent concurrent writepages on inode
1522 *
1523 * This is done by adding a negative bias to the inode write counter
1524 * and waiting for all pending writes to finish.
1525 */
1526void fuse_set_nowrite(struct inode *inode)
1527{
1528 struct fuse_conn *fc = get_fuse_conn(inode);
1529 struct fuse_inode *fi = get_fuse_inode(inode);
1530
1531 BUG_ON(!mutex_is_locked(&inode->i_mutex));
1532
1533 spin_lock(&fc->lock);
1534 BUG_ON(fi->writectr < 0);
1535 fi->writectr += FUSE_NOWRITE;
1536 spin_unlock(&fc->lock);
1537 wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE);
1538}
1539
1540/*
1541 * Allow writepages on inode
1542 *
1543 * Remove the bias from the writecounter and send any queued
1544 * writepages.
1545 */
1546static void __fuse_release_nowrite(struct inode *inode)
1547{
1548 struct fuse_inode *fi = get_fuse_inode(inode);
1549
1550 BUG_ON(fi->writectr != FUSE_NOWRITE);
1551 fi->writectr = 0;
1552 fuse_flush_writepages(inode);
1553}
1554
1555void fuse_release_nowrite(struct inode *inode)
1556{
1557 struct fuse_conn *fc = get_fuse_conn(inode);
1558
1559 spin_lock(&fc->lock);
1560 __fuse_release_nowrite(inode);
1561 spin_unlock(&fc->lock);
1562}
1563
1564/*
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001565 * Set attributes, and at the same time refresh them.
1566 *
1567 * Truncation is slightly complicated, because the 'truncate' request
1568 * may fail, in which case we don't want to touch the mapping.
Miklos Szeredi9ffbb912006-10-17 00:10:06 -07001569 * vmtruncate() doesn't allow for this case, so do the rlimit checking
1570 * and the actual truncation by hand.
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001571 */
Maxim Patlasovefb9fa92012-12-18 14:05:08 +04001572int fuse_do_setattr(struct inode *inode, struct iattr *attr,
1573 struct file *file)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001574{
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001575 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001576 struct fuse_req *req;
1577 struct fuse_setattr_in inarg;
1578 struct fuse_attr_out outarg;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001579 bool is_truncate = false;
1580 loff_t oldsize;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001581 int err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001582
Christoph Hellwigdb78b872010-06-04 11:30:03 +02001583 if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS))
1584 attr->ia_valid |= ATTR_FORCE;
1585
1586 err = inode_change_ok(inode, attr);
1587 if (err)
1588 return err;
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001589
Miklos Szeredi8d56add2011-02-25 14:44:58 +01001590 if (attr->ia_valid & ATTR_OPEN) {
1591 if (fc->atomic_o_trunc)
1592 return 0;
1593 file = NULL;
1594 }
Miklos Szeredi6ff958e2007-10-18 03:07:02 -07001595
Christoph Hellwig2c27c652010-06-04 11:30:04 +02001596 if (attr->ia_valid & ATTR_SIZE)
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001597 is_truncate = true;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001598
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001599 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001600 if (IS_ERR(req))
1601 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001602
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001603 if (is_truncate)
1604 fuse_set_nowrite(inode);
1605
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001606 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -07001607 memset(&outarg, 0, sizeof(outarg));
Miklos Szeredibefc6492005-11-07 00:59:52 -08001608 iattr_to_fattr(attr, &inarg);
Miklos Szeredi49d49142007-10-18 03:07:00 -07001609 if (file) {
1610 struct fuse_file *ff = file->private_data;
1611 inarg.valid |= FATTR_FH;
1612 inarg.fh = ff->fh;
1613 }
Miklos Szeredif3332112007-10-18 03:07:04 -07001614 if (attr->ia_valid & ATTR_SIZE) {
1615 /* For mandatory locking in truncate */
1616 inarg.valid |= FATTR_LOCKOWNER;
1617 inarg.lock_owner = fuse_lock_owner_id(fc, current->files);
1618 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001619 req->in.h.opcode = FUSE_SETATTR;
1620 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001621 req->in.numargs = 1;
1622 req->in.args[0].size = sizeof(inarg);
1623 req->in.args[0].value = &inarg;
1624 req->out.numargs = 1;
Miklos Szeredi0e9663e2007-10-18 03:07:05 -07001625 if (fc->minor < 9)
1626 req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
1627 else
1628 req->out.args[0].size = sizeof(outarg);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001629 req->out.args[0].value = &outarg;
Tejun Heob93f8582008-11-26 12:03:55 +01001630 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001631 err = req->out.h.error;
1632 fuse_put_request(fc, req);
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001633 if (err) {
1634 if (err == -EINTR)
1635 fuse_invalidate_attr(inode);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001636 goto error;
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001637 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001638
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001639 if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
1640 make_bad_inode(inode);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001641 err = -EIO;
1642 goto error;
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001643 }
1644
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001645 spin_lock(&fc->lock);
1646 fuse_change_attributes_common(inode, &outarg.attr,
1647 attr_timeout(&outarg));
1648 oldsize = inode->i_size;
1649 i_size_write(inode, outarg.attr.size);
1650
1651 if (is_truncate) {
1652 /* NOTE: this may release/reacquire fc->lock */
1653 __fuse_release_nowrite(inode);
1654 }
1655 spin_unlock(&fc->lock);
1656
1657 /*
1658 * Only call invalidate_inode_pages2() after removing
1659 * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock.
1660 */
1661 if (S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
npiggin@suse.dec08d3b02009-08-21 02:35:06 +10001662 truncate_pagecache(inode, oldsize, outarg.attr.size);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001663 invalidate_inode_pages2(inode->i_mapping);
1664 }
1665
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001666 return 0;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001667
1668error:
1669 if (is_truncate)
1670 fuse_release_nowrite(inode);
1671
1672 return err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001673}
1674
Miklos Szeredi49d49142007-10-18 03:07:00 -07001675static int fuse_setattr(struct dentry *entry, struct iattr *attr)
1676{
Maxim Patlasovefb9fa92012-12-18 14:05:08 +04001677 struct inode *inode = entry->d_inode;
1678
1679 if (!fuse_allow_current_process(get_fuse_conn(inode)))
1680 return -EACCES;
1681
Miklos Szeredi49d49142007-10-18 03:07:00 -07001682 if (attr->ia_valid & ATTR_FILE)
Maxim Patlasovefb9fa92012-12-18 14:05:08 +04001683 return fuse_do_setattr(inode, attr, attr->ia_file);
Miklos Szeredi49d49142007-10-18 03:07:00 -07001684 else
Maxim Patlasovefb9fa92012-12-18 14:05:08 +04001685 return fuse_do_setattr(inode, attr, NULL);
Miklos Szeredi49d49142007-10-18 03:07:00 -07001686}
1687
Miklos Szeredie5e55582005-09-09 13:10:28 -07001688static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
1689 struct kstat *stat)
1690{
1691 struct inode *inode = entry->d_inode;
Miklos Szeredi244f6382007-10-16 23:31:02 -07001692 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi244f6382007-10-16 23:31:02 -07001693
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001694 if (!fuse_allow_current_process(fc))
Miklos Szeredi244f6382007-10-16 23:31:02 -07001695 return -EACCES;
1696
Miklos Szeredibcb4be82007-11-28 16:21:59 -08001697 return fuse_update_attributes(inode, stat, NULL, NULL);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001698}
1699
Miklos Szeredi92a87802005-09-09 13:10:31 -07001700static int fuse_setxattr(struct dentry *entry, const char *name,
1701 const void *value, size_t size, int flags)
1702{
1703 struct inode *inode = entry->d_inode;
1704 struct fuse_conn *fc = get_fuse_conn(inode);
1705 struct fuse_req *req;
1706 struct fuse_setxattr_in inarg;
1707 int err;
1708
Miklos Szeredi92a87802005-09-09 13:10:31 -07001709 if (fc->no_setxattr)
1710 return -EOPNOTSUPP;
1711
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001712 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001713 if (IS_ERR(req))
1714 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001715
1716 memset(&inarg, 0, sizeof(inarg));
1717 inarg.size = size;
1718 inarg.flags = flags;
1719 req->in.h.opcode = FUSE_SETXATTR;
1720 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001721 req->in.numargs = 3;
1722 req->in.args[0].size = sizeof(inarg);
1723 req->in.args[0].value = &inarg;
1724 req->in.args[1].size = strlen(name) + 1;
1725 req->in.args[1].value = name;
1726 req->in.args[2].size = size;
1727 req->in.args[2].value = value;
Tejun Heob93f8582008-11-26 12:03:55 +01001728 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001729 err = req->out.h.error;
1730 fuse_put_request(fc, req);
1731 if (err == -ENOSYS) {
1732 fc->no_setxattr = 1;
1733 err = -EOPNOTSUPP;
1734 }
1735 return err;
1736}
1737
1738static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
1739 void *value, size_t size)
1740{
1741 struct inode *inode = entry->d_inode;
1742 struct fuse_conn *fc = get_fuse_conn(inode);
1743 struct fuse_req *req;
1744 struct fuse_getxattr_in inarg;
1745 struct fuse_getxattr_out outarg;
1746 ssize_t ret;
1747
1748 if (fc->no_getxattr)
1749 return -EOPNOTSUPP;
1750
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001751 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001752 if (IS_ERR(req))
1753 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001754
1755 memset(&inarg, 0, sizeof(inarg));
1756 inarg.size = size;
1757 req->in.h.opcode = FUSE_GETXATTR;
1758 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001759 req->in.numargs = 2;
1760 req->in.args[0].size = sizeof(inarg);
1761 req->in.args[0].value = &inarg;
1762 req->in.args[1].size = strlen(name) + 1;
1763 req->in.args[1].value = name;
1764 /* This is really two different operations rolled into one */
1765 req->out.numargs = 1;
1766 if (size) {
1767 req->out.argvar = 1;
1768 req->out.args[0].size = size;
1769 req->out.args[0].value = value;
1770 } else {
1771 req->out.args[0].size = sizeof(outarg);
1772 req->out.args[0].value = &outarg;
1773 }
Tejun Heob93f8582008-11-26 12:03:55 +01001774 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001775 ret = req->out.h.error;
1776 if (!ret)
1777 ret = size ? req->out.args[0].size : outarg.size;
1778 else {
1779 if (ret == -ENOSYS) {
1780 fc->no_getxattr = 1;
1781 ret = -EOPNOTSUPP;
1782 }
1783 }
1784 fuse_put_request(fc, req);
1785 return ret;
1786}
1787
1788static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
1789{
1790 struct inode *inode = entry->d_inode;
1791 struct fuse_conn *fc = get_fuse_conn(inode);
1792 struct fuse_req *req;
1793 struct fuse_getxattr_in inarg;
1794 struct fuse_getxattr_out outarg;
1795 ssize_t ret;
1796
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001797 if (!fuse_allow_current_process(fc))
Miklos Szeredie57ac682007-10-18 03:06:58 -07001798 return -EACCES;
1799
Miklos Szeredi92a87802005-09-09 13:10:31 -07001800 if (fc->no_listxattr)
1801 return -EOPNOTSUPP;
1802
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001803 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001804 if (IS_ERR(req))
1805 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001806
1807 memset(&inarg, 0, sizeof(inarg));
1808 inarg.size = size;
1809 req->in.h.opcode = FUSE_LISTXATTR;
1810 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001811 req->in.numargs = 1;
1812 req->in.args[0].size = sizeof(inarg);
1813 req->in.args[0].value = &inarg;
1814 /* This is really two different operations rolled into one */
1815 req->out.numargs = 1;
1816 if (size) {
1817 req->out.argvar = 1;
1818 req->out.args[0].size = size;
1819 req->out.args[0].value = list;
1820 } else {
1821 req->out.args[0].size = sizeof(outarg);
1822 req->out.args[0].value = &outarg;
1823 }
Tejun Heob93f8582008-11-26 12:03:55 +01001824 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001825 ret = req->out.h.error;
1826 if (!ret)
1827 ret = size ? req->out.args[0].size : outarg.size;
1828 else {
1829 if (ret == -ENOSYS) {
1830 fc->no_listxattr = 1;
1831 ret = -EOPNOTSUPP;
1832 }
1833 }
1834 fuse_put_request(fc, req);
1835 return ret;
1836}
1837
1838static int fuse_removexattr(struct dentry *entry, const char *name)
1839{
1840 struct inode *inode = entry->d_inode;
1841 struct fuse_conn *fc = get_fuse_conn(inode);
1842 struct fuse_req *req;
1843 int err;
1844
1845 if (fc->no_removexattr)
1846 return -EOPNOTSUPP;
1847
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001848 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001849 if (IS_ERR(req))
1850 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001851
1852 req->in.h.opcode = FUSE_REMOVEXATTR;
1853 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001854 req->in.numargs = 1;
1855 req->in.args[0].size = strlen(name) + 1;
1856 req->in.args[0].value = name;
Tejun Heob93f8582008-11-26 12:03:55 +01001857 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001858 err = req->out.h.error;
1859 fuse_put_request(fc, req);
1860 if (err == -ENOSYS) {
1861 fc->no_removexattr = 1;
1862 err = -EOPNOTSUPP;
1863 }
1864 return err;
1865}
1866
Arjan van de Ven754661f2007-02-12 00:55:38 -08001867static const struct inode_operations fuse_dir_inode_operations = {
Miklos Szeredie5e55582005-09-09 13:10:28 -07001868 .lookup = fuse_lookup,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001869 .mkdir = fuse_mkdir,
1870 .symlink = fuse_symlink,
1871 .unlink = fuse_unlink,
1872 .rmdir = fuse_rmdir,
1873 .rename = fuse_rename,
1874 .link = fuse_link,
1875 .setattr = fuse_setattr,
1876 .create = fuse_create,
Miklos Szeredic8ccbe02012-06-05 15:10:22 +02001877 .atomic_open = fuse_atomic_open,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001878 .mknod = fuse_mknod,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001879 .permission = fuse_permission,
1880 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001881 .setxattr = fuse_setxattr,
1882 .getxattr = fuse_getxattr,
1883 .listxattr = fuse_listxattr,
1884 .removexattr = fuse_removexattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001885};
1886
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -08001887static const struct file_operations fuse_dir_operations = {
Miklos Szeredib6aeade2005-09-09 13:10:30 -07001888 .llseek = generic_file_llseek,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001889 .read = generic_read_dir,
Al Viro8d3af7f2013-05-18 03:03:58 -04001890 .iterate = fuse_readdir,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001891 .open = fuse_dir_open,
1892 .release = fuse_dir_release,
Miklos Szeredi82547982005-09-09 13:10:38 -07001893 .fsync = fuse_dir_fsync,
Miklos Szeredib18da0c2011-12-13 11:58:49 +01001894 .unlocked_ioctl = fuse_dir_ioctl,
1895 .compat_ioctl = fuse_dir_compat_ioctl,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001896};
1897
Arjan van de Ven754661f2007-02-12 00:55:38 -08001898static const struct inode_operations fuse_common_inode_operations = {
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001899 .setattr = fuse_setattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001900 .permission = fuse_permission,
1901 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001902 .setxattr = fuse_setxattr,
1903 .getxattr = fuse_getxattr,
1904 .listxattr = fuse_listxattr,
1905 .removexattr = fuse_removexattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001906};
1907
Arjan van de Ven754661f2007-02-12 00:55:38 -08001908static const struct inode_operations fuse_symlink_inode_operations = {
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001909 .setattr = fuse_setattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001910 .follow_link = fuse_follow_link,
1911 .put_link = fuse_put_link,
1912 .readlink = generic_readlink,
1913 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001914 .setxattr = fuse_setxattr,
1915 .getxattr = fuse_getxattr,
1916 .listxattr = fuse_listxattr,
1917 .removexattr = fuse_removexattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001918};
1919
1920void fuse_init_common(struct inode *inode)
1921{
1922 inode->i_op = &fuse_common_inode_operations;
1923}
1924
1925void fuse_init_dir(struct inode *inode)
1926{
1927 inode->i_op = &fuse_dir_inode_operations;
1928 inode->i_fop = &fuse_dir_operations;
1929}
1930
1931void fuse_init_symlink(struct inode *inode)
1932{
1933 inode->i_op = &fuse_symlink_inode_operations;
1934}