blob: 0eda52738ec4d0fc6cac460fab9d4baddde4ff4b [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 Savolaa5bfffac2007-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 Szeredid2a85162006-10-17 00:10:11 -0700270/*
271 * Add a directory inode to a dentry, ensuring that no other dentry
272 * refers to this inode. Called with fc->inst_mutex.
273 */
Miklos Szeredi0de62562008-07-25 01:48:59 -0700274static struct dentry *fuse_d_add_directory(struct dentry *entry,
275 struct inode *inode)
Miklos Szeredid2a85162006-10-17 00:10:11 -0700276{
277 struct dentry *alias = d_find_alias(inode);
Miklos Szeredi0de62562008-07-25 01:48:59 -0700278 if (alias && !(alias->d_flags & DCACHE_DISCONNECTED)) {
Miklos Szeredid2a85162006-10-17 00:10:11 -0700279 /* This tries to shrink the subtree below alias */
280 fuse_invalidate_entry(alias);
281 dput(alias);
Al Virob3d9b7a2012-06-09 13:51:19 -0400282 if (!hlist_empty(&inode->i_dentry))
Miklos Szeredi0de62562008-07-25 01:48:59 -0700283 return ERR_PTR(-EBUSY);
284 } else {
285 dput(alias);
Miklos Szeredid2a85162006-10-17 00:10:11 -0700286 }
Miklos Szeredi0de62562008-07-25 01:48:59 -0700287 return d_splice_alias(inode, entry);
Miklos Szeredid2a85162006-10-17 00:10:11 -0700288}
289
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700290int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name,
291 struct fuse_entry_out *outarg, struct inode **inode)
292{
293 struct fuse_conn *fc = get_fuse_conn_super(sb);
294 struct fuse_req *req;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100295 struct fuse_forget_link *forget;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700296 u64 attr_version;
297 int err;
298
299 *inode = NULL;
300 err = -ENAMETOOLONG;
301 if (name->len > FUSE_NAME_MAX)
302 goto out;
303
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400304 req = fuse_get_req_nopages(fc);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700305 err = PTR_ERR(req);
306 if (IS_ERR(req))
307 goto out;
308
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100309 forget = fuse_alloc_forget();
310 err = -ENOMEM;
311 if (!forget) {
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700312 fuse_put_request(fc, req);
313 goto out;
314 }
315
316 attr_version = fuse_get_attr_version(fc);
317
318 fuse_lookup_init(fc, req, nodeid, name, outarg);
Tejun Heob93f8582008-11-26 12:03:55 +0100319 fuse_request_send(fc, req);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700320 err = req->out.h.error;
321 fuse_put_request(fc, req);
322 /* Zero nodeid is same as -ENOENT, but with valid timeout */
323 if (err || !outarg->nodeid)
324 goto out_put_forget;
325
326 err = -EIO;
327 if (!outarg->nodeid)
328 goto out_put_forget;
329 if (!fuse_valid_type(outarg->attr.mode))
330 goto out_put_forget;
331
332 *inode = fuse_iget(sb, outarg->nodeid, outarg->generation,
333 &outarg->attr, entry_attr_timeout(outarg),
334 attr_version);
335 err = -ENOMEM;
336 if (!*inode) {
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100337 fuse_queue_forget(fc, forget, outarg->nodeid, 1);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700338 goto out;
339 }
340 err = 0;
341
342 out_put_forget:
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100343 kfree(forget);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700344 out:
345 return err;
346}
347
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800348static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
Al Viro00cd8dd2012-06-10 17:13:09 -0400349 unsigned int flags)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700350{
351 int err;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700352 struct fuse_entry_out outarg;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700353 struct inode *inode;
Miklos Szeredi0de62562008-07-25 01:48:59 -0700354 struct dentry *newent;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700355 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700356 bool outarg_valid = true;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700357
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700358 err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name,
359 &outarg, &inode);
360 if (err == -ENOENT) {
361 outarg_valid = false;
362 err = 0;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800363 }
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700364 if (err)
365 goto out_err;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800366
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700367 err = -EIO;
368 if (inode && get_node_id(inode) == FUSE_ROOT_ID)
369 goto out_iput;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700370
Miklos Szeredid2a85162006-10-17 00:10:11 -0700371 if (inode && S_ISDIR(inode->i_mode)) {
372 mutex_lock(&fc->inst_mutex);
Miklos Szeredi0de62562008-07-25 01:48:59 -0700373 newent = fuse_d_add_directory(entry, inode);
Miklos Szeredid2a85162006-10-17 00:10:11 -0700374 mutex_unlock(&fc->inst_mutex);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700375 err = PTR_ERR(newent);
376 if (IS_ERR(newent))
377 goto out_iput;
378 } else {
Miklos Szeredi0de62562008-07-25 01:48:59 -0700379 newent = d_splice_alias(inode, entry);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700380 }
Miklos Szeredid2a85162006-10-17 00:10:11 -0700381
Miklos Szeredi0de62562008-07-25 01:48:59 -0700382 entry = newent ? newent : entry;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700383 if (outarg_valid)
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700384 fuse_change_entry_timeout(entry, &outarg);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800385 else
386 fuse_invalidate_entry_cache(entry);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700387
Feng Shuo4582a4a2013-01-15 11:23:28 +0800388 fuse_advise_use_readdirplus(dir);
Miklos Szeredi0de62562008-07-25 01:48:59 -0700389 return newent;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700390
391 out_iput:
392 iput(inode);
393 out_err:
394 return ERR_PTR(err);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700395}
396
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800397/*
398 * Atomic create+open operation
399 *
400 * If the filesystem doesn't support this, then fall back to separate
401 * 'mknod' + 'open' requests.
402 */
Al Virod9585272012-06-22 12:39:14 +0400403static int fuse_create_open(struct inode *dir, struct dentry *entry,
Al Viro30d90492012-06-22 12:40:19 +0400404 struct file *file, unsigned flags,
Al Virod9585272012-06-22 12:39:14 +0400405 umode_t mode, int *opened)
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800406{
407 int err;
408 struct inode *inode;
409 struct fuse_conn *fc = get_fuse_conn(dir);
410 struct fuse_req *req;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100411 struct fuse_forget_link *forget;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200412 struct fuse_create_in inarg;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800413 struct fuse_open_out outopen;
414 struct fuse_entry_out outentry;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800415 struct fuse_file *ff;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800416
Miklos Szerediaf109bc2012-08-15 13:01:24 +0200417 /* Userspace expects S_IFREG in create mode */
418 BUG_ON((mode & S_IFMT) != S_IFREG);
419
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100420 forget = fuse_alloc_forget();
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200421 err = -ENOMEM;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100422 if (!forget)
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200423 goto out_err;
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700424
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400425 req = fuse_get_req_nopages(fc);
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700426 err = PTR_ERR(req);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700427 if (IS_ERR(req))
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700428 goto out_put_forget_req;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800429
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700430 err = -ENOMEM;
Tejun Heoacf99432008-11-26 12:03:55 +0100431 ff = fuse_file_alloc(fc);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800432 if (!ff)
433 goto out_put_request;
434
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200435 if (!fc->dont_mask)
436 mode &= ~current_umask();
437
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800438 flags &= ~O_NOCTTY;
439 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700440 memset(&outentry, 0, sizeof(outentry));
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800441 inarg.flags = flags;
442 inarg.mode = mode;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200443 inarg.umask = current_umask();
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800444 req->in.h.opcode = FUSE_CREATE;
445 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800446 req->in.numargs = 2;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200447 req->in.args[0].size = fc->minor < 12 ? sizeof(struct fuse_open_in) :
448 sizeof(inarg);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800449 req->in.args[0].value = &inarg;
450 req->in.args[1].size = entry->d_name.len + 1;
451 req->in.args[1].value = entry->d_name.name;
452 req->out.numargs = 2;
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700453 if (fc->minor < 9)
454 req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
455 else
456 req->out.args[0].size = sizeof(outentry);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800457 req->out.args[0].value = &outentry;
458 req->out.args[1].size = sizeof(outopen);
459 req->out.args[1].value = &outopen;
Tejun Heob93f8582008-11-26 12:03:55 +0100460 fuse_request_send(fc, req);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800461 err = req->out.h.error;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200462 if (err)
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800463 goto out_free_ff;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800464
465 err = -EIO;
Miklos Szeredi2827d0b22005-11-28 13:44:16 -0800466 if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid))
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800467 goto out_free_ff;
468
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700469 fuse_put_request(fc, req);
Miklos Szeredic7b71432009-04-28 16:56:37 +0200470 ff->fh = outopen.fh;
471 ff->nodeid = outentry.nodeid;
472 ff->open_flags = outopen.open_flags;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800473 inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700474 &outentry.attr, entry_attr_timeout(&outentry), 0);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800475 if (!inode) {
476 flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
Miklos Szeredi8b0797a2009-04-28 16:56:39 +0200477 fuse_sync_release(ff, flags);
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100478 fuse_queue_forget(fc, forget, outentry.nodeid, 1);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200479 err = -ENOMEM;
480 goto out_err;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800481 }
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100482 kfree(forget);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800483 d_instantiate(entry, inode);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700484 fuse_change_entry_timeout(entry, &outentry);
Miklos Szeredi0952b2a2008-02-06 01:38:38 -0800485 fuse_invalidate_attr(dir);
Al Viro30d90492012-06-22 12:40:19 +0400486 err = finish_open(file, entry, generic_file_open, opened);
487 if (err) {
Miklos Szeredi8b0797a2009-04-28 16:56:39 +0200488 fuse_sync_release(ff, flags);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200489 } else {
490 file->private_data = fuse_file_get(ff);
491 fuse_finish_open(inode, file);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800492 }
Al Virod9585272012-06-22 12:39:14 +0400493 return err;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800494
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200495out_free_ff:
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800496 fuse_file_free(ff);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200497out_put_request:
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800498 fuse_put_request(fc, req);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200499out_put_forget_req:
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100500 kfree(forget);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200501out_err:
Al Virod9585272012-06-22 12:39:14 +0400502 return err;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200503}
504
505static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t);
Al Virod9585272012-06-22 12:39:14 +0400506static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
Al Viro30d90492012-06-22 12:40:19 +0400507 struct file *file, unsigned flags,
Al Virod9585272012-06-22 12:39:14 +0400508 umode_t mode, int *opened)
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200509{
510 int err;
511 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200512 struct dentry *res = NULL;
513
514 if (d_unhashed(entry)) {
Al Viro00cd8dd2012-06-10 17:13:09 -0400515 res = fuse_lookup(dir, entry, 0);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200516 if (IS_ERR(res))
Al Virod9585272012-06-22 12:39:14 +0400517 return PTR_ERR(res);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200518
519 if (res)
520 entry = res;
521 }
522
523 if (!(flags & O_CREAT) || entry->d_inode)
524 goto no_open;
525
526 /* Only creates */
Al Viro47237682012-06-10 05:01:45 -0400527 *opened |= FILE_CREATED;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200528
529 if (fc->no_create)
530 goto mknod;
531
Al Viro30d90492012-06-22 12:40:19 +0400532 err = fuse_create_open(dir, entry, file, flags, mode, opened);
Al Virod9585272012-06-22 12:39:14 +0400533 if (err == -ENOSYS) {
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200534 fc->no_create = 1;
535 goto mknod;
536 }
537out_dput:
538 dput(res);
Al Virod9585272012-06-22 12:39:14 +0400539 return err;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200540
541mknod:
542 err = fuse_mknod(dir, entry, mode, 0);
Al Virod9585272012-06-22 12:39:14 +0400543 if (err)
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200544 goto out_dput;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200545no_open:
Al Viroe45198a2012-06-10 06:48:09 -0400546 return finish_no_open(file, res);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800547}
548
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800549/*
550 * Code shared between mknod, mkdir, symlink and link
551 */
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700552static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
553 struct inode *dir, struct dentry *entry,
Al Viro541af6a2011-07-26 03:17:33 -0400554 umode_t mode)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700555{
556 struct fuse_entry_out outarg;
557 struct inode *inode;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700558 int err;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100559 struct fuse_forget_link *forget;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800560
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100561 forget = fuse_alloc_forget();
562 if (!forget) {
Miklos Szeredi2d510132006-11-25 11:09:20 -0800563 fuse_put_request(fc, req);
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100564 return -ENOMEM;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800565 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700566
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700567 memset(&outarg, 0, sizeof(outarg));
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700568 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700569 req->out.numargs = 1;
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700570 if (fc->minor < 9)
571 req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
572 else
573 req->out.args[0].size = sizeof(outarg);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700574 req->out.args[0].value = &outarg;
Tejun Heob93f8582008-11-26 12:03:55 +0100575 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700576 err = req->out.h.error;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800577 fuse_put_request(fc, req);
578 if (err)
579 goto out_put_forget_req;
580
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800581 err = -EIO;
582 if (invalid_nodeid(outarg.nodeid))
Miklos Szeredi2d510132006-11-25 11:09:20 -0800583 goto out_put_forget_req;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800584
585 if ((outarg.attr.mode ^ mode) & S_IFMT)
Miklos Szeredi2d510132006-11-25 11:09:20 -0800586 goto out_put_forget_req;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800587
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700588 inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700589 &outarg.attr, entry_attr_timeout(&outarg), 0);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700590 if (!inode) {
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100591 fuse_queue_forget(fc, forget, outarg.nodeid, 1);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700592 return -ENOMEM;
593 }
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100594 kfree(forget);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700595
Miklos Szeredid2a85162006-10-17 00:10:11 -0700596 if (S_ISDIR(inode->i_mode)) {
597 struct dentry *alias;
598 mutex_lock(&fc->inst_mutex);
599 alias = d_find_alias(inode);
600 if (alias) {
601 /* New directory must have moved since mkdir */
602 mutex_unlock(&fc->inst_mutex);
603 dput(alias);
604 iput(inode);
605 return -EBUSY;
606 }
607 d_instantiate(entry, inode);
608 mutex_unlock(&fc->inst_mutex);
609 } else
610 d_instantiate(entry, inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700611
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700612 fuse_change_entry_timeout(entry, &outarg);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700613 fuse_invalidate_attr(dir);
614 return 0;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800615
Miklos Szeredi2d510132006-11-25 11:09:20 -0800616 out_put_forget_req:
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100617 kfree(forget);
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800618 return err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700619}
620
Al Viro1a67aaf2011-07-26 01:52:52 -0400621static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700622 dev_t rdev)
623{
624 struct fuse_mknod_in inarg;
625 struct fuse_conn *fc = get_fuse_conn(dir);
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400626 struct fuse_req *req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700627 if (IS_ERR(req))
628 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700629
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200630 if (!fc->dont_mask)
631 mode &= ~current_umask();
632
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700633 memset(&inarg, 0, sizeof(inarg));
634 inarg.mode = mode;
635 inarg.rdev = new_encode_dev(rdev);
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200636 inarg.umask = current_umask();
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700637 req->in.h.opcode = FUSE_MKNOD;
638 req->in.numargs = 2;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200639 req->in.args[0].size = fc->minor < 12 ? FUSE_COMPAT_MKNOD_IN_SIZE :
640 sizeof(inarg);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700641 req->in.args[0].value = &inarg;
642 req->in.args[1].size = entry->d_name.len + 1;
643 req->in.args[1].value = entry->d_name.name;
644 return create_new_entry(fc, req, dir, entry, mode);
645}
646
Al Viro4acdaf22011-07-26 01:42:34 -0400647static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode,
Al Viroebfc3b42012-06-10 18:05:36 -0400648 bool excl)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700649{
650 return fuse_mknod(dir, entry, mode, 0);
651}
652
Al Viro18bb1db2011-07-26 01:41:39 -0400653static int fuse_mkdir(struct inode *dir, struct dentry *entry, umode_t mode)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700654{
655 struct fuse_mkdir_in inarg;
656 struct fuse_conn *fc = get_fuse_conn(dir);
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400657 struct fuse_req *req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700658 if (IS_ERR(req))
659 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700660
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200661 if (!fc->dont_mask)
662 mode &= ~current_umask();
663
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700664 memset(&inarg, 0, sizeof(inarg));
665 inarg.mode = mode;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200666 inarg.umask = current_umask();
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700667 req->in.h.opcode = FUSE_MKDIR;
668 req->in.numargs = 2;
669 req->in.args[0].size = sizeof(inarg);
670 req->in.args[0].value = &inarg;
671 req->in.args[1].size = entry->d_name.len + 1;
672 req->in.args[1].value = entry->d_name.name;
673 return create_new_entry(fc, req, dir, entry, S_IFDIR);
674}
675
676static int fuse_symlink(struct inode *dir, struct dentry *entry,
677 const char *link)
678{
679 struct fuse_conn *fc = get_fuse_conn(dir);
680 unsigned len = strlen(link) + 1;
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400681 struct fuse_req *req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700682 if (IS_ERR(req))
683 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700684
685 req->in.h.opcode = FUSE_SYMLINK;
686 req->in.numargs = 2;
687 req->in.args[0].size = entry->d_name.len + 1;
688 req->in.args[0].value = entry->d_name.name;
689 req->in.args[1].size = len;
690 req->in.args[1].value = link;
691 return create_new_entry(fc, req, dir, entry, S_IFLNK);
692}
693
694static int fuse_unlink(struct inode *dir, struct dentry *entry)
695{
696 int err;
697 struct fuse_conn *fc = get_fuse_conn(dir);
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400698 struct fuse_req *req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700699 if (IS_ERR(req))
700 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700701
702 req->in.h.opcode = FUSE_UNLINK;
703 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700704 req->in.numargs = 1;
705 req->in.args[0].size = entry->d_name.len + 1;
706 req->in.args[0].value = entry->d_name.name;
Tejun Heob93f8582008-11-26 12:03:55 +0100707 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700708 err = req->out.h.error;
709 fuse_put_request(fc, req);
710 if (!err) {
711 struct inode *inode = entry->d_inode;
Miklos Szerediac45d612012-03-05 15:48:11 +0100712 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700713
Miklos Szerediac45d612012-03-05 15:48:11 +0100714 spin_lock(&fc->lock);
715 fi->attr_version = ++fc->attr_version;
Miklos Szeredidfca7ce2013-02-04 15:57:42 +0100716 /*
717 * If i_nlink == 0 then unlink doesn't make sense, yet this can
718 * happen if userspace filesystem is careless. It would be
719 * difficult to enforce correct nlink usage so just ignore this
720 * condition here
721 */
722 if (inode->i_nlink > 0)
723 drop_nlink(inode);
Miklos Szerediac45d612012-03-05 15:48:11 +0100724 spin_unlock(&fc->lock);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700725 fuse_invalidate_attr(inode);
726 fuse_invalidate_attr(dir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800727 fuse_invalidate_entry_cache(entry);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700728 } else if (err == -EINTR)
729 fuse_invalidate_entry(entry);
730 return err;
731}
732
733static int fuse_rmdir(struct inode *dir, struct dentry *entry)
734{
735 int err;
736 struct fuse_conn *fc = get_fuse_conn(dir);
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400737 struct fuse_req *req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700738 if (IS_ERR(req))
739 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700740
741 req->in.h.opcode = FUSE_RMDIR;
742 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700743 req->in.numargs = 1;
744 req->in.args[0].size = entry->d_name.len + 1;
745 req->in.args[0].value = entry->d_name.name;
Tejun Heob93f8582008-11-26 12:03:55 +0100746 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700747 err = req->out.h.error;
748 fuse_put_request(fc, req);
749 if (!err) {
Dave Hansence71ec32006-09-30 23:29:06 -0700750 clear_nlink(entry->d_inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700751 fuse_invalidate_attr(dir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800752 fuse_invalidate_entry_cache(entry);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700753 } else if (err == -EINTR)
754 fuse_invalidate_entry(entry);
755 return err;
756}
757
758static int fuse_rename(struct inode *olddir, struct dentry *oldent,
759 struct inode *newdir, struct dentry *newent)
760{
761 int err;
762 struct fuse_rename_in inarg;
763 struct fuse_conn *fc = get_fuse_conn(olddir);
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400764 struct fuse_req *req = fuse_get_req_nopages(fc);
Sage Weile4eaac02011-05-24 13:06:07 -0700765
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700766 if (IS_ERR(req))
767 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700768
769 memset(&inarg, 0, sizeof(inarg));
770 inarg.newdir = get_node_id(newdir);
771 req->in.h.opcode = FUSE_RENAME;
772 req->in.h.nodeid = get_node_id(olddir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700773 req->in.numargs = 3;
774 req->in.args[0].size = sizeof(inarg);
775 req->in.args[0].value = &inarg;
776 req->in.args[1].size = oldent->d_name.len + 1;
777 req->in.args[1].value = oldent->d_name.name;
778 req->in.args[2].size = newent->d_name.len + 1;
779 req->in.args[2].value = newent->d_name.name;
Tejun Heob93f8582008-11-26 12:03:55 +0100780 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700781 err = req->out.h.error;
782 fuse_put_request(fc, req);
783 if (!err) {
Miklos Szeredi08b63302007-11-28 16:22:03 -0800784 /* ctime changes */
785 fuse_invalidate_attr(oldent->d_inode);
786
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700787 fuse_invalidate_attr(olddir);
788 if (olddir != newdir)
789 fuse_invalidate_attr(newdir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800790
791 /* newent will end up negative */
Miklos Szeredi5219f342009-11-04 10:24:52 +0100792 if (newent->d_inode) {
793 fuse_invalidate_attr(newent->d_inode);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800794 fuse_invalidate_entry_cache(newent);
Miklos Szeredi5219f342009-11-04 10:24:52 +0100795 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700796 } else if (err == -EINTR) {
797 /* If request was interrupted, DEITY only knows if the
798 rename actually took place. If the invalidation
799 fails (e.g. some process has CWD under the renamed
800 directory), then there can be inconsistency between
801 the dcache and the real filesystem. Tough luck. */
802 fuse_invalidate_entry(oldent);
803 if (newent->d_inode)
804 fuse_invalidate_entry(newent);
805 }
806
807 return err;
808}
809
810static int fuse_link(struct dentry *entry, struct inode *newdir,
811 struct dentry *newent)
812{
813 int err;
814 struct fuse_link_in inarg;
815 struct inode *inode = entry->d_inode;
816 struct fuse_conn *fc = get_fuse_conn(inode);
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400817 struct fuse_req *req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700818 if (IS_ERR(req))
819 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700820
821 memset(&inarg, 0, sizeof(inarg));
822 inarg.oldnodeid = get_node_id(inode);
823 req->in.h.opcode = FUSE_LINK;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700824 req->in.numargs = 2;
825 req->in.args[0].size = sizeof(inarg);
826 req->in.args[0].value = &inarg;
827 req->in.args[1].size = newent->d_name.len + 1;
828 req->in.args[1].value = newent->d_name.name;
829 err = create_new_entry(fc, req, newdir, newent, inode->i_mode);
830 /* Contrary to "normal" filesystems it can happen that link
831 makes two "logical" inodes point to the same "physical"
832 inode. We invalidate the attributes of the old one, so it
833 will reflect changes in the backing inode (link count,
834 etc.)
835 */
Miklos Szerediac45d612012-03-05 15:48:11 +0100836 if (!err) {
837 struct fuse_inode *fi = get_fuse_inode(inode);
838
839 spin_lock(&fc->lock);
840 fi->attr_version = ++fc->attr_version;
841 inc_nlink(inode);
842 spin_unlock(&fc->lock);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700843 fuse_invalidate_attr(inode);
Miklos Szerediac45d612012-03-05 15:48:11 +0100844 } else if (err == -EINTR) {
845 fuse_invalidate_attr(inode);
846 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700847 return err;
848}
849
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700850static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
851 struct kstat *stat)
852{
Miklos Szeredi203627b2012-05-10 19:49:38 +0400853 unsigned int blkbits;
854
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700855 stat->dev = inode->i_sb->s_dev;
856 stat->ino = attr->ino;
857 stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
858 stat->nlink = attr->nlink;
Eric W. Biederman499dcf22012-02-07 16:26:03 -0800859 stat->uid = make_kuid(&init_user_ns, attr->uid);
860 stat->gid = make_kgid(&init_user_ns, attr->gid);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700861 stat->rdev = inode->i_rdev;
862 stat->atime.tv_sec = attr->atime;
863 stat->atime.tv_nsec = attr->atimensec;
864 stat->mtime.tv_sec = attr->mtime;
865 stat->mtime.tv_nsec = attr->mtimensec;
866 stat->ctime.tv_sec = attr->ctime;
867 stat->ctime.tv_nsec = attr->ctimensec;
868 stat->size = attr->size;
869 stat->blocks = attr->blocks;
Miklos Szeredi203627b2012-05-10 19:49:38 +0400870
871 if (attr->blksize != 0)
872 blkbits = ilog2(attr->blksize);
873 else
874 blkbits = inode->i_sb->s_blocksize_bits;
875
876 stat->blksize = 1 << blkbits;
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700877}
878
Miklos Szeredic79e3222007-10-18 03:06:59 -0700879static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
880 struct file *file)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700881{
882 int err;
Miklos Szeredic79e3222007-10-18 03:06:59 -0700883 struct fuse_getattr_in inarg;
884 struct fuse_attr_out outarg;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700885 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700886 struct fuse_req *req;
887 u64 attr_version;
888
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400889 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700890 if (IS_ERR(req))
891 return PTR_ERR(req);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700892
Miklos Szeredi7dca9fd2007-11-28 16:21:59 -0800893 attr_version = fuse_get_attr_version(fc);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700894
Miklos Szeredic79e3222007-10-18 03:06:59 -0700895 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700896 memset(&outarg, 0, sizeof(outarg));
Miklos Szeredic79e3222007-10-18 03:06:59 -0700897 /* Directories have separate file-handle space */
898 if (file && S_ISREG(inode->i_mode)) {
899 struct fuse_file *ff = file->private_data;
900
901 inarg.getattr_flags |= FUSE_GETATTR_FH;
902 inarg.fh = ff->fh;
903 }
Miklos Szeredie5e55582005-09-09 13:10:28 -0700904 req->in.h.opcode = FUSE_GETATTR;
905 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredic79e3222007-10-18 03:06:59 -0700906 req->in.numargs = 1;
907 req->in.args[0].size = sizeof(inarg);
908 req->in.args[0].value = &inarg;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700909 req->out.numargs = 1;
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700910 if (fc->minor < 9)
911 req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
912 else
913 req->out.args[0].size = sizeof(outarg);
Miklos Szeredic79e3222007-10-18 03:06:59 -0700914 req->out.args[0].value = &outarg;
Tejun Heob93f8582008-11-26 12:03:55 +0100915 fuse_request_send(fc, req);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700916 err = req->out.h.error;
917 fuse_put_request(fc, req);
918 if (!err) {
Miklos Szeredic79e3222007-10-18 03:06:59 -0700919 if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
Miklos Szeredie5e55582005-09-09 13:10:28 -0700920 make_bad_inode(inode);
921 err = -EIO;
922 } else {
Miklos Szeredic79e3222007-10-18 03:06:59 -0700923 fuse_change_attributes(inode, &outarg.attr,
924 attr_timeout(&outarg),
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700925 attr_version);
926 if (stat)
Miklos Szeredic79e3222007-10-18 03:06:59 -0700927 fuse_fillattr(inode, &outarg.attr, stat);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700928 }
929 }
930 return err;
931}
932
Miklos Szeredibcb4be82007-11-28 16:21:59 -0800933int fuse_update_attributes(struct inode *inode, struct kstat *stat,
934 struct file *file, bool *refreshed)
935{
936 struct fuse_inode *fi = get_fuse_inode(inode);
937 int err;
938 bool r;
939
940 if (fi->i_time < get_jiffies_64()) {
941 r = true;
942 err = fuse_do_getattr(inode, stat, file);
943 } else {
944 r = false;
945 err = 0;
946 if (stat) {
947 generic_fillattr(inode, stat);
948 stat->mode = fi->orig_i_mode;
Pavel Shilovsky45c72cd2012-05-10 19:49:38 +0400949 stat->ino = fi->orig_ino;
Miklos Szeredibcb4be82007-11-28 16:21:59 -0800950 }
951 }
952
953 if (refreshed != NULL)
954 *refreshed = r;
955
956 return err;
957}
958
John Muir3b463ae2009-05-31 11:13:57 -0400959int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid,
John Muir451d0f52011-12-06 21:50:06 +0100960 u64 child_nodeid, struct qstr *name)
John Muir3b463ae2009-05-31 11:13:57 -0400961{
962 int err = -ENOTDIR;
963 struct inode *parent;
964 struct dentry *dir;
965 struct dentry *entry;
966
967 parent = ilookup5(sb, parent_nodeid, fuse_inode_eq, &parent_nodeid);
968 if (!parent)
969 return -ENOENT;
970
971 mutex_lock(&parent->i_mutex);
972 if (!S_ISDIR(parent->i_mode))
973 goto unlock;
974
975 err = -ENOENT;
976 dir = d_find_alias(parent);
977 if (!dir)
978 goto unlock;
979
980 entry = d_lookup(dir, name);
981 dput(dir);
982 if (!entry)
983 goto unlock;
984
985 fuse_invalidate_attr(parent);
986 fuse_invalidate_entry(entry);
John Muir451d0f52011-12-06 21:50:06 +0100987
988 if (child_nodeid != 0 && entry->d_inode) {
989 mutex_lock(&entry->d_inode->i_mutex);
990 if (get_node_id(entry->d_inode) != child_nodeid) {
991 err = -ENOENT;
992 goto badentry;
993 }
994 if (d_mountpoint(entry)) {
995 err = -EBUSY;
996 goto badentry;
997 }
998 if (S_ISDIR(entry->d_inode->i_mode)) {
999 shrink_dcache_parent(entry);
1000 if (!simple_empty(entry)) {
1001 err = -ENOTEMPTY;
1002 goto badentry;
1003 }
1004 entry->d_inode->i_flags |= S_DEAD;
1005 }
1006 dont_mount(entry);
1007 clear_nlink(entry->d_inode);
1008 err = 0;
1009 badentry:
1010 mutex_unlock(&entry->d_inode->i_mutex);
1011 if (!err)
1012 d_delete(entry);
1013 } else {
1014 err = 0;
1015 }
John Muir3b463ae2009-05-31 11:13:57 -04001016 dput(entry);
John Muir3b463ae2009-05-31 11:13:57 -04001017
1018 unlock:
1019 mutex_unlock(&parent->i_mutex);
1020 iput(parent);
1021 return err;
1022}
1023
Miklos Szeredi87729a52005-09-09 13:10:34 -07001024/*
1025 * Calling into a user-controlled filesystem gives the filesystem
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001026 * daemon ptrace-like capabilities over the current process. This
Miklos Szeredi87729a52005-09-09 13:10:34 -07001027 * means, that the filesystem daemon is able to record the exact
1028 * filesystem operations performed, and can also control the behavior
1029 * of the requester process in otherwise impossible ways. For example
1030 * it can delay the operation for arbitrary length of time allowing
1031 * DoS against the requester.
1032 *
1033 * For this reason only those processes can call into the filesystem,
1034 * for which the owner of the mount has ptrace privilege. This
1035 * excludes processes started by other users, suid or sgid processes.
1036 */
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001037int fuse_allow_current_process(struct fuse_conn *fc)
Miklos Szeredi87729a52005-09-09 13:10:34 -07001038{
David Howellsc69e8d92008-11-14 10:39:19 +11001039 const struct cred *cred;
David Howellsc69e8d92008-11-14 10:39:19 +11001040
Miklos Szeredi87729a52005-09-09 13:10:34 -07001041 if (fc->flags & FUSE_ALLOW_OTHER)
1042 return 1;
1043
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001044 cred = current_cred();
Eric W. Biederman499dcf22012-02-07 16:26:03 -08001045 if (uid_eq(cred->euid, fc->user_id) &&
1046 uid_eq(cred->suid, fc->user_id) &&
1047 uid_eq(cred->uid, fc->user_id) &&
1048 gid_eq(cred->egid, fc->group_id) &&
1049 gid_eq(cred->sgid, fc->group_id) &&
1050 gid_eq(cred->gid, fc->group_id))
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001051 return 1;
Miklos Szeredi87729a52005-09-09 13:10:34 -07001052
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001053 return 0;
Miklos Szeredi87729a52005-09-09 13:10:34 -07001054}
1055
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001056static int fuse_access(struct inode *inode, int mask)
1057{
1058 struct fuse_conn *fc = get_fuse_conn(inode);
1059 struct fuse_req *req;
1060 struct fuse_access_in inarg;
1061 int err;
1062
1063 if (fc->no_access)
1064 return 0;
1065
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001066 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001067 if (IS_ERR(req))
1068 return PTR_ERR(req);
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001069
1070 memset(&inarg, 0, sizeof(inarg));
Al Viroe6305c42008-07-15 21:03:57 -04001071 inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC);
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001072 req->in.h.opcode = FUSE_ACCESS;
1073 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001074 req->in.numargs = 1;
1075 req->in.args[0].size = sizeof(inarg);
1076 req->in.args[0].value = &inarg;
Tejun Heob93f8582008-11-26 12:03:55 +01001077 fuse_request_send(fc, req);
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001078 err = req->out.h.error;
1079 fuse_put_request(fc, req);
1080 if (err == -ENOSYS) {
1081 fc->no_access = 1;
1082 err = 0;
1083 }
1084 return err;
1085}
1086
Al Viro10556cb2011-06-20 19:28:19 -04001087static int fuse_perm_getattr(struct inode *inode, int mask)
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001088{
Al Viro10556cb2011-06-20 19:28:19 -04001089 if (mask & MAY_NOT_BLOCK)
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001090 return -ECHILD;
1091
1092 return fuse_do_getattr(inode, NULL, NULL);
1093}
1094
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001095/*
1096 * Check permission. The two basic access models of FUSE are:
1097 *
1098 * 1) Local access checking ('default_permissions' mount option) based
1099 * on file mode. This is the plain old disk filesystem permission
1100 * modell.
1101 *
1102 * 2) "Remote" access checking, where server is responsible for
1103 * checking permission in each inode operation. An exception to this
1104 * is if ->permission() was invoked from sys_access() in which case an
1105 * access request is sent. Execute permission is still checked
1106 * locally based on file mode.
1107 */
Al Viro10556cb2011-06-20 19:28:19 -04001108static int fuse_permission(struct inode *inode, int mask)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001109{
1110 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi244f6382007-10-16 23:31:02 -07001111 bool refreshed = false;
1112 int err = 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001113
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001114 if (!fuse_allow_current_process(fc))
Miklos Szeredie5e55582005-09-09 13:10:28 -07001115 return -EACCES;
Miklos Szeredi244f6382007-10-16 23:31:02 -07001116
1117 /*
Miklos Szeredie8e96152007-10-16 23:31:06 -07001118 * If attributes are needed, refresh them before proceeding
Miklos Szeredi244f6382007-10-16 23:31:02 -07001119 */
Miklos Szeredie8e96152007-10-16 23:31:06 -07001120 if ((fc->flags & FUSE_DEFAULT_PERMISSIONS) ||
1121 ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001122 struct fuse_inode *fi = get_fuse_inode(inode);
1123
1124 if (fi->i_time < get_jiffies_64()) {
1125 refreshed = true;
1126
Al Viro10556cb2011-06-20 19:28:19 -04001127 err = fuse_perm_getattr(inode, mask);
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001128 if (err)
1129 return err;
1130 }
Miklos Szeredi244f6382007-10-16 23:31:02 -07001131 }
1132
1133 if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
Al Viro2830ba72011-06-20 19:16:29 -04001134 err = generic_permission(inode, mask);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001135
1136 /* If permission is denied, try to refresh file
1137 attributes. This is also needed, because the root
1138 node will at first have no permissions */
Miklos Szeredi244f6382007-10-16 23:31:02 -07001139 if (err == -EACCES && !refreshed) {
Al Viro10556cb2011-06-20 19:28:19 -04001140 err = fuse_perm_getattr(inode, mask);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001141 if (!err)
Al Viro2830ba72011-06-20 19:16:29 -04001142 err = generic_permission(inode, mask);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001143 }
1144
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001145 /* Note: the opposite of the above test does not
1146 exist. So if permissions are revoked this won't be
1147 noticed immediately, only after the attribute
1148 timeout has expired */
Eric Paris9cfcac82010-07-23 11:43:51 -04001149 } else if (mask & (MAY_ACCESS | MAY_CHDIR)) {
Al Viro10556cb2011-06-20 19:28:19 -04001150 if (mask & MAY_NOT_BLOCK)
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001151 return -ECHILD;
1152
Miklos Szeredie8e96152007-10-16 23:31:06 -07001153 err = fuse_access(inode, mask);
1154 } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
1155 if (!(inode->i_mode & S_IXUGO)) {
1156 if (refreshed)
1157 return -EACCES;
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001158
Al Viro10556cb2011-06-20 19:28:19 -04001159 err = fuse_perm_getattr(inode, mask);
Miklos Szeredie8e96152007-10-16 23:31:06 -07001160 if (!err && !(inode->i_mode & S_IXUGO))
1161 return -EACCES;
1162 }
Miklos Szeredie5e55582005-09-09 13:10:28 -07001163 }
Miklos Szeredi244f6382007-10-16 23:31:02 -07001164 return err;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001165}
1166
1167static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
Al Viro8d3af7f2013-05-18 03:03:58 -04001168 struct dir_context *ctx)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001169{
1170 while (nbytes >= FUSE_NAME_OFFSET) {
1171 struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
1172 size_t reclen = FUSE_DIRENT_SIZE(dirent);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001173 if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
1174 return -EIO;
1175 if (reclen > nbytes)
1176 break;
1177
Al Viro8d3af7f2013-05-18 03:03:58 -04001178 if (!dir_emit(ctx, dirent->name, dirent->namelen,
1179 dirent->ino, dirent->type))
Miklos Szeredie5e55582005-09-09 13:10:28 -07001180 break;
1181
1182 buf += reclen;
1183 nbytes -= reclen;
Al Viro8d3af7f2013-05-18 03:03:58 -04001184 ctx->pos = dirent->off;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001185 }
1186
1187 return 0;
1188}
1189
Anand V. Avati0b05b182012-08-19 08:53:23 -04001190static int fuse_direntplus_link(struct file *file,
1191 struct fuse_direntplus *direntplus,
1192 u64 attr_version)
1193{
1194 int err;
1195 struct fuse_entry_out *o = &direntplus->entry_out;
1196 struct fuse_dirent *dirent = &direntplus->dirent;
1197 struct dentry *parent = file->f_path.dentry;
1198 struct qstr name = QSTR_INIT(dirent->name, dirent->namelen);
1199 struct dentry *dentry;
1200 struct dentry *alias;
1201 struct inode *dir = parent->d_inode;
1202 struct fuse_conn *fc;
1203 struct inode *inode;
1204
1205 if (!o->nodeid) {
1206 /*
1207 * Unlike in the case of fuse_lookup, zero nodeid does not mean
1208 * ENOENT. Instead, it only means the userspace filesystem did
1209 * not want to return attributes/handle for this entry.
1210 *
1211 * So do nothing.
1212 */
1213 return 0;
1214 }
1215
1216 if (name.name[0] == '.') {
1217 /*
1218 * We could potentially refresh the attributes of the directory
1219 * and its parent?
1220 */
1221 if (name.len == 1)
1222 return 0;
1223 if (name.name[1] == '.' && name.len == 2)
1224 return 0;
1225 }
1226 fc = get_fuse_conn(dir);
1227
1228 name.hash = full_name_hash(name.name, name.len);
1229 dentry = d_lookup(parent, &name);
1230 if (dentry && dentry->d_inode) {
1231 inode = dentry->d_inode;
1232 if (get_node_id(inode) == o->nodeid) {
1233 struct fuse_inode *fi;
1234 fi = get_fuse_inode(inode);
1235 spin_lock(&fc->lock);
1236 fi->nlookup++;
1237 spin_unlock(&fc->lock);
1238
1239 /*
1240 * The other branch to 'found' comes via fuse_iget()
1241 * which bumps nlookup inside
1242 */
1243 goto found;
1244 }
1245 err = d_invalidate(dentry);
1246 if (err)
1247 goto out;
1248 dput(dentry);
1249 dentry = NULL;
1250 }
1251
1252 dentry = d_alloc(parent, &name);
1253 err = -ENOMEM;
1254 if (!dentry)
1255 goto out;
1256
1257 inode = fuse_iget(dir->i_sb, o->nodeid, o->generation,
1258 &o->attr, entry_attr_timeout(o), attr_version);
1259 if (!inode)
1260 goto out;
1261
1262 alias = d_materialise_unique(dentry, inode);
1263 err = PTR_ERR(alias);
1264 if (IS_ERR(alias))
1265 goto out;
1266 if (alias) {
1267 dput(dentry);
1268 dentry = alias;
1269 }
1270
1271found:
1272 fuse_change_attributes(inode, &o->attr, entry_attr_timeout(o),
1273 attr_version);
1274
1275 fuse_change_entry_timeout(dentry, o);
1276
1277 err = 0;
1278out:
1279 if (dentry)
1280 dput(dentry);
1281 return err;
1282}
1283
1284static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file,
Al Viro8d3af7f2013-05-18 03:03:58 -04001285 struct dir_context *ctx, u64 attr_version)
Anand V. Avati0b05b182012-08-19 08:53:23 -04001286{
1287 struct fuse_direntplus *direntplus;
1288 struct fuse_dirent *dirent;
1289 size_t reclen;
1290 int over = 0;
1291 int ret;
1292
1293 while (nbytes >= FUSE_NAME_OFFSET_DIRENTPLUS) {
1294 direntplus = (struct fuse_direntplus *) buf;
1295 dirent = &direntplus->dirent;
1296 reclen = FUSE_DIRENTPLUS_SIZE(direntplus);
1297
1298 if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
1299 return -EIO;
1300 if (reclen > nbytes)
1301 break;
1302
1303 if (!over) {
1304 /* We fill entries into dstbuf only as much as
1305 it can hold. But we still continue iterating
1306 over remaining entries to link them. If not,
1307 we need to send a FORGET for each of those
1308 which we did not link.
1309 */
Al Viro8d3af7f2013-05-18 03:03:58 -04001310 over = !dir_emit(ctx, dirent->name, dirent->namelen,
1311 dirent->ino, dirent->type);
1312 ctx->pos = dirent->off;
Anand V. Avati0b05b182012-08-19 08:53:23 -04001313 }
1314
1315 buf += reclen;
1316 nbytes -= reclen;
1317
1318 ret = fuse_direntplus_link(file, direntplus, attr_version);
1319 if (ret)
1320 fuse_force_forget(file, direntplus->entry_out.nodeid);
1321 }
1322
1323 return 0;
1324}
1325
Al Viro8d3af7f2013-05-18 03:03:58 -04001326static int fuse_readdir(struct file *file, struct dir_context *ctx)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001327{
Feng Shuo4582a4a2013-01-15 11:23:28 +08001328 int plus, err;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001329 size_t nbytes;
1330 struct page *page;
Al Viro496ad9a2013-01-23 17:07:38 -05001331 struct inode *inode = file_inode(file);
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001332 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi248d86e2006-01-06 00:19:39 -08001333 struct fuse_req *req;
Anand V. Avati0b05b182012-08-19 08:53:23 -04001334 u64 attr_version = 0;
Miklos Szeredi248d86e2006-01-06 00:19:39 -08001335
1336 if (is_bad_inode(inode))
1337 return -EIO;
1338
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001339 req = fuse_get_req(fc, 1);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001340 if (IS_ERR(req))
1341 return PTR_ERR(req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001342
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001343 page = alloc_page(GFP_KERNEL);
1344 if (!page) {
1345 fuse_put_request(fc, req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001346 return -ENOMEM;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001347 }
Feng Shuo4582a4a2013-01-15 11:23:28 +08001348
Al Viro8d3af7f2013-05-18 03:03:58 -04001349 plus = fuse_use_readdirplus(inode, ctx);
Miklos Szeredif4975c62009-04-02 14:25:34 +02001350 req->out.argpages = 1;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001351 req->num_pages = 1;
1352 req->pages[0] = page;
Maxim Patlasov85f40ae2012-10-26 19:49:33 +04001353 req->page_descs[0].length = PAGE_SIZE;
Feng Shuo4582a4a2013-01-15 11:23:28 +08001354 if (plus) {
Anand V. Avati0b05b182012-08-19 08:53:23 -04001355 attr_version = fuse_get_attr_version(fc);
Al Viro8d3af7f2013-05-18 03:03:58 -04001356 fuse_read_fill(req, file, ctx->pos, PAGE_SIZE,
Anand V. Avati0b05b182012-08-19 08:53:23 -04001357 FUSE_READDIRPLUS);
1358 } else {
Al Viro8d3af7f2013-05-18 03:03:58 -04001359 fuse_read_fill(req, file, ctx->pos, PAGE_SIZE,
Anand V. Avati0b05b182012-08-19 08:53:23 -04001360 FUSE_READDIR);
1361 }
Tejun Heob93f8582008-11-26 12:03:55 +01001362 fuse_request_send(fc, req);
Miklos Szeredi361b1eb52006-01-16 22:14:45 -08001363 nbytes = req->out.args[0].size;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001364 err = req->out.h.error;
1365 fuse_put_request(fc, req);
Anand V. Avati0b05b182012-08-19 08:53:23 -04001366 if (!err) {
Feng Shuo4582a4a2013-01-15 11:23:28 +08001367 if (plus) {
Anand V. Avati0b05b182012-08-19 08:53:23 -04001368 err = parse_dirplusfile(page_address(page), nbytes,
Al Viro8d3af7f2013-05-18 03:03:58 -04001369 file, ctx,
Anand V. Avati0b05b182012-08-19 08:53:23 -04001370 attr_version);
1371 } else {
1372 err = parse_dirfile(page_address(page), nbytes, file,
Al Viro8d3af7f2013-05-18 03:03:58 -04001373 ctx);
Anand V. Avati0b05b182012-08-19 08:53:23 -04001374 }
1375 }
Miklos Szeredie5e55582005-09-09 13:10:28 -07001376
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001377 __free_page(page);
Miklos Szeredib36c31b2005-09-09 13:10:38 -07001378 fuse_invalidate_attr(inode); /* atime changed */
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001379 return err;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001380}
1381
1382static char *read_link(struct dentry *dentry)
1383{
1384 struct inode *inode = dentry->d_inode;
1385 struct fuse_conn *fc = get_fuse_conn(inode);
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001386 struct fuse_req *req = fuse_get_req_nopages(fc);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001387 char *link;
1388
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001389 if (IS_ERR(req))
David Howellse231c2e2008-02-07 00:15:26 -08001390 return ERR_CAST(req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001391
1392 link = (char *) __get_free_page(GFP_KERNEL);
1393 if (!link) {
1394 link = ERR_PTR(-ENOMEM);
1395 goto out;
1396 }
1397 req->in.h.opcode = FUSE_READLINK;
1398 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001399 req->out.argvar = 1;
1400 req->out.numargs = 1;
1401 req->out.args[0].size = PAGE_SIZE - 1;
1402 req->out.args[0].value = link;
Tejun Heob93f8582008-11-26 12:03:55 +01001403 fuse_request_send(fc, req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001404 if (req->out.h.error) {
1405 free_page((unsigned long) link);
1406 link = ERR_PTR(req->out.h.error);
1407 } else
1408 link[req->out.args[0].size] = '\0';
1409 out:
1410 fuse_put_request(fc, req);
Miklos Szeredib36c31b2005-09-09 13:10:38 -07001411 fuse_invalidate_attr(inode); /* atime changed */
Miklos Szeredie5e55582005-09-09 13:10:28 -07001412 return link;
1413}
1414
1415static void free_link(char *link)
1416{
1417 if (!IS_ERR(link))
1418 free_page((unsigned long) link);
1419}
1420
1421static void *fuse_follow_link(struct dentry *dentry, struct nameidata *nd)
1422{
1423 nd_set_link(nd, read_link(dentry));
1424 return NULL;
1425}
1426
1427static void fuse_put_link(struct dentry *dentry, struct nameidata *nd, void *c)
1428{
1429 free_link(nd_get_link(nd));
1430}
1431
1432static int fuse_dir_open(struct inode *inode, struct file *file)
1433{
Miklos Szeredi91fe96b2009-04-28 16:56:37 +02001434 return fuse_open_common(inode, file, true);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001435}
1436
1437static int fuse_dir_release(struct inode *inode, struct file *file)
1438{
Miklos Szeredi8b0797a2009-04-28 16:56:39 +02001439 fuse_release_common(file, FUSE_RELEASEDIR);
1440
1441 return 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001442}
1443
Josef Bacik02c24a82011-07-16 20:44:56 -04001444static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end,
1445 int datasync)
Miklos Szeredi82547982005-09-09 13:10:38 -07001446{
Josef Bacik02c24a82011-07-16 20:44:56 -04001447 return fuse_fsync_common(file, start, end, datasync, 1);
Miklos Szeredi82547982005-09-09 13:10:38 -07001448}
1449
Miklos Szeredib18da0c2011-12-13 11:58:49 +01001450static long fuse_dir_ioctl(struct file *file, unsigned int cmd,
1451 unsigned long arg)
1452{
1453 struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1454
1455 /* FUSE_IOCTL_DIR only supported for API version >= 7.18 */
1456 if (fc->minor < 18)
1457 return -ENOTTY;
1458
1459 return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR);
1460}
1461
1462static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd,
1463 unsigned long arg)
1464{
1465 struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1466
1467 if (fc->minor < 18)
1468 return -ENOTTY;
1469
1470 return fuse_ioctl_common(file, cmd, arg,
1471 FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR);
1472}
1473
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001474static bool update_mtime(unsigned ivalid)
1475{
1476 /* Always update if mtime is explicitly set */
1477 if (ivalid & ATTR_MTIME_SET)
1478 return true;
1479
1480 /* If it's an open(O_TRUNC) or an ftruncate(), don't update */
1481 if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
1482 return false;
1483
1484 /* In all other cases update */
1485 return true;
1486}
1487
Miklos Szeredibefc6492005-11-07 00:59:52 -08001488static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001489{
1490 unsigned ivalid = iattr->ia_valid;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001491
1492 if (ivalid & ATTR_MODE)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001493 arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001494 if (ivalid & ATTR_UID)
Eric W. Biederman499dcf22012-02-07 16:26:03 -08001495 arg->valid |= FATTR_UID, arg->uid = from_kuid(&init_user_ns, iattr->ia_uid);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001496 if (ivalid & ATTR_GID)
Eric W. Biederman499dcf22012-02-07 16:26:03 -08001497 arg->valid |= FATTR_GID, arg->gid = from_kgid(&init_user_ns, iattr->ia_gid);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001498 if (ivalid & ATTR_SIZE)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001499 arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001500 if (ivalid & ATTR_ATIME) {
1501 arg->valid |= FATTR_ATIME;
Miklos Szeredibefc6492005-11-07 00:59:52 -08001502 arg->atime = iattr->ia_atime.tv_sec;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001503 arg->atimensec = iattr->ia_atime.tv_nsec;
1504 if (!(ivalid & ATTR_ATIME_SET))
1505 arg->valid |= FATTR_ATIME_NOW;
1506 }
1507 if ((ivalid & ATTR_MTIME) && update_mtime(ivalid)) {
1508 arg->valid |= FATTR_MTIME;
Miklos Szeredibefc6492005-11-07 00:59:52 -08001509 arg->mtime = iattr->ia_mtime.tv_sec;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001510 arg->mtimensec = iattr->ia_mtime.tv_nsec;
1511 if (!(ivalid & ATTR_MTIME_SET))
1512 arg->valid |= FATTR_MTIME_NOW;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001513 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001514}
1515
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001516/*
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001517 * Prevent concurrent writepages on inode
1518 *
1519 * This is done by adding a negative bias to the inode write counter
1520 * and waiting for all pending writes to finish.
1521 */
1522void fuse_set_nowrite(struct inode *inode)
1523{
1524 struct fuse_conn *fc = get_fuse_conn(inode);
1525 struct fuse_inode *fi = get_fuse_inode(inode);
1526
1527 BUG_ON(!mutex_is_locked(&inode->i_mutex));
1528
1529 spin_lock(&fc->lock);
1530 BUG_ON(fi->writectr < 0);
1531 fi->writectr += FUSE_NOWRITE;
1532 spin_unlock(&fc->lock);
1533 wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE);
1534}
1535
1536/*
1537 * Allow writepages on inode
1538 *
1539 * Remove the bias from the writecounter and send any queued
1540 * writepages.
1541 */
1542static void __fuse_release_nowrite(struct inode *inode)
1543{
1544 struct fuse_inode *fi = get_fuse_inode(inode);
1545
1546 BUG_ON(fi->writectr != FUSE_NOWRITE);
1547 fi->writectr = 0;
1548 fuse_flush_writepages(inode);
1549}
1550
1551void fuse_release_nowrite(struct inode *inode)
1552{
1553 struct fuse_conn *fc = get_fuse_conn(inode);
1554
1555 spin_lock(&fc->lock);
1556 __fuse_release_nowrite(inode);
1557 spin_unlock(&fc->lock);
1558}
1559
1560/*
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001561 * Set attributes, and at the same time refresh them.
1562 *
1563 * Truncation is slightly complicated, because the 'truncate' request
1564 * may fail, in which case we don't want to touch the mapping.
Miklos Szeredi9ffbb912006-10-17 00:10:06 -07001565 * vmtruncate() doesn't allow for this case, so do the rlimit checking
1566 * and the actual truncation by hand.
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001567 */
Maxim Patlasovefb9fa92012-12-18 14:05:08 +04001568int fuse_do_setattr(struct inode *inode, struct iattr *attr,
1569 struct file *file)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001570{
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001571 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001572 struct fuse_req *req;
1573 struct fuse_setattr_in inarg;
1574 struct fuse_attr_out outarg;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001575 bool is_truncate = false;
1576 loff_t oldsize;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001577 int err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001578
Christoph Hellwigdb78b872010-06-04 11:30:03 +02001579 if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS))
1580 attr->ia_valid |= ATTR_FORCE;
1581
1582 err = inode_change_ok(inode, attr);
1583 if (err)
1584 return err;
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001585
Miklos Szeredi8d56add2011-02-25 14:44:58 +01001586 if (attr->ia_valid & ATTR_OPEN) {
1587 if (fc->atomic_o_trunc)
1588 return 0;
1589 file = NULL;
1590 }
Miklos Szeredi6ff958e2007-10-18 03:07:02 -07001591
Christoph Hellwig2c27c652010-06-04 11:30:04 +02001592 if (attr->ia_valid & ATTR_SIZE)
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001593 is_truncate = true;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001594
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001595 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001596 if (IS_ERR(req))
1597 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001598
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001599 if (is_truncate)
1600 fuse_set_nowrite(inode);
1601
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001602 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -07001603 memset(&outarg, 0, sizeof(outarg));
Miklos Szeredibefc6492005-11-07 00:59:52 -08001604 iattr_to_fattr(attr, &inarg);
Miklos Szeredi49d49142007-10-18 03:07:00 -07001605 if (file) {
1606 struct fuse_file *ff = file->private_data;
1607 inarg.valid |= FATTR_FH;
1608 inarg.fh = ff->fh;
1609 }
Miklos Szeredif3332112007-10-18 03:07:04 -07001610 if (attr->ia_valid & ATTR_SIZE) {
1611 /* For mandatory locking in truncate */
1612 inarg.valid |= FATTR_LOCKOWNER;
1613 inarg.lock_owner = fuse_lock_owner_id(fc, current->files);
1614 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001615 req->in.h.opcode = FUSE_SETATTR;
1616 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001617 req->in.numargs = 1;
1618 req->in.args[0].size = sizeof(inarg);
1619 req->in.args[0].value = &inarg;
1620 req->out.numargs = 1;
Miklos Szeredi0e9663e2007-10-18 03:07:05 -07001621 if (fc->minor < 9)
1622 req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
1623 else
1624 req->out.args[0].size = sizeof(outarg);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001625 req->out.args[0].value = &outarg;
Tejun Heob93f8582008-11-26 12:03:55 +01001626 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001627 err = req->out.h.error;
1628 fuse_put_request(fc, req);
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001629 if (err) {
1630 if (err == -EINTR)
1631 fuse_invalidate_attr(inode);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001632 goto error;
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001633 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001634
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001635 if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
1636 make_bad_inode(inode);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001637 err = -EIO;
1638 goto error;
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001639 }
1640
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001641 spin_lock(&fc->lock);
1642 fuse_change_attributes_common(inode, &outarg.attr,
1643 attr_timeout(&outarg));
1644 oldsize = inode->i_size;
1645 i_size_write(inode, outarg.attr.size);
1646
1647 if (is_truncate) {
1648 /* NOTE: this may release/reacquire fc->lock */
1649 __fuse_release_nowrite(inode);
1650 }
1651 spin_unlock(&fc->lock);
1652
1653 /*
1654 * Only call invalidate_inode_pages2() after removing
1655 * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock.
1656 */
1657 if (S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
npiggin@suse.dec08d3b02009-08-21 02:35:06 +10001658 truncate_pagecache(inode, oldsize, outarg.attr.size);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001659 invalidate_inode_pages2(inode->i_mapping);
1660 }
1661
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001662 return 0;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001663
1664error:
1665 if (is_truncate)
1666 fuse_release_nowrite(inode);
1667
1668 return err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001669}
1670
Miklos Szeredi49d49142007-10-18 03:07:00 -07001671static int fuse_setattr(struct dentry *entry, struct iattr *attr)
1672{
Maxim Patlasovefb9fa92012-12-18 14:05:08 +04001673 struct inode *inode = entry->d_inode;
1674
1675 if (!fuse_allow_current_process(get_fuse_conn(inode)))
1676 return -EACCES;
1677
Miklos Szeredi49d49142007-10-18 03:07:00 -07001678 if (attr->ia_valid & ATTR_FILE)
Maxim Patlasovefb9fa92012-12-18 14:05:08 +04001679 return fuse_do_setattr(inode, attr, attr->ia_file);
Miklos Szeredi49d49142007-10-18 03:07:00 -07001680 else
Maxim Patlasovefb9fa92012-12-18 14:05:08 +04001681 return fuse_do_setattr(inode, attr, NULL);
Miklos Szeredi49d49142007-10-18 03:07:00 -07001682}
1683
Miklos Szeredie5e55582005-09-09 13:10:28 -07001684static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
1685 struct kstat *stat)
1686{
1687 struct inode *inode = entry->d_inode;
Miklos Szeredi244f6382007-10-16 23:31:02 -07001688 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi244f6382007-10-16 23:31:02 -07001689
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001690 if (!fuse_allow_current_process(fc))
Miklos Szeredi244f6382007-10-16 23:31:02 -07001691 return -EACCES;
1692
Miklos Szeredibcb4be82007-11-28 16:21:59 -08001693 return fuse_update_attributes(inode, stat, NULL, NULL);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001694}
1695
Miklos Szeredi92a87802005-09-09 13:10:31 -07001696static int fuse_setxattr(struct dentry *entry, const char *name,
1697 const void *value, size_t size, int flags)
1698{
1699 struct inode *inode = entry->d_inode;
1700 struct fuse_conn *fc = get_fuse_conn(inode);
1701 struct fuse_req *req;
1702 struct fuse_setxattr_in inarg;
1703 int err;
1704
Miklos Szeredi92a87802005-09-09 13:10:31 -07001705 if (fc->no_setxattr)
1706 return -EOPNOTSUPP;
1707
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001708 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001709 if (IS_ERR(req))
1710 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001711
1712 memset(&inarg, 0, sizeof(inarg));
1713 inarg.size = size;
1714 inarg.flags = flags;
1715 req->in.h.opcode = FUSE_SETXATTR;
1716 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001717 req->in.numargs = 3;
1718 req->in.args[0].size = sizeof(inarg);
1719 req->in.args[0].value = &inarg;
1720 req->in.args[1].size = strlen(name) + 1;
1721 req->in.args[1].value = name;
1722 req->in.args[2].size = size;
1723 req->in.args[2].value = value;
Tejun Heob93f8582008-11-26 12:03:55 +01001724 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001725 err = req->out.h.error;
1726 fuse_put_request(fc, req);
1727 if (err == -ENOSYS) {
1728 fc->no_setxattr = 1;
1729 err = -EOPNOTSUPP;
1730 }
1731 return err;
1732}
1733
1734static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
1735 void *value, size_t size)
1736{
1737 struct inode *inode = entry->d_inode;
1738 struct fuse_conn *fc = get_fuse_conn(inode);
1739 struct fuse_req *req;
1740 struct fuse_getxattr_in inarg;
1741 struct fuse_getxattr_out outarg;
1742 ssize_t ret;
1743
1744 if (fc->no_getxattr)
1745 return -EOPNOTSUPP;
1746
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001747 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001748 if (IS_ERR(req))
1749 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001750
1751 memset(&inarg, 0, sizeof(inarg));
1752 inarg.size = size;
1753 req->in.h.opcode = FUSE_GETXATTR;
1754 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001755 req->in.numargs = 2;
1756 req->in.args[0].size = sizeof(inarg);
1757 req->in.args[0].value = &inarg;
1758 req->in.args[1].size = strlen(name) + 1;
1759 req->in.args[1].value = name;
1760 /* This is really two different operations rolled into one */
1761 req->out.numargs = 1;
1762 if (size) {
1763 req->out.argvar = 1;
1764 req->out.args[0].size = size;
1765 req->out.args[0].value = value;
1766 } else {
1767 req->out.args[0].size = sizeof(outarg);
1768 req->out.args[0].value = &outarg;
1769 }
Tejun Heob93f8582008-11-26 12:03:55 +01001770 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001771 ret = req->out.h.error;
1772 if (!ret)
1773 ret = size ? req->out.args[0].size : outarg.size;
1774 else {
1775 if (ret == -ENOSYS) {
1776 fc->no_getxattr = 1;
1777 ret = -EOPNOTSUPP;
1778 }
1779 }
1780 fuse_put_request(fc, req);
1781 return ret;
1782}
1783
1784static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
1785{
1786 struct inode *inode = entry->d_inode;
1787 struct fuse_conn *fc = get_fuse_conn(inode);
1788 struct fuse_req *req;
1789 struct fuse_getxattr_in inarg;
1790 struct fuse_getxattr_out outarg;
1791 ssize_t ret;
1792
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001793 if (!fuse_allow_current_process(fc))
Miklos Szeredie57ac682007-10-18 03:06:58 -07001794 return -EACCES;
1795
Miklos Szeredi92a87802005-09-09 13:10:31 -07001796 if (fc->no_listxattr)
1797 return -EOPNOTSUPP;
1798
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001799 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001800 if (IS_ERR(req))
1801 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001802
1803 memset(&inarg, 0, sizeof(inarg));
1804 inarg.size = size;
1805 req->in.h.opcode = FUSE_LISTXATTR;
1806 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001807 req->in.numargs = 1;
1808 req->in.args[0].size = sizeof(inarg);
1809 req->in.args[0].value = &inarg;
1810 /* This is really two different operations rolled into one */
1811 req->out.numargs = 1;
1812 if (size) {
1813 req->out.argvar = 1;
1814 req->out.args[0].size = size;
1815 req->out.args[0].value = list;
1816 } else {
1817 req->out.args[0].size = sizeof(outarg);
1818 req->out.args[0].value = &outarg;
1819 }
Tejun Heob93f8582008-11-26 12:03:55 +01001820 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001821 ret = req->out.h.error;
1822 if (!ret)
1823 ret = size ? req->out.args[0].size : outarg.size;
1824 else {
1825 if (ret == -ENOSYS) {
1826 fc->no_listxattr = 1;
1827 ret = -EOPNOTSUPP;
1828 }
1829 }
1830 fuse_put_request(fc, req);
1831 return ret;
1832}
1833
1834static int fuse_removexattr(struct dentry *entry, const char *name)
1835{
1836 struct inode *inode = entry->d_inode;
1837 struct fuse_conn *fc = get_fuse_conn(inode);
1838 struct fuse_req *req;
1839 int err;
1840
1841 if (fc->no_removexattr)
1842 return -EOPNOTSUPP;
1843
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001844 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001845 if (IS_ERR(req))
1846 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001847
1848 req->in.h.opcode = FUSE_REMOVEXATTR;
1849 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001850 req->in.numargs = 1;
1851 req->in.args[0].size = strlen(name) + 1;
1852 req->in.args[0].value = name;
Tejun Heob93f8582008-11-26 12:03:55 +01001853 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001854 err = req->out.h.error;
1855 fuse_put_request(fc, req);
1856 if (err == -ENOSYS) {
1857 fc->no_removexattr = 1;
1858 err = -EOPNOTSUPP;
1859 }
1860 return err;
1861}
1862
Arjan van de Ven754661f2007-02-12 00:55:38 -08001863static const struct inode_operations fuse_dir_inode_operations = {
Miklos Szeredie5e55582005-09-09 13:10:28 -07001864 .lookup = fuse_lookup,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001865 .mkdir = fuse_mkdir,
1866 .symlink = fuse_symlink,
1867 .unlink = fuse_unlink,
1868 .rmdir = fuse_rmdir,
1869 .rename = fuse_rename,
1870 .link = fuse_link,
1871 .setattr = fuse_setattr,
1872 .create = fuse_create,
Miklos Szeredic8ccbe02012-06-05 15:10:22 +02001873 .atomic_open = fuse_atomic_open,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001874 .mknod = fuse_mknod,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001875 .permission = fuse_permission,
1876 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001877 .setxattr = fuse_setxattr,
1878 .getxattr = fuse_getxattr,
1879 .listxattr = fuse_listxattr,
1880 .removexattr = fuse_removexattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001881};
1882
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -08001883static const struct file_operations fuse_dir_operations = {
Miklos Szeredib6aeade2005-09-09 13:10:30 -07001884 .llseek = generic_file_llseek,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001885 .read = generic_read_dir,
Al Viro8d3af7f2013-05-18 03:03:58 -04001886 .iterate = fuse_readdir,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001887 .open = fuse_dir_open,
1888 .release = fuse_dir_release,
Miklos Szeredi82547982005-09-09 13:10:38 -07001889 .fsync = fuse_dir_fsync,
Miklos Szeredib18da0c2011-12-13 11:58:49 +01001890 .unlocked_ioctl = fuse_dir_ioctl,
1891 .compat_ioctl = fuse_dir_compat_ioctl,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001892};
1893
Arjan van de Ven754661f2007-02-12 00:55:38 -08001894static const struct inode_operations fuse_common_inode_operations = {
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001895 .setattr = fuse_setattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001896 .permission = fuse_permission,
1897 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001898 .setxattr = fuse_setxattr,
1899 .getxattr = fuse_getxattr,
1900 .listxattr = fuse_listxattr,
1901 .removexattr = fuse_removexattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001902};
1903
Arjan van de Ven754661f2007-02-12 00:55:38 -08001904static const struct inode_operations fuse_symlink_inode_operations = {
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001905 .setattr = fuse_setattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001906 .follow_link = fuse_follow_link,
1907 .put_link = fuse_put_link,
1908 .readlink = generic_readlink,
1909 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001910 .setxattr = fuse_setxattr,
1911 .getxattr = fuse_getxattr,
1912 .listxattr = fuse_listxattr,
1913 .removexattr = fuse_removexattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001914};
1915
1916void fuse_init_common(struct inode *inode)
1917{
1918 inode->i_op = &fuse_common_inode_operations;
1919}
1920
1921void fuse_init_dir(struct inode *inode)
1922{
1923 inode->i_op = &fuse_dir_inode_operations;
1924 inode->i_fop = &fuse_dir_operations;
1925}
1926
1927void fuse_init_symlink(struct inode *inode)
1928{
1929 inode->i_op = &fuse_symlink_inode_operations;
1930}