blob: 06a18700a845542ab140590553b53f51de807030 [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>
Max Reitzbf109c62020-04-21 14:47:15 +020013#include <linux/fs_context.h>
Miklos Szeredie5e55582005-09-09 13:10:28 -070014#include <linux/sched.h>
15#include <linux/namei.h>
Miklos Szeredi07e77dc2010-12-07 20:16:56 +010016#include <linux/slab.h>
Seth Forshee703c7362016-08-29 08:46:36 -050017#include <linux/xattr.h>
Miklos Szeredi261aaba72018-10-01 10:07:05 +020018#include <linux/iversion.h>
Seth Forshee60bcc882016-08-29 08:46:37 -050019#include <linux/posix_acl.h>
Miklos Szeredie5e55582005-09-09 13:10:28 -070020
Feng Shuo4582a4a2013-01-15 11:23:28 +080021static void fuse_advise_use_readdirplus(struct inode *dir)
22{
23 struct fuse_inode *fi = get_fuse_inode(dir);
24
25 set_bit(FUSE_I_ADVISE_RDPLUS, &fi->state);
26}
27
Khazhismel Kumykov30c6a232019-09-16 16:56:41 -070028#if BITS_PER_LONG >= 64
29static inline void __fuse_dentry_settime(struct dentry *entry, u64 time)
30{
31 entry->d_fsdata = (void *) time;
32}
33
34static inline u64 fuse_dentry_time(const struct dentry *entry)
35{
36 return (u64)entry->d_fsdata;
37}
38
39#else
Miklos Szeredif75fdf22016-10-01 07:32:32 +020040union fuse_dentry {
41 u64 time;
42 struct rcu_head rcu;
43};
44
Khazhismel Kumykov30c6a232019-09-16 16:56:41 -070045static inline void __fuse_dentry_settime(struct dentry *dentry, u64 time)
46{
47 ((union fuse_dentry *) dentry->d_fsdata)->time = time;
48}
49
50static inline u64 fuse_dentry_time(const struct dentry *entry)
51{
52 return ((union fuse_dentry *) entry->d_fsdata)->time;
53}
54#endif
55
Miklos Szeredi8fab0102018-08-15 17:42:34 +020056static void fuse_dentry_settime(struct dentry *dentry, u64 time)
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070057{
Miklos Szeredi8fab0102018-08-15 17:42:34 +020058 struct fuse_conn *fc = get_fuse_conn_super(dentry->d_sb);
59 bool delete = !time && fc->delete_stale;
60 /*
61 * Mess with DCACHE_OP_DELETE because dput() will be faster without it.
62 * Don't care about races, either way it's just an optimization
63 */
64 if ((!delete && (dentry->d_flags & DCACHE_OP_DELETE)) ||
65 (delete && !(dentry->d_flags & DCACHE_OP_DELETE))) {
66 spin_lock(&dentry->d_lock);
67 if (!delete)
68 dentry->d_flags &= ~DCACHE_OP_DELETE;
69 else
70 dentry->d_flags |= DCACHE_OP_DELETE;
71 spin_unlock(&dentry->d_lock);
72 }
73
Khazhismel Kumykov30c6a232019-09-16 16:56:41 -070074 __fuse_dentry_settime(dentry, time);
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070075}
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070076
Miklos Szeredi6f9f1182006-01-06 00:19:39 -080077/*
78 * FUSE caches dentries and attributes with separate timeout. The
79 * time in jiffies until the dentry/attributes are valid is stored in
Miklos Szeredif75fdf22016-10-01 07:32:32 +020080 * dentry->d_fsdata and fuse_inode->i_time respectively.
Miklos Szeredi6f9f1182006-01-06 00:19:39 -080081 */
82
83/*
84 * Calculate the time in jiffies until a dentry/attributes are valid
85 */
Miklos Szeredibcb6f6d2016-10-01 07:32:32 +020086static u64 time_to_jiffies(u64 sec, u32 nsec)
Miklos Szeredie5e55582005-09-09 13:10:28 -070087{
Miklos Szeredi685d16d2006-07-30 03:04:08 -070088 if (sec || nsec) {
Miklos Szeredibcb6f6d2016-10-01 07:32:32 +020089 struct timespec64 ts = {
90 sec,
David Sheets21067522017-01-13 15:58:30 +000091 min_t(u32, nsec, NSEC_PER_SEC - 1)
Miklos Szeredibcb6f6d2016-10-01 07:32:32 +020092 };
93
94 return get_jiffies_64() + timespec64_to_jiffies(&ts);
Miklos Szeredi685d16d2006-07-30 03:04:08 -070095 } else
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070096 return 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -070097}
98
Miklos Szeredi6f9f1182006-01-06 00:19:39 -080099/*
100 * Set dentry and possibly attribute timeouts from the lookup/mk*
101 * replies
102 */
Miklos Szeredid123d8e2018-09-28 16:43:23 +0200103void fuse_change_entry_timeout(struct dentry *entry, struct fuse_entry_out *o)
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800104{
Miklos Szeredi0a0898c2006-07-30 03:04:10 -0700105 fuse_dentry_settime(entry,
106 time_to_jiffies(o->entry_valid, o->entry_valid_nsec));
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700107}
108
109static u64 attr_timeout(struct fuse_attr_out *o)
110{
111 return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
112}
113
Miklos Szeredid123d8e2018-09-28 16:43:23 +0200114u64 entry_attr_timeout(struct fuse_entry_out *o)
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700115{
116 return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800117}
118
Miklos Szeredi2f1e8192018-10-15 15:43:06 +0200119static void fuse_invalidate_attr_mask(struct inode *inode, u32 mask)
120{
121 set_mask_bits(&get_fuse_inode(inode)->inval_mask, 0, mask);
122}
123
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800124/*
125 * Mark the attributes as stale, so that at the next call to
126 * ->getattr() they will be fetched from userspace
127 */
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800128void fuse_invalidate_attr(struct inode *inode)
129{
Miklos Szeredi2f1e8192018-10-15 15:43:06 +0200130 fuse_invalidate_attr_mask(inode, STATX_BASIC_STATS);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800131}
132
Miklos Szeredi261aaba72018-10-01 10:07:05 +0200133static void fuse_dir_changed(struct inode *dir)
134{
135 fuse_invalidate_attr(dir);
136 inode_maybe_inc_iversion(dir, false);
137}
138
Andrew Gallagher451418f2013-11-05 03:55:43 -0800139/**
140 * Mark the attributes as stale due to an atime change. Avoid the invalidate if
141 * atime is not used.
142 */
143void fuse_invalidate_atime(struct inode *inode)
144{
145 if (!IS_RDONLY(inode))
Miklos Szeredi2f1e8192018-10-15 15:43:06 +0200146 fuse_invalidate_attr_mask(inode, STATX_ATIME);
Andrew Gallagher451418f2013-11-05 03:55:43 -0800147}
148
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800149/*
150 * Just mark the entry as stale, so that a next attempt to look it up
151 * will result in a new lookup call to userspace
152 *
153 * This is called when a dentry is about to become negative and the
154 * timeout is unknown (unlink, rmdir, rename and in some cases
155 * lookup)
156 */
Miklos Szeredidbd561d2008-07-25 01:49:00 -0700157void fuse_invalidate_entry_cache(struct dentry *entry)
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800158{
Miklos Szeredi0a0898c2006-07-30 03:04:10 -0700159 fuse_dentry_settime(entry, 0);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800160}
161
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800162/*
163 * Same as fuse_invalidate_entry_cache(), but also try to remove the
164 * dentry from the hash
165 */
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800166static void fuse_invalidate_entry(struct dentry *entry)
167{
168 d_invalidate(entry);
169 fuse_invalidate_entry_cache(entry);
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800170}
171
Miklos Szeredi70781872014-12-12 09:49:05 +0100172static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_args *args,
Al Viro13983d02016-07-20 22:34:44 -0400173 u64 nodeid, const struct qstr *name,
Miklos Szeredie5e55582005-09-09 13:10:28 -0700174 struct fuse_entry_out *outarg)
175{
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700176 memset(outarg, 0, sizeof(struct fuse_entry_out));
Miklos Szeredid5b48542019-09-10 15:04:08 +0200177 args->opcode = FUSE_LOOKUP;
178 args->nodeid = nodeid;
179 args->in_numargs = 1;
180 args->in_args[0].size = name->len + 1;
181 args->in_args[0].value = name->name;
182 args->out_numargs = 1;
183 args->out_args[0].size = sizeof(struct fuse_entry_out);
184 args->out_args[0].value = outarg;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700185}
186
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800187/*
188 * Check whether the dentry is still valid
189 *
190 * If the entry validity timeout has expired and the dentry is
191 * positive, try to redo the lookup. If the lookup results in a
192 * different inode, then let the VFS invalidate the dentry and redo
193 * the lookup once more. If the lookup results in the same inode,
194 * then refresh the attributes, timeouts and mark the dentry valid.
195 */
Al Viro0b728e12012-06-10 16:03:43 -0400196static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700197{
Nick Piggin34286d62011-01-07 17:49:57 +1100198 struct inode *inode;
Miklos Szeredi28420da2013-06-03 14:40:22 +0200199 struct dentry *parent;
Max Reitzfcee2162020-05-06 17:44:12 +0200200 struct fuse_mount *fm;
Miklos Szeredi6314efe2013-10-01 16:41:22 +0200201 struct fuse_inode *fi;
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200202 int ret;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800203
David Howells2b0143b2015-03-17 22:25:59 +0000204 inode = d_inode_rcu(entry);
Miklos Szeredi5d069db2020-12-10 15:33:14 +0100205 if (inode && fuse_is_bad(inode))
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200206 goto invalid;
Anand Avati154210c2014-06-26 20:21:57 -0400207 else if (time_before64(fuse_dentry_time(entry), get_jiffies_64()) ||
Miklos Szeredidf8629a2020-11-11 17:22:32 +0100208 (flags & (LOOKUP_EXCL | LOOKUP_REVAL))) {
Miklos Szeredie5e55582005-09-09 13:10:28 -0700209 struct fuse_entry_out outarg;
Miklos Szeredi70781872014-12-12 09:49:05 +0100210 FUSE_ARGS(args);
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100211 struct fuse_forget_link *forget;
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700212 u64 attr_version;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800213
Miklos Szeredi50322fe2006-02-28 16:59:03 -0800214 /* For negative dentries, always do a fresh lookup */
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800215 if (!inode)
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200216 goto invalid;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800217
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200218 ret = -ECHILD;
Al Viro0b728e12012-06-10 16:03:43 -0400219 if (flags & LOOKUP_RCU)
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200220 goto out;
Miklos Szeredie7c0a162011-03-21 13:58:06 +0100221
Max Reitzfcee2162020-05-06 17:44:12 +0200222 fm = get_fuse_mount(inode);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700223
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100224 forget = fuse_alloc_forget();
Miklos Szeredi70781872014-12-12 09:49:05 +0100225 ret = -ENOMEM;
226 if (!forget)
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200227 goto out;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800228
Max Reitzfcee2162020-05-06 17:44:12 +0200229 attr_version = fuse_get_attr_version(fm->fc);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700230
Miklos Szeredie956edd2006-10-17 00:10:12 -0700231 parent = dget_parent(entry);
Max Reitzfcee2162020-05-06 17:44:12 +0200232 fuse_lookup_init(fm->fc, &args, get_node_id(d_inode(parent)),
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700233 &entry->d_name, &outarg);
Max Reitzfcee2162020-05-06 17:44:12 +0200234 ret = fuse_simple_request(fm, &args);
Miklos Szeredie956edd2006-10-17 00:10:12 -0700235 dput(parent);
Miklos Szeredi50322fe2006-02-28 16:59:03 -0800236 /* Zero nodeid is same as -ENOENT */
Miklos Szeredi70781872014-12-12 09:49:05 +0100237 if (!ret && !outarg.nodeid)
238 ret = -ENOENT;
239 if (!ret) {
Miklos Szeredi6314efe2013-10-01 16:41:22 +0200240 fi = get_fuse_inode(inode);
Max Reitzbf109c62020-04-21 14:47:15 +0200241 if (outarg.nodeid != get_node_id(inode) ||
242 (bool) IS_AUTOMOUNT(inode) != (bool) (outarg.attr.flags & FUSE_ATTR_SUBMOUNT)) {
Max Reitzfcee2162020-05-06 17:44:12 +0200243 fuse_queue_forget(fm->fc, forget,
244 outarg.nodeid, 1);
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200245 goto invalid;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700246 }
Kirill Tkhaic9d8f5f2018-11-09 13:33:27 +0300247 spin_lock(&fi->lock);
Miklos Szeredi1729a162008-11-26 12:03:54 +0100248 fi->nlookup++;
Kirill Tkhaic9d8f5f2018-11-09 13:33:27 +0300249 spin_unlock(&fi->lock);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700250 }
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100251 kfree(forget);
Miklos Szeredi70781872014-12-12 09:49:05 +0100252 if (ret == -ENOMEM)
253 goto out;
Miklos Szeredieb59bd12019-11-12 11:49:04 +0100254 if (ret || fuse_invalid_attr(&outarg.attr) ||
255 (outarg.attr.mode ^ inode->i_mode) & S_IFMT)
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200256 goto invalid;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700257
Seth Forshee60bcc882016-08-29 08:46:37 -0500258 forget_all_cached_acls(inode);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700259 fuse_change_attributes(inode, &outarg.attr,
260 entry_attr_timeout(&outarg),
261 attr_version);
262 fuse_change_entry_timeout(entry, &outarg);
Miklos Szeredi28420da2013-06-03 14:40:22 +0200263 } else if (inode) {
Miklos Szeredi6314efe2013-10-01 16:41:22 +0200264 fi = get_fuse_inode(inode);
265 if (flags & LOOKUP_RCU) {
266 if (test_bit(FUSE_I_INIT_RDPLUS, &fi->state))
267 return -ECHILD;
268 } else if (test_and_clear_bit(FUSE_I_INIT_RDPLUS, &fi->state)) {
Miklos Szeredi28420da2013-06-03 14:40:22 +0200269 parent = dget_parent(entry);
David Howells2b0143b2015-03-17 22:25:59 +0000270 fuse_advise_use_readdirplus(d_inode(parent));
Miklos Szeredi28420da2013-06-03 14:40:22 +0200271 dput(parent);
272 }
Miklos Szeredie5e55582005-09-09 13:10:28 -0700273 }
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200274 ret = 1;
275out:
276 return ret;
277
278invalid:
279 ret = 0;
280 goto out;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700281}
282
Khazhismel Kumykov30c6a232019-09-16 16:56:41 -0700283#if BITS_PER_LONG < 64
Miklos Szeredif75fdf22016-10-01 07:32:32 +0200284static int fuse_dentry_init(struct dentry *dentry)
285{
Khazhismel Kumykovdc69e982019-09-17 12:35:33 -0700286 dentry->d_fsdata = kzalloc(sizeof(union fuse_dentry),
287 GFP_KERNEL_ACCOUNT | __GFP_RECLAIMABLE);
Miklos Szeredif75fdf22016-10-01 07:32:32 +0200288
289 return dentry->d_fsdata ? 0 : -ENOMEM;
290}
291static void fuse_dentry_release(struct dentry *dentry)
292{
293 union fuse_dentry *fd = dentry->d_fsdata;
294
295 kfree_rcu(fd, rcu);
296}
Khazhismel Kumykov30c6a232019-09-16 16:56:41 -0700297#endif
Miklos Szeredif75fdf22016-10-01 07:32:32 +0200298
Miklos Szeredi8fab0102018-08-15 17:42:34 +0200299static int fuse_dentry_delete(const struct dentry *dentry)
300{
301 return time_before64(fuse_dentry_time(dentry), get_jiffies_64());
302}
303
Max Reitzbf109c62020-04-21 14:47:15 +0200304/*
305 * Create a fuse_mount object with a new superblock (with path->dentry
306 * as the root), and return that mount so it can be auto-mounted on
307 * @path.
308 */
309static struct vfsmount *fuse_dentry_automount(struct path *path)
310{
311 struct fs_context *fsc;
312 struct fuse_mount *parent_fm = get_fuse_mount_super(path->mnt->mnt_sb);
313 struct fuse_conn *fc = parent_fm->fc;
314 struct fuse_mount *fm;
315 struct vfsmount *mnt;
316 struct fuse_inode *mp_fi = get_fuse_inode(d_inode(path->dentry));
317 struct super_block *sb;
318 int err;
319
320 fsc = fs_context_for_submount(path->mnt->mnt_sb->s_type, path->dentry);
321 if (IS_ERR(fsc)) {
322 err = PTR_ERR(fsc);
323 goto out;
324 }
325
326 err = -ENOMEM;
327 fm = kzalloc(sizeof(struct fuse_mount), GFP_KERNEL);
328 if (!fm)
329 goto out_put_fsc;
330
Max Reitzbf109c62020-04-21 14:47:15 +0200331 fsc->s_fs_info = fm;
332 sb = sget_fc(fsc, NULL, set_anon_super_fc);
333 if (IS_ERR(sb)) {
334 err = PTR_ERR(sb);
Miklos Szeredi514b5e32020-11-11 17:22:32 +0100335 kfree(fm);
Max Reitzbf109c62020-04-21 14:47:15 +0200336 goto out_put_fsc;
337 }
338 fm->fc = fuse_conn_get(fc);
339
340 /* Initialize superblock, making @mp_fi its root */
341 err = fuse_fill_super_submount(sb, mp_fi);
342 if (err)
343 goto out_put_sb;
344
345 sb->s_flags |= SB_ACTIVE;
346 fsc->root = dget(sb->s_root);
347 /* We are done configuring the superblock, so unlock it */
348 up_write(&sb->s_umount);
349
350 down_write(&fc->killsb);
351 list_add_tail(&fm->fc_entry, &fc->mounts);
352 up_write(&fc->killsb);
353
354 /* Create the submount */
355 mnt = vfs_create_mount(fsc);
356 if (IS_ERR(mnt)) {
357 err = PTR_ERR(mnt);
358 goto out_put_fsc;
359 }
360 mntget(mnt);
361 put_fs_context(fsc);
362 return mnt;
363
364out_put_sb:
365 /*
366 * Only jump here when fsc->root is NULL and sb is still locked
367 * (otherwise put_fs_context() will put the superblock)
368 */
369 deactivate_locked_super(sb);
370out_put_fsc:
371 put_fs_context(fsc);
372out:
373 return ERR_PTR(err);
374}
375
Al Viro42695902009-02-20 05:59:13 +0000376const struct dentry_operations fuse_dentry_operations = {
Miklos Szeredie5e55582005-09-09 13:10:28 -0700377 .d_revalidate = fuse_dentry_revalidate,
Miklos Szeredi8fab0102018-08-15 17:42:34 +0200378 .d_delete = fuse_dentry_delete,
Khazhismel Kumykov30c6a232019-09-16 16:56:41 -0700379#if BITS_PER_LONG < 64
Miklos Szeredif75fdf22016-10-01 07:32:32 +0200380 .d_init = fuse_dentry_init,
381 .d_release = fuse_dentry_release,
Khazhismel Kumykov30c6a232019-09-16 16:56:41 -0700382#endif
Max Reitzbf109c62020-04-21 14:47:15 +0200383 .d_automount = fuse_dentry_automount,
Miklos Szeredie5e55582005-09-09 13:10:28 -0700384};
385
Miklos Szeredi0ce267f2016-10-18 15:36:48 +0200386const struct dentry_operations fuse_root_dentry_operations = {
Khazhismel Kumykov30c6a232019-09-16 16:56:41 -0700387#if BITS_PER_LONG < 64
Miklos Szeredi0ce267f2016-10-18 15:36:48 +0200388 .d_init = fuse_dentry_init,
389 .d_release = fuse_dentry_release,
Khazhismel Kumykov30c6a232019-09-16 16:56:41 -0700390#endif
Miklos Szeredi0ce267f2016-10-18 15:36:48 +0200391};
392
Timo Savolaa5bfffac2007-04-08 16:04:00 -0700393int fuse_valid_type(int m)
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800394{
395 return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) ||
396 S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m);
397}
398
Miklos Szeredieb59bd12019-11-12 11:49:04 +0100399bool fuse_invalid_attr(struct fuse_attr *attr)
400{
401 return !fuse_valid_type(attr->mode) ||
402 attr->size > LLONG_MAX;
403}
404
Al Viro13983d02016-07-20 22:34:44 -0400405int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name,
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700406 struct fuse_entry_out *outarg, struct inode **inode)
407{
Max Reitzfcee2162020-05-06 17:44:12 +0200408 struct fuse_mount *fm = get_fuse_mount_super(sb);
Miklos Szeredi70781872014-12-12 09:49:05 +0100409 FUSE_ARGS(args);
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100410 struct fuse_forget_link *forget;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700411 u64 attr_version;
412 int err;
413
414 *inode = NULL;
415 err = -ENAMETOOLONG;
416 if (name->len > FUSE_NAME_MAX)
417 goto out;
418
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700419
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100420 forget = fuse_alloc_forget();
421 err = -ENOMEM;
Miklos Szeredi70781872014-12-12 09:49:05 +0100422 if (!forget)
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700423 goto out;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700424
Max Reitzfcee2162020-05-06 17:44:12 +0200425 attr_version = fuse_get_attr_version(fm->fc);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700426
Max Reitzfcee2162020-05-06 17:44:12 +0200427 fuse_lookup_init(fm->fc, &args, nodeid, name, outarg);
428 err = fuse_simple_request(fm, &args);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700429 /* Zero nodeid is same as -ENOENT, but with valid timeout */
430 if (err || !outarg->nodeid)
431 goto out_put_forget;
432
433 err = -EIO;
434 if (!outarg->nodeid)
435 goto out_put_forget;
Miklos Szeredieb59bd12019-11-12 11:49:04 +0100436 if (fuse_invalid_attr(&outarg->attr))
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700437 goto out_put_forget;
438
439 *inode = fuse_iget(sb, outarg->nodeid, outarg->generation,
440 &outarg->attr, entry_attr_timeout(outarg),
441 attr_version);
442 err = -ENOMEM;
443 if (!*inode) {
Max Reitzfcee2162020-05-06 17:44:12 +0200444 fuse_queue_forget(fm->fc, forget, outarg->nodeid, 1);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700445 goto out;
446 }
447 err = 0;
448
449 out_put_forget:
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100450 kfree(forget);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700451 out:
452 return err;
453}
454
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800455static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
Al Viro00cd8dd2012-06-10 17:13:09 -0400456 unsigned int flags)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700457{
458 int err;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700459 struct fuse_entry_out outarg;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700460 struct inode *inode;
Miklos Szeredi0de62562008-07-25 01:48:59 -0700461 struct dentry *newent;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700462 bool outarg_valid = true;
Miklos Szeredi63576c12018-07-26 16:13:11 +0200463 bool locked;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700464
Miklos Szeredi5d069db2020-12-10 15:33:14 +0100465 if (fuse_is_bad(dir))
466 return ERR_PTR(-EIO);
467
Miklos Szeredi63576c12018-07-26 16:13:11 +0200468 locked = fuse_lock_inode(dir);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700469 err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name,
470 &outarg, &inode);
Miklos Szeredi63576c12018-07-26 16:13:11 +0200471 fuse_unlock_inode(dir, locked);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700472 if (err == -ENOENT) {
473 outarg_valid = false;
474 err = 0;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800475 }
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700476 if (err)
477 goto out_err;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800478
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700479 err = -EIO;
480 if (inode && get_node_id(inode) == FUSE_ROOT_ID)
481 goto out_iput;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700482
Al Viro41d28bc2014-10-12 22:24:21 -0400483 newent = d_splice_alias(inode, entry);
Miklos Szeredi5835f332013-09-05 11:44:42 +0200484 err = PTR_ERR(newent);
485 if (IS_ERR(newent))
486 goto out_err;
Miklos Szeredid2a85162006-10-17 00:10:11 -0700487
Miklos Szeredi0de62562008-07-25 01:48:59 -0700488 entry = newent ? newent : entry;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700489 if (outarg_valid)
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700490 fuse_change_entry_timeout(entry, &outarg);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800491 else
492 fuse_invalidate_entry_cache(entry);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700493
Miklos Szeredi6c26f712019-10-21 15:57:07 +0200494 if (inode)
495 fuse_advise_use_readdirplus(dir);
Miklos Szeredi0de62562008-07-25 01:48:59 -0700496 return newent;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700497
498 out_iput:
499 iput(inode);
500 out_err:
501 return ERR_PTR(err);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700502}
503
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800504/*
505 * Atomic create+open operation
506 *
507 * If the filesystem doesn't support this, then fall back to separate
508 * 'mknod' + 'open' requests.
509 */
Al Virod9585272012-06-22 12:39:14 +0400510static int fuse_create_open(struct inode *dir, struct dentry *entry,
Al Viro30d90492012-06-22 12:40:19 +0400511 struct file *file, unsigned flags,
Al Virob452a452018-06-08 13:06:28 -0400512 umode_t mode)
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800513{
514 int err;
515 struct inode *inode;
Max Reitzfcee2162020-05-06 17:44:12 +0200516 struct fuse_mount *fm = get_fuse_mount(dir);
Miklos Szeredi70781872014-12-12 09:49:05 +0100517 FUSE_ARGS(args);
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100518 struct fuse_forget_link *forget;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200519 struct fuse_create_in inarg;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800520 struct fuse_open_out outopen;
521 struct fuse_entry_out outentry;
Kirill Tkhaiebf84d02018-11-09 13:33:11 +0300522 struct fuse_inode *fi;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800523 struct fuse_file *ff;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800524
Miklos Szerediaf109bc2012-08-15 13:01:24 +0200525 /* Userspace expects S_IFREG in create mode */
526 BUG_ON((mode & S_IFMT) != S_IFREG);
527
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100528 forget = fuse_alloc_forget();
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200529 err = -ENOMEM;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100530 if (!forget)
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200531 goto out_err;
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700532
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700533 err = -ENOMEM;
Max Reitzfcee2162020-05-06 17:44:12 +0200534 ff = fuse_file_alloc(fm);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800535 if (!ff)
Miklos Szeredi70781872014-12-12 09:49:05 +0100536 goto out_put_forget_req;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800537
Max Reitzfcee2162020-05-06 17:44:12 +0200538 if (!fm->fc->dont_mask)
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200539 mode &= ~current_umask();
540
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800541 flags &= ~O_NOCTTY;
542 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700543 memset(&outentry, 0, sizeof(outentry));
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800544 inarg.flags = flags;
545 inarg.mode = mode;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200546 inarg.umask = current_umask();
Vivek Goyal643a6662020-10-09 14:15:11 -0400547
548 if (fm->fc->handle_killpriv_v2 && (flags & O_TRUNC) &&
549 !(flags & O_EXCL) && !capable(CAP_FSETID)) {
550 inarg.open_flags |= FUSE_OPEN_KILL_SUIDGID;
551 }
552
Miklos Szeredid5b48542019-09-10 15:04:08 +0200553 args.opcode = FUSE_CREATE;
554 args.nodeid = get_node_id(dir);
555 args.in_numargs = 2;
556 args.in_args[0].size = sizeof(inarg);
557 args.in_args[0].value = &inarg;
558 args.in_args[1].size = entry->d_name.len + 1;
559 args.in_args[1].value = entry->d_name.name;
560 args.out_numargs = 2;
561 args.out_args[0].size = sizeof(outentry);
562 args.out_args[0].value = &outentry;
563 args.out_args[1].size = sizeof(outopen);
564 args.out_args[1].value = &outopen;
Max Reitzfcee2162020-05-06 17:44:12 +0200565 err = fuse_simple_request(fm, &args);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200566 if (err)
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800567 goto out_free_ff;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800568
569 err = -EIO;
Miklos Szeredieb59bd12019-11-12 11:49:04 +0100570 if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid) ||
571 fuse_invalid_attr(&outentry.attr))
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800572 goto out_free_ff;
573
Miklos Szeredic7b71432009-04-28 16:56:37 +0200574 ff->fh = outopen.fh;
575 ff->nodeid = outentry.nodeid;
576 ff->open_flags = outopen.open_flags;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800577 inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700578 &outentry.attr, entry_attr_timeout(&outentry), 0);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800579 if (!inode) {
580 flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
Kirill Tkhaiebf84d02018-11-09 13:33:11 +0300581 fuse_sync_release(NULL, ff, flags);
Max Reitzfcee2162020-05-06 17:44:12 +0200582 fuse_queue_forget(fm->fc, forget, outentry.nodeid, 1);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200583 err = -ENOMEM;
584 goto out_err;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800585 }
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100586 kfree(forget);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800587 d_instantiate(entry, inode);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700588 fuse_change_entry_timeout(entry, &outentry);
Miklos Szeredi261aaba72018-10-01 10:07:05 +0200589 fuse_dir_changed(dir);
Al Virobe12af32018-06-08 11:44:56 -0400590 err = finish_open(file, entry, generic_file_open);
Al Viro30d90492012-06-22 12:40:19 +0400591 if (err) {
Kirill Tkhaiebf84d02018-11-09 13:33:11 +0300592 fi = get_fuse_inode(inode);
593 fuse_sync_release(fi, ff, flags);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200594 } else {
Miklos Szeredi267d8442017-02-22 20:08:25 +0100595 file->private_data = ff;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200596 fuse_finish_open(inode, file);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800597 }
Al Virod9585272012-06-22 12:39:14 +0400598 return err;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800599
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200600out_free_ff:
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800601 fuse_file_free(ff);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200602out_put_forget_req:
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100603 kfree(forget);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200604out_err:
Al Virod9585272012-06-22 12:39:14 +0400605 return err;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200606}
607
Christian Brauner549c7292021-01-21 14:19:43 +0100608static int fuse_mknod(struct user_namespace *, struct inode *, struct dentry *,
609 umode_t, dev_t);
Al Virod9585272012-06-22 12:39:14 +0400610static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
Al Viro30d90492012-06-22 12:40:19 +0400611 struct file *file, unsigned flags,
Al Viro44907d72018-06-08 13:32:02 -0400612 umode_t mode)
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200613{
614 int err;
615 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200616 struct dentry *res = NULL;
617
Miklos Szeredi5d069db2020-12-10 15:33:14 +0100618 if (fuse_is_bad(dir))
619 return -EIO;
620
Al Viro00699ad2016-07-05 09:44:53 -0400621 if (d_in_lookup(entry)) {
Al Viro00cd8dd2012-06-10 17:13:09 -0400622 res = fuse_lookup(dir, entry, 0);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200623 if (IS_ERR(res))
Al Virod9585272012-06-22 12:39:14 +0400624 return PTR_ERR(res);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200625
626 if (res)
627 entry = res;
628 }
629
David Howells2b0143b2015-03-17 22:25:59 +0000630 if (!(flags & O_CREAT) || d_really_is_positive(entry))
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200631 goto no_open;
632
633 /* Only creates */
Al Viro73a09dd2018-06-08 13:22:02 -0400634 file->f_mode |= FMODE_CREATED;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200635
636 if (fc->no_create)
637 goto mknod;
638
Al Virob452a452018-06-08 13:06:28 -0400639 err = fuse_create_open(dir, entry, file, flags, mode);
Al Virod9585272012-06-22 12:39:14 +0400640 if (err == -ENOSYS) {
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200641 fc->no_create = 1;
642 goto mknod;
643 }
644out_dput:
645 dput(res);
Al Virod9585272012-06-22 12:39:14 +0400646 return err;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200647
648mknod:
Christian Brauner549c7292021-01-21 14:19:43 +0100649 err = fuse_mknod(&init_user_ns, dir, entry, mode, 0);
Al Virod9585272012-06-22 12:39:14 +0400650 if (err)
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200651 goto out_dput;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200652no_open:
Al Viroe45198a2012-06-10 06:48:09 -0400653 return finish_no_open(file, res);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800654}
655
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800656/*
657 * Code shared between mknod, mkdir, symlink and link
658 */
Max Reitzfcee2162020-05-06 17:44:12 +0200659static int create_new_entry(struct fuse_mount *fm, struct fuse_args *args,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700660 struct inode *dir, struct dentry *entry,
Al Viro541af6a2011-07-26 03:17:33 -0400661 umode_t mode)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700662{
663 struct fuse_entry_out outarg;
664 struct inode *inode;
Al Viroc971e6a2018-05-28 18:27:19 -0400665 struct dentry *d;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700666 int err;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100667 struct fuse_forget_link *forget;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800668
Miklos Szeredi5d069db2020-12-10 15:33:14 +0100669 if (fuse_is_bad(dir))
670 return -EIO;
671
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100672 forget = fuse_alloc_forget();
Miklos Szeredi70781872014-12-12 09:49:05 +0100673 if (!forget)
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100674 return -ENOMEM;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700675
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700676 memset(&outarg, 0, sizeof(outarg));
Miklos Szeredid5b48542019-09-10 15:04:08 +0200677 args->nodeid = get_node_id(dir);
678 args->out_numargs = 1;
679 args->out_args[0].size = sizeof(outarg);
680 args->out_args[0].value = &outarg;
Max Reitzfcee2162020-05-06 17:44:12 +0200681 err = fuse_simple_request(fm, args);
Miklos Szeredi2d510132006-11-25 11:09:20 -0800682 if (err)
683 goto out_put_forget_req;
684
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800685 err = -EIO;
Miklos Szeredieb59bd12019-11-12 11:49:04 +0100686 if (invalid_nodeid(outarg.nodeid) || fuse_invalid_attr(&outarg.attr))
Miklos Szeredi2d510132006-11-25 11:09:20 -0800687 goto out_put_forget_req;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800688
689 if ((outarg.attr.mode ^ mode) & S_IFMT)
Miklos Szeredi2d510132006-11-25 11:09:20 -0800690 goto out_put_forget_req;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800691
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700692 inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700693 &outarg.attr, entry_attr_timeout(&outarg), 0);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700694 if (!inode) {
Max Reitzfcee2162020-05-06 17:44:12 +0200695 fuse_queue_forget(fm->fc, forget, outarg.nodeid, 1);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700696 return -ENOMEM;
697 }
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100698 kfree(forget);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700699
Al Viroc971e6a2018-05-28 18:27:19 -0400700 d_drop(entry);
701 d = d_splice_alias(inode, entry);
702 if (IS_ERR(d))
703 return PTR_ERR(d);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700704
Al Viroc971e6a2018-05-28 18:27:19 -0400705 if (d) {
706 fuse_change_entry_timeout(d, &outarg);
707 dput(d);
708 } else {
709 fuse_change_entry_timeout(entry, &outarg);
710 }
Miklos Szeredi261aaba72018-10-01 10:07:05 +0200711 fuse_dir_changed(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700712 return 0;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800713
Miklos Szeredi2d510132006-11-25 11:09:20 -0800714 out_put_forget_req:
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100715 kfree(forget);
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800716 return err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700717}
718
Christian Brauner549c7292021-01-21 14:19:43 +0100719static int fuse_mknod(struct user_namespace *mnt_userns, struct inode *dir,
720 struct dentry *entry, umode_t mode, dev_t rdev)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700721{
722 struct fuse_mknod_in inarg;
Max Reitzfcee2162020-05-06 17:44:12 +0200723 struct fuse_mount *fm = get_fuse_mount(dir);
Miklos Szeredi70781872014-12-12 09:49:05 +0100724 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700725
Max Reitzfcee2162020-05-06 17:44:12 +0200726 if (!fm->fc->dont_mask)
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200727 mode &= ~current_umask();
728
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700729 memset(&inarg, 0, sizeof(inarg));
730 inarg.mode = mode;
731 inarg.rdev = new_encode_dev(rdev);
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200732 inarg.umask = current_umask();
Miklos Szeredid5b48542019-09-10 15:04:08 +0200733 args.opcode = FUSE_MKNOD;
734 args.in_numargs = 2;
735 args.in_args[0].size = sizeof(inarg);
736 args.in_args[0].value = &inarg;
737 args.in_args[1].size = entry->d_name.len + 1;
738 args.in_args[1].value = entry->d_name.name;
Max Reitzfcee2162020-05-06 17:44:12 +0200739 return create_new_entry(fm, &args, dir, entry, mode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700740}
741
Christian Brauner549c7292021-01-21 14:19:43 +0100742static int fuse_create(struct user_namespace *mnt_userns, struct inode *dir,
743 struct dentry *entry, umode_t mode, bool excl)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700744{
Christian Brauner549c7292021-01-21 14:19:43 +0100745 return fuse_mknod(&init_user_ns, dir, entry, mode, 0);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700746}
747
Christian Brauner549c7292021-01-21 14:19:43 +0100748static int fuse_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
749 struct dentry *entry, umode_t mode)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700750{
751 struct fuse_mkdir_in inarg;
Max Reitzfcee2162020-05-06 17:44:12 +0200752 struct fuse_mount *fm = get_fuse_mount(dir);
Miklos Szeredi70781872014-12-12 09:49:05 +0100753 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700754
Max Reitzfcee2162020-05-06 17:44:12 +0200755 if (!fm->fc->dont_mask)
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200756 mode &= ~current_umask();
757
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700758 memset(&inarg, 0, sizeof(inarg));
759 inarg.mode = mode;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200760 inarg.umask = current_umask();
Miklos Szeredid5b48542019-09-10 15:04:08 +0200761 args.opcode = FUSE_MKDIR;
762 args.in_numargs = 2;
763 args.in_args[0].size = sizeof(inarg);
764 args.in_args[0].value = &inarg;
765 args.in_args[1].size = entry->d_name.len + 1;
766 args.in_args[1].value = entry->d_name.name;
Max Reitzfcee2162020-05-06 17:44:12 +0200767 return create_new_entry(fm, &args, dir, entry, S_IFDIR);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700768}
769
Christian Brauner549c7292021-01-21 14:19:43 +0100770static int fuse_symlink(struct user_namespace *mnt_userns, struct inode *dir,
771 struct dentry *entry, const char *link)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700772{
Max Reitzfcee2162020-05-06 17:44:12 +0200773 struct fuse_mount *fm = get_fuse_mount(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700774 unsigned len = strlen(link) + 1;
Miklos Szeredi70781872014-12-12 09:49:05 +0100775 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700776
Miklos Szeredid5b48542019-09-10 15:04:08 +0200777 args.opcode = FUSE_SYMLINK;
778 args.in_numargs = 2;
779 args.in_args[0].size = entry->d_name.len + 1;
780 args.in_args[0].value = entry->d_name.name;
781 args.in_args[1].size = len;
782 args.in_args[1].value = link;
Max Reitzfcee2162020-05-06 17:44:12 +0200783 return create_new_entry(fm, &args, dir, entry, S_IFLNK);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700784}
785
Seth Forshee703c7362016-08-29 08:46:36 -0500786void fuse_update_ctime(struct inode *inode)
Maxim Patlasov31f32672014-04-28 14:19:24 +0200787{
788 if (!IS_NOCMTIME(inode)) {
Deepa Dinamanic2050a42016-09-14 07:48:06 -0700789 inode->i_ctime = current_time(inode);
Maxim Patlasov31f32672014-04-28 14:19:24 +0200790 mark_inode_dirty_sync(inode);
791 }
792}
793
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700794static int fuse_unlink(struct inode *dir, struct dentry *entry)
795{
796 int err;
Max Reitzfcee2162020-05-06 17:44:12 +0200797 struct fuse_mount *fm = get_fuse_mount(dir);
Miklos Szeredi70781872014-12-12 09:49:05 +0100798 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700799
Miklos Szeredi5d069db2020-12-10 15:33:14 +0100800 if (fuse_is_bad(dir))
801 return -EIO;
802
Miklos Szeredid5b48542019-09-10 15:04:08 +0200803 args.opcode = FUSE_UNLINK;
804 args.nodeid = get_node_id(dir);
805 args.in_numargs = 1;
806 args.in_args[0].size = entry->d_name.len + 1;
807 args.in_args[0].value = entry->d_name.name;
Max Reitzfcee2162020-05-06 17:44:12 +0200808 err = fuse_simple_request(fm, &args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700809 if (!err) {
David Howells2b0143b2015-03-17 22:25:59 +0000810 struct inode *inode = d_inode(entry);
Miklos Szerediac45d612012-03-05 15:48:11 +0100811 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700812
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +0300813 spin_lock(&fi->lock);
Max Reitzfcee2162020-05-06 17:44:12 +0200814 fi->attr_version = atomic64_inc_return(&fm->fc->attr_version);
Miklos Szeredidfca7ce2013-02-04 15:57:42 +0100815 /*
816 * If i_nlink == 0 then unlink doesn't make sense, yet this can
817 * happen if userspace filesystem is careless. It would be
818 * difficult to enforce correct nlink usage so just ignore this
819 * condition here
820 */
821 if (inode->i_nlink > 0)
822 drop_nlink(inode);
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +0300823 spin_unlock(&fi->lock);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700824 fuse_invalidate_attr(inode);
Miklos Szeredi261aaba72018-10-01 10:07:05 +0200825 fuse_dir_changed(dir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800826 fuse_invalidate_entry_cache(entry);
Maxim Patlasov31f32672014-04-28 14:19:24 +0200827 fuse_update_ctime(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700828 } else if (err == -EINTR)
829 fuse_invalidate_entry(entry);
830 return err;
831}
832
833static int fuse_rmdir(struct inode *dir, struct dentry *entry)
834{
835 int err;
Max Reitzfcee2162020-05-06 17:44:12 +0200836 struct fuse_mount *fm = get_fuse_mount(dir);
Miklos Szeredi70781872014-12-12 09:49:05 +0100837 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700838
Miklos Szeredi5d069db2020-12-10 15:33:14 +0100839 if (fuse_is_bad(dir))
840 return -EIO;
841
Miklos Szeredid5b48542019-09-10 15:04:08 +0200842 args.opcode = FUSE_RMDIR;
843 args.nodeid = get_node_id(dir);
844 args.in_numargs = 1;
845 args.in_args[0].size = entry->d_name.len + 1;
846 args.in_args[0].value = entry->d_name.name;
Max Reitzfcee2162020-05-06 17:44:12 +0200847 err = fuse_simple_request(fm, &args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700848 if (!err) {
David Howells2b0143b2015-03-17 22:25:59 +0000849 clear_nlink(d_inode(entry));
Miklos Szeredi261aaba72018-10-01 10:07:05 +0200850 fuse_dir_changed(dir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800851 fuse_invalidate_entry_cache(entry);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700852 } else if (err == -EINTR)
853 fuse_invalidate_entry(entry);
854 return err;
855}
856
Miklos Szeredi1560c972014-04-28 16:43:44 +0200857static int fuse_rename_common(struct inode *olddir, struct dentry *oldent,
858 struct inode *newdir, struct dentry *newent,
859 unsigned int flags, int opcode, size_t argsize)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700860{
861 int err;
Miklos Szeredi1560c972014-04-28 16:43:44 +0200862 struct fuse_rename2_in inarg;
Max Reitzfcee2162020-05-06 17:44:12 +0200863 struct fuse_mount *fm = get_fuse_mount(olddir);
Miklos Szeredi70781872014-12-12 09:49:05 +0100864 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700865
Miklos Szeredi1560c972014-04-28 16:43:44 +0200866 memset(&inarg, 0, argsize);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700867 inarg.newdir = get_node_id(newdir);
Miklos Szeredi1560c972014-04-28 16:43:44 +0200868 inarg.flags = flags;
Miklos Szeredid5b48542019-09-10 15:04:08 +0200869 args.opcode = opcode;
870 args.nodeid = get_node_id(olddir);
871 args.in_numargs = 3;
872 args.in_args[0].size = argsize;
873 args.in_args[0].value = &inarg;
874 args.in_args[1].size = oldent->d_name.len + 1;
875 args.in_args[1].value = oldent->d_name.name;
876 args.in_args[2].size = newent->d_name.len + 1;
877 args.in_args[2].value = newent->d_name.name;
Max Reitzfcee2162020-05-06 17:44:12 +0200878 err = fuse_simple_request(fm, &args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700879 if (!err) {
Miklos Szeredi08b63302007-11-28 16:22:03 -0800880 /* ctime changes */
David Howells2b0143b2015-03-17 22:25:59 +0000881 fuse_invalidate_attr(d_inode(oldent));
882 fuse_update_ctime(d_inode(oldent));
Miklos Szeredi08b63302007-11-28 16:22:03 -0800883
Miklos Szeredi1560c972014-04-28 16:43:44 +0200884 if (flags & RENAME_EXCHANGE) {
David Howells2b0143b2015-03-17 22:25:59 +0000885 fuse_invalidate_attr(d_inode(newent));
886 fuse_update_ctime(d_inode(newent));
Miklos Szeredi1560c972014-04-28 16:43:44 +0200887 }
888
Miklos Szeredi261aaba72018-10-01 10:07:05 +0200889 fuse_dir_changed(olddir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700890 if (olddir != newdir)
Miklos Szeredi261aaba72018-10-01 10:07:05 +0200891 fuse_dir_changed(newdir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800892
893 /* newent will end up negative */
David Howells2b0143b2015-03-17 22:25:59 +0000894 if (!(flags & RENAME_EXCHANGE) && d_really_is_positive(newent)) {
895 fuse_invalidate_attr(d_inode(newent));
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800896 fuse_invalidate_entry_cache(newent);
David Howells2b0143b2015-03-17 22:25:59 +0000897 fuse_update_ctime(d_inode(newent));
Miklos Szeredi5219f342009-11-04 10:24:52 +0100898 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700899 } else if (err == -EINTR) {
900 /* If request was interrupted, DEITY only knows if the
901 rename actually took place. If the invalidation
902 fails (e.g. some process has CWD under the renamed
903 directory), then there can be inconsistency between
904 the dcache and the real filesystem. Tough luck. */
905 fuse_invalidate_entry(oldent);
David Howells2b0143b2015-03-17 22:25:59 +0000906 if (d_really_is_positive(newent))
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700907 fuse_invalidate_entry(newent);
908 }
909
910 return err;
911}
912
Christian Brauner549c7292021-01-21 14:19:43 +0100913static int fuse_rename2(struct user_namespace *mnt_userns, struct inode *olddir,
914 struct dentry *oldent, struct inode *newdir,
915 struct dentry *newent, unsigned int flags)
Miklos Szeredi1560c972014-04-28 16:43:44 +0200916{
917 struct fuse_conn *fc = get_fuse_conn(olddir);
918 int err;
919
Miklos Szeredi5d069db2020-12-10 15:33:14 +0100920 if (fuse_is_bad(olddir))
921 return -EIO;
922
Vivek Goyal519525f2020-02-05 08:15:46 -0500923 if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT))
Miklos Szeredi1560c972014-04-28 16:43:44 +0200924 return -EINVAL;
925
Miklos Szeredi4237ba42014-07-10 10:50:19 +0200926 if (flags) {
927 if (fc->no_rename2 || fc->minor < 23)
928 return -EINVAL;
Miklos Szeredi1560c972014-04-28 16:43:44 +0200929
Miklos Szeredi4237ba42014-07-10 10:50:19 +0200930 err = fuse_rename_common(olddir, oldent, newdir, newent, flags,
931 FUSE_RENAME2,
932 sizeof(struct fuse_rename2_in));
933 if (err == -ENOSYS) {
934 fc->no_rename2 = 1;
935 err = -EINVAL;
936 }
937 } else {
938 err = fuse_rename_common(olddir, oldent, newdir, newent, 0,
939 FUSE_RENAME,
940 sizeof(struct fuse_rename_in));
Miklos Szeredi1560c972014-04-28 16:43:44 +0200941 }
Miklos Szeredi1560c972014-04-28 16:43:44 +0200942
Miklos Szeredi4237ba42014-07-10 10:50:19 +0200943 return err;
944}
945
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700946static int fuse_link(struct dentry *entry, struct inode *newdir,
947 struct dentry *newent)
948{
949 int err;
950 struct fuse_link_in inarg;
David Howells2b0143b2015-03-17 22:25:59 +0000951 struct inode *inode = d_inode(entry);
Max Reitzfcee2162020-05-06 17:44:12 +0200952 struct fuse_mount *fm = get_fuse_mount(inode);
Miklos Szeredi70781872014-12-12 09:49:05 +0100953 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700954
955 memset(&inarg, 0, sizeof(inarg));
956 inarg.oldnodeid = get_node_id(inode);
Miklos Szeredid5b48542019-09-10 15:04:08 +0200957 args.opcode = FUSE_LINK;
958 args.in_numargs = 2;
959 args.in_args[0].size = sizeof(inarg);
960 args.in_args[0].value = &inarg;
961 args.in_args[1].size = newent->d_name.len + 1;
962 args.in_args[1].value = newent->d_name.name;
Max Reitzfcee2162020-05-06 17:44:12 +0200963 err = create_new_entry(fm, &args, newdir, newent, inode->i_mode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700964 /* Contrary to "normal" filesystems it can happen that link
965 makes two "logical" inodes point to the same "physical"
966 inode. We invalidate the attributes of the old one, so it
967 will reflect changes in the backing inode (link count,
968 etc.)
969 */
Miklos Szerediac45d612012-03-05 15:48:11 +0100970 if (!err) {
971 struct fuse_inode *fi = get_fuse_inode(inode);
972
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +0300973 spin_lock(&fi->lock);
Max Reitzfcee2162020-05-06 17:44:12 +0200974 fi->attr_version = atomic64_inc_return(&fm->fc->attr_version);
Miklos Szeredic634da72019-11-12 11:49:04 +0100975 if (likely(inode->i_nlink < UINT_MAX))
976 inc_nlink(inode);
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +0300977 spin_unlock(&fi->lock);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700978 fuse_invalidate_attr(inode);
Maxim Patlasov31f32672014-04-28 14:19:24 +0200979 fuse_update_ctime(inode);
Miklos Szerediac45d612012-03-05 15:48:11 +0100980 } else if (err == -EINTR) {
981 fuse_invalidate_attr(inode);
982 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700983 return err;
984}
985
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700986static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
987 struct kstat *stat)
988{
Miklos Szeredi203627b2012-05-10 19:49:38 +0400989 unsigned int blkbits;
Pavel Emelyanov83732002013-10-10 17:10:46 +0400990 struct fuse_conn *fc = get_fuse_conn(inode);
991
992 /* see the comment in fuse_change_attributes() */
Maxim Patlasovb0aa7602013-12-26 19:51:11 +0400993 if (fc->writeback_cache && S_ISREG(inode->i_mode)) {
Pavel Emelyanov83732002013-10-10 17:10:46 +0400994 attr->size = i_size_read(inode);
Maxim Patlasovb0aa7602013-12-26 19:51:11 +0400995 attr->mtime = inode->i_mtime.tv_sec;
996 attr->mtimensec = inode->i_mtime.tv_nsec;
Maxim Patlasov31f32672014-04-28 14:19:24 +0200997 attr->ctime = inode->i_ctime.tv_sec;
998 attr->ctimensec = inode->i_ctime.tv_nsec;
Maxim Patlasovb0aa7602013-12-26 19:51:11 +0400999 }
Miklos Szeredi203627b2012-05-10 19:49:38 +04001000
Miklos Szeredi1fb69e72007-10-18 03:06:58 -07001001 stat->dev = inode->i_sb->s_dev;
1002 stat->ino = attr->ino;
1003 stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
1004 stat->nlink = attr->nlink;
Eric W. Biederman8cb08322018-02-21 11:18:07 -06001005 stat->uid = make_kuid(fc->user_ns, attr->uid);
1006 stat->gid = make_kgid(fc->user_ns, attr->gid);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -07001007 stat->rdev = inode->i_rdev;
1008 stat->atime.tv_sec = attr->atime;
1009 stat->atime.tv_nsec = attr->atimensec;
1010 stat->mtime.tv_sec = attr->mtime;
1011 stat->mtime.tv_nsec = attr->mtimensec;
1012 stat->ctime.tv_sec = attr->ctime;
1013 stat->ctime.tv_nsec = attr->ctimensec;
1014 stat->size = attr->size;
1015 stat->blocks = attr->blocks;
Miklos Szeredi203627b2012-05-10 19:49:38 +04001016
1017 if (attr->blksize != 0)
1018 blkbits = ilog2(attr->blksize);
1019 else
1020 blkbits = inode->i_sb->s_blocksize_bits;
1021
1022 stat->blksize = 1 << blkbits;
Miklos Szeredi1fb69e72007-10-18 03:06:58 -07001023}
1024
Miklos Szeredic79e3222007-10-18 03:06:59 -07001025static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
1026 struct file *file)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001027{
1028 int err;
Miklos Szeredic79e3222007-10-18 03:06:59 -07001029 struct fuse_getattr_in inarg;
1030 struct fuse_attr_out outarg;
Max Reitzfcee2162020-05-06 17:44:12 +02001031 struct fuse_mount *fm = get_fuse_mount(inode);
Miklos Szeredi70781872014-12-12 09:49:05 +01001032 FUSE_ARGS(args);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -07001033 u64 attr_version;
1034
Max Reitzfcee2162020-05-06 17:44:12 +02001035 attr_version = fuse_get_attr_version(fm->fc);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -07001036
Miklos Szeredic79e3222007-10-18 03:06:59 -07001037 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -07001038 memset(&outarg, 0, sizeof(outarg));
Miklos Szeredic79e3222007-10-18 03:06:59 -07001039 /* Directories have separate file-handle space */
1040 if (file && S_ISREG(inode->i_mode)) {
1041 struct fuse_file *ff = file->private_data;
1042
1043 inarg.getattr_flags |= FUSE_GETATTR_FH;
1044 inarg.fh = ff->fh;
1045 }
Miklos Szeredid5b48542019-09-10 15:04:08 +02001046 args.opcode = FUSE_GETATTR;
1047 args.nodeid = get_node_id(inode);
1048 args.in_numargs = 1;
1049 args.in_args[0].size = sizeof(inarg);
1050 args.in_args[0].value = &inarg;
1051 args.out_numargs = 1;
1052 args.out_args[0].size = sizeof(outarg);
1053 args.out_args[0].value = &outarg;
Max Reitzfcee2162020-05-06 17:44:12 +02001054 err = fuse_simple_request(fm, &args);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001055 if (!err) {
Miklos Szeredieb59bd12019-11-12 11:49:04 +01001056 if (fuse_invalid_attr(&outarg.attr) ||
1057 (inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
Miklos Szeredi5d069db2020-12-10 15:33:14 +01001058 fuse_make_bad(inode);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001059 err = -EIO;
1060 } else {
Miklos Szeredic79e3222007-10-18 03:06:59 -07001061 fuse_change_attributes(inode, &outarg.attr,
1062 attr_timeout(&outarg),
Miklos Szeredi1fb69e72007-10-18 03:06:58 -07001063 attr_version);
1064 if (stat)
Miklos Szeredic79e3222007-10-18 03:06:59 -07001065 fuse_fillattr(inode, &outarg.attr, stat);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001066 }
1067 }
1068 return err;
1069}
1070
Miklos Szeredi5b97eea2017-09-12 16:57:54 +02001071static int fuse_update_get_attr(struct inode *inode, struct file *file,
Miklos Szeredi2f1e8192018-10-15 15:43:06 +02001072 struct kstat *stat, u32 request_mask,
1073 unsigned int flags)
Miklos Szeredibcb4be82007-11-28 16:21:59 -08001074{
1075 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredi5b97eea2017-09-12 16:57:54 +02001076 int err = 0;
Miklos Szeredibf5c1892018-03-20 17:11:44 +01001077 bool sync;
Miklos Szeredibcb4be82007-11-28 16:21:59 -08001078
Miklos Szeredibf5c1892018-03-20 17:11:44 +01001079 if (flags & AT_STATX_FORCE_SYNC)
1080 sync = true;
1081 else if (flags & AT_STATX_DONT_SYNC)
1082 sync = false;
Miklos Szeredi2f1e8192018-10-15 15:43:06 +02001083 else if (request_mask & READ_ONCE(fi->inval_mask))
1084 sync = true;
Miklos Szeredibf5c1892018-03-20 17:11:44 +01001085 else
1086 sync = time_before64(fi->i_time, get_jiffies_64());
1087
1088 if (sync) {
Seth Forshee60bcc882016-08-29 08:46:37 -05001089 forget_all_cached_acls(inode);
Miklos Szeredibcb4be82007-11-28 16:21:59 -08001090 err = fuse_do_getattr(inode, stat, file);
Miklos Szeredi5b97eea2017-09-12 16:57:54 +02001091 } else if (stat) {
Christian Brauner0d56a452021-01-21 14:19:30 +01001092 generic_fillattr(&init_user_ns, inode, stat);
Miklos Szeredi5b97eea2017-09-12 16:57:54 +02001093 stat->mode = fi->orig_i_mode;
1094 stat->ino = fi->orig_ino;
Miklos Szeredibcb4be82007-11-28 16:21:59 -08001095 }
1096
Miklos Szeredibcb4be82007-11-28 16:21:59 -08001097 return err;
1098}
1099
Miklos Szeredi5b97eea2017-09-12 16:57:54 +02001100int fuse_update_attributes(struct inode *inode, struct file *file)
1101{
Miklos Szeredi802dc042018-10-15 15:43:06 +02001102 /* Do *not* need to get atime for internal purposes */
1103 return fuse_update_get_attr(inode, file, NULL,
1104 STATX_BASIC_STATS & ~STATX_ATIME, 0);
Miklos Szeredi5b97eea2017-09-12 16:57:54 +02001105}
1106
Max Reitzfcee2162020-05-06 17:44:12 +02001107int fuse_reverse_inval_entry(struct fuse_conn *fc, u64 parent_nodeid,
John Muir451d0f52011-12-06 21:50:06 +01001108 u64 child_nodeid, struct qstr *name)
John Muir3b463ae2009-05-31 11:13:57 -04001109{
1110 int err = -ENOTDIR;
1111 struct inode *parent;
1112 struct dentry *dir;
1113 struct dentry *entry;
1114
Max Reitzfcee2162020-05-06 17:44:12 +02001115 parent = fuse_ilookup(fc, parent_nodeid, NULL);
John Muir3b463ae2009-05-31 11:13:57 -04001116 if (!parent)
1117 return -ENOENT;
1118
Al Viro59551022016-01-22 15:40:57 -05001119 inode_lock(parent);
John Muir3b463ae2009-05-31 11:13:57 -04001120 if (!S_ISDIR(parent->i_mode))
1121 goto unlock;
1122
1123 err = -ENOENT;
1124 dir = d_find_alias(parent);
1125 if (!dir)
1126 goto unlock;
1127
Linus Torvalds8387ff22016-06-10 07:51:30 -07001128 name->hash = full_name_hash(dir, name->name, name->len);
John Muir3b463ae2009-05-31 11:13:57 -04001129 entry = d_lookup(dir, name);
1130 dput(dir);
1131 if (!entry)
1132 goto unlock;
1133
Miklos Szeredi261aaba72018-10-01 10:07:05 +02001134 fuse_dir_changed(parent);
John Muir3b463ae2009-05-31 11:13:57 -04001135 fuse_invalidate_entry(entry);
John Muir451d0f52011-12-06 21:50:06 +01001136
David Howells2b0143b2015-03-17 22:25:59 +00001137 if (child_nodeid != 0 && d_really_is_positive(entry)) {
Al Viro59551022016-01-22 15:40:57 -05001138 inode_lock(d_inode(entry));
David Howells2b0143b2015-03-17 22:25:59 +00001139 if (get_node_id(d_inode(entry)) != child_nodeid) {
John Muir451d0f52011-12-06 21:50:06 +01001140 err = -ENOENT;
1141 goto badentry;
1142 }
1143 if (d_mountpoint(entry)) {
1144 err = -EBUSY;
1145 goto badentry;
1146 }
David Howellse36cb0b2015-01-29 12:02:35 +00001147 if (d_is_dir(entry)) {
John Muir451d0f52011-12-06 21:50:06 +01001148 shrink_dcache_parent(entry);
1149 if (!simple_empty(entry)) {
1150 err = -ENOTEMPTY;
1151 goto badentry;
1152 }
David Howells2b0143b2015-03-17 22:25:59 +00001153 d_inode(entry)->i_flags |= S_DEAD;
John Muir451d0f52011-12-06 21:50:06 +01001154 }
1155 dont_mount(entry);
David Howells2b0143b2015-03-17 22:25:59 +00001156 clear_nlink(d_inode(entry));
John Muir451d0f52011-12-06 21:50:06 +01001157 err = 0;
1158 badentry:
Al Viro59551022016-01-22 15:40:57 -05001159 inode_unlock(d_inode(entry));
John Muir451d0f52011-12-06 21:50:06 +01001160 if (!err)
1161 d_delete(entry);
1162 } else {
1163 err = 0;
1164 }
John Muir3b463ae2009-05-31 11:13:57 -04001165 dput(entry);
John Muir3b463ae2009-05-31 11:13:57 -04001166
1167 unlock:
Al Viro59551022016-01-22 15:40:57 -05001168 inode_unlock(parent);
John Muir3b463ae2009-05-31 11:13:57 -04001169 iput(parent);
1170 return err;
1171}
1172
Miklos Szeredi87729a52005-09-09 13:10:34 -07001173/*
1174 * Calling into a user-controlled filesystem gives the filesystem
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001175 * daemon ptrace-like capabilities over the current process. This
Miklos Szeredi87729a52005-09-09 13:10:34 -07001176 * means, that the filesystem daemon is able to record the exact
1177 * filesystem operations performed, and can also control the behavior
1178 * of the requester process in otherwise impossible ways. For example
1179 * it can delay the operation for arbitrary length of time allowing
1180 * DoS against the requester.
1181 *
1182 * For this reason only those processes can call into the filesystem,
1183 * for which the owner of the mount has ptrace privilege. This
1184 * excludes processes started by other users, suid or sgid processes.
1185 */
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001186int fuse_allow_current_process(struct fuse_conn *fc)
Miklos Szeredi87729a52005-09-09 13:10:34 -07001187{
David Howellsc69e8d92008-11-14 10:39:19 +11001188 const struct cred *cred;
David Howellsc69e8d92008-11-14 10:39:19 +11001189
Miklos Szeredi29433a22016-10-01 07:32:32 +02001190 if (fc->allow_other)
Seth Forshee73f03c22017-12-22 15:32:33 +01001191 return current_in_userns(fc->user_ns);
Miklos Szeredi87729a52005-09-09 13:10:34 -07001192
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001193 cred = current_cred();
Eric W. Biederman499dcf22012-02-07 16:26:03 -08001194 if (uid_eq(cred->euid, fc->user_id) &&
1195 uid_eq(cred->suid, fc->user_id) &&
1196 uid_eq(cred->uid, fc->user_id) &&
1197 gid_eq(cred->egid, fc->group_id) &&
1198 gid_eq(cred->sgid, fc->group_id) &&
1199 gid_eq(cred->gid, fc->group_id))
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001200 return 1;
Miklos Szeredi87729a52005-09-09 13:10:34 -07001201
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001202 return 0;
Miklos Szeredi87729a52005-09-09 13:10:34 -07001203}
1204
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001205static int fuse_access(struct inode *inode, int mask)
1206{
Max Reitzfcee2162020-05-06 17:44:12 +02001207 struct fuse_mount *fm = get_fuse_mount(inode);
Miklos Szeredi70781872014-12-12 09:49:05 +01001208 FUSE_ARGS(args);
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001209 struct fuse_access_in inarg;
1210 int err;
1211
Miklos Szeredi698fa1d2013-10-01 16:41:23 +02001212 BUG_ON(mask & MAY_NOT_BLOCK);
1213
Max Reitzfcee2162020-05-06 17:44:12 +02001214 if (fm->fc->no_access)
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001215 return 0;
1216
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001217 memset(&inarg, 0, sizeof(inarg));
Al Viroe6305c42008-07-15 21:03:57 -04001218 inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC);
Miklos Szeredid5b48542019-09-10 15:04:08 +02001219 args.opcode = FUSE_ACCESS;
1220 args.nodeid = get_node_id(inode);
1221 args.in_numargs = 1;
1222 args.in_args[0].size = sizeof(inarg);
1223 args.in_args[0].value = &inarg;
Max Reitzfcee2162020-05-06 17:44:12 +02001224 err = fuse_simple_request(fm, &args);
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001225 if (err == -ENOSYS) {
Max Reitzfcee2162020-05-06 17:44:12 +02001226 fm->fc->no_access = 1;
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001227 err = 0;
1228 }
1229 return err;
1230}
1231
Al Viro10556cb22011-06-20 19:28:19 -04001232static int fuse_perm_getattr(struct inode *inode, int mask)
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001233{
Al Viro10556cb22011-06-20 19:28:19 -04001234 if (mask & MAY_NOT_BLOCK)
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001235 return -ECHILD;
1236
Seth Forshee60bcc882016-08-29 08:46:37 -05001237 forget_all_cached_acls(inode);
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001238 return fuse_do_getattr(inode, NULL, NULL);
1239}
1240
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001241/*
1242 * Check permission. The two basic access models of FUSE are:
1243 *
1244 * 1) Local access checking ('default_permissions' mount option) based
1245 * on file mode. This is the plain old disk filesystem permission
1246 * modell.
1247 *
1248 * 2) "Remote" access checking, where server is responsible for
1249 * checking permission in each inode operation. An exception to this
1250 * is if ->permission() was invoked from sys_access() in which case an
1251 * access request is sent. Execute permission is still checked
1252 * locally based on file mode.
1253 */
Christian Brauner549c7292021-01-21 14:19:43 +01001254static int fuse_permission(struct user_namespace *mnt_userns,
1255 struct inode *inode, int mask)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001256{
1257 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi244f6382007-10-16 23:31:02 -07001258 bool refreshed = false;
1259 int err = 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001260
Miklos Szeredi5d069db2020-12-10 15:33:14 +01001261 if (fuse_is_bad(inode))
1262 return -EIO;
1263
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001264 if (!fuse_allow_current_process(fc))
Miklos Szeredie5e55582005-09-09 13:10:28 -07001265 return -EACCES;
Miklos Szeredi244f6382007-10-16 23:31:02 -07001266
1267 /*
Miklos Szeredie8e96152007-10-16 23:31:06 -07001268 * If attributes are needed, refresh them before proceeding
Miklos Szeredi244f6382007-10-16 23:31:02 -07001269 */
Miklos Szeredi29433a22016-10-01 07:32:32 +02001270 if (fc->default_permissions ||
Miklos Szeredie8e96152007-10-16 23:31:06 -07001271 ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001272 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredid233c7d2018-12-03 10:14:43 +01001273 u32 perm_mask = STATX_MODE | STATX_UID | STATX_GID;
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001274
Miklos Szeredid233c7d2018-12-03 10:14:43 +01001275 if (perm_mask & READ_ONCE(fi->inval_mask) ||
1276 time_before64(fi->i_time, get_jiffies_64())) {
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001277 refreshed = true;
1278
Al Viro10556cb22011-06-20 19:28:19 -04001279 err = fuse_perm_getattr(inode, mask);
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001280 if (err)
1281 return err;
1282 }
Miklos Szeredi244f6382007-10-16 23:31:02 -07001283 }
1284
Miklos Szeredi29433a22016-10-01 07:32:32 +02001285 if (fc->default_permissions) {
Christian Brauner47291ba2021-01-21 14:19:24 +01001286 err = generic_permission(&init_user_ns, inode, mask);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001287
1288 /* If permission is denied, try to refresh file
1289 attributes. This is also needed, because the root
1290 node will at first have no permissions */
Miklos Szeredi244f6382007-10-16 23:31:02 -07001291 if (err == -EACCES && !refreshed) {
Al Viro10556cb22011-06-20 19:28:19 -04001292 err = fuse_perm_getattr(inode, mask);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001293 if (!err)
Christian Brauner47291ba2021-01-21 14:19:24 +01001294 err = generic_permission(&init_user_ns,
1295 inode, mask);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001296 }
1297
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001298 /* Note: the opposite of the above test does not
1299 exist. So if permissions are revoked this won't be
1300 noticed immediately, only after the attribute
1301 timeout has expired */
Eric Paris9cfcac82010-07-23 11:43:51 -04001302 } else if (mask & (MAY_ACCESS | MAY_CHDIR)) {
Miklos Szeredie8e96152007-10-16 23:31:06 -07001303 err = fuse_access(inode, mask);
1304 } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
1305 if (!(inode->i_mode & S_IXUGO)) {
1306 if (refreshed)
1307 return -EACCES;
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001308
Al Viro10556cb22011-06-20 19:28:19 -04001309 err = fuse_perm_getattr(inode, mask);
Miklos Szeredie8e96152007-10-16 23:31:06 -07001310 if (!err && !(inode->i_mode & S_IXUGO))
1311 return -EACCES;
1312 }
Miklos Szeredie5e55582005-09-09 13:10:28 -07001313 }
Miklos Szeredi244f6382007-10-16 23:31:02 -07001314 return err;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001315}
1316
Dan Schatzberg5571f1e2018-10-11 08:17:00 -07001317static int fuse_readlink_page(struct inode *inode, struct page *page)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001318{
Max Reitzfcee2162020-05-06 17:44:12 +02001319 struct fuse_mount *fm = get_fuse_mount(inode);
Miklos Szeredi4c29afe2019-09-10 15:04:09 +02001320 struct fuse_page_desc desc = { .length = PAGE_SIZE - 1 };
1321 struct fuse_args_pages ap = {
1322 .num_pages = 1,
1323 .pages = &page,
1324 .descs = &desc,
1325 };
1326 char *link;
1327 ssize_t res;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001328
Miklos Szeredi4c29afe2019-09-10 15:04:09 +02001329 ap.args.opcode = FUSE_READLINK;
1330 ap.args.nodeid = get_node_id(inode);
1331 ap.args.out_pages = true;
1332 ap.args.out_argvar = true;
1333 ap.args.page_zeroing = true;
1334 ap.args.out_numargs = 1;
1335 ap.args.out_args[0].size = desc.length;
Max Reitzfcee2162020-05-06 17:44:12 +02001336 res = fuse_simple_request(fm, &ap.args);
Al Viro6b255392015-11-17 10:20:54 -05001337
Andrew Gallagher451418f2013-11-05 03:55:43 -08001338 fuse_invalidate_atime(inode);
Dan Schatzberg5571f1e2018-10-11 08:17:00 -07001339
Miklos Szeredi4c29afe2019-09-10 15:04:09 +02001340 if (res < 0)
1341 return res;
1342
1343 if (WARN_ON(res >= PAGE_SIZE))
1344 return -EIO;
1345
1346 link = page_address(page);
1347 link[res] = '\0';
1348
1349 return 0;
Dan Schatzberg5571f1e2018-10-11 08:17:00 -07001350}
1351
1352static const char *fuse_get_link(struct dentry *dentry, struct inode *inode,
1353 struct delayed_call *callback)
1354{
1355 struct fuse_conn *fc = get_fuse_conn(inode);
1356 struct page *page;
1357 int err;
1358
1359 err = -EIO;
Miklos Szeredi5d069db2020-12-10 15:33:14 +01001360 if (fuse_is_bad(inode))
Dan Schatzberg5571f1e2018-10-11 08:17:00 -07001361 goto out_err;
1362
1363 if (fc->cache_symlinks)
1364 return page_get_link(dentry, inode, callback);
1365
1366 err = -ECHILD;
1367 if (!dentry)
1368 goto out_err;
1369
1370 page = alloc_page(GFP_KERNEL);
1371 err = -ENOMEM;
1372 if (!page)
1373 goto out_err;
1374
1375 err = fuse_readlink_page(inode, page);
1376 if (err) {
1377 __free_page(page);
1378 goto out_err;
1379 }
1380
1381 set_delayed_call(callback, page_put_link, page);
1382
1383 return page_address(page);
1384
1385out_err:
1386 return ERR_PTR(err);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001387}
1388
Miklos Szeredie5e55582005-09-09 13:10:28 -07001389static int fuse_dir_open(struct inode *inode, struct file *file)
1390{
Miklos Szeredi91fe96b2009-04-28 16:56:37 +02001391 return fuse_open_common(inode, file, true);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001392}
1393
1394static int fuse_dir_release(struct inode *inode, struct file *file)
1395{
Chad Austin2e64ff12018-12-10 10:54:52 -08001396 fuse_release_common(file, true);
Miklos Szeredi8b0797a2009-04-28 16:56:39 +02001397
1398 return 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001399}
1400
Josef Bacik02c24a82011-07-16 20:44:56 -04001401static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end,
1402 int datasync)
Miklos Szeredi82547982005-09-09 13:10:38 -07001403{
Miklos Szeredia9c2d1e2018-12-03 10:14:43 +01001404 struct inode *inode = file->f_mapping->host;
1405 struct fuse_conn *fc = get_fuse_conn(inode);
1406 int err;
1407
Miklos Szeredi5d069db2020-12-10 15:33:14 +01001408 if (fuse_is_bad(inode))
Miklos Szeredia9c2d1e2018-12-03 10:14:43 +01001409 return -EIO;
1410
1411 if (fc->no_fsyncdir)
1412 return 0;
1413
1414 inode_lock(inode);
1415 err = fuse_fsync_common(file, start, end, datasync, FUSE_FSYNCDIR);
1416 if (err == -ENOSYS) {
1417 fc->no_fsyncdir = 1;
1418 err = 0;
1419 }
1420 inode_unlock(inode);
1421
1422 return err;
Miklos Szeredi82547982005-09-09 13:10:38 -07001423}
1424
Miklos Szeredib18da0c2011-12-13 11:58:49 +01001425static long fuse_dir_ioctl(struct file *file, unsigned int cmd,
1426 unsigned long arg)
1427{
1428 struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1429
1430 /* FUSE_IOCTL_DIR only supported for API version >= 7.18 */
1431 if (fc->minor < 18)
1432 return -ENOTTY;
1433
1434 return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR);
1435}
1436
1437static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd,
1438 unsigned long arg)
1439{
1440 struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1441
1442 if (fc->minor < 18)
1443 return -ENOTTY;
1444
1445 return fuse_ioctl_common(file, cmd, arg,
1446 FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR);
1447}
1448
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001449static bool update_mtime(unsigned ivalid, bool trust_local_mtime)
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001450{
1451 /* Always update if mtime is explicitly set */
1452 if (ivalid & ATTR_MTIME_SET)
1453 return true;
1454
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001455 /* Or if kernel i_mtime is the official one */
1456 if (trust_local_mtime)
1457 return true;
1458
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001459 /* If it's an open(O_TRUNC) or an ftruncate(), don't update */
1460 if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
1461 return false;
1462
1463 /* In all other cases update */
1464 return true;
1465}
1466
Eric W. Biederman8cb08322018-02-21 11:18:07 -06001467static void iattr_to_fattr(struct fuse_conn *fc, struct iattr *iattr,
1468 struct fuse_setattr_in *arg, bool trust_local_cmtime)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001469{
1470 unsigned ivalid = iattr->ia_valid;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001471
1472 if (ivalid & ATTR_MODE)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001473 arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001474 if (ivalid & ATTR_UID)
Eric W. Biederman8cb08322018-02-21 11:18:07 -06001475 arg->valid |= FATTR_UID, arg->uid = from_kuid(fc->user_ns, iattr->ia_uid);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001476 if (ivalid & ATTR_GID)
Eric W. Biederman8cb08322018-02-21 11:18:07 -06001477 arg->valid |= FATTR_GID, arg->gid = from_kgid(fc->user_ns, iattr->ia_gid);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001478 if (ivalid & ATTR_SIZE)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001479 arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001480 if (ivalid & ATTR_ATIME) {
1481 arg->valid |= FATTR_ATIME;
Miklos Szeredibefc6492005-11-07 00:59:52 -08001482 arg->atime = iattr->ia_atime.tv_sec;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001483 arg->atimensec = iattr->ia_atime.tv_nsec;
1484 if (!(ivalid & ATTR_ATIME_SET))
1485 arg->valid |= FATTR_ATIME_NOW;
1486 }
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001487 if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, trust_local_cmtime)) {
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001488 arg->valid |= FATTR_MTIME;
Miklos Szeredibefc6492005-11-07 00:59:52 -08001489 arg->mtime = iattr->ia_mtime.tv_sec;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001490 arg->mtimensec = iattr->ia_mtime.tv_nsec;
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001491 if (!(ivalid & ATTR_MTIME_SET) && !trust_local_cmtime)
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001492 arg->valid |= FATTR_MTIME_NOW;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001493 }
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001494 if ((ivalid & ATTR_CTIME) && trust_local_cmtime) {
1495 arg->valid |= FATTR_CTIME;
1496 arg->ctime = iattr->ia_ctime.tv_sec;
1497 arg->ctimensec = iattr->ia_ctime.tv_nsec;
1498 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001499}
1500
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001501/*
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001502 * Prevent concurrent writepages on inode
1503 *
1504 * This is done by adding a negative bias to the inode write counter
1505 * and waiting for all pending writes to finish.
1506 */
1507void fuse_set_nowrite(struct inode *inode)
1508{
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001509 struct fuse_inode *fi = get_fuse_inode(inode);
1510
Al Viro59551022016-01-22 15:40:57 -05001511 BUG_ON(!inode_is_locked(inode));
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001512
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +03001513 spin_lock(&fi->lock);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001514 BUG_ON(fi->writectr < 0);
1515 fi->writectr += FUSE_NOWRITE;
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +03001516 spin_unlock(&fi->lock);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001517 wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE);
1518}
1519
1520/*
1521 * Allow writepages on inode
1522 *
1523 * Remove the bias from the writecounter and send any queued
1524 * writepages.
1525 */
1526static void __fuse_release_nowrite(struct inode *inode)
1527{
1528 struct fuse_inode *fi = get_fuse_inode(inode);
1529
1530 BUG_ON(fi->writectr != FUSE_NOWRITE);
1531 fi->writectr = 0;
1532 fuse_flush_writepages(inode);
1533}
1534
1535void fuse_release_nowrite(struct inode *inode)
1536{
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +03001537 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001538
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +03001539 spin_lock(&fi->lock);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001540 __fuse_release_nowrite(inode);
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +03001541 spin_unlock(&fi->lock);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001542}
1543
Miklos Szeredi70781872014-12-12 09:49:05 +01001544static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_args *args,
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001545 struct inode *inode,
1546 struct fuse_setattr_in *inarg_p,
1547 struct fuse_attr_out *outarg_p)
1548{
Miklos Szeredid5b48542019-09-10 15:04:08 +02001549 args->opcode = FUSE_SETATTR;
1550 args->nodeid = get_node_id(inode);
1551 args->in_numargs = 1;
1552 args->in_args[0].size = sizeof(*inarg_p);
1553 args->in_args[0].value = inarg_p;
1554 args->out_numargs = 1;
1555 args->out_args[0].size = sizeof(*outarg_p);
1556 args->out_args[0].value = outarg_p;
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001557}
1558
1559/*
1560 * Flush inode->i_mtime to the server
1561 */
Maxim Patlasovab9e13f2014-04-28 14:19:24 +02001562int fuse_flush_times(struct inode *inode, struct fuse_file *ff)
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001563{
Max Reitzfcee2162020-05-06 17:44:12 +02001564 struct fuse_mount *fm = get_fuse_mount(inode);
Miklos Szeredi70781872014-12-12 09:49:05 +01001565 FUSE_ARGS(args);
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001566 struct fuse_setattr_in inarg;
1567 struct fuse_attr_out outarg;
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001568
1569 memset(&inarg, 0, sizeof(inarg));
1570 memset(&outarg, 0, sizeof(outarg));
1571
Maxim Patlasovab9e13f2014-04-28 14:19:24 +02001572 inarg.valid = FATTR_MTIME;
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001573 inarg.mtime = inode->i_mtime.tv_sec;
1574 inarg.mtimensec = inode->i_mtime.tv_nsec;
Max Reitzfcee2162020-05-06 17:44:12 +02001575 if (fm->fc->minor >= 23) {
Maxim Patlasovab9e13f2014-04-28 14:19:24 +02001576 inarg.valid |= FATTR_CTIME;
1577 inarg.ctime = inode->i_ctime.tv_sec;
1578 inarg.ctimensec = inode->i_ctime.tv_nsec;
1579 }
Miklos Szeredi1e18bda2014-04-28 14:19:23 +02001580 if (ff) {
1581 inarg.valid |= FATTR_FH;
1582 inarg.fh = ff->fh;
1583 }
Max Reitzfcee2162020-05-06 17:44:12 +02001584 fuse_setattr_fill(fm->fc, &args, inode, &inarg, &outarg);
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001585
Max Reitzfcee2162020-05-06 17:44:12 +02001586 return fuse_simple_request(fm, &args);
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001587}
1588
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001589/*
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001590 * Set attributes, and at the same time refresh them.
1591 *
1592 * Truncation is slightly complicated, because the 'truncate' request
1593 * may fail, in which case we don't want to touch the mapping.
Miklos Szeredi9ffbb912006-10-17 00:10:06 -07001594 * vmtruncate() doesn't allow for this case, so do the rlimit checking
1595 * and the actual truncation by hand.
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001596 */
Jan Kara62490332016-05-26 17:12:41 +02001597int fuse_do_setattr(struct dentry *dentry, struct iattr *attr,
Maxim Patlasovefb9fa92012-12-18 14:05:08 +04001598 struct file *file)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001599{
Jan Kara62490332016-05-26 17:12:41 +02001600 struct inode *inode = d_inode(dentry);
Max Reitzfcee2162020-05-06 17:44:12 +02001601 struct fuse_mount *fm = get_fuse_mount(inode);
1602 struct fuse_conn *fc = fm->fc;
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001603 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredi70781872014-12-12 09:49:05 +01001604 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001605 struct fuse_setattr_in inarg;
1606 struct fuse_attr_out outarg;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001607 bool is_truncate = false;
Pavel Emelyanov83732002013-10-10 17:10:46 +04001608 bool is_wb = fc->writeback_cache;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001609 loff_t oldsize;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001610 int err;
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001611 bool trust_local_cmtime = is_wb && S_ISREG(inode->i_mode);
Vivek Goyal6ae330c2020-08-19 18:19:54 -04001612 bool fault_blocked = false;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001613
Miklos Szeredi29433a22016-10-01 07:32:32 +02001614 if (!fc->default_permissions)
Christoph Hellwigdb78b872010-06-04 11:30:03 +02001615 attr->ia_valid |= ATTR_FORCE;
1616
Christian Brauner2f221d62021-01-21 14:19:26 +01001617 err = setattr_prepare(&init_user_ns, dentry, attr);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02001618 if (err)
1619 return err;
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001620
Vivek Goyal6ae330c2020-08-19 18:19:54 -04001621 if (attr->ia_valid & ATTR_SIZE) {
1622 if (WARN_ON(!S_ISREG(inode->i_mode)))
1623 return -EIO;
1624 is_truncate = true;
1625 }
1626
1627 if (FUSE_IS_DAX(inode) && is_truncate) {
1628 down_write(&fi->i_mmap_sem);
1629 fault_blocked = true;
1630 err = fuse_dax_break_layouts(inode, 0, 0);
1631 if (err) {
1632 up_write(&fi->i_mmap_sem);
1633 return err;
1634 }
1635 }
1636
Miklos Szeredi8d56add2011-02-25 14:44:58 +01001637 if (attr->ia_valid & ATTR_OPEN) {
Miklos Szeredidf0e91d2018-02-08 15:17:38 +01001638 /* This is coming from open(..., ... | O_TRUNC); */
1639 WARN_ON(!(attr->ia_valid & ATTR_SIZE));
1640 WARN_ON(attr->ia_size != 0);
1641 if (fc->atomic_o_trunc) {
1642 /*
1643 * No need to send request to userspace, since actual
1644 * truncation has already been done by OPEN. But still
1645 * need to truncate page cache.
1646 */
1647 i_size_write(inode, 0);
1648 truncate_pagecache(inode, 0);
Vivek Goyal6ae330c2020-08-19 18:19:54 -04001649 goto out;
Miklos Szeredidf0e91d2018-02-08 15:17:38 +01001650 }
Miklos Szeredi8d56add2011-02-25 14:44:58 +01001651 file = NULL;
1652 }
Miklos Szeredi6ff958e2007-10-18 03:07:02 -07001653
Miklos Szeredib24e7592019-10-23 14:26:37 +02001654 /* Flush dirty data/metadata before non-truncate SETATTR */
1655 if (is_wb && S_ISREG(inode->i_mode) &&
1656 attr->ia_valid &
1657 (ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_MTIME_SET |
1658 ATTR_TIMES_SET)) {
1659 err = write_inode_now(inode, true);
1660 if (err)
1661 return err;
1662
1663 fuse_set_nowrite(inode);
1664 fuse_release_nowrite(inode);
1665 }
1666
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001667 if (is_truncate) {
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001668 fuse_set_nowrite(inode);
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001669 set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001670 if (trust_local_cmtime && attr->ia_size != inode->i_size)
1671 attr->ia_valid |= ATTR_MTIME | ATTR_CTIME;
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001672 }
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001673
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001674 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -07001675 memset(&outarg, 0, sizeof(outarg));
Eric W. Biederman8cb08322018-02-21 11:18:07 -06001676 iattr_to_fattr(fc, attr, &inarg, trust_local_cmtime);
Miklos Szeredi49d49142007-10-18 03:07:00 -07001677 if (file) {
1678 struct fuse_file *ff = file->private_data;
1679 inarg.valid |= FATTR_FH;
1680 inarg.fh = ff->fh;
1681 }
Vivek Goyal31792162020-10-09 14:15:09 -04001682
1683 /* Kill suid/sgid for non-directory chown unconditionally */
1684 if (fc->handle_killpriv_v2 && !S_ISDIR(inode->i_mode) &&
1685 attr->ia_valid & (ATTR_UID | ATTR_GID))
1686 inarg.valid |= FATTR_KILL_SUIDGID;
1687
Miklos Szeredif3332112007-10-18 03:07:04 -07001688 if (attr->ia_valid & ATTR_SIZE) {
1689 /* For mandatory locking in truncate */
1690 inarg.valid |= FATTR_LOCKOWNER;
1691 inarg.lock_owner = fuse_lock_owner_id(fc, current->files);
Vivek Goyal31792162020-10-09 14:15:09 -04001692
1693 /* Kill suid/sgid for truncate only if no CAP_FSETID */
1694 if (fc->handle_killpriv_v2 && !capable(CAP_FSETID))
1695 inarg.valid |= FATTR_KILL_SUIDGID;
Miklos Szeredif3332112007-10-18 03:07:04 -07001696 }
Miklos Szeredi70781872014-12-12 09:49:05 +01001697 fuse_setattr_fill(fc, &args, inode, &inarg, &outarg);
Max Reitzfcee2162020-05-06 17:44:12 +02001698 err = fuse_simple_request(fm, &args);
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001699 if (err) {
1700 if (err == -EINTR)
1701 fuse_invalidate_attr(inode);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001702 goto error;
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001703 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001704
Miklos Szeredieb59bd12019-11-12 11:49:04 +01001705 if (fuse_invalid_attr(&outarg.attr) ||
1706 (inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
Miklos Szeredi5d069db2020-12-10 15:33:14 +01001707 fuse_make_bad(inode);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001708 err = -EIO;
1709 goto error;
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001710 }
1711
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +03001712 spin_lock(&fi->lock);
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001713 /* the kernel maintains i_mtime locally */
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001714 if (trust_local_cmtime) {
1715 if (attr->ia_valid & ATTR_MTIME)
1716 inode->i_mtime = attr->ia_mtime;
1717 if (attr->ia_valid & ATTR_CTIME)
1718 inode->i_ctime = attr->ia_ctime;
Miklos Szeredi1e18bda2014-04-28 14:19:23 +02001719 /* FIXME: clear I_DIRTY_SYNC? */
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001720 }
1721
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001722 fuse_change_attributes_common(inode, &outarg.attr,
1723 attr_timeout(&outarg));
1724 oldsize = inode->i_size;
Pavel Emelyanov83732002013-10-10 17:10:46 +04001725 /* see the comment in fuse_change_attributes() */
1726 if (!is_wb || is_truncate || !S_ISREG(inode->i_mode))
1727 i_size_write(inode, outarg.attr.size);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001728
1729 if (is_truncate) {
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +03001730 /* NOTE: this may release/reacquire fi->lock */
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001731 __fuse_release_nowrite(inode);
1732 }
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +03001733 spin_unlock(&fi->lock);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001734
1735 /*
1736 * Only call invalidate_inode_pages2() after removing
1737 * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock.
1738 */
Pavel Emelyanov83732002013-10-10 17:10:46 +04001739 if ((is_truncate || !is_wb) &&
1740 S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
Kirill A. Shutemov7caef262013-09-12 15:13:56 -07001741 truncate_pagecache(inode, outarg.attr.size);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001742 invalidate_inode_pages2(inode->i_mapping);
1743 }
1744
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001745 clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
Vivek Goyal6ae330c2020-08-19 18:19:54 -04001746out:
1747 if (fault_blocked)
1748 up_write(&fi->i_mmap_sem);
1749
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001750 return 0;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001751
1752error:
1753 if (is_truncate)
1754 fuse_release_nowrite(inode);
1755
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001756 clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
Vivek Goyal6ae330c2020-08-19 18:19:54 -04001757
1758 if (fault_blocked)
1759 up_write(&fi->i_mmap_sem);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001760 return err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001761}
1762
Christian Brauner549c7292021-01-21 14:19:43 +01001763static int fuse_setattr(struct user_namespace *mnt_userns, struct dentry *entry,
1764 struct iattr *attr)
Miklos Szeredi49d49142007-10-18 03:07:00 -07001765{
David Howells2b0143b2015-03-17 22:25:59 +00001766 struct inode *inode = d_inode(entry);
Miklos Szeredi5e940c12016-10-01 07:32:32 +02001767 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredia09f99e2016-10-01 07:32:32 +02001768 struct file *file = (attr->ia_valid & ATTR_FILE) ? attr->ia_file : NULL;
Miklos Szeredi5e2b8822016-10-01 07:32:32 +02001769 int ret;
Maxim Patlasovefb9fa92012-12-18 14:05:08 +04001770
Miklos Szeredi5d069db2020-12-10 15:33:14 +01001771 if (fuse_is_bad(inode))
1772 return -EIO;
1773
Maxim Patlasovefb9fa92012-12-18 14:05:08 +04001774 if (!fuse_allow_current_process(get_fuse_conn(inode)))
1775 return -EACCES;
1776
Miklos Szeredia09f99e2016-10-01 07:32:32 +02001777 if (attr->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) {
Miklos Szeredia09f99e2016-10-01 07:32:32 +02001778 attr->ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID |
1779 ATTR_MODE);
Miklos Szeredia09f99e2016-10-01 07:32:32 +02001780
Miklos Szeredi5e940c12016-10-01 07:32:32 +02001781 /*
1782 * The only sane way to reliably kill suid/sgid is to do it in
1783 * the userspace filesystem
1784 *
1785 * This should be done on write(), truncate() and chown().
1786 */
Vivek Goyal8981bdf2020-10-09 14:15:10 -04001787 if (!fc->handle_killpriv && !fc->handle_killpriv_v2) {
Miklos Szeredi5e940c12016-10-01 07:32:32 +02001788 /*
1789 * ia_mode calculation may have used stale i_mode.
1790 * Refresh and recalculate.
1791 */
1792 ret = fuse_do_getattr(inode, NULL, file);
1793 if (ret)
1794 return ret;
1795
1796 attr->ia_mode = inode->i_mode;
Miklos Szeredic01638f2016-12-06 16:18:45 +01001797 if (inode->i_mode & S_ISUID) {
Miklos Szeredi5e940c12016-10-01 07:32:32 +02001798 attr->ia_valid |= ATTR_MODE;
1799 attr->ia_mode &= ~S_ISUID;
1800 }
Miklos Szeredic01638f2016-12-06 16:18:45 +01001801 if ((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
Miklos Szeredi5e940c12016-10-01 07:32:32 +02001802 attr->ia_valid |= ATTR_MODE;
1803 attr->ia_mode &= ~S_ISGID;
1804 }
Miklos Szeredia09f99e2016-10-01 07:32:32 +02001805 }
1806 }
1807 if (!attr->ia_valid)
1808 return 0;
1809
Linus Torvaldsabb5a142016-10-10 13:04:49 -07001810 ret = fuse_do_setattr(entry, attr, file);
Miklos Szeredi5e2b8822016-10-01 07:32:32 +02001811 if (!ret) {
Seth Forshee60bcc882016-08-29 08:46:37 -05001812 /*
1813 * If filesystem supports acls it may have updated acl xattrs in
1814 * the filesystem, so forget cached acls for the inode.
1815 */
1816 if (fc->posix_acl)
1817 forget_all_cached_acls(inode);
1818
Miklos Szeredi5e2b8822016-10-01 07:32:32 +02001819 /* Directory mode changed, may need to revalidate access */
1820 if (d_is_dir(entry) && (attr->ia_valid & ATTR_MODE))
1821 fuse_invalidate_entry_cache(entry);
1822 }
1823 return ret;
Miklos Szeredi49d49142007-10-18 03:07:00 -07001824}
1825
Christian Brauner549c7292021-01-21 14:19:43 +01001826static int fuse_getattr(struct user_namespace *mnt_userns,
1827 const struct path *path, struct kstat *stat,
David Howellsa528d352017-01-31 16:46:22 +00001828 u32 request_mask, unsigned int flags)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001829{
David Howellsa528d352017-01-31 16:46:22 +00001830 struct inode *inode = d_inode(path->dentry);
Miklos Szeredi244f6382007-10-16 23:31:02 -07001831 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi244f6382007-10-16 23:31:02 -07001832
Miklos Szeredi5d069db2020-12-10 15:33:14 +01001833 if (fuse_is_bad(inode))
1834 return -EIO;
1835
Miklos Szeredi5157da22020-05-19 14:50:37 +02001836 if (!fuse_allow_current_process(fc)) {
1837 if (!request_mask) {
1838 /*
1839 * If user explicitly requested *nothing* then don't
1840 * error out, but return st_dev only.
1841 */
1842 stat->result_mask = 0;
1843 stat->dev = inode->i_sb->s_dev;
1844 return 0;
1845 }
Miklos Szeredi244f6382007-10-16 23:31:02 -07001846 return -EACCES;
Miklos Szeredi5157da22020-05-19 14:50:37 +02001847 }
Miklos Szeredi244f6382007-10-16 23:31:02 -07001848
Miklos Szeredi2f1e8192018-10-15 15:43:06 +02001849 return fuse_update_get_attr(inode, NULL, stat, request_mask, flags);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001850}
1851
Arjan van de Ven754661f2007-02-12 00:55:38 -08001852static const struct inode_operations fuse_dir_inode_operations = {
Miklos Szeredie5e55582005-09-09 13:10:28 -07001853 .lookup = fuse_lookup,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001854 .mkdir = fuse_mkdir,
1855 .symlink = fuse_symlink,
1856 .unlink = fuse_unlink,
1857 .rmdir = fuse_rmdir,
Miklos Szeredi2773bf02016-09-27 11:03:58 +02001858 .rename = fuse_rename2,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001859 .link = fuse_link,
1860 .setattr = fuse_setattr,
1861 .create = fuse_create,
Miklos Szeredic8ccbe02012-06-05 15:10:22 +02001862 .atomic_open = fuse_atomic_open,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001863 .mknod = fuse_mknod,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001864 .permission = fuse_permission,
1865 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001866 .listxattr = fuse_listxattr,
Seth Forshee60bcc882016-08-29 08:46:37 -05001867 .get_acl = fuse_get_acl,
1868 .set_acl = fuse_set_acl,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001869};
1870
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -08001871static const struct file_operations fuse_dir_operations = {
Miklos Szeredib6aeade2005-09-09 13:10:30 -07001872 .llseek = generic_file_llseek,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001873 .read = generic_read_dir,
Al Virod9b3dbd2016-04-20 17:30:32 -04001874 .iterate_shared = fuse_readdir,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001875 .open = fuse_dir_open,
1876 .release = fuse_dir_release,
Miklos Szeredi82547982005-09-09 13:10:38 -07001877 .fsync = fuse_dir_fsync,
Miklos Szeredib18da0c2011-12-13 11:58:49 +01001878 .unlocked_ioctl = fuse_dir_ioctl,
1879 .compat_ioctl = fuse_dir_compat_ioctl,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001880};
1881
Arjan van de Ven754661f2007-02-12 00:55:38 -08001882static const struct inode_operations fuse_common_inode_operations = {
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001883 .setattr = fuse_setattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001884 .permission = fuse_permission,
1885 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001886 .listxattr = fuse_listxattr,
Seth Forshee60bcc882016-08-29 08:46:37 -05001887 .get_acl = fuse_get_acl,
1888 .set_acl = fuse_set_acl,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001889};
1890
Arjan van de Ven754661f2007-02-12 00:55:38 -08001891static const struct inode_operations fuse_symlink_inode_operations = {
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001892 .setattr = fuse_setattr,
Al Viro6b255392015-11-17 10:20:54 -05001893 .get_link = fuse_get_link,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001894 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001895 .listxattr = fuse_listxattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001896};
1897
1898void fuse_init_common(struct inode *inode)
1899{
1900 inode->i_op = &fuse_common_inode_operations;
1901}
1902
1903void fuse_init_dir(struct inode *inode)
1904{
Miklos Szerediab2257e2018-10-01 10:07:05 +02001905 struct fuse_inode *fi = get_fuse_inode(inode);
1906
Miklos Szeredie5e55582005-09-09 13:10:28 -07001907 inode->i_op = &fuse_dir_inode_operations;
1908 inode->i_fop = &fuse_dir_operations;
Miklos Szerediab2257e2018-10-01 10:07:05 +02001909
1910 spin_lock_init(&fi->rdc.lock);
1911 fi->rdc.cached = false;
1912 fi->rdc.size = 0;
1913 fi->rdc.pos = 0;
1914 fi->rdc.version = 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001915}
1916
Dan Schatzberg5571f1e2018-10-11 08:17:00 -07001917static int fuse_symlink_readpage(struct file *null, struct page *page)
1918{
1919 int err = fuse_readlink_page(page->mapping->host, page);
1920
1921 if (!err)
1922 SetPageUptodate(page);
1923
1924 unlock_page(page);
1925
1926 return err;
1927}
1928
1929static const struct address_space_operations fuse_symlink_aops = {
1930 .readpage = fuse_symlink_readpage,
1931};
1932
Miklos Szeredie5e55582005-09-09 13:10:28 -07001933void fuse_init_symlink(struct inode *inode)
1934{
1935 inode->i_op = &fuse_symlink_inode_operations;
Dan Schatzberg5571f1e2018-10-11 08:17:00 -07001936 inode->i_data.a_ops = &fuse_symlink_aops;
1937 inode_nohighmem(inode);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001938}