xref: /openbmc/linux/fs/fuse/dir.c (revision d95852777bc8ba6b3ad3397d495c5f9dd8ca8383)
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 
170a0898cfSMiklos Szeredi #if BITS_PER_LONG >= 64
180a0898cfSMiklos Szeredi static inline void fuse_dentry_settime(struct dentry *entry, u64 time)
190a0898cfSMiklos Szeredi {
200a0898cfSMiklos Szeredi 	entry->d_time = time;
210a0898cfSMiklos Szeredi }
220a0898cfSMiklos Szeredi 
230a0898cfSMiklos Szeredi static inline u64 fuse_dentry_time(struct dentry *entry)
240a0898cfSMiklos Szeredi {
250a0898cfSMiklos Szeredi 	return entry->d_time;
260a0898cfSMiklos Szeredi }
270a0898cfSMiklos Szeredi #else
280a0898cfSMiklos Szeredi /*
290a0898cfSMiklos Szeredi  * On 32 bit archs store the high 32 bits of time in d_fsdata
300a0898cfSMiklos Szeredi  */
310a0898cfSMiklos Szeredi static void fuse_dentry_settime(struct dentry *entry, u64 time)
320a0898cfSMiklos Szeredi {
330a0898cfSMiklos Szeredi 	entry->d_time = time;
340a0898cfSMiklos Szeredi 	entry->d_fsdata = (void *) (unsigned long) (time >> 32);
350a0898cfSMiklos Szeredi }
360a0898cfSMiklos Szeredi 
370a0898cfSMiklos Szeredi static u64 fuse_dentry_time(struct dentry *entry)
380a0898cfSMiklos Szeredi {
390a0898cfSMiklos Szeredi 	return (u64) entry->d_time +
400a0898cfSMiklos Szeredi 		((u64) (unsigned long) entry->d_fsdata << 32);
410a0898cfSMiklos Szeredi }
420a0898cfSMiklos Szeredi #endif
430a0898cfSMiklos Szeredi 
446f9f1180SMiklos Szeredi /*
456f9f1180SMiklos Szeredi  * FUSE caches dentries and attributes with separate timeout.  The
466f9f1180SMiklos Szeredi  * time in jiffies until the dentry/attributes are valid is stored in
476f9f1180SMiklos Szeredi  * dentry->d_time and fuse_inode->i_time respectively.
486f9f1180SMiklos Szeredi  */
496f9f1180SMiklos Szeredi 
506f9f1180SMiklos Szeredi /*
516f9f1180SMiklos Szeredi  * Calculate the time in jiffies until a dentry/attributes are valid
526f9f1180SMiklos Szeredi  */
530a0898cfSMiklos Szeredi static u64 time_to_jiffies(unsigned long sec, unsigned long nsec)
54e5e5558eSMiklos Szeredi {
55685d16ddSMiklos Szeredi 	if (sec || nsec) {
56e5e5558eSMiklos Szeredi 		struct timespec ts = {sec, nsec};
570a0898cfSMiklos Szeredi 		return get_jiffies_64() + timespec_to_jiffies(&ts);
58685d16ddSMiklos Szeredi 	} else
590a0898cfSMiklos Szeredi 		return 0;
60e5e5558eSMiklos Szeredi }
61e5e5558eSMiklos Szeredi 
626f9f1180SMiklos Szeredi /*
636f9f1180SMiklos Szeredi  * Set dentry and possibly attribute timeouts from the lookup/mk*
646f9f1180SMiklos Szeredi  * replies
656f9f1180SMiklos Szeredi  */
661fb69e78SMiklos Szeredi static void fuse_change_entry_timeout(struct dentry *entry,
671fb69e78SMiklos Szeredi 				      struct fuse_entry_out *o)
680aa7c699SMiklos Szeredi {
690a0898cfSMiklos Szeredi 	fuse_dentry_settime(entry,
700a0898cfSMiklos Szeredi 		time_to_jiffies(o->entry_valid, o->entry_valid_nsec));
711fb69e78SMiklos Szeredi }
721fb69e78SMiklos Szeredi 
731fb69e78SMiklos Szeredi static u64 attr_timeout(struct fuse_attr_out *o)
741fb69e78SMiklos Szeredi {
751fb69e78SMiklos Szeredi 	return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
761fb69e78SMiklos Szeredi }
771fb69e78SMiklos Szeredi 
781fb69e78SMiklos Szeredi static u64 entry_attr_timeout(struct fuse_entry_out *o)
791fb69e78SMiklos Szeredi {
801fb69e78SMiklos Szeredi 	return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
818cbdf1e6SMiklos Szeredi }
828cbdf1e6SMiklos Szeredi 
836f9f1180SMiklos Szeredi /*
846f9f1180SMiklos Szeredi  * Mark the attributes as stale, so that at the next call to
856f9f1180SMiklos Szeredi  * ->getattr() they will be fetched from userspace
866f9f1180SMiklos Szeredi  */
878cbdf1e6SMiklos Szeredi void fuse_invalidate_attr(struct inode *inode)
888cbdf1e6SMiklos Szeredi {
890a0898cfSMiklos Szeredi 	get_fuse_inode(inode)->i_time = 0;
908cbdf1e6SMiklos Szeredi }
918cbdf1e6SMiklos Szeredi 
926f9f1180SMiklos Szeredi /*
936f9f1180SMiklos Szeredi  * Just mark the entry as stale, so that a next attempt to look it up
946f9f1180SMiklos Szeredi  * will result in a new lookup call to userspace
956f9f1180SMiklos Szeredi  *
966f9f1180SMiklos Szeredi  * This is called when a dentry is about to become negative and the
976f9f1180SMiklos Szeredi  * timeout is unknown (unlink, rmdir, rename and in some cases
986f9f1180SMiklos Szeredi  * lookup)
996f9f1180SMiklos Szeredi  */
100dbd561d2SMiklos Szeredi void fuse_invalidate_entry_cache(struct dentry *entry)
1018cbdf1e6SMiklos Szeredi {
1020a0898cfSMiklos Szeredi 	fuse_dentry_settime(entry, 0);
1038cbdf1e6SMiklos Szeredi }
1048cbdf1e6SMiklos Szeredi 
1056f9f1180SMiklos Szeredi /*
1066f9f1180SMiklos Szeredi  * Same as fuse_invalidate_entry_cache(), but also try to remove the
1076f9f1180SMiklos Szeredi  * dentry from the hash
1086f9f1180SMiklos Szeredi  */
1098cbdf1e6SMiklos Szeredi static void fuse_invalidate_entry(struct dentry *entry)
1108cbdf1e6SMiklos Szeredi {
1118cbdf1e6SMiklos Szeredi 	d_invalidate(entry);
1128cbdf1e6SMiklos Szeredi 	fuse_invalidate_entry_cache(entry);
1130aa7c699SMiklos Szeredi }
1140aa7c699SMiklos Szeredi 
115c180eebeSMiklos Szeredi static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_req *req,
116c180eebeSMiklos Szeredi 			     u64 nodeid, struct qstr *name,
117e5e5558eSMiklos Szeredi 			     struct fuse_entry_out *outarg)
118e5e5558eSMiklos Szeredi {
1190e9663eeSMiklos Szeredi 	memset(outarg, 0, sizeof(struct fuse_entry_out));
120e5e5558eSMiklos Szeredi 	req->in.h.opcode = FUSE_LOOKUP;
121c180eebeSMiklos Szeredi 	req->in.h.nodeid = nodeid;
122e5e5558eSMiklos Szeredi 	req->in.numargs = 1;
123c180eebeSMiklos Szeredi 	req->in.args[0].size = name->len + 1;
124c180eebeSMiklos Szeredi 	req->in.args[0].value = name->name;
125e5e5558eSMiklos Szeredi 	req->out.numargs = 1;
1260e9663eeSMiklos Szeredi 	if (fc->minor < 9)
1270e9663eeSMiklos Szeredi 		req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
1280e9663eeSMiklos Szeredi 	else
129e5e5558eSMiklos Szeredi 		req->out.args[0].size = sizeof(struct fuse_entry_out);
130e5e5558eSMiklos Szeredi 	req->out.args[0].value = outarg;
131e5e5558eSMiklos Szeredi }
132e5e5558eSMiklos Szeredi 
1335c5c5e51SMiklos Szeredi u64 fuse_get_attr_version(struct fuse_conn *fc)
1347dca9fd3SMiklos Szeredi {
1357dca9fd3SMiklos Szeredi 	u64 curr_version;
1367dca9fd3SMiklos Szeredi 
1377dca9fd3SMiklos Szeredi 	/*
1387dca9fd3SMiklos Szeredi 	 * The spin lock isn't actually needed on 64bit archs, but we
1397dca9fd3SMiklos Szeredi 	 * don't yet care too much about such optimizations.
1407dca9fd3SMiklos Szeredi 	 */
1417dca9fd3SMiklos Szeredi 	spin_lock(&fc->lock);
1427dca9fd3SMiklos Szeredi 	curr_version = fc->attr_version;
1437dca9fd3SMiklos Szeredi 	spin_unlock(&fc->lock);
1447dca9fd3SMiklos Szeredi 
1457dca9fd3SMiklos Szeredi 	return curr_version;
1467dca9fd3SMiklos Szeredi }
1477dca9fd3SMiklos Szeredi 
1486f9f1180SMiklos Szeredi /*
1496f9f1180SMiklos Szeredi  * Check whether the dentry is still valid
1506f9f1180SMiklos Szeredi  *
1516f9f1180SMiklos Szeredi  * If the entry validity timeout has expired and the dentry is
1526f9f1180SMiklos Szeredi  * positive, try to redo the lookup.  If the lookup results in a
1536f9f1180SMiklos Szeredi  * different inode, then let the VFS invalidate the dentry and redo
1546f9f1180SMiklos Szeredi  * the lookup once more.  If the lookup results in the same inode,
1556f9f1180SMiklos Szeredi  * then refresh the attributes, timeouts and mark the dentry valid.
1566f9f1180SMiklos Szeredi  */
157e5e5558eSMiklos Szeredi static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
158e5e5558eSMiklos Szeredi {
15934286d66SNick Piggin 	struct inode *inode;
1608cbdf1e6SMiklos Szeredi 
161e7c0a167SMiklos Szeredi 	inode = ACCESS_ONCE(entry->d_inode);
1628cbdf1e6SMiklos Szeredi 	if (inode && is_bad_inode(inode))
163e5e5558eSMiklos Szeredi 		return 0;
1640a0898cfSMiklos Szeredi 	else if (fuse_dentry_time(entry) < get_jiffies_64()) {
165e5e5558eSMiklos Szeredi 		int err;
166e5e5558eSMiklos Szeredi 		struct fuse_entry_out outarg;
1678cbdf1e6SMiklos Szeredi 		struct fuse_conn *fc;
1688cbdf1e6SMiklos Szeredi 		struct fuse_req *req;
16907e77dcaSMiklos Szeredi 		struct fuse_forget_link *forget;
170e956edd0SMiklos Szeredi 		struct dentry *parent;
1711fb69e78SMiklos Szeredi 		u64 attr_version;
1728cbdf1e6SMiklos Szeredi 
17350322fe7SMiklos Szeredi 		/* For negative dentries, always do a fresh lookup */
1748cbdf1e6SMiklos Szeredi 		if (!inode)
1758cbdf1e6SMiklos Szeredi 			return 0;
1768cbdf1e6SMiklos Szeredi 
177d2433905SMiklos Szeredi 		if (nd && (nd->flags & LOOKUP_RCU))
178e7c0a167SMiklos Szeredi 			return -ECHILD;
179e7c0a167SMiklos Szeredi 
1808cbdf1e6SMiklos Szeredi 		fc = get_fuse_conn(inode);
181ce1d5a49SMiklos Szeredi 		req = fuse_get_req(fc);
182ce1d5a49SMiklos Szeredi 		if (IS_ERR(req))
183e5e5558eSMiklos Szeredi 			return 0;
184e5e5558eSMiklos Szeredi 
18507e77dcaSMiklos Szeredi 		forget = fuse_alloc_forget();
18607e77dcaSMiklos Szeredi 		if (!forget) {
1872d51013eSMiklos Szeredi 			fuse_put_request(fc, req);
1882d51013eSMiklos Szeredi 			return 0;
1892d51013eSMiklos Szeredi 		}
1902d51013eSMiklos Szeredi 
1917dca9fd3SMiklos Szeredi 		attr_version = fuse_get_attr_version(fc);
1921fb69e78SMiklos Szeredi 
193e956edd0SMiklos Szeredi 		parent = dget_parent(entry);
194c180eebeSMiklos Szeredi 		fuse_lookup_init(fc, req, get_node_id(parent->d_inode),
195c180eebeSMiklos Szeredi 				 &entry->d_name, &outarg);
196b93f858aSTejun Heo 		fuse_request_send(fc, req);
197e956edd0SMiklos Szeredi 		dput(parent);
198e5e5558eSMiklos Szeredi 		err = req->out.h.error;
1992d51013eSMiklos Szeredi 		fuse_put_request(fc, req);
20050322fe7SMiklos Szeredi 		/* Zero nodeid is same as -ENOENT */
20150322fe7SMiklos Szeredi 		if (!err && !outarg.nodeid)
20250322fe7SMiklos Szeredi 			err = -ENOENT;
2039e6268dbSMiklos Szeredi 		if (!err) {
2048cbdf1e6SMiklos Szeredi 			struct fuse_inode *fi = get_fuse_inode(inode);
2059e6268dbSMiklos Szeredi 			if (outarg.nodeid != get_node_id(inode)) {
20607e77dcaSMiklos Szeredi 				fuse_queue_forget(fc, forget, outarg.nodeid, 1);
2079e6268dbSMiklos Szeredi 				return 0;
2089e6268dbSMiklos Szeredi 			}
2098da5ff23SMiklos Szeredi 			spin_lock(&fc->lock);
2109e6268dbSMiklos Szeredi 			fi->nlookup++;
2118da5ff23SMiklos Szeredi 			spin_unlock(&fc->lock);
2129e6268dbSMiklos Szeredi 		}
21307e77dcaSMiklos Szeredi 		kfree(forget);
2149e6268dbSMiklos Szeredi 		if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT)
215e5e5558eSMiklos Szeredi 			return 0;
216e5e5558eSMiklos Szeredi 
2171fb69e78SMiklos Szeredi 		fuse_change_attributes(inode, &outarg.attr,
2181fb69e78SMiklos Szeredi 				       entry_attr_timeout(&outarg),
2191fb69e78SMiklos Szeredi 				       attr_version);
2201fb69e78SMiklos Szeredi 		fuse_change_entry_timeout(entry, &outarg);
221e5e5558eSMiklos Szeredi 	}
222e5e5558eSMiklos Szeredi 	return 1;
223e5e5558eSMiklos Szeredi }
224e5e5558eSMiklos Szeredi 
2258bfc016dSMiklos Szeredi static int invalid_nodeid(u64 nodeid)
2262827d0b2SMiklos Szeredi {
2272827d0b2SMiklos Szeredi 	return !nodeid || nodeid == FUSE_ROOT_ID;
2282827d0b2SMiklos Szeredi }
2292827d0b2SMiklos Szeredi 
2304269590aSAl Viro const struct dentry_operations fuse_dentry_operations = {
231e5e5558eSMiklos Szeredi 	.d_revalidate	= fuse_dentry_revalidate,
232e5e5558eSMiklos Szeredi };
233e5e5558eSMiklos Szeredi 
234a5bfffacSTimo Savola int fuse_valid_type(int m)
23539ee059aSMiklos Szeredi {
23639ee059aSMiklos Szeredi 	return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) ||
23739ee059aSMiklos Szeredi 		S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m);
23839ee059aSMiklos Szeredi }
23939ee059aSMiklos Szeredi 
240d2a85164SMiklos Szeredi /*
241d2a85164SMiklos Szeredi  * Add a directory inode to a dentry, ensuring that no other dentry
242d2a85164SMiklos Szeredi  * refers to this inode.  Called with fc->inst_mutex.
243d2a85164SMiklos Szeredi  */
2440de6256dSMiklos Szeredi static struct dentry *fuse_d_add_directory(struct dentry *entry,
2450de6256dSMiklos Szeredi 					   struct inode *inode)
246d2a85164SMiklos Szeredi {
247d2a85164SMiklos Szeredi 	struct dentry *alias = d_find_alias(inode);
2480de6256dSMiklos Szeredi 	if (alias && !(alias->d_flags & DCACHE_DISCONNECTED)) {
249d2a85164SMiklos Szeredi 		/* This tries to shrink the subtree below alias */
250d2a85164SMiklos Szeredi 		fuse_invalidate_entry(alias);
251d2a85164SMiklos Szeredi 		dput(alias);
252b3d9b7a3SAl Viro 		if (!hlist_empty(&inode->i_dentry))
2530de6256dSMiklos Szeredi 			return ERR_PTR(-EBUSY);
2540de6256dSMiklos Szeredi 	} else {
2550de6256dSMiklos Szeredi 		dput(alias);
256d2a85164SMiklos Szeredi 	}
2570de6256dSMiklos Szeredi 	return d_splice_alias(inode, entry);
258d2a85164SMiklos Szeredi }
259d2a85164SMiklos Szeredi 
260c180eebeSMiklos Szeredi int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name,
261c180eebeSMiklos Szeredi 		     struct fuse_entry_out *outarg, struct inode **inode)
262c180eebeSMiklos Szeredi {
263c180eebeSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn_super(sb);
264c180eebeSMiklos Szeredi 	struct fuse_req *req;
26507e77dcaSMiklos Szeredi 	struct fuse_forget_link *forget;
266c180eebeSMiklos Szeredi 	u64 attr_version;
267c180eebeSMiklos Szeredi 	int err;
268c180eebeSMiklos Szeredi 
269c180eebeSMiklos Szeredi 	*inode = NULL;
270c180eebeSMiklos Szeredi 	err = -ENAMETOOLONG;
271c180eebeSMiklos Szeredi 	if (name->len > FUSE_NAME_MAX)
272c180eebeSMiklos Szeredi 		goto out;
273c180eebeSMiklos Szeredi 
274c180eebeSMiklos Szeredi 	req = fuse_get_req(fc);
275c180eebeSMiklos Szeredi 	err = PTR_ERR(req);
276c180eebeSMiklos Szeredi 	if (IS_ERR(req))
277c180eebeSMiklos Szeredi 		goto out;
278c180eebeSMiklos Szeredi 
27907e77dcaSMiklos Szeredi 	forget = fuse_alloc_forget();
28007e77dcaSMiklos Szeredi 	err = -ENOMEM;
28107e77dcaSMiklos Szeredi 	if (!forget) {
282c180eebeSMiklos Szeredi 		fuse_put_request(fc, req);
283c180eebeSMiklos Szeredi 		goto out;
284c180eebeSMiklos Szeredi 	}
285c180eebeSMiklos Szeredi 
286c180eebeSMiklos Szeredi 	attr_version = fuse_get_attr_version(fc);
287c180eebeSMiklos Szeredi 
288c180eebeSMiklos Szeredi 	fuse_lookup_init(fc, req, nodeid, name, outarg);
289b93f858aSTejun Heo 	fuse_request_send(fc, req);
290c180eebeSMiklos Szeredi 	err = req->out.h.error;
291c180eebeSMiklos Szeredi 	fuse_put_request(fc, req);
292c180eebeSMiklos Szeredi 	/* Zero nodeid is same as -ENOENT, but with valid timeout */
293c180eebeSMiklos Szeredi 	if (err || !outarg->nodeid)
294c180eebeSMiklos Szeredi 		goto out_put_forget;
295c180eebeSMiklos Szeredi 
296c180eebeSMiklos Szeredi 	err = -EIO;
297c180eebeSMiklos Szeredi 	if (!outarg->nodeid)
298c180eebeSMiklos Szeredi 		goto out_put_forget;
299c180eebeSMiklos Szeredi 	if (!fuse_valid_type(outarg->attr.mode))
300c180eebeSMiklos Szeredi 		goto out_put_forget;
301c180eebeSMiklos Szeredi 
302c180eebeSMiklos Szeredi 	*inode = fuse_iget(sb, outarg->nodeid, outarg->generation,
303c180eebeSMiklos Szeredi 			   &outarg->attr, entry_attr_timeout(outarg),
304c180eebeSMiklos Szeredi 			   attr_version);
305c180eebeSMiklos Szeredi 	err = -ENOMEM;
306c180eebeSMiklos Szeredi 	if (!*inode) {
30707e77dcaSMiklos Szeredi 		fuse_queue_forget(fc, forget, outarg->nodeid, 1);
308c180eebeSMiklos Szeredi 		goto out;
309c180eebeSMiklos Szeredi 	}
310c180eebeSMiklos Szeredi 	err = 0;
311c180eebeSMiklos Szeredi 
312c180eebeSMiklos Szeredi  out_put_forget:
31307e77dcaSMiklos Szeredi 	kfree(forget);
314c180eebeSMiklos Szeredi  out:
315c180eebeSMiklos Szeredi 	return err;
316c180eebeSMiklos Szeredi }
317c180eebeSMiklos Szeredi 
3180aa7c699SMiklos Szeredi static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
3190aa7c699SMiklos Szeredi 				  struct nameidata *nd)
320e5e5558eSMiklos Szeredi {
321e5e5558eSMiklos Szeredi 	int err;
322e5e5558eSMiklos Szeredi 	struct fuse_entry_out outarg;
323c180eebeSMiklos Szeredi 	struct inode *inode;
3240de6256dSMiklos Szeredi 	struct dentry *newent;
325e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
326c180eebeSMiklos Szeredi 	bool outarg_valid = true;
327e5e5558eSMiklos Szeredi 
328c180eebeSMiklos Szeredi 	err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name,
329c180eebeSMiklos Szeredi 			       &outarg, &inode);
330c180eebeSMiklos Szeredi 	if (err == -ENOENT) {
331c180eebeSMiklos Szeredi 		outarg_valid = false;
332c180eebeSMiklos Szeredi 		err = 0;
3332d51013eSMiklos Szeredi 	}
334c180eebeSMiklos Szeredi 	if (err)
335c180eebeSMiklos Szeredi 		goto out_err;
3362d51013eSMiklos Szeredi 
337ee4e5271SMiklos Szeredi 	err = -EIO;
338c180eebeSMiklos Szeredi 	if (inode && get_node_id(inode) == FUSE_ROOT_ID)
339c180eebeSMiklos Szeredi 		goto out_iput;
340e5e5558eSMiklos Szeredi 
341d2a85164SMiklos Szeredi 	if (inode && S_ISDIR(inode->i_mode)) {
342d2a85164SMiklos Szeredi 		mutex_lock(&fc->inst_mutex);
3430de6256dSMiklos Szeredi 		newent = fuse_d_add_directory(entry, inode);
344d2a85164SMiklos Szeredi 		mutex_unlock(&fc->inst_mutex);
345c180eebeSMiklos Szeredi 		err = PTR_ERR(newent);
346c180eebeSMiklos Szeredi 		if (IS_ERR(newent))
347c180eebeSMiklos Szeredi 			goto out_iput;
348c180eebeSMiklos Szeredi 	} else {
3490de6256dSMiklos Szeredi 		newent = d_splice_alias(inode, entry);
350c180eebeSMiklos Szeredi 	}
351d2a85164SMiklos Szeredi 
3520de6256dSMiklos Szeredi 	entry = newent ? newent : entry;
353c180eebeSMiklos Szeredi 	if (outarg_valid)
3541fb69e78SMiklos Szeredi 		fuse_change_entry_timeout(entry, &outarg);
3558cbdf1e6SMiklos Szeredi 	else
3568cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
357c180eebeSMiklos Szeredi 
3580de6256dSMiklos Szeredi 	return newent;
359c180eebeSMiklos Szeredi 
360c180eebeSMiklos Szeredi  out_iput:
361c180eebeSMiklos Szeredi 	iput(inode);
362c180eebeSMiklos Szeredi  out_err:
363c180eebeSMiklos Szeredi 	return ERR_PTR(err);
364e5e5558eSMiklos Szeredi }
365e5e5558eSMiklos Szeredi 
3666f9f1180SMiklos Szeredi /*
3676f9f1180SMiklos Szeredi  * Atomic create+open operation
3686f9f1180SMiklos Szeredi  *
3696f9f1180SMiklos Szeredi  * If the filesystem doesn't support this, then fall back to separate
3706f9f1180SMiklos Szeredi  * 'mknod' + 'open' requests.
3716f9f1180SMiklos Szeredi  */
372*d9585277SAl Viro static int fuse_create_open(struct inode *dir, struct dentry *entry,
373c8ccbe03SMiklos Szeredi 			    struct opendata *od, unsigned flags,
37447237687SAl Viro 			    umode_t mode, int *opened)
375fd72faacSMiklos Szeredi {
376fd72faacSMiklos Szeredi 	int err;
377fd72faacSMiklos Szeredi 	struct inode *inode;
378fd72faacSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
379fd72faacSMiklos Szeredi 	struct fuse_req *req;
38007e77dcaSMiklos Szeredi 	struct fuse_forget_link *forget;
381e0a43ddcSMiklos Szeredi 	struct fuse_create_in inarg;
382fd72faacSMiklos Szeredi 	struct fuse_open_out outopen;
383fd72faacSMiklos Szeredi 	struct fuse_entry_out outentry;
384fd72faacSMiklos Szeredi 	struct fuse_file *ff;
385fd72faacSMiklos Szeredi 	struct file *file;
386fd72faacSMiklos Szeredi 
38707e77dcaSMiklos Szeredi 	forget = fuse_alloc_forget();
388c8ccbe03SMiklos Szeredi 	err = -ENOMEM;
38907e77dcaSMiklos Szeredi 	if (!forget)
390c8ccbe03SMiklos Szeredi 		goto out_err;
39151eb01e7SMiklos Szeredi 
392ce1d5a49SMiklos Szeredi 	req = fuse_get_req(fc);
39351eb01e7SMiklos Szeredi 	err = PTR_ERR(req);
394ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
39551eb01e7SMiklos Szeredi 		goto out_put_forget_req;
396fd72faacSMiklos Szeredi 
397ce1d5a49SMiklos Szeredi 	err = -ENOMEM;
398acf99433STejun Heo 	ff = fuse_file_alloc(fc);
399fd72faacSMiklos Szeredi 	if (!ff)
400fd72faacSMiklos Szeredi 		goto out_put_request;
401fd72faacSMiklos Szeredi 
402e0a43ddcSMiklos Szeredi 	if (!fc->dont_mask)
403e0a43ddcSMiklos Szeredi 		mode &= ~current_umask();
404e0a43ddcSMiklos Szeredi 
405fd72faacSMiklos Szeredi 	flags &= ~O_NOCTTY;
406fd72faacSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
4070e9663eeSMiklos Szeredi 	memset(&outentry, 0, sizeof(outentry));
408fd72faacSMiklos Szeredi 	inarg.flags = flags;
409fd72faacSMiklos Szeredi 	inarg.mode = mode;
410e0a43ddcSMiklos Szeredi 	inarg.umask = current_umask();
411fd72faacSMiklos Szeredi 	req->in.h.opcode = FUSE_CREATE;
412fd72faacSMiklos Szeredi 	req->in.h.nodeid = get_node_id(dir);
413fd72faacSMiklos Szeredi 	req->in.numargs = 2;
414e0a43ddcSMiklos Szeredi 	req->in.args[0].size = fc->minor < 12 ? sizeof(struct fuse_open_in) :
415e0a43ddcSMiklos Szeredi 						sizeof(inarg);
416fd72faacSMiklos Szeredi 	req->in.args[0].value = &inarg;
417fd72faacSMiklos Szeredi 	req->in.args[1].size = entry->d_name.len + 1;
418fd72faacSMiklos Szeredi 	req->in.args[1].value = entry->d_name.name;
419fd72faacSMiklos Szeredi 	req->out.numargs = 2;
4200e9663eeSMiklos Szeredi 	if (fc->minor < 9)
4210e9663eeSMiklos Szeredi 		req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
4220e9663eeSMiklos Szeredi 	else
423fd72faacSMiklos Szeredi 		req->out.args[0].size = sizeof(outentry);
424fd72faacSMiklos Szeredi 	req->out.args[0].value = &outentry;
425fd72faacSMiklos Szeredi 	req->out.args[1].size = sizeof(outopen);
426fd72faacSMiklos Szeredi 	req->out.args[1].value = &outopen;
427b93f858aSTejun Heo 	fuse_request_send(fc, req);
428fd72faacSMiklos Szeredi 	err = req->out.h.error;
429c8ccbe03SMiklos Szeredi 	if (err)
430fd72faacSMiklos Szeredi 		goto out_free_ff;
431fd72faacSMiklos Szeredi 
432fd72faacSMiklos Szeredi 	err = -EIO;
4332827d0b2SMiklos Szeredi 	if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid))
434fd72faacSMiklos Szeredi 		goto out_free_ff;
435fd72faacSMiklos Szeredi 
43651eb01e7SMiklos Szeredi 	fuse_put_request(fc, req);
437c7b7143cSMiklos Szeredi 	ff->fh = outopen.fh;
438c7b7143cSMiklos Szeredi 	ff->nodeid = outentry.nodeid;
439c7b7143cSMiklos Szeredi 	ff->open_flags = outopen.open_flags;
440fd72faacSMiklos Szeredi 	inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
4411fb69e78SMiklos Szeredi 			  &outentry.attr, entry_attr_timeout(&outentry), 0);
442fd72faacSMiklos Szeredi 	if (!inode) {
443fd72faacSMiklos Szeredi 		flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
4448b0797a4SMiklos Szeredi 		fuse_sync_release(ff, flags);
44507e77dcaSMiklos Szeredi 		fuse_queue_forget(fc, forget, outentry.nodeid, 1);
446c8ccbe03SMiklos Szeredi 		err = -ENOMEM;
447c8ccbe03SMiklos Szeredi 		goto out_err;
448fd72faacSMiklos Szeredi 	}
44907e77dcaSMiklos Szeredi 	kfree(forget);
450fd72faacSMiklos Szeredi 	d_instantiate(entry, inode);
4511fb69e78SMiklos Szeredi 	fuse_change_entry_timeout(entry, &outentry);
4520952b2a4SMiklos Szeredi 	fuse_invalidate_attr(dir);
45347237687SAl Viro 	file = finish_open(od, entry, generic_file_open, opened);
454fd72faacSMiklos Szeredi 	if (IS_ERR(file)) {
455*d9585277SAl Viro 		err = PTR_ERR(file);
4568b0797a4SMiklos Szeredi 		fuse_sync_release(ff, flags);
457c8ccbe03SMiklos Szeredi 	} else {
458c7b7143cSMiklos Szeredi 		file->private_data = fuse_file_get(ff);
459c7b7143cSMiklos Szeredi 		fuse_finish_open(inode, file);
460*d9585277SAl Viro 		err = 0;
461c8ccbe03SMiklos Szeredi 	}
462*d9585277SAl Viro 	return err;
463fd72faacSMiklos Szeredi 
464fd72faacSMiklos Szeredi out_free_ff:
465fd72faacSMiklos Szeredi 	fuse_file_free(ff);
466fd72faacSMiklos Szeredi out_put_request:
467fd72faacSMiklos Szeredi 	fuse_put_request(fc, req);
46851eb01e7SMiklos Szeredi out_put_forget_req:
46907e77dcaSMiklos Szeredi 	kfree(forget);
470c8ccbe03SMiklos Szeredi out_err:
471*d9585277SAl Viro 	return err;
472c8ccbe03SMiklos Szeredi }
473c8ccbe03SMiklos Szeredi 
474c8ccbe03SMiklos Szeredi static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t);
475*d9585277SAl Viro static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
476c8ccbe03SMiklos Szeredi 			    struct opendata *od, unsigned flags,
47747237687SAl Viro 			    umode_t mode, int *opened)
478c8ccbe03SMiklos Szeredi {
479c8ccbe03SMiklos Szeredi 	int err;
480c8ccbe03SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
481c8ccbe03SMiklos Szeredi 	struct dentry *res = NULL;
482c8ccbe03SMiklos Szeredi 
483c8ccbe03SMiklos Szeredi 	if (d_unhashed(entry)) {
484c8ccbe03SMiklos Szeredi 		res = fuse_lookup(dir, entry, NULL);
485c8ccbe03SMiklos Szeredi 		if (IS_ERR(res))
486*d9585277SAl Viro 			return PTR_ERR(res);
487c8ccbe03SMiklos Szeredi 
488c8ccbe03SMiklos Szeredi 		if (res)
489c8ccbe03SMiklos Szeredi 			entry = res;
490c8ccbe03SMiklos Szeredi 	}
491c8ccbe03SMiklos Szeredi 
492c8ccbe03SMiklos Szeredi 	if (!(flags & O_CREAT) || entry->d_inode)
493c8ccbe03SMiklos Szeredi 		goto no_open;
494c8ccbe03SMiklos Szeredi 
495c8ccbe03SMiklos Szeredi 	/* Only creates */
49647237687SAl Viro 	*opened |= FILE_CREATED;
497c8ccbe03SMiklos Szeredi 
498c8ccbe03SMiklos Szeredi 	if (fc->no_create)
499c8ccbe03SMiklos Szeredi 		goto mknod;
500c8ccbe03SMiklos Szeredi 
501*d9585277SAl Viro 	err = fuse_create_open(dir, entry, od, flags, mode, opened);
502*d9585277SAl Viro 	if (err == -ENOSYS) {
503c8ccbe03SMiklos Szeredi 		fc->no_create = 1;
504c8ccbe03SMiklos Szeredi 		goto mknod;
505c8ccbe03SMiklos Szeredi 	}
506c8ccbe03SMiklos Szeredi out_dput:
507c8ccbe03SMiklos Szeredi 	dput(res);
508*d9585277SAl Viro 	return err;
509c8ccbe03SMiklos Szeredi 
510c8ccbe03SMiklos Szeredi mknod:
511c8ccbe03SMiklos Szeredi 	err = fuse_mknod(dir, entry, mode, 0);
512*d9585277SAl Viro 	if (err)
513c8ccbe03SMiklos Szeredi 		goto out_dput;
514c8ccbe03SMiklos Szeredi no_open:
515c8ccbe03SMiklos Szeredi 	finish_no_open(od, res);
516*d9585277SAl Viro 	return 1;
517fd72faacSMiklos Szeredi }
518fd72faacSMiklos Szeredi 
5196f9f1180SMiklos Szeredi /*
5206f9f1180SMiklos Szeredi  * Code shared between mknod, mkdir, symlink and link
5216f9f1180SMiklos Szeredi  */
5229e6268dbSMiklos Szeredi static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
5239e6268dbSMiklos Szeredi 			    struct inode *dir, struct dentry *entry,
524541af6a0SAl Viro 			    umode_t mode)
5259e6268dbSMiklos Szeredi {
5269e6268dbSMiklos Szeredi 	struct fuse_entry_out outarg;
5279e6268dbSMiklos Szeredi 	struct inode *inode;
5289e6268dbSMiklos Szeredi 	int err;
52907e77dcaSMiklos Szeredi 	struct fuse_forget_link *forget;
5302d51013eSMiklos Szeredi 
53107e77dcaSMiklos Szeredi 	forget = fuse_alloc_forget();
53207e77dcaSMiklos Szeredi 	if (!forget) {
5332d51013eSMiklos Szeredi 		fuse_put_request(fc, req);
53407e77dcaSMiklos Szeredi 		return -ENOMEM;
5352d51013eSMiklos Szeredi 	}
5369e6268dbSMiklos Szeredi 
5370e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
5389e6268dbSMiklos Szeredi 	req->in.h.nodeid = get_node_id(dir);
5399e6268dbSMiklos Szeredi 	req->out.numargs = 1;
5400e9663eeSMiklos Szeredi 	if (fc->minor < 9)
5410e9663eeSMiklos Szeredi 		req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
5420e9663eeSMiklos Szeredi 	else
5439e6268dbSMiklos Szeredi 		req->out.args[0].size = sizeof(outarg);
5449e6268dbSMiklos Szeredi 	req->out.args[0].value = &outarg;
545b93f858aSTejun Heo 	fuse_request_send(fc, req);
5469e6268dbSMiklos Szeredi 	err = req->out.h.error;
5479e6268dbSMiklos Szeredi 	fuse_put_request(fc, req);
5482d51013eSMiklos Szeredi 	if (err)
5492d51013eSMiklos Szeredi 		goto out_put_forget_req;
5502d51013eSMiklos Szeredi 
55139ee059aSMiklos Szeredi 	err = -EIO;
55239ee059aSMiklos Szeredi 	if (invalid_nodeid(outarg.nodeid))
5532d51013eSMiklos Szeredi 		goto out_put_forget_req;
55439ee059aSMiklos Szeredi 
55539ee059aSMiklos Szeredi 	if ((outarg.attr.mode ^ mode) & S_IFMT)
5562d51013eSMiklos Szeredi 		goto out_put_forget_req;
55739ee059aSMiklos Szeredi 
5589e6268dbSMiklos Szeredi 	inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
5591fb69e78SMiklos Szeredi 			  &outarg.attr, entry_attr_timeout(&outarg), 0);
5609e6268dbSMiklos Szeredi 	if (!inode) {
56107e77dcaSMiklos Szeredi 		fuse_queue_forget(fc, forget, outarg.nodeid, 1);
5629e6268dbSMiklos Szeredi 		return -ENOMEM;
5639e6268dbSMiklos Szeredi 	}
56407e77dcaSMiklos Szeredi 	kfree(forget);
5659e6268dbSMiklos Szeredi 
566d2a85164SMiklos Szeredi 	if (S_ISDIR(inode->i_mode)) {
567d2a85164SMiklos Szeredi 		struct dentry *alias;
568d2a85164SMiklos Szeredi 		mutex_lock(&fc->inst_mutex);
569d2a85164SMiklos Szeredi 		alias = d_find_alias(inode);
570d2a85164SMiklos Szeredi 		if (alias) {
571d2a85164SMiklos Szeredi 			/* New directory must have moved since mkdir */
572d2a85164SMiklos Szeredi 			mutex_unlock(&fc->inst_mutex);
573d2a85164SMiklos Szeredi 			dput(alias);
5749e6268dbSMiklos Szeredi 			iput(inode);
575d2a85164SMiklos Szeredi 			return -EBUSY;
5769e6268dbSMiklos Szeredi 		}
5779e6268dbSMiklos Szeredi 		d_instantiate(entry, inode);
578d2a85164SMiklos Szeredi 		mutex_unlock(&fc->inst_mutex);
579d2a85164SMiklos Szeredi 	} else
580d2a85164SMiklos Szeredi 		d_instantiate(entry, inode);
581d2a85164SMiklos Szeredi 
5821fb69e78SMiklos Szeredi 	fuse_change_entry_timeout(entry, &outarg);
5839e6268dbSMiklos Szeredi 	fuse_invalidate_attr(dir);
5849e6268dbSMiklos Szeredi 	return 0;
58539ee059aSMiklos Szeredi 
5862d51013eSMiklos Szeredi  out_put_forget_req:
58707e77dcaSMiklos Szeredi 	kfree(forget);
58839ee059aSMiklos Szeredi 	return err;
5899e6268dbSMiklos Szeredi }
5909e6268dbSMiklos Szeredi 
5911a67aafbSAl Viro static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode,
5929e6268dbSMiklos Szeredi 		      dev_t rdev)
5939e6268dbSMiklos Szeredi {
5949e6268dbSMiklos Szeredi 	struct fuse_mknod_in inarg;
5959e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
596ce1d5a49SMiklos Szeredi 	struct fuse_req *req = fuse_get_req(fc);
597ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
598ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
5999e6268dbSMiklos Szeredi 
600e0a43ddcSMiklos Szeredi 	if (!fc->dont_mask)
601e0a43ddcSMiklos Szeredi 		mode &= ~current_umask();
602e0a43ddcSMiklos Szeredi 
6039e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
6049e6268dbSMiklos Szeredi 	inarg.mode = mode;
6059e6268dbSMiklos Szeredi 	inarg.rdev = new_encode_dev(rdev);
606e0a43ddcSMiklos Szeredi 	inarg.umask = current_umask();
6079e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_MKNOD;
6089e6268dbSMiklos Szeredi 	req->in.numargs = 2;
609e0a43ddcSMiklos Szeredi 	req->in.args[0].size = fc->minor < 12 ? FUSE_COMPAT_MKNOD_IN_SIZE :
610e0a43ddcSMiklos Szeredi 						sizeof(inarg);
6119e6268dbSMiklos Szeredi 	req->in.args[0].value = &inarg;
6129e6268dbSMiklos Szeredi 	req->in.args[1].size = entry->d_name.len + 1;
6139e6268dbSMiklos Szeredi 	req->in.args[1].value = entry->d_name.name;
6149e6268dbSMiklos Szeredi 	return create_new_entry(fc, req, dir, entry, mode);
6159e6268dbSMiklos Szeredi }
6169e6268dbSMiklos Szeredi 
6174acdaf27SAl Viro static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode,
6189e6268dbSMiklos Szeredi 		       struct nameidata *nd)
6199e6268dbSMiklos Szeredi {
6209e6268dbSMiklos Szeredi 	return fuse_mknod(dir, entry, mode, 0);
6219e6268dbSMiklos Szeredi }
6229e6268dbSMiklos Szeredi 
62318bb1db3SAl Viro static int fuse_mkdir(struct inode *dir, struct dentry *entry, umode_t mode)
6249e6268dbSMiklos Szeredi {
6259e6268dbSMiklos Szeredi 	struct fuse_mkdir_in inarg;
6269e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
627ce1d5a49SMiklos Szeredi 	struct fuse_req *req = fuse_get_req(fc);
628ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
629ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
6309e6268dbSMiklos Szeredi 
631e0a43ddcSMiklos Szeredi 	if (!fc->dont_mask)
632e0a43ddcSMiklos Szeredi 		mode &= ~current_umask();
633e0a43ddcSMiklos Szeredi 
6349e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
6359e6268dbSMiklos Szeredi 	inarg.mode = mode;
636e0a43ddcSMiklos Szeredi 	inarg.umask = current_umask();
6379e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_MKDIR;
6389e6268dbSMiklos Szeredi 	req->in.numargs = 2;
6399e6268dbSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
6409e6268dbSMiklos Szeredi 	req->in.args[0].value = &inarg;
6419e6268dbSMiklos Szeredi 	req->in.args[1].size = entry->d_name.len + 1;
6429e6268dbSMiklos Szeredi 	req->in.args[1].value = entry->d_name.name;
6439e6268dbSMiklos Szeredi 	return create_new_entry(fc, req, dir, entry, S_IFDIR);
6449e6268dbSMiklos Szeredi }
6459e6268dbSMiklos Szeredi 
6469e6268dbSMiklos Szeredi static int fuse_symlink(struct inode *dir, struct dentry *entry,
6479e6268dbSMiklos Szeredi 			const char *link)
6489e6268dbSMiklos Szeredi {
6499e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
6509e6268dbSMiklos Szeredi 	unsigned len = strlen(link) + 1;
651ce1d5a49SMiklos Szeredi 	struct fuse_req *req = fuse_get_req(fc);
652ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
653ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
6549e6268dbSMiklos Szeredi 
6559e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_SYMLINK;
6569e6268dbSMiklos Szeredi 	req->in.numargs = 2;
6579e6268dbSMiklos Szeredi 	req->in.args[0].size = entry->d_name.len + 1;
6589e6268dbSMiklos Szeredi 	req->in.args[0].value = entry->d_name.name;
6599e6268dbSMiklos Szeredi 	req->in.args[1].size = len;
6609e6268dbSMiklos Szeredi 	req->in.args[1].value = link;
6619e6268dbSMiklos Szeredi 	return create_new_entry(fc, req, dir, entry, S_IFLNK);
6629e6268dbSMiklos Szeredi }
6639e6268dbSMiklos Szeredi 
6649e6268dbSMiklos Szeredi static int fuse_unlink(struct inode *dir, struct dentry *entry)
6659e6268dbSMiklos Szeredi {
6669e6268dbSMiklos Szeredi 	int err;
6679e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
668ce1d5a49SMiklos Szeredi 	struct fuse_req *req = fuse_get_req(fc);
669ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
670ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
6719e6268dbSMiklos Szeredi 
6729e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_UNLINK;
6739e6268dbSMiklos Szeredi 	req->in.h.nodeid = get_node_id(dir);
6749e6268dbSMiklos Szeredi 	req->in.numargs = 1;
6759e6268dbSMiklos Szeredi 	req->in.args[0].size = entry->d_name.len + 1;
6769e6268dbSMiklos Szeredi 	req->in.args[0].value = entry->d_name.name;
677b93f858aSTejun Heo 	fuse_request_send(fc, req);
6789e6268dbSMiklos Szeredi 	err = req->out.h.error;
6799e6268dbSMiklos Szeredi 	fuse_put_request(fc, req);
6809e6268dbSMiklos Szeredi 	if (!err) {
6819e6268dbSMiklos Szeredi 		struct inode *inode = entry->d_inode;
682ac45d613SMiklos Szeredi 		struct fuse_inode *fi = get_fuse_inode(inode);
6839e6268dbSMiklos Szeredi 
684ac45d613SMiklos Szeredi 		spin_lock(&fc->lock);
685ac45d613SMiklos Szeredi 		fi->attr_version = ++fc->attr_version;
686ac45d613SMiklos Szeredi 		drop_nlink(inode);
687ac45d613SMiklos Szeredi 		spin_unlock(&fc->lock);
6889e6268dbSMiklos Szeredi 		fuse_invalidate_attr(inode);
6899e6268dbSMiklos Szeredi 		fuse_invalidate_attr(dir);
6908cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
6919e6268dbSMiklos Szeredi 	} else if (err == -EINTR)
6929e6268dbSMiklos Szeredi 		fuse_invalidate_entry(entry);
6939e6268dbSMiklos Szeredi 	return err;
6949e6268dbSMiklos Szeredi }
6959e6268dbSMiklos Szeredi 
6969e6268dbSMiklos Szeredi static int fuse_rmdir(struct inode *dir, struct dentry *entry)
6979e6268dbSMiklos Szeredi {
6989e6268dbSMiklos Szeredi 	int err;
6999e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
700ce1d5a49SMiklos Szeredi 	struct fuse_req *req = fuse_get_req(fc);
701ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
702ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
7039e6268dbSMiklos Szeredi 
7049e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_RMDIR;
7059e6268dbSMiklos Szeredi 	req->in.h.nodeid = get_node_id(dir);
7069e6268dbSMiklos Szeredi 	req->in.numargs = 1;
7079e6268dbSMiklos Szeredi 	req->in.args[0].size = entry->d_name.len + 1;
7089e6268dbSMiklos Szeredi 	req->in.args[0].value = entry->d_name.name;
709b93f858aSTejun Heo 	fuse_request_send(fc, req);
7109e6268dbSMiklos Szeredi 	err = req->out.h.error;
7119e6268dbSMiklos Szeredi 	fuse_put_request(fc, req);
7129e6268dbSMiklos Szeredi 	if (!err) {
713ce71ec36SDave Hansen 		clear_nlink(entry->d_inode);
7149e6268dbSMiklos Szeredi 		fuse_invalidate_attr(dir);
7158cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
7169e6268dbSMiklos Szeredi 	} else if (err == -EINTR)
7179e6268dbSMiklos Szeredi 		fuse_invalidate_entry(entry);
7189e6268dbSMiklos Szeredi 	return err;
7199e6268dbSMiklos Szeredi }
7209e6268dbSMiklos Szeredi 
7219e6268dbSMiklos Szeredi static int fuse_rename(struct inode *olddir, struct dentry *oldent,
7229e6268dbSMiklos Szeredi 		       struct inode *newdir, struct dentry *newent)
7239e6268dbSMiklos Szeredi {
7249e6268dbSMiklos Szeredi 	int err;
7259e6268dbSMiklos Szeredi 	struct fuse_rename_in inarg;
7269e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(olddir);
727ce1d5a49SMiklos Szeredi 	struct fuse_req *req = fuse_get_req(fc);
728e4eaac06SSage Weil 
729ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
730ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
7319e6268dbSMiklos Szeredi 
7329e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
7339e6268dbSMiklos Szeredi 	inarg.newdir = get_node_id(newdir);
7349e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_RENAME;
7359e6268dbSMiklos Szeredi 	req->in.h.nodeid = get_node_id(olddir);
7369e6268dbSMiklos Szeredi 	req->in.numargs = 3;
7379e6268dbSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
7389e6268dbSMiklos Szeredi 	req->in.args[0].value = &inarg;
7399e6268dbSMiklos Szeredi 	req->in.args[1].size = oldent->d_name.len + 1;
7409e6268dbSMiklos Szeredi 	req->in.args[1].value = oldent->d_name.name;
7419e6268dbSMiklos Szeredi 	req->in.args[2].size = newent->d_name.len + 1;
7429e6268dbSMiklos Szeredi 	req->in.args[2].value = newent->d_name.name;
743b93f858aSTejun Heo 	fuse_request_send(fc, req);
7449e6268dbSMiklos Szeredi 	err = req->out.h.error;
7459e6268dbSMiklos Szeredi 	fuse_put_request(fc, req);
7469e6268dbSMiklos Szeredi 	if (!err) {
74708b63307SMiklos Szeredi 		/* ctime changes */
74808b63307SMiklos Szeredi 		fuse_invalidate_attr(oldent->d_inode);
74908b63307SMiklos Szeredi 
7509e6268dbSMiklos Szeredi 		fuse_invalidate_attr(olddir);
7519e6268dbSMiklos Szeredi 		if (olddir != newdir)
7529e6268dbSMiklos Szeredi 			fuse_invalidate_attr(newdir);
7538cbdf1e6SMiklos Szeredi 
7548cbdf1e6SMiklos Szeredi 		/* newent will end up negative */
7555219f346SMiklos Szeredi 		if (newent->d_inode) {
7565219f346SMiklos Szeredi 			fuse_invalidate_attr(newent->d_inode);
7578cbdf1e6SMiklos Szeredi 			fuse_invalidate_entry_cache(newent);
7585219f346SMiklos Szeredi 		}
7599e6268dbSMiklos Szeredi 	} else if (err == -EINTR) {
7609e6268dbSMiklos Szeredi 		/* If request was interrupted, DEITY only knows if the
7619e6268dbSMiklos Szeredi 		   rename actually took place.  If the invalidation
7629e6268dbSMiklos Szeredi 		   fails (e.g. some process has CWD under the renamed
7639e6268dbSMiklos Szeredi 		   directory), then there can be inconsistency between
7649e6268dbSMiklos Szeredi 		   the dcache and the real filesystem.  Tough luck. */
7659e6268dbSMiklos Szeredi 		fuse_invalidate_entry(oldent);
7669e6268dbSMiklos Szeredi 		if (newent->d_inode)
7679e6268dbSMiklos Szeredi 			fuse_invalidate_entry(newent);
7689e6268dbSMiklos Szeredi 	}
7699e6268dbSMiklos Szeredi 
7709e6268dbSMiklos Szeredi 	return err;
7719e6268dbSMiklos Szeredi }
7729e6268dbSMiklos Szeredi 
7739e6268dbSMiklos Szeredi static int fuse_link(struct dentry *entry, struct inode *newdir,
7749e6268dbSMiklos Szeredi 		     struct dentry *newent)
7759e6268dbSMiklos Szeredi {
7769e6268dbSMiklos Szeredi 	int err;
7779e6268dbSMiklos Szeredi 	struct fuse_link_in inarg;
7789e6268dbSMiklos Szeredi 	struct inode *inode = entry->d_inode;
7799e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
780ce1d5a49SMiklos Szeredi 	struct fuse_req *req = fuse_get_req(fc);
781ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
782ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
7839e6268dbSMiklos Szeredi 
7849e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
7859e6268dbSMiklos Szeredi 	inarg.oldnodeid = get_node_id(inode);
7869e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_LINK;
7879e6268dbSMiklos Szeredi 	req->in.numargs = 2;
7889e6268dbSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
7899e6268dbSMiklos Szeredi 	req->in.args[0].value = &inarg;
7909e6268dbSMiklos Szeredi 	req->in.args[1].size = newent->d_name.len + 1;
7919e6268dbSMiklos Szeredi 	req->in.args[1].value = newent->d_name.name;
7929e6268dbSMiklos Szeredi 	err = create_new_entry(fc, req, newdir, newent, inode->i_mode);
7939e6268dbSMiklos Szeredi 	/* Contrary to "normal" filesystems it can happen that link
7949e6268dbSMiklos Szeredi 	   makes two "logical" inodes point to the same "physical"
7959e6268dbSMiklos Szeredi 	   inode.  We invalidate the attributes of the old one, so it
7969e6268dbSMiklos Szeredi 	   will reflect changes in the backing inode (link count,
7979e6268dbSMiklos Szeredi 	   etc.)
7989e6268dbSMiklos Szeredi 	*/
799ac45d613SMiklos Szeredi 	if (!err) {
800ac45d613SMiklos Szeredi 		struct fuse_inode *fi = get_fuse_inode(inode);
801ac45d613SMiklos Szeredi 
802ac45d613SMiklos Szeredi 		spin_lock(&fc->lock);
803ac45d613SMiklos Szeredi 		fi->attr_version = ++fc->attr_version;
804ac45d613SMiklos Szeredi 		inc_nlink(inode);
805ac45d613SMiklos Szeredi 		spin_unlock(&fc->lock);
8069e6268dbSMiklos Szeredi 		fuse_invalidate_attr(inode);
807ac45d613SMiklos Szeredi 	} else if (err == -EINTR) {
808ac45d613SMiklos Szeredi 		fuse_invalidate_attr(inode);
809ac45d613SMiklos Szeredi 	}
8109e6268dbSMiklos Szeredi 	return err;
8119e6268dbSMiklos Szeredi }
8129e6268dbSMiklos Szeredi 
8131fb69e78SMiklos Szeredi static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
8141fb69e78SMiklos Szeredi 			  struct kstat *stat)
8151fb69e78SMiklos Szeredi {
816203627bbSMiklos Szeredi 	unsigned int blkbits;
817203627bbSMiklos Szeredi 
8181fb69e78SMiklos Szeredi 	stat->dev = inode->i_sb->s_dev;
8191fb69e78SMiklos Szeredi 	stat->ino = attr->ino;
8201fb69e78SMiklos Szeredi 	stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
8211fb69e78SMiklos Szeredi 	stat->nlink = attr->nlink;
8221fb69e78SMiklos Szeredi 	stat->uid = attr->uid;
8231fb69e78SMiklos Szeredi 	stat->gid = attr->gid;
8241fb69e78SMiklos Szeredi 	stat->rdev = inode->i_rdev;
8251fb69e78SMiklos Szeredi 	stat->atime.tv_sec = attr->atime;
8261fb69e78SMiklos Szeredi 	stat->atime.tv_nsec = attr->atimensec;
8271fb69e78SMiklos Szeredi 	stat->mtime.tv_sec = attr->mtime;
8281fb69e78SMiklos Szeredi 	stat->mtime.tv_nsec = attr->mtimensec;
8291fb69e78SMiklos Szeredi 	stat->ctime.tv_sec = attr->ctime;
8301fb69e78SMiklos Szeredi 	stat->ctime.tv_nsec = attr->ctimensec;
8311fb69e78SMiklos Szeredi 	stat->size = attr->size;
8321fb69e78SMiklos Szeredi 	stat->blocks = attr->blocks;
833203627bbSMiklos Szeredi 
834203627bbSMiklos Szeredi 	if (attr->blksize != 0)
835203627bbSMiklos Szeredi 		blkbits = ilog2(attr->blksize);
836203627bbSMiklos Szeredi 	else
837203627bbSMiklos Szeredi 		blkbits = inode->i_sb->s_blocksize_bits;
838203627bbSMiklos Szeredi 
839203627bbSMiklos Szeredi 	stat->blksize = 1 << blkbits;
8401fb69e78SMiklos Szeredi }
8411fb69e78SMiklos Szeredi 
842c79e322fSMiklos Szeredi static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
843c79e322fSMiklos Szeredi 			   struct file *file)
844e5e5558eSMiklos Szeredi {
845e5e5558eSMiklos Szeredi 	int err;
846c79e322fSMiklos Szeredi 	struct fuse_getattr_in inarg;
847c79e322fSMiklos Szeredi 	struct fuse_attr_out outarg;
848e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
8491fb69e78SMiklos Szeredi 	struct fuse_req *req;
8501fb69e78SMiklos Szeredi 	u64 attr_version;
8511fb69e78SMiklos Szeredi 
8521fb69e78SMiklos Szeredi 	req = fuse_get_req(fc);
853ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
854ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
855e5e5558eSMiklos Szeredi 
8567dca9fd3SMiklos Szeredi 	attr_version = fuse_get_attr_version(fc);
8571fb69e78SMiklos Szeredi 
858c79e322fSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
8590e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
860c79e322fSMiklos Szeredi 	/* Directories have separate file-handle space */
861c79e322fSMiklos Szeredi 	if (file && S_ISREG(inode->i_mode)) {
862c79e322fSMiklos Szeredi 		struct fuse_file *ff = file->private_data;
863c79e322fSMiklos Szeredi 
864c79e322fSMiklos Szeredi 		inarg.getattr_flags |= FUSE_GETATTR_FH;
865c79e322fSMiklos Szeredi 		inarg.fh = ff->fh;
866c79e322fSMiklos Szeredi 	}
867e5e5558eSMiklos Szeredi 	req->in.h.opcode = FUSE_GETATTR;
868e5e5558eSMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
869c79e322fSMiklos Szeredi 	req->in.numargs = 1;
870c79e322fSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
871c79e322fSMiklos Szeredi 	req->in.args[0].value = &inarg;
872e5e5558eSMiklos Szeredi 	req->out.numargs = 1;
8730e9663eeSMiklos Szeredi 	if (fc->minor < 9)
8740e9663eeSMiklos Szeredi 		req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
8750e9663eeSMiklos Szeredi 	else
876c79e322fSMiklos Szeredi 		req->out.args[0].size = sizeof(outarg);
877c79e322fSMiklos Szeredi 	req->out.args[0].value = &outarg;
878b93f858aSTejun Heo 	fuse_request_send(fc, req);
879e5e5558eSMiklos Szeredi 	err = req->out.h.error;
880e5e5558eSMiklos Szeredi 	fuse_put_request(fc, req);
881e5e5558eSMiklos Szeredi 	if (!err) {
882c79e322fSMiklos Szeredi 		if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
883e5e5558eSMiklos Szeredi 			make_bad_inode(inode);
884e5e5558eSMiklos Szeredi 			err = -EIO;
885e5e5558eSMiklos Szeredi 		} else {
886c79e322fSMiklos Szeredi 			fuse_change_attributes(inode, &outarg.attr,
887c79e322fSMiklos Szeredi 					       attr_timeout(&outarg),
8881fb69e78SMiklos Szeredi 					       attr_version);
8891fb69e78SMiklos Szeredi 			if (stat)
890c79e322fSMiklos Szeredi 				fuse_fillattr(inode, &outarg.attr, stat);
891e5e5558eSMiklos Szeredi 		}
892e5e5558eSMiklos Szeredi 	}
893e5e5558eSMiklos Szeredi 	return err;
894e5e5558eSMiklos Szeredi }
895e5e5558eSMiklos Szeredi 
896bcb4be80SMiklos Szeredi int fuse_update_attributes(struct inode *inode, struct kstat *stat,
897bcb4be80SMiklos Szeredi 			   struct file *file, bool *refreshed)
898bcb4be80SMiklos Szeredi {
899bcb4be80SMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
900bcb4be80SMiklos Szeredi 	int err;
901bcb4be80SMiklos Szeredi 	bool r;
902bcb4be80SMiklos Szeredi 
903bcb4be80SMiklos Szeredi 	if (fi->i_time < get_jiffies_64()) {
904bcb4be80SMiklos Szeredi 		r = true;
905bcb4be80SMiklos Szeredi 		err = fuse_do_getattr(inode, stat, file);
906bcb4be80SMiklos Szeredi 	} else {
907bcb4be80SMiklos Szeredi 		r = false;
908bcb4be80SMiklos Szeredi 		err = 0;
909bcb4be80SMiklos Szeredi 		if (stat) {
910bcb4be80SMiklos Szeredi 			generic_fillattr(inode, stat);
911bcb4be80SMiklos Szeredi 			stat->mode = fi->orig_i_mode;
91245c72cd7SPavel Shilovsky 			stat->ino = fi->orig_ino;
913bcb4be80SMiklos Szeredi 		}
914bcb4be80SMiklos Szeredi 	}
915bcb4be80SMiklos Szeredi 
916bcb4be80SMiklos Szeredi 	if (refreshed != NULL)
917bcb4be80SMiklos Szeredi 		*refreshed = r;
918bcb4be80SMiklos Szeredi 
919bcb4be80SMiklos Szeredi 	return err;
920bcb4be80SMiklos Szeredi }
921bcb4be80SMiklos Szeredi 
9223b463ae0SJohn Muir int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid,
923451d0f59SJohn Muir 			     u64 child_nodeid, struct qstr *name)
9243b463ae0SJohn Muir {
9253b463ae0SJohn Muir 	int err = -ENOTDIR;
9263b463ae0SJohn Muir 	struct inode *parent;
9273b463ae0SJohn Muir 	struct dentry *dir;
9283b463ae0SJohn Muir 	struct dentry *entry;
9293b463ae0SJohn Muir 
9303b463ae0SJohn Muir 	parent = ilookup5(sb, parent_nodeid, fuse_inode_eq, &parent_nodeid);
9313b463ae0SJohn Muir 	if (!parent)
9323b463ae0SJohn Muir 		return -ENOENT;
9333b463ae0SJohn Muir 
9343b463ae0SJohn Muir 	mutex_lock(&parent->i_mutex);
9353b463ae0SJohn Muir 	if (!S_ISDIR(parent->i_mode))
9363b463ae0SJohn Muir 		goto unlock;
9373b463ae0SJohn Muir 
9383b463ae0SJohn Muir 	err = -ENOENT;
9393b463ae0SJohn Muir 	dir = d_find_alias(parent);
9403b463ae0SJohn Muir 	if (!dir)
9413b463ae0SJohn Muir 		goto unlock;
9423b463ae0SJohn Muir 
9433b463ae0SJohn Muir 	entry = d_lookup(dir, name);
9443b463ae0SJohn Muir 	dput(dir);
9453b463ae0SJohn Muir 	if (!entry)
9463b463ae0SJohn Muir 		goto unlock;
9473b463ae0SJohn Muir 
9483b463ae0SJohn Muir 	fuse_invalidate_attr(parent);
9493b463ae0SJohn Muir 	fuse_invalidate_entry(entry);
950451d0f59SJohn Muir 
951451d0f59SJohn Muir 	if (child_nodeid != 0 && entry->d_inode) {
952451d0f59SJohn Muir 		mutex_lock(&entry->d_inode->i_mutex);
953451d0f59SJohn Muir 		if (get_node_id(entry->d_inode) != child_nodeid) {
954451d0f59SJohn Muir 			err = -ENOENT;
955451d0f59SJohn Muir 			goto badentry;
956451d0f59SJohn Muir 		}
957451d0f59SJohn Muir 		if (d_mountpoint(entry)) {
958451d0f59SJohn Muir 			err = -EBUSY;
959451d0f59SJohn Muir 			goto badentry;
960451d0f59SJohn Muir 		}
961451d0f59SJohn Muir 		if (S_ISDIR(entry->d_inode->i_mode)) {
962451d0f59SJohn Muir 			shrink_dcache_parent(entry);
963451d0f59SJohn Muir 			if (!simple_empty(entry)) {
964451d0f59SJohn Muir 				err = -ENOTEMPTY;
965451d0f59SJohn Muir 				goto badentry;
966451d0f59SJohn Muir 			}
967451d0f59SJohn Muir 			entry->d_inode->i_flags |= S_DEAD;
968451d0f59SJohn Muir 		}
969451d0f59SJohn Muir 		dont_mount(entry);
970451d0f59SJohn Muir 		clear_nlink(entry->d_inode);
9713b463ae0SJohn Muir 		err = 0;
972451d0f59SJohn Muir  badentry:
973451d0f59SJohn Muir 		mutex_unlock(&entry->d_inode->i_mutex);
974451d0f59SJohn Muir 		if (!err)
975451d0f59SJohn Muir 			d_delete(entry);
976451d0f59SJohn Muir 	} else {
977451d0f59SJohn Muir 		err = 0;
978451d0f59SJohn Muir 	}
979451d0f59SJohn Muir 	dput(entry);
9803b463ae0SJohn Muir 
9813b463ae0SJohn Muir  unlock:
9823b463ae0SJohn Muir 	mutex_unlock(&parent->i_mutex);
9833b463ae0SJohn Muir 	iput(parent);
9843b463ae0SJohn Muir 	return err;
9853b463ae0SJohn Muir }
9863b463ae0SJohn Muir 
98787729a55SMiklos Szeredi /*
98887729a55SMiklos Szeredi  * Calling into a user-controlled filesystem gives the filesystem
98987729a55SMiklos Szeredi  * daemon ptrace-like capabilities over the requester process.  This
99087729a55SMiklos Szeredi  * means, that the filesystem daemon is able to record the exact
99187729a55SMiklos Szeredi  * filesystem operations performed, and can also control the behavior
99287729a55SMiklos Szeredi  * of the requester process in otherwise impossible ways.  For example
99387729a55SMiklos Szeredi  * it can delay the operation for arbitrary length of time allowing
99487729a55SMiklos Szeredi  * DoS against the requester.
99587729a55SMiklos Szeredi  *
99687729a55SMiklos Szeredi  * For this reason only those processes can call into the filesystem,
99787729a55SMiklos Szeredi  * for which the owner of the mount has ptrace privilege.  This
99887729a55SMiklos Szeredi  * excludes processes started by other users, suid or sgid processes.
99987729a55SMiklos Szeredi  */
1000e57ac683SMiklos Szeredi int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task)
100187729a55SMiklos Szeredi {
1002c69e8d9cSDavid Howells 	const struct cred *cred;
1003c69e8d9cSDavid Howells 	int ret;
1004c69e8d9cSDavid Howells 
100587729a55SMiklos Szeredi 	if (fc->flags & FUSE_ALLOW_OTHER)
100687729a55SMiklos Szeredi 		return 1;
100787729a55SMiklos Szeredi 
1008c69e8d9cSDavid Howells 	rcu_read_lock();
1009c69e8d9cSDavid Howells 	ret = 0;
1010c69e8d9cSDavid Howells 	cred = __task_cred(task);
1011c69e8d9cSDavid Howells 	if (cred->euid == fc->user_id &&
1012c69e8d9cSDavid Howells 	    cred->suid == fc->user_id &&
1013c69e8d9cSDavid Howells 	    cred->uid  == fc->user_id &&
1014c69e8d9cSDavid Howells 	    cred->egid == fc->group_id &&
1015c69e8d9cSDavid Howells 	    cred->sgid == fc->group_id &&
1016c69e8d9cSDavid Howells 	    cred->gid  == fc->group_id)
1017c69e8d9cSDavid Howells 		ret = 1;
1018c69e8d9cSDavid Howells 	rcu_read_unlock();
101987729a55SMiklos Szeredi 
1020c69e8d9cSDavid Howells 	return ret;
102187729a55SMiklos Szeredi }
102287729a55SMiklos Szeredi 
102331d40d74SMiklos Szeredi static int fuse_access(struct inode *inode, int mask)
102431d40d74SMiklos Szeredi {
102531d40d74SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
102631d40d74SMiklos Szeredi 	struct fuse_req *req;
102731d40d74SMiklos Szeredi 	struct fuse_access_in inarg;
102831d40d74SMiklos Szeredi 	int err;
102931d40d74SMiklos Szeredi 
103031d40d74SMiklos Szeredi 	if (fc->no_access)
103131d40d74SMiklos Szeredi 		return 0;
103231d40d74SMiklos Szeredi 
1033ce1d5a49SMiklos Szeredi 	req = fuse_get_req(fc);
1034ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1035ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
103631d40d74SMiklos Szeredi 
103731d40d74SMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
1038e6305c43SAl Viro 	inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC);
103931d40d74SMiklos Szeredi 	req->in.h.opcode = FUSE_ACCESS;
104031d40d74SMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
104131d40d74SMiklos Szeredi 	req->in.numargs = 1;
104231d40d74SMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
104331d40d74SMiklos Szeredi 	req->in.args[0].value = &inarg;
1044b93f858aSTejun Heo 	fuse_request_send(fc, req);
104531d40d74SMiklos Szeredi 	err = req->out.h.error;
104631d40d74SMiklos Szeredi 	fuse_put_request(fc, req);
104731d40d74SMiklos Szeredi 	if (err == -ENOSYS) {
104831d40d74SMiklos Szeredi 		fc->no_access = 1;
104931d40d74SMiklos Szeredi 		err = 0;
105031d40d74SMiklos Szeredi 	}
105131d40d74SMiklos Szeredi 	return err;
105231d40d74SMiklos Szeredi }
105331d40d74SMiklos Szeredi 
105410556cb2SAl Viro static int fuse_perm_getattr(struct inode *inode, int mask)
105519690ddbSMiklos Szeredi {
105610556cb2SAl Viro 	if (mask & MAY_NOT_BLOCK)
105719690ddbSMiklos Szeredi 		return -ECHILD;
105819690ddbSMiklos Szeredi 
105919690ddbSMiklos Szeredi 	return fuse_do_getattr(inode, NULL, NULL);
106019690ddbSMiklos Szeredi }
106119690ddbSMiklos Szeredi 
10626f9f1180SMiklos Szeredi /*
10636f9f1180SMiklos Szeredi  * Check permission.  The two basic access models of FUSE are:
10646f9f1180SMiklos Szeredi  *
10656f9f1180SMiklos Szeredi  * 1) Local access checking ('default_permissions' mount option) based
10666f9f1180SMiklos Szeredi  * on file mode.  This is the plain old disk filesystem permission
10676f9f1180SMiklos Szeredi  * modell.
10686f9f1180SMiklos Szeredi  *
10696f9f1180SMiklos Szeredi  * 2) "Remote" access checking, where server is responsible for
10706f9f1180SMiklos Szeredi  * checking permission in each inode operation.  An exception to this
10716f9f1180SMiklos Szeredi  * is if ->permission() was invoked from sys_access() in which case an
10726f9f1180SMiklos Szeredi  * access request is sent.  Execute permission is still checked
10736f9f1180SMiklos Szeredi  * locally based on file mode.
10746f9f1180SMiklos Szeredi  */
107510556cb2SAl Viro static int fuse_permission(struct inode *inode, int mask)
1076e5e5558eSMiklos Szeredi {
1077e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1078244f6385SMiklos Szeredi 	bool refreshed = false;
1079244f6385SMiklos Szeredi 	int err = 0;
1080e5e5558eSMiklos Szeredi 
108187729a55SMiklos Szeredi 	if (!fuse_allow_task(fc, current))
1082e5e5558eSMiklos Szeredi 		return -EACCES;
1083244f6385SMiklos Szeredi 
1084244f6385SMiklos Szeredi 	/*
1085e8e96157SMiklos Szeredi 	 * If attributes are needed, refresh them before proceeding
1086244f6385SMiklos Szeredi 	 */
1087e8e96157SMiklos Szeredi 	if ((fc->flags & FUSE_DEFAULT_PERMISSIONS) ||
1088e8e96157SMiklos Szeredi 	    ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
108919690ddbSMiklos Szeredi 		struct fuse_inode *fi = get_fuse_inode(inode);
109019690ddbSMiklos Szeredi 
109119690ddbSMiklos Szeredi 		if (fi->i_time < get_jiffies_64()) {
109219690ddbSMiklos Szeredi 			refreshed = true;
109319690ddbSMiklos Szeredi 
109410556cb2SAl Viro 			err = fuse_perm_getattr(inode, mask);
1095244f6385SMiklos Szeredi 			if (err)
1096244f6385SMiklos Szeredi 				return err;
10971fb69e78SMiklos Szeredi 		}
109819690ddbSMiklos Szeredi 	}
1099244f6385SMiklos Szeredi 
1100244f6385SMiklos Szeredi 	if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
11012830ba7fSAl Viro 		err = generic_permission(inode, mask);
11021e9a4ed9SMiklos Szeredi 
11031e9a4ed9SMiklos Szeredi 		/* If permission is denied, try to refresh file
11041e9a4ed9SMiklos Szeredi 		   attributes.  This is also needed, because the root
11051e9a4ed9SMiklos Szeredi 		   node will at first have no permissions */
1106244f6385SMiklos Szeredi 		if (err == -EACCES && !refreshed) {
110710556cb2SAl Viro 			err = fuse_perm_getattr(inode, mask);
11081e9a4ed9SMiklos Szeredi 			if (!err)
11092830ba7fSAl Viro 				err = generic_permission(inode, mask);
11101e9a4ed9SMiklos Szeredi 		}
11111e9a4ed9SMiklos Szeredi 
11126f9f1180SMiklos Szeredi 		/* Note: the opposite of the above test does not
11136f9f1180SMiklos Szeredi 		   exist.  So if permissions are revoked this won't be
11146f9f1180SMiklos Szeredi 		   noticed immediately, only after the attribute
11156f9f1180SMiklos Szeredi 		   timeout has expired */
11169cfcac81SEric Paris 	} else if (mask & (MAY_ACCESS | MAY_CHDIR)) {
111710556cb2SAl Viro 		if (mask & MAY_NOT_BLOCK)
111819690ddbSMiklos Szeredi 			return -ECHILD;
111919690ddbSMiklos Szeredi 
1120e8e96157SMiklos Szeredi 		err = fuse_access(inode, mask);
1121e8e96157SMiklos Szeredi 	} else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
1122e8e96157SMiklos Szeredi 		if (!(inode->i_mode & S_IXUGO)) {
1123e8e96157SMiklos Szeredi 			if (refreshed)
1124e5e5558eSMiklos Szeredi 				return -EACCES;
112531d40d74SMiklos Szeredi 
112610556cb2SAl Viro 			err = fuse_perm_getattr(inode, mask);
1127e8e96157SMiklos Szeredi 			if (!err && !(inode->i_mode & S_IXUGO))
1128e8e96157SMiklos Szeredi 				return -EACCES;
1129e8e96157SMiklos Szeredi 		}
1130e5e5558eSMiklos Szeredi 	}
1131244f6385SMiklos Szeredi 	return err;
1132e5e5558eSMiklos Szeredi }
1133e5e5558eSMiklos Szeredi 
1134e5e5558eSMiklos Szeredi static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
1135e5e5558eSMiklos Szeredi 			 void *dstbuf, filldir_t filldir)
1136e5e5558eSMiklos Szeredi {
1137e5e5558eSMiklos Szeredi 	while (nbytes >= FUSE_NAME_OFFSET) {
1138e5e5558eSMiklos Szeredi 		struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
1139e5e5558eSMiklos Szeredi 		size_t reclen = FUSE_DIRENT_SIZE(dirent);
1140e5e5558eSMiklos Szeredi 		int over;
1141e5e5558eSMiklos Szeredi 		if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
1142e5e5558eSMiklos Szeredi 			return -EIO;
1143e5e5558eSMiklos Szeredi 		if (reclen > nbytes)
1144e5e5558eSMiklos Szeredi 			break;
1145e5e5558eSMiklos Szeredi 
1146e5e5558eSMiklos Szeredi 		over = filldir(dstbuf, dirent->name, dirent->namelen,
1147e5e5558eSMiklos Szeredi 			       file->f_pos, dirent->ino, dirent->type);
1148e5e5558eSMiklos Szeredi 		if (over)
1149e5e5558eSMiklos Szeredi 			break;
1150e5e5558eSMiklos Szeredi 
1151e5e5558eSMiklos Szeredi 		buf += reclen;
1152e5e5558eSMiklos Szeredi 		nbytes -= reclen;
1153e5e5558eSMiklos Szeredi 		file->f_pos = dirent->off;
1154e5e5558eSMiklos Szeredi 	}
1155e5e5558eSMiklos Szeredi 
1156e5e5558eSMiklos Szeredi 	return 0;
1157e5e5558eSMiklos Szeredi }
1158e5e5558eSMiklos Szeredi 
1159e5e5558eSMiklos Szeredi static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
1160e5e5558eSMiklos Szeredi {
116104730fefSMiklos Szeredi 	int err;
116204730fefSMiklos Szeredi 	size_t nbytes;
116304730fefSMiklos Szeredi 	struct page *page;
11647706a9d6SJosef Sipek 	struct inode *inode = file->f_path.dentry->d_inode;
116504730fefSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1166248d86e8SMiklos Szeredi 	struct fuse_req *req;
1167248d86e8SMiklos Szeredi 
1168248d86e8SMiklos Szeredi 	if (is_bad_inode(inode))
1169248d86e8SMiklos Szeredi 		return -EIO;
1170248d86e8SMiklos Szeredi 
1171ce1d5a49SMiklos Szeredi 	req = fuse_get_req(fc);
1172ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1173ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
1174e5e5558eSMiklos Szeredi 
117504730fefSMiklos Szeredi 	page = alloc_page(GFP_KERNEL);
117604730fefSMiklos Szeredi 	if (!page) {
117704730fefSMiklos Szeredi 		fuse_put_request(fc, req);
1178e5e5558eSMiklos Szeredi 		return -ENOMEM;
117904730fefSMiklos Szeredi 	}
1180f4975c67SMiklos Szeredi 	req->out.argpages = 1;
118104730fefSMiklos Szeredi 	req->num_pages = 1;
118204730fefSMiklos Szeredi 	req->pages[0] = page;
11832106cb18SMiklos Szeredi 	fuse_read_fill(req, file, file->f_pos, PAGE_SIZE, FUSE_READDIR);
1184b93f858aSTejun Heo 	fuse_request_send(fc, req);
1185361b1eb5SMiklos Szeredi 	nbytes = req->out.args[0].size;
118604730fefSMiklos Szeredi 	err = req->out.h.error;
118704730fefSMiklos Szeredi 	fuse_put_request(fc, req);
118804730fefSMiklos Szeredi 	if (!err)
118904730fefSMiklos Szeredi 		err = parse_dirfile(page_address(page), nbytes, file, dstbuf,
119004730fefSMiklos Szeredi 				    filldir);
1191e5e5558eSMiklos Szeredi 
119204730fefSMiklos Szeredi 	__free_page(page);
1193b36c31baSMiklos Szeredi 	fuse_invalidate_attr(inode); /* atime changed */
119404730fefSMiklos Szeredi 	return err;
1195e5e5558eSMiklos Szeredi }
1196e5e5558eSMiklos Szeredi 
1197e5e5558eSMiklos Szeredi static char *read_link(struct dentry *dentry)
1198e5e5558eSMiklos Szeredi {
1199e5e5558eSMiklos Szeredi 	struct inode *inode = dentry->d_inode;
1200e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1201ce1d5a49SMiklos Szeredi 	struct fuse_req *req = fuse_get_req(fc);
1202e5e5558eSMiklos Szeredi 	char *link;
1203e5e5558eSMiklos Szeredi 
1204ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1205e231c2eeSDavid Howells 		return ERR_CAST(req);
1206e5e5558eSMiklos Szeredi 
1207e5e5558eSMiklos Szeredi 	link = (char *) __get_free_page(GFP_KERNEL);
1208e5e5558eSMiklos Szeredi 	if (!link) {
1209e5e5558eSMiklos Szeredi 		link = ERR_PTR(-ENOMEM);
1210e5e5558eSMiklos Szeredi 		goto out;
1211e5e5558eSMiklos Szeredi 	}
1212e5e5558eSMiklos Szeredi 	req->in.h.opcode = FUSE_READLINK;
1213e5e5558eSMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
1214e5e5558eSMiklos Szeredi 	req->out.argvar = 1;
1215e5e5558eSMiklos Szeredi 	req->out.numargs = 1;
1216e5e5558eSMiklos Szeredi 	req->out.args[0].size = PAGE_SIZE - 1;
1217e5e5558eSMiklos Szeredi 	req->out.args[0].value = link;
1218b93f858aSTejun Heo 	fuse_request_send(fc, req);
1219e5e5558eSMiklos Szeredi 	if (req->out.h.error) {
1220e5e5558eSMiklos Szeredi 		free_page((unsigned long) link);
1221e5e5558eSMiklos Szeredi 		link = ERR_PTR(req->out.h.error);
1222e5e5558eSMiklos Szeredi 	} else
1223e5e5558eSMiklos Szeredi 		link[req->out.args[0].size] = '\0';
1224e5e5558eSMiklos Szeredi  out:
1225e5e5558eSMiklos Szeredi 	fuse_put_request(fc, req);
1226b36c31baSMiklos Szeredi 	fuse_invalidate_attr(inode); /* atime changed */
1227e5e5558eSMiklos Szeredi 	return link;
1228e5e5558eSMiklos Szeredi }
1229e5e5558eSMiklos Szeredi 
1230e5e5558eSMiklos Szeredi static void free_link(char *link)
1231e5e5558eSMiklos Szeredi {
1232e5e5558eSMiklos Szeredi 	if (!IS_ERR(link))
1233e5e5558eSMiklos Szeredi 		free_page((unsigned long) link);
1234e5e5558eSMiklos Szeredi }
1235e5e5558eSMiklos Szeredi 
1236e5e5558eSMiklos Szeredi static void *fuse_follow_link(struct dentry *dentry, struct nameidata *nd)
1237e5e5558eSMiklos Szeredi {
1238e5e5558eSMiklos Szeredi 	nd_set_link(nd, read_link(dentry));
1239e5e5558eSMiklos Szeredi 	return NULL;
1240e5e5558eSMiklos Szeredi }
1241e5e5558eSMiklos Szeredi 
1242e5e5558eSMiklos Szeredi static void fuse_put_link(struct dentry *dentry, struct nameidata *nd, void *c)
1243e5e5558eSMiklos Szeredi {
1244e5e5558eSMiklos Szeredi 	free_link(nd_get_link(nd));
1245e5e5558eSMiklos Szeredi }
1246e5e5558eSMiklos Szeredi 
1247e5e5558eSMiklos Szeredi static int fuse_dir_open(struct inode *inode, struct file *file)
1248e5e5558eSMiklos Szeredi {
124991fe96b4SMiklos Szeredi 	return fuse_open_common(inode, file, true);
1250e5e5558eSMiklos Szeredi }
1251e5e5558eSMiklos Szeredi 
1252e5e5558eSMiklos Szeredi static int fuse_dir_release(struct inode *inode, struct file *file)
1253e5e5558eSMiklos Szeredi {
12548b0797a4SMiklos Szeredi 	fuse_release_common(file, FUSE_RELEASEDIR);
12558b0797a4SMiklos Szeredi 
12568b0797a4SMiklos Szeredi 	return 0;
1257e5e5558eSMiklos Szeredi }
1258e5e5558eSMiklos Szeredi 
125902c24a82SJosef Bacik static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end,
126002c24a82SJosef Bacik 			  int datasync)
126182547981SMiklos Szeredi {
126202c24a82SJosef Bacik 	return fuse_fsync_common(file, start, end, datasync, 1);
126382547981SMiklos Szeredi }
126482547981SMiklos Szeredi 
1265b18da0c5SMiklos Szeredi static long fuse_dir_ioctl(struct file *file, unsigned int cmd,
1266b18da0c5SMiklos Szeredi 			    unsigned long arg)
1267b18da0c5SMiklos Szeredi {
1268b18da0c5SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1269b18da0c5SMiklos Szeredi 
1270b18da0c5SMiklos Szeredi 	/* FUSE_IOCTL_DIR only supported for API version >= 7.18 */
1271b18da0c5SMiklos Szeredi 	if (fc->minor < 18)
1272b18da0c5SMiklos Szeredi 		return -ENOTTY;
1273b18da0c5SMiklos Szeredi 
1274b18da0c5SMiklos Szeredi 	return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR);
1275b18da0c5SMiklos Szeredi }
1276b18da0c5SMiklos Szeredi 
1277b18da0c5SMiklos Szeredi static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd,
1278b18da0c5SMiklos Szeredi 				   unsigned long arg)
1279b18da0c5SMiklos Szeredi {
1280b18da0c5SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1281b18da0c5SMiklos Szeredi 
1282b18da0c5SMiklos Szeredi 	if (fc->minor < 18)
1283b18da0c5SMiklos Szeredi 		return -ENOTTY;
1284b18da0c5SMiklos Szeredi 
1285b18da0c5SMiklos Szeredi 	return fuse_ioctl_common(file, cmd, arg,
1286b18da0c5SMiklos Szeredi 				 FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR);
1287b18da0c5SMiklos Szeredi }
1288b18da0c5SMiklos Szeredi 
128917637cbaSMiklos Szeredi static bool update_mtime(unsigned ivalid)
129017637cbaSMiklos Szeredi {
129117637cbaSMiklos Szeredi 	/* Always update if mtime is explicitly set  */
129217637cbaSMiklos Szeredi 	if (ivalid & ATTR_MTIME_SET)
129317637cbaSMiklos Szeredi 		return true;
129417637cbaSMiklos Szeredi 
129517637cbaSMiklos Szeredi 	/* If it's an open(O_TRUNC) or an ftruncate(), don't update */
129617637cbaSMiklos Szeredi 	if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
129717637cbaSMiklos Szeredi 		return false;
129817637cbaSMiklos Szeredi 
129917637cbaSMiklos Szeredi 	/* In all other cases update */
130017637cbaSMiklos Szeredi 	return true;
130117637cbaSMiklos Szeredi }
130217637cbaSMiklos Szeredi 
1303befc649cSMiklos Szeredi static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg)
13049e6268dbSMiklos Szeredi {
13059e6268dbSMiklos Szeredi 	unsigned ivalid = iattr->ia_valid;
13069e6268dbSMiklos Szeredi 
13079e6268dbSMiklos Szeredi 	if (ivalid & ATTR_MODE)
1308befc649cSMiklos Szeredi 		arg->valid |= FATTR_MODE,   arg->mode = iattr->ia_mode;
13099e6268dbSMiklos Szeredi 	if (ivalid & ATTR_UID)
1310befc649cSMiklos Szeredi 		arg->valid |= FATTR_UID,    arg->uid = iattr->ia_uid;
13119e6268dbSMiklos Szeredi 	if (ivalid & ATTR_GID)
1312befc649cSMiklos Szeredi 		arg->valid |= FATTR_GID,    arg->gid = iattr->ia_gid;
13139e6268dbSMiklos Szeredi 	if (ivalid & ATTR_SIZE)
1314befc649cSMiklos Szeredi 		arg->valid |= FATTR_SIZE,   arg->size = iattr->ia_size;
131517637cbaSMiklos Szeredi 	if (ivalid & ATTR_ATIME) {
131617637cbaSMiklos Szeredi 		arg->valid |= FATTR_ATIME;
1317befc649cSMiklos Szeredi 		arg->atime = iattr->ia_atime.tv_sec;
131817637cbaSMiklos Szeredi 		arg->atimensec = iattr->ia_atime.tv_nsec;
131917637cbaSMiklos Szeredi 		if (!(ivalid & ATTR_ATIME_SET))
132017637cbaSMiklos Szeredi 			arg->valid |= FATTR_ATIME_NOW;
132117637cbaSMiklos Szeredi 	}
132217637cbaSMiklos Szeredi 	if ((ivalid & ATTR_MTIME) && update_mtime(ivalid)) {
132317637cbaSMiklos Szeredi 		arg->valid |= FATTR_MTIME;
1324befc649cSMiklos Szeredi 		arg->mtime = iattr->ia_mtime.tv_sec;
132517637cbaSMiklos Szeredi 		arg->mtimensec = iattr->ia_mtime.tv_nsec;
132617637cbaSMiklos Szeredi 		if (!(ivalid & ATTR_MTIME_SET))
132717637cbaSMiklos Szeredi 			arg->valid |= FATTR_MTIME_NOW;
13289e6268dbSMiklos Szeredi 	}
13299e6268dbSMiklos Szeredi }
13309e6268dbSMiklos Szeredi 
13316f9f1180SMiklos Szeredi /*
13323be5a52bSMiklos Szeredi  * Prevent concurrent writepages on inode
13333be5a52bSMiklos Szeredi  *
13343be5a52bSMiklos Szeredi  * This is done by adding a negative bias to the inode write counter
13353be5a52bSMiklos Szeredi  * and waiting for all pending writes to finish.
13363be5a52bSMiklos Szeredi  */
13373be5a52bSMiklos Szeredi void fuse_set_nowrite(struct inode *inode)
13383be5a52bSMiklos Szeredi {
13393be5a52bSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
13403be5a52bSMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
13413be5a52bSMiklos Szeredi 
13423be5a52bSMiklos Szeredi 	BUG_ON(!mutex_is_locked(&inode->i_mutex));
13433be5a52bSMiklos Szeredi 
13443be5a52bSMiklos Szeredi 	spin_lock(&fc->lock);
13453be5a52bSMiklos Szeredi 	BUG_ON(fi->writectr < 0);
13463be5a52bSMiklos Szeredi 	fi->writectr += FUSE_NOWRITE;
13473be5a52bSMiklos Szeredi 	spin_unlock(&fc->lock);
13483be5a52bSMiklos Szeredi 	wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE);
13493be5a52bSMiklos Szeredi }
13503be5a52bSMiklos Szeredi 
13513be5a52bSMiklos Szeredi /*
13523be5a52bSMiklos Szeredi  * Allow writepages on inode
13533be5a52bSMiklos Szeredi  *
13543be5a52bSMiklos Szeredi  * Remove the bias from the writecounter and send any queued
13553be5a52bSMiklos Szeredi  * writepages.
13563be5a52bSMiklos Szeredi  */
13573be5a52bSMiklos Szeredi static void __fuse_release_nowrite(struct inode *inode)
13583be5a52bSMiklos Szeredi {
13593be5a52bSMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
13603be5a52bSMiklos Szeredi 
13613be5a52bSMiklos Szeredi 	BUG_ON(fi->writectr != FUSE_NOWRITE);
13623be5a52bSMiklos Szeredi 	fi->writectr = 0;
13633be5a52bSMiklos Szeredi 	fuse_flush_writepages(inode);
13643be5a52bSMiklos Szeredi }
13653be5a52bSMiklos Szeredi 
13663be5a52bSMiklos Szeredi void fuse_release_nowrite(struct inode *inode)
13673be5a52bSMiklos Szeredi {
13683be5a52bSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
13693be5a52bSMiklos Szeredi 
13703be5a52bSMiklos Szeredi 	spin_lock(&fc->lock);
13713be5a52bSMiklos Szeredi 	__fuse_release_nowrite(inode);
13723be5a52bSMiklos Szeredi 	spin_unlock(&fc->lock);
13733be5a52bSMiklos Szeredi }
13743be5a52bSMiklos Szeredi 
13753be5a52bSMiklos Szeredi /*
13766f9f1180SMiklos Szeredi  * Set attributes, and at the same time refresh them.
13776f9f1180SMiklos Szeredi  *
13786f9f1180SMiklos Szeredi  * Truncation is slightly complicated, because the 'truncate' request
13796f9f1180SMiklos Szeredi  * may fail, in which case we don't want to touch the mapping.
13809ffbb916SMiklos Szeredi  * vmtruncate() doesn't allow for this case, so do the rlimit checking
13819ffbb916SMiklos Szeredi  * and the actual truncation by hand.
13826f9f1180SMiklos Szeredi  */
138349d4914fSMiklos Szeredi static int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
138449d4914fSMiklos Szeredi 			   struct file *file)
13859e6268dbSMiklos Szeredi {
13869e6268dbSMiklos Szeredi 	struct inode *inode = entry->d_inode;
13879e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
13889e6268dbSMiklos Szeredi 	struct fuse_req *req;
13899e6268dbSMiklos Szeredi 	struct fuse_setattr_in inarg;
13909e6268dbSMiklos Szeredi 	struct fuse_attr_out outarg;
13913be5a52bSMiklos Szeredi 	bool is_truncate = false;
13923be5a52bSMiklos Szeredi 	loff_t oldsize;
13939e6268dbSMiklos Szeredi 	int err;
13949e6268dbSMiklos Szeredi 
1395e57ac683SMiklos Szeredi 	if (!fuse_allow_task(fc, current))
1396e57ac683SMiklos Szeredi 		return -EACCES;
1397e57ac683SMiklos Szeredi 
1398db78b877SChristoph Hellwig 	if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS))
1399db78b877SChristoph Hellwig 		attr->ia_valid |= ATTR_FORCE;
1400db78b877SChristoph Hellwig 
14011e9a4ed9SMiklos Szeredi 	err = inode_change_ok(inode, attr);
14021e9a4ed9SMiklos Szeredi 	if (err)
14031e9a4ed9SMiklos Szeredi 		return err;
14041e9a4ed9SMiklos Szeredi 
14058d56adddSMiklos Szeredi 	if (attr->ia_valid & ATTR_OPEN) {
14068d56adddSMiklos Szeredi 		if (fc->atomic_o_trunc)
14076ff958edSMiklos Szeredi 			return 0;
14088d56adddSMiklos Szeredi 		file = NULL;
14098d56adddSMiklos Szeredi 	}
14106ff958edSMiklos Szeredi 
14112c27c65eSChristoph Hellwig 	if (attr->ia_valid & ATTR_SIZE)
14123be5a52bSMiklos Szeredi 		is_truncate = true;
14139e6268dbSMiklos Szeredi 
1414ce1d5a49SMiklos Szeredi 	req = fuse_get_req(fc);
1415ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1416ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
14179e6268dbSMiklos Szeredi 
14183be5a52bSMiklos Szeredi 	if (is_truncate)
14193be5a52bSMiklos Szeredi 		fuse_set_nowrite(inode);
14203be5a52bSMiklos Szeredi 
14219e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
14220e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
1423befc649cSMiklos Szeredi 	iattr_to_fattr(attr, &inarg);
142449d4914fSMiklos Szeredi 	if (file) {
142549d4914fSMiklos Szeredi 		struct fuse_file *ff = file->private_data;
142649d4914fSMiklos Szeredi 		inarg.valid |= FATTR_FH;
142749d4914fSMiklos Szeredi 		inarg.fh = ff->fh;
142849d4914fSMiklos Szeredi 	}
1429f3332114SMiklos Szeredi 	if (attr->ia_valid & ATTR_SIZE) {
1430f3332114SMiklos Szeredi 		/* For mandatory locking in truncate */
1431f3332114SMiklos Szeredi 		inarg.valid |= FATTR_LOCKOWNER;
1432f3332114SMiklos Szeredi 		inarg.lock_owner = fuse_lock_owner_id(fc, current->files);
1433f3332114SMiklos Szeredi 	}
14349e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_SETATTR;
14359e6268dbSMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
14369e6268dbSMiklos Szeredi 	req->in.numargs = 1;
14379e6268dbSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
14389e6268dbSMiklos Szeredi 	req->in.args[0].value = &inarg;
14399e6268dbSMiklos Szeredi 	req->out.numargs = 1;
14400e9663eeSMiklos Szeredi 	if (fc->minor < 9)
14410e9663eeSMiklos Szeredi 		req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
14420e9663eeSMiklos Szeredi 	else
14439e6268dbSMiklos Szeredi 		req->out.args[0].size = sizeof(outarg);
14449e6268dbSMiklos Szeredi 	req->out.args[0].value = &outarg;
1445b93f858aSTejun Heo 	fuse_request_send(fc, req);
14469e6268dbSMiklos Szeredi 	err = req->out.h.error;
14479e6268dbSMiklos Szeredi 	fuse_put_request(fc, req);
1448e00d2c2dSMiklos Szeredi 	if (err) {
1449e00d2c2dSMiklos Szeredi 		if (err == -EINTR)
1450e00d2c2dSMiklos Szeredi 			fuse_invalidate_attr(inode);
14513be5a52bSMiklos Szeredi 		goto error;
1452e00d2c2dSMiklos Szeredi 	}
1453e00d2c2dSMiklos Szeredi 
14549e6268dbSMiklos Szeredi 	if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
14559e6268dbSMiklos Szeredi 		make_bad_inode(inode);
14563be5a52bSMiklos Szeredi 		err = -EIO;
14573be5a52bSMiklos Szeredi 		goto error;
14589e6268dbSMiklos Szeredi 	}
14599e6268dbSMiklos Szeredi 
14603be5a52bSMiklos Szeredi 	spin_lock(&fc->lock);
14613be5a52bSMiklos Szeredi 	fuse_change_attributes_common(inode, &outarg.attr,
14623be5a52bSMiklos Szeredi 				      attr_timeout(&outarg));
14633be5a52bSMiklos Szeredi 	oldsize = inode->i_size;
14643be5a52bSMiklos Szeredi 	i_size_write(inode, outarg.attr.size);
14653be5a52bSMiklos Szeredi 
14663be5a52bSMiklos Szeredi 	if (is_truncate) {
14673be5a52bSMiklos Szeredi 		/* NOTE: this may release/reacquire fc->lock */
14683be5a52bSMiklos Szeredi 		__fuse_release_nowrite(inode);
14693be5a52bSMiklos Szeredi 	}
14703be5a52bSMiklos Szeredi 	spin_unlock(&fc->lock);
14713be5a52bSMiklos Szeredi 
14723be5a52bSMiklos Szeredi 	/*
14733be5a52bSMiklos Szeredi 	 * Only call invalidate_inode_pages2() after removing
14743be5a52bSMiklos Szeredi 	 * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock.
14753be5a52bSMiklos Szeredi 	 */
14763be5a52bSMiklos Szeredi 	if (S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
1477c08d3b0eSnpiggin@suse.de 		truncate_pagecache(inode, oldsize, outarg.attr.size);
14783be5a52bSMiklos Szeredi 		invalidate_inode_pages2(inode->i_mapping);
14793be5a52bSMiklos Szeredi 	}
14803be5a52bSMiklos Szeredi 
1481e00d2c2dSMiklos Szeredi 	return 0;
14823be5a52bSMiklos Szeredi 
14833be5a52bSMiklos Szeredi error:
14843be5a52bSMiklos Szeredi 	if (is_truncate)
14853be5a52bSMiklos Szeredi 		fuse_release_nowrite(inode);
14863be5a52bSMiklos Szeredi 
14873be5a52bSMiklos Szeredi 	return err;
14889e6268dbSMiklos Szeredi }
14899e6268dbSMiklos Szeredi 
149049d4914fSMiklos Szeredi static int fuse_setattr(struct dentry *entry, struct iattr *attr)
149149d4914fSMiklos Szeredi {
149249d4914fSMiklos Szeredi 	if (attr->ia_valid & ATTR_FILE)
149349d4914fSMiklos Szeredi 		return fuse_do_setattr(entry, attr, attr->ia_file);
149449d4914fSMiklos Szeredi 	else
149549d4914fSMiklos Szeredi 		return fuse_do_setattr(entry, attr, NULL);
149649d4914fSMiklos Szeredi }
149749d4914fSMiklos Szeredi 
1498e5e5558eSMiklos Szeredi static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
1499e5e5558eSMiklos Szeredi 			struct kstat *stat)
1500e5e5558eSMiklos Szeredi {
1501e5e5558eSMiklos Szeredi 	struct inode *inode = entry->d_inode;
1502244f6385SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1503244f6385SMiklos Szeredi 
1504244f6385SMiklos Szeredi 	if (!fuse_allow_task(fc, current))
1505244f6385SMiklos Szeredi 		return -EACCES;
1506244f6385SMiklos Szeredi 
1507bcb4be80SMiklos Szeredi 	return fuse_update_attributes(inode, stat, NULL, NULL);
1508e5e5558eSMiklos Szeredi }
1509e5e5558eSMiklos Szeredi 
151092a8780eSMiklos Szeredi static int fuse_setxattr(struct dentry *entry, const char *name,
151192a8780eSMiklos Szeredi 			 const void *value, size_t size, int flags)
151292a8780eSMiklos Szeredi {
151392a8780eSMiklos Szeredi 	struct inode *inode = entry->d_inode;
151492a8780eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
151592a8780eSMiklos Szeredi 	struct fuse_req *req;
151692a8780eSMiklos Szeredi 	struct fuse_setxattr_in inarg;
151792a8780eSMiklos Szeredi 	int err;
151892a8780eSMiklos Szeredi 
151992a8780eSMiklos Szeredi 	if (fc->no_setxattr)
152092a8780eSMiklos Szeredi 		return -EOPNOTSUPP;
152192a8780eSMiklos Szeredi 
1522ce1d5a49SMiklos Szeredi 	req = fuse_get_req(fc);
1523ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1524ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
152592a8780eSMiklos Szeredi 
152692a8780eSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
152792a8780eSMiklos Szeredi 	inarg.size = size;
152892a8780eSMiklos Szeredi 	inarg.flags = flags;
152992a8780eSMiklos Szeredi 	req->in.h.opcode = FUSE_SETXATTR;
153092a8780eSMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
153192a8780eSMiklos Szeredi 	req->in.numargs = 3;
153292a8780eSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
153392a8780eSMiklos Szeredi 	req->in.args[0].value = &inarg;
153492a8780eSMiklos Szeredi 	req->in.args[1].size = strlen(name) + 1;
153592a8780eSMiklos Szeredi 	req->in.args[1].value = name;
153692a8780eSMiklos Szeredi 	req->in.args[2].size = size;
153792a8780eSMiklos Szeredi 	req->in.args[2].value = value;
1538b93f858aSTejun Heo 	fuse_request_send(fc, req);
153992a8780eSMiklos Szeredi 	err = req->out.h.error;
154092a8780eSMiklos Szeredi 	fuse_put_request(fc, req);
154192a8780eSMiklos Szeredi 	if (err == -ENOSYS) {
154292a8780eSMiklos Szeredi 		fc->no_setxattr = 1;
154392a8780eSMiklos Szeredi 		err = -EOPNOTSUPP;
154492a8780eSMiklos Szeredi 	}
154592a8780eSMiklos Szeredi 	return err;
154692a8780eSMiklos Szeredi }
154792a8780eSMiklos Szeredi 
154892a8780eSMiklos Szeredi static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
154992a8780eSMiklos Szeredi 			     void *value, size_t size)
155092a8780eSMiklos Szeredi {
155192a8780eSMiklos Szeredi 	struct inode *inode = entry->d_inode;
155292a8780eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
155392a8780eSMiklos Szeredi 	struct fuse_req *req;
155492a8780eSMiklos Szeredi 	struct fuse_getxattr_in inarg;
155592a8780eSMiklos Szeredi 	struct fuse_getxattr_out outarg;
155692a8780eSMiklos Szeredi 	ssize_t ret;
155792a8780eSMiklos Szeredi 
155892a8780eSMiklos Szeredi 	if (fc->no_getxattr)
155992a8780eSMiklos Szeredi 		return -EOPNOTSUPP;
156092a8780eSMiklos Szeredi 
1561ce1d5a49SMiklos Szeredi 	req = fuse_get_req(fc);
1562ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1563ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
156492a8780eSMiklos Szeredi 
156592a8780eSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
156692a8780eSMiklos Szeredi 	inarg.size = size;
156792a8780eSMiklos Szeredi 	req->in.h.opcode = FUSE_GETXATTR;
156892a8780eSMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
156992a8780eSMiklos Szeredi 	req->in.numargs = 2;
157092a8780eSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
157192a8780eSMiklos Szeredi 	req->in.args[0].value = &inarg;
157292a8780eSMiklos Szeredi 	req->in.args[1].size = strlen(name) + 1;
157392a8780eSMiklos Szeredi 	req->in.args[1].value = name;
157492a8780eSMiklos Szeredi 	/* This is really two different operations rolled into one */
157592a8780eSMiklos Szeredi 	req->out.numargs = 1;
157692a8780eSMiklos Szeredi 	if (size) {
157792a8780eSMiklos Szeredi 		req->out.argvar = 1;
157892a8780eSMiklos Szeredi 		req->out.args[0].size = size;
157992a8780eSMiklos Szeredi 		req->out.args[0].value = value;
158092a8780eSMiklos Szeredi 	} else {
158192a8780eSMiklos Szeredi 		req->out.args[0].size = sizeof(outarg);
158292a8780eSMiklos Szeredi 		req->out.args[0].value = &outarg;
158392a8780eSMiklos Szeredi 	}
1584b93f858aSTejun Heo 	fuse_request_send(fc, req);
158592a8780eSMiklos Szeredi 	ret = req->out.h.error;
158692a8780eSMiklos Szeredi 	if (!ret)
158792a8780eSMiklos Szeredi 		ret = size ? req->out.args[0].size : outarg.size;
158892a8780eSMiklos Szeredi 	else {
158992a8780eSMiklos Szeredi 		if (ret == -ENOSYS) {
159092a8780eSMiklos Szeredi 			fc->no_getxattr = 1;
159192a8780eSMiklos Szeredi 			ret = -EOPNOTSUPP;
159292a8780eSMiklos Szeredi 		}
159392a8780eSMiklos Szeredi 	}
159492a8780eSMiklos Szeredi 	fuse_put_request(fc, req);
159592a8780eSMiklos Szeredi 	return ret;
159692a8780eSMiklos Szeredi }
159792a8780eSMiklos Szeredi 
159892a8780eSMiklos Szeredi static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
159992a8780eSMiklos Szeredi {
160092a8780eSMiklos Szeredi 	struct inode *inode = entry->d_inode;
160192a8780eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
160292a8780eSMiklos Szeredi 	struct fuse_req *req;
160392a8780eSMiklos Szeredi 	struct fuse_getxattr_in inarg;
160492a8780eSMiklos Szeredi 	struct fuse_getxattr_out outarg;
160592a8780eSMiklos Szeredi 	ssize_t ret;
160692a8780eSMiklos Szeredi 
1607e57ac683SMiklos Szeredi 	if (!fuse_allow_task(fc, current))
1608e57ac683SMiklos Szeredi 		return -EACCES;
1609e57ac683SMiklos Szeredi 
161092a8780eSMiklos Szeredi 	if (fc->no_listxattr)
161192a8780eSMiklos Szeredi 		return -EOPNOTSUPP;
161292a8780eSMiklos Szeredi 
1613ce1d5a49SMiklos Szeredi 	req = fuse_get_req(fc);
1614ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1615ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
161692a8780eSMiklos Szeredi 
161792a8780eSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
161892a8780eSMiklos Szeredi 	inarg.size = size;
161992a8780eSMiklos Szeredi 	req->in.h.opcode = FUSE_LISTXATTR;
162092a8780eSMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
162192a8780eSMiklos Szeredi 	req->in.numargs = 1;
162292a8780eSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
162392a8780eSMiklos Szeredi 	req->in.args[0].value = &inarg;
162492a8780eSMiklos Szeredi 	/* This is really two different operations rolled into one */
162592a8780eSMiklos Szeredi 	req->out.numargs = 1;
162692a8780eSMiklos Szeredi 	if (size) {
162792a8780eSMiklos Szeredi 		req->out.argvar = 1;
162892a8780eSMiklos Szeredi 		req->out.args[0].size = size;
162992a8780eSMiklos Szeredi 		req->out.args[0].value = list;
163092a8780eSMiklos Szeredi 	} else {
163192a8780eSMiklos Szeredi 		req->out.args[0].size = sizeof(outarg);
163292a8780eSMiklos Szeredi 		req->out.args[0].value = &outarg;
163392a8780eSMiklos Szeredi 	}
1634b93f858aSTejun Heo 	fuse_request_send(fc, req);
163592a8780eSMiklos Szeredi 	ret = req->out.h.error;
163692a8780eSMiklos Szeredi 	if (!ret)
163792a8780eSMiklos Szeredi 		ret = size ? req->out.args[0].size : outarg.size;
163892a8780eSMiklos Szeredi 	else {
163992a8780eSMiklos Szeredi 		if (ret == -ENOSYS) {
164092a8780eSMiklos Szeredi 			fc->no_listxattr = 1;
164192a8780eSMiklos Szeredi 			ret = -EOPNOTSUPP;
164292a8780eSMiklos Szeredi 		}
164392a8780eSMiklos Szeredi 	}
164492a8780eSMiklos Szeredi 	fuse_put_request(fc, req);
164592a8780eSMiklos Szeredi 	return ret;
164692a8780eSMiklos Szeredi }
164792a8780eSMiklos Szeredi 
164892a8780eSMiklos Szeredi static int fuse_removexattr(struct dentry *entry, const char *name)
164992a8780eSMiklos Szeredi {
165092a8780eSMiklos Szeredi 	struct inode *inode = entry->d_inode;
165192a8780eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
165292a8780eSMiklos Szeredi 	struct fuse_req *req;
165392a8780eSMiklos Szeredi 	int err;
165492a8780eSMiklos Szeredi 
165592a8780eSMiklos Szeredi 	if (fc->no_removexattr)
165692a8780eSMiklos Szeredi 		return -EOPNOTSUPP;
165792a8780eSMiklos Szeredi 
1658ce1d5a49SMiklos Szeredi 	req = fuse_get_req(fc);
1659ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1660ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
166192a8780eSMiklos Szeredi 
166292a8780eSMiklos Szeredi 	req->in.h.opcode = FUSE_REMOVEXATTR;
166392a8780eSMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
166492a8780eSMiklos Szeredi 	req->in.numargs = 1;
166592a8780eSMiklos Szeredi 	req->in.args[0].size = strlen(name) + 1;
166692a8780eSMiklos Szeredi 	req->in.args[0].value = name;
1667b93f858aSTejun Heo 	fuse_request_send(fc, req);
166892a8780eSMiklos Szeredi 	err = req->out.h.error;
166992a8780eSMiklos Szeredi 	fuse_put_request(fc, req);
167092a8780eSMiklos Szeredi 	if (err == -ENOSYS) {
167192a8780eSMiklos Szeredi 		fc->no_removexattr = 1;
167292a8780eSMiklos Szeredi 		err = -EOPNOTSUPP;
167392a8780eSMiklos Szeredi 	}
167492a8780eSMiklos Szeredi 	return err;
167592a8780eSMiklos Szeredi }
167692a8780eSMiklos Szeredi 
1677754661f1SArjan van de Ven static const struct inode_operations fuse_dir_inode_operations = {
1678e5e5558eSMiklos Szeredi 	.lookup		= fuse_lookup,
16799e6268dbSMiklos Szeredi 	.mkdir		= fuse_mkdir,
16809e6268dbSMiklos Szeredi 	.symlink	= fuse_symlink,
16819e6268dbSMiklos Szeredi 	.unlink		= fuse_unlink,
16829e6268dbSMiklos Szeredi 	.rmdir		= fuse_rmdir,
16839e6268dbSMiklos Szeredi 	.rename		= fuse_rename,
16849e6268dbSMiklos Szeredi 	.link		= fuse_link,
16859e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
16869e6268dbSMiklos Szeredi 	.create		= fuse_create,
1687c8ccbe03SMiklos Szeredi 	.atomic_open	= fuse_atomic_open,
16889e6268dbSMiklos Szeredi 	.mknod		= fuse_mknod,
1689e5e5558eSMiklos Szeredi 	.permission	= fuse_permission,
1690e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
169192a8780eSMiklos Szeredi 	.setxattr	= fuse_setxattr,
169292a8780eSMiklos Szeredi 	.getxattr	= fuse_getxattr,
169392a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
169492a8780eSMiklos Szeredi 	.removexattr	= fuse_removexattr,
1695e5e5558eSMiklos Szeredi };
1696e5e5558eSMiklos Szeredi 
16974b6f5d20SArjan van de Ven static const struct file_operations fuse_dir_operations = {
1698b6aeadedSMiklos Szeredi 	.llseek		= generic_file_llseek,
1699e5e5558eSMiklos Szeredi 	.read		= generic_read_dir,
1700e5e5558eSMiklos Szeredi 	.readdir	= fuse_readdir,
1701e5e5558eSMiklos Szeredi 	.open		= fuse_dir_open,
1702e5e5558eSMiklos Szeredi 	.release	= fuse_dir_release,
170382547981SMiklos Szeredi 	.fsync		= fuse_dir_fsync,
1704b18da0c5SMiklos Szeredi 	.unlocked_ioctl	= fuse_dir_ioctl,
1705b18da0c5SMiklos Szeredi 	.compat_ioctl	= fuse_dir_compat_ioctl,
1706e5e5558eSMiklos Szeredi };
1707e5e5558eSMiklos Szeredi 
1708754661f1SArjan van de Ven static const struct inode_operations fuse_common_inode_operations = {
17099e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
1710e5e5558eSMiklos Szeredi 	.permission	= fuse_permission,
1711e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
171292a8780eSMiklos Szeredi 	.setxattr	= fuse_setxattr,
171392a8780eSMiklos Szeredi 	.getxattr	= fuse_getxattr,
171492a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
171592a8780eSMiklos Szeredi 	.removexattr	= fuse_removexattr,
1716e5e5558eSMiklos Szeredi };
1717e5e5558eSMiklos Szeredi 
1718754661f1SArjan van de Ven static const struct inode_operations fuse_symlink_inode_operations = {
17199e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
1720e5e5558eSMiklos Szeredi 	.follow_link	= fuse_follow_link,
1721e5e5558eSMiklos Szeredi 	.put_link	= fuse_put_link,
1722e5e5558eSMiklos Szeredi 	.readlink	= generic_readlink,
1723e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
172492a8780eSMiklos Szeredi 	.setxattr	= fuse_setxattr,
172592a8780eSMiklos Szeredi 	.getxattr	= fuse_getxattr,
172692a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
172792a8780eSMiklos Szeredi 	.removexattr	= fuse_removexattr,
1728e5e5558eSMiklos Szeredi };
1729e5e5558eSMiklos Szeredi 
1730e5e5558eSMiklos Szeredi void fuse_init_common(struct inode *inode)
1731e5e5558eSMiklos Szeredi {
1732e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_common_inode_operations;
1733e5e5558eSMiklos Szeredi }
1734e5e5558eSMiklos Szeredi 
1735e5e5558eSMiklos Szeredi void fuse_init_dir(struct inode *inode)
1736e5e5558eSMiklos Szeredi {
1737e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_dir_inode_operations;
1738e5e5558eSMiklos Szeredi 	inode->i_fop = &fuse_dir_operations;
1739e5e5558eSMiklos Szeredi }
1740e5e5558eSMiklos Szeredi 
1741e5e5558eSMiklos Szeredi void fuse_init_symlink(struct inode *inode)
1742e5e5558eSMiklos Szeredi {
1743e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_symlink_inode_operations;
1744e5e5558eSMiklos Szeredi }
1745