blob: f738599fd8cd0b18e52d298513f5230c0359503c [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 */
Nick Pigginb74c79e2011-01-07 17:49:58 +1100988static int fuse_permission(struct inode *inode, int mask, unsigned int flags)
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
Nick Pigginb74c79e2011-01-07 17:49:58 +1100994 if (flags & IPERM_FLAG_RCU)
995 return -ECHILD;
996
Miklos Szeredi87729a52005-09-09 13:10:34 -0700997 if (!fuse_allow_task(fc, current))
Miklos Szeredie5e55582005-09-09 13:10:28 -0700998 return -EACCES;
Miklos Szeredi244f6382007-10-16 23:31:02 -0700999
1000 /*
Miklos Szeredie8e96152007-10-16 23:31:06 -07001001 * If attributes are needed, refresh them before proceeding
Miklos Szeredi244f6382007-10-16 23:31:02 -07001002 */
Miklos Szeredie8e96152007-10-16 23:31:06 -07001003 if ((fc->flags & FUSE_DEFAULT_PERMISSIONS) ||
1004 ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
Miklos Szeredibcb4be82007-11-28 16:21:59 -08001005 err = fuse_update_attributes(inode, NULL, NULL, &refreshed);
1006 if (err)
1007 return err;
Miklos Szeredi244f6382007-10-16 23:31:02 -07001008 }
1009
1010 if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
Nick Pigginb74c79e2011-01-07 17:49:58 +11001011 err = generic_permission(inode, mask, flags, NULL);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001012
1013 /* If permission is denied, try to refresh file
1014 attributes. This is also needed, because the root
1015 node will at first have no permissions */
Miklos Szeredi244f6382007-10-16 23:31:02 -07001016 if (err == -EACCES && !refreshed) {
Miklos Szeredic79e3222007-10-18 03:06:59 -07001017 err = fuse_do_getattr(inode, NULL, NULL);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001018 if (!err)
Nick Pigginb74c79e2011-01-07 17:49:58 +11001019 err = generic_permission(inode, mask,
1020 flags, NULL);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001021 }
1022
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001023 /* Note: the opposite of the above test does not
1024 exist. So if permissions are revoked this won't be
1025 noticed immediately, only after the attribute
1026 timeout has expired */
Eric Paris9cfcac82010-07-23 11:43:51 -04001027 } else if (mask & (MAY_ACCESS | MAY_CHDIR)) {
Miklos Szeredie8e96152007-10-16 23:31:06 -07001028 err = fuse_access(inode, mask);
1029 } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
1030 if (!(inode->i_mode & S_IXUGO)) {
1031 if (refreshed)
1032 return -EACCES;
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001033
Miklos Szeredic79e3222007-10-18 03:06:59 -07001034 err = fuse_do_getattr(inode, NULL, NULL);
Miklos Szeredie8e96152007-10-16 23:31:06 -07001035 if (!err && !(inode->i_mode & S_IXUGO))
1036 return -EACCES;
1037 }
Miklos Szeredie5e55582005-09-09 13:10:28 -07001038 }
Miklos Szeredi244f6382007-10-16 23:31:02 -07001039 return err;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001040}
1041
1042static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
1043 void *dstbuf, filldir_t filldir)
1044{
1045 while (nbytes >= FUSE_NAME_OFFSET) {
1046 struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
1047 size_t reclen = FUSE_DIRENT_SIZE(dirent);
1048 int over;
1049 if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
1050 return -EIO;
1051 if (reclen > nbytes)
1052 break;
1053
1054 over = filldir(dstbuf, dirent->name, dirent->namelen,
1055 file->f_pos, dirent->ino, dirent->type);
1056 if (over)
1057 break;
1058
1059 buf += reclen;
1060 nbytes -= reclen;
1061 file->f_pos = dirent->off;
1062 }
1063
1064 return 0;
1065}
1066
Miklos Szeredie5e55582005-09-09 13:10:28 -07001067static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
1068{
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001069 int err;
1070 size_t nbytes;
1071 struct page *page;
Josef Sipek7706a9d2006-12-08 02:37:02 -08001072 struct inode *inode = file->f_path.dentry->d_inode;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001073 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi248d86e2006-01-06 00:19:39 -08001074 struct fuse_req *req;
1075
1076 if (is_bad_inode(inode))
1077 return -EIO;
1078
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001079 req = fuse_get_req(fc);
1080 if (IS_ERR(req))
1081 return PTR_ERR(req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001082
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001083 page = alloc_page(GFP_KERNEL);
1084 if (!page) {
1085 fuse_put_request(fc, req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001086 return -ENOMEM;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001087 }
Miklos Szeredif4975c62009-04-02 14:25:34 +02001088 req->out.argpages = 1;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001089 req->num_pages = 1;
1090 req->pages[0] = page;
Miklos Szeredi2106cb12009-04-28 16:56:37 +02001091 fuse_read_fill(req, file, file->f_pos, PAGE_SIZE, FUSE_READDIR);
Tejun Heob93f8582008-11-26 12:03:55 +01001092 fuse_request_send(fc, req);
Miklos Szeredi361b1eb52006-01-16 22:14:45 -08001093 nbytes = req->out.args[0].size;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001094 err = req->out.h.error;
1095 fuse_put_request(fc, req);
1096 if (!err)
1097 err = parse_dirfile(page_address(page), nbytes, file, dstbuf,
1098 filldir);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001099
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001100 __free_page(page);
Miklos Szeredib36c31b2005-09-09 13:10:38 -07001101 fuse_invalidate_attr(inode); /* atime changed */
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001102 return err;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001103}
1104
1105static char *read_link(struct dentry *dentry)
1106{
1107 struct inode *inode = dentry->d_inode;
1108 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001109 struct fuse_req *req = fuse_get_req(fc);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001110 char *link;
1111
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001112 if (IS_ERR(req))
David Howellse231c2e2008-02-07 00:15:26 -08001113 return ERR_CAST(req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001114
1115 link = (char *) __get_free_page(GFP_KERNEL);
1116 if (!link) {
1117 link = ERR_PTR(-ENOMEM);
1118 goto out;
1119 }
1120 req->in.h.opcode = FUSE_READLINK;
1121 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001122 req->out.argvar = 1;
1123 req->out.numargs = 1;
1124 req->out.args[0].size = PAGE_SIZE - 1;
1125 req->out.args[0].value = link;
Tejun Heob93f8582008-11-26 12:03:55 +01001126 fuse_request_send(fc, req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001127 if (req->out.h.error) {
1128 free_page((unsigned long) link);
1129 link = ERR_PTR(req->out.h.error);
1130 } else
1131 link[req->out.args[0].size] = '\0';
1132 out:
1133 fuse_put_request(fc, req);
Miklos Szeredib36c31b2005-09-09 13:10:38 -07001134 fuse_invalidate_attr(inode); /* atime changed */
Miklos Szeredie5e55582005-09-09 13:10:28 -07001135 return link;
1136}
1137
1138static void free_link(char *link)
1139{
1140 if (!IS_ERR(link))
1141 free_page((unsigned long) link);
1142}
1143
1144static void *fuse_follow_link(struct dentry *dentry, struct nameidata *nd)
1145{
1146 nd_set_link(nd, read_link(dentry));
1147 return NULL;
1148}
1149
1150static void fuse_put_link(struct dentry *dentry, struct nameidata *nd, void *c)
1151{
1152 free_link(nd_get_link(nd));
1153}
1154
1155static int fuse_dir_open(struct inode *inode, struct file *file)
1156{
Miklos Szeredi91fe96b2009-04-28 16:56:37 +02001157 return fuse_open_common(inode, file, true);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001158}
1159
1160static int fuse_dir_release(struct inode *inode, struct file *file)
1161{
Miklos Szeredi8b0797a2009-04-28 16:56:39 +02001162 fuse_release_common(file, FUSE_RELEASEDIR);
1163
1164 return 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001165}
1166
Christoph Hellwig7ea80852010-05-26 17:53:25 +02001167static int fuse_dir_fsync(struct file *file, int datasync)
Miklos Szeredi82547982005-09-09 13:10:38 -07001168{
Christoph Hellwig7ea80852010-05-26 17:53:25 +02001169 return fuse_fsync_common(file, datasync, 1);
Miklos Szeredi82547982005-09-09 13:10:38 -07001170}
1171
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001172static bool update_mtime(unsigned ivalid)
1173{
1174 /* Always update if mtime is explicitly set */
1175 if (ivalid & ATTR_MTIME_SET)
1176 return true;
1177
1178 /* If it's an open(O_TRUNC) or an ftruncate(), don't update */
1179 if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
1180 return false;
1181
1182 /* In all other cases update */
1183 return true;
1184}
1185
Miklos Szeredibefc6492005-11-07 00:59:52 -08001186static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001187{
1188 unsigned ivalid = iattr->ia_valid;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001189
1190 if (ivalid & ATTR_MODE)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001191 arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001192 if (ivalid & ATTR_UID)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001193 arg->valid |= FATTR_UID, arg->uid = iattr->ia_uid;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001194 if (ivalid & ATTR_GID)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001195 arg->valid |= FATTR_GID, arg->gid = iattr->ia_gid;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001196 if (ivalid & ATTR_SIZE)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001197 arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001198 if (ivalid & ATTR_ATIME) {
1199 arg->valid |= FATTR_ATIME;
Miklos Szeredibefc6492005-11-07 00:59:52 -08001200 arg->atime = iattr->ia_atime.tv_sec;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001201 arg->atimensec = iattr->ia_atime.tv_nsec;
1202 if (!(ivalid & ATTR_ATIME_SET))
1203 arg->valid |= FATTR_ATIME_NOW;
1204 }
1205 if ((ivalid & ATTR_MTIME) && update_mtime(ivalid)) {
1206 arg->valid |= FATTR_MTIME;
Miklos Szeredibefc6492005-11-07 00:59:52 -08001207 arg->mtime = iattr->ia_mtime.tv_sec;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001208 arg->mtimensec = iattr->ia_mtime.tv_nsec;
1209 if (!(ivalid & ATTR_MTIME_SET))
1210 arg->valid |= FATTR_MTIME_NOW;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001211 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001212}
1213
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001214/*
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001215 * Prevent concurrent writepages on inode
1216 *
1217 * This is done by adding a negative bias to the inode write counter
1218 * and waiting for all pending writes to finish.
1219 */
1220void fuse_set_nowrite(struct inode *inode)
1221{
1222 struct fuse_conn *fc = get_fuse_conn(inode);
1223 struct fuse_inode *fi = get_fuse_inode(inode);
1224
1225 BUG_ON(!mutex_is_locked(&inode->i_mutex));
1226
1227 spin_lock(&fc->lock);
1228 BUG_ON(fi->writectr < 0);
1229 fi->writectr += FUSE_NOWRITE;
1230 spin_unlock(&fc->lock);
1231 wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE);
1232}
1233
1234/*
1235 * Allow writepages on inode
1236 *
1237 * Remove the bias from the writecounter and send any queued
1238 * writepages.
1239 */
1240static void __fuse_release_nowrite(struct inode *inode)
1241{
1242 struct fuse_inode *fi = get_fuse_inode(inode);
1243
1244 BUG_ON(fi->writectr != FUSE_NOWRITE);
1245 fi->writectr = 0;
1246 fuse_flush_writepages(inode);
1247}
1248
1249void fuse_release_nowrite(struct inode *inode)
1250{
1251 struct fuse_conn *fc = get_fuse_conn(inode);
1252
1253 spin_lock(&fc->lock);
1254 __fuse_release_nowrite(inode);
1255 spin_unlock(&fc->lock);
1256}
1257
1258/*
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001259 * Set attributes, and at the same time refresh them.
1260 *
1261 * Truncation is slightly complicated, because the 'truncate' request
1262 * may fail, in which case we don't want to touch the mapping.
Miklos Szeredi9ffbb912006-10-17 00:10:06 -07001263 * vmtruncate() doesn't allow for this case, so do the rlimit checking
1264 * and the actual truncation by hand.
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001265 */
Miklos Szeredi49d49142007-10-18 03:07:00 -07001266static int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
1267 struct file *file)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001268{
1269 struct inode *inode = entry->d_inode;
1270 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001271 struct fuse_req *req;
1272 struct fuse_setattr_in inarg;
1273 struct fuse_attr_out outarg;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001274 bool is_truncate = false;
1275 loff_t oldsize;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001276 int err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001277
Miklos Szeredie57ac682007-10-18 03:06:58 -07001278 if (!fuse_allow_task(fc, current))
1279 return -EACCES;
1280
Christoph Hellwigdb78b872010-06-04 11:30:03 +02001281 if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS))
1282 attr->ia_valid |= ATTR_FORCE;
1283
1284 err = inode_change_ok(inode, attr);
1285 if (err)
1286 return err;
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001287
Miklos Szeredi6ff958e2007-10-18 03:07:02 -07001288 if ((attr->ia_valid & ATTR_OPEN) && fc->atomic_o_trunc)
1289 return 0;
1290
Christoph Hellwig2c27c652010-06-04 11:30:04 +02001291 if (attr->ia_valid & ATTR_SIZE)
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001292 is_truncate = true;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001293
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001294 req = fuse_get_req(fc);
1295 if (IS_ERR(req))
1296 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001297
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001298 if (is_truncate)
1299 fuse_set_nowrite(inode);
1300
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001301 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -07001302 memset(&outarg, 0, sizeof(outarg));
Miklos Szeredibefc6492005-11-07 00:59:52 -08001303 iattr_to_fattr(attr, &inarg);
Miklos Szeredi49d49142007-10-18 03:07:00 -07001304 if (file) {
1305 struct fuse_file *ff = file->private_data;
1306 inarg.valid |= FATTR_FH;
1307 inarg.fh = ff->fh;
1308 }
Miklos Szeredif3332112007-10-18 03:07:04 -07001309 if (attr->ia_valid & ATTR_SIZE) {
1310 /* For mandatory locking in truncate */
1311 inarg.valid |= FATTR_LOCKOWNER;
1312 inarg.lock_owner = fuse_lock_owner_id(fc, current->files);
1313 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001314 req->in.h.opcode = FUSE_SETATTR;
1315 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001316 req->in.numargs = 1;
1317 req->in.args[0].size = sizeof(inarg);
1318 req->in.args[0].value = &inarg;
1319 req->out.numargs = 1;
Miklos Szeredi0e9663e2007-10-18 03:07:05 -07001320 if (fc->minor < 9)
1321 req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
1322 else
1323 req->out.args[0].size = sizeof(outarg);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001324 req->out.args[0].value = &outarg;
Tejun Heob93f8582008-11-26 12:03:55 +01001325 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001326 err = req->out.h.error;
1327 fuse_put_request(fc, req);
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001328 if (err) {
1329 if (err == -EINTR)
1330 fuse_invalidate_attr(inode);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001331 goto error;
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001332 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001333
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001334 if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
1335 make_bad_inode(inode);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001336 err = -EIO;
1337 goto error;
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001338 }
1339
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001340 spin_lock(&fc->lock);
1341 fuse_change_attributes_common(inode, &outarg.attr,
1342 attr_timeout(&outarg));
1343 oldsize = inode->i_size;
1344 i_size_write(inode, outarg.attr.size);
1345
1346 if (is_truncate) {
1347 /* NOTE: this may release/reacquire fc->lock */
1348 __fuse_release_nowrite(inode);
1349 }
1350 spin_unlock(&fc->lock);
1351
1352 /*
1353 * Only call invalidate_inode_pages2() after removing
1354 * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock.
1355 */
1356 if (S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
npiggin@suse.dec08d3b02009-08-21 02:35:06 +10001357 truncate_pagecache(inode, oldsize, outarg.attr.size);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001358 invalidate_inode_pages2(inode->i_mapping);
1359 }
1360
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001361 return 0;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001362
1363error:
1364 if (is_truncate)
1365 fuse_release_nowrite(inode);
1366
1367 return err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001368}
1369
Miklos Szeredi49d49142007-10-18 03:07:00 -07001370static int fuse_setattr(struct dentry *entry, struct iattr *attr)
1371{
1372 if (attr->ia_valid & ATTR_FILE)
1373 return fuse_do_setattr(entry, attr, attr->ia_file);
1374 else
1375 return fuse_do_setattr(entry, attr, NULL);
1376}
1377
Miklos Szeredie5e55582005-09-09 13:10:28 -07001378static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
1379 struct kstat *stat)
1380{
1381 struct inode *inode = entry->d_inode;
Miklos Szeredi244f6382007-10-16 23:31:02 -07001382 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi244f6382007-10-16 23:31:02 -07001383
1384 if (!fuse_allow_task(fc, current))
1385 return -EACCES;
1386
Miklos Szeredibcb4be82007-11-28 16:21:59 -08001387 return fuse_update_attributes(inode, stat, NULL, NULL);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001388}
1389
Miklos Szeredi92a87802005-09-09 13:10:31 -07001390static int fuse_setxattr(struct dentry *entry, const char *name,
1391 const void *value, size_t size, int flags)
1392{
1393 struct inode *inode = entry->d_inode;
1394 struct fuse_conn *fc = get_fuse_conn(inode);
1395 struct fuse_req *req;
1396 struct fuse_setxattr_in inarg;
1397 int err;
1398
Miklos Szeredi92a87802005-09-09 13:10:31 -07001399 if (fc->no_setxattr)
1400 return -EOPNOTSUPP;
1401
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001402 req = fuse_get_req(fc);
1403 if (IS_ERR(req))
1404 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001405
1406 memset(&inarg, 0, sizeof(inarg));
1407 inarg.size = size;
1408 inarg.flags = flags;
1409 req->in.h.opcode = FUSE_SETXATTR;
1410 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001411 req->in.numargs = 3;
1412 req->in.args[0].size = sizeof(inarg);
1413 req->in.args[0].value = &inarg;
1414 req->in.args[1].size = strlen(name) + 1;
1415 req->in.args[1].value = name;
1416 req->in.args[2].size = size;
1417 req->in.args[2].value = value;
Tejun Heob93f8582008-11-26 12:03:55 +01001418 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001419 err = req->out.h.error;
1420 fuse_put_request(fc, req);
1421 if (err == -ENOSYS) {
1422 fc->no_setxattr = 1;
1423 err = -EOPNOTSUPP;
1424 }
1425 return err;
1426}
1427
1428static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
1429 void *value, size_t size)
1430{
1431 struct inode *inode = entry->d_inode;
1432 struct fuse_conn *fc = get_fuse_conn(inode);
1433 struct fuse_req *req;
1434 struct fuse_getxattr_in inarg;
1435 struct fuse_getxattr_out outarg;
1436 ssize_t ret;
1437
1438 if (fc->no_getxattr)
1439 return -EOPNOTSUPP;
1440
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001441 req = fuse_get_req(fc);
1442 if (IS_ERR(req))
1443 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001444
1445 memset(&inarg, 0, sizeof(inarg));
1446 inarg.size = size;
1447 req->in.h.opcode = FUSE_GETXATTR;
1448 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001449 req->in.numargs = 2;
1450 req->in.args[0].size = sizeof(inarg);
1451 req->in.args[0].value = &inarg;
1452 req->in.args[1].size = strlen(name) + 1;
1453 req->in.args[1].value = name;
1454 /* This is really two different operations rolled into one */
1455 req->out.numargs = 1;
1456 if (size) {
1457 req->out.argvar = 1;
1458 req->out.args[0].size = size;
1459 req->out.args[0].value = value;
1460 } else {
1461 req->out.args[0].size = sizeof(outarg);
1462 req->out.args[0].value = &outarg;
1463 }
Tejun Heob93f8582008-11-26 12:03:55 +01001464 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001465 ret = req->out.h.error;
1466 if (!ret)
1467 ret = size ? req->out.args[0].size : outarg.size;
1468 else {
1469 if (ret == -ENOSYS) {
1470 fc->no_getxattr = 1;
1471 ret = -EOPNOTSUPP;
1472 }
1473 }
1474 fuse_put_request(fc, req);
1475 return ret;
1476}
1477
1478static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
1479{
1480 struct inode *inode = entry->d_inode;
1481 struct fuse_conn *fc = get_fuse_conn(inode);
1482 struct fuse_req *req;
1483 struct fuse_getxattr_in inarg;
1484 struct fuse_getxattr_out outarg;
1485 ssize_t ret;
1486
Miklos Szeredie57ac682007-10-18 03:06:58 -07001487 if (!fuse_allow_task(fc, current))
1488 return -EACCES;
1489
Miklos Szeredi92a87802005-09-09 13:10:31 -07001490 if (fc->no_listxattr)
1491 return -EOPNOTSUPP;
1492
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001493 req = fuse_get_req(fc);
1494 if (IS_ERR(req))
1495 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001496
1497 memset(&inarg, 0, sizeof(inarg));
1498 inarg.size = size;
1499 req->in.h.opcode = FUSE_LISTXATTR;
1500 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001501 req->in.numargs = 1;
1502 req->in.args[0].size = sizeof(inarg);
1503 req->in.args[0].value = &inarg;
1504 /* This is really two different operations rolled into one */
1505 req->out.numargs = 1;
1506 if (size) {
1507 req->out.argvar = 1;
1508 req->out.args[0].size = size;
1509 req->out.args[0].value = list;
1510 } else {
1511 req->out.args[0].size = sizeof(outarg);
1512 req->out.args[0].value = &outarg;
1513 }
Tejun Heob93f8582008-11-26 12:03:55 +01001514 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001515 ret = req->out.h.error;
1516 if (!ret)
1517 ret = size ? req->out.args[0].size : outarg.size;
1518 else {
1519 if (ret == -ENOSYS) {
1520 fc->no_listxattr = 1;
1521 ret = -EOPNOTSUPP;
1522 }
1523 }
1524 fuse_put_request(fc, req);
1525 return ret;
1526}
1527
1528static int fuse_removexattr(struct dentry *entry, const char *name)
1529{
1530 struct inode *inode = entry->d_inode;
1531 struct fuse_conn *fc = get_fuse_conn(inode);
1532 struct fuse_req *req;
1533 int err;
1534
1535 if (fc->no_removexattr)
1536 return -EOPNOTSUPP;
1537
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001538 req = fuse_get_req(fc);
1539 if (IS_ERR(req))
1540 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001541
1542 req->in.h.opcode = FUSE_REMOVEXATTR;
1543 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001544 req->in.numargs = 1;
1545 req->in.args[0].size = strlen(name) + 1;
1546 req->in.args[0].value = name;
Tejun Heob93f8582008-11-26 12:03:55 +01001547 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001548 err = req->out.h.error;
1549 fuse_put_request(fc, req);
1550 if (err == -ENOSYS) {
1551 fc->no_removexattr = 1;
1552 err = -EOPNOTSUPP;
1553 }
1554 return err;
1555}
1556
Arjan van de Ven754661f2007-02-12 00:55:38 -08001557static const struct inode_operations fuse_dir_inode_operations = {
Miklos Szeredie5e55582005-09-09 13:10:28 -07001558 .lookup = fuse_lookup,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001559 .mkdir = fuse_mkdir,
1560 .symlink = fuse_symlink,
1561 .unlink = fuse_unlink,
1562 .rmdir = fuse_rmdir,
1563 .rename = fuse_rename,
1564 .link = fuse_link,
1565 .setattr = fuse_setattr,
1566 .create = fuse_create,
1567 .mknod = fuse_mknod,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001568 .permission = fuse_permission,
1569 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001570 .setxattr = fuse_setxattr,
1571 .getxattr = fuse_getxattr,
1572 .listxattr = fuse_listxattr,
1573 .removexattr = fuse_removexattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001574};
1575
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -08001576static const struct file_operations fuse_dir_operations = {
Miklos Szeredib6aeade2005-09-09 13:10:30 -07001577 .llseek = generic_file_llseek,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001578 .read = generic_read_dir,
1579 .readdir = fuse_readdir,
1580 .open = fuse_dir_open,
1581 .release = fuse_dir_release,
Miklos Szeredi82547982005-09-09 13:10:38 -07001582 .fsync = fuse_dir_fsync,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001583};
1584
Arjan van de Ven754661f2007-02-12 00:55:38 -08001585static const struct inode_operations fuse_common_inode_operations = {
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001586 .setattr = fuse_setattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001587 .permission = fuse_permission,
1588 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001589 .setxattr = fuse_setxattr,
1590 .getxattr = fuse_getxattr,
1591 .listxattr = fuse_listxattr,
1592 .removexattr = fuse_removexattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001593};
1594
Arjan van de Ven754661f2007-02-12 00:55:38 -08001595static const struct inode_operations fuse_symlink_inode_operations = {
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001596 .setattr = fuse_setattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001597 .follow_link = fuse_follow_link,
1598 .put_link = fuse_put_link,
1599 .readlink = generic_readlink,
1600 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001601 .setxattr = fuse_setxattr,
1602 .getxattr = fuse_getxattr,
1603 .listxattr = fuse_listxattr,
1604 .removexattr = fuse_removexattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001605};
1606
1607void fuse_init_common(struct inode *inode)
1608{
1609 inode->i_op = &fuse_common_inode_operations;
1610}
1611
1612void fuse_init_dir(struct inode *inode)
1613{
1614 inode->i_op = &fuse_dir_inode_operations;
1615 inode->i_fop = &fuse_dir_operations;
1616}
1617
1618void fuse_init_symlink(struct inode *inode)
1619{
1620 inode->i_op = &fuse_symlink_inode_operations;
1621}