xref: /openbmc/linux/fs/fuse/dir.c (revision efeb9e60)
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 
1156f9f1180SMiklos Szeredi /*
1166f9f1180SMiklos Szeredi  * Just mark the entry as stale, so that a next attempt to look it up
1176f9f1180SMiklos Szeredi  * will result in a new lookup call to userspace
1186f9f1180SMiklos Szeredi  *
1196f9f1180SMiklos Szeredi  * This is called when a dentry is about to become negative and the
1206f9f1180SMiklos Szeredi  * timeout is unknown (unlink, rmdir, rename and in some cases
1216f9f1180SMiklos Szeredi  * lookup)
1226f9f1180SMiklos Szeredi  */
123dbd561d2SMiklos Szeredi void fuse_invalidate_entry_cache(struct dentry *entry)
1248cbdf1e6SMiklos Szeredi {
1250a0898cfSMiklos Szeredi 	fuse_dentry_settime(entry, 0);
1268cbdf1e6SMiklos Szeredi }
1278cbdf1e6SMiklos Szeredi 
1286f9f1180SMiklos Szeredi /*
1296f9f1180SMiklos Szeredi  * Same as fuse_invalidate_entry_cache(), but also try to remove the
1306f9f1180SMiklos Szeredi  * dentry from the hash
1316f9f1180SMiklos Szeredi  */
1328cbdf1e6SMiklos Szeredi static void fuse_invalidate_entry(struct dentry *entry)
1338cbdf1e6SMiklos Szeredi {
1348cbdf1e6SMiklos Szeredi 	d_invalidate(entry);
1358cbdf1e6SMiklos Szeredi 	fuse_invalidate_entry_cache(entry);
1360aa7c699SMiklos Szeredi }
1370aa7c699SMiklos Szeredi 
138c180eebeSMiklos Szeredi static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_req *req,
139c180eebeSMiklos Szeredi 			     u64 nodeid, struct qstr *name,
140e5e5558eSMiklos Szeredi 			     struct fuse_entry_out *outarg)
141e5e5558eSMiklos Szeredi {
1420e9663eeSMiklos Szeredi 	memset(outarg, 0, sizeof(struct fuse_entry_out));
143e5e5558eSMiklos Szeredi 	req->in.h.opcode = FUSE_LOOKUP;
144c180eebeSMiklos Szeredi 	req->in.h.nodeid = nodeid;
145e5e5558eSMiklos Szeredi 	req->in.numargs = 1;
146c180eebeSMiklos Szeredi 	req->in.args[0].size = name->len + 1;
147c180eebeSMiklos Szeredi 	req->in.args[0].value = name->name;
148e5e5558eSMiklos Szeredi 	req->out.numargs = 1;
1490e9663eeSMiklos Szeredi 	if (fc->minor < 9)
1500e9663eeSMiklos Szeredi 		req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
1510e9663eeSMiklos Szeredi 	else
152e5e5558eSMiklos Szeredi 		req->out.args[0].size = sizeof(struct fuse_entry_out);
153e5e5558eSMiklos Szeredi 	req->out.args[0].value = outarg;
154e5e5558eSMiklos Szeredi }
155e5e5558eSMiklos Szeredi 
1565c5c5e51SMiklos Szeredi u64 fuse_get_attr_version(struct fuse_conn *fc)
1577dca9fd3SMiklos Szeredi {
1587dca9fd3SMiklos Szeredi 	u64 curr_version;
1597dca9fd3SMiklos Szeredi 
1607dca9fd3SMiklos Szeredi 	/*
1617dca9fd3SMiklos Szeredi 	 * The spin lock isn't actually needed on 64bit archs, but we
1627dca9fd3SMiklos Szeredi 	 * don't yet care too much about such optimizations.
1637dca9fd3SMiklos Szeredi 	 */
1647dca9fd3SMiklos Szeredi 	spin_lock(&fc->lock);
1657dca9fd3SMiklos Szeredi 	curr_version = fc->attr_version;
1667dca9fd3SMiklos Szeredi 	spin_unlock(&fc->lock);
1677dca9fd3SMiklos Szeredi 
1687dca9fd3SMiklos Szeredi 	return curr_version;
1697dca9fd3SMiklos Szeredi }
1707dca9fd3SMiklos Szeredi 
1716f9f1180SMiklos Szeredi /*
1726f9f1180SMiklos Szeredi  * Check whether the dentry is still valid
1736f9f1180SMiklos Szeredi  *
1746f9f1180SMiklos Szeredi  * If the entry validity timeout has expired and the dentry is
1756f9f1180SMiklos Szeredi  * positive, try to redo the lookup.  If the lookup results in a
1766f9f1180SMiklos Szeredi  * different inode, then let the VFS invalidate the dentry and redo
1776f9f1180SMiklos Szeredi  * the lookup once more.  If the lookup results in the same inode,
1786f9f1180SMiklos Szeredi  * then refresh the attributes, timeouts and mark the dentry valid.
1796f9f1180SMiklos Szeredi  */
1800b728e19SAl Viro static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
181e5e5558eSMiklos Szeredi {
18234286d66SNick Piggin 	struct inode *inode;
18328420dadSMiklos Szeredi 	struct dentry *parent;
18428420dadSMiklos Szeredi 	struct fuse_conn *fc;
1858cbdf1e6SMiklos Szeredi 
186e7c0a167SMiklos Szeredi 	inode = ACCESS_ONCE(entry->d_inode);
1878cbdf1e6SMiklos Szeredi 	if (inode && is_bad_inode(inode))
188e5e5558eSMiklos Szeredi 		return 0;
1890a0898cfSMiklos Szeredi 	else if (fuse_dentry_time(entry) < get_jiffies_64()) {
190e5e5558eSMiklos Szeredi 		int err;
191e5e5558eSMiklos Szeredi 		struct fuse_entry_out outarg;
1928cbdf1e6SMiklos Szeredi 		struct fuse_req *req;
19307e77dcaSMiklos Szeredi 		struct fuse_forget_link *forget;
1941fb69e78SMiklos Szeredi 		u64 attr_version;
1958cbdf1e6SMiklos Szeredi 
19650322fe7SMiklos Szeredi 		/* For negative dentries, always do a fresh lookup */
1978cbdf1e6SMiklos Szeredi 		if (!inode)
1988cbdf1e6SMiklos Szeredi 			return 0;
1998cbdf1e6SMiklos Szeredi 
2000b728e19SAl Viro 		if (flags & LOOKUP_RCU)
201e7c0a167SMiklos Szeredi 			return -ECHILD;
202e7c0a167SMiklos Szeredi 
2038cbdf1e6SMiklos Szeredi 		fc = get_fuse_conn(inode);
204b111c8c0SMaxim Patlasov 		req = fuse_get_req_nopages(fc);
205ce1d5a49SMiklos Szeredi 		if (IS_ERR(req))
206e5e5558eSMiklos Szeredi 			return 0;
207e5e5558eSMiklos Szeredi 
20807e77dcaSMiklos Szeredi 		forget = fuse_alloc_forget();
20907e77dcaSMiklos Szeredi 		if (!forget) {
2102d51013eSMiklos Szeredi 			fuse_put_request(fc, req);
2112d51013eSMiklos Szeredi 			return 0;
2122d51013eSMiklos Szeredi 		}
2132d51013eSMiklos Szeredi 
2147dca9fd3SMiklos Szeredi 		attr_version = fuse_get_attr_version(fc);
2151fb69e78SMiklos Szeredi 
216e956edd0SMiklos Szeredi 		parent = dget_parent(entry);
217c180eebeSMiklos Szeredi 		fuse_lookup_init(fc, req, get_node_id(parent->d_inode),
218c180eebeSMiklos Szeredi 				 &entry->d_name, &outarg);
219b93f858aSTejun Heo 		fuse_request_send(fc, req);
220e956edd0SMiklos Szeredi 		dput(parent);
221e5e5558eSMiklos Szeredi 		err = req->out.h.error;
2222d51013eSMiklos Szeredi 		fuse_put_request(fc, req);
22350322fe7SMiklos Szeredi 		/* Zero nodeid is same as -ENOENT */
22450322fe7SMiklos Szeredi 		if (!err && !outarg.nodeid)
22550322fe7SMiklos Szeredi 			err = -ENOENT;
2269e6268dbSMiklos Szeredi 		if (!err) {
2278cbdf1e6SMiklos Szeredi 			struct fuse_inode *fi = get_fuse_inode(inode);
2289e6268dbSMiklos Szeredi 			if (outarg.nodeid != get_node_id(inode)) {
22907e77dcaSMiklos Szeredi 				fuse_queue_forget(fc, forget, outarg.nodeid, 1);
2309e6268dbSMiklos Szeredi 				return 0;
2319e6268dbSMiklos Szeredi 			}
2328da5ff23SMiklos Szeredi 			spin_lock(&fc->lock);
2339e6268dbSMiklos Szeredi 			fi->nlookup++;
2348da5ff23SMiklos Szeredi 			spin_unlock(&fc->lock);
2359e6268dbSMiklos Szeredi 		}
23607e77dcaSMiklos Szeredi 		kfree(forget);
2379e6268dbSMiklos Szeredi 		if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT)
238e5e5558eSMiklos Szeredi 			return 0;
239e5e5558eSMiklos Szeredi 
2401fb69e78SMiklos Szeredi 		fuse_change_attributes(inode, &outarg.attr,
2411fb69e78SMiklos Szeredi 				       entry_attr_timeout(&outarg),
2421fb69e78SMiklos Szeredi 				       attr_version);
2431fb69e78SMiklos Szeredi 		fuse_change_entry_timeout(entry, &outarg);
24428420dadSMiklos Szeredi 	} else if (inode) {
24528420dadSMiklos Szeredi 		fc = get_fuse_conn(inode);
24628420dadSMiklos Szeredi 		if (fc->readdirplus_auto) {
24728420dadSMiklos Szeredi 			parent = dget_parent(entry);
24828420dadSMiklos Szeredi 			fuse_advise_use_readdirplus(parent->d_inode);
24928420dadSMiklos Szeredi 			dput(parent);
250e5e5558eSMiklos Szeredi 		}
25128420dadSMiklos Szeredi 	}
252e5e5558eSMiklos Szeredi 	return 1;
253e5e5558eSMiklos Szeredi }
254e5e5558eSMiklos Szeredi 
2558bfc016dSMiklos Szeredi static int invalid_nodeid(u64 nodeid)
2562827d0b2SMiklos Szeredi {
2572827d0b2SMiklos Szeredi 	return !nodeid || nodeid == FUSE_ROOT_ID;
2582827d0b2SMiklos Szeredi }
2592827d0b2SMiklos Szeredi 
2604269590aSAl Viro const struct dentry_operations fuse_dentry_operations = {
261e5e5558eSMiklos Szeredi 	.d_revalidate	= fuse_dentry_revalidate,
262e5e5558eSMiklos Szeredi };
263e5e5558eSMiklos Szeredi 
264a5bfffacSTimo Savola int fuse_valid_type(int m)
26539ee059aSMiklos Szeredi {
26639ee059aSMiklos Szeredi 	return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) ||
26739ee059aSMiklos Szeredi 		S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m);
26839ee059aSMiklos Szeredi }
26939ee059aSMiklos Szeredi 
270d2a85164SMiklos Szeredi /*
271d2a85164SMiklos Szeredi  * Add a directory inode to a dentry, ensuring that no other dentry
272d2a85164SMiklos Szeredi  * refers to this inode.  Called with fc->inst_mutex.
273d2a85164SMiklos Szeredi  */
2740de6256dSMiklos Szeredi static struct dentry *fuse_d_add_directory(struct dentry *entry,
2750de6256dSMiklos Szeredi 					   struct inode *inode)
276d2a85164SMiklos Szeredi {
277d2a85164SMiklos Szeredi 	struct dentry *alias = d_find_alias(inode);
2780de6256dSMiklos Szeredi 	if (alias && !(alias->d_flags & DCACHE_DISCONNECTED)) {
279d2a85164SMiklos Szeredi 		/* This tries to shrink the subtree below alias */
280d2a85164SMiklos Szeredi 		fuse_invalidate_entry(alias);
281d2a85164SMiklos Szeredi 		dput(alias);
282b3d9b7a3SAl Viro 		if (!hlist_empty(&inode->i_dentry))
2830de6256dSMiklos Szeredi 			return ERR_PTR(-EBUSY);
2840de6256dSMiklos Szeredi 	} else {
2850de6256dSMiklos Szeredi 		dput(alias);
286d2a85164SMiklos Szeredi 	}
2870de6256dSMiklos Szeredi 	return d_splice_alias(inode, entry);
288d2a85164SMiklos Szeredi }
289d2a85164SMiklos Szeredi 
290c180eebeSMiklos Szeredi int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name,
291c180eebeSMiklos Szeredi 		     struct fuse_entry_out *outarg, struct inode **inode)
292c180eebeSMiklos Szeredi {
293c180eebeSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn_super(sb);
294c180eebeSMiklos Szeredi 	struct fuse_req *req;
29507e77dcaSMiklos Szeredi 	struct fuse_forget_link *forget;
296c180eebeSMiklos Szeredi 	u64 attr_version;
297c180eebeSMiklos Szeredi 	int err;
298c180eebeSMiklos Szeredi 
299c180eebeSMiklos Szeredi 	*inode = NULL;
300c180eebeSMiklos Szeredi 	err = -ENAMETOOLONG;
301c180eebeSMiklos Szeredi 	if (name->len > FUSE_NAME_MAX)
302c180eebeSMiklos Szeredi 		goto out;
303c180eebeSMiklos Szeredi 
304b111c8c0SMaxim Patlasov 	req = fuse_get_req_nopages(fc);
305c180eebeSMiklos Szeredi 	err = PTR_ERR(req);
306c180eebeSMiklos Szeredi 	if (IS_ERR(req))
307c180eebeSMiklos Szeredi 		goto out;
308c180eebeSMiklos Szeredi 
30907e77dcaSMiklos Szeredi 	forget = fuse_alloc_forget();
31007e77dcaSMiklos Szeredi 	err = -ENOMEM;
31107e77dcaSMiklos Szeredi 	if (!forget) {
312c180eebeSMiklos Szeredi 		fuse_put_request(fc, req);
313c180eebeSMiklos Szeredi 		goto out;
314c180eebeSMiklos Szeredi 	}
315c180eebeSMiklos Szeredi 
316c180eebeSMiklos Szeredi 	attr_version = fuse_get_attr_version(fc);
317c180eebeSMiklos Szeredi 
318c180eebeSMiklos Szeredi 	fuse_lookup_init(fc, req, nodeid, name, outarg);
319b93f858aSTejun Heo 	fuse_request_send(fc, req);
320c180eebeSMiklos Szeredi 	err = req->out.h.error;
321c180eebeSMiklos Szeredi 	fuse_put_request(fc, req);
322c180eebeSMiklos Szeredi 	/* Zero nodeid is same as -ENOENT, but with valid timeout */
323c180eebeSMiklos Szeredi 	if (err || !outarg->nodeid)
324c180eebeSMiklos Szeredi 		goto out_put_forget;
325c180eebeSMiklos Szeredi 
326c180eebeSMiklos Szeredi 	err = -EIO;
327c180eebeSMiklos Szeredi 	if (!outarg->nodeid)
328c180eebeSMiklos Szeredi 		goto out_put_forget;
329c180eebeSMiklos Szeredi 	if (!fuse_valid_type(outarg->attr.mode))
330c180eebeSMiklos Szeredi 		goto out_put_forget;
331c180eebeSMiklos Szeredi 
332c180eebeSMiklos Szeredi 	*inode = fuse_iget(sb, outarg->nodeid, outarg->generation,
333c180eebeSMiklos Szeredi 			   &outarg->attr, entry_attr_timeout(outarg),
334c180eebeSMiklos Szeredi 			   attr_version);
335c180eebeSMiklos Szeredi 	err = -ENOMEM;
336c180eebeSMiklos Szeredi 	if (!*inode) {
33707e77dcaSMiklos Szeredi 		fuse_queue_forget(fc, forget, outarg->nodeid, 1);
338c180eebeSMiklos Szeredi 		goto out;
339c180eebeSMiklos Szeredi 	}
340c180eebeSMiklos Szeredi 	err = 0;
341c180eebeSMiklos Szeredi 
342c180eebeSMiklos Szeredi  out_put_forget:
34307e77dcaSMiklos Szeredi 	kfree(forget);
344c180eebeSMiklos Szeredi  out:
345c180eebeSMiklos Szeredi 	return err;
346c180eebeSMiklos Szeredi }
347c180eebeSMiklos Szeredi 
3480aa7c699SMiklos Szeredi static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
34900cd8dd3SAl Viro 				  unsigned int flags)
350e5e5558eSMiklos Szeredi {
351e5e5558eSMiklos Szeredi 	int err;
352e5e5558eSMiklos Szeredi 	struct fuse_entry_out outarg;
353c180eebeSMiklos Szeredi 	struct inode *inode;
3540de6256dSMiklos Szeredi 	struct dentry *newent;
355e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
356c180eebeSMiklos Szeredi 	bool outarg_valid = true;
357e5e5558eSMiklos Szeredi 
358c180eebeSMiklos Szeredi 	err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name,
359c180eebeSMiklos Szeredi 			       &outarg, &inode);
360c180eebeSMiklos Szeredi 	if (err == -ENOENT) {
361c180eebeSMiklos Szeredi 		outarg_valid = false;
362c180eebeSMiklos Szeredi 		err = 0;
3632d51013eSMiklos Szeredi 	}
364c180eebeSMiklos Szeredi 	if (err)
365c180eebeSMiklos Szeredi 		goto out_err;
3662d51013eSMiklos Szeredi 
367ee4e5271SMiklos Szeredi 	err = -EIO;
368c180eebeSMiklos Szeredi 	if (inode && get_node_id(inode) == FUSE_ROOT_ID)
369c180eebeSMiklos Szeredi 		goto out_iput;
370e5e5558eSMiklos Szeredi 
371d2a85164SMiklos Szeredi 	if (inode && S_ISDIR(inode->i_mode)) {
372d2a85164SMiklos Szeredi 		mutex_lock(&fc->inst_mutex);
3730de6256dSMiklos Szeredi 		newent = fuse_d_add_directory(entry, inode);
374d2a85164SMiklos Szeredi 		mutex_unlock(&fc->inst_mutex);
375c180eebeSMiklos Szeredi 		err = PTR_ERR(newent);
376c180eebeSMiklos Szeredi 		if (IS_ERR(newent))
377c180eebeSMiklos Szeredi 			goto out_iput;
378c180eebeSMiklos Szeredi 	} else {
3790de6256dSMiklos Szeredi 		newent = d_splice_alias(inode, entry);
380c180eebeSMiklos Szeredi 	}
381d2a85164SMiklos Szeredi 
3820de6256dSMiklos Szeredi 	entry = newent ? newent : entry;
383c180eebeSMiklos Szeredi 	if (outarg_valid)
3841fb69e78SMiklos Szeredi 		fuse_change_entry_timeout(entry, &outarg);
3858cbdf1e6SMiklos Szeredi 	else
3868cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
387c180eebeSMiklos Szeredi 
3884582a4abSFeng Shuo 	fuse_advise_use_readdirplus(dir);
3890de6256dSMiklos Szeredi 	return newent;
390c180eebeSMiklos Szeredi 
391c180eebeSMiklos Szeredi  out_iput:
392c180eebeSMiklos Szeredi 	iput(inode);
393c180eebeSMiklos Szeredi  out_err:
394c180eebeSMiklos Szeredi 	return ERR_PTR(err);
395e5e5558eSMiklos Szeredi }
396e5e5558eSMiklos Szeredi 
3976f9f1180SMiklos Szeredi /*
3986f9f1180SMiklos Szeredi  * Atomic create+open operation
3996f9f1180SMiklos Szeredi  *
4006f9f1180SMiklos Szeredi  * If the filesystem doesn't support this, then fall back to separate
4016f9f1180SMiklos Szeredi  * 'mknod' + 'open' requests.
4026f9f1180SMiklos Szeredi  */
403d9585277SAl Viro static int fuse_create_open(struct inode *dir, struct dentry *entry,
40430d90494SAl Viro 			    struct file *file, unsigned flags,
40547237687SAl Viro 			    umode_t mode, int *opened)
406fd72faacSMiklos Szeredi {
407fd72faacSMiklos Szeredi 	int err;
408fd72faacSMiklos Szeredi 	struct inode *inode;
409fd72faacSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
410fd72faacSMiklos Szeredi 	struct fuse_req *req;
41107e77dcaSMiklos Szeredi 	struct fuse_forget_link *forget;
412e0a43ddcSMiklos Szeredi 	struct fuse_create_in inarg;
413fd72faacSMiklos Szeredi 	struct fuse_open_out outopen;
414fd72faacSMiklos Szeredi 	struct fuse_entry_out outentry;
415fd72faacSMiklos Szeredi 	struct fuse_file *ff;
416fd72faacSMiklos Szeredi 
417af109bcaSMiklos Szeredi 	/* Userspace expects S_IFREG in create mode */
418af109bcaSMiklos Szeredi 	BUG_ON((mode & S_IFMT) != S_IFREG);
419af109bcaSMiklos Szeredi 
42007e77dcaSMiklos Szeredi 	forget = fuse_alloc_forget();
421c8ccbe03SMiklos Szeredi 	err = -ENOMEM;
42207e77dcaSMiklos Szeredi 	if (!forget)
423c8ccbe03SMiklos Szeredi 		goto out_err;
42451eb01e7SMiklos Szeredi 
425b111c8c0SMaxim Patlasov 	req = fuse_get_req_nopages(fc);
42651eb01e7SMiklos Szeredi 	err = PTR_ERR(req);
427ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
42851eb01e7SMiklos Szeredi 		goto out_put_forget_req;
429fd72faacSMiklos Szeredi 
430ce1d5a49SMiklos Szeredi 	err = -ENOMEM;
431acf99433STejun Heo 	ff = fuse_file_alloc(fc);
432fd72faacSMiklos Szeredi 	if (!ff)
433fd72faacSMiklos Szeredi 		goto out_put_request;
434fd72faacSMiklos Szeredi 
435e0a43ddcSMiklos Szeredi 	if (!fc->dont_mask)
436e0a43ddcSMiklos Szeredi 		mode &= ~current_umask();
437e0a43ddcSMiklos Szeredi 
438fd72faacSMiklos Szeredi 	flags &= ~O_NOCTTY;
439fd72faacSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
4400e9663eeSMiklos Szeredi 	memset(&outentry, 0, sizeof(outentry));
441fd72faacSMiklos Szeredi 	inarg.flags = flags;
442fd72faacSMiklos Szeredi 	inarg.mode = mode;
443e0a43ddcSMiklos Szeredi 	inarg.umask = current_umask();
444fd72faacSMiklos Szeredi 	req->in.h.opcode = FUSE_CREATE;
445fd72faacSMiklos Szeredi 	req->in.h.nodeid = get_node_id(dir);
446fd72faacSMiklos Szeredi 	req->in.numargs = 2;
447e0a43ddcSMiklos Szeredi 	req->in.args[0].size = fc->minor < 12 ? sizeof(struct fuse_open_in) :
448e0a43ddcSMiklos Szeredi 						sizeof(inarg);
449fd72faacSMiklos Szeredi 	req->in.args[0].value = &inarg;
450fd72faacSMiklos Szeredi 	req->in.args[1].size = entry->d_name.len + 1;
451fd72faacSMiklos Szeredi 	req->in.args[1].value = entry->d_name.name;
452fd72faacSMiklos Szeredi 	req->out.numargs = 2;
4530e9663eeSMiklos Szeredi 	if (fc->minor < 9)
4540e9663eeSMiklos Szeredi 		req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
4550e9663eeSMiklos Szeredi 	else
456fd72faacSMiklos Szeredi 		req->out.args[0].size = sizeof(outentry);
457fd72faacSMiklos Szeredi 	req->out.args[0].value = &outentry;
458fd72faacSMiklos Szeredi 	req->out.args[1].size = sizeof(outopen);
459fd72faacSMiklos Szeredi 	req->out.args[1].value = &outopen;
460b93f858aSTejun Heo 	fuse_request_send(fc, req);
461fd72faacSMiklos Szeredi 	err = req->out.h.error;
462c8ccbe03SMiklos Szeredi 	if (err)
463fd72faacSMiklos Szeredi 		goto out_free_ff;
464fd72faacSMiklos Szeredi 
465fd72faacSMiklos Szeredi 	err = -EIO;
4662827d0b2SMiklos Szeredi 	if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid))
467fd72faacSMiklos Szeredi 		goto out_free_ff;
468fd72faacSMiklos Szeredi 
46951eb01e7SMiklos Szeredi 	fuse_put_request(fc, req);
470c7b7143cSMiklos Szeredi 	ff->fh = outopen.fh;
471c7b7143cSMiklos Szeredi 	ff->nodeid = outentry.nodeid;
472c7b7143cSMiklos Szeredi 	ff->open_flags = outopen.open_flags;
473fd72faacSMiklos Szeredi 	inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
4741fb69e78SMiklos Szeredi 			  &outentry.attr, entry_attr_timeout(&outentry), 0);
475fd72faacSMiklos Szeredi 	if (!inode) {
476fd72faacSMiklos Szeredi 		flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
4778b0797a4SMiklos Szeredi 		fuse_sync_release(ff, flags);
47807e77dcaSMiklos Szeredi 		fuse_queue_forget(fc, forget, outentry.nodeid, 1);
479c8ccbe03SMiklos Szeredi 		err = -ENOMEM;
480c8ccbe03SMiklos Szeredi 		goto out_err;
481fd72faacSMiklos Szeredi 	}
48207e77dcaSMiklos Szeredi 	kfree(forget);
483fd72faacSMiklos Szeredi 	d_instantiate(entry, inode);
4841fb69e78SMiklos Szeredi 	fuse_change_entry_timeout(entry, &outentry);
4850952b2a4SMiklos Szeredi 	fuse_invalidate_attr(dir);
48630d90494SAl Viro 	err = finish_open(file, entry, generic_file_open, opened);
48730d90494SAl Viro 	if (err) {
4888b0797a4SMiklos Szeredi 		fuse_sync_release(ff, flags);
489c8ccbe03SMiklos Szeredi 	} else {
490c7b7143cSMiklos Szeredi 		file->private_data = fuse_file_get(ff);
491c7b7143cSMiklos Szeredi 		fuse_finish_open(inode, file);
492c8ccbe03SMiklos Szeredi 	}
493d9585277SAl Viro 	return err;
494fd72faacSMiklos Szeredi 
495fd72faacSMiklos Szeredi out_free_ff:
496fd72faacSMiklos Szeredi 	fuse_file_free(ff);
497fd72faacSMiklos Szeredi out_put_request:
498fd72faacSMiklos Szeredi 	fuse_put_request(fc, req);
49951eb01e7SMiklos Szeredi out_put_forget_req:
50007e77dcaSMiklos Szeredi 	kfree(forget);
501c8ccbe03SMiklos Szeredi out_err:
502d9585277SAl Viro 	return err;
503c8ccbe03SMiklos Szeredi }
504c8ccbe03SMiklos Szeredi 
505c8ccbe03SMiklos Szeredi static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t);
506d9585277SAl Viro static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
50730d90494SAl Viro 			    struct file *file, unsigned flags,
50847237687SAl Viro 			    umode_t mode, int *opened)
509c8ccbe03SMiklos Szeredi {
510c8ccbe03SMiklos Szeredi 	int err;
511c8ccbe03SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
512c8ccbe03SMiklos Szeredi 	struct dentry *res = NULL;
513c8ccbe03SMiklos Szeredi 
514c8ccbe03SMiklos Szeredi 	if (d_unhashed(entry)) {
51500cd8dd3SAl Viro 		res = fuse_lookup(dir, entry, 0);
516c8ccbe03SMiklos Szeredi 		if (IS_ERR(res))
517d9585277SAl Viro 			return PTR_ERR(res);
518c8ccbe03SMiklos Szeredi 
519c8ccbe03SMiklos Szeredi 		if (res)
520c8ccbe03SMiklos Szeredi 			entry = res;
521c8ccbe03SMiklos Szeredi 	}
522c8ccbe03SMiklos Szeredi 
523c8ccbe03SMiklos Szeredi 	if (!(flags & O_CREAT) || entry->d_inode)
524c8ccbe03SMiklos Szeredi 		goto no_open;
525c8ccbe03SMiklos Szeredi 
526c8ccbe03SMiklos Szeredi 	/* Only creates */
52747237687SAl Viro 	*opened |= FILE_CREATED;
528c8ccbe03SMiklos Szeredi 
529c8ccbe03SMiklos Szeredi 	if (fc->no_create)
530c8ccbe03SMiklos Szeredi 		goto mknod;
531c8ccbe03SMiklos Szeredi 
53230d90494SAl Viro 	err = fuse_create_open(dir, entry, file, flags, mode, opened);
533d9585277SAl Viro 	if (err == -ENOSYS) {
534c8ccbe03SMiklos Szeredi 		fc->no_create = 1;
535c8ccbe03SMiklos Szeredi 		goto mknod;
536c8ccbe03SMiklos Szeredi 	}
537c8ccbe03SMiklos Szeredi out_dput:
538c8ccbe03SMiklos Szeredi 	dput(res);
539d9585277SAl Viro 	return err;
540c8ccbe03SMiklos Szeredi 
541c8ccbe03SMiklos Szeredi mknod:
542c8ccbe03SMiklos Szeredi 	err = fuse_mknod(dir, entry, mode, 0);
543d9585277SAl Viro 	if (err)
544c8ccbe03SMiklos Szeredi 		goto out_dput;
545c8ccbe03SMiklos Szeredi no_open:
546e45198a6SAl Viro 	return finish_no_open(file, res);
547fd72faacSMiklos Szeredi }
548fd72faacSMiklos Szeredi 
5496f9f1180SMiklos Szeredi /*
5506f9f1180SMiklos Szeredi  * Code shared between mknod, mkdir, symlink and link
5516f9f1180SMiklos Szeredi  */
5529e6268dbSMiklos Szeredi static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
5539e6268dbSMiklos Szeredi 			    struct inode *dir, struct dentry *entry,
554541af6a0SAl Viro 			    umode_t mode)
5559e6268dbSMiklos Szeredi {
5569e6268dbSMiklos Szeredi 	struct fuse_entry_out outarg;
5579e6268dbSMiklos Szeredi 	struct inode *inode;
5589e6268dbSMiklos Szeredi 	int err;
55907e77dcaSMiklos Szeredi 	struct fuse_forget_link *forget;
5602d51013eSMiklos Szeredi 
56107e77dcaSMiklos Szeredi 	forget = fuse_alloc_forget();
56207e77dcaSMiklos Szeredi 	if (!forget) {
5632d51013eSMiklos Szeredi 		fuse_put_request(fc, req);
56407e77dcaSMiklos Szeredi 		return -ENOMEM;
5652d51013eSMiklos Szeredi 	}
5669e6268dbSMiklos Szeredi 
5670e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
5689e6268dbSMiklos Szeredi 	req->in.h.nodeid = get_node_id(dir);
5699e6268dbSMiklos Szeredi 	req->out.numargs = 1;
5700e9663eeSMiklos Szeredi 	if (fc->minor < 9)
5710e9663eeSMiklos Szeredi 		req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
5720e9663eeSMiklos Szeredi 	else
5739e6268dbSMiklos Szeredi 		req->out.args[0].size = sizeof(outarg);
5749e6268dbSMiklos Szeredi 	req->out.args[0].value = &outarg;
575b93f858aSTejun Heo 	fuse_request_send(fc, req);
5769e6268dbSMiklos Szeredi 	err = req->out.h.error;
5779e6268dbSMiklos Szeredi 	fuse_put_request(fc, req);
5782d51013eSMiklos Szeredi 	if (err)
5792d51013eSMiklos Szeredi 		goto out_put_forget_req;
5802d51013eSMiklos Szeredi 
58139ee059aSMiklos Szeredi 	err = -EIO;
58239ee059aSMiklos Szeredi 	if (invalid_nodeid(outarg.nodeid))
5832d51013eSMiklos Szeredi 		goto out_put_forget_req;
58439ee059aSMiklos Szeredi 
58539ee059aSMiklos Szeredi 	if ((outarg.attr.mode ^ mode) & S_IFMT)
5862d51013eSMiklos Szeredi 		goto out_put_forget_req;
58739ee059aSMiklos Szeredi 
5889e6268dbSMiklos Szeredi 	inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
5891fb69e78SMiklos Szeredi 			  &outarg.attr, entry_attr_timeout(&outarg), 0);
5909e6268dbSMiklos Szeredi 	if (!inode) {
59107e77dcaSMiklos Szeredi 		fuse_queue_forget(fc, forget, outarg.nodeid, 1);
5929e6268dbSMiklos Szeredi 		return -ENOMEM;
5939e6268dbSMiklos Szeredi 	}
59407e77dcaSMiklos Szeredi 	kfree(forget);
5959e6268dbSMiklos Szeredi 
596d2a85164SMiklos Szeredi 	if (S_ISDIR(inode->i_mode)) {
597d2a85164SMiklos Szeredi 		struct dentry *alias;
598d2a85164SMiklos Szeredi 		mutex_lock(&fc->inst_mutex);
599d2a85164SMiklos Szeredi 		alias = d_find_alias(inode);
600d2a85164SMiklos Szeredi 		if (alias) {
601d2a85164SMiklos Szeredi 			/* New directory must have moved since mkdir */
602d2a85164SMiklos Szeredi 			mutex_unlock(&fc->inst_mutex);
603d2a85164SMiklos Szeredi 			dput(alias);
6049e6268dbSMiklos Szeredi 			iput(inode);
605d2a85164SMiklos Szeredi 			return -EBUSY;
6069e6268dbSMiklos Szeredi 		}
6079e6268dbSMiklos Szeredi 		d_instantiate(entry, inode);
608d2a85164SMiklos Szeredi 		mutex_unlock(&fc->inst_mutex);
609d2a85164SMiklos Szeredi 	} else
610d2a85164SMiklos Szeredi 		d_instantiate(entry, inode);
611d2a85164SMiklos Szeredi 
6121fb69e78SMiklos Szeredi 	fuse_change_entry_timeout(entry, &outarg);
6139e6268dbSMiklos Szeredi 	fuse_invalidate_attr(dir);
6149e6268dbSMiklos Szeredi 	return 0;
61539ee059aSMiklos Szeredi 
6162d51013eSMiklos Szeredi  out_put_forget_req:
61707e77dcaSMiklos Szeredi 	kfree(forget);
61839ee059aSMiklos Szeredi 	return err;
6199e6268dbSMiklos Szeredi }
6209e6268dbSMiklos Szeredi 
6211a67aafbSAl Viro static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode,
6229e6268dbSMiklos Szeredi 		      dev_t rdev)
6239e6268dbSMiklos Szeredi {
6249e6268dbSMiklos Szeredi 	struct fuse_mknod_in inarg;
6259e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
626b111c8c0SMaxim Patlasov 	struct fuse_req *req = fuse_get_req_nopages(fc);
627ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
628ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
6299e6268dbSMiklos Szeredi 
630e0a43ddcSMiklos Szeredi 	if (!fc->dont_mask)
631e0a43ddcSMiklos Szeredi 		mode &= ~current_umask();
632e0a43ddcSMiklos Szeredi 
6339e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
6349e6268dbSMiklos Szeredi 	inarg.mode = mode;
6359e6268dbSMiklos Szeredi 	inarg.rdev = new_encode_dev(rdev);
636e0a43ddcSMiklos Szeredi 	inarg.umask = current_umask();
6379e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_MKNOD;
6389e6268dbSMiklos Szeredi 	req->in.numargs = 2;
639e0a43ddcSMiklos Szeredi 	req->in.args[0].size = fc->minor < 12 ? FUSE_COMPAT_MKNOD_IN_SIZE :
640e0a43ddcSMiklos Szeredi 						sizeof(inarg);
6419e6268dbSMiklos Szeredi 	req->in.args[0].value = &inarg;
6429e6268dbSMiklos Szeredi 	req->in.args[1].size = entry->d_name.len + 1;
6439e6268dbSMiklos Szeredi 	req->in.args[1].value = entry->d_name.name;
6449e6268dbSMiklos Szeredi 	return create_new_entry(fc, req, dir, entry, mode);
6459e6268dbSMiklos Szeredi }
6469e6268dbSMiklos Szeredi 
6474acdaf27SAl Viro static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode,
648ebfc3b49SAl Viro 		       bool excl)
6499e6268dbSMiklos Szeredi {
6509e6268dbSMiklos Szeredi 	return fuse_mknod(dir, entry, mode, 0);
6519e6268dbSMiklos Szeredi }
6529e6268dbSMiklos Szeredi 
65318bb1db3SAl Viro static int fuse_mkdir(struct inode *dir, struct dentry *entry, umode_t mode)
6549e6268dbSMiklos Szeredi {
6559e6268dbSMiklos Szeredi 	struct fuse_mkdir_in inarg;
6569e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
657b111c8c0SMaxim Patlasov 	struct fuse_req *req = fuse_get_req_nopages(fc);
658ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
659ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
6609e6268dbSMiklos Szeredi 
661e0a43ddcSMiklos Szeredi 	if (!fc->dont_mask)
662e0a43ddcSMiklos Szeredi 		mode &= ~current_umask();
663e0a43ddcSMiklos Szeredi 
6649e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
6659e6268dbSMiklos Szeredi 	inarg.mode = mode;
666e0a43ddcSMiklos Szeredi 	inarg.umask = current_umask();
6679e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_MKDIR;
6689e6268dbSMiklos Szeredi 	req->in.numargs = 2;
6699e6268dbSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
6709e6268dbSMiklos Szeredi 	req->in.args[0].value = &inarg;
6719e6268dbSMiklos Szeredi 	req->in.args[1].size = entry->d_name.len + 1;
6729e6268dbSMiklos Szeredi 	req->in.args[1].value = entry->d_name.name;
6739e6268dbSMiklos Szeredi 	return create_new_entry(fc, req, dir, entry, S_IFDIR);
6749e6268dbSMiklos Szeredi }
6759e6268dbSMiklos Szeredi 
6769e6268dbSMiklos Szeredi static int fuse_symlink(struct inode *dir, struct dentry *entry,
6779e6268dbSMiklos Szeredi 			const char *link)
6789e6268dbSMiklos Szeredi {
6799e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
6809e6268dbSMiklos Szeredi 	unsigned len = strlen(link) + 1;
681b111c8c0SMaxim Patlasov 	struct fuse_req *req = fuse_get_req_nopages(fc);
682ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
683ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
6849e6268dbSMiklos Szeredi 
6859e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_SYMLINK;
6869e6268dbSMiklos Szeredi 	req->in.numargs = 2;
6879e6268dbSMiklos Szeredi 	req->in.args[0].size = entry->d_name.len + 1;
6889e6268dbSMiklos Szeredi 	req->in.args[0].value = entry->d_name.name;
6899e6268dbSMiklos Szeredi 	req->in.args[1].size = len;
6909e6268dbSMiklos Szeredi 	req->in.args[1].value = link;
6919e6268dbSMiklos Szeredi 	return create_new_entry(fc, req, dir, entry, S_IFLNK);
6929e6268dbSMiklos Szeredi }
6939e6268dbSMiklos Szeredi 
6949e6268dbSMiklos Szeredi static int fuse_unlink(struct inode *dir, struct dentry *entry)
6959e6268dbSMiklos Szeredi {
6969e6268dbSMiklos Szeredi 	int err;
6979e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
698b111c8c0SMaxim Patlasov 	struct fuse_req *req = fuse_get_req_nopages(fc);
699ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
700ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
7019e6268dbSMiklos Szeredi 
7029e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_UNLINK;
7039e6268dbSMiklos Szeredi 	req->in.h.nodeid = get_node_id(dir);
7049e6268dbSMiklos Szeredi 	req->in.numargs = 1;
7059e6268dbSMiklos Szeredi 	req->in.args[0].size = entry->d_name.len + 1;
7069e6268dbSMiklos Szeredi 	req->in.args[0].value = entry->d_name.name;
707b93f858aSTejun Heo 	fuse_request_send(fc, req);
7089e6268dbSMiklos Szeredi 	err = req->out.h.error;
7099e6268dbSMiklos Szeredi 	fuse_put_request(fc, req);
7109e6268dbSMiklos Szeredi 	if (!err) {
7119e6268dbSMiklos Szeredi 		struct inode *inode = entry->d_inode;
712ac45d613SMiklos Szeredi 		struct fuse_inode *fi = get_fuse_inode(inode);
7139e6268dbSMiklos Szeredi 
714ac45d613SMiklos Szeredi 		spin_lock(&fc->lock);
715ac45d613SMiklos Szeredi 		fi->attr_version = ++fc->attr_version;
716dfca7cebSMiklos Szeredi 		/*
717dfca7cebSMiklos Szeredi 		 * If i_nlink == 0 then unlink doesn't make sense, yet this can
718dfca7cebSMiklos Szeredi 		 * happen if userspace filesystem is careless.  It would be
719dfca7cebSMiklos Szeredi 		 * difficult to enforce correct nlink usage so just ignore this
720dfca7cebSMiklos Szeredi 		 * condition here
721dfca7cebSMiklos Szeredi 		 */
722dfca7cebSMiklos Szeredi 		if (inode->i_nlink > 0)
723ac45d613SMiklos Szeredi 			drop_nlink(inode);
724ac45d613SMiklos Szeredi 		spin_unlock(&fc->lock);
7259e6268dbSMiklos Szeredi 		fuse_invalidate_attr(inode);
7269e6268dbSMiklos Szeredi 		fuse_invalidate_attr(dir);
7278cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
7289e6268dbSMiklos Szeredi 	} else if (err == -EINTR)
7299e6268dbSMiklos Szeredi 		fuse_invalidate_entry(entry);
7309e6268dbSMiklos Szeredi 	return err;
7319e6268dbSMiklos Szeredi }
7329e6268dbSMiklos Szeredi 
7339e6268dbSMiklos Szeredi static int fuse_rmdir(struct inode *dir, struct dentry *entry)
7349e6268dbSMiklos Szeredi {
7359e6268dbSMiklos Szeredi 	int err;
7369e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
737b111c8c0SMaxim Patlasov 	struct fuse_req *req = fuse_get_req_nopages(fc);
738ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
739ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
7409e6268dbSMiklos Szeredi 
7419e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_RMDIR;
7429e6268dbSMiklos Szeredi 	req->in.h.nodeid = get_node_id(dir);
7439e6268dbSMiklos Szeredi 	req->in.numargs = 1;
7449e6268dbSMiklos Szeredi 	req->in.args[0].size = entry->d_name.len + 1;
7459e6268dbSMiklos Szeredi 	req->in.args[0].value = entry->d_name.name;
746b93f858aSTejun Heo 	fuse_request_send(fc, req);
7479e6268dbSMiklos Szeredi 	err = req->out.h.error;
7489e6268dbSMiklos Szeredi 	fuse_put_request(fc, req);
7499e6268dbSMiklos Szeredi 	if (!err) {
750ce71ec36SDave Hansen 		clear_nlink(entry->d_inode);
7519e6268dbSMiklos Szeredi 		fuse_invalidate_attr(dir);
7528cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
7539e6268dbSMiklos Szeredi 	} else if (err == -EINTR)
7549e6268dbSMiklos Szeredi 		fuse_invalidate_entry(entry);
7559e6268dbSMiklos Szeredi 	return err;
7569e6268dbSMiklos Szeredi }
7579e6268dbSMiklos Szeredi 
7589e6268dbSMiklos Szeredi static int fuse_rename(struct inode *olddir, struct dentry *oldent,
7599e6268dbSMiklos Szeredi 		       struct inode *newdir, struct dentry *newent)
7609e6268dbSMiklos Szeredi {
7619e6268dbSMiklos Szeredi 	int err;
7629e6268dbSMiklos Szeredi 	struct fuse_rename_in inarg;
7639e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(olddir);
764b111c8c0SMaxim Patlasov 	struct fuse_req *req = fuse_get_req_nopages(fc);
765e4eaac06SSage Weil 
766ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
767ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
7689e6268dbSMiklos Szeredi 
7699e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
7709e6268dbSMiklos Szeredi 	inarg.newdir = get_node_id(newdir);
7719e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_RENAME;
7729e6268dbSMiklos Szeredi 	req->in.h.nodeid = get_node_id(olddir);
7739e6268dbSMiklos Szeredi 	req->in.numargs = 3;
7749e6268dbSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
7759e6268dbSMiklos Szeredi 	req->in.args[0].value = &inarg;
7769e6268dbSMiklos Szeredi 	req->in.args[1].size = oldent->d_name.len + 1;
7779e6268dbSMiklos Szeredi 	req->in.args[1].value = oldent->d_name.name;
7789e6268dbSMiklos Szeredi 	req->in.args[2].size = newent->d_name.len + 1;
7799e6268dbSMiklos Szeredi 	req->in.args[2].value = newent->d_name.name;
780b93f858aSTejun Heo 	fuse_request_send(fc, req);
7819e6268dbSMiklos Szeredi 	err = req->out.h.error;
7829e6268dbSMiklos Szeredi 	fuse_put_request(fc, req);
7839e6268dbSMiklos Szeredi 	if (!err) {
78408b63307SMiklos Szeredi 		/* ctime changes */
78508b63307SMiklos Szeredi 		fuse_invalidate_attr(oldent->d_inode);
78608b63307SMiklos Szeredi 
7879e6268dbSMiklos Szeredi 		fuse_invalidate_attr(olddir);
7889e6268dbSMiklos Szeredi 		if (olddir != newdir)
7899e6268dbSMiklos Szeredi 			fuse_invalidate_attr(newdir);
7908cbdf1e6SMiklos Szeredi 
7918cbdf1e6SMiklos Szeredi 		/* newent will end up negative */
7925219f346SMiklos Szeredi 		if (newent->d_inode) {
7935219f346SMiklos Szeredi 			fuse_invalidate_attr(newent->d_inode);
7948cbdf1e6SMiklos Szeredi 			fuse_invalidate_entry_cache(newent);
7955219f346SMiklos Szeredi 		}
7969e6268dbSMiklos Szeredi 	} else if (err == -EINTR) {
7979e6268dbSMiklos Szeredi 		/* If request was interrupted, DEITY only knows if the
7989e6268dbSMiklos Szeredi 		   rename actually took place.  If the invalidation
7999e6268dbSMiklos Szeredi 		   fails (e.g. some process has CWD under the renamed
8009e6268dbSMiklos Szeredi 		   directory), then there can be inconsistency between
8019e6268dbSMiklos Szeredi 		   the dcache and the real filesystem.  Tough luck. */
8029e6268dbSMiklos Szeredi 		fuse_invalidate_entry(oldent);
8039e6268dbSMiklos Szeredi 		if (newent->d_inode)
8049e6268dbSMiklos Szeredi 			fuse_invalidate_entry(newent);
8059e6268dbSMiklos Szeredi 	}
8069e6268dbSMiklos Szeredi 
8079e6268dbSMiklos Szeredi 	return err;
8089e6268dbSMiklos Szeredi }
8099e6268dbSMiklos Szeredi 
8109e6268dbSMiklos Szeredi static int fuse_link(struct dentry *entry, struct inode *newdir,
8119e6268dbSMiklos Szeredi 		     struct dentry *newent)
8129e6268dbSMiklos Szeredi {
8139e6268dbSMiklos Szeredi 	int err;
8149e6268dbSMiklos Szeredi 	struct fuse_link_in inarg;
8159e6268dbSMiklos Szeredi 	struct inode *inode = entry->d_inode;
8169e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
817b111c8c0SMaxim Patlasov 	struct fuse_req *req = fuse_get_req_nopages(fc);
818ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
819ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
8209e6268dbSMiklos Szeredi 
8219e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
8229e6268dbSMiklos Szeredi 	inarg.oldnodeid = get_node_id(inode);
8239e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_LINK;
8249e6268dbSMiklos Szeredi 	req->in.numargs = 2;
8259e6268dbSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
8269e6268dbSMiklos Szeredi 	req->in.args[0].value = &inarg;
8279e6268dbSMiklos Szeredi 	req->in.args[1].size = newent->d_name.len + 1;
8289e6268dbSMiklos Szeredi 	req->in.args[1].value = newent->d_name.name;
8299e6268dbSMiklos Szeredi 	err = create_new_entry(fc, req, newdir, newent, inode->i_mode);
8309e6268dbSMiklos Szeredi 	/* Contrary to "normal" filesystems it can happen that link
8319e6268dbSMiklos Szeredi 	   makes two "logical" inodes point to the same "physical"
8329e6268dbSMiklos Szeredi 	   inode.  We invalidate the attributes of the old one, so it
8339e6268dbSMiklos Szeredi 	   will reflect changes in the backing inode (link count,
8349e6268dbSMiklos Szeredi 	   etc.)
8359e6268dbSMiklos Szeredi 	*/
836ac45d613SMiklos Szeredi 	if (!err) {
837ac45d613SMiklos Szeredi 		struct fuse_inode *fi = get_fuse_inode(inode);
838ac45d613SMiklos Szeredi 
839ac45d613SMiklos Szeredi 		spin_lock(&fc->lock);
840ac45d613SMiklos Szeredi 		fi->attr_version = ++fc->attr_version;
841ac45d613SMiklos Szeredi 		inc_nlink(inode);
842ac45d613SMiklos Szeredi 		spin_unlock(&fc->lock);
8439e6268dbSMiklos Szeredi 		fuse_invalidate_attr(inode);
844ac45d613SMiklos Szeredi 	} else if (err == -EINTR) {
845ac45d613SMiklos Szeredi 		fuse_invalidate_attr(inode);
846ac45d613SMiklos Szeredi 	}
8479e6268dbSMiklos Szeredi 	return err;
8489e6268dbSMiklos Szeredi }
8499e6268dbSMiklos Szeredi 
8501fb69e78SMiklos Szeredi static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
8511fb69e78SMiklos Szeredi 			  struct kstat *stat)
8521fb69e78SMiklos Szeredi {
853203627bbSMiklos Szeredi 	unsigned int blkbits;
854203627bbSMiklos Szeredi 
8551fb69e78SMiklos Szeredi 	stat->dev = inode->i_sb->s_dev;
8561fb69e78SMiklos Szeredi 	stat->ino = attr->ino;
8571fb69e78SMiklos Szeredi 	stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
8581fb69e78SMiklos Szeredi 	stat->nlink = attr->nlink;
859499dcf20SEric W. Biederman 	stat->uid = make_kuid(&init_user_ns, attr->uid);
860499dcf20SEric W. Biederman 	stat->gid = make_kgid(&init_user_ns, attr->gid);
8611fb69e78SMiklos Szeredi 	stat->rdev = inode->i_rdev;
8621fb69e78SMiklos Szeredi 	stat->atime.tv_sec = attr->atime;
8631fb69e78SMiklos Szeredi 	stat->atime.tv_nsec = attr->atimensec;
8641fb69e78SMiklos Szeredi 	stat->mtime.tv_sec = attr->mtime;
8651fb69e78SMiklos Szeredi 	stat->mtime.tv_nsec = attr->mtimensec;
8661fb69e78SMiklos Szeredi 	stat->ctime.tv_sec = attr->ctime;
8671fb69e78SMiklos Szeredi 	stat->ctime.tv_nsec = attr->ctimensec;
8681fb69e78SMiklos Szeredi 	stat->size = attr->size;
8691fb69e78SMiklos Szeredi 	stat->blocks = attr->blocks;
870203627bbSMiklos Szeredi 
871203627bbSMiklos Szeredi 	if (attr->blksize != 0)
872203627bbSMiklos Szeredi 		blkbits = ilog2(attr->blksize);
873203627bbSMiklos Szeredi 	else
874203627bbSMiklos Szeredi 		blkbits = inode->i_sb->s_blocksize_bits;
875203627bbSMiklos Szeredi 
876203627bbSMiklos Szeredi 	stat->blksize = 1 << blkbits;
8771fb69e78SMiklos Szeredi }
8781fb69e78SMiklos Szeredi 
879c79e322fSMiklos Szeredi static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
880c79e322fSMiklos Szeredi 			   struct file *file)
881e5e5558eSMiklos Szeredi {
882e5e5558eSMiklos Szeredi 	int err;
883c79e322fSMiklos Szeredi 	struct fuse_getattr_in inarg;
884c79e322fSMiklos Szeredi 	struct fuse_attr_out outarg;
885e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
8861fb69e78SMiklos Szeredi 	struct fuse_req *req;
8871fb69e78SMiklos Szeredi 	u64 attr_version;
8881fb69e78SMiklos Szeredi 
889b111c8c0SMaxim Patlasov 	req = fuse_get_req_nopages(fc);
890ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
891ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
892e5e5558eSMiklos Szeredi 
8937dca9fd3SMiklos Szeredi 	attr_version = fuse_get_attr_version(fc);
8941fb69e78SMiklos Szeredi 
895c79e322fSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
8960e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
897c79e322fSMiklos Szeredi 	/* Directories have separate file-handle space */
898c79e322fSMiklos Szeredi 	if (file && S_ISREG(inode->i_mode)) {
899c79e322fSMiklos Szeredi 		struct fuse_file *ff = file->private_data;
900c79e322fSMiklos Szeredi 
901c79e322fSMiklos Szeredi 		inarg.getattr_flags |= FUSE_GETATTR_FH;
902c79e322fSMiklos Szeredi 		inarg.fh = ff->fh;
903c79e322fSMiklos Szeredi 	}
904e5e5558eSMiklos Szeredi 	req->in.h.opcode = FUSE_GETATTR;
905e5e5558eSMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
906c79e322fSMiklos Szeredi 	req->in.numargs = 1;
907c79e322fSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
908c79e322fSMiklos Szeredi 	req->in.args[0].value = &inarg;
909e5e5558eSMiklos Szeredi 	req->out.numargs = 1;
9100e9663eeSMiklos Szeredi 	if (fc->minor < 9)
9110e9663eeSMiklos Szeredi 		req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
9120e9663eeSMiklos Szeredi 	else
913c79e322fSMiklos Szeredi 		req->out.args[0].size = sizeof(outarg);
914c79e322fSMiklos Szeredi 	req->out.args[0].value = &outarg;
915b93f858aSTejun Heo 	fuse_request_send(fc, req);
916e5e5558eSMiklos Szeredi 	err = req->out.h.error;
917e5e5558eSMiklos Szeredi 	fuse_put_request(fc, req);
918e5e5558eSMiklos Szeredi 	if (!err) {
919c79e322fSMiklos Szeredi 		if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
920e5e5558eSMiklos Szeredi 			make_bad_inode(inode);
921e5e5558eSMiklos Szeredi 			err = -EIO;
922e5e5558eSMiklos Szeredi 		} else {
923c79e322fSMiklos Szeredi 			fuse_change_attributes(inode, &outarg.attr,
924c79e322fSMiklos Szeredi 					       attr_timeout(&outarg),
9251fb69e78SMiklos Szeredi 					       attr_version);
9261fb69e78SMiklos Szeredi 			if (stat)
927c79e322fSMiklos Szeredi 				fuse_fillattr(inode, &outarg.attr, stat);
928e5e5558eSMiklos Szeredi 		}
929e5e5558eSMiklos Szeredi 	}
930e5e5558eSMiklos Szeredi 	return err;
931e5e5558eSMiklos Szeredi }
932e5e5558eSMiklos Szeredi 
933bcb4be80SMiklos Szeredi int fuse_update_attributes(struct inode *inode, struct kstat *stat,
934bcb4be80SMiklos Szeredi 			   struct file *file, bool *refreshed)
935bcb4be80SMiklos Szeredi {
936bcb4be80SMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
937bcb4be80SMiklos Szeredi 	int err;
938bcb4be80SMiklos Szeredi 	bool r;
939bcb4be80SMiklos Szeredi 
940bcb4be80SMiklos Szeredi 	if (fi->i_time < get_jiffies_64()) {
941bcb4be80SMiklos Szeredi 		r = true;
942bcb4be80SMiklos Szeredi 		err = fuse_do_getattr(inode, stat, file);
943bcb4be80SMiklos Szeredi 	} else {
944bcb4be80SMiklos Szeredi 		r = false;
945bcb4be80SMiklos Szeredi 		err = 0;
946bcb4be80SMiklos Szeredi 		if (stat) {
947bcb4be80SMiklos Szeredi 			generic_fillattr(inode, stat);
948bcb4be80SMiklos Szeredi 			stat->mode = fi->orig_i_mode;
94945c72cd7SPavel Shilovsky 			stat->ino = fi->orig_ino;
950bcb4be80SMiklos Szeredi 		}
951bcb4be80SMiklos Szeredi 	}
952bcb4be80SMiklos Szeredi 
953bcb4be80SMiklos Szeredi 	if (refreshed != NULL)
954bcb4be80SMiklos Szeredi 		*refreshed = r;
955bcb4be80SMiklos Szeredi 
956bcb4be80SMiklos Szeredi 	return err;
957bcb4be80SMiklos Szeredi }
958bcb4be80SMiklos Szeredi 
9593b463ae0SJohn Muir int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid,
960451d0f59SJohn Muir 			     u64 child_nodeid, struct qstr *name)
9613b463ae0SJohn Muir {
9623b463ae0SJohn Muir 	int err = -ENOTDIR;
9633b463ae0SJohn Muir 	struct inode *parent;
9643b463ae0SJohn Muir 	struct dentry *dir;
9653b463ae0SJohn Muir 	struct dentry *entry;
9663b463ae0SJohn Muir 
9673b463ae0SJohn Muir 	parent = ilookup5(sb, parent_nodeid, fuse_inode_eq, &parent_nodeid);
9683b463ae0SJohn Muir 	if (!parent)
9693b463ae0SJohn Muir 		return -ENOENT;
9703b463ae0SJohn Muir 
9713b463ae0SJohn Muir 	mutex_lock(&parent->i_mutex);
9723b463ae0SJohn Muir 	if (!S_ISDIR(parent->i_mode))
9733b463ae0SJohn Muir 		goto unlock;
9743b463ae0SJohn Muir 
9753b463ae0SJohn Muir 	err = -ENOENT;
9763b463ae0SJohn Muir 	dir = d_find_alias(parent);
9773b463ae0SJohn Muir 	if (!dir)
9783b463ae0SJohn Muir 		goto unlock;
9793b463ae0SJohn Muir 
9803b463ae0SJohn Muir 	entry = d_lookup(dir, name);
9813b463ae0SJohn Muir 	dput(dir);
9823b463ae0SJohn Muir 	if (!entry)
9833b463ae0SJohn Muir 		goto unlock;
9843b463ae0SJohn Muir 
9853b463ae0SJohn Muir 	fuse_invalidate_attr(parent);
9863b463ae0SJohn Muir 	fuse_invalidate_entry(entry);
987451d0f59SJohn Muir 
988451d0f59SJohn Muir 	if (child_nodeid != 0 && entry->d_inode) {
989451d0f59SJohn Muir 		mutex_lock(&entry->d_inode->i_mutex);
990451d0f59SJohn Muir 		if (get_node_id(entry->d_inode) != child_nodeid) {
991451d0f59SJohn Muir 			err = -ENOENT;
992451d0f59SJohn Muir 			goto badentry;
993451d0f59SJohn Muir 		}
994451d0f59SJohn Muir 		if (d_mountpoint(entry)) {
995451d0f59SJohn Muir 			err = -EBUSY;
996451d0f59SJohn Muir 			goto badentry;
997451d0f59SJohn Muir 		}
998451d0f59SJohn Muir 		if (S_ISDIR(entry->d_inode->i_mode)) {
999451d0f59SJohn Muir 			shrink_dcache_parent(entry);
1000451d0f59SJohn Muir 			if (!simple_empty(entry)) {
1001451d0f59SJohn Muir 				err = -ENOTEMPTY;
1002451d0f59SJohn Muir 				goto badentry;
1003451d0f59SJohn Muir 			}
1004451d0f59SJohn Muir 			entry->d_inode->i_flags |= S_DEAD;
1005451d0f59SJohn Muir 		}
1006451d0f59SJohn Muir 		dont_mount(entry);
1007451d0f59SJohn Muir 		clear_nlink(entry->d_inode);
10083b463ae0SJohn Muir 		err = 0;
1009451d0f59SJohn Muir  badentry:
1010451d0f59SJohn Muir 		mutex_unlock(&entry->d_inode->i_mutex);
1011451d0f59SJohn Muir 		if (!err)
1012451d0f59SJohn Muir 			d_delete(entry);
1013451d0f59SJohn Muir 	} else {
1014451d0f59SJohn Muir 		err = 0;
1015451d0f59SJohn Muir 	}
1016451d0f59SJohn Muir 	dput(entry);
10173b463ae0SJohn Muir 
10183b463ae0SJohn Muir  unlock:
10193b463ae0SJohn Muir 	mutex_unlock(&parent->i_mutex);
10203b463ae0SJohn Muir 	iput(parent);
10213b463ae0SJohn Muir 	return err;
10223b463ae0SJohn Muir }
10233b463ae0SJohn Muir 
102487729a55SMiklos Szeredi /*
102587729a55SMiklos Szeredi  * Calling into a user-controlled filesystem gives the filesystem
1026c2132c1bSAnatol Pomozov  * daemon ptrace-like capabilities over the current process.  This
102787729a55SMiklos Szeredi  * means, that the filesystem daemon is able to record the exact
102887729a55SMiklos Szeredi  * filesystem operations performed, and can also control the behavior
102987729a55SMiklos Szeredi  * of the requester process in otherwise impossible ways.  For example
103087729a55SMiklos Szeredi  * it can delay the operation for arbitrary length of time allowing
103187729a55SMiklos Szeredi  * DoS against the requester.
103287729a55SMiklos Szeredi  *
103387729a55SMiklos Szeredi  * For this reason only those processes can call into the filesystem,
103487729a55SMiklos Szeredi  * for which the owner of the mount has ptrace privilege.  This
103587729a55SMiklos Szeredi  * excludes processes started by other users, suid or sgid processes.
103687729a55SMiklos Szeredi  */
1037c2132c1bSAnatol Pomozov int fuse_allow_current_process(struct fuse_conn *fc)
103887729a55SMiklos Szeredi {
1039c69e8d9cSDavid Howells 	const struct cred *cred;
1040c69e8d9cSDavid Howells 
104187729a55SMiklos Szeredi 	if (fc->flags & FUSE_ALLOW_OTHER)
104287729a55SMiklos Szeredi 		return 1;
104387729a55SMiklos Szeredi 
1044c2132c1bSAnatol Pomozov 	cred = current_cred();
1045499dcf20SEric W. Biederman 	if (uid_eq(cred->euid, fc->user_id) &&
1046499dcf20SEric W. Biederman 	    uid_eq(cred->suid, fc->user_id) &&
1047499dcf20SEric W. Biederman 	    uid_eq(cred->uid,  fc->user_id) &&
1048499dcf20SEric W. Biederman 	    gid_eq(cred->egid, fc->group_id) &&
1049499dcf20SEric W. Biederman 	    gid_eq(cred->sgid, fc->group_id) &&
1050499dcf20SEric W. Biederman 	    gid_eq(cred->gid,  fc->group_id))
1051c2132c1bSAnatol Pomozov 		return 1;
105287729a55SMiklos Szeredi 
1053c2132c1bSAnatol Pomozov 	return 0;
105487729a55SMiklos Szeredi }
105587729a55SMiklos Szeredi 
105631d40d74SMiklos Szeredi static int fuse_access(struct inode *inode, int mask)
105731d40d74SMiklos Szeredi {
105831d40d74SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
105931d40d74SMiklos Szeredi 	struct fuse_req *req;
106031d40d74SMiklos Szeredi 	struct fuse_access_in inarg;
106131d40d74SMiklos Szeredi 	int err;
106231d40d74SMiklos Szeredi 
106331d40d74SMiklos Szeredi 	if (fc->no_access)
106431d40d74SMiklos Szeredi 		return 0;
106531d40d74SMiklos Szeredi 
1066b111c8c0SMaxim Patlasov 	req = fuse_get_req_nopages(fc);
1067ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1068ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
106931d40d74SMiklos Szeredi 
107031d40d74SMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
1071e6305c43SAl Viro 	inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC);
107231d40d74SMiklos Szeredi 	req->in.h.opcode = FUSE_ACCESS;
107331d40d74SMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
107431d40d74SMiklos Szeredi 	req->in.numargs = 1;
107531d40d74SMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
107631d40d74SMiklos Szeredi 	req->in.args[0].value = &inarg;
1077b93f858aSTejun Heo 	fuse_request_send(fc, req);
107831d40d74SMiklos Szeredi 	err = req->out.h.error;
107931d40d74SMiklos Szeredi 	fuse_put_request(fc, req);
108031d40d74SMiklos Szeredi 	if (err == -ENOSYS) {
108131d40d74SMiklos Szeredi 		fc->no_access = 1;
108231d40d74SMiklos Szeredi 		err = 0;
108331d40d74SMiklos Szeredi 	}
108431d40d74SMiklos Szeredi 	return err;
108531d40d74SMiklos Szeredi }
108631d40d74SMiklos Szeredi 
108710556cb2SAl Viro static int fuse_perm_getattr(struct inode *inode, int mask)
108819690ddbSMiklos Szeredi {
108910556cb2SAl Viro 	if (mask & MAY_NOT_BLOCK)
109019690ddbSMiklos Szeredi 		return -ECHILD;
109119690ddbSMiklos Szeredi 
109219690ddbSMiklos Szeredi 	return fuse_do_getattr(inode, NULL, NULL);
109319690ddbSMiklos Szeredi }
109419690ddbSMiklos Szeredi 
10956f9f1180SMiklos Szeredi /*
10966f9f1180SMiklos Szeredi  * Check permission.  The two basic access models of FUSE are:
10976f9f1180SMiklos Szeredi  *
10986f9f1180SMiklos Szeredi  * 1) Local access checking ('default_permissions' mount option) based
10996f9f1180SMiklos Szeredi  * on file mode.  This is the plain old disk filesystem permission
11006f9f1180SMiklos Szeredi  * modell.
11016f9f1180SMiklos Szeredi  *
11026f9f1180SMiklos Szeredi  * 2) "Remote" access checking, where server is responsible for
11036f9f1180SMiklos Szeredi  * checking permission in each inode operation.  An exception to this
11046f9f1180SMiklos Szeredi  * is if ->permission() was invoked from sys_access() in which case an
11056f9f1180SMiklos Szeredi  * access request is sent.  Execute permission is still checked
11066f9f1180SMiklos Szeredi  * locally based on file mode.
11076f9f1180SMiklos Szeredi  */
110810556cb2SAl Viro static int fuse_permission(struct inode *inode, int mask)
1109e5e5558eSMiklos Szeredi {
1110e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1111244f6385SMiklos Szeredi 	bool refreshed = false;
1112244f6385SMiklos Szeredi 	int err = 0;
1113e5e5558eSMiklos Szeredi 
1114c2132c1bSAnatol Pomozov 	if (!fuse_allow_current_process(fc))
1115e5e5558eSMiklos Szeredi 		return -EACCES;
1116244f6385SMiklos Szeredi 
1117244f6385SMiklos Szeredi 	/*
1118e8e96157SMiklos Szeredi 	 * If attributes are needed, refresh them before proceeding
1119244f6385SMiklos Szeredi 	 */
1120e8e96157SMiklos Szeredi 	if ((fc->flags & FUSE_DEFAULT_PERMISSIONS) ||
1121e8e96157SMiklos Szeredi 	    ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
112219690ddbSMiklos Szeredi 		struct fuse_inode *fi = get_fuse_inode(inode);
112319690ddbSMiklos Szeredi 
112419690ddbSMiklos Szeredi 		if (fi->i_time < get_jiffies_64()) {
112519690ddbSMiklos Szeredi 			refreshed = true;
112619690ddbSMiklos Szeredi 
112710556cb2SAl Viro 			err = fuse_perm_getattr(inode, mask);
1128244f6385SMiklos Szeredi 			if (err)
1129244f6385SMiklos Szeredi 				return err;
11301fb69e78SMiklos Szeredi 		}
113119690ddbSMiklos Szeredi 	}
1132244f6385SMiklos Szeredi 
1133244f6385SMiklos Szeredi 	if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
11342830ba7fSAl Viro 		err = generic_permission(inode, mask);
11351e9a4ed9SMiklos Szeredi 
11361e9a4ed9SMiklos Szeredi 		/* If permission is denied, try to refresh file
11371e9a4ed9SMiklos Szeredi 		   attributes.  This is also needed, because the root
11381e9a4ed9SMiklos Szeredi 		   node will at first have no permissions */
1139244f6385SMiklos Szeredi 		if (err == -EACCES && !refreshed) {
114010556cb2SAl Viro 			err = fuse_perm_getattr(inode, mask);
11411e9a4ed9SMiklos Szeredi 			if (!err)
11422830ba7fSAl Viro 				err = generic_permission(inode, mask);
11431e9a4ed9SMiklos Szeredi 		}
11441e9a4ed9SMiklos Szeredi 
11456f9f1180SMiklos Szeredi 		/* Note: the opposite of the above test does not
11466f9f1180SMiklos Szeredi 		   exist.  So if permissions are revoked this won't be
11476f9f1180SMiklos Szeredi 		   noticed immediately, only after the attribute
11486f9f1180SMiklos Szeredi 		   timeout has expired */
11499cfcac81SEric Paris 	} else if (mask & (MAY_ACCESS | MAY_CHDIR)) {
115010556cb2SAl Viro 		if (mask & MAY_NOT_BLOCK)
115119690ddbSMiklos Szeredi 			return -ECHILD;
115219690ddbSMiklos Szeredi 
1153e8e96157SMiklos Szeredi 		err = fuse_access(inode, mask);
1154e8e96157SMiklos Szeredi 	} else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
1155e8e96157SMiklos Szeredi 		if (!(inode->i_mode & S_IXUGO)) {
1156e8e96157SMiklos Szeredi 			if (refreshed)
1157e5e5558eSMiklos Szeredi 				return -EACCES;
115831d40d74SMiklos Szeredi 
115910556cb2SAl Viro 			err = fuse_perm_getattr(inode, mask);
1160e8e96157SMiklos Szeredi 			if (!err && !(inode->i_mode & S_IXUGO))
1161e8e96157SMiklos Szeredi 				return -EACCES;
1162e8e96157SMiklos Szeredi 		}
1163e5e5558eSMiklos Szeredi 	}
1164244f6385SMiklos Szeredi 	return err;
1165e5e5558eSMiklos Szeredi }
1166e5e5558eSMiklos Szeredi 
1167e5e5558eSMiklos Szeredi static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
11688d3af7f3SAl Viro 			 struct dir_context *ctx)
1169e5e5558eSMiklos Szeredi {
1170e5e5558eSMiklos Szeredi 	while (nbytes >= FUSE_NAME_OFFSET) {
1171e5e5558eSMiklos Szeredi 		struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
1172e5e5558eSMiklos Szeredi 		size_t reclen = FUSE_DIRENT_SIZE(dirent);
1173e5e5558eSMiklos Szeredi 		if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
1174e5e5558eSMiklos Szeredi 			return -EIO;
1175e5e5558eSMiklos Szeredi 		if (reclen > nbytes)
1176e5e5558eSMiklos Szeredi 			break;
1177*efeb9e60SMiklos Szeredi 		if (memchr(dirent->name, '/', dirent->namelen) != NULL)
1178*efeb9e60SMiklos Szeredi 			return -EIO;
1179e5e5558eSMiklos Szeredi 
11808d3af7f3SAl Viro 		if (!dir_emit(ctx, dirent->name, dirent->namelen,
11818d3af7f3SAl Viro 			       dirent->ino, dirent->type))
1182e5e5558eSMiklos Szeredi 			break;
1183e5e5558eSMiklos Szeredi 
1184e5e5558eSMiklos Szeredi 		buf += reclen;
1185e5e5558eSMiklos Szeredi 		nbytes -= reclen;
11868d3af7f3SAl Viro 		ctx->pos = dirent->off;
1187e5e5558eSMiklos Szeredi 	}
1188e5e5558eSMiklos Szeredi 
1189e5e5558eSMiklos Szeredi 	return 0;
1190e5e5558eSMiklos Szeredi }
1191e5e5558eSMiklos Szeredi 
11920b05b183SAnand V. Avati static int fuse_direntplus_link(struct file *file,
11930b05b183SAnand V. Avati 				struct fuse_direntplus *direntplus,
11940b05b183SAnand V. Avati 				u64 attr_version)
11950b05b183SAnand V. Avati {
11960b05b183SAnand V. Avati 	int err;
11970b05b183SAnand V. Avati 	struct fuse_entry_out *o = &direntplus->entry_out;
11980b05b183SAnand V. Avati 	struct fuse_dirent *dirent = &direntplus->dirent;
11990b05b183SAnand V. Avati 	struct dentry *parent = file->f_path.dentry;
12000b05b183SAnand V. Avati 	struct qstr name = QSTR_INIT(dirent->name, dirent->namelen);
12010b05b183SAnand V. Avati 	struct dentry *dentry;
12020b05b183SAnand V. Avati 	struct dentry *alias;
12030b05b183SAnand V. Avati 	struct inode *dir = parent->d_inode;
12040b05b183SAnand V. Avati 	struct fuse_conn *fc;
12050b05b183SAnand V. Avati 	struct inode *inode;
12060b05b183SAnand V. Avati 
12070b05b183SAnand V. Avati 	if (!o->nodeid) {
12080b05b183SAnand V. Avati 		/*
12090b05b183SAnand V. Avati 		 * Unlike in the case of fuse_lookup, zero nodeid does not mean
12100b05b183SAnand V. Avati 		 * ENOENT. Instead, it only means the userspace filesystem did
12110b05b183SAnand V. Avati 		 * not want to return attributes/handle for this entry.
12120b05b183SAnand V. Avati 		 *
12130b05b183SAnand V. Avati 		 * So do nothing.
12140b05b183SAnand V. Avati 		 */
12150b05b183SAnand V. Avati 		return 0;
12160b05b183SAnand V. Avati 	}
12170b05b183SAnand V. Avati 
12180b05b183SAnand V. Avati 	if (name.name[0] == '.') {
12190b05b183SAnand V. Avati 		/*
12200b05b183SAnand V. Avati 		 * We could potentially refresh the attributes of the directory
12210b05b183SAnand V. Avati 		 * and its parent?
12220b05b183SAnand V. Avati 		 */
12230b05b183SAnand V. Avati 		if (name.len == 1)
12240b05b183SAnand V. Avati 			return 0;
12250b05b183SAnand V. Avati 		if (name.name[1] == '.' && name.len == 2)
12260b05b183SAnand V. Avati 			return 0;
12270b05b183SAnand V. Avati 	}
1228a28ef45cSMiklos Szeredi 
1229a28ef45cSMiklos Szeredi 	if (invalid_nodeid(o->nodeid))
1230a28ef45cSMiklos Szeredi 		return -EIO;
1231a28ef45cSMiklos Szeredi 	if (!fuse_valid_type(o->attr.mode))
1232a28ef45cSMiklos Szeredi 		return -EIO;
1233a28ef45cSMiklos Szeredi 
12340b05b183SAnand V. Avati 	fc = get_fuse_conn(dir);
12350b05b183SAnand V. Avati 
12360b05b183SAnand V. Avati 	name.hash = full_name_hash(name.name, name.len);
12370b05b183SAnand V. Avati 	dentry = d_lookup(parent, &name);
123853ce9a33SNiels de Vos 	if (dentry) {
12390b05b183SAnand V. Avati 		inode = dentry->d_inode;
124053ce9a33SNiels de Vos 		if (!inode) {
124153ce9a33SNiels de Vos 			d_drop(dentry);
1242a28ef45cSMiklos Szeredi 		} else if (get_node_id(inode) != o->nodeid ||
1243a28ef45cSMiklos Szeredi 			   ((o->attr.mode ^ inode->i_mode) & S_IFMT)) {
124453ce9a33SNiels de Vos 			err = d_invalidate(dentry);
124553ce9a33SNiels de Vos 			if (err)
124653ce9a33SNiels de Vos 				goto out;
1247a28ef45cSMiklos Szeredi 		} else if (is_bad_inode(inode)) {
1248a28ef45cSMiklos Szeredi 			err = -EIO;
1249a28ef45cSMiklos Szeredi 			goto out;
125053ce9a33SNiels de Vos 		} else {
12510b05b183SAnand V. Avati 			struct fuse_inode *fi;
12520b05b183SAnand V. Avati 			fi = get_fuse_inode(inode);
12530b05b183SAnand V. Avati 			spin_lock(&fc->lock);
12540b05b183SAnand V. Avati 			fi->nlookup++;
12550b05b183SAnand V. Avati 			spin_unlock(&fc->lock);
12560b05b183SAnand V. Avati 
1257fa2b7213SMiklos Szeredi 			fuse_change_attributes(inode, &o->attr,
1258fa2b7213SMiklos Szeredi 					       entry_attr_timeout(o),
1259fa2b7213SMiklos Szeredi 					       attr_version);
1260fa2b7213SMiklos Szeredi 
12610b05b183SAnand V. Avati 			/*
12620b05b183SAnand V. Avati 			 * The other branch to 'found' comes via fuse_iget()
12630b05b183SAnand V. Avati 			 * which bumps nlookup inside
12640b05b183SAnand V. Avati 			 */
12650b05b183SAnand V. Avati 			goto found;
12660b05b183SAnand V. Avati 		}
12670b05b183SAnand V. Avati 		dput(dentry);
12680b05b183SAnand V. Avati 	}
12690b05b183SAnand V. Avati 
12700b05b183SAnand V. Avati 	dentry = d_alloc(parent, &name);
12710b05b183SAnand V. Avati 	err = -ENOMEM;
12720b05b183SAnand V. Avati 	if (!dentry)
12730b05b183SAnand V. Avati 		goto out;
12740b05b183SAnand V. Avati 
12750b05b183SAnand V. Avati 	inode = fuse_iget(dir->i_sb, o->nodeid, o->generation,
12760b05b183SAnand V. Avati 			  &o->attr, entry_attr_timeout(o), attr_version);
12770b05b183SAnand V. Avati 	if (!inode)
12780b05b183SAnand V. Avati 		goto out;
12790b05b183SAnand V. Avati 
12802914941eSMiklos Szeredi 	if (S_ISDIR(inode->i_mode)) {
12812914941eSMiklos Szeredi 		mutex_lock(&fc->inst_mutex);
12822914941eSMiklos Szeredi 		alias = fuse_d_add_directory(dentry, inode);
12832914941eSMiklos Szeredi 		mutex_unlock(&fc->inst_mutex);
12840b05b183SAnand V. Avati 		err = PTR_ERR(alias);
12852914941eSMiklos Szeredi 		if (IS_ERR(alias)) {
12862914941eSMiklos Szeredi 			iput(inode);
12870b05b183SAnand V. Avati 			goto out;
12882914941eSMiklos Szeredi 		}
12892914941eSMiklos Szeredi 	} else {
12902914941eSMiklos Szeredi 		alias = d_splice_alias(inode, dentry);
12912914941eSMiklos Szeredi 	}
12922914941eSMiklos Szeredi 
12930b05b183SAnand V. Avati 	if (alias) {
12940b05b183SAnand V. Avati 		dput(dentry);
12950b05b183SAnand V. Avati 		dentry = alias;
12960b05b183SAnand V. Avati 	}
12970b05b183SAnand V. Avati 
12980b05b183SAnand V. Avati found:
12990b05b183SAnand V. Avati 	fuse_change_entry_timeout(dentry, o);
13000b05b183SAnand V. Avati 
13010b05b183SAnand V. Avati 	err = 0;
13020b05b183SAnand V. Avati out:
13030b05b183SAnand V. Avati 	dput(dentry);
13040b05b183SAnand V. Avati 	return err;
13050b05b183SAnand V. Avati }
13060b05b183SAnand V. Avati 
13070b05b183SAnand V. Avati static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file,
13088d3af7f3SAl Viro 			     struct dir_context *ctx, u64 attr_version)
13090b05b183SAnand V. Avati {
13100b05b183SAnand V. Avati 	struct fuse_direntplus *direntplus;
13110b05b183SAnand V. Avati 	struct fuse_dirent *dirent;
13120b05b183SAnand V. Avati 	size_t reclen;
13130b05b183SAnand V. Avati 	int over = 0;
13140b05b183SAnand V. Avati 	int ret;
13150b05b183SAnand V. Avati 
13160b05b183SAnand V. Avati 	while (nbytes >= FUSE_NAME_OFFSET_DIRENTPLUS) {
13170b05b183SAnand V. Avati 		direntplus = (struct fuse_direntplus *) buf;
13180b05b183SAnand V. Avati 		dirent = &direntplus->dirent;
13190b05b183SAnand V. Avati 		reclen = FUSE_DIRENTPLUS_SIZE(direntplus);
13200b05b183SAnand V. Avati 
13210b05b183SAnand V. Avati 		if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
13220b05b183SAnand V. Avati 			return -EIO;
13230b05b183SAnand V. Avati 		if (reclen > nbytes)
13240b05b183SAnand V. Avati 			break;
1325*efeb9e60SMiklos Szeredi 		if (memchr(dirent->name, '/', dirent->namelen) != NULL)
1326*efeb9e60SMiklos Szeredi 			return -EIO;
13270b05b183SAnand V. Avati 
13280b05b183SAnand V. Avati 		if (!over) {
13290b05b183SAnand V. Avati 			/* We fill entries into dstbuf only as much as
13300b05b183SAnand V. Avati 			   it can hold. But we still continue iterating
13310b05b183SAnand V. Avati 			   over remaining entries to link them. If not,
13320b05b183SAnand V. Avati 			   we need to send a FORGET for each of those
13330b05b183SAnand V. Avati 			   which we did not link.
13340b05b183SAnand V. Avati 			*/
13358d3af7f3SAl Viro 			over = !dir_emit(ctx, dirent->name, dirent->namelen,
13368d3af7f3SAl Viro 				       dirent->ino, dirent->type);
13378d3af7f3SAl Viro 			ctx->pos = dirent->off;
13380b05b183SAnand V. Avati 		}
13390b05b183SAnand V. Avati 
13400b05b183SAnand V. Avati 		buf += reclen;
13410b05b183SAnand V. Avati 		nbytes -= reclen;
13420b05b183SAnand V. Avati 
13430b05b183SAnand V. Avati 		ret = fuse_direntplus_link(file, direntplus, attr_version);
13440b05b183SAnand V. Avati 		if (ret)
13450b05b183SAnand V. Avati 			fuse_force_forget(file, direntplus->entry_out.nodeid);
13460b05b183SAnand V. Avati 	}
13470b05b183SAnand V. Avati 
13480b05b183SAnand V. Avati 	return 0;
13490b05b183SAnand V. Avati }
13500b05b183SAnand V. Avati 
13518d3af7f3SAl Viro static int fuse_readdir(struct file *file, struct dir_context *ctx)
1352e5e5558eSMiklos Szeredi {
13534582a4abSFeng Shuo 	int plus, err;
135404730fefSMiklos Szeredi 	size_t nbytes;
135504730fefSMiklos Szeredi 	struct page *page;
1356496ad9aaSAl Viro 	struct inode *inode = file_inode(file);
135704730fefSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1358248d86e8SMiklos Szeredi 	struct fuse_req *req;
13590b05b183SAnand V. Avati 	u64 attr_version = 0;
1360248d86e8SMiklos Szeredi 
1361248d86e8SMiklos Szeredi 	if (is_bad_inode(inode))
1362248d86e8SMiklos Szeredi 		return -EIO;
1363248d86e8SMiklos Szeredi 
1364b111c8c0SMaxim Patlasov 	req = fuse_get_req(fc, 1);
1365ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1366ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
1367e5e5558eSMiklos Szeredi 
136804730fefSMiklos Szeredi 	page = alloc_page(GFP_KERNEL);
136904730fefSMiklos Szeredi 	if (!page) {
137004730fefSMiklos Szeredi 		fuse_put_request(fc, req);
1371e5e5558eSMiklos Szeredi 		return -ENOMEM;
137204730fefSMiklos Szeredi 	}
13734582a4abSFeng Shuo 
13748d3af7f3SAl Viro 	plus = fuse_use_readdirplus(inode, ctx);
1375f4975c67SMiklos Szeredi 	req->out.argpages = 1;
137604730fefSMiklos Szeredi 	req->num_pages = 1;
137704730fefSMiklos Szeredi 	req->pages[0] = page;
137885f40aecSMaxim Patlasov 	req->page_descs[0].length = PAGE_SIZE;
13794582a4abSFeng Shuo 	if (plus) {
13800b05b183SAnand V. Avati 		attr_version = fuse_get_attr_version(fc);
13818d3af7f3SAl Viro 		fuse_read_fill(req, file, ctx->pos, PAGE_SIZE,
13820b05b183SAnand V. Avati 			       FUSE_READDIRPLUS);
13830b05b183SAnand V. Avati 	} else {
13848d3af7f3SAl Viro 		fuse_read_fill(req, file, ctx->pos, PAGE_SIZE,
13850b05b183SAnand V. Avati 			       FUSE_READDIR);
13860b05b183SAnand V. Avati 	}
1387b93f858aSTejun Heo 	fuse_request_send(fc, req);
1388361b1eb5SMiklos Szeredi 	nbytes = req->out.args[0].size;
138904730fefSMiklos Szeredi 	err = req->out.h.error;
139004730fefSMiklos Szeredi 	fuse_put_request(fc, req);
13910b05b183SAnand V. Avati 	if (!err) {
13924582a4abSFeng Shuo 		if (plus) {
13930b05b183SAnand V. Avati 			err = parse_dirplusfile(page_address(page), nbytes,
13948d3af7f3SAl Viro 						file, ctx,
13950b05b183SAnand V. Avati 						attr_version);
13960b05b183SAnand V. Avati 		} else {
13970b05b183SAnand V. Avati 			err = parse_dirfile(page_address(page), nbytes, file,
13988d3af7f3SAl Viro 					    ctx);
13990b05b183SAnand V. Avati 		}
14000b05b183SAnand V. Avati 	}
1401e5e5558eSMiklos Szeredi 
140204730fefSMiklos Szeredi 	__free_page(page);
1403b36c31baSMiklos Szeredi 	fuse_invalidate_attr(inode); /* atime changed */
140404730fefSMiklos Szeredi 	return err;
1405e5e5558eSMiklos Szeredi }
1406e5e5558eSMiklos Szeredi 
1407e5e5558eSMiklos Szeredi static char *read_link(struct dentry *dentry)
1408e5e5558eSMiklos Szeredi {
1409e5e5558eSMiklos Szeredi 	struct inode *inode = dentry->d_inode;
1410e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1411b111c8c0SMaxim Patlasov 	struct fuse_req *req = fuse_get_req_nopages(fc);
1412e5e5558eSMiklos Szeredi 	char *link;
1413e5e5558eSMiklos Szeredi 
1414ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1415e231c2eeSDavid Howells 		return ERR_CAST(req);
1416e5e5558eSMiklos Szeredi 
1417e5e5558eSMiklos Szeredi 	link = (char *) __get_free_page(GFP_KERNEL);
1418e5e5558eSMiklos Szeredi 	if (!link) {
1419e5e5558eSMiklos Szeredi 		link = ERR_PTR(-ENOMEM);
1420e5e5558eSMiklos Szeredi 		goto out;
1421e5e5558eSMiklos Szeredi 	}
1422e5e5558eSMiklos Szeredi 	req->in.h.opcode = FUSE_READLINK;
1423e5e5558eSMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
1424e5e5558eSMiklos Szeredi 	req->out.argvar = 1;
1425e5e5558eSMiklos Szeredi 	req->out.numargs = 1;
1426e5e5558eSMiklos Szeredi 	req->out.args[0].size = PAGE_SIZE - 1;
1427e5e5558eSMiklos Szeredi 	req->out.args[0].value = link;
1428b93f858aSTejun Heo 	fuse_request_send(fc, req);
1429e5e5558eSMiklos Szeredi 	if (req->out.h.error) {
1430e5e5558eSMiklos Szeredi 		free_page((unsigned long) link);
1431e5e5558eSMiklos Szeredi 		link = ERR_PTR(req->out.h.error);
1432e5e5558eSMiklos Szeredi 	} else
1433e5e5558eSMiklos Szeredi 		link[req->out.args[0].size] = '\0';
1434e5e5558eSMiklos Szeredi  out:
1435e5e5558eSMiklos Szeredi 	fuse_put_request(fc, req);
1436b36c31baSMiklos Szeredi 	fuse_invalidate_attr(inode); /* atime changed */
1437e5e5558eSMiklos Szeredi 	return link;
1438e5e5558eSMiklos Szeredi }
1439e5e5558eSMiklos Szeredi 
1440e5e5558eSMiklos Szeredi static void free_link(char *link)
1441e5e5558eSMiklos Szeredi {
1442e5e5558eSMiklos Szeredi 	if (!IS_ERR(link))
1443e5e5558eSMiklos Szeredi 		free_page((unsigned long) link);
1444e5e5558eSMiklos Szeredi }
1445e5e5558eSMiklos Szeredi 
1446e5e5558eSMiklos Szeredi static void *fuse_follow_link(struct dentry *dentry, struct nameidata *nd)
1447e5e5558eSMiklos Szeredi {
1448e5e5558eSMiklos Szeredi 	nd_set_link(nd, read_link(dentry));
1449e5e5558eSMiklos Szeredi 	return NULL;
1450e5e5558eSMiklos Szeredi }
1451e5e5558eSMiklos Szeredi 
1452e5e5558eSMiklos Szeredi static void fuse_put_link(struct dentry *dentry, struct nameidata *nd, void *c)
1453e5e5558eSMiklos Szeredi {
1454e5e5558eSMiklos Szeredi 	free_link(nd_get_link(nd));
1455e5e5558eSMiklos Szeredi }
1456e5e5558eSMiklos Szeredi 
1457e5e5558eSMiklos Szeredi static int fuse_dir_open(struct inode *inode, struct file *file)
1458e5e5558eSMiklos Szeredi {
145991fe96b4SMiklos Szeredi 	return fuse_open_common(inode, file, true);
1460e5e5558eSMiklos Szeredi }
1461e5e5558eSMiklos Szeredi 
1462e5e5558eSMiklos Szeredi static int fuse_dir_release(struct inode *inode, struct file *file)
1463e5e5558eSMiklos Szeredi {
14648b0797a4SMiklos Szeredi 	fuse_release_common(file, FUSE_RELEASEDIR);
14658b0797a4SMiklos Szeredi 
14668b0797a4SMiklos Szeredi 	return 0;
1467e5e5558eSMiklos Szeredi }
1468e5e5558eSMiklos Szeredi 
146902c24a82SJosef Bacik static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end,
147002c24a82SJosef Bacik 			  int datasync)
147182547981SMiklos Szeredi {
147202c24a82SJosef Bacik 	return fuse_fsync_common(file, start, end, datasync, 1);
147382547981SMiklos Szeredi }
147482547981SMiklos Szeredi 
1475b18da0c5SMiklos Szeredi static long fuse_dir_ioctl(struct file *file, unsigned int cmd,
1476b18da0c5SMiklos Szeredi 			    unsigned long arg)
1477b18da0c5SMiklos Szeredi {
1478b18da0c5SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1479b18da0c5SMiklos Szeredi 
1480b18da0c5SMiklos Szeredi 	/* FUSE_IOCTL_DIR only supported for API version >= 7.18 */
1481b18da0c5SMiklos Szeredi 	if (fc->minor < 18)
1482b18da0c5SMiklos Szeredi 		return -ENOTTY;
1483b18da0c5SMiklos Szeredi 
1484b18da0c5SMiklos Szeredi 	return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR);
1485b18da0c5SMiklos Szeredi }
1486b18da0c5SMiklos Szeredi 
1487b18da0c5SMiklos Szeredi static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd,
1488b18da0c5SMiklos Szeredi 				   unsigned long arg)
1489b18da0c5SMiklos Szeredi {
1490b18da0c5SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1491b18da0c5SMiklos Szeredi 
1492b18da0c5SMiklos Szeredi 	if (fc->minor < 18)
1493b18da0c5SMiklos Szeredi 		return -ENOTTY;
1494b18da0c5SMiklos Szeredi 
1495b18da0c5SMiklos Szeredi 	return fuse_ioctl_common(file, cmd, arg,
1496b18da0c5SMiklos Szeredi 				 FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR);
1497b18da0c5SMiklos Szeredi }
1498b18da0c5SMiklos Szeredi 
149917637cbaSMiklos Szeredi static bool update_mtime(unsigned ivalid)
150017637cbaSMiklos Szeredi {
150117637cbaSMiklos Szeredi 	/* Always update if mtime is explicitly set  */
150217637cbaSMiklos Szeredi 	if (ivalid & ATTR_MTIME_SET)
150317637cbaSMiklos Szeredi 		return true;
150417637cbaSMiklos Szeredi 
150517637cbaSMiklos Szeredi 	/* If it's an open(O_TRUNC) or an ftruncate(), don't update */
150617637cbaSMiklos Szeredi 	if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
150717637cbaSMiklos Szeredi 		return false;
150817637cbaSMiklos Szeredi 
150917637cbaSMiklos Szeredi 	/* In all other cases update */
151017637cbaSMiklos Szeredi 	return true;
151117637cbaSMiklos Szeredi }
151217637cbaSMiklos Szeredi 
1513befc649cSMiklos Szeredi static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg)
15149e6268dbSMiklos Szeredi {
15159e6268dbSMiklos Szeredi 	unsigned ivalid = iattr->ia_valid;
15169e6268dbSMiklos Szeredi 
15179e6268dbSMiklos Szeredi 	if (ivalid & ATTR_MODE)
1518befc649cSMiklos Szeredi 		arg->valid |= FATTR_MODE,   arg->mode = iattr->ia_mode;
15199e6268dbSMiklos Szeredi 	if (ivalid & ATTR_UID)
1520499dcf20SEric W. Biederman 		arg->valid |= FATTR_UID,    arg->uid = from_kuid(&init_user_ns, iattr->ia_uid);
15219e6268dbSMiklos Szeredi 	if (ivalid & ATTR_GID)
1522499dcf20SEric W. Biederman 		arg->valid |= FATTR_GID,    arg->gid = from_kgid(&init_user_ns, iattr->ia_gid);
15239e6268dbSMiklos Szeredi 	if (ivalid & ATTR_SIZE)
1524befc649cSMiklos Szeredi 		arg->valid |= FATTR_SIZE,   arg->size = iattr->ia_size;
152517637cbaSMiklos Szeredi 	if (ivalid & ATTR_ATIME) {
152617637cbaSMiklos Szeredi 		arg->valid |= FATTR_ATIME;
1527befc649cSMiklos Szeredi 		arg->atime = iattr->ia_atime.tv_sec;
152817637cbaSMiklos Szeredi 		arg->atimensec = iattr->ia_atime.tv_nsec;
152917637cbaSMiklos Szeredi 		if (!(ivalid & ATTR_ATIME_SET))
153017637cbaSMiklos Szeredi 			arg->valid |= FATTR_ATIME_NOW;
153117637cbaSMiklos Szeredi 	}
153217637cbaSMiklos Szeredi 	if ((ivalid & ATTR_MTIME) && update_mtime(ivalid)) {
153317637cbaSMiklos Szeredi 		arg->valid |= FATTR_MTIME;
1534befc649cSMiklos Szeredi 		arg->mtime = iattr->ia_mtime.tv_sec;
153517637cbaSMiklos Szeredi 		arg->mtimensec = iattr->ia_mtime.tv_nsec;
153617637cbaSMiklos Szeredi 		if (!(ivalid & ATTR_MTIME_SET))
153717637cbaSMiklos Szeredi 			arg->valid |= FATTR_MTIME_NOW;
15389e6268dbSMiklos Szeredi 	}
15399e6268dbSMiklos Szeredi }
15409e6268dbSMiklos Szeredi 
15416f9f1180SMiklos Szeredi /*
15423be5a52bSMiklos Szeredi  * Prevent concurrent writepages on inode
15433be5a52bSMiklos Szeredi  *
15443be5a52bSMiklos Szeredi  * This is done by adding a negative bias to the inode write counter
15453be5a52bSMiklos Szeredi  * and waiting for all pending writes to finish.
15463be5a52bSMiklos Szeredi  */
15473be5a52bSMiklos Szeredi void fuse_set_nowrite(struct inode *inode)
15483be5a52bSMiklos Szeredi {
15493be5a52bSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
15503be5a52bSMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
15513be5a52bSMiklos Szeredi 
15523be5a52bSMiklos Szeredi 	BUG_ON(!mutex_is_locked(&inode->i_mutex));
15533be5a52bSMiklos Szeredi 
15543be5a52bSMiklos Szeredi 	spin_lock(&fc->lock);
15553be5a52bSMiklos Szeredi 	BUG_ON(fi->writectr < 0);
15563be5a52bSMiklos Szeredi 	fi->writectr += FUSE_NOWRITE;
15573be5a52bSMiklos Szeredi 	spin_unlock(&fc->lock);
15583be5a52bSMiklos Szeredi 	wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE);
15593be5a52bSMiklos Szeredi }
15603be5a52bSMiklos Szeredi 
15613be5a52bSMiklos Szeredi /*
15623be5a52bSMiklos Szeredi  * Allow writepages on inode
15633be5a52bSMiklos Szeredi  *
15643be5a52bSMiklos Szeredi  * Remove the bias from the writecounter and send any queued
15653be5a52bSMiklos Szeredi  * writepages.
15663be5a52bSMiklos Szeredi  */
15673be5a52bSMiklos Szeredi static void __fuse_release_nowrite(struct inode *inode)
15683be5a52bSMiklos Szeredi {
15693be5a52bSMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
15703be5a52bSMiklos Szeredi 
15713be5a52bSMiklos Szeredi 	BUG_ON(fi->writectr != FUSE_NOWRITE);
15723be5a52bSMiklos Szeredi 	fi->writectr = 0;
15733be5a52bSMiklos Szeredi 	fuse_flush_writepages(inode);
15743be5a52bSMiklos Szeredi }
15753be5a52bSMiklos Szeredi 
15763be5a52bSMiklos Szeredi void fuse_release_nowrite(struct inode *inode)
15773be5a52bSMiklos Szeredi {
15783be5a52bSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
15793be5a52bSMiklos Szeredi 
15803be5a52bSMiklos Szeredi 	spin_lock(&fc->lock);
15813be5a52bSMiklos Szeredi 	__fuse_release_nowrite(inode);
15823be5a52bSMiklos Szeredi 	spin_unlock(&fc->lock);
15833be5a52bSMiklos Szeredi }
15843be5a52bSMiklos Szeredi 
15853be5a52bSMiklos Szeredi /*
15866f9f1180SMiklos Szeredi  * Set attributes, and at the same time refresh them.
15876f9f1180SMiklos Szeredi  *
15886f9f1180SMiklos Szeredi  * Truncation is slightly complicated, because the 'truncate' request
15896f9f1180SMiklos Szeredi  * may fail, in which case we don't want to touch the mapping.
15909ffbb916SMiklos Szeredi  * vmtruncate() doesn't allow for this case, so do the rlimit checking
15919ffbb916SMiklos Szeredi  * and the actual truncation by hand.
15926f9f1180SMiklos Szeredi  */
1593efb9fa9eSMaxim Patlasov int fuse_do_setattr(struct inode *inode, struct iattr *attr,
159449d4914fSMiklos Szeredi 		    struct file *file)
15959e6268dbSMiklos Szeredi {
15969e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
159706a7c3c2SMaxim Patlasov 	struct fuse_inode *fi = get_fuse_inode(inode);
15989e6268dbSMiklos Szeredi 	struct fuse_req *req;
15999e6268dbSMiklos Szeredi 	struct fuse_setattr_in inarg;
16009e6268dbSMiklos Szeredi 	struct fuse_attr_out outarg;
16013be5a52bSMiklos Szeredi 	bool is_truncate = false;
16023be5a52bSMiklos Szeredi 	loff_t oldsize;
16039e6268dbSMiklos Szeredi 	int err;
16049e6268dbSMiklos Szeredi 
1605db78b877SChristoph Hellwig 	if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS))
1606db78b877SChristoph Hellwig 		attr->ia_valid |= ATTR_FORCE;
1607db78b877SChristoph Hellwig 
16081e9a4ed9SMiklos Szeredi 	err = inode_change_ok(inode, attr);
16091e9a4ed9SMiklos Szeredi 	if (err)
16101e9a4ed9SMiklos Szeredi 		return err;
16111e9a4ed9SMiklos Szeredi 
16128d56adddSMiklos Szeredi 	if (attr->ia_valid & ATTR_OPEN) {
16138d56adddSMiklos Szeredi 		if (fc->atomic_o_trunc)
16146ff958edSMiklos Szeredi 			return 0;
16158d56adddSMiklos Szeredi 		file = NULL;
16168d56adddSMiklos Szeredi 	}
16176ff958edSMiklos Szeredi 
16182c27c65eSChristoph Hellwig 	if (attr->ia_valid & ATTR_SIZE)
16193be5a52bSMiklos Szeredi 		is_truncate = true;
16209e6268dbSMiklos Szeredi 
1621b111c8c0SMaxim Patlasov 	req = fuse_get_req_nopages(fc);
1622ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1623ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
16249e6268dbSMiklos Szeredi 
162506a7c3c2SMaxim Patlasov 	if (is_truncate) {
16263be5a52bSMiklos Szeredi 		fuse_set_nowrite(inode);
162706a7c3c2SMaxim Patlasov 		set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
162806a7c3c2SMaxim Patlasov 	}
16293be5a52bSMiklos Szeredi 
16309e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
16310e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
1632befc649cSMiklos Szeredi 	iattr_to_fattr(attr, &inarg);
163349d4914fSMiklos Szeredi 	if (file) {
163449d4914fSMiklos Szeredi 		struct fuse_file *ff = file->private_data;
163549d4914fSMiklos Szeredi 		inarg.valid |= FATTR_FH;
163649d4914fSMiklos Szeredi 		inarg.fh = ff->fh;
163749d4914fSMiklos Szeredi 	}
1638f3332114SMiklos Szeredi 	if (attr->ia_valid & ATTR_SIZE) {
1639f3332114SMiklos Szeredi 		/* For mandatory locking in truncate */
1640f3332114SMiklos Szeredi 		inarg.valid |= FATTR_LOCKOWNER;
1641f3332114SMiklos Szeredi 		inarg.lock_owner = fuse_lock_owner_id(fc, current->files);
1642f3332114SMiklos Szeredi 	}
16439e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_SETATTR;
16449e6268dbSMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
16459e6268dbSMiklos Szeredi 	req->in.numargs = 1;
16469e6268dbSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
16479e6268dbSMiklos Szeredi 	req->in.args[0].value = &inarg;
16489e6268dbSMiklos Szeredi 	req->out.numargs = 1;
16490e9663eeSMiklos Szeredi 	if (fc->minor < 9)
16500e9663eeSMiklos Szeredi 		req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
16510e9663eeSMiklos Szeredi 	else
16529e6268dbSMiklos Szeredi 		req->out.args[0].size = sizeof(outarg);
16539e6268dbSMiklos Szeredi 	req->out.args[0].value = &outarg;
1654b93f858aSTejun Heo 	fuse_request_send(fc, req);
16559e6268dbSMiklos Szeredi 	err = req->out.h.error;
16569e6268dbSMiklos Szeredi 	fuse_put_request(fc, req);
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);
16703be5a52bSMiklos Szeredi 	fuse_change_attributes_common(inode, &outarg.attr,
16713be5a52bSMiklos Szeredi 				      attr_timeout(&outarg));
16723be5a52bSMiklos Szeredi 	oldsize = inode->i_size;
16733be5a52bSMiklos Szeredi 	i_size_write(inode, outarg.attr.size);
16743be5a52bSMiklos Szeredi 
16753be5a52bSMiklos Szeredi 	if (is_truncate) {
16763be5a52bSMiklos Szeredi 		/* NOTE: this may release/reacquire fc->lock */
16773be5a52bSMiklos Szeredi 		__fuse_release_nowrite(inode);
16783be5a52bSMiklos Szeredi 	}
16793be5a52bSMiklos Szeredi 	spin_unlock(&fc->lock);
16803be5a52bSMiklos Szeredi 
16813be5a52bSMiklos Szeredi 	/*
16823be5a52bSMiklos Szeredi 	 * Only call invalidate_inode_pages2() after removing
16833be5a52bSMiklos Szeredi 	 * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock.
16843be5a52bSMiklos Szeredi 	 */
16853be5a52bSMiklos Szeredi 	if (S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
1686c08d3b0eSnpiggin@suse.de 		truncate_pagecache(inode, oldsize, outarg.attr.size);
16873be5a52bSMiklos Szeredi 		invalidate_inode_pages2(inode->i_mapping);
16883be5a52bSMiklos Szeredi 	}
16893be5a52bSMiklos Szeredi 
169006a7c3c2SMaxim Patlasov 	clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
1691e00d2c2dSMiklos Szeredi 	return 0;
16923be5a52bSMiklos Szeredi 
16933be5a52bSMiklos Szeredi error:
16943be5a52bSMiklos Szeredi 	if (is_truncate)
16953be5a52bSMiklos Szeredi 		fuse_release_nowrite(inode);
16963be5a52bSMiklos Szeredi 
169706a7c3c2SMaxim Patlasov 	clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
16983be5a52bSMiklos Szeredi 	return err;
16999e6268dbSMiklos Szeredi }
17009e6268dbSMiklos Szeredi 
170149d4914fSMiklos Szeredi static int fuse_setattr(struct dentry *entry, struct iattr *attr)
170249d4914fSMiklos Szeredi {
1703efb9fa9eSMaxim Patlasov 	struct inode *inode = entry->d_inode;
1704efb9fa9eSMaxim Patlasov 
1705efb9fa9eSMaxim Patlasov 	if (!fuse_allow_current_process(get_fuse_conn(inode)))
1706efb9fa9eSMaxim Patlasov 		return -EACCES;
1707efb9fa9eSMaxim Patlasov 
170849d4914fSMiklos Szeredi 	if (attr->ia_valid & ATTR_FILE)
1709efb9fa9eSMaxim Patlasov 		return fuse_do_setattr(inode, attr, attr->ia_file);
171049d4914fSMiklos Szeredi 	else
1711efb9fa9eSMaxim Patlasov 		return fuse_do_setattr(inode, attr, NULL);
171249d4914fSMiklos Szeredi }
171349d4914fSMiklos Szeredi 
1714e5e5558eSMiklos Szeredi static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
1715e5e5558eSMiklos Szeredi 			struct kstat *stat)
1716e5e5558eSMiklos Szeredi {
1717e5e5558eSMiklos Szeredi 	struct inode *inode = entry->d_inode;
1718244f6385SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1719244f6385SMiklos Szeredi 
1720c2132c1bSAnatol Pomozov 	if (!fuse_allow_current_process(fc))
1721244f6385SMiklos Szeredi 		return -EACCES;
1722244f6385SMiklos Szeredi 
1723bcb4be80SMiklos Szeredi 	return fuse_update_attributes(inode, stat, NULL, NULL);
1724e5e5558eSMiklos Szeredi }
1725e5e5558eSMiklos Szeredi 
172692a8780eSMiklos Szeredi static int fuse_setxattr(struct dentry *entry, const char *name,
172792a8780eSMiklos Szeredi 			 const void *value, size_t size, int flags)
172892a8780eSMiklos Szeredi {
172992a8780eSMiklos Szeredi 	struct inode *inode = entry->d_inode;
173092a8780eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
173192a8780eSMiklos Szeredi 	struct fuse_req *req;
173292a8780eSMiklos Szeredi 	struct fuse_setxattr_in inarg;
173392a8780eSMiklos Szeredi 	int err;
173492a8780eSMiklos Szeredi 
173592a8780eSMiklos Szeredi 	if (fc->no_setxattr)
173692a8780eSMiklos Szeredi 		return -EOPNOTSUPP;
173792a8780eSMiklos Szeredi 
1738b111c8c0SMaxim Patlasov 	req = fuse_get_req_nopages(fc);
1739ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1740ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
174192a8780eSMiklos Szeredi 
174292a8780eSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
174392a8780eSMiklos Szeredi 	inarg.size = size;
174492a8780eSMiklos Szeredi 	inarg.flags = flags;
174592a8780eSMiklos Szeredi 	req->in.h.opcode = FUSE_SETXATTR;
174692a8780eSMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
174792a8780eSMiklos Szeredi 	req->in.numargs = 3;
174892a8780eSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
174992a8780eSMiklos Szeredi 	req->in.args[0].value = &inarg;
175092a8780eSMiklos Szeredi 	req->in.args[1].size = strlen(name) + 1;
175192a8780eSMiklos Szeredi 	req->in.args[1].value = name;
175292a8780eSMiklos Szeredi 	req->in.args[2].size = size;
175392a8780eSMiklos Szeredi 	req->in.args[2].value = value;
1754b93f858aSTejun Heo 	fuse_request_send(fc, req);
175592a8780eSMiklos Szeredi 	err = req->out.h.error;
175692a8780eSMiklos Szeredi 	fuse_put_request(fc, req);
175792a8780eSMiklos Szeredi 	if (err == -ENOSYS) {
175892a8780eSMiklos Szeredi 		fc->no_setxattr = 1;
175992a8780eSMiklos Szeredi 		err = -EOPNOTSUPP;
176092a8780eSMiklos Szeredi 	}
1761d331a415SAnand Avati 	if (!err)
1762d331a415SAnand Avati 		fuse_invalidate_attr(inode);
176392a8780eSMiklos Szeredi 	return err;
176492a8780eSMiklos Szeredi }
176592a8780eSMiklos Szeredi 
176692a8780eSMiklos Szeredi static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
176792a8780eSMiklos Szeredi 			     void *value, size_t size)
176892a8780eSMiklos Szeredi {
176992a8780eSMiklos Szeredi 	struct inode *inode = entry->d_inode;
177092a8780eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
177192a8780eSMiklos Szeredi 	struct fuse_req *req;
177292a8780eSMiklos Szeredi 	struct fuse_getxattr_in inarg;
177392a8780eSMiklos Szeredi 	struct fuse_getxattr_out outarg;
177492a8780eSMiklos Szeredi 	ssize_t ret;
177592a8780eSMiklos Szeredi 
177692a8780eSMiklos Szeredi 	if (fc->no_getxattr)
177792a8780eSMiklos Szeredi 		return -EOPNOTSUPP;
177892a8780eSMiklos Szeredi 
1779b111c8c0SMaxim Patlasov 	req = fuse_get_req_nopages(fc);
1780ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1781ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
178292a8780eSMiklos Szeredi 
178392a8780eSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
178492a8780eSMiklos Szeredi 	inarg.size = size;
178592a8780eSMiklos Szeredi 	req->in.h.opcode = FUSE_GETXATTR;
178692a8780eSMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
178792a8780eSMiklos Szeredi 	req->in.numargs = 2;
178892a8780eSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
178992a8780eSMiklos Szeredi 	req->in.args[0].value = &inarg;
179092a8780eSMiklos Szeredi 	req->in.args[1].size = strlen(name) + 1;
179192a8780eSMiklos Szeredi 	req->in.args[1].value = name;
179292a8780eSMiklos Szeredi 	/* This is really two different operations rolled into one */
179392a8780eSMiklos Szeredi 	req->out.numargs = 1;
179492a8780eSMiklos Szeredi 	if (size) {
179592a8780eSMiklos Szeredi 		req->out.argvar = 1;
179692a8780eSMiklos Szeredi 		req->out.args[0].size = size;
179792a8780eSMiklos Szeredi 		req->out.args[0].value = value;
179892a8780eSMiklos Szeredi 	} else {
179992a8780eSMiklos Szeredi 		req->out.args[0].size = sizeof(outarg);
180092a8780eSMiklos Szeredi 		req->out.args[0].value = &outarg;
180192a8780eSMiklos Szeredi 	}
1802b93f858aSTejun Heo 	fuse_request_send(fc, req);
180392a8780eSMiklos Szeredi 	ret = req->out.h.error;
180492a8780eSMiklos Szeredi 	if (!ret)
180592a8780eSMiklos Szeredi 		ret = size ? req->out.args[0].size : outarg.size;
180692a8780eSMiklos Szeredi 	else {
180792a8780eSMiklos Szeredi 		if (ret == -ENOSYS) {
180892a8780eSMiklos Szeredi 			fc->no_getxattr = 1;
180992a8780eSMiklos Szeredi 			ret = -EOPNOTSUPP;
181092a8780eSMiklos Szeredi 		}
181192a8780eSMiklos Szeredi 	}
181292a8780eSMiklos Szeredi 	fuse_put_request(fc, req);
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);
182092a8780eSMiklos Szeredi 	struct fuse_req *req;
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 
1831b111c8c0SMaxim Patlasov 	req = fuse_get_req_nopages(fc);
1832ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1833ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
183492a8780eSMiklos Szeredi 
183592a8780eSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
183692a8780eSMiklos Szeredi 	inarg.size = size;
183792a8780eSMiklos Szeredi 	req->in.h.opcode = FUSE_LISTXATTR;
183892a8780eSMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
183992a8780eSMiklos Szeredi 	req->in.numargs = 1;
184092a8780eSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
184192a8780eSMiklos Szeredi 	req->in.args[0].value = &inarg;
184292a8780eSMiklos Szeredi 	/* This is really two different operations rolled into one */
184392a8780eSMiklos Szeredi 	req->out.numargs = 1;
184492a8780eSMiklos Szeredi 	if (size) {
184592a8780eSMiklos Szeredi 		req->out.argvar = 1;
184692a8780eSMiklos Szeredi 		req->out.args[0].size = size;
184792a8780eSMiklos Szeredi 		req->out.args[0].value = list;
184892a8780eSMiklos Szeredi 	} else {
184992a8780eSMiklos Szeredi 		req->out.args[0].size = sizeof(outarg);
185092a8780eSMiklos Szeredi 		req->out.args[0].value = &outarg;
185192a8780eSMiklos Szeredi 	}
1852b93f858aSTejun Heo 	fuse_request_send(fc, req);
185392a8780eSMiklos Szeredi 	ret = req->out.h.error;
185492a8780eSMiklos Szeredi 	if (!ret)
185592a8780eSMiklos Szeredi 		ret = size ? req->out.args[0].size : outarg.size;
185692a8780eSMiklos Szeredi 	else {
185792a8780eSMiklos Szeredi 		if (ret == -ENOSYS) {
185892a8780eSMiklos Szeredi 			fc->no_listxattr = 1;
185992a8780eSMiklos Szeredi 			ret = -EOPNOTSUPP;
186092a8780eSMiklos Szeredi 		}
186192a8780eSMiklos Szeredi 	}
186292a8780eSMiklos Szeredi 	fuse_put_request(fc, req);
186392a8780eSMiklos Szeredi 	return ret;
186492a8780eSMiklos Szeredi }
186592a8780eSMiklos Szeredi 
186692a8780eSMiklos Szeredi static int fuse_removexattr(struct dentry *entry, const char *name)
186792a8780eSMiklos Szeredi {
186892a8780eSMiklos Szeredi 	struct inode *inode = entry->d_inode;
186992a8780eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
187092a8780eSMiklos Szeredi 	struct fuse_req *req;
187192a8780eSMiklos Szeredi 	int err;
187292a8780eSMiklos Szeredi 
187392a8780eSMiklos Szeredi 	if (fc->no_removexattr)
187492a8780eSMiklos Szeredi 		return -EOPNOTSUPP;
187592a8780eSMiklos Szeredi 
1876b111c8c0SMaxim Patlasov 	req = fuse_get_req_nopages(fc);
1877ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1878ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
187992a8780eSMiklos Szeredi 
188092a8780eSMiklos Szeredi 	req->in.h.opcode = FUSE_REMOVEXATTR;
188192a8780eSMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
188292a8780eSMiklos Szeredi 	req->in.numargs = 1;
188392a8780eSMiklos Szeredi 	req->in.args[0].size = strlen(name) + 1;
188492a8780eSMiklos Szeredi 	req->in.args[0].value = name;
1885b93f858aSTejun Heo 	fuse_request_send(fc, req);
188692a8780eSMiklos Szeredi 	err = req->out.h.error;
188792a8780eSMiklos Szeredi 	fuse_put_request(fc, req);
188892a8780eSMiklos Szeredi 	if (err == -ENOSYS) {
188992a8780eSMiklos Szeredi 		fc->no_removexattr = 1;
189092a8780eSMiklos Szeredi 		err = -EOPNOTSUPP;
189192a8780eSMiklos Szeredi 	}
1892d331a415SAnand Avati 	if (!err)
1893d331a415SAnand Avati 		fuse_invalidate_attr(inode);
189492a8780eSMiklos Szeredi 	return err;
189592a8780eSMiklos Szeredi }
189692a8780eSMiklos Szeredi 
1897754661f1SArjan van de Ven static const struct inode_operations fuse_dir_inode_operations = {
1898e5e5558eSMiklos Szeredi 	.lookup		= fuse_lookup,
18999e6268dbSMiklos Szeredi 	.mkdir		= fuse_mkdir,
19009e6268dbSMiklos Szeredi 	.symlink	= fuse_symlink,
19019e6268dbSMiklos Szeredi 	.unlink		= fuse_unlink,
19029e6268dbSMiklos Szeredi 	.rmdir		= fuse_rmdir,
19039e6268dbSMiklos Szeredi 	.rename		= fuse_rename,
19049e6268dbSMiklos Szeredi 	.link		= fuse_link,
19059e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
19069e6268dbSMiklos Szeredi 	.create		= fuse_create,
1907c8ccbe03SMiklos Szeredi 	.atomic_open	= fuse_atomic_open,
19089e6268dbSMiklos Szeredi 	.mknod		= fuse_mknod,
1909e5e5558eSMiklos Szeredi 	.permission	= fuse_permission,
1910e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
191192a8780eSMiklos Szeredi 	.setxattr	= fuse_setxattr,
191292a8780eSMiklos Szeredi 	.getxattr	= fuse_getxattr,
191392a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
191492a8780eSMiklos Szeredi 	.removexattr	= fuse_removexattr,
1915e5e5558eSMiklos Szeredi };
1916e5e5558eSMiklos Szeredi 
19174b6f5d20SArjan van de Ven static const struct file_operations fuse_dir_operations = {
1918b6aeadedSMiklos Szeredi 	.llseek		= generic_file_llseek,
1919e5e5558eSMiklos Szeredi 	.read		= generic_read_dir,
19208d3af7f3SAl Viro 	.iterate	= fuse_readdir,
1921e5e5558eSMiklos Szeredi 	.open		= fuse_dir_open,
1922e5e5558eSMiklos Szeredi 	.release	= fuse_dir_release,
192382547981SMiklos Szeredi 	.fsync		= fuse_dir_fsync,
1924b18da0c5SMiklos Szeredi 	.unlocked_ioctl	= fuse_dir_ioctl,
1925b18da0c5SMiklos Szeredi 	.compat_ioctl	= fuse_dir_compat_ioctl,
1926e5e5558eSMiklos Szeredi };
1927e5e5558eSMiklos Szeredi 
1928754661f1SArjan van de Ven static const struct inode_operations fuse_common_inode_operations = {
19299e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
1930e5e5558eSMiklos Szeredi 	.permission	= fuse_permission,
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 
1938754661f1SArjan van de Ven static const struct inode_operations fuse_symlink_inode_operations = {
19399e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
1940e5e5558eSMiklos Szeredi 	.follow_link	= fuse_follow_link,
1941e5e5558eSMiklos Szeredi 	.put_link	= fuse_put_link,
1942e5e5558eSMiklos Szeredi 	.readlink	= generic_readlink,
1943e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
194492a8780eSMiklos Szeredi 	.setxattr	= fuse_setxattr,
194592a8780eSMiklos Szeredi 	.getxattr	= fuse_getxattr,
194692a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
194792a8780eSMiklos Szeredi 	.removexattr	= fuse_removexattr,
1948e5e5558eSMiklos Szeredi };
1949e5e5558eSMiklos Szeredi 
1950e5e5558eSMiklos Szeredi void fuse_init_common(struct inode *inode)
1951e5e5558eSMiklos Szeredi {
1952e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_common_inode_operations;
1953e5e5558eSMiklos Szeredi }
1954e5e5558eSMiklos Szeredi 
1955e5e5558eSMiklos Szeredi void fuse_init_dir(struct inode *inode)
1956e5e5558eSMiklos Szeredi {
1957e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_dir_inode_operations;
1958e5e5558eSMiklos Szeredi 	inode->i_fop = &fuse_dir_operations;
1959e5e5558eSMiklos Szeredi }
1960e5e5558eSMiklos Szeredi 
1961e5e5558eSMiklos Szeredi void fuse_init_symlink(struct inode *inode)
1962e5e5558eSMiklos Szeredi {
1963e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_symlink_inode_operations;
1964e5e5558eSMiklos Szeredi }
1965