blob: 42198359fa1b472557e44f325e9f55c305237e99 [file] [log] [blame]
Miklos Szeredie5e55582005-09-09 13:10:28 -07001/*
2 FUSE: Filesystem in Userspace
Miklos Szeredi1729a162008-11-26 12:03:54 +01003 Copyright (C) 2001-2008 Miklos Szeredi <miklos@szeredi.hu>
Miklos Szeredie5e55582005-09-09 13:10:28 -07004
5 This program can be distributed under the terms of the GNU GPL.
6 See the file COPYING.
7*/
8
9#include "fuse_i.h"
10
11#include <linux/pagemap.h>
12#include <linux/file.h>
Miklos Szeredie5e55582005-09-09 13:10:28 -070013#include <linux/sched.h>
14#include <linux/namei.h>
Miklos Szeredi07e77dc2010-12-07 20:16:56 +010015#include <linux/slab.h>
Miklos Szeredie5e55582005-09-09 13:10:28 -070016
Al Viro8d3af7f2013-05-18 03:03:58 -040017static bool fuse_use_readdirplus(struct inode *dir, struct dir_context *ctx)
Feng Shuo4582a4a2013-01-15 11:23:28 +080018{
19 struct fuse_conn *fc = get_fuse_conn(dir);
20 struct fuse_inode *fi = get_fuse_inode(dir);
21
22 if (!fc->do_readdirplus)
23 return false;
Eric Wong634734b2013-02-06 22:29:01 +000024 if (!fc->readdirplus_auto)
25 return true;
Feng Shuo4582a4a2013-01-15 11:23:28 +080026 if (test_and_clear_bit(FUSE_I_ADVISE_RDPLUS, &fi->state))
27 return true;
Al Viro8d3af7f2013-05-18 03:03:58 -040028 if (ctx->pos == 0)
Feng Shuo4582a4a2013-01-15 11:23:28 +080029 return true;
30 return false;
31}
32
33static void fuse_advise_use_readdirplus(struct inode *dir)
34{
35 struct fuse_inode *fi = get_fuse_inode(dir);
36
37 set_bit(FUSE_I_ADVISE_RDPLUS, &fi->state);
38}
39
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070040#if BITS_PER_LONG >= 64
41static inline void fuse_dentry_settime(struct dentry *entry, u64 time)
42{
43 entry->d_time = time;
44}
45
46static inline u64 fuse_dentry_time(struct dentry *entry)
47{
48 return entry->d_time;
49}
50#else
51/*
52 * On 32 bit archs store the high 32 bits of time in d_fsdata
53 */
54static void fuse_dentry_settime(struct dentry *entry, u64 time)
55{
56 entry->d_time = time;
57 entry->d_fsdata = (void *) (unsigned long) (time >> 32);
58}
59
60static u64 fuse_dentry_time(struct dentry *entry)
61{
62 return (u64) entry->d_time +
63 ((u64) (unsigned long) entry->d_fsdata << 32);
64}
65#endif
66
Miklos Szeredi6f9f1182006-01-06 00:19:39 -080067/*
68 * FUSE caches dentries and attributes with separate timeout. The
69 * time in jiffies until the dentry/attributes are valid is stored in
70 * dentry->d_time and fuse_inode->i_time respectively.
71 */
72
73/*
74 * Calculate the time in jiffies until a dentry/attributes are valid
75 */
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070076static u64 time_to_jiffies(unsigned long sec, unsigned long nsec)
Miklos Szeredie5e55582005-09-09 13:10:28 -070077{
Miklos Szeredi685d16d2006-07-30 03:04:08 -070078 if (sec || nsec) {
79 struct timespec ts = {sec, nsec};
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070080 return get_jiffies_64() + timespec_to_jiffies(&ts);
Miklos Szeredi685d16d2006-07-30 03:04:08 -070081 } else
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070082 return 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -070083}
84
Miklos Szeredi6f9f1182006-01-06 00:19:39 -080085/*
86 * Set dentry and possibly attribute timeouts from the lookup/mk*
87 * replies
88 */
Miklos Szeredi1fb69e72007-10-18 03:06:58 -070089static void fuse_change_entry_timeout(struct dentry *entry,
90 struct fuse_entry_out *o)
Miklos Szeredi0aa7c692006-01-06 00:19:34 -080091{
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070092 fuse_dentry_settime(entry,
93 time_to_jiffies(o->entry_valid, o->entry_valid_nsec));
Miklos Szeredi1fb69e72007-10-18 03:06:58 -070094}
95
96static u64 attr_timeout(struct fuse_attr_out *o)
97{
98 return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
99}
100
101static u64 entry_attr_timeout(struct fuse_entry_out *o)
102{
103 return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800104}
105
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800106/*
107 * Mark the attributes as stale, so that at the next call to
108 * ->getattr() they will be fetched from userspace
109 */
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800110void fuse_invalidate_attr(struct inode *inode)
111{
Miklos Szeredi0a0898c2006-07-30 03:04:10 -0700112 get_fuse_inode(inode)->i_time = 0;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800113}
114
Andrew Gallagher451418f2013-11-05 03:55:43 -0800115/**
116 * Mark the attributes as stale due to an atime change. Avoid the invalidate if
117 * atime is not used.
118 */
119void fuse_invalidate_atime(struct inode *inode)
120{
121 if (!IS_RDONLY(inode))
122 fuse_invalidate_attr(inode);
123}
124
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800125/*
126 * Just mark the entry as stale, so that a next attempt to look it up
127 * will result in a new lookup call to userspace
128 *
129 * This is called when a dentry is about to become negative and the
130 * timeout is unknown (unlink, rmdir, rename and in some cases
131 * lookup)
132 */
Miklos Szeredidbd561d2008-07-25 01:49:00 -0700133void fuse_invalidate_entry_cache(struct dentry *entry)
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800134{
Miklos Szeredi0a0898c2006-07-30 03:04:10 -0700135 fuse_dentry_settime(entry, 0);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800136}
137
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800138/*
139 * Same as fuse_invalidate_entry_cache(), but also try to remove the
140 * dentry from the hash
141 */
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800142static void fuse_invalidate_entry(struct dentry *entry)
143{
144 d_invalidate(entry);
145 fuse_invalidate_entry_cache(entry);
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800146}
147
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700148static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_req *req,
149 u64 nodeid, struct qstr *name,
Miklos Szeredie5e55582005-09-09 13:10:28 -0700150 struct fuse_entry_out *outarg)
151{
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700152 memset(outarg, 0, sizeof(struct fuse_entry_out));
Miklos Szeredie5e55582005-09-09 13:10:28 -0700153 req->in.h.opcode = FUSE_LOOKUP;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700154 req->in.h.nodeid = nodeid;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700155 req->in.numargs = 1;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700156 req->in.args[0].size = name->len + 1;
157 req->in.args[0].value = name->name;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700158 req->out.numargs = 1;
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700159 if (fc->minor < 9)
160 req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
161 else
162 req->out.args[0].size = sizeof(struct fuse_entry_out);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700163 req->out.args[0].value = outarg;
164}
165
Miklos Szeredi5c5c5e52008-04-30 00:54:43 -0700166u64 fuse_get_attr_version(struct fuse_conn *fc)
Miklos Szeredi7dca9fd2007-11-28 16:21:59 -0800167{
168 u64 curr_version;
169
170 /*
171 * The spin lock isn't actually needed on 64bit archs, but we
172 * don't yet care too much about such optimizations.
173 */
174 spin_lock(&fc->lock);
175 curr_version = fc->attr_version;
176 spin_unlock(&fc->lock);
177
178 return curr_version;
179}
180
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800181/*
182 * Check whether the dentry is still valid
183 *
184 * If the entry validity timeout has expired and the dentry is
185 * positive, try to redo the lookup. If the lookup results in a
186 * different inode, then let the VFS invalidate the dentry and redo
187 * the lookup once more. If the lookup results in the same inode,
188 * then refresh the attributes, timeouts and mark the dentry valid.
189 */
Al Viro0b728e12012-06-10 16:03:43 -0400190static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700191{
Nick Piggin34286d62011-01-07 17:49:57 +1100192 struct inode *inode;
Miklos Szeredi28420da2013-06-03 14:40:22 +0200193 struct dentry *parent;
194 struct fuse_conn *fc;
Miklos Szeredi6314efe2013-10-01 16:41:22 +0200195 struct fuse_inode *fi;
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200196 int ret;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800197
Miklos Szeredie7c0a162011-03-21 13:58:06 +0100198 inode = ACCESS_ONCE(entry->d_inode);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800199 if (inode && is_bad_inode(inode))
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200200 goto invalid;
Miklos Szeredi0a0898c2006-07-30 03:04:10 -0700201 else if (fuse_dentry_time(entry) < get_jiffies_64()) {
Miklos Szeredie5e55582005-09-09 13:10:28 -0700202 int err;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700203 struct fuse_entry_out outarg;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800204 struct fuse_req *req;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100205 struct fuse_forget_link *forget;
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700206 u64 attr_version;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800207
Miklos Szeredi50322fe2006-02-28 16:59:03 -0800208 /* For negative dentries, always do a fresh lookup */
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800209 if (!inode)
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200210 goto invalid;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800211
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200212 ret = -ECHILD;
Al Viro0b728e12012-06-10 16:03:43 -0400213 if (flags & LOOKUP_RCU)
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200214 goto out;
Miklos Szeredie7c0a162011-03-21 13:58:06 +0100215
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800216 fc = get_fuse_conn(inode);
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400217 req = fuse_get_req_nopages(fc);
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200218 ret = PTR_ERR(req);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700219 if (IS_ERR(req))
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200220 goto out;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700221
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100222 forget = fuse_alloc_forget();
223 if (!forget) {
Miklos Szeredi2d510132006-11-25 11:09:20 -0800224 fuse_put_request(fc, req);
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200225 ret = -ENOMEM;
226 goto out;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800227 }
228
Miklos Szeredi7dca9fd2007-11-28 16:21:59 -0800229 attr_version = fuse_get_attr_version(fc);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700230
Miklos Szeredie956edd2006-10-17 00:10:12 -0700231 parent = dget_parent(entry);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700232 fuse_lookup_init(fc, req, get_node_id(parent->d_inode),
233 &entry->d_name, &outarg);
Tejun Heob93f8582008-11-26 12:03:55 +0100234 fuse_request_send(fc, req);
Miklos Szeredie956edd2006-10-17 00:10:12 -0700235 dput(parent);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700236 err = req->out.h.error;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800237 fuse_put_request(fc, req);
Miklos Szeredi50322fe2006-02-28 16:59:03 -0800238 /* Zero nodeid is same as -ENOENT */
239 if (!err && !outarg.nodeid)
240 err = -ENOENT;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700241 if (!err) {
Miklos Szeredi6314efe2013-10-01 16:41:22 +0200242 fi = get_fuse_inode(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700243 if (outarg.nodeid != get_node_id(inode)) {
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100244 fuse_queue_forget(fc, forget, outarg.nodeid, 1);
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200245 goto invalid;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700246 }
Miklos Szeredi8da5ff22006-10-17 00:10:08 -0700247 spin_lock(&fc->lock);
Miklos Szeredi1729a162008-11-26 12:03:54 +0100248 fi->nlookup++;
Miklos Szeredi8da5ff22006-10-17 00:10:08 -0700249 spin_unlock(&fc->lock);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700250 }
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100251 kfree(forget);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700252 if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT)
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200253 goto invalid;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700254
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700255 fuse_change_attributes(inode, &outarg.attr,
256 entry_attr_timeout(&outarg),
257 attr_version);
258 fuse_change_entry_timeout(entry, &outarg);
Miklos Szeredi28420da2013-06-03 14:40:22 +0200259 } else if (inode) {
Miklos Szeredi6314efe2013-10-01 16:41:22 +0200260 fi = get_fuse_inode(inode);
261 if (flags & LOOKUP_RCU) {
262 if (test_bit(FUSE_I_INIT_RDPLUS, &fi->state))
263 return -ECHILD;
264 } else if (test_and_clear_bit(FUSE_I_INIT_RDPLUS, &fi->state)) {
Miklos Szeredi28420da2013-06-03 14:40:22 +0200265 parent = dget_parent(entry);
266 fuse_advise_use_readdirplus(parent->d_inode);
267 dput(parent);
268 }
Miklos Szeredie5e55582005-09-09 13:10:28 -0700269 }
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200270 ret = 1;
271out:
272 return ret;
273
274invalid:
275 ret = 0;
Miklos Szeredi3c70b8e2013-10-01 16:41:22 +0200276
277 if (!(flags & LOOKUP_RCU) && check_submounts_and_drop(entry) != 0)
Anand Avati46ea1562013-09-05 11:44:44 +0200278 ret = 1;
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200279 goto out;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700280}
281
Miklos Szeredi8bfc0162006-01-16 22:14:28 -0800282static int invalid_nodeid(u64 nodeid)
Miklos Szeredi2827d0b22005-11-28 13:44:16 -0800283{
284 return !nodeid || nodeid == FUSE_ROOT_ID;
285}
286
Al Viro42695902009-02-20 05:59:13 +0000287const struct dentry_operations fuse_dentry_operations = {
Miklos Szeredie5e55582005-09-09 13:10:28 -0700288 .d_revalidate = fuse_dentry_revalidate,
289};
290
Timo Savolaa5bfffac2007-04-08 16:04:00 -0700291int fuse_valid_type(int m)
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800292{
293 return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) ||
294 S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m);
295}
296
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700297int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name,
298 struct fuse_entry_out *outarg, struct inode **inode)
299{
300 struct fuse_conn *fc = get_fuse_conn_super(sb);
301 struct fuse_req *req;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100302 struct fuse_forget_link *forget;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700303 u64 attr_version;
304 int err;
305
306 *inode = NULL;
307 err = -ENAMETOOLONG;
308 if (name->len > FUSE_NAME_MAX)
309 goto out;
310
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400311 req = fuse_get_req_nopages(fc);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700312 err = PTR_ERR(req);
313 if (IS_ERR(req))
314 goto out;
315
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100316 forget = fuse_alloc_forget();
317 err = -ENOMEM;
318 if (!forget) {
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700319 fuse_put_request(fc, req);
320 goto out;
321 }
322
323 attr_version = fuse_get_attr_version(fc);
324
325 fuse_lookup_init(fc, req, nodeid, name, outarg);
Tejun Heob93f8582008-11-26 12:03:55 +0100326 fuse_request_send(fc, req);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700327 err = req->out.h.error;
328 fuse_put_request(fc, req);
329 /* Zero nodeid is same as -ENOENT, but with valid timeout */
330 if (err || !outarg->nodeid)
331 goto out_put_forget;
332
333 err = -EIO;
334 if (!outarg->nodeid)
335 goto out_put_forget;
336 if (!fuse_valid_type(outarg->attr.mode))
337 goto out_put_forget;
338
339 *inode = fuse_iget(sb, outarg->nodeid, outarg->generation,
340 &outarg->attr, entry_attr_timeout(outarg),
341 attr_version);
342 err = -ENOMEM;
343 if (!*inode) {
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100344 fuse_queue_forget(fc, forget, outarg->nodeid, 1);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700345 goto out;
346 }
347 err = 0;
348
349 out_put_forget:
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100350 kfree(forget);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700351 out:
352 return err;
353}
354
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800355static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
Al Viro00cd8dd2012-06-10 17:13:09 -0400356 unsigned int flags)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700357{
358 int err;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700359 struct fuse_entry_out outarg;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700360 struct inode *inode;
Miklos Szeredi0de62562008-07-25 01:48:59 -0700361 struct dentry *newent;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700362 bool outarg_valid = true;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700363
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700364 err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name,
365 &outarg, &inode);
366 if (err == -ENOENT) {
367 outarg_valid = false;
368 err = 0;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800369 }
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700370 if (err)
371 goto out_err;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800372
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700373 err = -EIO;
374 if (inode && get_node_id(inode) == FUSE_ROOT_ID)
375 goto out_iput;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700376
Miklos Szeredib70a80e2013-10-01 16:44:54 +0200377 newent = d_materialise_unique(entry, inode);
Miklos Szeredi5835f332013-09-05 11:44:42 +0200378 err = PTR_ERR(newent);
379 if (IS_ERR(newent))
380 goto out_err;
Miklos Szeredid2a85162006-10-17 00:10:11 -0700381
Miklos Szeredi0de62562008-07-25 01:48:59 -0700382 entry = newent ? newent : entry;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700383 if (outarg_valid)
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700384 fuse_change_entry_timeout(entry, &outarg);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800385 else
386 fuse_invalidate_entry_cache(entry);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700387
Feng Shuo4582a4a2013-01-15 11:23:28 +0800388 fuse_advise_use_readdirplus(dir);
Miklos Szeredi0de62562008-07-25 01:48:59 -0700389 return newent;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700390
391 out_iput:
392 iput(inode);
393 out_err:
394 return ERR_PTR(err);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700395}
396
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800397/*
398 * Atomic create+open operation
399 *
400 * If the filesystem doesn't support this, then fall back to separate
401 * 'mknod' + 'open' requests.
402 */
Al Virod9585272012-06-22 12:39:14 +0400403static int fuse_create_open(struct inode *dir, struct dentry *entry,
Al Viro30d90492012-06-22 12:40:19 +0400404 struct file *file, unsigned flags,
Al Virod9585272012-06-22 12:39:14 +0400405 umode_t mode, int *opened)
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800406{
407 int err;
408 struct inode *inode;
409 struct fuse_conn *fc = get_fuse_conn(dir);
410 struct fuse_req *req;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100411 struct fuse_forget_link *forget;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200412 struct fuse_create_in inarg;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800413 struct fuse_open_out outopen;
414 struct fuse_entry_out outentry;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800415 struct fuse_file *ff;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800416
Miklos Szerediaf109bc2012-08-15 13:01:24 +0200417 /* Userspace expects S_IFREG in create mode */
418 BUG_ON((mode & S_IFMT) != S_IFREG);
419
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100420 forget = fuse_alloc_forget();
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200421 err = -ENOMEM;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100422 if (!forget)
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200423 goto out_err;
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700424
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400425 req = fuse_get_req_nopages(fc);
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700426 err = PTR_ERR(req);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700427 if (IS_ERR(req))
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700428 goto out_put_forget_req;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800429
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700430 err = -ENOMEM;
Tejun Heoacf99432008-11-26 12:03:55 +0100431 ff = fuse_file_alloc(fc);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800432 if (!ff)
433 goto out_put_request;
434
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200435 if (!fc->dont_mask)
436 mode &= ~current_umask();
437
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800438 flags &= ~O_NOCTTY;
439 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700440 memset(&outentry, 0, sizeof(outentry));
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800441 inarg.flags = flags;
442 inarg.mode = mode;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200443 inarg.umask = current_umask();
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800444 req->in.h.opcode = FUSE_CREATE;
445 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800446 req->in.numargs = 2;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200447 req->in.args[0].size = fc->minor < 12 ? sizeof(struct fuse_open_in) :
448 sizeof(inarg);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800449 req->in.args[0].value = &inarg;
450 req->in.args[1].size = entry->d_name.len + 1;
451 req->in.args[1].value = entry->d_name.name;
452 req->out.numargs = 2;
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700453 if (fc->minor < 9)
454 req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
455 else
456 req->out.args[0].size = sizeof(outentry);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800457 req->out.args[0].value = &outentry;
458 req->out.args[1].size = sizeof(outopen);
459 req->out.args[1].value = &outopen;
Tejun Heob93f8582008-11-26 12:03:55 +0100460 fuse_request_send(fc, req);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800461 err = req->out.h.error;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200462 if (err)
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800463 goto out_free_ff;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800464
465 err = -EIO;
Miklos Szeredi2827d0b22005-11-28 13:44:16 -0800466 if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid))
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800467 goto out_free_ff;
468
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700469 fuse_put_request(fc, req);
Miklos Szeredic7b71432009-04-28 16:56:37 +0200470 ff->fh = outopen.fh;
471 ff->nodeid = outentry.nodeid;
472 ff->open_flags = outopen.open_flags;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800473 inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700474 &outentry.attr, entry_attr_timeout(&outentry), 0);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800475 if (!inode) {
476 flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
Miklos Szeredi8b0797a2009-04-28 16:56:39 +0200477 fuse_sync_release(ff, flags);
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100478 fuse_queue_forget(fc, forget, outentry.nodeid, 1);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200479 err = -ENOMEM;
480 goto out_err;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800481 }
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100482 kfree(forget);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800483 d_instantiate(entry, inode);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700484 fuse_change_entry_timeout(entry, &outentry);
Miklos Szeredi0952b2a2008-02-06 01:38:38 -0800485 fuse_invalidate_attr(dir);
Al Viro30d90492012-06-22 12:40:19 +0400486 err = finish_open(file, entry, generic_file_open, opened);
487 if (err) {
Miklos Szeredi8b0797a2009-04-28 16:56:39 +0200488 fuse_sync_release(ff, flags);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200489 } else {
490 file->private_data = fuse_file_get(ff);
491 fuse_finish_open(inode, file);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800492 }
Al Virod9585272012-06-22 12:39:14 +0400493 return err;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800494
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200495out_free_ff:
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800496 fuse_file_free(ff);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200497out_put_request:
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800498 fuse_put_request(fc, req);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200499out_put_forget_req:
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100500 kfree(forget);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200501out_err:
Al Virod9585272012-06-22 12:39:14 +0400502 return err;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200503}
504
505static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t);
Al Virod9585272012-06-22 12:39:14 +0400506static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
Al Viro30d90492012-06-22 12:40:19 +0400507 struct file *file, unsigned flags,
Al Virod9585272012-06-22 12:39:14 +0400508 umode_t mode, int *opened)
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200509{
510 int err;
511 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200512 struct dentry *res = NULL;
513
514 if (d_unhashed(entry)) {
Al Viro00cd8dd2012-06-10 17:13:09 -0400515 res = fuse_lookup(dir, entry, 0);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200516 if (IS_ERR(res))
Al Virod9585272012-06-22 12:39:14 +0400517 return PTR_ERR(res);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200518
519 if (res)
520 entry = res;
521 }
522
523 if (!(flags & O_CREAT) || entry->d_inode)
524 goto no_open;
525
526 /* Only creates */
Al Viro47237682012-06-10 05:01:45 -0400527 *opened |= FILE_CREATED;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200528
529 if (fc->no_create)
530 goto mknod;
531
Al Viro30d90492012-06-22 12:40:19 +0400532 err = fuse_create_open(dir, entry, file, flags, mode, opened);
Al Virod9585272012-06-22 12:39:14 +0400533 if (err == -ENOSYS) {
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200534 fc->no_create = 1;
535 goto mknod;
536 }
537out_dput:
538 dput(res);
Al Virod9585272012-06-22 12:39:14 +0400539 return err;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200540
541mknod:
542 err = fuse_mknod(dir, entry, mode, 0);
Al Virod9585272012-06-22 12:39:14 +0400543 if (err)
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200544 goto out_dput;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200545no_open:
Al Viroe45198a2012-06-10 06:48:09 -0400546 return finish_no_open(file, res);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800547}
548
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800549/*
550 * Code shared between mknod, mkdir, symlink and link
551 */
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700552static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
553 struct inode *dir, struct dentry *entry,
Al Viro541af6a2011-07-26 03:17:33 -0400554 umode_t mode)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700555{
556 struct fuse_entry_out outarg;
557 struct inode *inode;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700558 int err;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100559 struct fuse_forget_link *forget;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800560
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100561 forget = fuse_alloc_forget();
562 if (!forget) {
Miklos Szeredi2d510132006-11-25 11:09:20 -0800563 fuse_put_request(fc, req);
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100564 return -ENOMEM;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800565 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700566
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700567 memset(&outarg, 0, sizeof(outarg));
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700568 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700569 req->out.numargs = 1;
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700570 if (fc->minor < 9)
571 req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
572 else
573 req->out.args[0].size = sizeof(outarg);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700574 req->out.args[0].value = &outarg;
Tejun Heob93f8582008-11-26 12:03:55 +0100575 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700576 err = req->out.h.error;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800577 fuse_put_request(fc, req);
578 if (err)
579 goto out_put_forget_req;
580
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800581 err = -EIO;
582 if (invalid_nodeid(outarg.nodeid))
Miklos Szeredi2d510132006-11-25 11:09:20 -0800583 goto out_put_forget_req;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800584
585 if ((outarg.attr.mode ^ mode) & S_IFMT)
Miklos Szeredi2d510132006-11-25 11:09:20 -0800586 goto out_put_forget_req;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800587
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700588 inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700589 &outarg.attr, entry_attr_timeout(&outarg), 0);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700590 if (!inode) {
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100591 fuse_queue_forget(fc, forget, outarg.nodeid, 1);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700592 return -ENOMEM;
593 }
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100594 kfree(forget);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700595
Miklos Szeredib70a80e2013-10-01 16:44:54 +0200596 err = d_instantiate_no_diralias(entry, inode);
597 if (err)
598 return err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700599
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700600 fuse_change_entry_timeout(entry, &outarg);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700601 fuse_invalidate_attr(dir);
602 return 0;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800603
Miklos Szeredi2d510132006-11-25 11:09:20 -0800604 out_put_forget_req:
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100605 kfree(forget);
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800606 return err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700607}
608
Al Viro1a67aaf2011-07-26 01:52:52 -0400609static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700610 dev_t rdev)
611{
612 struct fuse_mknod_in inarg;
613 struct fuse_conn *fc = get_fuse_conn(dir);
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400614 struct fuse_req *req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700615 if (IS_ERR(req))
616 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700617
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200618 if (!fc->dont_mask)
619 mode &= ~current_umask();
620
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700621 memset(&inarg, 0, sizeof(inarg));
622 inarg.mode = mode;
623 inarg.rdev = new_encode_dev(rdev);
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200624 inarg.umask = current_umask();
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700625 req->in.h.opcode = FUSE_MKNOD;
626 req->in.numargs = 2;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200627 req->in.args[0].size = fc->minor < 12 ? FUSE_COMPAT_MKNOD_IN_SIZE :
628 sizeof(inarg);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700629 req->in.args[0].value = &inarg;
630 req->in.args[1].size = entry->d_name.len + 1;
631 req->in.args[1].value = entry->d_name.name;
632 return create_new_entry(fc, req, dir, entry, mode);
633}
634
Al Viro4acdaf22011-07-26 01:42:34 -0400635static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode,
Al Viroebfc3b42012-06-10 18:05:36 -0400636 bool excl)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700637{
638 return fuse_mknod(dir, entry, mode, 0);
639}
640
Al Viro18bb1db2011-07-26 01:41:39 -0400641static int fuse_mkdir(struct inode *dir, struct dentry *entry, umode_t mode)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700642{
643 struct fuse_mkdir_in inarg;
644 struct fuse_conn *fc = get_fuse_conn(dir);
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400645 struct fuse_req *req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700646 if (IS_ERR(req))
647 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700648
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200649 if (!fc->dont_mask)
650 mode &= ~current_umask();
651
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700652 memset(&inarg, 0, sizeof(inarg));
653 inarg.mode = mode;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200654 inarg.umask = current_umask();
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700655 req->in.h.opcode = FUSE_MKDIR;
656 req->in.numargs = 2;
657 req->in.args[0].size = sizeof(inarg);
658 req->in.args[0].value = &inarg;
659 req->in.args[1].size = entry->d_name.len + 1;
660 req->in.args[1].value = entry->d_name.name;
661 return create_new_entry(fc, req, dir, entry, S_IFDIR);
662}
663
664static int fuse_symlink(struct inode *dir, struct dentry *entry,
665 const char *link)
666{
667 struct fuse_conn *fc = get_fuse_conn(dir);
668 unsigned len = strlen(link) + 1;
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400669 struct fuse_req *req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700670 if (IS_ERR(req))
671 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700672
673 req->in.h.opcode = FUSE_SYMLINK;
674 req->in.numargs = 2;
675 req->in.args[0].size = entry->d_name.len + 1;
676 req->in.args[0].value = entry->d_name.name;
677 req->in.args[1].size = len;
678 req->in.args[1].value = link;
679 return create_new_entry(fc, req, dir, entry, S_IFLNK);
680}
681
Maxim Patlasov31f32672014-04-28 14:19:24 +0200682static inline void fuse_update_ctime(struct inode *inode)
683{
684 if (!IS_NOCMTIME(inode)) {
685 inode->i_ctime = current_fs_time(inode->i_sb);
686 mark_inode_dirty_sync(inode);
687 }
688}
689
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700690static int fuse_unlink(struct inode *dir, struct dentry *entry)
691{
692 int err;
693 struct fuse_conn *fc = get_fuse_conn(dir);
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400694 struct fuse_req *req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700695 if (IS_ERR(req))
696 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700697
698 req->in.h.opcode = FUSE_UNLINK;
699 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700700 req->in.numargs = 1;
701 req->in.args[0].size = entry->d_name.len + 1;
702 req->in.args[0].value = entry->d_name.name;
Tejun Heob93f8582008-11-26 12:03:55 +0100703 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700704 err = req->out.h.error;
705 fuse_put_request(fc, req);
706 if (!err) {
707 struct inode *inode = entry->d_inode;
Miklos Szerediac45d612012-03-05 15:48:11 +0100708 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700709
Miklos Szerediac45d612012-03-05 15:48:11 +0100710 spin_lock(&fc->lock);
711 fi->attr_version = ++fc->attr_version;
Miklos Szeredidfca7ce2013-02-04 15:57:42 +0100712 /*
713 * If i_nlink == 0 then unlink doesn't make sense, yet this can
714 * happen if userspace filesystem is careless. It would be
715 * difficult to enforce correct nlink usage so just ignore this
716 * condition here
717 */
718 if (inode->i_nlink > 0)
719 drop_nlink(inode);
Miklos Szerediac45d612012-03-05 15:48:11 +0100720 spin_unlock(&fc->lock);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700721 fuse_invalidate_attr(inode);
722 fuse_invalidate_attr(dir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800723 fuse_invalidate_entry_cache(entry);
Maxim Patlasov31f32672014-04-28 14:19:24 +0200724 fuse_update_ctime(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700725 } else if (err == -EINTR)
726 fuse_invalidate_entry(entry);
727 return err;
728}
729
730static int fuse_rmdir(struct inode *dir, struct dentry *entry)
731{
732 int err;
733 struct fuse_conn *fc = get_fuse_conn(dir);
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400734 struct fuse_req *req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700735 if (IS_ERR(req))
736 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700737
738 req->in.h.opcode = FUSE_RMDIR;
739 req->in.h.nodeid = get_node_id(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700740 req->in.numargs = 1;
741 req->in.args[0].size = entry->d_name.len + 1;
742 req->in.args[0].value = entry->d_name.name;
Tejun Heob93f8582008-11-26 12:03:55 +0100743 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700744 err = req->out.h.error;
745 fuse_put_request(fc, req);
746 if (!err) {
Dave Hansence71ec32006-09-30 23:29:06 -0700747 clear_nlink(entry->d_inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700748 fuse_invalidate_attr(dir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800749 fuse_invalidate_entry_cache(entry);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700750 } else if (err == -EINTR)
751 fuse_invalidate_entry(entry);
752 return err;
753}
754
Miklos Szeredi1560c972014-04-28 16:43:44 +0200755static int fuse_rename_common(struct inode *olddir, struct dentry *oldent,
756 struct inode *newdir, struct dentry *newent,
757 unsigned int flags, int opcode, size_t argsize)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700758{
759 int err;
Miklos Szeredi1560c972014-04-28 16:43:44 +0200760 struct fuse_rename2_in inarg;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700761 struct fuse_conn *fc = get_fuse_conn(olddir);
Miklos Szeredi1560c972014-04-28 16:43:44 +0200762 struct fuse_req *req;
Sage Weile4eaac02011-05-24 13:06:07 -0700763
Miklos Szeredi1560c972014-04-28 16:43:44 +0200764 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700765 if (IS_ERR(req))
766 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700767
Miklos Szeredi1560c972014-04-28 16:43:44 +0200768 memset(&inarg, 0, argsize);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700769 inarg.newdir = get_node_id(newdir);
Miklos Szeredi1560c972014-04-28 16:43:44 +0200770 inarg.flags = flags;
771 req->in.h.opcode = opcode;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700772 req->in.h.nodeid = get_node_id(olddir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700773 req->in.numargs = 3;
Miklos Szeredi1560c972014-04-28 16:43:44 +0200774 req->in.args[0].size = argsize;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700775 req->in.args[0].value = &inarg;
776 req->in.args[1].size = oldent->d_name.len + 1;
777 req->in.args[1].value = oldent->d_name.name;
778 req->in.args[2].size = newent->d_name.len + 1;
779 req->in.args[2].value = newent->d_name.name;
Tejun Heob93f8582008-11-26 12:03:55 +0100780 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700781 err = req->out.h.error;
782 fuse_put_request(fc, req);
783 if (!err) {
Miklos Szeredi08b63302007-11-28 16:22:03 -0800784 /* ctime changes */
785 fuse_invalidate_attr(oldent->d_inode);
Maxim Patlasov31f32672014-04-28 14:19:24 +0200786 fuse_update_ctime(oldent->d_inode);
Miklos Szeredi08b63302007-11-28 16:22:03 -0800787
Miklos Szeredi1560c972014-04-28 16:43:44 +0200788 if (flags & RENAME_EXCHANGE) {
789 fuse_invalidate_attr(newent->d_inode);
790 fuse_update_ctime(newent->d_inode);
791 }
792
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700793 fuse_invalidate_attr(olddir);
794 if (olddir != newdir)
795 fuse_invalidate_attr(newdir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800796
797 /* newent will end up negative */
Miklos Szeredi1560c972014-04-28 16:43:44 +0200798 if (!(flags & RENAME_EXCHANGE) && newent->d_inode) {
Miklos Szeredi5219f342009-11-04 10:24:52 +0100799 fuse_invalidate_attr(newent->d_inode);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800800 fuse_invalidate_entry_cache(newent);
Maxim Patlasov31f32672014-04-28 14:19:24 +0200801 fuse_update_ctime(newent->d_inode);
Miklos Szeredi5219f342009-11-04 10:24:52 +0100802 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700803 } else if (err == -EINTR) {
804 /* If request was interrupted, DEITY only knows if the
805 rename actually took place. If the invalidation
806 fails (e.g. some process has CWD under the renamed
807 directory), then there can be inconsistency between
808 the dcache and the real filesystem. Tough luck. */
809 fuse_invalidate_entry(oldent);
810 if (newent->d_inode)
811 fuse_invalidate_entry(newent);
812 }
813
814 return err;
815}
816
Miklos Szeredi1560c972014-04-28 16:43:44 +0200817static int fuse_rename(struct inode *olddir, struct dentry *oldent,
818 struct inode *newdir, struct dentry *newent)
819{
820 return fuse_rename_common(olddir, oldent, newdir, newent, 0,
821 FUSE_RENAME, sizeof(struct fuse_rename_in));
822}
823
824static int fuse_rename2(struct inode *olddir, struct dentry *oldent,
825 struct inode *newdir, struct dentry *newent,
826 unsigned int flags)
827{
828 struct fuse_conn *fc = get_fuse_conn(olddir);
829 int err;
830
831 if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE))
832 return -EINVAL;
833
834 if (fc->no_rename2 || fc->minor < 23)
835 return -EINVAL;
836
837 err = fuse_rename_common(olddir, oldent, newdir, newent, flags,
838 FUSE_RENAME2, sizeof(struct fuse_rename2_in));
839 if (err == -ENOSYS) {
840 fc->no_rename2 = 1;
841 err = -EINVAL;
842 }
843 return err;
844
845}
846
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700847static int fuse_link(struct dentry *entry, struct inode *newdir,
848 struct dentry *newent)
849{
850 int err;
851 struct fuse_link_in inarg;
852 struct inode *inode = entry->d_inode;
853 struct fuse_conn *fc = get_fuse_conn(inode);
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400854 struct fuse_req *req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700855 if (IS_ERR(req))
856 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700857
858 memset(&inarg, 0, sizeof(inarg));
859 inarg.oldnodeid = get_node_id(inode);
860 req->in.h.opcode = FUSE_LINK;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700861 req->in.numargs = 2;
862 req->in.args[0].size = sizeof(inarg);
863 req->in.args[0].value = &inarg;
864 req->in.args[1].size = newent->d_name.len + 1;
865 req->in.args[1].value = newent->d_name.name;
866 err = create_new_entry(fc, req, newdir, newent, inode->i_mode);
867 /* Contrary to "normal" filesystems it can happen that link
868 makes two "logical" inodes point to the same "physical"
869 inode. We invalidate the attributes of the old one, so it
870 will reflect changes in the backing inode (link count,
871 etc.)
872 */
Miklos Szerediac45d612012-03-05 15:48:11 +0100873 if (!err) {
874 struct fuse_inode *fi = get_fuse_inode(inode);
875
876 spin_lock(&fc->lock);
877 fi->attr_version = ++fc->attr_version;
878 inc_nlink(inode);
879 spin_unlock(&fc->lock);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700880 fuse_invalidate_attr(inode);
Maxim Patlasov31f32672014-04-28 14:19:24 +0200881 fuse_update_ctime(inode);
Miklos Szerediac45d612012-03-05 15:48:11 +0100882 } else if (err == -EINTR) {
883 fuse_invalidate_attr(inode);
884 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700885 return err;
886}
887
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700888static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
889 struct kstat *stat)
890{
Miklos Szeredi203627b2012-05-10 19:49:38 +0400891 unsigned int blkbits;
Pavel Emelyanov83732002013-10-10 17:10:46 +0400892 struct fuse_conn *fc = get_fuse_conn(inode);
893
894 /* see the comment in fuse_change_attributes() */
Maxim Patlasovb0aa7602013-12-26 19:51:11 +0400895 if (fc->writeback_cache && S_ISREG(inode->i_mode)) {
Pavel Emelyanov83732002013-10-10 17:10:46 +0400896 attr->size = i_size_read(inode);
Maxim Patlasovb0aa7602013-12-26 19:51:11 +0400897 attr->mtime = inode->i_mtime.tv_sec;
898 attr->mtimensec = inode->i_mtime.tv_nsec;
Maxim Patlasov31f32672014-04-28 14:19:24 +0200899 attr->ctime = inode->i_ctime.tv_sec;
900 attr->ctimensec = inode->i_ctime.tv_nsec;
Maxim Patlasovb0aa7602013-12-26 19:51:11 +0400901 }
Miklos Szeredi203627b2012-05-10 19:49:38 +0400902
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700903 stat->dev = inode->i_sb->s_dev;
904 stat->ino = attr->ino;
905 stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
906 stat->nlink = attr->nlink;
Eric W. Biederman499dcf22012-02-07 16:26:03 -0800907 stat->uid = make_kuid(&init_user_ns, attr->uid);
908 stat->gid = make_kgid(&init_user_ns, attr->gid);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700909 stat->rdev = inode->i_rdev;
910 stat->atime.tv_sec = attr->atime;
911 stat->atime.tv_nsec = attr->atimensec;
912 stat->mtime.tv_sec = attr->mtime;
913 stat->mtime.tv_nsec = attr->mtimensec;
914 stat->ctime.tv_sec = attr->ctime;
915 stat->ctime.tv_nsec = attr->ctimensec;
916 stat->size = attr->size;
917 stat->blocks = attr->blocks;
Miklos Szeredi203627b2012-05-10 19:49:38 +0400918
919 if (attr->blksize != 0)
920 blkbits = ilog2(attr->blksize);
921 else
922 blkbits = inode->i_sb->s_blocksize_bits;
923
924 stat->blksize = 1 << blkbits;
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700925}
926
Miklos Szeredic79e3222007-10-18 03:06:59 -0700927static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
928 struct file *file)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700929{
930 int err;
Miklos Szeredic79e3222007-10-18 03:06:59 -0700931 struct fuse_getattr_in inarg;
932 struct fuse_attr_out outarg;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700933 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700934 struct fuse_req *req;
935 u64 attr_version;
936
Maxim Patlasovb111c8c2012-10-26 19:48:30 +0400937 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700938 if (IS_ERR(req))
939 return PTR_ERR(req);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700940
Miklos Szeredi7dca9fd2007-11-28 16:21:59 -0800941 attr_version = fuse_get_attr_version(fc);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700942
Miklos Szeredic79e3222007-10-18 03:06:59 -0700943 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700944 memset(&outarg, 0, sizeof(outarg));
Miklos Szeredic79e3222007-10-18 03:06:59 -0700945 /* Directories have separate file-handle space */
946 if (file && S_ISREG(inode->i_mode)) {
947 struct fuse_file *ff = file->private_data;
948
949 inarg.getattr_flags |= FUSE_GETATTR_FH;
950 inarg.fh = ff->fh;
951 }
Miklos Szeredie5e55582005-09-09 13:10:28 -0700952 req->in.h.opcode = FUSE_GETATTR;
953 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredic79e3222007-10-18 03:06:59 -0700954 req->in.numargs = 1;
955 req->in.args[0].size = sizeof(inarg);
956 req->in.args[0].value = &inarg;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700957 req->out.numargs = 1;
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700958 if (fc->minor < 9)
959 req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
960 else
961 req->out.args[0].size = sizeof(outarg);
Miklos Szeredic79e3222007-10-18 03:06:59 -0700962 req->out.args[0].value = &outarg;
Tejun Heob93f8582008-11-26 12:03:55 +0100963 fuse_request_send(fc, req);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700964 err = req->out.h.error;
965 fuse_put_request(fc, req);
966 if (!err) {
Miklos Szeredic79e3222007-10-18 03:06:59 -0700967 if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
Miklos Szeredie5e55582005-09-09 13:10:28 -0700968 make_bad_inode(inode);
969 err = -EIO;
970 } else {
Miklos Szeredic79e3222007-10-18 03:06:59 -0700971 fuse_change_attributes(inode, &outarg.attr,
972 attr_timeout(&outarg),
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700973 attr_version);
974 if (stat)
Miklos Szeredic79e3222007-10-18 03:06:59 -0700975 fuse_fillattr(inode, &outarg.attr, stat);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700976 }
977 }
978 return err;
979}
980
Miklos Szeredibcb4be82007-11-28 16:21:59 -0800981int fuse_update_attributes(struct inode *inode, struct kstat *stat,
982 struct file *file, bool *refreshed)
983{
984 struct fuse_inode *fi = get_fuse_inode(inode);
985 int err;
986 bool r;
987
988 if (fi->i_time < get_jiffies_64()) {
989 r = true;
990 err = fuse_do_getattr(inode, stat, file);
991 } else {
992 r = false;
993 err = 0;
994 if (stat) {
995 generic_fillattr(inode, stat);
996 stat->mode = fi->orig_i_mode;
Pavel Shilovsky45c72cd2012-05-10 19:49:38 +0400997 stat->ino = fi->orig_ino;
Miklos Szeredibcb4be82007-11-28 16:21:59 -0800998 }
999 }
1000
1001 if (refreshed != NULL)
1002 *refreshed = r;
1003
1004 return err;
1005}
1006
John Muir3b463ae2009-05-31 11:13:57 -04001007int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid,
John Muir451d0f52011-12-06 21:50:06 +01001008 u64 child_nodeid, struct qstr *name)
John Muir3b463ae2009-05-31 11:13:57 -04001009{
1010 int err = -ENOTDIR;
1011 struct inode *parent;
1012 struct dentry *dir;
1013 struct dentry *entry;
1014
1015 parent = ilookup5(sb, parent_nodeid, fuse_inode_eq, &parent_nodeid);
1016 if (!parent)
1017 return -ENOENT;
1018
1019 mutex_lock(&parent->i_mutex);
1020 if (!S_ISDIR(parent->i_mode))
1021 goto unlock;
1022
1023 err = -ENOENT;
1024 dir = d_find_alias(parent);
1025 if (!dir)
1026 goto unlock;
1027
1028 entry = d_lookup(dir, name);
1029 dput(dir);
1030 if (!entry)
1031 goto unlock;
1032
1033 fuse_invalidate_attr(parent);
1034 fuse_invalidate_entry(entry);
John Muir451d0f52011-12-06 21:50:06 +01001035
1036 if (child_nodeid != 0 && entry->d_inode) {
1037 mutex_lock(&entry->d_inode->i_mutex);
1038 if (get_node_id(entry->d_inode) != child_nodeid) {
1039 err = -ENOENT;
1040 goto badentry;
1041 }
1042 if (d_mountpoint(entry)) {
1043 err = -EBUSY;
1044 goto badentry;
1045 }
1046 if (S_ISDIR(entry->d_inode->i_mode)) {
1047 shrink_dcache_parent(entry);
1048 if (!simple_empty(entry)) {
1049 err = -ENOTEMPTY;
1050 goto badentry;
1051 }
1052 entry->d_inode->i_flags |= S_DEAD;
1053 }
1054 dont_mount(entry);
1055 clear_nlink(entry->d_inode);
1056 err = 0;
1057 badentry:
1058 mutex_unlock(&entry->d_inode->i_mutex);
1059 if (!err)
1060 d_delete(entry);
1061 } else {
1062 err = 0;
1063 }
John Muir3b463ae2009-05-31 11:13:57 -04001064 dput(entry);
John Muir3b463ae2009-05-31 11:13:57 -04001065
1066 unlock:
1067 mutex_unlock(&parent->i_mutex);
1068 iput(parent);
1069 return err;
1070}
1071
Miklos Szeredi87729a52005-09-09 13:10:34 -07001072/*
1073 * Calling into a user-controlled filesystem gives the filesystem
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001074 * daemon ptrace-like capabilities over the current process. This
Miklos Szeredi87729a52005-09-09 13:10:34 -07001075 * means, that the filesystem daemon is able to record the exact
1076 * filesystem operations performed, and can also control the behavior
1077 * of the requester process in otherwise impossible ways. For example
1078 * it can delay the operation for arbitrary length of time allowing
1079 * DoS against the requester.
1080 *
1081 * For this reason only those processes can call into the filesystem,
1082 * for which the owner of the mount has ptrace privilege. This
1083 * excludes processes started by other users, suid or sgid processes.
1084 */
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001085int fuse_allow_current_process(struct fuse_conn *fc)
Miklos Szeredi87729a52005-09-09 13:10:34 -07001086{
David Howellsc69e8d92008-11-14 10:39:19 +11001087 const struct cred *cred;
David Howellsc69e8d92008-11-14 10:39:19 +11001088
Miklos Szeredi87729a52005-09-09 13:10:34 -07001089 if (fc->flags & FUSE_ALLOW_OTHER)
1090 return 1;
1091
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001092 cred = current_cred();
Eric W. Biederman499dcf22012-02-07 16:26:03 -08001093 if (uid_eq(cred->euid, fc->user_id) &&
1094 uid_eq(cred->suid, fc->user_id) &&
1095 uid_eq(cred->uid, fc->user_id) &&
1096 gid_eq(cred->egid, fc->group_id) &&
1097 gid_eq(cred->sgid, fc->group_id) &&
1098 gid_eq(cred->gid, fc->group_id))
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001099 return 1;
Miklos Szeredi87729a52005-09-09 13:10:34 -07001100
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001101 return 0;
Miklos Szeredi87729a52005-09-09 13:10:34 -07001102}
1103
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001104static int fuse_access(struct inode *inode, int mask)
1105{
1106 struct fuse_conn *fc = get_fuse_conn(inode);
1107 struct fuse_req *req;
1108 struct fuse_access_in inarg;
1109 int err;
1110
Miklos Szeredi698fa1d2013-10-01 16:41:23 +02001111 BUG_ON(mask & MAY_NOT_BLOCK);
1112
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001113 if (fc->no_access)
1114 return 0;
1115
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001116 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001117 if (IS_ERR(req))
1118 return PTR_ERR(req);
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001119
1120 memset(&inarg, 0, sizeof(inarg));
Al Viroe6305c42008-07-15 21:03:57 -04001121 inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC);
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001122 req->in.h.opcode = FUSE_ACCESS;
1123 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001124 req->in.numargs = 1;
1125 req->in.args[0].size = sizeof(inarg);
1126 req->in.args[0].value = &inarg;
Tejun Heob93f8582008-11-26 12:03:55 +01001127 fuse_request_send(fc, req);
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001128 err = req->out.h.error;
1129 fuse_put_request(fc, req);
1130 if (err == -ENOSYS) {
1131 fc->no_access = 1;
1132 err = 0;
1133 }
1134 return err;
1135}
1136
Al Viro10556cb2011-06-20 19:28:19 -04001137static int fuse_perm_getattr(struct inode *inode, int mask)
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001138{
Al Viro10556cb2011-06-20 19:28:19 -04001139 if (mask & MAY_NOT_BLOCK)
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001140 return -ECHILD;
1141
1142 return fuse_do_getattr(inode, NULL, NULL);
1143}
1144
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001145/*
1146 * Check permission. The two basic access models of FUSE are:
1147 *
1148 * 1) Local access checking ('default_permissions' mount option) based
1149 * on file mode. This is the plain old disk filesystem permission
1150 * modell.
1151 *
1152 * 2) "Remote" access checking, where server is responsible for
1153 * checking permission in each inode operation. An exception to this
1154 * is if ->permission() was invoked from sys_access() in which case an
1155 * access request is sent. Execute permission is still checked
1156 * locally based on file mode.
1157 */
Al Viro10556cb2011-06-20 19:28:19 -04001158static int fuse_permission(struct inode *inode, int mask)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001159{
1160 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi244f6382007-10-16 23:31:02 -07001161 bool refreshed = false;
1162 int err = 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001163
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001164 if (!fuse_allow_current_process(fc))
Miklos Szeredie5e55582005-09-09 13:10:28 -07001165 return -EACCES;
Miklos Szeredi244f6382007-10-16 23:31:02 -07001166
1167 /*
Miklos Szeredie8e96152007-10-16 23:31:06 -07001168 * If attributes are needed, refresh them before proceeding
Miklos Szeredi244f6382007-10-16 23:31:02 -07001169 */
Miklos Szeredie8e96152007-10-16 23:31:06 -07001170 if ((fc->flags & FUSE_DEFAULT_PERMISSIONS) ||
1171 ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001172 struct fuse_inode *fi = get_fuse_inode(inode);
1173
1174 if (fi->i_time < get_jiffies_64()) {
1175 refreshed = true;
1176
Al Viro10556cb2011-06-20 19:28:19 -04001177 err = fuse_perm_getattr(inode, mask);
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001178 if (err)
1179 return err;
1180 }
Miklos Szeredi244f6382007-10-16 23:31:02 -07001181 }
1182
1183 if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
Al Viro2830ba72011-06-20 19:16:29 -04001184 err = generic_permission(inode, mask);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001185
1186 /* If permission is denied, try to refresh file
1187 attributes. This is also needed, because the root
1188 node will at first have no permissions */
Miklos Szeredi244f6382007-10-16 23:31:02 -07001189 if (err == -EACCES && !refreshed) {
Al Viro10556cb2011-06-20 19:28:19 -04001190 err = fuse_perm_getattr(inode, mask);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001191 if (!err)
Al Viro2830ba72011-06-20 19:16:29 -04001192 err = generic_permission(inode, mask);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001193 }
1194
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001195 /* Note: the opposite of the above test does not
1196 exist. So if permissions are revoked this won't be
1197 noticed immediately, only after the attribute
1198 timeout has expired */
Eric Paris9cfcac82010-07-23 11:43:51 -04001199 } else if (mask & (MAY_ACCESS | MAY_CHDIR)) {
Miklos Szeredie8e96152007-10-16 23:31:06 -07001200 err = fuse_access(inode, mask);
1201 } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
1202 if (!(inode->i_mode & S_IXUGO)) {
1203 if (refreshed)
1204 return -EACCES;
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001205
Al Viro10556cb2011-06-20 19:28:19 -04001206 err = fuse_perm_getattr(inode, mask);
Miklos Szeredie8e96152007-10-16 23:31:06 -07001207 if (!err && !(inode->i_mode & S_IXUGO))
1208 return -EACCES;
1209 }
Miklos Szeredie5e55582005-09-09 13:10:28 -07001210 }
Miklos Szeredi244f6382007-10-16 23:31:02 -07001211 return err;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001212}
1213
1214static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
Al Viro8d3af7f2013-05-18 03:03:58 -04001215 struct dir_context *ctx)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001216{
1217 while (nbytes >= FUSE_NAME_OFFSET) {
1218 struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
1219 size_t reclen = FUSE_DIRENT_SIZE(dirent);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001220 if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
1221 return -EIO;
1222 if (reclen > nbytes)
1223 break;
Miklos Szerediefeb9e62013-09-03 14:28:38 +02001224 if (memchr(dirent->name, '/', dirent->namelen) != NULL)
1225 return -EIO;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001226
Al Viro8d3af7f2013-05-18 03:03:58 -04001227 if (!dir_emit(ctx, dirent->name, dirent->namelen,
1228 dirent->ino, dirent->type))
Miklos Szeredie5e55582005-09-09 13:10:28 -07001229 break;
1230
1231 buf += reclen;
1232 nbytes -= reclen;
Al Viro8d3af7f2013-05-18 03:03:58 -04001233 ctx->pos = dirent->off;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001234 }
1235
1236 return 0;
1237}
1238
Anand V. Avati0b05b182012-08-19 08:53:23 -04001239static int fuse_direntplus_link(struct file *file,
1240 struct fuse_direntplus *direntplus,
1241 u64 attr_version)
1242{
1243 int err;
1244 struct fuse_entry_out *o = &direntplus->entry_out;
1245 struct fuse_dirent *dirent = &direntplus->dirent;
1246 struct dentry *parent = file->f_path.dentry;
1247 struct qstr name = QSTR_INIT(dirent->name, dirent->namelen);
1248 struct dentry *dentry;
1249 struct dentry *alias;
1250 struct inode *dir = parent->d_inode;
1251 struct fuse_conn *fc;
1252 struct inode *inode;
1253
1254 if (!o->nodeid) {
1255 /*
1256 * Unlike in the case of fuse_lookup, zero nodeid does not mean
1257 * ENOENT. Instead, it only means the userspace filesystem did
1258 * not want to return attributes/handle for this entry.
1259 *
1260 * So do nothing.
1261 */
1262 return 0;
1263 }
1264
1265 if (name.name[0] == '.') {
1266 /*
1267 * We could potentially refresh the attributes of the directory
1268 * and its parent?
1269 */
1270 if (name.len == 1)
1271 return 0;
1272 if (name.name[1] == '.' && name.len == 2)
1273 return 0;
1274 }
Miklos Szeredia28ef452013-07-17 14:53:53 +02001275
1276 if (invalid_nodeid(o->nodeid))
1277 return -EIO;
1278 if (!fuse_valid_type(o->attr.mode))
1279 return -EIO;
1280
Anand V. Avati0b05b182012-08-19 08:53:23 -04001281 fc = get_fuse_conn(dir);
1282
1283 name.hash = full_name_hash(name.name, name.len);
1284 dentry = d_lookup(parent, &name);
Niels de Vos53ce9a32013-07-17 14:53:53 +02001285 if (dentry) {
Anand V. Avati0b05b182012-08-19 08:53:23 -04001286 inode = dentry->d_inode;
Niels de Vos53ce9a32013-07-17 14:53:53 +02001287 if (!inode) {
1288 d_drop(dentry);
Miklos Szeredia28ef452013-07-17 14:53:53 +02001289 } else if (get_node_id(inode) != o->nodeid ||
1290 ((o->attr.mode ^ inode->i_mode) & S_IFMT)) {
Niels de Vos53ce9a32013-07-17 14:53:53 +02001291 err = d_invalidate(dentry);
1292 if (err)
1293 goto out;
Miklos Szeredia28ef452013-07-17 14:53:53 +02001294 } else if (is_bad_inode(inode)) {
1295 err = -EIO;
1296 goto out;
Niels de Vos53ce9a32013-07-17 14:53:53 +02001297 } else {
Anand V. Avati0b05b182012-08-19 08:53:23 -04001298 struct fuse_inode *fi;
1299 fi = get_fuse_inode(inode);
1300 spin_lock(&fc->lock);
1301 fi->nlookup++;
1302 spin_unlock(&fc->lock);
1303
Miklos Szeredifa2b7212013-07-17 14:53:53 +02001304 fuse_change_attributes(inode, &o->attr,
1305 entry_attr_timeout(o),
1306 attr_version);
1307
Anand V. Avati0b05b182012-08-19 08:53:23 -04001308 /*
1309 * The other branch to 'found' comes via fuse_iget()
1310 * which bumps nlookup inside
1311 */
1312 goto found;
1313 }
Anand V. Avati0b05b182012-08-19 08:53:23 -04001314 dput(dentry);
Anand V. Avati0b05b182012-08-19 08:53:23 -04001315 }
1316
1317 dentry = d_alloc(parent, &name);
1318 err = -ENOMEM;
1319 if (!dentry)
1320 goto out;
1321
1322 inode = fuse_iget(dir->i_sb, o->nodeid, o->generation,
1323 &o->attr, entry_attr_timeout(o), attr_version);
1324 if (!inode)
1325 goto out;
1326
Miklos Szeredib70a80e2013-10-01 16:44:54 +02001327 alias = d_materialise_unique(dentry, inode);
Miklos Szeredi5835f332013-09-05 11:44:42 +02001328 err = PTR_ERR(alias);
1329 if (IS_ERR(alias))
1330 goto out;
Miklos Szeredi29149412013-07-17 14:53:53 +02001331
Anand V. Avati0b05b182012-08-19 08:53:23 -04001332 if (alias) {
1333 dput(dentry);
1334 dentry = alias;
1335 }
1336
1337found:
Miklos Szeredi6314efe2013-10-01 16:41:22 +02001338 if (fc->readdirplus_auto)
1339 set_bit(FUSE_I_INIT_RDPLUS, &get_fuse_inode(inode)->state);
Anand V. Avati0b05b182012-08-19 08:53:23 -04001340 fuse_change_entry_timeout(dentry, o);
1341
1342 err = 0;
1343out:
Miklos Szeredic7263bc2013-07-17 14:53:54 +02001344 dput(dentry);
Anand V. Avati0b05b182012-08-19 08:53:23 -04001345 return err;
1346}
1347
1348static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file,
Al Viro8d3af7f2013-05-18 03:03:58 -04001349 struct dir_context *ctx, u64 attr_version)
Anand V. Avati0b05b182012-08-19 08:53:23 -04001350{
1351 struct fuse_direntplus *direntplus;
1352 struct fuse_dirent *dirent;
1353 size_t reclen;
1354 int over = 0;
1355 int ret;
1356
1357 while (nbytes >= FUSE_NAME_OFFSET_DIRENTPLUS) {
1358 direntplus = (struct fuse_direntplus *) buf;
1359 dirent = &direntplus->dirent;
1360 reclen = FUSE_DIRENTPLUS_SIZE(direntplus);
1361
1362 if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
1363 return -EIO;
1364 if (reclen > nbytes)
1365 break;
Miklos Szerediefeb9e62013-09-03 14:28:38 +02001366 if (memchr(dirent->name, '/', dirent->namelen) != NULL)
1367 return -EIO;
Anand V. Avati0b05b182012-08-19 08:53:23 -04001368
1369 if (!over) {
1370 /* We fill entries into dstbuf only as much as
1371 it can hold. But we still continue iterating
1372 over remaining entries to link them. If not,
1373 we need to send a FORGET for each of those
1374 which we did not link.
1375 */
Al Viro8d3af7f2013-05-18 03:03:58 -04001376 over = !dir_emit(ctx, dirent->name, dirent->namelen,
1377 dirent->ino, dirent->type);
1378 ctx->pos = dirent->off;
Anand V. Avati0b05b182012-08-19 08:53:23 -04001379 }
1380
1381 buf += reclen;
1382 nbytes -= reclen;
1383
1384 ret = fuse_direntplus_link(file, direntplus, attr_version);
1385 if (ret)
1386 fuse_force_forget(file, direntplus->entry_out.nodeid);
1387 }
1388
1389 return 0;
1390}
1391
Al Viro8d3af7f2013-05-18 03:03:58 -04001392static int fuse_readdir(struct file *file, struct dir_context *ctx)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001393{
Feng Shuo4582a4a2013-01-15 11:23:28 +08001394 int plus, err;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001395 size_t nbytes;
1396 struct page *page;
Al Viro496ad9a2013-01-23 17:07:38 -05001397 struct inode *inode = file_inode(file);
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001398 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi248d86e2006-01-06 00:19:39 -08001399 struct fuse_req *req;
Anand V. Avati0b05b182012-08-19 08:53:23 -04001400 u64 attr_version = 0;
Miklos Szeredi248d86e2006-01-06 00:19:39 -08001401
1402 if (is_bad_inode(inode))
1403 return -EIO;
1404
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001405 req = fuse_get_req(fc, 1);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001406 if (IS_ERR(req))
1407 return PTR_ERR(req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001408
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001409 page = alloc_page(GFP_KERNEL);
1410 if (!page) {
1411 fuse_put_request(fc, req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001412 return -ENOMEM;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001413 }
Feng Shuo4582a4a2013-01-15 11:23:28 +08001414
Al Viro8d3af7f2013-05-18 03:03:58 -04001415 plus = fuse_use_readdirplus(inode, ctx);
Miklos Szeredif4975c62009-04-02 14:25:34 +02001416 req->out.argpages = 1;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001417 req->num_pages = 1;
1418 req->pages[0] = page;
Maxim Patlasov85f40ae2012-10-26 19:49:33 +04001419 req->page_descs[0].length = PAGE_SIZE;
Feng Shuo4582a4a2013-01-15 11:23:28 +08001420 if (plus) {
Anand V. Avati0b05b182012-08-19 08:53:23 -04001421 attr_version = fuse_get_attr_version(fc);
Al Viro8d3af7f2013-05-18 03:03:58 -04001422 fuse_read_fill(req, file, ctx->pos, PAGE_SIZE,
Anand V. Avati0b05b182012-08-19 08:53:23 -04001423 FUSE_READDIRPLUS);
1424 } else {
Al Viro8d3af7f2013-05-18 03:03:58 -04001425 fuse_read_fill(req, file, ctx->pos, PAGE_SIZE,
Anand V. Avati0b05b182012-08-19 08:53:23 -04001426 FUSE_READDIR);
1427 }
Tejun Heob93f8582008-11-26 12:03:55 +01001428 fuse_request_send(fc, req);
Miklos Szeredi361b1eb52006-01-16 22:14:45 -08001429 nbytes = req->out.args[0].size;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001430 err = req->out.h.error;
1431 fuse_put_request(fc, req);
Anand V. Avati0b05b182012-08-19 08:53:23 -04001432 if (!err) {
Feng Shuo4582a4a2013-01-15 11:23:28 +08001433 if (plus) {
Anand V. Avati0b05b182012-08-19 08:53:23 -04001434 err = parse_dirplusfile(page_address(page), nbytes,
Al Viro8d3af7f2013-05-18 03:03:58 -04001435 file, ctx,
Anand V. Avati0b05b182012-08-19 08:53:23 -04001436 attr_version);
1437 } else {
1438 err = parse_dirfile(page_address(page), nbytes, file,
Al Viro8d3af7f2013-05-18 03:03:58 -04001439 ctx);
Anand V. Avati0b05b182012-08-19 08:53:23 -04001440 }
1441 }
Miklos Szeredie5e55582005-09-09 13:10:28 -07001442
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001443 __free_page(page);
Andrew Gallagher451418f2013-11-05 03:55:43 -08001444 fuse_invalidate_atime(inode);
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001445 return err;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001446}
1447
1448static char *read_link(struct dentry *dentry)
1449{
1450 struct inode *inode = dentry->d_inode;
1451 struct fuse_conn *fc = get_fuse_conn(inode);
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001452 struct fuse_req *req = fuse_get_req_nopages(fc);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001453 char *link;
1454
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001455 if (IS_ERR(req))
David Howellse231c2e2008-02-07 00:15:26 -08001456 return ERR_CAST(req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001457
1458 link = (char *) __get_free_page(GFP_KERNEL);
1459 if (!link) {
1460 link = ERR_PTR(-ENOMEM);
1461 goto out;
1462 }
1463 req->in.h.opcode = FUSE_READLINK;
1464 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001465 req->out.argvar = 1;
1466 req->out.numargs = 1;
1467 req->out.args[0].size = PAGE_SIZE - 1;
1468 req->out.args[0].value = link;
Tejun Heob93f8582008-11-26 12:03:55 +01001469 fuse_request_send(fc, req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001470 if (req->out.h.error) {
1471 free_page((unsigned long) link);
1472 link = ERR_PTR(req->out.h.error);
1473 } else
1474 link[req->out.args[0].size] = '\0';
1475 out:
1476 fuse_put_request(fc, req);
Andrew Gallagher451418f2013-11-05 03:55:43 -08001477 fuse_invalidate_atime(inode);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001478 return link;
1479}
1480
1481static void free_link(char *link)
1482{
1483 if (!IS_ERR(link))
1484 free_page((unsigned long) link);
1485}
1486
1487static void *fuse_follow_link(struct dentry *dentry, struct nameidata *nd)
1488{
1489 nd_set_link(nd, read_link(dentry));
1490 return NULL;
1491}
1492
1493static void fuse_put_link(struct dentry *dentry, struct nameidata *nd, void *c)
1494{
1495 free_link(nd_get_link(nd));
1496}
1497
1498static int fuse_dir_open(struct inode *inode, struct file *file)
1499{
Miklos Szeredi91fe96b2009-04-28 16:56:37 +02001500 return fuse_open_common(inode, file, true);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001501}
1502
1503static int fuse_dir_release(struct inode *inode, struct file *file)
1504{
Miklos Szeredi8b0797a2009-04-28 16:56:39 +02001505 fuse_release_common(file, FUSE_RELEASEDIR);
1506
1507 return 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001508}
1509
Josef Bacik02c24a82011-07-16 20:44:56 -04001510static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end,
1511 int datasync)
Miklos Szeredi82547982005-09-09 13:10:38 -07001512{
Josef Bacik02c24a82011-07-16 20:44:56 -04001513 return fuse_fsync_common(file, start, end, datasync, 1);
Miklos Szeredi82547982005-09-09 13:10:38 -07001514}
1515
Miklos Szeredib18da0c2011-12-13 11:58:49 +01001516static long fuse_dir_ioctl(struct file *file, unsigned int cmd,
1517 unsigned long arg)
1518{
1519 struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1520
1521 /* FUSE_IOCTL_DIR only supported for API version >= 7.18 */
1522 if (fc->minor < 18)
1523 return -ENOTTY;
1524
1525 return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR);
1526}
1527
1528static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd,
1529 unsigned long arg)
1530{
1531 struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1532
1533 if (fc->minor < 18)
1534 return -ENOTTY;
1535
1536 return fuse_ioctl_common(file, cmd, arg,
1537 FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR);
1538}
1539
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001540static bool update_mtime(unsigned ivalid, bool trust_local_mtime)
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001541{
1542 /* Always update if mtime is explicitly set */
1543 if (ivalid & ATTR_MTIME_SET)
1544 return true;
1545
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001546 /* Or if kernel i_mtime is the official one */
1547 if (trust_local_mtime)
1548 return true;
1549
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001550 /* If it's an open(O_TRUNC) or an ftruncate(), don't update */
1551 if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
1552 return false;
1553
1554 /* In all other cases update */
1555 return true;
1556}
1557
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001558static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg,
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001559 bool trust_local_cmtime)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001560{
1561 unsigned ivalid = iattr->ia_valid;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001562
1563 if (ivalid & ATTR_MODE)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001564 arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001565 if (ivalid & ATTR_UID)
Eric W. Biederman499dcf22012-02-07 16:26:03 -08001566 arg->valid |= FATTR_UID, arg->uid = from_kuid(&init_user_ns, iattr->ia_uid);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001567 if (ivalid & ATTR_GID)
Eric W. Biederman499dcf22012-02-07 16:26:03 -08001568 arg->valid |= FATTR_GID, arg->gid = from_kgid(&init_user_ns, iattr->ia_gid);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001569 if (ivalid & ATTR_SIZE)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001570 arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001571 if (ivalid & ATTR_ATIME) {
1572 arg->valid |= FATTR_ATIME;
Miklos Szeredibefc6492005-11-07 00:59:52 -08001573 arg->atime = iattr->ia_atime.tv_sec;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001574 arg->atimensec = iattr->ia_atime.tv_nsec;
1575 if (!(ivalid & ATTR_ATIME_SET))
1576 arg->valid |= FATTR_ATIME_NOW;
1577 }
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001578 if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, trust_local_cmtime)) {
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001579 arg->valid |= FATTR_MTIME;
Miklos Szeredibefc6492005-11-07 00:59:52 -08001580 arg->mtime = iattr->ia_mtime.tv_sec;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001581 arg->mtimensec = iattr->ia_mtime.tv_nsec;
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001582 if (!(ivalid & ATTR_MTIME_SET) && !trust_local_cmtime)
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001583 arg->valid |= FATTR_MTIME_NOW;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001584 }
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001585 if ((ivalid & ATTR_CTIME) && trust_local_cmtime) {
1586 arg->valid |= FATTR_CTIME;
1587 arg->ctime = iattr->ia_ctime.tv_sec;
1588 arg->ctimensec = iattr->ia_ctime.tv_nsec;
1589 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001590}
1591
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001592/*
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001593 * Prevent concurrent writepages on inode
1594 *
1595 * This is done by adding a negative bias to the inode write counter
1596 * and waiting for all pending writes to finish.
1597 */
1598void fuse_set_nowrite(struct inode *inode)
1599{
1600 struct fuse_conn *fc = get_fuse_conn(inode);
1601 struct fuse_inode *fi = get_fuse_inode(inode);
1602
1603 BUG_ON(!mutex_is_locked(&inode->i_mutex));
1604
1605 spin_lock(&fc->lock);
1606 BUG_ON(fi->writectr < 0);
1607 fi->writectr += FUSE_NOWRITE;
1608 spin_unlock(&fc->lock);
1609 wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE);
1610}
1611
1612/*
1613 * Allow writepages on inode
1614 *
1615 * Remove the bias from the writecounter and send any queued
1616 * writepages.
1617 */
1618static void __fuse_release_nowrite(struct inode *inode)
1619{
1620 struct fuse_inode *fi = get_fuse_inode(inode);
1621
1622 BUG_ON(fi->writectr != FUSE_NOWRITE);
1623 fi->writectr = 0;
1624 fuse_flush_writepages(inode);
1625}
1626
1627void fuse_release_nowrite(struct inode *inode)
1628{
1629 struct fuse_conn *fc = get_fuse_conn(inode);
1630
1631 spin_lock(&fc->lock);
1632 __fuse_release_nowrite(inode);
1633 spin_unlock(&fc->lock);
1634}
1635
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001636static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_req *req,
1637 struct inode *inode,
1638 struct fuse_setattr_in *inarg_p,
1639 struct fuse_attr_out *outarg_p)
1640{
1641 req->in.h.opcode = FUSE_SETATTR;
1642 req->in.h.nodeid = get_node_id(inode);
1643 req->in.numargs = 1;
1644 req->in.args[0].size = sizeof(*inarg_p);
1645 req->in.args[0].value = inarg_p;
1646 req->out.numargs = 1;
1647 if (fc->minor < 9)
1648 req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
1649 else
1650 req->out.args[0].size = sizeof(*outarg_p);
1651 req->out.args[0].value = outarg_p;
1652}
1653
1654/*
1655 * Flush inode->i_mtime to the server
1656 */
Maxim Patlasovab9e13f2014-04-28 14:19:24 +02001657int fuse_flush_times(struct inode *inode, struct fuse_file *ff)
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001658{
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001659 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi1e18bda2014-04-28 14:19:23 +02001660 struct fuse_req *req;
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001661 struct fuse_setattr_in inarg;
1662 struct fuse_attr_out outarg;
1663 int err;
1664
Miklos Szeredi1e18bda2014-04-28 14:19:23 +02001665 req = fuse_get_req_nopages(fc);
1666 if (IS_ERR(req))
1667 return PTR_ERR(req);
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001668
1669 memset(&inarg, 0, sizeof(inarg));
1670 memset(&outarg, 0, sizeof(outarg));
1671
Maxim Patlasovab9e13f2014-04-28 14:19:24 +02001672 inarg.valid = FATTR_MTIME;
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001673 inarg.mtime = inode->i_mtime.tv_sec;
1674 inarg.mtimensec = inode->i_mtime.tv_nsec;
Maxim Patlasovab9e13f2014-04-28 14:19:24 +02001675 if (fc->minor >= 23) {
1676 inarg.valid |= FATTR_CTIME;
1677 inarg.ctime = inode->i_ctime.tv_sec;
1678 inarg.ctimensec = inode->i_ctime.tv_nsec;
1679 }
Miklos Szeredi1e18bda2014-04-28 14:19:23 +02001680 if (ff) {
1681 inarg.valid |= FATTR_FH;
1682 inarg.fh = ff->fh;
1683 }
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001684 fuse_setattr_fill(fc, req, inode, &inarg, &outarg);
1685 fuse_request_send(fc, req);
1686 err = req->out.h.error;
1687 fuse_put_request(fc, req);
1688
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001689 return err;
1690}
1691
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001692/*
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001693 * Set attributes, and at the same time refresh them.
1694 *
1695 * Truncation is slightly complicated, because the 'truncate' request
1696 * may fail, in which case we don't want to touch the mapping.
Miklos Szeredi9ffbb912006-10-17 00:10:06 -07001697 * vmtruncate() doesn't allow for this case, so do the rlimit checking
1698 * and the actual truncation by hand.
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001699 */
Maxim Patlasovefb9fa92012-12-18 14:05:08 +04001700int fuse_do_setattr(struct inode *inode, struct iattr *attr,
1701 struct file *file)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001702{
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001703 struct fuse_conn *fc = get_fuse_conn(inode);
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001704 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001705 struct fuse_req *req;
1706 struct fuse_setattr_in inarg;
1707 struct fuse_attr_out outarg;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001708 bool is_truncate = false;
Pavel Emelyanov83732002013-10-10 17:10:46 +04001709 bool is_wb = fc->writeback_cache;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001710 loff_t oldsize;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001711 int err;
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001712 bool trust_local_cmtime = is_wb && S_ISREG(inode->i_mode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001713
Christoph Hellwigdb78b872010-06-04 11:30:03 +02001714 if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS))
1715 attr->ia_valid |= ATTR_FORCE;
1716
1717 err = inode_change_ok(inode, attr);
1718 if (err)
1719 return err;
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001720
Miklos Szeredi8d56add2011-02-25 14:44:58 +01001721 if (attr->ia_valid & ATTR_OPEN) {
1722 if (fc->atomic_o_trunc)
1723 return 0;
1724 file = NULL;
1725 }
Miklos Szeredi6ff958e2007-10-18 03:07:02 -07001726
Christoph Hellwig2c27c652010-06-04 11:30:04 +02001727 if (attr->ia_valid & ATTR_SIZE)
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001728 is_truncate = true;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001729
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001730 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001731 if (IS_ERR(req))
1732 return PTR_ERR(req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001733
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001734 if (is_truncate) {
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001735 fuse_set_nowrite(inode);
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001736 set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001737 if (trust_local_cmtime && attr->ia_size != inode->i_size)
1738 attr->ia_valid |= ATTR_MTIME | ATTR_CTIME;
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001739 }
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001740
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001741 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -07001742 memset(&outarg, 0, sizeof(outarg));
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001743 iattr_to_fattr(attr, &inarg, trust_local_cmtime);
Miklos Szeredi49d49142007-10-18 03:07:00 -07001744 if (file) {
1745 struct fuse_file *ff = file->private_data;
1746 inarg.valid |= FATTR_FH;
1747 inarg.fh = ff->fh;
1748 }
Miklos Szeredif3332112007-10-18 03:07:04 -07001749 if (attr->ia_valid & ATTR_SIZE) {
1750 /* For mandatory locking in truncate */
1751 inarg.valid |= FATTR_LOCKOWNER;
1752 inarg.lock_owner = fuse_lock_owner_id(fc, current->files);
1753 }
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001754 fuse_setattr_fill(fc, req, inode, &inarg, &outarg);
Tejun Heob93f8582008-11-26 12:03:55 +01001755 fuse_request_send(fc, req);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001756 err = req->out.h.error;
1757 fuse_put_request(fc, req);
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001758 if (err) {
1759 if (err == -EINTR)
1760 fuse_invalidate_attr(inode);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001761 goto error;
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001762 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001763
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001764 if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
1765 make_bad_inode(inode);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001766 err = -EIO;
1767 goto error;
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001768 }
1769
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001770 spin_lock(&fc->lock);
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001771 /* the kernel maintains i_mtime locally */
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001772 if (trust_local_cmtime) {
1773 if (attr->ia_valid & ATTR_MTIME)
1774 inode->i_mtime = attr->ia_mtime;
1775 if (attr->ia_valid & ATTR_CTIME)
1776 inode->i_ctime = attr->ia_ctime;
Miklos Szeredi1e18bda2014-04-28 14:19:23 +02001777 /* FIXME: clear I_DIRTY_SYNC? */
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001778 }
1779
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001780 fuse_change_attributes_common(inode, &outarg.attr,
1781 attr_timeout(&outarg));
1782 oldsize = inode->i_size;
Pavel Emelyanov83732002013-10-10 17:10:46 +04001783 /* see the comment in fuse_change_attributes() */
1784 if (!is_wb || is_truncate || !S_ISREG(inode->i_mode))
1785 i_size_write(inode, outarg.attr.size);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001786
1787 if (is_truncate) {
1788 /* NOTE: this may release/reacquire fc->lock */
1789 __fuse_release_nowrite(inode);
1790 }
1791 spin_unlock(&fc->lock);
1792
1793 /*
1794 * Only call invalidate_inode_pages2() after removing
1795 * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock.
1796 */
Pavel Emelyanov83732002013-10-10 17:10:46 +04001797 if ((is_truncate || !is_wb) &&
1798 S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
Kirill A. Shutemov7caef262013-09-12 15:13:56 -07001799 truncate_pagecache(inode, outarg.attr.size);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001800 invalidate_inode_pages2(inode->i_mapping);
1801 }
1802
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001803 clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001804 return 0;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001805
1806error:
1807 if (is_truncate)
1808 fuse_release_nowrite(inode);
1809
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001810 clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001811 return err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001812}
1813
Miklos Szeredi49d49142007-10-18 03:07:00 -07001814static int fuse_setattr(struct dentry *entry, struct iattr *attr)
1815{
Maxim Patlasovefb9fa92012-12-18 14:05:08 +04001816 struct inode *inode = entry->d_inode;
1817
1818 if (!fuse_allow_current_process(get_fuse_conn(inode)))
1819 return -EACCES;
1820
Miklos Szeredi49d49142007-10-18 03:07:00 -07001821 if (attr->ia_valid & ATTR_FILE)
Maxim Patlasovefb9fa92012-12-18 14:05:08 +04001822 return fuse_do_setattr(inode, attr, attr->ia_file);
Miklos Szeredi49d49142007-10-18 03:07:00 -07001823 else
Maxim Patlasovefb9fa92012-12-18 14:05:08 +04001824 return fuse_do_setattr(inode, attr, NULL);
Miklos Szeredi49d49142007-10-18 03:07:00 -07001825}
1826
Miklos Szeredie5e55582005-09-09 13:10:28 -07001827static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
1828 struct kstat *stat)
1829{
1830 struct inode *inode = entry->d_inode;
Miklos Szeredi244f6382007-10-16 23:31:02 -07001831 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi244f6382007-10-16 23:31:02 -07001832
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001833 if (!fuse_allow_current_process(fc))
Miklos Szeredi244f6382007-10-16 23:31:02 -07001834 return -EACCES;
1835
Miklos Szeredibcb4be82007-11-28 16:21:59 -08001836 return fuse_update_attributes(inode, stat, NULL, NULL);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001837}
1838
Miklos Szeredi92a87802005-09-09 13:10:31 -07001839static int fuse_setxattr(struct dentry *entry, const char *name,
1840 const void *value, size_t size, int flags)
1841{
1842 struct inode *inode = entry->d_inode;
1843 struct fuse_conn *fc = get_fuse_conn(inode);
1844 struct fuse_req *req;
1845 struct fuse_setxattr_in inarg;
1846 int err;
1847
Miklos Szeredi92a87802005-09-09 13:10:31 -07001848 if (fc->no_setxattr)
1849 return -EOPNOTSUPP;
1850
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001851 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001852 if (IS_ERR(req))
1853 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001854
1855 memset(&inarg, 0, sizeof(inarg));
1856 inarg.size = size;
1857 inarg.flags = flags;
1858 req->in.h.opcode = FUSE_SETXATTR;
1859 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001860 req->in.numargs = 3;
1861 req->in.args[0].size = sizeof(inarg);
1862 req->in.args[0].value = &inarg;
1863 req->in.args[1].size = strlen(name) + 1;
1864 req->in.args[1].value = name;
1865 req->in.args[2].size = size;
1866 req->in.args[2].value = value;
Tejun Heob93f8582008-11-26 12:03:55 +01001867 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001868 err = req->out.h.error;
1869 fuse_put_request(fc, req);
1870 if (err == -ENOSYS) {
1871 fc->no_setxattr = 1;
1872 err = -EOPNOTSUPP;
1873 }
Maxim Patlasov31f32672014-04-28 14:19:24 +02001874 if (!err) {
Anand Avatid331a412013-08-20 02:21:07 -04001875 fuse_invalidate_attr(inode);
Maxim Patlasov31f32672014-04-28 14:19:24 +02001876 fuse_update_ctime(inode);
1877 }
Miklos Szeredi92a87802005-09-09 13:10:31 -07001878 return err;
1879}
1880
1881static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
1882 void *value, size_t size)
1883{
1884 struct inode *inode = entry->d_inode;
1885 struct fuse_conn *fc = get_fuse_conn(inode);
1886 struct fuse_req *req;
1887 struct fuse_getxattr_in inarg;
1888 struct fuse_getxattr_out outarg;
1889 ssize_t ret;
1890
1891 if (fc->no_getxattr)
1892 return -EOPNOTSUPP;
1893
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001894 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001895 if (IS_ERR(req))
1896 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001897
1898 memset(&inarg, 0, sizeof(inarg));
1899 inarg.size = size;
1900 req->in.h.opcode = FUSE_GETXATTR;
1901 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001902 req->in.numargs = 2;
1903 req->in.args[0].size = sizeof(inarg);
1904 req->in.args[0].value = &inarg;
1905 req->in.args[1].size = strlen(name) + 1;
1906 req->in.args[1].value = name;
1907 /* This is really two different operations rolled into one */
1908 req->out.numargs = 1;
1909 if (size) {
1910 req->out.argvar = 1;
1911 req->out.args[0].size = size;
1912 req->out.args[0].value = value;
1913 } else {
1914 req->out.args[0].size = sizeof(outarg);
1915 req->out.args[0].value = &outarg;
1916 }
Tejun Heob93f8582008-11-26 12:03:55 +01001917 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001918 ret = req->out.h.error;
1919 if (!ret)
1920 ret = size ? req->out.args[0].size : outarg.size;
1921 else {
1922 if (ret == -ENOSYS) {
1923 fc->no_getxattr = 1;
1924 ret = -EOPNOTSUPP;
1925 }
1926 }
1927 fuse_put_request(fc, req);
1928 return ret;
1929}
1930
1931static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
1932{
1933 struct inode *inode = entry->d_inode;
1934 struct fuse_conn *fc = get_fuse_conn(inode);
1935 struct fuse_req *req;
1936 struct fuse_getxattr_in inarg;
1937 struct fuse_getxattr_out outarg;
1938 ssize_t ret;
1939
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001940 if (!fuse_allow_current_process(fc))
Miklos Szeredie57ac682007-10-18 03:06:58 -07001941 return -EACCES;
1942
Miklos Szeredi92a87802005-09-09 13:10:31 -07001943 if (fc->no_listxattr)
1944 return -EOPNOTSUPP;
1945
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001946 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001947 if (IS_ERR(req))
1948 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001949
1950 memset(&inarg, 0, sizeof(inarg));
1951 inarg.size = size;
1952 req->in.h.opcode = FUSE_LISTXATTR;
1953 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001954 req->in.numargs = 1;
1955 req->in.args[0].size = sizeof(inarg);
1956 req->in.args[0].value = &inarg;
1957 /* This is really two different operations rolled into one */
1958 req->out.numargs = 1;
1959 if (size) {
1960 req->out.argvar = 1;
1961 req->out.args[0].size = size;
1962 req->out.args[0].value = list;
1963 } else {
1964 req->out.args[0].size = sizeof(outarg);
1965 req->out.args[0].value = &outarg;
1966 }
Tejun Heob93f8582008-11-26 12:03:55 +01001967 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001968 ret = req->out.h.error;
1969 if (!ret)
1970 ret = size ? req->out.args[0].size : outarg.size;
1971 else {
1972 if (ret == -ENOSYS) {
1973 fc->no_listxattr = 1;
1974 ret = -EOPNOTSUPP;
1975 }
1976 }
1977 fuse_put_request(fc, req);
1978 return ret;
1979}
1980
1981static int fuse_removexattr(struct dentry *entry, const char *name)
1982{
1983 struct inode *inode = entry->d_inode;
1984 struct fuse_conn *fc = get_fuse_conn(inode);
1985 struct fuse_req *req;
1986 int err;
1987
1988 if (fc->no_removexattr)
1989 return -EOPNOTSUPP;
1990
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001991 req = fuse_get_req_nopages(fc);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001992 if (IS_ERR(req))
1993 return PTR_ERR(req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001994
1995 req->in.h.opcode = FUSE_REMOVEXATTR;
1996 req->in.h.nodeid = get_node_id(inode);
Miklos Szeredi92a87802005-09-09 13:10:31 -07001997 req->in.numargs = 1;
1998 req->in.args[0].size = strlen(name) + 1;
1999 req->in.args[0].value = name;
Tejun Heob93f8582008-11-26 12:03:55 +01002000 fuse_request_send(fc, req);
Miklos Szeredi92a87802005-09-09 13:10:31 -07002001 err = req->out.h.error;
2002 fuse_put_request(fc, req);
2003 if (err == -ENOSYS) {
2004 fc->no_removexattr = 1;
2005 err = -EOPNOTSUPP;
2006 }
Maxim Patlasov31f32672014-04-28 14:19:24 +02002007 if (!err) {
Anand Avatid331a412013-08-20 02:21:07 -04002008 fuse_invalidate_attr(inode);
Maxim Patlasov31f32672014-04-28 14:19:24 +02002009 fuse_update_ctime(inode);
2010 }
Miklos Szeredi92a87802005-09-09 13:10:31 -07002011 return err;
2012}
2013
Arjan van de Ven754661f2007-02-12 00:55:38 -08002014static const struct inode_operations fuse_dir_inode_operations = {
Miklos Szeredie5e55582005-09-09 13:10:28 -07002015 .lookup = fuse_lookup,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07002016 .mkdir = fuse_mkdir,
2017 .symlink = fuse_symlink,
2018 .unlink = fuse_unlink,
2019 .rmdir = fuse_rmdir,
2020 .rename = fuse_rename,
Miklos Szeredi1560c972014-04-28 16:43:44 +02002021 .rename2 = fuse_rename2,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07002022 .link = fuse_link,
2023 .setattr = fuse_setattr,
2024 .create = fuse_create,
Miklos Szeredic8ccbe02012-06-05 15:10:22 +02002025 .atomic_open = fuse_atomic_open,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07002026 .mknod = fuse_mknod,
Miklos Szeredie5e55582005-09-09 13:10:28 -07002027 .permission = fuse_permission,
2028 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07002029 .setxattr = fuse_setxattr,
2030 .getxattr = fuse_getxattr,
2031 .listxattr = fuse_listxattr,
2032 .removexattr = fuse_removexattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07002033};
2034
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -08002035static const struct file_operations fuse_dir_operations = {
Miklos Szeredib6aeade2005-09-09 13:10:30 -07002036 .llseek = generic_file_llseek,
Miklos Szeredie5e55582005-09-09 13:10:28 -07002037 .read = generic_read_dir,
Al Viro8d3af7f2013-05-18 03:03:58 -04002038 .iterate = fuse_readdir,
Miklos Szeredie5e55582005-09-09 13:10:28 -07002039 .open = fuse_dir_open,
2040 .release = fuse_dir_release,
Miklos Szeredi82547982005-09-09 13:10:38 -07002041 .fsync = fuse_dir_fsync,
Miklos Szeredib18da0c2011-12-13 11:58:49 +01002042 .unlocked_ioctl = fuse_dir_ioctl,
2043 .compat_ioctl = fuse_dir_compat_ioctl,
Miklos Szeredie5e55582005-09-09 13:10:28 -07002044};
2045
Arjan van de Ven754661f2007-02-12 00:55:38 -08002046static const struct inode_operations fuse_common_inode_operations = {
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07002047 .setattr = fuse_setattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07002048 .permission = fuse_permission,
2049 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07002050 .setxattr = fuse_setxattr,
2051 .getxattr = fuse_getxattr,
2052 .listxattr = fuse_listxattr,
2053 .removexattr = fuse_removexattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07002054};
2055
Arjan van de Ven754661f2007-02-12 00:55:38 -08002056static const struct inode_operations fuse_symlink_inode_operations = {
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07002057 .setattr = fuse_setattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07002058 .follow_link = fuse_follow_link,
2059 .put_link = fuse_put_link,
2060 .readlink = generic_readlink,
2061 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07002062 .setxattr = fuse_setxattr,
2063 .getxattr = fuse_getxattr,
2064 .listxattr = fuse_listxattr,
2065 .removexattr = fuse_removexattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07002066};
2067
2068void fuse_init_common(struct inode *inode)
2069{
2070 inode->i_op = &fuse_common_inode_operations;
2071}
2072
2073void fuse_init_dir(struct inode *inode)
2074{
2075 inode->i_op = &fuse_dir_inode_operations;
2076 inode->i_fop = &fuse_dir_operations;
2077}
2078
2079void fuse_init_symlink(struct inode *inode)
2080{
2081 inode->i_op = &fuse_symlink_inode_operations;
2082}