xref: /openbmc/linux/fs/fuse/dir.c (revision 41d28bca2da4bd75a8915c1ccf2cacf7f4a2e531)
1e5e5558eSMiklos Szeredi /*
2e5e5558eSMiklos Szeredi   FUSE: Filesystem in Userspace
31729a16cSMiklos Szeredi   Copyright (C) 2001-2008  Miklos Szeredi <miklos@szeredi.hu>
4e5e5558eSMiklos Szeredi 
5e5e5558eSMiklos Szeredi   This program can be distributed under the terms of the GNU GPL.
6e5e5558eSMiklos Szeredi   See the file COPYING.
7e5e5558eSMiklos Szeredi */
8e5e5558eSMiklos Szeredi 
9e5e5558eSMiklos Szeredi #include "fuse_i.h"
10e5e5558eSMiklos Szeredi 
11e5e5558eSMiklos Szeredi #include <linux/pagemap.h>
12e5e5558eSMiklos Szeredi #include <linux/file.h>
13e5e5558eSMiklos Szeredi #include <linux/sched.h>
14e5e5558eSMiklos Szeredi #include <linux/namei.h>
1507e77dcaSMiklos Szeredi #include <linux/slab.h>
16e5e5558eSMiklos Szeredi 
178d3af7f3SAl Viro static bool fuse_use_readdirplus(struct inode *dir, struct dir_context *ctx)
184582a4abSFeng Shuo {
194582a4abSFeng Shuo 	struct fuse_conn *fc = get_fuse_conn(dir);
204582a4abSFeng Shuo 	struct fuse_inode *fi = get_fuse_inode(dir);
214582a4abSFeng Shuo 
224582a4abSFeng Shuo 	if (!fc->do_readdirplus)
234582a4abSFeng Shuo 		return false;
24634734b6SEric Wong 	if (!fc->readdirplus_auto)
25634734b6SEric Wong 		return true;
264582a4abSFeng Shuo 	if (test_and_clear_bit(FUSE_I_ADVISE_RDPLUS, &fi->state))
274582a4abSFeng Shuo 		return true;
288d3af7f3SAl Viro 	if (ctx->pos == 0)
294582a4abSFeng Shuo 		return true;
304582a4abSFeng Shuo 	return false;
314582a4abSFeng Shuo }
324582a4abSFeng Shuo 
334582a4abSFeng Shuo static void fuse_advise_use_readdirplus(struct inode *dir)
344582a4abSFeng Shuo {
354582a4abSFeng Shuo 	struct fuse_inode *fi = get_fuse_inode(dir);
364582a4abSFeng Shuo 
374582a4abSFeng Shuo 	set_bit(FUSE_I_ADVISE_RDPLUS, &fi->state);
384582a4abSFeng Shuo }
394582a4abSFeng Shuo 
400a0898cfSMiklos Szeredi #if BITS_PER_LONG >= 64
410a0898cfSMiklos Szeredi static inline void fuse_dentry_settime(struct dentry *entry, u64 time)
420a0898cfSMiklos Szeredi {
430a0898cfSMiklos Szeredi 	entry->d_time = time;
440a0898cfSMiklos Szeredi }
450a0898cfSMiklos Szeredi 
460a0898cfSMiklos Szeredi static inline u64 fuse_dentry_time(struct dentry *entry)
470a0898cfSMiklos Szeredi {
480a0898cfSMiklos Szeredi 	return entry->d_time;
490a0898cfSMiklos Szeredi }
500a0898cfSMiklos Szeredi #else
510a0898cfSMiklos Szeredi /*
520a0898cfSMiklos Szeredi  * On 32 bit archs store the high 32 bits of time in d_fsdata
530a0898cfSMiklos Szeredi  */
540a0898cfSMiklos Szeredi static void fuse_dentry_settime(struct dentry *entry, u64 time)
550a0898cfSMiklos Szeredi {
560a0898cfSMiklos Szeredi 	entry->d_time = time;
570a0898cfSMiklos Szeredi 	entry->d_fsdata = (void *) (unsigned long) (time >> 32);
580a0898cfSMiklos Szeredi }
590a0898cfSMiklos Szeredi 
600a0898cfSMiklos Szeredi static u64 fuse_dentry_time(struct dentry *entry)
610a0898cfSMiklos Szeredi {
620a0898cfSMiklos Szeredi 	return (u64) entry->d_time +
630a0898cfSMiklos Szeredi 		((u64) (unsigned long) entry->d_fsdata << 32);
640a0898cfSMiklos Szeredi }
650a0898cfSMiklos Szeredi #endif
660a0898cfSMiklos Szeredi 
676f9f1180SMiklos Szeredi /*
686f9f1180SMiklos Szeredi  * FUSE caches dentries and attributes with separate timeout.  The
696f9f1180SMiklos Szeredi  * time in jiffies until the dentry/attributes are valid is stored in
706f9f1180SMiklos Szeredi  * dentry->d_time and fuse_inode->i_time respectively.
716f9f1180SMiklos Szeredi  */
726f9f1180SMiklos Szeredi 
736f9f1180SMiklos Szeredi /*
746f9f1180SMiklos Szeredi  * Calculate the time in jiffies until a dentry/attributes are valid
756f9f1180SMiklos Szeredi  */
760a0898cfSMiklos Szeredi static u64 time_to_jiffies(unsigned long sec, unsigned long nsec)
77e5e5558eSMiklos Szeredi {
78685d16ddSMiklos Szeredi 	if (sec || nsec) {
79e5e5558eSMiklos Szeredi 		struct timespec ts = {sec, nsec};
800a0898cfSMiklos Szeredi 		return get_jiffies_64() + timespec_to_jiffies(&ts);
81685d16ddSMiklos Szeredi 	} else
820a0898cfSMiklos Szeredi 		return 0;
83e5e5558eSMiklos Szeredi }
84e5e5558eSMiklos Szeredi 
856f9f1180SMiklos Szeredi /*
866f9f1180SMiklos Szeredi  * Set dentry and possibly attribute timeouts from the lookup/mk*
876f9f1180SMiklos Szeredi  * replies
886f9f1180SMiklos Szeredi  */
891fb69e78SMiklos Szeredi static void fuse_change_entry_timeout(struct dentry *entry,
901fb69e78SMiklos Szeredi 				      struct fuse_entry_out *o)
910aa7c699SMiklos Szeredi {
920a0898cfSMiklos Szeredi 	fuse_dentry_settime(entry,
930a0898cfSMiklos Szeredi 		time_to_jiffies(o->entry_valid, o->entry_valid_nsec));
941fb69e78SMiklos Szeredi }
951fb69e78SMiklos Szeredi 
961fb69e78SMiklos Szeredi static u64 attr_timeout(struct fuse_attr_out *o)
971fb69e78SMiklos Szeredi {
981fb69e78SMiklos Szeredi 	return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
991fb69e78SMiklos Szeredi }
1001fb69e78SMiklos Szeredi 
1011fb69e78SMiklos Szeredi static u64 entry_attr_timeout(struct fuse_entry_out *o)
1021fb69e78SMiklos Szeredi {
1031fb69e78SMiklos Szeredi 	return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
1048cbdf1e6SMiklos Szeredi }
1058cbdf1e6SMiklos Szeredi 
1066f9f1180SMiklos Szeredi /*
1076f9f1180SMiklos Szeredi  * Mark the attributes as stale, so that at the next call to
1086f9f1180SMiklos Szeredi  * ->getattr() they will be fetched from userspace
1096f9f1180SMiklos Szeredi  */
1108cbdf1e6SMiklos Szeredi void fuse_invalidate_attr(struct inode *inode)
1118cbdf1e6SMiklos Szeredi {
1120a0898cfSMiklos Szeredi 	get_fuse_inode(inode)->i_time = 0;
1138cbdf1e6SMiklos Szeredi }
1148cbdf1e6SMiklos Szeredi 
115451418fcSAndrew Gallagher /**
116451418fcSAndrew Gallagher  * Mark the attributes as stale due to an atime change.  Avoid the invalidate if
117451418fcSAndrew Gallagher  * atime is not used.
118451418fcSAndrew Gallagher  */
119451418fcSAndrew Gallagher void fuse_invalidate_atime(struct inode *inode)
120451418fcSAndrew Gallagher {
121451418fcSAndrew Gallagher 	if (!IS_RDONLY(inode))
122451418fcSAndrew Gallagher 		fuse_invalidate_attr(inode);
123451418fcSAndrew Gallagher }
124451418fcSAndrew Gallagher 
1256f9f1180SMiklos Szeredi /*
1266f9f1180SMiklos Szeredi  * Just mark the entry as stale, so that a next attempt to look it up
1276f9f1180SMiklos Szeredi  * will result in a new lookup call to userspace
1286f9f1180SMiklos Szeredi  *
1296f9f1180SMiklos Szeredi  * This is called when a dentry is about to become negative and the
1306f9f1180SMiklos Szeredi  * timeout is unknown (unlink, rmdir, rename and in some cases
1316f9f1180SMiklos Szeredi  * lookup)
1326f9f1180SMiklos Szeredi  */
133dbd561d2SMiklos Szeredi void fuse_invalidate_entry_cache(struct dentry *entry)
1348cbdf1e6SMiklos Szeredi {
1350a0898cfSMiklos Szeredi 	fuse_dentry_settime(entry, 0);
1368cbdf1e6SMiklos Szeredi }
1378cbdf1e6SMiklos Szeredi 
1386f9f1180SMiklos Szeredi /*
1396f9f1180SMiklos Szeredi  * Same as fuse_invalidate_entry_cache(), but also try to remove the
1406f9f1180SMiklos Szeredi  * dentry from the hash
1416f9f1180SMiklos Szeredi  */
1428cbdf1e6SMiklos Szeredi static void fuse_invalidate_entry(struct dentry *entry)
1438cbdf1e6SMiklos Szeredi {
1448cbdf1e6SMiklos Szeredi 	d_invalidate(entry);
1458cbdf1e6SMiklos Szeredi 	fuse_invalidate_entry_cache(entry);
1460aa7c699SMiklos Szeredi }
1470aa7c699SMiklos Szeredi 
148c180eebeSMiklos Szeredi static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_req *req,
149c180eebeSMiklos Szeredi 			     u64 nodeid, struct qstr *name,
150e5e5558eSMiklos Szeredi 			     struct fuse_entry_out *outarg)
151e5e5558eSMiklos Szeredi {
1520e9663eeSMiklos Szeredi 	memset(outarg, 0, sizeof(struct fuse_entry_out));
153e5e5558eSMiklos Szeredi 	req->in.h.opcode = FUSE_LOOKUP;
154c180eebeSMiklos Szeredi 	req->in.h.nodeid = nodeid;
155e5e5558eSMiklos Szeredi 	req->in.numargs = 1;
156c180eebeSMiklos Szeredi 	req->in.args[0].size = name->len + 1;
157c180eebeSMiklos Szeredi 	req->in.args[0].value = name->name;
158e5e5558eSMiklos Szeredi 	req->out.numargs = 1;
1590e9663eeSMiklos Szeredi 	if (fc->minor < 9)
1600e9663eeSMiklos Szeredi 		req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
1610e9663eeSMiklos Szeredi 	else
162e5e5558eSMiklos Szeredi 		req->out.args[0].size = sizeof(struct fuse_entry_out);
163e5e5558eSMiklos Szeredi 	req->out.args[0].value = outarg;
164e5e5558eSMiklos Szeredi }
165e5e5558eSMiklos Szeredi 
1665c5c5e51SMiklos Szeredi u64 fuse_get_attr_version(struct fuse_conn *fc)
1677dca9fd3SMiklos Szeredi {
1687dca9fd3SMiklos Szeredi 	u64 curr_version;
1697dca9fd3SMiklos Szeredi 
1707dca9fd3SMiklos Szeredi 	/*
1717dca9fd3SMiklos Szeredi 	 * The spin lock isn't actually needed on 64bit archs, but we
1727dca9fd3SMiklos Szeredi 	 * don't yet care too much about such optimizations.
1737dca9fd3SMiklos Szeredi 	 */
1747dca9fd3SMiklos Szeredi 	spin_lock(&fc->lock);
1757dca9fd3SMiklos Szeredi 	curr_version = fc->attr_version;
1767dca9fd3SMiklos Szeredi 	spin_unlock(&fc->lock);
1777dca9fd3SMiklos Szeredi 
1787dca9fd3SMiklos Szeredi 	return curr_version;
1797dca9fd3SMiklos Szeredi }
1807dca9fd3SMiklos Szeredi 
1816f9f1180SMiklos Szeredi /*
1826f9f1180SMiklos Szeredi  * Check whether the dentry is still valid
1836f9f1180SMiklos Szeredi  *
1846f9f1180SMiklos Szeredi  * If the entry validity timeout has expired and the dentry is
1856f9f1180SMiklos Szeredi  * positive, try to redo the lookup.  If the lookup results in a
1866f9f1180SMiklos Szeredi  * different inode, then let the VFS invalidate the dentry and redo
1876f9f1180SMiklos Szeredi  * the lookup once more.  If the lookup results in the same inode,
1886f9f1180SMiklos Szeredi  * then refresh the attributes, timeouts and mark the dentry valid.
1896f9f1180SMiklos Szeredi  */
1900b728e19SAl Viro static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
191e5e5558eSMiklos Szeredi {
19234286d66SNick Piggin 	struct inode *inode;
19328420dadSMiklos Szeredi 	struct dentry *parent;
19428420dadSMiklos Szeredi 	struct fuse_conn *fc;
1956314efeeSMiklos Szeredi 	struct fuse_inode *fi;
196e2a6b952SMiklos Szeredi 	int ret;
1978cbdf1e6SMiklos Szeredi 
198e7c0a167SMiklos Szeredi 	inode = ACCESS_ONCE(entry->d_inode);
1998cbdf1e6SMiklos Szeredi 	if (inode && is_bad_inode(inode))
200e2a6b952SMiklos Szeredi 		goto invalid;
201154210ccSAnand Avati 	else if (time_before64(fuse_dentry_time(entry), get_jiffies_64()) ||
202154210ccSAnand Avati 		 (flags & LOOKUP_REVAL)) {
203e5e5558eSMiklos Szeredi 		int err;
204e5e5558eSMiklos Szeredi 		struct fuse_entry_out outarg;
2058cbdf1e6SMiklos Szeredi 		struct fuse_req *req;
20607e77dcaSMiklos Szeredi 		struct fuse_forget_link *forget;
2071fb69e78SMiklos Szeredi 		u64 attr_version;
2088cbdf1e6SMiklos Szeredi 
20950322fe7SMiklos Szeredi 		/* For negative dentries, always do a fresh lookup */
2108cbdf1e6SMiklos Szeredi 		if (!inode)
211e2a6b952SMiklos Szeredi 			goto invalid;
2128cbdf1e6SMiklos Szeredi 
213e2a6b952SMiklos Szeredi 		ret = -ECHILD;
2140b728e19SAl Viro 		if (flags & LOOKUP_RCU)
215e2a6b952SMiklos Szeredi 			goto out;
216e7c0a167SMiklos Szeredi 
2178cbdf1e6SMiklos Szeredi 		fc = get_fuse_conn(inode);
218b111c8c0SMaxim Patlasov 		req = fuse_get_req_nopages(fc);
219e2a6b952SMiklos Szeredi 		ret = PTR_ERR(req);
220ce1d5a49SMiklos Szeredi 		if (IS_ERR(req))
221e2a6b952SMiklos Szeredi 			goto out;
222e5e5558eSMiklos Szeredi 
22307e77dcaSMiklos Szeredi 		forget = fuse_alloc_forget();
22407e77dcaSMiklos Szeredi 		if (!forget) {
2252d51013eSMiklos Szeredi 			fuse_put_request(fc, req);
226e2a6b952SMiklos Szeredi 			ret = -ENOMEM;
227e2a6b952SMiklos Szeredi 			goto out;
2282d51013eSMiklos Szeredi 		}
2292d51013eSMiklos Szeredi 
2307dca9fd3SMiklos Szeredi 		attr_version = fuse_get_attr_version(fc);
2311fb69e78SMiklos Szeredi 
232e956edd0SMiklos Szeredi 		parent = dget_parent(entry);
233c180eebeSMiklos Szeredi 		fuse_lookup_init(fc, req, get_node_id(parent->d_inode),
234c180eebeSMiklos Szeredi 				 &entry->d_name, &outarg);
235b93f858aSTejun Heo 		fuse_request_send(fc, req);
236e956edd0SMiklos Szeredi 		dput(parent);
237e5e5558eSMiklos Szeredi 		err = req->out.h.error;
2382d51013eSMiklos Szeredi 		fuse_put_request(fc, req);
23950322fe7SMiklos Szeredi 		/* Zero nodeid is same as -ENOENT */
24050322fe7SMiklos Szeredi 		if (!err && !outarg.nodeid)
24150322fe7SMiklos Szeredi 			err = -ENOENT;
2429e6268dbSMiklos Szeredi 		if (!err) {
2436314efeeSMiklos Szeredi 			fi = get_fuse_inode(inode);
2449e6268dbSMiklos Szeredi 			if (outarg.nodeid != get_node_id(inode)) {
24507e77dcaSMiklos Szeredi 				fuse_queue_forget(fc, forget, outarg.nodeid, 1);
246e2a6b952SMiklos Szeredi 				goto invalid;
2479e6268dbSMiklos Szeredi 			}
2488da5ff23SMiklos Szeredi 			spin_lock(&fc->lock);
2499e6268dbSMiklos Szeredi 			fi->nlookup++;
2508da5ff23SMiklos Szeredi 			spin_unlock(&fc->lock);
2519e6268dbSMiklos Szeredi 		}
25207e77dcaSMiklos Szeredi 		kfree(forget);
2539e6268dbSMiklos Szeredi 		if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT)
254e2a6b952SMiklos Szeredi 			goto invalid;
255e5e5558eSMiklos Szeredi 
2561fb69e78SMiklos Szeredi 		fuse_change_attributes(inode, &outarg.attr,
2571fb69e78SMiklos Szeredi 				       entry_attr_timeout(&outarg),
2581fb69e78SMiklos Szeredi 				       attr_version);
2591fb69e78SMiklos Szeredi 		fuse_change_entry_timeout(entry, &outarg);
26028420dadSMiklos Szeredi 	} else if (inode) {
2616314efeeSMiklos Szeredi 		fi = get_fuse_inode(inode);
2626314efeeSMiklos Szeredi 		if (flags & LOOKUP_RCU) {
2636314efeeSMiklos Szeredi 			if (test_bit(FUSE_I_INIT_RDPLUS, &fi->state))
2646314efeeSMiklos Szeredi 				return -ECHILD;
2656314efeeSMiklos Szeredi 		} else if (test_and_clear_bit(FUSE_I_INIT_RDPLUS, &fi->state)) {
26628420dadSMiklos Szeredi 			parent = dget_parent(entry);
26728420dadSMiklos Szeredi 			fuse_advise_use_readdirplus(parent->d_inode);
26828420dadSMiklos Szeredi 			dput(parent);
269e5e5558eSMiklos Szeredi 		}
27028420dadSMiklos Szeredi 	}
271e2a6b952SMiklos Szeredi 	ret = 1;
272e2a6b952SMiklos Szeredi out:
273e2a6b952SMiklos Szeredi 	return ret;
274e2a6b952SMiklos Szeredi 
275e2a6b952SMiklos Szeredi invalid:
276e2a6b952SMiklos Szeredi 	ret = 0;
277e2a6b952SMiklos Szeredi 	goto out;
278e5e5558eSMiklos Szeredi }
279e5e5558eSMiklos Szeredi 
2808bfc016dSMiklos Szeredi static int invalid_nodeid(u64 nodeid)
2812827d0b2SMiklos Szeredi {
2822827d0b2SMiklos Szeredi 	return !nodeid || nodeid == FUSE_ROOT_ID;
2832827d0b2SMiklos Szeredi }
2842827d0b2SMiklos Szeredi 
2854269590aSAl Viro const struct dentry_operations fuse_dentry_operations = {
286e5e5558eSMiklos Szeredi 	.d_revalidate	= fuse_dentry_revalidate,
287e5e5558eSMiklos Szeredi };
288e5e5558eSMiklos Szeredi 
289a5bfffacSTimo Savola int fuse_valid_type(int m)
29039ee059aSMiklos Szeredi {
29139ee059aSMiklos Szeredi 	return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) ||
29239ee059aSMiklos Szeredi 		S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m);
29339ee059aSMiklos Szeredi }
29439ee059aSMiklos Szeredi 
295c180eebeSMiklos Szeredi int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name,
296c180eebeSMiklos Szeredi 		     struct fuse_entry_out *outarg, struct inode **inode)
297c180eebeSMiklos Szeredi {
298c180eebeSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn_super(sb);
299c180eebeSMiklos Szeredi 	struct fuse_req *req;
30007e77dcaSMiklos Szeredi 	struct fuse_forget_link *forget;
301c180eebeSMiklos Szeredi 	u64 attr_version;
302c180eebeSMiklos Szeredi 	int err;
303c180eebeSMiklos Szeredi 
304c180eebeSMiklos Szeredi 	*inode = NULL;
305c180eebeSMiklos Szeredi 	err = -ENAMETOOLONG;
306c180eebeSMiklos Szeredi 	if (name->len > FUSE_NAME_MAX)
307c180eebeSMiklos Szeredi 		goto out;
308c180eebeSMiklos Szeredi 
309b111c8c0SMaxim Patlasov 	req = fuse_get_req_nopages(fc);
310c180eebeSMiklos Szeredi 	err = PTR_ERR(req);
311c180eebeSMiklos Szeredi 	if (IS_ERR(req))
312c180eebeSMiklos Szeredi 		goto out;
313c180eebeSMiklos Szeredi 
31407e77dcaSMiklos Szeredi 	forget = fuse_alloc_forget();
31507e77dcaSMiklos Szeredi 	err = -ENOMEM;
31607e77dcaSMiklos Szeredi 	if (!forget) {
317c180eebeSMiklos Szeredi 		fuse_put_request(fc, req);
318c180eebeSMiklos Szeredi 		goto out;
319c180eebeSMiklos Szeredi 	}
320c180eebeSMiklos Szeredi 
321c180eebeSMiklos Szeredi 	attr_version = fuse_get_attr_version(fc);
322c180eebeSMiklos Szeredi 
323c180eebeSMiklos Szeredi 	fuse_lookup_init(fc, req, nodeid, name, outarg);
324b93f858aSTejun Heo 	fuse_request_send(fc, req);
325c180eebeSMiklos Szeredi 	err = req->out.h.error;
326c180eebeSMiklos Szeredi 	fuse_put_request(fc, req);
327c180eebeSMiklos Szeredi 	/* Zero nodeid is same as -ENOENT, but with valid timeout */
328c180eebeSMiklos Szeredi 	if (err || !outarg->nodeid)
329c180eebeSMiklos Szeredi 		goto out_put_forget;
330c180eebeSMiklos Szeredi 
331c180eebeSMiklos Szeredi 	err = -EIO;
332c180eebeSMiklos Szeredi 	if (!outarg->nodeid)
333c180eebeSMiklos Szeredi 		goto out_put_forget;
334c180eebeSMiklos Szeredi 	if (!fuse_valid_type(outarg->attr.mode))
335c180eebeSMiklos Szeredi 		goto out_put_forget;
336c180eebeSMiklos Szeredi 
337c180eebeSMiklos Szeredi 	*inode = fuse_iget(sb, outarg->nodeid, outarg->generation,
338c180eebeSMiklos Szeredi 			   &outarg->attr, entry_attr_timeout(outarg),
339c180eebeSMiklos Szeredi 			   attr_version);
340c180eebeSMiklos Szeredi 	err = -ENOMEM;
341c180eebeSMiklos Szeredi 	if (!*inode) {
34207e77dcaSMiklos Szeredi 		fuse_queue_forget(fc, forget, outarg->nodeid, 1);
343c180eebeSMiklos Szeredi 		goto out;
344c180eebeSMiklos Szeredi 	}
345c180eebeSMiklos Szeredi 	err = 0;
346c180eebeSMiklos Szeredi 
347c180eebeSMiklos Szeredi  out_put_forget:
34807e77dcaSMiklos Szeredi 	kfree(forget);
349c180eebeSMiklos Szeredi  out:
350c180eebeSMiklos Szeredi 	return err;
351c180eebeSMiklos Szeredi }
352c180eebeSMiklos Szeredi 
3530aa7c699SMiklos Szeredi static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
35400cd8dd3SAl Viro 				  unsigned int flags)
355e5e5558eSMiklos Szeredi {
356e5e5558eSMiklos Szeredi 	int err;
357e5e5558eSMiklos Szeredi 	struct fuse_entry_out outarg;
358c180eebeSMiklos Szeredi 	struct inode *inode;
3590de6256dSMiklos Szeredi 	struct dentry *newent;
360c180eebeSMiklos Szeredi 	bool outarg_valid = true;
361e5e5558eSMiklos Szeredi 
362c180eebeSMiklos Szeredi 	err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name,
363c180eebeSMiklos Szeredi 			       &outarg, &inode);
364c180eebeSMiklos Szeredi 	if (err == -ENOENT) {
365c180eebeSMiklos Szeredi 		outarg_valid = false;
366c180eebeSMiklos Szeredi 		err = 0;
3672d51013eSMiklos Szeredi 	}
368c180eebeSMiklos Szeredi 	if (err)
369c180eebeSMiklos Szeredi 		goto out_err;
3702d51013eSMiklos Szeredi 
371ee4e5271SMiklos Szeredi 	err = -EIO;
372c180eebeSMiklos Szeredi 	if (inode && get_node_id(inode) == FUSE_ROOT_ID)
373c180eebeSMiklos Szeredi 		goto out_iput;
374e5e5558eSMiklos Szeredi 
375*41d28bcaSAl Viro 	newent = d_splice_alias(inode, entry);
376c180eebeSMiklos Szeredi 	err = PTR_ERR(newent);
377c180eebeSMiklos Szeredi 	if (IS_ERR(newent))
3785835f339SMiklos Szeredi 		goto out_err;
379d2a85164SMiklos Szeredi 
3800de6256dSMiklos Szeredi 	entry = newent ? newent : entry;
381c180eebeSMiklos Szeredi 	if (outarg_valid)
3821fb69e78SMiklos Szeredi 		fuse_change_entry_timeout(entry, &outarg);
3838cbdf1e6SMiklos Szeredi 	else
3848cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
385c180eebeSMiklos Szeredi 
3864582a4abSFeng Shuo 	fuse_advise_use_readdirplus(dir);
3870de6256dSMiklos Szeredi 	return newent;
388c180eebeSMiklos Szeredi 
389c180eebeSMiklos Szeredi  out_iput:
390c180eebeSMiklos Szeredi 	iput(inode);
391c180eebeSMiklos Szeredi  out_err:
392c180eebeSMiklos Szeredi 	return ERR_PTR(err);
393e5e5558eSMiklos Szeredi }
394e5e5558eSMiklos Szeredi 
3956f9f1180SMiklos Szeredi /*
3966f9f1180SMiklos Szeredi  * Atomic create+open operation
3976f9f1180SMiklos Szeredi  *
3986f9f1180SMiklos Szeredi  * If the filesystem doesn't support this, then fall back to separate
3996f9f1180SMiklos Szeredi  * 'mknod' + 'open' requests.
4006f9f1180SMiklos Szeredi  */
401d9585277SAl Viro static int fuse_create_open(struct inode *dir, struct dentry *entry,
40230d90494SAl Viro 			    struct file *file, unsigned flags,
40347237687SAl Viro 			    umode_t mode, int *opened)
404fd72faacSMiklos Szeredi {
405fd72faacSMiklos Szeredi 	int err;
406fd72faacSMiklos Szeredi 	struct inode *inode;
407fd72faacSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
408fd72faacSMiklos Szeredi 	struct fuse_req *req;
40907e77dcaSMiklos Szeredi 	struct fuse_forget_link *forget;
410e0a43ddcSMiklos Szeredi 	struct fuse_create_in inarg;
411fd72faacSMiklos Szeredi 	struct fuse_open_out outopen;
412fd72faacSMiklos Szeredi 	struct fuse_entry_out outentry;
413fd72faacSMiklos Szeredi 	struct fuse_file *ff;
414fd72faacSMiklos Szeredi 
415af109bcaSMiklos Szeredi 	/* Userspace expects S_IFREG in create mode */
416af109bcaSMiklos Szeredi 	BUG_ON((mode & S_IFMT) != S_IFREG);
417af109bcaSMiklos Szeredi 
41807e77dcaSMiklos Szeredi 	forget = fuse_alloc_forget();
419c8ccbe03SMiklos Szeredi 	err = -ENOMEM;
42007e77dcaSMiklos Szeredi 	if (!forget)
421c8ccbe03SMiklos Szeredi 		goto out_err;
42251eb01e7SMiklos Szeredi 
423b111c8c0SMaxim Patlasov 	req = fuse_get_req_nopages(fc);
42451eb01e7SMiklos Szeredi 	err = PTR_ERR(req);
425ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
42651eb01e7SMiklos Szeredi 		goto out_put_forget_req;
427fd72faacSMiklos Szeredi 
428ce1d5a49SMiklos Szeredi 	err = -ENOMEM;
429acf99433STejun Heo 	ff = fuse_file_alloc(fc);
430fd72faacSMiklos Szeredi 	if (!ff)
431fd72faacSMiklos Szeredi 		goto out_put_request;
432fd72faacSMiklos Szeredi 
433e0a43ddcSMiklos Szeredi 	if (!fc->dont_mask)
434e0a43ddcSMiklos Szeredi 		mode &= ~current_umask();
435e0a43ddcSMiklos Szeredi 
436fd72faacSMiklos Szeredi 	flags &= ~O_NOCTTY;
437fd72faacSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
4380e9663eeSMiklos Szeredi 	memset(&outentry, 0, sizeof(outentry));
439fd72faacSMiklos Szeredi 	inarg.flags = flags;
440fd72faacSMiklos Szeredi 	inarg.mode = mode;
441e0a43ddcSMiklos Szeredi 	inarg.umask = current_umask();
442fd72faacSMiklos Szeredi 	req->in.h.opcode = FUSE_CREATE;
443fd72faacSMiklos Szeredi 	req->in.h.nodeid = get_node_id(dir);
444fd72faacSMiklos Szeredi 	req->in.numargs = 2;
445e0a43ddcSMiklos Szeredi 	req->in.args[0].size = fc->minor < 12 ? sizeof(struct fuse_open_in) :
446e0a43ddcSMiklos Szeredi 						sizeof(inarg);
447fd72faacSMiklos Szeredi 	req->in.args[0].value = &inarg;
448fd72faacSMiklos Szeredi 	req->in.args[1].size = entry->d_name.len + 1;
449fd72faacSMiklos Szeredi 	req->in.args[1].value = entry->d_name.name;
450fd72faacSMiklos Szeredi 	req->out.numargs = 2;
4510e9663eeSMiklos Szeredi 	if (fc->minor < 9)
4520e9663eeSMiklos Szeredi 		req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
4530e9663eeSMiklos Szeredi 	else
454fd72faacSMiklos Szeredi 		req->out.args[0].size = sizeof(outentry);
455fd72faacSMiklos Szeredi 	req->out.args[0].value = &outentry;
456fd72faacSMiklos Szeredi 	req->out.args[1].size = sizeof(outopen);
457fd72faacSMiklos Szeredi 	req->out.args[1].value = &outopen;
458b93f858aSTejun Heo 	fuse_request_send(fc, req);
459fd72faacSMiklos Szeredi 	err = req->out.h.error;
460c8ccbe03SMiklos Szeredi 	if (err)
461fd72faacSMiklos Szeredi 		goto out_free_ff;
462fd72faacSMiklos Szeredi 
463fd72faacSMiklos Szeredi 	err = -EIO;
4642827d0b2SMiklos Szeredi 	if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid))
465fd72faacSMiklos Szeredi 		goto out_free_ff;
466fd72faacSMiklos Szeredi 
46751eb01e7SMiklos Szeredi 	fuse_put_request(fc, req);
468c7b7143cSMiklos Szeredi 	ff->fh = outopen.fh;
469c7b7143cSMiklos Szeredi 	ff->nodeid = outentry.nodeid;
470c7b7143cSMiklos Szeredi 	ff->open_flags = outopen.open_flags;
471fd72faacSMiklos Szeredi 	inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
4721fb69e78SMiklos Szeredi 			  &outentry.attr, entry_attr_timeout(&outentry), 0);
473fd72faacSMiklos Szeredi 	if (!inode) {
474fd72faacSMiklos Szeredi 		flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
4758b0797a4SMiklos Szeredi 		fuse_sync_release(ff, flags);
47607e77dcaSMiklos Szeredi 		fuse_queue_forget(fc, forget, outentry.nodeid, 1);
477c8ccbe03SMiklos Szeredi 		err = -ENOMEM;
478c8ccbe03SMiklos Szeredi 		goto out_err;
479fd72faacSMiklos Szeredi 	}
48007e77dcaSMiklos Szeredi 	kfree(forget);
481fd72faacSMiklos Szeredi 	d_instantiate(entry, inode);
4821fb69e78SMiklos Szeredi 	fuse_change_entry_timeout(entry, &outentry);
4830952b2a4SMiklos Szeredi 	fuse_invalidate_attr(dir);
48430d90494SAl Viro 	err = finish_open(file, entry, generic_file_open, opened);
48530d90494SAl Viro 	if (err) {
4868b0797a4SMiklos Szeredi 		fuse_sync_release(ff, flags);
487c8ccbe03SMiklos Szeredi 	} else {
488c7b7143cSMiklos Szeredi 		file->private_data = fuse_file_get(ff);
489c7b7143cSMiklos Szeredi 		fuse_finish_open(inode, file);
490c8ccbe03SMiklos Szeredi 	}
491d9585277SAl Viro 	return err;
492fd72faacSMiklos Szeredi 
493fd72faacSMiklos Szeredi out_free_ff:
494fd72faacSMiklos Szeredi 	fuse_file_free(ff);
495fd72faacSMiklos Szeredi out_put_request:
496fd72faacSMiklos Szeredi 	fuse_put_request(fc, req);
49751eb01e7SMiklos Szeredi out_put_forget_req:
49807e77dcaSMiklos Szeredi 	kfree(forget);
499c8ccbe03SMiklos Szeredi out_err:
500d9585277SAl Viro 	return err;
501c8ccbe03SMiklos Szeredi }
502c8ccbe03SMiklos Szeredi 
503c8ccbe03SMiklos Szeredi static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t);
504d9585277SAl Viro static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
50530d90494SAl Viro 			    struct file *file, unsigned flags,
50647237687SAl Viro 			    umode_t mode, int *opened)
507c8ccbe03SMiklos Szeredi {
508c8ccbe03SMiklos Szeredi 	int err;
509c8ccbe03SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
510c8ccbe03SMiklos Szeredi 	struct dentry *res = NULL;
511c8ccbe03SMiklos Szeredi 
512c8ccbe03SMiklos Szeredi 	if (d_unhashed(entry)) {
51300cd8dd3SAl Viro 		res = fuse_lookup(dir, entry, 0);
514c8ccbe03SMiklos Szeredi 		if (IS_ERR(res))
515d9585277SAl Viro 			return PTR_ERR(res);
516c8ccbe03SMiklos Szeredi 
517c8ccbe03SMiklos Szeredi 		if (res)
518c8ccbe03SMiklos Szeredi 			entry = res;
519c8ccbe03SMiklos Szeredi 	}
520c8ccbe03SMiklos Szeredi 
521c8ccbe03SMiklos Szeredi 	if (!(flags & O_CREAT) || entry->d_inode)
522c8ccbe03SMiklos Szeredi 		goto no_open;
523c8ccbe03SMiklos Szeredi 
524c8ccbe03SMiklos Szeredi 	/* Only creates */
52547237687SAl Viro 	*opened |= FILE_CREATED;
526c8ccbe03SMiklos Szeredi 
527c8ccbe03SMiklos Szeredi 	if (fc->no_create)
528c8ccbe03SMiklos Szeredi 		goto mknod;
529c8ccbe03SMiklos Szeredi 
53030d90494SAl Viro 	err = fuse_create_open(dir, entry, file, flags, mode, opened);
531d9585277SAl Viro 	if (err == -ENOSYS) {
532c8ccbe03SMiklos Szeredi 		fc->no_create = 1;
533c8ccbe03SMiklos Szeredi 		goto mknod;
534c8ccbe03SMiklos Szeredi 	}
535c8ccbe03SMiklos Szeredi out_dput:
536c8ccbe03SMiklos Szeredi 	dput(res);
537d9585277SAl Viro 	return err;
538c8ccbe03SMiklos Szeredi 
539c8ccbe03SMiklos Szeredi mknod:
540c8ccbe03SMiklos Szeredi 	err = fuse_mknod(dir, entry, mode, 0);
541d9585277SAl Viro 	if (err)
542c8ccbe03SMiklos Szeredi 		goto out_dput;
543c8ccbe03SMiklos Szeredi no_open:
544e45198a6SAl Viro 	return finish_no_open(file, res);
545fd72faacSMiklos Szeredi }
546fd72faacSMiklos Szeredi 
5476f9f1180SMiklos Szeredi /*
5486f9f1180SMiklos Szeredi  * Code shared between mknod, mkdir, symlink and link
5496f9f1180SMiklos Szeredi  */
5509e6268dbSMiklos Szeredi static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
5519e6268dbSMiklos Szeredi 			    struct inode *dir, struct dentry *entry,
552541af6a0SAl Viro 			    umode_t mode)
5539e6268dbSMiklos Szeredi {
5549e6268dbSMiklos Szeredi 	struct fuse_entry_out outarg;
5559e6268dbSMiklos Szeredi 	struct inode *inode;
5569e6268dbSMiklos Szeredi 	int err;
55707e77dcaSMiklos Szeredi 	struct fuse_forget_link *forget;
5582d51013eSMiklos Szeredi 
55907e77dcaSMiklos Szeredi 	forget = fuse_alloc_forget();
56007e77dcaSMiklos Szeredi 	if (!forget) {
5612d51013eSMiklos Szeredi 		fuse_put_request(fc, req);
56207e77dcaSMiklos Szeredi 		return -ENOMEM;
5632d51013eSMiklos Szeredi 	}
5649e6268dbSMiklos Szeredi 
5650e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
5669e6268dbSMiklos Szeredi 	req->in.h.nodeid = get_node_id(dir);
5679e6268dbSMiklos Szeredi 	req->out.numargs = 1;
5680e9663eeSMiklos Szeredi 	if (fc->minor < 9)
5690e9663eeSMiklos Szeredi 		req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
5700e9663eeSMiklos Szeredi 	else
5719e6268dbSMiklos Szeredi 		req->out.args[0].size = sizeof(outarg);
5729e6268dbSMiklos Szeredi 	req->out.args[0].value = &outarg;
573b93f858aSTejun Heo 	fuse_request_send(fc, req);
5749e6268dbSMiklos Szeredi 	err = req->out.h.error;
5759e6268dbSMiklos Szeredi 	fuse_put_request(fc, req);
5762d51013eSMiklos Szeredi 	if (err)
5772d51013eSMiklos Szeredi 		goto out_put_forget_req;
5782d51013eSMiklos Szeredi 
57939ee059aSMiklos Szeredi 	err = -EIO;
58039ee059aSMiklos Szeredi 	if (invalid_nodeid(outarg.nodeid))
5812d51013eSMiklos Szeredi 		goto out_put_forget_req;
58239ee059aSMiklos Szeredi 
58339ee059aSMiklos Szeredi 	if ((outarg.attr.mode ^ mode) & S_IFMT)
5842d51013eSMiklos Szeredi 		goto out_put_forget_req;
58539ee059aSMiklos Szeredi 
5869e6268dbSMiklos Szeredi 	inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
5871fb69e78SMiklos Szeredi 			  &outarg.attr, entry_attr_timeout(&outarg), 0);
5889e6268dbSMiklos Szeredi 	if (!inode) {
58907e77dcaSMiklos Szeredi 		fuse_queue_forget(fc, forget, outarg.nodeid, 1);
5909e6268dbSMiklos Szeredi 		return -ENOMEM;
5919e6268dbSMiklos Szeredi 	}
59207e77dcaSMiklos Szeredi 	kfree(forget);
5939e6268dbSMiklos Szeredi 
594b70a80e7SMiklos Szeredi 	err = d_instantiate_no_diralias(entry, inode);
595b70a80e7SMiklos Szeredi 	if (err)
596b70a80e7SMiklos Szeredi 		return err;
597d2a85164SMiklos Szeredi 
5981fb69e78SMiklos Szeredi 	fuse_change_entry_timeout(entry, &outarg);
5999e6268dbSMiklos Szeredi 	fuse_invalidate_attr(dir);
6009e6268dbSMiklos Szeredi 	return 0;
60139ee059aSMiklos Szeredi 
6022d51013eSMiklos Szeredi  out_put_forget_req:
60307e77dcaSMiklos Szeredi 	kfree(forget);
60439ee059aSMiklos Szeredi 	return err;
6059e6268dbSMiklos Szeredi }
6069e6268dbSMiklos Szeredi 
6071a67aafbSAl Viro static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode,
6089e6268dbSMiklos Szeredi 		      dev_t rdev)
6099e6268dbSMiklos Szeredi {
6109e6268dbSMiklos Szeredi 	struct fuse_mknod_in inarg;
6119e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
612b111c8c0SMaxim Patlasov 	struct fuse_req *req = fuse_get_req_nopages(fc);
613ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
614ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
6159e6268dbSMiklos Szeredi 
616e0a43ddcSMiklos Szeredi 	if (!fc->dont_mask)
617e0a43ddcSMiklos Szeredi 		mode &= ~current_umask();
618e0a43ddcSMiklos Szeredi 
6199e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
6209e6268dbSMiklos Szeredi 	inarg.mode = mode;
6219e6268dbSMiklos Szeredi 	inarg.rdev = new_encode_dev(rdev);
622e0a43ddcSMiklos Szeredi 	inarg.umask = current_umask();
6239e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_MKNOD;
6249e6268dbSMiklos Szeredi 	req->in.numargs = 2;
625e0a43ddcSMiklos Szeredi 	req->in.args[0].size = fc->minor < 12 ? FUSE_COMPAT_MKNOD_IN_SIZE :
626e0a43ddcSMiklos Szeredi 						sizeof(inarg);
6279e6268dbSMiklos Szeredi 	req->in.args[0].value = &inarg;
6289e6268dbSMiklos Szeredi 	req->in.args[1].size = entry->d_name.len + 1;
6299e6268dbSMiklos Szeredi 	req->in.args[1].value = entry->d_name.name;
6309e6268dbSMiklos Szeredi 	return create_new_entry(fc, req, dir, entry, mode);
6319e6268dbSMiklos Szeredi }
6329e6268dbSMiklos Szeredi 
6334acdaf27SAl Viro static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode,
634ebfc3b49SAl Viro 		       bool excl)
6359e6268dbSMiklos Szeredi {
6369e6268dbSMiklos Szeredi 	return fuse_mknod(dir, entry, mode, 0);
6379e6268dbSMiklos Szeredi }
6389e6268dbSMiklos Szeredi 
63918bb1db3SAl Viro static int fuse_mkdir(struct inode *dir, struct dentry *entry, umode_t mode)
6409e6268dbSMiklos Szeredi {
6419e6268dbSMiklos Szeredi 	struct fuse_mkdir_in inarg;
6429e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
643b111c8c0SMaxim Patlasov 	struct fuse_req *req = fuse_get_req_nopages(fc);
644ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
645ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
6469e6268dbSMiklos Szeredi 
647e0a43ddcSMiklos Szeredi 	if (!fc->dont_mask)
648e0a43ddcSMiklos Szeredi 		mode &= ~current_umask();
649e0a43ddcSMiklos Szeredi 
6509e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
6519e6268dbSMiklos Szeredi 	inarg.mode = mode;
652e0a43ddcSMiklos Szeredi 	inarg.umask = current_umask();
6539e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_MKDIR;
6549e6268dbSMiklos Szeredi 	req->in.numargs = 2;
6559e6268dbSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
6569e6268dbSMiklos Szeredi 	req->in.args[0].value = &inarg;
6579e6268dbSMiklos Szeredi 	req->in.args[1].size = entry->d_name.len + 1;
6589e6268dbSMiklos Szeredi 	req->in.args[1].value = entry->d_name.name;
6599e6268dbSMiklos Szeredi 	return create_new_entry(fc, req, dir, entry, S_IFDIR);
6609e6268dbSMiklos Szeredi }
6619e6268dbSMiklos Szeredi 
6629e6268dbSMiklos Szeredi static int fuse_symlink(struct inode *dir, struct dentry *entry,
6639e6268dbSMiklos Szeredi 			const char *link)
6649e6268dbSMiklos Szeredi {
6659e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
6669e6268dbSMiklos Szeredi 	unsigned len = strlen(link) + 1;
667b111c8c0SMaxim Patlasov 	struct fuse_req *req = fuse_get_req_nopages(fc);
668ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
669ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
6709e6268dbSMiklos Szeredi 
6719e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_SYMLINK;
6729e6268dbSMiklos Szeredi 	req->in.numargs = 2;
6739e6268dbSMiklos Szeredi 	req->in.args[0].size = entry->d_name.len + 1;
6749e6268dbSMiklos Szeredi 	req->in.args[0].value = entry->d_name.name;
6759e6268dbSMiklos Szeredi 	req->in.args[1].size = len;
6769e6268dbSMiklos Szeredi 	req->in.args[1].value = link;
6779e6268dbSMiklos Szeredi 	return create_new_entry(fc, req, dir, entry, S_IFLNK);
6789e6268dbSMiklos Szeredi }
6799e6268dbSMiklos Szeredi 
68031f3267bSMaxim Patlasov static inline void fuse_update_ctime(struct inode *inode)
68131f3267bSMaxim Patlasov {
68231f3267bSMaxim Patlasov 	if (!IS_NOCMTIME(inode)) {
68331f3267bSMaxim Patlasov 		inode->i_ctime = current_fs_time(inode->i_sb);
68431f3267bSMaxim Patlasov 		mark_inode_dirty_sync(inode);
68531f3267bSMaxim Patlasov 	}
68631f3267bSMaxim Patlasov }
68731f3267bSMaxim Patlasov 
6889e6268dbSMiklos Szeredi static int fuse_unlink(struct inode *dir, struct dentry *entry)
6899e6268dbSMiklos Szeredi {
6909e6268dbSMiklos Szeredi 	int err;
6919e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
692b111c8c0SMaxim Patlasov 	struct fuse_req *req = fuse_get_req_nopages(fc);
693ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
694ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
6959e6268dbSMiklos Szeredi 
6969e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_UNLINK;
6979e6268dbSMiklos Szeredi 	req->in.h.nodeid = get_node_id(dir);
6989e6268dbSMiklos Szeredi 	req->in.numargs = 1;
6999e6268dbSMiklos Szeredi 	req->in.args[0].size = entry->d_name.len + 1;
7009e6268dbSMiklos Szeredi 	req->in.args[0].value = entry->d_name.name;
701b93f858aSTejun Heo 	fuse_request_send(fc, req);
7029e6268dbSMiklos Szeredi 	err = req->out.h.error;
7039e6268dbSMiklos Szeredi 	fuse_put_request(fc, req);
7049e6268dbSMiklos Szeredi 	if (!err) {
7059e6268dbSMiklos Szeredi 		struct inode *inode = entry->d_inode;
706ac45d613SMiklos Szeredi 		struct fuse_inode *fi = get_fuse_inode(inode);
7079e6268dbSMiklos Szeredi 
708ac45d613SMiklos Szeredi 		spin_lock(&fc->lock);
709ac45d613SMiklos Szeredi 		fi->attr_version = ++fc->attr_version;
710dfca7cebSMiklos Szeredi 		/*
711dfca7cebSMiklos Szeredi 		 * If i_nlink == 0 then unlink doesn't make sense, yet this can
712dfca7cebSMiklos Szeredi 		 * happen if userspace filesystem is careless.  It would be
713dfca7cebSMiklos Szeredi 		 * difficult to enforce correct nlink usage so just ignore this
714dfca7cebSMiklos Szeredi 		 * condition here
715dfca7cebSMiklos Szeredi 		 */
716dfca7cebSMiklos Szeredi 		if (inode->i_nlink > 0)
717ac45d613SMiklos Szeredi 			drop_nlink(inode);
718ac45d613SMiklos Szeredi 		spin_unlock(&fc->lock);
7199e6268dbSMiklos Szeredi 		fuse_invalidate_attr(inode);
7209e6268dbSMiklos Szeredi 		fuse_invalidate_attr(dir);
7218cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
72231f3267bSMaxim Patlasov 		fuse_update_ctime(inode);
7239e6268dbSMiklos Szeredi 	} else if (err == -EINTR)
7249e6268dbSMiklos Szeredi 		fuse_invalidate_entry(entry);
7259e6268dbSMiklos Szeredi 	return err;
7269e6268dbSMiklos Szeredi }
7279e6268dbSMiklos Szeredi 
7289e6268dbSMiklos Szeredi static int fuse_rmdir(struct inode *dir, struct dentry *entry)
7299e6268dbSMiklos Szeredi {
7309e6268dbSMiklos Szeredi 	int err;
7319e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
732b111c8c0SMaxim Patlasov 	struct fuse_req *req = fuse_get_req_nopages(fc);
733ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
734ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
7359e6268dbSMiklos Szeredi 
7369e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_RMDIR;
7379e6268dbSMiklos Szeredi 	req->in.h.nodeid = get_node_id(dir);
7389e6268dbSMiklos Szeredi 	req->in.numargs = 1;
7399e6268dbSMiklos Szeredi 	req->in.args[0].size = entry->d_name.len + 1;
7409e6268dbSMiklos Szeredi 	req->in.args[0].value = entry->d_name.name;
741b93f858aSTejun Heo 	fuse_request_send(fc, req);
7429e6268dbSMiklos Szeredi 	err = req->out.h.error;
7439e6268dbSMiklos Szeredi 	fuse_put_request(fc, req);
7449e6268dbSMiklos Szeredi 	if (!err) {
745ce71ec36SDave Hansen 		clear_nlink(entry->d_inode);
7469e6268dbSMiklos Szeredi 		fuse_invalidate_attr(dir);
7478cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
7489e6268dbSMiklos Szeredi 	} else if (err == -EINTR)
7499e6268dbSMiklos Szeredi 		fuse_invalidate_entry(entry);
7509e6268dbSMiklos Szeredi 	return err;
7519e6268dbSMiklos Szeredi }
7529e6268dbSMiklos Szeredi 
7531560c974SMiklos Szeredi static int fuse_rename_common(struct inode *olddir, struct dentry *oldent,
7541560c974SMiklos Szeredi 			      struct inode *newdir, struct dentry *newent,
7551560c974SMiklos Szeredi 			      unsigned int flags, int opcode, size_t argsize)
7569e6268dbSMiklos Szeredi {
7579e6268dbSMiklos Szeredi 	int err;
7581560c974SMiklos Szeredi 	struct fuse_rename2_in inarg;
7599e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(olddir);
7601560c974SMiklos Szeredi 	struct fuse_req *req;
761e4eaac06SSage Weil 
7621560c974SMiklos Szeredi 	req = fuse_get_req_nopages(fc);
763ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
764ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
7659e6268dbSMiklos Szeredi 
7661560c974SMiklos Szeredi 	memset(&inarg, 0, argsize);
7679e6268dbSMiklos Szeredi 	inarg.newdir = get_node_id(newdir);
7681560c974SMiklos Szeredi 	inarg.flags = flags;
7691560c974SMiklos Szeredi 	req->in.h.opcode = opcode;
7709e6268dbSMiklos Szeredi 	req->in.h.nodeid = get_node_id(olddir);
7719e6268dbSMiklos Szeredi 	req->in.numargs = 3;
7721560c974SMiklos Szeredi 	req->in.args[0].size = argsize;
7739e6268dbSMiklos Szeredi 	req->in.args[0].value = &inarg;
7749e6268dbSMiklos Szeredi 	req->in.args[1].size = oldent->d_name.len + 1;
7759e6268dbSMiklos Szeredi 	req->in.args[1].value = oldent->d_name.name;
7769e6268dbSMiklos Szeredi 	req->in.args[2].size = newent->d_name.len + 1;
7779e6268dbSMiklos Szeredi 	req->in.args[2].value = newent->d_name.name;
778b93f858aSTejun Heo 	fuse_request_send(fc, req);
7799e6268dbSMiklos Szeredi 	err = req->out.h.error;
7809e6268dbSMiklos Szeredi 	fuse_put_request(fc, req);
7819e6268dbSMiklos Szeredi 	if (!err) {
78208b63307SMiklos Szeredi 		/* ctime changes */
78308b63307SMiklos Szeredi 		fuse_invalidate_attr(oldent->d_inode);
78431f3267bSMaxim Patlasov 		fuse_update_ctime(oldent->d_inode);
78508b63307SMiklos Szeredi 
7861560c974SMiklos Szeredi 		if (flags & RENAME_EXCHANGE) {
7871560c974SMiklos Szeredi 			fuse_invalidate_attr(newent->d_inode);
7881560c974SMiklos Szeredi 			fuse_update_ctime(newent->d_inode);
7891560c974SMiklos Szeredi 		}
7901560c974SMiklos Szeredi 
7919e6268dbSMiklos Szeredi 		fuse_invalidate_attr(olddir);
7929e6268dbSMiklos Szeredi 		if (olddir != newdir)
7939e6268dbSMiklos Szeredi 			fuse_invalidate_attr(newdir);
7948cbdf1e6SMiklos Szeredi 
7958cbdf1e6SMiklos Szeredi 		/* newent will end up negative */
7961560c974SMiklos Szeredi 		if (!(flags & RENAME_EXCHANGE) && newent->d_inode) {
7975219f346SMiklos Szeredi 			fuse_invalidate_attr(newent->d_inode);
7988cbdf1e6SMiklos Szeredi 			fuse_invalidate_entry_cache(newent);
79931f3267bSMaxim Patlasov 			fuse_update_ctime(newent->d_inode);
8005219f346SMiklos Szeredi 		}
8019e6268dbSMiklos Szeredi 	} else if (err == -EINTR) {
8029e6268dbSMiklos Szeredi 		/* If request was interrupted, DEITY only knows if the
8039e6268dbSMiklos Szeredi 		   rename actually took place.  If the invalidation
8049e6268dbSMiklos Szeredi 		   fails (e.g. some process has CWD under the renamed
8059e6268dbSMiklos Szeredi 		   directory), then there can be inconsistency between
8069e6268dbSMiklos Szeredi 		   the dcache and the real filesystem.  Tough luck. */
8079e6268dbSMiklos Szeredi 		fuse_invalidate_entry(oldent);
8089e6268dbSMiklos Szeredi 		if (newent->d_inode)
8099e6268dbSMiklos Szeredi 			fuse_invalidate_entry(newent);
8109e6268dbSMiklos Szeredi 	}
8119e6268dbSMiklos Szeredi 
8129e6268dbSMiklos Szeredi 	return err;
8139e6268dbSMiklos Szeredi }
8149e6268dbSMiklos Szeredi 
8151560c974SMiklos Szeredi static int fuse_rename2(struct inode *olddir, struct dentry *oldent,
8161560c974SMiklos Szeredi 			struct inode *newdir, struct dentry *newent,
8171560c974SMiklos Szeredi 			unsigned int flags)
8181560c974SMiklos Szeredi {
8191560c974SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(olddir);
8201560c974SMiklos Szeredi 	int err;
8211560c974SMiklos Szeredi 
8221560c974SMiklos Szeredi 	if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE))
8231560c974SMiklos Szeredi 		return -EINVAL;
8241560c974SMiklos Szeredi 
8254237ba43SMiklos Szeredi 	if (flags) {
8261560c974SMiklos Szeredi 		if (fc->no_rename2 || fc->minor < 23)
8271560c974SMiklos Szeredi 			return -EINVAL;
8281560c974SMiklos Szeredi 
8291560c974SMiklos Szeredi 		err = fuse_rename_common(olddir, oldent, newdir, newent, flags,
8304237ba43SMiklos Szeredi 					 FUSE_RENAME2,
8314237ba43SMiklos Szeredi 					 sizeof(struct fuse_rename2_in));
8321560c974SMiklos Szeredi 		if (err == -ENOSYS) {
8331560c974SMiklos Szeredi 			fc->no_rename2 = 1;
8341560c974SMiklos Szeredi 			err = -EINVAL;
8351560c974SMiklos Szeredi 		}
8364237ba43SMiklos Szeredi 	} else {
8374237ba43SMiklos Szeredi 		err = fuse_rename_common(olddir, oldent, newdir, newent, 0,
8384237ba43SMiklos Szeredi 					 FUSE_RENAME,
8394237ba43SMiklos Szeredi 					 sizeof(struct fuse_rename_in));
8404237ba43SMiklos Szeredi 	}
8411560c974SMiklos Szeredi 
8424237ba43SMiklos Szeredi 	return err;
8434237ba43SMiklos Szeredi }
8444237ba43SMiklos Szeredi 
8459e6268dbSMiklos Szeredi static int fuse_link(struct dentry *entry, struct inode *newdir,
8469e6268dbSMiklos Szeredi 		     struct dentry *newent)
8479e6268dbSMiklos Szeredi {
8489e6268dbSMiklos Szeredi 	int err;
8499e6268dbSMiklos Szeredi 	struct fuse_link_in inarg;
8509e6268dbSMiklos Szeredi 	struct inode *inode = entry->d_inode;
8519e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
852b111c8c0SMaxim Patlasov 	struct fuse_req *req = fuse_get_req_nopages(fc);
853ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
854ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
8559e6268dbSMiklos Szeredi 
8569e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
8579e6268dbSMiklos Szeredi 	inarg.oldnodeid = get_node_id(inode);
8589e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_LINK;
8599e6268dbSMiklos Szeredi 	req->in.numargs = 2;
8609e6268dbSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
8619e6268dbSMiklos Szeredi 	req->in.args[0].value = &inarg;
8629e6268dbSMiklos Szeredi 	req->in.args[1].size = newent->d_name.len + 1;
8639e6268dbSMiklos Szeredi 	req->in.args[1].value = newent->d_name.name;
8649e6268dbSMiklos Szeredi 	err = create_new_entry(fc, req, newdir, newent, inode->i_mode);
8659e6268dbSMiklos Szeredi 	/* Contrary to "normal" filesystems it can happen that link
8669e6268dbSMiklos Szeredi 	   makes two "logical" inodes point to the same "physical"
8679e6268dbSMiklos Szeredi 	   inode.  We invalidate the attributes of the old one, so it
8689e6268dbSMiklos Szeredi 	   will reflect changes in the backing inode (link count,
8699e6268dbSMiklos Szeredi 	   etc.)
8709e6268dbSMiklos Szeredi 	*/
871ac45d613SMiklos Szeredi 	if (!err) {
872ac45d613SMiklos Szeredi 		struct fuse_inode *fi = get_fuse_inode(inode);
873ac45d613SMiklos Szeredi 
874ac45d613SMiklos Szeredi 		spin_lock(&fc->lock);
875ac45d613SMiklos Szeredi 		fi->attr_version = ++fc->attr_version;
876ac45d613SMiklos Szeredi 		inc_nlink(inode);
877ac45d613SMiklos Szeredi 		spin_unlock(&fc->lock);
8789e6268dbSMiklos Szeredi 		fuse_invalidate_attr(inode);
87931f3267bSMaxim Patlasov 		fuse_update_ctime(inode);
880ac45d613SMiklos Szeredi 	} else if (err == -EINTR) {
881ac45d613SMiklos Szeredi 		fuse_invalidate_attr(inode);
882ac45d613SMiklos Szeredi 	}
8839e6268dbSMiklos Szeredi 	return err;
8849e6268dbSMiklos Szeredi }
8859e6268dbSMiklos Szeredi 
8861fb69e78SMiklos Szeredi static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
8871fb69e78SMiklos Szeredi 			  struct kstat *stat)
8881fb69e78SMiklos Szeredi {
889203627bbSMiklos Szeredi 	unsigned int blkbits;
8908373200bSPavel Emelyanov 	struct fuse_conn *fc = get_fuse_conn(inode);
8918373200bSPavel Emelyanov 
8928373200bSPavel Emelyanov 	/* see the comment in fuse_change_attributes() */
893b0aa7606SMaxim Patlasov 	if (fc->writeback_cache && S_ISREG(inode->i_mode)) {
8948373200bSPavel Emelyanov 		attr->size = i_size_read(inode);
895b0aa7606SMaxim Patlasov 		attr->mtime = inode->i_mtime.tv_sec;
896b0aa7606SMaxim Patlasov 		attr->mtimensec = inode->i_mtime.tv_nsec;
89731f3267bSMaxim Patlasov 		attr->ctime = inode->i_ctime.tv_sec;
89831f3267bSMaxim Patlasov 		attr->ctimensec = inode->i_ctime.tv_nsec;
899b0aa7606SMaxim Patlasov 	}
900203627bbSMiklos Szeredi 
9011fb69e78SMiklos Szeredi 	stat->dev = inode->i_sb->s_dev;
9021fb69e78SMiklos Szeredi 	stat->ino = attr->ino;
9031fb69e78SMiklos Szeredi 	stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
9041fb69e78SMiklos Szeredi 	stat->nlink = attr->nlink;
905499dcf20SEric W. Biederman 	stat->uid = make_kuid(&init_user_ns, attr->uid);
906499dcf20SEric W. Biederman 	stat->gid = make_kgid(&init_user_ns, attr->gid);
9071fb69e78SMiklos Szeredi 	stat->rdev = inode->i_rdev;
9081fb69e78SMiklos Szeredi 	stat->atime.tv_sec = attr->atime;
9091fb69e78SMiklos Szeredi 	stat->atime.tv_nsec = attr->atimensec;
9101fb69e78SMiklos Szeredi 	stat->mtime.tv_sec = attr->mtime;
9111fb69e78SMiklos Szeredi 	stat->mtime.tv_nsec = attr->mtimensec;
9121fb69e78SMiklos Szeredi 	stat->ctime.tv_sec = attr->ctime;
9131fb69e78SMiklos Szeredi 	stat->ctime.tv_nsec = attr->ctimensec;
9141fb69e78SMiklos Szeredi 	stat->size = attr->size;
9151fb69e78SMiklos Szeredi 	stat->blocks = attr->blocks;
916203627bbSMiklos Szeredi 
917203627bbSMiklos Szeredi 	if (attr->blksize != 0)
918203627bbSMiklos Szeredi 		blkbits = ilog2(attr->blksize);
919203627bbSMiklos Szeredi 	else
920203627bbSMiklos Szeredi 		blkbits = inode->i_sb->s_blocksize_bits;
921203627bbSMiklos Szeredi 
922203627bbSMiklos Szeredi 	stat->blksize = 1 << blkbits;
9231fb69e78SMiklos Szeredi }
9241fb69e78SMiklos Szeredi 
925c79e322fSMiklos Szeredi static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
926c79e322fSMiklos Szeredi 			   struct file *file)
927e5e5558eSMiklos Szeredi {
928e5e5558eSMiklos Szeredi 	int err;
929c79e322fSMiklos Szeredi 	struct fuse_getattr_in inarg;
930c79e322fSMiklos Szeredi 	struct fuse_attr_out outarg;
931e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
9321fb69e78SMiklos Szeredi 	struct fuse_req *req;
9331fb69e78SMiklos Szeredi 	u64 attr_version;
9341fb69e78SMiklos Szeredi 
935b111c8c0SMaxim Patlasov 	req = fuse_get_req_nopages(fc);
936ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
937ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
938e5e5558eSMiklos Szeredi 
9397dca9fd3SMiklos Szeredi 	attr_version = fuse_get_attr_version(fc);
9401fb69e78SMiklos Szeredi 
941c79e322fSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
9420e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
943c79e322fSMiklos Szeredi 	/* Directories have separate file-handle space */
944c79e322fSMiklos Szeredi 	if (file && S_ISREG(inode->i_mode)) {
945c79e322fSMiklos Szeredi 		struct fuse_file *ff = file->private_data;
946c79e322fSMiklos Szeredi 
947c79e322fSMiklos Szeredi 		inarg.getattr_flags |= FUSE_GETATTR_FH;
948c79e322fSMiklos Szeredi 		inarg.fh = ff->fh;
949c79e322fSMiklos Szeredi 	}
950e5e5558eSMiklos Szeredi 	req->in.h.opcode = FUSE_GETATTR;
951e5e5558eSMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
952c79e322fSMiklos Szeredi 	req->in.numargs = 1;
953c79e322fSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
954c79e322fSMiklos Szeredi 	req->in.args[0].value = &inarg;
955e5e5558eSMiklos Szeredi 	req->out.numargs = 1;
9560e9663eeSMiklos Szeredi 	if (fc->minor < 9)
9570e9663eeSMiklos Szeredi 		req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
9580e9663eeSMiklos Szeredi 	else
959c79e322fSMiklos Szeredi 		req->out.args[0].size = sizeof(outarg);
960c79e322fSMiklos Szeredi 	req->out.args[0].value = &outarg;
961b93f858aSTejun Heo 	fuse_request_send(fc, req);
962e5e5558eSMiklos Szeredi 	err = req->out.h.error;
963e5e5558eSMiklos Szeredi 	fuse_put_request(fc, req);
964e5e5558eSMiklos Szeredi 	if (!err) {
965c79e322fSMiklos Szeredi 		if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
966e5e5558eSMiklos Szeredi 			make_bad_inode(inode);
967e5e5558eSMiklos Szeredi 			err = -EIO;
968e5e5558eSMiklos Szeredi 		} else {
969c79e322fSMiklos Szeredi 			fuse_change_attributes(inode, &outarg.attr,
970c79e322fSMiklos Szeredi 					       attr_timeout(&outarg),
9711fb69e78SMiklos Szeredi 					       attr_version);
9721fb69e78SMiklos Szeredi 			if (stat)
973c79e322fSMiklos Szeredi 				fuse_fillattr(inode, &outarg.attr, stat);
974e5e5558eSMiklos Szeredi 		}
975e5e5558eSMiklos Szeredi 	}
976e5e5558eSMiklos Szeredi 	return err;
977e5e5558eSMiklos Szeredi }
978e5e5558eSMiklos Szeredi 
979bcb4be80SMiklos Szeredi int fuse_update_attributes(struct inode *inode, struct kstat *stat,
980bcb4be80SMiklos Szeredi 			   struct file *file, bool *refreshed)
981bcb4be80SMiklos Szeredi {
982bcb4be80SMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
983bcb4be80SMiklos Szeredi 	int err;
984bcb4be80SMiklos Szeredi 	bool r;
985bcb4be80SMiklos Szeredi 
986126b9d43SMiklos Szeredi 	if (time_before64(fi->i_time, get_jiffies_64())) {
987bcb4be80SMiklos Szeredi 		r = true;
988bcb4be80SMiklos Szeredi 		err = fuse_do_getattr(inode, stat, file);
989bcb4be80SMiklos Szeredi 	} else {
990bcb4be80SMiklos Szeredi 		r = false;
991bcb4be80SMiklos Szeredi 		err = 0;
992bcb4be80SMiklos Szeredi 		if (stat) {
993bcb4be80SMiklos Szeredi 			generic_fillattr(inode, stat);
994bcb4be80SMiklos Szeredi 			stat->mode = fi->orig_i_mode;
99545c72cd7SPavel Shilovsky 			stat->ino = fi->orig_ino;
996bcb4be80SMiklos Szeredi 		}
997bcb4be80SMiklos Szeredi 	}
998bcb4be80SMiklos Szeredi 
999bcb4be80SMiklos Szeredi 	if (refreshed != NULL)
1000bcb4be80SMiklos Szeredi 		*refreshed = r;
1001bcb4be80SMiklos Szeredi 
1002bcb4be80SMiklos Szeredi 	return err;
1003bcb4be80SMiklos Szeredi }
1004bcb4be80SMiklos Szeredi 
10053b463ae0SJohn Muir int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid,
1006451d0f59SJohn Muir 			     u64 child_nodeid, struct qstr *name)
10073b463ae0SJohn Muir {
10083b463ae0SJohn Muir 	int err = -ENOTDIR;
10093b463ae0SJohn Muir 	struct inode *parent;
10103b463ae0SJohn Muir 	struct dentry *dir;
10113b463ae0SJohn Muir 	struct dentry *entry;
10123b463ae0SJohn Muir 
10133b463ae0SJohn Muir 	parent = ilookup5(sb, parent_nodeid, fuse_inode_eq, &parent_nodeid);
10143b463ae0SJohn Muir 	if (!parent)
10153b463ae0SJohn Muir 		return -ENOENT;
10163b463ae0SJohn Muir 
10173b463ae0SJohn Muir 	mutex_lock(&parent->i_mutex);
10183b463ae0SJohn Muir 	if (!S_ISDIR(parent->i_mode))
10193b463ae0SJohn Muir 		goto unlock;
10203b463ae0SJohn Muir 
10213b463ae0SJohn Muir 	err = -ENOENT;
10223b463ae0SJohn Muir 	dir = d_find_alias(parent);
10233b463ae0SJohn Muir 	if (!dir)
10243b463ae0SJohn Muir 		goto unlock;
10253b463ae0SJohn Muir 
10263b463ae0SJohn Muir 	entry = d_lookup(dir, name);
10273b463ae0SJohn Muir 	dput(dir);
10283b463ae0SJohn Muir 	if (!entry)
10293b463ae0SJohn Muir 		goto unlock;
10303b463ae0SJohn Muir 
10313b463ae0SJohn Muir 	fuse_invalidate_attr(parent);
10323b463ae0SJohn Muir 	fuse_invalidate_entry(entry);
1033451d0f59SJohn Muir 
1034451d0f59SJohn Muir 	if (child_nodeid != 0 && entry->d_inode) {
1035451d0f59SJohn Muir 		mutex_lock(&entry->d_inode->i_mutex);
1036451d0f59SJohn Muir 		if (get_node_id(entry->d_inode) != child_nodeid) {
1037451d0f59SJohn Muir 			err = -ENOENT;
1038451d0f59SJohn Muir 			goto badentry;
1039451d0f59SJohn Muir 		}
1040451d0f59SJohn Muir 		if (d_mountpoint(entry)) {
1041451d0f59SJohn Muir 			err = -EBUSY;
1042451d0f59SJohn Muir 			goto badentry;
1043451d0f59SJohn Muir 		}
1044451d0f59SJohn Muir 		if (S_ISDIR(entry->d_inode->i_mode)) {
1045451d0f59SJohn Muir 			shrink_dcache_parent(entry);
1046451d0f59SJohn Muir 			if (!simple_empty(entry)) {
1047451d0f59SJohn Muir 				err = -ENOTEMPTY;
1048451d0f59SJohn Muir 				goto badentry;
1049451d0f59SJohn Muir 			}
1050451d0f59SJohn Muir 			entry->d_inode->i_flags |= S_DEAD;
1051451d0f59SJohn Muir 		}
1052451d0f59SJohn Muir 		dont_mount(entry);
1053451d0f59SJohn Muir 		clear_nlink(entry->d_inode);
10543b463ae0SJohn Muir 		err = 0;
1055451d0f59SJohn Muir  badentry:
1056451d0f59SJohn Muir 		mutex_unlock(&entry->d_inode->i_mutex);
1057451d0f59SJohn Muir 		if (!err)
1058451d0f59SJohn Muir 			d_delete(entry);
1059451d0f59SJohn Muir 	} else {
1060451d0f59SJohn Muir 		err = 0;
1061451d0f59SJohn Muir 	}
1062451d0f59SJohn Muir 	dput(entry);
10633b463ae0SJohn Muir 
10643b463ae0SJohn Muir  unlock:
10653b463ae0SJohn Muir 	mutex_unlock(&parent->i_mutex);
10663b463ae0SJohn Muir 	iput(parent);
10673b463ae0SJohn Muir 	return err;
10683b463ae0SJohn Muir }
10693b463ae0SJohn Muir 
107087729a55SMiklos Szeredi /*
107187729a55SMiklos Szeredi  * Calling into a user-controlled filesystem gives the filesystem
1072c2132c1bSAnatol Pomozov  * daemon ptrace-like capabilities over the current process.  This
107387729a55SMiklos Szeredi  * means, that the filesystem daemon is able to record the exact
107487729a55SMiklos Szeredi  * filesystem operations performed, and can also control the behavior
107587729a55SMiklos Szeredi  * of the requester process in otherwise impossible ways.  For example
107687729a55SMiklos Szeredi  * it can delay the operation for arbitrary length of time allowing
107787729a55SMiklos Szeredi  * DoS against the requester.
107887729a55SMiklos Szeredi  *
107987729a55SMiklos Szeredi  * For this reason only those processes can call into the filesystem,
108087729a55SMiklos Szeredi  * for which the owner of the mount has ptrace privilege.  This
108187729a55SMiklos Szeredi  * excludes processes started by other users, suid or sgid processes.
108287729a55SMiklos Szeredi  */
1083c2132c1bSAnatol Pomozov int fuse_allow_current_process(struct fuse_conn *fc)
108487729a55SMiklos Szeredi {
1085c69e8d9cSDavid Howells 	const struct cred *cred;
1086c69e8d9cSDavid Howells 
108787729a55SMiklos Szeredi 	if (fc->flags & FUSE_ALLOW_OTHER)
108887729a55SMiklos Szeredi 		return 1;
108987729a55SMiklos Szeredi 
1090c2132c1bSAnatol Pomozov 	cred = current_cred();
1091499dcf20SEric W. Biederman 	if (uid_eq(cred->euid, fc->user_id) &&
1092499dcf20SEric W. Biederman 	    uid_eq(cred->suid, fc->user_id) &&
1093499dcf20SEric W. Biederman 	    uid_eq(cred->uid,  fc->user_id) &&
1094499dcf20SEric W. Biederman 	    gid_eq(cred->egid, fc->group_id) &&
1095499dcf20SEric W. Biederman 	    gid_eq(cred->sgid, fc->group_id) &&
1096499dcf20SEric W. Biederman 	    gid_eq(cred->gid,  fc->group_id))
1097c2132c1bSAnatol Pomozov 		return 1;
109887729a55SMiklos Szeredi 
1099c2132c1bSAnatol Pomozov 	return 0;
110087729a55SMiklos Szeredi }
110187729a55SMiklos Szeredi 
110231d40d74SMiklos Szeredi static int fuse_access(struct inode *inode, int mask)
110331d40d74SMiklos Szeredi {
110431d40d74SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
110531d40d74SMiklos Szeredi 	struct fuse_req *req;
110631d40d74SMiklos Szeredi 	struct fuse_access_in inarg;
110731d40d74SMiklos Szeredi 	int err;
110831d40d74SMiklos Szeredi 
1109698fa1d1SMiklos Szeredi 	BUG_ON(mask & MAY_NOT_BLOCK);
1110698fa1d1SMiklos Szeredi 
111131d40d74SMiklos Szeredi 	if (fc->no_access)
111231d40d74SMiklos Szeredi 		return 0;
111331d40d74SMiklos Szeredi 
1114b111c8c0SMaxim Patlasov 	req = fuse_get_req_nopages(fc);
1115ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1116ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
111731d40d74SMiklos Szeredi 
111831d40d74SMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
1119e6305c43SAl Viro 	inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC);
112031d40d74SMiklos Szeredi 	req->in.h.opcode = FUSE_ACCESS;
112131d40d74SMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
112231d40d74SMiklos Szeredi 	req->in.numargs = 1;
112331d40d74SMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
112431d40d74SMiklos Szeredi 	req->in.args[0].value = &inarg;
1125b93f858aSTejun Heo 	fuse_request_send(fc, req);
112631d40d74SMiklos Szeredi 	err = req->out.h.error;
112731d40d74SMiklos Szeredi 	fuse_put_request(fc, req);
112831d40d74SMiklos Szeredi 	if (err == -ENOSYS) {
112931d40d74SMiklos Szeredi 		fc->no_access = 1;
113031d40d74SMiklos Szeredi 		err = 0;
113131d40d74SMiklos Szeredi 	}
113231d40d74SMiklos Szeredi 	return err;
113331d40d74SMiklos Szeredi }
113431d40d74SMiklos Szeredi 
113510556cb2SAl Viro static int fuse_perm_getattr(struct inode *inode, int mask)
113619690ddbSMiklos Szeredi {
113710556cb2SAl Viro 	if (mask & MAY_NOT_BLOCK)
113819690ddbSMiklos Szeredi 		return -ECHILD;
113919690ddbSMiklos Szeredi 
114019690ddbSMiklos Szeredi 	return fuse_do_getattr(inode, NULL, NULL);
114119690ddbSMiklos Szeredi }
114219690ddbSMiklos Szeredi 
11436f9f1180SMiklos Szeredi /*
11446f9f1180SMiklos Szeredi  * Check permission.  The two basic access models of FUSE are:
11456f9f1180SMiklos Szeredi  *
11466f9f1180SMiklos Szeredi  * 1) Local access checking ('default_permissions' mount option) based
11476f9f1180SMiklos Szeredi  * on file mode.  This is the plain old disk filesystem permission
11486f9f1180SMiklos Szeredi  * modell.
11496f9f1180SMiklos Szeredi  *
11506f9f1180SMiklos Szeredi  * 2) "Remote" access checking, where server is responsible for
11516f9f1180SMiklos Szeredi  * checking permission in each inode operation.  An exception to this
11526f9f1180SMiklos Szeredi  * is if ->permission() was invoked from sys_access() in which case an
11536f9f1180SMiklos Szeredi  * access request is sent.  Execute permission is still checked
11546f9f1180SMiklos Szeredi  * locally based on file mode.
11556f9f1180SMiklos Szeredi  */
115610556cb2SAl Viro static int fuse_permission(struct inode *inode, int mask)
1157e5e5558eSMiklos Szeredi {
1158e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1159244f6385SMiklos Szeredi 	bool refreshed = false;
1160244f6385SMiklos Szeredi 	int err = 0;
1161e5e5558eSMiklos Szeredi 
1162c2132c1bSAnatol Pomozov 	if (!fuse_allow_current_process(fc))
1163e5e5558eSMiklos Szeredi 		return -EACCES;
1164244f6385SMiklos Szeredi 
1165244f6385SMiklos Szeredi 	/*
1166e8e96157SMiklos Szeredi 	 * If attributes are needed, refresh them before proceeding
1167244f6385SMiklos Szeredi 	 */
1168e8e96157SMiklos Szeredi 	if ((fc->flags & FUSE_DEFAULT_PERMISSIONS) ||
1169e8e96157SMiklos Szeredi 	    ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
117019690ddbSMiklos Szeredi 		struct fuse_inode *fi = get_fuse_inode(inode);
117119690ddbSMiklos Szeredi 
1172126b9d43SMiklos Szeredi 		if (time_before64(fi->i_time, get_jiffies_64())) {
117319690ddbSMiklos Szeredi 			refreshed = true;
117419690ddbSMiklos Szeredi 
117510556cb2SAl Viro 			err = fuse_perm_getattr(inode, mask);
1176244f6385SMiklos Szeredi 			if (err)
1177244f6385SMiklos Szeredi 				return err;
11781fb69e78SMiklos Szeredi 		}
117919690ddbSMiklos Szeredi 	}
1180244f6385SMiklos Szeredi 
1181244f6385SMiklos Szeredi 	if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
11822830ba7fSAl Viro 		err = generic_permission(inode, mask);
11831e9a4ed9SMiklos Szeredi 
11841e9a4ed9SMiklos Szeredi 		/* If permission is denied, try to refresh file
11851e9a4ed9SMiklos Szeredi 		   attributes.  This is also needed, because the root
11861e9a4ed9SMiklos Szeredi 		   node will at first have no permissions */
1187244f6385SMiklos Szeredi 		if (err == -EACCES && !refreshed) {
118810556cb2SAl Viro 			err = fuse_perm_getattr(inode, mask);
11891e9a4ed9SMiklos Szeredi 			if (!err)
11902830ba7fSAl Viro 				err = generic_permission(inode, mask);
11911e9a4ed9SMiklos Szeredi 		}
11921e9a4ed9SMiklos Szeredi 
11936f9f1180SMiklos Szeredi 		/* Note: the opposite of the above test does not
11946f9f1180SMiklos Szeredi 		   exist.  So if permissions are revoked this won't be
11956f9f1180SMiklos Szeredi 		   noticed immediately, only after the attribute
11966f9f1180SMiklos Szeredi 		   timeout has expired */
11979cfcac81SEric Paris 	} else if (mask & (MAY_ACCESS | MAY_CHDIR)) {
1198e8e96157SMiklos Szeredi 		err = fuse_access(inode, mask);
1199e8e96157SMiklos Szeredi 	} else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
1200e8e96157SMiklos Szeredi 		if (!(inode->i_mode & S_IXUGO)) {
1201e8e96157SMiklos Szeredi 			if (refreshed)
1202e5e5558eSMiklos Szeredi 				return -EACCES;
120331d40d74SMiklos Szeredi 
120410556cb2SAl Viro 			err = fuse_perm_getattr(inode, mask);
1205e8e96157SMiklos Szeredi 			if (!err && !(inode->i_mode & S_IXUGO))
1206e8e96157SMiklos Szeredi 				return -EACCES;
1207e8e96157SMiklos Szeredi 		}
1208e5e5558eSMiklos Szeredi 	}
1209244f6385SMiklos Szeredi 	return err;
1210e5e5558eSMiklos Szeredi }
1211e5e5558eSMiklos Szeredi 
1212e5e5558eSMiklos Szeredi static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
12138d3af7f3SAl Viro 			 struct dir_context *ctx)
1214e5e5558eSMiklos Szeredi {
1215e5e5558eSMiklos Szeredi 	while (nbytes >= FUSE_NAME_OFFSET) {
1216e5e5558eSMiklos Szeredi 		struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
1217e5e5558eSMiklos Szeredi 		size_t reclen = FUSE_DIRENT_SIZE(dirent);
1218e5e5558eSMiklos Szeredi 		if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
1219e5e5558eSMiklos Szeredi 			return -EIO;
1220e5e5558eSMiklos Szeredi 		if (reclen > nbytes)
1221e5e5558eSMiklos Szeredi 			break;
1222efeb9e60SMiklos Szeredi 		if (memchr(dirent->name, '/', dirent->namelen) != NULL)
1223efeb9e60SMiklos Szeredi 			return -EIO;
1224e5e5558eSMiklos Szeredi 
12258d3af7f3SAl Viro 		if (!dir_emit(ctx, dirent->name, dirent->namelen,
12268d3af7f3SAl Viro 			       dirent->ino, dirent->type))
1227e5e5558eSMiklos Szeredi 			break;
1228e5e5558eSMiklos Szeredi 
1229e5e5558eSMiklos Szeredi 		buf += reclen;
1230e5e5558eSMiklos Szeredi 		nbytes -= reclen;
12318d3af7f3SAl Viro 		ctx->pos = dirent->off;
1232e5e5558eSMiklos Szeredi 	}
1233e5e5558eSMiklos Szeredi 
1234e5e5558eSMiklos Szeredi 	return 0;
1235e5e5558eSMiklos Szeredi }
1236e5e5558eSMiklos Szeredi 
12370b05b183SAnand V. Avati static int fuse_direntplus_link(struct file *file,
12380b05b183SAnand V. Avati 				struct fuse_direntplus *direntplus,
12390b05b183SAnand V. Avati 				u64 attr_version)
12400b05b183SAnand V. Avati {
12410b05b183SAnand V. Avati 	int err;
12420b05b183SAnand V. Avati 	struct fuse_entry_out *o = &direntplus->entry_out;
12430b05b183SAnand V. Avati 	struct fuse_dirent *dirent = &direntplus->dirent;
12440b05b183SAnand V. Avati 	struct dentry *parent = file->f_path.dentry;
12450b05b183SAnand V. Avati 	struct qstr name = QSTR_INIT(dirent->name, dirent->namelen);
12460b05b183SAnand V. Avati 	struct dentry *dentry;
12470b05b183SAnand V. Avati 	struct dentry *alias;
12480b05b183SAnand V. Avati 	struct inode *dir = parent->d_inode;
12490b05b183SAnand V. Avati 	struct fuse_conn *fc;
12500b05b183SAnand V. Avati 	struct inode *inode;
12510b05b183SAnand V. Avati 
12520b05b183SAnand V. Avati 	if (!o->nodeid) {
12530b05b183SAnand V. Avati 		/*
12540b05b183SAnand V. Avati 		 * Unlike in the case of fuse_lookup, zero nodeid does not mean
12550b05b183SAnand V. Avati 		 * ENOENT. Instead, it only means the userspace filesystem did
12560b05b183SAnand V. Avati 		 * not want to return attributes/handle for this entry.
12570b05b183SAnand V. Avati 		 *
12580b05b183SAnand V. Avati 		 * So do nothing.
12590b05b183SAnand V. Avati 		 */
12600b05b183SAnand V. Avati 		return 0;
12610b05b183SAnand V. Avati 	}
12620b05b183SAnand V. Avati 
12630b05b183SAnand V. Avati 	if (name.name[0] == '.') {
12640b05b183SAnand V. Avati 		/*
12650b05b183SAnand V. Avati 		 * We could potentially refresh the attributes of the directory
12660b05b183SAnand V. Avati 		 * and its parent?
12670b05b183SAnand V. Avati 		 */
12680b05b183SAnand V. Avati 		if (name.len == 1)
12690b05b183SAnand V. Avati 			return 0;
12700b05b183SAnand V. Avati 		if (name.name[1] == '.' && name.len == 2)
12710b05b183SAnand V. Avati 			return 0;
12720b05b183SAnand V. Avati 	}
1273a28ef45cSMiklos Szeredi 
1274a28ef45cSMiklos Szeredi 	if (invalid_nodeid(o->nodeid))
1275a28ef45cSMiklos Szeredi 		return -EIO;
1276a28ef45cSMiklos Szeredi 	if (!fuse_valid_type(o->attr.mode))
1277a28ef45cSMiklos Szeredi 		return -EIO;
1278a28ef45cSMiklos Szeredi 
12790b05b183SAnand V. Avati 	fc = get_fuse_conn(dir);
12800b05b183SAnand V. Avati 
12810b05b183SAnand V. Avati 	name.hash = full_name_hash(name.name, name.len);
12820b05b183SAnand V. Avati 	dentry = d_lookup(parent, &name);
128353ce9a33SNiels de Vos 	if (dentry) {
12840b05b183SAnand V. Avati 		inode = dentry->d_inode;
128553ce9a33SNiels de Vos 		if (!inode) {
128653ce9a33SNiels de Vos 			d_drop(dentry);
1287a28ef45cSMiklos Szeredi 		} else if (get_node_id(inode) != o->nodeid ||
1288a28ef45cSMiklos Szeredi 			   ((o->attr.mode ^ inode->i_mode) & S_IFMT)) {
12895542aa2fSEric W. Biederman 			d_invalidate(dentry);
1290a28ef45cSMiklos Szeredi 		} else if (is_bad_inode(inode)) {
1291a28ef45cSMiklos Szeredi 			err = -EIO;
1292a28ef45cSMiklos Szeredi 			goto out;
129353ce9a33SNiels de Vos 		} else {
12940b05b183SAnand V. Avati 			struct fuse_inode *fi;
12950b05b183SAnand V. Avati 			fi = get_fuse_inode(inode);
12960b05b183SAnand V. Avati 			spin_lock(&fc->lock);
12970b05b183SAnand V. Avati 			fi->nlookup++;
12980b05b183SAnand V. Avati 			spin_unlock(&fc->lock);
12990b05b183SAnand V. Avati 
1300fa2b7213SMiklos Szeredi 			fuse_change_attributes(inode, &o->attr,
1301fa2b7213SMiklos Szeredi 					       entry_attr_timeout(o),
1302fa2b7213SMiklos Szeredi 					       attr_version);
1303fa2b7213SMiklos Szeredi 
13040b05b183SAnand V. Avati 			/*
13050b05b183SAnand V. Avati 			 * The other branch to 'found' comes via fuse_iget()
13060b05b183SAnand V. Avati 			 * which bumps nlookup inside
13070b05b183SAnand V. Avati 			 */
13080b05b183SAnand V. Avati 			goto found;
13090b05b183SAnand V. Avati 		}
13100b05b183SAnand V. Avati 		dput(dentry);
13110b05b183SAnand V. Avati 	}
13120b05b183SAnand V. Avati 
13130b05b183SAnand V. Avati 	dentry = d_alloc(parent, &name);
13140b05b183SAnand V. Avati 	err = -ENOMEM;
13150b05b183SAnand V. Avati 	if (!dentry)
13160b05b183SAnand V. Avati 		goto out;
13170b05b183SAnand V. Avati 
13180b05b183SAnand V. Avati 	inode = fuse_iget(dir->i_sb, o->nodeid, o->generation,
13190b05b183SAnand V. Avati 			  &o->attr, entry_attr_timeout(o), attr_version);
13200b05b183SAnand V. Avati 	if (!inode)
13210b05b183SAnand V. Avati 		goto out;
13220b05b183SAnand V. Avati 
1323*41d28bcaSAl Viro 	alias = d_splice_alias(inode, dentry);
13240b05b183SAnand V. Avati 	err = PTR_ERR(alias);
13255835f339SMiklos Szeredi 	if (IS_ERR(alias))
13260b05b183SAnand V. Avati 		goto out;
13272914941eSMiklos Szeredi 
13280b05b183SAnand V. Avati 	if (alias) {
13290b05b183SAnand V. Avati 		dput(dentry);
13300b05b183SAnand V. Avati 		dentry = alias;
13310b05b183SAnand V. Avati 	}
13320b05b183SAnand V. Avati 
13330b05b183SAnand V. Avati found:
13346314efeeSMiklos Szeredi 	if (fc->readdirplus_auto)
13356314efeeSMiklos Szeredi 		set_bit(FUSE_I_INIT_RDPLUS, &get_fuse_inode(inode)->state);
13360b05b183SAnand V. Avati 	fuse_change_entry_timeout(dentry, o);
13370b05b183SAnand V. Avati 
13380b05b183SAnand V. Avati 	err = 0;
13390b05b183SAnand V. Avati out:
13400b05b183SAnand V. Avati 	dput(dentry);
13410b05b183SAnand V. Avati 	return err;
13420b05b183SAnand V. Avati }
13430b05b183SAnand V. Avati 
13440b05b183SAnand V. Avati static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file,
13458d3af7f3SAl Viro 			     struct dir_context *ctx, u64 attr_version)
13460b05b183SAnand V. Avati {
13470b05b183SAnand V. Avati 	struct fuse_direntplus *direntplus;
13480b05b183SAnand V. Avati 	struct fuse_dirent *dirent;
13490b05b183SAnand V. Avati 	size_t reclen;
13500b05b183SAnand V. Avati 	int over = 0;
13510b05b183SAnand V. Avati 	int ret;
13520b05b183SAnand V. Avati 
13530b05b183SAnand V. Avati 	while (nbytes >= FUSE_NAME_OFFSET_DIRENTPLUS) {
13540b05b183SAnand V. Avati 		direntplus = (struct fuse_direntplus *) buf;
13550b05b183SAnand V. Avati 		dirent = &direntplus->dirent;
13560b05b183SAnand V. Avati 		reclen = FUSE_DIRENTPLUS_SIZE(direntplus);
13570b05b183SAnand V. Avati 
13580b05b183SAnand V. Avati 		if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
13590b05b183SAnand V. Avati 			return -EIO;
13600b05b183SAnand V. Avati 		if (reclen > nbytes)
13610b05b183SAnand V. Avati 			break;
1362efeb9e60SMiklos Szeredi 		if (memchr(dirent->name, '/', dirent->namelen) != NULL)
1363efeb9e60SMiklos Szeredi 			return -EIO;
13640b05b183SAnand V. Avati 
13650b05b183SAnand V. Avati 		if (!over) {
13660b05b183SAnand V. Avati 			/* We fill entries into dstbuf only as much as
13670b05b183SAnand V. Avati 			   it can hold. But we still continue iterating
13680b05b183SAnand V. Avati 			   over remaining entries to link them. If not,
13690b05b183SAnand V. Avati 			   we need to send a FORGET for each of those
13700b05b183SAnand V. Avati 			   which we did not link.
13710b05b183SAnand V. Avati 			*/
13728d3af7f3SAl Viro 			over = !dir_emit(ctx, dirent->name, dirent->namelen,
13738d3af7f3SAl Viro 				       dirent->ino, dirent->type);
13748d3af7f3SAl Viro 			ctx->pos = dirent->off;
13750b05b183SAnand V. Avati 		}
13760b05b183SAnand V. Avati 
13770b05b183SAnand V. Avati 		buf += reclen;
13780b05b183SAnand V. Avati 		nbytes -= reclen;
13790b05b183SAnand V. Avati 
13800b05b183SAnand V. Avati 		ret = fuse_direntplus_link(file, direntplus, attr_version);
13810b05b183SAnand V. Avati 		if (ret)
13820b05b183SAnand V. Avati 			fuse_force_forget(file, direntplus->entry_out.nodeid);
13830b05b183SAnand V. Avati 	}
13840b05b183SAnand V. Avati 
13850b05b183SAnand V. Avati 	return 0;
13860b05b183SAnand V. Avati }
13870b05b183SAnand V. Avati 
13888d3af7f3SAl Viro static int fuse_readdir(struct file *file, struct dir_context *ctx)
1389e5e5558eSMiklos Szeredi {
13904582a4abSFeng Shuo 	int plus, err;
139104730fefSMiklos Szeredi 	size_t nbytes;
139204730fefSMiklos Szeredi 	struct page *page;
1393496ad9aaSAl Viro 	struct inode *inode = file_inode(file);
139404730fefSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1395248d86e8SMiklos Szeredi 	struct fuse_req *req;
13960b05b183SAnand V. Avati 	u64 attr_version = 0;
1397248d86e8SMiklos Szeredi 
1398248d86e8SMiklos Szeredi 	if (is_bad_inode(inode))
1399248d86e8SMiklos Szeredi 		return -EIO;
1400248d86e8SMiklos Szeredi 
1401b111c8c0SMaxim Patlasov 	req = fuse_get_req(fc, 1);
1402ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1403ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
1404e5e5558eSMiklos Szeredi 
140504730fefSMiklos Szeredi 	page = alloc_page(GFP_KERNEL);
140604730fefSMiklos Szeredi 	if (!page) {
140704730fefSMiklos Szeredi 		fuse_put_request(fc, req);
1408e5e5558eSMiklos Szeredi 		return -ENOMEM;
140904730fefSMiklos Szeredi 	}
14104582a4abSFeng Shuo 
14118d3af7f3SAl Viro 	plus = fuse_use_readdirplus(inode, ctx);
1412f4975c67SMiklos Szeredi 	req->out.argpages = 1;
141304730fefSMiklos Szeredi 	req->num_pages = 1;
141404730fefSMiklos Szeredi 	req->pages[0] = page;
141585f40aecSMaxim Patlasov 	req->page_descs[0].length = PAGE_SIZE;
14164582a4abSFeng Shuo 	if (plus) {
14170b05b183SAnand V. Avati 		attr_version = fuse_get_attr_version(fc);
14188d3af7f3SAl Viro 		fuse_read_fill(req, file, ctx->pos, PAGE_SIZE,
14190b05b183SAnand V. Avati 			       FUSE_READDIRPLUS);
14200b05b183SAnand V. Avati 	} else {
14218d3af7f3SAl Viro 		fuse_read_fill(req, file, ctx->pos, PAGE_SIZE,
14220b05b183SAnand V. Avati 			       FUSE_READDIR);
14230b05b183SAnand V. Avati 	}
1424b93f858aSTejun Heo 	fuse_request_send(fc, req);
1425361b1eb5SMiklos Szeredi 	nbytes = req->out.args[0].size;
142604730fefSMiklos Szeredi 	err = req->out.h.error;
142704730fefSMiklos Szeredi 	fuse_put_request(fc, req);
14280b05b183SAnand V. Avati 	if (!err) {
14294582a4abSFeng Shuo 		if (plus) {
14300b05b183SAnand V. Avati 			err = parse_dirplusfile(page_address(page), nbytes,
14318d3af7f3SAl Viro 						file, ctx,
14320b05b183SAnand V. Avati 						attr_version);
14330b05b183SAnand V. Avati 		} else {
14340b05b183SAnand V. Avati 			err = parse_dirfile(page_address(page), nbytes, file,
14358d3af7f3SAl Viro 					    ctx);
14360b05b183SAnand V. Avati 		}
14370b05b183SAnand V. Avati 	}
1438e5e5558eSMiklos Szeredi 
143904730fefSMiklos Szeredi 	__free_page(page);
1440451418fcSAndrew Gallagher 	fuse_invalidate_atime(inode);
144104730fefSMiklos Szeredi 	return err;
1442e5e5558eSMiklos Szeredi }
1443e5e5558eSMiklos Szeredi 
1444e5e5558eSMiklos Szeredi static char *read_link(struct dentry *dentry)
1445e5e5558eSMiklos Szeredi {
1446e5e5558eSMiklos Szeredi 	struct inode *inode = dentry->d_inode;
1447e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1448b111c8c0SMaxim Patlasov 	struct fuse_req *req = fuse_get_req_nopages(fc);
1449e5e5558eSMiklos Szeredi 	char *link;
1450e5e5558eSMiklos Szeredi 
1451ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1452e231c2eeSDavid Howells 		return ERR_CAST(req);
1453e5e5558eSMiklos Szeredi 
1454e5e5558eSMiklos Szeredi 	link = (char *) __get_free_page(GFP_KERNEL);
1455e5e5558eSMiklos Szeredi 	if (!link) {
1456e5e5558eSMiklos Szeredi 		link = ERR_PTR(-ENOMEM);
1457e5e5558eSMiklos Szeredi 		goto out;
1458e5e5558eSMiklos Szeredi 	}
1459e5e5558eSMiklos Szeredi 	req->in.h.opcode = FUSE_READLINK;
1460e5e5558eSMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
1461e5e5558eSMiklos Szeredi 	req->out.argvar = 1;
1462e5e5558eSMiklos Szeredi 	req->out.numargs = 1;
1463e5e5558eSMiklos Szeredi 	req->out.args[0].size = PAGE_SIZE - 1;
1464e5e5558eSMiklos Szeredi 	req->out.args[0].value = link;
1465b93f858aSTejun Heo 	fuse_request_send(fc, req);
1466e5e5558eSMiklos Szeredi 	if (req->out.h.error) {
1467e5e5558eSMiklos Szeredi 		free_page((unsigned long) link);
1468e5e5558eSMiklos Szeredi 		link = ERR_PTR(req->out.h.error);
1469e5e5558eSMiklos Szeredi 	} else
1470e5e5558eSMiklos Szeredi 		link[req->out.args[0].size] = '\0';
1471e5e5558eSMiklos Szeredi  out:
1472e5e5558eSMiklos Szeredi 	fuse_put_request(fc, req);
1473451418fcSAndrew Gallagher 	fuse_invalidate_atime(inode);
1474e5e5558eSMiklos Szeredi 	return link;
1475e5e5558eSMiklos Szeredi }
1476e5e5558eSMiklos Szeredi 
1477e5e5558eSMiklos Szeredi static void free_link(char *link)
1478e5e5558eSMiklos Szeredi {
1479e5e5558eSMiklos Szeredi 	if (!IS_ERR(link))
1480e5e5558eSMiklos Szeredi 		free_page((unsigned long) link);
1481e5e5558eSMiklos Szeredi }
1482e5e5558eSMiklos Szeredi 
1483e5e5558eSMiklos Szeredi static void *fuse_follow_link(struct dentry *dentry, struct nameidata *nd)
1484e5e5558eSMiklos Szeredi {
1485e5e5558eSMiklos Szeredi 	nd_set_link(nd, read_link(dentry));
1486e5e5558eSMiklos Szeredi 	return NULL;
1487e5e5558eSMiklos Szeredi }
1488e5e5558eSMiklos Szeredi 
1489e5e5558eSMiklos Szeredi static void fuse_put_link(struct dentry *dentry, struct nameidata *nd, void *c)
1490e5e5558eSMiklos Szeredi {
1491e5e5558eSMiklos Szeredi 	free_link(nd_get_link(nd));
1492e5e5558eSMiklos Szeredi }
1493e5e5558eSMiklos Szeredi 
1494e5e5558eSMiklos Szeredi static int fuse_dir_open(struct inode *inode, struct file *file)
1495e5e5558eSMiklos Szeredi {
149691fe96b4SMiklos Szeredi 	return fuse_open_common(inode, file, true);
1497e5e5558eSMiklos Szeredi }
1498e5e5558eSMiklos Szeredi 
1499e5e5558eSMiklos Szeredi static int fuse_dir_release(struct inode *inode, struct file *file)
1500e5e5558eSMiklos Szeredi {
15018b0797a4SMiklos Szeredi 	fuse_release_common(file, FUSE_RELEASEDIR);
15028b0797a4SMiklos Szeredi 
15038b0797a4SMiklos Szeredi 	return 0;
1504e5e5558eSMiklos Szeredi }
1505e5e5558eSMiklos Szeredi 
150602c24a82SJosef Bacik static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end,
150702c24a82SJosef Bacik 			  int datasync)
150882547981SMiklos Szeredi {
150902c24a82SJosef Bacik 	return fuse_fsync_common(file, start, end, datasync, 1);
151082547981SMiklos Szeredi }
151182547981SMiklos Szeredi 
1512b18da0c5SMiklos Szeredi static long fuse_dir_ioctl(struct file *file, unsigned int cmd,
1513b18da0c5SMiklos Szeredi 			    unsigned long arg)
1514b18da0c5SMiklos Szeredi {
1515b18da0c5SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1516b18da0c5SMiklos Szeredi 
1517b18da0c5SMiklos Szeredi 	/* FUSE_IOCTL_DIR only supported for API version >= 7.18 */
1518b18da0c5SMiklos Szeredi 	if (fc->minor < 18)
1519b18da0c5SMiklos Szeredi 		return -ENOTTY;
1520b18da0c5SMiklos Szeredi 
1521b18da0c5SMiklos Szeredi 	return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR);
1522b18da0c5SMiklos Szeredi }
1523b18da0c5SMiklos Szeredi 
1524b18da0c5SMiklos Szeredi static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd,
1525b18da0c5SMiklos Szeredi 				   unsigned long arg)
1526b18da0c5SMiklos Szeredi {
1527b18da0c5SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1528b18da0c5SMiklos Szeredi 
1529b18da0c5SMiklos Szeredi 	if (fc->minor < 18)
1530b18da0c5SMiklos Szeredi 		return -ENOTTY;
1531b18da0c5SMiklos Szeredi 
1532b18da0c5SMiklos Szeredi 	return fuse_ioctl_common(file, cmd, arg,
1533b18da0c5SMiklos Szeredi 				 FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR);
1534b18da0c5SMiklos Szeredi }
1535b18da0c5SMiklos Szeredi 
1536b0aa7606SMaxim Patlasov static bool update_mtime(unsigned ivalid, bool trust_local_mtime)
153717637cbaSMiklos Szeredi {
153817637cbaSMiklos Szeredi 	/* Always update if mtime is explicitly set  */
153917637cbaSMiklos Szeredi 	if (ivalid & ATTR_MTIME_SET)
154017637cbaSMiklos Szeredi 		return true;
154117637cbaSMiklos Szeredi 
1542b0aa7606SMaxim Patlasov 	/* Or if kernel i_mtime is the official one */
1543b0aa7606SMaxim Patlasov 	if (trust_local_mtime)
1544b0aa7606SMaxim Patlasov 		return true;
1545b0aa7606SMaxim Patlasov 
154617637cbaSMiklos Szeredi 	/* If it's an open(O_TRUNC) or an ftruncate(), don't update */
154717637cbaSMiklos Szeredi 	if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
154817637cbaSMiklos Szeredi 		return false;
154917637cbaSMiklos Szeredi 
155017637cbaSMiklos Szeredi 	/* In all other cases update */
155117637cbaSMiklos Szeredi 	return true;
155217637cbaSMiklos Szeredi }
155317637cbaSMiklos Szeredi 
1554b0aa7606SMaxim Patlasov static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg,
15553ad22c62SMaxim Patlasov 			   bool trust_local_cmtime)
15569e6268dbSMiklos Szeredi {
15579e6268dbSMiklos Szeredi 	unsigned ivalid = iattr->ia_valid;
15589e6268dbSMiklos Szeredi 
15599e6268dbSMiklos Szeredi 	if (ivalid & ATTR_MODE)
1560befc649cSMiklos Szeredi 		arg->valid |= FATTR_MODE,   arg->mode = iattr->ia_mode;
15619e6268dbSMiklos Szeredi 	if (ivalid & ATTR_UID)
1562499dcf20SEric W. Biederman 		arg->valid |= FATTR_UID,    arg->uid = from_kuid(&init_user_ns, iattr->ia_uid);
15639e6268dbSMiklos Szeredi 	if (ivalid & ATTR_GID)
1564499dcf20SEric W. Biederman 		arg->valid |= FATTR_GID,    arg->gid = from_kgid(&init_user_ns, iattr->ia_gid);
15659e6268dbSMiklos Szeredi 	if (ivalid & ATTR_SIZE)
1566befc649cSMiklos Szeredi 		arg->valid |= FATTR_SIZE,   arg->size = iattr->ia_size;
156717637cbaSMiklos Szeredi 	if (ivalid & ATTR_ATIME) {
156817637cbaSMiklos Szeredi 		arg->valid |= FATTR_ATIME;
1569befc649cSMiklos Szeredi 		arg->atime = iattr->ia_atime.tv_sec;
157017637cbaSMiklos Szeredi 		arg->atimensec = iattr->ia_atime.tv_nsec;
157117637cbaSMiklos Szeredi 		if (!(ivalid & ATTR_ATIME_SET))
157217637cbaSMiklos Szeredi 			arg->valid |= FATTR_ATIME_NOW;
157317637cbaSMiklos Szeredi 	}
15743ad22c62SMaxim Patlasov 	if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, trust_local_cmtime)) {
157517637cbaSMiklos Szeredi 		arg->valid |= FATTR_MTIME;
1576befc649cSMiklos Szeredi 		arg->mtime = iattr->ia_mtime.tv_sec;
157717637cbaSMiklos Szeredi 		arg->mtimensec = iattr->ia_mtime.tv_nsec;
15783ad22c62SMaxim Patlasov 		if (!(ivalid & ATTR_MTIME_SET) && !trust_local_cmtime)
157917637cbaSMiklos Szeredi 			arg->valid |= FATTR_MTIME_NOW;
15809e6268dbSMiklos Szeredi 	}
15813ad22c62SMaxim Patlasov 	if ((ivalid & ATTR_CTIME) && trust_local_cmtime) {
15823ad22c62SMaxim Patlasov 		arg->valid |= FATTR_CTIME;
15833ad22c62SMaxim Patlasov 		arg->ctime = iattr->ia_ctime.tv_sec;
15843ad22c62SMaxim Patlasov 		arg->ctimensec = iattr->ia_ctime.tv_nsec;
15853ad22c62SMaxim Patlasov 	}
15869e6268dbSMiklos Szeredi }
15879e6268dbSMiklos Szeredi 
15886f9f1180SMiklos Szeredi /*
15893be5a52bSMiklos Szeredi  * Prevent concurrent writepages on inode
15903be5a52bSMiklos Szeredi  *
15913be5a52bSMiklos Szeredi  * This is done by adding a negative bias to the inode write counter
15923be5a52bSMiklos Szeredi  * and waiting for all pending writes to finish.
15933be5a52bSMiklos Szeredi  */
15943be5a52bSMiklos Szeredi void fuse_set_nowrite(struct inode *inode)
15953be5a52bSMiklos Szeredi {
15963be5a52bSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
15973be5a52bSMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
15983be5a52bSMiklos Szeredi 
15993be5a52bSMiklos Szeredi 	BUG_ON(!mutex_is_locked(&inode->i_mutex));
16003be5a52bSMiklos Szeredi 
16013be5a52bSMiklos Szeredi 	spin_lock(&fc->lock);
16023be5a52bSMiklos Szeredi 	BUG_ON(fi->writectr < 0);
16033be5a52bSMiklos Szeredi 	fi->writectr += FUSE_NOWRITE;
16043be5a52bSMiklos Szeredi 	spin_unlock(&fc->lock);
16053be5a52bSMiklos Szeredi 	wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE);
16063be5a52bSMiklos Szeredi }
16073be5a52bSMiklos Szeredi 
16083be5a52bSMiklos Szeredi /*
16093be5a52bSMiklos Szeredi  * Allow writepages on inode
16103be5a52bSMiklos Szeredi  *
16113be5a52bSMiklos Szeredi  * Remove the bias from the writecounter and send any queued
16123be5a52bSMiklos Szeredi  * writepages.
16133be5a52bSMiklos Szeredi  */
16143be5a52bSMiklos Szeredi static void __fuse_release_nowrite(struct inode *inode)
16153be5a52bSMiklos Szeredi {
16163be5a52bSMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
16173be5a52bSMiklos Szeredi 
16183be5a52bSMiklos Szeredi 	BUG_ON(fi->writectr != FUSE_NOWRITE);
16193be5a52bSMiklos Szeredi 	fi->writectr = 0;
16203be5a52bSMiklos Szeredi 	fuse_flush_writepages(inode);
16213be5a52bSMiklos Szeredi }
16223be5a52bSMiklos Szeredi 
16233be5a52bSMiklos Szeredi void fuse_release_nowrite(struct inode *inode)
16243be5a52bSMiklos Szeredi {
16253be5a52bSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
16263be5a52bSMiklos Szeredi 
16273be5a52bSMiklos Szeredi 	spin_lock(&fc->lock);
16283be5a52bSMiklos Szeredi 	__fuse_release_nowrite(inode);
16293be5a52bSMiklos Szeredi 	spin_unlock(&fc->lock);
16303be5a52bSMiklos Szeredi }
16313be5a52bSMiklos Szeredi 
1632b0aa7606SMaxim Patlasov static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_req *req,
1633b0aa7606SMaxim Patlasov 			      struct inode *inode,
1634b0aa7606SMaxim Patlasov 			      struct fuse_setattr_in *inarg_p,
1635b0aa7606SMaxim Patlasov 			      struct fuse_attr_out *outarg_p)
1636b0aa7606SMaxim Patlasov {
1637b0aa7606SMaxim Patlasov 	req->in.h.opcode = FUSE_SETATTR;
1638b0aa7606SMaxim Patlasov 	req->in.h.nodeid = get_node_id(inode);
1639b0aa7606SMaxim Patlasov 	req->in.numargs = 1;
1640b0aa7606SMaxim Patlasov 	req->in.args[0].size = sizeof(*inarg_p);
1641b0aa7606SMaxim Patlasov 	req->in.args[0].value = inarg_p;
1642b0aa7606SMaxim Patlasov 	req->out.numargs = 1;
1643b0aa7606SMaxim Patlasov 	if (fc->minor < 9)
1644b0aa7606SMaxim Patlasov 		req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
1645b0aa7606SMaxim Patlasov 	else
1646b0aa7606SMaxim Patlasov 		req->out.args[0].size = sizeof(*outarg_p);
1647b0aa7606SMaxim Patlasov 	req->out.args[0].value = outarg_p;
1648b0aa7606SMaxim Patlasov }
1649b0aa7606SMaxim Patlasov 
1650b0aa7606SMaxim Patlasov /*
1651b0aa7606SMaxim Patlasov  * Flush inode->i_mtime to the server
1652b0aa7606SMaxim Patlasov  */
1653ab9e13f7SMaxim Patlasov int fuse_flush_times(struct inode *inode, struct fuse_file *ff)
1654b0aa7606SMaxim Patlasov {
1655b0aa7606SMaxim Patlasov 	struct fuse_conn *fc = get_fuse_conn(inode);
16561e18bda8SMiklos Szeredi 	struct fuse_req *req;
1657b0aa7606SMaxim Patlasov 	struct fuse_setattr_in inarg;
1658b0aa7606SMaxim Patlasov 	struct fuse_attr_out outarg;
1659b0aa7606SMaxim Patlasov 	int err;
1660b0aa7606SMaxim Patlasov 
1661b0aa7606SMaxim Patlasov 	req = fuse_get_req_nopages(fc);
1662b0aa7606SMaxim Patlasov 	if (IS_ERR(req))
1663b0aa7606SMaxim Patlasov 		return PTR_ERR(req);
1664b0aa7606SMaxim Patlasov 
1665b0aa7606SMaxim Patlasov 	memset(&inarg, 0, sizeof(inarg));
1666b0aa7606SMaxim Patlasov 	memset(&outarg, 0, sizeof(outarg));
1667b0aa7606SMaxim Patlasov 
1668ab9e13f7SMaxim Patlasov 	inarg.valid = FATTR_MTIME;
1669b0aa7606SMaxim Patlasov 	inarg.mtime = inode->i_mtime.tv_sec;
1670b0aa7606SMaxim Patlasov 	inarg.mtimensec = inode->i_mtime.tv_nsec;
1671ab9e13f7SMaxim Patlasov 	if (fc->minor >= 23) {
1672ab9e13f7SMaxim Patlasov 		inarg.valid |= FATTR_CTIME;
1673ab9e13f7SMaxim Patlasov 		inarg.ctime = inode->i_ctime.tv_sec;
1674ab9e13f7SMaxim Patlasov 		inarg.ctimensec = inode->i_ctime.tv_nsec;
1675ab9e13f7SMaxim Patlasov 	}
16761e18bda8SMiklos Szeredi 	if (ff) {
16771e18bda8SMiklos Szeredi 		inarg.valid |= FATTR_FH;
16781e18bda8SMiklos Szeredi 		inarg.fh = ff->fh;
16791e18bda8SMiklos Szeredi 	}
1680b0aa7606SMaxim Patlasov 	fuse_setattr_fill(fc, req, inode, &inarg, &outarg);
1681b0aa7606SMaxim Patlasov 	fuse_request_send(fc, req);
1682b0aa7606SMaxim Patlasov 	err = req->out.h.error;
1683b0aa7606SMaxim Patlasov 	fuse_put_request(fc, req);
1684b0aa7606SMaxim Patlasov 
1685b0aa7606SMaxim Patlasov 	return err;
1686b0aa7606SMaxim Patlasov }
1687b0aa7606SMaxim Patlasov 
16883be5a52bSMiklos Szeredi /*
16896f9f1180SMiklos Szeredi  * Set attributes, and at the same time refresh them.
16906f9f1180SMiklos Szeredi  *
16916f9f1180SMiklos Szeredi  * Truncation is slightly complicated, because the 'truncate' request
16926f9f1180SMiklos Szeredi  * may fail, in which case we don't want to touch the mapping.
16939ffbb916SMiklos Szeredi  * vmtruncate() doesn't allow for this case, so do the rlimit checking
16949ffbb916SMiklos Szeredi  * and the actual truncation by hand.
16956f9f1180SMiklos Szeredi  */
1696efb9fa9eSMaxim Patlasov int fuse_do_setattr(struct inode *inode, struct iattr *attr,
169749d4914fSMiklos Szeredi 		    struct file *file)
16989e6268dbSMiklos Szeredi {
16999e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
170006a7c3c2SMaxim Patlasov 	struct fuse_inode *fi = get_fuse_inode(inode);
17019e6268dbSMiklos Szeredi 	struct fuse_req *req;
17029e6268dbSMiklos Szeredi 	struct fuse_setattr_in inarg;
17039e6268dbSMiklos Szeredi 	struct fuse_attr_out outarg;
17043be5a52bSMiklos Szeredi 	bool is_truncate = false;
17058373200bSPavel Emelyanov 	bool is_wb = fc->writeback_cache;
17063be5a52bSMiklos Szeredi 	loff_t oldsize;
17079e6268dbSMiklos Szeredi 	int err;
17083ad22c62SMaxim Patlasov 	bool trust_local_cmtime = is_wb && S_ISREG(inode->i_mode);
17099e6268dbSMiklos Szeredi 
1710db78b877SChristoph Hellwig 	if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS))
1711db78b877SChristoph Hellwig 		attr->ia_valid |= ATTR_FORCE;
1712db78b877SChristoph Hellwig 
17131e9a4ed9SMiklos Szeredi 	err = inode_change_ok(inode, attr);
17141e9a4ed9SMiklos Szeredi 	if (err)
17151e9a4ed9SMiklos Szeredi 		return err;
17161e9a4ed9SMiklos Szeredi 
17178d56adddSMiklos Szeredi 	if (attr->ia_valid & ATTR_OPEN) {
17188d56adddSMiklos Szeredi 		if (fc->atomic_o_trunc)
17196ff958edSMiklos Szeredi 			return 0;
17208d56adddSMiklos Szeredi 		file = NULL;
17218d56adddSMiklos Szeredi 	}
17226ff958edSMiklos Szeredi 
17232c27c65eSChristoph Hellwig 	if (attr->ia_valid & ATTR_SIZE)
17243be5a52bSMiklos Szeredi 		is_truncate = true;
17259e6268dbSMiklos Szeredi 
1726b111c8c0SMaxim Patlasov 	req = fuse_get_req_nopages(fc);
1727ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1728ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
17299e6268dbSMiklos Szeredi 
173006a7c3c2SMaxim Patlasov 	if (is_truncate) {
17313be5a52bSMiklos Szeredi 		fuse_set_nowrite(inode);
173206a7c3c2SMaxim Patlasov 		set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
17333ad22c62SMaxim Patlasov 		if (trust_local_cmtime && attr->ia_size != inode->i_size)
17343ad22c62SMaxim Patlasov 			attr->ia_valid |= ATTR_MTIME | ATTR_CTIME;
173506a7c3c2SMaxim Patlasov 	}
17363be5a52bSMiklos Szeredi 
17379e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
17380e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
17393ad22c62SMaxim Patlasov 	iattr_to_fattr(attr, &inarg, trust_local_cmtime);
174049d4914fSMiklos Szeredi 	if (file) {
174149d4914fSMiklos Szeredi 		struct fuse_file *ff = file->private_data;
174249d4914fSMiklos Szeredi 		inarg.valid |= FATTR_FH;
174349d4914fSMiklos Szeredi 		inarg.fh = ff->fh;
174449d4914fSMiklos Szeredi 	}
1745f3332114SMiklos Szeredi 	if (attr->ia_valid & ATTR_SIZE) {
1746f3332114SMiklos Szeredi 		/* For mandatory locking in truncate */
1747f3332114SMiklos Szeredi 		inarg.valid |= FATTR_LOCKOWNER;
1748f3332114SMiklos Szeredi 		inarg.lock_owner = fuse_lock_owner_id(fc, current->files);
1749f3332114SMiklos Szeredi 	}
1750b0aa7606SMaxim Patlasov 	fuse_setattr_fill(fc, req, inode, &inarg, &outarg);
1751b93f858aSTejun Heo 	fuse_request_send(fc, req);
17529e6268dbSMiklos Szeredi 	err = req->out.h.error;
17539e6268dbSMiklos Szeredi 	fuse_put_request(fc, req);
1754e00d2c2dSMiklos Szeredi 	if (err) {
1755e00d2c2dSMiklos Szeredi 		if (err == -EINTR)
1756e00d2c2dSMiklos Szeredi 			fuse_invalidate_attr(inode);
17573be5a52bSMiklos Szeredi 		goto error;
1758e00d2c2dSMiklos Szeredi 	}
1759e00d2c2dSMiklos Szeredi 
17609e6268dbSMiklos Szeredi 	if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
17619e6268dbSMiklos Szeredi 		make_bad_inode(inode);
17623be5a52bSMiklos Szeredi 		err = -EIO;
17633be5a52bSMiklos Szeredi 		goto error;
17649e6268dbSMiklos Szeredi 	}
17659e6268dbSMiklos Szeredi 
17663be5a52bSMiklos Szeredi 	spin_lock(&fc->lock);
1767b0aa7606SMaxim Patlasov 	/* the kernel maintains i_mtime locally */
17683ad22c62SMaxim Patlasov 	if (trust_local_cmtime) {
17693ad22c62SMaxim Patlasov 		if (attr->ia_valid & ATTR_MTIME)
1770b0aa7606SMaxim Patlasov 			inode->i_mtime = attr->ia_mtime;
17713ad22c62SMaxim Patlasov 		if (attr->ia_valid & ATTR_CTIME)
17723ad22c62SMaxim Patlasov 			inode->i_ctime = attr->ia_ctime;
17731e18bda8SMiklos Szeredi 		/* FIXME: clear I_DIRTY_SYNC? */
1774b0aa7606SMaxim Patlasov 	}
1775b0aa7606SMaxim Patlasov 
17763be5a52bSMiklos Szeredi 	fuse_change_attributes_common(inode, &outarg.attr,
17773be5a52bSMiklos Szeredi 				      attr_timeout(&outarg));
17783be5a52bSMiklos Szeredi 	oldsize = inode->i_size;
17798373200bSPavel Emelyanov 	/* see the comment in fuse_change_attributes() */
17808373200bSPavel Emelyanov 	if (!is_wb || is_truncate || !S_ISREG(inode->i_mode))
17813be5a52bSMiklos Szeredi 		i_size_write(inode, outarg.attr.size);
17823be5a52bSMiklos Szeredi 
17833be5a52bSMiklos Szeredi 	if (is_truncate) {
17843be5a52bSMiklos Szeredi 		/* NOTE: this may release/reacquire fc->lock */
17853be5a52bSMiklos Szeredi 		__fuse_release_nowrite(inode);
17863be5a52bSMiklos Szeredi 	}
17873be5a52bSMiklos Szeredi 	spin_unlock(&fc->lock);
17883be5a52bSMiklos Szeredi 
17893be5a52bSMiklos Szeredi 	/*
17903be5a52bSMiklos Szeredi 	 * Only call invalidate_inode_pages2() after removing
17913be5a52bSMiklos Szeredi 	 * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock.
17923be5a52bSMiklos Szeredi 	 */
17938373200bSPavel Emelyanov 	if ((is_truncate || !is_wb) &&
17948373200bSPavel Emelyanov 	    S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
17957caef267SKirill A. Shutemov 		truncate_pagecache(inode, outarg.attr.size);
17963be5a52bSMiklos Szeredi 		invalidate_inode_pages2(inode->i_mapping);
17973be5a52bSMiklos Szeredi 	}
17983be5a52bSMiklos Szeredi 
179906a7c3c2SMaxim Patlasov 	clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
1800e00d2c2dSMiklos Szeredi 	return 0;
18013be5a52bSMiklos Szeredi 
18023be5a52bSMiklos Szeredi error:
18033be5a52bSMiklos Szeredi 	if (is_truncate)
18043be5a52bSMiklos Szeredi 		fuse_release_nowrite(inode);
18053be5a52bSMiklos Szeredi 
180606a7c3c2SMaxim Patlasov 	clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
18073be5a52bSMiklos Szeredi 	return err;
18089e6268dbSMiklos Szeredi }
18099e6268dbSMiklos Szeredi 
181049d4914fSMiklos Szeredi static int fuse_setattr(struct dentry *entry, struct iattr *attr)
181149d4914fSMiklos Szeredi {
1812efb9fa9eSMaxim Patlasov 	struct inode *inode = entry->d_inode;
1813efb9fa9eSMaxim Patlasov 
1814efb9fa9eSMaxim Patlasov 	if (!fuse_allow_current_process(get_fuse_conn(inode)))
1815efb9fa9eSMaxim Patlasov 		return -EACCES;
1816efb9fa9eSMaxim Patlasov 
181749d4914fSMiklos Szeredi 	if (attr->ia_valid & ATTR_FILE)
1818efb9fa9eSMaxim Patlasov 		return fuse_do_setattr(inode, attr, attr->ia_file);
181949d4914fSMiklos Szeredi 	else
1820efb9fa9eSMaxim Patlasov 		return fuse_do_setattr(inode, attr, NULL);
182149d4914fSMiklos Szeredi }
182249d4914fSMiklos Szeredi 
1823e5e5558eSMiklos Szeredi static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
1824e5e5558eSMiklos Szeredi 			struct kstat *stat)
1825e5e5558eSMiklos Szeredi {
1826e5e5558eSMiklos Szeredi 	struct inode *inode = entry->d_inode;
1827244f6385SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1828244f6385SMiklos Szeredi 
1829c2132c1bSAnatol Pomozov 	if (!fuse_allow_current_process(fc))
1830244f6385SMiklos Szeredi 		return -EACCES;
1831244f6385SMiklos Szeredi 
1832bcb4be80SMiklos Szeredi 	return fuse_update_attributes(inode, stat, NULL, NULL);
1833e5e5558eSMiklos Szeredi }
1834e5e5558eSMiklos Szeredi 
183592a8780eSMiklos Szeredi static int fuse_setxattr(struct dentry *entry, const char *name,
183692a8780eSMiklos Szeredi 			 const void *value, size_t size, int flags)
183792a8780eSMiklos Szeredi {
183892a8780eSMiklos Szeredi 	struct inode *inode = entry->d_inode;
183992a8780eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
184092a8780eSMiklos Szeredi 	struct fuse_req *req;
184192a8780eSMiklos Szeredi 	struct fuse_setxattr_in inarg;
184292a8780eSMiklos Szeredi 	int err;
184392a8780eSMiklos Szeredi 
184492a8780eSMiklos Szeredi 	if (fc->no_setxattr)
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 	memset(&inarg, 0, sizeof(inarg));
185292a8780eSMiklos Szeredi 	inarg.size = size;
185392a8780eSMiklos Szeredi 	inarg.flags = flags;
185492a8780eSMiklos Szeredi 	req->in.h.opcode = FUSE_SETXATTR;
185592a8780eSMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
185692a8780eSMiklos Szeredi 	req->in.numargs = 3;
185792a8780eSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
185892a8780eSMiklos Szeredi 	req->in.args[0].value = &inarg;
185992a8780eSMiklos Szeredi 	req->in.args[1].size = strlen(name) + 1;
186092a8780eSMiklos Szeredi 	req->in.args[1].value = name;
186192a8780eSMiklos Szeredi 	req->in.args[2].size = size;
186292a8780eSMiklos Szeredi 	req->in.args[2].value = value;
1863b93f858aSTejun Heo 	fuse_request_send(fc, req);
186492a8780eSMiklos Szeredi 	err = req->out.h.error;
186592a8780eSMiklos Szeredi 	fuse_put_request(fc, req);
186692a8780eSMiklos Szeredi 	if (err == -ENOSYS) {
186792a8780eSMiklos Szeredi 		fc->no_setxattr = 1;
186892a8780eSMiklos Szeredi 		err = -EOPNOTSUPP;
186992a8780eSMiklos Szeredi 	}
187031f3267bSMaxim Patlasov 	if (!err) {
1871d331a415SAnand Avati 		fuse_invalidate_attr(inode);
187231f3267bSMaxim Patlasov 		fuse_update_ctime(inode);
187331f3267bSMaxim Patlasov 	}
187492a8780eSMiklos Szeredi 	return err;
187592a8780eSMiklos Szeredi }
187692a8780eSMiklos Szeredi 
187792a8780eSMiklos Szeredi static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
187892a8780eSMiklos Szeredi 			     void *value, size_t size)
187992a8780eSMiklos Szeredi {
188092a8780eSMiklos Szeredi 	struct inode *inode = entry->d_inode;
188192a8780eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
188292a8780eSMiklos Szeredi 	struct fuse_req *req;
188392a8780eSMiklos Szeredi 	struct fuse_getxattr_in inarg;
188492a8780eSMiklos Szeredi 	struct fuse_getxattr_out outarg;
188592a8780eSMiklos Szeredi 	ssize_t ret;
188692a8780eSMiklos Szeredi 
188792a8780eSMiklos Szeredi 	if (fc->no_getxattr)
188892a8780eSMiklos Szeredi 		return -EOPNOTSUPP;
188992a8780eSMiklos Szeredi 
1890b111c8c0SMaxim Patlasov 	req = fuse_get_req_nopages(fc);
1891ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1892ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
189392a8780eSMiklos Szeredi 
189492a8780eSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
189592a8780eSMiklos Szeredi 	inarg.size = size;
189692a8780eSMiklos Szeredi 	req->in.h.opcode = FUSE_GETXATTR;
189792a8780eSMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
189892a8780eSMiklos Szeredi 	req->in.numargs = 2;
189992a8780eSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
190092a8780eSMiklos Szeredi 	req->in.args[0].value = &inarg;
190192a8780eSMiklos Szeredi 	req->in.args[1].size = strlen(name) + 1;
190292a8780eSMiklos Szeredi 	req->in.args[1].value = name;
190392a8780eSMiklos Szeredi 	/* This is really two different operations rolled into one */
190492a8780eSMiklos Szeredi 	req->out.numargs = 1;
190592a8780eSMiklos Szeredi 	if (size) {
190692a8780eSMiklos Szeredi 		req->out.argvar = 1;
190792a8780eSMiklos Szeredi 		req->out.args[0].size = size;
190892a8780eSMiklos Szeredi 		req->out.args[0].value = value;
190992a8780eSMiklos Szeredi 	} else {
191092a8780eSMiklos Szeredi 		req->out.args[0].size = sizeof(outarg);
191192a8780eSMiklos Szeredi 		req->out.args[0].value = &outarg;
191292a8780eSMiklos Szeredi 	}
1913b93f858aSTejun Heo 	fuse_request_send(fc, req);
191492a8780eSMiklos Szeredi 	ret = req->out.h.error;
191592a8780eSMiklos Szeredi 	if (!ret)
191692a8780eSMiklos Szeredi 		ret = size ? req->out.args[0].size : outarg.size;
191792a8780eSMiklos Szeredi 	else {
191892a8780eSMiklos Szeredi 		if (ret == -ENOSYS) {
191992a8780eSMiklos Szeredi 			fc->no_getxattr = 1;
192092a8780eSMiklos Szeredi 			ret = -EOPNOTSUPP;
192192a8780eSMiklos Szeredi 		}
192292a8780eSMiklos Szeredi 	}
192392a8780eSMiklos Szeredi 	fuse_put_request(fc, req);
192492a8780eSMiklos Szeredi 	return ret;
192592a8780eSMiklos Szeredi }
192692a8780eSMiklos Szeredi 
192792a8780eSMiklos Szeredi static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
192892a8780eSMiklos Szeredi {
192992a8780eSMiklos Szeredi 	struct inode *inode = entry->d_inode;
193092a8780eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
193192a8780eSMiklos Szeredi 	struct fuse_req *req;
193292a8780eSMiklos Szeredi 	struct fuse_getxattr_in inarg;
193392a8780eSMiklos Szeredi 	struct fuse_getxattr_out outarg;
193492a8780eSMiklos Szeredi 	ssize_t ret;
193592a8780eSMiklos Szeredi 
1936c2132c1bSAnatol Pomozov 	if (!fuse_allow_current_process(fc))
1937e57ac683SMiklos Szeredi 		return -EACCES;
1938e57ac683SMiklos Szeredi 
193992a8780eSMiklos Szeredi 	if (fc->no_listxattr)
194092a8780eSMiklos Szeredi 		return -EOPNOTSUPP;
194192a8780eSMiklos Szeredi 
1942b111c8c0SMaxim Patlasov 	req = fuse_get_req_nopages(fc);
1943ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1944ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
194592a8780eSMiklos Szeredi 
194692a8780eSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
194792a8780eSMiklos Szeredi 	inarg.size = size;
194892a8780eSMiklos Szeredi 	req->in.h.opcode = FUSE_LISTXATTR;
194992a8780eSMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
195092a8780eSMiklos Szeredi 	req->in.numargs = 1;
195192a8780eSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
195292a8780eSMiklos Szeredi 	req->in.args[0].value = &inarg;
195392a8780eSMiklos Szeredi 	/* This is really two different operations rolled into one */
195492a8780eSMiklos Szeredi 	req->out.numargs = 1;
195592a8780eSMiklos Szeredi 	if (size) {
195692a8780eSMiklos Szeredi 		req->out.argvar = 1;
195792a8780eSMiklos Szeredi 		req->out.args[0].size = size;
195892a8780eSMiklos Szeredi 		req->out.args[0].value = list;
195992a8780eSMiklos Szeredi 	} else {
196092a8780eSMiklos Szeredi 		req->out.args[0].size = sizeof(outarg);
196192a8780eSMiklos Szeredi 		req->out.args[0].value = &outarg;
196292a8780eSMiklos Szeredi 	}
1963b93f858aSTejun Heo 	fuse_request_send(fc, req);
196492a8780eSMiklos Szeredi 	ret = req->out.h.error;
196592a8780eSMiklos Szeredi 	if (!ret)
196692a8780eSMiklos Szeredi 		ret = size ? req->out.args[0].size : outarg.size;
196792a8780eSMiklos Szeredi 	else {
196892a8780eSMiklos Szeredi 		if (ret == -ENOSYS) {
196992a8780eSMiklos Szeredi 			fc->no_listxattr = 1;
197092a8780eSMiklos Szeredi 			ret = -EOPNOTSUPP;
197192a8780eSMiklos Szeredi 		}
197292a8780eSMiklos Szeredi 	}
197392a8780eSMiklos Szeredi 	fuse_put_request(fc, req);
197492a8780eSMiklos Szeredi 	return ret;
197592a8780eSMiklos Szeredi }
197692a8780eSMiklos Szeredi 
197792a8780eSMiklos Szeredi static int fuse_removexattr(struct dentry *entry, const char *name)
197892a8780eSMiklos Szeredi {
197992a8780eSMiklos Szeredi 	struct inode *inode = entry->d_inode;
198092a8780eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
198192a8780eSMiklos Szeredi 	struct fuse_req *req;
198292a8780eSMiklos Szeredi 	int err;
198392a8780eSMiklos Szeredi 
198492a8780eSMiklos Szeredi 	if (fc->no_removexattr)
198592a8780eSMiklos Szeredi 		return -EOPNOTSUPP;
198692a8780eSMiklos Szeredi 
1987b111c8c0SMaxim Patlasov 	req = fuse_get_req_nopages(fc);
1988ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1989ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
199092a8780eSMiklos Szeredi 
199192a8780eSMiklos Szeredi 	req->in.h.opcode = FUSE_REMOVEXATTR;
199292a8780eSMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
199392a8780eSMiklos Szeredi 	req->in.numargs = 1;
199492a8780eSMiklos Szeredi 	req->in.args[0].size = strlen(name) + 1;
199592a8780eSMiklos Szeredi 	req->in.args[0].value = name;
1996b93f858aSTejun Heo 	fuse_request_send(fc, req);
199792a8780eSMiklos Szeredi 	err = req->out.h.error;
199892a8780eSMiklos Szeredi 	fuse_put_request(fc, req);
199992a8780eSMiklos Szeredi 	if (err == -ENOSYS) {
200092a8780eSMiklos Szeredi 		fc->no_removexattr = 1;
200192a8780eSMiklos Szeredi 		err = -EOPNOTSUPP;
200292a8780eSMiklos Szeredi 	}
200331f3267bSMaxim Patlasov 	if (!err) {
2004d331a415SAnand Avati 		fuse_invalidate_attr(inode);
200531f3267bSMaxim Patlasov 		fuse_update_ctime(inode);
200631f3267bSMaxim Patlasov 	}
200792a8780eSMiklos Szeredi 	return err;
200892a8780eSMiklos Szeredi }
200992a8780eSMiklos Szeredi 
2010754661f1SArjan van de Ven static const struct inode_operations fuse_dir_inode_operations = {
2011e5e5558eSMiklos Szeredi 	.lookup		= fuse_lookup,
20129e6268dbSMiklos Szeredi 	.mkdir		= fuse_mkdir,
20139e6268dbSMiklos Szeredi 	.symlink	= fuse_symlink,
20149e6268dbSMiklos Szeredi 	.unlink		= fuse_unlink,
20159e6268dbSMiklos Szeredi 	.rmdir		= fuse_rmdir,
20161560c974SMiklos Szeredi 	.rename2	= fuse_rename2,
20179e6268dbSMiklos Szeredi 	.link		= fuse_link,
20189e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
20199e6268dbSMiklos Szeredi 	.create		= fuse_create,
2020c8ccbe03SMiklos Szeredi 	.atomic_open	= fuse_atomic_open,
20219e6268dbSMiklos Szeredi 	.mknod		= fuse_mknod,
2022e5e5558eSMiklos Szeredi 	.permission	= fuse_permission,
2023e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
202492a8780eSMiklos Szeredi 	.setxattr	= fuse_setxattr,
202592a8780eSMiklos Szeredi 	.getxattr	= fuse_getxattr,
202692a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
202792a8780eSMiklos Szeredi 	.removexattr	= fuse_removexattr,
2028e5e5558eSMiklos Szeredi };
2029e5e5558eSMiklos Szeredi 
20304b6f5d20SArjan van de Ven static const struct file_operations fuse_dir_operations = {
2031b6aeadedSMiklos Szeredi 	.llseek		= generic_file_llseek,
2032e5e5558eSMiklos Szeredi 	.read		= generic_read_dir,
20338d3af7f3SAl Viro 	.iterate	= fuse_readdir,
2034e5e5558eSMiklos Szeredi 	.open		= fuse_dir_open,
2035e5e5558eSMiklos Szeredi 	.release	= fuse_dir_release,
203682547981SMiklos Szeredi 	.fsync		= fuse_dir_fsync,
2037b18da0c5SMiklos Szeredi 	.unlocked_ioctl	= fuse_dir_ioctl,
2038b18da0c5SMiklos Szeredi 	.compat_ioctl	= fuse_dir_compat_ioctl,
2039e5e5558eSMiklos Szeredi };
2040e5e5558eSMiklos Szeredi 
2041754661f1SArjan van de Ven static const struct inode_operations fuse_common_inode_operations = {
20429e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
2043e5e5558eSMiklos Szeredi 	.permission	= fuse_permission,
2044e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
204592a8780eSMiklos Szeredi 	.setxattr	= fuse_setxattr,
204692a8780eSMiklos Szeredi 	.getxattr	= fuse_getxattr,
204792a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
204892a8780eSMiklos Szeredi 	.removexattr	= fuse_removexattr,
2049e5e5558eSMiklos Szeredi };
2050e5e5558eSMiklos Szeredi 
2051754661f1SArjan van de Ven static const struct inode_operations fuse_symlink_inode_operations = {
20529e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
2053e5e5558eSMiklos Szeredi 	.follow_link	= fuse_follow_link,
2054e5e5558eSMiklos Szeredi 	.put_link	= fuse_put_link,
2055e5e5558eSMiklos Szeredi 	.readlink	= generic_readlink,
2056e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
205792a8780eSMiklos Szeredi 	.setxattr	= fuse_setxattr,
205892a8780eSMiklos Szeredi 	.getxattr	= fuse_getxattr,
205992a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
206092a8780eSMiklos Szeredi 	.removexattr	= fuse_removexattr,
2061e5e5558eSMiklos Szeredi };
2062e5e5558eSMiklos Szeredi 
2063e5e5558eSMiklos Szeredi void fuse_init_common(struct inode *inode)
2064e5e5558eSMiklos Szeredi {
2065e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_common_inode_operations;
2066e5e5558eSMiklos Szeredi }
2067e5e5558eSMiklos Szeredi 
2068e5e5558eSMiklos Szeredi void fuse_init_dir(struct inode *inode)
2069e5e5558eSMiklos Szeredi {
2070e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_dir_inode_operations;
2071e5e5558eSMiklos Szeredi 	inode->i_fop = &fuse_dir_operations;
2072e5e5558eSMiklos Szeredi }
2073e5e5558eSMiklos Szeredi 
2074e5e5558eSMiklos Szeredi void fuse_init_symlink(struct inode *inode)
2075e5e5558eSMiklos Szeredi {
2076e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_symlink_inode_operations;
2077e5e5558eSMiklos Szeredi }
2078