xref: /openbmc/linux/fs/fuse/dir.c (revision 802dc0497be2b538ca4300704b45b59bffe29585)
1e5e5558eSMiklos Szeredi /*
2e5e5558eSMiklos Szeredi   FUSE: Filesystem in Userspace
31729a16cSMiklos Szeredi   Copyright (C) 2001-2008  Miklos Szeredi <miklos@szeredi.hu>
4e5e5558eSMiklos Szeredi 
5e5e5558eSMiklos Szeredi   This program can be distributed under the terms of the GNU GPL.
6e5e5558eSMiklos Szeredi   See the file COPYING.
7e5e5558eSMiklos Szeredi */
8e5e5558eSMiklos Szeredi 
9e5e5558eSMiklos Szeredi #include "fuse_i.h"
10e5e5558eSMiklos Szeredi 
11e5e5558eSMiklos Szeredi #include <linux/pagemap.h>
12e5e5558eSMiklos Szeredi #include <linux/file.h>
13e5e5558eSMiklos Szeredi #include <linux/sched.h>
14e5e5558eSMiklos Szeredi #include <linux/namei.h>
1507e77dcaSMiklos Szeredi #include <linux/slab.h>
16703c7362SSeth Forshee #include <linux/xattr.h>
17261aaba7SMiklos Szeredi #include <linux/iversion.h>
1860bcc88aSSeth Forshee #include <linux/posix_acl.h>
19e5e5558eSMiklos Szeredi 
204582a4abSFeng Shuo static void fuse_advise_use_readdirplus(struct inode *dir)
214582a4abSFeng Shuo {
224582a4abSFeng Shuo 	struct fuse_inode *fi = get_fuse_inode(dir);
234582a4abSFeng Shuo 
244582a4abSFeng Shuo 	set_bit(FUSE_I_ADVISE_RDPLUS, &fi->state);
254582a4abSFeng Shuo }
264582a4abSFeng Shuo 
27f75fdf22SMiklos Szeredi union fuse_dentry {
28f75fdf22SMiklos Szeredi 	u64 time;
29f75fdf22SMiklos Szeredi 	struct rcu_head rcu;
30f75fdf22SMiklos Szeredi };
31f75fdf22SMiklos Szeredi 
320a0898cfSMiklos Szeredi static inline void fuse_dentry_settime(struct dentry *entry, u64 time)
330a0898cfSMiklos Szeredi {
34f75fdf22SMiklos Szeredi 	((union fuse_dentry *) entry->d_fsdata)->time = time;
350a0898cfSMiklos Szeredi }
360a0898cfSMiklos Szeredi 
370a0898cfSMiklos Szeredi static inline u64 fuse_dentry_time(struct dentry *entry)
380a0898cfSMiklos Szeredi {
39f75fdf22SMiklos Szeredi 	return ((union fuse_dentry *) entry->d_fsdata)->time;
400a0898cfSMiklos Szeredi }
410a0898cfSMiklos Szeredi 
426f9f1180SMiklos Szeredi /*
436f9f1180SMiklos Szeredi  * FUSE caches dentries and attributes with separate timeout.  The
446f9f1180SMiklos Szeredi  * time in jiffies until the dentry/attributes are valid is stored in
45f75fdf22SMiklos Szeredi  * dentry->d_fsdata and fuse_inode->i_time respectively.
466f9f1180SMiklos Szeredi  */
476f9f1180SMiklos Szeredi 
486f9f1180SMiklos Szeredi /*
496f9f1180SMiklos Szeredi  * Calculate the time in jiffies until a dentry/attributes are valid
506f9f1180SMiklos Szeredi  */
51bcb6f6d2SMiklos Szeredi static u64 time_to_jiffies(u64 sec, u32 nsec)
52e5e5558eSMiklos Szeredi {
53685d16ddSMiklos Szeredi 	if (sec || nsec) {
54bcb6f6d2SMiklos Szeredi 		struct timespec64 ts = {
55bcb6f6d2SMiklos Szeredi 			sec,
5621067527SDavid Sheets 			min_t(u32, nsec, NSEC_PER_SEC - 1)
57bcb6f6d2SMiklos Szeredi 		};
58bcb6f6d2SMiklos Szeredi 
59bcb6f6d2SMiklos Szeredi 		return get_jiffies_64() + timespec64_to_jiffies(&ts);
60685d16ddSMiklos Szeredi 	} else
610a0898cfSMiklos Szeredi 		return 0;
62e5e5558eSMiklos Szeredi }
63e5e5558eSMiklos Szeredi 
646f9f1180SMiklos Szeredi /*
656f9f1180SMiklos Szeredi  * Set dentry and possibly attribute timeouts from the lookup/mk*
666f9f1180SMiklos Szeredi  * replies
676f9f1180SMiklos Szeredi  */
68d123d8e1SMiklos Szeredi void fuse_change_entry_timeout(struct dentry *entry, struct fuse_entry_out *o)
690aa7c699SMiklos Szeredi {
700a0898cfSMiklos Szeredi 	fuse_dentry_settime(entry,
710a0898cfSMiklos Szeredi 		time_to_jiffies(o->entry_valid, o->entry_valid_nsec));
721fb69e78SMiklos Szeredi }
731fb69e78SMiklos Szeredi 
741fb69e78SMiklos Szeredi static u64 attr_timeout(struct fuse_attr_out *o)
751fb69e78SMiklos Szeredi {
761fb69e78SMiklos Szeredi 	return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
771fb69e78SMiklos Szeredi }
781fb69e78SMiklos Szeredi 
79d123d8e1SMiklos Szeredi u64 entry_attr_timeout(struct fuse_entry_out *o)
801fb69e78SMiklos Szeredi {
811fb69e78SMiklos Szeredi 	return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
828cbdf1e6SMiklos Szeredi }
838cbdf1e6SMiklos Szeredi 
842f1e8196SMiklos Szeredi static void fuse_invalidate_attr_mask(struct inode *inode, u32 mask)
852f1e8196SMiklos Szeredi {
862f1e8196SMiklos Szeredi 	set_mask_bits(&get_fuse_inode(inode)->inval_mask, 0, mask);
872f1e8196SMiklos Szeredi }
882f1e8196SMiklos Szeredi 
896f9f1180SMiklos Szeredi /*
906f9f1180SMiklos Szeredi  * Mark the attributes as stale, so that at the next call to
916f9f1180SMiklos Szeredi  * ->getattr() they will be fetched from userspace
926f9f1180SMiklos Szeredi  */
938cbdf1e6SMiklos Szeredi void fuse_invalidate_attr(struct inode *inode)
948cbdf1e6SMiklos Szeredi {
952f1e8196SMiklos Szeredi 	fuse_invalidate_attr_mask(inode, STATX_BASIC_STATS);
968cbdf1e6SMiklos Szeredi }
978cbdf1e6SMiklos Szeredi 
98261aaba7SMiklos Szeredi static void fuse_dir_changed(struct inode *dir)
99261aaba7SMiklos Szeredi {
100261aaba7SMiklos Szeredi 	fuse_invalidate_attr(dir);
101261aaba7SMiklos Szeredi 	inode_maybe_inc_iversion(dir, false);
102261aaba7SMiklos Szeredi }
103261aaba7SMiklos Szeredi 
104451418fcSAndrew Gallagher /**
105451418fcSAndrew Gallagher  * Mark the attributes as stale due to an atime change.  Avoid the invalidate if
106451418fcSAndrew Gallagher  * atime is not used.
107451418fcSAndrew Gallagher  */
108451418fcSAndrew Gallagher void fuse_invalidate_atime(struct inode *inode)
109451418fcSAndrew Gallagher {
110451418fcSAndrew Gallagher 	if (!IS_RDONLY(inode))
1112f1e8196SMiklos Szeredi 		fuse_invalidate_attr_mask(inode, STATX_ATIME);
112451418fcSAndrew Gallagher }
113451418fcSAndrew Gallagher 
1146f9f1180SMiklos Szeredi /*
1156f9f1180SMiklos Szeredi  * Just mark the entry as stale, so that a next attempt to look it up
1166f9f1180SMiklos Szeredi  * will result in a new lookup call to userspace
1176f9f1180SMiklos Szeredi  *
1186f9f1180SMiklos Szeredi  * This is called when a dentry is about to become negative and the
1196f9f1180SMiklos Szeredi  * timeout is unknown (unlink, rmdir, rename and in some cases
1206f9f1180SMiklos Szeredi  * lookup)
1216f9f1180SMiklos Szeredi  */
122dbd561d2SMiklos Szeredi void fuse_invalidate_entry_cache(struct dentry *entry)
1238cbdf1e6SMiklos Szeredi {
1240a0898cfSMiklos Szeredi 	fuse_dentry_settime(entry, 0);
1258cbdf1e6SMiklos Szeredi }
1268cbdf1e6SMiklos Szeredi 
1276f9f1180SMiklos Szeredi /*
1286f9f1180SMiklos Szeredi  * Same as fuse_invalidate_entry_cache(), but also try to remove the
1296f9f1180SMiklos Szeredi  * dentry from the hash
1306f9f1180SMiklos Szeredi  */
1318cbdf1e6SMiklos Szeredi static void fuse_invalidate_entry(struct dentry *entry)
1328cbdf1e6SMiklos Szeredi {
1338cbdf1e6SMiklos Szeredi 	d_invalidate(entry);
1348cbdf1e6SMiklos Szeredi 	fuse_invalidate_entry_cache(entry);
1350aa7c699SMiklos Szeredi }
1360aa7c699SMiklos Szeredi 
1377078187aSMiklos Szeredi static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_args *args,
13813983d06SAl Viro 			     u64 nodeid, const struct qstr *name,
139e5e5558eSMiklos Szeredi 			     struct fuse_entry_out *outarg)
140e5e5558eSMiklos Szeredi {
1410e9663eeSMiklos Szeredi 	memset(outarg, 0, sizeof(struct fuse_entry_out));
1427078187aSMiklos Szeredi 	args->in.h.opcode = FUSE_LOOKUP;
1437078187aSMiklos Szeredi 	args->in.h.nodeid = nodeid;
1447078187aSMiklos Szeredi 	args->in.numargs = 1;
1457078187aSMiklos Szeredi 	args->in.args[0].size = name->len + 1;
1467078187aSMiklos Szeredi 	args->in.args[0].value = name->name;
1477078187aSMiklos Szeredi 	args->out.numargs = 1;
1487078187aSMiklos Szeredi 	args->out.args[0].size = sizeof(struct fuse_entry_out);
1497078187aSMiklos Szeredi 	args->out.args[0].value = outarg;
150e5e5558eSMiklos Szeredi }
151e5e5558eSMiklos Szeredi 
1525c5c5e51SMiklos Szeredi u64 fuse_get_attr_version(struct fuse_conn *fc)
1537dca9fd3SMiklos Szeredi {
1547dca9fd3SMiklos Szeredi 	u64 curr_version;
1557dca9fd3SMiklos Szeredi 
1567dca9fd3SMiklos Szeredi 	/*
1577dca9fd3SMiklos Szeredi 	 * The spin lock isn't actually needed on 64bit archs, but we
1587dca9fd3SMiklos Szeredi 	 * don't yet care too much about such optimizations.
1597dca9fd3SMiklos Szeredi 	 */
1607dca9fd3SMiklos Szeredi 	spin_lock(&fc->lock);
1617dca9fd3SMiklos Szeredi 	curr_version = fc->attr_version;
1627dca9fd3SMiklos Szeredi 	spin_unlock(&fc->lock);
1637dca9fd3SMiklos Szeredi 
1647dca9fd3SMiklos Szeredi 	return curr_version;
1657dca9fd3SMiklos Szeredi }
1667dca9fd3SMiklos Szeredi 
1676f9f1180SMiklos Szeredi /*
1686f9f1180SMiklos Szeredi  * Check whether the dentry is still valid
1696f9f1180SMiklos Szeredi  *
1706f9f1180SMiklos Szeredi  * If the entry validity timeout has expired and the dentry is
1716f9f1180SMiklos Szeredi  * positive, try to redo the lookup.  If the lookup results in a
1726f9f1180SMiklos Szeredi  * different inode, then let the VFS invalidate the dentry and redo
1736f9f1180SMiklos Szeredi  * the lookup once more.  If the lookup results in the same inode,
1746f9f1180SMiklos Szeredi  * then refresh the attributes, timeouts and mark the dentry valid.
1756f9f1180SMiklos Szeredi  */
1760b728e19SAl Viro static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
177e5e5558eSMiklos Szeredi {
17834286d66SNick Piggin 	struct inode *inode;
17928420dadSMiklos Szeredi 	struct dentry *parent;
18028420dadSMiklos Szeredi 	struct fuse_conn *fc;
1816314efeeSMiklos Szeredi 	struct fuse_inode *fi;
182e2a6b952SMiklos Szeredi 	int ret;
1838cbdf1e6SMiklos Szeredi 
1842b0143b5SDavid Howells 	inode = d_inode_rcu(entry);
1858cbdf1e6SMiklos Szeredi 	if (inode && is_bad_inode(inode))
186e2a6b952SMiklos Szeredi 		goto invalid;
187154210ccSAnand Avati 	else if (time_before64(fuse_dentry_time(entry), get_jiffies_64()) ||
188154210ccSAnand Avati 		 (flags & LOOKUP_REVAL)) {
189e5e5558eSMiklos Szeredi 		struct fuse_entry_out outarg;
1907078187aSMiklos Szeredi 		FUSE_ARGS(args);
19107e77dcaSMiklos Szeredi 		struct fuse_forget_link *forget;
1921fb69e78SMiklos Szeredi 		u64 attr_version;
1938cbdf1e6SMiklos Szeredi 
19450322fe7SMiklos Szeredi 		/* For negative dentries, always do a fresh lookup */
1958cbdf1e6SMiklos Szeredi 		if (!inode)
196e2a6b952SMiklos Szeredi 			goto invalid;
1978cbdf1e6SMiklos Szeredi 
198e2a6b952SMiklos Szeredi 		ret = -ECHILD;
1990b728e19SAl Viro 		if (flags & LOOKUP_RCU)
200e2a6b952SMiklos Szeredi 			goto out;
201e7c0a167SMiklos Szeredi 
2028cbdf1e6SMiklos Szeredi 		fc = get_fuse_conn(inode);
203e5e5558eSMiklos Szeredi 
20407e77dcaSMiklos Szeredi 		forget = fuse_alloc_forget();
205e2a6b952SMiklos Szeredi 		ret = -ENOMEM;
2067078187aSMiklos Szeredi 		if (!forget)
207e2a6b952SMiklos Szeredi 			goto out;
2082d51013eSMiklos Szeredi 
2097dca9fd3SMiklos Szeredi 		attr_version = fuse_get_attr_version(fc);
2101fb69e78SMiklos Szeredi 
211e956edd0SMiklos Szeredi 		parent = dget_parent(entry);
2122b0143b5SDavid Howells 		fuse_lookup_init(fc, &args, get_node_id(d_inode(parent)),
213c180eebeSMiklos Szeredi 				 &entry->d_name, &outarg);
2147078187aSMiklos Szeredi 		ret = fuse_simple_request(fc, &args);
215e956edd0SMiklos Szeredi 		dput(parent);
21650322fe7SMiklos Szeredi 		/* Zero nodeid is same as -ENOENT */
2177078187aSMiklos Szeredi 		if (!ret && !outarg.nodeid)
2187078187aSMiklos Szeredi 			ret = -ENOENT;
2197078187aSMiklos Szeredi 		if (!ret) {
2206314efeeSMiklos Szeredi 			fi = get_fuse_inode(inode);
2219e6268dbSMiklos Szeredi 			if (outarg.nodeid != get_node_id(inode)) {
22207e77dcaSMiklos Szeredi 				fuse_queue_forget(fc, forget, outarg.nodeid, 1);
223e2a6b952SMiklos Szeredi 				goto invalid;
2249e6268dbSMiklos Szeredi 			}
2258da5ff23SMiklos Szeredi 			spin_lock(&fc->lock);
2269e6268dbSMiklos Szeredi 			fi->nlookup++;
2278da5ff23SMiklos Szeredi 			spin_unlock(&fc->lock);
2289e6268dbSMiklos Szeredi 		}
22907e77dcaSMiklos Szeredi 		kfree(forget);
2307078187aSMiklos Szeredi 		if (ret == -ENOMEM)
2317078187aSMiklos Szeredi 			goto out;
2327078187aSMiklos Szeredi 		if (ret || (outarg.attr.mode ^ inode->i_mode) & S_IFMT)
233e2a6b952SMiklos Szeredi 			goto invalid;
234e5e5558eSMiklos Szeredi 
23560bcc88aSSeth Forshee 		forget_all_cached_acls(inode);
2361fb69e78SMiklos Szeredi 		fuse_change_attributes(inode, &outarg.attr,
2371fb69e78SMiklos Szeredi 				       entry_attr_timeout(&outarg),
2381fb69e78SMiklos Szeredi 				       attr_version);
2391fb69e78SMiklos Szeredi 		fuse_change_entry_timeout(entry, &outarg);
24028420dadSMiklos Szeredi 	} else if (inode) {
2416314efeeSMiklos Szeredi 		fi = get_fuse_inode(inode);
2426314efeeSMiklos Szeredi 		if (flags & LOOKUP_RCU) {
2436314efeeSMiklos Szeredi 			if (test_bit(FUSE_I_INIT_RDPLUS, &fi->state))
2446314efeeSMiklos Szeredi 				return -ECHILD;
2456314efeeSMiklos Szeredi 		} else if (test_and_clear_bit(FUSE_I_INIT_RDPLUS, &fi->state)) {
24628420dadSMiklos Szeredi 			parent = dget_parent(entry);
2472b0143b5SDavid Howells 			fuse_advise_use_readdirplus(d_inode(parent));
24828420dadSMiklos Szeredi 			dput(parent);
249e5e5558eSMiklos Szeredi 		}
25028420dadSMiklos Szeredi 	}
251e2a6b952SMiklos Szeredi 	ret = 1;
252e2a6b952SMiklos Szeredi out:
253e2a6b952SMiklos Szeredi 	return ret;
254e2a6b952SMiklos Szeredi 
255e2a6b952SMiklos Szeredi invalid:
256e2a6b952SMiklos Szeredi 	ret = 0;
257e2a6b952SMiklos Szeredi 	goto out;
258e5e5558eSMiklos Szeredi }
259e5e5558eSMiklos Szeredi 
260f75fdf22SMiklos Szeredi static int fuse_dentry_init(struct dentry *dentry)
261f75fdf22SMiklos Szeredi {
262f75fdf22SMiklos Szeredi 	dentry->d_fsdata = kzalloc(sizeof(union fuse_dentry), GFP_KERNEL);
263f75fdf22SMiklos Szeredi 
264f75fdf22SMiklos Szeredi 	return dentry->d_fsdata ? 0 : -ENOMEM;
265f75fdf22SMiklos Szeredi }
266f75fdf22SMiklos Szeredi static void fuse_dentry_release(struct dentry *dentry)
267f75fdf22SMiklos Szeredi {
268f75fdf22SMiklos Szeredi 	union fuse_dentry *fd = dentry->d_fsdata;
269f75fdf22SMiklos Szeredi 
270f75fdf22SMiklos Szeredi 	kfree_rcu(fd, rcu);
271f75fdf22SMiklos Szeredi }
272f75fdf22SMiklos Szeredi 
2734269590aSAl Viro const struct dentry_operations fuse_dentry_operations = {
274e5e5558eSMiklos Szeredi 	.d_revalidate	= fuse_dentry_revalidate,
275f75fdf22SMiklos Szeredi 	.d_init		= fuse_dentry_init,
276f75fdf22SMiklos Szeredi 	.d_release	= fuse_dentry_release,
277e5e5558eSMiklos Szeredi };
278e5e5558eSMiklos Szeredi 
2790ce267ffSMiklos Szeredi const struct dentry_operations fuse_root_dentry_operations = {
2800ce267ffSMiklos Szeredi 	.d_init		= fuse_dentry_init,
2810ce267ffSMiklos Szeredi 	.d_release	= fuse_dentry_release,
2820ce267ffSMiklos Szeredi };
2830ce267ffSMiklos Szeredi 
284a5bfffacSTimo Savola int fuse_valid_type(int m)
28539ee059aSMiklos Szeredi {
28639ee059aSMiklos Szeredi 	return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) ||
28739ee059aSMiklos Szeredi 		S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m);
28839ee059aSMiklos Szeredi }
28939ee059aSMiklos Szeredi 
29013983d06SAl Viro int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name,
291c180eebeSMiklos Szeredi 		     struct fuse_entry_out *outarg, struct inode **inode)
292c180eebeSMiklos Szeredi {
293c180eebeSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn_super(sb);
2947078187aSMiklos Szeredi 	FUSE_ARGS(args);
29507e77dcaSMiklos Szeredi 	struct fuse_forget_link *forget;
296c180eebeSMiklos Szeredi 	u64 attr_version;
297c180eebeSMiklos Szeredi 	int err;
298c180eebeSMiklos Szeredi 
299c180eebeSMiklos Szeredi 	*inode = NULL;
300c180eebeSMiklos Szeredi 	err = -ENAMETOOLONG;
301c180eebeSMiklos Szeredi 	if (name->len > FUSE_NAME_MAX)
302c180eebeSMiklos Szeredi 		goto out;
303c180eebeSMiklos Szeredi 
304c180eebeSMiklos Szeredi 
30507e77dcaSMiklos Szeredi 	forget = fuse_alloc_forget();
30607e77dcaSMiklos Szeredi 	err = -ENOMEM;
3077078187aSMiklos Szeredi 	if (!forget)
308c180eebeSMiklos Szeredi 		goto out;
309c180eebeSMiklos Szeredi 
310c180eebeSMiklos Szeredi 	attr_version = fuse_get_attr_version(fc);
311c180eebeSMiklos Szeredi 
3127078187aSMiklos Szeredi 	fuse_lookup_init(fc, &args, nodeid, name, outarg);
3137078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
314c180eebeSMiklos Szeredi 	/* Zero nodeid is same as -ENOENT, but with valid timeout */
315c180eebeSMiklos Szeredi 	if (err || !outarg->nodeid)
316c180eebeSMiklos Szeredi 		goto out_put_forget;
317c180eebeSMiklos Szeredi 
318c180eebeSMiklos Szeredi 	err = -EIO;
319c180eebeSMiklos Szeredi 	if (!outarg->nodeid)
320c180eebeSMiklos Szeredi 		goto out_put_forget;
321c180eebeSMiklos Szeredi 	if (!fuse_valid_type(outarg->attr.mode))
322c180eebeSMiklos Szeredi 		goto out_put_forget;
323c180eebeSMiklos Szeredi 
324c180eebeSMiklos Szeredi 	*inode = fuse_iget(sb, outarg->nodeid, outarg->generation,
325c180eebeSMiklos Szeredi 			   &outarg->attr, entry_attr_timeout(outarg),
326c180eebeSMiklos Szeredi 			   attr_version);
327c180eebeSMiklos Szeredi 	err = -ENOMEM;
328c180eebeSMiklos Szeredi 	if (!*inode) {
32907e77dcaSMiklos Szeredi 		fuse_queue_forget(fc, forget, outarg->nodeid, 1);
330c180eebeSMiklos Szeredi 		goto out;
331c180eebeSMiklos Szeredi 	}
332c180eebeSMiklos Szeredi 	err = 0;
333c180eebeSMiklos Szeredi 
334c180eebeSMiklos Szeredi  out_put_forget:
33507e77dcaSMiklos Szeredi 	kfree(forget);
336c180eebeSMiklos Szeredi  out:
337c180eebeSMiklos Szeredi 	return err;
338c180eebeSMiklos Szeredi }
339c180eebeSMiklos Szeredi 
3400aa7c699SMiklos Szeredi static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
34100cd8dd3SAl Viro 				  unsigned int flags)
342e5e5558eSMiklos Szeredi {
343e5e5558eSMiklos Szeredi 	int err;
344e5e5558eSMiklos Szeredi 	struct fuse_entry_out outarg;
345c180eebeSMiklos Szeredi 	struct inode *inode;
3460de6256dSMiklos Szeredi 	struct dentry *newent;
347c180eebeSMiklos Szeredi 	bool outarg_valid = true;
34863576c13SMiklos Szeredi 	bool locked;
349e5e5558eSMiklos Szeredi 
35063576c13SMiklos Szeredi 	locked = fuse_lock_inode(dir);
351c180eebeSMiklos Szeredi 	err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name,
352c180eebeSMiklos Szeredi 			       &outarg, &inode);
35363576c13SMiklos Szeredi 	fuse_unlock_inode(dir, locked);
354c180eebeSMiklos Szeredi 	if (err == -ENOENT) {
355c180eebeSMiklos Szeredi 		outarg_valid = false;
356c180eebeSMiklos Szeredi 		err = 0;
3572d51013eSMiklos Szeredi 	}
358c180eebeSMiklos Szeredi 	if (err)
359c180eebeSMiklos Szeredi 		goto out_err;
3602d51013eSMiklos Szeredi 
361ee4e5271SMiklos Szeredi 	err = -EIO;
362c180eebeSMiklos Szeredi 	if (inode && get_node_id(inode) == FUSE_ROOT_ID)
363c180eebeSMiklos Szeredi 		goto out_iput;
364e5e5558eSMiklos Szeredi 
36541d28bcaSAl Viro 	newent = d_splice_alias(inode, entry);
366c180eebeSMiklos Szeredi 	err = PTR_ERR(newent);
367c180eebeSMiklos Szeredi 	if (IS_ERR(newent))
3685835f339SMiklos Szeredi 		goto out_err;
369d2a85164SMiklos Szeredi 
3700de6256dSMiklos Szeredi 	entry = newent ? newent : entry;
371c180eebeSMiklos Szeredi 	if (outarg_valid)
3721fb69e78SMiklos Szeredi 		fuse_change_entry_timeout(entry, &outarg);
3738cbdf1e6SMiklos Szeredi 	else
3748cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
375c180eebeSMiklos Szeredi 
3764582a4abSFeng Shuo 	fuse_advise_use_readdirplus(dir);
3770de6256dSMiklos Szeredi 	return newent;
378c180eebeSMiklos Szeredi 
379c180eebeSMiklos Szeredi  out_iput:
380c180eebeSMiklos Szeredi 	iput(inode);
381c180eebeSMiklos Szeredi  out_err:
382c180eebeSMiklos Szeredi 	return ERR_PTR(err);
383e5e5558eSMiklos Szeredi }
384e5e5558eSMiklos Szeredi 
3856f9f1180SMiklos Szeredi /*
3866f9f1180SMiklos Szeredi  * Atomic create+open operation
3876f9f1180SMiklos Szeredi  *
3886f9f1180SMiklos Szeredi  * If the filesystem doesn't support this, then fall back to separate
3896f9f1180SMiklos Szeredi  * 'mknod' + 'open' requests.
3906f9f1180SMiklos Szeredi  */
391d9585277SAl Viro static int fuse_create_open(struct inode *dir, struct dentry *entry,
39230d90494SAl Viro 			    struct file *file, unsigned flags,
393b452a458SAl Viro 			    umode_t mode)
394fd72faacSMiklos Szeredi {
395fd72faacSMiklos Szeredi 	int err;
396fd72faacSMiklos Szeredi 	struct inode *inode;
397fd72faacSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
3987078187aSMiklos Szeredi 	FUSE_ARGS(args);
39907e77dcaSMiklos Szeredi 	struct fuse_forget_link *forget;
400e0a43ddcSMiklos Szeredi 	struct fuse_create_in inarg;
401fd72faacSMiklos Szeredi 	struct fuse_open_out outopen;
402fd72faacSMiklos Szeredi 	struct fuse_entry_out outentry;
403fd72faacSMiklos Szeredi 	struct fuse_file *ff;
404fd72faacSMiklos Szeredi 
405af109bcaSMiklos Szeredi 	/* Userspace expects S_IFREG in create mode */
406af109bcaSMiklos Szeredi 	BUG_ON((mode & S_IFMT) != S_IFREG);
407af109bcaSMiklos Szeredi 
40807e77dcaSMiklos Szeredi 	forget = fuse_alloc_forget();
409c8ccbe03SMiklos Szeredi 	err = -ENOMEM;
41007e77dcaSMiklos Szeredi 	if (!forget)
411c8ccbe03SMiklos Szeredi 		goto out_err;
41251eb01e7SMiklos Szeredi 
413ce1d5a49SMiklos Szeredi 	err = -ENOMEM;
414acf99433STejun Heo 	ff = fuse_file_alloc(fc);
415fd72faacSMiklos Szeredi 	if (!ff)
4167078187aSMiklos Szeredi 		goto out_put_forget_req;
417fd72faacSMiklos Szeredi 
418e0a43ddcSMiklos Szeredi 	if (!fc->dont_mask)
419e0a43ddcSMiklos Szeredi 		mode &= ~current_umask();
420e0a43ddcSMiklos Szeredi 
421fd72faacSMiklos Szeredi 	flags &= ~O_NOCTTY;
422fd72faacSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
4230e9663eeSMiklos Szeredi 	memset(&outentry, 0, sizeof(outentry));
424fd72faacSMiklos Szeredi 	inarg.flags = flags;
425fd72faacSMiklos Szeredi 	inarg.mode = mode;
426e0a43ddcSMiklos Szeredi 	inarg.umask = current_umask();
4277078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_CREATE;
4287078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(dir);
4297078187aSMiklos Szeredi 	args.in.numargs = 2;
43021f62174SMiklos Szeredi 	args.in.args[0].size = sizeof(inarg);
4317078187aSMiklos Szeredi 	args.in.args[0].value = &inarg;
4327078187aSMiklos Szeredi 	args.in.args[1].size = entry->d_name.len + 1;
4337078187aSMiklos Szeredi 	args.in.args[1].value = entry->d_name.name;
4347078187aSMiklos Szeredi 	args.out.numargs = 2;
4357078187aSMiklos Szeredi 	args.out.args[0].size = sizeof(outentry);
4367078187aSMiklos Szeredi 	args.out.args[0].value = &outentry;
4377078187aSMiklos Szeredi 	args.out.args[1].size = sizeof(outopen);
4387078187aSMiklos Szeredi 	args.out.args[1].value = &outopen;
4397078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
440c8ccbe03SMiklos Szeredi 	if (err)
441fd72faacSMiklos Szeredi 		goto out_free_ff;
442fd72faacSMiklos Szeredi 
443fd72faacSMiklos Szeredi 	err = -EIO;
4442827d0b2SMiklos Szeredi 	if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid))
445fd72faacSMiklos Szeredi 		goto out_free_ff;
446fd72faacSMiklos Szeredi 
447c7b7143cSMiklos Szeredi 	ff->fh = outopen.fh;
448c7b7143cSMiklos Szeredi 	ff->nodeid = outentry.nodeid;
449c7b7143cSMiklos Szeredi 	ff->open_flags = outopen.open_flags;
450fd72faacSMiklos Szeredi 	inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
4511fb69e78SMiklos Szeredi 			  &outentry.attr, entry_attr_timeout(&outentry), 0);
452fd72faacSMiklos Szeredi 	if (!inode) {
453fd72faacSMiklos Szeredi 		flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
4548b0797a4SMiklos Szeredi 		fuse_sync_release(ff, flags);
45507e77dcaSMiklos Szeredi 		fuse_queue_forget(fc, forget, outentry.nodeid, 1);
456c8ccbe03SMiklos Szeredi 		err = -ENOMEM;
457c8ccbe03SMiklos Szeredi 		goto out_err;
458fd72faacSMiklos Szeredi 	}
45907e77dcaSMiklos Szeredi 	kfree(forget);
460fd72faacSMiklos Szeredi 	d_instantiate(entry, inode);
4611fb69e78SMiklos Szeredi 	fuse_change_entry_timeout(entry, &outentry);
462261aaba7SMiklos Szeredi 	fuse_dir_changed(dir);
463be12af3eSAl Viro 	err = finish_open(file, entry, generic_file_open);
46430d90494SAl Viro 	if (err) {
4658b0797a4SMiklos Szeredi 		fuse_sync_release(ff, flags);
466c8ccbe03SMiklos Szeredi 	} else {
467267d8444SMiklos Szeredi 		file->private_data = ff;
468c7b7143cSMiklos Szeredi 		fuse_finish_open(inode, file);
469c8ccbe03SMiklos Szeredi 	}
470d9585277SAl Viro 	return err;
471fd72faacSMiklos Szeredi 
472fd72faacSMiklos Szeredi out_free_ff:
473fd72faacSMiklos Szeredi 	fuse_file_free(ff);
47451eb01e7SMiklos Szeredi out_put_forget_req:
47507e77dcaSMiklos Szeredi 	kfree(forget);
476c8ccbe03SMiklos Szeredi out_err:
477d9585277SAl Viro 	return err;
478c8ccbe03SMiklos Szeredi }
479c8ccbe03SMiklos Szeredi 
480c8ccbe03SMiklos Szeredi static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t);
481d9585277SAl Viro static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
48230d90494SAl Viro 			    struct file *file, unsigned flags,
48344907d79SAl Viro 			    umode_t mode)
484c8ccbe03SMiklos Szeredi {
485c8ccbe03SMiklos Szeredi 	int err;
486c8ccbe03SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
487c8ccbe03SMiklos Szeredi 	struct dentry *res = NULL;
488c8ccbe03SMiklos Szeredi 
48900699ad8SAl Viro 	if (d_in_lookup(entry)) {
49000cd8dd3SAl Viro 		res = fuse_lookup(dir, entry, 0);
491c8ccbe03SMiklos Szeredi 		if (IS_ERR(res))
492d9585277SAl Viro 			return PTR_ERR(res);
493c8ccbe03SMiklos Szeredi 
494c8ccbe03SMiklos Szeredi 		if (res)
495c8ccbe03SMiklos Szeredi 			entry = res;
496c8ccbe03SMiklos Szeredi 	}
497c8ccbe03SMiklos Szeredi 
4982b0143b5SDavid Howells 	if (!(flags & O_CREAT) || d_really_is_positive(entry))
499c8ccbe03SMiklos Szeredi 		goto no_open;
500c8ccbe03SMiklos Szeredi 
501c8ccbe03SMiklos Szeredi 	/* Only creates */
50273a09dd9SAl Viro 	file->f_mode |= FMODE_CREATED;
503c8ccbe03SMiklos Szeredi 
504c8ccbe03SMiklos Szeredi 	if (fc->no_create)
505c8ccbe03SMiklos Szeredi 		goto mknod;
506c8ccbe03SMiklos Szeredi 
507b452a458SAl Viro 	err = fuse_create_open(dir, entry, file, flags, mode);
508d9585277SAl Viro 	if (err == -ENOSYS) {
509c8ccbe03SMiklos Szeredi 		fc->no_create = 1;
510c8ccbe03SMiklos Szeredi 		goto mknod;
511c8ccbe03SMiklos Szeredi 	}
512c8ccbe03SMiklos Szeredi out_dput:
513c8ccbe03SMiklos Szeredi 	dput(res);
514d9585277SAl Viro 	return err;
515c8ccbe03SMiklos Szeredi 
516c8ccbe03SMiklos Szeredi mknod:
517c8ccbe03SMiklos Szeredi 	err = fuse_mknod(dir, entry, mode, 0);
518d9585277SAl Viro 	if (err)
519c8ccbe03SMiklos Szeredi 		goto out_dput;
520c8ccbe03SMiklos Szeredi no_open:
521e45198a6SAl Viro 	return finish_no_open(file, res);
522fd72faacSMiklos Szeredi }
523fd72faacSMiklos Szeredi 
5246f9f1180SMiklos Szeredi /*
5256f9f1180SMiklos Szeredi  * Code shared between mknod, mkdir, symlink and link
5266f9f1180SMiklos Szeredi  */
5277078187aSMiklos Szeredi static int create_new_entry(struct fuse_conn *fc, struct fuse_args *args,
5289e6268dbSMiklos Szeredi 			    struct inode *dir, struct dentry *entry,
529541af6a0SAl Viro 			    umode_t mode)
5309e6268dbSMiklos Szeredi {
5319e6268dbSMiklos Szeredi 	struct fuse_entry_out outarg;
5329e6268dbSMiklos Szeredi 	struct inode *inode;
533c971e6a0SAl Viro 	struct dentry *d;
5349e6268dbSMiklos Szeredi 	int err;
53507e77dcaSMiklos Szeredi 	struct fuse_forget_link *forget;
5362d51013eSMiklos Szeredi 
53707e77dcaSMiklos Szeredi 	forget = fuse_alloc_forget();
5387078187aSMiklos Szeredi 	if (!forget)
53907e77dcaSMiklos Szeredi 		return -ENOMEM;
5409e6268dbSMiklos Szeredi 
5410e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
5427078187aSMiklos Szeredi 	args->in.h.nodeid = get_node_id(dir);
5437078187aSMiklos Szeredi 	args->out.numargs = 1;
5447078187aSMiklos Szeredi 	args->out.args[0].size = sizeof(outarg);
5457078187aSMiklos Szeredi 	args->out.args[0].value = &outarg;
5467078187aSMiklos Szeredi 	err = fuse_simple_request(fc, args);
5472d51013eSMiklos Szeredi 	if (err)
5482d51013eSMiklos Szeredi 		goto out_put_forget_req;
5492d51013eSMiklos Szeredi 
55039ee059aSMiklos Szeredi 	err = -EIO;
55139ee059aSMiklos Szeredi 	if (invalid_nodeid(outarg.nodeid))
5522d51013eSMiklos Szeredi 		goto out_put_forget_req;
55339ee059aSMiklos Szeredi 
55439ee059aSMiklos Szeredi 	if ((outarg.attr.mode ^ mode) & S_IFMT)
5552d51013eSMiklos Szeredi 		goto out_put_forget_req;
55639ee059aSMiklos Szeredi 
5579e6268dbSMiklos Szeredi 	inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
5581fb69e78SMiklos Szeredi 			  &outarg.attr, entry_attr_timeout(&outarg), 0);
5599e6268dbSMiklos Szeredi 	if (!inode) {
56007e77dcaSMiklos Szeredi 		fuse_queue_forget(fc, forget, outarg.nodeid, 1);
5619e6268dbSMiklos Szeredi 		return -ENOMEM;
5629e6268dbSMiklos Szeredi 	}
56307e77dcaSMiklos Szeredi 	kfree(forget);
5649e6268dbSMiklos Szeredi 
565c971e6a0SAl Viro 	d_drop(entry);
566c971e6a0SAl Viro 	d = d_splice_alias(inode, entry);
567c971e6a0SAl Viro 	if (IS_ERR(d))
568c971e6a0SAl Viro 		return PTR_ERR(d);
569d2a85164SMiklos Szeredi 
570c971e6a0SAl Viro 	if (d) {
571c971e6a0SAl Viro 		fuse_change_entry_timeout(d, &outarg);
572c971e6a0SAl Viro 		dput(d);
573c971e6a0SAl Viro 	} else {
5741fb69e78SMiklos Szeredi 		fuse_change_entry_timeout(entry, &outarg);
575c971e6a0SAl Viro 	}
576261aaba7SMiklos Szeredi 	fuse_dir_changed(dir);
5779e6268dbSMiklos Szeredi 	return 0;
57839ee059aSMiklos Szeredi 
5792d51013eSMiklos Szeredi  out_put_forget_req:
58007e77dcaSMiklos Szeredi 	kfree(forget);
58139ee059aSMiklos Szeredi 	return err;
5829e6268dbSMiklos Szeredi }
5839e6268dbSMiklos Szeredi 
5841a67aafbSAl Viro static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode,
5859e6268dbSMiklos Szeredi 		      dev_t rdev)
5869e6268dbSMiklos Szeredi {
5879e6268dbSMiklos Szeredi 	struct fuse_mknod_in inarg;
5889e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
5897078187aSMiklos Szeredi 	FUSE_ARGS(args);
5909e6268dbSMiklos Szeredi 
591e0a43ddcSMiklos Szeredi 	if (!fc->dont_mask)
592e0a43ddcSMiklos Szeredi 		mode &= ~current_umask();
593e0a43ddcSMiklos Szeredi 
5949e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
5959e6268dbSMiklos Szeredi 	inarg.mode = mode;
5969e6268dbSMiklos Szeredi 	inarg.rdev = new_encode_dev(rdev);
597e0a43ddcSMiklos Szeredi 	inarg.umask = current_umask();
5987078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_MKNOD;
5997078187aSMiklos Szeredi 	args.in.numargs = 2;
60021f62174SMiklos Szeredi 	args.in.args[0].size = sizeof(inarg);
6017078187aSMiklos Szeredi 	args.in.args[0].value = &inarg;
6027078187aSMiklos Szeredi 	args.in.args[1].size = entry->d_name.len + 1;
6037078187aSMiklos Szeredi 	args.in.args[1].value = entry->d_name.name;
6047078187aSMiklos Szeredi 	return create_new_entry(fc, &args, dir, entry, mode);
6059e6268dbSMiklos Szeredi }
6069e6268dbSMiklos Szeredi 
6074acdaf27SAl Viro static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode,
608ebfc3b49SAl Viro 		       bool excl)
6099e6268dbSMiklos Szeredi {
6109e6268dbSMiklos Szeredi 	return fuse_mknod(dir, entry, mode, 0);
6119e6268dbSMiklos Szeredi }
6129e6268dbSMiklos Szeredi 
61318bb1db3SAl Viro static int fuse_mkdir(struct inode *dir, struct dentry *entry, umode_t mode)
6149e6268dbSMiklos Szeredi {
6159e6268dbSMiklos Szeredi 	struct fuse_mkdir_in inarg;
6169e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
6177078187aSMiklos Szeredi 	FUSE_ARGS(args);
6189e6268dbSMiklos Szeredi 
619e0a43ddcSMiklos Szeredi 	if (!fc->dont_mask)
620e0a43ddcSMiklos Szeredi 		mode &= ~current_umask();
621e0a43ddcSMiklos Szeredi 
6229e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
6239e6268dbSMiklos Szeredi 	inarg.mode = mode;
624e0a43ddcSMiklos Szeredi 	inarg.umask = current_umask();
6257078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_MKDIR;
6267078187aSMiklos Szeredi 	args.in.numargs = 2;
6277078187aSMiklos Szeredi 	args.in.args[0].size = sizeof(inarg);
6287078187aSMiklos Szeredi 	args.in.args[0].value = &inarg;
6297078187aSMiklos Szeredi 	args.in.args[1].size = entry->d_name.len + 1;
6307078187aSMiklos Szeredi 	args.in.args[1].value = entry->d_name.name;
6317078187aSMiklos Szeredi 	return create_new_entry(fc, &args, dir, entry, S_IFDIR);
6329e6268dbSMiklos Szeredi }
6339e6268dbSMiklos Szeredi 
6349e6268dbSMiklos Szeredi static int fuse_symlink(struct inode *dir, struct dentry *entry,
6359e6268dbSMiklos Szeredi 			const char *link)
6369e6268dbSMiklos Szeredi {
6379e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
6389e6268dbSMiklos Szeredi 	unsigned len = strlen(link) + 1;
6397078187aSMiklos Szeredi 	FUSE_ARGS(args);
6409e6268dbSMiklos Szeredi 
6417078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_SYMLINK;
6427078187aSMiklos Szeredi 	args.in.numargs = 2;
6437078187aSMiklos Szeredi 	args.in.args[0].size = entry->d_name.len + 1;
6447078187aSMiklos Szeredi 	args.in.args[0].value = entry->d_name.name;
6457078187aSMiklos Szeredi 	args.in.args[1].size = len;
6467078187aSMiklos Szeredi 	args.in.args[1].value = link;
6477078187aSMiklos Szeredi 	return create_new_entry(fc, &args, dir, entry, S_IFLNK);
6489e6268dbSMiklos Szeredi }
6499e6268dbSMiklos Szeredi 
650703c7362SSeth Forshee void fuse_update_ctime(struct inode *inode)
65131f3267bSMaxim Patlasov {
65231f3267bSMaxim Patlasov 	if (!IS_NOCMTIME(inode)) {
653c2050a45SDeepa Dinamani 		inode->i_ctime = current_time(inode);
65431f3267bSMaxim Patlasov 		mark_inode_dirty_sync(inode);
65531f3267bSMaxim Patlasov 	}
65631f3267bSMaxim Patlasov }
65731f3267bSMaxim Patlasov 
6589e6268dbSMiklos Szeredi static int fuse_unlink(struct inode *dir, struct dentry *entry)
6599e6268dbSMiklos Szeredi {
6609e6268dbSMiklos Szeredi 	int err;
6619e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
6627078187aSMiklos Szeredi 	FUSE_ARGS(args);
6639e6268dbSMiklos Szeredi 
6647078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_UNLINK;
6657078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(dir);
6667078187aSMiklos Szeredi 	args.in.numargs = 1;
6677078187aSMiklos Szeredi 	args.in.args[0].size = entry->d_name.len + 1;
6687078187aSMiklos Szeredi 	args.in.args[0].value = entry->d_name.name;
6697078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
6709e6268dbSMiklos Szeredi 	if (!err) {
6712b0143b5SDavid Howells 		struct inode *inode = d_inode(entry);
672ac45d613SMiklos Szeredi 		struct fuse_inode *fi = get_fuse_inode(inode);
6739e6268dbSMiklos Szeredi 
674ac45d613SMiklos Szeredi 		spin_lock(&fc->lock);
675ac45d613SMiklos Szeredi 		fi->attr_version = ++fc->attr_version;
676dfca7cebSMiklos Szeredi 		/*
677dfca7cebSMiklos Szeredi 		 * If i_nlink == 0 then unlink doesn't make sense, yet this can
678dfca7cebSMiklos Szeredi 		 * happen if userspace filesystem is careless.  It would be
679dfca7cebSMiklos Szeredi 		 * difficult to enforce correct nlink usage so just ignore this
680dfca7cebSMiklos Szeredi 		 * condition here
681dfca7cebSMiklos Szeredi 		 */
682dfca7cebSMiklos Szeredi 		if (inode->i_nlink > 0)
683ac45d613SMiklos Szeredi 			drop_nlink(inode);
684ac45d613SMiklos Szeredi 		spin_unlock(&fc->lock);
6859e6268dbSMiklos Szeredi 		fuse_invalidate_attr(inode);
686261aaba7SMiklos Szeredi 		fuse_dir_changed(dir);
6878cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
68831f3267bSMaxim Patlasov 		fuse_update_ctime(inode);
6899e6268dbSMiklos Szeredi 	} else if (err == -EINTR)
6909e6268dbSMiklos Szeredi 		fuse_invalidate_entry(entry);
6919e6268dbSMiklos Szeredi 	return err;
6929e6268dbSMiklos Szeredi }
6939e6268dbSMiklos Szeredi 
6949e6268dbSMiklos Szeredi static int fuse_rmdir(struct inode *dir, struct dentry *entry)
6959e6268dbSMiklos Szeredi {
6969e6268dbSMiklos Szeredi 	int err;
6979e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
6987078187aSMiklos Szeredi 	FUSE_ARGS(args);
6999e6268dbSMiklos Szeredi 
7007078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_RMDIR;
7017078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(dir);
7027078187aSMiklos Szeredi 	args.in.numargs = 1;
7037078187aSMiklos Szeredi 	args.in.args[0].size = entry->d_name.len + 1;
7047078187aSMiklos Szeredi 	args.in.args[0].value = entry->d_name.name;
7057078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
7069e6268dbSMiklos Szeredi 	if (!err) {
7072b0143b5SDavid Howells 		clear_nlink(d_inode(entry));
708261aaba7SMiklos Szeredi 		fuse_dir_changed(dir);
7098cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
7109e6268dbSMiklos Szeredi 	} else if (err == -EINTR)
7119e6268dbSMiklos Szeredi 		fuse_invalidate_entry(entry);
7129e6268dbSMiklos Szeredi 	return err;
7139e6268dbSMiklos Szeredi }
7149e6268dbSMiklos Szeredi 
7151560c974SMiklos Szeredi static int fuse_rename_common(struct inode *olddir, struct dentry *oldent,
7161560c974SMiklos Szeredi 			      struct inode *newdir, struct dentry *newent,
7171560c974SMiklos Szeredi 			      unsigned int flags, int opcode, size_t argsize)
7189e6268dbSMiklos Szeredi {
7199e6268dbSMiklos Szeredi 	int err;
7201560c974SMiklos Szeredi 	struct fuse_rename2_in inarg;
7219e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(olddir);
7227078187aSMiklos Szeredi 	FUSE_ARGS(args);
7239e6268dbSMiklos Szeredi 
7241560c974SMiklos Szeredi 	memset(&inarg, 0, argsize);
7259e6268dbSMiklos Szeredi 	inarg.newdir = get_node_id(newdir);
7261560c974SMiklos Szeredi 	inarg.flags = flags;
7277078187aSMiklos Szeredi 	args.in.h.opcode = opcode;
7287078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(olddir);
7297078187aSMiklos Szeredi 	args.in.numargs = 3;
7307078187aSMiklos Szeredi 	args.in.args[0].size = argsize;
7317078187aSMiklos Szeredi 	args.in.args[0].value = &inarg;
7327078187aSMiklos Szeredi 	args.in.args[1].size = oldent->d_name.len + 1;
7337078187aSMiklos Szeredi 	args.in.args[1].value = oldent->d_name.name;
7347078187aSMiklos Szeredi 	args.in.args[2].size = newent->d_name.len + 1;
7357078187aSMiklos Szeredi 	args.in.args[2].value = newent->d_name.name;
7367078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
7379e6268dbSMiklos Szeredi 	if (!err) {
73808b63307SMiklos Szeredi 		/* ctime changes */
7392b0143b5SDavid Howells 		fuse_invalidate_attr(d_inode(oldent));
7402b0143b5SDavid Howells 		fuse_update_ctime(d_inode(oldent));
74108b63307SMiklos Szeredi 
7421560c974SMiklos Szeredi 		if (flags & RENAME_EXCHANGE) {
7432b0143b5SDavid Howells 			fuse_invalidate_attr(d_inode(newent));
7442b0143b5SDavid Howells 			fuse_update_ctime(d_inode(newent));
7451560c974SMiklos Szeredi 		}
7461560c974SMiklos Szeredi 
747261aaba7SMiklos Szeredi 		fuse_dir_changed(olddir);
7489e6268dbSMiklos Szeredi 		if (olddir != newdir)
749261aaba7SMiklos Szeredi 			fuse_dir_changed(newdir);
7508cbdf1e6SMiklos Szeredi 
7518cbdf1e6SMiklos Szeredi 		/* newent will end up negative */
7522b0143b5SDavid Howells 		if (!(flags & RENAME_EXCHANGE) && d_really_is_positive(newent)) {
7532b0143b5SDavid Howells 			fuse_invalidate_attr(d_inode(newent));
7548cbdf1e6SMiklos Szeredi 			fuse_invalidate_entry_cache(newent);
7552b0143b5SDavid Howells 			fuse_update_ctime(d_inode(newent));
7565219f346SMiklos Szeredi 		}
7579e6268dbSMiklos Szeredi 	} else if (err == -EINTR) {
7589e6268dbSMiklos Szeredi 		/* If request was interrupted, DEITY only knows if the
7599e6268dbSMiklos Szeredi 		   rename actually took place.  If the invalidation
7609e6268dbSMiklos Szeredi 		   fails (e.g. some process has CWD under the renamed
7619e6268dbSMiklos Szeredi 		   directory), then there can be inconsistency between
7629e6268dbSMiklos Szeredi 		   the dcache and the real filesystem.  Tough luck. */
7639e6268dbSMiklos Szeredi 		fuse_invalidate_entry(oldent);
7642b0143b5SDavid Howells 		if (d_really_is_positive(newent))
7659e6268dbSMiklos Szeredi 			fuse_invalidate_entry(newent);
7669e6268dbSMiklos Szeredi 	}
7679e6268dbSMiklos Szeredi 
7689e6268dbSMiklos Szeredi 	return err;
7699e6268dbSMiklos Szeredi }
7709e6268dbSMiklos Szeredi 
7711560c974SMiklos Szeredi static int fuse_rename2(struct inode *olddir, struct dentry *oldent,
7721560c974SMiklos Szeredi 			struct inode *newdir, struct dentry *newent,
7731560c974SMiklos Szeredi 			unsigned int flags)
7741560c974SMiklos Szeredi {
7751560c974SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(olddir);
7761560c974SMiklos Szeredi 	int err;
7771560c974SMiklos Szeredi 
7781560c974SMiklos Szeredi 	if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE))
7791560c974SMiklos Szeredi 		return -EINVAL;
7801560c974SMiklos Szeredi 
7814237ba43SMiklos Szeredi 	if (flags) {
7821560c974SMiklos Szeredi 		if (fc->no_rename2 || fc->minor < 23)
7831560c974SMiklos Szeredi 			return -EINVAL;
7841560c974SMiklos Szeredi 
7851560c974SMiklos Szeredi 		err = fuse_rename_common(olddir, oldent, newdir, newent, flags,
7864237ba43SMiklos Szeredi 					 FUSE_RENAME2,
7874237ba43SMiklos Szeredi 					 sizeof(struct fuse_rename2_in));
7881560c974SMiklos Szeredi 		if (err == -ENOSYS) {
7891560c974SMiklos Szeredi 			fc->no_rename2 = 1;
7901560c974SMiklos Szeredi 			err = -EINVAL;
7911560c974SMiklos Szeredi 		}
7924237ba43SMiklos Szeredi 	} else {
7934237ba43SMiklos Szeredi 		err = fuse_rename_common(olddir, oldent, newdir, newent, 0,
7944237ba43SMiklos Szeredi 					 FUSE_RENAME,
7954237ba43SMiklos Szeredi 					 sizeof(struct fuse_rename_in));
7964237ba43SMiklos Szeredi 	}
7971560c974SMiklos Szeredi 
7984237ba43SMiklos Szeredi 	return err;
7994237ba43SMiklos Szeredi }
8004237ba43SMiklos Szeredi 
8019e6268dbSMiklos Szeredi static int fuse_link(struct dentry *entry, struct inode *newdir,
8029e6268dbSMiklos Szeredi 		     struct dentry *newent)
8039e6268dbSMiklos Szeredi {
8049e6268dbSMiklos Szeredi 	int err;
8059e6268dbSMiklos Szeredi 	struct fuse_link_in inarg;
8062b0143b5SDavid Howells 	struct inode *inode = d_inode(entry);
8079e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
8087078187aSMiklos Szeredi 	FUSE_ARGS(args);
8099e6268dbSMiklos Szeredi 
8109e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
8119e6268dbSMiklos Szeredi 	inarg.oldnodeid = get_node_id(inode);
8127078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_LINK;
8137078187aSMiklos Szeredi 	args.in.numargs = 2;
8147078187aSMiklos Szeredi 	args.in.args[0].size = sizeof(inarg);
8157078187aSMiklos Szeredi 	args.in.args[0].value = &inarg;
8167078187aSMiklos Szeredi 	args.in.args[1].size = newent->d_name.len + 1;
8177078187aSMiklos Szeredi 	args.in.args[1].value = newent->d_name.name;
8187078187aSMiklos Szeredi 	err = create_new_entry(fc, &args, newdir, newent, inode->i_mode);
8199e6268dbSMiklos Szeredi 	/* Contrary to "normal" filesystems it can happen that link
8209e6268dbSMiklos Szeredi 	   makes two "logical" inodes point to the same "physical"
8219e6268dbSMiklos Szeredi 	   inode.  We invalidate the attributes of the old one, so it
8229e6268dbSMiklos Szeredi 	   will reflect changes in the backing inode (link count,
8239e6268dbSMiklos Szeredi 	   etc.)
8249e6268dbSMiklos Szeredi 	*/
825ac45d613SMiklos Szeredi 	if (!err) {
826ac45d613SMiklos Szeredi 		struct fuse_inode *fi = get_fuse_inode(inode);
827ac45d613SMiklos Szeredi 
828ac45d613SMiklos Szeredi 		spin_lock(&fc->lock);
829ac45d613SMiklos Szeredi 		fi->attr_version = ++fc->attr_version;
830ac45d613SMiklos Szeredi 		inc_nlink(inode);
831ac45d613SMiklos Szeredi 		spin_unlock(&fc->lock);
8329e6268dbSMiklos Szeredi 		fuse_invalidate_attr(inode);
83331f3267bSMaxim Patlasov 		fuse_update_ctime(inode);
834ac45d613SMiklos Szeredi 	} else if (err == -EINTR) {
835ac45d613SMiklos Szeredi 		fuse_invalidate_attr(inode);
836ac45d613SMiklos Szeredi 	}
8379e6268dbSMiklos Szeredi 	return err;
8389e6268dbSMiklos Szeredi }
8399e6268dbSMiklos Szeredi 
8401fb69e78SMiklos Szeredi static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
8411fb69e78SMiklos Szeredi 			  struct kstat *stat)
8421fb69e78SMiklos Szeredi {
843203627bbSMiklos Szeredi 	unsigned int blkbits;
8448373200bSPavel Emelyanov 	struct fuse_conn *fc = get_fuse_conn(inode);
8458373200bSPavel Emelyanov 
8468373200bSPavel Emelyanov 	/* see the comment in fuse_change_attributes() */
847b0aa7606SMaxim Patlasov 	if (fc->writeback_cache && S_ISREG(inode->i_mode)) {
8488373200bSPavel Emelyanov 		attr->size = i_size_read(inode);
849b0aa7606SMaxim Patlasov 		attr->mtime = inode->i_mtime.tv_sec;
850b0aa7606SMaxim Patlasov 		attr->mtimensec = inode->i_mtime.tv_nsec;
85131f3267bSMaxim Patlasov 		attr->ctime = inode->i_ctime.tv_sec;
85231f3267bSMaxim Patlasov 		attr->ctimensec = inode->i_ctime.tv_nsec;
853b0aa7606SMaxim Patlasov 	}
854203627bbSMiklos Szeredi 
8551fb69e78SMiklos Szeredi 	stat->dev = inode->i_sb->s_dev;
8561fb69e78SMiklos Szeredi 	stat->ino = attr->ino;
8571fb69e78SMiklos Szeredi 	stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
8581fb69e78SMiklos Szeredi 	stat->nlink = attr->nlink;
8598cb08329SEric W. Biederman 	stat->uid = make_kuid(fc->user_ns, attr->uid);
8608cb08329SEric W. Biederman 	stat->gid = make_kgid(fc->user_ns, attr->gid);
8611fb69e78SMiklos Szeredi 	stat->rdev = inode->i_rdev;
8621fb69e78SMiklos Szeredi 	stat->atime.tv_sec = attr->atime;
8631fb69e78SMiklos Szeredi 	stat->atime.tv_nsec = attr->atimensec;
8641fb69e78SMiklos Szeredi 	stat->mtime.tv_sec = attr->mtime;
8651fb69e78SMiklos Szeredi 	stat->mtime.tv_nsec = attr->mtimensec;
8661fb69e78SMiklos Szeredi 	stat->ctime.tv_sec = attr->ctime;
8671fb69e78SMiklos Szeredi 	stat->ctime.tv_nsec = attr->ctimensec;
8681fb69e78SMiklos Szeredi 	stat->size = attr->size;
8691fb69e78SMiklos Szeredi 	stat->blocks = attr->blocks;
870203627bbSMiklos Szeredi 
871203627bbSMiklos Szeredi 	if (attr->blksize != 0)
872203627bbSMiklos Szeredi 		blkbits = ilog2(attr->blksize);
873203627bbSMiklos Szeredi 	else
874203627bbSMiklos Szeredi 		blkbits = inode->i_sb->s_blocksize_bits;
875203627bbSMiklos Szeredi 
876203627bbSMiklos Szeredi 	stat->blksize = 1 << blkbits;
8771fb69e78SMiklos Szeredi }
8781fb69e78SMiklos Szeredi 
879c79e322fSMiklos Szeredi static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
880c79e322fSMiklos Szeredi 			   struct file *file)
881e5e5558eSMiklos Szeredi {
882e5e5558eSMiklos Szeredi 	int err;
883c79e322fSMiklos Szeredi 	struct fuse_getattr_in inarg;
884c79e322fSMiklos Szeredi 	struct fuse_attr_out outarg;
885e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
8867078187aSMiklos Szeredi 	FUSE_ARGS(args);
8871fb69e78SMiklos Szeredi 	u64 attr_version;
8881fb69e78SMiklos Szeredi 
8897dca9fd3SMiklos Szeredi 	attr_version = fuse_get_attr_version(fc);
8901fb69e78SMiklos Szeredi 
891c79e322fSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
8920e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
893c79e322fSMiklos Szeredi 	/* Directories have separate file-handle space */
894c79e322fSMiklos Szeredi 	if (file && S_ISREG(inode->i_mode)) {
895c79e322fSMiklos Szeredi 		struct fuse_file *ff = file->private_data;
896c79e322fSMiklos Szeredi 
897c79e322fSMiklos Szeredi 		inarg.getattr_flags |= FUSE_GETATTR_FH;
898c79e322fSMiklos Szeredi 		inarg.fh = ff->fh;
899c79e322fSMiklos Szeredi 	}
9007078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_GETATTR;
9017078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(inode);
9027078187aSMiklos Szeredi 	args.in.numargs = 1;
9037078187aSMiklos Szeredi 	args.in.args[0].size = sizeof(inarg);
9047078187aSMiklos Szeredi 	args.in.args[0].value = &inarg;
9057078187aSMiklos Szeredi 	args.out.numargs = 1;
9067078187aSMiklos Szeredi 	args.out.args[0].size = sizeof(outarg);
9077078187aSMiklos Szeredi 	args.out.args[0].value = &outarg;
9087078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
909e5e5558eSMiklos Szeredi 	if (!err) {
910c79e322fSMiklos Szeredi 		if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
911e5e5558eSMiklos Szeredi 			make_bad_inode(inode);
912e5e5558eSMiklos Szeredi 			err = -EIO;
913e5e5558eSMiklos Szeredi 		} else {
914c79e322fSMiklos Szeredi 			fuse_change_attributes(inode, &outarg.attr,
915c79e322fSMiklos Szeredi 					       attr_timeout(&outarg),
9161fb69e78SMiklos Szeredi 					       attr_version);
9171fb69e78SMiklos Szeredi 			if (stat)
918c79e322fSMiklos Szeredi 				fuse_fillattr(inode, &outarg.attr, stat);
919e5e5558eSMiklos Szeredi 		}
920e5e5558eSMiklos Szeredi 	}
921e5e5558eSMiklos Szeredi 	return err;
922e5e5558eSMiklos Szeredi }
923e5e5558eSMiklos Szeredi 
9245b97eeacSMiklos Szeredi static int fuse_update_get_attr(struct inode *inode, struct file *file,
9252f1e8196SMiklos Szeredi 				struct kstat *stat, u32 request_mask,
9262f1e8196SMiklos Szeredi 				unsigned int flags)
927bcb4be80SMiklos Szeredi {
928bcb4be80SMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
9295b97eeacSMiklos Szeredi 	int err = 0;
930bf5c1898SMiklos Szeredi 	bool sync;
931bcb4be80SMiklos Szeredi 
932bf5c1898SMiklos Szeredi 	if (flags & AT_STATX_FORCE_SYNC)
933bf5c1898SMiklos Szeredi 		sync = true;
934bf5c1898SMiklos Szeredi 	else if (flags & AT_STATX_DONT_SYNC)
935bf5c1898SMiklos Szeredi 		sync = false;
9362f1e8196SMiklos Szeredi 	else if (request_mask & READ_ONCE(fi->inval_mask))
9372f1e8196SMiklos Szeredi 		sync = true;
938bf5c1898SMiklos Szeredi 	else
939bf5c1898SMiklos Szeredi 		sync = time_before64(fi->i_time, get_jiffies_64());
940bf5c1898SMiklos Szeredi 
941bf5c1898SMiklos Szeredi 	if (sync) {
94260bcc88aSSeth Forshee 		forget_all_cached_acls(inode);
943bcb4be80SMiklos Szeredi 		err = fuse_do_getattr(inode, stat, file);
9445b97eeacSMiklos Szeredi 	} else if (stat) {
945bcb4be80SMiklos Szeredi 		generic_fillattr(inode, stat);
946bcb4be80SMiklos Szeredi 		stat->mode = fi->orig_i_mode;
94745c72cd7SPavel Shilovsky 		stat->ino = fi->orig_ino;
948bcb4be80SMiklos Szeredi 	}
949bcb4be80SMiklos Szeredi 
950bcb4be80SMiklos Szeredi 	return err;
951bcb4be80SMiklos Szeredi }
952bcb4be80SMiklos Szeredi 
9535b97eeacSMiklos Szeredi int fuse_update_attributes(struct inode *inode, struct file *file)
9545b97eeacSMiklos Szeredi {
955*802dc049SMiklos Szeredi 	/* Do *not* need to get atime for internal purposes */
956*802dc049SMiklos Szeredi 	return fuse_update_get_attr(inode, file, NULL,
957*802dc049SMiklos Szeredi 				    STATX_BASIC_STATS & ~STATX_ATIME, 0);
9585b97eeacSMiklos Szeredi }
9595b97eeacSMiklos Szeredi 
9603b463ae0SJohn Muir int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid,
961451d0f59SJohn Muir 			     u64 child_nodeid, struct qstr *name)
9623b463ae0SJohn Muir {
9633b463ae0SJohn Muir 	int err = -ENOTDIR;
9643b463ae0SJohn Muir 	struct inode *parent;
9653b463ae0SJohn Muir 	struct dentry *dir;
9663b463ae0SJohn Muir 	struct dentry *entry;
9673b463ae0SJohn Muir 
9683b463ae0SJohn Muir 	parent = ilookup5(sb, parent_nodeid, fuse_inode_eq, &parent_nodeid);
9693b463ae0SJohn Muir 	if (!parent)
9703b463ae0SJohn Muir 		return -ENOENT;
9713b463ae0SJohn Muir 
9725955102cSAl Viro 	inode_lock(parent);
9733b463ae0SJohn Muir 	if (!S_ISDIR(parent->i_mode))
9743b463ae0SJohn Muir 		goto unlock;
9753b463ae0SJohn Muir 
9763b463ae0SJohn Muir 	err = -ENOENT;
9773b463ae0SJohn Muir 	dir = d_find_alias(parent);
9783b463ae0SJohn Muir 	if (!dir)
9793b463ae0SJohn Muir 		goto unlock;
9803b463ae0SJohn Muir 
9818387ff25SLinus Torvalds 	name->hash = full_name_hash(dir, name->name, name->len);
9823b463ae0SJohn Muir 	entry = d_lookup(dir, name);
9833b463ae0SJohn Muir 	dput(dir);
9843b463ae0SJohn Muir 	if (!entry)
9853b463ae0SJohn Muir 		goto unlock;
9863b463ae0SJohn Muir 
987261aaba7SMiklos Szeredi 	fuse_dir_changed(parent);
9883b463ae0SJohn Muir 	fuse_invalidate_entry(entry);
989451d0f59SJohn Muir 
9902b0143b5SDavid Howells 	if (child_nodeid != 0 && d_really_is_positive(entry)) {
9915955102cSAl Viro 		inode_lock(d_inode(entry));
9922b0143b5SDavid Howells 		if (get_node_id(d_inode(entry)) != child_nodeid) {
993451d0f59SJohn Muir 			err = -ENOENT;
994451d0f59SJohn Muir 			goto badentry;
995451d0f59SJohn Muir 		}
996451d0f59SJohn Muir 		if (d_mountpoint(entry)) {
997451d0f59SJohn Muir 			err = -EBUSY;
998451d0f59SJohn Muir 			goto badentry;
999451d0f59SJohn Muir 		}
1000e36cb0b8SDavid Howells 		if (d_is_dir(entry)) {
1001451d0f59SJohn Muir 			shrink_dcache_parent(entry);
1002451d0f59SJohn Muir 			if (!simple_empty(entry)) {
1003451d0f59SJohn Muir 				err = -ENOTEMPTY;
1004451d0f59SJohn Muir 				goto badentry;
1005451d0f59SJohn Muir 			}
10062b0143b5SDavid Howells 			d_inode(entry)->i_flags |= S_DEAD;
1007451d0f59SJohn Muir 		}
1008451d0f59SJohn Muir 		dont_mount(entry);
10092b0143b5SDavid Howells 		clear_nlink(d_inode(entry));
10103b463ae0SJohn Muir 		err = 0;
1011451d0f59SJohn Muir  badentry:
10125955102cSAl Viro 		inode_unlock(d_inode(entry));
1013451d0f59SJohn Muir 		if (!err)
1014451d0f59SJohn Muir 			d_delete(entry);
1015451d0f59SJohn Muir 	} else {
1016451d0f59SJohn Muir 		err = 0;
1017451d0f59SJohn Muir 	}
1018451d0f59SJohn Muir 	dput(entry);
10193b463ae0SJohn Muir 
10203b463ae0SJohn Muir  unlock:
10215955102cSAl Viro 	inode_unlock(parent);
10223b463ae0SJohn Muir 	iput(parent);
10233b463ae0SJohn Muir 	return err;
10243b463ae0SJohn Muir }
10253b463ae0SJohn Muir 
102687729a55SMiklos Szeredi /*
102787729a55SMiklos Szeredi  * Calling into a user-controlled filesystem gives the filesystem
1028c2132c1bSAnatol Pomozov  * daemon ptrace-like capabilities over the current process.  This
102987729a55SMiklos Szeredi  * means, that the filesystem daemon is able to record the exact
103087729a55SMiklos Szeredi  * filesystem operations performed, and can also control the behavior
103187729a55SMiklos Szeredi  * of the requester process in otherwise impossible ways.  For example
103287729a55SMiklos Szeredi  * it can delay the operation for arbitrary length of time allowing
103387729a55SMiklos Szeredi  * DoS against the requester.
103487729a55SMiklos Szeredi  *
103587729a55SMiklos Szeredi  * For this reason only those processes can call into the filesystem,
103687729a55SMiklos Szeredi  * for which the owner of the mount has ptrace privilege.  This
103787729a55SMiklos Szeredi  * excludes processes started by other users, suid or sgid processes.
103887729a55SMiklos Szeredi  */
1039c2132c1bSAnatol Pomozov int fuse_allow_current_process(struct fuse_conn *fc)
104087729a55SMiklos Szeredi {
1041c69e8d9cSDavid Howells 	const struct cred *cred;
1042c69e8d9cSDavid Howells 
104329433a29SMiklos Szeredi 	if (fc->allow_other)
104473f03c2bSSeth Forshee 		return current_in_userns(fc->user_ns);
104587729a55SMiklos Szeredi 
1046c2132c1bSAnatol Pomozov 	cred = current_cred();
1047499dcf20SEric W. Biederman 	if (uid_eq(cred->euid, fc->user_id) &&
1048499dcf20SEric W. Biederman 	    uid_eq(cred->suid, fc->user_id) &&
1049499dcf20SEric W. Biederman 	    uid_eq(cred->uid,  fc->user_id) &&
1050499dcf20SEric W. Biederman 	    gid_eq(cred->egid, fc->group_id) &&
1051499dcf20SEric W. Biederman 	    gid_eq(cred->sgid, fc->group_id) &&
1052499dcf20SEric W. Biederman 	    gid_eq(cred->gid,  fc->group_id))
1053c2132c1bSAnatol Pomozov 		return 1;
105487729a55SMiklos Szeredi 
1055c2132c1bSAnatol Pomozov 	return 0;
105687729a55SMiklos Szeredi }
105787729a55SMiklos Szeredi 
105831d40d74SMiklos Szeredi static int fuse_access(struct inode *inode, int mask)
105931d40d74SMiklos Szeredi {
106031d40d74SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
10617078187aSMiklos Szeredi 	FUSE_ARGS(args);
106231d40d74SMiklos Szeredi 	struct fuse_access_in inarg;
106331d40d74SMiklos Szeredi 	int err;
106431d40d74SMiklos Szeredi 
1065698fa1d1SMiklos Szeredi 	BUG_ON(mask & MAY_NOT_BLOCK);
1066698fa1d1SMiklos Szeredi 
106731d40d74SMiklos Szeredi 	if (fc->no_access)
106831d40d74SMiklos Szeredi 		return 0;
106931d40d74SMiklos Szeredi 
107031d40d74SMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
1071e6305c43SAl Viro 	inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC);
10727078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_ACCESS;
10737078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(inode);
10747078187aSMiklos Szeredi 	args.in.numargs = 1;
10757078187aSMiklos Szeredi 	args.in.args[0].size = sizeof(inarg);
10767078187aSMiklos Szeredi 	args.in.args[0].value = &inarg;
10777078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
107831d40d74SMiklos Szeredi 	if (err == -ENOSYS) {
107931d40d74SMiklos Szeredi 		fc->no_access = 1;
108031d40d74SMiklos Szeredi 		err = 0;
108131d40d74SMiklos Szeredi 	}
108231d40d74SMiklos Szeredi 	return err;
108331d40d74SMiklos Szeredi }
108431d40d74SMiklos Szeredi 
108510556cb2SAl Viro static int fuse_perm_getattr(struct inode *inode, int mask)
108619690ddbSMiklos Szeredi {
108710556cb2SAl Viro 	if (mask & MAY_NOT_BLOCK)
108819690ddbSMiklos Szeredi 		return -ECHILD;
108919690ddbSMiklos Szeredi 
109060bcc88aSSeth Forshee 	forget_all_cached_acls(inode);
109119690ddbSMiklos Szeredi 	return fuse_do_getattr(inode, NULL, NULL);
109219690ddbSMiklos Szeredi }
109319690ddbSMiklos Szeredi 
10946f9f1180SMiklos Szeredi /*
10956f9f1180SMiklos Szeredi  * Check permission.  The two basic access models of FUSE are:
10966f9f1180SMiklos Szeredi  *
10976f9f1180SMiklos Szeredi  * 1) Local access checking ('default_permissions' mount option) based
10986f9f1180SMiklos Szeredi  * on file mode.  This is the plain old disk filesystem permission
10996f9f1180SMiklos Szeredi  * modell.
11006f9f1180SMiklos Szeredi  *
11016f9f1180SMiklos Szeredi  * 2) "Remote" access checking, where server is responsible for
11026f9f1180SMiklos Szeredi  * checking permission in each inode operation.  An exception to this
11036f9f1180SMiklos Szeredi  * is if ->permission() was invoked from sys_access() in which case an
11046f9f1180SMiklos Szeredi  * access request is sent.  Execute permission is still checked
11056f9f1180SMiklos Szeredi  * locally based on file mode.
11066f9f1180SMiklos Szeredi  */
110710556cb2SAl Viro static int fuse_permission(struct inode *inode, int mask)
1108e5e5558eSMiklos Szeredi {
1109e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1110244f6385SMiklos Szeredi 	bool refreshed = false;
1111244f6385SMiklos Szeredi 	int err = 0;
1112e5e5558eSMiklos Szeredi 
1113c2132c1bSAnatol Pomozov 	if (!fuse_allow_current_process(fc))
1114e5e5558eSMiklos Szeredi 		return -EACCES;
1115244f6385SMiklos Szeredi 
1116244f6385SMiklos Szeredi 	/*
1117e8e96157SMiklos Szeredi 	 * If attributes are needed, refresh them before proceeding
1118244f6385SMiklos Szeredi 	 */
111929433a29SMiklos Szeredi 	if (fc->default_permissions ||
1120e8e96157SMiklos Szeredi 	    ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
112119690ddbSMiklos Szeredi 		struct fuse_inode *fi = get_fuse_inode(inode);
112219690ddbSMiklos Szeredi 
1123126b9d43SMiklos Szeredi 		if (time_before64(fi->i_time, get_jiffies_64())) {
112419690ddbSMiklos Szeredi 			refreshed = true;
112519690ddbSMiklos Szeredi 
112610556cb2SAl Viro 			err = fuse_perm_getattr(inode, mask);
1127244f6385SMiklos Szeredi 			if (err)
1128244f6385SMiklos Szeredi 				return err;
11291fb69e78SMiklos Szeredi 		}
113019690ddbSMiklos Szeredi 	}
1131244f6385SMiklos Szeredi 
113229433a29SMiklos Szeredi 	if (fc->default_permissions) {
11332830ba7fSAl Viro 		err = generic_permission(inode, mask);
11341e9a4ed9SMiklos Szeredi 
11351e9a4ed9SMiklos Szeredi 		/* If permission is denied, try to refresh file
11361e9a4ed9SMiklos Szeredi 		   attributes.  This is also needed, because the root
11371e9a4ed9SMiklos Szeredi 		   node will at first have no permissions */
1138244f6385SMiklos Szeredi 		if (err == -EACCES && !refreshed) {
113910556cb2SAl Viro 			err = fuse_perm_getattr(inode, mask);
11401e9a4ed9SMiklos Szeredi 			if (!err)
11412830ba7fSAl Viro 				err = generic_permission(inode, mask);
11421e9a4ed9SMiklos Szeredi 		}
11431e9a4ed9SMiklos Szeredi 
11446f9f1180SMiklos Szeredi 		/* Note: the opposite of the above test does not
11456f9f1180SMiklos Szeredi 		   exist.  So if permissions are revoked this won't be
11466f9f1180SMiklos Szeredi 		   noticed immediately, only after the attribute
11476f9f1180SMiklos Szeredi 		   timeout has expired */
11489cfcac81SEric Paris 	} else if (mask & (MAY_ACCESS | MAY_CHDIR)) {
1149e8e96157SMiklos Szeredi 		err = fuse_access(inode, mask);
1150e8e96157SMiklos Szeredi 	} else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
1151e8e96157SMiklos Szeredi 		if (!(inode->i_mode & S_IXUGO)) {
1152e8e96157SMiklos Szeredi 			if (refreshed)
1153e5e5558eSMiklos Szeredi 				return -EACCES;
115431d40d74SMiklos Szeredi 
115510556cb2SAl Viro 			err = fuse_perm_getattr(inode, mask);
1156e8e96157SMiklos Szeredi 			if (!err && !(inode->i_mode & S_IXUGO))
1157e8e96157SMiklos Szeredi 				return -EACCES;
1158e8e96157SMiklos Szeredi 		}
1159e5e5558eSMiklos Szeredi 	}
1160244f6385SMiklos Szeredi 	return err;
1161e5e5558eSMiklos Szeredi }
1162e5e5558eSMiklos Szeredi 
11636b255391SAl Viro static const char *fuse_get_link(struct dentry *dentry,
1164fceef393SAl Viro 				 struct inode *inode,
1165fceef393SAl Viro 				 struct delayed_call *done)
1166e5e5558eSMiklos Szeredi {
1167e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
11687078187aSMiklos Szeredi 	FUSE_ARGS(args);
1169e5e5558eSMiklos Szeredi 	char *link;
11707078187aSMiklos Szeredi 	ssize_t ret;
1171e5e5558eSMiklos Szeredi 
11726b255391SAl Viro 	if (!dentry)
11736b255391SAl Viro 		return ERR_PTR(-ECHILD);
11746b255391SAl Viro 
1175cd3417c8SAl Viro 	link = kmalloc(PAGE_SIZE, GFP_KERNEL);
11767078187aSMiklos Szeredi 	if (!link)
11777078187aSMiklos Szeredi 		return ERR_PTR(-ENOMEM);
11787078187aSMiklos Szeredi 
11797078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_READLINK;
11807078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(inode);
11817078187aSMiklos Szeredi 	args.out.argvar = 1;
11827078187aSMiklos Szeredi 	args.out.numargs = 1;
11837078187aSMiklos Szeredi 	args.out.args[0].size = PAGE_SIZE - 1;
11847078187aSMiklos Szeredi 	args.out.args[0].value = link;
11857078187aSMiklos Szeredi 	ret = fuse_simple_request(fc, &args);
11867078187aSMiklos Szeredi 	if (ret < 0) {
1187cd3417c8SAl Viro 		kfree(link);
11887078187aSMiklos Szeredi 		link = ERR_PTR(ret);
11897078187aSMiklos Szeredi 	} else {
11907078187aSMiklos Szeredi 		link[ret] = '\0';
1191fceef393SAl Viro 		set_delayed_call(done, kfree_link, link);
11927078187aSMiklos Szeredi 	}
1193451418fcSAndrew Gallagher 	fuse_invalidate_atime(inode);
1194e5e5558eSMiklos Szeredi 	return link;
1195e5e5558eSMiklos Szeredi }
1196e5e5558eSMiklos Szeredi 
1197e5e5558eSMiklos Szeredi static int fuse_dir_open(struct inode *inode, struct file *file)
1198e5e5558eSMiklos Szeredi {
119991fe96b4SMiklos Szeredi 	return fuse_open_common(inode, file, true);
1200e5e5558eSMiklos Szeredi }
1201e5e5558eSMiklos Szeredi 
1202e5e5558eSMiklos Szeredi static int fuse_dir_release(struct inode *inode, struct file *file)
1203e5e5558eSMiklos Szeredi {
12048b0797a4SMiklos Szeredi 	fuse_release_common(file, FUSE_RELEASEDIR);
12058b0797a4SMiklos Szeredi 
12068b0797a4SMiklos Szeredi 	return 0;
1207e5e5558eSMiklos Szeredi }
1208e5e5558eSMiklos Szeredi 
120902c24a82SJosef Bacik static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end,
121002c24a82SJosef Bacik 			  int datasync)
121182547981SMiklos Szeredi {
121202c24a82SJosef Bacik 	return fuse_fsync_common(file, start, end, datasync, 1);
121382547981SMiklos Szeredi }
121482547981SMiklos Szeredi 
1215b18da0c5SMiklos Szeredi static long fuse_dir_ioctl(struct file *file, unsigned int cmd,
1216b18da0c5SMiklos Szeredi 			    unsigned long arg)
1217b18da0c5SMiklos Szeredi {
1218b18da0c5SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1219b18da0c5SMiklos Szeredi 
1220b18da0c5SMiklos Szeredi 	/* FUSE_IOCTL_DIR only supported for API version >= 7.18 */
1221b18da0c5SMiklos Szeredi 	if (fc->minor < 18)
1222b18da0c5SMiklos Szeredi 		return -ENOTTY;
1223b18da0c5SMiklos Szeredi 
1224b18da0c5SMiklos Szeredi 	return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR);
1225b18da0c5SMiklos Szeredi }
1226b18da0c5SMiklos Szeredi 
1227b18da0c5SMiklos Szeredi static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd,
1228b18da0c5SMiklos Szeredi 				   unsigned long arg)
1229b18da0c5SMiklos Szeredi {
1230b18da0c5SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1231b18da0c5SMiklos Szeredi 
1232b18da0c5SMiklos Szeredi 	if (fc->minor < 18)
1233b18da0c5SMiklos Szeredi 		return -ENOTTY;
1234b18da0c5SMiklos Szeredi 
1235b18da0c5SMiklos Szeredi 	return fuse_ioctl_common(file, cmd, arg,
1236b18da0c5SMiklos Szeredi 				 FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR);
1237b18da0c5SMiklos Szeredi }
1238b18da0c5SMiklos Szeredi 
1239b0aa7606SMaxim Patlasov static bool update_mtime(unsigned ivalid, bool trust_local_mtime)
124017637cbaSMiklos Szeredi {
124117637cbaSMiklos Szeredi 	/* Always update if mtime is explicitly set  */
124217637cbaSMiklos Szeredi 	if (ivalid & ATTR_MTIME_SET)
124317637cbaSMiklos Szeredi 		return true;
124417637cbaSMiklos Szeredi 
1245b0aa7606SMaxim Patlasov 	/* Or if kernel i_mtime is the official one */
1246b0aa7606SMaxim Patlasov 	if (trust_local_mtime)
1247b0aa7606SMaxim Patlasov 		return true;
1248b0aa7606SMaxim Patlasov 
124917637cbaSMiklos Szeredi 	/* If it's an open(O_TRUNC) or an ftruncate(), don't update */
125017637cbaSMiklos Szeredi 	if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
125117637cbaSMiklos Szeredi 		return false;
125217637cbaSMiklos Szeredi 
125317637cbaSMiklos Szeredi 	/* In all other cases update */
125417637cbaSMiklos Szeredi 	return true;
125517637cbaSMiklos Szeredi }
125617637cbaSMiklos Szeredi 
12578cb08329SEric W. Biederman static void iattr_to_fattr(struct fuse_conn *fc, struct iattr *iattr,
12588cb08329SEric W. Biederman 			   struct fuse_setattr_in *arg, bool trust_local_cmtime)
12599e6268dbSMiklos Szeredi {
12609e6268dbSMiklos Szeredi 	unsigned ivalid = iattr->ia_valid;
12619e6268dbSMiklos Szeredi 
12629e6268dbSMiklos Szeredi 	if (ivalid & ATTR_MODE)
1263befc649cSMiklos Szeredi 		arg->valid |= FATTR_MODE,   arg->mode = iattr->ia_mode;
12649e6268dbSMiklos Szeredi 	if (ivalid & ATTR_UID)
12658cb08329SEric W. Biederman 		arg->valid |= FATTR_UID,    arg->uid = from_kuid(fc->user_ns, iattr->ia_uid);
12669e6268dbSMiklos Szeredi 	if (ivalid & ATTR_GID)
12678cb08329SEric W. Biederman 		arg->valid |= FATTR_GID,    arg->gid = from_kgid(fc->user_ns, iattr->ia_gid);
12689e6268dbSMiklos Szeredi 	if (ivalid & ATTR_SIZE)
1269befc649cSMiklos Szeredi 		arg->valid |= FATTR_SIZE,   arg->size = iattr->ia_size;
127017637cbaSMiklos Szeredi 	if (ivalid & ATTR_ATIME) {
127117637cbaSMiklos Szeredi 		arg->valid |= FATTR_ATIME;
1272befc649cSMiklos Szeredi 		arg->atime = iattr->ia_atime.tv_sec;
127317637cbaSMiklos Szeredi 		arg->atimensec = iattr->ia_atime.tv_nsec;
127417637cbaSMiklos Szeredi 		if (!(ivalid & ATTR_ATIME_SET))
127517637cbaSMiklos Szeredi 			arg->valid |= FATTR_ATIME_NOW;
127617637cbaSMiklos Szeredi 	}
12773ad22c62SMaxim Patlasov 	if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, trust_local_cmtime)) {
127817637cbaSMiklos Szeredi 		arg->valid |= FATTR_MTIME;
1279befc649cSMiklos Szeredi 		arg->mtime = iattr->ia_mtime.tv_sec;
128017637cbaSMiklos Szeredi 		arg->mtimensec = iattr->ia_mtime.tv_nsec;
12813ad22c62SMaxim Patlasov 		if (!(ivalid & ATTR_MTIME_SET) && !trust_local_cmtime)
128217637cbaSMiklos Szeredi 			arg->valid |= FATTR_MTIME_NOW;
12839e6268dbSMiklos Szeredi 	}
12843ad22c62SMaxim Patlasov 	if ((ivalid & ATTR_CTIME) && trust_local_cmtime) {
12853ad22c62SMaxim Patlasov 		arg->valid |= FATTR_CTIME;
12863ad22c62SMaxim Patlasov 		arg->ctime = iattr->ia_ctime.tv_sec;
12873ad22c62SMaxim Patlasov 		arg->ctimensec = iattr->ia_ctime.tv_nsec;
12883ad22c62SMaxim Patlasov 	}
12899e6268dbSMiklos Szeredi }
12909e6268dbSMiklos Szeredi 
12916f9f1180SMiklos Szeredi /*
12923be5a52bSMiklos Szeredi  * Prevent concurrent writepages on inode
12933be5a52bSMiklos Szeredi  *
12943be5a52bSMiklos Szeredi  * This is done by adding a negative bias to the inode write counter
12953be5a52bSMiklos Szeredi  * and waiting for all pending writes to finish.
12963be5a52bSMiklos Szeredi  */
12973be5a52bSMiklos Szeredi void fuse_set_nowrite(struct inode *inode)
12983be5a52bSMiklos Szeredi {
12993be5a52bSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
13003be5a52bSMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
13013be5a52bSMiklos Szeredi 
13025955102cSAl Viro 	BUG_ON(!inode_is_locked(inode));
13033be5a52bSMiklos Szeredi 
13043be5a52bSMiklos Szeredi 	spin_lock(&fc->lock);
13053be5a52bSMiklos Szeredi 	BUG_ON(fi->writectr < 0);
13063be5a52bSMiklos Szeredi 	fi->writectr += FUSE_NOWRITE;
13073be5a52bSMiklos Szeredi 	spin_unlock(&fc->lock);
13083be5a52bSMiklos Szeredi 	wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE);
13093be5a52bSMiklos Szeredi }
13103be5a52bSMiklos Szeredi 
13113be5a52bSMiklos Szeredi /*
13123be5a52bSMiklos Szeredi  * Allow writepages on inode
13133be5a52bSMiklos Szeredi  *
13143be5a52bSMiklos Szeredi  * Remove the bias from the writecounter and send any queued
13153be5a52bSMiklos Szeredi  * writepages.
13163be5a52bSMiklos Szeredi  */
13173be5a52bSMiklos Szeredi static void __fuse_release_nowrite(struct inode *inode)
13183be5a52bSMiklos Szeredi {
13193be5a52bSMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
13203be5a52bSMiklos Szeredi 
13213be5a52bSMiklos Szeredi 	BUG_ON(fi->writectr != FUSE_NOWRITE);
13223be5a52bSMiklos Szeredi 	fi->writectr = 0;
13233be5a52bSMiklos Szeredi 	fuse_flush_writepages(inode);
13243be5a52bSMiklos Szeredi }
13253be5a52bSMiklos Szeredi 
13263be5a52bSMiklos Szeredi void fuse_release_nowrite(struct inode *inode)
13273be5a52bSMiklos Szeredi {
13283be5a52bSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
13293be5a52bSMiklos Szeredi 
13303be5a52bSMiklos Szeredi 	spin_lock(&fc->lock);
13313be5a52bSMiklos Szeredi 	__fuse_release_nowrite(inode);
13323be5a52bSMiklos Szeredi 	spin_unlock(&fc->lock);
13333be5a52bSMiklos Szeredi }
13343be5a52bSMiklos Szeredi 
13357078187aSMiklos Szeredi static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_args *args,
1336b0aa7606SMaxim Patlasov 			      struct inode *inode,
1337b0aa7606SMaxim Patlasov 			      struct fuse_setattr_in *inarg_p,
1338b0aa7606SMaxim Patlasov 			      struct fuse_attr_out *outarg_p)
1339b0aa7606SMaxim Patlasov {
13407078187aSMiklos Szeredi 	args->in.h.opcode = FUSE_SETATTR;
13417078187aSMiklos Szeredi 	args->in.h.nodeid = get_node_id(inode);
13427078187aSMiklos Szeredi 	args->in.numargs = 1;
13437078187aSMiklos Szeredi 	args->in.args[0].size = sizeof(*inarg_p);
13447078187aSMiklos Szeredi 	args->in.args[0].value = inarg_p;
13457078187aSMiklos Szeredi 	args->out.numargs = 1;
13467078187aSMiklos Szeredi 	args->out.args[0].size = sizeof(*outarg_p);
13477078187aSMiklos Szeredi 	args->out.args[0].value = outarg_p;
1348b0aa7606SMaxim Patlasov }
1349b0aa7606SMaxim Patlasov 
1350b0aa7606SMaxim Patlasov /*
1351b0aa7606SMaxim Patlasov  * Flush inode->i_mtime to the server
1352b0aa7606SMaxim Patlasov  */
1353ab9e13f7SMaxim Patlasov int fuse_flush_times(struct inode *inode, struct fuse_file *ff)
1354b0aa7606SMaxim Patlasov {
1355b0aa7606SMaxim Patlasov 	struct fuse_conn *fc = get_fuse_conn(inode);
13567078187aSMiklos Szeredi 	FUSE_ARGS(args);
1357b0aa7606SMaxim Patlasov 	struct fuse_setattr_in inarg;
1358b0aa7606SMaxim Patlasov 	struct fuse_attr_out outarg;
1359b0aa7606SMaxim Patlasov 
1360b0aa7606SMaxim Patlasov 	memset(&inarg, 0, sizeof(inarg));
1361b0aa7606SMaxim Patlasov 	memset(&outarg, 0, sizeof(outarg));
1362b0aa7606SMaxim Patlasov 
1363ab9e13f7SMaxim Patlasov 	inarg.valid = FATTR_MTIME;
1364b0aa7606SMaxim Patlasov 	inarg.mtime = inode->i_mtime.tv_sec;
1365b0aa7606SMaxim Patlasov 	inarg.mtimensec = inode->i_mtime.tv_nsec;
1366ab9e13f7SMaxim Patlasov 	if (fc->minor >= 23) {
1367ab9e13f7SMaxim Patlasov 		inarg.valid |= FATTR_CTIME;
1368ab9e13f7SMaxim Patlasov 		inarg.ctime = inode->i_ctime.tv_sec;
1369ab9e13f7SMaxim Patlasov 		inarg.ctimensec = inode->i_ctime.tv_nsec;
1370ab9e13f7SMaxim Patlasov 	}
13711e18bda8SMiklos Szeredi 	if (ff) {
13721e18bda8SMiklos Szeredi 		inarg.valid |= FATTR_FH;
13731e18bda8SMiklos Szeredi 		inarg.fh = ff->fh;
13741e18bda8SMiklos Szeredi 	}
13757078187aSMiklos Szeredi 	fuse_setattr_fill(fc, &args, inode, &inarg, &outarg);
1376b0aa7606SMaxim Patlasov 
13777078187aSMiklos Szeredi 	return fuse_simple_request(fc, &args);
1378b0aa7606SMaxim Patlasov }
1379b0aa7606SMaxim Patlasov 
13803be5a52bSMiklos Szeredi /*
13816f9f1180SMiklos Szeredi  * Set attributes, and at the same time refresh them.
13826f9f1180SMiklos Szeredi  *
13836f9f1180SMiklos Szeredi  * Truncation is slightly complicated, because the 'truncate' request
13846f9f1180SMiklos Szeredi  * may fail, in which case we don't want to touch the mapping.
13859ffbb916SMiklos Szeredi  * vmtruncate() doesn't allow for this case, so do the rlimit checking
13869ffbb916SMiklos Szeredi  * and the actual truncation by hand.
13876f9f1180SMiklos Szeredi  */
138862490330SJan Kara int fuse_do_setattr(struct dentry *dentry, struct iattr *attr,
138949d4914fSMiklos Szeredi 		    struct file *file)
13909e6268dbSMiklos Szeredi {
139162490330SJan Kara 	struct inode *inode = d_inode(dentry);
13929e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
139306a7c3c2SMaxim Patlasov 	struct fuse_inode *fi = get_fuse_inode(inode);
13947078187aSMiklos Szeredi 	FUSE_ARGS(args);
13959e6268dbSMiklos Szeredi 	struct fuse_setattr_in inarg;
13969e6268dbSMiklos Szeredi 	struct fuse_attr_out outarg;
13973be5a52bSMiklos Szeredi 	bool is_truncate = false;
13988373200bSPavel Emelyanov 	bool is_wb = fc->writeback_cache;
13993be5a52bSMiklos Szeredi 	loff_t oldsize;
14009e6268dbSMiklos Szeredi 	int err;
14013ad22c62SMaxim Patlasov 	bool trust_local_cmtime = is_wb && S_ISREG(inode->i_mode);
14029e6268dbSMiklos Szeredi 
140329433a29SMiklos Szeredi 	if (!fc->default_permissions)
1404db78b877SChristoph Hellwig 		attr->ia_valid |= ATTR_FORCE;
1405db78b877SChristoph Hellwig 
140631051c85SJan Kara 	err = setattr_prepare(dentry, attr);
14071e9a4ed9SMiklos Szeredi 	if (err)
14081e9a4ed9SMiklos Szeredi 		return err;
14091e9a4ed9SMiklos Szeredi 
14108d56adddSMiklos Szeredi 	if (attr->ia_valid & ATTR_OPEN) {
1411df0e91d4SMiklos Szeredi 		/* This is coming from open(..., ... | O_TRUNC); */
1412df0e91d4SMiklos Szeredi 		WARN_ON(!(attr->ia_valid & ATTR_SIZE));
1413df0e91d4SMiklos Szeredi 		WARN_ON(attr->ia_size != 0);
1414df0e91d4SMiklos Szeredi 		if (fc->atomic_o_trunc) {
1415df0e91d4SMiklos Szeredi 			/*
1416df0e91d4SMiklos Szeredi 			 * No need to send request to userspace, since actual
1417df0e91d4SMiklos Szeredi 			 * truncation has already been done by OPEN.  But still
1418df0e91d4SMiklos Szeredi 			 * need to truncate page cache.
1419df0e91d4SMiklos Szeredi 			 */
1420df0e91d4SMiklos Szeredi 			i_size_write(inode, 0);
1421df0e91d4SMiklos Szeredi 			truncate_pagecache(inode, 0);
14226ff958edSMiklos Szeredi 			return 0;
1423df0e91d4SMiklos Szeredi 		}
14248d56adddSMiklos Szeredi 		file = NULL;
14258d56adddSMiklos Szeredi 	}
14266ff958edSMiklos Szeredi 
1427ab2257e9SMiklos Szeredi 	if (attr->ia_valid & ATTR_SIZE) {
1428ab2257e9SMiklos Szeredi 		if (WARN_ON(!S_ISREG(inode->i_mode)))
1429ab2257e9SMiklos Szeredi 			return -EIO;
14303be5a52bSMiklos Szeredi 		is_truncate = true;
1431ab2257e9SMiklos Szeredi 	}
14329e6268dbSMiklos Szeredi 
143306a7c3c2SMaxim Patlasov 	if (is_truncate) {
14343be5a52bSMiklos Szeredi 		fuse_set_nowrite(inode);
143506a7c3c2SMaxim Patlasov 		set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
14363ad22c62SMaxim Patlasov 		if (trust_local_cmtime && attr->ia_size != inode->i_size)
14373ad22c62SMaxim Patlasov 			attr->ia_valid |= ATTR_MTIME | ATTR_CTIME;
143806a7c3c2SMaxim Patlasov 	}
14393be5a52bSMiklos Szeredi 
14409e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
14410e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
14428cb08329SEric W. Biederman 	iattr_to_fattr(fc, attr, &inarg, trust_local_cmtime);
144349d4914fSMiklos Szeredi 	if (file) {
144449d4914fSMiklos Szeredi 		struct fuse_file *ff = file->private_data;
144549d4914fSMiklos Szeredi 		inarg.valid |= FATTR_FH;
144649d4914fSMiklos Szeredi 		inarg.fh = ff->fh;
144749d4914fSMiklos Szeredi 	}
1448f3332114SMiklos Szeredi 	if (attr->ia_valid & ATTR_SIZE) {
1449f3332114SMiklos Szeredi 		/* For mandatory locking in truncate */
1450f3332114SMiklos Szeredi 		inarg.valid |= FATTR_LOCKOWNER;
1451f3332114SMiklos Szeredi 		inarg.lock_owner = fuse_lock_owner_id(fc, current->files);
1452f3332114SMiklos Szeredi 	}
14537078187aSMiklos Szeredi 	fuse_setattr_fill(fc, &args, inode, &inarg, &outarg);
14547078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
1455e00d2c2dSMiklos Szeredi 	if (err) {
1456e00d2c2dSMiklos Szeredi 		if (err == -EINTR)
1457e00d2c2dSMiklos Szeredi 			fuse_invalidate_attr(inode);
14583be5a52bSMiklos Szeredi 		goto error;
1459e00d2c2dSMiklos Szeredi 	}
1460e00d2c2dSMiklos Szeredi 
14619e6268dbSMiklos Szeredi 	if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
14629e6268dbSMiklos Szeredi 		make_bad_inode(inode);
14633be5a52bSMiklos Szeredi 		err = -EIO;
14643be5a52bSMiklos Szeredi 		goto error;
14659e6268dbSMiklos Szeredi 	}
14669e6268dbSMiklos Szeredi 
14673be5a52bSMiklos Szeredi 	spin_lock(&fc->lock);
1468b0aa7606SMaxim Patlasov 	/* the kernel maintains i_mtime locally */
14693ad22c62SMaxim Patlasov 	if (trust_local_cmtime) {
14703ad22c62SMaxim Patlasov 		if (attr->ia_valid & ATTR_MTIME)
1471b0aa7606SMaxim Patlasov 			inode->i_mtime = attr->ia_mtime;
14723ad22c62SMaxim Patlasov 		if (attr->ia_valid & ATTR_CTIME)
14733ad22c62SMaxim Patlasov 			inode->i_ctime = attr->ia_ctime;
14741e18bda8SMiklos Szeredi 		/* FIXME: clear I_DIRTY_SYNC? */
1475b0aa7606SMaxim Patlasov 	}
1476b0aa7606SMaxim Patlasov 
14773be5a52bSMiklos Szeredi 	fuse_change_attributes_common(inode, &outarg.attr,
14783be5a52bSMiklos Szeredi 				      attr_timeout(&outarg));
14793be5a52bSMiklos Szeredi 	oldsize = inode->i_size;
14808373200bSPavel Emelyanov 	/* see the comment in fuse_change_attributes() */
14818373200bSPavel Emelyanov 	if (!is_wb || is_truncate || !S_ISREG(inode->i_mode))
14823be5a52bSMiklos Szeredi 		i_size_write(inode, outarg.attr.size);
14833be5a52bSMiklos Szeredi 
14843be5a52bSMiklos Szeredi 	if (is_truncate) {
14853be5a52bSMiklos Szeredi 		/* NOTE: this may release/reacquire fc->lock */
14863be5a52bSMiklos Szeredi 		__fuse_release_nowrite(inode);
14873be5a52bSMiklos Szeredi 	}
14883be5a52bSMiklos Szeredi 	spin_unlock(&fc->lock);
14893be5a52bSMiklos Szeredi 
14903be5a52bSMiklos Szeredi 	/*
14913be5a52bSMiklos Szeredi 	 * Only call invalidate_inode_pages2() after removing
14923be5a52bSMiklos Szeredi 	 * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock.
14933be5a52bSMiklos Szeredi 	 */
14948373200bSPavel Emelyanov 	if ((is_truncate || !is_wb) &&
14958373200bSPavel Emelyanov 	    S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
14967caef267SKirill A. Shutemov 		truncate_pagecache(inode, outarg.attr.size);
14973be5a52bSMiklos Szeredi 		invalidate_inode_pages2(inode->i_mapping);
14983be5a52bSMiklos Szeredi 	}
14993be5a52bSMiklos Szeredi 
150006a7c3c2SMaxim Patlasov 	clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
1501e00d2c2dSMiklos Szeredi 	return 0;
15023be5a52bSMiklos Szeredi 
15033be5a52bSMiklos Szeredi error:
15043be5a52bSMiklos Szeredi 	if (is_truncate)
15053be5a52bSMiklos Szeredi 		fuse_release_nowrite(inode);
15063be5a52bSMiklos Szeredi 
150706a7c3c2SMaxim Patlasov 	clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
15083be5a52bSMiklos Szeredi 	return err;
15099e6268dbSMiklos Szeredi }
15109e6268dbSMiklos Szeredi 
151149d4914fSMiklos Szeredi static int fuse_setattr(struct dentry *entry, struct iattr *attr)
151249d4914fSMiklos Szeredi {
15132b0143b5SDavid Howells 	struct inode *inode = d_inode(entry);
15145e940c1dSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1515a09f99edSMiklos Szeredi 	struct file *file = (attr->ia_valid & ATTR_FILE) ? attr->ia_file : NULL;
15165e2b8828SMiklos Szeredi 	int ret;
1517efb9fa9eSMaxim Patlasov 
1518efb9fa9eSMaxim Patlasov 	if (!fuse_allow_current_process(get_fuse_conn(inode)))
1519efb9fa9eSMaxim Patlasov 		return -EACCES;
1520efb9fa9eSMaxim Patlasov 
1521a09f99edSMiklos Szeredi 	if (attr->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) {
1522a09f99edSMiklos Szeredi 		attr->ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID |
1523a09f99edSMiklos Szeredi 				    ATTR_MODE);
15245e940c1dSMiklos Szeredi 
1525a09f99edSMiklos Szeredi 		/*
15265e940c1dSMiklos Szeredi 		 * The only sane way to reliably kill suid/sgid is to do it in
15275e940c1dSMiklos Szeredi 		 * the userspace filesystem
15285e940c1dSMiklos Szeredi 		 *
15295e940c1dSMiklos Szeredi 		 * This should be done on write(), truncate() and chown().
15305e940c1dSMiklos Szeredi 		 */
15315e940c1dSMiklos Szeredi 		if (!fc->handle_killpriv) {
15325e940c1dSMiklos Szeredi 			/*
15335e940c1dSMiklos Szeredi 			 * ia_mode calculation may have used stale i_mode.
15345e940c1dSMiklos Szeredi 			 * Refresh and recalculate.
1535a09f99edSMiklos Szeredi 			 */
1536a09f99edSMiklos Szeredi 			ret = fuse_do_getattr(inode, NULL, file);
1537a09f99edSMiklos Szeredi 			if (ret)
1538a09f99edSMiklos Szeredi 				return ret;
1539a09f99edSMiklos Szeredi 
1540a09f99edSMiklos Szeredi 			attr->ia_mode = inode->i_mode;
1541c01638f5SMiklos Szeredi 			if (inode->i_mode & S_ISUID) {
1542a09f99edSMiklos Szeredi 				attr->ia_valid |= ATTR_MODE;
1543a09f99edSMiklos Szeredi 				attr->ia_mode &= ~S_ISUID;
1544a09f99edSMiklos Szeredi 			}
1545c01638f5SMiklos Szeredi 			if ((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
1546a09f99edSMiklos Szeredi 				attr->ia_valid |= ATTR_MODE;
1547a09f99edSMiklos Szeredi 				attr->ia_mode &= ~S_ISGID;
1548a09f99edSMiklos Szeredi 			}
1549a09f99edSMiklos Szeredi 		}
15505e940c1dSMiklos Szeredi 	}
1551a09f99edSMiklos Szeredi 	if (!attr->ia_valid)
1552a09f99edSMiklos Szeredi 		return 0;
1553a09f99edSMiklos Szeredi 
1554abb5a14fSLinus Torvalds 	ret = fuse_do_setattr(entry, attr, file);
15555e2b8828SMiklos Szeredi 	if (!ret) {
155660bcc88aSSeth Forshee 		/*
155760bcc88aSSeth Forshee 		 * If filesystem supports acls it may have updated acl xattrs in
155860bcc88aSSeth Forshee 		 * the filesystem, so forget cached acls for the inode.
155960bcc88aSSeth Forshee 		 */
156060bcc88aSSeth Forshee 		if (fc->posix_acl)
156160bcc88aSSeth Forshee 			forget_all_cached_acls(inode);
156260bcc88aSSeth Forshee 
15635e2b8828SMiklos Szeredi 		/* Directory mode changed, may need to revalidate access */
15645e2b8828SMiklos Szeredi 		if (d_is_dir(entry) && (attr->ia_valid & ATTR_MODE))
15655e2b8828SMiklos Szeredi 			fuse_invalidate_entry_cache(entry);
15665e2b8828SMiklos Szeredi 	}
15675e2b8828SMiklos Szeredi 	return ret;
156849d4914fSMiklos Szeredi }
156949d4914fSMiklos Szeredi 
1570a528d35eSDavid Howells static int fuse_getattr(const struct path *path, struct kstat *stat,
1571a528d35eSDavid Howells 			u32 request_mask, unsigned int flags)
1572e5e5558eSMiklos Szeredi {
1573a528d35eSDavid Howells 	struct inode *inode = d_inode(path->dentry);
1574244f6385SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1575244f6385SMiklos Szeredi 
1576c2132c1bSAnatol Pomozov 	if (!fuse_allow_current_process(fc))
1577244f6385SMiklos Szeredi 		return -EACCES;
1578244f6385SMiklos Szeredi 
15792f1e8196SMiklos Szeredi 	return fuse_update_get_attr(inode, NULL, stat, request_mask, flags);
1580e5e5558eSMiklos Szeredi }
1581e5e5558eSMiklos Szeredi 
1582754661f1SArjan van de Ven static const struct inode_operations fuse_dir_inode_operations = {
1583e5e5558eSMiklos Szeredi 	.lookup		= fuse_lookup,
15849e6268dbSMiklos Szeredi 	.mkdir		= fuse_mkdir,
15859e6268dbSMiklos Szeredi 	.symlink	= fuse_symlink,
15869e6268dbSMiklos Szeredi 	.unlink		= fuse_unlink,
15879e6268dbSMiklos Szeredi 	.rmdir		= fuse_rmdir,
15882773bf00SMiklos Szeredi 	.rename		= fuse_rename2,
15899e6268dbSMiklos Szeredi 	.link		= fuse_link,
15909e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
15919e6268dbSMiklos Szeredi 	.create		= fuse_create,
1592c8ccbe03SMiklos Szeredi 	.atomic_open	= fuse_atomic_open,
15939e6268dbSMiklos Szeredi 	.mknod		= fuse_mknod,
1594e5e5558eSMiklos Szeredi 	.permission	= fuse_permission,
1595e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
159692a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
159760bcc88aSSeth Forshee 	.get_acl	= fuse_get_acl,
159860bcc88aSSeth Forshee 	.set_acl	= fuse_set_acl,
1599e5e5558eSMiklos Szeredi };
1600e5e5558eSMiklos Szeredi 
16014b6f5d20SArjan van de Ven static const struct file_operations fuse_dir_operations = {
1602b6aeadedSMiklos Szeredi 	.llseek		= generic_file_llseek,
1603e5e5558eSMiklos Szeredi 	.read		= generic_read_dir,
1604d9b3dbdcSAl Viro 	.iterate_shared	= fuse_readdir,
1605e5e5558eSMiklos Szeredi 	.open		= fuse_dir_open,
1606e5e5558eSMiklos Szeredi 	.release	= fuse_dir_release,
160782547981SMiklos Szeredi 	.fsync		= fuse_dir_fsync,
1608b18da0c5SMiklos Szeredi 	.unlocked_ioctl	= fuse_dir_ioctl,
1609b18da0c5SMiklos Szeredi 	.compat_ioctl	= fuse_dir_compat_ioctl,
1610e5e5558eSMiklos Szeredi };
1611e5e5558eSMiklos Szeredi 
1612754661f1SArjan van de Ven static const struct inode_operations fuse_common_inode_operations = {
16139e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
1614e5e5558eSMiklos Szeredi 	.permission	= fuse_permission,
1615e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
161692a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
161760bcc88aSSeth Forshee 	.get_acl	= fuse_get_acl,
161860bcc88aSSeth Forshee 	.set_acl	= fuse_set_acl,
1619e5e5558eSMiklos Szeredi };
1620e5e5558eSMiklos Szeredi 
1621754661f1SArjan van de Ven static const struct inode_operations fuse_symlink_inode_operations = {
16229e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
16236b255391SAl Viro 	.get_link	= fuse_get_link,
1624e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
162592a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
1626e5e5558eSMiklos Szeredi };
1627e5e5558eSMiklos Szeredi 
1628e5e5558eSMiklos Szeredi void fuse_init_common(struct inode *inode)
1629e5e5558eSMiklos Szeredi {
1630e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_common_inode_operations;
1631e5e5558eSMiklos Szeredi }
1632e5e5558eSMiklos Szeredi 
1633e5e5558eSMiklos Szeredi void fuse_init_dir(struct inode *inode)
1634e5e5558eSMiklos Szeredi {
1635ab2257e9SMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
1636ab2257e9SMiklos Szeredi 
1637e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_dir_inode_operations;
1638e5e5558eSMiklos Szeredi 	inode->i_fop = &fuse_dir_operations;
1639ab2257e9SMiklos Szeredi 
1640ab2257e9SMiklos Szeredi 	spin_lock_init(&fi->rdc.lock);
1641ab2257e9SMiklos Szeredi 	fi->rdc.cached = false;
1642ab2257e9SMiklos Szeredi 	fi->rdc.size = 0;
1643ab2257e9SMiklos Szeredi 	fi->rdc.pos = 0;
1644ab2257e9SMiklos Szeredi 	fi->rdc.version = 0;
1645e5e5558eSMiklos Szeredi }
1646e5e5558eSMiklos Szeredi 
1647e5e5558eSMiklos Szeredi void fuse_init_symlink(struct inode *inode)
1648e5e5558eSMiklos Szeredi {
1649e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_symlink_inode_operations;
1650e5e5558eSMiklos Szeredi }
1651