xref: /openbmc/linux/fs/fuse/dir.c (revision 5835f3390e35ae3da9add646a2ca2cc30b47370e)
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 
270c180eebeSMiklos Szeredi int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name,
271c180eebeSMiklos Szeredi 		     struct fuse_entry_out *outarg, struct inode **inode)
272c180eebeSMiklos Szeredi {
273c180eebeSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn_super(sb);
274c180eebeSMiklos Szeredi 	struct fuse_req *req;
27507e77dcaSMiklos Szeredi 	struct fuse_forget_link *forget;
276c180eebeSMiklos Szeredi 	u64 attr_version;
277c180eebeSMiklos Szeredi 	int err;
278c180eebeSMiklos Szeredi 
279c180eebeSMiklos Szeredi 	*inode = NULL;
280c180eebeSMiklos Szeredi 	err = -ENAMETOOLONG;
281c180eebeSMiklos Szeredi 	if (name->len > FUSE_NAME_MAX)
282c180eebeSMiklos Szeredi 		goto out;
283c180eebeSMiklos Szeredi 
284b111c8c0SMaxim Patlasov 	req = fuse_get_req_nopages(fc);
285c180eebeSMiklos Szeredi 	err = PTR_ERR(req);
286c180eebeSMiklos Szeredi 	if (IS_ERR(req))
287c180eebeSMiklos Szeredi 		goto out;
288c180eebeSMiklos Szeredi 
28907e77dcaSMiklos Szeredi 	forget = fuse_alloc_forget();
29007e77dcaSMiklos Szeredi 	err = -ENOMEM;
29107e77dcaSMiklos Szeredi 	if (!forget) {
292c180eebeSMiklos Szeredi 		fuse_put_request(fc, req);
293c180eebeSMiklos Szeredi 		goto out;
294c180eebeSMiklos Szeredi 	}
295c180eebeSMiklos Szeredi 
296c180eebeSMiklos Szeredi 	attr_version = fuse_get_attr_version(fc);
297c180eebeSMiklos Szeredi 
298c180eebeSMiklos Szeredi 	fuse_lookup_init(fc, req, nodeid, name, outarg);
299b93f858aSTejun Heo 	fuse_request_send(fc, req);
300c180eebeSMiklos Szeredi 	err = req->out.h.error;
301c180eebeSMiklos Szeredi 	fuse_put_request(fc, req);
302c180eebeSMiklos Szeredi 	/* Zero nodeid is same as -ENOENT, but with valid timeout */
303c180eebeSMiklos Szeredi 	if (err || !outarg->nodeid)
304c180eebeSMiklos Szeredi 		goto out_put_forget;
305c180eebeSMiklos Szeredi 
306c180eebeSMiklos Szeredi 	err = -EIO;
307c180eebeSMiklos Szeredi 	if (!outarg->nodeid)
308c180eebeSMiklos Szeredi 		goto out_put_forget;
309c180eebeSMiklos Szeredi 	if (!fuse_valid_type(outarg->attr.mode))
310c180eebeSMiklos Szeredi 		goto out_put_forget;
311c180eebeSMiklos Szeredi 
312c180eebeSMiklos Szeredi 	*inode = fuse_iget(sb, outarg->nodeid, outarg->generation,
313c180eebeSMiklos Szeredi 			   &outarg->attr, entry_attr_timeout(outarg),
314c180eebeSMiklos Szeredi 			   attr_version);
315c180eebeSMiklos Szeredi 	err = -ENOMEM;
316c180eebeSMiklos Szeredi 	if (!*inode) {
31707e77dcaSMiklos Szeredi 		fuse_queue_forget(fc, forget, outarg->nodeid, 1);
318c180eebeSMiklos Szeredi 		goto out;
319c180eebeSMiklos Szeredi 	}
320c180eebeSMiklos Szeredi 	err = 0;
321c180eebeSMiklos Szeredi 
322c180eebeSMiklos Szeredi  out_put_forget:
32307e77dcaSMiklos Szeredi 	kfree(forget);
324c180eebeSMiklos Szeredi  out:
325c180eebeSMiklos Szeredi 	return err;
326c180eebeSMiklos Szeredi }
327c180eebeSMiklos Szeredi 
328*5835f339SMiklos Szeredi static struct dentry *fuse_materialise_dentry(struct dentry *dentry,
329*5835f339SMiklos Szeredi 					      struct inode *inode)
330*5835f339SMiklos Szeredi {
331*5835f339SMiklos Szeredi 	struct dentry *newent;
332*5835f339SMiklos Szeredi 
333*5835f339SMiklos Szeredi 	if (inode && S_ISDIR(inode->i_mode)) {
334*5835f339SMiklos Szeredi 		struct fuse_conn *fc = get_fuse_conn(inode);
335*5835f339SMiklos Szeredi 
336*5835f339SMiklos Szeredi 		mutex_lock(&fc->inst_mutex);
337*5835f339SMiklos Szeredi 		newent = d_materialise_unique(dentry, inode);
338*5835f339SMiklos Szeredi 		mutex_unlock(&fc->inst_mutex);
339*5835f339SMiklos Szeredi 	} else {
340*5835f339SMiklos Szeredi 		newent = d_materialise_unique(dentry, inode);
341*5835f339SMiklos Szeredi 	}
342*5835f339SMiklos Szeredi 
343*5835f339SMiklos Szeredi 	return newent;
344*5835f339SMiklos Szeredi }
345*5835f339SMiklos Szeredi 
3460aa7c699SMiklos Szeredi static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
34700cd8dd3SAl Viro 				  unsigned int flags)
348e5e5558eSMiklos Szeredi {
349e5e5558eSMiklos Szeredi 	int err;
350e5e5558eSMiklos Szeredi 	struct fuse_entry_out outarg;
351c180eebeSMiklos Szeredi 	struct inode *inode;
3520de6256dSMiklos Szeredi 	struct dentry *newent;
353c180eebeSMiklos Szeredi 	bool outarg_valid = true;
354e5e5558eSMiklos Szeredi 
355c180eebeSMiklos Szeredi 	err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name,
356c180eebeSMiklos Szeredi 			       &outarg, &inode);
357c180eebeSMiklos Szeredi 	if (err == -ENOENT) {
358c180eebeSMiklos Szeredi 		outarg_valid = false;
359c180eebeSMiklos Szeredi 		err = 0;
3602d51013eSMiklos Szeredi 	}
361c180eebeSMiklos Szeredi 	if (err)
362c180eebeSMiklos Szeredi 		goto out_err;
3632d51013eSMiklos Szeredi 
364ee4e5271SMiklos Szeredi 	err = -EIO;
365c180eebeSMiklos Szeredi 	if (inode && get_node_id(inode) == FUSE_ROOT_ID)
366c180eebeSMiklos Szeredi 		goto out_iput;
367e5e5558eSMiklos Szeredi 
368*5835f339SMiklos Szeredi 	newent = fuse_materialise_dentry(entry, inode);
369c180eebeSMiklos Szeredi 	err = PTR_ERR(newent);
370c180eebeSMiklos Szeredi 	if (IS_ERR(newent))
371*5835f339SMiklos Szeredi 		goto out_err;
372d2a85164SMiklos Szeredi 
3730de6256dSMiklos Szeredi 	entry = newent ? newent : entry;
374c180eebeSMiklos Szeredi 	if (outarg_valid)
3751fb69e78SMiklos Szeredi 		fuse_change_entry_timeout(entry, &outarg);
3768cbdf1e6SMiklos Szeredi 	else
3778cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
378c180eebeSMiklos Szeredi 
3794582a4abSFeng Shuo 	fuse_advise_use_readdirplus(dir);
3800de6256dSMiklos Szeredi 	return newent;
381c180eebeSMiklos Szeredi 
382c180eebeSMiklos Szeredi  out_iput:
383c180eebeSMiklos Szeredi 	iput(inode);
384c180eebeSMiklos Szeredi  out_err:
385c180eebeSMiklos Szeredi 	return ERR_PTR(err);
386e5e5558eSMiklos Szeredi }
387e5e5558eSMiklos Szeredi 
3886f9f1180SMiklos Szeredi /*
3896f9f1180SMiklos Szeredi  * Atomic create+open operation
3906f9f1180SMiklos Szeredi  *
3916f9f1180SMiklos Szeredi  * If the filesystem doesn't support this, then fall back to separate
3926f9f1180SMiklos Szeredi  * 'mknod' + 'open' requests.
3936f9f1180SMiklos Szeredi  */
394d9585277SAl Viro static int fuse_create_open(struct inode *dir, struct dentry *entry,
39530d90494SAl Viro 			    struct file *file, unsigned flags,
39647237687SAl Viro 			    umode_t mode, int *opened)
397fd72faacSMiklos Szeredi {
398fd72faacSMiklos Szeredi 	int err;
399fd72faacSMiklos Szeredi 	struct inode *inode;
400fd72faacSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
401fd72faacSMiklos Szeredi 	struct fuse_req *req;
40207e77dcaSMiklos Szeredi 	struct fuse_forget_link *forget;
403e0a43ddcSMiklos Szeredi 	struct fuse_create_in inarg;
404fd72faacSMiklos Szeredi 	struct fuse_open_out outopen;
405fd72faacSMiklos Szeredi 	struct fuse_entry_out outentry;
406fd72faacSMiklos Szeredi 	struct fuse_file *ff;
407fd72faacSMiklos Szeredi 
408af109bcaSMiklos Szeredi 	/* Userspace expects S_IFREG in create mode */
409af109bcaSMiklos Szeredi 	BUG_ON((mode & S_IFMT) != S_IFREG);
410af109bcaSMiklos Szeredi 
41107e77dcaSMiklos Szeredi 	forget = fuse_alloc_forget();
412c8ccbe03SMiklos Szeredi 	err = -ENOMEM;
41307e77dcaSMiklos Szeredi 	if (!forget)
414c8ccbe03SMiklos Szeredi 		goto out_err;
41551eb01e7SMiklos Szeredi 
416b111c8c0SMaxim Patlasov 	req = fuse_get_req_nopages(fc);
41751eb01e7SMiklos Szeredi 	err = PTR_ERR(req);
418ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
41951eb01e7SMiklos Szeredi 		goto out_put_forget_req;
420fd72faacSMiklos Szeredi 
421ce1d5a49SMiklos Szeredi 	err = -ENOMEM;
422acf99433STejun Heo 	ff = fuse_file_alloc(fc);
423fd72faacSMiklos Szeredi 	if (!ff)
424fd72faacSMiklos Szeredi 		goto out_put_request;
425fd72faacSMiklos Szeredi 
426e0a43ddcSMiklos Szeredi 	if (!fc->dont_mask)
427e0a43ddcSMiklos Szeredi 		mode &= ~current_umask();
428e0a43ddcSMiklos Szeredi 
429fd72faacSMiklos Szeredi 	flags &= ~O_NOCTTY;
430fd72faacSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
4310e9663eeSMiklos Szeredi 	memset(&outentry, 0, sizeof(outentry));
432fd72faacSMiklos Szeredi 	inarg.flags = flags;
433fd72faacSMiklos Szeredi 	inarg.mode = mode;
434e0a43ddcSMiklos Szeredi 	inarg.umask = current_umask();
435fd72faacSMiklos Szeredi 	req->in.h.opcode = FUSE_CREATE;
436fd72faacSMiklos Szeredi 	req->in.h.nodeid = get_node_id(dir);
437fd72faacSMiklos Szeredi 	req->in.numargs = 2;
438e0a43ddcSMiklos Szeredi 	req->in.args[0].size = fc->minor < 12 ? sizeof(struct fuse_open_in) :
439e0a43ddcSMiklos Szeredi 						sizeof(inarg);
440fd72faacSMiklos Szeredi 	req->in.args[0].value = &inarg;
441fd72faacSMiklos Szeredi 	req->in.args[1].size = entry->d_name.len + 1;
442fd72faacSMiklos Szeredi 	req->in.args[1].value = entry->d_name.name;
443fd72faacSMiklos Szeredi 	req->out.numargs = 2;
4440e9663eeSMiklos Szeredi 	if (fc->minor < 9)
4450e9663eeSMiklos Szeredi 		req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
4460e9663eeSMiklos Szeredi 	else
447fd72faacSMiklos Szeredi 		req->out.args[0].size = sizeof(outentry);
448fd72faacSMiklos Szeredi 	req->out.args[0].value = &outentry;
449fd72faacSMiklos Szeredi 	req->out.args[1].size = sizeof(outopen);
450fd72faacSMiklos Szeredi 	req->out.args[1].value = &outopen;
451b93f858aSTejun Heo 	fuse_request_send(fc, req);
452fd72faacSMiklos Szeredi 	err = req->out.h.error;
453c8ccbe03SMiklos Szeredi 	if (err)
454fd72faacSMiklos Szeredi 		goto out_free_ff;
455fd72faacSMiklos Szeredi 
456fd72faacSMiklos Szeredi 	err = -EIO;
4572827d0b2SMiklos Szeredi 	if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid))
458fd72faacSMiklos Szeredi 		goto out_free_ff;
459fd72faacSMiklos Szeredi 
46051eb01e7SMiklos Szeredi 	fuse_put_request(fc, req);
461c7b7143cSMiklos Szeredi 	ff->fh = outopen.fh;
462c7b7143cSMiklos Szeredi 	ff->nodeid = outentry.nodeid;
463c7b7143cSMiklos Szeredi 	ff->open_flags = outopen.open_flags;
464fd72faacSMiklos Szeredi 	inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
4651fb69e78SMiklos Szeredi 			  &outentry.attr, entry_attr_timeout(&outentry), 0);
466fd72faacSMiklos Szeredi 	if (!inode) {
467fd72faacSMiklos Szeredi 		flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
4688b0797a4SMiklos Szeredi 		fuse_sync_release(ff, flags);
46907e77dcaSMiklos Szeredi 		fuse_queue_forget(fc, forget, outentry.nodeid, 1);
470c8ccbe03SMiklos Szeredi 		err = -ENOMEM;
471c8ccbe03SMiklos Szeredi 		goto out_err;
472fd72faacSMiklos Szeredi 	}
47307e77dcaSMiklos Szeredi 	kfree(forget);
474fd72faacSMiklos Szeredi 	d_instantiate(entry, inode);
4751fb69e78SMiklos Szeredi 	fuse_change_entry_timeout(entry, &outentry);
4760952b2a4SMiklos Szeredi 	fuse_invalidate_attr(dir);
47730d90494SAl Viro 	err = finish_open(file, entry, generic_file_open, opened);
47830d90494SAl Viro 	if (err) {
4798b0797a4SMiklos Szeredi 		fuse_sync_release(ff, flags);
480c8ccbe03SMiklos Szeredi 	} else {
481c7b7143cSMiklos Szeredi 		file->private_data = fuse_file_get(ff);
482c7b7143cSMiklos Szeredi 		fuse_finish_open(inode, file);
483c8ccbe03SMiklos Szeredi 	}
484d9585277SAl Viro 	return err;
485fd72faacSMiklos Szeredi 
486fd72faacSMiklos Szeredi out_free_ff:
487fd72faacSMiklos Szeredi 	fuse_file_free(ff);
488fd72faacSMiklos Szeredi out_put_request:
489fd72faacSMiklos Szeredi 	fuse_put_request(fc, req);
49051eb01e7SMiklos Szeredi out_put_forget_req:
49107e77dcaSMiklos Szeredi 	kfree(forget);
492c8ccbe03SMiklos Szeredi out_err:
493d9585277SAl Viro 	return err;
494c8ccbe03SMiklos Szeredi }
495c8ccbe03SMiklos Szeredi 
496c8ccbe03SMiklos Szeredi static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t);
497d9585277SAl Viro static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
49830d90494SAl Viro 			    struct file *file, unsigned flags,
49947237687SAl Viro 			    umode_t mode, int *opened)
500c8ccbe03SMiklos Szeredi {
501c8ccbe03SMiklos Szeredi 	int err;
502c8ccbe03SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
503c8ccbe03SMiklos Szeredi 	struct dentry *res = NULL;
504c8ccbe03SMiklos Szeredi 
505c8ccbe03SMiklos Szeredi 	if (d_unhashed(entry)) {
50600cd8dd3SAl Viro 		res = fuse_lookup(dir, entry, 0);
507c8ccbe03SMiklos Szeredi 		if (IS_ERR(res))
508d9585277SAl Viro 			return PTR_ERR(res);
509c8ccbe03SMiklos Szeredi 
510c8ccbe03SMiklos Szeredi 		if (res)
511c8ccbe03SMiklos Szeredi 			entry = res;
512c8ccbe03SMiklos Szeredi 	}
513c8ccbe03SMiklos Szeredi 
514c8ccbe03SMiklos Szeredi 	if (!(flags & O_CREAT) || entry->d_inode)
515c8ccbe03SMiklos Szeredi 		goto no_open;
516c8ccbe03SMiklos Szeredi 
517c8ccbe03SMiklos Szeredi 	/* Only creates */
51847237687SAl Viro 	*opened |= FILE_CREATED;
519c8ccbe03SMiklos Szeredi 
520c8ccbe03SMiklos Szeredi 	if (fc->no_create)
521c8ccbe03SMiklos Szeredi 		goto mknod;
522c8ccbe03SMiklos Szeredi 
52330d90494SAl Viro 	err = fuse_create_open(dir, entry, file, flags, mode, opened);
524d9585277SAl Viro 	if (err == -ENOSYS) {
525c8ccbe03SMiklos Szeredi 		fc->no_create = 1;
526c8ccbe03SMiklos Szeredi 		goto mknod;
527c8ccbe03SMiklos Szeredi 	}
528c8ccbe03SMiklos Szeredi out_dput:
529c8ccbe03SMiklos Szeredi 	dput(res);
530d9585277SAl Viro 	return err;
531c8ccbe03SMiklos Szeredi 
532c8ccbe03SMiklos Szeredi mknod:
533c8ccbe03SMiklos Szeredi 	err = fuse_mknod(dir, entry, mode, 0);
534d9585277SAl Viro 	if (err)
535c8ccbe03SMiklos Szeredi 		goto out_dput;
536c8ccbe03SMiklos Szeredi no_open:
537e45198a6SAl Viro 	return finish_no_open(file, res);
538fd72faacSMiklos Szeredi }
539fd72faacSMiklos Szeredi 
5406f9f1180SMiklos Szeredi /*
5416f9f1180SMiklos Szeredi  * Code shared between mknod, mkdir, symlink and link
5426f9f1180SMiklos Szeredi  */
5439e6268dbSMiklos Szeredi static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
5449e6268dbSMiklos Szeredi 			    struct inode *dir, struct dentry *entry,
545541af6a0SAl Viro 			    umode_t mode)
5469e6268dbSMiklos Szeredi {
5479e6268dbSMiklos Szeredi 	struct fuse_entry_out outarg;
5489e6268dbSMiklos Szeredi 	struct inode *inode;
5499e6268dbSMiklos Szeredi 	int err;
55007e77dcaSMiklos Szeredi 	struct fuse_forget_link *forget;
5512d51013eSMiklos Szeredi 
55207e77dcaSMiklos Szeredi 	forget = fuse_alloc_forget();
55307e77dcaSMiklos Szeredi 	if (!forget) {
5542d51013eSMiklos Szeredi 		fuse_put_request(fc, req);
55507e77dcaSMiklos Szeredi 		return -ENOMEM;
5562d51013eSMiklos Szeredi 	}
5579e6268dbSMiklos Szeredi 
5580e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
5599e6268dbSMiklos Szeredi 	req->in.h.nodeid = get_node_id(dir);
5609e6268dbSMiklos Szeredi 	req->out.numargs = 1;
5610e9663eeSMiklos Szeredi 	if (fc->minor < 9)
5620e9663eeSMiklos Szeredi 		req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
5630e9663eeSMiklos Szeredi 	else
5649e6268dbSMiklos Szeredi 		req->out.args[0].size = sizeof(outarg);
5659e6268dbSMiklos Szeredi 	req->out.args[0].value = &outarg;
566b93f858aSTejun Heo 	fuse_request_send(fc, req);
5679e6268dbSMiklos Szeredi 	err = req->out.h.error;
5689e6268dbSMiklos Szeredi 	fuse_put_request(fc, req);
5692d51013eSMiklos Szeredi 	if (err)
5702d51013eSMiklos Szeredi 		goto out_put_forget_req;
5712d51013eSMiklos Szeredi 
57239ee059aSMiklos Szeredi 	err = -EIO;
57339ee059aSMiklos Szeredi 	if (invalid_nodeid(outarg.nodeid))
5742d51013eSMiklos Szeredi 		goto out_put_forget_req;
57539ee059aSMiklos Szeredi 
57639ee059aSMiklos Szeredi 	if ((outarg.attr.mode ^ mode) & S_IFMT)
5772d51013eSMiklos Szeredi 		goto out_put_forget_req;
57839ee059aSMiklos Szeredi 
5799e6268dbSMiklos Szeredi 	inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
5801fb69e78SMiklos Szeredi 			  &outarg.attr, entry_attr_timeout(&outarg), 0);
5819e6268dbSMiklos Szeredi 	if (!inode) {
58207e77dcaSMiklos Szeredi 		fuse_queue_forget(fc, forget, outarg.nodeid, 1);
5839e6268dbSMiklos Szeredi 		return -ENOMEM;
5849e6268dbSMiklos Szeredi 	}
58507e77dcaSMiklos Szeredi 	kfree(forget);
5869e6268dbSMiklos Szeredi 
587d2a85164SMiklos Szeredi 	if (S_ISDIR(inode->i_mode)) {
588d2a85164SMiklos Szeredi 		struct dentry *alias;
589d2a85164SMiklos Szeredi 		mutex_lock(&fc->inst_mutex);
590d2a85164SMiklos Szeredi 		alias = d_find_alias(inode);
591d2a85164SMiklos Szeredi 		if (alias) {
592d2a85164SMiklos Szeredi 			/* New directory must have moved since mkdir */
593d2a85164SMiklos Szeredi 			mutex_unlock(&fc->inst_mutex);
594d2a85164SMiklos Szeredi 			dput(alias);
5959e6268dbSMiklos Szeredi 			iput(inode);
596d2a85164SMiklos Szeredi 			return -EBUSY;
5979e6268dbSMiklos Szeredi 		}
5989e6268dbSMiklos Szeredi 		d_instantiate(entry, inode);
599d2a85164SMiklos Szeredi 		mutex_unlock(&fc->inst_mutex);
600d2a85164SMiklos Szeredi 	} else
601d2a85164SMiklos Szeredi 		d_instantiate(entry, inode);
602d2a85164SMiklos Szeredi 
6031fb69e78SMiklos Szeredi 	fuse_change_entry_timeout(entry, &outarg);
6049e6268dbSMiklos Szeredi 	fuse_invalidate_attr(dir);
6059e6268dbSMiklos Szeredi 	return 0;
60639ee059aSMiklos Szeredi 
6072d51013eSMiklos Szeredi  out_put_forget_req:
60807e77dcaSMiklos Szeredi 	kfree(forget);
60939ee059aSMiklos Szeredi 	return err;
6109e6268dbSMiklos Szeredi }
6119e6268dbSMiklos Szeredi 
6121a67aafbSAl Viro static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode,
6139e6268dbSMiklos Szeredi 		      dev_t rdev)
6149e6268dbSMiklos Szeredi {
6159e6268dbSMiklos Szeredi 	struct fuse_mknod_in inarg;
6169e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
617b111c8c0SMaxim Patlasov 	struct fuse_req *req = fuse_get_req_nopages(fc);
618ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
619ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
6209e6268dbSMiklos Szeredi 
621e0a43ddcSMiklos Szeredi 	if (!fc->dont_mask)
622e0a43ddcSMiklos Szeredi 		mode &= ~current_umask();
623e0a43ddcSMiklos Szeredi 
6249e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
6259e6268dbSMiklos Szeredi 	inarg.mode = mode;
6269e6268dbSMiklos Szeredi 	inarg.rdev = new_encode_dev(rdev);
627e0a43ddcSMiklos Szeredi 	inarg.umask = current_umask();
6289e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_MKNOD;
6299e6268dbSMiklos Szeredi 	req->in.numargs = 2;
630e0a43ddcSMiklos Szeredi 	req->in.args[0].size = fc->minor < 12 ? FUSE_COMPAT_MKNOD_IN_SIZE :
631e0a43ddcSMiklos Szeredi 						sizeof(inarg);
6329e6268dbSMiklos Szeredi 	req->in.args[0].value = &inarg;
6339e6268dbSMiklos Szeredi 	req->in.args[1].size = entry->d_name.len + 1;
6349e6268dbSMiklos Szeredi 	req->in.args[1].value = entry->d_name.name;
6359e6268dbSMiklos Szeredi 	return create_new_entry(fc, req, dir, entry, mode);
6369e6268dbSMiklos Szeredi }
6379e6268dbSMiklos Szeredi 
6384acdaf27SAl Viro static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode,
639ebfc3b49SAl Viro 		       bool excl)
6409e6268dbSMiklos Szeredi {
6419e6268dbSMiklos Szeredi 	return fuse_mknod(dir, entry, mode, 0);
6429e6268dbSMiklos Szeredi }
6439e6268dbSMiklos Szeredi 
64418bb1db3SAl Viro static int fuse_mkdir(struct inode *dir, struct dentry *entry, umode_t mode)
6459e6268dbSMiklos Szeredi {
6469e6268dbSMiklos Szeredi 	struct fuse_mkdir_in inarg;
6479e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
648b111c8c0SMaxim Patlasov 	struct fuse_req *req = fuse_get_req_nopages(fc);
649ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
650ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
6519e6268dbSMiklos Szeredi 
652e0a43ddcSMiklos Szeredi 	if (!fc->dont_mask)
653e0a43ddcSMiklos Szeredi 		mode &= ~current_umask();
654e0a43ddcSMiklos Szeredi 
6559e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
6569e6268dbSMiklos Szeredi 	inarg.mode = mode;
657e0a43ddcSMiklos Szeredi 	inarg.umask = current_umask();
6589e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_MKDIR;
6599e6268dbSMiklos Szeredi 	req->in.numargs = 2;
6609e6268dbSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
6619e6268dbSMiklos Szeredi 	req->in.args[0].value = &inarg;
6629e6268dbSMiklos Szeredi 	req->in.args[1].size = entry->d_name.len + 1;
6639e6268dbSMiklos Szeredi 	req->in.args[1].value = entry->d_name.name;
6649e6268dbSMiklos Szeredi 	return create_new_entry(fc, req, dir, entry, S_IFDIR);
6659e6268dbSMiklos Szeredi }
6669e6268dbSMiklos Szeredi 
6679e6268dbSMiklos Szeredi static int fuse_symlink(struct inode *dir, struct dentry *entry,
6689e6268dbSMiklos Szeredi 			const char *link)
6699e6268dbSMiklos Szeredi {
6709e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
6719e6268dbSMiklos Szeredi 	unsigned len = strlen(link) + 1;
672b111c8c0SMaxim Patlasov 	struct fuse_req *req = fuse_get_req_nopages(fc);
673ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
674ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
6759e6268dbSMiklos Szeredi 
6769e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_SYMLINK;
6779e6268dbSMiklos Szeredi 	req->in.numargs = 2;
6789e6268dbSMiklos Szeredi 	req->in.args[0].size = entry->d_name.len + 1;
6799e6268dbSMiklos Szeredi 	req->in.args[0].value = entry->d_name.name;
6809e6268dbSMiklos Szeredi 	req->in.args[1].size = len;
6819e6268dbSMiklos Szeredi 	req->in.args[1].value = link;
6829e6268dbSMiklos Szeredi 	return create_new_entry(fc, req, dir, entry, S_IFLNK);
6839e6268dbSMiklos Szeredi }
6849e6268dbSMiklos Szeredi 
6859e6268dbSMiklos Szeredi static int fuse_unlink(struct inode *dir, struct dentry *entry)
6869e6268dbSMiklos Szeredi {
6879e6268dbSMiklos Szeredi 	int err;
6889e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
689b111c8c0SMaxim Patlasov 	struct fuse_req *req = fuse_get_req_nopages(fc);
690ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
691ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
6929e6268dbSMiklos Szeredi 
6939e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_UNLINK;
6949e6268dbSMiklos Szeredi 	req->in.h.nodeid = get_node_id(dir);
6959e6268dbSMiklos Szeredi 	req->in.numargs = 1;
6969e6268dbSMiklos Szeredi 	req->in.args[0].size = entry->d_name.len + 1;
6979e6268dbSMiklos Szeredi 	req->in.args[0].value = entry->d_name.name;
698b93f858aSTejun Heo 	fuse_request_send(fc, req);
6999e6268dbSMiklos Szeredi 	err = req->out.h.error;
7009e6268dbSMiklos Szeredi 	fuse_put_request(fc, req);
7019e6268dbSMiklos Szeredi 	if (!err) {
7029e6268dbSMiklos Szeredi 		struct inode *inode = entry->d_inode;
703ac45d613SMiklos Szeredi 		struct fuse_inode *fi = get_fuse_inode(inode);
7049e6268dbSMiklos Szeredi 
705ac45d613SMiklos Szeredi 		spin_lock(&fc->lock);
706ac45d613SMiklos Szeredi 		fi->attr_version = ++fc->attr_version;
707dfca7cebSMiklos Szeredi 		/*
708dfca7cebSMiklos Szeredi 		 * If i_nlink == 0 then unlink doesn't make sense, yet this can
709dfca7cebSMiklos Szeredi 		 * happen if userspace filesystem is careless.  It would be
710dfca7cebSMiklos Szeredi 		 * difficult to enforce correct nlink usage so just ignore this
711dfca7cebSMiklos Szeredi 		 * condition here
712dfca7cebSMiklos Szeredi 		 */
713dfca7cebSMiklos Szeredi 		if (inode->i_nlink > 0)
714ac45d613SMiklos Szeredi 			drop_nlink(inode);
715ac45d613SMiklos Szeredi 		spin_unlock(&fc->lock);
7169e6268dbSMiklos Szeredi 		fuse_invalidate_attr(inode);
7179e6268dbSMiklos Szeredi 		fuse_invalidate_attr(dir);
7188cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
7199e6268dbSMiklos Szeredi 	} else if (err == -EINTR)
7209e6268dbSMiklos Szeredi 		fuse_invalidate_entry(entry);
7219e6268dbSMiklos Szeredi 	return err;
7229e6268dbSMiklos Szeredi }
7239e6268dbSMiklos Szeredi 
7249e6268dbSMiklos Szeredi static int fuse_rmdir(struct inode *dir, struct dentry *entry)
7259e6268dbSMiklos Szeredi {
7269e6268dbSMiklos Szeredi 	int err;
7279e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
728b111c8c0SMaxim Patlasov 	struct fuse_req *req = fuse_get_req_nopages(fc);
729ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
730ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
7319e6268dbSMiklos Szeredi 
7329e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_RMDIR;
7339e6268dbSMiklos Szeredi 	req->in.h.nodeid = get_node_id(dir);
7349e6268dbSMiklos Szeredi 	req->in.numargs = 1;
7359e6268dbSMiklos Szeredi 	req->in.args[0].size = entry->d_name.len + 1;
7369e6268dbSMiklos Szeredi 	req->in.args[0].value = entry->d_name.name;
737b93f858aSTejun Heo 	fuse_request_send(fc, req);
7389e6268dbSMiklos Szeredi 	err = req->out.h.error;
7399e6268dbSMiklos Szeredi 	fuse_put_request(fc, req);
7409e6268dbSMiklos Szeredi 	if (!err) {
741ce71ec36SDave Hansen 		clear_nlink(entry->d_inode);
7429e6268dbSMiklos Szeredi 		fuse_invalidate_attr(dir);
7438cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
7449e6268dbSMiklos Szeredi 	} else if (err == -EINTR)
7459e6268dbSMiklos Szeredi 		fuse_invalidate_entry(entry);
7469e6268dbSMiklos Szeredi 	return err;
7479e6268dbSMiklos Szeredi }
7489e6268dbSMiklos Szeredi 
7499e6268dbSMiklos Szeredi static int fuse_rename(struct inode *olddir, struct dentry *oldent,
7509e6268dbSMiklos Szeredi 		       struct inode *newdir, struct dentry *newent)
7519e6268dbSMiklos Szeredi {
7529e6268dbSMiklos Szeredi 	int err;
7539e6268dbSMiklos Szeredi 	struct fuse_rename_in inarg;
7549e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(olddir);
755b111c8c0SMaxim Patlasov 	struct fuse_req *req = fuse_get_req_nopages(fc);
756e4eaac06SSage Weil 
757ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
758ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
7599e6268dbSMiklos Szeredi 
7609e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
7619e6268dbSMiklos Szeredi 	inarg.newdir = get_node_id(newdir);
7629e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_RENAME;
7639e6268dbSMiklos Szeredi 	req->in.h.nodeid = get_node_id(olddir);
7649e6268dbSMiklos Szeredi 	req->in.numargs = 3;
7659e6268dbSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
7669e6268dbSMiklos Szeredi 	req->in.args[0].value = &inarg;
7679e6268dbSMiklos Szeredi 	req->in.args[1].size = oldent->d_name.len + 1;
7689e6268dbSMiklos Szeredi 	req->in.args[1].value = oldent->d_name.name;
7699e6268dbSMiklos Szeredi 	req->in.args[2].size = newent->d_name.len + 1;
7709e6268dbSMiklos Szeredi 	req->in.args[2].value = newent->d_name.name;
771b93f858aSTejun Heo 	fuse_request_send(fc, req);
7729e6268dbSMiklos Szeredi 	err = req->out.h.error;
7739e6268dbSMiklos Szeredi 	fuse_put_request(fc, req);
7749e6268dbSMiklos Szeredi 	if (!err) {
77508b63307SMiklos Szeredi 		/* ctime changes */
77608b63307SMiklos Szeredi 		fuse_invalidate_attr(oldent->d_inode);
77708b63307SMiklos Szeredi 
7789e6268dbSMiklos Szeredi 		fuse_invalidate_attr(olddir);
7799e6268dbSMiklos Szeredi 		if (olddir != newdir)
7809e6268dbSMiklos Szeredi 			fuse_invalidate_attr(newdir);
7818cbdf1e6SMiklos Szeredi 
7828cbdf1e6SMiklos Szeredi 		/* newent will end up negative */
7835219f346SMiklos Szeredi 		if (newent->d_inode) {
7845219f346SMiklos Szeredi 			fuse_invalidate_attr(newent->d_inode);
7858cbdf1e6SMiklos Szeredi 			fuse_invalidate_entry_cache(newent);
7865219f346SMiklos Szeredi 		}
7879e6268dbSMiklos Szeredi 	} else if (err == -EINTR) {
7889e6268dbSMiklos Szeredi 		/* If request was interrupted, DEITY only knows if the
7899e6268dbSMiklos Szeredi 		   rename actually took place.  If the invalidation
7909e6268dbSMiklos Szeredi 		   fails (e.g. some process has CWD under the renamed
7919e6268dbSMiklos Szeredi 		   directory), then there can be inconsistency between
7929e6268dbSMiklos Szeredi 		   the dcache and the real filesystem.  Tough luck. */
7939e6268dbSMiklos Szeredi 		fuse_invalidate_entry(oldent);
7949e6268dbSMiklos Szeredi 		if (newent->d_inode)
7959e6268dbSMiklos Szeredi 			fuse_invalidate_entry(newent);
7969e6268dbSMiklos Szeredi 	}
7979e6268dbSMiklos Szeredi 
7989e6268dbSMiklos Szeredi 	return err;
7999e6268dbSMiklos Szeredi }
8009e6268dbSMiklos Szeredi 
8019e6268dbSMiklos Szeredi static int fuse_link(struct dentry *entry, struct inode *newdir,
8029e6268dbSMiklos Szeredi 		     struct dentry *newent)
8039e6268dbSMiklos Szeredi {
8049e6268dbSMiklos Szeredi 	int err;
8059e6268dbSMiklos Szeredi 	struct fuse_link_in inarg;
8069e6268dbSMiklos Szeredi 	struct inode *inode = entry->d_inode;
8079e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
808b111c8c0SMaxim Patlasov 	struct fuse_req *req = fuse_get_req_nopages(fc);
809ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
810ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
8119e6268dbSMiklos Szeredi 
8129e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
8139e6268dbSMiklos Szeredi 	inarg.oldnodeid = get_node_id(inode);
8149e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_LINK;
8159e6268dbSMiklos Szeredi 	req->in.numargs = 2;
8169e6268dbSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
8179e6268dbSMiklos Szeredi 	req->in.args[0].value = &inarg;
8189e6268dbSMiklos Szeredi 	req->in.args[1].size = newent->d_name.len + 1;
8199e6268dbSMiklos Szeredi 	req->in.args[1].value = newent->d_name.name;
8209e6268dbSMiklos Szeredi 	err = create_new_entry(fc, req, newdir, newent, inode->i_mode);
8219e6268dbSMiklos Szeredi 	/* Contrary to "normal" filesystems it can happen that link
8229e6268dbSMiklos Szeredi 	   makes two "logical" inodes point to the same "physical"
8239e6268dbSMiklos Szeredi 	   inode.  We invalidate the attributes of the old one, so it
8249e6268dbSMiklos Szeredi 	   will reflect changes in the backing inode (link count,
8259e6268dbSMiklos Szeredi 	   etc.)
8269e6268dbSMiklos Szeredi 	*/
827ac45d613SMiklos Szeredi 	if (!err) {
828ac45d613SMiklos Szeredi 		struct fuse_inode *fi = get_fuse_inode(inode);
829ac45d613SMiklos Szeredi 
830ac45d613SMiklos Szeredi 		spin_lock(&fc->lock);
831ac45d613SMiklos Szeredi 		fi->attr_version = ++fc->attr_version;
832ac45d613SMiklos Szeredi 		inc_nlink(inode);
833ac45d613SMiklos Szeredi 		spin_unlock(&fc->lock);
8349e6268dbSMiklos Szeredi 		fuse_invalidate_attr(inode);
835ac45d613SMiklos Szeredi 	} else if (err == -EINTR) {
836ac45d613SMiklos Szeredi 		fuse_invalidate_attr(inode);
837ac45d613SMiklos Szeredi 	}
8389e6268dbSMiklos Szeredi 	return err;
8399e6268dbSMiklos Szeredi }
8409e6268dbSMiklos Szeredi 
8411fb69e78SMiklos Szeredi static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
8421fb69e78SMiklos Szeredi 			  struct kstat *stat)
8431fb69e78SMiklos Szeredi {
844203627bbSMiklos Szeredi 	unsigned int blkbits;
845203627bbSMiklos Szeredi 
8461fb69e78SMiklos Szeredi 	stat->dev = inode->i_sb->s_dev;
8471fb69e78SMiklos Szeredi 	stat->ino = attr->ino;
8481fb69e78SMiklos Szeredi 	stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
8491fb69e78SMiklos Szeredi 	stat->nlink = attr->nlink;
850499dcf20SEric W. Biederman 	stat->uid = make_kuid(&init_user_ns, attr->uid);
851499dcf20SEric W. Biederman 	stat->gid = make_kgid(&init_user_ns, attr->gid);
8521fb69e78SMiklos Szeredi 	stat->rdev = inode->i_rdev;
8531fb69e78SMiklos Szeredi 	stat->atime.tv_sec = attr->atime;
8541fb69e78SMiklos Szeredi 	stat->atime.tv_nsec = attr->atimensec;
8551fb69e78SMiklos Szeredi 	stat->mtime.tv_sec = attr->mtime;
8561fb69e78SMiklos Szeredi 	stat->mtime.tv_nsec = attr->mtimensec;
8571fb69e78SMiklos Szeredi 	stat->ctime.tv_sec = attr->ctime;
8581fb69e78SMiklos Szeredi 	stat->ctime.tv_nsec = attr->ctimensec;
8591fb69e78SMiklos Szeredi 	stat->size = attr->size;
8601fb69e78SMiklos Szeredi 	stat->blocks = attr->blocks;
861203627bbSMiklos Szeredi 
862203627bbSMiklos Szeredi 	if (attr->blksize != 0)
863203627bbSMiklos Szeredi 		blkbits = ilog2(attr->blksize);
864203627bbSMiklos Szeredi 	else
865203627bbSMiklos Szeredi 		blkbits = inode->i_sb->s_blocksize_bits;
866203627bbSMiklos Szeredi 
867203627bbSMiklos Szeredi 	stat->blksize = 1 << blkbits;
8681fb69e78SMiklos Szeredi }
8691fb69e78SMiklos Szeredi 
870c79e322fSMiklos Szeredi static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
871c79e322fSMiklos Szeredi 			   struct file *file)
872e5e5558eSMiklos Szeredi {
873e5e5558eSMiklos Szeredi 	int err;
874c79e322fSMiklos Szeredi 	struct fuse_getattr_in inarg;
875c79e322fSMiklos Szeredi 	struct fuse_attr_out outarg;
876e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
8771fb69e78SMiklos Szeredi 	struct fuse_req *req;
8781fb69e78SMiklos Szeredi 	u64 attr_version;
8791fb69e78SMiklos Szeredi 
880b111c8c0SMaxim Patlasov 	req = fuse_get_req_nopages(fc);
881ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
882ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
883e5e5558eSMiklos Szeredi 
8847dca9fd3SMiklos Szeredi 	attr_version = fuse_get_attr_version(fc);
8851fb69e78SMiklos Szeredi 
886c79e322fSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
8870e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
888c79e322fSMiklos Szeredi 	/* Directories have separate file-handle space */
889c79e322fSMiklos Szeredi 	if (file && S_ISREG(inode->i_mode)) {
890c79e322fSMiklos Szeredi 		struct fuse_file *ff = file->private_data;
891c79e322fSMiklos Szeredi 
892c79e322fSMiklos Szeredi 		inarg.getattr_flags |= FUSE_GETATTR_FH;
893c79e322fSMiklos Szeredi 		inarg.fh = ff->fh;
894c79e322fSMiklos Szeredi 	}
895e5e5558eSMiklos Szeredi 	req->in.h.opcode = FUSE_GETATTR;
896e5e5558eSMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
897c79e322fSMiklos Szeredi 	req->in.numargs = 1;
898c79e322fSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
899c79e322fSMiklos Szeredi 	req->in.args[0].value = &inarg;
900e5e5558eSMiklos Szeredi 	req->out.numargs = 1;
9010e9663eeSMiklos Szeredi 	if (fc->minor < 9)
9020e9663eeSMiklos Szeredi 		req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
9030e9663eeSMiklos Szeredi 	else
904c79e322fSMiklos Szeredi 		req->out.args[0].size = sizeof(outarg);
905c79e322fSMiklos Szeredi 	req->out.args[0].value = &outarg;
906b93f858aSTejun Heo 	fuse_request_send(fc, req);
907e5e5558eSMiklos Szeredi 	err = req->out.h.error;
908e5e5558eSMiklos Szeredi 	fuse_put_request(fc, req);
909e5e5558eSMiklos Szeredi 	if (!err) {
910c79e322fSMiklos Szeredi 		if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
911e5e5558eSMiklos Szeredi 			make_bad_inode(inode);
912e5e5558eSMiklos Szeredi 			err = -EIO;
913e5e5558eSMiklos Szeredi 		} else {
914c79e322fSMiklos Szeredi 			fuse_change_attributes(inode, &outarg.attr,
915c79e322fSMiklos Szeredi 					       attr_timeout(&outarg),
9161fb69e78SMiklos Szeredi 					       attr_version);
9171fb69e78SMiklos Szeredi 			if (stat)
918c79e322fSMiklos Szeredi 				fuse_fillattr(inode, &outarg.attr, stat);
919e5e5558eSMiklos Szeredi 		}
920e5e5558eSMiklos Szeredi 	}
921e5e5558eSMiklos Szeredi 	return err;
922e5e5558eSMiklos Szeredi }
923e5e5558eSMiklos Szeredi 
924bcb4be80SMiklos Szeredi int fuse_update_attributes(struct inode *inode, struct kstat *stat,
925bcb4be80SMiklos Szeredi 			   struct file *file, bool *refreshed)
926bcb4be80SMiklos Szeredi {
927bcb4be80SMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
928bcb4be80SMiklos Szeredi 	int err;
929bcb4be80SMiklos Szeredi 	bool r;
930bcb4be80SMiklos Szeredi 
931bcb4be80SMiklos Szeredi 	if (fi->i_time < get_jiffies_64()) {
932bcb4be80SMiklos Szeredi 		r = true;
933bcb4be80SMiklos Szeredi 		err = fuse_do_getattr(inode, stat, file);
934bcb4be80SMiklos Szeredi 	} else {
935bcb4be80SMiklos Szeredi 		r = false;
936bcb4be80SMiklos Szeredi 		err = 0;
937bcb4be80SMiklos Szeredi 		if (stat) {
938bcb4be80SMiklos Szeredi 			generic_fillattr(inode, stat);
939bcb4be80SMiklos Szeredi 			stat->mode = fi->orig_i_mode;
94045c72cd7SPavel Shilovsky 			stat->ino = fi->orig_ino;
941bcb4be80SMiklos Szeredi 		}
942bcb4be80SMiklos Szeredi 	}
943bcb4be80SMiklos Szeredi 
944bcb4be80SMiklos Szeredi 	if (refreshed != NULL)
945bcb4be80SMiklos Szeredi 		*refreshed = r;
946bcb4be80SMiklos Szeredi 
947bcb4be80SMiklos Szeredi 	return err;
948bcb4be80SMiklos Szeredi }
949bcb4be80SMiklos Szeredi 
9503b463ae0SJohn Muir int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid,
951451d0f59SJohn Muir 			     u64 child_nodeid, struct qstr *name)
9523b463ae0SJohn Muir {
9533b463ae0SJohn Muir 	int err = -ENOTDIR;
9543b463ae0SJohn Muir 	struct inode *parent;
9553b463ae0SJohn Muir 	struct dentry *dir;
9563b463ae0SJohn Muir 	struct dentry *entry;
9573b463ae0SJohn Muir 
9583b463ae0SJohn Muir 	parent = ilookup5(sb, parent_nodeid, fuse_inode_eq, &parent_nodeid);
9593b463ae0SJohn Muir 	if (!parent)
9603b463ae0SJohn Muir 		return -ENOENT;
9613b463ae0SJohn Muir 
9623b463ae0SJohn Muir 	mutex_lock(&parent->i_mutex);
9633b463ae0SJohn Muir 	if (!S_ISDIR(parent->i_mode))
9643b463ae0SJohn Muir 		goto unlock;
9653b463ae0SJohn Muir 
9663b463ae0SJohn Muir 	err = -ENOENT;
9673b463ae0SJohn Muir 	dir = d_find_alias(parent);
9683b463ae0SJohn Muir 	if (!dir)
9693b463ae0SJohn Muir 		goto unlock;
9703b463ae0SJohn Muir 
9713b463ae0SJohn Muir 	entry = d_lookup(dir, name);
9723b463ae0SJohn Muir 	dput(dir);
9733b463ae0SJohn Muir 	if (!entry)
9743b463ae0SJohn Muir 		goto unlock;
9753b463ae0SJohn Muir 
9763b463ae0SJohn Muir 	fuse_invalidate_attr(parent);
9773b463ae0SJohn Muir 	fuse_invalidate_entry(entry);
978451d0f59SJohn Muir 
979451d0f59SJohn Muir 	if (child_nodeid != 0 && entry->d_inode) {
980451d0f59SJohn Muir 		mutex_lock(&entry->d_inode->i_mutex);
981451d0f59SJohn Muir 		if (get_node_id(entry->d_inode) != child_nodeid) {
982451d0f59SJohn Muir 			err = -ENOENT;
983451d0f59SJohn Muir 			goto badentry;
984451d0f59SJohn Muir 		}
985451d0f59SJohn Muir 		if (d_mountpoint(entry)) {
986451d0f59SJohn Muir 			err = -EBUSY;
987451d0f59SJohn Muir 			goto badentry;
988451d0f59SJohn Muir 		}
989451d0f59SJohn Muir 		if (S_ISDIR(entry->d_inode->i_mode)) {
990451d0f59SJohn Muir 			shrink_dcache_parent(entry);
991451d0f59SJohn Muir 			if (!simple_empty(entry)) {
992451d0f59SJohn Muir 				err = -ENOTEMPTY;
993451d0f59SJohn Muir 				goto badentry;
994451d0f59SJohn Muir 			}
995451d0f59SJohn Muir 			entry->d_inode->i_flags |= S_DEAD;
996451d0f59SJohn Muir 		}
997451d0f59SJohn Muir 		dont_mount(entry);
998451d0f59SJohn Muir 		clear_nlink(entry->d_inode);
9993b463ae0SJohn Muir 		err = 0;
1000451d0f59SJohn Muir  badentry:
1001451d0f59SJohn Muir 		mutex_unlock(&entry->d_inode->i_mutex);
1002451d0f59SJohn Muir 		if (!err)
1003451d0f59SJohn Muir 			d_delete(entry);
1004451d0f59SJohn Muir 	} else {
1005451d0f59SJohn Muir 		err = 0;
1006451d0f59SJohn Muir 	}
1007451d0f59SJohn Muir 	dput(entry);
10083b463ae0SJohn Muir 
10093b463ae0SJohn Muir  unlock:
10103b463ae0SJohn Muir 	mutex_unlock(&parent->i_mutex);
10113b463ae0SJohn Muir 	iput(parent);
10123b463ae0SJohn Muir 	return err;
10133b463ae0SJohn Muir }
10143b463ae0SJohn Muir 
101587729a55SMiklos Szeredi /*
101687729a55SMiklos Szeredi  * Calling into a user-controlled filesystem gives the filesystem
1017c2132c1bSAnatol Pomozov  * daemon ptrace-like capabilities over the current process.  This
101887729a55SMiklos Szeredi  * means, that the filesystem daemon is able to record the exact
101987729a55SMiklos Szeredi  * filesystem operations performed, and can also control the behavior
102087729a55SMiklos Szeredi  * of the requester process in otherwise impossible ways.  For example
102187729a55SMiklos Szeredi  * it can delay the operation for arbitrary length of time allowing
102287729a55SMiklos Szeredi  * DoS against the requester.
102387729a55SMiklos Szeredi  *
102487729a55SMiklos Szeredi  * For this reason only those processes can call into the filesystem,
102587729a55SMiklos Szeredi  * for which the owner of the mount has ptrace privilege.  This
102687729a55SMiklos Szeredi  * excludes processes started by other users, suid or sgid processes.
102787729a55SMiklos Szeredi  */
1028c2132c1bSAnatol Pomozov int fuse_allow_current_process(struct fuse_conn *fc)
102987729a55SMiklos Szeredi {
1030c69e8d9cSDavid Howells 	const struct cred *cred;
1031c69e8d9cSDavid Howells 
103287729a55SMiklos Szeredi 	if (fc->flags & FUSE_ALLOW_OTHER)
103387729a55SMiklos Szeredi 		return 1;
103487729a55SMiklos Szeredi 
1035c2132c1bSAnatol Pomozov 	cred = current_cred();
1036499dcf20SEric W. Biederman 	if (uid_eq(cred->euid, fc->user_id) &&
1037499dcf20SEric W. Biederman 	    uid_eq(cred->suid, fc->user_id) &&
1038499dcf20SEric W. Biederman 	    uid_eq(cred->uid,  fc->user_id) &&
1039499dcf20SEric W. Biederman 	    gid_eq(cred->egid, fc->group_id) &&
1040499dcf20SEric W. Biederman 	    gid_eq(cred->sgid, fc->group_id) &&
1041499dcf20SEric W. Biederman 	    gid_eq(cred->gid,  fc->group_id))
1042c2132c1bSAnatol Pomozov 		return 1;
104387729a55SMiklos Szeredi 
1044c2132c1bSAnatol Pomozov 	return 0;
104587729a55SMiklos Szeredi }
104687729a55SMiklos Szeredi 
104731d40d74SMiklos Szeredi static int fuse_access(struct inode *inode, int mask)
104831d40d74SMiklos Szeredi {
104931d40d74SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
105031d40d74SMiklos Szeredi 	struct fuse_req *req;
105131d40d74SMiklos Szeredi 	struct fuse_access_in inarg;
105231d40d74SMiklos Szeredi 	int err;
105331d40d74SMiklos Szeredi 
105431d40d74SMiklos Szeredi 	if (fc->no_access)
105531d40d74SMiklos Szeredi 		return 0;
105631d40d74SMiklos Szeredi 
1057b111c8c0SMaxim Patlasov 	req = fuse_get_req_nopages(fc);
1058ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1059ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
106031d40d74SMiklos Szeredi 
106131d40d74SMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
1062e6305c43SAl Viro 	inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC);
106331d40d74SMiklos Szeredi 	req->in.h.opcode = FUSE_ACCESS;
106431d40d74SMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
106531d40d74SMiklos Szeredi 	req->in.numargs = 1;
106631d40d74SMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
106731d40d74SMiklos Szeredi 	req->in.args[0].value = &inarg;
1068b93f858aSTejun Heo 	fuse_request_send(fc, req);
106931d40d74SMiklos Szeredi 	err = req->out.h.error;
107031d40d74SMiklos Szeredi 	fuse_put_request(fc, req);
107131d40d74SMiklos Szeredi 	if (err == -ENOSYS) {
107231d40d74SMiklos Szeredi 		fc->no_access = 1;
107331d40d74SMiklos Szeredi 		err = 0;
107431d40d74SMiklos Szeredi 	}
107531d40d74SMiklos Szeredi 	return err;
107631d40d74SMiklos Szeredi }
107731d40d74SMiklos Szeredi 
107810556cb2SAl Viro static int fuse_perm_getattr(struct inode *inode, int mask)
107919690ddbSMiklos Szeredi {
108010556cb2SAl Viro 	if (mask & MAY_NOT_BLOCK)
108119690ddbSMiklos Szeredi 		return -ECHILD;
108219690ddbSMiklos Szeredi 
108319690ddbSMiklos Szeredi 	return fuse_do_getattr(inode, NULL, NULL);
108419690ddbSMiklos Szeredi }
108519690ddbSMiklos Szeredi 
10866f9f1180SMiklos Szeredi /*
10876f9f1180SMiklos Szeredi  * Check permission.  The two basic access models of FUSE are:
10886f9f1180SMiklos Szeredi  *
10896f9f1180SMiklos Szeredi  * 1) Local access checking ('default_permissions' mount option) based
10906f9f1180SMiklos Szeredi  * on file mode.  This is the plain old disk filesystem permission
10916f9f1180SMiklos Szeredi  * modell.
10926f9f1180SMiklos Szeredi  *
10936f9f1180SMiklos Szeredi  * 2) "Remote" access checking, where server is responsible for
10946f9f1180SMiklos Szeredi  * checking permission in each inode operation.  An exception to this
10956f9f1180SMiklos Szeredi  * is if ->permission() was invoked from sys_access() in which case an
10966f9f1180SMiklos Szeredi  * access request is sent.  Execute permission is still checked
10976f9f1180SMiklos Szeredi  * locally based on file mode.
10986f9f1180SMiklos Szeredi  */
109910556cb2SAl Viro static int fuse_permission(struct inode *inode, int mask)
1100e5e5558eSMiklos Szeredi {
1101e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1102244f6385SMiklos Szeredi 	bool refreshed = false;
1103244f6385SMiklos Szeredi 	int err = 0;
1104e5e5558eSMiklos Szeredi 
1105c2132c1bSAnatol Pomozov 	if (!fuse_allow_current_process(fc))
1106e5e5558eSMiklos Szeredi 		return -EACCES;
1107244f6385SMiklos Szeredi 
1108244f6385SMiklos Szeredi 	/*
1109e8e96157SMiklos Szeredi 	 * If attributes are needed, refresh them before proceeding
1110244f6385SMiklos Szeredi 	 */
1111e8e96157SMiklos Szeredi 	if ((fc->flags & FUSE_DEFAULT_PERMISSIONS) ||
1112e8e96157SMiklos Szeredi 	    ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
111319690ddbSMiklos Szeredi 		struct fuse_inode *fi = get_fuse_inode(inode);
111419690ddbSMiklos Szeredi 
111519690ddbSMiklos Szeredi 		if (fi->i_time < get_jiffies_64()) {
111619690ddbSMiklos Szeredi 			refreshed = true;
111719690ddbSMiklos Szeredi 
111810556cb2SAl Viro 			err = fuse_perm_getattr(inode, mask);
1119244f6385SMiklos Szeredi 			if (err)
1120244f6385SMiklos Szeredi 				return err;
11211fb69e78SMiklos Szeredi 		}
112219690ddbSMiklos Szeredi 	}
1123244f6385SMiklos Szeredi 
1124244f6385SMiklos Szeredi 	if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
11252830ba7fSAl Viro 		err = generic_permission(inode, mask);
11261e9a4ed9SMiklos Szeredi 
11271e9a4ed9SMiklos Szeredi 		/* If permission is denied, try to refresh file
11281e9a4ed9SMiklos Szeredi 		   attributes.  This is also needed, because the root
11291e9a4ed9SMiklos Szeredi 		   node will at first have no permissions */
1130244f6385SMiklos Szeredi 		if (err == -EACCES && !refreshed) {
113110556cb2SAl Viro 			err = fuse_perm_getattr(inode, mask);
11321e9a4ed9SMiklos Szeredi 			if (!err)
11332830ba7fSAl Viro 				err = generic_permission(inode, mask);
11341e9a4ed9SMiklos Szeredi 		}
11351e9a4ed9SMiklos Szeredi 
11366f9f1180SMiklos Szeredi 		/* Note: the opposite of the above test does not
11376f9f1180SMiklos Szeredi 		   exist.  So if permissions are revoked this won't be
11386f9f1180SMiklos Szeredi 		   noticed immediately, only after the attribute
11396f9f1180SMiklos Szeredi 		   timeout has expired */
11409cfcac81SEric Paris 	} else if (mask & (MAY_ACCESS | MAY_CHDIR)) {
114110556cb2SAl Viro 		if (mask & MAY_NOT_BLOCK)
114219690ddbSMiklos Szeredi 			return -ECHILD;
114319690ddbSMiklos Szeredi 
1144e8e96157SMiklos Szeredi 		err = fuse_access(inode, mask);
1145e8e96157SMiklos Szeredi 	} else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
1146e8e96157SMiklos Szeredi 		if (!(inode->i_mode & S_IXUGO)) {
1147e8e96157SMiklos Szeredi 			if (refreshed)
1148e5e5558eSMiklos Szeredi 				return -EACCES;
114931d40d74SMiklos Szeredi 
115010556cb2SAl Viro 			err = fuse_perm_getattr(inode, mask);
1151e8e96157SMiklos Szeredi 			if (!err && !(inode->i_mode & S_IXUGO))
1152e8e96157SMiklos Szeredi 				return -EACCES;
1153e8e96157SMiklos Szeredi 		}
1154e5e5558eSMiklos Szeredi 	}
1155244f6385SMiklos Szeredi 	return err;
1156e5e5558eSMiklos Szeredi }
1157e5e5558eSMiklos Szeredi 
1158e5e5558eSMiklos Szeredi static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
11598d3af7f3SAl Viro 			 struct dir_context *ctx)
1160e5e5558eSMiklos Szeredi {
1161e5e5558eSMiklos Szeredi 	while (nbytes >= FUSE_NAME_OFFSET) {
1162e5e5558eSMiklos Szeredi 		struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
1163e5e5558eSMiklos Szeredi 		size_t reclen = FUSE_DIRENT_SIZE(dirent);
1164e5e5558eSMiklos Szeredi 		if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
1165e5e5558eSMiklos Szeredi 			return -EIO;
1166e5e5558eSMiklos Szeredi 		if (reclen > nbytes)
1167e5e5558eSMiklos Szeredi 			break;
1168e5e5558eSMiklos Szeredi 
11698d3af7f3SAl Viro 		if (!dir_emit(ctx, dirent->name, dirent->namelen,
11708d3af7f3SAl Viro 			       dirent->ino, dirent->type))
1171e5e5558eSMiklos Szeredi 			break;
1172e5e5558eSMiklos Szeredi 
1173e5e5558eSMiklos Szeredi 		buf += reclen;
1174e5e5558eSMiklos Szeredi 		nbytes -= reclen;
11758d3af7f3SAl Viro 		ctx->pos = dirent->off;
1176e5e5558eSMiklos Szeredi 	}
1177e5e5558eSMiklos Szeredi 
1178e5e5558eSMiklos Szeredi 	return 0;
1179e5e5558eSMiklos Szeredi }
1180e5e5558eSMiklos Szeredi 
11810b05b183SAnand V. Avati static int fuse_direntplus_link(struct file *file,
11820b05b183SAnand V. Avati 				struct fuse_direntplus *direntplus,
11830b05b183SAnand V. Avati 				u64 attr_version)
11840b05b183SAnand V. Avati {
11850b05b183SAnand V. Avati 	int err;
11860b05b183SAnand V. Avati 	struct fuse_entry_out *o = &direntplus->entry_out;
11870b05b183SAnand V. Avati 	struct fuse_dirent *dirent = &direntplus->dirent;
11880b05b183SAnand V. Avati 	struct dentry *parent = file->f_path.dentry;
11890b05b183SAnand V. Avati 	struct qstr name = QSTR_INIT(dirent->name, dirent->namelen);
11900b05b183SAnand V. Avati 	struct dentry *dentry;
11910b05b183SAnand V. Avati 	struct dentry *alias;
11920b05b183SAnand V. Avati 	struct inode *dir = parent->d_inode;
11930b05b183SAnand V. Avati 	struct fuse_conn *fc;
11940b05b183SAnand V. Avati 	struct inode *inode;
11950b05b183SAnand V. Avati 
11960b05b183SAnand V. Avati 	if (!o->nodeid) {
11970b05b183SAnand V. Avati 		/*
11980b05b183SAnand V. Avati 		 * Unlike in the case of fuse_lookup, zero nodeid does not mean
11990b05b183SAnand V. Avati 		 * ENOENT. Instead, it only means the userspace filesystem did
12000b05b183SAnand V. Avati 		 * not want to return attributes/handle for this entry.
12010b05b183SAnand V. Avati 		 *
12020b05b183SAnand V. Avati 		 * So do nothing.
12030b05b183SAnand V. Avati 		 */
12040b05b183SAnand V. Avati 		return 0;
12050b05b183SAnand V. Avati 	}
12060b05b183SAnand V. Avati 
12070b05b183SAnand V. Avati 	if (name.name[0] == '.') {
12080b05b183SAnand V. Avati 		/*
12090b05b183SAnand V. Avati 		 * We could potentially refresh the attributes of the directory
12100b05b183SAnand V. Avati 		 * and its parent?
12110b05b183SAnand V. Avati 		 */
12120b05b183SAnand V. Avati 		if (name.len == 1)
12130b05b183SAnand V. Avati 			return 0;
12140b05b183SAnand V. Avati 		if (name.name[1] == '.' && name.len == 2)
12150b05b183SAnand V. Avati 			return 0;
12160b05b183SAnand V. Avati 	}
1217a28ef45cSMiklos Szeredi 
1218a28ef45cSMiklos Szeredi 	if (invalid_nodeid(o->nodeid))
1219a28ef45cSMiklos Szeredi 		return -EIO;
1220a28ef45cSMiklos Szeredi 	if (!fuse_valid_type(o->attr.mode))
1221a28ef45cSMiklos Szeredi 		return -EIO;
1222a28ef45cSMiklos Szeredi 
12230b05b183SAnand V. Avati 	fc = get_fuse_conn(dir);
12240b05b183SAnand V. Avati 
12250b05b183SAnand V. Avati 	name.hash = full_name_hash(name.name, name.len);
12260b05b183SAnand V. Avati 	dentry = d_lookup(parent, &name);
122753ce9a33SNiels de Vos 	if (dentry) {
12280b05b183SAnand V. Avati 		inode = dentry->d_inode;
122953ce9a33SNiels de Vos 		if (!inode) {
123053ce9a33SNiels de Vos 			d_drop(dentry);
1231a28ef45cSMiklos Szeredi 		} else if (get_node_id(inode) != o->nodeid ||
1232a28ef45cSMiklos Szeredi 			   ((o->attr.mode ^ inode->i_mode) & S_IFMT)) {
123353ce9a33SNiels de Vos 			err = d_invalidate(dentry);
123453ce9a33SNiels de Vos 			if (err)
123553ce9a33SNiels de Vos 				goto out;
1236a28ef45cSMiklos Szeredi 		} else if (is_bad_inode(inode)) {
1237a28ef45cSMiklos Szeredi 			err = -EIO;
1238a28ef45cSMiklos Szeredi 			goto out;
123953ce9a33SNiels de Vos 		} else {
12400b05b183SAnand V. Avati 			struct fuse_inode *fi;
12410b05b183SAnand V. Avati 			fi = get_fuse_inode(inode);
12420b05b183SAnand V. Avati 			spin_lock(&fc->lock);
12430b05b183SAnand V. Avati 			fi->nlookup++;
12440b05b183SAnand V. Avati 			spin_unlock(&fc->lock);
12450b05b183SAnand V. Avati 
1246fa2b7213SMiklos Szeredi 			fuse_change_attributes(inode, &o->attr,
1247fa2b7213SMiklos Szeredi 					       entry_attr_timeout(o),
1248fa2b7213SMiklos Szeredi 					       attr_version);
1249fa2b7213SMiklos Szeredi 
12500b05b183SAnand V. Avati 			/*
12510b05b183SAnand V. Avati 			 * The other branch to 'found' comes via fuse_iget()
12520b05b183SAnand V. Avati 			 * which bumps nlookup inside
12530b05b183SAnand V. Avati 			 */
12540b05b183SAnand V. Avati 			goto found;
12550b05b183SAnand V. Avati 		}
12560b05b183SAnand V. Avati 		dput(dentry);
12570b05b183SAnand V. Avati 	}
12580b05b183SAnand V. Avati 
12590b05b183SAnand V. Avati 	dentry = d_alloc(parent, &name);
12600b05b183SAnand V. Avati 	err = -ENOMEM;
12610b05b183SAnand V. Avati 	if (!dentry)
12620b05b183SAnand V. Avati 		goto out;
12630b05b183SAnand V. Avati 
12640b05b183SAnand V. Avati 	inode = fuse_iget(dir->i_sb, o->nodeid, o->generation,
12650b05b183SAnand V. Avati 			  &o->attr, entry_attr_timeout(o), attr_version);
12660b05b183SAnand V. Avati 	if (!inode)
12670b05b183SAnand V. Avati 		goto out;
12680b05b183SAnand V. Avati 
1269*5835f339SMiklos Szeredi 	alias = fuse_materialise_dentry(dentry, inode);
12700b05b183SAnand V. Avati 	err = PTR_ERR(alias);
1271*5835f339SMiklos Szeredi 	if (IS_ERR(alias))
12720b05b183SAnand V. Avati 		goto out;
12732914941eSMiklos Szeredi 
12740b05b183SAnand V. Avati 	if (alias) {
12750b05b183SAnand V. Avati 		dput(dentry);
12760b05b183SAnand V. Avati 		dentry = alias;
12770b05b183SAnand V. Avati 	}
12780b05b183SAnand V. Avati 
12790b05b183SAnand V. Avati found:
12800b05b183SAnand V. Avati 	fuse_change_entry_timeout(dentry, o);
12810b05b183SAnand V. Avati 
12820b05b183SAnand V. Avati 	err = 0;
12830b05b183SAnand V. Avati out:
12840b05b183SAnand V. Avati 	dput(dentry);
12850b05b183SAnand V. Avati 	return err;
12860b05b183SAnand V. Avati }
12870b05b183SAnand V. Avati 
12880b05b183SAnand V. Avati static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file,
12898d3af7f3SAl Viro 			     struct dir_context *ctx, u64 attr_version)
12900b05b183SAnand V. Avati {
12910b05b183SAnand V. Avati 	struct fuse_direntplus *direntplus;
12920b05b183SAnand V. Avati 	struct fuse_dirent *dirent;
12930b05b183SAnand V. Avati 	size_t reclen;
12940b05b183SAnand V. Avati 	int over = 0;
12950b05b183SAnand V. Avati 	int ret;
12960b05b183SAnand V. Avati 
12970b05b183SAnand V. Avati 	while (nbytes >= FUSE_NAME_OFFSET_DIRENTPLUS) {
12980b05b183SAnand V. Avati 		direntplus = (struct fuse_direntplus *) buf;
12990b05b183SAnand V. Avati 		dirent = &direntplus->dirent;
13000b05b183SAnand V. Avati 		reclen = FUSE_DIRENTPLUS_SIZE(direntplus);
13010b05b183SAnand V. Avati 
13020b05b183SAnand V. Avati 		if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
13030b05b183SAnand V. Avati 			return -EIO;
13040b05b183SAnand V. Avati 		if (reclen > nbytes)
13050b05b183SAnand V. Avati 			break;
13060b05b183SAnand V. Avati 
13070b05b183SAnand V. Avati 		if (!over) {
13080b05b183SAnand V. Avati 			/* We fill entries into dstbuf only as much as
13090b05b183SAnand V. Avati 			   it can hold. But we still continue iterating
13100b05b183SAnand V. Avati 			   over remaining entries to link them. If not,
13110b05b183SAnand V. Avati 			   we need to send a FORGET for each of those
13120b05b183SAnand V. Avati 			   which we did not link.
13130b05b183SAnand V. Avati 			*/
13148d3af7f3SAl Viro 			over = !dir_emit(ctx, dirent->name, dirent->namelen,
13158d3af7f3SAl Viro 				       dirent->ino, dirent->type);
13168d3af7f3SAl Viro 			ctx->pos = dirent->off;
13170b05b183SAnand V. Avati 		}
13180b05b183SAnand V. Avati 
13190b05b183SAnand V. Avati 		buf += reclen;
13200b05b183SAnand V. Avati 		nbytes -= reclen;
13210b05b183SAnand V. Avati 
13220b05b183SAnand V. Avati 		ret = fuse_direntplus_link(file, direntplus, attr_version);
13230b05b183SAnand V. Avati 		if (ret)
13240b05b183SAnand V. Avati 			fuse_force_forget(file, direntplus->entry_out.nodeid);
13250b05b183SAnand V. Avati 	}
13260b05b183SAnand V. Avati 
13270b05b183SAnand V. Avati 	return 0;
13280b05b183SAnand V. Avati }
13290b05b183SAnand V. Avati 
13308d3af7f3SAl Viro static int fuse_readdir(struct file *file, struct dir_context *ctx)
1331e5e5558eSMiklos Szeredi {
13324582a4abSFeng Shuo 	int plus, err;
133304730fefSMiklos Szeredi 	size_t nbytes;
133404730fefSMiklos Szeredi 	struct page *page;
1335496ad9aaSAl Viro 	struct inode *inode = file_inode(file);
133604730fefSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1337248d86e8SMiklos Szeredi 	struct fuse_req *req;
13380b05b183SAnand V. Avati 	u64 attr_version = 0;
1339248d86e8SMiklos Szeredi 
1340248d86e8SMiklos Szeredi 	if (is_bad_inode(inode))
1341248d86e8SMiklos Szeredi 		return -EIO;
1342248d86e8SMiklos Szeredi 
1343b111c8c0SMaxim Patlasov 	req = fuse_get_req(fc, 1);
1344ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1345ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
1346e5e5558eSMiklos Szeredi 
134704730fefSMiklos Szeredi 	page = alloc_page(GFP_KERNEL);
134804730fefSMiklos Szeredi 	if (!page) {
134904730fefSMiklos Szeredi 		fuse_put_request(fc, req);
1350e5e5558eSMiklos Szeredi 		return -ENOMEM;
135104730fefSMiklos Szeredi 	}
13524582a4abSFeng Shuo 
13538d3af7f3SAl Viro 	plus = fuse_use_readdirplus(inode, ctx);
1354f4975c67SMiklos Szeredi 	req->out.argpages = 1;
135504730fefSMiklos Szeredi 	req->num_pages = 1;
135604730fefSMiklos Szeredi 	req->pages[0] = page;
135785f40aecSMaxim Patlasov 	req->page_descs[0].length = PAGE_SIZE;
13584582a4abSFeng Shuo 	if (plus) {
13590b05b183SAnand V. Avati 		attr_version = fuse_get_attr_version(fc);
13608d3af7f3SAl Viro 		fuse_read_fill(req, file, ctx->pos, PAGE_SIZE,
13610b05b183SAnand V. Avati 			       FUSE_READDIRPLUS);
13620b05b183SAnand V. Avati 	} else {
13638d3af7f3SAl Viro 		fuse_read_fill(req, file, ctx->pos, PAGE_SIZE,
13640b05b183SAnand V. Avati 			       FUSE_READDIR);
13650b05b183SAnand V. Avati 	}
1366b93f858aSTejun Heo 	fuse_request_send(fc, req);
1367361b1eb5SMiklos Szeredi 	nbytes = req->out.args[0].size;
136804730fefSMiklos Szeredi 	err = req->out.h.error;
136904730fefSMiklos Szeredi 	fuse_put_request(fc, req);
13700b05b183SAnand V. Avati 	if (!err) {
13714582a4abSFeng Shuo 		if (plus) {
13720b05b183SAnand V. Avati 			err = parse_dirplusfile(page_address(page), nbytes,
13738d3af7f3SAl Viro 						file, ctx,
13740b05b183SAnand V. Avati 						attr_version);
13750b05b183SAnand V. Avati 		} else {
13760b05b183SAnand V. Avati 			err = parse_dirfile(page_address(page), nbytes, file,
13778d3af7f3SAl Viro 					    ctx);
13780b05b183SAnand V. Avati 		}
13790b05b183SAnand V. Avati 	}
1380e5e5558eSMiklos Szeredi 
138104730fefSMiklos Szeredi 	__free_page(page);
1382b36c31baSMiklos Szeredi 	fuse_invalidate_attr(inode); /* atime changed */
138304730fefSMiklos Szeredi 	return err;
1384e5e5558eSMiklos Szeredi }
1385e5e5558eSMiklos Szeredi 
1386e5e5558eSMiklos Szeredi static char *read_link(struct dentry *dentry)
1387e5e5558eSMiklos Szeredi {
1388e5e5558eSMiklos Szeredi 	struct inode *inode = dentry->d_inode;
1389e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1390b111c8c0SMaxim Patlasov 	struct fuse_req *req = fuse_get_req_nopages(fc);
1391e5e5558eSMiklos Szeredi 	char *link;
1392e5e5558eSMiklos Szeredi 
1393ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1394e231c2eeSDavid Howells 		return ERR_CAST(req);
1395e5e5558eSMiklos Szeredi 
1396e5e5558eSMiklos Szeredi 	link = (char *) __get_free_page(GFP_KERNEL);
1397e5e5558eSMiklos Szeredi 	if (!link) {
1398e5e5558eSMiklos Szeredi 		link = ERR_PTR(-ENOMEM);
1399e5e5558eSMiklos Szeredi 		goto out;
1400e5e5558eSMiklos Szeredi 	}
1401e5e5558eSMiklos Szeredi 	req->in.h.opcode = FUSE_READLINK;
1402e5e5558eSMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
1403e5e5558eSMiklos Szeredi 	req->out.argvar = 1;
1404e5e5558eSMiklos Szeredi 	req->out.numargs = 1;
1405e5e5558eSMiklos Szeredi 	req->out.args[0].size = PAGE_SIZE - 1;
1406e5e5558eSMiklos Szeredi 	req->out.args[0].value = link;
1407b93f858aSTejun Heo 	fuse_request_send(fc, req);
1408e5e5558eSMiklos Szeredi 	if (req->out.h.error) {
1409e5e5558eSMiklos Szeredi 		free_page((unsigned long) link);
1410e5e5558eSMiklos Szeredi 		link = ERR_PTR(req->out.h.error);
1411e5e5558eSMiklos Szeredi 	} else
1412e5e5558eSMiklos Szeredi 		link[req->out.args[0].size] = '\0';
1413e5e5558eSMiklos Szeredi  out:
1414e5e5558eSMiklos Szeredi 	fuse_put_request(fc, req);
1415b36c31baSMiklos Szeredi 	fuse_invalidate_attr(inode); /* atime changed */
1416e5e5558eSMiklos Szeredi 	return link;
1417e5e5558eSMiklos Szeredi }
1418e5e5558eSMiklos Szeredi 
1419e5e5558eSMiklos Szeredi static void free_link(char *link)
1420e5e5558eSMiklos Szeredi {
1421e5e5558eSMiklos Szeredi 	if (!IS_ERR(link))
1422e5e5558eSMiklos Szeredi 		free_page((unsigned long) link);
1423e5e5558eSMiklos Szeredi }
1424e5e5558eSMiklos Szeredi 
1425e5e5558eSMiklos Szeredi static void *fuse_follow_link(struct dentry *dentry, struct nameidata *nd)
1426e5e5558eSMiklos Szeredi {
1427e5e5558eSMiklos Szeredi 	nd_set_link(nd, read_link(dentry));
1428e5e5558eSMiklos Szeredi 	return NULL;
1429e5e5558eSMiklos Szeredi }
1430e5e5558eSMiklos Szeredi 
1431e5e5558eSMiklos Szeredi static void fuse_put_link(struct dentry *dentry, struct nameidata *nd, void *c)
1432e5e5558eSMiklos Szeredi {
1433e5e5558eSMiklos Szeredi 	free_link(nd_get_link(nd));
1434e5e5558eSMiklos Szeredi }
1435e5e5558eSMiklos Szeredi 
1436e5e5558eSMiklos Szeredi static int fuse_dir_open(struct inode *inode, struct file *file)
1437e5e5558eSMiklos Szeredi {
143891fe96b4SMiklos Szeredi 	return fuse_open_common(inode, file, true);
1439e5e5558eSMiklos Szeredi }
1440e5e5558eSMiklos Szeredi 
1441e5e5558eSMiklos Szeredi static int fuse_dir_release(struct inode *inode, struct file *file)
1442e5e5558eSMiklos Szeredi {
14438b0797a4SMiklos Szeredi 	fuse_release_common(file, FUSE_RELEASEDIR);
14448b0797a4SMiklos Szeredi 
14458b0797a4SMiklos Szeredi 	return 0;
1446e5e5558eSMiklos Szeredi }
1447e5e5558eSMiklos Szeredi 
144802c24a82SJosef Bacik static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end,
144902c24a82SJosef Bacik 			  int datasync)
145082547981SMiklos Szeredi {
145102c24a82SJosef Bacik 	return fuse_fsync_common(file, start, end, datasync, 1);
145282547981SMiklos Szeredi }
145382547981SMiklos Szeredi 
1454b18da0c5SMiklos Szeredi static long fuse_dir_ioctl(struct file *file, unsigned int cmd,
1455b18da0c5SMiklos Szeredi 			    unsigned long arg)
1456b18da0c5SMiklos Szeredi {
1457b18da0c5SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1458b18da0c5SMiklos Szeredi 
1459b18da0c5SMiklos Szeredi 	/* FUSE_IOCTL_DIR only supported for API version >= 7.18 */
1460b18da0c5SMiklos Szeredi 	if (fc->minor < 18)
1461b18da0c5SMiklos Szeredi 		return -ENOTTY;
1462b18da0c5SMiklos Szeredi 
1463b18da0c5SMiklos Szeredi 	return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR);
1464b18da0c5SMiklos Szeredi }
1465b18da0c5SMiklos Szeredi 
1466b18da0c5SMiklos Szeredi static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd,
1467b18da0c5SMiklos Szeredi 				   unsigned long arg)
1468b18da0c5SMiklos Szeredi {
1469b18da0c5SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1470b18da0c5SMiklos Szeredi 
1471b18da0c5SMiklos Szeredi 	if (fc->minor < 18)
1472b18da0c5SMiklos Szeredi 		return -ENOTTY;
1473b18da0c5SMiklos Szeredi 
1474b18da0c5SMiklos Szeredi 	return fuse_ioctl_common(file, cmd, arg,
1475b18da0c5SMiklos Szeredi 				 FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR);
1476b18da0c5SMiklos Szeredi }
1477b18da0c5SMiklos Szeredi 
147817637cbaSMiklos Szeredi static bool update_mtime(unsigned ivalid)
147917637cbaSMiklos Szeredi {
148017637cbaSMiklos Szeredi 	/* Always update if mtime is explicitly set  */
148117637cbaSMiklos Szeredi 	if (ivalid & ATTR_MTIME_SET)
148217637cbaSMiklos Szeredi 		return true;
148317637cbaSMiklos Szeredi 
148417637cbaSMiklos Szeredi 	/* If it's an open(O_TRUNC) or an ftruncate(), don't update */
148517637cbaSMiklos Szeredi 	if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
148617637cbaSMiklos Szeredi 		return false;
148717637cbaSMiklos Szeredi 
148817637cbaSMiklos Szeredi 	/* In all other cases update */
148917637cbaSMiklos Szeredi 	return true;
149017637cbaSMiklos Szeredi }
149117637cbaSMiklos Szeredi 
1492befc649cSMiklos Szeredi static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg)
14939e6268dbSMiklos Szeredi {
14949e6268dbSMiklos Szeredi 	unsigned ivalid = iattr->ia_valid;
14959e6268dbSMiklos Szeredi 
14969e6268dbSMiklos Szeredi 	if (ivalid & ATTR_MODE)
1497befc649cSMiklos Szeredi 		arg->valid |= FATTR_MODE,   arg->mode = iattr->ia_mode;
14989e6268dbSMiklos Szeredi 	if (ivalid & ATTR_UID)
1499499dcf20SEric W. Biederman 		arg->valid |= FATTR_UID,    arg->uid = from_kuid(&init_user_ns, iattr->ia_uid);
15009e6268dbSMiklos Szeredi 	if (ivalid & ATTR_GID)
1501499dcf20SEric W. Biederman 		arg->valid |= FATTR_GID,    arg->gid = from_kgid(&init_user_ns, iattr->ia_gid);
15029e6268dbSMiklos Szeredi 	if (ivalid & ATTR_SIZE)
1503befc649cSMiklos Szeredi 		arg->valid |= FATTR_SIZE,   arg->size = iattr->ia_size;
150417637cbaSMiklos Szeredi 	if (ivalid & ATTR_ATIME) {
150517637cbaSMiklos Szeredi 		arg->valid |= FATTR_ATIME;
1506befc649cSMiklos Szeredi 		arg->atime = iattr->ia_atime.tv_sec;
150717637cbaSMiklos Szeredi 		arg->atimensec = iattr->ia_atime.tv_nsec;
150817637cbaSMiklos Szeredi 		if (!(ivalid & ATTR_ATIME_SET))
150917637cbaSMiklos Szeredi 			arg->valid |= FATTR_ATIME_NOW;
151017637cbaSMiklos Szeredi 	}
151117637cbaSMiklos Szeredi 	if ((ivalid & ATTR_MTIME) && update_mtime(ivalid)) {
151217637cbaSMiklos Szeredi 		arg->valid |= FATTR_MTIME;
1513befc649cSMiklos Szeredi 		arg->mtime = iattr->ia_mtime.tv_sec;
151417637cbaSMiklos Szeredi 		arg->mtimensec = iattr->ia_mtime.tv_nsec;
151517637cbaSMiklos Szeredi 		if (!(ivalid & ATTR_MTIME_SET))
151617637cbaSMiklos Szeredi 			arg->valid |= FATTR_MTIME_NOW;
15179e6268dbSMiklos Szeredi 	}
15189e6268dbSMiklos Szeredi }
15199e6268dbSMiklos Szeredi 
15206f9f1180SMiklos Szeredi /*
15213be5a52bSMiklos Szeredi  * Prevent concurrent writepages on inode
15223be5a52bSMiklos Szeredi  *
15233be5a52bSMiklos Szeredi  * This is done by adding a negative bias to the inode write counter
15243be5a52bSMiklos Szeredi  * and waiting for all pending writes to finish.
15253be5a52bSMiklos Szeredi  */
15263be5a52bSMiklos Szeredi void fuse_set_nowrite(struct inode *inode)
15273be5a52bSMiklos Szeredi {
15283be5a52bSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
15293be5a52bSMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
15303be5a52bSMiklos Szeredi 
15313be5a52bSMiklos Szeredi 	BUG_ON(!mutex_is_locked(&inode->i_mutex));
15323be5a52bSMiklos Szeredi 
15333be5a52bSMiklos Szeredi 	spin_lock(&fc->lock);
15343be5a52bSMiklos Szeredi 	BUG_ON(fi->writectr < 0);
15353be5a52bSMiklos Szeredi 	fi->writectr += FUSE_NOWRITE;
15363be5a52bSMiklos Szeredi 	spin_unlock(&fc->lock);
15373be5a52bSMiklos Szeredi 	wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE);
15383be5a52bSMiklos Szeredi }
15393be5a52bSMiklos Szeredi 
15403be5a52bSMiklos Szeredi /*
15413be5a52bSMiklos Szeredi  * Allow writepages on inode
15423be5a52bSMiklos Szeredi  *
15433be5a52bSMiklos Szeredi  * Remove the bias from the writecounter and send any queued
15443be5a52bSMiklos Szeredi  * writepages.
15453be5a52bSMiklos Szeredi  */
15463be5a52bSMiklos Szeredi static void __fuse_release_nowrite(struct inode *inode)
15473be5a52bSMiklos Szeredi {
15483be5a52bSMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
15493be5a52bSMiklos Szeredi 
15503be5a52bSMiklos Szeredi 	BUG_ON(fi->writectr != FUSE_NOWRITE);
15513be5a52bSMiklos Szeredi 	fi->writectr = 0;
15523be5a52bSMiklos Szeredi 	fuse_flush_writepages(inode);
15533be5a52bSMiklos Szeredi }
15543be5a52bSMiklos Szeredi 
15553be5a52bSMiklos Szeredi void fuse_release_nowrite(struct inode *inode)
15563be5a52bSMiklos Szeredi {
15573be5a52bSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
15583be5a52bSMiklos Szeredi 
15593be5a52bSMiklos Szeredi 	spin_lock(&fc->lock);
15603be5a52bSMiklos Szeredi 	__fuse_release_nowrite(inode);
15613be5a52bSMiklos Szeredi 	spin_unlock(&fc->lock);
15623be5a52bSMiklos Szeredi }
15633be5a52bSMiklos Szeredi 
15643be5a52bSMiklos Szeredi /*
15656f9f1180SMiklos Szeredi  * Set attributes, and at the same time refresh them.
15666f9f1180SMiklos Szeredi  *
15676f9f1180SMiklos Szeredi  * Truncation is slightly complicated, because the 'truncate' request
15686f9f1180SMiklos Szeredi  * may fail, in which case we don't want to touch the mapping.
15699ffbb916SMiklos Szeredi  * vmtruncate() doesn't allow for this case, so do the rlimit checking
15709ffbb916SMiklos Szeredi  * and the actual truncation by hand.
15716f9f1180SMiklos Szeredi  */
1572efb9fa9eSMaxim Patlasov int fuse_do_setattr(struct inode *inode, struct iattr *attr,
157349d4914fSMiklos Szeredi 		    struct file *file)
15749e6268dbSMiklos Szeredi {
15759e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
15769e6268dbSMiklos Szeredi 	struct fuse_req *req;
15779e6268dbSMiklos Szeredi 	struct fuse_setattr_in inarg;
15789e6268dbSMiklos Szeredi 	struct fuse_attr_out outarg;
15793be5a52bSMiklos Szeredi 	bool is_truncate = false;
15803be5a52bSMiklos Szeredi 	loff_t oldsize;
15819e6268dbSMiklos Szeredi 	int err;
15829e6268dbSMiklos Szeredi 
1583db78b877SChristoph Hellwig 	if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS))
1584db78b877SChristoph Hellwig 		attr->ia_valid |= ATTR_FORCE;
1585db78b877SChristoph Hellwig 
15861e9a4ed9SMiklos Szeredi 	err = inode_change_ok(inode, attr);
15871e9a4ed9SMiklos Szeredi 	if (err)
15881e9a4ed9SMiklos Szeredi 		return err;
15891e9a4ed9SMiklos Szeredi 
15908d56adddSMiklos Szeredi 	if (attr->ia_valid & ATTR_OPEN) {
15918d56adddSMiklos Szeredi 		if (fc->atomic_o_trunc)
15926ff958edSMiklos Szeredi 			return 0;
15938d56adddSMiklos Szeredi 		file = NULL;
15948d56adddSMiklos Szeredi 	}
15956ff958edSMiklos Szeredi 
15962c27c65eSChristoph Hellwig 	if (attr->ia_valid & ATTR_SIZE)
15973be5a52bSMiklos Szeredi 		is_truncate = true;
15989e6268dbSMiklos Szeredi 
1599b111c8c0SMaxim Patlasov 	req = fuse_get_req_nopages(fc);
1600ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1601ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
16029e6268dbSMiklos Szeredi 
16033be5a52bSMiklos Szeredi 	if (is_truncate)
16043be5a52bSMiklos Szeredi 		fuse_set_nowrite(inode);
16053be5a52bSMiklos Szeredi 
16069e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
16070e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
1608befc649cSMiklos Szeredi 	iattr_to_fattr(attr, &inarg);
160949d4914fSMiklos Szeredi 	if (file) {
161049d4914fSMiklos Szeredi 		struct fuse_file *ff = file->private_data;
161149d4914fSMiklos Szeredi 		inarg.valid |= FATTR_FH;
161249d4914fSMiklos Szeredi 		inarg.fh = ff->fh;
161349d4914fSMiklos Szeredi 	}
1614f3332114SMiklos Szeredi 	if (attr->ia_valid & ATTR_SIZE) {
1615f3332114SMiklos Szeredi 		/* For mandatory locking in truncate */
1616f3332114SMiklos Szeredi 		inarg.valid |= FATTR_LOCKOWNER;
1617f3332114SMiklos Szeredi 		inarg.lock_owner = fuse_lock_owner_id(fc, current->files);
1618f3332114SMiklos Szeredi 	}
16199e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_SETATTR;
16209e6268dbSMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
16219e6268dbSMiklos Szeredi 	req->in.numargs = 1;
16229e6268dbSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
16239e6268dbSMiklos Szeredi 	req->in.args[0].value = &inarg;
16249e6268dbSMiklos Szeredi 	req->out.numargs = 1;
16250e9663eeSMiklos Szeredi 	if (fc->minor < 9)
16260e9663eeSMiklos Szeredi 		req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
16270e9663eeSMiklos Szeredi 	else
16289e6268dbSMiklos Szeredi 		req->out.args[0].size = sizeof(outarg);
16299e6268dbSMiklos Szeredi 	req->out.args[0].value = &outarg;
1630b93f858aSTejun Heo 	fuse_request_send(fc, req);
16319e6268dbSMiklos Szeredi 	err = req->out.h.error;
16329e6268dbSMiklos Szeredi 	fuse_put_request(fc, req);
1633e00d2c2dSMiklos Szeredi 	if (err) {
1634e00d2c2dSMiklos Szeredi 		if (err == -EINTR)
1635e00d2c2dSMiklos Szeredi 			fuse_invalidate_attr(inode);
16363be5a52bSMiklos Szeredi 		goto error;
1637e00d2c2dSMiklos Szeredi 	}
1638e00d2c2dSMiklos Szeredi 
16399e6268dbSMiklos Szeredi 	if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
16409e6268dbSMiklos Szeredi 		make_bad_inode(inode);
16413be5a52bSMiklos Szeredi 		err = -EIO;
16423be5a52bSMiklos Szeredi 		goto error;
16439e6268dbSMiklos Szeredi 	}
16449e6268dbSMiklos Szeredi 
16453be5a52bSMiklos Szeredi 	spin_lock(&fc->lock);
16463be5a52bSMiklos Szeredi 	fuse_change_attributes_common(inode, &outarg.attr,
16473be5a52bSMiklos Szeredi 				      attr_timeout(&outarg));
16483be5a52bSMiklos Szeredi 	oldsize = inode->i_size;
16493be5a52bSMiklos Szeredi 	i_size_write(inode, outarg.attr.size);
16503be5a52bSMiklos Szeredi 
16513be5a52bSMiklos Szeredi 	if (is_truncate) {
16523be5a52bSMiklos Szeredi 		/* NOTE: this may release/reacquire fc->lock */
16533be5a52bSMiklos Szeredi 		__fuse_release_nowrite(inode);
16543be5a52bSMiklos Szeredi 	}
16553be5a52bSMiklos Szeredi 	spin_unlock(&fc->lock);
16563be5a52bSMiklos Szeredi 
16573be5a52bSMiklos Szeredi 	/*
16583be5a52bSMiklos Szeredi 	 * Only call invalidate_inode_pages2() after removing
16593be5a52bSMiklos Szeredi 	 * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock.
16603be5a52bSMiklos Szeredi 	 */
16613be5a52bSMiklos Szeredi 	if (S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
1662c08d3b0eSnpiggin@suse.de 		truncate_pagecache(inode, oldsize, outarg.attr.size);
16633be5a52bSMiklos Szeredi 		invalidate_inode_pages2(inode->i_mapping);
16643be5a52bSMiklos Szeredi 	}
16653be5a52bSMiklos Szeredi 
1666e00d2c2dSMiklos Szeredi 	return 0;
16673be5a52bSMiklos Szeredi 
16683be5a52bSMiklos Szeredi error:
16693be5a52bSMiklos Szeredi 	if (is_truncate)
16703be5a52bSMiklos Szeredi 		fuse_release_nowrite(inode);
16713be5a52bSMiklos Szeredi 
16723be5a52bSMiklos Szeredi 	return err;
16739e6268dbSMiklos Szeredi }
16749e6268dbSMiklos Szeredi 
167549d4914fSMiklos Szeredi static int fuse_setattr(struct dentry *entry, struct iattr *attr)
167649d4914fSMiklos Szeredi {
1677efb9fa9eSMaxim Patlasov 	struct inode *inode = entry->d_inode;
1678efb9fa9eSMaxim Patlasov 
1679efb9fa9eSMaxim Patlasov 	if (!fuse_allow_current_process(get_fuse_conn(inode)))
1680efb9fa9eSMaxim Patlasov 		return -EACCES;
1681efb9fa9eSMaxim Patlasov 
168249d4914fSMiklos Szeredi 	if (attr->ia_valid & ATTR_FILE)
1683efb9fa9eSMaxim Patlasov 		return fuse_do_setattr(inode, attr, attr->ia_file);
168449d4914fSMiklos Szeredi 	else
1685efb9fa9eSMaxim Patlasov 		return fuse_do_setattr(inode, attr, NULL);
168649d4914fSMiklos Szeredi }
168749d4914fSMiklos Szeredi 
1688e5e5558eSMiklos Szeredi static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
1689e5e5558eSMiklos Szeredi 			struct kstat *stat)
1690e5e5558eSMiklos Szeredi {
1691e5e5558eSMiklos Szeredi 	struct inode *inode = entry->d_inode;
1692244f6385SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1693244f6385SMiklos Szeredi 
1694c2132c1bSAnatol Pomozov 	if (!fuse_allow_current_process(fc))
1695244f6385SMiklos Szeredi 		return -EACCES;
1696244f6385SMiklos Szeredi 
1697bcb4be80SMiklos Szeredi 	return fuse_update_attributes(inode, stat, NULL, NULL);
1698e5e5558eSMiklos Szeredi }
1699e5e5558eSMiklos Szeredi 
170092a8780eSMiklos Szeredi static int fuse_setxattr(struct dentry *entry, const char *name,
170192a8780eSMiklos Szeredi 			 const void *value, size_t size, int flags)
170292a8780eSMiklos Szeredi {
170392a8780eSMiklos Szeredi 	struct inode *inode = entry->d_inode;
170492a8780eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
170592a8780eSMiklos Szeredi 	struct fuse_req *req;
170692a8780eSMiklos Szeredi 	struct fuse_setxattr_in inarg;
170792a8780eSMiklos Szeredi 	int err;
170892a8780eSMiklos Szeredi 
170992a8780eSMiklos Szeredi 	if (fc->no_setxattr)
171092a8780eSMiklos Szeredi 		return -EOPNOTSUPP;
171192a8780eSMiklos Szeredi 
1712b111c8c0SMaxim Patlasov 	req = fuse_get_req_nopages(fc);
1713ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1714ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
171592a8780eSMiklos Szeredi 
171692a8780eSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
171792a8780eSMiklos Szeredi 	inarg.size = size;
171892a8780eSMiklos Szeredi 	inarg.flags = flags;
171992a8780eSMiklos Szeredi 	req->in.h.opcode = FUSE_SETXATTR;
172092a8780eSMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
172192a8780eSMiklos Szeredi 	req->in.numargs = 3;
172292a8780eSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
172392a8780eSMiklos Szeredi 	req->in.args[0].value = &inarg;
172492a8780eSMiklos Szeredi 	req->in.args[1].size = strlen(name) + 1;
172592a8780eSMiklos Szeredi 	req->in.args[1].value = name;
172692a8780eSMiklos Szeredi 	req->in.args[2].size = size;
172792a8780eSMiklos Szeredi 	req->in.args[2].value = value;
1728b93f858aSTejun Heo 	fuse_request_send(fc, req);
172992a8780eSMiklos Szeredi 	err = req->out.h.error;
173092a8780eSMiklos Szeredi 	fuse_put_request(fc, req);
173192a8780eSMiklos Szeredi 	if (err == -ENOSYS) {
173292a8780eSMiklos Szeredi 		fc->no_setxattr = 1;
173392a8780eSMiklos Szeredi 		err = -EOPNOTSUPP;
173492a8780eSMiklos Szeredi 	}
173592a8780eSMiklos Szeredi 	return err;
173692a8780eSMiklos Szeredi }
173792a8780eSMiklos Szeredi 
173892a8780eSMiklos Szeredi static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
173992a8780eSMiklos Szeredi 			     void *value, size_t size)
174092a8780eSMiklos Szeredi {
174192a8780eSMiklos Szeredi 	struct inode *inode = entry->d_inode;
174292a8780eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
174392a8780eSMiklos Szeredi 	struct fuse_req *req;
174492a8780eSMiklos Szeredi 	struct fuse_getxattr_in inarg;
174592a8780eSMiklos Szeredi 	struct fuse_getxattr_out outarg;
174692a8780eSMiklos Szeredi 	ssize_t ret;
174792a8780eSMiklos Szeredi 
174892a8780eSMiklos Szeredi 	if (fc->no_getxattr)
174992a8780eSMiklos Szeredi 		return -EOPNOTSUPP;
175092a8780eSMiklos Szeredi 
1751b111c8c0SMaxim Patlasov 	req = fuse_get_req_nopages(fc);
1752ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1753ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
175492a8780eSMiklos Szeredi 
175592a8780eSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
175692a8780eSMiklos Szeredi 	inarg.size = size;
175792a8780eSMiklos Szeredi 	req->in.h.opcode = FUSE_GETXATTR;
175892a8780eSMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
175992a8780eSMiklos Szeredi 	req->in.numargs = 2;
176092a8780eSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
176192a8780eSMiklos Szeredi 	req->in.args[0].value = &inarg;
176292a8780eSMiklos Szeredi 	req->in.args[1].size = strlen(name) + 1;
176392a8780eSMiklos Szeredi 	req->in.args[1].value = name;
176492a8780eSMiklos Szeredi 	/* This is really two different operations rolled into one */
176592a8780eSMiklos Szeredi 	req->out.numargs = 1;
176692a8780eSMiklos Szeredi 	if (size) {
176792a8780eSMiklos Szeredi 		req->out.argvar = 1;
176892a8780eSMiklos Szeredi 		req->out.args[0].size = size;
176992a8780eSMiklos Szeredi 		req->out.args[0].value = value;
177092a8780eSMiklos Szeredi 	} else {
177192a8780eSMiklos Szeredi 		req->out.args[0].size = sizeof(outarg);
177292a8780eSMiklos Szeredi 		req->out.args[0].value = &outarg;
177392a8780eSMiklos Szeredi 	}
1774b93f858aSTejun Heo 	fuse_request_send(fc, req);
177592a8780eSMiklos Szeredi 	ret = req->out.h.error;
177692a8780eSMiklos Szeredi 	if (!ret)
177792a8780eSMiklos Szeredi 		ret = size ? req->out.args[0].size : outarg.size;
177892a8780eSMiklos Szeredi 	else {
177992a8780eSMiklos Szeredi 		if (ret == -ENOSYS) {
178092a8780eSMiklos Szeredi 			fc->no_getxattr = 1;
178192a8780eSMiklos Szeredi 			ret = -EOPNOTSUPP;
178292a8780eSMiklos Szeredi 		}
178392a8780eSMiklos Szeredi 	}
178492a8780eSMiklos Szeredi 	fuse_put_request(fc, req);
178592a8780eSMiklos Szeredi 	return ret;
178692a8780eSMiklos Szeredi }
178792a8780eSMiklos Szeredi 
178892a8780eSMiklos Szeredi static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
178992a8780eSMiklos Szeredi {
179092a8780eSMiklos Szeredi 	struct inode *inode = entry->d_inode;
179192a8780eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
179292a8780eSMiklos Szeredi 	struct fuse_req *req;
179392a8780eSMiklos Szeredi 	struct fuse_getxattr_in inarg;
179492a8780eSMiklos Szeredi 	struct fuse_getxattr_out outarg;
179592a8780eSMiklos Szeredi 	ssize_t ret;
179692a8780eSMiklos Szeredi 
1797c2132c1bSAnatol Pomozov 	if (!fuse_allow_current_process(fc))
1798e57ac683SMiklos Szeredi 		return -EACCES;
1799e57ac683SMiklos Szeredi 
180092a8780eSMiklos Szeredi 	if (fc->no_listxattr)
180192a8780eSMiklos Szeredi 		return -EOPNOTSUPP;
180292a8780eSMiklos Szeredi 
1803b111c8c0SMaxim Patlasov 	req = fuse_get_req_nopages(fc);
1804ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1805ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
180692a8780eSMiklos Szeredi 
180792a8780eSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
180892a8780eSMiklos Szeredi 	inarg.size = size;
180992a8780eSMiklos Szeredi 	req->in.h.opcode = FUSE_LISTXATTR;
181092a8780eSMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
181192a8780eSMiklos Szeredi 	req->in.numargs = 1;
181292a8780eSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
181392a8780eSMiklos Szeredi 	req->in.args[0].value = &inarg;
181492a8780eSMiklos Szeredi 	/* This is really two different operations rolled into one */
181592a8780eSMiklos Szeredi 	req->out.numargs = 1;
181692a8780eSMiklos Szeredi 	if (size) {
181792a8780eSMiklos Szeredi 		req->out.argvar = 1;
181892a8780eSMiklos Szeredi 		req->out.args[0].size = size;
181992a8780eSMiklos Szeredi 		req->out.args[0].value = list;
182092a8780eSMiklos Szeredi 	} else {
182192a8780eSMiklos Szeredi 		req->out.args[0].size = sizeof(outarg);
182292a8780eSMiklos Szeredi 		req->out.args[0].value = &outarg;
182392a8780eSMiklos Szeredi 	}
1824b93f858aSTejun Heo 	fuse_request_send(fc, req);
182592a8780eSMiklos Szeredi 	ret = req->out.h.error;
182692a8780eSMiklos Szeredi 	if (!ret)
182792a8780eSMiklos Szeredi 		ret = size ? req->out.args[0].size : outarg.size;
182892a8780eSMiklos Szeredi 	else {
182992a8780eSMiklos Szeredi 		if (ret == -ENOSYS) {
183092a8780eSMiklos Szeredi 			fc->no_listxattr = 1;
183192a8780eSMiklos Szeredi 			ret = -EOPNOTSUPP;
183292a8780eSMiklos Szeredi 		}
183392a8780eSMiklos Szeredi 	}
183492a8780eSMiklos Szeredi 	fuse_put_request(fc, req);
183592a8780eSMiklos Szeredi 	return ret;
183692a8780eSMiklos Szeredi }
183792a8780eSMiklos Szeredi 
183892a8780eSMiklos Szeredi static int fuse_removexattr(struct dentry *entry, const char *name)
183992a8780eSMiklos Szeredi {
184092a8780eSMiklos Szeredi 	struct inode *inode = entry->d_inode;
184192a8780eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
184292a8780eSMiklos Szeredi 	struct fuse_req *req;
184392a8780eSMiklos Szeredi 	int err;
184492a8780eSMiklos Szeredi 
184592a8780eSMiklos Szeredi 	if (fc->no_removexattr)
184692a8780eSMiklos Szeredi 		return -EOPNOTSUPP;
184792a8780eSMiklos Szeredi 
1848b111c8c0SMaxim Patlasov 	req = fuse_get_req_nopages(fc);
1849ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1850ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
185192a8780eSMiklos Szeredi 
185292a8780eSMiklos Szeredi 	req->in.h.opcode = FUSE_REMOVEXATTR;
185392a8780eSMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
185492a8780eSMiklos Szeredi 	req->in.numargs = 1;
185592a8780eSMiklos Szeredi 	req->in.args[0].size = strlen(name) + 1;
185692a8780eSMiklos Szeredi 	req->in.args[0].value = name;
1857b93f858aSTejun Heo 	fuse_request_send(fc, req);
185892a8780eSMiklos Szeredi 	err = req->out.h.error;
185992a8780eSMiklos Szeredi 	fuse_put_request(fc, req);
186092a8780eSMiklos Szeredi 	if (err == -ENOSYS) {
186192a8780eSMiklos Szeredi 		fc->no_removexattr = 1;
186292a8780eSMiklos Szeredi 		err = -EOPNOTSUPP;
186392a8780eSMiklos Szeredi 	}
186492a8780eSMiklos Szeredi 	return err;
186592a8780eSMiklos Szeredi }
186692a8780eSMiklos Szeredi 
1867754661f1SArjan van de Ven static const struct inode_operations fuse_dir_inode_operations = {
1868e5e5558eSMiklos Szeredi 	.lookup		= fuse_lookup,
18699e6268dbSMiklos Szeredi 	.mkdir		= fuse_mkdir,
18709e6268dbSMiklos Szeredi 	.symlink	= fuse_symlink,
18719e6268dbSMiklos Szeredi 	.unlink		= fuse_unlink,
18729e6268dbSMiklos Szeredi 	.rmdir		= fuse_rmdir,
18739e6268dbSMiklos Szeredi 	.rename		= fuse_rename,
18749e6268dbSMiklos Szeredi 	.link		= fuse_link,
18759e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
18769e6268dbSMiklos Szeredi 	.create		= fuse_create,
1877c8ccbe03SMiklos Szeredi 	.atomic_open	= fuse_atomic_open,
18789e6268dbSMiklos Szeredi 	.mknod		= fuse_mknod,
1879e5e5558eSMiklos Szeredi 	.permission	= fuse_permission,
1880e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
188192a8780eSMiklos Szeredi 	.setxattr	= fuse_setxattr,
188292a8780eSMiklos Szeredi 	.getxattr	= fuse_getxattr,
188392a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
188492a8780eSMiklos Szeredi 	.removexattr	= fuse_removexattr,
1885e5e5558eSMiklos Szeredi };
1886e5e5558eSMiklos Szeredi 
18874b6f5d20SArjan van de Ven static const struct file_operations fuse_dir_operations = {
1888b6aeadedSMiklos Szeredi 	.llseek		= generic_file_llseek,
1889e5e5558eSMiklos Szeredi 	.read		= generic_read_dir,
18908d3af7f3SAl Viro 	.iterate	= fuse_readdir,
1891e5e5558eSMiklos Szeredi 	.open		= fuse_dir_open,
1892e5e5558eSMiklos Szeredi 	.release	= fuse_dir_release,
189382547981SMiklos Szeredi 	.fsync		= fuse_dir_fsync,
1894b18da0c5SMiklos Szeredi 	.unlocked_ioctl	= fuse_dir_ioctl,
1895b18da0c5SMiklos Szeredi 	.compat_ioctl	= fuse_dir_compat_ioctl,
1896e5e5558eSMiklos Szeredi };
1897e5e5558eSMiklos Szeredi 
1898754661f1SArjan van de Ven static const struct inode_operations fuse_common_inode_operations = {
18999e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
1900e5e5558eSMiklos Szeredi 	.permission	= fuse_permission,
1901e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
190292a8780eSMiklos Szeredi 	.setxattr	= fuse_setxattr,
190392a8780eSMiklos Szeredi 	.getxattr	= fuse_getxattr,
190492a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
190592a8780eSMiklos Szeredi 	.removexattr	= fuse_removexattr,
1906e5e5558eSMiklos Szeredi };
1907e5e5558eSMiklos Szeredi 
1908754661f1SArjan van de Ven static const struct inode_operations fuse_symlink_inode_operations = {
19099e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
1910e5e5558eSMiklos Szeredi 	.follow_link	= fuse_follow_link,
1911e5e5558eSMiklos Szeredi 	.put_link	= fuse_put_link,
1912e5e5558eSMiklos Szeredi 	.readlink	= generic_readlink,
1913e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
191492a8780eSMiklos Szeredi 	.setxattr	= fuse_setxattr,
191592a8780eSMiklos Szeredi 	.getxattr	= fuse_getxattr,
191692a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
191792a8780eSMiklos Szeredi 	.removexattr	= fuse_removexattr,
1918e5e5558eSMiklos Szeredi };
1919e5e5558eSMiklos Szeredi 
1920e5e5558eSMiklos Szeredi void fuse_init_common(struct inode *inode)
1921e5e5558eSMiklos Szeredi {
1922e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_common_inode_operations;
1923e5e5558eSMiklos Szeredi }
1924e5e5558eSMiklos Szeredi 
1925e5e5558eSMiklos Szeredi void fuse_init_dir(struct inode *inode)
1926e5e5558eSMiklos Szeredi {
1927e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_dir_inode_operations;
1928e5e5558eSMiklos Szeredi 	inode->i_fop = &fuse_dir_operations;
1929e5e5558eSMiklos Szeredi }
1930e5e5558eSMiklos Szeredi 
1931e5e5558eSMiklos Szeredi void fuse_init_symlink(struct inode *inode)
1932e5e5558eSMiklos Szeredi {
1933e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_symlink_inode_operations;
1934e5e5558eSMiklos Szeredi }
1935