xref: /openbmc/linux/fs/exportfs/expfs.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
109c434b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2e38f9817SChristoph Hellwig /*
3e38f9817SChristoph Hellwig  * Copyright (C) Neil Brown 2002
4e38f9817SChristoph Hellwig  * Copyright (C) Christoph Hellwig 2007
5e38f9817SChristoph Hellwig  *
6e38f9817SChristoph Hellwig  * This file contains the code mapping from inodes to NFS file handles,
7e38f9817SChristoph Hellwig  * and for mapping back from file handles to dentries.
8e38f9817SChristoph Hellwig  *
9e38f9817SChristoph Hellwig  * For details on why we do all the strange and hairy things in here
10ec23eb54SMauro Carvalho Chehab  * take a look at Documentation/filesystems/nfs/exporting.rst.
11e38f9817SChristoph Hellwig  */
12a5694255SChristoph Hellwig #include <linux/exportfs.h>
131da177e4SLinus Torvalds #include <linux/fs.h>
141da177e4SLinus Torvalds #include <linux/file.h>
151da177e4SLinus Torvalds #include <linux/module.h>
16d37065cdSChristoph Hellwig #include <linux/mount.h>
171da177e4SLinus Torvalds #include <linux/namei.h>
18745ca247SDavid Howells #include <linux/sched.h>
195b825c3aSIngo Molnar #include <linux/cred.h>
201da177e4SLinus Torvalds 
21427505ffSDavid Disseldorp #define dprintk(fmt, args...) pr_debug(fmt, ##args)
221da177e4SLinus Torvalds 
2310f11c34SChristoph Hellwig 
24765927b2SAl Viro static int get_name(const struct path *path, char *name, struct dentry *child);
2510f11c34SChristoph Hellwig 
2610f11c34SChristoph Hellwig 
exportfs_get_name(struct vfsmount * mnt,struct dentry * dir,char * name,struct dentry * child)27e38f9817SChristoph Hellwig static int exportfs_get_name(struct vfsmount *mnt, struct dentry *dir,
28e38f9817SChristoph Hellwig 		char *name, struct dentry *child)
2910f11c34SChristoph Hellwig {
3039655164SChristoph Hellwig 	const struct export_operations *nop = dir->d_sb->s_export_op;
31765927b2SAl Viro 	struct path path = {.mnt = mnt, .dentry = dir};
3210f11c34SChristoph Hellwig 
3310f11c34SChristoph Hellwig 	if (nop->get_name)
3410f11c34SChristoph Hellwig 		return nop->get_name(dir, name, child);
3510f11c34SChristoph Hellwig 	else
36765927b2SAl Viro 		return get_name(&path, name, child);
3710f11c34SChristoph Hellwig }
3810f11c34SChristoph Hellwig 
39fb66a198SChristoph Hellwig /*
40fb66a198SChristoph Hellwig  * Check if the dentry or any of it's aliases is acceptable.
41fb66a198SChristoph Hellwig  */
42e2f99018SChristoph Hellwig static struct dentry *
find_acceptable_alias(struct dentry * result,int (* acceptable)(void * context,struct dentry * dentry),void * context)43e2f99018SChristoph Hellwig find_acceptable_alias(struct dentry *result,
44e2f99018SChristoph Hellwig 		int (*acceptable)(void *context, struct dentry *dentry),
45e2f99018SChristoph Hellwig 		void *context)
46e2f99018SChristoph Hellwig {
47e2f99018SChristoph Hellwig 	struct dentry *dentry, *toput = NULL;
48873feea0SNick Piggin 	struct inode *inode;
49e2f99018SChristoph Hellwig 
50fb66a198SChristoph Hellwig 	if (acceptable(context, result))
51fb66a198SChristoph Hellwig 		return result;
52fb66a198SChristoph Hellwig 
53873feea0SNick Piggin 	inode = result->d_inode;
54873feea0SNick Piggin 	spin_lock(&inode->i_lock);
55946e51f2SAl Viro 	hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
56dc0474beSNick Piggin 		dget(dentry);
57873feea0SNick Piggin 		spin_unlock(&inode->i_lock);
58e2f99018SChristoph Hellwig 		if (toput)
59e2f99018SChristoph Hellwig 			dput(toput);
60e2f99018SChristoph Hellwig 		if (dentry != result && acceptable(context, dentry)) {
61e2f99018SChristoph Hellwig 			dput(result);
62e2f99018SChristoph Hellwig 			return dentry;
63e2f99018SChristoph Hellwig 		}
64873feea0SNick Piggin 		spin_lock(&inode->i_lock);
65e2f99018SChristoph Hellwig 		toput = dentry;
66e2f99018SChristoph Hellwig 	}
67873feea0SNick Piggin 	spin_unlock(&inode->i_lock);
68e2f99018SChristoph Hellwig 
69e2f99018SChristoph Hellwig 	if (toput)
70e2f99018SChristoph Hellwig 		dput(toput);
71e2f99018SChristoph Hellwig 	return NULL;
72e2f99018SChristoph Hellwig }
73e2f99018SChristoph Hellwig 
dentry_connected(struct dentry * dentry)74a056cc89SJ. Bruce Fields static bool dentry_connected(struct dentry *dentry)
75a056cc89SJ. Bruce Fields {
76a056cc89SJ. Bruce Fields 	dget(dentry);
77a056cc89SJ. Bruce Fields 	while (dentry->d_flags & DCACHE_DISCONNECTED) {
78a056cc89SJ. Bruce Fields 		struct dentry *parent = dget_parent(dentry);
79a056cc89SJ. Bruce Fields 
80a056cc89SJ. Bruce Fields 		dput(dentry);
812084ac6cSPan Bian 		if (dentry == parent) {
82a056cc89SJ. Bruce Fields 			dput(parent);
83a056cc89SJ. Bruce Fields 			return false;
84a056cc89SJ. Bruce Fields 		}
85a056cc89SJ. Bruce Fields 		dentry = parent;
86a056cc89SJ. Bruce Fields 	}
87a056cc89SJ. Bruce Fields 	dput(dentry);
88a056cc89SJ. Bruce Fields 	return true;
89a056cc89SJ. Bruce Fields }
90a056cc89SJ. Bruce Fields 
clear_disconnected(struct dentry * dentry)910dbc018aSJ. Bruce Fields static void clear_disconnected(struct dentry *dentry)
920dbc018aSJ. Bruce Fields {
930dbc018aSJ. Bruce Fields 	dget(dentry);
940dbc018aSJ. Bruce Fields 	while (dentry->d_flags & DCACHE_DISCONNECTED) {
950dbc018aSJ. Bruce Fields 		struct dentry *parent = dget_parent(dentry);
960dbc018aSJ. Bruce Fields 
970dbc018aSJ. Bruce Fields 		WARN_ON_ONCE(IS_ROOT(dentry));
980dbc018aSJ. Bruce Fields 
990dbc018aSJ. Bruce Fields 		spin_lock(&dentry->d_lock);
1000dbc018aSJ. Bruce Fields 		dentry->d_flags &= ~DCACHE_DISCONNECTED;
1010dbc018aSJ. Bruce Fields 		spin_unlock(&dentry->d_lock);
1020dbc018aSJ. Bruce Fields 
1030dbc018aSJ. Bruce Fields 		dput(dentry);
1040dbc018aSJ. Bruce Fields 		dentry = parent;
1050dbc018aSJ. Bruce Fields 	}
1060dbc018aSJ. Bruce Fields 	dput(dentry);
1070dbc018aSJ. Bruce Fields }
1080dbc018aSJ. Bruce Fields 
109019ab801SChristoph Hellwig /*
110bbf7a8a3SJ. Bruce Fields  * Reconnect a directory dentry with its parent.
111bbf7a8a3SJ. Bruce Fields  *
112bbf7a8a3SJ. Bruce Fields  * This can return a dentry, or NULL, or an error.
113bbf7a8a3SJ. Bruce Fields  *
114bbf7a8a3SJ. Bruce Fields  * In the first case the returned dentry is the parent of the given
115bbf7a8a3SJ. Bruce Fields  * dentry, and may itself need to be reconnected to its parent.
116bbf7a8a3SJ. Bruce Fields  *
117bbf7a8a3SJ. Bruce Fields  * In the NULL case, a concurrent VFS operation has either renamed or
118bbf7a8a3SJ. Bruce Fields  * removed this directory.  The concurrent operation has reconnected our
119bbf7a8a3SJ. Bruce Fields  * dentry, so we no longer need to.
120bbf7a8a3SJ. Bruce Fields  */
reconnect_one(struct vfsmount * mnt,struct dentry * dentry,char * nbuf)121bbf7a8a3SJ. Bruce Fields static struct dentry *reconnect_one(struct vfsmount *mnt,
122bbf7a8a3SJ. Bruce Fields 		struct dentry *dentry, char *nbuf)
123bbf7a8a3SJ. Bruce Fields {
124bbf7a8a3SJ. Bruce Fields 	struct dentry *parent;
125bbf7a8a3SJ. Bruce Fields 	struct dentry *tmp;
126bbf7a8a3SJ. Bruce Fields 	int err;
127bbf7a8a3SJ. Bruce Fields 
128bbf7a8a3SJ. Bruce Fields 	parent = ERR_PTR(-EACCES);
1295955102cSAl Viro 	inode_lock(dentry->d_inode);
130bbf7a8a3SJ. Bruce Fields 	if (mnt->mnt_sb->s_export_op->get_parent)
131bbf7a8a3SJ. Bruce Fields 		parent = mnt->mnt_sb->s_export_op->get_parent(dentry);
1325955102cSAl Viro 	inode_unlock(dentry->d_inode);
133bbf7a8a3SJ. Bruce Fields 
134bbf7a8a3SJ. Bruce Fields 	if (IS_ERR(parent)) {
135427505ffSDavid Disseldorp 		dprintk("get_parent of %lu failed, err %ld\n",
136427505ffSDavid Disseldorp 			dentry->d_inode->i_ino, PTR_ERR(parent));
137bbf7a8a3SJ. Bruce Fields 		return parent;
138bbf7a8a3SJ. Bruce Fields 	}
139bbf7a8a3SJ. Bruce Fields 
140bbf7a8a3SJ. Bruce Fields 	dprintk("%s: find name of %lu in %lu\n", __func__,
141bbf7a8a3SJ. Bruce Fields 		dentry->d_inode->i_ino, parent->d_inode->i_ino);
142bbf7a8a3SJ. Bruce Fields 	err = exportfs_get_name(mnt, parent, nbuf, dentry);
143bbf7a8a3SJ. Bruce Fields 	if (err == -ENOENT)
144bbf7a8a3SJ. Bruce Fields 		goto out_reconnected;
145bbf7a8a3SJ. Bruce Fields 	if (err)
146bbf7a8a3SJ. Bruce Fields 		goto out_err;
147bbf7a8a3SJ. Bruce Fields 	dprintk("%s: found name: %s\n", __func__, nbuf);
1484609e1f1SChristian Brauner 	tmp = lookup_one_unlocked(mnt_idmap(mnt), nbuf, parent, strlen(nbuf));
149bbf7a8a3SJ. Bruce Fields 	if (IS_ERR(tmp)) {
150427505ffSDavid Disseldorp 		dprintk("lookup failed: %ld\n", PTR_ERR(tmp));
151909e22e0SYueHaibing 		err = PTR_ERR(tmp);
152bbf7a8a3SJ. Bruce Fields 		goto out_err;
153bbf7a8a3SJ. Bruce Fields 	}
154bbf7a8a3SJ. Bruce Fields 	if (tmp != dentry) {
155383d4e8aSAl Viro 		/*
156383d4e8aSAl Viro 		 * Somebody has renamed it since exportfs_get_name();
157383d4e8aSAl Viro 		 * great, since it could've only been renamed if it
158383d4e8aSAl Viro 		 * got looked up and thus connected, and it would
159383d4e8aSAl Viro 		 * remain connected afterwards.  We are done.
160383d4e8aSAl Viro 		 */
161bbf7a8a3SJ. Bruce Fields 		dput(tmp);
162bbf7a8a3SJ. Bruce Fields 		goto out_reconnected;
163bbf7a8a3SJ. Bruce Fields 	}
164bbf7a8a3SJ. Bruce Fields 	dput(tmp);
165bbf7a8a3SJ. Bruce Fields 	if (IS_ROOT(dentry)) {
166bbf7a8a3SJ. Bruce Fields 		err = -ESTALE;
167bbf7a8a3SJ. Bruce Fields 		goto out_err;
168bbf7a8a3SJ. Bruce Fields 	}
169bbf7a8a3SJ. Bruce Fields 	return parent;
170bbf7a8a3SJ. Bruce Fields 
171bbf7a8a3SJ. Bruce Fields out_err:
172bbf7a8a3SJ. Bruce Fields 	dput(parent);
173bbf7a8a3SJ. Bruce Fields 	return ERR_PTR(err);
174bbf7a8a3SJ. Bruce Fields out_reconnected:
175bbf7a8a3SJ. Bruce Fields 	dput(parent);
176bbf7a8a3SJ. Bruce Fields 	/*
177bbf7a8a3SJ. Bruce Fields 	 * Someone must have renamed our entry into another parent, in
178bbf7a8a3SJ. Bruce Fields 	 * which case it has been reconnected by the rename.
179bbf7a8a3SJ. Bruce Fields 	 *
180bbf7a8a3SJ. Bruce Fields 	 * Or someone removed it entirely, in which case filehandle
181bbf7a8a3SJ. Bruce Fields 	 * lookup will succeed but the directory is now IS_DEAD and
182bbf7a8a3SJ. Bruce Fields 	 * subsequent operations on it will fail.
183bbf7a8a3SJ. Bruce Fields 	 *
184bbf7a8a3SJ. Bruce Fields 	 * Alternatively, maybe there was no race at all, and the
185bbf7a8a3SJ. Bruce Fields 	 * filesystem is just corrupt and gave us a parent that doesn't
186bbf7a8a3SJ. Bruce Fields 	 * actually contain any entry pointing to this inode.  So,
187bbf7a8a3SJ. Bruce Fields 	 * double check that this worked and return -ESTALE if not:
188bbf7a8a3SJ. Bruce Fields 	 */
189bbf7a8a3SJ. Bruce Fields 	if (!dentry_connected(dentry))
190bbf7a8a3SJ. Bruce Fields 		return ERR_PTR(-ESTALE);
191bbf7a8a3SJ. Bruce Fields 	return NULL;
192bbf7a8a3SJ. Bruce Fields }
193bbf7a8a3SJ. Bruce Fields 
194bbf7a8a3SJ. Bruce Fields /*
195019ab801SChristoph Hellwig  * Make sure target_dir is fully connected to the dentry tree.
196019ab801SChristoph Hellwig  *
19778cee9a8SJ. Bruce Fields  * On successful return, DCACHE_DISCONNECTED will be cleared on
19878cee9a8SJ. Bruce Fields  * target_dir, and target_dir->d_parent->...->d_parent will reach the
19978cee9a8SJ. Bruce Fields  * root of the filesystem.
20078cee9a8SJ. Bruce Fields  *
20178cee9a8SJ. Bruce Fields  * Whenever DCACHE_DISCONNECTED is unset, target_dir is fully connected.
20278cee9a8SJ. Bruce Fields  * But the converse is not true: target_dir may have DCACHE_DISCONNECTED
20378cee9a8SJ. Bruce Fields  * set but already be connected.  In that case we'll verify the
20478cee9a8SJ. Bruce Fields  * connection to root and then clear the flag.
20578cee9a8SJ. Bruce Fields  *
20678cee9a8SJ. Bruce Fields  * Note that target_dir could be removed by a concurrent operation.  In
20778cee9a8SJ. Bruce Fields  * that case reconnect_path may still succeed with target_dir fully
20878cee9a8SJ. Bruce Fields  * connected, but further operations using the filehandle will fail when
20978cee9a8SJ. Bruce Fields  * necessary (due to S_DEAD being set on the directory).
210019ab801SChristoph Hellwig  */
211019ab801SChristoph Hellwig static int
reconnect_path(struct vfsmount * mnt,struct dentry * target_dir,char * nbuf)212f3f8e175SAl Viro reconnect_path(struct vfsmount *mnt, struct dentry *target_dir, char *nbuf)
213019ab801SChristoph Hellwig {
214f27c9298SJ. Bruce Fields 	struct dentry *dentry, *parent;
215019ab801SChristoph Hellwig 
216f27c9298SJ. Bruce Fields 	dentry = dget(target_dir);
217019ab801SChristoph Hellwig 
218f27c9298SJ. Bruce Fields 	while (dentry->d_flags & DCACHE_DISCONNECTED) {
219efbf201fSJ. Bruce Fields 		BUG_ON(dentry == mnt->mnt_sb->s_root);
220854ff5caSChristoph Hellwig 
221f27c9298SJ. Bruce Fields 		if (IS_ROOT(dentry))
222efbf201fSJ. Bruce Fields 			parent = reconnect_one(mnt, dentry, nbuf);
223f27c9298SJ. Bruce Fields 		else
224f27c9298SJ. Bruce Fields 			parent = dget_parent(dentry);
225f27c9298SJ. Bruce Fields 
226bbf7a8a3SJ. Bruce Fields 		if (!parent)
227019ab801SChristoph Hellwig 			break;
228f27c9298SJ. Bruce Fields 		dput(dentry);
229f27c9298SJ. Bruce Fields 		if (IS_ERR(parent))
230f27c9298SJ. Bruce Fields 			return PTR_ERR(parent);
231f27c9298SJ. Bruce Fields 		dentry = parent;
232019ab801SChristoph Hellwig 	}
233efbf201fSJ. Bruce Fields 	dput(dentry);
234a056cc89SJ. Bruce Fields 	clear_disconnected(target_dir);
235a056cc89SJ. Bruce Fields 	return 0;
236019ab801SChristoph Hellwig }
237019ab801SChristoph Hellwig 
2381da177e4SLinus Torvalds struct getdents_callback {
2395c0ba4e0SAl Viro 	struct dir_context ctx;
2401da177e4SLinus Torvalds 	char *name;		/* name that was found. It already points to a
2411da177e4SLinus Torvalds 				   buffer NAME_MAX+1 is size */
242950ee956SJ. Bruce Fields 	u64 ino;		/* the inum we are looking for */
2431da177e4SLinus Torvalds 	int found;		/* inode matched? */
2441da177e4SLinus Torvalds 	int sequence;		/* sequence counter */
2451da177e4SLinus Torvalds };
2461da177e4SLinus Torvalds 
2471da177e4SLinus Torvalds /*
2481da177e4SLinus Torvalds  * A rather strange filldir function to capture
2491da177e4SLinus Torvalds  * the name matching the specified inode number.
2501da177e4SLinus Torvalds  */
filldir_one(struct dir_context * ctx,const char * name,int len,loff_t pos,u64 ino,unsigned int d_type)25125885a35SAl Viro static bool filldir_one(struct dir_context *ctx, const char *name, int len,
252afefdbb2SDavid Howells 			loff_t pos, u64 ino, unsigned int d_type)
2531da177e4SLinus Torvalds {
254ac7576f4SMiklos Szeredi 	struct getdents_callback *buf =
255ac7576f4SMiklos Szeredi 		container_of(ctx, struct getdents_callback, ctx);
2561da177e4SLinus Torvalds 
2571da177e4SLinus Torvalds 	buf->sequence++;
258dfc59e2cSAl Viro 	if (buf->ino == ino && len <= NAME_MAX) {
2591da177e4SLinus Torvalds 		memcpy(buf->name, name, len);
2601da177e4SLinus Torvalds 		buf->name[len] = '\0';
2611da177e4SLinus Torvalds 		buf->found = 1;
26225885a35SAl Viro 		return false;	// no more
2631da177e4SLinus Torvalds 	}
26425885a35SAl Viro 	return true;
2651da177e4SLinus Torvalds }
2661da177e4SLinus Torvalds 
2671da177e4SLinus Torvalds /**
2681da177e4SLinus Torvalds  * get_name - default export_operations->get_name function
26900f01791SFabian Frederick  * @path:   the directory in which to find a name
2701da177e4SLinus Torvalds  * @name:   a pointer to a %NAME_MAX+1 char buffer to store the name
2711da177e4SLinus Torvalds  * @child:  the dentry for the child directory.
2721da177e4SLinus Torvalds  *
2731da177e4SLinus Torvalds  * calls readdir on the parent until it finds an entry with
2741da177e4SLinus Torvalds  * the same inode number as the child, and returns that.
2751da177e4SLinus Torvalds  */
get_name(const struct path * path,char * name,struct dentry * child)276765927b2SAl Viro static int get_name(const struct path *path, char *name, struct dentry *child)
2771da177e4SLinus Torvalds {
278745ca247SDavid Howells 	const struct cred *cred = current_cred();
279765927b2SAl Viro 	struct inode *dir = path->dentry->d_inode;
2801da177e4SLinus Torvalds 	int error;
2811da177e4SLinus Torvalds 	struct file *file;
282950ee956SJ. Bruce Fields 	struct kstat stat;
283950ee956SJ. Bruce Fields 	struct path child_path = {
284950ee956SJ. Bruce Fields 		.mnt = path->mnt,
285950ee956SJ. Bruce Fields 		.dentry = child,
286950ee956SJ. Bruce Fields 	};
287ac6614b7SAl Viro 	struct getdents_callback buffer = {
288ac6614b7SAl Viro 		.ctx.actor = filldir_one,
289ac6614b7SAl Viro 		.name = name,
290ac6614b7SAl Viro 	};
2911da177e4SLinus Torvalds 
2921da177e4SLinus Torvalds 	error = -ENOTDIR;
2931da177e4SLinus Torvalds 	if (!dir || !S_ISDIR(dir->i_mode))
2941da177e4SLinus Torvalds 		goto out;
2951da177e4SLinus Torvalds 	error = -EINVAL;
2961da177e4SLinus Torvalds 	if (!dir->i_fop)
2971da177e4SLinus Torvalds 		goto out;
2981da177e4SLinus Torvalds 	/*
299950ee956SJ. Bruce Fields 	 * inode->i_ino is unsigned long, kstat->ino is u64, so the
300950ee956SJ. Bruce Fields 	 * former would be insufficient on 32-bit hosts when the
301950ee956SJ. Bruce Fields 	 * filesystem supports 64-bit inode numbers.  So we need to
302950ee956SJ. Bruce Fields 	 * actually call ->getattr, not just read i_ino:
303950ee956SJ. Bruce Fields 	 */
304a528d35eSDavid Howells 	error = vfs_getattr_nosec(&child_path, &stat,
305a528d35eSDavid Howells 				  STATX_INO, AT_STATX_SYNC_AS_STAT);
306950ee956SJ. Bruce Fields 	if (error)
307950ee956SJ. Bruce Fields 		return error;
308950ee956SJ. Bruce Fields 	buffer.ino = stat.ino;
309950ee956SJ. Bruce Fields 	/*
3101da177e4SLinus Torvalds 	 * Open the directory ...
3111da177e4SLinus Torvalds 	 */
312765927b2SAl Viro 	file = dentry_open(path, O_RDONLY, cred);
3131da177e4SLinus Torvalds 	error = PTR_ERR(file);
3141da177e4SLinus Torvalds 	if (IS_ERR(file))
3151da177e4SLinus Torvalds 		goto out;
3161da177e4SLinus Torvalds 
3171da177e4SLinus Torvalds 	error = -EINVAL;
3183e327154SLinus Torvalds 	if (!file->f_op->iterate_shared)
3191da177e4SLinus Torvalds 		goto out_close;
3201da177e4SLinus Torvalds 
3211da177e4SLinus Torvalds 	buffer.sequence = 0;
3221da177e4SLinus Torvalds 	while (1) {
3231da177e4SLinus Torvalds 		int old_seq = buffer.sequence;
3241da177e4SLinus Torvalds 
3255c0ba4e0SAl Viro 		error = iterate_dir(file, &buffer.ctx);
32653c9c5c0SAl Viro 		if (buffer.found) {
32753c9c5c0SAl Viro 			error = 0;
32853c9c5c0SAl Viro 			break;
32953c9c5c0SAl Viro 		}
3301da177e4SLinus Torvalds 
3311da177e4SLinus Torvalds 		if (error < 0)
3321da177e4SLinus Torvalds 			break;
3331da177e4SLinus Torvalds 
3341da177e4SLinus Torvalds 		error = -ENOENT;
3351da177e4SLinus Torvalds 		if (old_seq == buffer.sequence)
3361da177e4SLinus Torvalds 			break;
3371da177e4SLinus Torvalds 	}
3381da177e4SLinus Torvalds 
3391da177e4SLinus Torvalds out_close:
3401da177e4SLinus Torvalds 	fput(file);
3411da177e4SLinus Torvalds out:
3421da177e4SLinus Torvalds 	return error;
3431da177e4SLinus Torvalds }
3441da177e4SLinus Torvalds 
3451da177e4SLinus Torvalds /**
3461da177e4SLinus Torvalds  * export_encode_fh - default export_operations->encode_fh function
347b0b0382bSAl Viro  * @inode:   the object to encode
34800f01791SFabian Frederick  * @fid:     where to store the file handle fragment
3491da177e4SLinus Torvalds  * @max_len: maximum length to store there
350b0b0382bSAl Viro  * @parent:  parent directory inode, if wanted
3511da177e4SLinus Torvalds  *
3521da177e4SLinus Torvalds  * This default encode_fh function assumes that the 32 inode number
3531da177e4SLinus Torvalds  * is suitable for locating an inode, and that the generation number
3541da177e4SLinus Torvalds  * can be used to check that it is still valid.  It places them in the
3551da177e4SLinus Torvalds  * filehandle fragment where export_decode_fh expects to find them.
3561da177e4SLinus Torvalds  */
export_encode_fh(struct inode * inode,struct fid * fid,int * max_len,struct inode * parent)357b0b0382bSAl Viro static int export_encode_fh(struct inode *inode, struct fid *fid,
358b0b0382bSAl Viro 		int *max_len, struct inode *parent)
3591da177e4SLinus Torvalds {
3601da177e4SLinus Torvalds 	int len = *max_len;
3616e91ea2bSChristoph Hellwig 	int type = FILEID_INO32_GEN;
3621da177e4SLinus Torvalds 
363b0b0382bSAl Viro 	if (parent && (len < 4)) {
3645fe0c237SAneesh Kumar K.V 		*max_len = 4;
365216b6cbdSNamjae Jeon 		return FILEID_INVALID;
3665fe0c237SAneesh Kumar K.V 	} else if (len < 2) {
3675fe0c237SAneesh Kumar K.V 		*max_len = 2;
368216b6cbdSNamjae Jeon 		return FILEID_INVALID;
3695fe0c237SAneesh Kumar K.V 	}
3701da177e4SLinus Torvalds 
3711da177e4SLinus Torvalds 	len = 2;
3726e91ea2bSChristoph Hellwig 	fid->i32.ino = inode->i_ino;
3736e91ea2bSChristoph Hellwig 	fid->i32.gen = inode->i_generation;
374b0b0382bSAl Viro 	if (parent) {
3756e91ea2bSChristoph Hellwig 		fid->i32.parent_ino = parent->i_ino;
3766e91ea2bSChristoph Hellwig 		fid->i32.parent_gen = parent->i_generation;
3771da177e4SLinus Torvalds 		len = 4;
3786e91ea2bSChristoph Hellwig 		type = FILEID_INO32_GEN_PARENT;
3791da177e4SLinus Torvalds 	}
3801da177e4SLinus Torvalds 	*max_len = len;
3811da177e4SLinus Torvalds 	return type;
3821da177e4SLinus Torvalds }
3831da177e4SLinus Torvalds 
384304e9c83SAmir Goldstein /**
385304e9c83SAmir Goldstein  * exportfs_encode_inode_fh - encode a file handle from inode
386304e9c83SAmir Goldstein  * @inode:   the object to encode
387304e9c83SAmir Goldstein  * @fid:     where to store the file handle fragment
388304e9c83SAmir Goldstein  * @max_len: maximum length to store there
389*7afdc0c9SZhu Wang  * @parent:  parent directory inode, if wanted
390304e9c83SAmir Goldstein  * @flags:   properties of the requested file handle
391304e9c83SAmir Goldstein  *
392304e9c83SAmir Goldstein  * Returns an enum fid_type or a negative errno.
393304e9c83SAmir Goldstein  */
exportfs_encode_inode_fh(struct inode * inode,struct fid * fid,int * max_len,struct inode * parent,int flags)394711c7bf9SCyrill Gorcunov int exportfs_encode_inode_fh(struct inode *inode, struct fid *fid,
395304e9c83SAmir Goldstein 			     int *max_len, struct inode *parent, int flags)
396711c7bf9SCyrill Gorcunov {
397711c7bf9SCyrill Gorcunov 	const struct export_operations *nop = inode->i_sb->s_export_op;
398711c7bf9SCyrill Gorcunov 
399304e9c83SAmir Goldstein 	/*
400304e9c83SAmir Goldstein 	 * If a decodeable file handle was requested, we need to make sure that
401304e9c83SAmir Goldstein 	 * filesystem can decode file handles.
402304e9c83SAmir Goldstein 	 */
403304e9c83SAmir Goldstein 	if (nop && !(flags & EXPORT_FH_FID) && !nop->fh_to_dentry)
404304e9c83SAmir Goldstein 		return -EOPNOTSUPP;
405304e9c83SAmir Goldstein 
406711c7bf9SCyrill Gorcunov 	if (nop && nop->encode_fh)
407711c7bf9SCyrill Gorcunov 		return nop->encode_fh(inode, fid->raw, max_len, parent);
408711c7bf9SCyrill Gorcunov 
409711c7bf9SCyrill Gorcunov 	return export_encode_fh(inode, fid, max_len, parent);
410711c7bf9SCyrill Gorcunov }
411711c7bf9SCyrill Gorcunov EXPORT_SYMBOL_GPL(exportfs_encode_inode_fh);
412711c7bf9SCyrill Gorcunov 
413b5287827SAmir Goldstein /**
414b5287827SAmir Goldstein  * exportfs_encode_fh - encode a file handle from dentry
415b5287827SAmir Goldstein  * @dentry:  the object to encode
416b5287827SAmir Goldstein  * @fid:     where to store the file handle fragment
417b5287827SAmir Goldstein  * @max_len: maximum length to store there
418b5287827SAmir Goldstein  * @flags:   properties of the requested file handle
419b5287827SAmir Goldstein  *
420b5287827SAmir Goldstein  * Returns an enum fid_type or a negative errno.
421b5287827SAmir Goldstein  */
exportfs_encode_fh(struct dentry * dentry,struct fid * fid,int * max_len,int flags)4226e91ea2bSChristoph Hellwig int exportfs_encode_fh(struct dentry *dentry, struct fid *fid, int *max_len,
423b5287827SAmir Goldstein 		       int flags)
424d37065cdSChristoph Hellwig {
42510f11c34SChristoph Hellwig 	int error;
426b0b0382bSAl Viro 	struct dentry *p = NULL;
427b0b0382bSAl Viro 	struct inode *inode = dentry->d_inode, *parent = NULL;
428d37065cdSChristoph Hellwig 
429b5287827SAmir Goldstein 	if ((flags & EXPORT_FH_CONNECTABLE) && !S_ISDIR(inode->i_mode)) {
430b0b0382bSAl Viro 		p = dget_parent(dentry);
431b0b0382bSAl Viro 		/*
432b0b0382bSAl Viro 		 * note that while p might've ceased to be our parent already,
433b0b0382bSAl Viro 		 * it's still pinned by and still positive.
434b0b0382bSAl Viro 		 */
435b0b0382bSAl Viro 		parent = p->d_inode;
436b0b0382bSAl Viro 	}
437711c7bf9SCyrill Gorcunov 
438304e9c83SAmir Goldstein 	error = exportfs_encode_inode_fh(inode, fid, max_len, parent, flags);
439b0b0382bSAl Viro 	dput(p);
44010f11c34SChristoph Hellwig 
44110f11c34SChristoph Hellwig 	return error;
442d37065cdSChristoph Hellwig }
443d37065cdSChristoph Hellwig EXPORT_SYMBOL_GPL(exportfs_encode_fh);
444d37065cdSChristoph Hellwig 
445d045465fSTrond Myklebust struct dentry *
exportfs_decode_fh_raw(struct vfsmount * mnt,struct fid * fid,int fh_len,int fileid_type,int (* acceptable)(void *,struct dentry *),void * context)446d045465fSTrond Myklebust exportfs_decode_fh_raw(struct vfsmount *mnt, struct fid *fid, int fh_len,
447d045465fSTrond Myklebust 		       int fileid_type,
448d045465fSTrond Myklebust 		       int (*acceptable)(void *, struct dentry *),
449d045465fSTrond Myklebust 		       void *context)
450d37065cdSChristoph Hellwig {
45139655164SChristoph Hellwig 	const struct export_operations *nop = mnt->mnt_sb->s_export_op;
4522596110aSChristoph Hellwig 	struct dentry *result, *alias;
453f3f8e175SAl Viro 	char nbuf[NAME_MAX+1];
4542596110aSChristoph Hellwig 	int err;
455d37065cdSChristoph Hellwig 
4562596110aSChristoph Hellwig 	/*
4572596110aSChristoph Hellwig 	 * Try to get any dentry for the given file handle from the filesystem.
4582596110aSChristoph Hellwig 	 */
459becfd1f3SAneesh Kumar K.V 	if (!nop || !nop->fh_to_dentry)
460becfd1f3SAneesh Kumar K.V 		return ERR_PTR(-ESTALE);
4612596110aSChristoph Hellwig 	result = nop->fh_to_dentry(mnt->mnt_sb, fid, fh_len, fileid_type);
46209bb8bffSNeilBrown 	if (IS_ERR_OR_NULL(result))
463d045465fSTrond Myklebust 		return result;
4642596110aSChristoph Hellwig 
4658a22efa1SAmir Goldstein 	/*
4668a22efa1SAmir Goldstein 	 * If no acceptance criteria was specified by caller, a disconnected
4678a22efa1SAmir Goldstein 	 * dentry is also accepatable. Callers may use this mode to query if
4688a22efa1SAmir Goldstein 	 * file handle is stale or to get a reference to an inode without
4698a22efa1SAmir Goldstein 	 * risking the high overhead caused by directory reconnect.
4708a22efa1SAmir Goldstein 	 */
4718a22efa1SAmir Goldstein 	if (!acceptable)
4728a22efa1SAmir Goldstein 		return result;
4738a22efa1SAmir Goldstein 
474e36cb0b8SDavid Howells 	if (d_is_dir(result)) {
4752596110aSChristoph Hellwig 		/*
4762596110aSChristoph Hellwig 		 * This request is for a directory.
4772596110aSChristoph Hellwig 		 *
4782596110aSChristoph Hellwig 		 * On the positive side there is only one dentry for each
4792596110aSChristoph Hellwig 		 * directory inode.  On the negative side this implies that we
4802596110aSChristoph Hellwig 		 * to ensure our dentry is connected all the way up to the
4812596110aSChristoph Hellwig 		 * filesystem root.
4822596110aSChristoph Hellwig 		 */
4832596110aSChristoph Hellwig 		if (result->d_flags & DCACHE_DISCONNECTED) {
484f3f8e175SAl Viro 			err = reconnect_path(mnt, result, nbuf);
4852596110aSChristoph Hellwig 			if (err)
4862596110aSChristoph Hellwig 				goto err_result;
4872596110aSChristoph Hellwig 		}
4882596110aSChristoph Hellwig 
4892596110aSChristoph Hellwig 		if (!acceptable(context, result)) {
4902596110aSChristoph Hellwig 			err = -EACCES;
4912596110aSChristoph Hellwig 			goto err_result;
4922596110aSChristoph Hellwig 		}
49310f11c34SChristoph Hellwig 
49410f11c34SChristoph Hellwig 		return result;
4952596110aSChristoph Hellwig 	} else {
4962596110aSChristoph Hellwig 		/*
4972596110aSChristoph Hellwig 		 * It's not a directory.  Life is a little more complicated.
4982596110aSChristoph Hellwig 		 */
4992596110aSChristoph Hellwig 		struct dentry *target_dir, *nresult;
5002596110aSChristoph Hellwig 
5012596110aSChristoph Hellwig 		/*
5022596110aSChristoph Hellwig 		 * See if either the dentry we just got from the filesystem
5032596110aSChristoph Hellwig 		 * or any alias for it is acceptable.  This is always true
5042596110aSChristoph Hellwig 		 * if this filesystem is exported without the subtreecheck
5052596110aSChristoph Hellwig 		 * option.  If the filesystem is exported with the subtree
5062596110aSChristoph Hellwig 		 * check option there's a fair chance we need to look at
5072596110aSChristoph Hellwig 		 * the parent directory in the file handle and make sure
5082596110aSChristoph Hellwig 		 * it's connected to the filesystem root.
5092596110aSChristoph Hellwig 		 */
5102596110aSChristoph Hellwig 		alias = find_acceptable_alias(result, acceptable, context);
5112596110aSChristoph Hellwig 		if (alias)
5122596110aSChristoph Hellwig 			return alias;
5132596110aSChristoph Hellwig 
5142596110aSChristoph Hellwig 		/*
5152596110aSChristoph Hellwig 		 * Try to extract a dentry for the parent directory from the
5162596110aSChristoph Hellwig 		 * file handle.  If this fails we'll have to give up.
5172596110aSChristoph Hellwig 		 */
5182596110aSChristoph Hellwig 		err = -ESTALE;
5192596110aSChristoph Hellwig 		if (!nop->fh_to_parent)
5202596110aSChristoph Hellwig 			goto err_result;
5212596110aSChristoph Hellwig 
5222596110aSChristoph Hellwig 		target_dir = nop->fh_to_parent(mnt->mnt_sb, fid,
5232596110aSChristoph Hellwig 				fh_len, fileid_type);
524a4f4d6dfSJ. Bruce Fields 		if (!target_dir)
525a4f4d6dfSJ. Bruce Fields 			goto err_result;
5262596110aSChristoph Hellwig 		err = PTR_ERR(target_dir);
5272596110aSChristoph Hellwig 		if (IS_ERR(target_dir))
5282596110aSChristoph Hellwig 			goto err_result;
5292596110aSChristoph Hellwig 
5302596110aSChristoph Hellwig 		/*
5312596110aSChristoph Hellwig 		 * And as usual we need to make sure the parent directory is
5322596110aSChristoph Hellwig 		 * connected to the filesystem root.  The VFS really doesn't
5332596110aSChristoph Hellwig 		 * like disconnected directories..
5342596110aSChristoph Hellwig 		 */
535f3f8e175SAl Viro 		err = reconnect_path(mnt, target_dir, nbuf);
5362596110aSChristoph Hellwig 		if (err) {
5372596110aSChristoph Hellwig 			dput(target_dir);
5382596110aSChristoph Hellwig 			goto err_result;
5392596110aSChristoph Hellwig 		}
5402596110aSChristoph Hellwig 
5412596110aSChristoph Hellwig 		/*
5422596110aSChristoph Hellwig 		 * Now that we've got both a well-connected parent and a
5432596110aSChristoph Hellwig 		 * dentry for the inode we're after, make sure that our
5442596110aSChristoph Hellwig 		 * inode is actually connected to the parent.
5452596110aSChristoph Hellwig 		 */
546e38f9817SChristoph Hellwig 		err = exportfs_get_name(mnt, target_dir, nbuf, result);
547a2ece088SAl Viro 		if (err) {
548a2ece088SAl Viro 			dput(target_dir);
549a2ece088SAl Viro 			goto err_result;
5502596110aSChristoph Hellwig 		}
5512596110aSChristoph Hellwig 
552a2ece088SAl Viro 		inode_lock(target_dir->d_inode);
5534609e1f1SChristian Brauner 		nresult = lookup_one(mnt_idmap(mnt), nbuf,
5543a761d72SChristian Brauner 				     target_dir, strlen(nbuf));
555a2ece088SAl Viro 		if (!IS_ERR(nresult)) {
556a2ece088SAl Viro 			if (unlikely(nresult->d_inode != result->d_inode)) {
557a2ece088SAl Viro 				dput(nresult);
558a2ece088SAl Viro 				nresult = ERR_PTR(-ESTALE);
559a2ece088SAl Viro 			}
560a2ece088SAl Viro 		}
561a2ece088SAl Viro 		inode_unlock(target_dir->d_inode);
5622596110aSChristoph Hellwig 		/*
5632596110aSChristoph Hellwig 		 * At this point we are done with the parent, but it's pinned
5642596110aSChristoph Hellwig 		 * by the child dentry anyway.
5652596110aSChristoph Hellwig 		 */
5662596110aSChristoph Hellwig 		dput(target_dir);
5672596110aSChristoph Hellwig 
568a2ece088SAl Viro 		if (IS_ERR(nresult)) {
569a2ece088SAl Viro 			err = PTR_ERR(nresult);
570a2ece088SAl Viro 			goto err_result;
571a2ece088SAl Viro 		}
572a2ece088SAl Viro 		dput(result);
573a2ece088SAl Viro 		result = nresult;
574a2ece088SAl Viro 
5752596110aSChristoph Hellwig 		/*
5762596110aSChristoph Hellwig 		 * And finally make sure the dentry is actually acceptable
5772596110aSChristoph Hellwig 		 * to NFSD.
5782596110aSChristoph Hellwig 		 */
5792596110aSChristoph Hellwig 		alias = find_acceptable_alias(result, acceptable, context);
5802596110aSChristoph Hellwig 		if (!alias) {
5812596110aSChristoph Hellwig 			err = -EACCES;
5822596110aSChristoph Hellwig 			goto err_result;
5832596110aSChristoph Hellwig 		}
5842596110aSChristoph Hellwig 
5852596110aSChristoph Hellwig 		return alias;
5862596110aSChristoph Hellwig 	}
5872596110aSChristoph Hellwig 
5882596110aSChristoph Hellwig  err_result:
5892596110aSChristoph Hellwig 	dput(result);
5902596110aSChristoph Hellwig 	return ERR_PTR(err);
59110f11c34SChristoph Hellwig }
592d045465fSTrond Myklebust EXPORT_SYMBOL_GPL(exportfs_decode_fh_raw);
593d045465fSTrond Myklebust 
exportfs_decode_fh(struct vfsmount * mnt,struct fid * fid,int fh_len,int fileid_type,int (* acceptable)(void *,struct dentry *),void * context)594d045465fSTrond Myklebust struct dentry *exportfs_decode_fh(struct vfsmount *mnt, struct fid *fid,
595d045465fSTrond Myklebust 				  int fh_len, int fileid_type,
596d045465fSTrond Myklebust 				  int (*acceptable)(void *, struct dentry *),
597d045465fSTrond Myklebust 				  void *context)
598d045465fSTrond Myklebust {
599d045465fSTrond Myklebust 	struct dentry *ret;
600d045465fSTrond Myklebust 
601d045465fSTrond Myklebust 	ret = exportfs_decode_fh_raw(mnt, fid, fh_len, fileid_type,
602d045465fSTrond Myklebust 				     acceptable, context);
603d045465fSTrond Myklebust 	if (IS_ERR_OR_NULL(ret)) {
604d045465fSTrond Myklebust 		if (ret == ERR_PTR(-ENOMEM))
605d045465fSTrond Myklebust 			return ret;
606d045465fSTrond Myklebust 		return ERR_PTR(-ESTALE);
607d045465fSTrond Myklebust 	}
608d045465fSTrond Myklebust 	return ret;
609d045465fSTrond Myklebust }
610d37065cdSChristoph Hellwig EXPORT_SYMBOL_GPL(exportfs_decode_fh);
611d37065cdSChristoph Hellwig 
6121da177e4SLinus Torvalds MODULE_LICENSE("GPL");
613