blob: 531ecc75f0b417255af1b60050c5217618df9115 [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;
502 err = fuse_simple_request(fc, &args);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200503 if (err)
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800504 goto out_free_ff;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800505
506 err = -EIO;
Miklos Szeredic392b3a2019-11-12 11:49:04 +0100507 if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid) ||
508 fuse_invalid_attr(&outentry.attr))
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800509 goto out_free_ff;
510
Miklos Szeredic7b71432009-04-28 16:56:37 +0200511 ff->fh = outopen.fh;
512 ff->nodeid = outentry.nodeid;
513 ff->open_flags = outopen.open_flags;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800514 inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700515 &outentry.attr, entry_attr_timeout(&outentry), 0);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800516 if (!inode) {
517 flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
Miklos Szeredi8b0797a2009-04-28 16:56:39 +0200518 fuse_sync_release(ff, flags);
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100519 fuse_queue_forget(fc, forget, outentry.nodeid, 1);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200520 err = -ENOMEM;
521 goto out_err;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800522 }
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100523 kfree(forget);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800524 d_instantiate(entry, inode);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700525 fuse_change_entry_timeout(entry, &outentry);
Miklos Szeredi0952b2a2008-02-06 01:38:38 -0800526 fuse_invalidate_attr(dir);
Al Viro30d90492012-06-22 12:40:19 +0400527 err = finish_open(file, entry, generic_file_open, opened);
528 if (err) {
Miklos Szeredi8b0797a2009-04-28 16:56:39 +0200529 fuse_sync_release(ff, flags);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200530 } else {
531 file->private_data = fuse_file_get(ff);
532 fuse_finish_open(inode, file);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800533 }
Al Virod9585272012-06-22 12:39:14 +0400534 return err;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800535
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200536out_free_ff:
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800537 fuse_file_free(ff);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200538out_put_forget_req:
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100539 kfree(forget);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200540out_err:
Al Virod9585272012-06-22 12:39:14 +0400541 return err;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200542}
543
544static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t);
Al Virod9585272012-06-22 12:39:14 +0400545static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
Al Viro30d90492012-06-22 12:40:19 +0400546 struct file *file, unsigned flags,
Al Virod9585272012-06-22 12:39:14 +0400547 umode_t mode, int *opened)
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200548{
549 int err;
550 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200551 struct dentry *res = NULL;
552
Al Viro00699ad2016-07-05 09:44:53 -0400553 if (d_in_lookup(entry)) {
Al Viro00cd8dd2012-06-10 17:13:09 -0400554 res = fuse_lookup(dir, entry, 0);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200555 if (IS_ERR(res))
Al Virod9585272012-06-22 12:39:14 +0400556 return PTR_ERR(res);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200557
558 if (res)
559 entry = res;
560 }
561
David Howells2b0143b2015-03-17 22:25:59 +0000562 if (!(flags & O_CREAT) || d_really_is_positive(entry))
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200563 goto no_open;
564
565 /* Only creates */
Al Viro47237682012-06-10 05:01:45 -0400566 *opened |= FILE_CREATED;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200567
568 if (fc->no_create)
569 goto mknod;
570
Al Viro30d90492012-06-22 12:40:19 +0400571 err = fuse_create_open(dir, entry, file, flags, mode, opened);
Al Virod9585272012-06-22 12:39:14 +0400572 if (err == -ENOSYS) {
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200573 fc->no_create = 1;
574 goto mknod;
575 }
576out_dput:
577 dput(res);
Al Virod9585272012-06-22 12:39:14 +0400578 return err;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200579
580mknod:
581 err = fuse_mknod(dir, entry, mode, 0);
Al Virod9585272012-06-22 12:39:14 +0400582 if (err)
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200583 goto out_dput;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200584no_open:
Al Viroe45198a2012-06-10 06:48:09 -0400585 return finish_no_open(file, res);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800586}
587
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800588/*
589 * Code shared between mknod, mkdir, symlink and link
590 */
Miklos Szeredi70781872014-12-12 09:49:05 +0100591static int create_new_entry(struct fuse_conn *fc, struct fuse_args *args,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700592 struct inode *dir, struct dentry *entry,
Al Viro541af6a2011-07-26 03:17:33 -0400593 umode_t mode)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700594{
595 struct fuse_entry_out outarg;
596 struct inode *inode;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700597 int err;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100598 struct fuse_forget_link *forget;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800599
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100600 forget = fuse_alloc_forget();
Miklos Szeredi70781872014-12-12 09:49:05 +0100601 if (!forget)
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100602 return -ENOMEM;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700603
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700604 memset(&outarg, 0, sizeof(outarg));
Miklos Szeredi70781872014-12-12 09:49:05 +0100605 args->in.h.nodeid = get_node_id(dir);
606 args->out.numargs = 1;
Miklos Szeredi21f62172015-01-06 10:45:35 +0100607 args->out.args[0].size = sizeof(outarg);
Miklos Szeredi70781872014-12-12 09:49:05 +0100608 args->out.args[0].value = &outarg;
609 err = fuse_simple_request(fc, args);
Miklos Szeredi2d510132006-11-25 11:09:20 -0800610 if (err)
611 goto out_put_forget_req;
612
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800613 err = -EIO;
Miklos Szeredic392b3a2019-11-12 11:49:04 +0100614 if (invalid_nodeid(outarg.nodeid) || fuse_invalid_attr(&outarg.attr))
Miklos Szeredi2d510132006-11-25 11:09:20 -0800615 goto out_put_forget_req;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800616
617 if ((outarg.attr.mode ^ mode) & S_IFMT)
Miklos Szeredi2d510132006-11-25 11:09:20 -0800618 goto out_put_forget_req;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800619
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700620 inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700621 &outarg.attr, entry_attr_timeout(&outarg), 0);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700622 if (!inode) {
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100623 fuse_queue_forget(fc, forget, outarg.nodeid, 1);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700624 return -ENOMEM;
625 }
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100626 kfree(forget);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700627
Miklos Szeredib70a80e2013-10-01 16:44:54 +0200628 err = d_instantiate_no_diralias(entry, inode);
629 if (err)
630 return err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700631
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700632 fuse_change_entry_timeout(entry, &outarg);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700633 fuse_invalidate_attr(dir);
634 return 0;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800635
Miklos Szeredi2d510132006-11-25 11:09:20 -0800636 out_put_forget_req:
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100637 kfree(forget);
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800638 return err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700639}
640
Al Viro1a67aaf2011-07-26 01:52:52 -0400641static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700642 dev_t rdev)
643{
644 struct fuse_mknod_in inarg;
645 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredi70781872014-12-12 09:49:05 +0100646 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700647
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200648 if (!fc->dont_mask)
649 mode &= ~current_umask();
650
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700651 memset(&inarg, 0, sizeof(inarg));
652 inarg.mode = mode;
653 inarg.rdev = new_encode_dev(rdev);
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200654 inarg.umask = current_umask();
Miklos Szeredi70781872014-12-12 09:49:05 +0100655 args.in.h.opcode = FUSE_MKNOD;
656 args.in.numargs = 2;
Miklos Szeredi21f62172015-01-06 10:45:35 +0100657 args.in.args[0].size = sizeof(inarg);
Miklos Szeredi70781872014-12-12 09:49:05 +0100658 args.in.args[0].value = &inarg;
659 args.in.args[1].size = entry->d_name.len + 1;
660 args.in.args[1].value = entry->d_name.name;
661 return create_new_entry(fc, &args, dir, entry, mode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700662}
663
Al Viro4acdaf22011-07-26 01:42:34 -0400664static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode,
Al Viroebfc3b42012-06-10 18:05:36 -0400665 bool excl)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700666{
667 return fuse_mknod(dir, entry, mode, 0);
668}
669
Al Viro18bb1db2011-07-26 01:41:39 -0400670static int fuse_mkdir(struct inode *dir, struct dentry *entry, umode_t mode)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700671{
672 struct fuse_mkdir_in inarg;
673 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredi70781872014-12-12 09:49:05 +0100674 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700675
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200676 if (!fc->dont_mask)
677 mode &= ~current_umask();
678
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700679 memset(&inarg, 0, sizeof(inarg));
680 inarg.mode = mode;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200681 inarg.umask = current_umask();
Miklos Szeredi70781872014-12-12 09:49:05 +0100682 args.in.h.opcode = FUSE_MKDIR;
683 args.in.numargs = 2;
684 args.in.args[0].size = sizeof(inarg);
685 args.in.args[0].value = &inarg;
686 args.in.args[1].size = entry->d_name.len + 1;
687 args.in.args[1].value = entry->d_name.name;
688 return create_new_entry(fc, &args, dir, entry, S_IFDIR);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700689}
690
691static int fuse_symlink(struct inode *dir, struct dentry *entry,
692 const char *link)
693{
694 struct fuse_conn *fc = get_fuse_conn(dir);
695 unsigned len = strlen(link) + 1;
Miklos Szeredi70781872014-12-12 09:49:05 +0100696 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700697
Miklos Szeredi70781872014-12-12 09:49:05 +0100698 args.in.h.opcode = FUSE_SYMLINK;
699 args.in.numargs = 2;
700 args.in.args[0].size = entry->d_name.len + 1;
701 args.in.args[0].value = entry->d_name.name;
702 args.in.args[1].size = len;
703 args.in.args[1].value = link;
704 return create_new_entry(fc, &args, dir, entry, S_IFLNK);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700705}
706
Seth Forshee703c7362016-08-29 08:46:36 -0500707void fuse_update_ctime(struct inode *inode)
Maxim Patlasov31f32672014-04-28 14:19:24 +0200708{
709 if (!IS_NOCMTIME(inode)) {
Deepa Dinamanic2050a42016-09-14 07:48:06 -0700710 inode->i_ctime = current_time(inode);
Maxim Patlasov31f32672014-04-28 14:19:24 +0200711 mark_inode_dirty_sync(inode);
712 }
713}
714
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700715static int fuse_unlink(struct inode *dir, struct dentry *entry)
716{
717 int err;
718 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredi70781872014-12-12 09:49:05 +0100719 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700720
Miklos Szeredi70781872014-12-12 09:49:05 +0100721 args.in.h.opcode = FUSE_UNLINK;
722 args.in.h.nodeid = get_node_id(dir);
723 args.in.numargs = 1;
724 args.in.args[0].size = entry->d_name.len + 1;
725 args.in.args[0].value = entry->d_name.name;
726 err = fuse_simple_request(fc, &args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700727 if (!err) {
David Howells2b0143b2015-03-17 22:25:59 +0000728 struct inode *inode = d_inode(entry);
Miklos Szerediac45d612012-03-05 15:48:11 +0100729 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700730
Miklos Szerediac45d612012-03-05 15:48:11 +0100731 spin_lock(&fc->lock);
732 fi->attr_version = ++fc->attr_version;
Miklos Szeredidfca7ce2013-02-04 15:57:42 +0100733 /*
734 * If i_nlink == 0 then unlink doesn't make sense, yet this can
735 * happen if userspace filesystem is careless. It would be
736 * difficult to enforce correct nlink usage so just ignore this
737 * condition here
738 */
739 if (inode->i_nlink > 0)
740 drop_nlink(inode);
Miklos Szerediac45d612012-03-05 15:48:11 +0100741 spin_unlock(&fc->lock);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700742 fuse_invalidate_attr(inode);
743 fuse_invalidate_attr(dir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800744 fuse_invalidate_entry_cache(entry);
Maxim Patlasov31f32672014-04-28 14:19:24 +0200745 fuse_update_ctime(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700746 } else if (err == -EINTR)
747 fuse_invalidate_entry(entry);
748 return err;
749}
750
751static int fuse_rmdir(struct inode *dir, struct dentry *entry)
752{
753 int err;
754 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredi70781872014-12-12 09:49:05 +0100755 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700756
Miklos Szeredi70781872014-12-12 09:49:05 +0100757 args.in.h.opcode = FUSE_RMDIR;
758 args.in.h.nodeid = get_node_id(dir);
759 args.in.numargs = 1;
760 args.in.args[0].size = entry->d_name.len + 1;
761 args.in.args[0].value = entry->d_name.name;
762 err = fuse_simple_request(fc, &args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700763 if (!err) {
David Howells2b0143b2015-03-17 22:25:59 +0000764 clear_nlink(d_inode(entry));
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700765 fuse_invalidate_attr(dir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800766 fuse_invalidate_entry_cache(entry);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700767 } else if (err == -EINTR)
768 fuse_invalidate_entry(entry);
769 return err;
770}
771
Miklos Szeredi1560c972014-04-28 16:43:44 +0200772static int fuse_rename_common(struct inode *olddir, struct dentry *oldent,
773 struct inode *newdir, struct dentry *newent,
774 unsigned int flags, int opcode, size_t argsize)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700775{
776 int err;
Miklos Szeredi1560c972014-04-28 16:43:44 +0200777 struct fuse_rename2_in inarg;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700778 struct fuse_conn *fc = get_fuse_conn(olddir);
Miklos Szeredi70781872014-12-12 09:49:05 +0100779 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700780
Miklos Szeredi1560c972014-04-28 16:43:44 +0200781 memset(&inarg, 0, argsize);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700782 inarg.newdir = get_node_id(newdir);
Miklos Szeredi1560c972014-04-28 16:43:44 +0200783 inarg.flags = flags;
Miklos Szeredi70781872014-12-12 09:49:05 +0100784 args.in.h.opcode = opcode;
785 args.in.h.nodeid = get_node_id(olddir);
786 args.in.numargs = 3;
787 args.in.args[0].size = argsize;
788 args.in.args[0].value = &inarg;
789 args.in.args[1].size = oldent->d_name.len + 1;
790 args.in.args[1].value = oldent->d_name.name;
791 args.in.args[2].size = newent->d_name.len + 1;
792 args.in.args[2].value = newent->d_name.name;
793 err = fuse_simple_request(fc, &args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700794 if (!err) {
Miklos Szeredi08b63302007-11-28 16:22:03 -0800795 /* ctime changes */
David Howells2b0143b2015-03-17 22:25:59 +0000796 fuse_invalidate_attr(d_inode(oldent));
797 fuse_update_ctime(d_inode(oldent));
Miklos Szeredi08b63302007-11-28 16:22:03 -0800798
Miklos Szeredi1560c972014-04-28 16:43:44 +0200799 if (flags & RENAME_EXCHANGE) {
David Howells2b0143b2015-03-17 22:25:59 +0000800 fuse_invalidate_attr(d_inode(newent));
801 fuse_update_ctime(d_inode(newent));
Miklos Szeredi1560c972014-04-28 16:43:44 +0200802 }
803
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700804 fuse_invalidate_attr(olddir);
805 if (olddir != newdir)
806 fuse_invalidate_attr(newdir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800807
808 /* newent will end up negative */
David Howells2b0143b2015-03-17 22:25:59 +0000809 if (!(flags & RENAME_EXCHANGE) && d_really_is_positive(newent)) {
810 fuse_invalidate_attr(d_inode(newent));
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800811 fuse_invalidate_entry_cache(newent);
David Howells2b0143b2015-03-17 22:25:59 +0000812 fuse_update_ctime(d_inode(newent));
Miklos Szeredi5219f342009-11-04 10:24:52 +0100813 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700814 } else if (err == -EINTR) {
815 /* If request was interrupted, DEITY only knows if the
816 rename actually took place. If the invalidation
817 fails (e.g. some process has CWD under the renamed
818 directory), then there can be inconsistency between
819 the dcache and the real filesystem. Tough luck. */
820 fuse_invalidate_entry(oldent);
David Howells2b0143b2015-03-17 22:25:59 +0000821 if (d_really_is_positive(newent))
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700822 fuse_invalidate_entry(newent);
823 }
824
825 return err;
826}
827
Miklos Szeredi1560c972014-04-28 16:43:44 +0200828static int fuse_rename2(struct inode *olddir, struct dentry *oldent,
829 struct inode *newdir, struct dentry *newent,
830 unsigned int flags)
831{
832 struct fuse_conn *fc = get_fuse_conn(olddir);
833 int err;
834
835 if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE))
836 return -EINVAL;
837
Miklos Szeredi4237ba42014-07-10 10:50:19 +0200838 if (flags) {
839 if (fc->no_rename2 || fc->minor < 23)
840 return -EINVAL;
Miklos Szeredi1560c972014-04-28 16:43:44 +0200841
Miklos Szeredi4237ba42014-07-10 10:50:19 +0200842 err = fuse_rename_common(olddir, oldent, newdir, newent, flags,
843 FUSE_RENAME2,
844 sizeof(struct fuse_rename2_in));
845 if (err == -ENOSYS) {
846 fc->no_rename2 = 1;
847 err = -EINVAL;
848 }
849 } else {
850 err = fuse_rename_common(olddir, oldent, newdir, newent, 0,
851 FUSE_RENAME,
852 sizeof(struct fuse_rename_in));
Miklos Szeredi1560c972014-04-28 16:43:44 +0200853 }
Miklos Szeredi1560c972014-04-28 16:43:44 +0200854
Miklos Szeredi4237ba42014-07-10 10:50:19 +0200855 return err;
856}
857
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700858static int fuse_link(struct dentry *entry, struct inode *newdir,
859 struct dentry *newent)
860{
861 int err;
862 struct fuse_link_in inarg;
David Howells2b0143b2015-03-17 22:25:59 +0000863 struct inode *inode = d_inode(entry);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700864 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi70781872014-12-12 09:49:05 +0100865 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700866
867 memset(&inarg, 0, sizeof(inarg));
868 inarg.oldnodeid = get_node_id(inode);
Miklos Szeredi70781872014-12-12 09:49:05 +0100869 args.in.h.opcode = FUSE_LINK;
870 args.in.numargs = 2;
871 args.in.args[0].size = sizeof(inarg);
872 args.in.args[0].value = &inarg;
873 args.in.args[1].size = newent->d_name.len + 1;
874 args.in.args[1].value = newent->d_name.name;
875 err = create_new_entry(fc, &args, newdir, newent, inode->i_mode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700876 /* Contrary to "normal" filesystems it can happen that link
877 makes two "logical" inodes point to the same "physical"
878 inode. We invalidate the attributes of the old one, so it
879 will reflect changes in the backing inode (link count,
880 etc.)
881 */
Miklos Szerediac45d612012-03-05 15:48:11 +0100882 if (!err) {
883 struct fuse_inode *fi = get_fuse_inode(inode);
884
885 spin_lock(&fc->lock);
886 fi->attr_version = ++fc->attr_version;
Miklos Szeredi38969fe2019-11-12 11:49:04 +0100887 if (likely(inode->i_nlink < UINT_MAX))
888 inc_nlink(inode);
Miklos Szerediac45d612012-03-05 15:48:11 +0100889 spin_unlock(&fc->lock);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700890 fuse_invalidate_attr(inode);
Maxim Patlasov31f32672014-04-28 14:19:24 +0200891 fuse_update_ctime(inode);
Miklos Szerediac45d612012-03-05 15:48:11 +0100892 } else if (err == -EINTR) {
893 fuse_invalidate_attr(inode);
894 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700895 return err;
896}
897
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700898static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
899 struct kstat *stat)
900{
Miklos Szeredi203627b2012-05-10 19:49:38 +0400901 unsigned int blkbits;
Pavel Emelyanov83732002013-10-10 17:10:46 +0400902 struct fuse_conn *fc = get_fuse_conn(inode);
903
904 /* see the comment in fuse_change_attributes() */
Maxim Patlasovb0aa7602013-12-26 19:51:11 +0400905 if (fc->writeback_cache && S_ISREG(inode->i_mode)) {
Pavel Emelyanov83732002013-10-10 17:10:46 +0400906 attr->size = i_size_read(inode);
Maxim Patlasovb0aa7602013-12-26 19:51:11 +0400907 attr->mtime = inode->i_mtime.tv_sec;
908 attr->mtimensec = inode->i_mtime.tv_nsec;
Maxim Patlasov31f32672014-04-28 14:19:24 +0200909 attr->ctime = inode->i_ctime.tv_sec;
910 attr->ctimensec = inode->i_ctime.tv_nsec;
Maxim Patlasovb0aa7602013-12-26 19:51:11 +0400911 }
Miklos Szeredi203627b2012-05-10 19:49:38 +0400912
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700913 stat->dev = inode->i_sb->s_dev;
914 stat->ino = attr->ino;
915 stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
916 stat->nlink = attr->nlink;
Eric W. Biederman499dcf22012-02-07 16:26:03 -0800917 stat->uid = make_kuid(&init_user_ns, attr->uid);
918 stat->gid = make_kgid(&init_user_ns, attr->gid);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700919 stat->rdev = inode->i_rdev;
920 stat->atime.tv_sec = attr->atime;
921 stat->atime.tv_nsec = attr->atimensec;
922 stat->mtime.tv_sec = attr->mtime;
923 stat->mtime.tv_nsec = attr->mtimensec;
924 stat->ctime.tv_sec = attr->ctime;
925 stat->ctime.tv_nsec = attr->ctimensec;
926 stat->size = attr->size;
927 stat->blocks = attr->blocks;
Miklos Szeredi203627b2012-05-10 19:49:38 +0400928
929 if (attr->blksize != 0)
930 blkbits = ilog2(attr->blksize);
931 else
932 blkbits = inode->i_sb->s_blocksize_bits;
933
934 stat->blksize = 1 << blkbits;
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700935}
936
Miklos Szeredic79e3222007-10-18 03:06:59 -0700937static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
938 struct file *file)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700939{
940 int err;
Miklos Szeredic79e3222007-10-18 03:06:59 -0700941 struct fuse_getattr_in inarg;
942 struct fuse_attr_out outarg;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700943 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi70781872014-12-12 09:49:05 +0100944 FUSE_ARGS(args);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700945 u64 attr_version;
946
Miklos Szeredi7dca9fd2007-11-28 16:21:59 -0800947 attr_version = fuse_get_attr_version(fc);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700948
Miklos Szeredic79e3222007-10-18 03:06:59 -0700949 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700950 memset(&outarg, 0, sizeof(outarg));
Miklos Szeredic79e3222007-10-18 03:06:59 -0700951 /* Directories have separate file-handle space */
952 if (file && S_ISREG(inode->i_mode)) {
953 struct fuse_file *ff = file->private_data;
954
955 inarg.getattr_flags |= FUSE_GETATTR_FH;
956 inarg.fh = ff->fh;
957 }
Miklos Szeredi70781872014-12-12 09:49:05 +0100958 args.in.h.opcode = FUSE_GETATTR;
959 args.in.h.nodeid = get_node_id(inode);
960 args.in.numargs = 1;
961 args.in.args[0].size = sizeof(inarg);
962 args.in.args[0].value = &inarg;
963 args.out.numargs = 1;
Miklos Szeredi21f62172015-01-06 10:45:35 +0100964 args.out.args[0].size = sizeof(outarg);
Miklos Szeredi70781872014-12-12 09:49:05 +0100965 args.out.args[0].value = &outarg;
966 err = fuse_simple_request(fc, &args);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700967 if (!err) {
Miklos Szeredic392b3a2019-11-12 11:49:04 +0100968 if (fuse_invalid_attr(&outarg.attr) ||
969 (inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
Miklos Szeredie5e55582005-09-09 13:10:28 -0700970 make_bad_inode(inode);
971 err = -EIO;
972 } else {
Miklos Szeredic79e3222007-10-18 03:06:59 -0700973 fuse_change_attributes(inode, &outarg.attr,
974 attr_timeout(&outarg),
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700975 attr_version);
976 if (stat)
Miklos Szeredic79e3222007-10-18 03:06:59 -0700977 fuse_fillattr(inode, &outarg.attr, stat);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700978 }
979 }
980 return err;
981}
982
Miklos Szeredibcb4be82007-11-28 16:21:59 -0800983int fuse_update_attributes(struct inode *inode, struct kstat *stat,
984 struct file *file, bool *refreshed)
985{
986 struct fuse_inode *fi = get_fuse_inode(inode);
987 int err;
988 bool r;
989
Miklos Szeredi126b9d42014-07-07 15:28:50 +0200990 if (time_before64(fi->i_time, get_jiffies_64())) {
Miklos Szeredibcb4be82007-11-28 16:21:59 -0800991 r = true;
Seth Forshee60bcc882016-08-29 08:46:37 -0500992 forget_all_cached_acls(inode);
Miklos Szeredibcb4be82007-11-28 16:21:59 -0800993 err = fuse_do_getattr(inode, stat, file);
994 } else {
995 r = false;
996 err = 0;
997 if (stat) {
998 generic_fillattr(inode, stat);
999 stat->mode = fi->orig_i_mode;
Pavel Shilovsky45c72cd2012-05-10 19:49:38 +04001000 stat->ino = fi->orig_ino;
Miklos Szeredibcb4be82007-11-28 16:21:59 -08001001 }
1002 }
1003
1004 if (refreshed != NULL)
1005 *refreshed = r;
1006
1007 return err;
1008}
1009
John Muir3b463ae2009-05-31 11:13:57 -04001010int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid,
John Muir451d0f52011-12-06 21:50:06 +01001011 u64 child_nodeid, struct qstr *name)
John Muir3b463ae2009-05-31 11:13:57 -04001012{
1013 int err = -ENOTDIR;
1014 struct inode *parent;
1015 struct dentry *dir;
1016 struct dentry *entry;
1017
1018 parent = ilookup5(sb, parent_nodeid, fuse_inode_eq, &parent_nodeid);
1019 if (!parent)
1020 return -ENOENT;
1021
Al Viro59551022016-01-22 15:40:57 -05001022 inode_lock(parent);
John Muir3b463ae2009-05-31 11:13:57 -04001023 if (!S_ISDIR(parent->i_mode))
1024 goto unlock;
1025
1026 err = -ENOENT;
1027 dir = d_find_alias(parent);
1028 if (!dir)
1029 goto unlock;
1030
Linus Torvalds8387ff22016-06-10 07:51:30 -07001031 name->hash = full_name_hash(dir, name->name, name->len);
John Muir3b463ae2009-05-31 11:13:57 -04001032 entry = d_lookup(dir, name);
1033 dput(dir);
1034 if (!entry)
1035 goto unlock;
1036
1037 fuse_invalidate_attr(parent);
1038 fuse_invalidate_entry(entry);
John Muir451d0f52011-12-06 21:50:06 +01001039
David Howells2b0143b2015-03-17 22:25:59 +00001040 if (child_nodeid != 0 && d_really_is_positive(entry)) {
Al Viro59551022016-01-22 15:40:57 -05001041 inode_lock(d_inode(entry));
David Howells2b0143b2015-03-17 22:25:59 +00001042 if (get_node_id(d_inode(entry)) != child_nodeid) {
John Muir451d0f52011-12-06 21:50:06 +01001043 err = -ENOENT;
1044 goto badentry;
1045 }
1046 if (d_mountpoint(entry)) {
1047 err = -EBUSY;
1048 goto badentry;
1049 }
David Howellse36cb0b2015-01-29 12:02:35 +00001050 if (d_is_dir(entry)) {
John Muir451d0f52011-12-06 21:50:06 +01001051 shrink_dcache_parent(entry);
1052 if (!simple_empty(entry)) {
1053 err = -ENOTEMPTY;
1054 goto badentry;
1055 }
David Howells2b0143b2015-03-17 22:25:59 +00001056 d_inode(entry)->i_flags |= S_DEAD;
John Muir451d0f52011-12-06 21:50:06 +01001057 }
1058 dont_mount(entry);
David Howells2b0143b2015-03-17 22:25:59 +00001059 clear_nlink(d_inode(entry));
John Muir451d0f52011-12-06 21:50:06 +01001060 err = 0;
1061 badentry:
Al Viro59551022016-01-22 15:40:57 -05001062 inode_unlock(d_inode(entry));
John Muir451d0f52011-12-06 21:50:06 +01001063 if (!err)
1064 d_delete(entry);
1065 } else {
1066 err = 0;
1067 }
John Muir3b463ae2009-05-31 11:13:57 -04001068 dput(entry);
John Muir3b463ae2009-05-31 11:13:57 -04001069
1070 unlock:
Al Viro59551022016-01-22 15:40:57 -05001071 inode_unlock(parent);
John Muir3b463ae2009-05-31 11:13:57 -04001072 iput(parent);
1073 return err;
1074}
1075
Miklos Szeredi87729a52005-09-09 13:10:34 -07001076/*
1077 * Calling into a user-controlled filesystem gives the filesystem
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001078 * daemon ptrace-like capabilities over the current process. This
Miklos Szeredi87729a52005-09-09 13:10:34 -07001079 * means, that the filesystem daemon is able to record the exact
1080 * filesystem operations performed, and can also control the behavior
1081 * of the requester process in otherwise impossible ways. For example
1082 * it can delay the operation for arbitrary length of time allowing
1083 * DoS against the requester.
1084 *
1085 * For this reason only those processes can call into the filesystem,
1086 * for which the owner of the mount has ptrace privilege. This
1087 * excludes processes started by other users, suid or sgid processes.
1088 */
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001089int fuse_allow_current_process(struct fuse_conn *fc)
Miklos Szeredi87729a52005-09-09 13:10:34 -07001090{
David Howellsc69e8d92008-11-14 10:39:19 +11001091 const struct cred *cred;
David Howellsc69e8d92008-11-14 10:39:19 +11001092
Miklos Szeredi29433a22016-10-01 07:32:32 +02001093 if (fc->allow_other)
Miklos Szeredi87729a52005-09-09 13:10:34 -07001094 return 1;
1095
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001096 cred = current_cred();
Eric W. Biederman499dcf22012-02-07 16:26:03 -08001097 if (uid_eq(cred->euid, fc->user_id) &&
1098 uid_eq(cred->suid, fc->user_id) &&
1099 uid_eq(cred->uid, fc->user_id) &&
1100 gid_eq(cred->egid, fc->group_id) &&
1101 gid_eq(cred->sgid, fc->group_id) &&
1102 gid_eq(cred->gid, fc->group_id))
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001103 return 1;
Miklos Szeredi87729a52005-09-09 13:10:34 -07001104
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001105 return 0;
Miklos Szeredi87729a52005-09-09 13:10:34 -07001106}
1107
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001108static int fuse_access(struct inode *inode, int mask)
1109{
1110 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi70781872014-12-12 09:49:05 +01001111 FUSE_ARGS(args);
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001112 struct fuse_access_in inarg;
1113 int err;
1114
Miklos Szeredi698fa1d2013-10-01 16:41:23 +02001115 BUG_ON(mask & MAY_NOT_BLOCK);
1116
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001117 if (fc->no_access)
1118 return 0;
1119
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001120 memset(&inarg, 0, sizeof(inarg));
Al Viroe6305c42008-07-15 21:03:57 -04001121 inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC);
Miklos Szeredi70781872014-12-12 09:49:05 +01001122 args.in.h.opcode = FUSE_ACCESS;
1123 args.in.h.nodeid = get_node_id(inode);
1124 args.in.numargs = 1;
1125 args.in.args[0].size = sizeof(inarg);
1126 args.in.args[0].value = &inarg;
1127 err = fuse_simple_request(fc, &args);
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001128 if (err == -ENOSYS) {
1129 fc->no_access = 1;
1130 err = 0;
1131 }
1132 return err;
1133}
1134
Al Viro10556cb2011-06-20 19:28:19 -04001135static int fuse_perm_getattr(struct inode *inode, int mask)
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001136{
Al Viro10556cb2011-06-20 19:28:19 -04001137 if (mask & MAY_NOT_BLOCK)
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001138 return -ECHILD;
1139
Seth Forshee60bcc882016-08-29 08:46:37 -05001140 forget_all_cached_acls(inode);
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001141 return fuse_do_getattr(inode, NULL, NULL);
1142}
1143
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001144/*
1145 * Check permission. The two basic access models of FUSE are:
1146 *
1147 * 1) Local access checking ('default_permissions' mount option) based
1148 * on file mode. This is the plain old disk filesystem permission
1149 * modell.
1150 *
1151 * 2) "Remote" access checking, where server is responsible for
1152 * checking permission in each inode operation. An exception to this
1153 * is if ->permission() was invoked from sys_access() in which case an
1154 * access request is sent. Execute permission is still checked
1155 * locally based on file mode.
1156 */
Al Viro10556cb2011-06-20 19:28:19 -04001157static int fuse_permission(struct inode *inode, int mask)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001158{
1159 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi244f6382007-10-16 23:31:02 -07001160 bool refreshed = false;
1161 int err = 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001162
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001163 if (!fuse_allow_current_process(fc))
Miklos Szeredie5e55582005-09-09 13:10:28 -07001164 return -EACCES;
Miklos Szeredi244f6382007-10-16 23:31:02 -07001165
1166 /*
Miklos Szeredie8e96152007-10-16 23:31:06 -07001167 * If attributes are needed, refresh them before proceeding
Miklos Szeredi244f6382007-10-16 23:31:02 -07001168 */
Miklos Szeredi29433a22016-10-01 07:32:32 +02001169 if (fc->default_permissions ||
Miklos Szeredie8e96152007-10-16 23:31:06 -07001170 ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001171 struct fuse_inode *fi = get_fuse_inode(inode);
1172
Miklos Szeredi126b9d42014-07-07 15:28:50 +02001173 if (time_before64(fi->i_time, get_jiffies_64())) {
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001174 refreshed = true;
1175
Al Viro10556cb2011-06-20 19:28:19 -04001176 err = fuse_perm_getattr(inode, mask);
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001177 if (err)
1178 return err;
1179 }
Miklos Szeredi244f6382007-10-16 23:31:02 -07001180 }
1181
Miklos Szeredi29433a22016-10-01 07:32:32 +02001182 if (fc->default_permissions) {
Al Viro2830ba72011-06-20 19:16:29 -04001183 err = generic_permission(inode, mask);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001184
1185 /* If permission is denied, try to refresh file
1186 attributes. This is also needed, because the root
1187 node will at first have no permissions */
Miklos Szeredi244f6382007-10-16 23:31:02 -07001188 if (err == -EACCES && !refreshed) {
Al Viro10556cb2011-06-20 19:28:19 -04001189 err = fuse_perm_getattr(inode, mask);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001190 if (!err)
Al Viro2830ba72011-06-20 19:16:29 -04001191 err = generic_permission(inode, mask);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001192 }
1193
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001194 /* Note: the opposite of the above test does not
1195 exist. So if permissions are revoked this won't be
1196 noticed immediately, only after the attribute
1197 timeout has expired */
Eric Paris9cfcac82010-07-23 11:43:51 -04001198 } else if (mask & (MAY_ACCESS | MAY_CHDIR)) {
Miklos Szeredie8e96152007-10-16 23:31:06 -07001199 err = fuse_access(inode, mask);
1200 } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
1201 if (!(inode->i_mode & S_IXUGO)) {
1202 if (refreshed)
1203 return -EACCES;
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001204
Al Viro10556cb2011-06-20 19:28:19 -04001205 err = fuse_perm_getattr(inode, mask);
Miklos Szeredie8e96152007-10-16 23:31:06 -07001206 if (!err && !(inode->i_mode & S_IXUGO))
1207 return -EACCES;
1208 }
Miklos Szeredie5e55582005-09-09 13:10:28 -07001209 }
Miklos Szeredi244f6382007-10-16 23:31:02 -07001210 return err;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001211}
1212
1213static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
Al Viro8d3af7f2013-05-18 03:03:58 -04001214 struct dir_context *ctx)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001215{
1216 while (nbytes >= FUSE_NAME_OFFSET) {
1217 struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
1218 size_t reclen = FUSE_DIRENT_SIZE(dirent);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001219 if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
1220 return -EIO;
1221 if (reclen > nbytes)
1222 break;
Miklos Szerediefeb9e62013-09-03 14:28:38 +02001223 if (memchr(dirent->name, '/', dirent->namelen) != NULL)
1224 return -EIO;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001225
Al Viro8d3af7f2013-05-18 03:03:58 -04001226 if (!dir_emit(ctx, dirent->name, dirent->namelen,
1227 dirent->ino, dirent->type))
Miklos Szeredie5e55582005-09-09 13:10:28 -07001228 break;
1229
1230 buf += reclen;
1231 nbytes -= reclen;
Al Viro8d3af7f2013-05-18 03:03:58 -04001232 ctx->pos = dirent->off;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001233 }
1234
1235 return 0;
1236}
1237
Anand V. Avati0b05b182012-08-19 08:53:23 -04001238static int fuse_direntplus_link(struct file *file,
1239 struct fuse_direntplus *direntplus,
1240 u64 attr_version)
1241{
Anand V. Avati0b05b182012-08-19 08:53:23 -04001242 struct fuse_entry_out *o = &direntplus->entry_out;
1243 struct fuse_dirent *dirent = &direntplus->dirent;
1244 struct dentry *parent = file->f_path.dentry;
1245 struct qstr name = QSTR_INIT(dirent->name, dirent->namelen);
1246 struct dentry *dentry;
1247 struct dentry *alias;
David Howells2b0143b2015-03-17 22:25:59 +00001248 struct inode *dir = d_inode(parent);
Anand V. Avati0b05b182012-08-19 08:53:23 -04001249 struct fuse_conn *fc;
1250 struct inode *inode;
Al Virod9b3dbd2016-04-20 17:30:32 -04001251 DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
Anand V. Avati0b05b182012-08-19 08:53:23 -04001252
1253 if (!o->nodeid) {
1254 /*
1255 * Unlike in the case of fuse_lookup, zero nodeid does not mean
1256 * ENOENT. Instead, it only means the userspace filesystem did
1257 * not want to return attributes/handle for this entry.
1258 *
1259 * So do nothing.
1260 */
1261 return 0;
1262 }
1263
1264 if (name.name[0] == '.') {
1265 /*
1266 * We could potentially refresh the attributes of the directory
1267 * and its parent?
1268 */
1269 if (name.len == 1)
1270 return 0;
1271 if (name.name[1] == '.' && name.len == 2)
1272 return 0;
1273 }
Miklos Szeredia28ef452013-07-17 14:53:53 +02001274
1275 if (invalid_nodeid(o->nodeid))
1276 return -EIO;
Miklos Szeredic392b3a2019-11-12 11:49:04 +01001277 if (fuse_invalid_attr(&o->attr))
Miklos Szeredia28ef452013-07-17 14:53:53 +02001278 return -EIO;
1279
Anand V. Avati0b05b182012-08-19 08:53:23 -04001280 fc = get_fuse_conn(dir);
1281
Linus Torvalds8387ff22016-06-10 07:51:30 -07001282 name.hash = full_name_hash(parent, name.name, name.len);
Anand V. Avati0b05b182012-08-19 08:53:23 -04001283 dentry = d_lookup(parent, &name);
Al Virod9b3dbd2016-04-20 17:30:32 -04001284 if (!dentry) {
1285retry:
1286 dentry = d_alloc_parallel(parent, &name, &wq);
1287 if (IS_ERR(dentry))
1288 return PTR_ERR(dentry);
1289 }
1290 if (!d_in_lookup(dentry)) {
1291 struct fuse_inode *fi;
David Howells2b0143b2015-03-17 22:25:59 +00001292 inode = d_inode(dentry);
Al Virod9b3dbd2016-04-20 17:30:32 -04001293 if (!inode ||
1294 get_node_id(inode) != o->nodeid ||
1295 ((o->attr.mode ^ inode->i_mode) & S_IFMT)) {
Eric W. Biederman5542aa22014-02-13 09:46:25 -08001296 d_invalidate(dentry);
Al Virod9b3dbd2016-04-20 17:30:32 -04001297 dput(dentry);
1298 goto retry;
Anand V. Avati0b05b182012-08-19 08:53:23 -04001299 }
Al Virod9b3dbd2016-04-20 17:30:32 -04001300 if (is_bad_inode(inode)) {
1301 dput(dentry);
1302 return -EIO;
1303 }
1304
1305 fi = get_fuse_inode(inode);
1306 spin_lock(&fc->lock);
1307 fi->nlookup++;
1308 spin_unlock(&fc->lock);
1309
Seth Forshee60bcc882016-08-29 08:46:37 -05001310 forget_all_cached_acls(inode);
Al Virod9b3dbd2016-04-20 17:30:32 -04001311 fuse_change_attributes(inode, &o->attr,
1312 entry_attr_timeout(o),
1313 attr_version);
1314 /*
1315 * The other branch comes via fuse_iget()
1316 * which bumps nlookup inside
1317 */
1318 } else {
1319 inode = fuse_iget(dir->i_sb, o->nodeid, o->generation,
1320 &o->attr, entry_attr_timeout(o),
1321 attr_version);
1322 if (!inode)
1323 inode = ERR_PTR(-ENOMEM);
1324
1325 alias = d_splice_alias(inode, dentry);
1326 d_lookup_done(dentry);
1327 if (alias) {
1328 dput(dentry);
1329 dentry = alias;
1330 }
1331 if (IS_ERR(dentry))
1332 return PTR_ERR(dentry);
Anand V. Avati0b05b182012-08-19 08:53:23 -04001333 }
Miklos Szeredi6314efe2013-10-01 16:41:22 +02001334 if (fc->readdirplus_auto)
1335 set_bit(FUSE_I_INIT_RDPLUS, &get_fuse_inode(inode)->state);
Anand V. Avati0b05b182012-08-19 08:53:23 -04001336 fuse_change_entry_timeout(dentry, o);
1337
Miklos Szeredic7263bc2013-07-17 14:53:54 +02001338 dput(dentry);
Al Virod9b3dbd2016-04-20 17:30:32 -04001339 return 0;
Anand V. Avati0b05b182012-08-19 08:53:23 -04001340}
1341
1342static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file,
Al Viro8d3af7f2013-05-18 03:03:58 -04001343 struct dir_context *ctx, u64 attr_version)
Anand V. Avati0b05b182012-08-19 08:53:23 -04001344{
1345 struct fuse_direntplus *direntplus;
1346 struct fuse_dirent *dirent;
1347 size_t reclen;
1348 int over = 0;
1349 int ret;
1350
1351 while (nbytes >= FUSE_NAME_OFFSET_DIRENTPLUS) {
1352 direntplus = (struct fuse_direntplus *) buf;
1353 dirent = &direntplus->dirent;
1354 reclen = FUSE_DIRENTPLUS_SIZE(direntplus);
1355
1356 if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
1357 return -EIO;
1358 if (reclen > nbytes)
1359 break;
Miklos Szerediefeb9e62013-09-03 14:28:38 +02001360 if (memchr(dirent->name, '/', dirent->namelen) != NULL)
1361 return -EIO;
Anand V. Avati0b05b182012-08-19 08:53:23 -04001362
1363 if (!over) {
1364 /* We fill entries into dstbuf only as much as
1365 it can hold. But we still continue iterating
1366 over remaining entries to link them. If not,
1367 we need to send a FORGET for each of those
1368 which we did not link.
1369 */
Al Viro8d3af7f2013-05-18 03:03:58 -04001370 over = !dir_emit(ctx, dirent->name, dirent->namelen,
1371 dirent->ino, dirent->type);
Miklos Szeredi87838852017-10-25 16:34:27 +02001372 if (!over)
1373 ctx->pos = dirent->off;
Anand V. Avati0b05b182012-08-19 08:53:23 -04001374 }
1375
1376 buf += reclen;
1377 nbytes -= reclen;
1378
1379 ret = fuse_direntplus_link(file, direntplus, attr_version);
1380 if (ret)
1381 fuse_force_forget(file, direntplus->entry_out.nodeid);
1382 }
1383
1384 return 0;
1385}
1386
Al Viro8d3af7f2013-05-18 03:03:58 -04001387static int fuse_readdir(struct file *file, struct dir_context *ctx)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001388{
Feng Shuo4582a4a2013-01-15 11:23:28 +08001389 int plus, err;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001390 size_t nbytes;
1391 struct page *page;
Al Viro496ad9a2013-01-23 17:07:38 -05001392 struct inode *inode = file_inode(file);
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001393 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi248d86e2006-01-06 00:19:39 -08001394 struct fuse_req *req;
Anand V. Avati0b05b182012-08-19 08:53:23 -04001395 u64 attr_version = 0;
Miklos Szeredi68fbfcb2018-07-26 16:13:11 +02001396 bool locked;
Miklos Szeredi248d86e2006-01-06 00:19:39 -08001397
1398 if (is_bad_inode(inode))
1399 return -EIO;
1400
Maxim Patlasovb111c8c2012-10-26 19:48:30 +04001401 req = fuse_get_req(fc, 1);
Miklos Szeredice1d5a42006-04-10 22:54:58 -07001402 if (IS_ERR(req))
1403 return PTR_ERR(req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001404
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001405 page = alloc_page(GFP_KERNEL);
1406 if (!page) {
1407 fuse_put_request(fc, req);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001408 return -ENOMEM;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001409 }
Feng Shuo4582a4a2013-01-15 11:23:28 +08001410
Al Viro8d3af7f2013-05-18 03:03:58 -04001411 plus = fuse_use_readdirplus(inode, ctx);
Miklos Szeredif4975c62009-04-02 14:25:34 +02001412 req->out.argpages = 1;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001413 req->num_pages = 1;
1414 req->pages[0] = page;
Maxim Patlasov85f40ae2012-10-26 19:49:33 +04001415 req->page_descs[0].length = PAGE_SIZE;
Feng Shuo4582a4a2013-01-15 11:23:28 +08001416 if (plus) {
Anand V. Avati0b05b182012-08-19 08:53:23 -04001417 attr_version = fuse_get_attr_version(fc);
Al Viro8d3af7f2013-05-18 03:03:58 -04001418 fuse_read_fill(req, file, ctx->pos, PAGE_SIZE,
Anand V. Avati0b05b182012-08-19 08:53:23 -04001419 FUSE_READDIRPLUS);
1420 } else {
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_READDIR);
1423 }
Miklos Szeredi68fbfcb2018-07-26 16:13:11 +02001424 locked = fuse_lock_inode(inode);
Tejun Heob93f8582008-11-26 12:03:55 +01001425 fuse_request_send(fc, req);
Miklos Szeredi68fbfcb2018-07-26 16:13:11 +02001426 fuse_unlock_inode(inode, locked);
Miklos Szeredi361b1eb52006-01-16 22:14:45 -08001427 nbytes = req->out.args[0].size;
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001428 err = req->out.h.error;
1429 fuse_put_request(fc, req);
Anand V. Avati0b05b182012-08-19 08:53:23 -04001430 if (!err) {
Feng Shuo4582a4a2013-01-15 11:23:28 +08001431 if (plus) {
Anand V. Avati0b05b182012-08-19 08:53:23 -04001432 err = parse_dirplusfile(page_address(page), nbytes,
Al Viro8d3af7f2013-05-18 03:03:58 -04001433 file, ctx,
Anand V. Avati0b05b182012-08-19 08:53:23 -04001434 attr_version);
1435 } else {
1436 err = parse_dirfile(page_address(page), nbytes, file,
Al Viro8d3af7f2013-05-18 03:03:58 -04001437 ctx);
Anand V. Avati0b05b182012-08-19 08:53:23 -04001438 }
1439 }
Miklos Szeredie5e55582005-09-09 13:10:28 -07001440
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001441 __free_page(page);
Andrew Gallagher451418f2013-11-05 03:55:43 -08001442 fuse_invalidate_atime(inode);
Miklos Szeredi04730fe2005-09-09 13:10:36 -07001443 return err;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001444}
1445
Al Viro6b255392015-11-17 10:20:54 -05001446static const char *fuse_get_link(struct dentry *dentry,
Al Virofceef392015-12-29 15:58:39 -05001447 struct inode *inode,
1448 struct delayed_call *done)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001449{
Miklos Szeredie5e55582005-09-09 13:10:28 -07001450 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi70781872014-12-12 09:49:05 +01001451 FUSE_ARGS(args);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001452 char *link;
Miklos Szeredi70781872014-12-12 09:49:05 +01001453 ssize_t ret;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001454
Al Viro6b255392015-11-17 10:20:54 -05001455 if (!dentry)
1456 return ERR_PTR(-ECHILD);
1457
Al Virocd3417c2015-12-29 16:03:53 -05001458 link = kmalloc(PAGE_SIZE, GFP_KERNEL);
Miklos Szeredi70781872014-12-12 09:49:05 +01001459 if (!link)
1460 return ERR_PTR(-ENOMEM);
1461
1462 args.in.h.opcode = FUSE_READLINK;
1463 args.in.h.nodeid = get_node_id(inode);
1464 args.out.argvar = 1;
1465 args.out.numargs = 1;
1466 args.out.args[0].size = PAGE_SIZE - 1;
1467 args.out.args[0].value = link;
1468 ret = fuse_simple_request(fc, &args);
1469 if (ret < 0) {
Al Virocd3417c2015-12-29 16:03:53 -05001470 kfree(link);
Miklos Szeredi70781872014-12-12 09:49:05 +01001471 link = ERR_PTR(ret);
1472 } else {
1473 link[ret] = '\0';
Al Virofceef392015-12-29 15:58:39 -05001474 set_delayed_call(done, kfree_link, link);
Miklos Szeredi70781872014-12-12 09:49:05 +01001475 }
Andrew Gallagher451418f2013-11-05 03:55:43 -08001476 fuse_invalidate_atime(inode);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001477 return link;
1478}
1479
Miklos Szeredie5e55582005-09-09 13:10:28 -07001480static int fuse_dir_open(struct inode *inode, struct file *file)
1481{
Miklos Szeredi91fe96b2009-04-28 16:56:37 +02001482 return fuse_open_common(inode, file, true);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001483}
1484
1485static int fuse_dir_release(struct inode *inode, struct file *file)
1486{
Miklos Szeredi8b0797a2009-04-28 16:56:39 +02001487 fuse_release_common(file, FUSE_RELEASEDIR);
1488
1489 return 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001490}
1491
Josef Bacik02c24a82011-07-16 20:44:56 -04001492static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end,
1493 int datasync)
Miklos Szeredi82547982005-09-09 13:10:38 -07001494{
Josef Bacik02c24a82011-07-16 20:44:56 -04001495 return fuse_fsync_common(file, start, end, datasync, 1);
Miklos Szeredi82547982005-09-09 13:10:38 -07001496}
1497
Miklos Szeredib18da0c2011-12-13 11:58:49 +01001498static long fuse_dir_ioctl(struct file *file, unsigned int cmd,
1499 unsigned long arg)
1500{
1501 struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1502
1503 /* FUSE_IOCTL_DIR only supported for API version >= 7.18 */
1504 if (fc->minor < 18)
1505 return -ENOTTY;
1506
1507 return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR);
1508}
1509
1510static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd,
1511 unsigned long arg)
1512{
1513 struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1514
1515 if (fc->minor < 18)
1516 return -ENOTTY;
1517
1518 return fuse_ioctl_common(file, cmd, arg,
1519 FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR);
1520}
1521
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001522static bool update_mtime(unsigned ivalid, bool trust_local_mtime)
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001523{
1524 /* Always update if mtime is explicitly set */
1525 if (ivalid & ATTR_MTIME_SET)
1526 return true;
1527
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001528 /* Or if kernel i_mtime is the official one */
1529 if (trust_local_mtime)
1530 return true;
1531
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001532 /* If it's an open(O_TRUNC) or an ftruncate(), don't update */
1533 if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
1534 return false;
1535
1536 /* In all other cases update */
1537 return true;
1538}
1539
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001540static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg,
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001541 bool trust_local_cmtime)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001542{
1543 unsigned ivalid = iattr->ia_valid;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001544
1545 if (ivalid & ATTR_MODE)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001546 arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001547 if (ivalid & ATTR_UID)
Eric W. Biederman499dcf22012-02-07 16:26:03 -08001548 arg->valid |= FATTR_UID, arg->uid = from_kuid(&init_user_ns, iattr->ia_uid);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001549 if (ivalid & ATTR_GID)
Eric W. Biederman499dcf22012-02-07 16:26:03 -08001550 arg->valid |= FATTR_GID, arg->gid = from_kgid(&init_user_ns, iattr->ia_gid);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001551 if (ivalid & ATTR_SIZE)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001552 arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001553 if (ivalid & ATTR_ATIME) {
1554 arg->valid |= FATTR_ATIME;
Miklos Szeredibefc6492005-11-07 00:59:52 -08001555 arg->atime = iattr->ia_atime.tv_sec;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001556 arg->atimensec = iattr->ia_atime.tv_nsec;
1557 if (!(ivalid & ATTR_ATIME_SET))
1558 arg->valid |= FATTR_ATIME_NOW;
1559 }
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001560 if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, trust_local_cmtime)) {
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001561 arg->valid |= FATTR_MTIME;
Miklos Szeredibefc6492005-11-07 00:59:52 -08001562 arg->mtime = iattr->ia_mtime.tv_sec;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001563 arg->mtimensec = iattr->ia_mtime.tv_nsec;
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001564 if (!(ivalid & ATTR_MTIME_SET) && !trust_local_cmtime)
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001565 arg->valid |= FATTR_MTIME_NOW;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001566 }
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001567 if ((ivalid & ATTR_CTIME) && trust_local_cmtime) {
1568 arg->valid |= FATTR_CTIME;
1569 arg->ctime = iattr->ia_ctime.tv_sec;
1570 arg->ctimensec = iattr->ia_ctime.tv_nsec;
1571 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001572}
1573
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001574/*
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001575 * Prevent concurrent writepages on inode
1576 *
1577 * This is done by adding a negative bias to the inode write counter
1578 * and waiting for all pending writes to finish.
1579 */
1580void fuse_set_nowrite(struct inode *inode)
1581{
1582 struct fuse_conn *fc = get_fuse_conn(inode);
1583 struct fuse_inode *fi = get_fuse_inode(inode);
1584
Al Viro59551022016-01-22 15:40:57 -05001585 BUG_ON(!inode_is_locked(inode));
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001586
1587 spin_lock(&fc->lock);
1588 BUG_ON(fi->writectr < 0);
1589 fi->writectr += FUSE_NOWRITE;
1590 spin_unlock(&fc->lock);
1591 wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE);
1592}
1593
1594/*
1595 * Allow writepages on inode
1596 *
1597 * Remove the bias from the writecounter and send any queued
1598 * writepages.
1599 */
1600static void __fuse_release_nowrite(struct inode *inode)
1601{
1602 struct fuse_inode *fi = get_fuse_inode(inode);
1603
1604 BUG_ON(fi->writectr != FUSE_NOWRITE);
1605 fi->writectr = 0;
1606 fuse_flush_writepages(inode);
1607}
1608
1609void fuse_release_nowrite(struct inode *inode)
1610{
1611 struct fuse_conn *fc = get_fuse_conn(inode);
1612
1613 spin_lock(&fc->lock);
1614 __fuse_release_nowrite(inode);
1615 spin_unlock(&fc->lock);
1616}
1617
Miklos Szeredi70781872014-12-12 09:49:05 +01001618static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_args *args,
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001619 struct inode *inode,
1620 struct fuse_setattr_in *inarg_p,
1621 struct fuse_attr_out *outarg_p)
1622{
Miklos Szeredi70781872014-12-12 09:49:05 +01001623 args->in.h.opcode = FUSE_SETATTR;
1624 args->in.h.nodeid = get_node_id(inode);
1625 args->in.numargs = 1;
1626 args->in.args[0].size = sizeof(*inarg_p);
1627 args->in.args[0].value = inarg_p;
1628 args->out.numargs = 1;
Miklos Szeredi21f62172015-01-06 10:45:35 +01001629 args->out.args[0].size = sizeof(*outarg_p);
Miklos Szeredi70781872014-12-12 09:49:05 +01001630 args->out.args[0].value = outarg_p;
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001631}
1632
1633/*
1634 * Flush inode->i_mtime to the server
1635 */
Maxim Patlasovab9e13f2014-04-28 14:19:24 +02001636int fuse_flush_times(struct inode *inode, struct fuse_file *ff)
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001637{
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001638 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi70781872014-12-12 09:49:05 +01001639 FUSE_ARGS(args);
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001640 struct fuse_setattr_in inarg;
1641 struct fuse_attr_out outarg;
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001642
1643 memset(&inarg, 0, sizeof(inarg));
1644 memset(&outarg, 0, sizeof(outarg));
1645
Maxim Patlasovab9e13f2014-04-28 14:19:24 +02001646 inarg.valid = FATTR_MTIME;
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001647 inarg.mtime = inode->i_mtime.tv_sec;
1648 inarg.mtimensec = inode->i_mtime.tv_nsec;
Maxim Patlasovab9e13f2014-04-28 14:19:24 +02001649 if (fc->minor >= 23) {
1650 inarg.valid |= FATTR_CTIME;
1651 inarg.ctime = inode->i_ctime.tv_sec;
1652 inarg.ctimensec = inode->i_ctime.tv_nsec;
1653 }
Miklos Szeredi1e18bda2014-04-28 14:19:23 +02001654 if (ff) {
1655 inarg.valid |= FATTR_FH;
1656 inarg.fh = ff->fh;
1657 }
Miklos Szeredi70781872014-12-12 09:49:05 +01001658 fuse_setattr_fill(fc, &args, inode, &inarg, &outarg);
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001659
Miklos Szeredi70781872014-12-12 09:49:05 +01001660 return fuse_simple_request(fc, &args);
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001661}
1662
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001663/*
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001664 * Set attributes, and at the same time refresh them.
1665 *
1666 * Truncation is slightly complicated, because the 'truncate' request
1667 * may fail, in which case we don't want to touch the mapping.
Miklos Szeredi9ffbb912006-10-17 00:10:06 -07001668 * vmtruncate() doesn't allow for this case, so do the rlimit checking
1669 * and the actual truncation by hand.
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001670 */
Jan Kara62490332016-05-26 17:12:41 +02001671int fuse_do_setattr(struct dentry *dentry, struct iattr *attr,
Maxim Patlasovefb9fa92012-12-18 14:05:08 +04001672 struct file *file)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001673{
Jan Kara62490332016-05-26 17:12:41 +02001674 struct inode *inode = d_inode(dentry);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001675 struct fuse_conn *fc = get_fuse_conn(inode);
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001676 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredi70781872014-12-12 09:49:05 +01001677 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001678 struct fuse_setattr_in inarg;
1679 struct fuse_attr_out outarg;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001680 bool is_truncate = false;
Pavel Emelyanov83732002013-10-10 17:10:46 +04001681 bool is_wb = fc->writeback_cache;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001682 loff_t oldsize;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001683 int err;
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001684 bool trust_local_cmtime = is_wb && S_ISREG(inode->i_mode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001685
Miklos Szeredi29433a22016-10-01 07:32:32 +02001686 if (!fc->default_permissions)
Christoph Hellwigdb78b872010-06-04 11:30:03 +02001687 attr->ia_valid |= ATTR_FORCE;
1688
Jan Kara31051c82016-05-26 16:55:18 +02001689 err = setattr_prepare(dentry, attr);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02001690 if (err)
1691 return err;
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001692
Miklos Szeredi8d56add2011-02-25 14:44:58 +01001693 if (attr->ia_valid & ATTR_OPEN) {
Miklos Szerediebdc37f2018-02-08 15:17:38 +01001694 /* This is coming from open(..., ... | O_TRUNC); */
1695 WARN_ON(!(attr->ia_valid & ATTR_SIZE));
1696 WARN_ON(attr->ia_size != 0);
1697 if (fc->atomic_o_trunc) {
1698 /*
1699 * No need to send request to userspace, since actual
1700 * truncation has already been done by OPEN. But still
1701 * need to truncate page cache.
1702 */
1703 i_size_write(inode, 0);
1704 truncate_pagecache(inode, 0);
Miklos Szeredi8d56add2011-02-25 14:44:58 +01001705 return 0;
Miklos Szerediebdc37f2018-02-08 15:17:38 +01001706 }
Miklos Szeredi8d56add2011-02-25 14:44:58 +01001707 file = NULL;
1708 }
Miklos Szeredi6ff958e2007-10-18 03:07:02 -07001709
Christoph Hellwig2c27c652010-06-04 11:30:04 +02001710 if (attr->ia_valid & ATTR_SIZE)
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001711 is_truncate = true;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001712
Miklos Szeredic829f322019-10-23 14:26:37 +02001713 /* Flush dirty data/metadata before non-truncate SETATTR */
1714 if (is_wb && S_ISREG(inode->i_mode) &&
1715 attr->ia_valid &
1716 (ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_MTIME_SET |
1717 ATTR_TIMES_SET)) {
1718 err = write_inode_now(inode, true);
1719 if (err)
1720 return err;
1721
1722 fuse_set_nowrite(inode);
1723 fuse_release_nowrite(inode);
1724 }
1725
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001726 if (is_truncate) {
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001727 fuse_set_nowrite(inode);
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001728 set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001729 if (trust_local_cmtime && attr->ia_size != inode->i_size)
1730 attr->ia_valid |= ATTR_MTIME | ATTR_CTIME;
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001731 }
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001732
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001733 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -07001734 memset(&outarg, 0, sizeof(outarg));
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001735 iattr_to_fattr(attr, &inarg, trust_local_cmtime);
Miklos Szeredi49d49142007-10-18 03:07:00 -07001736 if (file) {
1737 struct fuse_file *ff = file->private_data;
1738 inarg.valid |= FATTR_FH;
1739 inarg.fh = ff->fh;
1740 }
Miklos Szeredif3332112007-10-18 03:07:04 -07001741 if (attr->ia_valid & ATTR_SIZE) {
1742 /* For mandatory locking in truncate */
1743 inarg.valid |= FATTR_LOCKOWNER;
1744 inarg.lock_owner = fuse_lock_owner_id(fc, current->files);
1745 }
Miklos Szeredi70781872014-12-12 09:49:05 +01001746 fuse_setattr_fill(fc, &args, inode, &inarg, &outarg);
1747 err = fuse_simple_request(fc, &args);
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001748 if (err) {
1749 if (err == -EINTR)
1750 fuse_invalidate_attr(inode);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001751 goto error;
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001752 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001753
Miklos Szeredic392b3a2019-11-12 11:49:04 +01001754 if (fuse_invalid_attr(&outarg.attr) ||
1755 (inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001756 make_bad_inode(inode);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001757 err = -EIO;
1758 goto error;
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001759 }
1760
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001761 spin_lock(&fc->lock);
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001762 /* the kernel maintains i_mtime locally */
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001763 if (trust_local_cmtime) {
1764 if (attr->ia_valid & ATTR_MTIME)
1765 inode->i_mtime = attr->ia_mtime;
1766 if (attr->ia_valid & ATTR_CTIME)
1767 inode->i_ctime = attr->ia_ctime;
Miklos Szeredi1e18bda2014-04-28 14:19:23 +02001768 /* FIXME: clear I_DIRTY_SYNC? */
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001769 }
1770
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001771 fuse_change_attributes_common(inode, &outarg.attr,
1772 attr_timeout(&outarg));
1773 oldsize = inode->i_size;
Pavel Emelyanov83732002013-10-10 17:10:46 +04001774 /* see the comment in fuse_change_attributes() */
1775 if (!is_wb || is_truncate || !S_ISREG(inode->i_mode))
1776 i_size_write(inode, outarg.attr.size);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001777
1778 if (is_truncate) {
1779 /* NOTE: this may release/reacquire fc->lock */
1780 __fuse_release_nowrite(inode);
1781 }
1782 spin_unlock(&fc->lock);
1783
1784 /*
1785 * Only call invalidate_inode_pages2() after removing
1786 * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock.
1787 */
Pavel Emelyanov83732002013-10-10 17:10:46 +04001788 if ((is_truncate || !is_wb) &&
1789 S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
Kirill A. Shutemov7caef262013-09-12 15:13:56 -07001790 truncate_pagecache(inode, outarg.attr.size);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001791 invalidate_inode_pages2(inode->i_mapping);
1792 }
1793
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001794 clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001795 return 0;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001796
1797error:
1798 if (is_truncate)
1799 fuse_release_nowrite(inode);
1800
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001801 clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001802 return err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001803}
1804
Miklos Szeredi49d49142007-10-18 03:07:00 -07001805static int fuse_setattr(struct dentry *entry, struct iattr *attr)
1806{
David Howells2b0143b2015-03-17 22:25:59 +00001807 struct inode *inode = d_inode(entry);
Miklos Szeredi5e940c12016-10-01 07:32:32 +02001808 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredia09f99e2016-10-01 07:32:32 +02001809 struct file *file = (attr->ia_valid & ATTR_FILE) ? attr->ia_file : NULL;
Miklos Szeredi5e2b8822016-10-01 07:32:32 +02001810 int ret;
Maxim Patlasovefb9fa92012-12-18 14:05:08 +04001811
1812 if (!fuse_allow_current_process(get_fuse_conn(inode)))
1813 return -EACCES;
1814
Miklos Szeredia09f99e2016-10-01 07:32:32 +02001815 if (attr->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) {
Miklos Szeredia09f99e2016-10-01 07:32:32 +02001816 attr->ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID |
1817 ATTR_MODE);
Miklos Szeredia09f99e2016-10-01 07:32:32 +02001818
Miklos Szeredi5e940c12016-10-01 07:32:32 +02001819 /*
1820 * The only sane way to reliably kill suid/sgid is to do it in
1821 * the userspace filesystem
1822 *
1823 * This should be done on write(), truncate() and chown().
1824 */
1825 if (!fc->handle_killpriv) {
Miklos Szeredi5e940c12016-10-01 07:32:32 +02001826 /*
1827 * ia_mode calculation may have used stale i_mode.
1828 * Refresh and recalculate.
1829 */
1830 ret = fuse_do_getattr(inode, NULL, file);
1831 if (ret)
1832 return ret;
1833
1834 attr->ia_mode = inode->i_mode;
Miklos Szeredic01638f2016-12-06 16:18:45 +01001835 if (inode->i_mode & S_ISUID) {
Miklos Szeredi5e940c12016-10-01 07:32:32 +02001836 attr->ia_valid |= ATTR_MODE;
1837 attr->ia_mode &= ~S_ISUID;
1838 }
Miklos Szeredic01638f2016-12-06 16:18:45 +01001839 if ((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
Miklos Szeredi5e940c12016-10-01 07:32:32 +02001840 attr->ia_valid |= ATTR_MODE;
1841 attr->ia_mode &= ~S_ISGID;
1842 }
Miklos Szeredia09f99e2016-10-01 07:32:32 +02001843 }
1844 }
1845 if (!attr->ia_valid)
1846 return 0;
1847
Linus Torvaldsabb5a142016-10-10 13:04:49 -07001848 ret = fuse_do_setattr(entry, attr, file);
Miklos Szeredi5e2b8822016-10-01 07:32:32 +02001849 if (!ret) {
Seth Forshee60bcc882016-08-29 08:46:37 -05001850 /*
1851 * If filesystem supports acls it may have updated acl xattrs in
1852 * the filesystem, so forget cached acls for the inode.
1853 */
1854 if (fc->posix_acl)
1855 forget_all_cached_acls(inode);
1856
Miklos Szeredi5e2b8822016-10-01 07:32:32 +02001857 /* Directory mode changed, may need to revalidate access */
1858 if (d_is_dir(entry) && (attr->ia_valid & ATTR_MODE))
1859 fuse_invalidate_entry_cache(entry);
1860 }
1861 return ret;
Miklos Szeredi49d49142007-10-18 03:07:00 -07001862}
1863
Miklos Szeredie5e55582005-09-09 13:10:28 -07001864static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
1865 struct kstat *stat)
1866{
David Howells2b0143b2015-03-17 22:25:59 +00001867 struct inode *inode = d_inode(entry);
Miklos Szeredi244f6382007-10-16 23:31:02 -07001868 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi244f6382007-10-16 23:31:02 -07001869
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001870 if (!fuse_allow_current_process(fc))
Miklos Szeredi244f6382007-10-16 23:31:02 -07001871 return -EACCES;
1872
Miklos Szeredibcb4be82007-11-28 16:21:59 -08001873 return fuse_update_attributes(inode, stat, NULL, NULL);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001874}
1875
Arjan van de Ven754661f2007-02-12 00:55:38 -08001876static const struct inode_operations fuse_dir_inode_operations = {
Miklos Szeredie5e55582005-09-09 13:10:28 -07001877 .lookup = fuse_lookup,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001878 .mkdir = fuse_mkdir,
1879 .symlink = fuse_symlink,
1880 .unlink = fuse_unlink,
1881 .rmdir = fuse_rmdir,
Miklos Szeredi2773bf02016-09-27 11:03:58 +02001882 .rename = fuse_rename2,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001883 .link = fuse_link,
1884 .setattr = fuse_setattr,
1885 .create = fuse_create,
Miklos Szeredic8ccbe02012-06-05 15:10:22 +02001886 .atomic_open = fuse_atomic_open,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001887 .mknod = fuse_mknod,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001888 .permission = fuse_permission,
1889 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001890 .listxattr = fuse_listxattr,
Seth Forshee60bcc882016-08-29 08:46:37 -05001891 .get_acl = fuse_get_acl,
1892 .set_acl = fuse_set_acl,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001893};
1894
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -08001895static const struct file_operations fuse_dir_operations = {
Miklos Szeredib6aeade2005-09-09 13:10:30 -07001896 .llseek = generic_file_llseek,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001897 .read = generic_read_dir,
Al Virod9b3dbd2016-04-20 17:30:32 -04001898 .iterate_shared = fuse_readdir,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001899 .open = fuse_dir_open,
1900 .release = fuse_dir_release,
Miklos Szeredi82547982005-09-09 13:10:38 -07001901 .fsync = fuse_dir_fsync,
Miklos Szeredib18da0c2011-12-13 11:58:49 +01001902 .unlocked_ioctl = fuse_dir_ioctl,
1903 .compat_ioctl = fuse_dir_compat_ioctl,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001904};
1905
Arjan van de Ven754661f2007-02-12 00:55:38 -08001906static const struct inode_operations fuse_common_inode_operations = {
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001907 .setattr = fuse_setattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001908 .permission = fuse_permission,
1909 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001910 .listxattr = fuse_listxattr,
Seth Forshee60bcc882016-08-29 08:46:37 -05001911 .get_acl = fuse_get_acl,
1912 .set_acl = fuse_set_acl,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001913};
1914
Arjan van de Ven754661f2007-02-12 00:55:38 -08001915static const struct inode_operations fuse_symlink_inode_operations = {
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001916 .setattr = fuse_setattr,
Al Viro6b255392015-11-17 10:20:54 -05001917 .get_link = fuse_get_link,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001918 .readlink = generic_readlink,
1919 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001920 .listxattr = fuse_listxattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001921};
1922
1923void fuse_init_common(struct inode *inode)
1924{
1925 inode->i_op = &fuse_common_inode_operations;
1926}
1927
1928void fuse_init_dir(struct inode *inode)
1929{
1930 inode->i_op = &fuse_dir_inode_operations;
1931 inode->i_fop = &fuse_dir_operations;
1932}
1933
1934void fuse_init_symlink(struct inode *inode)
1935{
1936 inode->i_op = &fuse_symlink_inode_operations;
1937}