xref: /openbmc/linux/fs/fuse/dir.c (revision c6cdd51404b7ac12dd95173ddfc548c59ecf037f)
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);
47230d90494SAl Viro 	err = finish_open(file, entry, generic_file_open, opened);
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 */
51147237687SAl Viro 	*opened |= FILE_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;
861499dcf20SEric W. Biederman 	stat->uid = make_kuid(&init_user_ns, attr->uid);
862499dcf20SEric W. Biederman 	stat->gid = make_kgid(&init_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,
9275b97eeacSMiklos Szeredi 				struct kstat *stat)
928bcb4be80SMiklos Szeredi {
929bcb4be80SMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
9305b97eeacSMiklos Szeredi 	int err = 0;
931bcb4be80SMiklos Szeredi 
932126b9d43SMiklos Szeredi 	if (time_before64(fi->i_time, get_jiffies_64())) {
93360bcc88aSSeth Forshee 		forget_all_cached_acls(inode);
934bcb4be80SMiklos Szeredi 		err = fuse_do_getattr(inode, stat, file);
9355b97eeacSMiklos Szeredi 	} else if (stat) {
936bcb4be80SMiklos Szeredi 		generic_fillattr(inode, stat);
937bcb4be80SMiklos Szeredi 		stat->mode = fi->orig_i_mode;
93845c72cd7SPavel Shilovsky 		stat->ino = fi->orig_ino;
939bcb4be80SMiklos Szeredi 	}
940bcb4be80SMiklos Szeredi 
941bcb4be80SMiklos Szeredi 	return err;
942bcb4be80SMiklos Szeredi }
943bcb4be80SMiklos Szeredi 
9445b97eeacSMiklos Szeredi int fuse_update_attributes(struct inode *inode, struct file *file)
9455b97eeacSMiklos Szeredi {
9465b97eeacSMiklos Szeredi 	return fuse_update_get_attr(inode, file, NULL);
9475b97eeacSMiklos Szeredi }
9485b97eeacSMiklos Szeredi 
9493b463ae0SJohn Muir int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid,
950451d0f59SJohn Muir 			     u64 child_nodeid, struct qstr *name)
9513b463ae0SJohn Muir {
9523b463ae0SJohn Muir 	int err = -ENOTDIR;
9533b463ae0SJohn Muir 	struct inode *parent;
9543b463ae0SJohn Muir 	struct dentry *dir;
9553b463ae0SJohn Muir 	struct dentry *entry;
9563b463ae0SJohn Muir 
9573b463ae0SJohn Muir 	parent = ilookup5(sb, parent_nodeid, fuse_inode_eq, &parent_nodeid);
9583b463ae0SJohn Muir 	if (!parent)
9593b463ae0SJohn Muir 		return -ENOENT;
9603b463ae0SJohn Muir 
9615955102cSAl Viro 	inode_lock(parent);
9623b463ae0SJohn Muir 	if (!S_ISDIR(parent->i_mode))
9633b463ae0SJohn Muir 		goto unlock;
9643b463ae0SJohn Muir 
9653b463ae0SJohn Muir 	err = -ENOENT;
9663b463ae0SJohn Muir 	dir = d_find_alias(parent);
9673b463ae0SJohn Muir 	if (!dir)
9683b463ae0SJohn Muir 		goto unlock;
9693b463ae0SJohn Muir 
9708387ff25SLinus Torvalds 	name->hash = full_name_hash(dir, name->name, name->len);
9713b463ae0SJohn Muir 	entry = d_lookup(dir, name);
9723b463ae0SJohn Muir 	dput(dir);
9733b463ae0SJohn Muir 	if (!entry)
9743b463ae0SJohn Muir 		goto unlock;
9753b463ae0SJohn Muir 
9763b463ae0SJohn Muir 	fuse_invalidate_attr(parent);
9773b463ae0SJohn Muir 	fuse_invalidate_entry(entry);
978451d0f59SJohn Muir 
9792b0143b5SDavid Howells 	if (child_nodeid != 0 && d_really_is_positive(entry)) {
9805955102cSAl Viro 		inode_lock(d_inode(entry));
9812b0143b5SDavid Howells 		if (get_node_id(d_inode(entry)) != child_nodeid) {
982451d0f59SJohn Muir 			err = -ENOENT;
983451d0f59SJohn Muir 			goto badentry;
984451d0f59SJohn Muir 		}
985451d0f59SJohn Muir 		if (d_mountpoint(entry)) {
986451d0f59SJohn Muir 			err = -EBUSY;
987451d0f59SJohn Muir 			goto badentry;
988451d0f59SJohn Muir 		}
989e36cb0b8SDavid Howells 		if (d_is_dir(entry)) {
990451d0f59SJohn Muir 			shrink_dcache_parent(entry);
991451d0f59SJohn Muir 			if (!simple_empty(entry)) {
992451d0f59SJohn Muir 				err = -ENOTEMPTY;
993451d0f59SJohn Muir 				goto badentry;
994451d0f59SJohn Muir 			}
9952b0143b5SDavid Howells 			d_inode(entry)->i_flags |= S_DEAD;
996451d0f59SJohn Muir 		}
997451d0f59SJohn Muir 		dont_mount(entry);
9982b0143b5SDavid Howells 		clear_nlink(d_inode(entry));
9993b463ae0SJohn Muir 		err = 0;
1000451d0f59SJohn Muir  badentry:
10015955102cSAl Viro 		inode_unlock(d_inode(entry));
1002451d0f59SJohn Muir 		if (!err)
1003451d0f59SJohn Muir 			d_delete(entry);
1004451d0f59SJohn Muir 	} else {
1005451d0f59SJohn Muir 		err = 0;
1006451d0f59SJohn Muir 	}
1007451d0f59SJohn Muir 	dput(entry);
10083b463ae0SJohn Muir 
10093b463ae0SJohn Muir  unlock:
10105955102cSAl Viro 	inode_unlock(parent);
10113b463ae0SJohn Muir 	iput(parent);
10123b463ae0SJohn Muir 	return err;
10133b463ae0SJohn Muir }
10143b463ae0SJohn Muir 
101587729a55SMiklos Szeredi /*
101687729a55SMiklos Szeredi  * Calling into a user-controlled filesystem gives the filesystem
1017c2132c1bSAnatol Pomozov  * daemon ptrace-like capabilities over the current process.  This
101887729a55SMiklos Szeredi  * means, that the filesystem daemon is able to record the exact
101987729a55SMiklos Szeredi  * filesystem operations performed, and can also control the behavior
102087729a55SMiklos Szeredi  * of the requester process in otherwise impossible ways.  For example
102187729a55SMiklos Szeredi  * it can delay the operation for arbitrary length of time allowing
102287729a55SMiklos Szeredi  * DoS against the requester.
102387729a55SMiklos Szeredi  *
102487729a55SMiklos Szeredi  * For this reason only those processes can call into the filesystem,
102587729a55SMiklos Szeredi  * for which the owner of the mount has ptrace privilege.  This
102687729a55SMiklos Szeredi  * excludes processes started by other users, suid or sgid processes.
102787729a55SMiklos Szeredi  */
1028c2132c1bSAnatol Pomozov int fuse_allow_current_process(struct fuse_conn *fc)
102987729a55SMiklos Szeredi {
1030c69e8d9cSDavid Howells 	const struct cred *cred;
1031c69e8d9cSDavid Howells 
103229433a29SMiklos Szeredi 	if (fc->allow_other)
103387729a55SMiklos Szeredi 		return 1;
103487729a55SMiklos Szeredi 
1035c2132c1bSAnatol Pomozov 	cred = current_cred();
1036499dcf20SEric W. Biederman 	if (uid_eq(cred->euid, fc->user_id) &&
1037499dcf20SEric W. Biederman 	    uid_eq(cred->suid, fc->user_id) &&
1038499dcf20SEric W. Biederman 	    uid_eq(cred->uid,  fc->user_id) &&
1039499dcf20SEric W. Biederman 	    gid_eq(cred->egid, fc->group_id) &&
1040499dcf20SEric W. Biederman 	    gid_eq(cred->sgid, fc->group_id) &&
1041499dcf20SEric W. Biederman 	    gid_eq(cred->gid,  fc->group_id))
1042c2132c1bSAnatol Pomozov 		return 1;
104387729a55SMiklos Szeredi 
1044c2132c1bSAnatol Pomozov 	return 0;
104587729a55SMiklos Szeredi }
104687729a55SMiklos Szeredi 
104731d40d74SMiklos Szeredi static int fuse_access(struct inode *inode, int mask)
104831d40d74SMiklos Szeredi {
104931d40d74SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
10507078187aSMiklos Szeredi 	FUSE_ARGS(args);
105131d40d74SMiklos Szeredi 	struct fuse_access_in inarg;
105231d40d74SMiklos Szeredi 	int err;
105331d40d74SMiklos Szeredi 
1054698fa1d1SMiklos Szeredi 	BUG_ON(mask & MAY_NOT_BLOCK);
1055698fa1d1SMiklos Szeredi 
105631d40d74SMiklos Szeredi 	if (fc->no_access)
105731d40d74SMiklos Szeredi 		return 0;
105831d40d74SMiklos Szeredi 
105931d40d74SMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
1060e6305c43SAl Viro 	inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC);
10617078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_ACCESS;
10627078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(inode);
10637078187aSMiklos Szeredi 	args.in.numargs = 1;
10647078187aSMiklos Szeredi 	args.in.args[0].size = sizeof(inarg);
10657078187aSMiklos Szeredi 	args.in.args[0].value = &inarg;
10667078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
106731d40d74SMiklos Szeredi 	if (err == -ENOSYS) {
106831d40d74SMiklos Szeredi 		fc->no_access = 1;
106931d40d74SMiklos Szeredi 		err = 0;
107031d40d74SMiklos Szeredi 	}
107131d40d74SMiklos Szeredi 	return err;
107231d40d74SMiklos Szeredi }
107331d40d74SMiklos Szeredi 
107410556cb2SAl Viro static int fuse_perm_getattr(struct inode *inode, int mask)
107519690ddbSMiklos Szeredi {
107610556cb2SAl Viro 	if (mask & MAY_NOT_BLOCK)
107719690ddbSMiklos Szeredi 		return -ECHILD;
107819690ddbSMiklos Szeredi 
107960bcc88aSSeth Forshee 	forget_all_cached_acls(inode);
108019690ddbSMiklos Szeredi 	return fuse_do_getattr(inode, NULL, NULL);
108119690ddbSMiklos Szeredi }
108219690ddbSMiklos Szeredi 
10836f9f1180SMiklos Szeredi /*
10846f9f1180SMiklos Szeredi  * Check permission.  The two basic access models of FUSE are:
10856f9f1180SMiklos Szeredi  *
10866f9f1180SMiklos Szeredi  * 1) Local access checking ('default_permissions' mount option) based
10876f9f1180SMiklos Szeredi  * on file mode.  This is the plain old disk filesystem permission
10886f9f1180SMiklos Szeredi  * modell.
10896f9f1180SMiklos Szeredi  *
10906f9f1180SMiklos Szeredi  * 2) "Remote" access checking, where server is responsible for
10916f9f1180SMiklos Szeredi  * checking permission in each inode operation.  An exception to this
10926f9f1180SMiklos Szeredi  * is if ->permission() was invoked from sys_access() in which case an
10936f9f1180SMiklos Szeredi  * access request is sent.  Execute permission is still checked
10946f9f1180SMiklos Szeredi  * locally based on file mode.
10956f9f1180SMiklos Szeredi  */
109610556cb2SAl Viro static int fuse_permission(struct inode *inode, int mask)
1097e5e5558eSMiklos Szeredi {
1098e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1099244f6385SMiklos Szeredi 	bool refreshed = false;
1100244f6385SMiklos Szeredi 	int err = 0;
1101e5e5558eSMiklos Szeredi 
1102c2132c1bSAnatol Pomozov 	if (!fuse_allow_current_process(fc))
1103e5e5558eSMiklos Szeredi 		return -EACCES;
1104244f6385SMiklos Szeredi 
1105244f6385SMiklos Szeredi 	/*
1106e8e96157SMiklos Szeredi 	 * If attributes are needed, refresh them before proceeding
1107244f6385SMiklos Szeredi 	 */
110829433a29SMiklos Szeredi 	if (fc->default_permissions ||
1109e8e96157SMiklos Szeredi 	    ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
111019690ddbSMiklos Szeredi 		struct fuse_inode *fi = get_fuse_inode(inode);
111119690ddbSMiklos Szeredi 
1112126b9d43SMiklos Szeredi 		if (time_before64(fi->i_time, get_jiffies_64())) {
111319690ddbSMiklos Szeredi 			refreshed = true;
111419690ddbSMiklos Szeredi 
111510556cb2SAl Viro 			err = fuse_perm_getattr(inode, mask);
1116244f6385SMiklos Szeredi 			if (err)
1117244f6385SMiklos Szeredi 				return err;
11181fb69e78SMiklos Szeredi 		}
111919690ddbSMiklos Szeredi 	}
1120244f6385SMiklos Szeredi 
112129433a29SMiklos Szeredi 	if (fc->default_permissions) {
11222830ba7fSAl Viro 		err = generic_permission(inode, mask);
11231e9a4ed9SMiklos Szeredi 
11241e9a4ed9SMiklos Szeredi 		/* If permission is denied, try to refresh file
11251e9a4ed9SMiklos Szeredi 		   attributes.  This is also needed, because the root
11261e9a4ed9SMiklos Szeredi 		   node will at first have no permissions */
1127244f6385SMiklos Szeredi 		if (err == -EACCES && !refreshed) {
112810556cb2SAl Viro 			err = fuse_perm_getattr(inode, mask);
11291e9a4ed9SMiklos Szeredi 			if (!err)
11302830ba7fSAl Viro 				err = generic_permission(inode, mask);
11311e9a4ed9SMiklos Szeredi 		}
11321e9a4ed9SMiklos Szeredi 
11336f9f1180SMiklos Szeredi 		/* Note: the opposite of the above test does not
11346f9f1180SMiklos Szeredi 		   exist.  So if permissions are revoked this won't be
11356f9f1180SMiklos Szeredi 		   noticed immediately, only after the attribute
11366f9f1180SMiklos Szeredi 		   timeout has expired */
11379cfcac81SEric Paris 	} else if (mask & (MAY_ACCESS | MAY_CHDIR)) {
1138e8e96157SMiklos Szeredi 		err = fuse_access(inode, mask);
1139e8e96157SMiklos Szeredi 	} else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
1140e8e96157SMiklos Szeredi 		if (!(inode->i_mode & S_IXUGO)) {
1141e8e96157SMiklos Szeredi 			if (refreshed)
1142e5e5558eSMiklos Szeredi 				return -EACCES;
114331d40d74SMiklos Szeredi 
114410556cb2SAl Viro 			err = fuse_perm_getattr(inode, mask);
1145e8e96157SMiklos Szeredi 			if (!err && !(inode->i_mode & S_IXUGO))
1146e8e96157SMiklos Szeredi 				return -EACCES;
1147e8e96157SMiklos Szeredi 		}
1148e5e5558eSMiklos Szeredi 	}
1149244f6385SMiklos Szeredi 	return err;
1150e5e5558eSMiklos Szeredi }
1151e5e5558eSMiklos Szeredi 
1152e5e5558eSMiklos Szeredi static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
11538d3af7f3SAl Viro 			 struct dir_context *ctx)
1154e5e5558eSMiklos Szeredi {
1155e5e5558eSMiklos Szeredi 	while (nbytes >= FUSE_NAME_OFFSET) {
1156e5e5558eSMiklos Szeredi 		struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
1157e5e5558eSMiklos Szeredi 		size_t reclen = FUSE_DIRENT_SIZE(dirent);
1158e5e5558eSMiklos Szeredi 		if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
1159e5e5558eSMiklos Szeredi 			return -EIO;
1160e5e5558eSMiklos Szeredi 		if (reclen > nbytes)
1161e5e5558eSMiklos Szeredi 			break;
1162efeb9e60SMiklos Szeredi 		if (memchr(dirent->name, '/', dirent->namelen) != NULL)
1163efeb9e60SMiklos Szeredi 			return -EIO;
1164e5e5558eSMiklos Szeredi 
11658d3af7f3SAl Viro 		if (!dir_emit(ctx, dirent->name, dirent->namelen,
11668d3af7f3SAl Viro 			       dirent->ino, dirent->type))
1167e5e5558eSMiklos Szeredi 			break;
1168e5e5558eSMiklos Szeredi 
1169e5e5558eSMiklos Szeredi 		buf += reclen;
1170e5e5558eSMiklos Szeredi 		nbytes -= reclen;
11718d3af7f3SAl Viro 		ctx->pos = dirent->off;
1172e5e5558eSMiklos Szeredi 	}
1173e5e5558eSMiklos Szeredi 
1174e5e5558eSMiklos Szeredi 	return 0;
1175e5e5558eSMiklos Szeredi }
1176e5e5558eSMiklos Szeredi 
11770b05b183SAnand V. Avati static int fuse_direntplus_link(struct file *file,
11780b05b183SAnand V. Avati 				struct fuse_direntplus *direntplus,
11790b05b183SAnand V. Avati 				u64 attr_version)
11800b05b183SAnand V. Avati {
11810b05b183SAnand V. Avati 	struct fuse_entry_out *o = &direntplus->entry_out;
11820b05b183SAnand V. Avati 	struct fuse_dirent *dirent = &direntplus->dirent;
11830b05b183SAnand V. Avati 	struct dentry *parent = file->f_path.dentry;
11840b05b183SAnand V. Avati 	struct qstr name = QSTR_INIT(dirent->name, dirent->namelen);
11850b05b183SAnand V. Avati 	struct dentry *dentry;
11860b05b183SAnand V. Avati 	struct dentry *alias;
11872b0143b5SDavid Howells 	struct inode *dir = d_inode(parent);
11880b05b183SAnand V. Avati 	struct fuse_conn *fc;
11890b05b183SAnand V. Avati 	struct inode *inode;
1190d9b3dbdcSAl Viro 	DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
11910b05b183SAnand V. Avati 
11920b05b183SAnand V. Avati 	if (!o->nodeid) {
11930b05b183SAnand V. Avati 		/*
11940b05b183SAnand V. Avati 		 * Unlike in the case of fuse_lookup, zero nodeid does not mean
11950b05b183SAnand V. Avati 		 * ENOENT. Instead, it only means the userspace filesystem did
11960b05b183SAnand V. Avati 		 * not want to return attributes/handle for this entry.
11970b05b183SAnand V. Avati 		 *
11980b05b183SAnand V. Avati 		 * So do nothing.
11990b05b183SAnand V. Avati 		 */
12000b05b183SAnand V. Avati 		return 0;
12010b05b183SAnand V. Avati 	}
12020b05b183SAnand V. Avati 
12030b05b183SAnand V. Avati 	if (name.name[0] == '.') {
12040b05b183SAnand V. Avati 		/*
12050b05b183SAnand V. Avati 		 * We could potentially refresh the attributes of the directory
12060b05b183SAnand V. Avati 		 * and its parent?
12070b05b183SAnand V. Avati 		 */
12080b05b183SAnand V. Avati 		if (name.len == 1)
12090b05b183SAnand V. Avati 			return 0;
12100b05b183SAnand V. Avati 		if (name.name[1] == '.' && name.len == 2)
12110b05b183SAnand V. Avati 			return 0;
12120b05b183SAnand V. Avati 	}
1213a28ef45cSMiklos Szeredi 
1214a28ef45cSMiklos Szeredi 	if (invalid_nodeid(o->nodeid))
1215a28ef45cSMiklos Szeredi 		return -EIO;
1216a28ef45cSMiklos Szeredi 	if (!fuse_valid_type(o->attr.mode))
1217a28ef45cSMiklos Szeredi 		return -EIO;
1218a28ef45cSMiklos Szeredi 
12190b05b183SAnand V. Avati 	fc = get_fuse_conn(dir);
12200b05b183SAnand V. Avati 
12218387ff25SLinus Torvalds 	name.hash = full_name_hash(parent, name.name, name.len);
12220b05b183SAnand V. Avati 	dentry = d_lookup(parent, &name);
1223d9b3dbdcSAl Viro 	if (!dentry) {
1224d9b3dbdcSAl Viro retry:
1225d9b3dbdcSAl Viro 		dentry = d_alloc_parallel(parent, &name, &wq);
1226d9b3dbdcSAl Viro 		if (IS_ERR(dentry))
1227d9b3dbdcSAl Viro 			return PTR_ERR(dentry);
1228d9b3dbdcSAl Viro 	}
1229d9b3dbdcSAl Viro 	if (!d_in_lookup(dentry)) {
1230d9b3dbdcSAl Viro 		struct fuse_inode *fi;
12312b0143b5SDavid Howells 		inode = d_inode(dentry);
1232d9b3dbdcSAl Viro 		if (!inode ||
1233d9b3dbdcSAl Viro 		    get_node_id(inode) != o->nodeid ||
1234a28ef45cSMiklos Szeredi 		    ((o->attr.mode ^ inode->i_mode) & S_IFMT)) {
12355542aa2fSEric W. Biederman 			d_invalidate(dentry);
1236d9b3dbdcSAl Viro 			dput(dentry);
1237d9b3dbdcSAl Viro 			goto retry;
1238d9b3dbdcSAl Viro 		}
1239d9b3dbdcSAl Viro 		if (is_bad_inode(inode)) {
1240d9b3dbdcSAl Viro 			dput(dentry);
1241d9b3dbdcSAl Viro 			return -EIO;
1242d9b3dbdcSAl Viro 		}
1243d9b3dbdcSAl Viro 
12440b05b183SAnand V. Avati 		fi = get_fuse_inode(inode);
12450b05b183SAnand V. Avati 		spin_lock(&fc->lock);
12460b05b183SAnand V. Avati 		fi->nlookup++;
12470b05b183SAnand V. Avati 		spin_unlock(&fc->lock);
12480b05b183SAnand V. Avati 
124960bcc88aSSeth Forshee 		forget_all_cached_acls(inode);
1250fa2b7213SMiklos Szeredi 		fuse_change_attributes(inode, &o->attr,
1251fa2b7213SMiklos Szeredi 				       entry_attr_timeout(o),
1252fa2b7213SMiklos Szeredi 				       attr_version);
12530b05b183SAnand V. Avati 		/*
1254d9b3dbdcSAl Viro 		 * The other branch comes via fuse_iget()
12550b05b183SAnand V. Avati 		 * which bumps nlookup inside
12560b05b183SAnand V. Avati 		 */
1257d9b3dbdcSAl Viro 	} else {
12580b05b183SAnand V. Avati 		inode = fuse_iget(dir->i_sb, o->nodeid, o->generation,
1259d9b3dbdcSAl Viro 				  &o->attr, entry_attr_timeout(o),
1260d9b3dbdcSAl Viro 				  attr_version);
12610b05b183SAnand V. Avati 		if (!inode)
1262d9b3dbdcSAl Viro 			inode = ERR_PTR(-ENOMEM);
12630b05b183SAnand V. Avati 
126441d28bcaSAl Viro 		alias = d_splice_alias(inode, dentry);
1265d9b3dbdcSAl Viro 		d_lookup_done(dentry);
12660b05b183SAnand V. Avati 		if (alias) {
12670b05b183SAnand V. Avati 			dput(dentry);
12680b05b183SAnand V. Avati 			dentry = alias;
12690b05b183SAnand V. Avati 		}
1270d9b3dbdcSAl Viro 		if (IS_ERR(dentry))
1271d9b3dbdcSAl Viro 			return PTR_ERR(dentry);
1272d9b3dbdcSAl Viro 	}
12736314efeeSMiklos Szeredi 	if (fc->readdirplus_auto)
12746314efeeSMiklos Szeredi 		set_bit(FUSE_I_INIT_RDPLUS, &get_fuse_inode(inode)->state);
12750b05b183SAnand V. Avati 	fuse_change_entry_timeout(dentry, o);
12760b05b183SAnand V. Avati 
12770b05b183SAnand V. Avati 	dput(dentry);
1278d9b3dbdcSAl Viro 	return 0;
12790b05b183SAnand V. Avati }
12800b05b183SAnand V. Avati 
12810b05b183SAnand V. Avati static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file,
12828d3af7f3SAl Viro 			     struct dir_context *ctx, u64 attr_version)
12830b05b183SAnand V. Avati {
12840b05b183SAnand V. Avati 	struct fuse_direntplus *direntplus;
12850b05b183SAnand V. Avati 	struct fuse_dirent *dirent;
12860b05b183SAnand V. Avati 	size_t reclen;
12870b05b183SAnand V. Avati 	int over = 0;
12880b05b183SAnand V. Avati 	int ret;
12890b05b183SAnand V. Avati 
12900b05b183SAnand V. Avati 	while (nbytes >= FUSE_NAME_OFFSET_DIRENTPLUS) {
12910b05b183SAnand V. Avati 		direntplus = (struct fuse_direntplus *) buf;
12920b05b183SAnand V. Avati 		dirent = &direntplus->dirent;
12930b05b183SAnand V. Avati 		reclen = FUSE_DIRENTPLUS_SIZE(direntplus);
12940b05b183SAnand V. Avati 
12950b05b183SAnand V. Avati 		if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
12960b05b183SAnand V. Avati 			return -EIO;
12970b05b183SAnand V. Avati 		if (reclen > nbytes)
12980b05b183SAnand V. Avati 			break;
1299efeb9e60SMiklos Szeredi 		if (memchr(dirent->name, '/', dirent->namelen) != NULL)
1300efeb9e60SMiklos Szeredi 			return -EIO;
13010b05b183SAnand V. Avati 
13020b05b183SAnand V. Avati 		if (!over) {
13030b05b183SAnand V. Avati 			/* We fill entries into dstbuf only as much as
13040b05b183SAnand V. Avati 			   it can hold. But we still continue iterating
13050b05b183SAnand V. Avati 			   over remaining entries to link them. If not,
13060b05b183SAnand V. Avati 			   we need to send a FORGET for each of those
13070b05b183SAnand V. Avati 			   which we did not link.
13080b05b183SAnand V. Avati 			*/
13098d3af7f3SAl Viro 			over = !dir_emit(ctx, dirent->name, dirent->namelen,
13108d3af7f3SAl Viro 				       dirent->ino, dirent->type);
1311*c6cdd514SMiklos Szeredi 			if (!over)
13128d3af7f3SAl Viro 				ctx->pos = dirent->off;
13130b05b183SAnand V. Avati 		}
13140b05b183SAnand V. Avati 
13150b05b183SAnand V. Avati 		buf += reclen;
13160b05b183SAnand V. Avati 		nbytes -= reclen;
13170b05b183SAnand V. Avati 
13180b05b183SAnand V. Avati 		ret = fuse_direntplus_link(file, direntplus, attr_version);
13190b05b183SAnand V. Avati 		if (ret)
13200b05b183SAnand V. Avati 			fuse_force_forget(file, direntplus->entry_out.nodeid);
13210b05b183SAnand V. Avati 	}
13220b05b183SAnand V. Avati 
13230b05b183SAnand V. Avati 	return 0;
13240b05b183SAnand V. Avati }
13250b05b183SAnand V. Avati 
13268d3af7f3SAl Viro static int fuse_readdir(struct file *file, struct dir_context *ctx)
1327e5e5558eSMiklos Szeredi {
13284582a4abSFeng Shuo 	int plus, err;
132904730fefSMiklos Szeredi 	size_t nbytes;
133004730fefSMiklos Szeredi 	struct page *page;
1331496ad9aaSAl Viro 	struct inode *inode = file_inode(file);
133204730fefSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1333248d86e8SMiklos Szeredi 	struct fuse_req *req;
13340b05b183SAnand V. Avati 	u64 attr_version = 0;
1335248d86e8SMiklos Szeredi 
1336248d86e8SMiklos Szeredi 	if (is_bad_inode(inode))
1337248d86e8SMiklos Szeredi 		return -EIO;
1338248d86e8SMiklos Szeredi 
1339b111c8c0SMaxim Patlasov 	req = fuse_get_req(fc, 1);
1340ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1341ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
1342e5e5558eSMiklos Szeredi 
134304730fefSMiklos Szeredi 	page = alloc_page(GFP_KERNEL);
134404730fefSMiklos Szeredi 	if (!page) {
134504730fefSMiklos Szeredi 		fuse_put_request(fc, req);
1346e5e5558eSMiklos Szeredi 		return -ENOMEM;
134704730fefSMiklos Szeredi 	}
13484582a4abSFeng Shuo 
13498d3af7f3SAl Viro 	plus = fuse_use_readdirplus(inode, ctx);
1350f4975c67SMiklos Szeredi 	req->out.argpages = 1;
135104730fefSMiklos Szeredi 	req->num_pages = 1;
135204730fefSMiklos Szeredi 	req->pages[0] = page;
135385f40aecSMaxim Patlasov 	req->page_descs[0].length = PAGE_SIZE;
13544582a4abSFeng Shuo 	if (plus) {
13550b05b183SAnand V. Avati 		attr_version = fuse_get_attr_version(fc);
13568d3af7f3SAl Viro 		fuse_read_fill(req, file, ctx->pos, PAGE_SIZE,
13570b05b183SAnand V. Avati 			       FUSE_READDIRPLUS);
13580b05b183SAnand V. Avati 	} else {
13598d3af7f3SAl Viro 		fuse_read_fill(req, file, ctx->pos, PAGE_SIZE,
13600b05b183SAnand V. Avati 			       FUSE_READDIR);
13610b05b183SAnand V. Avati 	}
13625c672ab3SMiklos Szeredi 	fuse_lock_inode(inode);
1363b93f858aSTejun Heo 	fuse_request_send(fc, req);
13645c672ab3SMiklos Szeredi 	fuse_unlock_inode(inode);
1365361b1eb5SMiklos Szeredi 	nbytes = req->out.args[0].size;
136604730fefSMiklos Szeredi 	err = req->out.h.error;
136704730fefSMiklos Szeredi 	fuse_put_request(fc, req);
13680b05b183SAnand V. Avati 	if (!err) {
13694582a4abSFeng Shuo 		if (plus) {
13700b05b183SAnand V. Avati 			err = parse_dirplusfile(page_address(page), nbytes,
13718d3af7f3SAl Viro 						file, ctx,
13720b05b183SAnand V. Avati 						attr_version);
13730b05b183SAnand V. Avati 		} else {
13740b05b183SAnand V. Avati 			err = parse_dirfile(page_address(page), nbytes, file,
13758d3af7f3SAl Viro 					    ctx);
13760b05b183SAnand V. Avati 		}
13770b05b183SAnand V. Avati 	}
1378e5e5558eSMiklos Szeredi 
137904730fefSMiklos Szeredi 	__free_page(page);
1380451418fcSAndrew Gallagher 	fuse_invalidate_atime(inode);
138104730fefSMiklos Szeredi 	return err;
1382e5e5558eSMiklos Szeredi }
1383e5e5558eSMiklos Szeredi 
13846b255391SAl Viro static const char *fuse_get_link(struct dentry *dentry,
1385fceef393SAl Viro 				 struct inode *inode,
1386fceef393SAl Viro 				 struct delayed_call *done)
1387e5e5558eSMiklos Szeredi {
1388e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
13897078187aSMiklos Szeredi 	FUSE_ARGS(args);
1390e5e5558eSMiklos Szeredi 	char *link;
13917078187aSMiklos Szeredi 	ssize_t ret;
1392e5e5558eSMiklos Szeredi 
13936b255391SAl Viro 	if (!dentry)
13946b255391SAl Viro 		return ERR_PTR(-ECHILD);
13956b255391SAl Viro 
1396cd3417c8SAl Viro 	link = kmalloc(PAGE_SIZE, GFP_KERNEL);
13977078187aSMiklos Szeredi 	if (!link)
13987078187aSMiklos Szeredi 		return ERR_PTR(-ENOMEM);
13997078187aSMiklos Szeredi 
14007078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_READLINK;
14017078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(inode);
14027078187aSMiklos Szeredi 	args.out.argvar = 1;
14037078187aSMiklos Szeredi 	args.out.numargs = 1;
14047078187aSMiklos Szeredi 	args.out.args[0].size = PAGE_SIZE - 1;
14057078187aSMiklos Szeredi 	args.out.args[0].value = link;
14067078187aSMiklos Szeredi 	ret = fuse_simple_request(fc, &args);
14077078187aSMiklos Szeredi 	if (ret < 0) {
1408cd3417c8SAl Viro 		kfree(link);
14097078187aSMiklos Szeredi 		link = ERR_PTR(ret);
14107078187aSMiklos Szeredi 	} else {
14117078187aSMiklos Szeredi 		link[ret] = '\0';
1412fceef393SAl Viro 		set_delayed_call(done, kfree_link, link);
14137078187aSMiklos Szeredi 	}
1414451418fcSAndrew Gallagher 	fuse_invalidate_atime(inode);
1415e5e5558eSMiklos Szeredi 	return link;
1416e5e5558eSMiklos Szeredi }
1417e5e5558eSMiklos Szeredi 
1418e5e5558eSMiklos Szeredi static int fuse_dir_open(struct inode *inode, struct file *file)
1419e5e5558eSMiklos Szeredi {
142091fe96b4SMiklos Szeredi 	return fuse_open_common(inode, file, true);
1421e5e5558eSMiklos Szeredi }
1422e5e5558eSMiklos Szeredi 
1423e5e5558eSMiklos Szeredi static int fuse_dir_release(struct inode *inode, struct file *file)
1424e5e5558eSMiklos Szeredi {
14258b0797a4SMiklos Szeredi 	fuse_release_common(file, FUSE_RELEASEDIR);
14268b0797a4SMiklos Szeredi 
14278b0797a4SMiklos Szeredi 	return 0;
1428e5e5558eSMiklos Szeredi }
1429e5e5558eSMiklos Szeredi 
143002c24a82SJosef Bacik static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end,
143102c24a82SJosef Bacik 			  int datasync)
143282547981SMiklos Szeredi {
143302c24a82SJosef Bacik 	return fuse_fsync_common(file, start, end, datasync, 1);
143482547981SMiklos Szeredi }
143582547981SMiklos Szeredi 
1436b18da0c5SMiklos Szeredi static long fuse_dir_ioctl(struct file *file, unsigned int cmd,
1437b18da0c5SMiklos Szeredi 			    unsigned long arg)
1438b18da0c5SMiklos Szeredi {
1439b18da0c5SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1440b18da0c5SMiklos Szeredi 
1441b18da0c5SMiklos Szeredi 	/* FUSE_IOCTL_DIR only supported for API version >= 7.18 */
1442b18da0c5SMiklos Szeredi 	if (fc->minor < 18)
1443b18da0c5SMiklos Szeredi 		return -ENOTTY;
1444b18da0c5SMiklos Szeredi 
1445b18da0c5SMiklos Szeredi 	return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR);
1446b18da0c5SMiklos Szeredi }
1447b18da0c5SMiklos Szeredi 
1448b18da0c5SMiklos Szeredi static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd,
1449b18da0c5SMiklos Szeredi 				   unsigned long arg)
1450b18da0c5SMiklos Szeredi {
1451b18da0c5SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1452b18da0c5SMiklos Szeredi 
1453b18da0c5SMiklos Szeredi 	if (fc->minor < 18)
1454b18da0c5SMiklos Szeredi 		return -ENOTTY;
1455b18da0c5SMiklos Szeredi 
1456b18da0c5SMiklos Szeredi 	return fuse_ioctl_common(file, cmd, arg,
1457b18da0c5SMiklos Szeredi 				 FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR);
1458b18da0c5SMiklos Szeredi }
1459b18da0c5SMiklos Szeredi 
1460b0aa7606SMaxim Patlasov static bool update_mtime(unsigned ivalid, bool trust_local_mtime)
146117637cbaSMiklos Szeredi {
146217637cbaSMiklos Szeredi 	/* Always update if mtime is explicitly set  */
146317637cbaSMiklos Szeredi 	if (ivalid & ATTR_MTIME_SET)
146417637cbaSMiklos Szeredi 		return true;
146517637cbaSMiklos Szeredi 
1466b0aa7606SMaxim Patlasov 	/* Or if kernel i_mtime is the official one */
1467b0aa7606SMaxim Patlasov 	if (trust_local_mtime)
1468b0aa7606SMaxim Patlasov 		return true;
1469b0aa7606SMaxim Patlasov 
147017637cbaSMiklos Szeredi 	/* If it's an open(O_TRUNC) or an ftruncate(), don't update */
147117637cbaSMiklos Szeredi 	if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
147217637cbaSMiklos Szeredi 		return false;
147317637cbaSMiklos Szeredi 
147417637cbaSMiklos Szeredi 	/* In all other cases update */
147517637cbaSMiklos Szeredi 	return true;
147617637cbaSMiklos Szeredi }
147717637cbaSMiklos Szeredi 
1478b0aa7606SMaxim Patlasov static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg,
14793ad22c62SMaxim Patlasov 			   bool trust_local_cmtime)
14809e6268dbSMiklos Szeredi {
14819e6268dbSMiklos Szeredi 	unsigned ivalid = iattr->ia_valid;
14829e6268dbSMiklos Szeredi 
14839e6268dbSMiklos Szeredi 	if (ivalid & ATTR_MODE)
1484befc649cSMiklos Szeredi 		arg->valid |= FATTR_MODE,   arg->mode = iattr->ia_mode;
14859e6268dbSMiklos Szeredi 	if (ivalid & ATTR_UID)
1486499dcf20SEric W. Biederman 		arg->valid |= FATTR_UID,    arg->uid = from_kuid(&init_user_ns, iattr->ia_uid);
14879e6268dbSMiklos Szeredi 	if (ivalid & ATTR_GID)
1488499dcf20SEric W. Biederman 		arg->valid |= FATTR_GID,    arg->gid = from_kgid(&init_user_ns, iattr->ia_gid);
14899e6268dbSMiklos Szeredi 	if (ivalid & ATTR_SIZE)
1490befc649cSMiklos Szeredi 		arg->valid |= FATTR_SIZE,   arg->size = iattr->ia_size;
149117637cbaSMiklos Szeredi 	if (ivalid & ATTR_ATIME) {
149217637cbaSMiklos Szeredi 		arg->valid |= FATTR_ATIME;
1493befc649cSMiklos Szeredi 		arg->atime = iattr->ia_atime.tv_sec;
149417637cbaSMiklos Szeredi 		arg->atimensec = iattr->ia_atime.tv_nsec;
149517637cbaSMiklos Szeredi 		if (!(ivalid & ATTR_ATIME_SET))
149617637cbaSMiklos Szeredi 			arg->valid |= FATTR_ATIME_NOW;
149717637cbaSMiklos Szeredi 	}
14983ad22c62SMaxim Patlasov 	if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, trust_local_cmtime)) {
149917637cbaSMiklos Szeredi 		arg->valid |= FATTR_MTIME;
1500befc649cSMiklos Szeredi 		arg->mtime = iattr->ia_mtime.tv_sec;
150117637cbaSMiklos Szeredi 		arg->mtimensec = iattr->ia_mtime.tv_nsec;
15023ad22c62SMaxim Patlasov 		if (!(ivalid & ATTR_MTIME_SET) && !trust_local_cmtime)
150317637cbaSMiklos Szeredi 			arg->valid |= FATTR_MTIME_NOW;
15049e6268dbSMiklos Szeredi 	}
15053ad22c62SMaxim Patlasov 	if ((ivalid & ATTR_CTIME) && trust_local_cmtime) {
15063ad22c62SMaxim Patlasov 		arg->valid |= FATTR_CTIME;
15073ad22c62SMaxim Patlasov 		arg->ctime = iattr->ia_ctime.tv_sec;
15083ad22c62SMaxim Patlasov 		arg->ctimensec = iattr->ia_ctime.tv_nsec;
15093ad22c62SMaxim Patlasov 	}
15109e6268dbSMiklos Szeredi }
15119e6268dbSMiklos Szeredi 
15126f9f1180SMiklos Szeredi /*
15133be5a52bSMiklos Szeredi  * Prevent concurrent writepages on inode
15143be5a52bSMiklos Szeredi  *
15153be5a52bSMiklos Szeredi  * This is done by adding a negative bias to the inode write counter
15163be5a52bSMiklos Szeredi  * and waiting for all pending writes to finish.
15173be5a52bSMiklos Szeredi  */
15183be5a52bSMiklos Szeredi void fuse_set_nowrite(struct inode *inode)
15193be5a52bSMiklos Szeredi {
15203be5a52bSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
15213be5a52bSMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
15223be5a52bSMiklos Szeredi 
15235955102cSAl Viro 	BUG_ON(!inode_is_locked(inode));
15243be5a52bSMiklos Szeredi 
15253be5a52bSMiklos Szeredi 	spin_lock(&fc->lock);
15263be5a52bSMiklos Szeredi 	BUG_ON(fi->writectr < 0);
15273be5a52bSMiklos Szeredi 	fi->writectr += FUSE_NOWRITE;
15283be5a52bSMiklos Szeredi 	spin_unlock(&fc->lock);
15293be5a52bSMiklos Szeredi 	wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE);
15303be5a52bSMiklos Szeredi }
15313be5a52bSMiklos Szeredi 
15323be5a52bSMiklos Szeredi /*
15333be5a52bSMiklos Szeredi  * Allow writepages on inode
15343be5a52bSMiklos Szeredi  *
15353be5a52bSMiklos Szeredi  * Remove the bias from the writecounter and send any queued
15363be5a52bSMiklos Szeredi  * writepages.
15373be5a52bSMiklos Szeredi  */
15383be5a52bSMiklos Szeredi static void __fuse_release_nowrite(struct inode *inode)
15393be5a52bSMiklos Szeredi {
15403be5a52bSMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
15413be5a52bSMiklos Szeredi 
15423be5a52bSMiklos Szeredi 	BUG_ON(fi->writectr != FUSE_NOWRITE);
15433be5a52bSMiklos Szeredi 	fi->writectr = 0;
15443be5a52bSMiklos Szeredi 	fuse_flush_writepages(inode);
15453be5a52bSMiklos Szeredi }
15463be5a52bSMiklos Szeredi 
15473be5a52bSMiklos Szeredi void fuse_release_nowrite(struct inode *inode)
15483be5a52bSMiklos Szeredi {
15493be5a52bSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
15503be5a52bSMiklos Szeredi 
15513be5a52bSMiklos Szeredi 	spin_lock(&fc->lock);
15523be5a52bSMiklos Szeredi 	__fuse_release_nowrite(inode);
15533be5a52bSMiklos Szeredi 	spin_unlock(&fc->lock);
15543be5a52bSMiklos Szeredi }
15553be5a52bSMiklos Szeredi 
15567078187aSMiklos Szeredi static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_args *args,
1557b0aa7606SMaxim Patlasov 			      struct inode *inode,
1558b0aa7606SMaxim Patlasov 			      struct fuse_setattr_in *inarg_p,
1559b0aa7606SMaxim Patlasov 			      struct fuse_attr_out *outarg_p)
1560b0aa7606SMaxim Patlasov {
15617078187aSMiklos Szeredi 	args->in.h.opcode = FUSE_SETATTR;
15627078187aSMiklos Szeredi 	args->in.h.nodeid = get_node_id(inode);
15637078187aSMiklos Szeredi 	args->in.numargs = 1;
15647078187aSMiklos Szeredi 	args->in.args[0].size = sizeof(*inarg_p);
15657078187aSMiklos Szeredi 	args->in.args[0].value = inarg_p;
15667078187aSMiklos Szeredi 	args->out.numargs = 1;
15677078187aSMiklos Szeredi 	args->out.args[0].size = sizeof(*outarg_p);
15687078187aSMiklos Szeredi 	args->out.args[0].value = outarg_p;
1569b0aa7606SMaxim Patlasov }
1570b0aa7606SMaxim Patlasov 
1571b0aa7606SMaxim Patlasov /*
1572b0aa7606SMaxim Patlasov  * Flush inode->i_mtime to the server
1573b0aa7606SMaxim Patlasov  */
1574ab9e13f7SMaxim Patlasov int fuse_flush_times(struct inode *inode, struct fuse_file *ff)
1575b0aa7606SMaxim Patlasov {
1576b0aa7606SMaxim Patlasov 	struct fuse_conn *fc = get_fuse_conn(inode);
15777078187aSMiklos Szeredi 	FUSE_ARGS(args);
1578b0aa7606SMaxim Patlasov 	struct fuse_setattr_in inarg;
1579b0aa7606SMaxim Patlasov 	struct fuse_attr_out outarg;
1580b0aa7606SMaxim Patlasov 
1581b0aa7606SMaxim Patlasov 	memset(&inarg, 0, sizeof(inarg));
1582b0aa7606SMaxim Patlasov 	memset(&outarg, 0, sizeof(outarg));
1583b0aa7606SMaxim Patlasov 
1584ab9e13f7SMaxim Patlasov 	inarg.valid = FATTR_MTIME;
1585b0aa7606SMaxim Patlasov 	inarg.mtime = inode->i_mtime.tv_sec;
1586b0aa7606SMaxim Patlasov 	inarg.mtimensec = inode->i_mtime.tv_nsec;
1587ab9e13f7SMaxim Patlasov 	if (fc->minor >= 23) {
1588ab9e13f7SMaxim Patlasov 		inarg.valid |= FATTR_CTIME;
1589ab9e13f7SMaxim Patlasov 		inarg.ctime = inode->i_ctime.tv_sec;
1590ab9e13f7SMaxim Patlasov 		inarg.ctimensec = inode->i_ctime.tv_nsec;
1591ab9e13f7SMaxim Patlasov 	}
15921e18bda8SMiklos Szeredi 	if (ff) {
15931e18bda8SMiklos Szeredi 		inarg.valid |= FATTR_FH;
15941e18bda8SMiklos Szeredi 		inarg.fh = ff->fh;
15951e18bda8SMiklos Szeredi 	}
15967078187aSMiklos Szeredi 	fuse_setattr_fill(fc, &args, inode, &inarg, &outarg);
1597b0aa7606SMaxim Patlasov 
15987078187aSMiklos Szeredi 	return fuse_simple_request(fc, &args);
1599b0aa7606SMaxim Patlasov }
1600b0aa7606SMaxim Patlasov 
16013be5a52bSMiklos Szeredi /*
16026f9f1180SMiklos Szeredi  * Set attributes, and at the same time refresh them.
16036f9f1180SMiklos Szeredi  *
16046f9f1180SMiklos Szeredi  * Truncation is slightly complicated, because the 'truncate' request
16056f9f1180SMiklos Szeredi  * may fail, in which case we don't want to touch the mapping.
16069ffbb916SMiklos Szeredi  * vmtruncate() doesn't allow for this case, so do the rlimit checking
16079ffbb916SMiklos Szeredi  * and the actual truncation by hand.
16086f9f1180SMiklos Szeredi  */
160962490330SJan Kara int fuse_do_setattr(struct dentry *dentry, struct iattr *attr,
161049d4914fSMiklos Szeredi 		    struct file *file)
16119e6268dbSMiklos Szeredi {
161262490330SJan Kara 	struct inode *inode = d_inode(dentry);
16139e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
161406a7c3c2SMaxim Patlasov 	struct fuse_inode *fi = get_fuse_inode(inode);
16157078187aSMiklos Szeredi 	FUSE_ARGS(args);
16169e6268dbSMiklos Szeredi 	struct fuse_setattr_in inarg;
16179e6268dbSMiklos Szeredi 	struct fuse_attr_out outarg;
16183be5a52bSMiklos Szeredi 	bool is_truncate = false;
16198373200bSPavel Emelyanov 	bool is_wb = fc->writeback_cache;
16203be5a52bSMiklos Szeredi 	loff_t oldsize;
16219e6268dbSMiklos Szeredi 	int err;
16223ad22c62SMaxim Patlasov 	bool trust_local_cmtime = is_wb && S_ISREG(inode->i_mode);
16239e6268dbSMiklos Szeredi 
162429433a29SMiklos Szeredi 	if (!fc->default_permissions)
1625db78b877SChristoph Hellwig 		attr->ia_valid |= ATTR_FORCE;
1626db78b877SChristoph Hellwig 
162731051c85SJan Kara 	err = setattr_prepare(dentry, attr);
16281e9a4ed9SMiklos Szeredi 	if (err)
16291e9a4ed9SMiklos Szeredi 		return err;
16301e9a4ed9SMiklos Szeredi 
16318d56adddSMiklos Szeredi 	if (attr->ia_valid & ATTR_OPEN) {
16328d56adddSMiklos Szeredi 		if (fc->atomic_o_trunc)
16336ff958edSMiklos Szeredi 			return 0;
16348d56adddSMiklos Szeredi 		file = NULL;
16358d56adddSMiklos Szeredi 	}
16366ff958edSMiklos Szeredi 
16372c27c65eSChristoph Hellwig 	if (attr->ia_valid & ATTR_SIZE)
16383be5a52bSMiklos Szeredi 		is_truncate = true;
16399e6268dbSMiklos Szeredi 
164006a7c3c2SMaxim Patlasov 	if (is_truncate) {
16413be5a52bSMiklos Szeredi 		fuse_set_nowrite(inode);
164206a7c3c2SMaxim Patlasov 		set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
16433ad22c62SMaxim Patlasov 		if (trust_local_cmtime && attr->ia_size != inode->i_size)
16443ad22c62SMaxim Patlasov 			attr->ia_valid |= ATTR_MTIME | ATTR_CTIME;
164506a7c3c2SMaxim Patlasov 	}
16463be5a52bSMiklos Szeredi 
16479e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
16480e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
16493ad22c62SMaxim Patlasov 	iattr_to_fattr(attr, &inarg, trust_local_cmtime);
165049d4914fSMiklos Szeredi 	if (file) {
165149d4914fSMiklos Szeredi 		struct fuse_file *ff = file->private_data;
165249d4914fSMiklos Szeredi 		inarg.valid |= FATTR_FH;
165349d4914fSMiklos Szeredi 		inarg.fh = ff->fh;
165449d4914fSMiklos Szeredi 	}
1655f3332114SMiklos Szeredi 	if (attr->ia_valid & ATTR_SIZE) {
1656f3332114SMiklos Szeredi 		/* For mandatory locking in truncate */
1657f3332114SMiklos Szeredi 		inarg.valid |= FATTR_LOCKOWNER;
1658f3332114SMiklos Szeredi 		inarg.lock_owner = fuse_lock_owner_id(fc, current->files);
1659f3332114SMiklos Szeredi 	}
16607078187aSMiklos Szeredi 	fuse_setattr_fill(fc, &args, inode, &inarg, &outarg);
16617078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
1662e00d2c2dSMiklos Szeredi 	if (err) {
1663e00d2c2dSMiklos Szeredi 		if (err == -EINTR)
1664e00d2c2dSMiklos Szeredi 			fuse_invalidate_attr(inode);
16653be5a52bSMiklos Szeredi 		goto error;
1666e00d2c2dSMiklos Szeredi 	}
1667e00d2c2dSMiklos Szeredi 
16689e6268dbSMiklos Szeredi 	if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
16699e6268dbSMiklos Szeredi 		make_bad_inode(inode);
16703be5a52bSMiklos Szeredi 		err = -EIO;
16713be5a52bSMiklos Szeredi 		goto error;
16729e6268dbSMiklos Szeredi 	}
16739e6268dbSMiklos Szeredi 
16743be5a52bSMiklos Szeredi 	spin_lock(&fc->lock);
1675b0aa7606SMaxim Patlasov 	/* the kernel maintains i_mtime locally */
16763ad22c62SMaxim Patlasov 	if (trust_local_cmtime) {
16773ad22c62SMaxim Patlasov 		if (attr->ia_valid & ATTR_MTIME)
1678b0aa7606SMaxim Patlasov 			inode->i_mtime = attr->ia_mtime;
16793ad22c62SMaxim Patlasov 		if (attr->ia_valid & ATTR_CTIME)
16803ad22c62SMaxim Patlasov 			inode->i_ctime = attr->ia_ctime;
16811e18bda8SMiklos Szeredi 		/* FIXME: clear I_DIRTY_SYNC? */
1682b0aa7606SMaxim Patlasov 	}
1683b0aa7606SMaxim Patlasov 
16843be5a52bSMiklos Szeredi 	fuse_change_attributes_common(inode, &outarg.attr,
16853be5a52bSMiklos Szeredi 				      attr_timeout(&outarg));
16863be5a52bSMiklos Szeredi 	oldsize = inode->i_size;
16878373200bSPavel Emelyanov 	/* see the comment in fuse_change_attributes() */
16888373200bSPavel Emelyanov 	if (!is_wb || is_truncate || !S_ISREG(inode->i_mode))
16893be5a52bSMiklos Szeredi 		i_size_write(inode, outarg.attr.size);
16903be5a52bSMiklos Szeredi 
16913be5a52bSMiklos Szeredi 	if (is_truncate) {
16923be5a52bSMiklos Szeredi 		/* NOTE: this may release/reacquire fc->lock */
16933be5a52bSMiklos Szeredi 		__fuse_release_nowrite(inode);
16943be5a52bSMiklos Szeredi 	}
16953be5a52bSMiklos Szeredi 	spin_unlock(&fc->lock);
16963be5a52bSMiklos Szeredi 
16973be5a52bSMiklos Szeredi 	/*
16983be5a52bSMiklos Szeredi 	 * Only call invalidate_inode_pages2() after removing
16993be5a52bSMiklos Szeredi 	 * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock.
17003be5a52bSMiklos Szeredi 	 */
17018373200bSPavel Emelyanov 	if ((is_truncate || !is_wb) &&
17028373200bSPavel Emelyanov 	    S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
17037caef267SKirill A. Shutemov 		truncate_pagecache(inode, outarg.attr.size);
17043be5a52bSMiklos Szeredi 		invalidate_inode_pages2(inode->i_mapping);
17053be5a52bSMiklos Szeredi 	}
17063be5a52bSMiklos Szeredi 
170706a7c3c2SMaxim Patlasov 	clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
1708e00d2c2dSMiklos Szeredi 	return 0;
17093be5a52bSMiklos Szeredi 
17103be5a52bSMiklos Szeredi error:
17113be5a52bSMiklos Szeredi 	if (is_truncate)
17123be5a52bSMiklos Szeredi 		fuse_release_nowrite(inode);
17133be5a52bSMiklos Szeredi 
171406a7c3c2SMaxim Patlasov 	clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
17153be5a52bSMiklos Szeredi 	return err;
17169e6268dbSMiklos Szeredi }
17179e6268dbSMiklos Szeredi 
171849d4914fSMiklos Szeredi static int fuse_setattr(struct dentry *entry, struct iattr *attr)
171949d4914fSMiklos Szeredi {
17202b0143b5SDavid Howells 	struct inode *inode = d_inode(entry);
17215e940c1dSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1722a09f99edSMiklos Szeredi 	struct file *file = (attr->ia_valid & ATTR_FILE) ? attr->ia_file : NULL;
17235e2b8828SMiklos Szeredi 	int ret;
1724efb9fa9eSMaxim Patlasov 
1725efb9fa9eSMaxim Patlasov 	if (!fuse_allow_current_process(get_fuse_conn(inode)))
1726efb9fa9eSMaxim Patlasov 		return -EACCES;
1727efb9fa9eSMaxim Patlasov 
1728a09f99edSMiklos Szeredi 	if (attr->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) {
1729a09f99edSMiklos Szeredi 		attr->ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID |
1730a09f99edSMiklos Szeredi 				    ATTR_MODE);
17315e940c1dSMiklos Szeredi 
1732a09f99edSMiklos Szeredi 		/*
17335e940c1dSMiklos Szeredi 		 * The only sane way to reliably kill suid/sgid is to do it in
17345e940c1dSMiklos Szeredi 		 * the userspace filesystem
17355e940c1dSMiklos Szeredi 		 *
17365e940c1dSMiklos Szeredi 		 * This should be done on write(), truncate() and chown().
17375e940c1dSMiklos Szeredi 		 */
17385e940c1dSMiklos Szeredi 		if (!fc->handle_killpriv) {
17395e940c1dSMiklos Szeredi 			/*
17405e940c1dSMiklos Szeredi 			 * ia_mode calculation may have used stale i_mode.
17415e940c1dSMiklos Szeredi 			 * Refresh and recalculate.
1742a09f99edSMiklos Szeredi 			 */
1743a09f99edSMiklos Szeredi 			ret = fuse_do_getattr(inode, NULL, file);
1744a09f99edSMiklos Szeredi 			if (ret)
1745a09f99edSMiklos Szeredi 				return ret;
1746a09f99edSMiklos Szeredi 
1747a09f99edSMiklos Szeredi 			attr->ia_mode = inode->i_mode;
1748c01638f5SMiklos Szeredi 			if (inode->i_mode & S_ISUID) {
1749a09f99edSMiklos Szeredi 				attr->ia_valid |= ATTR_MODE;
1750a09f99edSMiklos Szeredi 				attr->ia_mode &= ~S_ISUID;
1751a09f99edSMiklos Szeredi 			}
1752c01638f5SMiklos Szeredi 			if ((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
1753a09f99edSMiklos Szeredi 				attr->ia_valid |= ATTR_MODE;
1754a09f99edSMiklos Szeredi 				attr->ia_mode &= ~S_ISGID;
1755a09f99edSMiklos Szeredi 			}
1756a09f99edSMiklos Szeredi 		}
17575e940c1dSMiklos Szeredi 	}
1758a09f99edSMiklos Szeredi 	if (!attr->ia_valid)
1759a09f99edSMiklos Szeredi 		return 0;
1760a09f99edSMiklos Szeredi 
1761abb5a14fSLinus Torvalds 	ret = fuse_do_setattr(entry, attr, file);
17625e2b8828SMiklos Szeredi 	if (!ret) {
176360bcc88aSSeth Forshee 		/*
176460bcc88aSSeth Forshee 		 * If filesystem supports acls it may have updated acl xattrs in
176560bcc88aSSeth Forshee 		 * the filesystem, so forget cached acls for the inode.
176660bcc88aSSeth Forshee 		 */
176760bcc88aSSeth Forshee 		if (fc->posix_acl)
176860bcc88aSSeth Forshee 			forget_all_cached_acls(inode);
176960bcc88aSSeth Forshee 
17705e2b8828SMiklos Szeredi 		/* Directory mode changed, may need to revalidate access */
17715e2b8828SMiklos Szeredi 		if (d_is_dir(entry) && (attr->ia_valid & ATTR_MODE))
17725e2b8828SMiklos Szeredi 			fuse_invalidate_entry_cache(entry);
17735e2b8828SMiklos Szeredi 	}
17745e2b8828SMiklos Szeredi 	return ret;
177549d4914fSMiklos Szeredi }
177649d4914fSMiklos Szeredi 
1777a528d35eSDavid Howells static int fuse_getattr(const struct path *path, struct kstat *stat,
1778a528d35eSDavid Howells 			u32 request_mask, unsigned int flags)
1779e5e5558eSMiklos Szeredi {
1780a528d35eSDavid Howells 	struct inode *inode = d_inode(path->dentry);
1781244f6385SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1782244f6385SMiklos Szeredi 
1783c2132c1bSAnatol Pomozov 	if (!fuse_allow_current_process(fc))
1784244f6385SMiklos Szeredi 		return -EACCES;
1785244f6385SMiklos Szeredi 
17865b97eeacSMiklos Szeredi 	return fuse_update_get_attr(inode, NULL, stat);
1787e5e5558eSMiklos Szeredi }
1788e5e5558eSMiklos Szeredi 
1789754661f1SArjan van de Ven static const struct inode_operations fuse_dir_inode_operations = {
1790e5e5558eSMiklos Szeredi 	.lookup		= fuse_lookup,
17919e6268dbSMiklos Szeredi 	.mkdir		= fuse_mkdir,
17929e6268dbSMiklos Szeredi 	.symlink	= fuse_symlink,
17939e6268dbSMiklos Szeredi 	.unlink		= fuse_unlink,
17949e6268dbSMiklos Szeredi 	.rmdir		= fuse_rmdir,
17952773bf00SMiklos Szeredi 	.rename		= fuse_rename2,
17969e6268dbSMiklos Szeredi 	.link		= fuse_link,
17979e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
17989e6268dbSMiklos Szeredi 	.create		= fuse_create,
1799c8ccbe03SMiklos Szeredi 	.atomic_open	= fuse_atomic_open,
18009e6268dbSMiklos Szeredi 	.mknod		= fuse_mknod,
1801e5e5558eSMiklos Szeredi 	.permission	= fuse_permission,
1802e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
180392a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
180460bcc88aSSeth Forshee 	.get_acl	= fuse_get_acl,
180560bcc88aSSeth Forshee 	.set_acl	= fuse_set_acl,
1806e5e5558eSMiklos Szeredi };
1807e5e5558eSMiklos Szeredi 
18084b6f5d20SArjan van de Ven static const struct file_operations fuse_dir_operations = {
1809b6aeadedSMiklos Szeredi 	.llseek		= generic_file_llseek,
1810e5e5558eSMiklos Szeredi 	.read		= generic_read_dir,
1811d9b3dbdcSAl Viro 	.iterate_shared	= fuse_readdir,
1812e5e5558eSMiklos Szeredi 	.open		= fuse_dir_open,
1813e5e5558eSMiklos Szeredi 	.release	= fuse_dir_release,
181482547981SMiklos Szeredi 	.fsync		= fuse_dir_fsync,
1815b18da0c5SMiklos Szeredi 	.unlocked_ioctl	= fuse_dir_ioctl,
1816b18da0c5SMiklos Szeredi 	.compat_ioctl	= fuse_dir_compat_ioctl,
1817e5e5558eSMiklos Szeredi };
1818e5e5558eSMiklos Szeredi 
1819754661f1SArjan van de Ven static const struct inode_operations fuse_common_inode_operations = {
18209e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
1821e5e5558eSMiklos Szeredi 	.permission	= fuse_permission,
1822e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
182392a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
182460bcc88aSSeth Forshee 	.get_acl	= fuse_get_acl,
182560bcc88aSSeth Forshee 	.set_acl	= fuse_set_acl,
1826e5e5558eSMiklos Szeredi };
1827e5e5558eSMiklos Szeredi 
1828754661f1SArjan van de Ven static const struct inode_operations fuse_symlink_inode_operations = {
18299e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
18306b255391SAl Viro 	.get_link	= fuse_get_link,
1831e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
183292a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
1833e5e5558eSMiklos Szeredi };
1834e5e5558eSMiklos Szeredi 
1835e5e5558eSMiklos Szeredi void fuse_init_common(struct inode *inode)
1836e5e5558eSMiklos Szeredi {
1837e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_common_inode_operations;
1838e5e5558eSMiklos Szeredi }
1839e5e5558eSMiklos Szeredi 
1840e5e5558eSMiklos Szeredi void fuse_init_dir(struct inode *inode)
1841e5e5558eSMiklos Szeredi {
1842e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_dir_inode_operations;
1843e5e5558eSMiklos Szeredi 	inode->i_fop = &fuse_dir_operations;
1844e5e5558eSMiklos Szeredi }
1845e5e5558eSMiklos Szeredi 
1846e5e5558eSMiklos Szeredi void fuse_init_symlink(struct inode *inode)
1847e5e5558eSMiklos Szeredi {
1848e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_symlink_inode_operations;
1849e5e5558eSMiklos Szeredi }
1850