xref: /openbmc/linux/fs/fuse/dir.c (revision 519525fa47b5a8155f0b203e49a3a6a2319f75ae)
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>
13e5e5558eSMiklos Szeredi #include <linux/sched.h>
14e5e5558eSMiklos Szeredi #include <linux/namei.h>
1507e77dcaSMiklos Szeredi #include <linux/slab.h>
16703c7362SSeth Forshee #include <linux/xattr.h>
17261aaba7SMiklos Szeredi #include <linux/iversion.h>
1860bcc88aSSeth Forshee #include <linux/posix_acl.h>
19e5e5558eSMiklos Szeredi 
204582a4abSFeng Shuo static void fuse_advise_use_readdirplus(struct inode *dir)
214582a4abSFeng Shuo {
224582a4abSFeng Shuo 	struct fuse_inode *fi = get_fuse_inode(dir);
234582a4abSFeng Shuo 
244582a4abSFeng Shuo 	set_bit(FUSE_I_ADVISE_RDPLUS, &fi->state);
254582a4abSFeng Shuo }
264582a4abSFeng Shuo 
2730c6a23dSKhazhismel Kumykov #if BITS_PER_LONG >= 64
2830c6a23dSKhazhismel Kumykov static inline void __fuse_dentry_settime(struct dentry *entry, u64 time)
2930c6a23dSKhazhismel Kumykov {
3030c6a23dSKhazhismel Kumykov 	entry->d_fsdata = (void *) time;
3130c6a23dSKhazhismel Kumykov }
3230c6a23dSKhazhismel Kumykov 
3330c6a23dSKhazhismel Kumykov static inline u64 fuse_dentry_time(const struct dentry *entry)
3430c6a23dSKhazhismel Kumykov {
3530c6a23dSKhazhismel Kumykov 	return (u64)entry->d_fsdata;
3630c6a23dSKhazhismel Kumykov }
3730c6a23dSKhazhismel Kumykov 
3830c6a23dSKhazhismel Kumykov #else
39f75fdf22SMiklos Szeredi union fuse_dentry {
40f75fdf22SMiklos Szeredi 	u64 time;
41f75fdf22SMiklos Szeredi 	struct rcu_head rcu;
42f75fdf22SMiklos Szeredi };
43f75fdf22SMiklos Szeredi 
4430c6a23dSKhazhismel Kumykov static inline void __fuse_dentry_settime(struct dentry *dentry, u64 time)
4530c6a23dSKhazhismel Kumykov {
4630c6a23dSKhazhismel Kumykov 	((union fuse_dentry *) dentry->d_fsdata)->time = time;
4730c6a23dSKhazhismel Kumykov }
4830c6a23dSKhazhismel Kumykov 
4930c6a23dSKhazhismel Kumykov static inline u64 fuse_dentry_time(const struct dentry *entry)
5030c6a23dSKhazhismel Kumykov {
5130c6a23dSKhazhismel Kumykov 	return ((union fuse_dentry *) entry->d_fsdata)->time;
5230c6a23dSKhazhismel Kumykov }
5330c6a23dSKhazhismel Kumykov #endif
5430c6a23dSKhazhismel Kumykov 
558fab0106SMiklos Szeredi static void fuse_dentry_settime(struct dentry *dentry, u64 time)
560a0898cfSMiklos Szeredi {
578fab0106SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn_super(dentry->d_sb);
588fab0106SMiklos Szeredi 	bool delete = !time && fc->delete_stale;
598fab0106SMiklos Szeredi 	/*
608fab0106SMiklos Szeredi 	 * Mess with DCACHE_OP_DELETE because dput() will be faster without it.
618fab0106SMiklos Szeredi 	 * Don't care about races, either way it's just an optimization
628fab0106SMiklos Szeredi 	 */
638fab0106SMiklos Szeredi 	if ((!delete && (dentry->d_flags & DCACHE_OP_DELETE)) ||
648fab0106SMiklos Szeredi 	    (delete && !(dentry->d_flags & DCACHE_OP_DELETE))) {
658fab0106SMiklos Szeredi 		spin_lock(&dentry->d_lock);
668fab0106SMiklos Szeredi 		if (!delete)
678fab0106SMiklos Szeredi 			dentry->d_flags &= ~DCACHE_OP_DELETE;
688fab0106SMiklos Szeredi 		else
698fab0106SMiklos Szeredi 			dentry->d_flags |= DCACHE_OP_DELETE;
708fab0106SMiklos Szeredi 		spin_unlock(&dentry->d_lock);
710a0898cfSMiklos Szeredi 	}
720a0898cfSMiklos Szeredi 
7330c6a23dSKhazhismel Kumykov 	__fuse_dentry_settime(dentry, time);
740a0898cfSMiklos Szeredi }
750a0898cfSMiklos Szeredi 
766f9f1180SMiklos Szeredi /*
776f9f1180SMiklos Szeredi  * FUSE caches dentries and attributes with separate timeout.  The
786f9f1180SMiklos Szeredi  * time in jiffies until the dentry/attributes are valid is stored in
79f75fdf22SMiklos Szeredi  * dentry->d_fsdata and fuse_inode->i_time respectively.
806f9f1180SMiklos Szeredi  */
816f9f1180SMiklos Szeredi 
826f9f1180SMiklos Szeredi /*
836f9f1180SMiklos Szeredi  * Calculate the time in jiffies until a dentry/attributes are valid
846f9f1180SMiklos Szeredi  */
85bcb6f6d2SMiklos Szeredi static u64 time_to_jiffies(u64 sec, u32 nsec)
86e5e5558eSMiklos Szeredi {
87685d16ddSMiklos Szeredi 	if (sec || nsec) {
88bcb6f6d2SMiklos Szeredi 		struct timespec64 ts = {
89bcb6f6d2SMiklos Szeredi 			sec,
9021067527SDavid Sheets 			min_t(u32, nsec, NSEC_PER_SEC - 1)
91bcb6f6d2SMiklos Szeredi 		};
92bcb6f6d2SMiklos Szeredi 
93bcb6f6d2SMiklos Szeredi 		return get_jiffies_64() + timespec64_to_jiffies(&ts);
94685d16ddSMiklos Szeredi 	} else
950a0898cfSMiklos Szeredi 		return 0;
96e5e5558eSMiklos Szeredi }
97e5e5558eSMiklos Szeredi 
986f9f1180SMiklos Szeredi /*
996f9f1180SMiklos Szeredi  * Set dentry and possibly attribute timeouts from the lookup/mk*
1006f9f1180SMiklos Szeredi  * replies
1016f9f1180SMiklos Szeredi  */
102d123d8e1SMiklos Szeredi void fuse_change_entry_timeout(struct dentry *entry, struct fuse_entry_out *o)
1030aa7c699SMiklos Szeredi {
1040a0898cfSMiklos Szeredi 	fuse_dentry_settime(entry,
1050a0898cfSMiklos Szeredi 		time_to_jiffies(o->entry_valid, o->entry_valid_nsec));
1061fb69e78SMiklos Szeredi }
1071fb69e78SMiklos Szeredi 
1081fb69e78SMiklos Szeredi static u64 attr_timeout(struct fuse_attr_out *o)
1091fb69e78SMiklos Szeredi {
1101fb69e78SMiklos Szeredi 	return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
1111fb69e78SMiklos Szeredi }
1121fb69e78SMiklos Szeredi 
113d123d8e1SMiklos Szeredi u64 entry_attr_timeout(struct fuse_entry_out *o)
1141fb69e78SMiklos Szeredi {
1151fb69e78SMiklos Szeredi 	return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
1168cbdf1e6SMiklos Szeredi }
1178cbdf1e6SMiklos Szeredi 
1182f1e8196SMiklos Szeredi static void fuse_invalidate_attr_mask(struct inode *inode, u32 mask)
1192f1e8196SMiklos Szeredi {
1202f1e8196SMiklos Szeredi 	set_mask_bits(&get_fuse_inode(inode)->inval_mask, 0, mask);
1212f1e8196SMiklos Szeredi }
1222f1e8196SMiklos Szeredi 
1236f9f1180SMiklos Szeredi /*
1246f9f1180SMiklos Szeredi  * Mark the attributes as stale, so that at the next call to
1256f9f1180SMiklos Szeredi  * ->getattr() they will be fetched from userspace
1266f9f1180SMiklos Szeredi  */
1278cbdf1e6SMiklos Szeredi void fuse_invalidate_attr(struct inode *inode)
1288cbdf1e6SMiklos Szeredi {
1292f1e8196SMiklos Szeredi 	fuse_invalidate_attr_mask(inode, STATX_BASIC_STATS);
1308cbdf1e6SMiklos Szeredi }
1318cbdf1e6SMiklos Szeredi 
132261aaba7SMiklos Szeredi static void fuse_dir_changed(struct inode *dir)
133261aaba7SMiklos Szeredi {
134261aaba7SMiklos Szeredi 	fuse_invalidate_attr(dir);
135261aaba7SMiklos Szeredi 	inode_maybe_inc_iversion(dir, false);
136261aaba7SMiklos Szeredi }
137261aaba7SMiklos Szeredi 
138451418fcSAndrew Gallagher /**
139451418fcSAndrew Gallagher  * Mark the attributes as stale due to an atime change.  Avoid the invalidate if
140451418fcSAndrew Gallagher  * atime is not used.
141451418fcSAndrew Gallagher  */
142451418fcSAndrew Gallagher void fuse_invalidate_atime(struct inode *inode)
143451418fcSAndrew Gallagher {
144451418fcSAndrew Gallagher 	if (!IS_RDONLY(inode))
1452f1e8196SMiklos Szeredi 		fuse_invalidate_attr_mask(inode, STATX_ATIME);
146451418fcSAndrew Gallagher }
147451418fcSAndrew Gallagher 
1486f9f1180SMiklos Szeredi /*
1496f9f1180SMiklos Szeredi  * Just mark the entry as stale, so that a next attempt to look it up
1506f9f1180SMiklos Szeredi  * will result in a new lookup call to userspace
1516f9f1180SMiklos Szeredi  *
1526f9f1180SMiklos Szeredi  * This is called when a dentry is about to become negative and the
1536f9f1180SMiklos Szeredi  * timeout is unknown (unlink, rmdir, rename and in some cases
1546f9f1180SMiklos Szeredi  * lookup)
1556f9f1180SMiklos Szeredi  */
156dbd561d2SMiklos Szeredi void fuse_invalidate_entry_cache(struct dentry *entry)
1578cbdf1e6SMiklos Szeredi {
1580a0898cfSMiklos Szeredi 	fuse_dentry_settime(entry, 0);
1598cbdf1e6SMiklos Szeredi }
1608cbdf1e6SMiklos Szeredi 
1616f9f1180SMiklos Szeredi /*
1626f9f1180SMiklos Szeredi  * Same as fuse_invalidate_entry_cache(), but also try to remove the
1636f9f1180SMiklos Szeredi  * dentry from the hash
1646f9f1180SMiklos Szeredi  */
1658cbdf1e6SMiklos Szeredi static void fuse_invalidate_entry(struct dentry *entry)
1668cbdf1e6SMiklos Szeredi {
1678cbdf1e6SMiklos Szeredi 	d_invalidate(entry);
1688cbdf1e6SMiklos Szeredi 	fuse_invalidate_entry_cache(entry);
1690aa7c699SMiklos Szeredi }
1700aa7c699SMiklos Szeredi 
1717078187aSMiklos Szeredi static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_args *args,
17213983d06SAl Viro 			     u64 nodeid, const struct qstr *name,
173e5e5558eSMiklos Szeredi 			     struct fuse_entry_out *outarg)
174e5e5558eSMiklos Szeredi {
1750e9663eeSMiklos Szeredi 	memset(outarg, 0, sizeof(struct fuse_entry_out));
176d5b48543SMiklos Szeredi 	args->opcode = FUSE_LOOKUP;
177d5b48543SMiklos Szeredi 	args->nodeid = nodeid;
178d5b48543SMiklos Szeredi 	args->in_numargs = 1;
179d5b48543SMiklos Szeredi 	args->in_args[0].size = name->len + 1;
180d5b48543SMiklos Szeredi 	args->in_args[0].value = name->name;
181d5b48543SMiklos Szeredi 	args->out_numargs = 1;
182d5b48543SMiklos Szeredi 	args->out_args[0].size = sizeof(struct fuse_entry_out);
183d5b48543SMiklos Szeredi 	args->out_args[0].value = outarg;
184e5e5558eSMiklos Szeredi }
185e5e5558eSMiklos Szeredi 
1866f9f1180SMiklos Szeredi /*
1876f9f1180SMiklos Szeredi  * Check whether the dentry is still valid
1886f9f1180SMiklos Szeredi  *
1896f9f1180SMiklos Szeredi  * If the entry validity timeout has expired and the dentry is
1906f9f1180SMiklos Szeredi  * positive, try to redo the lookup.  If the lookup results in a
1916f9f1180SMiklos Szeredi  * different inode, then let the VFS invalidate the dentry and redo
1926f9f1180SMiklos Szeredi  * the lookup once more.  If the lookup results in the same inode,
1936f9f1180SMiklos Szeredi  * then refresh the attributes, timeouts and mark the dentry valid.
1946f9f1180SMiklos Szeredi  */
1950b728e19SAl Viro static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
196e5e5558eSMiklos Szeredi {
19734286d66SNick Piggin 	struct inode *inode;
19828420dadSMiklos Szeredi 	struct dentry *parent;
19928420dadSMiklos Szeredi 	struct fuse_conn *fc;
2006314efeeSMiklos Szeredi 	struct fuse_inode *fi;
201e2a6b952SMiklos Szeredi 	int ret;
2028cbdf1e6SMiklos Szeredi 
2032b0143b5SDavid Howells 	inode = d_inode_rcu(entry);
2048cbdf1e6SMiklos Szeredi 	if (inode && is_bad_inode(inode))
205e2a6b952SMiklos Szeredi 		goto invalid;
206154210ccSAnand Avati 	else if (time_before64(fuse_dentry_time(entry), get_jiffies_64()) ||
207154210ccSAnand Avati 		 (flags & LOOKUP_REVAL)) {
208e5e5558eSMiklos Szeredi 		struct fuse_entry_out outarg;
2097078187aSMiklos Szeredi 		FUSE_ARGS(args);
21007e77dcaSMiklos Szeredi 		struct fuse_forget_link *forget;
2111fb69e78SMiklos Szeredi 		u64 attr_version;
2128cbdf1e6SMiklos Szeredi 
21350322fe7SMiklos Szeredi 		/* For negative dentries, always do a fresh lookup */
2148cbdf1e6SMiklos Szeredi 		if (!inode)
215e2a6b952SMiklos Szeredi 			goto invalid;
2168cbdf1e6SMiklos Szeredi 
217e2a6b952SMiklos Szeredi 		ret = -ECHILD;
2180b728e19SAl Viro 		if (flags & LOOKUP_RCU)
219e2a6b952SMiklos Szeredi 			goto out;
220e7c0a167SMiklos Szeredi 
2218cbdf1e6SMiklos Szeredi 		fc = get_fuse_conn(inode);
222e5e5558eSMiklos Szeredi 
22307e77dcaSMiklos Szeredi 		forget = fuse_alloc_forget();
224e2a6b952SMiklos Szeredi 		ret = -ENOMEM;
2257078187aSMiklos Szeredi 		if (!forget)
226e2a6b952SMiklos Szeredi 			goto out;
2272d51013eSMiklos Szeredi 
2287dca9fd3SMiklos Szeredi 		attr_version = fuse_get_attr_version(fc);
2291fb69e78SMiklos Szeredi 
230e956edd0SMiklos Szeredi 		parent = dget_parent(entry);
2312b0143b5SDavid Howells 		fuse_lookup_init(fc, &args, get_node_id(d_inode(parent)),
232c180eebeSMiklos Szeredi 				 &entry->d_name, &outarg);
2337078187aSMiklos Szeredi 		ret = fuse_simple_request(fc, &args);
234e956edd0SMiklos Szeredi 		dput(parent);
23550322fe7SMiklos Szeredi 		/* Zero nodeid is same as -ENOENT */
2367078187aSMiklos Szeredi 		if (!ret && !outarg.nodeid)
2377078187aSMiklos Szeredi 			ret = -ENOENT;
2387078187aSMiklos Szeredi 		if (!ret) {
2396314efeeSMiklos Szeredi 			fi = get_fuse_inode(inode);
2409e6268dbSMiklos Szeredi 			if (outarg.nodeid != get_node_id(inode)) {
24107e77dcaSMiklos Szeredi 				fuse_queue_forget(fc, forget, outarg.nodeid, 1);
242e2a6b952SMiklos Szeredi 				goto invalid;
2439e6268dbSMiklos Szeredi 			}
244c9d8f5f0SKirill Tkhai 			spin_lock(&fi->lock);
2459e6268dbSMiklos Szeredi 			fi->nlookup++;
246c9d8f5f0SKirill Tkhai 			spin_unlock(&fi->lock);
2479e6268dbSMiklos Szeredi 		}
24807e77dcaSMiklos Szeredi 		kfree(forget);
2497078187aSMiklos Szeredi 		if (ret == -ENOMEM)
2507078187aSMiklos Szeredi 			goto out;
251eb59bd17SMiklos Szeredi 		if (ret || fuse_invalid_attr(&outarg.attr) ||
252eb59bd17SMiklos Szeredi 		    (outarg.attr.mode ^ inode->i_mode) & S_IFMT)
253e2a6b952SMiklos Szeredi 			goto invalid;
254e5e5558eSMiklos Szeredi 
25560bcc88aSSeth Forshee 		forget_all_cached_acls(inode);
2561fb69e78SMiklos Szeredi 		fuse_change_attributes(inode, &outarg.attr,
2571fb69e78SMiklos Szeredi 				       entry_attr_timeout(&outarg),
2581fb69e78SMiklos Szeredi 				       attr_version);
2591fb69e78SMiklos Szeredi 		fuse_change_entry_timeout(entry, &outarg);
26028420dadSMiklos Szeredi 	} else if (inode) {
2616314efeeSMiklos Szeredi 		fi = get_fuse_inode(inode);
2626314efeeSMiklos Szeredi 		if (flags & LOOKUP_RCU) {
2636314efeeSMiklos Szeredi 			if (test_bit(FUSE_I_INIT_RDPLUS, &fi->state))
2646314efeeSMiklos Szeredi 				return -ECHILD;
2656314efeeSMiklos Szeredi 		} else if (test_and_clear_bit(FUSE_I_INIT_RDPLUS, &fi->state)) {
26628420dadSMiklos Szeredi 			parent = dget_parent(entry);
2672b0143b5SDavid Howells 			fuse_advise_use_readdirplus(d_inode(parent));
26828420dadSMiklos Szeredi 			dput(parent);
269e5e5558eSMiklos Szeredi 		}
27028420dadSMiklos Szeredi 	}
271e2a6b952SMiklos Szeredi 	ret = 1;
272e2a6b952SMiklos Szeredi out:
273e2a6b952SMiklos Szeredi 	return ret;
274e2a6b952SMiklos Szeredi 
275e2a6b952SMiklos Szeredi invalid:
276e2a6b952SMiklos Szeredi 	ret = 0;
277e2a6b952SMiklos Szeredi 	goto out;
278e5e5558eSMiklos Szeredi }
279e5e5558eSMiklos Szeredi 
28030c6a23dSKhazhismel Kumykov #if BITS_PER_LONG < 64
281f75fdf22SMiklos Szeredi static int fuse_dentry_init(struct dentry *dentry)
282f75fdf22SMiklos Szeredi {
283dc69e98cSKhazhismel Kumykov 	dentry->d_fsdata = kzalloc(sizeof(union fuse_dentry),
284dc69e98cSKhazhismel Kumykov 				   GFP_KERNEL_ACCOUNT | __GFP_RECLAIMABLE);
285f75fdf22SMiklos Szeredi 
286f75fdf22SMiklos Szeredi 	return dentry->d_fsdata ? 0 : -ENOMEM;
287f75fdf22SMiklos Szeredi }
288f75fdf22SMiklos Szeredi static void fuse_dentry_release(struct dentry *dentry)
289f75fdf22SMiklos Szeredi {
290f75fdf22SMiklos Szeredi 	union fuse_dentry *fd = dentry->d_fsdata;
291f75fdf22SMiklos Szeredi 
292f75fdf22SMiklos Szeredi 	kfree_rcu(fd, rcu);
293f75fdf22SMiklos Szeredi }
29430c6a23dSKhazhismel Kumykov #endif
295f75fdf22SMiklos Szeredi 
2968fab0106SMiklos Szeredi static int fuse_dentry_delete(const struct dentry *dentry)
2978fab0106SMiklos Szeredi {
2988fab0106SMiklos Szeredi 	return time_before64(fuse_dentry_time(dentry), get_jiffies_64());
2998fab0106SMiklos Szeredi }
3008fab0106SMiklos Szeredi 
3014269590aSAl Viro const struct dentry_operations fuse_dentry_operations = {
302e5e5558eSMiklos Szeredi 	.d_revalidate	= fuse_dentry_revalidate,
3038fab0106SMiklos Szeredi 	.d_delete	= fuse_dentry_delete,
30430c6a23dSKhazhismel Kumykov #if BITS_PER_LONG < 64
305f75fdf22SMiklos Szeredi 	.d_init		= fuse_dentry_init,
306f75fdf22SMiklos Szeredi 	.d_release	= fuse_dentry_release,
30730c6a23dSKhazhismel Kumykov #endif
308e5e5558eSMiklos Szeredi };
309e5e5558eSMiklos Szeredi 
3100ce267ffSMiklos Szeredi const struct dentry_operations fuse_root_dentry_operations = {
31130c6a23dSKhazhismel Kumykov #if BITS_PER_LONG < 64
3120ce267ffSMiklos Szeredi 	.d_init		= fuse_dentry_init,
3130ce267ffSMiklos Szeredi 	.d_release	= fuse_dentry_release,
31430c6a23dSKhazhismel Kumykov #endif
3150ce267ffSMiklos Szeredi };
3160ce267ffSMiklos Szeredi 
317a5bfffacSTimo Savola int fuse_valid_type(int m)
31839ee059aSMiklos Szeredi {
31939ee059aSMiklos Szeredi 	return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) ||
32039ee059aSMiklos Szeredi 		S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m);
32139ee059aSMiklos Szeredi }
32239ee059aSMiklos Szeredi 
323eb59bd17SMiklos Szeredi bool fuse_invalid_attr(struct fuse_attr *attr)
324eb59bd17SMiklos Szeredi {
325eb59bd17SMiklos Szeredi 	return !fuse_valid_type(attr->mode) ||
326eb59bd17SMiklos Szeredi 		attr->size > LLONG_MAX;
327eb59bd17SMiklos Szeredi }
328eb59bd17SMiklos Szeredi 
32913983d06SAl Viro int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name,
330c180eebeSMiklos Szeredi 		     struct fuse_entry_out *outarg, struct inode **inode)
331c180eebeSMiklos Szeredi {
332c180eebeSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn_super(sb);
3337078187aSMiklos Szeredi 	FUSE_ARGS(args);
33407e77dcaSMiklos Szeredi 	struct fuse_forget_link *forget;
335c180eebeSMiklos Szeredi 	u64 attr_version;
336c180eebeSMiklos Szeredi 	int err;
337c180eebeSMiklos Szeredi 
338c180eebeSMiklos Szeredi 	*inode = NULL;
339c180eebeSMiklos Szeredi 	err = -ENAMETOOLONG;
340c180eebeSMiklos Szeredi 	if (name->len > FUSE_NAME_MAX)
341c180eebeSMiklos Szeredi 		goto out;
342c180eebeSMiklos Szeredi 
343c180eebeSMiklos Szeredi 
34407e77dcaSMiklos Szeredi 	forget = fuse_alloc_forget();
34507e77dcaSMiklos Szeredi 	err = -ENOMEM;
3467078187aSMiklos Szeredi 	if (!forget)
347c180eebeSMiklos Szeredi 		goto out;
348c180eebeSMiklos Szeredi 
349c180eebeSMiklos Szeredi 	attr_version = fuse_get_attr_version(fc);
350c180eebeSMiklos Szeredi 
3517078187aSMiklos Szeredi 	fuse_lookup_init(fc, &args, nodeid, name, outarg);
3527078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
353c180eebeSMiklos Szeredi 	/* Zero nodeid is same as -ENOENT, but with valid timeout */
354c180eebeSMiklos Szeredi 	if (err || !outarg->nodeid)
355c180eebeSMiklos Szeredi 		goto out_put_forget;
356c180eebeSMiklos Szeredi 
357c180eebeSMiklos Szeredi 	err = -EIO;
358c180eebeSMiklos Szeredi 	if (!outarg->nodeid)
359c180eebeSMiklos Szeredi 		goto out_put_forget;
360eb59bd17SMiklos Szeredi 	if (fuse_invalid_attr(&outarg->attr))
361c180eebeSMiklos Szeredi 		goto out_put_forget;
362c180eebeSMiklos Szeredi 
363c180eebeSMiklos Szeredi 	*inode = fuse_iget(sb, outarg->nodeid, outarg->generation,
364c180eebeSMiklos Szeredi 			   &outarg->attr, entry_attr_timeout(outarg),
365c180eebeSMiklos Szeredi 			   attr_version);
366c180eebeSMiklos Szeredi 	err = -ENOMEM;
367c180eebeSMiklos Szeredi 	if (!*inode) {
36807e77dcaSMiklos Szeredi 		fuse_queue_forget(fc, forget, outarg->nodeid, 1);
369c180eebeSMiklos Szeredi 		goto out;
370c180eebeSMiklos Szeredi 	}
371c180eebeSMiklos Szeredi 	err = 0;
372c180eebeSMiklos Szeredi 
373c180eebeSMiklos Szeredi  out_put_forget:
37407e77dcaSMiklos Szeredi 	kfree(forget);
375c180eebeSMiklos Szeredi  out:
376c180eebeSMiklos Szeredi 	return err;
377c180eebeSMiklos Szeredi }
378c180eebeSMiklos Szeredi 
3790aa7c699SMiklos Szeredi static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
38000cd8dd3SAl Viro 				  unsigned int flags)
381e5e5558eSMiklos Szeredi {
382e5e5558eSMiklos Szeredi 	int err;
383e5e5558eSMiklos Szeredi 	struct fuse_entry_out outarg;
384c180eebeSMiklos Szeredi 	struct inode *inode;
3850de6256dSMiklos Szeredi 	struct dentry *newent;
386c180eebeSMiklos Szeredi 	bool outarg_valid = true;
38763576c13SMiklos Szeredi 	bool locked;
388e5e5558eSMiklos Szeredi 
38963576c13SMiklos Szeredi 	locked = fuse_lock_inode(dir);
390c180eebeSMiklos Szeredi 	err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name,
391c180eebeSMiklos Szeredi 			       &outarg, &inode);
39263576c13SMiklos Szeredi 	fuse_unlock_inode(dir, locked);
393c180eebeSMiklos Szeredi 	if (err == -ENOENT) {
394c180eebeSMiklos Szeredi 		outarg_valid = false;
395c180eebeSMiklos Szeredi 		err = 0;
3962d51013eSMiklos Szeredi 	}
397c180eebeSMiklos Szeredi 	if (err)
398c180eebeSMiklos Szeredi 		goto out_err;
3992d51013eSMiklos Szeredi 
400ee4e5271SMiklos Szeredi 	err = -EIO;
401c180eebeSMiklos Szeredi 	if (inode && get_node_id(inode) == FUSE_ROOT_ID)
402c180eebeSMiklos Szeredi 		goto out_iput;
403e5e5558eSMiklos Szeredi 
40441d28bcaSAl Viro 	newent = d_splice_alias(inode, entry);
405c180eebeSMiklos Szeredi 	err = PTR_ERR(newent);
406c180eebeSMiklos Szeredi 	if (IS_ERR(newent))
4075835f339SMiklos Szeredi 		goto out_err;
408d2a85164SMiklos Szeredi 
4090de6256dSMiklos Szeredi 	entry = newent ? newent : entry;
410c180eebeSMiklos Szeredi 	if (outarg_valid)
4111fb69e78SMiklos Szeredi 		fuse_change_entry_timeout(entry, &outarg);
4128cbdf1e6SMiklos Szeredi 	else
4138cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
414c180eebeSMiklos Szeredi 
4156c26f717SMiklos Szeredi 	if (inode)
4164582a4abSFeng Shuo 		fuse_advise_use_readdirplus(dir);
4170de6256dSMiklos Szeredi 	return newent;
418c180eebeSMiklos Szeredi 
419c180eebeSMiklos Szeredi  out_iput:
420c180eebeSMiklos Szeredi 	iput(inode);
421c180eebeSMiklos Szeredi  out_err:
422c180eebeSMiklos Szeredi 	return ERR_PTR(err);
423e5e5558eSMiklos Szeredi }
424e5e5558eSMiklos Szeredi 
4256f9f1180SMiklos Szeredi /*
4266f9f1180SMiklos Szeredi  * Atomic create+open operation
4276f9f1180SMiklos Szeredi  *
4286f9f1180SMiklos Szeredi  * If the filesystem doesn't support this, then fall back to separate
4296f9f1180SMiklos Szeredi  * 'mknod' + 'open' requests.
4306f9f1180SMiklos Szeredi  */
431d9585277SAl Viro static int fuse_create_open(struct inode *dir, struct dentry *entry,
43230d90494SAl Viro 			    struct file *file, unsigned flags,
433b452a458SAl Viro 			    umode_t mode)
434fd72faacSMiklos Szeredi {
435fd72faacSMiklos Szeredi 	int err;
436fd72faacSMiklos Szeredi 	struct inode *inode;
437fd72faacSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
4387078187aSMiklos Szeredi 	FUSE_ARGS(args);
43907e77dcaSMiklos Szeredi 	struct fuse_forget_link *forget;
440e0a43ddcSMiklos Szeredi 	struct fuse_create_in inarg;
441fd72faacSMiklos Szeredi 	struct fuse_open_out outopen;
442fd72faacSMiklos Szeredi 	struct fuse_entry_out outentry;
443ebf84d0cSKirill Tkhai 	struct fuse_inode *fi;
444fd72faacSMiklos Szeredi 	struct fuse_file *ff;
445fd72faacSMiklos Szeredi 
446af109bcaSMiklos Szeredi 	/* Userspace expects S_IFREG in create mode */
447af109bcaSMiklos Szeredi 	BUG_ON((mode & S_IFMT) != S_IFREG);
448af109bcaSMiklos Szeredi 
44907e77dcaSMiklos Szeredi 	forget = fuse_alloc_forget();
450c8ccbe03SMiklos Szeredi 	err = -ENOMEM;
45107e77dcaSMiklos Szeredi 	if (!forget)
452c8ccbe03SMiklos Szeredi 		goto out_err;
45351eb01e7SMiklos Szeredi 
454ce1d5a49SMiklos Szeredi 	err = -ENOMEM;
455acf99433STejun Heo 	ff = fuse_file_alloc(fc);
456fd72faacSMiklos Szeredi 	if (!ff)
4577078187aSMiklos Szeredi 		goto out_put_forget_req;
458fd72faacSMiklos Szeredi 
459e0a43ddcSMiklos Szeredi 	if (!fc->dont_mask)
460e0a43ddcSMiklos Szeredi 		mode &= ~current_umask();
461e0a43ddcSMiklos Szeredi 
462fd72faacSMiklos Szeredi 	flags &= ~O_NOCTTY;
463fd72faacSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
4640e9663eeSMiklos Szeredi 	memset(&outentry, 0, sizeof(outentry));
465fd72faacSMiklos Szeredi 	inarg.flags = flags;
466fd72faacSMiklos Szeredi 	inarg.mode = mode;
467e0a43ddcSMiklos Szeredi 	inarg.umask = current_umask();
468d5b48543SMiklos Szeredi 	args.opcode = FUSE_CREATE;
469d5b48543SMiklos Szeredi 	args.nodeid = get_node_id(dir);
470d5b48543SMiklos Szeredi 	args.in_numargs = 2;
471d5b48543SMiklos Szeredi 	args.in_args[0].size = sizeof(inarg);
472d5b48543SMiklos Szeredi 	args.in_args[0].value = &inarg;
473d5b48543SMiklos Szeredi 	args.in_args[1].size = entry->d_name.len + 1;
474d5b48543SMiklos Szeredi 	args.in_args[1].value = entry->d_name.name;
475d5b48543SMiklos Szeredi 	args.out_numargs = 2;
476d5b48543SMiklos Szeredi 	args.out_args[0].size = sizeof(outentry);
477d5b48543SMiklos Szeredi 	args.out_args[0].value = &outentry;
478d5b48543SMiklos Szeredi 	args.out_args[1].size = sizeof(outopen);
479d5b48543SMiklos Szeredi 	args.out_args[1].value = &outopen;
4807078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
481c8ccbe03SMiklos Szeredi 	if (err)
482fd72faacSMiklos Szeredi 		goto out_free_ff;
483fd72faacSMiklos Szeredi 
484fd72faacSMiklos Szeredi 	err = -EIO;
485eb59bd17SMiklos Szeredi 	if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid) ||
486eb59bd17SMiklos Szeredi 	    fuse_invalid_attr(&outentry.attr))
487fd72faacSMiklos Szeredi 		goto out_free_ff;
488fd72faacSMiklos Szeredi 
489c7b7143cSMiklos Szeredi 	ff->fh = outopen.fh;
490c7b7143cSMiklos Szeredi 	ff->nodeid = outentry.nodeid;
491c7b7143cSMiklos Szeredi 	ff->open_flags = outopen.open_flags;
492fd72faacSMiklos Szeredi 	inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
4931fb69e78SMiklos Szeredi 			  &outentry.attr, entry_attr_timeout(&outentry), 0);
494fd72faacSMiklos Szeredi 	if (!inode) {
495fd72faacSMiklos Szeredi 		flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
496ebf84d0cSKirill Tkhai 		fuse_sync_release(NULL, ff, flags);
49707e77dcaSMiklos Szeredi 		fuse_queue_forget(fc, forget, outentry.nodeid, 1);
498c8ccbe03SMiklos Szeredi 		err = -ENOMEM;
499c8ccbe03SMiklos Szeredi 		goto out_err;
500fd72faacSMiklos Szeredi 	}
50107e77dcaSMiklos Szeredi 	kfree(forget);
502fd72faacSMiklos Szeredi 	d_instantiate(entry, inode);
5031fb69e78SMiklos Szeredi 	fuse_change_entry_timeout(entry, &outentry);
504261aaba7SMiklos Szeredi 	fuse_dir_changed(dir);
505be12af3eSAl Viro 	err = finish_open(file, entry, generic_file_open);
50630d90494SAl Viro 	if (err) {
507ebf84d0cSKirill Tkhai 		fi = get_fuse_inode(inode);
508ebf84d0cSKirill Tkhai 		fuse_sync_release(fi, ff, flags);
509c8ccbe03SMiklos Szeredi 	} else {
510267d8444SMiklos Szeredi 		file->private_data = ff;
511c7b7143cSMiklos Szeredi 		fuse_finish_open(inode, file);
512c8ccbe03SMiklos Szeredi 	}
513d9585277SAl Viro 	return err;
514fd72faacSMiklos Szeredi 
515fd72faacSMiklos Szeredi out_free_ff:
516fd72faacSMiklos Szeredi 	fuse_file_free(ff);
51751eb01e7SMiklos Szeredi out_put_forget_req:
51807e77dcaSMiklos Szeredi 	kfree(forget);
519c8ccbe03SMiklos Szeredi out_err:
520d9585277SAl Viro 	return err;
521c8ccbe03SMiklos Szeredi }
522c8ccbe03SMiklos Szeredi 
523c8ccbe03SMiklos Szeredi static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t);
524d9585277SAl Viro static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
52530d90494SAl Viro 			    struct file *file, unsigned flags,
52644907d79SAl Viro 			    umode_t mode)
527c8ccbe03SMiklos Szeredi {
528c8ccbe03SMiklos Szeredi 	int err;
529c8ccbe03SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
530c8ccbe03SMiklos Szeredi 	struct dentry *res = NULL;
531c8ccbe03SMiklos Szeredi 
53200699ad8SAl Viro 	if (d_in_lookup(entry)) {
53300cd8dd3SAl Viro 		res = fuse_lookup(dir, entry, 0);
534c8ccbe03SMiklos Szeredi 		if (IS_ERR(res))
535d9585277SAl Viro 			return PTR_ERR(res);
536c8ccbe03SMiklos Szeredi 
537c8ccbe03SMiklos Szeredi 		if (res)
538c8ccbe03SMiklos Szeredi 			entry = res;
539c8ccbe03SMiklos Szeredi 	}
540c8ccbe03SMiklos Szeredi 
5412b0143b5SDavid Howells 	if (!(flags & O_CREAT) || d_really_is_positive(entry))
542c8ccbe03SMiklos Szeredi 		goto no_open;
543c8ccbe03SMiklos Szeredi 
544c8ccbe03SMiklos Szeredi 	/* Only creates */
54573a09dd9SAl Viro 	file->f_mode |= FMODE_CREATED;
546c8ccbe03SMiklos Szeredi 
547c8ccbe03SMiklos Szeredi 	if (fc->no_create)
548c8ccbe03SMiklos Szeredi 		goto mknod;
549c8ccbe03SMiklos Szeredi 
550b452a458SAl Viro 	err = fuse_create_open(dir, entry, file, flags, mode);
551d9585277SAl Viro 	if (err == -ENOSYS) {
552c8ccbe03SMiklos Szeredi 		fc->no_create = 1;
553c8ccbe03SMiklos Szeredi 		goto mknod;
554c8ccbe03SMiklos Szeredi 	}
555c8ccbe03SMiklos Szeredi out_dput:
556c8ccbe03SMiklos Szeredi 	dput(res);
557d9585277SAl Viro 	return err;
558c8ccbe03SMiklos Szeredi 
559c8ccbe03SMiklos Szeredi mknod:
560c8ccbe03SMiklos Szeredi 	err = fuse_mknod(dir, entry, mode, 0);
561d9585277SAl Viro 	if (err)
562c8ccbe03SMiklos Szeredi 		goto out_dput;
563c8ccbe03SMiklos Szeredi no_open:
564e45198a6SAl Viro 	return finish_no_open(file, res);
565fd72faacSMiklos Szeredi }
566fd72faacSMiklos Szeredi 
5676f9f1180SMiklos Szeredi /*
5686f9f1180SMiklos Szeredi  * Code shared between mknod, mkdir, symlink and link
5696f9f1180SMiklos Szeredi  */
5707078187aSMiklos Szeredi static int create_new_entry(struct fuse_conn *fc, struct fuse_args *args,
5719e6268dbSMiklos Szeredi 			    struct inode *dir, struct dentry *entry,
572541af6a0SAl Viro 			    umode_t mode)
5739e6268dbSMiklos Szeredi {
5749e6268dbSMiklos Szeredi 	struct fuse_entry_out outarg;
5759e6268dbSMiklos Szeredi 	struct inode *inode;
576c971e6a0SAl Viro 	struct dentry *d;
5779e6268dbSMiklos Szeredi 	int err;
57807e77dcaSMiklos Szeredi 	struct fuse_forget_link *forget;
5792d51013eSMiklos Szeredi 
58007e77dcaSMiklos Szeredi 	forget = fuse_alloc_forget();
5817078187aSMiklos Szeredi 	if (!forget)
58207e77dcaSMiklos Szeredi 		return -ENOMEM;
5839e6268dbSMiklos Szeredi 
5840e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
585d5b48543SMiklos Szeredi 	args->nodeid = get_node_id(dir);
586d5b48543SMiklos Szeredi 	args->out_numargs = 1;
587d5b48543SMiklos Szeredi 	args->out_args[0].size = sizeof(outarg);
588d5b48543SMiklos Szeredi 	args->out_args[0].value = &outarg;
5897078187aSMiklos Szeredi 	err = fuse_simple_request(fc, args);
5902d51013eSMiklos Szeredi 	if (err)
5912d51013eSMiklos Szeredi 		goto out_put_forget_req;
5922d51013eSMiklos Szeredi 
59339ee059aSMiklos Szeredi 	err = -EIO;
594eb59bd17SMiklos Szeredi 	if (invalid_nodeid(outarg.nodeid) || fuse_invalid_attr(&outarg.attr))
5952d51013eSMiklos Szeredi 		goto out_put_forget_req;
59639ee059aSMiklos Szeredi 
59739ee059aSMiklos Szeredi 	if ((outarg.attr.mode ^ mode) & S_IFMT)
5982d51013eSMiklos Szeredi 		goto out_put_forget_req;
59939ee059aSMiklos Szeredi 
6009e6268dbSMiklos Szeredi 	inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
6011fb69e78SMiklos Szeredi 			  &outarg.attr, entry_attr_timeout(&outarg), 0);
6029e6268dbSMiklos Szeredi 	if (!inode) {
60307e77dcaSMiklos Szeredi 		fuse_queue_forget(fc, forget, outarg.nodeid, 1);
6049e6268dbSMiklos Szeredi 		return -ENOMEM;
6059e6268dbSMiklos Szeredi 	}
60607e77dcaSMiklos Szeredi 	kfree(forget);
6079e6268dbSMiklos Szeredi 
608c971e6a0SAl Viro 	d_drop(entry);
609c971e6a0SAl Viro 	d = d_splice_alias(inode, entry);
610c971e6a0SAl Viro 	if (IS_ERR(d))
611c971e6a0SAl Viro 		return PTR_ERR(d);
612d2a85164SMiklos Szeredi 
613c971e6a0SAl Viro 	if (d) {
614c971e6a0SAl Viro 		fuse_change_entry_timeout(d, &outarg);
615c971e6a0SAl Viro 		dput(d);
616c971e6a0SAl Viro 	} else {
6171fb69e78SMiklos Szeredi 		fuse_change_entry_timeout(entry, &outarg);
618c971e6a0SAl Viro 	}
619261aaba7SMiklos Szeredi 	fuse_dir_changed(dir);
6209e6268dbSMiklos Szeredi 	return 0;
62139ee059aSMiklos Szeredi 
6222d51013eSMiklos Szeredi  out_put_forget_req:
62307e77dcaSMiklos Szeredi 	kfree(forget);
62439ee059aSMiklos Szeredi 	return err;
6259e6268dbSMiklos Szeredi }
6269e6268dbSMiklos Szeredi 
6271a67aafbSAl Viro static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode,
6289e6268dbSMiklos Szeredi 		      dev_t rdev)
6299e6268dbSMiklos Szeredi {
6309e6268dbSMiklos Szeredi 	struct fuse_mknod_in inarg;
6319e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
6327078187aSMiklos Szeredi 	FUSE_ARGS(args);
6339e6268dbSMiklos Szeredi 
634e0a43ddcSMiklos Szeredi 	if (!fc->dont_mask)
635e0a43ddcSMiklos Szeredi 		mode &= ~current_umask();
636e0a43ddcSMiklos Szeredi 
6379e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
6389e6268dbSMiklos Szeredi 	inarg.mode = mode;
6399e6268dbSMiklos Szeredi 	inarg.rdev = new_encode_dev(rdev);
640e0a43ddcSMiklos Szeredi 	inarg.umask = current_umask();
641d5b48543SMiklos Szeredi 	args.opcode = FUSE_MKNOD;
642d5b48543SMiklos Szeredi 	args.in_numargs = 2;
643d5b48543SMiklos Szeredi 	args.in_args[0].size = sizeof(inarg);
644d5b48543SMiklos Szeredi 	args.in_args[0].value = &inarg;
645d5b48543SMiklos Szeredi 	args.in_args[1].size = entry->d_name.len + 1;
646d5b48543SMiklos Szeredi 	args.in_args[1].value = entry->d_name.name;
6477078187aSMiklos Szeredi 	return create_new_entry(fc, &args, dir, entry, mode);
6489e6268dbSMiklos Szeredi }
6499e6268dbSMiklos Szeredi 
6504acdaf27SAl Viro static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode,
651ebfc3b49SAl Viro 		       bool excl)
6529e6268dbSMiklos Szeredi {
6539e6268dbSMiklos Szeredi 	return fuse_mknod(dir, entry, mode, 0);
6549e6268dbSMiklos Szeredi }
6559e6268dbSMiklos Szeredi 
65618bb1db3SAl Viro static int fuse_mkdir(struct inode *dir, struct dentry *entry, umode_t mode)
6579e6268dbSMiklos Szeredi {
6589e6268dbSMiklos Szeredi 	struct fuse_mkdir_in inarg;
6599e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
6607078187aSMiklos Szeredi 	FUSE_ARGS(args);
6619e6268dbSMiklos Szeredi 
662e0a43ddcSMiklos Szeredi 	if (!fc->dont_mask)
663e0a43ddcSMiklos Szeredi 		mode &= ~current_umask();
664e0a43ddcSMiklos Szeredi 
6659e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
6669e6268dbSMiklos Szeredi 	inarg.mode = mode;
667e0a43ddcSMiklos Szeredi 	inarg.umask = current_umask();
668d5b48543SMiklos Szeredi 	args.opcode = FUSE_MKDIR;
669d5b48543SMiklos Szeredi 	args.in_numargs = 2;
670d5b48543SMiklos Szeredi 	args.in_args[0].size = sizeof(inarg);
671d5b48543SMiklos Szeredi 	args.in_args[0].value = &inarg;
672d5b48543SMiklos Szeredi 	args.in_args[1].size = entry->d_name.len + 1;
673d5b48543SMiklos Szeredi 	args.in_args[1].value = entry->d_name.name;
6747078187aSMiklos Szeredi 	return create_new_entry(fc, &args, dir, entry, S_IFDIR);
6759e6268dbSMiklos Szeredi }
6769e6268dbSMiklos Szeredi 
6779e6268dbSMiklos Szeredi static int fuse_symlink(struct inode *dir, struct dentry *entry,
6789e6268dbSMiklos Szeredi 			const char *link)
6799e6268dbSMiklos Szeredi {
6809e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
6819e6268dbSMiklos Szeredi 	unsigned len = strlen(link) + 1;
6827078187aSMiklos Szeredi 	FUSE_ARGS(args);
6839e6268dbSMiklos Szeredi 
684d5b48543SMiklos Szeredi 	args.opcode = FUSE_SYMLINK;
685d5b48543SMiklos Szeredi 	args.in_numargs = 2;
686d5b48543SMiklos Szeredi 	args.in_args[0].size = entry->d_name.len + 1;
687d5b48543SMiklos Szeredi 	args.in_args[0].value = entry->d_name.name;
688d5b48543SMiklos Szeredi 	args.in_args[1].size = len;
689d5b48543SMiklos Szeredi 	args.in_args[1].value = link;
6907078187aSMiklos Szeredi 	return create_new_entry(fc, &args, dir, entry, S_IFLNK);
6919e6268dbSMiklos Szeredi }
6929e6268dbSMiklos Szeredi 
693703c7362SSeth Forshee void fuse_update_ctime(struct inode *inode)
69431f3267bSMaxim Patlasov {
69531f3267bSMaxim Patlasov 	if (!IS_NOCMTIME(inode)) {
696c2050a45SDeepa Dinamani 		inode->i_ctime = current_time(inode);
69731f3267bSMaxim Patlasov 		mark_inode_dirty_sync(inode);
69831f3267bSMaxim Patlasov 	}
69931f3267bSMaxim Patlasov }
70031f3267bSMaxim Patlasov 
7019e6268dbSMiklos Szeredi static int fuse_unlink(struct inode *dir, struct dentry *entry)
7029e6268dbSMiklos Szeredi {
7039e6268dbSMiklos Szeredi 	int err;
7049e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
7057078187aSMiklos Szeredi 	FUSE_ARGS(args);
7069e6268dbSMiklos Szeredi 
707d5b48543SMiklos Szeredi 	args.opcode = FUSE_UNLINK;
708d5b48543SMiklos Szeredi 	args.nodeid = get_node_id(dir);
709d5b48543SMiklos Szeredi 	args.in_numargs = 1;
710d5b48543SMiklos Szeredi 	args.in_args[0].size = entry->d_name.len + 1;
711d5b48543SMiklos Szeredi 	args.in_args[0].value = entry->d_name.name;
7127078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
7139e6268dbSMiklos Szeredi 	if (!err) {
7142b0143b5SDavid Howells 		struct inode *inode = d_inode(entry);
715ac45d613SMiklos Szeredi 		struct fuse_inode *fi = get_fuse_inode(inode);
7169e6268dbSMiklos Szeredi 
717f15ecfefSKirill Tkhai 		spin_lock(&fi->lock);
7184510d86fSKirill Tkhai 		fi->attr_version = atomic64_inc_return(&fc->attr_version);
719dfca7cebSMiklos Szeredi 		/*
720dfca7cebSMiklos Szeredi 		 * If i_nlink == 0 then unlink doesn't make sense, yet this can
721dfca7cebSMiklos Szeredi 		 * happen if userspace filesystem is careless.  It would be
722dfca7cebSMiklos Szeredi 		 * difficult to enforce correct nlink usage so just ignore this
723dfca7cebSMiklos Szeredi 		 * condition here
724dfca7cebSMiklos Szeredi 		 */
725dfca7cebSMiklos Szeredi 		if (inode->i_nlink > 0)
726ac45d613SMiklos Szeredi 			drop_nlink(inode);
727f15ecfefSKirill Tkhai 		spin_unlock(&fi->lock);
7289e6268dbSMiklos Szeredi 		fuse_invalidate_attr(inode);
729261aaba7SMiklos Szeredi 		fuse_dir_changed(dir);
7308cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
73131f3267bSMaxim Patlasov 		fuse_update_ctime(inode);
7329e6268dbSMiklos Szeredi 	} else if (err == -EINTR)
7339e6268dbSMiklos Szeredi 		fuse_invalidate_entry(entry);
7349e6268dbSMiklos Szeredi 	return err;
7359e6268dbSMiklos Szeredi }
7369e6268dbSMiklos Szeredi 
7379e6268dbSMiklos Szeredi static int fuse_rmdir(struct inode *dir, struct dentry *entry)
7389e6268dbSMiklos Szeredi {
7399e6268dbSMiklos Szeredi 	int err;
7409e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
7417078187aSMiklos Szeredi 	FUSE_ARGS(args);
7429e6268dbSMiklos Szeredi 
743d5b48543SMiklos Szeredi 	args.opcode = FUSE_RMDIR;
744d5b48543SMiklos Szeredi 	args.nodeid = get_node_id(dir);
745d5b48543SMiklos Szeredi 	args.in_numargs = 1;
746d5b48543SMiklos Szeredi 	args.in_args[0].size = entry->d_name.len + 1;
747d5b48543SMiklos Szeredi 	args.in_args[0].value = entry->d_name.name;
7487078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
7499e6268dbSMiklos Szeredi 	if (!err) {
7502b0143b5SDavid Howells 		clear_nlink(d_inode(entry));
751261aaba7SMiklos Szeredi 		fuse_dir_changed(dir);
7528cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
7539e6268dbSMiklos Szeredi 	} else if (err == -EINTR)
7549e6268dbSMiklos Szeredi 		fuse_invalidate_entry(entry);
7559e6268dbSMiklos Szeredi 	return err;
7569e6268dbSMiklos Szeredi }
7579e6268dbSMiklos Szeredi 
7581560c974SMiklos Szeredi static int fuse_rename_common(struct inode *olddir, struct dentry *oldent,
7591560c974SMiklos Szeredi 			      struct inode *newdir, struct dentry *newent,
7601560c974SMiklos Szeredi 			      unsigned int flags, int opcode, size_t argsize)
7619e6268dbSMiklos Szeredi {
7629e6268dbSMiklos Szeredi 	int err;
7631560c974SMiklos Szeredi 	struct fuse_rename2_in inarg;
7649e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(olddir);
7657078187aSMiklos Szeredi 	FUSE_ARGS(args);
7669e6268dbSMiklos Szeredi 
7671560c974SMiklos Szeredi 	memset(&inarg, 0, argsize);
7689e6268dbSMiklos Szeredi 	inarg.newdir = get_node_id(newdir);
7691560c974SMiklos Szeredi 	inarg.flags = flags;
770d5b48543SMiklos Szeredi 	args.opcode = opcode;
771d5b48543SMiklos Szeredi 	args.nodeid = get_node_id(olddir);
772d5b48543SMiklos Szeredi 	args.in_numargs = 3;
773d5b48543SMiklos Szeredi 	args.in_args[0].size = argsize;
774d5b48543SMiklos Szeredi 	args.in_args[0].value = &inarg;
775d5b48543SMiklos Szeredi 	args.in_args[1].size = oldent->d_name.len + 1;
776d5b48543SMiklos Szeredi 	args.in_args[1].value = oldent->d_name.name;
777d5b48543SMiklos Szeredi 	args.in_args[2].size = newent->d_name.len + 1;
778d5b48543SMiklos Szeredi 	args.in_args[2].value = newent->d_name.name;
7797078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
7809e6268dbSMiklos Szeredi 	if (!err) {
78108b63307SMiklos Szeredi 		/* ctime changes */
7822b0143b5SDavid Howells 		fuse_invalidate_attr(d_inode(oldent));
7832b0143b5SDavid Howells 		fuse_update_ctime(d_inode(oldent));
78408b63307SMiklos Szeredi 
7851560c974SMiklos Szeredi 		if (flags & RENAME_EXCHANGE) {
7862b0143b5SDavid Howells 			fuse_invalidate_attr(d_inode(newent));
7872b0143b5SDavid Howells 			fuse_update_ctime(d_inode(newent));
7881560c974SMiklos Szeredi 		}
7891560c974SMiklos Szeredi 
790261aaba7SMiklos Szeredi 		fuse_dir_changed(olddir);
7919e6268dbSMiklos Szeredi 		if (olddir != newdir)
792261aaba7SMiklos Szeredi 			fuse_dir_changed(newdir);
7938cbdf1e6SMiklos Szeredi 
7948cbdf1e6SMiklos Szeredi 		/* newent will end up negative */
7952b0143b5SDavid Howells 		if (!(flags & RENAME_EXCHANGE) && d_really_is_positive(newent)) {
7962b0143b5SDavid Howells 			fuse_invalidate_attr(d_inode(newent));
7978cbdf1e6SMiklos Szeredi 			fuse_invalidate_entry_cache(newent);
7982b0143b5SDavid Howells 			fuse_update_ctime(d_inode(newent));
7995219f346SMiklos Szeredi 		}
8009e6268dbSMiklos Szeredi 	} else if (err == -EINTR) {
8019e6268dbSMiklos Szeredi 		/* If request was interrupted, DEITY only knows if the
8029e6268dbSMiklos Szeredi 		   rename actually took place.  If the invalidation
8039e6268dbSMiklos Szeredi 		   fails (e.g. some process has CWD under the renamed
8049e6268dbSMiklos Szeredi 		   directory), then there can be inconsistency between
8059e6268dbSMiklos Szeredi 		   the dcache and the real filesystem.  Tough luck. */
8069e6268dbSMiklos Szeredi 		fuse_invalidate_entry(oldent);
8072b0143b5SDavid Howells 		if (d_really_is_positive(newent))
8089e6268dbSMiklos Szeredi 			fuse_invalidate_entry(newent);
8099e6268dbSMiklos Szeredi 	}
8109e6268dbSMiklos Szeredi 
8119e6268dbSMiklos Szeredi 	return err;
8129e6268dbSMiklos Szeredi }
8139e6268dbSMiklos Szeredi 
8141560c974SMiklos Szeredi static int fuse_rename2(struct inode *olddir, struct dentry *oldent,
8151560c974SMiklos Szeredi 			struct inode *newdir, struct dentry *newent,
8161560c974SMiklos Szeredi 			unsigned int flags)
8171560c974SMiklos Szeredi {
8181560c974SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(olddir);
8191560c974SMiklos Szeredi 	int err;
8201560c974SMiklos Szeredi 
821*519525faSVivek Goyal 	if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT))
8221560c974SMiklos Szeredi 		return -EINVAL;
8231560c974SMiklos Szeredi 
8244237ba43SMiklos Szeredi 	if (flags) {
8251560c974SMiklos Szeredi 		if (fc->no_rename2 || fc->minor < 23)
8261560c974SMiklos Szeredi 			return -EINVAL;
8271560c974SMiklos Szeredi 
8281560c974SMiklos Szeredi 		err = fuse_rename_common(olddir, oldent, newdir, newent, flags,
8294237ba43SMiklos Szeredi 					 FUSE_RENAME2,
8304237ba43SMiklos Szeredi 					 sizeof(struct fuse_rename2_in));
8311560c974SMiklos Szeredi 		if (err == -ENOSYS) {
8321560c974SMiklos Szeredi 			fc->no_rename2 = 1;
8331560c974SMiklos Szeredi 			err = -EINVAL;
8341560c974SMiklos Szeredi 		}
8354237ba43SMiklos Szeredi 	} else {
8364237ba43SMiklos Szeredi 		err = fuse_rename_common(olddir, oldent, newdir, newent, 0,
8374237ba43SMiklos Szeredi 					 FUSE_RENAME,
8384237ba43SMiklos Szeredi 					 sizeof(struct fuse_rename_in));
8394237ba43SMiklos Szeredi 	}
8401560c974SMiklos Szeredi 
8414237ba43SMiklos Szeredi 	return err;
8424237ba43SMiklos Szeredi }
8434237ba43SMiklos Szeredi 
8449e6268dbSMiklos Szeredi static int fuse_link(struct dentry *entry, struct inode *newdir,
8459e6268dbSMiklos Szeredi 		     struct dentry *newent)
8469e6268dbSMiklos Szeredi {
8479e6268dbSMiklos Szeredi 	int err;
8489e6268dbSMiklos Szeredi 	struct fuse_link_in inarg;
8492b0143b5SDavid Howells 	struct inode *inode = d_inode(entry);
8509e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
8517078187aSMiklos Szeredi 	FUSE_ARGS(args);
8529e6268dbSMiklos Szeredi 
8539e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
8549e6268dbSMiklos Szeredi 	inarg.oldnodeid = get_node_id(inode);
855d5b48543SMiklos Szeredi 	args.opcode = FUSE_LINK;
856d5b48543SMiklos Szeredi 	args.in_numargs = 2;
857d5b48543SMiklos Szeredi 	args.in_args[0].size = sizeof(inarg);
858d5b48543SMiklos Szeredi 	args.in_args[0].value = &inarg;
859d5b48543SMiklos Szeredi 	args.in_args[1].size = newent->d_name.len + 1;
860d5b48543SMiklos Szeredi 	args.in_args[1].value = newent->d_name.name;
8617078187aSMiklos Szeredi 	err = create_new_entry(fc, &args, newdir, newent, inode->i_mode);
8629e6268dbSMiklos Szeredi 	/* Contrary to "normal" filesystems it can happen that link
8639e6268dbSMiklos Szeredi 	   makes two "logical" inodes point to the same "physical"
8649e6268dbSMiklos Szeredi 	   inode.  We invalidate the attributes of the old one, so it
8659e6268dbSMiklos Szeredi 	   will reflect changes in the backing inode (link count,
8669e6268dbSMiklos Szeredi 	   etc.)
8679e6268dbSMiklos Szeredi 	*/
868ac45d613SMiklos Szeredi 	if (!err) {
869ac45d613SMiklos Szeredi 		struct fuse_inode *fi = get_fuse_inode(inode);
870ac45d613SMiklos Szeredi 
871f15ecfefSKirill Tkhai 		spin_lock(&fi->lock);
8724510d86fSKirill Tkhai 		fi->attr_version = atomic64_inc_return(&fc->attr_version);
873c634da71SMiklos Szeredi 		if (likely(inode->i_nlink < UINT_MAX))
874ac45d613SMiklos Szeredi 			inc_nlink(inode);
875f15ecfefSKirill Tkhai 		spin_unlock(&fi->lock);
8769e6268dbSMiklos Szeredi 		fuse_invalidate_attr(inode);
87731f3267bSMaxim Patlasov 		fuse_update_ctime(inode);
878ac45d613SMiklos Szeredi 	} else if (err == -EINTR) {
879ac45d613SMiklos Szeredi 		fuse_invalidate_attr(inode);
880ac45d613SMiklos Szeredi 	}
8819e6268dbSMiklos Szeredi 	return err;
8829e6268dbSMiklos Szeredi }
8839e6268dbSMiklos Szeredi 
8841fb69e78SMiklos Szeredi static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
8851fb69e78SMiklos Szeredi 			  struct kstat *stat)
8861fb69e78SMiklos Szeredi {
887203627bbSMiklos Szeredi 	unsigned int blkbits;
8888373200bSPavel Emelyanov 	struct fuse_conn *fc = get_fuse_conn(inode);
8898373200bSPavel Emelyanov 
8908373200bSPavel Emelyanov 	/* see the comment in fuse_change_attributes() */
891b0aa7606SMaxim Patlasov 	if (fc->writeback_cache && S_ISREG(inode->i_mode)) {
8928373200bSPavel Emelyanov 		attr->size = i_size_read(inode);
893b0aa7606SMaxim Patlasov 		attr->mtime = inode->i_mtime.tv_sec;
894b0aa7606SMaxim Patlasov 		attr->mtimensec = inode->i_mtime.tv_nsec;
89531f3267bSMaxim Patlasov 		attr->ctime = inode->i_ctime.tv_sec;
89631f3267bSMaxim Patlasov 		attr->ctimensec = inode->i_ctime.tv_nsec;
897b0aa7606SMaxim Patlasov 	}
898203627bbSMiklos Szeredi 
8991fb69e78SMiklos Szeredi 	stat->dev = inode->i_sb->s_dev;
9001fb69e78SMiklos Szeredi 	stat->ino = attr->ino;
9011fb69e78SMiklos Szeredi 	stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
9021fb69e78SMiklos Szeredi 	stat->nlink = attr->nlink;
9038cb08329SEric W. Biederman 	stat->uid = make_kuid(fc->user_ns, attr->uid);
9048cb08329SEric W. Biederman 	stat->gid = make_kgid(fc->user_ns, attr->gid);
9051fb69e78SMiklos Szeredi 	stat->rdev = inode->i_rdev;
9061fb69e78SMiklos Szeredi 	stat->atime.tv_sec = attr->atime;
9071fb69e78SMiklos Szeredi 	stat->atime.tv_nsec = attr->atimensec;
9081fb69e78SMiklos Szeredi 	stat->mtime.tv_sec = attr->mtime;
9091fb69e78SMiklos Szeredi 	stat->mtime.tv_nsec = attr->mtimensec;
9101fb69e78SMiklos Szeredi 	stat->ctime.tv_sec = attr->ctime;
9111fb69e78SMiklos Szeredi 	stat->ctime.tv_nsec = attr->ctimensec;
9121fb69e78SMiklos Szeredi 	stat->size = attr->size;
9131fb69e78SMiklos Szeredi 	stat->blocks = attr->blocks;
914203627bbSMiklos Szeredi 
915203627bbSMiklos Szeredi 	if (attr->blksize != 0)
916203627bbSMiklos Szeredi 		blkbits = ilog2(attr->blksize);
917203627bbSMiklos Szeredi 	else
918203627bbSMiklos Szeredi 		blkbits = inode->i_sb->s_blocksize_bits;
919203627bbSMiklos Szeredi 
920203627bbSMiklos Szeredi 	stat->blksize = 1 << blkbits;
9211fb69e78SMiklos Szeredi }
9221fb69e78SMiklos Szeredi 
923c79e322fSMiklos Szeredi static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
924c79e322fSMiklos Szeredi 			   struct file *file)
925e5e5558eSMiklos Szeredi {
926e5e5558eSMiklos Szeredi 	int err;
927c79e322fSMiklos Szeredi 	struct fuse_getattr_in inarg;
928c79e322fSMiklos Szeredi 	struct fuse_attr_out outarg;
929e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
9307078187aSMiklos Szeredi 	FUSE_ARGS(args);
9311fb69e78SMiklos Szeredi 	u64 attr_version;
9321fb69e78SMiklos Szeredi 
9337dca9fd3SMiklos Szeredi 	attr_version = fuse_get_attr_version(fc);
9341fb69e78SMiklos Szeredi 
935c79e322fSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
9360e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
937c79e322fSMiklos Szeredi 	/* Directories have separate file-handle space */
938c79e322fSMiklos Szeredi 	if (file && S_ISREG(inode->i_mode)) {
939c79e322fSMiklos Szeredi 		struct fuse_file *ff = file->private_data;
940c79e322fSMiklos Szeredi 
941c79e322fSMiklos Szeredi 		inarg.getattr_flags |= FUSE_GETATTR_FH;
942c79e322fSMiklos Szeredi 		inarg.fh = ff->fh;
943c79e322fSMiklos Szeredi 	}
944d5b48543SMiklos Szeredi 	args.opcode = FUSE_GETATTR;
945d5b48543SMiklos Szeredi 	args.nodeid = get_node_id(inode);
946d5b48543SMiklos Szeredi 	args.in_numargs = 1;
947d5b48543SMiklos Szeredi 	args.in_args[0].size = sizeof(inarg);
948d5b48543SMiklos Szeredi 	args.in_args[0].value = &inarg;
949d5b48543SMiklos Szeredi 	args.out_numargs = 1;
950d5b48543SMiklos Szeredi 	args.out_args[0].size = sizeof(outarg);
951d5b48543SMiklos Szeredi 	args.out_args[0].value = &outarg;
9527078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
953e5e5558eSMiklos Szeredi 	if (!err) {
954eb59bd17SMiklos Szeredi 		if (fuse_invalid_attr(&outarg.attr) ||
955eb59bd17SMiklos Szeredi 		    (inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
956e5e5558eSMiklos Szeredi 			make_bad_inode(inode);
957e5e5558eSMiklos Szeredi 			err = -EIO;
958e5e5558eSMiklos Szeredi 		} else {
959c79e322fSMiklos Szeredi 			fuse_change_attributes(inode, &outarg.attr,
960c79e322fSMiklos Szeredi 					       attr_timeout(&outarg),
9611fb69e78SMiklos Szeredi 					       attr_version);
9621fb69e78SMiklos Szeredi 			if (stat)
963c79e322fSMiklos Szeredi 				fuse_fillattr(inode, &outarg.attr, stat);
964e5e5558eSMiklos Szeredi 		}
965e5e5558eSMiklos Szeredi 	}
966e5e5558eSMiklos Szeredi 	return err;
967e5e5558eSMiklos Szeredi }
968e5e5558eSMiklos Szeredi 
9695b97eeacSMiklos Szeredi static int fuse_update_get_attr(struct inode *inode, struct file *file,
9702f1e8196SMiklos Szeredi 				struct kstat *stat, u32 request_mask,
9712f1e8196SMiklos Szeredi 				unsigned int flags)
972bcb4be80SMiklos Szeredi {
973bcb4be80SMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
9745b97eeacSMiklos Szeredi 	int err = 0;
975bf5c1898SMiklos Szeredi 	bool sync;
976bcb4be80SMiklos Szeredi 
977bf5c1898SMiklos Szeredi 	if (flags & AT_STATX_FORCE_SYNC)
978bf5c1898SMiklos Szeredi 		sync = true;
979bf5c1898SMiklos Szeredi 	else if (flags & AT_STATX_DONT_SYNC)
980bf5c1898SMiklos Szeredi 		sync = false;
9812f1e8196SMiklos Szeredi 	else if (request_mask & READ_ONCE(fi->inval_mask))
9822f1e8196SMiklos Szeredi 		sync = true;
983bf5c1898SMiklos Szeredi 	else
984bf5c1898SMiklos Szeredi 		sync = time_before64(fi->i_time, get_jiffies_64());
985bf5c1898SMiklos Szeredi 
986bf5c1898SMiklos Szeredi 	if (sync) {
98760bcc88aSSeth Forshee 		forget_all_cached_acls(inode);
988bcb4be80SMiklos Szeredi 		err = fuse_do_getattr(inode, stat, file);
9895b97eeacSMiklos Szeredi 	} else if (stat) {
990bcb4be80SMiklos Szeredi 		generic_fillattr(inode, stat);
991bcb4be80SMiklos Szeredi 		stat->mode = fi->orig_i_mode;
99245c72cd7SPavel Shilovsky 		stat->ino = fi->orig_ino;
993bcb4be80SMiklos Szeredi 	}
994bcb4be80SMiklos Szeredi 
995bcb4be80SMiklos Szeredi 	return err;
996bcb4be80SMiklos Szeredi }
997bcb4be80SMiklos Szeredi 
9985b97eeacSMiklos Szeredi int fuse_update_attributes(struct inode *inode, struct file *file)
9995b97eeacSMiklos Szeredi {
1000802dc049SMiklos Szeredi 	/* Do *not* need to get atime for internal purposes */
1001802dc049SMiklos Szeredi 	return fuse_update_get_attr(inode, file, NULL,
1002802dc049SMiklos Szeredi 				    STATX_BASIC_STATS & ~STATX_ATIME, 0);
10035b97eeacSMiklos Szeredi }
10045b97eeacSMiklos Szeredi 
10053b463ae0SJohn Muir int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid,
1006451d0f59SJohn Muir 			     u64 child_nodeid, struct qstr *name)
10073b463ae0SJohn Muir {
10083b463ae0SJohn Muir 	int err = -ENOTDIR;
10093b463ae0SJohn Muir 	struct inode *parent;
10103b463ae0SJohn Muir 	struct dentry *dir;
10113b463ae0SJohn Muir 	struct dentry *entry;
10123b463ae0SJohn Muir 
10133b463ae0SJohn Muir 	parent = ilookup5(sb, parent_nodeid, fuse_inode_eq, &parent_nodeid);
10143b463ae0SJohn Muir 	if (!parent)
10153b463ae0SJohn Muir 		return -ENOENT;
10163b463ae0SJohn Muir 
10175955102cSAl Viro 	inode_lock(parent);
10183b463ae0SJohn Muir 	if (!S_ISDIR(parent->i_mode))
10193b463ae0SJohn Muir 		goto unlock;
10203b463ae0SJohn Muir 
10213b463ae0SJohn Muir 	err = -ENOENT;
10223b463ae0SJohn Muir 	dir = d_find_alias(parent);
10233b463ae0SJohn Muir 	if (!dir)
10243b463ae0SJohn Muir 		goto unlock;
10253b463ae0SJohn Muir 
10268387ff25SLinus Torvalds 	name->hash = full_name_hash(dir, name->name, name->len);
10273b463ae0SJohn Muir 	entry = d_lookup(dir, name);
10283b463ae0SJohn Muir 	dput(dir);
10293b463ae0SJohn Muir 	if (!entry)
10303b463ae0SJohn Muir 		goto unlock;
10313b463ae0SJohn Muir 
1032261aaba7SMiklos Szeredi 	fuse_dir_changed(parent);
10333b463ae0SJohn Muir 	fuse_invalidate_entry(entry);
1034451d0f59SJohn Muir 
10352b0143b5SDavid Howells 	if (child_nodeid != 0 && d_really_is_positive(entry)) {
10365955102cSAl Viro 		inode_lock(d_inode(entry));
10372b0143b5SDavid Howells 		if (get_node_id(d_inode(entry)) != child_nodeid) {
1038451d0f59SJohn Muir 			err = -ENOENT;
1039451d0f59SJohn Muir 			goto badentry;
1040451d0f59SJohn Muir 		}
1041451d0f59SJohn Muir 		if (d_mountpoint(entry)) {
1042451d0f59SJohn Muir 			err = -EBUSY;
1043451d0f59SJohn Muir 			goto badentry;
1044451d0f59SJohn Muir 		}
1045e36cb0b8SDavid Howells 		if (d_is_dir(entry)) {
1046451d0f59SJohn Muir 			shrink_dcache_parent(entry);
1047451d0f59SJohn Muir 			if (!simple_empty(entry)) {
1048451d0f59SJohn Muir 				err = -ENOTEMPTY;
1049451d0f59SJohn Muir 				goto badentry;
1050451d0f59SJohn Muir 			}
10512b0143b5SDavid Howells 			d_inode(entry)->i_flags |= S_DEAD;
1052451d0f59SJohn Muir 		}
1053451d0f59SJohn Muir 		dont_mount(entry);
10542b0143b5SDavid Howells 		clear_nlink(d_inode(entry));
10553b463ae0SJohn Muir 		err = 0;
1056451d0f59SJohn Muir  badentry:
10575955102cSAl Viro 		inode_unlock(d_inode(entry));
1058451d0f59SJohn Muir 		if (!err)
1059451d0f59SJohn Muir 			d_delete(entry);
1060451d0f59SJohn Muir 	} else {
1061451d0f59SJohn Muir 		err = 0;
1062451d0f59SJohn Muir 	}
1063451d0f59SJohn Muir 	dput(entry);
10643b463ae0SJohn Muir 
10653b463ae0SJohn Muir  unlock:
10665955102cSAl Viro 	inode_unlock(parent);
10673b463ae0SJohn Muir 	iput(parent);
10683b463ae0SJohn Muir 	return err;
10693b463ae0SJohn Muir }
10703b463ae0SJohn Muir 
107187729a55SMiklos Szeredi /*
107287729a55SMiklos Szeredi  * Calling into a user-controlled filesystem gives the filesystem
1073c2132c1bSAnatol Pomozov  * daemon ptrace-like capabilities over the current process.  This
107487729a55SMiklos Szeredi  * means, that the filesystem daemon is able to record the exact
107587729a55SMiklos Szeredi  * filesystem operations performed, and can also control the behavior
107687729a55SMiklos Szeredi  * of the requester process in otherwise impossible ways.  For example
107787729a55SMiklos Szeredi  * it can delay the operation for arbitrary length of time allowing
107887729a55SMiklos Szeredi  * DoS against the requester.
107987729a55SMiklos Szeredi  *
108087729a55SMiklos Szeredi  * For this reason only those processes can call into the filesystem,
108187729a55SMiklos Szeredi  * for which the owner of the mount has ptrace privilege.  This
108287729a55SMiklos Szeredi  * excludes processes started by other users, suid or sgid processes.
108387729a55SMiklos Szeredi  */
1084c2132c1bSAnatol Pomozov int fuse_allow_current_process(struct fuse_conn *fc)
108587729a55SMiklos Szeredi {
1086c69e8d9cSDavid Howells 	const struct cred *cred;
1087c69e8d9cSDavid Howells 
108829433a29SMiklos Szeredi 	if (fc->allow_other)
108973f03c2bSSeth Forshee 		return current_in_userns(fc->user_ns);
109087729a55SMiklos Szeredi 
1091c2132c1bSAnatol Pomozov 	cred = current_cred();
1092499dcf20SEric W. Biederman 	if (uid_eq(cred->euid, fc->user_id) &&
1093499dcf20SEric W. Biederman 	    uid_eq(cred->suid, fc->user_id) &&
1094499dcf20SEric W. Biederman 	    uid_eq(cred->uid,  fc->user_id) &&
1095499dcf20SEric W. Biederman 	    gid_eq(cred->egid, fc->group_id) &&
1096499dcf20SEric W. Biederman 	    gid_eq(cred->sgid, fc->group_id) &&
1097499dcf20SEric W. Biederman 	    gid_eq(cred->gid,  fc->group_id))
1098c2132c1bSAnatol Pomozov 		return 1;
109987729a55SMiklos Szeredi 
1100c2132c1bSAnatol Pomozov 	return 0;
110187729a55SMiklos Szeredi }
110287729a55SMiklos Szeredi 
110331d40d74SMiklos Szeredi static int fuse_access(struct inode *inode, int mask)
110431d40d74SMiklos Szeredi {
110531d40d74SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
11067078187aSMiklos Szeredi 	FUSE_ARGS(args);
110731d40d74SMiklos Szeredi 	struct fuse_access_in inarg;
110831d40d74SMiklos Szeredi 	int err;
110931d40d74SMiklos Szeredi 
1110698fa1d1SMiklos Szeredi 	BUG_ON(mask & MAY_NOT_BLOCK);
1111698fa1d1SMiklos Szeredi 
111231d40d74SMiklos Szeredi 	if (fc->no_access)
111331d40d74SMiklos Szeredi 		return 0;
111431d40d74SMiklos Szeredi 
111531d40d74SMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
1116e6305c43SAl Viro 	inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC);
1117d5b48543SMiklos Szeredi 	args.opcode = FUSE_ACCESS;
1118d5b48543SMiklos Szeredi 	args.nodeid = get_node_id(inode);
1119d5b48543SMiklos Szeredi 	args.in_numargs = 1;
1120d5b48543SMiklos Szeredi 	args.in_args[0].size = sizeof(inarg);
1121d5b48543SMiklos Szeredi 	args.in_args[0].value = &inarg;
11227078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
112331d40d74SMiklos Szeredi 	if (err == -ENOSYS) {
112431d40d74SMiklos Szeredi 		fc->no_access = 1;
112531d40d74SMiklos Szeredi 		err = 0;
112631d40d74SMiklos Szeredi 	}
112731d40d74SMiklos Szeredi 	return err;
112831d40d74SMiklos Szeredi }
112931d40d74SMiklos Szeredi 
113010556cb2SAl Viro static int fuse_perm_getattr(struct inode *inode, int mask)
113119690ddbSMiklos Szeredi {
113210556cb2SAl Viro 	if (mask & MAY_NOT_BLOCK)
113319690ddbSMiklos Szeredi 		return -ECHILD;
113419690ddbSMiklos Szeredi 
113560bcc88aSSeth Forshee 	forget_all_cached_acls(inode);
113619690ddbSMiklos Szeredi 	return fuse_do_getattr(inode, NULL, NULL);
113719690ddbSMiklos Szeredi }
113819690ddbSMiklos Szeredi 
11396f9f1180SMiklos Szeredi /*
11406f9f1180SMiklos Szeredi  * Check permission.  The two basic access models of FUSE are:
11416f9f1180SMiklos Szeredi  *
11426f9f1180SMiklos Szeredi  * 1) Local access checking ('default_permissions' mount option) based
11436f9f1180SMiklos Szeredi  * on file mode.  This is the plain old disk filesystem permission
11446f9f1180SMiklos Szeredi  * modell.
11456f9f1180SMiklos Szeredi  *
11466f9f1180SMiklos Szeredi  * 2) "Remote" access checking, where server is responsible for
11476f9f1180SMiklos Szeredi  * checking permission in each inode operation.  An exception to this
11486f9f1180SMiklos Szeredi  * is if ->permission() was invoked from sys_access() in which case an
11496f9f1180SMiklos Szeredi  * access request is sent.  Execute permission is still checked
11506f9f1180SMiklos Szeredi  * locally based on file mode.
11516f9f1180SMiklos Szeredi  */
115210556cb2SAl Viro static int fuse_permission(struct inode *inode, int mask)
1153e5e5558eSMiklos Szeredi {
1154e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1155244f6385SMiklos Szeredi 	bool refreshed = false;
1156244f6385SMiklos Szeredi 	int err = 0;
1157e5e5558eSMiklos Szeredi 
1158c2132c1bSAnatol Pomozov 	if (!fuse_allow_current_process(fc))
1159e5e5558eSMiklos Szeredi 		return -EACCES;
1160244f6385SMiklos Szeredi 
1161244f6385SMiklos Szeredi 	/*
1162e8e96157SMiklos Szeredi 	 * If attributes are needed, refresh them before proceeding
1163244f6385SMiklos Szeredi 	 */
116429433a29SMiklos Szeredi 	if (fc->default_permissions ||
1165e8e96157SMiklos Szeredi 	    ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
116619690ddbSMiklos Szeredi 		struct fuse_inode *fi = get_fuse_inode(inode);
1167d233c7ddSMiklos Szeredi 		u32 perm_mask = STATX_MODE | STATX_UID | STATX_GID;
116819690ddbSMiklos Szeredi 
1169d233c7ddSMiklos Szeredi 		if (perm_mask & READ_ONCE(fi->inval_mask) ||
1170d233c7ddSMiklos Szeredi 		    time_before64(fi->i_time, get_jiffies_64())) {
117119690ddbSMiklos Szeredi 			refreshed = true;
117219690ddbSMiklos Szeredi 
117310556cb2SAl Viro 			err = fuse_perm_getattr(inode, mask);
1174244f6385SMiklos Szeredi 			if (err)
1175244f6385SMiklos Szeredi 				return err;
11761fb69e78SMiklos Szeredi 		}
117719690ddbSMiklos Szeredi 	}
1178244f6385SMiklos Szeredi 
117929433a29SMiklos Szeredi 	if (fc->default_permissions) {
11802830ba7fSAl Viro 		err = generic_permission(inode, mask);
11811e9a4ed9SMiklos Szeredi 
11821e9a4ed9SMiklos Szeredi 		/* If permission is denied, try to refresh file
11831e9a4ed9SMiklos Szeredi 		   attributes.  This is also needed, because the root
11841e9a4ed9SMiklos Szeredi 		   node will at first have no permissions */
1185244f6385SMiklos Szeredi 		if (err == -EACCES && !refreshed) {
118610556cb2SAl Viro 			err = fuse_perm_getattr(inode, mask);
11871e9a4ed9SMiklos Szeredi 			if (!err)
11882830ba7fSAl Viro 				err = generic_permission(inode, mask);
11891e9a4ed9SMiklos Szeredi 		}
11901e9a4ed9SMiklos Szeredi 
11916f9f1180SMiklos Szeredi 		/* Note: the opposite of the above test does not
11926f9f1180SMiklos Szeredi 		   exist.  So if permissions are revoked this won't be
11936f9f1180SMiklos Szeredi 		   noticed immediately, only after the attribute
11946f9f1180SMiklos Szeredi 		   timeout has expired */
11959cfcac81SEric Paris 	} else if (mask & (MAY_ACCESS | MAY_CHDIR)) {
1196e8e96157SMiklos Szeredi 		err = fuse_access(inode, mask);
1197e8e96157SMiklos Szeredi 	} else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
1198e8e96157SMiklos Szeredi 		if (!(inode->i_mode & S_IXUGO)) {
1199e8e96157SMiklos Szeredi 			if (refreshed)
1200e5e5558eSMiklos Szeredi 				return -EACCES;
120131d40d74SMiklos Szeredi 
120210556cb2SAl Viro 			err = fuse_perm_getattr(inode, mask);
1203e8e96157SMiklos Szeredi 			if (!err && !(inode->i_mode & S_IXUGO))
1204e8e96157SMiklos Szeredi 				return -EACCES;
1205e8e96157SMiklos Szeredi 		}
1206e5e5558eSMiklos Szeredi 	}
1207244f6385SMiklos Szeredi 	return err;
1208e5e5558eSMiklos Szeredi }
1209e5e5558eSMiklos Szeredi 
12105571f1e6SDan Schatzberg static int fuse_readlink_page(struct inode *inode, struct page *page)
1211e5e5558eSMiklos Szeredi {
1212e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
12134c29afecSMiklos Szeredi 	struct fuse_page_desc desc = { .length = PAGE_SIZE - 1 };
12144c29afecSMiklos Szeredi 	struct fuse_args_pages ap = {
12154c29afecSMiklos Szeredi 		.num_pages = 1,
12164c29afecSMiklos Szeredi 		.pages = &page,
12174c29afecSMiklos Szeredi 		.descs = &desc,
12184c29afecSMiklos Szeredi 	};
12194c29afecSMiklos Szeredi 	char *link;
12204c29afecSMiklos Szeredi 	ssize_t res;
1221e5e5558eSMiklos Szeredi 
12224c29afecSMiklos Szeredi 	ap.args.opcode = FUSE_READLINK;
12234c29afecSMiklos Szeredi 	ap.args.nodeid = get_node_id(inode);
12244c29afecSMiklos Szeredi 	ap.args.out_pages = true;
12254c29afecSMiklos Szeredi 	ap.args.out_argvar = true;
12264c29afecSMiklos Szeredi 	ap.args.page_zeroing = true;
12274c29afecSMiklos Szeredi 	ap.args.out_numargs = 1;
12284c29afecSMiklos Szeredi 	ap.args.out_args[0].size = desc.length;
12294c29afecSMiklos Szeredi 	res = fuse_simple_request(fc, &ap.args);
12306b255391SAl Viro 
1231451418fcSAndrew Gallagher 	fuse_invalidate_atime(inode);
12325571f1e6SDan Schatzberg 
12334c29afecSMiklos Szeredi 	if (res < 0)
12344c29afecSMiklos Szeredi 		return res;
12354c29afecSMiklos Szeredi 
12364c29afecSMiklos Szeredi 	if (WARN_ON(res >= PAGE_SIZE))
12374c29afecSMiklos Szeredi 		return -EIO;
12384c29afecSMiklos Szeredi 
12394c29afecSMiklos Szeredi 	link = page_address(page);
12404c29afecSMiklos Szeredi 	link[res] = '\0';
12414c29afecSMiklos Szeredi 
12424c29afecSMiklos Szeredi 	return 0;
12435571f1e6SDan Schatzberg }
12445571f1e6SDan Schatzberg 
12455571f1e6SDan Schatzberg static const char *fuse_get_link(struct dentry *dentry, struct inode *inode,
12465571f1e6SDan Schatzberg 				 struct delayed_call *callback)
12475571f1e6SDan Schatzberg {
12485571f1e6SDan Schatzberg 	struct fuse_conn *fc = get_fuse_conn(inode);
12495571f1e6SDan Schatzberg 	struct page *page;
12505571f1e6SDan Schatzberg 	int err;
12515571f1e6SDan Schatzberg 
12525571f1e6SDan Schatzberg 	err = -EIO;
12535571f1e6SDan Schatzberg 	if (is_bad_inode(inode))
12545571f1e6SDan Schatzberg 		goto out_err;
12555571f1e6SDan Schatzberg 
12565571f1e6SDan Schatzberg 	if (fc->cache_symlinks)
12575571f1e6SDan Schatzberg 		return page_get_link(dentry, inode, callback);
12585571f1e6SDan Schatzberg 
12595571f1e6SDan Schatzberg 	err = -ECHILD;
12605571f1e6SDan Schatzberg 	if (!dentry)
12615571f1e6SDan Schatzberg 		goto out_err;
12625571f1e6SDan Schatzberg 
12635571f1e6SDan Schatzberg 	page = alloc_page(GFP_KERNEL);
12645571f1e6SDan Schatzberg 	err = -ENOMEM;
12655571f1e6SDan Schatzberg 	if (!page)
12665571f1e6SDan Schatzberg 		goto out_err;
12675571f1e6SDan Schatzberg 
12685571f1e6SDan Schatzberg 	err = fuse_readlink_page(inode, page);
12695571f1e6SDan Schatzberg 	if (err) {
12705571f1e6SDan Schatzberg 		__free_page(page);
12715571f1e6SDan Schatzberg 		goto out_err;
12725571f1e6SDan Schatzberg 	}
12735571f1e6SDan Schatzberg 
12745571f1e6SDan Schatzberg 	set_delayed_call(callback, page_put_link, page);
12755571f1e6SDan Schatzberg 
12765571f1e6SDan Schatzberg 	return page_address(page);
12775571f1e6SDan Schatzberg 
12785571f1e6SDan Schatzberg out_err:
12795571f1e6SDan Schatzberg 	return ERR_PTR(err);
1280e5e5558eSMiklos Szeredi }
1281e5e5558eSMiklos Szeredi 
1282e5e5558eSMiklos Szeredi static int fuse_dir_open(struct inode *inode, struct file *file)
1283e5e5558eSMiklos Szeredi {
128491fe96b4SMiklos Szeredi 	return fuse_open_common(inode, file, true);
1285e5e5558eSMiklos Szeredi }
1286e5e5558eSMiklos Szeredi 
1287e5e5558eSMiklos Szeredi static int fuse_dir_release(struct inode *inode, struct file *file)
1288e5e5558eSMiklos Szeredi {
12892e64ff15SChad Austin 	fuse_release_common(file, true);
12908b0797a4SMiklos Szeredi 
12918b0797a4SMiklos Szeredi 	return 0;
1292e5e5558eSMiklos Szeredi }
1293e5e5558eSMiklos Szeredi 
129402c24a82SJosef Bacik static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end,
129502c24a82SJosef Bacik 			  int datasync)
129682547981SMiklos Szeredi {
1297a9c2d1e8SMiklos Szeredi 	struct inode *inode = file->f_mapping->host;
1298a9c2d1e8SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1299a9c2d1e8SMiklos Szeredi 	int err;
1300a9c2d1e8SMiklos Szeredi 
1301a9c2d1e8SMiklos Szeredi 	if (is_bad_inode(inode))
1302a9c2d1e8SMiklos Szeredi 		return -EIO;
1303a9c2d1e8SMiklos Szeredi 
1304a9c2d1e8SMiklos Szeredi 	if (fc->no_fsyncdir)
1305a9c2d1e8SMiklos Szeredi 		return 0;
1306a9c2d1e8SMiklos Szeredi 
1307a9c2d1e8SMiklos Szeredi 	inode_lock(inode);
1308a9c2d1e8SMiklos Szeredi 	err = fuse_fsync_common(file, start, end, datasync, FUSE_FSYNCDIR);
1309a9c2d1e8SMiklos Szeredi 	if (err == -ENOSYS) {
1310a9c2d1e8SMiklos Szeredi 		fc->no_fsyncdir = 1;
1311a9c2d1e8SMiklos Szeredi 		err = 0;
1312a9c2d1e8SMiklos Szeredi 	}
1313a9c2d1e8SMiklos Szeredi 	inode_unlock(inode);
1314a9c2d1e8SMiklos Szeredi 
1315a9c2d1e8SMiklos Szeredi 	return err;
131682547981SMiklos Szeredi }
131782547981SMiklos Szeredi 
1318b18da0c5SMiklos Szeredi static long fuse_dir_ioctl(struct file *file, unsigned int cmd,
1319b18da0c5SMiklos Szeredi 			    unsigned long arg)
1320b18da0c5SMiklos Szeredi {
1321b18da0c5SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1322b18da0c5SMiklos Szeredi 
1323b18da0c5SMiklos Szeredi 	/* FUSE_IOCTL_DIR only supported for API version >= 7.18 */
1324b18da0c5SMiklos Szeredi 	if (fc->minor < 18)
1325b18da0c5SMiklos Szeredi 		return -ENOTTY;
1326b18da0c5SMiklos Szeredi 
1327b18da0c5SMiklos Szeredi 	return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR);
1328b18da0c5SMiklos Szeredi }
1329b18da0c5SMiklos Szeredi 
1330b18da0c5SMiklos Szeredi static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd,
1331b18da0c5SMiklos Szeredi 				   unsigned long arg)
1332b18da0c5SMiklos Szeredi {
1333b18da0c5SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1334b18da0c5SMiklos Szeredi 
1335b18da0c5SMiklos Szeredi 	if (fc->minor < 18)
1336b18da0c5SMiklos Szeredi 		return -ENOTTY;
1337b18da0c5SMiklos Szeredi 
1338b18da0c5SMiklos Szeredi 	return fuse_ioctl_common(file, cmd, arg,
1339b18da0c5SMiklos Szeredi 				 FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR);
1340b18da0c5SMiklos Szeredi }
1341b18da0c5SMiklos Szeredi 
1342b0aa7606SMaxim Patlasov static bool update_mtime(unsigned ivalid, bool trust_local_mtime)
134317637cbaSMiklos Szeredi {
134417637cbaSMiklos Szeredi 	/* Always update if mtime is explicitly set  */
134517637cbaSMiklos Szeredi 	if (ivalid & ATTR_MTIME_SET)
134617637cbaSMiklos Szeredi 		return true;
134717637cbaSMiklos Szeredi 
1348b0aa7606SMaxim Patlasov 	/* Or if kernel i_mtime is the official one */
1349b0aa7606SMaxim Patlasov 	if (trust_local_mtime)
1350b0aa7606SMaxim Patlasov 		return true;
1351b0aa7606SMaxim Patlasov 
135217637cbaSMiklos Szeredi 	/* If it's an open(O_TRUNC) or an ftruncate(), don't update */
135317637cbaSMiklos Szeredi 	if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
135417637cbaSMiklos Szeredi 		return false;
135517637cbaSMiklos Szeredi 
135617637cbaSMiklos Szeredi 	/* In all other cases update */
135717637cbaSMiklos Szeredi 	return true;
135817637cbaSMiklos Szeredi }
135917637cbaSMiklos Szeredi 
13608cb08329SEric W. Biederman static void iattr_to_fattr(struct fuse_conn *fc, struct iattr *iattr,
13618cb08329SEric W. Biederman 			   struct fuse_setattr_in *arg, bool trust_local_cmtime)
13629e6268dbSMiklos Szeredi {
13639e6268dbSMiklos Szeredi 	unsigned ivalid = iattr->ia_valid;
13649e6268dbSMiklos Szeredi 
13659e6268dbSMiklos Szeredi 	if (ivalid & ATTR_MODE)
1366befc649cSMiklos Szeredi 		arg->valid |= FATTR_MODE,   arg->mode = iattr->ia_mode;
13679e6268dbSMiklos Szeredi 	if (ivalid & ATTR_UID)
13688cb08329SEric W. Biederman 		arg->valid |= FATTR_UID,    arg->uid = from_kuid(fc->user_ns, iattr->ia_uid);
13699e6268dbSMiklos Szeredi 	if (ivalid & ATTR_GID)
13708cb08329SEric W. Biederman 		arg->valid |= FATTR_GID,    arg->gid = from_kgid(fc->user_ns, iattr->ia_gid);
13719e6268dbSMiklos Szeredi 	if (ivalid & ATTR_SIZE)
1372befc649cSMiklos Szeredi 		arg->valid |= FATTR_SIZE,   arg->size = iattr->ia_size;
137317637cbaSMiklos Szeredi 	if (ivalid & ATTR_ATIME) {
137417637cbaSMiklos Szeredi 		arg->valid |= FATTR_ATIME;
1375befc649cSMiklos Szeredi 		arg->atime = iattr->ia_atime.tv_sec;
137617637cbaSMiklos Szeredi 		arg->atimensec = iattr->ia_atime.tv_nsec;
137717637cbaSMiklos Szeredi 		if (!(ivalid & ATTR_ATIME_SET))
137817637cbaSMiklos Szeredi 			arg->valid |= FATTR_ATIME_NOW;
137917637cbaSMiklos Szeredi 	}
13803ad22c62SMaxim Patlasov 	if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, trust_local_cmtime)) {
138117637cbaSMiklos Szeredi 		arg->valid |= FATTR_MTIME;
1382befc649cSMiklos Szeredi 		arg->mtime = iattr->ia_mtime.tv_sec;
138317637cbaSMiklos Szeredi 		arg->mtimensec = iattr->ia_mtime.tv_nsec;
13843ad22c62SMaxim Patlasov 		if (!(ivalid & ATTR_MTIME_SET) && !trust_local_cmtime)
138517637cbaSMiklos Szeredi 			arg->valid |= FATTR_MTIME_NOW;
13869e6268dbSMiklos Szeredi 	}
13873ad22c62SMaxim Patlasov 	if ((ivalid & ATTR_CTIME) && trust_local_cmtime) {
13883ad22c62SMaxim Patlasov 		arg->valid |= FATTR_CTIME;
13893ad22c62SMaxim Patlasov 		arg->ctime = iattr->ia_ctime.tv_sec;
13903ad22c62SMaxim Patlasov 		arg->ctimensec = iattr->ia_ctime.tv_nsec;
13913ad22c62SMaxim Patlasov 	}
13929e6268dbSMiklos Szeredi }
13939e6268dbSMiklos Szeredi 
13946f9f1180SMiklos Szeredi /*
13953be5a52bSMiklos Szeredi  * Prevent concurrent writepages on inode
13963be5a52bSMiklos Szeredi  *
13973be5a52bSMiklos Szeredi  * This is done by adding a negative bias to the inode write counter
13983be5a52bSMiklos Szeredi  * and waiting for all pending writes to finish.
13993be5a52bSMiklos Szeredi  */
14003be5a52bSMiklos Szeredi void fuse_set_nowrite(struct inode *inode)
14013be5a52bSMiklos Szeredi {
14023be5a52bSMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
14033be5a52bSMiklos Szeredi 
14045955102cSAl Viro 	BUG_ON(!inode_is_locked(inode));
14053be5a52bSMiklos Szeredi 
1406f15ecfefSKirill Tkhai 	spin_lock(&fi->lock);
14073be5a52bSMiklos Szeredi 	BUG_ON(fi->writectr < 0);
14083be5a52bSMiklos Szeredi 	fi->writectr += FUSE_NOWRITE;
1409f15ecfefSKirill Tkhai 	spin_unlock(&fi->lock);
14103be5a52bSMiklos Szeredi 	wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE);
14113be5a52bSMiklos Szeredi }
14123be5a52bSMiklos Szeredi 
14133be5a52bSMiklos Szeredi /*
14143be5a52bSMiklos Szeredi  * Allow writepages on inode
14153be5a52bSMiklos Szeredi  *
14163be5a52bSMiklos Szeredi  * Remove the bias from the writecounter and send any queued
14173be5a52bSMiklos Szeredi  * writepages.
14183be5a52bSMiklos Szeredi  */
14193be5a52bSMiklos Szeredi static void __fuse_release_nowrite(struct inode *inode)
14203be5a52bSMiklos Szeredi {
14213be5a52bSMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
14223be5a52bSMiklos Szeredi 
14233be5a52bSMiklos Szeredi 	BUG_ON(fi->writectr != FUSE_NOWRITE);
14243be5a52bSMiklos Szeredi 	fi->writectr = 0;
14253be5a52bSMiklos Szeredi 	fuse_flush_writepages(inode);
14263be5a52bSMiklos Szeredi }
14273be5a52bSMiklos Szeredi 
14283be5a52bSMiklos Szeredi void fuse_release_nowrite(struct inode *inode)
14293be5a52bSMiklos Szeredi {
1430f15ecfefSKirill Tkhai 	struct fuse_inode *fi = get_fuse_inode(inode);
14313be5a52bSMiklos Szeredi 
1432f15ecfefSKirill Tkhai 	spin_lock(&fi->lock);
14333be5a52bSMiklos Szeredi 	__fuse_release_nowrite(inode);
1434f15ecfefSKirill Tkhai 	spin_unlock(&fi->lock);
14353be5a52bSMiklos Szeredi }
14363be5a52bSMiklos Szeredi 
14377078187aSMiklos Szeredi static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_args *args,
1438b0aa7606SMaxim Patlasov 			      struct inode *inode,
1439b0aa7606SMaxim Patlasov 			      struct fuse_setattr_in *inarg_p,
1440b0aa7606SMaxim Patlasov 			      struct fuse_attr_out *outarg_p)
1441b0aa7606SMaxim Patlasov {
1442d5b48543SMiklos Szeredi 	args->opcode = FUSE_SETATTR;
1443d5b48543SMiklos Szeredi 	args->nodeid = get_node_id(inode);
1444d5b48543SMiklos Szeredi 	args->in_numargs = 1;
1445d5b48543SMiklos Szeredi 	args->in_args[0].size = sizeof(*inarg_p);
1446d5b48543SMiklos Szeredi 	args->in_args[0].value = inarg_p;
1447d5b48543SMiklos Szeredi 	args->out_numargs = 1;
1448d5b48543SMiklos Szeredi 	args->out_args[0].size = sizeof(*outarg_p);
1449d5b48543SMiklos Szeredi 	args->out_args[0].value = outarg_p;
1450b0aa7606SMaxim Patlasov }
1451b0aa7606SMaxim Patlasov 
1452b0aa7606SMaxim Patlasov /*
1453b0aa7606SMaxim Patlasov  * Flush inode->i_mtime to the server
1454b0aa7606SMaxim Patlasov  */
1455ab9e13f7SMaxim Patlasov int fuse_flush_times(struct inode *inode, struct fuse_file *ff)
1456b0aa7606SMaxim Patlasov {
1457b0aa7606SMaxim Patlasov 	struct fuse_conn *fc = get_fuse_conn(inode);
14587078187aSMiklos Szeredi 	FUSE_ARGS(args);
1459b0aa7606SMaxim Patlasov 	struct fuse_setattr_in inarg;
1460b0aa7606SMaxim Patlasov 	struct fuse_attr_out outarg;
1461b0aa7606SMaxim Patlasov 
1462b0aa7606SMaxim Patlasov 	memset(&inarg, 0, sizeof(inarg));
1463b0aa7606SMaxim Patlasov 	memset(&outarg, 0, sizeof(outarg));
1464b0aa7606SMaxim Patlasov 
1465ab9e13f7SMaxim Patlasov 	inarg.valid = FATTR_MTIME;
1466b0aa7606SMaxim Patlasov 	inarg.mtime = inode->i_mtime.tv_sec;
1467b0aa7606SMaxim Patlasov 	inarg.mtimensec = inode->i_mtime.tv_nsec;
1468ab9e13f7SMaxim Patlasov 	if (fc->minor >= 23) {
1469ab9e13f7SMaxim Patlasov 		inarg.valid |= FATTR_CTIME;
1470ab9e13f7SMaxim Patlasov 		inarg.ctime = inode->i_ctime.tv_sec;
1471ab9e13f7SMaxim Patlasov 		inarg.ctimensec = inode->i_ctime.tv_nsec;
1472ab9e13f7SMaxim Patlasov 	}
14731e18bda8SMiklos Szeredi 	if (ff) {
14741e18bda8SMiklos Szeredi 		inarg.valid |= FATTR_FH;
14751e18bda8SMiklos Szeredi 		inarg.fh = ff->fh;
14761e18bda8SMiklos Szeredi 	}
14777078187aSMiklos Szeredi 	fuse_setattr_fill(fc, &args, inode, &inarg, &outarg);
1478b0aa7606SMaxim Patlasov 
14797078187aSMiklos Szeredi 	return fuse_simple_request(fc, &args);
1480b0aa7606SMaxim Patlasov }
1481b0aa7606SMaxim Patlasov 
14823be5a52bSMiklos Szeredi /*
14836f9f1180SMiklos Szeredi  * Set attributes, and at the same time refresh them.
14846f9f1180SMiklos Szeredi  *
14856f9f1180SMiklos Szeredi  * Truncation is slightly complicated, because the 'truncate' request
14866f9f1180SMiklos Szeredi  * may fail, in which case we don't want to touch the mapping.
14879ffbb916SMiklos Szeredi  * vmtruncate() doesn't allow for this case, so do the rlimit checking
14889ffbb916SMiklos Szeredi  * and the actual truncation by hand.
14896f9f1180SMiklos Szeredi  */
149062490330SJan Kara int fuse_do_setattr(struct dentry *dentry, struct iattr *attr,
149149d4914fSMiklos Szeredi 		    struct file *file)
14929e6268dbSMiklos Szeredi {
149362490330SJan Kara 	struct inode *inode = d_inode(dentry);
14949e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
149506a7c3c2SMaxim Patlasov 	struct fuse_inode *fi = get_fuse_inode(inode);
14967078187aSMiklos Szeredi 	FUSE_ARGS(args);
14979e6268dbSMiklos Szeredi 	struct fuse_setattr_in inarg;
14989e6268dbSMiklos Szeredi 	struct fuse_attr_out outarg;
14993be5a52bSMiklos Szeredi 	bool is_truncate = false;
15008373200bSPavel Emelyanov 	bool is_wb = fc->writeback_cache;
15013be5a52bSMiklos Szeredi 	loff_t oldsize;
15029e6268dbSMiklos Szeredi 	int err;
15033ad22c62SMaxim Patlasov 	bool trust_local_cmtime = is_wb && S_ISREG(inode->i_mode);
15049e6268dbSMiklos Szeredi 
150529433a29SMiklos Szeredi 	if (!fc->default_permissions)
1506db78b877SChristoph Hellwig 		attr->ia_valid |= ATTR_FORCE;
1507db78b877SChristoph Hellwig 
150831051c85SJan Kara 	err = setattr_prepare(dentry, attr);
15091e9a4ed9SMiklos Szeredi 	if (err)
15101e9a4ed9SMiklos Szeredi 		return err;
15111e9a4ed9SMiklos Szeredi 
15128d56adddSMiklos Szeredi 	if (attr->ia_valid & ATTR_OPEN) {
1513df0e91d4SMiklos Szeredi 		/* This is coming from open(..., ... | O_TRUNC); */
1514df0e91d4SMiklos Szeredi 		WARN_ON(!(attr->ia_valid & ATTR_SIZE));
1515df0e91d4SMiklos Szeredi 		WARN_ON(attr->ia_size != 0);
1516df0e91d4SMiklos Szeredi 		if (fc->atomic_o_trunc) {
1517df0e91d4SMiklos Szeredi 			/*
1518df0e91d4SMiklos Szeredi 			 * No need to send request to userspace, since actual
1519df0e91d4SMiklos Szeredi 			 * truncation has already been done by OPEN.  But still
1520df0e91d4SMiklos Szeredi 			 * need to truncate page cache.
1521df0e91d4SMiklos Szeredi 			 */
1522df0e91d4SMiklos Szeredi 			i_size_write(inode, 0);
1523df0e91d4SMiklos Szeredi 			truncate_pagecache(inode, 0);
15246ff958edSMiklos Szeredi 			return 0;
1525df0e91d4SMiklos Szeredi 		}
15268d56adddSMiklos Szeredi 		file = NULL;
15278d56adddSMiklos Szeredi 	}
15286ff958edSMiklos Szeredi 
1529ab2257e9SMiklos Szeredi 	if (attr->ia_valid & ATTR_SIZE) {
1530ab2257e9SMiklos Szeredi 		if (WARN_ON(!S_ISREG(inode->i_mode)))
1531ab2257e9SMiklos Szeredi 			return -EIO;
15323be5a52bSMiklos Szeredi 		is_truncate = true;
1533ab2257e9SMiklos Szeredi 	}
15349e6268dbSMiklos Szeredi 
1535b24e7598SMiklos Szeredi 	/* Flush dirty data/metadata before non-truncate SETATTR */
1536b24e7598SMiklos Szeredi 	if (is_wb && S_ISREG(inode->i_mode) &&
1537b24e7598SMiklos Szeredi 	    attr->ia_valid &
1538b24e7598SMiklos Szeredi 			(ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_MTIME_SET |
1539b24e7598SMiklos Szeredi 			 ATTR_TIMES_SET)) {
1540b24e7598SMiklos Szeredi 		err = write_inode_now(inode, true);
1541b24e7598SMiklos Szeredi 		if (err)
1542b24e7598SMiklos Szeredi 			return err;
1543b24e7598SMiklos Szeredi 
1544b24e7598SMiklos Szeredi 		fuse_set_nowrite(inode);
1545b24e7598SMiklos Szeredi 		fuse_release_nowrite(inode);
1546b24e7598SMiklos Szeredi 	}
1547b24e7598SMiklos Szeredi 
154806a7c3c2SMaxim Patlasov 	if (is_truncate) {
15493be5a52bSMiklos Szeredi 		fuse_set_nowrite(inode);
155006a7c3c2SMaxim Patlasov 		set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
15513ad22c62SMaxim Patlasov 		if (trust_local_cmtime && attr->ia_size != inode->i_size)
15523ad22c62SMaxim Patlasov 			attr->ia_valid |= ATTR_MTIME | ATTR_CTIME;
155306a7c3c2SMaxim Patlasov 	}
15543be5a52bSMiklos Szeredi 
15559e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
15560e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
15578cb08329SEric W. Biederman 	iattr_to_fattr(fc, attr, &inarg, trust_local_cmtime);
155849d4914fSMiklos Szeredi 	if (file) {
155949d4914fSMiklos Szeredi 		struct fuse_file *ff = file->private_data;
156049d4914fSMiklos Szeredi 		inarg.valid |= FATTR_FH;
156149d4914fSMiklos Szeredi 		inarg.fh = ff->fh;
156249d4914fSMiklos Szeredi 	}
1563f3332114SMiklos Szeredi 	if (attr->ia_valid & ATTR_SIZE) {
1564f3332114SMiklos Szeredi 		/* For mandatory locking in truncate */
1565f3332114SMiklos Szeredi 		inarg.valid |= FATTR_LOCKOWNER;
1566f3332114SMiklos Szeredi 		inarg.lock_owner = fuse_lock_owner_id(fc, current->files);
1567f3332114SMiklos Szeredi 	}
15687078187aSMiklos Szeredi 	fuse_setattr_fill(fc, &args, inode, &inarg, &outarg);
15697078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
1570e00d2c2dSMiklos Szeredi 	if (err) {
1571e00d2c2dSMiklos Szeredi 		if (err == -EINTR)
1572e00d2c2dSMiklos Szeredi 			fuse_invalidate_attr(inode);
15733be5a52bSMiklos Szeredi 		goto error;
1574e00d2c2dSMiklos Szeredi 	}
1575e00d2c2dSMiklos Szeredi 
1576eb59bd17SMiklos Szeredi 	if (fuse_invalid_attr(&outarg.attr) ||
1577eb59bd17SMiklos Szeredi 	    (inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
15789e6268dbSMiklos Szeredi 		make_bad_inode(inode);
15793be5a52bSMiklos Szeredi 		err = -EIO;
15803be5a52bSMiklos Szeredi 		goto error;
15819e6268dbSMiklos Szeredi 	}
15829e6268dbSMiklos Szeredi 
1583f15ecfefSKirill Tkhai 	spin_lock(&fi->lock);
1584b0aa7606SMaxim Patlasov 	/* the kernel maintains i_mtime locally */
15853ad22c62SMaxim Patlasov 	if (trust_local_cmtime) {
15863ad22c62SMaxim Patlasov 		if (attr->ia_valid & ATTR_MTIME)
1587b0aa7606SMaxim Patlasov 			inode->i_mtime = attr->ia_mtime;
15883ad22c62SMaxim Patlasov 		if (attr->ia_valid & ATTR_CTIME)
15893ad22c62SMaxim Patlasov 			inode->i_ctime = attr->ia_ctime;
15901e18bda8SMiklos Szeredi 		/* FIXME: clear I_DIRTY_SYNC? */
1591b0aa7606SMaxim Patlasov 	}
1592b0aa7606SMaxim Patlasov 
15933be5a52bSMiklos Szeredi 	fuse_change_attributes_common(inode, &outarg.attr,
15943be5a52bSMiklos Szeredi 				      attr_timeout(&outarg));
15953be5a52bSMiklos Szeredi 	oldsize = inode->i_size;
15968373200bSPavel Emelyanov 	/* see the comment in fuse_change_attributes() */
15978373200bSPavel Emelyanov 	if (!is_wb || is_truncate || !S_ISREG(inode->i_mode))
15983be5a52bSMiklos Szeredi 		i_size_write(inode, outarg.attr.size);
15993be5a52bSMiklos Szeredi 
16003be5a52bSMiklos Szeredi 	if (is_truncate) {
1601f15ecfefSKirill Tkhai 		/* NOTE: this may release/reacquire fi->lock */
16023be5a52bSMiklos Szeredi 		__fuse_release_nowrite(inode);
16033be5a52bSMiklos Szeredi 	}
1604f15ecfefSKirill Tkhai 	spin_unlock(&fi->lock);
16053be5a52bSMiklos Szeredi 
16063be5a52bSMiklos Szeredi 	/*
16073be5a52bSMiklos Szeredi 	 * Only call invalidate_inode_pages2() after removing
16083be5a52bSMiklos Szeredi 	 * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock.
16093be5a52bSMiklos Szeredi 	 */
16108373200bSPavel Emelyanov 	if ((is_truncate || !is_wb) &&
16118373200bSPavel Emelyanov 	    S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
16127caef267SKirill A. Shutemov 		truncate_pagecache(inode, outarg.attr.size);
16133be5a52bSMiklos Szeredi 		invalidate_inode_pages2(inode->i_mapping);
16143be5a52bSMiklos Szeredi 	}
16153be5a52bSMiklos Szeredi 
161606a7c3c2SMaxim Patlasov 	clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
1617e00d2c2dSMiklos Szeredi 	return 0;
16183be5a52bSMiklos Szeredi 
16193be5a52bSMiklos Szeredi error:
16203be5a52bSMiklos Szeredi 	if (is_truncate)
16213be5a52bSMiklos Szeredi 		fuse_release_nowrite(inode);
16223be5a52bSMiklos Szeredi 
162306a7c3c2SMaxim Patlasov 	clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
16243be5a52bSMiklos Szeredi 	return err;
16259e6268dbSMiklos Szeredi }
16269e6268dbSMiklos Szeredi 
162749d4914fSMiklos Szeredi static int fuse_setattr(struct dentry *entry, struct iattr *attr)
162849d4914fSMiklos Szeredi {
16292b0143b5SDavid Howells 	struct inode *inode = d_inode(entry);
16305e940c1dSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1631a09f99edSMiklos Szeredi 	struct file *file = (attr->ia_valid & ATTR_FILE) ? attr->ia_file : NULL;
16325e2b8828SMiklos Szeredi 	int ret;
1633efb9fa9eSMaxim Patlasov 
1634efb9fa9eSMaxim Patlasov 	if (!fuse_allow_current_process(get_fuse_conn(inode)))
1635efb9fa9eSMaxim Patlasov 		return -EACCES;
1636efb9fa9eSMaxim Patlasov 
1637a09f99edSMiklos Szeredi 	if (attr->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) {
1638a09f99edSMiklos Szeredi 		attr->ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID |
1639a09f99edSMiklos Szeredi 				    ATTR_MODE);
16405e940c1dSMiklos Szeredi 
1641a09f99edSMiklos Szeredi 		/*
16425e940c1dSMiklos Szeredi 		 * The only sane way to reliably kill suid/sgid is to do it in
16435e940c1dSMiklos Szeredi 		 * the userspace filesystem
16445e940c1dSMiklos Szeredi 		 *
16455e940c1dSMiklos Szeredi 		 * This should be done on write(), truncate() and chown().
16465e940c1dSMiklos Szeredi 		 */
16475e940c1dSMiklos Szeredi 		if (!fc->handle_killpriv) {
16485e940c1dSMiklos Szeredi 			/*
16495e940c1dSMiklos Szeredi 			 * ia_mode calculation may have used stale i_mode.
16505e940c1dSMiklos Szeredi 			 * Refresh and recalculate.
1651a09f99edSMiklos Szeredi 			 */
1652a09f99edSMiklos Szeredi 			ret = fuse_do_getattr(inode, NULL, file);
1653a09f99edSMiklos Szeredi 			if (ret)
1654a09f99edSMiklos Szeredi 				return ret;
1655a09f99edSMiklos Szeredi 
1656a09f99edSMiklos Szeredi 			attr->ia_mode = inode->i_mode;
1657c01638f5SMiklos Szeredi 			if (inode->i_mode & S_ISUID) {
1658a09f99edSMiklos Szeredi 				attr->ia_valid |= ATTR_MODE;
1659a09f99edSMiklos Szeredi 				attr->ia_mode &= ~S_ISUID;
1660a09f99edSMiklos Szeredi 			}
1661c01638f5SMiklos Szeredi 			if ((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
1662a09f99edSMiklos Szeredi 				attr->ia_valid |= ATTR_MODE;
1663a09f99edSMiklos Szeredi 				attr->ia_mode &= ~S_ISGID;
1664a09f99edSMiklos Szeredi 			}
1665a09f99edSMiklos Szeredi 		}
16665e940c1dSMiklos Szeredi 	}
1667a09f99edSMiklos Szeredi 	if (!attr->ia_valid)
1668a09f99edSMiklos Szeredi 		return 0;
1669a09f99edSMiklos Szeredi 
1670abb5a14fSLinus Torvalds 	ret = fuse_do_setattr(entry, attr, file);
16715e2b8828SMiklos Szeredi 	if (!ret) {
167260bcc88aSSeth Forshee 		/*
167360bcc88aSSeth Forshee 		 * If filesystem supports acls it may have updated acl xattrs in
167460bcc88aSSeth Forshee 		 * the filesystem, so forget cached acls for the inode.
167560bcc88aSSeth Forshee 		 */
167660bcc88aSSeth Forshee 		if (fc->posix_acl)
167760bcc88aSSeth Forshee 			forget_all_cached_acls(inode);
167860bcc88aSSeth Forshee 
16795e2b8828SMiklos Szeredi 		/* Directory mode changed, may need to revalidate access */
16805e2b8828SMiklos Szeredi 		if (d_is_dir(entry) && (attr->ia_valid & ATTR_MODE))
16815e2b8828SMiklos Szeredi 			fuse_invalidate_entry_cache(entry);
16825e2b8828SMiklos Szeredi 	}
16835e2b8828SMiklos Szeredi 	return ret;
168449d4914fSMiklos Szeredi }
168549d4914fSMiklos Szeredi 
1686a528d35eSDavid Howells static int fuse_getattr(const struct path *path, struct kstat *stat,
1687a528d35eSDavid Howells 			u32 request_mask, unsigned int flags)
1688e5e5558eSMiklos Szeredi {
1689a528d35eSDavid Howells 	struct inode *inode = d_inode(path->dentry);
1690244f6385SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1691244f6385SMiklos Szeredi 
1692c2132c1bSAnatol Pomozov 	if (!fuse_allow_current_process(fc))
1693244f6385SMiklos Szeredi 		return -EACCES;
1694244f6385SMiklos Szeredi 
16952f1e8196SMiklos Szeredi 	return fuse_update_get_attr(inode, NULL, stat, request_mask, flags);
1696e5e5558eSMiklos Szeredi }
1697e5e5558eSMiklos Szeredi 
1698754661f1SArjan van de Ven static const struct inode_operations fuse_dir_inode_operations = {
1699e5e5558eSMiklos Szeredi 	.lookup		= fuse_lookup,
17009e6268dbSMiklos Szeredi 	.mkdir		= fuse_mkdir,
17019e6268dbSMiklos Szeredi 	.symlink	= fuse_symlink,
17029e6268dbSMiklos Szeredi 	.unlink		= fuse_unlink,
17039e6268dbSMiklos Szeredi 	.rmdir		= fuse_rmdir,
17042773bf00SMiklos Szeredi 	.rename		= fuse_rename2,
17059e6268dbSMiklos Szeredi 	.link		= fuse_link,
17069e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
17079e6268dbSMiklos Szeredi 	.create		= fuse_create,
1708c8ccbe03SMiklos Szeredi 	.atomic_open	= fuse_atomic_open,
17099e6268dbSMiklos Szeredi 	.mknod		= fuse_mknod,
1710e5e5558eSMiklos Szeredi 	.permission	= fuse_permission,
1711e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
171292a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
171360bcc88aSSeth Forshee 	.get_acl	= fuse_get_acl,
171460bcc88aSSeth Forshee 	.set_acl	= fuse_set_acl,
1715e5e5558eSMiklos Szeredi };
1716e5e5558eSMiklos Szeredi 
17174b6f5d20SArjan van de Ven static const struct file_operations fuse_dir_operations = {
1718b6aeadedSMiklos Szeredi 	.llseek		= generic_file_llseek,
1719e5e5558eSMiklos Szeredi 	.read		= generic_read_dir,
1720d9b3dbdcSAl Viro 	.iterate_shared	= fuse_readdir,
1721e5e5558eSMiklos Szeredi 	.open		= fuse_dir_open,
1722e5e5558eSMiklos Szeredi 	.release	= fuse_dir_release,
172382547981SMiklos Szeredi 	.fsync		= fuse_dir_fsync,
1724b18da0c5SMiklos Szeredi 	.unlocked_ioctl	= fuse_dir_ioctl,
1725b18da0c5SMiklos Szeredi 	.compat_ioctl	= fuse_dir_compat_ioctl,
1726e5e5558eSMiklos Szeredi };
1727e5e5558eSMiklos Szeredi 
1728754661f1SArjan van de Ven static const struct inode_operations fuse_common_inode_operations = {
17299e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
1730e5e5558eSMiklos Szeredi 	.permission	= fuse_permission,
1731e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
173292a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
173360bcc88aSSeth Forshee 	.get_acl	= fuse_get_acl,
173460bcc88aSSeth Forshee 	.set_acl	= fuse_set_acl,
1735e5e5558eSMiklos Szeredi };
1736e5e5558eSMiklos Szeredi 
1737754661f1SArjan van de Ven static const struct inode_operations fuse_symlink_inode_operations = {
17389e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
17396b255391SAl Viro 	.get_link	= fuse_get_link,
1740e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
174192a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
1742e5e5558eSMiklos Szeredi };
1743e5e5558eSMiklos Szeredi 
1744e5e5558eSMiklos Szeredi void fuse_init_common(struct inode *inode)
1745e5e5558eSMiklos Szeredi {
1746e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_common_inode_operations;
1747e5e5558eSMiklos Szeredi }
1748e5e5558eSMiklos Szeredi 
1749e5e5558eSMiklos Szeredi void fuse_init_dir(struct inode *inode)
1750e5e5558eSMiklos Szeredi {
1751ab2257e9SMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
1752ab2257e9SMiklos Szeredi 
1753e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_dir_inode_operations;
1754e5e5558eSMiklos Szeredi 	inode->i_fop = &fuse_dir_operations;
1755ab2257e9SMiklos Szeredi 
1756ab2257e9SMiklos Szeredi 	spin_lock_init(&fi->rdc.lock);
1757ab2257e9SMiklos Szeredi 	fi->rdc.cached = false;
1758ab2257e9SMiklos Szeredi 	fi->rdc.size = 0;
1759ab2257e9SMiklos Szeredi 	fi->rdc.pos = 0;
1760ab2257e9SMiklos Szeredi 	fi->rdc.version = 0;
1761e5e5558eSMiklos Szeredi }
1762e5e5558eSMiklos Szeredi 
17635571f1e6SDan Schatzberg static int fuse_symlink_readpage(struct file *null, struct page *page)
17645571f1e6SDan Schatzberg {
17655571f1e6SDan Schatzberg 	int err = fuse_readlink_page(page->mapping->host, page);
17665571f1e6SDan Schatzberg 
17675571f1e6SDan Schatzberg 	if (!err)
17685571f1e6SDan Schatzberg 		SetPageUptodate(page);
17695571f1e6SDan Schatzberg 
17705571f1e6SDan Schatzberg 	unlock_page(page);
17715571f1e6SDan Schatzberg 
17725571f1e6SDan Schatzberg 	return err;
17735571f1e6SDan Schatzberg }
17745571f1e6SDan Schatzberg 
17755571f1e6SDan Schatzberg static const struct address_space_operations fuse_symlink_aops = {
17765571f1e6SDan Schatzberg 	.readpage	= fuse_symlink_readpage,
17775571f1e6SDan Schatzberg };
17785571f1e6SDan Schatzberg 
1779e5e5558eSMiklos Szeredi void fuse_init_symlink(struct inode *inode)
1780e5e5558eSMiklos Szeredi {
1781e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_symlink_inode_operations;
17825571f1e6SDan Schatzberg 	inode->i_data.a_ops = &fuse_symlink_aops;
17835571f1e6SDan Schatzberg 	inode_nohighmem(inode);
1784e5e5558eSMiklos Szeredi }
1785