|
@@ -122,115 +122,44 @@ struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh)
|
|
|
|
|
|
#ifdef CONFIG_NFS_V4
|
|
#ifdef CONFIG_NFS_V4
|
|
|
|
|
|
-/*
|
|
|
|
- * Do a simple pathwalk from the root FH of the server to the nominated target
|
|
|
|
- * of the mountpoint
|
|
|
|
- * - give error on symlinks
|
|
|
|
- * - give error on ".." occurring in the path
|
|
|
|
- * - follow traversals
|
|
|
|
- */
|
|
|
|
-int nfs4_path_walk(struct nfs_server *server,
|
|
|
|
- struct nfs_fh *mntfh,
|
|
|
|
- const char *path)
|
|
|
|
|
|
+int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh)
|
|
{
|
|
{
|
|
struct nfs_fsinfo fsinfo;
|
|
struct nfs_fsinfo fsinfo;
|
|
- struct nfs_fattr fattr;
|
|
|
|
- struct nfs_fh lastfh;
|
|
|
|
- struct qstr name;
|
|
|
|
- int ret;
|
|
|
|
|
|
+ int ret = -ENOMEM;
|
|
|
|
|
|
- dprintk("--> nfs4_path_walk(,,%s)\n", path);
|
|
|
|
|
|
+ dprintk("--> nfs4_get_rootfh()\n");
|
|
|
|
|
|
- fsinfo.fattr = &fattr;
|
|
|
|
- nfs_fattr_init(&fattr);
|
|
|
|
-
|
|
|
|
- /* Eat leading slashes */
|
|
|
|
- while (*path == '/')
|
|
|
|
- path++;
|
|
|
|
|
|
+ fsinfo.fattr = nfs_alloc_fattr();
|
|
|
|
+ if (fsinfo.fattr == NULL)
|
|
|
|
+ goto out;
|
|
|
|
|
|
/* Start by getting the root filehandle from the server */
|
|
/* Start by getting the root filehandle from the server */
|
|
ret = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo);
|
|
ret = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo);
|
|
if (ret < 0) {
|
|
if (ret < 0) {
|
|
- dprintk("nfs4_get_root: getroot error = %d\n", -ret);
|
|
|
|
- return ret;
|
|
|
|
|
|
+ dprintk("nfs4_get_rootfh: getroot error = %d\n", -ret);
|
|
|
|
+ goto out;
|
|
}
|
|
}
|
|
|
|
|
|
- if (!S_ISDIR(fattr.mode)) {
|
|
|
|
- printk(KERN_ERR "nfs4_get_root:"
|
|
|
|
|
|
+ if (!(fsinfo.fattr->valid & NFS_ATTR_FATTR_MODE)
|
|
|
|
+ || !S_ISDIR(fsinfo.fattr->mode)) {
|
|
|
|
+ printk(KERN_ERR "nfs4_get_rootfh:"
|
|
" getroot encountered non-directory\n");
|
|
" getroot encountered non-directory\n");
|
|
- return -ENOTDIR;
|
|
|
|
|
|
+ ret = -ENOTDIR;
|
|
|
|
+ goto out;
|
|
}
|
|
}
|
|
|
|
|
|
- /* FIXME: It is quite valid for the server to return a referral here */
|
|
|
|
- if (fattr.valid & NFS_ATTR_FATTR_V4_REFERRAL) {
|
|
|
|
- printk(KERN_ERR "nfs4_get_root:"
|
|
|
|
|
|
+ if (fsinfo.fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) {
|
|
|
|
+ printk(KERN_ERR "nfs4_get_rootfh:"
|
|
" getroot obtained referral\n");
|
|
" getroot obtained referral\n");
|
|
- return -EREMOTE;
|
|
|
|
|
|
+ ret = -EREMOTE;
|
|
|
|
+ goto out;
|
|
}
|
|
}
|
|
|
|
|
|
-next_component:
|
|
|
|
- dprintk("Next: %s\n", path);
|
|
|
|
-
|
|
|
|
- /* extract the next bit of the path */
|
|
|
|
- if (!*path)
|
|
|
|
- goto path_walk_complete;
|
|
|
|
-
|
|
|
|
- name.name = path;
|
|
|
|
- while (*path && *path != '/')
|
|
|
|
- path++;
|
|
|
|
- name.len = path - (const char *) name.name;
|
|
|
|
-
|
|
|
|
- if (name.len > NFS4_MAXNAMLEN)
|
|
|
|
- return -ENAMETOOLONG;
|
|
|
|
-
|
|
|
|
-eat_dot_dir:
|
|
|
|
- while (*path == '/')
|
|
|
|
- path++;
|
|
|
|
-
|
|
|
|
- if (path[0] == '.' && (path[1] == '/' || !path[1])) {
|
|
|
|
- path += 2;
|
|
|
|
- goto eat_dot_dir;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* FIXME: Why shouldn't the user be able to use ".." in the path? */
|
|
|
|
- if (path[0] == '.' && path[1] == '.' && (path[2] == '/' || !path[2])
|
|
|
|
- ) {
|
|
|
|
- printk(KERN_ERR "nfs4_get_root:"
|
|
|
|
- " Mount path contains reference to \"..\"\n");
|
|
|
|
- return -EINVAL;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* lookup the next FH in the sequence */
|
|
|
|
- memcpy(&lastfh, mntfh, sizeof(lastfh));
|
|
|
|
-
|
|
|
|
- dprintk("LookupFH: %*.*s [%s]\n", name.len, name.len, name.name, path);
|
|
|
|
-
|
|
|
|
- ret = server->nfs_client->rpc_ops->lookupfh(server, &lastfh, &name,
|
|
|
|
- mntfh, &fattr);
|
|
|
|
- if (ret < 0) {
|
|
|
|
- dprintk("nfs4_get_root: getroot error = %d\n", -ret);
|
|
|
|
- return ret;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (!S_ISDIR(fattr.mode)) {
|
|
|
|
- printk(KERN_ERR "nfs4_get_root:"
|
|
|
|
- " lookupfh encountered non-directory\n");
|
|
|
|
- return -ENOTDIR;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* FIXME: Referrals are quite valid here too */
|
|
|
|
- if (fattr.valid & NFS_ATTR_FATTR_V4_REFERRAL) {
|
|
|
|
- printk(KERN_ERR "nfs4_get_root:"
|
|
|
|
- " lookupfh obtained referral\n");
|
|
|
|
- return -EREMOTE;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- goto next_component;
|
|
|
|
-
|
|
|
|
-path_walk_complete:
|
|
|
|
- memcpy(&server->fsid, &fattr.fsid, sizeof(server->fsid));
|
|
|
|
- dprintk("<-- nfs4_path_walk() = 0\n");
|
|
|
|
- return 0;
|
|
|
|
|
|
+ memcpy(&server->fsid, &fsinfo.fattr->fsid, sizeof(server->fsid));
|
|
|
|
+out:
|
|
|
|
+ nfs_free_fattr(fsinfo.fattr);
|
|
|
|
+ dprintk("<-- nfs4_get_rootfh() = %d\n", ret);
|
|
|
|
+ return ret;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|