diff options
author | Rodrigo Vivi <rodrigo.vivi@intel.com> | 2020-02-25 20:29:58 +0300 |
---|---|---|
committer | Rodrigo Vivi <rodrigo.vivi@intel.com> | 2020-02-25 20:39:23 +0300 |
commit | ff36e78fdb251b9fa65028554689806961e011eb (patch) | |
tree | f5af925d509224e06a10936196be6c06bcbdc6ae /fs/nfs/nfs4super.c | |
parent | 143d9c3e7b6aa2b785abba04266ed75f2b52e94a (diff) | |
parent | 1b245ec5b685ebf8e6e5d1e6b5bcc03b6608e8b0 (diff) | |
download | linux-ff36e78fdb251b9fa65028554689806961e011eb.tar.xz |
Merge drm/drm-next into drm-intel-next-queued
Some DSI and VBT pending patches from Hans will apply
cleanly and with less ugly conflicts if they are rebuilt
on top of other patches that recently landed on drm-next.
Reference: https://patchwork.freedesktop.org/series/70952/
Cc: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com
Diffstat (limited to 'fs/nfs/nfs4super.c')
-rw-r--r-- | fs/nfs/nfs4super.c | 257 |
1 files changed, 97 insertions, 160 deletions
diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c index 2c9cbade561a..1475f932d7da 100644 --- a/fs/nfs/nfs4super.c +++ b/fs/nfs/nfs4super.c @@ -4,6 +4,7 @@ */ #include <linux/init.h> #include <linux/module.h> +#include <linux/mount.h> #include <linux/nfs4_mount.h> #include <linux/nfs_fs.h> #include "delegation.h" @@ -18,36 +19,6 @@ static int nfs4_write_inode(struct inode *inode, struct writeback_control *wbc); static void nfs4_evict_inode(struct inode *inode); -static struct dentry *nfs4_remote_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, void *raw_data); -static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, void *raw_data); -static struct dentry *nfs4_remote_referral_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, void *raw_data); - -static struct file_system_type nfs4_remote_fs_type = { - .owner = THIS_MODULE, - .name = "nfs4", - .mount = nfs4_remote_mount, - .kill_sb = nfs_kill_super, - .fs_flags = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA, -}; - -static struct file_system_type nfs4_remote_referral_fs_type = { - .owner = THIS_MODULE, - .name = "nfs4", - .mount = nfs4_remote_referral_mount, - .kill_sb = nfs_kill_super, - .fs_flags = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA, -}; - -struct file_system_type nfs4_referral_fs_type = { - .owner = THIS_MODULE, - .name = "nfs4", - .mount = nfs4_referral_mount, - .kill_sb = nfs_kill_super, - .fs_flags = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA, -}; static const struct super_operations nfs4_sops = { .alloc_inode = nfs_alloc_inode, @@ -61,16 +32,15 @@ static const struct super_operations nfs4_sops = { .show_devname = nfs_show_devname, .show_path = nfs_show_path, .show_stats = nfs_show_stats, - .remount_fs = nfs_remount, }; struct nfs_subversion nfs_v4 = { - .owner = THIS_MODULE, - .nfs_fs = &nfs4_fs_type, - .rpc_vers = &nfs_version4, - .rpc_ops = &nfs_v4_clientops, - .sops = &nfs4_sops, - .xattr = nfs4_xattr_handlers, + .owner = THIS_MODULE, + .nfs_fs = &nfs4_fs_type, + .rpc_vers = &nfs_version4, + .rpc_ops = &nfs_v4_clientops, + .sops = &nfs4_sops, + .xattr = nfs4_xattr_handlers, }; static int nfs4_write_inode(struct inode *inode, struct writeback_control *wbc) @@ -101,53 +71,6 @@ static void nfs4_evict_inode(struct inode *inode) nfs_clear_inode(inode); } -/* - * Get the superblock for the NFS4 root partition - */ -static struct dentry * -nfs4_remote_mount(struct file_system_type *fs_type, int flags, - const char *dev_name, void *info) -{ - struct nfs_mount_info *mount_info = info; - struct nfs_server *server; - struct dentry *mntroot = ERR_PTR(-ENOMEM); - - mount_info->set_security = nfs_set_sb_security; - - /* Get a volume representation */ - server = nfs4_create_server(mount_info, &nfs_v4); - if (IS_ERR(server)) { - mntroot = ERR_CAST(server); - goto out; - } - - mntroot = nfs_fs_mount_common(server, flags, dev_name, mount_info, &nfs_v4); - -out: - return mntroot; -} - -static struct vfsmount *nfs_do_root_mount(struct file_system_type *fs_type, - int flags, void *data, const char *hostname) -{ - struct vfsmount *root_mnt; - char *root_devname; - size_t len; - - len = strlen(hostname) + 5; - root_devname = kmalloc(len, GFP_KERNEL); - if (root_devname == NULL) - return ERR_PTR(-ENOMEM); - /* Does hostname needs to be enclosed in brackets? */ - if (strchr(hostname, ':')) - snprintf(root_devname, len, "[%s]:/", hostname); - else - snprintf(root_devname, len, "%s:/", hostname); - root_mnt = vfs_kern_mount(fs_type, flags, root_devname, data); - kfree(root_devname); - return root_mnt; -} - struct nfs_referral_count { struct list_head list; const struct task_struct *task; @@ -214,111 +137,125 @@ static void nfs_referral_loop_unprotect(void) kfree(p); } -static struct dentry *nfs_follow_remote_path(struct vfsmount *root_mnt, - const char *export_path) +static int do_nfs4_mount(struct nfs_server *server, + struct fs_context *fc, + const char *hostname, + const char *export_path) { + struct nfs_fs_context *root_ctx; + struct fs_context *root_fc; + struct vfsmount *root_mnt; struct dentry *dentry; - int err; + size_t len; + int ret; - if (IS_ERR(root_mnt)) - return ERR_CAST(root_mnt); + struct fs_parameter param = { + .key = "source", + .type = fs_value_is_string, + .dirfd = -1, + }; - err = nfs_referral_loop_protect(); - if (err) { - mntput(root_mnt); - return ERR_PTR(err); + if (IS_ERR(server)) + return PTR_ERR(server); + + root_fc = vfs_dup_fs_context(fc); + if (IS_ERR(root_fc)) { + nfs_free_server(server); + return PTR_ERR(root_fc); } + kfree(root_fc->source); + root_fc->source = NULL; - dentry = mount_subtree(root_mnt, export_path); - nfs_referral_loop_unprotect(); + root_ctx = nfs_fc2context(root_fc); + root_ctx->internal = true; + root_ctx->server = server; + /* We leave export_path unset as it's not used to find the root. */ - return dentry; -} + len = strlen(hostname) + 5; + param.string = kmalloc(len, GFP_KERNEL); + if (param.string == NULL) { + put_fs_context(root_fc); + return -ENOMEM; + } -struct dentry *nfs4_try_mount(int flags, const char *dev_name, - struct nfs_mount_info *mount_info, - struct nfs_subversion *nfs_mod) -{ - char *export_path; - struct vfsmount *root_mnt; - struct dentry *res; - struct nfs_parsed_mount_data *data = mount_info->parsed; + /* Does hostname needs to be enclosed in brackets? */ + if (strchr(hostname, ':')) + param.size = snprintf(param.string, len, "[%s]:/", hostname); + else + param.size = snprintf(param.string, len, "%s:/", hostname); + ret = vfs_parse_fs_param(root_fc, ¶m); + kfree(param.string); + if (ret < 0) { + put_fs_context(root_fc); + return ret; + } + root_mnt = fc_mount(root_fc); + put_fs_context(root_fc); + + if (IS_ERR(root_mnt)) + return PTR_ERR(root_mnt); - dfprintk(MOUNT, "--> nfs4_try_mount()\n"); + ret = nfs_referral_loop_protect(); + if (ret) { + mntput(root_mnt); + return ret; + } - export_path = data->nfs_server.export_path; - data->nfs_server.export_path = "/"; - root_mnt = nfs_do_root_mount(&nfs4_remote_fs_type, flags, mount_info, - data->nfs_server.hostname); - data->nfs_server.export_path = export_path; + dentry = mount_subtree(root_mnt, export_path); + nfs_referral_loop_unprotect(); - res = nfs_follow_remote_path(root_mnt, export_path); + if (IS_ERR(dentry)) + return PTR_ERR(dentry); - dfprintk(MOUNT, "<-- nfs4_try_mount() = %d%s\n", - PTR_ERR_OR_ZERO(res), - IS_ERR(res) ? " [error]" : ""); - return res; + fc->root = dentry; + return 0; } -static struct dentry * -nfs4_remote_referral_mount(struct file_system_type *fs_type, int flags, - const char *dev_name, void *raw_data) +int nfs4_try_get_tree(struct fs_context *fc) { - struct nfs_mount_info mount_info = { - .fill_super = nfs_fill_super, - .set_security = nfs_clone_sb_security, - .cloned = raw_data, - }; - struct nfs_server *server; - struct dentry *mntroot = ERR_PTR(-ENOMEM); - - dprintk("--> nfs4_referral_get_sb()\n"); + struct nfs_fs_context *ctx = nfs_fc2context(fc); + int err; - mount_info.mntfh = nfs_alloc_fhandle(); - if (mount_info.cloned == NULL || mount_info.mntfh == NULL) - goto out; + dfprintk(MOUNT, "--> nfs4_try_get_tree()\n"); - /* create a new volume representation */ - server = nfs4_create_referral_server(mount_info.cloned, mount_info.mntfh); - if (IS_ERR(server)) { - mntroot = ERR_CAST(server); - goto out; + /* We create a mount for the server's root, walk to the requested + * location and then create another mount for that. + */ + err= do_nfs4_mount(nfs4_create_server(fc), + fc, ctx->nfs_server.hostname, + ctx->nfs_server.export_path); + if (err) { + nfs_errorf(fc, "NFS4: Couldn't follow remote path"); + dfprintk(MOUNT, "<-- nfs4_try_get_tree() = %d [error]\n", err); + } else { + dfprintk(MOUNT, "<-- nfs4_try_get_tree() = 0\n"); } - - mntroot = nfs_fs_mount_common(server, flags, dev_name, &mount_info, &nfs_v4); -out: - nfs_free_fhandle(mount_info.mntfh); - return mntroot; + return err; } /* * Create an NFS4 server record on referral traversal */ -static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, void *raw_data) +int nfs4_get_referral_tree(struct fs_context *fc) { - struct nfs_clone_mount *data = raw_data; - char *export_path; - struct vfsmount *root_mnt; - struct dentry *res; + struct nfs_fs_context *ctx = nfs_fc2context(fc); + int err; dprintk("--> nfs4_referral_mount()\n"); - export_path = data->mnt_path; - data->mnt_path = "/"; - - root_mnt = nfs_do_root_mount(&nfs4_remote_referral_fs_type, - flags, data, data->hostname); - data->mnt_path = export_path; - - res = nfs_follow_remote_path(root_mnt, export_path); - dprintk("<-- nfs4_referral_mount() = %d%s\n", - PTR_ERR_OR_ZERO(res), - IS_ERR(res) ? " [error]" : ""); - return res; + /* create a new volume representation */ + err = do_nfs4_mount(nfs4_create_referral_server(fc), + fc, ctx->nfs_server.hostname, + ctx->nfs_server.export_path); + if (err) { + nfs_errorf(fc, "NFS4: Couldn't follow remote path"); + dfprintk(MOUNT, "<-- nfs4_get_referral_tree() = %d [error]\n", err); + } else { + dfprintk(MOUNT, "<-- nfs4_get_referral_tree() = 0\n"); + } + return err; } - static int __init init_nfs_v4(void) { int err; |