xref: /openbmc/linux/fs/fuse/dir.c (revision e36cb0b8)
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,
149c180eebeSMiklos Szeredi 			     u64 nodeid, 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 
195e7c0a167SMiklos Szeredi 	inode = ACCESS_ONCE(entry->d_inode);
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);
2237078187aSMiklos Szeredi 		fuse_lookup_init(fc, &args, get_node_id(parent->d_inode),
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);
25728420dadSMiklos Szeredi 			fuse_advise_use_readdirplus(parent->d_inode);
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 
285c180eebeSMiklos Szeredi int fuse_lookup_name(struct super_block *sb, u64 nodeid, 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 
344c180eebeSMiklos Szeredi 	err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name,
345c180eebeSMiklos Szeredi 			       &outarg, &inode);
346c180eebeSMiklos Szeredi 	if (err == -ENOENT) {
347c180eebeSMiklos Szeredi 		outarg_valid = false;
348c180eebeSMiklos Szeredi 		err = 0;
3492d51013eSMiklos Szeredi 	}
350c180eebeSMiklos Szeredi 	if (err)
351c180eebeSMiklos Szeredi 		goto out_err;
3522d51013eSMiklos Szeredi 
353ee4e5271SMiklos Szeredi 	err = -EIO;
354c180eebeSMiklos Szeredi 	if (inode && get_node_id(inode) == FUSE_ROOT_ID)
355c180eebeSMiklos Szeredi 		goto out_iput;
356e5e5558eSMiklos Szeredi 
35741d28bcaSAl Viro 	newent = d_splice_alias(inode, entry);
358c180eebeSMiklos Szeredi 	err = PTR_ERR(newent);
359c180eebeSMiklos Szeredi 	if (IS_ERR(newent))
3605835f339SMiklos Szeredi 		goto out_err;
361d2a85164SMiklos Szeredi 
3620de6256dSMiklos Szeredi 	entry = newent ? newent : entry;
363c180eebeSMiklos Szeredi 	if (outarg_valid)
3641fb69e78SMiklos Szeredi 		fuse_change_entry_timeout(entry, &outarg);
3658cbdf1e6SMiklos Szeredi 	else
3668cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
367c180eebeSMiklos Szeredi 
3684582a4abSFeng Shuo 	fuse_advise_use_readdirplus(dir);
3690de6256dSMiklos Szeredi 	return newent;
370c180eebeSMiklos Szeredi 
371c180eebeSMiklos Szeredi  out_iput:
372c180eebeSMiklos Szeredi 	iput(inode);
373c180eebeSMiklos Szeredi  out_err:
374c180eebeSMiklos Szeredi 	return ERR_PTR(err);
375e5e5558eSMiklos Szeredi }
376e5e5558eSMiklos Szeredi 
3776f9f1180SMiklos Szeredi /*
3786f9f1180SMiklos Szeredi  * Atomic create+open operation
3796f9f1180SMiklos Szeredi  *
3806f9f1180SMiklos Szeredi  * If the filesystem doesn't support this, then fall back to separate
3816f9f1180SMiklos Szeredi  * 'mknod' + 'open' requests.
3826f9f1180SMiklos Szeredi  */
383d9585277SAl Viro static int fuse_create_open(struct inode *dir, struct dentry *entry,
38430d90494SAl Viro 			    struct file *file, unsigned flags,
38547237687SAl Viro 			    umode_t mode, int *opened)
386fd72faacSMiklos Szeredi {
387fd72faacSMiklos Szeredi 	int err;
388fd72faacSMiklos Szeredi 	struct inode *inode;
389fd72faacSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
3907078187aSMiklos Szeredi 	FUSE_ARGS(args);
39107e77dcaSMiklos Szeredi 	struct fuse_forget_link *forget;
392e0a43ddcSMiklos Szeredi 	struct fuse_create_in inarg;
393fd72faacSMiklos Szeredi 	struct fuse_open_out outopen;
394fd72faacSMiklos Szeredi 	struct fuse_entry_out outentry;
395fd72faacSMiklos Szeredi 	struct fuse_file *ff;
396fd72faacSMiklos Szeredi 
397af109bcaSMiklos Szeredi 	/* Userspace expects S_IFREG in create mode */
398af109bcaSMiklos Szeredi 	BUG_ON((mode & S_IFMT) != S_IFREG);
399af109bcaSMiklos Szeredi 
40007e77dcaSMiklos Szeredi 	forget = fuse_alloc_forget();
401c8ccbe03SMiklos Szeredi 	err = -ENOMEM;
40207e77dcaSMiklos Szeredi 	if (!forget)
403c8ccbe03SMiklos Szeredi 		goto out_err;
40451eb01e7SMiklos Szeredi 
405ce1d5a49SMiklos Szeredi 	err = -ENOMEM;
406acf99433STejun Heo 	ff = fuse_file_alloc(fc);
407fd72faacSMiklos Szeredi 	if (!ff)
4087078187aSMiklos Szeredi 		goto out_put_forget_req;
409fd72faacSMiklos Szeredi 
410e0a43ddcSMiklos Szeredi 	if (!fc->dont_mask)
411e0a43ddcSMiklos Szeredi 		mode &= ~current_umask();
412e0a43ddcSMiklos Szeredi 
413fd72faacSMiklos Szeredi 	flags &= ~O_NOCTTY;
414fd72faacSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
4150e9663eeSMiklos Szeredi 	memset(&outentry, 0, sizeof(outentry));
416fd72faacSMiklos Szeredi 	inarg.flags = flags;
417fd72faacSMiklos Szeredi 	inarg.mode = mode;
418e0a43ddcSMiklos Szeredi 	inarg.umask = current_umask();
4197078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_CREATE;
4207078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(dir);
4217078187aSMiklos Szeredi 	args.in.numargs = 2;
42221f62174SMiklos Szeredi 	args.in.args[0].size = sizeof(inarg);
4237078187aSMiklos Szeredi 	args.in.args[0].value = &inarg;
4247078187aSMiklos Szeredi 	args.in.args[1].size = entry->d_name.len + 1;
4257078187aSMiklos Szeredi 	args.in.args[1].value = entry->d_name.name;
4267078187aSMiklos Szeredi 	args.out.numargs = 2;
4277078187aSMiklos Szeredi 	args.out.args[0].size = sizeof(outentry);
4287078187aSMiklos Szeredi 	args.out.args[0].value = &outentry;
4297078187aSMiklos Szeredi 	args.out.args[1].size = sizeof(outopen);
4307078187aSMiklos Szeredi 	args.out.args[1].value = &outopen;
4317078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
432c8ccbe03SMiklos Szeredi 	if (err)
433fd72faacSMiklos Szeredi 		goto out_free_ff;
434fd72faacSMiklos Szeredi 
435fd72faacSMiklos Szeredi 	err = -EIO;
4362827d0b2SMiklos Szeredi 	if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid))
437fd72faacSMiklos Szeredi 		goto out_free_ff;
438fd72faacSMiklos Szeredi 
439c7b7143cSMiklos Szeredi 	ff->fh = outopen.fh;
440c7b7143cSMiklos Szeredi 	ff->nodeid = outentry.nodeid;
441c7b7143cSMiklos Szeredi 	ff->open_flags = outopen.open_flags;
442fd72faacSMiklos Szeredi 	inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
4431fb69e78SMiklos Szeredi 			  &outentry.attr, entry_attr_timeout(&outentry), 0);
444fd72faacSMiklos Szeredi 	if (!inode) {
445fd72faacSMiklos Szeredi 		flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
4468b0797a4SMiklos Szeredi 		fuse_sync_release(ff, flags);
44707e77dcaSMiklos Szeredi 		fuse_queue_forget(fc, forget, outentry.nodeid, 1);
448c8ccbe03SMiklos Szeredi 		err = -ENOMEM;
449c8ccbe03SMiklos Szeredi 		goto out_err;
450fd72faacSMiklos Szeredi 	}
45107e77dcaSMiklos Szeredi 	kfree(forget);
452fd72faacSMiklos Szeredi 	d_instantiate(entry, inode);
4531fb69e78SMiklos Szeredi 	fuse_change_entry_timeout(entry, &outentry);
4540952b2a4SMiklos Szeredi 	fuse_invalidate_attr(dir);
45530d90494SAl Viro 	err = finish_open(file, entry, generic_file_open, opened);
45630d90494SAl Viro 	if (err) {
4578b0797a4SMiklos Szeredi 		fuse_sync_release(ff, flags);
458c8ccbe03SMiklos Szeredi 	} else {
459c7b7143cSMiklos Szeredi 		file->private_data = fuse_file_get(ff);
460c7b7143cSMiklos Szeredi 		fuse_finish_open(inode, file);
461c8ccbe03SMiklos Szeredi 	}
462d9585277SAl Viro 	return err;
463fd72faacSMiklos Szeredi 
464fd72faacSMiklos Szeredi out_free_ff:
465fd72faacSMiklos Szeredi 	fuse_file_free(ff);
46651eb01e7SMiklos Szeredi out_put_forget_req:
46707e77dcaSMiklos Szeredi 	kfree(forget);
468c8ccbe03SMiklos Szeredi out_err:
469d9585277SAl Viro 	return err;
470c8ccbe03SMiklos Szeredi }
471c8ccbe03SMiklos Szeredi 
472c8ccbe03SMiklos Szeredi static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t);
473d9585277SAl Viro static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
47430d90494SAl Viro 			    struct file *file, unsigned flags,
47547237687SAl Viro 			    umode_t mode, int *opened)
476c8ccbe03SMiklos Szeredi {
477c8ccbe03SMiklos Szeredi 	int err;
478c8ccbe03SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
479c8ccbe03SMiklos Szeredi 	struct dentry *res = NULL;
480c8ccbe03SMiklos Szeredi 
481c8ccbe03SMiklos Szeredi 	if (d_unhashed(entry)) {
48200cd8dd3SAl Viro 		res = fuse_lookup(dir, entry, 0);
483c8ccbe03SMiklos Szeredi 		if (IS_ERR(res))
484d9585277SAl Viro 			return PTR_ERR(res);
485c8ccbe03SMiklos Szeredi 
486c8ccbe03SMiklos Szeredi 		if (res)
487c8ccbe03SMiklos Szeredi 			entry = res;
488c8ccbe03SMiklos Szeredi 	}
489c8ccbe03SMiklos Szeredi 
490c8ccbe03SMiklos Szeredi 	if (!(flags & O_CREAT) || entry->d_inode)
491c8ccbe03SMiklos Szeredi 		goto no_open;
492c8ccbe03SMiklos Szeredi 
493c8ccbe03SMiklos Szeredi 	/* Only creates */
49447237687SAl Viro 	*opened |= FILE_CREATED;
495c8ccbe03SMiklos Szeredi 
496c8ccbe03SMiklos Szeredi 	if (fc->no_create)
497c8ccbe03SMiklos Szeredi 		goto mknod;
498c8ccbe03SMiklos Szeredi 
49930d90494SAl Viro 	err = fuse_create_open(dir, entry, file, flags, mode, opened);
500d9585277SAl Viro 	if (err == -ENOSYS) {
501c8ccbe03SMiklos Szeredi 		fc->no_create = 1;
502c8ccbe03SMiklos Szeredi 		goto mknod;
503c8ccbe03SMiklos Szeredi 	}
504c8ccbe03SMiklos Szeredi out_dput:
505c8ccbe03SMiklos Szeredi 	dput(res);
506d9585277SAl Viro 	return err;
507c8ccbe03SMiklos Szeredi 
508c8ccbe03SMiklos Szeredi mknod:
509c8ccbe03SMiklos Szeredi 	err = fuse_mknod(dir, entry, mode, 0);
510d9585277SAl Viro 	if (err)
511c8ccbe03SMiklos Szeredi 		goto out_dput;
512c8ccbe03SMiklos Szeredi no_open:
513e45198a6SAl Viro 	return finish_no_open(file, res);
514fd72faacSMiklos Szeredi }
515fd72faacSMiklos Szeredi 
5166f9f1180SMiklos Szeredi /*
5176f9f1180SMiklos Szeredi  * Code shared between mknod, mkdir, symlink and link
5186f9f1180SMiklos Szeredi  */
5197078187aSMiklos Szeredi static int create_new_entry(struct fuse_conn *fc, struct fuse_args *args,
5209e6268dbSMiklos Szeredi 			    struct inode *dir, struct dentry *entry,
521541af6a0SAl Viro 			    umode_t mode)
5229e6268dbSMiklos Szeredi {
5239e6268dbSMiklos Szeredi 	struct fuse_entry_out outarg;
5249e6268dbSMiklos Szeredi 	struct inode *inode;
5259e6268dbSMiklos Szeredi 	int err;
52607e77dcaSMiklos Szeredi 	struct fuse_forget_link *forget;
5272d51013eSMiklos Szeredi 
52807e77dcaSMiklos Szeredi 	forget = fuse_alloc_forget();
5297078187aSMiklos Szeredi 	if (!forget)
53007e77dcaSMiklos Szeredi 		return -ENOMEM;
5319e6268dbSMiklos Szeredi 
5320e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
5337078187aSMiklos Szeredi 	args->in.h.nodeid = get_node_id(dir);
5347078187aSMiklos Szeredi 	args->out.numargs = 1;
5357078187aSMiklos Szeredi 	args->out.args[0].size = sizeof(outarg);
5367078187aSMiklos Szeredi 	args->out.args[0].value = &outarg;
5377078187aSMiklos Szeredi 	err = fuse_simple_request(fc, args);
5382d51013eSMiklos Szeredi 	if (err)
5392d51013eSMiklos Szeredi 		goto out_put_forget_req;
5402d51013eSMiklos Szeredi 
54139ee059aSMiklos Szeredi 	err = -EIO;
54239ee059aSMiklos Szeredi 	if (invalid_nodeid(outarg.nodeid))
5432d51013eSMiklos Szeredi 		goto out_put_forget_req;
54439ee059aSMiklos Szeredi 
54539ee059aSMiklos Szeredi 	if ((outarg.attr.mode ^ mode) & S_IFMT)
5462d51013eSMiklos Szeredi 		goto out_put_forget_req;
54739ee059aSMiklos Szeredi 
5489e6268dbSMiklos Szeredi 	inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
5491fb69e78SMiklos Szeredi 			  &outarg.attr, entry_attr_timeout(&outarg), 0);
5509e6268dbSMiklos Szeredi 	if (!inode) {
55107e77dcaSMiklos Szeredi 		fuse_queue_forget(fc, forget, outarg.nodeid, 1);
5529e6268dbSMiklos Szeredi 		return -ENOMEM;
5539e6268dbSMiklos Szeredi 	}
55407e77dcaSMiklos Szeredi 	kfree(forget);
5559e6268dbSMiklos Szeredi 
556b70a80e7SMiklos Szeredi 	err = d_instantiate_no_diralias(entry, inode);
557b70a80e7SMiklos Szeredi 	if (err)
558b70a80e7SMiklos Szeredi 		return err;
559d2a85164SMiklos Szeredi 
5601fb69e78SMiklos Szeredi 	fuse_change_entry_timeout(entry, &outarg);
5619e6268dbSMiklos Szeredi 	fuse_invalidate_attr(dir);
5629e6268dbSMiklos Szeredi 	return 0;
56339ee059aSMiklos Szeredi 
5642d51013eSMiklos Szeredi  out_put_forget_req:
56507e77dcaSMiklos Szeredi 	kfree(forget);
56639ee059aSMiklos Szeredi 	return err;
5679e6268dbSMiklos Szeredi }
5689e6268dbSMiklos Szeredi 
5691a67aafbSAl Viro static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode,
5709e6268dbSMiklos Szeredi 		      dev_t rdev)
5719e6268dbSMiklos Szeredi {
5729e6268dbSMiklos Szeredi 	struct fuse_mknod_in inarg;
5739e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
5747078187aSMiklos Szeredi 	FUSE_ARGS(args);
5759e6268dbSMiklos Szeredi 
576e0a43ddcSMiklos Szeredi 	if (!fc->dont_mask)
577e0a43ddcSMiklos Szeredi 		mode &= ~current_umask();
578e0a43ddcSMiklos Szeredi 
5799e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
5809e6268dbSMiklos Szeredi 	inarg.mode = mode;
5819e6268dbSMiklos Szeredi 	inarg.rdev = new_encode_dev(rdev);
582e0a43ddcSMiklos Szeredi 	inarg.umask = current_umask();
5837078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_MKNOD;
5847078187aSMiklos Szeredi 	args.in.numargs = 2;
58521f62174SMiklos Szeredi 	args.in.args[0].size = sizeof(inarg);
5867078187aSMiklos Szeredi 	args.in.args[0].value = &inarg;
5877078187aSMiklos Szeredi 	args.in.args[1].size = entry->d_name.len + 1;
5887078187aSMiklos Szeredi 	args.in.args[1].value = entry->d_name.name;
5897078187aSMiklos Szeredi 	return create_new_entry(fc, &args, dir, entry, mode);
5909e6268dbSMiklos Szeredi }
5919e6268dbSMiklos Szeredi 
5924acdaf27SAl Viro static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode,
593ebfc3b49SAl Viro 		       bool excl)
5949e6268dbSMiklos Szeredi {
5959e6268dbSMiklos Szeredi 	return fuse_mknod(dir, entry, mode, 0);
5969e6268dbSMiklos Szeredi }
5979e6268dbSMiklos Szeredi 
59818bb1db3SAl Viro static int fuse_mkdir(struct inode *dir, struct dentry *entry, umode_t mode)
5999e6268dbSMiklos Szeredi {
6009e6268dbSMiklos Szeredi 	struct fuse_mkdir_in inarg;
6019e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
6027078187aSMiklos Szeredi 	FUSE_ARGS(args);
6039e6268dbSMiklos Szeredi 
604e0a43ddcSMiklos Szeredi 	if (!fc->dont_mask)
605e0a43ddcSMiklos Szeredi 		mode &= ~current_umask();
606e0a43ddcSMiklos Szeredi 
6079e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
6089e6268dbSMiklos Szeredi 	inarg.mode = mode;
609e0a43ddcSMiklos Szeredi 	inarg.umask = current_umask();
6107078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_MKDIR;
6117078187aSMiklos Szeredi 	args.in.numargs = 2;
6127078187aSMiklos Szeredi 	args.in.args[0].size = sizeof(inarg);
6137078187aSMiklos Szeredi 	args.in.args[0].value = &inarg;
6147078187aSMiklos Szeredi 	args.in.args[1].size = entry->d_name.len + 1;
6157078187aSMiklos Szeredi 	args.in.args[1].value = entry->d_name.name;
6167078187aSMiklos Szeredi 	return create_new_entry(fc, &args, dir, entry, S_IFDIR);
6179e6268dbSMiklos Szeredi }
6189e6268dbSMiklos Szeredi 
6199e6268dbSMiklos Szeredi static int fuse_symlink(struct inode *dir, struct dentry *entry,
6209e6268dbSMiklos Szeredi 			const char *link)
6219e6268dbSMiklos Szeredi {
6229e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
6239e6268dbSMiklos Szeredi 	unsigned len = strlen(link) + 1;
6247078187aSMiklos Szeredi 	FUSE_ARGS(args);
6259e6268dbSMiklos Szeredi 
6267078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_SYMLINK;
6277078187aSMiklos Szeredi 	args.in.numargs = 2;
6287078187aSMiklos Szeredi 	args.in.args[0].size = entry->d_name.len + 1;
6297078187aSMiklos Szeredi 	args.in.args[0].value = entry->d_name.name;
6307078187aSMiklos Szeredi 	args.in.args[1].size = len;
6317078187aSMiklos Szeredi 	args.in.args[1].value = link;
6327078187aSMiklos Szeredi 	return create_new_entry(fc, &args, dir, entry, S_IFLNK);
6339e6268dbSMiklos Szeredi }
6349e6268dbSMiklos Szeredi 
63531f3267bSMaxim Patlasov static inline void fuse_update_ctime(struct inode *inode)
63631f3267bSMaxim Patlasov {
63731f3267bSMaxim Patlasov 	if (!IS_NOCMTIME(inode)) {
63831f3267bSMaxim Patlasov 		inode->i_ctime = current_fs_time(inode->i_sb);
63931f3267bSMaxim Patlasov 		mark_inode_dirty_sync(inode);
64031f3267bSMaxim Patlasov 	}
64131f3267bSMaxim Patlasov }
64231f3267bSMaxim Patlasov 
6439e6268dbSMiklos Szeredi static int fuse_unlink(struct inode *dir, struct dentry *entry)
6449e6268dbSMiklos Szeredi {
6459e6268dbSMiklos Szeredi 	int err;
6469e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
6477078187aSMiklos Szeredi 	FUSE_ARGS(args);
6489e6268dbSMiklos Szeredi 
6497078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_UNLINK;
6507078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(dir);
6517078187aSMiklos Szeredi 	args.in.numargs = 1;
6527078187aSMiklos Szeredi 	args.in.args[0].size = entry->d_name.len + 1;
6537078187aSMiklos Szeredi 	args.in.args[0].value = entry->d_name.name;
6547078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
6559e6268dbSMiklos Szeredi 	if (!err) {
6569e6268dbSMiklos Szeredi 		struct inode *inode = entry->d_inode;
657ac45d613SMiklos Szeredi 		struct fuse_inode *fi = get_fuse_inode(inode);
6589e6268dbSMiklos Szeredi 
659ac45d613SMiklos Szeredi 		spin_lock(&fc->lock);
660ac45d613SMiklos Szeredi 		fi->attr_version = ++fc->attr_version;
661dfca7cebSMiklos Szeredi 		/*
662dfca7cebSMiklos Szeredi 		 * If i_nlink == 0 then unlink doesn't make sense, yet this can
663dfca7cebSMiklos Szeredi 		 * happen if userspace filesystem is careless.  It would be
664dfca7cebSMiklos Szeredi 		 * difficult to enforce correct nlink usage so just ignore this
665dfca7cebSMiklos Szeredi 		 * condition here
666dfca7cebSMiklos Szeredi 		 */
667dfca7cebSMiklos Szeredi 		if (inode->i_nlink > 0)
668ac45d613SMiklos Szeredi 			drop_nlink(inode);
669ac45d613SMiklos Szeredi 		spin_unlock(&fc->lock);
6709e6268dbSMiklos Szeredi 		fuse_invalidate_attr(inode);
6719e6268dbSMiklos Szeredi 		fuse_invalidate_attr(dir);
6728cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
67331f3267bSMaxim Patlasov 		fuse_update_ctime(inode);
6749e6268dbSMiklos Szeredi 	} else if (err == -EINTR)
6759e6268dbSMiklos Szeredi 		fuse_invalidate_entry(entry);
6769e6268dbSMiklos Szeredi 	return err;
6779e6268dbSMiklos Szeredi }
6789e6268dbSMiklos Szeredi 
6799e6268dbSMiklos Szeredi static int fuse_rmdir(struct inode *dir, struct dentry *entry)
6809e6268dbSMiklos Szeredi {
6819e6268dbSMiklos Szeredi 	int err;
6829e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
6837078187aSMiklos Szeredi 	FUSE_ARGS(args);
6849e6268dbSMiklos Szeredi 
6857078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_RMDIR;
6867078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(dir);
6877078187aSMiklos Szeredi 	args.in.numargs = 1;
6887078187aSMiklos Szeredi 	args.in.args[0].size = entry->d_name.len + 1;
6897078187aSMiklos Szeredi 	args.in.args[0].value = entry->d_name.name;
6907078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
6919e6268dbSMiklos Szeredi 	if (!err) {
692ce71ec36SDave Hansen 		clear_nlink(entry->d_inode);
6939e6268dbSMiklos Szeredi 		fuse_invalidate_attr(dir);
6948cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
6959e6268dbSMiklos Szeredi 	} else if (err == -EINTR)
6969e6268dbSMiklos Szeredi 		fuse_invalidate_entry(entry);
6979e6268dbSMiklos Szeredi 	return err;
6989e6268dbSMiklos Szeredi }
6999e6268dbSMiklos Szeredi 
7001560c974SMiklos Szeredi static int fuse_rename_common(struct inode *olddir, struct dentry *oldent,
7011560c974SMiklos Szeredi 			      struct inode *newdir, struct dentry *newent,
7021560c974SMiklos Szeredi 			      unsigned int flags, int opcode, size_t argsize)
7039e6268dbSMiklos Szeredi {
7049e6268dbSMiklos Szeredi 	int err;
7051560c974SMiklos Szeredi 	struct fuse_rename2_in inarg;
7069e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(olddir);
7077078187aSMiklos Szeredi 	FUSE_ARGS(args);
7089e6268dbSMiklos Szeredi 
7091560c974SMiklos Szeredi 	memset(&inarg, 0, argsize);
7109e6268dbSMiklos Szeredi 	inarg.newdir = get_node_id(newdir);
7111560c974SMiklos Szeredi 	inarg.flags = flags;
7127078187aSMiklos Szeredi 	args.in.h.opcode = opcode;
7137078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(olddir);
7147078187aSMiklos Szeredi 	args.in.numargs = 3;
7157078187aSMiklos Szeredi 	args.in.args[0].size = argsize;
7167078187aSMiklos Szeredi 	args.in.args[0].value = &inarg;
7177078187aSMiklos Szeredi 	args.in.args[1].size = oldent->d_name.len + 1;
7187078187aSMiklos Szeredi 	args.in.args[1].value = oldent->d_name.name;
7197078187aSMiklos Szeredi 	args.in.args[2].size = newent->d_name.len + 1;
7207078187aSMiklos Szeredi 	args.in.args[2].value = newent->d_name.name;
7217078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
7229e6268dbSMiklos Szeredi 	if (!err) {
72308b63307SMiklos Szeredi 		/* ctime changes */
72408b63307SMiklos Szeredi 		fuse_invalidate_attr(oldent->d_inode);
72531f3267bSMaxim Patlasov 		fuse_update_ctime(oldent->d_inode);
72608b63307SMiklos Szeredi 
7271560c974SMiklos Szeredi 		if (flags & RENAME_EXCHANGE) {
7281560c974SMiklos Szeredi 			fuse_invalidate_attr(newent->d_inode);
7291560c974SMiklos Szeredi 			fuse_update_ctime(newent->d_inode);
7301560c974SMiklos Szeredi 		}
7311560c974SMiklos Szeredi 
7329e6268dbSMiklos Szeredi 		fuse_invalidate_attr(olddir);
7339e6268dbSMiklos Szeredi 		if (olddir != newdir)
7349e6268dbSMiklos Szeredi 			fuse_invalidate_attr(newdir);
7358cbdf1e6SMiklos Szeredi 
7368cbdf1e6SMiklos Szeredi 		/* newent will end up negative */
7371560c974SMiklos Szeredi 		if (!(flags & RENAME_EXCHANGE) && newent->d_inode) {
7385219f346SMiklos Szeredi 			fuse_invalidate_attr(newent->d_inode);
7398cbdf1e6SMiklos Szeredi 			fuse_invalidate_entry_cache(newent);
74031f3267bSMaxim Patlasov 			fuse_update_ctime(newent->d_inode);
7415219f346SMiklos Szeredi 		}
7429e6268dbSMiklos Szeredi 	} else if (err == -EINTR) {
7439e6268dbSMiklos Szeredi 		/* If request was interrupted, DEITY only knows if the
7449e6268dbSMiklos Szeredi 		   rename actually took place.  If the invalidation
7459e6268dbSMiklos Szeredi 		   fails (e.g. some process has CWD under the renamed
7469e6268dbSMiklos Szeredi 		   directory), then there can be inconsistency between
7479e6268dbSMiklos Szeredi 		   the dcache and the real filesystem.  Tough luck. */
7489e6268dbSMiklos Szeredi 		fuse_invalidate_entry(oldent);
7499e6268dbSMiklos Szeredi 		if (newent->d_inode)
7509e6268dbSMiklos Szeredi 			fuse_invalidate_entry(newent);
7519e6268dbSMiklos Szeredi 	}
7529e6268dbSMiklos Szeredi 
7539e6268dbSMiklos Szeredi 	return err;
7549e6268dbSMiklos Szeredi }
7559e6268dbSMiklos Szeredi 
7561560c974SMiklos Szeredi static int fuse_rename2(struct inode *olddir, struct dentry *oldent,
7571560c974SMiklos Szeredi 			struct inode *newdir, struct dentry *newent,
7581560c974SMiklos Szeredi 			unsigned int flags)
7591560c974SMiklos Szeredi {
7601560c974SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(olddir);
7611560c974SMiklos Szeredi 	int err;
7621560c974SMiklos Szeredi 
7631560c974SMiklos Szeredi 	if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE))
7641560c974SMiklos Szeredi 		return -EINVAL;
7651560c974SMiklos Szeredi 
7664237ba43SMiklos Szeredi 	if (flags) {
7671560c974SMiklos Szeredi 		if (fc->no_rename2 || fc->minor < 23)
7681560c974SMiklos Szeredi 			return -EINVAL;
7691560c974SMiklos Szeredi 
7701560c974SMiklos Szeredi 		err = fuse_rename_common(olddir, oldent, newdir, newent, flags,
7714237ba43SMiklos Szeredi 					 FUSE_RENAME2,
7724237ba43SMiklos Szeredi 					 sizeof(struct fuse_rename2_in));
7731560c974SMiklos Szeredi 		if (err == -ENOSYS) {
7741560c974SMiklos Szeredi 			fc->no_rename2 = 1;
7751560c974SMiklos Szeredi 			err = -EINVAL;
7761560c974SMiklos Szeredi 		}
7774237ba43SMiklos Szeredi 	} else {
7784237ba43SMiklos Szeredi 		err = fuse_rename_common(olddir, oldent, newdir, newent, 0,
7794237ba43SMiklos Szeredi 					 FUSE_RENAME,
7804237ba43SMiklos Szeredi 					 sizeof(struct fuse_rename_in));
7814237ba43SMiklos Szeredi 	}
7821560c974SMiklos Szeredi 
7834237ba43SMiklos Szeredi 	return err;
7844237ba43SMiklos Szeredi }
7854237ba43SMiklos Szeredi 
7869e6268dbSMiklos Szeredi static int fuse_link(struct dentry *entry, struct inode *newdir,
7879e6268dbSMiklos Szeredi 		     struct dentry *newent)
7889e6268dbSMiklos Szeredi {
7899e6268dbSMiklos Szeredi 	int err;
7909e6268dbSMiklos Szeredi 	struct fuse_link_in inarg;
7919e6268dbSMiklos Szeredi 	struct inode *inode = entry->d_inode;
7929e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
7937078187aSMiklos Szeredi 	FUSE_ARGS(args);
7949e6268dbSMiklos Szeredi 
7959e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
7969e6268dbSMiklos Szeredi 	inarg.oldnodeid = get_node_id(inode);
7977078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_LINK;
7987078187aSMiklos Szeredi 	args.in.numargs = 2;
7997078187aSMiklos Szeredi 	args.in.args[0].size = sizeof(inarg);
8007078187aSMiklos Szeredi 	args.in.args[0].value = &inarg;
8017078187aSMiklos Szeredi 	args.in.args[1].size = newent->d_name.len + 1;
8027078187aSMiklos Szeredi 	args.in.args[1].value = newent->d_name.name;
8037078187aSMiklos Szeredi 	err = create_new_entry(fc, &args, newdir, newent, inode->i_mode);
8049e6268dbSMiklos Szeredi 	/* Contrary to "normal" filesystems it can happen that link
8059e6268dbSMiklos Szeredi 	   makes two "logical" inodes point to the same "physical"
8069e6268dbSMiklos Szeredi 	   inode.  We invalidate the attributes of the old one, so it
8079e6268dbSMiklos Szeredi 	   will reflect changes in the backing inode (link count,
8089e6268dbSMiklos Szeredi 	   etc.)
8099e6268dbSMiklos Szeredi 	*/
810ac45d613SMiklos Szeredi 	if (!err) {
811ac45d613SMiklos Szeredi 		struct fuse_inode *fi = get_fuse_inode(inode);
812ac45d613SMiklos Szeredi 
813ac45d613SMiklos Szeredi 		spin_lock(&fc->lock);
814ac45d613SMiklos Szeredi 		fi->attr_version = ++fc->attr_version;
815ac45d613SMiklos Szeredi 		inc_nlink(inode);
816ac45d613SMiklos Szeredi 		spin_unlock(&fc->lock);
8179e6268dbSMiklos Szeredi 		fuse_invalidate_attr(inode);
81831f3267bSMaxim Patlasov 		fuse_update_ctime(inode);
819ac45d613SMiklos Szeredi 	} else if (err == -EINTR) {
820ac45d613SMiklos Szeredi 		fuse_invalidate_attr(inode);
821ac45d613SMiklos Szeredi 	}
8229e6268dbSMiklos Szeredi 	return err;
8239e6268dbSMiklos Szeredi }
8249e6268dbSMiklos Szeredi 
8251fb69e78SMiklos Szeredi static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
8261fb69e78SMiklos Szeredi 			  struct kstat *stat)
8271fb69e78SMiklos Szeredi {
828203627bbSMiklos Szeredi 	unsigned int blkbits;
8298373200bSPavel Emelyanov 	struct fuse_conn *fc = get_fuse_conn(inode);
8308373200bSPavel Emelyanov 
8318373200bSPavel Emelyanov 	/* see the comment in fuse_change_attributes() */
832b0aa7606SMaxim Patlasov 	if (fc->writeback_cache && S_ISREG(inode->i_mode)) {
8338373200bSPavel Emelyanov 		attr->size = i_size_read(inode);
834b0aa7606SMaxim Patlasov 		attr->mtime = inode->i_mtime.tv_sec;
835b0aa7606SMaxim Patlasov 		attr->mtimensec = inode->i_mtime.tv_nsec;
83631f3267bSMaxim Patlasov 		attr->ctime = inode->i_ctime.tv_sec;
83731f3267bSMaxim Patlasov 		attr->ctimensec = inode->i_ctime.tv_nsec;
838b0aa7606SMaxim Patlasov 	}
839203627bbSMiklos Szeredi 
8401fb69e78SMiklos Szeredi 	stat->dev = inode->i_sb->s_dev;
8411fb69e78SMiklos Szeredi 	stat->ino = attr->ino;
8421fb69e78SMiklos Szeredi 	stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
8431fb69e78SMiklos Szeredi 	stat->nlink = attr->nlink;
844499dcf20SEric W. Biederman 	stat->uid = make_kuid(&init_user_ns, attr->uid);
845499dcf20SEric W. Biederman 	stat->gid = make_kgid(&init_user_ns, attr->gid);
8461fb69e78SMiklos Szeredi 	stat->rdev = inode->i_rdev;
8471fb69e78SMiklos Szeredi 	stat->atime.tv_sec = attr->atime;
8481fb69e78SMiklos Szeredi 	stat->atime.tv_nsec = attr->atimensec;
8491fb69e78SMiklos Szeredi 	stat->mtime.tv_sec = attr->mtime;
8501fb69e78SMiklos Szeredi 	stat->mtime.tv_nsec = attr->mtimensec;
8511fb69e78SMiklos Szeredi 	stat->ctime.tv_sec = attr->ctime;
8521fb69e78SMiklos Szeredi 	stat->ctime.tv_nsec = attr->ctimensec;
8531fb69e78SMiklos Szeredi 	stat->size = attr->size;
8541fb69e78SMiklos Szeredi 	stat->blocks = attr->blocks;
855203627bbSMiklos Szeredi 
856203627bbSMiklos Szeredi 	if (attr->blksize != 0)
857203627bbSMiklos Szeredi 		blkbits = ilog2(attr->blksize);
858203627bbSMiklos Szeredi 	else
859203627bbSMiklos Szeredi 		blkbits = inode->i_sb->s_blocksize_bits;
860203627bbSMiklos Szeredi 
861203627bbSMiklos Szeredi 	stat->blksize = 1 << blkbits;
8621fb69e78SMiklos Szeredi }
8631fb69e78SMiklos Szeredi 
864c79e322fSMiklos Szeredi static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
865c79e322fSMiklos Szeredi 			   struct file *file)
866e5e5558eSMiklos Szeredi {
867e5e5558eSMiklos Szeredi 	int err;
868c79e322fSMiklos Szeredi 	struct fuse_getattr_in inarg;
869c79e322fSMiklos Szeredi 	struct fuse_attr_out outarg;
870e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
8717078187aSMiklos Szeredi 	FUSE_ARGS(args);
8721fb69e78SMiklos Szeredi 	u64 attr_version;
8731fb69e78SMiklos Szeredi 
8747dca9fd3SMiklos Szeredi 	attr_version = fuse_get_attr_version(fc);
8751fb69e78SMiklos Szeredi 
876c79e322fSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
8770e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
878c79e322fSMiklos Szeredi 	/* Directories have separate file-handle space */
879c79e322fSMiklos Szeredi 	if (file && S_ISREG(inode->i_mode)) {
880c79e322fSMiklos Szeredi 		struct fuse_file *ff = file->private_data;
881c79e322fSMiklos Szeredi 
882c79e322fSMiklos Szeredi 		inarg.getattr_flags |= FUSE_GETATTR_FH;
883c79e322fSMiklos Szeredi 		inarg.fh = ff->fh;
884c79e322fSMiklos Szeredi 	}
8857078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_GETATTR;
8867078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(inode);
8877078187aSMiklos Szeredi 	args.in.numargs = 1;
8887078187aSMiklos Szeredi 	args.in.args[0].size = sizeof(inarg);
8897078187aSMiklos Szeredi 	args.in.args[0].value = &inarg;
8907078187aSMiklos Szeredi 	args.out.numargs = 1;
8917078187aSMiklos Szeredi 	args.out.args[0].size = sizeof(outarg);
8927078187aSMiklos Szeredi 	args.out.args[0].value = &outarg;
8937078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
894e5e5558eSMiklos Szeredi 	if (!err) {
895c79e322fSMiklos Szeredi 		if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
896e5e5558eSMiklos Szeredi 			make_bad_inode(inode);
897e5e5558eSMiklos Szeredi 			err = -EIO;
898e5e5558eSMiklos Szeredi 		} else {
899c79e322fSMiklos Szeredi 			fuse_change_attributes(inode, &outarg.attr,
900c79e322fSMiklos Szeredi 					       attr_timeout(&outarg),
9011fb69e78SMiklos Szeredi 					       attr_version);
9021fb69e78SMiklos Szeredi 			if (stat)
903c79e322fSMiklos Szeredi 				fuse_fillattr(inode, &outarg.attr, stat);
904e5e5558eSMiklos Szeredi 		}
905e5e5558eSMiklos Szeredi 	}
906e5e5558eSMiklos Szeredi 	return err;
907e5e5558eSMiklos Szeredi }
908e5e5558eSMiklos Szeredi 
909bcb4be80SMiklos Szeredi int fuse_update_attributes(struct inode *inode, struct kstat *stat,
910bcb4be80SMiklos Szeredi 			   struct file *file, bool *refreshed)
911bcb4be80SMiklos Szeredi {
912bcb4be80SMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
913bcb4be80SMiklos Szeredi 	int err;
914bcb4be80SMiklos Szeredi 	bool r;
915bcb4be80SMiklos Szeredi 
916126b9d43SMiklos Szeredi 	if (time_before64(fi->i_time, get_jiffies_64())) {
917bcb4be80SMiklos Szeredi 		r = true;
918bcb4be80SMiklos Szeredi 		err = fuse_do_getattr(inode, stat, file);
919bcb4be80SMiklos Szeredi 	} else {
920bcb4be80SMiklos Szeredi 		r = false;
921bcb4be80SMiklos Szeredi 		err = 0;
922bcb4be80SMiklos Szeredi 		if (stat) {
923bcb4be80SMiklos Szeredi 			generic_fillattr(inode, stat);
924bcb4be80SMiklos Szeredi 			stat->mode = fi->orig_i_mode;
92545c72cd7SPavel Shilovsky 			stat->ino = fi->orig_ino;
926bcb4be80SMiklos Szeredi 		}
927bcb4be80SMiklos Szeredi 	}
928bcb4be80SMiklos Szeredi 
929bcb4be80SMiklos Szeredi 	if (refreshed != NULL)
930bcb4be80SMiklos Szeredi 		*refreshed = r;
931bcb4be80SMiklos Szeredi 
932bcb4be80SMiklos Szeredi 	return err;
933bcb4be80SMiklos Szeredi }
934bcb4be80SMiklos Szeredi 
9353b463ae0SJohn Muir int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid,
936451d0f59SJohn Muir 			     u64 child_nodeid, struct qstr *name)
9373b463ae0SJohn Muir {
9383b463ae0SJohn Muir 	int err = -ENOTDIR;
9393b463ae0SJohn Muir 	struct inode *parent;
9403b463ae0SJohn Muir 	struct dentry *dir;
9413b463ae0SJohn Muir 	struct dentry *entry;
9423b463ae0SJohn Muir 
9433b463ae0SJohn Muir 	parent = ilookup5(sb, parent_nodeid, fuse_inode_eq, &parent_nodeid);
9443b463ae0SJohn Muir 	if (!parent)
9453b463ae0SJohn Muir 		return -ENOENT;
9463b463ae0SJohn Muir 
9473b463ae0SJohn Muir 	mutex_lock(&parent->i_mutex);
9483b463ae0SJohn Muir 	if (!S_ISDIR(parent->i_mode))
9493b463ae0SJohn Muir 		goto unlock;
9503b463ae0SJohn Muir 
9513b463ae0SJohn Muir 	err = -ENOENT;
9523b463ae0SJohn Muir 	dir = d_find_alias(parent);
9533b463ae0SJohn Muir 	if (!dir)
9543b463ae0SJohn Muir 		goto unlock;
9553b463ae0SJohn Muir 
9563b463ae0SJohn Muir 	entry = d_lookup(dir, name);
9573b463ae0SJohn Muir 	dput(dir);
9583b463ae0SJohn Muir 	if (!entry)
9593b463ae0SJohn Muir 		goto unlock;
9603b463ae0SJohn Muir 
9613b463ae0SJohn Muir 	fuse_invalidate_attr(parent);
9623b463ae0SJohn Muir 	fuse_invalidate_entry(entry);
963451d0f59SJohn Muir 
964451d0f59SJohn Muir 	if (child_nodeid != 0 && entry->d_inode) {
965451d0f59SJohn Muir 		mutex_lock(&entry->d_inode->i_mutex);
966451d0f59SJohn Muir 		if (get_node_id(entry->d_inode) != child_nodeid) {
967451d0f59SJohn Muir 			err = -ENOENT;
968451d0f59SJohn Muir 			goto badentry;
969451d0f59SJohn Muir 		}
970451d0f59SJohn Muir 		if (d_mountpoint(entry)) {
971451d0f59SJohn Muir 			err = -EBUSY;
972451d0f59SJohn Muir 			goto badentry;
973451d0f59SJohn Muir 		}
974*e36cb0b8SDavid Howells 		if (d_is_dir(entry)) {
975451d0f59SJohn Muir 			shrink_dcache_parent(entry);
976451d0f59SJohn Muir 			if (!simple_empty(entry)) {
977451d0f59SJohn Muir 				err = -ENOTEMPTY;
978451d0f59SJohn Muir 				goto badentry;
979451d0f59SJohn Muir 			}
980451d0f59SJohn Muir 			entry->d_inode->i_flags |= S_DEAD;
981451d0f59SJohn Muir 		}
982451d0f59SJohn Muir 		dont_mount(entry);
983451d0f59SJohn Muir 		clear_nlink(entry->d_inode);
9843b463ae0SJohn Muir 		err = 0;
985451d0f59SJohn Muir  badentry:
986451d0f59SJohn Muir 		mutex_unlock(&entry->d_inode->i_mutex);
987451d0f59SJohn Muir 		if (!err)
988451d0f59SJohn Muir 			d_delete(entry);
989451d0f59SJohn Muir 	} else {
990451d0f59SJohn Muir 		err = 0;
991451d0f59SJohn Muir 	}
992451d0f59SJohn Muir 	dput(entry);
9933b463ae0SJohn Muir 
9943b463ae0SJohn Muir  unlock:
9953b463ae0SJohn Muir 	mutex_unlock(&parent->i_mutex);
9963b463ae0SJohn Muir 	iput(parent);
9973b463ae0SJohn Muir 	return err;
9983b463ae0SJohn Muir }
9993b463ae0SJohn Muir 
100087729a55SMiklos Szeredi /*
100187729a55SMiklos Szeredi  * Calling into a user-controlled filesystem gives the filesystem
1002c2132c1bSAnatol Pomozov  * daemon ptrace-like capabilities over the current process.  This
100387729a55SMiklos Szeredi  * means, that the filesystem daemon is able to record the exact
100487729a55SMiklos Szeredi  * filesystem operations performed, and can also control the behavior
100587729a55SMiklos Szeredi  * of the requester process in otherwise impossible ways.  For example
100687729a55SMiklos Szeredi  * it can delay the operation for arbitrary length of time allowing
100787729a55SMiklos Szeredi  * DoS against the requester.
100887729a55SMiklos Szeredi  *
100987729a55SMiklos Szeredi  * For this reason only those processes can call into the filesystem,
101087729a55SMiklos Szeredi  * for which the owner of the mount has ptrace privilege.  This
101187729a55SMiklos Szeredi  * excludes processes started by other users, suid or sgid processes.
101287729a55SMiklos Szeredi  */
1013c2132c1bSAnatol Pomozov int fuse_allow_current_process(struct fuse_conn *fc)
101487729a55SMiklos Szeredi {
1015c69e8d9cSDavid Howells 	const struct cred *cred;
1016c69e8d9cSDavid Howells 
101787729a55SMiklos Szeredi 	if (fc->flags & FUSE_ALLOW_OTHER)
101887729a55SMiklos Szeredi 		return 1;
101987729a55SMiklos Szeredi 
1020c2132c1bSAnatol Pomozov 	cred = current_cred();
1021499dcf20SEric W. Biederman 	if (uid_eq(cred->euid, fc->user_id) &&
1022499dcf20SEric W. Biederman 	    uid_eq(cred->suid, fc->user_id) &&
1023499dcf20SEric W. Biederman 	    uid_eq(cred->uid,  fc->user_id) &&
1024499dcf20SEric W. Biederman 	    gid_eq(cred->egid, fc->group_id) &&
1025499dcf20SEric W. Biederman 	    gid_eq(cred->sgid, fc->group_id) &&
1026499dcf20SEric W. Biederman 	    gid_eq(cred->gid,  fc->group_id))
1027c2132c1bSAnatol Pomozov 		return 1;
102887729a55SMiklos Szeredi 
1029c2132c1bSAnatol Pomozov 	return 0;
103087729a55SMiklos Szeredi }
103187729a55SMiklos Szeredi 
103231d40d74SMiklos Szeredi static int fuse_access(struct inode *inode, int mask)
103331d40d74SMiklos Szeredi {
103431d40d74SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
10357078187aSMiklos Szeredi 	FUSE_ARGS(args);
103631d40d74SMiklos Szeredi 	struct fuse_access_in inarg;
103731d40d74SMiklos Szeredi 	int err;
103831d40d74SMiklos Szeredi 
1039698fa1d1SMiklos Szeredi 	BUG_ON(mask & MAY_NOT_BLOCK);
1040698fa1d1SMiklos Szeredi 
104131d40d74SMiklos Szeredi 	if (fc->no_access)
104231d40d74SMiklos Szeredi 		return 0;
104331d40d74SMiklos Szeredi 
104431d40d74SMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
1045e6305c43SAl Viro 	inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC);
10467078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_ACCESS;
10477078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(inode);
10487078187aSMiklos Szeredi 	args.in.numargs = 1;
10497078187aSMiklos Szeredi 	args.in.args[0].size = sizeof(inarg);
10507078187aSMiklos Szeredi 	args.in.args[0].value = &inarg;
10517078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
105231d40d74SMiklos Szeredi 	if (err == -ENOSYS) {
105331d40d74SMiklos Szeredi 		fc->no_access = 1;
105431d40d74SMiklos Szeredi 		err = 0;
105531d40d74SMiklos Szeredi 	}
105631d40d74SMiklos Szeredi 	return err;
105731d40d74SMiklos Szeredi }
105831d40d74SMiklos Szeredi 
105910556cb2SAl Viro static int fuse_perm_getattr(struct inode *inode, int mask)
106019690ddbSMiklos Szeredi {
106110556cb2SAl Viro 	if (mask & MAY_NOT_BLOCK)
106219690ddbSMiklos Szeredi 		return -ECHILD;
106319690ddbSMiklos Szeredi 
106419690ddbSMiklos Szeredi 	return fuse_do_getattr(inode, NULL, NULL);
106519690ddbSMiklos Szeredi }
106619690ddbSMiklos Szeredi 
10676f9f1180SMiklos Szeredi /*
10686f9f1180SMiklos Szeredi  * Check permission.  The two basic access models of FUSE are:
10696f9f1180SMiklos Szeredi  *
10706f9f1180SMiklos Szeredi  * 1) Local access checking ('default_permissions' mount option) based
10716f9f1180SMiklos Szeredi  * on file mode.  This is the plain old disk filesystem permission
10726f9f1180SMiklos Szeredi  * modell.
10736f9f1180SMiklos Szeredi  *
10746f9f1180SMiklos Szeredi  * 2) "Remote" access checking, where server is responsible for
10756f9f1180SMiklos Szeredi  * checking permission in each inode operation.  An exception to this
10766f9f1180SMiklos Szeredi  * is if ->permission() was invoked from sys_access() in which case an
10776f9f1180SMiklos Szeredi  * access request is sent.  Execute permission is still checked
10786f9f1180SMiklos Szeredi  * locally based on file mode.
10796f9f1180SMiklos Szeredi  */
108010556cb2SAl Viro static int fuse_permission(struct inode *inode, int mask)
1081e5e5558eSMiklos Szeredi {
1082e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1083244f6385SMiklos Szeredi 	bool refreshed = false;
1084244f6385SMiklos Szeredi 	int err = 0;
1085e5e5558eSMiklos Szeredi 
1086c2132c1bSAnatol Pomozov 	if (!fuse_allow_current_process(fc))
1087e5e5558eSMiklos Szeredi 		return -EACCES;
1088244f6385SMiklos Szeredi 
1089244f6385SMiklos Szeredi 	/*
1090e8e96157SMiklos Szeredi 	 * If attributes are needed, refresh them before proceeding
1091244f6385SMiklos Szeredi 	 */
1092e8e96157SMiklos Szeredi 	if ((fc->flags & FUSE_DEFAULT_PERMISSIONS) ||
1093e8e96157SMiklos Szeredi 	    ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
109419690ddbSMiklos Szeredi 		struct fuse_inode *fi = get_fuse_inode(inode);
109519690ddbSMiklos Szeredi 
1096126b9d43SMiklos Szeredi 		if (time_before64(fi->i_time, get_jiffies_64())) {
109719690ddbSMiklos Szeredi 			refreshed = true;
109819690ddbSMiklos Szeredi 
109910556cb2SAl Viro 			err = fuse_perm_getattr(inode, mask);
1100244f6385SMiklos Szeredi 			if (err)
1101244f6385SMiklos Szeredi 				return err;
11021fb69e78SMiklos Szeredi 		}
110319690ddbSMiklos Szeredi 	}
1104244f6385SMiklos Szeredi 
1105244f6385SMiklos Szeredi 	if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
11062830ba7fSAl Viro 		err = generic_permission(inode, mask);
11071e9a4ed9SMiklos Szeredi 
11081e9a4ed9SMiklos Szeredi 		/* If permission is denied, try to refresh file
11091e9a4ed9SMiklos Szeredi 		   attributes.  This is also needed, because the root
11101e9a4ed9SMiklos Szeredi 		   node will at first have no permissions */
1111244f6385SMiklos Szeredi 		if (err == -EACCES && !refreshed) {
111210556cb2SAl Viro 			err = fuse_perm_getattr(inode, mask);
11131e9a4ed9SMiklos Szeredi 			if (!err)
11142830ba7fSAl Viro 				err = generic_permission(inode, mask);
11151e9a4ed9SMiklos Szeredi 		}
11161e9a4ed9SMiklos Szeredi 
11176f9f1180SMiklos Szeredi 		/* Note: the opposite of the above test does not
11186f9f1180SMiklos Szeredi 		   exist.  So if permissions are revoked this won't be
11196f9f1180SMiklos Szeredi 		   noticed immediately, only after the attribute
11206f9f1180SMiklos Szeredi 		   timeout has expired */
11219cfcac81SEric Paris 	} else if (mask & (MAY_ACCESS | MAY_CHDIR)) {
1122e8e96157SMiklos Szeredi 		err = fuse_access(inode, mask);
1123e8e96157SMiklos Szeredi 	} else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
1124e8e96157SMiklos Szeredi 		if (!(inode->i_mode & S_IXUGO)) {
1125e8e96157SMiklos Szeredi 			if (refreshed)
1126e5e5558eSMiklos Szeredi 				return -EACCES;
112731d40d74SMiklos Szeredi 
112810556cb2SAl Viro 			err = fuse_perm_getattr(inode, mask);
1129e8e96157SMiklos Szeredi 			if (!err && !(inode->i_mode & S_IXUGO))
1130e8e96157SMiklos Szeredi 				return -EACCES;
1131e8e96157SMiklos Szeredi 		}
1132e5e5558eSMiklos Szeredi 	}
1133244f6385SMiklos Szeredi 	return err;
1134e5e5558eSMiklos Szeredi }
1135e5e5558eSMiklos Szeredi 
1136e5e5558eSMiklos Szeredi static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
11378d3af7f3SAl Viro 			 struct dir_context *ctx)
1138e5e5558eSMiklos Szeredi {
1139e5e5558eSMiklos Szeredi 	while (nbytes >= FUSE_NAME_OFFSET) {
1140e5e5558eSMiklos Szeredi 		struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
1141e5e5558eSMiklos Szeredi 		size_t reclen = FUSE_DIRENT_SIZE(dirent);
1142e5e5558eSMiklos Szeredi 		if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
1143e5e5558eSMiklos Szeredi 			return -EIO;
1144e5e5558eSMiklos Szeredi 		if (reclen > nbytes)
1145e5e5558eSMiklos Szeredi 			break;
1146efeb9e60SMiklos Szeredi 		if (memchr(dirent->name, '/', dirent->namelen) != NULL)
1147efeb9e60SMiklos Szeredi 			return -EIO;
1148e5e5558eSMiklos Szeredi 
11498d3af7f3SAl Viro 		if (!dir_emit(ctx, dirent->name, dirent->namelen,
11508d3af7f3SAl Viro 			       dirent->ino, dirent->type))
1151e5e5558eSMiklos Szeredi 			break;
1152e5e5558eSMiklos Szeredi 
1153e5e5558eSMiklos Szeredi 		buf += reclen;
1154e5e5558eSMiklos Szeredi 		nbytes -= reclen;
11558d3af7f3SAl Viro 		ctx->pos = dirent->off;
1156e5e5558eSMiklos Szeredi 	}
1157e5e5558eSMiklos Szeredi 
1158e5e5558eSMiklos Szeredi 	return 0;
1159e5e5558eSMiklos Szeredi }
1160e5e5558eSMiklos Szeredi 
11610b05b183SAnand V. Avati static int fuse_direntplus_link(struct file *file,
11620b05b183SAnand V. Avati 				struct fuse_direntplus *direntplus,
11630b05b183SAnand V. Avati 				u64 attr_version)
11640b05b183SAnand V. Avati {
11650b05b183SAnand V. Avati 	int err;
11660b05b183SAnand V. Avati 	struct fuse_entry_out *o = &direntplus->entry_out;
11670b05b183SAnand V. Avati 	struct fuse_dirent *dirent = &direntplus->dirent;
11680b05b183SAnand V. Avati 	struct dentry *parent = file->f_path.dentry;
11690b05b183SAnand V. Avati 	struct qstr name = QSTR_INIT(dirent->name, dirent->namelen);
11700b05b183SAnand V. Avati 	struct dentry *dentry;
11710b05b183SAnand V. Avati 	struct dentry *alias;
11720b05b183SAnand V. Avati 	struct inode *dir = parent->d_inode;
11730b05b183SAnand V. Avati 	struct fuse_conn *fc;
11740b05b183SAnand V. Avati 	struct inode *inode;
11750b05b183SAnand V. Avati 
11760b05b183SAnand V. Avati 	if (!o->nodeid) {
11770b05b183SAnand V. Avati 		/*
11780b05b183SAnand V. Avati 		 * Unlike in the case of fuse_lookup, zero nodeid does not mean
11790b05b183SAnand V. Avati 		 * ENOENT. Instead, it only means the userspace filesystem did
11800b05b183SAnand V. Avati 		 * not want to return attributes/handle for this entry.
11810b05b183SAnand V. Avati 		 *
11820b05b183SAnand V. Avati 		 * So do nothing.
11830b05b183SAnand V. Avati 		 */
11840b05b183SAnand V. Avati 		return 0;
11850b05b183SAnand V. Avati 	}
11860b05b183SAnand V. Avati 
11870b05b183SAnand V. Avati 	if (name.name[0] == '.') {
11880b05b183SAnand V. Avati 		/*
11890b05b183SAnand V. Avati 		 * We could potentially refresh the attributes of the directory
11900b05b183SAnand V. Avati 		 * and its parent?
11910b05b183SAnand V. Avati 		 */
11920b05b183SAnand V. Avati 		if (name.len == 1)
11930b05b183SAnand V. Avati 			return 0;
11940b05b183SAnand V. Avati 		if (name.name[1] == '.' && name.len == 2)
11950b05b183SAnand V. Avati 			return 0;
11960b05b183SAnand V. Avati 	}
1197a28ef45cSMiklos Szeredi 
1198a28ef45cSMiklos Szeredi 	if (invalid_nodeid(o->nodeid))
1199a28ef45cSMiklos Szeredi 		return -EIO;
1200a28ef45cSMiklos Szeredi 	if (!fuse_valid_type(o->attr.mode))
1201a28ef45cSMiklos Szeredi 		return -EIO;
1202a28ef45cSMiklos Szeredi 
12030b05b183SAnand V. Avati 	fc = get_fuse_conn(dir);
12040b05b183SAnand V. Avati 
12050b05b183SAnand V. Avati 	name.hash = full_name_hash(name.name, name.len);
12060b05b183SAnand V. Avati 	dentry = d_lookup(parent, &name);
120753ce9a33SNiels de Vos 	if (dentry) {
12080b05b183SAnand V. Avati 		inode = dentry->d_inode;
120953ce9a33SNiels de Vos 		if (!inode) {
121053ce9a33SNiels de Vos 			d_drop(dentry);
1211a28ef45cSMiklos Szeredi 		} else if (get_node_id(inode) != o->nodeid ||
1212a28ef45cSMiklos Szeredi 			   ((o->attr.mode ^ inode->i_mode) & S_IFMT)) {
12135542aa2fSEric W. Biederman 			d_invalidate(dentry);
1214a28ef45cSMiklos Szeredi 		} else if (is_bad_inode(inode)) {
1215a28ef45cSMiklos Szeredi 			err = -EIO;
1216a28ef45cSMiklos Szeredi 			goto out;
121753ce9a33SNiels de Vos 		} else {
12180b05b183SAnand V. Avati 			struct fuse_inode *fi;
12190b05b183SAnand V. Avati 			fi = get_fuse_inode(inode);
12200b05b183SAnand V. Avati 			spin_lock(&fc->lock);
12210b05b183SAnand V. Avati 			fi->nlookup++;
12220b05b183SAnand V. Avati 			spin_unlock(&fc->lock);
12230b05b183SAnand V. Avati 
1224fa2b7213SMiklos Szeredi 			fuse_change_attributes(inode, &o->attr,
1225fa2b7213SMiklos Szeredi 					       entry_attr_timeout(o),
1226fa2b7213SMiklos Szeredi 					       attr_version);
1227fa2b7213SMiklos Szeredi 
12280b05b183SAnand V. Avati 			/*
12290b05b183SAnand V. Avati 			 * The other branch to 'found' comes via fuse_iget()
12300b05b183SAnand V. Avati 			 * which bumps nlookup inside
12310b05b183SAnand V. Avati 			 */
12320b05b183SAnand V. Avati 			goto found;
12330b05b183SAnand V. Avati 		}
12340b05b183SAnand V. Avati 		dput(dentry);
12350b05b183SAnand V. Avati 	}
12360b05b183SAnand V. Avati 
12370b05b183SAnand V. Avati 	dentry = d_alloc(parent, &name);
12380b05b183SAnand V. Avati 	err = -ENOMEM;
12390b05b183SAnand V. Avati 	if (!dentry)
12400b05b183SAnand V. Avati 		goto out;
12410b05b183SAnand V. Avati 
12420b05b183SAnand V. Avati 	inode = fuse_iget(dir->i_sb, o->nodeid, o->generation,
12430b05b183SAnand V. Avati 			  &o->attr, entry_attr_timeout(o), attr_version);
12440b05b183SAnand V. Avati 	if (!inode)
12450b05b183SAnand V. Avati 		goto out;
12460b05b183SAnand V. Avati 
124741d28bcaSAl Viro 	alias = d_splice_alias(inode, dentry);
12480b05b183SAnand V. Avati 	err = PTR_ERR(alias);
12495835f339SMiklos Szeredi 	if (IS_ERR(alias))
12500b05b183SAnand V. Avati 		goto out;
12512914941eSMiklos Szeredi 
12520b05b183SAnand V. Avati 	if (alias) {
12530b05b183SAnand V. Avati 		dput(dentry);
12540b05b183SAnand V. Avati 		dentry = alias;
12550b05b183SAnand V. Avati 	}
12560b05b183SAnand V. Avati 
12570b05b183SAnand V. Avati found:
12586314efeeSMiklos Szeredi 	if (fc->readdirplus_auto)
12596314efeeSMiklos Szeredi 		set_bit(FUSE_I_INIT_RDPLUS, &get_fuse_inode(inode)->state);
12600b05b183SAnand V. Avati 	fuse_change_entry_timeout(dentry, o);
12610b05b183SAnand V. Avati 
12620b05b183SAnand V. Avati 	err = 0;
12630b05b183SAnand V. Avati out:
12640b05b183SAnand V. Avati 	dput(dentry);
12650b05b183SAnand V. Avati 	return err;
12660b05b183SAnand V. Avati }
12670b05b183SAnand V. Avati 
12680b05b183SAnand V. Avati static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file,
12698d3af7f3SAl Viro 			     struct dir_context *ctx, u64 attr_version)
12700b05b183SAnand V. Avati {
12710b05b183SAnand V. Avati 	struct fuse_direntplus *direntplus;
12720b05b183SAnand V. Avati 	struct fuse_dirent *dirent;
12730b05b183SAnand V. Avati 	size_t reclen;
12740b05b183SAnand V. Avati 	int over = 0;
12750b05b183SAnand V. Avati 	int ret;
12760b05b183SAnand V. Avati 
12770b05b183SAnand V. Avati 	while (nbytes >= FUSE_NAME_OFFSET_DIRENTPLUS) {
12780b05b183SAnand V. Avati 		direntplus = (struct fuse_direntplus *) buf;
12790b05b183SAnand V. Avati 		dirent = &direntplus->dirent;
12800b05b183SAnand V. Avati 		reclen = FUSE_DIRENTPLUS_SIZE(direntplus);
12810b05b183SAnand V. Avati 
12820b05b183SAnand V. Avati 		if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
12830b05b183SAnand V. Avati 			return -EIO;
12840b05b183SAnand V. Avati 		if (reclen > nbytes)
12850b05b183SAnand V. Avati 			break;
1286efeb9e60SMiklos Szeredi 		if (memchr(dirent->name, '/', dirent->namelen) != NULL)
1287efeb9e60SMiklos Szeredi 			return -EIO;
12880b05b183SAnand V. Avati 
12890b05b183SAnand V. Avati 		if (!over) {
12900b05b183SAnand V. Avati 			/* We fill entries into dstbuf only as much as
12910b05b183SAnand V. Avati 			   it can hold. But we still continue iterating
12920b05b183SAnand V. Avati 			   over remaining entries to link them. If not,
12930b05b183SAnand V. Avati 			   we need to send a FORGET for each of those
12940b05b183SAnand V. Avati 			   which we did not link.
12950b05b183SAnand V. Avati 			*/
12968d3af7f3SAl Viro 			over = !dir_emit(ctx, dirent->name, dirent->namelen,
12978d3af7f3SAl Viro 				       dirent->ino, dirent->type);
12988d3af7f3SAl Viro 			ctx->pos = dirent->off;
12990b05b183SAnand V. Avati 		}
13000b05b183SAnand V. Avati 
13010b05b183SAnand V. Avati 		buf += reclen;
13020b05b183SAnand V. Avati 		nbytes -= reclen;
13030b05b183SAnand V. Avati 
13040b05b183SAnand V. Avati 		ret = fuse_direntplus_link(file, direntplus, attr_version);
13050b05b183SAnand V. Avati 		if (ret)
13060b05b183SAnand V. Avati 			fuse_force_forget(file, direntplus->entry_out.nodeid);
13070b05b183SAnand V. Avati 	}
13080b05b183SAnand V. Avati 
13090b05b183SAnand V. Avati 	return 0;
13100b05b183SAnand V. Avati }
13110b05b183SAnand V. Avati 
13128d3af7f3SAl Viro static int fuse_readdir(struct file *file, struct dir_context *ctx)
1313e5e5558eSMiklos Szeredi {
13144582a4abSFeng Shuo 	int plus, err;
131504730fefSMiklos Szeredi 	size_t nbytes;
131604730fefSMiklos Szeredi 	struct page *page;
1317496ad9aaSAl Viro 	struct inode *inode = file_inode(file);
131804730fefSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1319248d86e8SMiklos Szeredi 	struct fuse_req *req;
13200b05b183SAnand V. Avati 	u64 attr_version = 0;
1321248d86e8SMiklos Szeredi 
1322248d86e8SMiklos Szeredi 	if (is_bad_inode(inode))
1323248d86e8SMiklos Szeredi 		return -EIO;
1324248d86e8SMiklos Szeredi 
1325b111c8c0SMaxim Patlasov 	req = fuse_get_req(fc, 1);
1326ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1327ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
1328e5e5558eSMiklos Szeredi 
132904730fefSMiklos Szeredi 	page = alloc_page(GFP_KERNEL);
133004730fefSMiklos Szeredi 	if (!page) {
133104730fefSMiklos Szeredi 		fuse_put_request(fc, req);
1332e5e5558eSMiklos Szeredi 		return -ENOMEM;
133304730fefSMiklos Szeredi 	}
13344582a4abSFeng Shuo 
13358d3af7f3SAl Viro 	plus = fuse_use_readdirplus(inode, ctx);
1336f4975c67SMiklos Szeredi 	req->out.argpages = 1;
133704730fefSMiklos Szeredi 	req->num_pages = 1;
133804730fefSMiklos Szeredi 	req->pages[0] = page;
133985f40aecSMaxim Patlasov 	req->page_descs[0].length = PAGE_SIZE;
13404582a4abSFeng Shuo 	if (plus) {
13410b05b183SAnand V. Avati 		attr_version = fuse_get_attr_version(fc);
13428d3af7f3SAl Viro 		fuse_read_fill(req, file, ctx->pos, PAGE_SIZE,
13430b05b183SAnand V. Avati 			       FUSE_READDIRPLUS);
13440b05b183SAnand V. Avati 	} else {
13458d3af7f3SAl Viro 		fuse_read_fill(req, file, ctx->pos, PAGE_SIZE,
13460b05b183SAnand V. Avati 			       FUSE_READDIR);
13470b05b183SAnand V. Avati 	}
1348b93f858aSTejun Heo 	fuse_request_send(fc, req);
1349361b1eb5SMiklos Szeredi 	nbytes = req->out.args[0].size;
135004730fefSMiklos Szeredi 	err = req->out.h.error;
135104730fefSMiklos Szeredi 	fuse_put_request(fc, req);
13520b05b183SAnand V. Avati 	if (!err) {
13534582a4abSFeng Shuo 		if (plus) {
13540b05b183SAnand V. Avati 			err = parse_dirplusfile(page_address(page), nbytes,
13558d3af7f3SAl Viro 						file, ctx,
13560b05b183SAnand V. Avati 						attr_version);
13570b05b183SAnand V. Avati 		} else {
13580b05b183SAnand V. Avati 			err = parse_dirfile(page_address(page), nbytes, file,
13598d3af7f3SAl Viro 					    ctx);
13600b05b183SAnand V. Avati 		}
13610b05b183SAnand V. Avati 	}
1362e5e5558eSMiklos Szeredi 
136304730fefSMiklos Szeredi 	__free_page(page);
1364451418fcSAndrew Gallagher 	fuse_invalidate_atime(inode);
136504730fefSMiklos Szeredi 	return err;
1366e5e5558eSMiklos Szeredi }
1367e5e5558eSMiklos Szeredi 
1368e5e5558eSMiklos Szeredi static char *read_link(struct dentry *dentry)
1369e5e5558eSMiklos Szeredi {
1370e5e5558eSMiklos Szeredi 	struct inode *inode = dentry->d_inode;
1371e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
13727078187aSMiklos Szeredi 	FUSE_ARGS(args);
1373e5e5558eSMiklos Szeredi 	char *link;
13747078187aSMiklos Szeredi 	ssize_t ret;
1375e5e5558eSMiklos Szeredi 
1376e5e5558eSMiklos Szeredi 	link = (char *) __get_free_page(GFP_KERNEL);
13777078187aSMiklos Szeredi 	if (!link)
13787078187aSMiklos Szeredi 		return ERR_PTR(-ENOMEM);
13797078187aSMiklos Szeredi 
13807078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_READLINK;
13817078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(inode);
13827078187aSMiklos Szeredi 	args.out.argvar = 1;
13837078187aSMiklos Szeredi 	args.out.numargs = 1;
13847078187aSMiklos Szeredi 	args.out.args[0].size = PAGE_SIZE - 1;
13857078187aSMiklos Szeredi 	args.out.args[0].value = link;
13867078187aSMiklos Szeredi 	ret = fuse_simple_request(fc, &args);
13877078187aSMiklos Szeredi 	if (ret < 0) {
1388e5e5558eSMiklos Szeredi 		free_page((unsigned long) link);
13897078187aSMiklos Szeredi 		link = ERR_PTR(ret);
13907078187aSMiklos Szeredi 	} else {
13917078187aSMiklos Szeredi 		link[ret] = '\0';
13927078187aSMiklos Szeredi 	}
1393451418fcSAndrew Gallagher 	fuse_invalidate_atime(inode);
1394e5e5558eSMiklos Szeredi 	return link;
1395e5e5558eSMiklos Szeredi }
1396e5e5558eSMiklos Szeredi 
1397e5e5558eSMiklos Szeredi static void free_link(char *link)
1398e5e5558eSMiklos Szeredi {
1399e5e5558eSMiklos Szeredi 	if (!IS_ERR(link))
1400e5e5558eSMiklos Szeredi 		free_page((unsigned long) link);
1401e5e5558eSMiklos Szeredi }
1402e5e5558eSMiklos Szeredi 
1403e5e5558eSMiklos Szeredi static void *fuse_follow_link(struct dentry *dentry, struct nameidata *nd)
1404e5e5558eSMiklos Szeredi {
1405e5e5558eSMiklos Szeredi 	nd_set_link(nd, read_link(dentry));
1406e5e5558eSMiklos Szeredi 	return NULL;
1407e5e5558eSMiklos Szeredi }
1408e5e5558eSMiklos Szeredi 
1409e5e5558eSMiklos Szeredi static void fuse_put_link(struct dentry *dentry, struct nameidata *nd, void *c)
1410e5e5558eSMiklos Szeredi {
1411e5e5558eSMiklos Szeredi 	free_link(nd_get_link(nd));
1412e5e5558eSMiklos Szeredi }
1413e5e5558eSMiklos Szeredi 
1414e5e5558eSMiklos Szeredi static int fuse_dir_open(struct inode *inode, struct file *file)
1415e5e5558eSMiklos Szeredi {
141691fe96b4SMiklos Szeredi 	return fuse_open_common(inode, file, true);
1417e5e5558eSMiklos Szeredi }
1418e5e5558eSMiklos Szeredi 
1419e5e5558eSMiklos Szeredi static int fuse_dir_release(struct inode *inode, struct file *file)
1420e5e5558eSMiklos Szeredi {
14218b0797a4SMiklos Szeredi 	fuse_release_common(file, FUSE_RELEASEDIR);
14228b0797a4SMiklos Szeredi 
14238b0797a4SMiklos Szeredi 	return 0;
1424e5e5558eSMiklos Szeredi }
1425e5e5558eSMiklos Szeredi 
142602c24a82SJosef Bacik static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end,
142702c24a82SJosef Bacik 			  int datasync)
142882547981SMiklos Szeredi {
142902c24a82SJosef Bacik 	return fuse_fsync_common(file, start, end, datasync, 1);
143082547981SMiklos Szeredi }
143182547981SMiklos Szeredi 
1432b18da0c5SMiklos Szeredi static long fuse_dir_ioctl(struct file *file, unsigned int cmd,
1433b18da0c5SMiklos Szeredi 			    unsigned long arg)
1434b18da0c5SMiklos Szeredi {
1435b18da0c5SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1436b18da0c5SMiklos Szeredi 
1437b18da0c5SMiklos Szeredi 	/* FUSE_IOCTL_DIR only supported for API version >= 7.18 */
1438b18da0c5SMiklos Szeredi 	if (fc->minor < 18)
1439b18da0c5SMiklos Szeredi 		return -ENOTTY;
1440b18da0c5SMiklos Szeredi 
1441b18da0c5SMiklos Szeredi 	return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR);
1442b18da0c5SMiklos Szeredi }
1443b18da0c5SMiklos Szeredi 
1444b18da0c5SMiklos Szeredi static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd,
1445b18da0c5SMiklos Szeredi 				   unsigned long arg)
1446b18da0c5SMiklos Szeredi {
1447b18da0c5SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1448b18da0c5SMiklos Szeredi 
1449b18da0c5SMiklos Szeredi 	if (fc->minor < 18)
1450b18da0c5SMiklos Szeredi 		return -ENOTTY;
1451b18da0c5SMiklos Szeredi 
1452b18da0c5SMiklos Szeredi 	return fuse_ioctl_common(file, cmd, arg,
1453b18da0c5SMiklos Szeredi 				 FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR);
1454b18da0c5SMiklos Szeredi }
1455b18da0c5SMiklos Szeredi 
1456b0aa7606SMaxim Patlasov static bool update_mtime(unsigned ivalid, bool trust_local_mtime)
145717637cbaSMiklos Szeredi {
145817637cbaSMiklos Szeredi 	/* Always update if mtime is explicitly set  */
145917637cbaSMiklos Szeredi 	if (ivalid & ATTR_MTIME_SET)
146017637cbaSMiklos Szeredi 		return true;
146117637cbaSMiklos Szeredi 
1462b0aa7606SMaxim Patlasov 	/* Or if kernel i_mtime is the official one */
1463b0aa7606SMaxim Patlasov 	if (trust_local_mtime)
1464b0aa7606SMaxim Patlasov 		return true;
1465b0aa7606SMaxim Patlasov 
146617637cbaSMiklos Szeredi 	/* If it's an open(O_TRUNC) or an ftruncate(), don't update */
146717637cbaSMiklos Szeredi 	if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
146817637cbaSMiklos Szeredi 		return false;
146917637cbaSMiklos Szeredi 
147017637cbaSMiklos Szeredi 	/* In all other cases update */
147117637cbaSMiklos Szeredi 	return true;
147217637cbaSMiklos Szeredi }
147317637cbaSMiklos Szeredi 
1474b0aa7606SMaxim Patlasov static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg,
14753ad22c62SMaxim Patlasov 			   bool trust_local_cmtime)
14769e6268dbSMiklos Szeredi {
14779e6268dbSMiklos Szeredi 	unsigned ivalid = iattr->ia_valid;
14789e6268dbSMiklos Szeredi 
14799e6268dbSMiklos Szeredi 	if (ivalid & ATTR_MODE)
1480befc649cSMiklos Szeredi 		arg->valid |= FATTR_MODE,   arg->mode = iattr->ia_mode;
14819e6268dbSMiklos Szeredi 	if (ivalid & ATTR_UID)
1482499dcf20SEric W. Biederman 		arg->valid |= FATTR_UID,    arg->uid = from_kuid(&init_user_ns, iattr->ia_uid);
14839e6268dbSMiklos Szeredi 	if (ivalid & ATTR_GID)
1484499dcf20SEric W. Biederman 		arg->valid |= FATTR_GID,    arg->gid = from_kgid(&init_user_ns, iattr->ia_gid);
14859e6268dbSMiklos Szeredi 	if (ivalid & ATTR_SIZE)
1486befc649cSMiklos Szeredi 		arg->valid |= FATTR_SIZE,   arg->size = iattr->ia_size;
148717637cbaSMiklos Szeredi 	if (ivalid & ATTR_ATIME) {
148817637cbaSMiklos Szeredi 		arg->valid |= FATTR_ATIME;
1489befc649cSMiklos Szeredi 		arg->atime = iattr->ia_atime.tv_sec;
149017637cbaSMiklos Szeredi 		arg->atimensec = iattr->ia_atime.tv_nsec;
149117637cbaSMiklos Szeredi 		if (!(ivalid & ATTR_ATIME_SET))
149217637cbaSMiklos Szeredi 			arg->valid |= FATTR_ATIME_NOW;
149317637cbaSMiklos Szeredi 	}
14943ad22c62SMaxim Patlasov 	if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, trust_local_cmtime)) {
149517637cbaSMiklos Szeredi 		arg->valid |= FATTR_MTIME;
1496befc649cSMiklos Szeredi 		arg->mtime = iattr->ia_mtime.tv_sec;
149717637cbaSMiklos Szeredi 		arg->mtimensec = iattr->ia_mtime.tv_nsec;
14983ad22c62SMaxim Patlasov 		if (!(ivalid & ATTR_MTIME_SET) && !trust_local_cmtime)
149917637cbaSMiklos Szeredi 			arg->valid |= FATTR_MTIME_NOW;
15009e6268dbSMiklos Szeredi 	}
15013ad22c62SMaxim Patlasov 	if ((ivalid & ATTR_CTIME) && trust_local_cmtime) {
15023ad22c62SMaxim Patlasov 		arg->valid |= FATTR_CTIME;
15033ad22c62SMaxim Patlasov 		arg->ctime = iattr->ia_ctime.tv_sec;
15043ad22c62SMaxim Patlasov 		arg->ctimensec = iattr->ia_ctime.tv_nsec;
15053ad22c62SMaxim Patlasov 	}
15069e6268dbSMiklos Szeredi }
15079e6268dbSMiklos Szeredi 
15086f9f1180SMiklos Szeredi /*
15093be5a52bSMiklos Szeredi  * Prevent concurrent writepages on inode
15103be5a52bSMiklos Szeredi  *
15113be5a52bSMiklos Szeredi  * This is done by adding a negative bias to the inode write counter
15123be5a52bSMiklos Szeredi  * and waiting for all pending writes to finish.
15133be5a52bSMiklos Szeredi  */
15143be5a52bSMiklos Szeredi void fuse_set_nowrite(struct inode *inode)
15153be5a52bSMiklos Szeredi {
15163be5a52bSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
15173be5a52bSMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
15183be5a52bSMiklos Szeredi 
15193be5a52bSMiklos Szeredi 	BUG_ON(!mutex_is_locked(&inode->i_mutex));
15203be5a52bSMiklos Szeredi 
15213be5a52bSMiklos Szeredi 	spin_lock(&fc->lock);
15223be5a52bSMiklos Szeredi 	BUG_ON(fi->writectr < 0);
15233be5a52bSMiklos Szeredi 	fi->writectr += FUSE_NOWRITE;
15243be5a52bSMiklos Szeredi 	spin_unlock(&fc->lock);
15253be5a52bSMiklos Szeredi 	wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE);
15263be5a52bSMiklos Szeredi }
15273be5a52bSMiklos Szeredi 
15283be5a52bSMiklos Szeredi /*
15293be5a52bSMiklos Szeredi  * Allow writepages on inode
15303be5a52bSMiklos Szeredi  *
15313be5a52bSMiklos Szeredi  * Remove the bias from the writecounter and send any queued
15323be5a52bSMiklos Szeredi  * writepages.
15333be5a52bSMiklos Szeredi  */
15343be5a52bSMiklos Szeredi static void __fuse_release_nowrite(struct inode *inode)
15353be5a52bSMiklos Szeredi {
15363be5a52bSMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
15373be5a52bSMiklos Szeredi 
15383be5a52bSMiklos Szeredi 	BUG_ON(fi->writectr != FUSE_NOWRITE);
15393be5a52bSMiklos Szeredi 	fi->writectr = 0;
15403be5a52bSMiklos Szeredi 	fuse_flush_writepages(inode);
15413be5a52bSMiklos Szeredi }
15423be5a52bSMiklos Szeredi 
15433be5a52bSMiklos Szeredi void fuse_release_nowrite(struct inode *inode)
15443be5a52bSMiklos Szeredi {
15453be5a52bSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
15463be5a52bSMiklos Szeredi 
15473be5a52bSMiklos Szeredi 	spin_lock(&fc->lock);
15483be5a52bSMiklos Szeredi 	__fuse_release_nowrite(inode);
15493be5a52bSMiklos Szeredi 	spin_unlock(&fc->lock);
15503be5a52bSMiklos Szeredi }
15513be5a52bSMiklos Szeredi 
15527078187aSMiklos Szeredi static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_args *args,
1553b0aa7606SMaxim Patlasov 			      struct inode *inode,
1554b0aa7606SMaxim Patlasov 			      struct fuse_setattr_in *inarg_p,
1555b0aa7606SMaxim Patlasov 			      struct fuse_attr_out *outarg_p)
1556b0aa7606SMaxim Patlasov {
15577078187aSMiklos Szeredi 	args->in.h.opcode = FUSE_SETATTR;
15587078187aSMiklos Szeredi 	args->in.h.nodeid = get_node_id(inode);
15597078187aSMiklos Szeredi 	args->in.numargs = 1;
15607078187aSMiklos Szeredi 	args->in.args[0].size = sizeof(*inarg_p);
15617078187aSMiklos Szeredi 	args->in.args[0].value = inarg_p;
15627078187aSMiklos Szeredi 	args->out.numargs = 1;
15637078187aSMiklos Szeredi 	args->out.args[0].size = sizeof(*outarg_p);
15647078187aSMiklos Szeredi 	args->out.args[0].value = outarg_p;
1565b0aa7606SMaxim Patlasov }
1566b0aa7606SMaxim Patlasov 
1567b0aa7606SMaxim Patlasov /*
1568b0aa7606SMaxim Patlasov  * Flush inode->i_mtime to the server
1569b0aa7606SMaxim Patlasov  */
1570ab9e13f7SMaxim Patlasov int fuse_flush_times(struct inode *inode, struct fuse_file *ff)
1571b0aa7606SMaxim Patlasov {
1572b0aa7606SMaxim Patlasov 	struct fuse_conn *fc = get_fuse_conn(inode);
15737078187aSMiklos Szeredi 	FUSE_ARGS(args);
1574b0aa7606SMaxim Patlasov 	struct fuse_setattr_in inarg;
1575b0aa7606SMaxim Patlasov 	struct fuse_attr_out outarg;
1576b0aa7606SMaxim Patlasov 
1577b0aa7606SMaxim Patlasov 	memset(&inarg, 0, sizeof(inarg));
1578b0aa7606SMaxim Patlasov 	memset(&outarg, 0, sizeof(outarg));
1579b0aa7606SMaxim Patlasov 
1580ab9e13f7SMaxim Patlasov 	inarg.valid = FATTR_MTIME;
1581b0aa7606SMaxim Patlasov 	inarg.mtime = inode->i_mtime.tv_sec;
1582b0aa7606SMaxim Patlasov 	inarg.mtimensec = inode->i_mtime.tv_nsec;
1583ab9e13f7SMaxim Patlasov 	if (fc->minor >= 23) {
1584ab9e13f7SMaxim Patlasov 		inarg.valid |= FATTR_CTIME;
1585ab9e13f7SMaxim Patlasov 		inarg.ctime = inode->i_ctime.tv_sec;
1586ab9e13f7SMaxim Patlasov 		inarg.ctimensec = inode->i_ctime.tv_nsec;
1587ab9e13f7SMaxim Patlasov 	}
15881e18bda8SMiklos Szeredi 	if (ff) {
15891e18bda8SMiklos Szeredi 		inarg.valid |= FATTR_FH;
15901e18bda8SMiklos Szeredi 		inarg.fh = ff->fh;
15911e18bda8SMiklos Szeredi 	}
15927078187aSMiklos Szeredi 	fuse_setattr_fill(fc, &args, inode, &inarg, &outarg);
1593b0aa7606SMaxim Patlasov 
15947078187aSMiklos Szeredi 	return fuse_simple_request(fc, &args);
1595b0aa7606SMaxim Patlasov }
1596b0aa7606SMaxim Patlasov 
15973be5a52bSMiklos Szeredi /*
15986f9f1180SMiklos Szeredi  * Set attributes, and at the same time refresh them.
15996f9f1180SMiklos Szeredi  *
16006f9f1180SMiklos Szeredi  * Truncation is slightly complicated, because the 'truncate' request
16016f9f1180SMiklos Szeredi  * may fail, in which case we don't want to touch the mapping.
16029ffbb916SMiklos Szeredi  * vmtruncate() doesn't allow for this case, so do the rlimit checking
16039ffbb916SMiklos Szeredi  * and the actual truncation by hand.
16046f9f1180SMiklos Szeredi  */
1605efb9fa9eSMaxim Patlasov int fuse_do_setattr(struct inode *inode, struct iattr *attr,
160649d4914fSMiklos Szeredi 		    struct file *file)
16079e6268dbSMiklos Szeredi {
16089e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
160906a7c3c2SMaxim Patlasov 	struct fuse_inode *fi = get_fuse_inode(inode);
16107078187aSMiklos Szeredi 	FUSE_ARGS(args);
16119e6268dbSMiklos Szeredi 	struct fuse_setattr_in inarg;
16129e6268dbSMiklos Szeredi 	struct fuse_attr_out outarg;
16133be5a52bSMiklos Szeredi 	bool is_truncate = false;
16148373200bSPavel Emelyanov 	bool is_wb = fc->writeback_cache;
16153be5a52bSMiklos Szeredi 	loff_t oldsize;
16169e6268dbSMiklos Szeredi 	int err;
16173ad22c62SMaxim Patlasov 	bool trust_local_cmtime = is_wb && S_ISREG(inode->i_mode);
16189e6268dbSMiklos Szeredi 
1619db78b877SChristoph Hellwig 	if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS))
1620db78b877SChristoph Hellwig 		attr->ia_valid |= ATTR_FORCE;
1621db78b877SChristoph Hellwig 
16221e9a4ed9SMiklos Szeredi 	err = inode_change_ok(inode, attr);
16231e9a4ed9SMiklos Szeredi 	if (err)
16241e9a4ed9SMiklos Szeredi 		return err;
16251e9a4ed9SMiklos Szeredi 
16268d56adddSMiklos Szeredi 	if (attr->ia_valid & ATTR_OPEN) {
16278d56adddSMiklos Szeredi 		if (fc->atomic_o_trunc)
16286ff958edSMiklos Szeredi 			return 0;
16298d56adddSMiklos Szeredi 		file = NULL;
16308d56adddSMiklos Szeredi 	}
16316ff958edSMiklos Szeredi 
16322c27c65eSChristoph Hellwig 	if (attr->ia_valid & ATTR_SIZE)
16333be5a52bSMiklos Szeredi 		is_truncate = true;
16349e6268dbSMiklos Szeredi 
163506a7c3c2SMaxim Patlasov 	if (is_truncate) {
16363be5a52bSMiklos Szeredi 		fuse_set_nowrite(inode);
163706a7c3c2SMaxim Patlasov 		set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
16383ad22c62SMaxim Patlasov 		if (trust_local_cmtime && attr->ia_size != inode->i_size)
16393ad22c62SMaxim Patlasov 			attr->ia_valid |= ATTR_MTIME | ATTR_CTIME;
164006a7c3c2SMaxim Patlasov 	}
16413be5a52bSMiklos Szeredi 
16429e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
16430e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
16443ad22c62SMaxim Patlasov 	iattr_to_fattr(attr, &inarg, trust_local_cmtime);
164549d4914fSMiklos Szeredi 	if (file) {
164649d4914fSMiklos Szeredi 		struct fuse_file *ff = file->private_data;
164749d4914fSMiklos Szeredi 		inarg.valid |= FATTR_FH;
164849d4914fSMiklos Szeredi 		inarg.fh = ff->fh;
164949d4914fSMiklos Szeredi 	}
1650f3332114SMiklos Szeredi 	if (attr->ia_valid & ATTR_SIZE) {
1651f3332114SMiklos Szeredi 		/* For mandatory locking in truncate */
1652f3332114SMiklos Szeredi 		inarg.valid |= FATTR_LOCKOWNER;
1653f3332114SMiklos Szeredi 		inarg.lock_owner = fuse_lock_owner_id(fc, current->files);
1654f3332114SMiklos Szeredi 	}
16557078187aSMiklos Szeredi 	fuse_setattr_fill(fc, &args, inode, &inarg, &outarg);
16567078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
1657e00d2c2dSMiklos Szeredi 	if (err) {
1658e00d2c2dSMiklos Szeredi 		if (err == -EINTR)
1659e00d2c2dSMiklos Szeredi 			fuse_invalidate_attr(inode);
16603be5a52bSMiklos Szeredi 		goto error;
1661e00d2c2dSMiklos Szeredi 	}
1662e00d2c2dSMiklos Szeredi 
16639e6268dbSMiklos Szeredi 	if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
16649e6268dbSMiklos Szeredi 		make_bad_inode(inode);
16653be5a52bSMiklos Szeredi 		err = -EIO;
16663be5a52bSMiklos Szeredi 		goto error;
16679e6268dbSMiklos Szeredi 	}
16689e6268dbSMiklos Szeredi 
16693be5a52bSMiklos Szeredi 	spin_lock(&fc->lock);
1670b0aa7606SMaxim Patlasov 	/* the kernel maintains i_mtime locally */
16713ad22c62SMaxim Patlasov 	if (trust_local_cmtime) {
16723ad22c62SMaxim Patlasov 		if (attr->ia_valid & ATTR_MTIME)
1673b0aa7606SMaxim Patlasov 			inode->i_mtime = attr->ia_mtime;
16743ad22c62SMaxim Patlasov 		if (attr->ia_valid & ATTR_CTIME)
16753ad22c62SMaxim Patlasov 			inode->i_ctime = attr->ia_ctime;
16761e18bda8SMiklos Szeredi 		/* FIXME: clear I_DIRTY_SYNC? */
1677b0aa7606SMaxim Patlasov 	}
1678b0aa7606SMaxim Patlasov 
16793be5a52bSMiklos Szeredi 	fuse_change_attributes_common(inode, &outarg.attr,
16803be5a52bSMiklos Szeredi 				      attr_timeout(&outarg));
16813be5a52bSMiklos Szeredi 	oldsize = inode->i_size;
16828373200bSPavel Emelyanov 	/* see the comment in fuse_change_attributes() */
16838373200bSPavel Emelyanov 	if (!is_wb || is_truncate || !S_ISREG(inode->i_mode))
16843be5a52bSMiklos Szeredi 		i_size_write(inode, outarg.attr.size);
16853be5a52bSMiklos Szeredi 
16863be5a52bSMiklos Szeredi 	if (is_truncate) {
16873be5a52bSMiklos Szeredi 		/* NOTE: this may release/reacquire fc->lock */
16883be5a52bSMiklos Szeredi 		__fuse_release_nowrite(inode);
16893be5a52bSMiklos Szeredi 	}
16903be5a52bSMiklos Szeredi 	spin_unlock(&fc->lock);
16913be5a52bSMiklos Szeredi 
16923be5a52bSMiklos Szeredi 	/*
16933be5a52bSMiklos Szeredi 	 * Only call invalidate_inode_pages2() after removing
16943be5a52bSMiklos Szeredi 	 * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock.
16953be5a52bSMiklos Szeredi 	 */
16968373200bSPavel Emelyanov 	if ((is_truncate || !is_wb) &&
16978373200bSPavel Emelyanov 	    S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
16987caef267SKirill A. Shutemov 		truncate_pagecache(inode, outarg.attr.size);
16993be5a52bSMiklos Szeredi 		invalidate_inode_pages2(inode->i_mapping);
17003be5a52bSMiklos Szeredi 	}
17013be5a52bSMiklos Szeredi 
170206a7c3c2SMaxim Patlasov 	clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
1703e00d2c2dSMiklos Szeredi 	return 0;
17043be5a52bSMiklos Szeredi 
17053be5a52bSMiklos Szeredi error:
17063be5a52bSMiklos Szeredi 	if (is_truncate)
17073be5a52bSMiklos Szeredi 		fuse_release_nowrite(inode);
17083be5a52bSMiklos Szeredi 
170906a7c3c2SMaxim Patlasov 	clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
17103be5a52bSMiklos Szeredi 	return err;
17119e6268dbSMiklos Szeredi }
17129e6268dbSMiklos Szeredi 
171349d4914fSMiklos Szeredi static int fuse_setattr(struct dentry *entry, struct iattr *attr)
171449d4914fSMiklos Szeredi {
1715efb9fa9eSMaxim Patlasov 	struct inode *inode = entry->d_inode;
1716efb9fa9eSMaxim Patlasov 
1717efb9fa9eSMaxim Patlasov 	if (!fuse_allow_current_process(get_fuse_conn(inode)))
1718efb9fa9eSMaxim Patlasov 		return -EACCES;
1719efb9fa9eSMaxim Patlasov 
172049d4914fSMiklos Szeredi 	if (attr->ia_valid & ATTR_FILE)
1721efb9fa9eSMaxim Patlasov 		return fuse_do_setattr(inode, attr, attr->ia_file);
172249d4914fSMiklos Szeredi 	else
1723efb9fa9eSMaxim Patlasov 		return fuse_do_setattr(inode, attr, NULL);
172449d4914fSMiklos Szeredi }
172549d4914fSMiklos Szeredi 
1726e5e5558eSMiklos Szeredi static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
1727e5e5558eSMiklos Szeredi 			struct kstat *stat)
1728e5e5558eSMiklos Szeredi {
1729e5e5558eSMiklos Szeredi 	struct inode *inode = entry->d_inode;
1730244f6385SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1731244f6385SMiklos Szeredi 
1732c2132c1bSAnatol Pomozov 	if (!fuse_allow_current_process(fc))
1733244f6385SMiklos Szeredi 		return -EACCES;
1734244f6385SMiklos Szeredi 
1735bcb4be80SMiklos Szeredi 	return fuse_update_attributes(inode, stat, NULL, NULL);
1736e5e5558eSMiklos Szeredi }
1737e5e5558eSMiklos Szeredi 
173892a8780eSMiklos Szeredi static int fuse_setxattr(struct dentry *entry, const char *name,
173992a8780eSMiklos Szeredi 			 const void *value, size_t size, int flags)
174092a8780eSMiklos Szeredi {
174192a8780eSMiklos Szeredi 	struct inode *inode = entry->d_inode;
174292a8780eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
17437078187aSMiklos Szeredi 	FUSE_ARGS(args);
174492a8780eSMiklos Szeredi 	struct fuse_setxattr_in inarg;
174592a8780eSMiklos Szeredi 	int err;
174692a8780eSMiklos Szeredi 
174792a8780eSMiklos Szeredi 	if (fc->no_setxattr)
174892a8780eSMiklos Szeredi 		return -EOPNOTSUPP;
174992a8780eSMiklos Szeredi 
175092a8780eSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
175192a8780eSMiklos Szeredi 	inarg.size = size;
175292a8780eSMiklos Szeredi 	inarg.flags = flags;
17537078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_SETXATTR;
17547078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(inode);
17557078187aSMiklos Szeredi 	args.in.numargs = 3;
17567078187aSMiklos Szeredi 	args.in.args[0].size = sizeof(inarg);
17577078187aSMiklos Szeredi 	args.in.args[0].value = &inarg;
17587078187aSMiklos Szeredi 	args.in.args[1].size = strlen(name) + 1;
17597078187aSMiklos Szeredi 	args.in.args[1].value = name;
17607078187aSMiklos Szeredi 	args.in.args[2].size = size;
17617078187aSMiklos Szeredi 	args.in.args[2].value = value;
17627078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
176392a8780eSMiklos Szeredi 	if (err == -ENOSYS) {
176492a8780eSMiklos Szeredi 		fc->no_setxattr = 1;
176592a8780eSMiklos Szeredi 		err = -EOPNOTSUPP;
176692a8780eSMiklos Szeredi 	}
176731f3267bSMaxim Patlasov 	if (!err) {
1768d331a415SAnand Avati 		fuse_invalidate_attr(inode);
176931f3267bSMaxim Patlasov 		fuse_update_ctime(inode);
177031f3267bSMaxim Patlasov 	}
177192a8780eSMiklos Szeredi 	return err;
177292a8780eSMiklos Szeredi }
177392a8780eSMiklos Szeredi 
177492a8780eSMiklos Szeredi static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
177592a8780eSMiklos Szeredi 			     void *value, size_t size)
177692a8780eSMiklos Szeredi {
177792a8780eSMiklos Szeredi 	struct inode *inode = entry->d_inode;
177892a8780eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
17797078187aSMiklos Szeredi 	FUSE_ARGS(args);
178092a8780eSMiklos Szeredi 	struct fuse_getxattr_in inarg;
178192a8780eSMiklos Szeredi 	struct fuse_getxattr_out outarg;
178292a8780eSMiklos Szeredi 	ssize_t ret;
178392a8780eSMiklos Szeredi 
178492a8780eSMiklos Szeredi 	if (fc->no_getxattr)
178592a8780eSMiklos Szeredi 		return -EOPNOTSUPP;
178692a8780eSMiklos Szeredi 
178792a8780eSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
178892a8780eSMiklos Szeredi 	inarg.size = size;
17897078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_GETXATTR;
17907078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(inode);
17917078187aSMiklos Szeredi 	args.in.numargs = 2;
17927078187aSMiklos Szeredi 	args.in.args[0].size = sizeof(inarg);
17937078187aSMiklos Szeredi 	args.in.args[0].value = &inarg;
17947078187aSMiklos Szeredi 	args.in.args[1].size = strlen(name) + 1;
17957078187aSMiklos Szeredi 	args.in.args[1].value = name;
179692a8780eSMiklos Szeredi 	/* This is really two different operations rolled into one */
17977078187aSMiklos Szeredi 	args.out.numargs = 1;
179892a8780eSMiklos Szeredi 	if (size) {
17997078187aSMiklos Szeredi 		args.out.argvar = 1;
18007078187aSMiklos Szeredi 		args.out.args[0].size = size;
18017078187aSMiklos Szeredi 		args.out.args[0].value = value;
180292a8780eSMiklos Szeredi 	} else {
18037078187aSMiklos Szeredi 		args.out.args[0].size = sizeof(outarg);
18047078187aSMiklos Szeredi 		args.out.args[0].value = &outarg;
180592a8780eSMiklos Szeredi 	}
18067078187aSMiklos Szeredi 	ret = fuse_simple_request(fc, &args);
18077078187aSMiklos Szeredi 	if (!ret && !size)
18087078187aSMiklos Szeredi 		ret = outarg.size;
180992a8780eSMiklos Szeredi 	if (ret == -ENOSYS) {
181092a8780eSMiklos Szeredi 		fc->no_getxattr = 1;
181192a8780eSMiklos Szeredi 		ret = -EOPNOTSUPP;
181292a8780eSMiklos Szeredi 	}
181392a8780eSMiklos Szeredi 	return ret;
181492a8780eSMiklos Szeredi }
181592a8780eSMiklos Szeredi 
181692a8780eSMiklos Szeredi static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
181792a8780eSMiklos Szeredi {
181892a8780eSMiklos Szeredi 	struct inode *inode = entry->d_inode;
181992a8780eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
18207078187aSMiklos Szeredi 	FUSE_ARGS(args);
182192a8780eSMiklos Szeredi 	struct fuse_getxattr_in inarg;
182292a8780eSMiklos Szeredi 	struct fuse_getxattr_out outarg;
182392a8780eSMiklos Szeredi 	ssize_t ret;
182492a8780eSMiklos Szeredi 
1825c2132c1bSAnatol Pomozov 	if (!fuse_allow_current_process(fc))
1826e57ac683SMiklos Szeredi 		return -EACCES;
1827e57ac683SMiklos Szeredi 
182892a8780eSMiklos Szeredi 	if (fc->no_listxattr)
182992a8780eSMiklos Szeredi 		return -EOPNOTSUPP;
183092a8780eSMiklos Szeredi 
183192a8780eSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
183292a8780eSMiklos Szeredi 	inarg.size = size;
18337078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_LISTXATTR;
18347078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(inode);
18357078187aSMiklos Szeredi 	args.in.numargs = 1;
18367078187aSMiklos Szeredi 	args.in.args[0].size = sizeof(inarg);
18377078187aSMiklos Szeredi 	args.in.args[0].value = &inarg;
183892a8780eSMiklos Szeredi 	/* This is really two different operations rolled into one */
18397078187aSMiklos Szeredi 	args.out.numargs = 1;
184092a8780eSMiklos Szeredi 	if (size) {
18417078187aSMiklos Szeredi 		args.out.argvar = 1;
18427078187aSMiklos Szeredi 		args.out.args[0].size = size;
18437078187aSMiklos Szeredi 		args.out.args[0].value = list;
184492a8780eSMiklos Szeredi 	} else {
18457078187aSMiklos Szeredi 		args.out.args[0].size = sizeof(outarg);
18467078187aSMiklos Szeredi 		args.out.args[0].value = &outarg;
184792a8780eSMiklos Szeredi 	}
18487078187aSMiklos Szeredi 	ret = fuse_simple_request(fc, &args);
18497078187aSMiklos Szeredi 	if (!ret && !size)
18507078187aSMiklos Szeredi 		ret = outarg.size;
185192a8780eSMiklos Szeredi 	if (ret == -ENOSYS) {
185292a8780eSMiklos Szeredi 		fc->no_listxattr = 1;
185392a8780eSMiklos Szeredi 		ret = -EOPNOTSUPP;
185492a8780eSMiklos Szeredi 	}
185592a8780eSMiklos Szeredi 	return ret;
185692a8780eSMiklos Szeredi }
185792a8780eSMiklos Szeredi 
185892a8780eSMiklos Szeredi static int fuse_removexattr(struct dentry *entry, const char *name)
185992a8780eSMiklos Szeredi {
186092a8780eSMiklos Szeredi 	struct inode *inode = entry->d_inode;
186192a8780eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
18627078187aSMiklos Szeredi 	FUSE_ARGS(args);
186392a8780eSMiklos Szeredi 	int err;
186492a8780eSMiklos Szeredi 
186592a8780eSMiklos Szeredi 	if (fc->no_removexattr)
186692a8780eSMiklos Szeredi 		return -EOPNOTSUPP;
186792a8780eSMiklos Szeredi 
18687078187aSMiklos Szeredi 	args.in.h.opcode = FUSE_REMOVEXATTR;
18697078187aSMiklos Szeredi 	args.in.h.nodeid = get_node_id(inode);
18707078187aSMiklos Szeredi 	args.in.numargs = 1;
18717078187aSMiklos Szeredi 	args.in.args[0].size = strlen(name) + 1;
18727078187aSMiklos Szeredi 	args.in.args[0].value = name;
18737078187aSMiklos Szeredi 	err = fuse_simple_request(fc, &args);
187492a8780eSMiklos Szeredi 	if (err == -ENOSYS) {
187592a8780eSMiklos Szeredi 		fc->no_removexattr = 1;
187692a8780eSMiklos Szeredi 		err = -EOPNOTSUPP;
187792a8780eSMiklos Szeredi 	}
187831f3267bSMaxim Patlasov 	if (!err) {
1879d331a415SAnand Avati 		fuse_invalidate_attr(inode);
188031f3267bSMaxim Patlasov 		fuse_update_ctime(inode);
188131f3267bSMaxim Patlasov 	}
188292a8780eSMiklos Szeredi 	return err;
188392a8780eSMiklos Szeredi }
188492a8780eSMiklos Szeredi 
1885754661f1SArjan van de Ven static const struct inode_operations fuse_dir_inode_operations = {
1886e5e5558eSMiklos Szeredi 	.lookup		= fuse_lookup,
18879e6268dbSMiklos Szeredi 	.mkdir		= fuse_mkdir,
18889e6268dbSMiklos Szeredi 	.symlink	= fuse_symlink,
18899e6268dbSMiklos Szeredi 	.unlink		= fuse_unlink,
18909e6268dbSMiklos Szeredi 	.rmdir		= fuse_rmdir,
18911560c974SMiklos Szeredi 	.rename2	= fuse_rename2,
18929e6268dbSMiklos Szeredi 	.link		= fuse_link,
18939e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
18949e6268dbSMiklos Szeredi 	.create		= fuse_create,
1895c8ccbe03SMiklos Szeredi 	.atomic_open	= fuse_atomic_open,
18969e6268dbSMiklos Szeredi 	.mknod		= fuse_mknod,
1897e5e5558eSMiklos Szeredi 	.permission	= fuse_permission,
1898e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
189992a8780eSMiklos Szeredi 	.setxattr	= fuse_setxattr,
190092a8780eSMiklos Szeredi 	.getxattr	= fuse_getxattr,
190192a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
190292a8780eSMiklos Szeredi 	.removexattr	= fuse_removexattr,
1903e5e5558eSMiklos Szeredi };
1904e5e5558eSMiklos Szeredi 
19054b6f5d20SArjan van de Ven static const struct file_operations fuse_dir_operations = {
1906b6aeadedSMiklos Szeredi 	.llseek		= generic_file_llseek,
1907e5e5558eSMiklos Szeredi 	.read		= generic_read_dir,
19088d3af7f3SAl Viro 	.iterate	= fuse_readdir,
1909e5e5558eSMiklos Szeredi 	.open		= fuse_dir_open,
1910e5e5558eSMiklos Szeredi 	.release	= fuse_dir_release,
191182547981SMiklos Szeredi 	.fsync		= fuse_dir_fsync,
1912b18da0c5SMiklos Szeredi 	.unlocked_ioctl	= fuse_dir_ioctl,
1913b18da0c5SMiklos Szeredi 	.compat_ioctl	= fuse_dir_compat_ioctl,
1914e5e5558eSMiklos Szeredi };
1915e5e5558eSMiklos Szeredi 
1916754661f1SArjan van de Ven static const struct inode_operations fuse_common_inode_operations = {
19179e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
1918e5e5558eSMiklos Szeredi 	.permission	= fuse_permission,
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 
1926754661f1SArjan van de Ven static const struct inode_operations fuse_symlink_inode_operations = {
19279e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
1928e5e5558eSMiklos Szeredi 	.follow_link	= fuse_follow_link,
1929e5e5558eSMiklos Szeredi 	.put_link	= fuse_put_link,
1930e5e5558eSMiklos Szeredi 	.readlink	= generic_readlink,
1931e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
193292a8780eSMiklos Szeredi 	.setxattr	= fuse_setxattr,
193392a8780eSMiklos Szeredi 	.getxattr	= fuse_getxattr,
193492a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
193592a8780eSMiklos Szeredi 	.removexattr	= fuse_removexattr,
1936e5e5558eSMiklos Szeredi };
1937e5e5558eSMiklos Szeredi 
1938e5e5558eSMiklos Szeredi void fuse_init_common(struct inode *inode)
1939e5e5558eSMiklos Szeredi {
1940e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_common_inode_operations;
1941e5e5558eSMiklos Szeredi }
1942e5e5558eSMiklos Szeredi 
1943e5e5558eSMiklos Szeredi void fuse_init_dir(struct inode *inode)
1944e5e5558eSMiklos Szeredi {
1945e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_dir_inode_operations;
1946e5e5558eSMiklos Szeredi 	inode->i_fop = &fuse_dir_operations;
1947e5e5558eSMiklos Szeredi }
1948e5e5558eSMiklos Szeredi 
1949e5e5558eSMiklos Szeredi void fuse_init_symlink(struct inode *inode)
1950e5e5558eSMiklos Szeredi {
1951e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_symlink_inode_operations;
1952e5e5558eSMiklos Szeredi }
1953