xref: /openbmc/linux/fs/fuse/dir.c (revision b70a80e7)
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;
1856314efeeSMiklos Szeredi 	struct fuse_inode *fi;
186e2a6b952SMiklos Szeredi 	int ret;
1878cbdf1e6SMiklos Szeredi 
188e7c0a167SMiklos Szeredi 	inode = ACCESS_ONCE(entry->d_inode);
1898cbdf1e6SMiklos Szeredi 	if (inode && is_bad_inode(inode))
190e2a6b952SMiklos Szeredi 		goto invalid;
1910a0898cfSMiklos Szeredi 	else if (fuse_dentry_time(entry) < get_jiffies_64()) {
192e5e5558eSMiklos Szeredi 		int err;
193e5e5558eSMiklos Szeredi 		struct fuse_entry_out outarg;
1948cbdf1e6SMiklos Szeredi 		struct fuse_req *req;
19507e77dcaSMiklos Szeredi 		struct fuse_forget_link *forget;
1961fb69e78SMiklos Szeredi 		u64 attr_version;
1978cbdf1e6SMiklos Szeredi 
19850322fe7SMiklos Szeredi 		/* For negative dentries, always do a fresh lookup */
1998cbdf1e6SMiklos Szeredi 		if (!inode)
200e2a6b952SMiklos Szeredi 			goto invalid;
2018cbdf1e6SMiklos Szeredi 
202e2a6b952SMiklos Szeredi 		ret = -ECHILD;
2030b728e19SAl Viro 		if (flags & LOOKUP_RCU)
204e2a6b952SMiklos Szeredi 			goto out;
205e7c0a167SMiklos Szeredi 
2068cbdf1e6SMiklos Szeredi 		fc = get_fuse_conn(inode);
207b111c8c0SMaxim Patlasov 		req = fuse_get_req_nopages(fc);
208e2a6b952SMiklos Szeredi 		ret = PTR_ERR(req);
209ce1d5a49SMiklos Szeredi 		if (IS_ERR(req))
210e2a6b952SMiklos Szeredi 			goto out;
211e5e5558eSMiklos Szeredi 
21207e77dcaSMiklos Szeredi 		forget = fuse_alloc_forget();
21307e77dcaSMiklos Szeredi 		if (!forget) {
2142d51013eSMiklos Szeredi 			fuse_put_request(fc, req);
215e2a6b952SMiklos Szeredi 			ret = -ENOMEM;
216e2a6b952SMiklos Szeredi 			goto out;
2172d51013eSMiklos Szeredi 		}
2182d51013eSMiklos Szeredi 
2197dca9fd3SMiklos Szeredi 		attr_version = fuse_get_attr_version(fc);
2201fb69e78SMiklos Szeredi 
221e956edd0SMiklos Szeredi 		parent = dget_parent(entry);
222c180eebeSMiklos Szeredi 		fuse_lookup_init(fc, req, get_node_id(parent->d_inode),
223c180eebeSMiklos Szeredi 				 &entry->d_name, &outarg);
224b93f858aSTejun Heo 		fuse_request_send(fc, req);
225e956edd0SMiklos Szeredi 		dput(parent);
226e5e5558eSMiklos Szeredi 		err = req->out.h.error;
2272d51013eSMiklos Szeredi 		fuse_put_request(fc, req);
22850322fe7SMiklos Szeredi 		/* Zero nodeid is same as -ENOENT */
22950322fe7SMiklos Szeredi 		if (!err && !outarg.nodeid)
23050322fe7SMiklos Szeredi 			err = -ENOENT;
2319e6268dbSMiklos Szeredi 		if (!err) {
2326314efeeSMiklos Szeredi 			fi = get_fuse_inode(inode);
2339e6268dbSMiklos Szeredi 			if (outarg.nodeid != get_node_id(inode)) {
23407e77dcaSMiklos Szeredi 				fuse_queue_forget(fc, forget, outarg.nodeid, 1);
235e2a6b952SMiklos Szeredi 				goto invalid;
2369e6268dbSMiklos Szeredi 			}
2378da5ff23SMiklos Szeredi 			spin_lock(&fc->lock);
2389e6268dbSMiklos Szeredi 			fi->nlookup++;
2398da5ff23SMiklos Szeredi 			spin_unlock(&fc->lock);
2409e6268dbSMiklos Szeredi 		}
24107e77dcaSMiklos Szeredi 		kfree(forget);
2429e6268dbSMiklos Szeredi 		if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT)
243e2a6b952SMiklos Szeredi 			goto invalid;
244e5e5558eSMiklos Szeredi 
2451fb69e78SMiklos Szeredi 		fuse_change_attributes(inode, &outarg.attr,
2461fb69e78SMiklos Szeredi 				       entry_attr_timeout(&outarg),
2471fb69e78SMiklos Szeredi 				       attr_version);
2481fb69e78SMiklos Szeredi 		fuse_change_entry_timeout(entry, &outarg);
24928420dadSMiklos Szeredi 	} else if (inode) {
2506314efeeSMiklos Szeredi 		fi = get_fuse_inode(inode);
2516314efeeSMiklos Szeredi 		if (flags & LOOKUP_RCU) {
2526314efeeSMiklos Szeredi 			if (test_bit(FUSE_I_INIT_RDPLUS, &fi->state))
2536314efeeSMiklos Szeredi 				return -ECHILD;
2546314efeeSMiklos Szeredi 		} else if (test_and_clear_bit(FUSE_I_INIT_RDPLUS, &fi->state)) {
25528420dadSMiklos Szeredi 			parent = dget_parent(entry);
25628420dadSMiklos Szeredi 			fuse_advise_use_readdirplus(parent->d_inode);
25728420dadSMiklos Szeredi 			dput(parent);
258e5e5558eSMiklos Szeredi 		}
25928420dadSMiklos Szeredi 	}
260e2a6b952SMiklos Szeredi 	ret = 1;
261e2a6b952SMiklos Szeredi out:
262e2a6b952SMiklos Szeredi 	return ret;
263e2a6b952SMiklos Szeredi 
264e2a6b952SMiklos Szeredi invalid:
265e2a6b952SMiklos Szeredi 	ret = 0;
2663c70b8eeSMiklos Szeredi 
2673c70b8eeSMiklos Szeredi 	if (!(flags & LOOKUP_RCU) && check_submounts_and_drop(entry) != 0)
26846ea1562SAnand Avati 		ret = 1;
269e2a6b952SMiklos Szeredi 	goto out;
270e5e5558eSMiklos Szeredi }
271e5e5558eSMiklos Szeredi 
2728bfc016dSMiklos Szeredi static int invalid_nodeid(u64 nodeid)
2732827d0b2SMiklos Szeredi {
2742827d0b2SMiklos Szeredi 	return !nodeid || nodeid == FUSE_ROOT_ID;
2752827d0b2SMiklos Szeredi }
2762827d0b2SMiklos Szeredi 
2774269590aSAl Viro const struct dentry_operations fuse_dentry_operations = {
278e5e5558eSMiklos Szeredi 	.d_revalidate	= fuse_dentry_revalidate,
279e5e5558eSMiklos Szeredi };
280e5e5558eSMiklos Szeredi 
281a5bfffacSTimo Savola int fuse_valid_type(int m)
28239ee059aSMiklos Szeredi {
28339ee059aSMiklos Szeredi 	return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) ||
28439ee059aSMiklos Szeredi 		S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m);
28539ee059aSMiklos Szeredi }
28639ee059aSMiklos Szeredi 
287c180eebeSMiklos Szeredi int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name,
288c180eebeSMiklos Szeredi 		     struct fuse_entry_out *outarg, struct inode **inode)
289c180eebeSMiklos Szeredi {
290c180eebeSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn_super(sb);
291c180eebeSMiklos Szeredi 	struct fuse_req *req;
29207e77dcaSMiklos Szeredi 	struct fuse_forget_link *forget;
293c180eebeSMiklos Szeredi 	u64 attr_version;
294c180eebeSMiklos Szeredi 	int err;
295c180eebeSMiklos Szeredi 
296c180eebeSMiklos Szeredi 	*inode = NULL;
297c180eebeSMiklos Szeredi 	err = -ENAMETOOLONG;
298c180eebeSMiklos Szeredi 	if (name->len > FUSE_NAME_MAX)
299c180eebeSMiklos Szeredi 		goto out;
300c180eebeSMiklos Szeredi 
301b111c8c0SMaxim Patlasov 	req = fuse_get_req_nopages(fc);
302c180eebeSMiklos Szeredi 	err = PTR_ERR(req);
303c180eebeSMiklos Szeredi 	if (IS_ERR(req))
304c180eebeSMiklos Szeredi 		goto out;
305c180eebeSMiklos Szeredi 
30607e77dcaSMiklos Szeredi 	forget = fuse_alloc_forget();
30707e77dcaSMiklos Szeredi 	err = -ENOMEM;
30807e77dcaSMiklos Szeredi 	if (!forget) {
309c180eebeSMiklos Szeredi 		fuse_put_request(fc, req);
310c180eebeSMiklos Szeredi 		goto out;
311c180eebeSMiklos Szeredi 	}
312c180eebeSMiklos Szeredi 
313c180eebeSMiklos Szeredi 	attr_version = fuse_get_attr_version(fc);
314c180eebeSMiklos Szeredi 
315c180eebeSMiklos Szeredi 	fuse_lookup_init(fc, req, nodeid, name, outarg);
316b93f858aSTejun Heo 	fuse_request_send(fc, req);
317c180eebeSMiklos Szeredi 	err = req->out.h.error;
318c180eebeSMiklos Szeredi 	fuse_put_request(fc, req);
319c180eebeSMiklos Szeredi 	/* Zero nodeid is same as -ENOENT, but with valid timeout */
320c180eebeSMiklos Szeredi 	if (err || !outarg->nodeid)
321c180eebeSMiklos Szeredi 		goto out_put_forget;
322c180eebeSMiklos Szeredi 
323c180eebeSMiklos Szeredi 	err = -EIO;
324c180eebeSMiklos Szeredi 	if (!outarg->nodeid)
325c180eebeSMiklos Szeredi 		goto out_put_forget;
326c180eebeSMiklos Szeredi 	if (!fuse_valid_type(outarg->attr.mode))
327c180eebeSMiklos Szeredi 		goto out_put_forget;
328c180eebeSMiklos Szeredi 
329c180eebeSMiklos Szeredi 	*inode = fuse_iget(sb, outarg->nodeid, outarg->generation,
330c180eebeSMiklos Szeredi 			   &outarg->attr, entry_attr_timeout(outarg),
331c180eebeSMiklos Szeredi 			   attr_version);
332c180eebeSMiklos Szeredi 	err = -ENOMEM;
333c180eebeSMiklos Szeredi 	if (!*inode) {
33407e77dcaSMiklos Szeredi 		fuse_queue_forget(fc, forget, outarg->nodeid, 1);
335c180eebeSMiklos Szeredi 		goto out;
336c180eebeSMiklos Szeredi 	}
337c180eebeSMiklos Szeredi 	err = 0;
338c180eebeSMiklos Szeredi 
339c180eebeSMiklos Szeredi  out_put_forget:
34007e77dcaSMiklos Szeredi 	kfree(forget);
341c180eebeSMiklos Szeredi  out:
342c180eebeSMiklos Szeredi 	return err;
343c180eebeSMiklos Szeredi }
344c180eebeSMiklos Szeredi 
3450aa7c699SMiklos Szeredi static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
34600cd8dd3SAl Viro 				  unsigned int flags)
347e5e5558eSMiklos Szeredi {
348e5e5558eSMiklos Szeredi 	int err;
349e5e5558eSMiklos Szeredi 	struct fuse_entry_out outarg;
350c180eebeSMiklos Szeredi 	struct inode *inode;
3510de6256dSMiklos Szeredi 	struct dentry *newent;
352c180eebeSMiklos Szeredi 	bool outarg_valid = true;
353e5e5558eSMiklos Szeredi 
354c180eebeSMiklos Szeredi 	err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name,
355c180eebeSMiklos Szeredi 			       &outarg, &inode);
356c180eebeSMiklos Szeredi 	if (err == -ENOENT) {
357c180eebeSMiklos Szeredi 		outarg_valid = false;
358c180eebeSMiklos Szeredi 		err = 0;
3592d51013eSMiklos Szeredi 	}
360c180eebeSMiklos Szeredi 	if (err)
361c180eebeSMiklos Szeredi 		goto out_err;
3622d51013eSMiklos Szeredi 
363ee4e5271SMiklos Szeredi 	err = -EIO;
364c180eebeSMiklos Szeredi 	if (inode && get_node_id(inode) == FUSE_ROOT_ID)
365c180eebeSMiklos Szeredi 		goto out_iput;
366e5e5558eSMiklos Szeredi 
367*b70a80e7SMiklos Szeredi 	newent = d_materialise_unique(entry, inode);
368c180eebeSMiklos Szeredi 	err = PTR_ERR(newent);
369c180eebeSMiklos Szeredi 	if (IS_ERR(newent))
3705835f339SMiklos Szeredi 		goto out_err;
371d2a85164SMiklos Szeredi 
3720de6256dSMiklos Szeredi 	entry = newent ? newent : entry;
373c180eebeSMiklos Szeredi 	if (outarg_valid)
3741fb69e78SMiklos Szeredi 		fuse_change_entry_timeout(entry, &outarg);
3758cbdf1e6SMiklos Szeredi 	else
3768cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
377c180eebeSMiklos Szeredi 
3784582a4abSFeng Shuo 	fuse_advise_use_readdirplus(dir);
3790de6256dSMiklos Szeredi 	return newent;
380c180eebeSMiklos Szeredi 
381c180eebeSMiklos Szeredi  out_iput:
382c180eebeSMiklos Szeredi 	iput(inode);
383c180eebeSMiklos Szeredi  out_err:
384c180eebeSMiklos Szeredi 	return ERR_PTR(err);
385e5e5558eSMiklos Szeredi }
386e5e5558eSMiklos Szeredi 
3876f9f1180SMiklos Szeredi /*
3886f9f1180SMiklos Szeredi  * Atomic create+open operation
3896f9f1180SMiklos Szeredi  *
3906f9f1180SMiklos Szeredi  * If the filesystem doesn't support this, then fall back to separate
3916f9f1180SMiklos Szeredi  * 'mknod' + 'open' requests.
3926f9f1180SMiklos Szeredi  */
393d9585277SAl Viro static int fuse_create_open(struct inode *dir, struct dentry *entry,
39430d90494SAl Viro 			    struct file *file, unsigned flags,
39547237687SAl Viro 			    umode_t mode, int *opened)
396fd72faacSMiklos Szeredi {
397fd72faacSMiklos Szeredi 	int err;
398fd72faacSMiklos Szeredi 	struct inode *inode;
399fd72faacSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
400fd72faacSMiklos Szeredi 	struct fuse_req *req;
40107e77dcaSMiklos Szeredi 	struct fuse_forget_link *forget;
402e0a43ddcSMiklos Szeredi 	struct fuse_create_in inarg;
403fd72faacSMiklos Szeredi 	struct fuse_open_out outopen;
404fd72faacSMiklos Szeredi 	struct fuse_entry_out outentry;
405fd72faacSMiklos Szeredi 	struct fuse_file *ff;
406fd72faacSMiklos Szeredi 
407af109bcaSMiklos Szeredi 	/* Userspace expects S_IFREG in create mode */
408af109bcaSMiklos Szeredi 	BUG_ON((mode & S_IFMT) != S_IFREG);
409af109bcaSMiklos Szeredi 
41007e77dcaSMiklos Szeredi 	forget = fuse_alloc_forget();
411c8ccbe03SMiklos Szeredi 	err = -ENOMEM;
41207e77dcaSMiklos Szeredi 	if (!forget)
413c8ccbe03SMiklos Szeredi 		goto out_err;
41451eb01e7SMiklos Szeredi 
415b111c8c0SMaxim Patlasov 	req = fuse_get_req_nopages(fc);
41651eb01e7SMiklos Szeredi 	err = PTR_ERR(req);
417ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
41851eb01e7SMiklos Szeredi 		goto out_put_forget_req;
419fd72faacSMiklos Szeredi 
420ce1d5a49SMiklos Szeredi 	err = -ENOMEM;
421acf99433STejun Heo 	ff = fuse_file_alloc(fc);
422fd72faacSMiklos Szeredi 	if (!ff)
423fd72faacSMiklos Szeredi 		goto out_put_request;
424fd72faacSMiklos Szeredi 
425e0a43ddcSMiklos Szeredi 	if (!fc->dont_mask)
426e0a43ddcSMiklos Szeredi 		mode &= ~current_umask();
427e0a43ddcSMiklos Szeredi 
428fd72faacSMiklos Szeredi 	flags &= ~O_NOCTTY;
429fd72faacSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
4300e9663eeSMiklos Szeredi 	memset(&outentry, 0, sizeof(outentry));
431fd72faacSMiklos Szeredi 	inarg.flags = flags;
432fd72faacSMiklos Szeredi 	inarg.mode = mode;
433e0a43ddcSMiklos Szeredi 	inarg.umask = current_umask();
434fd72faacSMiklos Szeredi 	req->in.h.opcode = FUSE_CREATE;
435fd72faacSMiklos Szeredi 	req->in.h.nodeid = get_node_id(dir);
436fd72faacSMiklos Szeredi 	req->in.numargs = 2;
437e0a43ddcSMiklos Szeredi 	req->in.args[0].size = fc->minor < 12 ? sizeof(struct fuse_open_in) :
438e0a43ddcSMiklos Szeredi 						sizeof(inarg);
439fd72faacSMiklos Szeredi 	req->in.args[0].value = &inarg;
440fd72faacSMiklos Szeredi 	req->in.args[1].size = entry->d_name.len + 1;
441fd72faacSMiklos Szeredi 	req->in.args[1].value = entry->d_name.name;
442fd72faacSMiklos Szeredi 	req->out.numargs = 2;
4430e9663eeSMiklos Szeredi 	if (fc->minor < 9)
4440e9663eeSMiklos Szeredi 		req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
4450e9663eeSMiklos Szeredi 	else
446fd72faacSMiklos Szeredi 		req->out.args[0].size = sizeof(outentry);
447fd72faacSMiklos Szeredi 	req->out.args[0].value = &outentry;
448fd72faacSMiklos Szeredi 	req->out.args[1].size = sizeof(outopen);
449fd72faacSMiklos Szeredi 	req->out.args[1].value = &outopen;
450b93f858aSTejun Heo 	fuse_request_send(fc, req);
451fd72faacSMiklos Szeredi 	err = req->out.h.error;
452c8ccbe03SMiklos Szeredi 	if (err)
453fd72faacSMiklos Szeredi 		goto out_free_ff;
454fd72faacSMiklos Szeredi 
455fd72faacSMiklos Szeredi 	err = -EIO;
4562827d0b2SMiklos Szeredi 	if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid))
457fd72faacSMiklos Szeredi 		goto out_free_ff;
458fd72faacSMiklos Szeredi 
45951eb01e7SMiklos Szeredi 	fuse_put_request(fc, req);
460c7b7143cSMiklos Szeredi 	ff->fh = outopen.fh;
461c7b7143cSMiklos Szeredi 	ff->nodeid = outentry.nodeid;
462c7b7143cSMiklos Szeredi 	ff->open_flags = outopen.open_flags;
463fd72faacSMiklos Szeredi 	inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
4641fb69e78SMiklos Szeredi 			  &outentry.attr, entry_attr_timeout(&outentry), 0);
465fd72faacSMiklos Szeredi 	if (!inode) {
466fd72faacSMiklos Szeredi 		flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
4678b0797a4SMiklos Szeredi 		fuse_sync_release(ff, flags);
46807e77dcaSMiklos Szeredi 		fuse_queue_forget(fc, forget, outentry.nodeid, 1);
469c8ccbe03SMiklos Szeredi 		err = -ENOMEM;
470c8ccbe03SMiklos Szeredi 		goto out_err;
471fd72faacSMiklos Szeredi 	}
47207e77dcaSMiklos Szeredi 	kfree(forget);
473fd72faacSMiklos Szeredi 	d_instantiate(entry, inode);
4741fb69e78SMiklos Szeredi 	fuse_change_entry_timeout(entry, &outentry);
4750952b2a4SMiklos Szeredi 	fuse_invalidate_attr(dir);
47630d90494SAl Viro 	err = finish_open(file, entry, generic_file_open, opened);
47730d90494SAl Viro 	if (err) {
4788b0797a4SMiklos Szeredi 		fuse_sync_release(ff, flags);
479c8ccbe03SMiklos Szeredi 	} else {
480c7b7143cSMiklos Szeredi 		file->private_data = fuse_file_get(ff);
481c7b7143cSMiklos Szeredi 		fuse_finish_open(inode, file);
482c8ccbe03SMiklos Szeredi 	}
483d9585277SAl Viro 	return err;
484fd72faacSMiklos Szeredi 
485fd72faacSMiklos Szeredi out_free_ff:
486fd72faacSMiklos Szeredi 	fuse_file_free(ff);
487fd72faacSMiklos Szeredi out_put_request:
488fd72faacSMiklos Szeredi 	fuse_put_request(fc, req);
48951eb01e7SMiklos Szeredi out_put_forget_req:
49007e77dcaSMiklos Szeredi 	kfree(forget);
491c8ccbe03SMiklos Szeredi out_err:
492d9585277SAl Viro 	return err;
493c8ccbe03SMiklos Szeredi }
494c8ccbe03SMiklos Szeredi 
495c8ccbe03SMiklos Szeredi static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t);
496d9585277SAl Viro static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
49730d90494SAl Viro 			    struct file *file, unsigned flags,
49847237687SAl Viro 			    umode_t mode, int *opened)
499c8ccbe03SMiklos Szeredi {
500c8ccbe03SMiklos Szeredi 	int err;
501c8ccbe03SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
502c8ccbe03SMiklos Szeredi 	struct dentry *res = NULL;
503c8ccbe03SMiklos Szeredi 
504c8ccbe03SMiklos Szeredi 	if (d_unhashed(entry)) {
50500cd8dd3SAl Viro 		res = fuse_lookup(dir, entry, 0);
506c8ccbe03SMiklos Szeredi 		if (IS_ERR(res))
507d9585277SAl Viro 			return PTR_ERR(res);
508c8ccbe03SMiklos Szeredi 
509c8ccbe03SMiklos Szeredi 		if (res)
510c8ccbe03SMiklos Szeredi 			entry = res;
511c8ccbe03SMiklos Szeredi 	}
512c8ccbe03SMiklos Szeredi 
513c8ccbe03SMiklos Szeredi 	if (!(flags & O_CREAT) || entry->d_inode)
514c8ccbe03SMiklos Szeredi 		goto no_open;
515c8ccbe03SMiklos Szeredi 
516c8ccbe03SMiklos Szeredi 	/* Only creates */
51747237687SAl Viro 	*opened |= FILE_CREATED;
518c8ccbe03SMiklos Szeredi 
519c8ccbe03SMiklos Szeredi 	if (fc->no_create)
520c8ccbe03SMiklos Szeredi 		goto mknod;
521c8ccbe03SMiklos Szeredi 
52230d90494SAl Viro 	err = fuse_create_open(dir, entry, file, flags, mode, opened);
523d9585277SAl Viro 	if (err == -ENOSYS) {
524c8ccbe03SMiklos Szeredi 		fc->no_create = 1;
525c8ccbe03SMiklos Szeredi 		goto mknod;
526c8ccbe03SMiklos Szeredi 	}
527c8ccbe03SMiklos Szeredi out_dput:
528c8ccbe03SMiklos Szeredi 	dput(res);
529d9585277SAl Viro 	return err;
530c8ccbe03SMiklos Szeredi 
531c8ccbe03SMiklos Szeredi mknod:
532c8ccbe03SMiklos Szeredi 	err = fuse_mknod(dir, entry, mode, 0);
533d9585277SAl Viro 	if (err)
534c8ccbe03SMiklos Szeredi 		goto out_dput;
535c8ccbe03SMiklos Szeredi no_open:
536e45198a6SAl Viro 	return finish_no_open(file, res);
537fd72faacSMiklos Szeredi }
538fd72faacSMiklos Szeredi 
5396f9f1180SMiklos Szeredi /*
5406f9f1180SMiklos Szeredi  * Code shared between mknod, mkdir, symlink and link
5416f9f1180SMiklos Szeredi  */
5429e6268dbSMiklos Szeredi static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
5439e6268dbSMiklos Szeredi 			    struct inode *dir, struct dentry *entry,
544541af6a0SAl Viro 			    umode_t mode)
5459e6268dbSMiklos Szeredi {
5469e6268dbSMiklos Szeredi 	struct fuse_entry_out outarg;
5479e6268dbSMiklos Szeredi 	struct inode *inode;
5489e6268dbSMiklos Szeredi 	int err;
54907e77dcaSMiklos Szeredi 	struct fuse_forget_link *forget;
5502d51013eSMiklos Szeredi 
55107e77dcaSMiklos Szeredi 	forget = fuse_alloc_forget();
55207e77dcaSMiklos Szeredi 	if (!forget) {
5532d51013eSMiklos Szeredi 		fuse_put_request(fc, req);
55407e77dcaSMiklos Szeredi 		return -ENOMEM;
5552d51013eSMiklos Szeredi 	}
5569e6268dbSMiklos Szeredi 
5570e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
5589e6268dbSMiklos Szeredi 	req->in.h.nodeid = get_node_id(dir);
5599e6268dbSMiklos Szeredi 	req->out.numargs = 1;
5600e9663eeSMiklos Szeredi 	if (fc->minor < 9)
5610e9663eeSMiklos Szeredi 		req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
5620e9663eeSMiklos Szeredi 	else
5639e6268dbSMiklos Szeredi 		req->out.args[0].size = sizeof(outarg);
5649e6268dbSMiklos Szeredi 	req->out.args[0].value = &outarg;
565b93f858aSTejun Heo 	fuse_request_send(fc, req);
5669e6268dbSMiklos Szeredi 	err = req->out.h.error;
5679e6268dbSMiklos Szeredi 	fuse_put_request(fc, req);
5682d51013eSMiklos Szeredi 	if (err)
5692d51013eSMiklos Szeredi 		goto out_put_forget_req;
5702d51013eSMiklos Szeredi 
57139ee059aSMiklos Szeredi 	err = -EIO;
57239ee059aSMiklos Szeredi 	if (invalid_nodeid(outarg.nodeid))
5732d51013eSMiklos Szeredi 		goto out_put_forget_req;
57439ee059aSMiklos Szeredi 
57539ee059aSMiklos Szeredi 	if ((outarg.attr.mode ^ mode) & S_IFMT)
5762d51013eSMiklos Szeredi 		goto out_put_forget_req;
57739ee059aSMiklos Szeredi 
5789e6268dbSMiklos Szeredi 	inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
5791fb69e78SMiklos Szeredi 			  &outarg.attr, entry_attr_timeout(&outarg), 0);
5809e6268dbSMiklos Szeredi 	if (!inode) {
58107e77dcaSMiklos Szeredi 		fuse_queue_forget(fc, forget, outarg.nodeid, 1);
5829e6268dbSMiklos Szeredi 		return -ENOMEM;
5839e6268dbSMiklos Szeredi 	}
58407e77dcaSMiklos Szeredi 	kfree(forget);
5859e6268dbSMiklos Szeredi 
586*b70a80e7SMiklos Szeredi 	err = d_instantiate_no_diralias(entry, inode);
587*b70a80e7SMiklos Szeredi 	if (err)
588*b70a80e7SMiklos Szeredi 		return err;
589d2a85164SMiklos Szeredi 
5901fb69e78SMiklos Szeredi 	fuse_change_entry_timeout(entry, &outarg);
5919e6268dbSMiklos Szeredi 	fuse_invalidate_attr(dir);
5929e6268dbSMiklos Szeredi 	return 0;
59339ee059aSMiklos Szeredi 
5942d51013eSMiklos Szeredi  out_put_forget_req:
59507e77dcaSMiklos Szeredi 	kfree(forget);
59639ee059aSMiklos Szeredi 	return err;
5979e6268dbSMiklos Szeredi }
5989e6268dbSMiklos Szeredi 
5991a67aafbSAl Viro static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode,
6009e6268dbSMiklos Szeredi 		      dev_t rdev)
6019e6268dbSMiklos Szeredi {
6029e6268dbSMiklos Szeredi 	struct fuse_mknod_in inarg;
6039e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
604b111c8c0SMaxim Patlasov 	struct fuse_req *req = fuse_get_req_nopages(fc);
605ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
606ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
6079e6268dbSMiklos Szeredi 
608e0a43ddcSMiklos Szeredi 	if (!fc->dont_mask)
609e0a43ddcSMiklos Szeredi 		mode &= ~current_umask();
610e0a43ddcSMiklos Szeredi 
6119e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
6129e6268dbSMiklos Szeredi 	inarg.mode = mode;
6139e6268dbSMiklos Szeredi 	inarg.rdev = new_encode_dev(rdev);
614e0a43ddcSMiklos Szeredi 	inarg.umask = current_umask();
6159e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_MKNOD;
6169e6268dbSMiklos Szeredi 	req->in.numargs = 2;
617e0a43ddcSMiklos Szeredi 	req->in.args[0].size = fc->minor < 12 ? FUSE_COMPAT_MKNOD_IN_SIZE :
618e0a43ddcSMiklos Szeredi 						sizeof(inarg);
6199e6268dbSMiklos Szeredi 	req->in.args[0].value = &inarg;
6209e6268dbSMiklos Szeredi 	req->in.args[1].size = entry->d_name.len + 1;
6219e6268dbSMiklos Szeredi 	req->in.args[1].value = entry->d_name.name;
6229e6268dbSMiklos Szeredi 	return create_new_entry(fc, req, dir, entry, mode);
6239e6268dbSMiklos Szeredi }
6249e6268dbSMiklos Szeredi 
6254acdaf27SAl Viro static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode,
626ebfc3b49SAl Viro 		       bool excl)
6279e6268dbSMiklos Szeredi {
6289e6268dbSMiklos Szeredi 	return fuse_mknod(dir, entry, mode, 0);
6299e6268dbSMiklos Szeredi }
6309e6268dbSMiklos Szeredi 
63118bb1db3SAl Viro static int fuse_mkdir(struct inode *dir, struct dentry *entry, umode_t mode)
6329e6268dbSMiklos Szeredi {
6339e6268dbSMiklos Szeredi 	struct fuse_mkdir_in inarg;
6349e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
635b111c8c0SMaxim Patlasov 	struct fuse_req *req = fuse_get_req_nopages(fc);
636ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
637ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
6389e6268dbSMiklos Szeredi 
639e0a43ddcSMiklos Szeredi 	if (!fc->dont_mask)
640e0a43ddcSMiklos Szeredi 		mode &= ~current_umask();
641e0a43ddcSMiklos Szeredi 
6429e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
6439e6268dbSMiklos Szeredi 	inarg.mode = mode;
644e0a43ddcSMiklos Szeredi 	inarg.umask = current_umask();
6459e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_MKDIR;
6469e6268dbSMiklos Szeredi 	req->in.numargs = 2;
6479e6268dbSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
6489e6268dbSMiklos Szeredi 	req->in.args[0].value = &inarg;
6499e6268dbSMiklos Szeredi 	req->in.args[1].size = entry->d_name.len + 1;
6509e6268dbSMiklos Szeredi 	req->in.args[1].value = entry->d_name.name;
6519e6268dbSMiklos Szeredi 	return create_new_entry(fc, req, dir, entry, S_IFDIR);
6529e6268dbSMiklos Szeredi }
6539e6268dbSMiklos Szeredi 
6549e6268dbSMiklos Szeredi static int fuse_symlink(struct inode *dir, struct dentry *entry,
6559e6268dbSMiklos Szeredi 			const char *link)
6569e6268dbSMiklos Szeredi {
6579e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
6589e6268dbSMiklos Szeredi 	unsigned len = strlen(link) + 1;
659b111c8c0SMaxim Patlasov 	struct fuse_req *req = fuse_get_req_nopages(fc);
660ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
661ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
6629e6268dbSMiklos Szeredi 
6639e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_SYMLINK;
6649e6268dbSMiklos Szeredi 	req->in.numargs = 2;
6659e6268dbSMiklos Szeredi 	req->in.args[0].size = entry->d_name.len + 1;
6669e6268dbSMiklos Szeredi 	req->in.args[0].value = entry->d_name.name;
6679e6268dbSMiklos Szeredi 	req->in.args[1].size = len;
6689e6268dbSMiklos Szeredi 	req->in.args[1].value = link;
6699e6268dbSMiklos Szeredi 	return create_new_entry(fc, req, dir, entry, S_IFLNK);
6709e6268dbSMiklos Szeredi }
6719e6268dbSMiklos Szeredi 
6729e6268dbSMiklos Szeredi static int fuse_unlink(struct inode *dir, struct dentry *entry)
6739e6268dbSMiklos Szeredi {
6749e6268dbSMiklos Szeredi 	int err;
6759e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
676b111c8c0SMaxim Patlasov 	struct fuse_req *req = fuse_get_req_nopages(fc);
677ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
678ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
6799e6268dbSMiklos Szeredi 
6809e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_UNLINK;
6819e6268dbSMiklos Szeredi 	req->in.h.nodeid = get_node_id(dir);
6829e6268dbSMiklos Szeredi 	req->in.numargs = 1;
6839e6268dbSMiklos Szeredi 	req->in.args[0].size = entry->d_name.len + 1;
6849e6268dbSMiklos Szeredi 	req->in.args[0].value = entry->d_name.name;
685b93f858aSTejun Heo 	fuse_request_send(fc, req);
6869e6268dbSMiklos Szeredi 	err = req->out.h.error;
6879e6268dbSMiklos Szeredi 	fuse_put_request(fc, req);
6889e6268dbSMiklos Szeredi 	if (!err) {
6899e6268dbSMiklos Szeredi 		struct inode *inode = entry->d_inode;
690ac45d613SMiklos Szeredi 		struct fuse_inode *fi = get_fuse_inode(inode);
6919e6268dbSMiklos Szeredi 
692ac45d613SMiklos Szeredi 		spin_lock(&fc->lock);
693ac45d613SMiklos Szeredi 		fi->attr_version = ++fc->attr_version;
694dfca7cebSMiklos Szeredi 		/*
695dfca7cebSMiklos Szeredi 		 * If i_nlink == 0 then unlink doesn't make sense, yet this can
696dfca7cebSMiklos Szeredi 		 * happen if userspace filesystem is careless.  It would be
697dfca7cebSMiklos Szeredi 		 * difficult to enforce correct nlink usage so just ignore this
698dfca7cebSMiklos Szeredi 		 * condition here
699dfca7cebSMiklos Szeredi 		 */
700dfca7cebSMiklos Szeredi 		if (inode->i_nlink > 0)
701ac45d613SMiklos Szeredi 			drop_nlink(inode);
702ac45d613SMiklos Szeredi 		spin_unlock(&fc->lock);
7039e6268dbSMiklos Szeredi 		fuse_invalidate_attr(inode);
7049e6268dbSMiklos Szeredi 		fuse_invalidate_attr(dir);
7058cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
7069e6268dbSMiklos Szeredi 	} else if (err == -EINTR)
7079e6268dbSMiklos Szeredi 		fuse_invalidate_entry(entry);
7089e6268dbSMiklos Szeredi 	return err;
7099e6268dbSMiklos Szeredi }
7109e6268dbSMiklos Szeredi 
7119e6268dbSMiklos Szeredi static int fuse_rmdir(struct inode *dir, struct dentry *entry)
7129e6268dbSMiklos Szeredi {
7139e6268dbSMiklos Szeredi 	int err;
7149e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
715b111c8c0SMaxim Patlasov 	struct fuse_req *req = fuse_get_req_nopages(fc);
716ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
717ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
7189e6268dbSMiklos Szeredi 
7199e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_RMDIR;
7209e6268dbSMiklos Szeredi 	req->in.h.nodeid = get_node_id(dir);
7219e6268dbSMiklos Szeredi 	req->in.numargs = 1;
7229e6268dbSMiklos Szeredi 	req->in.args[0].size = entry->d_name.len + 1;
7239e6268dbSMiklos Szeredi 	req->in.args[0].value = entry->d_name.name;
724b93f858aSTejun Heo 	fuse_request_send(fc, req);
7259e6268dbSMiklos Szeredi 	err = req->out.h.error;
7269e6268dbSMiklos Szeredi 	fuse_put_request(fc, req);
7279e6268dbSMiklos Szeredi 	if (!err) {
728ce71ec36SDave Hansen 		clear_nlink(entry->d_inode);
7299e6268dbSMiklos Szeredi 		fuse_invalidate_attr(dir);
7308cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
7319e6268dbSMiklos Szeredi 	} else if (err == -EINTR)
7329e6268dbSMiklos Szeredi 		fuse_invalidate_entry(entry);
7339e6268dbSMiklos Szeredi 	return err;
7349e6268dbSMiklos Szeredi }
7359e6268dbSMiklos Szeredi 
7369e6268dbSMiklos Szeredi static int fuse_rename(struct inode *olddir, struct dentry *oldent,
7379e6268dbSMiklos Szeredi 		       struct inode *newdir, struct dentry *newent)
7389e6268dbSMiklos Szeredi {
7399e6268dbSMiklos Szeredi 	int err;
7409e6268dbSMiklos Szeredi 	struct fuse_rename_in inarg;
7419e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(olddir);
742b111c8c0SMaxim Patlasov 	struct fuse_req *req = fuse_get_req_nopages(fc);
743e4eaac06SSage Weil 
744ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
745ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
7469e6268dbSMiklos Szeredi 
7479e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
7489e6268dbSMiklos Szeredi 	inarg.newdir = get_node_id(newdir);
7499e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_RENAME;
7509e6268dbSMiklos Szeredi 	req->in.h.nodeid = get_node_id(olddir);
7519e6268dbSMiklos Szeredi 	req->in.numargs = 3;
7529e6268dbSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
7539e6268dbSMiklos Szeredi 	req->in.args[0].value = &inarg;
7549e6268dbSMiklos Szeredi 	req->in.args[1].size = oldent->d_name.len + 1;
7559e6268dbSMiklos Szeredi 	req->in.args[1].value = oldent->d_name.name;
7569e6268dbSMiklos Szeredi 	req->in.args[2].size = newent->d_name.len + 1;
7579e6268dbSMiklos Szeredi 	req->in.args[2].value = newent->d_name.name;
758b93f858aSTejun Heo 	fuse_request_send(fc, req);
7599e6268dbSMiklos Szeredi 	err = req->out.h.error;
7609e6268dbSMiklos Szeredi 	fuse_put_request(fc, req);
7619e6268dbSMiklos Szeredi 	if (!err) {
76208b63307SMiklos Szeredi 		/* ctime changes */
76308b63307SMiklos Szeredi 		fuse_invalidate_attr(oldent->d_inode);
76408b63307SMiklos Szeredi 
7659e6268dbSMiklos Szeredi 		fuse_invalidate_attr(olddir);
7669e6268dbSMiklos Szeredi 		if (olddir != newdir)
7679e6268dbSMiklos Szeredi 			fuse_invalidate_attr(newdir);
7688cbdf1e6SMiklos Szeredi 
7698cbdf1e6SMiklos Szeredi 		/* newent will end up negative */
7705219f346SMiklos Szeredi 		if (newent->d_inode) {
7715219f346SMiklos Szeredi 			fuse_invalidate_attr(newent->d_inode);
7728cbdf1e6SMiklos Szeredi 			fuse_invalidate_entry_cache(newent);
7735219f346SMiklos Szeredi 		}
7749e6268dbSMiklos Szeredi 	} else if (err == -EINTR) {
7759e6268dbSMiklos Szeredi 		/* If request was interrupted, DEITY only knows if the
7769e6268dbSMiklos Szeredi 		   rename actually took place.  If the invalidation
7779e6268dbSMiklos Szeredi 		   fails (e.g. some process has CWD under the renamed
7789e6268dbSMiklos Szeredi 		   directory), then there can be inconsistency between
7799e6268dbSMiklos Szeredi 		   the dcache and the real filesystem.  Tough luck. */
7809e6268dbSMiklos Szeredi 		fuse_invalidate_entry(oldent);
7819e6268dbSMiklos Szeredi 		if (newent->d_inode)
7829e6268dbSMiklos Szeredi 			fuse_invalidate_entry(newent);
7839e6268dbSMiklos Szeredi 	}
7849e6268dbSMiklos Szeredi 
7859e6268dbSMiklos Szeredi 	return err;
7869e6268dbSMiklos Szeredi }
7879e6268dbSMiklos Szeredi 
7889e6268dbSMiklos Szeredi static int fuse_link(struct dentry *entry, struct inode *newdir,
7899e6268dbSMiklos Szeredi 		     struct dentry *newent)
7909e6268dbSMiklos Szeredi {
7919e6268dbSMiklos Szeredi 	int err;
7929e6268dbSMiklos Szeredi 	struct fuse_link_in inarg;
7939e6268dbSMiklos Szeredi 	struct inode *inode = entry->d_inode;
7949e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
795b111c8c0SMaxim Patlasov 	struct fuse_req *req = fuse_get_req_nopages(fc);
796ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
797ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
7989e6268dbSMiklos Szeredi 
7999e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
8009e6268dbSMiklos Szeredi 	inarg.oldnodeid = get_node_id(inode);
8019e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_LINK;
8029e6268dbSMiklos Szeredi 	req->in.numargs = 2;
8039e6268dbSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
8049e6268dbSMiklos Szeredi 	req->in.args[0].value = &inarg;
8059e6268dbSMiklos Szeredi 	req->in.args[1].size = newent->d_name.len + 1;
8069e6268dbSMiklos Szeredi 	req->in.args[1].value = newent->d_name.name;
8079e6268dbSMiklos Szeredi 	err = create_new_entry(fc, req, newdir, newent, inode->i_mode);
8089e6268dbSMiklos Szeredi 	/* Contrary to "normal" filesystems it can happen that link
8099e6268dbSMiklos Szeredi 	   makes two "logical" inodes point to the same "physical"
8109e6268dbSMiklos Szeredi 	   inode.  We invalidate the attributes of the old one, so it
8119e6268dbSMiklos Szeredi 	   will reflect changes in the backing inode (link count,
8129e6268dbSMiklos Szeredi 	   etc.)
8139e6268dbSMiklos Szeredi 	*/
814ac45d613SMiklos Szeredi 	if (!err) {
815ac45d613SMiklos Szeredi 		struct fuse_inode *fi = get_fuse_inode(inode);
816ac45d613SMiklos Szeredi 
817ac45d613SMiklos Szeredi 		spin_lock(&fc->lock);
818ac45d613SMiklos Szeredi 		fi->attr_version = ++fc->attr_version;
819ac45d613SMiklos Szeredi 		inc_nlink(inode);
820ac45d613SMiklos Szeredi 		spin_unlock(&fc->lock);
8219e6268dbSMiklos Szeredi 		fuse_invalidate_attr(inode);
822ac45d613SMiklos Szeredi 	} else if (err == -EINTR) {
823ac45d613SMiklos Szeredi 		fuse_invalidate_attr(inode);
824ac45d613SMiklos Szeredi 	}
8259e6268dbSMiklos Szeredi 	return err;
8269e6268dbSMiklos Szeredi }
8279e6268dbSMiklos Szeredi 
8281fb69e78SMiklos Szeredi static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
8291fb69e78SMiklos Szeredi 			  struct kstat *stat)
8301fb69e78SMiklos Szeredi {
831203627bbSMiklos Szeredi 	unsigned int blkbits;
832203627bbSMiklos Szeredi 
8331fb69e78SMiklos Szeredi 	stat->dev = inode->i_sb->s_dev;
8341fb69e78SMiklos Szeredi 	stat->ino = attr->ino;
8351fb69e78SMiklos Szeredi 	stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
8361fb69e78SMiklos Szeredi 	stat->nlink = attr->nlink;
837499dcf20SEric W. Biederman 	stat->uid = make_kuid(&init_user_ns, attr->uid);
838499dcf20SEric W. Biederman 	stat->gid = make_kgid(&init_user_ns, attr->gid);
8391fb69e78SMiklos Szeredi 	stat->rdev = inode->i_rdev;
8401fb69e78SMiklos Szeredi 	stat->atime.tv_sec = attr->atime;
8411fb69e78SMiklos Szeredi 	stat->atime.tv_nsec = attr->atimensec;
8421fb69e78SMiklos Szeredi 	stat->mtime.tv_sec = attr->mtime;
8431fb69e78SMiklos Szeredi 	stat->mtime.tv_nsec = attr->mtimensec;
8441fb69e78SMiklos Szeredi 	stat->ctime.tv_sec = attr->ctime;
8451fb69e78SMiklos Szeredi 	stat->ctime.tv_nsec = attr->ctimensec;
8461fb69e78SMiklos Szeredi 	stat->size = attr->size;
8471fb69e78SMiklos Szeredi 	stat->blocks = attr->blocks;
848203627bbSMiklos Szeredi 
849203627bbSMiklos Szeredi 	if (attr->blksize != 0)
850203627bbSMiklos Szeredi 		blkbits = ilog2(attr->blksize);
851203627bbSMiklos Szeredi 	else
852203627bbSMiklos Szeredi 		blkbits = inode->i_sb->s_blocksize_bits;
853203627bbSMiklos Szeredi 
854203627bbSMiklos Szeredi 	stat->blksize = 1 << blkbits;
8551fb69e78SMiklos Szeredi }
8561fb69e78SMiklos Szeredi 
857c79e322fSMiklos Szeredi static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
858c79e322fSMiklos Szeredi 			   struct file *file)
859e5e5558eSMiklos Szeredi {
860e5e5558eSMiklos Szeredi 	int err;
861c79e322fSMiklos Szeredi 	struct fuse_getattr_in inarg;
862c79e322fSMiklos Szeredi 	struct fuse_attr_out outarg;
863e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
8641fb69e78SMiklos Szeredi 	struct fuse_req *req;
8651fb69e78SMiklos Szeredi 	u64 attr_version;
8661fb69e78SMiklos Szeredi 
867b111c8c0SMaxim Patlasov 	req = fuse_get_req_nopages(fc);
868ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
869ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
870e5e5558eSMiklos Szeredi 
8717dca9fd3SMiklos Szeredi 	attr_version = fuse_get_attr_version(fc);
8721fb69e78SMiklos Szeredi 
873c79e322fSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
8740e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
875c79e322fSMiklos Szeredi 	/* Directories have separate file-handle space */
876c79e322fSMiklos Szeredi 	if (file && S_ISREG(inode->i_mode)) {
877c79e322fSMiklos Szeredi 		struct fuse_file *ff = file->private_data;
878c79e322fSMiklos Szeredi 
879c79e322fSMiklos Szeredi 		inarg.getattr_flags |= FUSE_GETATTR_FH;
880c79e322fSMiklos Szeredi 		inarg.fh = ff->fh;
881c79e322fSMiklos Szeredi 	}
882e5e5558eSMiklos Szeredi 	req->in.h.opcode = FUSE_GETATTR;
883e5e5558eSMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
884c79e322fSMiklos Szeredi 	req->in.numargs = 1;
885c79e322fSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
886c79e322fSMiklos Szeredi 	req->in.args[0].value = &inarg;
887e5e5558eSMiklos Szeredi 	req->out.numargs = 1;
8880e9663eeSMiklos Szeredi 	if (fc->minor < 9)
8890e9663eeSMiklos Szeredi 		req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
8900e9663eeSMiklos Szeredi 	else
891c79e322fSMiklos Szeredi 		req->out.args[0].size = sizeof(outarg);
892c79e322fSMiklos Szeredi 	req->out.args[0].value = &outarg;
893b93f858aSTejun Heo 	fuse_request_send(fc, req);
894e5e5558eSMiklos Szeredi 	err = req->out.h.error;
895e5e5558eSMiklos Szeredi 	fuse_put_request(fc, req);
896e5e5558eSMiklos Szeredi 	if (!err) {
897c79e322fSMiklos Szeredi 		if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
898e5e5558eSMiklos Szeredi 			make_bad_inode(inode);
899e5e5558eSMiklos Szeredi 			err = -EIO;
900e5e5558eSMiklos Szeredi 		} else {
901c79e322fSMiklos Szeredi 			fuse_change_attributes(inode, &outarg.attr,
902c79e322fSMiklos Szeredi 					       attr_timeout(&outarg),
9031fb69e78SMiklos Szeredi 					       attr_version);
9041fb69e78SMiklos Szeredi 			if (stat)
905c79e322fSMiklos Szeredi 				fuse_fillattr(inode, &outarg.attr, stat);
906e5e5558eSMiklos Szeredi 		}
907e5e5558eSMiklos Szeredi 	}
908e5e5558eSMiklos Szeredi 	return err;
909e5e5558eSMiklos Szeredi }
910e5e5558eSMiklos Szeredi 
911bcb4be80SMiklos Szeredi int fuse_update_attributes(struct inode *inode, struct kstat *stat,
912bcb4be80SMiklos Szeredi 			   struct file *file, bool *refreshed)
913bcb4be80SMiklos Szeredi {
914bcb4be80SMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
915bcb4be80SMiklos Szeredi 	int err;
916bcb4be80SMiklos Szeredi 	bool r;
917bcb4be80SMiklos Szeredi 
918bcb4be80SMiklos Szeredi 	if (fi->i_time < get_jiffies_64()) {
919bcb4be80SMiklos Szeredi 		r = true;
920bcb4be80SMiklos Szeredi 		err = fuse_do_getattr(inode, stat, file);
921bcb4be80SMiklos Szeredi 	} else {
922bcb4be80SMiklos Szeredi 		r = false;
923bcb4be80SMiklos Szeredi 		err = 0;
924bcb4be80SMiklos Szeredi 		if (stat) {
925bcb4be80SMiklos Szeredi 			generic_fillattr(inode, stat);
926bcb4be80SMiklos Szeredi 			stat->mode = fi->orig_i_mode;
92745c72cd7SPavel Shilovsky 			stat->ino = fi->orig_ino;
928bcb4be80SMiklos Szeredi 		}
929bcb4be80SMiklos Szeredi 	}
930bcb4be80SMiklos Szeredi 
931bcb4be80SMiklos Szeredi 	if (refreshed != NULL)
932bcb4be80SMiklos Szeredi 		*refreshed = r;
933bcb4be80SMiklos Szeredi 
934bcb4be80SMiklos Szeredi 	return err;
935bcb4be80SMiklos Szeredi }
936bcb4be80SMiklos Szeredi 
9373b463ae0SJohn Muir int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid,
938451d0f59SJohn Muir 			     u64 child_nodeid, struct qstr *name)
9393b463ae0SJohn Muir {
9403b463ae0SJohn Muir 	int err = -ENOTDIR;
9413b463ae0SJohn Muir 	struct inode *parent;
9423b463ae0SJohn Muir 	struct dentry *dir;
9433b463ae0SJohn Muir 	struct dentry *entry;
9443b463ae0SJohn Muir 
9453b463ae0SJohn Muir 	parent = ilookup5(sb, parent_nodeid, fuse_inode_eq, &parent_nodeid);
9463b463ae0SJohn Muir 	if (!parent)
9473b463ae0SJohn Muir 		return -ENOENT;
9483b463ae0SJohn Muir 
9493b463ae0SJohn Muir 	mutex_lock(&parent->i_mutex);
9503b463ae0SJohn Muir 	if (!S_ISDIR(parent->i_mode))
9513b463ae0SJohn Muir 		goto unlock;
9523b463ae0SJohn Muir 
9533b463ae0SJohn Muir 	err = -ENOENT;
9543b463ae0SJohn Muir 	dir = d_find_alias(parent);
9553b463ae0SJohn Muir 	if (!dir)
9563b463ae0SJohn Muir 		goto unlock;
9573b463ae0SJohn Muir 
9583b463ae0SJohn Muir 	entry = d_lookup(dir, name);
9593b463ae0SJohn Muir 	dput(dir);
9603b463ae0SJohn Muir 	if (!entry)
9613b463ae0SJohn Muir 		goto unlock;
9623b463ae0SJohn Muir 
9633b463ae0SJohn Muir 	fuse_invalidate_attr(parent);
9643b463ae0SJohn Muir 	fuse_invalidate_entry(entry);
965451d0f59SJohn Muir 
966451d0f59SJohn Muir 	if (child_nodeid != 0 && entry->d_inode) {
967451d0f59SJohn Muir 		mutex_lock(&entry->d_inode->i_mutex);
968451d0f59SJohn Muir 		if (get_node_id(entry->d_inode) != child_nodeid) {
969451d0f59SJohn Muir 			err = -ENOENT;
970451d0f59SJohn Muir 			goto badentry;
971451d0f59SJohn Muir 		}
972451d0f59SJohn Muir 		if (d_mountpoint(entry)) {
973451d0f59SJohn Muir 			err = -EBUSY;
974451d0f59SJohn Muir 			goto badentry;
975451d0f59SJohn Muir 		}
976451d0f59SJohn Muir 		if (S_ISDIR(entry->d_inode->i_mode)) {
977451d0f59SJohn Muir 			shrink_dcache_parent(entry);
978451d0f59SJohn Muir 			if (!simple_empty(entry)) {
979451d0f59SJohn Muir 				err = -ENOTEMPTY;
980451d0f59SJohn Muir 				goto badentry;
981451d0f59SJohn Muir 			}
982451d0f59SJohn Muir 			entry->d_inode->i_flags |= S_DEAD;
983451d0f59SJohn Muir 		}
984451d0f59SJohn Muir 		dont_mount(entry);
985451d0f59SJohn Muir 		clear_nlink(entry->d_inode);
9863b463ae0SJohn Muir 		err = 0;
987451d0f59SJohn Muir  badentry:
988451d0f59SJohn Muir 		mutex_unlock(&entry->d_inode->i_mutex);
989451d0f59SJohn Muir 		if (!err)
990451d0f59SJohn Muir 			d_delete(entry);
991451d0f59SJohn Muir 	} else {
992451d0f59SJohn Muir 		err = 0;
993451d0f59SJohn Muir 	}
994451d0f59SJohn Muir 	dput(entry);
9953b463ae0SJohn Muir 
9963b463ae0SJohn Muir  unlock:
9973b463ae0SJohn Muir 	mutex_unlock(&parent->i_mutex);
9983b463ae0SJohn Muir 	iput(parent);
9993b463ae0SJohn Muir 	return err;
10003b463ae0SJohn Muir }
10013b463ae0SJohn Muir 
100287729a55SMiklos Szeredi /*
100387729a55SMiklos Szeredi  * Calling into a user-controlled filesystem gives the filesystem
1004c2132c1bSAnatol Pomozov  * daemon ptrace-like capabilities over the current process.  This
100587729a55SMiklos Szeredi  * means, that the filesystem daemon is able to record the exact
100687729a55SMiklos Szeredi  * filesystem operations performed, and can also control the behavior
100787729a55SMiklos Szeredi  * of the requester process in otherwise impossible ways.  For example
100887729a55SMiklos Szeredi  * it can delay the operation for arbitrary length of time allowing
100987729a55SMiklos Szeredi  * DoS against the requester.
101087729a55SMiklos Szeredi  *
101187729a55SMiklos Szeredi  * For this reason only those processes can call into the filesystem,
101287729a55SMiklos Szeredi  * for which the owner of the mount has ptrace privilege.  This
101387729a55SMiklos Szeredi  * excludes processes started by other users, suid or sgid processes.
101487729a55SMiklos Szeredi  */
1015c2132c1bSAnatol Pomozov int fuse_allow_current_process(struct fuse_conn *fc)
101687729a55SMiklos Szeredi {
1017c69e8d9cSDavid Howells 	const struct cred *cred;
1018c69e8d9cSDavid Howells 
101987729a55SMiklos Szeredi 	if (fc->flags & FUSE_ALLOW_OTHER)
102087729a55SMiklos Szeredi 		return 1;
102187729a55SMiklos Szeredi 
1022c2132c1bSAnatol Pomozov 	cred = current_cred();
1023499dcf20SEric W. Biederman 	if (uid_eq(cred->euid, fc->user_id) &&
1024499dcf20SEric W. Biederman 	    uid_eq(cred->suid, fc->user_id) &&
1025499dcf20SEric W. Biederman 	    uid_eq(cred->uid,  fc->user_id) &&
1026499dcf20SEric W. Biederman 	    gid_eq(cred->egid, fc->group_id) &&
1027499dcf20SEric W. Biederman 	    gid_eq(cred->sgid, fc->group_id) &&
1028499dcf20SEric W. Biederman 	    gid_eq(cred->gid,  fc->group_id))
1029c2132c1bSAnatol Pomozov 		return 1;
103087729a55SMiklos Szeredi 
1031c2132c1bSAnatol Pomozov 	return 0;
103287729a55SMiklos Szeredi }
103387729a55SMiklos Szeredi 
103431d40d74SMiklos Szeredi static int fuse_access(struct inode *inode, int mask)
103531d40d74SMiklos Szeredi {
103631d40d74SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
103731d40d74SMiklos Szeredi 	struct fuse_req *req;
103831d40d74SMiklos Szeredi 	struct fuse_access_in inarg;
103931d40d74SMiklos Szeredi 	int err;
104031d40d74SMiklos Szeredi 
1041698fa1d1SMiklos Szeredi 	BUG_ON(mask & MAY_NOT_BLOCK);
1042698fa1d1SMiklos Szeredi 
104331d40d74SMiklos Szeredi 	if (fc->no_access)
104431d40d74SMiklos Szeredi 		return 0;
104531d40d74SMiklos Szeredi 
1046b111c8c0SMaxim Patlasov 	req = fuse_get_req_nopages(fc);
1047ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1048ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
104931d40d74SMiklos Szeredi 
105031d40d74SMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
1051e6305c43SAl Viro 	inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC);
105231d40d74SMiklos Szeredi 	req->in.h.opcode = FUSE_ACCESS;
105331d40d74SMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
105431d40d74SMiklos Szeredi 	req->in.numargs = 1;
105531d40d74SMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
105631d40d74SMiklos Szeredi 	req->in.args[0].value = &inarg;
1057b93f858aSTejun Heo 	fuse_request_send(fc, req);
105831d40d74SMiklos Szeredi 	err = req->out.h.error;
105931d40d74SMiklos Szeredi 	fuse_put_request(fc, req);
106031d40d74SMiklos Szeredi 	if (err == -ENOSYS) {
106131d40d74SMiklos Szeredi 		fc->no_access = 1;
106231d40d74SMiklos Szeredi 		err = 0;
106331d40d74SMiklos Szeredi 	}
106431d40d74SMiklos Szeredi 	return err;
106531d40d74SMiklos Szeredi }
106631d40d74SMiklos Szeredi 
106710556cb2SAl Viro static int fuse_perm_getattr(struct inode *inode, int mask)
106819690ddbSMiklos Szeredi {
106910556cb2SAl Viro 	if (mask & MAY_NOT_BLOCK)
107019690ddbSMiklos Szeredi 		return -ECHILD;
107119690ddbSMiklos Szeredi 
107219690ddbSMiklos Szeredi 	return fuse_do_getattr(inode, NULL, NULL);
107319690ddbSMiklos Szeredi }
107419690ddbSMiklos Szeredi 
10756f9f1180SMiklos Szeredi /*
10766f9f1180SMiklos Szeredi  * Check permission.  The two basic access models of FUSE are:
10776f9f1180SMiklos Szeredi  *
10786f9f1180SMiklos Szeredi  * 1) Local access checking ('default_permissions' mount option) based
10796f9f1180SMiklos Szeredi  * on file mode.  This is the plain old disk filesystem permission
10806f9f1180SMiklos Szeredi  * modell.
10816f9f1180SMiklos Szeredi  *
10826f9f1180SMiklos Szeredi  * 2) "Remote" access checking, where server is responsible for
10836f9f1180SMiklos Szeredi  * checking permission in each inode operation.  An exception to this
10846f9f1180SMiklos Szeredi  * is if ->permission() was invoked from sys_access() in which case an
10856f9f1180SMiklos Szeredi  * access request is sent.  Execute permission is still checked
10866f9f1180SMiklos Szeredi  * locally based on file mode.
10876f9f1180SMiklos Szeredi  */
108810556cb2SAl Viro static int fuse_permission(struct inode *inode, int mask)
1089e5e5558eSMiklos Szeredi {
1090e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1091244f6385SMiklos Szeredi 	bool refreshed = false;
1092244f6385SMiklos Szeredi 	int err = 0;
1093e5e5558eSMiklos Szeredi 
1094c2132c1bSAnatol Pomozov 	if (!fuse_allow_current_process(fc))
1095e5e5558eSMiklos Szeredi 		return -EACCES;
1096244f6385SMiklos Szeredi 
1097244f6385SMiklos Szeredi 	/*
1098e8e96157SMiklos Szeredi 	 * If attributes are needed, refresh them before proceeding
1099244f6385SMiklos Szeredi 	 */
1100e8e96157SMiklos Szeredi 	if ((fc->flags & FUSE_DEFAULT_PERMISSIONS) ||
1101e8e96157SMiklos Szeredi 	    ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
110219690ddbSMiklos Szeredi 		struct fuse_inode *fi = get_fuse_inode(inode);
110319690ddbSMiklos Szeredi 
110419690ddbSMiklos Szeredi 		if (fi->i_time < get_jiffies_64()) {
110519690ddbSMiklos Szeredi 			refreshed = true;
110619690ddbSMiklos Szeredi 
110710556cb2SAl Viro 			err = fuse_perm_getattr(inode, mask);
1108244f6385SMiklos Szeredi 			if (err)
1109244f6385SMiklos Szeredi 				return err;
11101fb69e78SMiklos Szeredi 		}
111119690ddbSMiklos Szeredi 	}
1112244f6385SMiklos Szeredi 
1113244f6385SMiklos Szeredi 	if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
11142830ba7fSAl Viro 		err = generic_permission(inode, mask);
11151e9a4ed9SMiklos Szeredi 
11161e9a4ed9SMiklos Szeredi 		/* If permission is denied, try to refresh file
11171e9a4ed9SMiklos Szeredi 		   attributes.  This is also needed, because the root
11181e9a4ed9SMiklos Szeredi 		   node will at first have no permissions */
1119244f6385SMiklos Szeredi 		if (err == -EACCES && !refreshed) {
112010556cb2SAl Viro 			err = fuse_perm_getattr(inode, mask);
11211e9a4ed9SMiklos Szeredi 			if (!err)
11222830ba7fSAl Viro 				err = generic_permission(inode, mask);
11231e9a4ed9SMiklos Szeredi 		}
11241e9a4ed9SMiklos Szeredi 
11256f9f1180SMiklos Szeredi 		/* Note: the opposite of the above test does not
11266f9f1180SMiklos Szeredi 		   exist.  So if permissions are revoked this won't be
11276f9f1180SMiklos Szeredi 		   noticed immediately, only after the attribute
11286f9f1180SMiklos Szeredi 		   timeout has expired */
11299cfcac81SEric Paris 	} else if (mask & (MAY_ACCESS | MAY_CHDIR)) {
1130e8e96157SMiklos Szeredi 		err = fuse_access(inode, mask);
1131e8e96157SMiklos Szeredi 	} else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
1132e8e96157SMiklos Szeredi 		if (!(inode->i_mode & S_IXUGO)) {
1133e8e96157SMiklos Szeredi 			if (refreshed)
1134e5e5558eSMiklos Szeredi 				return -EACCES;
113531d40d74SMiklos Szeredi 
113610556cb2SAl Viro 			err = fuse_perm_getattr(inode, mask);
1137e8e96157SMiklos Szeredi 			if (!err && !(inode->i_mode & S_IXUGO))
1138e8e96157SMiklos Szeredi 				return -EACCES;
1139e8e96157SMiklos Szeredi 		}
1140e5e5558eSMiklos Szeredi 	}
1141244f6385SMiklos Szeredi 	return err;
1142e5e5558eSMiklos Szeredi }
1143e5e5558eSMiklos Szeredi 
1144e5e5558eSMiklos Szeredi static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
11458d3af7f3SAl Viro 			 struct dir_context *ctx)
1146e5e5558eSMiklos Szeredi {
1147e5e5558eSMiklos Szeredi 	while (nbytes >= FUSE_NAME_OFFSET) {
1148e5e5558eSMiklos Szeredi 		struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
1149e5e5558eSMiklos Szeredi 		size_t reclen = FUSE_DIRENT_SIZE(dirent);
1150e5e5558eSMiklos Szeredi 		if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
1151e5e5558eSMiklos Szeredi 			return -EIO;
1152e5e5558eSMiklos Szeredi 		if (reclen > nbytes)
1153e5e5558eSMiklos Szeredi 			break;
1154efeb9e60SMiklos Szeredi 		if (memchr(dirent->name, '/', dirent->namelen) != NULL)
1155efeb9e60SMiklos Szeredi 			return -EIO;
1156e5e5558eSMiklos Szeredi 
11578d3af7f3SAl Viro 		if (!dir_emit(ctx, dirent->name, dirent->namelen,
11588d3af7f3SAl Viro 			       dirent->ino, dirent->type))
1159e5e5558eSMiklos Szeredi 			break;
1160e5e5558eSMiklos Szeredi 
1161e5e5558eSMiklos Szeredi 		buf += reclen;
1162e5e5558eSMiklos Szeredi 		nbytes -= reclen;
11638d3af7f3SAl Viro 		ctx->pos = dirent->off;
1164e5e5558eSMiklos Szeredi 	}
1165e5e5558eSMiklos Szeredi 
1166e5e5558eSMiklos Szeredi 	return 0;
1167e5e5558eSMiklos Szeredi }
1168e5e5558eSMiklos Szeredi 
11690b05b183SAnand V. Avati static int fuse_direntplus_link(struct file *file,
11700b05b183SAnand V. Avati 				struct fuse_direntplus *direntplus,
11710b05b183SAnand V. Avati 				u64 attr_version)
11720b05b183SAnand V. Avati {
11730b05b183SAnand V. Avati 	int err;
11740b05b183SAnand V. Avati 	struct fuse_entry_out *o = &direntplus->entry_out;
11750b05b183SAnand V. Avati 	struct fuse_dirent *dirent = &direntplus->dirent;
11760b05b183SAnand V. Avati 	struct dentry *parent = file->f_path.dentry;
11770b05b183SAnand V. Avati 	struct qstr name = QSTR_INIT(dirent->name, dirent->namelen);
11780b05b183SAnand V. Avati 	struct dentry *dentry;
11790b05b183SAnand V. Avati 	struct dentry *alias;
11800b05b183SAnand V. Avati 	struct inode *dir = parent->d_inode;
11810b05b183SAnand V. Avati 	struct fuse_conn *fc;
11820b05b183SAnand V. Avati 	struct inode *inode;
11830b05b183SAnand V. Avati 
11840b05b183SAnand V. Avati 	if (!o->nodeid) {
11850b05b183SAnand V. Avati 		/*
11860b05b183SAnand V. Avati 		 * Unlike in the case of fuse_lookup, zero nodeid does not mean
11870b05b183SAnand V. Avati 		 * ENOENT. Instead, it only means the userspace filesystem did
11880b05b183SAnand V. Avati 		 * not want to return attributes/handle for this entry.
11890b05b183SAnand V. Avati 		 *
11900b05b183SAnand V. Avati 		 * So do nothing.
11910b05b183SAnand V. Avati 		 */
11920b05b183SAnand V. Avati 		return 0;
11930b05b183SAnand V. Avati 	}
11940b05b183SAnand V. Avati 
11950b05b183SAnand V. Avati 	if (name.name[0] == '.') {
11960b05b183SAnand V. Avati 		/*
11970b05b183SAnand V. Avati 		 * We could potentially refresh the attributes of the directory
11980b05b183SAnand V. Avati 		 * and its parent?
11990b05b183SAnand V. Avati 		 */
12000b05b183SAnand V. Avati 		if (name.len == 1)
12010b05b183SAnand V. Avati 			return 0;
12020b05b183SAnand V. Avati 		if (name.name[1] == '.' && name.len == 2)
12030b05b183SAnand V. Avati 			return 0;
12040b05b183SAnand V. Avati 	}
1205a28ef45cSMiklos Szeredi 
1206a28ef45cSMiklos Szeredi 	if (invalid_nodeid(o->nodeid))
1207a28ef45cSMiklos Szeredi 		return -EIO;
1208a28ef45cSMiklos Szeredi 	if (!fuse_valid_type(o->attr.mode))
1209a28ef45cSMiklos Szeredi 		return -EIO;
1210a28ef45cSMiklos Szeredi 
12110b05b183SAnand V. Avati 	fc = get_fuse_conn(dir);
12120b05b183SAnand V. Avati 
12130b05b183SAnand V. Avati 	name.hash = full_name_hash(name.name, name.len);
12140b05b183SAnand V. Avati 	dentry = d_lookup(parent, &name);
121553ce9a33SNiels de Vos 	if (dentry) {
12160b05b183SAnand V. Avati 		inode = dentry->d_inode;
121753ce9a33SNiels de Vos 		if (!inode) {
121853ce9a33SNiels de Vos 			d_drop(dentry);
1219a28ef45cSMiklos Szeredi 		} else if (get_node_id(inode) != o->nodeid ||
1220a28ef45cSMiklos Szeredi 			   ((o->attr.mode ^ inode->i_mode) & S_IFMT)) {
122153ce9a33SNiels de Vos 			err = d_invalidate(dentry);
122253ce9a33SNiels de Vos 			if (err)
122353ce9a33SNiels de Vos 				goto out;
1224a28ef45cSMiklos Szeredi 		} else if (is_bad_inode(inode)) {
1225a28ef45cSMiklos Szeredi 			err = -EIO;
1226a28ef45cSMiklos Szeredi 			goto out;
122753ce9a33SNiels de Vos 		} else {
12280b05b183SAnand V. Avati 			struct fuse_inode *fi;
12290b05b183SAnand V. Avati 			fi = get_fuse_inode(inode);
12300b05b183SAnand V. Avati 			spin_lock(&fc->lock);
12310b05b183SAnand V. Avati 			fi->nlookup++;
12320b05b183SAnand V. Avati 			spin_unlock(&fc->lock);
12330b05b183SAnand V. Avati 
1234fa2b7213SMiklos Szeredi 			fuse_change_attributes(inode, &o->attr,
1235fa2b7213SMiklos Szeredi 					       entry_attr_timeout(o),
1236fa2b7213SMiklos Szeredi 					       attr_version);
1237fa2b7213SMiklos Szeredi 
12380b05b183SAnand V. Avati 			/*
12390b05b183SAnand V. Avati 			 * The other branch to 'found' comes via fuse_iget()
12400b05b183SAnand V. Avati 			 * which bumps nlookup inside
12410b05b183SAnand V. Avati 			 */
12420b05b183SAnand V. Avati 			goto found;
12430b05b183SAnand V. Avati 		}
12440b05b183SAnand V. Avati 		dput(dentry);
12450b05b183SAnand V. Avati 	}
12460b05b183SAnand V. Avati 
12470b05b183SAnand V. Avati 	dentry = d_alloc(parent, &name);
12480b05b183SAnand V. Avati 	err = -ENOMEM;
12490b05b183SAnand V. Avati 	if (!dentry)
12500b05b183SAnand V. Avati 		goto out;
12510b05b183SAnand V. Avati 
12520b05b183SAnand V. Avati 	inode = fuse_iget(dir->i_sb, o->nodeid, o->generation,
12530b05b183SAnand V. Avati 			  &o->attr, entry_attr_timeout(o), attr_version);
12540b05b183SAnand V. Avati 	if (!inode)
12550b05b183SAnand V. Avati 		goto out;
12560b05b183SAnand V. Avati 
1257*b70a80e7SMiklos Szeredi 	alias = d_materialise_unique(dentry, inode);
12580b05b183SAnand V. Avati 	err = PTR_ERR(alias);
12595835f339SMiklos Szeredi 	if (IS_ERR(alias))
12600b05b183SAnand V. Avati 		goto out;
12612914941eSMiklos Szeredi 
12620b05b183SAnand V. Avati 	if (alias) {
12630b05b183SAnand V. Avati 		dput(dentry);
12640b05b183SAnand V. Avati 		dentry = alias;
12650b05b183SAnand V. Avati 	}
12660b05b183SAnand V. Avati 
12670b05b183SAnand V. Avati found:
12686314efeeSMiklos Szeredi 	if (fc->readdirplus_auto)
12696314efeeSMiklos Szeredi 		set_bit(FUSE_I_INIT_RDPLUS, &get_fuse_inode(inode)->state);
12700b05b183SAnand V. Avati 	fuse_change_entry_timeout(dentry, o);
12710b05b183SAnand V. Avati 
12720b05b183SAnand V. Avati 	err = 0;
12730b05b183SAnand V. Avati out:
12740b05b183SAnand V. Avati 	dput(dentry);
12750b05b183SAnand V. Avati 	return err;
12760b05b183SAnand V. Avati }
12770b05b183SAnand V. Avati 
12780b05b183SAnand V. Avati static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file,
12798d3af7f3SAl Viro 			     struct dir_context *ctx, u64 attr_version)
12800b05b183SAnand V. Avati {
12810b05b183SAnand V. Avati 	struct fuse_direntplus *direntplus;
12820b05b183SAnand V. Avati 	struct fuse_dirent *dirent;
12830b05b183SAnand V. Avati 	size_t reclen;
12840b05b183SAnand V. Avati 	int over = 0;
12850b05b183SAnand V. Avati 	int ret;
12860b05b183SAnand V. Avati 
12870b05b183SAnand V. Avati 	while (nbytes >= FUSE_NAME_OFFSET_DIRENTPLUS) {
12880b05b183SAnand V. Avati 		direntplus = (struct fuse_direntplus *) buf;
12890b05b183SAnand V. Avati 		dirent = &direntplus->dirent;
12900b05b183SAnand V. Avati 		reclen = FUSE_DIRENTPLUS_SIZE(direntplus);
12910b05b183SAnand V. Avati 
12920b05b183SAnand V. Avati 		if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
12930b05b183SAnand V. Avati 			return -EIO;
12940b05b183SAnand V. Avati 		if (reclen > nbytes)
12950b05b183SAnand V. Avati 			break;
1296efeb9e60SMiklos Szeredi 		if (memchr(dirent->name, '/', dirent->namelen) != NULL)
1297efeb9e60SMiklos Szeredi 			return -EIO;
12980b05b183SAnand V. Avati 
12990b05b183SAnand V. Avati 		if (!over) {
13000b05b183SAnand V. Avati 			/* We fill entries into dstbuf only as much as
13010b05b183SAnand V. Avati 			   it can hold. But we still continue iterating
13020b05b183SAnand V. Avati 			   over remaining entries to link them. If not,
13030b05b183SAnand V. Avati 			   we need to send a FORGET for each of those
13040b05b183SAnand V. Avati 			   which we did not link.
13050b05b183SAnand V. Avati 			*/
13068d3af7f3SAl Viro 			over = !dir_emit(ctx, dirent->name, dirent->namelen,
13078d3af7f3SAl Viro 				       dirent->ino, dirent->type);
13088d3af7f3SAl Viro 			ctx->pos = dirent->off;
13090b05b183SAnand V. Avati 		}
13100b05b183SAnand V. Avati 
13110b05b183SAnand V. Avati 		buf += reclen;
13120b05b183SAnand V. Avati 		nbytes -= reclen;
13130b05b183SAnand V. Avati 
13140b05b183SAnand V. Avati 		ret = fuse_direntplus_link(file, direntplus, attr_version);
13150b05b183SAnand V. Avati 		if (ret)
13160b05b183SAnand V. Avati 			fuse_force_forget(file, direntplus->entry_out.nodeid);
13170b05b183SAnand V. Avati 	}
13180b05b183SAnand V. Avati 
13190b05b183SAnand V. Avati 	return 0;
13200b05b183SAnand V. Avati }
13210b05b183SAnand V. Avati 
13228d3af7f3SAl Viro static int fuse_readdir(struct file *file, struct dir_context *ctx)
1323e5e5558eSMiklos Szeredi {
13244582a4abSFeng Shuo 	int plus, err;
132504730fefSMiklos Szeredi 	size_t nbytes;
132604730fefSMiklos Szeredi 	struct page *page;
1327496ad9aaSAl Viro 	struct inode *inode = file_inode(file);
132804730fefSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1329248d86e8SMiklos Szeredi 	struct fuse_req *req;
13300b05b183SAnand V. Avati 	u64 attr_version = 0;
1331248d86e8SMiklos Szeredi 
1332248d86e8SMiklos Szeredi 	if (is_bad_inode(inode))
1333248d86e8SMiklos Szeredi 		return -EIO;
1334248d86e8SMiklos Szeredi 
1335b111c8c0SMaxim Patlasov 	req = fuse_get_req(fc, 1);
1336ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1337ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
1338e5e5558eSMiklos Szeredi 
133904730fefSMiklos Szeredi 	page = alloc_page(GFP_KERNEL);
134004730fefSMiklos Szeredi 	if (!page) {
134104730fefSMiklos Szeredi 		fuse_put_request(fc, req);
1342e5e5558eSMiklos Szeredi 		return -ENOMEM;
134304730fefSMiklos Szeredi 	}
13444582a4abSFeng Shuo 
13458d3af7f3SAl Viro 	plus = fuse_use_readdirplus(inode, ctx);
1346f4975c67SMiklos Szeredi 	req->out.argpages = 1;
134704730fefSMiklos Szeredi 	req->num_pages = 1;
134804730fefSMiklos Szeredi 	req->pages[0] = page;
134985f40aecSMaxim Patlasov 	req->page_descs[0].length = PAGE_SIZE;
13504582a4abSFeng Shuo 	if (plus) {
13510b05b183SAnand V. Avati 		attr_version = fuse_get_attr_version(fc);
13528d3af7f3SAl Viro 		fuse_read_fill(req, file, ctx->pos, PAGE_SIZE,
13530b05b183SAnand V. Avati 			       FUSE_READDIRPLUS);
13540b05b183SAnand V. Avati 	} else {
13558d3af7f3SAl Viro 		fuse_read_fill(req, file, ctx->pos, PAGE_SIZE,
13560b05b183SAnand V. Avati 			       FUSE_READDIR);
13570b05b183SAnand V. Avati 	}
1358b93f858aSTejun Heo 	fuse_request_send(fc, req);
1359361b1eb5SMiklos Szeredi 	nbytes = req->out.args[0].size;
136004730fefSMiklos Szeredi 	err = req->out.h.error;
136104730fefSMiklos Szeredi 	fuse_put_request(fc, req);
13620b05b183SAnand V. Avati 	if (!err) {
13634582a4abSFeng Shuo 		if (plus) {
13640b05b183SAnand V. Avati 			err = parse_dirplusfile(page_address(page), nbytes,
13658d3af7f3SAl Viro 						file, ctx,
13660b05b183SAnand V. Avati 						attr_version);
13670b05b183SAnand V. Avati 		} else {
13680b05b183SAnand V. Avati 			err = parse_dirfile(page_address(page), nbytes, file,
13698d3af7f3SAl Viro 					    ctx);
13700b05b183SAnand V. Avati 		}
13710b05b183SAnand V. Avati 	}
1372e5e5558eSMiklos Szeredi 
137304730fefSMiklos Szeredi 	__free_page(page);
1374b36c31baSMiklos Szeredi 	fuse_invalidate_attr(inode); /* atime changed */
137504730fefSMiklos Szeredi 	return err;
1376e5e5558eSMiklos Szeredi }
1377e5e5558eSMiklos Szeredi 
1378e5e5558eSMiklos Szeredi static char *read_link(struct dentry *dentry)
1379e5e5558eSMiklos Szeredi {
1380e5e5558eSMiklos Szeredi 	struct inode *inode = dentry->d_inode;
1381e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1382b111c8c0SMaxim Patlasov 	struct fuse_req *req = fuse_get_req_nopages(fc);
1383e5e5558eSMiklos Szeredi 	char *link;
1384e5e5558eSMiklos Szeredi 
1385ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1386e231c2eeSDavid Howells 		return ERR_CAST(req);
1387e5e5558eSMiklos Szeredi 
1388e5e5558eSMiklos Szeredi 	link = (char *) __get_free_page(GFP_KERNEL);
1389e5e5558eSMiklos Szeredi 	if (!link) {
1390e5e5558eSMiklos Szeredi 		link = ERR_PTR(-ENOMEM);
1391e5e5558eSMiklos Szeredi 		goto out;
1392e5e5558eSMiklos Szeredi 	}
1393e5e5558eSMiklos Szeredi 	req->in.h.opcode = FUSE_READLINK;
1394e5e5558eSMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
1395e5e5558eSMiklos Szeredi 	req->out.argvar = 1;
1396e5e5558eSMiklos Szeredi 	req->out.numargs = 1;
1397e5e5558eSMiklos Szeredi 	req->out.args[0].size = PAGE_SIZE - 1;
1398e5e5558eSMiklos Szeredi 	req->out.args[0].value = link;
1399b93f858aSTejun Heo 	fuse_request_send(fc, req);
1400e5e5558eSMiklos Szeredi 	if (req->out.h.error) {
1401e5e5558eSMiklos Szeredi 		free_page((unsigned long) link);
1402e5e5558eSMiklos Szeredi 		link = ERR_PTR(req->out.h.error);
1403e5e5558eSMiklos Szeredi 	} else
1404e5e5558eSMiklos Szeredi 		link[req->out.args[0].size] = '\0';
1405e5e5558eSMiklos Szeredi  out:
1406e5e5558eSMiklos Szeredi 	fuse_put_request(fc, req);
1407b36c31baSMiklos Szeredi 	fuse_invalidate_attr(inode); /* atime changed */
1408e5e5558eSMiklos Szeredi 	return link;
1409e5e5558eSMiklos Szeredi }
1410e5e5558eSMiklos Szeredi 
1411e5e5558eSMiklos Szeredi static void free_link(char *link)
1412e5e5558eSMiklos Szeredi {
1413e5e5558eSMiklos Szeredi 	if (!IS_ERR(link))
1414e5e5558eSMiklos Szeredi 		free_page((unsigned long) link);
1415e5e5558eSMiklos Szeredi }
1416e5e5558eSMiklos Szeredi 
1417e5e5558eSMiklos Szeredi static void *fuse_follow_link(struct dentry *dentry, struct nameidata *nd)
1418e5e5558eSMiklos Szeredi {
1419e5e5558eSMiklos Szeredi 	nd_set_link(nd, read_link(dentry));
1420e5e5558eSMiklos Szeredi 	return NULL;
1421e5e5558eSMiklos Szeredi }
1422e5e5558eSMiklos Szeredi 
1423e5e5558eSMiklos Szeredi static void fuse_put_link(struct dentry *dentry, struct nameidata *nd, void *c)
1424e5e5558eSMiklos Szeredi {
1425e5e5558eSMiklos Szeredi 	free_link(nd_get_link(nd));
1426e5e5558eSMiklos Szeredi }
1427e5e5558eSMiklos Szeredi 
1428e5e5558eSMiklos Szeredi static int fuse_dir_open(struct inode *inode, struct file *file)
1429e5e5558eSMiklos Szeredi {
143091fe96b4SMiklos Szeredi 	return fuse_open_common(inode, file, true);
1431e5e5558eSMiklos Szeredi }
1432e5e5558eSMiklos Szeredi 
1433e5e5558eSMiklos Szeredi static int fuse_dir_release(struct inode *inode, struct file *file)
1434e5e5558eSMiklos Szeredi {
14358b0797a4SMiklos Szeredi 	fuse_release_common(file, FUSE_RELEASEDIR);
14368b0797a4SMiklos Szeredi 
14378b0797a4SMiklos Szeredi 	return 0;
1438e5e5558eSMiklos Szeredi }
1439e5e5558eSMiklos Szeredi 
144002c24a82SJosef Bacik static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end,
144102c24a82SJosef Bacik 			  int datasync)
144282547981SMiklos Szeredi {
144302c24a82SJosef Bacik 	return fuse_fsync_common(file, start, end, datasync, 1);
144482547981SMiklos Szeredi }
144582547981SMiklos Szeredi 
1446b18da0c5SMiklos Szeredi static long fuse_dir_ioctl(struct file *file, unsigned int cmd,
1447b18da0c5SMiklos Szeredi 			    unsigned long arg)
1448b18da0c5SMiklos Szeredi {
1449b18da0c5SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1450b18da0c5SMiklos Szeredi 
1451b18da0c5SMiklos Szeredi 	/* FUSE_IOCTL_DIR only supported for API version >= 7.18 */
1452b18da0c5SMiklos Szeredi 	if (fc->minor < 18)
1453b18da0c5SMiklos Szeredi 		return -ENOTTY;
1454b18da0c5SMiklos Szeredi 
1455b18da0c5SMiklos Szeredi 	return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR);
1456b18da0c5SMiklos Szeredi }
1457b18da0c5SMiklos Szeredi 
1458b18da0c5SMiklos Szeredi static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd,
1459b18da0c5SMiklos Szeredi 				   unsigned long arg)
1460b18da0c5SMiklos Szeredi {
1461b18da0c5SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1462b18da0c5SMiklos Szeredi 
1463b18da0c5SMiklos Szeredi 	if (fc->minor < 18)
1464b18da0c5SMiklos Szeredi 		return -ENOTTY;
1465b18da0c5SMiklos Szeredi 
1466b18da0c5SMiklos Szeredi 	return fuse_ioctl_common(file, cmd, arg,
1467b18da0c5SMiklos Szeredi 				 FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR);
1468b18da0c5SMiklos Szeredi }
1469b18da0c5SMiklos Szeredi 
147017637cbaSMiklos Szeredi static bool update_mtime(unsigned ivalid)
147117637cbaSMiklos Szeredi {
147217637cbaSMiklos Szeredi 	/* Always update if mtime is explicitly set  */
147317637cbaSMiklos Szeredi 	if (ivalid & ATTR_MTIME_SET)
147417637cbaSMiklos Szeredi 		return true;
147517637cbaSMiklos Szeredi 
147617637cbaSMiklos Szeredi 	/* If it's an open(O_TRUNC) or an ftruncate(), don't update */
147717637cbaSMiklos Szeredi 	if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
147817637cbaSMiklos Szeredi 		return false;
147917637cbaSMiklos Szeredi 
148017637cbaSMiklos Szeredi 	/* In all other cases update */
148117637cbaSMiklos Szeredi 	return true;
148217637cbaSMiklos Szeredi }
148317637cbaSMiklos Szeredi 
1484befc649cSMiklos Szeredi static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg)
14859e6268dbSMiklos Szeredi {
14869e6268dbSMiklos Szeredi 	unsigned ivalid = iattr->ia_valid;
14879e6268dbSMiklos Szeredi 
14889e6268dbSMiklos Szeredi 	if (ivalid & ATTR_MODE)
1489befc649cSMiklos Szeredi 		arg->valid |= FATTR_MODE,   arg->mode = iattr->ia_mode;
14909e6268dbSMiklos Szeredi 	if (ivalid & ATTR_UID)
1491499dcf20SEric W. Biederman 		arg->valid |= FATTR_UID,    arg->uid = from_kuid(&init_user_ns, iattr->ia_uid);
14929e6268dbSMiklos Szeredi 	if (ivalid & ATTR_GID)
1493499dcf20SEric W. Biederman 		arg->valid |= FATTR_GID,    arg->gid = from_kgid(&init_user_ns, iattr->ia_gid);
14949e6268dbSMiklos Szeredi 	if (ivalid & ATTR_SIZE)
1495befc649cSMiklos Szeredi 		arg->valid |= FATTR_SIZE,   arg->size = iattr->ia_size;
149617637cbaSMiklos Szeredi 	if (ivalid & ATTR_ATIME) {
149717637cbaSMiklos Szeredi 		arg->valid |= FATTR_ATIME;
1498befc649cSMiklos Szeredi 		arg->atime = iattr->ia_atime.tv_sec;
149917637cbaSMiklos Szeredi 		arg->atimensec = iattr->ia_atime.tv_nsec;
150017637cbaSMiklos Szeredi 		if (!(ivalid & ATTR_ATIME_SET))
150117637cbaSMiklos Szeredi 			arg->valid |= FATTR_ATIME_NOW;
150217637cbaSMiklos Szeredi 	}
150317637cbaSMiklos Szeredi 	if ((ivalid & ATTR_MTIME) && update_mtime(ivalid)) {
150417637cbaSMiklos Szeredi 		arg->valid |= FATTR_MTIME;
1505befc649cSMiklos Szeredi 		arg->mtime = iattr->ia_mtime.tv_sec;
150617637cbaSMiklos Szeredi 		arg->mtimensec = iattr->ia_mtime.tv_nsec;
150717637cbaSMiklos Szeredi 		if (!(ivalid & ATTR_MTIME_SET))
150817637cbaSMiklos Szeredi 			arg->valid |= FATTR_MTIME_NOW;
15099e6268dbSMiklos Szeredi 	}
15109e6268dbSMiklos Szeredi }
15119e6268dbSMiklos Szeredi 
15126f9f1180SMiklos Szeredi /*
15133be5a52bSMiklos Szeredi  * Prevent concurrent writepages on inode
15143be5a52bSMiklos Szeredi  *
15153be5a52bSMiklos Szeredi  * This is done by adding a negative bias to the inode write counter
15163be5a52bSMiklos Szeredi  * and waiting for all pending writes to finish.
15173be5a52bSMiklos Szeredi  */
15183be5a52bSMiklos Szeredi void fuse_set_nowrite(struct inode *inode)
15193be5a52bSMiklos Szeredi {
15203be5a52bSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
15213be5a52bSMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
15223be5a52bSMiklos Szeredi 
15233be5a52bSMiklos Szeredi 	BUG_ON(!mutex_is_locked(&inode->i_mutex));
15243be5a52bSMiklos Szeredi 
15253be5a52bSMiklos Szeredi 	spin_lock(&fc->lock);
15263be5a52bSMiklos Szeredi 	BUG_ON(fi->writectr < 0);
15273be5a52bSMiklos Szeredi 	fi->writectr += FUSE_NOWRITE;
15283be5a52bSMiklos Szeredi 	spin_unlock(&fc->lock);
15293be5a52bSMiklos Szeredi 	wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE);
15303be5a52bSMiklos Szeredi }
15313be5a52bSMiklos Szeredi 
15323be5a52bSMiklos Szeredi /*
15333be5a52bSMiklos Szeredi  * Allow writepages on inode
15343be5a52bSMiklos Szeredi  *
15353be5a52bSMiklos Szeredi  * Remove the bias from the writecounter and send any queued
15363be5a52bSMiklos Szeredi  * writepages.
15373be5a52bSMiklos Szeredi  */
15383be5a52bSMiklos Szeredi static void __fuse_release_nowrite(struct inode *inode)
15393be5a52bSMiklos Szeredi {
15403be5a52bSMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
15413be5a52bSMiklos Szeredi 
15423be5a52bSMiklos Szeredi 	BUG_ON(fi->writectr != FUSE_NOWRITE);
15433be5a52bSMiklos Szeredi 	fi->writectr = 0;
15443be5a52bSMiklos Szeredi 	fuse_flush_writepages(inode);
15453be5a52bSMiklos Szeredi }
15463be5a52bSMiklos Szeredi 
15473be5a52bSMiklos Szeredi void fuse_release_nowrite(struct inode *inode)
15483be5a52bSMiklos Szeredi {
15493be5a52bSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
15503be5a52bSMiklos Szeredi 
15513be5a52bSMiklos Szeredi 	spin_lock(&fc->lock);
15523be5a52bSMiklos Szeredi 	__fuse_release_nowrite(inode);
15533be5a52bSMiklos Szeredi 	spin_unlock(&fc->lock);
15543be5a52bSMiklos Szeredi }
15553be5a52bSMiklos Szeredi 
15563be5a52bSMiklos Szeredi /*
15576f9f1180SMiklos Szeredi  * Set attributes, and at the same time refresh them.
15586f9f1180SMiklos Szeredi  *
15596f9f1180SMiklos Szeredi  * Truncation is slightly complicated, because the 'truncate' request
15606f9f1180SMiklos Szeredi  * may fail, in which case we don't want to touch the mapping.
15619ffbb916SMiklos Szeredi  * vmtruncate() doesn't allow for this case, so do the rlimit checking
15629ffbb916SMiklos Szeredi  * and the actual truncation by hand.
15636f9f1180SMiklos Szeredi  */
1564efb9fa9eSMaxim Patlasov int fuse_do_setattr(struct inode *inode, struct iattr *attr,
156549d4914fSMiklos Szeredi 		    struct file *file)
15669e6268dbSMiklos Szeredi {
15679e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
156806a7c3c2SMaxim Patlasov 	struct fuse_inode *fi = get_fuse_inode(inode);
15699e6268dbSMiklos Szeredi 	struct fuse_req *req;
15709e6268dbSMiklos Szeredi 	struct fuse_setattr_in inarg;
15719e6268dbSMiklos Szeredi 	struct fuse_attr_out outarg;
15723be5a52bSMiklos Szeredi 	bool is_truncate = false;
15733be5a52bSMiklos Szeredi 	loff_t oldsize;
15749e6268dbSMiklos Szeredi 	int err;
15759e6268dbSMiklos Szeredi 
1576db78b877SChristoph Hellwig 	if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS))
1577db78b877SChristoph Hellwig 		attr->ia_valid |= ATTR_FORCE;
1578db78b877SChristoph Hellwig 
15791e9a4ed9SMiklos Szeredi 	err = inode_change_ok(inode, attr);
15801e9a4ed9SMiklos Szeredi 	if (err)
15811e9a4ed9SMiklos Szeredi 		return err;
15821e9a4ed9SMiklos Szeredi 
15838d56adddSMiklos Szeredi 	if (attr->ia_valid & ATTR_OPEN) {
15848d56adddSMiklos Szeredi 		if (fc->atomic_o_trunc)
15856ff958edSMiklos Szeredi 			return 0;
15868d56adddSMiklos Szeredi 		file = NULL;
15878d56adddSMiklos Szeredi 	}
15886ff958edSMiklos Szeredi 
15892c27c65eSChristoph Hellwig 	if (attr->ia_valid & ATTR_SIZE)
15903be5a52bSMiklos Szeredi 		is_truncate = true;
15919e6268dbSMiklos Szeredi 
1592b111c8c0SMaxim Patlasov 	req = fuse_get_req_nopages(fc);
1593ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1594ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
15959e6268dbSMiklos Szeredi 
159606a7c3c2SMaxim Patlasov 	if (is_truncate) {
15973be5a52bSMiklos Szeredi 		fuse_set_nowrite(inode);
159806a7c3c2SMaxim Patlasov 		set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
159906a7c3c2SMaxim Patlasov 	}
16003be5a52bSMiklos Szeredi 
16019e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
16020e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
1603befc649cSMiklos Szeredi 	iattr_to_fattr(attr, &inarg);
160449d4914fSMiklos Szeredi 	if (file) {
160549d4914fSMiklos Szeredi 		struct fuse_file *ff = file->private_data;
160649d4914fSMiklos Szeredi 		inarg.valid |= FATTR_FH;
160749d4914fSMiklos Szeredi 		inarg.fh = ff->fh;
160849d4914fSMiklos Szeredi 	}
1609f3332114SMiklos Szeredi 	if (attr->ia_valid & ATTR_SIZE) {
1610f3332114SMiklos Szeredi 		/* For mandatory locking in truncate */
1611f3332114SMiklos Szeredi 		inarg.valid |= FATTR_LOCKOWNER;
1612f3332114SMiklos Szeredi 		inarg.lock_owner = fuse_lock_owner_id(fc, current->files);
1613f3332114SMiklos Szeredi 	}
16149e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_SETATTR;
16159e6268dbSMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
16169e6268dbSMiklos Szeredi 	req->in.numargs = 1;
16179e6268dbSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
16189e6268dbSMiklos Szeredi 	req->in.args[0].value = &inarg;
16199e6268dbSMiklos Szeredi 	req->out.numargs = 1;
16200e9663eeSMiklos Szeredi 	if (fc->minor < 9)
16210e9663eeSMiklos Szeredi 		req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
16220e9663eeSMiklos Szeredi 	else
16239e6268dbSMiklos Szeredi 		req->out.args[0].size = sizeof(outarg);
16249e6268dbSMiklos Szeredi 	req->out.args[0].value = &outarg;
1625b93f858aSTejun Heo 	fuse_request_send(fc, req);
16269e6268dbSMiklos Szeredi 	err = req->out.h.error;
16279e6268dbSMiklos Szeredi 	fuse_put_request(fc, req);
1628e00d2c2dSMiklos Szeredi 	if (err) {
1629e00d2c2dSMiklos Szeredi 		if (err == -EINTR)
1630e00d2c2dSMiklos Szeredi 			fuse_invalidate_attr(inode);
16313be5a52bSMiklos Szeredi 		goto error;
1632e00d2c2dSMiklos Szeredi 	}
1633e00d2c2dSMiklos Szeredi 
16349e6268dbSMiklos Szeredi 	if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
16359e6268dbSMiklos Szeredi 		make_bad_inode(inode);
16363be5a52bSMiklos Szeredi 		err = -EIO;
16373be5a52bSMiklos Szeredi 		goto error;
16389e6268dbSMiklos Szeredi 	}
16399e6268dbSMiklos Szeredi 
16403be5a52bSMiklos Szeredi 	spin_lock(&fc->lock);
16413be5a52bSMiklos Szeredi 	fuse_change_attributes_common(inode, &outarg.attr,
16423be5a52bSMiklos Szeredi 				      attr_timeout(&outarg));
16433be5a52bSMiklos Szeredi 	oldsize = inode->i_size;
16443be5a52bSMiklos Szeredi 	i_size_write(inode, outarg.attr.size);
16453be5a52bSMiklos Szeredi 
16463be5a52bSMiklos Szeredi 	if (is_truncate) {
16473be5a52bSMiklos Szeredi 		/* NOTE: this may release/reacquire fc->lock */
16483be5a52bSMiklos Szeredi 		__fuse_release_nowrite(inode);
16493be5a52bSMiklos Szeredi 	}
16503be5a52bSMiklos Szeredi 	spin_unlock(&fc->lock);
16513be5a52bSMiklos Szeredi 
16523be5a52bSMiklos Szeredi 	/*
16533be5a52bSMiklos Szeredi 	 * Only call invalidate_inode_pages2() after removing
16543be5a52bSMiklos Szeredi 	 * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock.
16553be5a52bSMiklos Szeredi 	 */
16563be5a52bSMiklos Szeredi 	if (S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
16577caef267SKirill A. Shutemov 		truncate_pagecache(inode, outarg.attr.size);
16583be5a52bSMiklos Szeredi 		invalidate_inode_pages2(inode->i_mapping);
16593be5a52bSMiklos Szeredi 	}
16603be5a52bSMiklos Szeredi 
166106a7c3c2SMaxim Patlasov 	clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
1662e00d2c2dSMiklos Szeredi 	return 0;
16633be5a52bSMiklos Szeredi 
16643be5a52bSMiklos Szeredi error:
16653be5a52bSMiklos Szeredi 	if (is_truncate)
16663be5a52bSMiklos Szeredi 		fuse_release_nowrite(inode);
16673be5a52bSMiklos Szeredi 
166806a7c3c2SMaxim Patlasov 	clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
16693be5a52bSMiklos Szeredi 	return err;
16709e6268dbSMiklos Szeredi }
16719e6268dbSMiklos Szeredi 
167249d4914fSMiklos Szeredi static int fuse_setattr(struct dentry *entry, struct iattr *attr)
167349d4914fSMiklos Szeredi {
1674efb9fa9eSMaxim Patlasov 	struct inode *inode = entry->d_inode;
1675efb9fa9eSMaxim Patlasov 
1676efb9fa9eSMaxim Patlasov 	if (!fuse_allow_current_process(get_fuse_conn(inode)))
1677efb9fa9eSMaxim Patlasov 		return -EACCES;
1678efb9fa9eSMaxim Patlasov 
167949d4914fSMiklos Szeredi 	if (attr->ia_valid & ATTR_FILE)
1680efb9fa9eSMaxim Patlasov 		return fuse_do_setattr(inode, attr, attr->ia_file);
168149d4914fSMiklos Szeredi 	else
1682efb9fa9eSMaxim Patlasov 		return fuse_do_setattr(inode, attr, NULL);
168349d4914fSMiklos Szeredi }
168449d4914fSMiklos Szeredi 
1685e5e5558eSMiklos Szeredi static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
1686e5e5558eSMiklos Szeredi 			struct kstat *stat)
1687e5e5558eSMiklos Szeredi {
1688e5e5558eSMiklos Szeredi 	struct inode *inode = entry->d_inode;
1689244f6385SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1690244f6385SMiklos Szeredi 
1691c2132c1bSAnatol Pomozov 	if (!fuse_allow_current_process(fc))
1692244f6385SMiklos Szeredi 		return -EACCES;
1693244f6385SMiklos Szeredi 
1694bcb4be80SMiklos Szeredi 	return fuse_update_attributes(inode, stat, NULL, NULL);
1695e5e5558eSMiklos Szeredi }
1696e5e5558eSMiklos Szeredi 
169792a8780eSMiklos Szeredi static int fuse_setxattr(struct dentry *entry, const char *name,
169892a8780eSMiklos Szeredi 			 const void *value, size_t size, int flags)
169992a8780eSMiklos Szeredi {
170092a8780eSMiklos Szeredi 	struct inode *inode = entry->d_inode;
170192a8780eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
170292a8780eSMiklos Szeredi 	struct fuse_req *req;
170392a8780eSMiklos Szeredi 	struct fuse_setxattr_in inarg;
170492a8780eSMiklos Szeredi 	int err;
170592a8780eSMiklos Szeredi 
170692a8780eSMiklos Szeredi 	if (fc->no_setxattr)
170792a8780eSMiklos Szeredi 		return -EOPNOTSUPP;
170892a8780eSMiklos Szeredi 
1709b111c8c0SMaxim Patlasov 	req = fuse_get_req_nopages(fc);
1710ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1711ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
171292a8780eSMiklos Szeredi 
171392a8780eSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
171492a8780eSMiklos Szeredi 	inarg.size = size;
171592a8780eSMiklos Szeredi 	inarg.flags = flags;
171692a8780eSMiklos Szeredi 	req->in.h.opcode = FUSE_SETXATTR;
171792a8780eSMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
171892a8780eSMiklos Szeredi 	req->in.numargs = 3;
171992a8780eSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
172092a8780eSMiklos Szeredi 	req->in.args[0].value = &inarg;
172192a8780eSMiklos Szeredi 	req->in.args[1].size = strlen(name) + 1;
172292a8780eSMiklos Szeredi 	req->in.args[1].value = name;
172392a8780eSMiklos Szeredi 	req->in.args[2].size = size;
172492a8780eSMiklos Szeredi 	req->in.args[2].value = value;
1725b93f858aSTejun Heo 	fuse_request_send(fc, req);
172692a8780eSMiklos Szeredi 	err = req->out.h.error;
172792a8780eSMiklos Szeredi 	fuse_put_request(fc, req);
172892a8780eSMiklos Szeredi 	if (err == -ENOSYS) {
172992a8780eSMiklos Szeredi 		fc->no_setxattr = 1;
173092a8780eSMiklos Szeredi 		err = -EOPNOTSUPP;
173192a8780eSMiklos Szeredi 	}
1732d331a415SAnand Avati 	if (!err)
1733d331a415SAnand Avati 		fuse_invalidate_attr(inode);
173492a8780eSMiklos Szeredi 	return err;
173592a8780eSMiklos Szeredi }
173692a8780eSMiklos Szeredi 
173792a8780eSMiklos Szeredi static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
173892a8780eSMiklos Szeredi 			     void *value, size_t size)
173992a8780eSMiklos Szeredi {
174092a8780eSMiklos Szeredi 	struct inode *inode = entry->d_inode;
174192a8780eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
174292a8780eSMiklos Szeredi 	struct fuse_req *req;
174392a8780eSMiklos Szeredi 	struct fuse_getxattr_in inarg;
174492a8780eSMiklos Szeredi 	struct fuse_getxattr_out outarg;
174592a8780eSMiklos Szeredi 	ssize_t ret;
174692a8780eSMiklos Szeredi 
174792a8780eSMiklos Szeredi 	if (fc->no_getxattr)
174892a8780eSMiklos Szeredi 		return -EOPNOTSUPP;
174992a8780eSMiklos Szeredi 
1750b111c8c0SMaxim Patlasov 	req = fuse_get_req_nopages(fc);
1751ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1752ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
175392a8780eSMiklos Szeredi 
175492a8780eSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
175592a8780eSMiklos Szeredi 	inarg.size = size;
175692a8780eSMiklos Szeredi 	req->in.h.opcode = FUSE_GETXATTR;
175792a8780eSMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
175892a8780eSMiklos Szeredi 	req->in.numargs = 2;
175992a8780eSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
176092a8780eSMiklos Szeredi 	req->in.args[0].value = &inarg;
176192a8780eSMiklos Szeredi 	req->in.args[1].size = strlen(name) + 1;
176292a8780eSMiklos Szeredi 	req->in.args[1].value = name;
176392a8780eSMiklos Szeredi 	/* This is really two different operations rolled into one */
176492a8780eSMiklos Szeredi 	req->out.numargs = 1;
176592a8780eSMiklos Szeredi 	if (size) {
176692a8780eSMiklos Szeredi 		req->out.argvar = 1;
176792a8780eSMiklos Szeredi 		req->out.args[0].size = size;
176892a8780eSMiklos Szeredi 		req->out.args[0].value = value;
176992a8780eSMiklos Szeredi 	} else {
177092a8780eSMiklos Szeredi 		req->out.args[0].size = sizeof(outarg);
177192a8780eSMiklos Szeredi 		req->out.args[0].value = &outarg;
177292a8780eSMiklos Szeredi 	}
1773b93f858aSTejun Heo 	fuse_request_send(fc, req);
177492a8780eSMiklos Szeredi 	ret = req->out.h.error;
177592a8780eSMiklos Szeredi 	if (!ret)
177692a8780eSMiklos Szeredi 		ret = size ? req->out.args[0].size : outarg.size;
177792a8780eSMiklos Szeredi 	else {
177892a8780eSMiklos Szeredi 		if (ret == -ENOSYS) {
177992a8780eSMiklos Szeredi 			fc->no_getxattr = 1;
178092a8780eSMiklos Szeredi 			ret = -EOPNOTSUPP;
178192a8780eSMiklos Szeredi 		}
178292a8780eSMiklos Szeredi 	}
178392a8780eSMiklos Szeredi 	fuse_put_request(fc, req);
178492a8780eSMiklos Szeredi 	return ret;
178592a8780eSMiklos Szeredi }
178692a8780eSMiklos Szeredi 
178792a8780eSMiklos Szeredi static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
178892a8780eSMiklos Szeredi {
178992a8780eSMiklos Szeredi 	struct inode *inode = entry->d_inode;
179092a8780eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
179192a8780eSMiklos Szeredi 	struct fuse_req *req;
179292a8780eSMiklos Szeredi 	struct fuse_getxattr_in inarg;
179392a8780eSMiklos Szeredi 	struct fuse_getxattr_out outarg;
179492a8780eSMiklos Szeredi 	ssize_t ret;
179592a8780eSMiklos Szeredi 
1796c2132c1bSAnatol Pomozov 	if (!fuse_allow_current_process(fc))
1797e57ac683SMiklos Szeredi 		return -EACCES;
1798e57ac683SMiklos Szeredi 
179992a8780eSMiklos Szeredi 	if (fc->no_listxattr)
180092a8780eSMiklos Szeredi 		return -EOPNOTSUPP;
180192a8780eSMiklos Szeredi 
1802b111c8c0SMaxim Patlasov 	req = fuse_get_req_nopages(fc);
1803ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1804ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
180592a8780eSMiklos Szeredi 
180692a8780eSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
180792a8780eSMiklos Szeredi 	inarg.size = size;
180892a8780eSMiklos Szeredi 	req->in.h.opcode = FUSE_LISTXATTR;
180992a8780eSMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
181092a8780eSMiklos Szeredi 	req->in.numargs = 1;
181192a8780eSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
181292a8780eSMiklos Szeredi 	req->in.args[0].value = &inarg;
181392a8780eSMiklos Szeredi 	/* This is really two different operations rolled into one */
181492a8780eSMiklos Szeredi 	req->out.numargs = 1;
181592a8780eSMiklos Szeredi 	if (size) {
181692a8780eSMiklos Szeredi 		req->out.argvar = 1;
181792a8780eSMiklos Szeredi 		req->out.args[0].size = size;
181892a8780eSMiklos Szeredi 		req->out.args[0].value = list;
181992a8780eSMiklos Szeredi 	} else {
182092a8780eSMiklos Szeredi 		req->out.args[0].size = sizeof(outarg);
182192a8780eSMiklos Szeredi 		req->out.args[0].value = &outarg;
182292a8780eSMiklos Szeredi 	}
1823b93f858aSTejun Heo 	fuse_request_send(fc, req);
182492a8780eSMiklos Szeredi 	ret = req->out.h.error;
182592a8780eSMiklos Szeredi 	if (!ret)
182692a8780eSMiklos Szeredi 		ret = size ? req->out.args[0].size : outarg.size;
182792a8780eSMiklos Szeredi 	else {
182892a8780eSMiklos Szeredi 		if (ret == -ENOSYS) {
182992a8780eSMiklos Szeredi 			fc->no_listxattr = 1;
183092a8780eSMiklos Szeredi 			ret = -EOPNOTSUPP;
183192a8780eSMiklos Szeredi 		}
183292a8780eSMiklos Szeredi 	}
183392a8780eSMiklos Szeredi 	fuse_put_request(fc, req);
183492a8780eSMiklos Szeredi 	return ret;
183592a8780eSMiklos Szeredi }
183692a8780eSMiklos Szeredi 
183792a8780eSMiklos Szeredi static int fuse_removexattr(struct dentry *entry, const char *name)
183892a8780eSMiklos Szeredi {
183992a8780eSMiklos Szeredi 	struct inode *inode = entry->d_inode;
184092a8780eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
184192a8780eSMiklos Szeredi 	struct fuse_req *req;
184292a8780eSMiklos Szeredi 	int err;
184392a8780eSMiklos Szeredi 
184492a8780eSMiklos Szeredi 	if (fc->no_removexattr)
184592a8780eSMiklos Szeredi 		return -EOPNOTSUPP;
184692a8780eSMiklos Szeredi 
1847b111c8c0SMaxim Patlasov 	req = fuse_get_req_nopages(fc);
1848ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1849ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
185092a8780eSMiklos Szeredi 
185192a8780eSMiklos Szeredi 	req->in.h.opcode = FUSE_REMOVEXATTR;
185292a8780eSMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
185392a8780eSMiklos Szeredi 	req->in.numargs = 1;
185492a8780eSMiklos Szeredi 	req->in.args[0].size = strlen(name) + 1;
185592a8780eSMiklos Szeredi 	req->in.args[0].value = name;
1856b93f858aSTejun Heo 	fuse_request_send(fc, req);
185792a8780eSMiklos Szeredi 	err = req->out.h.error;
185892a8780eSMiklos Szeredi 	fuse_put_request(fc, req);
185992a8780eSMiklos Szeredi 	if (err == -ENOSYS) {
186092a8780eSMiklos Szeredi 		fc->no_removexattr = 1;
186192a8780eSMiklos Szeredi 		err = -EOPNOTSUPP;
186292a8780eSMiklos Szeredi 	}
1863d331a415SAnand Avati 	if (!err)
1864d331a415SAnand Avati 		fuse_invalidate_attr(inode);
186592a8780eSMiklos Szeredi 	return err;
186692a8780eSMiklos Szeredi }
186792a8780eSMiklos Szeredi 
1868754661f1SArjan van de Ven static const struct inode_operations fuse_dir_inode_operations = {
1869e5e5558eSMiklos Szeredi 	.lookup		= fuse_lookup,
18709e6268dbSMiklos Szeredi 	.mkdir		= fuse_mkdir,
18719e6268dbSMiklos Szeredi 	.symlink	= fuse_symlink,
18729e6268dbSMiklos Szeredi 	.unlink		= fuse_unlink,
18739e6268dbSMiklos Szeredi 	.rmdir		= fuse_rmdir,
18749e6268dbSMiklos Szeredi 	.rename		= fuse_rename,
18759e6268dbSMiklos Szeredi 	.link		= fuse_link,
18769e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
18779e6268dbSMiklos Szeredi 	.create		= fuse_create,
1878c8ccbe03SMiklos Szeredi 	.atomic_open	= fuse_atomic_open,
18799e6268dbSMiklos Szeredi 	.mknod		= fuse_mknod,
1880e5e5558eSMiklos Szeredi 	.permission	= fuse_permission,
1881e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
188292a8780eSMiklos Szeredi 	.setxattr	= fuse_setxattr,
188392a8780eSMiklos Szeredi 	.getxattr	= fuse_getxattr,
188492a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
188592a8780eSMiklos Szeredi 	.removexattr	= fuse_removexattr,
1886e5e5558eSMiklos Szeredi };
1887e5e5558eSMiklos Szeredi 
18884b6f5d20SArjan van de Ven static const struct file_operations fuse_dir_operations = {
1889b6aeadedSMiklos Szeredi 	.llseek		= generic_file_llseek,
1890e5e5558eSMiklos Szeredi 	.read		= generic_read_dir,
18918d3af7f3SAl Viro 	.iterate	= fuse_readdir,
1892e5e5558eSMiklos Szeredi 	.open		= fuse_dir_open,
1893e5e5558eSMiklos Szeredi 	.release	= fuse_dir_release,
189482547981SMiklos Szeredi 	.fsync		= fuse_dir_fsync,
1895b18da0c5SMiklos Szeredi 	.unlocked_ioctl	= fuse_dir_ioctl,
1896b18da0c5SMiklos Szeredi 	.compat_ioctl	= fuse_dir_compat_ioctl,
1897e5e5558eSMiklos Szeredi };
1898e5e5558eSMiklos Szeredi 
1899754661f1SArjan van de Ven static const struct inode_operations fuse_common_inode_operations = {
19009e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
1901e5e5558eSMiklos Szeredi 	.permission	= fuse_permission,
1902e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
190392a8780eSMiklos Szeredi 	.setxattr	= fuse_setxattr,
190492a8780eSMiklos Szeredi 	.getxattr	= fuse_getxattr,
190592a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
190692a8780eSMiklos Szeredi 	.removexattr	= fuse_removexattr,
1907e5e5558eSMiklos Szeredi };
1908e5e5558eSMiklos Szeredi 
1909754661f1SArjan van de Ven static const struct inode_operations fuse_symlink_inode_operations = {
19109e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
1911e5e5558eSMiklos Szeredi 	.follow_link	= fuse_follow_link,
1912e5e5558eSMiklos Szeredi 	.put_link	= fuse_put_link,
1913e5e5558eSMiklos Szeredi 	.readlink	= generic_readlink,
1914e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
191592a8780eSMiklos Szeredi 	.setxattr	= fuse_setxattr,
191692a8780eSMiklos Szeredi 	.getxattr	= fuse_getxattr,
191792a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
191892a8780eSMiklos Szeredi 	.removexattr	= fuse_removexattr,
1919e5e5558eSMiklos Szeredi };
1920e5e5558eSMiklos Szeredi 
1921e5e5558eSMiklos Szeredi void fuse_init_common(struct inode *inode)
1922e5e5558eSMiklos Szeredi {
1923e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_common_inode_operations;
1924e5e5558eSMiklos Szeredi }
1925e5e5558eSMiklos Szeredi 
1926e5e5558eSMiklos Szeredi void fuse_init_dir(struct inode *inode)
1927e5e5558eSMiklos Szeredi {
1928e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_dir_inode_operations;
1929e5e5558eSMiklos Szeredi 	inode->i_fop = &fuse_dir_operations;
1930e5e5558eSMiklos Szeredi }
1931e5e5558eSMiklos Szeredi 
1932e5e5558eSMiklos Szeredi void fuse_init_symlink(struct inode *inode)
1933e5e5558eSMiklos Szeredi {
1934e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_symlink_inode_operations;
1935e5e5558eSMiklos Szeredi }
1936