blob: a24f5a9750ddfbdfefbd375509ff9094b4a1cffb [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>
Seth Forshee703c7362016-08-29 08:46:36 -050016#include <linux/xattr.h>
Seth Forshee60bcc882016-08-29 08:46:37 -050017#include <linux/posix_acl.h>
Miklos Szeredie5e55582005-09-09 13:10:28 -070018
Al Viro8d3af7f2013-05-18 03:03:58 -040019static bool fuse_use_readdirplus(struct inode *dir, struct dir_context *ctx)
Feng Shuo4582a4a2013-01-15 11:23:28 +080020{
21 struct fuse_conn *fc = get_fuse_conn(dir);
22 struct fuse_inode *fi = get_fuse_inode(dir);
23
24 if (!fc->do_readdirplus)
25 return false;
Eric Wong634734b2013-02-06 22:29:01 +000026 if (!fc->readdirplus_auto)
27 return true;
Feng Shuo4582a4a2013-01-15 11:23:28 +080028 if (test_and_clear_bit(FUSE_I_ADVISE_RDPLUS, &fi->state))
29 return true;
Al Viro8d3af7f2013-05-18 03:03:58 -040030 if (ctx->pos == 0)
Feng Shuo4582a4a2013-01-15 11:23:28 +080031 return true;
32 return false;
33}
34
35static void fuse_advise_use_readdirplus(struct inode *dir)
36{
37 struct fuse_inode *fi = get_fuse_inode(dir);
38
39 set_bit(FUSE_I_ADVISE_RDPLUS, &fi->state);
40}
41
Miklos Szeredif75fdf22016-10-01 07:32:32 +020042union fuse_dentry {
43 u64 time;
44 struct rcu_head rcu;
45};
46
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070047static inline void fuse_dentry_settime(struct dentry *entry, u64 time)
48{
Miklos Szeredif75fdf22016-10-01 07:32:32 +020049 ((union fuse_dentry *) entry->d_fsdata)->time = time;
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070050}
51
52static inline u64 fuse_dentry_time(struct dentry *entry)
53{
Miklos Szeredif75fdf22016-10-01 07:32:32 +020054 return ((union fuse_dentry *) entry->d_fsdata)->time;
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070055}
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070056
Miklos Szeredi6f9f1182006-01-06 00:19:39 -080057/*
58 * FUSE caches dentries and attributes with separate timeout. The
59 * time in jiffies until the dentry/attributes are valid is stored in
Miklos Szeredif75fdf22016-10-01 07:32:32 +020060 * dentry->d_fsdata and fuse_inode->i_time respectively.
Miklos Szeredi6f9f1182006-01-06 00:19:39 -080061 */
62
63/*
64 * Calculate the time in jiffies until a dentry/attributes are valid
65 */
Miklos Szeredibcb6f6d2016-10-01 07:32:32 +020066static u64 time_to_jiffies(u64 sec, u32 nsec)
Miklos Szeredie5e55582005-09-09 13:10:28 -070067{
Miklos Szeredi685d16d2006-07-30 03:04:08 -070068 if (sec || nsec) {
Miklos Szeredibcb6f6d2016-10-01 07:32:32 +020069 struct timespec64 ts = {
70 sec,
David Sheets07f02672017-01-13 15:58:30 +000071 min_t(u32, nsec, NSEC_PER_SEC - 1)
Miklos Szeredibcb6f6d2016-10-01 07:32:32 +020072 };
73
74 return get_jiffies_64() + timespec64_to_jiffies(&ts);
Miklos Szeredi685d16d2006-07-30 03:04:08 -070075 } else
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070076 return 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -070077}
78
Miklos Szeredi6f9f1182006-01-06 00:19:39 -080079/*
80 * Set dentry and possibly attribute timeouts from the lookup/mk*
81 * replies
82 */
Miklos Szeredi1fb69e72007-10-18 03:06:58 -070083static void fuse_change_entry_timeout(struct dentry *entry,
84 struct fuse_entry_out *o)
Miklos Szeredi0aa7c692006-01-06 00:19:34 -080085{
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070086 fuse_dentry_settime(entry,
87 time_to_jiffies(o->entry_valid, o->entry_valid_nsec));
Miklos Szeredi1fb69e72007-10-18 03:06:58 -070088}
89
90static u64 attr_timeout(struct fuse_attr_out *o)
91{
92 return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
93}
94
95static u64 entry_attr_timeout(struct fuse_entry_out *o)
96{
97 return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -080098}
99
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800100/*
101 * Mark the attributes as stale, so that at the next call to
102 * ->getattr() they will be fetched from userspace
103 */
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800104void fuse_invalidate_attr(struct inode *inode)
105{
Miklos Szeredi0a0898c2006-07-30 03:04:10 -0700106 get_fuse_inode(inode)->i_time = 0;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800107}
108
Andrew Gallagher451418f2013-11-05 03:55:43 -0800109/**
110 * Mark the attributes as stale due to an atime change. Avoid the invalidate if
111 * atime is not used.
112 */
113void fuse_invalidate_atime(struct inode *inode)
114{
115 if (!IS_RDONLY(inode))
116 fuse_invalidate_attr(inode);
117}
118
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800119/*
120 * Just mark the entry as stale, so that a next attempt to look it up
121 * will result in a new lookup call to userspace
122 *
123 * This is called when a dentry is about to become negative and the
124 * timeout is unknown (unlink, rmdir, rename and in some cases
125 * lookup)
126 */
Miklos Szeredidbd561d2008-07-25 01:49:00 -0700127void fuse_invalidate_entry_cache(struct dentry *entry)
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800128{
Miklos Szeredi0a0898c2006-07-30 03:04:10 -0700129 fuse_dentry_settime(entry, 0);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800130}
131
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800132/*
133 * Same as fuse_invalidate_entry_cache(), but also try to remove the
134 * dentry from the hash
135 */
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800136static void fuse_invalidate_entry(struct dentry *entry)
137{
138 d_invalidate(entry);
139 fuse_invalidate_entry_cache(entry);
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800140}
141
Miklos Szeredi70781872014-12-12 09:49:05 +0100142static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_args *args,
Al Viro13983d02016-07-20 22:34:44 -0400143 u64 nodeid, const struct qstr *name,
Miklos Szeredie5e55582005-09-09 13:10:28 -0700144 struct fuse_entry_out *outarg)
145{
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700146 memset(outarg, 0, sizeof(struct fuse_entry_out));
Miklos Szeredi70781872014-12-12 09:49:05 +0100147 args->in.h.opcode = FUSE_LOOKUP;
148 args->in.h.nodeid = nodeid;
149 args->in.numargs = 1;
150 args->in.args[0].size = name->len + 1;
151 args->in.args[0].value = name->name;
152 args->out.numargs = 1;
Miklos Szeredi21f62172015-01-06 10:45:35 +0100153 args->out.args[0].size = sizeof(struct fuse_entry_out);
Miklos Szeredi70781872014-12-12 09:49:05 +0100154 args->out.args[0].value = outarg;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700155}
156
Miklos Szeredi5c5c5e52008-04-30 00:54:43 -0700157u64 fuse_get_attr_version(struct fuse_conn *fc)
Miklos Szeredi7dca9fd2007-11-28 16:21:59 -0800158{
159 u64 curr_version;
160
161 /*
162 * The spin lock isn't actually needed on 64bit archs, but we
163 * don't yet care too much about such optimizations.
164 */
165 spin_lock(&fc->lock);
166 curr_version = fc->attr_version;
167 spin_unlock(&fc->lock);
168
169 return curr_version;
170}
171
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800172/*
173 * Check whether the dentry is still valid
174 *
175 * If the entry validity timeout has expired and the dentry is
176 * positive, try to redo the lookup. If the lookup results in a
177 * different inode, then let the VFS invalidate the dentry and redo
178 * the lookup once more. If the lookup results in the same inode,
179 * then refresh the attributes, timeouts and mark the dentry valid.
180 */
Al Viro0b728e12012-06-10 16:03:43 -0400181static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700182{
Nick Piggin34286d62011-01-07 17:49:57 +1100183 struct inode *inode;
Miklos Szeredi28420da2013-06-03 14:40:22 +0200184 struct dentry *parent;
185 struct fuse_conn *fc;
Miklos Szeredi6314efe2013-10-01 16:41:22 +0200186 struct fuse_inode *fi;
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200187 int ret;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800188
David Howells2b0143b2015-03-17 22:25:59 +0000189 inode = d_inode_rcu(entry);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800190 if (inode && is_bad_inode(inode))
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200191 goto invalid;
Anand Avati154210c2014-06-26 20:21:57 -0400192 else if (time_before64(fuse_dentry_time(entry), get_jiffies_64()) ||
193 (flags & LOOKUP_REVAL)) {
Miklos Szeredie5e55582005-09-09 13:10:28 -0700194 struct fuse_entry_out outarg;
Miklos Szeredi70781872014-12-12 09:49:05 +0100195 FUSE_ARGS(args);
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100196 struct fuse_forget_link *forget;
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700197 u64 attr_version;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800198
Miklos Szeredi50322fe2006-02-28 16:59:03 -0800199 /* For negative dentries, always do a fresh lookup */
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800200 if (!inode)
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200201 goto invalid;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800202
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200203 ret = -ECHILD;
Al Viro0b728e12012-06-10 16:03:43 -0400204 if (flags & LOOKUP_RCU)
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200205 goto out;
Miklos Szeredie7c0a162011-03-21 13:58:06 +0100206
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800207 fc = get_fuse_conn(inode);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700208
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100209 forget = fuse_alloc_forget();
Miklos Szeredi70781872014-12-12 09:49:05 +0100210 ret = -ENOMEM;
211 if (!forget)
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200212 goto out;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800213
Miklos Szeredi7dca9fd2007-11-28 16:21:59 -0800214 attr_version = fuse_get_attr_version(fc);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700215
Miklos Szeredie956edd2006-10-17 00:10:12 -0700216 parent = dget_parent(entry);
David Howells2b0143b2015-03-17 22:25:59 +0000217 fuse_lookup_init(fc, &args, get_node_id(d_inode(parent)),
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700218 &entry->d_name, &outarg);
Miklos Szeredi70781872014-12-12 09:49:05 +0100219 ret = fuse_simple_request(fc, &args);
Miklos Szeredie956edd2006-10-17 00:10:12 -0700220 dput(parent);
Miklos Szeredi50322fe2006-02-28 16:59:03 -0800221 /* Zero nodeid is same as -ENOENT */
Miklos Szeredi70781872014-12-12 09:49:05 +0100222 if (!ret && !outarg.nodeid)
223 ret = -ENOENT;
224 if (!ret) {
Miklos Szeredi6314efe2013-10-01 16:41:22 +0200225 fi = get_fuse_inode(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700226 if (outarg.nodeid != get_node_id(inode)) {
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100227 fuse_queue_forget(fc, forget, outarg.nodeid, 1);
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200228 goto invalid;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700229 }
Miklos Szeredi8da5ff22006-10-17 00:10:08 -0700230 spin_lock(&fc->lock);
Miklos Szeredi1729a162008-11-26 12:03:54 +0100231 fi->nlookup++;
Miklos Szeredi8da5ff22006-10-17 00:10:08 -0700232 spin_unlock(&fc->lock);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700233 }
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100234 kfree(forget);
Miklos Szeredi70781872014-12-12 09:49:05 +0100235 if (ret == -ENOMEM)
236 goto out;
Miklos Szeredic392b3a2019-11-12 11:49:04 +0100237 if (ret || fuse_invalid_attr(&outarg.attr) ||
238 (outarg.attr.mode ^ inode->i_mode) & S_IFMT)
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200239 goto invalid;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700240
Seth Forshee60bcc882016-08-29 08:46:37 -0500241 forget_all_cached_acls(inode);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700242 fuse_change_attributes(inode, &outarg.attr,
243 entry_attr_timeout(&outarg),
244 attr_version);
245 fuse_change_entry_timeout(entry, &outarg);
Miklos Szeredi28420da2013-06-03 14:40:22 +0200246 } else if (inode) {
Miklos Szeredi6314efe2013-10-01 16:41:22 +0200247 fi = get_fuse_inode(inode);
248 if (flags & LOOKUP_RCU) {
249 if (test_bit(FUSE_I_INIT_RDPLUS, &fi->state))
250 return -ECHILD;
251 } else if (test_and_clear_bit(FUSE_I_INIT_RDPLUS, &fi->state)) {
Miklos Szeredi28420da2013-06-03 14:40:22 +0200252 parent = dget_parent(entry);
David Howells2b0143b2015-03-17 22:25:59 +0000253 fuse_advise_use_readdirplus(d_inode(parent));
Miklos Szeredi28420da2013-06-03 14:40:22 +0200254 dput(parent);
255 }
Miklos Szeredie5e55582005-09-09 13:10:28 -0700256 }
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200257 ret = 1;
258out:
259 return ret;
260
261invalid:
262 ret = 0;
263 goto out;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700264}
265
Daniel Rosenbergfac99a72016-04-22 00:00:48 -0700266/*
267 * Get the canonical path. Since we must translate to a path, this must be done
268 * in the context of the userspace daemon, however, the userspace daemon cannot
269 * look up paths on its own. Instead, we handle the lookup as a special case
270 * inside of the write request.
271 */
272static void fuse_dentry_canonical_path(const struct path *path, struct path *canonical_path) {
273 struct inode *inode = path->dentry->d_inode;
274 struct fuse_conn *fc = get_fuse_conn(inode);
275 struct fuse_req *req;
276 int err;
277 char *path_name;
278
279 req = fuse_get_req(fc, 1);
280 err = PTR_ERR(req);
281 if (IS_ERR(req))
282 goto default_path;
283
284 path_name = (char*)__get_free_page(GFP_KERNEL);
285 if (!path_name) {
286 fuse_put_request(fc, req);
287 goto default_path;
288 }
289
290 req->in.h.opcode = FUSE_CANONICAL_PATH;
291 req->in.h.nodeid = get_node_id(inode);
292 req->in.numargs = 0;
293 req->out.numargs = 1;
294 req->out.args[0].size = PATH_MAX;
295 req->out.args[0].value = path_name;
296 req->canonical_path = canonical_path;
297 req->out.argvar = 1;
298 fuse_request_send(fc, req);
299 err = req->out.h.error;
300 fuse_put_request(fc, req);
301 free_page((unsigned long)path_name);
302 if (!err)
303 return;
304default_path:
305 canonical_path->dentry = path->dentry;
306 canonical_path->mnt = path->mnt;
307 path_get(canonical_path);
308}
309
Miklos Szeredi8bfc0162006-01-16 22:14:28 -0800310static int invalid_nodeid(u64 nodeid)
Miklos Szeredi2827d0b22005-11-28 13:44:16 -0800311{
312 return !nodeid || nodeid == FUSE_ROOT_ID;
313}
314
Miklos Szeredif75fdf22016-10-01 07:32:32 +0200315static int fuse_dentry_init(struct dentry *dentry)
316{
317 dentry->d_fsdata = kzalloc(sizeof(union fuse_dentry), GFP_KERNEL);
318
319 return dentry->d_fsdata ? 0 : -ENOMEM;
320}
321static void fuse_dentry_release(struct dentry *dentry)
322{
323 union fuse_dentry *fd = dentry->d_fsdata;
324
325 kfree_rcu(fd, rcu);
326}
327
Al Viro42695902009-02-20 05:59:13 +0000328const struct dentry_operations fuse_dentry_operations = {
Miklos Szeredie5e55582005-09-09 13:10:28 -0700329 .d_revalidate = fuse_dentry_revalidate,
Miklos Szeredif75fdf22016-10-01 07:32:32 +0200330 .d_init = fuse_dentry_init,
331 .d_release = fuse_dentry_release,
Daniel Rosenbergfac99a72016-04-22 00:00:48 -0700332 .d_canonical_path = fuse_dentry_canonical_path,
Miklos Szeredie5e55582005-09-09 13:10:28 -0700333};
334
Miklos Szeredi0ce267f2016-10-18 15:36:48 +0200335const struct dentry_operations fuse_root_dentry_operations = {
336 .d_init = fuse_dentry_init,
337 .d_release = fuse_dentry_release,
Daniel Rosenbergfac99a72016-04-22 00:00:48 -0700338 .d_canonical_path = fuse_dentry_canonical_path,
Miklos Szeredi0ce267f2016-10-18 15:36:48 +0200339};
340
Timo Savolaa5bfffac2007-04-08 16:04:00 -0700341int fuse_valid_type(int m)
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800342{
343 return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) ||
344 S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m);
345}
346
Miklos Szeredic392b3a2019-11-12 11:49:04 +0100347bool fuse_invalid_attr(struct fuse_attr *attr)
348{
349 return !fuse_valid_type(attr->mode) ||
350 attr->size > LLONG_MAX;
351}
352
Al Viro13983d02016-07-20 22:34:44 -0400353int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name,
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700354 struct fuse_entry_out *outarg, struct inode **inode)
355{
356 struct fuse_conn *fc = get_fuse_conn_super(sb);
Miklos Szeredi70781872014-12-12 09:49:05 +0100357 FUSE_ARGS(args);
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100358 struct fuse_forget_link *forget;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700359 u64 attr_version;
360 int err;
361
362 *inode = NULL;
363 err = -ENAMETOOLONG;
364 if (name->len > FUSE_NAME_MAX)
365 goto out;
366
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700367
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100368 forget = fuse_alloc_forget();
369 err = -ENOMEM;
Miklos Szeredi70781872014-12-12 09:49:05 +0100370 if (!forget)
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700371 goto out;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700372
373 attr_version = fuse_get_attr_version(fc);
374
Miklos Szeredi70781872014-12-12 09:49:05 +0100375 fuse_lookup_init(fc, &args, nodeid, name, outarg);
376 err = fuse_simple_request(fc, &args);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700377 /* Zero nodeid is same as -ENOENT, but with valid timeout */
378 if (err || !outarg->nodeid)
379 goto out_put_forget;
380
381 err = -EIO;
382 if (!outarg->nodeid)
383 goto out_put_forget;
Miklos Szeredic392b3a2019-11-12 11:49:04 +0100384 if (fuse_invalid_attr(&outarg->attr))
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700385 goto out_put_forget;
386
387 *inode = fuse_iget(sb, outarg->nodeid, outarg->generation,
388 &outarg->attr, entry_attr_timeout(outarg),
389 attr_version);
390 err = -ENOMEM;
391 if (!*inode) {
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100392 fuse_queue_forget(fc, forget, outarg->nodeid, 1);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700393 goto out;
394 }
395 err = 0;
396
397 out_put_forget:
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100398 kfree(forget);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700399 out:
400 return err;
401}
402
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800403static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
Al Viro00cd8dd2012-06-10 17:13:09 -0400404 unsigned int flags)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700405{
406 int err;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700407 struct fuse_entry_out outarg;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700408 struct inode *inode;
Miklos Szeredi0de62562008-07-25 01:48:59 -0700409 struct dentry *newent;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700410 bool outarg_valid = true;
Miklos Szeredi68fbfcb2018-07-26 16:13:11 +0200411 bool locked;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700412
Miklos Szeredi68fbfcb2018-07-26 16:13:11 +0200413 locked = fuse_lock_inode(dir);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700414 err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name,
415 &outarg, &inode);
Miklos Szeredi68fbfcb2018-07-26 16:13:11 +0200416 fuse_unlock_inode(dir, locked);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700417 if (err == -ENOENT) {
418 outarg_valid = false;
419 err = 0;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800420 }
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700421 if (err)
422 goto out_err;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800423
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700424 err = -EIO;
425 if (inode && get_node_id(inode) == FUSE_ROOT_ID)
426 goto out_iput;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700427
Al Viro41d28bc2014-10-12 22:24:21 -0400428 newent = d_splice_alias(inode, entry);
Miklos Szeredi5835f332013-09-05 11:44:42 +0200429 err = PTR_ERR(newent);
430 if (IS_ERR(newent))
431 goto out_err;
Miklos Szeredid2a85162006-10-17 00:10:11 -0700432
Miklos Szeredi0de62562008-07-25 01:48:59 -0700433 entry = newent ? newent : entry;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700434 if (outarg_valid)
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700435 fuse_change_entry_timeout(entry, &outarg);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800436 else
437 fuse_invalidate_entry_cache(entry);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700438
Feng Shuo4582a4a2013-01-15 11:23:28 +0800439 fuse_advise_use_readdirplus(dir);
Miklos Szeredi0de62562008-07-25 01:48:59 -0700440 return newent;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700441
442 out_iput:
443 iput(inode);
444 out_err:
445 return ERR_PTR(err);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700446}
447
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800448/*
449 * Atomic create+open operation
450 *
451 * If the filesystem doesn't support this, then fall back to separate
452 * 'mknod' + 'open' requests.
453 */
Al Virod9585272012-06-22 12:39:14 +0400454static int fuse_create_open(struct inode *dir, struct dentry *entry,
Al Viro30d90492012-06-22 12:40:19 +0400455 struct file *file, unsigned flags,
Al Virod9585272012-06-22 12:39:14 +0400456 umode_t mode, int *opened)
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800457{
458 int err;
459 struct inode *inode;
460 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredi70781872014-12-12 09:49:05 +0100461 FUSE_ARGS(args);
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100462 struct fuse_forget_link *forget;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200463 struct fuse_create_in inarg;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800464 struct fuse_open_out outopen;
465 struct fuse_entry_out outentry;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800466 struct fuse_file *ff;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800467
Miklos Szerediaf109bc2012-08-15 13:01:24 +0200468 /* Userspace expects S_IFREG in create mode */
469 BUG_ON((mode & S_IFMT) != S_IFREG);
470
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100471 forget = fuse_alloc_forget();
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200472 err = -ENOMEM;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100473 if (!forget)
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200474 goto out_err;
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700475
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700476 err = -ENOMEM;
Tejun Heoacf99432008-11-26 12:03:55 +0100477 ff = fuse_file_alloc(fc);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800478 if (!ff)
Miklos Szeredi70781872014-12-12 09:49:05 +0100479 goto out_put_forget_req;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800480
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200481 if (!fc->dont_mask)
482 mode &= ~current_umask();
483
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800484 flags &= ~O_NOCTTY;
485 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700486 memset(&outentry, 0, sizeof(outentry));
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800487 inarg.flags = flags;
488 inarg.mode = mode;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200489 inarg.umask = current_umask();
Miklos Szeredi70781872014-12-12 09:49:05 +0100490 args.in.h.opcode = FUSE_CREATE;
491 args.in.h.nodeid = get_node_id(dir);
492 args.in.numargs = 2;
Miklos Szeredi21f62172015-01-06 10:45:35 +0100493 args.in.args[0].size = sizeof(inarg);
Miklos Szeredi70781872014-12-12 09:49:05 +0100494 args.in.args[0].value = &inarg;
495 args.in.args[1].size = entry->d_name.len + 1;
496 args.in.args[1].value = entry->d_name.name;
497 args.out.numargs = 2;
Miklos Szeredi21f62172015-01-06 10:45:35 +0100498 args.out.args[0].size = sizeof(outentry);
Miklos Szeredi70781872014-12-12 09:49:05 +0100499 args.out.args[0].value = &outentry;
500 args.out.args[1].size = sizeof(outopen);
501 args.out.args[1].value = &outopen;
Nikhilesh Reddy759832b2017-07-26 09:41:57 +0530502 args.out.passthrough_filp = NULL;
Miklos Szeredi70781872014-12-12 09:49:05 +0100503 err = fuse_simple_request(fc, &args);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200504 if (err)
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800505 goto out_free_ff;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800506
507 err = -EIO;
Miklos Szeredic392b3a2019-11-12 11:49:04 +0100508 if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid) ||
509 fuse_invalid_attr(&outentry.attr))
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800510 goto out_free_ff;
511
Miklos Szeredic7b71432009-04-28 16:56:37 +0200512 ff->fh = outopen.fh;
513 ff->nodeid = outentry.nodeid;
514 ff->open_flags = outopen.open_flags;
Nikhilesh Reddy759832b2017-07-26 09:41:57 +0530515 if (args.out.passthrough_filp != NULL)
516 ff->passthrough_filp = args.out.passthrough_filp;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800517 inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700518 &outentry.attr, entry_attr_timeout(&outentry), 0);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800519 if (!inode) {
520 flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
Miklos Szeredi8b0797a2009-04-28 16:56:39 +0200521 fuse_sync_release(ff, flags);
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100522 fuse_queue_forget(fc, forget, outentry.nodeid, 1);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200523 err = -ENOMEM;
524 goto out_err;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800525 }
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100526 kfree(forget);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800527 d_instantiate(entry, inode);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700528 fuse_change_entry_timeout(entry, &outentry);
Miklos Szeredi0952b2a2008-02-06 01:38:38 -0800529 fuse_invalidate_attr(dir);
Al Viro30d90492012-06-22 12:40:19 +0400530 err = finish_open(file, entry, generic_file_open, opened);
531 if (err) {
Miklos Szeredi8b0797a2009-04-28 16:56:39 +0200532 fuse_sync_release(ff, flags);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200533 } else {
534 file->private_data = fuse_file_get(ff);
535 fuse_finish_open(inode, file);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800536 }
Al Virod9585272012-06-22 12:39:14 +0400537 return err;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800538
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200539out_free_ff:
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800540 fuse_file_free(ff);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200541out_put_forget_req:
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100542 kfree(forget);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200543out_err:
Al Virod9585272012-06-22 12:39:14 +0400544 return err;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200545}
546
547static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t);
Al Virod9585272012-06-22 12:39:14 +0400548static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
Al Viro30d90492012-06-22 12:40:19 +0400549 struct file *file, unsigned flags,
Al Virod9585272012-06-22 12:39:14 +0400550 umode_t mode, int *opened)
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200551{
552 int err;
553 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200554 struct dentry *res = NULL;
555
Al Viro00699ad2016-07-05 09:44:53 -0400556 if (d_in_lookup(entry)) {
Al Viro00cd8dd2012-06-10 17:13:09 -0400557 res = fuse_lookup(dir, entry, 0);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200558 if (IS_ERR(res))
Al Virod9585272012-06-22 12:39:14 +0400559 return PTR_ERR(res);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200560
561 if (res)
562 entry = res;
563 }
564
David Howells2b0143b2015-03-17 22:25:59 +0000565 if (!(flags & O_CREAT) || d_really_is_positive(entry))
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200566 goto no_open;
567
568 /* Only creates */
Al Viro47237682012-06-10 05:01:45 -0400569 *opened |= FILE_CREATED;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200570
571 if (fc->no_create)
572 goto mknod;
573
Al Viro30d90492012-06-22 12:40:19 +0400574 err = fuse_create_open(dir, entry, file, flags, mode, opened);
Al Virod9585272012-06-22 12:39:14 +0400575 if (err == -ENOSYS) {
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200576 fc->no_create = 1;
577 goto mknod;
578 }
579out_dput:
580 dput(res);
Al Virod9585272012-06-22 12:39:14 +0400581 return err;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200582
583mknod:
584 err = fuse_mknod(dir, entry, mode, 0);
Al Virod9585272012-06-22 12:39:14 +0400585 if (err)
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200586 goto out_dput;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200587no_open:
Al Viroe45198a2012-06-10 06:48:09 -0400588 return finish_no_open(file, res);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800589}
590
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800591/*
592 * Code shared between mknod, mkdir, symlink and link
593 */
Miklos Szeredi70781872014-12-12 09:49:05 +0100594static int create_new_entry(struct fuse_conn *fc, struct fuse_args *args,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700595 struct inode *dir, struct dentry *entry,
Al Viro541af6a2011-07-26 03:17:33 -0400596 umode_t mode)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700597{
598 struct fuse_entry_out outarg;
599 struct inode *inode;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700600 int err;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100601 struct fuse_forget_link *forget;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800602
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100603 forget = fuse_alloc_forget();
Miklos Szeredi70781872014-12-12 09:49:05 +0100604 if (!forget)
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100605 return -ENOMEM;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700606
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700607 memset(&outarg, 0, sizeof(outarg));
Miklos Szeredi70781872014-12-12 09:49:05 +0100608 args->in.h.nodeid = get_node_id(dir);
609 args->out.numargs = 1;
Miklos Szeredi21f62172015-01-06 10:45:35 +0100610 args->out.args[0].size = sizeof(outarg);
Miklos Szeredi70781872014-12-12 09:49:05 +0100611 args->out.args[0].value = &outarg;
612 err = fuse_simple_request(fc, args);
Miklos Szeredi2d510132006-11-25 11:09:20 -0800613 if (err)
614 goto out_put_forget_req;
615
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800616 err = -EIO;
Miklos Szeredic392b3a2019-11-12 11:49:04 +0100617 if (invalid_nodeid(outarg.nodeid) || fuse_invalid_attr(&outarg.attr))
Miklos Szeredi2d510132006-11-25 11:09:20 -0800618 goto out_put_forget_req;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800619
620 if ((outarg.attr.mode ^ mode) & S_IFMT)
Miklos Szeredi2d510132006-11-25 11:09:20 -0800621 goto out_put_forget_req;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800622
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700623 inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700624 &outarg.attr, entry_attr_timeout(&outarg), 0);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700625 if (!inode) {
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100626 fuse_queue_forget(fc, forget, outarg.nodeid, 1);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700627 return -ENOMEM;
628 }
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100629 kfree(forget);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700630
Miklos Szeredib70a80e2013-10-01 16:44:54 +0200631 err = d_instantiate_no_diralias(entry, inode);
632 if (err)
633 return err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700634
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700635 fuse_change_entry_timeout(entry, &outarg);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700636 fuse_invalidate_attr(dir);
637 return 0;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800638
Miklos Szeredi2d510132006-11-25 11:09:20 -0800639 out_put_forget_req:
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100640 kfree(forget);
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800641 return err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700642}
643
Al Viro1a67aaf2011-07-26 01:52:52 -0400644static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700645 dev_t rdev)
646{
647 struct fuse_mknod_in inarg;
648 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredi70781872014-12-12 09:49:05 +0100649 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700650
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200651 if (!fc->dont_mask)
652 mode &= ~current_umask();
653
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700654 memset(&inarg, 0, sizeof(inarg));
655 inarg.mode = mode;
656 inarg.rdev = new_encode_dev(rdev);
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200657 inarg.umask = current_umask();
Miklos Szeredi70781872014-12-12 09:49:05 +0100658 args.in.h.opcode = FUSE_MKNOD;
659 args.in.numargs = 2;
Miklos Szeredi21f62172015-01-06 10:45:35 +0100660 args.in.args[0].size = sizeof(inarg);
Miklos Szeredi70781872014-12-12 09:49:05 +0100661 args.in.args[0].value = &inarg;
662 args.in.args[1].size = entry->d_name.len + 1;
663 args.in.args[1].value = entry->d_name.name;
664 return create_new_entry(fc, &args, dir, entry, mode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700665}
666
Al Viro4acdaf22011-07-26 01:42:34 -0400667static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode,
Al Viroebfc3b42012-06-10 18:05:36 -0400668 bool excl)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700669{
670 return fuse_mknod(dir, entry, mode, 0);
671}
672
Al Viro18bb1db2011-07-26 01:41:39 -0400673static int fuse_mkdir(struct inode *dir, struct dentry *entry, umode_t mode)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700674{
675 struct fuse_mkdir_in inarg;
676 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredi70781872014-12-12 09:49:05 +0100677 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700678
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200679 if (!fc->dont_mask)
680 mode &= ~current_umask();
681
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700682 memset(&inarg, 0, sizeof(inarg));
683 inarg.mode = mode;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200684 inarg.umask = current_umask();
Miklos Szeredi70781872014-12-12 09:49:05 +0100685 args.in.h.opcode = FUSE_MKDIR;
686 args.in.numargs = 2;
687 args.in.args[0].size = sizeof(inarg);
688 args.in.args[0].value = &inarg;
689 args.in.args[1].size = entry->d_name.len + 1;
690 args.in.args[1].value = entry->d_name.name;
691 return create_new_entry(fc, &args, dir, entry, S_IFDIR);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700692}
693
694static int fuse_symlink(struct inode *dir, struct dentry *entry,
695 const char *link)
696{
697 struct fuse_conn *fc = get_fuse_conn(dir);
698 unsigned len = strlen(link) + 1;
Miklos Szeredi70781872014-12-12 09:49:05 +0100699 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700700
Miklos Szeredi70781872014-12-12 09:49:05 +0100701 args.in.h.opcode = FUSE_SYMLINK;
702 args.in.numargs = 2;
703 args.in.args[0].size = entry->d_name.len + 1;
704 args.in.args[0].value = entry->d_name.name;
705 args.in.args[1].size = len;
706 args.in.args[1].value = link;
707 return create_new_entry(fc, &args, dir, entry, S_IFLNK);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700708}
709
Seth Forshee703c7362016-08-29 08:46:36 -0500710void fuse_update_ctime(struct inode *inode)
Maxim Patlasov31f32672014-04-28 14:19:24 +0200711{
712 if (!IS_NOCMTIME(inode)) {
Deepa Dinamanic2050a42016-09-14 07:48:06 -0700713 inode->i_ctime = current_time(inode);
Maxim Patlasov31f32672014-04-28 14:19:24 +0200714 mark_inode_dirty_sync(inode);
715 }
716}
717
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700718static int fuse_unlink(struct inode *dir, struct dentry *entry)
719{
720 int err;
721 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredi70781872014-12-12 09:49:05 +0100722 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700723
Miklos Szeredi70781872014-12-12 09:49:05 +0100724 args.in.h.opcode = FUSE_UNLINK;
725 args.in.h.nodeid = get_node_id(dir);
726 args.in.numargs = 1;
727 args.in.args[0].size = entry->d_name.len + 1;
728 args.in.args[0].value = entry->d_name.name;
729 err = fuse_simple_request(fc, &args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700730 if (!err) {
David Howells2b0143b2015-03-17 22:25:59 +0000731 struct inode *inode = d_inode(entry);
Miklos Szerediac45d612012-03-05 15:48:11 +0100732 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700733
Miklos Szerediac45d612012-03-05 15:48:11 +0100734 spin_lock(&fc->lock);
735 fi->attr_version = ++fc->attr_version;
Miklos Szeredidfca7ce2013-02-04 15:57:42 +0100736 /*
737 * If i_nlink == 0 then unlink doesn't make sense, yet this can
738 * happen if userspace filesystem is careless. It would be
739 * difficult to enforce correct nlink usage so just ignore this
740 * condition here
741 */
742 if (inode->i_nlink > 0)
743 drop_nlink(inode);
Miklos Szerediac45d612012-03-05 15:48:11 +0100744 spin_unlock(&fc->lock);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700745 fuse_invalidate_attr(inode);
746 fuse_invalidate_attr(dir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800747 fuse_invalidate_entry_cache(entry);
Maxim Patlasov31f32672014-04-28 14:19:24 +0200748 fuse_update_ctime(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700749 } else if (err == -EINTR)
750 fuse_invalidate_entry(entry);
751 return err;
752}
753
754static int fuse_rmdir(struct inode *dir, struct dentry *entry)
755{
756 int err;
757 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredi70781872014-12-12 09:49:05 +0100758 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700759
Miklos Szeredi70781872014-12-12 09:49:05 +0100760 args.in.h.opcode = FUSE_RMDIR;
761 args.in.h.nodeid = get_node_id(dir);
762 args.in.numargs = 1;
763 args.in.args[0].size = entry->d_name.len + 1;
764 args.in.args[0].value = entry->d_name.name;
765 err = fuse_simple_request(fc, &args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700766 if (!err) {
David Howells2b0143b2015-03-17 22:25:59 +0000767 clear_nlink(d_inode(entry));
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700768 fuse_invalidate_attr(dir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800769 fuse_invalidate_entry_cache(entry);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700770 } else if (err == -EINTR)
771 fuse_invalidate_entry(entry);
772 return err;
773}
774
Miklos Szeredi1560c972014-04-28 16:43:44 +0200775static int fuse_rename_common(struct inode *olddir, struct dentry *oldent,
776 struct inode *newdir, struct dentry *newent,
777 unsigned int flags, int opcode, size_t argsize)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700778{
779 int err;
Miklos Szeredi1560c972014-04-28 16:43:44 +0200780 struct fuse_rename2_in inarg;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700781 struct fuse_conn *fc = get_fuse_conn(olddir);
Miklos Szeredi70781872014-12-12 09:49:05 +0100782 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700783
Miklos Szeredi1560c972014-04-28 16:43:44 +0200784 memset(&inarg, 0, argsize);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700785 inarg.newdir = get_node_id(newdir);
Miklos Szeredi1560c972014-04-28 16:43:44 +0200786 inarg.flags = flags;
Miklos Szeredi70781872014-12-12 09:49:05 +0100787 args.in.h.opcode = opcode;
788 args.in.h.nodeid = get_node_id(olddir);
789 args.in.numargs = 3;
790 args.in.args[0].size = argsize;
791 args.in.args[0].value = &inarg;
792 args.in.args[1].size = oldent->d_name.len + 1;
793 args.in.args[1].value = oldent->d_name.name;
794 args.in.args[2].size = newent->d_name.len + 1;
795 args.in.args[2].value = newent->d_name.name;
796 err = fuse_simple_request(fc, &args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700797 if (!err) {
Miklos Szeredi08b63302007-11-28 16:22:03 -0800798 /* ctime changes */
David Howells2b0143b2015-03-17 22:25:59 +0000799 fuse_invalidate_attr(d_inode(oldent));
800 fuse_update_ctime(d_inode(oldent));
Miklos Szeredi08b63302007-11-28 16:22:03 -0800801
Miklos Szeredi1560c972014-04-28 16:43:44 +0200802 if (flags & RENAME_EXCHANGE) {
David Howells2b0143b2015-03-17 22:25:59 +0000803 fuse_invalidate_attr(d_inode(newent));
804 fuse_update_ctime(d_inode(newent));
Miklos Szeredi1560c972014-04-28 16:43:44 +0200805 }
806
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700807 fuse_invalidate_attr(olddir);
808 if (olddir != newdir)
809 fuse_invalidate_attr(newdir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800810
811 /* newent will end up negative */
David Howells2b0143b2015-03-17 22:25:59 +0000812 if (!(flags & RENAME_EXCHANGE) && d_really_is_positive(newent)) {
813 fuse_invalidate_attr(d_inode(newent));
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800814 fuse_invalidate_entry_cache(newent);
David Howells2b0143b2015-03-17 22:25:59 +0000815 fuse_update_ctime(d_inode(newent));
Miklos Szeredi5219f342009-11-04 10:24:52 +0100816 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700817 } else if (err == -EINTR) {
818 /* If request was interrupted, DEITY only knows if the
819 rename actually took place. If the invalidation
820 fails (e.g. some process has CWD under the renamed
821 directory), then there can be inconsistency between
822 the dcache and the real filesystem. Tough luck. */
823 fuse_invalidate_entry(oldent);
David Howells2b0143b2015-03-17 22:25:59 +0000824 if (d_really_is_positive(newent))
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700825 fuse_invalidate_entry(newent);
826 }
827
828 return err;
829}
830
Miklos Szeredi1560c972014-04-28 16:43:44 +0200831static int fuse_rename2(struct inode *olddir, struct dentry *oldent,
832 struct inode *newdir, struct dentry *newent,
833 unsigned int flags)
834{
835 struct fuse_conn *fc = get_fuse_conn(olddir);
836 int err;
837
838 if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE))
839 return -EINVAL;
840
Miklos Szeredi4237ba42014-07-10 10:50:19 +0200841 if (flags) {
842 if (fc->no_rename2 || fc->minor < 23)
843 return -EINVAL;
Miklos Szeredi1560c972014-04-28 16:43:44 +0200844
Miklos Szeredi4237ba42014-07-10 10:50:19 +0200845 err = fuse_rename_common(olddir, oldent, newdir, newent, flags,
846 FUSE_RENAME2,
847 sizeof(struct fuse_rename2_in));
848 if (err == -ENOSYS) {
849 fc->no_rename2 = 1;
850 err = -EINVAL;
851 }
852 } else {
853 err = fuse_rename_common(olddir, oldent, newdir, newent, 0,
854 FUSE_RENAME,
855 sizeof(struct fuse_rename_in));
Miklos Szeredi1560c972014-04-28 16:43:44 +0200856 }
Miklos Szeredi1560c972014-04-28 16:43:44 +0200857
Miklos Szeredi4237ba42014-07-10 10:50:19 +0200858 return err;
859}
860
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700861static int fuse_link(struct dentry *entry, struct inode *newdir,
862 struct dentry *newent)
863{
864 int err;
865 struct fuse_link_in inarg;
David Howells2b0143b2015-03-17 22:25:59 +0000866 struct inode *inode = d_inode(entry);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700867 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi70781872014-12-12 09:49:05 +0100868 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700869
870 memset(&inarg, 0, sizeof(inarg));
871 inarg.oldnodeid = get_node_id(inode);
Miklos Szeredi70781872014-12-12 09:49:05 +0100872 args.in.h.opcode = FUSE_LINK;
873 args.in.numargs = 2;
874 args.in.args[0].size = sizeof(inarg);
875 args.in.args[0].value = &inarg;
876 args.in.args[1].size = newent->d_name.len + 1;
877 args.in.args[1].value = newent->d_name.name;
878 err = create_new_entry(fc, &args, newdir, newent, inode->i_mode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700879 /* Contrary to "normal" filesystems it can happen that link
880 makes two "logical" inodes point to the same "physical"
881 inode. We invalidate the attributes of the old one, so it
882 will reflect changes in the backing inode (link count,
883 etc.)
884 */
Miklos Szerediac45d612012-03-05 15:48:11 +0100885 if (!err) {
886 struct fuse_inode *fi = get_fuse_inode(inode);
887
888 spin_lock(&fc->lock);
889 fi->attr_version = ++fc->attr_version;
Miklos Szeredi38969fe2019-11-12 11:49:04 +0100890 if (likely(inode->i_nlink < UINT_MAX))
891 inc_nlink(inode);
Miklos Szerediac45d612012-03-05 15:48:11 +0100892 spin_unlock(&fc->lock);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700893 fuse_invalidate_attr(inode);
Maxim Patlasov31f32672014-04-28 14:19:24 +0200894 fuse_update_ctime(inode);
Miklos Szerediac45d612012-03-05 15:48:11 +0100895 } else if (err == -EINTR) {
896 fuse_invalidate_attr(inode);
897 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700898 return err;
899}
900
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700901static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
902 struct kstat *stat)
903{
Miklos Szeredi203627b2012-05-10 19:49:38 +0400904 unsigned int blkbits;
Pavel Emelyanov83732002013-10-10 17:10:46 +0400905 struct fuse_conn *fc = get_fuse_conn(inode);
906
907 /* see the comment in fuse_change_attributes() */
Maxim Patlasovb0aa7602013-12-26 19:51:11 +0400908 if (fc->writeback_cache && S_ISREG(inode->i_mode)) {
Pavel Emelyanov83732002013-10-10 17:10:46 +0400909 attr->size = i_size_read(inode);
Maxim Patlasovb0aa7602013-12-26 19:51:11 +0400910 attr->mtime = inode->i_mtime.tv_sec;
911 attr->mtimensec = inode->i_mtime.tv_nsec;
Maxim Patlasov31f32672014-04-28 14:19:24 +0200912 attr->ctime = inode->i_ctime.tv_sec;
913 attr->ctimensec = inode->i_ctime.tv_nsec;
Maxim Patlasovb0aa7602013-12-26 19:51:11 +0400914 }
Miklos Szeredi203627b2012-05-10 19:49:38 +0400915
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700916 stat->dev = inode->i_sb->s_dev;
917 stat->ino = attr->ino;
918 stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
919 stat->nlink = attr->nlink;
Eric W. Biederman499dcf22012-02-07 16:26:03 -0800920 stat->uid = make_kuid(&init_user_ns, attr->uid);
921 stat->gid = make_kgid(&init_user_ns, attr->gid);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700922 stat->rdev = inode->i_rdev;
923 stat->atime.tv_sec = attr->atime;
924 stat->atime.tv_nsec = attr->atimensec;
925 stat->mtime.tv_sec = attr->mtime;
926 stat->mtime.tv_nsec = attr->mtimensec;
927 stat->ctime.tv_sec = attr->ctime;
928 stat->ctime.tv_nsec = attr->ctimensec;
929 stat->size = attr->size;
930 stat->blocks = attr->blocks;
Miklos Szeredi203627b2012-05-10 19:49:38 +0400931
932 if (attr->blksize != 0)
933 blkbits = ilog2(attr->blksize);
934 else
935 blkbits = inode->i_sb->s_blocksize_bits;
936
937 stat->blksize = 1 << blkbits;
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700938}
939
Miklos Szeredic79e3222007-10-18 03:06:59 -0700940static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
941 struct file *file)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700942{
943 int err;
Miklos Szeredic79e3222007-10-18 03:06:59 -0700944 struct fuse_getattr_in inarg;
945 struct fuse_attr_out outarg;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700946 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi70781872014-12-12 09:49:05 +0100947 FUSE_ARGS(args);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700948 u64 attr_version;
949
Miklos Szeredi7dca9fd2007-11-28 16:21:59 -0800950 attr_version = fuse_get_attr_version(fc);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700951
Miklos Szeredic79e3222007-10-18 03:06:59 -0700952 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700953 memset(&outarg, 0, sizeof(outarg));
Miklos Szeredic79e3222007-10-18 03:06:59 -0700954 /* Directories have separate file-handle space */
955 if (file && S_ISREG(inode->i_mode)) {
956 struct fuse_file *ff = file->private_data;
957
958 inarg.getattr_flags |= FUSE_GETATTR_FH;
959 inarg.fh = ff->fh;
960 }
Miklos Szeredi70781872014-12-12 09:49:05 +0100961 args.in.h.opcode = FUSE_GETATTR;
962 args.in.h.nodeid = get_node_id(inode);
963 args.in.numargs = 1;
964 args.in.args[0].size = sizeof(inarg);
965 args.in.args[0].value = &inarg;
966 args.out.numargs = 1;
Miklos Szeredi21f62172015-01-06 10:45:35 +0100967 args.out.args[0].size = sizeof(outarg);
Miklos Szeredi70781872014-12-12 09:49:05 +0100968 args.out.args[0].value = &outarg;
969 err = fuse_simple_request(fc, &args);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700970 if (!err) {
Miklos Szeredic392b3a2019-11-12 11:49:04 +0100971 if (fuse_invalid_attr(&outarg.attr) ||
972 (inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
Miklos Szeredie5e55582005-09-09 13:10:28 -0700973 make_bad_inode(inode);
974 err = -EIO;
975 } else {
Miklos Szeredic79e3222007-10-18 03:06:59 -0700976 fuse_change_attributes(inode, &outarg.attr,
977 attr_timeout(&outarg),
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700978 attr_version);
979 if (stat)
Miklos Szeredic79e3222007-10-18 03:06:59 -0700980 fuse_fillattr(inode, &outarg.attr, stat);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700981 }
982 }
983 return err;
984}
985
Miklos Szeredibcb4be82007-11-28 16:21:59 -0800986int fuse_update_attributes(struct inode *inode, struct kstat *stat,
987 struct file *file, bool *refreshed)
988{
989 struct fuse_inode *fi = get_fuse_inode(inode);
990 int err;
991 bool r;
992
Miklos Szeredi126b9d42014-07-07 15:28:50 +0200993 if (time_before64(fi->i_time, get_jiffies_64())) {
Miklos Szeredibcb4be82007-11-28 16:21:59 -0800994 r = true;
Seth Forshee60bcc882016-08-29 08:46:37 -0500995 forget_all_cached_acls(inode);
Miklos Szeredibcb4be82007-11-28 16:21:59 -0800996 err = fuse_do_getattr(inode, stat, file);
997 } else {
998 r = false;
999 err = 0;
1000 if (stat) {
1001 generic_fillattr(inode, stat);
1002 stat->mode = fi->orig_i_mode;
Pavel Shilovsky45c72cd2012-05-10 19:49:38 +04001003 stat->ino = fi->orig_ino;
Miklos Szeredibcb4be82007-11-28 16:21:59 -08001004 }
1005 }
1006
1007 if (refreshed != NULL)
1008 *refreshed = r;
1009
1010 return err;
1011}
1012
John Muir3b463ae2009-05-31 11:13:57 -04001013int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid,
John Muir451d0f52011-12-06 21:50:06 +01001014 u64 child_nodeid, struct qstr *name)
John Muir3b463ae2009-05-31 11:13:57 -04001015{
1016 int err = -ENOTDIR;
1017 struct inode *parent;
1018 struct dentry *dir;
1019 struct dentry *entry;
1020
1021 parent = ilookup5(sb, parent_nodeid, fuse_inode_eq, &parent_nodeid);
1022 if (!parent)
1023 return -ENOENT;
1024
Al Viro59551022016-01-22 15:40:57 -05001025 inode_lock(parent);
John Muir3b463ae2009-05-31 11:13:57 -04001026 if (!S_ISDIR(parent->i_mode))
1027 goto unlock;
1028
1029 err = -ENOENT;
1030 dir = d_find_alias(parent);
1031 if (!dir)
1032 goto unlock;
1033
Linus Torvalds8387ff22016-06-10 07:51:30 -07001034 name->hash = full_name_hash(dir, name->name, name->len);
John Muir3b463ae2009-05-31 11:13:57 -04001035 entry = d_lookup(dir, name);
1036 dput(dir);
1037 if (!entry)
1038 goto unlock;
1039
1040 fuse_invalidate_attr(parent);
1041 fuse_invalidate_entry(entry);
John Muir451d0f52011-12-06 21:50:06 +01001042
David Howells2b0143b2015-03-17 22:25:59 +00001043 if (child_nodeid != 0 && d_really_is_positive(entry)) {
Al Viro59551022016-01-22 15:40:57 -05001044 inode_lock(d_inode(entry));
David Howells2b0143b2015-03-17 22:25:59 +00001045 if (get_node_id(d_inode(entry)) != child_nodeid) {
John Muir451d0f52011-12-06 21:50:06 +01001046 err = -ENOENT;
1047 goto badentry;
1048 }
1049 if (d_mountpoint(entry)) {
1050 err = -EBUSY;
1051 goto badentry;
1052 }
David Howellse36cb0b2015-01-29 12:02:35 +00001053 if (d_is_dir(entry)) {
John Muir451d0f52011-12-06 21:50:06 +01001054 shrink_dcache_parent(entry);
1055 if (!simple_empty(entry)) {
1056 err = -ENOTEMPTY;
1057 goto badentry;
1058 }
David Howells2b0143b2015-03-17 22:25:59 +00001059 d_inode(entry)->i_flags |= S_DEAD;
John Muir451d0f52011-12-06 21:50:06 +01001060 }
1061 dont_mount(entry);
David Howells2b0143b2015-03-17 22:25:59 +00001062 clear_nlink(d_inode(entry));
John Muir451d0f52011-12-06 21:50:06 +01001063 err = 0;
1064 badentry:
Al Viro59551022016-01-22 15:40:57 -05001065 inode_unlock(d_inode(entry));
John Muir451d0f52011-12-06 21:50:06 +01001066 if (!err)
1067 d_delete(entry);
1068 } else {
1069 err = 0;
1070 }
John Muir3b463ae2009-05-31 11:13:57 -04001071 dput(entry);
John Muir3b463ae2009-05-31 11:13:57 -04001072
1073 unlock:
Al Viro59551022016-01-22 15:40:57 -05001074 inode_unlock(parent);
John Muir3b463ae2009-05-31 11:13:57 -04001075 iput(parent);
1076 return err;
1077}
1078
Miklos Szeredi87729a52005-09-09 13:10:34 -07001079/*
1080 * Calling into a user-controlled filesystem gives the filesystem
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001081 * daemon ptrace-like capabilities over the current process. This
Miklos Szeredi87729a52005-09-09 13:10:34 -07001082 * means, that the filesystem daemon is able to record the exact
1083 * filesystem operations performed, and can also control the behavior
1084 * of the requester process in otherwise impossible ways. For example
1085 * it can delay the operation for arbitrary length of time allowing
1086 * DoS against the requester.
1087 *
1088 * For this reason only those processes can call into the filesystem,
1089 * for which the owner of the mount has ptrace privilege. This
1090 * excludes processes started by other users, suid or sgid processes.
1091 */
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001092int fuse_allow_current_process(struct fuse_conn *fc)
Miklos Szeredi87729a52005-09-09 13:10:34 -07001093{
David Howellsc69e8d92008-11-14 10:39:19 +11001094 const struct cred *cred;
David Howellsc69e8d92008-11-14 10:39:19 +11001095
Miklos Szeredi29433a22016-10-01 07:32:32 +02001096 if (fc->allow_other)
Miklos Szeredi87729a52005-09-09 13:10:34 -07001097 return 1;
1098
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001099 cred = current_cred();
Eric W. Biederman499dcf22012-02-07 16:26:03 -08001100 if (uid_eq(cred->euid, fc->user_id) &&
1101 uid_eq(cred->suid, fc->user_id) &&
1102 uid_eq(cred->uid, fc->user_id) &&
1103 gid_eq(cred->egid, fc->group_id) &&
1104 gid_eq(cred->sgid, fc->group_id) &&
1105 gid_eq(cred->gid, fc->group_id))
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001106 return 1;
Miklos Szeredi87729a52005-09-09 13:10:34 -07001107
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001108 return 0;
Miklos Szeredi87729a52005-09-09 13:10:34 -07001109}
1110
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001111static int fuse_access(struct inode *inode, int mask)
1112{
1113 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi70781872014-12-12 09:49:05 +01001114 FUSE_ARGS(args);
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001115 struct fuse_access_in inarg;
1116 int err;
1117
Miklos Szeredi698fa1d2013-10-01 16:41:23 +02001118 BUG_ON(mask & MAY_NOT_BLOCK);
1119
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001120 if (fc->no_access)
1121 return 0;
1122
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001123 memset(&inarg, 0, sizeof(inarg));
Al Viroe6305c42008-07-15 21:03:57 -04001124 inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC);
Miklos Szeredi70781872014-12-12 09:49:05 +01001125 args.in.h.opcode = FUSE_ACCESS;
1126 args.in.h.nodeid = get_node_id(inode);
1127 args.in.numargs = 1;
1128 args.in.args[0].size = sizeof(inarg);
1129 args.in.args[0].value = &inarg;
1130 err = fuse_simple_request(fc, &args);
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001131 if (err == -ENOSYS) {
1132 fc->no_access = 1;
1133 err = 0;
1134 }
1135 return err;
1136}
1137
Al Viro10556cb2011-06-20 19:28:19 -04001138static int fuse_perm_getattr(struct inode *inode, int mask)
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001139{
Al Viro10556cb2011-06-20 19:28:19 -04001140 if (mask & MAY_NOT_BLOCK)
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001141 return -ECHILD;
1142
Seth Forshee60bcc882016-08-29 08:46:37 -05001143 forget_all_cached_acls(inode);
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001144 return fuse_do_getattr(inode, NULL, NULL);
1145}
1146
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001147/*
1148 * Check permission. The two basic access models of FUSE are:
1149 *
1150 * 1) Local access checking ('default_permissions' mount option) based
1151 * on file mode. This is the plain old disk filesystem permission
1152 * modell.
1153 *
1154 * 2) "Remote" access checking, where server is responsible for
1155 * checking permission in each inode operation. An exception to this
1156 * is if ->permission() was invoked from sys_access() in which case an
1157 * access request is sent. Execute permission is still checked
1158 * locally based on file mode.
1159 */
Al Viro10556cb2011-06-20 19:28:19 -04001160static int fuse_permission(struct inode *inode, int mask)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001161{
1162 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi244f6382007-10-16 23:31:02 -07001163 bool refreshed = false;
1164 int err = 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001165
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001166 if (!fuse_allow_current_process(fc))
Miklos Szeredie5e55582005-09-09 13:10:28 -07001167 return -EACCES;
Miklos Szeredi244f6382007-10-16 23:31:02 -07001168
1169 /*
Miklos Szeredie8e96152007-10-16 23:31:06 -07001170 * If attributes are needed, refresh them before proceeding
Miklos Szeredi244f6382007-10-16 23:31:02 -07001171 */
Miklos Szeredi29433a22016-10-01 07:32:32 +02001172 if (fc->default_permissions ||
Miklos Szeredie8e96152007-10-16 23:31:06 -07001173 ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001174 struct fuse_inode *fi = get_fuse_inode(inode);
1175
Miklos Szeredi126b9d42014-07-07 15:28:50 +02001176 if (time_before64(fi->i_time, get_jiffies_64())) {
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001177 refreshed = true;
1178
Al Viro10556cb2011-06-20 19:28:19 -04001179 err = fuse_perm_getattr(inode, mask);
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001180 if (err)
1181 return err;
1182 }
Miklos Szeredi244f6382007-10-16 23:31:02 -07001183 }
1184
Miklos Szeredi29433a22016-10-01 07:32:32 +02001185 if (fc->default_permissions) {
Al Viro2830ba72011-06-20 19:16:29 -04001186 err = generic_permission(inode, mask);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001187
1188 /* If permission is denied, try to refresh file
1189 attributes. This is also needed, because the root
1190 node will at first have no permissions */
Miklos Szeredi244f6382007-10-16 23:31:02 -07001191 if (err == -EACCES && !refreshed) {
Al Viro10556cb2011-06-20 19:28:19 -04001192 err = fuse_perm_getattr(inode, mask);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001193 if (!err)
Al Viro2830ba72011-06-20 19:16:29 -04001194 err = generic_permission(inode, mask);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001195 }
1196
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001197 /* Note: the opposite of the above test does not
1198 exist. So if permissions are revoked this won't be
1199 noticed immediately, only after the attribute
1200 timeout has expired */
Eric Paris9cfcac82010-07-23 11:43:51 -04001201 } else if (mask & (MAY_ACCESS | MAY_CHDIR)) {
Miklos Szeredie8e96152007-10-16 23:31:06 -07001202 err = fuse_access(inode, mask);
1203 } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
1204 if (!(inode->i_mode & S_IXUGO)) {
1205 if (refreshed)
1206 return -EACCES;
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001207
Al Viro10556cb2011-06-20 19:28:19 -04001208 err = fuse_perm_getattr(inode, mask);
Miklos Szeredie8e96152007-10-16 23:31:06 -07001209 if (!err && !(inode->i_mode & S_IXUGO))
1210 return -EACCES;
1211 }
Miklos Szeredie5e55582005-09-09 13:10:28 -07001212 }
Miklos Szeredi244f6382007-10-16 23:31:02 -07001213 return err;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001214}
1215
1216static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
Al Viro8d3af7f2013-05-18 03:03:58 -04001217 struct dir_context *ctx)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001218{
1219 while (nbytes >= FUSE_NAME_OFFSET) {
1220 struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
1221 size_t reclen = FUSE_DIRENT_SIZE(dirent);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001222 if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
1223 return -EIO;
1224 if (reclen > nbytes)
1225 break;
Miklos Szerediefeb9e62013-09-03 14:28:38 +02001226 if (memchr(dirent->name, '/', dirent->namelen) != NULL)
1227 return -EIO;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001228
Al Viro8d3af7f2013-05-18 03:03:58 -04001229 if (!dir_emit(ctx, dirent->name, dirent->namelen,
1230 dirent->ino, dirent->type))
Miklos Szeredie5e55582005-09-09 13:10:28 -07001231 break;
1232
1233 buf += reclen;
1234 nbytes -= reclen;
Al Viro8d3af7f2013-05-18 03:03:58 -04001235 ctx->pos = dirent->off;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001236 }
1237
1238 return 0;
1239}
1240
Anand V. Avati0b05b182012-08-19 08:53:23 -04001241static int fuse_direntplus_link(struct file *file,
1242 struct fuse_direntplus *direntplus,
1243 u64 attr_version)
1244{
Anand V. Avati0b05b182012-08-19 08:53:23 -04001245 struct fuse_entry_out *o = &direntplus->entry_out;
1246 struct fuse_dirent *dirent = &direntplus->dirent;
1247 struct dentry *parent = file->f_path.dentry;
1248 struct qstr name = QSTR_INIT(dirent->name, dirent->namelen);
1249 struct dentry *dentry;
1250 struct dentry *alias;
David Howells2b0143b2015-03-17 22:25:59 +00001251 struct inode *dir = d_inode(parent);
Anand V. Avati0b05b182012-08-19 08:53:23 -04001252 struct fuse_conn *fc;
1253 struct inode *inode;
Al Virod9b3dbd2016-04-20 17:30:32 -04001254 DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
Anand V. Avati0b05b182012-08-19 08:53:23 -04001255
1256 if (!o->nodeid) {
1257 /*
1258 * Unlike in the case of fuse_lookup, zero nodeid does not mean
1259 * ENOENT. Instead, it only means the userspace filesystem did
1260 * not want to return attributes/handle for this entry.
1261 *
1262 * So do nothing.
1263 */
1264 return 0;
1265 }
1266
1267 if (name.name[0] == '.') {
1268 /*
1269 * We could potentially refresh the attributes of the directory
1270 * and its parent?
1271 */
1272 if (name.len == 1)
1273 return 0;
1274 if (name.name[1] == '.' && name.len == 2)
1275 return 0;
1276 }
Miklos Szeredia28ef452013-07-17 14:53:53 +02001277
1278 if (invalid_nodeid(o->nodeid))
1279 return -EIO;
Miklos Szeredic392b3a2019-11-12 11:49:04 +01001280 if (fuse_invalid_attr(&o->attr))
Miklos Szeredia28ef452013-07-17 14:53:53 +02001281 return -EIO;
1282
Anand V. Avati0b05b182012-08-19 08:53:23 -04001283 fc = get_fuse_conn(dir);
1284
Linus Torvalds8387ff22016-06-10 07:51:30 -07001285 name.hash = full_name_hash(parent, name.name, name.len);
Anand V. Avati0b05b182012-08-19 08:53:23 -04001286 dentry = d_lookup(parent, &name);
Al Virod9b3dbd2016-04-20 17:30:32 -04001287 if (!dentry) {
1288retry:
1289 dentry = d_alloc_parallel(parent, &name, &wq);
1290 if (IS_ERR(dentry))
1291 return PTR_ERR(dentry);
1292 }
1293 if (!d_in_lookup(dentry)) {
1294 struct fuse_inode *fi;
David Howells2b0143b2015-03-17 22:25:59 +00001295 inode = d_inode(dentry);
Al Virod9b3dbd2016-04-20 17:30:32 -04001296 if (!inode ||
1297 get_node_id(inode) != o->nodeid ||
1298 ((o->attr.mode ^ inode->i_mode) & S_IFMT)) {
Eric W. Biederman5542aa22014-02-13 09:46:25 -08001299 d_invalidate(dentry);
Al Virod9b3dbd2016-04-20 17:30:32 -04001300 dput(dentry);
1301 goto retry;
Anand V. Avati0b05b182012-08-19 08:53:23 -04001302 }
Al Virod9b3dbd2016-04-20 17:30:32 -04001303 if (is_bad_inode(inode)) {
1304 dput(dentry);
1305 return -EIO;
1306 }
1307
1308 fi = get_fuse_inode(inode);
1309 spin_lock(&fc->lock);
1310 fi->nlookup++;
1311 spin_unlock(&fc->lock);
1312
Seth Forshee60bcc882016-08-29 08:46:37 -05001313 forget_all_cached_acls(inode);
Al Virod9b3dbd2016-04-20 17:30:32 -04001314 fuse_change_attributes(inode, &o->attr,
1315 entry_attr_timeout(o),
1316 attr_version);
1317 /*
1318 * The other branch comes via fuse_iget()
1319 * which bumps nlookup inside
1320 */
1321 } else {
1322 inode = fuse_iget(dir->i_sb, o->nodeid, o->generation,
1323 &o->attr, entry_attr_timeout(o),
1324 attr_version);
1325 if (!inode)
1326 inode = ERR_PTR(-ENOMEM);
1327
1328 alias = d_splice_alias(inode, dentry);
1329 d_lookup_done(dentry);
1330 if (alias) {
1331 dput(dentry);
1332 dentry = alias;
1333 }
1334 if (IS_ERR(dentry))
1335 return PTR_ERR(dentry);
Anand V. Avati0b05b182012-08-19 08:53:23 -04001336 }
Miklos Szeredi6314efe2013-10-01 16:41:22 +02001337 if (fc->readdirplus_auto)
1338 set_bit(FUSE_I_INIT_RDPLUS, &get_fuse_inode(inode)->state);
Anand V. Avati0b05b182012-08-19 08:53:23 -04001339 fuse_change_entry_timeout(dentry, o);
1340
Miklos Szeredic7263bc2013-07-17 14:53:54 +02001341 dput(dentry);
Al Virod9b3dbd2016-04-20 17:30:32 -04001342 return 0;
Anand V. Avati0b05b182012-08-19 08:53:23 -04001343}
1344
1345static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file,
Al Viro8d3af7f2013-05-18 03:03:58 -04001346 struct dir_context *ctx, u64 attr_version)
Anand V. Avati0b05b182012-08-19 08:53:23 -04001347{
1348 struct fuse_direntplus *direntplus;
1349 struct fuse_dirent *dirent;
1350 size_t reclen;
1351 int over = 0;
1352 int ret;
1353
1354 while (nbytes >= FUSE_NAME_OFFSET_DIRENTPLUS) {
1355 direntplus = (struct fuse_direntplus *) buf;
1356 dirent = &direntplus->dirent;
1357 reclen = FUSE_DIRENTPLUS_SIZE(direntplus);
1358
1359 if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
1360 return -EIO;
1361 if (reclen > nbytes)
1362 break;
Miklos Szerediefeb9e62013-09-03 14:28:38 +02001363 if (memchr(dirent->name, '/', dirent->namelen) != NULL)
1364 return -EIO;
Anand V. Avati0b05b182012-08-19 08:53:23 -04001365
1366 if (!over) {
1367 /* We fill entries into dstbuf only as much as
1368 it can hold. But we still continue iterating
1369 over remaining entries to link them. If not,
1370 we need to send a FORGET for each of those
1371 which we did not link.
1372 */
Al Viro8d3af7f2013-05-18 03:03:58 -04001373 over = !dir_emit(ctx, dirent->name, dirent->namelen,
1374 dirent->ino, dirent->type);
Miklos Szeredi87838852017-10-25 16:34:27 +02001375 if (!over)
1376 ctx->pos = dirent->off;
Anand V. Avati0b05b182012-08-19 08:53:23 -04001377 }
1378
1379 buf += reclen;
1380 nbytes -= reclen;
1381
1382 ret = fuse_direntplus_link(file, direntplus, attr_version);
1383 if (ret)
1384 fuse_force_forget(file, direntplus->entry_out.nodeid);
1385 }
1386
1387 return 0;
1388}
1389
Al Viro8d3af7f2013-05-18 03:03:58 -04001390static int fuse_readdir(struct file *file, struct dir_context *ctx)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001391{
Feng Shuo4582a4a2013-01-15 11:23:28 +08001392 int plus, err;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001393 size_t nbytes;
1394 struct page *page;
Al Viro496ad9a2013-01-23 17:07:38 -05001395 struct inode *inode = file_inode(file);
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001396 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi248d86e2006-01-06 00:19:39 -08001397 struct fuse_req *req;
Anand V. Avati0b05b182012-08-19 08:53:23 -04001398 u64 attr_version = 0;
Miklos Szeredi68fbfcb2018-07-26 16:13:11 +02001399 bool locked;
Miklos Szeredi248d86e2006-01-06 00:19:39 -08001400
1401 if (is_bad_inode(inode))
1402 return -EIO;
1403
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001404 req = fuse_get_req(fc, 1);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001405 if (IS_ERR(req))
1406 return PTR_ERR(req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001407
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001408 page = alloc_page(GFP_KERNEL);
1409 if (!page) {
1410 fuse_put_request(fc, req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001411 return -ENOMEM;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001412 }
Feng Shuo4582a4a2013-01-15 11:23:28 +08001413
Al Viro8d3af7f2013-05-18 03:03:58 -04001414 plus = fuse_use_readdirplus(inode, ctx);
Miklos Szeredif4975c62009-04-02 14:25:34 +02001415 req->out.argpages = 1;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001416 req->num_pages = 1;
1417 req->pages[0] = page;
Maxim Patlasov85f40ae2012-10-26 19:49:33 +04001418 req->page_descs[0].length = PAGE_SIZE;
Feng Shuo4582a4a2013-01-15 11:23:28 +08001419 if (plus) {
Anand V. Avati0b05b182012-08-19 08:53:23 -04001420 attr_version = fuse_get_attr_version(fc);
Al Viro8d3af7f2013-05-18 03:03:58 -04001421 fuse_read_fill(req, file, ctx->pos, PAGE_SIZE,
Anand V. Avati0b05b182012-08-19 08:53:23 -04001422 FUSE_READDIRPLUS);
1423 } else {
Al Viro8d3af7f2013-05-18 03:03:58 -04001424 fuse_read_fill(req, file, ctx->pos, PAGE_SIZE,
Anand V. Avati0b05b182012-08-19 08:53:23 -04001425 FUSE_READDIR);
1426 }
Miklos Szeredi68fbfcb2018-07-26 16:13:11 +02001427 locked = fuse_lock_inode(inode);
Tejun Heob93f8582008-11-26 12:03:55 +01001428 fuse_request_send(fc, req);
Miklos Szeredi68fbfcb2018-07-26 16:13:11 +02001429 fuse_unlock_inode(inode, locked);
Miklos Szeredi361b1eb52006-01-16 22:14:45 -08001430 nbytes = req->out.args[0].size;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001431 err = req->out.h.error;
1432 fuse_put_request(fc, req);
Anand V. Avati0b05b182012-08-19 08:53:23 -04001433 if (!err) {
Feng Shuo4582a4a2013-01-15 11:23:28 +08001434 if (plus) {
Anand V. Avati0b05b182012-08-19 08:53:23 -04001435 err = parse_dirplusfile(page_address(page), nbytes,
Al Viro8d3af7f2013-05-18 03:03:58 -04001436 file, ctx,
Anand V. Avati0b05b182012-08-19 08:53:23 -04001437 attr_version);
1438 } else {
1439 err = parse_dirfile(page_address(page), nbytes, file,
Al Viro8d3af7f2013-05-18 03:03:58 -04001440 ctx);
Anand V. Avati0b05b182012-08-19 08:53:23 -04001441 }
1442 }
Miklos Szeredie5e55582005-09-09 13:10:28 -07001443
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001444 __free_page(page);
Andrew Gallagher451418f2013-11-05 03:55:43 -08001445 fuse_invalidate_atime(inode);
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001446 return err;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001447}
1448
Al Viro6b255392015-11-17 10:20:54 -05001449static const char *fuse_get_link(struct dentry *dentry,
Al Virofceef392015-12-29 15:58:39 -05001450 struct inode *inode,
1451 struct delayed_call *done)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001452{
Miklos Szeredie5e55582005-09-09 13:10:28 -07001453 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi70781872014-12-12 09:49:05 +01001454 FUSE_ARGS(args);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001455 char *link;
Miklos Szeredi70781872014-12-12 09:49:05 +01001456 ssize_t ret;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001457
Al Viro6b255392015-11-17 10:20:54 -05001458 if (!dentry)
1459 return ERR_PTR(-ECHILD);
1460
Al Virocd3417c2015-12-29 16:03:53 -05001461 link = kmalloc(PAGE_SIZE, GFP_KERNEL);
Miklos Szeredi70781872014-12-12 09:49:05 +01001462 if (!link)
1463 return ERR_PTR(-ENOMEM);
1464
1465 args.in.h.opcode = FUSE_READLINK;
1466 args.in.h.nodeid = get_node_id(inode);
1467 args.out.argvar = 1;
1468 args.out.numargs = 1;
1469 args.out.args[0].size = PAGE_SIZE - 1;
1470 args.out.args[0].value = link;
1471 ret = fuse_simple_request(fc, &args);
1472 if (ret < 0) {
Al Virocd3417c2015-12-29 16:03:53 -05001473 kfree(link);
Miklos Szeredi70781872014-12-12 09:49:05 +01001474 link = ERR_PTR(ret);
1475 } else {
1476 link[ret] = '\0';
Al Virofceef392015-12-29 15:58:39 -05001477 set_delayed_call(done, kfree_link, link);
Miklos Szeredi70781872014-12-12 09:49:05 +01001478 }
Andrew Gallagher451418f2013-11-05 03:55:43 -08001479 fuse_invalidate_atime(inode);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001480 return link;
1481}
1482
Miklos Szeredie5e55582005-09-09 13:10:28 -07001483static int fuse_dir_open(struct inode *inode, struct file *file)
1484{
Miklos Szeredi91fe96b2009-04-28 16:56:37 +02001485 return fuse_open_common(inode, file, true);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001486}
1487
1488static int fuse_dir_release(struct inode *inode, struct file *file)
1489{
Miklos Szeredi8b0797a2009-04-28 16:56:39 +02001490 fuse_release_common(file, FUSE_RELEASEDIR);
1491
1492 return 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001493}
1494
Josef Bacik02c24a82011-07-16 20:44:56 -04001495static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end,
1496 int datasync)
Miklos Szeredi82547982005-09-09 13:10:38 -07001497{
Josef Bacik02c24a82011-07-16 20:44:56 -04001498 return fuse_fsync_common(file, start, end, datasync, 1);
Miklos Szeredi82547982005-09-09 13:10:38 -07001499}
1500
Miklos Szeredib18da0c2011-12-13 11:58:49 +01001501static long fuse_dir_ioctl(struct file *file, unsigned int cmd,
1502 unsigned long arg)
1503{
1504 struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1505
1506 /* FUSE_IOCTL_DIR only supported for API version >= 7.18 */
1507 if (fc->minor < 18)
1508 return -ENOTTY;
1509
1510 return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR);
1511}
1512
1513static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd,
1514 unsigned long arg)
1515{
1516 struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1517
1518 if (fc->minor < 18)
1519 return -ENOTTY;
1520
1521 return fuse_ioctl_common(file, cmd, arg,
1522 FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR);
1523}
1524
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001525static bool update_mtime(unsigned ivalid, bool trust_local_mtime)
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001526{
1527 /* Always update if mtime is explicitly set */
1528 if (ivalid & ATTR_MTIME_SET)
1529 return true;
1530
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001531 /* Or if kernel i_mtime is the official one */
1532 if (trust_local_mtime)
1533 return true;
1534
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001535 /* If it's an open(O_TRUNC) or an ftruncate(), don't update */
1536 if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
1537 return false;
1538
1539 /* In all other cases update */
1540 return true;
1541}
1542
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001543static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg,
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001544 bool trust_local_cmtime)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001545{
1546 unsigned ivalid = iattr->ia_valid;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001547
1548 if (ivalid & ATTR_MODE)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001549 arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001550 if (ivalid & ATTR_UID)
Eric W. Biederman499dcf22012-02-07 16:26:03 -08001551 arg->valid |= FATTR_UID, arg->uid = from_kuid(&init_user_ns, iattr->ia_uid);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001552 if (ivalid & ATTR_GID)
Eric W. Biederman499dcf22012-02-07 16:26:03 -08001553 arg->valid |= FATTR_GID, arg->gid = from_kgid(&init_user_ns, iattr->ia_gid);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001554 if (ivalid & ATTR_SIZE)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001555 arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001556 if (ivalid & ATTR_ATIME) {
1557 arg->valid |= FATTR_ATIME;
Miklos Szeredibefc6492005-11-07 00:59:52 -08001558 arg->atime = iattr->ia_atime.tv_sec;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001559 arg->atimensec = iattr->ia_atime.tv_nsec;
1560 if (!(ivalid & ATTR_ATIME_SET))
1561 arg->valid |= FATTR_ATIME_NOW;
1562 }
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001563 if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, trust_local_cmtime)) {
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001564 arg->valid |= FATTR_MTIME;
Miklos Szeredibefc6492005-11-07 00:59:52 -08001565 arg->mtime = iattr->ia_mtime.tv_sec;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001566 arg->mtimensec = iattr->ia_mtime.tv_nsec;
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001567 if (!(ivalid & ATTR_MTIME_SET) && !trust_local_cmtime)
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001568 arg->valid |= FATTR_MTIME_NOW;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001569 }
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001570 if ((ivalid & ATTR_CTIME) && trust_local_cmtime) {
1571 arg->valid |= FATTR_CTIME;
1572 arg->ctime = iattr->ia_ctime.tv_sec;
1573 arg->ctimensec = iattr->ia_ctime.tv_nsec;
1574 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001575}
1576
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001577/*
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001578 * Prevent concurrent writepages on inode
1579 *
1580 * This is done by adding a negative bias to the inode write counter
1581 * and waiting for all pending writes to finish.
1582 */
1583void fuse_set_nowrite(struct inode *inode)
1584{
1585 struct fuse_conn *fc = get_fuse_conn(inode);
1586 struct fuse_inode *fi = get_fuse_inode(inode);
1587
Al Viro59551022016-01-22 15:40:57 -05001588 BUG_ON(!inode_is_locked(inode));
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001589
1590 spin_lock(&fc->lock);
1591 BUG_ON(fi->writectr < 0);
1592 fi->writectr += FUSE_NOWRITE;
1593 spin_unlock(&fc->lock);
1594 wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE);
1595}
1596
1597/*
1598 * Allow writepages on inode
1599 *
1600 * Remove the bias from the writecounter and send any queued
1601 * writepages.
1602 */
1603static void __fuse_release_nowrite(struct inode *inode)
1604{
1605 struct fuse_inode *fi = get_fuse_inode(inode);
1606
1607 BUG_ON(fi->writectr != FUSE_NOWRITE);
1608 fi->writectr = 0;
1609 fuse_flush_writepages(inode);
1610}
1611
1612void fuse_release_nowrite(struct inode *inode)
1613{
1614 struct fuse_conn *fc = get_fuse_conn(inode);
1615
1616 spin_lock(&fc->lock);
1617 __fuse_release_nowrite(inode);
1618 spin_unlock(&fc->lock);
1619}
1620
Miklos Szeredi70781872014-12-12 09:49:05 +01001621static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_args *args,
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001622 struct inode *inode,
1623 struct fuse_setattr_in *inarg_p,
1624 struct fuse_attr_out *outarg_p)
1625{
Miklos Szeredi70781872014-12-12 09:49:05 +01001626 args->in.h.opcode = FUSE_SETATTR;
1627 args->in.h.nodeid = get_node_id(inode);
1628 args->in.numargs = 1;
1629 args->in.args[0].size = sizeof(*inarg_p);
1630 args->in.args[0].value = inarg_p;
1631 args->out.numargs = 1;
Miklos Szeredi21f62172015-01-06 10:45:35 +01001632 args->out.args[0].size = sizeof(*outarg_p);
Miklos Szeredi70781872014-12-12 09:49:05 +01001633 args->out.args[0].value = outarg_p;
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001634}
1635
1636/*
1637 * Flush inode->i_mtime to the server
1638 */
Maxim Patlasovab9e13f2014-04-28 14:19:24 +02001639int fuse_flush_times(struct inode *inode, struct fuse_file *ff)
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001640{
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001641 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi70781872014-12-12 09:49:05 +01001642 FUSE_ARGS(args);
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001643 struct fuse_setattr_in inarg;
1644 struct fuse_attr_out outarg;
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001645
1646 memset(&inarg, 0, sizeof(inarg));
1647 memset(&outarg, 0, sizeof(outarg));
1648
Maxim Patlasovab9e13f2014-04-28 14:19:24 +02001649 inarg.valid = FATTR_MTIME;
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001650 inarg.mtime = inode->i_mtime.tv_sec;
1651 inarg.mtimensec = inode->i_mtime.tv_nsec;
Maxim Patlasovab9e13f2014-04-28 14:19:24 +02001652 if (fc->minor >= 23) {
1653 inarg.valid |= FATTR_CTIME;
1654 inarg.ctime = inode->i_ctime.tv_sec;
1655 inarg.ctimensec = inode->i_ctime.tv_nsec;
1656 }
Miklos Szeredi1e18bda2014-04-28 14:19:23 +02001657 if (ff) {
1658 inarg.valid |= FATTR_FH;
1659 inarg.fh = ff->fh;
1660 }
Miklos Szeredi70781872014-12-12 09:49:05 +01001661 fuse_setattr_fill(fc, &args, inode, &inarg, &outarg);
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001662
Miklos Szeredi70781872014-12-12 09:49:05 +01001663 return fuse_simple_request(fc, &args);
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001664}
1665
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001666/*
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001667 * Set attributes, and at the same time refresh them.
1668 *
1669 * Truncation is slightly complicated, because the 'truncate' request
1670 * may fail, in which case we don't want to touch the mapping.
Miklos Szeredi9ffbb912006-10-17 00:10:06 -07001671 * vmtruncate() doesn't allow for this case, so do the rlimit checking
1672 * and the actual truncation by hand.
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001673 */
Jan Kara62490332016-05-26 17:12:41 +02001674int fuse_do_setattr(struct dentry *dentry, struct iattr *attr,
Maxim Patlasovefb9fa92012-12-18 14:05:08 +04001675 struct file *file)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001676{
Jan Kara62490332016-05-26 17:12:41 +02001677 struct inode *inode = d_inode(dentry);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001678 struct fuse_conn *fc = get_fuse_conn(inode);
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001679 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredi70781872014-12-12 09:49:05 +01001680 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001681 struct fuse_setattr_in inarg;
1682 struct fuse_attr_out outarg;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001683 bool is_truncate = false;
Pavel Emelyanov83732002013-10-10 17:10:46 +04001684 bool is_wb = fc->writeback_cache;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001685 loff_t oldsize;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001686 int err;
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001687 bool trust_local_cmtime = is_wb && S_ISREG(inode->i_mode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001688
Miklos Szeredi29433a22016-10-01 07:32:32 +02001689 if (!fc->default_permissions)
Christoph Hellwigdb78b872010-06-04 11:30:03 +02001690 attr->ia_valid |= ATTR_FORCE;
1691
Jan Kara31051c82016-05-26 16:55:18 +02001692 err = setattr_prepare(dentry, attr);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02001693 if (err)
1694 return err;
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001695
Miklos Szeredi8d56add2011-02-25 14:44:58 +01001696 if (attr->ia_valid & ATTR_OPEN) {
Miklos Szerediebdc37f2018-02-08 15:17:38 +01001697 /* This is coming from open(..., ... | O_TRUNC); */
1698 WARN_ON(!(attr->ia_valid & ATTR_SIZE));
1699 WARN_ON(attr->ia_size != 0);
1700 if (fc->atomic_o_trunc) {
1701 /*
1702 * No need to send request to userspace, since actual
1703 * truncation has already been done by OPEN. But still
1704 * need to truncate page cache.
1705 */
1706 i_size_write(inode, 0);
1707 truncate_pagecache(inode, 0);
Miklos Szeredi8d56add2011-02-25 14:44:58 +01001708 return 0;
Miklos Szerediebdc37f2018-02-08 15:17:38 +01001709 }
Miklos Szeredi8d56add2011-02-25 14:44:58 +01001710 file = NULL;
1711 }
Miklos Szeredi6ff958e2007-10-18 03:07:02 -07001712
Christoph Hellwig2c27c652010-06-04 11:30:04 +02001713 if (attr->ia_valid & ATTR_SIZE)
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001714 is_truncate = true;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001715
Miklos Szeredic829f322019-10-23 14:26:37 +02001716 /* Flush dirty data/metadata before non-truncate SETATTR */
1717 if (is_wb && S_ISREG(inode->i_mode) &&
1718 attr->ia_valid &
1719 (ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_MTIME_SET |
1720 ATTR_TIMES_SET)) {
1721 err = write_inode_now(inode, true);
1722 if (err)
1723 return err;
1724
1725 fuse_set_nowrite(inode);
1726 fuse_release_nowrite(inode);
1727 }
1728
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001729 if (is_truncate) {
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001730 fuse_set_nowrite(inode);
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001731 set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001732 if (trust_local_cmtime && attr->ia_size != inode->i_size)
1733 attr->ia_valid |= ATTR_MTIME | ATTR_CTIME;
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001734 }
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001735
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001736 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -07001737 memset(&outarg, 0, sizeof(outarg));
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001738 iattr_to_fattr(attr, &inarg, trust_local_cmtime);
Miklos Szeredi49d49142007-10-18 03:07:00 -07001739 if (file) {
1740 struct fuse_file *ff = file->private_data;
1741 inarg.valid |= FATTR_FH;
1742 inarg.fh = ff->fh;
1743 }
Miklos Szeredif3332112007-10-18 03:07:04 -07001744 if (attr->ia_valid & ATTR_SIZE) {
1745 /* For mandatory locking in truncate */
1746 inarg.valid |= FATTR_LOCKOWNER;
1747 inarg.lock_owner = fuse_lock_owner_id(fc, current->files);
1748 }
Miklos Szeredi70781872014-12-12 09:49:05 +01001749 fuse_setattr_fill(fc, &args, inode, &inarg, &outarg);
1750 err = fuse_simple_request(fc, &args);
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001751 if (err) {
1752 if (err == -EINTR)
1753 fuse_invalidate_attr(inode);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001754 goto error;
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001755 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001756
Miklos Szeredic392b3a2019-11-12 11:49:04 +01001757 if (fuse_invalid_attr(&outarg.attr) ||
1758 (inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001759 make_bad_inode(inode);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001760 err = -EIO;
1761 goto error;
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001762 }
1763
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001764 spin_lock(&fc->lock);
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001765 /* the kernel maintains i_mtime locally */
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001766 if (trust_local_cmtime) {
1767 if (attr->ia_valid & ATTR_MTIME)
1768 inode->i_mtime = attr->ia_mtime;
1769 if (attr->ia_valid & ATTR_CTIME)
1770 inode->i_ctime = attr->ia_ctime;
Miklos Szeredi1e18bda2014-04-28 14:19:23 +02001771 /* FIXME: clear I_DIRTY_SYNC? */
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001772 }
1773
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001774 fuse_change_attributes_common(inode, &outarg.attr,
1775 attr_timeout(&outarg));
1776 oldsize = inode->i_size;
Pavel Emelyanov83732002013-10-10 17:10:46 +04001777 /* see the comment in fuse_change_attributes() */
1778 if (!is_wb || is_truncate || !S_ISREG(inode->i_mode))
1779 i_size_write(inode, outarg.attr.size);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001780
1781 if (is_truncate) {
1782 /* NOTE: this may release/reacquire fc->lock */
1783 __fuse_release_nowrite(inode);
1784 }
1785 spin_unlock(&fc->lock);
1786
1787 /*
1788 * Only call invalidate_inode_pages2() after removing
1789 * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock.
1790 */
Pavel Emelyanov83732002013-10-10 17:10:46 +04001791 if ((is_truncate || !is_wb) &&
1792 S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
Kirill A. Shutemov7caef262013-09-12 15:13:56 -07001793 truncate_pagecache(inode, outarg.attr.size);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001794 invalidate_inode_pages2(inode->i_mapping);
1795 }
1796
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001797 clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001798 return 0;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001799
1800error:
1801 if (is_truncate)
1802 fuse_release_nowrite(inode);
1803
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001804 clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001805 return err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001806}
1807
Miklos Szeredi49d49142007-10-18 03:07:00 -07001808static int fuse_setattr(struct dentry *entry, struct iattr *attr)
1809{
David Howells2b0143b2015-03-17 22:25:59 +00001810 struct inode *inode = d_inode(entry);
Miklos Szeredi5e940c12016-10-01 07:32:32 +02001811 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredia09f99e2016-10-01 07:32:32 +02001812 struct file *file = (attr->ia_valid & ATTR_FILE) ? attr->ia_file : NULL;
Miklos Szeredi5e2b8822016-10-01 07:32:32 +02001813 int ret;
Maxim Patlasovefb9fa92012-12-18 14:05:08 +04001814
1815 if (!fuse_allow_current_process(get_fuse_conn(inode)))
1816 return -EACCES;
1817
Miklos Szeredia09f99e2016-10-01 07:32:32 +02001818 if (attr->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) {
Miklos Szeredia09f99e2016-10-01 07:32:32 +02001819 attr->ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID |
1820 ATTR_MODE);
Miklos Szeredia09f99e2016-10-01 07:32:32 +02001821
Miklos Szeredi5e940c12016-10-01 07:32:32 +02001822 /*
1823 * The only sane way to reliably kill suid/sgid is to do it in
1824 * the userspace filesystem
1825 *
1826 * This should be done on write(), truncate() and chown().
1827 */
1828 if (!fc->handle_killpriv) {
Miklos Szeredi5e940c12016-10-01 07:32:32 +02001829 /*
1830 * ia_mode calculation may have used stale i_mode.
1831 * Refresh and recalculate.
1832 */
1833 ret = fuse_do_getattr(inode, NULL, file);
1834 if (ret)
1835 return ret;
1836
1837 attr->ia_mode = inode->i_mode;
Miklos Szeredic01638f2016-12-06 16:18:45 +01001838 if (inode->i_mode & S_ISUID) {
Miklos Szeredi5e940c12016-10-01 07:32:32 +02001839 attr->ia_valid |= ATTR_MODE;
1840 attr->ia_mode &= ~S_ISUID;
1841 }
Miklos Szeredic01638f2016-12-06 16:18:45 +01001842 if ((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
Miklos Szeredi5e940c12016-10-01 07:32:32 +02001843 attr->ia_valid |= ATTR_MODE;
1844 attr->ia_mode &= ~S_ISGID;
1845 }
Miklos Szeredia09f99e2016-10-01 07:32:32 +02001846 }
1847 }
1848 if (!attr->ia_valid)
1849 return 0;
1850
Linus Torvaldsabb5a142016-10-10 13:04:49 -07001851 ret = fuse_do_setattr(entry, attr, file);
Miklos Szeredi5e2b8822016-10-01 07:32:32 +02001852 if (!ret) {
Seth Forshee60bcc882016-08-29 08:46:37 -05001853 /*
1854 * If filesystem supports acls it may have updated acl xattrs in
1855 * the filesystem, so forget cached acls for the inode.
1856 */
1857 if (fc->posix_acl)
1858 forget_all_cached_acls(inode);
1859
Miklos Szeredi5e2b8822016-10-01 07:32:32 +02001860 /* Directory mode changed, may need to revalidate access */
1861 if (d_is_dir(entry) && (attr->ia_valid & ATTR_MODE))
1862 fuse_invalidate_entry_cache(entry);
1863 }
1864 return ret;
Miklos Szeredi49d49142007-10-18 03:07:00 -07001865}
1866
Miklos Szeredie5e55582005-09-09 13:10:28 -07001867static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
1868 struct kstat *stat)
1869{
David Howells2b0143b2015-03-17 22:25:59 +00001870 struct inode *inode = d_inode(entry);
Miklos Szeredi244f6382007-10-16 23:31:02 -07001871 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi244f6382007-10-16 23:31:02 -07001872
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001873 if (!fuse_allow_current_process(fc))
Miklos Szeredi244f6382007-10-16 23:31:02 -07001874 return -EACCES;
1875
Miklos Szeredibcb4be82007-11-28 16:21:59 -08001876 return fuse_update_attributes(inode, stat, NULL, NULL);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001877}
1878
Arjan van de Ven754661f2007-02-12 00:55:38 -08001879static const struct inode_operations fuse_dir_inode_operations = {
Miklos Szeredie5e55582005-09-09 13:10:28 -07001880 .lookup = fuse_lookup,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001881 .mkdir = fuse_mkdir,
1882 .symlink = fuse_symlink,
1883 .unlink = fuse_unlink,
1884 .rmdir = fuse_rmdir,
Miklos Szeredi2773bf02016-09-27 11:03:58 +02001885 .rename = fuse_rename2,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001886 .link = fuse_link,
1887 .setattr = fuse_setattr,
1888 .create = fuse_create,
Miklos Szeredic8ccbe02012-06-05 15:10:22 +02001889 .atomic_open = fuse_atomic_open,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001890 .mknod = fuse_mknod,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001891 .permission = fuse_permission,
1892 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001893 .listxattr = fuse_listxattr,
Seth Forshee60bcc882016-08-29 08:46:37 -05001894 .get_acl = fuse_get_acl,
1895 .set_acl = fuse_set_acl,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001896};
1897
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -08001898static const struct file_operations fuse_dir_operations = {
Miklos Szeredib6aeade2005-09-09 13:10:30 -07001899 .llseek = generic_file_llseek,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001900 .read = generic_read_dir,
Al Virod9b3dbd2016-04-20 17:30:32 -04001901 .iterate_shared = fuse_readdir,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001902 .open = fuse_dir_open,
1903 .release = fuse_dir_release,
Miklos Szeredi82547982005-09-09 13:10:38 -07001904 .fsync = fuse_dir_fsync,
Miklos Szeredib18da0c2011-12-13 11:58:49 +01001905 .unlocked_ioctl = fuse_dir_ioctl,
1906 .compat_ioctl = fuse_dir_compat_ioctl,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001907};
1908
Arjan van de Ven754661f2007-02-12 00:55:38 -08001909static const struct inode_operations fuse_common_inode_operations = {
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001910 .setattr = fuse_setattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001911 .permission = fuse_permission,
1912 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001913 .listxattr = fuse_listxattr,
Seth Forshee60bcc882016-08-29 08:46:37 -05001914 .get_acl = fuse_get_acl,
1915 .set_acl = fuse_set_acl,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001916};
1917
Arjan van de Ven754661f2007-02-12 00:55:38 -08001918static const struct inode_operations fuse_symlink_inode_operations = {
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001919 .setattr = fuse_setattr,
Al Viro6b255392015-11-17 10:20:54 -05001920 .get_link = fuse_get_link,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001921 .readlink = generic_readlink,
1922 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001923 .listxattr = fuse_listxattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001924};
1925
1926void fuse_init_common(struct inode *inode)
1927{
1928 inode->i_op = &fuse_common_inode_operations;
1929}
1930
1931void fuse_init_dir(struct inode *inode)
1932{
1933 inode->i_op = &fuse_dir_inode_operations;
1934 inode->i_fop = &fuse_dir_operations;
1935}
1936
1937void fuse_init_symlink(struct inode *inode)
1938{
1939 inode->i_op = &fuse_symlink_inode_operations;
1940}