blob: e42442f1da16a1d489cff8072d0486a4aefe9eef [file] [log] [blame]
Miklos Szeredie5e55582005-09-09 13:10:28 -07001/*
2 FUSE: Filesystem in Userspace
Miklos Szeredi1729a162008-11-26 12:03:54 +01003 Copyright (C) 2001-2008 Miklos Szeredi <miklos@szeredi.hu>
Miklos Szeredie5e55582005-09-09 13:10:28 -07004
5 This program can be distributed under the terms of the GNU GPL.
6 See the file COPYING.
7*/
8
9#include "fuse_i.h"
10
11#include <linux/pagemap.h>
12#include <linux/file.h>
Miklos Szeredie5e55582005-09-09 13:10:28 -070013#include <linux/sched.h>
14#include <linux/namei.h>
Miklos Szeredi07e77dc2010-12-07 20:16:56 +010015#include <linux/slab.h>
Miklos Szeredie5e55582005-09-09 13:10:28 -070016
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
Miklos Szeredie7c0a162011-03-21 13:58:06 +0100161 inode = ACCESS_ONCE(entry->d_inode);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800162 if (inode && is_bad_inode(inode))
Miklos Szeredie5e55582005-09-09 13:10:28 -0700163 return 0;
Miklos Szeredi0a0898c2006-07-30 03:04:10 -0700164 else if (fuse_dentry_time(entry) < get_jiffies_64()) {
Miklos Szeredie5e55582005-09-09 13:10:28 -0700165 int err;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700166 struct fuse_entry_out outarg;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800167 struct fuse_conn *fc;
168 struct fuse_req *req;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100169 struct fuse_forget_link *forget;
Miklos Szeredie956edd2006-10-17 00:10:12 -0700170 struct dentry *parent;
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700171 u64 attr_version;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800172
Miklos Szeredi50322fe2006-02-28 16:59:03 -0800173 /* For negative dentries, always do a fresh lookup */
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800174 if (!inode)
175 return 0;
176
Miklos Szeredid2433902011-05-10 17:35:58 +0200177 if (nd && (nd->flags & LOOKUP_RCU))
Miklos Szeredie7c0a162011-03-21 13:58:06 +0100178 return -ECHILD;
179
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800180 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 Szeredi07e77dc2010-12-07 20:16:56 +0100185 forget = fuse_alloc_forget();
186 if (!forget) {
Miklos Szeredi2d510132006-11-25 11:09:20 -0800187 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 Szeredi07e77dc2010-12-07 20:16:56 +0100206 fuse_queue_forget(fc, forget, outarg.nodeid, 1);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700207 return 0;
208 }
Miklos Szeredi8da5ff22006-10-17 00:10:08 -0700209 spin_lock(&fc->lock);
Miklos Szeredi1729a162008-11-26 12:03:54 +0100210 fi->nlookup++;
Miklos Szeredi8da5ff22006-10-17 00:10:08 -0700211 spin_unlock(&fc->lock);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700212 }
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100213 kfree(forget);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700214 if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700215 return 0;
216
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700217 fuse_change_attributes(inode, &outarg.attr,
218 entry_attr_timeout(&outarg),
219 attr_version);
220 fuse_change_entry_timeout(entry, &outarg);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700221 }
222 return 1;
223}
224
Miklos Szeredi8bfc0162006-01-16 22:14:28 -0800225static int invalid_nodeid(u64 nodeid)
Miklos Szeredi2827d0b22005-11-28 13:44:16 -0800226{
227 return !nodeid || nodeid == FUSE_ROOT_ID;
228}
229
Al Viro42695902009-02-20 05:59:13 +0000230const struct dentry_operations fuse_dentry_operations = {
Miklos Szeredie5e55582005-09-09 13:10:28 -0700231 .d_revalidate = fuse_dentry_revalidate,
232};
233
Timo Savolaa5bfffac2007-04-08 16:04:00 -0700234int fuse_valid_type(int m)
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800235{
236 return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) ||
237 S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m);
238}
239
Miklos Szeredid2a85162006-10-17 00:10:11 -0700240/*
241 * Add a directory inode to a dentry, ensuring that no other dentry
242 * refers to this inode. Called with fc->inst_mutex.
243 */
Miklos Szeredi0de62562008-07-25 01:48:59 -0700244static struct dentry *fuse_d_add_directory(struct dentry *entry,
245 struct inode *inode)
Miklos Szeredid2a85162006-10-17 00:10:11 -0700246{
247 struct dentry *alias = d_find_alias(inode);
Miklos Szeredi0de62562008-07-25 01:48:59 -0700248 if (alias && !(alias->d_flags & DCACHE_DISCONNECTED)) {
Miklos Szeredid2a85162006-10-17 00:10:11 -0700249 /* This tries to shrink the subtree below alias */
250 fuse_invalidate_entry(alias);
251 dput(alias);
Al Virob3d9b7a2012-06-09 13:51:19 -0400252 if (!hlist_empty(&inode->i_dentry))
Miklos Szeredi0de62562008-07-25 01:48:59 -0700253 return ERR_PTR(-EBUSY);
254 } else {
255 dput(alias);
Miklos Szeredid2a85162006-10-17 00:10:11 -0700256 }
Miklos Szeredi0de62562008-07-25 01:48:59 -0700257 return d_splice_alias(inode, entry);
Miklos Szeredid2a85162006-10-17 00:10:11 -0700258}
259
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700260int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name,
261 struct fuse_entry_out *outarg, struct inode **inode)
262{
263 struct fuse_conn *fc = get_fuse_conn_super(sb);
264 struct fuse_req *req;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100265 struct fuse_forget_link *forget;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700266 u64 attr_version;
267 int err;
268
269 *inode = NULL;
270 err = -ENAMETOOLONG;
271 if (name->len > FUSE_NAME_MAX)
272 goto out;
273
274 req = fuse_get_req(fc);
275 err = PTR_ERR(req);
276 if (IS_ERR(req))
277 goto out;
278
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100279 forget = fuse_alloc_forget();
280 err = -ENOMEM;
281 if (!forget) {
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700282 fuse_put_request(fc, req);
283 goto out;
284 }
285
286 attr_version = fuse_get_attr_version(fc);
287
288 fuse_lookup_init(fc, req, nodeid, name, outarg);
Tejun Heob93f8582008-11-26 12:03:55 +0100289 fuse_request_send(fc, req);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700290 err = req->out.h.error;
291 fuse_put_request(fc, req);
292 /* Zero nodeid is same as -ENOENT, but with valid timeout */
293 if (err || !outarg->nodeid)
294 goto out_put_forget;
295
296 err = -EIO;
297 if (!outarg->nodeid)
298 goto out_put_forget;
299 if (!fuse_valid_type(outarg->attr.mode))
300 goto out_put_forget;
301
302 *inode = fuse_iget(sb, outarg->nodeid, outarg->generation,
303 &outarg->attr, entry_attr_timeout(outarg),
304 attr_version);
305 err = -ENOMEM;
306 if (!*inode) {
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100307 fuse_queue_forget(fc, forget, outarg->nodeid, 1);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700308 goto out;
309 }
310 err = 0;
311
312 out_put_forget:
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100313 kfree(forget);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700314 out:
315 return err;
316}
317
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800318static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
319 struct nameidata *nd)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700320{
321 int err;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700322 struct fuse_entry_out outarg;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700323 struct inode *inode;
Miklos Szeredi0de62562008-07-25 01:48:59 -0700324 struct dentry *newent;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700325 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700326 bool outarg_valid = true;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700327
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700328 err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name,
329 &outarg, &inode);
330 if (err == -ENOENT) {
331 outarg_valid = false;
332 err = 0;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800333 }
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700334 if (err)
335 goto out_err;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800336
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700337 err = -EIO;
338 if (inode && get_node_id(inode) == FUSE_ROOT_ID)
339 goto out_iput;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700340
Miklos Szeredid2a85162006-10-17 00:10:11 -0700341 if (inode && S_ISDIR(inode->i_mode)) {
342 mutex_lock(&fc->inst_mutex);
Miklos Szeredi0de62562008-07-25 01:48:59 -0700343 newent = fuse_d_add_directory(entry, inode);
Miklos Szeredid2a85162006-10-17 00:10:11 -0700344 mutex_unlock(&fc->inst_mutex);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700345 err = PTR_ERR(newent);
346 if (IS_ERR(newent))
347 goto out_iput;
348 } else {
Miklos Szeredi0de62562008-07-25 01:48:59 -0700349 newent = d_splice_alias(inode, entry);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700350 }
Miklos Szeredid2a85162006-10-17 00:10:11 -0700351
Miklos Szeredi0de62562008-07-25 01:48:59 -0700352 entry = newent ? newent : entry;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700353 if (outarg_valid)
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700354 fuse_change_entry_timeout(entry, &outarg);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800355 else
356 fuse_invalidate_entry_cache(entry);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700357
Miklos Szeredi0de62562008-07-25 01:48:59 -0700358 return newent;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700359
360 out_iput:
361 iput(inode);
362 out_err:
363 return ERR_PTR(err);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700364}
365
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800366/*
367 * Atomic create+open operation
368 *
369 * If the filesystem doesn't support this, then fall back to separate
370 * 'mknod' + 'open' requests.
371 */
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200372static struct file *fuse_create_open(struct inode *dir, struct dentry *entry,
373 struct opendata *od, unsigned flags,
374 umode_t mode)
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800375{
376 int err;
377 struct inode *inode;
378 struct fuse_conn *fc = get_fuse_conn(dir);
379 struct fuse_req *req;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100380 struct fuse_forget_link *forget;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200381 struct fuse_create_in inarg;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800382 struct fuse_open_out outopen;
383 struct fuse_entry_out outentry;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800384 struct fuse_file *ff;
385 struct file *file;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800386
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100387 forget = fuse_alloc_forget();
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200388 err = -ENOMEM;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100389 if (!forget)
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200390 goto out_err;
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700391
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700392 req = fuse_get_req(fc);
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700393 err = PTR_ERR(req);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700394 if (IS_ERR(req))
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700395 goto out_put_forget_req;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800396
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700397 err = -ENOMEM;
Tejun Heoacf99432008-11-26 12:03:55 +0100398 ff = fuse_file_alloc(fc);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800399 if (!ff)
400 goto out_put_request;
401
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200402 if (!fc->dont_mask)
403 mode &= ~current_umask();
404
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800405 flags &= ~O_NOCTTY;
406 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700407 memset(&outentry, 0, sizeof(outentry));
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800408 inarg.flags = flags;
409 inarg.mode = mode;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200410 inarg.umask = current_umask();
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800411 req->in.h.opcode = FUSE_CREATE;
412 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800413 req->in.numargs = 2;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200414 req->in.args[0].size = fc->minor < 12 ? sizeof(struct fuse_open_in) :
415 sizeof(inarg);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800416 req->in.args[0].value = &inarg;
417 req->in.args[1].size = entry->d_name.len + 1;
418 req->in.args[1].value = entry->d_name.name;
419 req->out.numargs = 2;
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700420 if (fc->minor < 9)
421 req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
422 else
423 req->out.args[0].size = sizeof(outentry);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800424 req->out.args[0].value = &outentry;
425 req->out.args[1].size = sizeof(outopen);
426 req->out.args[1].value = &outopen;
Tejun Heob93f8582008-11-26 12:03:55 +0100427 fuse_request_send(fc, req);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800428 err = req->out.h.error;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200429 if (err)
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800430 goto out_free_ff;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800431
432 err = -EIO;
Miklos Szeredi2827d0b22005-11-28 13:44:16 -0800433 if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid))
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800434 goto out_free_ff;
435
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700436 fuse_put_request(fc, req);
Miklos Szeredic7b71432009-04-28 16:56:37 +0200437 ff->fh = outopen.fh;
438 ff->nodeid = outentry.nodeid;
439 ff->open_flags = outopen.open_flags;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800440 inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700441 &outentry.attr, entry_attr_timeout(&outentry), 0);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800442 if (!inode) {
443 flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
Miklos Szeredi8b0797a2009-04-28 16:56:39 +0200444 fuse_sync_release(ff, flags);
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100445 fuse_queue_forget(fc, forget, outentry.nodeid, 1);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200446 err = -ENOMEM;
447 goto out_err;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800448 }
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100449 kfree(forget);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800450 d_instantiate(entry, inode);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700451 fuse_change_entry_timeout(entry, &outentry);
Miklos Szeredi0952b2a2008-02-06 01:38:38 -0800452 fuse_invalidate_attr(dir);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200453 file = finish_open(od, entry, generic_file_open);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800454 if (IS_ERR(file)) {
Miklos Szeredi8b0797a2009-04-28 16:56:39 +0200455 fuse_sync_release(ff, flags);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200456 } else {
457 file->private_data = fuse_file_get(ff);
458 fuse_finish_open(inode, file);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800459 }
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200460 return file;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800461
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200462out_free_ff:
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800463 fuse_file_free(ff);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200464out_put_request:
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800465 fuse_put_request(fc, req);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200466out_put_forget_req:
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100467 kfree(forget);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200468out_err:
469 return ERR_PTR(err);
470}
471
472static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t);
473static struct file *fuse_atomic_open(struct inode *dir, struct dentry *entry,
474 struct opendata *od, unsigned flags,
475 umode_t mode, bool *created)
476{
477 int err;
478 struct fuse_conn *fc = get_fuse_conn(dir);
479 struct file *file;
480 struct dentry *res = NULL;
481
482 if (d_unhashed(entry)) {
483 res = fuse_lookup(dir, entry, NULL);
484 if (IS_ERR(res))
485 return ERR_CAST(res);
486
487 if (res)
488 entry = res;
489 }
490
491 if (!(flags & O_CREAT) || entry->d_inode)
492 goto no_open;
493
494 /* Only creates */
495 *created = true;
496
497 if (fc->no_create)
498 goto mknod;
499
500 file = fuse_create_open(dir, entry, od, flags, mode);
501 if (PTR_ERR(file) == -ENOSYS) {
502 fc->no_create = 1;
503 goto mknod;
504 }
505out_dput:
506 dput(res);
507 return file;
508
509mknod:
510 err = fuse_mknod(dir, entry, mode, 0);
511 if (err) {
512 file = ERR_PTR(err);
513 goto out_dput;
514 }
515no_open:
516 finish_no_open(od, res);
517 return NULL;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800518}
519
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800520/*
521 * Code shared between mknod, mkdir, symlink and link
522 */
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700523static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
524 struct inode *dir, struct dentry *entry,
Al Viro541af6a2011-07-26 03:17:33 -0400525 umode_t mode)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700526{
527 struct fuse_entry_out outarg;
528 struct inode *inode;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700529 int err;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100530 struct fuse_forget_link *forget;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800531
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100532 forget = fuse_alloc_forget();
533 if (!forget) {
Miklos Szeredi2d510132006-11-25 11:09:20 -0800534 fuse_put_request(fc, req);
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100535 return -ENOMEM;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800536 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700537
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700538 memset(&outarg, 0, sizeof(outarg));
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700539 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700540 req->out.numargs = 1;
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700541 if (fc->minor < 9)
542 req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
543 else
544 req->out.args[0].size = sizeof(outarg);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700545 req->out.args[0].value = &outarg;
Tejun Heob93f8582008-11-26 12:03:55 +0100546 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700547 err = req->out.h.error;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800548 fuse_put_request(fc, req);
549 if (err)
550 goto out_put_forget_req;
551
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800552 err = -EIO;
553 if (invalid_nodeid(outarg.nodeid))
Miklos Szeredi2d510132006-11-25 11:09:20 -0800554 goto out_put_forget_req;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800555
556 if ((outarg.attr.mode ^ mode) & S_IFMT)
Miklos Szeredi2d510132006-11-25 11:09:20 -0800557 goto out_put_forget_req;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800558
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700559 inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700560 &outarg.attr, entry_attr_timeout(&outarg), 0);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700561 if (!inode) {
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100562 fuse_queue_forget(fc, forget, outarg.nodeid, 1);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700563 return -ENOMEM;
564 }
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100565 kfree(forget);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700566
Miklos Szeredid2a85162006-10-17 00:10:11 -0700567 if (S_ISDIR(inode->i_mode)) {
568 struct dentry *alias;
569 mutex_lock(&fc->inst_mutex);
570 alias = d_find_alias(inode);
571 if (alias) {
572 /* New directory must have moved since mkdir */
573 mutex_unlock(&fc->inst_mutex);
574 dput(alias);
575 iput(inode);
576 return -EBUSY;
577 }
578 d_instantiate(entry, inode);
579 mutex_unlock(&fc->inst_mutex);
580 } else
581 d_instantiate(entry, inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700582
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700583 fuse_change_entry_timeout(entry, &outarg);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700584 fuse_invalidate_attr(dir);
585 return 0;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800586
Miklos Szeredi2d510132006-11-25 11:09:20 -0800587 out_put_forget_req:
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100588 kfree(forget);
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800589 return err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700590}
591
Al Viro1a67aaf2011-07-26 01:52:52 -0400592static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700593 dev_t rdev)
594{
595 struct fuse_mknod_in inarg;
596 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700597 struct fuse_req *req = fuse_get_req(fc);
598 if (IS_ERR(req))
599 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700600
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200601 if (!fc->dont_mask)
602 mode &= ~current_umask();
603
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700604 memset(&inarg, 0, sizeof(inarg));
605 inarg.mode = mode;
606 inarg.rdev = new_encode_dev(rdev);
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200607 inarg.umask = current_umask();
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700608 req->in.h.opcode = FUSE_MKNOD;
609 req->in.numargs = 2;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200610 req->in.args[0].size = fc->minor < 12 ? FUSE_COMPAT_MKNOD_IN_SIZE :
611 sizeof(inarg);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700612 req->in.args[0].value = &inarg;
613 req->in.args[1].size = entry->d_name.len + 1;
614 req->in.args[1].value = entry->d_name.name;
615 return create_new_entry(fc, req, dir, entry, mode);
616}
617
Al Viro4acdaf22011-07-26 01:42:34 -0400618static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700619 struct nameidata *nd)
620{
621 return fuse_mknod(dir, entry, mode, 0);
622}
623
Al Viro18bb1db2011-07-26 01:41:39 -0400624static int fuse_mkdir(struct inode *dir, struct dentry *entry, umode_t mode)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700625{
626 struct fuse_mkdir_in inarg;
627 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700628 struct fuse_req *req = fuse_get_req(fc);
629 if (IS_ERR(req))
630 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700631
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200632 if (!fc->dont_mask)
633 mode &= ~current_umask();
634
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700635 memset(&inarg, 0, sizeof(inarg));
636 inarg.mode = mode;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200637 inarg.umask = current_umask();
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700638 req->in.h.opcode = FUSE_MKDIR;
639 req->in.numargs = 2;
640 req->in.args[0].size = sizeof(inarg);
641 req->in.args[0].value = &inarg;
642 req->in.args[1].size = entry->d_name.len + 1;
643 req->in.args[1].value = entry->d_name.name;
644 return create_new_entry(fc, req, dir, entry, S_IFDIR);
645}
646
647static int fuse_symlink(struct inode *dir, struct dentry *entry,
648 const char *link)
649{
650 struct fuse_conn *fc = get_fuse_conn(dir);
651 unsigned len = strlen(link) + 1;
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700652 struct fuse_req *req = fuse_get_req(fc);
653 if (IS_ERR(req))
654 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700655
656 req->in.h.opcode = FUSE_SYMLINK;
657 req->in.numargs = 2;
658 req->in.args[0].size = entry->d_name.len + 1;
659 req->in.args[0].value = entry->d_name.name;
660 req->in.args[1].size = len;
661 req->in.args[1].value = link;
662 return create_new_entry(fc, req, dir, entry, S_IFLNK);
663}
664
665static int fuse_unlink(struct inode *dir, struct dentry *entry)
666{
667 int err;
668 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700669 struct fuse_req *req = fuse_get_req(fc);
670 if (IS_ERR(req))
671 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700672
673 req->in.h.opcode = FUSE_UNLINK;
674 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700675 req->in.numargs = 1;
676 req->in.args[0].size = entry->d_name.len + 1;
677 req->in.args[0].value = entry->d_name.name;
Tejun Heob93f8582008-11-26 12:03:55 +0100678 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700679 err = req->out.h.error;
680 fuse_put_request(fc, req);
681 if (!err) {
682 struct inode *inode = entry->d_inode;
Miklos Szerediac45d612012-03-05 15:48:11 +0100683 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700684
Miklos Szerediac45d612012-03-05 15:48:11 +0100685 spin_lock(&fc->lock);
686 fi->attr_version = ++fc->attr_version;
687 drop_nlink(inode);
688 spin_unlock(&fc->lock);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700689 fuse_invalidate_attr(inode);
690 fuse_invalidate_attr(dir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800691 fuse_invalidate_entry_cache(entry);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700692 } else if (err == -EINTR)
693 fuse_invalidate_entry(entry);
694 return err;
695}
696
697static int fuse_rmdir(struct inode *dir, struct dentry *entry)
698{
699 int err;
700 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700701 struct fuse_req *req = fuse_get_req(fc);
702 if (IS_ERR(req))
703 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700704
705 req->in.h.opcode = FUSE_RMDIR;
706 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700707 req->in.numargs = 1;
708 req->in.args[0].size = entry->d_name.len + 1;
709 req->in.args[0].value = entry->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) {
Dave Hansence71ec32006-09-30 23:29:06 -0700714 clear_nlink(entry->d_inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700715 fuse_invalidate_attr(dir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800716 fuse_invalidate_entry_cache(entry);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700717 } else if (err == -EINTR)
718 fuse_invalidate_entry(entry);
719 return err;
720}
721
722static int fuse_rename(struct inode *olddir, struct dentry *oldent,
723 struct inode *newdir, struct dentry *newent)
724{
725 int err;
726 struct fuse_rename_in inarg;
727 struct fuse_conn *fc = get_fuse_conn(olddir);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700728 struct fuse_req *req = fuse_get_req(fc);
Sage Weile4eaac02011-05-24 13:06:07 -0700729
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700730 if (IS_ERR(req))
731 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700732
733 memset(&inarg, 0, sizeof(inarg));
734 inarg.newdir = get_node_id(newdir);
735 req->in.h.opcode = FUSE_RENAME;
736 req->in.h.nodeid = get_node_id(olddir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700737 req->in.numargs = 3;
738 req->in.args[0].size = sizeof(inarg);
739 req->in.args[0].value = &inarg;
740 req->in.args[1].size = oldent->d_name.len + 1;
741 req->in.args[1].value = oldent->d_name.name;
742 req->in.args[2].size = newent->d_name.len + 1;
743 req->in.args[2].value = newent->d_name.name;
Tejun Heob93f8582008-11-26 12:03:55 +0100744 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700745 err = req->out.h.error;
746 fuse_put_request(fc, req);
747 if (!err) {
Miklos Szeredi08b63302007-11-28 16:22:03 -0800748 /* ctime changes */
749 fuse_invalidate_attr(oldent->d_inode);
750
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700751 fuse_invalidate_attr(olddir);
752 if (olddir != newdir)
753 fuse_invalidate_attr(newdir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800754
755 /* newent will end up negative */
Miklos Szeredi5219f342009-11-04 10:24:52 +0100756 if (newent->d_inode) {
757 fuse_invalidate_attr(newent->d_inode);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800758 fuse_invalidate_entry_cache(newent);
Miklos Szeredi5219f342009-11-04 10:24:52 +0100759 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700760 } else if (err == -EINTR) {
761 /* If request was interrupted, DEITY only knows if the
762 rename actually took place. If the invalidation
763 fails (e.g. some process has CWD under the renamed
764 directory), then there can be inconsistency between
765 the dcache and the real filesystem. Tough luck. */
766 fuse_invalidate_entry(oldent);
767 if (newent->d_inode)
768 fuse_invalidate_entry(newent);
769 }
770
771 return err;
772}
773
774static int fuse_link(struct dentry *entry, struct inode *newdir,
775 struct dentry *newent)
776{
777 int err;
778 struct fuse_link_in inarg;
779 struct inode *inode = entry->d_inode;
780 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700781 struct fuse_req *req = fuse_get_req(fc);
782 if (IS_ERR(req))
783 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700784
785 memset(&inarg, 0, sizeof(inarg));
786 inarg.oldnodeid = get_node_id(inode);
787 req->in.h.opcode = FUSE_LINK;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700788 req->in.numargs = 2;
789 req->in.args[0].size = sizeof(inarg);
790 req->in.args[0].value = &inarg;
791 req->in.args[1].size = newent->d_name.len + 1;
792 req->in.args[1].value = newent->d_name.name;
793 err = create_new_entry(fc, req, newdir, newent, inode->i_mode);
794 /* Contrary to "normal" filesystems it can happen that link
795 makes two "logical" inodes point to the same "physical"
796 inode. We invalidate the attributes of the old one, so it
797 will reflect changes in the backing inode (link count,
798 etc.)
799 */
Miklos Szerediac45d612012-03-05 15:48:11 +0100800 if (!err) {
801 struct fuse_inode *fi = get_fuse_inode(inode);
802
803 spin_lock(&fc->lock);
804 fi->attr_version = ++fc->attr_version;
805 inc_nlink(inode);
806 spin_unlock(&fc->lock);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700807 fuse_invalidate_attr(inode);
Miklos Szerediac45d612012-03-05 15:48:11 +0100808 } else if (err == -EINTR) {
809 fuse_invalidate_attr(inode);
810 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700811 return err;
812}
813
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700814static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
815 struct kstat *stat)
816{
Miklos Szeredi203627b2012-05-10 19:49:38 +0400817 unsigned int blkbits;
818
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700819 stat->dev = inode->i_sb->s_dev;
820 stat->ino = attr->ino;
821 stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
822 stat->nlink = attr->nlink;
823 stat->uid = attr->uid;
824 stat->gid = attr->gid;
825 stat->rdev = inode->i_rdev;
826 stat->atime.tv_sec = attr->atime;
827 stat->atime.tv_nsec = attr->atimensec;
828 stat->mtime.tv_sec = attr->mtime;
829 stat->mtime.tv_nsec = attr->mtimensec;
830 stat->ctime.tv_sec = attr->ctime;
831 stat->ctime.tv_nsec = attr->ctimensec;
832 stat->size = attr->size;
833 stat->blocks = attr->blocks;
Miklos Szeredi203627b2012-05-10 19:49:38 +0400834
835 if (attr->blksize != 0)
836 blkbits = ilog2(attr->blksize);
837 else
838 blkbits = inode->i_sb->s_blocksize_bits;
839
840 stat->blksize = 1 << blkbits;
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700841}
842
Miklos Szeredic79e3222007-10-18 03:06:59 -0700843static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
844 struct file *file)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700845{
846 int err;
Miklos Szeredic79e3222007-10-18 03:06:59 -0700847 struct fuse_getattr_in inarg;
848 struct fuse_attr_out outarg;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700849 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700850 struct fuse_req *req;
851 u64 attr_version;
852
853 req = fuse_get_req(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700854 if (IS_ERR(req))
855 return PTR_ERR(req);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700856
Miklos Szeredi7dca9fd2007-11-28 16:21:59 -0800857 attr_version = fuse_get_attr_version(fc);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700858
Miklos Szeredic79e3222007-10-18 03:06:59 -0700859 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700860 memset(&outarg, 0, sizeof(outarg));
Miklos Szeredic79e3222007-10-18 03:06:59 -0700861 /* Directories have separate file-handle space */
862 if (file && S_ISREG(inode->i_mode)) {
863 struct fuse_file *ff = file->private_data;
864
865 inarg.getattr_flags |= FUSE_GETATTR_FH;
866 inarg.fh = ff->fh;
867 }
Miklos Szeredie5e55582005-09-09 13:10:28 -0700868 req->in.h.opcode = FUSE_GETATTR;
869 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredic79e3222007-10-18 03:06:59 -0700870 req->in.numargs = 1;
871 req->in.args[0].size = sizeof(inarg);
872 req->in.args[0].value = &inarg;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700873 req->out.numargs = 1;
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700874 if (fc->minor < 9)
875 req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
876 else
877 req->out.args[0].size = sizeof(outarg);
Miklos Szeredic79e3222007-10-18 03:06:59 -0700878 req->out.args[0].value = &outarg;
Tejun Heob93f8582008-11-26 12:03:55 +0100879 fuse_request_send(fc, req);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700880 err = req->out.h.error;
881 fuse_put_request(fc, req);
882 if (!err) {
Miklos Szeredic79e3222007-10-18 03:06:59 -0700883 if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
Miklos Szeredie5e55582005-09-09 13:10:28 -0700884 make_bad_inode(inode);
885 err = -EIO;
886 } else {
Miklos Szeredic79e3222007-10-18 03:06:59 -0700887 fuse_change_attributes(inode, &outarg.attr,
888 attr_timeout(&outarg),
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700889 attr_version);
890 if (stat)
Miklos Szeredic79e3222007-10-18 03:06:59 -0700891 fuse_fillattr(inode, &outarg.attr, stat);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700892 }
893 }
894 return err;
895}
896
Miklos Szeredibcb4be82007-11-28 16:21:59 -0800897int fuse_update_attributes(struct inode *inode, struct kstat *stat,
898 struct file *file, bool *refreshed)
899{
900 struct fuse_inode *fi = get_fuse_inode(inode);
901 int err;
902 bool r;
903
904 if (fi->i_time < get_jiffies_64()) {
905 r = true;
906 err = fuse_do_getattr(inode, stat, file);
907 } else {
908 r = false;
909 err = 0;
910 if (stat) {
911 generic_fillattr(inode, stat);
912 stat->mode = fi->orig_i_mode;
Pavel Shilovsky45c72cd2012-05-10 19:49:38 +0400913 stat->ino = fi->orig_ino;
Miklos Szeredibcb4be82007-11-28 16:21:59 -0800914 }
915 }
916
917 if (refreshed != NULL)
918 *refreshed = r;
919
920 return err;
921}
922
John Muir3b463ae2009-05-31 11:13:57 -0400923int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid,
John Muir451d0f52011-12-06 21:50:06 +0100924 u64 child_nodeid, struct qstr *name)
John Muir3b463ae2009-05-31 11:13:57 -0400925{
926 int err = -ENOTDIR;
927 struct inode *parent;
928 struct dentry *dir;
929 struct dentry *entry;
930
931 parent = ilookup5(sb, parent_nodeid, fuse_inode_eq, &parent_nodeid);
932 if (!parent)
933 return -ENOENT;
934
935 mutex_lock(&parent->i_mutex);
936 if (!S_ISDIR(parent->i_mode))
937 goto unlock;
938
939 err = -ENOENT;
940 dir = d_find_alias(parent);
941 if (!dir)
942 goto unlock;
943
944 entry = d_lookup(dir, name);
945 dput(dir);
946 if (!entry)
947 goto unlock;
948
949 fuse_invalidate_attr(parent);
950 fuse_invalidate_entry(entry);
John Muir451d0f52011-12-06 21:50:06 +0100951
952 if (child_nodeid != 0 && entry->d_inode) {
953 mutex_lock(&entry->d_inode->i_mutex);
954 if (get_node_id(entry->d_inode) != child_nodeid) {
955 err = -ENOENT;
956 goto badentry;
957 }
958 if (d_mountpoint(entry)) {
959 err = -EBUSY;
960 goto badentry;
961 }
962 if (S_ISDIR(entry->d_inode->i_mode)) {
963 shrink_dcache_parent(entry);
964 if (!simple_empty(entry)) {
965 err = -ENOTEMPTY;
966 goto badentry;
967 }
968 entry->d_inode->i_flags |= S_DEAD;
969 }
970 dont_mount(entry);
971 clear_nlink(entry->d_inode);
972 err = 0;
973 badentry:
974 mutex_unlock(&entry->d_inode->i_mutex);
975 if (!err)
976 d_delete(entry);
977 } else {
978 err = 0;
979 }
John Muir3b463ae2009-05-31 11:13:57 -0400980 dput(entry);
John Muir3b463ae2009-05-31 11:13:57 -0400981
982 unlock:
983 mutex_unlock(&parent->i_mutex);
984 iput(parent);
985 return err;
986}
987
Miklos Szeredi87729a52005-09-09 13:10:34 -0700988/*
989 * Calling into a user-controlled filesystem gives the filesystem
990 * daemon ptrace-like capabilities over the requester process. This
991 * means, that the filesystem daemon is able to record the exact
992 * filesystem operations performed, and can also control the behavior
993 * of the requester process in otherwise impossible ways. For example
994 * it can delay the operation for arbitrary length of time allowing
995 * DoS against the requester.
996 *
997 * For this reason only those processes can call into the filesystem,
998 * for which the owner of the mount has ptrace privilege. This
999 * excludes processes started by other users, suid or sgid processes.
1000 */
Miklos Szeredie57ac682007-10-18 03:06:58 -07001001int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task)
Miklos Szeredi87729a52005-09-09 13:10:34 -07001002{
David Howellsc69e8d92008-11-14 10:39:19 +11001003 const struct cred *cred;
1004 int ret;
1005
Miklos Szeredi87729a52005-09-09 13:10:34 -07001006 if (fc->flags & FUSE_ALLOW_OTHER)
1007 return 1;
1008
David Howellsc69e8d92008-11-14 10:39:19 +11001009 rcu_read_lock();
1010 ret = 0;
1011 cred = __task_cred(task);
1012 if (cred->euid == fc->user_id &&
1013 cred->suid == fc->user_id &&
1014 cred->uid == fc->user_id &&
1015 cred->egid == fc->group_id &&
1016 cred->sgid == fc->group_id &&
1017 cred->gid == fc->group_id)
1018 ret = 1;
1019 rcu_read_unlock();
Miklos Szeredi87729a52005-09-09 13:10:34 -07001020
David Howellsc69e8d92008-11-14 10:39:19 +11001021 return ret;
Miklos Szeredi87729a52005-09-09 13:10:34 -07001022}
1023
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001024static int fuse_access(struct inode *inode, int mask)
1025{
1026 struct fuse_conn *fc = get_fuse_conn(inode);
1027 struct fuse_req *req;
1028 struct fuse_access_in inarg;
1029 int err;
1030
1031 if (fc->no_access)
1032 return 0;
1033
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001034 req = fuse_get_req(fc);
1035 if (IS_ERR(req))
1036 return PTR_ERR(req);
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001037
1038 memset(&inarg, 0, sizeof(inarg));
Al Viroe6305c42008-07-15 21:03:57 -04001039 inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC);
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001040 req->in.h.opcode = FUSE_ACCESS;
1041 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001042 req->in.numargs = 1;
1043 req->in.args[0].size = sizeof(inarg);
1044 req->in.args[0].value = &inarg;
Tejun Heob93f8582008-11-26 12:03:55 +01001045 fuse_request_send(fc, req);
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001046 err = req->out.h.error;
1047 fuse_put_request(fc, req);
1048 if (err == -ENOSYS) {
1049 fc->no_access = 1;
1050 err = 0;
1051 }
1052 return err;
1053}
1054
Al Viro10556cb2011-06-20 19:28:19 -04001055static int fuse_perm_getattr(struct inode *inode, int mask)
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001056{
Al Viro10556cb2011-06-20 19:28:19 -04001057 if (mask & MAY_NOT_BLOCK)
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001058 return -ECHILD;
1059
1060 return fuse_do_getattr(inode, NULL, NULL);
1061}
1062
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001063/*
1064 * Check permission. The two basic access models of FUSE are:
1065 *
1066 * 1) Local access checking ('default_permissions' mount option) based
1067 * on file mode. This is the plain old disk filesystem permission
1068 * modell.
1069 *
1070 * 2) "Remote" access checking, where server is responsible for
1071 * checking permission in each inode operation. An exception to this
1072 * is if ->permission() was invoked from sys_access() in which case an
1073 * access request is sent. Execute permission is still checked
1074 * locally based on file mode.
1075 */
Al Viro10556cb2011-06-20 19:28:19 -04001076static int fuse_permission(struct inode *inode, int mask)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001077{
1078 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi244f6382007-10-16 23:31:02 -07001079 bool refreshed = false;
1080 int err = 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001081
Miklos Szeredi87729a52005-09-09 13:10:34 -07001082 if (!fuse_allow_task(fc, current))
Miklos Szeredie5e55582005-09-09 13:10:28 -07001083 return -EACCES;
Miklos Szeredi244f6382007-10-16 23:31:02 -07001084
1085 /*
Miklos Szeredie8e96152007-10-16 23:31:06 -07001086 * If attributes are needed, refresh them before proceeding
Miklos Szeredi244f6382007-10-16 23:31:02 -07001087 */
Miklos Szeredie8e96152007-10-16 23:31:06 -07001088 if ((fc->flags & FUSE_DEFAULT_PERMISSIONS) ||
1089 ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001090 struct fuse_inode *fi = get_fuse_inode(inode);
1091
1092 if (fi->i_time < get_jiffies_64()) {
1093 refreshed = true;
1094
Al Viro10556cb2011-06-20 19:28:19 -04001095 err = fuse_perm_getattr(inode, mask);
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001096 if (err)
1097 return err;
1098 }
Miklos Szeredi244f6382007-10-16 23:31:02 -07001099 }
1100
1101 if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
Al Viro2830ba72011-06-20 19:16:29 -04001102 err = generic_permission(inode, mask);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001103
1104 /* If permission is denied, try to refresh file
1105 attributes. This is also needed, because the root
1106 node will at first have no permissions */
Miklos Szeredi244f6382007-10-16 23:31:02 -07001107 if (err == -EACCES && !refreshed) {
Al Viro10556cb2011-06-20 19:28:19 -04001108 err = fuse_perm_getattr(inode, mask);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001109 if (!err)
Al Viro2830ba72011-06-20 19:16:29 -04001110 err = generic_permission(inode, mask);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001111 }
1112
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001113 /* Note: the opposite of the above test does not
1114 exist. So if permissions are revoked this won't be
1115 noticed immediately, only after the attribute
1116 timeout has expired */
Eric Paris9cfcac82010-07-23 11:43:51 -04001117 } else if (mask & (MAY_ACCESS | MAY_CHDIR)) {
Al Viro10556cb2011-06-20 19:28:19 -04001118 if (mask & MAY_NOT_BLOCK)
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001119 return -ECHILD;
1120
Miklos Szeredie8e96152007-10-16 23:31:06 -07001121 err = fuse_access(inode, mask);
1122 } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
1123 if (!(inode->i_mode & S_IXUGO)) {
1124 if (refreshed)
1125 return -EACCES;
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001126
Al Viro10556cb2011-06-20 19:28:19 -04001127 err = fuse_perm_getattr(inode, mask);
Miklos Szeredie8e96152007-10-16 23:31:06 -07001128 if (!err && !(inode->i_mode & S_IXUGO))
1129 return -EACCES;
1130 }
Miklos Szeredie5e55582005-09-09 13:10:28 -07001131 }
Miklos Szeredi244f6382007-10-16 23:31:02 -07001132 return err;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001133}
1134
1135static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
1136 void *dstbuf, filldir_t filldir)
1137{
1138 while (nbytes >= FUSE_NAME_OFFSET) {
1139 struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
1140 size_t reclen = FUSE_DIRENT_SIZE(dirent);
1141 int over;
1142 if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
1143 return -EIO;
1144 if (reclen > nbytes)
1145 break;
1146
1147 over = filldir(dstbuf, dirent->name, dirent->namelen,
1148 file->f_pos, dirent->ino, dirent->type);
1149 if (over)
1150 break;
1151
1152 buf += reclen;
1153 nbytes -= reclen;
1154 file->f_pos = dirent->off;
1155 }
1156
1157 return 0;
1158}
1159
Miklos Szeredie5e55582005-09-09 13:10:28 -07001160static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
1161{
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001162 int err;
1163 size_t nbytes;
1164 struct page *page;
Josef Sipek7706a9d2006-12-08 02:37:02 -08001165 struct inode *inode = file->f_path.dentry->d_inode;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001166 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi248d86e2006-01-06 00:19:39 -08001167 struct fuse_req *req;
1168
1169 if (is_bad_inode(inode))
1170 return -EIO;
1171
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001172 req = fuse_get_req(fc);
1173 if (IS_ERR(req))
1174 return PTR_ERR(req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001175
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001176 page = alloc_page(GFP_KERNEL);
1177 if (!page) {
1178 fuse_put_request(fc, req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001179 return -ENOMEM;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001180 }
Miklos Szeredif4975c62009-04-02 14:25:34 +02001181 req->out.argpages = 1;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001182 req->num_pages = 1;
1183 req->pages[0] = page;
Miklos Szeredi2106cb12009-04-28 16:56:37 +02001184 fuse_read_fill(req, file, file->f_pos, PAGE_SIZE, FUSE_READDIR);
Tejun Heob93f8582008-11-26 12:03:55 +01001185 fuse_request_send(fc, req);
Miklos Szeredi361b1eb52006-01-16 22:14:45 -08001186 nbytes = req->out.args[0].size;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001187 err = req->out.h.error;
1188 fuse_put_request(fc, req);
1189 if (!err)
1190 err = parse_dirfile(page_address(page), nbytes, file, dstbuf,
1191 filldir);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001192
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001193 __free_page(page);
Miklos Szeredib36c31b2005-09-09 13:10:38 -07001194 fuse_invalidate_attr(inode); /* atime changed */
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001195 return err;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001196}
1197
1198static char *read_link(struct dentry *dentry)
1199{
1200 struct inode *inode = dentry->d_inode;
1201 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001202 struct fuse_req *req = fuse_get_req(fc);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001203 char *link;
1204
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001205 if (IS_ERR(req))
David Howellse231c2e2008-02-07 00:15:26 -08001206 return ERR_CAST(req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001207
1208 link = (char *) __get_free_page(GFP_KERNEL);
1209 if (!link) {
1210 link = ERR_PTR(-ENOMEM);
1211 goto out;
1212 }
1213 req->in.h.opcode = FUSE_READLINK;
1214 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001215 req->out.argvar = 1;
1216 req->out.numargs = 1;
1217 req->out.args[0].size = PAGE_SIZE - 1;
1218 req->out.args[0].value = link;
Tejun Heob93f8582008-11-26 12:03:55 +01001219 fuse_request_send(fc, req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001220 if (req->out.h.error) {
1221 free_page((unsigned long) link);
1222 link = ERR_PTR(req->out.h.error);
1223 } else
1224 link[req->out.args[0].size] = '\0';
1225 out:
1226 fuse_put_request(fc, req);
Miklos Szeredib36c31b2005-09-09 13:10:38 -07001227 fuse_invalidate_attr(inode); /* atime changed */
Miklos Szeredie5e55582005-09-09 13:10:28 -07001228 return link;
1229}
1230
1231static void free_link(char *link)
1232{
1233 if (!IS_ERR(link))
1234 free_page((unsigned long) link);
1235}
1236
1237static void *fuse_follow_link(struct dentry *dentry, struct nameidata *nd)
1238{
1239 nd_set_link(nd, read_link(dentry));
1240 return NULL;
1241}
1242
1243static void fuse_put_link(struct dentry *dentry, struct nameidata *nd, void *c)
1244{
1245 free_link(nd_get_link(nd));
1246}
1247
1248static int fuse_dir_open(struct inode *inode, struct file *file)
1249{
Miklos Szeredi91fe96b2009-04-28 16:56:37 +02001250 return fuse_open_common(inode, file, true);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001251}
1252
1253static int fuse_dir_release(struct inode *inode, struct file *file)
1254{
Miklos Szeredi8b0797a2009-04-28 16:56:39 +02001255 fuse_release_common(file, FUSE_RELEASEDIR);
1256
1257 return 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001258}
1259
Josef Bacik02c24a82011-07-16 20:44:56 -04001260static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end,
1261 int datasync)
Miklos Szeredi82547982005-09-09 13:10:38 -07001262{
Josef Bacik02c24a82011-07-16 20:44:56 -04001263 return fuse_fsync_common(file, start, end, datasync, 1);
Miklos Szeredi82547982005-09-09 13:10:38 -07001264}
1265
Miklos Szeredib18da0c2011-12-13 11:58:49 +01001266static long fuse_dir_ioctl(struct file *file, unsigned int cmd,
1267 unsigned long arg)
1268{
1269 struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1270
1271 /* FUSE_IOCTL_DIR only supported for API version >= 7.18 */
1272 if (fc->minor < 18)
1273 return -ENOTTY;
1274
1275 return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR);
1276}
1277
1278static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd,
1279 unsigned long arg)
1280{
1281 struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1282
1283 if (fc->minor < 18)
1284 return -ENOTTY;
1285
1286 return fuse_ioctl_common(file, cmd, arg,
1287 FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR);
1288}
1289
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001290static bool update_mtime(unsigned ivalid)
1291{
1292 /* Always update if mtime is explicitly set */
1293 if (ivalid & ATTR_MTIME_SET)
1294 return true;
1295
1296 /* If it's an open(O_TRUNC) or an ftruncate(), don't update */
1297 if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
1298 return false;
1299
1300 /* In all other cases update */
1301 return true;
1302}
1303
Miklos Szeredibefc6492005-11-07 00:59:52 -08001304static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001305{
1306 unsigned ivalid = iattr->ia_valid;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001307
1308 if (ivalid & ATTR_MODE)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001309 arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001310 if (ivalid & ATTR_UID)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001311 arg->valid |= FATTR_UID, arg->uid = iattr->ia_uid;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001312 if (ivalid & ATTR_GID)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001313 arg->valid |= FATTR_GID, arg->gid = iattr->ia_gid;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001314 if (ivalid & ATTR_SIZE)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001315 arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001316 if (ivalid & ATTR_ATIME) {
1317 arg->valid |= FATTR_ATIME;
Miklos Szeredibefc6492005-11-07 00:59:52 -08001318 arg->atime = iattr->ia_atime.tv_sec;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001319 arg->atimensec = iattr->ia_atime.tv_nsec;
1320 if (!(ivalid & ATTR_ATIME_SET))
1321 arg->valid |= FATTR_ATIME_NOW;
1322 }
1323 if ((ivalid & ATTR_MTIME) && update_mtime(ivalid)) {
1324 arg->valid |= FATTR_MTIME;
Miklos Szeredibefc6492005-11-07 00:59:52 -08001325 arg->mtime = iattr->ia_mtime.tv_sec;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001326 arg->mtimensec = iattr->ia_mtime.tv_nsec;
1327 if (!(ivalid & ATTR_MTIME_SET))
1328 arg->valid |= FATTR_MTIME_NOW;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001329 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001330}
1331
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001332/*
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001333 * Prevent concurrent writepages on inode
1334 *
1335 * This is done by adding a negative bias to the inode write counter
1336 * and waiting for all pending writes to finish.
1337 */
1338void fuse_set_nowrite(struct inode *inode)
1339{
1340 struct fuse_conn *fc = get_fuse_conn(inode);
1341 struct fuse_inode *fi = get_fuse_inode(inode);
1342
1343 BUG_ON(!mutex_is_locked(&inode->i_mutex));
1344
1345 spin_lock(&fc->lock);
1346 BUG_ON(fi->writectr < 0);
1347 fi->writectr += FUSE_NOWRITE;
1348 spin_unlock(&fc->lock);
1349 wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE);
1350}
1351
1352/*
1353 * Allow writepages on inode
1354 *
1355 * Remove the bias from the writecounter and send any queued
1356 * writepages.
1357 */
1358static void __fuse_release_nowrite(struct inode *inode)
1359{
1360 struct fuse_inode *fi = get_fuse_inode(inode);
1361
1362 BUG_ON(fi->writectr != FUSE_NOWRITE);
1363 fi->writectr = 0;
1364 fuse_flush_writepages(inode);
1365}
1366
1367void fuse_release_nowrite(struct inode *inode)
1368{
1369 struct fuse_conn *fc = get_fuse_conn(inode);
1370
1371 spin_lock(&fc->lock);
1372 __fuse_release_nowrite(inode);
1373 spin_unlock(&fc->lock);
1374}
1375
1376/*
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001377 * Set attributes, and at the same time refresh them.
1378 *
1379 * Truncation is slightly complicated, because the 'truncate' request
1380 * may fail, in which case we don't want to touch the mapping.
Miklos Szeredi9ffbb912006-10-17 00:10:06 -07001381 * vmtruncate() doesn't allow for this case, so do the rlimit checking
1382 * and the actual truncation by hand.
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001383 */
Miklos Szeredi49d49142007-10-18 03:07:00 -07001384static int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
1385 struct file *file)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001386{
1387 struct inode *inode = entry->d_inode;
1388 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001389 struct fuse_req *req;
1390 struct fuse_setattr_in inarg;
1391 struct fuse_attr_out outarg;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001392 bool is_truncate = false;
1393 loff_t oldsize;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001394 int err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001395
Miklos Szeredie57ac682007-10-18 03:06:58 -07001396 if (!fuse_allow_task(fc, current))
1397 return -EACCES;
1398
Christoph Hellwigdb78b872010-06-04 11:30:03 +02001399 if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS))
1400 attr->ia_valid |= ATTR_FORCE;
1401
1402 err = inode_change_ok(inode, attr);
1403 if (err)
1404 return err;
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001405
Miklos Szeredi8d56add2011-02-25 14:44:58 +01001406 if (attr->ia_valid & ATTR_OPEN) {
1407 if (fc->atomic_o_trunc)
1408 return 0;
1409 file = NULL;
1410 }
Miklos Szeredi6ff958e2007-10-18 03:07:02 -07001411
Christoph Hellwig2c27c652010-06-04 11:30:04 +02001412 if (attr->ia_valid & ATTR_SIZE)
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001413 is_truncate = true;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001414
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001415 req = fuse_get_req(fc);
1416 if (IS_ERR(req))
1417 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001418
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001419 if (is_truncate)
1420 fuse_set_nowrite(inode);
1421
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001422 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -07001423 memset(&outarg, 0, sizeof(outarg));
Miklos Szeredibefc6492005-11-07 00:59:52 -08001424 iattr_to_fattr(attr, &inarg);
Miklos Szeredi49d49142007-10-18 03:07:00 -07001425 if (file) {
1426 struct fuse_file *ff = file->private_data;
1427 inarg.valid |= FATTR_FH;
1428 inarg.fh = ff->fh;
1429 }
Miklos Szeredif3332112007-10-18 03:07:04 -07001430 if (attr->ia_valid & ATTR_SIZE) {
1431 /* For mandatory locking in truncate */
1432 inarg.valid |= FATTR_LOCKOWNER;
1433 inarg.lock_owner = fuse_lock_owner_id(fc, current->files);
1434 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001435 req->in.h.opcode = FUSE_SETATTR;
1436 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001437 req->in.numargs = 1;
1438 req->in.args[0].size = sizeof(inarg);
1439 req->in.args[0].value = &inarg;
1440 req->out.numargs = 1;
Miklos Szeredi0e9663e2007-10-18 03:07:05 -07001441 if (fc->minor < 9)
1442 req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
1443 else
1444 req->out.args[0].size = sizeof(outarg);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001445 req->out.args[0].value = &outarg;
Tejun Heob93f8582008-11-26 12:03:55 +01001446 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001447 err = req->out.h.error;
1448 fuse_put_request(fc, req);
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001449 if (err) {
1450 if (err == -EINTR)
1451 fuse_invalidate_attr(inode);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001452 goto error;
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001453 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001454
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001455 if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
1456 make_bad_inode(inode);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001457 err = -EIO;
1458 goto error;
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001459 }
1460
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001461 spin_lock(&fc->lock);
1462 fuse_change_attributes_common(inode, &outarg.attr,
1463 attr_timeout(&outarg));
1464 oldsize = inode->i_size;
1465 i_size_write(inode, outarg.attr.size);
1466
1467 if (is_truncate) {
1468 /* NOTE: this may release/reacquire fc->lock */
1469 __fuse_release_nowrite(inode);
1470 }
1471 spin_unlock(&fc->lock);
1472
1473 /*
1474 * Only call invalidate_inode_pages2() after removing
1475 * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock.
1476 */
1477 if (S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
npiggin@suse.dec08d3b02009-08-21 02:35:06 +10001478 truncate_pagecache(inode, oldsize, outarg.attr.size);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001479 invalidate_inode_pages2(inode->i_mapping);
1480 }
1481
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001482 return 0;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001483
1484error:
1485 if (is_truncate)
1486 fuse_release_nowrite(inode);
1487
1488 return err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001489}
1490
Miklos Szeredi49d49142007-10-18 03:07:00 -07001491static int fuse_setattr(struct dentry *entry, struct iattr *attr)
1492{
1493 if (attr->ia_valid & ATTR_FILE)
1494 return fuse_do_setattr(entry, attr, attr->ia_file);
1495 else
1496 return fuse_do_setattr(entry, attr, NULL);
1497}
1498
Miklos Szeredie5e55582005-09-09 13:10:28 -07001499static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
1500 struct kstat *stat)
1501{
1502 struct inode *inode = entry->d_inode;
Miklos Szeredi244f6382007-10-16 23:31:02 -07001503 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi244f6382007-10-16 23:31:02 -07001504
1505 if (!fuse_allow_task(fc, current))
1506 return -EACCES;
1507
Miklos Szeredibcb4be82007-11-28 16:21:59 -08001508 return fuse_update_attributes(inode, stat, NULL, NULL);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001509}
1510
Miklos Szeredi92a87802005-09-09 13:10:31 -07001511static int fuse_setxattr(struct dentry *entry, const char *name,
1512 const void *value, size_t size, int flags)
1513{
1514 struct inode *inode = entry->d_inode;
1515 struct fuse_conn *fc = get_fuse_conn(inode);
1516 struct fuse_req *req;
1517 struct fuse_setxattr_in inarg;
1518 int err;
1519
Miklos Szeredi92a87802005-09-09 13:10:31 -07001520 if (fc->no_setxattr)
1521 return -EOPNOTSUPP;
1522
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001523 req = fuse_get_req(fc);
1524 if (IS_ERR(req))
1525 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001526
1527 memset(&inarg, 0, sizeof(inarg));
1528 inarg.size = size;
1529 inarg.flags = flags;
1530 req->in.h.opcode = FUSE_SETXATTR;
1531 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001532 req->in.numargs = 3;
1533 req->in.args[0].size = sizeof(inarg);
1534 req->in.args[0].value = &inarg;
1535 req->in.args[1].size = strlen(name) + 1;
1536 req->in.args[1].value = name;
1537 req->in.args[2].size = size;
1538 req->in.args[2].value = value;
Tejun Heob93f8582008-11-26 12:03:55 +01001539 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001540 err = req->out.h.error;
1541 fuse_put_request(fc, req);
1542 if (err == -ENOSYS) {
1543 fc->no_setxattr = 1;
1544 err = -EOPNOTSUPP;
1545 }
1546 return err;
1547}
1548
1549static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
1550 void *value, size_t size)
1551{
1552 struct inode *inode = entry->d_inode;
1553 struct fuse_conn *fc = get_fuse_conn(inode);
1554 struct fuse_req *req;
1555 struct fuse_getxattr_in inarg;
1556 struct fuse_getxattr_out outarg;
1557 ssize_t ret;
1558
1559 if (fc->no_getxattr)
1560 return -EOPNOTSUPP;
1561
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001562 req = fuse_get_req(fc);
1563 if (IS_ERR(req))
1564 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001565
1566 memset(&inarg, 0, sizeof(inarg));
1567 inarg.size = size;
1568 req->in.h.opcode = FUSE_GETXATTR;
1569 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001570 req->in.numargs = 2;
1571 req->in.args[0].size = sizeof(inarg);
1572 req->in.args[0].value = &inarg;
1573 req->in.args[1].size = strlen(name) + 1;
1574 req->in.args[1].value = name;
1575 /* This is really two different operations rolled into one */
1576 req->out.numargs = 1;
1577 if (size) {
1578 req->out.argvar = 1;
1579 req->out.args[0].size = size;
1580 req->out.args[0].value = value;
1581 } else {
1582 req->out.args[0].size = sizeof(outarg);
1583 req->out.args[0].value = &outarg;
1584 }
Tejun Heob93f8582008-11-26 12:03:55 +01001585 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001586 ret = req->out.h.error;
1587 if (!ret)
1588 ret = size ? req->out.args[0].size : outarg.size;
1589 else {
1590 if (ret == -ENOSYS) {
1591 fc->no_getxattr = 1;
1592 ret = -EOPNOTSUPP;
1593 }
1594 }
1595 fuse_put_request(fc, req);
1596 return ret;
1597}
1598
1599static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
1600{
1601 struct inode *inode = entry->d_inode;
1602 struct fuse_conn *fc = get_fuse_conn(inode);
1603 struct fuse_req *req;
1604 struct fuse_getxattr_in inarg;
1605 struct fuse_getxattr_out outarg;
1606 ssize_t ret;
1607
Miklos Szeredie57ac682007-10-18 03:06:58 -07001608 if (!fuse_allow_task(fc, current))
1609 return -EACCES;
1610
Miklos Szeredi92a87802005-09-09 13:10:31 -07001611 if (fc->no_listxattr)
1612 return -EOPNOTSUPP;
1613
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001614 req = fuse_get_req(fc);
1615 if (IS_ERR(req))
1616 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001617
1618 memset(&inarg, 0, sizeof(inarg));
1619 inarg.size = size;
1620 req->in.h.opcode = FUSE_LISTXATTR;
1621 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001622 req->in.numargs = 1;
1623 req->in.args[0].size = sizeof(inarg);
1624 req->in.args[0].value = &inarg;
1625 /* This is really two different operations rolled into one */
1626 req->out.numargs = 1;
1627 if (size) {
1628 req->out.argvar = 1;
1629 req->out.args[0].size = size;
1630 req->out.args[0].value = list;
1631 } else {
1632 req->out.args[0].size = sizeof(outarg);
1633 req->out.args[0].value = &outarg;
1634 }
Tejun Heob93f8582008-11-26 12:03:55 +01001635 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001636 ret = req->out.h.error;
1637 if (!ret)
1638 ret = size ? req->out.args[0].size : outarg.size;
1639 else {
1640 if (ret == -ENOSYS) {
1641 fc->no_listxattr = 1;
1642 ret = -EOPNOTSUPP;
1643 }
1644 }
1645 fuse_put_request(fc, req);
1646 return ret;
1647}
1648
1649static int fuse_removexattr(struct dentry *entry, const char *name)
1650{
1651 struct inode *inode = entry->d_inode;
1652 struct fuse_conn *fc = get_fuse_conn(inode);
1653 struct fuse_req *req;
1654 int err;
1655
1656 if (fc->no_removexattr)
1657 return -EOPNOTSUPP;
1658
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001659 req = fuse_get_req(fc);
1660 if (IS_ERR(req))
1661 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001662
1663 req->in.h.opcode = FUSE_REMOVEXATTR;
1664 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001665 req->in.numargs = 1;
1666 req->in.args[0].size = strlen(name) + 1;
1667 req->in.args[0].value = name;
Tejun Heob93f8582008-11-26 12:03:55 +01001668 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001669 err = req->out.h.error;
1670 fuse_put_request(fc, req);
1671 if (err == -ENOSYS) {
1672 fc->no_removexattr = 1;
1673 err = -EOPNOTSUPP;
1674 }
1675 return err;
1676}
1677
Arjan van de Ven754661f2007-02-12 00:55:38 -08001678static const struct inode_operations fuse_dir_inode_operations = {
Miklos Szeredie5e55582005-09-09 13:10:28 -07001679 .lookup = fuse_lookup,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001680 .mkdir = fuse_mkdir,
1681 .symlink = fuse_symlink,
1682 .unlink = fuse_unlink,
1683 .rmdir = fuse_rmdir,
1684 .rename = fuse_rename,
1685 .link = fuse_link,
1686 .setattr = fuse_setattr,
1687 .create = fuse_create,
Miklos Szeredic8ccbe02012-06-05 15:10:22 +02001688 .atomic_open = fuse_atomic_open,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001689 .mknod = fuse_mknod,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001690 .permission = fuse_permission,
1691 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001692 .setxattr = fuse_setxattr,
1693 .getxattr = fuse_getxattr,
1694 .listxattr = fuse_listxattr,
1695 .removexattr = fuse_removexattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001696};
1697
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -08001698static const struct file_operations fuse_dir_operations = {
Miklos Szeredib6aeade2005-09-09 13:10:30 -07001699 .llseek = generic_file_llseek,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001700 .read = generic_read_dir,
1701 .readdir = fuse_readdir,
1702 .open = fuse_dir_open,
1703 .release = fuse_dir_release,
Miklos Szeredi82547982005-09-09 13:10:38 -07001704 .fsync = fuse_dir_fsync,
Miklos Szeredib18da0c2011-12-13 11:58:49 +01001705 .unlocked_ioctl = fuse_dir_ioctl,
1706 .compat_ioctl = fuse_dir_compat_ioctl,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001707};
1708
Arjan van de Ven754661f2007-02-12 00:55:38 -08001709static const struct inode_operations fuse_common_inode_operations = {
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001710 .setattr = fuse_setattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001711 .permission = fuse_permission,
1712 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001713 .setxattr = fuse_setxattr,
1714 .getxattr = fuse_getxattr,
1715 .listxattr = fuse_listxattr,
1716 .removexattr = fuse_removexattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001717};
1718
Arjan van de Ven754661f2007-02-12 00:55:38 -08001719static const struct inode_operations fuse_symlink_inode_operations = {
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001720 .setattr = fuse_setattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001721 .follow_link = fuse_follow_link,
1722 .put_link = fuse_put_link,
1723 .readlink = generic_readlink,
1724 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001725 .setxattr = fuse_setxattr,
1726 .getxattr = fuse_getxattr,
1727 .listxattr = fuse_listxattr,
1728 .removexattr = fuse_removexattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001729};
1730
1731void fuse_init_common(struct inode *inode)
1732{
1733 inode->i_op = &fuse_common_inode_operations;
1734}
1735
1736void fuse_init_dir(struct inode *inode)
1737{
1738 inode->i_op = &fuse_dir_inode_operations;
1739 inode->i_fop = &fuse_dir_operations;
1740}
1741
1742void fuse_init_symlink(struct inode *inode)
1743{
1744 inode->i_op = &fuse_symlink_inode_operations;
1745}