xref: /openbmc/linux/fs/fuse/dir.c (revision 62490330769c1ce5dcba3f1f3e8f4005e9b797e6)
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>
16e5e5558eSMiklos Szeredi 
178d3af7f3SAl Viro static bool fuse_use_readdirplus(struct inode *dir, struct dir_context *ctx)
184582a4abSFeng Shuo {
194582a4abSFeng Shuo 	struct fuse_conn *fc = get_fuse_conn(dir);
204582a4abSFeng Shuo 	struct fuse_inode *fi = get_fuse_inode(dir);
214582a4abSFeng Shuo 
224582a4abSFeng Shuo 	if (!fc->do_readdirplus)
234582a4abSFeng Shuo 		return false;
24634734b6SEric Wong 	if (!fc->readdirplus_auto)
25634734b6SEric Wong 		return true;
264582a4abSFeng Shuo 	if (test_and_clear_bit(FUSE_I_ADVISE_RDPLUS, &fi->state))
274582a4abSFeng Shuo 		return true;
288d3af7f3SAl Viro 	if (ctx->pos == 0)
294582a4abSFeng Shuo 		return true;
304582a4abSFeng Shuo 	return false;
314582a4abSFeng Shuo }
324582a4abSFeng Shuo 
334582a4abSFeng Shuo static void fuse_advise_use_readdirplus(struct inode *dir)
344582a4abSFeng Shuo {
354582a4abSFeng Shuo 	struct fuse_inode *fi = get_fuse_inode(dir);
364582a4abSFeng Shuo 
374582a4abSFeng Shuo 	set_bit(FUSE_I_ADVISE_RDPLUS, &fi->state);
384582a4abSFeng Shuo }
394582a4abSFeng Shuo 
400a0898cfSMiklos Szeredi #if BITS_PER_LONG >= 64
410a0898cfSMiklos Szeredi static inline void fuse_dentry_settime(struct dentry *entry, u64 time)
420a0898cfSMiklos Szeredi {
430a0898cfSMiklos Szeredi 	entry->d_time = time;
440a0898cfSMiklos Szeredi }
450a0898cfSMiklos Szeredi 
460a0898cfSMiklos Szeredi static inline u64 fuse_dentry_time(struct dentry *entry)
470a0898cfSMiklos Szeredi {
480a0898cfSMiklos Szeredi 	return entry->d_time;
490a0898cfSMiklos Szeredi }
500a0898cfSMiklos Szeredi #else
510a0898cfSMiklos Szeredi /*
520a0898cfSMiklos Szeredi  * On 32 bit archs store the high 32 bits of time in d_fsdata
530a0898cfSMiklos Szeredi  */
540a0898cfSMiklos Szeredi static void fuse_dentry_settime(struct dentry *entry, u64 time)
550a0898cfSMiklos Szeredi {
560a0898cfSMiklos Szeredi 	entry->d_time = time;
570a0898cfSMiklos Szeredi 	entry->d_fsdata = (void *) (unsigned long) (time >> 32);
580a0898cfSMiklos Szeredi }
590a0898cfSMiklos Szeredi 
600a0898cfSMiklos Szeredi static u64 fuse_dentry_time(struct dentry *entry)
610a0898cfSMiklos Szeredi {
620a0898cfSMiklos Szeredi 	return (u64) entry->d_time +
630a0898cfSMiklos Szeredi 		((u64) (unsigned long) entry->d_fsdata << 32);
640a0898cfSMiklos Szeredi }
650a0898cfSMiklos Szeredi #endif
660a0898cfSMiklos Szeredi 
676f9f1180SMiklos Szeredi /*
686f9f1180SMiklos Szeredi  * FUSE caches dentries and attributes with separate timeout.  The
696f9f1180SMiklos Szeredi  * time in jiffies until the dentry/attributes are valid is stored in
706f9f1180SMiklos Szeredi  * dentry->d_time and fuse_inode->i_time respectively.
716f9f1180SMiklos Szeredi  */
726f9f1180SMiklos Szeredi 
736f9f1180SMiklos Szeredi /*
746f9f1180SMiklos Szeredi  * Calculate the time in jiffies until a dentry/attributes are valid
756f9f1180SMiklos Szeredi  */
760a0898cfSMiklos Szeredi static u64 time_to_jiffies(unsigned long sec, unsigned long nsec)
77e5e5558eSMiklos Szeredi {
78685d16ddSMiklos Szeredi 	if (sec || nsec) {
79e5e5558eSMiklos Szeredi 		struct timespec ts = {sec, nsec};
800a0898cfSMiklos Szeredi 		return get_jiffies_64() + timespec_to_jiffies(&ts);
81685d16ddSMiklos Szeredi 	} else
820a0898cfSMiklos Szeredi 		return 0;
83e5e5558eSMiklos Szeredi }
84e5e5558eSMiklos Szeredi 
856f9f1180SMiklos Szeredi /*
866f9f1180SMiklos Szeredi  * Set dentry and possibly attribute timeouts from the lookup/mk*
876f9f1180SMiklos Szeredi  * replies
886f9f1180SMiklos Szeredi  */
891fb69e78SMiklos Szeredi static void fuse_change_entry_timeout(struct dentry *entry,
901fb69e78SMiklos Szeredi 				      struct fuse_entry_out *o)
910aa7c699SMiklos Szeredi {
920a0898cfSMiklos Szeredi 	fuse_dentry_settime(entry,
930a0898cfSMiklos Szeredi 		time_to_jiffies(o->entry_valid, o->entry_valid_nsec));
941fb69e78SMiklos Szeredi }
951fb69e78SMiklos Szeredi 
961fb69e78SMiklos Szeredi static u64 attr_timeout(struct fuse_attr_out *o)
971fb69e78SMiklos Szeredi {
981fb69e78SMiklos Szeredi 	return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
991fb69e78SMiklos Szeredi }
1001fb69e78SMiklos Szeredi 
1011fb69e78SMiklos Szeredi static u64 entry_attr_timeout(struct fuse_entry_out *o)
1021fb69e78SMiklos Szeredi {
1031fb69e78SMiklos Szeredi 	return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
1048cbdf1e6SMiklos Szeredi }
1058cbdf1e6SMiklos Szeredi 
1066f9f1180SMiklos Szeredi /*
1076f9f1180SMiklos Szeredi  * Mark the attributes as stale, so that at the next call to
1086f9f1180SMiklos Szeredi  * ->getattr() they will be fetched from userspace
1096f9f1180SMiklos Szeredi  */
1108cbdf1e6SMiklos Szeredi void fuse_invalidate_attr(struct inode *inode)
1118cbdf1e6SMiklos Szeredi {
1120a0898cfSMiklos Szeredi 	get_fuse_inode(inode)->i_time = 0;
1138cbdf1e6SMiklos Szeredi }
1148cbdf1e6SMiklos Szeredi 
115451418fcSAndrew Gallagher /**
116451418fcSAndrew Gallagher  * Mark the attributes as stale due to an atime change.  Avoid the invalidate if
117451418fcSAndrew Gallagher  * atime is not used.
118451418fcSAndrew Gallagher  */
119451418fcSAndrew Gallagher void fuse_invalidate_atime(struct inode *inode)
120451418fcSAndrew Gallagher {
121451418fcSAndrew Gallagher 	if (!IS_RDONLY(inode))
122451418fcSAndrew Gallagher 		fuse_invalidate_attr(inode);
123451418fcSAndrew Gallagher }
124451418fcSAndrew Gallagher 
1256f9f1180SMiklos Szeredi /*
1266f9f1180SMiklos Szeredi  * Just mark the entry as stale, so that a next attempt to look it up
1276f9f1180SMiklos Szeredi  * will result in a new lookup call to userspace
1286f9f1180SMiklos Szeredi  *
1296f9f1180SMiklos Szeredi  * This is called when a dentry is about to become negative and the
1306f9f1180SMiklos Szeredi  * timeout is unknown (unlink, rmdir, rename and in some cases
1316f9f1180SMiklos Szeredi  * lookup)
1326f9f1180SMiklos Szeredi  */
133dbd561d2SMiklos Szeredi void fuse_invalidate_entry_cache(struct dentry *entry)
1348cbdf1e6SMiklos Szeredi {
1350a0898cfSMiklos Szeredi 	fuse_dentry_settime(entry, 0);
1368cbdf1e6SMiklos Szeredi }
1378cbdf1e6SMiklos Szeredi 
1386f9f1180SMiklos Szeredi /*
1396f9f1180SMiklos Szeredi  * Same as fuse_invalidate_entry_cache(), but also try to remove the
1406f9f1180SMiklos Szeredi  * dentry from the hash
1416f9f1180SMiklos Szeredi  */
1428cbdf1e6SMiklos Szeredi static void fuse_invalidate_entry(struct dentry *entry)
1438cbdf1e6SMiklos Szeredi {
1448cbdf1e6SMiklos Szeredi 	d_invalidate(entry);
1458cbdf1e6SMiklos Szeredi 	fuse_invalidate_entry_cache(entry);
1460aa7c699SMiklos Szeredi }
1470aa7c699SMiklos Szeredi 
1487078187aSMiklos Szeredi static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_args *args,
14913983d06SAl Viro 			     u64 nodeid, const struct qstr *name,
150e5e5558eSMiklos Szeredi 			     struct fuse_entry_out *outarg)
151e5e5558eSMiklos Szeredi {
1520e9663eeSMiklos Szeredi 	memset(outarg, 0, sizeof(struct fuse_entry_out));
1537078187aSMiklos Szeredi 	args->in.h.opcode = FUSE_LOOKUP;
1547078187aSMiklos Szeredi 	args->in.h.nodeid = nodeid;
1557078187aSMiklos Szeredi 	args->in.numargs = 1;
1567078187aSMiklos Szeredi 	args->in.args[0].size = name->len + 1;
1577078187aSMiklos Szeredi 	args->in.args[0].value = name->name;
1587078187aSMiklos Szeredi 	args->out.numargs = 1;
1597078187aSMiklos Szeredi 	args->out.args[0].size = sizeof(struct fuse_entry_out);
1607078187aSMiklos Szeredi 	args->out.args[0].value = outarg;
161e5e5558eSMiklos Szeredi }
162e5e5558eSMiklos Szeredi 
1635c5c5e51SMiklos Szeredi u64 fuse_get_attr_version(struct fuse_conn *fc)
1647dca9fd3SMiklos Szeredi {
1657dca9fd3SMiklos Szeredi 	u64 curr_version;
1667dca9fd3SMiklos Szeredi 
1677dca9fd3SMiklos Szeredi 	/*
1687dca9fd3SMiklos Szeredi 	 * The spin lock isn't actually needed on 64bit archs, but we
1697dca9fd3SMiklos Szeredi 	 * don't yet care too much about such optimizations.
1707dca9fd3SMiklos Szeredi 	 */
1717dca9fd3SMiklos Szeredi 	spin_lock(&fc->lock);
1727dca9fd3SMiklos Szeredi 	curr_version = fc->attr_version;
1737dca9fd3SMiklos Szeredi 	spin_unlock(&fc->lock);
1747dca9fd3SMiklos Szeredi 
1757dca9fd3SMiklos Szeredi 	return curr_version;
1767dca9fd3SMiklos Szeredi }
1777dca9fd3SMiklos Szeredi 
1786f9f1180SMiklos Szeredi /*
1796f9f1180SMiklos Szeredi  * Check whether the dentry is still valid
1806f9f1180SMiklos Szeredi  *
1816f9f1180SMiklos Szeredi  * If the entry validity timeout has expired and the dentry is
1826f9f1180SMiklos Szeredi  * positive, try to redo the lookup.  If the lookup results in a
1836f9f1180SMiklos Szeredi  * different inode, then let the VFS invalidate the dentry and redo
1846f9f1180SMiklos Szeredi  * the lookup once more.  If the lookup results in the same inode,
1856f9f1180SMiklos Szeredi  * then refresh the attributes, timeouts and mark the dentry valid.
1866f9f1180SMiklos Szeredi  */
1870b728e19SAl Viro static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
188e5e5558eSMiklos Szeredi {
18934286d66SNick Piggin 	struct inode *inode;
19028420dadSMiklos Szeredi 	struct dentry *parent;
19128420dadSMiklos Szeredi 	struct fuse_conn *fc;
1926314efeeSMiklos Szeredi 	struct fuse_inode *fi;
193e2a6b952SMiklos Szeredi 	int ret;
1948cbdf1e6SMiklos Szeredi 
1952b0143b5SDavid Howells 	inode = d_inode_rcu(entry);
1968cbdf1e6SMiklos Szeredi 	if (inode && is_bad_inode(inode))
197e2a6b952SMiklos Szeredi 		goto invalid;
198154210ccSAnand Avati 	else if (time_before64(fuse_dentry_time(entry), get_jiffies_64()) ||
199154210ccSAnand Avati 		 (flags & LOOKUP_REVAL)) {
200e5e5558eSMiklos Szeredi 		struct fuse_entry_out outarg;
2017078187aSMiklos Szeredi 		FUSE_ARGS(args);
20207e77dcaSMiklos Szeredi 		struct fuse_forget_link *forget;
2031fb69e78SMiklos Szeredi 		u64 attr_version;
2048cbdf1e6SMiklos Szeredi 
20550322fe7SMiklos Szeredi 		/* For negative dentries, always do a fresh lookup */
2068cbdf1e6SMiklos Szeredi 		if (!inode)
207e2a6b952SMiklos Szeredi 			goto invalid;
2088cbdf1e6SMiklos Szeredi 
209e2a6b952SMiklos Szeredi 		ret = -ECHILD;
2100b728e19SAl Viro 		if (flags & LOOKUP_RCU)
211e2a6b952SMiklos Szeredi 			goto out;
212e7c0a167SMiklos Szeredi 
2138cbdf1e6SMiklos Szeredi 		fc = get_fuse_conn(inode);
214e5e5558eSMiklos Szeredi 
21507e77dcaSMiklos Szeredi 		forget = fuse_alloc_forget();
216e2a6b952SMiklos Szeredi 		ret = -ENOMEM;
2177078187aSMiklos Szeredi 		if (!forget)
218e2a6b952SMiklos Szeredi 			goto out;
2192d51013eSMiklos Szeredi 
2207dca9fd3SMiklos Szeredi 		attr_version = fuse_get_attr_version(fc);
2211fb69e78SMiklos Szeredi 
222e956edd0SMiklos Szeredi 		parent = dget_parent(entry);
2232b0143b5SDavid Howells 		fuse_lookup_init(fc, &args, get_node_id(d_inode(parent)),
224c180eebeSMiklos Szeredi 				 &entry->d_name, &outarg);
2257078187aSMiklos Szeredi 		ret = fuse_simple_request(fc, &args);
226e956edd0SMiklos Szeredi 		dput(parent);
22750322fe7SMiklos Szeredi 		/* Zero nodeid is same as -ENOENT */
2287078187aSMiklos Szeredi 		if (!ret && !outarg.nodeid)
2297078187aSMiklos Szeredi 			ret = -ENOENT;
2307078187aSMiklos Szeredi 		if (!ret) {
2316314efeeSMiklos Szeredi 			fi = get_fuse_inode(inode);
2329e6268dbSMiklos Szeredi 			if (outarg.nodeid != get_node_id(inode)) {
23307e77dcaSMiklos Szeredi 				fuse_queue_forget(fc, forget, outarg.nodeid, 1);
234e2a6b952SMiklos Szeredi 				goto invalid;
2359e6268dbSMiklos Szeredi 			}
2368da5ff23SMiklos Szeredi 			spin_lock(&fc->lock);
2379e6268dbSMiklos Szeredi 			fi->nlookup++;
2388da5ff23SMiklos Szeredi 			spin_unlock(&fc->lock);
2399e6268dbSMiklos Szeredi 		}
24007e77dcaSMiklos Szeredi 		kfree(forget);
2417078187aSMiklos Szeredi 		if (ret == -ENOMEM)
2427078187aSMiklos Szeredi 			goto out;
2437078187aSMiklos Szeredi 		if (ret || (outarg.attr.mode ^ inode->i_mode) & S_IFMT)
244e2a6b952SMiklos Szeredi 			goto invalid;
245e5e5558eSMiklos Szeredi 
2461fb69e78SMiklos Szeredi 		fuse_change_attributes(inode, &outarg.attr,
2471fb69e78SMiklos Szeredi 				       entry_attr_timeout(&outarg),
2481fb69e78SMiklos Szeredi 				       attr_version);
2491fb69e78SMiklos Szeredi 		fuse_change_entry_timeout(entry, &outarg);
25028420dadSMiklos Szeredi 	} else if (inode) {
2516314efeeSMiklos Szeredi 		fi = get_fuse_inode(inode);
2526314efeeSMiklos Szeredi 		if (flags & LOOKUP_RCU) {
2536314efeeSMiklos Szeredi 			if (test_bit(FUSE_I_INIT_RDPLUS, &fi->state))
2546314efeeSMiklos Szeredi 				return -ECHILD;
2556314efeeSMiklos Szeredi 		} else if (test_and_clear_bit(FUSE_I_INIT_RDPLUS, &fi->state)) {
25628420dadSMiklos Szeredi 			parent = dget_parent(entry);
2572b0143b5SDavid Howells 			fuse_advise_use_readdirplus(d_inode(parent));
25828420dadSMiklos Szeredi 			dput(parent);
259e5e5558eSMiklos Szeredi 		}
26028420dadSMiklos Szeredi 	}
261e2a6b952SMiklos Szeredi 	ret = 1;
262e2a6b952SMiklos Szeredi out:
263e2a6b952SMiklos Szeredi 	return ret;
264e2a6b952SMiklos Szeredi 
265e2a6b952SMiklos Szeredi invalid:
266e2a6b952SMiklos Szeredi 	ret = 0;
267e2a6b952SMiklos Szeredi 	goto out;
268e5e5558eSMiklos Szeredi }
269e5e5558eSMiklos Szeredi 
2708bfc016dSMiklos Szeredi static int invalid_nodeid(u64 nodeid)
2712827d0b2SMiklos Szeredi {
2722827d0b2SMiklos Szeredi 	return !nodeid || nodeid == FUSE_ROOT_ID;
2732827d0b2SMiklos Szeredi }
2742827d0b2SMiklos Szeredi 
2754269590aSAl Viro const struct dentry_operations fuse_dentry_operations = {
276e5e5558eSMiklos Szeredi 	.d_revalidate	= fuse_dentry_revalidate,
277e5e5558eSMiklos Szeredi };
278e5e5558eSMiklos Szeredi 
279a5bfffacSTimo Savola int fuse_valid_type(int m)
28039ee059aSMiklos Szeredi {
28139ee059aSMiklos Szeredi 	return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) ||
28239ee059aSMiklos Szeredi 		S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m);
28339ee059aSMiklos Szeredi }
28439ee059aSMiklos Szeredi 
28513983d06SAl Viro int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name,
286c180eebeSMiklos Szeredi 		     struct fuse_entry_out *outarg, struct inode **inode)
287c180eebeSMiklos Szeredi {
288c180eebeSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn_super(sb);
2897078187aSMiklos Szeredi 	FUSE_ARGS(args);
29007e77dcaSMiklos Szeredi 	struct fuse_forget_link *forget;
291c180eebeSMiklos Szeredi 	u64 attr_version;
292c180eebeSMiklos Szeredi 	int err;
293c180eebeSMiklos Szeredi 
294c180eebeSMiklos Szeredi 	*inode = NULL;
295c180eebeSMiklos Szeredi 	err = -ENAMETOOLONG;
296c180eebeSMiklos Szeredi 	if (name->len > FUSE_NAME_MAX)
297c180eebeSMiklos Szeredi 		goto out;
298c180eebeSMiklos Szeredi 
299c180eebeSMiklos Szeredi 
30007e77dcaSMiklos Szeredi 	forget = fuse_alloc_forget();
30107e77dcaSMiklos Szeredi 	err = -ENOMEM;
3027078187aSMiklos Szeredi 	if (!forget)
303c180eebeSMiklos Szeredi 		goto out;
304c180eebeSMiklos Szeredi 
305c180eebeSMiklos Szeredi 	attr_version = fuse_get_attr_version(fc);
306c180eebeSMiklos Szeredi 
3077078187aSMiklos Szeredi 	fuse_lookup_init(fc, &args, nodeid, name, outarg);
3087078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
309c180eebeSMiklos Szeredi 	/* Zero nodeid is same as -ENOENT, but with valid timeout */
310c180eebeSMiklos Szeredi 	if (err || !outarg->nodeid)
311c180eebeSMiklos Szeredi 		goto out_put_forget;
312c180eebeSMiklos Szeredi 
313c180eebeSMiklos Szeredi 	err = -EIO;
314c180eebeSMiklos Szeredi 	if (!outarg->nodeid)
315c180eebeSMiklos Szeredi 		goto out_put_forget;
316c180eebeSMiklos Szeredi 	if (!fuse_valid_type(outarg->attr.mode))
317c180eebeSMiklos Szeredi 		goto out_put_forget;
318c180eebeSMiklos Szeredi 
319c180eebeSMiklos Szeredi 	*inode = fuse_iget(sb, outarg->nodeid, outarg->generation,
320c180eebeSMiklos Szeredi 			   &outarg->attr, entry_attr_timeout(outarg),
321c180eebeSMiklos Szeredi 			   attr_version);
322c180eebeSMiklos Szeredi 	err = -ENOMEM;
323c180eebeSMiklos Szeredi 	if (!*inode) {
32407e77dcaSMiklos Szeredi 		fuse_queue_forget(fc, forget, outarg->nodeid, 1);
325c180eebeSMiklos Szeredi 		goto out;
326c180eebeSMiklos Szeredi 	}
327c180eebeSMiklos Szeredi 	err = 0;
328c180eebeSMiklos Szeredi 
329c180eebeSMiklos Szeredi  out_put_forget:
33007e77dcaSMiklos Szeredi 	kfree(forget);
331c180eebeSMiklos Szeredi  out:
332c180eebeSMiklos Szeredi 	return err;
333c180eebeSMiklos Szeredi }
334c180eebeSMiklos Szeredi 
3350aa7c699SMiklos Szeredi static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
33600cd8dd3SAl Viro 				  unsigned int flags)
337e5e5558eSMiklos Szeredi {
338e5e5558eSMiklos Szeredi 	int err;
339e5e5558eSMiklos Szeredi 	struct fuse_entry_out outarg;
340c180eebeSMiklos Szeredi 	struct inode *inode;
3410de6256dSMiklos Szeredi 	struct dentry *newent;
342c180eebeSMiklos Szeredi 	bool outarg_valid = true;
343e5e5558eSMiklos Szeredi 
3445c672ab3SMiklos Szeredi 	fuse_lock_inode(dir);
345c180eebeSMiklos Szeredi 	err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name,
346c180eebeSMiklos Szeredi 			       &outarg, &inode);
3475c672ab3SMiklos Szeredi 	fuse_unlock_inode(dir);
348c180eebeSMiklos Szeredi 	if (err == -ENOENT) {
349c180eebeSMiklos Szeredi 		outarg_valid = false;
350c180eebeSMiklos Szeredi 		err = 0;
3512d51013eSMiklos Szeredi 	}
352c180eebeSMiklos Szeredi 	if (err)
353c180eebeSMiklos Szeredi 		goto out_err;
3542d51013eSMiklos Szeredi 
355ee4e5271SMiklos Szeredi 	err = -EIO;
356c180eebeSMiklos Szeredi 	if (inode && get_node_id(inode) == FUSE_ROOT_ID)
357c180eebeSMiklos Szeredi 		goto out_iput;
358e5e5558eSMiklos Szeredi 
35941d28bcaSAl Viro 	newent = d_splice_alias(inode, entry);
360c180eebeSMiklos Szeredi 	err = PTR_ERR(newent);
361c180eebeSMiklos Szeredi 	if (IS_ERR(newent))
3625835f339SMiklos Szeredi 		goto out_err;
363d2a85164SMiklos Szeredi 
3640de6256dSMiklos Szeredi 	entry = newent ? newent : entry;
365c180eebeSMiklos Szeredi 	if (outarg_valid)
3661fb69e78SMiklos Szeredi 		fuse_change_entry_timeout(entry, &outarg);
3678cbdf1e6SMiklos Szeredi 	else
3688cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
369c180eebeSMiklos Szeredi 
3704582a4abSFeng Shuo 	fuse_advise_use_readdirplus(dir);
3710de6256dSMiklos Szeredi 	return newent;
372c180eebeSMiklos Szeredi 
373c180eebeSMiklos Szeredi  out_iput:
374c180eebeSMiklos Szeredi 	iput(inode);
375c180eebeSMiklos Szeredi  out_err:
376c180eebeSMiklos Szeredi 	return ERR_PTR(err);
377e5e5558eSMiklos Szeredi }
378e5e5558eSMiklos Szeredi 
3796f9f1180SMiklos Szeredi /*
3806f9f1180SMiklos Szeredi  * Atomic create+open operation
3816f9f1180SMiklos Szeredi  *
3826f9f1180SMiklos Szeredi  * If the filesystem doesn't support this, then fall back to separate
3836f9f1180SMiklos Szeredi  * 'mknod' + 'open' requests.
3846f9f1180SMiklos Szeredi  */
385d9585277SAl Viro static int fuse_create_open(struct inode *dir, struct dentry *entry,
38630d90494SAl Viro 			    struct file *file, unsigned flags,
38747237687SAl Viro 			    umode_t mode, int *opened)
388fd72faacSMiklos Szeredi {
389fd72faacSMiklos Szeredi 	int err;
390fd72faacSMiklos Szeredi 	struct inode *inode;
391fd72faacSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
3927078187aSMiklos Szeredi 	FUSE_ARGS(args);
39307e77dcaSMiklos Szeredi 	struct fuse_forget_link *forget;
394e0a43ddcSMiklos Szeredi 	struct fuse_create_in inarg;
395fd72faacSMiklos Szeredi 	struct fuse_open_out outopen;
396fd72faacSMiklos Szeredi 	struct fuse_entry_out outentry;
397fd72faacSMiklos Szeredi 	struct fuse_file *ff;
398fd72faacSMiklos Szeredi 
399af109bcaSMiklos Szeredi 	/* Userspace expects S_IFREG in create mode */
400af109bcaSMiklos Szeredi 	BUG_ON((mode & S_IFMT) != S_IFREG);
401af109bcaSMiklos Szeredi 
40207e77dcaSMiklos Szeredi 	forget = fuse_alloc_forget();
403c8ccbe03SMiklos Szeredi 	err = -ENOMEM;
40407e77dcaSMiklos Szeredi 	if (!forget)
405c8ccbe03SMiklos Szeredi 		goto out_err;
40651eb01e7SMiklos Szeredi 
407ce1d5a49SMiklos Szeredi 	err = -ENOMEM;
408acf99433STejun Heo 	ff = fuse_file_alloc(fc);
409fd72faacSMiklos Szeredi 	if (!ff)
4107078187aSMiklos Szeredi 		goto out_put_forget_req;
411fd72faacSMiklos Szeredi 
412e0a43ddcSMiklos Szeredi 	if (!fc->dont_mask)
413e0a43ddcSMiklos Szeredi 		mode &= ~current_umask();
414e0a43ddcSMiklos Szeredi 
415fd72faacSMiklos Szeredi 	flags &= ~O_NOCTTY;
416fd72faacSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
4170e9663eeSMiklos Szeredi 	memset(&outentry, 0, sizeof(outentry));
418fd72faacSMiklos Szeredi 	inarg.flags = flags;
419fd72faacSMiklos Szeredi 	inarg.mode = mode;
420e0a43ddcSMiklos Szeredi 	inarg.umask = current_umask();
4217078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_CREATE;
4227078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(dir);
4237078187aSMiklos Szeredi 	args.in.numargs = 2;
42421f62174SMiklos Szeredi 	args.in.args[0].size = sizeof(inarg);
4257078187aSMiklos Szeredi 	args.in.args[0].value = &inarg;
4267078187aSMiklos Szeredi 	args.in.args[1].size = entry->d_name.len + 1;
4277078187aSMiklos Szeredi 	args.in.args[1].value = entry->d_name.name;
4287078187aSMiklos Szeredi 	args.out.numargs = 2;
4297078187aSMiklos Szeredi 	args.out.args[0].size = sizeof(outentry);
4307078187aSMiklos Szeredi 	args.out.args[0].value = &outentry;
4317078187aSMiklos Szeredi 	args.out.args[1].size = sizeof(outopen);
4327078187aSMiklos Szeredi 	args.out.args[1].value = &outopen;
4337078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
434c8ccbe03SMiklos Szeredi 	if (err)
435fd72faacSMiklos Szeredi 		goto out_free_ff;
436fd72faacSMiklos Szeredi 
437fd72faacSMiklos Szeredi 	err = -EIO;
4382827d0b2SMiklos Szeredi 	if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid))
439fd72faacSMiklos Szeredi 		goto out_free_ff;
440fd72faacSMiklos Szeredi 
441c7b7143cSMiklos Szeredi 	ff->fh = outopen.fh;
442c7b7143cSMiklos Szeredi 	ff->nodeid = outentry.nodeid;
443c7b7143cSMiklos Szeredi 	ff->open_flags = outopen.open_flags;
444fd72faacSMiklos Szeredi 	inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
4451fb69e78SMiklos Szeredi 			  &outentry.attr, entry_attr_timeout(&outentry), 0);
446fd72faacSMiklos Szeredi 	if (!inode) {
447fd72faacSMiklos Szeredi 		flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
4488b0797a4SMiklos Szeredi 		fuse_sync_release(ff, flags);
44907e77dcaSMiklos Szeredi 		fuse_queue_forget(fc, forget, outentry.nodeid, 1);
450c8ccbe03SMiklos Szeredi 		err = -ENOMEM;
451c8ccbe03SMiklos Szeredi 		goto out_err;
452fd72faacSMiklos Szeredi 	}
45307e77dcaSMiklos Szeredi 	kfree(forget);
454fd72faacSMiklos Szeredi 	d_instantiate(entry, inode);
4551fb69e78SMiklos Szeredi 	fuse_change_entry_timeout(entry, &outentry);
4560952b2a4SMiklos Szeredi 	fuse_invalidate_attr(dir);
45730d90494SAl Viro 	err = finish_open(file, entry, generic_file_open, opened);
45830d90494SAl Viro 	if (err) {
4598b0797a4SMiklos Szeredi 		fuse_sync_release(ff, flags);
460c8ccbe03SMiklos Szeredi 	} else {
461c7b7143cSMiklos Szeredi 		file->private_data = fuse_file_get(ff);
462c7b7143cSMiklos Szeredi 		fuse_finish_open(inode, file);
463c8ccbe03SMiklos Szeredi 	}
464d9585277SAl Viro 	return err;
465fd72faacSMiklos Szeredi 
466fd72faacSMiklos Szeredi out_free_ff:
467fd72faacSMiklos Szeredi 	fuse_file_free(ff);
46851eb01e7SMiklos Szeredi out_put_forget_req:
46907e77dcaSMiklos Szeredi 	kfree(forget);
470c8ccbe03SMiklos Szeredi out_err:
471d9585277SAl Viro 	return err;
472c8ccbe03SMiklos Szeredi }
473c8ccbe03SMiklos Szeredi 
474c8ccbe03SMiklos Szeredi static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t);
475d9585277SAl Viro static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
47630d90494SAl Viro 			    struct file *file, unsigned flags,
47747237687SAl Viro 			    umode_t mode, int *opened)
478c8ccbe03SMiklos Szeredi {
479c8ccbe03SMiklos Szeredi 	int err;
480c8ccbe03SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
481c8ccbe03SMiklos Szeredi 	struct dentry *res = NULL;
482c8ccbe03SMiklos Szeredi 
48300699ad8SAl Viro 	if (d_in_lookup(entry)) {
48400cd8dd3SAl Viro 		res = fuse_lookup(dir, entry, 0);
485c8ccbe03SMiklos Szeredi 		if (IS_ERR(res))
486d9585277SAl Viro 			return PTR_ERR(res);
487c8ccbe03SMiklos Szeredi 
488c8ccbe03SMiklos Szeredi 		if (res)
489c8ccbe03SMiklos Szeredi 			entry = res;
490c8ccbe03SMiklos Szeredi 	}
491c8ccbe03SMiklos Szeredi 
4922b0143b5SDavid Howells 	if (!(flags & O_CREAT) || d_really_is_positive(entry))
493c8ccbe03SMiklos Szeredi 		goto no_open;
494c8ccbe03SMiklos Szeredi 
495c8ccbe03SMiklos Szeredi 	/* Only creates */
49647237687SAl Viro 	*opened |= FILE_CREATED;
497c8ccbe03SMiklos Szeredi 
498c8ccbe03SMiklos Szeredi 	if (fc->no_create)
499c8ccbe03SMiklos Szeredi 		goto mknod;
500c8ccbe03SMiklos Szeredi 
50130d90494SAl Viro 	err = fuse_create_open(dir, entry, file, flags, mode, opened);
502d9585277SAl Viro 	if (err == -ENOSYS) {
503c8ccbe03SMiklos Szeredi 		fc->no_create = 1;
504c8ccbe03SMiklos Szeredi 		goto mknod;
505c8ccbe03SMiklos Szeredi 	}
506c8ccbe03SMiklos Szeredi out_dput:
507c8ccbe03SMiklos Szeredi 	dput(res);
508d9585277SAl Viro 	return err;
509c8ccbe03SMiklos Szeredi 
510c8ccbe03SMiklos Szeredi mknod:
511c8ccbe03SMiklos Szeredi 	err = fuse_mknod(dir, entry, mode, 0);
512d9585277SAl Viro 	if (err)
513c8ccbe03SMiklos Szeredi 		goto out_dput;
514c8ccbe03SMiklos Szeredi no_open:
515e45198a6SAl Viro 	return finish_no_open(file, res);
516fd72faacSMiklos Szeredi }
517fd72faacSMiklos Szeredi 
5186f9f1180SMiklos Szeredi /*
5196f9f1180SMiklos Szeredi  * Code shared between mknod, mkdir, symlink and link
5206f9f1180SMiklos Szeredi  */
5217078187aSMiklos Szeredi static int create_new_entry(struct fuse_conn *fc, struct fuse_args *args,
5229e6268dbSMiklos Szeredi 			    struct inode *dir, struct dentry *entry,
523541af6a0SAl Viro 			    umode_t mode)
5249e6268dbSMiklos Szeredi {
5259e6268dbSMiklos Szeredi 	struct fuse_entry_out outarg;
5269e6268dbSMiklos Szeredi 	struct inode *inode;
5279e6268dbSMiklos Szeredi 	int err;
52807e77dcaSMiklos Szeredi 	struct fuse_forget_link *forget;
5292d51013eSMiklos Szeredi 
53007e77dcaSMiklos Szeredi 	forget = fuse_alloc_forget();
5317078187aSMiklos Szeredi 	if (!forget)
53207e77dcaSMiklos Szeredi 		return -ENOMEM;
5339e6268dbSMiklos Szeredi 
5340e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
5357078187aSMiklos Szeredi 	args->in.h.nodeid = get_node_id(dir);
5367078187aSMiklos Szeredi 	args->out.numargs = 1;
5377078187aSMiklos Szeredi 	args->out.args[0].size = sizeof(outarg);
5387078187aSMiklos Szeredi 	args->out.args[0].value = &outarg;
5397078187aSMiklos Szeredi 	err = fuse_simple_request(fc, args);
5402d51013eSMiklos Szeredi 	if (err)
5412d51013eSMiklos Szeredi 		goto out_put_forget_req;
5422d51013eSMiklos Szeredi 
54339ee059aSMiklos Szeredi 	err = -EIO;
54439ee059aSMiklos Szeredi 	if (invalid_nodeid(outarg.nodeid))
5452d51013eSMiklos Szeredi 		goto out_put_forget_req;
54639ee059aSMiklos Szeredi 
54739ee059aSMiklos Szeredi 	if ((outarg.attr.mode ^ mode) & S_IFMT)
5482d51013eSMiklos Szeredi 		goto out_put_forget_req;
54939ee059aSMiklos Szeredi 
5509e6268dbSMiklos Szeredi 	inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
5511fb69e78SMiklos Szeredi 			  &outarg.attr, entry_attr_timeout(&outarg), 0);
5529e6268dbSMiklos Szeredi 	if (!inode) {
55307e77dcaSMiklos Szeredi 		fuse_queue_forget(fc, forget, outarg.nodeid, 1);
5549e6268dbSMiklos Szeredi 		return -ENOMEM;
5559e6268dbSMiklos Szeredi 	}
55607e77dcaSMiklos Szeredi 	kfree(forget);
5579e6268dbSMiklos Szeredi 
558b70a80e7SMiklos Szeredi 	err = d_instantiate_no_diralias(entry, inode);
559b70a80e7SMiklos Szeredi 	if (err)
560b70a80e7SMiklos Szeredi 		return err;
561d2a85164SMiklos Szeredi 
5621fb69e78SMiklos Szeredi 	fuse_change_entry_timeout(entry, &outarg);
5639e6268dbSMiklos Szeredi 	fuse_invalidate_attr(dir);
5649e6268dbSMiklos Szeredi 	return 0;
56539ee059aSMiklos Szeredi 
5662d51013eSMiklos Szeredi  out_put_forget_req:
56707e77dcaSMiklos Szeredi 	kfree(forget);
56839ee059aSMiklos Szeredi 	return err;
5699e6268dbSMiklos Szeredi }
5709e6268dbSMiklos Szeredi 
5711a67aafbSAl Viro static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode,
5729e6268dbSMiklos Szeredi 		      dev_t rdev)
5739e6268dbSMiklos Szeredi {
5749e6268dbSMiklos Szeredi 	struct fuse_mknod_in inarg;
5759e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
5767078187aSMiklos Szeredi 	FUSE_ARGS(args);
5779e6268dbSMiklos Szeredi 
578e0a43ddcSMiklos Szeredi 	if (!fc->dont_mask)
579e0a43ddcSMiklos Szeredi 		mode &= ~current_umask();
580e0a43ddcSMiklos Szeredi 
5819e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
5829e6268dbSMiklos Szeredi 	inarg.mode = mode;
5839e6268dbSMiklos Szeredi 	inarg.rdev = new_encode_dev(rdev);
584e0a43ddcSMiklos Szeredi 	inarg.umask = current_umask();
5857078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_MKNOD;
5867078187aSMiklos Szeredi 	args.in.numargs = 2;
58721f62174SMiklos Szeredi 	args.in.args[0].size = sizeof(inarg);
5887078187aSMiklos Szeredi 	args.in.args[0].value = &inarg;
5897078187aSMiklos Szeredi 	args.in.args[1].size = entry->d_name.len + 1;
5907078187aSMiklos Szeredi 	args.in.args[1].value = entry->d_name.name;
5917078187aSMiklos Szeredi 	return create_new_entry(fc, &args, dir, entry, mode);
5929e6268dbSMiklos Szeredi }
5939e6268dbSMiklos Szeredi 
5944acdaf27SAl Viro static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode,
595ebfc3b49SAl Viro 		       bool excl)
5969e6268dbSMiklos Szeredi {
5979e6268dbSMiklos Szeredi 	return fuse_mknod(dir, entry, mode, 0);
5989e6268dbSMiklos Szeredi }
5999e6268dbSMiklos Szeredi 
60018bb1db3SAl Viro static int fuse_mkdir(struct inode *dir, struct dentry *entry, umode_t mode)
6019e6268dbSMiklos Szeredi {
6029e6268dbSMiklos Szeredi 	struct fuse_mkdir_in inarg;
6039e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
6047078187aSMiklos Szeredi 	FUSE_ARGS(args);
6059e6268dbSMiklos Szeredi 
606e0a43ddcSMiklos Szeredi 	if (!fc->dont_mask)
607e0a43ddcSMiklos Szeredi 		mode &= ~current_umask();
608e0a43ddcSMiklos Szeredi 
6099e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
6109e6268dbSMiklos Szeredi 	inarg.mode = mode;
611e0a43ddcSMiklos Szeredi 	inarg.umask = current_umask();
6127078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_MKDIR;
6137078187aSMiklos Szeredi 	args.in.numargs = 2;
6147078187aSMiklos Szeredi 	args.in.args[0].size = sizeof(inarg);
6157078187aSMiklos Szeredi 	args.in.args[0].value = &inarg;
6167078187aSMiklos Szeredi 	args.in.args[1].size = entry->d_name.len + 1;
6177078187aSMiklos Szeredi 	args.in.args[1].value = entry->d_name.name;
6187078187aSMiklos Szeredi 	return create_new_entry(fc, &args, dir, entry, S_IFDIR);
6199e6268dbSMiklos Szeredi }
6209e6268dbSMiklos Szeredi 
6219e6268dbSMiklos Szeredi static int fuse_symlink(struct inode *dir, struct dentry *entry,
6229e6268dbSMiklos Szeredi 			const char *link)
6239e6268dbSMiklos Szeredi {
6249e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
6259e6268dbSMiklos Szeredi 	unsigned len = strlen(link) + 1;
6267078187aSMiklos Szeredi 	FUSE_ARGS(args);
6279e6268dbSMiklos Szeredi 
6287078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_SYMLINK;
6297078187aSMiklos Szeredi 	args.in.numargs = 2;
6307078187aSMiklos Szeredi 	args.in.args[0].size = entry->d_name.len + 1;
6317078187aSMiklos Szeredi 	args.in.args[0].value = entry->d_name.name;
6327078187aSMiklos Szeredi 	args.in.args[1].size = len;
6337078187aSMiklos Szeredi 	args.in.args[1].value = link;
6347078187aSMiklos Szeredi 	return create_new_entry(fc, &args, dir, entry, S_IFLNK);
6359e6268dbSMiklos Szeredi }
6369e6268dbSMiklos Szeredi 
63731f3267bSMaxim Patlasov static inline void fuse_update_ctime(struct inode *inode)
63831f3267bSMaxim Patlasov {
63931f3267bSMaxim Patlasov 	if (!IS_NOCMTIME(inode)) {
64031f3267bSMaxim Patlasov 		inode->i_ctime = current_fs_time(inode->i_sb);
64131f3267bSMaxim Patlasov 		mark_inode_dirty_sync(inode);
64231f3267bSMaxim Patlasov 	}
64331f3267bSMaxim Patlasov }
64431f3267bSMaxim Patlasov 
6459e6268dbSMiklos Szeredi static int fuse_unlink(struct inode *dir, struct dentry *entry)
6469e6268dbSMiklos Szeredi {
6479e6268dbSMiklos Szeredi 	int err;
6489e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
6497078187aSMiklos Szeredi 	FUSE_ARGS(args);
6509e6268dbSMiklos Szeredi 
6517078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_UNLINK;
6527078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(dir);
6537078187aSMiklos Szeredi 	args.in.numargs = 1;
6547078187aSMiklos Szeredi 	args.in.args[0].size = entry->d_name.len + 1;
6557078187aSMiklos Szeredi 	args.in.args[0].value = entry->d_name.name;
6567078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
6579e6268dbSMiklos Szeredi 	if (!err) {
6582b0143b5SDavid Howells 		struct inode *inode = d_inode(entry);
659ac45d613SMiklos Szeredi 		struct fuse_inode *fi = get_fuse_inode(inode);
6609e6268dbSMiklos Szeredi 
661ac45d613SMiklos Szeredi 		spin_lock(&fc->lock);
662ac45d613SMiklos Szeredi 		fi->attr_version = ++fc->attr_version;
663dfca7cebSMiklos Szeredi 		/*
664dfca7cebSMiklos Szeredi 		 * If i_nlink == 0 then unlink doesn't make sense, yet this can
665dfca7cebSMiklos Szeredi 		 * happen if userspace filesystem is careless.  It would be
666dfca7cebSMiklos Szeredi 		 * difficult to enforce correct nlink usage so just ignore this
667dfca7cebSMiklos Szeredi 		 * condition here
668dfca7cebSMiklos Szeredi 		 */
669dfca7cebSMiklos Szeredi 		if (inode->i_nlink > 0)
670ac45d613SMiklos Szeredi 			drop_nlink(inode);
671ac45d613SMiklos Szeredi 		spin_unlock(&fc->lock);
6729e6268dbSMiklos Szeredi 		fuse_invalidate_attr(inode);
6739e6268dbSMiklos Szeredi 		fuse_invalidate_attr(dir);
6748cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
67531f3267bSMaxim Patlasov 		fuse_update_ctime(inode);
6769e6268dbSMiklos Szeredi 	} else if (err == -EINTR)
6779e6268dbSMiklos Szeredi 		fuse_invalidate_entry(entry);
6789e6268dbSMiklos Szeredi 	return err;
6799e6268dbSMiklos Szeredi }
6809e6268dbSMiklos Szeredi 
6819e6268dbSMiklos Szeredi static int fuse_rmdir(struct inode *dir, struct dentry *entry)
6829e6268dbSMiklos Szeredi {
6839e6268dbSMiklos Szeredi 	int err;
6849e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
6857078187aSMiklos Szeredi 	FUSE_ARGS(args);
6869e6268dbSMiklos Szeredi 
6877078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_RMDIR;
6887078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(dir);
6897078187aSMiklos Szeredi 	args.in.numargs = 1;
6907078187aSMiklos Szeredi 	args.in.args[0].size = entry->d_name.len + 1;
6917078187aSMiklos Szeredi 	args.in.args[0].value = entry->d_name.name;
6927078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
6939e6268dbSMiklos Szeredi 	if (!err) {
6942b0143b5SDavid Howells 		clear_nlink(d_inode(entry));
6959e6268dbSMiklos Szeredi 		fuse_invalidate_attr(dir);
6968cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
6979e6268dbSMiklos Szeredi 	} else if (err == -EINTR)
6989e6268dbSMiklos Szeredi 		fuse_invalidate_entry(entry);
6999e6268dbSMiklos Szeredi 	return err;
7009e6268dbSMiklos Szeredi }
7019e6268dbSMiklos Szeredi 
7021560c974SMiklos Szeredi static int fuse_rename_common(struct inode *olddir, struct dentry *oldent,
7031560c974SMiklos Szeredi 			      struct inode *newdir, struct dentry *newent,
7041560c974SMiklos Szeredi 			      unsigned int flags, int opcode, size_t argsize)
7059e6268dbSMiklos Szeredi {
7069e6268dbSMiklos Szeredi 	int err;
7071560c974SMiklos Szeredi 	struct fuse_rename2_in inarg;
7089e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(olddir);
7097078187aSMiklos Szeredi 	FUSE_ARGS(args);
7109e6268dbSMiklos Szeredi 
7111560c974SMiklos Szeredi 	memset(&inarg, 0, argsize);
7129e6268dbSMiklos Szeredi 	inarg.newdir = get_node_id(newdir);
7131560c974SMiklos Szeredi 	inarg.flags = flags;
7147078187aSMiklos Szeredi 	args.in.h.opcode = opcode;
7157078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(olddir);
7167078187aSMiklos Szeredi 	args.in.numargs = 3;
7177078187aSMiklos Szeredi 	args.in.args[0].size = argsize;
7187078187aSMiklos Szeredi 	args.in.args[0].value = &inarg;
7197078187aSMiklos Szeredi 	args.in.args[1].size = oldent->d_name.len + 1;
7207078187aSMiklos Szeredi 	args.in.args[1].value = oldent->d_name.name;
7217078187aSMiklos Szeredi 	args.in.args[2].size = newent->d_name.len + 1;
7227078187aSMiklos Szeredi 	args.in.args[2].value = newent->d_name.name;
7237078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
7249e6268dbSMiklos Szeredi 	if (!err) {
72508b63307SMiklos Szeredi 		/* ctime changes */
7262b0143b5SDavid Howells 		fuse_invalidate_attr(d_inode(oldent));
7272b0143b5SDavid Howells 		fuse_update_ctime(d_inode(oldent));
72808b63307SMiklos Szeredi 
7291560c974SMiklos Szeredi 		if (flags & RENAME_EXCHANGE) {
7302b0143b5SDavid Howells 			fuse_invalidate_attr(d_inode(newent));
7312b0143b5SDavid Howells 			fuse_update_ctime(d_inode(newent));
7321560c974SMiklos Szeredi 		}
7331560c974SMiklos Szeredi 
7349e6268dbSMiklos Szeredi 		fuse_invalidate_attr(olddir);
7359e6268dbSMiklos Szeredi 		if (olddir != newdir)
7369e6268dbSMiklos Szeredi 			fuse_invalidate_attr(newdir);
7378cbdf1e6SMiklos Szeredi 
7388cbdf1e6SMiklos Szeredi 		/* newent will end up negative */
7392b0143b5SDavid Howells 		if (!(flags & RENAME_EXCHANGE) && d_really_is_positive(newent)) {
7402b0143b5SDavid Howells 			fuse_invalidate_attr(d_inode(newent));
7418cbdf1e6SMiklos Szeredi 			fuse_invalidate_entry_cache(newent);
7422b0143b5SDavid Howells 			fuse_update_ctime(d_inode(newent));
7435219f346SMiklos Szeredi 		}
7449e6268dbSMiklos Szeredi 	} else if (err == -EINTR) {
7459e6268dbSMiklos Szeredi 		/* If request was interrupted, DEITY only knows if the
7469e6268dbSMiklos Szeredi 		   rename actually took place.  If the invalidation
7479e6268dbSMiklos Szeredi 		   fails (e.g. some process has CWD under the renamed
7489e6268dbSMiklos Szeredi 		   directory), then there can be inconsistency between
7499e6268dbSMiklos Szeredi 		   the dcache and the real filesystem.  Tough luck. */
7509e6268dbSMiklos Szeredi 		fuse_invalidate_entry(oldent);
7512b0143b5SDavid Howells 		if (d_really_is_positive(newent))
7529e6268dbSMiklos Szeredi 			fuse_invalidate_entry(newent);
7539e6268dbSMiklos Szeredi 	}
7549e6268dbSMiklos Szeredi 
7559e6268dbSMiklos Szeredi 	return err;
7569e6268dbSMiklos Szeredi }
7579e6268dbSMiklos Szeredi 
7581560c974SMiklos Szeredi static int fuse_rename2(struct inode *olddir, struct dentry *oldent,
7591560c974SMiklos Szeredi 			struct inode *newdir, struct dentry *newent,
7601560c974SMiklos Szeredi 			unsigned int flags)
7611560c974SMiklos Szeredi {
7621560c974SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(olddir);
7631560c974SMiklos Szeredi 	int err;
7641560c974SMiklos Szeredi 
7651560c974SMiklos Szeredi 	if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE))
7661560c974SMiklos Szeredi 		return -EINVAL;
7671560c974SMiklos Szeredi 
7684237ba43SMiklos Szeredi 	if (flags) {
7691560c974SMiklos Szeredi 		if (fc->no_rename2 || fc->minor < 23)
7701560c974SMiklos Szeredi 			return -EINVAL;
7711560c974SMiklos Szeredi 
7721560c974SMiklos Szeredi 		err = fuse_rename_common(olddir, oldent, newdir, newent, flags,
7734237ba43SMiklos Szeredi 					 FUSE_RENAME2,
7744237ba43SMiklos Szeredi 					 sizeof(struct fuse_rename2_in));
7751560c974SMiklos Szeredi 		if (err == -ENOSYS) {
7761560c974SMiklos Szeredi 			fc->no_rename2 = 1;
7771560c974SMiklos Szeredi 			err = -EINVAL;
7781560c974SMiklos Szeredi 		}
7794237ba43SMiklos Szeredi 	} else {
7804237ba43SMiklos Szeredi 		err = fuse_rename_common(olddir, oldent, newdir, newent, 0,
7814237ba43SMiklos Szeredi 					 FUSE_RENAME,
7824237ba43SMiklos Szeredi 					 sizeof(struct fuse_rename_in));
7834237ba43SMiklos Szeredi 	}
7841560c974SMiklos Szeredi 
7854237ba43SMiklos Szeredi 	return err;
7864237ba43SMiklos Szeredi }
7874237ba43SMiklos Szeredi 
7889e6268dbSMiklos Szeredi static int fuse_link(struct dentry *entry, struct inode *newdir,
7899e6268dbSMiklos Szeredi 		     struct dentry *newent)
7909e6268dbSMiklos Szeredi {
7919e6268dbSMiklos Szeredi 	int err;
7929e6268dbSMiklos Szeredi 	struct fuse_link_in inarg;
7932b0143b5SDavid Howells 	struct inode *inode = d_inode(entry);
7949e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
7957078187aSMiklos Szeredi 	FUSE_ARGS(args);
7969e6268dbSMiklos Szeredi 
7979e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
7989e6268dbSMiklos Szeredi 	inarg.oldnodeid = get_node_id(inode);
7997078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_LINK;
8007078187aSMiklos Szeredi 	args.in.numargs = 2;
8017078187aSMiklos Szeredi 	args.in.args[0].size = sizeof(inarg);
8027078187aSMiklos Szeredi 	args.in.args[0].value = &inarg;
8037078187aSMiklos Szeredi 	args.in.args[1].size = newent->d_name.len + 1;
8047078187aSMiklos Szeredi 	args.in.args[1].value = newent->d_name.name;
8057078187aSMiklos Szeredi 	err = create_new_entry(fc, &args, newdir, newent, inode->i_mode);
8069e6268dbSMiklos Szeredi 	/* Contrary to "normal" filesystems it can happen that link
8079e6268dbSMiklos Szeredi 	   makes two "logical" inodes point to the same "physical"
8089e6268dbSMiklos Szeredi 	   inode.  We invalidate the attributes of the old one, so it
8099e6268dbSMiklos Szeredi 	   will reflect changes in the backing inode (link count,
8109e6268dbSMiklos Szeredi 	   etc.)
8119e6268dbSMiklos Szeredi 	*/
812ac45d613SMiklos Szeredi 	if (!err) {
813ac45d613SMiklos Szeredi 		struct fuse_inode *fi = get_fuse_inode(inode);
814ac45d613SMiklos Szeredi 
815ac45d613SMiklos Szeredi 		spin_lock(&fc->lock);
816ac45d613SMiklos Szeredi 		fi->attr_version = ++fc->attr_version;
817ac45d613SMiklos Szeredi 		inc_nlink(inode);
818ac45d613SMiklos Szeredi 		spin_unlock(&fc->lock);
8199e6268dbSMiklos Szeredi 		fuse_invalidate_attr(inode);
82031f3267bSMaxim Patlasov 		fuse_update_ctime(inode);
821ac45d613SMiklos Szeredi 	} else if (err == -EINTR) {
822ac45d613SMiklos Szeredi 		fuse_invalidate_attr(inode);
823ac45d613SMiklos Szeredi 	}
8249e6268dbSMiklos Szeredi 	return err;
8259e6268dbSMiklos Szeredi }
8269e6268dbSMiklos Szeredi 
8271fb69e78SMiklos Szeredi static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
8281fb69e78SMiklos Szeredi 			  struct kstat *stat)
8291fb69e78SMiklos Szeredi {
830203627bbSMiklos Szeredi 	unsigned int blkbits;
8318373200bSPavel Emelyanov 	struct fuse_conn *fc = get_fuse_conn(inode);
8328373200bSPavel Emelyanov 
8338373200bSPavel Emelyanov 	/* see the comment in fuse_change_attributes() */
834b0aa7606SMaxim Patlasov 	if (fc->writeback_cache && S_ISREG(inode->i_mode)) {
8358373200bSPavel Emelyanov 		attr->size = i_size_read(inode);
836b0aa7606SMaxim Patlasov 		attr->mtime = inode->i_mtime.tv_sec;
837b0aa7606SMaxim Patlasov 		attr->mtimensec = inode->i_mtime.tv_nsec;
83831f3267bSMaxim Patlasov 		attr->ctime = inode->i_ctime.tv_sec;
83931f3267bSMaxim Patlasov 		attr->ctimensec = inode->i_ctime.tv_nsec;
840b0aa7606SMaxim Patlasov 	}
841203627bbSMiklos Szeredi 
8421fb69e78SMiklos Szeredi 	stat->dev = inode->i_sb->s_dev;
8431fb69e78SMiklos Szeredi 	stat->ino = attr->ino;
8441fb69e78SMiklos Szeredi 	stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
8451fb69e78SMiklos Szeredi 	stat->nlink = attr->nlink;
846499dcf20SEric W. Biederman 	stat->uid = make_kuid(&init_user_ns, attr->uid);
847499dcf20SEric W. Biederman 	stat->gid = make_kgid(&init_user_ns, attr->gid);
8481fb69e78SMiklos Szeredi 	stat->rdev = inode->i_rdev;
8491fb69e78SMiklos Szeredi 	stat->atime.tv_sec = attr->atime;
8501fb69e78SMiklos Szeredi 	stat->atime.tv_nsec = attr->atimensec;
8511fb69e78SMiklos Szeredi 	stat->mtime.tv_sec = attr->mtime;
8521fb69e78SMiklos Szeredi 	stat->mtime.tv_nsec = attr->mtimensec;
8531fb69e78SMiklos Szeredi 	stat->ctime.tv_sec = attr->ctime;
8541fb69e78SMiklos Szeredi 	stat->ctime.tv_nsec = attr->ctimensec;
8551fb69e78SMiklos Szeredi 	stat->size = attr->size;
8561fb69e78SMiklos Szeredi 	stat->blocks = attr->blocks;
857203627bbSMiklos Szeredi 
858203627bbSMiklos Szeredi 	if (attr->blksize != 0)
859203627bbSMiklos Szeredi 		blkbits = ilog2(attr->blksize);
860203627bbSMiklos Szeredi 	else
861203627bbSMiklos Szeredi 		blkbits = inode->i_sb->s_blocksize_bits;
862203627bbSMiklos Szeredi 
863203627bbSMiklos Szeredi 	stat->blksize = 1 << blkbits;
8641fb69e78SMiklos Szeredi }
8651fb69e78SMiklos Szeredi 
866c79e322fSMiklos Szeredi static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
867c79e322fSMiklos Szeredi 			   struct file *file)
868e5e5558eSMiklos Szeredi {
869e5e5558eSMiklos Szeredi 	int err;
870c79e322fSMiklos Szeredi 	struct fuse_getattr_in inarg;
871c79e322fSMiklos Szeredi 	struct fuse_attr_out outarg;
872e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
8737078187aSMiklos Szeredi 	FUSE_ARGS(args);
8741fb69e78SMiklos Szeredi 	u64 attr_version;
8751fb69e78SMiklos Szeredi 
8767dca9fd3SMiklos Szeredi 	attr_version = fuse_get_attr_version(fc);
8771fb69e78SMiklos Szeredi 
878c79e322fSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
8790e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
880c79e322fSMiklos Szeredi 	/* Directories have separate file-handle space */
881c79e322fSMiklos Szeredi 	if (file && S_ISREG(inode->i_mode)) {
882c79e322fSMiklos Szeredi 		struct fuse_file *ff = file->private_data;
883c79e322fSMiklos Szeredi 
884c79e322fSMiklos Szeredi 		inarg.getattr_flags |= FUSE_GETATTR_FH;
885c79e322fSMiklos Szeredi 		inarg.fh = ff->fh;
886c79e322fSMiklos Szeredi 	}
8877078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_GETATTR;
8887078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(inode);
8897078187aSMiklos Szeredi 	args.in.numargs = 1;
8907078187aSMiklos Szeredi 	args.in.args[0].size = sizeof(inarg);
8917078187aSMiklos Szeredi 	args.in.args[0].value = &inarg;
8927078187aSMiklos Szeredi 	args.out.numargs = 1;
8937078187aSMiklos Szeredi 	args.out.args[0].size = sizeof(outarg);
8947078187aSMiklos Szeredi 	args.out.args[0].value = &outarg;
8957078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
896e5e5558eSMiklos Szeredi 	if (!err) {
897c79e322fSMiklos Szeredi 		if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
898e5e5558eSMiklos Szeredi 			make_bad_inode(inode);
899e5e5558eSMiklos Szeredi 			err = -EIO;
900e5e5558eSMiklos Szeredi 		} else {
901c79e322fSMiklos Szeredi 			fuse_change_attributes(inode, &outarg.attr,
902c79e322fSMiklos Szeredi 					       attr_timeout(&outarg),
9031fb69e78SMiklos Szeredi 					       attr_version);
9041fb69e78SMiklos Szeredi 			if (stat)
905c79e322fSMiklos Szeredi 				fuse_fillattr(inode, &outarg.attr, stat);
906e5e5558eSMiklos Szeredi 		}
907e5e5558eSMiklos Szeredi 	}
908e5e5558eSMiklos Szeredi 	return err;
909e5e5558eSMiklos Szeredi }
910e5e5558eSMiklos Szeredi 
911bcb4be80SMiklos Szeredi int fuse_update_attributes(struct inode *inode, struct kstat *stat,
912bcb4be80SMiklos Szeredi 			   struct file *file, bool *refreshed)
913bcb4be80SMiklos Szeredi {
914bcb4be80SMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
915bcb4be80SMiklos Szeredi 	int err;
916bcb4be80SMiklos Szeredi 	bool r;
917bcb4be80SMiklos Szeredi 
918126b9d43SMiklos Szeredi 	if (time_before64(fi->i_time, get_jiffies_64())) {
919bcb4be80SMiklos Szeredi 		r = true;
920bcb4be80SMiklos Szeredi 		err = fuse_do_getattr(inode, stat, file);
921bcb4be80SMiklos Szeredi 	} else {
922bcb4be80SMiklos Szeredi 		r = false;
923bcb4be80SMiklos Szeredi 		err = 0;
924bcb4be80SMiklos Szeredi 		if (stat) {
925bcb4be80SMiklos Szeredi 			generic_fillattr(inode, stat);
926bcb4be80SMiklos Szeredi 			stat->mode = fi->orig_i_mode;
92745c72cd7SPavel Shilovsky 			stat->ino = fi->orig_ino;
928bcb4be80SMiklos Szeredi 		}
929bcb4be80SMiklos Szeredi 	}
930bcb4be80SMiklos Szeredi 
931bcb4be80SMiklos Szeredi 	if (refreshed != NULL)
932bcb4be80SMiklos Szeredi 		*refreshed = r;
933bcb4be80SMiklos Szeredi 
934bcb4be80SMiklos Szeredi 	return err;
935bcb4be80SMiklos Szeredi }
936bcb4be80SMiklos Szeredi 
9373b463ae0SJohn Muir int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid,
938451d0f59SJohn Muir 			     u64 child_nodeid, struct qstr *name)
9393b463ae0SJohn Muir {
9403b463ae0SJohn Muir 	int err = -ENOTDIR;
9413b463ae0SJohn Muir 	struct inode *parent;
9423b463ae0SJohn Muir 	struct dentry *dir;
9433b463ae0SJohn Muir 	struct dentry *entry;
9443b463ae0SJohn Muir 
9453b463ae0SJohn Muir 	parent = ilookup5(sb, parent_nodeid, fuse_inode_eq, &parent_nodeid);
9463b463ae0SJohn Muir 	if (!parent)
9473b463ae0SJohn Muir 		return -ENOENT;
9483b463ae0SJohn Muir 
9495955102cSAl Viro 	inode_lock(parent);
9503b463ae0SJohn Muir 	if (!S_ISDIR(parent->i_mode))
9513b463ae0SJohn Muir 		goto unlock;
9523b463ae0SJohn Muir 
9533b463ae0SJohn Muir 	err = -ENOENT;
9543b463ae0SJohn Muir 	dir = d_find_alias(parent);
9553b463ae0SJohn Muir 	if (!dir)
9563b463ae0SJohn Muir 		goto unlock;
9573b463ae0SJohn Muir 
9588387ff25SLinus Torvalds 	name->hash = full_name_hash(dir, name->name, name->len);
9593b463ae0SJohn Muir 	entry = d_lookup(dir, name);
9603b463ae0SJohn Muir 	dput(dir);
9613b463ae0SJohn Muir 	if (!entry)
9623b463ae0SJohn Muir 		goto unlock;
9633b463ae0SJohn Muir 
9643b463ae0SJohn Muir 	fuse_invalidate_attr(parent);
9653b463ae0SJohn Muir 	fuse_invalidate_entry(entry);
966451d0f59SJohn Muir 
9672b0143b5SDavid Howells 	if (child_nodeid != 0 && d_really_is_positive(entry)) {
9685955102cSAl Viro 		inode_lock(d_inode(entry));
9692b0143b5SDavid Howells 		if (get_node_id(d_inode(entry)) != child_nodeid) {
970451d0f59SJohn Muir 			err = -ENOENT;
971451d0f59SJohn Muir 			goto badentry;
972451d0f59SJohn Muir 		}
973451d0f59SJohn Muir 		if (d_mountpoint(entry)) {
974451d0f59SJohn Muir 			err = -EBUSY;
975451d0f59SJohn Muir 			goto badentry;
976451d0f59SJohn Muir 		}
977e36cb0b8SDavid Howells 		if (d_is_dir(entry)) {
978451d0f59SJohn Muir 			shrink_dcache_parent(entry);
979451d0f59SJohn Muir 			if (!simple_empty(entry)) {
980451d0f59SJohn Muir 				err = -ENOTEMPTY;
981451d0f59SJohn Muir 				goto badentry;
982451d0f59SJohn Muir 			}
9832b0143b5SDavid Howells 			d_inode(entry)->i_flags |= S_DEAD;
984451d0f59SJohn Muir 		}
985451d0f59SJohn Muir 		dont_mount(entry);
9862b0143b5SDavid Howells 		clear_nlink(d_inode(entry));
9873b463ae0SJohn Muir 		err = 0;
988451d0f59SJohn Muir  badentry:
9895955102cSAl Viro 		inode_unlock(d_inode(entry));
990451d0f59SJohn Muir 		if (!err)
991451d0f59SJohn Muir 			d_delete(entry);
992451d0f59SJohn Muir 	} else {
993451d0f59SJohn Muir 		err = 0;
994451d0f59SJohn Muir 	}
995451d0f59SJohn Muir 	dput(entry);
9963b463ae0SJohn Muir 
9973b463ae0SJohn Muir  unlock:
9985955102cSAl Viro 	inode_unlock(parent);
9993b463ae0SJohn Muir 	iput(parent);
10003b463ae0SJohn Muir 	return err;
10013b463ae0SJohn Muir }
10023b463ae0SJohn Muir 
100387729a55SMiklos Szeredi /*
100487729a55SMiklos Szeredi  * Calling into a user-controlled filesystem gives the filesystem
1005c2132c1bSAnatol Pomozov  * daemon ptrace-like capabilities over the current process.  This
100687729a55SMiklos Szeredi  * means, that the filesystem daemon is able to record the exact
100787729a55SMiklos Szeredi  * filesystem operations performed, and can also control the behavior
100887729a55SMiklos Szeredi  * of the requester process in otherwise impossible ways.  For example
100987729a55SMiklos Szeredi  * it can delay the operation for arbitrary length of time allowing
101087729a55SMiklos Szeredi  * DoS against the requester.
101187729a55SMiklos Szeredi  *
101287729a55SMiklos Szeredi  * For this reason only those processes can call into the filesystem,
101387729a55SMiklos Szeredi  * for which the owner of the mount has ptrace privilege.  This
101487729a55SMiklos Szeredi  * excludes processes started by other users, suid or sgid processes.
101587729a55SMiklos Szeredi  */
1016c2132c1bSAnatol Pomozov int fuse_allow_current_process(struct fuse_conn *fc)
101787729a55SMiklos Szeredi {
1018c69e8d9cSDavid Howells 	const struct cred *cred;
1019c69e8d9cSDavid Howells 
102087729a55SMiklos Szeredi 	if (fc->flags & FUSE_ALLOW_OTHER)
102187729a55SMiklos Szeredi 		return 1;
102287729a55SMiklos Szeredi 
1023c2132c1bSAnatol Pomozov 	cred = current_cred();
1024499dcf20SEric W. Biederman 	if (uid_eq(cred->euid, fc->user_id) &&
1025499dcf20SEric W. Biederman 	    uid_eq(cred->suid, fc->user_id) &&
1026499dcf20SEric W. Biederman 	    uid_eq(cred->uid,  fc->user_id) &&
1027499dcf20SEric W. Biederman 	    gid_eq(cred->egid, fc->group_id) &&
1028499dcf20SEric W. Biederman 	    gid_eq(cred->sgid, fc->group_id) &&
1029499dcf20SEric W. Biederman 	    gid_eq(cred->gid,  fc->group_id))
1030c2132c1bSAnatol Pomozov 		return 1;
103187729a55SMiklos Szeredi 
1032c2132c1bSAnatol Pomozov 	return 0;
103387729a55SMiklos Szeredi }
103487729a55SMiklos Szeredi 
103531d40d74SMiklos Szeredi static int fuse_access(struct inode *inode, int mask)
103631d40d74SMiklos Szeredi {
103731d40d74SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
10387078187aSMiklos Szeredi 	FUSE_ARGS(args);
103931d40d74SMiklos Szeredi 	struct fuse_access_in inarg;
104031d40d74SMiklos Szeredi 	int err;
104131d40d74SMiklos Szeredi 
1042698fa1d1SMiklos Szeredi 	BUG_ON(mask & MAY_NOT_BLOCK);
1043698fa1d1SMiklos Szeredi 
104431d40d74SMiklos Szeredi 	if (fc->no_access)
104531d40d74SMiklos Szeredi 		return 0;
104631d40d74SMiklos Szeredi 
104731d40d74SMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
1048e6305c43SAl Viro 	inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC);
10497078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_ACCESS;
10507078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(inode);
10517078187aSMiklos Szeredi 	args.in.numargs = 1;
10527078187aSMiklos Szeredi 	args.in.args[0].size = sizeof(inarg);
10537078187aSMiklos Szeredi 	args.in.args[0].value = &inarg;
10547078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
105531d40d74SMiklos Szeredi 	if (err == -ENOSYS) {
105631d40d74SMiklos Szeredi 		fc->no_access = 1;
105731d40d74SMiklos Szeredi 		err = 0;
105831d40d74SMiklos Szeredi 	}
105931d40d74SMiklos Szeredi 	return err;
106031d40d74SMiklos Szeredi }
106131d40d74SMiklos Szeredi 
106210556cb2SAl Viro static int fuse_perm_getattr(struct inode *inode, int mask)
106319690ddbSMiklos Szeredi {
106410556cb2SAl Viro 	if (mask & MAY_NOT_BLOCK)
106519690ddbSMiklos Szeredi 		return -ECHILD;
106619690ddbSMiklos Szeredi 
106719690ddbSMiklos Szeredi 	return fuse_do_getattr(inode, NULL, NULL);
106819690ddbSMiklos Szeredi }
106919690ddbSMiklos Szeredi 
10706f9f1180SMiklos Szeredi /*
10716f9f1180SMiklos Szeredi  * Check permission.  The two basic access models of FUSE are:
10726f9f1180SMiklos Szeredi  *
10736f9f1180SMiklos Szeredi  * 1) Local access checking ('default_permissions' mount option) based
10746f9f1180SMiklos Szeredi  * on file mode.  This is the plain old disk filesystem permission
10756f9f1180SMiklos Szeredi  * modell.
10766f9f1180SMiklos Szeredi  *
10776f9f1180SMiklos Szeredi  * 2) "Remote" access checking, where server is responsible for
10786f9f1180SMiklos Szeredi  * checking permission in each inode operation.  An exception to this
10796f9f1180SMiklos Szeredi  * is if ->permission() was invoked from sys_access() in which case an
10806f9f1180SMiklos Szeredi  * access request is sent.  Execute permission is still checked
10816f9f1180SMiklos Szeredi  * locally based on file mode.
10826f9f1180SMiklos Szeredi  */
108310556cb2SAl Viro static int fuse_permission(struct inode *inode, int mask)
1084e5e5558eSMiklos Szeredi {
1085e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1086244f6385SMiklos Szeredi 	bool refreshed = false;
1087244f6385SMiklos Szeredi 	int err = 0;
1088e5e5558eSMiklos Szeredi 
1089c2132c1bSAnatol Pomozov 	if (!fuse_allow_current_process(fc))
1090e5e5558eSMiklos Szeredi 		return -EACCES;
1091244f6385SMiklos Szeredi 
1092244f6385SMiklos Szeredi 	/*
1093e8e96157SMiklos Szeredi 	 * If attributes are needed, refresh them before proceeding
1094244f6385SMiklos Szeredi 	 */
1095e8e96157SMiklos Szeredi 	if ((fc->flags & FUSE_DEFAULT_PERMISSIONS) ||
1096e8e96157SMiklos Szeredi 	    ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
109719690ddbSMiklos Szeredi 		struct fuse_inode *fi = get_fuse_inode(inode);
109819690ddbSMiklos Szeredi 
1099126b9d43SMiklos Szeredi 		if (time_before64(fi->i_time, get_jiffies_64())) {
110019690ddbSMiklos Szeredi 			refreshed = true;
110119690ddbSMiklos Szeredi 
110210556cb2SAl Viro 			err = fuse_perm_getattr(inode, mask);
1103244f6385SMiklos Szeredi 			if (err)
1104244f6385SMiklos Szeredi 				return err;
11051fb69e78SMiklos Szeredi 		}
110619690ddbSMiklos Szeredi 	}
1107244f6385SMiklos Szeredi 
1108244f6385SMiklos Szeredi 	if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
11092830ba7fSAl Viro 		err = generic_permission(inode, mask);
11101e9a4ed9SMiklos Szeredi 
11111e9a4ed9SMiklos Szeredi 		/* If permission is denied, try to refresh file
11121e9a4ed9SMiklos Szeredi 		   attributes.  This is also needed, because the root
11131e9a4ed9SMiklos Szeredi 		   node will at first have no permissions */
1114244f6385SMiklos Szeredi 		if (err == -EACCES && !refreshed) {
111510556cb2SAl Viro 			err = fuse_perm_getattr(inode, mask);
11161e9a4ed9SMiklos Szeredi 			if (!err)
11172830ba7fSAl Viro 				err = generic_permission(inode, mask);
11181e9a4ed9SMiklos Szeredi 		}
11191e9a4ed9SMiklos Szeredi 
11206f9f1180SMiklos Szeredi 		/* Note: the opposite of the above test does not
11216f9f1180SMiklos Szeredi 		   exist.  So if permissions are revoked this won't be
11226f9f1180SMiklos Szeredi 		   noticed immediately, only after the attribute
11236f9f1180SMiklos Szeredi 		   timeout has expired */
11249cfcac81SEric Paris 	} else if (mask & (MAY_ACCESS | MAY_CHDIR)) {
1125e8e96157SMiklos Szeredi 		err = fuse_access(inode, mask);
1126e8e96157SMiklos Szeredi 	} else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
1127e8e96157SMiklos Szeredi 		if (!(inode->i_mode & S_IXUGO)) {
1128e8e96157SMiklos Szeredi 			if (refreshed)
1129e5e5558eSMiklos Szeredi 				return -EACCES;
113031d40d74SMiklos Szeredi 
113110556cb2SAl Viro 			err = fuse_perm_getattr(inode, mask);
1132e8e96157SMiklos Szeredi 			if (!err && !(inode->i_mode & S_IXUGO))
1133e8e96157SMiklos Szeredi 				return -EACCES;
1134e8e96157SMiklos Szeredi 		}
1135e5e5558eSMiklos Szeredi 	}
1136244f6385SMiklos Szeredi 	return err;
1137e5e5558eSMiklos Szeredi }
1138e5e5558eSMiklos Szeredi 
1139e5e5558eSMiklos Szeredi static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
11408d3af7f3SAl Viro 			 struct dir_context *ctx)
1141e5e5558eSMiklos Szeredi {
1142e5e5558eSMiklos Szeredi 	while (nbytes >= FUSE_NAME_OFFSET) {
1143e5e5558eSMiklos Szeredi 		struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
1144e5e5558eSMiklos Szeredi 		size_t reclen = FUSE_DIRENT_SIZE(dirent);
1145e5e5558eSMiklos Szeredi 		if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
1146e5e5558eSMiklos Szeredi 			return -EIO;
1147e5e5558eSMiklos Szeredi 		if (reclen > nbytes)
1148e5e5558eSMiklos Szeredi 			break;
1149efeb9e60SMiklos Szeredi 		if (memchr(dirent->name, '/', dirent->namelen) != NULL)
1150efeb9e60SMiklos Szeredi 			return -EIO;
1151e5e5558eSMiklos Szeredi 
11528d3af7f3SAl Viro 		if (!dir_emit(ctx, dirent->name, dirent->namelen,
11538d3af7f3SAl Viro 			       dirent->ino, dirent->type))
1154e5e5558eSMiklos Szeredi 			break;
1155e5e5558eSMiklos Szeredi 
1156e5e5558eSMiklos Szeredi 		buf += reclen;
1157e5e5558eSMiklos Szeredi 		nbytes -= reclen;
11588d3af7f3SAl Viro 		ctx->pos = dirent->off;
1159e5e5558eSMiklos Szeredi 	}
1160e5e5558eSMiklos Szeredi 
1161e5e5558eSMiklos Szeredi 	return 0;
1162e5e5558eSMiklos Szeredi }
1163e5e5558eSMiklos Szeredi 
11640b05b183SAnand V. Avati static int fuse_direntplus_link(struct file *file,
11650b05b183SAnand V. Avati 				struct fuse_direntplus *direntplus,
11660b05b183SAnand V. Avati 				u64 attr_version)
11670b05b183SAnand V. Avati {
11680b05b183SAnand V. Avati 	struct fuse_entry_out *o = &direntplus->entry_out;
11690b05b183SAnand V. Avati 	struct fuse_dirent *dirent = &direntplus->dirent;
11700b05b183SAnand V. Avati 	struct dentry *parent = file->f_path.dentry;
11710b05b183SAnand V. Avati 	struct qstr name = QSTR_INIT(dirent->name, dirent->namelen);
11720b05b183SAnand V. Avati 	struct dentry *dentry;
11730b05b183SAnand V. Avati 	struct dentry *alias;
11742b0143b5SDavid Howells 	struct inode *dir = d_inode(parent);
11750b05b183SAnand V. Avati 	struct fuse_conn *fc;
11760b05b183SAnand V. Avati 	struct inode *inode;
1177d9b3dbdcSAl Viro 	DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
11780b05b183SAnand V. Avati 
11790b05b183SAnand V. Avati 	if (!o->nodeid) {
11800b05b183SAnand V. Avati 		/*
11810b05b183SAnand V. Avati 		 * Unlike in the case of fuse_lookup, zero nodeid does not mean
11820b05b183SAnand V. Avati 		 * ENOENT. Instead, it only means the userspace filesystem did
11830b05b183SAnand V. Avati 		 * not want to return attributes/handle for this entry.
11840b05b183SAnand V. Avati 		 *
11850b05b183SAnand V. Avati 		 * So do nothing.
11860b05b183SAnand V. Avati 		 */
11870b05b183SAnand V. Avati 		return 0;
11880b05b183SAnand V. Avati 	}
11890b05b183SAnand V. Avati 
11900b05b183SAnand V. Avati 	if (name.name[0] == '.') {
11910b05b183SAnand V. Avati 		/*
11920b05b183SAnand V. Avati 		 * We could potentially refresh the attributes of the directory
11930b05b183SAnand V. Avati 		 * and its parent?
11940b05b183SAnand V. Avati 		 */
11950b05b183SAnand V. Avati 		if (name.len == 1)
11960b05b183SAnand V. Avati 			return 0;
11970b05b183SAnand V. Avati 		if (name.name[1] == '.' && name.len == 2)
11980b05b183SAnand V. Avati 			return 0;
11990b05b183SAnand V. Avati 	}
1200a28ef45cSMiklos Szeredi 
1201a28ef45cSMiklos Szeredi 	if (invalid_nodeid(o->nodeid))
1202a28ef45cSMiklos Szeredi 		return -EIO;
1203a28ef45cSMiklos Szeredi 	if (!fuse_valid_type(o->attr.mode))
1204a28ef45cSMiklos Szeredi 		return -EIO;
1205a28ef45cSMiklos Szeredi 
12060b05b183SAnand V. Avati 	fc = get_fuse_conn(dir);
12070b05b183SAnand V. Avati 
12088387ff25SLinus Torvalds 	name.hash = full_name_hash(parent, name.name, name.len);
12090b05b183SAnand V. Avati 	dentry = d_lookup(parent, &name);
1210d9b3dbdcSAl Viro 	if (!dentry) {
1211d9b3dbdcSAl Viro retry:
1212d9b3dbdcSAl Viro 		dentry = d_alloc_parallel(parent, &name, &wq);
1213d9b3dbdcSAl Viro 		if (IS_ERR(dentry))
1214d9b3dbdcSAl Viro 			return PTR_ERR(dentry);
1215d9b3dbdcSAl Viro 	}
1216d9b3dbdcSAl Viro 	if (!d_in_lookup(dentry)) {
1217d9b3dbdcSAl Viro 		struct fuse_inode *fi;
12182b0143b5SDavid Howells 		inode = d_inode(dentry);
1219d9b3dbdcSAl Viro 		if (!inode ||
1220d9b3dbdcSAl Viro 		    get_node_id(inode) != o->nodeid ||
1221a28ef45cSMiklos Szeredi 		    ((o->attr.mode ^ inode->i_mode) & S_IFMT)) {
12225542aa2fSEric W. Biederman 			d_invalidate(dentry);
1223d9b3dbdcSAl Viro 			dput(dentry);
1224d9b3dbdcSAl Viro 			goto retry;
1225d9b3dbdcSAl Viro 		}
1226d9b3dbdcSAl Viro 		if (is_bad_inode(inode)) {
1227d9b3dbdcSAl Viro 			dput(dentry);
1228d9b3dbdcSAl Viro 			return -EIO;
1229d9b3dbdcSAl Viro 		}
1230d9b3dbdcSAl Viro 
12310b05b183SAnand V. Avati 		fi = get_fuse_inode(inode);
12320b05b183SAnand V. Avati 		spin_lock(&fc->lock);
12330b05b183SAnand V. Avati 		fi->nlookup++;
12340b05b183SAnand V. Avati 		spin_unlock(&fc->lock);
12350b05b183SAnand V. Avati 
1236fa2b7213SMiklos Szeredi 		fuse_change_attributes(inode, &o->attr,
1237fa2b7213SMiklos Szeredi 				       entry_attr_timeout(o),
1238fa2b7213SMiklos Szeredi 				       attr_version);
12390b05b183SAnand V. Avati 		/*
1240d9b3dbdcSAl Viro 		 * The other branch comes via fuse_iget()
12410b05b183SAnand V. Avati 		 * which bumps nlookup inside
12420b05b183SAnand V. Avati 		 */
1243d9b3dbdcSAl Viro 	} else {
12440b05b183SAnand V. Avati 		inode = fuse_iget(dir->i_sb, o->nodeid, o->generation,
1245d9b3dbdcSAl Viro 				  &o->attr, entry_attr_timeout(o),
1246d9b3dbdcSAl Viro 				  attr_version);
12470b05b183SAnand V. Avati 		if (!inode)
1248d9b3dbdcSAl Viro 			inode = ERR_PTR(-ENOMEM);
12490b05b183SAnand V. Avati 
125041d28bcaSAl Viro 		alias = d_splice_alias(inode, dentry);
1251d9b3dbdcSAl Viro 		d_lookup_done(dentry);
12520b05b183SAnand V. Avati 		if (alias) {
12530b05b183SAnand V. Avati 			dput(dentry);
12540b05b183SAnand V. Avati 			dentry = alias;
12550b05b183SAnand V. Avati 		}
1256d9b3dbdcSAl Viro 		if (IS_ERR(dentry))
1257d9b3dbdcSAl Viro 			return PTR_ERR(dentry);
1258d9b3dbdcSAl Viro 	}
12596314efeeSMiklos Szeredi 	if (fc->readdirplus_auto)
12606314efeeSMiklos Szeredi 		set_bit(FUSE_I_INIT_RDPLUS, &get_fuse_inode(inode)->state);
12610b05b183SAnand V. Avati 	fuse_change_entry_timeout(dentry, o);
12620b05b183SAnand V. Avati 
12630b05b183SAnand V. Avati 	dput(dentry);
1264d9b3dbdcSAl Viro 	return 0;
12650b05b183SAnand V. Avati }
12660b05b183SAnand V. Avati 
12670b05b183SAnand V. Avati static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file,
12688d3af7f3SAl Viro 			     struct dir_context *ctx, u64 attr_version)
12690b05b183SAnand V. Avati {
12700b05b183SAnand V. Avati 	struct fuse_direntplus *direntplus;
12710b05b183SAnand V. Avati 	struct fuse_dirent *dirent;
12720b05b183SAnand V. Avati 	size_t reclen;
12730b05b183SAnand V. Avati 	int over = 0;
12740b05b183SAnand V. Avati 	int ret;
12750b05b183SAnand V. Avati 
12760b05b183SAnand V. Avati 	while (nbytes >= FUSE_NAME_OFFSET_DIRENTPLUS) {
12770b05b183SAnand V. Avati 		direntplus = (struct fuse_direntplus *) buf;
12780b05b183SAnand V. Avati 		dirent = &direntplus->dirent;
12790b05b183SAnand V. Avati 		reclen = FUSE_DIRENTPLUS_SIZE(direntplus);
12800b05b183SAnand V. Avati 
12810b05b183SAnand V. Avati 		if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
12820b05b183SAnand V. Avati 			return -EIO;
12830b05b183SAnand V. Avati 		if (reclen > nbytes)
12840b05b183SAnand V. Avati 			break;
1285efeb9e60SMiklos Szeredi 		if (memchr(dirent->name, '/', dirent->namelen) != NULL)
1286efeb9e60SMiklos Szeredi 			return -EIO;
12870b05b183SAnand V. Avati 
12880b05b183SAnand V. Avati 		if (!over) {
12890b05b183SAnand V. Avati 			/* We fill entries into dstbuf only as much as
12900b05b183SAnand V. Avati 			   it can hold. But we still continue iterating
12910b05b183SAnand V. Avati 			   over remaining entries to link them. If not,
12920b05b183SAnand V. Avati 			   we need to send a FORGET for each of those
12930b05b183SAnand V. Avati 			   which we did not link.
12940b05b183SAnand V. Avati 			*/
12958d3af7f3SAl Viro 			over = !dir_emit(ctx, dirent->name, dirent->namelen,
12968d3af7f3SAl Viro 				       dirent->ino, dirent->type);
12978d3af7f3SAl Viro 			ctx->pos = dirent->off;
12980b05b183SAnand V. Avati 		}
12990b05b183SAnand V. Avati 
13000b05b183SAnand V. Avati 		buf += reclen;
13010b05b183SAnand V. Avati 		nbytes -= reclen;
13020b05b183SAnand V. Avati 
13030b05b183SAnand V. Avati 		ret = fuse_direntplus_link(file, direntplus, attr_version);
13040b05b183SAnand V. Avati 		if (ret)
13050b05b183SAnand V. Avati 			fuse_force_forget(file, direntplus->entry_out.nodeid);
13060b05b183SAnand V. Avati 	}
13070b05b183SAnand V. Avati 
13080b05b183SAnand V. Avati 	return 0;
13090b05b183SAnand V. Avati }
13100b05b183SAnand V. Avati 
13118d3af7f3SAl Viro static int fuse_readdir(struct file *file, struct dir_context *ctx)
1312e5e5558eSMiklos Szeredi {
13134582a4abSFeng Shuo 	int plus, err;
131404730fefSMiklos Szeredi 	size_t nbytes;
131504730fefSMiklos Szeredi 	struct page *page;
1316496ad9aaSAl Viro 	struct inode *inode = file_inode(file);
131704730fefSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1318248d86e8SMiklos Szeredi 	struct fuse_req *req;
13190b05b183SAnand V. Avati 	u64 attr_version = 0;
1320248d86e8SMiklos Szeredi 
1321248d86e8SMiklos Szeredi 	if (is_bad_inode(inode))
1322248d86e8SMiklos Szeredi 		return -EIO;
1323248d86e8SMiklos Szeredi 
1324b111c8c0SMaxim Patlasov 	req = fuse_get_req(fc, 1);
1325ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1326ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
1327e5e5558eSMiklos Szeredi 
132804730fefSMiklos Szeredi 	page = alloc_page(GFP_KERNEL);
132904730fefSMiklos Szeredi 	if (!page) {
133004730fefSMiklos Szeredi 		fuse_put_request(fc, req);
1331e5e5558eSMiklos Szeredi 		return -ENOMEM;
133204730fefSMiklos Szeredi 	}
13334582a4abSFeng Shuo 
13348d3af7f3SAl Viro 	plus = fuse_use_readdirplus(inode, ctx);
1335f4975c67SMiklos Szeredi 	req->out.argpages = 1;
133604730fefSMiklos Szeredi 	req->num_pages = 1;
133704730fefSMiklos Szeredi 	req->pages[0] = page;
133885f40aecSMaxim Patlasov 	req->page_descs[0].length = PAGE_SIZE;
13394582a4abSFeng Shuo 	if (plus) {
13400b05b183SAnand V. Avati 		attr_version = fuse_get_attr_version(fc);
13418d3af7f3SAl Viro 		fuse_read_fill(req, file, ctx->pos, PAGE_SIZE,
13420b05b183SAnand V. Avati 			       FUSE_READDIRPLUS);
13430b05b183SAnand V. Avati 	} else {
13448d3af7f3SAl Viro 		fuse_read_fill(req, file, ctx->pos, PAGE_SIZE,
13450b05b183SAnand V. Avati 			       FUSE_READDIR);
13460b05b183SAnand V. Avati 	}
13475c672ab3SMiklos Szeredi 	fuse_lock_inode(inode);
1348b93f858aSTejun Heo 	fuse_request_send(fc, req);
13495c672ab3SMiklos Szeredi 	fuse_unlock_inode(inode);
1350361b1eb5SMiklos Szeredi 	nbytes = req->out.args[0].size;
135104730fefSMiklos Szeredi 	err = req->out.h.error;
135204730fefSMiklos Szeredi 	fuse_put_request(fc, req);
13530b05b183SAnand V. Avati 	if (!err) {
13544582a4abSFeng Shuo 		if (plus) {
13550b05b183SAnand V. Avati 			err = parse_dirplusfile(page_address(page), nbytes,
13568d3af7f3SAl Viro 						file, ctx,
13570b05b183SAnand V. Avati 						attr_version);
13580b05b183SAnand V. Avati 		} else {
13590b05b183SAnand V. Avati 			err = parse_dirfile(page_address(page), nbytes, file,
13608d3af7f3SAl Viro 					    ctx);
13610b05b183SAnand V. Avati 		}
13620b05b183SAnand V. Avati 	}
1363e5e5558eSMiklos Szeredi 
136404730fefSMiklos Szeredi 	__free_page(page);
1365451418fcSAndrew Gallagher 	fuse_invalidate_atime(inode);
136604730fefSMiklos Szeredi 	return err;
1367e5e5558eSMiklos Szeredi }
1368e5e5558eSMiklos Szeredi 
13696b255391SAl Viro static const char *fuse_get_link(struct dentry *dentry,
1370fceef393SAl Viro 				 struct inode *inode,
1371fceef393SAl Viro 				 struct delayed_call *done)
1372e5e5558eSMiklos Szeredi {
1373e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
13747078187aSMiklos Szeredi 	FUSE_ARGS(args);
1375e5e5558eSMiklos Szeredi 	char *link;
13767078187aSMiklos Szeredi 	ssize_t ret;
1377e5e5558eSMiklos Szeredi 
13786b255391SAl Viro 	if (!dentry)
13796b255391SAl Viro 		return ERR_PTR(-ECHILD);
13806b255391SAl Viro 
1381cd3417c8SAl Viro 	link = kmalloc(PAGE_SIZE, GFP_KERNEL);
13827078187aSMiklos Szeredi 	if (!link)
13837078187aSMiklos Szeredi 		return ERR_PTR(-ENOMEM);
13847078187aSMiklos Szeredi 
13857078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_READLINK;
13867078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(inode);
13877078187aSMiklos Szeredi 	args.out.argvar = 1;
13887078187aSMiklos Szeredi 	args.out.numargs = 1;
13897078187aSMiklos Szeredi 	args.out.args[0].size = PAGE_SIZE - 1;
13907078187aSMiklos Szeredi 	args.out.args[0].value = link;
13917078187aSMiklos Szeredi 	ret = fuse_simple_request(fc, &args);
13927078187aSMiklos Szeredi 	if (ret < 0) {
1393cd3417c8SAl Viro 		kfree(link);
13947078187aSMiklos Szeredi 		link = ERR_PTR(ret);
13957078187aSMiklos Szeredi 	} else {
13967078187aSMiklos Szeredi 		link[ret] = '\0';
1397fceef393SAl Viro 		set_delayed_call(done, kfree_link, link);
13987078187aSMiklos Szeredi 	}
1399451418fcSAndrew Gallagher 	fuse_invalidate_atime(inode);
1400e5e5558eSMiklos Szeredi 	return link;
1401e5e5558eSMiklos Szeredi }
1402e5e5558eSMiklos Szeredi 
1403e5e5558eSMiklos Szeredi static int fuse_dir_open(struct inode *inode, struct file *file)
1404e5e5558eSMiklos Szeredi {
140591fe96b4SMiklos Szeredi 	return fuse_open_common(inode, file, true);
1406e5e5558eSMiklos Szeredi }
1407e5e5558eSMiklos Szeredi 
1408e5e5558eSMiklos Szeredi static int fuse_dir_release(struct inode *inode, struct file *file)
1409e5e5558eSMiklos Szeredi {
14108b0797a4SMiklos Szeredi 	fuse_release_common(file, FUSE_RELEASEDIR);
14118b0797a4SMiklos Szeredi 
14128b0797a4SMiklos Szeredi 	return 0;
1413e5e5558eSMiklos Szeredi }
1414e5e5558eSMiklos Szeredi 
141502c24a82SJosef Bacik static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end,
141602c24a82SJosef Bacik 			  int datasync)
141782547981SMiklos Szeredi {
141802c24a82SJosef Bacik 	return fuse_fsync_common(file, start, end, datasync, 1);
141982547981SMiklos Szeredi }
142082547981SMiklos Szeredi 
1421b18da0c5SMiklos Szeredi static long fuse_dir_ioctl(struct file *file, unsigned int cmd,
1422b18da0c5SMiklos Szeredi 			    unsigned long arg)
1423b18da0c5SMiklos Szeredi {
1424b18da0c5SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1425b18da0c5SMiklos Szeredi 
1426b18da0c5SMiklos Szeredi 	/* FUSE_IOCTL_DIR only supported for API version >= 7.18 */
1427b18da0c5SMiklos Szeredi 	if (fc->minor < 18)
1428b18da0c5SMiklos Szeredi 		return -ENOTTY;
1429b18da0c5SMiklos Szeredi 
1430b18da0c5SMiklos Szeredi 	return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR);
1431b18da0c5SMiklos Szeredi }
1432b18da0c5SMiklos Szeredi 
1433b18da0c5SMiklos Szeredi static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd,
1434b18da0c5SMiklos Szeredi 				   unsigned long arg)
1435b18da0c5SMiklos Szeredi {
1436b18da0c5SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1437b18da0c5SMiklos Szeredi 
1438b18da0c5SMiklos Szeredi 	if (fc->minor < 18)
1439b18da0c5SMiklos Szeredi 		return -ENOTTY;
1440b18da0c5SMiklos Szeredi 
1441b18da0c5SMiklos Szeredi 	return fuse_ioctl_common(file, cmd, arg,
1442b18da0c5SMiklos Szeredi 				 FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR);
1443b18da0c5SMiklos Szeredi }
1444b18da0c5SMiklos Szeredi 
1445b0aa7606SMaxim Patlasov static bool update_mtime(unsigned ivalid, bool trust_local_mtime)
144617637cbaSMiklos Szeredi {
144717637cbaSMiklos Szeredi 	/* Always update if mtime is explicitly set  */
144817637cbaSMiklos Szeredi 	if (ivalid & ATTR_MTIME_SET)
144917637cbaSMiklos Szeredi 		return true;
145017637cbaSMiklos Szeredi 
1451b0aa7606SMaxim Patlasov 	/* Or if kernel i_mtime is the official one */
1452b0aa7606SMaxim Patlasov 	if (trust_local_mtime)
1453b0aa7606SMaxim Patlasov 		return true;
1454b0aa7606SMaxim Patlasov 
145517637cbaSMiklos Szeredi 	/* If it's an open(O_TRUNC) or an ftruncate(), don't update */
145617637cbaSMiklos Szeredi 	if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
145717637cbaSMiklos Szeredi 		return false;
145817637cbaSMiklos Szeredi 
145917637cbaSMiklos Szeredi 	/* In all other cases update */
146017637cbaSMiklos Szeredi 	return true;
146117637cbaSMiklos Szeredi }
146217637cbaSMiklos Szeredi 
1463b0aa7606SMaxim Patlasov static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg,
14643ad22c62SMaxim Patlasov 			   bool trust_local_cmtime)
14659e6268dbSMiklos Szeredi {
14669e6268dbSMiklos Szeredi 	unsigned ivalid = iattr->ia_valid;
14679e6268dbSMiklos Szeredi 
14689e6268dbSMiklos Szeredi 	if (ivalid & ATTR_MODE)
1469befc649cSMiklos Szeredi 		arg->valid |= FATTR_MODE,   arg->mode = iattr->ia_mode;
14709e6268dbSMiklos Szeredi 	if (ivalid & ATTR_UID)
1471499dcf20SEric W. Biederman 		arg->valid |= FATTR_UID,    arg->uid = from_kuid(&init_user_ns, iattr->ia_uid);
14729e6268dbSMiklos Szeredi 	if (ivalid & ATTR_GID)
1473499dcf20SEric W. Biederman 		arg->valid |= FATTR_GID,    arg->gid = from_kgid(&init_user_ns, iattr->ia_gid);
14749e6268dbSMiklos Szeredi 	if (ivalid & ATTR_SIZE)
1475befc649cSMiklos Szeredi 		arg->valid |= FATTR_SIZE,   arg->size = iattr->ia_size;
147617637cbaSMiklos Szeredi 	if (ivalid & ATTR_ATIME) {
147717637cbaSMiklos Szeredi 		arg->valid |= FATTR_ATIME;
1478befc649cSMiklos Szeredi 		arg->atime = iattr->ia_atime.tv_sec;
147917637cbaSMiklos Szeredi 		arg->atimensec = iattr->ia_atime.tv_nsec;
148017637cbaSMiklos Szeredi 		if (!(ivalid & ATTR_ATIME_SET))
148117637cbaSMiklos Szeredi 			arg->valid |= FATTR_ATIME_NOW;
148217637cbaSMiklos Szeredi 	}
14833ad22c62SMaxim Patlasov 	if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, trust_local_cmtime)) {
148417637cbaSMiklos Szeredi 		arg->valid |= FATTR_MTIME;
1485befc649cSMiklos Szeredi 		arg->mtime = iattr->ia_mtime.tv_sec;
148617637cbaSMiklos Szeredi 		arg->mtimensec = iattr->ia_mtime.tv_nsec;
14873ad22c62SMaxim Patlasov 		if (!(ivalid & ATTR_MTIME_SET) && !trust_local_cmtime)
148817637cbaSMiklos Szeredi 			arg->valid |= FATTR_MTIME_NOW;
14899e6268dbSMiklos Szeredi 	}
14903ad22c62SMaxim Patlasov 	if ((ivalid & ATTR_CTIME) && trust_local_cmtime) {
14913ad22c62SMaxim Patlasov 		arg->valid |= FATTR_CTIME;
14923ad22c62SMaxim Patlasov 		arg->ctime = iattr->ia_ctime.tv_sec;
14933ad22c62SMaxim Patlasov 		arg->ctimensec = iattr->ia_ctime.tv_nsec;
14943ad22c62SMaxim Patlasov 	}
14959e6268dbSMiklos Szeredi }
14969e6268dbSMiklos Szeredi 
14976f9f1180SMiklos Szeredi /*
14983be5a52bSMiklos Szeredi  * Prevent concurrent writepages on inode
14993be5a52bSMiklos Szeredi  *
15003be5a52bSMiklos Szeredi  * This is done by adding a negative bias to the inode write counter
15013be5a52bSMiklos Szeredi  * and waiting for all pending writes to finish.
15023be5a52bSMiklos Szeredi  */
15033be5a52bSMiklos Szeredi void fuse_set_nowrite(struct inode *inode)
15043be5a52bSMiklos Szeredi {
15053be5a52bSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
15063be5a52bSMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
15073be5a52bSMiklos Szeredi 
15085955102cSAl Viro 	BUG_ON(!inode_is_locked(inode));
15093be5a52bSMiklos Szeredi 
15103be5a52bSMiklos Szeredi 	spin_lock(&fc->lock);
15113be5a52bSMiklos Szeredi 	BUG_ON(fi->writectr < 0);
15123be5a52bSMiklos Szeredi 	fi->writectr += FUSE_NOWRITE;
15133be5a52bSMiklos Szeredi 	spin_unlock(&fc->lock);
15143be5a52bSMiklos Szeredi 	wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE);
15153be5a52bSMiklos Szeredi }
15163be5a52bSMiklos Szeredi 
15173be5a52bSMiklos Szeredi /*
15183be5a52bSMiklos Szeredi  * Allow writepages on inode
15193be5a52bSMiklos Szeredi  *
15203be5a52bSMiklos Szeredi  * Remove the bias from the writecounter and send any queued
15213be5a52bSMiklos Szeredi  * writepages.
15223be5a52bSMiklos Szeredi  */
15233be5a52bSMiklos Szeredi static void __fuse_release_nowrite(struct inode *inode)
15243be5a52bSMiklos Szeredi {
15253be5a52bSMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
15263be5a52bSMiklos Szeredi 
15273be5a52bSMiklos Szeredi 	BUG_ON(fi->writectr != FUSE_NOWRITE);
15283be5a52bSMiklos Szeredi 	fi->writectr = 0;
15293be5a52bSMiklos Szeredi 	fuse_flush_writepages(inode);
15303be5a52bSMiklos Szeredi }
15313be5a52bSMiklos Szeredi 
15323be5a52bSMiklos Szeredi void fuse_release_nowrite(struct inode *inode)
15333be5a52bSMiklos Szeredi {
15343be5a52bSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
15353be5a52bSMiklos Szeredi 
15363be5a52bSMiklos Szeredi 	spin_lock(&fc->lock);
15373be5a52bSMiklos Szeredi 	__fuse_release_nowrite(inode);
15383be5a52bSMiklos Szeredi 	spin_unlock(&fc->lock);
15393be5a52bSMiklos Szeredi }
15403be5a52bSMiklos Szeredi 
15417078187aSMiklos Szeredi static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_args *args,
1542b0aa7606SMaxim Patlasov 			      struct inode *inode,
1543b0aa7606SMaxim Patlasov 			      struct fuse_setattr_in *inarg_p,
1544b0aa7606SMaxim Patlasov 			      struct fuse_attr_out *outarg_p)
1545b0aa7606SMaxim Patlasov {
15467078187aSMiklos Szeredi 	args->in.h.opcode = FUSE_SETATTR;
15477078187aSMiklos Szeredi 	args->in.h.nodeid = get_node_id(inode);
15487078187aSMiklos Szeredi 	args->in.numargs = 1;
15497078187aSMiklos Szeredi 	args->in.args[0].size = sizeof(*inarg_p);
15507078187aSMiklos Szeredi 	args->in.args[0].value = inarg_p;
15517078187aSMiklos Szeredi 	args->out.numargs = 1;
15527078187aSMiklos Szeredi 	args->out.args[0].size = sizeof(*outarg_p);
15537078187aSMiklos Szeredi 	args->out.args[0].value = outarg_p;
1554b0aa7606SMaxim Patlasov }
1555b0aa7606SMaxim Patlasov 
1556b0aa7606SMaxim Patlasov /*
1557b0aa7606SMaxim Patlasov  * Flush inode->i_mtime to the server
1558b0aa7606SMaxim Patlasov  */
1559ab9e13f7SMaxim Patlasov int fuse_flush_times(struct inode *inode, struct fuse_file *ff)
1560b0aa7606SMaxim Patlasov {
1561b0aa7606SMaxim Patlasov 	struct fuse_conn *fc = get_fuse_conn(inode);
15627078187aSMiklos Szeredi 	FUSE_ARGS(args);
1563b0aa7606SMaxim Patlasov 	struct fuse_setattr_in inarg;
1564b0aa7606SMaxim Patlasov 	struct fuse_attr_out outarg;
1565b0aa7606SMaxim Patlasov 
1566b0aa7606SMaxim Patlasov 	memset(&inarg, 0, sizeof(inarg));
1567b0aa7606SMaxim Patlasov 	memset(&outarg, 0, sizeof(outarg));
1568b0aa7606SMaxim Patlasov 
1569ab9e13f7SMaxim Patlasov 	inarg.valid = FATTR_MTIME;
1570b0aa7606SMaxim Patlasov 	inarg.mtime = inode->i_mtime.tv_sec;
1571b0aa7606SMaxim Patlasov 	inarg.mtimensec = inode->i_mtime.tv_nsec;
1572ab9e13f7SMaxim Patlasov 	if (fc->minor >= 23) {
1573ab9e13f7SMaxim Patlasov 		inarg.valid |= FATTR_CTIME;
1574ab9e13f7SMaxim Patlasov 		inarg.ctime = inode->i_ctime.tv_sec;
1575ab9e13f7SMaxim Patlasov 		inarg.ctimensec = inode->i_ctime.tv_nsec;
1576ab9e13f7SMaxim Patlasov 	}
15771e18bda8SMiklos Szeredi 	if (ff) {
15781e18bda8SMiklos Szeredi 		inarg.valid |= FATTR_FH;
15791e18bda8SMiklos Szeredi 		inarg.fh = ff->fh;
15801e18bda8SMiklos Szeredi 	}
15817078187aSMiklos Szeredi 	fuse_setattr_fill(fc, &args, inode, &inarg, &outarg);
1582b0aa7606SMaxim Patlasov 
15837078187aSMiklos Szeredi 	return fuse_simple_request(fc, &args);
1584b0aa7606SMaxim Patlasov }
1585b0aa7606SMaxim Patlasov 
15863be5a52bSMiklos Szeredi /*
15876f9f1180SMiklos Szeredi  * Set attributes, and at the same time refresh them.
15886f9f1180SMiklos Szeredi  *
15896f9f1180SMiklos Szeredi  * Truncation is slightly complicated, because the 'truncate' request
15906f9f1180SMiklos Szeredi  * may fail, in which case we don't want to touch the mapping.
15919ffbb916SMiklos Szeredi  * vmtruncate() doesn't allow for this case, so do the rlimit checking
15929ffbb916SMiklos Szeredi  * and the actual truncation by hand.
15936f9f1180SMiklos Szeredi  */
1594*62490330SJan Kara int fuse_do_setattr(struct dentry *dentry, struct iattr *attr,
159549d4914fSMiklos Szeredi 		    struct file *file)
15969e6268dbSMiklos Szeredi {
1597*62490330SJan Kara 	struct inode *inode = d_inode(dentry);
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);
1706efb9fa9eSMaxim Patlasov 
1707efb9fa9eSMaxim Patlasov 	if (!fuse_allow_current_process(get_fuse_conn(inode)))
1708efb9fa9eSMaxim Patlasov 		return -EACCES;
1709efb9fa9eSMaxim Patlasov 
171049d4914fSMiklos Szeredi 	if (attr->ia_valid & ATTR_FILE)
1711*62490330SJan Kara 		return fuse_do_setattr(entry, attr, attr->ia_file);
171249d4914fSMiklos Szeredi 	else
1713*62490330SJan Kara 		return fuse_do_setattr(entry, attr, NULL);
171449d4914fSMiklos Szeredi }
171549d4914fSMiklos Szeredi 
1716e5e5558eSMiklos Szeredi static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
1717e5e5558eSMiklos Szeredi 			struct kstat *stat)
1718e5e5558eSMiklos Szeredi {
17192b0143b5SDavid Howells 	struct inode *inode = d_inode(entry);
1720244f6385SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1721244f6385SMiklos Szeredi 
1722c2132c1bSAnatol Pomozov 	if (!fuse_allow_current_process(fc))
1723244f6385SMiklos Szeredi 		return -EACCES;
1724244f6385SMiklos Szeredi 
1725bcb4be80SMiklos Szeredi 	return fuse_update_attributes(inode, stat, NULL, NULL);
1726e5e5558eSMiklos Szeredi }
1727e5e5558eSMiklos Szeredi 
17283767e255SAl Viro static int fuse_setxattr(struct dentry *unused, struct inode *inode,
17293767e255SAl Viro 			 const char *name, const void *value,
17303767e255SAl Viro 			 size_t size, int flags)
173192a8780eSMiklos Szeredi {
173292a8780eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
17337078187aSMiklos Szeredi 	FUSE_ARGS(args);
173492a8780eSMiklos Szeredi 	struct fuse_setxattr_in inarg;
173592a8780eSMiklos Szeredi 	int err;
173692a8780eSMiklos Szeredi 
173792a8780eSMiklos Szeredi 	if (fc->no_setxattr)
173892a8780eSMiklos Szeredi 		return -EOPNOTSUPP;
173992a8780eSMiklos Szeredi 
174092a8780eSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
174192a8780eSMiklos Szeredi 	inarg.size = size;
174292a8780eSMiklos Szeredi 	inarg.flags = flags;
17437078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_SETXATTR;
17447078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(inode);
17457078187aSMiklos Szeredi 	args.in.numargs = 3;
17467078187aSMiklos Szeredi 	args.in.args[0].size = sizeof(inarg);
17477078187aSMiklos Szeredi 	args.in.args[0].value = &inarg;
17487078187aSMiklos Szeredi 	args.in.args[1].size = strlen(name) + 1;
17497078187aSMiklos Szeredi 	args.in.args[1].value = name;
17507078187aSMiklos Szeredi 	args.in.args[2].size = size;
17517078187aSMiklos Szeredi 	args.in.args[2].value = value;
17527078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
175392a8780eSMiklos Szeredi 	if (err == -ENOSYS) {
175492a8780eSMiklos Szeredi 		fc->no_setxattr = 1;
175592a8780eSMiklos Szeredi 		err = -EOPNOTSUPP;
175692a8780eSMiklos Szeredi 	}
175731f3267bSMaxim Patlasov 	if (!err) {
1758d331a415SAnand Avati 		fuse_invalidate_attr(inode);
175931f3267bSMaxim Patlasov 		fuse_update_ctime(inode);
176031f3267bSMaxim Patlasov 	}
176192a8780eSMiklos Szeredi 	return err;
176292a8780eSMiklos Szeredi }
176392a8780eSMiklos Szeredi 
1764ce23e640SAl Viro static ssize_t fuse_getxattr(struct dentry *entry, struct inode *inode,
1765ce23e640SAl Viro 			     const char *name, void *value, size_t size)
176692a8780eSMiklos Szeredi {
176792a8780eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
17687078187aSMiklos Szeredi 	FUSE_ARGS(args);
176992a8780eSMiklos Szeredi 	struct fuse_getxattr_in inarg;
177092a8780eSMiklos Szeredi 	struct fuse_getxattr_out outarg;
177192a8780eSMiklos Szeredi 	ssize_t ret;
177292a8780eSMiklos Szeredi 
177392a8780eSMiklos Szeredi 	if (fc->no_getxattr)
177492a8780eSMiklos Szeredi 		return -EOPNOTSUPP;
177592a8780eSMiklos Szeredi 
177692a8780eSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
177792a8780eSMiklos Szeredi 	inarg.size = size;
17787078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_GETXATTR;
17797078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(inode);
17807078187aSMiklos Szeredi 	args.in.numargs = 2;
17817078187aSMiklos Szeredi 	args.in.args[0].size = sizeof(inarg);
17827078187aSMiklos Szeredi 	args.in.args[0].value = &inarg;
17837078187aSMiklos Szeredi 	args.in.args[1].size = strlen(name) + 1;
17847078187aSMiklos Szeredi 	args.in.args[1].value = name;
178592a8780eSMiklos Szeredi 	/* This is really two different operations rolled into one */
17867078187aSMiklos Szeredi 	args.out.numargs = 1;
178792a8780eSMiklos Szeredi 	if (size) {
17887078187aSMiklos Szeredi 		args.out.argvar = 1;
17897078187aSMiklos Szeredi 		args.out.args[0].size = size;
17907078187aSMiklos Szeredi 		args.out.args[0].value = value;
179192a8780eSMiklos Szeredi 	} else {
17927078187aSMiklos Szeredi 		args.out.args[0].size = sizeof(outarg);
17937078187aSMiklos Szeredi 		args.out.args[0].value = &outarg;
179492a8780eSMiklos Szeredi 	}
17957078187aSMiklos Szeredi 	ret = fuse_simple_request(fc, &args);
17967078187aSMiklos Szeredi 	if (!ret && !size)
17977078187aSMiklos Szeredi 		ret = outarg.size;
179892a8780eSMiklos Szeredi 	if (ret == -ENOSYS) {
179992a8780eSMiklos Szeredi 		fc->no_getxattr = 1;
180092a8780eSMiklos Szeredi 		ret = -EOPNOTSUPP;
180192a8780eSMiklos Szeredi 	}
180292a8780eSMiklos Szeredi 	return ret;
180392a8780eSMiklos Szeredi }
180492a8780eSMiklos Szeredi 
180592a8780eSMiklos Szeredi static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
180692a8780eSMiklos Szeredi {
18072b0143b5SDavid Howells 	struct inode *inode = d_inode(entry);
180892a8780eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
18097078187aSMiklos Szeredi 	FUSE_ARGS(args);
181092a8780eSMiklos Szeredi 	struct fuse_getxattr_in inarg;
181192a8780eSMiklos Szeredi 	struct fuse_getxattr_out outarg;
181292a8780eSMiklos Szeredi 	ssize_t ret;
181392a8780eSMiklos Szeredi 
1814c2132c1bSAnatol Pomozov 	if (!fuse_allow_current_process(fc))
1815e57ac683SMiklos Szeredi 		return -EACCES;
1816e57ac683SMiklos Szeredi 
181792a8780eSMiklos Szeredi 	if (fc->no_listxattr)
181892a8780eSMiklos Szeredi 		return -EOPNOTSUPP;
181992a8780eSMiklos Szeredi 
182092a8780eSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
182192a8780eSMiklos Szeredi 	inarg.size = size;
18227078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_LISTXATTR;
18237078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(inode);
18247078187aSMiklos Szeredi 	args.in.numargs = 1;
18257078187aSMiklos Szeredi 	args.in.args[0].size = sizeof(inarg);
18267078187aSMiklos Szeredi 	args.in.args[0].value = &inarg;
182792a8780eSMiklos Szeredi 	/* This is really two different operations rolled into one */
18287078187aSMiklos Szeredi 	args.out.numargs = 1;
182992a8780eSMiklos Szeredi 	if (size) {
18307078187aSMiklos Szeredi 		args.out.argvar = 1;
18317078187aSMiklos Szeredi 		args.out.args[0].size = size;
18327078187aSMiklos Szeredi 		args.out.args[0].value = list;
183392a8780eSMiklos Szeredi 	} else {
18347078187aSMiklos Szeredi 		args.out.args[0].size = sizeof(outarg);
18357078187aSMiklos Szeredi 		args.out.args[0].value = &outarg;
183692a8780eSMiklos Szeredi 	}
18377078187aSMiklos Szeredi 	ret = fuse_simple_request(fc, &args);
18387078187aSMiklos Szeredi 	if (!ret && !size)
18397078187aSMiklos Szeredi 		ret = outarg.size;
184092a8780eSMiklos Szeredi 	if (ret == -ENOSYS) {
184192a8780eSMiklos Szeredi 		fc->no_listxattr = 1;
184292a8780eSMiklos Szeredi 		ret = -EOPNOTSUPP;
184392a8780eSMiklos Szeredi 	}
184492a8780eSMiklos Szeredi 	return ret;
184592a8780eSMiklos Szeredi }
184692a8780eSMiklos Szeredi 
184792a8780eSMiklos Szeredi static int fuse_removexattr(struct dentry *entry, const char *name)
184892a8780eSMiklos Szeredi {
18492b0143b5SDavid Howells 	struct inode *inode = d_inode(entry);
185092a8780eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
18517078187aSMiklos Szeredi 	FUSE_ARGS(args);
185292a8780eSMiklos Szeredi 	int err;
185392a8780eSMiklos Szeredi 
185492a8780eSMiklos Szeredi 	if (fc->no_removexattr)
185592a8780eSMiklos Szeredi 		return -EOPNOTSUPP;
185692a8780eSMiklos Szeredi 
18577078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_REMOVEXATTR;
18587078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(inode);
18597078187aSMiklos Szeredi 	args.in.numargs = 1;
18607078187aSMiklos Szeredi 	args.in.args[0].size = strlen(name) + 1;
18617078187aSMiklos Szeredi 	args.in.args[0].value = name;
18627078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
186392a8780eSMiklos Szeredi 	if (err == -ENOSYS) {
186492a8780eSMiklos Szeredi 		fc->no_removexattr = 1;
186592a8780eSMiklos Szeredi 		err = -EOPNOTSUPP;
186692a8780eSMiklos Szeredi 	}
186731f3267bSMaxim Patlasov 	if (!err) {
1868d331a415SAnand Avati 		fuse_invalidate_attr(inode);
186931f3267bSMaxim Patlasov 		fuse_update_ctime(inode);
187031f3267bSMaxim Patlasov 	}
187192a8780eSMiklos Szeredi 	return err;
187292a8780eSMiklos Szeredi }
187392a8780eSMiklos Szeredi 
1874754661f1SArjan van de Ven static const struct inode_operations fuse_dir_inode_operations = {
1875e5e5558eSMiklos Szeredi 	.lookup		= fuse_lookup,
18769e6268dbSMiklos Szeredi 	.mkdir		= fuse_mkdir,
18779e6268dbSMiklos Szeredi 	.symlink	= fuse_symlink,
18789e6268dbSMiklos Szeredi 	.unlink		= fuse_unlink,
18799e6268dbSMiklos Szeredi 	.rmdir		= fuse_rmdir,
18801560c974SMiklos Szeredi 	.rename2	= fuse_rename2,
18819e6268dbSMiklos Szeredi 	.link		= fuse_link,
18829e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
18839e6268dbSMiklos Szeredi 	.create		= fuse_create,
1884c8ccbe03SMiklos Szeredi 	.atomic_open	= fuse_atomic_open,
18859e6268dbSMiklos Szeredi 	.mknod		= fuse_mknod,
1886e5e5558eSMiklos Szeredi 	.permission	= fuse_permission,
1887e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
188892a8780eSMiklos Szeredi 	.setxattr	= fuse_setxattr,
188992a8780eSMiklos Szeredi 	.getxattr	= fuse_getxattr,
189092a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
189192a8780eSMiklos Szeredi 	.removexattr	= fuse_removexattr,
1892e5e5558eSMiklos Szeredi };
1893e5e5558eSMiklos Szeredi 
18944b6f5d20SArjan van de Ven static const struct file_operations fuse_dir_operations = {
1895b6aeadedSMiklos Szeredi 	.llseek		= generic_file_llseek,
1896e5e5558eSMiklos Szeredi 	.read		= generic_read_dir,
1897d9b3dbdcSAl Viro 	.iterate_shared	= fuse_readdir,
1898e5e5558eSMiklos Szeredi 	.open		= fuse_dir_open,
1899e5e5558eSMiklos Szeredi 	.release	= fuse_dir_release,
190082547981SMiklos Szeredi 	.fsync		= fuse_dir_fsync,
1901b18da0c5SMiklos Szeredi 	.unlocked_ioctl	= fuse_dir_ioctl,
1902b18da0c5SMiklos Szeredi 	.compat_ioctl	= fuse_dir_compat_ioctl,
1903e5e5558eSMiklos Szeredi };
1904e5e5558eSMiklos Szeredi 
1905754661f1SArjan van de Ven static const struct inode_operations fuse_common_inode_operations = {
19069e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
1907e5e5558eSMiklos Szeredi 	.permission	= fuse_permission,
1908e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
190992a8780eSMiklos Szeredi 	.setxattr	= fuse_setxattr,
191092a8780eSMiklos Szeredi 	.getxattr	= fuse_getxattr,
191192a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
191292a8780eSMiklos Szeredi 	.removexattr	= fuse_removexattr,
1913e5e5558eSMiklos Szeredi };
1914e5e5558eSMiklos Szeredi 
1915754661f1SArjan van de Ven static const struct inode_operations fuse_symlink_inode_operations = {
19169e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
19176b255391SAl Viro 	.get_link	= fuse_get_link,
1918e5e5558eSMiklos Szeredi 	.readlink	= generic_readlink,
1919e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
192092a8780eSMiklos Szeredi 	.setxattr	= fuse_setxattr,
192192a8780eSMiklos Szeredi 	.getxattr	= fuse_getxattr,
192292a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
192392a8780eSMiklos Szeredi 	.removexattr	= fuse_removexattr,
1924e5e5558eSMiklos Szeredi };
1925e5e5558eSMiklos Szeredi 
1926e5e5558eSMiklos Szeredi void fuse_init_common(struct inode *inode)
1927e5e5558eSMiklos Szeredi {
1928e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_common_inode_operations;
1929e5e5558eSMiklos Szeredi }
1930e5e5558eSMiklos Szeredi 
1931e5e5558eSMiklos Szeredi void fuse_init_dir(struct inode *inode)
1932e5e5558eSMiklos Szeredi {
1933e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_dir_inode_operations;
1934e5e5558eSMiklos Szeredi 	inode->i_fop = &fuse_dir_operations;
1935e5e5558eSMiklos Szeredi }
1936e5e5558eSMiklos Szeredi 
1937e5e5558eSMiklos Szeredi void fuse_init_symlink(struct inode *inode)
1938e5e5558eSMiklos Szeredi {
1939e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_symlink_inode_operations;
1940e5e5558eSMiklos Szeredi }
1941