xref: /openbmc/linux/fs/fuse/dir.c (revision be12af3ef5e61ebc44d065e121424ac605d7bb8e)
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>
1760bcc88aSSeth Forshee #include <linux/posix_acl.h>
18e5e5558eSMiklos Szeredi 
198d3af7f3SAl Viro static bool fuse_use_readdirplus(struct inode *dir, struct dir_context *ctx)
204582a4abSFeng Shuo {
214582a4abSFeng Shuo 	struct fuse_conn *fc = get_fuse_conn(dir);
224582a4abSFeng Shuo 	struct fuse_inode *fi = get_fuse_inode(dir);
234582a4abSFeng Shuo 
244582a4abSFeng Shuo 	if (!fc->do_readdirplus)
254582a4abSFeng Shuo 		return false;
26634734b6SEric Wong 	if (!fc->readdirplus_auto)
27634734b6SEric Wong 		return true;
284582a4abSFeng Shuo 	if (test_and_clear_bit(FUSE_I_ADVISE_RDPLUS, &fi->state))
294582a4abSFeng Shuo 		return true;
308d3af7f3SAl Viro 	if (ctx->pos == 0)
314582a4abSFeng Shuo 		return true;
324582a4abSFeng Shuo 	return false;
334582a4abSFeng Shuo }
344582a4abSFeng Shuo 
354582a4abSFeng Shuo static void fuse_advise_use_readdirplus(struct inode *dir)
364582a4abSFeng Shuo {
374582a4abSFeng Shuo 	struct fuse_inode *fi = get_fuse_inode(dir);
384582a4abSFeng Shuo 
394582a4abSFeng Shuo 	set_bit(FUSE_I_ADVISE_RDPLUS, &fi->state);
404582a4abSFeng Shuo }
414582a4abSFeng Shuo 
42f75fdf22SMiklos Szeredi union fuse_dentry {
43f75fdf22SMiklos Szeredi 	u64 time;
44f75fdf22SMiklos Szeredi 	struct rcu_head rcu;
45f75fdf22SMiklos Szeredi };
46f75fdf22SMiklos Szeredi 
470a0898cfSMiklos Szeredi static inline void fuse_dentry_settime(struct dentry *entry, u64 time)
480a0898cfSMiklos Szeredi {
49f75fdf22SMiklos Szeredi 	((union fuse_dentry *) entry->d_fsdata)->time = time;
500a0898cfSMiklos Szeredi }
510a0898cfSMiklos Szeredi 
520a0898cfSMiklos Szeredi static inline u64 fuse_dentry_time(struct dentry *entry)
530a0898cfSMiklos Szeredi {
54f75fdf22SMiklos Szeredi 	return ((union fuse_dentry *) entry->d_fsdata)->time;
550a0898cfSMiklos Szeredi }
560a0898cfSMiklos Szeredi 
576f9f1180SMiklos Szeredi /*
586f9f1180SMiklos Szeredi  * FUSE caches dentries and attributes with separate timeout.  The
596f9f1180SMiklos Szeredi  * time in jiffies until the dentry/attributes are valid is stored in
60f75fdf22SMiklos Szeredi  * dentry->d_fsdata and fuse_inode->i_time respectively.
616f9f1180SMiklos Szeredi  */
626f9f1180SMiklos Szeredi 
636f9f1180SMiklos Szeredi /*
646f9f1180SMiklos Szeredi  * Calculate the time in jiffies until a dentry/attributes are valid
656f9f1180SMiklos Szeredi  */
66bcb6f6d2SMiklos Szeredi static u64 time_to_jiffies(u64 sec, u32 nsec)
67e5e5558eSMiklos Szeredi {
68685d16ddSMiklos Szeredi 	if (sec || nsec) {
69bcb6f6d2SMiklos Szeredi 		struct timespec64 ts = {
70bcb6f6d2SMiklos Szeredi 			sec,
7121067527SDavid Sheets 			min_t(u32, nsec, NSEC_PER_SEC - 1)
72bcb6f6d2SMiklos Szeredi 		};
73bcb6f6d2SMiklos Szeredi 
74bcb6f6d2SMiklos Szeredi 		return get_jiffies_64() + timespec64_to_jiffies(&ts);
75685d16ddSMiklos Szeredi 	} else
760a0898cfSMiklos Szeredi 		return 0;
77e5e5558eSMiklos Szeredi }
78e5e5558eSMiklos Szeredi 
796f9f1180SMiklos Szeredi /*
806f9f1180SMiklos Szeredi  * Set dentry and possibly attribute timeouts from the lookup/mk*
816f9f1180SMiklos Szeredi  * replies
826f9f1180SMiklos Szeredi  */
831fb69e78SMiklos Szeredi static void fuse_change_entry_timeout(struct dentry *entry,
841fb69e78SMiklos Szeredi 				      struct fuse_entry_out *o)
850aa7c699SMiklos Szeredi {
860a0898cfSMiklos Szeredi 	fuse_dentry_settime(entry,
870a0898cfSMiklos Szeredi 		time_to_jiffies(o->entry_valid, o->entry_valid_nsec));
881fb69e78SMiklos Szeredi }
891fb69e78SMiklos Szeredi 
901fb69e78SMiklos Szeredi static u64 attr_timeout(struct fuse_attr_out *o)
911fb69e78SMiklos Szeredi {
921fb69e78SMiklos Szeredi 	return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
931fb69e78SMiklos Szeredi }
941fb69e78SMiklos Szeredi 
951fb69e78SMiklos Szeredi static u64 entry_attr_timeout(struct fuse_entry_out *o)
961fb69e78SMiklos Szeredi {
971fb69e78SMiklos Szeredi 	return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
988cbdf1e6SMiklos Szeredi }
998cbdf1e6SMiklos Szeredi 
1006f9f1180SMiklos Szeredi /*
1016f9f1180SMiklos Szeredi  * Mark the attributes as stale, so that at the next call to
1026f9f1180SMiklos Szeredi  * ->getattr() they will be fetched from userspace
1036f9f1180SMiklos Szeredi  */
1048cbdf1e6SMiklos Szeredi void fuse_invalidate_attr(struct inode *inode)
1058cbdf1e6SMiklos Szeredi {
1060a0898cfSMiklos Szeredi 	get_fuse_inode(inode)->i_time = 0;
1078cbdf1e6SMiklos Szeredi }
1088cbdf1e6SMiklos Szeredi 
109451418fcSAndrew Gallagher /**
110451418fcSAndrew Gallagher  * Mark the attributes as stale due to an atime change.  Avoid the invalidate if
111451418fcSAndrew Gallagher  * atime is not used.
112451418fcSAndrew Gallagher  */
113451418fcSAndrew Gallagher void fuse_invalidate_atime(struct inode *inode)
114451418fcSAndrew Gallagher {
115451418fcSAndrew Gallagher 	if (!IS_RDONLY(inode))
116451418fcSAndrew Gallagher 		fuse_invalidate_attr(inode);
117451418fcSAndrew Gallagher }
118451418fcSAndrew Gallagher 
1196f9f1180SMiklos Szeredi /*
1206f9f1180SMiklos Szeredi  * Just mark the entry as stale, so that a next attempt to look it up
1216f9f1180SMiklos Szeredi  * will result in a new lookup call to userspace
1226f9f1180SMiklos Szeredi  *
1236f9f1180SMiklos Szeredi  * This is called when a dentry is about to become negative and the
1246f9f1180SMiklos Szeredi  * timeout is unknown (unlink, rmdir, rename and in some cases
1256f9f1180SMiklos Szeredi  * lookup)
1266f9f1180SMiklos Szeredi  */
127dbd561d2SMiklos Szeredi void fuse_invalidate_entry_cache(struct dentry *entry)
1288cbdf1e6SMiklos Szeredi {
1290a0898cfSMiklos Szeredi 	fuse_dentry_settime(entry, 0);
1308cbdf1e6SMiklos Szeredi }
1318cbdf1e6SMiklos Szeredi 
1326f9f1180SMiklos Szeredi /*
1336f9f1180SMiklos Szeredi  * Same as fuse_invalidate_entry_cache(), but also try to remove the
1346f9f1180SMiklos Szeredi  * dentry from the hash
1356f9f1180SMiklos Szeredi  */
1368cbdf1e6SMiklos Szeredi static void fuse_invalidate_entry(struct dentry *entry)
1378cbdf1e6SMiklos Szeredi {
1388cbdf1e6SMiklos Szeredi 	d_invalidate(entry);
1398cbdf1e6SMiklos Szeredi 	fuse_invalidate_entry_cache(entry);
1400aa7c699SMiklos Szeredi }
1410aa7c699SMiklos Szeredi 
1427078187aSMiklos Szeredi static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_args *args,
14313983d06SAl Viro 			     u64 nodeid, const struct qstr *name,
144e5e5558eSMiklos Szeredi 			     struct fuse_entry_out *outarg)
145e5e5558eSMiklos Szeredi {
1460e9663eeSMiklos Szeredi 	memset(outarg, 0, sizeof(struct fuse_entry_out));
1477078187aSMiklos Szeredi 	args->in.h.opcode = FUSE_LOOKUP;
1487078187aSMiklos Szeredi 	args->in.h.nodeid = nodeid;
1497078187aSMiklos Szeredi 	args->in.numargs = 1;
1507078187aSMiklos Szeredi 	args->in.args[0].size = name->len + 1;
1517078187aSMiklos Szeredi 	args->in.args[0].value = name->name;
1527078187aSMiklos Szeredi 	args->out.numargs = 1;
1537078187aSMiklos Szeredi 	args->out.args[0].size = sizeof(struct fuse_entry_out);
1547078187aSMiklos Szeredi 	args->out.args[0].value = outarg;
155e5e5558eSMiklos Szeredi }
156e5e5558eSMiklos Szeredi 
1575c5c5e51SMiklos Szeredi u64 fuse_get_attr_version(struct fuse_conn *fc)
1587dca9fd3SMiklos Szeredi {
1597dca9fd3SMiklos Szeredi 	u64 curr_version;
1607dca9fd3SMiklos Szeredi 
1617dca9fd3SMiklos Szeredi 	/*
1627dca9fd3SMiklos Szeredi 	 * The spin lock isn't actually needed on 64bit archs, but we
1637dca9fd3SMiklos Szeredi 	 * don't yet care too much about such optimizations.
1647dca9fd3SMiklos Szeredi 	 */
1657dca9fd3SMiklos Szeredi 	spin_lock(&fc->lock);
1667dca9fd3SMiklos Szeredi 	curr_version = fc->attr_version;
1677dca9fd3SMiklos Szeredi 	spin_unlock(&fc->lock);
1687dca9fd3SMiklos Szeredi 
1697dca9fd3SMiklos Szeredi 	return curr_version;
1707dca9fd3SMiklos Szeredi }
1717dca9fd3SMiklos Szeredi 
1726f9f1180SMiklos Szeredi /*
1736f9f1180SMiklos Szeredi  * Check whether the dentry is still valid
1746f9f1180SMiklos Szeredi  *
1756f9f1180SMiklos Szeredi  * If the entry validity timeout has expired and the dentry is
1766f9f1180SMiklos Szeredi  * positive, try to redo the lookup.  If the lookup results in a
1776f9f1180SMiklos Szeredi  * different inode, then let the VFS invalidate the dentry and redo
1786f9f1180SMiklos Szeredi  * the lookup once more.  If the lookup results in the same inode,
1796f9f1180SMiklos Szeredi  * then refresh the attributes, timeouts and mark the dentry valid.
1806f9f1180SMiklos Szeredi  */
1810b728e19SAl Viro static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
182e5e5558eSMiklos Szeredi {
18334286d66SNick Piggin 	struct inode *inode;
18428420dadSMiklos Szeredi 	struct dentry *parent;
18528420dadSMiklos Szeredi 	struct fuse_conn *fc;
1866314efeeSMiklos Szeredi 	struct fuse_inode *fi;
187e2a6b952SMiklos Szeredi 	int ret;
1888cbdf1e6SMiklos Szeredi 
1892b0143b5SDavid Howells 	inode = d_inode_rcu(entry);
1908cbdf1e6SMiklos Szeredi 	if (inode && is_bad_inode(inode))
191e2a6b952SMiklos Szeredi 		goto invalid;
192154210ccSAnand Avati 	else if (time_before64(fuse_dentry_time(entry), get_jiffies_64()) ||
193154210ccSAnand Avati 		 (flags & LOOKUP_REVAL)) {
194e5e5558eSMiklos Szeredi 		struct fuse_entry_out outarg;
1957078187aSMiklos Szeredi 		FUSE_ARGS(args);
19607e77dcaSMiklos Szeredi 		struct fuse_forget_link *forget;
1971fb69e78SMiklos Szeredi 		u64 attr_version;
1988cbdf1e6SMiklos Szeredi 
19950322fe7SMiklos Szeredi 		/* For negative dentries, always do a fresh lookup */
2008cbdf1e6SMiklos Szeredi 		if (!inode)
201e2a6b952SMiklos Szeredi 			goto invalid;
2028cbdf1e6SMiklos Szeredi 
203e2a6b952SMiklos Szeredi 		ret = -ECHILD;
2040b728e19SAl Viro 		if (flags & LOOKUP_RCU)
205e2a6b952SMiklos Szeredi 			goto out;
206e7c0a167SMiklos Szeredi 
2078cbdf1e6SMiklos Szeredi 		fc = get_fuse_conn(inode);
208e5e5558eSMiklos Szeredi 
20907e77dcaSMiklos Szeredi 		forget = fuse_alloc_forget();
210e2a6b952SMiklos Szeredi 		ret = -ENOMEM;
2117078187aSMiklos Szeredi 		if (!forget)
212e2a6b952SMiklos Szeredi 			goto out;
2132d51013eSMiklos Szeredi 
2147dca9fd3SMiklos Szeredi 		attr_version = fuse_get_attr_version(fc);
2151fb69e78SMiklos Szeredi 
216e956edd0SMiklos Szeredi 		parent = dget_parent(entry);
2172b0143b5SDavid Howells 		fuse_lookup_init(fc, &args, get_node_id(d_inode(parent)),
218c180eebeSMiklos Szeredi 				 &entry->d_name, &outarg);
2197078187aSMiklos Szeredi 		ret = fuse_simple_request(fc, &args);
220e956edd0SMiklos Szeredi 		dput(parent);
22150322fe7SMiklos Szeredi 		/* Zero nodeid is same as -ENOENT */
2227078187aSMiklos Szeredi 		if (!ret && !outarg.nodeid)
2237078187aSMiklos Szeredi 			ret = -ENOENT;
2247078187aSMiklos Szeredi 		if (!ret) {
2256314efeeSMiklos Szeredi 			fi = get_fuse_inode(inode);
2269e6268dbSMiklos Szeredi 			if (outarg.nodeid != get_node_id(inode)) {
22707e77dcaSMiklos Szeredi 				fuse_queue_forget(fc, forget, outarg.nodeid, 1);
228e2a6b952SMiklos Szeredi 				goto invalid;
2299e6268dbSMiklos Szeredi 			}
2308da5ff23SMiklos Szeredi 			spin_lock(&fc->lock);
2319e6268dbSMiklos Szeredi 			fi->nlookup++;
2328da5ff23SMiklos Szeredi 			spin_unlock(&fc->lock);
2339e6268dbSMiklos Szeredi 		}
23407e77dcaSMiklos Szeredi 		kfree(forget);
2357078187aSMiklos Szeredi 		if (ret == -ENOMEM)
2367078187aSMiklos Szeredi 			goto out;
2377078187aSMiklos Szeredi 		if (ret || (outarg.attr.mode ^ inode->i_mode) & S_IFMT)
238e2a6b952SMiklos Szeredi 			goto invalid;
239e5e5558eSMiklos Szeredi 
24060bcc88aSSeth Forshee 		forget_all_cached_acls(inode);
2411fb69e78SMiklos Szeredi 		fuse_change_attributes(inode, &outarg.attr,
2421fb69e78SMiklos Szeredi 				       entry_attr_timeout(&outarg),
2431fb69e78SMiklos Szeredi 				       attr_version);
2441fb69e78SMiklos Szeredi 		fuse_change_entry_timeout(entry, &outarg);
24528420dadSMiklos Szeredi 	} else if (inode) {
2466314efeeSMiklos Szeredi 		fi = get_fuse_inode(inode);
2476314efeeSMiklos Szeredi 		if (flags & LOOKUP_RCU) {
2486314efeeSMiklos Szeredi 			if (test_bit(FUSE_I_INIT_RDPLUS, &fi->state))
2496314efeeSMiklos Szeredi 				return -ECHILD;
2506314efeeSMiklos Szeredi 		} else if (test_and_clear_bit(FUSE_I_INIT_RDPLUS, &fi->state)) {
25128420dadSMiklos Szeredi 			parent = dget_parent(entry);
2522b0143b5SDavid Howells 			fuse_advise_use_readdirplus(d_inode(parent));
25328420dadSMiklos Szeredi 			dput(parent);
254e5e5558eSMiklos Szeredi 		}
25528420dadSMiklos Szeredi 	}
256e2a6b952SMiklos Szeredi 	ret = 1;
257e2a6b952SMiklos Szeredi out:
258e2a6b952SMiklos Szeredi 	return ret;
259e2a6b952SMiklos Szeredi 
260e2a6b952SMiklos Szeredi invalid:
261e2a6b952SMiklos Szeredi 	ret = 0;
262e2a6b952SMiklos Szeredi 	goto out;
263e5e5558eSMiklos Szeredi }
264e5e5558eSMiklos Szeredi 
2658bfc016dSMiklos Szeredi static int invalid_nodeid(u64 nodeid)
2662827d0b2SMiklos Szeredi {
2672827d0b2SMiklos Szeredi 	return !nodeid || nodeid == FUSE_ROOT_ID;
2682827d0b2SMiklos Szeredi }
2692827d0b2SMiklos Szeredi 
270f75fdf22SMiklos Szeredi static int fuse_dentry_init(struct dentry *dentry)
271f75fdf22SMiklos Szeredi {
272f75fdf22SMiklos Szeredi 	dentry->d_fsdata = kzalloc(sizeof(union fuse_dentry), GFP_KERNEL);
273f75fdf22SMiklos Szeredi 
274f75fdf22SMiklos Szeredi 	return dentry->d_fsdata ? 0 : -ENOMEM;
275f75fdf22SMiklos Szeredi }
276f75fdf22SMiklos Szeredi static void fuse_dentry_release(struct dentry *dentry)
277f75fdf22SMiklos Szeredi {
278f75fdf22SMiklos Szeredi 	union fuse_dentry *fd = dentry->d_fsdata;
279f75fdf22SMiklos Szeredi 
280f75fdf22SMiklos Szeredi 	kfree_rcu(fd, rcu);
281f75fdf22SMiklos Szeredi }
282f75fdf22SMiklos Szeredi 
2834269590aSAl Viro const struct dentry_operations fuse_dentry_operations = {
284e5e5558eSMiklos Szeredi 	.d_revalidate	= fuse_dentry_revalidate,
285f75fdf22SMiklos Szeredi 	.d_init		= fuse_dentry_init,
286f75fdf22SMiklos Szeredi 	.d_release	= fuse_dentry_release,
287e5e5558eSMiklos Szeredi };
288e5e5558eSMiklos Szeredi 
2890ce267ffSMiklos Szeredi const struct dentry_operations fuse_root_dentry_operations = {
2900ce267ffSMiklos Szeredi 	.d_init		= fuse_dentry_init,
2910ce267ffSMiklos Szeredi 	.d_release	= fuse_dentry_release,
2920ce267ffSMiklos Szeredi };
2930ce267ffSMiklos Szeredi 
294a5bfffacSTimo Savola int fuse_valid_type(int m)
29539ee059aSMiklos Szeredi {
29639ee059aSMiklos Szeredi 	return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) ||
29739ee059aSMiklos Szeredi 		S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m);
29839ee059aSMiklos Szeredi }
29939ee059aSMiklos Szeredi 
30013983d06SAl Viro int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name,
301c180eebeSMiklos Szeredi 		     struct fuse_entry_out *outarg, struct inode **inode)
302c180eebeSMiklos Szeredi {
303c180eebeSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn_super(sb);
3047078187aSMiklos Szeredi 	FUSE_ARGS(args);
30507e77dcaSMiklos Szeredi 	struct fuse_forget_link *forget;
306c180eebeSMiklos Szeredi 	u64 attr_version;
307c180eebeSMiklos Szeredi 	int err;
308c180eebeSMiklos Szeredi 
309c180eebeSMiklos Szeredi 	*inode = NULL;
310c180eebeSMiklos Szeredi 	err = -ENAMETOOLONG;
311c180eebeSMiklos Szeredi 	if (name->len > FUSE_NAME_MAX)
312c180eebeSMiklos Szeredi 		goto out;
313c180eebeSMiklos Szeredi 
314c180eebeSMiklos Szeredi 
31507e77dcaSMiklos Szeredi 	forget = fuse_alloc_forget();
31607e77dcaSMiklos Szeredi 	err = -ENOMEM;
3177078187aSMiklos Szeredi 	if (!forget)
318c180eebeSMiklos Szeredi 		goto out;
319c180eebeSMiklos Szeredi 
320c180eebeSMiklos Szeredi 	attr_version = fuse_get_attr_version(fc);
321c180eebeSMiklos Szeredi 
3227078187aSMiklos Szeredi 	fuse_lookup_init(fc, &args, nodeid, name, outarg);
3237078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
324c180eebeSMiklos Szeredi 	/* Zero nodeid is same as -ENOENT, but with valid timeout */
325c180eebeSMiklos Szeredi 	if (err || !outarg->nodeid)
326c180eebeSMiklos Szeredi 		goto out_put_forget;
327c180eebeSMiklos Szeredi 
328c180eebeSMiklos Szeredi 	err = -EIO;
329c180eebeSMiklos Szeredi 	if (!outarg->nodeid)
330c180eebeSMiklos Szeredi 		goto out_put_forget;
331c180eebeSMiklos Szeredi 	if (!fuse_valid_type(outarg->attr.mode))
332c180eebeSMiklos Szeredi 		goto out_put_forget;
333c180eebeSMiklos Szeredi 
334c180eebeSMiklos Szeredi 	*inode = fuse_iget(sb, outarg->nodeid, outarg->generation,
335c180eebeSMiklos Szeredi 			   &outarg->attr, entry_attr_timeout(outarg),
336c180eebeSMiklos Szeredi 			   attr_version);
337c180eebeSMiklos Szeredi 	err = -ENOMEM;
338c180eebeSMiklos Szeredi 	if (!*inode) {
33907e77dcaSMiklos Szeredi 		fuse_queue_forget(fc, forget, outarg->nodeid, 1);
340c180eebeSMiklos Szeredi 		goto out;
341c180eebeSMiklos Szeredi 	}
342c180eebeSMiklos Szeredi 	err = 0;
343c180eebeSMiklos Szeredi 
344c180eebeSMiklos Szeredi  out_put_forget:
34507e77dcaSMiklos Szeredi 	kfree(forget);
346c180eebeSMiklos Szeredi  out:
347c180eebeSMiklos Szeredi 	return err;
348c180eebeSMiklos Szeredi }
349c180eebeSMiklos Szeredi 
3500aa7c699SMiklos Szeredi static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
35100cd8dd3SAl Viro 				  unsigned int flags)
352e5e5558eSMiklos Szeredi {
353e5e5558eSMiklos Szeredi 	int err;
354e5e5558eSMiklos Szeredi 	struct fuse_entry_out outarg;
355c180eebeSMiklos Szeredi 	struct inode *inode;
3560de6256dSMiklos Szeredi 	struct dentry *newent;
357c180eebeSMiklos Szeredi 	bool outarg_valid = true;
358e5e5558eSMiklos Szeredi 
3595c672ab3SMiklos Szeredi 	fuse_lock_inode(dir);
360c180eebeSMiklos Szeredi 	err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name,
361c180eebeSMiklos Szeredi 			       &outarg, &inode);
3625c672ab3SMiklos Szeredi 	fuse_unlock_inode(dir);
363c180eebeSMiklos Szeredi 	if (err == -ENOENT) {
364c180eebeSMiklos Szeredi 		outarg_valid = false;
365c180eebeSMiklos Szeredi 		err = 0;
3662d51013eSMiklos Szeredi 	}
367c180eebeSMiklos Szeredi 	if (err)
368c180eebeSMiklos Szeredi 		goto out_err;
3692d51013eSMiklos Szeredi 
370ee4e5271SMiklos Szeredi 	err = -EIO;
371c180eebeSMiklos Szeredi 	if (inode && get_node_id(inode) == FUSE_ROOT_ID)
372c180eebeSMiklos Szeredi 		goto out_iput;
373e5e5558eSMiklos Szeredi 
37441d28bcaSAl Viro 	newent = d_splice_alias(inode, entry);
375c180eebeSMiklos Szeredi 	err = PTR_ERR(newent);
376c180eebeSMiklos Szeredi 	if (IS_ERR(newent))
3775835f339SMiklos Szeredi 		goto out_err;
378d2a85164SMiklos Szeredi 
3790de6256dSMiklos Szeredi 	entry = newent ? newent : entry;
380c180eebeSMiklos Szeredi 	if (outarg_valid)
3811fb69e78SMiklos Szeredi 		fuse_change_entry_timeout(entry, &outarg);
3828cbdf1e6SMiklos Szeredi 	else
3838cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
384c180eebeSMiklos Szeredi 
3854582a4abSFeng Shuo 	fuse_advise_use_readdirplus(dir);
3860de6256dSMiklos Szeredi 	return newent;
387c180eebeSMiklos Szeredi 
388c180eebeSMiklos Szeredi  out_iput:
389c180eebeSMiklos Szeredi 	iput(inode);
390c180eebeSMiklos Szeredi  out_err:
391c180eebeSMiklos Szeredi 	return ERR_PTR(err);
392e5e5558eSMiklos Szeredi }
393e5e5558eSMiklos Szeredi 
3946f9f1180SMiklos Szeredi /*
3956f9f1180SMiklos Szeredi  * Atomic create+open operation
3966f9f1180SMiklos Szeredi  *
3976f9f1180SMiklos Szeredi  * If the filesystem doesn't support this, then fall back to separate
3986f9f1180SMiklos Szeredi  * 'mknod' + 'open' requests.
3996f9f1180SMiklos Szeredi  */
400d9585277SAl Viro static int fuse_create_open(struct inode *dir, struct dentry *entry,
40130d90494SAl Viro 			    struct file *file, unsigned flags,
40247237687SAl Viro 			    umode_t mode, int *opened)
403fd72faacSMiklos Szeredi {
404fd72faacSMiklos Szeredi 	int err;
405fd72faacSMiklos Szeredi 	struct inode *inode;
406fd72faacSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
4077078187aSMiklos Szeredi 	FUSE_ARGS(args);
40807e77dcaSMiklos Szeredi 	struct fuse_forget_link *forget;
409e0a43ddcSMiklos Szeredi 	struct fuse_create_in inarg;
410fd72faacSMiklos Szeredi 	struct fuse_open_out outopen;
411fd72faacSMiklos Szeredi 	struct fuse_entry_out outentry;
412fd72faacSMiklos Szeredi 	struct fuse_file *ff;
413fd72faacSMiklos Szeredi 
414af109bcaSMiklos Szeredi 	/* Userspace expects S_IFREG in create mode */
415af109bcaSMiklos Szeredi 	BUG_ON((mode & S_IFMT) != S_IFREG);
416af109bcaSMiklos Szeredi 
41707e77dcaSMiklos Szeredi 	forget = fuse_alloc_forget();
418c8ccbe03SMiklos Szeredi 	err = -ENOMEM;
41907e77dcaSMiklos Szeredi 	if (!forget)
420c8ccbe03SMiklos Szeredi 		goto out_err;
42151eb01e7SMiklos Szeredi 
422ce1d5a49SMiklos Szeredi 	err = -ENOMEM;
423acf99433STejun Heo 	ff = fuse_file_alloc(fc);
424fd72faacSMiklos Szeredi 	if (!ff)
4257078187aSMiklos Szeredi 		goto out_put_forget_req;
426fd72faacSMiklos Szeredi 
427e0a43ddcSMiklos Szeredi 	if (!fc->dont_mask)
428e0a43ddcSMiklos Szeredi 		mode &= ~current_umask();
429e0a43ddcSMiklos Szeredi 
430fd72faacSMiklos Szeredi 	flags &= ~O_NOCTTY;
431fd72faacSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
4320e9663eeSMiklos Szeredi 	memset(&outentry, 0, sizeof(outentry));
433fd72faacSMiklos Szeredi 	inarg.flags = flags;
434fd72faacSMiklos Szeredi 	inarg.mode = mode;
435e0a43ddcSMiklos Szeredi 	inarg.umask = current_umask();
4367078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_CREATE;
4377078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(dir);
4387078187aSMiklos Szeredi 	args.in.numargs = 2;
43921f62174SMiklos Szeredi 	args.in.args[0].size = sizeof(inarg);
4407078187aSMiklos Szeredi 	args.in.args[0].value = &inarg;
4417078187aSMiklos Szeredi 	args.in.args[1].size = entry->d_name.len + 1;
4427078187aSMiklos Szeredi 	args.in.args[1].value = entry->d_name.name;
4437078187aSMiklos Szeredi 	args.out.numargs = 2;
4447078187aSMiklos Szeredi 	args.out.args[0].size = sizeof(outentry);
4457078187aSMiklos Szeredi 	args.out.args[0].value = &outentry;
4467078187aSMiklos Szeredi 	args.out.args[1].size = sizeof(outopen);
4477078187aSMiklos Szeredi 	args.out.args[1].value = &outopen;
4487078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
449c8ccbe03SMiklos Szeredi 	if (err)
450fd72faacSMiklos Szeredi 		goto out_free_ff;
451fd72faacSMiklos Szeredi 
452fd72faacSMiklos Szeredi 	err = -EIO;
4532827d0b2SMiklos Szeredi 	if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid))
454fd72faacSMiklos Szeredi 		goto out_free_ff;
455fd72faacSMiklos Szeredi 
456c7b7143cSMiklos Szeredi 	ff->fh = outopen.fh;
457c7b7143cSMiklos Szeredi 	ff->nodeid = outentry.nodeid;
458c7b7143cSMiklos Szeredi 	ff->open_flags = outopen.open_flags;
459fd72faacSMiklos Szeredi 	inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
4601fb69e78SMiklos Szeredi 			  &outentry.attr, entry_attr_timeout(&outentry), 0);
461fd72faacSMiklos Szeredi 	if (!inode) {
462fd72faacSMiklos Szeredi 		flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
4638b0797a4SMiklos Szeredi 		fuse_sync_release(ff, flags);
46407e77dcaSMiklos Szeredi 		fuse_queue_forget(fc, forget, outentry.nodeid, 1);
465c8ccbe03SMiklos Szeredi 		err = -ENOMEM;
466c8ccbe03SMiklos Szeredi 		goto out_err;
467fd72faacSMiklos Szeredi 	}
46807e77dcaSMiklos Szeredi 	kfree(forget);
469fd72faacSMiklos Szeredi 	d_instantiate(entry, inode);
4701fb69e78SMiklos Szeredi 	fuse_change_entry_timeout(entry, &outentry);
4710952b2a4SMiklos Szeredi 	fuse_invalidate_attr(dir);
472*be12af3eSAl Viro 	err = finish_open(file, entry, generic_file_open);
47330d90494SAl Viro 	if (err) {
4748b0797a4SMiklos Szeredi 		fuse_sync_release(ff, flags);
475c8ccbe03SMiklos Szeredi 	} else {
476267d8444SMiklos Szeredi 		file->private_data = ff;
477c7b7143cSMiklos Szeredi 		fuse_finish_open(inode, file);
478c8ccbe03SMiklos Szeredi 	}
479d9585277SAl Viro 	return err;
480fd72faacSMiklos Szeredi 
481fd72faacSMiklos Szeredi out_free_ff:
482fd72faacSMiklos Szeredi 	fuse_file_free(ff);
48351eb01e7SMiklos Szeredi out_put_forget_req:
48407e77dcaSMiklos Szeredi 	kfree(forget);
485c8ccbe03SMiklos Szeredi out_err:
486d9585277SAl Viro 	return err;
487c8ccbe03SMiklos Szeredi }
488c8ccbe03SMiklos Szeredi 
489c8ccbe03SMiklos Szeredi static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t);
490d9585277SAl Viro static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
49130d90494SAl Viro 			    struct file *file, unsigned flags,
49247237687SAl Viro 			    umode_t mode, int *opened)
493c8ccbe03SMiklos Szeredi {
494c8ccbe03SMiklos Szeredi 	int err;
495c8ccbe03SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
496c8ccbe03SMiklos Szeredi 	struct dentry *res = NULL;
497c8ccbe03SMiklos Szeredi 
49800699ad8SAl Viro 	if (d_in_lookup(entry)) {
49900cd8dd3SAl Viro 		res = fuse_lookup(dir, entry, 0);
500c8ccbe03SMiklos Szeredi 		if (IS_ERR(res))
501d9585277SAl Viro 			return PTR_ERR(res);
502c8ccbe03SMiklos Szeredi 
503c8ccbe03SMiklos Szeredi 		if (res)
504c8ccbe03SMiklos Szeredi 			entry = res;
505c8ccbe03SMiklos Szeredi 	}
506c8ccbe03SMiklos Szeredi 
5072b0143b5SDavid Howells 	if (!(flags & O_CREAT) || d_really_is_positive(entry))
508c8ccbe03SMiklos Szeredi 		goto no_open;
509c8ccbe03SMiklos Szeredi 
510c8ccbe03SMiklos Szeredi 	/* Only creates */
51173a09dd9SAl Viro 	file->f_mode |= FMODE_CREATED;
512c8ccbe03SMiklos Szeredi 
513c8ccbe03SMiklos Szeredi 	if (fc->no_create)
514c8ccbe03SMiklos Szeredi 		goto mknod;
515c8ccbe03SMiklos Szeredi 
51630d90494SAl Viro 	err = fuse_create_open(dir, entry, file, flags, mode, opened);
517d9585277SAl Viro 	if (err == -ENOSYS) {
518c8ccbe03SMiklos Szeredi 		fc->no_create = 1;
519c8ccbe03SMiklos Szeredi 		goto mknod;
520c8ccbe03SMiklos Szeredi 	}
521c8ccbe03SMiklos Szeredi out_dput:
522c8ccbe03SMiklos Szeredi 	dput(res);
523d9585277SAl Viro 	return err;
524c8ccbe03SMiklos Szeredi 
525c8ccbe03SMiklos Szeredi mknod:
526c8ccbe03SMiklos Szeredi 	err = fuse_mknod(dir, entry, mode, 0);
527d9585277SAl Viro 	if (err)
528c8ccbe03SMiklos Szeredi 		goto out_dput;
529c8ccbe03SMiklos Szeredi no_open:
530e45198a6SAl Viro 	return finish_no_open(file, res);
531fd72faacSMiklos Szeredi }
532fd72faacSMiklos Szeredi 
5336f9f1180SMiklos Szeredi /*
5346f9f1180SMiklos Szeredi  * Code shared between mknod, mkdir, symlink and link
5356f9f1180SMiklos Szeredi  */
5367078187aSMiklos Szeredi static int create_new_entry(struct fuse_conn *fc, struct fuse_args *args,
5379e6268dbSMiklos Szeredi 			    struct inode *dir, struct dentry *entry,
538541af6a0SAl Viro 			    umode_t mode)
5399e6268dbSMiklos Szeredi {
5409e6268dbSMiklos Szeredi 	struct fuse_entry_out outarg;
5419e6268dbSMiklos Szeredi 	struct inode *inode;
5429e6268dbSMiklos Szeredi 	int err;
54307e77dcaSMiklos Szeredi 	struct fuse_forget_link *forget;
5442d51013eSMiklos Szeredi 
54507e77dcaSMiklos Szeredi 	forget = fuse_alloc_forget();
5467078187aSMiklos Szeredi 	if (!forget)
54707e77dcaSMiklos Szeredi 		return -ENOMEM;
5489e6268dbSMiklos Szeredi 
5490e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
5507078187aSMiklos Szeredi 	args->in.h.nodeid = get_node_id(dir);
5517078187aSMiklos Szeredi 	args->out.numargs = 1;
5527078187aSMiklos Szeredi 	args->out.args[0].size = sizeof(outarg);
5537078187aSMiklos Szeredi 	args->out.args[0].value = &outarg;
5547078187aSMiklos Szeredi 	err = fuse_simple_request(fc, args);
5552d51013eSMiklos Szeredi 	if (err)
5562d51013eSMiklos Szeredi 		goto out_put_forget_req;
5572d51013eSMiklos Szeredi 
55839ee059aSMiklos Szeredi 	err = -EIO;
55939ee059aSMiklos Szeredi 	if (invalid_nodeid(outarg.nodeid))
5602d51013eSMiklos Szeredi 		goto out_put_forget_req;
56139ee059aSMiklos Szeredi 
56239ee059aSMiklos Szeredi 	if ((outarg.attr.mode ^ mode) & S_IFMT)
5632d51013eSMiklos Szeredi 		goto out_put_forget_req;
56439ee059aSMiklos Szeredi 
5659e6268dbSMiklos Szeredi 	inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
5661fb69e78SMiklos Szeredi 			  &outarg.attr, entry_attr_timeout(&outarg), 0);
5679e6268dbSMiklos Szeredi 	if (!inode) {
56807e77dcaSMiklos Szeredi 		fuse_queue_forget(fc, forget, outarg.nodeid, 1);
5699e6268dbSMiklos Szeredi 		return -ENOMEM;
5709e6268dbSMiklos Szeredi 	}
57107e77dcaSMiklos Szeredi 	kfree(forget);
5729e6268dbSMiklos Szeredi 
573b70a80e7SMiklos Szeredi 	err = d_instantiate_no_diralias(entry, inode);
574b70a80e7SMiklos Szeredi 	if (err)
575b70a80e7SMiklos Szeredi 		return err;
576d2a85164SMiklos Szeredi 
5771fb69e78SMiklos Szeredi 	fuse_change_entry_timeout(entry, &outarg);
5789e6268dbSMiklos Szeredi 	fuse_invalidate_attr(dir);
5799e6268dbSMiklos Szeredi 	return 0;
58039ee059aSMiklos Szeredi 
5812d51013eSMiklos Szeredi  out_put_forget_req:
58207e77dcaSMiklos Szeredi 	kfree(forget);
58339ee059aSMiklos Szeredi 	return err;
5849e6268dbSMiklos Szeredi }
5859e6268dbSMiklos Szeredi 
5861a67aafbSAl Viro static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode,
5879e6268dbSMiklos Szeredi 		      dev_t rdev)
5889e6268dbSMiklos Szeredi {
5899e6268dbSMiklos Szeredi 	struct fuse_mknod_in inarg;
5909e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
5917078187aSMiklos Szeredi 	FUSE_ARGS(args);
5929e6268dbSMiklos Szeredi 
593e0a43ddcSMiklos Szeredi 	if (!fc->dont_mask)
594e0a43ddcSMiklos Szeredi 		mode &= ~current_umask();
595e0a43ddcSMiklos Szeredi 
5969e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
5979e6268dbSMiklos Szeredi 	inarg.mode = mode;
5989e6268dbSMiklos Szeredi 	inarg.rdev = new_encode_dev(rdev);
599e0a43ddcSMiklos Szeredi 	inarg.umask = current_umask();
6007078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_MKNOD;
6017078187aSMiklos Szeredi 	args.in.numargs = 2;
60221f62174SMiklos Szeredi 	args.in.args[0].size = sizeof(inarg);
6037078187aSMiklos Szeredi 	args.in.args[0].value = &inarg;
6047078187aSMiklos Szeredi 	args.in.args[1].size = entry->d_name.len + 1;
6057078187aSMiklos Szeredi 	args.in.args[1].value = entry->d_name.name;
6067078187aSMiklos Szeredi 	return create_new_entry(fc, &args, dir, entry, mode);
6079e6268dbSMiklos Szeredi }
6089e6268dbSMiklos Szeredi 
6094acdaf27SAl Viro static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode,
610ebfc3b49SAl Viro 		       bool excl)
6119e6268dbSMiklos Szeredi {
6129e6268dbSMiklos Szeredi 	return fuse_mknod(dir, entry, mode, 0);
6139e6268dbSMiklos Szeredi }
6149e6268dbSMiklos Szeredi 
61518bb1db3SAl Viro static int fuse_mkdir(struct inode *dir, struct dentry *entry, umode_t mode)
6169e6268dbSMiklos Szeredi {
6179e6268dbSMiklos Szeredi 	struct fuse_mkdir_in inarg;
6189e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
6197078187aSMiklos Szeredi 	FUSE_ARGS(args);
6209e6268dbSMiklos Szeredi 
621e0a43ddcSMiklos Szeredi 	if (!fc->dont_mask)
622e0a43ddcSMiklos Szeredi 		mode &= ~current_umask();
623e0a43ddcSMiklos Szeredi 
6249e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
6259e6268dbSMiklos Szeredi 	inarg.mode = mode;
626e0a43ddcSMiklos Szeredi 	inarg.umask = current_umask();
6277078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_MKDIR;
6287078187aSMiklos Szeredi 	args.in.numargs = 2;
6297078187aSMiklos Szeredi 	args.in.args[0].size = sizeof(inarg);
6307078187aSMiklos Szeredi 	args.in.args[0].value = &inarg;
6317078187aSMiklos Szeredi 	args.in.args[1].size = entry->d_name.len + 1;
6327078187aSMiklos Szeredi 	args.in.args[1].value = entry->d_name.name;
6337078187aSMiklos Szeredi 	return create_new_entry(fc, &args, dir, entry, S_IFDIR);
6349e6268dbSMiklos Szeredi }
6359e6268dbSMiklos Szeredi 
6369e6268dbSMiklos Szeredi static int fuse_symlink(struct inode *dir, struct dentry *entry,
6379e6268dbSMiklos Szeredi 			const char *link)
6389e6268dbSMiklos Szeredi {
6399e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
6409e6268dbSMiklos Szeredi 	unsigned len = strlen(link) + 1;
6417078187aSMiklos Szeredi 	FUSE_ARGS(args);
6429e6268dbSMiklos Szeredi 
6437078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_SYMLINK;
6447078187aSMiklos Szeredi 	args.in.numargs = 2;
6457078187aSMiklos Szeredi 	args.in.args[0].size = entry->d_name.len + 1;
6467078187aSMiklos Szeredi 	args.in.args[0].value = entry->d_name.name;
6477078187aSMiklos Szeredi 	args.in.args[1].size = len;
6487078187aSMiklos Szeredi 	args.in.args[1].value = link;
6497078187aSMiklos Szeredi 	return create_new_entry(fc, &args, dir, entry, S_IFLNK);
6509e6268dbSMiklos Szeredi }
6519e6268dbSMiklos Szeredi 
652703c7362SSeth Forshee void fuse_update_ctime(struct inode *inode)
65331f3267bSMaxim Patlasov {
65431f3267bSMaxim Patlasov 	if (!IS_NOCMTIME(inode)) {
655c2050a45SDeepa Dinamani 		inode->i_ctime = current_time(inode);
65631f3267bSMaxim Patlasov 		mark_inode_dirty_sync(inode);
65731f3267bSMaxim Patlasov 	}
65831f3267bSMaxim Patlasov }
65931f3267bSMaxim Patlasov 
6609e6268dbSMiklos Szeredi static int fuse_unlink(struct inode *dir, struct dentry *entry)
6619e6268dbSMiklos Szeredi {
6629e6268dbSMiklos Szeredi 	int err;
6639e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
6647078187aSMiklos Szeredi 	FUSE_ARGS(args);
6659e6268dbSMiklos Szeredi 
6667078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_UNLINK;
6677078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(dir);
6687078187aSMiklos Szeredi 	args.in.numargs = 1;
6697078187aSMiklos Szeredi 	args.in.args[0].size = entry->d_name.len + 1;
6707078187aSMiklos Szeredi 	args.in.args[0].value = entry->d_name.name;
6717078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
6729e6268dbSMiklos Szeredi 	if (!err) {
6732b0143b5SDavid Howells 		struct inode *inode = d_inode(entry);
674ac45d613SMiklos Szeredi 		struct fuse_inode *fi = get_fuse_inode(inode);
6759e6268dbSMiklos Szeredi 
676ac45d613SMiklos Szeredi 		spin_lock(&fc->lock);
677ac45d613SMiklos Szeredi 		fi->attr_version = ++fc->attr_version;
678dfca7cebSMiklos Szeredi 		/*
679dfca7cebSMiklos Szeredi 		 * If i_nlink == 0 then unlink doesn't make sense, yet this can
680dfca7cebSMiklos Szeredi 		 * happen if userspace filesystem is careless.  It would be
681dfca7cebSMiklos Szeredi 		 * difficult to enforce correct nlink usage so just ignore this
682dfca7cebSMiklos Szeredi 		 * condition here
683dfca7cebSMiklos Szeredi 		 */
684dfca7cebSMiklos Szeredi 		if (inode->i_nlink > 0)
685ac45d613SMiklos Szeredi 			drop_nlink(inode);
686ac45d613SMiklos Szeredi 		spin_unlock(&fc->lock);
6879e6268dbSMiklos Szeredi 		fuse_invalidate_attr(inode);
6889e6268dbSMiklos Szeredi 		fuse_invalidate_attr(dir);
6898cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
69031f3267bSMaxim Patlasov 		fuse_update_ctime(inode);
6919e6268dbSMiklos Szeredi 	} else if (err == -EINTR)
6929e6268dbSMiklos Szeredi 		fuse_invalidate_entry(entry);
6939e6268dbSMiklos Szeredi 	return err;
6949e6268dbSMiklos Szeredi }
6959e6268dbSMiklos Szeredi 
6969e6268dbSMiklos Szeredi static int fuse_rmdir(struct inode *dir, struct dentry *entry)
6979e6268dbSMiklos Szeredi {
6989e6268dbSMiklos Szeredi 	int err;
6999e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
7007078187aSMiklos Szeredi 	FUSE_ARGS(args);
7019e6268dbSMiklos Szeredi 
7027078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_RMDIR;
7037078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(dir);
7047078187aSMiklos Szeredi 	args.in.numargs = 1;
7057078187aSMiklos Szeredi 	args.in.args[0].size = entry->d_name.len + 1;
7067078187aSMiklos Szeredi 	args.in.args[0].value = entry->d_name.name;
7077078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
7089e6268dbSMiklos Szeredi 	if (!err) {
7092b0143b5SDavid Howells 		clear_nlink(d_inode(entry));
7109e6268dbSMiklos Szeredi 		fuse_invalidate_attr(dir);
7118cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
7129e6268dbSMiklos Szeredi 	} else if (err == -EINTR)
7139e6268dbSMiklos Szeredi 		fuse_invalidate_entry(entry);
7149e6268dbSMiklos Szeredi 	return err;
7159e6268dbSMiklos Szeredi }
7169e6268dbSMiklos Szeredi 
7171560c974SMiklos Szeredi static int fuse_rename_common(struct inode *olddir, struct dentry *oldent,
7181560c974SMiklos Szeredi 			      struct inode *newdir, struct dentry *newent,
7191560c974SMiklos Szeredi 			      unsigned int flags, int opcode, size_t argsize)
7209e6268dbSMiklos Szeredi {
7219e6268dbSMiklos Szeredi 	int err;
7221560c974SMiklos Szeredi 	struct fuse_rename2_in inarg;
7239e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(olddir);
7247078187aSMiklos Szeredi 	FUSE_ARGS(args);
7259e6268dbSMiklos Szeredi 
7261560c974SMiklos Szeredi 	memset(&inarg, 0, argsize);
7279e6268dbSMiklos Szeredi 	inarg.newdir = get_node_id(newdir);
7281560c974SMiklos Szeredi 	inarg.flags = flags;
7297078187aSMiklos Szeredi 	args.in.h.opcode = opcode;
7307078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(olddir);
7317078187aSMiklos Szeredi 	args.in.numargs = 3;
7327078187aSMiklos Szeredi 	args.in.args[0].size = argsize;
7337078187aSMiklos Szeredi 	args.in.args[0].value = &inarg;
7347078187aSMiklos Szeredi 	args.in.args[1].size = oldent->d_name.len + 1;
7357078187aSMiklos Szeredi 	args.in.args[1].value = oldent->d_name.name;
7367078187aSMiklos Szeredi 	args.in.args[2].size = newent->d_name.len + 1;
7377078187aSMiklos Szeredi 	args.in.args[2].value = newent->d_name.name;
7387078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
7399e6268dbSMiklos Szeredi 	if (!err) {
74008b63307SMiklos Szeredi 		/* ctime changes */
7412b0143b5SDavid Howells 		fuse_invalidate_attr(d_inode(oldent));
7422b0143b5SDavid Howells 		fuse_update_ctime(d_inode(oldent));
74308b63307SMiklos Szeredi 
7441560c974SMiklos Szeredi 		if (flags & RENAME_EXCHANGE) {
7452b0143b5SDavid Howells 			fuse_invalidate_attr(d_inode(newent));
7462b0143b5SDavid Howells 			fuse_update_ctime(d_inode(newent));
7471560c974SMiklos Szeredi 		}
7481560c974SMiklos Szeredi 
7499e6268dbSMiklos Szeredi 		fuse_invalidate_attr(olddir);
7509e6268dbSMiklos Szeredi 		if (olddir != newdir)
7519e6268dbSMiklos Szeredi 			fuse_invalidate_attr(newdir);
7528cbdf1e6SMiklos Szeredi 
7538cbdf1e6SMiklos Szeredi 		/* newent will end up negative */
7542b0143b5SDavid Howells 		if (!(flags & RENAME_EXCHANGE) && d_really_is_positive(newent)) {
7552b0143b5SDavid Howells 			fuse_invalidate_attr(d_inode(newent));
7568cbdf1e6SMiklos Szeredi 			fuse_invalidate_entry_cache(newent);
7572b0143b5SDavid Howells 			fuse_update_ctime(d_inode(newent));
7585219f346SMiklos Szeredi 		}
7599e6268dbSMiklos Szeredi 	} else if (err == -EINTR) {
7609e6268dbSMiklos Szeredi 		/* If request was interrupted, DEITY only knows if the
7619e6268dbSMiklos Szeredi 		   rename actually took place.  If the invalidation
7629e6268dbSMiklos Szeredi 		   fails (e.g. some process has CWD under the renamed
7639e6268dbSMiklos Szeredi 		   directory), then there can be inconsistency between
7649e6268dbSMiklos Szeredi 		   the dcache and the real filesystem.  Tough luck. */
7659e6268dbSMiklos Szeredi 		fuse_invalidate_entry(oldent);
7662b0143b5SDavid Howells 		if (d_really_is_positive(newent))
7679e6268dbSMiklos Szeredi 			fuse_invalidate_entry(newent);
7689e6268dbSMiklos Szeredi 	}
7699e6268dbSMiklos Szeredi 
7709e6268dbSMiklos Szeredi 	return err;
7719e6268dbSMiklos Szeredi }
7729e6268dbSMiklos Szeredi 
7731560c974SMiklos Szeredi static int fuse_rename2(struct inode *olddir, struct dentry *oldent,
7741560c974SMiklos Szeredi 			struct inode *newdir, struct dentry *newent,
7751560c974SMiklos Szeredi 			unsigned int flags)
7761560c974SMiklos Szeredi {
7771560c974SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(olddir);
7781560c974SMiklos Szeredi 	int err;
7791560c974SMiklos Szeredi 
7801560c974SMiklos Szeredi 	if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE))
7811560c974SMiklos Szeredi 		return -EINVAL;
7821560c974SMiklos Szeredi 
7834237ba43SMiklos Szeredi 	if (flags) {
7841560c974SMiklos Szeredi 		if (fc->no_rename2 || fc->minor < 23)
7851560c974SMiklos Szeredi 			return -EINVAL;
7861560c974SMiklos Szeredi 
7871560c974SMiklos Szeredi 		err = fuse_rename_common(olddir, oldent, newdir, newent, flags,
7884237ba43SMiklos Szeredi 					 FUSE_RENAME2,
7894237ba43SMiklos Szeredi 					 sizeof(struct fuse_rename2_in));
7901560c974SMiklos Szeredi 		if (err == -ENOSYS) {
7911560c974SMiklos Szeredi 			fc->no_rename2 = 1;
7921560c974SMiklos Szeredi 			err = -EINVAL;
7931560c974SMiklos Szeredi 		}
7944237ba43SMiklos Szeredi 	} else {
7954237ba43SMiklos Szeredi 		err = fuse_rename_common(olddir, oldent, newdir, newent, 0,
7964237ba43SMiklos Szeredi 					 FUSE_RENAME,
7974237ba43SMiklos Szeredi 					 sizeof(struct fuse_rename_in));
7984237ba43SMiklos Szeredi 	}
7991560c974SMiklos Szeredi 
8004237ba43SMiklos Szeredi 	return err;
8014237ba43SMiklos Szeredi }
8024237ba43SMiklos Szeredi 
8039e6268dbSMiklos Szeredi static int fuse_link(struct dentry *entry, struct inode *newdir,
8049e6268dbSMiklos Szeredi 		     struct dentry *newent)
8059e6268dbSMiklos Szeredi {
8069e6268dbSMiklos Szeredi 	int err;
8079e6268dbSMiklos Szeredi 	struct fuse_link_in inarg;
8082b0143b5SDavid Howells 	struct inode *inode = d_inode(entry);
8099e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
8107078187aSMiklos Szeredi 	FUSE_ARGS(args);
8119e6268dbSMiklos Szeredi 
8129e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
8139e6268dbSMiklos Szeredi 	inarg.oldnodeid = get_node_id(inode);
8147078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_LINK;
8157078187aSMiklos Szeredi 	args.in.numargs = 2;
8167078187aSMiklos Szeredi 	args.in.args[0].size = sizeof(inarg);
8177078187aSMiklos Szeredi 	args.in.args[0].value = &inarg;
8187078187aSMiklos Szeredi 	args.in.args[1].size = newent->d_name.len + 1;
8197078187aSMiklos Szeredi 	args.in.args[1].value = newent->d_name.name;
8207078187aSMiklos Szeredi 	err = create_new_entry(fc, &args, newdir, newent, inode->i_mode);
8219e6268dbSMiklos Szeredi 	/* Contrary to "normal" filesystems it can happen that link
8229e6268dbSMiklos Szeredi 	   makes two "logical" inodes point to the same "physical"
8239e6268dbSMiklos Szeredi 	   inode.  We invalidate the attributes of the old one, so it
8249e6268dbSMiklos Szeredi 	   will reflect changes in the backing inode (link count,
8259e6268dbSMiklos Szeredi 	   etc.)
8269e6268dbSMiklos Szeredi 	*/
827ac45d613SMiklos Szeredi 	if (!err) {
828ac45d613SMiklos Szeredi 		struct fuse_inode *fi = get_fuse_inode(inode);
829ac45d613SMiklos Szeredi 
830ac45d613SMiklos Szeredi 		spin_lock(&fc->lock);
831ac45d613SMiklos Szeredi 		fi->attr_version = ++fc->attr_version;
832ac45d613SMiklos Szeredi 		inc_nlink(inode);
833ac45d613SMiklos Szeredi 		spin_unlock(&fc->lock);
8349e6268dbSMiklos Szeredi 		fuse_invalidate_attr(inode);
83531f3267bSMaxim Patlasov 		fuse_update_ctime(inode);
836ac45d613SMiklos Szeredi 	} else if (err == -EINTR) {
837ac45d613SMiklos Szeredi 		fuse_invalidate_attr(inode);
838ac45d613SMiklos Szeredi 	}
8399e6268dbSMiklos Szeredi 	return err;
8409e6268dbSMiklos Szeredi }
8419e6268dbSMiklos Szeredi 
8421fb69e78SMiklos Szeredi static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
8431fb69e78SMiklos Szeredi 			  struct kstat *stat)
8441fb69e78SMiklos Szeredi {
845203627bbSMiklos Szeredi 	unsigned int blkbits;
8468373200bSPavel Emelyanov 	struct fuse_conn *fc = get_fuse_conn(inode);
8478373200bSPavel Emelyanov 
8488373200bSPavel Emelyanov 	/* see the comment in fuse_change_attributes() */
849b0aa7606SMaxim Patlasov 	if (fc->writeback_cache && S_ISREG(inode->i_mode)) {
8508373200bSPavel Emelyanov 		attr->size = i_size_read(inode);
851b0aa7606SMaxim Patlasov 		attr->mtime = inode->i_mtime.tv_sec;
852b0aa7606SMaxim Patlasov 		attr->mtimensec = inode->i_mtime.tv_nsec;
85331f3267bSMaxim Patlasov 		attr->ctime = inode->i_ctime.tv_sec;
85431f3267bSMaxim Patlasov 		attr->ctimensec = inode->i_ctime.tv_nsec;
855b0aa7606SMaxim Patlasov 	}
856203627bbSMiklos Szeredi 
8571fb69e78SMiklos Szeredi 	stat->dev = inode->i_sb->s_dev;
8581fb69e78SMiklos Szeredi 	stat->ino = attr->ino;
8591fb69e78SMiklos Szeredi 	stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
8601fb69e78SMiklos Szeredi 	stat->nlink = attr->nlink;
8618cb08329SEric W. Biederman 	stat->uid = make_kuid(fc->user_ns, attr->uid);
8628cb08329SEric W. Biederman 	stat->gid = make_kgid(fc->user_ns, attr->gid);
8631fb69e78SMiklos Szeredi 	stat->rdev = inode->i_rdev;
8641fb69e78SMiklos Szeredi 	stat->atime.tv_sec = attr->atime;
8651fb69e78SMiklos Szeredi 	stat->atime.tv_nsec = attr->atimensec;
8661fb69e78SMiklos Szeredi 	stat->mtime.tv_sec = attr->mtime;
8671fb69e78SMiklos Szeredi 	stat->mtime.tv_nsec = attr->mtimensec;
8681fb69e78SMiklos Szeredi 	stat->ctime.tv_sec = attr->ctime;
8691fb69e78SMiklos Szeredi 	stat->ctime.tv_nsec = attr->ctimensec;
8701fb69e78SMiklos Szeredi 	stat->size = attr->size;
8711fb69e78SMiklos Szeredi 	stat->blocks = attr->blocks;
872203627bbSMiklos Szeredi 
873203627bbSMiklos Szeredi 	if (attr->blksize != 0)
874203627bbSMiklos Szeredi 		blkbits = ilog2(attr->blksize);
875203627bbSMiklos Szeredi 	else
876203627bbSMiklos Szeredi 		blkbits = inode->i_sb->s_blocksize_bits;
877203627bbSMiklos Szeredi 
878203627bbSMiklos Szeredi 	stat->blksize = 1 << blkbits;
8791fb69e78SMiklos Szeredi }
8801fb69e78SMiklos Szeredi 
881c79e322fSMiklos Szeredi static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
882c79e322fSMiklos Szeredi 			   struct file *file)
883e5e5558eSMiklos Szeredi {
884e5e5558eSMiklos Szeredi 	int err;
885c79e322fSMiklos Szeredi 	struct fuse_getattr_in inarg;
886c79e322fSMiklos Szeredi 	struct fuse_attr_out outarg;
887e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
8887078187aSMiklos Szeredi 	FUSE_ARGS(args);
8891fb69e78SMiklos Szeredi 	u64 attr_version;
8901fb69e78SMiklos Szeredi 
8917dca9fd3SMiklos Szeredi 	attr_version = fuse_get_attr_version(fc);
8921fb69e78SMiklos Szeredi 
893c79e322fSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
8940e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
895c79e322fSMiklos Szeredi 	/* Directories have separate file-handle space */
896c79e322fSMiklos Szeredi 	if (file && S_ISREG(inode->i_mode)) {
897c79e322fSMiklos Szeredi 		struct fuse_file *ff = file->private_data;
898c79e322fSMiklos Szeredi 
899c79e322fSMiklos Szeredi 		inarg.getattr_flags |= FUSE_GETATTR_FH;
900c79e322fSMiklos Szeredi 		inarg.fh = ff->fh;
901c79e322fSMiklos Szeredi 	}
9027078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_GETATTR;
9037078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(inode);
9047078187aSMiklos Szeredi 	args.in.numargs = 1;
9057078187aSMiklos Szeredi 	args.in.args[0].size = sizeof(inarg);
9067078187aSMiklos Szeredi 	args.in.args[0].value = &inarg;
9077078187aSMiklos Szeredi 	args.out.numargs = 1;
9087078187aSMiklos Szeredi 	args.out.args[0].size = sizeof(outarg);
9097078187aSMiklos Szeredi 	args.out.args[0].value = &outarg;
9107078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
911e5e5558eSMiklos Szeredi 	if (!err) {
912c79e322fSMiklos Szeredi 		if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
913e5e5558eSMiklos Szeredi 			make_bad_inode(inode);
914e5e5558eSMiklos Szeredi 			err = -EIO;
915e5e5558eSMiklos Szeredi 		} else {
916c79e322fSMiklos Szeredi 			fuse_change_attributes(inode, &outarg.attr,
917c79e322fSMiklos Szeredi 					       attr_timeout(&outarg),
9181fb69e78SMiklos Szeredi 					       attr_version);
9191fb69e78SMiklos Szeredi 			if (stat)
920c79e322fSMiklos Szeredi 				fuse_fillattr(inode, &outarg.attr, stat);
921e5e5558eSMiklos Szeredi 		}
922e5e5558eSMiklos Szeredi 	}
923e5e5558eSMiklos Szeredi 	return err;
924e5e5558eSMiklos Szeredi }
925e5e5558eSMiklos Szeredi 
9265b97eeacSMiklos Szeredi static int fuse_update_get_attr(struct inode *inode, struct file *file,
927ff1b89f3SMiklos Szeredi 				struct kstat *stat, unsigned int flags)
928bcb4be80SMiklos Szeredi {
929bcb4be80SMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
9305b97eeacSMiklos Szeredi 	int err = 0;
931bf5c1898SMiklos Szeredi 	bool sync;
932bcb4be80SMiklos Szeredi 
933bf5c1898SMiklos Szeredi 	if (flags & AT_STATX_FORCE_SYNC)
934bf5c1898SMiklos Szeredi 		sync = true;
935bf5c1898SMiklos Szeredi 	else if (flags & AT_STATX_DONT_SYNC)
936bf5c1898SMiklos Szeredi 		sync = false;
937bf5c1898SMiklos Szeredi 	else
938bf5c1898SMiklos Szeredi 		sync = time_before64(fi->i_time, get_jiffies_64());
939bf5c1898SMiklos Szeredi 
940bf5c1898SMiklos Szeredi 	if (sync) {
94160bcc88aSSeth Forshee 		forget_all_cached_acls(inode);
942bcb4be80SMiklos Szeredi 		err = fuse_do_getattr(inode, stat, file);
9435b97eeacSMiklos Szeredi 	} else if (stat) {
944bcb4be80SMiklos Szeredi 		generic_fillattr(inode, stat);
945bcb4be80SMiklos Szeredi 		stat->mode = fi->orig_i_mode;
94645c72cd7SPavel Shilovsky 		stat->ino = fi->orig_ino;
947bcb4be80SMiklos Szeredi 	}
948bcb4be80SMiklos Szeredi 
949bcb4be80SMiklos Szeredi 	return err;
950bcb4be80SMiklos Szeredi }
951bcb4be80SMiklos Szeredi 
9525b97eeacSMiklos Szeredi int fuse_update_attributes(struct inode *inode, struct file *file)
9535b97eeacSMiklos Szeredi {
954ff1b89f3SMiklos Szeredi 	return fuse_update_get_attr(inode, file, NULL, 0);
9555b97eeacSMiklos Szeredi }
9565b97eeacSMiklos Szeredi 
9573b463ae0SJohn Muir int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid,
958451d0f59SJohn Muir 			     u64 child_nodeid, struct qstr *name)
9593b463ae0SJohn Muir {
9603b463ae0SJohn Muir 	int err = -ENOTDIR;
9613b463ae0SJohn Muir 	struct inode *parent;
9623b463ae0SJohn Muir 	struct dentry *dir;
9633b463ae0SJohn Muir 	struct dentry *entry;
9643b463ae0SJohn Muir 
9653b463ae0SJohn Muir 	parent = ilookup5(sb, parent_nodeid, fuse_inode_eq, &parent_nodeid);
9663b463ae0SJohn Muir 	if (!parent)
9673b463ae0SJohn Muir 		return -ENOENT;
9683b463ae0SJohn Muir 
9695955102cSAl Viro 	inode_lock(parent);
9703b463ae0SJohn Muir 	if (!S_ISDIR(parent->i_mode))
9713b463ae0SJohn Muir 		goto unlock;
9723b463ae0SJohn Muir 
9733b463ae0SJohn Muir 	err = -ENOENT;
9743b463ae0SJohn Muir 	dir = d_find_alias(parent);
9753b463ae0SJohn Muir 	if (!dir)
9763b463ae0SJohn Muir 		goto unlock;
9773b463ae0SJohn Muir 
9788387ff25SLinus Torvalds 	name->hash = full_name_hash(dir, name->name, name->len);
9793b463ae0SJohn Muir 	entry = d_lookup(dir, name);
9803b463ae0SJohn Muir 	dput(dir);
9813b463ae0SJohn Muir 	if (!entry)
9823b463ae0SJohn Muir 		goto unlock;
9833b463ae0SJohn Muir 
9843b463ae0SJohn Muir 	fuse_invalidate_attr(parent);
9853b463ae0SJohn Muir 	fuse_invalidate_entry(entry);
986451d0f59SJohn Muir 
9872b0143b5SDavid Howells 	if (child_nodeid != 0 && d_really_is_positive(entry)) {
9885955102cSAl Viro 		inode_lock(d_inode(entry));
9892b0143b5SDavid Howells 		if (get_node_id(d_inode(entry)) != child_nodeid) {
990451d0f59SJohn Muir 			err = -ENOENT;
991451d0f59SJohn Muir 			goto badentry;
992451d0f59SJohn Muir 		}
993451d0f59SJohn Muir 		if (d_mountpoint(entry)) {
994451d0f59SJohn Muir 			err = -EBUSY;
995451d0f59SJohn Muir 			goto badentry;
996451d0f59SJohn Muir 		}
997e36cb0b8SDavid Howells 		if (d_is_dir(entry)) {
998451d0f59SJohn Muir 			shrink_dcache_parent(entry);
999451d0f59SJohn Muir 			if (!simple_empty(entry)) {
1000451d0f59SJohn Muir 				err = -ENOTEMPTY;
1001451d0f59SJohn Muir 				goto badentry;
1002451d0f59SJohn Muir 			}
10032b0143b5SDavid Howells 			d_inode(entry)->i_flags |= S_DEAD;
1004451d0f59SJohn Muir 		}
1005451d0f59SJohn Muir 		dont_mount(entry);
10062b0143b5SDavid Howells 		clear_nlink(d_inode(entry));
10073b463ae0SJohn Muir 		err = 0;
1008451d0f59SJohn Muir  badentry:
10095955102cSAl Viro 		inode_unlock(d_inode(entry));
1010451d0f59SJohn Muir 		if (!err)
1011451d0f59SJohn Muir 			d_delete(entry);
1012451d0f59SJohn Muir 	} else {
1013451d0f59SJohn Muir 		err = 0;
1014451d0f59SJohn Muir 	}
1015451d0f59SJohn Muir 	dput(entry);
10163b463ae0SJohn Muir 
10173b463ae0SJohn Muir  unlock:
10185955102cSAl Viro 	inode_unlock(parent);
10193b463ae0SJohn Muir 	iput(parent);
10203b463ae0SJohn Muir 	return err;
10213b463ae0SJohn Muir }
10223b463ae0SJohn Muir 
102387729a55SMiklos Szeredi /*
102487729a55SMiklos Szeredi  * Calling into a user-controlled filesystem gives the filesystem
1025c2132c1bSAnatol Pomozov  * daemon ptrace-like capabilities over the current process.  This
102687729a55SMiklos Szeredi  * means, that the filesystem daemon is able to record the exact
102787729a55SMiklos Szeredi  * filesystem operations performed, and can also control the behavior
102887729a55SMiklos Szeredi  * of the requester process in otherwise impossible ways.  For example
102987729a55SMiklos Szeredi  * it can delay the operation for arbitrary length of time allowing
103087729a55SMiklos Szeredi  * DoS against the requester.
103187729a55SMiklos Szeredi  *
103287729a55SMiklos Szeredi  * For this reason only those processes can call into the filesystem,
103387729a55SMiklos Szeredi  * for which the owner of the mount has ptrace privilege.  This
103487729a55SMiklos Szeredi  * excludes processes started by other users, suid or sgid processes.
103587729a55SMiklos Szeredi  */
1036c2132c1bSAnatol Pomozov int fuse_allow_current_process(struct fuse_conn *fc)
103787729a55SMiklos Szeredi {
1038c69e8d9cSDavid Howells 	const struct cred *cred;
1039c69e8d9cSDavid Howells 
104029433a29SMiklos Szeredi 	if (fc->allow_other)
104173f03c2bSSeth Forshee 		return current_in_userns(fc->user_ns);
104287729a55SMiklos Szeredi 
1043c2132c1bSAnatol Pomozov 	cred = current_cred();
1044499dcf20SEric W. Biederman 	if (uid_eq(cred->euid, fc->user_id) &&
1045499dcf20SEric W. Biederman 	    uid_eq(cred->suid, fc->user_id) &&
1046499dcf20SEric W. Biederman 	    uid_eq(cred->uid,  fc->user_id) &&
1047499dcf20SEric W. Biederman 	    gid_eq(cred->egid, fc->group_id) &&
1048499dcf20SEric W. Biederman 	    gid_eq(cred->sgid, fc->group_id) &&
1049499dcf20SEric W. Biederman 	    gid_eq(cred->gid,  fc->group_id))
1050c2132c1bSAnatol Pomozov 		return 1;
105187729a55SMiklos Szeredi 
1052c2132c1bSAnatol Pomozov 	return 0;
105387729a55SMiklos Szeredi }
105487729a55SMiklos Szeredi 
105531d40d74SMiklos Szeredi static int fuse_access(struct inode *inode, int mask)
105631d40d74SMiklos Szeredi {
105731d40d74SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
10587078187aSMiklos Szeredi 	FUSE_ARGS(args);
105931d40d74SMiklos Szeredi 	struct fuse_access_in inarg;
106031d40d74SMiklos Szeredi 	int err;
106131d40d74SMiklos Szeredi 
1062698fa1d1SMiklos Szeredi 	BUG_ON(mask & MAY_NOT_BLOCK);
1063698fa1d1SMiklos Szeredi 
106431d40d74SMiklos Szeredi 	if (fc->no_access)
106531d40d74SMiklos Szeredi 		return 0;
106631d40d74SMiklos Szeredi 
106731d40d74SMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
1068e6305c43SAl Viro 	inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC);
10697078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_ACCESS;
10707078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(inode);
10717078187aSMiklos Szeredi 	args.in.numargs = 1;
10727078187aSMiklos Szeredi 	args.in.args[0].size = sizeof(inarg);
10737078187aSMiklos Szeredi 	args.in.args[0].value = &inarg;
10747078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
107531d40d74SMiklos Szeredi 	if (err == -ENOSYS) {
107631d40d74SMiklos Szeredi 		fc->no_access = 1;
107731d40d74SMiklos Szeredi 		err = 0;
107831d40d74SMiklos Szeredi 	}
107931d40d74SMiklos Szeredi 	return err;
108031d40d74SMiklos Szeredi }
108131d40d74SMiklos Szeredi 
108210556cb2SAl Viro static int fuse_perm_getattr(struct inode *inode, int mask)
108319690ddbSMiklos Szeredi {
108410556cb2SAl Viro 	if (mask & MAY_NOT_BLOCK)
108519690ddbSMiklos Szeredi 		return -ECHILD;
108619690ddbSMiklos Szeredi 
108760bcc88aSSeth Forshee 	forget_all_cached_acls(inode);
108819690ddbSMiklos Szeredi 	return fuse_do_getattr(inode, NULL, NULL);
108919690ddbSMiklos Szeredi }
109019690ddbSMiklos Szeredi 
10916f9f1180SMiklos Szeredi /*
10926f9f1180SMiklos Szeredi  * Check permission.  The two basic access models of FUSE are:
10936f9f1180SMiklos Szeredi  *
10946f9f1180SMiklos Szeredi  * 1) Local access checking ('default_permissions' mount option) based
10956f9f1180SMiklos Szeredi  * on file mode.  This is the plain old disk filesystem permission
10966f9f1180SMiklos Szeredi  * modell.
10976f9f1180SMiklos Szeredi  *
10986f9f1180SMiklos Szeredi  * 2) "Remote" access checking, where server is responsible for
10996f9f1180SMiklos Szeredi  * checking permission in each inode operation.  An exception to this
11006f9f1180SMiklos Szeredi  * is if ->permission() was invoked from sys_access() in which case an
11016f9f1180SMiklos Szeredi  * access request is sent.  Execute permission is still checked
11026f9f1180SMiklos Szeredi  * locally based on file mode.
11036f9f1180SMiklos Szeredi  */
110410556cb2SAl Viro static int fuse_permission(struct inode *inode, int mask)
1105e5e5558eSMiklos Szeredi {
1106e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1107244f6385SMiklos Szeredi 	bool refreshed = false;
1108244f6385SMiklos Szeredi 	int err = 0;
1109e5e5558eSMiklos Szeredi 
1110c2132c1bSAnatol Pomozov 	if (!fuse_allow_current_process(fc))
1111e5e5558eSMiklos Szeredi 		return -EACCES;
1112244f6385SMiklos Szeredi 
1113244f6385SMiklos Szeredi 	/*
1114e8e96157SMiklos Szeredi 	 * If attributes are needed, refresh them before proceeding
1115244f6385SMiklos Szeredi 	 */
111629433a29SMiklos Szeredi 	if (fc->default_permissions ||
1117e8e96157SMiklos Szeredi 	    ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
111819690ddbSMiklos Szeredi 		struct fuse_inode *fi = get_fuse_inode(inode);
111919690ddbSMiklos Szeredi 
1120126b9d43SMiklos Szeredi 		if (time_before64(fi->i_time, get_jiffies_64())) {
112119690ddbSMiklos Szeredi 			refreshed = true;
112219690ddbSMiklos Szeredi 
112310556cb2SAl Viro 			err = fuse_perm_getattr(inode, mask);
1124244f6385SMiklos Szeredi 			if (err)
1125244f6385SMiklos Szeredi 				return err;
11261fb69e78SMiklos Szeredi 		}
112719690ddbSMiklos Szeredi 	}
1128244f6385SMiklos Szeredi 
112929433a29SMiklos Szeredi 	if (fc->default_permissions) {
11302830ba7fSAl Viro 		err = generic_permission(inode, mask);
11311e9a4ed9SMiklos Szeredi 
11321e9a4ed9SMiklos Szeredi 		/* If permission is denied, try to refresh file
11331e9a4ed9SMiklos Szeredi 		   attributes.  This is also needed, because the root
11341e9a4ed9SMiklos Szeredi 		   node will at first have no permissions */
1135244f6385SMiklos Szeredi 		if (err == -EACCES && !refreshed) {
113610556cb2SAl Viro 			err = fuse_perm_getattr(inode, mask);
11371e9a4ed9SMiklos Szeredi 			if (!err)
11382830ba7fSAl Viro 				err = generic_permission(inode, mask);
11391e9a4ed9SMiklos Szeredi 		}
11401e9a4ed9SMiklos Szeredi 
11416f9f1180SMiklos Szeredi 		/* Note: the opposite of the above test does not
11426f9f1180SMiklos Szeredi 		   exist.  So if permissions are revoked this won't be
11436f9f1180SMiklos Szeredi 		   noticed immediately, only after the attribute
11446f9f1180SMiklos Szeredi 		   timeout has expired */
11459cfcac81SEric Paris 	} else if (mask & (MAY_ACCESS | MAY_CHDIR)) {
1146e8e96157SMiklos Szeredi 		err = fuse_access(inode, mask);
1147e8e96157SMiklos Szeredi 	} else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
1148e8e96157SMiklos Szeredi 		if (!(inode->i_mode & S_IXUGO)) {
1149e8e96157SMiklos Szeredi 			if (refreshed)
1150e5e5558eSMiklos Szeredi 				return -EACCES;
115131d40d74SMiklos Szeredi 
115210556cb2SAl Viro 			err = fuse_perm_getattr(inode, mask);
1153e8e96157SMiklos Szeredi 			if (!err && !(inode->i_mode & S_IXUGO))
1154e8e96157SMiklos Szeredi 				return -EACCES;
1155e8e96157SMiklos Szeredi 		}
1156e5e5558eSMiklos Szeredi 	}
1157244f6385SMiklos Szeredi 	return err;
1158e5e5558eSMiklos Szeredi }
1159e5e5558eSMiklos Szeredi 
1160e5e5558eSMiklos Szeredi static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
11618d3af7f3SAl Viro 			 struct dir_context *ctx)
1162e5e5558eSMiklos Szeredi {
1163e5e5558eSMiklos Szeredi 	while (nbytes >= FUSE_NAME_OFFSET) {
1164e5e5558eSMiklos Szeredi 		struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
1165e5e5558eSMiklos Szeredi 		size_t reclen = FUSE_DIRENT_SIZE(dirent);
1166e5e5558eSMiklos Szeredi 		if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
1167e5e5558eSMiklos Szeredi 			return -EIO;
1168e5e5558eSMiklos Szeredi 		if (reclen > nbytes)
1169e5e5558eSMiklos Szeredi 			break;
1170efeb9e60SMiklos Szeredi 		if (memchr(dirent->name, '/', dirent->namelen) != NULL)
1171efeb9e60SMiklos Szeredi 			return -EIO;
1172e5e5558eSMiklos Szeredi 
11738d3af7f3SAl Viro 		if (!dir_emit(ctx, dirent->name, dirent->namelen,
11748d3af7f3SAl Viro 			       dirent->ino, dirent->type))
1175e5e5558eSMiklos Szeredi 			break;
1176e5e5558eSMiklos Szeredi 
1177e5e5558eSMiklos Szeredi 		buf += reclen;
1178e5e5558eSMiklos Szeredi 		nbytes -= reclen;
11798d3af7f3SAl Viro 		ctx->pos = dirent->off;
1180e5e5558eSMiklos Szeredi 	}
1181e5e5558eSMiklos Szeredi 
1182e5e5558eSMiklos Szeredi 	return 0;
1183e5e5558eSMiklos Szeredi }
1184e5e5558eSMiklos Szeredi 
11850b05b183SAnand V. Avati static int fuse_direntplus_link(struct file *file,
11860b05b183SAnand V. Avati 				struct fuse_direntplus *direntplus,
11870b05b183SAnand V. Avati 				u64 attr_version)
11880b05b183SAnand V. Avati {
11890b05b183SAnand V. Avati 	struct fuse_entry_out *o = &direntplus->entry_out;
11900b05b183SAnand V. Avati 	struct fuse_dirent *dirent = &direntplus->dirent;
11910b05b183SAnand V. Avati 	struct dentry *parent = file->f_path.dentry;
11920b05b183SAnand V. Avati 	struct qstr name = QSTR_INIT(dirent->name, dirent->namelen);
11930b05b183SAnand V. Avati 	struct dentry *dentry;
11940b05b183SAnand V. Avati 	struct dentry *alias;
11952b0143b5SDavid Howells 	struct inode *dir = d_inode(parent);
11960b05b183SAnand V. Avati 	struct fuse_conn *fc;
11970b05b183SAnand V. Avati 	struct inode *inode;
1198d9b3dbdcSAl Viro 	DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
11990b05b183SAnand V. Avati 
12000b05b183SAnand V. Avati 	if (!o->nodeid) {
12010b05b183SAnand V. Avati 		/*
12020b05b183SAnand V. Avati 		 * Unlike in the case of fuse_lookup, zero nodeid does not mean
12030b05b183SAnand V. Avati 		 * ENOENT. Instead, it only means the userspace filesystem did
12040b05b183SAnand V. Avati 		 * not want to return attributes/handle for this entry.
12050b05b183SAnand V. Avati 		 *
12060b05b183SAnand V. Avati 		 * So do nothing.
12070b05b183SAnand V. Avati 		 */
12080b05b183SAnand V. Avati 		return 0;
12090b05b183SAnand V. Avati 	}
12100b05b183SAnand V. Avati 
12110b05b183SAnand V. Avati 	if (name.name[0] == '.') {
12120b05b183SAnand V. Avati 		/*
12130b05b183SAnand V. Avati 		 * We could potentially refresh the attributes of the directory
12140b05b183SAnand V. Avati 		 * and its parent?
12150b05b183SAnand V. Avati 		 */
12160b05b183SAnand V. Avati 		if (name.len == 1)
12170b05b183SAnand V. Avati 			return 0;
12180b05b183SAnand V. Avati 		if (name.name[1] == '.' && name.len == 2)
12190b05b183SAnand V. Avati 			return 0;
12200b05b183SAnand V. Avati 	}
1221a28ef45cSMiklos Szeredi 
1222a28ef45cSMiklos Szeredi 	if (invalid_nodeid(o->nodeid))
1223a28ef45cSMiklos Szeredi 		return -EIO;
1224a28ef45cSMiklos Szeredi 	if (!fuse_valid_type(o->attr.mode))
1225a28ef45cSMiklos Szeredi 		return -EIO;
1226a28ef45cSMiklos Szeredi 
12270b05b183SAnand V. Avati 	fc = get_fuse_conn(dir);
12280b05b183SAnand V. Avati 
12298387ff25SLinus Torvalds 	name.hash = full_name_hash(parent, name.name, name.len);
12300b05b183SAnand V. Avati 	dentry = d_lookup(parent, &name);
1231d9b3dbdcSAl Viro 	if (!dentry) {
1232d9b3dbdcSAl Viro retry:
1233d9b3dbdcSAl Viro 		dentry = d_alloc_parallel(parent, &name, &wq);
1234d9b3dbdcSAl Viro 		if (IS_ERR(dentry))
1235d9b3dbdcSAl Viro 			return PTR_ERR(dentry);
1236d9b3dbdcSAl Viro 	}
1237d9b3dbdcSAl Viro 	if (!d_in_lookup(dentry)) {
1238d9b3dbdcSAl Viro 		struct fuse_inode *fi;
12392b0143b5SDavid Howells 		inode = d_inode(dentry);
1240d9b3dbdcSAl Viro 		if (!inode ||
1241d9b3dbdcSAl Viro 		    get_node_id(inode) != o->nodeid ||
1242a28ef45cSMiklos Szeredi 		    ((o->attr.mode ^ inode->i_mode) & S_IFMT)) {
12435542aa2fSEric W. Biederman 			d_invalidate(dentry);
1244d9b3dbdcSAl Viro 			dput(dentry);
1245d9b3dbdcSAl Viro 			goto retry;
1246d9b3dbdcSAl Viro 		}
1247d9b3dbdcSAl Viro 		if (is_bad_inode(inode)) {
1248d9b3dbdcSAl Viro 			dput(dentry);
1249d9b3dbdcSAl Viro 			return -EIO;
1250d9b3dbdcSAl Viro 		}
1251d9b3dbdcSAl Viro 
12520b05b183SAnand V. Avati 		fi = get_fuse_inode(inode);
12530b05b183SAnand V. Avati 		spin_lock(&fc->lock);
12540b05b183SAnand V. Avati 		fi->nlookup++;
12550b05b183SAnand V. Avati 		spin_unlock(&fc->lock);
12560b05b183SAnand V. Avati 
125760bcc88aSSeth Forshee 		forget_all_cached_acls(inode);
1258fa2b7213SMiklos Szeredi 		fuse_change_attributes(inode, &o->attr,
1259fa2b7213SMiklos Szeredi 				       entry_attr_timeout(o),
1260fa2b7213SMiklos Szeredi 				       attr_version);
12610b05b183SAnand V. Avati 		/*
1262d9b3dbdcSAl Viro 		 * The other branch comes via fuse_iget()
12630b05b183SAnand V. Avati 		 * which bumps nlookup inside
12640b05b183SAnand V. Avati 		 */
1265d9b3dbdcSAl Viro 	} else {
12660b05b183SAnand V. Avati 		inode = fuse_iget(dir->i_sb, o->nodeid, o->generation,
1267d9b3dbdcSAl Viro 				  &o->attr, entry_attr_timeout(o),
1268d9b3dbdcSAl Viro 				  attr_version);
12690b05b183SAnand V. Avati 		if (!inode)
1270d9b3dbdcSAl Viro 			inode = ERR_PTR(-ENOMEM);
12710b05b183SAnand V. Avati 
127241d28bcaSAl Viro 		alias = d_splice_alias(inode, dentry);
1273d9b3dbdcSAl Viro 		d_lookup_done(dentry);
12740b05b183SAnand V. Avati 		if (alias) {
12750b05b183SAnand V. Avati 			dput(dentry);
12760b05b183SAnand V. Avati 			dentry = alias;
12770b05b183SAnand V. Avati 		}
1278d9b3dbdcSAl Viro 		if (IS_ERR(dentry))
1279d9b3dbdcSAl Viro 			return PTR_ERR(dentry);
1280d9b3dbdcSAl Viro 	}
12816314efeeSMiklos Szeredi 	if (fc->readdirplus_auto)
12826314efeeSMiklos Szeredi 		set_bit(FUSE_I_INIT_RDPLUS, &get_fuse_inode(inode)->state);
12830b05b183SAnand V. Avati 	fuse_change_entry_timeout(dentry, o);
12840b05b183SAnand V. Avati 
12850b05b183SAnand V. Avati 	dput(dentry);
1286d9b3dbdcSAl Viro 	return 0;
12870b05b183SAnand V. Avati }
12880b05b183SAnand V. Avati 
12890b05b183SAnand V. Avati static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file,
12908d3af7f3SAl Viro 			     struct dir_context *ctx, u64 attr_version)
12910b05b183SAnand V. Avati {
12920b05b183SAnand V. Avati 	struct fuse_direntplus *direntplus;
12930b05b183SAnand V. Avati 	struct fuse_dirent *dirent;
12940b05b183SAnand V. Avati 	size_t reclen;
12950b05b183SAnand V. Avati 	int over = 0;
12960b05b183SAnand V. Avati 	int ret;
12970b05b183SAnand V. Avati 
12980b05b183SAnand V. Avati 	while (nbytes >= FUSE_NAME_OFFSET_DIRENTPLUS) {
12990b05b183SAnand V. Avati 		direntplus = (struct fuse_direntplus *) buf;
13000b05b183SAnand V. Avati 		dirent = &direntplus->dirent;
13010b05b183SAnand V. Avati 		reclen = FUSE_DIRENTPLUS_SIZE(direntplus);
13020b05b183SAnand V. Avati 
13030b05b183SAnand V. Avati 		if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
13040b05b183SAnand V. Avati 			return -EIO;
13050b05b183SAnand V. Avati 		if (reclen > nbytes)
13060b05b183SAnand V. Avati 			break;
1307efeb9e60SMiklos Szeredi 		if (memchr(dirent->name, '/', dirent->namelen) != NULL)
1308efeb9e60SMiklos Szeredi 			return -EIO;
13090b05b183SAnand V. Avati 
13100b05b183SAnand V. Avati 		if (!over) {
13110b05b183SAnand V. Avati 			/* We fill entries into dstbuf only as much as
13120b05b183SAnand V. Avati 			   it can hold. But we still continue iterating
13130b05b183SAnand V. Avati 			   over remaining entries to link them. If not,
13140b05b183SAnand V. Avati 			   we need to send a FORGET for each of those
13150b05b183SAnand V. Avati 			   which we did not link.
13160b05b183SAnand V. Avati 			*/
13178d3af7f3SAl Viro 			over = !dir_emit(ctx, dirent->name, dirent->namelen,
13188d3af7f3SAl Viro 				       dirent->ino, dirent->type);
1319c6cdd514SMiklos Szeredi 			if (!over)
13208d3af7f3SAl Viro 				ctx->pos = dirent->off;
13210b05b183SAnand V. Avati 		}
13220b05b183SAnand V. Avati 
13230b05b183SAnand V. Avati 		buf += reclen;
13240b05b183SAnand V. Avati 		nbytes -= reclen;
13250b05b183SAnand V. Avati 
13260b05b183SAnand V. Avati 		ret = fuse_direntplus_link(file, direntplus, attr_version);
13270b05b183SAnand V. Avati 		if (ret)
13280b05b183SAnand V. Avati 			fuse_force_forget(file, direntplus->entry_out.nodeid);
13290b05b183SAnand V. Avati 	}
13300b05b183SAnand V. Avati 
13310b05b183SAnand V. Avati 	return 0;
13320b05b183SAnand V. Avati }
13330b05b183SAnand V. Avati 
13348d3af7f3SAl Viro static int fuse_readdir(struct file *file, struct dir_context *ctx)
1335e5e5558eSMiklos Szeredi {
13364582a4abSFeng Shuo 	int plus, err;
133704730fefSMiklos Szeredi 	size_t nbytes;
133804730fefSMiklos Szeredi 	struct page *page;
1339496ad9aaSAl Viro 	struct inode *inode = file_inode(file);
134004730fefSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1341248d86e8SMiklos Szeredi 	struct fuse_req *req;
13420b05b183SAnand V. Avati 	u64 attr_version = 0;
1343248d86e8SMiklos Szeredi 
1344248d86e8SMiklos Szeredi 	if (is_bad_inode(inode))
1345248d86e8SMiklos Szeredi 		return -EIO;
1346248d86e8SMiklos Szeredi 
1347b111c8c0SMaxim Patlasov 	req = fuse_get_req(fc, 1);
1348ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1349ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
1350e5e5558eSMiklos Szeredi 
135104730fefSMiklos Szeredi 	page = alloc_page(GFP_KERNEL);
135204730fefSMiklos Szeredi 	if (!page) {
135304730fefSMiklos Szeredi 		fuse_put_request(fc, req);
1354e5e5558eSMiklos Szeredi 		return -ENOMEM;
135504730fefSMiklos Szeredi 	}
13564582a4abSFeng Shuo 
13578d3af7f3SAl Viro 	plus = fuse_use_readdirplus(inode, ctx);
1358f4975c67SMiklos Szeredi 	req->out.argpages = 1;
135904730fefSMiklos Szeredi 	req->num_pages = 1;
136004730fefSMiklos Szeredi 	req->pages[0] = page;
136185f40aecSMaxim Patlasov 	req->page_descs[0].length = PAGE_SIZE;
13624582a4abSFeng Shuo 	if (plus) {
13630b05b183SAnand V. Avati 		attr_version = fuse_get_attr_version(fc);
13648d3af7f3SAl Viro 		fuse_read_fill(req, file, ctx->pos, PAGE_SIZE,
13650b05b183SAnand V. Avati 			       FUSE_READDIRPLUS);
13660b05b183SAnand V. Avati 	} else {
13678d3af7f3SAl Viro 		fuse_read_fill(req, file, ctx->pos, PAGE_SIZE,
13680b05b183SAnand V. Avati 			       FUSE_READDIR);
13690b05b183SAnand V. Avati 	}
13705c672ab3SMiklos Szeredi 	fuse_lock_inode(inode);
1371b93f858aSTejun Heo 	fuse_request_send(fc, req);
13725c672ab3SMiklos Szeredi 	fuse_unlock_inode(inode);
1373361b1eb5SMiklos Szeredi 	nbytes = req->out.args[0].size;
137404730fefSMiklos Szeredi 	err = req->out.h.error;
137504730fefSMiklos Szeredi 	fuse_put_request(fc, req);
13760b05b183SAnand V. Avati 	if (!err) {
13774582a4abSFeng Shuo 		if (plus) {
13780b05b183SAnand V. Avati 			err = parse_dirplusfile(page_address(page), nbytes,
13798d3af7f3SAl Viro 						file, ctx,
13800b05b183SAnand V. Avati 						attr_version);
13810b05b183SAnand V. Avati 		} else {
13820b05b183SAnand V. Avati 			err = parse_dirfile(page_address(page), nbytes, file,
13838d3af7f3SAl Viro 					    ctx);
13840b05b183SAnand V. Avati 		}
13850b05b183SAnand V. Avati 	}
1386e5e5558eSMiklos Szeredi 
138704730fefSMiklos Szeredi 	__free_page(page);
1388451418fcSAndrew Gallagher 	fuse_invalidate_atime(inode);
138904730fefSMiklos Szeredi 	return err;
1390e5e5558eSMiklos Szeredi }
1391e5e5558eSMiklos Szeredi 
13926b255391SAl Viro static const char *fuse_get_link(struct dentry *dentry,
1393fceef393SAl Viro 				 struct inode *inode,
1394fceef393SAl Viro 				 struct delayed_call *done)
1395e5e5558eSMiklos Szeredi {
1396e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
13977078187aSMiklos Szeredi 	FUSE_ARGS(args);
1398e5e5558eSMiklos Szeredi 	char *link;
13997078187aSMiklos Szeredi 	ssize_t ret;
1400e5e5558eSMiklos Szeredi 
14016b255391SAl Viro 	if (!dentry)
14026b255391SAl Viro 		return ERR_PTR(-ECHILD);
14036b255391SAl Viro 
1404cd3417c8SAl Viro 	link = kmalloc(PAGE_SIZE, GFP_KERNEL);
14057078187aSMiklos Szeredi 	if (!link)
14067078187aSMiklos Szeredi 		return ERR_PTR(-ENOMEM);
14077078187aSMiklos Szeredi 
14087078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_READLINK;
14097078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(inode);
14107078187aSMiklos Szeredi 	args.out.argvar = 1;
14117078187aSMiklos Szeredi 	args.out.numargs = 1;
14127078187aSMiklos Szeredi 	args.out.args[0].size = PAGE_SIZE - 1;
14137078187aSMiklos Szeredi 	args.out.args[0].value = link;
14147078187aSMiklos Szeredi 	ret = fuse_simple_request(fc, &args);
14157078187aSMiklos Szeredi 	if (ret < 0) {
1416cd3417c8SAl Viro 		kfree(link);
14177078187aSMiklos Szeredi 		link = ERR_PTR(ret);
14187078187aSMiklos Szeredi 	} else {
14197078187aSMiklos Szeredi 		link[ret] = '\0';
1420fceef393SAl Viro 		set_delayed_call(done, kfree_link, link);
14217078187aSMiklos Szeredi 	}
1422451418fcSAndrew Gallagher 	fuse_invalidate_atime(inode);
1423e5e5558eSMiklos Szeredi 	return link;
1424e5e5558eSMiklos Szeredi }
1425e5e5558eSMiklos Szeredi 
1426e5e5558eSMiklos Szeredi static int fuse_dir_open(struct inode *inode, struct file *file)
1427e5e5558eSMiklos Szeredi {
142891fe96b4SMiklos Szeredi 	return fuse_open_common(inode, file, true);
1429e5e5558eSMiklos Szeredi }
1430e5e5558eSMiklos Szeredi 
1431e5e5558eSMiklos Szeredi static int fuse_dir_release(struct inode *inode, struct file *file)
1432e5e5558eSMiklos Szeredi {
14338b0797a4SMiklos Szeredi 	fuse_release_common(file, FUSE_RELEASEDIR);
14348b0797a4SMiklos Szeredi 
14358b0797a4SMiklos Szeredi 	return 0;
1436e5e5558eSMiklos Szeredi }
1437e5e5558eSMiklos Szeredi 
143802c24a82SJosef Bacik static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end,
143902c24a82SJosef Bacik 			  int datasync)
144082547981SMiklos Szeredi {
144102c24a82SJosef Bacik 	return fuse_fsync_common(file, start, end, datasync, 1);
144282547981SMiklos Szeredi }
144382547981SMiklos Szeredi 
1444b18da0c5SMiklos Szeredi static long fuse_dir_ioctl(struct file *file, unsigned int cmd,
1445b18da0c5SMiklos Szeredi 			    unsigned long arg)
1446b18da0c5SMiklos Szeredi {
1447b18da0c5SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1448b18da0c5SMiklos Szeredi 
1449b18da0c5SMiklos Szeredi 	/* FUSE_IOCTL_DIR only supported for API version >= 7.18 */
1450b18da0c5SMiklos Szeredi 	if (fc->minor < 18)
1451b18da0c5SMiklos Szeredi 		return -ENOTTY;
1452b18da0c5SMiklos Szeredi 
1453b18da0c5SMiklos Szeredi 	return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR);
1454b18da0c5SMiklos Szeredi }
1455b18da0c5SMiklos Szeredi 
1456b18da0c5SMiklos Szeredi static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd,
1457b18da0c5SMiklos Szeredi 				   unsigned long arg)
1458b18da0c5SMiklos Szeredi {
1459b18da0c5SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1460b18da0c5SMiklos Szeredi 
1461b18da0c5SMiklos Szeredi 	if (fc->minor < 18)
1462b18da0c5SMiklos Szeredi 		return -ENOTTY;
1463b18da0c5SMiklos Szeredi 
1464b18da0c5SMiklos Szeredi 	return fuse_ioctl_common(file, cmd, arg,
1465b18da0c5SMiklos Szeredi 				 FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR);
1466b18da0c5SMiklos Szeredi }
1467b18da0c5SMiklos Szeredi 
1468b0aa7606SMaxim Patlasov static bool update_mtime(unsigned ivalid, bool trust_local_mtime)
146917637cbaSMiklos Szeredi {
147017637cbaSMiklos Szeredi 	/* Always update if mtime is explicitly set  */
147117637cbaSMiklos Szeredi 	if (ivalid & ATTR_MTIME_SET)
147217637cbaSMiklos Szeredi 		return true;
147317637cbaSMiklos Szeredi 
1474b0aa7606SMaxim Patlasov 	/* Or if kernel i_mtime is the official one */
1475b0aa7606SMaxim Patlasov 	if (trust_local_mtime)
1476b0aa7606SMaxim Patlasov 		return true;
1477b0aa7606SMaxim Patlasov 
147817637cbaSMiklos Szeredi 	/* If it's an open(O_TRUNC) or an ftruncate(), don't update */
147917637cbaSMiklos Szeredi 	if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
148017637cbaSMiklos Szeredi 		return false;
148117637cbaSMiklos Szeredi 
148217637cbaSMiklos Szeredi 	/* In all other cases update */
148317637cbaSMiklos Szeredi 	return true;
148417637cbaSMiklos Szeredi }
148517637cbaSMiklos Szeredi 
14868cb08329SEric W. Biederman static void iattr_to_fattr(struct fuse_conn *fc, struct iattr *iattr,
14878cb08329SEric W. Biederman 			   struct fuse_setattr_in *arg, bool trust_local_cmtime)
14889e6268dbSMiklos Szeredi {
14899e6268dbSMiklos Szeredi 	unsigned ivalid = iattr->ia_valid;
14909e6268dbSMiklos Szeredi 
14919e6268dbSMiklos Szeredi 	if (ivalid & ATTR_MODE)
1492befc649cSMiklos Szeredi 		arg->valid |= FATTR_MODE,   arg->mode = iattr->ia_mode;
14939e6268dbSMiklos Szeredi 	if (ivalid & ATTR_UID)
14948cb08329SEric W. Biederman 		arg->valid |= FATTR_UID,    arg->uid = from_kuid(fc->user_ns, iattr->ia_uid);
14959e6268dbSMiklos Szeredi 	if (ivalid & ATTR_GID)
14968cb08329SEric W. Biederman 		arg->valid |= FATTR_GID,    arg->gid = from_kgid(fc->user_ns, iattr->ia_gid);
14979e6268dbSMiklos Szeredi 	if (ivalid & ATTR_SIZE)
1498befc649cSMiklos Szeredi 		arg->valid |= FATTR_SIZE,   arg->size = iattr->ia_size;
149917637cbaSMiklos Szeredi 	if (ivalid & ATTR_ATIME) {
150017637cbaSMiklos Szeredi 		arg->valid |= FATTR_ATIME;
1501befc649cSMiklos Szeredi 		arg->atime = iattr->ia_atime.tv_sec;
150217637cbaSMiklos Szeredi 		arg->atimensec = iattr->ia_atime.tv_nsec;
150317637cbaSMiklos Szeredi 		if (!(ivalid & ATTR_ATIME_SET))
150417637cbaSMiklos Szeredi 			arg->valid |= FATTR_ATIME_NOW;
150517637cbaSMiklos Szeredi 	}
15063ad22c62SMaxim Patlasov 	if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, trust_local_cmtime)) {
150717637cbaSMiklos Szeredi 		arg->valid |= FATTR_MTIME;
1508befc649cSMiklos Szeredi 		arg->mtime = iattr->ia_mtime.tv_sec;
150917637cbaSMiklos Szeredi 		arg->mtimensec = iattr->ia_mtime.tv_nsec;
15103ad22c62SMaxim Patlasov 		if (!(ivalid & ATTR_MTIME_SET) && !trust_local_cmtime)
151117637cbaSMiklos Szeredi 			arg->valid |= FATTR_MTIME_NOW;
15129e6268dbSMiklos Szeredi 	}
15133ad22c62SMaxim Patlasov 	if ((ivalid & ATTR_CTIME) && trust_local_cmtime) {
15143ad22c62SMaxim Patlasov 		arg->valid |= FATTR_CTIME;
15153ad22c62SMaxim Patlasov 		arg->ctime = iattr->ia_ctime.tv_sec;
15163ad22c62SMaxim Patlasov 		arg->ctimensec = iattr->ia_ctime.tv_nsec;
15173ad22c62SMaxim Patlasov 	}
15189e6268dbSMiklos Szeredi }
15199e6268dbSMiklos Szeredi 
15206f9f1180SMiklos Szeredi /*
15213be5a52bSMiklos Szeredi  * Prevent concurrent writepages on inode
15223be5a52bSMiklos Szeredi  *
15233be5a52bSMiklos Szeredi  * This is done by adding a negative bias to the inode write counter
15243be5a52bSMiklos Szeredi  * and waiting for all pending writes to finish.
15253be5a52bSMiklos Szeredi  */
15263be5a52bSMiklos Szeredi void fuse_set_nowrite(struct inode *inode)
15273be5a52bSMiklos Szeredi {
15283be5a52bSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
15293be5a52bSMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
15303be5a52bSMiklos Szeredi 
15315955102cSAl Viro 	BUG_ON(!inode_is_locked(inode));
15323be5a52bSMiklos Szeredi 
15333be5a52bSMiklos Szeredi 	spin_lock(&fc->lock);
15343be5a52bSMiklos Szeredi 	BUG_ON(fi->writectr < 0);
15353be5a52bSMiklos Szeredi 	fi->writectr += FUSE_NOWRITE;
15363be5a52bSMiklos Szeredi 	spin_unlock(&fc->lock);
15373be5a52bSMiklos Szeredi 	wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE);
15383be5a52bSMiklos Szeredi }
15393be5a52bSMiklos Szeredi 
15403be5a52bSMiklos Szeredi /*
15413be5a52bSMiklos Szeredi  * Allow writepages on inode
15423be5a52bSMiklos Szeredi  *
15433be5a52bSMiklos Szeredi  * Remove the bias from the writecounter and send any queued
15443be5a52bSMiklos Szeredi  * writepages.
15453be5a52bSMiklos Szeredi  */
15463be5a52bSMiklos Szeredi static void __fuse_release_nowrite(struct inode *inode)
15473be5a52bSMiklos Szeredi {
15483be5a52bSMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
15493be5a52bSMiklos Szeredi 
15503be5a52bSMiklos Szeredi 	BUG_ON(fi->writectr != FUSE_NOWRITE);
15513be5a52bSMiklos Szeredi 	fi->writectr = 0;
15523be5a52bSMiklos Szeredi 	fuse_flush_writepages(inode);
15533be5a52bSMiklos Szeredi }
15543be5a52bSMiklos Szeredi 
15553be5a52bSMiklos Szeredi void fuse_release_nowrite(struct inode *inode)
15563be5a52bSMiklos Szeredi {
15573be5a52bSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
15583be5a52bSMiklos Szeredi 
15593be5a52bSMiklos Szeredi 	spin_lock(&fc->lock);
15603be5a52bSMiklos Szeredi 	__fuse_release_nowrite(inode);
15613be5a52bSMiklos Szeredi 	spin_unlock(&fc->lock);
15623be5a52bSMiklos Szeredi }
15633be5a52bSMiklos Szeredi 
15647078187aSMiklos Szeredi static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_args *args,
1565b0aa7606SMaxim Patlasov 			      struct inode *inode,
1566b0aa7606SMaxim Patlasov 			      struct fuse_setattr_in *inarg_p,
1567b0aa7606SMaxim Patlasov 			      struct fuse_attr_out *outarg_p)
1568b0aa7606SMaxim Patlasov {
15697078187aSMiklos Szeredi 	args->in.h.opcode = FUSE_SETATTR;
15707078187aSMiklos Szeredi 	args->in.h.nodeid = get_node_id(inode);
15717078187aSMiklos Szeredi 	args->in.numargs = 1;
15727078187aSMiklos Szeredi 	args->in.args[0].size = sizeof(*inarg_p);
15737078187aSMiklos Szeredi 	args->in.args[0].value = inarg_p;
15747078187aSMiklos Szeredi 	args->out.numargs = 1;
15757078187aSMiklos Szeredi 	args->out.args[0].size = sizeof(*outarg_p);
15767078187aSMiklos Szeredi 	args->out.args[0].value = outarg_p;
1577b0aa7606SMaxim Patlasov }
1578b0aa7606SMaxim Patlasov 
1579b0aa7606SMaxim Patlasov /*
1580b0aa7606SMaxim Patlasov  * Flush inode->i_mtime to the server
1581b0aa7606SMaxim Patlasov  */
1582ab9e13f7SMaxim Patlasov int fuse_flush_times(struct inode *inode, struct fuse_file *ff)
1583b0aa7606SMaxim Patlasov {
1584b0aa7606SMaxim Patlasov 	struct fuse_conn *fc = get_fuse_conn(inode);
15857078187aSMiklos Szeredi 	FUSE_ARGS(args);
1586b0aa7606SMaxim Patlasov 	struct fuse_setattr_in inarg;
1587b0aa7606SMaxim Patlasov 	struct fuse_attr_out outarg;
1588b0aa7606SMaxim Patlasov 
1589b0aa7606SMaxim Patlasov 	memset(&inarg, 0, sizeof(inarg));
1590b0aa7606SMaxim Patlasov 	memset(&outarg, 0, sizeof(outarg));
1591b0aa7606SMaxim Patlasov 
1592ab9e13f7SMaxim Patlasov 	inarg.valid = FATTR_MTIME;
1593b0aa7606SMaxim Patlasov 	inarg.mtime = inode->i_mtime.tv_sec;
1594b0aa7606SMaxim Patlasov 	inarg.mtimensec = inode->i_mtime.tv_nsec;
1595ab9e13f7SMaxim Patlasov 	if (fc->minor >= 23) {
1596ab9e13f7SMaxim Patlasov 		inarg.valid |= FATTR_CTIME;
1597ab9e13f7SMaxim Patlasov 		inarg.ctime = inode->i_ctime.tv_sec;
1598ab9e13f7SMaxim Patlasov 		inarg.ctimensec = inode->i_ctime.tv_nsec;
1599ab9e13f7SMaxim Patlasov 	}
16001e18bda8SMiklos Szeredi 	if (ff) {
16011e18bda8SMiklos Szeredi 		inarg.valid |= FATTR_FH;
16021e18bda8SMiklos Szeredi 		inarg.fh = ff->fh;
16031e18bda8SMiklos Szeredi 	}
16047078187aSMiklos Szeredi 	fuse_setattr_fill(fc, &args, inode, &inarg, &outarg);
1605b0aa7606SMaxim Patlasov 
16067078187aSMiklos Szeredi 	return fuse_simple_request(fc, &args);
1607b0aa7606SMaxim Patlasov }
1608b0aa7606SMaxim Patlasov 
16093be5a52bSMiklos Szeredi /*
16106f9f1180SMiklos Szeredi  * Set attributes, and at the same time refresh them.
16116f9f1180SMiklos Szeredi  *
16126f9f1180SMiklos Szeredi  * Truncation is slightly complicated, because the 'truncate' request
16136f9f1180SMiklos Szeredi  * may fail, in which case we don't want to touch the mapping.
16149ffbb916SMiklos Szeredi  * vmtruncate() doesn't allow for this case, so do the rlimit checking
16159ffbb916SMiklos Szeredi  * and the actual truncation by hand.
16166f9f1180SMiklos Szeredi  */
161762490330SJan Kara int fuse_do_setattr(struct dentry *dentry, struct iattr *attr,
161849d4914fSMiklos Szeredi 		    struct file *file)
16199e6268dbSMiklos Szeredi {
162062490330SJan Kara 	struct inode *inode = d_inode(dentry);
16219e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
162206a7c3c2SMaxim Patlasov 	struct fuse_inode *fi = get_fuse_inode(inode);
16237078187aSMiklos Szeredi 	FUSE_ARGS(args);
16249e6268dbSMiklos Szeredi 	struct fuse_setattr_in inarg;
16259e6268dbSMiklos Szeredi 	struct fuse_attr_out outarg;
16263be5a52bSMiklos Szeredi 	bool is_truncate = false;
16278373200bSPavel Emelyanov 	bool is_wb = fc->writeback_cache;
16283be5a52bSMiklos Szeredi 	loff_t oldsize;
16299e6268dbSMiklos Szeredi 	int err;
16303ad22c62SMaxim Patlasov 	bool trust_local_cmtime = is_wb && S_ISREG(inode->i_mode);
16319e6268dbSMiklos Szeredi 
163229433a29SMiklos Szeredi 	if (!fc->default_permissions)
1633db78b877SChristoph Hellwig 		attr->ia_valid |= ATTR_FORCE;
1634db78b877SChristoph Hellwig 
163531051c85SJan Kara 	err = setattr_prepare(dentry, attr);
16361e9a4ed9SMiklos Szeredi 	if (err)
16371e9a4ed9SMiklos Szeredi 		return err;
16381e9a4ed9SMiklos Szeredi 
16398d56adddSMiklos Szeredi 	if (attr->ia_valid & ATTR_OPEN) {
1640df0e91d4SMiklos Szeredi 		/* This is coming from open(..., ... | O_TRUNC); */
1641df0e91d4SMiklos Szeredi 		WARN_ON(!(attr->ia_valid & ATTR_SIZE));
1642df0e91d4SMiklos Szeredi 		WARN_ON(attr->ia_size != 0);
1643df0e91d4SMiklos Szeredi 		if (fc->atomic_o_trunc) {
1644df0e91d4SMiklos Szeredi 			/*
1645df0e91d4SMiklos Szeredi 			 * No need to send request to userspace, since actual
1646df0e91d4SMiklos Szeredi 			 * truncation has already been done by OPEN.  But still
1647df0e91d4SMiklos Szeredi 			 * need to truncate page cache.
1648df0e91d4SMiklos Szeredi 			 */
1649df0e91d4SMiklos Szeredi 			i_size_write(inode, 0);
1650df0e91d4SMiklos Szeredi 			truncate_pagecache(inode, 0);
16516ff958edSMiklos Szeredi 			return 0;
1652df0e91d4SMiklos Szeredi 		}
16538d56adddSMiklos Szeredi 		file = NULL;
16548d56adddSMiklos Szeredi 	}
16556ff958edSMiklos Szeredi 
16562c27c65eSChristoph Hellwig 	if (attr->ia_valid & ATTR_SIZE)
16573be5a52bSMiklos Szeredi 		is_truncate = true;
16589e6268dbSMiklos Szeredi 
165906a7c3c2SMaxim Patlasov 	if (is_truncate) {
16603be5a52bSMiklos Szeredi 		fuse_set_nowrite(inode);
166106a7c3c2SMaxim Patlasov 		set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
16623ad22c62SMaxim Patlasov 		if (trust_local_cmtime && attr->ia_size != inode->i_size)
16633ad22c62SMaxim Patlasov 			attr->ia_valid |= ATTR_MTIME | ATTR_CTIME;
166406a7c3c2SMaxim Patlasov 	}
16653be5a52bSMiklos Szeredi 
16669e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
16670e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
16688cb08329SEric W. Biederman 	iattr_to_fattr(fc, attr, &inarg, trust_local_cmtime);
166949d4914fSMiklos Szeredi 	if (file) {
167049d4914fSMiklos Szeredi 		struct fuse_file *ff = file->private_data;
167149d4914fSMiklos Szeredi 		inarg.valid |= FATTR_FH;
167249d4914fSMiklos Szeredi 		inarg.fh = ff->fh;
167349d4914fSMiklos Szeredi 	}
1674f3332114SMiklos Szeredi 	if (attr->ia_valid & ATTR_SIZE) {
1675f3332114SMiklos Szeredi 		/* For mandatory locking in truncate */
1676f3332114SMiklos Szeredi 		inarg.valid |= FATTR_LOCKOWNER;
1677f3332114SMiklos Szeredi 		inarg.lock_owner = fuse_lock_owner_id(fc, current->files);
1678f3332114SMiklos Szeredi 	}
16797078187aSMiklos Szeredi 	fuse_setattr_fill(fc, &args, inode, &inarg, &outarg);
16807078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
1681e00d2c2dSMiklos Szeredi 	if (err) {
1682e00d2c2dSMiklos Szeredi 		if (err == -EINTR)
1683e00d2c2dSMiklos Szeredi 			fuse_invalidate_attr(inode);
16843be5a52bSMiklos Szeredi 		goto error;
1685e00d2c2dSMiklos Szeredi 	}
1686e00d2c2dSMiklos Szeredi 
16879e6268dbSMiklos Szeredi 	if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
16889e6268dbSMiklos Szeredi 		make_bad_inode(inode);
16893be5a52bSMiklos Szeredi 		err = -EIO;
16903be5a52bSMiklos Szeredi 		goto error;
16919e6268dbSMiklos Szeredi 	}
16929e6268dbSMiklos Szeredi 
16933be5a52bSMiklos Szeredi 	spin_lock(&fc->lock);
1694b0aa7606SMaxim Patlasov 	/* the kernel maintains i_mtime locally */
16953ad22c62SMaxim Patlasov 	if (trust_local_cmtime) {
16963ad22c62SMaxim Patlasov 		if (attr->ia_valid & ATTR_MTIME)
1697b0aa7606SMaxim Patlasov 			inode->i_mtime = attr->ia_mtime;
16983ad22c62SMaxim Patlasov 		if (attr->ia_valid & ATTR_CTIME)
16993ad22c62SMaxim Patlasov 			inode->i_ctime = attr->ia_ctime;
17001e18bda8SMiklos Szeredi 		/* FIXME: clear I_DIRTY_SYNC? */
1701b0aa7606SMaxim Patlasov 	}
1702b0aa7606SMaxim Patlasov 
17033be5a52bSMiklos Szeredi 	fuse_change_attributes_common(inode, &outarg.attr,
17043be5a52bSMiklos Szeredi 				      attr_timeout(&outarg));
17053be5a52bSMiklos Szeredi 	oldsize = inode->i_size;
17068373200bSPavel Emelyanov 	/* see the comment in fuse_change_attributes() */
17078373200bSPavel Emelyanov 	if (!is_wb || is_truncate || !S_ISREG(inode->i_mode))
17083be5a52bSMiklos Szeredi 		i_size_write(inode, outarg.attr.size);
17093be5a52bSMiklos Szeredi 
17103be5a52bSMiklos Szeredi 	if (is_truncate) {
17113be5a52bSMiklos Szeredi 		/* NOTE: this may release/reacquire fc->lock */
17123be5a52bSMiklos Szeredi 		__fuse_release_nowrite(inode);
17133be5a52bSMiklos Szeredi 	}
17143be5a52bSMiklos Szeredi 	spin_unlock(&fc->lock);
17153be5a52bSMiklos Szeredi 
17163be5a52bSMiklos Szeredi 	/*
17173be5a52bSMiklos Szeredi 	 * Only call invalidate_inode_pages2() after removing
17183be5a52bSMiklos Szeredi 	 * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock.
17193be5a52bSMiklos Szeredi 	 */
17208373200bSPavel Emelyanov 	if ((is_truncate || !is_wb) &&
17218373200bSPavel Emelyanov 	    S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
17227caef267SKirill A. Shutemov 		truncate_pagecache(inode, outarg.attr.size);
17233be5a52bSMiklos Szeredi 		invalidate_inode_pages2(inode->i_mapping);
17243be5a52bSMiklos Szeredi 	}
17253be5a52bSMiklos Szeredi 
172606a7c3c2SMaxim Patlasov 	clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
1727e00d2c2dSMiklos Szeredi 	return 0;
17283be5a52bSMiklos Szeredi 
17293be5a52bSMiklos Szeredi error:
17303be5a52bSMiklos Szeredi 	if (is_truncate)
17313be5a52bSMiklos Szeredi 		fuse_release_nowrite(inode);
17323be5a52bSMiklos Szeredi 
173306a7c3c2SMaxim Patlasov 	clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
17343be5a52bSMiklos Szeredi 	return err;
17359e6268dbSMiklos Szeredi }
17369e6268dbSMiklos Szeredi 
173749d4914fSMiklos Szeredi static int fuse_setattr(struct dentry *entry, struct iattr *attr)
173849d4914fSMiklos Szeredi {
17392b0143b5SDavid Howells 	struct inode *inode = d_inode(entry);
17405e940c1dSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1741a09f99edSMiklos Szeredi 	struct file *file = (attr->ia_valid & ATTR_FILE) ? attr->ia_file : NULL;
17425e2b8828SMiklos Szeredi 	int ret;
1743efb9fa9eSMaxim Patlasov 
1744efb9fa9eSMaxim Patlasov 	if (!fuse_allow_current_process(get_fuse_conn(inode)))
1745efb9fa9eSMaxim Patlasov 		return -EACCES;
1746efb9fa9eSMaxim Patlasov 
1747a09f99edSMiklos Szeredi 	if (attr->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) {
1748a09f99edSMiklos Szeredi 		attr->ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID |
1749a09f99edSMiklos Szeredi 				    ATTR_MODE);
17505e940c1dSMiklos Szeredi 
1751a09f99edSMiklos Szeredi 		/*
17525e940c1dSMiklos Szeredi 		 * The only sane way to reliably kill suid/sgid is to do it in
17535e940c1dSMiklos Szeredi 		 * the userspace filesystem
17545e940c1dSMiklos Szeredi 		 *
17555e940c1dSMiklos Szeredi 		 * This should be done on write(), truncate() and chown().
17565e940c1dSMiklos Szeredi 		 */
17575e940c1dSMiklos Szeredi 		if (!fc->handle_killpriv) {
17585e940c1dSMiklos Szeredi 			/*
17595e940c1dSMiklos Szeredi 			 * ia_mode calculation may have used stale i_mode.
17605e940c1dSMiklos Szeredi 			 * Refresh and recalculate.
1761a09f99edSMiklos Szeredi 			 */
1762a09f99edSMiklos Szeredi 			ret = fuse_do_getattr(inode, NULL, file);
1763a09f99edSMiklos Szeredi 			if (ret)
1764a09f99edSMiklos Szeredi 				return ret;
1765a09f99edSMiklos Szeredi 
1766a09f99edSMiklos Szeredi 			attr->ia_mode = inode->i_mode;
1767c01638f5SMiklos Szeredi 			if (inode->i_mode & S_ISUID) {
1768a09f99edSMiklos Szeredi 				attr->ia_valid |= ATTR_MODE;
1769a09f99edSMiklos Szeredi 				attr->ia_mode &= ~S_ISUID;
1770a09f99edSMiklos Szeredi 			}
1771c01638f5SMiklos Szeredi 			if ((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
1772a09f99edSMiklos Szeredi 				attr->ia_valid |= ATTR_MODE;
1773a09f99edSMiklos Szeredi 				attr->ia_mode &= ~S_ISGID;
1774a09f99edSMiklos Szeredi 			}
1775a09f99edSMiklos Szeredi 		}
17765e940c1dSMiklos Szeredi 	}
1777a09f99edSMiklos Szeredi 	if (!attr->ia_valid)
1778a09f99edSMiklos Szeredi 		return 0;
1779a09f99edSMiklos Szeredi 
1780abb5a14fSLinus Torvalds 	ret = fuse_do_setattr(entry, attr, file);
17815e2b8828SMiklos Szeredi 	if (!ret) {
178260bcc88aSSeth Forshee 		/*
178360bcc88aSSeth Forshee 		 * If filesystem supports acls it may have updated acl xattrs in
178460bcc88aSSeth Forshee 		 * the filesystem, so forget cached acls for the inode.
178560bcc88aSSeth Forshee 		 */
178660bcc88aSSeth Forshee 		if (fc->posix_acl)
178760bcc88aSSeth Forshee 			forget_all_cached_acls(inode);
178860bcc88aSSeth Forshee 
17895e2b8828SMiklos Szeredi 		/* Directory mode changed, may need to revalidate access */
17905e2b8828SMiklos Szeredi 		if (d_is_dir(entry) && (attr->ia_valid & ATTR_MODE))
17915e2b8828SMiklos Szeredi 			fuse_invalidate_entry_cache(entry);
17925e2b8828SMiklos Szeredi 	}
17935e2b8828SMiklos Szeredi 	return ret;
179449d4914fSMiklos Szeredi }
179549d4914fSMiklos Szeredi 
1796a528d35eSDavid Howells static int fuse_getattr(const struct path *path, struct kstat *stat,
1797a528d35eSDavid Howells 			u32 request_mask, unsigned int flags)
1798e5e5558eSMiklos Szeredi {
1799a528d35eSDavid Howells 	struct inode *inode = d_inode(path->dentry);
1800244f6385SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1801244f6385SMiklos Szeredi 
1802c2132c1bSAnatol Pomozov 	if (!fuse_allow_current_process(fc))
1803244f6385SMiklos Szeredi 		return -EACCES;
1804244f6385SMiklos Szeredi 
1805ff1b89f3SMiklos Szeredi 	return fuse_update_get_attr(inode, NULL, stat, flags);
1806e5e5558eSMiklos Szeredi }
1807e5e5558eSMiklos Szeredi 
1808754661f1SArjan van de Ven static const struct inode_operations fuse_dir_inode_operations = {
1809e5e5558eSMiklos Szeredi 	.lookup		= fuse_lookup,
18109e6268dbSMiklos Szeredi 	.mkdir		= fuse_mkdir,
18119e6268dbSMiklos Szeredi 	.symlink	= fuse_symlink,
18129e6268dbSMiklos Szeredi 	.unlink		= fuse_unlink,
18139e6268dbSMiklos Szeredi 	.rmdir		= fuse_rmdir,
18142773bf00SMiklos Szeredi 	.rename		= fuse_rename2,
18159e6268dbSMiklos Szeredi 	.link		= fuse_link,
18169e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
18179e6268dbSMiklos Szeredi 	.create		= fuse_create,
1818c8ccbe03SMiklos Szeredi 	.atomic_open	= fuse_atomic_open,
18199e6268dbSMiklos Szeredi 	.mknod		= fuse_mknod,
1820e5e5558eSMiklos Szeredi 	.permission	= fuse_permission,
1821e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
182292a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
182360bcc88aSSeth Forshee 	.get_acl	= fuse_get_acl,
182460bcc88aSSeth Forshee 	.set_acl	= fuse_set_acl,
1825e5e5558eSMiklos Szeredi };
1826e5e5558eSMiklos Szeredi 
18274b6f5d20SArjan van de Ven static const struct file_operations fuse_dir_operations = {
1828b6aeadedSMiklos Szeredi 	.llseek		= generic_file_llseek,
1829e5e5558eSMiklos Szeredi 	.read		= generic_read_dir,
1830d9b3dbdcSAl Viro 	.iterate_shared	= fuse_readdir,
1831e5e5558eSMiklos Szeredi 	.open		= fuse_dir_open,
1832e5e5558eSMiklos Szeredi 	.release	= fuse_dir_release,
183382547981SMiklos Szeredi 	.fsync		= fuse_dir_fsync,
1834b18da0c5SMiklos Szeredi 	.unlocked_ioctl	= fuse_dir_ioctl,
1835b18da0c5SMiklos Szeredi 	.compat_ioctl	= fuse_dir_compat_ioctl,
1836e5e5558eSMiklos Szeredi };
1837e5e5558eSMiklos Szeredi 
1838754661f1SArjan van de Ven static const struct inode_operations fuse_common_inode_operations = {
18399e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
1840e5e5558eSMiklos Szeredi 	.permission	= fuse_permission,
1841e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
184292a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
184360bcc88aSSeth Forshee 	.get_acl	= fuse_get_acl,
184460bcc88aSSeth Forshee 	.set_acl	= fuse_set_acl,
1845e5e5558eSMiklos Szeredi };
1846e5e5558eSMiklos Szeredi 
1847754661f1SArjan van de Ven static const struct inode_operations fuse_symlink_inode_operations = {
18489e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
18496b255391SAl Viro 	.get_link	= fuse_get_link,
1850e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
185192a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
1852e5e5558eSMiklos Szeredi };
1853e5e5558eSMiklos Szeredi 
1854e5e5558eSMiklos Szeredi void fuse_init_common(struct inode *inode)
1855e5e5558eSMiklos Szeredi {
1856e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_common_inode_operations;
1857e5e5558eSMiklos Szeredi }
1858e5e5558eSMiklos Szeredi 
1859e5e5558eSMiklos Szeredi void fuse_init_dir(struct inode *inode)
1860e5e5558eSMiklos Szeredi {
1861e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_dir_inode_operations;
1862e5e5558eSMiklos Szeredi 	inode->i_fop = &fuse_dir_operations;
1863e5e5558eSMiklos Szeredi }
1864e5e5558eSMiklos Szeredi 
1865e5e5558eSMiklos Szeredi void fuse_init_symlink(struct inode *inode)
1866e5e5558eSMiklos Szeredi {
1867e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_symlink_inode_operations;
1868e5e5558eSMiklos Szeredi }
1869