xref: /openbmc/linux/fs/fuse/dir.c (revision 8d8f9c4b8df6bc2bf005c91b73b23a0e60f0e413)
1e5e5558eSMiklos Szeredi /*
2e5e5558eSMiklos Szeredi   FUSE: Filesystem in Userspace
31729a16cSMiklos Szeredi   Copyright (C) 2001-2008  Miklos Szeredi <miklos@szeredi.hu>
4e5e5558eSMiklos Szeredi 
5e5e5558eSMiklos Szeredi   This program can be distributed under the terms of the GNU GPL.
6e5e5558eSMiklos Szeredi   See the file COPYING.
7e5e5558eSMiklos Szeredi */
8e5e5558eSMiklos Szeredi 
9e5e5558eSMiklos Szeredi #include "fuse_i.h"
10e5e5558eSMiklos Szeredi 
11e5e5558eSMiklos Szeredi #include <linux/pagemap.h>
12e5e5558eSMiklos Szeredi #include <linux/file.h>
13bf109c64SMax Reitz #include <linux/fs_context.h>
149ccf47b2SDave Marchevsky #include <linux/moduleparam.h>
15e5e5558eSMiklos Szeredi #include <linux/sched.h>
16e5e5558eSMiklos Szeredi #include <linux/namei.h>
1707e77dcaSMiklos Szeredi #include <linux/slab.h>
18703c7362SSeth Forshee #include <linux/xattr.h>
19261aaba7SMiklos Szeredi #include <linux/iversion.h>
2060bcc88aSSeth Forshee #include <linux/posix_acl.h>
213e2b6fdbSVivek Goyal #include <linux/security.h>
223e2b6fdbSVivek Goyal #include <linux/types.h>
233e2b6fdbSVivek Goyal #include <linux/kernel.h>
24e5e5558eSMiklos Szeredi 
259ccf47b2SDave Marchevsky static bool __read_mostly allow_sys_admin_access;
269ccf47b2SDave Marchevsky module_param(allow_sys_admin_access, bool, 0644);
279ccf47b2SDave Marchevsky MODULE_PARM_DESC(allow_sys_admin_access,
289ccf47b2SDave Marchevsky 		 "Allow users with CAP_SYS_ADMIN in initial userns to bypass allow_other access check");
299ccf47b2SDave Marchevsky 
304582a4abSFeng Shuo static void fuse_advise_use_readdirplus(struct inode *dir)
314582a4abSFeng Shuo {
324582a4abSFeng Shuo 	struct fuse_inode *fi = get_fuse_inode(dir);
334582a4abSFeng Shuo 
344582a4abSFeng Shuo 	set_bit(FUSE_I_ADVISE_RDPLUS, &fi->state);
354582a4abSFeng Shuo }
364582a4abSFeng Shuo 
3730c6a23dSKhazhismel Kumykov #if BITS_PER_LONG >= 64
3830c6a23dSKhazhismel Kumykov static inline void __fuse_dentry_settime(struct dentry *entry, u64 time)
3930c6a23dSKhazhismel Kumykov {
4030c6a23dSKhazhismel Kumykov 	entry->d_fsdata = (void *) time;
4130c6a23dSKhazhismel Kumykov }
4230c6a23dSKhazhismel Kumykov 
4330c6a23dSKhazhismel Kumykov static inline u64 fuse_dentry_time(const struct dentry *entry)
4430c6a23dSKhazhismel Kumykov {
4530c6a23dSKhazhismel Kumykov 	return (u64)entry->d_fsdata;
4630c6a23dSKhazhismel Kumykov }
4730c6a23dSKhazhismel Kumykov 
4830c6a23dSKhazhismel Kumykov #else
49f75fdf22SMiklos Szeredi union fuse_dentry {
50f75fdf22SMiklos Szeredi 	u64 time;
51f75fdf22SMiklos Szeredi 	struct rcu_head rcu;
52f75fdf22SMiklos Szeredi };
53f75fdf22SMiklos Szeredi 
5430c6a23dSKhazhismel Kumykov static inline void __fuse_dentry_settime(struct dentry *dentry, u64 time)
5530c6a23dSKhazhismel Kumykov {
5630c6a23dSKhazhismel Kumykov 	((union fuse_dentry *) dentry->d_fsdata)->time = time;
5730c6a23dSKhazhismel Kumykov }
5830c6a23dSKhazhismel Kumykov 
5930c6a23dSKhazhismel Kumykov static inline u64 fuse_dentry_time(const struct dentry *entry)
6030c6a23dSKhazhismel Kumykov {
6130c6a23dSKhazhismel Kumykov 	return ((union fuse_dentry *) entry->d_fsdata)->time;
6230c6a23dSKhazhismel Kumykov }
6330c6a23dSKhazhismel Kumykov #endif
6430c6a23dSKhazhismel Kumykov 
658fab0106SMiklos Szeredi static void fuse_dentry_settime(struct dentry *dentry, u64 time)
660a0898cfSMiklos Szeredi {
678fab0106SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn_super(dentry->d_sb);
688fab0106SMiklos Szeredi 	bool delete = !time && fc->delete_stale;
698fab0106SMiklos Szeredi 	/*
708fab0106SMiklos Szeredi 	 * Mess with DCACHE_OP_DELETE because dput() will be faster without it.
718fab0106SMiklos Szeredi 	 * Don't care about races, either way it's just an optimization
728fab0106SMiklos Szeredi 	 */
738fab0106SMiklos Szeredi 	if ((!delete && (dentry->d_flags & DCACHE_OP_DELETE)) ||
748fab0106SMiklos Szeredi 	    (delete && !(dentry->d_flags & DCACHE_OP_DELETE))) {
758fab0106SMiklos Szeredi 		spin_lock(&dentry->d_lock);
768fab0106SMiklos Szeredi 		if (!delete)
778fab0106SMiklos Szeredi 			dentry->d_flags &= ~DCACHE_OP_DELETE;
788fab0106SMiklos Szeredi 		else
798fab0106SMiklos Szeredi 			dentry->d_flags |= DCACHE_OP_DELETE;
808fab0106SMiklos Szeredi 		spin_unlock(&dentry->d_lock);
810a0898cfSMiklos Szeredi 	}
820a0898cfSMiklos Szeredi 
8330c6a23dSKhazhismel Kumykov 	__fuse_dentry_settime(dentry, time);
840a0898cfSMiklos Szeredi }
850a0898cfSMiklos Szeredi 
866f9f1180SMiklos Szeredi /*
876f9f1180SMiklos Szeredi  * FUSE caches dentries and attributes with separate timeout.  The
886f9f1180SMiklos Szeredi  * time in jiffies until the dentry/attributes are valid is stored in
89f75fdf22SMiklos Szeredi  * dentry->d_fsdata and fuse_inode->i_time respectively.
906f9f1180SMiklos Szeredi  */
916f9f1180SMiklos Szeredi 
926f9f1180SMiklos Szeredi /*
936f9f1180SMiklos Szeredi  * Calculate the time in jiffies until a dentry/attributes are valid
946f9f1180SMiklos Szeredi  */
95bcb6f6d2SMiklos Szeredi static u64 time_to_jiffies(u64 sec, u32 nsec)
96e5e5558eSMiklos Szeredi {
97685d16ddSMiklos Szeredi 	if (sec || nsec) {
98bcb6f6d2SMiklos Szeredi 		struct timespec64 ts = {
99bcb6f6d2SMiklos Szeredi 			sec,
10021067527SDavid Sheets 			min_t(u32, nsec, NSEC_PER_SEC - 1)
101bcb6f6d2SMiklos Szeredi 		};
102bcb6f6d2SMiklos Szeredi 
103bcb6f6d2SMiklos Szeredi 		return get_jiffies_64() + timespec64_to_jiffies(&ts);
104685d16ddSMiklos Szeredi 	} else
1050a0898cfSMiklos Szeredi 		return 0;
106e5e5558eSMiklos Szeredi }
107e5e5558eSMiklos Szeredi 
1086f9f1180SMiklos Szeredi /*
1096f9f1180SMiklos Szeredi  * Set dentry and possibly attribute timeouts from the lookup/mk*
1106f9f1180SMiklos Szeredi  * replies
1116f9f1180SMiklos Szeredi  */
112d123d8e1SMiklos Szeredi void fuse_change_entry_timeout(struct dentry *entry, struct fuse_entry_out *o)
1130aa7c699SMiklos Szeredi {
1140a0898cfSMiklos Szeredi 	fuse_dentry_settime(entry,
1150a0898cfSMiklos Szeredi 		time_to_jiffies(o->entry_valid, o->entry_valid_nsec));
1161fb69e78SMiklos Szeredi }
1171fb69e78SMiklos Szeredi 
1181fb69e78SMiklos Szeredi static u64 attr_timeout(struct fuse_attr_out *o)
1191fb69e78SMiklos Szeredi {
1201fb69e78SMiklos Szeredi 	return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
1211fb69e78SMiklos Szeredi }
1221fb69e78SMiklos Szeredi 
123d123d8e1SMiklos Szeredi u64 entry_attr_timeout(struct fuse_entry_out *o)
1241fb69e78SMiklos Szeredi {
1251fb69e78SMiklos Szeredi 	return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
1268cbdf1e6SMiklos Szeredi }
1278cbdf1e6SMiklos Szeredi 
128fa5eee57SMiklos Szeredi void fuse_invalidate_attr_mask(struct inode *inode, u32 mask)
1292f1e8196SMiklos Szeredi {
1302f1e8196SMiklos Szeredi 	set_mask_bits(&get_fuse_inode(inode)->inval_mask, 0, mask);
1312f1e8196SMiklos Szeredi }
1322f1e8196SMiklos Szeredi 
1336f9f1180SMiklos Szeredi /*
1346f9f1180SMiklos Szeredi  * Mark the attributes as stale, so that at the next call to
1356f9f1180SMiklos Szeredi  * ->getattr() they will be fetched from userspace
1366f9f1180SMiklos Szeredi  */
1378cbdf1e6SMiklos Szeredi void fuse_invalidate_attr(struct inode *inode)
1388cbdf1e6SMiklos Szeredi {
1392f1e8196SMiklos Szeredi 	fuse_invalidate_attr_mask(inode, STATX_BASIC_STATS);
1408cbdf1e6SMiklos Szeredi }
1418cbdf1e6SMiklos Szeredi 
142261aaba7SMiklos Szeredi static void fuse_dir_changed(struct inode *dir)
143261aaba7SMiklos Szeredi {
144261aaba7SMiklos Szeredi 	fuse_invalidate_attr(dir);
145261aaba7SMiklos Szeredi 	inode_maybe_inc_iversion(dir, false);
146261aaba7SMiklos Szeredi }
147261aaba7SMiklos Szeredi 
14806bbb761SRandy Dunlap /*
149451418fcSAndrew Gallagher  * Mark the attributes as stale due to an atime change.  Avoid the invalidate if
150451418fcSAndrew Gallagher  * atime is not used.
151451418fcSAndrew Gallagher  */
152451418fcSAndrew Gallagher void fuse_invalidate_atime(struct inode *inode)
153451418fcSAndrew Gallagher {
154451418fcSAndrew Gallagher 	if (!IS_RDONLY(inode))
1552f1e8196SMiklos Szeredi 		fuse_invalidate_attr_mask(inode, STATX_ATIME);
156451418fcSAndrew Gallagher }
157451418fcSAndrew Gallagher 
1586f9f1180SMiklos Szeredi /*
1596f9f1180SMiklos Szeredi  * Just mark the entry as stale, so that a next attempt to look it up
1606f9f1180SMiklos Szeredi  * will result in a new lookup call to userspace
1616f9f1180SMiklos Szeredi  *
1626f9f1180SMiklos Szeredi  * This is called when a dentry is about to become negative and the
1636f9f1180SMiklos Szeredi  * timeout is unknown (unlink, rmdir, rename and in some cases
1646f9f1180SMiklos Szeredi  * lookup)
1656f9f1180SMiklos Szeredi  */
166dbd561d2SMiklos Szeredi void fuse_invalidate_entry_cache(struct dentry *entry)
1678cbdf1e6SMiklos Szeredi {
1680a0898cfSMiklos Szeredi 	fuse_dentry_settime(entry, 0);
1698cbdf1e6SMiklos Szeredi }
1708cbdf1e6SMiklos Szeredi 
1716f9f1180SMiklos Szeredi /*
1726f9f1180SMiklos Szeredi  * Same as fuse_invalidate_entry_cache(), but also try to remove the
1736f9f1180SMiklos Szeredi  * dentry from the hash
1746f9f1180SMiklos Szeredi  */
1758cbdf1e6SMiklos Szeredi static void fuse_invalidate_entry(struct dentry *entry)
1768cbdf1e6SMiklos Szeredi {
1778cbdf1e6SMiklos Szeredi 	d_invalidate(entry);
1788cbdf1e6SMiklos Szeredi 	fuse_invalidate_entry_cache(entry);
1790aa7c699SMiklos Szeredi }
1800aa7c699SMiklos Szeredi 
1817078187aSMiklos Szeredi static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_args *args,
18213983d06SAl Viro 			     u64 nodeid, const struct qstr *name,
183e5e5558eSMiklos Szeredi 			     struct fuse_entry_out *outarg)
184e5e5558eSMiklos Szeredi {
1850e9663eeSMiklos Szeredi 	memset(outarg, 0, sizeof(struct fuse_entry_out));
186d5b48543SMiklos Szeredi 	args->opcode = FUSE_LOOKUP;
187d5b48543SMiklos Szeredi 	args->nodeid = nodeid;
188d5b48543SMiklos Szeredi 	args->in_numargs = 1;
189d5b48543SMiklos Szeredi 	args->in_args[0].size = name->len + 1;
190d5b48543SMiklos Szeredi 	args->in_args[0].value = name->name;
191d5b48543SMiklos Szeredi 	args->out_numargs = 1;
192d5b48543SMiklos Szeredi 	args->out_args[0].size = sizeof(struct fuse_entry_out);
193d5b48543SMiklos Szeredi 	args->out_args[0].value = outarg;
194e5e5558eSMiklos Szeredi }
195e5e5558eSMiklos Szeredi 
1966f9f1180SMiklos Szeredi /*
1976f9f1180SMiklos Szeredi  * Check whether the dentry is still valid
1986f9f1180SMiklos Szeredi  *
1996f9f1180SMiklos Szeredi  * If the entry validity timeout has expired and the dentry is
2006f9f1180SMiklos Szeredi  * positive, try to redo the lookup.  If the lookup results in a
2016f9f1180SMiklos Szeredi  * different inode, then let the VFS invalidate the dentry and redo
2026f9f1180SMiklos Szeredi  * the lookup once more.  If the lookup results in the same inode,
2036f9f1180SMiklos Szeredi  * then refresh the attributes, timeouts and mark the dentry valid.
2046f9f1180SMiklos Szeredi  */
2050b728e19SAl Viro static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
206e5e5558eSMiklos Szeredi {
20734286d66SNick Piggin 	struct inode *inode;
20828420dadSMiklos Szeredi 	struct dentry *parent;
209fcee216bSMax Reitz 	struct fuse_mount *fm;
2106314efeeSMiklos Szeredi 	struct fuse_inode *fi;
211e2a6b952SMiklos Szeredi 	int ret;
2128cbdf1e6SMiklos Szeredi 
2132b0143b5SDavid Howells 	inode = d_inode_rcu(entry);
2145d069dbeSMiklos Szeredi 	if (inode && fuse_is_bad(inode))
215e2a6b952SMiklos Szeredi 		goto invalid;
216154210ccSAnand Avati 	else if (time_before64(fuse_dentry_time(entry), get_jiffies_64()) ||
217ccc031e2SJiachen Zhang 		 (flags & (LOOKUP_EXCL | LOOKUP_REVAL | LOOKUP_RENAME_TARGET))) {
218e5e5558eSMiklos Szeredi 		struct fuse_entry_out outarg;
2197078187aSMiklos Szeredi 		FUSE_ARGS(args);
22007e77dcaSMiklos Szeredi 		struct fuse_forget_link *forget;
2211fb69e78SMiklos Szeredi 		u64 attr_version;
2228cbdf1e6SMiklos Szeredi 
22350322fe7SMiklos Szeredi 		/* For negative dentries, always do a fresh lookup */
2248cbdf1e6SMiklos Szeredi 		if (!inode)
225e2a6b952SMiklos Szeredi 			goto invalid;
2268cbdf1e6SMiklos Szeredi 
227e2a6b952SMiklos Szeredi 		ret = -ECHILD;
2280b728e19SAl Viro 		if (flags & LOOKUP_RCU)
229e2a6b952SMiklos Szeredi 			goto out;
230e7c0a167SMiklos Szeredi 
231fcee216bSMax Reitz 		fm = get_fuse_mount(inode);
232e5e5558eSMiklos Szeredi 
23307e77dcaSMiklos Szeredi 		forget = fuse_alloc_forget();
234e2a6b952SMiklos Szeredi 		ret = -ENOMEM;
2357078187aSMiklos Szeredi 		if (!forget)
236e2a6b952SMiklos Szeredi 			goto out;
2372d51013eSMiklos Szeredi 
238fcee216bSMax Reitz 		attr_version = fuse_get_attr_version(fm->fc);
2391fb69e78SMiklos Szeredi 
240e956edd0SMiklos Szeredi 		parent = dget_parent(entry);
241fcee216bSMax Reitz 		fuse_lookup_init(fm->fc, &args, get_node_id(d_inode(parent)),
242c180eebeSMiklos Szeredi 				 &entry->d_name, &outarg);
243fcee216bSMax Reitz 		ret = fuse_simple_request(fm, &args);
244e956edd0SMiklos Szeredi 		dput(parent);
24550322fe7SMiklos Szeredi 		/* Zero nodeid is same as -ENOENT */
2467078187aSMiklos Szeredi 		if (!ret && !outarg.nodeid)
2477078187aSMiklos Szeredi 			ret = -ENOENT;
2487078187aSMiklos Szeredi 		if (!ret) {
2496314efeeSMiklos Szeredi 			fi = get_fuse_inode(inode);
250bf109c64SMax Reitz 			if (outarg.nodeid != get_node_id(inode) ||
251bf109c64SMax Reitz 			    (bool) IS_AUTOMOUNT(inode) != (bool) (outarg.attr.flags & FUSE_ATTR_SUBMOUNT)) {
252fcee216bSMax Reitz 				fuse_queue_forget(fm->fc, forget,
253fcee216bSMax Reitz 						  outarg.nodeid, 1);
254e2a6b952SMiklos Szeredi 				goto invalid;
2559e6268dbSMiklos Szeredi 			}
256c9d8f5f0SKirill Tkhai 			spin_lock(&fi->lock);
2579e6268dbSMiklos Szeredi 			fi->nlookup++;
258c9d8f5f0SKirill Tkhai 			spin_unlock(&fi->lock);
2599e6268dbSMiklos Szeredi 		}
26007e77dcaSMiklos Szeredi 		kfree(forget);
261a9d1c4c6SMiklos Szeredi 		if (ret == -ENOMEM || ret == -EINTR)
2627078187aSMiklos Szeredi 			goto out;
263eb59bd17SMiklos Szeredi 		if (ret || fuse_invalid_attr(&outarg.attr) ||
26415db1683SAmir Goldstein 		    fuse_stale_inode(inode, outarg.generation, &outarg.attr))
265e2a6b952SMiklos Szeredi 			goto invalid;
266e5e5558eSMiklos Szeredi 
26760bcc88aSSeth Forshee 		forget_all_cached_acls(inode);
2681fb69e78SMiklos Szeredi 		fuse_change_attributes(inode, &outarg.attr,
2691fb69e78SMiklos Szeredi 				       entry_attr_timeout(&outarg),
2701fb69e78SMiklos Szeredi 				       attr_version);
2711fb69e78SMiklos Szeredi 		fuse_change_entry_timeout(entry, &outarg);
27228420dadSMiklos Szeredi 	} else if (inode) {
2736314efeeSMiklos Szeredi 		fi = get_fuse_inode(inode);
2746314efeeSMiklos Szeredi 		if (flags & LOOKUP_RCU) {
2756314efeeSMiklos Szeredi 			if (test_bit(FUSE_I_INIT_RDPLUS, &fi->state))
2766314efeeSMiklos Szeredi 				return -ECHILD;
2776314efeeSMiklos Szeredi 		} else if (test_and_clear_bit(FUSE_I_INIT_RDPLUS, &fi->state)) {
27828420dadSMiklos Szeredi 			parent = dget_parent(entry);
2792b0143b5SDavid Howells 			fuse_advise_use_readdirplus(d_inode(parent));
28028420dadSMiklos Szeredi 			dput(parent);
281e5e5558eSMiklos Szeredi 		}
28228420dadSMiklos Szeredi 	}
283e2a6b952SMiklos Szeredi 	ret = 1;
284e2a6b952SMiklos Szeredi out:
285e2a6b952SMiklos Szeredi 	return ret;
286e2a6b952SMiklos Szeredi 
287e2a6b952SMiklos Szeredi invalid:
288e2a6b952SMiklos Szeredi 	ret = 0;
289e2a6b952SMiklos Szeredi 	goto out;
290e5e5558eSMiklos Szeredi }
291e5e5558eSMiklos Szeredi 
29230c6a23dSKhazhismel Kumykov #if BITS_PER_LONG < 64
293f75fdf22SMiklos Szeredi static int fuse_dentry_init(struct dentry *dentry)
294f75fdf22SMiklos Szeredi {
295dc69e98cSKhazhismel Kumykov 	dentry->d_fsdata = kzalloc(sizeof(union fuse_dentry),
296dc69e98cSKhazhismel Kumykov 				   GFP_KERNEL_ACCOUNT | __GFP_RECLAIMABLE);
297f75fdf22SMiklos Szeredi 
298f75fdf22SMiklos Szeredi 	return dentry->d_fsdata ? 0 : -ENOMEM;
299f75fdf22SMiklos Szeredi }
300f75fdf22SMiklos Szeredi static void fuse_dentry_release(struct dentry *dentry)
301f75fdf22SMiklos Szeredi {
302f75fdf22SMiklos Szeredi 	union fuse_dentry *fd = dentry->d_fsdata;
303f75fdf22SMiklos Szeredi 
304f75fdf22SMiklos Szeredi 	kfree_rcu(fd, rcu);
305f75fdf22SMiklos Szeredi }
30630c6a23dSKhazhismel Kumykov #endif
307f75fdf22SMiklos Szeredi 
3088fab0106SMiklos Szeredi static int fuse_dentry_delete(const struct dentry *dentry)
3098fab0106SMiklos Szeredi {
3108fab0106SMiklos Szeredi 	return time_before64(fuse_dentry_time(dentry), get_jiffies_64());
3118fab0106SMiklos Szeredi }
3128fab0106SMiklos Szeredi 
313bf109c64SMax Reitz /*
314bf109c64SMax Reitz  * Create a fuse_mount object with a new superblock (with path->dentry
315bf109c64SMax Reitz  * as the root), and return that mount so it can be auto-mounted on
316bf109c64SMax Reitz  * @path.
317bf109c64SMax Reitz  */
318bf109c64SMax Reitz static struct vfsmount *fuse_dentry_automount(struct path *path)
319bf109c64SMax Reitz {
320bf109c64SMax Reitz 	struct fs_context *fsc;
321bf109c64SMax Reitz 	struct vfsmount *mnt;
322bf109c64SMax Reitz 	struct fuse_inode *mp_fi = get_fuse_inode(d_inode(path->dentry));
323bf109c64SMax Reitz 
324bf109c64SMax Reitz 	fsc = fs_context_for_submount(path->mnt->mnt_sb->s_type, path->dentry);
32529e0e4dfSGreg Kurz 	if (IS_ERR(fsc))
32629e0e4dfSGreg Kurz 		return ERR_CAST(fsc);
327bf109c64SMax Reitz 
328266eb3f2SGreg Kurz 	/* Pass the FUSE inode of the mount for fuse_get_tree_submount() */
329266eb3f2SGreg Kurz 	fsc->fs_private = mp_fi;
330266eb3f2SGreg Kurz 
331bf109c64SMax Reitz 	/* Create the submount */
33229e0e4dfSGreg Kurz 	mnt = fc_mount(fsc);
33329e0e4dfSGreg Kurz 	if (!IS_ERR(mnt))
334bf109c64SMax Reitz 		mntget(mnt);
33529e0e4dfSGreg Kurz 
336bf109c64SMax Reitz 	put_fs_context(fsc);
337bf109c64SMax Reitz 	return mnt;
338bf109c64SMax Reitz }
339bf109c64SMax Reitz 
3404269590aSAl Viro const struct dentry_operations fuse_dentry_operations = {
341e5e5558eSMiklos Szeredi 	.d_revalidate	= fuse_dentry_revalidate,
3428fab0106SMiklos Szeredi 	.d_delete	= fuse_dentry_delete,
34330c6a23dSKhazhismel Kumykov #if BITS_PER_LONG < 64
344f75fdf22SMiklos Szeredi 	.d_init		= fuse_dentry_init,
345f75fdf22SMiklos Szeredi 	.d_release	= fuse_dentry_release,
34630c6a23dSKhazhismel Kumykov #endif
347bf109c64SMax Reitz 	.d_automount	= fuse_dentry_automount,
348e5e5558eSMiklos Szeredi };
349e5e5558eSMiklos Szeredi 
3500ce267ffSMiklos Szeredi const struct dentry_operations fuse_root_dentry_operations = {
35130c6a23dSKhazhismel Kumykov #if BITS_PER_LONG < 64
3520ce267ffSMiklos Szeredi 	.d_init		= fuse_dentry_init,
3530ce267ffSMiklos Szeredi 	.d_release	= fuse_dentry_release,
35430c6a23dSKhazhismel Kumykov #endif
3550ce267ffSMiklos Szeredi };
3560ce267ffSMiklos Szeredi 
357a5bfffacSTimo Savola int fuse_valid_type(int m)
35839ee059aSMiklos Szeredi {
35939ee059aSMiklos Szeredi 	return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) ||
36039ee059aSMiklos Szeredi 		S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m);
36139ee059aSMiklos Szeredi }
36239ee059aSMiklos Szeredi 
363eb59bd17SMiklos Szeredi bool fuse_invalid_attr(struct fuse_attr *attr)
364eb59bd17SMiklos Szeredi {
365eb59bd17SMiklos Szeredi 	return !fuse_valid_type(attr->mode) ||
366eb59bd17SMiklos Szeredi 		attr->size > LLONG_MAX;
367eb59bd17SMiklos Szeredi }
368eb59bd17SMiklos Szeredi 
36913983d06SAl Viro int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name,
370c180eebeSMiklos Szeredi 		     struct fuse_entry_out *outarg, struct inode **inode)
371c180eebeSMiklos Szeredi {
372fcee216bSMax Reitz 	struct fuse_mount *fm = get_fuse_mount_super(sb);
3737078187aSMiklos Szeredi 	FUSE_ARGS(args);
37407e77dcaSMiklos Szeredi 	struct fuse_forget_link *forget;
375c180eebeSMiklos Szeredi 	u64 attr_version;
376c180eebeSMiklos Szeredi 	int err;
377c180eebeSMiklos Szeredi 
378c180eebeSMiklos Szeredi 	*inode = NULL;
379c180eebeSMiklos Szeredi 	err = -ENAMETOOLONG;
380c180eebeSMiklos Szeredi 	if (name->len > FUSE_NAME_MAX)
381c180eebeSMiklos Szeredi 		goto out;
382c180eebeSMiklos Szeredi 
383c180eebeSMiklos Szeredi 
38407e77dcaSMiklos Szeredi 	forget = fuse_alloc_forget();
38507e77dcaSMiklos Szeredi 	err = -ENOMEM;
3867078187aSMiklos Szeredi 	if (!forget)
387c180eebeSMiklos Szeredi 		goto out;
388c180eebeSMiklos Szeredi 
389fcee216bSMax Reitz 	attr_version = fuse_get_attr_version(fm->fc);
390c180eebeSMiklos Szeredi 
391fcee216bSMax Reitz 	fuse_lookup_init(fm->fc, &args, nodeid, name, outarg);
392fcee216bSMax Reitz 	err = fuse_simple_request(fm, &args);
393c180eebeSMiklos Szeredi 	/* Zero nodeid is same as -ENOENT, but with valid timeout */
394c180eebeSMiklos Szeredi 	if (err || !outarg->nodeid)
395c180eebeSMiklos Szeredi 		goto out_put_forget;
396c180eebeSMiklos Szeredi 
397c180eebeSMiklos Szeredi 	err = -EIO;
398eb59bd17SMiklos Szeredi 	if (fuse_invalid_attr(&outarg->attr))
399c180eebeSMiklos Szeredi 		goto out_put_forget;
400c180eebeSMiklos Szeredi 
401c180eebeSMiklos Szeredi 	*inode = fuse_iget(sb, outarg->nodeid, outarg->generation,
402c180eebeSMiklos Szeredi 			   &outarg->attr, entry_attr_timeout(outarg),
403c180eebeSMiklos Szeredi 			   attr_version);
404c180eebeSMiklos Szeredi 	err = -ENOMEM;
405c180eebeSMiklos Szeredi 	if (!*inode) {
406fcee216bSMax Reitz 		fuse_queue_forget(fm->fc, forget, outarg->nodeid, 1);
407c180eebeSMiklos Szeredi 		goto out;
408c180eebeSMiklos Szeredi 	}
409c180eebeSMiklos Szeredi 	err = 0;
410c180eebeSMiklos Szeredi 
411c180eebeSMiklos Szeredi  out_put_forget:
41207e77dcaSMiklos Szeredi 	kfree(forget);
413c180eebeSMiklos Szeredi  out:
414c180eebeSMiklos Szeredi 	return err;
415c180eebeSMiklos Szeredi }
416c180eebeSMiklos Szeredi 
4170aa7c699SMiklos Szeredi static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
41800cd8dd3SAl Viro 				  unsigned int flags)
419e5e5558eSMiklos Szeredi {
420e5e5558eSMiklos Szeredi 	int err;
421e5e5558eSMiklos Szeredi 	struct fuse_entry_out outarg;
422c180eebeSMiklos Szeredi 	struct inode *inode;
4230de6256dSMiklos Szeredi 	struct dentry *newent;
424c180eebeSMiklos Szeredi 	bool outarg_valid = true;
42563576c13SMiklos Szeredi 	bool locked;
426e5e5558eSMiklos Szeredi 
4275d069dbeSMiklos Szeredi 	if (fuse_is_bad(dir))
4285d069dbeSMiklos Szeredi 		return ERR_PTR(-EIO);
4295d069dbeSMiklos Szeredi 
43063576c13SMiklos Szeredi 	locked = fuse_lock_inode(dir);
431c180eebeSMiklos Szeredi 	err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name,
432c180eebeSMiklos Szeredi 			       &outarg, &inode);
43363576c13SMiklos Szeredi 	fuse_unlock_inode(dir, locked);
434c180eebeSMiklos Szeredi 	if (err == -ENOENT) {
435c180eebeSMiklos Szeredi 		outarg_valid = false;
436c180eebeSMiklos Szeredi 		err = 0;
4372d51013eSMiklos Szeredi 	}
438c180eebeSMiklos Szeredi 	if (err)
439c180eebeSMiklos Szeredi 		goto out_err;
4402d51013eSMiklos Szeredi 
441ee4e5271SMiklos Szeredi 	err = -EIO;
442c180eebeSMiklos Szeredi 	if (inode && get_node_id(inode) == FUSE_ROOT_ID)
443c180eebeSMiklos Szeredi 		goto out_iput;
444e5e5558eSMiklos Szeredi 
44541d28bcaSAl Viro 	newent = d_splice_alias(inode, entry);
446c180eebeSMiklos Szeredi 	err = PTR_ERR(newent);
447c180eebeSMiklos Szeredi 	if (IS_ERR(newent))
4485835f339SMiklos Szeredi 		goto out_err;
449d2a85164SMiklos Szeredi 
4500de6256dSMiklos Szeredi 	entry = newent ? newent : entry;
451c180eebeSMiklos Szeredi 	if (outarg_valid)
4521fb69e78SMiklos Szeredi 		fuse_change_entry_timeout(entry, &outarg);
4538cbdf1e6SMiklos Szeredi 	else
4548cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
455c180eebeSMiklos Szeredi 
4566c26f717SMiklos Szeredi 	if (inode)
4574582a4abSFeng Shuo 		fuse_advise_use_readdirplus(dir);
4580de6256dSMiklos Szeredi 	return newent;
459c180eebeSMiklos Szeredi 
460c180eebeSMiklos Szeredi  out_iput:
461c180eebeSMiklos Szeredi 	iput(inode);
462c180eebeSMiklos Szeredi  out_err:
463c180eebeSMiklos Szeredi 	return ERR_PTR(err);
464e5e5558eSMiklos Szeredi }
465e5e5558eSMiklos Szeredi 
4663e2b6fdbSVivek Goyal static int get_security_context(struct dentry *entry, umode_t mode,
46715d937d7SMiklos Szeredi 				struct fuse_in_arg *ext)
4683e2b6fdbSVivek Goyal {
4693e2b6fdbSVivek Goyal 	struct fuse_secctx *fctx;
4703e2b6fdbSVivek Goyal 	struct fuse_secctx_header *header;
4713e2b6fdbSVivek Goyal 	void *ctx = NULL, *ptr;
4723e2b6fdbSVivek Goyal 	u32 ctxlen, total_len = sizeof(*header);
4733e2b6fdbSVivek Goyal 	int err, nr_ctx = 0;
4743e2b6fdbSVivek Goyal 	const char *name;
4753e2b6fdbSVivek Goyal 	size_t namelen;
4763e2b6fdbSVivek Goyal 
4773e2b6fdbSVivek Goyal 	err = security_dentry_init_security(entry, mode, &entry->d_name,
4783e2b6fdbSVivek Goyal 					    &name, &ctx, &ctxlen);
4793e2b6fdbSVivek Goyal 	if (err) {
4803e2b6fdbSVivek Goyal 		if (err != -EOPNOTSUPP)
4813e2b6fdbSVivek Goyal 			goto out_err;
4823e2b6fdbSVivek Goyal 		/* No LSM is supporting this security hook. Ignore error */
4833e2b6fdbSVivek Goyal 		ctxlen = 0;
4843e2b6fdbSVivek Goyal 		ctx = NULL;
4853e2b6fdbSVivek Goyal 	}
4863e2b6fdbSVivek Goyal 
4873e2b6fdbSVivek Goyal 	if (ctxlen) {
4883e2b6fdbSVivek Goyal 		nr_ctx = 1;
4893e2b6fdbSVivek Goyal 		namelen = strlen(name) + 1;
4903e2b6fdbSVivek Goyal 		err = -EIO;
4913e2b6fdbSVivek Goyal 		if (WARN_ON(namelen > XATTR_NAME_MAX + 1 || ctxlen > S32_MAX))
4923e2b6fdbSVivek Goyal 			goto out_err;
4933e2b6fdbSVivek Goyal 		total_len += FUSE_REC_ALIGN(sizeof(*fctx) + namelen + ctxlen);
4943e2b6fdbSVivek Goyal 	}
4953e2b6fdbSVivek Goyal 
4963e2b6fdbSVivek Goyal 	err = -ENOMEM;
4973e2b6fdbSVivek Goyal 	header = ptr = kzalloc(total_len, GFP_KERNEL);
4983e2b6fdbSVivek Goyal 	if (!ptr)
4993e2b6fdbSVivek Goyal 		goto out_err;
5003e2b6fdbSVivek Goyal 
5013e2b6fdbSVivek Goyal 	header->nr_secctx = nr_ctx;
5023e2b6fdbSVivek Goyal 	header->size = total_len;
5033e2b6fdbSVivek Goyal 	ptr += sizeof(*header);
5043e2b6fdbSVivek Goyal 	if (nr_ctx) {
5053e2b6fdbSVivek Goyal 		fctx = ptr;
5063e2b6fdbSVivek Goyal 		fctx->size = ctxlen;
5073e2b6fdbSVivek Goyal 		ptr += sizeof(*fctx);
5083e2b6fdbSVivek Goyal 
5093e2b6fdbSVivek Goyal 		strcpy(ptr, name);
5103e2b6fdbSVivek Goyal 		ptr += namelen;
5113e2b6fdbSVivek Goyal 
5123e2b6fdbSVivek Goyal 		memcpy(ptr, ctx, ctxlen);
5133e2b6fdbSVivek Goyal 	}
51415d937d7SMiklos Szeredi 	ext->size = total_len;
51515d937d7SMiklos Szeredi 	ext->value = header;
5163e2b6fdbSVivek Goyal 	err = 0;
5173e2b6fdbSVivek Goyal out_err:
5183e2b6fdbSVivek Goyal 	kfree(ctx);
5193e2b6fdbSVivek Goyal 	return err;
5203e2b6fdbSVivek Goyal }
5213e2b6fdbSVivek Goyal 
5228ed7cb3fSMiklos Szeredi static void *extend_arg(struct fuse_in_arg *buf, u32 bytes)
5238ed7cb3fSMiklos Szeredi {
5248ed7cb3fSMiklos Szeredi 	void *p;
5258ed7cb3fSMiklos Szeredi 	u32 newlen = buf->size + bytes;
5268ed7cb3fSMiklos Szeredi 
5278ed7cb3fSMiklos Szeredi 	p = krealloc(buf->value, newlen, GFP_KERNEL);
5288ed7cb3fSMiklos Szeredi 	if (!p) {
5298ed7cb3fSMiklos Szeredi 		kfree(buf->value);
5308ed7cb3fSMiklos Szeredi 		buf->size = 0;
5318ed7cb3fSMiklos Szeredi 		buf->value = NULL;
5328ed7cb3fSMiklos Szeredi 		return NULL;
5338ed7cb3fSMiklos Szeredi 	}
5348ed7cb3fSMiklos Szeredi 
5358ed7cb3fSMiklos Szeredi 	memset(p + buf->size, 0, bytes);
5368ed7cb3fSMiklos Szeredi 	buf->value = p;
5378ed7cb3fSMiklos Szeredi 	buf->size = newlen;
5388ed7cb3fSMiklos Szeredi 
5398ed7cb3fSMiklos Szeredi 	return p + newlen - bytes;
5408ed7cb3fSMiklos Szeredi }
5418ed7cb3fSMiklos Szeredi 
5428ed7cb3fSMiklos Szeredi static u32 fuse_ext_size(size_t size)
5438ed7cb3fSMiklos Szeredi {
5448ed7cb3fSMiklos Szeredi 	return FUSE_REC_ALIGN(sizeof(struct fuse_ext_header) + size);
5458ed7cb3fSMiklos Szeredi }
5468ed7cb3fSMiklos Szeredi 
5478ed7cb3fSMiklos Szeredi /*
5488ed7cb3fSMiklos Szeredi  * This adds just a single supplementary group that matches the parent's group.
5498ed7cb3fSMiklos Szeredi  */
5508ed7cb3fSMiklos Szeredi static int get_create_supp_group(struct inode *dir, struct fuse_in_arg *ext)
5518ed7cb3fSMiklos Szeredi {
5528ed7cb3fSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
5538ed7cb3fSMiklos Szeredi 	struct fuse_ext_header *xh;
5548ed7cb3fSMiklos Szeredi 	struct fuse_supp_groups *sg;
5558ed7cb3fSMiklos Szeredi 	kgid_t kgid = dir->i_gid;
5568ed7cb3fSMiklos Szeredi 	gid_t parent_gid = from_kgid(fc->user_ns, kgid);
5578ed7cb3fSMiklos Szeredi 	u32 sg_len = fuse_ext_size(sizeof(*sg) + sizeof(sg->groups[0]));
5588ed7cb3fSMiklos Szeredi 
5598ed7cb3fSMiklos Szeredi 	if (parent_gid == (gid_t) -1 || gid_eq(kgid, current_fsgid()) ||
5608ed7cb3fSMiklos Szeredi 	    !in_group_p(kgid))
5618ed7cb3fSMiklos Szeredi 		return 0;
5628ed7cb3fSMiklos Szeredi 
5638ed7cb3fSMiklos Szeredi 	xh = extend_arg(ext, sg_len);
5648ed7cb3fSMiklos Szeredi 	if (!xh)
5658ed7cb3fSMiklos Szeredi 		return -ENOMEM;
5668ed7cb3fSMiklos Szeredi 
5678ed7cb3fSMiklos Szeredi 	xh->size = sg_len;
5688ed7cb3fSMiklos Szeredi 	xh->type = FUSE_EXT_GROUPS;
5698ed7cb3fSMiklos Szeredi 
5708ed7cb3fSMiklos Szeredi 	sg = (struct fuse_supp_groups *) &xh[1];
5718ed7cb3fSMiklos Szeredi 	sg->nr_groups = 1;
5728ed7cb3fSMiklos Szeredi 	sg->groups[0] = parent_gid;
5738ed7cb3fSMiklos Szeredi 
5748ed7cb3fSMiklos Szeredi 	return 0;
5758ed7cb3fSMiklos Szeredi }
5768ed7cb3fSMiklos Szeredi 
5778ed7cb3fSMiklos Szeredi static int get_create_ext(struct fuse_args *args,
5788ed7cb3fSMiklos Szeredi 			  struct inode *dir, struct dentry *dentry,
57915d937d7SMiklos Szeredi 			  umode_t mode)
58015d937d7SMiklos Szeredi {
58115d937d7SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn_super(dentry->d_sb);
58215d937d7SMiklos Szeredi 	struct fuse_in_arg ext = { .size = 0, .value = NULL };
58315d937d7SMiklos Szeredi 	int err = 0;
58415d937d7SMiklos Szeredi 
58515d937d7SMiklos Szeredi 	if (fc->init_security)
58615d937d7SMiklos Szeredi 		err = get_security_context(dentry, mode, &ext);
5878ed7cb3fSMiklos Szeredi 	if (!err && fc->create_supp_group)
5888ed7cb3fSMiklos Szeredi 		err = get_create_supp_group(dir, &ext);
58915d937d7SMiklos Szeredi 
59015d937d7SMiklos Szeredi 	if (!err && ext.size) {
59115d937d7SMiklos Szeredi 		WARN_ON(args->in_numargs >= ARRAY_SIZE(args->in_args));
59215d937d7SMiklos Szeredi 		args->is_ext = true;
59315d937d7SMiklos Szeredi 		args->ext_idx = args->in_numargs++;
59415d937d7SMiklos Szeredi 		args->in_args[args->ext_idx] = ext;
59515d937d7SMiklos Szeredi 	} else {
59615d937d7SMiklos Szeredi 		kfree(ext.value);
59715d937d7SMiklos Szeredi 	}
59815d937d7SMiklos Szeredi 
59915d937d7SMiklos Szeredi 	return err;
60015d937d7SMiklos Szeredi }
60115d937d7SMiklos Szeredi 
60215d937d7SMiklos Szeredi static void free_ext_value(struct fuse_args *args)
60315d937d7SMiklos Szeredi {
60415d937d7SMiklos Szeredi 	if (args->is_ext)
60515d937d7SMiklos Szeredi 		kfree(args->in_args[args->ext_idx].value);
60615d937d7SMiklos Szeredi }
60715d937d7SMiklos Szeredi 
6086f9f1180SMiklos Szeredi /*
6096f9f1180SMiklos Szeredi  * Atomic create+open operation
6106f9f1180SMiklos Szeredi  *
6116f9f1180SMiklos Szeredi  * If the filesystem doesn't support this, then fall back to separate
6126f9f1180SMiklos Szeredi  * 'mknod' + 'open' requests.
6136f9f1180SMiklos Szeredi  */
614d9585277SAl Viro static int fuse_create_open(struct inode *dir, struct dentry *entry,
61554d601cbSMiklos Szeredi 			    struct file *file, unsigned int flags,
6167d375390SMiklos Szeredi 			    umode_t mode, u32 opcode)
617fd72faacSMiklos Szeredi {
618fd72faacSMiklos Szeredi 	int err;
619fd72faacSMiklos Szeredi 	struct inode *inode;
620fcee216bSMax Reitz 	struct fuse_mount *fm = get_fuse_mount(dir);
6217078187aSMiklos Szeredi 	FUSE_ARGS(args);
62207e77dcaSMiklos Szeredi 	struct fuse_forget_link *forget;
623e0a43ddcSMiklos Szeredi 	struct fuse_create_in inarg;
624fd72faacSMiklos Szeredi 	struct fuse_open_out outopen;
625fd72faacSMiklos Szeredi 	struct fuse_entry_out outentry;
626ebf84d0cSKirill Tkhai 	struct fuse_inode *fi;
627fd72faacSMiklos Szeredi 	struct fuse_file *ff;
6282fdbb8ddSMiklos Szeredi 	bool trunc = flags & O_TRUNC;
629fd72faacSMiklos Szeredi 
630af109bcaSMiklos Szeredi 	/* Userspace expects S_IFREG in create mode */
631af109bcaSMiklos Szeredi 	BUG_ON((mode & S_IFMT) != S_IFREG);
632af109bcaSMiklos Szeredi 
63307e77dcaSMiklos Szeredi 	forget = fuse_alloc_forget();
634c8ccbe03SMiklos Szeredi 	err = -ENOMEM;
63507e77dcaSMiklos Szeredi 	if (!forget)
636c8ccbe03SMiklos Szeredi 		goto out_err;
63751eb01e7SMiklos Szeredi 
638ce1d5a49SMiklos Szeredi 	err = -ENOMEM;
639fcee216bSMax Reitz 	ff = fuse_file_alloc(fm);
640fd72faacSMiklos Szeredi 	if (!ff)
6417078187aSMiklos Szeredi 		goto out_put_forget_req;
642fd72faacSMiklos Szeredi 
643fcee216bSMax Reitz 	if (!fm->fc->dont_mask)
644e0a43ddcSMiklos Szeredi 		mode &= ~current_umask();
645e0a43ddcSMiklos Szeredi 
646fd72faacSMiklos Szeredi 	flags &= ~O_NOCTTY;
647fd72faacSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
6480e9663eeSMiklos Szeredi 	memset(&outentry, 0, sizeof(outentry));
649fd72faacSMiklos Szeredi 	inarg.flags = flags;
650fd72faacSMiklos Szeredi 	inarg.mode = mode;
651e0a43ddcSMiklos Szeredi 	inarg.umask = current_umask();
652643a666aSVivek Goyal 
6532fdbb8ddSMiklos Szeredi 	if (fm->fc->handle_killpriv_v2 && trunc &&
654643a666aSVivek Goyal 	    !(flags & O_EXCL) && !capable(CAP_FSETID)) {
655643a666aSVivek Goyal 		inarg.open_flags |= FUSE_OPEN_KILL_SUIDGID;
656643a666aSVivek Goyal 	}
657643a666aSVivek Goyal 
6587d375390SMiklos Szeredi 	args.opcode = opcode;
659d5b48543SMiklos Szeredi 	args.nodeid = get_node_id(dir);
660d5b48543SMiklos Szeredi 	args.in_numargs = 2;
661d5b48543SMiklos Szeredi 	args.in_args[0].size = sizeof(inarg);
662d5b48543SMiklos Szeredi 	args.in_args[0].value = &inarg;
663d5b48543SMiklos Szeredi 	args.in_args[1].size = entry->d_name.len + 1;
664d5b48543SMiklos Szeredi 	args.in_args[1].value = entry->d_name.name;
665d5b48543SMiklos Szeredi 	args.out_numargs = 2;
666d5b48543SMiklos Szeredi 	args.out_args[0].size = sizeof(outentry);
667d5b48543SMiklos Szeredi 	args.out_args[0].value = &outentry;
668d5b48543SMiklos Szeredi 	args.out_args[1].size = sizeof(outopen);
669d5b48543SMiklos Szeredi 	args.out_args[1].value = &outopen;
6703e2b6fdbSVivek Goyal 
6718ed7cb3fSMiklos Szeredi 	err = get_create_ext(&args, dir, entry, mode);
6723e2b6fdbSVivek Goyal 	if (err)
6733e2b6fdbSVivek Goyal 		goto out_put_forget_req;
6743e2b6fdbSVivek Goyal 
675fcee216bSMax Reitz 	err = fuse_simple_request(fm, &args);
67615d937d7SMiklos Szeredi 	free_ext_value(&args);
677c8ccbe03SMiklos Szeredi 	if (err)
678fd72faacSMiklos Szeredi 		goto out_free_ff;
679fd72faacSMiklos Szeredi 
680fd72faacSMiklos Szeredi 	err = -EIO;
681eb59bd17SMiklos Szeredi 	if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid) ||
682eb59bd17SMiklos Szeredi 	    fuse_invalid_attr(&outentry.attr))
683fd72faacSMiklos Szeredi 		goto out_free_ff;
684fd72faacSMiklos Szeredi 
685c7b7143cSMiklos Szeredi 	ff->fh = outopen.fh;
686c7b7143cSMiklos Szeredi 	ff->nodeid = outentry.nodeid;
687c7b7143cSMiklos Szeredi 	ff->open_flags = outopen.open_flags;
688fd72faacSMiklos Szeredi 	inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
6891fb69e78SMiklos Szeredi 			  &outentry.attr, entry_attr_timeout(&outentry), 0);
690fd72faacSMiklos Szeredi 	if (!inode) {
691fd72faacSMiklos Szeredi 		flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
692ebf84d0cSKirill Tkhai 		fuse_sync_release(NULL, ff, flags);
693fcee216bSMax Reitz 		fuse_queue_forget(fm->fc, forget, outentry.nodeid, 1);
694c8ccbe03SMiklos Szeredi 		err = -ENOMEM;
695c8ccbe03SMiklos Szeredi 		goto out_err;
696fd72faacSMiklos Szeredi 	}
69707e77dcaSMiklos Szeredi 	kfree(forget);
698fd72faacSMiklos Szeredi 	d_instantiate(entry, inode);
6991fb69e78SMiklos Szeredi 	fuse_change_entry_timeout(entry, &outentry);
700261aaba7SMiklos Szeredi 	fuse_dir_changed(dir);
701be12af3eSAl Viro 	err = finish_open(file, entry, generic_file_open);
70230d90494SAl Viro 	if (err) {
703ebf84d0cSKirill Tkhai 		fi = get_fuse_inode(inode);
704ebf84d0cSKirill Tkhai 		fuse_sync_release(fi, ff, flags);
705c8ccbe03SMiklos Szeredi 	} else {
706267d8444SMiklos Szeredi 		file->private_data = ff;
707c7b7143cSMiklos Szeredi 		fuse_finish_open(inode, file);
7082fdbb8ddSMiklos Szeredi 		if (fm->fc->atomic_o_trunc && trunc)
7092fdbb8ddSMiklos Szeredi 			truncate_pagecache(inode, 0);
7102fdbb8ddSMiklos Szeredi 		else if (!(ff->open_flags & FOPEN_KEEP_CACHE))
7112fdbb8ddSMiklos Szeredi 			invalidate_inode_pages2(inode->i_mapping);
712c8ccbe03SMiklos Szeredi 	}
713d9585277SAl Viro 	return err;
714fd72faacSMiklos Szeredi 
715fd72faacSMiklos Szeredi out_free_ff:
716fd72faacSMiklos Szeredi 	fuse_file_free(ff);
71751eb01e7SMiklos Szeredi out_put_forget_req:
71807e77dcaSMiklos Szeredi 	kfree(forget);
719c8ccbe03SMiklos Szeredi out_err:
720d9585277SAl Viro 	return err;
721c8ccbe03SMiklos Szeredi }
722c8ccbe03SMiklos Szeredi 
7235ebb29beSChristian Brauner static int fuse_mknod(struct mnt_idmap *, struct inode *, struct dentry *,
724549c7297SChristian Brauner 		      umode_t, dev_t);
725d9585277SAl Viro static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
72630d90494SAl Viro 			    struct file *file, unsigned flags,
72744907d79SAl Viro 			    umode_t mode)
728c8ccbe03SMiklos Szeredi {
729c8ccbe03SMiklos Szeredi 	int err;
730c8ccbe03SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
731c8ccbe03SMiklos Szeredi 	struct dentry *res = NULL;
732c8ccbe03SMiklos Szeredi 
7335d069dbeSMiklos Szeredi 	if (fuse_is_bad(dir))
7345d069dbeSMiklos Szeredi 		return -EIO;
7355d069dbeSMiklos Szeredi 
73600699ad8SAl Viro 	if (d_in_lookup(entry)) {
73700cd8dd3SAl Viro 		res = fuse_lookup(dir, entry, 0);
738c8ccbe03SMiklos Szeredi 		if (IS_ERR(res))
739d9585277SAl Viro 			return PTR_ERR(res);
740c8ccbe03SMiklos Szeredi 
741c8ccbe03SMiklos Szeredi 		if (res)
742c8ccbe03SMiklos Szeredi 			entry = res;
743c8ccbe03SMiklos Szeredi 	}
744c8ccbe03SMiklos Szeredi 
7452b0143b5SDavid Howells 	if (!(flags & O_CREAT) || d_really_is_positive(entry))
746c8ccbe03SMiklos Szeredi 		goto no_open;
747c8ccbe03SMiklos Szeredi 
748c8ccbe03SMiklos Szeredi 	/* Only creates */
74973a09dd9SAl Viro 	file->f_mode |= FMODE_CREATED;
750c8ccbe03SMiklos Szeredi 
751c8ccbe03SMiklos Szeredi 	if (fc->no_create)
752c8ccbe03SMiklos Szeredi 		goto mknod;
753c8ccbe03SMiklos Szeredi 
7547d375390SMiklos Szeredi 	err = fuse_create_open(dir, entry, file, flags, mode, FUSE_CREATE);
755d9585277SAl Viro 	if (err == -ENOSYS) {
756c8ccbe03SMiklos Szeredi 		fc->no_create = 1;
757c8ccbe03SMiklos Szeredi 		goto mknod;
758c8ccbe03SMiklos Szeredi 	}
759c8ccbe03SMiklos Szeredi out_dput:
760c8ccbe03SMiklos Szeredi 	dput(res);
761d9585277SAl Viro 	return err;
762c8ccbe03SMiklos Szeredi 
763c8ccbe03SMiklos Szeredi mknod:
7645ebb29beSChristian Brauner 	err = fuse_mknod(&nop_mnt_idmap, dir, entry, mode, 0);
765d9585277SAl Viro 	if (err)
766c8ccbe03SMiklos Szeredi 		goto out_dput;
767c8ccbe03SMiklos Szeredi no_open:
768e45198a6SAl Viro 	return finish_no_open(file, res);
769fd72faacSMiklos Szeredi }
770fd72faacSMiklos Szeredi 
7716f9f1180SMiklos Szeredi /*
7726f9f1180SMiklos Szeredi  * Code shared between mknod, mkdir, symlink and link
7736f9f1180SMiklos Szeredi  */
774fcee216bSMax Reitz static int create_new_entry(struct fuse_mount *fm, struct fuse_args *args,
7759e6268dbSMiklos Szeredi 			    struct inode *dir, struct dentry *entry,
776541af6a0SAl Viro 			    umode_t mode)
7779e6268dbSMiklos Szeredi {
7789e6268dbSMiklos Szeredi 	struct fuse_entry_out outarg;
7799e6268dbSMiklos Szeredi 	struct inode *inode;
780c971e6a0SAl Viro 	struct dentry *d;
7819e6268dbSMiklos Szeredi 	int err;
78207e77dcaSMiklos Szeredi 	struct fuse_forget_link *forget;
7832d51013eSMiklos Szeredi 
7845d069dbeSMiklos Szeredi 	if (fuse_is_bad(dir))
7855d069dbeSMiklos Szeredi 		return -EIO;
7865d069dbeSMiklos Szeredi 
78707e77dcaSMiklos Szeredi 	forget = fuse_alloc_forget();
7887078187aSMiklos Szeredi 	if (!forget)
78907e77dcaSMiklos Szeredi 		return -ENOMEM;
7909e6268dbSMiklos Szeredi 
7910e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
792d5b48543SMiklos Szeredi 	args->nodeid = get_node_id(dir);
793d5b48543SMiklos Szeredi 	args->out_numargs = 1;
794d5b48543SMiklos Szeredi 	args->out_args[0].size = sizeof(outarg);
795d5b48543SMiklos Szeredi 	args->out_args[0].value = &outarg;
7963e2b6fdbSVivek Goyal 
79715d937d7SMiklos Szeredi 	if (args->opcode != FUSE_LINK) {
7988ed7cb3fSMiklos Szeredi 		err = get_create_ext(args, dir, entry, mode);
7993e2b6fdbSVivek Goyal 		if (err)
8003e2b6fdbSVivek Goyal 			goto out_put_forget_req;
8013e2b6fdbSVivek Goyal 	}
8023e2b6fdbSVivek Goyal 
803fcee216bSMax Reitz 	err = fuse_simple_request(fm, args);
80415d937d7SMiklos Szeredi 	free_ext_value(args);
8052d51013eSMiklos Szeredi 	if (err)
8062d51013eSMiklos Szeredi 		goto out_put_forget_req;
8072d51013eSMiklos Szeredi 
80839ee059aSMiklos Szeredi 	err = -EIO;
809eb59bd17SMiklos Szeredi 	if (invalid_nodeid(outarg.nodeid) || fuse_invalid_attr(&outarg.attr))
8102d51013eSMiklos Szeredi 		goto out_put_forget_req;
81139ee059aSMiklos Szeredi 
81239ee059aSMiklos Szeredi 	if ((outarg.attr.mode ^ mode) & S_IFMT)
8132d51013eSMiklos Szeredi 		goto out_put_forget_req;
81439ee059aSMiklos Szeredi 
8159e6268dbSMiklos Szeredi 	inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
8161fb69e78SMiklos Szeredi 			  &outarg.attr, entry_attr_timeout(&outarg), 0);
8179e6268dbSMiklos Szeredi 	if (!inode) {
818fcee216bSMax Reitz 		fuse_queue_forget(fm->fc, forget, outarg.nodeid, 1);
8199e6268dbSMiklos Szeredi 		return -ENOMEM;
8209e6268dbSMiklos Szeredi 	}
82107e77dcaSMiklos Szeredi 	kfree(forget);
8229e6268dbSMiklos Szeredi 
823c971e6a0SAl Viro 	d_drop(entry);
824c971e6a0SAl Viro 	d = d_splice_alias(inode, entry);
825c971e6a0SAl Viro 	if (IS_ERR(d))
826c971e6a0SAl Viro 		return PTR_ERR(d);
827d2a85164SMiklos Szeredi 
828c971e6a0SAl Viro 	if (d) {
829c971e6a0SAl Viro 		fuse_change_entry_timeout(d, &outarg);
830c971e6a0SAl Viro 		dput(d);
831c971e6a0SAl Viro 	} else {
8321fb69e78SMiklos Szeredi 		fuse_change_entry_timeout(entry, &outarg);
833c971e6a0SAl Viro 	}
834261aaba7SMiklos Szeredi 	fuse_dir_changed(dir);
8359e6268dbSMiklos Szeredi 	return 0;
83639ee059aSMiklos Szeredi 
8372d51013eSMiklos Szeredi  out_put_forget_req:
83807e77dcaSMiklos Szeredi 	kfree(forget);
83939ee059aSMiklos Szeredi 	return err;
8409e6268dbSMiklos Szeredi }
8419e6268dbSMiklos Szeredi 
8425ebb29beSChristian Brauner static int fuse_mknod(struct mnt_idmap *idmap, struct inode *dir,
843549c7297SChristian Brauner 		      struct dentry *entry, umode_t mode, dev_t rdev)
8449e6268dbSMiklos Szeredi {
8459e6268dbSMiklos Szeredi 	struct fuse_mknod_in inarg;
846fcee216bSMax Reitz 	struct fuse_mount *fm = get_fuse_mount(dir);
8477078187aSMiklos Szeredi 	FUSE_ARGS(args);
8489e6268dbSMiklos Szeredi 
849fcee216bSMax Reitz 	if (!fm->fc->dont_mask)
850e0a43ddcSMiklos Szeredi 		mode &= ~current_umask();
851e0a43ddcSMiklos Szeredi 
8529e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
8539e6268dbSMiklos Szeredi 	inarg.mode = mode;
8549e6268dbSMiklos Szeredi 	inarg.rdev = new_encode_dev(rdev);
855e0a43ddcSMiklos Szeredi 	inarg.umask = current_umask();
856d5b48543SMiklos Szeredi 	args.opcode = FUSE_MKNOD;
857d5b48543SMiklos Szeredi 	args.in_numargs = 2;
858d5b48543SMiklos Szeredi 	args.in_args[0].size = sizeof(inarg);
859d5b48543SMiklos Szeredi 	args.in_args[0].value = &inarg;
860d5b48543SMiklos Szeredi 	args.in_args[1].size = entry->d_name.len + 1;
861d5b48543SMiklos Szeredi 	args.in_args[1].value = entry->d_name.name;
862fcee216bSMax Reitz 	return create_new_entry(fm, &args, dir, entry, mode);
8639e6268dbSMiklos Szeredi }
8649e6268dbSMiklos Szeredi 
8656c960e68SChristian Brauner static int fuse_create(struct mnt_idmap *idmap, struct inode *dir,
866549c7297SChristian Brauner 		       struct dentry *entry, umode_t mode, bool excl)
8679e6268dbSMiklos Szeredi {
8685ebb29beSChristian Brauner 	return fuse_mknod(&nop_mnt_idmap, dir, entry, mode, 0);
8699e6268dbSMiklos Szeredi }
8709e6268dbSMiklos Szeredi 
871011e2b71SChristian Brauner static int fuse_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
8727d375390SMiklos Szeredi 			struct file *file, umode_t mode)
8737d375390SMiklos Szeredi {
8747d375390SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
8757d375390SMiklos Szeredi 	int err;
8767d375390SMiklos Szeredi 
8777d375390SMiklos Szeredi 	if (fc->no_tmpfile)
8787d375390SMiklos Szeredi 		return -EOPNOTSUPP;
8797d375390SMiklos Szeredi 
8807d375390SMiklos Szeredi 	err = fuse_create_open(dir, file->f_path.dentry, file, file->f_flags, mode, FUSE_TMPFILE);
8817d375390SMiklos Szeredi 	if (err == -ENOSYS) {
8827d375390SMiklos Szeredi 		fc->no_tmpfile = 1;
8837d375390SMiklos Szeredi 		err = -EOPNOTSUPP;
8847d375390SMiklos Szeredi 	}
8857d375390SMiklos Szeredi 	return err;
8867d375390SMiklos Szeredi }
8877d375390SMiklos Szeredi 
888c54bd91eSChristian Brauner static int fuse_mkdir(struct mnt_idmap *idmap, struct inode *dir,
889549c7297SChristian Brauner 		      struct dentry *entry, umode_t mode)
8909e6268dbSMiklos Szeredi {
8919e6268dbSMiklos Szeredi 	struct fuse_mkdir_in inarg;
892fcee216bSMax Reitz 	struct fuse_mount *fm = get_fuse_mount(dir);
8937078187aSMiklos Szeredi 	FUSE_ARGS(args);
8949e6268dbSMiklos Szeredi 
895fcee216bSMax Reitz 	if (!fm->fc->dont_mask)
896e0a43ddcSMiklos Szeredi 		mode &= ~current_umask();
897e0a43ddcSMiklos Szeredi 
8989e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
8999e6268dbSMiklos Szeredi 	inarg.mode = mode;
900e0a43ddcSMiklos Szeredi 	inarg.umask = current_umask();
901d5b48543SMiklos Szeredi 	args.opcode = FUSE_MKDIR;
902d5b48543SMiklos Szeredi 	args.in_numargs = 2;
903d5b48543SMiklos Szeredi 	args.in_args[0].size = sizeof(inarg);
904d5b48543SMiklos Szeredi 	args.in_args[0].value = &inarg;
905d5b48543SMiklos Szeredi 	args.in_args[1].size = entry->d_name.len + 1;
906d5b48543SMiklos Szeredi 	args.in_args[1].value = entry->d_name.name;
907fcee216bSMax Reitz 	return create_new_entry(fm, &args, dir, entry, S_IFDIR);
9089e6268dbSMiklos Szeredi }
9099e6268dbSMiklos Szeredi 
9107a77db95SChristian Brauner static int fuse_symlink(struct mnt_idmap *idmap, struct inode *dir,
911549c7297SChristian Brauner 			struct dentry *entry, const char *link)
9129e6268dbSMiklos Szeredi {
913fcee216bSMax Reitz 	struct fuse_mount *fm = get_fuse_mount(dir);
9149e6268dbSMiklos Szeredi 	unsigned len = strlen(link) + 1;
9157078187aSMiklos Szeredi 	FUSE_ARGS(args);
9169e6268dbSMiklos Szeredi 
917d5b48543SMiklos Szeredi 	args.opcode = FUSE_SYMLINK;
918d5b48543SMiklos Szeredi 	args.in_numargs = 2;
919d5b48543SMiklos Szeredi 	args.in_args[0].size = entry->d_name.len + 1;
920d5b48543SMiklos Szeredi 	args.in_args[0].value = entry->d_name.name;
921d5b48543SMiklos Szeredi 	args.in_args[1].size = len;
922d5b48543SMiklos Szeredi 	args.in_args[1].value = link;
923fcee216bSMax Reitz 	return create_new_entry(fm, &args, dir, entry, S_IFLNK);
9249e6268dbSMiklos Szeredi }
9259e6268dbSMiklos Szeredi 
9265c791fe1SMiklos Szeredi void fuse_flush_time_update(struct inode *inode)
9275c791fe1SMiklos Szeredi {
9285c791fe1SMiklos Szeredi 	int err = sync_inode_metadata(inode, 1);
9295c791fe1SMiklos Szeredi 
9305c791fe1SMiklos Szeredi 	mapping_set_error(inode->i_mapping, err);
9315c791fe1SMiklos Szeredi }
9325c791fe1SMiklos Szeredi 
93397f044f6SMiklos Szeredi static void fuse_update_ctime_in_cache(struct inode *inode)
93431f3267bSMaxim Patlasov {
93531f3267bSMaxim Patlasov 	if (!IS_NOCMTIME(inode)) {
936c2050a45SDeepa Dinamani 		inode->i_ctime = current_time(inode);
93731f3267bSMaxim Patlasov 		mark_inode_dirty_sync(inode);
9385c791fe1SMiklos Szeredi 		fuse_flush_time_update(inode);
93931f3267bSMaxim Patlasov 	}
94031f3267bSMaxim Patlasov }
94131f3267bSMaxim Patlasov 
94297f044f6SMiklos Szeredi void fuse_update_ctime(struct inode *inode)
94397f044f6SMiklos Szeredi {
944fa5eee57SMiklos Szeredi 	fuse_invalidate_attr_mask(inode, STATX_CTIME);
94597f044f6SMiklos Szeredi 	fuse_update_ctime_in_cache(inode);
94697f044f6SMiklos Szeredi }
94797f044f6SMiklos Szeredi 
948cefd1b83SMiklos Szeredi static void fuse_entry_unlinked(struct dentry *entry)
949cefd1b83SMiklos Szeredi {
950cefd1b83SMiklos Szeredi 	struct inode *inode = d_inode(entry);
951cefd1b83SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
952cefd1b83SMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
953cefd1b83SMiklos Szeredi 
954cefd1b83SMiklos Szeredi 	spin_lock(&fi->lock);
955cefd1b83SMiklos Szeredi 	fi->attr_version = atomic64_inc_return(&fc->attr_version);
956cefd1b83SMiklos Szeredi 	/*
957cefd1b83SMiklos Szeredi 	 * If i_nlink == 0 then unlink doesn't make sense, yet this can
958cefd1b83SMiklos Szeredi 	 * happen if userspace filesystem is careless.  It would be
959cefd1b83SMiklos Szeredi 	 * difficult to enforce correct nlink usage so just ignore this
960cefd1b83SMiklos Szeredi 	 * condition here
961cefd1b83SMiklos Szeredi 	 */
962cefd1b83SMiklos Szeredi 	if (S_ISDIR(inode->i_mode))
963cefd1b83SMiklos Szeredi 		clear_nlink(inode);
964cefd1b83SMiklos Szeredi 	else if (inode->i_nlink > 0)
965cefd1b83SMiklos Szeredi 		drop_nlink(inode);
966cefd1b83SMiklos Szeredi 	spin_unlock(&fi->lock);
967cefd1b83SMiklos Szeredi 	fuse_invalidate_entry_cache(entry);
968cefd1b83SMiklos Szeredi 	fuse_update_ctime(inode);
969cefd1b83SMiklos Szeredi }
970cefd1b83SMiklos Szeredi 
9719e6268dbSMiklos Szeredi static int fuse_unlink(struct inode *dir, struct dentry *entry)
9729e6268dbSMiklos Szeredi {
9739e6268dbSMiklos Szeredi 	int err;
974fcee216bSMax Reitz 	struct fuse_mount *fm = get_fuse_mount(dir);
9757078187aSMiklos Szeredi 	FUSE_ARGS(args);
9769e6268dbSMiklos Szeredi 
9775d069dbeSMiklos Szeredi 	if (fuse_is_bad(dir))
9785d069dbeSMiklos Szeredi 		return -EIO;
9795d069dbeSMiklos Szeredi 
980d5b48543SMiklos Szeredi 	args.opcode = FUSE_UNLINK;
981d5b48543SMiklos Szeredi 	args.nodeid = get_node_id(dir);
982d5b48543SMiklos Szeredi 	args.in_numargs = 1;
983d5b48543SMiklos Szeredi 	args.in_args[0].size = entry->d_name.len + 1;
984d5b48543SMiklos Szeredi 	args.in_args[0].value = entry->d_name.name;
985fcee216bSMax Reitz 	err = fuse_simple_request(fm, &args);
9869e6268dbSMiklos Szeredi 	if (!err) {
987261aaba7SMiklos Szeredi 		fuse_dir_changed(dir);
988cefd1b83SMiklos Szeredi 		fuse_entry_unlinked(entry);
9899e6268dbSMiklos Szeredi 	} else if (err == -EINTR)
9909e6268dbSMiklos Szeredi 		fuse_invalidate_entry(entry);
9919e6268dbSMiklos Szeredi 	return err;
9929e6268dbSMiklos Szeredi }
9939e6268dbSMiklos Szeredi 
9949e6268dbSMiklos Szeredi static int fuse_rmdir(struct inode *dir, struct dentry *entry)
9959e6268dbSMiklos Szeredi {
9969e6268dbSMiklos Szeredi 	int err;
997fcee216bSMax Reitz 	struct fuse_mount *fm = get_fuse_mount(dir);
9987078187aSMiklos Szeredi 	FUSE_ARGS(args);
9999e6268dbSMiklos Szeredi 
10005d069dbeSMiklos Szeredi 	if (fuse_is_bad(dir))
10015d069dbeSMiklos Szeredi 		return -EIO;
10025d069dbeSMiklos Szeredi 
1003d5b48543SMiklos Szeredi 	args.opcode = FUSE_RMDIR;
1004d5b48543SMiklos Szeredi 	args.nodeid = get_node_id(dir);
1005d5b48543SMiklos Szeredi 	args.in_numargs = 1;
1006d5b48543SMiklos Szeredi 	args.in_args[0].size = entry->d_name.len + 1;
1007d5b48543SMiklos Szeredi 	args.in_args[0].value = entry->d_name.name;
1008fcee216bSMax Reitz 	err = fuse_simple_request(fm, &args);
10099e6268dbSMiklos Szeredi 	if (!err) {
1010261aaba7SMiklos Szeredi 		fuse_dir_changed(dir);
1011cefd1b83SMiklos Szeredi 		fuse_entry_unlinked(entry);
10129e6268dbSMiklos Szeredi 	} else if (err == -EINTR)
10139e6268dbSMiklos Szeredi 		fuse_invalidate_entry(entry);
10149e6268dbSMiklos Szeredi 	return err;
10159e6268dbSMiklos Szeredi }
10169e6268dbSMiklos Szeredi 
10171560c974SMiklos Szeredi static int fuse_rename_common(struct inode *olddir, struct dentry *oldent,
10181560c974SMiklos Szeredi 			      struct inode *newdir, struct dentry *newent,
10191560c974SMiklos Szeredi 			      unsigned int flags, int opcode, size_t argsize)
10209e6268dbSMiklos Szeredi {
10219e6268dbSMiklos Szeredi 	int err;
10221560c974SMiklos Szeredi 	struct fuse_rename2_in inarg;
1023fcee216bSMax Reitz 	struct fuse_mount *fm = get_fuse_mount(olddir);
10247078187aSMiklos Szeredi 	FUSE_ARGS(args);
10259e6268dbSMiklos Szeredi 
10261560c974SMiklos Szeredi 	memset(&inarg, 0, argsize);
10279e6268dbSMiklos Szeredi 	inarg.newdir = get_node_id(newdir);
10281560c974SMiklos Szeredi 	inarg.flags = flags;
1029d5b48543SMiklos Szeredi 	args.opcode = opcode;
1030d5b48543SMiklos Szeredi 	args.nodeid = get_node_id(olddir);
1031d5b48543SMiklos Szeredi 	args.in_numargs = 3;
1032d5b48543SMiklos Szeredi 	args.in_args[0].size = argsize;
1033d5b48543SMiklos Szeredi 	args.in_args[0].value = &inarg;
1034d5b48543SMiklos Szeredi 	args.in_args[1].size = oldent->d_name.len + 1;
1035d5b48543SMiklos Szeredi 	args.in_args[1].value = oldent->d_name.name;
1036d5b48543SMiklos Szeredi 	args.in_args[2].size = newent->d_name.len + 1;
1037d5b48543SMiklos Szeredi 	args.in_args[2].value = newent->d_name.name;
1038fcee216bSMax Reitz 	err = fuse_simple_request(fm, &args);
10399e6268dbSMiklos Szeredi 	if (!err) {
104008b63307SMiklos Szeredi 		/* ctime changes */
10412b0143b5SDavid Howells 		fuse_update_ctime(d_inode(oldent));
104208b63307SMiklos Szeredi 
1043371e8fd0SMiklos Szeredi 		if (flags & RENAME_EXCHANGE)
10442b0143b5SDavid Howells 			fuse_update_ctime(d_inode(newent));
10451560c974SMiklos Szeredi 
1046261aaba7SMiklos Szeredi 		fuse_dir_changed(olddir);
10479e6268dbSMiklos Szeredi 		if (olddir != newdir)
1048261aaba7SMiklos Szeredi 			fuse_dir_changed(newdir);
10498cbdf1e6SMiklos Szeredi 
10508cbdf1e6SMiklos Szeredi 		/* newent will end up negative */
1051cefd1b83SMiklos Szeredi 		if (!(flags & RENAME_EXCHANGE) && d_really_is_positive(newent))
1052cefd1b83SMiklos Szeredi 			fuse_entry_unlinked(newent);
10539e6268dbSMiklos Szeredi 	} else if (err == -EINTR) {
10549e6268dbSMiklos Szeredi 		/* If request was interrupted, DEITY only knows if the
10559e6268dbSMiklos Szeredi 		   rename actually took place.  If the invalidation
10569e6268dbSMiklos Szeredi 		   fails (e.g. some process has CWD under the renamed
10579e6268dbSMiklos Szeredi 		   directory), then there can be inconsistency between
10589e6268dbSMiklos Szeredi 		   the dcache and the real filesystem.  Tough luck. */
10599e6268dbSMiklos Szeredi 		fuse_invalidate_entry(oldent);
10602b0143b5SDavid Howells 		if (d_really_is_positive(newent))
10619e6268dbSMiklos Szeredi 			fuse_invalidate_entry(newent);
10629e6268dbSMiklos Szeredi 	}
10639e6268dbSMiklos Szeredi 
10649e6268dbSMiklos Szeredi 	return err;
10659e6268dbSMiklos Szeredi }
10669e6268dbSMiklos Szeredi 
1067e18275aeSChristian Brauner static int fuse_rename2(struct mnt_idmap *idmap, struct inode *olddir,
1068549c7297SChristian Brauner 			struct dentry *oldent, struct inode *newdir,
1069549c7297SChristian Brauner 			struct dentry *newent, unsigned int flags)
10701560c974SMiklos Szeredi {
10711560c974SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(olddir);
10721560c974SMiklos Szeredi 	int err;
10731560c974SMiklos Szeredi 
10745d069dbeSMiklos Szeredi 	if (fuse_is_bad(olddir))
10755d069dbeSMiklos Szeredi 		return -EIO;
10765d069dbeSMiklos Szeredi 
1077519525faSVivek Goyal 	if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT))
10781560c974SMiklos Szeredi 		return -EINVAL;
10791560c974SMiklos Szeredi 
10804237ba43SMiklos Szeredi 	if (flags) {
10811560c974SMiklos Szeredi 		if (fc->no_rename2 || fc->minor < 23)
10821560c974SMiklos Szeredi 			return -EINVAL;
10831560c974SMiklos Szeredi 
10841560c974SMiklos Szeredi 		err = fuse_rename_common(olddir, oldent, newdir, newent, flags,
10854237ba43SMiklos Szeredi 					 FUSE_RENAME2,
10864237ba43SMiklos Szeredi 					 sizeof(struct fuse_rename2_in));
10871560c974SMiklos Szeredi 		if (err == -ENOSYS) {
10881560c974SMiklos Szeredi 			fc->no_rename2 = 1;
10891560c974SMiklos Szeredi 			err = -EINVAL;
10901560c974SMiklos Szeredi 		}
10914237ba43SMiklos Szeredi 	} else {
10924237ba43SMiklos Szeredi 		err = fuse_rename_common(olddir, oldent, newdir, newent, 0,
10934237ba43SMiklos Szeredi 					 FUSE_RENAME,
10944237ba43SMiklos Szeredi 					 sizeof(struct fuse_rename_in));
10954237ba43SMiklos Szeredi 	}
10961560c974SMiklos Szeredi 
10974237ba43SMiklos Szeredi 	return err;
10984237ba43SMiklos Szeredi }
10994237ba43SMiklos Szeredi 
11009e6268dbSMiklos Szeredi static int fuse_link(struct dentry *entry, struct inode *newdir,
11019e6268dbSMiklos Szeredi 		     struct dentry *newent)
11029e6268dbSMiklos Szeredi {
11039e6268dbSMiklos Szeredi 	int err;
11049e6268dbSMiklos Szeredi 	struct fuse_link_in inarg;
11052b0143b5SDavid Howells 	struct inode *inode = d_inode(entry);
1106fcee216bSMax Reitz 	struct fuse_mount *fm = get_fuse_mount(inode);
11077078187aSMiklos Szeredi 	FUSE_ARGS(args);
11089e6268dbSMiklos Szeredi 
11099e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
11109e6268dbSMiklos Szeredi 	inarg.oldnodeid = get_node_id(inode);
1111d5b48543SMiklos Szeredi 	args.opcode = FUSE_LINK;
1112d5b48543SMiklos Szeredi 	args.in_numargs = 2;
1113d5b48543SMiklos Szeredi 	args.in_args[0].size = sizeof(inarg);
1114d5b48543SMiklos Szeredi 	args.in_args[0].value = &inarg;
1115d5b48543SMiklos Szeredi 	args.in_args[1].size = newent->d_name.len + 1;
1116d5b48543SMiklos Szeredi 	args.in_args[1].value = newent->d_name.name;
1117fcee216bSMax Reitz 	err = create_new_entry(fm, &args, newdir, newent, inode->i_mode);
111897f044f6SMiklos Szeredi 	if (!err)
111997f044f6SMiklos Szeredi 		fuse_update_ctime_in_cache(inode);
112097f044f6SMiklos Szeredi 	else if (err == -EINTR)
1121ac45d613SMiklos Szeredi 		fuse_invalidate_attr(inode);
112297f044f6SMiklos Szeredi 
11239e6268dbSMiklos Szeredi 	return err;
11249e6268dbSMiklos Szeredi }
11259e6268dbSMiklos Szeredi 
11261fb69e78SMiklos Szeredi static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
11271fb69e78SMiklos Szeredi 			  struct kstat *stat)
11281fb69e78SMiklos Szeredi {
1129203627bbSMiklos Szeredi 	unsigned int blkbits;
11308373200bSPavel Emelyanov 	struct fuse_conn *fc = get_fuse_conn(inode);
11318373200bSPavel Emelyanov 
11321fb69e78SMiklos Szeredi 	stat->dev = inode->i_sb->s_dev;
11331fb69e78SMiklos Szeredi 	stat->ino = attr->ino;
11341fb69e78SMiklos Szeredi 	stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
11351fb69e78SMiklos Szeredi 	stat->nlink = attr->nlink;
11368cb08329SEric W. Biederman 	stat->uid = make_kuid(fc->user_ns, attr->uid);
11378cb08329SEric W. Biederman 	stat->gid = make_kgid(fc->user_ns, attr->gid);
11381fb69e78SMiklos Szeredi 	stat->rdev = inode->i_rdev;
11391fb69e78SMiklos Szeredi 	stat->atime.tv_sec = attr->atime;
11401fb69e78SMiklos Szeredi 	stat->atime.tv_nsec = attr->atimensec;
11411fb69e78SMiklos Szeredi 	stat->mtime.tv_sec = attr->mtime;
11421fb69e78SMiklos Szeredi 	stat->mtime.tv_nsec = attr->mtimensec;
11431fb69e78SMiklos Szeredi 	stat->ctime.tv_sec = attr->ctime;
11441fb69e78SMiklos Szeredi 	stat->ctime.tv_nsec = attr->ctimensec;
11451fb69e78SMiklos Szeredi 	stat->size = attr->size;
11461fb69e78SMiklos Szeredi 	stat->blocks = attr->blocks;
1147203627bbSMiklos Szeredi 
1148203627bbSMiklos Szeredi 	if (attr->blksize != 0)
1149203627bbSMiklos Szeredi 		blkbits = ilog2(attr->blksize);
1150203627bbSMiklos Szeredi 	else
1151203627bbSMiklos Szeredi 		blkbits = inode->i_sb->s_blocksize_bits;
1152203627bbSMiklos Szeredi 
1153203627bbSMiklos Szeredi 	stat->blksize = 1 << blkbits;
11541fb69e78SMiklos Szeredi }
11551fb69e78SMiklos Szeredi 
1156c79e322fSMiklos Szeredi static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
1157c79e322fSMiklos Szeredi 			   struct file *file)
1158e5e5558eSMiklos Szeredi {
1159e5e5558eSMiklos Szeredi 	int err;
1160c79e322fSMiklos Szeredi 	struct fuse_getattr_in inarg;
1161c79e322fSMiklos Szeredi 	struct fuse_attr_out outarg;
1162fcee216bSMax Reitz 	struct fuse_mount *fm = get_fuse_mount(inode);
11637078187aSMiklos Szeredi 	FUSE_ARGS(args);
11641fb69e78SMiklos Szeredi 	u64 attr_version;
11651fb69e78SMiklos Szeredi 
1166fcee216bSMax Reitz 	attr_version = fuse_get_attr_version(fm->fc);
11671fb69e78SMiklos Szeredi 
1168c79e322fSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
11690e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
1170c79e322fSMiklos Szeredi 	/* Directories have separate file-handle space */
1171c79e322fSMiklos Szeredi 	if (file && S_ISREG(inode->i_mode)) {
1172c79e322fSMiklos Szeredi 		struct fuse_file *ff = file->private_data;
1173c79e322fSMiklos Szeredi 
1174c79e322fSMiklos Szeredi 		inarg.getattr_flags |= FUSE_GETATTR_FH;
1175c79e322fSMiklos Szeredi 		inarg.fh = ff->fh;
1176c79e322fSMiklos Szeredi 	}
1177d5b48543SMiklos Szeredi 	args.opcode = FUSE_GETATTR;
1178d5b48543SMiklos Szeredi 	args.nodeid = get_node_id(inode);
1179d5b48543SMiklos Szeredi 	args.in_numargs = 1;
1180d5b48543SMiklos Szeredi 	args.in_args[0].size = sizeof(inarg);
1181d5b48543SMiklos Szeredi 	args.in_args[0].value = &inarg;
1182d5b48543SMiklos Szeredi 	args.out_numargs = 1;
1183d5b48543SMiklos Szeredi 	args.out_args[0].size = sizeof(outarg);
1184d5b48543SMiklos Szeredi 	args.out_args[0].value = &outarg;
1185fcee216bSMax Reitz 	err = fuse_simple_request(fm, &args);
1186e5e5558eSMiklos Szeredi 	if (!err) {
1187eb59bd17SMiklos Szeredi 		if (fuse_invalid_attr(&outarg.attr) ||
11886e3e2c43SAl Viro 		    inode_wrong_type(inode, outarg.attr.mode)) {
11895d069dbeSMiklos Szeredi 			fuse_make_bad(inode);
1190e5e5558eSMiklos Szeredi 			err = -EIO;
1191e5e5558eSMiklos Szeredi 		} else {
1192c79e322fSMiklos Szeredi 			fuse_change_attributes(inode, &outarg.attr,
1193c79e322fSMiklos Szeredi 					       attr_timeout(&outarg),
11941fb69e78SMiklos Szeredi 					       attr_version);
11951fb69e78SMiklos Szeredi 			if (stat)
1196c79e322fSMiklos Szeredi 				fuse_fillattr(inode, &outarg.attr, stat);
1197e5e5558eSMiklos Szeredi 		}
1198e5e5558eSMiklos Szeredi 	}
1199e5e5558eSMiklos Szeredi 	return err;
1200e5e5558eSMiklos Szeredi }
1201e5e5558eSMiklos Szeredi 
12025b97eeacSMiklos Szeredi static int fuse_update_get_attr(struct inode *inode, struct file *file,
12032f1e8196SMiklos Szeredi 				struct kstat *stat, u32 request_mask,
12042f1e8196SMiklos Szeredi 				unsigned int flags)
1205bcb4be80SMiklos Szeredi {
1206bcb4be80SMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
12075b97eeacSMiklos Szeredi 	int err = 0;
1208bf5c1898SMiklos Szeredi 	bool sync;
1209ec855375SMiklos Szeredi 	u32 inval_mask = READ_ONCE(fi->inval_mask);
1210ec855375SMiklos Szeredi 	u32 cache_mask = fuse_get_cache_mask(inode);
1211bcb4be80SMiklos Szeredi 
1212*8d8f9c4bSMiklos Szeredi 	/* FUSE only supports basic stats */
1213*8d8f9c4bSMiklos Szeredi 	request_mask &= STATX_BASIC_STATS;
1214*8d8f9c4bSMiklos Szeredi 
1215*8d8f9c4bSMiklos Szeredi 	if (!request_mask)
1216*8d8f9c4bSMiklos Szeredi 		sync = false;
1217*8d8f9c4bSMiklos Szeredi 	else if (flags & AT_STATX_FORCE_SYNC)
1218bf5c1898SMiklos Szeredi 		sync = true;
1219bf5c1898SMiklos Szeredi 	else if (flags & AT_STATX_DONT_SYNC)
1220bf5c1898SMiklos Szeredi 		sync = false;
1221ec855375SMiklos Szeredi 	else if (request_mask & inval_mask & ~cache_mask)
12222f1e8196SMiklos Szeredi 		sync = true;
1223bf5c1898SMiklos Szeredi 	else
1224bf5c1898SMiklos Szeredi 		sync = time_before64(fi->i_time, get_jiffies_64());
1225bf5c1898SMiklos Szeredi 
1226bf5c1898SMiklos Szeredi 	if (sync) {
122760bcc88aSSeth Forshee 		forget_all_cached_acls(inode);
1228bcb4be80SMiklos Szeredi 		err = fuse_do_getattr(inode, stat, file);
12295b97eeacSMiklos Szeredi 	} else if (stat) {
1230b74d24f7SChristian Brauner 		generic_fillattr(&nop_mnt_idmap, inode, stat);
1231bcb4be80SMiklos Szeredi 		stat->mode = fi->orig_i_mode;
123245c72cd7SPavel Shilovsky 		stat->ino = fi->orig_ino;
1233bcb4be80SMiklos Szeredi 	}
1234bcb4be80SMiklos Szeredi 
1235bcb4be80SMiklos Szeredi 	return err;
1236bcb4be80SMiklos Szeredi }
1237bcb4be80SMiklos Szeredi 
1238c6c745b8SMiklos Szeredi int fuse_update_attributes(struct inode *inode, struct file *file, u32 mask)
12395b97eeacSMiklos Szeredi {
1240c6c745b8SMiklos Szeredi 	return fuse_update_get_attr(inode, file, NULL, mask, 0);
12415b97eeacSMiklos Szeredi }
12425b97eeacSMiklos Szeredi 
1243fcee216bSMax Reitz int fuse_reverse_inval_entry(struct fuse_conn *fc, u64 parent_nodeid,
12444f8d3702SMiklos Szeredi 			     u64 child_nodeid, struct qstr *name, u32 flags)
12453b463ae0SJohn Muir {
12463b463ae0SJohn Muir 	int err = -ENOTDIR;
12473b463ae0SJohn Muir 	struct inode *parent;
12483b463ae0SJohn Muir 	struct dentry *dir;
12493b463ae0SJohn Muir 	struct dentry *entry;
12503b463ae0SJohn Muir 
1251fcee216bSMax Reitz 	parent = fuse_ilookup(fc, parent_nodeid, NULL);
12523b463ae0SJohn Muir 	if (!parent)
12533b463ae0SJohn Muir 		return -ENOENT;
12543b463ae0SJohn Muir 
1255bda9a719SMiklos Szeredi 	inode_lock_nested(parent, I_MUTEX_PARENT);
12563b463ae0SJohn Muir 	if (!S_ISDIR(parent->i_mode))
12573b463ae0SJohn Muir 		goto unlock;
12583b463ae0SJohn Muir 
12593b463ae0SJohn Muir 	err = -ENOENT;
12603b463ae0SJohn Muir 	dir = d_find_alias(parent);
12613b463ae0SJohn Muir 	if (!dir)
12623b463ae0SJohn Muir 		goto unlock;
12633b463ae0SJohn Muir 
12648387ff25SLinus Torvalds 	name->hash = full_name_hash(dir, name->name, name->len);
12653b463ae0SJohn Muir 	entry = d_lookup(dir, name);
12663b463ae0SJohn Muir 	dput(dir);
12673b463ae0SJohn Muir 	if (!entry)
12683b463ae0SJohn Muir 		goto unlock;
12693b463ae0SJohn Muir 
1270261aaba7SMiklos Szeredi 	fuse_dir_changed(parent);
12714f8d3702SMiklos Szeredi 	if (!(flags & FUSE_EXPIRE_ONLY))
12724f8d3702SMiklos Szeredi 		d_invalidate(entry);
12734f8d3702SMiklos Szeredi 	fuse_invalidate_entry_cache(entry);
1274451d0f59SJohn Muir 
12752b0143b5SDavid Howells 	if (child_nodeid != 0 && d_really_is_positive(entry)) {
12765955102cSAl Viro 		inode_lock(d_inode(entry));
12772b0143b5SDavid Howells 		if (get_node_id(d_inode(entry)) != child_nodeid) {
1278451d0f59SJohn Muir 			err = -ENOENT;
1279451d0f59SJohn Muir 			goto badentry;
1280451d0f59SJohn Muir 		}
1281451d0f59SJohn Muir 		if (d_mountpoint(entry)) {
1282451d0f59SJohn Muir 			err = -EBUSY;
1283451d0f59SJohn Muir 			goto badentry;
1284451d0f59SJohn Muir 		}
1285e36cb0b8SDavid Howells 		if (d_is_dir(entry)) {
1286451d0f59SJohn Muir 			shrink_dcache_parent(entry);
1287451d0f59SJohn Muir 			if (!simple_empty(entry)) {
1288451d0f59SJohn Muir 				err = -ENOTEMPTY;
1289451d0f59SJohn Muir 				goto badentry;
1290451d0f59SJohn Muir 			}
12912b0143b5SDavid Howells 			d_inode(entry)->i_flags |= S_DEAD;
1292451d0f59SJohn Muir 		}
1293451d0f59SJohn Muir 		dont_mount(entry);
12942b0143b5SDavid Howells 		clear_nlink(d_inode(entry));
12953b463ae0SJohn Muir 		err = 0;
1296451d0f59SJohn Muir  badentry:
12975955102cSAl Viro 		inode_unlock(d_inode(entry));
1298451d0f59SJohn Muir 		if (!err)
1299451d0f59SJohn Muir 			d_delete(entry);
1300451d0f59SJohn Muir 	} else {
1301451d0f59SJohn Muir 		err = 0;
1302451d0f59SJohn Muir 	}
1303451d0f59SJohn Muir 	dput(entry);
13043b463ae0SJohn Muir 
13053b463ae0SJohn Muir  unlock:
13065955102cSAl Viro 	inode_unlock(parent);
13073b463ae0SJohn Muir 	iput(parent);
13083b463ae0SJohn Muir 	return err;
13093b463ae0SJohn Muir }
13103b463ae0SJohn Muir 
1311b1387777SDave Marchevsky static inline bool fuse_permissible_uidgid(struct fuse_conn *fc)
1312b1387777SDave Marchevsky {
1313b1387777SDave Marchevsky 	const struct cred *cred = current_cred();
1314b1387777SDave Marchevsky 
1315b1387777SDave Marchevsky 	return (uid_eq(cred->euid, fc->user_id) &&
1316b1387777SDave Marchevsky 		uid_eq(cred->suid, fc->user_id) &&
1317b1387777SDave Marchevsky 		uid_eq(cred->uid,  fc->user_id) &&
1318b1387777SDave Marchevsky 		gid_eq(cred->egid, fc->group_id) &&
1319b1387777SDave Marchevsky 		gid_eq(cred->sgid, fc->group_id) &&
1320b1387777SDave Marchevsky 		gid_eq(cred->gid,  fc->group_id));
1321b1387777SDave Marchevsky }
1322b1387777SDave Marchevsky 
132387729a55SMiklos Szeredi /*
132487729a55SMiklos Szeredi  * Calling into a user-controlled filesystem gives the filesystem
1325c2132c1bSAnatol Pomozov  * daemon ptrace-like capabilities over the current process.  This
132687729a55SMiklos Szeredi  * means, that the filesystem daemon is able to record the exact
132787729a55SMiklos Szeredi  * filesystem operations performed, and can also control the behavior
132887729a55SMiklos Szeredi  * of the requester process in otherwise impossible ways.  For example
132987729a55SMiklos Szeredi  * it can delay the operation for arbitrary length of time allowing
133087729a55SMiklos Szeredi  * DoS against the requester.
133187729a55SMiklos Szeredi  *
133287729a55SMiklos Szeredi  * For this reason only those processes can call into the filesystem,
133387729a55SMiklos Szeredi  * for which the owner of the mount has ptrace privilege.  This
133487729a55SMiklos Szeredi  * excludes processes started by other users, suid or sgid processes.
133587729a55SMiklos Szeredi  */
1336b1387777SDave Marchevsky bool fuse_allow_current_process(struct fuse_conn *fc)
133787729a55SMiklos Szeredi {
1338b1387777SDave Marchevsky 	bool allow;
13399ccf47b2SDave Marchevsky 
134029433a29SMiklos Szeredi 	if (fc->allow_other)
1341b1387777SDave Marchevsky 		allow = current_in_userns(fc->user_ns);
1342b1387777SDave Marchevsky 	else
1343b1387777SDave Marchevsky 		allow = fuse_permissible_uidgid(fc);
134487729a55SMiklos Szeredi 
1345b1387777SDave Marchevsky 	if (!allow && allow_sys_admin_access && capable(CAP_SYS_ADMIN))
1346b1387777SDave Marchevsky 		allow = true;
134787729a55SMiklos Szeredi 
1348b1387777SDave Marchevsky 	return allow;
134987729a55SMiklos Szeredi }
135087729a55SMiklos Szeredi 
135131d40d74SMiklos Szeredi static int fuse_access(struct inode *inode, int mask)
135231d40d74SMiklos Szeredi {
1353fcee216bSMax Reitz 	struct fuse_mount *fm = get_fuse_mount(inode);
13547078187aSMiklos Szeredi 	FUSE_ARGS(args);
135531d40d74SMiklos Szeredi 	struct fuse_access_in inarg;
135631d40d74SMiklos Szeredi 	int err;
135731d40d74SMiklos Szeredi 
1358698fa1d1SMiklos Szeredi 	BUG_ON(mask & MAY_NOT_BLOCK);
1359698fa1d1SMiklos Szeredi 
1360fcee216bSMax Reitz 	if (fm->fc->no_access)
136131d40d74SMiklos Szeredi 		return 0;
136231d40d74SMiklos Szeredi 
136331d40d74SMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
1364e6305c43SAl Viro 	inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC);
1365d5b48543SMiklos Szeredi 	args.opcode = FUSE_ACCESS;
1366d5b48543SMiklos Szeredi 	args.nodeid = get_node_id(inode);
1367d5b48543SMiklos Szeredi 	args.in_numargs = 1;
1368d5b48543SMiklos Szeredi 	args.in_args[0].size = sizeof(inarg);
1369d5b48543SMiklos Szeredi 	args.in_args[0].value = &inarg;
1370fcee216bSMax Reitz 	err = fuse_simple_request(fm, &args);
137131d40d74SMiklos Szeredi 	if (err == -ENOSYS) {
1372fcee216bSMax Reitz 		fm->fc->no_access = 1;
137331d40d74SMiklos Szeredi 		err = 0;
137431d40d74SMiklos Szeredi 	}
137531d40d74SMiklos Szeredi 	return err;
137631d40d74SMiklos Szeredi }
137731d40d74SMiklos Szeredi 
137810556cb2SAl Viro static int fuse_perm_getattr(struct inode *inode, int mask)
137919690ddbSMiklos Szeredi {
138010556cb2SAl Viro 	if (mask & MAY_NOT_BLOCK)
138119690ddbSMiklos Szeredi 		return -ECHILD;
138219690ddbSMiklos Szeredi 
138360bcc88aSSeth Forshee 	forget_all_cached_acls(inode);
138419690ddbSMiklos Szeredi 	return fuse_do_getattr(inode, NULL, NULL);
138519690ddbSMiklos Szeredi }
138619690ddbSMiklos Szeredi 
13876f9f1180SMiklos Szeredi /*
13886f9f1180SMiklos Szeredi  * Check permission.  The two basic access models of FUSE are:
13896f9f1180SMiklos Szeredi  *
13906f9f1180SMiklos Szeredi  * 1) Local access checking ('default_permissions' mount option) based
13916f9f1180SMiklos Szeredi  * on file mode.  This is the plain old disk filesystem permission
13926f9f1180SMiklos Szeredi  * modell.
13936f9f1180SMiklos Szeredi  *
13946f9f1180SMiklos Szeredi  * 2) "Remote" access checking, where server is responsible for
13956f9f1180SMiklos Szeredi  * checking permission in each inode operation.  An exception to this
13966f9f1180SMiklos Szeredi  * is if ->permission() was invoked from sys_access() in which case an
13976f9f1180SMiklos Szeredi  * access request is sent.  Execute permission is still checked
13986f9f1180SMiklos Szeredi  * locally based on file mode.
13996f9f1180SMiklos Szeredi  */
14004609e1f1SChristian Brauner static int fuse_permission(struct mnt_idmap *idmap,
1401549c7297SChristian Brauner 			   struct inode *inode, int mask)
1402e5e5558eSMiklos Szeredi {
1403e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1404244f6385SMiklos Szeredi 	bool refreshed = false;
1405244f6385SMiklos Szeredi 	int err = 0;
1406e5e5558eSMiklos Szeredi 
14075d069dbeSMiklos Szeredi 	if (fuse_is_bad(inode))
14085d069dbeSMiklos Szeredi 		return -EIO;
14095d069dbeSMiklos Szeredi 
1410c2132c1bSAnatol Pomozov 	if (!fuse_allow_current_process(fc))
1411e5e5558eSMiklos Szeredi 		return -EACCES;
1412244f6385SMiklos Szeredi 
1413244f6385SMiklos Szeredi 	/*
1414e8e96157SMiklos Szeredi 	 * If attributes are needed, refresh them before proceeding
1415244f6385SMiklos Szeredi 	 */
141629433a29SMiklos Szeredi 	if (fc->default_permissions ||
1417e8e96157SMiklos Szeredi 	    ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
141819690ddbSMiklos Szeredi 		struct fuse_inode *fi = get_fuse_inode(inode);
1419d233c7ddSMiklos Szeredi 		u32 perm_mask = STATX_MODE | STATX_UID | STATX_GID;
142019690ddbSMiklos Szeredi 
1421d233c7ddSMiklos Szeredi 		if (perm_mask & READ_ONCE(fi->inval_mask) ||
1422d233c7ddSMiklos Szeredi 		    time_before64(fi->i_time, get_jiffies_64())) {
142319690ddbSMiklos Szeredi 			refreshed = true;
142419690ddbSMiklos Szeredi 
142510556cb2SAl Viro 			err = fuse_perm_getattr(inode, mask);
1426244f6385SMiklos Szeredi 			if (err)
1427244f6385SMiklos Szeredi 				return err;
14281fb69e78SMiklos Szeredi 		}
142919690ddbSMiklos Szeredi 	}
1430244f6385SMiklos Szeredi 
143129433a29SMiklos Szeredi 	if (fc->default_permissions) {
14324609e1f1SChristian Brauner 		err = generic_permission(&nop_mnt_idmap, inode, mask);
14331e9a4ed9SMiklos Szeredi 
14341e9a4ed9SMiklos Szeredi 		/* If permission is denied, try to refresh file
14351e9a4ed9SMiklos Szeredi 		   attributes.  This is also needed, because the root
14361e9a4ed9SMiklos Szeredi 		   node will at first have no permissions */
1437244f6385SMiklos Szeredi 		if (err == -EACCES && !refreshed) {
143810556cb2SAl Viro 			err = fuse_perm_getattr(inode, mask);
14391e9a4ed9SMiklos Szeredi 			if (!err)
14404609e1f1SChristian Brauner 				err = generic_permission(&nop_mnt_idmap,
144147291baaSChristian Brauner 							 inode, mask);
14421e9a4ed9SMiklos Szeredi 		}
14431e9a4ed9SMiklos Szeredi 
14446f9f1180SMiklos Szeredi 		/* Note: the opposite of the above test does not
14456f9f1180SMiklos Szeredi 		   exist.  So if permissions are revoked this won't be
14466f9f1180SMiklos Szeredi 		   noticed immediately, only after the attribute
14476f9f1180SMiklos Szeredi 		   timeout has expired */
14489cfcac81SEric Paris 	} else if (mask & (MAY_ACCESS | MAY_CHDIR)) {
1449e8e96157SMiklos Szeredi 		err = fuse_access(inode, mask);
1450e8e96157SMiklos Szeredi 	} else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
1451e8e96157SMiklos Szeredi 		if (!(inode->i_mode & S_IXUGO)) {
1452e8e96157SMiklos Szeredi 			if (refreshed)
1453e5e5558eSMiklos Szeredi 				return -EACCES;
145431d40d74SMiklos Szeredi 
145510556cb2SAl Viro 			err = fuse_perm_getattr(inode, mask);
1456e8e96157SMiklos Szeredi 			if (!err && !(inode->i_mode & S_IXUGO))
1457e8e96157SMiklos Szeredi 				return -EACCES;
1458e8e96157SMiklos Szeredi 		}
1459e5e5558eSMiklos Szeredi 	}
1460244f6385SMiklos Szeredi 	return err;
1461e5e5558eSMiklos Szeredi }
1462e5e5558eSMiklos Szeredi 
14635571f1e6SDan Schatzberg static int fuse_readlink_page(struct inode *inode, struct page *page)
1464e5e5558eSMiklos Szeredi {
1465fcee216bSMax Reitz 	struct fuse_mount *fm = get_fuse_mount(inode);
14664c29afecSMiklos Szeredi 	struct fuse_page_desc desc = { .length = PAGE_SIZE - 1 };
14674c29afecSMiklos Szeredi 	struct fuse_args_pages ap = {
14684c29afecSMiklos Szeredi 		.num_pages = 1,
14694c29afecSMiklos Szeredi 		.pages = &page,
14704c29afecSMiklos Szeredi 		.descs = &desc,
14714c29afecSMiklos Szeredi 	};
14724c29afecSMiklos Szeredi 	char *link;
14734c29afecSMiklos Szeredi 	ssize_t res;
1474e5e5558eSMiklos Szeredi 
14754c29afecSMiklos Szeredi 	ap.args.opcode = FUSE_READLINK;
14764c29afecSMiklos Szeredi 	ap.args.nodeid = get_node_id(inode);
14774c29afecSMiklos Szeredi 	ap.args.out_pages = true;
14784c29afecSMiklos Szeredi 	ap.args.out_argvar = true;
14794c29afecSMiklos Szeredi 	ap.args.page_zeroing = true;
14804c29afecSMiklos Szeredi 	ap.args.out_numargs = 1;
14814c29afecSMiklos Szeredi 	ap.args.out_args[0].size = desc.length;
1482fcee216bSMax Reitz 	res = fuse_simple_request(fm, &ap.args);
14836b255391SAl Viro 
1484451418fcSAndrew Gallagher 	fuse_invalidate_atime(inode);
14855571f1e6SDan Schatzberg 
14864c29afecSMiklos Szeredi 	if (res < 0)
14874c29afecSMiklos Szeredi 		return res;
14884c29afecSMiklos Szeredi 
14894c29afecSMiklos Szeredi 	if (WARN_ON(res >= PAGE_SIZE))
14904c29afecSMiklos Szeredi 		return -EIO;
14914c29afecSMiklos Szeredi 
14924c29afecSMiklos Szeredi 	link = page_address(page);
14934c29afecSMiklos Szeredi 	link[res] = '\0';
14944c29afecSMiklos Szeredi 
14954c29afecSMiklos Szeredi 	return 0;
14965571f1e6SDan Schatzberg }
14975571f1e6SDan Schatzberg 
14985571f1e6SDan Schatzberg static const char *fuse_get_link(struct dentry *dentry, struct inode *inode,
14995571f1e6SDan Schatzberg 				 struct delayed_call *callback)
15005571f1e6SDan Schatzberg {
15015571f1e6SDan Schatzberg 	struct fuse_conn *fc = get_fuse_conn(inode);
15025571f1e6SDan Schatzberg 	struct page *page;
15035571f1e6SDan Schatzberg 	int err;
15045571f1e6SDan Schatzberg 
15055571f1e6SDan Schatzberg 	err = -EIO;
15065d069dbeSMiklos Szeredi 	if (fuse_is_bad(inode))
15075571f1e6SDan Schatzberg 		goto out_err;
15085571f1e6SDan Schatzberg 
15095571f1e6SDan Schatzberg 	if (fc->cache_symlinks)
15105571f1e6SDan Schatzberg 		return page_get_link(dentry, inode, callback);
15115571f1e6SDan Schatzberg 
15125571f1e6SDan Schatzberg 	err = -ECHILD;
15135571f1e6SDan Schatzberg 	if (!dentry)
15145571f1e6SDan Schatzberg 		goto out_err;
15155571f1e6SDan Schatzberg 
15165571f1e6SDan Schatzberg 	page = alloc_page(GFP_KERNEL);
15175571f1e6SDan Schatzberg 	err = -ENOMEM;
15185571f1e6SDan Schatzberg 	if (!page)
15195571f1e6SDan Schatzberg 		goto out_err;
15205571f1e6SDan Schatzberg 
15215571f1e6SDan Schatzberg 	err = fuse_readlink_page(inode, page);
15225571f1e6SDan Schatzberg 	if (err) {
15235571f1e6SDan Schatzberg 		__free_page(page);
15245571f1e6SDan Schatzberg 		goto out_err;
15255571f1e6SDan Schatzberg 	}
15265571f1e6SDan Schatzberg 
15275571f1e6SDan Schatzberg 	set_delayed_call(callback, page_put_link, page);
15285571f1e6SDan Schatzberg 
15295571f1e6SDan Schatzberg 	return page_address(page);
15305571f1e6SDan Schatzberg 
15315571f1e6SDan Schatzberg out_err:
15325571f1e6SDan Schatzberg 	return ERR_PTR(err);
1533e5e5558eSMiklos Szeredi }
1534e5e5558eSMiklos Szeredi 
1535e5e5558eSMiklos Szeredi static int fuse_dir_open(struct inode *inode, struct file *file)
1536e5e5558eSMiklos Szeredi {
153791fe96b4SMiklos Szeredi 	return fuse_open_common(inode, file, true);
1538e5e5558eSMiklos Szeredi }
1539e5e5558eSMiklos Szeredi 
1540e5e5558eSMiklos Szeredi static int fuse_dir_release(struct inode *inode, struct file *file)
1541e5e5558eSMiklos Szeredi {
15422e64ff15SChad Austin 	fuse_release_common(file, true);
15438b0797a4SMiklos Szeredi 
15448b0797a4SMiklos Szeredi 	return 0;
1545e5e5558eSMiklos Szeredi }
1546e5e5558eSMiklos Szeredi 
154702c24a82SJosef Bacik static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end,
154802c24a82SJosef Bacik 			  int datasync)
154982547981SMiklos Szeredi {
1550a9c2d1e8SMiklos Szeredi 	struct inode *inode = file->f_mapping->host;
1551a9c2d1e8SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1552a9c2d1e8SMiklos Szeredi 	int err;
1553a9c2d1e8SMiklos Szeredi 
15545d069dbeSMiklos Szeredi 	if (fuse_is_bad(inode))
1555a9c2d1e8SMiklos Szeredi 		return -EIO;
1556a9c2d1e8SMiklos Szeredi 
1557a9c2d1e8SMiklos Szeredi 	if (fc->no_fsyncdir)
1558a9c2d1e8SMiklos Szeredi 		return 0;
1559a9c2d1e8SMiklos Szeredi 
1560a9c2d1e8SMiklos Szeredi 	inode_lock(inode);
1561a9c2d1e8SMiklos Szeredi 	err = fuse_fsync_common(file, start, end, datasync, FUSE_FSYNCDIR);
1562a9c2d1e8SMiklos Szeredi 	if (err == -ENOSYS) {
1563a9c2d1e8SMiklos Szeredi 		fc->no_fsyncdir = 1;
1564a9c2d1e8SMiklos Szeredi 		err = 0;
1565a9c2d1e8SMiklos Szeredi 	}
1566a9c2d1e8SMiklos Szeredi 	inode_unlock(inode);
1567a9c2d1e8SMiklos Szeredi 
1568a9c2d1e8SMiklos Szeredi 	return err;
156982547981SMiklos Szeredi }
157082547981SMiklos Szeredi 
1571b18da0c5SMiklos Szeredi static long fuse_dir_ioctl(struct file *file, unsigned int cmd,
1572b18da0c5SMiklos Szeredi 			    unsigned long arg)
1573b18da0c5SMiklos Szeredi {
1574b18da0c5SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1575b18da0c5SMiklos Szeredi 
1576b18da0c5SMiklos Szeredi 	/* FUSE_IOCTL_DIR only supported for API version >= 7.18 */
1577b18da0c5SMiklos Szeredi 	if (fc->minor < 18)
1578b18da0c5SMiklos Szeredi 		return -ENOTTY;
1579b18da0c5SMiklos Szeredi 
1580b18da0c5SMiklos Szeredi 	return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR);
1581b18da0c5SMiklos Szeredi }
1582b18da0c5SMiklos Szeredi 
1583b18da0c5SMiklos Szeredi static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd,
1584b18da0c5SMiklos Szeredi 				   unsigned long arg)
1585b18da0c5SMiklos Szeredi {
1586b18da0c5SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1587b18da0c5SMiklos Szeredi 
1588b18da0c5SMiklos Szeredi 	if (fc->minor < 18)
1589b18da0c5SMiklos Szeredi 		return -ENOTTY;
1590b18da0c5SMiklos Szeredi 
1591b18da0c5SMiklos Szeredi 	return fuse_ioctl_common(file, cmd, arg,
1592b18da0c5SMiklos Szeredi 				 FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR);
1593b18da0c5SMiklos Szeredi }
1594b18da0c5SMiklos Szeredi 
1595b0aa7606SMaxim Patlasov static bool update_mtime(unsigned ivalid, bool trust_local_mtime)
159617637cbaSMiklos Szeredi {
159717637cbaSMiklos Szeredi 	/* Always update if mtime is explicitly set  */
159817637cbaSMiklos Szeredi 	if (ivalid & ATTR_MTIME_SET)
159917637cbaSMiklos Szeredi 		return true;
160017637cbaSMiklos Szeredi 
1601b0aa7606SMaxim Patlasov 	/* Or if kernel i_mtime is the official one */
1602b0aa7606SMaxim Patlasov 	if (trust_local_mtime)
1603b0aa7606SMaxim Patlasov 		return true;
1604b0aa7606SMaxim Patlasov 
160517637cbaSMiklos Szeredi 	/* If it's an open(O_TRUNC) or an ftruncate(), don't update */
160617637cbaSMiklos Szeredi 	if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
160717637cbaSMiklos Szeredi 		return false;
160817637cbaSMiklos Szeredi 
160917637cbaSMiklos Szeredi 	/* In all other cases update */
161017637cbaSMiklos Szeredi 	return true;
161117637cbaSMiklos Szeredi }
161217637cbaSMiklos Szeredi 
16138cb08329SEric W. Biederman static void iattr_to_fattr(struct fuse_conn *fc, struct iattr *iattr,
16148cb08329SEric W. Biederman 			   struct fuse_setattr_in *arg, bool trust_local_cmtime)
16159e6268dbSMiklos Szeredi {
16169e6268dbSMiklos Szeredi 	unsigned ivalid = iattr->ia_valid;
16179e6268dbSMiklos Szeredi 
16189e6268dbSMiklos Szeredi 	if (ivalid & ATTR_MODE)
1619befc649cSMiklos Szeredi 		arg->valid |= FATTR_MODE,   arg->mode = iattr->ia_mode;
16209e6268dbSMiklos Szeredi 	if (ivalid & ATTR_UID)
16218cb08329SEric W. Biederman 		arg->valid |= FATTR_UID,    arg->uid = from_kuid(fc->user_ns, iattr->ia_uid);
16229e6268dbSMiklos Szeredi 	if (ivalid & ATTR_GID)
16238cb08329SEric W. Biederman 		arg->valid |= FATTR_GID,    arg->gid = from_kgid(fc->user_ns, iattr->ia_gid);
16249e6268dbSMiklos Szeredi 	if (ivalid & ATTR_SIZE)
1625befc649cSMiklos Szeredi 		arg->valid |= FATTR_SIZE,   arg->size = iattr->ia_size;
162617637cbaSMiklos Szeredi 	if (ivalid & ATTR_ATIME) {
162717637cbaSMiklos Szeredi 		arg->valid |= FATTR_ATIME;
1628befc649cSMiklos Szeredi 		arg->atime = iattr->ia_atime.tv_sec;
162917637cbaSMiklos Szeredi 		arg->atimensec = iattr->ia_atime.tv_nsec;
163017637cbaSMiklos Szeredi 		if (!(ivalid & ATTR_ATIME_SET))
163117637cbaSMiklos Szeredi 			arg->valid |= FATTR_ATIME_NOW;
163217637cbaSMiklos Szeredi 	}
16333ad22c62SMaxim Patlasov 	if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, trust_local_cmtime)) {
163417637cbaSMiklos Szeredi 		arg->valid |= FATTR_MTIME;
1635befc649cSMiklos Szeredi 		arg->mtime = iattr->ia_mtime.tv_sec;
163617637cbaSMiklos Szeredi 		arg->mtimensec = iattr->ia_mtime.tv_nsec;
16373ad22c62SMaxim Patlasov 		if (!(ivalid & ATTR_MTIME_SET) && !trust_local_cmtime)
163817637cbaSMiklos Szeredi 			arg->valid |= FATTR_MTIME_NOW;
16399e6268dbSMiklos Szeredi 	}
16403ad22c62SMaxim Patlasov 	if ((ivalid & ATTR_CTIME) && trust_local_cmtime) {
16413ad22c62SMaxim Patlasov 		arg->valid |= FATTR_CTIME;
16423ad22c62SMaxim Patlasov 		arg->ctime = iattr->ia_ctime.tv_sec;
16433ad22c62SMaxim Patlasov 		arg->ctimensec = iattr->ia_ctime.tv_nsec;
16443ad22c62SMaxim Patlasov 	}
16459e6268dbSMiklos Szeredi }
16469e6268dbSMiklos Szeredi 
16476f9f1180SMiklos Szeredi /*
16483be5a52bSMiklos Szeredi  * Prevent concurrent writepages on inode
16493be5a52bSMiklos Szeredi  *
16503be5a52bSMiklos Szeredi  * This is done by adding a negative bias to the inode write counter
16513be5a52bSMiklos Szeredi  * and waiting for all pending writes to finish.
16523be5a52bSMiklos Szeredi  */
16533be5a52bSMiklos Szeredi void fuse_set_nowrite(struct inode *inode)
16543be5a52bSMiklos Szeredi {
16553be5a52bSMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
16563be5a52bSMiklos Szeredi 
16575955102cSAl Viro 	BUG_ON(!inode_is_locked(inode));
16583be5a52bSMiklos Szeredi 
1659f15ecfefSKirill Tkhai 	spin_lock(&fi->lock);
16603be5a52bSMiklos Szeredi 	BUG_ON(fi->writectr < 0);
16613be5a52bSMiklos Szeredi 	fi->writectr += FUSE_NOWRITE;
1662f15ecfefSKirill Tkhai 	spin_unlock(&fi->lock);
16633be5a52bSMiklos Szeredi 	wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE);
16643be5a52bSMiklos Szeredi }
16653be5a52bSMiklos Szeredi 
16663be5a52bSMiklos Szeredi /*
16673be5a52bSMiklos Szeredi  * Allow writepages on inode
16683be5a52bSMiklos Szeredi  *
16693be5a52bSMiklos Szeredi  * Remove the bias from the writecounter and send any queued
16703be5a52bSMiklos Szeredi  * writepages.
16713be5a52bSMiklos Szeredi  */
16723be5a52bSMiklos Szeredi static void __fuse_release_nowrite(struct inode *inode)
16733be5a52bSMiklos Szeredi {
16743be5a52bSMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
16753be5a52bSMiklos Szeredi 
16763be5a52bSMiklos Szeredi 	BUG_ON(fi->writectr != FUSE_NOWRITE);
16773be5a52bSMiklos Szeredi 	fi->writectr = 0;
16783be5a52bSMiklos Szeredi 	fuse_flush_writepages(inode);
16793be5a52bSMiklos Szeredi }
16803be5a52bSMiklos Szeredi 
16813be5a52bSMiklos Szeredi void fuse_release_nowrite(struct inode *inode)
16823be5a52bSMiklos Szeredi {
1683f15ecfefSKirill Tkhai 	struct fuse_inode *fi = get_fuse_inode(inode);
16843be5a52bSMiklos Szeredi 
1685f15ecfefSKirill Tkhai 	spin_lock(&fi->lock);
16863be5a52bSMiklos Szeredi 	__fuse_release_nowrite(inode);
1687f15ecfefSKirill Tkhai 	spin_unlock(&fi->lock);
16883be5a52bSMiklos Szeredi }
16893be5a52bSMiklos Szeredi 
16907078187aSMiklos Szeredi static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_args *args,
1691b0aa7606SMaxim Patlasov 			      struct inode *inode,
1692b0aa7606SMaxim Patlasov 			      struct fuse_setattr_in *inarg_p,
1693b0aa7606SMaxim Patlasov 			      struct fuse_attr_out *outarg_p)
1694b0aa7606SMaxim Patlasov {
1695d5b48543SMiklos Szeredi 	args->opcode = FUSE_SETATTR;
1696d5b48543SMiklos Szeredi 	args->nodeid = get_node_id(inode);
1697d5b48543SMiklos Szeredi 	args->in_numargs = 1;
1698d5b48543SMiklos Szeredi 	args->in_args[0].size = sizeof(*inarg_p);
1699d5b48543SMiklos Szeredi 	args->in_args[0].value = inarg_p;
1700d5b48543SMiklos Szeredi 	args->out_numargs = 1;
1701d5b48543SMiklos Szeredi 	args->out_args[0].size = sizeof(*outarg_p);
1702d5b48543SMiklos Szeredi 	args->out_args[0].value = outarg_p;
1703b0aa7606SMaxim Patlasov }
1704b0aa7606SMaxim Patlasov 
1705b0aa7606SMaxim Patlasov /*
1706b0aa7606SMaxim Patlasov  * Flush inode->i_mtime to the server
1707b0aa7606SMaxim Patlasov  */
1708ab9e13f7SMaxim Patlasov int fuse_flush_times(struct inode *inode, struct fuse_file *ff)
1709b0aa7606SMaxim Patlasov {
1710fcee216bSMax Reitz 	struct fuse_mount *fm = get_fuse_mount(inode);
17117078187aSMiklos Szeredi 	FUSE_ARGS(args);
1712b0aa7606SMaxim Patlasov 	struct fuse_setattr_in inarg;
1713b0aa7606SMaxim Patlasov 	struct fuse_attr_out outarg;
1714b0aa7606SMaxim Patlasov 
1715b0aa7606SMaxim Patlasov 	memset(&inarg, 0, sizeof(inarg));
1716b0aa7606SMaxim Patlasov 	memset(&outarg, 0, sizeof(outarg));
1717b0aa7606SMaxim Patlasov 
1718ab9e13f7SMaxim Patlasov 	inarg.valid = FATTR_MTIME;
1719b0aa7606SMaxim Patlasov 	inarg.mtime = inode->i_mtime.tv_sec;
1720b0aa7606SMaxim Patlasov 	inarg.mtimensec = inode->i_mtime.tv_nsec;
1721fcee216bSMax Reitz 	if (fm->fc->minor >= 23) {
1722ab9e13f7SMaxim Patlasov 		inarg.valid |= FATTR_CTIME;
1723ab9e13f7SMaxim Patlasov 		inarg.ctime = inode->i_ctime.tv_sec;
1724ab9e13f7SMaxim Patlasov 		inarg.ctimensec = inode->i_ctime.tv_nsec;
1725ab9e13f7SMaxim Patlasov 	}
17261e18bda8SMiklos Szeredi 	if (ff) {
17271e18bda8SMiklos Szeredi 		inarg.valid |= FATTR_FH;
17281e18bda8SMiklos Szeredi 		inarg.fh = ff->fh;
17291e18bda8SMiklos Szeredi 	}
1730fcee216bSMax Reitz 	fuse_setattr_fill(fm->fc, &args, inode, &inarg, &outarg);
1731b0aa7606SMaxim Patlasov 
1732fcee216bSMax Reitz 	return fuse_simple_request(fm, &args);
1733b0aa7606SMaxim Patlasov }
1734b0aa7606SMaxim Patlasov 
17353be5a52bSMiklos Szeredi /*
17366f9f1180SMiklos Szeredi  * Set attributes, and at the same time refresh them.
17376f9f1180SMiklos Szeredi  *
17386f9f1180SMiklos Szeredi  * Truncation is slightly complicated, because the 'truncate' request
17396f9f1180SMiklos Szeredi  * may fail, in which case we don't want to touch the mapping.
17409ffbb916SMiklos Szeredi  * vmtruncate() doesn't allow for this case, so do the rlimit checking
17419ffbb916SMiklos Szeredi  * and the actual truncation by hand.
17426f9f1180SMiklos Szeredi  */
174362490330SJan Kara int fuse_do_setattr(struct dentry *dentry, struct iattr *attr,
174449d4914fSMiklos Szeredi 		    struct file *file)
17459e6268dbSMiklos Szeredi {
174662490330SJan Kara 	struct inode *inode = d_inode(dentry);
1747fcee216bSMax Reitz 	struct fuse_mount *fm = get_fuse_mount(inode);
1748fcee216bSMax Reitz 	struct fuse_conn *fc = fm->fc;
174906a7c3c2SMaxim Patlasov 	struct fuse_inode *fi = get_fuse_inode(inode);
17508bcbbe9cSJan Kara 	struct address_space *mapping = inode->i_mapping;
17517078187aSMiklos Szeredi 	FUSE_ARGS(args);
17529e6268dbSMiklos Szeredi 	struct fuse_setattr_in inarg;
17539e6268dbSMiklos Szeredi 	struct fuse_attr_out outarg;
17543be5a52bSMiklos Szeredi 	bool is_truncate = false;
1755c15016b7SMiklos Szeredi 	bool is_wb = fc->writeback_cache && S_ISREG(inode->i_mode);
17563be5a52bSMiklos Szeredi 	loff_t oldsize;
17579e6268dbSMiklos Szeredi 	int err;
1758c15016b7SMiklos Szeredi 	bool trust_local_cmtime = is_wb;
17596ae330caSVivek Goyal 	bool fault_blocked = false;
17609e6268dbSMiklos Szeredi 
176129433a29SMiklos Szeredi 	if (!fc->default_permissions)
1762db78b877SChristoph Hellwig 		attr->ia_valid |= ATTR_FORCE;
1763db78b877SChristoph Hellwig 
1764c1632a0fSChristian Brauner 	err = setattr_prepare(&nop_mnt_idmap, dentry, attr);
17651e9a4ed9SMiklos Szeredi 	if (err)
17661e9a4ed9SMiklos Szeredi 		return err;
17671e9a4ed9SMiklos Szeredi 
17686ae330caSVivek Goyal 	if (attr->ia_valid & ATTR_SIZE) {
17696ae330caSVivek Goyal 		if (WARN_ON(!S_ISREG(inode->i_mode)))
17706ae330caSVivek Goyal 			return -EIO;
17716ae330caSVivek Goyal 		is_truncate = true;
17726ae330caSVivek Goyal 	}
17736ae330caSVivek Goyal 
17746ae330caSVivek Goyal 	if (FUSE_IS_DAX(inode) && is_truncate) {
17758bcbbe9cSJan Kara 		filemap_invalidate_lock(mapping);
17766ae330caSVivek Goyal 		fault_blocked = true;
17776ae330caSVivek Goyal 		err = fuse_dax_break_layouts(inode, 0, 0);
17786ae330caSVivek Goyal 		if (err) {
17798bcbbe9cSJan Kara 			filemap_invalidate_unlock(mapping);
17806ae330caSVivek Goyal 			return err;
17816ae330caSVivek Goyal 		}
17826ae330caSVivek Goyal 	}
17836ae330caSVivek Goyal 
17848d56adddSMiklos Szeredi 	if (attr->ia_valid & ATTR_OPEN) {
1785df0e91d4SMiklos Szeredi 		/* This is coming from open(..., ... | O_TRUNC); */
1786df0e91d4SMiklos Szeredi 		WARN_ON(!(attr->ia_valid & ATTR_SIZE));
1787df0e91d4SMiklos Szeredi 		WARN_ON(attr->ia_size != 0);
1788df0e91d4SMiklos Szeredi 		if (fc->atomic_o_trunc) {
1789df0e91d4SMiklos Szeredi 			/*
1790df0e91d4SMiklos Szeredi 			 * No need to send request to userspace, since actual
1791df0e91d4SMiklos Szeredi 			 * truncation has already been done by OPEN.  But still
1792df0e91d4SMiklos Szeredi 			 * need to truncate page cache.
1793df0e91d4SMiklos Szeredi 			 */
1794df0e91d4SMiklos Szeredi 			i_size_write(inode, 0);
1795df0e91d4SMiklos Szeredi 			truncate_pagecache(inode, 0);
17966ae330caSVivek Goyal 			goto out;
1797df0e91d4SMiklos Szeredi 		}
17988d56adddSMiklos Szeredi 		file = NULL;
17998d56adddSMiklos Szeredi 	}
18006ff958edSMiklos Szeredi 
1801b24e7598SMiklos Szeredi 	/* Flush dirty data/metadata before non-truncate SETATTR */
1802c15016b7SMiklos Szeredi 	if (is_wb &&
1803b24e7598SMiklos Szeredi 	    attr->ia_valid &
1804b24e7598SMiklos Szeredi 			(ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_MTIME_SET |
1805b24e7598SMiklos Szeredi 			 ATTR_TIMES_SET)) {
1806b24e7598SMiklos Szeredi 		err = write_inode_now(inode, true);
1807b24e7598SMiklos Szeredi 		if (err)
1808b24e7598SMiklos Szeredi 			return err;
1809b24e7598SMiklos Szeredi 
1810b24e7598SMiklos Szeredi 		fuse_set_nowrite(inode);
1811b24e7598SMiklos Szeredi 		fuse_release_nowrite(inode);
1812b24e7598SMiklos Szeredi 	}
1813b24e7598SMiklos Szeredi 
181406a7c3c2SMaxim Patlasov 	if (is_truncate) {
18153be5a52bSMiklos Szeredi 		fuse_set_nowrite(inode);
181606a7c3c2SMaxim Patlasov 		set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
18173ad22c62SMaxim Patlasov 		if (trust_local_cmtime && attr->ia_size != inode->i_size)
18183ad22c62SMaxim Patlasov 			attr->ia_valid |= ATTR_MTIME | ATTR_CTIME;
181906a7c3c2SMaxim Patlasov 	}
18203be5a52bSMiklos Szeredi 
18219e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
18220e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
18238cb08329SEric W. Biederman 	iattr_to_fattr(fc, attr, &inarg, trust_local_cmtime);
182449d4914fSMiklos Szeredi 	if (file) {
182549d4914fSMiklos Szeredi 		struct fuse_file *ff = file->private_data;
182649d4914fSMiklos Szeredi 		inarg.valid |= FATTR_FH;
182749d4914fSMiklos Szeredi 		inarg.fh = ff->fh;
182849d4914fSMiklos Szeredi 	}
182931792161SVivek Goyal 
183031792161SVivek Goyal 	/* Kill suid/sgid for non-directory chown unconditionally */
183131792161SVivek Goyal 	if (fc->handle_killpriv_v2 && !S_ISDIR(inode->i_mode) &&
183231792161SVivek Goyal 	    attr->ia_valid & (ATTR_UID | ATTR_GID))
183331792161SVivek Goyal 		inarg.valid |= FATTR_KILL_SUIDGID;
183431792161SVivek Goyal 
1835f3332114SMiklos Szeredi 	if (attr->ia_valid & ATTR_SIZE) {
1836f3332114SMiklos Szeredi 		/* For mandatory locking in truncate */
1837f3332114SMiklos Szeredi 		inarg.valid |= FATTR_LOCKOWNER;
1838f3332114SMiklos Szeredi 		inarg.lock_owner = fuse_lock_owner_id(fc, current->files);
183931792161SVivek Goyal 
184031792161SVivek Goyal 		/* Kill suid/sgid for truncate only if no CAP_FSETID */
184131792161SVivek Goyal 		if (fc->handle_killpriv_v2 && !capable(CAP_FSETID))
184231792161SVivek Goyal 			inarg.valid |= FATTR_KILL_SUIDGID;
1843f3332114SMiklos Szeredi 	}
18447078187aSMiklos Szeredi 	fuse_setattr_fill(fc, &args, inode, &inarg, &outarg);
1845fcee216bSMax Reitz 	err = fuse_simple_request(fm, &args);
1846e00d2c2dSMiklos Szeredi 	if (err) {
1847e00d2c2dSMiklos Szeredi 		if (err == -EINTR)
1848e00d2c2dSMiklos Szeredi 			fuse_invalidate_attr(inode);
18493be5a52bSMiklos Szeredi 		goto error;
1850e00d2c2dSMiklos Szeredi 	}
1851e00d2c2dSMiklos Szeredi 
1852eb59bd17SMiklos Szeredi 	if (fuse_invalid_attr(&outarg.attr) ||
18536e3e2c43SAl Viro 	    inode_wrong_type(inode, outarg.attr.mode)) {
18545d069dbeSMiklos Szeredi 		fuse_make_bad(inode);
18553be5a52bSMiklos Szeredi 		err = -EIO;
18563be5a52bSMiklos Szeredi 		goto error;
18579e6268dbSMiklos Szeredi 	}
18589e6268dbSMiklos Szeredi 
1859f15ecfefSKirill Tkhai 	spin_lock(&fi->lock);
1860b0aa7606SMaxim Patlasov 	/* the kernel maintains i_mtime locally */
18613ad22c62SMaxim Patlasov 	if (trust_local_cmtime) {
18623ad22c62SMaxim Patlasov 		if (attr->ia_valid & ATTR_MTIME)
1863b0aa7606SMaxim Patlasov 			inode->i_mtime = attr->ia_mtime;
18643ad22c62SMaxim Patlasov 		if (attr->ia_valid & ATTR_CTIME)
18653ad22c62SMaxim Patlasov 			inode->i_ctime = attr->ia_ctime;
18661e18bda8SMiklos Szeredi 		/* FIXME: clear I_DIRTY_SYNC? */
1867b0aa7606SMaxim Patlasov 	}
1868b0aa7606SMaxim Patlasov 
18693be5a52bSMiklos Szeredi 	fuse_change_attributes_common(inode, &outarg.attr,
18704b52f059SMiklos Szeredi 				      attr_timeout(&outarg),
18714b52f059SMiklos Szeredi 				      fuse_get_cache_mask(inode));
18723be5a52bSMiklos Szeredi 	oldsize = inode->i_size;
18738373200bSPavel Emelyanov 	/* see the comment in fuse_change_attributes() */
1874c15016b7SMiklos Szeredi 	if (!is_wb || is_truncate)
18753be5a52bSMiklos Szeredi 		i_size_write(inode, outarg.attr.size);
18763be5a52bSMiklos Szeredi 
18773be5a52bSMiklos Szeredi 	if (is_truncate) {
1878f15ecfefSKirill Tkhai 		/* NOTE: this may release/reacquire fi->lock */
18793be5a52bSMiklos Szeredi 		__fuse_release_nowrite(inode);
18803be5a52bSMiklos Szeredi 	}
1881f15ecfefSKirill Tkhai 	spin_unlock(&fi->lock);
18823be5a52bSMiklos Szeredi 
18833be5a52bSMiklos Szeredi 	/*
18843be5a52bSMiklos Szeredi 	 * Only call invalidate_inode_pages2() after removing
18852bf06b8eSMatthew Wilcox (Oracle) 	 * FUSE_NOWRITE, otherwise fuse_launder_folio() would deadlock.
18863be5a52bSMiklos Szeredi 	 */
18878373200bSPavel Emelyanov 	if ((is_truncate || !is_wb) &&
18888373200bSPavel Emelyanov 	    S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
18897caef267SKirill A. Shutemov 		truncate_pagecache(inode, outarg.attr.size);
18908bcbbe9cSJan Kara 		invalidate_inode_pages2(mapping);
18913be5a52bSMiklos Szeredi 	}
18923be5a52bSMiklos Szeredi 
189306a7c3c2SMaxim Patlasov 	clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
18946ae330caSVivek Goyal out:
18956ae330caSVivek Goyal 	if (fault_blocked)
18968bcbbe9cSJan Kara 		filemap_invalidate_unlock(mapping);
18976ae330caSVivek Goyal 
1898e00d2c2dSMiklos Szeredi 	return 0;
18993be5a52bSMiklos Szeredi 
19003be5a52bSMiklos Szeredi error:
19013be5a52bSMiklos Szeredi 	if (is_truncate)
19023be5a52bSMiklos Szeredi 		fuse_release_nowrite(inode);
19033be5a52bSMiklos Szeredi 
190406a7c3c2SMaxim Patlasov 	clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
19056ae330caSVivek Goyal 
19066ae330caSVivek Goyal 	if (fault_blocked)
19078bcbbe9cSJan Kara 		filemap_invalidate_unlock(mapping);
19083be5a52bSMiklos Szeredi 	return err;
19099e6268dbSMiklos Szeredi }
19109e6268dbSMiklos Szeredi 
1911c1632a0fSChristian Brauner static int fuse_setattr(struct mnt_idmap *idmap, struct dentry *entry,
1912549c7297SChristian Brauner 			struct iattr *attr)
191349d4914fSMiklos Szeredi {
19142b0143b5SDavid Howells 	struct inode *inode = d_inode(entry);
19155e940c1dSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1916a09f99edSMiklos Szeredi 	struct file *file = (attr->ia_valid & ATTR_FILE) ? attr->ia_file : NULL;
19175e2b8828SMiklos Szeredi 	int ret;
1918efb9fa9eSMaxim Patlasov 
19195d069dbeSMiklos Szeredi 	if (fuse_is_bad(inode))
19205d069dbeSMiklos Szeredi 		return -EIO;
19215d069dbeSMiklos Szeredi 
1922efb9fa9eSMaxim Patlasov 	if (!fuse_allow_current_process(get_fuse_conn(inode)))
1923efb9fa9eSMaxim Patlasov 		return -EACCES;
1924efb9fa9eSMaxim Patlasov 
1925a09f99edSMiklos Szeredi 	if (attr->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) {
1926a09f99edSMiklos Szeredi 		attr->ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID |
1927a09f99edSMiklos Szeredi 				    ATTR_MODE);
19285e940c1dSMiklos Szeredi 
1929a09f99edSMiklos Szeredi 		/*
19305e940c1dSMiklos Szeredi 		 * The only sane way to reliably kill suid/sgid is to do it in
19315e940c1dSMiklos Szeredi 		 * the userspace filesystem
19325e940c1dSMiklos Szeredi 		 *
19335e940c1dSMiklos Szeredi 		 * This should be done on write(), truncate() and chown().
19345e940c1dSMiklos Szeredi 		 */
19358981bdfdSVivek Goyal 		if (!fc->handle_killpriv && !fc->handle_killpriv_v2) {
19365e940c1dSMiklos Szeredi 			/*
19375e940c1dSMiklos Szeredi 			 * ia_mode calculation may have used stale i_mode.
19385e940c1dSMiklos Szeredi 			 * Refresh and recalculate.
1939a09f99edSMiklos Szeredi 			 */
1940a09f99edSMiklos Szeredi 			ret = fuse_do_getattr(inode, NULL, file);
1941a09f99edSMiklos Szeredi 			if (ret)
1942a09f99edSMiklos Szeredi 				return ret;
1943a09f99edSMiklos Szeredi 
1944a09f99edSMiklos Szeredi 			attr->ia_mode = inode->i_mode;
1945c01638f5SMiklos Szeredi 			if (inode->i_mode & S_ISUID) {
1946a09f99edSMiklos Szeredi 				attr->ia_valid |= ATTR_MODE;
1947a09f99edSMiklos Szeredi 				attr->ia_mode &= ~S_ISUID;
1948a09f99edSMiklos Szeredi 			}
1949c01638f5SMiklos Szeredi 			if ((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
1950a09f99edSMiklos Szeredi 				attr->ia_valid |= ATTR_MODE;
1951a09f99edSMiklos Szeredi 				attr->ia_mode &= ~S_ISGID;
1952a09f99edSMiklos Szeredi 			}
1953a09f99edSMiklos Szeredi 		}
19545e940c1dSMiklos Szeredi 	}
1955a09f99edSMiklos Szeredi 	if (!attr->ia_valid)
1956a09f99edSMiklos Szeredi 		return 0;
1957a09f99edSMiklos Szeredi 
1958abb5a14fSLinus Torvalds 	ret = fuse_do_setattr(entry, attr, file);
19595e2b8828SMiklos Szeredi 	if (!ret) {
196060bcc88aSSeth Forshee 		/*
196160bcc88aSSeth Forshee 		 * If filesystem supports acls it may have updated acl xattrs in
196260bcc88aSSeth Forshee 		 * the filesystem, so forget cached acls for the inode.
196360bcc88aSSeth Forshee 		 */
196460bcc88aSSeth Forshee 		if (fc->posix_acl)
196560bcc88aSSeth Forshee 			forget_all_cached_acls(inode);
196660bcc88aSSeth Forshee 
19675e2b8828SMiklos Szeredi 		/* Directory mode changed, may need to revalidate access */
19685e2b8828SMiklos Szeredi 		if (d_is_dir(entry) && (attr->ia_valid & ATTR_MODE))
19695e2b8828SMiklos Szeredi 			fuse_invalidate_entry_cache(entry);
19705e2b8828SMiklos Szeredi 	}
19715e2b8828SMiklos Szeredi 	return ret;
197249d4914fSMiklos Szeredi }
197349d4914fSMiklos Szeredi 
1974b74d24f7SChristian Brauner static int fuse_getattr(struct mnt_idmap *idmap,
1975549c7297SChristian Brauner 			const struct path *path, struct kstat *stat,
1976a528d35eSDavid Howells 			u32 request_mask, unsigned int flags)
1977e5e5558eSMiklos Szeredi {
1978a528d35eSDavid Howells 	struct inode *inode = d_inode(path->dentry);
1979244f6385SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1980244f6385SMiklos Szeredi 
19815d069dbeSMiklos Szeredi 	if (fuse_is_bad(inode))
19825d069dbeSMiklos Szeredi 		return -EIO;
19835d069dbeSMiklos Szeredi 
19845157da2cSMiklos Szeredi 	if (!fuse_allow_current_process(fc)) {
19855157da2cSMiklos Szeredi 		if (!request_mask) {
19865157da2cSMiklos Szeredi 			/*
19875157da2cSMiklos Szeredi 			 * If user explicitly requested *nothing* then don't
19885157da2cSMiklos Szeredi 			 * error out, but return st_dev only.
19895157da2cSMiklos Szeredi 			 */
19905157da2cSMiklos Szeredi 			stat->result_mask = 0;
19915157da2cSMiklos Szeredi 			stat->dev = inode->i_sb->s_dev;
19925157da2cSMiklos Szeredi 			return 0;
19935157da2cSMiklos Szeredi 		}
1994244f6385SMiklos Szeredi 		return -EACCES;
19955157da2cSMiklos Szeredi 	}
1996244f6385SMiklos Szeredi 
19972f1e8196SMiklos Szeredi 	return fuse_update_get_attr(inode, NULL, stat, request_mask, flags);
1998e5e5558eSMiklos Szeredi }
1999e5e5558eSMiklos Szeredi 
2000754661f1SArjan van de Ven static const struct inode_operations fuse_dir_inode_operations = {
2001e5e5558eSMiklos Szeredi 	.lookup		= fuse_lookup,
20029e6268dbSMiklos Szeredi 	.mkdir		= fuse_mkdir,
20039e6268dbSMiklos Szeredi 	.symlink	= fuse_symlink,
20049e6268dbSMiklos Szeredi 	.unlink		= fuse_unlink,
20059e6268dbSMiklos Szeredi 	.rmdir		= fuse_rmdir,
20062773bf00SMiklos Szeredi 	.rename		= fuse_rename2,
20079e6268dbSMiklos Szeredi 	.link		= fuse_link,
20089e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
20099e6268dbSMiklos Szeredi 	.create		= fuse_create,
2010c8ccbe03SMiklos Szeredi 	.atomic_open	= fuse_atomic_open,
20117d375390SMiklos Szeredi 	.tmpfile	= fuse_tmpfile,
20129e6268dbSMiklos Szeredi 	.mknod		= fuse_mknod,
2013e5e5558eSMiklos Szeredi 	.permission	= fuse_permission,
2014e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
201592a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
2016facd6105SChristian Brauner 	.get_inode_acl	= fuse_get_inode_acl,
2017facd6105SChristian Brauner 	.get_acl	= fuse_get_acl,
201860bcc88aSSeth Forshee 	.set_acl	= fuse_set_acl,
201972227eacSMiklos Szeredi 	.fileattr_get	= fuse_fileattr_get,
202072227eacSMiklos Szeredi 	.fileattr_set	= fuse_fileattr_set,
2021e5e5558eSMiklos Szeredi };
2022e5e5558eSMiklos Szeredi 
20234b6f5d20SArjan van de Ven static const struct file_operations fuse_dir_operations = {
2024b6aeadedSMiklos Szeredi 	.llseek		= generic_file_llseek,
2025e5e5558eSMiklos Szeredi 	.read		= generic_read_dir,
2026d9b3dbdcSAl Viro 	.iterate_shared	= fuse_readdir,
2027e5e5558eSMiklos Szeredi 	.open		= fuse_dir_open,
2028e5e5558eSMiklos Szeredi 	.release	= fuse_dir_release,
202982547981SMiklos Szeredi 	.fsync		= fuse_dir_fsync,
2030b18da0c5SMiklos Szeredi 	.unlocked_ioctl	= fuse_dir_ioctl,
2031b18da0c5SMiklos Szeredi 	.compat_ioctl	= fuse_dir_compat_ioctl,
2032e5e5558eSMiklos Szeredi };
2033e5e5558eSMiklos Szeredi 
2034754661f1SArjan van de Ven static const struct inode_operations fuse_common_inode_operations = {
20359e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
2036e5e5558eSMiklos Szeredi 	.permission	= fuse_permission,
2037e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
203892a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
2039facd6105SChristian Brauner 	.get_inode_acl	= fuse_get_inode_acl,
2040facd6105SChristian Brauner 	.get_acl	= fuse_get_acl,
204160bcc88aSSeth Forshee 	.set_acl	= fuse_set_acl,
204272227eacSMiklos Szeredi 	.fileattr_get	= fuse_fileattr_get,
204372227eacSMiklos Szeredi 	.fileattr_set	= fuse_fileattr_set,
2044e5e5558eSMiklos Szeredi };
2045e5e5558eSMiklos Szeredi 
2046754661f1SArjan van de Ven static const struct inode_operations fuse_symlink_inode_operations = {
20479e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
20486b255391SAl Viro 	.get_link	= fuse_get_link,
2049e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
205092a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
2051e5e5558eSMiklos Szeredi };
2052e5e5558eSMiklos Szeredi 
2053e5e5558eSMiklos Szeredi void fuse_init_common(struct inode *inode)
2054e5e5558eSMiklos Szeredi {
2055e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_common_inode_operations;
2056e5e5558eSMiklos Szeredi }
2057e5e5558eSMiklos Szeredi 
2058e5e5558eSMiklos Szeredi void fuse_init_dir(struct inode *inode)
2059e5e5558eSMiklos Szeredi {
2060ab2257e9SMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
2061ab2257e9SMiklos Szeredi 
2062e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_dir_inode_operations;
2063e5e5558eSMiklos Szeredi 	inode->i_fop = &fuse_dir_operations;
2064ab2257e9SMiklos Szeredi 
2065ab2257e9SMiklos Szeredi 	spin_lock_init(&fi->rdc.lock);
2066ab2257e9SMiklos Szeredi 	fi->rdc.cached = false;
2067ab2257e9SMiklos Szeredi 	fi->rdc.size = 0;
2068ab2257e9SMiklos Szeredi 	fi->rdc.pos = 0;
2069ab2257e9SMiklos Szeredi 	fi->rdc.version = 0;
2070e5e5558eSMiklos Szeredi }
2071e5e5558eSMiklos Szeredi 
20725efd00e4SMatthew Wilcox (Oracle) static int fuse_symlink_read_folio(struct file *null, struct folio *folio)
20735571f1e6SDan Schatzberg {
20745efd00e4SMatthew Wilcox (Oracle) 	int err = fuse_readlink_page(folio->mapping->host, &folio->page);
20755571f1e6SDan Schatzberg 
20765571f1e6SDan Schatzberg 	if (!err)
20775efd00e4SMatthew Wilcox (Oracle) 		folio_mark_uptodate(folio);
20785571f1e6SDan Schatzberg 
20795efd00e4SMatthew Wilcox (Oracle) 	folio_unlock(folio);
20805571f1e6SDan Schatzberg 
20815571f1e6SDan Schatzberg 	return err;
20825571f1e6SDan Schatzberg }
20835571f1e6SDan Schatzberg 
20845571f1e6SDan Schatzberg static const struct address_space_operations fuse_symlink_aops = {
20855efd00e4SMatthew Wilcox (Oracle) 	.read_folio	= fuse_symlink_read_folio,
20865571f1e6SDan Schatzberg };
20875571f1e6SDan Schatzberg 
2088e5e5558eSMiklos Szeredi void fuse_init_symlink(struct inode *inode)
2089e5e5558eSMiklos Szeredi {
2090e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_symlink_inode_operations;
20915571f1e6SDan Schatzberg 	inode->i_data.a_ops = &fuse_symlink_aops;
20925571f1e6SDan Schatzberg 	inode_nohighmem(inode);
2093e5e5558eSMiklos Szeredi }
2094