VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   33 Branches   55 Tags
09c434b8a0047 (Thomas Gleixner       2019-05-19 13:08:20 +0100   1) // SPDX-License-Identifier: GPL-2.0-only
e38f981758118 (Christoph Hellwig     2007-10-21 16:42:19 -0700   2) /*
e38f981758118 (Christoph Hellwig     2007-10-21 16:42:19 -0700   3)  * Copyright (C) Neil Brown 2002
e38f981758118 (Christoph Hellwig     2007-10-21 16:42:19 -0700   4)  * Copyright (C) Christoph Hellwig 2007
e38f981758118 (Christoph Hellwig     2007-10-21 16:42:19 -0700   5)  *
e38f981758118 (Christoph Hellwig     2007-10-21 16:42:19 -0700   6)  * This file contains the code mapping from inodes to NFS file handles,
e38f981758118 (Christoph Hellwig     2007-10-21 16:42:19 -0700   7)  * and for mapping back from file handles to dentries.
e38f981758118 (Christoph Hellwig     2007-10-21 16:42:19 -0700   8)  *
e38f981758118 (Christoph Hellwig     2007-10-21 16:42:19 -0700   9)  * For details on why we do all the strange and hairy things in here
ec23eb54fbc7a (Mauro Carvalho Chehab 2019-07-26 09:51:27 -0300  10)  * take a look at Documentation/filesystems/nfs/exporting.rst.
e38f981758118 (Christoph Hellwig     2007-10-21 16:42:19 -0700  11)  */
a569425512253 (Christoph Hellwig     2007-07-17 04:04:28 -0700  12) #include <linux/exportfs.h>
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700  13) #include <linux/fs.h>
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700  14) #include <linux/file.h>
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700  15) #include <linux/module.h>
d37065cd6d6bb (Christoph Hellwig     2007-07-17 04:04:30 -0700  16) #include <linux/mount.h>
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700  17) #include <linux/namei.h>
745ca2475a6ac (David Howells         2008-11-14 10:39:22 +1100  18) #include <linux/sched.h>
5b825c3af1d8a (Ingo Molnar           2017-02-02 17:54:15 +0100  19) #include <linux/cred.h>
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700  20) 
10f11c341da8c (Christoph Hellwig     2007-07-17 04:04:31 -0700  21) #define dprintk(fmt, args...) do{}while(0)
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700  22) 
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700  23) 
765927b2d5087 (Al Viro               2012-06-26 21:58:53 +0400  24) static int get_name(const struct path *path, char *name, struct dentry *child);
10f11c341da8c (Christoph Hellwig     2007-07-17 04:04:31 -0700  25) 
10f11c341da8c (Christoph Hellwig     2007-07-17 04:04:31 -0700  26) 
e38f981758118 (Christoph Hellwig     2007-10-21 16:42:19 -0700  27) static int exportfs_get_name(struct vfsmount *mnt, struct dentry *dir,
e38f981758118 (Christoph Hellwig     2007-10-21 16:42:19 -0700  28) 		char *name, struct dentry *child)
10f11c341da8c (Christoph Hellwig     2007-07-17 04:04:31 -0700  29) {
3965516440594 (Christoph Hellwig     2007-10-21 16:42:17 -0700  30) 	const struct export_operations *nop = dir->d_sb->s_export_op;
765927b2d5087 (Al Viro               2012-06-26 21:58:53 +0400  31) 	struct path path = {.mnt = mnt, .dentry = dir};
10f11c341da8c (Christoph Hellwig     2007-07-17 04:04:31 -0700  32) 
10f11c341da8c (Christoph Hellwig     2007-07-17 04:04:31 -0700  33) 	if (nop->get_name)
10f11c341da8c (Christoph Hellwig     2007-07-17 04:04:31 -0700  34) 		return nop->get_name(dir, name, child);
10f11c341da8c (Christoph Hellwig     2007-07-17 04:04:31 -0700  35) 	else
765927b2d5087 (Al Viro               2012-06-26 21:58:53 +0400  36) 		return get_name(&path, name, child);
10f11c341da8c (Christoph Hellwig     2007-07-17 04:04:31 -0700  37) }
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700  38) 
fb66a1989c8ab (Christoph Hellwig     2007-07-17 04:04:32 -0700  39) /*
fb66a1989c8ab (Christoph Hellwig     2007-07-17 04:04:32 -0700  40)  * Check if the dentry or any of it's aliases is acceptable.
fb66a1989c8ab (Christoph Hellwig     2007-07-17 04:04:32 -0700  41)  */
e2f99018eb7b2 (Christoph Hellwig     2006-01-18 17:43:52 -0800  42) static struct dentry *
e2f99018eb7b2 (Christoph Hellwig     2006-01-18 17:43:52 -0800  43) find_acceptable_alias(struct dentry *result,
e2f99018eb7b2 (Christoph Hellwig     2006-01-18 17:43:52 -0800  44) 		int (*acceptable)(void *context, struct dentry *dentry),
e2f99018eb7b2 (Christoph Hellwig     2006-01-18 17:43:52 -0800  45) 		void *context)
e2f99018eb7b2 (Christoph Hellwig     2006-01-18 17:43:52 -0800  46) {
e2f99018eb7b2 (Christoph Hellwig     2006-01-18 17:43:52 -0800  47) 	struct dentry *dentry, *toput = NULL;
873feea09ebc9 (Nicholas Piggin       2011-01-07 17:50:06 +1100  48) 	struct inode *inode;
e2f99018eb7b2 (Christoph Hellwig     2006-01-18 17:43:52 -0800  49) 
fb66a1989c8ab (Christoph Hellwig     2007-07-17 04:04:32 -0700  50) 	if (acceptable(context, result))
fb66a1989c8ab (Christoph Hellwig     2007-07-17 04:04:32 -0700  51) 		return result;
fb66a1989c8ab (Christoph Hellwig     2007-07-17 04:04:32 -0700  52) 
873feea09ebc9 (Nicholas Piggin       2011-01-07 17:50:06 +1100  53) 	inode = result->d_inode;
873feea09ebc9 (Nicholas Piggin       2011-01-07 17:50:06 +1100  54) 	spin_lock(&inode->i_lock);
946e51f2bf37f (Al Viro               2014-10-26 19:19:16 -0400  55) 	hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
dc0474be3e274 (Nicholas Piggin       2011-01-07 17:49:43 +1100  56) 		dget(dentry);
873feea09ebc9 (Nicholas Piggin       2011-01-07 17:50:06 +1100  57) 		spin_unlock(&inode->i_lock);
e2f99018eb7b2 (Christoph Hellwig     2006-01-18 17:43:52 -0800  58) 		if (toput)
e2f99018eb7b2 (Christoph Hellwig     2006-01-18 17:43:52 -0800  59) 			dput(toput);
e2f99018eb7b2 (Christoph Hellwig     2006-01-18 17:43:52 -0800  60) 		if (dentry != result && acceptable(context, dentry)) {
e2f99018eb7b2 (Christoph Hellwig     2006-01-18 17:43:52 -0800  61) 			dput(result);
e2f99018eb7b2 (Christoph Hellwig     2006-01-18 17:43:52 -0800  62) 			return dentry;
e2f99018eb7b2 (Christoph Hellwig     2006-01-18 17:43:52 -0800  63) 		}
873feea09ebc9 (Nicholas Piggin       2011-01-07 17:50:06 +1100  64) 		spin_lock(&inode->i_lock);
e2f99018eb7b2 (Christoph Hellwig     2006-01-18 17:43:52 -0800  65) 		toput = dentry;
e2f99018eb7b2 (Christoph Hellwig     2006-01-18 17:43:52 -0800  66) 	}
873feea09ebc9 (Nicholas Piggin       2011-01-07 17:50:06 +1100  67) 	spin_unlock(&inode->i_lock);
e2f99018eb7b2 (Christoph Hellwig     2006-01-18 17:43:52 -0800  68) 
e2f99018eb7b2 (Christoph Hellwig     2006-01-18 17:43:52 -0800  69) 	if (toput)
e2f99018eb7b2 (Christoph Hellwig     2006-01-18 17:43:52 -0800  70) 		dput(toput);
e2f99018eb7b2 (Christoph Hellwig     2006-01-18 17:43:52 -0800  71) 	return NULL;
e2f99018eb7b2 (Christoph Hellwig     2006-01-18 17:43:52 -0800  72) }
e2f99018eb7b2 (Christoph Hellwig     2006-01-18 17:43:52 -0800  73) 
a056cc8934c7b (J. Bruce Fields       2013-10-16 21:09:30 -0400  74) static bool dentry_connected(struct dentry *dentry)
a056cc8934c7b (J. Bruce Fields       2013-10-16 21:09:30 -0400  75) {
a056cc8934c7b (J. Bruce Fields       2013-10-16 21:09:30 -0400  76) 	dget(dentry);
a056cc8934c7b (J. Bruce Fields       2013-10-16 21:09:30 -0400  77) 	while (dentry->d_flags & DCACHE_DISCONNECTED) {
a056cc8934c7b (J. Bruce Fields       2013-10-16 21:09:30 -0400  78) 		struct dentry *parent = dget_parent(dentry);
a056cc8934c7b (J. Bruce Fields       2013-10-16 21:09:30 -0400  79) 
a056cc8934c7b (J. Bruce Fields       2013-10-16 21:09:30 -0400  80) 		dput(dentry);
2084ac6c505a5 (Pan Bian              2018-11-23 15:56:33 +0800  81) 		if (dentry == parent) {
a056cc8934c7b (J. Bruce Fields       2013-10-16 21:09:30 -0400  82) 			dput(parent);
a056cc8934c7b (J. Bruce Fields       2013-10-16 21:09:30 -0400  83) 			return false;
a056cc8934c7b (J. Bruce Fields       2013-10-16 21:09:30 -0400  84) 		}
a056cc8934c7b (J. Bruce Fields       2013-10-16 21:09:30 -0400  85) 		dentry = parent;
a056cc8934c7b (J. Bruce Fields       2013-10-16 21:09:30 -0400  86) 	}
a056cc8934c7b (J. Bruce Fields       2013-10-16 21:09:30 -0400  87) 	dput(dentry);
a056cc8934c7b (J. Bruce Fields       2013-10-16 21:09:30 -0400  88) 	return true;
a056cc8934c7b (J. Bruce Fields       2013-10-16 21:09:30 -0400  89) }
a056cc8934c7b (J. Bruce Fields       2013-10-16 21:09:30 -0400  90) 
0dbc018a490ed (J. Bruce Fields       2013-09-09 16:15:13 -0400  91) static void clear_disconnected(struct dentry *dentry)
0dbc018a490ed (J. Bruce Fields       2013-09-09 16:15:13 -0400  92) {
0dbc018a490ed (J. Bruce Fields       2013-09-09 16:15:13 -0400  93) 	dget(dentry);
0dbc018a490ed (J. Bruce Fields       2013-09-09 16:15:13 -0400  94) 	while (dentry->d_flags & DCACHE_DISCONNECTED) {
0dbc018a490ed (J. Bruce Fields       2013-09-09 16:15:13 -0400  95) 		struct dentry *parent = dget_parent(dentry);
0dbc018a490ed (J. Bruce Fields       2013-09-09 16:15:13 -0400  96) 
0dbc018a490ed (J. Bruce Fields       2013-09-09 16:15:13 -0400  97) 		WARN_ON_ONCE(IS_ROOT(dentry));
0dbc018a490ed (J. Bruce Fields       2013-09-09 16:15:13 -0400  98) 
0dbc018a490ed (J. Bruce Fields       2013-09-09 16:15:13 -0400  99) 		spin_lock(&dentry->d_lock);
0dbc018a490ed (J. Bruce Fields       2013-09-09 16:15:13 -0400 100) 		dentry->d_flags &= ~DCACHE_DISCONNECTED;
0dbc018a490ed (J. Bruce Fields       2013-09-09 16:15:13 -0400 101) 		spin_unlock(&dentry->d_lock);
0dbc018a490ed (J. Bruce Fields       2013-09-09 16:15:13 -0400 102) 
0dbc018a490ed (J. Bruce Fields       2013-09-09 16:15:13 -0400 103) 		dput(dentry);
0dbc018a490ed (J. Bruce Fields       2013-09-09 16:15:13 -0400 104) 		dentry = parent;
0dbc018a490ed (J. Bruce Fields       2013-09-09 16:15:13 -0400 105) 	}
0dbc018a490ed (J. Bruce Fields       2013-09-09 16:15:13 -0400 106) 	dput(dentry);
0dbc018a490ed (J. Bruce Fields       2013-09-09 16:15:13 -0400 107) }
0dbc018a490ed (J. Bruce Fields       2013-09-09 16:15:13 -0400 108) 
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 109) /*
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 110)  * Reconnect a directory dentry with its parent.
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 111)  *
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 112)  * This can return a dentry, or NULL, or an error.
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 113)  *
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 114)  * In the first case the returned dentry is the parent of the given
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 115)  * dentry, and may itself need to be reconnected to its parent.
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 116)  *
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 117)  * In the NULL case, a concurrent VFS operation has either renamed or
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 118)  * removed this directory.  The concurrent operation has reconnected our
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 119)  * dentry, so we no longer need to.
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 120)  */
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 121) static struct dentry *reconnect_one(struct vfsmount *mnt,
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 122) 		struct dentry *dentry, char *nbuf)
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 123) {
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 124) 	struct dentry *parent;
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 125) 	struct dentry *tmp;
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 126) 	int err;
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 127) 
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 128) 	parent = ERR_PTR(-EACCES);
5955102c9984f (Al Viro               2016-01-22 15:40:57 -0500 129) 	inode_lock(dentry->d_inode);
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 130) 	if (mnt->mnt_sb->s_export_op->get_parent)
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 131) 		parent = mnt->mnt_sb->s_export_op->get_parent(dentry);
5955102c9984f (Al Viro               2016-01-22 15:40:57 -0500 132) 	inode_unlock(dentry->d_inode);
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 133) 
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 134) 	if (IS_ERR(parent)) {
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 135) 		dprintk("%s: get_parent of %ld failed, err %d\n",
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 136) 			__func__, dentry->d_inode->i_ino, PTR_ERR(parent));
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 137) 		return parent;
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 138) 	}
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 139) 
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 140) 	dprintk("%s: find name of %lu in %lu\n", __func__,
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 141) 		dentry->d_inode->i_ino, parent->d_inode->i_ino);
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 142) 	err = exportfs_get_name(mnt, parent, nbuf, dentry);
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 143) 	if (err == -ENOENT)
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 144) 		goto out_reconnected;
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 145) 	if (err)
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 146) 		goto out_err;
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 147) 	dprintk("%s: found name: %s\n", __func__, nbuf);
383d4e8ab02c0 (Al Viro               2016-04-14 19:12:42 -0400 148) 	tmp = lookup_one_len_unlocked(nbuf, parent, strlen(nbuf));
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 149) 	if (IS_ERR(tmp)) {
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 150) 		dprintk("%s: lookup failed: %d\n", __func__, PTR_ERR(tmp));
909e22e05353a (YueHaibing            2018-11-19 11:32:41 +0800 151) 		err = PTR_ERR(tmp);
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 152) 		goto out_err;
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 153) 	}
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 154) 	if (tmp != dentry) {
383d4e8ab02c0 (Al Viro               2016-04-14 19:12:42 -0400 155) 		/*
383d4e8ab02c0 (Al Viro               2016-04-14 19:12:42 -0400 156) 		 * Somebody has renamed it since exportfs_get_name();
383d4e8ab02c0 (Al Viro               2016-04-14 19:12:42 -0400 157) 		 * great, since it could've only been renamed if it
383d4e8ab02c0 (Al Viro               2016-04-14 19:12:42 -0400 158) 		 * got looked up and thus connected, and it would
383d4e8ab02c0 (Al Viro               2016-04-14 19:12:42 -0400 159) 		 * remain connected afterwards.  We are done.
383d4e8ab02c0 (Al Viro               2016-04-14 19:12:42 -0400 160) 		 */
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 161) 		dput(tmp);
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 162) 		goto out_reconnected;
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 163) 	}
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 164) 	dput(tmp);
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 165) 	if (IS_ROOT(dentry)) {
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 166) 		err = -ESTALE;
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 167) 		goto out_err;
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 168) 	}
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 169) 	return parent;
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 170) 
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 171) out_err:
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 172) 	dput(parent);
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 173) 	return ERR_PTR(err);
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 174) out_reconnected:
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 175) 	dput(parent);
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 176) 	/*
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 177) 	 * Someone must have renamed our entry into another parent, in
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 178) 	 * which case it has been reconnected by the rename.
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 179) 	 *
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 180) 	 * Or someone removed it entirely, in which case filehandle
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 181) 	 * lookup will succeed but the directory is now IS_DEAD and
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 182) 	 * subsequent operations on it will fail.
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 183) 	 *
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 184) 	 * Alternatively, maybe there was no race at all, and the
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 185) 	 * filesystem is just corrupt and gave us a parent that doesn't
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 186) 	 * actually contain any entry pointing to this inode.  So,
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 187) 	 * double check that this worked and return -ESTALE if not:
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 188) 	 */
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 189) 	if (!dentry_connected(dentry))
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 190) 		return ERR_PTR(-ESTALE);
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 191) 	return NULL;
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 192) }
bbf7a8a3562f2 (J. Bruce Fields       2013-10-17 11:13:00 -0400 193) 
019ab801cf323 (Christoph Hellwig     2007-07-17 04:04:33 -0700 194) /*
019ab801cf323 (Christoph Hellwig     2007-07-17 04:04:33 -0700 195)  * Make sure target_dir is fully connected to the dentry tree.
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 196)  *
78cee9a8e4b42 (J. Bruce Fields       2013-10-22 20:59:19 -0400 197)  * On successful return, DCACHE_DISCONNECTED will be cleared on
78cee9a8e4b42 (J. Bruce Fields       2013-10-22 20:59:19 -0400 198)  * target_dir, and target_dir->d_parent->...->d_parent will reach the
78cee9a8e4b42 (J. Bruce Fields       2013-10-22 20:59:19 -0400 199)  * root of the filesystem.
78cee9a8e4b42 (J. Bruce Fields       2013-10-22 20:59:19 -0400 200)  *
78cee9a8e4b42 (J. Bruce Fields       2013-10-22 20:59:19 -0400 201)  * Whenever DCACHE_DISCONNECTED is unset, target_dir is fully connected.
78cee9a8e4b42 (J. Bruce Fields       2013-10-22 20:59:19 -0400 202)  * But the converse is not true: target_dir may have DCACHE_DISCONNECTED
78cee9a8e4b42 (J. Bruce Fields       2013-10-22 20:59:19 -0400 203)  * set but already be connected.  In that case we'll verify the
78cee9a8e4b42 (J. Bruce Fields       2013-10-22 20:59:19 -0400 204)  * connection to root and then clear the flag.
78cee9a8e4b42 (J. Bruce Fields       2013-10-22 20:59:19 -0400 205)  *
78cee9a8e4b42 (J. Bruce Fields       2013-10-22 20:59:19 -0400 206)  * Note that target_dir could be removed by a concurrent operation.  In
78cee9a8e4b42 (J. Bruce Fields       2013-10-22 20:59:19 -0400 207)  * that case reconnect_path may still succeed with target_dir fully
78cee9a8e4b42 (J. Bruce Fields       2013-10-22 20:59:19 -0400 208)  * connected, but further operations using the filehandle will fail when
78cee9a8e4b42 (J. Bruce Fields       2013-10-22 20:59:19 -0400 209)  * necessary (due to S_DEAD being set on the directory).
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 210)  */
019ab801cf323 (Christoph Hellwig     2007-07-17 04:04:33 -0700 211) static int
f3f8e17571934 (Al Viro               2008-08-11 12:39:47 -0400 212) reconnect_path(struct vfsmount *mnt, struct dentry *target_dir, char *nbuf)
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 213) {
f27c9298fd717 (J. Bruce Fields       2013-10-17 21:34:21 -0400 214) 	struct dentry *dentry, *parent;
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 215) 
f27c9298fd717 (J. Bruce Fields       2013-10-17 21:34:21 -0400 216) 	dentry = dget(target_dir);
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 217) 
f27c9298fd717 (J. Bruce Fields       2013-10-17 21:34:21 -0400 218) 	while (dentry->d_flags & DCACHE_DISCONNECTED) {
efbf201f7a0be (J. Bruce Fields       2013-10-17 21:42:35 -0400 219) 		BUG_ON(dentry == mnt->mnt_sb->s_root);
854ff5caabb59 (Christoph Hellwig     2013-10-16 15:48:53 -0400 220) 
f27c9298fd717 (J. Bruce Fields       2013-10-17 21:34:21 -0400 221) 		if (IS_ROOT(dentry))
f27c9298fd717 (J. Bruce Fields       2013-10-17 21:34:21 -0400 222) 			parent = reconnect_one(mnt, dentry, nbuf);
f27c9298fd717 (J. Bruce Fields       2013-10-17 21:34:21 -0400 223) 		else
f27c9298fd717 (J. Bruce Fields       2013-10-17 21:34:21 -0400 224) 			parent = dget_parent(dentry);
f27c9298fd717 (J. Bruce Fields       2013-10-17 21:34:21 -0400 225) 
f27c9298fd717 (J. Bruce Fields       2013-10-17 21:34:21 -0400 226) 		if (!parent)
0dbc018a490ed (J. Bruce Fields       2013-09-09 16:15:13 -0400 227) 			break;
efbf201f7a0be (J. Bruce Fields       2013-10-17 21:42:35 -0400 228) 		dput(dentry);
f27c9298fd717 (J. Bruce Fields       2013-10-17 21:34:21 -0400 229) 		if (IS_ERR(parent))
f27c9298fd717 (J. Bruce Fields       2013-10-17 21:34:21 -0400 230) 			return PTR_ERR(parent);
f27c9298fd717 (J. Bruce Fields       2013-10-17 21:34:21 -0400 231) 		dentry = parent;
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 232) 	}
f27c9298fd717 (J. Bruce Fields       2013-10-17 21:34:21 -0400 233) 	dput(dentry);
a056cc8934c7b (J. Bruce Fields       2013-10-16 21:09:30 -0400 234) 	clear_disconnected(target_dir);
019ab801cf323 (Christoph Hellwig     2007-07-17 04:04:33 -0700 235) 	return 0;
019ab801cf323 (Christoph Hellwig     2007-07-17 04:04:33 -0700 236) }
019ab801cf323 (Christoph Hellwig     2007-07-17 04:04:33 -0700 237) 
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 238) struct getdents_callback {
5c0ba4e0762e6 (Al Viro               2013-05-15 13:52:59 -0400 239) 	struct dir_context ctx;
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 240) 	char *name;		/* name that was found. It already points to a
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 241) 				   buffer NAME_MAX+1 is size */
950ee9566a5b6 (J. Bruce Fields       2013-09-10 11:41:12 -0400 242) 	u64 ino;		/* the inum we are looking for */
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 243) 	int found;		/* inode matched? */
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 244) 	int sequence;		/* sequence counter */
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 245) };
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 246) 
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 247) /*
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 248)  * A rather strange filldir function to capture
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 249)  * the name matching the specified inode number.
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 250)  */
ac7576f4b1da8 (Miklos Szeredi        2014-10-30 17:37:34 +0100 251) static int filldir_one(struct dir_context *ctx, const char *name, int len,
afefdbb28a0a2 (David Howells         2006-10-03 01:13:46 -0700 252) 			loff_t pos, u64 ino, unsigned int d_type)
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 253) {
ac7576f4b1da8 (Miklos Szeredi        2014-10-30 17:37:34 +0100 254) 	struct getdents_callback *buf =
ac7576f4b1da8 (Miklos Szeredi        2014-10-30 17:37:34 +0100 255) 		container_of(ctx, struct getdents_callback, ctx);
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 256) 	int result = 0;
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 257) 
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 258) 	buf->sequence++;
dfc59e2c90f78 (Al Viro               2013-09-06 16:55:36 -0400 259) 	if (buf->ino == ino && len <= NAME_MAX) {
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 260) 		memcpy(buf->name, name, len);
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 261) 		buf->name[len] = '\0';
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 262) 		buf->found = 1;
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 263) 		result = -1;
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 264) 	}
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 265) 	return result;
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 266) }
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 267) 
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 268) /**
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 269)  * get_name - default export_operations->get_name function
00f01791e159b (Fabian Frederick      2014-06-04 16:11:15 -0700 270)  * @path:   the directory in which to find a name
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 271)  * @name:   a pointer to a %NAME_MAX+1 char buffer to store the name
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 272)  * @child:  the dentry for the child directory.
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 273)  *
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 274)  * calls readdir on the parent until it finds an entry with
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 275)  * the same inode number as the child, and returns that.
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 276)  */
765927b2d5087 (Al Viro               2012-06-26 21:58:53 +0400 277) static int get_name(const struct path *path, char *name, struct dentry *child)
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 278) {
745ca2475a6ac (David Howells         2008-11-14 10:39:22 +1100 279) 	const struct cred *cred = current_cred();
765927b2d5087 (Al Viro               2012-06-26 21:58:53 +0400 280) 	struct inode *dir = path->dentry->d_inode;
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 281) 	int error;
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 282) 	struct file *file;
950ee9566a5b6 (J. Bruce Fields       2013-09-10 11:41:12 -0400 283) 	struct kstat stat;
950ee9566a5b6 (J. Bruce Fields       2013-09-10 11:41:12 -0400 284) 	struct path child_path = {
950ee9566a5b6 (J. Bruce Fields       2013-09-10 11:41:12 -0400 285) 		.mnt = path->mnt,
950ee9566a5b6 (J. Bruce Fields       2013-09-10 11:41:12 -0400 286) 		.dentry = child,
950ee9566a5b6 (J. Bruce Fields       2013-09-10 11:41:12 -0400 287) 	};
ac6614b76478e (Al Viro               2013-05-22 22:22:04 -0400 288) 	struct getdents_callback buffer = {
ac6614b76478e (Al Viro               2013-05-22 22:22:04 -0400 289) 		.ctx.actor = filldir_one,
ac6614b76478e (Al Viro               2013-05-22 22:22:04 -0400 290) 		.name = name,
ac6614b76478e (Al Viro               2013-05-22 22:22:04 -0400 291) 	};
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 292) 
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 293) 	error = -ENOTDIR;
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 294) 	if (!dir || !S_ISDIR(dir->i_mode))
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 295) 		goto out;
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 296) 	error = -EINVAL;
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 297) 	if (!dir->i_fop)
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 298) 		goto out;
950ee9566a5b6 (J. Bruce Fields       2013-09-10 11:41:12 -0400 299) 	/*
950ee9566a5b6 (J. Bruce Fields       2013-09-10 11:41:12 -0400 300) 	 * inode->i_ino is unsigned long, kstat->ino is u64, so the
950ee9566a5b6 (J. Bruce Fields       2013-09-10 11:41:12 -0400 301) 	 * former would be insufficient on 32-bit hosts when the
950ee9566a5b6 (J. Bruce Fields       2013-09-10 11:41:12 -0400 302) 	 * filesystem supports 64-bit inode numbers.  So we need to
950ee9566a5b6 (J. Bruce Fields       2013-09-10 11:41:12 -0400 303) 	 * actually call ->getattr, not just read i_ino:
950ee9566a5b6 (J. Bruce Fields       2013-09-10 11:41:12 -0400 304) 	 */
a528d35e8bfcc (David Howells         2017-01-31 16:46:22 +0000 305) 	error = vfs_getattr_nosec(&child_path, &stat,
a528d35e8bfcc (David Howells         2017-01-31 16:46:22 +0000 306) 				  STATX_INO, AT_STATX_SYNC_AS_STAT);
950ee9566a5b6 (J. Bruce Fields       2013-09-10 11:41:12 -0400 307) 	if (error)
950ee9566a5b6 (J. Bruce Fields       2013-09-10 11:41:12 -0400 308) 		return error;
950ee9566a5b6 (J. Bruce Fields       2013-09-10 11:41:12 -0400 309) 	buffer.ino = stat.ino;
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 310) 	/*
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 311) 	 * Open the directory ...
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 312) 	 */
765927b2d5087 (Al Viro               2012-06-26 21:58:53 +0400 313) 	file = dentry_open(path, O_RDONLY, cred);
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 314) 	error = PTR_ERR(file);
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 315) 	if (IS_ERR(file))
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 316) 		goto out;
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 317) 
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 318) 	error = -EINVAL;
6192269444ebf (Al Viro               2016-04-20 23:08:32 -0400 319) 	if (!file->f_op->iterate && !file->f_op->iterate_shared)
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 320) 		goto out_close;
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 321) 
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 322) 	buffer.sequence = 0;
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 323) 	while (1) {
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 324) 		int old_seq = buffer.sequence;
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 325) 
5c0ba4e0762e6 (Al Viro               2013-05-15 13:52:59 -0400 326) 		error = iterate_dir(file, &buffer.ctx);
53c9c5c0e32c6 (Al Viro               2008-08-24 07:29:52 -0400 327) 		if (buffer.found) {
53c9c5c0e32c6 (Al Viro               2008-08-24 07:29:52 -0400 328) 			error = 0;
53c9c5c0e32c6 (Al Viro               2008-08-24 07:29:52 -0400 329) 			break;
53c9c5c0e32c6 (Al Viro               2008-08-24 07:29:52 -0400 330) 		}
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 331) 
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 332) 		if (error < 0)
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 333) 			break;
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 334) 
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 335) 		error = -ENOENT;
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 336) 		if (old_seq == buffer.sequence)
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 337) 			break;
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 338) 	}
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 339) 
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 340) out_close:
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 341) 	fput(file);
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 342) out:
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 343) 	return error;
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 344) }
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 345) 
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 346) /**
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 347)  * export_encode_fh - default export_operations->encode_fh function
b0b0382bb4904 (Al Viro               2012-04-02 14:34:06 -0400 348)  * @inode:   the object to encode
00f01791e159b (Fabian Frederick      2014-06-04 16:11:15 -0700 349)  * @fid:     where to store the file handle fragment
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 350)  * @max_len: maximum length to store there
b0b0382bb4904 (Al Viro               2012-04-02 14:34:06 -0400 351)  * @parent:  parent directory inode, if wanted
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 352)  *
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 353)  * This default encode_fh function assumes that the 32 inode number
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 354)  * is suitable for locating an inode, and that the generation number
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 355)  * can be used to check that it is still valid.  It places them in the
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 356)  * filehandle fragment where export_decode_fh expects to find them.
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 357)  */
b0b0382bb4904 (Al Viro               2012-04-02 14:34:06 -0400 358) static int export_encode_fh(struct inode *inode, struct fid *fid,
b0b0382bb4904 (Al Viro               2012-04-02 14:34:06 -0400 359) 		int *max_len, struct inode *parent)
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 360) {
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 361) 	int len = *max_len;
6e91ea2bb0b6a (Christoph Hellwig     2007-10-21 16:42:03 -0700 362) 	int type = FILEID_INO32_GEN;
5fe0c2378884e (Aneesh Kumar K.V      2011-01-29 18:43:25 +0530 363) 
b0b0382bb4904 (Al Viro               2012-04-02 14:34:06 -0400 364) 	if (parent && (len < 4)) {
5fe0c2378884e (Aneesh Kumar K.V      2011-01-29 18:43:25 +0530 365) 		*max_len = 4;
216b6cbdcbd86 (Namjae Jeon           2012-08-29 10:10:10 -0400 366) 		return FILEID_INVALID;
5fe0c2378884e (Aneesh Kumar K.V      2011-01-29 18:43:25 +0530 367) 	} else if (len < 2) {
5fe0c2378884e (Aneesh Kumar K.V      2011-01-29 18:43:25 +0530 368) 		*max_len = 2;
216b6cbdcbd86 (Namjae Jeon           2012-08-29 10:10:10 -0400 369) 		return FILEID_INVALID;
5fe0c2378884e (Aneesh Kumar K.V      2011-01-29 18:43:25 +0530 370) 	}
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 371) 
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 372) 	len = 2;
6e91ea2bb0b6a (Christoph Hellwig     2007-10-21 16:42:03 -0700 373) 	fid->i32.ino = inode->i_ino;
6e91ea2bb0b6a (Christoph Hellwig     2007-10-21 16:42:03 -0700 374) 	fid->i32.gen = inode->i_generation;
b0b0382bb4904 (Al Viro               2012-04-02 14:34:06 -0400 375) 	if (parent) {
6e91ea2bb0b6a (Christoph Hellwig     2007-10-21 16:42:03 -0700 376) 		fid->i32.parent_ino = parent->i_ino;
6e91ea2bb0b6a (Christoph Hellwig     2007-10-21 16:42:03 -0700 377) 		fid->i32.parent_gen = parent->i_generation;
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 378) 		len = 4;
6e91ea2bb0b6a (Christoph Hellwig     2007-10-21 16:42:03 -0700 379) 		type = FILEID_INO32_GEN_PARENT;
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 380) 	}
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 381) 	*max_len = len;
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 382) 	return type;
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 383) }
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 384) 
711c7bf991406 (Cyrill Gorcunov       2012-12-17 16:05:08 -0800 385) int exportfs_encode_inode_fh(struct inode *inode, struct fid *fid,
711c7bf991406 (Cyrill Gorcunov       2012-12-17 16:05:08 -0800 386) 			     int *max_len, struct inode *parent)
711c7bf991406 (Cyrill Gorcunov       2012-12-17 16:05:08 -0800 387) {
711c7bf991406 (Cyrill Gorcunov       2012-12-17 16:05:08 -0800 388) 	const struct export_operations *nop = inode->i_sb->s_export_op;
711c7bf991406 (Cyrill Gorcunov       2012-12-17 16:05:08 -0800 389) 
711c7bf991406 (Cyrill Gorcunov       2012-12-17 16:05:08 -0800 390) 	if (nop && nop->encode_fh)
711c7bf991406 (Cyrill Gorcunov       2012-12-17 16:05:08 -0800 391) 		return nop->encode_fh(inode, fid->raw, max_len, parent);
711c7bf991406 (Cyrill Gorcunov       2012-12-17 16:05:08 -0800 392) 
711c7bf991406 (Cyrill Gorcunov       2012-12-17 16:05:08 -0800 393) 	return export_encode_fh(inode, fid, max_len, parent);
711c7bf991406 (Cyrill Gorcunov       2012-12-17 16:05:08 -0800 394) }
711c7bf991406 (Cyrill Gorcunov       2012-12-17 16:05:08 -0800 395) EXPORT_SYMBOL_GPL(exportfs_encode_inode_fh);
711c7bf991406 (Cyrill Gorcunov       2012-12-17 16:05:08 -0800 396) 
6e91ea2bb0b6a (Christoph Hellwig     2007-10-21 16:42:03 -0700 397) int exportfs_encode_fh(struct dentry *dentry, struct fid *fid, int *max_len,
d37065cd6d6bb (Christoph Hellwig     2007-07-17 04:04:30 -0700 398) 		int connectable)
d37065cd6d6bb (Christoph Hellwig     2007-07-17 04:04:30 -0700 399) {
10f11c341da8c (Christoph Hellwig     2007-07-17 04:04:31 -0700 400) 	int error;
b0b0382bb4904 (Al Viro               2012-04-02 14:34:06 -0400 401) 	struct dentry *p = NULL;
b0b0382bb4904 (Al Viro               2012-04-02 14:34:06 -0400 402) 	struct inode *inode = dentry->d_inode, *parent = NULL;
d37065cd6d6bb (Christoph Hellwig     2007-07-17 04:04:30 -0700 403) 
b0b0382bb4904 (Al Viro               2012-04-02 14:34:06 -0400 404) 	if (connectable && !S_ISDIR(inode->i_mode)) {
b0b0382bb4904 (Al Viro               2012-04-02 14:34:06 -0400 405) 		p = dget_parent(dentry);
b0b0382bb4904 (Al Viro               2012-04-02 14:34:06 -0400 406) 		/*
b0b0382bb4904 (Al Viro               2012-04-02 14:34:06 -0400 407) 		 * note that while p might've ceased to be our parent already,
b0b0382bb4904 (Al Viro               2012-04-02 14:34:06 -0400 408) 		 * it's still pinned by and still positive.
b0b0382bb4904 (Al Viro               2012-04-02 14:34:06 -0400 409) 		 */
b0b0382bb4904 (Al Viro               2012-04-02 14:34:06 -0400 410) 		parent = p->d_inode;
b0b0382bb4904 (Al Viro               2012-04-02 14:34:06 -0400 411) 	}
711c7bf991406 (Cyrill Gorcunov       2012-12-17 16:05:08 -0800 412) 
711c7bf991406 (Cyrill Gorcunov       2012-12-17 16:05:08 -0800 413) 	error = exportfs_encode_inode_fh(inode, fid, max_len, parent);
b0b0382bb4904 (Al Viro               2012-04-02 14:34:06 -0400 414) 	dput(p);
10f11c341da8c (Christoph Hellwig     2007-07-17 04:04:31 -0700 415) 
10f11c341da8c (Christoph Hellwig     2007-07-17 04:04:31 -0700 416) 	return error;
d37065cd6d6bb (Christoph Hellwig     2007-07-17 04:04:30 -0700 417) }
d37065cd6d6bb (Christoph Hellwig     2007-07-17 04:04:30 -0700 418) EXPORT_SYMBOL_GPL(exportfs_encode_fh);
d37065cd6d6bb (Christoph Hellwig     2007-07-17 04:04:30 -0700 419) 
d045465fc6cbf (Trond Myklebust       2020-11-30 17:03:17 -0500 420) struct dentry *
d045465fc6cbf (Trond Myklebust       2020-11-30 17:03:17 -0500 421) exportfs_decode_fh_raw(struct vfsmount *mnt, struct fid *fid, int fh_len,
d045465fc6cbf (Trond Myklebust       2020-11-30 17:03:17 -0500 422) 		       int fileid_type,
d045465fc6cbf (Trond Myklebust       2020-11-30 17:03:17 -0500 423) 		       int (*acceptable)(void *, struct dentry *),
d045465fc6cbf (Trond Myklebust       2020-11-30 17:03:17 -0500 424) 		       void *context)
d37065cd6d6bb (Christoph Hellwig     2007-07-17 04:04:30 -0700 425) {
3965516440594 (Christoph Hellwig     2007-10-21 16:42:17 -0700 426) 	const struct export_operations *nop = mnt->mnt_sb->s_export_op;
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 427) 	struct dentry *result, *alias;
f3f8e17571934 (Al Viro               2008-08-11 12:39:47 -0400 428) 	char nbuf[NAME_MAX+1];
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 429) 	int err;
d37065cd6d6bb (Christoph Hellwig     2007-07-17 04:04:30 -0700 430) 
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 431) 	/*
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 432) 	 * Try to get any dentry for the given file handle from the filesystem.
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 433) 	 */
becfd1f375447 (Aneesh Kumar K.V      2011-01-29 18:43:26 +0530 434) 	if (!nop || !nop->fh_to_dentry)
becfd1f375447 (Aneesh Kumar K.V      2011-01-29 18:43:26 +0530 435) 		return ERR_PTR(-ESTALE);
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 436) 	result = nop->fh_to_dentry(mnt->mnt_sb, fid, fh_len, fileid_type);
09bb8bfffd29c (NeilBrown             2016-08-04 10:19:06 +1000 437) 	if (IS_ERR_OR_NULL(result))
d045465fc6cbf (Trond Myklebust       2020-11-30 17:03:17 -0500 438) 		return result;
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 439) 
8a22efa15b46d (Amir Goldstein        2018-03-09 15:51:02 +0200 440) 	/*
8a22efa15b46d (Amir Goldstein        2018-03-09 15:51:02 +0200 441) 	 * If no acceptance criteria was specified by caller, a disconnected
8a22efa15b46d (Amir Goldstein        2018-03-09 15:51:02 +0200 442) 	 * dentry is also accepatable. Callers may use this mode to query if
8a22efa15b46d (Amir Goldstein        2018-03-09 15:51:02 +0200 443) 	 * file handle is stale or to get a reference to an inode without
8a22efa15b46d (Amir Goldstein        2018-03-09 15:51:02 +0200 444) 	 * risking the high overhead caused by directory reconnect.
8a22efa15b46d (Amir Goldstein        2018-03-09 15:51:02 +0200 445) 	 */
8a22efa15b46d (Amir Goldstein        2018-03-09 15:51:02 +0200 446) 	if (!acceptable)
8a22efa15b46d (Amir Goldstein        2018-03-09 15:51:02 +0200 447) 		return result;
8a22efa15b46d (Amir Goldstein        2018-03-09 15:51:02 +0200 448) 
e36cb0b89ce20 (David Howells         2015-01-29 12:02:35 +0000 449) 	if (d_is_dir(result)) {
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 450) 		/*
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 451) 		 * This request is for a directory.
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 452) 		 *
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 453) 		 * On the positive side there is only one dentry for each
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 454) 		 * directory inode.  On the negative side this implies that we
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 455) 		 * to ensure our dentry is connected all the way up to the
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 456) 		 * filesystem root.
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 457) 		 */
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 458) 		if (result->d_flags & DCACHE_DISCONNECTED) {
f3f8e17571934 (Al Viro               2008-08-11 12:39:47 -0400 459) 			err = reconnect_path(mnt, result, nbuf);
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 460) 			if (err)
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 461) 				goto err_result;
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 462) 		}
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 463) 
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 464) 		if (!acceptable(context, result)) {
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 465) 			err = -EACCES;
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 466) 			goto err_result;
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 467) 		}
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 468) 
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 469) 		return result;
10f11c341da8c (Christoph Hellwig     2007-07-17 04:04:31 -0700 470) 	} else {
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 471) 		/*
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 472) 		 * It's not a directory.  Life is a little more complicated.
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 473) 		 */
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 474) 		struct dentry *target_dir, *nresult;
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 475) 
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 476) 		/*
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 477) 		 * See if either the dentry we just got from the filesystem
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 478) 		 * or any alias for it is acceptable.  This is always true
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 479) 		 * if this filesystem is exported without the subtreecheck
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 480) 		 * option.  If the filesystem is exported with the subtree
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 481) 		 * check option there's a fair chance we need to look at
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 482) 		 * the parent directory in the file handle and make sure
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 483) 		 * it's connected to the filesystem root.
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 484) 		 */
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 485) 		alias = find_acceptable_alias(result, acceptable, context);
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 486) 		if (alias)
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 487) 			return alias;
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 488) 
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 489) 		/*
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 490) 		 * Try to extract a dentry for the parent directory from the
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 491) 		 * file handle.  If this fails we'll have to give up.
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 492) 		 */
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 493) 		err = -ESTALE;
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 494) 		if (!nop->fh_to_parent)
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 495) 			goto err_result;
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 496) 
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 497) 		target_dir = nop->fh_to_parent(mnt->mnt_sb, fid,
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 498) 				fh_len, fileid_type);
a4f4d6df53736 (J. Bruce Fields       2008-12-08 18:24:18 -0500 499) 		if (!target_dir)
a4f4d6df53736 (J. Bruce Fields       2008-12-08 18:24:18 -0500 500) 			goto err_result;
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 501) 		err = PTR_ERR(target_dir);
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 502) 		if (IS_ERR(target_dir))
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 503) 			goto err_result;
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 504) 
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 505) 		/*
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 506) 		 * And as usual we need to make sure the parent directory is
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 507) 		 * connected to the filesystem root.  The VFS really doesn't
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 508) 		 * like disconnected directories..
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 509) 		 */
f3f8e17571934 (Al Viro               2008-08-11 12:39:47 -0400 510) 		err = reconnect_path(mnt, target_dir, nbuf);
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 511) 		if (err) {
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 512) 			dput(target_dir);
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 513) 			goto err_result;
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 514) 		}
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 515) 
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 516) 		/*
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 517) 		 * Now that we've got both a well-connected parent and a
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 518) 		 * dentry for the inode we're after, make sure that our
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 519) 		 * inode is actually connected to the parent.
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 520) 		 */
e38f981758118 (Christoph Hellwig     2007-10-21 16:42:19 -0700 521) 		err = exportfs_get_name(mnt, target_dir, nbuf, result);
a2ece08888266 (Al Viro               2019-11-08 22:08:29 -0500 522) 		if (err) {
a2ece08888266 (Al Viro               2019-11-08 22:08:29 -0500 523) 			dput(target_dir);
a2ece08888266 (Al Viro               2019-11-08 22:08:29 -0500 524) 			goto err_result;
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 525) 		}
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 526) 
a2ece08888266 (Al Viro               2019-11-08 22:08:29 -0500 527) 		inode_lock(target_dir->d_inode);
a2ece08888266 (Al Viro               2019-11-08 22:08:29 -0500 528) 		nresult = lookup_one_len(nbuf, target_dir, strlen(nbuf));
a2ece08888266 (Al Viro               2019-11-08 22:08:29 -0500 529) 		if (!IS_ERR(nresult)) {
a2ece08888266 (Al Viro               2019-11-08 22:08:29 -0500 530) 			if (unlikely(nresult->d_inode != result->d_inode)) {
a2ece08888266 (Al Viro               2019-11-08 22:08:29 -0500 531) 				dput(nresult);
a2ece08888266 (Al Viro               2019-11-08 22:08:29 -0500 532) 				nresult = ERR_PTR(-ESTALE);
a2ece08888266 (Al Viro               2019-11-08 22:08:29 -0500 533) 			}
a2ece08888266 (Al Viro               2019-11-08 22:08:29 -0500 534) 		}
a2ece08888266 (Al Viro               2019-11-08 22:08:29 -0500 535) 		inode_unlock(target_dir->d_inode);
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 536) 		/*
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 537) 		 * At this point we are done with the parent, but it's pinned
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 538) 		 * by the child dentry anyway.
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 539) 		 */
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 540) 		dput(target_dir);
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 541) 
a2ece08888266 (Al Viro               2019-11-08 22:08:29 -0500 542) 		if (IS_ERR(nresult)) {
a2ece08888266 (Al Viro               2019-11-08 22:08:29 -0500 543) 			err = PTR_ERR(nresult);
a2ece08888266 (Al Viro               2019-11-08 22:08:29 -0500 544) 			goto err_result;
a2ece08888266 (Al Viro               2019-11-08 22:08:29 -0500 545) 		}
a2ece08888266 (Al Viro               2019-11-08 22:08:29 -0500 546) 		dput(result);
a2ece08888266 (Al Viro               2019-11-08 22:08:29 -0500 547) 		result = nresult;
a2ece08888266 (Al Viro               2019-11-08 22:08:29 -0500 548) 
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 549) 		/*
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 550) 		 * And finally make sure the dentry is actually acceptable
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 551) 		 * to NFSD.
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 552) 		 */
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 553) 		alias = find_acceptable_alias(result, acceptable, context);
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 554) 		if (!alias) {
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 555) 			err = -EACCES;
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 556) 			goto err_result;
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 557) 		}
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 558) 
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 559) 		return alias;
10f11c341da8c (Christoph Hellwig     2007-07-17 04:04:31 -0700 560) 	}
10f11c341da8c (Christoph Hellwig     2007-07-17 04:04:31 -0700 561) 
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 562)  err_result:
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 563) 	dput(result);
2596110a39945 (Christoph Hellwig     2007-10-21 16:42:05 -0700 564) 	return ERR_PTR(err);
d37065cd6d6bb (Christoph Hellwig     2007-07-17 04:04:30 -0700 565) }
d045465fc6cbf (Trond Myklebust       2020-11-30 17:03:17 -0500 566) EXPORT_SYMBOL_GPL(exportfs_decode_fh_raw);
d045465fc6cbf (Trond Myklebust       2020-11-30 17:03:17 -0500 567) 
d045465fc6cbf (Trond Myklebust       2020-11-30 17:03:17 -0500 568) struct dentry *exportfs_decode_fh(struct vfsmount *mnt, struct fid *fid,
d045465fc6cbf (Trond Myklebust       2020-11-30 17:03:17 -0500 569) 				  int fh_len, int fileid_type,
d045465fc6cbf (Trond Myklebust       2020-11-30 17:03:17 -0500 570) 				  int (*acceptable)(void *, struct dentry *),
d045465fc6cbf (Trond Myklebust       2020-11-30 17:03:17 -0500 571) 				  void *context)
d045465fc6cbf (Trond Myklebust       2020-11-30 17:03:17 -0500 572) {
d045465fc6cbf (Trond Myklebust       2020-11-30 17:03:17 -0500 573) 	struct dentry *ret;
d045465fc6cbf (Trond Myklebust       2020-11-30 17:03:17 -0500 574) 
d045465fc6cbf (Trond Myklebust       2020-11-30 17:03:17 -0500 575) 	ret = exportfs_decode_fh_raw(mnt, fid, fh_len, fileid_type,
d045465fc6cbf (Trond Myklebust       2020-11-30 17:03:17 -0500 576) 				     acceptable, context);
d045465fc6cbf (Trond Myklebust       2020-11-30 17:03:17 -0500 577) 	if (IS_ERR_OR_NULL(ret)) {
d045465fc6cbf (Trond Myklebust       2020-11-30 17:03:17 -0500 578) 		if (ret == ERR_PTR(-ENOMEM))
d045465fc6cbf (Trond Myklebust       2020-11-30 17:03:17 -0500 579) 			return ret;
d045465fc6cbf (Trond Myklebust       2020-11-30 17:03:17 -0500 580) 		return ERR_PTR(-ESTALE);
d045465fc6cbf (Trond Myklebust       2020-11-30 17:03:17 -0500 581) 	}
d045465fc6cbf (Trond Myklebust       2020-11-30 17:03:17 -0500 582) 	return ret;
d045465fc6cbf (Trond Myklebust       2020-11-30 17:03:17 -0500 583) }
d37065cd6d6bb (Christoph Hellwig     2007-07-17 04:04:30 -0700 584) EXPORT_SYMBOL_GPL(exportfs_decode_fh);
d37065cd6d6bb (Christoph Hellwig     2007-07-17 04:04:30 -0700 585) 
^1da177e4c3f4 (Linus Torvalds        2005-04-16 15:20:36 -0700 586) MODULE_LICENSE("GPL");