blob: 8e95a75a4559c6435a52a9e352854ec05c639a24 [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) ||
Amir Goldsteinad5e13f2021-06-21 14:03:53 +0300255 fuse_stale_inode(inode, outarg.generation, &outarg.attr))
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
Greg Kurzae6ab392021-06-04 18:11:51 +0200350 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
Al Viro42695902009-02-20 05:59:13 +0000392const struct dentry_operations fuse_dentry_operations = {
Miklos Szeredie5e55582005-09-09 13:10:28 -0700393 .d_revalidate = fuse_dentry_revalidate,
Miklos Szeredi8fab0102018-08-15 17:42:34 +0200394 .d_delete = fuse_dentry_delete,
Khazhismel Kumykov30c6a232019-09-16 16:56:41 -0700395#if BITS_PER_LONG < 64
Miklos Szeredif75fdf22016-10-01 07:32:32 +0200396 .d_init = fuse_dentry_init,
397 .d_release = fuse_dentry_release,
Khazhismel Kumykov30c6a232019-09-16 16:56:41 -0700398#endif
Max Reitzbf109c62020-04-21 14:47:15 +0200399 .d_automount = fuse_dentry_automount,
Miklos Szeredie5e55582005-09-09 13:10:28 -0700400};
401
Miklos Szeredi0ce267f2016-10-18 15:36:48 +0200402const struct dentry_operations fuse_root_dentry_operations = {
Khazhismel Kumykov30c6a232019-09-16 16:56:41 -0700403#if BITS_PER_LONG < 64
Miklos Szeredi0ce267f2016-10-18 15:36:48 +0200404 .d_init = fuse_dentry_init,
405 .d_release = fuse_dentry_release,
Khazhismel Kumykov30c6a232019-09-16 16:56:41 -0700406#endif
Miklos Szeredi0ce267f2016-10-18 15:36:48 +0200407};
408
Timo Savolaa5bfffac2007-04-08 16:04:00 -0700409int fuse_valid_type(int m)
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800410{
411 return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) ||
412 S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m);
413}
414
Miklos Szeredieb59bd12019-11-12 11:49:04 +0100415bool fuse_invalid_attr(struct fuse_attr *attr)
416{
417 return !fuse_valid_type(attr->mode) ||
418 attr->size > LLONG_MAX;
419}
420
Al Viro13983d02016-07-20 22:34:44 -0400421int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name,
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700422 struct fuse_entry_out *outarg, struct inode **inode)
423{
Max Reitzfcee2162020-05-06 17:44:12 +0200424 struct fuse_mount *fm = get_fuse_mount_super(sb);
Miklos Szeredi70781872014-12-12 09:49:05 +0100425 FUSE_ARGS(args);
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100426 struct fuse_forget_link *forget;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700427 u64 attr_version;
428 int err;
429
430 *inode = NULL;
431 err = -ENAMETOOLONG;
432 if (name->len > FUSE_NAME_MAX)
433 goto out;
434
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700435
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100436 forget = fuse_alloc_forget();
437 err = -ENOMEM;
Miklos Szeredi70781872014-12-12 09:49:05 +0100438 if (!forget)
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700439 goto out;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700440
Max Reitzfcee2162020-05-06 17:44:12 +0200441 attr_version = fuse_get_attr_version(fm->fc);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700442
Max Reitzfcee2162020-05-06 17:44:12 +0200443 fuse_lookup_init(fm->fc, &args, nodeid, name, outarg);
444 err = fuse_simple_request(fm, &args);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700445 /* Zero nodeid is same as -ENOENT, but with valid timeout */
446 if (err || !outarg->nodeid)
447 goto out_put_forget;
448
449 err = -EIO;
450 if (!outarg->nodeid)
451 goto out_put_forget;
Miklos Szeredieb59bd12019-11-12 11:49:04 +0100452 if (fuse_invalid_attr(&outarg->attr))
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700453 goto out_put_forget;
454
455 *inode = fuse_iget(sb, outarg->nodeid, outarg->generation,
456 &outarg->attr, entry_attr_timeout(outarg),
457 attr_version);
458 err = -ENOMEM;
459 if (!*inode) {
Max Reitzfcee2162020-05-06 17:44:12 +0200460 fuse_queue_forget(fm->fc, forget, outarg->nodeid, 1);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700461 goto out;
462 }
463 err = 0;
464
465 out_put_forget:
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100466 kfree(forget);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700467 out:
468 return err;
469}
470
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800471static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
Al Viro00cd8dd2012-06-10 17:13:09 -0400472 unsigned int flags)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700473{
474 int err;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700475 struct fuse_entry_out outarg;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700476 struct inode *inode;
Miklos Szeredi0de62562008-07-25 01:48:59 -0700477 struct dentry *newent;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700478 bool outarg_valid = true;
Miklos Szeredi63576c12018-07-26 16:13:11 +0200479 bool locked;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700480
Miklos Szeredi36cf9ae2020-12-10 15:33:14 +0100481 if (fuse_is_bad(dir))
482 return ERR_PTR(-EIO);
483
Miklos Szeredi63576c12018-07-26 16:13:11 +0200484 locked = fuse_lock_inode(dir);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700485 err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name,
486 &outarg, &inode);
Miklos Szeredi63576c12018-07-26 16:13:11 +0200487 fuse_unlock_inode(dir, locked);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700488 if (err == -ENOENT) {
489 outarg_valid = false;
490 err = 0;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800491 }
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700492 if (err)
493 goto out_err;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800494
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700495 err = -EIO;
496 if (inode && get_node_id(inode) == FUSE_ROOT_ID)
497 goto out_iput;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700498
Al Viro41d28bc2014-10-12 22:24:21 -0400499 newent = d_splice_alias(inode, entry);
Miklos Szeredi5835f332013-09-05 11:44:42 +0200500 err = PTR_ERR(newent);
501 if (IS_ERR(newent))
502 goto out_err;
Miklos Szeredid2a85162006-10-17 00:10:11 -0700503
Miklos Szeredi0de62562008-07-25 01:48:59 -0700504 entry = newent ? newent : entry;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700505 if (outarg_valid)
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700506 fuse_change_entry_timeout(entry, &outarg);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800507 else
508 fuse_invalidate_entry_cache(entry);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700509
Miklos Szeredi6c26f712019-10-21 15:57:07 +0200510 if (inode)
511 fuse_advise_use_readdirplus(dir);
Miklos Szeredi0de62562008-07-25 01:48:59 -0700512 return newent;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700513
514 out_iput:
515 iput(inode);
516 out_err:
517 return ERR_PTR(err);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700518}
519
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800520/*
521 * Atomic create+open operation
522 *
523 * If the filesystem doesn't support this, then fall back to separate
524 * 'mknod' + 'open' requests.
525 */
Al Virod9585272012-06-22 12:39:14 +0400526static int fuse_create_open(struct inode *dir, struct dentry *entry,
Al Viro30d90492012-06-22 12:40:19 +0400527 struct file *file, unsigned flags,
Al Virob452a452018-06-08 13:06:28 -0400528 umode_t mode)
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800529{
530 int err;
531 struct inode *inode;
Max Reitzfcee2162020-05-06 17:44:12 +0200532 struct fuse_mount *fm = get_fuse_mount(dir);
Miklos Szeredi70781872014-12-12 09:49:05 +0100533 FUSE_ARGS(args);
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100534 struct fuse_forget_link *forget;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200535 struct fuse_create_in inarg;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800536 struct fuse_open_out outopen;
537 struct fuse_entry_out outentry;
Kirill Tkhaiebf84d02018-11-09 13:33:11 +0300538 struct fuse_inode *fi;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800539 struct fuse_file *ff;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800540
Miklos Szerediaf109bc2012-08-15 13:01:24 +0200541 /* Userspace expects S_IFREG in create mode */
542 BUG_ON((mode & S_IFMT) != S_IFREG);
543
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100544 forget = fuse_alloc_forget();
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200545 err = -ENOMEM;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100546 if (!forget)
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200547 goto out_err;
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700548
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700549 err = -ENOMEM;
Max Reitzfcee2162020-05-06 17:44:12 +0200550 ff = fuse_file_alloc(fm);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800551 if (!ff)
Miklos Szeredi70781872014-12-12 09:49:05 +0100552 goto out_put_forget_req;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800553
Max Reitzfcee2162020-05-06 17:44:12 +0200554 if (!fm->fc->dont_mask)
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200555 mode &= ~current_umask();
556
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800557 flags &= ~O_NOCTTY;
558 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700559 memset(&outentry, 0, sizeof(outentry));
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800560 inarg.flags = flags;
561 inarg.mode = mode;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200562 inarg.umask = current_umask();
Miklos Szeredid5b48542019-09-10 15:04:08 +0200563 args.opcode = FUSE_CREATE;
564 args.nodeid = get_node_id(dir);
565 args.in_numargs = 2;
566 args.in_args[0].size = sizeof(inarg);
567 args.in_args[0].value = &inarg;
568 args.in_args[1].size = entry->d_name.len + 1;
569 args.in_args[1].value = entry->d_name.name;
570 args.out_numargs = 2;
571 args.out_args[0].size = sizeof(outentry);
572 args.out_args[0].value = &outentry;
573 args.out_args[1].size = sizeof(outopen);
574 args.out_args[1].value = &outopen;
Max Reitzfcee2162020-05-06 17:44:12 +0200575 err = fuse_simple_request(fm, &args);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200576 if (err)
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800577 goto out_free_ff;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800578
579 err = -EIO;
Miklos Szeredieb59bd12019-11-12 11:49:04 +0100580 if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid) ||
581 fuse_invalid_attr(&outentry.attr))
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800582 goto out_free_ff;
583
Miklos Szeredic7b71432009-04-28 16:56:37 +0200584 ff->fh = outopen.fh;
585 ff->nodeid = outentry.nodeid;
586 ff->open_flags = outopen.open_flags;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800587 inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700588 &outentry.attr, entry_attr_timeout(&outentry), 0);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800589 if (!inode) {
590 flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
Kirill Tkhaiebf84d02018-11-09 13:33:11 +0300591 fuse_sync_release(NULL, ff, flags);
Max Reitzfcee2162020-05-06 17:44:12 +0200592 fuse_queue_forget(fm->fc, forget, outentry.nodeid, 1);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200593 err = -ENOMEM;
594 goto out_err;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800595 }
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100596 kfree(forget);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800597 d_instantiate(entry, inode);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700598 fuse_change_entry_timeout(entry, &outentry);
Miklos Szeredi261aaba72018-10-01 10:07:05 +0200599 fuse_dir_changed(dir);
Al Virobe12af32018-06-08 11:44:56 -0400600 err = finish_open(file, entry, generic_file_open);
Al Viro30d90492012-06-22 12:40:19 +0400601 if (err) {
Kirill Tkhaiebf84d02018-11-09 13:33:11 +0300602 fi = get_fuse_inode(inode);
603 fuse_sync_release(fi, ff, flags);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200604 } else {
Miklos Szeredi267d8442017-02-22 20:08:25 +0100605 file->private_data = ff;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200606 fuse_finish_open(inode, file);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800607 }
Al Virod9585272012-06-22 12:39:14 +0400608 return err;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800609
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200610out_free_ff:
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800611 fuse_file_free(ff);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200612out_put_forget_req:
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100613 kfree(forget);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200614out_err:
Al Virod9585272012-06-22 12:39:14 +0400615 return err;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200616}
617
618static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t);
Al Virod9585272012-06-22 12:39:14 +0400619static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
Al Viro30d90492012-06-22 12:40:19 +0400620 struct file *file, unsigned flags,
Al Viro44907d72018-06-08 13:32:02 -0400621 umode_t mode)
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200622{
623 int err;
624 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200625 struct dentry *res = NULL;
626
Miklos Szeredi36cf9ae2020-12-10 15:33:14 +0100627 if (fuse_is_bad(dir))
628 return -EIO;
629
Al Viro00699ad2016-07-05 09:44:53 -0400630 if (d_in_lookup(entry)) {
Al Viro00cd8dd2012-06-10 17:13:09 -0400631 res = fuse_lookup(dir, entry, 0);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200632 if (IS_ERR(res))
Al Virod9585272012-06-22 12:39:14 +0400633 return PTR_ERR(res);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200634
635 if (res)
636 entry = res;
637 }
638
David Howells2b0143b2015-03-17 22:25:59 +0000639 if (!(flags & O_CREAT) || d_really_is_positive(entry))
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200640 goto no_open;
641
642 /* Only creates */
Al Viro73a09dd2018-06-08 13:22:02 -0400643 file->f_mode |= FMODE_CREATED;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200644
645 if (fc->no_create)
646 goto mknod;
647
Al Virob452a452018-06-08 13:06:28 -0400648 err = fuse_create_open(dir, entry, file, flags, mode);
Al Virod9585272012-06-22 12:39:14 +0400649 if (err == -ENOSYS) {
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200650 fc->no_create = 1;
651 goto mknod;
652 }
653out_dput:
654 dput(res);
Al Virod9585272012-06-22 12:39:14 +0400655 return err;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200656
657mknod:
658 err = fuse_mknod(dir, entry, mode, 0);
Al Virod9585272012-06-22 12:39:14 +0400659 if (err)
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200660 goto out_dput;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200661no_open:
Al Viroe45198a2012-06-10 06:48:09 -0400662 return finish_no_open(file, res);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800663}
664
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800665/*
666 * Code shared between mknod, mkdir, symlink and link
667 */
Max Reitzfcee2162020-05-06 17:44:12 +0200668static int create_new_entry(struct fuse_mount *fm, struct fuse_args *args,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700669 struct inode *dir, struct dentry *entry,
Al Viro541af6a2011-07-26 03:17:33 -0400670 umode_t mode)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700671{
672 struct fuse_entry_out outarg;
673 struct inode *inode;
Al Viroc971e6a2018-05-28 18:27:19 -0400674 struct dentry *d;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700675 int err;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100676 struct fuse_forget_link *forget;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800677
Miklos Szeredi36cf9ae2020-12-10 15:33:14 +0100678 if (fuse_is_bad(dir))
679 return -EIO;
680
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100681 forget = fuse_alloc_forget();
Miklos Szeredi70781872014-12-12 09:49:05 +0100682 if (!forget)
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100683 return -ENOMEM;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700684
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700685 memset(&outarg, 0, sizeof(outarg));
Miklos Szeredid5b48542019-09-10 15:04:08 +0200686 args->nodeid = get_node_id(dir);
687 args->out_numargs = 1;
688 args->out_args[0].size = sizeof(outarg);
689 args->out_args[0].value = &outarg;
Max Reitzfcee2162020-05-06 17:44:12 +0200690 err = fuse_simple_request(fm, args);
Miklos Szeredi2d510132006-11-25 11:09:20 -0800691 if (err)
692 goto out_put_forget_req;
693
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800694 err = -EIO;
Miklos Szeredieb59bd12019-11-12 11:49:04 +0100695 if (invalid_nodeid(outarg.nodeid) || fuse_invalid_attr(&outarg.attr))
Miklos Szeredi2d510132006-11-25 11:09:20 -0800696 goto out_put_forget_req;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800697
698 if ((outarg.attr.mode ^ mode) & S_IFMT)
Miklos Szeredi2d510132006-11-25 11:09:20 -0800699 goto out_put_forget_req;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800700
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700701 inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700702 &outarg.attr, entry_attr_timeout(&outarg), 0);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700703 if (!inode) {
Max Reitzfcee2162020-05-06 17:44:12 +0200704 fuse_queue_forget(fm->fc, forget, outarg.nodeid, 1);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700705 return -ENOMEM;
706 }
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100707 kfree(forget);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700708
Al Viroc971e6a2018-05-28 18:27:19 -0400709 d_drop(entry);
710 d = d_splice_alias(inode, entry);
711 if (IS_ERR(d))
712 return PTR_ERR(d);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700713
Al Viroc971e6a2018-05-28 18:27:19 -0400714 if (d) {
715 fuse_change_entry_timeout(d, &outarg);
716 dput(d);
717 } else {
718 fuse_change_entry_timeout(entry, &outarg);
719 }
Miklos Szeredi261aaba72018-10-01 10:07:05 +0200720 fuse_dir_changed(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700721 return 0;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800722
Miklos Szeredi2d510132006-11-25 11:09:20 -0800723 out_put_forget_req:
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100724 kfree(forget);
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800725 return err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700726}
727
Al Viro1a67aaf2011-07-26 01:52:52 -0400728static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700729 dev_t rdev)
730{
731 struct fuse_mknod_in inarg;
Max Reitzfcee2162020-05-06 17:44:12 +0200732 struct fuse_mount *fm = get_fuse_mount(dir);
Miklos Szeredi70781872014-12-12 09:49:05 +0100733 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700734
Max Reitzfcee2162020-05-06 17:44:12 +0200735 if (!fm->fc->dont_mask)
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200736 mode &= ~current_umask();
737
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700738 memset(&inarg, 0, sizeof(inarg));
739 inarg.mode = mode;
740 inarg.rdev = new_encode_dev(rdev);
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200741 inarg.umask = current_umask();
Miklos Szeredid5b48542019-09-10 15:04:08 +0200742 args.opcode = FUSE_MKNOD;
743 args.in_numargs = 2;
744 args.in_args[0].size = sizeof(inarg);
745 args.in_args[0].value = &inarg;
746 args.in_args[1].size = entry->d_name.len + 1;
747 args.in_args[1].value = entry->d_name.name;
Max Reitzfcee2162020-05-06 17:44:12 +0200748 return create_new_entry(fm, &args, dir, entry, mode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700749}
750
Al Viro4acdaf22011-07-26 01:42:34 -0400751static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode,
Al Viroebfc3b42012-06-10 18:05:36 -0400752 bool excl)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700753{
754 return fuse_mknod(dir, entry, mode, 0);
755}
756
Al Viro18bb1db2011-07-26 01:41:39 -0400757static int fuse_mkdir(struct inode *dir, struct dentry *entry, umode_t mode)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700758{
759 struct fuse_mkdir_in inarg;
Max Reitzfcee2162020-05-06 17:44:12 +0200760 struct fuse_mount *fm = get_fuse_mount(dir);
Miklos Szeredi70781872014-12-12 09:49:05 +0100761 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700762
Max Reitzfcee2162020-05-06 17:44:12 +0200763 if (!fm->fc->dont_mask)
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200764 mode &= ~current_umask();
765
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700766 memset(&inarg, 0, sizeof(inarg));
767 inarg.mode = mode;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200768 inarg.umask = current_umask();
Miklos Szeredid5b48542019-09-10 15:04:08 +0200769 args.opcode = FUSE_MKDIR;
770 args.in_numargs = 2;
771 args.in_args[0].size = sizeof(inarg);
772 args.in_args[0].value = &inarg;
773 args.in_args[1].size = entry->d_name.len + 1;
774 args.in_args[1].value = entry->d_name.name;
Max Reitzfcee2162020-05-06 17:44:12 +0200775 return create_new_entry(fm, &args, dir, entry, S_IFDIR);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700776}
777
778static int fuse_symlink(struct inode *dir, struct dentry *entry,
779 const char *link)
780{
Max Reitzfcee2162020-05-06 17:44:12 +0200781 struct fuse_mount *fm = get_fuse_mount(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700782 unsigned len = strlen(link) + 1;
Miklos Szeredi70781872014-12-12 09:49:05 +0100783 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700784
Miklos Szeredid5b48542019-09-10 15:04:08 +0200785 args.opcode = FUSE_SYMLINK;
786 args.in_numargs = 2;
787 args.in_args[0].size = entry->d_name.len + 1;
788 args.in_args[0].value = entry->d_name.name;
789 args.in_args[1].size = len;
790 args.in_args[1].value = link;
Max Reitzfcee2162020-05-06 17:44:12 +0200791 return create_new_entry(fm, &args, dir, entry, S_IFLNK);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700792}
793
Miklos Szeredic31470a2021-10-22 17:03:01 +0200794void fuse_flush_time_update(struct inode *inode)
795{
796 int err = sync_inode_metadata(inode, 1);
797
798 mapping_set_error(inode->i_mapping, err);
799}
800
Seth Forshee703c7362016-08-29 08:46:36 -0500801void fuse_update_ctime(struct inode *inode)
Maxim Patlasov31f32672014-04-28 14:19:24 +0200802{
803 if (!IS_NOCMTIME(inode)) {
Deepa Dinamanic2050a42016-09-14 07:48:06 -0700804 inode->i_ctime = current_time(inode);
Maxim Patlasov31f32672014-04-28 14:19:24 +0200805 mark_inode_dirty_sync(inode);
Miklos Szeredic31470a2021-10-22 17:03:01 +0200806 fuse_flush_time_update(inode);
Maxim Patlasov31f32672014-04-28 14:19:24 +0200807 }
808}
809
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700810static int fuse_unlink(struct inode *dir, struct dentry *entry)
811{
812 int err;
Max Reitzfcee2162020-05-06 17:44:12 +0200813 struct fuse_mount *fm = get_fuse_mount(dir);
Miklos Szeredi70781872014-12-12 09:49:05 +0100814 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700815
Miklos Szeredi36cf9ae2020-12-10 15:33:14 +0100816 if (fuse_is_bad(dir))
817 return -EIO;
818
Miklos Szeredid5b48542019-09-10 15:04:08 +0200819 args.opcode = FUSE_UNLINK;
820 args.nodeid = get_node_id(dir);
821 args.in_numargs = 1;
822 args.in_args[0].size = entry->d_name.len + 1;
823 args.in_args[0].value = entry->d_name.name;
Max Reitzfcee2162020-05-06 17:44:12 +0200824 err = fuse_simple_request(fm, &args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700825 if (!err) {
David Howells2b0143b2015-03-17 22:25:59 +0000826 struct inode *inode = d_inode(entry);
Miklos Szerediac45d612012-03-05 15:48:11 +0100827 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700828
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +0300829 spin_lock(&fi->lock);
Max Reitzfcee2162020-05-06 17:44:12 +0200830 fi->attr_version = atomic64_inc_return(&fm->fc->attr_version);
Miklos Szeredidfca7ce2013-02-04 15:57:42 +0100831 /*
832 * If i_nlink == 0 then unlink doesn't make sense, yet this can
833 * happen if userspace filesystem is careless. It would be
834 * difficult to enforce correct nlink usage so just ignore this
835 * condition here
836 */
837 if (inode->i_nlink > 0)
838 drop_nlink(inode);
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +0300839 spin_unlock(&fi->lock);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700840 fuse_invalidate_attr(inode);
Miklos Szeredi261aaba72018-10-01 10:07:05 +0200841 fuse_dir_changed(dir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800842 fuse_invalidate_entry_cache(entry);
Maxim Patlasov31f32672014-04-28 14:19:24 +0200843 fuse_update_ctime(inode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700844 } else if (err == -EINTR)
845 fuse_invalidate_entry(entry);
846 return err;
847}
848
849static int fuse_rmdir(struct inode *dir, struct dentry *entry)
850{
851 int err;
Max Reitzfcee2162020-05-06 17:44:12 +0200852 struct fuse_mount *fm = get_fuse_mount(dir);
Miklos Szeredi70781872014-12-12 09:49:05 +0100853 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700854
Miklos Szeredi36cf9ae2020-12-10 15:33:14 +0100855 if (fuse_is_bad(dir))
856 return -EIO;
857
Miklos Szeredid5b48542019-09-10 15:04:08 +0200858 args.opcode = FUSE_RMDIR;
859 args.nodeid = get_node_id(dir);
860 args.in_numargs = 1;
861 args.in_args[0].size = entry->d_name.len + 1;
862 args.in_args[0].value = entry->d_name.name;
Max Reitzfcee2162020-05-06 17:44:12 +0200863 err = fuse_simple_request(fm, &args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700864 if (!err) {
David Howells2b0143b2015-03-17 22:25:59 +0000865 clear_nlink(d_inode(entry));
Miklos Szeredi261aaba72018-10-01 10:07:05 +0200866 fuse_dir_changed(dir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800867 fuse_invalidate_entry_cache(entry);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700868 } else if (err == -EINTR)
869 fuse_invalidate_entry(entry);
870 return err;
871}
872
Miklos Szeredi1560c972014-04-28 16:43:44 +0200873static int fuse_rename_common(struct inode *olddir, struct dentry *oldent,
874 struct inode *newdir, struct dentry *newent,
875 unsigned int flags, int opcode, size_t argsize)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700876{
877 int err;
Miklos Szeredi1560c972014-04-28 16:43:44 +0200878 struct fuse_rename2_in inarg;
Max Reitzfcee2162020-05-06 17:44:12 +0200879 struct fuse_mount *fm = get_fuse_mount(olddir);
Miklos Szeredi70781872014-12-12 09:49:05 +0100880 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700881
Miklos Szeredi1560c972014-04-28 16:43:44 +0200882 memset(&inarg, 0, argsize);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700883 inarg.newdir = get_node_id(newdir);
Miklos Szeredi1560c972014-04-28 16:43:44 +0200884 inarg.flags = flags;
Miklos Szeredid5b48542019-09-10 15:04:08 +0200885 args.opcode = opcode;
886 args.nodeid = get_node_id(olddir);
887 args.in_numargs = 3;
888 args.in_args[0].size = argsize;
889 args.in_args[0].value = &inarg;
890 args.in_args[1].size = oldent->d_name.len + 1;
891 args.in_args[1].value = oldent->d_name.name;
892 args.in_args[2].size = newent->d_name.len + 1;
893 args.in_args[2].value = newent->d_name.name;
Max Reitzfcee2162020-05-06 17:44:12 +0200894 err = fuse_simple_request(fm, &args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700895 if (!err) {
Miklos Szeredi08b63302007-11-28 16:22:03 -0800896 /* ctime changes */
David Howells2b0143b2015-03-17 22:25:59 +0000897 fuse_invalidate_attr(d_inode(oldent));
898 fuse_update_ctime(d_inode(oldent));
Miklos Szeredi08b63302007-11-28 16:22:03 -0800899
Miklos Szeredi1560c972014-04-28 16:43:44 +0200900 if (flags & RENAME_EXCHANGE) {
David Howells2b0143b2015-03-17 22:25:59 +0000901 fuse_invalidate_attr(d_inode(newent));
902 fuse_update_ctime(d_inode(newent));
Miklos Szeredi1560c972014-04-28 16:43:44 +0200903 }
904
Miklos Szeredi261aaba72018-10-01 10:07:05 +0200905 fuse_dir_changed(olddir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700906 if (olddir != newdir)
Miklos Szeredi261aaba72018-10-01 10:07:05 +0200907 fuse_dir_changed(newdir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800908
909 /* newent will end up negative */
David Howells2b0143b2015-03-17 22:25:59 +0000910 if (!(flags & RENAME_EXCHANGE) && d_really_is_positive(newent)) {
911 fuse_invalidate_attr(d_inode(newent));
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800912 fuse_invalidate_entry_cache(newent);
David Howells2b0143b2015-03-17 22:25:59 +0000913 fuse_update_ctime(d_inode(newent));
Miklos Szeredi5219f342009-11-04 10:24:52 +0100914 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700915 } else if (err == -EINTR) {
916 /* If request was interrupted, DEITY only knows if the
917 rename actually took place. If the invalidation
918 fails (e.g. some process has CWD under the renamed
919 directory), then there can be inconsistency between
920 the dcache and the real filesystem. Tough luck. */
921 fuse_invalidate_entry(oldent);
David Howells2b0143b2015-03-17 22:25:59 +0000922 if (d_really_is_positive(newent))
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700923 fuse_invalidate_entry(newent);
924 }
925
926 return err;
927}
928
Miklos Szeredi1560c972014-04-28 16:43:44 +0200929static int fuse_rename2(struct inode *olddir, struct dentry *oldent,
930 struct inode *newdir, struct dentry *newent,
931 unsigned int flags)
932{
933 struct fuse_conn *fc = get_fuse_conn(olddir);
934 int err;
935
Miklos Szeredi36cf9ae2020-12-10 15:33:14 +0100936 if (fuse_is_bad(olddir))
937 return -EIO;
938
Vivek Goyal519525f2020-02-05 08:15:46 -0500939 if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT))
Miklos Szeredi1560c972014-04-28 16:43:44 +0200940 return -EINVAL;
941
Miklos Szeredi4237ba42014-07-10 10:50:19 +0200942 if (flags) {
943 if (fc->no_rename2 || fc->minor < 23)
944 return -EINVAL;
Miklos Szeredi1560c972014-04-28 16:43:44 +0200945
Miklos Szeredi4237ba42014-07-10 10:50:19 +0200946 err = fuse_rename_common(olddir, oldent, newdir, newent, flags,
947 FUSE_RENAME2,
948 sizeof(struct fuse_rename2_in));
949 if (err == -ENOSYS) {
950 fc->no_rename2 = 1;
951 err = -EINVAL;
952 }
953 } else {
954 err = fuse_rename_common(olddir, oldent, newdir, newent, 0,
955 FUSE_RENAME,
956 sizeof(struct fuse_rename_in));
Miklos Szeredi1560c972014-04-28 16:43:44 +0200957 }
Miklos Szeredi1560c972014-04-28 16:43:44 +0200958
Miklos Szeredi4237ba42014-07-10 10:50:19 +0200959 return err;
960}
961
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700962static int fuse_link(struct dentry *entry, struct inode *newdir,
963 struct dentry *newent)
964{
965 int err;
966 struct fuse_link_in inarg;
David Howells2b0143b2015-03-17 22:25:59 +0000967 struct inode *inode = d_inode(entry);
Max Reitzfcee2162020-05-06 17:44:12 +0200968 struct fuse_mount *fm = get_fuse_mount(inode);
Miklos Szeredi70781872014-12-12 09:49:05 +0100969 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700970
971 memset(&inarg, 0, sizeof(inarg));
972 inarg.oldnodeid = get_node_id(inode);
Miklos Szeredid5b48542019-09-10 15:04:08 +0200973 args.opcode = FUSE_LINK;
974 args.in_numargs = 2;
975 args.in_args[0].size = sizeof(inarg);
976 args.in_args[0].value = &inarg;
977 args.in_args[1].size = newent->d_name.len + 1;
978 args.in_args[1].value = newent->d_name.name;
Max Reitzfcee2162020-05-06 17:44:12 +0200979 err = create_new_entry(fm, &args, newdir, newent, inode->i_mode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700980 /* Contrary to "normal" filesystems it can happen that link
981 makes two "logical" inodes point to the same "physical"
982 inode. We invalidate the attributes of the old one, so it
983 will reflect changes in the backing inode (link count,
984 etc.)
985 */
Miklos Szerediac45d612012-03-05 15:48:11 +0100986 if (!err) {
987 struct fuse_inode *fi = get_fuse_inode(inode);
988
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +0300989 spin_lock(&fi->lock);
Max Reitzfcee2162020-05-06 17:44:12 +0200990 fi->attr_version = atomic64_inc_return(&fm->fc->attr_version);
Miklos Szeredic634da72019-11-12 11:49:04 +0100991 if (likely(inode->i_nlink < UINT_MAX))
992 inc_nlink(inode);
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +0300993 spin_unlock(&fi->lock);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700994 fuse_invalidate_attr(inode);
Maxim Patlasov31f32672014-04-28 14:19:24 +0200995 fuse_update_ctime(inode);
Miklos Szerediac45d612012-03-05 15:48:11 +0100996 } else if (err == -EINTR) {
997 fuse_invalidate_attr(inode);
998 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700999 return err;
1000}
1001
Miklos Szeredi1fb69e72007-10-18 03:06:58 -07001002static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
1003 struct kstat *stat)
1004{
Miklos Szeredi203627b2012-05-10 19:49:38 +04001005 unsigned int blkbits;
Pavel Emelyanov83732002013-10-10 17:10:46 +04001006 struct fuse_conn *fc = get_fuse_conn(inode);
1007
1008 /* see the comment in fuse_change_attributes() */
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001009 if (fc->writeback_cache && S_ISREG(inode->i_mode)) {
Pavel Emelyanov83732002013-10-10 17:10:46 +04001010 attr->size = i_size_read(inode);
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001011 attr->mtime = inode->i_mtime.tv_sec;
1012 attr->mtimensec = inode->i_mtime.tv_nsec;
Maxim Patlasov31f32672014-04-28 14:19:24 +02001013 attr->ctime = inode->i_ctime.tv_sec;
1014 attr->ctimensec = inode->i_ctime.tv_nsec;
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001015 }
Miklos Szeredi203627b2012-05-10 19:49:38 +04001016
Miklos Szeredi1fb69e72007-10-18 03:06:58 -07001017 stat->dev = inode->i_sb->s_dev;
1018 stat->ino = attr->ino;
1019 stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
1020 stat->nlink = attr->nlink;
Eric W. Biederman8cb08322018-02-21 11:18:07 -06001021 stat->uid = make_kuid(fc->user_ns, attr->uid);
1022 stat->gid = make_kgid(fc->user_ns, attr->gid);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -07001023 stat->rdev = inode->i_rdev;
1024 stat->atime.tv_sec = attr->atime;
1025 stat->atime.tv_nsec = attr->atimensec;
1026 stat->mtime.tv_sec = attr->mtime;
1027 stat->mtime.tv_nsec = attr->mtimensec;
1028 stat->ctime.tv_sec = attr->ctime;
1029 stat->ctime.tv_nsec = attr->ctimensec;
1030 stat->size = attr->size;
1031 stat->blocks = attr->blocks;
Miklos Szeredi203627b2012-05-10 19:49:38 +04001032
1033 if (attr->blksize != 0)
1034 blkbits = ilog2(attr->blksize);
1035 else
1036 blkbits = inode->i_sb->s_blocksize_bits;
1037
1038 stat->blksize = 1 << blkbits;
Miklos Szeredi1fb69e72007-10-18 03:06:58 -07001039}
1040
Miklos Szeredic79e3222007-10-18 03:06:59 -07001041static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
1042 struct file *file)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001043{
1044 int err;
Miklos Szeredic79e3222007-10-18 03:06:59 -07001045 struct fuse_getattr_in inarg;
1046 struct fuse_attr_out outarg;
Max Reitzfcee2162020-05-06 17:44:12 +02001047 struct fuse_mount *fm = get_fuse_mount(inode);
Miklos Szeredi70781872014-12-12 09:49:05 +01001048 FUSE_ARGS(args);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -07001049 u64 attr_version;
1050
Max Reitzfcee2162020-05-06 17:44:12 +02001051 attr_version = fuse_get_attr_version(fm->fc);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -07001052
Miklos Szeredic79e3222007-10-18 03:06:59 -07001053 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -07001054 memset(&outarg, 0, sizeof(outarg));
Miklos Szeredic79e3222007-10-18 03:06:59 -07001055 /* Directories have separate file-handle space */
1056 if (file && S_ISREG(inode->i_mode)) {
1057 struct fuse_file *ff = file->private_data;
1058
1059 inarg.getattr_flags |= FUSE_GETATTR_FH;
1060 inarg.fh = ff->fh;
1061 }
Miklos Szeredid5b48542019-09-10 15:04:08 +02001062 args.opcode = FUSE_GETATTR;
1063 args.nodeid = get_node_id(inode);
1064 args.in_numargs = 1;
1065 args.in_args[0].size = sizeof(inarg);
1066 args.in_args[0].value = &inarg;
1067 args.out_numargs = 1;
1068 args.out_args[0].size = sizeof(outarg);
1069 args.out_args[0].value = &outarg;
Max Reitzfcee2162020-05-06 17:44:12 +02001070 err = fuse_simple_request(fm, &args);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001071 if (!err) {
Miklos Szeredieb59bd12019-11-12 11:49:04 +01001072 if (fuse_invalid_attr(&outarg.attr) ||
Al Viro40ba4332021-03-01 20:37:10 -05001073 inode_wrong_type(inode, outarg.attr.mode)) {
Miklos Szeredi36cf9ae2020-12-10 15:33:14 +01001074 fuse_make_bad(inode);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001075 err = -EIO;
1076 } else {
Miklos Szeredic79e3222007-10-18 03:06:59 -07001077 fuse_change_attributes(inode, &outarg.attr,
1078 attr_timeout(&outarg),
Miklos Szeredi1fb69e72007-10-18 03:06:58 -07001079 attr_version);
1080 if (stat)
Miklos Szeredic79e3222007-10-18 03:06:59 -07001081 fuse_fillattr(inode, &outarg.attr, stat);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001082 }
1083 }
1084 return err;
1085}
1086
Miklos Szeredi5b97eea2017-09-12 16:57:54 +02001087static int fuse_update_get_attr(struct inode *inode, struct file *file,
Miklos Szeredi2f1e8192018-10-15 15:43:06 +02001088 struct kstat *stat, u32 request_mask,
1089 unsigned int flags)
Miklos Szeredibcb4be82007-11-28 16:21:59 -08001090{
1091 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredi5b97eea2017-09-12 16:57:54 +02001092 int err = 0;
Miklos Szeredibf5c1892018-03-20 17:11:44 +01001093 bool sync;
Miklos Szeredibcb4be82007-11-28 16:21:59 -08001094
Miklos Szeredibf5c1892018-03-20 17:11:44 +01001095 if (flags & AT_STATX_FORCE_SYNC)
1096 sync = true;
1097 else if (flags & AT_STATX_DONT_SYNC)
1098 sync = false;
Miklos Szeredi2f1e8192018-10-15 15:43:06 +02001099 else if (request_mask & READ_ONCE(fi->inval_mask))
1100 sync = true;
Miklos Szeredibf5c1892018-03-20 17:11:44 +01001101 else
1102 sync = time_before64(fi->i_time, get_jiffies_64());
1103
1104 if (sync) {
Seth Forshee60bcc882016-08-29 08:46:37 -05001105 forget_all_cached_acls(inode);
Miklos Szeredibcb4be82007-11-28 16:21:59 -08001106 err = fuse_do_getattr(inode, stat, file);
Miklos Szeredi5b97eea2017-09-12 16:57:54 +02001107 } else if (stat) {
1108 generic_fillattr(inode, stat);
1109 stat->mode = fi->orig_i_mode;
1110 stat->ino = fi->orig_ino;
Miklos Szeredibcb4be82007-11-28 16:21:59 -08001111 }
1112
Miklos Szeredibcb4be82007-11-28 16:21:59 -08001113 return err;
1114}
1115
Miklos Szeredi5b97eea2017-09-12 16:57:54 +02001116int fuse_update_attributes(struct inode *inode, struct file *file)
1117{
Miklos Szeredi802dc042018-10-15 15:43:06 +02001118 /* Do *not* need to get atime for internal purposes */
1119 return fuse_update_get_attr(inode, file, NULL,
1120 STATX_BASIC_STATS & ~STATX_ATIME, 0);
Miklos Szeredi5b97eea2017-09-12 16:57:54 +02001121}
1122
Max Reitzfcee2162020-05-06 17:44:12 +02001123int fuse_reverse_inval_entry(struct fuse_conn *fc, u64 parent_nodeid,
John Muir451d0f52011-12-06 21:50:06 +01001124 u64 child_nodeid, struct qstr *name)
John Muir3b463ae2009-05-31 11:13:57 -04001125{
1126 int err = -ENOTDIR;
1127 struct inode *parent;
1128 struct dentry *dir;
1129 struct dentry *entry;
1130
Max Reitzfcee2162020-05-06 17:44:12 +02001131 parent = fuse_ilookup(fc, parent_nodeid, NULL);
John Muir3b463ae2009-05-31 11:13:57 -04001132 if (!parent)
1133 return -ENOENT;
1134
Miklos Szeredi5fd7d622021-10-22 17:03:01 +02001135 inode_lock_nested(parent, I_MUTEX_PARENT);
John Muir3b463ae2009-05-31 11:13:57 -04001136 if (!S_ISDIR(parent->i_mode))
1137 goto unlock;
1138
1139 err = -ENOENT;
1140 dir = d_find_alias(parent);
1141 if (!dir)
1142 goto unlock;
1143
Linus Torvalds8387ff22016-06-10 07:51:30 -07001144 name->hash = full_name_hash(dir, name->name, name->len);
John Muir3b463ae2009-05-31 11:13:57 -04001145 entry = d_lookup(dir, name);
1146 dput(dir);
1147 if (!entry)
1148 goto unlock;
1149
Miklos Szeredi261aaba72018-10-01 10:07:05 +02001150 fuse_dir_changed(parent);
John Muir3b463ae2009-05-31 11:13:57 -04001151 fuse_invalidate_entry(entry);
John Muir451d0f52011-12-06 21:50:06 +01001152
David Howells2b0143b2015-03-17 22:25:59 +00001153 if (child_nodeid != 0 && d_really_is_positive(entry)) {
Al Viro59551022016-01-22 15:40:57 -05001154 inode_lock(d_inode(entry));
David Howells2b0143b2015-03-17 22:25:59 +00001155 if (get_node_id(d_inode(entry)) != child_nodeid) {
John Muir451d0f52011-12-06 21:50:06 +01001156 err = -ENOENT;
1157 goto badentry;
1158 }
1159 if (d_mountpoint(entry)) {
1160 err = -EBUSY;
1161 goto badentry;
1162 }
David Howellse36cb0b2015-01-29 12:02:35 +00001163 if (d_is_dir(entry)) {
John Muir451d0f52011-12-06 21:50:06 +01001164 shrink_dcache_parent(entry);
1165 if (!simple_empty(entry)) {
1166 err = -ENOTEMPTY;
1167 goto badentry;
1168 }
David Howells2b0143b2015-03-17 22:25:59 +00001169 d_inode(entry)->i_flags |= S_DEAD;
John Muir451d0f52011-12-06 21:50:06 +01001170 }
1171 dont_mount(entry);
David Howells2b0143b2015-03-17 22:25:59 +00001172 clear_nlink(d_inode(entry));
John Muir451d0f52011-12-06 21:50:06 +01001173 err = 0;
1174 badentry:
Al Viro59551022016-01-22 15:40:57 -05001175 inode_unlock(d_inode(entry));
John Muir451d0f52011-12-06 21:50:06 +01001176 if (!err)
1177 d_delete(entry);
1178 } else {
1179 err = 0;
1180 }
John Muir3b463ae2009-05-31 11:13:57 -04001181 dput(entry);
John Muir3b463ae2009-05-31 11:13:57 -04001182
1183 unlock:
Al Viro59551022016-01-22 15:40:57 -05001184 inode_unlock(parent);
John Muir3b463ae2009-05-31 11:13:57 -04001185 iput(parent);
1186 return err;
1187}
1188
Miklos Szeredi87729a52005-09-09 13:10:34 -07001189/*
1190 * Calling into a user-controlled filesystem gives the filesystem
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001191 * daemon ptrace-like capabilities over the current process. This
Miklos Szeredi87729a52005-09-09 13:10:34 -07001192 * means, that the filesystem daemon is able to record the exact
1193 * filesystem operations performed, and can also control the behavior
1194 * of the requester process in otherwise impossible ways. For example
1195 * it can delay the operation for arbitrary length of time allowing
1196 * DoS against the requester.
1197 *
1198 * For this reason only those processes can call into the filesystem,
1199 * for which the owner of the mount has ptrace privilege. This
1200 * excludes processes started by other users, suid or sgid processes.
1201 */
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001202int fuse_allow_current_process(struct fuse_conn *fc)
Miklos Szeredi87729a52005-09-09 13:10:34 -07001203{
David Howellsc69e8d92008-11-14 10:39:19 +11001204 const struct cred *cred;
David Howellsc69e8d92008-11-14 10:39:19 +11001205
Miklos Szeredi29433a22016-10-01 07:32:32 +02001206 if (fc->allow_other)
Seth Forshee73f03c22017-12-22 15:32:33 +01001207 return current_in_userns(fc->user_ns);
Miklos Szeredi87729a52005-09-09 13:10:34 -07001208
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001209 cred = current_cred();
Eric W. Biederman499dcf22012-02-07 16:26:03 -08001210 if (uid_eq(cred->euid, fc->user_id) &&
1211 uid_eq(cred->suid, fc->user_id) &&
1212 uid_eq(cred->uid, fc->user_id) &&
1213 gid_eq(cred->egid, fc->group_id) &&
1214 gid_eq(cred->sgid, fc->group_id) &&
1215 gid_eq(cred->gid, fc->group_id))
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001216 return 1;
Miklos Szeredi87729a52005-09-09 13:10:34 -07001217
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001218 return 0;
Miklos Szeredi87729a52005-09-09 13:10:34 -07001219}
1220
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001221static int fuse_access(struct inode *inode, int mask)
1222{
Max Reitzfcee2162020-05-06 17:44:12 +02001223 struct fuse_mount *fm = get_fuse_mount(inode);
Miklos Szeredi70781872014-12-12 09:49:05 +01001224 FUSE_ARGS(args);
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001225 struct fuse_access_in inarg;
1226 int err;
1227
Miklos Szeredi698fa1d2013-10-01 16:41:23 +02001228 BUG_ON(mask & MAY_NOT_BLOCK);
1229
Max Reitzfcee2162020-05-06 17:44:12 +02001230 if (fm->fc->no_access)
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001231 return 0;
1232
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001233 memset(&inarg, 0, sizeof(inarg));
Al Viroe6305c42008-07-15 21:03:57 -04001234 inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC);
Miklos Szeredid5b48542019-09-10 15:04:08 +02001235 args.opcode = FUSE_ACCESS;
1236 args.nodeid = get_node_id(inode);
1237 args.in_numargs = 1;
1238 args.in_args[0].size = sizeof(inarg);
1239 args.in_args[0].value = &inarg;
Max Reitzfcee2162020-05-06 17:44:12 +02001240 err = fuse_simple_request(fm, &args);
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001241 if (err == -ENOSYS) {
Max Reitzfcee2162020-05-06 17:44:12 +02001242 fm->fc->no_access = 1;
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001243 err = 0;
1244 }
1245 return err;
1246}
1247
Al Viro10556cb2011-06-20 19:28:19 -04001248static int fuse_perm_getattr(struct inode *inode, int mask)
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001249{
Al Viro10556cb2011-06-20 19:28:19 -04001250 if (mask & MAY_NOT_BLOCK)
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001251 return -ECHILD;
1252
Seth Forshee60bcc882016-08-29 08:46:37 -05001253 forget_all_cached_acls(inode);
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001254 return fuse_do_getattr(inode, NULL, NULL);
1255}
1256
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001257/*
1258 * Check permission. The two basic access models of FUSE are:
1259 *
1260 * 1) Local access checking ('default_permissions' mount option) based
1261 * on file mode. This is the plain old disk filesystem permission
1262 * modell.
1263 *
1264 * 2) "Remote" access checking, where server is responsible for
1265 * checking permission in each inode operation. An exception to this
1266 * is if ->permission() was invoked from sys_access() in which case an
1267 * access request is sent. Execute permission is still checked
1268 * locally based on file mode.
1269 */
Al Viro10556cb2011-06-20 19:28:19 -04001270static int fuse_permission(struct inode *inode, int mask)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001271{
1272 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi244f6382007-10-16 23:31:02 -07001273 bool refreshed = false;
1274 int err = 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001275
Miklos Szeredi36cf9ae2020-12-10 15:33:14 +01001276 if (fuse_is_bad(inode))
1277 return -EIO;
1278
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001279 if (!fuse_allow_current_process(fc))
Miklos Szeredie5e55582005-09-09 13:10:28 -07001280 return -EACCES;
Miklos Szeredi244f6382007-10-16 23:31:02 -07001281
1282 /*
Miklos Szeredie8e96152007-10-16 23:31:06 -07001283 * If attributes are needed, refresh them before proceeding
Miklos Szeredi244f6382007-10-16 23:31:02 -07001284 */
Miklos Szeredi29433a22016-10-01 07:32:32 +02001285 if (fc->default_permissions ||
Miklos Szeredie8e96152007-10-16 23:31:06 -07001286 ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001287 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredid233c7d2018-12-03 10:14:43 +01001288 u32 perm_mask = STATX_MODE | STATX_UID | STATX_GID;
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001289
Miklos Szeredid233c7d2018-12-03 10:14:43 +01001290 if (perm_mask & READ_ONCE(fi->inval_mask) ||
1291 time_before64(fi->i_time, get_jiffies_64())) {
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001292 refreshed = true;
1293
Al Viro10556cb2011-06-20 19:28:19 -04001294 err = fuse_perm_getattr(inode, mask);
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001295 if (err)
1296 return err;
1297 }
Miklos Szeredi244f6382007-10-16 23:31:02 -07001298 }
1299
Miklos Szeredi29433a22016-10-01 07:32:32 +02001300 if (fc->default_permissions) {
Al Viro2830ba72011-06-20 19:16:29 -04001301 err = generic_permission(inode, mask);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001302
1303 /* If permission is denied, try to refresh file
1304 attributes. This is also needed, because the root
1305 node will at first have no permissions */
Miklos Szeredi244f6382007-10-16 23:31:02 -07001306 if (err == -EACCES && !refreshed) {
Al Viro10556cb2011-06-20 19:28:19 -04001307 err = fuse_perm_getattr(inode, mask);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001308 if (!err)
Al Viro2830ba72011-06-20 19:16:29 -04001309 err = generic_permission(inode, mask);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001310 }
1311
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001312 /* Note: the opposite of the above test does not
1313 exist. So if permissions are revoked this won't be
1314 noticed immediately, only after the attribute
1315 timeout has expired */
Eric Paris9cfcac82010-07-23 11:43:51 -04001316 } else if (mask & (MAY_ACCESS | MAY_CHDIR)) {
Miklos Szeredie8e96152007-10-16 23:31:06 -07001317 err = fuse_access(inode, mask);
1318 } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
1319 if (!(inode->i_mode & S_IXUGO)) {
1320 if (refreshed)
1321 return -EACCES;
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001322
Al Viro10556cb2011-06-20 19:28:19 -04001323 err = fuse_perm_getattr(inode, mask);
Miklos Szeredie8e96152007-10-16 23:31:06 -07001324 if (!err && !(inode->i_mode & S_IXUGO))
1325 return -EACCES;
1326 }
Miklos Szeredie5e55582005-09-09 13:10:28 -07001327 }
Miklos Szeredi244f6382007-10-16 23:31:02 -07001328 return err;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001329}
1330
Dan Schatzberg5571f1e2018-10-11 08:17:00 -07001331static int fuse_readlink_page(struct inode *inode, struct page *page)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001332{
Max Reitzfcee2162020-05-06 17:44:12 +02001333 struct fuse_mount *fm = get_fuse_mount(inode);
Miklos Szeredi4c29afe2019-09-10 15:04:09 +02001334 struct fuse_page_desc desc = { .length = PAGE_SIZE - 1 };
1335 struct fuse_args_pages ap = {
1336 .num_pages = 1,
1337 .pages = &page,
1338 .descs = &desc,
1339 };
1340 char *link;
1341 ssize_t res;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001342
Miklos Szeredi4c29afe2019-09-10 15:04:09 +02001343 ap.args.opcode = FUSE_READLINK;
1344 ap.args.nodeid = get_node_id(inode);
1345 ap.args.out_pages = true;
1346 ap.args.out_argvar = true;
1347 ap.args.page_zeroing = true;
1348 ap.args.out_numargs = 1;
1349 ap.args.out_args[0].size = desc.length;
Max Reitzfcee2162020-05-06 17:44:12 +02001350 res = fuse_simple_request(fm, &ap.args);
Al Viro6b255392015-11-17 10:20:54 -05001351
Andrew Gallagher451418f2013-11-05 03:55:43 -08001352 fuse_invalidate_atime(inode);
Dan Schatzberg5571f1e2018-10-11 08:17:00 -07001353
Miklos Szeredi4c29afe2019-09-10 15:04:09 +02001354 if (res < 0)
1355 return res;
1356
1357 if (WARN_ON(res >= PAGE_SIZE))
1358 return -EIO;
1359
1360 link = page_address(page);
1361 link[res] = '\0';
1362
1363 return 0;
Dan Schatzberg5571f1e2018-10-11 08:17:00 -07001364}
1365
1366static const char *fuse_get_link(struct dentry *dentry, struct inode *inode,
1367 struct delayed_call *callback)
1368{
1369 struct fuse_conn *fc = get_fuse_conn(inode);
1370 struct page *page;
1371 int err;
1372
1373 err = -EIO;
Miklos Szeredi36cf9ae2020-12-10 15:33:14 +01001374 if (fuse_is_bad(inode))
Dan Schatzberg5571f1e2018-10-11 08:17:00 -07001375 goto out_err;
1376
1377 if (fc->cache_symlinks)
1378 return page_get_link(dentry, inode, callback);
1379
1380 err = -ECHILD;
1381 if (!dentry)
1382 goto out_err;
1383
1384 page = alloc_page(GFP_KERNEL);
1385 err = -ENOMEM;
1386 if (!page)
1387 goto out_err;
1388
1389 err = fuse_readlink_page(inode, page);
1390 if (err) {
1391 __free_page(page);
1392 goto out_err;
1393 }
1394
1395 set_delayed_call(callback, page_put_link, page);
1396
1397 return page_address(page);
1398
1399out_err:
1400 return ERR_PTR(err);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001401}
1402
Miklos Szeredie5e55582005-09-09 13:10:28 -07001403static int fuse_dir_open(struct inode *inode, struct file *file)
1404{
Miklos Szeredi91fe96b2009-04-28 16:56:37 +02001405 return fuse_open_common(inode, file, true);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001406}
1407
1408static int fuse_dir_release(struct inode *inode, struct file *file)
1409{
Chad Austin2e64ff12018-12-10 10:54:52 -08001410 fuse_release_common(file, true);
Miklos Szeredi8b0797a2009-04-28 16:56:39 +02001411
1412 return 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001413}
1414
Josef Bacik02c24a82011-07-16 20:44:56 -04001415static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end,
1416 int datasync)
Miklos Szeredi82547982005-09-09 13:10:38 -07001417{
Miklos Szeredia9c2d1e2018-12-03 10:14:43 +01001418 struct inode *inode = file->f_mapping->host;
1419 struct fuse_conn *fc = get_fuse_conn(inode);
1420 int err;
1421
Miklos Szeredi36cf9ae2020-12-10 15:33:14 +01001422 if (fuse_is_bad(inode))
Miklos Szeredia9c2d1e2018-12-03 10:14:43 +01001423 return -EIO;
1424
1425 if (fc->no_fsyncdir)
1426 return 0;
1427
1428 inode_lock(inode);
1429 err = fuse_fsync_common(file, start, end, datasync, FUSE_FSYNCDIR);
1430 if (err == -ENOSYS) {
1431 fc->no_fsyncdir = 1;
1432 err = 0;
1433 }
1434 inode_unlock(inode);
1435
1436 return err;
Miklos Szeredi82547982005-09-09 13:10:38 -07001437}
1438
Miklos Szeredib18da0c2011-12-13 11:58:49 +01001439static long fuse_dir_ioctl(struct file *file, unsigned int cmd,
1440 unsigned long arg)
1441{
1442 struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1443
1444 /* FUSE_IOCTL_DIR only supported for API version >= 7.18 */
1445 if (fc->minor < 18)
1446 return -ENOTTY;
1447
1448 return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR);
1449}
1450
1451static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd,
1452 unsigned long arg)
1453{
1454 struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1455
1456 if (fc->minor < 18)
1457 return -ENOTTY;
1458
1459 return fuse_ioctl_common(file, cmd, arg,
1460 FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR);
1461}
1462
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001463static bool update_mtime(unsigned ivalid, bool trust_local_mtime)
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001464{
1465 /* Always update if mtime is explicitly set */
1466 if (ivalid & ATTR_MTIME_SET)
1467 return true;
1468
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001469 /* Or if kernel i_mtime is the official one */
1470 if (trust_local_mtime)
1471 return true;
1472
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001473 /* If it's an open(O_TRUNC) or an ftruncate(), don't update */
1474 if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
1475 return false;
1476
1477 /* In all other cases update */
1478 return true;
1479}
1480
Eric W. Biederman8cb08322018-02-21 11:18:07 -06001481static void iattr_to_fattr(struct fuse_conn *fc, struct iattr *iattr,
1482 struct fuse_setattr_in *arg, bool trust_local_cmtime)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001483{
1484 unsigned ivalid = iattr->ia_valid;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001485
1486 if (ivalid & ATTR_MODE)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001487 arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001488 if (ivalid & ATTR_UID)
Eric W. Biederman8cb08322018-02-21 11:18:07 -06001489 arg->valid |= FATTR_UID, arg->uid = from_kuid(fc->user_ns, iattr->ia_uid);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001490 if (ivalid & ATTR_GID)
Eric W. Biederman8cb08322018-02-21 11:18:07 -06001491 arg->valid |= FATTR_GID, arg->gid = from_kgid(fc->user_ns, iattr->ia_gid);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001492 if (ivalid & ATTR_SIZE)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001493 arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001494 if (ivalid & ATTR_ATIME) {
1495 arg->valid |= FATTR_ATIME;
Miklos Szeredibefc6492005-11-07 00:59:52 -08001496 arg->atime = iattr->ia_atime.tv_sec;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001497 arg->atimensec = iattr->ia_atime.tv_nsec;
1498 if (!(ivalid & ATTR_ATIME_SET))
1499 arg->valid |= FATTR_ATIME_NOW;
1500 }
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001501 if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, trust_local_cmtime)) {
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001502 arg->valid |= FATTR_MTIME;
Miklos Szeredibefc6492005-11-07 00:59:52 -08001503 arg->mtime = iattr->ia_mtime.tv_sec;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001504 arg->mtimensec = iattr->ia_mtime.tv_nsec;
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001505 if (!(ivalid & ATTR_MTIME_SET) && !trust_local_cmtime)
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001506 arg->valid |= FATTR_MTIME_NOW;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001507 }
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001508 if ((ivalid & ATTR_CTIME) && trust_local_cmtime) {
1509 arg->valid |= FATTR_CTIME;
1510 arg->ctime = iattr->ia_ctime.tv_sec;
1511 arg->ctimensec = iattr->ia_ctime.tv_nsec;
1512 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001513}
1514
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001515/*
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001516 * Prevent concurrent writepages on inode
1517 *
1518 * This is done by adding a negative bias to the inode write counter
1519 * and waiting for all pending writes to finish.
1520 */
1521void fuse_set_nowrite(struct inode *inode)
1522{
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001523 struct fuse_inode *fi = get_fuse_inode(inode);
1524
Al Viro59551022016-01-22 15:40:57 -05001525 BUG_ON(!inode_is_locked(inode));
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001526
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +03001527 spin_lock(&fi->lock);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001528 BUG_ON(fi->writectr < 0);
1529 fi->writectr += FUSE_NOWRITE;
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +03001530 spin_unlock(&fi->lock);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001531 wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE);
1532}
1533
1534/*
1535 * Allow writepages on inode
1536 *
1537 * Remove the bias from the writecounter and send any queued
1538 * writepages.
1539 */
1540static void __fuse_release_nowrite(struct inode *inode)
1541{
1542 struct fuse_inode *fi = get_fuse_inode(inode);
1543
1544 BUG_ON(fi->writectr != FUSE_NOWRITE);
1545 fi->writectr = 0;
1546 fuse_flush_writepages(inode);
1547}
1548
1549void fuse_release_nowrite(struct inode *inode)
1550{
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +03001551 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001552
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +03001553 spin_lock(&fi->lock);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001554 __fuse_release_nowrite(inode);
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +03001555 spin_unlock(&fi->lock);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001556}
1557
Miklos Szeredi70781872014-12-12 09:49:05 +01001558static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_args *args,
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001559 struct inode *inode,
1560 struct fuse_setattr_in *inarg_p,
1561 struct fuse_attr_out *outarg_p)
1562{
Miklos Szeredid5b48542019-09-10 15:04:08 +02001563 args->opcode = FUSE_SETATTR;
1564 args->nodeid = get_node_id(inode);
1565 args->in_numargs = 1;
1566 args->in_args[0].size = sizeof(*inarg_p);
1567 args->in_args[0].value = inarg_p;
1568 args->out_numargs = 1;
1569 args->out_args[0].size = sizeof(*outarg_p);
1570 args->out_args[0].value = outarg_p;
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001571}
1572
1573/*
1574 * Flush inode->i_mtime to the server
1575 */
Maxim Patlasovab9e13f2014-04-28 14:19:24 +02001576int fuse_flush_times(struct inode *inode, struct fuse_file *ff)
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001577{
Max Reitzfcee2162020-05-06 17:44:12 +02001578 struct fuse_mount *fm = get_fuse_mount(inode);
Miklos Szeredi70781872014-12-12 09:49:05 +01001579 FUSE_ARGS(args);
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001580 struct fuse_setattr_in inarg;
1581 struct fuse_attr_out outarg;
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001582
1583 memset(&inarg, 0, sizeof(inarg));
1584 memset(&outarg, 0, sizeof(outarg));
1585
Maxim Patlasovab9e13f2014-04-28 14:19:24 +02001586 inarg.valid = FATTR_MTIME;
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001587 inarg.mtime = inode->i_mtime.tv_sec;
1588 inarg.mtimensec = inode->i_mtime.tv_nsec;
Max Reitzfcee2162020-05-06 17:44:12 +02001589 if (fm->fc->minor >= 23) {
Maxim Patlasovab9e13f2014-04-28 14:19:24 +02001590 inarg.valid |= FATTR_CTIME;
1591 inarg.ctime = inode->i_ctime.tv_sec;
1592 inarg.ctimensec = inode->i_ctime.tv_nsec;
1593 }
Miklos Szeredi1e18bda2014-04-28 14:19:23 +02001594 if (ff) {
1595 inarg.valid |= FATTR_FH;
1596 inarg.fh = ff->fh;
1597 }
Max Reitzfcee2162020-05-06 17:44:12 +02001598 fuse_setattr_fill(fm->fc, &args, inode, &inarg, &outarg);
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001599
Max Reitzfcee2162020-05-06 17:44:12 +02001600 return fuse_simple_request(fm, &args);
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001601}
1602
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001603/*
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001604 * Set attributes, and at the same time refresh them.
1605 *
1606 * Truncation is slightly complicated, because the 'truncate' request
1607 * may fail, in which case we don't want to touch the mapping.
Miklos Szeredi9ffbb912006-10-17 00:10:06 -07001608 * vmtruncate() doesn't allow for this case, so do the rlimit checking
1609 * and the actual truncation by hand.
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001610 */
Jan Kara62490332016-05-26 17:12:41 +02001611int fuse_do_setattr(struct dentry *dentry, struct iattr *attr,
Maxim Patlasovefb9fa92012-12-18 14:05:08 +04001612 struct file *file)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001613{
Jan Kara62490332016-05-26 17:12:41 +02001614 struct inode *inode = d_inode(dentry);
Max Reitzfcee2162020-05-06 17:44:12 +02001615 struct fuse_mount *fm = get_fuse_mount(inode);
1616 struct fuse_conn *fc = fm->fc;
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001617 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredi70781872014-12-12 09:49:05 +01001618 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001619 struct fuse_setattr_in inarg;
1620 struct fuse_attr_out outarg;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001621 bool is_truncate = false;
Pavel Emelyanov83732002013-10-10 17:10:46 +04001622 bool is_wb = fc->writeback_cache;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001623 loff_t oldsize;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001624 int err;
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001625 bool trust_local_cmtime = is_wb && S_ISREG(inode->i_mode);
Vivek Goyal6ae330c2020-08-19 18:19:54 -04001626 bool fault_blocked = false;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001627
Miklos Szeredi29433a22016-10-01 07:32:32 +02001628 if (!fc->default_permissions)
Christoph Hellwigdb78b872010-06-04 11:30:03 +02001629 attr->ia_valid |= ATTR_FORCE;
1630
Jan Kara31051c82016-05-26 16:55:18 +02001631 err = setattr_prepare(dentry, attr);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02001632 if (err)
1633 return err;
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001634
Vivek Goyal6ae330c2020-08-19 18:19:54 -04001635 if (attr->ia_valid & ATTR_SIZE) {
1636 if (WARN_ON(!S_ISREG(inode->i_mode)))
1637 return -EIO;
1638 is_truncate = true;
1639 }
1640
1641 if (FUSE_IS_DAX(inode) && is_truncate) {
1642 down_write(&fi->i_mmap_sem);
1643 fault_blocked = true;
1644 err = fuse_dax_break_layouts(inode, 0, 0);
1645 if (err) {
1646 up_write(&fi->i_mmap_sem);
1647 return err;
1648 }
1649 }
1650
Miklos Szeredi8d56add2011-02-25 14:44:58 +01001651 if (attr->ia_valid & ATTR_OPEN) {
Miklos Szeredidf0e91d2018-02-08 15:17:38 +01001652 /* This is coming from open(..., ... | O_TRUNC); */
1653 WARN_ON(!(attr->ia_valid & ATTR_SIZE));
1654 WARN_ON(attr->ia_size != 0);
1655 if (fc->atomic_o_trunc) {
1656 /*
1657 * No need to send request to userspace, since actual
1658 * truncation has already been done by OPEN. But still
1659 * need to truncate page cache.
1660 */
1661 i_size_write(inode, 0);
1662 truncate_pagecache(inode, 0);
Vivek Goyal6ae330c2020-08-19 18:19:54 -04001663 goto out;
Miklos Szeredidf0e91d2018-02-08 15:17:38 +01001664 }
Miklos Szeredi8d56add2011-02-25 14:44:58 +01001665 file = NULL;
1666 }
Miklos Szeredi6ff958e2007-10-18 03:07:02 -07001667
Miklos Szeredib24e7592019-10-23 14:26:37 +02001668 /* Flush dirty data/metadata before non-truncate SETATTR */
1669 if (is_wb && S_ISREG(inode->i_mode) &&
1670 attr->ia_valid &
1671 (ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_MTIME_SET |
1672 ATTR_TIMES_SET)) {
1673 err = write_inode_now(inode, true);
1674 if (err)
1675 return err;
1676
1677 fuse_set_nowrite(inode);
1678 fuse_release_nowrite(inode);
1679 }
1680
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001681 if (is_truncate) {
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001682 fuse_set_nowrite(inode);
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001683 set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001684 if (trust_local_cmtime && attr->ia_size != inode->i_size)
1685 attr->ia_valid |= ATTR_MTIME | ATTR_CTIME;
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001686 }
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001687
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001688 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -07001689 memset(&outarg, 0, sizeof(outarg));
Eric W. Biederman8cb08322018-02-21 11:18:07 -06001690 iattr_to_fattr(fc, attr, &inarg, trust_local_cmtime);
Miklos Szeredi49d49142007-10-18 03:07:00 -07001691 if (file) {
1692 struct fuse_file *ff = file->private_data;
1693 inarg.valid |= FATTR_FH;
1694 inarg.fh = ff->fh;
1695 }
Miklos Szeredif3332112007-10-18 03:07:04 -07001696 if (attr->ia_valid & ATTR_SIZE) {
1697 /* For mandatory locking in truncate */
1698 inarg.valid |= FATTR_LOCKOWNER;
1699 inarg.lock_owner = fuse_lock_owner_id(fc, current->files);
1700 }
Miklos Szeredi70781872014-12-12 09:49:05 +01001701 fuse_setattr_fill(fc, &args, inode, &inarg, &outarg);
Max Reitzfcee2162020-05-06 17:44:12 +02001702 err = fuse_simple_request(fm, &args);
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001703 if (err) {
1704 if (err == -EINTR)
1705 fuse_invalidate_attr(inode);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001706 goto error;
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001707 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001708
Miklos Szeredieb59bd12019-11-12 11:49:04 +01001709 if (fuse_invalid_attr(&outarg.attr) ||
Al Viro40ba4332021-03-01 20:37:10 -05001710 inode_wrong_type(inode, outarg.attr.mode)) {
Miklos Szeredi36cf9ae2020-12-10 15:33:14 +01001711 fuse_make_bad(inode);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001712 err = -EIO;
1713 goto error;
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001714 }
1715
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +03001716 spin_lock(&fi->lock);
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001717 /* the kernel maintains i_mtime locally */
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001718 if (trust_local_cmtime) {
1719 if (attr->ia_valid & ATTR_MTIME)
1720 inode->i_mtime = attr->ia_mtime;
1721 if (attr->ia_valid & ATTR_CTIME)
1722 inode->i_ctime = attr->ia_ctime;
Miklos Szeredi1e18bda2014-04-28 14:19:23 +02001723 /* FIXME: clear I_DIRTY_SYNC? */
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001724 }
1725
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001726 fuse_change_attributes_common(inode, &outarg.attr,
1727 attr_timeout(&outarg));
1728 oldsize = inode->i_size;
Pavel Emelyanov83732002013-10-10 17:10:46 +04001729 /* see the comment in fuse_change_attributes() */
1730 if (!is_wb || is_truncate || !S_ISREG(inode->i_mode))
1731 i_size_write(inode, outarg.attr.size);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001732
1733 if (is_truncate) {
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +03001734 /* NOTE: this may release/reacquire fi->lock */
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001735 __fuse_release_nowrite(inode);
1736 }
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +03001737 spin_unlock(&fi->lock);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001738
1739 /*
1740 * Only call invalidate_inode_pages2() after removing
1741 * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock.
1742 */
Pavel Emelyanov83732002013-10-10 17:10:46 +04001743 if ((is_truncate || !is_wb) &&
1744 S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
Kirill A. Shutemov7caef262013-09-12 15:13:56 -07001745 truncate_pagecache(inode, outarg.attr.size);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001746 invalidate_inode_pages2(inode->i_mapping);
1747 }
1748
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001749 clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
Vivek Goyal6ae330c2020-08-19 18:19:54 -04001750out:
1751 if (fault_blocked)
1752 up_write(&fi->i_mmap_sem);
1753
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001754 return 0;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001755
1756error:
1757 if (is_truncate)
1758 fuse_release_nowrite(inode);
1759
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001760 clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
Vivek Goyal6ae330c2020-08-19 18:19:54 -04001761
1762 if (fault_blocked)
1763 up_write(&fi->i_mmap_sem);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001764 return err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001765}
1766
Miklos Szeredi49d49142007-10-18 03:07:00 -07001767static int fuse_setattr(struct dentry *entry, struct iattr *attr)
1768{
David Howells2b0143b2015-03-17 22:25:59 +00001769 struct inode *inode = d_inode(entry);
Miklos Szeredi5e940c12016-10-01 07:32:32 +02001770 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredia09f99e2016-10-01 07:32:32 +02001771 struct file *file = (attr->ia_valid & ATTR_FILE) ? attr->ia_file : NULL;
Miklos Szeredi5e2b8822016-10-01 07:32:32 +02001772 int ret;
Maxim Patlasovefb9fa92012-12-18 14:05:08 +04001773
Miklos Szeredi36cf9ae2020-12-10 15:33:14 +01001774 if (fuse_is_bad(inode))
1775 return -EIO;
1776
Maxim Patlasovefb9fa92012-12-18 14:05:08 +04001777 if (!fuse_allow_current_process(get_fuse_conn(inode)))
1778 return -EACCES;
1779
Miklos Szeredia09f99e2016-10-01 07:32:32 +02001780 if (attr->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) {
Miklos Szeredia09f99e2016-10-01 07:32:32 +02001781 attr->ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID |
1782 ATTR_MODE);
Miklos Szeredia09f99e2016-10-01 07:32:32 +02001783
Miklos Szeredi5e940c12016-10-01 07:32:32 +02001784 /*
1785 * The only sane way to reliably kill suid/sgid is to do it in
1786 * the userspace filesystem
1787 *
1788 * This should be done on write(), truncate() and chown().
1789 */
1790 if (!fc->handle_killpriv) {
Miklos Szeredi5e940c12016-10-01 07:32:32 +02001791 /*
1792 * ia_mode calculation may have used stale i_mode.
1793 * Refresh and recalculate.
1794 */
1795 ret = fuse_do_getattr(inode, NULL, file);
1796 if (ret)
1797 return ret;
1798
1799 attr->ia_mode = inode->i_mode;
Miklos Szeredic01638f2016-12-06 16:18:45 +01001800 if (inode->i_mode & S_ISUID) {
Miklos Szeredi5e940c12016-10-01 07:32:32 +02001801 attr->ia_valid |= ATTR_MODE;
1802 attr->ia_mode &= ~S_ISUID;
1803 }
Miklos Szeredic01638f2016-12-06 16:18:45 +01001804 if ((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
Miklos Szeredi5e940c12016-10-01 07:32:32 +02001805 attr->ia_valid |= ATTR_MODE;
1806 attr->ia_mode &= ~S_ISGID;
1807 }
Miklos Szeredia09f99e2016-10-01 07:32:32 +02001808 }
1809 }
1810 if (!attr->ia_valid)
1811 return 0;
1812
Linus Torvaldsabb5a142016-10-10 13:04:49 -07001813 ret = fuse_do_setattr(entry, attr, file);
Miklos Szeredi5e2b8822016-10-01 07:32:32 +02001814 if (!ret) {
Seth Forshee60bcc882016-08-29 08:46:37 -05001815 /*
1816 * If filesystem supports acls it may have updated acl xattrs in
1817 * the filesystem, so forget cached acls for the inode.
1818 */
1819 if (fc->posix_acl)
1820 forget_all_cached_acls(inode);
1821
Miklos Szeredi5e2b8822016-10-01 07:32:32 +02001822 /* Directory mode changed, may need to revalidate access */
1823 if (d_is_dir(entry) && (attr->ia_valid & ATTR_MODE))
1824 fuse_invalidate_entry_cache(entry);
1825 }
1826 return ret;
Miklos Szeredi49d49142007-10-18 03:07:00 -07001827}
1828
David Howellsa528d352017-01-31 16:46:22 +00001829static int fuse_getattr(const struct path *path, struct kstat *stat,
1830 u32 request_mask, unsigned int flags)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001831{
David Howellsa528d352017-01-31 16:46:22 +00001832 struct inode *inode = d_inode(path->dentry);
Miklos Szeredi244f6382007-10-16 23:31:02 -07001833 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi244f6382007-10-16 23:31:02 -07001834
Miklos Szeredi36cf9ae2020-12-10 15:33:14 +01001835 if (fuse_is_bad(inode))
1836 return -EIO;
1837
Miklos Szeredi5157da22020-05-19 14:50:37 +02001838 if (!fuse_allow_current_process(fc)) {
1839 if (!request_mask) {
1840 /*
1841 * If user explicitly requested *nothing* then don't
1842 * error out, but return st_dev only.
1843 */
1844 stat->result_mask = 0;
1845 stat->dev = inode->i_sb->s_dev;
1846 return 0;
1847 }
Miklos Szeredi244f6382007-10-16 23:31:02 -07001848 return -EACCES;
Miklos Szeredi5157da22020-05-19 14:50:37 +02001849 }
Miklos Szeredi244f6382007-10-16 23:31:02 -07001850
Miklos Szeredi2f1e8192018-10-15 15:43:06 +02001851 return fuse_update_get_attr(inode, NULL, stat, request_mask, flags);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001852}
1853
Arjan van de Ven754661f2007-02-12 00:55:38 -08001854static const struct inode_operations fuse_dir_inode_operations = {
Miklos Szeredie5e55582005-09-09 13:10:28 -07001855 .lookup = fuse_lookup,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001856 .mkdir = fuse_mkdir,
1857 .symlink = fuse_symlink,
1858 .unlink = fuse_unlink,
1859 .rmdir = fuse_rmdir,
Miklos Szeredi2773bf02016-09-27 11:03:58 +02001860 .rename = fuse_rename2,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001861 .link = fuse_link,
1862 .setattr = fuse_setattr,
1863 .create = fuse_create,
Miklos Szeredic8ccbe02012-06-05 15:10:22 +02001864 .atomic_open = fuse_atomic_open,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001865 .mknod = fuse_mknod,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001866 .permission = fuse_permission,
1867 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001868 .listxattr = fuse_listxattr,
Seth Forshee60bcc882016-08-29 08:46:37 -05001869 .get_acl = fuse_get_acl,
1870 .set_acl = fuse_set_acl,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001871};
1872
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -08001873static const struct file_operations fuse_dir_operations = {
Miklos Szeredib6aeade2005-09-09 13:10:30 -07001874 .llseek = generic_file_llseek,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001875 .read = generic_read_dir,
Al Virod9b3dbd2016-04-20 17:30:32 -04001876 .iterate_shared = fuse_readdir,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001877 .open = fuse_dir_open,
1878 .release = fuse_dir_release,
Miklos Szeredi82547982005-09-09 13:10:38 -07001879 .fsync = fuse_dir_fsync,
Miklos Szeredib18da0c2011-12-13 11:58:49 +01001880 .unlocked_ioctl = fuse_dir_ioctl,
1881 .compat_ioctl = fuse_dir_compat_ioctl,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001882};
1883
Arjan van de Ven754661f2007-02-12 00:55:38 -08001884static const struct inode_operations fuse_common_inode_operations = {
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001885 .setattr = fuse_setattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001886 .permission = fuse_permission,
1887 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001888 .listxattr = fuse_listxattr,
Seth Forshee60bcc882016-08-29 08:46:37 -05001889 .get_acl = fuse_get_acl,
1890 .set_acl = fuse_set_acl,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001891};
1892
Arjan van de Ven754661f2007-02-12 00:55:38 -08001893static const struct inode_operations fuse_symlink_inode_operations = {
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001894 .setattr = fuse_setattr,
Al Viro6b255392015-11-17 10:20:54 -05001895 .get_link = fuse_get_link,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001896 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001897 .listxattr = fuse_listxattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001898};
1899
1900void fuse_init_common(struct inode *inode)
1901{
1902 inode->i_op = &fuse_common_inode_operations;
1903}
1904
1905void fuse_init_dir(struct inode *inode)
1906{
Miklos Szerediab2257e2018-10-01 10:07:05 +02001907 struct fuse_inode *fi = get_fuse_inode(inode);
1908
Miklos Szeredie5e55582005-09-09 13:10:28 -07001909 inode->i_op = &fuse_dir_inode_operations;
1910 inode->i_fop = &fuse_dir_operations;
Miklos Szerediab2257e2018-10-01 10:07:05 +02001911
1912 spin_lock_init(&fi->rdc.lock);
1913 fi->rdc.cached = false;
1914 fi->rdc.size = 0;
1915 fi->rdc.pos = 0;
1916 fi->rdc.version = 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001917}
1918
Dan Schatzberg5571f1e2018-10-11 08:17:00 -07001919static int fuse_symlink_readpage(struct file *null, struct page *page)
1920{
1921 int err = fuse_readlink_page(page->mapping->host, page);
1922
1923 if (!err)
1924 SetPageUptodate(page);
1925
1926 unlock_page(page);
1927
1928 return err;
1929}
1930
1931static const struct address_space_operations fuse_symlink_aops = {
1932 .readpage = fuse_symlink_readpage,
1933};
1934
Miklos Szeredie5e55582005-09-09 13:10:28 -07001935void fuse_init_symlink(struct inode *inode)
1936{
1937 inode->i_op = &fuse_symlink_inode_operations;
Dan Schatzberg5571f1e2018-10-11 08:17:00 -07001938 inode->i_data.a_ops = &fuse_symlink_aops;
1939 inode_nohighmem(inode);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001940}