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");