blob: 07f4b5e675fcdb3f47c7886e42a5d3588e5f0046 [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>
13#include <linux/gfp.h>
14#include <linux/sched.h>
15#include <linux/namei.h>
16
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070017#if BITS_PER_LONG >= 64
18static inline void fuse_dentry_settime(struct dentry *entry, u64 time)
19{
20 entry->d_time = time;
21}
22
23static inline u64 fuse_dentry_time(struct dentry *entry)
24{
25 return entry->d_time;
26}
27#else
28/*
29 * On 32 bit archs store the high 32 bits of time in d_fsdata
30 */
31static void fuse_dentry_settime(struct dentry *entry, u64 time)
32{
33 entry->d_time = time;
34 entry->d_fsdata = (void *) (unsigned long) (time >> 32);
35}
36
37static u64 fuse_dentry_time(struct dentry *entry)
38{
39 return (u64) entry->d_time +
40 ((u64) (unsigned long) entry->d_fsdata << 32);
41}
42#endif
43
Miklos Szeredi6f9f1182006-01-06 00:19:39 -080044/*
45 * FUSE caches dentries and attributes with separate timeout. The
46 * time in jiffies until the dentry/attributes are valid is stored in
47 * dentry->d_time and fuse_inode->i_time respectively.
48 */
49
50/*
51 * Calculate the time in jiffies until a dentry/attributes are valid
52 */
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070053static u64 time_to_jiffies(unsigned long sec, unsigned long nsec)
Miklos Szeredie5e55582005-09-09 13:10:28 -070054{
Miklos Szeredi685d16d2006-07-30 03:04:08 -070055 if (sec || nsec) {
56 struct timespec ts = {sec, nsec};
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070057 return get_jiffies_64() + timespec_to_jiffies(&ts);
Miklos Szeredi685d16d2006-07-30 03:04:08 -070058 } else
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070059 return 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -070060}
61
Miklos Szeredi6f9f1182006-01-06 00:19:39 -080062/*
63 * Set dentry and possibly attribute timeouts from the lookup/mk*
64 * replies
65 */
Miklos Szeredi1fb69e72007-10-18 03:06:58 -070066static void fuse_change_entry_timeout(struct dentry *entry,
67 struct fuse_entry_out *o)
Miklos Szeredi0aa7c692006-01-06 00:19:34 -080068{
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070069 fuse_dentry_settime(entry,
70 time_to_jiffies(o->entry_valid, o->entry_valid_nsec));
Miklos Szeredi1fb69e72007-10-18 03:06:58 -070071}
72
73static u64 attr_timeout(struct fuse_attr_out *o)
74{
75 return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
76}
77
78static u64 entry_attr_timeout(struct fuse_entry_out *o)
79{
80 return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -080081}
82
Miklos Szeredi6f9f1182006-01-06 00:19:39 -080083/*
84 * Mark the attributes as stale, so that at the next call to
85 * ->getattr() they will be fetched from userspace
86 */
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -080087void fuse_invalidate_attr(struct inode *inode)
88{
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070089 get_fuse_inode(inode)->i_time = 0;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -080090}
91
Miklos Szeredi6f9f1182006-01-06 00:19:39 -080092/*
93 * Just mark the entry as stale, so that a next attempt to look it up
94 * will result in a new lookup call to userspace
95 *
96 * This is called when a dentry is about to become negative and the
97 * timeout is unknown (unlink, rmdir, rename and in some cases
98 * lookup)
99 */
Miklos Szeredidbd561d2008-07-25 01:49:00 -0700100void fuse_invalidate_entry_cache(struct dentry *entry)
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800101{
Miklos Szeredi0a0898c2006-07-30 03:04:10 -0700102 fuse_dentry_settime(entry, 0);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800103}
104
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800105/*
106 * Same as fuse_invalidate_entry_cache(), but also try to remove the
107 * dentry from the hash
108 */
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800109static void fuse_invalidate_entry(struct dentry *entry)
110{
111 d_invalidate(entry);
112 fuse_invalidate_entry_cache(entry);
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800113}
114
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700115static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_req *req,
116 u64 nodeid, struct qstr *name,
Miklos Szeredie5e55582005-09-09 13:10:28 -0700117 struct fuse_entry_out *outarg)
118{
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700119 memset(outarg, 0, sizeof(struct fuse_entry_out));
Miklos Szeredie5e55582005-09-09 13:10:28 -0700120 req->in.h.opcode = FUSE_LOOKUP;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700121 req->in.h.nodeid = nodeid;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700122 req->in.numargs = 1;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700123 req->in.args[0].size = name->len + 1;
124 req->in.args[0].value = name->name;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700125 req->out.numargs = 1;
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700126 if (fc->minor < 9)
127 req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
128 else
129 req->out.args[0].size = sizeof(struct fuse_entry_out);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700130 req->out.args[0].value = outarg;
131}
132
Miklos Szeredi5c5c5e52008-04-30 00:54:43 -0700133u64 fuse_get_attr_version(struct fuse_conn *fc)
Miklos Szeredi7dca9fd2007-11-28 16:21:59 -0800134{
135 u64 curr_version;
136
137 /*
138 * The spin lock isn't actually needed on 64bit archs, but we
139 * don't yet care too much about such optimizations.
140 */
141 spin_lock(&fc->lock);
142 curr_version = fc->attr_version;
143 spin_unlock(&fc->lock);
144
145 return curr_version;
146}
147
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800148/*
149 * Check whether the dentry is still valid
150 *
151 * If the entry validity timeout has expired and the dentry is
152 * positive, try to redo the lookup. If the lookup results in a
153 * different inode, then let the VFS invalidate the dentry and redo
154 * the lookup once more. If the lookup results in the same inode,
155 * then refresh the attributes, timeouts and mark the dentry valid.
156 */
Miklos Szeredie5e55582005-09-09 13:10:28 -0700157static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
158{
Nick Piggin34286d62011-01-07 17:49:57 +1100159 struct inode *inode;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800160
Nick Piggin34286d62011-01-07 17:49:57 +1100161 if (nd->flags & LOOKUP_RCU)
162 return -ECHILD;
163
164 inode = entry->d_inode;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800165 if (inode && is_bad_inode(inode))
Miklos Szeredie5e55582005-09-09 13:10:28 -0700166 return 0;
Miklos Szeredi0a0898c2006-07-30 03:04:10 -0700167 else if (fuse_dentry_time(entry) < get_jiffies_64()) {
Miklos Szeredie5e55582005-09-09 13:10:28 -0700168 int err;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700169 struct fuse_entry_out outarg;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800170 struct fuse_conn *fc;
171 struct fuse_req *req;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800172 struct fuse_req *forget_req;
Miklos Szeredie956edd2006-10-17 00:10:12 -0700173 struct dentry *parent;
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700174 u64 attr_version;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800175
Miklos Szeredi50322fe2006-02-28 16:59:03 -0800176 /* For negative dentries, always do a fresh lookup */
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800177 if (!inode)
178 return 0;
179
180 fc = get_fuse_conn(inode);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700181 req = fuse_get_req(fc);
182 if (IS_ERR(req))
Miklos Szeredie5e55582005-09-09 13:10:28 -0700183 return 0;
184
Miklos Szeredi2d510132006-11-25 11:09:20 -0800185 forget_req = fuse_get_req(fc);
186 if (IS_ERR(forget_req)) {
187 fuse_put_request(fc, req);
188 return 0;
189 }
190
Miklos Szeredi7dca9fd2007-11-28 16:21:59 -0800191 attr_version = fuse_get_attr_version(fc);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700192
Miklos Szeredie956edd2006-10-17 00:10:12 -0700193 parent = dget_parent(entry);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700194 fuse_lookup_init(fc, req, get_node_id(parent->d_inode),
195 &entry->d_name, &outarg);
Tejun Heob93f8582008-11-26 12:03:55 +0100196 fuse_request_send(fc, req);
Miklos Szeredie956edd2006-10-17 00:10:12 -0700197 dput(parent);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700198 err = req->out.h.error;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800199 fuse_put_request(fc, req);
Miklos Szeredi50322fe2006-02-28 16:59:03 -0800200 /* Zero nodeid is same as -ENOENT */
201 if (!err && !outarg.nodeid)
202 err = -ENOENT;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700203 if (!err) {
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800204 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700205 if (outarg.nodeid != get_node_id(inode)) {
Miklos Szeredi2d510132006-11-25 11:09:20 -0800206 fuse_send_forget(fc, forget_req,
207 outarg.nodeid, 1);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700208 return 0;
209 }
Miklos Szeredi8da5ff22006-10-17 00:10:08 -0700210 spin_lock(&fc->lock);
Miklos Szeredi1729a162008-11-26 12:03:54 +0100211 fi->nlookup++;
Miklos Szeredi8da5ff22006-10-17 00:10:08 -0700212 spin_unlock(&fc->lock);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700213 }
Miklos Szeredi2d510132006-11-25 11:09:20 -0800214 fuse_put_request(fc, forget_req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700215 if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700216 return 0;
217
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700218 fuse_change_attributes(inode, &outarg.attr,
219 entry_attr_timeout(&outarg),
220 attr_version);
221 fuse_change_entry_timeout(entry, &outarg);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700222 }
223 return 1;
224}
225
Miklos Szeredi8bfc0162006-01-16 22:14:28 -0800226static int invalid_nodeid(u64 nodeid)
Miklos Szeredi2827d0b22005-11-28 13:44:16 -0800227{
228 return !nodeid || nodeid == FUSE_ROOT_ID;
229}
230
Al Viro42695902009-02-20 05:59:13 +0000231const struct dentry_operations fuse_dentry_operations = {
Miklos Szeredie5e55582005-09-09 13:10:28 -0700232 .d_revalidate = fuse_dentry_revalidate,
233};
234
Timo Savolaa5bfffac2007-04-08 16:04:00 -0700235int fuse_valid_type(int m)
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800236{
237 return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) ||
238 S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m);
239}
240
Miklos Szeredid2a85162006-10-17 00:10:11 -0700241/*
242 * Add a directory inode to a dentry, ensuring that no other dentry
243 * refers to this inode. Called with fc->inst_mutex.
244 */
Miklos Szeredi0de62562008-07-25 01:48:59 -0700245static struct dentry *fuse_d_add_directory(struct dentry *entry,
246 struct inode *inode)
Miklos Szeredid2a85162006-10-17 00:10:11 -0700247{
248 struct dentry *alias = d_find_alias(inode);
Miklos Szeredi0de62562008-07-25 01:48:59 -0700249 if (alias && !(alias->d_flags & DCACHE_DISCONNECTED)) {
Miklos Szeredid2a85162006-10-17 00:10:11 -0700250 /* This tries to shrink the subtree below alias */
251 fuse_invalidate_entry(alias);
252 dput(alias);
253 if (!list_empty(&inode->i_dentry))
Miklos Szeredi0de62562008-07-25 01:48:59 -0700254 return ERR_PTR(-EBUSY);
255 } else {
256 dput(alias);
Miklos Szeredid2a85162006-10-17 00:10:11 -0700257 }
Miklos Szeredi0de62562008-07-25 01:48:59 -0700258 return d_splice_alias(inode, entry);
Miklos Szeredid2a85162006-10-17 00:10:11 -0700259}
260
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700261int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name,
262 struct fuse_entry_out *outarg, struct inode **inode)
263{
264 struct fuse_conn *fc = get_fuse_conn_super(sb);
265 struct fuse_req *req;
266 struct fuse_req *forget_req;
267 u64 attr_version;
268 int err;
269
270 *inode = NULL;
271 err = -ENAMETOOLONG;
272 if (name->len > FUSE_NAME_MAX)
273 goto out;
274
275 req = fuse_get_req(fc);
276 err = PTR_ERR(req);
277 if (IS_ERR(req))
278 goto out;
279
280 forget_req = fuse_get_req(fc);
281 err = PTR_ERR(forget_req);
282 if (IS_ERR(forget_req)) {
283 fuse_put_request(fc, req);
284 goto out;
285 }
286
287 attr_version = fuse_get_attr_version(fc);
288
289 fuse_lookup_init(fc, req, nodeid, name, outarg);
Tejun Heob93f8582008-11-26 12:03:55 +0100290 fuse_request_send(fc, req);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700291 err = req->out.h.error;
292 fuse_put_request(fc, req);
293 /* Zero nodeid is same as -ENOENT, but with valid timeout */
294 if (err || !outarg->nodeid)
295 goto out_put_forget;
296
297 err = -EIO;
298 if (!outarg->nodeid)
299 goto out_put_forget;
300 if (!fuse_valid_type(outarg->attr.mode))
301 goto out_put_forget;
302
303 *inode = fuse_iget(sb, outarg->nodeid, outarg->generation,
304 &outarg->attr, entry_attr_timeout(outarg),
305 attr_version);
306 err = -ENOMEM;
307 if (!*inode) {
308 fuse_send_forget(fc, forget_req, outarg->nodeid, 1);
309 goto out;
310 }
311 err = 0;
312
313 out_put_forget:
314 fuse_put_request(fc, forget_req);
315 out:
316 return err;
317}
318
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800319static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
320 struct nameidata *nd)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700321{
322 int err;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700323 struct fuse_entry_out outarg;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700324 struct inode *inode;
Miklos Szeredi0de62562008-07-25 01:48:59 -0700325 struct dentry *newent;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700326 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700327 bool outarg_valid = true;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700328
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700329 err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name,
330 &outarg, &inode);
331 if (err == -ENOENT) {
332 outarg_valid = false;
333 err = 0;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800334 }
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700335 if (err)
336 goto out_err;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800337
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700338 err = -EIO;
339 if (inode && get_node_id(inode) == FUSE_ROOT_ID)
340 goto out_iput;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700341
Miklos Szeredid2a85162006-10-17 00:10:11 -0700342 if (inode && S_ISDIR(inode->i_mode)) {
343 mutex_lock(&fc->inst_mutex);
Miklos Szeredi0de62562008-07-25 01:48:59 -0700344 newent = fuse_d_add_directory(entry, inode);
Miklos Szeredid2a85162006-10-17 00:10:11 -0700345 mutex_unlock(&fc->inst_mutex);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700346 err = PTR_ERR(newent);
347 if (IS_ERR(newent))
348 goto out_iput;
349 } else {
Miklos Szeredi0de62562008-07-25 01:48:59 -0700350 newent = d_splice_alias(inode, entry);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700351 }
Miklos Szeredid2a85162006-10-17 00:10:11 -0700352
Miklos Szeredi0de62562008-07-25 01:48:59 -0700353 entry = newent ? newent : entry;
Nick Pigginfb045ad2011-01-07 17:49:55 +1100354 d_set_d_op(entry, &fuse_dentry_operations);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700355 if (outarg_valid)
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700356 fuse_change_entry_timeout(entry, &outarg);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800357 else
358 fuse_invalidate_entry_cache(entry);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700359
Miklos Szeredi0de62562008-07-25 01:48:59 -0700360 return newent;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700361
362 out_iput:
363 iput(inode);
364 out_err:
365 return ERR_PTR(err);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700366}
367
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800368/*
369 * Atomic create+open operation
370 *
371 * If the filesystem doesn't support this, then fall back to separate
372 * 'mknod' + 'open' requests.
373 */
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800374static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
375 struct nameidata *nd)
376{
377 int err;
378 struct inode *inode;
379 struct fuse_conn *fc = get_fuse_conn(dir);
380 struct fuse_req *req;
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700381 struct fuse_req *forget_req;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200382 struct fuse_create_in inarg;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800383 struct fuse_open_out outopen;
384 struct fuse_entry_out outentry;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800385 struct fuse_file *ff;
386 struct file *file;
387 int flags = nd->intent.open.flags - 1;
388
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800389 if (fc->no_create)
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700390 return -ENOSYS;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800391
Csaba Henk1b732392009-11-27 19:30:14 +0530392 if (flags & O_DIRECT)
393 return -EINVAL;
394
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700395 forget_req = fuse_get_req(fc);
396 if (IS_ERR(forget_req))
397 return PTR_ERR(forget_req);
398
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700399 req = fuse_get_req(fc);
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700400 err = PTR_ERR(req);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700401 if (IS_ERR(req))
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700402 goto out_put_forget_req;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800403
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700404 err = -ENOMEM;
Tejun Heoacf99432008-11-26 12:03:55 +0100405 ff = fuse_file_alloc(fc);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800406 if (!ff)
407 goto out_put_request;
408
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200409 if (!fc->dont_mask)
410 mode &= ~current_umask();
411
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800412 flags &= ~O_NOCTTY;
413 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700414 memset(&outentry, 0, sizeof(outentry));
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800415 inarg.flags = flags;
416 inarg.mode = mode;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200417 inarg.umask = current_umask();
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800418 req->in.h.opcode = FUSE_CREATE;
419 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800420 req->in.numargs = 2;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200421 req->in.args[0].size = fc->minor < 12 ? sizeof(struct fuse_open_in) :
422 sizeof(inarg);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800423 req->in.args[0].value = &inarg;
424 req->in.args[1].size = entry->d_name.len + 1;
425 req->in.args[1].value = entry->d_name.name;
426 req->out.numargs = 2;
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700427 if (fc->minor < 9)
428 req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
429 else
430 req->out.args[0].size = sizeof(outentry);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800431 req->out.args[0].value = &outentry;
432 req->out.args[1].size = sizeof(outopen);
433 req->out.args[1].value = &outopen;
Tejun Heob93f8582008-11-26 12:03:55 +0100434 fuse_request_send(fc, req);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800435 err = req->out.h.error;
436 if (err) {
437 if (err == -ENOSYS)
438 fc->no_create = 1;
439 goto out_free_ff;
440 }
441
442 err = -EIO;
Miklos Szeredi2827d0b22005-11-28 13:44:16 -0800443 if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid))
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800444 goto out_free_ff;
445
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700446 fuse_put_request(fc, req);
Miklos Szeredic7b71432009-04-28 16:56:37 +0200447 ff->fh = outopen.fh;
448 ff->nodeid = outentry.nodeid;
449 ff->open_flags = outopen.open_flags;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800450 inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700451 &outentry.attr, entry_attr_timeout(&outentry), 0);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800452 if (!inode) {
453 flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
Miklos Szeredi8b0797a2009-04-28 16:56:39 +0200454 fuse_sync_release(ff, flags);
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700455 fuse_send_forget(fc, forget_req, outentry.nodeid, 1);
456 return -ENOMEM;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800457 }
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700458 fuse_put_request(fc, forget_req);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800459 d_instantiate(entry, inode);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700460 fuse_change_entry_timeout(entry, &outentry);
Miklos Szeredi0952b2a2008-02-06 01:38:38 -0800461 fuse_invalidate_attr(dir);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800462 file = lookup_instantiate_filp(nd, entry, generic_file_open);
463 if (IS_ERR(file)) {
Miklos Szeredi8b0797a2009-04-28 16:56:39 +0200464 fuse_sync_release(ff, flags);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800465 return PTR_ERR(file);
466 }
Miklos Szeredic7b71432009-04-28 16:56:37 +0200467 file->private_data = fuse_file_get(ff);
468 fuse_finish_open(inode, file);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800469 return 0;
470
471 out_free_ff:
472 fuse_file_free(ff);
473 out_put_request:
474 fuse_put_request(fc, req);
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700475 out_put_forget_req:
476 fuse_put_request(fc, forget_req);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800477 return err;
478}
479
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800480/*
481 * Code shared between mknod, mkdir, symlink and link
482 */
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700483static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
484 struct inode *dir, struct dentry *entry,
485 int mode)
486{
487 struct fuse_entry_out outarg;
488 struct inode *inode;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700489 int err;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800490 struct fuse_req *forget_req;
491
492 forget_req = fuse_get_req(fc);
493 if (IS_ERR(forget_req)) {
494 fuse_put_request(fc, req);
495 return PTR_ERR(forget_req);
496 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700497
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700498 memset(&outarg, 0, sizeof(outarg));
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700499 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700500 req->out.numargs = 1;
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700501 if (fc->minor < 9)
502 req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
503 else
504 req->out.args[0].size = sizeof(outarg);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700505 req->out.args[0].value = &outarg;
Tejun Heob93f8582008-11-26 12:03:55 +0100506 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700507 err = req->out.h.error;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800508 fuse_put_request(fc, req);
509 if (err)
510 goto out_put_forget_req;
511
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800512 err = -EIO;
513 if (invalid_nodeid(outarg.nodeid))
Miklos Szeredi2d510132006-11-25 11:09:20 -0800514 goto out_put_forget_req;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800515
516 if ((outarg.attr.mode ^ mode) & S_IFMT)
Miklos Szeredi2d510132006-11-25 11:09:20 -0800517 goto out_put_forget_req;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800518
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700519 inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700520 &outarg.attr, entry_attr_timeout(&outarg), 0);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700521 if (!inode) {
Miklos Szeredi2d510132006-11-25 11:09:20 -0800522 fuse_send_forget(fc, forget_req, outarg.nodeid, 1);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700523 return -ENOMEM;
524 }
Miklos Szeredi2d510132006-11-25 11:09:20 -0800525 fuse_put_request(fc, forget_req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700526
Miklos Szeredid2a85162006-10-17 00:10:11 -0700527 if (S_ISDIR(inode->i_mode)) {
528 struct dentry *alias;
529 mutex_lock(&fc->inst_mutex);
530 alias = d_find_alias(inode);
531 if (alias) {
532 /* New directory must have moved since mkdir */
533 mutex_unlock(&fc->inst_mutex);
534 dput(alias);
535 iput(inode);
536 return -EBUSY;
537 }
538 d_instantiate(entry, inode);
539 mutex_unlock(&fc->inst_mutex);
540 } else
541 d_instantiate(entry, inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700542
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700543 fuse_change_entry_timeout(entry, &outarg);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700544 fuse_invalidate_attr(dir);
545 return 0;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800546
Miklos Szeredi2d510132006-11-25 11:09:20 -0800547 out_put_forget_req:
548 fuse_put_request(fc, forget_req);
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800549 return err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700550}
551
552static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode,
553 dev_t rdev)
554{
555 struct fuse_mknod_in inarg;
556 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700557 struct fuse_req *req = fuse_get_req(fc);
558 if (IS_ERR(req))
559 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700560
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200561 if (!fc->dont_mask)
562 mode &= ~current_umask();
563
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700564 memset(&inarg, 0, sizeof(inarg));
565 inarg.mode = mode;
566 inarg.rdev = new_encode_dev(rdev);
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200567 inarg.umask = current_umask();
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700568 req->in.h.opcode = FUSE_MKNOD;
569 req->in.numargs = 2;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200570 req->in.args[0].size = fc->minor < 12 ? FUSE_COMPAT_MKNOD_IN_SIZE :
571 sizeof(inarg);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700572 req->in.args[0].value = &inarg;
573 req->in.args[1].size = entry->d_name.len + 1;
574 req->in.args[1].value = entry->d_name.name;
575 return create_new_entry(fc, req, dir, entry, mode);
576}
577
578static int fuse_create(struct inode *dir, struct dentry *entry, int mode,
579 struct nameidata *nd)
580{
Miklos Szeredib9ba3472007-05-23 13:57:32 -0700581 if (nd && (nd->flags & LOOKUP_OPEN)) {
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800582 int err = fuse_create_open(dir, entry, mode, nd);
583 if (err != -ENOSYS)
584 return err;
585 /* Fall back on mknod */
586 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700587 return fuse_mknod(dir, entry, mode, 0);
588}
589
590static int fuse_mkdir(struct inode *dir, struct dentry *entry, int mode)
591{
592 struct fuse_mkdir_in inarg;
593 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700594 struct fuse_req *req = fuse_get_req(fc);
595 if (IS_ERR(req))
596 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700597
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200598 if (!fc->dont_mask)
599 mode &= ~current_umask();
600
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700601 memset(&inarg, 0, sizeof(inarg));
602 inarg.mode = mode;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200603 inarg.umask = current_umask();
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700604 req->in.h.opcode = FUSE_MKDIR;
605 req->in.numargs = 2;
606 req->in.args[0].size = sizeof(inarg);
607 req->in.args[0].value = &inarg;
608 req->in.args[1].size = entry->d_name.len + 1;
609 req->in.args[1].value = entry->d_name.name;
610 return create_new_entry(fc, req, dir, entry, S_IFDIR);
611}
612
613static int fuse_symlink(struct inode *dir, struct dentry *entry,
614 const char *link)
615{
616 struct fuse_conn *fc = get_fuse_conn(dir);
617 unsigned len = strlen(link) + 1;
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700618 struct fuse_req *req = fuse_get_req(fc);
619 if (IS_ERR(req))
620 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700621
622 req->in.h.opcode = FUSE_SYMLINK;
623 req->in.numargs = 2;
624 req->in.args[0].size = entry->d_name.len + 1;
625 req->in.args[0].value = entry->d_name.name;
626 req->in.args[1].size = len;
627 req->in.args[1].value = link;
628 return create_new_entry(fc, req, dir, entry, S_IFLNK);
629}
630
631static int fuse_unlink(struct inode *dir, struct dentry *entry)
632{
633 int err;
634 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700635 struct fuse_req *req = fuse_get_req(fc);
636 if (IS_ERR(req))
637 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700638
639 req->in.h.opcode = FUSE_UNLINK;
640 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700641 req->in.numargs = 1;
642 req->in.args[0].size = entry->d_name.len + 1;
643 req->in.args[0].value = entry->d_name.name;
Tejun Heob93f8582008-11-26 12:03:55 +0100644 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700645 err = req->out.h.error;
646 fuse_put_request(fc, req);
647 if (!err) {
648 struct inode *inode = entry->d_inode;
649
Miklos Szeredi1729a162008-11-26 12:03:54 +0100650 /*
651 * Set nlink to zero so the inode can be cleared, if the inode
652 * does have more links this will be discovered at the next
653 * lookup/getattr.
654 */
Dave Hansence71ec32006-09-30 23:29:06 -0700655 clear_nlink(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700656 fuse_invalidate_attr(inode);
657 fuse_invalidate_attr(dir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800658 fuse_invalidate_entry_cache(entry);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700659 } else if (err == -EINTR)
660 fuse_invalidate_entry(entry);
661 return err;
662}
663
664static int fuse_rmdir(struct inode *dir, struct dentry *entry)
665{
666 int err;
667 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700668 struct fuse_req *req = fuse_get_req(fc);
669 if (IS_ERR(req))
670 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700671
672 req->in.h.opcode = FUSE_RMDIR;
673 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700674 req->in.numargs = 1;
675 req->in.args[0].size = entry->d_name.len + 1;
676 req->in.args[0].value = entry->d_name.name;
Tejun Heob93f8582008-11-26 12:03:55 +0100677 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700678 err = req->out.h.error;
679 fuse_put_request(fc, req);
680 if (!err) {
Dave Hansence71ec32006-09-30 23:29:06 -0700681 clear_nlink(entry->d_inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700682 fuse_invalidate_attr(dir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800683 fuse_invalidate_entry_cache(entry);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700684 } else if (err == -EINTR)
685 fuse_invalidate_entry(entry);
686 return err;
687}
688
689static int fuse_rename(struct inode *olddir, struct dentry *oldent,
690 struct inode *newdir, struct dentry *newent)
691{
692 int err;
693 struct fuse_rename_in inarg;
694 struct fuse_conn *fc = get_fuse_conn(olddir);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700695 struct fuse_req *req = fuse_get_req(fc);
696 if (IS_ERR(req))
697 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700698
699 memset(&inarg, 0, sizeof(inarg));
700 inarg.newdir = get_node_id(newdir);
701 req->in.h.opcode = FUSE_RENAME;
702 req->in.h.nodeid = get_node_id(olddir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700703 req->in.numargs = 3;
704 req->in.args[0].size = sizeof(inarg);
705 req->in.args[0].value = &inarg;
706 req->in.args[1].size = oldent->d_name.len + 1;
707 req->in.args[1].value = oldent->d_name.name;
708 req->in.args[2].size = newent->d_name.len + 1;
709 req->in.args[2].value = newent->d_name.name;
Tejun Heob93f8582008-11-26 12:03:55 +0100710 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700711 err = req->out.h.error;
712 fuse_put_request(fc, req);
713 if (!err) {
Miklos Szeredi08b63302007-11-28 16:22:03 -0800714 /* ctime changes */
715 fuse_invalidate_attr(oldent->d_inode);
716
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700717 fuse_invalidate_attr(olddir);
718 if (olddir != newdir)
719 fuse_invalidate_attr(newdir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800720
721 /* newent will end up negative */
Miklos Szeredi5219f342009-11-04 10:24:52 +0100722 if (newent->d_inode) {
723 fuse_invalidate_attr(newent->d_inode);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800724 fuse_invalidate_entry_cache(newent);
Miklos Szeredi5219f342009-11-04 10:24:52 +0100725 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700726 } else if (err == -EINTR) {
727 /* If request was interrupted, DEITY only knows if the
728 rename actually took place. If the invalidation
729 fails (e.g. some process has CWD under the renamed
730 directory), then there can be inconsistency between
731 the dcache and the real filesystem. Tough luck. */
732 fuse_invalidate_entry(oldent);
733 if (newent->d_inode)
734 fuse_invalidate_entry(newent);
735 }
736
737 return err;
738}
739
740static int fuse_link(struct dentry *entry, struct inode *newdir,
741 struct dentry *newent)
742{
743 int err;
744 struct fuse_link_in inarg;
745 struct inode *inode = entry->d_inode;
746 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700747 struct fuse_req *req = fuse_get_req(fc);
748 if (IS_ERR(req))
749 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700750
751 memset(&inarg, 0, sizeof(inarg));
752 inarg.oldnodeid = get_node_id(inode);
753 req->in.h.opcode = FUSE_LINK;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700754 req->in.numargs = 2;
755 req->in.args[0].size = sizeof(inarg);
756 req->in.args[0].value = &inarg;
757 req->in.args[1].size = newent->d_name.len + 1;
758 req->in.args[1].value = newent->d_name.name;
759 err = create_new_entry(fc, req, newdir, newent, inode->i_mode);
760 /* Contrary to "normal" filesystems it can happen that link
761 makes two "logical" inodes point to the same "physical"
762 inode. We invalidate the attributes of the old one, so it
763 will reflect changes in the backing inode (link count,
764 etc.)
765 */
766 if (!err || err == -EINTR)
767 fuse_invalidate_attr(inode);
768 return err;
769}
770
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700771static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
772 struct kstat *stat)
773{
774 stat->dev = inode->i_sb->s_dev;
775 stat->ino = attr->ino;
776 stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
777 stat->nlink = attr->nlink;
778 stat->uid = attr->uid;
779 stat->gid = attr->gid;
780 stat->rdev = inode->i_rdev;
781 stat->atime.tv_sec = attr->atime;
782 stat->atime.tv_nsec = attr->atimensec;
783 stat->mtime.tv_sec = attr->mtime;
784 stat->mtime.tv_nsec = attr->mtimensec;
785 stat->ctime.tv_sec = attr->ctime;
786 stat->ctime.tv_nsec = attr->ctimensec;
787 stat->size = attr->size;
788 stat->blocks = attr->blocks;
789 stat->blksize = (1 << inode->i_blkbits);
790}
791
Miklos Szeredic79e3222007-10-18 03:06:59 -0700792static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
793 struct file *file)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700794{
795 int err;
Miklos Szeredic79e3222007-10-18 03:06:59 -0700796 struct fuse_getattr_in inarg;
797 struct fuse_attr_out outarg;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700798 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700799 struct fuse_req *req;
800 u64 attr_version;
801
802 req = fuse_get_req(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700803 if (IS_ERR(req))
804 return PTR_ERR(req);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700805
Miklos Szeredi7dca9fd2007-11-28 16:21:59 -0800806 attr_version = fuse_get_attr_version(fc);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700807
Miklos Szeredic79e3222007-10-18 03:06:59 -0700808 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700809 memset(&outarg, 0, sizeof(outarg));
Miklos Szeredic79e3222007-10-18 03:06:59 -0700810 /* Directories have separate file-handle space */
811 if (file && S_ISREG(inode->i_mode)) {
812 struct fuse_file *ff = file->private_data;
813
814 inarg.getattr_flags |= FUSE_GETATTR_FH;
815 inarg.fh = ff->fh;
816 }
Miklos Szeredie5e55582005-09-09 13:10:28 -0700817 req->in.h.opcode = FUSE_GETATTR;
818 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredic79e3222007-10-18 03:06:59 -0700819 req->in.numargs = 1;
820 req->in.args[0].size = sizeof(inarg);
821 req->in.args[0].value = &inarg;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700822 req->out.numargs = 1;
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700823 if (fc->minor < 9)
824 req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
825 else
826 req->out.args[0].size = sizeof(outarg);
Miklos Szeredic79e3222007-10-18 03:06:59 -0700827 req->out.args[0].value = &outarg;
Tejun Heob93f8582008-11-26 12:03:55 +0100828 fuse_request_send(fc, req);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700829 err = req->out.h.error;
830 fuse_put_request(fc, req);
831 if (!err) {
Miklos Szeredic79e3222007-10-18 03:06:59 -0700832 if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
Miklos Szeredie5e55582005-09-09 13:10:28 -0700833 make_bad_inode(inode);
834 err = -EIO;
835 } else {
Miklos Szeredic79e3222007-10-18 03:06:59 -0700836 fuse_change_attributes(inode, &outarg.attr,
837 attr_timeout(&outarg),
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700838 attr_version);
839 if (stat)
Miklos Szeredic79e3222007-10-18 03:06:59 -0700840 fuse_fillattr(inode, &outarg.attr, stat);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700841 }
842 }
843 return err;
844}
845
Miklos Szeredibcb4be82007-11-28 16:21:59 -0800846int fuse_update_attributes(struct inode *inode, struct kstat *stat,
847 struct file *file, bool *refreshed)
848{
849 struct fuse_inode *fi = get_fuse_inode(inode);
850 int err;
851 bool r;
852
853 if (fi->i_time < get_jiffies_64()) {
854 r = true;
855 err = fuse_do_getattr(inode, stat, file);
856 } else {
857 r = false;
858 err = 0;
859 if (stat) {
860 generic_fillattr(inode, stat);
861 stat->mode = fi->orig_i_mode;
862 }
863 }
864
865 if (refreshed != NULL)
866 *refreshed = r;
867
868 return err;
869}
870
John Muir3b463ae2009-05-31 11:13:57 -0400871int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid,
872 struct qstr *name)
873{
874 int err = -ENOTDIR;
875 struct inode *parent;
876 struct dentry *dir;
877 struct dentry *entry;
878
879 parent = ilookup5(sb, parent_nodeid, fuse_inode_eq, &parent_nodeid);
880 if (!parent)
881 return -ENOENT;
882
883 mutex_lock(&parent->i_mutex);
884 if (!S_ISDIR(parent->i_mode))
885 goto unlock;
886
887 err = -ENOENT;
888 dir = d_find_alias(parent);
889 if (!dir)
890 goto unlock;
891
892 entry = d_lookup(dir, name);
893 dput(dir);
894 if (!entry)
895 goto unlock;
896
897 fuse_invalidate_attr(parent);
898 fuse_invalidate_entry(entry);
899 dput(entry);
900 err = 0;
901
902 unlock:
903 mutex_unlock(&parent->i_mutex);
904 iput(parent);
905 return err;
906}
907
Miklos Szeredi87729a52005-09-09 13:10:34 -0700908/*
909 * Calling into a user-controlled filesystem gives the filesystem
910 * daemon ptrace-like capabilities over the requester process. This
911 * means, that the filesystem daemon is able to record the exact
912 * filesystem operations performed, and can also control the behavior
913 * of the requester process in otherwise impossible ways. For example
914 * it can delay the operation for arbitrary length of time allowing
915 * DoS against the requester.
916 *
917 * For this reason only those processes can call into the filesystem,
918 * for which the owner of the mount has ptrace privilege. This
919 * excludes processes started by other users, suid or sgid processes.
920 */
Miklos Szeredie57ac682007-10-18 03:06:58 -0700921int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task)
Miklos Szeredi87729a52005-09-09 13:10:34 -0700922{
David Howellsc69e8d92008-11-14 10:39:19 +1100923 const struct cred *cred;
924 int ret;
925
Miklos Szeredi87729a52005-09-09 13:10:34 -0700926 if (fc->flags & FUSE_ALLOW_OTHER)
927 return 1;
928
David Howellsc69e8d92008-11-14 10:39:19 +1100929 rcu_read_lock();
930 ret = 0;
931 cred = __task_cred(task);
932 if (cred->euid == fc->user_id &&
933 cred->suid == fc->user_id &&
934 cred->uid == fc->user_id &&
935 cred->egid == fc->group_id &&
936 cred->sgid == fc->group_id &&
937 cred->gid == fc->group_id)
938 ret = 1;
939 rcu_read_unlock();
Miklos Szeredi87729a52005-09-09 13:10:34 -0700940
David Howellsc69e8d92008-11-14 10:39:19 +1100941 return ret;
Miklos Szeredi87729a52005-09-09 13:10:34 -0700942}
943
Miklos Szeredi31d40d72005-11-07 00:59:50 -0800944static int fuse_access(struct inode *inode, int mask)
945{
946 struct fuse_conn *fc = get_fuse_conn(inode);
947 struct fuse_req *req;
948 struct fuse_access_in inarg;
949 int err;
950
951 if (fc->no_access)
952 return 0;
953
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700954 req = fuse_get_req(fc);
955 if (IS_ERR(req))
956 return PTR_ERR(req);
Miklos Szeredi31d40d72005-11-07 00:59:50 -0800957
958 memset(&inarg, 0, sizeof(inarg));
Al Viroe6305c42008-07-15 21:03:57 -0400959 inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC);
Miklos Szeredi31d40d72005-11-07 00:59:50 -0800960 req->in.h.opcode = FUSE_ACCESS;
961 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi31d40d72005-11-07 00:59:50 -0800962 req->in.numargs = 1;
963 req->in.args[0].size = sizeof(inarg);
964 req->in.args[0].value = &inarg;
Tejun Heob93f8582008-11-26 12:03:55 +0100965 fuse_request_send(fc, req);
Miklos Szeredi31d40d72005-11-07 00:59:50 -0800966 err = req->out.h.error;
967 fuse_put_request(fc, req);
968 if (err == -ENOSYS) {
969 fc->no_access = 1;
970 err = 0;
971 }
972 return err;
973}
974
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800975/*
976 * Check permission. The two basic access models of FUSE are:
977 *
978 * 1) Local access checking ('default_permissions' mount option) based
979 * on file mode. This is the plain old disk filesystem permission
980 * modell.
981 *
982 * 2) "Remote" access checking, where server is responsible for
983 * checking permission in each inode operation. An exception to this
984 * is if ->permission() was invoked from sys_access() in which case an
985 * access request is sent. Execute permission is still checked
986 * locally based on file mode.
987 */
Al Viroe6305c42008-07-15 21:03:57 -0400988static int fuse_permission(struct inode *inode, int mask)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700989{
990 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi244f6382007-10-16 23:31:02 -0700991 bool refreshed = false;
992 int err = 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700993
Miklos Szeredi87729a52005-09-09 13:10:34 -0700994 if (!fuse_allow_task(fc, current))
Miklos Szeredie5e55582005-09-09 13:10:28 -0700995 return -EACCES;
Miklos Szeredi244f6382007-10-16 23:31:02 -0700996
997 /*
Miklos Szeredie8e96152007-10-16 23:31:06 -0700998 * If attributes are needed, refresh them before proceeding
Miklos Szeredi244f6382007-10-16 23:31:02 -0700999 */
Miklos Szeredie8e96152007-10-16 23:31:06 -07001000 if ((fc->flags & FUSE_DEFAULT_PERMISSIONS) ||
1001 ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
Miklos Szeredibcb4be82007-11-28 16:21:59 -08001002 err = fuse_update_attributes(inode, NULL, NULL, &refreshed);
1003 if (err)
1004 return err;
Miklos Szeredi244f6382007-10-16 23:31:02 -07001005 }
1006
1007 if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
Miklos Szeredi1a823ac2008-02-23 15:23:27 -08001008 err = generic_permission(inode, mask, NULL);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001009
1010 /* If permission is denied, try to refresh file
1011 attributes. This is also needed, because the root
1012 node will at first have no permissions */
Miklos Szeredi244f6382007-10-16 23:31:02 -07001013 if (err == -EACCES && !refreshed) {
Miklos Szeredic79e3222007-10-18 03:06:59 -07001014 err = fuse_do_getattr(inode, NULL, NULL);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001015 if (!err)
1016 err = generic_permission(inode, mask, NULL);
1017 }
1018
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001019 /* Note: the opposite of the above test does not
1020 exist. So if permissions are revoked this won't be
1021 noticed immediately, only after the attribute
1022 timeout has expired */
Eric Paris9cfcac82010-07-23 11:43:51 -04001023 } else if (mask & (MAY_ACCESS | MAY_CHDIR)) {
Miklos Szeredie8e96152007-10-16 23:31:06 -07001024 err = fuse_access(inode, mask);
1025 } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
1026 if (!(inode->i_mode & S_IXUGO)) {
1027 if (refreshed)
1028 return -EACCES;
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001029
Miklos Szeredic79e3222007-10-18 03:06:59 -07001030 err = fuse_do_getattr(inode, NULL, NULL);
Miklos Szeredie8e96152007-10-16 23:31:06 -07001031 if (!err && !(inode->i_mode & S_IXUGO))
1032 return -EACCES;
1033 }
Miklos Szeredie5e55582005-09-09 13:10:28 -07001034 }
Miklos Szeredi244f6382007-10-16 23:31:02 -07001035 return err;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001036}
1037
1038static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
1039 void *dstbuf, filldir_t filldir)
1040{
1041 while (nbytes >= FUSE_NAME_OFFSET) {
1042 struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
1043 size_t reclen = FUSE_DIRENT_SIZE(dirent);
1044 int over;
1045 if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
1046 return -EIO;
1047 if (reclen > nbytes)
1048 break;
1049
1050 over = filldir(dstbuf, dirent->name, dirent->namelen,
1051 file->f_pos, dirent->ino, dirent->type);
1052 if (over)
1053 break;
1054
1055 buf += reclen;
1056 nbytes -= reclen;
1057 file->f_pos = dirent->off;
1058 }
1059
1060 return 0;
1061}
1062
Miklos Szeredie5e55582005-09-09 13:10:28 -07001063static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
1064{
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001065 int err;
1066 size_t nbytes;
1067 struct page *page;
Josef Sipek7706a9d2006-12-08 02:37:02 -08001068 struct inode *inode = file->f_path.dentry->d_inode;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001069 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi248d86e2006-01-06 00:19:39 -08001070 struct fuse_req *req;
1071
1072 if (is_bad_inode(inode))
1073 return -EIO;
1074
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001075 req = fuse_get_req(fc);
1076 if (IS_ERR(req))
1077 return PTR_ERR(req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001078
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001079 page = alloc_page(GFP_KERNEL);
1080 if (!page) {
1081 fuse_put_request(fc, req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001082 return -ENOMEM;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001083 }
Miklos Szeredif4975c62009-04-02 14:25:34 +02001084 req->out.argpages = 1;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001085 req->num_pages = 1;
1086 req->pages[0] = page;
Miklos Szeredi2106cb12009-04-28 16:56:37 +02001087 fuse_read_fill(req, file, file->f_pos, PAGE_SIZE, FUSE_READDIR);
Tejun Heob93f8582008-11-26 12:03:55 +01001088 fuse_request_send(fc, req);
Miklos Szeredi361b1eb52006-01-16 22:14:45 -08001089 nbytes = req->out.args[0].size;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001090 err = req->out.h.error;
1091 fuse_put_request(fc, req);
1092 if (!err)
1093 err = parse_dirfile(page_address(page), nbytes, file, dstbuf,
1094 filldir);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001095
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001096 __free_page(page);
Miklos Szeredib36c31b2005-09-09 13:10:38 -07001097 fuse_invalidate_attr(inode); /* atime changed */
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001098 return err;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001099}
1100
1101static char *read_link(struct dentry *dentry)
1102{
1103 struct inode *inode = dentry->d_inode;
1104 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001105 struct fuse_req *req = fuse_get_req(fc);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001106 char *link;
1107
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001108 if (IS_ERR(req))
David Howellse231c2e2008-02-07 00:15:26 -08001109 return ERR_CAST(req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001110
1111 link = (char *) __get_free_page(GFP_KERNEL);
1112 if (!link) {
1113 link = ERR_PTR(-ENOMEM);
1114 goto out;
1115 }
1116 req->in.h.opcode = FUSE_READLINK;
1117 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001118 req->out.argvar = 1;
1119 req->out.numargs = 1;
1120 req->out.args[0].size = PAGE_SIZE - 1;
1121 req->out.args[0].value = link;
Tejun Heob93f8582008-11-26 12:03:55 +01001122 fuse_request_send(fc, req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001123 if (req->out.h.error) {
1124 free_page((unsigned long) link);
1125 link = ERR_PTR(req->out.h.error);
1126 } else
1127 link[req->out.args[0].size] = '\0';
1128 out:
1129 fuse_put_request(fc, req);
Miklos Szeredib36c31b2005-09-09 13:10:38 -07001130 fuse_invalidate_attr(inode); /* atime changed */
Miklos Szeredie5e55582005-09-09 13:10:28 -07001131 return link;
1132}
1133
1134static void free_link(char *link)
1135{
1136 if (!IS_ERR(link))
1137 free_page((unsigned long) link);
1138}
1139
1140static void *fuse_follow_link(struct dentry *dentry, struct nameidata *nd)
1141{
1142 nd_set_link(nd, read_link(dentry));
1143 return NULL;
1144}
1145
1146static void fuse_put_link(struct dentry *dentry, struct nameidata *nd, void *c)
1147{
1148 free_link(nd_get_link(nd));
1149}
1150
1151static int fuse_dir_open(struct inode *inode, struct file *file)
1152{
Miklos Szeredi91fe96b2009-04-28 16:56:37 +02001153 return fuse_open_common(inode, file, true);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001154}
1155
1156static int fuse_dir_release(struct inode *inode, struct file *file)
1157{
Miklos Szeredi8b0797a2009-04-28 16:56:39 +02001158 fuse_release_common(file, FUSE_RELEASEDIR);
1159
1160 return 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001161}
1162
Christoph Hellwig7ea80852010-05-26 17:53:25 +02001163static int fuse_dir_fsync(struct file *file, int datasync)
Miklos Szeredi82547982005-09-09 13:10:38 -07001164{
Christoph Hellwig7ea80852010-05-26 17:53:25 +02001165 return fuse_fsync_common(file, datasync, 1);
Miklos Szeredi82547982005-09-09 13:10:38 -07001166}
1167
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001168static bool update_mtime(unsigned ivalid)
1169{
1170 /* Always update if mtime is explicitly set */
1171 if (ivalid & ATTR_MTIME_SET)
1172 return true;
1173
1174 /* If it's an open(O_TRUNC) or an ftruncate(), don't update */
1175 if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
1176 return false;
1177
1178 /* In all other cases update */
1179 return true;
1180}
1181
Miklos Szeredibefc6492005-11-07 00:59:52 -08001182static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001183{
1184 unsigned ivalid = iattr->ia_valid;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001185
1186 if (ivalid & ATTR_MODE)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001187 arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001188 if (ivalid & ATTR_UID)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001189 arg->valid |= FATTR_UID, arg->uid = iattr->ia_uid;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001190 if (ivalid & ATTR_GID)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001191 arg->valid |= FATTR_GID, arg->gid = iattr->ia_gid;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001192 if (ivalid & ATTR_SIZE)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001193 arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001194 if (ivalid & ATTR_ATIME) {
1195 arg->valid |= FATTR_ATIME;
Miklos Szeredibefc6492005-11-07 00:59:52 -08001196 arg->atime = iattr->ia_atime.tv_sec;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001197 arg->atimensec = iattr->ia_atime.tv_nsec;
1198 if (!(ivalid & ATTR_ATIME_SET))
1199 arg->valid |= FATTR_ATIME_NOW;
1200 }
1201 if ((ivalid & ATTR_MTIME) && update_mtime(ivalid)) {
1202 arg->valid |= FATTR_MTIME;
Miklos Szeredibefc6492005-11-07 00:59:52 -08001203 arg->mtime = iattr->ia_mtime.tv_sec;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001204 arg->mtimensec = iattr->ia_mtime.tv_nsec;
1205 if (!(ivalid & ATTR_MTIME_SET))
1206 arg->valid |= FATTR_MTIME_NOW;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001207 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001208}
1209
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001210/*
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001211 * Prevent concurrent writepages on inode
1212 *
1213 * This is done by adding a negative bias to the inode write counter
1214 * and waiting for all pending writes to finish.
1215 */
1216void fuse_set_nowrite(struct inode *inode)
1217{
1218 struct fuse_conn *fc = get_fuse_conn(inode);
1219 struct fuse_inode *fi = get_fuse_inode(inode);
1220
1221 BUG_ON(!mutex_is_locked(&inode->i_mutex));
1222
1223 spin_lock(&fc->lock);
1224 BUG_ON(fi->writectr < 0);
1225 fi->writectr += FUSE_NOWRITE;
1226 spin_unlock(&fc->lock);
1227 wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE);
1228}
1229
1230/*
1231 * Allow writepages on inode
1232 *
1233 * Remove the bias from the writecounter and send any queued
1234 * writepages.
1235 */
1236static void __fuse_release_nowrite(struct inode *inode)
1237{
1238 struct fuse_inode *fi = get_fuse_inode(inode);
1239
1240 BUG_ON(fi->writectr != FUSE_NOWRITE);
1241 fi->writectr = 0;
1242 fuse_flush_writepages(inode);
1243}
1244
1245void fuse_release_nowrite(struct inode *inode)
1246{
1247 struct fuse_conn *fc = get_fuse_conn(inode);
1248
1249 spin_lock(&fc->lock);
1250 __fuse_release_nowrite(inode);
1251 spin_unlock(&fc->lock);
1252}
1253
1254/*
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001255 * Set attributes, and at the same time refresh them.
1256 *
1257 * Truncation is slightly complicated, because the 'truncate' request
1258 * may fail, in which case we don't want to touch the mapping.
Miklos Szeredi9ffbb912006-10-17 00:10:06 -07001259 * vmtruncate() doesn't allow for this case, so do the rlimit checking
1260 * and the actual truncation by hand.
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001261 */
Miklos Szeredi49d49142007-10-18 03:07:00 -07001262static int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
1263 struct file *file)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001264{
1265 struct inode *inode = entry->d_inode;
1266 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001267 struct fuse_req *req;
1268 struct fuse_setattr_in inarg;
1269 struct fuse_attr_out outarg;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001270 bool is_truncate = false;
1271 loff_t oldsize;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001272 int err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001273
Miklos Szeredie57ac682007-10-18 03:06:58 -07001274 if (!fuse_allow_task(fc, current))
1275 return -EACCES;
1276
Christoph Hellwigdb78b872010-06-04 11:30:03 +02001277 if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS))
1278 attr->ia_valid |= ATTR_FORCE;
1279
1280 err = inode_change_ok(inode, attr);
1281 if (err)
1282 return err;
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001283
Miklos Szeredi6ff958e2007-10-18 03:07:02 -07001284 if ((attr->ia_valid & ATTR_OPEN) && fc->atomic_o_trunc)
1285 return 0;
1286
Christoph Hellwig2c27c652010-06-04 11:30:04 +02001287 if (attr->ia_valid & ATTR_SIZE)
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001288 is_truncate = true;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001289
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001290 req = fuse_get_req(fc);
1291 if (IS_ERR(req))
1292 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001293
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001294 if (is_truncate)
1295 fuse_set_nowrite(inode);
1296
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001297 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -07001298 memset(&outarg, 0, sizeof(outarg));
Miklos Szeredibefc6492005-11-07 00:59:52 -08001299 iattr_to_fattr(attr, &inarg);
Miklos Szeredi49d49142007-10-18 03:07:00 -07001300 if (file) {
1301 struct fuse_file *ff = file->private_data;
1302 inarg.valid |= FATTR_FH;
1303 inarg.fh = ff->fh;
1304 }
Miklos Szeredif3332112007-10-18 03:07:04 -07001305 if (attr->ia_valid & ATTR_SIZE) {
1306 /* For mandatory locking in truncate */
1307 inarg.valid |= FATTR_LOCKOWNER;
1308 inarg.lock_owner = fuse_lock_owner_id(fc, current->files);
1309 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001310 req->in.h.opcode = FUSE_SETATTR;
1311 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001312 req->in.numargs = 1;
1313 req->in.args[0].size = sizeof(inarg);
1314 req->in.args[0].value = &inarg;
1315 req->out.numargs = 1;
Miklos Szeredi0e9663e2007-10-18 03:07:05 -07001316 if (fc->minor < 9)
1317 req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
1318 else
1319 req->out.args[0].size = sizeof(outarg);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001320 req->out.args[0].value = &outarg;
Tejun Heob93f8582008-11-26 12:03:55 +01001321 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001322 err = req->out.h.error;
1323 fuse_put_request(fc, req);
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001324 if (err) {
1325 if (err == -EINTR)
1326 fuse_invalidate_attr(inode);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001327 goto error;
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001328 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001329
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001330 if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
1331 make_bad_inode(inode);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001332 err = -EIO;
1333 goto error;
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001334 }
1335
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001336 spin_lock(&fc->lock);
1337 fuse_change_attributes_common(inode, &outarg.attr,
1338 attr_timeout(&outarg));
1339 oldsize = inode->i_size;
1340 i_size_write(inode, outarg.attr.size);
1341
1342 if (is_truncate) {
1343 /* NOTE: this may release/reacquire fc->lock */
1344 __fuse_release_nowrite(inode);
1345 }
1346 spin_unlock(&fc->lock);
1347
1348 /*
1349 * Only call invalidate_inode_pages2() after removing
1350 * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock.
1351 */
1352 if (S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
npiggin@suse.dec08d3b02009-08-21 02:35:06 +10001353 truncate_pagecache(inode, oldsize, outarg.attr.size);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001354 invalidate_inode_pages2(inode->i_mapping);
1355 }
1356
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001357 return 0;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001358
1359error:
1360 if (is_truncate)
1361 fuse_release_nowrite(inode);
1362
1363 return err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001364}
1365
Miklos Szeredi49d49142007-10-18 03:07:00 -07001366static int fuse_setattr(struct dentry *entry, struct iattr *attr)
1367{
1368 if (attr->ia_valid & ATTR_FILE)
1369 return fuse_do_setattr(entry, attr, attr->ia_file);
1370 else
1371 return fuse_do_setattr(entry, attr, NULL);
1372}
1373
Miklos Szeredie5e55582005-09-09 13:10:28 -07001374static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
1375 struct kstat *stat)
1376{
1377 struct inode *inode = entry->d_inode;
Miklos Szeredi244f6382007-10-16 23:31:02 -07001378 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi244f6382007-10-16 23:31:02 -07001379
1380 if (!fuse_allow_task(fc, current))
1381 return -EACCES;
1382
Miklos Szeredibcb4be82007-11-28 16:21:59 -08001383 return fuse_update_attributes(inode, stat, NULL, NULL);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001384}
1385
Miklos Szeredi92a87802005-09-09 13:10:31 -07001386static int fuse_setxattr(struct dentry *entry, const char *name,
1387 const void *value, size_t size, int flags)
1388{
1389 struct inode *inode = entry->d_inode;
1390 struct fuse_conn *fc = get_fuse_conn(inode);
1391 struct fuse_req *req;
1392 struct fuse_setxattr_in inarg;
1393 int err;
1394
Miklos Szeredi92a87802005-09-09 13:10:31 -07001395 if (fc->no_setxattr)
1396 return -EOPNOTSUPP;
1397
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001398 req = fuse_get_req(fc);
1399 if (IS_ERR(req))
1400 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001401
1402 memset(&inarg, 0, sizeof(inarg));
1403 inarg.size = size;
1404 inarg.flags = flags;
1405 req->in.h.opcode = FUSE_SETXATTR;
1406 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001407 req->in.numargs = 3;
1408 req->in.args[0].size = sizeof(inarg);
1409 req->in.args[0].value = &inarg;
1410 req->in.args[1].size = strlen(name) + 1;
1411 req->in.args[1].value = name;
1412 req->in.args[2].size = size;
1413 req->in.args[2].value = value;
Tejun Heob93f8582008-11-26 12:03:55 +01001414 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001415 err = req->out.h.error;
1416 fuse_put_request(fc, req);
1417 if (err == -ENOSYS) {
1418 fc->no_setxattr = 1;
1419 err = -EOPNOTSUPP;
1420 }
1421 return err;
1422}
1423
1424static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
1425 void *value, size_t size)
1426{
1427 struct inode *inode = entry->d_inode;
1428 struct fuse_conn *fc = get_fuse_conn(inode);
1429 struct fuse_req *req;
1430 struct fuse_getxattr_in inarg;
1431 struct fuse_getxattr_out outarg;
1432 ssize_t ret;
1433
1434 if (fc->no_getxattr)
1435 return -EOPNOTSUPP;
1436
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001437 req = fuse_get_req(fc);
1438 if (IS_ERR(req))
1439 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001440
1441 memset(&inarg, 0, sizeof(inarg));
1442 inarg.size = size;
1443 req->in.h.opcode = FUSE_GETXATTR;
1444 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001445 req->in.numargs = 2;
1446 req->in.args[0].size = sizeof(inarg);
1447 req->in.args[0].value = &inarg;
1448 req->in.args[1].size = strlen(name) + 1;
1449 req->in.args[1].value = name;
1450 /* This is really two different operations rolled into one */
1451 req->out.numargs = 1;
1452 if (size) {
1453 req->out.argvar = 1;
1454 req->out.args[0].size = size;
1455 req->out.args[0].value = value;
1456 } else {
1457 req->out.args[0].size = sizeof(outarg);
1458 req->out.args[0].value = &outarg;
1459 }
Tejun Heob93f8582008-11-26 12:03:55 +01001460 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001461 ret = req->out.h.error;
1462 if (!ret)
1463 ret = size ? req->out.args[0].size : outarg.size;
1464 else {
1465 if (ret == -ENOSYS) {
1466 fc->no_getxattr = 1;
1467 ret = -EOPNOTSUPP;
1468 }
1469 }
1470 fuse_put_request(fc, req);
1471 return ret;
1472}
1473
1474static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
1475{
1476 struct inode *inode = entry->d_inode;
1477 struct fuse_conn *fc = get_fuse_conn(inode);
1478 struct fuse_req *req;
1479 struct fuse_getxattr_in inarg;
1480 struct fuse_getxattr_out outarg;
1481 ssize_t ret;
1482
Miklos Szeredie57ac682007-10-18 03:06:58 -07001483 if (!fuse_allow_task(fc, current))
1484 return -EACCES;
1485
Miklos Szeredi92a87802005-09-09 13:10:31 -07001486 if (fc->no_listxattr)
1487 return -EOPNOTSUPP;
1488
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001489 req = fuse_get_req(fc);
1490 if (IS_ERR(req))
1491 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001492
1493 memset(&inarg, 0, sizeof(inarg));
1494 inarg.size = size;
1495 req->in.h.opcode = FUSE_LISTXATTR;
1496 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001497 req->in.numargs = 1;
1498 req->in.args[0].size = sizeof(inarg);
1499 req->in.args[0].value = &inarg;
1500 /* This is really two different operations rolled into one */
1501 req->out.numargs = 1;
1502 if (size) {
1503 req->out.argvar = 1;
1504 req->out.args[0].size = size;
1505 req->out.args[0].value = list;
1506 } else {
1507 req->out.args[0].size = sizeof(outarg);
1508 req->out.args[0].value = &outarg;
1509 }
Tejun Heob93f8582008-11-26 12:03:55 +01001510 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001511 ret = req->out.h.error;
1512 if (!ret)
1513 ret = size ? req->out.args[0].size : outarg.size;
1514 else {
1515 if (ret == -ENOSYS) {
1516 fc->no_listxattr = 1;
1517 ret = -EOPNOTSUPP;
1518 }
1519 }
1520 fuse_put_request(fc, req);
1521 return ret;
1522}
1523
1524static int fuse_removexattr(struct dentry *entry, const char *name)
1525{
1526 struct inode *inode = entry->d_inode;
1527 struct fuse_conn *fc = get_fuse_conn(inode);
1528 struct fuse_req *req;
1529 int err;
1530
1531 if (fc->no_removexattr)
1532 return -EOPNOTSUPP;
1533
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001534 req = fuse_get_req(fc);
1535 if (IS_ERR(req))
1536 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001537
1538 req->in.h.opcode = FUSE_REMOVEXATTR;
1539 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001540 req->in.numargs = 1;
1541 req->in.args[0].size = strlen(name) + 1;
1542 req->in.args[0].value = name;
Tejun Heob93f8582008-11-26 12:03:55 +01001543 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001544 err = req->out.h.error;
1545 fuse_put_request(fc, req);
1546 if (err == -ENOSYS) {
1547 fc->no_removexattr = 1;
1548 err = -EOPNOTSUPP;
1549 }
1550 return err;
1551}
1552
Arjan van de Ven754661f2007-02-12 00:55:38 -08001553static const struct inode_operations fuse_dir_inode_operations = {
Miklos Szeredie5e55582005-09-09 13:10:28 -07001554 .lookup = fuse_lookup,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001555 .mkdir = fuse_mkdir,
1556 .symlink = fuse_symlink,
1557 .unlink = fuse_unlink,
1558 .rmdir = fuse_rmdir,
1559 .rename = fuse_rename,
1560 .link = fuse_link,
1561 .setattr = fuse_setattr,
1562 .create = fuse_create,
1563 .mknod = fuse_mknod,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001564 .permission = fuse_permission,
1565 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001566 .setxattr = fuse_setxattr,
1567 .getxattr = fuse_getxattr,
1568 .listxattr = fuse_listxattr,
1569 .removexattr = fuse_removexattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001570};
1571
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -08001572static const struct file_operations fuse_dir_operations = {
Miklos Szeredib6aeade2005-09-09 13:10:30 -07001573 .llseek = generic_file_llseek,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001574 .read = generic_read_dir,
1575 .readdir = fuse_readdir,
1576 .open = fuse_dir_open,
1577 .release = fuse_dir_release,
Miklos Szeredi82547982005-09-09 13:10:38 -07001578 .fsync = fuse_dir_fsync,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001579};
1580
Arjan van de Ven754661f2007-02-12 00:55:38 -08001581static const struct inode_operations fuse_common_inode_operations = {
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001582 .setattr = fuse_setattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001583 .permission = fuse_permission,
1584 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001585 .setxattr = fuse_setxattr,
1586 .getxattr = fuse_getxattr,
1587 .listxattr = fuse_listxattr,
1588 .removexattr = fuse_removexattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001589};
1590
Arjan van de Ven754661f2007-02-12 00:55:38 -08001591static const struct inode_operations fuse_symlink_inode_operations = {
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001592 .setattr = fuse_setattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001593 .follow_link = fuse_follow_link,
1594 .put_link = fuse_put_link,
1595 .readlink = generic_readlink,
1596 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001597 .setxattr = fuse_setxattr,
1598 .getxattr = fuse_getxattr,
1599 .listxattr = fuse_listxattr,
1600 .removexattr = fuse_removexattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001601};
1602
1603void fuse_init_common(struct inode *inode)
1604{
1605 inode->i_op = &fuse_common_inode_operations;
1606}
1607
1608void fuse_init_dir(struct inode *inode)
1609{
1610 inode->i_op = &fuse_dir_inode_operations;
1611 inode->i_fop = &fuse_dir_operations;
1612}
1613
1614void fuse_init_symlink(struct inode *inode)
1615{
1616 inode->i_op = &fuse_symlink_inode_operations;
1617}