xref: /openbmc/linux/fs/fuse/dir.c (revision c69e8d9c01db2adc503464993c358901c9af9de4)
1e5e5558eSMiklos Szeredi /*
2e5e5558eSMiklos Szeredi   FUSE: Filesystem in Userspace
351eb01e7SMiklos Szeredi   Copyright (C) 2001-2006  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/gfp.h>
14e5e5558eSMiklos Szeredi #include <linux/sched.h>
15e5e5558eSMiklos Szeredi #include <linux/namei.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 {
1598cbdf1e6SMiklos Szeredi 	struct inode *inode = entry->d_inode;
1608cbdf1e6SMiklos Szeredi 
1618cbdf1e6SMiklos Szeredi 	if (inode && is_bad_inode(inode))
162e5e5558eSMiklos Szeredi 		return 0;
1630a0898cfSMiklos Szeredi 	else if (fuse_dentry_time(entry) < get_jiffies_64()) {
164e5e5558eSMiklos Szeredi 		int err;
165e5e5558eSMiklos Szeredi 		struct fuse_entry_out outarg;
1668cbdf1e6SMiklos Szeredi 		struct fuse_conn *fc;
1678cbdf1e6SMiklos Szeredi 		struct fuse_req *req;
1682d51013eSMiklos Szeredi 		struct fuse_req *forget_req;
169e956edd0SMiklos Szeredi 		struct dentry *parent;
1701fb69e78SMiklos Szeredi 		u64 attr_version;
1718cbdf1e6SMiklos Szeredi 
17250322fe7SMiklos Szeredi 		/* For negative dentries, always do a fresh lookup */
1738cbdf1e6SMiklos Szeredi 		if (!inode)
1748cbdf1e6SMiklos Szeredi 			return 0;
1758cbdf1e6SMiklos Szeredi 
1768cbdf1e6SMiklos Szeredi 		fc = get_fuse_conn(inode);
177ce1d5a49SMiklos Szeredi 		req = fuse_get_req(fc);
178ce1d5a49SMiklos Szeredi 		if (IS_ERR(req))
179e5e5558eSMiklos Szeredi 			return 0;
180e5e5558eSMiklos Szeredi 
1812d51013eSMiklos Szeredi 		forget_req = fuse_get_req(fc);
1822d51013eSMiklos Szeredi 		if (IS_ERR(forget_req)) {
1832d51013eSMiklos Szeredi 			fuse_put_request(fc, req);
1842d51013eSMiklos Szeredi 			return 0;
1852d51013eSMiklos Szeredi 		}
1862d51013eSMiklos Szeredi 
1877dca9fd3SMiklos Szeredi 		attr_version = fuse_get_attr_version(fc);
1881fb69e78SMiklos Szeredi 
189e956edd0SMiklos Szeredi 		parent = dget_parent(entry);
190c180eebeSMiklos Szeredi 		fuse_lookup_init(fc, req, get_node_id(parent->d_inode),
191c180eebeSMiklos Szeredi 				 &entry->d_name, &outarg);
1927c352bdfSMiklos Szeredi 		request_send(fc, req);
193e956edd0SMiklos Szeredi 		dput(parent);
194e5e5558eSMiklos Szeredi 		err = req->out.h.error;
1952d51013eSMiklos Szeredi 		fuse_put_request(fc, req);
19650322fe7SMiklos Szeredi 		/* Zero nodeid is same as -ENOENT */
19750322fe7SMiklos Szeredi 		if (!err && !outarg.nodeid)
19850322fe7SMiklos Szeredi 			err = -ENOENT;
1999e6268dbSMiklos Szeredi 		if (!err) {
2008cbdf1e6SMiklos Szeredi 			struct fuse_inode *fi = get_fuse_inode(inode);
2019e6268dbSMiklos Szeredi 			if (outarg.nodeid != get_node_id(inode)) {
2022d51013eSMiklos Szeredi 				fuse_send_forget(fc, forget_req,
2032d51013eSMiklos Szeredi 						 outarg.nodeid, 1);
2049e6268dbSMiklos Szeredi 				return 0;
2059e6268dbSMiklos Szeredi 			}
2068da5ff23SMiklos Szeredi 			spin_lock(&fc->lock);
2079e6268dbSMiklos Szeredi 			fi->nlookup ++;
2088da5ff23SMiklos Szeredi 			spin_unlock(&fc->lock);
2099e6268dbSMiklos Szeredi 		}
2102d51013eSMiklos Szeredi 		fuse_put_request(fc, forget_req);
2119e6268dbSMiklos Szeredi 		if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT)
212e5e5558eSMiklos Szeredi 			return 0;
213e5e5558eSMiklos Szeredi 
2141fb69e78SMiklos Szeredi 		fuse_change_attributes(inode, &outarg.attr,
2151fb69e78SMiklos Szeredi 				       entry_attr_timeout(&outarg),
2161fb69e78SMiklos Szeredi 				       attr_version);
2171fb69e78SMiklos Szeredi 		fuse_change_entry_timeout(entry, &outarg);
218e5e5558eSMiklos Szeredi 	}
219e5e5558eSMiklos Szeredi 	return 1;
220e5e5558eSMiklos Szeredi }
221e5e5558eSMiklos Szeredi 
2228bfc016dSMiklos Szeredi static int invalid_nodeid(u64 nodeid)
2232827d0b2SMiklos Szeredi {
2242827d0b2SMiklos Szeredi 	return !nodeid || nodeid == FUSE_ROOT_ID;
2252827d0b2SMiklos Szeredi }
2262827d0b2SMiklos Szeredi 
227dbd561d2SMiklos Szeredi struct dentry_operations fuse_dentry_operations = {
228e5e5558eSMiklos Szeredi 	.d_revalidate	= fuse_dentry_revalidate,
229e5e5558eSMiklos Szeredi };
230e5e5558eSMiklos Szeredi 
231a5bfffacSTimo Savola int fuse_valid_type(int m)
23239ee059aSMiklos Szeredi {
23339ee059aSMiklos Szeredi 	return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) ||
23439ee059aSMiklos Szeredi 		S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m);
23539ee059aSMiklos Szeredi }
23639ee059aSMiklos Szeredi 
237d2a85164SMiklos Szeredi /*
238d2a85164SMiklos Szeredi  * Add a directory inode to a dentry, ensuring that no other dentry
239d2a85164SMiklos Szeredi  * refers to this inode.  Called with fc->inst_mutex.
240d2a85164SMiklos Szeredi  */
2410de6256dSMiklos Szeredi static struct dentry *fuse_d_add_directory(struct dentry *entry,
2420de6256dSMiklos Szeredi 					   struct inode *inode)
243d2a85164SMiklos Szeredi {
244d2a85164SMiklos Szeredi 	struct dentry *alias = d_find_alias(inode);
2450de6256dSMiklos Szeredi 	if (alias && !(alias->d_flags & DCACHE_DISCONNECTED)) {
246d2a85164SMiklos Szeredi 		/* This tries to shrink the subtree below alias */
247d2a85164SMiklos Szeredi 		fuse_invalidate_entry(alias);
248d2a85164SMiklos Szeredi 		dput(alias);
249d2a85164SMiklos Szeredi 		if (!list_empty(&inode->i_dentry))
2500de6256dSMiklos Szeredi 			return ERR_PTR(-EBUSY);
2510de6256dSMiklos Szeredi 	} else {
2520de6256dSMiklos Szeredi 		dput(alias);
253d2a85164SMiklos Szeredi 	}
2540de6256dSMiklos Szeredi 	return d_splice_alias(inode, entry);
255d2a85164SMiklos Szeredi }
256d2a85164SMiklos Szeredi 
257c180eebeSMiklos Szeredi int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name,
258c180eebeSMiklos Szeredi 		     struct fuse_entry_out *outarg, struct inode **inode)
259c180eebeSMiklos Szeredi {
260c180eebeSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn_super(sb);
261c180eebeSMiklos Szeredi 	struct fuse_req *req;
262c180eebeSMiklos Szeredi 	struct fuse_req *forget_req;
263c180eebeSMiklos Szeredi 	u64 attr_version;
264c180eebeSMiklos Szeredi 	int err;
265c180eebeSMiklos Szeredi 
266c180eebeSMiklos Szeredi 	*inode = NULL;
267c180eebeSMiklos Szeredi 	err = -ENAMETOOLONG;
268c180eebeSMiklos Szeredi 	if (name->len > FUSE_NAME_MAX)
269c180eebeSMiklos Szeredi 		goto out;
270c180eebeSMiklos Szeredi 
271c180eebeSMiklos Szeredi 	req = fuse_get_req(fc);
272c180eebeSMiklos Szeredi 	err = PTR_ERR(req);
273c180eebeSMiklos Szeredi 	if (IS_ERR(req))
274c180eebeSMiklos Szeredi 		goto out;
275c180eebeSMiklos Szeredi 
276c180eebeSMiklos Szeredi 	forget_req = fuse_get_req(fc);
277c180eebeSMiklos Szeredi 	err = PTR_ERR(forget_req);
278c180eebeSMiklos Szeredi 	if (IS_ERR(forget_req)) {
279c180eebeSMiklos Szeredi 		fuse_put_request(fc, req);
280c180eebeSMiklos Szeredi 		goto out;
281c180eebeSMiklos Szeredi 	}
282c180eebeSMiklos Szeredi 
283c180eebeSMiklos Szeredi 	attr_version = fuse_get_attr_version(fc);
284c180eebeSMiklos Szeredi 
285c180eebeSMiklos Szeredi 	fuse_lookup_init(fc, req, nodeid, name, outarg);
286c180eebeSMiklos Szeredi 	request_send(fc, req);
287c180eebeSMiklos Szeredi 	err = req->out.h.error;
288c180eebeSMiklos Szeredi 	fuse_put_request(fc, req);
289c180eebeSMiklos Szeredi 	/* Zero nodeid is same as -ENOENT, but with valid timeout */
290c180eebeSMiklos Szeredi 	if (err || !outarg->nodeid)
291c180eebeSMiklos Szeredi 		goto out_put_forget;
292c180eebeSMiklos Szeredi 
293c180eebeSMiklos Szeredi 	err = -EIO;
294c180eebeSMiklos Szeredi 	if (!outarg->nodeid)
295c180eebeSMiklos Szeredi 		goto out_put_forget;
296c180eebeSMiklos Szeredi 	if (!fuse_valid_type(outarg->attr.mode))
297c180eebeSMiklos Szeredi 		goto out_put_forget;
298c180eebeSMiklos Szeredi 
299c180eebeSMiklos Szeredi 	*inode = fuse_iget(sb, outarg->nodeid, outarg->generation,
300c180eebeSMiklos Szeredi 			   &outarg->attr, entry_attr_timeout(outarg),
301c180eebeSMiklos Szeredi 			   attr_version);
302c180eebeSMiklos Szeredi 	err = -ENOMEM;
303c180eebeSMiklos Szeredi 	if (!*inode) {
304c180eebeSMiklos Szeredi 		fuse_send_forget(fc, forget_req, outarg->nodeid, 1);
305c180eebeSMiklos Szeredi 		goto out;
306c180eebeSMiklos Szeredi 	}
307c180eebeSMiklos Szeredi 	err = 0;
308c180eebeSMiklos Szeredi 
309c180eebeSMiklos Szeredi  out_put_forget:
310c180eebeSMiklos Szeredi 	fuse_put_request(fc, forget_req);
311c180eebeSMiklos Szeredi  out:
312c180eebeSMiklos Szeredi 	return err;
313c180eebeSMiklos Szeredi }
314c180eebeSMiklos Szeredi 
3150aa7c699SMiklos Szeredi static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
3160aa7c699SMiklos Szeredi 				  struct nameidata *nd)
317e5e5558eSMiklos Szeredi {
318e5e5558eSMiklos Szeredi 	int err;
319e5e5558eSMiklos Szeredi 	struct fuse_entry_out outarg;
320c180eebeSMiklos Szeredi 	struct inode *inode;
3210de6256dSMiklos Szeredi 	struct dentry *newent;
322e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
323c180eebeSMiklos Szeredi 	bool outarg_valid = true;
324e5e5558eSMiklos Szeredi 
325c180eebeSMiklos Szeredi 	err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name,
326c180eebeSMiklos Szeredi 			       &outarg, &inode);
327c180eebeSMiklos Szeredi 	if (err == -ENOENT) {
328c180eebeSMiklos Szeredi 		outarg_valid = false;
329c180eebeSMiklos Szeredi 		err = 0;
3302d51013eSMiklos Szeredi 	}
331c180eebeSMiklos Szeredi 	if (err)
332c180eebeSMiklos Szeredi 		goto out_err;
3332d51013eSMiklos Szeredi 
334ee4e5271SMiklos Szeredi 	err = -EIO;
335c180eebeSMiklos Szeredi 	if (inode && get_node_id(inode) == FUSE_ROOT_ID)
336c180eebeSMiklos Szeredi 		goto out_iput;
337e5e5558eSMiklos Szeredi 
338d2a85164SMiklos Szeredi 	if (inode && S_ISDIR(inode->i_mode)) {
339d2a85164SMiklos Szeredi 		mutex_lock(&fc->inst_mutex);
3400de6256dSMiklos Szeredi 		newent = fuse_d_add_directory(entry, inode);
341d2a85164SMiklos Szeredi 		mutex_unlock(&fc->inst_mutex);
342c180eebeSMiklos Szeredi 		err = PTR_ERR(newent);
343c180eebeSMiklos Szeredi 		if (IS_ERR(newent))
344c180eebeSMiklos Szeredi 			goto out_iput;
345c180eebeSMiklos Szeredi 	} else {
3460de6256dSMiklos Szeredi 		newent = d_splice_alias(inode, entry);
347c180eebeSMiklos Szeredi 	}
348d2a85164SMiklos Szeredi 
3490de6256dSMiklos Szeredi 	entry = newent ? newent : entry;
350e5e5558eSMiklos Szeredi 	entry->d_op = &fuse_dentry_operations;
351c180eebeSMiklos Szeredi 	if (outarg_valid)
3521fb69e78SMiklos Szeredi 		fuse_change_entry_timeout(entry, &outarg);
3538cbdf1e6SMiklos Szeredi 	else
3548cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
355c180eebeSMiklos Szeredi 
3560de6256dSMiklos Szeredi 	return newent;
357c180eebeSMiklos Szeredi 
358c180eebeSMiklos Szeredi  out_iput:
359c180eebeSMiklos Szeredi 	iput(inode);
360c180eebeSMiklos Szeredi  out_err:
361c180eebeSMiklos Szeredi 	return ERR_PTR(err);
362e5e5558eSMiklos Szeredi }
363e5e5558eSMiklos Szeredi 
3646f9f1180SMiklos Szeredi /*
36551eb01e7SMiklos Szeredi  * Synchronous release for the case when something goes wrong in CREATE_OPEN
36651eb01e7SMiklos Szeredi  */
36751eb01e7SMiklos Szeredi static void fuse_sync_release(struct fuse_conn *fc, struct fuse_file *ff,
36851eb01e7SMiklos Szeredi 			      u64 nodeid, int flags)
36951eb01e7SMiklos Szeredi {
370c756e0a4SMiklos Szeredi 	fuse_release_fill(ff, nodeid, flags, FUSE_RELEASE);
371c756e0a4SMiklos Szeredi 	ff->reserved_req->force = 1;
372c756e0a4SMiklos Szeredi 	request_send(fc, ff->reserved_req);
373c756e0a4SMiklos Szeredi 	fuse_put_request(fc, ff->reserved_req);
374c756e0a4SMiklos Szeredi 	kfree(ff);
37551eb01e7SMiklos Szeredi }
37651eb01e7SMiklos Szeredi 
37751eb01e7SMiklos Szeredi /*
3786f9f1180SMiklos Szeredi  * Atomic create+open operation
3796f9f1180SMiklos Szeredi  *
3806f9f1180SMiklos Szeredi  * If the filesystem doesn't support this, then fall back to separate
3816f9f1180SMiklos Szeredi  * 'mknod' + 'open' requests.
3826f9f1180SMiklos Szeredi  */
383fd72faacSMiklos Szeredi static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
384fd72faacSMiklos Szeredi 			    struct nameidata *nd)
385fd72faacSMiklos Szeredi {
386fd72faacSMiklos Szeredi 	int err;
387fd72faacSMiklos Szeredi 	struct inode *inode;
388fd72faacSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
389fd72faacSMiklos Szeredi 	struct fuse_req *req;
39051eb01e7SMiklos Szeredi 	struct fuse_req *forget_req;
391fd72faacSMiklos Szeredi 	struct fuse_open_in inarg;
392fd72faacSMiklos Szeredi 	struct fuse_open_out outopen;
393fd72faacSMiklos Szeredi 	struct fuse_entry_out outentry;
394fd72faacSMiklos Szeredi 	struct fuse_file *ff;
395fd72faacSMiklos Szeredi 	struct file *file;
396fd72faacSMiklos Szeredi 	int flags = nd->intent.open.flags - 1;
397fd72faacSMiklos Szeredi 
398fd72faacSMiklos Szeredi 	if (fc->no_create)
399ce1d5a49SMiklos Szeredi 		return -ENOSYS;
400fd72faacSMiklos Szeredi 
40151eb01e7SMiklos Szeredi 	forget_req = fuse_get_req(fc);
40251eb01e7SMiklos Szeredi 	if (IS_ERR(forget_req))
40351eb01e7SMiklos Szeredi 		return PTR_ERR(forget_req);
40451eb01e7SMiklos Szeredi 
405ce1d5a49SMiklos Szeredi 	req = fuse_get_req(fc);
40651eb01e7SMiklos Szeredi 	err = PTR_ERR(req);
407ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
40851eb01e7SMiklos Szeredi 		goto out_put_forget_req;
409fd72faacSMiklos Szeredi 
410ce1d5a49SMiklos Szeredi 	err = -ENOMEM;
411fd72faacSMiklos Szeredi 	ff = fuse_file_alloc();
412fd72faacSMiklos Szeredi 	if (!ff)
413fd72faacSMiklos Szeredi 		goto out_put_request;
414fd72faacSMiklos Szeredi 
415fd72faacSMiklos Szeredi 	flags &= ~O_NOCTTY;
416fd72faacSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
4170e9663eeSMiklos Szeredi 	memset(&outentry, 0, sizeof(outentry));
418fd72faacSMiklos Szeredi 	inarg.flags = flags;
419fd72faacSMiklos Szeredi 	inarg.mode = mode;
420fd72faacSMiklos Szeredi 	req->in.h.opcode = FUSE_CREATE;
421fd72faacSMiklos Szeredi 	req->in.h.nodeid = get_node_id(dir);
422fd72faacSMiklos Szeredi 	req->in.numargs = 2;
423fd72faacSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
424fd72faacSMiklos Szeredi 	req->in.args[0].value = &inarg;
425fd72faacSMiklos Szeredi 	req->in.args[1].size = entry->d_name.len + 1;
426fd72faacSMiklos Szeredi 	req->in.args[1].value = entry->d_name.name;
427fd72faacSMiklos Szeredi 	req->out.numargs = 2;
4280e9663eeSMiklos Szeredi 	if (fc->minor < 9)
4290e9663eeSMiklos Szeredi 		req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
4300e9663eeSMiklos Szeredi 	else
431fd72faacSMiklos Szeredi 		req->out.args[0].size = sizeof(outentry);
432fd72faacSMiklos Szeredi 	req->out.args[0].value = &outentry;
433fd72faacSMiklos Szeredi 	req->out.args[1].size = sizeof(outopen);
434fd72faacSMiklos Szeredi 	req->out.args[1].value = &outopen;
435fd72faacSMiklos Szeredi 	request_send(fc, req);
436fd72faacSMiklos Szeredi 	err = req->out.h.error;
437fd72faacSMiklos Szeredi 	if (err) {
438fd72faacSMiklos Szeredi 		if (err == -ENOSYS)
439fd72faacSMiklos Szeredi 			fc->no_create = 1;
440fd72faacSMiklos Szeredi 		goto out_free_ff;
441fd72faacSMiklos Szeredi 	}
442fd72faacSMiklos Szeredi 
443fd72faacSMiklos Szeredi 	err = -EIO;
4442827d0b2SMiklos Szeredi 	if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid))
445fd72faacSMiklos Szeredi 		goto out_free_ff;
446fd72faacSMiklos Szeredi 
44751eb01e7SMiklos Szeredi 	fuse_put_request(fc, req);
448fd72faacSMiklos Szeredi 	inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
4491fb69e78SMiklos Szeredi 			  &outentry.attr, entry_attr_timeout(&outentry), 0);
450fd72faacSMiklos Szeredi 	if (!inode) {
451fd72faacSMiklos Szeredi 		flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
452fd72faacSMiklos Szeredi 		ff->fh = outopen.fh;
45351eb01e7SMiklos Szeredi 		fuse_sync_release(fc, ff, outentry.nodeid, flags);
45451eb01e7SMiklos Szeredi 		fuse_send_forget(fc, forget_req, outentry.nodeid, 1);
45551eb01e7SMiklos Szeredi 		return -ENOMEM;
456fd72faacSMiklos Szeredi 	}
45751eb01e7SMiklos Szeredi 	fuse_put_request(fc, forget_req);
458fd72faacSMiklos Szeredi 	d_instantiate(entry, inode);
4591fb69e78SMiklos Szeredi 	fuse_change_entry_timeout(entry, &outentry);
4600952b2a4SMiklos Szeredi 	fuse_invalidate_attr(dir);
461fd72faacSMiklos Szeredi 	file = lookup_instantiate_filp(nd, entry, generic_file_open);
462fd72faacSMiklos Szeredi 	if (IS_ERR(file)) {
463fd72faacSMiklos Szeredi 		ff->fh = outopen.fh;
46451eb01e7SMiklos Szeredi 		fuse_sync_release(fc, ff, outentry.nodeid, flags);
465fd72faacSMiklos Szeredi 		return PTR_ERR(file);
466fd72faacSMiklos Szeredi 	}
467fd72faacSMiklos Szeredi 	fuse_finish_open(inode, file, ff, &outopen);
468fd72faacSMiklos Szeredi 	return 0;
469fd72faacSMiklos Szeredi 
470fd72faacSMiklos Szeredi  out_free_ff:
471fd72faacSMiklos Szeredi 	fuse_file_free(ff);
472fd72faacSMiklos Szeredi  out_put_request:
473fd72faacSMiklos Szeredi 	fuse_put_request(fc, req);
47451eb01e7SMiklos Szeredi  out_put_forget_req:
47551eb01e7SMiklos Szeredi 	fuse_put_request(fc, forget_req);
476fd72faacSMiklos Szeredi 	return err;
477fd72faacSMiklos Szeredi }
478fd72faacSMiklos Szeredi 
4796f9f1180SMiklos Szeredi /*
4806f9f1180SMiklos Szeredi  * Code shared between mknod, mkdir, symlink and link
4816f9f1180SMiklos Szeredi  */
4829e6268dbSMiklos Szeredi static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
4839e6268dbSMiklos Szeredi 			    struct inode *dir, struct dentry *entry,
4849e6268dbSMiklos Szeredi 			    int mode)
4859e6268dbSMiklos Szeredi {
4869e6268dbSMiklos Szeredi 	struct fuse_entry_out outarg;
4879e6268dbSMiklos Szeredi 	struct inode *inode;
4889e6268dbSMiklos Szeredi 	int err;
4892d51013eSMiklos Szeredi 	struct fuse_req *forget_req;
4902d51013eSMiklos Szeredi 
4912d51013eSMiklos Szeredi 	forget_req = fuse_get_req(fc);
4922d51013eSMiklos Szeredi 	if (IS_ERR(forget_req)) {
4932d51013eSMiklos Szeredi 		fuse_put_request(fc, req);
4942d51013eSMiklos Szeredi 		return PTR_ERR(forget_req);
4952d51013eSMiklos Szeredi 	}
4969e6268dbSMiklos Szeredi 
4970e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
4989e6268dbSMiklos Szeredi 	req->in.h.nodeid = get_node_id(dir);
4999e6268dbSMiklos Szeredi 	req->out.numargs = 1;
5000e9663eeSMiklos Szeredi 	if (fc->minor < 9)
5010e9663eeSMiklos Szeredi 		req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
5020e9663eeSMiklos Szeredi 	else
5039e6268dbSMiklos Szeredi 		req->out.args[0].size = sizeof(outarg);
5049e6268dbSMiklos Szeredi 	req->out.args[0].value = &outarg;
5059e6268dbSMiklos Szeredi 	request_send(fc, req);
5069e6268dbSMiklos Szeredi 	err = req->out.h.error;
5079e6268dbSMiklos Szeredi 	fuse_put_request(fc, req);
5082d51013eSMiklos Szeredi 	if (err)
5092d51013eSMiklos Szeredi 		goto out_put_forget_req;
5102d51013eSMiklos Szeredi 
51139ee059aSMiklos Szeredi 	err = -EIO;
51239ee059aSMiklos Szeredi 	if (invalid_nodeid(outarg.nodeid))
5132d51013eSMiklos Szeredi 		goto out_put_forget_req;
51439ee059aSMiklos Szeredi 
51539ee059aSMiklos Szeredi 	if ((outarg.attr.mode ^ mode) & S_IFMT)
5162d51013eSMiklos Szeredi 		goto out_put_forget_req;
51739ee059aSMiklos Szeredi 
5189e6268dbSMiklos Szeredi 	inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
5191fb69e78SMiklos Szeredi 			  &outarg.attr, entry_attr_timeout(&outarg), 0);
5209e6268dbSMiklos Szeredi 	if (!inode) {
5212d51013eSMiklos Szeredi 		fuse_send_forget(fc, forget_req, outarg.nodeid, 1);
5229e6268dbSMiklos Szeredi 		return -ENOMEM;
5239e6268dbSMiklos Szeredi 	}
5242d51013eSMiklos Szeredi 	fuse_put_request(fc, forget_req);
5259e6268dbSMiklos Szeredi 
526d2a85164SMiklos Szeredi 	if (S_ISDIR(inode->i_mode)) {
527d2a85164SMiklos Szeredi 		struct dentry *alias;
528d2a85164SMiklos Szeredi 		mutex_lock(&fc->inst_mutex);
529d2a85164SMiklos Szeredi 		alias = d_find_alias(inode);
530d2a85164SMiklos Szeredi 		if (alias) {
531d2a85164SMiklos Szeredi 			/* New directory must have moved since mkdir */
532d2a85164SMiklos Szeredi 			mutex_unlock(&fc->inst_mutex);
533d2a85164SMiklos Szeredi 			dput(alias);
5349e6268dbSMiklos Szeredi 			iput(inode);
535d2a85164SMiklos Szeredi 			return -EBUSY;
5369e6268dbSMiklos Szeredi 		}
5379e6268dbSMiklos Szeredi 		d_instantiate(entry, inode);
538d2a85164SMiklos Szeredi 		mutex_unlock(&fc->inst_mutex);
539d2a85164SMiklos Szeredi 	} else
540d2a85164SMiklos Szeredi 		d_instantiate(entry, inode);
541d2a85164SMiklos Szeredi 
5421fb69e78SMiklos Szeredi 	fuse_change_entry_timeout(entry, &outarg);
5439e6268dbSMiklos Szeredi 	fuse_invalidate_attr(dir);
5449e6268dbSMiklos Szeredi 	return 0;
54539ee059aSMiklos Szeredi 
5462d51013eSMiklos Szeredi  out_put_forget_req:
5472d51013eSMiklos Szeredi 	fuse_put_request(fc, forget_req);
54839ee059aSMiklos Szeredi 	return err;
5499e6268dbSMiklos Szeredi }
5509e6268dbSMiklos Szeredi 
5519e6268dbSMiklos Szeredi static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode,
5529e6268dbSMiklos Szeredi 		      dev_t rdev)
5539e6268dbSMiklos Szeredi {
5549e6268dbSMiklos Szeredi 	struct fuse_mknod_in inarg;
5559e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
556ce1d5a49SMiklos Szeredi 	struct fuse_req *req = fuse_get_req(fc);
557ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
558ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
5599e6268dbSMiklos Szeredi 
5609e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
5619e6268dbSMiklos Szeredi 	inarg.mode = mode;
5629e6268dbSMiklos Szeredi 	inarg.rdev = new_encode_dev(rdev);
5639e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_MKNOD;
5649e6268dbSMiklos Szeredi 	req->in.numargs = 2;
5659e6268dbSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
5669e6268dbSMiklos Szeredi 	req->in.args[0].value = &inarg;
5679e6268dbSMiklos Szeredi 	req->in.args[1].size = entry->d_name.len + 1;
5689e6268dbSMiklos Szeredi 	req->in.args[1].value = entry->d_name.name;
5699e6268dbSMiklos Szeredi 	return create_new_entry(fc, req, dir, entry, mode);
5709e6268dbSMiklos Szeredi }
5719e6268dbSMiklos Szeredi 
5729e6268dbSMiklos Szeredi static int fuse_create(struct inode *dir, struct dentry *entry, int mode,
5739e6268dbSMiklos Szeredi 		       struct nameidata *nd)
5749e6268dbSMiklos Szeredi {
575b9ba347fSMiklos Szeredi 	if (nd && (nd->flags & LOOKUP_OPEN)) {
576fd72faacSMiklos Szeredi 		int err = fuse_create_open(dir, entry, mode, nd);
577fd72faacSMiklos Szeredi 		if (err != -ENOSYS)
578fd72faacSMiklos Szeredi 			return err;
579fd72faacSMiklos Szeredi 		/* Fall back on mknod */
580fd72faacSMiklos Szeredi 	}
5819e6268dbSMiklos Szeredi 	return fuse_mknod(dir, entry, mode, 0);
5829e6268dbSMiklos Szeredi }
5839e6268dbSMiklos Szeredi 
5849e6268dbSMiklos Szeredi static int fuse_mkdir(struct inode *dir, struct dentry *entry, int mode)
5859e6268dbSMiklos Szeredi {
5869e6268dbSMiklos Szeredi 	struct fuse_mkdir_in inarg;
5879e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
588ce1d5a49SMiklos Szeredi 	struct fuse_req *req = fuse_get_req(fc);
589ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
590ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
5919e6268dbSMiklos Szeredi 
5929e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
5939e6268dbSMiklos Szeredi 	inarg.mode = mode;
5949e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_MKDIR;
5959e6268dbSMiklos Szeredi 	req->in.numargs = 2;
5969e6268dbSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
5979e6268dbSMiklos Szeredi 	req->in.args[0].value = &inarg;
5989e6268dbSMiklos Szeredi 	req->in.args[1].size = entry->d_name.len + 1;
5999e6268dbSMiklos Szeredi 	req->in.args[1].value = entry->d_name.name;
6009e6268dbSMiklos Szeredi 	return create_new_entry(fc, req, dir, entry, S_IFDIR);
6019e6268dbSMiklos Szeredi }
6029e6268dbSMiklos Szeredi 
6039e6268dbSMiklos Szeredi static int fuse_symlink(struct inode *dir, struct dentry *entry,
6049e6268dbSMiklos Szeredi 			const char *link)
6059e6268dbSMiklos Szeredi {
6069e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
6079e6268dbSMiklos Szeredi 	unsigned len = strlen(link) + 1;
608ce1d5a49SMiklos Szeredi 	struct fuse_req *req = fuse_get_req(fc);
609ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
610ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
6119e6268dbSMiklos Szeredi 
6129e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_SYMLINK;
6139e6268dbSMiklos Szeredi 	req->in.numargs = 2;
6149e6268dbSMiklos Szeredi 	req->in.args[0].size = entry->d_name.len + 1;
6159e6268dbSMiklos Szeredi 	req->in.args[0].value = entry->d_name.name;
6169e6268dbSMiklos Szeredi 	req->in.args[1].size = len;
6179e6268dbSMiklos Szeredi 	req->in.args[1].value = link;
6189e6268dbSMiklos Szeredi 	return create_new_entry(fc, req, dir, entry, S_IFLNK);
6199e6268dbSMiklos Szeredi }
6209e6268dbSMiklos Szeredi 
6219e6268dbSMiklos Szeredi static int fuse_unlink(struct inode *dir, struct dentry *entry)
6229e6268dbSMiklos Szeredi {
6239e6268dbSMiklos Szeredi 	int err;
6249e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
625ce1d5a49SMiklos Szeredi 	struct fuse_req *req = fuse_get_req(fc);
626ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
627ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
6289e6268dbSMiklos Szeredi 
6299e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_UNLINK;
6309e6268dbSMiklos Szeredi 	req->in.h.nodeid = get_node_id(dir);
6319e6268dbSMiklos Szeredi 	req->in.numargs = 1;
6329e6268dbSMiklos Szeredi 	req->in.args[0].size = entry->d_name.len + 1;
6339e6268dbSMiklos Szeredi 	req->in.args[0].value = entry->d_name.name;
6349e6268dbSMiklos Szeredi 	request_send(fc, req);
6359e6268dbSMiklos Szeredi 	err = req->out.h.error;
6369e6268dbSMiklos Szeredi 	fuse_put_request(fc, req);
6379e6268dbSMiklos Szeredi 	if (!err) {
6389e6268dbSMiklos Szeredi 		struct inode *inode = entry->d_inode;
6399e6268dbSMiklos Szeredi 
6409e6268dbSMiklos Szeredi 		/* Set nlink to zero so the inode can be cleared, if
6419e6268dbSMiklos Szeredi                    the inode does have more links this will be
6429e6268dbSMiklos Szeredi                    discovered at the next lookup/getattr */
643ce71ec36SDave Hansen 		clear_nlink(inode);
6449e6268dbSMiklos Szeredi 		fuse_invalidate_attr(inode);
6459e6268dbSMiklos Szeredi 		fuse_invalidate_attr(dir);
6468cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
6479e6268dbSMiklos Szeredi 	} else if (err == -EINTR)
6489e6268dbSMiklos Szeredi 		fuse_invalidate_entry(entry);
6499e6268dbSMiklos Szeredi 	return err;
6509e6268dbSMiklos Szeredi }
6519e6268dbSMiklos Szeredi 
6529e6268dbSMiklos Szeredi static int fuse_rmdir(struct inode *dir, struct dentry *entry)
6539e6268dbSMiklos Szeredi {
6549e6268dbSMiklos Szeredi 	int err;
6559e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(dir);
656ce1d5a49SMiklos Szeredi 	struct fuse_req *req = fuse_get_req(fc);
657ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
658ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
6599e6268dbSMiklos Szeredi 
6609e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_RMDIR;
6619e6268dbSMiklos Szeredi 	req->in.h.nodeid = get_node_id(dir);
6629e6268dbSMiklos Szeredi 	req->in.numargs = 1;
6639e6268dbSMiklos Szeredi 	req->in.args[0].size = entry->d_name.len + 1;
6649e6268dbSMiklos Szeredi 	req->in.args[0].value = entry->d_name.name;
6659e6268dbSMiklos Szeredi 	request_send(fc, req);
6669e6268dbSMiklos Szeredi 	err = req->out.h.error;
6679e6268dbSMiklos Szeredi 	fuse_put_request(fc, req);
6689e6268dbSMiklos Szeredi 	if (!err) {
669ce71ec36SDave Hansen 		clear_nlink(entry->d_inode);
6709e6268dbSMiklos Szeredi 		fuse_invalidate_attr(dir);
6718cbdf1e6SMiklos Szeredi 		fuse_invalidate_entry_cache(entry);
6729e6268dbSMiklos Szeredi 	} else if (err == -EINTR)
6739e6268dbSMiklos Szeredi 		fuse_invalidate_entry(entry);
6749e6268dbSMiklos Szeredi 	return err;
6759e6268dbSMiklos Szeredi }
6769e6268dbSMiklos Szeredi 
6779e6268dbSMiklos Szeredi static int fuse_rename(struct inode *olddir, struct dentry *oldent,
6789e6268dbSMiklos Szeredi 		       struct inode *newdir, struct dentry *newent)
6799e6268dbSMiklos Szeredi {
6809e6268dbSMiklos Szeredi 	int err;
6819e6268dbSMiklos Szeredi 	struct fuse_rename_in inarg;
6829e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(olddir);
683ce1d5a49SMiklos Szeredi 	struct fuse_req *req = fuse_get_req(fc);
684ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
685ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
6869e6268dbSMiklos Szeredi 
6879e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
6889e6268dbSMiklos Szeredi 	inarg.newdir = get_node_id(newdir);
6899e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_RENAME;
6909e6268dbSMiklos Szeredi 	req->in.h.nodeid = get_node_id(olddir);
6919e6268dbSMiklos Szeredi 	req->in.numargs = 3;
6929e6268dbSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
6939e6268dbSMiklos Szeredi 	req->in.args[0].value = &inarg;
6949e6268dbSMiklos Szeredi 	req->in.args[1].size = oldent->d_name.len + 1;
6959e6268dbSMiklos Szeredi 	req->in.args[1].value = oldent->d_name.name;
6969e6268dbSMiklos Szeredi 	req->in.args[2].size = newent->d_name.len + 1;
6979e6268dbSMiklos Szeredi 	req->in.args[2].value = newent->d_name.name;
6989e6268dbSMiklos Szeredi 	request_send(fc, req);
6999e6268dbSMiklos Szeredi 	err = req->out.h.error;
7009e6268dbSMiklos Szeredi 	fuse_put_request(fc, req);
7019e6268dbSMiklos Szeredi 	if (!err) {
70208b63307SMiklos Szeredi 		/* ctime changes */
70308b63307SMiklos Szeredi 		fuse_invalidate_attr(oldent->d_inode);
70408b63307SMiklos Szeredi 
7059e6268dbSMiklos Szeredi 		fuse_invalidate_attr(olddir);
7069e6268dbSMiklos Szeredi 		if (olddir != newdir)
7079e6268dbSMiklos Szeredi 			fuse_invalidate_attr(newdir);
7088cbdf1e6SMiklos Szeredi 
7098cbdf1e6SMiklos Szeredi 		/* newent will end up negative */
7108cbdf1e6SMiklos Szeredi 		if (newent->d_inode)
7118cbdf1e6SMiklos Szeredi 			fuse_invalidate_entry_cache(newent);
7129e6268dbSMiklos Szeredi 	} else if (err == -EINTR) {
7139e6268dbSMiklos Szeredi 		/* If request was interrupted, DEITY only knows if the
7149e6268dbSMiklos Szeredi 		   rename actually took place.  If the invalidation
7159e6268dbSMiklos Szeredi 		   fails (e.g. some process has CWD under the renamed
7169e6268dbSMiklos Szeredi 		   directory), then there can be inconsistency between
7179e6268dbSMiklos Szeredi 		   the dcache and the real filesystem.  Tough luck. */
7189e6268dbSMiklos Szeredi 		fuse_invalidate_entry(oldent);
7199e6268dbSMiklos Szeredi 		if (newent->d_inode)
7209e6268dbSMiklos Szeredi 			fuse_invalidate_entry(newent);
7219e6268dbSMiklos Szeredi 	}
7229e6268dbSMiklos Szeredi 
7239e6268dbSMiklos Szeredi 	return err;
7249e6268dbSMiklos Szeredi }
7259e6268dbSMiklos Szeredi 
7269e6268dbSMiklos Szeredi static int fuse_link(struct dentry *entry, struct inode *newdir,
7279e6268dbSMiklos Szeredi 		     struct dentry *newent)
7289e6268dbSMiklos Szeredi {
7299e6268dbSMiklos Szeredi 	int err;
7309e6268dbSMiklos Szeredi 	struct fuse_link_in inarg;
7319e6268dbSMiklos Szeredi 	struct inode *inode = entry->d_inode;
7329e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
733ce1d5a49SMiklos Szeredi 	struct fuse_req *req = fuse_get_req(fc);
734ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
735ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
7369e6268dbSMiklos Szeredi 
7379e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
7389e6268dbSMiklos Szeredi 	inarg.oldnodeid = get_node_id(inode);
7399e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_LINK;
7409e6268dbSMiklos Szeredi 	req->in.numargs = 2;
7419e6268dbSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
7429e6268dbSMiklos Szeredi 	req->in.args[0].value = &inarg;
7439e6268dbSMiklos Szeredi 	req->in.args[1].size = newent->d_name.len + 1;
7449e6268dbSMiklos Szeredi 	req->in.args[1].value = newent->d_name.name;
7459e6268dbSMiklos Szeredi 	err = create_new_entry(fc, req, newdir, newent, inode->i_mode);
7469e6268dbSMiklos Szeredi 	/* Contrary to "normal" filesystems it can happen that link
7479e6268dbSMiklos Szeredi 	   makes two "logical" inodes point to the same "physical"
7489e6268dbSMiklos Szeredi 	   inode.  We invalidate the attributes of the old one, so it
7499e6268dbSMiklos Szeredi 	   will reflect changes in the backing inode (link count,
7509e6268dbSMiklos Szeredi 	   etc.)
7519e6268dbSMiklos Szeredi 	*/
7529e6268dbSMiklos Szeredi 	if (!err || err == -EINTR)
7539e6268dbSMiklos Szeredi 		fuse_invalidate_attr(inode);
7549e6268dbSMiklos Szeredi 	return err;
7559e6268dbSMiklos Szeredi }
7569e6268dbSMiklos Szeredi 
7571fb69e78SMiklos Szeredi static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
7581fb69e78SMiklos Szeredi 			  struct kstat *stat)
7591fb69e78SMiklos Szeredi {
7601fb69e78SMiklos Szeredi 	stat->dev = inode->i_sb->s_dev;
7611fb69e78SMiklos Szeredi 	stat->ino = attr->ino;
7621fb69e78SMiklos Szeredi 	stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
7631fb69e78SMiklos Szeredi 	stat->nlink = attr->nlink;
7641fb69e78SMiklos Szeredi 	stat->uid = attr->uid;
7651fb69e78SMiklos Szeredi 	stat->gid = attr->gid;
7661fb69e78SMiklos Szeredi 	stat->rdev = inode->i_rdev;
7671fb69e78SMiklos Szeredi 	stat->atime.tv_sec = attr->atime;
7681fb69e78SMiklos Szeredi 	stat->atime.tv_nsec = attr->atimensec;
7691fb69e78SMiklos Szeredi 	stat->mtime.tv_sec = attr->mtime;
7701fb69e78SMiklos Szeredi 	stat->mtime.tv_nsec = attr->mtimensec;
7711fb69e78SMiklos Szeredi 	stat->ctime.tv_sec = attr->ctime;
7721fb69e78SMiklos Szeredi 	stat->ctime.tv_nsec = attr->ctimensec;
7731fb69e78SMiklos Szeredi 	stat->size = attr->size;
7741fb69e78SMiklos Szeredi 	stat->blocks = attr->blocks;
7751fb69e78SMiklos Szeredi 	stat->blksize = (1 << inode->i_blkbits);
7761fb69e78SMiklos Szeredi }
7771fb69e78SMiklos Szeredi 
778c79e322fSMiklos Szeredi static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
779c79e322fSMiklos Szeredi 			   struct file *file)
780e5e5558eSMiklos Szeredi {
781e5e5558eSMiklos Szeredi 	int err;
782c79e322fSMiklos Szeredi 	struct fuse_getattr_in inarg;
783c79e322fSMiklos Szeredi 	struct fuse_attr_out outarg;
784e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
7851fb69e78SMiklos Szeredi 	struct fuse_req *req;
7861fb69e78SMiklos Szeredi 	u64 attr_version;
7871fb69e78SMiklos Szeredi 
7881fb69e78SMiklos Szeredi 	req = fuse_get_req(fc);
789ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
790ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
791e5e5558eSMiklos Szeredi 
7927dca9fd3SMiklos Szeredi 	attr_version = fuse_get_attr_version(fc);
7931fb69e78SMiklos Szeredi 
794c79e322fSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
7950e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
796c79e322fSMiklos Szeredi 	/* Directories have separate file-handle space */
797c79e322fSMiklos Szeredi 	if (file && S_ISREG(inode->i_mode)) {
798c79e322fSMiklos Szeredi 		struct fuse_file *ff = file->private_data;
799c79e322fSMiklos Szeredi 
800c79e322fSMiklos Szeredi 		inarg.getattr_flags |= FUSE_GETATTR_FH;
801c79e322fSMiklos Szeredi 		inarg.fh = ff->fh;
802c79e322fSMiklos Szeredi 	}
803e5e5558eSMiklos Szeredi 	req->in.h.opcode = FUSE_GETATTR;
804e5e5558eSMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
805c79e322fSMiklos Szeredi 	req->in.numargs = 1;
806c79e322fSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
807c79e322fSMiklos Szeredi 	req->in.args[0].value = &inarg;
808e5e5558eSMiklos Szeredi 	req->out.numargs = 1;
8090e9663eeSMiklos Szeredi 	if (fc->minor < 9)
8100e9663eeSMiklos Szeredi 		req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
8110e9663eeSMiklos Szeredi 	else
812c79e322fSMiklos Szeredi 		req->out.args[0].size = sizeof(outarg);
813c79e322fSMiklos Szeredi 	req->out.args[0].value = &outarg;
814e5e5558eSMiklos Szeredi 	request_send(fc, req);
815e5e5558eSMiklos Szeredi 	err = req->out.h.error;
816e5e5558eSMiklos Szeredi 	fuse_put_request(fc, req);
817e5e5558eSMiklos Szeredi 	if (!err) {
818c79e322fSMiklos Szeredi 		if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
819e5e5558eSMiklos Szeredi 			make_bad_inode(inode);
820e5e5558eSMiklos Szeredi 			err = -EIO;
821e5e5558eSMiklos Szeredi 		} else {
822c79e322fSMiklos Szeredi 			fuse_change_attributes(inode, &outarg.attr,
823c79e322fSMiklos Szeredi 					       attr_timeout(&outarg),
8241fb69e78SMiklos Szeredi 					       attr_version);
8251fb69e78SMiklos Szeredi 			if (stat)
826c79e322fSMiklos Szeredi 				fuse_fillattr(inode, &outarg.attr, stat);
827e5e5558eSMiklos Szeredi 		}
828e5e5558eSMiklos Szeredi 	}
829e5e5558eSMiklos Szeredi 	return err;
830e5e5558eSMiklos Szeredi }
831e5e5558eSMiklos Szeredi 
832bcb4be80SMiklos Szeredi int fuse_update_attributes(struct inode *inode, struct kstat *stat,
833bcb4be80SMiklos Szeredi 			   struct file *file, bool *refreshed)
834bcb4be80SMiklos Szeredi {
835bcb4be80SMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
836bcb4be80SMiklos Szeredi 	int err;
837bcb4be80SMiklos Szeredi 	bool r;
838bcb4be80SMiklos Szeredi 
839bcb4be80SMiklos Szeredi 	if (fi->i_time < get_jiffies_64()) {
840bcb4be80SMiklos Szeredi 		r = true;
841bcb4be80SMiklos Szeredi 		err = fuse_do_getattr(inode, stat, file);
842bcb4be80SMiklos Szeredi 	} else {
843bcb4be80SMiklos Szeredi 		r = false;
844bcb4be80SMiklos Szeredi 		err = 0;
845bcb4be80SMiklos Szeredi 		if (stat) {
846bcb4be80SMiklos Szeredi 			generic_fillattr(inode, stat);
847bcb4be80SMiklos Szeredi 			stat->mode = fi->orig_i_mode;
848bcb4be80SMiklos Szeredi 		}
849bcb4be80SMiklos Szeredi 	}
850bcb4be80SMiklos Szeredi 
851bcb4be80SMiklos Szeredi 	if (refreshed != NULL)
852bcb4be80SMiklos Szeredi 		*refreshed = r;
853bcb4be80SMiklos Szeredi 
854bcb4be80SMiklos Szeredi 	return err;
855bcb4be80SMiklos Szeredi }
856bcb4be80SMiklos Szeredi 
85787729a55SMiklos Szeredi /*
85887729a55SMiklos Szeredi  * Calling into a user-controlled filesystem gives the filesystem
85987729a55SMiklos Szeredi  * daemon ptrace-like capabilities over the requester process.  This
86087729a55SMiklos Szeredi  * means, that the filesystem daemon is able to record the exact
86187729a55SMiklos Szeredi  * filesystem operations performed, and can also control the behavior
86287729a55SMiklos Szeredi  * of the requester process in otherwise impossible ways.  For example
86387729a55SMiklos Szeredi  * it can delay the operation for arbitrary length of time allowing
86487729a55SMiklos Szeredi  * DoS against the requester.
86587729a55SMiklos Szeredi  *
86687729a55SMiklos Szeredi  * For this reason only those processes can call into the filesystem,
86787729a55SMiklos Szeredi  * for which the owner of the mount has ptrace privilege.  This
86887729a55SMiklos Szeredi  * excludes processes started by other users, suid or sgid processes.
86987729a55SMiklos Szeredi  */
870e57ac683SMiklos Szeredi int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task)
87187729a55SMiklos Szeredi {
872*c69e8d9cSDavid Howells 	const struct cred *cred;
873*c69e8d9cSDavid Howells 	int ret;
874*c69e8d9cSDavid Howells 
87587729a55SMiklos Szeredi 	if (fc->flags & FUSE_ALLOW_OTHER)
87687729a55SMiklos Szeredi 		return 1;
87787729a55SMiklos Szeredi 
878*c69e8d9cSDavid Howells 	rcu_read_lock();
879*c69e8d9cSDavid Howells 	ret = 0;
880*c69e8d9cSDavid Howells 	cred = __task_cred(task);
881*c69e8d9cSDavid Howells 	if (cred->euid == fc->user_id &&
882*c69e8d9cSDavid Howells 	    cred->suid == fc->user_id &&
883*c69e8d9cSDavid Howells 	    cred->uid  == fc->user_id &&
884*c69e8d9cSDavid Howells 	    cred->egid == fc->group_id &&
885*c69e8d9cSDavid Howells 	    cred->sgid == fc->group_id &&
886*c69e8d9cSDavid Howells 	    cred->gid  == fc->group_id)
887*c69e8d9cSDavid Howells 		ret = 1;
888*c69e8d9cSDavid Howells 	rcu_read_unlock();
88987729a55SMiklos Szeredi 
890*c69e8d9cSDavid Howells 	return ret;
89187729a55SMiklos Szeredi }
89287729a55SMiklos Szeredi 
89331d40d74SMiklos Szeredi static int fuse_access(struct inode *inode, int mask)
89431d40d74SMiklos Szeredi {
89531d40d74SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
89631d40d74SMiklos Szeredi 	struct fuse_req *req;
89731d40d74SMiklos Szeredi 	struct fuse_access_in inarg;
89831d40d74SMiklos Szeredi 	int err;
89931d40d74SMiklos Szeredi 
90031d40d74SMiklos Szeredi 	if (fc->no_access)
90131d40d74SMiklos Szeredi 		return 0;
90231d40d74SMiklos Szeredi 
903ce1d5a49SMiklos Szeredi 	req = fuse_get_req(fc);
904ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
905ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
90631d40d74SMiklos Szeredi 
90731d40d74SMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
908e6305c43SAl Viro 	inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC);
90931d40d74SMiklos Szeredi 	req->in.h.opcode = FUSE_ACCESS;
91031d40d74SMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
91131d40d74SMiklos Szeredi 	req->in.numargs = 1;
91231d40d74SMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
91331d40d74SMiklos Szeredi 	req->in.args[0].value = &inarg;
91431d40d74SMiklos Szeredi 	request_send(fc, req);
91531d40d74SMiklos Szeredi 	err = req->out.h.error;
91631d40d74SMiklos Szeredi 	fuse_put_request(fc, req);
91731d40d74SMiklos Szeredi 	if (err == -ENOSYS) {
91831d40d74SMiklos Szeredi 		fc->no_access = 1;
91931d40d74SMiklos Szeredi 		err = 0;
92031d40d74SMiklos Szeredi 	}
92131d40d74SMiklos Szeredi 	return err;
92231d40d74SMiklos Szeredi }
92331d40d74SMiklos Szeredi 
9246f9f1180SMiklos Szeredi /*
9256f9f1180SMiklos Szeredi  * Check permission.  The two basic access models of FUSE are:
9266f9f1180SMiklos Szeredi  *
9276f9f1180SMiklos Szeredi  * 1) Local access checking ('default_permissions' mount option) based
9286f9f1180SMiklos Szeredi  * on file mode.  This is the plain old disk filesystem permission
9296f9f1180SMiklos Szeredi  * modell.
9306f9f1180SMiklos Szeredi  *
9316f9f1180SMiklos Szeredi  * 2) "Remote" access checking, where server is responsible for
9326f9f1180SMiklos Szeredi  * checking permission in each inode operation.  An exception to this
9336f9f1180SMiklos Szeredi  * is if ->permission() was invoked from sys_access() in which case an
9346f9f1180SMiklos Szeredi  * access request is sent.  Execute permission is still checked
9356f9f1180SMiklos Szeredi  * locally based on file mode.
9366f9f1180SMiklos Szeredi  */
937e6305c43SAl Viro static int fuse_permission(struct inode *inode, int mask)
938e5e5558eSMiklos Szeredi {
939e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
940244f6385SMiklos Szeredi 	bool refreshed = false;
941244f6385SMiklos Szeredi 	int err = 0;
942e5e5558eSMiklos Szeredi 
94387729a55SMiklos Szeredi 	if (!fuse_allow_task(fc, current))
944e5e5558eSMiklos Szeredi 		return -EACCES;
945244f6385SMiklos Szeredi 
946244f6385SMiklos Szeredi 	/*
947e8e96157SMiklos Szeredi 	 * If attributes are needed, refresh them before proceeding
948244f6385SMiklos Szeredi 	 */
949e8e96157SMiklos Szeredi 	if ((fc->flags & FUSE_DEFAULT_PERMISSIONS) ||
950e8e96157SMiklos Szeredi 	    ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
951bcb4be80SMiklos Szeredi 		err = fuse_update_attributes(inode, NULL, NULL, &refreshed);
952244f6385SMiklos Szeredi 		if (err)
953244f6385SMiklos Szeredi 			return err;
9541fb69e78SMiklos Szeredi 	}
955244f6385SMiklos Szeredi 
956244f6385SMiklos Szeredi 	if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
9571a823ac9SMiklos Szeredi 		err = generic_permission(inode, mask, NULL);
9581e9a4ed9SMiklos Szeredi 
9591e9a4ed9SMiklos Szeredi 		/* If permission is denied, try to refresh file
9601e9a4ed9SMiklos Szeredi 		   attributes.  This is also needed, because the root
9611e9a4ed9SMiklos Szeredi 		   node will at first have no permissions */
962244f6385SMiklos Szeredi 		if (err == -EACCES && !refreshed) {
963c79e322fSMiklos Szeredi 			err = fuse_do_getattr(inode, NULL, NULL);
9641e9a4ed9SMiklos Szeredi 			if (!err)
9651e9a4ed9SMiklos Szeredi 				err = generic_permission(inode, mask, NULL);
9661e9a4ed9SMiklos Szeredi 		}
9671e9a4ed9SMiklos Szeredi 
9686f9f1180SMiklos Szeredi 		/* Note: the opposite of the above test does not
9696f9f1180SMiklos Szeredi 		   exist.  So if permissions are revoked this won't be
9706f9f1180SMiklos Szeredi 		   noticed immediately, only after the attribute
9716f9f1180SMiklos Szeredi 		   timeout has expired */
972a110343fSAl Viro 	} else if (mask & MAY_ACCESS) {
973e8e96157SMiklos Szeredi 		err = fuse_access(inode, mask);
974e8e96157SMiklos Szeredi 	} else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
975e8e96157SMiklos Szeredi 		if (!(inode->i_mode & S_IXUGO)) {
976e8e96157SMiklos Szeredi 			if (refreshed)
977e5e5558eSMiklos Szeredi 				return -EACCES;
97831d40d74SMiklos Szeredi 
979c79e322fSMiklos Szeredi 			err = fuse_do_getattr(inode, NULL, NULL);
980e8e96157SMiklos Szeredi 			if (!err && !(inode->i_mode & S_IXUGO))
981e8e96157SMiklos Szeredi 				return -EACCES;
982e8e96157SMiklos Szeredi 		}
983e5e5558eSMiklos Szeredi 	}
984244f6385SMiklos Szeredi 	return err;
985e5e5558eSMiklos Szeredi }
986e5e5558eSMiklos Szeredi 
987e5e5558eSMiklos Szeredi static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
988e5e5558eSMiklos Szeredi 			 void *dstbuf, filldir_t filldir)
989e5e5558eSMiklos Szeredi {
990e5e5558eSMiklos Szeredi 	while (nbytes >= FUSE_NAME_OFFSET) {
991e5e5558eSMiklos Szeredi 		struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
992e5e5558eSMiklos Szeredi 		size_t reclen = FUSE_DIRENT_SIZE(dirent);
993e5e5558eSMiklos Szeredi 		int over;
994e5e5558eSMiklos Szeredi 		if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
995e5e5558eSMiklos Szeredi 			return -EIO;
996e5e5558eSMiklos Szeredi 		if (reclen > nbytes)
997e5e5558eSMiklos Szeredi 			break;
998e5e5558eSMiklos Szeredi 
999e5e5558eSMiklos Szeredi 		over = filldir(dstbuf, dirent->name, dirent->namelen,
1000e5e5558eSMiklos Szeredi 			       file->f_pos, dirent->ino, dirent->type);
1001e5e5558eSMiklos Szeredi 		if (over)
1002e5e5558eSMiklos Szeredi 			break;
1003e5e5558eSMiklos Szeredi 
1004e5e5558eSMiklos Szeredi 		buf += reclen;
1005e5e5558eSMiklos Szeredi 		nbytes -= reclen;
1006e5e5558eSMiklos Szeredi 		file->f_pos = dirent->off;
1007e5e5558eSMiklos Szeredi 	}
1008e5e5558eSMiklos Szeredi 
1009e5e5558eSMiklos Szeredi 	return 0;
1010e5e5558eSMiklos Szeredi }
1011e5e5558eSMiklos Szeredi 
1012e5e5558eSMiklos Szeredi static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
1013e5e5558eSMiklos Szeredi {
101404730fefSMiklos Szeredi 	int err;
101504730fefSMiklos Szeredi 	size_t nbytes;
101604730fefSMiklos Szeredi 	struct page *page;
10177706a9d6SJosef Sipek 	struct inode *inode = file->f_path.dentry->d_inode;
101804730fefSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1019248d86e8SMiklos Szeredi 	struct fuse_req *req;
1020248d86e8SMiklos Szeredi 
1021248d86e8SMiklos Szeredi 	if (is_bad_inode(inode))
1022248d86e8SMiklos Szeredi 		return -EIO;
1023248d86e8SMiklos Szeredi 
1024ce1d5a49SMiklos Szeredi 	req = fuse_get_req(fc);
1025ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1026ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
1027e5e5558eSMiklos Szeredi 
102804730fefSMiklos Szeredi 	page = alloc_page(GFP_KERNEL);
102904730fefSMiklos Szeredi 	if (!page) {
103004730fefSMiklos Szeredi 		fuse_put_request(fc, req);
1031e5e5558eSMiklos Szeredi 		return -ENOMEM;
103204730fefSMiklos Szeredi 	}
103304730fefSMiklos Szeredi 	req->num_pages = 1;
103404730fefSMiklos Szeredi 	req->pages[0] = page;
1035a6643094SMiklos Szeredi 	fuse_read_fill(req, file, inode, file->f_pos, PAGE_SIZE, FUSE_READDIR);
1036361b1eb5SMiklos Szeredi 	request_send(fc, req);
1037361b1eb5SMiklos Szeredi 	nbytes = req->out.args[0].size;
103804730fefSMiklos Szeredi 	err = req->out.h.error;
103904730fefSMiklos Szeredi 	fuse_put_request(fc, req);
104004730fefSMiklos Szeredi 	if (!err)
104104730fefSMiklos Szeredi 		err = parse_dirfile(page_address(page), nbytes, file, dstbuf,
104204730fefSMiklos Szeredi 				    filldir);
1043e5e5558eSMiklos Szeredi 
104404730fefSMiklos Szeredi 	__free_page(page);
1045b36c31baSMiklos Szeredi 	fuse_invalidate_attr(inode); /* atime changed */
104604730fefSMiklos Szeredi 	return err;
1047e5e5558eSMiklos Szeredi }
1048e5e5558eSMiklos Szeredi 
1049e5e5558eSMiklos Szeredi static char *read_link(struct dentry *dentry)
1050e5e5558eSMiklos Szeredi {
1051e5e5558eSMiklos Szeredi 	struct inode *inode = dentry->d_inode;
1052e5e5558eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1053ce1d5a49SMiklos Szeredi 	struct fuse_req *req = fuse_get_req(fc);
1054e5e5558eSMiklos Szeredi 	char *link;
1055e5e5558eSMiklos Szeredi 
1056ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1057e231c2eeSDavid Howells 		return ERR_CAST(req);
1058e5e5558eSMiklos Szeredi 
1059e5e5558eSMiklos Szeredi 	link = (char *) __get_free_page(GFP_KERNEL);
1060e5e5558eSMiklos Szeredi 	if (!link) {
1061e5e5558eSMiklos Szeredi 		link = ERR_PTR(-ENOMEM);
1062e5e5558eSMiklos Szeredi 		goto out;
1063e5e5558eSMiklos Szeredi 	}
1064e5e5558eSMiklos Szeredi 	req->in.h.opcode = FUSE_READLINK;
1065e5e5558eSMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
1066e5e5558eSMiklos Szeredi 	req->out.argvar = 1;
1067e5e5558eSMiklos Szeredi 	req->out.numargs = 1;
1068e5e5558eSMiklos Szeredi 	req->out.args[0].size = PAGE_SIZE - 1;
1069e5e5558eSMiklos Szeredi 	req->out.args[0].value = link;
1070e5e5558eSMiklos Szeredi 	request_send(fc, req);
1071e5e5558eSMiklos Szeredi 	if (req->out.h.error) {
1072e5e5558eSMiklos Szeredi 		free_page((unsigned long) link);
1073e5e5558eSMiklos Szeredi 		link = ERR_PTR(req->out.h.error);
1074e5e5558eSMiklos Szeredi 	} else
1075e5e5558eSMiklos Szeredi 		link[req->out.args[0].size] = '\0';
1076e5e5558eSMiklos Szeredi  out:
1077e5e5558eSMiklos Szeredi 	fuse_put_request(fc, req);
1078b36c31baSMiklos Szeredi 	fuse_invalidate_attr(inode); /* atime changed */
1079e5e5558eSMiklos Szeredi 	return link;
1080e5e5558eSMiklos Szeredi }
1081e5e5558eSMiklos Szeredi 
1082e5e5558eSMiklos Szeredi static void free_link(char *link)
1083e5e5558eSMiklos Szeredi {
1084e5e5558eSMiklos Szeredi 	if (!IS_ERR(link))
1085e5e5558eSMiklos Szeredi 		free_page((unsigned long) link);
1086e5e5558eSMiklos Szeredi }
1087e5e5558eSMiklos Szeredi 
1088e5e5558eSMiklos Szeredi static void *fuse_follow_link(struct dentry *dentry, struct nameidata *nd)
1089e5e5558eSMiklos Szeredi {
1090e5e5558eSMiklos Szeredi 	nd_set_link(nd, read_link(dentry));
1091e5e5558eSMiklos Szeredi 	return NULL;
1092e5e5558eSMiklos Szeredi }
1093e5e5558eSMiklos Szeredi 
1094e5e5558eSMiklos Szeredi static void fuse_put_link(struct dentry *dentry, struct nameidata *nd, void *c)
1095e5e5558eSMiklos Szeredi {
1096e5e5558eSMiklos Szeredi 	free_link(nd_get_link(nd));
1097e5e5558eSMiklos Szeredi }
1098e5e5558eSMiklos Szeredi 
1099e5e5558eSMiklos Szeredi static int fuse_dir_open(struct inode *inode, struct file *file)
1100e5e5558eSMiklos Szeredi {
110104730fefSMiklos Szeredi 	return fuse_open_common(inode, file, 1);
1102e5e5558eSMiklos Szeredi }
1103e5e5558eSMiklos Szeredi 
1104e5e5558eSMiklos Szeredi static int fuse_dir_release(struct inode *inode, struct file *file)
1105e5e5558eSMiklos Szeredi {
110604730fefSMiklos Szeredi 	return fuse_release_common(inode, file, 1);
1107e5e5558eSMiklos Szeredi }
1108e5e5558eSMiklos Szeredi 
110982547981SMiklos Szeredi static int fuse_dir_fsync(struct file *file, struct dentry *de, int datasync)
111082547981SMiklos Szeredi {
111182547981SMiklos Szeredi 	/* nfsd can call this with no file */
111282547981SMiklos Szeredi 	return file ? fuse_fsync_common(file, de, datasync, 1) : 0;
111382547981SMiklos Szeredi }
111482547981SMiklos Szeredi 
111517637cbaSMiklos Szeredi static bool update_mtime(unsigned ivalid)
111617637cbaSMiklos Szeredi {
111717637cbaSMiklos Szeredi 	/* Always update if mtime is explicitly set  */
111817637cbaSMiklos Szeredi 	if (ivalid & ATTR_MTIME_SET)
111917637cbaSMiklos Szeredi 		return true;
112017637cbaSMiklos Szeredi 
112117637cbaSMiklos Szeredi 	/* If it's an open(O_TRUNC) or an ftruncate(), don't update */
112217637cbaSMiklos Szeredi 	if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
112317637cbaSMiklos Szeredi 		return false;
112417637cbaSMiklos Szeredi 
112517637cbaSMiklos Szeredi 	/* In all other cases update */
112617637cbaSMiklos Szeredi 	return true;
112717637cbaSMiklos Szeredi }
112817637cbaSMiklos Szeredi 
1129befc649cSMiklos Szeredi static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg)
11309e6268dbSMiklos Szeredi {
11319e6268dbSMiklos Szeredi 	unsigned ivalid = iattr->ia_valid;
11329e6268dbSMiklos Szeredi 
11339e6268dbSMiklos Szeredi 	if (ivalid & ATTR_MODE)
1134befc649cSMiklos Szeredi 		arg->valid |= FATTR_MODE,   arg->mode = iattr->ia_mode;
11359e6268dbSMiklos Szeredi 	if (ivalid & ATTR_UID)
1136befc649cSMiklos Szeredi 		arg->valid |= FATTR_UID,    arg->uid = iattr->ia_uid;
11379e6268dbSMiklos Szeredi 	if (ivalid & ATTR_GID)
1138befc649cSMiklos Szeredi 		arg->valid |= FATTR_GID,    arg->gid = iattr->ia_gid;
11399e6268dbSMiklos Szeredi 	if (ivalid & ATTR_SIZE)
1140befc649cSMiklos Szeredi 		arg->valid |= FATTR_SIZE,   arg->size = iattr->ia_size;
114117637cbaSMiklos Szeredi 	if (ivalid & ATTR_ATIME) {
114217637cbaSMiklos Szeredi 		arg->valid |= FATTR_ATIME;
1143befc649cSMiklos Szeredi 		arg->atime = iattr->ia_atime.tv_sec;
114417637cbaSMiklos Szeredi 		arg->atimensec = iattr->ia_atime.tv_nsec;
114517637cbaSMiklos Szeredi 		if (!(ivalid & ATTR_ATIME_SET))
114617637cbaSMiklos Szeredi 			arg->valid |= FATTR_ATIME_NOW;
114717637cbaSMiklos Szeredi 	}
114817637cbaSMiklos Szeredi 	if ((ivalid & ATTR_MTIME) && update_mtime(ivalid)) {
114917637cbaSMiklos Szeredi 		arg->valid |= FATTR_MTIME;
1150befc649cSMiklos Szeredi 		arg->mtime = iattr->ia_mtime.tv_sec;
115117637cbaSMiklos Szeredi 		arg->mtimensec = iattr->ia_mtime.tv_nsec;
115217637cbaSMiklos Szeredi 		if (!(ivalid & ATTR_MTIME_SET))
115317637cbaSMiklos Szeredi 			arg->valid |= FATTR_MTIME_NOW;
11549e6268dbSMiklos Szeredi 	}
11559e6268dbSMiklos Szeredi }
11569e6268dbSMiklos Szeredi 
11576f9f1180SMiklos Szeredi /*
11583be5a52bSMiklos Szeredi  * Prevent concurrent writepages on inode
11593be5a52bSMiklos Szeredi  *
11603be5a52bSMiklos Szeredi  * This is done by adding a negative bias to the inode write counter
11613be5a52bSMiklos Szeredi  * and waiting for all pending writes to finish.
11623be5a52bSMiklos Szeredi  */
11633be5a52bSMiklos Szeredi void fuse_set_nowrite(struct inode *inode)
11643be5a52bSMiklos Szeredi {
11653be5a52bSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
11663be5a52bSMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
11673be5a52bSMiklos Szeredi 
11683be5a52bSMiklos Szeredi 	BUG_ON(!mutex_is_locked(&inode->i_mutex));
11693be5a52bSMiklos Szeredi 
11703be5a52bSMiklos Szeredi 	spin_lock(&fc->lock);
11713be5a52bSMiklos Szeredi 	BUG_ON(fi->writectr < 0);
11723be5a52bSMiklos Szeredi 	fi->writectr += FUSE_NOWRITE;
11733be5a52bSMiklos Szeredi 	spin_unlock(&fc->lock);
11743be5a52bSMiklos Szeredi 	wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE);
11753be5a52bSMiklos Szeredi }
11763be5a52bSMiklos Szeredi 
11773be5a52bSMiklos Szeredi /*
11783be5a52bSMiklos Szeredi  * Allow writepages on inode
11793be5a52bSMiklos Szeredi  *
11803be5a52bSMiklos Szeredi  * Remove the bias from the writecounter and send any queued
11813be5a52bSMiklos Szeredi  * writepages.
11823be5a52bSMiklos Szeredi  */
11833be5a52bSMiklos Szeredi static void __fuse_release_nowrite(struct inode *inode)
11843be5a52bSMiklos Szeredi {
11853be5a52bSMiklos Szeredi 	struct fuse_inode *fi = get_fuse_inode(inode);
11863be5a52bSMiklos Szeredi 
11873be5a52bSMiklos Szeredi 	BUG_ON(fi->writectr != FUSE_NOWRITE);
11883be5a52bSMiklos Szeredi 	fi->writectr = 0;
11893be5a52bSMiklos Szeredi 	fuse_flush_writepages(inode);
11903be5a52bSMiklos Szeredi }
11913be5a52bSMiklos Szeredi 
11923be5a52bSMiklos Szeredi void fuse_release_nowrite(struct inode *inode)
11933be5a52bSMiklos Szeredi {
11943be5a52bSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
11953be5a52bSMiklos Szeredi 
11963be5a52bSMiklos Szeredi 	spin_lock(&fc->lock);
11973be5a52bSMiklos Szeredi 	__fuse_release_nowrite(inode);
11983be5a52bSMiklos Szeredi 	spin_unlock(&fc->lock);
11993be5a52bSMiklos Szeredi }
12003be5a52bSMiklos Szeredi 
12013be5a52bSMiklos Szeredi /*
12026f9f1180SMiklos Szeredi  * Set attributes, and at the same time refresh them.
12036f9f1180SMiklos Szeredi  *
12046f9f1180SMiklos Szeredi  * Truncation is slightly complicated, because the 'truncate' request
12056f9f1180SMiklos Szeredi  * may fail, in which case we don't want to touch the mapping.
12069ffbb916SMiklos Szeredi  * vmtruncate() doesn't allow for this case, so do the rlimit checking
12079ffbb916SMiklos Szeredi  * and the actual truncation by hand.
12086f9f1180SMiklos Szeredi  */
120949d4914fSMiklos Szeredi static int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
121049d4914fSMiklos Szeredi 			   struct file *file)
12119e6268dbSMiklos Szeredi {
12129e6268dbSMiklos Szeredi 	struct inode *inode = entry->d_inode;
12139e6268dbSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
12149e6268dbSMiklos Szeredi 	struct fuse_req *req;
12159e6268dbSMiklos Szeredi 	struct fuse_setattr_in inarg;
12169e6268dbSMiklos Szeredi 	struct fuse_attr_out outarg;
12173be5a52bSMiklos Szeredi 	bool is_truncate = false;
12183be5a52bSMiklos Szeredi 	loff_t oldsize;
12199e6268dbSMiklos Szeredi 	int err;
12209e6268dbSMiklos Szeredi 
1221e57ac683SMiklos Szeredi 	if (!fuse_allow_task(fc, current))
1222e57ac683SMiklos Szeredi 		return -EACCES;
1223e57ac683SMiklos Szeredi 
12241e9a4ed9SMiklos Szeredi 	if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
12251e9a4ed9SMiklos Szeredi 		err = inode_change_ok(inode, attr);
12261e9a4ed9SMiklos Szeredi 		if (err)
12271e9a4ed9SMiklos Szeredi 			return err;
12281e9a4ed9SMiklos Szeredi 	}
12291e9a4ed9SMiklos Szeredi 
12306ff958edSMiklos Szeredi 	if ((attr->ia_valid & ATTR_OPEN) && fc->atomic_o_trunc)
12316ff958edSMiklos Szeredi 		return 0;
12326ff958edSMiklos Szeredi 
12339e6268dbSMiklos Szeredi 	if (attr->ia_valid & ATTR_SIZE) {
12349e6268dbSMiklos Szeredi 		unsigned long limit;
1235b2d2272fSMiklos Szeredi 		if (IS_SWAPFILE(inode))
1236b2d2272fSMiklos Szeredi 			return -ETXTBSY;
12379e6268dbSMiklos Szeredi 		limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
12389e6268dbSMiklos Szeredi 		if (limit != RLIM_INFINITY && attr->ia_size > (loff_t) limit) {
12399e6268dbSMiklos Szeredi 			send_sig(SIGXFSZ, current, 0);
12409e6268dbSMiklos Szeredi 			return -EFBIG;
12419e6268dbSMiklos Szeredi 		}
12423be5a52bSMiklos Szeredi 		is_truncate = true;
12439e6268dbSMiklos Szeredi 	}
12449e6268dbSMiklos Szeredi 
1245ce1d5a49SMiklos Szeredi 	req = fuse_get_req(fc);
1246ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1247ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
12489e6268dbSMiklos Szeredi 
12493be5a52bSMiklos Szeredi 	if (is_truncate)
12503be5a52bSMiklos Szeredi 		fuse_set_nowrite(inode);
12513be5a52bSMiklos Szeredi 
12529e6268dbSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
12530e9663eeSMiklos Szeredi 	memset(&outarg, 0, sizeof(outarg));
1254befc649cSMiklos Szeredi 	iattr_to_fattr(attr, &inarg);
125549d4914fSMiklos Szeredi 	if (file) {
125649d4914fSMiklos Szeredi 		struct fuse_file *ff = file->private_data;
125749d4914fSMiklos Szeredi 		inarg.valid |= FATTR_FH;
125849d4914fSMiklos Szeredi 		inarg.fh = ff->fh;
125949d4914fSMiklos Szeredi 	}
1260f3332114SMiklos Szeredi 	if (attr->ia_valid & ATTR_SIZE) {
1261f3332114SMiklos Szeredi 		/* For mandatory locking in truncate */
1262f3332114SMiklos Szeredi 		inarg.valid |= FATTR_LOCKOWNER;
1263f3332114SMiklos Szeredi 		inarg.lock_owner = fuse_lock_owner_id(fc, current->files);
1264f3332114SMiklos Szeredi 	}
12659e6268dbSMiklos Szeredi 	req->in.h.opcode = FUSE_SETATTR;
12669e6268dbSMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
12679e6268dbSMiklos Szeredi 	req->in.numargs = 1;
12689e6268dbSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
12699e6268dbSMiklos Szeredi 	req->in.args[0].value = &inarg;
12709e6268dbSMiklos Szeredi 	req->out.numargs = 1;
12710e9663eeSMiklos Szeredi 	if (fc->minor < 9)
12720e9663eeSMiklos Szeredi 		req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
12730e9663eeSMiklos Szeredi 	else
12749e6268dbSMiklos Szeredi 		req->out.args[0].size = sizeof(outarg);
12759e6268dbSMiklos Szeredi 	req->out.args[0].value = &outarg;
12769e6268dbSMiklos Szeredi 	request_send(fc, req);
12779e6268dbSMiklos Szeredi 	err = req->out.h.error;
12789e6268dbSMiklos Szeredi 	fuse_put_request(fc, req);
1279e00d2c2dSMiklos Szeredi 	if (err) {
1280e00d2c2dSMiklos Szeredi 		if (err == -EINTR)
1281e00d2c2dSMiklos Szeredi 			fuse_invalidate_attr(inode);
12823be5a52bSMiklos Szeredi 		goto error;
1283e00d2c2dSMiklos Szeredi 	}
1284e00d2c2dSMiklos Szeredi 
12859e6268dbSMiklos Szeredi 	if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
12869e6268dbSMiklos Szeredi 		make_bad_inode(inode);
12873be5a52bSMiklos Szeredi 		err = -EIO;
12883be5a52bSMiklos Szeredi 		goto error;
12899e6268dbSMiklos Szeredi 	}
12909e6268dbSMiklos Szeredi 
12913be5a52bSMiklos Szeredi 	spin_lock(&fc->lock);
12923be5a52bSMiklos Szeredi 	fuse_change_attributes_common(inode, &outarg.attr,
12933be5a52bSMiklos Szeredi 				      attr_timeout(&outarg));
12943be5a52bSMiklos Szeredi 	oldsize = inode->i_size;
12953be5a52bSMiklos Szeredi 	i_size_write(inode, outarg.attr.size);
12963be5a52bSMiklos Szeredi 
12973be5a52bSMiklos Szeredi 	if (is_truncate) {
12983be5a52bSMiklos Szeredi 		/* NOTE: this may release/reacquire fc->lock */
12993be5a52bSMiklos Szeredi 		__fuse_release_nowrite(inode);
13003be5a52bSMiklos Szeredi 	}
13013be5a52bSMiklos Szeredi 	spin_unlock(&fc->lock);
13023be5a52bSMiklos Szeredi 
13033be5a52bSMiklos Szeredi 	/*
13043be5a52bSMiklos Szeredi 	 * Only call invalidate_inode_pages2() after removing
13053be5a52bSMiklos Szeredi 	 * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock.
13063be5a52bSMiklos Szeredi 	 */
13073be5a52bSMiklos Szeredi 	if (S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
13083be5a52bSMiklos Szeredi 		if (outarg.attr.size < oldsize)
13093be5a52bSMiklos Szeredi 			fuse_truncate(inode->i_mapping, outarg.attr.size);
13103be5a52bSMiklos Szeredi 		invalidate_inode_pages2(inode->i_mapping);
13113be5a52bSMiklos Szeredi 	}
13123be5a52bSMiklos Szeredi 
1313e00d2c2dSMiklos Szeredi 	return 0;
13143be5a52bSMiklos Szeredi 
13153be5a52bSMiklos Szeredi error:
13163be5a52bSMiklos Szeredi 	if (is_truncate)
13173be5a52bSMiklos Szeredi 		fuse_release_nowrite(inode);
13183be5a52bSMiklos Szeredi 
13193be5a52bSMiklos Szeredi 	return err;
13209e6268dbSMiklos Szeredi }
13219e6268dbSMiklos Szeredi 
132249d4914fSMiklos Szeredi static int fuse_setattr(struct dentry *entry, struct iattr *attr)
132349d4914fSMiklos Szeredi {
132449d4914fSMiklos Szeredi 	if (attr->ia_valid & ATTR_FILE)
132549d4914fSMiklos Szeredi 		return fuse_do_setattr(entry, attr, attr->ia_file);
132649d4914fSMiklos Szeredi 	else
132749d4914fSMiklos Szeredi 		return fuse_do_setattr(entry, attr, NULL);
132849d4914fSMiklos Szeredi }
132949d4914fSMiklos Szeredi 
1330e5e5558eSMiklos Szeredi static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
1331e5e5558eSMiklos Szeredi 			struct kstat *stat)
1332e5e5558eSMiklos Szeredi {
1333e5e5558eSMiklos Szeredi 	struct inode *inode = entry->d_inode;
1334244f6385SMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
1335244f6385SMiklos Szeredi 
1336244f6385SMiklos Szeredi 	if (!fuse_allow_task(fc, current))
1337244f6385SMiklos Szeredi 		return -EACCES;
1338244f6385SMiklos Szeredi 
1339bcb4be80SMiklos Szeredi 	return fuse_update_attributes(inode, stat, NULL, NULL);
1340e5e5558eSMiklos Szeredi }
1341e5e5558eSMiklos Szeredi 
134292a8780eSMiklos Szeredi static int fuse_setxattr(struct dentry *entry, const char *name,
134392a8780eSMiklos Szeredi 			 const void *value, size_t size, int flags)
134492a8780eSMiklos Szeredi {
134592a8780eSMiklos Szeredi 	struct inode *inode = entry->d_inode;
134692a8780eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
134792a8780eSMiklos Szeredi 	struct fuse_req *req;
134892a8780eSMiklos Szeredi 	struct fuse_setxattr_in inarg;
134992a8780eSMiklos Szeredi 	int err;
135092a8780eSMiklos Szeredi 
135192a8780eSMiklos Szeredi 	if (fc->no_setxattr)
135292a8780eSMiklos Szeredi 		return -EOPNOTSUPP;
135392a8780eSMiklos Szeredi 
1354ce1d5a49SMiklos Szeredi 	req = fuse_get_req(fc);
1355ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1356ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
135792a8780eSMiklos Szeredi 
135892a8780eSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
135992a8780eSMiklos Szeredi 	inarg.size = size;
136092a8780eSMiklos Szeredi 	inarg.flags = flags;
136192a8780eSMiklos Szeredi 	req->in.h.opcode = FUSE_SETXATTR;
136292a8780eSMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
136392a8780eSMiklos Szeredi 	req->in.numargs = 3;
136492a8780eSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
136592a8780eSMiklos Szeredi 	req->in.args[0].value = &inarg;
136692a8780eSMiklos Szeredi 	req->in.args[1].size = strlen(name) + 1;
136792a8780eSMiklos Szeredi 	req->in.args[1].value = name;
136892a8780eSMiklos Szeredi 	req->in.args[2].size = size;
136992a8780eSMiklos Szeredi 	req->in.args[2].value = value;
137092a8780eSMiklos Szeredi 	request_send(fc, req);
137192a8780eSMiklos Szeredi 	err = req->out.h.error;
137292a8780eSMiklos Szeredi 	fuse_put_request(fc, req);
137392a8780eSMiklos Szeredi 	if (err == -ENOSYS) {
137492a8780eSMiklos Szeredi 		fc->no_setxattr = 1;
137592a8780eSMiklos Szeredi 		err = -EOPNOTSUPP;
137692a8780eSMiklos Szeredi 	}
137792a8780eSMiklos Szeredi 	return err;
137892a8780eSMiklos Szeredi }
137992a8780eSMiklos Szeredi 
138092a8780eSMiklos Szeredi static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
138192a8780eSMiklos Szeredi 			     void *value, size_t size)
138292a8780eSMiklos Szeredi {
138392a8780eSMiklos Szeredi 	struct inode *inode = entry->d_inode;
138492a8780eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
138592a8780eSMiklos Szeredi 	struct fuse_req *req;
138692a8780eSMiklos Szeredi 	struct fuse_getxattr_in inarg;
138792a8780eSMiklos Szeredi 	struct fuse_getxattr_out outarg;
138892a8780eSMiklos Szeredi 	ssize_t ret;
138992a8780eSMiklos Szeredi 
139092a8780eSMiklos Szeredi 	if (fc->no_getxattr)
139192a8780eSMiklos Szeredi 		return -EOPNOTSUPP;
139292a8780eSMiklos Szeredi 
1393ce1d5a49SMiklos Szeredi 	req = fuse_get_req(fc);
1394ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1395ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
139692a8780eSMiklos Szeredi 
139792a8780eSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
139892a8780eSMiklos Szeredi 	inarg.size = size;
139992a8780eSMiklos Szeredi 	req->in.h.opcode = FUSE_GETXATTR;
140092a8780eSMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
140192a8780eSMiklos Szeredi 	req->in.numargs = 2;
140292a8780eSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
140392a8780eSMiklos Szeredi 	req->in.args[0].value = &inarg;
140492a8780eSMiklos Szeredi 	req->in.args[1].size = strlen(name) + 1;
140592a8780eSMiklos Szeredi 	req->in.args[1].value = name;
140692a8780eSMiklos Szeredi 	/* This is really two different operations rolled into one */
140792a8780eSMiklos Szeredi 	req->out.numargs = 1;
140892a8780eSMiklos Szeredi 	if (size) {
140992a8780eSMiklos Szeredi 		req->out.argvar = 1;
141092a8780eSMiklos Szeredi 		req->out.args[0].size = size;
141192a8780eSMiklos Szeredi 		req->out.args[0].value = value;
141292a8780eSMiklos Szeredi 	} else {
141392a8780eSMiklos Szeredi 		req->out.args[0].size = sizeof(outarg);
141492a8780eSMiklos Szeredi 		req->out.args[0].value = &outarg;
141592a8780eSMiklos Szeredi 	}
141692a8780eSMiklos Szeredi 	request_send(fc, req);
141792a8780eSMiklos Szeredi 	ret = req->out.h.error;
141892a8780eSMiklos Szeredi 	if (!ret)
141992a8780eSMiklos Szeredi 		ret = size ? req->out.args[0].size : outarg.size;
142092a8780eSMiklos Szeredi 	else {
142192a8780eSMiklos Szeredi 		if (ret == -ENOSYS) {
142292a8780eSMiklos Szeredi 			fc->no_getxattr = 1;
142392a8780eSMiklos Szeredi 			ret = -EOPNOTSUPP;
142492a8780eSMiklos Szeredi 		}
142592a8780eSMiklos Szeredi 	}
142692a8780eSMiklos Szeredi 	fuse_put_request(fc, req);
142792a8780eSMiklos Szeredi 	return ret;
142892a8780eSMiklos Szeredi }
142992a8780eSMiklos Szeredi 
143092a8780eSMiklos Szeredi static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
143192a8780eSMiklos Szeredi {
143292a8780eSMiklos Szeredi 	struct inode *inode = entry->d_inode;
143392a8780eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
143492a8780eSMiklos Szeredi 	struct fuse_req *req;
143592a8780eSMiklos Szeredi 	struct fuse_getxattr_in inarg;
143692a8780eSMiklos Szeredi 	struct fuse_getxattr_out outarg;
143792a8780eSMiklos Szeredi 	ssize_t ret;
143892a8780eSMiklos Szeredi 
1439e57ac683SMiklos Szeredi 	if (!fuse_allow_task(fc, current))
1440e57ac683SMiklos Szeredi 		return -EACCES;
1441e57ac683SMiklos Szeredi 
144292a8780eSMiklos Szeredi 	if (fc->no_listxattr)
144392a8780eSMiklos Szeredi 		return -EOPNOTSUPP;
144492a8780eSMiklos Szeredi 
1445ce1d5a49SMiklos Szeredi 	req = fuse_get_req(fc);
1446ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1447ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
144892a8780eSMiklos Szeredi 
144992a8780eSMiklos Szeredi 	memset(&inarg, 0, sizeof(inarg));
145092a8780eSMiklos Szeredi 	inarg.size = size;
145192a8780eSMiklos Szeredi 	req->in.h.opcode = FUSE_LISTXATTR;
145292a8780eSMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
145392a8780eSMiklos Szeredi 	req->in.numargs = 1;
145492a8780eSMiklos Szeredi 	req->in.args[0].size = sizeof(inarg);
145592a8780eSMiklos Szeredi 	req->in.args[0].value = &inarg;
145692a8780eSMiklos Szeredi 	/* This is really two different operations rolled into one */
145792a8780eSMiklos Szeredi 	req->out.numargs = 1;
145892a8780eSMiklos Szeredi 	if (size) {
145992a8780eSMiklos Szeredi 		req->out.argvar = 1;
146092a8780eSMiklos Szeredi 		req->out.args[0].size = size;
146192a8780eSMiklos Szeredi 		req->out.args[0].value = list;
146292a8780eSMiklos Szeredi 	} else {
146392a8780eSMiklos Szeredi 		req->out.args[0].size = sizeof(outarg);
146492a8780eSMiklos Szeredi 		req->out.args[0].value = &outarg;
146592a8780eSMiklos Szeredi 	}
146692a8780eSMiklos Szeredi 	request_send(fc, req);
146792a8780eSMiklos Szeredi 	ret = req->out.h.error;
146892a8780eSMiklos Szeredi 	if (!ret)
146992a8780eSMiklos Szeredi 		ret = size ? req->out.args[0].size : outarg.size;
147092a8780eSMiklos Szeredi 	else {
147192a8780eSMiklos Szeredi 		if (ret == -ENOSYS) {
147292a8780eSMiklos Szeredi 			fc->no_listxattr = 1;
147392a8780eSMiklos Szeredi 			ret = -EOPNOTSUPP;
147492a8780eSMiklos Szeredi 		}
147592a8780eSMiklos Szeredi 	}
147692a8780eSMiklos Szeredi 	fuse_put_request(fc, req);
147792a8780eSMiklos Szeredi 	return ret;
147892a8780eSMiklos Szeredi }
147992a8780eSMiklos Szeredi 
148092a8780eSMiklos Szeredi static int fuse_removexattr(struct dentry *entry, const char *name)
148192a8780eSMiklos Szeredi {
148292a8780eSMiklos Szeredi 	struct inode *inode = entry->d_inode;
148392a8780eSMiklos Szeredi 	struct fuse_conn *fc = get_fuse_conn(inode);
148492a8780eSMiklos Szeredi 	struct fuse_req *req;
148592a8780eSMiklos Szeredi 	int err;
148692a8780eSMiklos Szeredi 
148792a8780eSMiklos Szeredi 	if (fc->no_removexattr)
148892a8780eSMiklos Szeredi 		return -EOPNOTSUPP;
148992a8780eSMiklos Szeredi 
1490ce1d5a49SMiklos Szeredi 	req = fuse_get_req(fc);
1491ce1d5a49SMiklos Szeredi 	if (IS_ERR(req))
1492ce1d5a49SMiklos Szeredi 		return PTR_ERR(req);
149392a8780eSMiklos Szeredi 
149492a8780eSMiklos Szeredi 	req->in.h.opcode = FUSE_REMOVEXATTR;
149592a8780eSMiklos Szeredi 	req->in.h.nodeid = get_node_id(inode);
149692a8780eSMiklos Szeredi 	req->in.numargs = 1;
149792a8780eSMiklos Szeredi 	req->in.args[0].size = strlen(name) + 1;
149892a8780eSMiklos Szeredi 	req->in.args[0].value = name;
149992a8780eSMiklos Szeredi 	request_send(fc, req);
150092a8780eSMiklos Szeredi 	err = req->out.h.error;
150192a8780eSMiklos Szeredi 	fuse_put_request(fc, req);
150292a8780eSMiklos Szeredi 	if (err == -ENOSYS) {
150392a8780eSMiklos Szeredi 		fc->no_removexattr = 1;
150492a8780eSMiklos Szeredi 		err = -EOPNOTSUPP;
150592a8780eSMiklos Szeredi 	}
150692a8780eSMiklos Szeredi 	return err;
150792a8780eSMiklos Szeredi }
150892a8780eSMiklos Szeredi 
1509754661f1SArjan van de Ven static const struct inode_operations fuse_dir_inode_operations = {
1510e5e5558eSMiklos Szeredi 	.lookup		= fuse_lookup,
15119e6268dbSMiklos Szeredi 	.mkdir		= fuse_mkdir,
15129e6268dbSMiklos Szeredi 	.symlink	= fuse_symlink,
15139e6268dbSMiklos Szeredi 	.unlink		= fuse_unlink,
15149e6268dbSMiklos Szeredi 	.rmdir		= fuse_rmdir,
15159e6268dbSMiklos Szeredi 	.rename		= fuse_rename,
15169e6268dbSMiklos Szeredi 	.link		= fuse_link,
15179e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
15189e6268dbSMiklos Szeredi 	.create		= fuse_create,
15199e6268dbSMiklos Szeredi 	.mknod		= fuse_mknod,
1520e5e5558eSMiklos Szeredi 	.permission	= fuse_permission,
1521e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
152292a8780eSMiklos Szeredi 	.setxattr	= fuse_setxattr,
152392a8780eSMiklos Szeredi 	.getxattr	= fuse_getxattr,
152492a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
152592a8780eSMiklos Szeredi 	.removexattr	= fuse_removexattr,
1526e5e5558eSMiklos Szeredi };
1527e5e5558eSMiklos Szeredi 
15284b6f5d20SArjan van de Ven static const struct file_operations fuse_dir_operations = {
1529b6aeadedSMiklos Szeredi 	.llseek		= generic_file_llseek,
1530e5e5558eSMiklos Szeredi 	.read		= generic_read_dir,
1531e5e5558eSMiklos Szeredi 	.readdir	= fuse_readdir,
1532e5e5558eSMiklos Szeredi 	.open		= fuse_dir_open,
1533e5e5558eSMiklos Szeredi 	.release	= fuse_dir_release,
153482547981SMiklos Szeredi 	.fsync		= fuse_dir_fsync,
1535e5e5558eSMiklos Szeredi };
1536e5e5558eSMiklos Szeredi 
1537754661f1SArjan van de Ven static const struct inode_operations fuse_common_inode_operations = {
15389e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
1539e5e5558eSMiklos Szeredi 	.permission	= fuse_permission,
1540e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
154192a8780eSMiklos Szeredi 	.setxattr	= fuse_setxattr,
154292a8780eSMiklos Szeredi 	.getxattr	= fuse_getxattr,
154392a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
154492a8780eSMiklos Szeredi 	.removexattr	= fuse_removexattr,
1545e5e5558eSMiklos Szeredi };
1546e5e5558eSMiklos Szeredi 
1547754661f1SArjan van de Ven static const struct inode_operations fuse_symlink_inode_operations = {
15489e6268dbSMiklos Szeredi 	.setattr	= fuse_setattr,
1549e5e5558eSMiklos Szeredi 	.follow_link	= fuse_follow_link,
1550e5e5558eSMiklos Szeredi 	.put_link	= fuse_put_link,
1551e5e5558eSMiklos Szeredi 	.readlink	= generic_readlink,
1552e5e5558eSMiklos Szeredi 	.getattr	= fuse_getattr,
155392a8780eSMiklos Szeredi 	.setxattr	= fuse_setxattr,
155492a8780eSMiklos Szeredi 	.getxattr	= fuse_getxattr,
155592a8780eSMiklos Szeredi 	.listxattr	= fuse_listxattr,
155692a8780eSMiklos Szeredi 	.removexattr	= fuse_removexattr,
1557e5e5558eSMiklos Szeredi };
1558e5e5558eSMiklos Szeredi 
1559e5e5558eSMiklos Szeredi void fuse_init_common(struct inode *inode)
1560e5e5558eSMiklos Szeredi {
1561e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_common_inode_operations;
1562e5e5558eSMiklos Szeredi }
1563e5e5558eSMiklos Szeredi 
1564e5e5558eSMiklos Szeredi void fuse_init_dir(struct inode *inode)
1565e5e5558eSMiklos Szeredi {
1566e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_dir_inode_operations;
1567e5e5558eSMiklos Szeredi 	inode->i_fop = &fuse_dir_operations;
1568e5e5558eSMiklos Szeredi }
1569e5e5558eSMiklos Szeredi 
1570e5e5558eSMiklos Szeredi void fuse_init_symlink(struct inode *inode)
1571e5e5558eSMiklos Szeredi {
1572e5e5558eSMiklos Szeredi 	inode->i_op = &fuse_symlink_inode_operations;
1573e5e5558eSMiklos Szeredi }
1574