~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/nfs/getroot.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /fs/nfs/getroot.c (Version linux-6.11.5) and /fs/nfs/getroot.c (Version linux-2.6.32.71)


  1 // SPDX-License-Identifier: GPL-2.0-or-later   << 
  2 /* getroot.c: get the root dentry for an NFS m      1 /* getroot.c: get the root dentry for an NFS mount
  3  *                                                  2  *
  4  * Copyright (C) 2006 Red Hat, Inc. All Rights      3  * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
  5  * Written by David Howells (dhowells@redhat.c      4  * Written by David Howells (dhowells@redhat.com)
                                                   >>   5  *
                                                   >>   6  * This program is free software; you can redistribute it and/or
                                                   >>   7  * modify it under the terms of the GNU General Public License
                                                   >>   8  * as published by the Free Software Foundation; either version
                                                   >>   9  * 2 of the License, or (at your option) any later version.
  6  */                                                10  */
  7                                                    11 
  8 #include <linux/module.h>                          12 #include <linux/module.h>
  9 #include <linux/init.h>                            13 #include <linux/init.h>
 10                                                    14 
 11 #include <linux/time.h>                            15 #include <linux/time.h>
 12 #include <linux/kernel.h>                          16 #include <linux/kernel.h>
 13 #include <linux/mm.h>                              17 #include <linux/mm.h>
 14 #include <linux/string.h>                          18 #include <linux/string.h>
 15 #include <linux/stat.h>                            19 #include <linux/stat.h>
 16 #include <linux/errno.h>                           20 #include <linux/errno.h>
 17 #include <linux/unistd.h>                          21 #include <linux/unistd.h>
 18 #include <linux/sunrpc/clnt.h>                     22 #include <linux/sunrpc/clnt.h>
 19 #include <linux/sunrpc/stats.h>                    23 #include <linux/sunrpc/stats.h>
 20 #include <linux/nfs_fs.h>                          24 #include <linux/nfs_fs.h>
 21 #include <linux/nfs_mount.h>                       25 #include <linux/nfs_mount.h>
                                                   >>  26 #include <linux/nfs4_mount.h>
 22 #include <linux/lockd/bind.h>                      27 #include <linux/lockd/bind.h>
 23 #include <linux/seq_file.h>                        28 #include <linux/seq_file.h>
 24 #include <linux/mount.h>                           29 #include <linux/mount.h>
                                                   >>  30 #include <linux/nfs_idmap.h>
 25 #include <linux/vfs.h>                             31 #include <linux/vfs.h>
 26 #include <linux/namei.h>                           32 #include <linux/namei.h>
 27 #include <linux/security.h>                        33 #include <linux/security.h>
 28                                                    34 
 29 #include <linux/uaccess.h>                     !!  35 #include <asm/system.h>
                                                   >>  36 #include <asm/uaccess.h>
 30                                                    37 
                                                   >>  38 #include "nfs4_fs.h"
                                                   >>  39 #include "delegation.h"
 31 #include "internal.h"                              40 #include "internal.h"
 32                                                    41 
 33 #define NFSDBG_FACILITY         NFSDBG_CLIENT      42 #define NFSDBG_FACILITY         NFSDBG_CLIENT
 34                                                    43 
 35 /*                                                 44 /*
 36  * Set the superblock root dentry.                 45  * Set the superblock root dentry.
 37  * Note that this function frees the inode in      46  * Note that this function frees the inode in case of error.
 38  */                                                47  */
 39 static int nfs_superblock_set_dummy_root(struc     48 static int nfs_superblock_set_dummy_root(struct super_block *sb, struct inode *inode)
 40 {                                                  49 {
 41         /* The mntroot acts as the dummy root      50         /* The mntroot acts as the dummy root dentry for this superblock */
 42         if (sb->s_root == NULL) {                  51         if (sb->s_root == NULL) {
 43                 sb->s_root = d_make_root(inode !!  52                 sb->s_root = d_alloc_root(inode);
 44                 if (sb->s_root == NULL)        !!  53                 if (sb->s_root == NULL) {
                                                   >>  54                         iput(inode);
 45                         return -ENOMEM;            55                         return -ENOMEM;
 46                 ihold(inode);                  !!  56                 }
                                                   >>  57                 /* Circumvent igrab(): we know the inode is not being freed */
                                                   >>  58                 atomic_inc(&inode->i_count);
 47                 /*                                 59                 /*
 48                  * Ensure that this dentry is      60                  * Ensure that this dentry is invisible to d_find_alias().
 49                  * Otherwise, it may be splice     61                  * Otherwise, it may be spliced into the tree by
 50                  * d_splice_alias if a parent  !!  62                  * d_materialise_unique if a parent directory from the same
 51                  * filesystem gets mounted at      63                  * filesystem gets mounted at a later time.
 52                  * This again causes shrink_dc     64                  * This again causes shrink_dcache_for_umount_subtree() to
 53                  * Oops, since the test for IS     65                  * Oops, since the test for IS_ROOT() will fail.
 54                  */                                66                  */
 55                 spin_lock(&d_inode(sb->s_root) !!  67                 spin_lock(&dcache_lock);
 56                 spin_lock(&sb->s_root->d_lock) !!  68                 list_del_init(&sb->s_root->d_alias);
 57                 hlist_del_init(&sb->s_root->d_ !!  69                 spin_unlock(&dcache_lock);
 58                 spin_unlock(&sb->s_root->d_loc << 
 59                 spin_unlock(&d_inode(sb->s_roo << 
 60         }                                          70         }
 61         return 0;                                  71         return 0;
 62 }                                                  72 }
 63                                                    73 
 64 /*                                                 74 /*
 65  * get an NFS2/NFS3 root dentry from the root      75  * get an NFS2/NFS3 root dentry from the root filehandle
 66  */                                                76  */
 67 int nfs_get_root(struct super_block *s, struct !!  77 struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh)
 68 {                                                  78 {
 69         struct nfs_fs_context *ctx = nfs_fc2co !!  79         struct nfs_server *server = NFS_SB(sb);
 70         struct nfs_server *server = NFS_SB(s), << 
 71         struct nfs_fsinfo fsinfo;                  80         struct nfs_fsinfo fsinfo;
 72         struct dentry *root;                   !!  81         struct nfs_fattr fattr;
                                                   >>  82         struct dentry *mntroot;
 73         struct inode *inode;                       83         struct inode *inode;
 74         char *name;                            !!  84         int error;
 75         int error = -ENOMEM;                   << 
 76         unsigned long kflags = 0, kflags_out = << 
 77                                                << 
 78         name = kstrdup(fc->source, GFP_KERNEL) << 
 79         if (!name)                             << 
 80                 goto out;                      << 
 81                                                    85 
 82         /* get the actual root for this mount      86         /* get the actual root for this mount */
 83         fsinfo.fattr = nfs_alloc_fattr_with_la !!  87         fsinfo.fattr = &fattr;
 84         if (fsinfo.fattr == NULL)              << 
 85                 goto out_name;                 << 
 86                                                    88 
 87         error = server->nfs_client->rpc_ops->g !!  89         error = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo);
 88         if (error < 0) {                           90         if (error < 0) {
 89                 dprintk("nfs_get_root: getattr     91                 dprintk("nfs_get_root: getattr error = %d\n", -error);
 90                 nfs_errorf(fc, "NFS: Couldn't  !!  92                 return ERR_PTR(error);
 91                 goto out_fattr;                << 
 92         }                                          93         }
 93                                                    94 
 94         inode = nfs_fhget(s, ctx->mntfh, fsinf !!  95         inode = nfs_fhget(sb, mntfh, fsinfo.fattr);
 95         if (IS_ERR(inode)) {                       96         if (IS_ERR(inode)) {
 96                 dprintk("nfs_get_root: get roo     97                 dprintk("nfs_get_root: get root inode failed\n");
 97                 error = PTR_ERR(inode);        !!  98                 return ERR_CAST(inode);
 98                 nfs_errorf(fc, "NFS: Couldn't  << 
 99                 goto out_fattr;                << 
100         }                                          99         }
101                                                   100 
102         error = nfs_superblock_set_dummy_root( !! 101         error = nfs_superblock_set_dummy_root(sb, inode);
103         if (error != 0)                           102         if (error != 0)
104                 goto out_fattr;                !! 103                 return ERR_PTR(error);
105                                                   104 
106         /* root dentries normally start off an    105         /* root dentries normally start off anonymous and get spliced in later
107          * if the dentry tree reaches them; ho    106          * if the dentry tree reaches them; however if the dentry already
108          * exists, we'll pick it up at this po    107          * exists, we'll pick it up at this point and use it as the root
109          */                                       108          */
110         root = d_obtain_root(inode);           !! 109         mntroot = d_obtain_alias(inode);
111         if (IS_ERR(root)) {                    !! 110         if (IS_ERR(mntroot)) {
112                 dprintk("nfs_get_root: get roo    111                 dprintk("nfs_get_root: get root dentry failed\n");
113                 error = PTR_ERR(root);         !! 112                 return mntroot;
114                 nfs_errorf(fc, "NFS: Couldn't  !! 113         }
115                 goto out_fattr;                !! 114 
116         }                                      !! 115         security_d_instantiate(mntroot, inode);
117                                                !! 116 
118         security_d_instantiate(root, inode);   !! 117         if (!mntroot->d_op)
119         spin_lock(&root->d_lock);              !! 118                 mntroot->d_op = server->nfs_client->rpc_ops->dentry_ops;
120         if (IS_ROOT(root) && !root->d_fsdata & !! 119 
121             !(root->d_flags & DCACHE_NFSFS_REN !! 120         return mntroot;
122                 root->d_fsdata = name;         << 
123                 name = NULL;                   << 
124         }                                      << 
125         spin_unlock(&root->d_lock);            << 
126         fc->root = root;                       << 
127         if (server->caps & NFS_CAP_SECURITY_LA << 
128                 kflags |= SECURITY_LSM_NATIVE_ << 
129         if (ctx->clone_data.sb) {              << 
130                 if (d_inode(fc->root)->i_fop ! << 
131                         error = -ESTALE;       << 
132                         goto error_splat_root; << 
133                 }                              << 
134                 /* clone lsm security options  << 
135                 error = security_sb_clone_mnt_ << 
136                                                << 
137                 if (error)                     << 
138                         goto error_splat_root; << 
139                 clone_server = NFS_SB(ctx->clo << 
140                 server->has_sec_mnt_opts = clo << 
141         } else {                               << 
142                 error = security_sb_set_mnt_op << 
143                                                << 
144         }                                      << 
145         if (error)                             << 
146                 goto error_splat_root;         << 
147         if (server->caps & NFS_CAP_SECURITY_LA << 
148                 !(kflags_out & SECURITY_LSM_NA << 
149                 server->caps &= ~NFS_CAP_SECUR << 
150                                                << 
151         nfs_setsecurity(inode, fsinfo.fattr);  << 
152         error = 0;                             << 
153                                                << 
154 out_fattr:                                     << 
155         nfs_free_fattr(fsinfo.fattr);          << 
156 out_name:                                      << 
157         kfree(name);                           << 
158 out:                                           << 
159         return error;                          << 
160 error_splat_root:                              << 
161         dput(fc->root);                        << 
162         fc->root = NULL;                       << 
163         goto out_fattr;                        << 
164 }                                                 121 }
                                                   >> 122 
                                                   >> 123 #ifdef CONFIG_NFS_V4
                                                   >> 124 
                                                   >> 125 /*
                                                   >> 126  * Do a simple pathwalk from the root FH of the server to the nominated target
                                                   >> 127  * of the mountpoint
                                                   >> 128  * - give error on symlinks
                                                   >> 129  * - give error on ".." occurring in the path
                                                   >> 130  * - follow traversals
                                                   >> 131  */
                                                   >> 132 int nfs4_path_walk(struct nfs_server *server,
                                                   >> 133                    struct nfs_fh *mntfh,
                                                   >> 134                    const char *path)
                                                   >> 135 {
                                                   >> 136         struct nfs_fsinfo fsinfo;
                                                   >> 137         struct nfs_fattr fattr;
                                                   >> 138         struct nfs_fh lastfh;
                                                   >> 139         struct qstr name;
                                                   >> 140         int ret;
                                                   >> 141 
                                                   >> 142         dprintk("--> nfs4_path_walk(,,%s)\n", path);
                                                   >> 143 
                                                   >> 144         fsinfo.fattr = &fattr;
                                                   >> 145         nfs_fattr_init(&fattr);
                                                   >> 146 
                                                   >> 147         /* Eat leading slashes */
                                                   >> 148         while (*path == '/')
                                                   >> 149                 path++;
                                                   >> 150 
                                                   >> 151         /* Start by getting the root filehandle from the server */
                                                   >> 152         ret = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo);
                                                   >> 153         if (ret < 0) {
                                                   >> 154                 dprintk("nfs4_get_root: getroot error = %d\n", -ret);
                                                   >> 155                 return ret;
                                                   >> 156         }
                                                   >> 157 
                                                   >> 158         if (!S_ISDIR(fattr.mode)) {
                                                   >> 159                 printk(KERN_ERR "nfs4_get_root:"
                                                   >> 160                        " getroot encountered non-directory\n");
                                                   >> 161                 return -ENOTDIR;
                                                   >> 162         }
                                                   >> 163 
                                                   >> 164         /* FIXME: It is quite valid for the server to return a referral here */
                                                   >> 165         if (fattr.valid & NFS_ATTR_FATTR_V4_REFERRAL) {
                                                   >> 166                 printk(KERN_ERR "nfs4_get_root:"
                                                   >> 167                        " getroot obtained referral\n");
                                                   >> 168                 return -EREMOTE;
                                                   >> 169         }
                                                   >> 170 
                                                   >> 171 next_component:
                                                   >> 172         dprintk("Next: %s\n", path);
                                                   >> 173 
                                                   >> 174         /* extract the next bit of the path */
                                                   >> 175         if (!*path)
                                                   >> 176                 goto path_walk_complete;
                                                   >> 177 
                                                   >> 178         name.name = path;
                                                   >> 179         while (*path && *path != '/')
                                                   >> 180                 path++;
                                                   >> 181         name.len = path - (const char *) name.name;
                                                   >> 182 
                                                   >> 183         if (name.len > NFS4_MAXNAMLEN)
                                                   >> 184                 return -ENAMETOOLONG;
                                                   >> 185 
                                                   >> 186 eat_dot_dir:
                                                   >> 187         while (*path == '/')
                                                   >> 188                 path++;
                                                   >> 189 
                                                   >> 190         if (path[0] == '.' && (path[1] == '/' || !path[1])) {
                                                   >> 191                 path += 2;
                                                   >> 192                 goto eat_dot_dir;
                                                   >> 193         }
                                                   >> 194 
                                                   >> 195         /* FIXME: Why shouldn't the user be able to use ".." in the path? */
                                                   >> 196         if (path[0] == '.' && path[1] == '.' && (path[2] == '/' || !path[2])
                                                   >> 197             ) {
                                                   >> 198                 printk(KERN_ERR "nfs4_get_root:"
                                                   >> 199                        " Mount path contains reference to \"..\"\n");
                                                   >> 200                 return -EINVAL;
                                                   >> 201         }
                                                   >> 202 
                                                   >> 203         /* lookup the next FH in the sequence */
                                                   >> 204         memcpy(&lastfh, mntfh, sizeof(lastfh));
                                                   >> 205 
                                                   >> 206         dprintk("LookupFH: %*.*s [%s]\n", name.len, name.len, name.name, path);
                                                   >> 207 
                                                   >> 208         ret = server->nfs_client->rpc_ops->lookupfh(server, &lastfh, &name,
                                                   >> 209                                                     mntfh, &fattr);
                                                   >> 210         if (ret < 0) {
                                                   >> 211                 dprintk("nfs4_get_root: getroot error = %d\n", -ret);
                                                   >> 212                 return ret;
                                                   >> 213         }
                                                   >> 214 
                                                   >> 215         if (!S_ISDIR(fattr.mode)) {
                                                   >> 216                 printk(KERN_ERR "nfs4_get_root:"
                                                   >> 217                        " lookupfh encountered non-directory\n");
                                                   >> 218                 return -ENOTDIR;
                                                   >> 219         }
                                                   >> 220 
                                                   >> 221         /* FIXME: Referrals are quite valid here too */
                                                   >> 222         if (fattr.valid & NFS_ATTR_FATTR_V4_REFERRAL) {
                                                   >> 223                 printk(KERN_ERR "nfs4_get_root:"
                                                   >> 224                        " lookupfh obtained referral\n");
                                                   >> 225                 return -EREMOTE;
                                                   >> 226         }
                                                   >> 227 
                                                   >> 228         goto next_component;
                                                   >> 229 
                                                   >> 230 path_walk_complete:
                                                   >> 231         memcpy(&server->fsid, &fattr.fsid, sizeof(server->fsid));
                                                   >> 232         dprintk("<-- nfs4_path_walk() = 0\n");
                                                   >> 233         return 0;
                                                   >> 234 }
                                                   >> 235 
                                                   >> 236 /*
                                                   >> 237  * get an NFS4 root dentry from the root filehandle
                                                   >> 238  */
                                                   >> 239 struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh)
                                                   >> 240 {
                                                   >> 241         struct nfs_server *server = NFS_SB(sb);
                                                   >> 242         struct nfs_fattr fattr;
                                                   >> 243         struct dentry *mntroot;
                                                   >> 244         struct inode *inode;
                                                   >> 245         int error;
                                                   >> 246 
                                                   >> 247         dprintk("--> nfs4_get_root()\n");
                                                   >> 248 
                                                   >> 249         /* get the info about the server and filesystem */
                                                   >> 250         error = nfs4_server_capabilities(server, mntfh);
                                                   >> 251         if (error < 0) {
                                                   >> 252                 dprintk("nfs_get_root: getcaps error = %d\n",
                                                   >> 253                         -error);
                                                   >> 254                 return ERR_PTR(error);
                                                   >> 255         }
                                                   >> 256 
                                                   >> 257         /* get the actual root for this mount */
                                                   >> 258         error = server->nfs_client->rpc_ops->getattr(server, mntfh, &fattr);
                                                   >> 259         if (error < 0) {
                                                   >> 260                 dprintk("nfs_get_root: getattr error = %d\n", -error);
                                                   >> 261                 return ERR_PTR(error);
                                                   >> 262         }
                                                   >> 263 
                                                   >> 264         inode = nfs_fhget(sb, mntfh, &fattr);
                                                   >> 265         if (IS_ERR(inode)) {
                                                   >> 266                 dprintk("nfs_get_root: get root inode failed\n");
                                                   >> 267                 return ERR_CAST(inode);
                                                   >> 268         }
                                                   >> 269 
                                                   >> 270         error = nfs_superblock_set_dummy_root(sb, inode);
                                                   >> 271         if (error != 0)
                                                   >> 272                 return ERR_PTR(error);
                                                   >> 273 
                                                   >> 274         /* root dentries normally start off anonymous and get spliced in later
                                                   >> 275          * if the dentry tree reaches them; however if the dentry already
                                                   >> 276          * exists, we'll pick it up at this point and use it as the root
                                                   >> 277          */
                                                   >> 278         mntroot = d_obtain_alias(inode);
                                                   >> 279         if (IS_ERR(mntroot)) {
                                                   >> 280                 dprintk("nfs_get_root: get root dentry failed\n");
                                                   >> 281                 return mntroot;
                                                   >> 282         }
                                                   >> 283 
                                                   >> 284         security_d_instantiate(mntroot, inode);
                                                   >> 285 
                                                   >> 286         if (!mntroot->d_op)
                                                   >> 287                 mntroot->d_op = server->nfs_client->rpc_ops->dentry_ops;
                                                   >> 288 
                                                   >> 289         dprintk("<-- nfs4_get_root()\n");
                                                   >> 290         return mntroot;
                                                   >> 291 }
                                                   >> 292 
                                                   >> 293 #endif /* CONFIG_NFS_V4 */
165                                                   294 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php