blob: 0034d7b915c17584cd8444b80a68686eda4e58dd [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 Szeredi36cf9ae2020-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()) ||
208 (flags & 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
331 refcount_set(&fm->count, 1);
332 fsc->s_fs_info = fm;
333 sb = sget_fc(fsc, NULL, set_anon_super_fc);
334 if (IS_ERR(sb)) {
335 err = PTR_ERR(sb);
336 fuse_mount_put(fm);
337 goto out_put_fsc;
338 }
339 fm->fc = fuse_conn_get(fc);
340
341 /* Initialize superblock, making @mp_fi its root */
342 err = fuse_fill_super_submount(sb, mp_fi);
Greg Kurz91c2aa22021-06-04 18:11:50 +0200343 if (err) {
344 fuse_conn_put(fc);
345 kfree(fm);
346 sb->s_fs_info = NULL;
Max Reitzbf109c62020-04-21 14:47:15 +0200347 goto out_put_sb;
Greg Kurz91c2aa22021-06-04 18:11:50 +0200348 }
Max Reitzbf109c62020-04-21 14:47:15 +0200349
350 down_write(&fc->killsb);
351 list_add_tail(&fm->fc_entry, &fc->mounts);
352 up_write(&fc->killsb);
353
Max Reitzbf109c62020-04-21 14:47:15 +0200354 sb->s_flags |= SB_ACTIVE;
355 fsc->root = dget(sb->s_root);
Greg Kurz576b44c2021-06-04 18:11:52 +0200356
357 /*
358 * FIXME: setting SB_BORN requires a write barrier for
359 * super_cache_count(). We should actually come
360 * up with a proper ->get_tree() implementation
361 * for submounts and call vfs_get_tree() to take
362 * care of the write barrier.
363 */
364 smp_wmb();
365 sb->s_flags |= SB_BORN;
366
Max Reitzbf109c62020-04-21 14:47:15 +0200367 /* We are done configuring the superblock, so unlock it */
368 up_write(&sb->s_umount);
369
Max Reitzbf109c62020-04-21 14:47:15 +0200370 /* Create the submount */
371 mnt = vfs_create_mount(fsc);
372 if (IS_ERR(mnt)) {
373 err = PTR_ERR(mnt);
374 goto out_put_fsc;
375 }
376 mntget(mnt);
377 put_fs_context(fsc);
378 return mnt;
379
380out_put_sb:
381 /*
382 * Only jump here when fsc->root is NULL and sb is still locked
383 * (otherwise put_fs_context() will put the superblock)
384 */
385 deactivate_locked_super(sb);
386out_put_fsc:
387 put_fs_context(fsc);
388out:
389 return ERR_PTR(err);
390}
391
Daniel Rosenbergaca26512016-04-22 00:00:48 -0700392/*
393 * Get the canonical path. Since we must translate to a path, this must be done
394 * in the context of the userspace daemon, however, the userspace daemon cannot
395 * look up paths on its own. Instead, we handle the lookup as a special case
396 * inside of the write request.
397 */
398static void fuse_dentry_canonical_path(const struct path *path,
399 struct path *canonical_path)
400{
401 struct inode *inode = d_inode(path->dentry);
402 //struct fuse_conn *fc = get_fuse_conn(inode);
403 struct fuse_mount *fm = get_fuse_mount_super(path->mnt->mnt_sb);
404 FUSE_ARGS(args);
405 char *path_name;
406 int err;
407
408 path_name = (char *)__get_free_page(GFP_KERNEL);
409 if (!path_name)
410 goto default_path;
411
412 args.opcode = FUSE_CANONICAL_PATH;
413 args.nodeid = get_node_id(inode);
414 args.in_numargs = 0;
415 args.out_numargs = 1;
416 args.out_args[0].size = PATH_MAX;
417 args.out_args[0].value = path_name;
418 args.canonical_path = canonical_path;
419 args.out_argvar = 1;
420
421 err = fuse_simple_request(fm, &args);
422 free_page((unsigned long)path_name);
423 if (err > 0)
424 return;
425default_path:
426 canonical_path->dentry = path->dentry;
427 canonical_path->mnt = path->mnt;
428 path_get(canonical_path);
429}
430
Al Viro42695902009-02-20 05:59:13 +0000431const struct dentry_operations fuse_dentry_operations = {
Miklos Szeredie5e55582005-09-09 13:10:28 -0700432 .d_revalidate = fuse_dentry_revalidate,
Miklos Szeredi8fab0102018-08-15 17:42:34 +0200433 .d_delete = fuse_dentry_delete,
Khazhismel Kumykov30c6a232019-09-16 16:56:41 -0700434#if BITS_PER_LONG < 64
Miklos Szeredif75fdf22016-10-01 07:32:32 +0200435 .d_init = fuse_dentry_init,
436 .d_release = fuse_dentry_release,
Khazhismel Kumykov30c6a232019-09-16 16:56:41 -0700437#endif
Max Reitzbf109c62020-04-21 14:47:15 +0200438 .d_automount = fuse_dentry_automount,
Daniel Rosenbergaca26512016-04-22 00:00:48 -0700439 .d_canonical_path = fuse_dentry_canonical_path,
Miklos Szeredie5e55582005-09-09 13:10:28 -0700440};
441
Miklos Szeredi0ce267f2016-10-18 15:36:48 +0200442const struct dentry_operations fuse_root_dentry_operations = {
Khazhismel Kumykov30c6a232019-09-16 16:56:41 -0700443#if BITS_PER_LONG < 64
Miklos Szeredi0ce267f2016-10-18 15:36:48 +0200444 .d_init = fuse_dentry_init,
445 .d_release = fuse_dentry_release,
Khazhismel Kumykov30c6a232019-09-16 16:56:41 -0700446#endif
Miklos Szeredi0ce267f2016-10-18 15:36:48 +0200447};
448
Timo Savolaa5bfffac2007-04-08 16:04:00 -0700449int fuse_valid_type(int m)
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800450{
451 return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) ||
452 S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m);
453}
454
Miklos Szeredieb59bd12019-11-12 11:49:04 +0100455bool fuse_invalid_attr(struct fuse_attr *attr)
456{
457 return !fuse_valid_type(attr->mode) ||
458 attr->size > LLONG_MAX;
459}
460
Al Viro13983d02016-07-20 22:34:44 -0400461int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name,
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700462 struct fuse_entry_out *outarg, struct inode **inode)
463{
Max Reitzfcee2162020-05-06 17:44:12 +0200464 struct fuse_mount *fm = get_fuse_mount_super(sb);
Miklos Szeredi70781872014-12-12 09:49:05 +0100465 FUSE_ARGS(args);
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100466 struct fuse_forget_link *forget;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700467 u64 attr_version;
468 int err;
469
470 *inode = NULL;
471 err = -ENAMETOOLONG;
472 if (name->len > FUSE_NAME_MAX)
473 goto out;
474
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700475
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100476 forget = fuse_alloc_forget();
477 err = -ENOMEM;
Miklos Szeredi70781872014-12-12 09:49:05 +0100478 if (!forget)
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700479 goto out;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700480
Max Reitzfcee2162020-05-06 17:44:12 +0200481 attr_version = fuse_get_attr_version(fm->fc);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700482
Max Reitzfcee2162020-05-06 17:44:12 +0200483 fuse_lookup_init(fm->fc, &args, nodeid, name, outarg);
484 err = fuse_simple_request(fm, &args);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700485 /* Zero nodeid is same as -ENOENT, but with valid timeout */
486 if (err || !outarg->nodeid)
487 goto out_put_forget;
488
489 err = -EIO;
490 if (!outarg->nodeid)
491 goto out_put_forget;
Miklos Szeredieb59bd12019-11-12 11:49:04 +0100492 if (fuse_invalid_attr(&outarg->attr))
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700493 goto out_put_forget;
494
495 *inode = fuse_iget(sb, outarg->nodeid, outarg->generation,
496 &outarg->attr, entry_attr_timeout(outarg),
497 attr_version);
498 err = -ENOMEM;
499 if (!*inode) {
Max Reitzfcee2162020-05-06 17:44:12 +0200500 fuse_queue_forget(fm->fc, forget, outarg->nodeid, 1);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700501 goto out;
502 }
503 err = 0;
504
505 out_put_forget:
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100506 kfree(forget);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700507 out:
508 return err;
509}
510
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800511static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
Al Viro00cd8dd2012-06-10 17:13:09 -0400512 unsigned int flags)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700513{
514 int err;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700515 struct fuse_entry_out outarg;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700516 struct inode *inode;
Miklos Szeredi0de62562008-07-25 01:48:59 -0700517 struct dentry *newent;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700518 bool outarg_valid = true;
Miklos Szeredi63576c12018-07-26 16:13:11 +0200519 bool locked;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700520
Miklos Szeredi36cf9ae2020-12-10 15:33:14 +0100521 if (fuse_is_bad(dir))
522 return ERR_PTR(-EIO);
523
Miklos Szeredi63576c12018-07-26 16:13:11 +0200524 locked = fuse_lock_inode(dir);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700525 err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name,
526 &outarg, &inode);
Miklos Szeredi63576c12018-07-26 16:13:11 +0200527 fuse_unlock_inode(dir, locked);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700528 if (err == -ENOENT) {
529 outarg_valid = false;
530 err = 0;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800531 }
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700532 if (err)
533 goto out_err;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800534
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700535 err = -EIO;
536 if (inode && get_node_id(inode) == FUSE_ROOT_ID)
537 goto out_iput;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700538
Al Viro41d28bc2014-10-12 22:24:21 -0400539 newent = d_splice_alias(inode, entry);
Miklos Szeredi5835f332013-09-05 11:44:42 +0200540 err = PTR_ERR(newent);
541 if (IS_ERR(newent))
542 goto out_err;
Miklos Szeredid2a85162006-10-17 00:10:11 -0700543
Miklos Szeredi0de62562008-07-25 01:48:59 -0700544 entry = newent ? newent : entry;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700545 if (outarg_valid)
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700546 fuse_change_entry_timeout(entry, &outarg);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800547 else
548 fuse_invalidate_entry_cache(entry);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700549
Miklos Szeredi6c26f712019-10-21 15:57:07 +0200550 if (inode)
551 fuse_advise_use_readdirplus(dir);
Miklos Szeredi0de62562008-07-25 01:48:59 -0700552 return newent;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700553
554 out_iput:
555 iput(inode);
556 out_err:
557 return ERR_PTR(err);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700558}
559
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800560/*
561 * Atomic create+open operation
562 *
563 * If the filesystem doesn't support this, then fall back to separate
564 * 'mknod' + 'open' requests.
565 */
Al Virod9585272012-06-22 12:39:14 +0400566static int fuse_create_open(struct inode *dir, struct dentry *entry,
Al Viro30d90492012-06-22 12:40:19 +0400567 struct file *file, unsigned flags,
Al Virob452a452018-06-08 13:06:28 -0400568 umode_t mode)
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800569{
570 int err;
571 struct inode *inode;
Alessio Balsini9634f0e2021-01-25 17:02:28 +0000572 struct fuse_conn *fc = get_fuse_conn(dir);
Max Reitzfcee2162020-05-06 17:44:12 +0200573 struct fuse_mount *fm = get_fuse_mount(dir);
Miklos Szeredi70781872014-12-12 09:49:05 +0100574 FUSE_ARGS(args);
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100575 struct fuse_forget_link *forget;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200576 struct fuse_create_in inarg;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800577 struct fuse_open_out outopen;
578 struct fuse_entry_out outentry;
Kirill Tkhaiebf84d02018-11-09 13:33:11 +0300579 struct fuse_inode *fi;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800580 struct fuse_file *ff;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800581
Miklos Szerediaf109bc2012-08-15 13:01:24 +0200582 /* Userspace expects S_IFREG in create mode */
583 BUG_ON((mode & S_IFMT) != S_IFREG);
584
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100585 forget = fuse_alloc_forget();
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200586 err = -ENOMEM;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100587 if (!forget)
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200588 goto out_err;
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700589
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700590 err = -ENOMEM;
Max Reitzfcee2162020-05-06 17:44:12 +0200591 ff = fuse_file_alloc(fm);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800592 if (!ff)
Miklos Szeredi70781872014-12-12 09:49:05 +0100593 goto out_put_forget_req;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800594
Max Reitzfcee2162020-05-06 17:44:12 +0200595 if (!fm->fc->dont_mask)
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200596 mode &= ~current_umask();
597
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800598 flags &= ~O_NOCTTY;
599 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700600 memset(&outentry, 0, sizeof(outentry));
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800601 inarg.flags = flags;
602 inarg.mode = mode;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200603 inarg.umask = current_umask();
Miklos Szeredid5b48542019-09-10 15:04:08 +0200604 args.opcode = FUSE_CREATE;
605 args.nodeid = get_node_id(dir);
606 args.in_numargs = 2;
607 args.in_args[0].size = sizeof(inarg);
608 args.in_args[0].value = &inarg;
609 args.in_args[1].size = entry->d_name.len + 1;
610 args.in_args[1].value = entry->d_name.name;
611 args.out_numargs = 2;
612 args.out_args[0].size = sizeof(outentry);
613 args.out_args[0].value = &outentry;
614 args.out_args[1].size = sizeof(outopen);
615 args.out_args[1].value = &outopen;
Max Reitzfcee2162020-05-06 17:44:12 +0200616 err = fuse_simple_request(fm, &args);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200617 if (err)
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800618 goto out_free_ff;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800619
620 err = -EIO;
Miklos Szeredieb59bd12019-11-12 11:49:04 +0100621 if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid) ||
622 fuse_invalid_attr(&outentry.attr))
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800623 goto out_free_ff;
624
Miklos Szeredic7b71432009-04-28 16:56:37 +0200625 ff->fh = outopen.fh;
626 ff->nodeid = outentry.nodeid;
627 ff->open_flags = outopen.open_flags;
Alessio Balsini9634f0e2021-01-25 17:02:28 +0000628 fuse_passthrough_setup(fc, ff, &outopen);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800629 inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700630 &outentry.attr, entry_attr_timeout(&outentry), 0);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800631 if (!inode) {
632 flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
Kirill Tkhaiebf84d02018-11-09 13:33:11 +0300633 fuse_sync_release(NULL, ff, flags);
Max Reitzfcee2162020-05-06 17:44:12 +0200634 fuse_queue_forget(fm->fc, forget, outentry.nodeid, 1);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200635 err = -ENOMEM;
636 goto out_err;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800637 }
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100638 kfree(forget);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800639 d_instantiate(entry, inode);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700640 fuse_change_entry_timeout(entry, &outentry);
Miklos Szeredi261aaba72018-10-01 10:07:05 +0200641 fuse_dir_changed(dir);
Al Virobe12af32018-06-08 11:44:56 -0400642 err = finish_open(file, entry, generic_file_open);
Al Viro30d90492012-06-22 12:40:19 +0400643 if (err) {
Kirill Tkhaiebf84d02018-11-09 13:33:11 +0300644 fi = get_fuse_inode(inode);
645 fuse_sync_release(fi, ff, flags);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200646 } else {
Miklos Szeredi267d8442017-02-22 20:08:25 +0100647 file->private_data = ff;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200648 fuse_finish_open(inode, file);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800649 }
Al Virod9585272012-06-22 12:39:14 +0400650 return err;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800651
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200652out_free_ff:
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800653 fuse_file_free(ff);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200654out_put_forget_req:
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100655 kfree(forget);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200656out_err:
Al Virod9585272012-06-22 12:39:14 +0400657 return err;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200658}
659
660static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t);
Al Virod9585272012-06-22 12:39:14 +0400661static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
Al Viro30d90492012-06-22 12:40:19 +0400662 struct file *file, unsigned flags,
Al Viro44907d72018-06-08 13:32:02 -0400663 umode_t mode)
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200664{
665 int err;
666 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200667 struct dentry *res = NULL;
668
Miklos Szeredi36cf9ae2020-12-10 15:33:14 +0100669 if (fuse_is_bad(dir))
670 return -EIO;
671
Al Viro00699ad2016-07-05 09:44:53 -0400672 if (d_in_lookup(entry)) {
Al Viro00cd8dd2012-06-10 17:13:09 -0400673 res = fuse_lookup(dir, entry, 0);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200674 if (IS_ERR(res))
Al Virod9585272012-06-22 12:39:14 +0400675 return PTR_ERR(res);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200676
677 if (res)
678 entry = res;
679 }
680
David Howells2b0143b2015-03-17 22:25:59 +0000681 if (!(flags & O_CREAT) || d_really_is_positive(entry))
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200682 goto no_open;
683
684 /* Only creates */
Al Viro73a09dd2018-06-08 13:22:02 -0400685 file->f_mode |= FMODE_CREATED;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200686
687 if (fc->no_create)
688 goto mknod;
689
Al Virob452a452018-06-08 13:06:28 -0400690 err = fuse_create_open(dir, entry, file, flags, mode);
Al Virod9585272012-06-22 12:39:14 +0400691 if (err == -ENOSYS) {
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200692 fc->no_create = 1;
693 goto mknod;
694 }
695out_dput:
696 dput(res);
Al Virod9585272012-06-22 12:39:14 +0400697 return err;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200698
699mknod:
700 err = fuse_mknod(dir, entry, mode, 0);
Al Virod9585272012-06-22 12:39:14 +0400701 if (err)
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200702 goto out_dput;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200703no_open:
Al Viroe45198a2012-06-10 06:48:09 -0400704 return finish_no_open(file, res);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800705}
706
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800707/*
708 * Code shared between mknod, mkdir, symlink and link
709 */
Max Reitzfcee2162020-05-06 17:44:12 +0200710static int create_new_entry(struct fuse_mount *fm, struct fuse_args *args,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700711 struct inode *dir, struct dentry *entry,
Al Viro541af6a2011-07-26 03:17:33 -0400712 umode_t mode)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700713{
714 struct fuse_entry_out outarg;
715 struct inode *inode;
Al Viroc971e6a02018-05-28 18:27:19 -0400716 struct dentry *d;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700717 int err;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100718 struct fuse_forget_link *forget;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800719
Miklos Szeredi36cf9ae2020-12-10 15:33:14 +0100720 if (fuse_is_bad(dir))
721 return -EIO;
722
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100723 forget = fuse_alloc_forget();
Miklos Szeredi70781872014-12-12 09:49:05 +0100724 if (!forget)
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100725 return -ENOMEM;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700726
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700727 memset(&outarg, 0, sizeof(outarg));
Miklos Szeredid5b48542019-09-10 15:04:08 +0200728 args->nodeid = get_node_id(dir);
729 args->out_numargs = 1;
730 args->out_args[0].size = sizeof(outarg);
731 args->out_args[0].value = &outarg;
Max Reitzfcee2162020-05-06 17:44:12 +0200732 err = fuse_simple_request(fm, args);
Miklos Szeredi2d510132006-11-25 11:09:20 -0800733 if (err)
734 goto out_put_forget_req;
735
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800736 err = -EIO;
Miklos Szeredieb59bd12019-11-12 11:49:04 +0100737 if (invalid_nodeid(outarg.nodeid) || fuse_invalid_attr(&outarg.attr))
Miklos Szeredi2d510132006-11-25 11:09:20 -0800738 goto out_put_forget_req;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800739
740 if ((outarg.attr.mode ^ mode) & S_IFMT)
Miklos Szeredi2d510132006-11-25 11:09:20 -0800741 goto out_put_forget_req;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800742
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700743 inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700744 &outarg.attr, entry_attr_timeout(&outarg), 0);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700745 if (!inode) {
Max Reitzfcee2162020-05-06 17:44:12 +0200746 fuse_queue_forget(fm->fc, forget, outarg.nodeid, 1);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700747 return -ENOMEM;
748 }
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100749 kfree(forget);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700750
Al Viroc971e6a02018-05-28 18:27:19 -0400751 d_drop(entry);
752 d = d_splice_alias(inode, entry);
753 if (IS_ERR(d))
754 return PTR_ERR(d);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700755
Al Viroc971e6a02018-05-28 18:27:19 -0400756 if (d) {
757 fuse_change_entry_timeout(d, &outarg);
758 dput(d);
759 } else {
760 fuse_change_entry_timeout(entry, &outarg);
761 }
Miklos Szeredi261aaba72018-10-01 10:07:05 +0200762 fuse_dir_changed(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700763 return 0;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800764
Miklos Szeredi2d510132006-11-25 11:09:20 -0800765 out_put_forget_req:
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100766 kfree(forget);
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800767 return err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700768}
769
Al Viro1a67aaf2011-07-26 01:52:52 -0400770static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700771 dev_t rdev)
772{
773 struct fuse_mknod_in inarg;
Max Reitzfcee2162020-05-06 17:44:12 +0200774 struct fuse_mount *fm = get_fuse_mount(dir);
Miklos Szeredi70781872014-12-12 09:49:05 +0100775 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700776
Max Reitzfcee2162020-05-06 17:44:12 +0200777 if (!fm->fc->dont_mask)
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200778 mode &= ~current_umask();
779
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700780 memset(&inarg, 0, sizeof(inarg));
781 inarg.mode = mode;
782 inarg.rdev = new_encode_dev(rdev);
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200783 inarg.umask = current_umask();
Miklos Szeredid5b48542019-09-10 15:04:08 +0200784 args.opcode = FUSE_MKNOD;
785 args.in_numargs = 2;
786 args.in_args[0].size = sizeof(inarg);
787 args.in_args[0].value = &inarg;
788 args.in_args[1].size = entry->d_name.len + 1;
789 args.in_args[1].value = entry->d_name.name;
Max Reitzfcee2162020-05-06 17:44:12 +0200790 return create_new_entry(fm, &args, dir, entry, mode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700791}
792
Al Viro4acdaf22011-07-26 01:42:34 -0400793static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode,
Al Viroebfc3b42012-06-10 18:05:36 -0400794 bool excl)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700795{
796 return fuse_mknod(dir, entry, mode, 0);
797}
798
Al Viro18bb1db2011-07-26 01:41:39 -0400799static int fuse_mkdir(struct inode *dir, struct dentry *entry, umode_t mode)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700800{
801 struct fuse_mkdir_in inarg;
Max Reitzfcee2162020-05-06 17:44:12 +0200802 struct fuse_mount *fm = get_fuse_mount(dir);
Miklos Szeredi70781872014-12-12 09:49:05 +0100803 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700804
Max Reitzfcee2162020-05-06 17:44:12 +0200805 if (!fm->fc->dont_mask)
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200806 mode &= ~current_umask();
807
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700808 memset(&inarg, 0, sizeof(inarg));
809 inarg.mode = mode;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200810 inarg.umask = current_umask();
Miklos Szeredid5b48542019-09-10 15:04:08 +0200811 args.opcode = FUSE_MKDIR;
812 args.in_numargs = 2;
813 args.in_args[0].size = sizeof(inarg);
814 args.in_args[0].value = &inarg;
815 args.in_args[1].size = entry->d_name.len + 1;
816 args.in_args[1].value = entry->d_name.name;
Max Reitzfcee2162020-05-06 17:44:12 +0200817 return create_new_entry(fm, &args, dir, entry, S_IFDIR);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700818}
819
820static int fuse_symlink(struct inode *dir, struct dentry *entry,
821 const char *link)
822{
Max Reitzfcee2162020-05-06 17:44:12 +0200823 struct fuse_mount *fm = get_fuse_mount(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700824 unsigned len = strlen(link) + 1;
Miklos Szeredi70781872014-12-12 09:49:05 +0100825 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700826
Miklos Szeredid5b48542019-09-10 15:04:08 +0200827 args.opcode = FUSE_SYMLINK;
828 args.in_numargs = 2;
829 args.in_args[0].size = entry->d_name.len + 1;
830 args.in_args[0].value = entry->d_name.name;
831 args.in_args[1].size = len;
832 args.in_args[1].value = link;
Max Reitzfcee2162020-05-06 17:44:12 +0200833 return create_new_entry(fm, &args, dir, entry, S_IFLNK);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700834}
835
Seth Forshee703c7362016-08-29 08:46:36 -0500836void fuse_update_ctime(struct inode *inode)
Maxim Patlasov31f32672014-04-28 14:19:24 +0200837{
838 if (!IS_NOCMTIME(inode)) {
Deepa Dinamanic2050a42016-09-14 07:48:06 -0700839 inode->i_ctime = current_time(inode);
Maxim Patlasov31f32672014-04-28 14:19:24 +0200840 mark_inode_dirty_sync(inode);
841 }
842}
843
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700844static int fuse_unlink(struct inode *dir, struct dentry *entry)
845{
846 int err;
Max Reitzfcee2162020-05-06 17:44:12 +0200847 struct fuse_mount *fm = get_fuse_mount(dir);
Miklos Szeredi70781872014-12-12 09:49:05 +0100848 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700849
Miklos Szeredi36cf9ae2020-12-10 15:33:14 +0100850 if (fuse_is_bad(dir))
851 return -EIO;
852
Miklos Szeredid5b48542019-09-10 15:04:08 +0200853 args.opcode = FUSE_UNLINK;
854 args.nodeid = get_node_id(dir);
855 args.in_numargs = 1;
856 args.in_args[0].size = entry->d_name.len + 1;
857 args.in_args[0].value = entry->d_name.name;
Max Reitzfcee2162020-05-06 17:44:12 +0200858 err = fuse_simple_request(fm, &args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700859 if (!err) {
David Howells2b0143b2015-03-17 22:25:59 +0000860 struct inode *inode = d_inode(entry);
Miklos Szerediac45d612012-03-05 15:48:11 +0100861 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700862
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +0300863 spin_lock(&fi->lock);
Max Reitzfcee2162020-05-06 17:44:12 +0200864 fi->attr_version = atomic64_inc_return(&fm->fc->attr_version);
Miklos Szeredidfca7ce2013-02-04 15:57:42 +0100865 /*
866 * If i_nlink == 0 then unlink doesn't make sense, yet this can
867 * happen if userspace filesystem is careless. It would be
868 * difficult to enforce correct nlink usage so just ignore this
869 * condition here
870 */
871 if (inode->i_nlink > 0)
872 drop_nlink(inode);
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +0300873 spin_unlock(&fi->lock);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700874 fuse_invalidate_attr(inode);
Miklos Szeredi261aaba72018-10-01 10:07:05 +0200875 fuse_dir_changed(dir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800876 fuse_invalidate_entry_cache(entry);
Maxim Patlasov31f32672014-04-28 14:19:24 +0200877 fuse_update_ctime(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700878 } else if (err == -EINTR)
879 fuse_invalidate_entry(entry);
880 return err;
881}
882
883static int fuse_rmdir(struct inode *dir, struct dentry *entry)
884{
885 int err;
Max Reitzfcee2162020-05-06 17:44:12 +0200886 struct fuse_mount *fm = get_fuse_mount(dir);
Miklos Szeredi70781872014-12-12 09:49:05 +0100887 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700888
Miklos Szeredi36cf9ae2020-12-10 15:33:14 +0100889 if (fuse_is_bad(dir))
890 return -EIO;
891
Miklos Szeredid5b48542019-09-10 15:04:08 +0200892 args.opcode = FUSE_RMDIR;
893 args.nodeid = get_node_id(dir);
894 args.in_numargs = 1;
895 args.in_args[0].size = entry->d_name.len + 1;
896 args.in_args[0].value = entry->d_name.name;
Max Reitzfcee2162020-05-06 17:44:12 +0200897 err = fuse_simple_request(fm, &args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700898 if (!err) {
David Howells2b0143b2015-03-17 22:25:59 +0000899 clear_nlink(d_inode(entry));
Miklos Szeredi261aaba72018-10-01 10:07:05 +0200900 fuse_dir_changed(dir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800901 fuse_invalidate_entry_cache(entry);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700902 } else if (err == -EINTR)
903 fuse_invalidate_entry(entry);
904 return err;
905}
906
Miklos Szeredi1560c972014-04-28 16:43:44 +0200907static int fuse_rename_common(struct inode *olddir, struct dentry *oldent,
908 struct inode *newdir, struct dentry *newent,
909 unsigned int flags, int opcode, size_t argsize)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700910{
911 int err;
Miklos Szeredi1560c972014-04-28 16:43:44 +0200912 struct fuse_rename2_in inarg;
Max Reitzfcee2162020-05-06 17:44:12 +0200913 struct fuse_mount *fm = get_fuse_mount(olddir);
Miklos Szeredi70781872014-12-12 09:49:05 +0100914 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700915
Miklos Szeredi1560c972014-04-28 16:43:44 +0200916 memset(&inarg, 0, argsize);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700917 inarg.newdir = get_node_id(newdir);
Miklos Szeredi1560c972014-04-28 16:43:44 +0200918 inarg.flags = flags;
Miklos Szeredid5b48542019-09-10 15:04:08 +0200919 args.opcode = opcode;
920 args.nodeid = get_node_id(olddir);
921 args.in_numargs = 3;
922 args.in_args[0].size = argsize;
923 args.in_args[0].value = &inarg;
924 args.in_args[1].size = oldent->d_name.len + 1;
925 args.in_args[1].value = oldent->d_name.name;
926 args.in_args[2].size = newent->d_name.len + 1;
927 args.in_args[2].value = newent->d_name.name;
Max Reitzfcee2162020-05-06 17:44:12 +0200928 err = fuse_simple_request(fm, &args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700929 if (!err) {
Miklos Szeredi08b63302007-11-28 16:22:03 -0800930 /* ctime changes */
David Howells2b0143b2015-03-17 22:25:59 +0000931 fuse_invalidate_attr(d_inode(oldent));
932 fuse_update_ctime(d_inode(oldent));
Miklos Szeredi08b63302007-11-28 16:22:03 -0800933
Miklos Szeredi1560c972014-04-28 16:43:44 +0200934 if (flags & RENAME_EXCHANGE) {
David Howells2b0143b2015-03-17 22:25:59 +0000935 fuse_invalidate_attr(d_inode(newent));
936 fuse_update_ctime(d_inode(newent));
Miklos Szeredi1560c972014-04-28 16:43:44 +0200937 }
938
Miklos Szeredi261aaba72018-10-01 10:07:05 +0200939 fuse_dir_changed(olddir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700940 if (olddir != newdir)
Miklos Szeredi261aaba72018-10-01 10:07:05 +0200941 fuse_dir_changed(newdir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800942
943 /* newent will end up negative */
David Howells2b0143b2015-03-17 22:25:59 +0000944 if (!(flags & RENAME_EXCHANGE) && d_really_is_positive(newent)) {
945 fuse_invalidate_attr(d_inode(newent));
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800946 fuse_invalidate_entry_cache(newent);
David Howells2b0143b2015-03-17 22:25:59 +0000947 fuse_update_ctime(d_inode(newent));
Miklos Szeredi5219f342009-11-04 10:24:52 +0100948 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700949 } else if (err == -EINTR) {
950 /* If request was interrupted, DEITY only knows if the
951 rename actually took place. If the invalidation
952 fails (e.g. some process has CWD under the renamed
953 directory), then there can be inconsistency between
954 the dcache and the real filesystem. Tough luck. */
955 fuse_invalidate_entry(oldent);
David Howells2b0143b2015-03-17 22:25:59 +0000956 if (d_really_is_positive(newent))
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700957 fuse_invalidate_entry(newent);
958 }
959
960 return err;
961}
962
Miklos Szeredi1560c972014-04-28 16:43:44 +0200963static int fuse_rename2(struct inode *olddir, struct dentry *oldent,
964 struct inode *newdir, struct dentry *newent,
965 unsigned int flags)
966{
967 struct fuse_conn *fc = get_fuse_conn(olddir);
968 int err;
969
Miklos Szeredi36cf9ae2020-12-10 15:33:14 +0100970 if (fuse_is_bad(olddir))
971 return -EIO;
972
Vivek Goyal519525f2020-02-05 08:15:46 -0500973 if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT))
Miklos Szeredi1560c972014-04-28 16:43:44 +0200974 return -EINVAL;
975
Miklos Szeredi4237ba42014-07-10 10:50:19 +0200976 if (flags) {
977 if (fc->no_rename2 || fc->minor < 23)
978 return -EINVAL;
Miklos Szeredi1560c972014-04-28 16:43:44 +0200979
Miklos Szeredi4237ba42014-07-10 10:50:19 +0200980 err = fuse_rename_common(olddir, oldent, newdir, newent, flags,
981 FUSE_RENAME2,
982 sizeof(struct fuse_rename2_in));
983 if (err == -ENOSYS) {
984 fc->no_rename2 = 1;
985 err = -EINVAL;
986 }
987 } else {
988 err = fuse_rename_common(olddir, oldent, newdir, newent, 0,
989 FUSE_RENAME,
990 sizeof(struct fuse_rename_in));
Miklos Szeredi1560c972014-04-28 16:43:44 +0200991 }
Miklos Szeredi1560c972014-04-28 16:43:44 +0200992
Miklos Szeredi4237ba42014-07-10 10:50:19 +0200993 return err;
994}
995
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700996static int fuse_link(struct dentry *entry, struct inode *newdir,
997 struct dentry *newent)
998{
999 int err;
1000 struct fuse_link_in inarg;
David Howells2b0143b2015-03-17 22:25:59 +00001001 struct inode *inode = d_inode(entry);
Max Reitzfcee2162020-05-06 17:44:12 +02001002 struct fuse_mount *fm = get_fuse_mount(inode);
Miklos Szeredi70781872014-12-12 09:49:05 +01001003 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001004
1005 memset(&inarg, 0, sizeof(inarg));
1006 inarg.oldnodeid = get_node_id(inode);
Miklos Szeredid5b48542019-09-10 15:04:08 +02001007 args.opcode = FUSE_LINK;
1008 args.in_numargs = 2;
1009 args.in_args[0].size = sizeof(inarg);
1010 args.in_args[0].value = &inarg;
1011 args.in_args[1].size = newent->d_name.len + 1;
1012 args.in_args[1].value = newent->d_name.name;
Max Reitzfcee2162020-05-06 17:44:12 +02001013 err = create_new_entry(fm, &args, newdir, newent, inode->i_mode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001014 /* Contrary to "normal" filesystems it can happen that link
1015 makes two "logical" inodes point to the same "physical"
1016 inode. We invalidate the attributes of the old one, so it
1017 will reflect changes in the backing inode (link count,
1018 etc.)
1019 */
Miklos Szerediac45d612012-03-05 15:48:11 +01001020 if (!err) {
1021 struct fuse_inode *fi = get_fuse_inode(inode);
1022
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +03001023 spin_lock(&fi->lock);
Max Reitzfcee2162020-05-06 17:44:12 +02001024 fi->attr_version = atomic64_inc_return(&fm->fc->attr_version);
Miklos Szeredic634da72019-11-12 11:49:04 +01001025 if (likely(inode->i_nlink < UINT_MAX))
1026 inc_nlink(inode);
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +03001027 spin_unlock(&fi->lock);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001028 fuse_invalidate_attr(inode);
Maxim Patlasov31f32672014-04-28 14:19:24 +02001029 fuse_update_ctime(inode);
Miklos Szerediac45d612012-03-05 15:48:11 +01001030 } else if (err == -EINTR) {
1031 fuse_invalidate_attr(inode);
1032 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001033 return err;
1034}
1035
Miklos Szeredi1fb69e72007-10-18 03:06:58 -07001036static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
1037 struct kstat *stat)
1038{
Miklos Szeredi203627b2012-05-10 19:49:38 +04001039 unsigned int blkbits;
Pavel Emelyanov83732002013-10-10 17:10:46 +04001040 struct fuse_conn *fc = get_fuse_conn(inode);
1041
1042 /* see the comment in fuse_change_attributes() */
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001043 if (fc->writeback_cache && S_ISREG(inode->i_mode)) {
Pavel Emelyanov83732002013-10-10 17:10:46 +04001044 attr->size = i_size_read(inode);
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001045 attr->mtime = inode->i_mtime.tv_sec;
1046 attr->mtimensec = inode->i_mtime.tv_nsec;
Maxim Patlasov31f32672014-04-28 14:19:24 +02001047 attr->ctime = inode->i_ctime.tv_sec;
1048 attr->ctimensec = inode->i_ctime.tv_nsec;
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001049 }
Miklos Szeredi203627b2012-05-10 19:49:38 +04001050
Miklos Szeredi1fb69e72007-10-18 03:06:58 -07001051 stat->dev = inode->i_sb->s_dev;
1052 stat->ino = attr->ino;
1053 stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
1054 stat->nlink = attr->nlink;
Eric W. Biederman8cb08322018-02-21 11:18:07 -06001055 stat->uid = make_kuid(fc->user_ns, attr->uid);
1056 stat->gid = make_kgid(fc->user_ns, attr->gid);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -07001057 stat->rdev = inode->i_rdev;
1058 stat->atime.tv_sec = attr->atime;
1059 stat->atime.tv_nsec = attr->atimensec;
1060 stat->mtime.tv_sec = attr->mtime;
1061 stat->mtime.tv_nsec = attr->mtimensec;
1062 stat->ctime.tv_sec = attr->ctime;
1063 stat->ctime.tv_nsec = attr->ctimensec;
1064 stat->size = attr->size;
1065 stat->blocks = attr->blocks;
Miklos Szeredi203627b2012-05-10 19:49:38 +04001066
1067 if (attr->blksize != 0)
1068 blkbits = ilog2(attr->blksize);
1069 else
1070 blkbits = inode->i_sb->s_blocksize_bits;
1071
1072 stat->blksize = 1 << blkbits;
Miklos Szeredi1fb69e72007-10-18 03:06:58 -07001073}
1074
Miklos Szeredic79e3222007-10-18 03:06:59 -07001075static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
1076 struct file *file)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001077{
1078 int err;
Miklos Szeredic79e3222007-10-18 03:06:59 -07001079 struct fuse_getattr_in inarg;
1080 struct fuse_attr_out outarg;
Max Reitzfcee2162020-05-06 17:44:12 +02001081 struct fuse_mount *fm = get_fuse_mount(inode);
Miklos Szeredi70781872014-12-12 09:49:05 +01001082 FUSE_ARGS(args);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -07001083 u64 attr_version;
1084
Max Reitzfcee2162020-05-06 17:44:12 +02001085 attr_version = fuse_get_attr_version(fm->fc);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -07001086
Miklos Szeredic79e3222007-10-18 03:06:59 -07001087 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -07001088 memset(&outarg, 0, sizeof(outarg));
Miklos Szeredic79e3222007-10-18 03:06:59 -07001089 /* Directories have separate file-handle space */
1090 if (file && S_ISREG(inode->i_mode)) {
1091 struct fuse_file *ff = file->private_data;
1092
1093 inarg.getattr_flags |= FUSE_GETATTR_FH;
1094 inarg.fh = ff->fh;
1095 }
Miklos Szeredid5b48542019-09-10 15:04:08 +02001096 args.opcode = FUSE_GETATTR;
1097 args.nodeid = get_node_id(inode);
1098 args.in_numargs = 1;
1099 args.in_args[0].size = sizeof(inarg);
1100 args.in_args[0].value = &inarg;
1101 args.out_numargs = 1;
1102 args.out_args[0].size = sizeof(outarg);
1103 args.out_args[0].value = &outarg;
Max Reitzfcee2162020-05-06 17:44:12 +02001104 err = fuse_simple_request(fm, &args);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001105 if (!err) {
Miklos Szeredieb59bd12019-11-12 11:49:04 +01001106 if (fuse_invalid_attr(&outarg.attr) ||
1107 (inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
Miklos Szeredi36cf9ae2020-12-10 15:33:14 +01001108 fuse_make_bad(inode);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001109 err = -EIO;
1110 } else {
Miklos Szeredic79e3222007-10-18 03:06:59 -07001111 fuse_change_attributes(inode, &outarg.attr,
1112 attr_timeout(&outarg),
Miklos Szeredi1fb69e72007-10-18 03:06:58 -07001113 attr_version);
1114 if (stat)
Miklos Szeredic79e3222007-10-18 03:06:59 -07001115 fuse_fillattr(inode, &outarg.attr, stat);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001116 }
1117 }
1118 return err;
1119}
1120
Miklos Szeredi5b97eea2017-09-12 16:57:54 +02001121static int fuse_update_get_attr(struct inode *inode, struct file *file,
Miklos Szeredi2f1e8192018-10-15 15:43:06 +02001122 struct kstat *stat, u32 request_mask,
1123 unsigned int flags)
Miklos Szeredibcb4be82007-11-28 16:21:59 -08001124{
1125 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredi5b97eea2017-09-12 16:57:54 +02001126 int err = 0;
Miklos Szeredibf5c1892018-03-20 17:11:44 +01001127 bool sync;
Miklos Szeredibcb4be82007-11-28 16:21:59 -08001128
Miklos Szeredibf5c1892018-03-20 17:11:44 +01001129 if (flags & AT_STATX_FORCE_SYNC)
1130 sync = true;
1131 else if (flags & AT_STATX_DONT_SYNC)
1132 sync = false;
Miklos Szeredi2f1e8192018-10-15 15:43:06 +02001133 else if (request_mask & READ_ONCE(fi->inval_mask))
1134 sync = true;
Miklos Szeredibf5c1892018-03-20 17:11:44 +01001135 else
1136 sync = time_before64(fi->i_time, get_jiffies_64());
1137
1138 if (sync) {
Seth Forshee60bcc882016-08-29 08:46:37 -05001139 forget_all_cached_acls(inode);
Miklos Szeredibcb4be82007-11-28 16:21:59 -08001140 err = fuse_do_getattr(inode, stat, file);
Miklos Szeredi5b97eea2017-09-12 16:57:54 +02001141 } else if (stat) {
1142 generic_fillattr(inode, stat);
1143 stat->mode = fi->orig_i_mode;
1144 stat->ino = fi->orig_ino;
Miklos Szeredibcb4be82007-11-28 16:21:59 -08001145 }
1146
Miklos Szeredibcb4be82007-11-28 16:21:59 -08001147 return err;
1148}
1149
Miklos Szeredi5b97eea2017-09-12 16:57:54 +02001150int fuse_update_attributes(struct inode *inode, struct file *file)
1151{
Miklos Szeredi802dc042018-10-15 15:43:06 +02001152 /* Do *not* need to get atime for internal purposes */
1153 return fuse_update_get_attr(inode, file, NULL,
1154 STATX_BASIC_STATS & ~STATX_ATIME, 0);
Miklos Szeredi5b97eea2017-09-12 16:57:54 +02001155}
1156
Max Reitzfcee2162020-05-06 17:44:12 +02001157int fuse_reverse_inval_entry(struct fuse_conn *fc, u64 parent_nodeid,
John Muir451d0f52011-12-06 21:50:06 +01001158 u64 child_nodeid, struct qstr *name)
John Muir3b463ae2009-05-31 11:13:57 -04001159{
1160 int err = -ENOTDIR;
1161 struct inode *parent;
1162 struct dentry *dir;
1163 struct dentry *entry;
1164
Max Reitzfcee2162020-05-06 17:44:12 +02001165 parent = fuse_ilookup(fc, parent_nodeid, NULL);
John Muir3b463ae2009-05-31 11:13:57 -04001166 if (!parent)
1167 return -ENOENT;
1168
Al Viro59551022016-01-22 15:40:57 -05001169 inode_lock(parent);
John Muir3b463ae2009-05-31 11:13:57 -04001170 if (!S_ISDIR(parent->i_mode))
1171 goto unlock;
1172
1173 err = -ENOENT;
1174 dir = d_find_alias(parent);
1175 if (!dir)
1176 goto unlock;
1177
Linus Torvalds8387ff22016-06-10 07:51:30 -07001178 name->hash = full_name_hash(dir, name->name, name->len);
John Muir3b463ae2009-05-31 11:13:57 -04001179 entry = d_lookup(dir, name);
1180 dput(dir);
1181 if (!entry)
1182 goto unlock;
1183
Miklos Szeredi261aaba72018-10-01 10:07:05 +02001184 fuse_dir_changed(parent);
John Muir3b463ae2009-05-31 11:13:57 -04001185 fuse_invalidate_entry(entry);
John Muir451d0f52011-12-06 21:50:06 +01001186
David Howells2b0143b2015-03-17 22:25:59 +00001187 if (child_nodeid != 0 && d_really_is_positive(entry)) {
Al Viro59551022016-01-22 15:40:57 -05001188 inode_lock(d_inode(entry));
David Howells2b0143b2015-03-17 22:25:59 +00001189 if (get_node_id(d_inode(entry)) != child_nodeid) {
John Muir451d0f52011-12-06 21:50:06 +01001190 err = -ENOENT;
1191 goto badentry;
1192 }
1193 if (d_mountpoint(entry)) {
1194 err = -EBUSY;
1195 goto badentry;
1196 }
David Howellse36cb0b2015-01-29 12:02:35 +00001197 if (d_is_dir(entry)) {
John Muir451d0f52011-12-06 21:50:06 +01001198 shrink_dcache_parent(entry);
1199 if (!simple_empty(entry)) {
1200 err = -ENOTEMPTY;
1201 goto badentry;
1202 }
David Howells2b0143b2015-03-17 22:25:59 +00001203 d_inode(entry)->i_flags |= S_DEAD;
John Muir451d0f52011-12-06 21:50:06 +01001204 }
1205 dont_mount(entry);
David Howells2b0143b2015-03-17 22:25:59 +00001206 clear_nlink(d_inode(entry));
John Muir451d0f52011-12-06 21:50:06 +01001207 err = 0;
1208 badentry:
Al Viro59551022016-01-22 15:40:57 -05001209 inode_unlock(d_inode(entry));
John Muir451d0f52011-12-06 21:50:06 +01001210 if (!err)
1211 d_delete(entry);
1212 } else {
1213 err = 0;
1214 }
John Muir3b463ae2009-05-31 11:13:57 -04001215 dput(entry);
John Muir3b463ae2009-05-31 11:13:57 -04001216
1217 unlock:
Al Viro59551022016-01-22 15:40:57 -05001218 inode_unlock(parent);
John Muir3b463ae2009-05-31 11:13:57 -04001219 iput(parent);
1220 return err;
1221}
1222
Miklos Szeredi87729a52005-09-09 13:10:34 -07001223/*
1224 * Calling into a user-controlled filesystem gives the filesystem
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001225 * daemon ptrace-like capabilities over the current process. This
Miklos Szeredi87729a52005-09-09 13:10:34 -07001226 * means, that the filesystem daemon is able to record the exact
1227 * filesystem operations performed, and can also control the behavior
1228 * of the requester process in otherwise impossible ways. For example
1229 * it can delay the operation for arbitrary length of time allowing
1230 * DoS against the requester.
1231 *
1232 * For this reason only those processes can call into the filesystem,
1233 * for which the owner of the mount has ptrace privilege. This
1234 * excludes processes started by other users, suid or sgid processes.
1235 */
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001236int fuse_allow_current_process(struct fuse_conn *fc)
Miklos Szeredi87729a52005-09-09 13:10:34 -07001237{
David Howellsc69e8d92008-11-14 10:39:19 +11001238 const struct cred *cred;
David Howellsc69e8d92008-11-14 10:39:19 +11001239
Miklos Szeredi29433a22016-10-01 07:32:32 +02001240 if (fc->allow_other)
Seth Forshee73f03c22017-12-22 15:32:33 +01001241 return current_in_userns(fc->user_ns);
Miklos Szeredi87729a52005-09-09 13:10:34 -07001242
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001243 cred = current_cred();
Eric W. Biederman499dcf22012-02-07 16:26:03 -08001244 if (uid_eq(cred->euid, fc->user_id) &&
1245 uid_eq(cred->suid, fc->user_id) &&
1246 uid_eq(cred->uid, fc->user_id) &&
1247 gid_eq(cred->egid, fc->group_id) &&
1248 gid_eq(cred->sgid, fc->group_id) &&
1249 gid_eq(cred->gid, fc->group_id))
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001250 return 1;
Miklos Szeredi87729a52005-09-09 13:10:34 -07001251
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001252 return 0;
Miklos Szeredi87729a52005-09-09 13:10:34 -07001253}
1254
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001255static int fuse_access(struct inode *inode, int mask)
1256{
Max Reitzfcee2162020-05-06 17:44:12 +02001257 struct fuse_mount *fm = get_fuse_mount(inode);
Miklos Szeredi70781872014-12-12 09:49:05 +01001258 FUSE_ARGS(args);
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001259 struct fuse_access_in inarg;
1260 int err;
1261
Miklos Szeredi698fa1d2013-10-01 16:41:23 +02001262 BUG_ON(mask & MAY_NOT_BLOCK);
1263
Max Reitzfcee2162020-05-06 17:44:12 +02001264 if (fm->fc->no_access)
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001265 return 0;
1266
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001267 memset(&inarg, 0, sizeof(inarg));
Al Viroe6305c42008-07-15 21:03:57 -04001268 inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC);
Miklos Szeredid5b48542019-09-10 15:04:08 +02001269 args.opcode = FUSE_ACCESS;
1270 args.nodeid = get_node_id(inode);
1271 args.in_numargs = 1;
1272 args.in_args[0].size = sizeof(inarg);
1273 args.in_args[0].value = &inarg;
Max Reitzfcee2162020-05-06 17:44:12 +02001274 err = fuse_simple_request(fm, &args);
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001275 if (err == -ENOSYS) {
Max Reitzfcee2162020-05-06 17:44:12 +02001276 fm->fc->no_access = 1;
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001277 err = 0;
1278 }
1279 return err;
1280}
1281
Al Viro10556cb22011-06-20 19:28:19 -04001282static int fuse_perm_getattr(struct inode *inode, int mask)
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001283{
Al Viro10556cb22011-06-20 19:28:19 -04001284 if (mask & MAY_NOT_BLOCK)
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001285 return -ECHILD;
1286
Seth Forshee60bcc882016-08-29 08:46:37 -05001287 forget_all_cached_acls(inode);
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001288 return fuse_do_getattr(inode, NULL, NULL);
1289}
1290
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001291/*
1292 * Check permission. The two basic access models of FUSE are:
1293 *
1294 * 1) Local access checking ('default_permissions' mount option) based
1295 * on file mode. This is the plain old disk filesystem permission
1296 * modell.
1297 *
1298 * 2) "Remote" access checking, where server is responsible for
1299 * checking permission in each inode operation. An exception to this
1300 * is if ->permission() was invoked from sys_access() in which case an
1301 * access request is sent. Execute permission is still checked
1302 * locally based on file mode.
1303 */
Al Viro10556cb22011-06-20 19:28:19 -04001304static int fuse_permission(struct inode *inode, int mask)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001305{
1306 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi244f6382007-10-16 23:31:02 -07001307 bool refreshed = false;
1308 int err = 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001309
Miklos Szeredi36cf9ae2020-12-10 15:33:14 +01001310 if (fuse_is_bad(inode))
1311 return -EIO;
1312
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001313 if (!fuse_allow_current_process(fc))
Miklos Szeredie5e55582005-09-09 13:10:28 -07001314 return -EACCES;
Miklos Szeredi244f6382007-10-16 23:31:02 -07001315
1316 /*
Miklos Szeredie8e96152007-10-16 23:31:06 -07001317 * If attributes are needed, refresh them before proceeding
Miklos Szeredi244f6382007-10-16 23:31:02 -07001318 */
Miklos Szeredi29433a22016-10-01 07:32:32 +02001319 if (fc->default_permissions ||
Miklos Szeredie8e96152007-10-16 23:31:06 -07001320 ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001321 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredid233c7d2018-12-03 10:14:43 +01001322 u32 perm_mask = STATX_MODE | STATX_UID | STATX_GID;
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001323
Miklos Szeredid233c7d2018-12-03 10:14:43 +01001324 if (perm_mask & READ_ONCE(fi->inval_mask) ||
1325 time_before64(fi->i_time, get_jiffies_64())) {
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001326 refreshed = true;
1327
Al Viro10556cb22011-06-20 19:28:19 -04001328 err = fuse_perm_getattr(inode, mask);
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001329 if (err)
1330 return err;
1331 }
Miklos Szeredi244f6382007-10-16 23:31:02 -07001332 }
1333
Miklos Szeredi29433a22016-10-01 07:32:32 +02001334 if (fc->default_permissions) {
Al Viro2830ba72011-06-20 19:16:29 -04001335 err = generic_permission(inode, mask);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001336
1337 /* If permission is denied, try to refresh file
1338 attributes. This is also needed, because the root
1339 node will at first have no permissions */
Miklos Szeredi244f6382007-10-16 23:31:02 -07001340 if (err == -EACCES && !refreshed) {
Al Viro10556cb22011-06-20 19:28:19 -04001341 err = fuse_perm_getattr(inode, mask);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001342 if (!err)
Al Viro2830ba72011-06-20 19:16:29 -04001343 err = generic_permission(inode, mask);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001344 }
1345
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001346 /* Note: the opposite of the above test does not
1347 exist. So if permissions are revoked this won't be
1348 noticed immediately, only after the attribute
1349 timeout has expired */
Eric Paris9cfcac82010-07-23 11:43:51 -04001350 } else if (mask & (MAY_ACCESS | MAY_CHDIR)) {
Miklos Szeredie8e96152007-10-16 23:31:06 -07001351 err = fuse_access(inode, mask);
1352 } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
1353 if (!(inode->i_mode & S_IXUGO)) {
1354 if (refreshed)
1355 return -EACCES;
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001356
Al Viro10556cb22011-06-20 19:28:19 -04001357 err = fuse_perm_getattr(inode, mask);
Miklos Szeredie8e96152007-10-16 23:31:06 -07001358 if (!err && !(inode->i_mode & S_IXUGO))
1359 return -EACCES;
1360 }
Miklos Szeredie5e55582005-09-09 13:10:28 -07001361 }
Miklos Szeredi244f6382007-10-16 23:31:02 -07001362 return err;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001363}
1364
Dan Schatzberg5571f1e2018-10-11 08:17:00 -07001365static int fuse_readlink_page(struct inode *inode, struct page *page)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001366{
Max Reitzfcee2162020-05-06 17:44:12 +02001367 struct fuse_mount *fm = get_fuse_mount(inode);
Miklos Szeredi4c29afe2019-09-10 15:04:09 +02001368 struct fuse_page_desc desc = { .length = PAGE_SIZE - 1 };
1369 struct fuse_args_pages ap = {
1370 .num_pages = 1,
1371 .pages = &page,
1372 .descs = &desc,
1373 };
1374 char *link;
1375 ssize_t res;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001376
Miklos Szeredi4c29afe2019-09-10 15:04:09 +02001377 ap.args.opcode = FUSE_READLINK;
1378 ap.args.nodeid = get_node_id(inode);
1379 ap.args.out_pages = true;
1380 ap.args.out_argvar = true;
1381 ap.args.page_zeroing = true;
1382 ap.args.out_numargs = 1;
1383 ap.args.out_args[0].size = desc.length;
Max Reitzfcee2162020-05-06 17:44:12 +02001384 res = fuse_simple_request(fm, &ap.args);
Al Viro6b255392015-11-17 10:20:54 -05001385
Andrew Gallagher451418f2013-11-05 03:55:43 -08001386 fuse_invalidate_atime(inode);
Dan Schatzberg5571f1e2018-10-11 08:17:00 -07001387
Miklos Szeredi4c29afe2019-09-10 15:04:09 +02001388 if (res < 0)
1389 return res;
1390
1391 if (WARN_ON(res >= PAGE_SIZE))
1392 return -EIO;
1393
1394 link = page_address(page);
1395 link[res] = '\0';
1396
1397 return 0;
Dan Schatzberg5571f1e2018-10-11 08:17:00 -07001398}
1399
1400static const char *fuse_get_link(struct dentry *dentry, struct inode *inode,
1401 struct delayed_call *callback)
1402{
1403 struct fuse_conn *fc = get_fuse_conn(inode);
1404 struct page *page;
1405 int err;
1406
1407 err = -EIO;
Miklos Szeredi36cf9ae2020-12-10 15:33:14 +01001408 if (fuse_is_bad(inode))
Dan Schatzberg5571f1e2018-10-11 08:17:00 -07001409 goto out_err;
1410
1411 if (fc->cache_symlinks)
1412 return page_get_link(dentry, inode, callback);
1413
1414 err = -ECHILD;
1415 if (!dentry)
1416 goto out_err;
1417
1418 page = alloc_page(GFP_KERNEL);
1419 err = -ENOMEM;
1420 if (!page)
1421 goto out_err;
1422
1423 err = fuse_readlink_page(inode, page);
1424 if (err) {
1425 __free_page(page);
1426 goto out_err;
1427 }
1428
1429 set_delayed_call(callback, page_put_link, page);
1430
1431 return page_address(page);
1432
1433out_err:
1434 return ERR_PTR(err);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001435}
1436
Miklos Szeredie5e55582005-09-09 13:10:28 -07001437static int fuse_dir_open(struct inode *inode, struct file *file)
1438{
Miklos Szeredi91fe96b2009-04-28 16:56:37 +02001439 return fuse_open_common(inode, file, true);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001440}
1441
1442static int fuse_dir_release(struct inode *inode, struct file *file)
1443{
Chad Austin2e64ff12018-12-10 10:54:52 -08001444 fuse_release_common(file, true);
Miklos Szeredi8b0797a2009-04-28 16:56:39 +02001445
1446 return 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001447}
1448
Josef Bacik02c24a82011-07-16 20:44:56 -04001449static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end,
1450 int datasync)
Miklos Szeredi82547982005-09-09 13:10:38 -07001451{
Miklos Szeredia9c2d1e2018-12-03 10:14:43 +01001452 struct inode *inode = file->f_mapping->host;
1453 struct fuse_conn *fc = get_fuse_conn(inode);
1454 int err;
1455
Miklos Szeredi36cf9ae2020-12-10 15:33:14 +01001456 if (fuse_is_bad(inode))
Miklos Szeredia9c2d1e2018-12-03 10:14:43 +01001457 return -EIO;
1458
1459 if (fc->no_fsyncdir)
1460 return 0;
1461
1462 inode_lock(inode);
1463 err = fuse_fsync_common(file, start, end, datasync, FUSE_FSYNCDIR);
1464 if (err == -ENOSYS) {
1465 fc->no_fsyncdir = 1;
1466 err = 0;
1467 }
1468 inode_unlock(inode);
1469
1470 return err;
Miklos Szeredi82547982005-09-09 13:10:38 -07001471}
1472
Miklos Szeredib18da0c2011-12-13 11:58:49 +01001473static long fuse_dir_ioctl(struct file *file, unsigned int cmd,
1474 unsigned long arg)
1475{
1476 struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1477
1478 /* FUSE_IOCTL_DIR only supported for API version >= 7.18 */
1479 if (fc->minor < 18)
1480 return -ENOTTY;
1481
1482 return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR);
1483}
1484
1485static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd,
1486 unsigned long arg)
1487{
1488 struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1489
1490 if (fc->minor < 18)
1491 return -ENOTTY;
1492
1493 return fuse_ioctl_common(file, cmd, arg,
1494 FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR);
1495}
1496
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001497static bool update_mtime(unsigned ivalid, bool trust_local_mtime)
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001498{
1499 /* Always update if mtime is explicitly set */
1500 if (ivalid & ATTR_MTIME_SET)
1501 return true;
1502
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001503 /* Or if kernel i_mtime is the official one */
1504 if (trust_local_mtime)
1505 return true;
1506
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001507 /* If it's an open(O_TRUNC) or an ftruncate(), don't update */
1508 if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
1509 return false;
1510
1511 /* In all other cases update */
1512 return true;
1513}
1514
Eric W. Biederman8cb08322018-02-21 11:18:07 -06001515static void iattr_to_fattr(struct fuse_conn *fc, struct iattr *iattr,
1516 struct fuse_setattr_in *arg, bool trust_local_cmtime)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001517{
1518 unsigned ivalid = iattr->ia_valid;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001519
1520 if (ivalid & ATTR_MODE)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001521 arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001522 if (ivalid & ATTR_UID)
Eric W. Biederman8cb08322018-02-21 11:18:07 -06001523 arg->valid |= FATTR_UID, arg->uid = from_kuid(fc->user_ns, iattr->ia_uid);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001524 if (ivalid & ATTR_GID)
Eric W. Biederman8cb08322018-02-21 11:18:07 -06001525 arg->valid |= FATTR_GID, arg->gid = from_kgid(fc->user_ns, iattr->ia_gid);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001526 if (ivalid & ATTR_SIZE)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001527 arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001528 if (ivalid & ATTR_ATIME) {
1529 arg->valid |= FATTR_ATIME;
Miklos Szeredibefc6492005-11-07 00:59:52 -08001530 arg->atime = iattr->ia_atime.tv_sec;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001531 arg->atimensec = iattr->ia_atime.tv_nsec;
1532 if (!(ivalid & ATTR_ATIME_SET))
1533 arg->valid |= FATTR_ATIME_NOW;
1534 }
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001535 if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, trust_local_cmtime)) {
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001536 arg->valid |= FATTR_MTIME;
Miklos Szeredibefc6492005-11-07 00:59:52 -08001537 arg->mtime = iattr->ia_mtime.tv_sec;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001538 arg->mtimensec = iattr->ia_mtime.tv_nsec;
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001539 if (!(ivalid & ATTR_MTIME_SET) && !trust_local_cmtime)
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001540 arg->valid |= FATTR_MTIME_NOW;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001541 }
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001542 if ((ivalid & ATTR_CTIME) && trust_local_cmtime) {
1543 arg->valid |= FATTR_CTIME;
1544 arg->ctime = iattr->ia_ctime.tv_sec;
1545 arg->ctimensec = iattr->ia_ctime.tv_nsec;
1546 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001547}
1548
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001549/*
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001550 * Prevent concurrent writepages on inode
1551 *
1552 * This is done by adding a negative bias to the inode write counter
1553 * and waiting for all pending writes to finish.
1554 */
1555void fuse_set_nowrite(struct inode *inode)
1556{
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001557 struct fuse_inode *fi = get_fuse_inode(inode);
1558
Al Viro59551022016-01-22 15:40:57 -05001559 BUG_ON(!inode_is_locked(inode));
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001560
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +03001561 spin_lock(&fi->lock);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001562 BUG_ON(fi->writectr < 0);
1563 fi->writectr += FUSE_NOWRITE;
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +03001564 spin_unlock(&fi->lock);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001565 wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE);
1566}
1567
1568/*
1569 * Allow writepages on inode
1570 *
1571 * Remove the bias from the writecounter and send any queued
1572 * writepages.
1573 */
1574static void __fuse_release_nowrite(struct inode *inode)
1575{
1576 struct fuse_inode *fi = get_fuse_inode(inode);
1577
1578 BUG_ON(fi->writectr != FUSE_NOWRITE);
1579 fi->writectr = 0;
1580 fuse_flush_writepages(inode);
1581}
1582
1583void fuse_release_nowrite(struct inode *inode)
1584{
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +03001585 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001586
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +03001587 spin_lock(&fi->lock);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001588 __fuse_release_nowrite(inode);
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +03001589 spin_unlock(&fi->lock);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001590}
1591
Miklos Szeredi70781872014-12-12 09:49:05 +01001592static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_args *args,
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001593 struct inode *inode,
1594 struct fuse_setattr_in *inarg_p,
1595 struct fuse_attr_out *outarg_p)
1596{
Miklos Szeredid5b48542019-09-10 15:04:08 +02001597 args->opcode = FUSE_SETATTR;
1598 args->nodeid = get_node_id(inode);
1599 args->in_numargs = 1;
1600 args->in_args[0].size = sizeof(*inarg_p);
1601 args->in_args[0].value = inarg_p;
1602 args->out_numargs = 1;
1603 args->out_args[0].size = sizeof(*outarg_p);
1604 args->out_args[0].value = outarg_p;
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001605}
1606
1607/*
1608 * Flush inode->i_mtime to the server
1609 */
Maxim Patlasovab9e13f2014-04-28 14:19:24 +02001610int fuse_flush_times(struct inode *inode, struct fuse_file *ff)
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001611{
Max Reitzfcee2162020-05-06 17:44:12 +02001612 struct fuse_mount *fm = get_fuse_mount(inode);
Miklos Szeredi70781872014-12-12 09:49:05 +01001613 FUSE_ARGS(args);
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001614 struct fuse_setattr_in inarg;
1615 struct fuse_attr_out outarg;
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001616
1617 memset(&inarg, 0, sizeof(inarg));
1618 memset(&outarg, 0, sizeof(outarg));
1619
Maxim Patlasovab9e13f2014-04-28 14:19:24 +02001620 inarg.valid = FATTR_MTIME;
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001621 inarg.mtime = inode->i_mtime.tv_sec;
1622 inarg.mtimensec = inode->i_mtime.tv_nsec;
Max Reitzfcee2162020-05-06 17:44:12 +02001623 if (fm->fc->minor >= 23) {
Maxim Patlasovab9e13f2014-04-28 14:19:24 +02001624 inarg.valid |= FATTR_CTIME;
1625 inarg.ctime = inode->i_ctime.tv_sec;
1626 inarg.ctimensec = inode->i_ctime.tv_nsec;
1627 }
Miklos Szeredi1e18bda2014-04-28 14:19:23 +02001628 if (ff) {
1629 inarg.valid |= FATTR_FH;
1630 inarg.fh = ff->fh;
1631 }
Max Reitzfcee2162020-05-06 17:44:12 +02001632 fuse_setattr_fill(fm->fc, &args, inode, &inarg, &outarg);
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001633
Max Reitzfcee2162020-05-06 17:44:12 +02001634 return fuse_simple_request(fm, &args);
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001635}
1636
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001637/*
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001638 * Set attributes, and at the same time refresh them.
1639 *
1640 * Truncation is slightly complicated, because the 'truncate' request
1641 * may fail, in which case we don't want to touch the mapping.
Miklos Szeredi9ffbb912006-10-17 00:10:06 -07001642 * vmtruncate() doesn't allow for this case, so do the rlimit checking
1643 * and the actual truncation by hand.
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001644 */
Jan Kara62490332016-05-26 17:12:41 +02001645int fuse_do_setattr(struct dentry *dentry, struct iattr *attr,
Maxim Patlasovefb9fa92012-12-18 14:05:08 +04001646 struct file *file)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001647{
Jan Kara62490332016-05-26 17:12:41 +02001648 struct inode *inode = d_inode(dentry);
Max Reitzfcee2162020-05-06 17:44:12 +02001649 struct fuse_mount *fm = get_fuse_mount(inode);
1650 struct fuse_conn *fc = fm->fc;
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001651 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredi70781872014-12-12 09:49:05 +01001652 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001653 struct fuse_setattr_in inarg;
1654 struct fuse_attr_out outarg;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001655 bool is_truncate = false;
Pavel Emelyanov83732002013-10-10 17:10:46 +04001656 bool is_wb = fc->writeback_cache;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001657 loff_t oldsize;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001658 int err;
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001659 bool trust_local_cmtime = is_wb && S_ISREG(inode->i_mode);
Vivek Goyal6ae330c2020-08-19 18:19:54 -04001660 bool fault_blocked = false;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001661
Miklos Szeredi29433a22016-10-01 07:32:32 +02001662 if (!fc->default_permissions)
Christoph Hellwigdb78b872010-06-04 11:30:03 +02001663 attr->ia_valid |= ATTR_FORCE;
1664
Jan Kara31051c82016-05-26 16:55:18 +02001665 err = setattr_prepare(dentry, attr);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02001666 if (err)
1667 return err;
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001668
Vivek Goyal6ae330c2020-08-19 18:19:54 -04001669 if (attr->ia_valid & ATTR_SIZE) {
1670 if (WARN_ON(!S_ISREG(inode->i_mode)))
1671 return -EIO;
1672 is_truncate = true;
1673 }
1674
1675 if (FUSE_IS_DAX(inode) && is_truncate) {
1676 down_write(&fi->i_mmap_sem);
1677 fault_blocked = true;
1678 err = fuse_dax_break_layouts(inode, 0, 0);
1679 if (err) {
1680 up_write(&fi->i_mmap_sem);
1681 return err;
1682 }
1683 }
1684
Miklos Szeredi8d56add2011-02-25 14:44:58 +01001685 if (attr->ia_valid & ATTR_OPEN) {
Miklos Szeredidf0e91d2018-02-08 15:17:38 +01001686 /* This is coming from open(..., ... | O_TRUNC); */
1687 WARN_ON(!(attr->ia_valid & ATTR_SIZE));
1688 WARN_ON(attr->ia_size != 0);
1689 if (fc->atomic_o_trunc) {
1690 /*
1691 * No need to send request to userspace, since actual
1692 * truncation has already been done by OPEN. But still
1693 * need to truncate page cache.
1694 */
1695 i_size_write(inode, 0);
1696 truncate_pagecache(inode, 0);
Vivek Goyal6ae330c2020-08-19 18:19:54 -04001697 goto out;
Miklos Szeredidf0e91d2018-02-08 15:17:38 +01001698 }
Miklos Szeredi8d56add2011-02-25 14:44:58 +01001699 file = NULL;
1700 }
Miklos Szeredi6ff958e2007-10-18 03:07:02 -07001701
Miklos Szeredib24e7592019-10-23 14:26:37 +02001702 /* Flush dirty data/metadata before non-truncate SETATTR */
1703 if (is_wb && S_ISREG(inode->i_mode) &&
1704 attr->ia_valid &
1705 (ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_MTIME_SET |
1706 ATTR_TIMES_SET)) {
1707 err = write_inode_now(inode, true);
1708 if (err)
1709 return err;
1710
1711 fuse_set_nowrite(inode);
1712 fuse_release_nowrite(inode);
1713 }
1714
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001715 if (is_truncate) {
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001716 fuse_set_nowrite(inode);
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001717 set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001718 if (trust_local_cmtime && attr->ia_size != inode->i_size)
1719 attr->ia_valid |= ATTR_MTIME | ATTR_CTIME;
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001720 }
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001721
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001722 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -07001723 memset(&outarg, 0, sizeof(outarg));
Eric W. Biederman8cb08322018-02-21 11:18:07 -06001724 iattr_to_fattr(fc, attr, &inarg, trust_local_cmtime);
Miklos Szeredi49d49142007-10-18 03:07:00 -07001725 if (file) {
1726 struct fuse_file *ff = file->private_data;
1727 inarg.valid |= FATTR_FH;
1728 inarg.fh = ff->fh;
1729 }
Miklos Szeredif3332112007-10-18 03:07:04 -07001730 if (attr->ia_valid & ATTR_SIZE) {
1731 /* For mandatory locking in truncate */
1732 inarg.valid |= FATTR_LOCKOWNER;
1733 inarg.lock_owner = fuse_lock_owner_id(fc, current->files);
1734 }
Miklos Szeredi70781872014-12-12 09:49:05 +01001735 fuse_setattr_fill(fc, &args, inode, &inarg, &outarg);
Max Reitzfcee2162020-05-06 17:44:12 +02001736 err = fuse_simple_request(fm, &args);
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001737 if (err) {
1738 if (err == -EINTR)
1739 fuse_invalidate_attr(inode);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001740 goto error;
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001741 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001742
Miklos Szeredieb59bd12019-11-12 11:49:04 +01001743 if (fuse_invalid_attr(&outarg.attr) ||
1744 (inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
Miklos Szeredi36cf9ae2020-12-10 15:33:14 +01001745 fuse_make_bad(inode);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001746 err = -EIO;
1747 goto error;
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001748 }
1749
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +03001750 spin_lock(&fi->lock);
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001751 /* the kernel maintains i_mtime locally */
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001752 if (trust_local_cmtime) {
1753 if (attr->ia_valid & ATTR_MTIME)
1754 inode->i_mtime = attr->ia_mtime;
1755 if (attr->ia_valid & ATTR_CTIME)
1756 inode->i_ctime = attr->ia_ctime;
Miklos Szeredi1e18bda2014-04-28 14:19:23 +02001757 /* FIXME: clear I_DIRTY_SYNC? */
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001758 }
1759
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001760 fuse_change_attributes_common(inode, &outarg.attr,
1761 attr_timeout(&outarg));
1762 oldsize = inode->i_size;
Pavel Emelyanov83732002013-10-10 17:10:46 +04001763 /* see the comment in fuse_change_attributes() */
1764 if (!is_wb || is_truncate || !S_ISREG(inode->i_mode))
1765 i_size_write(inode, outarg.attr.size);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001766
1767 if (is_truncate) {
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +03001768 /* NOTE: this may release/reacquire fi->lock */
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001769 __fuse_release_nowrite(inode);
1770 }
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +03001771 spin_unlock(&fi->lock);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001772
1773 /*
1774 * Only call invalidate_inode_pages2() after removing
1775 * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock.
1776 */
Pavel Emelyanov83732002013-10-10 17:10:46 +04001777 if ((is_truncate || !is_wb) &&
1778 S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
Kirill A. Shutemov7caef262013-09-12 15:13:56 -07001779 truncate_pagecache(inode, outarg.attr.size);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001780 invalidate_inode_pages2(inode->i_mapping);
1781 }
1782
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001783 clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
Vivek Goyal6ae330c2020-08-19 18:19:54 -04001784out:
1785 if (fault_blocked)
1786 up_write(&fi->i_mmap_sem);
1787
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001788 return 0;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001789
1790error:
1791 if (is_truncate)
1792 fuse_release_nowrite(inode);
1793
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001794 clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
Vivek Goyal6ae330c2020-08-19 18:19:54 -04001795
1796 if (fault_blocked)
1797 up_write(&fi->i_mmap_sem);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001798 return err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001799}
1800
Miklos Szeredi49d49142007-10-18 03:07:00 -07001801static int fuse_setattr(struct dentry *entry, struct iattr *attr)
1802{
David Howells2b0143b2015-03-17 22:25:59 +00001803 struct inode *inode = d_inode(entry);
Miklos Szeredi5e940c12016-10-01 07:32:32 +02001804 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredia09f99e2016-10-01 07:32:32 +02001805 struct file *file = (attr->ia_valid & ATTR_FILE) ? attr->ia_file : NULL;
Miklos Szeredi5e2b8822016-10-01 07:32:32 +02001806 int ret;
Maxim Patlasovefb9fa92012-12-18 14:05:08 +04001807
Miklos Szeredi36cf9ae2020-12-10 15:33:14 +01001808 if (fuse_is_bad(inode))
1809 return -EIO;
1810
Maxim Patlasovefb9fa92012-12-18 14:05:08 +04001811 if (!fuse_allow_current_process(get_fuse_conn(inode)))
1812 return -EACCES;
1813
Miklos Szeredia09f99e2016-10-01 07:32:32 +02001814 if (attr->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) {
Miklos Szeredia09f99e2016-10-01 07:32:32 +02001815 attr->ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID |
1816 ATTR_MODE);
Miklos Szeredia09f99e2016-10-01 07:32:32 +02001817
Miklos Szeredi5e940c12016-10-01 07:32:32 +02001818 /*
1819 * The only sane way to reliably kill suid/sgid is to do it in
1820 * the userspace filesystem
1821 *
1822 * This should be done on write(), truncate() and chown().
1823 */
1824 if (!fc->handle_killpriv) {
Miklos Szeredi5e940c12016-10-01 07:32:32 +02001825 /*
1826 * ia_mode calculation may have used stale i_mode.
1827 * Refresh and recalculate.
1828 */
1829 ret = fuse_do_getattr(inode, NULL, file);
1830 if (ret)
1831 return ret;
1832
1833 attr->ia_mode = inode->i_mode;
Miklos Szeredic01638f2016-12-06 16:18:45 +01001834 if (inode->i_mode & S_ISUID) {
Miklos Szeredi5e940c12016-10-01 07:32:32 +02001835 attr->ia_valid |= ATTR_MODE;
1836 attr->ia_mode &= ~S_ISUID;
1837 }
Miklos Szeredic01638f2016-12-06 16:18:45 +01001838 if ((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
Miklos Szeredi5e940c12016-10-01 07:32:32 +02001839 attr->ia_valid |= ATTR_MODE;
1840 attr->ia_mode &= ~S_ISGID;
1841 }
Miklos Szeredia09f99e2016-10-01 07:32:32 +02001842 }
1843 }
1844 if (!attr->ia_valid)
1845 return 0;
1846
Linus Torvaldsabb5a142016-10-10 13:04:49 -07001847 ret = fuse_do_setattr(entry, attr, file);
Miklos Szeredi5e2b8822016-10-01 07:32:32 +02001848 if (!ret) {
Seth Forshee60bcc882016-08-29 08:46:37 -05001849 /*
1850 * If filesystem supports acls it may have updated acl xattrs in
1851 * the filesystem, so forget cached acls for the inode.
1852 */
1853 if (fc->posix_acl)
1854 forget_all_cached_acls(inode);
1855
Miklos Szeredi5e2b8822016-10-01 07:32:32 +02001856 /* Directory mode changed, may need to revalidate access */
1857 if (d_is_dir(entry) && (attr->ia_valid & ATTR_MODE))
1858 fuse_invalidate_entry_cache(entry);
1859 }
1860 return ret;
Miklos Szeredi49d49142007-10-18 03:07:00 -07001861}
1862
David Howellsa528d352017-01-31 16:46:22 +00001863static int fuse_getattr(const struct path *path, struct kstat *stat,
1864 u32 request_mask, unsigned int flags)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001865{
David Howellsa528d352017-01-31 16:46:22 +00001866 struct inode *inode = d_inode(path->dentry);
Miklos Szeredi244f6382007-10-16 23:31:02 -07001867 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi244f6382007-10-16 23:31:02 -07001868
Miklos Szeredi36cf9ae2020-12-10 15:33:14 +01001869 if (fuse_is_bad(inode))
1870 return -EIO;
1871
Miklos Szeredi5157da22020-05-19 14:50:37 +02001872 if (!fuse_allow_current_process(fc)) {
1873 if (!request_mask) {
1874 /*
1875 * If user explicitly requested *nothing* then don't
1876 * error out, but return st_dev only.
1877 */
1878 stat->result_mask = 0;
1879 stat->dev = inode->i_sb->s_dev;
1880 return 0;
1881 }
Miklos Szeredi244f6382007-10-16 23:31:02 -07001882 return -EACCES;
Miklos Szeredi5157da22020-05-19 14:50:37 +02001883 }
Miklos Szeredi244f6382007-10-16 23:31:02 -07001884
Miklos Szeredi2f1e8192018-10-15 15:43:06 +02001885 return fuse_update_get_attr(inode, NULL, stat, request_mask, flags);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001886}
1887
Arjan van de Ven754661f2007-02-12 00:55:38 -08001888static const struct inode_operations fuse_dir_inode_operations = {
Miklos Szeredie5e55582005-09-09 13:10:28 -07001889 .lookup = fuse_lookup,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001890 .mkdir = fuse_mkdir,
1891 .symlink = fuse_symlink,
1892 .unlink = fuse_unlink,
1893 .rmdir = fuse_rmdir,
Miklos Szeredi2773bf02016-09-27 11:03:58 +02001894 .rename = fuse_rename2,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001895 .link = fuse_link,
1896 .setattr = fuse_setattr,
1897 .create = fuse_create,
Miklos Szeredic8ccbe02012-06-05 15:10:22 +02001898 .atomic_open = fuse_atomic_open,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001899 .mknod = fuse_mknod,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001900 .permission = fuse_permission,
1901 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001902 .listxattr = fuse_listxattr,
Seth Forshee60bcc882016-08-29 08:46:37 -05001903 .get_acl = fuse_get_acl,
1904 .set_acl = fuse_set_acl,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001905};
1906
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -08001907static const struct file_operations fuse_dir_operations = {
Miklos Szeredib6aeade2005-09-09 13:10:30 -07001908 .llseek = generic_file_llseek,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001909 .read = generic_read_dir,
Al Virod9b3dbd2016-04-20 17:30:32 -04001910 .iterate_shared = fuse_readdir,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001911 .open = fuse_dir_open,
1912 .release = fuse_dir_release,
Miklos Szeredi82547982005-09-09 13:10:38 -07001913 .fsync = fuse_dir_fsync,
Miklos Szeredib18da0c2011-12-13 11:58:49 +01001914 .unlocked_ioctl = fuse_dir_ioctl,
1915 .compat_ioctl = fuse_dir_compat_ioctl,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001916};
1917
Arjan van de Ven754661f2007-02-12 00:55:38 -08001918static const struct inode_operations fuse_common_inode_operations = {
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001919 .setattr = fuse_setattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001920 .permission = fuse_permission,
1921 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001922 .listxattr = fuse_listxattr,
Seth Forshee60bcc882016-08-29 08:46:37 -05001923 .get_acl = fuse_get_acl,
1924 .set_acl = fuse_set_acl,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001925};
1926
Arjan van de Ven754661f2007-02-12 00:55:38 -08001927static const struct inode_operations fuse_symlink_inode_operations = {
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001928 .setattr = fuse_setattr,
Al Viro6b255392015-11-17 10:20:54 -05001929 .get_link = fuse_get_link,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001930 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001931 .listxattr = fuse_listxattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001932};
1933
1934void fuse_init_common(struct inode *inode)
1935{
1936 inode->i_op = &fuse_common_inode_operations;
1937}
1938
1939void fuse_init_dir(struct inode *inode)
1940{
Miklos Szerediab2257e2018-10-01 10:07:05 +02001941 struct fuse_inode *fi = get_fuse_inode(inode);
1942
Miklos Szeredie5e55582005-09-09 13:10:28 -07001943 inode->i_op = &fuse_dir_inode_operations;
1944 inode->i_fop = &fuse_dir_operations;
Miklos Szerediab2257e2018-10-01 10:07:05 +02001945
1946 spin_lock_init(&fi->rdc.lock);
1947 fi->rdc.cached = false;
1948 fi->rdc.size = 0;
1949 fi->rdc.pos = 0;
1950 fi->rdc.version = 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001951}
1952
Dan Schatzberg5571f1e2018-10-11 08:17:00 -07001953static int fuse_symlink_readpage(struct file *null, struct page *page)
1954{
1955 int err = fuse_readlink_page(page->mapping->host, page);
1956
1957 if (!err)
1958 SetPageUptodate(page);
1959
1960 unlock_page(page);
1961
1962 return err;
1963}
1964
1965static const struct address_space_operations fuse_symlink_aops = {
1966 .readpage = fuse_symlink_readpage,
1967};
1968
Miklos Szeredie5e55582005-09-09 13:10:28 -07001969void fuse_init_symlink(struct inode *inode)
1970{
1971 inode->i_op = &fuse_symlink_inode_operations;
Dan Schatzberg5571f1e2018-10-11 08:17:00 -07001972 inode->i_data.a_ops = &fuse_symlink_aops;
1973 inode_nohighmem(inode);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001974}