blob: 37d85e05b1f5f6719acf3a5d192ea4365a6793b3 [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 }
Miklos Szeredia28ef452013-07-17 14:53:53 +02001226
1227 if (invalid_nodeid(o->nodeid))
1228 return -EIO;
1229 if (!fuse_valid_type(o->attr.mode))
1230 return -EIO;
1231
Anand V. Avati0b05b182012-08-19 08:53:23 -04001232 fc = get_fuse_conn(dir);
1233
1234 name.hash = full_name_hash(name.name, name.len);
1235 dentry = d_lookup(parent, &name);
Niels de Vos53ce9a32013-07-17 14:53:53 +02001236 if (dentry) {
Anand V. Avati0b05b182012-08-19 08:53:23 -04001237 inode = dentry->d_inode;
Niels de Vos53ce9a32013-07-17 14:53:53 +02001238 if (!inode) {
1239 d_drop(dentry);
Miklos Szeredia28ef452013-07-17 14:53:53 +02001240 } else if (get_node_id(inode) != o->nodeid ||
1241 ((o->attr.mode ^ inode->i_mode) & S_IFMT)) {
Niels de Vos53ce9a32013-07-17 14:53:53 +02001242 err = d_invalidate(dentry);
1243 if (err)
1244 goto out;
Miklos Szeredia28ef452013-07-17 14:53:53 +02001245 } else if (is_bad_inode(inode)) {
1246 err = -EIO;
1247 goto out;
Niels de Vos53ce9a32013-07-17 14:53:53 +02001248 } else {
Anand V. Avati0b05b182012-08-19 08:53:23 -04001249 struct fuse_inode *fi;
1250 fi = get_fuse_inode(inode);
1251 spin_lock(&fc->lock);
1252 fi->nlookup++;
1253 spin_unlock(&fc->lock);
1254
Miklos Szeredifa2b7212013-07-17 14:53:53 +02001255 fuse_change_attributes(inode, &o->attr,
1256 entry_attr_timeout(o),
1257 attr_version);
1258
Anand V. Avati0b05b182012-08-19 08:53:23 -04001259 /*
1260 * The other branch to 'found' comes via fuse_iget()
1261 * which bumps nlookup inside
1262 */
1263 goto found;
1264 }
Anand V. Avati0b05b182012-08-19 08:53:23 -04001265 dput(dentry);
1266 dentry = NULL;
1267 }
1268
1269 dentry = d_alloc(parent, &name);
1270 err = -ENOMEM;
1271 if (!dentry)
1272 goto out;
1273
1274 inode = fuse_iget(dir->i_sb, o->nodeid, o->generation,
1275 &o->attr, entry_attr_timeout(o), attr_version);
1276 if (!inode)
1277 goto out;
1278
Miklos Szeredi29149412013-07-17 14:53:53 +02001279 if (S_ISDIR(inode->i_mode)) {
1280 mutex_lock(&fc->inst_mutex);
1281 alias = fuse_d_add_directory(dentry, inode);
1282 mutex_unlock(&fc->inst_mutex);
1283 err = PTR_ERR(alias);
1284 if (IS_ERR(alias)) {
1285 iput(inode);
1286 goto out;
1287 }
1288 } else {
1289 alias = d_splice_alias(inode, dentry);
1290 }
1291
Anand V. Avati0b05b182012-08-19 08:53:23 -04001292 if (alias) {
1293 dput(dentry);
1294 dentry = alias;
1295 }
1296
1297found:
Anand V. Avati0b05b182012-08-19 08:53:23 -04001298 fuse_change_entry_timeout(dentry, o);
1299
1300 err = 0;
1301out:
1302 if (dentry)
1303 dput(dentry);
1304 return err;
1305}
1306
1307static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file,
Al Viro8d3af7f2013-05-18 03:03:58 -04001308 struct dir_context *ctx, u64 attr_version)
Anand V. Avati0b05b182012-08-19 08:53:23 -04001309{
1310 struct fuse_direntplus *direntplus;
1311 struct fuse_dirent *dirent;
1312 size_t reclen;
1313 int over = 0;
1314 int ret;
1315
1316 while (nbytes >= FUSE_NAME_OFFSET_DIRENTPLUS) {
1317 direntplus = (struct fuse_direntplus *) buf;
1318 dirent = &direntplus->dirent;
1319 reclen = FUSE_DIRENTPLUS_SIZE(direntplus);
1320
1321 if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
1322 return -EIO;
1323 if (reclen > nbytes)
1324 break;
1325
1326 if (!over) {
1327 /* We fill entries into dstbuf only as much as
1328 it can hold. But we still continue iterating
1329 over remaining entries to link them. If not,
1330 we need to send a FORGET for each of those
1331 which we did not link.
1332 */
Al Viro8d3af7f2013-05-18 03:03:58 -04001333 over = !dir_emit(ctx, dirent->name, dirent->namelen,
1334 dirent->ino, dirent->type);
1335 ctx->pos = dirent->off;
Anand V. Avati0b05b182012-08-19 08:53:23 -04001336 }
1337
1338 buf += reclen;
1339 nbytes -= reclen;
1340
1341 ret = fuse_direntplus_link(file, direntplus, attr_version);
1342 if (ret)
1343 fuse_force_forget(file, direntplus->entry_out.nodeid);
1344 }
1345
1346 return 0;
1347}
1348
Al Viro8d3af7f2013-05-18 03:03:58 -04001349static int fuse_readdir(struct file *file, struct dir_context *ctx)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001350{
Feng Shuo4582a4a2013-01-15 11:23:28 +08001351 int plus, err;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001352 size_t nbytes;
1353 struct page *page;
Al Viro496ad9a2013-01-23 17:07:38 -05001354 struct inode *inode = file_inode(file);
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001355 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi248d86e2006-01-06 00:19:39 -08001356 struct fuse_req *req;
Anand V. Avati0b05b182012-08-19 08:53:23 -04001357 u64 attr_version = 0;
Miklos Szeredi248d86e2006-01-06 00:19:39 -08001358
1359 if (is_bad_inode(inode))
1360 return -EIO;
1361
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001362 req = fuse_get_req(fc, 1);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001363 if (IS_ERR(req))
1364 return PTR_ERR(req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001365
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001366 page = alloc_page(GFP_KERNEL);
1367 if (!page) {
1368 fuse_put_request(fc, req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001369 return -ENOMEM;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001370 }
Feng Shuo4582a4a2013-01-15 11:23:28 +08001371
Al Viro8d3af7f2013-05-18 03:03:58 -04001372 plus = fuse_use_readdirplus(inode, ctx);
Miklos Szeredif4975c62009-04-02 14:25:34 +02001373 req->out.argpages = 1;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001374 req->num_pages = 1;
1375 req->pages[0] = page;
Maxim Patlasov85f40ae2012-10-26 19:49:33 +04001376 req->page_descs[0].length = PAGE_SIZE;
Feng Shuo4582a4a2013-01-15 11:23:28 +08001377 if (plus) {
Anand V. Avati0b05b182012-08-19 08:53:23 -04001378 attr_version = fuse_get_attr_version(fc);
Al Viro8d3af7f2013-05-18 03:03:58 -04001379 fuse_read_fill(req, file, ctx->pos, PAGE_SIZE,
Anand V. Avati0b05b182012-08-19 08:53:23 -04001380 FUSE_READDIRPLUS);
1381 } else {
Al Viro8d3af7f2013-05-18 03:03:58 -04001382 fuse_read_fill(req, file, ctx->pos, PAGE_SIZE,
Anand V. Avati0b05b182012-08-19 08:53:23 -04001383 FUSE_READDIR);
1384 }
Tejun Heob93f8582008-11-26 12:03:55 +01001385 fuse_request_send(fc, req);
Miklos Szeredi361b1eb52006-01-16 22:14:45 -08001386 nbytes = req->out.args[0].size;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001387 err = req->out.h.error;
1388 fuse_put_request(fc, req);
Anand V. Avati0b05b182012-08-19 08:53:23 -04001389 if (!err) {
Feng Shuo4582a4a2013-01-15 11:23:28 +08001390 if (plus) {
Anand V. Avati0b05b182012-08-19 08:53:23 -04001391 err = parse_dirplusfile(page_address(page), nbytes,
Al Viro8d3af7f2013-05-18 03:03:58 -04001392 file, ctx,
Anand V. Avati0b05b182012-08-19 08:53:23 -04001393 attr_version);
1394 } else {
1395 err = parse_dirfile(page_address(page), nbytes, file,
Al Viro8d3af7f2013-05-18 03:03:58 -04001396 ctx);
Anand V. Avati0b05b182012-08-19 08:53:23 -04001397 }
1398 }
Miklos Szeredie5e55582005-09-09 13:10:28 -07001399
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001400 __free_page(page);
Miklos Szeredib36c31b2005-09-09 13:10:38 -07001401 fuse_invalidate_attr(inode); /* atime changed */
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001402 return err;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001403}
1404
1405static char *read_link(struct dentry *dentry)
1406{
1407 struct inode *inode = dentry->d_inode;
1408 struct fuse_conn *fc = get_fuse_conn(inode);
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001409 struct fuse_req *req = fuse_get_req_nopages(fc);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001410 char *link;
1411
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001412 if (IS_ERR(req))
David Howellse231c2e2008-02-07 00:15:26 -08001413 return ERR_CAST(req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001414
1415 link = (char *) __get_free_page(GFP_KERNEL);
1416 if (!link) {
1417 link = ERR_PTR(-ENOMEM);
1418 goto out;
1419 }
1420 req->in.h.opcode = FUSE_READLINK;
1421 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001422 req->out.argvar = 1;
1423 req->out.numargs = 1;
1424 req->out.args[0].size = PAGE_SIZE - 1;
1425 req->out.args[0].value = link;
Tejun Heob93f8582008-11-26 12:03:55 +01001426 fuse_request_send(fc, req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001427 if (req->out.h.error) {
1428 free_page((unsigned long) link);
1429 link = ERR_PTR(req->out.h.error);
1430 } else
1431 link[req->out.args[0].size] = '\0';
1432 out:
1433 fuse_put_request(fc, req);
Miklos Szeredib36c31b2005-09-09 13:10:38 -07001434 fuse_invalidate_attr(inode); /* atime changed */
Miklos Szeredie5e55582005-09-09 13:10:28 -07001435 return link;
1436}
1437
1438static void free_link(char *link)
1439{
1440 if (!IS_ERR(link))
1441 free_page((unsigned long) link);
1442}
1443
1444static void *fuse_follow_link(struct dentry *dentry, struct nameidata *nd)
1445{
1446 nd_set_link(nd, read_link(dentry));
1447 return NULL;
1448}
1449
1450static void fuse_put_link(struct dentry *dentry, struct nameidata *nd, void *c)
1451{
1452 free_link(nd_get_link(nd));
1453}
1454
1455static int fuse_dir_open(struct inode *inode, struct file *file)
1456{
Miklos Szeredi91fe96b2009-04-28 16:56:37 +02001457 return fuse_open_common(inode, file, true);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001458}
1459
1460static int fuse_dir_release(struct inode *inode, struct file *file)
1461{
Miklos Szeredi8b0797a2009-04-28 16:56:39 +02001462 fuse_release_common(file, FUSE_RELEASEDIR);
1463
1464 return 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001465}
1466
Josef Bacik02c24a82011-07-16 20:44:56 -04001467static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end,
1468 int datasync)
Miklos Szeredi82547982005-09-09 13:10:38 -07001469{
Josef Bacik02c24a82011-07-16 20:44:56 -04001470 return fuse_fsync_common(file, start, end, datasync, 1);
Miklos Szeredi82547982005-09-09 13:10:38 -07001471}
1472
Miklos Szeredib18da0c2011-12-13 11:58:49 +01001473static long fuse_dir_ioctl(struct file *file, unsigned int cmd,
1474 unsigned long arg)
1475{
1476 struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1477
1478 /* FUSE_IOCTL_DIR only supported for API version >= 7.18 */
1479 if (fc->minor < 18)
1480 return -ENOTTY;
1481
1482 return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR);
1483}
1484
1485static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd,
1486 unsigned long arg)
1487{
1488 struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1489
1490 if (fc->minor < 18)
1491 return -ENOTTY;
1492
1493 return fuse_ioctl_common(file, cmd, arg,
1494 FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR);
1495}
1496
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001497static bool update_mtime(unsigned ivalid)
1498{
1499 /* Always update if mtime is explicitly set */
1500 if (ivalid & ATTR_MTIME_SET)
1501 return true;
1502
1503 /* If it's an open(O_TRUNC) or an ftruncate(), don't update */
1504 if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
1505 return false;
1506
1507 /* In all other cases update */
1508 return true;
1509}
1510
Miklos Szeredibefc6492005-11-07 00:59:52 -08001511static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001512{
1513 unsigned ivalid = iattr->ia_valid;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001514
1515 if (ivalid & ATTR_MODE)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001516 arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001517 if (ivalid & ATTR_UID)
Eric W. Biederman499dcf22012-02-07 16:26:03 -08001518 arg->valid |= FATTR_UID, arg->uid = from_kuid(&init_user_ns, iattr->ia_uid);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001519 if (ivalid & ATTR_GID)
Eric W. Biederman499dcf22012-02-07 16:26:03 -08001520 arg->valid |= FATTR_GID, arg->gid = from_kgid(&init_user_ns, iattr->ia_gid);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001521 if (ivalid & ATTR_SIZE)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001522 arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001523 if (ivalid & ATTR_ATIME) {
1524 arg->valid |= FATTR_ATIME;
Miklos Szeredibefc6492005-11-07 00:59:52 -08001525 arg->atime = iattr->ia_atime.tv_sec;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001526 arg->atimensec = iattr->ia_atime.tv_nsec;
1527 if (!(ivalid & ATTR_ATIME_SET))
1528 arg->valid |= FATTR_ATIME_NOW;
1529 }
1530 if ((ivalid & ATTR_MTIME) && update_mtime(ivalid)) {
1531 arg->valid |= FATTR_MTIME;
Miklos Szeredibefc6492005-11-07 00:59:52 -08001532 arg->mtime = iattr->ia_mtime.tv_sec;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001533 arg->mtimensec = iattr->ia_mtime.tv_nsec;
1534 if (!(ivalid & ATTR_MTIME_SET))
1535 arg->valid |= FATTR_MTIME_NOW;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001536 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001537}
1538
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001539/*
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001540 * Prevent concurrent writepages on inode
1541 *
1542 * This is done by adding a negative bias to the inode write counter
1543 * and waiting for all pending writes to finish.
1544 */
1545void fuse_set_nowrite(struct inode *inode)
1546{
1547 struct fuse_conn *fc = get_fuse_conn(inode);
1548 struct fuse_inode *fi = get_fuse_inode(inode);
1549
1550 BUG_ON(!mutex_is_locked(&inode->i_mutex));
1551
1552 spin_lock(&fc->lock);
1553 BUG_ON(fi->writectr < 0);
1554 fi->writectr += FUSE_NOWRITE;
1555 spin_unlock(&fc->lock);
1556 wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE);
1557}
1558
1559/*
1560 * Allow writepages on inode
1561 *
1562 * Remove the bias from the writecounter and send any queued
1563 * writepages.
1564 */
1565static void __fuse_release_nowrite(struct inode *inode)
1566{
1567 struct fuse_inode *fi = get_fuse_inode(inode);
1568
1569 BUG_ON(fi->writectr != FUSE_NOWRITE);
1570 fi->writectr = 0;
1571 fuse_flush_writepages(inode);
1572}
1573
1574void fuse_release_nowrite(struct inode *inode)
1575{
1576 struct fuse_conn *fc = get_fuse_conn(inode);
1577
1578 spin_lock(&fc->lock);
1579 __fuse_release_nowrite(inode);
1580 spin_unlock(&fc->lock);
1581}
1582
1583/*
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001584 * Set attributes, and at the same time refresh them.
1585 *
1586 * Truncation is slightly complicated, because the 'truncate' request
1587 * may fail, in which case we don't want to touch the mapping.
Miklos Szeredi9ffbb912006-10-17 00:10:06 -07001588 * vmtruncate() doesn't allow for this case, so do the rlimit checking
1589 * and the actual truncation by hand.
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001590 */
Maxim Patlasovefb9fa92012-12-18 14:05:08 +04001591int fuse_do_setattr(struct inode *inode, struct iattr *attr,
1592 struct file *file)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001593{
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001594 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001595 struct fuse_req *req;
1596 struct fuse_setattr_in inarg;
1597 struct fuse_attr_out outarg;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001598 bool is_truncate = false;
1599 loff_t oldsize;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001600 int err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001601
Christoph Hellwigdb78b872010-06-04 11:30:03 +02001602 if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS))
1603 attr->ia_valid |= ATTR_FORCE;
1604
1605 err = inode_change_ok(inode, attr);
1606 if (err)
1607 return err;
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001608
Miklos Szeredi8d56add2011-02-25 14:44:58 +01001609 if (attr->ia_valid & ATTR_OPEN) {
1610 if (fc->atomic_o_trunc)
1611 return 0;
1612 file = NULL;
1613 }
Miklos Szeredi6ff958e2007-10-18 03:07:02 -07001614
Christoph Hellwig2c27c652010-06-04 11:30:04 +02001615 if (attr->ia_valid & ATTR_SIZE)
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001616 is_truncate = true;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001617
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001618 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001619 if (IS_ERR(req))
1620 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001621
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001622 if (is_truncate)
1623 fuse_set_nowrite(inode);
1624
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001625 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -07001626 memset(&outarg, 0, sizeof(outarg));
Miklos Szeredibefc6492005-11-07 00:59:52 -08001627 iattr_to_fattr(attr, &inarg);
Miklos Szeredi49d49142007-10-18 03:07:00 -07001628 if (file) {
1629 struct fuse_file *ff = file->private_data;
1630 inarg.valid |= FATTR_FH;
1631 inarg.fh = ff->fh;
1632 }
Miklos Szeredif3332112007-10-18 03:07:04 -07001633 if (attr->ia_valid & ATTR_SIZE) {
1634 /* For mandatory locking in truncate */
1635 inarg.valid |= FATTR_LOCKOWNER;
1636 inarg.lock_owner = fuse_lock_owner_id(fc, current->files);
1637 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001638 req->in.h.opcode = FUSE_SETATTR;
1639 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001640 req->in.numargs = 1;
1641 req->in.args[0].size = sizeof(inarg);
1642 req->in.args[0].value = &inarg;
1643 req->out.numargs = 1;
Miklos Szeredi0e9663e2007-10-18 03:07:05 -07001644 if (fc->minor < 9)
1645 req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
1646 else
1647 req->out.args[0].size = sizeof(outarg);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001648 req->out.args[0].value = &outarg;
Tejun Heob93f8582008-11-26 12:03:55 +01001649 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001650 err = req->out.h.error;
1651 fuse_put_request(fc, req);
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001652 if (err) {
1653 if (err == -EINTR)
1654 fuse_invalidate_attr(inode);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001655 goto error;
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001656 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001657
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001658 if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
1659 make_bad_inode(inode);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001660 err = -EIO;
1661 goto error;
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001662 }
1663
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001664 spin_lock(&fc->lock);
1665 fuse_change_attributes_common(inode, &outarg.attr,
1666 attr_timeout(&outarg));
1667 oldsize = inode->i_size;
1668 i_size_write(inode, outarg.attr.size);
1669
1670 if (is_truncate) {
1671 /* NOTE: this may release/reacquire fc->lock */
1672 __fuse_release_nowrite(inode);
1673 }
1674 spin_unlock(&fc->lock);
1675
1676 /*
1677 * Only call invalidate_inode_pages2() after removing
1678 * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock.
1679 */
1680 if (S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
npiggin@suse.dec08d3b02009-08-21 02:35:06 +10001681 truncate_pagecache(inode, oldsize, outarg.attr.size);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001682 invalidate_inode_pages2(inode->i_mapping);
1683 }
1684
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001685 return 0;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001686
1687error:
1688 if (is_truncate)
1689 fuse_release_nowrite(inode);
1690
1691 return err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001692}
1693
Miklos Szeredi49d49142007-10-18 03:07:00 -07001694static int fuse_setattr(struct dentry *entry, struct iattr *attr)
1695{
Maxim Patlasovefb9fa92012-12-18 14:05:08 +04001696 struct inode *inode = entry->d_inode;
1697
1698 if (!fuse_allow_current_process(get_fuse_conn(inode)))
1699 return -EACCES;
1700
Miklos Szeredi49d49142007-10-18 03:07:00 -07001701 if (attr->ia_valid & ATTR_FILE)
Maxim Patlasovefb9fa92012-12-18 14:05:08 +04001702 return fuse_do_setattr(inode, attr, attr->ia_file);
Miklos Szeredi49d49142007-10-18 03:07:00 -07001703 else
Maxim Patlasovefb9fa92012-12-18 14:05:08 +04001704 return fuse_do_setattr(inode, attr, NULL);
Miklos Szeredi49d49142007-10-18 03:07:00 -07001705}
1706
Miklos Szeredie5e55582005-09-09 13:10:28 -07001707static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
1708 struct kstat *stat)
1709{
1710 struct inode *inode = entry->d_inode;
Miklos Szeredi244f6382007-10-16 23:31:02 -07001711 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi244f6382007-10-16 23:31:02 -07001712
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001713 if (!fuse_allow_current_process(fc))
Miklos Szeredi244f6382007-10-16 23:31:02 -07001714 return -EACCES;
1715
Miklos Szeredibcb4be82007-11-28 16:21:59 -08001716 return fuse_update_attributes(inode, stat, NULL, NULL);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001717}
1718
Miklos Szeredi92a87802005-09-09 13:10:31 -07001719static int fuse_setxattr(struct dentry *entry, const char *name,
1720 const void *value, size_t size, int flags)
1721{
1722 struct inode *inode = entry->d_inode;
1723 struct fuse_conn *fc = get_fuse_conn(inode);
1724 struct fuse_req *req;
1725 struct fuse_setxattr_in inarg;
1726 int err;
1727
Miklos Szeredi92a87802005-09-09 13:10:31 -07001728 if (fc->no_setxattr)
1729 return -EOPNOTSUPP;
1730
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001731 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001732 if (IS_ERR(req))
1733 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001734
1735 memset(&inarg, 0, sizeof(inarg));
1736 inarg.size = size;
1737 inarg.flags = flags;
1738 req->in.h.opcode = FUSE_SETXATTR;
1739 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001740 req->in.numargs = 3;
1741 req->in.args[0].size = sizeof(inarg);
1742 req->in.args[0].value = &inarg;
1743 req->in.args[1].size = strlen(name) + 1;
1744 req->in.args[1].value = name;
1745 req->in.args[2].size = size;
1746 req->in.args[2].value = value;
Tejun Heob93f8582008-11-26 12:03:55 +01001747 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001748 err = req->out.h.error;
1749 fuse_put_request(fc, req);
1750 if (err == -ENOSYS) {
1751 fc->no_setxattr = 1;
1752 err = -EOPNOTSUPP;
1753 }
1754 return err;
1755}
1756
1757static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
1758 void *value, size_t size)
1759{
1760 struct inode *inode = entry->d_inode;
1761 struct fuse_conn *fc = get_fuse_conn(inode);
1762 struct fuse_req *req;
1763 struct fuse_getxattr_in inarg;
1764 struct fuse_getxattr_out outarg;
1765 ssize_t ret;
1766
1767 if (fc->no_getxattr)
1768 return -EOPNOTSUPP;
1769
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001770 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001771 if (IS_ERR(req))
1772 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001773
1774 memset(&inarg, 0, sizeof(inarg));
1775 inarg.size = size;
1776 req->in.h.opcode = FUSE_GETXATTR;
1777 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001778 req->in.numargs = 2;
1779 req->in.args[0].size = sizeof(inarg);
1780 req->in.args[0].value = &inarg;
1781 req->in.args[1].size = strlen(name) + 1;
1782 req->in.args[1].value = name;
1783 /* This is really two different operations rolled into one */
1784 req->out.numargs = 1;
1785 if (size) {
1786 req->out.argvar = 1;
1787 req->out.args[0].size = size;
1788 req->out.args[0].value = value;
1789 } else {
1790 req->out.args[0].size = sizeof(outarg);
1791 req->out.args[0].value = &outarg;
1792 }
Tejun Heob93f8582008-11-26 12:03:55 +01001793 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001794 ret = req->out.h.error;
1795 if (!ret)
1796 ret = size ? req->out.args[0].size : outarg.size;
1797 else {
1798 if (ret == -ENOSYS) {
1799 fc->no_getxattr = 1;
1800 ret = -EOPNOTSUPP;
1801 }
1802 }
1803 fuse_put_request(fc, req);
1804 return ret;
1805}
1806
1807static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
1808{
1809 struct inode *inode = entry->d_inode;
1810 struct fuse_conn *fc = get_fuse_conn(inode);
1811 struct fuse_req *req;
1812 struct fuse_getxattr_in inarg;
1813 struct fuse_getxattr_out outarg;
1814 ssize_t ret;
1815
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001816 if (!fuse_allow_current_process(fc))
Miklos Szeredie57ac682007-10-18 03:06:58 -07001817 return -EACCES;
1818
Miklos Szeredi92a87802005-09-09 13:10:31 -07001819 if (fc->no_listxattr)
1820 return -EOPNOTSUPP;
1821
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001822 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001823 if (IS_ERR(req))
1824 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001825
1826 memset(&inarg, 0, sizeof(inarg));
1827 inarg.size = size;
1828 req->in.h.opcode = FUSE_LISTXATTR;
1829 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001830 req->in.numargs = 1;
1831 req->in.args[0].size = sizeof(inarg);
1832 req->in.args[0].value = &inarg;
1833 /* This is really two different operations rolled into one */
1834 req->out.numargs = 1;
1835 if (size) {
1836 req->out.argvar = 1;
1837 req->out.args[0].size = size;
1838 req->out.args[0].value = list;
1839 } else {
1840 req->out.args[0].size = sizeof(outarg);
1841 req->out.args[0].value = &outarg;
1842 }
Tejun Heob93f8582008-11-26 12:03:55 +01001843 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001844 ret = req->out.h.error;
1845 if (!ret)
1846 ret = size ? req->out.args[0].size : outarg.size;
1847 else {
1848 if (ret == -ENOSYS) {
1849 fc->no_listxattr = 1;
1850 ret = -EOPNOTSUPP;
1851 }
1852 }
1853 fuse_put_request(fc, req);
1854 return ret;
1855}
1856
1857static int fuse_removexattr(struct dentry *entry, const char *name)
1858{
1859 struct inode *inode = entry->d_inode;
1860 struct fuse_conn *fc = get_fuse_conn(inode);
1861 struct fuse_req *req;
1862 int err;
1863
1864 if (fc->no_removexattr)
1865 return -EOPNOTSUPP;
1866
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001867 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001868 if (IS_ERR(req))
1869 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001870
1871 req->in.h.opcode = FUSE_REMOVEXATTR;
1872 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001873 req->in.numargs = 1;
1874 req->in.args[0].size = strlen(name) + 1;
1875 req->in.args[0].value = name;
Tejun Heob93f8582008-11-26 12:03:55 +01001876 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001877 err = req->out.h.error;
1878 fuse_put_request(fc, req);
1879 if (err == -ENOSYS) {
1880 fc->no_removexattr = 1;
1881 err = -EOPNOTSUPP;
1882 }
1883 return err;
1884}
1885
Arjan van de Ven754661f2007-02-12 00:55:38 -08001886static const struct inode_operations fuse_dir_inode_operations = {
Miklos Szeredie5e55582005-09-09 13:10:28 -07001887 .lookup = fuse_lookup,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001888 .mkdir = fuse_mkdir,
1889 .symlink = fuse_symlink,
1890 .unlink = fuse_unlink,
1891 .rmdir = fuse_rmdir,
1892 .rename = fuse_rename,
1893 .link = fuse_link,
1894 .setattr = fuse_setattr,
1895 .create = fuse_create,
Miklos Szeredic8ccbe02012-06-05 15:10:22 +02001896 .atomic_open = fuse_atomic_open,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001897 .mknod = fuse_mknod,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001898 .permission = fuse_permission,
1899 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001900 .setxattr = fuse_setxattr,
1901 .getxattr = fuse_getxattr,
1902 .listxattr = fuse_listxattr,
1903 .removexattr = fuse_removexattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001904};
1905
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -08001906static const struct file_operations fuse_dir_operations = {
Miklos Szeredib6aeade2005-09-09 13:10:30 -07001907 .llseek = generic_file_llseek,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001908 .read = generic_read_dir,
Al Viro8d3af7f2013-05-18 03:03:58 -04001909 .iterate = fuse_readdir,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001910 .open = fuse_dir_open,
1911 .release = fuse_dir_release,
Miklos Szeredi82547982005-09-09 13:10:38 -07001912 .fsync = fuse_dir_fsync,
Miklos Szeredib18da0c2011-12-13 11:58:49 +01001913 .unlocked_ioctl = fuse_dir_ioctl,
1914 .compat_ioctl = fuse_dir_compat_ioctl,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001915};
1916
Arjan van de Ven754661f2007-02-12 00:55:38 -08001917static const struct inode_operations fuse_common_inode_operations = {
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001918 .setattr = fuse_setattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001919 .permission = fuse_permission,
1920 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001921 .setxattr = fuse_setxattr,
1922 .getxattr = fuse_getxattr,
1923 .listxattr = fuse_listxattr,
1924 .removexattr = fuse_removexattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001925};
1926
Arjan van de Ven754661f2007-02-12 00:55:38 -08001927static const struct inode_operations fuse_symlink_inode_operations = {
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001928 .setattr = fuse_setattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001929 .follow_link = fuse_follow_link,
1930 .put_link = fuse_put_link,
1931 .readlink = generic_readlink,
1932 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001933 .setxattr = fuse_setxattr,
1934 .getxattr = fuse_getxattr,
1935 .listxattr = fuse_listxattr,
1936 .removexattr = fuse_removexattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001937};
1938
1939void fuse_init_common(struct inode *inode)
1940{
1941 inode->i_op = &fuse_common_inode_operations;
1942}
1943
1944void fuse_init_dir(struct inode *inode)
1945{
1946 inode->i_op = &fuse_dir_inode_operations;
1947 inode->i_fop = &fuse_dir_operations;
1948}
1949
1950void fuse_init_symlink(struct inode *inode)
1951{
1952 inode->i_op = &fuse_symlink_inode_operations;
1953}