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