xref: /openbmc/linux/fs/fuse/dir.c (revision 5e940c1dd3c1f7561924954eecee956ec277a79b)
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>
16*703c7362SSeth Forshee #include <linux/xattr.h>
17e5e5558eSMiklos Szeredi 
188d3af7f3SAl Viro static bool fuse_use_readdirplus(struct inode *dir, struct dir_context *ctx)
194582a4abSFeng Shuo {
204582a4abSFeng Shuo 	struct fuse_conn *fc = get_fuse_conn(dir);
214582a4abSFeng Shuo 	struct fuse_inode *fi = get_fuse_inode(dir);
224582a4abSFeng Shuo 
234582a4abSFeng Shuo 	if (!fc->do_readdirplus)
244582a4abSFeng Shuo 		return false;
25634734b6SEric Wong 	if (!fc->readdirplus_auto)
26634734b6SEric Wong 		return true;
274582a4abSFeng Shuo 	if (test_and_clear_bit(FUSE_I_ADVISE_RDPLUS, &fi->state))
284582a4abSFeng Shuo 		return true;
298d3af7f3SAl Viro 	if (ctx->pos == 0)
304582a4abSFeng Shuo 		return true;
314582a4abSFeng Shuo 	return false;
324582a4abSFeng Shuo }
334582a4abSFeng Shuo 
344582a4abSFeng Shuo static void fuse_advise_use_readdirplus(struct inode *dir)
354582a4abSFeng Shuo {
364582a4abSFeng Shuo 	struct fuse_inode *fi = get_fuse_inode(dir);
374582a4abSFeng Shuo 
384582a4abSFeng Shuo 	set_bit(FUSE_I_ADVISE_RDPLUS, &fi->state);
394582a4abSFeng Shuo }
404582a4abSFeng Shuo 
410a0898cfSMiklos Szeredi #if BITS_PER_LONG >= 64
420a0898cfSMiklos Szeredi static inline void fuse_dentry_settime(struct dentry *entry, u64 time)
430a0898cfSMiklos Szeredi {
440a0898cfSMiklos Szeredi 	entry->d_time = time;
450a0898cfSMiklos Szeredi }
460a0898cfSMiklos Szeredi 
470a0898cfSMiklos Szeredi static inline u64 fuse_dentry_time(struct dentry *entry)
480a0898cfSMiklos Szeredi {
490a0898cfSMiklos Szeredi 	return entry->d_time;
500a0898cfSMiklos Szeredi }
510a0898cfSMiklos Szeredi #else
520a0898cfSMiklos Szeredi /*
530a0898cfSMiklos Szeredi  * On 32 bit archs store the high 32 bits of time in d_fsdata
540a0898cfSMiklos Szeredi  */
550a0898cfSMiklos Szeredi static void fuse_dentry_settime(struct dentry *entry, u64 time)
560a0898cfSMiklos Szeredi {
570a0898cfSMiklos Szeredi 	entry->d_time = time;
580a0898cfSMiklos Szeredi 	entry->d_fsdata = (void *) (unsigned long) (time >> 32);
590a0898cfSMiklos Szeredi }
600a0898cfSMiklos Szeredi 
610a0898cfSMiklos Szeredi static u64 fuse_dentry_time(struct dentry *entry)
620a0898cfSMiklos Szeredi {
630a0898cfSMiklos Szeredi 	return (u64) entry->d_time +
640a0898cfSMiklos Szeredi 		((u64) (unsigned long) entry->d_fsdata << 32);
650a0898cfSMiklos Szeredi }
660a0898cfSMiklos Szeredi #endif
670a0898cfSMiklos Szeredi 
686f9f1180SMiklos Szeredi /*
696f9f1180SMiklos Szeredi  * FUSE caches dentries and attributes with separate timeout.  The
706f9f1180SMiklos Szeredi  * time in jiffies until the dentry/attributes are valid is stored in
716f9f1180SMiklos Szeredi  * dentry->d_time and fuse_inode->i_time respectively.
726f9f1180SMiklos Szeredi  */
736f9f1180SMiklos Szeredi 
746f9f1180SMiklos Szeredi /*
756f9f1180SMiklos Szeredi  * Calculate the time in jiffies until a dentry/attributes are valid
766f9f1180SMiklos Szeredi  */
770a0898cfSMiklos Szeredi static u64 time_to_jiffies(unsigned long sec, unsigned long nsec)
78e5e5558eSMiklos Szeredi {
79685d16ddSMiklos Szeredi 	if (sec || nsec) {
80e5e5558eSMiklos Szeredi 		struct timespec ts = {sec, nsec};
810a0898cfSMiklos Szeredi 		return get_jiffies_64() + timespec_to_jiffies(&ts);
82685d16ddSMiklos Szeredi 	} else
830a0898cfSMiklos Szeredi 		return 0;
84e5e5558eSMiklos Szeredi }
85e5e5558eSMiklos Szeredi 
866f9f1180SMiklos Szeredi /*
876f9f1180SMiklos Szeredi  * Set dentry and possibly attribute timeouts from the lookup/mk*
886f9f1180SMiklos Szeredi  * replies
896f9f1180SMiklos Szeredi  */
901fb69e78SMiklos Szeredi static void fuse_change_entry_timeout(struct dentry *entry,
911fb69e78SMiklos Szeredi 				      struct fuse_entry_out *o)
920aa7c699SMiklos Szeredi {
930a0898cfSMiklos Szeredi 	fuse_dentry_settime(entry,
940a0898cfSMiklos Szeredi 		time_to_jiffies(o->entry_valid, o->entry_valid_nsec));
951fb69e78SMiklos Szeredi }
961fb69e78SMiklos Szeredi 
971fb69e78SMiklos Szeredi static u64 attr_timeout(struct fuse_attr_out *o)
981fb69e78SMiklos Szeredi {
991fb69e78SMiklos Szeredi 	return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
1001fb69e78SMiklos Szeredi }
1011fb69e78SMiklos Szeredi 
1021fb69e78SMiklos Szeredi static u64 entry_attr_timeout(struct fuse_entry_out *o)
1031fb69e78SMiklos Szeredi {
1041fb69e78SMiklos Szeredi 	return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
1058cbdf1e6SMiklos Szeredi }
1068cbdf1e6SMiklos Szeredi 
1076f9f1180SMiklos Szeredi /*
1086f9f1180SMiklos Szeredi  * Mark the attributes as stale, so that at the next call to
1096f9f1180SMiklos Szeredi  * ->getattr() they will be fetched from userspace
1106f9f1180SMiklos Szeredi  */
1118cbdf1e6SMiklos Szeredi void fuse_invalidate_attr(struct inode *inode)
1128cbdf1e6SMiklos Szeredi {
1130a0898cfSMiklos Szeredi 	get_fuse_inode(inode)->i_time = 0;
1148cbdf1e6SMiklos Szeredi }
1158cbdf1e6SMiklos Szeredi 
116451418fcSAndrew Gallagher /**
117451418fcSAndrew Gallagher  * Mark the attributes as stale due to an atime change.  Avoid the invalidate if
118451418fcSAndrew Gallagher  * atime is not used.
119451418fcSAndrew Gallagher  */
120451418fcSAndrew Gallagher void fuse_invalidate_atime(struct inode *inode)
121451418fcSAndrew Gallagher {
122451418fcSAndrew Gallagher 	if (!IS_RDONLY(inode))
123451418fcSAndrew Gallagher 		fuse_invalidate_attr(inode);
124451418fcSAndrew Gallagher }
125451418fcSAndrew Gallagher 
1266f9f1180SMiklos Szeredi /*
1276f9f1180SMiklos Szeredi  * Just mark the entry as stale, so that a next attempt to look it up
1286f9f1180SMiklos Szeredi  * will result in a new lookup call to userspace
1296f9f1180SMiklos Szeredi  *
1306f9f1180SMiklos Szeredi  * This is called when a dentry is about to become negative and the
1316f9f1180SMiklos Szeredi  * timeout is unknown (unlink, rmdir, rename and in some cases
1326f9f1180SMiklos Szeredi  * lookup)
1336f9f1180SMiklos Szeredi  */
134dbd561d2SMiklos Szeredi void fuse_invalidate_entry_cache(struct dentry *entry)
1358cbdf1e6SMiklos Szeredi {
1360a0898cfSMiklos Szeredi 	fuse_dentry_settime(entry, 0);
1378cbdf1e6SMiklos Szeredi }
1388cbdf1e6SMiklos Szeredi 
1396f9f1180SMiklos Szeredi /*
1406f9f1180SMiklos Szeredi  * Same as fuse_invalidate_entry_cache(), but also try to remove the
1416f9f1180SMiklos Szeredi  * dentry from the hash
1426f9f1180SMiklos Szeredi  */
1438cbdf1e6SMiklos Szeredi static void fuse_invalidate_entry(struct dentry *entry)
1448cbdf1e6SMiklos Szeredi {
1458cbdf1e6SMiklos Szeredi 	d_invalidate(entry);
1468cbdf1e6SMiklos Szeredi 	fuse_invalidate_entry_cache(entry);
1470aa7c699SMiklos Szeredi }
1480aa7c699SMiklos Szeredi 
1497078187aSMiklos Szeredi static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_args *args,
15013983d06SAl Viro 			     u64 nodeid, const struct qstr *name,
151e5e5558eSMiklos Szeredi 			     struct fuse_entry_out *outarg)
152e5e5558eSMiklos Szeredi {
1530e9663eeSMiklos Szeredi 	memset(outarg, 0, sizeof(struct fuse_entry_out));
1547078187aSMiklos Szeredi 	args->in.h.opcode = FUSE_LOOKUP;
1557078187aSMiklos Szeredi 	args->in.h.nodeid = nodeid;
1567078187aSMiklos Szeredi 	args->in.numargs = 1;
1577078187aSMiklos Szeredi 	args->in.args[0].size = name->len + 1;
1587078187aSMiklos Szeredi 	args->in.args[0].value = name->name;
1597078187aSMiklos Szeredi 	args->out.numargs = 1;
1607078187aSMiklos Szeredi 	args->out.args[0].size = sizeof(struct fuse_entry_out);
1617078187aSMiklos Szeredi 	args->out.args[0].value = outarg;
162e5e5558eSMiklos Szeredi }
163e5e5558eSMiklos Szeredi 
1645c5c5e51SMiklos Szeredi u64 fuse_get_attr_version(struct fuse_conn *fc)
1657dca9fd3SMiklos Szeredi {
1667dca9fd3SMiklos Szeredi 	u64 curr_version;
1677dca9fd3SMiklos Szeredi 
1687dca9fd3SMiklos Szeredi 	/*
1697dca9fd3SMiklos Szeredi 	 * The spin lock isn't actually needed on 64bit archs, but we
1707dca9fd3SMiklos Szeredi 	 * don't yet care too much about such optimizations.
1717dca9fd3SMiklos Szeredi 	 */
1727dca9fd3SMiklos Szeredi 	spin_lock(&fc->lock);
1737dca9fd3SMiklos Szeredi 	curr_version = fc->attr_version;
1747dca9fd3SMiklos Szeredi 	spin_unlock(&fc->lock);
1757dca9fd3SMiklos Szeredi 
1767dca9fd3SMiklos Szeredi 	return curr_version;
1777dca9fd3SMiklos Szeredi }
1787dca9fd3SMiklos Szeredi 
1796f9f1180SMiklos Szeredi /*
1806f9f1180SMiklos Szeredi  * Check whether the dentry is still valid
1816f9f1180SMiklos Szeredi  *
1826f9f1180SMiklos Szeredi  * If the entry validity timeout has expired and the dentry is
1836f9f1180SMiklos Szeredi  * positive, try to redo the lookup.  If the lookup results in a
1846f9f1180SMiklos Szeredi  * different inode, then let the VFS invalidate the dentry and redo
1856f9f1180SMiklos Szeredi  * the lookup once more.  If the lookup results in the same inode,
1866f9f1180SMiklos Szeredi  * then refresh the attributes, timeouts and mark the dentry valid.
1876f9f1180SMiklos Szeredi  */
1880b728e19SAl Viro static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
189e5e5558eSMiklos Szeredi {
19034286d66SNick Piggin 	struct inode *inode;
19128420dadSMiklos Szeredi 	struct dentry *parent;
19228420dadSMiklos Szeredi 	struct fuse_conn *fc;
1936314efeeSMiklos Szeredi 	struct fuse_inode *fi;
194e2a6b952SMiklos Szeredi 	int ret;
1958cbdf1e6SMiklos Szeredi 
1962b0143b5SDavid Howells 	inode = d_inode_rcu(entry);
1978cbdf1e6SMiklos Szeredi 	if (inode && is_bad_inode(inode))
198e2a6b952SMiklos Szeredi 		goto invalid;
199154210ccSAnand Avati 	else if (time_before64(fuse_dentry_time(entry), get_jiffies_64()) ||
200154210ccSAnand Avati 		 (flags & LOOKUP_REVAL)) {
201e5e5558eSMiklos Szeredi 		struct fuse_entry_out outarg;
2027078187aSMiklos Szeredi 		FUSE_ARGS(args);
20307e77dcaSMiklos Szeredi 		struct fuse_forget_link *forget;
2041fb69e78SMiklos Szeredi 		u64 attr_version;
2058cbdf1e6SMiklos Szeredi 
20650322fe7SMiklos Szeredi 		/* For negative dentries, always do a fresh lookup */
2078cbdf1e6SMiklos Szeredi 		if (!inode)
208e2a6b952SMiklos Szeredi 			goto invalid;
2098cbdf1e6SMiklos Szeredi 
210e2a6b952SMiklos Szeredi 		ret = -ECHILD;
2110b728e19SAl Viro 		if (flags & LOOKUP_RCU)
212e2a6b952SMiklos Szeredi 			goto out;
213e7c0a167SMiklos Szeredi 
2148cbdf1e6SMiklos Szeredi 		fc = get_fuse_conn(inode);
215e5e5558eSMiklos Szeredi 
21607e77dcaSMiklos Szeredi 		forget = fuse_alloc_forget();
217e2a6b952SMiklos Szeredi 		ret = -ENOMEM;
2187078187aSMiklos Szeredi 		if (!forget)
219e2a6b952SMiklos Szeredi 			goto out;
2202d51013eSMiklos Szeredi 
2217dca9fd3SMiklos Szeredi 		attr_version = fuse_get_attr_version(fc);
2221fb69e78SMiklos Szeredi 
223e956edd0SMiklos Szeredi 		parent = dget_parent(entry);
2242b0143b5SDavid Howells 		fuse_lookup_init(fc, &args, get_node_id(d_inode(parent)),
225c180eebeSMiklos Szeredi 				 &entry->d_name, &outarg);
2267078187aSMiklos Szeredi 		ret = fuse_simple_request(fc, &args);
227e956edd0SMiklos Szeredi 		dput(parent);
22850322fe7SMiklos Szeredi 		/* Zero nodeid is same as -ENOENT */
2297078187aSMiklos Szeredi 		if (!ret && !outarg.nodeid)
2307078187aSMiklos Szeredi 			ret = -ENOENT;
2317078187aSMiklos Szeredi 		if (!ret) {
2326314efeeSMiklos Szeredi 			fi = get_fuse_inode(inode);
2339e6268dbSMiklos Szeredi 			if (outarg.nodeid != get_node_id(inode)) {
23407e77dcaSMiklos Szeredi 				fuse_queue_forget(fc, forget, outarg.nodeid, 1);
235e2a6b952SMiklos Szeredi 				goto invalid;
2369e6268dbSMiklos Szeredi 			}
2378da5ff23SMiklos Szeredi 			spin_lock(&fc->lock);
2389e6268dbSMiklos Szeredi 			fi->nlookup++;
2398da5ff23SMiklos Szeredi 			spin_unlock(&fc->lock);
2409e6268dbSMiklos Szeredi 		}
24107e77dcaSMiklos Szeredi 		kfree(forget);
2427078187aSMiklos Szeredi 		if (ret == -ENOMEM)
2437078187aSMiklos Szeredi 			goto out;
2447078187aSMiklos Szeredi 		if (ret || (outarg.attr.mode ^ inode->i_mode) & S_IFMT)
245e2a6b952SMiklos Szeredi 			goto invalid;
246e5e5558eSMiklos Szeredi 
2471fb69e78SMiklos Szeredi 		fuse_change_attributes(inode, &outarg.attr,
2481fb69e78SMiklos Szeredi 				       entry_attr_timeout(&outarg),
2491fb69e78SMiklos Szeredi 				       attr_version);
2501fb69e78SMiklos Szeredi 		fuse_change_entry_timeout(entry, &outarg);
25128420dadSMiklos Szeredi 	} else if (inode) {
2526314efeeSMiklos Szeredi 		fi = get_fuse_inode(inode);
2536314efeeSMiklos Szeredi 		if (flags & LOOKUP_RCU) {
2546314efeeSMiklos Szeredi 			if (test_bit(FUSE_I_INIT_RDPLUS, &fi->state))
2556314efeeSMiklos Szeredi 				return -ECHILD;
2566314efeeSMiklos Szeredi 		} else if (test_and_clear_bit(FUSE_I_INIT_RDPLUS, &fi->state)) {
25728420dadSMiklos Szeredi 			parent = dget_parent(entry);
2582b0143b5SDavid Howells 			fuse_advise_use_readdirplus(d_inode(parent));
25928420dadSMiklos Szeredi 			dput(parent);
260e5e5558eSMiklos Szeredi 		}
26128420dadSMiklos Szeredi 	}
262e2a6b952SMiklos Szeredi 	ret = 1;
263e2a6b952SMiklos Szeredi out:
264e2a6b952SMiklos Szeredi 	return ret;
265e2a6b952SMiklos Szeredi 
266e2a6b952SMiklos Szeredi invalid:
267e2a6b952SMiklos Szeredi 	ret = 0;
268e2a6b952SMiklos Szeredi 	goto out;
269e5e5558eSMiklos Szeredi }
270e5e5558eSMiklos Szeredi 
2718bfc016dSMiklos Szeredi static int invalid_nodeid(u64 nodeid)
2722827d0b2SMiklos Szeredi {
2732827d0b2SMiklos Szeredi 	return !nodeid || nodeid == FUSE_ROOT_ID;
2742827d0b2SMiklos Szeredi }
2752827d0b2SMiklos Szeredi 
2764269590aSAl Viro const struct dentry_operations fuse_dentry_operations = {
277e5e5558eSMiklos Szeredi 	.d_revalidate	= fuse_dentry_revalidate,
278e5e5558eSMiklos Szeredi };
279e5e5558eSMiklos Szeredi 
280a5bfffacSTimo Savola int fuse_valid_type(int m)
28139ee059aSMiklos Szeredi {
28239ee059aSMiklos Szeredi 	return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) ||
28339ee059aSMiklos Szeredi 		S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m);
28439ee059aSMiklos Szeredi }
28539ee059aSMiklos Szeredi 
28613983d06SAl Viro int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name,
287c180eebeSMiklos Szeredi 		     struct fuse_entry_out *outarg, struct inode **inode)
288c180eebeSMiklos Szeredi {
289c180eebeSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn_super(sb);
2907078187aSMiklos Szeredi 	FUSE_ARGS(args);
29107e77dcaSMiklos Szeredi 	struct fuse_forget_link *forget;
292c180eebeSMiklos Szeredi 	u64 attr_version;
293c180eebeSMiklos Szeredi 	int err;
294c180eebeSMiklos Szeredi 
295c180eebeSMiklos Szeredi 	*inode = NULL;
296c180eebeSMiklos Szeredi 	err = -ENAMETOOLONG;
297c180eebeSMiklos Szeredi 	if (name->len > FUSE_NAME_MAX)
298c180eebeSMiklos Szeredi 		goto out;
299c180eebeSMiklos Szeredi 
300c180eebeSMiklos Szeredi 
30107e77dcaSMiklos Szeredi 	forget = fuse_alloc_forget();
30207e77dcaSMiklos Szeredi 	err = -ENOMEM;
3037078187aSMiklos Szeredi 	if (!forget)
304c180eebeSMiklos Szeredi 		goto out;
305c180eebeSMiklos Szeredi 
306c180eebeSMiklos Szeredi 	attr_version = fuse_get_attr_version(fc);
307c180eebeSMiklos Szeredi 
3087078187aSMiklos Szeredi 	fuse_lookup_init(fc, &args, nodeid, name, outarg);
3097078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
310c180eebeSMiklos Szeredi 	/* Zero nodeid is same as -ENOENT, but with valid timeout */
311c180eebeSMiklos Szeredi 	if (err || !outarg->nodeid)
312c180eebeSMiklos Szeredi 		goto out_put_forget;
313c180eebeSMiklos Szeredi 
314c180eebeSMiklos Szeredi 	err = -EIO;
315c180eebeSMiklos Szeredi 	if (!outarg->nodeid)
316c180eebeSMiklos Szeredi 		goto out_put_forget;
317c180eebeSMiklos Szeredi 	if (!fuse_valid_type(outarg->attr.mode))
318c180eebeSMiklos Szeredi 		goto out_put_forget;
319c180eebeSMiklos Szeredi 
320c180eebeSMiklos Szeredi 	*inode = fuse_iget(sb, outarg->nodeid, outarg->generation,
321c180eebeSMiklos Szeredi 			   &outarg->attr, entry_attr_timeout(outarg),
322c180eebeSMiklos Szeredi 			   attr_version);
323c180eebeSMiklos Szeredi 	err = -ENOMEM;
324c180eebeSMiklos Szeredi 	if (!*inode) {
32507e77dcaSMiklos Szeredi 		fuse_queue_forget(fc, forget, outarg->nodeid, 1);
326c180eebeSMiklos Szeredi 		goto out;
327c180eebeSMiklos Szeredi 	}
328c180eebeSMiklos Szeredi 	err = 0;
329c180eebeSMiklos Szeredi 
330c180eebeSMiklos Szeredi  out_put_forget:
33107e77dcaSMiklos Szeredi 	kfree(forget);
332c180eebeSMiklos Szeredi  out:
333c180eebeSMiklos Szeredi 	return err;
334c180eebeSMiklos Szeredi }
335c180eebeSMiklos Szeredi 
3360aa7c699SMiklos Szeredi static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
33700cd8dd3SAl Viro 				  unsigned int flags)
338e5e5558eSMiklos Szeredi {
339e5e5558eSMiklos Szeredi 	int err;
340e5e5558eSMiklos Szeredi 	struct fuse_entry_out outarg;
341c180eebeSMiklos Szeredi 	struct inode *inode;
3420de6256dSMiklos Szeredi 	struct dentry *newent;
343c180eebeSMiklos Szeredi 	bool outarg_valid = true;
344e5e5558eSMiklos Szeredi 
3455c672ab3SMiklos Szeredi 	fuse_lock_inode(dir);
346c180eebeSMiklos Szeredi 	err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name,
347c180eebeSMiklos Szeredi 			       &outarg, &inode);
3485c672ab3SMiklos Szeredi 	fuse_unlock_inode(dir);
349c180eebeSMiklos Szeredi 	if (err == -ENOENT) {
350c180eebeSMiklos Szeredi 		outarg_valid = false;
351c180eebeSMiklos Szeredi 		err = 0;
3522d51013eSMiklos Szeredi 	}
353c180eebeSMiklos Szeredi 	if (err)
354c180eebeSMiklos Szeredi 		goto out_err;
3552d51013eSMiklos Szeredi 
356ee4e5271SMiklos Szeredi 	err = -EIO;
357c180eebeSMiklos Szeredi 	if (inode && get_node_id(inode) == FUSE_ROOT_ID)
358c180eebeSMiklos Szeredi 		goto out_iput;
359e5e5558eSMiklos Szeredi 
36041d28bcaSAl Viro 	newent = d_splice_alias(inode, entry);
361c180eebeSMiklos Szeredi 	err = PTR_ERR(newent);
362c180eebeSMiklos Szeredi 	if (IS_ERR(newent))
3635835f339SMiklos Szeredi 		goto out_err;
364d2a85164SMiklos Szeredi 
3650de6256dSMiklos Szeredi 	entry = newent ? newent : entry;
366c180eebeSMiklos Szeredi 	if (outarg_valid)
3671fb69e78SMiklos Szeredi 		fuse_change_entry_timeout(entry, &outarg);
3688cbdf1e6SMiklos Szeredi 	else
3698cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
370c180eebeSMiklos Szeredi 
3714582a4abSFeng Shuo 	fuse_advise_use_readdirplus(dir);
3720de6256dSMiklos Szeredi 	return newent;
373c180eebeSMiklos Szeredi 
374c180eebeSMiklos Szeredi  out_iput:
375c180eebeSMiklos Szeredi 	iput(inode);
376c180eebeSMiklos Szeredi  out_err:
377c180eebeSMiklos Szeredi 	return ERR_PTR(err);
378e5e5558eSMiklos Szeredi }
379e5e5558eSMiklos Szeredi 
3806f9f1180SMiklos Szeredi /*
3816f9f1180SMiklos Szeredi  * Atomic create+open operation
3826f9f1180SMiklos Szeredi  *
3836f9f1180SMiklos Szeredi  * If the filesystem doesn't support this, then fall back to separate
3846f9f1180SMiklos Szeredi  * 'mknod' + 'open' requests.
3856f9f1180SMiklos Szeredi  */
386d9585277SAl Viro static int fuse_create_open(struct inode *dir, struct dentry *entry,
38730d90494SAl Viro 			    struct file *file, unsigned flags,
38847237687SAl Viro 			    umode_t mode, int *opened)
389fd72faacSMiklos Szeredi {
390fd72faacSMiklos Szeredi 	int err;
391fd72faacSMiklos Szeredi 	struct inode *inode;
392fd72faacSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
3937078187aSMiklos Szeredi 	FUSE_ARGS(args);
39407e77dcaSMiklos Szeredi 	struct fuse_forget_link *forget;
395e0a43ddcSMiklos Szeredi 	struct fuse_create_in inarg;
396fd72faacSMiklos Szeredi 	struct fuse_open_out outopen;
397fd72faacSMiklos Szeredi 	struct fuse_entry_out outentry;
398fd72faacSMiklos Szeredi 	struct fuse_file *ff;
399fd72faacSMiklos Szeredi 
400af109bcaSMiklos Szeredi 	/* Userspace expects S_IFREG in create mode */
401af109bcaSMiklos Szeredi 	BUG_ON((mode & S_IFMT) != S_IFREG);
402af109bcaSMiklos Szeredi 
40307e77dcaSMiklos Szeredi 	forget = fuse_alloc_forget();
404c8ccbe03SMiklos Szeredi 	err = -ENOMEM;
40507e77dcaSMiklos Szeredi 	if (!forget)
406c8ccbe03SMiklos Szeredi 		goto out_err;
40751eb01e7SMiklos Szeredi 
408ce1d5a49SMiklos Szeredi 	err = -ENOMEM;
409acf99433STejun Heo 	ff = fuse_file_alloc(fc);
410fd72faacSMiklos Szeredi 	if (!ff)
4117078187aSMiklos Szeredi 		goto out_put_forget_req;
412fd72faacSMiklos Szeredi 
413e0a43ddcSMiklos Szeredi 	if (!fc->dont_mask)
414e0a43ddcSMiklos Szeredi 		mode &= ~current_umask();
415e0a43ddcSMiklos Szeredi 
416fd72faacSMiklos Szeredi 	flags &= ~O_NOCTTY;
417fd72faacSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
4180e9663eeSMiklos Szeredi 	memset(&outentry, 0, sizeof(outentry));
419fd72faacSMiklos Szeredi 	inarg.flags = flags;
420fd72faacSMiklos Szeredi 	inarg.mode = mode;
421e0a43ddcSMiklos Szeredi 	inarg.umask = current_umask();
4227078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_CREATE;
4237078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(dir);
4247078187aSMiklos Szeredi 	args.in.numargs = 2;
42521f62174SMiklos Szeredi 	args.in.args[0].size = sizeof(inarg);
4267078187aSMiklos Szeredi 	args.in.args[0].value = &inarg;
4277078187aSMiklos Szeredi 	args.in.args[1].size = entry->d_name.len + 1;
4287078187aSMiklos Szeredi 	args.in.args[1].value = entry->d_name.name;
4297078187aSMiklos Szeredi 	args.out.numargs = 2;
4307078187aSMiklos Szeredi 	args.out.args[0].size = sizeof(outentry);
4317078187aSMiklos Szeredi 	args.out.args[0].value = &outentry;
4327078187aSMiklos Szeredi 	args.out.args[1].size = sizeof(outopen);
4337078187aSMiklos Szeredi 	args.out.args[1].value = &outopen;
4347078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
435c8ccbe03SMiklos Szeredi 	if (err)
436fd72faacSMiklos Szeredi 		goto out_free_ff;
437fd72faacSMiklos Szeredi 
438fd72faacSMiklos Szeredi 	err = -EIO;
4392827d0b2SMiklos Szeredi 	if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid))
440fd72faacSMiklos Szeredi 		goto out_free_ff;
441fd72faacSMiklos Szeredi 
442c7b7143cSMiklos Szeredi 	ff->fh = outopen.fh;
443c7b7143cSMiklos Szeredi 	ff->nodeid = outentry.nodeid;
444c7b7143cSMiklos Szeredi 	ff->open_flags = outopen.open_flags;
445fd72faacSMiklos Szeredi 	inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
4461fb69e78SMiklos Szeredi 			  &outentry.attr, entry_attr_timeout(&outentry), 0);
447fd72faacSMiklos Szeredi 	if (!inode) {
448fd72faacSMiklos Szeredi 		flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
4498b0797a4SMiklos Szeredi 		fuse_sync_release(ff, flags);
45007e77dcaSMiklos Szeredi 		fuse_queue_forget(fc, forget, outentry.nodeid, 1);
451c8ccbe03SMiklos Szeredi 		err = -ENOMEM;
452c8ccbe03SMiklos Szeredi 		goto out_err;
453fd72faacSMiklos Szeredi 	}
45407e77dcaSMiklos Szeredi 	kfree(forget);
455fd72faacSMiklos Szeredi 	d_instantiate(entry, inode);
4561fb69e78SMiklos Szeredi 	fuse_change_entry_timeout(entry, &outentry);
4570952b2a4SMiklos Szeredi 	fuse_invalidate_attr(dir);
45830d90494SAl Viro 	err = finish_open(file, entry, generic_file_open, opened);
45930d90494SAl Viro 	if (err) {
4608b0797a4SMiklos Szeredi 		fuse_sync_release(ff, flags);
461c8ccbe03SMiklos Szeredi 	} else {
462c7b7143cSMiklos Szeredi 		file->private_data = fuse_file_get(ff);
463c7b7143cSMiklos Szeredi 		fuse_finish_open(inode, file);
464c8ccbe03SMiklos Szeredi 	}
465d9585277SAl Viro 	return err;
466fd72faacSMiklos Szeredi 
467fd72faacSMiklos Szeredi out_free_ff:
468fd72faacSMiklos Szeredi 	fuse_file_free(ff);
46951eb01e7SMiklos Szeredi out_put_forget_req:
47007e77dcaSMiklos Szeredi 	kfree(forget);
471c8ccbe03SMiklos Szeredi out_err:
472d9585277SAl Viro 	return err;
473c8ccbe03SMiklos Szeredi }
474c8ccbe03SMiklos Szeredi 
475c8ccbe03SMiklos Szeredi static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t);
476d9585277SAl Viro static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
47730d90494SAl Viro 			    struct file *file, unsigned flags,
47847237687SAl Viro 			    umode_t mode, int *opened)
479c8ccbe03SMiklos Szeredi {
480c8ccbe03SMiklos Szeredi 	int err;
481c8ccbe03SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
482c8ccbe03SMiklos Szeredi 	struct dentry *res = NULL;
483c8ccbe03SMiklos Szeredi 
48400699ad8SAl Viro 	if (d_in_lookup(entry)) {
48500cd8dd3SAl Viro 		res = fuse_lookup(dir, entry, 0);
486c8ccbe03SMiklos Szeredi 		if (IS_ERR(res))
487d9585277SAl Viro 			return PTR_ERR(res);
488c8ccbe03SMiklos Szeredi 
489c8ccbe03SMiklos Szeredi 		if (res)
490c8ccbe03SMiklos Szeredi 			entry = res;
491c8ccbe03SMiklos Szeredi 	}
492c8ccbe03SMiklos Szeredi 
4932b0143b5SDavid Howells 	if (!(flags & O_CREAT) || d_really_is_positive(entry))
494c8ccbe03SMiklos Szeredi 		goto no_open;
495c8ccbe03SMiklos Szeredi 
496c8ccbe03SMiklos Szeredi 	/* Only creates */
49747237687SAl Viro 	*opened |= FILE_CREATED;
498c8ccbe03SMiklos Szeredi 
499c8ccbe03SMiklos Szeredi 	if (fc->no_create)
500c8ccbe03SMiklos Szeredi 		goto mknod;
501c8ccbe03SMiklos Szeredi 
50230d90494SAl Viro 	err = fuse_create_open(dir, entry, file, flags, mode, opened);
503d9585277SAl Viro 	if (err == -ENOSYS) {
504c8ccbe03SMiklos Szeredi 		fc->no_create = 1;
505c8ccbe03SMiklos Szeredi 		goto mknod;
506c8ccbe03SMiklos Szeredi 	}
507c8ccbe03SMiklos Szeredi out_dput:
508c8ccbe03SMiklos Szeredi 	dput(res);
509d9585277SAl Viro 	return err;
510c8ccbe03SMiklos Szeredi 
511c8ccbe03SMiklos Szeredi mknod:
512c8ccbe03SMiklos Szeredi 	err = fuse_mknod(dir, entry, mode, 0);
513d9585277SAl Viro 	if (err)
514c8ccbe03SMiklos Szeredi 		goto out_dput;
515c8ccbe03SMiklos Szeredi no_open:
516e45198a6SAl Viro 	return finish_no_open(file, res);
517fd72faacSMiklos Szeredi }
518fd72faacSMiklos Szeredi 
5196f9f1180SMiklos Szeredi /*
5206f9f1180SMiklos Szeredi  * Code shared between mknod, mkdir, symlink and link
5216f9f1180SMiklos Szeredi  */
5227078187aSMiklos Szeredi static int create_new_entry(struct fuse_conn *fc, struct fuse_args *args,
5239e6268dbSMiklos Szeredi 			    struct inode *dir, struct dentry *entry,
524541af6a0SAl Viro 			    umode_t mode)
5259e6268dbSMiklos Szeredi {
5269e6268dbSMiklos Szeredi 	struct fuse_entry_out outarg;
5279e6268dbSMiklos Szeredi 	struct inode *inode;
5289e6268dbSMiklos Szeredi 	int err;
52907e77dcaSMiklos Szeredi 	struct fuse_forget_link *forget;
5302d51013eSMiklos Szeredi 
53107e77dcaSMiklos Szeredi 	forget = fuse_alloc_forget();
5327078187aSMiklos Szeredi 	if (!forget)
53307e77dcaSMiklos Szeredi 		return -ENOMEM;
5349e6268dbSMiklos Szeredi 
5350e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
5367078187aSMiklos Szeredi 	args->in.h.nodeid = get_node_id(dir);
5377078187aSMiklos Szeredi 	args->out.numargs = 1;
5387078187aSMiklos Szeredi 	args->out.args[0].size = sizeof(outarg);
5397078187aSMiklos Szeredi 	args->out.args[0].value = &outarg;
5407078187aSMiklos Szeredi 	err = fuse_simple_request(fc, args);
5412d51013eSMiklos Szeredi 	if (err)
5422d51013eSMiklos Szeredi 		goto out_put_forget_req;
5432d51013eSMiklos Szeredi 
54439ee059aSMiklos Szeredi 	err = -EIO;
54539ee059aSMiklos Szeredi 	if (invalid_nodeid(outarg.nodeid))
5462d51013eSMiklos Szeredi 		goto out_put_forget_req;
54739ee059aSMiklos Szeredi 
54839ee059aSMiklos Szeredi 	if ((outarg.attr.mode ^ mode) & S_IFMT)
5492d51013eSMiklos Szeredi 		goto out_put_forget_req;
55039ee059aSMiklos Szeredi 
5519e6268dbSMiklos Szeredi 	inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
5521fb69e78SMiklos Szeredi 			  &outarg.attr, entry_attr_timeout(&outarg), 0);
5539e6268dbSMiklos Szeredi 	if (!inode) {
55407e77dcaSMiklos Szeredi 		fuse_queue_forget(fc, forget, outarg.nodeid, 1);
5559e6268dbSMiklos Szeredi 		return -ENOMEM;
5569e6268dbSMiklos Szeredi 	}
55707e77dcaSMiklos Szeredi 	kfree(forget);
5589e6268dbSMiklos Szeredi 
559b70a80e7SMiklos Szeredi 	err = d_instantiate_no_diralias(entry, inode);
560b70a80e7SMiklos Szeredi 	if (err)
561b70a80e7SMiklos Szeredi 		return err;
562d2a85164SMiklos Szeredi 
5631fb69e78SMiklos Szeredi 	fuse_change_entry_timeout(entry, &outarg);
5649e6268dbSMiklos Szeredi 	fuse_invalidate_attr(dir);
5659e6268dbSMiklos Szeredi 	return 0;
56639ee059aSMiklos Szeredi 
5672d51013eSMiklos Szeredi  out_put_forget_req:
56807e77dcaSMiklos Szeredi 	kfree(forget);
56939ee059aSMiklos Szeredi 	return err;
5709e6268dbSMiklos Szeredi }
5719e6268dbSMiklos Szeredi 
5721a67aafbSAl Viro static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode,
5739e6268dbSMiklos Szeredi 		      dev_t rdev)
5749e6268dbSMiklos Szeredi {
5759e6268dbSMiklos Szeredi 	struct fuse_mknod_in inarg;
5769e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
5777078187aSMiklos Szeredi 	FUSE_ARGS(args);
5789e6268dbSMiklos Szeredi 
579e0a43ddcSMiklos Szeredi 	if (!fc->dont_mask)
580e0a43ddcSMiklos Szeredi 		mode &= ~current_umask();
581e0a43ddcSMiklos Szeredi 
5829e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
5839e6268dbSMiklos Szeredi 	inarg.mode = mode;
5849e6268dbSMiklos Szeredi 	inarg.rdev = new_encode_dev(rdev);
585e0a43ddcSMiklos Szeredi 	inarg.umask = current_umask();
5867078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_MKNOD;
5877078187aSMiklos Szeredi 	args.in.numargs = 2;
58821f62174SMiklos Szeredi 	args.in.args[0].size = sizeof(inarg);
5897078187aSMiklos Szeredi 	args.in.args[0].value = &inarg;
5907078187aSMiklos Szeredi 	args.in.args[1].size = entry->d_name.len + 1;
5917078187aSMiklos Szeredi 	args.in.args[1].value = entry->d_name.name;
5927078187aSMiklos Szeredi 	return create_new_entry(fc, &args, dir, entry, mode);
5939e6268dbSMiklos Szeredi }
5949e6268dbSMiklos Szeredi 
5954acdaf27SAl Viro static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode,
596ebfc3b49SAl Viro 		       bool excl)
5979e6268dbSMiklos Szeredi {
5989e6268dbSMiklos Szeredi 	return fuse_mknod(dir, entry, mode, 0);
5999e6268dbSMiklos Szeredi }
6009e6268dbSMiklos Szeredi 
60118bb1db3SAl Viro static int fuse_mkdir(struct inode *dir, struct dentry *entry, umode_t mode)
6029e6268dbSMiklos Szeredi {
6039e6268dbSMiklos Szeredi 	struct fuse_mkdir_in inarg;
6049e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
6057078187aSMiklos Szeredi 	FUSE_ARGS(args);
6069e6268dbSMiklos Szeredi 
607e0a43ddcSMiklos Szeredi 	if (!fc->dont_mask)
608e0a43ddcSMiklos Szeredi 		mode &= ~current_umask();
609e0a43ddcSMiklos Szeredi 
6109e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
6119e6268dbSMiklos Szeredi 	inarg.mode = mode;
612e0a43ddcSMiklos Szeredi 	inarg.umask = current_umask();
6137078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_MKDIR;
6147078187aSMiklos Szeredi 	args.in.numargs = 2;
6157078187aSMiklos Szeredi 	args.in.args[0].size = sizeof(inarg);
6167078187aSMiklos Szeredi 	args.in.args[0].value = &inarg;
6177078187aSMiklos Szeredi 	args.in.args[1].size = entry->d_name.len + 1;
6187078187aSMiklos Szeredi 	args.in.args[1].value = entry->d_name.name;
6197078187aSMiklos Szeredi 	return create_new_entry(fc, &args, dir, entry, S_IFDIR);
6209e6268dbSMiklos Szeredi }
6219e6268dbSMiklos Szeredi 
6229e6268dbSMiklos Szeredi static int fuse_symlink(struct inode *dir, struct dentry *entry,
6239e6268dbSMiklos Szeredi 			const char *link)
6249e6268dbSMiklos Szeredi {
6259e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
6269e6268dbSMiklos Szeredi 	unsigned len = strlen(link) + 1;
6277078187aSMiklos Szeredi 	FUSE_ARGS(args);
6289e6268dbSMiklos Szeredi 
6297078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_SYMLINK;
6307078187aSMiklos Szeredi 	args.in.numargs = 2;
6317078187aSMiklos Szeredi 	args.in.args[0].size = entry->d_name.len + 1;
6327078187aSMiklos Szeredi 	args.in.args[0].value = entry->d_name.name;
6337078187aSMiklos Szeredi 	args.in.args[1].size = len;
6347078187aSMiklos Szeredi 	args.in.args[1].value = link;
6357078187aSMiklos Szeredi 	return create_new_entry(fc, &args, dir, entry, S_IFLNK);
6369e6268dbSMiklos Szeredi }
6379e6268dbSMiklos Szeredi 
638*703c7362SSeth Forshee void fuse_update_ctime(struct inode *inode)
63931f3267bSMaxim Patlasov {
64031f3267bSMaxim Patlasov 	if (!IS_NOCMTIME(inode)) {
64131f3267bSMaxim Patlasov 		inode->i_ctime = current_fs_time(inode->i_sb);
64231f3267bSMaxim Patlasov 		mark_inode_dirty_sync(inode);
64331f3267bSMaxim Patlasov 	}
64431f3267bSMaxim Patlasov }
64531f3267bSMaxim Patlasov 
6469e6268dbSMiklos Szeredi static int fuse_unlink(struct inode *dir, struct dentry *entry)
6479e6268dbSMiklos Szeredi {
6489e6268dbSMiklos Szeredi 	int err;
6499e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
6507078187aSMiklos Szeredi 	FUSE_ARGS(args);
6519e6268dbSMiklos Szeredi 
6527078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_UNLINK;
6537078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(dir);
6547078187aSMiklos Szeredi 	args.in.numargs = 1;
6557078187aSMiklos Szeredi 	args.in.args[0].size = entry->d_name.len + 1;
6567078187aSMiklos Szeredi 	args.in.args[0].value = entry->d_name.name;
6577078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
6589e6268dbSMiklos Szeredi 	if (!err) {
6592b0143b5SDavid Howells 		struct inode *inode = d_inode(entry);
660ac45d613SMiklos Szeredi 		struct fuse_inode *fi = get_fuse_inode(inode);
6619e6268dbSMiklos Szeredi 
662ac45d613SMiklos Szeredi 		spin_lock(&fc->lock);
663ac45d613SMiklos Szeredi 		fi->attr_version = ++fc->attr_version;
664dfca7cebSMiklos Szeredi 		/*
665dfca7cebSMiklos Szeredi 		 * If i_nlink == 0 then unlink doesn't make sense, yet this can
666dfca7cebSMiklos Szeredi 		 * happen if userspace filesystem is careless.  It would be
667dfca7cebSMiklos Szeredi 		 * difficult to enforce correct nlink usage so just ignore this
668dfca7cebSMiklos Szeredi 		 * condition here
669dfca7cebSMiklos Szeredi 		 */
670dfca7cebSMiklos Szeredi 		if (inode->i_nlink > 0)
671ac45d613SMiklos Szeredi 			drop_nlink(inode);
672ac45d613SMiklos Szeredi 		spin_unlock(&fc->lock);
6739e6268dbSMiklos Szeredi 		fuse_invalidate_attr(inode);
6749e6268dbSMiklos Szeredi 		fuse_invalidate_attr(dir);
6758cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
67631f3267bSMaxim Patlasov 		fuse_update_ctime(inode);
6779e6268dbSMiklos Szeredi 	} else if (err == -EINTR)
6789e6268dbSMiklos Szeredi 		fuse_invalidate_entry(entry);
6799e6268dbSMiklos Szeredi 	return err;
6809e6268dbSMiklos Szeredi }
6819e6268dbSMiklos Szeredi 
6829e6268dbSMiklos Szeredi static int fuse_rmdir(struct inode *dir, struct dentry *entry)
6839e6268dbSMiklos Szeredi {
6849e6268dbSMiklos Szeredi 	int err;
6859e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
6867078187aSMiklos Szeredi 	FUSE_ARGS(args);
6879e6268dbSMiklos Szeredi 
6887078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_RMDIR;
6897078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(dir);
6907078187aSMiklos Szeredi 	args.in.numargs = 1;
6917078187aSMiklos Szeredi 	args.in.args[0].size = entry->d_name.len + 1;
6927078187aSMiklos Szeredi 	args.in.args[0].value = entry->d_name.name;
6937078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
6949e6268dbSMiklos Szeredi 	if (!err) {
6952b0143b5SDavid Howells 		clear_nlink(d_inode(entry));
6969e6268dbSMiklos Szeredi 		fuse_invalidate_attr(dir);
6978cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
6989e6268dbSMiklos Szeredi 	} else if (err == -EINTR)
6999e6268dbSMiklos Szeredi 		fuse_invalidate_entry(entry);
7009e6268dbSMiklos Szeredi 	return err;
7019e6268dbSMiklos Szeredi }
7029e6268dbSMiklos Szeredi 
7031560c974SMiklos Szeredi static int fuse_rename_common(struct inode *olddir, struct dentry *oldent,
7041560c974SMiklos Szeredi 			      struct inode *newdir, struct dentry *newent,
7051560c974SMiklos Szeredi 			      unsigned int flags, int opcode, size_t argsize)
7069e6268dbSMiklos Szeredi {
7079e6268dbSMiklos Szeredi 	int err;
7081560c974SMiklos Szeredi 	struct fuse_rename2_in inarg;
7099e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(olddir);
7107078187aSMiklos Szeredi 	FUSE_ARGS(args);
7119e6268dbSMiklos Szeredi 
7121560c974SMiklos Szeredi 	memset(&inarg, 0, argsize);
7139e6268dbSMiklos Szeredi 	inarg.newdir = get_node_id(newdir);
7141560c974SMiklos Szeredi 	inarg.flags = flags;
7157078187aSMiklos Szeredi 	args.in.h.opcode = opcode;
7167078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(olddir);
7177078187aSMiklos Szeredi 	args.in.numargs = 3;
7187078187aSMiklos Szeredi 	args.in.args[0].size = argsize;
7197078187aSMiklos Szeredi 	args.in.args[0].value = &inarg;
7207078187aSMiklos Szeredi 	args.in.args[1].size = oldent->d_name.len + 1;
7217078187aSMiklos Szeredi 	args.in.args[1].value = oldent->d_name.name;
7227078187aSMiklos Szeredi 	args.in.args[2].size = newent->d_name.len + 1;
7237078187aSMiklos Szeredi 	args.in.args[2].value = newent->d_name.name;
7247078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
7259e6268dbSMiklos Szeredi 	if (!err) {
72608b63307SMiklos Szeredi 		/* ctime changes */
7272b0143b5SDavid Howells 		fuse_invalidate_attr(d_inode(oldent));
7282b0143b5SDavid Howells 		fuse_update_ctime(d_inode(oldent));
72908b63307SMiklos Szeredi 
7301560c974SMiklos Szeredi 		if (flags & RENAME_EXCHANGE) {
7312b0143b5SDavid Howells 			fuse_invalidate_attr(d_inode(newent));
7322b0143b5SDavid Howells 			fuse_update_ctime(d_inode(newent));
7331560c974SMiklos Szeredi 		}
7341560c974SMiklos Szeredi 
7359e6268dbSMiklos Szeredi 		fuse_invalidate_attr(olddir);
7369e6268dbSMiklos Szeredi 		if (olddir != newdir)
7379e6268dbSMiklos Szeredi 			fuse_invalidate_attr(newdir);
7388cbdf1e6SMiklos Szeredi 
7398cbdf1e6SMiklos Szeredi 		/* newent will end up negative */
7402b0143b5SDavid Howells 		if (!(flags & RENAME_EXCHANGE) && d_really_is_positive(newent)) {
7412b0143b5SDavid Howells 			fuse_invalidate_attr(d_inode(newent));
7428cbdf1e6SMiklos Szeredi 			fuse_invalidate_entry_cache(newent);
7432b0143b5SDavid Howells 			fuse_update_ctime(d_inode(newent));
7445219f346SMiklos Szeredi 		}
7459e6268dbSMiklos Szeredi 	} else if (err == -EINTR) {
7469e6268dbSMiklos Szeredi 		/* If request was interrupted, DEITY only knows if the
7479e6268dbSMiklos Szeredi 		   rename actually took place.  If the invalidation
7489e6268dbSMiklos Szeredi 		   fails (e.g. some process has CWD under the renamed
7499e6268dbSMiklos Szeredi 		   directory), then there can be inconsistency between
7509e6268dbSMiklos Szeredi 		   the dcache and the real filesystem.  Tough luck. */
7519e6268dbSMiklos Szeredi 		fuse_invalidate_entry(oldent);
7522b0143b5SDavid Howells 		if (d_really_is_positive(newent))
7539e6268dbSMiklos Szeredi 			fuse_invalidate_entry(newent);
7549e6268dbSMiklos Szeredi 	}
7559e6268dbSMiklos Szeredi 
7569e6268dbSMiklos Szeredi 	return err;
7579e6268dbSMiklos Szeredi }
7589e6268dbSMiklos Szeredi 
7591560c974SMiklos Szeredi static int fuse_rename2(struct inode *olddir, struct dentry *oldent,
7601560c974SMiklos Szeredi 			struct inode *newdir, struct dentry *newent,
7611560c974SMiklos Szeredi 			unsigned int flags)
7621560c974SMiklos Szeredi {
7631560c974SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(olddir);
7641560c974SMiklos Szeredi 	int err;
7651560c974SMiklos Szeredi 
7661560c974SMiklos Szeredi 	if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE))
7671560c974SMiklos Szeredi 		return -EINVAL;
7681560c974SMiklos Szeredi 
7694237ba43SMiklos Szeredi 	if (flags) {
7701560c974SMiklos Szeredi 		if (fc->no_rename2 || fc->minor < 23)
7711560c974SMiklos Szeredi 			return -EINVAL;
7721560c974SMiklos Szeredi 
7731560c974SMiklos Szeredi 		err = fuse_rename_common(olddir, oldent, newdir, newent, flags,
7744237ba43SMiklos Szeredi 					 FUSE_RENAME2,
7754237ba43SMiklos Szeredi 					 sizeof(struct fuse_rename2_in));
7761560c974SMiklos Szeredi 		if (err == -ENOSYS) {
7771560c974SMiklos Szeredi 			fc->no_rename2 = 1;
7781560c974SMiklos Szeredi 			err = -EINVAL;
7791560c974SMiklos Szeredi 		}
7804237ba43SMiklos Szeredi 	} else {
7814237ba43SMiklos Szeredi 		err = fuse_rename_common(olddir, oldent, newdir, newent, 0,
7824237ba43SMiklos Szeredi 					 FUSE_RENAME,
7834237ba43SMiklos Szeredi 					 sizeof(struct fuse_rename_in));
7844237ba43SMiklos Szeredi 	}
7851560c974SMiklos Szeredi 
7864237ba43SMiklos Szeredi 	return err;
7874237ba43SMiklos Szeredi }
7884237ba43SMiklos Szeredi 
7899e6268dbSMiklos Szeredi static int fuse_link(struct dentry *entry, struct inode *newdir,
7909e6268dbSMiklos Szeredi 		     struct dentry *newent)
7919e6268dbSMiklos Szeredi {
7929e6268dbSMiklos Szeredi 	int err;
7939e6268dbSMiklos Szeredi 	struct fuse_link_in inarg;
7942b0143b5SDavid Howells 	struct inode *inode = d_inode(entry);
7959e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
7967078187aSMiklos Szeredi 	FUSE_ARGS(args);
7979e6268dbSMiklos Szeredi 
7989e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
7999e6268dbSMiklos Szeredi 	inarg.oldnodeid = get_node_id(inode);
8007078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_LINK;
8017078187aSMiklos Szeredi 	args.in.numargs = 2;
8027078187aSMiklos Szeredi 	args.in.args[0].size = sizeof(inarg);
8037078187aSMiklos Szeredi 	args.in.args[0].value = &inarg;
8047078187aSMiklos Szeredi 	args.in.args[1].size = newent->d_name.len + 1;
8057078187aSMiklos Szeredi 	args.in.args[1].value = newent->d_name.name;
8067078187aSMiklos Szeredi 	err = create_new_entry(fc, &args, newdir, newent, inode->i_mode);
8079e6268dbSMiklos Szeredi 	/* Contrary to "normal" filesystems it can happen that link
8089e6268dbSMiklos Szeredi 	   makes two "logical" inodes point to the same "physical"
8099e6268dbSMiklos Szeredi 	   inode.  We invalidate the attributes of the old one, so it
8109e6268dbSMiklos Szeredi 	   will reflect changes in the backing inode (link count,
8119e6268dbSMiklos Szeredi 	   etc.)
8129e6268dbSMiklos Szeredi 	*/
813ac45d613SMiklos Szeredi 	if (!err) {
814ac45d613SMiklos Szeredi 		struct fuse_inode *fi = get_fuse_inode(inode);
815ac45d613SMiklos Szeredi 
816ac45d613SMiklos Szeredi 		spin_lock(&fc->lock);
817ac45d613SMiklos Szeredi 		fi->attr_version = ++fc->attr_version;
818ac45d613SMiklos Szeredi 		inc_nlink(inode);
819ac45d613SMiklos Szeredi 		spin_unlock(&fc->lock);
8209e6268dbSMiklos Szeredi 		fuse_invalidate_attr(inode);
82131f3267bSMaxim Patlasov 		fuse_update_ctime(inode);
822ac45d613SMiklos Szeredi 	} else if (err == -EINTR) {
823ac45d613SMiklos Szeredi 		fuse_invalidate_attr(inode);
824ac45d613SMiklos Szeredi 	}
8259e6268dbSMiklos Szeredi 	return err;
8269e6268dbSMiklos Szeredi }
8279e6268dbSMiklos Szeredi 
8281fb69e78SMiklos Szeredi static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
8291fb69e78SMiklos Szeredi 			  struct kstat *stat)
8301fb69e78SMiklos Szeredi {
831203627bbSMiklos Szeredi 	unsigned int blkbits;
8328373200bSPavel Emelyanov 	struct fuse_conn *fc = get_fuse_conn(inode);
8338373200bSPavel Emelyanov 
8348373200bSPavel Emelyanov 	/* see the comment in fuse_change_attributes() */
835b0aa7606SMaxim Patlasov 	if (fc->writeback_cache && S_ISREG(inode->i_mode)) {
8368373200bSPavel Emelyanov 		attr->size = i_size_read(inode);
837b0aa7606SMaxim Patlasov 		attr->mtime = inode->i_mtime.tv_sec;
838b0aa7606SMaxim Patlasov 		attr->mtimensec = inode->i_mtime.tv_nsec;
83931f3267bSMaxim Patlasov 		attr->ctime = inode->i_ctime.tv_sec;
84031f3267bSMaxim Patlasov 		attr->ctimensec = inode->i_ctime.tv_nsec;
841b0aa7606SMaxim Patlasov 	}
842203627bbSMiklos Szeredi 
8431fb69e78SMiklos Szeredi 	stat->dev = inode->i_sb->s_dev;
8441fb69e78SMiklos Szeredi 	stat->ino = attr->ino;
8451fb69e78SMiklos Szeredi 	stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
8461fb69e78SMiklos Szeredi 	stat->nlink = attr->nlink;
847499dcf20SEric W. Biederman 	stat->uid = make_kuid(&init_user_ns, attr->uid);
848499dcf20SEric W. Biederman 	stat->gid = make_kgid(&init_user_ns, attr->gid);
8491fb69e78SMiklos Szeredi 	stat->rdev = inode->i_rdev;
8501fb69e78SMiklos Szeredi 	stat->atime.tv_sec = attr->atime;
8511fb69e78SMiklos Szeredi 	stat->atime.tv_nsec = attr->atimensec;
8521fb69e78SMiklos Szeredi 	stat->mtime.tv_sec = attr->mtime;
8531fb69e78SMiklos Szeredi 	stat->mtime.tv_nsec = attr->mtimensec;
8541fb69e78SMiklos Szeredi 	stat->ctime.tv_sec = attr->ctime;
8551fb69e78SMiklos Szeredi 	stat->ctime.tv_nsec = attr->ctimensec;
8561fb69e78SMiklos Szeredi 	stat->size = attr->size;
8571fb69e78SMiklos Szeredi 	stat->blocks = attr->blocks;
858203627bbSMiklos Szeredi 
859203627bbSMiklos Szeredi 	if (attr->blksize != 0)
860203627bbSMiklos Szeredi 		blkbits = ilog2(attr->blksize);
861203627bbSMiklos Szeredi 	else
862203627bbSMiklos Szeredi 		blkbits = inode->i_sb->s_blocksize_bits;
863203627bbSMiklos Szeredi 
864203627bbSMiklos Szeredi 	stat->blksize = 1 << blkbits;
8651fb69e78SMiklos Szeredi }
8661fb69e78SMiklos Szeredi 
867c79e322fSMiklos Szeredi static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
868c79e322fSMiklos Szeredi 			   struct file *file)
869e5e5558eSMiklos Szeredi {
870e5e5558eSMiklos Szeredi 	int err;
871c79e322fSMiklos Szeredi 	struct fuse_getattr_in inarg;
872c79e322fSMiklos Szeredi 	struct fuse_attr_out outarg;
873e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
8747078187aSMiklos Szeredi 	FUSE_ARGS(args);
8751fb69e78SMiklos Szeredi 	u64 attr_version;
8761fb69e78SMiklos Szeredi 
8777dca9fd3SMiklos Szeredi 	attr_version = fuse_get_attr_version(fc);
8781fb69e78SMiklos Szeredi 
879c79e322fSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
8800e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
881c79e322fSMiklos Szeredi 	/* Directories have separate file-handle space */
882c79e322fSMiklos Szeredi 	if (file && S_ISREG(inode->i_mode)) {
883c79e322fSMiklos Szeredi 		struct fuse_file *ff = file->private_data;
884c79e322fSMiklos Szeredi 
885c79e322fSMiklos Szeredi 		inarg.getattr_flags |= FUSE_GETATTR_FH;
886c79e322fSMiklos Szeredi 		inarg.fh = ff->fh;
887c79e322fSMiklos Szeredi 	}
8887078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_GETATTR;
8897078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(inode);
8907078187aSMiklos Szeredi 	args.in.numargs = 1;
8917078187aSMiklos Szeredi 	args.in.args[0].size = sizeof(inarg);
8927078187aSMiklos Szeredi 	args.in.args[0].value = &inarg;
8937078187aSMiklos Szeredi 	args.out.numargs = 1;
8947078187aSMiklos Szeredi 	args.out.args[0].size = sizeof(outarg);
8957078187aSMiklos Szeredi 	args.out.args[0].value = &outarg;
8967078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
897e5e5558eSMiklos Szeredi 	if (!err) {
898c79e322fSMiklos Szeredi 		if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
899e5e5558eSMiklos Szeredi 			make_bad_inode(inode);
900e5e5558eSMiklos Szeredi 			err = -EIO;
901e5e5558eSMiklos Szeredi 		} else {
902c79e322fSMiklos Szeredi 			fuse_change_attributes(inode, &outarg.attr,
903c79e322fSMiklos Szeredi 					       attr_timeout(&outarg),
9041fb69e78SMiklos Szeredi 					       attr_version);
9051fb69e78SMiklos Szeredi 			if (stat)
906c79e322fSMiklos Szeredi 				fuse_fillattr(inode, &outarg.attr, stat);
907e5e5558eSMiklos Szeredi 		}
908e5e5558eSMiklos Szeredi 	}
909e5e5558eSMiklos Szeredi 	return err;
910e5e5558eSMiklos Szeredi }
911e5e5558eSMiklos Szeredi 
912bcb4be80SMiklos Szeredi int fuse_update_attributes(struct inode *inode, struct kstat *stat,
913bcb4be80SMiklos Szeredi 			   struct file *file, bool *refreshed)
914bcb4be80SMiklos Szeredi {
915bcb4be80SMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
916bcb4be80SMiklos Szeredi 	int err;
917bcb4be80SMiklos Szeredi 	bool r;
918bcb4be80SMiklos Szeredi 
919126b9d43SMiklos Szeredi 	if (time_before64(fi->i_time, get_jiffies_64())) {
920bcb4be80SMiklos Szeredi 		r = true;
921bcb4be80SMiklos Szeredi 		err = fuse_do_getattr(inode, stat, file);
922bcb4be80SMiklos Szeredi 	} else {
923bcb4be80SMiklos Szeredi 		r = false;
924bcb4be80SMiklos Szeredi 		err = 0;
925bcb4be80SMiklos Szeredi 		if (stat) {
926bcb4be80SMiklos Szeredi 			generic_fillattr(inode, stat);
927bcb4be80SMiklos Szeredi 			stat->mode = fi->orig_i_mode;
92845c72cd7SPavel Shilovsky 			stat->ino = fi->orig_ino;
929bcb4be80SMiklos Szeredi 		}
930bcb4be80SMiklos Szeredi 	}
931bcb4be80SMiklos Szeredi 
932bcb4be80SMiklos Szeredi 	if (refreshed != NULL)
933bcb4be80SMiklos Szeredi 		*refreshed = r;
934bcb4be80SMiklos Szeredi 
935bcb4be80SMiklos Szeredi 	return err;
936bcb4be80SMiklos Szeredi }
937bcb4be80SMiklos Szeredi 
9383b463ae0SJohn Muir int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid,
939451d0f59SJohn Muir 			     u64 child_nodeid, struct qstr *name)
9403b463ae0SJohn Muir {
9413b463ae0SJohn Muir 	int err = -ENOTDIR;
9423b463ae0SJohn Muir 	struct inode *parent;
9433b463ae0SJohn Muir 	struct dentry *dir;
9443b463ae0SJohn Muir 	struct dentry *entry;
9453b463ae0SJohn Muir 
9463b463ae0SJohn Muir 	parent = ilookup5(sb, parent_nodeid, fuse_inode_eq, &parent_nodeid);
9473b463ae0SJohn Muir 	if (!parent)
9483b463ae0SJohn Muir 		return -ENOENT;
9493b463ae0SJohn Muir 
9505955102cSAl Viro 	inode_lock(parent);
9513b463ae0SJohn Muir 	if (!S_ISDIR(parent->i_mode))
9523b463ae0SJohn Muir 		goto unlock;
9533b463ae0SJohn Muir 
9543b463ae0SJohn Muir 	err = -ENOENT;
9553b463ae0SJohn Muir 	dir = d_find_alias(parent);
9563b463ae0SJohn Muir 	if (!dir)
9573b463ae0SJohn Muir 		goto unlock;
9583b463ae0SJohn Muir 
9598387ff25SLinus Torvalds 	name->hash = full_name_hash(dir, name->name, name->len);
9603b463ae0SJohn Muir 	entry = d_lookup(dir, name);
9613b463ae0SJohn Muir 	dput(dir);
9623b463ae0SJohn Muir 	if (!entry)
9633b463ae0SJohn Muir 		goto unlock;
9643b463ae0SJohn Muir 
9653b463ae0SJohn Muir 	fuse_invalidate_attr(parent);
9663b463ae0SJohn Muir 	fuse_invalidate_entry(entry);
967451d0f59SJohn Muir 
9682b0143b5SDavid Howells 	if (child_nodeid != 0 && d_really_is_positive(entry)) {
9695955102cSAl Viro 		inode_lock(d_inode(entry));
9702b0143b5SDavid Howells 		if (get_node_id(d_inode(entry)) != child_nodeid) {
971451d0f59SJohn Muir 			err = -ENOENT;
972451d0f59SJohn Muir 			goto badentry;
973451d0f59SJohn Muir 		}
974451d0f59SJohn Muir 		if (d_mountpoint(entry)) {
975451d0f59SJohn Muir 			err = -EBUSY;
976451d0f59SJohn Muir 			goto badentry;
977451d0f59SJohn Muir 		}
978e36cb0b8SDavid Howells 		if (d_is_dir(entry)) {
979451d0f59SJohn Muir 			shrink_dcache_parent(entry);
980451d0f59SJohn Muir 			if (!simple_empty(entry)) {
981451d0f59SJohn Muir 				err = -ENOTEMPTY;
982451d0f59SJohn Muir 				goto badentry;
983451d0f59SJohn Muir 			}
9842b0143b5SDavid Howells 			d_inode(entry)->i_flags |= S_DEAD;
985451d0f59SJohn Muir 		}
986451d0f59SJohn Muir 		dont_mount(entry);
9872b0143b5SDavid Howells 		clear_nlink(d_inode(entry));
9883b463ae0SJohn Muir 		err = 0;
989451d0f59SJohn Muir  badentry:
9905955102cSAl Viro 		inode_unlock(d_inode(entry));
991451d0f59SJohn Muir 		if (!err)
992451d0f59SJohn Muir 			d_delete(entry);
993451d0f59SJohn Muir 	} else {
994451d0f59SJohn Muir 		err = 0;
995451d0f59SJohn Muir 	}
996451d0f59SJohn Muir 	dput(entry);
9973b463ae0SJohn Muir 
9983b463ae0SJohn Muir  unlock:
9995955102cSAl Viro 	inode_unlock(parent);
10003b463ae0SJohn Muir 	iput(parent);
10013b463ae0SJohn Muir 	return err;
10023b463ae0SJohn Muir }
10033b463ae0SJohn Muir 
100487729a55SMiklos Szeredi /*
100587729a55SMiklos Szeredi  * Calling into a user-controlled filesystem gives the filesystem
1006c2132c1bSAnatol Pomozov  * daemon ptrace-like capabilities over the current process.  This
100787729a55SMiklos Szeredi  * means, that the filesystem daemon is able to record the exact
100887729a55SMiklos Szeredi  * filesystem operations performed, and can also control the behavior
100987729a55SMiklos Szeredi  * of the requester process in otherwise impossible ways.  For example
101087729a55SMiklos Szeredi  * it can delay the operation for arbitrary length of time allowing
101187729a55SMiklos Szeredi  * DoS against the requester.
101287729a55SMiklos Szeredi  *
101387729a55SMiklos Szeredi  * For this reason only those processes can call into the filesystem,
101487729a55SMiklos Szeredi  * for which the owner of the mount has ptrace privilege.  This
101587729a55SMiklos Szeredi  * excludes processes started by other users, suid or sgid processes.
101687729a55SMiklos Szeredi  */
1017c2132c1bSAnatol Pomozov int fuse_allow_current_process(struct fuse_conn *fc)
101887729a55SMiklos Szeredi {
1019c69e8d9cSDavid Howells 	const struct cred *cred;
1020c69e8d9cSDavid Howells 
102187729a55SMiklos Szeredi 	if (fc->flags & FUSE_ALLOW_OTHER)
102287729a55SMiklos Szeredi 		return 1;
102387729a55SMiklos Szeredi 
1024c2132c1bSAnatol Pomozov 	cred = current_cred();
1025499dcf20SEric W. Biederman 	if (uid_eq(cred->euid, fc->user_id) &&
1026499dcf20SEric W. Biederman 	    uid_eq(cred->suid, fc->user_id) &&
1027499dcf20SEric W. Biederman 	    uid_eq(cred->uid,  fc->user_id) &&
1028499dcf20SEric W. Biederman 	    gid_eq(cred->egid, fc->group_id) &&
1029499dcf20SEric W. Biederman 	    gid_eq(cred->sgid, fc->group_id) &&
1030499dcf20SEric W. Biederman 	    gid_eq(cred->gid,  fc->group_id))
1031c2132c1bSAnatol Pomozov 		return 1;
103287729a55SMiklos Szeredi 
1033c2132c1bSAnatol Pomozov 	return 0;
103487729a55SMiklos Szeredi }
103587729a55SMiklos Szeredi 
103631d40d74SMiklos Szeredi static int fuse_access(struct inode *inode, int mask)
103731d40d74SMiklos Szeredi {
103831d40d74SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
10397078187aSMiklos Szeredi 	FUSE_ARGS(args);
104031d40d74SMiklos Szeredi 	struct fuse_access_in inarg;
104131d40d74SMiklos Szeredi 	int err;
104231d40d74SMiklos Szeredi 
1043698fa1d1SMiklos Szeredi 	BUG_ON(mask & MAY_NOT_BLOCK);
1044698fa1d1SMiklos Szeredi 
104531d40d74SMiklos Szeredi 	if (fc->no_access)
104631d40d74SMiklos Szeredi 		return 0;
104731d40d74SMiklos Szeredi 
104831d40d74SMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
1049e6305c43SAl Viro 	inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC);
10507078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_ACCESS;
10517078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(inode);
10527078187aSMiklos Szeredi 	args.in.numargs = 1;
10537078187aSMiklos Szeredi 	args.in.args[0].size = sizeof(inarg);
10547078187aSMiklos Szeredi 	args.in.args[0].value = &inarg;
10557078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
105631d40d74SMiklos Szeredi 	if (err == -ENOSYS) {
105731d40d74SMiklos Szeredi 		fc->no_access = 1;
105831d40d74SMiklos Szeredi 		err = 0;
105931d40d74SMiklos Szeredi 	}
106031d40d74SMiklos Szeredi 	return err;
106131d40d74SMiklos Szeredi }
106231d40d74SMiklos Szeredi 
106310556cb2SAl Viro static int fuse_perm_getattr(struct inode *inode, int mask)
106419690ddbSMiklos Szeredi {
106510556cb2SAl Viro 	if (mask & MAY_NOT_BLOCK)
106619690ddbSMiklos Szeredi 		return -ECHILD;
106719690ddbSMiklos Szeredi 
106819690ddbSMiklos Szeredi 	return fuse_do_getattr(inode, NULL, NULL);
106919690ddbSMiklos Szeredi }
107019690ddbSMiklos Szeredi 
10716f9f1180SMiklos Szeredi /*
10726f9f1180SMiklos Szeredi  * Check permission.  The two basic access models of FUSE are:
10736f9f1180SMiklos Szeredi  *
10746f9f1180SMiklos Szeredi  * 1) Local access checking ('default_permissions' mount option) based
10756f9f1180SMiklos Szeredi  * on file mode.  This is the plain old disk filesystem permission
10766f9f1180SMiklos Szeredi  * modell.
10776f9f1180SMiklos Szeredi  *
10786f9f1180SMiklos Szeredi  * 2) "Remote" access checking, where server is responsible for
10796f9f1180SMiklos Szeredi  * checking permission in each inode operation.  An exception to this
10806f9f1180SMiklos Szeredi  * is if ->permission() was invoked from sys_access() in which case an
10816f9f1180SMiklos Szeredi  * access request is sent.  Execute permission is still checked
10826f9f1180SMiklos Szeredi  * locally based on file mode.
10836f9f1180SMiklos Szeredi  */
108410556cb2SAl Viro static int fuse_permission(struct inode *inode, int mask)
1085e5e5558eSMiklos Szeredi {
1086e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1087244f6385SMiklos Szeredi 	bool refreshed = false;
1088244f6385SMiklos Szeredi 	int err = 0;
1089e5e5558eSMiklos Szeredi 
1090c2132c1bSAnatol Pomozov 	if (!fuse_allow_current_process(fc))
1091e5e5558eSMiklos Szeredi 		return -EACCES;
1092244f6385SMiklos Szeredi 
1093244f6385SMiklos Szeredi 	/*
1094e8e96157SMiklos Szeredi 	 * If attributes are needed, refresh them before proceeding
1095244f6385SMiklos Szeredi 	 */
1096e8e96157SMiklos Szeredi 	if ((fc->flags & FUSE_DEFAULT_PERMISSIONS) ||
1097e8e96157SMiklos Szeredi 	    ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
109819690ddbSMiklos Szeredi 		struct fuse_inode *fi = get_fuse_inode(inode);
109919690ddbSMiklos Szeredi 
1100126b9d43SMiklos Szeredi 		if (time_before64(fi->i_time, get_jiffies_64())) {
110119690ddbSMiklos Szeredi 			refreshed = true;
110219690ddbSMiklos Szeredi 
110310556cb2SAl Viro 			err = fuse_perm_getattr(inode, mask);
1104244f6385SMiklos Szeredi 			if (err)
1105244f6385SMiklos Szeredi 				return err;
11061fb69e78SMiklos Szeredi 		}
110719690ddbSMiklos Szeredi 	}
1108244f6385SMiklos Szeredi 
1109244f6385SMiklos Szeredi 	if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
11102830ba7fSAl Viro 		err = generic_permission(inode, mask);
11111e9a4ed9SMiklos Szeredi 
11121e9a4ed9SMiklos Szeredi 		/* If permission is denied, try to refresh file
11131e9a4ed9SMiklos Szeredi 		   attributes.  This is also needed, because the root
11141e9a4ed9SMiklos Szeredi 		   node will at first have no permissions */
1115244f6385SMiklos Szeredi 		if (err == -EACCES && !refreshed) {
111610556cb2SAl Viro 			err = fuse_perm_getattr(inode, mask);
11171e9a4ed9SMiklos Szeredi 			if (!err)
11182830ba7fSAl Viro 				err = generic_permission(inode, mask);
11191e9a4ed9SMiklos Szeredi 		}
11201e9a4ed9SMiklos Szeredi 
11216f9f1180SMiklos Szeredi 		/* Note: the opposite of the above test does not
11226f9f1180SMiklos Szeredi 		   exist.  So if permissions are revoked this won't be
11236f9f1180SMiklos Szeredi 		   noticed immediately, only after the attribute
11246f9f1180SMiklos Szeredi 		   timeout has expired */
11259cfcac81SEric Paris 	} else if (mask & (MAY_ACCESS | MAY_CHDIR)) {
1126e8e96157SMiklos Szeredi 		err = fuse_access(inode, mask);
1127e8e96157SMiklos Szeredi 	} else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
1128e8e96157SMiklos Szeredi 		if (!(inode->i_mode & S_IXUGO)) {
1129e8e96157SMiklos Szeredi 			if (refreshed)
1130e5e5558eSMiklos Szeredi 				return -EACCES;
113131d40d74SMiklos Szeredi 
113210556cb2SAl Viro 			err = fuse_perm_getattr(inode, mask);
1133e8e96157SMiklos Szeredi 			if (!err && !(inode->i_mode & S_IXUGO))
1134e8e96157SMiklos Szeredi 				return -EACCES;
1135e8e96157SMiklos Szeredi 		}
1136e5e5558eSMiklos Szeredi 	}
1137244f6385SMiklos Szeredi 	return err;
1138e5e5558eSMiklos Szeredi }
1139e5e5558eSMiklos Szeredi 
1140e5e5558eSMiklos Szeredi static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
11418d3af7f3SAl Viro 			 struct dir_context *ctx)
1142e5e5558eSMiklos Szeredi {
1143e5e5558eSMiklos Szeredi 	while (nbytes >= FUSE_NAME_OFFSET) {
1144e5e5558eSMiklos Szeredi 		struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
1145e5e5558eSMiklos Szeredi 		size_t reclen = FUSE_DIRENT_SIZE(dirent);
1146e5e5558eSMiklos Szeredi 		if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
1147e5e5558eSMiklos Szeredi 			return -EIO;
1148e5e5558eSMiklos Szeredi 		if (reclen > nbytes)
1149e5e5558eSMiklos Szeredi 			break;
1150efeb9e60SMiklos Szeredi 		if (memchr(dirent->name, '/', dirent->namelen) != NULL)
1151efeb9e60SMiklos Szeredi 			return -EIO;
1152e5e5558eSMiklos Szeredi 
11538d3af7f3SAl Viro 		if (!dir_emit(ctx, dirent->name, dirent->namelen,
11548d3af7f3SAl Viro 			       dirent->ino, dirent->type))
1155e5e5558eSMiklos Szeredi 			break;
1156e5e5558eSMiklos Szeredi 
1157e5e5558eSMiklos Szeredi 		buf += reclen;
1158e5e5558eSMiklos Szeredi 		nbytes -= reclen;
11598d3af7f3SAl Viro 		ctx->pos = dirent->off;
1160e5e5558eSMiklos Szeredi 	}
1161e5e5558eSMiklos Szeredi 
1162e5e5558eSMiklos Szeredi 	return 0;
1163e5e5558eSMiklos Szeredi }
1164e5e5558eSMiklos Szeredi 
11650b05b183SAnand V. Avati static int fuse_direntplus_link(struct file *file,
11660b05b183SAnand V. Avati 				struct fuse_direntplus *direntplus,
11670b05b183SAnand V. Avati 				u64 attr_version)
11680b05b183SAnand V. Avati {
11690b05b183SAnand V. Avati 	struct fuse_entry_out *o = &direntplus->entry_out;
11700b05b183SAnand V. Avati 	struct fuse_dirent *dirent = &direntplus->dirent;
11710b05b183SAnand V. Avati 	struct dentry *parent = file->f_path.dentry;
11720b05b183SAnand V. Avati 	struct qstr name = QSTR_INIT(dirent->name, dirent->namelen);
11730b05b183SAnand V. Avati 	struct dentry *dentry;
11740b05b183SAnand V. Avati 	struct dentry *alias;
11752b0143b5SDavid Howells 	struct inode *dir = d_inode(parent);
11760b05b183SAnand V. Avati 	struct fuse_conn *fc;
11770b05b183SAnand V. Avati 	struct inode *inode;
1178d9b3dbdcSAl Viro 	DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
11790b05b183SAnand V. Avati 
11800b05b183SAnand V. Avati 	if (!o->nodeid) {
11810b05b183SAnand V. Avati 		/*
11820b05b183SAnand V. Avati 		 * Unlike in the case of fuse_lookup, zero nodeid does not mean
11830b05b183SAnand V. Avati 		 * ENOENT. Instead, it only means the userspace filesystem did
11840b05b183SAnand V. Avati 		 * not want to return attributes/handle for this entry.
11850b05b183SAnand V. Avati 		 *
11860b05b183SAnand V. Avati 		 * So do nothing.
11870b05b183SAnand V. Avati 		 */
11880b05b183SAnand V. Avati 		return 0;
11890b05b183SAnand V. Avati 	}
11900b05b183SAnand V. Avati 
11910b05b183SAnand V. Avati 	if (name.name[0] == '.') {
11920b05b183SAnand V. Avati 		/*
11930b05b183SAnand V. Avati 		 * We could potentially refresh the attributes of the directory
11940b05b183SAnand V. Avati 		 * and its parent?
11950b05b183SAnand V. Avati 		 */
11960b05b183SAnand V. Avati 		if (name.len == 1)
11970b05b183SAnand V. Avati 			return 0;
11980b05b183SAnand V. Avati 		if (name.name[1] == '.' && name.len == 2)
11990b05b183SAnand V. Avati 			return 0;
12000b05b183SAnand V. Avati 	}
1201a28ef45cSMiklos Szeredi 
1202a28ef45cSMiklos Szeredi 	if (invalid_nodeid(o->nodeid))
1203a28ef45cSMiklos Szeredi 		return -EIO;
1204a28ef45cSMiklos Szeredi 	if (!fuse_valid_type(o->attr.mode))
1205a28ef45cSMiklos Szeredi 		return -EIO;
1206a28ef45cSMiklos Szeredi 
12070b05b183SAnand V. Avati 	fc = get_fuse_conn(dir);
12080b05b183SAnand V. Avati 
12098387ff25SLinus Torvalds 	name.hash = full_name_hash(parent, name.name, name.len);
12100b05b183SAnand V. Avati 	dentry = d_lookup(parent, &name);
1211d9b3dbdcSAl Viro 	if (!dentry) {
1212d9b3dbdcSAl Viro retry:
1213d9b3dbdcSAl Viro 		dentry = d_alloc_parallel(parent, &name, &wq);
1214d9b3dbdcSAl Viro 		if (IS_ERR(dentry))
1215d9b3dbdcSAl Viro 			return PTR_ERR(dentry);
1216d9b3dbdcSAl Viro 	}
1217d9b3dbdcSAl Viro 	if (!d_in_lookup(dentry)) {
1218d9b3dbdcSAl Viro 		struct fuse_inode *fi;
12192b0143b5SDavid Howells 		inode = d_inode(dentry);
1220d9b3dbdcSAl Viro 		if (!inode ||
1221d9b3dbdcSAl Viro 		    get_node_id(inode) != o->nodeid ||
1222a28ef45cSMiklos Szeredi 		    ((o->attr.mode ^ inode->i_mode) & S_IFMT)) {
12235542aa2fSEric W. Biederman 			d_invalidate(dentry);
1224d9b3dbdcSAl Viro 			dput(dentry);
1225d9b3dbdcSAl Viro 			goto retry;
1226d9b3dbdcSAl Viro 		}
1227d9b3dbdcSAl Viro 		if (is_bad_inode(inode)) {
1228d9b3dbdcSAl Viro 			dput(dentry);
1229d9b3dbdcSAl Viro 			return -EIO;
1230d9b3dbdcSAl Viro 		}
1231d9b3dbdcSAl Viro 
12320b05b183SAnand V. Avati 		fi = get_fuse_inode(inode);
12330b05b183SAnand V. Avati 		spin_lock(&fc->lock);
12340b05b183SAnand V. Avati 		fi->nlookup++;
12350b05b183SAnand V. Avati 		spin_unlock(&fc->lock);
12360b05b183SAnand V. Avati 
1237fa2b7213SMiklos Szeredi 		fuse_change_attributes(inode, &o->attr,
1238fa2b7213SMiklos Szeredi 				       entry_attr_timeout(o),
1239fa2b7213SMiklos Szeredi 				       attr_version);
12400b05b183SAnand V. Avati 		/*
1241d9b3dbdcSAl Viro 		 * The other branch comes via fuse_iget()
12420b05b183SAnand V. Avati 		 * which bumps nlookup inside
12430b05b183SAnand V. Avati 		 */
1244d9b3dbdcSAl Viro 	} else {
12450b05b183SAnand V. Avati 		inode = fuse_iget(dir->i_sb, o->nodeid, o->generation,
1246d9b3dbdcSAl Viro 				  &o->attr, entry_attr_timeout(o),
1247d9b3dbdcSAl Viro 				  attr_version);
12480b05b183SAnand V. Avati 		if (!inode)
1249d9b3dbdcSAl Viro 			inode = ERR_PTR(-ENOMEM);
12500b05b183SAnand V. Avati 
125141d28bcaSAl Viro 		alias = d_splice_alias(inode, dentry);
1252d9b3dbdcSAl Viro 		d_lookup_done(dentry);
12530b05b183SAnand V. Avati 		if (alias) {
12540b05b183SAnand V. Avati 			dput(dentry);
12550b05b183SAnand V. Avati 			dentry = alias;
12560b05b183SAnand V. Avati 		}
1257d9b3dbdcSAl Viro 		if (IS_ERR(dentry))
1258d9b3dbdcSAl Viro 			return PTR_ERR(dentry);
1259d9b3dbdcSAl Viro 	}
12606314efeeSMiklos Szeredi 	if (fc->readdirplus_auto)
12616314efeeSMiklos Szeredi 		set_bit(FUSE_I_INIT_RDPLUS, &get_fuse_inode(inode)->state);
12620b05b183SAnand V. Avati 	fuse_change_entry_timeout(dentry, o);
12630b05b183SAnand V. Avati 
12640b05b183SAnand V. Avati 	dput(dentry);
1265d9b3dbdcSAl Viro 	return 0;
12660b05b183SAnand V. Avati }
12670b05b183SAnand V. Avati 
12680b05b183SAnand V. Avati static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file,
12698d3af7f3SAl Viro 			     struct dir_context *ctx, u64 attr_version)
12700b05b183SAnand V. Avati {
12710b05b183SAnand V. Avati 	struct fuse_direntplus *direntplus;
12720b05b183SAnand V. Avati 	struct fuse_dirent *dirent;
12730b05b183SAnand V. Avati 	size_t reclen;
12740b05b183SAnand V. Avati 	int over = 0;
12750b05b183SAnand V. Avati 	int ret;
12760b05b183SAnand V. Avati 
12770b05b183SAnand V. Avati 	while (nbytes >= FUSE_NAME_OFFSET_DIRENTPLUS) {
12780b05b183SAnand V. Avati 		direntplus = (struct fuse_direntplus *) buf;
12790b05b183SAnand V. Avati 		dirent = &direntplus->dirent;
12800b05b183SAnand V. Avati 		reclen = FUSE_DIRENTPLUS_SIZE(direntplus);
12810b05b183SAnand V. Avati 
12820b05b183SAnand V. Avati 		if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
12830b05b183SAnand V. Avati 			return -EIO;
12840b05b183SAnand V. Avati 		if (reclen > nbytes)
12850b05b183SAnand V. Avati 			break;
1286efeb9e60SMiklos Szeredi 		if (memchr(dirent->name, '/', dirent->namelen) != NULL)
1287efeb9e60SMiklos Szeredi 			return -EIO;
12880b05b183SAnand V. Avati 
12890b05b183SAnand V. Avati 		if (!over) {
12900b05b183SAnand V. Avati 			/* We fill entries into dstbuf only as much as
12910b05b183SAnand V. Avati 			   it can hold. But we still continue iterating
12920b05b183SAnand V. Avati 			   over remaining entries to link them. If not,
12930b05b183SAnand V. Avati 			   we need to send a FORGET for each of those
12940b05b183SAnand V. Avati 			   which we did not link.
12950b05b183SAnand V. Avati 			*/
12968d3af7f3SAl Viro 			over = !dir_emit(ctx, dirent->name, dirent->namelen,
12978d3af7f3SAl Viro 				       dirent->ino, dirent->type);
12988d3af7f3SAl Viro 			ctx->pos = dirent->off;
12990b05b183SAnand V. Avati 		}
13000b05b183SAnand V. Avati 
13010b05b183SAnand V. Avati 		buf += reclen;
13020b05b183SAnand V. Avati 		nbytes -= reclen;
13030b05b183SAnand V. Avati 
13040b05b183SAnand V. Avati 		ret = fuse_direntplus_link(file, direntplus, attr_version);
13050b05b183SAnand V. Avati 		if (ret)
13060b05b183SAnand V. Avati 			fuse_force_forget(file, direntplus->entry_out.nodeid);
13070b05b183SAnand V. Avati 	}
13080b05b183SAnand V. Avati 
13090b05b183SAnand V. Avati 	return 0;
13100b05b183SAnand V. Avati }
13110b05b183SAnand V. Avati 
13128d3af7f3SAl Viro static int fuse_readdir(struct file *file, struct dir_context *ctx)
1313e5e5558eSMiklos Szeredi {
13144582a4abSFeng Shuo 	int plus, err;
131504730fefSMiklos Szeredi 	size_t nbytes;
131604730fefSMiklos Szeredi 	struct page *page;
1317496ad9aaSAl Viro 	struct inode *inode = file_inode(file);
131804730fefSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1319248d86e8SMiklos Szeredi 	struct fuse_req *req;
13200b05b183SAnand V. Avati 	u64 attr_version = 0;
1321248d86e8SMiklos Szeredi 
1322248d86e8SMiklos Szeredi 	if (is_bad_inode(inode))
1323248d86e8SMiklos Szeredi 		return -EIO;
1324248d86e8SMiklos Szeredi 
1325b111c8c0SMaxim Patlasov 	req = fuse_get_req(fc, 1);
1326ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1327ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
1328e5e5558eSMiklos Szeredi 
132904730fefSMiklos Szeredi 	page = alloc_page(GFP_KERNEL);
133004730fefSMiklos Szeredi 	if (!page) {
133104730fefSMiklos Szeredi 		fuse_put_request(fc, req);
1332e5e5558eSMiklos Szeredi 		return -ENOMEM;
133304730fefSMiklos Szeredi 	}
13344582a4abSFeng Shuo 
13358d3af7f3SAl Viro 	plus = fuse_use_readdirplus(inode, ctx);
1336f4975c67SMiklos Szeredi 	req->out.argpages = 1;
133704730fefSMiklos Szeredi 	req->num_pages = 1;
133804730fefSMiklos Szeredi 	req->pages[0] = page;
133985f40aecSMaxim Patlasov 	req->page_descs[0].length = PAGE_SIZE;
13404582a4abSFeng Shuo 	if (plus) {
13410b05b183SAnand V. Avati 		attr_version = fuse_get_attr_version(fc);
13428d3af7f3SAl Viro 		fuse_read_fill(req, file, ctx->pos, PAGE_SIZE,
13430b05b183SAnand V. Avati 			       FUSE_READDIRPLUS);
13440b05b183SAnand V. Avati 	} else {
13458d3af7f3SAl Viro 		fuse_read_fill(req, file, ctx->pos, PAGE_SIZE,
13460b05b183SAnand V. Avati 			       FUSE_READDIR);
13470b05b183SAnand V. Avati 	}
13485c672ab3SMiklos Szeredi 	fuse_lock_inode(inode);
1349b93f858aSTejun Heo 	fuse_request_send(fc, req);
13505c672ab3SMiklos Szeredi 	fuse_unlock_inode(inode);
1351361b1eb5SMiklos Szeredi 	nbytes = req->out.args[0].size;
135204730fefSMiklos Szeredi 	err = req->out.h.error;
135304730fefSMiklos Szeredi 	fuse_put_request(fc, req);
13540b05b183SAnand V. Avati 	if (!err) {
13554582a4abSFeng Shuo 		if (plus) {
13560b05b183SAnand V. Avati 			err = parse_dirplusfile(page_address(page), nbytes,
13578d3af7f3SAl Viro 						file, ctx,
13580b05b183SAnand V. Avati 						attr_version);
13590b05b183SAnand V. Avati 		} else {
13600b05b183SAnand V. Avati 			err = parse_dirfile(page_address(page), nbytes, file,
13618d3af7f3SAl Viro 					    ctx);
13620b05b183SAnand V. Avati 		}
13630b05b183SAnand V. Avati 	}
1364e5e5558eSMiklos Szeredi 
136504730fefSMiklos Szeredi 	__free_page(page);
1366451418fcSAndrew Gallagher 	fuse_invalidate_atime(inode);
136704730fefSMiklos Szeredi 	return err;
1368e5e5558eSMiklos Szeredi }
1369e5e5558eSMiklos Szeredi 
13706b255391SAl Viro static const char *fuse_get_link(struct dentry *dentry,
1371fceef393SAl Viro 				 struct inode *inode,
1372fceef393SAl Viro 				 struct delayed_call *done)
1373e5e5558eSMiklos Szeredi {
1374e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
13757078187aSMiklos Szeredi 	FUSE_ARGS(args);
1376e5e5558eSMiklos Szeredi 	char *link;
13777078187aSMiklos Szeredi 	ssize_t ret;
1378e5e5558eSMiklos Szeredi 
13796b255391SAl Viro 	if (!dentry)
13806b255391SAl Viro 		return ERR_PTR(-ECHILD);
13816b255391SAl Viro 
1382cd3417c8SAl Viro 	link = kmalloc(PAGE_SIZE, GFP_KERNEL);
13837078187aSMiklos Szeredi 	if (!link)
13847078187aSMiklos Szeredi 		return ERR_PTR(-ENOMEM);
13857078187aSMiklos Szeredi 
13867078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_READLINK;
13877078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(inode);
13887078187aSMiklos Szeredi 	args.out.argvar = 1;
13897078187aSMiklos Szeredi 	args.out.numargs = 1;
13907078187aSMiklos Szeredi 	args.out.args[0].size = PAGE_SIZE - 1;
13917078187aSMiklos Szeredi 	args.out.args[0].value = link;
13927078187aSMiklos Szeredi 	ret = fuse_simple_request(fc, &args);
13937078187aSMiklos Szeredi 	if (ret < 0) {
1394cd3417c8SAl Viro 		kfree(link);
13957078187aSMiklos Szeredi 		link = ERR_PTR(ret);
13967078187aSMiklos Szeredi 	} else {
13977078187aSMiklos Szeredi 		link[ret] = '\0';
1398fceef393SAl Viro 		set_delayed_call(done, kfree_link, link);
13997078187aSMiklos Szeredi 	}
1400451418fcSAndrew Gallagher 	fuse_invalidate_atime(inode);
1401e5e5558eSMiklos Szeredi 	return link;
1402e5e5558eSMiklos Szeredi }
1403e5e5558eSMiklos Szeredi 
1404e5e5558eSMiklos Szeredi static int fuse_dir_open(struct inode *inode, struct file *file)
1405e5e5558eSMiklos Szeredi {
140691fe96b4SMiklos Szeredi 	return fuse_open_common(inode, file, true);
1407e5e5558eSMiklos Szeredi }
1408e5e5558eSMiklos Szeredi 
1409e5e5558eSMiklos Szeredi static int fuse_dir_release(struct inode *inode, struct file *file)
1410e5e5558eSMiklos Szeredi {
14118b0797a4SMiklos Szeredi 	fuse_release_common(file, FUSE_RELEASEDIR);
14128b0797a4SMiklos Szeredi 
14138b0797a4SMiklos Szeredi 	return 0;
1414e5e5558eSMiklos Szeredi }
1415e5e5558eSMiklos Szeredi 
141602c24a82SJosef Bacik static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end,
141702c24a82SJosef Bacik 			  int datasync)
141882547981SMiklos Szeredi {
141902c24a82SJosef Bacik 	return fuse_fsync_common(file, start, end, datasync, 1);
142082547981SMiklos Szeredi }
142182547981SMiklos Szeredi 
1422b18da0c5SMiklos Szeredi static long fuse_dir_ioctl(struct file *file, unsigned int cmd,
1423b18da0c5SMiklos Szeredi 			    unsigned long arg)
1424b18da0c5SMiklos Szeredi {
1425b18da0c5SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1426b18da0c5SMiklos Szeredi 
1427b18da0c5SMiklos Szeredi 	/* FUSE_IOCTL_DIR only supported for API version >= 7.18 */
1428b18da0c5SMiklos Szeredi 	if (fc->minor < 18)
1429b18da0c5SMiklos Szeredi 		return -ENOTTY;
1430b18da0c5SMiklos Szeredi 
1431b18da0c5SMiklos Szeredi 	return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR);
1432b18da0c5SMiklos Szeredi }
1433b18da0c5SMiklos Szeredi 
1434b18da0c5SMiklos Szeredi static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd,
1435b18da0c5SMiklos Szeredi 				   unsigned long arg)
1436b18da0c5SMiklos Szeredi {
1437b18da0c5SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1438b18da0c5SMiklos Szeredi 
1439b18da0c5SMiklos Szeredi 	if (fc->minor < 18)
1440b18da0c5SMiklos Szeredi 		return -ENOTTY;
1441b18da0c5SMiklos Szeredi 
1442b18da0c5SMiklos Szeredi 	return fuse_ioctl_common(file, cmd, arg,
1443b18da0c5SMiklos Szeredi 				 FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR);
1444b18da0c5SMiklos Szeredi }
1445b18da0c5SMiklos Szeredi 
1446b0aa7606SMaxim Patlasov static bool update_mtime(unsigned ivalid, bool trust_local_mtime)
144717637cbaSMiklos Szeredi {
144817637cbaSMiklos Szeredi 	/* Always update if mtime is explicitly set  */
144917637cbaSMiklos Szeredi 	if (ivalid & ATTR_MTIME_SET)
145017637cbaSMiklos Szeredi 		return true;
145117637cbaSMiklos Szeredi 
1452b0aa7606SMaxim Patlasov 	/* Or if kernel i_mtime is the official one */
1453b0aa7606SMaxim Patlasov 	if (trust_local_mtime)
1454b0aa7606SMaxim Patlasov 		return true;
1455b0aa7606SMaxim Patlasov 
145617637cbaSMiklos Szeredi 	/* If it's an open(O_TRUNC) or an ftruncate(), don't update */
145717637cbaSMiklos Szeredi 	if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
145817637cbaSMiklos Szeredi 		return false;
145917637cbaSMiklos Szeredi 
146017637cbaSMiklos Szeredi 	/* In all other cases update */
146117637cbaSMiklos Szeredi 	return true;
146217637cbaSMiklos Szeredi }
146317637cbaSMiklos Szeredi 
1464b0aa7606SMaxim Patlasov static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg,
14653ad22c62SMaxim Patlasov 			   bool trust_local_cmtime)
14669e6268dbSMiklos Szeredi {
14679e6268dbSMiklos Szeredi 	unsigned ivalid = iattr->ia_valid;
14689e6268dbSMiklos Szeredi 
14699e6268dbSMiklos Szeredi 	if (ivalid & ATTR_MODE)
1470befc649cSMiklos Szeredi 		arg->valid |= FATTR_MODE,   arg->mode = iattr->ia_mode;
14719e6268dbSMiklos Szeredi 	if (ivalid & ATTR_UID)
1472499dcf20SEric W. Biederman 		arg->valid |= FATTR_UID,    arg->uid = from_kuid(&init_user_ns, iattr->ia_uid);
14739e6268dbSMiklos Szeredi 	if (ivalid & ATTR_GID)
1474499dcf20SEric W. Biederman 		arg->valid |= FATTR_GID,    arg->gid = from_kgid(&init_user_ns, iattr->ia_gid);
14759e6268dbSMiklos Szeredi 	if (ivalid & ATTR_SIZE)
1476befc649cSMiklos Szeredi 		arg->valid |= FATTR_SIZE,   arg->size = iattr->ia_size;
147717637cbaSMiklos Szeredi 	if (ivalid & ATTR_ATIME) {
147817637cbaSMiklos Szeredi 		arg->valid |= FATTR_ATIME;
1479befc649cSMiklos Szeredi 		arg->atime = iattr->ia_atime.tv_sec;
148017637cbaSMiklos Szeredi 		arg->atimensec = iattr->ia_atime.tv_nsec;
148117637cbaSMiklos Szeredi 		if (!(ivalid & ATTR_ATIME_SET))
148217637cbaSMiklos Szeredi 			arg->valid |= FATTR_ATIME_NOW;
148317637cbaSMiklos Szeredi 	}
14843ad22c62SMaxim Patlasov 	if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, trust_local_cmtime)) {
148517637cbaSMiklos Szeredi 		arg->valid |= FATTR_MTIME;
1486befc649cSMiklos Szeredi 		arg->mtime = iattr->ia_mtime.tv_sec;
148717637cbaSMiklos Szeredi 		arg->mtimensec = iattr->ia_mtime.tv_nsec;
14883ad22c62SMaxim Patlasov 		if (!(ivalid & ATTR_MTIME_SET) && !trust_local_cmtime)
148917637cbaSMiklos Szeredi 			arg->valid |= FATTR_MTIME_NOW;
14909e6268dbSMiklos Szeredi 	}
14913ad22c62SMaxim Patlasov 	if ((ivalid & ATTR_CTIME) && trust_local_cmtime) {
14923ad22c62SMaxim Patlasov 		arg->valid |= FATTR_CTIME;
14933ad22c62SMaxim Patlasov 		arg->ctime = iattr->ia_ctime.tv_sec;
14943ad22c62SMaxim Patlasov 		arg->ctimensec = iattr->ia_ctime.tv_nsec;
14953ad22c62SMaxim Patlasov 	}
14969e6268dbSMiklos Szeredi }
14979e6268dbSMiklos Szeredi 
14986f9f1180SMiklos Szeredi /*
14993be5a52bSMiklos Szeredi  * Prevent concurrent writepages on inode
15003be5a52bSMiklos Szeredi  *
15013be5a52bSMiklos Szeredi  * This is done by adding a negative bias to the inode write counter
15023be5a52bSMiklos Szeredi  * and waiting for all pending writes to finish.
15033be5a52bSMiklos Szeredi  */
15043be5a52bSMiklos Szeredi void fuse_set_nowrite(struct inode *inode)
15053be5a52bSMiklos Szeredi {
15063be5a52bSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
15073be5a52bSMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
15083be5a52bSMiklos Szeredi 
15095955102cSAl Viro 	BUG_ON(!inode_is_locked(inode));
15103be5a52bSMiklos Szeredi 
15113be5a52bSMiklos Szeredi 	spin_lock(&fc->lock);
15123be5a52bSMiklos Szeredi 	BUG_ON(fi->writectr < 0);
15133be5a52bSMiklos Szeredi 	fi->writectr += FUSE_NOWRITE;
15143be5a52bSMiklos Szeredi 	spin_unlock(&fc->lock);
15153be5a52bSMiklos Szeredi 	wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE);
15163be5a52bSMiklos Szeredi }
15173be5a52bSMiklos Szeredi 
15183be5a52bSMiklos Szeredi /*
15193be5a52bSMiklos Szeredi  * Allow writepages on inode
15203be5a52bSMiklos Szeredi  *
15213be5a52bSMiklos Szeredi  * Remove the bias from the writecounter and send any queued
15223be5a52bSMiklos Szeredi  * writepages.
15233be5a52bSMiklos Szeredi  */
15243be5a52bSMiklos Szeredi static void __fuse_release_nowrite(struct inode *inode)
15253be5a52bSMiklos Szeredi {
15263be5a52bSMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
15273be5a52bSMiklos Szeredi 
15283be5a52bSMiklos Szeredi 	BUG_ON(fi->writectr != FUSE_NOWRITE);
15293be5a52bSMiklos Szeredi 	fi->writectr = 0;
15303be5a52bSMiklos Szeredi 	fuse_flush_writepages(inode);
15313be5a52bSMiklos Szeredi }
15323be5a52bSMiklos Szeredi 
15333be5a52bSMiklos Szeredi void fuse_release_nowrite(struct inode *inode)
15343be5a52bSMiklos Szeredi {
15353be5a52bSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
15363be5a52bSMiklos Szeredi 
15373be5a52bSMiklos Szeredi 	spin_lock(&fc->lock);
15383be5a52bSMiklos Szeredi 	__fuse_release_nowrite(inode);
15393be5a52bSMiklos Szeredi 	spin_unlock(&fc->lock);
15403be5a52bSMiklos Szeredi }
15413be5a52bSMiklos Szeredi 
15427078187aSMiklos Szeredi static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_args *args,
1543b0aa7606SMaxim Patlasov 			      struct inode *inode,
1544b0aa7606SMaxim Patlasov 			      struct fuse_setattr_in *inarg_p,
1545b0aa7606SMaxim Patlasov 			      struct fuse_attr_out *outarg_p)
1546b0aa7606SMaxim Patlasov {
15477078187aSMiklos Szeredi 	args->in.h.opcode = FUSE_SETATTR;
15487078187aSMiklos Szeredi 	args->in.h.nodeid = get_node_id(inode);
15497078187aSMiklos Szeredi 	args->in.numargs = 1;
15507078187aSMiklos Szeredi 	args->in.args[0].size = sizeof(*inarg_p);
15517078187aSMiklos Szeredi 	args->in.args[0].value = inarg_p;
15527078187aSMiklos Szeredi 	args->out.numargs = 1;
15537078187aSMiklos Szeredi 	args->out.args[0].size = sizeof(*outarg_p);
15547078187aSMiklos Szeredi 	args->out.args[0].value = outarg_p;
1555b0aa7606SMaxim Patlasov }
1556b0aa7606SMaxim Patlasov 
1557b0aa7606SMaxim Patlasov /*
1558b0aa7606SMaxim Patlasov  * Flush inode->i_mtime to the server
1559b0aa7606SMaxim Patlasov  */
1560ab9e13f7SMaxim Patlasov int fuse_flush_times(struct inode *inode, struct fuse_file *ff)
1561b0aa7606SMaxim Patlasov {
1562b0aa7606SMaxim Patlasov 	struct fuse_conn *fc = get_fuse_conn(inode);
15637078187aSMiklos Szeredi 	FUSE_ARGS(args);
1564b0aa7606SMaxim Patlasov 	struct fuse_setattr_in inarg;
1565b0aa7606SMaxim Patlasov 	struct fuse_attr_out outarg;
1566b0aa7606SMaxim Patlasov 
1567b0aa7606SMaxim Patlasov 	memset(&inarg, 0, sizeof(inarg));
1568b0aa7606SMaxim Patlasov 	memset(&outarg, 0, sizeof(outarg));
1569b0aa7606SMaxim Patlasov 
1570ab9e13f7SMaxim Patlasov 	inarg.valid = FATTR_MTIME;
1571b0aa7606SMaxim Patlasov 	inarg.mtime = inode->i_mtime.tv_sec;
1572b0aa7606SMaxim Patlasov 	inarg.mtimensec = inode->i_mtime.tv_nsec;
1573ab9e13f7SMaxim Patlasov 	if (fc->minor >= 23) {
1574ab9e13f7SMaxim Patlasov 		inarg.valid |= FATTR_CTIME;
1575ab9e13f7SMaxim Patlasov 		inarg.ctime = inode->i_ctime.tv_sec;
1576ab9e13f7SMaxim Patlasov 		inarg.ctimensec = inode->i_ctime.tv_nsec;
1577ab9e13f7SMaxim Patlasov 	}
15781e18bda8SMiklos Szeredi 	if (ff) {
15791e18bda8SMiklos Szeredi 		inarg.valid |= FATTR_FH;
15801e18bda8SMiklos Szeredi 		inarg.fh = ff->fh;
15811e18bda8SMiklos Szeredi 	}
15827078187aSMiklos Szeredi 	fuse_setattr_fill(fc, &args, inode, &inarg, &outarg);
1583b0aa7606SMaxim Patlasov 
15847078187aSMiklos Szeredi 	return fuse_simple_request(fc, &args);
1585b0aa7606SMaxim Patlasov }
1586b0aa7606SMaxim Patlasov 
15873be5a52bSMiklos Szeredi /*
15886f9f1180SMiklos Szeredi  * Set attributes, and at the same time refresh them.
15896f9f1180SMiklos Szeredi  *
15906f9f1180SMiklos Szeredi  * Truncation is slightly complicated, because the 'truncate' request
15916f9f1180SMiklos Szeredi  * may fail, in which case we don't want to touch the mapping.
15929ffbb916SMiklos Szeredi  * vmtruncate() doesn't allow for this case, so do the rlimit checking
15939ffbb916SMiklos Szeredi  * and the actual truncation by hand.
15946f9f1180SMiklos Szeredi  */
1595efb9fa9eSMaxim Patlasov int fuse_do_setattr(struct inode *inode, struct iattr *attr,
159649d4914fSMiklos Szeredi 		    struct file *file)
15979e6268dbSMiklos Szeredi {
15989e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
159906a7c3c2SMaxim Patlasov 	struct fuse_inode *fi = get_fuse_inode(inode);
16007078187aSMiklos Szeredi 	FUSE_ARGS(args);
16019e6268dbSMiklos Szeredi 	struct fuse_setattr_in inarg;
16029e6268dbSMiklos Szeredi 	struct fuse_attr_out outarg;
16033be5a52bSMiklos Szeredi 	bool is_truncate = false;
16048373200bSPavel Emelyanov 	bool is_wb = fc->writeback_cache;
16053be5a52bSMiklos Szeredi 	loff_t oldsize;
16069e6268dbSMiklos Szeredi 	int err;
16073ad22c62SMaxim Patlasov 	bool trust_local_cmtime = is_wb && S_ISREG(inode->i_mode);
16089e6268dbSMiklos Szeredi 
1609db78b877SChristoph Hellwig 	if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS))
1610db78b877SChristoph Hellwig 		attr->ia_valid |= ATTR_FORCE;
1611db78b877SChristoph Hellwig 
16121e9a4ed9SMiklos Szeredi 	err = inode_change_ok(inode, attr);
16131e9a4ed9SMiklos Szeredi 	if (err)
16141e9a4ed9SMiklos Szeredi 		return err;
16151e9a4ed9SMiklos Szeredi 
16168d56adddSMiklos Szeredi 	if (attr->ia_valid & ATTR_OPEN) {
16178d56adddSMiklos Szeredi 		if (fc->atomic_o_trunc)
16186ff958edSMiklos Szeredi 			return 0;
16198d56adddSMiklos Szeredi 		file = NULL;
16208d56adddSMiklos Szeredi 	}
16216ff958edSMiklos Szeredi 
16222c27c65eSChristoph Hellwig 	if (attr->ia_valid & ATTR_SIZE)
16233be5a52bSMiklos Szeredi 		is_truncate = true;
16249e6268dbSMiklos Szeredi 
162506a7c3c2SMaxim Patlasov 	if (is_truncate) {
16263be5a52bSMiklos Szeredi 		fuse_set_nowrite(inode);
162706a7c3c2SMaxim Patlasov 		set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
16283ad22c62SMaxim Patlasov 		if (trust_local_cmtime && attr->ia_size != inode->i_size)
16293ad22c62SMaxim Patlasov 			attr->ia_valid |= ATTR_MTIME | ATTR_CTIME;
163006a7c3c2SMaxim Patlasov 	}
16313be5a52bSMiklos Szeredi 
16329e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
16330e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
16343ad22c62SMaxim Patlasov 	iattr_to_fattr(attr, &inarg, trust_local_cmtime);
163549d4914fSMiklos Szeredi 	if (file) {
163649d4914fSMiklos Szeredi 		struct fuse_file *ff = file->private_data;
163749d4914fSMiklos Szeredi 		inarg.valid |= FATTR_FH;
163849d4914fSMiklos Szeredi 		inarg.fh = ff->fh;
163949d4914fSMiklos Szeredi 	}
1640f3332114SMiklos Szeredi 	if (attr->ia_valid & ATTR_SIZE) {
1641f3332114SMiklos Szeredi 		/* For mandatory locking in truncate */
1642f3332114SMiklos Szeredi 		inarg.valid |= FATTR_LOCKOWNER;
1643f3332114SMiklos Szeredi 		inarg.lock_owner = fuse_lock_owner_id(fc, current->files);
1644f3332114SMiklos Szeredi 	}
16457078187aSMiklos Szeredi 	fuse_setattr_fill(fc, &args, inode, &inarg, &outarg);
16467078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
1647e00d2c2dSMiklos Szeredi 	if (err) {
1648e00d2c2dSMiklos Szeredi 		if (err == -EINTR)
1649e00d2c2dSMiklos Szeredi 			fuse_invalidate_attr(inode);
16503be5a52bSMiklos Szeredi 		goto error;
1651e00d2c2dSMiklos Szeredi 	}
1652e00d2c2dSMiklos Szeredi 
16539e6268dbSMiklos Szeredi 	if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
16549e6268dbSMiklos Szeredi 		make_bad_inode(inode);
16553be5a52bSMiklos Szeredi 		err = -EIO;
16563be5a52bSMiklos Szeredi 		goto error;
16579e6268dbSMiklos Szeredi 	}
16589e6268dbSMiklos Szeredi 
16593be5a52bSMiklos Szeredi 	spin_lock(&fc->lock);
1660b0aa7606SMaxim Patlasov 	/* the kernel maintains i_mtime locally */
16613ad22c62SMaxim Patlasov 	if (trust_local_cmtime) {
16623ad22c62SMaxim Patlasov 		if (attr->ia_valid & ATTR_MTIME)
1663b0aa7606SMaxim Patlasov 			inode->i_mtime = attr->ia_mtime;
16643ad22c62SMaxim Patlasov 		if (attr->ia_valid & ATTR_CTIME)
16653ad22c62SMaxim Patlasov 			inode->i_ctime = attr->ia_ctime;
16661e18bda8SMiklos Szeredi 		/* FIXME: clear I_DIRTY_SYNC? */
1667b0aa7606SMaxim Patlasov 	}
1668b0aa7606SMaxim Patlasov 
16693be5a52bSMiklos Szeredi 	fuse_change_attributes_common(inode, &outarg.attr,
16703be5a52bSMiklos Szeredi 				      attr_timeout(&outarg));
16713be5a52bSMiklos Szeredi 	oldsize = inode->i_size;
16728373200bSPavel Emelyanov 	/* see the comment in fuse_change_attributes() */
16738373200bSPavel Emelyanov 	if (!is_wb || is_truncate || !S_ISREG(inode->i_mode))
16743be5a52bSMiklos Szeredi 		i_size_write(inode, outarg.attr.size);
16753be5a52bSMiklos Szeredi 
16763be5a52bSMiklos Szeredi 	if (is_truncate) {
16773be5a52bSMiklos Szeredi 		/* NOTE: this may release/reacquire fc->lock */
16783be5a52bSMiklos Szeredi 		__fuse_release_nowrite(inode);
16793be5a52bSMiklos Szeredi 	}
16803be5a52bSMiklos Szeredi 	spin_unlock(&fc->lock);
16813be5a52bSMiklos Szeredi 
16823be5a52bSMiklos Szeredi 	/*
16833be5a52bSMiklos Szeredi 	 * Only call invalidate_inode_pages2() after removing
16843be5a52bSMiklos Szeredi 	 * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock.
16853be5a52bSMiklos Szeredi 	 */
16868373200bSPavel Emelyanov 	if ((is_truncate || !is_wb) &&
16878373200bSPavel Emelyanov 	    S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
16887caef267SKirill A. Shutemov 		truncate_pagecache(inode, outarg.attr.size);
16893be5a52bSMiklos Szeredi 		invalidate_inode_pages2(inode->i_mapping);
16903be5a52bSMiklos Szeredi 	}
16913be5a52bSMiklos Szeredi 
169206a7c3c2SMaxim Patlasov 	clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
1693e00d2c2dSMiklos Szeredi 	return 0;
16943be5a52bSMiklos Szeredi 
16953be5a52bSMiklos Szeredi error:
16963be5a52bSMiklos Szeredi 	if (is_truncate)
16973be5a52bSMiklos Szeredi 		fuse_release_nowrite(inode);
16983be5a52bSMiklos Szeredi 
169906a7c3c2SMaxim Patlasov 	clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
17003be5a52bSMiklos Szeredi 	return err;
17019e6268dbSMiklos Szeredi }
17029e6268dbSMiklos Szeredi 
170349d4914fSMiklos Szeredi static int fuse_setattr(struct dentry *entry, struct iattr *attr)
170449d4914fSMiklos Szeredi {
17052b0143b5SDavid Howells 	struct inode *inode = d_inode(entry);
17065e940c1dSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1707a09f99edSMiklos Szeredi 	struct file *file = (attr->ia_valid & ATTR_FILE) ? attr->ia_file : NULL;
17085e2b8828SMiklos Szeredi 	int ret;
1709efb9fa9eSMaxim Patlasov 
1710efb9fa9eSMaxim Patlasov 	if (!fuse_allow_current_process(get_fuse_conn(inode)))
1711efb9fa9eSMaxim Patlasov 		return -EACCES;
1712efb9fa9eSMaxim Patlasov 
1713a09f99edSMiklos Szeredi 	if (attr->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) {
1714a09f99edSMiklos Szeredi 		attr->ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID |
1715a09f99edSMiklos Szeredi 				    ATTR_MODE);
17165e940c1dSMiklos Szeredi 
1717a09f99edSMiklos Szeredi 		/*
17185e940c1dSMiklos Szeredi 		 * The only sane way to reliably kill suid/sgid is to do it in
17195e940c1dSMiklos Szeredi 		 * the userspace filesystem
17205e940c1dSMiklos Szeredi 		 *
17215e940c1dSMiklos Szeredi 		 * This should be done on write(), truncate() and chown().
17225e940c1dSMiklos Szeredi 		 */
17235e940c1dSMiklos Szeredi 		if (!fc->handle_killpriv) {
17245e940c1dSMiklos Szeredi 			int kill;
17255e940c1dSMiklos Szeredi 
17265e940c1dSMiklos Szeredi 			/*
17275e940c1dSMiklos Szeredi 			 * ia_mode calculation may have used stale i_mode.
17285e940c1dSMiklos Szeredi 			 * Refresh and recalculate.
1729a09f99edSMiklos Szeredi 			 */
1730a09f99edSMiklos Szeredi 			ret = fuse_do_getattr(inode, NULL, file);
1731a09f99edSMiklos Szeredi 			if (ret)
1732a09f99edSMiklos Szeredi 				return ret;
1733a09f99edSMiklos Szeredi 
1734a09f99edSMiklos Szeredi 			attr->ia_mode = inode->i_mode;
1735a09f99edSMiklos Szeredi 			kill = should_remove_suid(entry);
1736a09f99edSMiklos Szeredi 			if (kill & ATTR_KILL_SUID) {
1737a09f99edSMiklos Szeredi 				attr->ia_valid |= ATTR_MODE;
1738a09f99edSMiklos Szeredi 				attr->ia_mode &= ~S_ISUID;
1739a09f99edSMiklos Szeredi 			}
1740a09f99edSMiklos Szeredi 			if (kill & ATTR_KILL_SGID) {
1741a09f99edSMiklos Szeredi 				attr->ia_valid |= ATTR_MODE;
1742a09f99edSMiklos Szeredi 				attr->ia_mode &= ~S_ISGID;
1743a09f99edSMiklos Szeredi 			}
1744a09f99edSMiklos Szeredi 		}
17455e940c1dSMiklos Szeredi 	}
1746a09f99edSMiklos Szeredi 	if (!attr->ia_valid)
1747a09f99edSMiklos Szeredi 		return 0;
1748a09f99edSMiklos Szeredi 
1749a09f99edSMiklos Szeredi 	ret = fuse_do_setattr(inode, attr, file);
17505e2b8828SMiklos Szeredi 	if (!ret) {
17515e2b8828SMiklos Szeredi 		/* Directory mode changed, may need to revalidate access */
17525e2b8828SMiklos Szeredi 		if (d_is_dir(entry) && (attr->ia_valid & ATTR_MODE))
17535e2b8828SMiklos Szeredi 			fuse_invalidate_entry_cache(entry);
17545e2b8828SMiklos Szeredi 	}
17555e2b8828SMiklos Szeredi 	return ret;
175649d4914fSMiklos Szeredi }
175749d4914fSMiklos Szeredi 
1758e5e5558eSMiklos Szeredi static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
1759e5e5558eSMiklos Szeredi 			struct kstat *stat)
1760e5e5558eSMiklos Szeredi {
17612b0143b5SDavid Howells 	struct inode *inode = d_inode(entry);
1762244f6385SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1763244f6385SMiklos Szeredi 
1764c2132c1bSAnatol Pomozov 	if (!fuse_allow_current_process(fc))
1765244f6385SMiklos Szeredi 		return -EACCES;
1766244f6385SMiklos Szeredi 
1767bcb4be80SMiklos Szeredi 	return fuse_update_attributes(inode, stat, NULL, NULL);
1768e5e5558eSMiklos Szeredi }
1769e5e5558eSMiklos Szeredi 
1770754661f1SArjan van de Ven static const struct inode_operations fuse_dir_inode_operations = {
1771e5e5558eSMiklos Szeredi 	.lookup		= fuse_lookup,
17729e6268dbSMiklos Szeredi 	.mkdir		= fuse_mkdir,
17739e6268dbSMiklos Szeredi 	.symlink	= fuse_symlink,
17749e6268dbSMiklos Szeredi 	.unlink		= fuse_unlink,
17759e6268dbSMiklos Szeredi 	.rmdir		= fuse_rmdir,
17761560c974SMiklos Szeredi 	.rename2	= fuse_rename2,
17779e6268dbSMiklos Szeredi 	.link		= fuse_link,
17789e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
17799e6268dbSMiklos Szeredi 	.create		= fuse_create,
1780c8ccbe03SMiklos Szeredi 	.atomic_open	= fuse_atomic_open,
17819e6268dbSMiklos Szeredi 	.mknod		= fuse_mknod,
1782e5e5558eSMiklos Szeredi 	.permission	= fuse_permission,
1783e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
1784*703c7362SSeth Forshee 	.setxattr	= generic_setxattr,
1785*703c7362SSeth Forshee 	.getxattr	= generic_getxattr,
178692a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
1787*703c7362SSeth Forshee 	.removexattr	= generic_removexattr,
1788e5e5558eSMiklos Szeredi };
1789e5e5558eSMiklos Szeredi 
17904b6f5d20SArjan van de Ven static const struct file_operations fuse_dir_operations = {
1791b6aeadedSMiklos Szeredi 	.llseek		= generic_file_llseek,
1792e5e5558eSMiklos Szeredi 	.read		= generic_read_dir,
1793d9b3dbdcSAl Viro 	.iterate_shared	= fuse_readdir,
1794e5e5558eSMiklos Szeredi 	.open		= fuse_dir_open,
1795e5e5558eSMiklos Szeredi 	.release	= fuse_dir_release,
179682547981SMiklos Szeredi 	.fsync		= fuse_dir_fsync,
1797b18da0c5SMiklos Szeredi 	.unlocked_ioctl	= fuse_dir_ioctl,
1798b18da0c5SMiklos Szeredi 	.compat_ioctl	= fuse_dir_compat_ioctl,
1799e5e5558eSMiklos Szeredi };
1800e5e5558eSMiklos Szeredi 
1801754661f1SArjan van de Ven static const struct inode_operations fuse_common_inode_operations = {
18029e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
1803e5e5558eSMiklos Szeredi 	.permission	= fuse_permission,
1804e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
1805*703c7362SSeth Forshee 	.setxattr	= generic_setxattr,
1806*703c7362SSeth Forshee 	.getxattr	= generic_getxattr,
180792a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
1808*703c7362SSeth Forshee 	.removexattr	= generic_removexattr,
1809e5e5558eSMiklos Szeredi };
1810e5e5558eSMiklos Szeredi 
1811754661f1SArjan van de Ven static const struct inode_operations fuse_symlink_inode_operations = {
18129e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
18136b255391SAl Viro 	.get_link	= fuse_get_link,
1814e5e5558eSMiklos Szeredi 	.readlink	= generic_readlink,
1815e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
1816*703c7362SSeth Forshee 	.setxattr	= generic_setxattr,
1817*703c7362SSeth Forshee 	.getxattr	= generic_getxattr,
181892a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
1819*703c7362SSeth Forshee 	.removexattr	= generic_removexattr,
1820e5e5558eSMiklos Szeredi };
1821e5e5558eSMiklos Szeredi 
1822e5e5558eSMiklos Szeredi void fuse_init_common(struct inode *inode)
1823e5e5558eSMiklos Szeredi {
1824e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_common_inode_operations;
1825e5e5558eSMiklos Szeredi }
1826e5e5558eSMiklos Szeredi 
1827e5e5558eSMiklos Szeredi void fuse_init_dir(struct inode *inode)
1828e5e5558eSMiklos Szeredi {
1829e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_dir_inode_operations;
1830e5e5558eSMiklos Szeredi 	inode->i_fop = &fuse_dir_operations;
1831e5e5558eSMiklos Szeredi }
1832e5e5558eSMiklos Szeredi 
1833e5e5558eSMiklos Szeredi void fuse_init_symlink(struct inode *inode)
1834e5e5558eSMiklos Szeredi {
1835e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_symlink_inode_operations;
1836e5e5558eSMiklos Szeredi }
1837