xref: /openbmc/linux/fs/fuse/dir.c (revision 6c26f71759a6efc04b888dd2c1cc4f1cac38cdf0)
1e5e5558eSMiklos Szeredi /*
2e5e5558eSMiklos Szeredi   FUSE: Filesystem in Userspace
31729a16cSMiklos Szeredi   Copyright (C) 2001-2008  Miklos Szeredi <miklos@szeredi.hu>
4e5e5558eSMiklos Szeredi 
5e5e5558eSMiklos Szeredi   This program can be distributed under the terms of the GNU GPL.
6e5e5558eSMiklos Szeredi   See the file COPYING.
7e5e5558eSMiklos Szeredi */
8e5e5558eSMiklos Szeredi 
9e5e5558eSMiklos Szeredi #include "fuse_i.h"
10e5e5558eSMiklos Szeredi 
11e5e5558eSMiklos Szeredi #include <linux/pagemap.h>
12e5e5558eSMiklos Szeredi #include <linux/file.h>
13e5e5558eSMiklos Szeredi #include <linux/sched.h>
14e5e5558eSMiklos Szeredi #include <linux/namei.h>
1507e77dcaSMiklos Szeredi #include <linux/slab.h>
16703c7362SSeth Forshee #include <linux/xattr.h>
17261aaba7SMiklos Szeredi #include <linux/iversion.h>
1860bcc88aSSeth Forshee #include <linux/posix_acl.h>
19e5e5558eSMiklos Szeredi 
204582a4abSFeng Shuo static void fuse_advise_use_readdirplus(struct inode *dir)
214582a4abSFeng Shuo {
224582a4abSFeng Shuo 	struct fuse_inode *fi = get_fuse_inode(dir);
234582a4abSFeng Shuo 
244582a4abSFeng Shuo 	set_bit(FUSE_I_ADVISE_RDPLUS, &fi->state);
254582a4abSFeng Shuo }
264582a4abSFeng Shuo 
2730c6a23dSKhazhismel Kumykov #if BITS_PER_LONG >= 64
2830c6a23dSKhazhismel Kumykov static inline void __fuse_dentry_settime(struct dentry *entry, u64 time)
2930c6a23dSKhazhismel Kumykov {
3030c6a23dSKhazhismel Kumykov 	entry->d_fsdata = (void *) time;
3130c6a23dSKhazhismel Kumykov }
3230c6a23dSKhazhismel Kumykov 
3330c6a23dSKhazhismel Kumykov static inline u64 fuse_dentry_time(const struct dentry *entry)
3430c6a23dSKhazhismel Kumykov {
3530c6a23dSKhazhismel Kumykov 	return (u64)entry->d_fsdata;
3630c6a23dSKhazhismel Kumykov }
3730c6a23dSKhazhismel Kumykov 
3830c6a23dSKhazhismel Kumykov #else
39f75fdf22SMiklos Szeredi union fuse_dentry {
40f75fdf22SMiklos Szeredi 	u64 time;
41f75fdf22SMiklos Szeredi 	struct rcu_head rcu;
42f75fdf22SMiklos Szeredi };
43f75fdf22SMiklos Szeredi 
4430c6a23dSKhazhismel Kumykov static inline void __fuse_dentry_settime(struct dentry *dentry, u64 time)
4530c6a23dSKhazhismel Kumykov {
4630c6a23dSKhazhismel Kumykov 	((union fuse_dentry *) dentry->d_fsdata)->time = time;
4730c6a23dSKhazhismel Kumykov }
4830c6a23dSKhazhismel Kumykov 
4930c6a23dSKhazhismel Kumykov static inline u64 fuse_dentry_time(const struct dentry *entry)
5030c6a23dSKhazhismel Kumykov {
5130c6a23dSKhazhismel Kumykov 	return ((union fuse_dentry *) entry->d_fsdata)->time;
5230c6a23dSKhazhismel Kumykov }
5330c6a23dSKhazhismel Kumykov #endif
5430c6a23dSKhazhismel Kumykov 
558fab0106SMiklos Szeredi static void fuse_dentry_settime(struct dentry *dentry, u64 time)
560a0898cfSMiklos Szeredi {
578fab0106SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn_super(dentry->d_sb);
588fab0106SMiklos Szeredi 	bool delete = !time && fc->delete_stale;
598fab0106SMiklos Szeredi 	/*
608fab0106SMiklos Szeredi 	 * Mess with DCACHE_OP_DELETE because dput() will be faster without it.
618fab0106SMiklos Szeredi 	 * Don't care about races, either way it's just an optimization
628fab0106SMiklos Szeredi 	 */
638fab0106SMiklos Szeredi 	if ((!delete && (dentry->d_flags & DCACHE_OP_DELETE)) ||
648fab0106SMiklos Szeredi 	    (delete && !(dentry->d_flags & DCACHE_OP_DELETE))) {
658fab0106SMiklos Szeredi 		spin_lock(&dentry->d_lock);
668fab0106SMiklos Szeredi 		if (!delete)
678fab0106SMiklos Szeredi 			dentry->d_flags &= ~DCACHE_OP_DELETE;
688fab0106SMiklos Szeredi 		else
698fab0106SMiklos Szeredi 			dentry->d_flags |= DCACHE_OP_DELETE;
708fab0106SMiklos Szeredi 		spin_unlock(&dentry->d_lock);
710a0898cfSMiklos Szeredi 	}
720a0898cfSMiklos Szeredi 
7330c6a23dSKhazhismel Kumykov 	__fuse_dentry_settime(dentry, time);
740a0898cfSMiklos Szeredi }
750a0898cfSMiklos Szeredi 
766f9f1180SMiklos Szeredi /*
776f9f1180SMiklos Szeredi  * FUSE caches dentries and attributes with separate timeout.  The
786f9f1180SMiklos Szeredi  * time in jiffies until the dentry/attributes are valid is stored in
79f75fdf22SMiklos Szeredi  * dentry->d_fsdata and fuse_inode->i_time respectively.
806f9f1180SMiklos Szeredi  */
816f9f1180SMiklos Szeredi 
826f9f1180SMiklos Szeredi /*
836f9f1180SMiklos Szeredi  * Calculate the time in jiffies until a dentry/attributes are valid
846f9f1180SMiklos Szeredi  */
85bcb6f6d2SMiklos Szeredi static u64 time_to_jiffies(u64 sec, u32 nsec)
86e5e5558eSMiklos Szeredi {
87685d16ddSMiklos Szeredi 	if (sec || nsec) {
88bcb6f6d2SMiklos Szeredi 		struct timespec64 ts = {
89bcb6f6d2SMiklos Szeredi 			sec,
9021067527SDavid Sheets 			min_t(u32, nsec, NSEC_PER_SEC - 1)
91bcb6f6d2SMiklos Szeredi 		};
92bcb6f6d2SMiklos Szeredi 
93bcb6f6d2SMiklos Szeredi 		return get_jiffies_64() + timespec64_to_jiffies(&ts);
94685d16ddSMiklos Szeredi 	} else
950a0898cfSMiklos Szeredi 		return 0;
96e5e5558eSMiklos Szeredi }
97e5e5558eSMiklos Szeredi 
986f9f1180SMiklos Szeredi /*
996f9f1180SMiklos Szeredi  * Set dentry and possibly attribute timeouts from the lookup/mk*
1006f9f1180SMiklos Szeredi  * replies
1016f9f1180SMiklos Szeredi  */
102d123d8e1SMiklos Szeredi void fuse_change_entry_timeout(struct dentry *entry, struct fuse_entry_out *o)
1030aa7c699SMiklos Szeredi {
1040a0898cfSMiklos Szeredi 	fuse_dentry_settime(entry,
1050a0898cfSMiklos Szeredi 		time_to_jiffies(o->entry_valid, o->entry_valid_nsec));
1061fb69e78SMiklos Szeredi }
1071fb69e78SMiklos Szeredi 
1081fb69e78SMiklos Szeredi static u64 attr_timeout(struct fuse_attr_out *o)
1091fb69e78SMiklos Szeredi {
1101fb69e78SMiklos Szeredi 	return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
1111fb69e78SMiklos Szeredi }
1121fb69e78SMiklos Szeredi 
113d123d8e1SMiklos Szeredi u64 entry_attr_timeout(struct fuse_entry_out *o)
1141fb69e78SMiklos Szeredi {
1151fb69e78SMiklos Szeredi 	return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
1168cbdf1e6SMiklos Szeredi }
1178cbdf1e6SMiklos Szeredi 
1182f1e8196SMiklos Szeredi static void fuse_invalidate_attr_mask(struct inode *inode, u32 mask)
1192f1e8196SMiklos Szeredi {
1202f1e8196SMiklos Szeredi 	set_mask_bits(&get_fuse_inode(inode)->inval_mask, 0, mask);
1212f1e8196SMiklos Szeredi }
1222f1e8196SMiklos Szeredi 
1236f9f1180SMiklos Szeredi /*
1246f9f1180SMiklos Szeredi  * Mark the attributes as stale, so that at the next call to
1256f9f1180SMiklos Szeredi  * ->getattr() they will be fetched from userspace
1266f9f1180SMiklos Szeredi  */
1278cbdf1e6SMiklos Szeredi void fuse_invalidate_attr(struct inode *inode)
1288cbdf1e6SMiklos Szeredi {
1292f1e8196SMiklos Szeredi 	fuse_invalidate_attr_mask(inode, STATX_BASIC_STATS);
1308cbdf1e6SMiklos Szeredi }
1318cbdf1e6SMiklos Szeredi 
132261aaba7SMiklos Szeredi static void fuse_dir_changed(struct inode *dir)
133261aaba7SMiklos Szeredi {
134261aaba7SMiklos Szeredi 	fuse_invalidate_attr(dir);
135261aaba7SMiklos Szeredi 	inode_maybe_inc_iversion(dir, false);
136261aaba7SMiklos Szeredi }
137261aaba7SMiklos Szeredi 
138451418fcSAndrew Gallagher /**
139451418fcSAndrew Gallagher  * Mark the attributes as stale due to an atime change.  Avoid the invalidate if
140451418fcSAndrew Gallagher  * atime is not used.
141451418fcSAndrew Gallagher  */
142451418fcSAndrew Gallagher void fuse_invalidate_atime(struct inode *inode)
143451418fcSAndrew Gallagher {
144451418fcSAndrew Gallagher 	if (!IS_RDONLY(inode))
1452f1e8196SMiklos Szeredi 		fuse_invalidate_attr_mask(inode, STATX_ATIME);
146451418fcSAndrew Gallagher }
147451418fcSAndrew Gallagher 
1486f9f1180SMiklos Szeredi /*
1496f9f1180SMiklos Szeredi  * Just mark the entry as stale, so that a next attempt to look it up
1506f9f1180SMiklos Szeredi  * will result in a new lookup call to userspace
1516f9f1180SMiklos Szeredi  *
1526f9f1180SMiklos Szeredi  * This is called when a dentry is about to become negative and the
1536f9f1180SMiklos Szeredi  * timeout is unknown (unlink, rmdir, rename and in some cases
1546f9f1180SMiklos Szeredi  * lookup)
1556f9f1180SMiklos Szeredi  */
156dbd561d2SMiklos Szeredi void fuse_invalidate_entry_cache(struct dentry *entry)
1578cbdf1e6SMiklos Szeredi {
1580a0898cfSMiklos Szeredi 	fuse_dentry_settime(entry, 0);
1598cbdf1e6SMiklos Szeredi }
1608cbdf1e6SMiklos Szeredi 
1616f9f1180SMiklos Szeredi /*
1626f9f1180SMiklos Szeredi  * Same as fuse_invalidate_entry_cache(), but also try to remove the
1636f9f1180SMiklos Szeredi  * dentry from the hash
1646f9f1180SMiklos Szeredi  */
1658cbdf1e6SMiklos Szeredi static void fuse_invalidate_entry(struct dentry *entry)
1668cbdf1e6SMiklos Szeredi {
1678cbdf1e6SMiklos Szeredi 	d_invalidate(entry);
1688cbdf1e6SMiklos Szeredi 	fuse_invalidate_entry_cache(entry);
1690aa7c699SMiklos Szeredi }
1700aa7c699SMiklos Szeredi 
1717078187aSMiklos Szeredi static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_args *args,
17213983d06SAl Viro 			     u64 nodeid, const struct qstr *name,
173e5e5558eSMiklos Szeredi 			     struct fuse_entry_out *outarg)
174e5e5558eSMiklos Szeredi {
1750e9663eeSMiklos Szeredi 	memset(outarg, 0, sizeof(struct fuse_entry_out));
176d5b48543SMiklos Szeredi 	args->opcode = FUSE_LOOKUP;
177d5b48543SMiklos Szeredi 	args->nodeid = nodeid;
178d5b48543SMiklos Szeredi 	args->in_numargs = 1;
179d5b48543SMiklos Szeredi 	args->in_args[0].size = name->len + 1;
180d5b48543SMiklos Szeredi 	args->in_args[0].value = name->name;
181d5b48543SMiklos Szeredi 	args->out_numargs = 1;
182d5b48543SMiklos Szeredi 	args->out_args[0].size = sizeof(struct fuse_entry_out);
183d5b48543SMiklos Szeredi 	args->out_args[0].value = outarg;
184e5e5558eSMiklos Szeredi }
185e5e5558eSMiklos Szeredi 
1866f9f1180SMiklos Szeredi /*
1876f9f1180SMiklos Szeredi  * Check whether the dentry is still valid
1886f9f1180SMiklos Szeredi  *
1896f9f1180SMiklos Szeredi  * If the entry validity timeout has expired and the dentry is
1906f9f1180SMiklos Szeredi  * positive, try to redo the lookup.  If the lookup results in a
1916f9f1180SMiklos Szeredi  * different inode, then let the VFS invalidate the dentry and redo
1926f9f1180SMiklos Szeredi  * the lookup once more.  If the lookup results in the same inode,
1936f9f1180SMiklos Szeredi  * then refresh the attributes, timeouts and mark the dentry valid.
1946f9f1180SMiklos Szeredi  */
1950b728e19SAl Viro static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
196e5e5558eSMiklos Szeredi {
19734286d66SNick Piggin 	struct inode *inode;
19828420dadSMiklos Szeredi 	struct dentry *parent;
19928420dadSMiklos Szeredi 	struct fuse_conn *fc;
2006314efeeSMiklos Szeredi 	struct fuse_inode *fi;
201e2a6b952SMiklos Szeredi 	int ret;
2028cbdf1e6SMiklos Szeredi 
2032b0143b5SDavid Howells 	inode = d_inode_rcu(entry);
2048cbdf1e6SMiklos Szeredi 	if (inode && is_bad_inode(inode))
205e2a6b952SMiklos Szeredi 		goto invalid;
206154210ccSAnand Avati 	else if (time_before64(fuse_dentry_time(entry), get_jiffies_64()) ||
207154210ccSAnand Avati 		 (flags & LOOKUP_REVAL)) {
208e5e5558eSMiklos Szeredi 		struct fuse_entry_out outarg;
2097078187aSMiklos Szeredi 		FUSE_ARGS(args);
21007e77dcaSMiklos Szeredi 		struct fuse_forget_link *forget;
2111fb69e78SMiklos Szeredi 		u64 attr_version;
2128cbdf1e6SMiklos Szeredi 
21350322fe7SMiklos Szeredi 		/* For negative dentries, always do a fresh lookup */
2148cbdf1e6SMiklos Szeredi 		if (!inode)
215e2a6b952SMiklos Szeredi 			goto invalid;
2168cbdf1e6SMiklos Szeredi 
217e2a6b952SMiklos Szeredi 		ret = -ECHILD;
2180b728e19SAl Viro 		if (flags & LOOKUP_RCU)
219e2a6b952SMiklos Szeredi 			goto out;
220e7c0a167SMiklos Szeredi 
2218cbdf1e6SMiklos Szeredi 		fc = get_fuse_conn(inode);
222e5e5558eSMiklos Szeredi 
22307e77dcaSMiklos Szeredi 		forget = fuse_alloc_forget();
224e2a6b952SMiklos Szeredi 		ret = -ENOMEM;
2257078187aSMiklos Szeredi 		if (!forget)
226e2a6b952SMiklos Szeredi 			goto out;
2272d51013eSMiklos Szeredi 
2287dca9fd3SMiklos Szeredi 		attr_version = fuse_get_attr_version(fc);
2291fb69e78SMiklos Szeredi 
230e956edd0SMiklos Szeredi 		parent = dget_parent(entry);
2312b0143b5SDavid Howells 		fuse_lookup_init(fc, &args, get_node_id(d_inode(parent)),
232c180eebeSMiklos Szeredi 				 &entry->d_name, &outarg);
2337078187aSMiklos Szeredi 		ret = fuse_simple_request(fc, &args);
234e956edd0SMiklos Szeredi 		dput(parent);
23550322fe7SMiklos Szeredi 		/* Zero nodeid is same as -ENOENT */
2367078187aSMiklos Szeredi 		if (!ret && !outarg.nodeid)
2377078187aSMiklos Szeredi 			ret = -ENOENT;
2387078187aSMiklos Szeredi 		if (!ret) {
2396314efeeSMiklos Szeredi 			fi = get_fuse_inode(inode);
2409e6268dbSMiklos Szeredi 			if (outarg.nodeid != get_node_id(inode)) {
24107e77dcaSMiklos Szeredi 				fuse_queue_forget(fc, forget, outarg.nodeid, 1);
242e2a6b952SMiklos Szeredi 				goto invalid;
2439e6268dbSMiklos Szeredi 			}
244c9d8f5f0SKirill Tkhai 			spin_lock(&fi->lock);
2459e6268dbSMiklos Szeredi 			fi->nlookup++;
246c9d8f5f0SKirill Tkhai 			spin_unlock(&fi->lock);
2479e6268dbSMiklos Szeredi 		}
24807e77dcaSMiklos Szeredi 		kfree(forget);
2497078187aSMiklos Szeredi 		if (ret == -ENOMEM)
2507078187aSMiklos Szeredi 			goto out;
2517078187aSMiklos Szeredi 		if (ret || (outarg.attr.mode ^ inode->i_mode) & S_IFMT)
252e2a6b952SMiklos Szeredi 			goto invalid;
253e5e5558eSMiklos Szeredi 
25460bcc88aSSeth Forshee 		forget_all_cached_acls(inode);
2551fb69e78SMiklos Szeredi 		fuse_change_attributes(inode, &outarg.attr,
2561fb69e78SMiklos Szeredi 				       entry_attr_timeout(&outarg),
2571fb69e78SMiklos Szeredi 				       attr_version);
2581fb69e78SMiklos Szeredi 		fuse_change_entry_timeout(entry, &outarg);
25928420dadSMiklos Szeredi 	} else if (inode) {
2606314efeeSMiklos Szeredi 		fi = get_fuse_inode(inode);
2616314efeeSMiklos Szeredi 		if (flags & LOOKUP_RCU) {
2626314efeeSMiklos Szeredi 			if (test_bit(FUSE_I_INIT_RDPLUS, &fi->state))
2636314efeeSMiklos Szeredi 				return -ECHILD;
2646314efeeSMiklos Szeredi 		} else if (test_and_clear_bit(FUSE_I_INIT_RDPLUS, &fi->state)) {
26528420dadSMiklos Szeredi 			parent = dget_parent(entry);
2662b0143b5SDavid Howells 			fuse_advise_use_readdirplus(d_inode(parent));
26728420dadSMiklos Szeredi 			dput(parent);
268e5e5558eSMiklos Szeredi 		}
26928420dadSMiklos Szeredi 	}
270e2a6b952SMiklos Szeredi 	ret = 1;
271e2a6b952SMiklos Szeredi out:
272e2a6b952SMiklos Szeredi 	return ret;
273e2a6b952SMiklos Szeredi 
274e2a6b952SMiklos Szeredi invalid:
275e2a6b952SMiklos Szeredi 	ret = 0;
276e2a6b952SMiklos Szeredi 	goto out;
277e5e5558eSMiklos Szeredi }
278e5e5558eSMiklos Szeredi 
27930c6a23dSKhazhismel Kumykov #if BITS_PER_LONG < 64
280f75fdf22SMiklos Szeredi static int fuse_dentry_init(struct dentry *dentry)
281f75fdf22SMiklos Szeredi {
282dc69e98cSKhazhismel Kumykov 	dentry->d_fsdata = kzalloc(sizeof(union fuse_dentry),
283dc69e98cSKhazhismel Kumykov 				   GFP_KERNEL_ACCOUNT | __GFP_RECLAIMABLE);
284f75fdf22SMiklos Szeredi 
285f75fdf22SMiklos Szeredi 	return dentry->d_fsdata ? 0 : -ENOMEM;
286f75fdf22SMiklos Szeredi }
287f75fdf22SMiklos Szeredi static void fuse_dentry_release(struct dentry *dentry)
288f75fdf22SMiklos Szeredi {
289f75fdf22SMiklos Szeredi 	union fuse_dentry *fd = dentry->d_fsdata;
290f75fdf22SMiklos Szeredi 
291f75fdf22SMiklos Szeredi 	kfree_rcu(fd, rcu);
292f75fdf22SMiklos Szeredi }
29330c6a23dSKhazhismel Kumykov #endif
294f75fdf22SMiklos Szeredi 
2958fab0106SMiklos Szeredi static int fuse_dentry_delete(const struct dentry *dentry)
2968fab0106SMiklos Szeredi {
2978fab0106SMiklos Szeredi 	return time_before64(fuse_dentry_time(dentry), get_jiffies_64());
2988fab0106SMiklos Szeredi }
2998fab0106SMiklos Szeredi 
3004269590aSAl Viro const struct dentry_operations fuse_dentry_operations = {
301e5e5558eSMiklos Szeredi 	.d_revalidate	= fuse_dentry_revalidate,
3028fab0106SMiklos Szeredi 	.d_delete	= fuse_dentry_delete,
30330c6a23dSKhazhismel Kumykov #if BITS_PER_LONG < 64
304f75fdf22SMiklos Szeredi 	.d_init		= fuse_dentry_init,
305f75fdf22SMiklos Szeredi 	.d_release	= fuse_dentry_release,
30630c6a23dSKhazhismel Kumykov #endif
307e5e5558eSMiklos Szeredi };
308e5e5558eSMiklos Szeredi 
3090ce267ffSMiklos Szeredi const struct dentry_operations fuse_root_dentry_operations = {
31030c6a23dSKhazhismel Kumykov #if BITS_PER_LONG < 64
3110ce267ffSMiklos Szeredi 	.d_init		= fuse_dentry_init,
3120ce267ffSMiklos Szeredi 	.d_release	= fuse_dentry_release,
31330c6a23dSKhazhismel Kumykov #endif
3140ce267ffSMiklos Szeredi };
3150ce267ffSMiklos Szeredi 
316a5bfffacSTimo Savola int fuse_valid_type(int m)
31739ee059aSMiklos Szeredi {
31839ee059aSMiklos Szeredi 	return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) ||
31939ee059aSMiklos Szeredi 		S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m);
32039ee059aSMiklos Szeredi }
32139ee059aSMiklos Szeredi 
32213983d06SAl Viro int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name,
323c180eebeSMiklos Szeredi 		     struct fuse_entry_out *outarg, struct inode **inode)
324c180eebeSMiklos Szeredi {
325c180eebeSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn_super(sb);
3267078187aSMiklos Szeredi 	FUSE_ARGS(args);
32707e77dcaSMiklos Szeredi 	struct fuse_forget_link *forget;
328c180eebeSMiklos Szeredi 	u64 attr_version;
329c180eebeSMiklos Szeredi 	int err;
330c180eebeSMiklos Szeredi 
331c180eebeSMiklos Szeredi 	*inode = NULL;
332c180eebeSMiklos Szeredi 	err = -ENAMETOOLONG;
333c180eebeSMiklos Szeredi 	if (name->len > FUSE_NAME_MAX)
334c180eebeSMiklos Szeredi 		goto out;
335c180eebeSMiklos Szeredi 
336c180eebeSMiklos Szeredi 
33707e77dcaSMiklos Szeredi 	forget = fuse_alloc_forget();
33807e77dcaSMiklos Szeredi 	err = -ENOMEM;
3397078187aSMiklos Szeredi 	if (!forget)
340c180eebeSMiklos Szeredi 		goto out;
341c180eebeSMiklos Szeredi 
342c180eebeSMiklos Szeredi 	attr_version = fuse_get_attr_version(fc);
343c180eebeSMiklos Szeredi 
3447078187aSMiklos Szeredi 	fuse_lookup_init(fc, &args, nodeid, name, outarg);
3457078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
346c180eebeSMiklos Szeredi 	/* Zero nodeid is same as -ENOENT, but with valid timeout */
347c180eebeSMiklos Szeredi 	if (err || !outarg->nodeid)
348c180eebeSMiklos Szeredi 		goto out_put_forget;
349c180eebeSMiklos Szeredi 
350c180eebeSMiklos Szeredi 	err = -EIO;
351c180eebeSMiklos Szeredi 	if (!outarg->nodeid)
352c180eebeSMiklos Szeredi 		goto out_put_forget;
353c180eebeSMiklos Szeredi 	if (!fuse_valid_type(outarg->attr.mode))
354c180eebeSMiklos Szeredi 		goto out_put_forget;
355c180eebeSMiklos Szeredi 
356c180eebeSMiklos Szeredi 	*inode = fuse_iget(sb, outarg->nodeid, outarg->generation,
357c180eebeSMiklos Szeredi 			   &outarg->attr, entry_attr_timeout(outarg),
358c180eebeSMiklos Szeredi 			   attr_version);
359c180eebeSMiklos Szeredi 	err = -ENOMEM;
360c180eebeSMiklos Szeredi 	if (!*inode) {
36107e77dcaSMiklos Szeredi 		fuse_queue_forget(fc, forget, outarg->nodeid, 1);
362c180eebeSMiklos Szeredi 		goto out;
363c180eebeSMiklos Szeredi 	}
364c180eebeSMiklos Szeredi 	err = 0;
365c180eebeSMiklos Szeredi 
366c180eebeSMiklos Szeredi  out_put_forget:
36707e77dcaSMiklos Szeredi 	kfree(forget);
368c180eebeSMiklos Szeredi  out:
369c180eebeSMiklos Szeredi 	return err;
370c180eebeSMiklos Szeredi }
371c180eebeSMiklos Szeredi 
3720aa7c699SMiklos Szeredi static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
37300cd8dd3SAl Viro 				  unsigned int flags)
374e5e5558eSMiklos Szeredi {
375e5e5558eSMiklos Szeredi 	int err;
376e5e5558eSMiklos Szeredi 	struct fuse_entry_out outarg;
377c180eebeSMiklos Szeredi 	struct inode *inode;
3780de6256dSMiklos Szeredi 	struct dentry *newent;
379c180eebeSMiklos Szeredi 	bool outarg_valid = true;
38063576c13SMiklos Szeredi 	bool locked;
381e5e5558eSMiklos Szeredi 
38263576c13SMiklos Szeredi 	locked = fuse_lock_inode(dir);
383c180eebeSMiklos Szeredi 	err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name,
384c180eebeSMiklos Szeredi 			       &outarg, &inode);
38563576c13SMiklos Szeredi 	fuse_unlock_inode(dir, locked);
386c180eebeSMiklos Szeredi 	if (err == -ENOENT) {
387c180eebeSMiklos Szeredi 		outarg_valid = false;
388c180eebeSMiklos Szeredi 		err = 0;
3892d51013eSMiklos Szeredi 	}
390c180eebeSMiklos Szeredi 	if (err)
391c180eebeSMiklos Szeredi 		goto out_err;
3922d51013eSMiklos Szeredi 
393ee4e5271SMiklos Szeredi 	err = -EIO;
394c180eebeSMiklos Szeredi 	if (inode && get_node_id(inode) == FUSE_ROOT_ID)
395c180eebeSMiklos Szeredi 		goto out_iput;
396e5e5558eSMiklos Szeredi 
39741d28bcaSAl Viro 	newent = d_splice_alias(inode, entry);
398c180eebeSMiklos Szeredi 	err = PTR_ERR(newent);
399c180eebeSMiklos Szeredi 	if (IS_ERR(newent))
4005835f339SMiklos Szeredi 		goto out_err;
401d2a85164SMiklos Szeredi 
4020de6256dSMiklos Szeredi 	entry = newent ? newent : entry;
403c180eebeSMiklos Szeredi 	if (outarg_valid)
4041fb69e78SMiklos Szeredi 		fuse_change_entry_timeout(entry, &outarg);
4058cbdf1e6SMiklos Szeredi 	else
4068cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
407c180eebeSMiklos Szeredi 
408*6c26f717SMiklos Szeredi 	if (inode)
4094582a4abSFeng Shuo 		fuse_advise_use_readdirplus(dir);
4100de6256dSMiklos Szeredi 	return newent;
411c180eebeSMiklos Szeredi 
412c180eebeSMiklos Szeredi  out_iput:
413c180eebeSMiklos Szeredi 	iput(inode);
414c180eebeSMiklos Szeredi  out_err:
415c180eebeSMiklos Szeredi 	return ERR_PTR(err);
416e5e5558eSMiklos Szeredi }
417e5e5558eSMiklos Szeredi 
4186f9f1180SMiklos Szeredi /*
4196f9f1180SMiklos Szeredi  * Atomic create+open operation
4206f9f1180SMiklos Szeredi  *
4216f9f1180SMiklos Szeredi  * If the filesystem doesn't support this, then fall back to separate
4226f9f1180SMiklos Szeredi  * 'mknod' + 'open' requests.
4236f9f1180SMiklos Szeredi  */
424d9585277SAl Viro static int fuse_create_open(struct inode *dir, struct dentry *entry,
42530d90494SAl Viro 			    struct file *file, unsigned flags,
426b452a458SAl Viro 			    umode_t mode)
427fd72faacSMiklos Szeredi {
428fd72faacSMiklos Szeredi 	int err;
429fd72faacSMiklos Szeredi 	struct inode *inode;
430fd72faacSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
4317078187aSMiklos Szeredi 	FUSE_ARGS(args);
43207e77dcaSMiklos Szeredi 	struct fuse_forget_link *forget;
433e0a43ddcSMiklos Szeredi 	struct fuse_create_in inarg;
434fd72faacSMiklos Szeredi 	struct fuse_open_out outopen;
435fd72faacSMiklos Szeredi 	struct fuse_entry_out outentry;
436ebf84d0cSKirill Tkhai 	struct fuse_inode *fi;
437fd72faacSMiklos Szeredi 	struct fuse_file *ff;
438fd72faacSMiklos Szeredi 
439af109bcaSMiklos Szeredi 	/* Userspace expects S_IFREG in create mode */
440af109bcaSMiklos Szeredi 	BUG_ON((mode & S_IFMT) != S_IFREG);
441af109bcaSMiklos Szeredi 
44207e77dcaSMiklos Szeredi 	forget = fuse_alloc_forget();
443c8ccbe03SMiklos Szeredi 	err = -ENOMEM;
44407e77dcaSMiklos Szeredi 	if (!forget)
445c8ccbe03SMiklos Szeredi 		goto out_err;
44651eb01e7SMiklos Szeredi 
447ce1d5a49SMiklos Szeredi 	err = -ENOMEM;
448acf99433STejun Heo 	ff = fuse_file_alloc(fc);
449fd72faacSMiklos Szeredi 	if (!ff)
4507078187aSMiklos Szeredi 		goto out_put_forget_req;
451fd72faacSMiklos Szeredi 
452e0a43ddcSMiklos Szeredi 	if (!fc->dont_mask)
453e0a43ddcSMiklos Szeredi 		mode &= ~current_umask();
454e0a43ddcSMiklos Szeredi 
455fd72faacSMiklos Szeredi 	flags &= ~O_NOCTTY;
456fd72faacSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
4570e9663eeSMiklos Szeredi 	memset(&outentry, 0, sizeof(outentry));
458fd72faacSMiklos Szeredi 	inarg.flags = flags;
459fd72faacSMiklos Szeredi 	inarg.mode = mode;
460e0a43ddcSMiklos Szeredi 	inarg.umask = current_umask();
461d5b48543SMiklos Szeredi 	args.opcode = FUSE_CREATE;
462d5b48543SMiklos Szeredi 	args.nodeid = get_node_id(dir);
463d5b48543SMiklos Szeredi 	args.in_numargs = 2;
464d5b48543SMiklos Szeredi 	args.in_args[0].size = sizeof(inarg);
465d5b48543SMiklos Szeredi 	args.in_args[0].value = &inarg;
466d5b48543SMiklos Szeredi 	args.in_args[1].size = entry->d_name.len + 1;
467d5b48543SMiklos Szeredi 	args.in_args[1].value = entry->d_name.name;
468d5b48543SMiklos Szeredi 	args.out_numargs = 2;
469d5b48543SMiklos Szeredi 	args.out_args[0].size = sizeof(outentry);
470d5b48543SMiklos Szeredi 	args.out_args[0].value = &outentry;
471d5b48543SMiklos Szeredi 	args.out_args[1].size = sizeof(outopen);
472d5b48543SMiklos Szeredi 	args.out_args[1].value = &outopen;
4737078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
474c8ccbe03SMiklos Szeredi 	if (err)
475fd72faacSMiklos Szeredi 		goto out_free_ff;
476fd72faacSMiklos Szeredi 
477fd72faacSMiklos Szeredi 	err = -EIO;
4782827d0b2SMiklos Szeredi 	if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid))
479fd72faacSMiklos Szeredi 		goto out_free_ff;
480fd72faacSMiklos Szeredi 
481c7b7143cSMiklos Szeredi 	ff->fh = outopen.fh;
482c7b7143cSMiklos Szeredi 	ff->nodeid = outentry.nodeid;
483c7b7143cSMiklos Szeredi 	ff->open_flags = outopen.open_flags;
484fd72faacSMiklos Szeredi 	inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
4851fb69e78SMiklos Szeredi 			  &outentry.attr, entry_attr_timeout(&outentry), 0);
486fd72faacSMiklos Szeredi 	if (!inode) {
487fd72faacSMiklos Szeredi 		flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
488ebf84d0cSKirill Tkhai 		fuse_sync_release(NULL, ff, flags);
48907e77dcaSMiklos Szeredi 		fuse_queue_forget(fc, forget, outentry.nodeid, 1);
490c8ccbe03SMiklos Szeredi 		err = -ENOMEM;
491c8ccbe03SMiklos Szeredi 		goto out_err;
492fd72faacSMiklos Szeredi 	}
49307e77dcaSMiklos Szeredi 	kfree(forget);
494fd72faacSMiklos Szeredi 	d_instantiate(entry, inode);
4951fb69e78SMiklos Szeredi 	fuse_change_entry_timeout(entry, &outentry);
496261aaba7SMiklos Szeredi 	fuse_dir_changed(dir);
497be12af3eSAl Viro 	err = finish_open(file, entry, generic_file_open);
49830d90494SAl Viro 	if (err) {
499ebf84d0cSKirill Tkhai 		fi = get_fuse_inode(inode);
500ebf84d0cSKirill Tkhai 		fuse_sync_release(fi, ff, flags);
501c8ccbe03SMiklos Szeredi 	} else {
502267d8444SMiklos Szeredi 		file->private_data = ff;
503c7b7143cSMiklos Szeredi 		fuse_finish_open(inode, file);
504c8ccbe03SMiklos Szeredi 	}
505d9585277SAl Viro 	return err;
506fd72faacSMiklos Szeredi 
507fd72faacSMiklos Szeredi out_free_ff:
508fd72faacSMiklos Szeredi 	fuse_file_free(ff);
50951eb01e7SMiklos Szeredi out_put_forget_req:
51007e77dcaSMiklos Szeredi 	kfree(forget);
511c8ccbe03SMiklos Szeredi out_err:
512d9585277SAl Viro 	return err;
513c8ccbe03SMiklos Szeredi }
514c8ccbe03SMiklos Szeredi 
515c8ccbe03SMiklos Szeredi static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t);
516d9585277SAl Viro static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
51730d90494SAl Viro 			    struct file *file, unsigned flags,
51844907d79SAl Viro 			    umode_t mode)
519c8ccbe03SMiklos Szeredi {
520c8ccbe03SMiklos Szeredi 	int err;
521c8ccbe03SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
522c8ccbe03SMiklos Szeredi 	struct dentry *res = NULL;
523c8ccbe03SMiklos Szeredi 
52400699ad8SAl Viro 	if (d_in_lookup(entry)) {
52500cd8dd3SAl Viro 		res = fuse_lookup(dir, entry, 0);
526c8ccbe03SMiklos Szeredi 		if (IS_ERR(res))
527d9585277SAl Viro 			return PTR_ERR(res);
528c8ccbe03SMiklos Szeredi 
529c8ccbe03SMiklos Szeredi 		if (res)
530c8ccbe03SMiklos Szeredi 			entry = res;
531c8ccbe03SMiklos Szeredi 	}
532c8ccbe03SMiklos Szeredi 
5332b0143b5SDavid Howells 	if (!(flags & O_CREAT) || d_really_is_positive(entry))
534c8ccbe03SMiklos Szeredi 		goto no_open;
535c8ccbe03SMiklos Szeredi 
536c8ccbe03SMiklos Szeredi 	/* Only creates */
53773a09dd9SAl Viro 	file->f_mode |= FMODE_CREATED;
538c8ccbe03SMiklos Szeredi 
539c8ccbe03SMiklos Szeredi 	if (fc->no_create)
540c8ccbe03SMiklos Szeredi 		goto mknod;
541c8ccbe03SMiklos Szeredi 
542b452a458SAl Viro 	err = fuse_create_open(dir, entry, file, flags, mode);
543d9585277SAl Viro 	if (err == -ENOSYS) {
544c8ccbe03SMiklos Szeredi 		fc->no_create = 1;
545c8ccbe03SMiklos Szeredi 		goto mknod;
546c8ccbe03SMiklos Szeredi 	}
547c8ccbe03SMiklos Szeredi out_dput:
548c8ccbe03SMiklos Szeredi 	dput(res);
549d9585277SAl Viro 	return err;
550c8ccbe03SMiklos Szeredi 
551c8ccbe03SMiklos Szeredi mknod:
552c8ccbe03SMiklos Szeredi 	err = fuse_mknod(dir, entry, mode, 0);
553d9585277SAl Viro 	if (err)
554c8ccbe03SMiklos Szeredi 		goto out_dput;
555c8ccbe03SMiklos Szeredi no_open:
556e45198a6SAl Viro 	return finish_no_open(file, res);
557fd72faacSMiklos Szeredi }
558fd72faacSMiklos Szeredi 
5596f9f1180SMiklos Szeredi /*
5606f9f1180SMiklos Szeredi  * Code shared between mknod, mkdir, symlink and link
5616f9f1180SMiklos Szeredi  */
5627078187aSMiklos Szeredi static int create_new_entry(struct fuse_conn *fc, struct fuse_args *args,
5639e6268dbSMiklos Szeredi 			    struct inode *dir, struct dentry *entry,
564541af6a0SAl Viro 			    umode_t mode)
5659e6268dbSMiklos Szeredi {
5669e6268dbSMiklos Szeredi 	struct fuse_entry_out outarg;
5679e6268dbSMiklos Szeredi 	struct inode *inode;
568c971e6a0SAl Viro 	struct dentry *d;
5699e6268dbSMiklos Szeredi 	int err;
57007e77dcaSMiklos Szeredi 	struct fuse_forget_link *forget;
5712d51013eSMiklos Szeredi 
57207e77dcaSMiklos Szeredi 	forget = fuse_alloc_forget();
5737078187aSMiklos Szeredi 	if (!forget)
57407e77dcaSMiklos Szeredi 		return -ENOMEM;
5759e6268dbSMiklos Szeredi 
5760e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
577d5b48543SMiklos Szeredi 	args->nodeid = get_node_id(dir);
578d5b48543SMiklos Szeredi 	args->out_numargs = 1;
579d5b48543SMiklos Szeredi 	args->out_args[0].size = sizeof(outarg);
580d5b48543SMiklos Szeredi 	args->out_args[0].value = &outarg;
5817078187aSMiklos Szeredi 	err = fuse_simple_request(fc, args);
5822d51013eSMiklos Szeredi 	if (err)
5832d51013eSMiklos Szeredi 		goto out_put_forget_req;
5842d51013eSMiklos Szeredi 
58539ee059aSMiklos Szeredi 	err = -EIO;
58639ee059aSMiklos Szeredi 	if (invalid_nodeid(outarg.nodeid))
5872d51013eSMiklos Szeredi 		goto out_put_forget_req;
58839ee059aSMiklos Szeredi 
58939ee059aSMiklos Szeredi 	if ((outarg.attr.mode ^ mode) & S_IFMT)
5902d51013eSMiklos Szeredi 		goto out_put_forget_req;
59139ee059aSMiklos Szeredi 
5929e6268dbSMiklos Szeredi 	inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
5931fb69e78SMiklos Szeredi 			  &outarg.attr, entry_attr_timeout(&outarg), 0);
5949e6268dbSMiklos Szeredi 	if (!inode) {
59507e77dcaSMiklos Szeredi 		fuse_queue_forget(fc, forget, outarg.nodeid, 1);
5969e6268dbSMiklos Szeredi 		return -ENOMEM;
5979e6268dbSMiklos Szeredi 	}
59807e77dcaSMiklos Szeredi 	kfree(forget);
5999e6268dbSMiklos Szeredi 
600c971e6a0SAl Viro 	d_drop(entry);
601c971e6a0SAl Viro 	d = d_splice_alias(inode, entry);
602c971e6a0SAl Viro 	if (IS_ERR(d))
603c971e6a0SAl Viro 		return PTR_ERR(d);
604d2a85164SMiklos Szeredi 
605c971e6a0SAl Viro 	if (d) {
606c971e6a0SAl Viro 		fuse_change_entry_timeout(d, &outarg);
607c971e6a0SAl Viro 		dput(d);
608c971e6a0SAl Viro 	} else {
6091fb69e78SMiklos Szeredi 		fuse_change_entry_timeout(entry, &outarg);
610c971e6a0SAl Viro 	}
611261aaba7SMiklos Szeredi 	fuse_dir_changed(dir);
6129e6268dbSMiklos Szeredi 	return 0;
61339ee059aSMiklos Szeredi 
6142d51013eSMiklos Szeredi  out_put_forget_req:
61507e77dcaSMiklos Szeredi 	kfree(forget);
61639ee059aSMiklos Szeredi 	return err;
6179e6268dbSMiklos Szeredi }
6189e6268dbSMiklos Szeredi 
6191a67aafbSAl Viro static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode,
6209e6268dbSMiklos Szeredi 		      dev_t rdev)
6219e6268dbSMiklos Szeredi {
6229e6268dbSMiklos Szeredi 	struct fuse_mknod_in inarg;
6239e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
6247078187aSMiklos Szeredi 	FUSE_ARGS(args);
6259e6268dbSMiklos Szeredi 
626e0a43ddcSMiklos Szeredi 	if (!fc->dont_mask)
627e0a43ddcSMiklos Szeredi 		mode &= ~current_umask();
628e0a43ddcSMiklos Szeredi 
6299e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
6309e6268dbSMiklos Szeredi 	inarg.mode = mode;
6319e6268dbSMiklos Szeredi 	inarg.rdev = new_encode_dev(rdev);
632e0a43ddcSMiklos Szeredi 	inarg.umask = current_umask();
633d5b48543SMiklos Szeredi 	args.opcode = FUSE_MKNOD;
634d5b48543SMiklos Szeredi 	args.in_numargs = 2;
635d5b48543SMiklos Szeredi 	args.in_args[0].size = sizeof(inarg);
636d5b48543SMiklos Szeredi 	args.in_args[0].value = &inarg;
637d5b48543SMiklos Szeredi 	args.in_args[1].size = entry->d_name.len + 1;
638d5b48543SMiklos Szeredi 	args.in_args[1].value = entry->d_name.name;
6397078187aSMiklos Szeredi 	return create_new_entry(fc, &args, dir, entry, mode);
6409e6268dbSMiklos Szeredi }
6419e6268dbSMiklos Szeredi 
6424acdaf27SAl Viro static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode,
643ebfc3b49SAl Viro 		       bool excl)
6449e6268dbSMiklos Szeredi {
6459e6268dbSMiklos Szeredi 	return fuse_mknod(dir, entry, mode, 0);
6469e6268dbSMiklos Szeredi }
6479e6268dbSMiklos Szeredi 
64818bb1db3SAl Viro static int fuse_mkdir(struct inode *dir, struct dentry *entry, umode_t mode)
6499e6268dbSMiklos Szeredi {
6509e6268dbSMiklos Szeredi 	struct fuse_mkdir_in inarg;
6519e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
6527078187aSMiklos Szeredi 	FUSE_ARGS(args);
6539e6268dbSMiklos Szeredi 
654e0a43ddcSMiklos Szeredi 	if (!fc->dont_mask)
655e0a43ddcSMiklos Szeredi 		mode &= ~current_umask();
656e0a43ddcSMiklos Szeredi 
6579e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
6589e6268dbSMiklos Szeredi 	inarg.mode = mode;
659e0a43ddcSMiklos Szeredi 	inarg.umask = current_umask();
660d5b48543SMiklos Szeredi 	args.opcode = FUSE_MKDIR;
661d5b48543SMiklos Szeredi 	args.in_numargs = 2;
662d5b48543SMiklos Szeredi 	args.in_args[0].size = sizeof(inarg);
663d5b48543SMiklos Szeredi 	args.in_args[0].value = &inarg;
664d5b48543SMiklos Szeredi 	args.in_args[1].size = entry->d_name.len + 1;
665d5b48543SMiklos Szeredi 	args.in_args[1].value = entry->d_name.name;
6667078187aSMiklos Szeredi 	return create_new_entry(fc, &args, dir, entry, S_IFDIR);
6679e6268dbSMiklos Szeredi }
6689e6268dbSMiklos Szeredi 
6699e6268dbSMiklos Szeredi static int fuse_symlink(struct inode *dir, struct dentry *entry,
6709e6268dbSMiklos Szeredi 			const char *link)
6719e6268dbSMiklos Szeredi {
6729e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
6739e6268dbSMiklos Szeredi 	unsigned len = strlen(link) + 1;
6747078187aSMiklos Szeredi 	FUSE_ARGS(args);
6759e6268dbSMiklos Szeredi 
676d5b48543SMiklos Szeredi 	args.opcode = FUSE_SYMLINK;
677d5b48543SMiklos Szeredi 	args.in_numargs = 2;
678d5b48543SMiklos Szeredi 	args.in_args[0].size = entry->d_name.len + 1;
679d5b48543SMiklos Szeredi 	args.in_args[0].value = entry->d_name.name;
680d5b48543SMiklos Szeredi 	args.in_args[1].size = len;
681d5b48543SMiklos Szeredi 	args.in_args[1].value = link;
6827078187aSMiklos Szeredi 	return create_new_entry(fc, &args, dir, entry, S_IFLNK);
6839e6268dbSMiklos Szeredi }
6849e6268dbSMiklos Szeredi 
685703c7362SSeth Forshee void fuse_update_ctime(struct inode *inode)
68631f3267bSMaxim Patlasov {
68731f3267bSMaxim Patlasov 	if (!IS_NOCMTIME(inode)) {
688c2050a45SDeepa Dinamani 		inode->i_ctime = current_time(inode);
68931f3267bSMaxim Patlasov 		mark_inode_dirty_sync(inode);
69031f3267bSMaxim Patlasov 	}
69131f3267bSMaxim Patlasov }
69231f3267bSMaxim Patlasov 
6939e6268dbSMiklos Szeredi static int fuse_unlink(struct inode *dir, struct dentry *entry)
6949e6268dbSMiklos Szeredi {
6959e6268dbSMiklos Szeredi 	int err;
6969e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
6977078187aSMiklos Szeredi 	FUSE_ARGS(args);
6989e6268dbSMiklos Szeredi 
699d5b48543SMiklos Szeredi 	args.opcode = FUSE_UNLINK;
700d5b48543SMiklos Szeredi 	args.nodeid = get_node_id(dir);
701d5b48543SMiklos Szeredi 	args.in_numargs = 1;
702d5b48543SMiklos Szeredi 	args.in_args[0].size = entry->d_name.len + 1;
703d5b48543SMiklos Szeredi 	args.in_args[0].value = entry->d_name.name;
7047078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
7059e6268dbSMiklos Szeredi 	if (!err) {
7062b0143b5SDavid Howells 		struct inode *inode = d_inode(entry);
707ac45d613SMiklos Szeredi 		struct fuse_inode *fi = get_fuse_inode(inode);
7089e6268dbSMiklos Szeredi 
709f15ecfefSKirill Tkhai 		spin_lock(&fi->lock);
7104510d86fSKirill Tkhai 		fi->attr_version = atomic64_inc_return(&fc->attr_version);
711dfca7cebSMiklos Szeredi 		/*
712dfca7cebSMiklos Szeredi 		 * If i_nlink == 0 then unlink doesn't make sense, yet this can
713dfca7cebSMiklos Szeredi 		 * happen if userspace filesystem is careless.  It would be
714dfca7cebSMiklos Szeredi 		 * difficult to enforce correct nlink usage so just ignore this
715dfca7cebSMiklos Szeredi 		 * condition here
716dfca7cebSMiklos Szeredi 		 */
717dfca7cebSMiklos Szeredi 		if (inode->i_nlink > 0)
718ac45d613SMiklos Szeredi 			drop_nlink(inode);
719f15ecfefSKirill Tkhai 		spin_unlock(&fi->lock);
7209e6268dbSMiklos Szeredi 		fuse_invalidate_attr(inode);
721261aaba7SMiklos Szeredi 		fuse_dir_changed(dir);
7228cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
72331f3267bSMaxim Patlasov 		fuse_update_ctime(inode);
7249e6268dbSMiklos Szeredi 	} else if (err == -EINTR)
7259e6268dbSMiklos Szeredi 		fuse_invalidate_entry(entry);
7269e6268dbSMiklos Szeredi 	return err;
7279e6268dbSMiklos Szeredi }
7289e6268dbSMiklos Szeredi 
7299e6268dbSMiklos Szeredi static int fuse_rmdir(struct inode *dir, struct dentry *entry)
7309e6268dbSMiklos Szeredi {
7319e6268dbSMiklos Szeredi 	int err;
7329e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
7337078187aSMiklos Szeredi 	FUSE_ARGS(args);
7349e6268dbSMiklos Szeredi 
735d5b48543SMiklos Szeredi 	args.opcode = FUSE_RMDIR;
736d5b48543SMiklos Szeredi 	args.nodeid = get_node_id(dir);
737d5b48543SMiklos Szeredi 	args.in_numargs = 1;
738d5b48543SMiklos Szeredi 	args.in_args[0].size = entry->d_name.len + 1;
739d5b48543SMiklos Szeredi 	args.in_args[0].value = entry->d_name.name;
7407078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
7419e6268dbSMiklos Szeredi 	if (!err) {
7422b0143b5SDavid Howells 		clear_nlink(d_inode(entry));
743261aaba7SMiklos Szeredi 		fuse_dir_changed(dir);
7448cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
7459e6268dbSMiklos Szeredi 	} else if (err == -EINTR)
7469e6268dbSMiklos Szeredi 		fuse_invalidate_entry(entry);
7479e6268dbSMiklos Szeredi 	return err;
7489e6268dbSMiklos Szeredi }
7499e6268dbSMiklos Szeredi 
7501560c974SMiklos Szeredi static int fuse_rename_common(struct inode *olddir, struct dentry *oldent,
7511560c974SMiklos Szeredi 			      struct inode *newdir, struct dentry *newent,
7521560c974SMiklos Szeredi 			      unsigned int flags, int opcode, size_t argsize)
7539e6268dbSMiklos Szeredi {
7549e6268dbSMiklos Szeredi 	int err;
7551560c974SMiklos Szeredi 	struct fuse_rename2_in inarg;
7569e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(olddir);
7577078187aSMiklos Szeredi 	FUSE_ARGS(args);
7589e6268dbSMiklos Szeredi 
7591560c974SMiklos Szeredi 	memset(&inarg, 0, argsize);
7609e6268dbSMiklos Szeredi 	inarg.newdir = get_node_id(newdir);
7611560c974SMiklos Szeredi 	inarg.flags = flags;
762d5b48543SMiklos Szeredi 	args.opcode = opcode;
763d5b48543SMiklos Szeredi 	args.nodeid = get_node_id(olddir);
764d5b48543SMiklos Szeredi 	args.in_numargs = 3;
765d5b48543SMiklos Szeredi 	args.in_args[0].size = argsize;
766d5b48543SMiklos Szeredi 	args.in_args[0].value = &inarg;
767d5b48543SMiklos Szeredi 	args.in_args[1].size = oldent->d_name.len + 1;
768d5b48543SMiklos Szeredi 	args.in_args[1].value = oldent->d_name.name;
769d5b48543SMiklos Szeredi 	args.in_args[2].size = newent->d_name.len + 1;
770d5b48543SMiklos Szeredi 	args.in_args[2].value = newent->d_name.name;
7717078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
7729e6268dbSMiklos Szeredi 	if (!err) {
77308b63307SMiklos Szeredi 		/* ctime changes */
7742b0143b5SDavid Howells 		fuse_invalidate_attr(d_inode(oldent));
7752b0143b5SDavid Howells 		fuse_update_ctime(d_inode(oldent));
77608b63307SMiklos Szeredi 
7771560c974SMiklos Szeredi 		if (flags & RENAME_EXCHANGE) {
7782b0143b5SDavid Howells 			fuse_invalidate_attr(d_inode(newent));
7792b0143b5SDavid Howells 			fuse_update_ctime(d_inode(newent));
7801560c974SMiklos Szeredi 		}
7811560c974SMiklos Szeredi 
782261aaba7SMiklos Szeredi 		fuse_dir_changed(olddir);
7839e6268dbSMiklos Szeredi 		if (olddir != newdir)
784261aaba7SMiklos Szeredi 			fuse_dir_changed(newdir);
7858cbdf1e6SMiklos Szeredi 
7868cbdf1e6SMiklos Szeredi 		/* newent will end up negative */
7872b0143b5SDavid Howells 		if (!(flags & RENAME_EXCHANGE) && d_really_is_positive(newent)) {
7882b0143b5SDavid Howells 			fuse_invalidate_attr(d_inode(newent));
7898cbdf1e6SMiklos Szeredi 			fuse_invalidate_entry_cache(newent);
7902b0143b5SDavid Howells 			fuse_update_ctime(d_inode(newent));
7915219f346SMiklos Szeredi 		}
7929e6268dbSMiklos Szeredi 	} else if (err == -EINTR) {
7939e6268dbSMiklos Szeredi 		/* If request was interrupted, DEITY only knows if the
7949e6268dbSMiklos Szeredi 		   rename actually took place.  If the invalidation
7959e6268dbSMiklos Szeredi 		   fails (e.g. some process has CWD under the renamed
7969e6268dbSMiklos Szeredi 		   directory), then there can be inconsistency between
7979e6268dbSMiklos Szeredi 		   the dcache and the real filesystem.  Tough luck. */
7989e6268dbSMiklos Szeredi 		fuse_invalidate_entry(oldent);
7992b0143b5SDavid Howells 		if (d_really_is_positive(newent))
8009e6268dbSMiklos Szeredi 			fuse_invalidate_entry(newent);
8019e6268dbSMiklos Szeredi 	}
8029e6268dbSMiklos Szeredi 
8039e6268dbSMiklos Szeredi 	return err;
8049e6268dbSMiklos Szeredi }
8059e6268dbSMiklos Szeredi 
8061560c974SMiklos Szeredi static int fuse_rename2(struct inode *olddir, struct dentry *oldent,
8071560c974SMiklos Szeredi 			struct inode *newdir, struct dentry *newent,
8081560c974SMiklos Szeredi 			unsigned int flags)
8091560c974SMiklos Szeredi {
8101560c974SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(olddir);
8111560c974SMiklos Szeredi 	int err;
8121560c974SMiklos Szeredi 
8131560c974SMiklos Szeredi 	if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE))
8141560c974SMiklos Szeredi 		return -EINVAL;
8151560c974SMiklos Szeredi 
8164237ba43SMiklos Szeredi 	if (flags) {
8171560c974SMiklos Szeredi 		if (fc->no_rename2 || fc->minor < 23)
8181560c974SMiklos Szeredi 			return -EINVAL;
8191560c974SMiklos Szeredi 
8201560c974SMiklos Szeredi 		err = fuse_rename_common(olddir, oldent, newdir, newent, flags,
8214237ba43SMiklos Szeredi 					 FUSE_RENAME2,
8224237ba43SMiklos Szeredi 					 sizeof(struct fuse_rename2_in));
8231560c974SMiklos Szeredi 		if (err == -ENOSYS) {
8241560c974SMiklos Szeredi 			fc->no_rename2 = 1;
8251560c974SMiklos Szeredi 			err = -EINVAL;
8261560c974SMiklos Szeredi 		}
8274237ba43SMiklos Szeredi 	} else {
8284237ba43SMiklos Szeredi 		err = fuse_rename_common(olddir, oldent, newdir, newent, 0,
8294237ba43SMiklos Szeredi 					 FUSE_RENAME,
8304237ba43SMiklos Szeredi 					 sizeof(struct fuse_rename_in));
8314237ba43SMiklos Szeredi 	}
8321560c974SMiklos Szeredi 
8334237ba43SMiklos Szeredi 	return err;
8344237ba43SMiklos Szeredi }
8354237ba43SMiklos Szeredi 
8369e6268dbSMiklos Szeredi static int fuse_link(struct dentry *entry, struct inode *newdir,
8379e6268dbSMiklos Szeredi 		     struct dentry *newent)
8389e6268dbSMiklos Szeredi {
8399e6268dbSMiklos Szeredi 	int err;
8409e6268dbSMiklos Szeredi 	struct fuse_link_in inarg;
8412b0143b5SDavid Howells 	struct inode *inode = d_inode(entry);
8429e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
8437078187aSMiklos Szeredi 	FUSE_ARGS(args);
8449e6268dbSMiklos Szeredi 
8459e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
8469e6268dbSMiklos Szeredi 	inarg.oldnodeid = get_node_id(inode);
847d5b48543SMiklos Szeredi 	args.opcode = FUSE_LINK;
848d5b48543SMiklos Szeredi 	args.in_numargs = 2;
849d5b48543SMiklos Szeredi 	args.in_args[0].size = sizeof(inarg);
850d5b48543SMiklos Szeredi 	args.in_args[0].value = &inarg;
851d5b48543SMiklos Szeredi 	args.in_args[1].size = newent->d_name.len + 1;
852d5b48543SMiklos Szeredi 	args.in_args[1].value = newent->d_name.name;
8537078187aSMiklos Szeredi 	err = create_new_entry(fc, &args, newdir, newent, inode->i_mode);
8549e6268dbSMiklos Szeredi 	/* Contrary to "normal" filesystems it can happen that link
8559e6268dbSMiklos Szeredi 	   makes two "logical" inodes point to the same "physical"
8569e6268dbSMiklos Szeredi 	   inode.  We invalidate the attributes of the old one, so it
8579e6268dbSMiklos Szeredi 	   will reflect changes in the backing inode (link count,
8589e6268dbSMiklos Szeredi 	   etc.)
8599e6268dbSMiklos Szeredi 	*/
860ac45d613SMiklos Szeredi 	if (!err) {
861ac45d613SMiklos Szeredi 		struct fuse_inode *fi = get_fuse_inode(inode);
862ac45d613SMiklos Szeredi 
863f15ecfefSKirill Tkhai 		spin_lock(&fi->lock);
8644510d86fSKirill Tkhai 		fi->attr_version = atomic64_inc_return(&fc->attr_version);
865ac45d613SMiklos Szeredi 		inc_nlink(inode);
866f15ecfefSKirill Tkhai 		spin_unlock(&fi->lock);
8679e6268dbSMiklos Szeredi 		fuse_invalidate_attr(inode);
86831f3267bSMaxim Patlasov 		fuse_update_ctime(inode);
869ac45d613SMiklos Szeredi 	} else if (err == -EINTR) {
870ac45d613SMiklos Szeredi 		fuse_invalidate_attr(inode);
871ac45d613SMiklos Szeredi 	}
8729e6268dbSMiklos Szeredi 	return err;
8739e6268dbSMiklos Szeredi }
8749e6268dbSMiklos Szeredi 
8751fb69e78SMiklos Szeredi static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
8761fb69e78SMiklos Szeredi 			  struct kstat *stat)
8771fb69e78SMiklos Szeredi {
878203627bbSMiklos Szeredi 	unsigned int blkbits;
8798373200bSPavel Emelyanov 	struct fuse_conn *fc = get_fuse_conn(inode);
8808373200bSPavel Emelyanov 
8818373200bSPavel Emelyanov 	/* see the comment in fuse_change_attributes() */
882b0aa7606SMaxim Patlasov 	if (fc->writeback_cache && S_ISREG(inode->i_mode)) {
8838373200bSPavel Emelyanov 		attr->size = i_size_read(inode);
884b0aa7606SMaxim Patlasov 		attr->mtime = inode->i_mtime.tv_sec;
885b0aa7606SMaxim Patlasov 		attr->mtimensec = inode->i_mtime.tv_nsec;
88631f3267bSMaxim Patlasov 		attr->ctime = inode->i_ctime.tv_sec;
88731f3267bSMaxim Patlasov 		attr->ctimensec = inode->i_ctime.tv_nsec;
888b0aa7606SMaxim Patlasov 	}
889203627bbSMiklos Szeredi 
8901fb69e78SMiklos Szeredi 	stat->dev = inode->i_sb->s_dev;
8911fb69e78SMiklos Szeredi 	stat->ino = attr->ino;
8921fb69e78SMiklos Szeredi 	stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
8931fb69e78SMiklos Szeredi 	stat->nlink = attr->nlink;
8948cb08329SEric W. Biederman 	stat->uid = make_kuid(fc->user_ns, attr->uid);
8958cb08329SEric W. Biederman 	stat->gid = make_kgid(fc->user_ns, attr->gid);
8961fb69e78SMiklos Szeredi 	stat->rdev = inode->i_rdev;
8971fb69e78SMiklos Szeredi 	stat->atime.tv_sec = attr->atime;
8981fb69e78SMiklos Szeredi 	stat->atime.tv_nsec = attr->atimensec;
8991fb69e78SMiklos Szeredi 	stat->mtime.tv_sec = attr->mtime;
9001fb69e78SMiklos Szeredi 	stat->mtime.tv_nsec = attr->mtimensec;
9011fb69e78SMiklos Szeredi 	stat->ctime.tv_sec = attr->ctime;
9021fb69e78SMiklos Szeredi 	stat->ctime.tv_nsec = attr->ctimensec;
9031fb69e78SMiklos Szeredi 	stat->size = attr->size;
9041fb69e78SMiklos Szeredi 	stat->blocks = attr->blocks;
905203627bbSMiklos Szeredi 
906203627bbSMiklos Szeredi 	if (attr->blksize != 0)
907203627bbSMiklos Szeredi 		blkbits = ilog2(attr->blksize);
908203627bbSMiklos Szeredi 	else
909203627bbSMiklos Szeredi 		blkbits = inode->i_sb->s_blocksize_bits;
910203627bbSMiklos Szeredi 
911203627bbSMiklos Szeredi 	stat->blksize = 1 << blkbits;
9121fb69e78SMiklos Szeredi }
9131fb69e78SMiklos Szeredi 
914c79e322fSMiklos Szeredi static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
915c79e322fSMiklos Szeredi 			   struct file *file)
916e5e5558eSMiklos Szeredi {
917e5e5558eSMiklos Szeredi 	int err;
918c79e322fSMiklos Szeredi 	struct fuse_getattr_in inarg;
919c79e322fSMiklos Szeredi 	struct fuse_attr_out outarg;
920e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
9217078187aSMiklos Szeredi 	FUSE_ARGS(args);
9221fb69e78SMiklos Szeredi 	u64 attr_version;
9231fb69e78SMiklos Szeredi 
9247dca9fd3SMiklos Szeredi 	attr_version = fuse_get_attr_version(fc);
9251fb69e78SMiklos Szeredi 
926c79e322fSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
9270e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
928c79e322fSMiklos Szeredi 	/* Directories have separate file-handle space */
929c79e322fSMiklos Szeredi 	if (file && S_ISREG(inode->i_mode)) {
930c79e322fSMiklos Szeredi 		struct fuse_file *ff = file->private_data;
931c79e322fSMiklos Szeredi 
932c79e322fSMiklos Szeredi 		inarg.getattr_flags |= FUSE_GETATTR_FH;
933c79e322fSMiklos Szeredi 		inarg.fh = ff->fh;
934c79e322fSMiklos Szeredi 	}
935d5b48543SMiklos Szeredi 	args.opcode = FUSE_GETATTR;
936d5b48543SMiklos Szeredi 	args.nodeid = get_node_id(inode);
937d5b48543SMiklos Szeredi 	args.in_numargs = 1;
938d5b48543SMiklos Szeredi 	args.in_args[0].size = sizeof(inarg);
939d5b48543SMiklos Szeredi 	args.in_args[0].value = &inarg;
940d5b48543SMiklos Szeredi 	args.out_numargs = 1;
941d5b48543SMiklos Szeredi 	args.out_args[0].size = sizeof(outarg);
942d5b48543SMiklos Szeredi 	args.out_args[0].value = &outarg;
9437078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
944e5e5558eSMiklos Szeredi 	if (!err) {
945c79e322fSMiklos Szeredi 		if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
946e5e5558eSMiklos Szeredi 			make_bad_inode(inode);
947e5e5558eSMiklos Szeredi 			err = -EIO;
948e5e5558eSMiklos Szeredi 		} else {
949c79e322fSMiklos Szeredi 			fuse_change_attributes(inode, &outarg.attr,
950c79e322fSMiklos Szeredi 					       attr_timeout(&outarg),
9511fb69e78SMiklos Szeredi 					       attr_version);
9521fb69e78SMiklos Szeredi 			if (stat)
953c79e322fSMiklos Szeredi 				fuse_fillattr(inode, &outarg.attr, stat);
954e5e5558eSMiklos Szeredi 		}
955e5e5558eSMiklos Szeredi 	}
956e5e5558eSMiklos Szeredi 	return err;
957e5e5558eSMiklos Szeredi }
958e5e5558eSMiklos Szeredi 
9595b97eeacSMiklos Szeredi static int fuse_update_get_attr(struct inode *inode, struct file *file,
9602f1e8196SMiklos Szeredi 				struct kstat *stat, u32 request_mask,
9612f1e8196SMiklos Szeredi 				unsigned int flags)
962bcb4be80SMiklos Szeredi {
963bcb4be80SMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
9645b97eeacSMiklos Szeredi 	int err = 0;
965bf5c1898SMiklos Szeredi 	bool sync;
966bcb4be80SMiklos Szeredi 
967bf5c1898SMiklos Szeredi 	if (flags & AT_STATX_FORCE_SYNC)
968bf5c1898SMiklos Szeredi 		sync = true;
969bf5c1898SMiklos Szeredi 	else if (flags & AT_STATX_DONT_SYNC)
970bf5c1898SMiklos Szeredi 		sync = false;
9712f1e8196SMiklos Szeredi 	else if (request_mask & READ_ONCE(fi->inval_mask))
9722f1e8196SMiklos Szeredi 		sync = true;
973bf5c1898SMiklos Szeredi 	else
974bf5c1898SMiklos Szeredi 		sync = time_before64(fi->i_time, get_jiffies_64());
975bf5c1898SMiklos Szeredi 
976bf5c1898SMiklos Szeredi 	if (sync) {
97760bcc88aSSeth Forshee 		forget_all_cached_acls(inode);
978bcb4be80SMiklos Szeredi 		err = fuse_do_getattr(inode, stat, file);
9795b97eeacSMiklos Szeredi 	} else if (stat) {
980bcb4be80SMiklos Szeredi 		generic_fillattr(inode, stat);
981bcb4be80SMiklos Szeredi 		stat->mode = fi->orig_i_mode;
98245c72cd7SPavel Shilovsky 		stat->ino = fi->orig_ino;
983bcb4be80SMiklos Szeredi 	}
984bcb4be80SMiklos Szeredi 
985bcb4be80SMiklos Szeredi 	return err;
986bcb4be80SMiklos Szeredi }
987bcb4be80SMiklos Szeredi 
9885b97eeacSMiklos Szeredi int fuse_update_attributes(struct inode *inode, struct file *file)
9895b97eeacSMiklos Szeredi {
990802dc049SMiklos Szeredi 	/* Do *not* need to get atime for internal purposes */
991802dc049SMiklos Szeredi 	return fuse_update_get_attr(inode, file, NULL,
992802dc049SMiklos Szeredi 				    STATX_BASIC_STATS & ~STATX_ATIME, 0);
9935b97eeacSMiklos Szeredi }
9945b97eeacSMiklos Szeredi 
9953b463ae0SJohn Muir int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid,
996451d0f59SJohn Muir 			     u64 child_nodeid, struct qstr *name)
9973b463ae0SJohn Muir {
9983b463ae0SJohn Muir 	int err = -ENOTDIR;
9993b463ae0SJohn Muir 	struct inode *parent;
10003b463ae0SJohn Muir 	struct dentry *dir;
10013b463ae0SJohn Muir 	struct dentry *entry;
10023b463ae0SJohn Muir 
10033b463ae0SJohn Muir 	parent = ilookup5(sb, parent_nodeid, fuse_inode_eq, &parent_nodeid);
10043b463ae0SJohn Muir 	if (!parent)
10053b463ae0SJohn Muir 		return -ENOENT;
10063b463ae0SJohn Muir 
10075955102cSAl Viro 	inode_lock(parent);
10083b463ae0SJohn Muir 	if (!S_ISDIR(parent->i_mode))
10093b463ae0SJohn Muir 		goto unlock;
10103b463ae0SJohn Muir 
10113b463ae0SJohn Muir 	err = -ENOENT;
10123b463ae0SJohn Muir 	dir = d_find_alias(parent);
10133b463ae0SJohn Muir 	if (!dir)
10143b463ae0SJohn Muir 		goto unlock;
10153b463ae0SJohn Muir 
10168387ff25SLinus Torvalds 	name->hash = full_name_hash(dir, name->name, name->len);
10173b463ae0SJohn Muir 	entry = d_lookup(dir, name);
10183b463ae0SJohn Muir 	dput(dir);
10193b463ae0SJohn Muir 	if (!entry)
10203b463ae0SJohn Muir 		goto unlock;
10213b463ae0SJohn Muir 
1022261aaba7SMiklos Szeredi 	fuse_dir_changed(parent);
10233b463ae0SJohn Muir 	fuse_invalidate_entry(entry);
1024451d0f59SJohn Muir 
10252b0143b5SDavid Howells 	if (child_nodeid != 0 && d_really_is_positive(entry)) {
10265955102cSAl Viro 		inode_lock(d_inode(entry));
10272b0143b5SDavid Howells 		if (get_node_id(d_inode(entry)) != child_nodeid) {
1028451d0f59SJohn Muir 			err = -ENOENT;
1029451d0f59SJohn Muir 			goto badentry;
1030451d0f59SJohn Muir 		}
1031451d0f59SJohn Muir 		if (d_mountpoint(entry)) {
1032451d0f59SJohn Muir 			err = -EBUSY;
1033451d0f59SJohn Muir 			goto badentry;
1034451d0f59SJohn Muir 		}
1035e36cb0b8SDavid Howells 		if (d_is_dir(entry)) {
1036451d0f59SJohn Muir 			shrink_dcache_parent(entry);
1037451d0f59SJohn Muir 			if (!simple_empty(entry)) {
1038451d0f59SJohn Muir 				err = -ENOTEMPTY;
1039451d0f59SJohn Muir 				goto badentry;
1040451d0f59SJohn Muir 			}
10412b0143b5SDavid Howells 			d_inode(entry)->i_flags |= S_DEAD;
1042451d0f59SJohn Muir 		}
1043451d0f59SJohn Muir 		dont_mount(entry);
10442b0143b5SDavid Howells 		clear_nlink(d_inode(entry));
10453b463ae0SJohn Muir 		err = 0;
1046451d0f59SJohn Muir  badentry:
10475955102cSAl Viro 		inode_unlock(d_inode(entry));
1048451d0f59SJohn Muir 		if (!err)
1049451d0f59SJohn Muir 			d_delete(entry);
1050451d0f59SJohn Muir 	} else {
1051451d0f59SJohn Muir 		err = 0;
1052451d0f59SJohn Muir 	}
1053451d0f59SJohn Muir 	dput(entry);
10543b463ae0SJohn Muir 
10553b463ae0SJohn Muir  unlock:
10565955102cSAl Viro 	inode_unlock(parent);
10573b463ae0SJohn Muir 	iput(parent);
10583b463ae0SJohn Muir 	return err;
10593b463ae0SJohn Muir }
10603b463ae0SJohn Muir 
106187729a55SMiklos Szeredi /*
106287729a55SMiklos Szeredi  * Calling into a user-controlled filesystem gives the filesystem
1063c2132c1bSAnatol Pomozov  * daemon ptrace-like capabilities over the current process.  This
106487729a55SMiklos Szeredi  * means, that the filesystem daemon is able to record the exact
106587729a55SMiklos Szeredi  * filesystem operations performed, and can also control the behavior
106687729a55SMiklos Szeredi  * of the requester process in otherwise impossible ways.  For example
106787729a55SMiklos Szeredi  * it can delay the operation for arbitrary length of time allowing
106887729a55SMiklos Szeredi  * DoS against the requester.
106987729a55SMiklos Szeredi  *
107087729a55SMiklos Szeredi  * For this reason only those processes can call into the filesystem,
107187729a55SMiklos Szeredi  * for which the owner of the mount has ptrace privilege.  This
107287729a55SMiklos Szeredi  * excludes processes started by other users, suid or sgid processes.
107387729a55SMiklos Szeredi  */
1074c2132c1bSAnatol Pomozov int fuse_allow_current_process(struct fuse_conn *fc)
107587729a55SMiklos Szeredi {
1076c69e8d9cSDavid Howells 	const struct cred *cred;
1077c69e8d9cSDavid Howells 
107829433a29SMiklos Szeredi 	if (fc->allow_other)
107973f03c2bSSeth Forshee 		return current_in_userns(fc->user_ns);
108087729a55SMiklos Szeredi 
1081c2132c1bSAnatol Pomozov 	cred = current_cred();
1082499dcf20SEric W. Biederman 	if (uid_eq(cred->euid, fc->user_id) &&
1083499dcf20SEric W. Biederman 	    uid_eq(cred->suid, fc->user_id) &&
1084499dcf20SEric W. Biederman 	    uid_eq(cred->uid,  fc->user_id) &&
1085499dcf20SEric W. Biederman 	    gid_eq(cred->egid, fc->group_id) &&
1086499dcf20SEric W. Biederman 	    gid_eq(cred->sgid, fc->group_id) &&
1087499dcf20SEric W. Biederman 	    gid_eq(cred->gid,  fc->group_id))
1088c2132c1bSAnatol Pomozov 		return 1;
108987729a55SMiklos Szeredi 
1090c2132c1bSAnatol Pomozov 	return 0;
109187729a55SMiklos Szeredi }
109287729a55SMiklos Szeredi 
109331d40d74SMiklos Szeredi static int fuse_access(struct inode *inode, int mask)
109431d40d74SMiklos Szeredi {
109531d40d74SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
10967078187aSMiklos Szeredi 	FUSE_ARGS(args);
109731d40d74SMiklos Szeredi 	struct fuse_access_in inarg;
109831d40d74SMiklos Szeredi 	int err;
109931d40d74SMiklos Szeredi 
1100698fa1d1SMiklos Szeredi 	BUG_ON(mask & MAY_NOT_BLOCK);
1101698fa1d1SMiklos Szeredi 
110231d40d74SMiklos Szeredi 	if (fc->no_access)
110331d40d74SMiklos Szeredi 		return 0;
110431d40d74SMiklos Szeredi 
110531d40d74SMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
1106e6305c43SAl Viro 	inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC);
1107d5b48543SMiklos Szeredi 	args.opcode = FUSE_ACCESS;
1108d5b48543SMiklos Szeredi 	args.nodeid = get_node_id(inode);
1109d5b48543SMiklos Szeredi 	args.in_numargs = 1;
1110d5b48543SMiklos Szeredi 	args.in_args[0].size = sizeof(inarg);
1111d5b48543SMiklos Szeredi 	args.in_args[0].value = &inarg;
11127078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
111331d40d74SMiklos Szeredi 	if (err == -ENOSYS) {
111431d40d74SMiklos Szeredi 		fc->no_access = 1;
111531d40d74SMiklos Szeredi 		err = 0;
111631d40d74SMiklos Szeredi 	}
111731d40d74SMiklos Szeredi 	return err;
111831d40d74SMiklos Szeredi }
111931d40d74SMiklos Szeredi 
112010556cb2SAl Viro static int fuse_perm_getattr(struct inode *inode, int mask)
112119690ddbSMiklos Szeredi {
112210556cb2SAl Viro 	if (mask & MAY_NOT_BLOCK)
112319690ddbSMiklos Szeredi 		return -ECHILD;
112419690ddbSMiklos Szeredi 
112560bcc88aSSeth Forshee 	forget_all_cached_acls(inode);
112619690ddbSMiklos Szeredi 	return fuse_do_getattr(inode, NULL, NULL);
112719690ddbSMiklos Szeredi }
112819690ddbSMiklos Szeredi 
11296f9f1180SMiklos Szeredi /*
11306f9f1180SMiklos Szeredi  * Check permission.  The two basic access models of FUSE are:
11316f9f1180SMiklos Szeredi  *
11326f9f1180SMiklos Szeredi  * 1) Local access checking ('default_permissions' mount option) based
11336f9f1180SMiklos Szeredi  * on file mode.  This is the plain old disk filesystem permission
11346f9f1180SMiklos Szeredi  * modell.
11356f9f1180SMiklos Szeredi  *
11366f9f1180SMiklos Szeredi  * 2) "Remote" access checking, where server is responsible for
11376f9f1180SMiklos Szeredi  * checking permission in each inode operation.  An exception to this
11386f9f1180SMiklos Szeredi  * is if ->permission() was invoked from sys_access() in which case an
11396f9f1180SMiklos Szeredi  * access request is sent.  Execute permission is still checked
11406f9f1180SMiklos Szeredi  * locally based on file mode.
11416f9f1180SMiklos Szeredi  */
114210556cb2SAl Viro static int fuse_permission(struct inode *inode, int mask)
1143e5e5558eSMiklos Szeredi {
1144e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1145244f6385SMiklos Szeredi 	bool refreshed = false;
1146244f6385SMiklos Szeredi 	int err = 0;
1147e5e5558eSMiklos Szeredi 
1148c2132c1bSAnatol Pomozov 	if (!fuse_allow_current_process(fc))
1149e5e5558eSMiklos Szeredi 		return -EACCES;
1150244f6385SMiklos Szeredi 
1151244f6385SMiklos Szeredi 	/*
1152e8e96157SMiklos Szeredi 	 * If attributes are needed, refresh them before proceeding
1153244f6385SMiklos Szeredi 	 */
115429433a29SMiklos Szeredi 	if (fc->default_permissions ||
1155e8e96157SMiklos Szeredi 	    ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
115619690ddbSMiklos Szeredi 		struct fuse_inode *fi = get_fuse_inode(inode);
1157d233c7ddSMiklos Szeredi 		u32 perm_mask = STATX_MODE | STATX_UID | STATX_GID;
115819690ddbSMiklos Szeredi 
1159d233c7ddSMiklos Szeredi 		if (perm_mask & READ_ONCE(fi->inval_mask) ||
1160d233c7ddSMiklos Szeredi 		    time_before64(fi->i_time, get_jiffies_64())) {
116119690ddbSMiklos Szeredi 			refreshed = true;
116219690ddbSMiklos Szeredi 
116310556cb2SAl Viro 			err = fuse_perm_getattr(inode, mask);
1164244f6385SMiklos Szeredi 			if (err)
1165244f6385SMiklos Szeredi 				return err;
11661fb69e78SMiklos Szeredi 		}
116719690ddbSMiklos Szeredi 	}
1168244f6385SMiklos Szeredi 
116929433a29SMiklos Szeredi 	if (fc->default_permissions) {
11702830ba7fSAl Viro 		err = generic_permission(inode, mask);
11711e9a4ed9SMiklos Szeredi 
11721e9a4ed9SMiklos Szeredi 		/* If permission is denied, try to refresh file
11731e9a4ed9SMiklos Szeredi 		   attributes.  This is also needed, because the root
11741e9a4ed9SMiklos Szeredi 		   node will at first have no permissions */
1175244f6385SMiklos Szeredi 		if (err == -EACCES && !refreshed) {
117610556cb2SAl Viro 			err = fuse_perm_getattr(inode, mask);
11771e9a4ed9SMiklos Szeredi 			if (!err)
11782830ba7fSAl Viro 				err = generic_permission(inode, mask);
11791e9a4ed9SMiklos Szeredi 		}
11801e9a4ed9SMiklos Szeredi 
11816f9f1180SMiklos Szeredi 		/* Note: the opposite of the above test does not
11826f9f1180SMiklos Szeredi 		   exist.  So if permissions are revoked this won't be
11836f9f1180SMiklos Szeredi 		   noticed immediately, only after the attribute
11846f9f1180SMiklos Szeredi 		   timeout has expired */
11859cfcac81SEric Paris 	} else if (mask & (MAY_ACCESS | MAY_CHDIR)) {
1186e8e96157SMiklos Szeredi 		err = fuse_access(inode, mask);
1187e8e96157SMiklos Szeredi 	} else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
1188e8e96157SMiklos Szeredi 		if (!(inode->i_mode & S_IXUGO)) {
1189e8e96157SMiklos Szeredi 			if (refreshed)
1190e5e5558eSMiklos Szeredi 				return -EACCES;
119131d40d74SMiklos Szeredi 
119210556cb2SAl Viro 			err = fuse_perm_getattr(inode, mask);
1193e8e96157SMiklos Szeredi 			if (!err && !(inode->i_mode & S_IXUGO))
1194e8e96157SMiklos Szeredi 				return -EACCES;
1195e8e96157SMiklos Szeredi 		}
1196e5e5558eSMiklos Szeredi 	}
1197244f6385SMiklos Szeredi 	return err;
1198e5e5558eSMiklos Szeredi }
1199e5e5558eSMiklos Szeredi 
12005571f1e6SDan Schatzberg static int fuse_readlink_page(struct inode *inode, struct page *page)
1201e5e5558eSMiklos Szeredi {
1202e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
12034c29afecSMiklos Szeredi 	struct fuse_page_desc desc = { .length = PAGE_SIZE - 1 };
12044c29afecSMiklos Szeredi 	struct fuse_args_pages ap = {
12054c29afecSMiklos Szeredi 		.num_pages = 1,
12064c29afecSMiklos Szeredi 		.pages = &page,
12074c29afecSMiklos Szeredi 		.descs = &desc,
12084c29afecSMiklos Szeredi 	};
12094c29afecSMiklos Szeredi 	char *link;
12104c29afecSMiklos Szeredi 	ssize_t res;
1211e5e5558eSMiklos Szeredi 
12124c29afecSMiklos Szeredi 	ap.args.opcode = FUSE_READLINK;
12134c29afecSMiklos Szeredi 	ap.args.nodeid = get_node_id(inode);
12144c29afecSMiklos Szeredi 	ap.args.out_pages = true;
12154c29afecSMiklos Szeredi 	ap.args.out_argvar = true;
12164c29afecSMiklos Szeredi 	ap.args.page_zeroing = true;
12174c29afecSMiklos Szeredi 	ap.args.out_numargs = 1;
12184c29afecSMiklos Szeredi 	ap.args.out_args[0].size = desc.length;
12194c29afecSMiklos Szeredi 	res = fuse_simple_request(fc, &ap.args);
12206b255391SAl Viro 
1221451418fcSAndrew Gallagher 	fuse_invalidate_atime(inode);
12225571f1e6SDan Schatzberg 
12234c29afecSMiklos Szeredi 	if (res < 0)
12244c29afecSMiklos Szeredi 		return res;
12254c29afecSMiklos Szeredi 
12264c29afecSMiklos Szeredi 	if (WARN_ON(res >= PAGE_SIZE))
12274c29afecSMiklos Szeredi 		return -EIO;
12284c29afecSMiklos Szeredi 
12294c29afecSMiklos Szeredi 	link = page_address(page);
12304c29afecSMiklos Szeredi 	link[res] = '\0';
12314c29afecSMiklos Szeredi 
12324c29afecSMiklos Szeredi 	return 0;
12335571f1e6SDan Schatzberg }
12345571f1e6SDan Schatzberg 
12355571f1e6SDan Schatzberg static const char *fuse_get_link(struct dentry *dentry, struct inode *inode,
12365571f1e6SDan Schatzberg 				 struct delayed_call *callback)
12375571f1e6SDan Schatzberg {
12385571f1e6SDan Schatzberg 	struct fuse_conn *fc = get_fuse_conn(inode);
12395571f1e6SDan Schatzberg 	struct page *page;
12405571f1e6SDan Schatzberg 	int err;
12415571f1e6SDan Schatzberg 
12425571f1e6SDan Schatzberg 	err = -EIO;
12435571f1e6SDan Schatzberg 	if (is_bad_inode(inode))
12445571f1e6SDan Schatzberg 		goto out_err;
12455571f1e6SDan Schatzberg 
12465571f1e6SDan Schatzberg 	if (fc->cache_symlinks)
12475571f1e6SDan Schatzberg 		return page_get_link(dentry, inode, callback);
12485571f1e6SDan Schatzberg 
12495571f1e6SDan Schatzberg 	err = -ECHILD;
12505571f1e6SDan Schatzberg 	if (!dentry)
12515571f1e6SDan Schatzberg 		goto out_err;
12525571f1e6SDan Schatzberg 
12535571f1e6SDan Schatzberg 	page = alloc_page(GFP_KERNEL);
12545571f1e6SDan Schatzberg 	err = -ENOMEM;
12555571f1e6SDan Schatzberg 	if (!page)
12565571f1e6SDan Schatzberg 		goto out_err;
12575571f1e6SDan Schatzberg 
12585571f1e6SDan Schatzberg 	err = fuse_readlink_page(inode, page);
12595571f1e6SDan Schatzberg 	if (err) {
12605571f1e6SDan Schatzberg 		__free_page(page);
12615571f1e6SDan Schatzberg 		goto out_err;
12625571f1e6SDan Schatzberg 	}
12635571f1e6SDan Schatzberg 
12645571f1e6SDan Schatzberg 	set_delayed_call(callback, page_put_link, page);
12655571f1e6SDan Schatzberg 
12665571f1e6SDan Schatzberg 	return page_address(page);
12675571f1e6SDan Schatzberg 
12685571f1e6SDan Schatzberg out_err:
12695571f1e6SDan Schatzberg 	return ERR_PTR(err);
1270e5e5558eSMiklos Szeredi }
1271e5e5558eSMiklos Szeredi 
1272e5e5558eSMiklos Szeredi static int fuse_dir_open(struct inode *inode, struct file *file)
1273e5e5558eSMiklos Szeredi {
127491fe96b4SMiklos Szeredi 	return fuse_open_common(inode, file, true);
1275e5e5558eSMiklos Szeredi }
1276e5e5558eSMiklos Szeredi 
1277e5e5558eSMiklos Szeredi static int fuse_dir_release(struct inode *inode, struct file *file)
1278e5e5558eSMiklos Szeredi {
12792e64ff15SChad Austin 	fuse_release_common(file, true);
12808b0797a4SMiklos Szeredi 
12818b0797a4SMiklos Szeredi 	return 0;
1282e5e5558eSMiklos Szeredi }
1283e5e5558eSMiklos Szeredi 
128402c24a82SJosef Bacik static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end,
128502c24a82SJosef Bacik 			  int datasync)
128682547981SMiklos Szeredi {
1287a9c2d1e8SMiklos Szeredi 	struct inode *inode = file->f_mapping->host;
1288a9c2d1e8SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1289a9c2d1e8SMiklos Szeredi 	int err;
1290a9c2d1e8SMiklos Szeredi 
1291a9c2d1e8SMiklos Szeredi 	if (is_bad_inode(inode))
1292a9c2d1e8SMiklos Szeredi 		return -EIO;
1293a9c2d1e8SMiklos Szeredi 
1294a9c2d1e8SMiklos Szeredi 	if (fc->no_fsyncdir)
1295a9c2d1e8SMiklos Szeredi 		return 0;
1296a9c2d1e8SMiklos Szeredi 
1297a9c2d1e8SMiklos Szeredi 	inode_lock(inode);
1298a9c2d1e8SMiklos Szeredi 	err = fuse_fsync_common(file, start, end, datasync, FUSE_FSYNCDIR);
1299a9c2d1e8SMiklos Szeredi 	if (err == -ENOSYS) {
1300a9c2d1e8SMiklos Szeredi 		fc->no_fsyncdir = 1;
1301a9c2d1e8SMiklos Szeredi 		err = 0;
1302a9c2d1e8SMiklos Szeredi 	}
1303a9c2d1e8SMiklos Szeredi 	inode_unlock(inode);
1304a9c2d1e8SMiklos Szeredi 
1305a9c2d1e8SMiklos Szeredi 	return err;
130682547981SMiklos Szeredi }
130782547981SMiklos Szeredi 
1308b18da0c5SMiklos Szeredi static long fuse_dir_ioctl(struct file *file, unsigned int cmd,
1309b18da0c5SMiklos Szeredi 			    unsigned long arg)
1310b18da0c5SMiklos Szeredi {
1311b18da0c5SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1312b18da0c5SMiklos Szeredi 
1313b18da0c5SMiklos Szeredi 	/* FUSE_IOCTL_DIR only supported for API version >= 7.18 */
1314b18da0c5SMiklos Szeredi 	if (fc->minor < 18)
1315b18da0c5SMiklos Szeredi 		return -ENOTTY;
1316b18da0c5SMiklos Szeredi 
1317b18da0c5SMiklos Szeredi 	return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR);
1318b18da0c5SMiklos Szeredi }
1319b18da0c5SMiklos Szeredi 
1320b18da0c5SMiklos Szeredi static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd,
1321b18da0c5SMiklos Szeredi 				   unsigned long arg)
1322b18da0c5SMiklos Szeredi {
1323b18da0c5SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1324b18da0c5SMiklos Szeredi 
1325b18da0c5SMiklos Szeredi 	if (fc->minor < 18)
1326b18da0c5SMiklos Szeredi 		return -ENOTTY;
1327b18da0c5SMiklos Szeredi 
1328b18da0c5SMiklos Szeredi 	return fuse_ioctl_common(file, cmd, arg,
1329b18da0c5SMiklos Szeredi 				 FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR);
1330b18da0c5SMiklos Szeredi }
1331b18da0c5SMiklos Szeredi 
1332b0aa7606SMaxim Patlasov static bool update_mtime(unsigned ivalid, bool trust_local_mtime)
133317637cbaSMiklos Szeredi {
133417637cbaSMiklos Szeredi 	/* Always update if mtime is explicitly set  */
133517637cbaSMiklos Szeredi 	if (ivalid & ATTR_MTIME_SET)
133617637cbaSMiklos Szeredi 		return true;
133717637cbaSMiklos Szeredi 
1338b0aa7606SMaxim Patlasov 	/* Or if kernel i_mtime is the official one */
1339b0aa7606SMaxim Patlasov 	if (trust_local_mtime)
1340b0aa7606SMaxim Patlasov 		return true;
1341b0aa7606SMaxim Patlasov 
134217637cbaSMiklos Szeredi 	/* If it's an open(O_TRUNC) or an ftruncate(), don't update */
134317637cbaSMiklos Szeredi 	if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
134417637cbaSMiklos Szeredi 		return false;
134517637cbaSMiklos Szeredi 
134617637cbaSMiklos Szeredi 	/* In all other cases update */
134717637cbaSMiklos Szeredi 	return true;
134817637cbaSMiklos Szeredi }
134917637cbaSMiklos Szeredi 
13508cb08329SEric W. Biederman static void iattr_to_fattr(struct fuse_conn *fc, struct iattr *iattr,
13518cb08329SEric W. Biederman 			   struct fuse_setattr_in *arg, bool trust_local_cmtime)
13529e6268dbSMiklos Szeredi {
13539e6268dbSMiklos Szeredi 	unsigned ivalid = iattr->ia_valid;
13549e6268dbSMiklos Szeredi 
13559e6268dbSMiklos Szeredi 	if (ivalid & ATTR_MODE)
1356befc649cSMiklos Szeredi 		arg->valid |= FATTR_MODE,   arg->mode = iattr->ia_mode;
13579e6268dbSMiklos Szeredi 	if (ivalid & ATTR_UID)
13588cb08329SEric W. Biederman 		arg->valid |= FATTR_UID,    arg->uid = from_kuid(fc->user_ns, iattr->ia_uid);
13599e6268dbSMiklos Szeredi 	if (ivalid & ATTR_GID)
13608cb08329SEric W. Biederman 		arg->valid |= FATTR_GID,    arg->gid = from_kgid(fc->user_ns, iattr->ia_gid);
13619e6268dbSMiklos Szeredi 	if (ivalid & ATTR_SIZE)
1362befc649cSMiklos Szeredi 		arg->valid |= FATTR_SIZE,   arg->size = iattr->ia_size;
136317637cbaSMiklos Szeredi 	if (ivalid & ATTR_ATIME) {
136417637cbaSMiklos Szeredi 		arg->valid |= FATTR_ATIME;
1365befc649cSMiklos Szeredi 		arg->atime = iattr->ia_atime.tv_sec;
136617637cbaSMiklos Szeredi 		arg->atimensec = iattr->ia_atime.tv_nsec;
136717637cbaSMiklos Szeredi 		if (!(ivalid & ATTR_ATIME_SET))
136817637cbaSMiklos Szeredi 			arg->valid |= FATTR_ATIME_NOW;
136917637cbaSMiklos Szeredi 	}
13703ad22c62SMaxim Patlasov 	if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, trust_local_cmtime)) {
137117637cbaSMiklos Szeredi 		arg->valid |= FATTR_MTIME;
1372befc649cSMiklos Szeredi 		arg->mtime = iattr->ia_mtime.tv_sec;
137317637cbaSMiklos Szeredi 		arg->mtimensec = iattr->ia_mtime.tv_nsec;
13743ad22c62SMaxim Patlasov 		if (!(ivalid & ATTR_MTIME_SET) && !trust_local_cmtime)
137517637cbaSMiklos Szeredi 			arg->valid |= FATTR_MTIME_NOW;
13769e6268dbSMiklos Szeredi 	}
13773ad22c62SMaxim Patlasov 	if ((ivalid & ATTR_CTIME) && trust_local_cmtime) {
13783ad22c62SMaxim Patlasov 		arg->valid |= FATTR_CTIME;
13793ad22c62SMaxim Patlasov 		arg->ctime = iattr->ia_ctime.tv_sec;
13803ad22c62SMaxim Patlasov 		arg->ctimensec = iattr->ia_ctime.tv_nsec;
13813ad22c62SMaxim Patlasov 	}
13829e6268dbSMiklos Szeredi }
13839e6268dbSMiklos Szeredi 
13846f9f1180SMiklos Szeredi /*
13853be5a52bSMiklos Szeredi  * Prevent concurrent writepages on inode
13863be5a52bSMiklos Szeredi  *
13873be5a52bSMiklos Szeredi  * This is done by adding a negative bias to the inode write counter
13883be5a52bSMiklos Szeredi  * and waiting for all pending writes to finish.
13893be5a52bSMiklos Szeredi  */
13903be5a52bSMiklos Szeredi void fuse_set_nowrite(struct inode *inode)
13913be5a52bSMiklos Szeredi {
13923be5a52bSMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
13933be5a52bSMiklos Szeredi 
13945955102cSAl Viro 	BUG_ON(!inode_is_locked(inode));
13953be5a52bSMiklos Szeredi 
1396f15ecfefSKirill Tkhai 	spin_lock(&fi->lock);
13973be5a52bSMiklos Szeredi 	BUG_ON(fi->writectr < 0);
13983be5a52bSMiklos Szeredi 	fi->writectr += FUSE_NOWRITE;
1399f15ecfefSKirill Tkhai 	spin_unlock(&fi->lock);
14003be5a52bSMiklos Szeredi 	wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE);
14013be5a52bSMiklos Szeredi }
14023be5a52bSMiklos Szeredi 
14033be5a52bSMiklos Szeredi /*
14043be5a52bSMiklos Szeredi  * Allow writepages on inode
14053be5a52bSMiklos Szeredi  *
14063be5a52bSMiklos Szeredi  * Remove the bias from the writecounter and send any queued
14073be5a52bSMiklos Szeredi  * writepages.
14083be5a52bSMiklos Szeredi  */
14093be5a52bSMiklos Szeredi static void __fuse_release_nowrite(struct inode *inode)
14103be5a52bSMiklos Szeredi {
14113be5a52bSMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
14123be5a52bSMiklos Szeredi 
14133be5a52bSMiklos Szeredi 	BUG_ON(fi->writectr != FUSE_NOWRITE);
14143be5a52bSMiklos Szeredi 	fi->writectr = 0;
14153be5a52bSMiklos Szeredi 	fuse_flush_writepages(inode);
14163be5a52bSMiklos Szeredi }
14173be5a52bSMiklos Szeredi 
14183be5a52bSMiklos Szeredi void fuse_release_nowrite(struct inode *inode)
14193be5a52bSMiklos Szeredi {
1420f15ecfefSKirill Tkhai 	struct fuse_inode *fi = get_fuse_inode(inode);
14213be5a52bSMiklos Szeredi 
1422f15ecfefSKirill Tkhai 	spin_lock(&fi->lock);
14233be5a52bSMiklos Szeredi 	__fuse_release_nowrite(inode);
1424f15ecfefSKirill Tkhai 	spin_unlock(&fi->lock);
14253be5a52bSMiklos Szeredi }
14263be5a52bSMiklos Szeredi 
14277078187aSMiklos Szeredi static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_args *args,
1428b0aa7606SMaxim Patlasov 			      struct inode *inode,
1429b0aa7606SMaxim Patlasov 			      struct fuse_setattr_in *inarg_p,
1430b0aa7606SMaxim Patlasov 			      struct fuse_attr_out *outarg_p)
1431b0aa7606SMaxim Patlasov {
1432d5b48543SMiklos Szeredi 	args->opcode = FUSE_SETATTR;
1433d5b48543SMiklos Szeredi 	args->nodeid = get_node_id(inode);
1434d5b48543SMiklos Szeredi 	args->in_numargs = 1;
1435d5b48543SMiklos Szeredi 	args->in_args[0].size = sizeof(*inarg_p);
1436d5b48543SMiklos Szeredi 	args->in_args[0].value = inarg_p;
1437d5b48543SMiklos Szeredi 	args->out_numargs = 1;
1438d5b48543SMiklos Szeredi 	args->out_args[0].size = sizeof(*outarg_p);
1439d5b48543SMiklos Szeredi 	args->out_args[0].value = outarg_p;
1440b0aa7606SMaxim Patlasov }
1441b0aa7606SMaxim Patlasov 
1442b0aa7606SMaxim Patlasov /*
1443b0aa7606SMaxim Patlasov  * Flush inode->i_mtime to the server
1444b0aa7606SMaxim Patlasov  */
1445ab9e13f7SMaxim Patlasov int fuse_flush_times(struct inode *inode, struct fuse_file *ff)
1446b0aa7606SMaxim Patlasov {
1447b0aa7606SMaxim Patlasov 	struct fuse_conn *fc = get_fuse_conn(inode);
14487078187aSMiklos Szeredi 	FUSE_ARGS(args);
1449b0aa7606SMaxim Patlasov 	struct fuse_setattr_in inarg;
1450b0aa7606SMaxim Patlasov 	struct fuse_attr_out outarg;
1451b0aa7606SMaxim Patlasov 
1452b0aa7606SMaxim Patlasov 	memset(&inarg, 0, sizeof(inarg));
1453b0aa7606SMaxim Patlasov 	memset(&outarg, 0, sizeof(outarg));
1454b0aa7606SMaxim Patlasov 
1455ab9e13f7SMaxim Patlasov 	inarg.valid = FATTR_MTIME;
1456b0aa7606SMaxim Patlasov 	inarg.mtime = inode->i_mtime.tv_sec;
1457b0aa7606SMaxim Patlasov 	inarg.mtimensec = inode->i_mtime.tv_nsec;
1458ab9e13f7SMaxim Patlasov 	if (fc->minor >= 23) {
1459ab9e13f7SMaxim Patlasov 		inarg.valid |= FATTR_CTIME;
1460ab9e13f7SMaxim Patlasov 		inarg.ctime = inode->i_ctime.tv_sec;
1461ab9e13f7SMaxim Patlasov 		inarg.ctimensec = inode->i_ctime.tv_nsec;
1462ab9e13f7SMaxim Patlasov 	}
14631e18bda8SMiklos Szeredi 	if (ff) {
14641e18bda8SMiklos Szeredi 		inarg.valid |= FATTR_FH;
14651e18bda8SMiklos Szeredi 		inarg.fh = ff->fh;
14661e18bda8SMiklos Szeredi 	}
14677078187aSMiklos Szeredi 	fuse_setattr_fill(fc, &args, inode, &inarg, &outarg);
1468b0aa7606SMaxim Patlasov 
14697078187aSMiklos Szeredi 	return fuse_simple_request(fc, &args);
1470b0aa7606SMaxim Patlasov }
1471b0aa7606SMaxim Patlasov 
14723be5a52bSMiklos Szeredi /*
14736f9f1180SMiklos Szeredi  * Set attributes, and at the same time refresh them.
14746f9f1180SMiklos Szeredi  *
14756f9f1180SMiklos Szeredi  * Truncation is slightly complicated, because the 'truncate' request
14766f9f1180SMiklos Szeredi  * may fail, in which case we don't want to touch the mapping.
14779ffbb916SMiklos Szeredi  * vmtruncate() doesn't allow for this case, so do the rlimit checking
14789ffbb916SMiklos Szeredi  * and the actual truncation by hand.
14796f9f1180SMiklos Szeredi  */
148062490330SJan Kara int fuse_do_setattr(struct dentry *dentry, struct iattr *attr,
148149d4914fSMiklos Szeredi 		    struct file *file)
14829e6268dbSMiklos Szeredi {
148362490330SJan Kara 	struct inode *inode = d_inode(dentry);
14849e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
148506a7c3c2SMaxim Patlasov 	struct fuse_inode *fi = get_fuse_inode(inode);
14867078187aSMiklos Szeredi 	FUSE_ARGS(args);
14879e6268dbSMiklos Szeredi 	struct fuse_setattr_in inarg;
14889e6268dbSMiklos Szeredi 	struct fuse_attr_out outarg;
14893be5a52bSMiklos Szeredi 	bool is_truncate = false;
14908373200bSPavel Emelyanov 	bool is_wb = fc->writeback_cache;
14913be5a52bSMiklos Szeredi 	loff_t oldsize;
14929e6268dbSMiklos Szeredi 	int err;
14933ad22c62SMaxim Patlasov 	bool trust_local_cmtime = is_wb && S_ISREG(inode->i_mode);
14949e6268dbSMiklos Szeredi 
149529433a29SMiklos Szeredi 	if (!fc->default_permissions)
1496db78b877SChristoph Hellwig 		attr->ia_valid |= ATTR_FORCE;
1497db78b877SChristoph Hellwig 
149831051c85SJan Kara 	err = setattr_prepare(dentry, attr);
14991e9a4ed9SMiklos Szeredi 	if (err)
15001e9a4ed9SMiklos Szeredi 		return err;
15011e9a4ed9SMiklos Szeredi 
15028d56adddSMiklos Szeredi 	if (attr->ia_valid & ATTR_OPEN) {
1503df0e91d4SMiklos Szeredi 		/* This is coming from open(..., ... | O_TRUNC); */
1504df0e91d4SMiklos Szeredi 		WARN_ON(!(attr->ia_valid & ATTR_SIZE));
1505df0e91d4SMiklos Szeredi 		WARN_ON(attr->ia_size != 0);
1506df0e91d4SMiklos Szeredi 		if (fc->atomic_o_trunc) {
1507df0e91d4SMiklos Szeredi 			/*
1508df0e91d4SMiklos Szeredi 			 * No need to send request to userspace, since actual
1509df0e91d4SMiklos Szeredi 			 * truncation has already been done by OPEN.  But still
1510df0e91d4SMiklos Szeredi 			 * need to truncate page cache.
1511df0e91d4SMiklos Szeredi 			 */
1512df0e91d4SMiklos Szeredi 			i_size_write(inode, 0);
1513df0e91d4SMiklos Szeredi 			truncate_pagecache(inode, 0);
15146ff958edSMiklos Szeredi 			return 0;
1515df0e91d4SMiklos Szeredi 		}
15168d56adddSMiklos Szeredi 		file = NULL;
15178d56adddSMiklos Szeredi 	}
15186ff958edSMiklos Szeredi 
1519ab2257e9SMiklos Szeredi 	if (attr->ia_valid & ATTR_SIZE) {
1520ab2257e9SMiklos Szeredi 		if (WARN_ON(!S_ISREG(inode->i_mode)))
1521ab2257e9SMiklos Szeredi 			return -EIO;
15223be5a52bSMiklos Szeredi 		is_truncate = true;
1523ab2257e9SMiklos Szeredi 	}
15249e6268dbSMiklos Szeredi 
152506a7c3c2SMaxim Patlasov 	if (is_truncate) {
15263be5a52bSMiklos Szeredi 		fuse_set_nowrite(inode);
152706a7c3c2SMaxim Patlasov 		set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
15283ad22c62SMaxim Patlasov 		if (trust_local_cmtime && attr->ia_size != inode->i_size)
15293ad22c62SMaxim Patlasov 			attr->ia_valid |= ATTR_MTIME | ATTR_CTIME;
153006a7c3c2SMaxim Patlasov 	}
15313be5a52bSMiklos Szeredi 
15329e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
15330e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
15348cb08329SEric W. Biederman 	iattr_to_fattr(fc, attr, &inarg, trust_local_cmtime);
153549d4914fSMiklos Szeredi 	if (file) {
153649d4914fSMiklos Szeredi 		struct fuse_file *ff = file->private_data;
153749d4914fSMiklos Szeredi 		inarg.valid |= FATTR_FH;
153849d4914fSMiklos Szeredi 		inarg.fh = ff->fh;
153949d4914fSMiklos Szeredi 	}
1540f3332114SMiklos Szeredi 	if (attr->ia_valid & ATTR_SIZE) {
1541f3332114SMiklos Szeredi 		/* For mandatory locking in truncate */
1542f3332114SMiklos Szeredi 		inarg.valid |= FATTR_LOCKOWNER;
1543f3332114SMiklos Szeredi 		inarg.lock_owner = fuse_lock_owner_id(fc, current->files);
1544f3332114SMiklos Szeredi 	}
15457078187aSMiklos Szeredi 	fuse_setattr_fill(fc, &args, inode, &inarg, &outarg);
15467078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
1547e00d2c2dSMiklos Szeredi 	if (err) {
1548e00d2c2dSMiklos Szeredi 		if (err == -EINTR)
1549e00d2c2dSMiklos Szeredi 			fuse_invalidate_attr(inode);
15503be5a52bSMiklos Szeredi 		goto error;
1551e00d2c2dSMiklos Szeredi 	}
1552e00d2c2dSMiklos Szeredi 
15539e6268dbSMiklos Szeredi 	if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
15549e6268dbSMiklos Szeredi 		make_bad_inode(inode);
15553be5a52bSMiklos Szeredi 		err = -EIO;
15563be5a52bSMiklos Szeredi 		goto error;
15579e6268dbSMiklos Szeredi 	}
15589e6268dbSMiklos Szeredi 
1559f15ecfefSKirill Tkhai 	spin_lock(&fi->lock);
1560b0aa7606SMaxim Patlasov 	/* the kernel maintains i_mtime locally */
15613ad22c62SMaxim Patlasov 	if (trust_local_cmtime) {
15623ad22c62SMaxim Patlasov 		if (attr->ia_valid & ATTR_MTIME)
1563b0aa7606SMaxim Patlasov 			inode->i_mtime = attr->ia_mtime;
15643ad22c62SMaxim Patlasov 		if (attr->ia_valid & ATTR_CTIME)
15653ad22c62SMaxim Patlasov 			inode->i_ctime = attr->ia_ctime;
15661e18bda8SMiklos Szeredi 		/* FIXME: clear I_DIRTY_SYNC? */
1567b0aa7606SMaxim Patlasov 	}
1568b0aa7606SMaxim Patlasov 
15693be5a52bSMiklos Szeredi 	fuse_change_attributes_common(inode, &outarg.attr,
15703be5a52bSMiklos Szeredi 				      attr_timeout(&outarg));
15713be5a52bSMiklos Szeredi 	oldsize = inode->i_size;
15728373200bSPavel Emelyanov 	/* see the comment in fuse_change_attributes() */
15738373200bSPavel Emelyanov 	if (!is_wb || is_truncate || !S_ISREG(inode->i_mode))
15743be5a52bSMiklos Szeredi 		i_size_write(inode, outarg.attr.size);
15753be5a52bSMiklos Szeredi 
15763be5a52bSMiklos Szeredi 	if (is_truncate) {
1577f15ecfefSKirill Tkhai 		/* NOTE: this may release/reacquire fi->lock */
15783be5a52bSMiklos Szeredi 		__fuse_release_nowrite(inode);
15793be5a52bSMiklos Szeredi 	}
1580f15ecfefSKirill Tkhai 	spin_unlock(&fi->lock);
15813be5a52bSMiklos Szeredi 
15823be5a52bSMiklos Szeredi 	/*
15833be5a52bSMiklos Szeredi 	 * Only call invalidate_inode_pages2() after removing
15843be5a52bSMiklos Szeredi 	 * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock.
15853be5a52bSMiklos Szeredi 	 */
15868373200bSPavel Emelyanov 	if ((is_truncate || !is_wb) &&
15878373200bSPavel Emelyanov 	    S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
15887caef267SKirill A. Shutemov 		truncate_pagecache(inode, outarg.attr.size);
15893be5a52bSMiklos Szeredi 		invalidate_inode_pages2(inode->i_mapping);
15903be5a52bSMiklos Szeredi 	}
15913be5a52bSMiklos Szeredi 
159206a7c3c2SMaxim Patlasov 	clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
1593e00d2c2dSMiklos Szeredi 	return 0;
15943be5a52bSMiklos Szeredi 
15953be5a52bSMiklos Szeredi error:
15963be5a52bSMiklos Szeredi 	if (is_truncate)
15973be5a52bSMiklos Szeredi 		fuse_release_nowrite(inode);
15983be5a52bSMiklos Szeredi 
159906a7c3c2SMaxim Patlasov 	clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
16003be5a52bSMiklos Szeredi 	return err;
16019e6268dbSMiklos Szeredi }
16029e6268dbSMiklos Szeredi 
160349d4914fSMiklos Szeredi static int fuse_setattr(struct dentry *entry, struct iattr *attr)
160449d4914fSMiklos Szeredi {
16052b0143b5SDavid Howells 	struct inode *inode = d_inode(entry);
16065e940c1dSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1607a09f99edSMiklos Szeredi 	struct file *file = (attr->ia_valid & ATTR_FILE) ? attr->ia_file : NULL;
16085e2b8828SMiklos Szeredi 	int ret;
1609efb9fa9eSMaxim Patlasov 
1610efb9fa9eSMaxim Patlasov 	if (!fuse_allow_current_process(get_fuse_conn(inode)))
1611efb9fa9eSMaxim Patlasov 		return -EACCES;
1612efb9fa9eSMaxim Patlasov 
1613a09f99edSMiklos Szeredi 	if (attr->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) {
1614a09f99edSMiklos Szeredi 		attr->ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID |
1615a09f99edSMiklos Szeredi 				    ATTR_MODE);
16165e940c1dSMiklos Szeredi 
1617a09f99edSMiklos Szeredi 		/*
16185e940c1dSMiklos Szeredi 		 * The only sane way to reliably kill suid/sgid is to do it in
16195e940c1dSMiklos Szeredi 		 * the userspace filesystem
16205e940c1dSMiklos Szeredi 		 *
16215e940c1dSMiklos Szeredi 		 * This should be done on write(), truncate() and chown().
16225e940c1dSMiklos Szeredi 		 */
16235e940c1dSMiklos Szeredi 		if (!fc->handle_killpriv) {
16245e940c1dSMiklos Szeredi 			/*
16255e940c1dSMiklos Szeredi 			 * ia_mode calculation may have used stale i_mode.
16265e940c1dSMiklos Szeredi 			 * Refresh and recalculate.
1627a09f99edSMiklos Szeredi 			 */
1628a09f99edSMiklos Szeredi 			ret = fuse_do_getattr(inode, NULL, file);
1629a09f99edSMiklos Szeredi 			if (ret)
1630a09f99edSMiklos Szeredi 				return ret;
1631a09f99edSMiklos Szeredi 
1632a09f99edSMiklos Szeredi 			attr->ia_mode = inode->i_mode;
1633c01638f5SMiklos Szeredi 			if (inode->i_mode & S_ISUID) {
1634a09f99edSMiklos Szeredi 				attr->ia_valid |= ATTR_MODE;
1635a09f99edSMiklos Szeredi 				attr->ia_mode &= ~S_ISUID;
1636a09f99edSMiklos Szeredi 			}
1637c01638f5SMiklos Szeredi 			if ((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
1638a09f99edSMiklos Szeredi 				attr->ia_valid |= ATTR_MODE;
1639a09f99edSMiklos Szeredi 				attr->ia_mode &= ~S_ISGID;
1640a09f99edSMiklos Szeredi 			}
1641a09f99edSMiklos Szeredi 		}
16425e940c1dSMiklos Szeredi 	}
1643a09f99edSMiklos Szeredi 	if (!attr->ia_valid)
1644a09f99edSMiklos Szeredi 		return 0;
1645a09f99edSMiklos Szeredi 
1646abb5a14fSLinus Torvalds 	ret = fuse_do_setattr(entry, attr, file);
16475e2b8828SMiklos Szeredi 	if (!ret) {
164860bcc88aSSeth Forshee 		/*
164960bcc88aSSeth Forshee 		 * If filesystem supports acls it may have updated acl xattrs in
165060bcc88aSSeth Forshee 		 * the filesystem, so forget cached acls for the inode.
165160bcc88aSSeth Forshee 		 */
165260bcc88aSSeth Forshee 		if (fc->posix_acl)
165360bcc88aSSeth Forshee 			forget_all_cached_acls(inode);
165460bcc88aSSeth Forshee 
16555e2b8828SMiklos Szeredi 		/* Directory mode changed, may need to revalidate access */
16565e2b8828SMiklos Szeredi 		if (d_is_dir(entry) && (attr->ia_valid & ATTR_MODE))
16575e2b8828SMiklos Szeredi 			fuse_invalidate_entry_cache(entry);
16585e2b8828SMiklos Szeredi 	}
16595e2b8828SMiklos Szeredi 	return ret;
166049d4914fSMiklos Szeredi }
166149d4914fSMiklos Szeredi 
1662a528d35eSDavid Howells static int fuse_getattr(const struct path *path, struct kstat *stat,
1663a528d35eSDavid Howells 			u32 request_mask, unsigned int flags)
1664e5e5558eSMiklos Szeredi {
1665a528d35eSDavid Howells 	struct inode *inode = d_inode(path->dentry);
1666244f6385SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1667244f6385SMiklos Szeredi 
1668c2132c1bSAnatol Pomozov 	if (!fuse_allow_current_process(fc))
1669244f6385SMiklos Szeredi 		return -EACCES;
1670244f6385SMiklos Szeredi 
16712f1e8196SMiklos Szeredi 	return fuse_update_get_attr(inode, NULL, stat, request_mask, flags);
1672e5e5558eSMiklos Szeredi }
1673e5e5558eSMiklos Szeredi 
1674754661f1SArjan van de Ven static const struct inode_operations fuse_dir_inode_operations = {
1675e5e5558eSMiklos Szeredi 	.lookup		= fuse_lookup,
16769e6268dbSMiklos Szeredi 	.mkdir		= fuse_mkdir,
16779e6268dbSMiklos Szeredi 	.symlink	= fuse_symlink,
16789e6268dbSMiklos Szeredi 	.unlink		= fuse_unlink,
16799e6268dbSMiklos Szeredi 	.rmdir		= fuse_rmdir,
16802773bf00SMiklos Szeredi 	.rename		= fuse_rename2,
16819e6268dbSMiklos Szeredi 	.link		= fuse_link,
16829e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
16839e6268dbSMiklos Szeredi 	.create		= fuse_create,
1684c8ccbe03SMiklos Szeredi 	.atomic_open	= fuse_atomic_open,
16859e6268dbSMiklos Szeredi 	.mknod		= fuse_mknod,
1686e5e5558eSMiklos Szeredi 	.permission	= fuse_permission,
1687e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
168892a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
168960bcc88aSSeth Forshee 	.get_acl	= fuse_get_acl,
169060bcc88aSSeth Forshee 	.set_acl	= fuse_set_acl,
1691e5e5558eSMiklos Szeredi };
1692e5e5558eSMiklos Szeredi 
16934b6f5d20SArjan van de Ven static const struct file_operations fuse_dir_operations = {
1694b6aeadedSMiklos Szeredi 	.llseek		= generic_file_llseek,
1695e5e5558eSMiklos Szeredi 	.read		= generic_read_dir,
1696d9b3dbdcSAl Viro 	.iterate_shared	= fuse_readdir,
1697e5e5558eSMiklos Szeredi 	.open		= fuse_dir_open,
1698e5e5558eSMiklos Szeredi 	.release	= fuse_dir_release,
169982547981SMiklos Szeredi 	.fsync		= fuse_dir_fsync,
1700b18da0c5SMiklos Szeredi 	.unlocked_ioctl	= fuse_dir_ioctl,
1701b18da0c5SMiklos Szeredi 	.compat_ioctl	= fuse_dir_compat_ioctl,
1702e5e5558eSMiklos Szeredi };
1703e5e5558eSMiklos Szeredi 
1704754661f1SArjan van de Ven static const struct inode_operations fuse_common_inode_operations = {
17059e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
1706e5e5558eSMiklos Szeredi 	.permission	= fuse_permission,
1707e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
170892a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
170960bcc88aSSeth Forshee 	.get_acl	= fuse_get_acl,
171060bcc88aSSeth Forshee 	.set_acl	= fuse_set_acl,
1711e5e5558eSMiklos Szeredi };
1712e5e5558eSMiklos Szeredi 
1713754661f1SArjan van de Ven static const struct inode_operations fuse_symlink_inode_operations = {
17149e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
17156b255391SAl Viro 	.get_link	= fuse_get_link,
1716e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
171792a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
1718e5e5558eSMiklos Szeredi };
1719e5e5558eSMiklos Szeredi 
1720e5e5558eSMiklos Szeredi void fuse_init_common(struct inode *inode)
1721e5e5558eSMiklos Szeredi {
1722e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_common_inode_operations;
1723e5e5558eSMiklos Szeredi }
1724e5e5558eSMiklos Szeredi 
1725e5e5558eSMiklos Szeredi void fuse_init_dir(struct inode *inode)
1726e5e5558eSMiklos Szeredi {
1727ab2257e9SMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
1728ab2257e9SMiklos Szeredi 
1729e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_dir_inode_operations;
1730e5e5558eSMiklos Szeredi 	inode->i_fop = &fuse_dir_operations;
1731ab2257e9SMiklos Szeredi 
1732ab2257e9SMiklos Szeredi 	spin_lock_init(&fi->rdc.lock);
1733ab2257e9SMiklos Szeredi 	fi->rdc.cached = false;
1734ab2257e9SMiklos Szeredi 	fi->rdc.size = 0;
1735ab2257e9SMiklos Szeredi 	fi->rdc.pos = 0;
1736ab2257e9SMiklos Szeredi 	fi->rdc.version = 0;
1737e5e5558eSMiklos Szeredi }
1738e5e5558eSMiklos Szeredi 
17395571f1e6SDan Schatzberg static int fuse_symlink_readpage(struct file *null, struct page *page)
17405571f1e6SDan Schatzberg {
17415571f1e6SDan Schatzberg 	int err = fuse_readlink_page(page->mapping->host, page);
17425571f1e6SDan Schatzberg 
17435571f1e6SDan Schatzberg 	if (!err)
17445571f1e6SDan Schatzberg 		SetPageUptodate(page);
17455571f1e6SDan Schatzberg 
17465571f1e6SDan Schatzberg 	unlock_page(page);
17475571f1e6SDan Schatzberg 
17485571f1e6SDan Schatzberg 	return err;
17495571f1e6SDan Schatzberg }
17505571f1e6SDan Schatzberg 
17515571f1e6SDan Schatzberg static const struct address_space_operations fuse_symlink_aops = {
17525571f1e6SDan Schatzberg 	.readpage	= fuse_symlink_readpage,
17535571f1e6SDan Schatzberg };
17545571f1e6SDan Schatzberg 
1755e5e5558eSMiklos Szeredi void fuse_init_symlink(struct inode *inode)
1756e5e5558eSMiklos Szeredi {
1757e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_symlink_inode_operations;
17585571f1e6SDan Schatzberg 	inode->i_data.a_ops = &fuse_symlink_aops;
17595571f1e6SDan Schatzberg 	inode_nohighmem(inode);
1760e5e5558eSMiklos Szeredi }
1761