xref: /openbmc/linux/fs/fuse/dir.c (revision d5b4854357f47899ea5b0336b41b04e81b62b11d)
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));
142*d5b48543SMiklos Szeredi 	args->opcode = FUSE_LOOKUP;
143*d5b48543SMiklos Szeredi 	args->nodeid = nodeid;
144*d5b48543SMiklos Szeredi 	args->in_numargs = 1;
145*d5b48543SMiklos Szeredi 	args->in_args[0].size = name->len + 1;
146*d5b48543SMiklos Szeredi 	args->in_args[0].value = name->name;
147*d5b48543SMiklos Szeredi 	args->out_numargs = 1;
148*d5b48543SMiklos Szeredi 	args->out_args[0].size = sizeof(struct fuse_entry_out);
149*d5b48543SMiklos Szeredi 	args->out_args[0].value = outarg;
150e5e5558eSMiklos Szeredi }
151e5e5558eSMiklos Szeredi 
1526f9f1180SMiklos Szeredi /*
1536f9f1180SMiklos Szeredi  * Check whether the dentry is still valid
1546f9f1180SMiklos Szeredi  *
1556f9f1180SMiklos Szeredi  * If the entry validity timeout has expired and the dentry is
1566f9f1180SMiklos Szeredi  * positive, try to redo the lookup.  If the lookup results in a
1576f9f1180SMiklos Szeredi  * different inode, then let the VFS invalidate the dentry and redo
1586f9f1180SMiklos Szeredi  * the lookup once more.  If the lookup results in the same inode,
1596f9f1180SMiklos Szeredi  * then refresh the attributes, timeouts and mark the dentry valid.
1606f9f1180SMiklos Szeredi  */
1610b728e19SAl Viro static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
162e5e5558eSMiklos Szeredi {
16334286d66SNick Piggin 	struct inode *inode;
16428420dadSMiklos Szeredi 	struct dentry *parent;
16528420dadSMiklos Szeredi 	struct fuse_conn *fc;
1666314efeeSMiklos Szeredi 	struct fuse_inode *fi;
167e2a6b952SMiklos Szeredi 	int ret;
1688cbdf1e6SMiklos Szeredi 
1692b0143b5SDavid Howells 	inode = d_inode_rcu(entry);
1708cbdf1e6SMiklos Szeredi 	if (inode && is_bad_inode(inode))
171e2a6b952SMiklos Szeredi 		goto invalid;
172154210ccSAnand Avati 	else if (time_before64(fuse_dentry_time(entry), get_jiffies_64()) ||
173154210ccSAnand Avati 		 (flags & LOOKUP_REVAL)) {
174e5e5558eSMiklos Szeredi 		struct fuse_entry_out outarg;
1757078187aSMiklos Szeredi 		FUSE_ARGS(args);
17607e77dcaSMiklos Szeredi 		struct fuse_forget_link *forget;
1771fb69e78SMiklos Szeredi 		u64 attr_version;
1788cbdf1e6SMiklos Szeredi 
17950322fe7SMiklos Szeredi 		/* For negative dentries, always do a fresh lookup */
1808cbdf1e6SMiklos Szeredi 		if (!inode)
181e2a6b952SMiklos Szeredi 			goto invalid;
1828cbdf1e6SMiklos Szeredi 
183e2a6b952SMiklos Szeredi 		ret = -ECHILD;
1840b728e19SAl Viro 		if (flags & LOOKUP_RCU)
185e2a6b952SMiklos Szeredi 			goto out;
186e7c0a167SMiklos Szeredi 
1878cbdf1e6SMiklos Szeredi 		fc = get_fuse_conn(inode);
188e5e5558eSMiklos Szeredi 
18907e77dcaSMiklos Szeredi 		forget = fuse_alloc_forget();
190e2a6b952SMiklos Szeredi 		ret = -ENOMEM;
1917078187aSMiklos Szeredi 		if (!forget)
192e2a6b952SMiklos Szeredi 			goto out;
1932d51013eSMiklos Szeredi 
1947dca9fd3SMiklos Szeredi 		attr_version = fuse_get_attr_version(fc);
1951fb69e78SMiklos Szeredi 
196e956edd0SMiklos Szeredi 		parent = dget_parent(entry);
1972b0143b5SDavid Howells 		fuse_lookup_init(fc, &args, get_node_id(d_inode(parent)),
198c180eebeSMiklos Szeredi 				 &entry->d_name, &outarg);
1997078187aSMiklos Szeredi 		ret = fuse_simple_request(fc, &args);
200e956edd0SMiklos Szeredi 		dput(parent);
20150322fe7SMiklos Szeredi 		/* Zero nodeid is same as -ENOENT */
2027078187aSMiklos Szeredi 		if (!ret && !outarg.nodeid)
2037078187aSMiklos Szeredi 			ret = -ENOENT;
2047078187aSMiklos Szeredi 		if (!ret) {
2056314efeeSMiklos Szeredi 			fi = get_fuse_inode(inode);
2069e6268dbSMiklos Szeredi 			if (outarg.nodeid != get_node_id(inode)) {
20707e77dcaSMiklos Szeredi 				fuse_queue_forget(fc, forget, outarg.nodeid, 1);
208e2a6b952SMiklos Szeredi 				goto invalid;
2099e6268dbSMiklos Szeredi 			}
210c9d8f5f0SKirill Tkhai 			spin_lock(&fi->lock);
2119e6268dbSMiklos Szeredi 			fi->nlookup++;
212c9d8f5f0SKirill Tkhai 			spin_unlock(&fi->lock);
2139e6268dbSMiklos Szeredi 		}
21407e77dcaSMiklos Szeredi 		kfree(forget);
2157078187aSMiklos Szeredi 		if (ret == -ENOMEM)
2167078187aSMiklos Szeredi 			goto out;
2177078187aSMiklos Szeredi 		if (ret || (outarg.attr.mode ^ inode->i_mode) & S_IFMT)
218e2a6b952SMiklos Szeredi 			goto invalid;
219e5e5558eSMiklos Szeredi 
22060bcc88aSSeth Forshee 		forget_all_cached_acls(inode);
2211fb69e78SMiklos Szeredi 		fuse_change_attributes(inode, &outarg.attr,
2221fb69e78SMiklos Szeredi 				       entry_attr_timeout(&outarg),
2231fb69e78SMiklos Szeredi 				       attr_version);
2241fb69e78SMiklos Szeredi 		fuse_change_entry_timeout(entry, &outarg);
22528420dadSMiklos Szeredi 	} else if (inode) {
2266314efeeSMiklos Szeredi 		fi = get_fuse_inode(inode);
2276314efeeSMiklos Szeredi 		if (flags & LOOKUP_RCU) {
2286314efeeSMiklos Szeredi 			if (test_bit(FUSE_I_INIT_RDPLUS, &fi->state))
2296314efeeSMiklos Szeredi 				return -ECHILD;
2306314efeeSMiklos Szeredi 		} else if (test_and_clear_bit(FUSE_I_INIT_RDPLUS, &fi->state)) {
23128420dadSMiklos Szeredi 			parent = dget_parent(entry);
2322b0143b5SDavid Howells 			fuse_advise_use_readdirplus(d_inode(parent));
23328420dadSMiklos Szeredi 			dput(parent);
234e5e5558eSMiklos Szeredi 		}
23528420dadSMiklos Szeredi 	}
236e2a6b952SMiklos Szeredi 	ret = 1;
237e2a6b952SMiklos Szeredi out:
238e2a6b952SMiklos Szeredi 	return ret;
239e2a6b952SMiklos Szeredi 
240e2a6b952SMiklos Szeredi invalid:
241e2a6b952SMiklos Szeredi 	ret = 0;
242e2a6b952SMiklos Szeredi 	goto out;
243e5e5558eSMiklos Szeredi }
244e5e5558eSMiklos Szeredi 
245f75fdf22SMiklos Szeredi static int fuse_dentry_init(struct dentry *dentry)
246f75fdf22SMiklos Szeredi {
247f75fdf22SMiklos Szeredi 	dentry->d_fsdata = kzalloc(sizeof(union fuse_dentry), GFP_KERNEL);
248f75fdf22SMiklos Szeredi 
249f75fdf22SMiklos Szeredi 	return dentry->d_fsdata ? 0 : -ENOMEM;
250f75fdf22SMiklos Szeredi }
251f75fdf22SMiklos Szeredi static void fuse_dentry_release(struct dentry *dentry)
252f75fdf22SMiklos Szeredi {
253f75fdf22SMiklos Szeredi 	union fuse_dentry *fd = dentry->d_fsdata;
254f75fdf22SMiklos Szeredi 
255f75fdf22SMiklos Szeredi 	kfree_rcu(fd, rcu);
256f75fdf22SMiklos Szeredi }
257f75fdf22SMiklos Szeredi 
2584269590aSAl Viro const struct dentry_operations fuse_dentry_operations = {
259e5e5558eSMiklos Szeredi 	.d_revalidate	= fuse_dentry_revalidate,
260f75fdf22SMiklos Szeredi 	.d_init		= fuse_dentry_init,
261f75fdf22SMiklos Szeredi 	.d_release	= fuse_dentry_release,
262e5e5558eSMiklos Szeredi };
263e5e5558eSMiklos Szeredi 
2640ce267ffSMiklos Szeredi const struct dentry_operations fuse_root_dentry_operations = {
2650ce267ffSMiklos Szeredi 	.d_init		= fuse_dentry_init,
2660ce267ffSMiklos Szeredi 	.d_release	= fuse_dentry_release,
2670ce267ffSMiklos Szeredi };
2680ce267ffSMiklos Szeredi 
269a5bfffacSTimo Savola int fuse_valid_type(int m)
27039ee059aSMiklos Szeredi {
27139ee059aSMiklos Szeredi 	return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) ||
27239ee059aSMiklos Szeredi 		S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m);
27339ee059aSMiklos Szeredi }
27439ee059aSMiklos Szeredi 
27513983d06SAl Viro int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name,
276c180eebeSMiklos Szeredi 		     struct fuse_entry_out *outarg, struct inode **inode)
277c180eebeSMiklos Szeredi {
278c180eebeSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn_super(sb);
2797078187aSMiklos Szeredi 	FUSE_ARGS(args);
28007e77dcaSMiklos Szeredi 	struct fuse_forget_link *forget;
281c180eebeSMiklos Szeredi 	u64 attr_version;
282c180eebeSMiklos Szeredi 	int err;
283c180eebeSMiklos Szeredi 
284c180eebeSMiklos Szeredi 	*inode = NULL;
285c180eebeSMiklos Szeredi 	err = -ENAMETOOLONG;
286c180eebeSMiklos Szeredi 	if (name->len > FUSE_NAME_MAX)
287c180eebeSMiklos Szeredi 		goto out;
288c180eebeSMiklos Szeredi 
289c180eebeSMiklos Szeredi 
29007e77dcaSMiklos Szeredi 	forget = fuse_alloc_forget();
29107e77dcaSMiklos Szeredi 	err = -ENOMEM;
2927078187aSMiklos Szeredi 	if (!forget)
293c180eebeSMiklos Szeredi 		goto out;
294c180eebeSMiklos Szeredi 
295c180eebeSMiklos Szeredi 	attr_version = fuse_get_attr_version(fc);
296c180eebeSMiklos Szeredi 
2977078187aSMiklos Szeredi 	fuse_lookup_init(fc, &args, nodeid, name, outarg);
2987078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
299c180eebeSMiklos Szeredi 	/* Zero nodeid is same as -ENOENT, but with valid timeout */
300c180eebeSMiklos Szeredi 	if (err || !outarg->nodeid)
301c180eebeSMiklos Szeredi 		goto out_put_forget;
302c180eebeSMiklos Szeredi 
303c180eebeSMiklos Szeredi 	err = -EIO;
304c180eebeSMiklos Szeredi 	if (!outarg->nodeid)
305c180eebeSMiklos Szeredi 		goto out_put_forget;
306c180eebeSMiklos Szeredi 	if (!fuse_valid_type(outarg->attr.mode))
307c180eebeSMiklos Szeredi 		goto out_put_forget;
308c180eebeSMiklos Szeredi 
309c180eebeSMiklos Szeredi 	*inode = fuse_iget(sb, outarg->nodeid, outarg->generation,
310c180eebeSMiklos Szeredi 			   &outarg->attr, entry_attr_timeout(outarg),
311c180eebeSMiklos Szeredi 			   attr_version);
312c180eebeSMiklos Szeredi 	err = -ENOMEM;
313c180eebeSMiklos Szeredi 	if (!*inode) {
31407e77dcaSMiklos Szeredi 		fuse_queue_forget(fc, forget, outarg->nodeid, 1);
315c180eebeSMiklos Szeredi 		goto out;
316c180eebeSMiklos Szeredi 	}
317c180eebeSMiklos Szeredi 	err = 0;
318c180eebeSMiklos Szeredi 
319c180eebeSMiklos Szeredi  out_put_forget:
32007e77dcaSMiklos Szeredi 	kfree(forget);
321c180eebeSMiklos Szeredi  out:
322c180eebeSMiklos Szeredi 	return err;
323c180eebeSMiklos Szeredi }
324c180eebeSMiklos Szeredi 
3250aa7c699SMiklos Szeredi static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
32600cd8dd3SAl Viro 				  unsigned int flags)
327e5e5558eSMiklos Szeredi {
328e5e5558eSMiklos Szeredi 	int err;
329e5e5558eSMiklos Szeredi 	struct fuse_entry_out outarg;
330c180eebeSMiklos Szeredi 	struct inode *inode;
3310de6256dSMiklos Szeredi 	struct dentry *newent;
332c180eebeSMiklos Szeredi 	bool outarg_valid = true;
33363576c13SMiklos Szeredi 	bool locked;
334e5e5558eSMiklos Szeredi 
33563576c13SMiklos Szeredi 	locked = fuse_lock_inode(dir);
336c180eebeSMiklos Szeredi 	err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name,
337c180eebeSMiklos Szeredi 			       &outarg, &inode);
33863576c13SMiklos Szeredi 	fuse_unlock_inode(dir, locked);
339c180eebeSMiklos Szeredi 	if (err == -ENOENT) {
340c180eebeSMiklos Szeredi 		outarg_valid = false;
341c180eebeSMiklos Szeredi 		err = 0;
3422d51013eSMiklos Szeredi 	}
343c180eebeSMiklos Szeredi 	if (err)
344c180eebeSMiklos Szeredi 		goto out_err;
3452d51013eSMiklos Szeredi 
346ee4e5271SMiklos Szeredi 	err = -EIO;
347c180eebeSMiklos Szeredi 	if (inode && get_node_id(inode) == FUSE_ROOT_ID)
348c180eebeSMiklos Szeredi 		goto out_iput;
349e5e5558eSMiklos Szeredi 
35041d28bcaSAl Viro 	newent = d_splice_alias(inode, entry);
351c180eebeSMiklos Szeredi 	err = PTR_ERR(newent);
352c180eebeSMiklos Szeredi 	if (IS_ERR(newent))
3535835f339SMiklos Szeredi 		goto out_err;
354d2a85164SMiklos Szeredi 
3550de6256dSMiklos Szeredi 	entry = newent ? newent : entry;
356c180eebeSMiklos Szeredi 	if (outarg_valid)
3571fb69e78SMiklos Szeredi 		fuse_change_entry_timeout(entry, &outarg);
3588cbdf1e6SMiklos Szeredi 	else
3598cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
360c180eebeSMiklos Szeredi 
3614582a4abSFeng Shuo 	fuse_advise_use_readdirplus(dir);
3620de6256dSMiklos Szeredi 	return newent;
363c180eebeSMiklos Szeredi 
364c180eebeSMiklos Szeredi  out_iput:
365c180eebeSMiklos Szeredi 	iput(inode);
366c180eebeSMiklos Szeredi  out_err:
367c180eebeSMiklos Szeredi 	return ERR_PTR(err);
368e5e5558eSMiklos Szeredi }
369e5e5558eSMiklos Szeredi 
3706f9f1180SMiklos Szeredi /*
3716f9f1180SMiklos Szeredi  * Atomic create+open operation
3726f9f1180SMiklos Szeredi  *
3736f9f1180SMiklos Szeredi  * If the filesystem doesn't support this, then fall back to separate
3746f9f1180SMiklos Szeredi  * 'mknod' + 'open' requests.
3756f9f1180SMiklos Szeredi  */
376d9585277SAl Viro static int fuse_create_open(struct inode *dir, struct dentry *entry,
37730d90494SAl Viro 			    struct file *file, unsigned flags,
378b452a458SAl Viro 			    umode_t mode)
379fd72faacSMiklos Szeredi {
380fd72faacSMiklos Szeredi 	int err;
381fd72faacSMiklos Szeredi 	struct inode *inode;
382fd72faacSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
3837078187aSMiklos Szeredi 	FUSE_ARGS(args);
38407e77dcaSMiklos Szeredi 	struct fuse_forget_link *forget;
385e0a43ddcSMiklos Szeredi 	struct fuse_create_in inarg;
386fd72faacSMiklos Szeredi 	struct fuse_open_out outopen;
387fd72faacSMiklos Szeredi 	struct fuse_entry_out outentry;
388ebf84d0cSKirill Tkhai 	struct fuse_inode *fi;
389fd72faacSMiklos Szeredi 	struct fuse_file *ff;
390fd72faacSMiklos Szeredi 
391af109bcaSMiklos Szeredi 	/* Userspace expects S_IFREG in create mode */
392af109bcaSMiklos Szeredi 	BUG_ON((mode & S_IFMT) != S_IFREG);
393af109bcaSMiklos Szeredi 
39407e77dcaSMiklos Szeredi 	forget = fuse_alloc_forget();
395c8ccbe03SMiklos Szeredi 	err = -ENOMEM;
39607e77dcaSMiklos Szeredi 	if (!forget)
397c8ccbe03SMiklos Szeredi 		goto out_err;
39851eb01e7SMiklos Szeredi 
399ce1d5a49SMiklos Szeredi 	err = -ENOMEM;
400acf99433STejun Heo 	ff = fuse_file_alloc(fc);
401fd72faacSMiklos Szeredi 	if (!ff)
4027078187aSMiklos Szeredi 		goto out_put_forget_req;
403fd72faacSMiklos Szeredi 
404e0a43ddcSMiklos Szeredi 	if (!fc->dont_mask)
405e0a43ddcSMiklos Szeredi 		mode &= ~current_umask();
406e0a43ddcSMiklos Szeredi 
407fd72faacSMiklos Szeredi 	flags &= ~O_NOCTTY;
408fd72faacSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
4090e9663eeSMiklos Szeredi 	memset(&outentry, 0, sizeof(outentry));
410fd72faacSMiklos Szeredi 	inarg.flags = flags;
411fd72faacSMiklos Szeredi 	inarg.mode = mode;
412e0a43ddcSMiklos Szeredi 	inarg.umask = current_umask();
413*d5b48543SMiklos Szeredi 	args.opcode = FUSE_CREATE;
414*d5b48543SMiklos Szeredi 	args.nodeid = get_node_id(dir);
415*d5b48543SMiklos Szeredi 	args.in_numargs = 2;
416*d5b48543SMiklos Szeredi 	args.in_args[0].size = sizeof(inarg);
417*d5b48543SMiklos Szeredi 	args.in_args[0].value = &inarg;
418*d5b48543SMiklos Szeredi 	args.in_args[1].size = entry->d_name.len + 1;
419*d5b48543SMiklos Szeredi 	args.in_args[1].value = entry->d_name.name;
420*d5b48543SMiklos Szeredi 	args.out_numargs = 2;
421*d5b48543SMiklos Szeredi 	args.out_args[0].size = sizeof(outentry);
422*d5b48543SMiklos Szeredi 	args.out_args[0].value = &outentry;
423*d5b48543SMiklos Szeredi 	args.out_args[1].size = sizeof(outopen);
424*d5b48543SMiklos Szeredi 	args.out_args[1].value = &outopen;
4257078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
426c8ccbe03SMiklos Szeredi 	if (err)
427fd72faacSMiklos Szeredi 		goto out_free_ff;
428fd72faacSMiklos Szeredi 
429fd72faacSMiklos Szeredi 	err = -EIO;
4302827d0b2SMiklos Szeredi 	if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid))
431fd72faacSMiklos Szeredi 		goto out_free_ff;
432fd72faacSMiklos Szeredi 
433c7b7143cSMiklos Szeredi 	ff->fh = outopen.fh;
434c7b7143cSMiklos Szeredi 	ff->nodeid = outentry.nodeid;
435c7b7143cSMiklos Szeredi 	ff->open_flags = outopen.open_flags;
436fd72faacSMiklos Szeredi 	inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
4371fb69e78SMiklos Szeredi 			  &outentry.attr, entry_attr_timeout(&outentry), 0);
438fd72faacSMiklos Szeredi 	if (!inode) {
439fd72faacSMiklos Szeredi 		flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
440ebf84d0cSKirill Tkhai 		fuse_sync_release(NULL, ff, flags);
44107e77dcaSMiklos Szeredi 		fuse_queue_forget(fc, forget, outentry.nodeid, 1);
442c8ccbe03SMiklos Szeredi 		err = -ENOMEM;
443c8ccbe03SMiklos Szeredi 		goto out_err;
444fd72faacSMiklos Szeredi 	}
44507e77dcaSMiklos Szeredi 	kfree(forget);
446fd72faacSMiklos Szeredi 	d_instantiate(entry, inode);
4471fb69e78SMiklos Szeredi 	fuse_change_entry_timeout(entry, &outentry);
448261aaba7SMiklos Szeredi 	fuse_dir_changed(dir);
449be12af3eSAl Viro 	err = finish_open(file, entry, generic_file_open);
45030d90494SAl Viro 	if (err) {
451ebf84d0cSKirill Tkhai 		fi = get_fuse_inode(inode);
452ebf84d0cSKirill Tkhai 		fuse_sync_release(fi, ff, flags);
453c8ccbe03SMiklos Szeredi 	} else {
454267d8444SMiklos Szeredi 		file->private_data = ff;
455c7b7143cSMiklos Szeredi 		fuse_finish_open(inode, file);
456c8ccbe03SMiklos Szeredi 	}
457d9585277SAl Viro 	return err;
458fd72faacSMiklos Szeredi 
459fd72faacSMiklos Szeredi out_free_ff:
460fd72faacSMiklos Szeredi 	fuse_file_free(ff);
46151eb01e7SMiklos Szeredi out_put_forget_req:
46207e77dcaSMiklos Szeredi 	kfree(forget);
463c8ccbe03SMiklos Szeredi out_err:
464d9585277SAl Viro 	return err;
465c8ccbe03SMiklos Szeredi }
466c8ccbe03SMiklos Szeredi 
467c8ccbe03SMiklos Szeredi static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t);
468d9585277SAl Viro static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
46930d90494SAl Viro 			    struct file *file, unsigned flags,
47044907d79SAl Viro 			    umode_t mode)
471c8ccbe03SMiklos Szeredi {
472c8ccbe03SMiklos Szeredi 	int err;
473c8ccbe03SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
474c8ccbe03SMiklos Szeredi 	struct dentry *res = NULL;
475c8ccbe03SMiklos Szeredi 
47600699ad8SAl Viro 	if (d_in_lookup(entry)) {
47700cd8dd3SAl Viro 		res = fuse_lookup(dir, entry, 0);
478c8ccbe03SMiklos Szeredi 		if (IS_ERR(res))
479d9585277SAl Viro 			return PTR_ERR(res);
480c8ccbe03SMiklos Szeredi 
481c8ccbe03SMiklos Szeredi 		if (res)
482c8ccbe03SMiklos Szeredi 			entry = res;
483c8ccbe03SMiklos Szeredi 	}
484c8ccbe03SMiklos Szeredi 
4852b0143b5SDavid Howells 	if (!(flags & O_CREAT) || d_really_is_positive(entry))
486c8ccbe03SMiklos Szeredi 		goto no_open;
487c8ccbe03SMiklos Szeredi 
488c8ccbe03SMiklos Szeredi 	/* Only creates */
48973a09dd9SAl Viro 	file->f_mode |= FMODE_CREATED;
490c8ccbe03SMiklos Szeredi 
491c8ccbe03SMiklos Szeredi 	if (fc->no_create)
492c8ccbe03SMiklos Szeredi 		goto mknod;
493c8ccbe03SMiklos Szeredi 
494b452a458SAl Viro 	err = fuse_create_open(dir, entry, file, flags, mode);
495d9585277SAl Viro 	if (err == -ENOSYS) {
496c8ccbe03SMiklos Szeredi 		fc->no_create = 1;
497c8ccbe03SMiklos Szeredi 		goto mknod;
498c8ccbe03SMiklos Szeredi 	}
499c8ccbe03SMiklos Szeredi out_dput:
500c8ccbe03SMiklos Szeredi 	dput(res);
501d9585277SAl Viro 	return err;
502c8ccbe03SMiklos Szeredi 
503c8ccbe03SMiklos Szeredi mknod:
504c8ccbe03SMiklos Szeredi 	err = fuse_mknod(dir, entry, mode, 0);
505d9585277SAl Viro 	if (err)
506c8ccbe03SMiklos Szeredi 		goto out_dput;
507c8ccbe03SMiklos Szeredi no_open:
508e45198a6SAl Viro 	return finish_no_open(file, res);
509fd72faacSMiklos Szeredi }
510fd72faacSMiklos Szeredi 
5116f9f1180SMiklos Szeredi /*
5126f9f1180SMiklos Szeredi  * Code shared between mknod, mkdir, symlink and link
5136f9f1180SMiklos Szeredi  */
5147078187aSMiklos Szeredi static int create_new_entry(struct fuse_conn *fc, struct fuse_args *args,
5159e6268dbSMiklos Szeredi 			    struct inode *dir, struct dentry *entry,
516541af6a0SAl Viro 			    umode_t mode)
5179e6268dbSMiklos Szeredi {
5189e6268dbSMiklos Szeredi 	struct fuse_entry_out outarg;
5199e6268dbSMiklos Szeredi 	struct inode *inode;
520c971e6a0SAl Viro 	struct dentry *d;
5219e6268dbSMiklos Szeredi 	int err;
52207e77dcaSMiklos Szeredi 	struct fuse_forget_link *forget;
5232d51013eSMiklos Szeredi 
52407e77dcaSMiklos Szeredi 	forget = fuse_alloc_forget();
5257078187aSMiklos Szeredi 	if (!forget)
52607e77dcaSMiklos Szeredi 		return -ENOMEM;
5279e6268dbSMiklos Szeredi 
5280e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
529*d5b48543SMiklos Szeredi 	args->nodeid = get_node_id(dir);
530*d5b48543SMiklos Szeredi 	args->out_numargs = 1;
531*d5b48543SMiklos Szeredi 	args->out_args[0].size = sizeof(outarg);
532*d5b48543SMiklos Szeredi 	args->out_args[0].value = &outarg;
5337078187aSMiklos Szeredi 	err = fuse_simple_request(fc, args);
5342d51013eSMiklos Szeredi 	if (err)
5352d51013eSMiklos Szeredi 		goto out_put_forget_req;
5362d51013eSMiklos Szeredi 
53739ee059aSMiklos Szeredi 	err = -EIO;
53839ee059aSMiklos Szeredi 	if (invalid_nodeid(outarg.nodeid))
5392d51013eSMiklos Szeredi 		goto out_put_forget_req;
54039ee059aSMiklos Szeredi 
54139ee059aSMiklos Szeredi 	if ((outarg.attr.mode ^ mode) & S_IFMT)
5422d51013eSMiklos Szeredi 		goto out_put_forget_req;
54339ee059aSMiklos Szeredi 
5449e6268dbSMiklos Szeredi 	inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
5451fb69e78SMiklos Szeredi 			  &outarg.attr, entry_attr_timeout(&outarg), 0);
5469e6268dbSMiklos Szeredi 	if (!inode) {
54707e77dcaSMiklos Szeredi 		fuse_queue_forget(fc, forget, outarg.nodeid, 1);
5489e6268dbSMiklos Szeredi 		return -ENOMEM;
5499e6268dbSMiklos Szeredi 	}
55007e77dcaSMiklos Szeredi 	kfree(forget);
5519e6268dbSMiklos Szeredi 
552c971e6a0SAl Viro 	d_drop(entry);
553c971e6a0SAl Viro 	d = d_splice_alias(inode, entry);
554c971e6a0SAl Viro 	if (IS_ERR(d))
555c971e6a0SAl Viro 		return PTR_ERR(d);
556d2a85164SMiklos Szeredi 
557c971e6a0SAl Viro 	if (d) {
558c971e6a0SAl Viro 		fuse_change_entry_timeout(d, &outarg);
559c971e6a0SAl Viro 		dput(d);
560c971e6a0SAl Viro 	} else {
5611fb69e78SMiklos Szeredi 		fuse_change_entry_timeout(entry, &outarg);
562c971e6a0SAl Viro 	}
563261aaba7SMiklos Szeredi 	fuse_dir_changed(dir);
5649e6268dbSMiklos Szeredi 	return 0;
56539ee059aSMiklos Szeredi 
5662d51013eSMiklos Szeredi  out_put_forget_req:
56707e77dcaSMiklos Szeredi 	kfree(forget);
56839ee059aSMiklos Szeredi 	return err;
5699e6268dbSMiklos Szeredi }
5709e6268dbSMiklos Szeredi 
5711a67aafbSAl Viro static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode,
5729e6268dbSMiklos Szeredi 		      dev_t rdev)
5739e6268dbSMiklos Szeredi {
5749e6268dbSMiklos Szeredi 	struct fuse_mknod_in inarg;
5759e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
5767078187aSMiklos Szeredi 	FUSE_ARGS(args);
5779e6268dbSMiklos Szeredi 
578e0a43ddcSMiklos Szeredi 	if (!fc->dont_mask)
579e0a43ddcSMiklos Szeredi 		mode &= ~current_umask();
580e0a43ddcSMiklos Szeredi 
5819e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
5829e6268dbSMiklos Szeredi 	inarg.mode = mode;
5839e6268dbSMiklos Szeredi 	inarg.rdev = new_encode_dev(rdev);
584e0a43ddcSMiklos Szeredi 	inarg.umask = current_umask();
585*d5b48543SMiklos Szeredi 	args.opcode = FUSE_MKNOD;
586*d5b48543SMiklos Szeredi 	args.in_numargs = 2;
587*d5b48543SMiklos Szeredi 	args.in_args[0].size = sizeof(inarg);
588*d5b48543SMiklos Szeredi 	args.in_args[0].value = &inarg;
589*d5b48543SMiklos Szeredi 	args.in_args[1].size = entry->d_name.len + 1;
590*d5b48543SMiklos Szeredi 	args.in_args[1].value = entry->d_name.name;
5917078187aSMiklos Szeredi 	return create_new_entry(fc, &args, dir, entry, mode);
5929e6268dbSMiklos Szeredi }
5939e6268dbSMiklos Szeredi 
5944acdaf27SAl Viro static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode,
595ebfc3b49SAl Viro 		       bool excl)
5969e6268dbSMiklos Szeredi {
5979e6268dbSMiklos Szeredi 	return fuse_mknod(dir, entry, mode, 0);
5989e6268dbSMiklos Szeredi }
5999e6268dbSMiklos Szeredi 
60018bb1db3SAl Viro static int fuse_mkdir(struct inode *dir, struct dentry *entry, umode_t mode)
6019e6268dbSMiklos Szeredi {
6029e6268dbSMiklos Szeredi 	struct fuse_mkdir_in inarg;
6039e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
6047078187aSMiklos Szeredi 	FUSE_ARGS(args);
6059e6268dbSMiklos Szeredi 
606e0a43ddcSMiklos Szeredi 	if (!fc->dont_mask)
607e0a43ddcSMiklos Szeredi 		mode &= ~current_umask();
608e0a43ddcSMiklos Szeredi 
6099e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
6109e6268dbSMiklos Szeredi 	inarg.mode = mode;
611e0a43ddcSMiklos Szeredi 	inarg.umask = current_umask();
612*d5b48543SMiklos Szeredi 	args.opcode = FUSE_MKDIR;
613*d5b48543SMiklos Szeredi 	args.in_numargs = 2;
614*d5b48543SMiklos Szeredi 	args.in_args[0].size = sizeof(inarg);
615*d5b48543SMiklos Szeredi 	args.in_args[0].value = &inarg;
616*d5b48543SMiklos Szeredi 	args.in_args[1].size = entry->d_name.len + 1;
617*d5b48543SMiklos Szeredi 	args.in_args[1].value = entry->d_name.name;
6187078187aSMiklos Szeredi 	return create_new_entry(fc, &args, dir, entry, S_IFDIR);
6199e6268dbSMiklos Szeredi }
6209e6268dbSMiklos Szeredi 
6219e6268dbSMiklos Szeredi static int fuse_symlink(struct inode *dir, struct dentry *entry,
6229e6268dbSMiklos Szeredi 			const char *link)
6239e6268dbSMiklos Szeredi {
6249e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
6259e6268dbSMiklos Szeredi 	unsigned len = strlen(link) + 1;
6267078187aSMiklos Szeredi 	FUSE_ARGS(args);
6279e6268dbSMiklos Szeredi 
628*d5b48543SMiklos Szeredi 	args.opcode = FUSE_SYMLINK;
629*d5b48543SMiklos Szeredi 	args.in_numargs = 2;
630*d5b48543SMiklos Szeredi 	args.in_args[0].size = entry->d_name.len + 1;
631*d5b48543SMiklos Szeredi 	args.in_args[0].value = entry->d_name.name;
632*d5b48543SMiklos Szeredi 	args.in_args[1].size = len;
633*d5b48543SMiklos Szeredi 	args.in_args[1].value = link;
6347078187aSMiklos Szeredi 	return create_new_entry(fc, &args, dir, entry, S_IFLNK);
6359e6268dbSMiklos Szeredi }
6369e6268dbSMiklos Szeredi 
637703c7362SSeth Forshee void fuse_update_ctime(struct inode *inode)
63831f3267bSMaxim Patlasov {
63931f3267bSMaxim Patlasov 	if (!IS_NOCMTIME(inode)) {
640c2050a45SDeepa Dinamani 		inode->i_ctime = current_time(inode);
64131f3267bSMaxim Patlasov 		mark_inode_dirty_sync(inode);
64231f3267bSMaxim Patlasov 	}
64331f3267bSMaxim Patlasov }
64431f3267bSMaxim Patlasov 
6459e6268dbSMiklos Szeredi static int fuse_unlink(struct inode *dir, struct dentry *entry)
6469e6268dbSMiklos Szeredi {
6479e6268dbSMiklos Szeredi 	int err;
6489e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
6497078187aSMiklos Szeredi 	FUSE_ARGS(args);
6509e6268dbSMiklos Szeredi 
651*d5b48543SMiklos Szeredi 	args.opcode = FUSE_UNLINK;
652*d5b48543SMiklos Szeredi 	args.nodeid = get_node_id(dir);
653*d5b48543SMiklos Szeredi 	args.in_numargs = 1;
654*d5b48543SMiklos Szeredi 	args.in_args[0].size = entry->d_name.len + 1;
655*d5b48543SMiklos Szeredi 	args.in_args[0].value = entry->d_name.name;
6567078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
6579e6268dbSMiklos Szeredi 	if (!err) {
6582b0143b5SDavid Howells 		struct inode *inode = d_inode(entry);
659ac45d613SMiklos Szeredi 		struct fuse_inode *fi = get_fuse_inode(inode);
6609e6268dbSMiklos Szeredi 
661f15ecfefSKirill Tkhai 		spin_lock(&fi->lock);
6624510d86fSKirill Tkhai 		fi->attr_version = atomic64_inc_return(&fc->attr_version);
663dfca7cebSMiklos Szeredi 		/*
664dfca7cebSMiklos Szeredi 		 * If i_nlink == 0 then unlink doesn't make sense, yet this can
665dfca7cebSMiklos Szeredi 		 * happen if userspace filesystem is careless.  It would be
666dfca7cebSMiklos Szeredi 		 * difficult to enforce correct nlink usage so just ignore this
667dfca7cebSMiklos Szeredi 		 * condition here
668dfca7cebSMiklos Szeredi 		 */
669dfca7cebSMiklos Szeredi 		if (inode->i_nlink > 0)
670ac45d613SMiklos Szeredi 			drop_nlink(inode);
671f15ecfefSKirill Tkhai 		spin_unlock(&fi->lock);
6729e6268dbSMiklos Szeredi 		fuse_invalidate_attr(inode);
673261aaba7SMiklos Szeredi 		fuse_dir_changed(dir);
6748cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
67531f3267bSMaxim Patlasov 		fuse_update_ctime(inode);
6769e6268dbSMiklos Szeredi 	} else if (err == -EINTR)
6779e6268dbSMiklos Szeredi 		fuse_invalidate_entry(entry);
6789e6268dbSMiklos Szeredi 	return err;
6799e6268dbSMiklos Szeredi }
6809e6268dbSMiklos Szeredi 
6819e6268dbSMiklos Szeredi static int fuse_rmdir(struct inode *dir, struct dentry *entry)
6829e6268dbSMiklos Szeredi {
6839e6268dbSMiklos Szeredi 	int err;
6849e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
6857078187aSMiklos Szeredi 	FUSE_ARGS(args);
6869e6268dbSMiklos Szeredi 
687*d5b48543SMiklos Szeredi 	args.opcode = FUSE_RMDIR;
688*d5b48543SMiklos Szeredi 	args.nodeid = get_node_id(dir);
689*d5b48543SMiklos Szeredi 	args.in_numargs = 1;
690*d5b48543SMiklos Szeredi 	args.in_args[0].size = entry->d_name.len + 1;
691*d5b48543SMiklos Szeredi 	args.in_args[0].value = entry->d_name.name;
6927078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
6939e6268dbSMiklos Szeredi 	if (!err) {
6942b0143b5SDavid Howells 		clear_nlink(d_inode(entry));
695261aaba7SMiklos Szeredi 		fuse_dir_changed(dir);
6968cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
6979e6268dbSMiklos Szeredi 	} else if (err == -EINTR)
6989e6268dbSMiklos Szeredi 		fuse_invalidate_entry(entry);
6999e6268dbSMiklos Szeredi 	return err;
7009e6268dbSMiklos Szeredi }
7019e6268dbSMiklos Szeredi 
7021560c974SMiklos Szeredi static int fuse_rename_common(struct inode *olddir, struct dentry *oldent,
7031560c974SMiklos Szeredi 			      struct inode *newdir, struct dentry *newent,
7041560c974SMiklos Szeredi 			      unsigned int flags, int opcode, size_t argsize)
7059e6268dbSMiklos Szeredi {
7069e6268dbSMiklos Szeredi 	int err;
7071560c974SMiklos Szeredi 	struct fuse_rename2_in inarg;
7089e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(olddir);
7097078187aSMiklos Szeredi 	FUSE_ARGS(args);
7109e6268dbSMiklos Szeredi 
7111560c974SMiklos Szeredi 	memset(&inarg, 0, argsize);
7129e6268dbSMiklos Szeredi 	inarg.newdir = get_node_id(newdir);
7131560c974SMiklos Szeredi 	inarg.flags = flags;
714*d5b48543SMiklos Szeredi 	args.opcode = opcode;
715*d5b48543SMiklos Szeredi 	args.nodeid = get_node_id(olddir);
716*d5b48543SMiklos Szeredi 	args.in_numargs = 3;
717*d5b48543SMiklos Szeredi 	args.in_args[0].size = argsize;
718*d5b48543SMiklos Szeredi 	args.in_args[0].value = &inarg;
719*d5b48543SMiklos Szeredi 	args.in_args[1].size = oldent->d_name.len + 1;
720*d5b48543SMiklos Szeredi 	args.in_args[1].value = oldent->d_name.name;
721*d5b48543SMiklos Szeredi 	args.in_args[2].size = newent->d_name.len + 1;
722*d5b48543SMiklos Szeredi 	args.in_args[2].value = newent->d_name.name;
7237078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
7249e6268dbSMiklos Szeredi 	if (!err) {
72508b63307SMiklos Szeredi 		/* ctime changes */
7262b0143b5SDavid Howells 		fuse_invalidate_attr(d_inode(oldent));
7272b0143b5SDavid Howells 		fuse_update_ctime(d_inode(oldent));
72808b63307SMiklos Szeredi 
7291560c974SMiklos Szeredi 		if (flags & RENAME_EXCHANGE) {
7302b0143b5SDavid Howells 			fuse_invalidate_attr(d_inode(newent));
7312b0143b5SDavid Howells 			fuse_update_ctime(d_inode(newent));
7321560c974SMiklos Szeredi 		}
7331560c974SMiklos Szeredi 
734261aaba7SMiklos Szeredi 		fuse_dir_changed(olddir);
7359e6268dbSMiklos Szeredi 		if (olddir != newdir)
736261aaba7SMiklos Szeredi 			fuse_dir_changed(newdir);
7378cbdf1e6SMiklos Szeredi 
7388cbdf1e6SMiklos Szeredi 		/* newent will end up negative */
7392b0143b5SDavid Howells 		if (!(flags & RENAME_EXCHANGE) && d_really_is_positive(newent)) {
7402b0143b5SDavid Howells 			fuse_invalidate_attr(d_inode(newent));
7418cbdf1e6SMiklos Szeredi 			fuse_invalidate_entry_cache(newent);
7422b0143b5SDavid Howells 			fuse_update_ctime(d_inode(newent));
7435219f346SMiklos Szeredi 		}
7449e6268dbSMiklos Szeredi 	} else if (err == -EINTR) {
7459e6268dbSMiklos Szeredi 		/* If request was interrupted, DEITY only knows if the
7469e6268dbSMiklos Szeredi 		   rename actually took place.  If the invalidation
7479e6268dbSMiklos Szeredi 		   fails (e.g. some process has CWD under the renamed
7489e6268dbSMiklos Szeredi 		   directory), then there can be inconsistency between
7499e6268dbSMiklos Szeredi 		   the dcache and the real filesystem.  Tough luck. */
7509e6268dbSMiklos Szeredi 		fuse_invalidate_entry(oldent);
7512b0143b5SDavid Howells 		if (d_really_is_positive(newent))
7529e6268dbSMiklos Szeredi 			fuse_invalidate_entry(newent);
7539e6268dbSMiklos Szeredi 	}
7549e6268dbSMiklos Szeredi 
7559e6268dbSMiklos Szeredi 	return err;
7569e6268dbSMiklos Szeredi }
7579e6268dbSMiklos Szeredi 
7581560c974SMiklos Szeredi static int fuse_rename2(struct inode *olddir, struct dentry *oldent,
7591560c974SMiklos Szeredi 			struct inode *newdir, struct dentry *newent,
7601560c974SMiklos Szeredi 			unsigned int flags)
7611560c974SMiklos Szeredi {
7621560c974SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(olddir);
7631560c974SMiklos Szeredi 	int err;
7641560c974SMiklos Szeredi 
7651560c974SMiklos Szeredi 	if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE))
7661560c974SMiklos Szeredi 		return -EINVAL;
7671560c974SMiklos Szeredi 
7684237ba43SMiklos Szeredi 	if (flags) {
7691560c974SMiklos Szeredi 		if (fc->no_rename2 || fc->minor < 23)
7701560c974SMiklos Szeredi 			return -EINVAL;
7711560c974SMiklos Szeredi 
7721560c974SMiklos Szeredi 		err = fuse_rename_common(olddir, oldent, newdir, newent, flags,
7734237ba43SMiklos Szeredi 					 FUSE_RENAME2,
7744237ba43SMiklos Szeredi 					 sizeof(struct fuse_rename2_in));
7751560c974SMiklos Szeredi 		if (err == -ENOSYS) {
7761560c974SMiklos Szeredi 			fc->no_rename2 = 1;
7771560c974SMiklos Szeredi 			err = -EINVAL;
7781560c974SMiklos Szeredi 		}
7794237ba43SMiklos Szeredi 	} else {
7804237ba43SMiklos Szeredi 		err = fuse_rename_common(olddir, oldent, newdir, newent, 0,
7814237ba43SMiklos Szeredi 					 FUSE_RENAME,
7824237ba43SMiklos Szeredi 					 sizeof(struct fuse_rename_in));
7834237ba43SMiklos Szeredi 	}
7841560c974SMiklos Szeredi 
7854237ba43SMiklos Szeredi 	return err;
7864237ba43SMiklos Szeredi }
7874237ba43SMiklos Szeredi 
7889e6268dbSMiklos Szeredi static int fuse_link(struct dentry *entry, struct inode *newdir,
7899e6268dbSMiklos Szeredi 		     struct dentry *newent)
7909e6268dbSMiklos Szeredi {
7919e6268dbSMiklos Szeredi 	int err;
7929e6268dbSMiklos Szeredi 	struct fuse_link_in inarg;
7932b0143b5SDavid Howells 	struct inode *inode = d_inode(entry);
7949e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
7957078187aSMiklos Szeredi 	FUSE_ARGS(args);
7969e6268dbSMiklos Szeredi 
7979e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
7989e6268dbSMiklos Szeredi 	inarg.oldnodeid = get_node_id(inode);
799*d5b48543SMiklos Szeredi 	args.opcode = FUSE_LINK;
800*d5b48543SMiklos Szeredi 	args.in_numargs = 2;
801*d5b48543SMiklos Szeredi 	args.in_args[0].size = sizeof(inarg);
802*d5b48543SMiklos Szeredi 	args.in_args[0].value = &inarg;
803*d5b48543SMiklos Szeredi 	args.in_args[1].size = newent->d_name.len + 1;
804*d5b48543SMiklos Szeredi 	args.in_args[1].value = newent->d_name.name;
8057078187aSMiklos Szeredi 	err = create_new_entry(fc, &args, newdir, newent, inode->i_mode);
8069e6268dbSMiklos Szeredi 	/* Contrary to "normal" filesystems it can happen that link
8079e6268dbSMiklos Szeredi 	   makes two "logical" inodes point to the same "physical"
8089e6268dbSMiklos Szeredi 	   inode.  We invalidate the attributes of the old one, so it
8099e6268dbSMiklos Szeredi 	   will reflect changes in the backing inode (link count,
8109e6268dbSMiklos Szeredi 	   etc.)
8119e6268dbSMiklos Szeredi 	*/
812ac45d613SMiklos Szeredi 	if (!err) {
813ac45d613SMiklos Szeredi 		struct fuse_inode *fi = get_fuse_inode(inode);
814ac45d613SMiklos Szeredi 
815f15ecfefSKirill Tkhai 		spin_lock(&fi->lock);
8164510d86fSKirill Tkhai 		fi->attr_version = atomic64_inc_return(&fc->attr_version);
817ac45d613SMiklos Szeredi 		inc_nlink(inode);
818f15ecfefSKirill Tkhai 		spin_unlock(&fi->lock);
8199e6268dbSMiklos Szeredi 		fuse_invalidate_attr(inode);
82031f3267bSMaxim Patlasov 		fuse_update_ctime(inode);
821ac45d613SMiklos Szeredi 	} else if (err == -EINTR) {
822ac45d613SMiklos Szeredi 		fuse_invalidate_attr(inode);
823ac45d613SMiklos Szeredi 	}
8249e6268dbSMiklos Szeredi 	return err;
8259e6268dbSMiklos Szeredi }
8269e6268dbSMiklos Szeredi 
8271fb69e78SMiklos Szeredi static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
8281fb69e78SMiklos Szeredi 			  struct kstat *stat)
8291fb69e78SMiklos Szeredi {
830203627bbSMiklos Szeredi 	unsigned int blkbits;
8318373200bSPavel Emelyanov 	struct fuse_conn *fc = get_fuse_conn(inode);
8328373200bSPavel Emelyanov 
8338373200bSPavel Emelyanov 	/* see the comment in fuse_change_attributes() */
834b0aa7606SMaxim Patlasov 	if (fc->writeback_cache && S_ISREG(inode->i_mode)) {
8358373200bSPavel Emelyanov 		attr->size = i_size_read(inode);
836b0aa7606SMaxim Patlasov 		attr->mtime = inode->i_mtime.tv_sec;
837b0aa7606SMaxim Patlasov 		attr->mtimensec = inode->i_mtime.tv_nsec;
83831f3267bSMaxim Patlasov 		attr->ctime = inode->i_ctime.tv_sec;
83931f3267bSMaxim Patlasov 		attr->ctimensec = inode->i_ctime.tv_nsec;
840b0aa7606SMaxim Patlasov 	}
841203627bbSMiklos Szeredi 
8421fb69e78SMiklos Szeredi 	stat->dev = inode->i_sb->s_dev;
8431fb69e78SMiklos Szeredi 	stat->ino = attr->ino;
8441fb69e78SMiklos Szeredi 	stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
8451fb69e78SMiklos Szeredi 	stat->nlink = attr->nlink;
8468cb08329SEric W. Biederman 	stat->uid = make_kuid(fc->user_ns, attr->uid);
8478cb08329SEric W. Biederman 	stat->gid = make_kgid(fc->user_ns, attr->gid);
8481fb69e78SMiklos Szeredi 	stat->rdev = inode->i_rdev;
8491fb69e78SMiklos Szeredi 	stat->atime.tv_sec = attr->atime;
8501fb69e78SMiklos Szeredi 	stat->atime.tv_nsec = attr->atimensec;
8511fb69e78SMiklos Szeredi 	stat->mtime.tv_sec = attr->mtime;
8521fb69e78SMiklos Szeredi 	stat->mtime.tv_nsec = attr->mtimensec;
8531fb69e78SMiklos Szeredi 	stat->ctime.tv_sec = attr->ctime;
8541fb69e78SMiklos Szeredi 	stat->ctime.tv_nsec = attr->ctimensec;
8551fb69e78SMiklos Szeredi 	stat->size = attr->size;
8561fb69e78SMiklos Szeredi 	stat->blocks = attr->blocks;
857203627bbSMiklos Szeredi 
858203627bbSMiklos Szeredi 	if (attr->blksize != 0)
859203627bbSMiklos Szeredi 		blkbits = ilog2(attr->blksize);
860203627bbSMiklos Szeredi 	else
861203627bbSMiklos Szeredi 		blkbits = inode->i_sb->s_blocksize_bits;
862203627bbSMiklos Szeredi 
863203627bbSMiklos Szeredi 	stat->blksize = 1 << blkbits;
8641fb69e78SMiklos Szeredi }
8651fb69e78SMiklos Szeredi 
866c79e322fSMiklos Szeredi static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
867c79e322fSMiklos Szeredi 			   struct file *file)
868e5e5558eSMiklos Szeredi {
869e5e5558eSMiklos Szeredi 	int err;
870c79e322fSMiklos Szeredi 	struct fuse_getattr_in inarg;
871c79e322fSMiklos Szeredi 	struct fuse_attr_out outarg;
872e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
8737078187aSMiklos Szeredi 	FUSE_ARGS(args);
8741fb69e78SMiklos Szeredi 	u64 attr_version;
8751fb69e78SMiklos Szeredi 
8767dca9fd3SMiklos Szeredi 	attr_version = fuse_get_attr_version(fc);
8771fb69e78SMiklos Szeredi 
878c79e322fSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
8790e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
880c79e322fSMiklos Szeredi 	/* Directories have separate file-handle space */
881c79e322fSMiklos Szeredi 	if (file && S_ISREG(inode->i_mode)) {
882c79e322fSMiklos Szeredi 		struct fuse_file *ff = file->private_data;
883c79e322fSMiklos Szeredi 
884c79e322fSMiklos Szeredi 		inarg.getattr_flags |= FUSE_GETATTR_FH;
885c79e322fSMiklos Szeredi 		inarg.fh = ff->fh;
886c79e322fSMiklos Szeredi 	}
887*d5b48543SMiklos Szeredi 	args.opcode = FUSE_GETATTR;
888*d5b48543SMiklos Szeredi 	args.nodeid = get_node_id(inode);
889*d5b48543SMiklos Szeredi 	args.in_numargs = 1;
890*d5b48543SMiklos Szeredi 	args.in_args[0].size = sizeof(inarg);
891*d5b48543SMiklos Szeredi 	args.in_args[0].value = &inarg;
892*d5b48543SMiklos Szeredi 	args.out_numargs = 1;
893*d5b48543SMiklos Szeredi 	args.out_args[0].size = sizeof(outarg);
894*d5b48543SMiklos Szeredi 	args.out_args[0].value = &outarg;
8957078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
896e5e5558eSMiklos Szeredi 	if (!err) {
897c79e322fSMiklos Szeredi 		if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
898e5e5558eSMiklos Szeredi 			make_bad_inode(inode);
899e5e5558eSMiklos Szeredi 			err = -EIO;
900e5e5558eSMiklos Szeredi 		} else {
901c79e322fSMiklos Szeredi 			fuse_change_attributes(inode, &outarg.attr,
902c79e322fSMiklos Szeredi 					       attr_timeout(&outarg),
9031fb69e78SMiklos Szeredi 					       attr_version);
9041fb69e78SMiklos Szeredi 			if (stat)
905c79e322fSMiklos Szeredi 				fuse_fillattr(inode, &outarg.attr, stat);
906e5e5558eSMiklos Szeredi 		}
907e5e5558eSMiklos Szeredi 	}
908e5e5558eSMiklos Szeredi 	return err;
909e5e5558eSMiklos Szeredi }
910e5e5558eSMiklos Szeredi 
9115b97eeacSMiklos Szeredi static int fuse_update_get_attr(struct inode *inode, struct file *file,
9122f1e8196SMiklos Szeredi 				struct kstat *stat, u32 request_mask,
9132f1e8196SMiklos Szeredi 				unsigned int flags)
914bcb4be80SMiklos Szeredi {
915bcb4be80SMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
9165b97eeacSMiklos Szeredi 	int err = 0;
917bf5c1898SMiklos Szeredi 	bool sync;
918bcb4be80SMiklos Szeredi 
919bf5c1898SMiklos Szeredi 	if (flags & AT_STATX_FORCE_SYNC)
920bf5c1898SMiklos Szeredi 		sync = true;
921bf5c1898SMiklos Szeredi 	else if (flags & AT_STATX_DONT_SYNC)
922bf5c1898SMiklos Szeredi 		sync = false;
9232f1e8196SMiklos Szeredi 	else if (request_mask & READ_ONCE(fi->inval_mask))
9242f1e8196SMiklos Szeredi 		sync = true;
925bf5c1898SMiklos Szeredi 	else
926bf5c1898SMiklos Szeredi 		sync = time_before64(fi->i_time, get_jiffies_64());
927bf5c1898SMiklos Szeredi 
928bf5c1898SMiklos Szeredi 	if (sync) {
92960bcc88aSSeth Forshee 		forget_all_cached_acls(inode);
930bcb4be80SMiklos Szeredi 		err = fuse_do_getattr(inode, stat, file);
9315b97eeacSMiklos Szeredi 	} else if (stat) {
932bcb4be80SMiklos Szeredi 		generic_fillattr(inode, stat);
933bcb4be80SMiklos Szeredi 		stat->mode = fi->orig_i_mode;
93445c72cd7SPavel Shilovsky 		stat->ino = fi->orig_ino;
935bcb4be80SMiklos Szeredi 	}
936bcb4be80SMiklos Szeredi 
937bcb4be80SMiklos Szeredi 	return err;
938bcb4be80SMiklos Szeredi }
939bcb4be80SMiklos Szeredi 
9405b97eeacSMiklos Szeredi int fuse_update_attributes(struct inode *inode, struct file *file)
9415b97eeacSMiklos Szeredi {
942802dc049SMiklos Szeredi 	/* Do *not* need to get atime for internal purposes */
943802dc049SMiklos Szeredi 	return fuse_update_get_attr(inode, file, NULL,
944802dc049SMiklos Szeredi 				    STATX_BASIC_STATS & ~STATX_ATIME, 0);
9455b97eeacSMiklos Szeredi }
9465b97eeacSMiklos Szeredi 
9473b463ae0SJohn Muir int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid,
948451d0f59SJohn Muir 			     u64 child_nodeid, struct qstr *name)
9493b463ae0SJohn Muir {
9503b463ae0SJohn Muir 	int err = -ENOTDIR;
9513b463ae0SJohn Muir 	struct inode *parent;
9523b463ae0SJohn Muir 	struct dentry *dir;
9533b463ae0SJohn Muir 	struct dentry *entry;
9543b463ae0SJohn Muir 
9553b463ae0SJohn Muir 	parent = ilookup5(sb, parent_nodeid, fuse_inode_eq, &parent_nodeid);
9563b463ae0SJohn Muir 	if (!parent)
9573b463ae0SJohn Muir 		return -ENOENT;
9583b463ae0SJohn Muir 
9595955102cSAl Viro 	inode_lock(parent);
9603b463ae0SJohn Muir 	if (!S_ISDIR(parent->i_mode))
9613b463ae0SJohn Muir 		goto unlock;
9623b463ae0SJohn Muir 
9633b463ae0SJohn Muir 	err = -ENOENT;
9643b463ae0SJohn Muir 	dir = d_find_alias(parent);
9653b463ae0SJohn Muir 	if (!dir)
9663b463ae0SJohn Muir 		goto unlock;
9673b463ae0SJohn Muir 
9688387ff25SLinus Torvalds 	name->hash = full_name_hash(dir, name->name, name->len);
9693b463ae0SJohn Muir 	entry = d_lookup(dir, name);
9703b463ae0SJohn Muir 	dput(dir);
9713b463ae0SJohn Muir 	if (!entry)
9723b463ae0SJohn Muir 		goto unlock;
9733b463ae0SJohn Muir 
974261aaba7SMiklos Szeredi 	fuse_dir_changed(parent);
9753b463ae0SJohn Muir 	fuse_invalidate_entry(entry);
976451d0f59SJohn Muir 
9772b0143b5SDavid Howells 	if (child_nodeid != 0 && d_really_is_positive(entry)) {
9785955102cSAl Viro 		inode_lock(d_inode(entry));
9792b0143b5SDavid Howells 		if (get_node_id(d_inode(entry)) != child_nodeid) {
980451d0f59SJohn Muir 			err = -ENOENT;
981451d0f59SJohn Muir 			goto badentry;
982451d0f59SJohn Muir 		}
983451d0f59SJohn Muir 		if (d_mountpoint(entry)) {
984451d0f59SJohn Muir 			err = -EBUSY;
985451d0f59SJohn Muir 			goto badentry;
986451d0f59SJohn Muir 		}
987e36cb0b8SDavid Howells 		if (d_is_dir(entry)) {
988451d0f59SJohn Muir 			shrink_dcache_parent(entry);
989451d0f59SJohn Muir 			if (!simple_empty(entry)) {
990451d0f59SJohn Muir 				err = -ENOTEMPTY;
991451d0f59SJohn Muir 				goto badentry;
992451d0f59SJohn Muir 			}
9932b0143b5SDavid Howells 			d_inode(entry)->i_flags |= S_DEAD;
994451d0f59SJohn Muir 		}
995451d0f59SJohn Muir 		dont_mount(entry);
9962b0143b5SDavid Howells 		clear_nlink(d_inode(entry));
9973b463ae0SJohn Muir 		err = 0;
998451d0f59SJohn Muir  badentry:
9995955102cSAl Viro 		inode_unlock(d_inode(entry));
1000451d0f59SJohn Muir 		if (!err)
1001451d0f59SJohn Muir 			d_delete(entry);
1002451d0f59SJohn Muir 	} else {
1003451d0f59SJohn Muir 		err = 0;
1004451d0f59SJohn Muir 	}
1005451d0f59SJohn Muir 	dput(entry);
10063b463ae0SJohn Muir 
10073b463ae0SJohn Muir  unlock:
10085955102cSAl Viro 	inode_unlock(parent);
10093b463ae0SJohn Muir 	iput(parent);
10103b463ae0SJohn Muir 	return err;
10113b463ae0SJohn Muir }
10123b463ae0SJohn Muir 
101387729a55SMiklos Szeredi /*
101487729a55SMiklos Szeredi  * Calling into a user-controlled filesystem gives the filesystem
1015c2132c1bSAnatol Pomozov  * daemon ptrace-like capabilities over the current process.  This
101687729a55SMiklos Szeredi  * means, that the filesystem daemon is able to record the exact
101787729a55SMiklos Szeredi  * filesystem operations performed, and can also control the behavior
101887729a55SMiklos Szeredi  * of the requester process in otherwise impossible ways.  For example
101987729a55SMiklos Szeredi  * it can delay the operation for arbitrary length of time allowing
102087729a55SMiklos Szeredi  * DoS against the requester.
102187729a55SMiklos Szeredi  *
102287729a55SMiklos Szeredi  * For this reason only those processes can call into the filesystem,
102387729a55SMiklos Szeredi  * for which the owner of the mount has ptrace privilege.  This
102487729a55SMiklos Szeredi  * excludes processes started by other users, suid or sgid processes.
102587729a55SMiklos Szeredi  */
1026c2132c1bSAnatol Pomozov int fuse_allow_current_process(struct fuse_conn *fc)
102787729a55SMiklos Szeredi {
1028c69e8d9cSDavid Howells 	const struct cred *cred;
1029c69e8d9cSDavid Howells 
103029433a29SMiklos Szeredi 	if (fc->allow_other)
103173f03c2bSSeth Forshee 		return current_in_userns(fc->user_ns);
103287729a55SMiklos Szeredi 
1033c2132c1bSAnatol Pomozov 	cred = current_cred();
1034499dcf20SEric W. Biederman 	if (uid_eq(cred->euid, fc->user_id) &&
1035499dcf20SEric W. Biederman 	    uid_eq(cred->suid, fc->user_id) &&
1036499dcf20SEric W. Biederman 	    uid_eq(cred->uid,  fc->user_id) &&
1037499dcf20SEric W. Biederman 	    gid_eq(cred->egid, fc->group_id) &&
1038499dcf20SEric W. Biederman 	    gid_eq(cred->sgid, fc->group_id) &&
1039499dcf20SEric W. Biederman 	    gid_eq(cred->gid,  fc->group_id))
1040c2132c1bSAnatol Pomozov 		return 1;
104187729a55SMiklos Szeredi 
1042c2132c1bSAnatol Pomozov 	return 0;
104387729a55SMiklos Szeredi }
104487729a55SMiklos Szeredi 
104531d40d74SMiklos Szeredi static int fuse_access(struct inode *inode, int mask)
104631d40d74SMiklos Szeredi {
104731d40d74SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
10487078187aSMiklos Szeredi 	FUSE_ARGS(args);
104931d40d74SMiklos Szeredi 	struct fuse_access_in inarg;
105031d40d74SMiklos Szeredi 	int err;
105131d40d74SMiklos Szeredi 
1052698fa1d1SMiklos Szeredi 	BUG_ON(mask & MAY_NOT_BLOCK);
1053698fa1d1SMiklos Szeredi 
105431d40d74SMiklos Szeredi 	if (fc->no_access)
105531d40d74SMiklos Szeredi 		return 0;
105631d40d74SMiklos Szeredi 
105731d40d74SMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
1058e6305c43SAl Viro 	inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC);
1059*d5b48543SMiklos Szeredi 	args.opcode = FUSE_ACCESS;
1060*d5b48543SMiklos Szeredi 	args.nodeid = get_node_id(inode);
1061*d5b48543SMiklos Szeredi 	args.in_numargs = 1;
1062*d5b48543SMiklos Szeredi 	args.in_args[0].size = sizeof(inarg);
1063*d5b48543SMiklos Szeredi 	args.in_args[0].value = &inarg;
10647078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
106531d40d74SMiklos Szeredi 	if (err == -ENOSYS) {
106631d40d74SMiklos Szeredi 		fc->no_access = 1;
106731d40d74SMiklos Szeredi 		err = 0;
106831d40d74SMiklos Szeredi 	}
106931d40d74SMiklos Szeredi 	return err;
107031d40d74SMiklos Szeredi }
107131d40d74SMiklos Szeredi 
107210556cb2SAl Viro static int fuse_perm_getattr(struct inode *inode, int mask)
107319690ddbSMiklos Szeredi {
107410556cb2SAl Viro 	if (mask & MAY_NOT_BLOCK)
107519690ddbSMiklos Szeredi 		return -ECHILD;
107619690ddbSMiklos Szeredi 
107760bcc88aSSeth Forshee 	forget_all_cached_acls(inode);
107819690ddbSMiklos Szeredi 	return fuse_do_getattr(inode, NULL, NULL);
107919690ddbSMiklos Szeredi }
108019690ddbSMiklos Szeredi 
10816f9f1180SMiklos Szeredi /*
10826f9f1180SMiklos Szeredi  * Check permission.  The two basic access models of FUSE are:
10836f9f1180SMiklos Szeredi  *
10846f9f1180SMiklos Szeredi  * 1) Local access checking ('default_permissions' mount option) based
10856f9f1180SMiklos Szeredi  * on file mode.  This is the plain old disk filesystem permission
10866f9f1180SMiklos Szeredi  * modell.
10876f9f1180SMiklos Szeredi  *
10886f9f1180SMiklos Szeredi  * 2) "Remote" access checking, where server is responsible for
10896f9f1180SMiklos Szeredi  * checking permission in each inode operation.  An exception to this
10906f9f1180SMiklos Szeredi  * is if ->permission() was invoked from sys_access() in which case an
10916f9f1180SMiklos Szeredi  * access request is sent.  Execute permission is still checked
10926f9f1180SMiklos Szeredi  * locally based on file mode.
10936f9f1180SMiklos Szeredi  */
109410556cb2SAl Viro static int fuse_permission(struct inode *inode, int mask)
1095e5e5558eSMiklos Szeredi {
1096e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1097244f6385SMiklos Szeredi 	bool refreshed = false;
1098244f6385SMiklos Szeredi 	int err = 0;
1099e5e5558eSMiklos Szeredi 
1100c2132c1bSAnatol Pomozov 	if (!fuse_allow_current_process(fc))
1101e5e5558eSMiklos Szeredi 		return -EACCES;
1102244f6385SMiklos Szeredi 
1103244f6385SMiklos Szeredi 	/*
1104e8e96157SMiklos Szeredi 	 * If attributes are needed, refresh them before proceeding
1105244f6385SMiklos Szeredi 	 */
110629433a29SMiklos Szeredi 	if (fc->default_permissions ||
1107e8e96157SMiklos Szeredi 	    ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
110819690ddbSMiklos Szeredi 		struct fuse_inode *fi = get_fuse_inode(inode);
1109d233c7ddSMiklos Szeredi 		u32 perm_mask = STATX_MODE | STATX_UID | STATX_GID;
111019690ddbSMiklos Szeredi 
1111d233c7ddSMiklos Szeredi 		if (perm_mask & READ_ONCE(fi->inval_mask) ||
1112d233c7ddSMiklos Szeredi 		    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 
11525571f1e6SDan Schatzberg static int fuse_readlink_page(struct inode *inode, struct page *page)
1153e5e5558eSMiklos Szeredi {
1154e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
11555571f1e6SDan Schatzberg 	struct fuse_req *req;
11565571f1e6SDan Schatzberg 	int err;
1157e5e5558eSMiklos Szeredi 
11585571f1e6SDan Schatzberg 	req = fuse_get_req(fc, 1);
11595571f1e6SDan Schatzberg 	if (IS_ERR(req))
11605571f1e6SDan Schatzberg 		return PTR_ERR(req);
11616b255391SAl Viro 
11625571f1e6SDan Schatzberg 	req->out.page_zeroing = 1;
11635571f1e6SDan Schatzberg 	req->out.argpages = 1;
11645571f1e6SDan Schatzberg 	req->num_pages = 1;
11655571f1e6SDan Schatzberg 	req->pages[0] = page;
11665571f1e6SDan Schatzberg 	req->page_descs[0].length = PAGE_SIZE - 1;
11675571f1e6SDan Schatzberg 	req->in.h.opcode = FUSE_READLINK;
11685571f1e6SDan Schatzberg 	req->in.h.nodeid = get_node_id(inode);
11695571f1e6SDan Schatzberg 	req->out.argvar = 1;
11705571f1e6SDan Schatzberg 	req->out.numargs = 1;
11715571f1e6SDan Schatzberg 	req->out.args[0].size = PAGE_SIZE - 1;
11725571f1e6SDan Schatzberg 	fuse_request_send(fc, req);
11735571f1e6SDan Schatzberg 	err = req->out.h.error;
11747078187aSMiklos Szeredi 
11755571f1e6SDan Schatzberg 	if (!err) {
11765571f1e6SDan Schatzberg 		char *link = page_address(page);
11775571f1e6SDan Schatzberg 		size_t len = req->out.args[0].size;
11785571f1e6SDan Schatzberg 
11795571f1e6SDan Schatzberg 		BUG_ON(len >= PAGE_SIZE);
11805571f1e6SDan Schatzberg 		link[len] = '\0';
11817078187aSMiklos Szeredi 	}
11825571f1e6SDan Schatzberg 
11835571f1e6SDan Schatzberg 	fuse_put_request(fc, req);
1184451418fcSAndrew Gallagher 	fuse_invalidate_atime(inode);
11855571f1e6SDan Schatzberg 
11865571f1e6SDan Schatzberg 	return err;
11875571f1e6SDan Schatzberg }
11885571f1e6SDan Schatzberg 
11895571f1e6SDan Schatzberg static const char *fuse_get_link(struct dentry *dentry, struct inode *inode,
11905571f1e6SDan Schatzberg 				 struct delayed_call *callback)
11915571f1e6SDan Schatzberg {
11925571f1e6SDan Schatzberg 	struct fuse_conn *fc = get_fuse_conn(inode);
11935571f1e6SDan Schatzberg 	struct page *page;
11945571f1e6SDan Schatzberg 	int err;
11955571f1e6SDan Schatzberg 
11965571f1e6SDan Schatzberg 	err = -EIO;
11975571f1e6SDan Schatzberg 	if (is_bad_inode(inode))
11985571f1e6SDan Schatzberg 		goto out_err;
11995571f1e6SDan Schatzberg 
12005571f1e6SDan Schatzberg 	if (fc->cache_symlinks)
12015571f1e6SDan Schatzberg 		return page_get_link(dentry, inode, callback);
12025571f1e6SDan Schatzberg 
12035571f1e6SDan Schatzberg 	err = -ECHILD;
12045571f1e6SDan Schatzberg 	if (!dentry)
12055571f1e6SDan Schatzberg 		goto out_err;
12065571f1e6SDan Schatzberg 
12075571f1e6SDan Schatzberg 	page = alloc_page(GFP_KERNEL);
12085571f1e6SDan Schatzberg 	err = -ENOMEM;
12095571f1e6SDan Schatzberg 	if (!page)
12105571f1e6SDan Schatzberg 		goto out_err;
12115571f1e6SDan Schatzberg 
12125571f1e6SDan Schatzberg 	err = fuse_readlink_page(inode, page);
12135571f1e6SDan Schatzberg 	if (err) {
12145571f1e6SDan Schatzberg 		__free_page(page);
12155571f1e6SDan Schatzberg 		goto out_err;
12165571f1e6SDan Schatzberg 	}
12175571f1e6SDan Schatzberg 
12185571f1e6SDan Schatzberg 	set_delayed_call(callback, page_put_link, page);
12195571f1e6SDan Schatzberg 
12205571f1e6SDan Schatzberg 	return page_address(page);
12215571f1e6SDan Schatzberg 
12225571f1e6SDan Schatzberg out_err:
12235571f1e6SDan Schatzberg 	return ERR_PTR(err);
1224e5e5558eSMiklos Szeredi }
1225e5e5558eSMiklos Szeredi 
1226e5e5558eSMiklos Szeredi static int fuse_dir_open(struct inode *inode, struct file *file)
1227e5e5558eSMiklos Szeredi {
122891fe96b4SMiklos Szeredi 	return fuse_open_common(inode, file, true);
1229e5e5558eSMiklos Szeredi }
1230e5e5558eSMiklos Szeredi 
1231e5e5558eSMiklos Szeredi static int fuse_dir_release(struct inode *inode, struct file *file)
1232e5e5558eSMiklos Szeredi {
12332e64ff15SChad Austin 	fuse_release_common(file, true);
12348b0797a4SMiklos Szeredi 
12358b0797a4SMiklos Szeredi 	return 0;
1236e5e5558eSMiklos Szeredi }
1237e5e5558eSMiklos Szeredi 
123802c24a82SJosef Bacik static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end,
123902c24a82SJosef Bacik 			  int datasync)
124082547981SMiklos Szeredi {
1241a9c2d1e8SMiklos Szeredi 	struct inode *inode = file->f_mapping->host;
1242a9c2d1e8SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1243a9c2d1e8SMiklos Szeredi 	int err;
1244a9c2d1e8SMiklos Szeredi 
1245a9c2d1e8SMiklos Szeredi 	if (is_bad_inode(inode))
1246a9c2d1e8SMiklos Szeredi 		return -EIO;
1247a9c2d1e8SMiklos Szeredi 
1248a9c2d1e8SMiklos Szeredi 	if (fc->no_fsyncdir)
1249a9c2d1e8SMiklos Szeredi 		return 0;
1250a9c2d1e8SMiklos Szeredi 
1251a9c2d1e8SMiklos Szeredi 	inode_lock(inode);
1252a9c2d1e8SMiklos Szeredi 	err = fuse_fsync_common(file, start, end, datasync, FUSE_FSYNCDIR);
1253a9c2d1e8SMiklos Szeredi 	if (err == -ENOSYS) {
1254a9c2d1e8SMiklos Szeredi 		fc->no_fsyncdir = 1;
1255a9c2d1e8SMiklos Szeredi 		err = 0;
1256a9c2d1e8SMiklos Szeredi 	}
1257a9c2d1e8SMiklos Szeredi 	inode_unlock(inode);
1258a9c2d1e8SMiklos Szeredi 
1259a9c2d1e8SMiklos Szeredi 	return err;
126082547981SMiklos Szeredi }
126182547981SMiklos Szeredi 
1262b18da0c5SMiklos Szeredi static long fuse_dir_ioctl(struct file *file, unsigned int cmd,
1263b18da0c5SMiklos Szeredi 			    unsigned long arg)
1264b18da0c5SMiklos Szeredi {
1265b18da0c5SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1266b18da0c5SMiklos Szeredi 
1267b18da0c5SMiklos Szeredi 	/* FUSE_IOCTL_DIR only supported for API version >= 7.18 */
1268b18da0c5SMiklos Szeredi 	if (fc->minor < 18)
1269b18da0c5SMiklos Szeredi 		return -ENOTTY;
1270b18da0c5SMiklos Szeredi 
1271b18da0c5SMiklos Szeredi 	return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR);
1272b18da0c5SMiklos Szeredi }
1273b18da0c5SMiklos Szeredi 
1274b18da0c5SMiklos Szeredi static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd,
1275b18da0c5SMiklos Szeredi 				   unsigned long arg)
1276b18da0c5SMiklos Szeredi {
1277b18da0c5SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1278b18da0c5SMiklos Szeredi 
1279b18da0c5SMiklos Szeredi 	if (fc->minor < 18)
1280b18da0c5SMiklos Szeredi 		return -ENOTTY;
1281b18da0c5SMiklos Szeredi 
1282b18da0c5SMiklos Szeredi 	return fuse_ioctl_common(file, cmd, arg,
1283b18da0c5SMiklos Szeredi 				 FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR);
1284b18da0c5SMiklos Szeredi }
1285b18da0c5SMiklos Szeredi 
1286b0aa7606SMaxim Patlasov static bool update_mtime(unsigned ivalid, bool trust_local_mtime)
128717637cbaSMiklos Szeredi {
128817637cbaSMiklos Szeredi 	/* Always update if mtime is explicitly set  */
128917637cbaSMiklos Szeredi 	if (ivalid & ATTR_MTIME_SET)
129017637cbaSMiklos Szeredi 		return true;
129117637cbaSMiklos Szeredi 
1292b0aa7606SMaxim Patlasov 	/* Or if kernel i_mtime is the official one */
1293b0aa7606SMaxim Patlasov 	if (trust_local_mtime)
1294b0aa7606SMaxim Patlasov 		return true;
1295b0aa7606SMaxim Patlasov 
129617637cbaSMiklos Szeredi 	/* If it's an open(O_TRUNC) or an ftruncate(), don't update */
129717637cbaSMiklos Szeredi 	if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
129817637cbaSMiklos Szeredi 		return false;
129917637cbaSMiklos Szeredi 
130017637cbaSMiklos Szeredi 	/* In all other cases update */
130117637cbaSMiklos Szeredi 	return true;
130217637cbaSMiklos Szeredi }
130317637cbaSMiklos Szeredi 
13048cb08329SEric W. Biederman static void iattr_to_fattr(struct fuse_conn *fc, struct iattr *iattr,
13058cb08329SEric W. Biederman 			   struct fuse_setattr_in *arg, bool trust_local_cmtime)
13069e6268dbSMiklos Szeredi {
13079e6268dbSMiklos Szeredi 	unsigned ivalid = iattr->ia_valid;
13089e6268dbSMiklos Szeredi 
13099e6268dbSMiklos Szeredi 	if (ivalid & ATTR_MODE)
1310befc649cSMiklos Szeredi 		arg->valid |= FATTR_MODE,   arg->mode = iattr->ia_mode;
13119e6268dbSMiklos Szeredi 	if (ivalid & ATTR_UID)
13128cb08329SEric W. Biederman 		arg->valid |= FATTR_UID,    arg->uid = from_kuid(fc->user_ns, iattr->ia_uid);
13139e6268dbSMiklos Szeredi 	if (ivalid & ATTR_GID)
13148cb08329SEric W. Biederman 		arg->valid |= FATTR_GID,    arg->gid = from_kgid(fc->user_ns, iattr->ia_gid);
13159e6268dbSMiklos Szeredi 	if (ivalid & ATTR_SIZE)
1316befc649cSMiklos Szeredi 		arg->valid |= FATTR_SIZE,   arg->size = iattr->ia_size;
131717637cbaSMiklos Szeredi 	if (ivalid & ATTR_ATIME) {
131817637cbaSMiklos Szeredi 		arg->valid |= FATTR_ATIME;
1319befc649cSMiklos Szeredi 		arg->atime = iattr->ia_atime.tv_sec;
132017637cbaSMiklos Szeredi 		arg->atimensec = iattr->ia_atime.tv_nsec;
132117637cbaSMiklos Szeredi 		if (!(ivalid & ATTR_ATIME_SET))
132217637cbaSMiklos Szeredi 			arg->valid |= FATTR_ATIME_NOW;
132317637cbaSMiklos Szeredi 	}
13243ad22c62SMaxim Patlasov 	if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, trust_local_cmtime)) {
132517637cbaSMiklos Szeredi 		arg->valid |= FATTR_MTIME;
1326befc649cSMiklos Szeredi 		arg->mtime = iattr->ia_mtime.tv_sec;
132717637cbaSMiklos Szeredi 		arg->mtimensec = iattr->ia_mtime.tv_nsec;
13283ad22c62SMaxim Patlasov 		if (!(ivalid & ATTR_MTIME_SET) && !trust_local_cmtime)
132917637cbaSMiklos Szeredi 			arg->valid |= FATTR_MTIME_NOW;
13309e6268dbSMiklos Szeredi 	}
13313ad22c62SMaxim Patlasov 	if ((ivalid & ATTR_CTIME) && trust_local_cmtime) {
13323ad22c62SMaxim Patlasov 		arg->valid |= FATTR_CTIME;
13333ad22c62SMaxim Patlasov 		arg->ctime = iattr->ia_ctime.tv_sec;
13343ad22c62SMaxim Patlasov 		arg->ctimensec = iattr->ia_ctime.tv_nsec;
13353ad22c62SMaxim Patlasov 	}
13369e6268dbSMiklos Szeredi }
13379e6268dbSMiklos Szeredi 
13386f9f1180SMiklos Szeredi /*
13393be5a52bSMiklos Szeredi  * Prevent concurrent writepages on inode
13403be5a52bSMiklos Szeredi  *
13413be5a52bSMiklos Szeredi  * This is done by adding a negative bias to the inode write counter
13423be5a52bSMiklos Szeredi  * and waiting for all pending writes to finish.
13433be5a52bSMiklos Szeredi  */
13443be5a52bSMiklos Szeredi void fuse_set_nowrite(struct inode *inode)
13453be5a52bSMiklos Szeredi {
13463be5a52bSMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
13473be5a52bSMiklos Szeredi 
13485955102cSAl Viro 	BUG_ON(!inode_is_locked(inode));
13493be5a52bSMiklos Szeredi 
1350f15ecfefSKirill Tkhai 	spin_lock(&fi->lock);
13513be5a52bSMiklos Szeredi 	BUG_ON(fi->writectr < 0);
13523be5a52bSMiklos Szeredi 	fi->writectr += FUSE_NOWRITE;
1353f15ecfefSKirill Tkhai 	spin_unlock(&fi->lock);
13543be5a52bSMiklos Szeredi 	wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE);
13553be5a52bSMiklos Szeredi }
13563be5a52bSMiklos Szeredi 
13573be5a52bSMiklos Szeredi /*
13583be5a52bSMiklos Szeredi  * Allow writepages on inode
13593be5a52bSMiklos Szeredi  *
13603be5a52bSMiklos Szeredi  * Remove the bias from the writecounter and send any queued
13613be5a52bSMiklos Szeredi  * writepages.
13623be5a52bSMiklos Szeredi  */
13633be5a52bSMiklos Szeredi static void __fuse_release_nowrite(struct inode *inode)
13643be5a52bSMiklos Szeredi {
13653be5a52bSMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
13663be5a52bSMiklos Szeredi 
13673be5a52bSMiklos Szeredi 	BUG_ON(fi->writectr != FUSE_NOWRITE);
13683be5a52bSMiklos Szeredi 	fi->writectr = 0;
13693be5a52bSMiklos Szeredi 	fuse_flush_writepages(inode);
13703be5a52bSMiklos Szeredi }
13713be5a52bSMiklos Szeredi 
13723be5a52bSMiklos Szeredi void fuse_release_nowrite(struct inode *inode)
13733be5a52bSMiklos Szeredi {
1374f15ecfefSKirill Tkhai 	struct fuse_inode *fi = get_fuse_inode(inode);
13753be5a52bSMiklos Szeredi 
1376f15ecfefSKirill Tkhai 	spin_lock(&fi->lock);
13773be5a52bSMiklos Szeredi 	__fuse_release_nowrite(inode);
1378f15ecfefSKirill Tkhai 	spin_unlock(&fi->lock);
13793be5a52bSMiklos Szeredi }
13803be5a52bSMiklos Szeredi 
13817078187aSMiklos Szeredi static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_args *args,
1382b0aa7606SMaxim Patlasov 			      struct inode *inode,
1383b0aa7606SMaxim Patlasov 			      struct fuse_setattr_in *inarg_p,
1384b0aa7606SMaxim Patlasov 			      struct fuse_attr_out *outarg_p)
1385b0aa7606SMaxim Patlasov {
1386*d5b48543SMiklos Szeredi 	args->opcode = FUSE_SETATTR;
1387*d5b48543SMiklos Szeredi 	args->nodeid = get_node_id(inode);
1388*d5b48543SMiklos Szeredi 	args->in_numargs = 1;
1389*d5b48543SMiklos Szeredi 	args->in_args[0].size = sizeof(*inarg_p);
1390*d5b48543SMiklos Szeredi 	args->in_args[0].value = inarg_p;
1391*d5b48543SMiklos Szeredi 	args->out_numargs = 1;
1392*d5b48543SMiklos Szeredi 	args->out_args[0].size = sizeof(*outarg_p);
1393*d5b48543SMiklos Szeredi 	args->out_args[0].value = outarg_p;
1394b0aa7606SMaxim Patlasov }
1395b0aa7606SMaxim Patlasov 
1396b0aa7606SMaxim Patlasov /*
1397b0aa7606SMaxim Patlasov  * Flush inode->i_mtime to the server
1398b0aa7606SMaxim Patlasov  */
1399ab9e13f7SMaxim Patlasov int fuse_flush_times(struct inode *inode, struct fuse_file *ff)
1400b0aa7606SMaxim Patlasov {
1401b0aa7606SMaxim Patlasov 	struct fuse_conn *fc = get_fuse_conn(inode);
14027078187aSMiklos Szeredi 	FUSE_ARGS(args);
1403b0aa7606SMaxim Patlasov 	struct fuse_setattr_in inarg;
1404b0aa7606SMaxim Patlasov 	struct fuse_attr_out outarg;
1405b0aa7606SMaxim Patlasov 
1406b0aa7606SMaxim Patlasov 	memset(&inarg, 0, sizeof(inarg));
1407b0aa7606SMaxim Patlasov 	memset(&outarg, 0, sizeof(outarg));
1408b0aa7606SMaxim Patlasov 
1409ab9e13f7SMaxim Patlasov 	inarg.valid = FATTR_MTIME;
1410b0aa7606SMaxim Patlasov 	inarg.mtime = inode->i_mtime.tv_sec;
1411b0aa7606SMaxim Patlasov 	inarg.mtimensec = inode->i_mtime.tv_nsec;
1412ab9e13f7SMaxim Patlasov 	if (fc->minor >= 23) {
1413ab9e13f7SMaxim Patlasov 		inarg.valid |= FATTR_CTIME;
1414ab9e13f7SMaxim Patlasov 		inarg.ctime = inode->i_ctime.tv_sec;
1415ab9e13f7SMaxim Patlasov 		inarg.ctimensec = inode->i_ctime.tv_nsec;
1416ab9e13f7SMaxim Patlasov 	}
14171e18bda8SMiklos Szeredi 	if (ff) {
14181e18bda8SMiklos Szeredi 		inarg.valid |= FATTR_FH;
14191e18bda8SMiklos Szeredi 		inarg.fh = ff->fh;
14201e18bda8SMiklos Szeredi 	}
14217078187aSMiklos Szeredi 	fuse_setattr_fill(fc, &args, inode, &inarg, &outarg);
1422b0aa7606SMaxim Patlasov 
14237078187aSMiklos Szeredi 	return fuse_simple_request(fc, &args);
1424b0aa7606SMaxim Patlasov }
1425b0aa7606SMaxim Patlasov 
14263be5a52bSMiklos Szeredi /*
14276f9f1180SMiklos Szeredi  * Set attributes, and at the same time refresh them.
14286f9f1180SMiklos Szeredi  *
14296f9f1180SMiklos Szeredi  * Truncation is slightly complicated, because the 'truncate' request
14306f9f1180SMiklos Szeredi  * may fail, in which case we don't want to touch the mapping.
14319ffbb916SMiklos Szeredi  * vmtruncate() doesn't allow for this case, so do the rlimit checking
14329ffbb916SMiklos Szeredi  * and the actual truncation by hand.
14336f9f1180SMiklos Szeredi  */
143462490330SJan Kara int fuse_do_setattr(struct dentry *dentry, struct iattr *attr,
143549d4914fSMiklos Szeredi 		    struct file *file)
14369e6268dbSMiklos Szeredi {
143762490330SJan Kara 	struct inode *inode = d_inode(dentry);
14389e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
143906a7c3c2SMaxim Patlasov 	struct fuse_inode *fi = get_fuse_inode(inode);
14407078187aSMiklos Szeredi 	FUSE_ARGS(args);
14419e6268dbSMiklos Szeredi 	struct fuse_setattr_in inarg;
14429e6268dbSMiklos Szeredi 	struct fuse_attr_out outarg;
14433be5a52bSMiklos Szeredi 	bool is_truncate = false;
14448373200bSPavel Emelyanov 	bool is_wb = fc->writeback_cache;
14453be5a52bSMiklos Szeredi 	loff_t oldsize;
14469e6268dbSMiklos Szeredi 	int err;
14473ad22c62SMaxim Patlasov 	bool trust_local_cmtime = is_wb && S_ISREG(inode->i_mode);
14489e6268dbSMiklos Szeredi 
144929433a29SMiklos Szeredi 	if (!fc->default_permissions)
1450db78b877SChristoph Hellwig 		attr->ia_valid |= ATTR_FORCE;
1451db78b877SChristoph Hellwig 
145231051c85SJan Kara 	err = setattr_prepare(dentry, attr);
14531e9a4ed9SMiklos Szeredi 	if (err)
14541e9a4ed9SMiklos Szeredi 		return err;
14551e9a4ed9SMiklos Szeredi 
14568d56adddSMiklos Szeredi 	if (attr->ia_valid & ATTR_OPEN) {
1457df0e91d4SMiklos Szeredi 		/* This is coming from open(..., ... | O_TRUNC); */
1458df0e91d4SMiklos Szeredi 		WARN_ON(!(attr->ia_valid & ATTR_SIZE));
1459df0e91d4SMiklos Szeredi 		WARN_ON(attr->ia_size != 0);
1460df0e91d4SMiklos Szeredi 		if (fc->atomic_o_trunc) {
1461df0e91d4SMiklos Szeredi 			/*
1462df0e91d4SMiklos Szeredi 			 * No need to send request to userspace, since actual
1463df0e91d4SMiklos Szeredi 			 * truncation has already been done by OPEN.  But still
1464df0e91d4SMiklos Szeredi 			 * need to truncate page cache.
1465df0e91d4SMiklos Szeredi 			 */
1466df0e91d4SMiklos Szeredi 			i_size_write(inode, 0);
1467df0e91d4SMiklos Szeredi 			truncate_pagecache(inode, 0);
14686ff958edSMiklos Szeredi 			return 0;
1469df0e91d4SMiklos Szeredi 		}
14708d56adddSMiklos Szeredi 		file = NULL;
14718d56adddSMiklos Szeredi 	}
14726ff958edSMiklos Szeredi 
1473ab2257e9SMiklos Szeredi 	if (attr->ia_valid & ATTR_SIZE) {
1474ab2257e9SMiklos Szeredi 		if (WARN_ON(!S_ISREG(inode->i_mode)))
1475ab2257e9SMiklos Szeredi 			return -EIO;
14763be5a52bSMiklos Szeredi 		is_truncate = true;
1477ab2257e9SMiklos Szeredi 	}
14789e6268dbSMiklos Szeredi 
147906a7c3c2SMaxim Patlasov 	if (is_truncate) {
14803be5a52bSMiklos Szeredi 		fuse_set_nowrite(inode);
148106a7c3c2SMaxim Patlasov 		set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
14823ad22c62SMaxim Patlasov 		if (trust_local_cmtime && attr->ia_size != inode->i_size)
14833ad22c62SMaxim Patlasov 			attr->ia_valid |= ATTR_MTIME | ATTR_CTIME;
148406a7c3c2SMaxim Patlasov 	}
14853be5a52bSMiklos Szeredi 
14869e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
14870e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
14888cb08329SEric W. Biederman 	iattr_to_fattr(fc, attr, &inarg, trust_local_cmtime);
148949d4914fSMiklos Szeredi 	if (file) {
149049d4914fSMiklos Szeredi 		struct fuse_file *ff = file->private_data;
149149d4914fSMiklos Szeredi 		inarg.valid |= FATTR_FH;
149249d4914fSMiklos Szeredi 		inarg.fh = ff->fh;
149349d4914fSMiklos Szeredi 	}
1494f3332114SMiklos Szeredi 	if (attr->ia_valid & ATTR_SIZE) {
1495f3332114SMiklos Szeredi 		/* For mandatory locking in truncate */
1496f3332114SMiklos Szeredi 		inarg.valid |= FATTR_LOCKOWNER;
1497f3332114SMiklos Szeredi 		inarg.lock_owner = fuse_lock_owner_id(fc, current->files);
1498f3332114SMiklos Szeredi 	}
14997078187aSMiklos Szeredi 	fuse_setattr_fill(fc, &args, inode, &inarg, &outarg);
15007078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
1501e00d2c2dSMiklos Szeredi 	if (err) {
1502e00d2c2dSMiklos Szeredi 		if (err == -EINTR)
1503e00d2c2dSMiklos Szeredi 			fuse_invalidate_attr(inode);
15043be5a52bSMiklos Szeredi 		goto error;
1505e00d2c2dSMiklos Szeredi 	}
1506e00d2c2dSMiklos Szeredi 
15079e6268dbSMiklos Szeredi 	if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
15089e6268dbSMiklos Szeredi 		make_bad_inode(inode);
15093be5a52bSMiklos Szeredi 		err = -EIO;
15103be5a52bSMiklos Szeredi 		goto error;
15119e6268dbSMiklos Szeredi 	}
15129e6268dbSMiklos Szeredi 
1513f15ecfefSKirill Tkhai 	spin_lock(&fi->lock);
1514b0aa7606SMaxim Patlasov 	/* the kernel maintains i_mtime locally */
15153ad22c62SMaxim Patlasov 	if (trust_local_cmtime) {
15163ad22c62SMaxim Patlasov 		if (attr->ia_valid & ATTR_MTIME)
1517b0aa7606SMaxim Patlasov 			inode->i_mtime = attr->ia_mtime;
15183ad22c62SMaxim Patlasov 		if (attr->ia_valid & ATTR_CTIME)
15193ad22c62SMaxim Patlasov 			inode->i_ctime = attr->ia_ctime;
15201e18bda8SMiklos Szeredi 		/* FIXME: clear I_DIRTY_SYNC? */
1521b0aa7606SMaxim Patlasov 	}
1522b0aa7606SMaxim Patlasov 
15233be5a52bSMiklos Szeredi 	fuse_change_attributes_common(inode, &outarg.attr,
15243be5a52bSMiklos Szeredi 				      attr_timeout(&outarg));
15253be5a52bSMiklos Szeredi 	oldsize = inode->i_size;
15268373200bSPavel Emelyanov 	/* see the comment in fuse_change_attributes() */
15278373200bSPavel Emelyanov 	if (!is_wb || is_truncate || !S_ISREG(inode->i_mode))
15283be5a52bSMiklos Szeredi 		i_size_write(inode, outarg.attr.size);
15293be5a52bSMiklos Szeredi 
15303be5a52bSMiklos Szeredi 	if (is_truncate) {
1531f15ecfefSKirill Tkhai 		/* NOTE: this may release/reacquire fi->lock */
15323be5a52bSMiklos Szeredi 		__fuse_release_nowrite(inode);
15333be5a52bSMiklos Szeredi 	}
1534f15ecfefSKirill Tkhai 	spin_unlock(&fi->lock);
15353be5a52bSMiklos Szeredi 
15363be5a52bSMiklos Szeredi 	/*
15373be5a52bSMiklos Szeredi 	 * Only call invalidate_inode_pages2() after removing
15383be5a52bSMiklos Szeredi 	 * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock.
15393be5a52bSMiklos Szeredi 	 */
15408373200bSPavel Emelyanov 	if ((is_truncate || !is_wb) &&
15418373200bSPavel Emelyanov 	    S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
15427caef267SKirill A. Shutemov 		truncate_pagecache(inode, outarg.attr.size);
15433be5a52bSMiklos Szeredi 		invalidate_inode_pages2(inode->i_mapping);
15443be5a52bSMiklos Szeredi 	}
15453be5a52bSMiklos Szeredi 
154606a7c3c2SMaxim Patlasov 	clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
1547e00d2c2dSMiklos Szeredi 	return 0;
15483be5a52bSMiklos Szeredi 
15493be5a52bSMiklos Szeredi error:
15503be5a52bSMiklos Szeredi 	if (is_truncate)
15513be5a52bSMiklos Szeredi 		fuse_release_nowrite(inode);
15523be5a52bSMiklos Szeredi 
155306a7c3c2SMaxim Patlasov 	clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
15543be5a52bSMiklos Szeredi 	return err;
15559e6268dbSMiklos Szeredi }
15569e6268dbSMiklos Szeredi 
155749d4914fSMiklos Szeredi static int fuse_setattr(struct dentry *entry, struct iattr *attr)
155849d4914fSMiklos Szeredi {
15592b0143b5SDavid Howells 	struct inode *inode = d_inode(entry);
15605e940c1dSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1561a09f99edSMiklos Szeredi 	struct file *file = (attr->ia_valid & ATTR_FILE) ? attr->ia_file : NULL;
15625e2b8828SMiklos Szeredi 	int ret;
1563efb9fa9eSMaxim Patlasov 
1564efb9fa9eSMaxim Patlasov 	if (!fuse_allow_current_process(get_fuse_conn(inode)))
1565efb9fa9eSMaxim Patlasov 		return -EACCES;
1566efb9fa9eSMaxim Patlasov 
1567a09f99edSMiklos Szeredi 	if (attr->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) {
1568a09f99edSMiklos Szeredi 		attr->ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID |
1569a09f99edSMiklos Szeredi 				    ATTR_MODE);
15705e940c1dSMiklos Szeredi 
1571a09f99edSMiklos Szeredi 		/*
15725e940c1dSMiklos Szeredi 		 * The only sane way to reliably kill suid/sgid is to do it in
15735e940c1dSMiklos Szeredi 		 * the userspace filesystem
15745e940c1dSMiklos Szeredi 		 *
15755e940c1dSMiklos Szeredi 		 * This should be done on write(), truncate() and chown().
15765e940c1dSMiklos Szeredi 		 */
15775e940c1dSMiklos Szeredi 		if (!fc->handle_killpriv) {
15785e940c1dSMiklos Szeredi 			/*
15795e940c1dSMiklos Szeredi 			 * ia_mode calculation may have used stale i_mode.
15805e940c1dSMiklos Szeredi 			 * Refresh and recalculate.
1581a09f99edSMiklos Szeredi 			 */
1582a09f99edSMiklos Szeredi 			ret = fuse_do_getattr(inode, NULL, file);
1583a09f99edSMiklos Szeredi 			if (ret)
1584a09f99edSMiklos Szeredi 				return ret;
1585a09f99edSMiklos Szeredi 
1586a09f99edSMiklos Szeredi 			attr->ia_mode = inode->i_mode;
1587c01638f5SMiklos Szeredi 			if (inode->i_mode & S_ISUID) {
1588a09f99edSMiklos Szeredi 				attr->ia_valid |= ATTR_MODE;
1589a09f99edSMiklos Szeredi 				attr->ia_mode &= ~S_ISUID;
1590a09f99edSMiklos Szeredi 			}
1591c01638f5SMiklos Szeredi 			if ((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
1592a09f99edSMiklos Szeredi 				attr->ia_valid |= ATTR_MODE;
1593a09f99edSMiklos Szeredi 				attr->ia_mode &= ~S_ISGID;
1594a09f99edSMiklos Szeredi 			}
1595a09f99edSMiklos Szeredi 		}
15965e940c1dSMiklos Szeredi 	}
1597a09f99edSMiklos Szeredi 	if (!attr->ia_valid)
1598a09f99edSMiklos Szeredi 		return 0;
1599a09f99edSMiklos Szeredi 
1600abb5a14fSLinus Torvalds 	ret = fuse_do_setattr(entry, attr, file);
16015e2b8828SMiklos Szeredi 	if (!ret) {
160260bcc88aSSeth Forshee 		/*
160360bcc88aSSeth Forshee 		 * If filesystem supports acls it may have updated acl xattrs in
160460bcc88aSSeth Forshee 		 * the filesystem, so forget cached acls for the inode.
160560bcc88aSSeth Forshee 		 */
160660bcc88aSSeth Forshee 		if (fc->posix_acl)
160760bcc88aSSeth Forshee 			forget_all_cached_acls(inode);
160860bcc88aSSeth Forshee 
16095e2b8828SMiklos Szeredi 		/* Directory mode changed, may need to revalidate access */
16105e2b8828SMiklos Szeredi 		if (d_is_dir(entry) && (attr->ia_valid & ATTR_MODE))
16115e2b8828SMiklos Szeredi 			fuse_invalidate_entry_cache(entry);
16125e2b8828SMiklos Szeredi 	}
16135e2b8828SMiklos Szeredi 	return ret;
161449d4914fSMiklos Szeredi }
161549d4914fSMiklos Szeredi 
1616a528d35eSDavid Howells static int fuse_getattr(const struct path *path, struct kstat *stat,
1617a528d35eSDavid Howells 			u32 request_mask, unsigned int flags)
1618e5e5558eSMiklos Szeredi {
1619a528d35eSDavid Howells 	struct inode *inode = d_inode(path->dentry);
1620244f6385SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1621244f6385SMiklos Szeredi 
1622c2132c1bSAnatol Pomozov 	if (!fuse_allow_current_process(fc))
1623244f6385SMiklos Szeredi 		return -EACCES;
1624244f6385SMiklos Szeredi 
16252f1e8196SMiklos Szeredi 	return fuse_update_get_attr(inode, NULL, stat, request_mask, flags);
1626e5e5558eSMiklos Szeredi }
1627e5e5558eSMiklos Szeredi 
1628754661f1SArjan van de Ven static const struct inode_operations fuse_dir_inode_operations = {
1629e5e5558eSMiklos Szeredi 	.lookup		= fuse_lookup,
16309e6268dbSMiklos Szeredi 	.mkdir		= fuse_mkdir,
16319e6268dbSMiklos Szeredi 	.symlink	= fuse_symlink,
16329e6268dbSMiklos Szeredi 	.unlink		= fuse_unlink,
16339e6268dbSMiklos Szeredi 	.rmdir		= fuse_rmdir,
16342773bf00SMiklos Szeredi 	.rename		= fuse_rename2,
16359e6268dbSMiklos Szeredi 	.link		= fuse_link,
16369e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
16379e6268dbSMiklos Szeredi 	.create		= fuse_create,
1638c8ccbe03SMiklos Szeredi 	.atomic_open	= fuse_atomic_open,
16399e6268dbSMiklos Szeredi 	.mknod		= fuse_mknod,
1640e5e5558eSMiklos Szeredi 	.permission	= fuse_permission,
1641e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
164292a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
164360bcc88aSSeth Forshee 	.get_acl	= fuse_get_acl,
164460bcc88aSSeth Forshee 	.set_acl	= fuse_set_acl,
1645e5e5558eSMiklos Szeredi };
1646e5e5558eSMiklos Szeredi 
16474b6f5d20SArjan van de Ven static const struct file_operations fuse_dir_operations = {
1648b6aeadedSMiklos Szeredi 	.llseek		= generic_file_llseek,
1649e5e5558eSMiklos Szeredi 	.read		= generic_read_dir,
1650d9b3dbdcSAl Viro 	.iterate_shared	= fuse_readdir,
1651e5e5558eSMiklos Szeredi 	.open		= fuse_dir_open,
1652e5e5558eSMiklos Szeredi 	.release	= fuse_dir_release,
165382547981SMiklos Szeredi 	.fsync		= fuse_dir_fsync,
1654b18da0c5SMiklos Szeredi 	.unlocked_ioctl	= fuse_dir_ioctl,
1655b18da0c5SMiklos Szeredi 	.compat_ioctl	= fuse_dir_compat_ioctl,
1656e5e5558eSMiklos Szeredi };
1657e5e5558eSMiklos Szeredi 
1658754661f1SArjan van de Ven static const struct inode_operations fuse_common_inode_operations = {
16599e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
1660e5e5558eSMiklos Szeredi 	.permission	= fuse_permission,
1661e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
166292a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
166360bcc88aSSeth Forshee 	.get_acl	= fuse_get_acl,
166460bcc88aSSeth Forshee 	.set_acl	= fuse_set_acl,
1665e5e5558eSMiklos Szeredi };
1666e5e5558eSMiklos Szeredi 
1667754661f1SArjan van de Ven static const struct inode_operations fuse_symlink_inode_operations = {
16689e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
16696b255391SAl Viro 	.get_link	= fuse_get_link,
1670e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
167192a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
1672e5e5558eSMiklos Szeredi };
1673e5e5558eSMiklos Szeredi 
1674e5e5558eSMiklos Szeredi void fuse_init_common(struct inode *inode)
1675e5e5558eSMiklos Szeredi {
1676e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_common_inode_operations;
1677e5e5558eSMiklos Szeredi }
1678e5e5558eSMiklos Szeredi 
1679e5e5558eSMiklos Szeredi void fuse_init_dir(struct inode *inode)
1680e5e5558eSMiklos Szeredi {
1681ab2257e9SMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
1682ab2257e9SMiklos Szeredi 
1683e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_dir_inode_operations;
1684e5e5558eSMiklos Szeredi 	inode->i_fop = &fuse_dir_operations;
1685ab2257e9SMiklos Szeredi 
1686ab2257e9SMiklos Szeredi 	spin_lock_init(&fi->rdc.lock);
1687ab2257e9SMiklos Szeredi 	fi->rdc.cached = false;
1688ab2257e9SMiklos Szeredi 	fi->rdc.size = 0;
1689ab2257e9SMiklos Szeredi 	fi->rdc.pos = 0;
1690ab2257e9SMiklos Szeredi 	fi->rdc.version = 0;
1691e5e5558eSMiklos Szeredi }
1692e5e5558eSMiklos Szeredi 
16935571f1e6SDan Schatzberg static int fuse_symlink_readpage(struct file *null, struct page *page)
16945571f1e6SDan Schatzberg {
16955571f1e6SDan Schatzberg 	int err = fuse_readlink_page(page->mapping->host, page);
16965571f1e6SDan Schatzberg 
16975571f1e6SDan Schatzberg 	if (!err)
16985571f1e6SDan Schatzberg 		SetPageUptodate(page);
16995571f1e6SDan Schatzberg 
17005571f1e6SDan Schatzberg 	unlock_page(page);
17015571f1e6SDan Schatzberg 
17025571f1e6SDan Schatzberg 	return err;
17035571f1e6SDan Schatzberg }
17045571f1e6SDan Schatzberg 
17055571f1e6SDan Schatzberg static const struct address_space_operations fuse_symlink_aops = {
17065571f1e6SDan Schatzberg 	.readpage	= fuse_symlink_readpage,
17075571f1e6SDan Schatzberg };
17085571f1e6SDan Schatzberg 
1709e5e5558eSMiklos Szeredi void fuse_init_symlink(struct inode *inode)
1710e5e5558eSMiklos Szeredi {
1711e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_symlink_inode_operations;
17125571f1e6SDan Schatzberg 	inode->i_data.a_ops = &fuse_symlink_aops;
17135571f1e6SDan Schatzberg 	inode_nohighmem(inode);
1714e5e5558eSMiklos Szeredi }
1715