blob: d99bf6207b167f79a05089e54092b9cbf8368333 [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 sb->s_flags |= SB_ACTIVE;
351 fsc->root = dget(sb->s_root);
352 /* We are done configuring the superblock, so unlock it */
353 up_write(&sb->s_umount);
354
355 down_write(&fc->killsb);
356 list_add_tail(&fm->fc_entry, &fc->mounts);
357 up_write(&fc->killsb);
358
359 /* Create the submount */
360 mnt = vfs_create_mount(fsc);
361 if (IS_ERR(mnt)) {
362 err = PTR_ERR(mnt);
363 goto out_put_fsc;
364 }
365 mntget(mnt);
366 put_fs_context(fsc);
367 return mnt;
368
369out_put_sb:
370 /*
371 * Only jump here when fsc->root is NULL and sb is still locked
372 * (otherwise put_fs_context() will put the superblock)
373 */
374 deactivate_locked_super(sb);
375out_put_fsc:
376 put_fs_context(fsc);
377out:
378 return ERR_PTR(err);
379}
380
Al Viro42695902009-02-20 05:59:13 +0000381const struct dentry_operations fuse_dentry_operations = {
Miklos Szeredie5e55582005-09-09 13:10:28 -0700382 .d_revalidate = fuse_dentry_revalidate,
Miklos Szeredi8fab0102018-08-15 17:42:34 +0200383 .d_delete = fuse_dentry_delete,
Khazhismel Kumykov30c6a232019-09-16 16:56:41 -0700384#if BITS_PER_LONG < 64
Miklos Szeredif75fdf22016-10-01 07:32:32 +0200385 .d_init = fuse_dentry_init,
386 .d_release = fuse_dentry_release,
Khazhismel Kumykov30c6a232019-09-16 16:56:41 -0700387#endif
Max Reitzbf109c62020-04-21 14:47:15 +0200388 .d_automount = fuse_dentry_automount,
Miklos Szeredie5e55582005-09-09 13:10:28 -0700389};
390
Miklos Szeredi0ce267f2016-10-18 15:36:48 +0200391const struct dentry_operations fuse_root_dentry_operations = {
Khazhismel Kumykov30c6a232019-09-16 16:56:41 -0700392#if BITS_PER_LONG < 64
Miklos Szeredi0ce267f2016-10-18 15:36:48 +0200393 .d_init = fuse_dentry_init,
394 .d_release = fuse_dentry_release,
Khazhismel Kumykov30c6a232019-09-16 16:56:41 -0700395#endif
Miklos Szeredi0ce267f2016-10-18 15:36:48 +0200396};
397
Timo Savolaa5bfffac2007-04-08 16:04:00 -0700398int fuse_valid_type(int m)
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800399{
400 return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) ||
401 S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m);
402}
403
Miklos Szeredieb59bd12019-11-12 11:49:04 +0100404bool fuse_invalid_attr(struct fuse_attr *attr)
405{
406 return !fuse_valid_type(attr->mode) ||
407 attr->size > LLONG_MAX;
408}
409
Al Viro13983d02016-07-20 22:34:44 -0400410int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name,
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700411 struct fuse_entry_out *outarg, struct inode **inode)
412{
Max Reitzfcee2162020-05-06 17:44:12 +0200413 struct fuse_mount *fm = get_fuse_mount_super(sb);
Miklos Szeredi70781872014-12-12 09:49:05 +0100414 FUSE_ARGS(args);
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100415 struct fuse_forget_link *forget;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700416 u64 attr_version;
417 int err;
418
419 *inode = NULL;
420 err = -ENAMETOOLONG;
421 if (name->len > FUSE_NAME_MAX)
422 goto out;
423
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700424
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100425 forget = fuse_alloc_forget();
426 err = -ENOMEM;
Miklos Szeredi70781872014-12-12 09:49:05 +0100427 if (!forget)
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700428 goto out;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700429
Max Reitzfcee2162020-05-06 17:44:12 +0200430 attr_version = fuse_get_attr_version(fm->fc);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700431
Max Reitzfcee2162020-05-06 17:44:12 +0200432 fuse_lookup_init(fm->fc, &args, nodeid, name, outarg);
433 err = fuse_simple_request(fm, &args);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700434 /* Zero nodeid is same as -ENOENT, but with valid timeout */
435 if (err || !outarg->nodeid)
436 goto out_put_forget;
437
438 err = -EIO;
439 if (!outarg->nodeid)
440 goto out_put_forget;
Miklos Szeredieb59bd12019-11-12 11:49:04 +0100441 if (fuse_invalid_attr(&outarg->attr))
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700442 goto out_put_forget;
443
444 *inode = fuse_iget(sb, outarg->nodeid, outarg->generation,
445 &outarg->attr, entry_attr_timeout(outarg),
446 attr_version);
447 err = -ENOMEM;
448 if (!*inode) {
Max Reitzfcee2162020-05-06 17:44:12 +0200449 fuse_queue_forget(fm->fc, forget, outarg->nodeid, 1);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700450 goto out;
451 }
452 err = 0;
453
454 out_put_forget:
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100455 kfree(forget);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700456 out:
457 return err;
458}
459
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800460static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
Al Viro00cd8dd2012-06-10 17:13:09 -0400461 unsigned int flags)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700462{
463 int err;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700464 struct fuse_entry_out outarg;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700465 struct inode *inode;
Miklos Szeredi0de62562008-07-25 01:48:59 -0700466 struct dentry *newent;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700467 bool outarg_valid = true;
Miklos Szeredi63576c12018-07-26 16:13:11 +0200468 bool locked;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700469
Miklos Szeredi36cf9ae2020-12-10 15:33:14 +0100470 if (fuse_is_bad(dir))
471 return ERR_PTR(-EIO);
472
Miklos Szeredi63576c12018-07-26 16:13:11 +0200473 locked = fuse_lock_inode(dir);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700474 err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name,
475 &outarg, &inode);
Miklos Szeredi63576c12018-07-26 16:13:11 +0200476 fuse_unlock_inode(dir, locked);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700477 if (err == -ENOENT) {
478 outarg_valid = false;
479 err = 0;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800480 }
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700481 if (err)
482 goto out_err;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800483
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700484 err = -EIO;
485 if (inode && get_node_id(inode) == FUSE_ROOT_ID)
486 goto out_iput;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700487
Al Viro41d28bc2014-10-12 22:24:21 -0400488 newent = d_splice_alias(inode, entry);
Miklos Szeredi5835f332013-09-05 11:44:42 +0200489 err = PTR_ERR(newent);
490 if (IS_ERR(newent))
491 goto out_err;
Miklos Szeredid2a85162006-10-17 00:10:11 -0700492
Miklos Szeredi0de62562008-07-25 01:48:59 -0700493 entry = newent ? newent : entry;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700494 if (outarg_valid)
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700495 fuse_change_entry_timeout(entry, &outarg);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800496 else
497 fuse_invalidate_entry_cache(entry);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700498
Miklos Szeredi6c26f712019-10-21 15:57:07 +0200499 if (inode)
500 fuse_advise_use_readdirplus(dir);
Miklos Szeredi0de62562008-07-25 01:48:59 -0700501 return newent;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700502
503 out_iput:
504 iput(inode);
505 out_err:
506 return ERR_PTR(err);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700507}
508
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800509/*
510 * Atomic create+open operation
511 *
512 * If the filesystem doesn't support this, then fall back to separate
513 * 'mknod' + 'open' requests.
514 */
Al Virod9585272012-06-22 12:39:14 +0400515static int fuse_create_open(struct inode *dir, struct dentry *entry,
Al Viro30d90492012-06-22 12:40:19 +0400516 struct file *file, unsigned flags,
Al Virob452a452018-06-08 13:06:28 -0400517 umode_t mode)
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800518{
519 int err;
520 struct inode *inode;
Max Reitzfcee2162020-05-06 17:44:12 +0200521 struct fuse_mount *fm = get_fuse_mount(dir);
Miklos Szeredi70781872014-12-12 09:49:05 +0100522 FUSE_ARGS(args);
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100523 struct fuse_forget_link *forget;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200524 struct fuse_create_in inarg;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800525 struct fuse_open_out outopen;
526 struct fuse_entry_out outentry;
Kirill Tkhaiebf84d02018-11-09 13:33:11 +0300527 struct fuse_inode *fi;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800528 struct fuse_file *ff;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800529
Miklos Szerediaf109bc2012-08-15 13:01:24 +0200530 /* Userspace expects S_IFREG in create mode */
531 BUG_ON((mode & S_IFMT) != S_IFREG);
532
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100533 forget = fuse_alloc_forget();
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200534 err = -ENOMEM;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100535 if (!forget)
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200536 goto out_err;
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700537
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700538 err = -ENOMEM;
Max Reitzfcee2162020-05-06 17:44:12 +0200539 ff = fuse_file_alloc(fm);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800540 if (!ff)
Miklos Szeredi70781872014-12-12 09:49:05 +0100541 goto out_put_forget_req;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800542
Max Reitzfcee2162020-05-06 17:44:12 +0200543 if (!fm->fc->dont_mask)
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200544 mode &= ~current_umask();
545
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800546 flags &= ~O_NOCTTY;
547 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700548 memset(&outentry, 0, sizeof(outentry));
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800549 inarg.flags = flags;
550 inarg.mode = mode;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200551 inarg.umask = current_umask();
Miklos Szeredid5b48542019-09-10 15:04:08 +0200552 args.opcode = FUSE_CREATE;
553 args.nodeid = get_node_id(dir);
554 args.in_numargs = 2;
555 args.in_args[0].size = sizeof(inarg);
556 args.in_args[0].value = &inarg;
557 args.in_args[1].size = entry->d_name.len + 1;
558 args.in_args[1].value = entry->d_name.name;
559 args.out_numargs = 2;
560 args.out_args[0].size = sizeof(outentry);
561 args.out_args[0].value = &outentry;
562 args.out_args[1].size = sizeof(outopen);
563 args.out_args[1].value = &outopen;
Max Reitzfcee2162020-05-06 17:44:12 +0200564 err = fuse_simple_request(fm, &args);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200565 if (err)
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800566 goto out_free_ff;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800567
568 err = -EIO;
Miklos Szeredieb59bd12019-11-12 11:49:04 +0100569 if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid) ||
570 fuse_invalid_attr(&outentry.attr))
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800571 goto out_free_ff;
572
Miklos Szeredic7b71432009-04-28 16:56:37 +0200573 ff->fh = outopen.fh;
574 ff->nodeid = outentry.nodeid;
575 ff->open_flags = outopen.open_flags;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800576 inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700577 &outentry.attr, entry_attr_timeout(&outentry), 0);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800578 if (!inode) {
579 flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
Kirill Tkhaiebf84d02018-11-09 13:33:11 +0300580 fuse_sync_release(NULL, ff, flags);
Max Reitzfcee2162020-05-06 17:44:12 +0200581 fuse_queue_forget(fm->fc, forget, outentry.nodeid, 1);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200582 err = -ENOMEM;
583 goto out_err;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800584 }
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100585 kfree(forget);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800586 d_instantiate(entry, inode);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700587 fuse_change_entry_timeout(entry, &outentry);
Miklos Szeredi261aaba72018-10-01 10:07:05 +0200588 fuse_dir_changed(dir);
Al Virobe12af32018-06-08 11:44:56 -0400589 err = finish_open(file, entry, generic_file_open);
Al Viro30d90492012-06-22 12:40:19 +0400590 if (err) {
Kirill Tkhaiebf84d02018-11-09 13:33:11 +0300591 fi = get_fuse_inode(inode);
592 fuse_sync_release(fi, ff, flags);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200593 } else {
Miklos Szeredi267d8442017-02-22 20:08:25 +0100594 file->private_data = ff;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200595 fuse_finish_open(inode, file);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800596 }
Al Virod9585272012-06-22 12:39:14 +0400597 return err;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800598
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200599out_free_ff:
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800600 fuse_file_free(ff);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200601out_put_forget_req:
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100602 kfree(forget);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200603out_err:
Al Virod9585272012-06-22 12:39:14 +0400604 return err;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200605}
606
607static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t);
Al Virod9585272012-06-22 12:39:14 +0400608static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
Al Viro30d90492012-06-22 12:40:19 +0400609 struct file *file, unsigned flags,
Al Viro44907d72018-06-08 13:32:02 -0400610 umode_t mode)
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200611{
612 int err;
613 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200614 struct dentry *res = NULL;
615
Miklos Szeredi36cf9ae2020-12-10 15:33:14 +0100616 if (fuse_is_bad(dir))
617 return -EIO;
618
Al Viro00699ad2016-07-05 09:44:53 -0400619 if (d_in_lookup(entry)) {
Al Viro00cd8dd2012-06-10 17:13:09 -0400620 res = fuse_lookup(dir, entry, 0);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200621 if (IS_ERR(res))
Al Virod9585272012-06-22 12:39:14 +0400622 return PTR_ERR(res);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200623
624 if (res)
625 entry = res;
626 }
627
David Howells2b0143b2015-03-17 22:25:59 +0000628 if (!(flags & O_CREAT) || d_really_is_positive(entry))
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200629 goto no_open;
630
631 /* Only creates */
Al Viro73a09dd2018-06-08 13:22:02 -0400632 file->f_mode |= FMODE_CREATED;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200633
634 if (fc->no_create)
635 goto mknod;
636
Al Virob452a452018-06-08 13:06:28 -0400637 err = fuse_create_open(dir, entry, file, flags, mode);
Al Virod9585272012-06-22 12:39:14 +0400638 if (err == -ENOSYS) {
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200639 fc->no_create = 1;
640 goto mknod;
641 }
642out_dput:
643 dput(res);
Al Virod9585272012-06-22 12:39:14 +0400644 return err;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200645
646mknod:
647 err = fuse_mknod(dir, entry, mode, 0);
Al Virod9585272012-06-22 12:39:14 +0400648 if (err)
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200649 goto out_dput;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200650no_open:
Al Viroe45198a2012-06-10 06:48:09 -0400651 return finish_no_open(file, res);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800652}
653
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800654/*
655 * Code shared between mknod, mkdir, symlink and link
656 */
Max Reitzfcee2162020-05-06 17:44:12 +0200657static int create_new_entry(struct fuse_mount *fm, struct fuse_args *args,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700658 struct inode *dir, struct dentry *entry,
Al Viro541af6a2011-07-26 03:17:33 -0400659 umode_t mode)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700660{
661 struct fuse_entry_out outarg;
662 struct inode *inode;
Al Viroc971e6a02018-05-28 18:27:19 -0400663 struct dentry *d;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700664 int err;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100665 struct fuse_forget_link *forget;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800666
Miklos Szeredi36cf9ae2020-12-10 15:33:14 +0100667 if (fuse_is_bad(dir))
668 return -EIO;
669
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100670 forget = fuse_alloc_forget();
Miklos Szeredi70781872014-12-12 09:49:05 +0100671 if (!forget)
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100672 return -ENOMEM;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700673
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700674 memset(&outarg, 0, sizeof(outarg));
Miklos Szeredid5b48542019-09-10 15:04:08 +0200675 args->nodeid = get_node_id(dir);
676 args->out_numargs = 1;
677 args->out_args[0].size = sizeof(outarg);
678 args->out_args[0].value = &outarg;
Max Reitzfcee2162020-05-06 17:44:12 +0200679 err = fuse_simple_request(fm, args);
Miklos Szeredi2d510132006-11-25 11:09:20 -0800680 if (err)
681 goto out_put_forget_req;
682
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800683 err = -EIO;
Miklos Szeredieb59bd12019-11-12 11:49:04 +0100684 if (invalid_nodeid(outarg.nodeid) || fuse_invalid_attr(&outarg.attr))
Miklos Szeredi2d510132006-11-25 11:09:20 -0800685 goto out_put_forget_req;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800686
687 if ((outarg.attr.mode ^ mode) & S_IFMT)
Miklos Szeredi2d510132006-11-25 11:09:20 -0800688 goto out_put_forget_req;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800689
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700690 inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700691 &outarg.attr, entry_attr_timeout(&outarg), 0);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700692 if (!inode) {
Max Reitzfcee2162020-05-06 17:44:12 +0200693 fuse_queue_forget(fm->fc, forget, outarg.nodeid, 1);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700694 return -ENOMEM;
695 }
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100696 kfree(forget);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700697
Al Viroc971e6a02018-05-28 18:27:19 -0400698 d_drop(entry);
699 d = d_splice_alias(inode, entry);
700 if (IS_ERR(d))
701 return PTR_ERR(d);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700702
Al Viroc971e6a02018-05-28 18:27:19 -0400703 if (d) {
704 fuse_change_entry_timeout(d, &outarg);
705 dput(d);
706 } else {
707 fuse_change_entry_timeout(entry, &outarg);
708 }
Miklos Szeredi261aaba72018-10-01 10:07:05 +0200709 fuse_dir_changed(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700710 return 0;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800711
Miklos Szeredi2d510132006-11-25 11:09:20 -0800712 out_put_forget_req:
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100713 kfree(forget);
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800714 return err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700715}
716
Al Viro1a67aaf2011-07-26 01:52:52 -0400717static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700718 dev_t rdev)
719{
720 struct fuse_mknod_in inarg;
Max Reitzfcee2162020-05-06 17:44:12 +0200721 struct fuse_mount *fm = get_fuse_mount(dir);
Miklos Szeredi70781872014-12-12 09:49:05 +0100722 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700723
Max Reitzfcee2162020-05-06 17:44:12 +0200724 if (!fm->fc->dont_mask)
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200725 mode &= ~current_umask();
726
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700727 memset(&inarg, 0, sizeof(inarg));
728 inarg.mode = mode;
729 inarg.rdev = new_encode_dev(rdev);
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200730 inarg.umask = current_umask();
Miklos Szeredid5b48542019-09-10 15:04:08 +0200731 args.opcode = FUSE_MKNOD;
732 args.in_numargs = 2;
733 args.in_args[0].size = sizeof(inarg);
734 args.in_args[0].value = &inarg;
735 args.in_args[1].size = entry->d_name.len + 1;
736 args.in_args[1].value = entry->d_name.name;
Max Reitzfcee2162020-05-06 17:44:12 +0200737 return create_new_entry(fm, &args, dir, entry, mode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700738}
739
Al Viro4acdaf22011-07-26 01:42:34 -0400740static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode,
Al Viroebfc3b42012-06-10 18:05:36 -0400741 bool excl)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700742{
743 return fuse_mknod(dir, entry, mode, 0);
744}
745
Al Viro18bb1db2011-07-26 01:41:39 -0400746static int fuse_mkdir(struct inode *dir, struct dentry *entry, umode_t mode)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700747{
748 struct fuse_mkdir_in inarg;
Max Reitzfcee2162020-05-06 17:44:12 +0200749 struct fuse_mount *fm = get_fuse_mount(dir);
Miklos Szeredi70781872014-12-12 09:49:05 +0100750 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700751
Max Reitzfcee2162020-05-06 17:44:12 +0200752 if (!fm->fc->dont_mask)
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200753 mode &= ~current_umask();
754
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700755 memset(&inarg, 0, sizeof(inarg));
756 inarg.mode = mode;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200757 inarg.umask = current_umask();
Miklos Szeredid5b48542019-09-10 15:04:08 +0200758 args.opcode = FUSE_MKDIR;
759 args.in_numargs = 2;
760 args.in_args[0].size = sizeof(inarg);
761 args.in_args[0].value = &inarg;
762 args.in_args[1].size = entry->d_name.len + 1;
763 args.in_args[1].value = entry->d_name.name;
Max Reitzfcee2162020-05-06 17:44:12 +0200764 return create_new_entry(fm, &args, dir, entry, S_IFDIR);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700765}
766
767static int fuse_symlink(struct inode *dir, struct dentry *entry,
768 const char *link)
769{
Max Reitzfcee2162020-05-06 17:44:12 +0200770 struct fuse_mount *fm = get_fuse_mount(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700771 unsigned len = strlen(link) + 1;
Miklos Szeredi70781872014-12-12 09:49:05 +0100772 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700773
Miklos Szeredid5b48542019-09-10 15:04:08 +0200774 args.opcode = FUSE_SYMLINK;
775 args.in_numargs = 2;
776 args.in_args[0].size = entry->d_name.len + 1;
777 args.in_args[0].value = entry->d_name.name;
778 args.in_args[1].size = len;
779 args.in_args[1].value = link;
Max Reitzfcee2162020-05-06 17:44:12 +0200780 return create_new_entry(fm, &args, dir, entry, S_IFLNK);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700781}
782
Seth Forshee703c7362016-08-29 08:46:36 -0500783void fuse_update_ctime(struct inode *inode)
Maxim Patlasov31f32672014-04-28 14:19:24 +0200784{
785 if (!IS_NOCMTIME(inode)) {
Deepa Dinamanic2050a42016-09-14 07:48:06 -0700786 inode->i_ctime = current_time(inode);
Maxim Patlasov31f32672014-04-28 14:19:24 +0200787 mark_inode_dirty_sync(inode);
788 }
789}
790
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700791static int fuse_unlink(struct inode *dir, struct dentry *entry)
792{
793 int err;
Max Reitzfcee2162020-05-06 17:44:12 +0200794 struct fuse_mount *fm = get_fuse_mount(dir);
Miklos Szeredi70781872014-12-12 09:49:05 +0100795 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700796
Miklos Szeredi36cf9ae2020-12-10 15:33:14 +0100797 if (fuse_is_bad(dir))
798 return -EIO;
799
Miklos Szeredid5b48542019-09-10 15:04:08 +0200800 args.opcode = FUSE_UNLINK;
801 args.nodeid = get_node_id(dir);
802 args.in_numargs = 1;
803 args.in_args[0].size = entry->d_name.len + 1;
804 args.in_args[0].value = entry->d_name.name;
Max Reitzfcee2162020-05-06 17:44:12 +0200805 err = fuse_simple_request(fm, &args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700806 if (!err) {
David Howells2b0143b2015-03-17 22:25:59 +0000807 struct inode *inode = d_inode(entry);
Miklos Szerediac45d612012-03-05 15:48:11 +0100808 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700809
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +0300810 spin_lock(&fi->lock);
Max Reitzfcee2162020-05-06 17:44:12 +0200811 fi->attr_version = atomic64_inc_return(&fm->fc->attr_version);
Miklos Szeredidfca7ce2013-02-04 15:57:42 +0100812 /*
813 * If i_nlink == 0 then unlink doesn't make sense, yet this can
814 * happen if userspace filesystem is careless. It would be
815 * difficult to enforce correct nlink usage so just ignore this
816 * condition here
817 */
818 if (inode->i_nlink > 0)
819 drop_nlink(inode);
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +0300820 spin_unlock(&fi->lock);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700821 fuse_invalidate_attr(inode);
Miklos Szeredi261aaba72018-10-01 10:07:05 +0200822 fuse_dir_changed(dir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800823 fuse_invalidate_entry_cache(entry);
Maxim Patlasov31f32672014-04-28 14:19:24 +0200824 fuse_update_ctime(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700825 } else if (err == -EINTR)
826 fuse_invalidate_entry(entry);
827 return err;
828}
829
830static int fuse_rmdir(struct inode *dir, struct dentry *entry)
831{
832 int err;
Max Reitzfcee2162020-05-06 17:44:12 +0200833 struct fuse_mount *fm = get_fuse_mount(dir);
Miklos Szeredi70781872014-12-12 09:49:05 +0100834 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700835
Miklos Szeredi36cf9ae2020-12-10 15:33:14 +0100836 if (fuse_is_bad(dir))
837 return -EIO;
838
Miklos Szeredid5b48542019-09-10 15:04:08 +0200839 args.opcode = FUSE_RMDIR;
840 args.nodeid = get_node_id(dir);
841 args.in_numargs = 1;
842 args.in_args[0].size = entry->d_name.len + 1;
843 args.in_args[0].value = entry->d_name.name;
Max Reitzfcee2162020-05-06 17:44:12 +0200844 err = fuse_simple_request(fm, &args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700845 if (!err) {
David Howells2b0143b2015-03-17 22:25:59 +0000846 clear_nlink(d_inode(entry));
Miklos Szeredi261aaba72018-10-01 10:07:05 +0200847 fuse_dir_changed(dir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800848 fuse_invalidate_entry_cache(entry);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700849 } else if (err == -EINTR)
850 fuse_invalidate_entry(entry);
851 return err;
852}
853
Miklos Szeredi1560c972014-04-28 16:43:44 +0200854static int fuse_rename_common(struct inode *olddir, struct dentry *oldent,
855 struct inode *newdir, struct dentry *newent,
856 unsigned int flags, int opcode, size_t argsize)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700857{
858 int err;
Miklos Szeredi1560c972014-04-28 16:43:44 +0200859 struct fuse_rename2_in inarg;
Max Reitzfcee2162020-05-06 17:44:12 +0200860 struct fuse_mount *fm = get_fuse_mount(olddir);
Miklos Szeredi70781872014-12-12 09:49:05 +0100861 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700862
Miklos Szeredi1560c972014-04-28 16:43:44 +0200863 memset(&inarg, 0, argsize);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700864 inarg.newdir = get_node_id(newdir);
Miklos Szeredi1560c972014-04-28 16:43:44 +0200865 inarg.flags = flags;
Miklos Szeredid5b48542019-09-10 15:04:08 +0200866 args.opcode = opcode;
867 args.nodeid = get_node_id(olddir);
868 args.in_numargs = 3;
869 args.in_args[0].size = argsize;
870 args.in_args[0].value = &inarg;
871 args.in_args[1].size = oldent->d_name.len + 1;
872 args.in_args[1].value = oldent->d_name.name;
873 args.in_args[2].size = newent->d_name.len + 1;
874 args.in_args[2].value = newent->d_name.name;
Max Reitzfcee2162020-05-06 17:44:12 +0200875 err = fuse_simple_request(fm, &args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700876 if (!err) {
Miklos Szeredi08b63302007-11-28 16:22:03 -0800877 /* ctime changes */
David Howells2b0143b2015-03-17 22:25:59 +0000878 fuse_invalidate_attr(d_inode(oldent));
879 fuse_update_ctime(d_inode(oldent));
Miklos Szeredi08b63302007-11-28 16:22:03 -0800880
Miklos Szeredi1560c972014-04-28 16:43:44 +0200881 if (flags & RENAME_EXCHANGE) {
David Howells2b0143b2015-03-17 22:25:59 +0000882 fuse_invalidate_attr(d_inode(newent));
883 fuse_update_ctime(d_inode(newent));
Miklos Szeredi1560c972014-04-28 16:43:44 +0200884 }
885
Miklos Szeredi261aaba72018-10-01 10:07:05 +0200886 fuse_dir_changed(olddir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700887 if (olddir != newdir)
Miklos Szeredi261aaba72018-10-01 10:07:05 +0200888 fuse_dir_changed(newdir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800889
890 /* newent will end up negative */
David Howells2b0143b2015-03-17 22:25:59 +0000891 if (!(flags & RENAME_EXCHANGE) && d_really_is_positive(newent)) {
892 fuse_invalidate_attr(d_inode(newent));
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800893 fuse_invalidate_entry_cache(newent);
David Howells2b0143b2015-03-17 22:25:59 +0000894 fuse_update_ctime(d_inode(newent));
Miklos Szeredi5219f342009-11-04 10:24:52 +0100895 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700896 } else if (err == -EINTR) {
897 /* If request was interrupted, DEITY only knows if the
898 rename actually took place. If the invalidation
899 fails (e.g. some process has CWD under the renamed
900 directory), then there can be inconsistency between
901 the dcache and the real filesystem. Tough luck. */
902 fuse_invalidate_entry(oldent);
David Howells2b0143b2015-03-17 22:25:59 +0000903 if (d_really_is_positive(newent))
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700904 fuse_invalidate_entry(newent);
905 }
906
907 return err;
908}
909
Miklos Szeredi1560c972014-04-28 16:43:44 +0200910static int fuse_rename2(struct inode *olddir, struct dentry *oldent,
911 struct inode *newdir, struct dentry *newent,
912 unsigned int flags)
913{
914 struct fuse_conn *fc = get_fuse_conn(olddir);
915 int err;
916
Miklos Szeredi36cf9ae2020-12-10 15:33:14 +0100917 if (fuse_is_bad(olddir))
918 return -EIO;
919
Vivek Goyal519525f2020-02-05 08:15:46 -0500920 if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT))
Miklos Szeredi1560c972014-04-28 16:43:44 +0200921 return -EINVAL;
922
Miklos Szeredi4237ba42014-07-10 10:50:19 +0200923 if (flags) {
924 if (fc->no_rename2 || fc->minor < 23)
925 return -EINVAL;
Miklos Szeredi1560c972014-04-28 16:43:44 +0200926
Miklos Szeredi4237ba42014-07-10 10:50:19 +0200927 err = fuse_rename_common(olddir, oldent, newdir, newent, flags,
928 FUSE_RENAME2,
929 sizeof(struct fuse_rename2_in));
930 if (err == -ENOSYS) {
931 fc->no_rename2 = 1;
932 err = -EINVAL;
933 }
934 } else {
935 err = fuse_rename_common(olddir, oldent, newdir, newent, 0,
936 FUSE_RENAME,
937 sizeof(struct fuse_rename_in));
Miklos Szeredi1560c972014-04-28 16:43:44 +0200938 }
Miklos Szeredi1560c972014-04-28 16:43:44 +0200939
Miklos Szeredi4237ba42014-07-10 10:50:19 +0200940 return err;
941}
942
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700943static int fuse_link(struct dentry *entry, struct inode *newdir,
944 struct dentry *newent)
945{
946 int err;
947 struct fuse_link_in inarg;
David Howells2b0143b2015-03-17 22:25:59 +0000948 struct inode *inode = d_inode(entry);
Max Reitzfcee2162020-05-06 17:44:12 +0200949 struct fuse_mount *fm = get_fuse_mount(inode);
Miklos Szeredi70781872014-12-12 09:49:05 +0100950 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700951
952 memset(&inarg, 0, sizeof(inarg));
953 inarg.oldnodeid = get_node_id(inode);
Miklos Szeredid5b48542019-09-10 15:04:08 +0200954 args.opcode = FUSE_LINK;
955 args.in_numargs = 2;
956 args.in_args[0].size = sizeof(inarg);
957 args.in_args[0].value = &inarg;
958 args.in_args[1].size = newent->d_name.len + 1;
959 args.in_args[1].value = newent->d_name.name;
Max Reitzfcee2162020-05-06 17:44:12 +0200960 err = create_new_entry(fm, &args, newdir, newent, inode->i_mode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700961 /* Contrary to "normal" filesystems it can happen that link
962 makes two "logical" inodes point to the same "physical"
963 inode. We invalidate the attributes of the old one, so it
964 will reflect changes in the backing inode (link count,
965 etc.)
966 */
Miklos Szerediac45d612012-03-05 15:48:11 +0100967 if (!err) {
968 struct fuse_inode *fi = get_fuse_inode(inode);
969
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +0300970 spin_lock(&fi->lock);
Max Reitzfcee2162020-05-06 17:44:12 +0200971 fi->attr_version = atomic64_inc_return(&fm->fc->attr_version);
Miklos Szeredic634da72019-11-12 11:49:04 +0100972 if (likely(inode->i_nlink < UINT_MAX))
973 inc_nlink(inode);
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +0300974 spin_unlock(&fi->lock);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700975 fuse_invalidate_attr(inode);
Maxim Patlasov31f32672014-04-28 14:19:24 +0200976 fuse_update_ctime(inode);
Miklos Szerediac45d612012-03-05 15:48:11 +0100977 } else if (err == -EINTR) {
978 fuse_invalidate_attr(inode);
979 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700980 return err;
981}
982
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700983static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
984 struct kstat *stat)
985{
Miklos Szeredi203627b2012-05-10 19:49:38 +0400986 unsigned int blkbits;
Pavel Emelyanov83732002013-10-10 17:10:46 +0400987 struct fuse_conn *fc = get_fuse_conn(inode);
988
989 /* see the comment in fuse_change_attributes() */
Maxim Patlasovb0aa7602013-12-26 19:51:11 +0400990 if (fc->writeback_cache && S_ISREG(inode->i_mode)) {
Pavel Emelyanov83732002013-10-10 17:10:46 +0400991 attr->size = i_size_read(inode);
Maxim Patlasovb0aa7602013-12-26 19:51:11 +0400992 attr->mtime = inode->i_mtime.tv_sec;
993 attr->mtimensec = inode->i_mtime.tv_nsec;
Maxim Patlasov31f32672014-04-28 14:19:24 +0200994 attr->ctime = inode->i_ctime.tv_sec;
995 attr->ctimensec = inode->i_ctime.tv_nsec;
Maxim Patlasovb0aa7602013-12-26 19:51:11 +0400996 }
Miklos Szeredi203627b2012-05-10 19:49:38 +0400997
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700998 stat->dev = inode->i_sb->s_dev;
999 stat->ino = attr->ino;
1000 stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
1001 stat->nlink = attr->nlink;
Eric W. Biederman8cb08322018-02-21 11:18:07 -06001002 stat->uid = make_kuid(fc->user_ns, attr->uid);
1003 stat->gid = make_kgid(fc->user_ns, attr->gid);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -07001004 stat->rdev = inode->i_rdev;
1005 stat->atime.tv_sec = attr->atime;
1006 stat->atime.tv_nsec = attr->atimensec;
1007 stat->mtime.tv_sec = attr->mtime;
1008 stat->mtime.tv_nsec = attr->mtimensec;
1009 stat->ctime.tv_sec = attr->ctime;
1010 stat->ctime.tv_nsec = attr->ctimensec;
1011 stat->size = attr->size;
1012 stat->blocks = attr->blocks;
Miklos Szeredi203627b2012-05-10 19:49:38 +04001013
1014 if (attr->blksize != 0)
1015 blkbits = ilog2(attr->blksize);
1016 else
1017 blkbits = inode->i_sb->s_blocksize_bits;
1018
1019 stat->blksize = 1 << blkbits;
Miklos Szeredi1fb69e72007-10-18 03:06:58 -07001020}
1021
Miklos Szeredic79e3222007-10-18 03:06:59 -07001022static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
1023 struct file *file)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001024{
1025 int err;
Miklos Szeredic79e3222007-10-18 03:06:59 -07001026 struct fuse_getattr_in inarg;
1027 struct fuse_attr_out outarg;
Max Reitzfcee2162020-05-06 17:44:12 +02001028 struct fuse_mount *fm = get_fuse_mount(inode);
Miklos Szeredi70781872014-12-12 09:49:05 +01001029 FUSE_ARGS(args);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -07001030 u64 attr_version;
1031
Max Reitzfcee2162020-05-06 17:44:12 +02001032 attr_version = fuse_get_attr_version(fm->fc);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -07001033
Miklos Szeredic79e3222007-10-18 03:06:59 -07001034 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -07001035 memset(&outarg, 0, sizeof(outarg));
Miklos Szeredic79e3222007-10-18 03:06:59 -07001036 /* Directories have separate file-handle space */
1037 if (file && S_ISREG(inode->i_mode)) {
1038 struct fuse_file *ff = file->private_data;
1039
1040 inarg.getattr_flags |= FUSE_GETATTR_FH;
1041 inarg.fh = ff->fh;
1042 }
Miklos Szeredid5b48542019-09-10 15:04:08 +02001043 args.opcode = FUSE_GETATTR;
1044 args.nodeid = get_node_id(inode);
1045 args.in_numargs = 1;
1046 args.in_args[0].size = sizeof(inarg);
1047 args.in_args[0].value = &inarg;
1048 args.out_numargs = 1;
1049 args.out_args[0].size = sizeof(outarg);
1050 args.out_args[0].value = &outarg;
Max Reitzfcee2162020-05-06 17:44:12 +02001051 err = fuse_simple_request(fm, &args);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001052 if (!err) {
Miklos Szeredieb59bd12019-11-12 11:49:04 +01001053 if (fuse_invalid_attr(&outarg.attr) ||
1054 (inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
Miklos Szeredi36cf9ae2020-12-10 15:33:14 +01001055 fuse_make_bad(inode);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001056 err = -EIO;
1057 } else {
Miklos Szeredic79e3222007-10-18 03:06:59 -07001058 fuse_change_attributes(inode, &outarg.attr,
1059 attr_timeout(&outarg),
Miklos Szeredi1fb69e72007-10-18 03:06:58 -07001060 attr_version);
1061 if (stat)
Miklos Szeredic79e3222007-10-18 03:06:59 -07001062 fuse_fillattr(inode, &outarg.attr, stat);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001063 }
1064 }
1065 return err;
1066}
1067
Miklos Szeredi5b97eea2017-09-12 16:57:54 +02001068static int fuse_update_get_attr(struct inode *inode, struct file *file,
Miklos Szeredi2f1e8192018-10-15 15:43:06 +02001069 struct kstat *stat, u32 request_mask,
1070 unsigned int flags)
Miklos Szeredibcb4be82007-11-28 16:21:59 -08001071{
1072 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredi5b97eea2017-09-12 16:57:54 +02001073 int err = 0;
Miklos Szeredibf5c1892018-03-20 17:11:44 +01001074 bool sync;
Miklos Szeredibcb4be82007-11-28 16:21:59 -08001075
Miklos Szeredibf5c1892018-03-20 17:11:44 +01001076 if (flags & AT_STATX_FORCE_SYNC)
1077 sync = true;
1078 else if (flags & AT_STATX_DONT_SYNC)
1079 sync = false;
Miklos Szeredi2f1e8192018-10-15 15:43:06 +02001080 else if (request_mask & READ_ONCE(fi->inval_mask))
1081 sync = true;
Miklos Szeredibf5c1892018-03-20 17:11:44 +01001082 else
1083 sync = time_before64(fi->i_time, get_jiffies_64());
1084
1085 if (sync) {
Seth Forshee60bcc882016-08-29 08:46:37 -05001086 forget_all_cached_acls(inode);
Miklos Szeredibcb4be82007-11-28 16:21:59 -08001087 err = fuse_do_getattr(inode, stat, file);
Miklos Szeredi5b97eea2017-09-12 16:57:54 +02001088 } else if (stat) {
1089 generic_fillattr(inode, stat);
1090 stat->mode = fi->orig_i_mode;
1091 stat->ino = fi->orig_ino;
Miklos Szeredibcb4be82007-11-28 16:21:59 -08001092 }
1093
Miklos Szeredibcb4be82007-11-28 16:21:59 -08001094 return err;
1095}
1096
Miklos Szeredi5b97eea2017-09-12 16:57:54 +02001097int fuse_update_attributes(struct inode *inode, struct file *file)
1098{
Miklos Szeredi802dc042018-10-15 15:43:06 +02001099 /* Do *not* need to get atime for internal purposes */
1100 return fuse_update_get_attr(inode, file, NULL,
1101 STATX_BASIC_STATS & ~STATX_ATIME, 0);
Miklos Szeredi5b97eea2017-09-12 16:57:54 +02001102}
1103
Max Reitzfcee2162020-05-06 17:44:12 +02001104int fuse_reverse_inval_entry(struct fuse_conn *fc, u64 parent_nodeid,
John Muir451d0f52011-12-06 21:50:06 +01001105 u64 child_nodeid, struct qstr *name)
John Muir3b463ae2009-05-31 11:13:57 -04001106{
1107 int err = -ENOTDIR;
1108 struct inode *parent;
1109 struct dentry *dir;
1110 struct dentry *entry;
1111
Max Reitzfcee2162020-05-06 17:44:12 +02001112 parent = fuse_ilookup(fc, parent_nodeid, NULL);
John Muir3b463ae2009-05-31 11:13:57 -04001113 if (!parent)
1114 return -ENOENT;
1115
Al Viro59551022016-01-22 15:40:57 -05001116 inode_lock(parent);
John Muir3b463ae2009-05-31 11:13:57 -04001117 if (!S_ISDIR(parent->i_mode))
1118 goto unlock;
1119
1120 err = -ENOENT;
1121 dir = d_find_alias(parent);
1122 if (!dir)
1123 goto unlock;
1124
Linus Torvalds8387ff22016-06-10 07:51:30 -07001125 name->hash = full_name_hash(dir, name->name, name->len);
John Muir3b463ae2009-05-31 11:13:57 -04001126 entry = d_lookup(dir, name);
1127 dput(dir);
1128 if (!entry)
1129 goto unlock;
1130
Miklos Szeredi261aaba72018-10-01 10:07:05 +02001131 fuse_dir_changed(parent);
John Muir3b463ae2009-05-31 11:13:57 -04001132 fuse_invalidate_entry(entry);
John Muir451d0f52011-12-06 21:50:06 +01001133
David Howells2b0143b2015-03-17 22:25:59 +00001134 if (child_nodeid != 0 && d_really_is_positive(entry)) {
Al Viro59551022016-01-22 15:40:57 -05001135 inode_lock(d_inode(entry));
David Howells2b0143b2015-03-17 22:25:59 +00001136 if (get_node_id(d_inode(entry)) != child_nodeid) {
John Muir451d0f52011-12-06 21:50:06 +01001137 err = -ENOENT;
1138 goto badentry;
1139 }
1140 if (d_mountpoint(entry)) {
1141 err = -EBUSY;
1142 goto badentry;
1143 }
David Howellse36cb0b2015-01-29 12:02:35 +00001144 if (d_is_dir(entry)) {
John Muir451d0f52011-12-06 21:50:06 +01001145 shrink_dcache_parent(entry);
1146 if (!simple_empty(entry)) {
1147 err = -ENOTEMPTY;
1148 goto badentry;
1149 }
David Howells2b0143b2015-03-17 22:25:59 +00001150 d_inode(entry)->i_flags |= S_DEAD;
John Muir451d0f52011-12-06 21:50:06 +01001151 }
1152 dont_mount(entry);
David Howells2b0143b2015-03-17 22:25:59 +00001153 clear_nlink(d_inode(entry));
John Muir451d0f52011-12-06 21:50:06 +01001154 err = 0;
1155 badentry:
Al Viro59551022016-01-22 15:40:57 -05001156 inode_unlock(d_inode(entry));
John Muir451d0f52011-12-06 21:50:06 +01001157 if (!err)
1158 d_delete(entry);
1159 } else {
1160 err = 0;
1161 }
John Muir3b463ae2009-05-31 11:13:57 -04001162 dput(entry);
John Muir3b463ae2009-05-31 11:13:57 -04001163
1164 unlock:
Al Viro59551022016-01-22 15:40:57 -05001165 inode_unlock(parent);
John Muir3b463ae2009-05-31 11:13:57 -04001166 iput(parent);
1167 return err;
1168}
1169
Miklos Szeredi87729a52005-09-09 13:10:34 -07001170/*
1171 * Calling into a user-controlled filesystem gives the filesystem
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001172 * daemon ptrace-like capabilities over the current process. This
Miklos Szeredi87729a52005-09-09 13:10:34 -07001173 * means, that the filesystem daemon is able to record the exact
1174 * filesystem operations performed, and can also control the behavior
1175 * of the requester process in otherwise impossible ways. For example
1176 * it can delay the operation for arbitrary length of time allowing
1177 * DoS against the requester.
1178 *
1179 * For this reason only those processes can call into the filesystem,
1180 * for which the owner of the mount has ptrace privilege. This
1181 * excludes processes started by other users, suid or sgid processes.
1182 */
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001183int fuse_allow_current_process(struct fuse_conn *fc)
Miklos Szeredi87729a52005-09-09 13:10:34 -07001184{
David Howellsc69e8d92008-11-14 10:39:19 +11001185 const struct cred *cred;
David Howellsc69e8d92008-11-14 10:39:19 +11001186
Miklos Szeredi29433a22016-10-01 07:32:32 +02001187 if (fc->allow_other)
Seth Forshee73f03c22017-12-22 15:32:33 +01001188 return current_in_userns(fc->user_ns);
Miklos Szeredi87729a52005-09-09 13:10:34 -07001189
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001190 cred = current_cred();
Eric W. Biederman499dcf22012-02-07 16:26:03 -08001191 if (uid_eq(cred->euid, fc->user_id) &&
1192 uid_eq(cred->suid, fc->user_id) &&
1193 uid_eq(cred->uid, fc->user_id) &&
1194 gid_eq(cred->egid, fc->group_id) &&
1195 gid_eq(cred->sgid, fc->group_id) &&
1196 gid_eq(cred->gid, fc->group_id))
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001197 return 1;
Miklos Szeredi87729a52005-09-09 13:10:34 -07001198
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001199 return 0;
Miklos Szeredi87729a52005-09-09 13:10:34 -07001200}
1201
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001202static int fuse_access(struct inode *inode, int mask)
1203{
Max Reitzfcee2162020-05-06 17:44:12 +02001204 struct fuse_mount *fm = get_fuse_mount(inode);
Miklos Szeredi70781872014-12-12 09:49:05 +01001205 FUSE_ARGS(args);
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001206 struct fuse_access_in inarg;
1207 int err;
1208
Miklos Szeredi698fa1d2013-10-01 16:41:23 +02001209 BUG_ON(mask & MAY_NOT_BLOCK);
1210
Max Reitzfcee2162020-05-06 17:44:12 +02001211 if (fm->fc->no_access)
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001212 return 0;
1213
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001214 memset(&inarg, 0, sizeof(inarg));
Al Viroe6305c42008-07-15 21:03:57 -04001215 inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC);
Miklos Szeredid5b48542019-09-10 15:04:08 +02001216 args.opcode = FUSE_ACCESS;
1217 args.nodeid = get_node_id(inode);
1218 args.in_numargs = 1;
1219 args.in_args[0].size = sizeof(inarg);
1220 args.in_args[0].value = &inarg;
Max Reitzfcee2162020-05-06 17:44:12 +02001221 err = fuse_simple_request(fm, &args);
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001222 if (err == -ENOSYS) {
Max Reitzfcee2162020-05-06 17:44:12 +02001223 fm->fc->no_access = 1;
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001224 err = 0;
1225 }
1226 return err;
1227}
1228
Al Viro10556cb22011-06-20 19:28:19 -04001229static int fuse_perm_getattr(struct inode *inode, int mask)
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001230{
Al Viro10556cb22011-06-20 19:28:19 -04001231 if (mask & MAY_NOT_BLOCK)
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001232 return -ECHILD;
1233
Seth Forshee60bcc882016-08-29 08:46:37 -05001234 forget_all_cached_acls(inode);
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001235 return fuse_do_getattr(inode, NULL, NULL);
1236}
1237
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001238/*
1239 * Check permission. The two basic access models of FUSE are:
1240 *
1241 * 1) Local access checking ('default_permissions' mount option) based
1242 * on file mode. This is the plain old disk filesystem permission
1243 * modell.
1244 *
1245 * 2) "Remote" access checking, where server is responsible for
1246 * checking permission in each inode operation. An exception to this
1247 * is if ->permission() was invoked from sys_access() in which case an
1248 * access request is sent. Execute permission is still checked
1249 * locally based on file mode.
1250 */
Al Viro10556cb22011-06-20 19:28:19 -04001251static int fuse_permission(struct inode *inode, int mask)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001252{
1253 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi244f6382007-10-16 23:31:02 -07001254 bool refreshed = false;
1255 int err = 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001256
Miklos Szeredi36cf9ae2020-12-10 15:33:14 +01001257 if (fuse_is_bad(inode))
1258 return -EIO;
1259
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001260 if (!fuse_allow_current_process(fc))
Miklos Szeredie5e55582005-09-09 13:10:28 -07001261 return -EACCES;
Miklos Szeredi244f6382007-10-16 23:31:02 -07001262
1263 /*
Miklos Szeredie8e96152007-10-16 23:31:06 -07001264 * If attributes are needed, refresh them before proceeding
Miklos Szeredi244f6382007-10-16 23:31:02 -07001265 */
Miklos Szeredi29433a22016-10-01 07:32:32 +02001266 if (fc->default_permissions ||
Miklos Szeredie8e96152007-10-16 23:31:06 -07001267 ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001268 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredid233c7d2018-12-03 10:14:43 +01001269 u32 perm_mask = STATX_MODE | STATX_UID | STATX_GID;
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001270
Miklos Szeredid233c7d2018-12-03 10:14:43 +01001271 if (perm_mask & READ_ONCE(fi->inval_mask) ||
1272 time_before64(fi->i_time, get_jiffies_64())) {
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001273 refreshed = true;
1274
Al Viro10556cb22011-06-20 19:28:19 -04001275 err = fuse_perm_getattr(inode, mask);
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001276 if (err)
1277 return err;
1278 }
Miklos Szeredi244f6382007-10-16 23:31:02 -07001279 }
1280
Miklos Szeredi29433a22016-10-01 07:32:32 +02001281 if (fc->default_permissions) {
Al Viro2830ba72011-06-20 19:16:29 -04001282 err = generic_permission(inode, mask);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001283
1284 /* If permission is denied, try to refresh file
1285 attributes. This is also needed, because the root
1286 node will at first have no permissions */
Miklos Szeredi244f6382007-10-16 23:31:02 -07001287 if (err == -EACCES && !refreshed) {
Al Viro10556cb22011-06-20 19:28:19 -04001288 err = fuse_perm_getattr(inode, mask);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001289 if (!err)
Al Viro2830ba72011-06-20 19:16:29 -04001290 err = generic_permission(inode, mask);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001291 }
1292
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001293 /* Note: the opposite of the above test does not
1294 exist. So if permissions are revoked this won't be
1295 noticed immediately, only after the attribute
1296 timeout has expired */
Eric Paris9cfcac82010-07-23 11:43:51 -04001297 } else if (mask & (MAY_ACCESS | MAY_CHDIR)) {
Miklos Szeredie8e96152007-10-16 23:31:06 -07001298 err = fuse_access(inode, mask);
1299 } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
1300 if (!(inode->i_mode & S_IXUGO)) {
1301 if (refreshed)
1302 return -EACCES;
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001303
Al Viro10556cb22011-06-20 19:28:19 -04001304 err = fuse_perm_getattr(inode, mask);
Miklos Szeredie8e96152007-10-16 23:31:06 -07001305 if (!err && !(inode->i_mode & S_IXUGO))
1306 return -EACCES;
1307 }
Miklos Szeredie5e55582005-09-09 13:10:28 -07001308 }
Miklos Szeredi244f6382007-10-16 23:31:02 -07001309 return err;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001310}
1311
Dan Schatzberg5571f1e2018-10-11 08:17:00 -07001312static int fuse_readlink_page(struct inode *inode, struct page *page)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001313{
Max Reitzfcee2162020-05-06 17:44:12 +02001314 struct fuse_mount *fm = get_fuse_mount(inode);
Miklos Szeredi4c29afe2019-09-10 15:04:09 +02001315 struct fuse_page_desc desc = { .length = PAGE_SIZE - 1 };
1316 struct fuse_args_pages ap = {
1317 .num_pages = 1,
1318 .pages = &page,
1319 .descs = &desc,
1320 };
1321 char *link;
1322 ssize_t res;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001323
Miklos Szeredi4c29afe2019-09-10 15:04:09 +02001324 ap.args.opcode = FUSE_READLINK;
1325 ap.args.nodeid = get_node_id(inode);
1326 ap.args.out_pages = true;
1327 ap.args.out_argvar = true;
1328 ap.args.page_zeroing = true;
1329 ap.args.out_numargs = 1;
1330 ap.args.out_args[0].size = desc.length;
Max Reitzfcee2162020-05-06 17:44:12 +02001331 res = fuse_simple_request(fm, &ap.args);
Al Viro6b255392015-11-17 10:20:54 -05001332
Andrew Gallagher451418f2013-11-05 03:55:43 -08001333 fuse_invalidate_atime(inode);
Dan Schatzberg5571f1e2018-10-11 08:17:00 -07001334
Miklos Szeredi4c29afe2019-09-10 15:04:09 +02001335 if (res < 0)
1336 return res;
1337
1338 if (WARN_ON(res >= PAGE_SIZE))
1339 return -EIO;
1340
1341 link = page_address(page);
1342 link[res] = '\0';
1343
1344 return 0;
Dan Schatzberg5571f1e2018-10-11 08:17:00 -07001345}
1346
1347static const char *fuse_get_link(struct dentry *dentry, struct inode *inode,
1348 struct delayed_call *callback)
1349{
1350 struct fuse_conn *fc = get_fuse_conn(inode);
1351 struct page *page;
1352 int err;
1353
1354 err = -EIO;
Miklos Szeredi36cf9ae2020-12-10 15:33:14 +01001355 if (fuse_is_bad(inode))
Dan Schatzberg5571f1e2018-10-11 08:17:00 -07001356 goto out_err;
1357
1358 if (fc->cache_symlinks)
1359 return page_get_link(dentry, inode, callback);
1360
1361 err = -ECHILD;
1362 if (!dentry)
1363 goto out_err;
1364
1365 page = alloc_page(GFP_KERNEL);
1366 err = -ENOMEM;
1367 if (!page)
1368 goto out_err;
1369
1370 err = fuse_readlink_page(inode, page);
1371 if (err) {
1372 __free_page(page);
1373 goto out_err;
1374 }
1375
1376 set_delayed_call(callback, page_put_link, page);
1377
1378 return page_address(page);
1379
1380out_err:
1381 return ERR_PTR(err);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001382}
1383
Miklos Szeredie5e55582005-09-09 13:10:28 -07001384static int fuse_dir_open(struct inode *inode, struct file *file)
1385{
Miklos Szeredi91fe96b2009-04-28 16:56:37 +02001386 return fuse_open_common(inode, file, true);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001387}
1388
1389static int fuse_dir_release(struct inode *inode, struct file *file)
1390{
Chad Austin2e64ff12018-12-10 10:54:52 -08001391 fuse_release_common(file, true);
Miklos Szeredi8b0797a2009-04-28 16:56:39 +02001392
1393 return 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001394}
1395
Josef Bacik02c24a82011-07-16 20:44:56 -04001396static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end,
1397 int datasync)
Miklos Szeredi82547982005-09-09 13:10:38 -07001398{
Miklos Szeredia9c2d1e2018-12-03 10:14:43 +01001399 struct inode *inode = file->f_mapping->host;
1400 struct fuse_conn *fc = get_fuse_conn(inode);
1401 int err;
1402
Miklos Szeredi36cf9ae2020-12-10 15:33:14 +01001403 if (fuse_is_bad(inode))
Miklos Szeredia9c2d1e2018-12-03 10:14:43 +01001404 return -EIO;
1405
1406 if (fc->no_fsyncdir)
1407 return 0;
1408
1409 inode_lock(inode);
1410 err = fuse_fsync_common(file, start, end, datasync, FUSE_FSYNCDIR);
1411 if (err == -ENOSYS) {
1412 fc->no_fsyncdir = 1;
1413 err = 0;
1414 }
1415 inode_unlock(inode);
1416
1417 return err;
Miklos Szeredi82547982005-09-09 13:10:38 -07001418}
1419
Miklos Szeredib18da0c2011-12-13 11:58:49 +01001420static long fuse_dir_ioctl(struct file *file, unsigned int cmd,
1421 unsigned long arg)
1422{
1423 struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1424
1425 /* FUSE_IOCTL_DIR only supported for API version >= 7.18 */
1426 if (fc->minor < 18)
1427 return -ENOTTY;
1428
1429 return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR);
1430}
1431
1432static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd,
1433 unsigned long arg)
1434{
1435 struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1436
1437 if (fc->minor < 18)
1438 return -ENOTTY;
1439
1440 return fuse_ioctl_common(file, cmd, arg,
1441 FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR);
1442}
1443
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001444static bool update_mtime(unsigned ivalid, bool trust_local_mtime)
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001445{
1446 /* Always update if mtime is explicitly set */
1447 if (ivalid & ATTR_MTIME_SET)
1448 return true;
1449
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001450 /* Or if kernel i_mtime is the official one */
1451 if (trust_local_mtime)
1452 return true;
1453
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001454 /* If it's an open(O_TRUNC) or an ftruncate(), don't update */
1455 if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
1456 return false;
1457
1458 /* In all other cases update */
1459 return true;
1460}
1461
Eric W. Biederman8cb08322018-02-21 11:18:07 -06001462static void iattr_to_fattr(struct fuse_conn *fc, struct iattr *iattr,
1463 struct fuse_setattr_in *arg, bool trust_local_cmtime)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001464{
1465 unsigned ivalid = iattr->ia_valid;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001466
1467 if (ivalid & ATTR_MODE)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001468 arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001469 if (ivalid & ATTR_UID)
Eric W. Biederman8cb08322018-02-21 11:18:07 -06001470 arg->valid |= FATTR_UID, arg->uid = from_kuid(fc->user_ns, iattr->ia_uid);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001471 if (ivalid & ATTR_GID)
Eric W. Biederman8cb08322018-02-21 11:18:07 -06001472 arg->valid |= FATTR_GID, arg->gid = from_kgid(fc->user_ns, iattr->ia_gid);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001473 if (ivalid & ATTR_SIZE)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001474 arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001475 if (ivalid & ATTR_ATIME) {
1476 arg->valid |= FATTR_ATIME;
Miklos Szeredibefc6492005-11-07 00:59:52 -08001477 arg->atime = iattr->ia_atime.tv_sec;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001478 arg->atimensec = iattr->ia_atime.tv_nsec;
1479 if (!(ivalid & ATTR_ATIME_SET))
1480 arg->valid |= FATTR_ATIME_NOW;
1481 }
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001482 if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, trust_local_cmtime)) {
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001483 arg->valid |= FATTR_MTIME;
Miklos Szeredibefc6492005-11-07 00:59:52 -08001484 arg->mtime = iattr->ia_mtime.tv_sec;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001485 arg->mtimensec = iattr->ia_mtime.tv_nsec;
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001486 if (!(ivalid & ATTR_MTIME_SET) && !trust_local_cmtime)
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001487 arg->valid |= FATTR_MTIME_NOW;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001488 }
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001489 if ((ivalid & ATTR_CTIME) && trust_local_cmtime) {
1490 arg->valid |= FATTR_CTIME;
1491 arg->ctime = iattr->ia_ctime.tv_sec;
1492 arg->ctimensec = iattr->ia_ctime.tv_nsec;
1493 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001494}
1495
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001496/*
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001497 * Prevent concurrent writepages on inode
1498 *
1499 * This is done by adding a negative bias to the inode write counter
1500 * and waiting for all pending writes to finish.
1501 */
1502void fuse_set_nowrite(struct inode *inode)
1503{
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001504 struct fuse_inode *fi = get_fuse_inode(inode);
1505
Al Viro59551022016-01-22 15:40:57 -05001506 BUG_ON(!inode_is_locked(inode));
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001507
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +03001508 spin_lock(&fi->lock);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001509 BUG_ON(fi->writectr < 0);
1510 fi->writectr += FUSE_NOWRITE;
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +03001511 spin_unlock(&fi->lock);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001512 wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE);
1513}
1514
1515/*
1516 * Allow writepages on inode
1517 *
1518 * Remove the bias from the writecounter and send any queued
1519 * writepages.
1520 */
1521static void __fuse_release_nowrite(struct inode *inode)
1522{
1523 struct fuse_inode *fi = get_fuse_inode(inode);
1524
1525 BUG_ON(fi->writectr != FUSE_NOWRITE);
1526 fi->writectr = 0;
1527 fuse_flush_writepages(inode);
1528}
1529
1530void fuse_release_nowrite(struct inode *inode)
1531{
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +03001532 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001533
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +03001534 spin_lock(&fi->lock);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001535 __fuse_release_nowrite(inode);
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +03001536 spin_unlock(&fi->lock);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001537}
1538
Miklos Szeredi70781872014-12-12 09:49:05 +01001539static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_args *args,
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001540 struct inode *inode,
1541 struct fuse_setattr_in *inarg_p,
1542 struct fuse_attr_out *outarg_p)
1543{
Miklos Szeredid5b48542019-09-10 15:04:08 +02001544 args->opcode = FUSE_SETATTR;
1545 args->nodeid = get_node_id(inode);
1546 args->in_numargs = 1;
1547 args->in_args[0].size = sizeof(*inarg_p);
1548 args->in_args[0].value = inarg_p;
1549 args->out_numargs = 1;
1550 args->out_args[0].size = sizeof(*outarg_p);
1551 args->out_args[0].value = outarg_p;
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001552}
1553
1554/*
1555 * Flush inode->i_mtime to the server
1556 */
Maxim Patlasovab9e13f2014-04-28 14:19:24 +02001557int fuse_flush_times(struct inode *inode, struct fuse_file *ff)
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001558{
Max Reitzfcee2162020-05-06 17:44:12 +02001559 struct fuse_mount *fm = get_fuse_mount(inode);
Miklos Szeredi70781872014-12-12 09:49:05 +01001560 FUSE_ARGS(args);
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001561 struct fuse_setattr_in inarg;
1562 struct fuse_attr_out outarg;
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001563
1564 memset(&inarg, 0, sizeof(inarg));
1565 memset(&outarg, 0, sizeof(outarg));
1566
Maxim Patlasovab9e13f2014-04-28 14:19:24 +02001567 inarg.valid = FATTR_MTIME;
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001568 inarg.mtime = inode->i_mtime.tv_sec;
1569 inarg.mtimensec = inode->i_mtime.tv_nsec;
Max Reitzfcee2162020-05-06 17:44:12 +02001570 if (fm->fc->minor >= 23) {
Maxim Patlasovab9e13f2014-04-28 14:19:24 +02001571 inarg.valid |= FATTR_CTIME;
1572 inarg.ctime = inode->i_ctime.tv_sec;
1573 inarg.ctimensec = inode->i_ctime.tv_nsec;
1574 }
Miklos Szeredi1e18bda2014-04-28 14:19:23 +02001575 if (ff) {
1576 inarg.valid |= FATTR_FH;
1577 inarg.fh = ff->fh;
1578 }
Max Reitzfcee2162020-05-06 17:44:12 +02001579 fuse_setattr_fill(fm->fc, &args, inode, &inarg, &outarg);
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001580
Max Reitzfcee2162020-05-06 17:44:12 +02001581 return fuse_simple_request(fm, &args);
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001582}
1583
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001584/*
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001585 * Set attributes, and at the same time refresh them.
1586 *
1587 * Truncation is slightly complicated, because the 'truncate' request
1588 * may fail, in which case we don't want to touch the mapping.
Miklos Szeredi9ffbb912006-10-17 00:10:06 -07001589 * vmtruncate() doesn't allow for this case, so do the rlimit checking
1590 * and the actual truncation by hand.
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001591 */
Jan Kara62490332016-05-26 17:12:41 +02001592int fuse_do_setattr(struct dentry *dentry, struct iattr *attr,
Maxim Patlasovefb9fa92012-12-18 14:05:08 +04001593 struct file *file)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001594{
Jan Kara62490332016-05-26 17:12:41 +02001595 struct inode *inode = d_inode(dentry);
Max Reitzfcee2162020-05-06 17:44:12 +02001596 struct fuse_mount *fm = get_fuse_mount(inode);
1597 struct fuse_conn *fc = fm->fc;
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001598 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredi70781872014-12-12 09:49:05 +01001599 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001600 struct fuse_setattr_in inarg;
1601 struct fuse_attr_out outarg;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001602 bool is_truncate = false;
Pavel Emelyanov83732002013-10-10 17:10:46 +04001603 bool is_wb = fc->writeback_cache;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001604 loff_t oldsize;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001605 int err;
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001606 bool trust_local_cmtime = is_wb && S_ISREG(inode->i_mode);
Vivek Goyal6ae330c2020-08-19 18:19:54 -04001607 bool fault_blocked = false;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001608
Miklos Szeredi29433a22016-10-01 07:32:32 +02001609 if (!fc->default_permissions)
Christoph Hellwigdb78b872010-06-04 11:30:03 +02001610 attr->ia_valid |= ATTR_FORCE;
1611
Jan Kara31051c82016-05-26 16:55:18 +02001612 err = setattr_prepare(dentry, attr);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02001613 if (err)
1614 return err;
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001615
Vivek Goyal6ae330c2020-08-19 18:19:54 -04001616 if (attr->ia_valid & ATTR_SIZE) {
1617 if (WARN_ON(!S_ISREG(inode->i_mode)))
1618 return -EIO;
1619 is_truncate = true;
1620 }
1621
1622 if (FUSE_IS_DAX(inode) && is_truncate) {
1623 down_write(&fi->i_mmap_sem);
1624 fault_blocked = true;
1625 err = fuse_dax_break_layouts(inode, 0, 0);
1626 if (err) {
1627 up_write(&fi->i_mmap_sem);
1628 return err;
1629 }
1630 }
1631
Miklos Szeredi8d56add2011-02-25 14:44:58 +01001632 if (attr->ia_valid & ATTR_OPEN) {
Miklos Szeredidf0e91d2018-02-08 15:17:38 +01001633 /* This is coming from open(..., ... | O_TRUNC); */
1634 WARN_ON(!(attr->ia_valid & ATTR_SIZE));
1635 WARN_ON(attr->ia_size != 0);
1636 if (fc->atomic_o_trunc) {
1637 /*
1638 * No need to send request to userspace, since actual
1639 * truncation has already been done by OPEN. But still
1640 * need to truncate page cache.
1641 */
1642 i_size_write(inode, 0);
1643 truncate_pagecache(inode, 0);
Vivek Goyal6ae330c2020-08-19 18:19:54 -04001644 goto out;
Miklos Szeredidf0e91d2018-02-08 15:17:38 +01001645 }
Miklos Szeredi8d56add2011-02-25 14:44:58 +01001646 file = NULL;
1647 }
Miklos Szeredi6ff958e2007-10-18 03:07:02 -07001648
Miklos Szeredib24e7592019-10-23 14:26:37 +02001649 /* Flush dirty data/metadata before non-truncate SETATTR */
1650 if (is_wb && S_ISREG(inode->i_mode) &&
1651 attr->ia_valid &
1652 (ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_MTIME_SET |
1653 ATTR_TIMES_SET)) {
1654 err = write_inode_now(inode, true);
1655 if (err)
1656 return err;
1657
1658 fuse_set_nowrite(inode);
1659 fuse_release_nowrite(inode);
1660 }
1661
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001662 if (is_truncate) {
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001663 fuse_set_nowrite(inode);
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001664 set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001665 if (trust_local_cmtime && attr->ia_size != inode->i_size)
1666 attr->ia_valid |= ATTR_MTIME | ATTR_CTIME;
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001667 }
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001668
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001669 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -07001670 memset(&outarg, 0, sizeof(outarg));
Eric W. Biederman8cb08322018-02-21 11:18:07 -06001671 iattr_to_fattr(fc, attr, &inarg, trust_local_cmtime);
Miklos Szeredi49d49142007-10-18 03:07:00 -07001672 if (file) {
1673 struct fuse_file *ff = file->private_data;
1674 inarg.valid |= FATTR_FH;
1675 inarg.fh = ff->fh;
1676 }
Miklos Szeredif3332112007-10-18 03:07:04 -07001677 if (attr->ia_valid & ATTR_SIZE) {
1678 /* For mandatory locking in truncate */
1679 inarg.valid |= FATTR_LOCKOWNER;
1680 inarg.lock_owner = fuse_lock_owner_id(fc, current->files);
1681 }
Miklos Szeredi70781872014-12-12 09:49:05 +01001682 fuse_setattr_fill(fc, &args, inode, &inarg, &outarg);
Max Reitzfcee2162020-05-06 17:44:12 +02001683 err = fuse_simple_request(fm, &args);
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001684 if (err) {
1685 if (err == -EINTR)
1686 fuse_invalidate_attr(inode);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001687 goto error;
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001688 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001689
Miklos Szeredieb59bd12019-11-12 11:49:04 +01001690 if (fuse_invalid_attr(&outarg.attr) ||
1691 (inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
Miklos Szeredi36cf9ae2020-12-10 15:33:14 +01001692 fuse_make_bad(inode);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001693 err = -EIO;
1694 goto error;
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001695 }
1696
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +03001697 spin_lock(&fi->lock);
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001698 /* the kernel maintains i_mtime locally */
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001699 if (trust_local_cmtime) {
1700 if (attr->ia_valid & ATTR_MTIME)
1701 inode->i_mtime = attr->ia_mtime;
1702 if (attr->ia_valid & ATTR_CTIME)
1703 inode->i_ctime = attr->ia_ctime;
Miklos Szeredi1e18bda2014-04-28 14:19:23 +02001704 /* FIXME: clear I_DIRTY_SYNC? */
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001705 }
1706
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001707 fuse_change_attributes_common(inode, &outarg.attr,
1708 attr_timeout(&outarg));
1709 oldsize = inode->i_size;
Pavel Emelyanov83732002013-10-10 17:10:46 +04001710 /* see the comment in fuse_change_attributes() */
1711 if (!is_wb || is_truncate || !S_ISREG(inode->i_mode))
1712 i_size_write(inode, outarg.attr.size);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001713
1714 if (is_truncate) {
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +03001715 /* NOTE: this may release/reacquire fi->lock */
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001716 __fuse_release_nowrite(inode);
1717 }
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +03001718 spin_unlock(&fi->lock);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001719
1720 /*
1721 * Only call invalidate_inode_pages2() after removing
1722 * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock.
1723 */
Pavel Emelyanov83732002013-10-10 17:10:46 +04001724 if ((is_truncate || !is_wb) &&
1725 S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
Kirill A. Shutemov7caef262013-09-12 15:13:56 -07001726 truncate_pagecache(inode, outarg.attr.size);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001727 invalidate_inode_pages2(inode->i_mapping);
1728 }
1729
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001730 clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
Vivek Goyal6ae330c2020-08-19 18:19:54 -04001731out:
1732 if (fault_blocked)
1733 up_write(&fi->i_mmap_sem);
1734
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001735 return 0;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001736
1737error:
1738 if (is_truncate)
1739 fuse_release_nowrite(inode);
1740
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001741 clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
Vivek Goyal6ae330c2020-08-19 18:19:54 -04001742
1743 if (fault_blocked)
1744 up_write(&fi->i_mmap_sem);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001745 return err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001746}
1747
Miklos Szeredi49d49142007-10-18 03:07:00 -07001748static int fuse_setattr(struct dentry *entry, struct iattr *attr)
1749{
David Howells2b0143b2015-03-17 22:25:59 +00001750 struct inode *inode = d_inode(entry);
Miklos Szeredi5e940c12016-10-01 07:32:32 +02001751 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredia09f99e2016-10-01 07:32:32 +02001752 struct file *file = (attr->ia_valid & ATTR_FILE) ? attr->ia_file : NULL;
Miklos Szeredi5e2b8822016-10-01 07:32:32 +02001753 int ret;
Maxim Patlasovefb9fa92012-12-18 14:05:08 +04001754
Miklos Szeredi36cf9ae2020-12-10 15:33:14 +01001755 if (fuse_is_bad(inode))
1756 return -EIO;
1757
Maxim Patlasovefb9fa92012-12-18 14:05:08 +04001758 if (!fuse_allow_current_process(get_fuse_conn(inode)))
1759 return -EACCES;
1760
Miklos Szeredia09f99e2016-10-01 07:32:32 +02001761 if (attr->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) {
Miklos Szeredia09f99e2016-10-01 07:32:32 +02001762 attr->ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID |
1763 ATTR_MODE);
Miklos Szeredia09f99e2016-10-01 07:32:32 +02001764
Miklos Szeredi5e940c12016-10-01 07:32:32 +02001765 /*
1766 * The only sane way to reliably kill suid/sgid is to do it in
1767 * the userspace filesystem
1768 *
1769 * This should be done on write(), truncate() and chown().
1770 */
1771 if (!fc->handle_killpriv) {
Miklos Szeredi5e940c12016-10-01 07:32:32 +02001772 /*
1773 * ia_mode calculation may have used stale i_mode.
1774 * Refresh and recalculate.
1775 */
1776 ret = fuse_do_getattr(inode, NULL, file);
1777 if (ret)
1778 return ret;
1779
1780 attr->ia_mode = inode->i_mode;
Miklos Szeredic01638f2016-12-06 16:18:45 +01001781 if (inode->i_mode & S_ISUID) {
Miklos Szeredi5e940c12016-10-01 07:32:32 +02001782 attr->ia_valid |= ATTR_MODE;
1783 attr->ia_mode &= ~S_ISUID;
1784 }
Miklos Szeredic01638f2016-12-06 16:18:45 +01001785 if ((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
Miklos Szeredi5e940c12016-10-01 07:32:32 +02001786 attr->ia_valid |= ATTR_MODE;
1787 attr->ia_mode &= ~S_ISGID;
1788 }
Miklos Szeredia09f99e2016-10-01 07:32:32 +02001789 }
1790 }
1791 if (!attr->ia_valid)
1792 return 0;
1793
Linus Torvaldsabb5a142016-10-10 13:04:49 -07001794 ret = fuse_do_setattr(entry, attr, file);
Miklos Szeredi5e2b8822016-10-01 07:32:32 +02001795 if (!ret) {
Seth Forshee60bcc882016-08-29 08:46:37 -05001796 /*
1797 * If filesystem supports acls it may have updated acl xattrs in
1798 * the filesystem, so forget cached acls for the inode.
1799 */
1800 if (fc->posix_acl)
1801 forget_all_cached_acls(inode);
1802
Miklos Szeredi5e2b8822016-10-01 07:32:32 +02001803 /* Directory mode changed, may need to revalidate access */
1804 if (d_is_dir(entry) && (attr->ia_valid & ATTR_MODE))
1805 fuse_invalidate_entry_cache(entry);
1806 }
1807 return ret;
Miklos Szeredi49d49142007-10-18 03:07:00 -07001808}
1809
David Howellsa528d352017-01-31 16:46:22 +00001810static int fuse_getattr(const struct path *path, struct kstat *stat,
1811 u32 request_mask, unsigned int flags)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001812{
David Howellsa528d352017-01-31 16:46:22 +00001813 struct inode *inode = d_inode(path->dentry);
Miklos Szeredi244f6382007-10-16 23:31:02 -07001814 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi244f6382007-10-16 23:31:02 -07001815
Miklos Szeredi36cf9ae2020-12-10 15:33:14 +01001816 if (fuse_is_bad(inode))
1817 return -EIO;
1818
Miklos Szeredi5157da22020-05-19 14:50:37 +02001819 if (!fuse_allow_current_process(fc)) {
1820 if (!request_mask) {
1821 /*
1822 * If user explicitly requested *nothing* then don't
1823 * error out, but return st_dev only.
1824 */
1825 stat->result_mask = 0;
1826 stat->dev = inode->i_sb->s_dev;
1827 return 0;
1828 }
Miklos Szeredi244f6382007-10-16 23:31:02 -07001829 return -EACCES;
Miklos Szeredi5157da22020-05-19 14:50:37 +02001830 }
Miklos Szeredi244f6382007-10-16 23:31:02 -07001831
Miklos Szeredi2f1e8192018-10-15 15:43:06 +02001832 return fuse_update_get_attr(inode, NULL, stat, request_mask, flags);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001833}
1834
Arjan van de Ven754661f2007-02-12 00:55:38 -08001835static const struct inode_operations fuse_dir_inode_operations = {
Miklos Szeredie5e55582005-09-09 13:10:28 -07001836 .lookup = fuse_lookup,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001837 .mkdir = fuse_mkdir,
1838 .symlink = fuse_symlink,
1839 .unlink = fuse_unlink,
1840 .rmdir = fuse_rmdir,
Miklos Szeredi2773bf02016-09-27 11:03:58 +02001841 .rename = fuse_rename2,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001842 .link = fuse_link,
1843 .setattr = fuse_setattr,
1844 .create = fuse_create,
Miklos Szeredic8ccbe02012-06-05 15:10:22 +02001845 .atomic_open = fuse_atomic_open,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001846 .mknod = fuse_mknod,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001847 .permission = fuse_permission,
1848 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001849 .listxattr = fuse_listxattr,
Seth Forshee60bcc882016-08-29 08:46:37 -05001850 .get_acl = fuse_get_acl,
1851 .set_acl = fuse_set_acl,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001852};
1853
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -08001854static const struct file_operations fuse_dir_operations = {
Miklos Szeredib6aeade2005-09-09 13:10:30 -07001855 .llseek = generic_file_llseek,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001856 .read = generic_read_dir,
Al Virod9b3dbd2016-04-20 17:30:32 -04001857 .iterate_shared = fuse_readdir,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001858 .open = fuse_dir_open,
1859 .release = fuse_dir_release,
Miklos Szeredi82547982005-09-09 13:10:38 -07001860 .fsync = fuse_dir_fsync,
Miklos Szeredib18da0c2011-12-13 11:58:49 +01001861 .unlocked_ioctl = fuse_dir_ioctl,
1862 .compat_ioctl = fuse_dir_compat_ioctl,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001863};
1864
Arjan van de Ven754661f2007-02-12 00:55:38 -08001865static const struct inode_operations fuse_common_inode_operations = {
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001866 .setattr = fuse_setattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001867 .permission = fuse_permission,
1868 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001869 .listxattr = fuse_listxattr,
Seth Forshee60bcc882016-08-29 08:46:37 -05001870 .get_acl = fuse_get_acl,
1871 .set_acl = fuse_set_acl,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001872};
1873
Arjan van de Ven754661f2007-02-12 00:55:38 -08001874static const struct inode_operations fuse_symlink_inode_operations = {
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001875 .setattr = fuse_setattr,
Al Viro6b255392015-11-17 10:20:54 -05001876 .get_link = fuse_get_link,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001877 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001878 .listxattr = fuse_listxattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001879};
1880
1881void fuse_init_common(struct inode *inode)
1882{
1883 inode->i_op = &fuse_common_inode_operations;
1884}
1885
1886void fuse_init_dir(struct inode *inode)
1887{
Miklos Szerediab2257e2018-10-01 10:07:05 +02001888 struct fuse_inode *fi = get_fuse_inode(inode);
1889
Miklos Szeredie5e55582005-09-09 13:10:28 -07001890 inode->i_op = &fuse_dir_inode_operations;
1891 inode->i_fop = &fuse_dir_operations;
Miklos Szerediab2257e2018-10-01 10:07:05 +02001892
1893 spin_lock_init(&fi->rdc.lock);
1894 fi->rdc.cached = false;
1895 fi->rdc.size = 0;
1896 fi->rdc.pos = 0;
1897 fi->rdc.version = 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001898}
1899
Dan Schatzberg5571f1e2018-10-11 08:17:00 -07001900static int fuse_symlink_readpage(struct file *null, struct page *page)
1901{
1902 int err = fuse_readlink_page(page->mapping->host, page);
1903
1904 if (!err)
1905 SetPageUptodate(page);
1906
1907 unlock_page(page);
1908
1909 return err;
1910}
1911
1912static const struct address_space_operations fuse_symlink_aops = {
1913 .readpage = fuse_symlink_readpage,
1914};
1915
Miklos Szeredie5e55582005-09-09 13:10:28 -07001916void fuse_init_symlink(struct inode *inode)
1917{
1918 inode->i_op = &fuse_symlink_inode_operations;
Dan Schatzberg5571f1e2018-10-11 08:17:00 -07001919 inode->i_data.a_ops = &fuse_symlink_aops;
1920 inode_nohighmem(inode);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001921}