blob: faa3b2f867407e768f44dc28f1ceb99c7a4b78bd [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{
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800159 struct inode *inode = entry->d_inode;
160
161 if (inode && is_bad_inode(inode))
Miklos Szeredie5e55582005-09-09 13:10:28 -0700162 return 0;
Miklos Szeredi0a0898c2006-07-30 03:04:10 -0700163 else if (fuse_dentry_time(entry) < get_jiffies_64()) {
Miklos Szeredie5e55582005-09-09 13:10:28 -0700164 int err;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700165 struct fuse_entry_out outarg;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800166 struct fuse_conn *fc;
167 struct fuse_req *req;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800168 struct fuse_req *forget_req;
Miklos Szeredie956edd2006-10-17 00:10:12 -0700169 struct dentry *parent;
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700170 u64 attr_version;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800171
Miklos Szeredi50322fe2006-02-28 16:59:03 -0800172 /* For negative dentries, always do a fresh lookup */
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800173 if (!inode)
174 return 0;
175
176 fc = get_fuse_conn(inode);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700177 req = fuse_get_req(fc);
178 if (IS_ERR(req))
Miklos Szeredie5e55582005-09-09 13:10:28 -0700179 return 0;
180
Miklos Szeredi2d510132006-11-25 11:09:20 -0800181 forget_req = fuse_get_req(fc);
182 if (IS_ERR(forget_req)) {
183 fuse_put_request(fc, req);
184 return 0;
185 }
186
Miklos Szeredi7dca9fd2007-11-28 16:21:59 -0800187 attr_version = fuse_get_attr_version(fc);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700188
Miklos Szeredie956edd2006-10-17 00:10:12 -0700189 parent = dget_parent(entry);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700190 fuse_lookup_init(fc, req, get_node_id(parent->d_inode),
191 &entry->d_name, &outarg);
Tejun Heob93f8582008-11-26 12:03:55 +0100192 fuse_request_send(fc, req);
Miklos Szeredie956edd2006-10-17 00:10:12 -0700193 dput(parent);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700194 err = req->out.h.error;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800195 fuse_put_request(fc, req);
Miklos Szeredi50322fe2006-02-28 16:59:03 -0800196 /* Zero nodeid is same as -ENOENT */
197 if (!err && !outarg.nodeid)
198 err = -ENOENT;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700199 if (!err) {
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800200 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700201 if (outarg.nodeid != get_node_id(inode)) {
Miklos Szeredi2d510132006-11-25 11:09:20 -0800202 fuse_send_forget(fc, forget_req,
203 outarg.nodeid, 1);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700204 return 0;
205 }
Miklos Szeredi8da5ff22006-10-17 00:10:08 -0700206 spin_lock(&fc->lock);
Miklos Szeredi1729a162008-11-26 12:03:54 +0100207 fi->nlookup++;
Miklos Szeredi8da5ff22006-10-17 00:10:08 -0700208 spin_unlock(&fc->lock);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700209 }
Miklos Szeredi2d510132006-11-25 11:09:20 -0800210 fuse_put_request(fc, forget_req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700211 if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700212 return 0;
213
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700214 fuse_change_attributes(inode, &outarg.attr,
215 entry_attr_timeout(&outarg),
216 attr_version);
217 fuse_change_entry_timeout(entry, &outarg);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700218 }
219 return 1;
220}
221
Miklos Szeredi8bfc0162006-01-16 22:14:28 -0800222static int invalid_nodeid(u64 nodeid)
Miklos Szeredi2827d0b22005-11-28 13:44:16 -0800223{
224 return !nodeid || nodeid == FUSE_ROOT_ID;
225}
226
Al Viro42695902009-02-20 05:59:13 +0000227const struct dentry_operations fuse_dentry_operations = {
Miklos Szeredie5e55582005-09-09 13:10:28 -0700228 .d_revalidate = fuse_dentry_revalidate,
229};
230
Timo Savolaa5bfffac2007-04-08 16:04:00 -0700231int fuse_valid_type(int m)
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800232{
233 return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) ||
234 S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m);
235}
236
Miklos Szeredid2a85162006-10-17 00:10:11 -0700237/*
238 * Add a directory inode to a dentry, ensuring that no other dentry
239 * refers to this inode. Called with fc->inst_mutex.
240 */
Miklos Szeredi0de62562008-07-25 01:48:59 -0700241static struct dentry *fuse_d_add_directory(struct dentry *entry,
242 struct inode *inode)
Miklos Szeredid2a85162006-10-17 00:10:11 -0700243{
244 struct dentry *alias = d_find_alias(inode);
Miklos Szeredi0de62562008-07-25 01:48:59 -0700245 if (alias && !(alias->d_flags & DCACHE_DISCONNECTED)) {
Miklos Szeredid2a85162006-10-17 00:10:11 -0700246 /* This tries to shrink the subtree below alias */
247 fuse_invalidate_entry(alias);
248 dput(alias);
249 if (!list_empty(&inode->i_dentry))
Miklos Szeredi0de62562008-07-25 01:48:59 -0700250 return ERR_PTR(-EBUSY);
251 } else {
252 dput(alias);
Miklos Szeredid2a85162006-10-17 00:10:11 -0700253 }
Miklos Szeredi0de62562008-07-25 01:48:59 -0700254 return d_splice_alias(inode, entry);
Miklos Szeredid2a85162006-10-17 00:10:11 -0700255}
256
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700257int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name,
258 struct fuse_entry_out *outarg, struct inode **inode)
259{
260 struct fuse_conn *fc = get_fuse_conn_super(sb);
261 struct fuse_req *req;
262 struct fuse_req *forget_req;
263 u64 attr_version;
264 int err;
265
266 *inode = NULL;
267 err = -ENAMETOOLONG;
268 if (name->len > FUSE_NAME_MAX)
269 goto out;
270
271 req = fuse_get_req(fc);
272 err = PTR_ERR(req);
273 if (IS_ERR(req))
274 goto out;
275
276 forget_req = fuse_get_req(fc);
277 err = PTR_ERR(forget_req);
278 if (IS_ERR(forget_req)) {
279 fuse_put_request(fc, req);
280 goto out;
281 }
282
283 attr_version = fuse_get_attr_version(fc);
284
285 fuse_lookup_init(fc, req, nodeid, name, outarg);
Tejun Heob93f8582008-11-26 12:03:55 +0100286 fuse_request_send(fc, req);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700287 err = req->out.h.error;
288 fuse_put_request(fc, req);
289 /* Zero nodeid is same as -ENOENT, but with valid timeout */
290 if (err || !outarg->nodeid)
291 goto out_put_forget;
292
293 err = -EIO;
294 if (!outarg->nodeid)
295 goto out_put_forget;
296 if (!fuse_valid_type(outarg->attr.mode))
297 goto out_put_forget;
298
299 *inode = fuse_iget(sb, outarg->nodeid, outarg->generation,
300 &outarg->attr, entry_attr_timeout(outarg),
301 attr_version);
302 err = -ENOMEM;
303 if (!*inode) {
304 fuse_send_forget(fc, forget_req, outarg->nodeid, 1);
305 goto out;
306 }
307 err = 0;
308
309 out_put_forget:
310 fuse_put_request(fc, forget_req);
311 out:
312 return err;
313}
314
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800315static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
316 struct nameidata *nd)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700317{
318 int err;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700319 struct fuse_entry_out outarg;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700320 struct inode *inode;
Miklos Szeredi0de62562008-07-25 01:48:59 -0700321 struct dentry *newent;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700322 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700323 bool outarg_valid = true;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700324
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700325 err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name,
326 &outarg, &inode);
327 if (err == -ENOENT) {
328 outarg_valid = false;
329 err = 0;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800330 }
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700331 if (err)
332 goto out_err;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800333
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700334 err = -EIO;
335 if (inode && get_node_id(inode) == FUSE_ROOT_ID)
336 goto out_iput;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700337
Miklos Szeredid2a85162006-10-17 00:10:11 -0700338 if (inode && S_ISDIR(inode->i_mode)) {
339 mutex_lock(&fc->inst_mutex);
Miklos Szeredi0de62562008-07-25 01:48:59 -0700340 newent = fuse_d_add_directory(entry, inode);
Miklos Szeredid2a85162006-10-17 00:10:11 -0700341 mutex_unlock(&fc->inst_mutex);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700342 err = PTR_ERR(newent);
343 if (IS_ERR(newent))
344 goto out_iput;
345 } else {
Miklos Szeredi0de62562008-07-25 01:48:59 -0700346 newent = d_splice_alias(inode, entry);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700347 }
Miklos Szeredid2a85162006-10-17 00:10:11 -0700348
Miklos Szeredi0de62562008-07-25 01:48:59 -0700349 entry = newent ? newent : entry;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700350 entry->d_op = &fuse_dentry_operations;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700351 if (outarg_valid)
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700352 fuse_change_entry_timeout(entry, &outarg);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800353 else
354 fuse_invalidate_entry_cache(entry);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700355
Miklos Szeredi0de62562008-07-25 01:48:59 -0700356 return newent;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700357
358 out_iput:
359 iput(inode);
360 out_err:
361 return ERR_PTR(err);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700362}
363
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800364/*
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700365 * Synchronous release for the case when something goes wrong in CREATE_OPEN
366 */
367static void fuse_sync_release(struct fuse_conn *fc, struct fuse_file *ff,
Miklos Szeredic7b71432009-04-28 16:56:37 +0200368 int flags)
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700369{
Miklos Szeredic7b71432009-04-28 16:56:37 +0200370 fuse_release_fill(ff, flags, FUSE_RELEASE);
Miklos Szeredic756e0a2007-10-16 23:31:00 -0700371 ff->reserved_req->force = 1;
Tejun Heob93f8582008-11-26 12:03:55 +0100372 fuse_request_send(fc, ff->reserved_req);
Miklos Szeredic756e0a2007-10-16 23:31:00 -0700373 fuse_put_request(fc, ff->reserved_req);
374 kfree(ff);
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700375}
376
377/*
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800378 * Atomic create+open operation
379 *
380 * If the filesystem doesn't support this, then fall back to separate
381 * 'mknod' + 'open' requests.
382 */
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800383static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
384 struct nameidata *nd)
385{
386 int err;
387 struct inode *inode;
388 struct fuse_conn *fc = get_fuse_conn(dir);
389 struct fuse_req *req;
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700390 struct fuse_req *forget_req;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800391 struct fuse_open_in inarg;
392 struct fuse_open_out outopen;
393 struct fuse_entry_out outentry;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800394 struct fuse_file *ff;
395 struct file *file;
396 int flags = nd->intent.open.flags - 1;
397
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800398 if (fc->no_create)
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700399 return -ENOSYS;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800400
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700401 forget_req = fuse_get_req(fc);
402 if (IS_ERR(forget_req))
403 return PTR_ERR(forget_req);
404
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700405 req = fuse_get_req(fc);
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700406 err = PTR_ERR(req);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700407 if (IS_ERR(req))
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700408 goto out_put_forget_req;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800409
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700410 err = -ENOMEM;
Tejun Heoacf99432008-11-26 12:03:55 +0100411 ff = fuse_file_alloc(fc);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800412 if (!ff)
413 goto out_put_request;
414
415 flags &= ~O_NOCTTY;
416 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700417 memset(&outentry, 0, sizeof(outentry));
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800418 inarg.flags = flags;
419 inarg.mode = mode;
420 req->in.h.opcode = FUSE_CREATE;
421 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800422 req->in.numargs = 2;
423 req->in.args[0].size = sizeof(inarg);
424 req->in.args[0].value = &inarg;
425 req->in.args[1].size = entry->d_name.len + 1;
426 req->in.args[1].value = entry->d_name.name;
427 req->out.numargs = 2;
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700428 if (fc->minor < 9)
429 req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
430 else
431 req->out.args[0].size = sizeof(outentry);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800432 req->out.args[0].value = &outentry;
433 req->out.args[1].size = sizeof(outopen);
434 req->out.args[1].value = &outopen;
Tejun Heob93f8582008-11-26 12:03:55 +0100435 fuse_request_send(fc, req);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800436 err = req->out.h.error;
437 if (err) {
438 if (err == -ENOSYS)
439 fc->no_create = 1;
440 goto out_free_ff;
441 }
442
443 err = -EIO;
Miklos Szeredi2827d0b22005-11-28 13:44:16 -0800444 if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid))
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800445 goto out_free_ff;
446
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700447 fuse_put_request(fc, req);
Miklos Szeredic7b71432009-04-28 16:56:37 +0200448 ff->fh = outopen.fh;
449 ff->nodeid = outentry.nodeid;
450 ff->open_flags = outopen.open_flags;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800451 inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700452 &outentry.attr, entry_attr_timeout(&outentry), 0);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800453 if (!inode) {
454 flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
Miklos Szeredic7b71432009-04-28 16:56:37 +0200455 fuse_sync_release(fc, ff, flags);
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700456 fuse_send_forget(fc, forget_req, outentry.nodeid, 1);
457 return -ENOMEM;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800458 }
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700459 fuse_put_request(fc, forget_req);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800460 d_instantiate(entry, inode);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700461 fuse_change_entry_timeout(entry, &outentry);
Miklos Szeredi0952b2a2008-02-06 01:38:38 -0800462 fuse_invalidate_attr(dir);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800463 file = lookup_instantiate_filp(nd, entry, generic_file_open);
464 if (IS_ERR(file)) {
Miklos Szeredic7b71432009-04-28 16:56:37 +0200465 fuse_sync_release(fc, ff, flags);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800466 return PTR_ERR(file);
467 }
Miklos Szeredic7b71432009-04-28 16:56:37 +0200468 file->private_data = fuse_file_get(ff);
469 fuse_finish_open(inode, file);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800470 return 0;
471
472 out_free_ff:
473 fuse_file_free(ff);
474 out_put_request:
475 fuse_put_request(fc, req);
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700476 out_put_forget_req:
477 fuse_put_request(fc, forget_req);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800478 return err;
479}
480
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800481/*
482 * Code shared between mknod, mkdir, symlink and link
483 */
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700484static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
485 struct inode *dir, struct dentry *entry,
486 int mode)
487{
488 struct fuse_entry_out outarg;
489 struct inode *inode;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700490 int err;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800491 struct fuse_req *forget_req;
492
493 forget_req = fuse_get_req(fc);
494 if (IS_ERR(forget_req)) {
495 fuse_put_request(fc, req);
496 return PTR_ERR(forget_req);
497 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700498
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700499 memset(&outarg, 0, sizeof(outarg));
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700500 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700501 req->out.numargs = 1;
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700502 if (fc->minor < 9)
503 req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
504 else
505 req->out.args[0].size = sizeof(outarg);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700506 req->out.args[0].value = &outarg;
Tejun Heob93f8582008-11-26 12:03:55 +0100507 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700508 err = req->out.h.error;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800509 fuse_put_request(fc, req);
510 if (err)
511 goto out_put_forget_req;
512
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800513 err = -EIO;
514 if (invalid_nodeid(outarg.nodeid))
Miklos Szeredi2d510132006-11-25 11:09:20 -0800515 goto out_put_forget_req;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800516
517 if ((outarg.attr.mode ^ mode) & S_IFMT)
Miklos Szeredi2d510132006-11-25 11:09:20 -0800518 goto out_put_forget_req;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800519
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700520 inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700521 &outarg.attr, entry_attr_timeout(&outarg), 0);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700522 if (!inode) {
Miklos Szeredi2d510132006-11-25 11:09:20 -0800523 fuse_send_forget(fc, forget_req, outarg.nodeid, 1);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700524 return -ENOMEM;
525 }
Miklos Szeredi2d510132006-11-25 11:09:20 -0800526 fuse_put_request(fc, forget_req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700527
Miklos Szeredid2a85162006-10-17 00:10:11 -0700528 if (S_ISDIR(inode->i_mode)) {
529 struct dentry *alias;
530 mutex_lock(&fc->inst_mutex);
531 alias = d_find_alias(inode);
532 if (alias) {
533 /* New directory must have moved since mkdir */
534 mutex_unlock(&fc->inst_mutex);
535 dput(alias);
536 iput(inode);
537 return -EBUSY;
538 }
539 d_instantiate(entry, inode);
540 mutex_unlock(&fc->inst_mutex);
541 } else
542 d_instantiate(entry, inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700543
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700544 fuse_change_entry_timeout(entry, &outarg);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700545 fuse_invalidate_attr(dir);
546 return 0;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800547
Miklos Szeredi2d510132006-11-25 11:09:20 -0800548 out_put_forget_req:
549 fuse_put_request(fc, forget_req);
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800550 return err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700551}
552
553static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode,
554 dev_t rdev)
555{
556 struct fuse_mknod_in inarg;
557 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700558 struct fuse_req *req = fuse_get_req(fc);
559 if (IS_ERR(req))
560 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700561
562 memset(&inarg, 0, sizeof(inarg));
563 inarg.mode = mode;
564 inarg.rdev = new_encode_dev(rdev);
565 req->in.h.opcode = FUSE_MKNOD;
566 req->in.numargs = 2;
567 req->in.args[0].size = sizeof(inarg);
568 req->in.args[0].value = &inarg;
569 req->in.args[1].size = entry->d_name.len + 1;
570 req->in.args[1].value = entry->d_name.name;
571 return create_new_entry(fc, req, dir, entry, mode);
572}
573
574static int fuse_create(struct inode *dir, struct dentry *entry, int mode,
575 struct nameidata *nd)
576{
Miklos Szeredib9ba3472007-05-23 13:57:32 -0700577 if (nd && (nd->flags & LOOKUP_OPEN)) {
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800578 int err = fuse_create_open(dir, entry, mode, nd);
579 if (err != -ENOSYS)
580 return err;
581 /* Fall back on mknod */
582 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700583 return fuse_mknod(dir, entry, mode, 0);
584}
585
586static int fuse_mkdir(struct inode *dir, struct dentry *entry, int mode)
587{
588 struct fuse_mkdir_in inarg;
589 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700590 struct fuse_req *req = fuse_get_req(fc);
591 if (IS_ERR(req))
592 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700593
594 memset(&inarg, 0, sizeof(inarg));
595 inarg.mode = mode;
596 req->in.h.opcode = FUSE_MKDIR;
597 req->in.numargs = 2;
598 req->in.args[0].size = sizeof(inarg);
599 req->in.args[0].value = &inarg;
600 req->in.args[1].size = entry->d_name.len + 1;
601 req->in.args[1].value = entry->d_name.name;
602 return create_new_entry(fc, req, dir, entry, S_IFDIR);
603}
604
605static int fuse_symlink(struct inode *dir, struct dentry *entry,
606 const char *link)
607{
608 struct fuse_conn *fc = get_fuse_conn(dir);
609 unsigned len = strlen(link) + 1;
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700610 struct fuse_req *req = fuse_get_req(fc);
611 if (IS_ERR(req))
612 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700613
614 req->in.h.opcode = FUSE_SYMLINK;
615 req->in.numargs = 2;
616 req->in.args[0].size = entry->d_name.len + 1;
617 req->in.args[0].value = entry->d_name.name;
618 req->in.args[1].size = len;
619 req->in.args[1].value = link;
620 return create_new_entry(fc, req, dir, entry, S_IFLNK);
621}
622
623static int fuse_unlink(struct inode *dir, struct dentry *entry)
624{
625 int err;
626 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700627 struct fuse_req *req = fuse_get_req(fc);
628 if (IS_ERR(req))
629 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700630
631 req->in.h.opcode = FUSE_UNLINK;
632 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700633 req->in.numargs = 1;
634 req->in.args[0].size = entry->d_name.len + 1;
635 req->in.args[0].value = entry->d_name.name;
Tejun Heob93f8582008-11-26 12:03:55 +0100636 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700637 err = req->out.h.error;
638 fuse_put_request(fc, req);
639 if (!err) {
640 struct inode *inode = entry->d_inode;
641
Miklos Szeredi1729a162008-11-26 12:03:54 +0100642 /*
643 * Set nlink to zero so the inode can be cleared, if the inode
644 * does have more links this will be discovered at the next
645 * lookup/getattr.
646 */
Dave Hansence71ec32006-09-30 23:29:06 -0700647 clear_nlink(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700648 fuse_invalidate_attr(inode);
649 fuse_invalidate_attr(dir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800650 fuse_invalidate_entry_cache(entry);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700651 } else if (err == -EINTR)
652 fuse_invalidate_entry(entry);
653 return err;
654}
655
656static int fuse_rmdir(struct inode *dir, struct dentry *entry)
657{
658 int err;
659 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700660 struct fuse_req *req = fuse_get_req(fc);
661 if (IS_ERR(req))
662 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700663
664 req->in.h.opcode = FUSE_RMDIR;
665 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700666 req->in.numargs = 1;
667 req->in.args[0].size = entry->d_name.len + 1;
668 req->in.args[0].value = entry->d_name.name;
Tejun Heob93f8582008-11-26 12:03:55 +0100669 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700670 err = req->out.h.error;
671 fuse_put_request(fc, req);
672 if (!err) {
Dave Hansence71ec32006-09-30 23:29:06 -0700673 clear_nlink(entry->d_inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700674 fuse_invalidate_attr(dir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800675 fuse_invalidate_entry_cache(entry);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700676 } else if (err == -EINTR)
677 fuse_invalidate_entry(entry);
678 return err;
679}
680
681static int fuse_rename(struct inode *olddir, struct dentry *oldent,
682 struct inode *newdir, struct dentry *newent)
683{
684 int err;
685 struct fuse_rename_in inarg;
686 struct fuse_conn *fc = get_fuse_conn(olddir);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700687 struct fuse_req *req = fuse_get_req(fc);
688 if (IS_ERR(req))
689 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700690
691 memset(&inarg, 0, sizeof(inarg));
692 inarg.newdir = get_node_id(newdir);
693 req->in.h.opcode = FUSE_RENAME;
694 req->in.h.nodeid = get_node_id(olddir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700695 req->in.numargs = 3;
696 req->in.args[0].size = sizeof(inarg);
697 req->in.args[0].value = &inarg;
698 req->in.args[1].size = oldent->d_name.len + 1;
699 req->in.args[1].value = oldent->d_name.name;
700 req->in.args[2].size = newent->d_name.len + 1;
701 req->in.args[2].value = newent->d_name.name;
Tejun Heob93f8582008-11-26 12:03:55 +0100702 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700703 err = req->out.h.error;
704 fuse_put_request(fc, req);
705 if (!err) {
Miklos Szeredi08b63302007-11-28 16:22:03 -0800706 /* ctime changes */
707 fuse_invalidate_attr(oldent->d_inode);
708
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700709 fuse_invalidate_attr(olddir);
710 if (olddir != newdir)
711 fuse_invalidate_attr(newdir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800712
713 /* newent will end up negative */
714 if (newent->d_inode)
715 fuse_invalidate_entry_cache(newent);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700716 } else if (err == -EINTR) {
717 /* If request was interrupted, DEITY only knows if the
718 rename actually took place. If the invalidation
719 fails (e.g. some process has CWD under the renamed
720 directory), then there can be inconsistency between
721 the dcache and the real filesystem. Tough luck. */
722 fuse_invalidate_entry(oldent);
723 if (newent->d_inode)
724 fuse_invalidate_entry(newent);
725 }
726
727 return err;
728}
729
730static int fuse_link(struct dentry *entry, struct inode *newdir,
731 struct dentry *newent)
732{
733 int err;
734 struct fuse_link_in inarg;
735 struct inode *inode = entry->d_inode;
736 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700737 struct fuse_req *req = fuse_get_req(fc);
738 if (IS_ERR(req))
739 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700740
741 memset(&inarg, 0, sizeof(inarg));
742 inarg.oldnodeid = get_node_id(inode);
743 req->in.h.opcode = FUSE_LINK;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700744 req->in.numargs = 2;
745 req->in.args[0].size = sizeof(inarg);
746 req->in.args[0].value = &inarg;
747 req->in.args[1].size = newent->d_name.len + 1;
748 req->in.args[1].value = newent->d_name.name;
749 err = create_new_entry(fc, req, newdir, newent, inode->i_mode);
750 /* Contrary to "normal" filesystems it can happen that link
751 makes two "logical" inodes point to the same "physical"
752 inode. We invalidate the attributes of the old one, so it
753 will reflect changes in the backing inode (link count,
754 etc.)
755 */
756 if (!err || err == -EINTR)
757 fuse_invalidate_attr(inode);
758 return err;
759}
760
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700761static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
762 struct kstat *stat)
763{
764 stat->dev = inode->i_sb->s_dev;
765 stat->ino = attr->ino;
766 stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
767 stat->nlink = attr->nlink;
768 stat->uid = attr->uid;
769 stat->gid = attr->gid;
770 stat->rdev = inode->i_rdev;
771 stat->atime.tv_sec = attr->atime;
772 stat->atime.tv_nsec = attr->atimensec;
773 stat->mtime.tv_sec = attr->mtime;
774 stat->mtime.tv_nsec = attr->mtimensec;
775 stat->ctime.tv_sec = attr->ctime;
776 stat->ctime.tv_nsec = attr->ctimensec;
777 stat->size = attr->size;
778 stat->blocks = attr->blocks;
779 stat->blksize = (1 << inode->i_blkbits);
780}
781
Miklos Szeredic79e3222007-10-18 03:06:59 -0700782static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
783 struct file *file)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700784{
785 int err;
Miklos Szeredic79e3222007-10-18 03:06:59 -0700786 struct fuse_getattr_in inarg;
787 struct fuse_attr_out outarg;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700788 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700789 struct fuse_req *req;
790 u64 attr_version;
791
792 req = fuse_get_req(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700793 if (IS_ERR(req))
794 return PTR_ERR(req);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700795
Miklos Szeredi7dca9fd2007-11-28 16:21:59 -0800796 attr_version = fuse_get_attr_version(fc);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700797
Miklos Szeredic79e3222007-10-18 03:06:59 -0700798 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700799 memset(&outarg, 0, sizeof(outarg));
Miklos Szeredic79e3222007-10-18 03:06:59 -0700800 /* Directories have separate file-handle space */
801 if (file && S_ISREG(inode->i_mode)) {
802 struct fuse_file *ff = file->private_data;
803
804 inarg.getattr_flags |= FUSE_GETATTR_FH;
805 inarg.fh = ff->fh;
806 }
Miklos Szeredie5e55582005-09-09 13:10:28 -0700807 req->in.h.opcode = FUSE_GETATTR;
808 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredic79e3222007-10-18 03:06:59 -0700809 req->in.numargs = 1;
810 req->in.args[0].size = sizeof(inarg);
811 req->in.args[0].value = &inarg;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700812 req->out.numargs = 1;
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700813 if (fc->minor < 9)
814 req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
815 else
816 req->out.args[0].size = sizeof(outarg);
Miklos Szeredic79e3222007-10-18 03:06:59 -0700817 req->out.args[0].value = &outarg;
Tejun Heob93f8582008-11-26 12:03:55 +0100818 fuse_request_send(fc, req);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700819 err = req->out.h.error;
820 fuse_put_request(fc, req);
821 if (!err) {
Miklos Szeredic79e3222007-10-18 03:06:59 -0700822 if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
Miklos Szeredie5e55582005-09-09 13:10:28 -0700823 make_bad_inode(inode);
824 err = -EIO;
825 } else {
Miklos Szeredic79e3222007-10-18 03:06:59 -0700826 fuse_change_attributes(inode, &outarg.attr,
827 attr_timeout(&outarg),
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700828 attr_version);
829 if (stat)
Miklos Szeredic79e3222007-10-18 03:06:59 -0700830 fuse_fillattr(inode, &outarg.attr, stat);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700831 }
832 }
833 return err;
834}
835
Miklos Szeredibcb4be82007-11-28 16:21:59 -0800836int fuse_update_attributes(struct inode *inode, struct kstat *stat,
837 struct file *file, bool *refreshed)
838{
839 struct fuse_inode *fi = get_fuse_inode(inode);
840 int err;
841 bool r;
842
843 if (fi->i_time < get_jiffies_64()) {
844 r = true;
845 err = fuse_do_getattr(inode, stat, file);
846 } else {
847 r = false;
848 err = 0;
849 if (stat) {
850 generic_fillattr(inode, stat);
851 stat->mode = fi->orig_i_mode;
852 }
853 }
854
855 if (refreshed != NULL)
856 *refreshed = r;
857
858 return err;
859}
860
Miklos Szeredi87729a52005-09-09 13:10:34 -0700861/*
862 * Calling into a user-controlled filesystem gives the filesystem
863 * daemon ptrace-like capabilities over the requester process. This
864 * means, that the filesystem daemon is able to record the exact
865 * filesystem operations performed, and can also control the behavior
866 * of the requester process in otherwise impossible ways. For example
867 * it can delay the operation for arbitrary length of time allowing
868 * DoS against the requester.
869 *
870 * For this reason only those processes can call into the filesystem,
871 * for which the owner of the mount has ptrace privilege. This
872 * excludes processes started by other users, suid or sgid processes.
873 */
Miklos Szeredie57ac682007-10-18 03:06:58 -0700874int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task)
Miklos Szeredi87729a52005-09-09 13:10:34 -0700875{
David Howellsc69e8d92008-11-14 10:39:19 +1100876 const struct cred *cred;
877 int ret;
878
Miklos Szeredi87729a52005-09-09 13:10:34 -0700879 if (fc->flags & FUSE_ALLOW_OTHER)
880 return 1;
881
David Howellsc69e8d92008-11-14 10:39:19 +1100882 rcu_read_lock();
883 ret = 0;
884 cred = __task_cred(task);
885 if (cred->euid == fc->user_id &&
886 cred->suid == fc->user_id &&
887 cred->uid == fc->user_id &&
888 cred->egid == fc->group_id &&
889 cred->sgid == fc->group_id &&
890 cred->gid == fc->group_id)
891 ret = 1;
892 rcu_read_unlock();
Miklos Szeredi87729a52005-09-09 13:10:34 -0700893
David Howellsc69e8d92008-11-14 10:39:19 +1100894 return ret;
Miklos Szeredi87729a52005-09-09 13:10:34 -0700895}
896
Miklos Szeredi31d40d72005-11-07 00:59:50 -0800897static int fuse_access(struct inode *inode, int mask)
898{
899 struct fuse_conn *fc = get_fuse_conn(inode);
900 struct fuse_req *req;
901 struct fuse_access_in inarg;
902 int err;
903
904 if (fc->no_access)
905 return 0;
906
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700907 req = fuse_get_req(fc);
908 if (IS_ERR(req))
909 return PTR_ERR(req);
Miklos Szeredi31d40d72005-11-07 00:59:50 -0800910
911 memset(&inarg, 0, sizeof(inarg));
Al Viroe6305c42008-07-15 21:03:57 -0400912 inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC);
Miklos Szeredi31d40d72005-11-07 00:59:50 -0800913 req->in.h.opcode = FUSE_ACCESS;
914 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi31d40d72005-11-07 00:59:50 -0800915 req->in.numargs = 1;
916 req->in.args[0].size = sizeof(inarg);
917 req->in.args[0].value = &inarg;
Tejun Heob93f8582008-11-26 12:03:55 +0100918 fuse_request_send(fc, req);
Miklos Szeredi31d40d72005-11-07 00:59:50 -0800919 err = req->out.h.error;
920 fuse_put_request(fc, req);
921 if (err == -ENOSYS) {
922 fc->no_access = 1;
923 err = 0;
924 }
925 return err;
926}
927
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800928/*
929 * Check permission. The two basic access models of FUSE are:
930 *
931 * 1) Local access checking ('default_permissions' mount option) based
932 * on file mode. This is the plain old disk filesystem permission
933 * modell.
934 *
935 * 2) "Remote" access checking, where server is responsible for
936 * checking permission in each inode operation. An exception to this
937 * is if ->permission() was invoked from sys_access() in which case an
938 * access request is sent. Execute permission is still checked
939 * locally based on file mode.
940 */
Al Viroe6305c42008-07-15 21:03:57 -0400941static int fuse_permission(struct inode *inode, int mask)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700942{
943 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi244f6382007-10-16 23:31:02 -0700944 bool refreshed = false;
945 int err = 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700946
Miklos Szeredi87729a52005-09-09 13:10:34 -0700947 if (!fuse_allow_task(fc, current))
Miklos Szeredie5e55582005-09-09 13:10:28 -0700948 return -EACCES;
Miklos Szeredi244f6382007-10-16 23:31:02 -0700949
950 /*
Miklos Szeredie8e96152007-10-16 23:31:06 -0700951 * If attributes are needed, refresh them before proceeding
Miklos Szeredi244f6382007-10-16 23:31:02 -0700952 */
Miklos Szeredie8e96152007-10-16 23:31:06 -0700953 if ((fc->flags & FUSE_DEFAULT_PERMISSIONS) ||
954 ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
Miklos Szeredibcb4be82007-11-28 16:21:59 -0800955 err = fuse_update_attributes(inode, NULL, NULL, &refreshed);
956 if (err)
957 return err;
Miklos Szeredi244f6382007-10-16 23:31:02 -0700958 }
959
960 if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
Miklos Szeredi1a823ac2008-02-23 15:23:27 -0800961 err = generic_permission(inode, mask, NULL);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -0700962
963 /* If permission is denied, try to refresh file
964 attributes. This is also needed, because the root
965 node will at first have no permissions */
Miklos Szeredi244f6382007-10-16 23:31:02 -0700966 if (err == -EACCES && !refreshed) {
Miklos Szeredic79e3222007-10-18 03:06:59 -0700967 err = fuse_do_getattr(inode, NULL, NULL);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -0700968 if (!err)
969 err = generic_permission(inode, mask, NULL);
970 }
971
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800972 /* Note: the opposite of the above test does not
973 exist. So if permissions are revoked this won't be
974 noticed immediately, only after the attribute
975 timeout has expired */
Al Viroa1103432008-07-17 09:19:08 -0400976 } else if (mask & MAY_ACCESS) {
Miklos Szeredie8e96152007-10-16 23:31:06 -0700977 err = fuse_access(inode, mask);
978 } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
979 if (!(inode->i_mode & S_IXUGO)) {
980 if (refreshed)
981 return -EACCES;
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -0700982
Miklos Szeredic79e3222007-10-18 03:06:59 -0700983 err = fuse_do_getattr(inode, NULL, NULL);
Miklos Szeredie8e96152007-10-16 23:31:06 -0700984 if (!err && !(inode->i_mode & S_IXUGO))
985 return -EACCES;
986 }
Miklos Szeredie5e55582005-09-09 13:10:28 -0700987 }
Miklos Szeredi244f6382007-10-16 23:31:02 -0700988 return err;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700989}
990
991static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
992 void *dstbuf, filldir_t filldir)
993{
994 while (nbytes >= FUSE_NAME_OFFSET) {
995 struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
996 size_t reclen = FUSE_DIRENT_SIZE(dirent);
997 int over;
998 if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
999 return -EIO;
1000 if (reclen > nbytes)
1001 break;
1002
1003 over = filldir(dstbuf, dirent->name, dirent->namelen,
1004 file->f_pos, dirent->ino, dirent->type);
1005 if (over)
1006 break;
1007
1008 buf += reclen;
1009 nbytes -= reclen;
1010 file->f_pos = dirent->off;
1011 }
1012
1013 return 0;
1014}
1015
Miklos Szeredie5e55582005-09-09 13:10:28 -07001016static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
1017{
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001018 int err;
1019 size_t nbytes;
1020 struct page *page;
Josef Sipek7706a9d2006-12-08 02:37:02 -08001021 struct inode *inode = file->f_path.dentry->d_inode;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001022 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi248d86e2006-01-06 00:19:39 -08001023 struct fuse_req *req;
1024
1025 if (is_bad_inode(inode))
1026 return -EIO;
1027
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001028 req = fuse_get_req(fc);
1029 if (IS_ERR(req))
1030 return PTR_ERR(req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001031
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001032 page = alloc_page(GFP_KERNEL);
1033 if (!page) {
1034 fuse_put_request(fc, req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001035 return -ENOMEM;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001036 }
Miklos Szeredif4975c62009-04-02 14:25:34 +02001037 req->out.argpages = 1;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001038 req->num_pages = 1;
1039 req->pages[0] = page;
Miklos Szeredi2106cb12009-04-28 16:56:37 +02001040 fuse_read_fill(req, file, file->f_pos, PAGE_SIZE, FUSE_READDIR);
Tejun Heob93f8582008-11-26 12:03:55 +01001041 fuse_request_send(fc, req);
Miklos Szeredi361b1eb52006-01-16 22:14:45 -08001042 nbytes = req->out.args[0].size;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001043 err = req->out.h.error;
1044 fuse_put_request(fc, req);
1045 if (!err)
1046 err = parse_dirfile(page_address(page), nbytes, file, dstbuf,
1047 filldir);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001048
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001049 __free_page(page);
Miklos Szeredib36c31b2005-09-09 13:10:38 -07001050 fuse_invalidate_attr(inode); /* atime changed */
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001051 return err;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001052}
1053
1054static char *read_link(struct dentry *dentry)
1055{
1056 struct inode *inode = dentry->d_inode;
1057 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001058 struct fuse_req *req = fuse_get_req(fc);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001059 char *link;
1060
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001061 if (IS_ERR(req))
David Howellse231c2e2008-02-07 00:15:26 -08001062 return ERR_CAST(req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001063
1064 link = (char *) __get_free_page(GFP_KERNEL);
1065 if (!link) {
1066 link = ERR_PTR(-ENOMEM);
1067 goto out;
1068 }
1069 req->in.h.opcode = FUSE_READLINK;
1070 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001071 req->out.argvar = 1;
1072 req->out.numargs = 1;
1073 req->out.args[0].size = PAGE_SIZE - 1;
1074 req->out.args[0].value = link;
Tejun Heob93f8582008-11-26 12:03:55 +01001075 fuse_request_send(fc, req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001076 if (req->out.h.error) {
1077 free_page((unsigned long) link);
1078 link = ERR_PTR(req->out.h.error);
1079 } else
1080 link[req->out.args[0].size] = '\0';
1081 out:
1082 fuse_put_request(fc, req);
Miklos Szeredib36c31b2005-09-09 13:10:38 -07001083 fuse_invalidate_attr(inode); /* atime changed */
Miklos Szeredie5e55582005-09-09 13:10:28 -07001084 return link;
1085}
1086
1087static void free_link(char *link)
1088{
1089 if (!IS_ERR(link))
1090 free_page((unsigned long) link);
1091}
1092
1093static void *fuse_follow_link(struct dentry *dentry, struct nameidata *nd)
1094{
1095 nd_set_link(nd, read_link(dentry));
1096 return NULL;
1097}
1098
1099static void fuse_put_link(struct dentry *dentry, struct nameidata *nd, void *c)
1100{
1101 free_link(nd_get_link(nd));
1102}
1103
1104static int fuse_dir_open(struct inode *inode, struct file *file)
1105{
Miklos Szeredi91fe96b2009-04-28 16:56:37 +02001106 return fuse_open_common(inode, file, true);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001107}
1108
1109static int fuse_dir_release(struct inode *inode, struct file *file)
1110{
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001111 return fuse_release_common(inode, file, 1);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001112}
1113
Miklos Szeredi82547982005-09-09 13:10:38 -07001114static int fuse_dir_fsync(struct file *file, struct dentry *de, int datasync)
1115{
1116 /* nfsd can call this with no file */
1117 return file ? fuse_fsync_common(file, de, datasync, 1) : 0;
1118}
1119
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001120static bool update_mtime(unsigned ivalid)
1121{
1122 /* Always update if mtime is explicitly set */
1123 if (ivalid & ATTR_MTIME_SET)
1124 return true;
1125
1126 /* If it's an open(O_TRUNC) or an ftruncate(), don't update */
1127 if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
1128 return false;
1129
1130 /* In all other cases update */
1131 return true;
1132}
1133
Miklos Szeredibefc6492005-11-07 00:59:52 -08001134static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001135{
1136 unsigned ivalid = iattr->ia_valid;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001137
1138 if (ivalid & ATTR_MODE)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001139 arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001140 if (ivalid & ATTR_UID)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001141 arg->valid |= FATTR_UID, arg->uid = iattr->ia_uid;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001142 if (ivalid & ATTR_GID)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001143 arg->valid |= FATTR_GID, arg->gid = iattr->ia_gid;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001144 if (ivalid & ATTR_SIZE)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001145 arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001146 if (ivalid & ATTR_ATIME) {
1147 arg->valid |= FATTR_ATIME;
Miklos Szeredibefc6492005-11-07 00:59:52 -08001148 arg->atime = iattr->ia_atime.tv_sec;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001149 arg->atimensec = iattr->ia_atime.tv_nsec;
1150 if (!(ivalid & ATTR_ATIME_SET))
1151 arg->valid |= FATTR_ATIME_NOW;
1152 }
1153 if ((ivalid & ATTR_MTIME) && update_mtime(ivalid)) {
1154 arg->valid |= FATTR_MTIME;
Miklos Szeredibefc6492005-11-07 00:59:52 -08001155 arg->mtime = iattr->ia_mtime.tv_sec;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001156 arg->mtimensec = iattr->ia_mtime.tv_nsec;
1157 if (!(ivalid & ATTR_MTIME_SET))
1158 arg->valid |= FATTR_MTIME_NOW;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001159 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001160}
1161
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001162/*
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001163 * Prevent concurrent writepages on inode
1164 *
1165 * This is done by adding a negative bias to the inode write counter
1166 * and waiting for all pending writes to finish.
1167 */
1168void fuse_set_nowrite(struct inode *inode)
1169{
1170 struct fuse_conn *fc = get_fuse_conn(inode);
1171 struct fuse_inode *fi = get_fuse_inode(inode);
1172
1173 BUG_ON(!mutex_is_locked(&inode->i_mutex));
1174
1175 spin_lock(&fc->lock);
1176 BUG_ON(fi->writectr < 0);
1177 fi->writectr += FUSE_NOWRITE;
1178 spin_unlock(&fc->lock);
1179 wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE);
1180}
1181
1182/*
1183 * Allow writepages on inode
1184 *
1185 * Remove the bias from the writecounter and send any queued
1186 * writepages.
1187 */
1188static void __fuse_release_nowrite(struct inode *inode)
1189{
1190 struct fuse_inode *fi = get_fuse_inode(inode);
1191
1192 BUG_ON(fi->writectr != FUSE_NOWRITE);
1193 fi->writectr = 0;
1194 fuse_flush_writepages(inode);
1195}
1196
1197void fuse_release_nowrite(struct inode *inode)
1198{
1199 struct fuse_conn *fc = get_fuse_conn(inode);
1200
1201 spin_lock(&fc->lock);
1202 __fuse_release_nowrite(inode);
1203 spin_unlock(&fc->lock);
1204}
1205
1206/*
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001207 * Set attributes, and at the same time refresh them.
1208 *
1209 * Truncation is slightly complicated, because the 'truncate' request
1210 * may fail, in which case we don't want to touch the mapping.
Miklos Szeredi9ffbb912006-10-17 00:10:06 -07001211 * vmtruncate() doesn't allow for this case, so do the rlimit checking
1212 * and the actual truncation by hand.
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001213 */
Miklos Szeredi49d49142007-10-18 03:07:00 -07001214static int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
1215 struct file *file)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001216{
1217 struct inode *inode = entry->d_inode;
1218 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001219 struct fuse_req *req;
1220 struct fuse_setattr_in inarg;
1221 struct fuse_attr_out outarg;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001222 bool is_truncate = false;
1223 loff_t oldsize;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001224 int err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001225
Miklos Szeredie57ac682007-10-18 03:06:58 -07001226 if (!fuse_allow_task(fc, current))
1227 return -EACCES;
1228
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001229 if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
1230 err = inode_change_ok(inode, attr);
1231 if (err)
1232 return err;
1233 }
1234
Miklos Szeredi6ff958e2007-10-18 03:07:02 -07001235 if ((attr->ia_valid & ATTR_OPEN) && fc->atomic_o_trunc)
1236 return 0;
1237
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001238 if (attr->ia_valid & ATTR_SIZE) {
1239 unsigned long limit;
Miklos Szeredib2d22722006-12-06 20:35:51 -08001240 if (IS_SWAPFILE(inode))
1241 return -ETXTBSY;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001242 limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
1243 if (limit != RLIM_INFINITY && attr->ia_size > (loff_t) limit) {
1244 send_sig(SIGXFSZ, current, 0);
1245 return -EFBIG;
1246 }
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001247 is_truncate = true;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001248 }
1249
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001250 req = fuse_get_req(fc);
1251 if (IS_ERR(req))
1252 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001253
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001254 if (is_truncate)
1255 fuse_set_nowrite(inode);
1256
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001257 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -07001258 memset(&outarg, 0, sizeof(outarg));
Miklos Szeredibefc6492005-11-07 00:59:52 -08001259 iattr_to_fattr(attr, &inarg);
Miklos Szeredi49d49142007-10-18 03:07:00 -07001260 if (file) {
1261 struct fuse_file *ff = file->private_data;
1262 inarg.valid |= FATTR_FH;
1263 inarg.fh = ff->fh;
1264 }
Miklos Szeredif3332112007-10-18 03:07:04 -07001265 if (attr->ia_valid & ATTR_SIZE) {
1266 /* For mandatory locking in truncate */
1267 inarg.valid |= FATTR_LOCKOWNER;
1268 inarg.lock_owner = fuse_lock_owner_id(fc, current->files);
1269 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001270 req->in.h.opcode = FUSE_SETATTR;
1271 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001272 req->in.numargs = 1;
1273 req->in.args[0].size = sizeof(inarg);
1274 req->in.args[0].value = &inarg;
1275 req->out.numargs = 1;
Miklos Szeredi0e9663e2007-10-18 03:07:05 -07001276 if (fc->minor < 9)
1277 req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
1278 else
1279 req->out.args[0].size = sizeof(outarg);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001280 req->out.args[0].value = &outarg;
Tejun Heob93f8582008-11-26 12:03:55 +01001281 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001282 err = req->out.h.error;
1283 fuse_put_request(fc, req);
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001284 if (err) {
1285 if (err == -EINTR)
1286 fuse_invalidate_attr(inode);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001287 goto error;
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001288 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001289
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001290 if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
1291 make_bad_inode(inode);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001292 err = -EIO;
1293 goto error;
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001294 }
1295
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001296 spin_lock(&fc->lock);
1297 fuse_change_attributes_common(inode, &outarg.attr,
1298 attr_timeout(&outarg));
1299 oldsize = inode->i_size;
1300 i_size_write(inode, outarg.attr.size);
1301
1302 if (is_truncate) {
1303 /* NOTE: this may release/reacquire fc->lock */
1304 __fuse_release_nowrite(inode);
1305 }
1306 spin_unlock(&fc->lock);
1307
1308 /*
1309 * Only call invalidate_inode_pages2() after removing
1310 * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock.
1311 */
1312 if (S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
1313 if (outarg.attr.size < oldsize)
1314 fuse_truncate(inode->i_mapping, outarg.attr.size);
1315 invalidate_inode_pages2(inode->i_mapping);
1316 }
1317
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001318 return 0;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001319
1320error:
1321 if (is_truncate)
1322 fuse_release_nowrite(inode);
1323
1324 return err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001325}
1326
Miklos Szeredi49d49142007-10-18 03:07:00 -07001327static int fuse_setattr(struct dentry *entry, struct iattr *attr)
1328{
1329 if (attr->ia_valid & ATTR_FILE)
1330 return fuse_do_setattr(entry, attr, attr->ia_file);
1331 else
1332 return fuse_do_setattr(entry, attr, NULL);
1333}
1334
Miklos Szeredie5e55582005-09-09 13:10:28 -07001335static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
1336 struct kstat *stat)
1337{
1338 struct inode *inode = entry->d_inode;
Miklos Szeredi244f6382007-10-16 23:31:02 -07001339 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi244f6382007-10-16 23:31:02 -07001340
1341 if (!fuse_allow_task(fc, current))
1342 return -EACCES;
1343
Miklos Szeredibcb4be82007-11-28 16:21:59 -08001344 return fuse_update_attributes(inode, stat, NULL, NULL);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001345}
1346
Miklos Szeredi92a87802005-09-09 13:10:31 -07001347static int fuse_setxattr(struct dentry *entry, const char *name,
1348 const void *value, size_t size, int flags)
1349{
1350 struct inode *inode = entry->d_inode;
1351 struct fuse_conn *fc = get_fuse_conn(inode);
1352 struct fuse_req *req;
1353 struct fuse_setxattr_in inarg;
1354 int err;
1355
Miklos Szeredi92a87802005-09-09 13:10:31 -07001356 if (fc->no_setxattr)
1357 return -EOPNOTSUPP;
1358
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001359 req = fuse_get_req(fc);
1360 if (IS_ERR(req))
1361 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001362
1363 memset(&inarg, 0, sizeof(inarg));
1364 inarg.size = size;
1365 inarg.flags = flags;
1366 req->in.h.opcode = FUSE_SETXATTR;
1367 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001368 req->in.numargs = 3;
1369 req->in.args[0].size = sizeof(inarg);
1370 req->in.args[0].value = &inarg;
1371 req->in.args[1].size = strlen(name) + 1;
1372 req->in.args[1].value = name;
1373 req->in.args[2].size = size;
1374 req->in.args[2].value = value;
Tejun Heob93f8582008-11-26 12:03:55 +01001375 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001376 err = req->out.h.error;
1377 fuse_put_request(fc, req);
1378 if (err == -ENOSYS) {
1379 fc->no_setxattr = 1;
1380 err = -EOPNOTSUPP;
1381 }
1382 return err;
1383}
1384
1385static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
1386 void *value, size_t size)
1387{
1388 struct inode *inode = entry->d_inode;
1389 struct fuse_conn *fc = get_fuse_conn(inode);
1390 struct fuse_req *req;
1391 struct fuse_getxattr_in inarg;
1392 struct fuse_getxattr_out outarg;
1393 ssize_t ret;
1394
1395 if (fc->no_getxattr)
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 req->in.h.opcode = FUSE_GETXATTR;
1405 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001406 req->in.numargs = 2;
1407 req->in.args[0].size = sizeof(inarg);
1408 req->in.args[0].value = &inarg;
1409 req->in.args[1].size = strlen(name) + 1;
1410 req->in.args[1].value = name;
1411 /* This is really two different operations rolled into one */
1412 req->out.numargs = 1;
1413 if (size) {
1414 req->out.argvar = 1;
1415 req->out.args[0].size = size;
1416 req->out.args[0].value = value;
1417 } else {
1418 req->out.args[0].size = sizeof(outarg);
1419 req->out.args[0].value = &outarg;
1420 }
Tejun Heob93f8582008-11-26 12:03:55 +01001421 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001422 ret = req->out.h.error;
1423 if (!ret)
1424 ret = size ? req->out.args[0].size : outarg.size;
1425 else {
1426 if (ret == -ENOSYS) {
1427 fc->no_getxattr = 1;
1428 ret = -EOPNOTSUPP;
1429 }
1430 }
1431 fuse_put_request(fc, req);
1432 return ret;
1433}
1434
1435static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
1436{
1437 struct inode *inode = entry->d_inode;
1438 struct fuse_conn *fc = get_fuse_conn(inode);
1439 struct fuse_req *req;
1440 struct fuse_getxattr_in inarg;
1441 struct fuse_getxattr_out outarg;
1442 ssize_t ret;
1443
Miklos Szeredie57ac682007-10-18 03:06:58 -07001444 if (!fuse_allow_task(fc, current))
1445 return -EACCES;
1446
Miklos Szeredi92a87802005-09-09 13:10:31 -07001447 if (fc->no_listxattr)
1448 return -EOPNOTSUPP;
1449
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001450 req = fuse_get_req(fc);
1451 if (IS_ERR(req))
1452 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001453
1454 memset(&inarg, 0, sizeof(inarg));
1455 inarg.size = size;
1456 req->in.h.opcode = FUSE_LISTXATTR;
1457 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001458 req->in.numargs = 1;
1459 req->in.args[0].size = sizeof(inarg);
1460 req->in.args[0].value = &inarg;
1461 /* This is really two different operations rolled into one */
1462 req->out.numargs = 1;
1463 if (size) {
1464 req->out.argvar = 1;
1465 req->out.args[0].size = size;
1466 req->out.args[0].value = list;
1467 } else {
1468 req->out.args[0].size = sizeof(outarg);
1469 req->out.args[0].value = &outarg;
1470 }
Tejun Heob93f8582008-11-26 12:03:55 +01001471 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001472 ret = req->out.h.error;
1473 if (!ret)
1474 ret = size ? req->out.args[0].size : outarg.size;
1475 else {
1476 if (ret == -ENOSYS) {
1477 fc->no_listxattr = 1;
1478 ret = -EOPNOTSUPP;
1479 }
1480 }
1481 fuse_put_request(fc, req);
1482 return ret;
1483}
1484
1485static int fuse_removexattr(struct dentry *entry, const char *name)
1486{
1487 struct inode *inode = entry->d_inode;
1488 struct fuse_conn *fc = get_fuse_conn(inode);
1489 struct fuse_req *req;
1490 int err;
1491
1492 if (fc->no_removexattr)
1493 return -EOPNOTSUPP;
1494
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001495 req = fuse_get_req(fc);
1496 if (IS_ERR(req))
1497 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001498
1499 req->in.h.opcode = FUSE_REMOVEXATTR;
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 = strlen(name) + 1;
1503 req->in.args[0].value = name;
Tejun Heob93f8582008-11-26 12:03:55 +01001504 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001505 err = req->out.h.error;
1506 fuse_put_request(fc, req);
1507 if (err == -ENOSYS) {
1508 fc->no_removexattr = 1;
1509 err = -EOPNOTSUPP;
1510 }
1511 return err;
1512}
1513
Arjan van de Ven754661f2007-02-12 00:55:38 -08001514static const struct inode_operations fuse_dir_inode_operations = {
Miklos Szeredie5e55582005-09-09 13:10:28 -07001515 .lookup = fuse_lookup,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001516 .mkdir = fuse_mkdir,
1517 .symlink = fuse_symlink,
1518 .unlink = fuse_unlink,
1519 .rmdir = fuse_rmdir,
1520 .rename = fuse_rename,
1521 .link = fuse_link,
1522 .setattr = fuse_setattr,
1523 .create = fuse_create,
1524 .mknod = fuse_mknod,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001525 .permission = fuse_permission,
1526 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001527 .setxattr = fuse_setxattr,
1528 .getxattr = fuse_getxattr,
1529 .listxattr = fuse_listxattr,
1530 .removexattr = fuse_removexattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001531};
1532
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -08001533static const struct file_operations fuse_dir_operations = {
Miklos Szeredib6aeade2005-09-09 13:10:30 -07001534 .llseek = generic_file_llseek,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001535 .read = generic_read_dir,
1536 .readdir = fuse_readdir,
1537 .open = fuse_dir_open,
1538 .release = fuse_dir_release,
Miklos Szeredi82547982005-09-09 13:10:38 -07001539 .fsync = fuse_dir_fsync,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001540};
1541
Arjan van de Ven754661f2007-02-12 00:55:38 -08001542static const struct inode_operations fuse_common_inode_operations = {
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001543 .setattr = fuse_setattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001544 .permission = fuse_permission,
1545 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001546 .setxattr = fuse_setxattr,
1547 .getxattr = fuse_getxattr,
1548 .listxattr = fuse_listxattr,
1549 .removexattr = fuse_removexattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001550};
1551
Arjan van de Ven754661f2007-02-12 00:55:38 -08001552static const struct inode_operations fuse_symlink_inode_operations = {
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001553 .setattr = fuse_setattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001554 .follow_link = fuse_follow_link,
1555 .put_link = fuse_put_link,
1556 .readlink = generic_readlink,
1557 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001558 .setxattr = fuse_setxattr,
1559 .getxattr = fuse_getxattr,
1560 .listxattr = fuse_listxattr,
1561 .removexattr = fuse_removexattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001562};
1563
1564void fuse_init_common(struct inode *inode)
1565{
1566 inode->i_op = &fuse_common_inode_operations;
1567}
1568
1569void fuse_init_dir(struct inode *inode)
1570{
1571 inode->i_op = &fuse_dir_inode_operations;
1572 inode->i_fop = &fuse_dir_operations;
1573}
1574
1575void fuse_init_symlink(struct inode *inode)
1576{
1577 inode->i_op = &fuse_symlink_inode_operations;
1578}