1129d1977SBryan Schumaker /* 2129d1977SBryan Schumaker * Copyright (c) 2012 Bryan Schumaker <bjschuma@netapp.com> 3129d1977SBryan Schumaker */ 4129d1977SBryan Schumaker #include <linux/init.h> 5fbdefd64SBryan Schumaker #include <linux/module.h> 6129d1977SBryan Schumaker #include <linux/nfs_idmap.h> 7fbdefd64SBryan Schumaker #include <linux/nfs4_mount.h> 8466bfe7fSBryan Schumaker #include <linux/nfs_fs.h> 9fbdefd64SBryan Schumaker #include "internal.h" 10466bfe7fSBryan Schumaker #include "nfs4_fs.h" 11*ab7017a3SBryan Schumaker #include "nfs.h" 12129d1977SBryan Schumaker 13fbdefd64SBryan Schumaker #define NFSDBG_FACILITY NFSDBG_VFS 14fbdefd64SBryan Schumaker 15fbdefd64SBryan Schumaker static struct dentry *nfs4_remote_mount(struct file_system_type *fs_type, 16fbdefd64SBryan Schumaker int flags, const char *dev_name, void *raw_data); 17fbdefd64SBryan Schumaker static struct dentry *nfs4_xdev_mount(struct file_system_type *fs_type, 18fbdefd64SBryan Schumaker int flags, const char *dev_name, void *raw_data); 19fbdefd64SBryan Schumaker static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type, 20fbdefd64SBryan Schumaker int flags, const char *dev_name, void *raw_data); 21fbdefd64SBryan Schumaker static struct dentry *nfs4_remote_referral_mount(struct file_system_type *fs_type, 22fbdefd64SBryan Schumaker int flags, const char *dev_name, void *raw_data); 23fbdefd64SBryan Schumaker 24fbdefd64SBryan Schumaker static struct file_system_type nfs4_fs_type = { 25fbdefd64SBryan Schumaker .owner = THIS_MODULE, 26fbdefd64SBryan Schumaker .name = "nfs4", 27fbdefd64SBryan Schumaker .mount = nfs_fs_mount, 28fbdefd64SBryan Schumaker .kill_sb = nfs_kill_super, 29fbdefd64SBryan Schumaker .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, 30fbdefd64SBryan Schumaker }; 31fbdefd64SBryan Schumaker 32fbdefd64SBryan Schumaker static struct file_system_type nfs4_remote_fs_type = { 33fbdefd64SBryan Schumaker .owner = THIS_MODULE, 34fbdefd64SBryan Schumaker .name = "nfs4", 35fbdefd64SBryan Schumaker .mount = nfs4_remote_mount, 36fbdefd64SBryan Schumaker .kill_sb = nfs_kill_super, 37fbdefd64SBryan Schumaker .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, 38fbdefd64SBryan Schumaker }; 39fbdefd64SBryan Schumaker 40fbdefd64SBryan Schumaker struct file_system_type nfs4_xdev_fs_type = { 41fbdefd64SBryan Schumaker .owner = THIS_MODULE, 42fbdefd64SBryan Schumaker .name = "nfs4", 43fbdefd64SBryan Schumaker .mount = nfs4_xdev_mount, 44fbdefd64SBryan Schumaker .kill_sb = nfs_kill_super, 45fbdefd64SBryan Schumaker .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, 46fbdefd64SBryan Schumaker }; 47fbdefd64SBryan Schumaker 48fbdefd64SBryan Schumaker static struct file_system_type nfs4_remote_referral_fs_type = { 49fbdefd64SBryan Schumaker .owner = THIS_MODULE, 50fbdefd64SBryan Schumaker .name = "nfs4", 51fbdefd64SBryan Schumaker .mount = nfs4_remote_referral_mount, 52fbdefd64SBryan Schumaker .kill_sb = nfs_kill_super, 53fbdefd64SBryan Schumaker .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, 54fbdefd64SBryan Schumaker }; 55fbdefd64SBryan Schumaker 56fbdefd64SBryan Schumaker struct file_system_type nfs4_referral_fs_type = { 57fbdefd64SBryan Schumaker .owner = THIS_MODULE, 58fbdefd64SBryan Schumaker .name = "nfs4", 59fbdefd64SBryan Schumaker .mount = nfs4_referral_mount, 60fbdefd64SBryan Schumaker .kill_sb = nfs_kill_super, 61fbdefd64SBryan Schumaker .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, 62fbdefd64SBryan Schumaker }; 63fbdefd64SBryan Schumaker 64fbdefd64SBryan Schumaker static const struct super_operations nfs4_sops = { 65fbdefd64SBryan Schumaker .alloc_inode = nfs_alloc_inode, 66fbdefd64SBryan Schumaker .destroy_inode = nfs_destroy_inode, 67fbdefd64SBryan Schumaker .write_inode = nfs4_write_inode, 68fbdefd64SBryan Schumaker .put_super = nfs_put_super, 69fbdefd64SBryan Schumaker .statfs = nfs_statfs, 70fbdefd64SBryan Schumaker .evict_inode = nfs4_evict_inode, 71fbdefd64SBryan Schumaker .umount_begin = nfs_umount_begin, 72fbdefd64SBryan Schumaker .show_options = nfs_show_options, 73fbdefd64SBryan Schumaker .show_devname = nfs_show_devname, 74fbdefd64SBryan Schumaker .show_path = nfs_show_path, 75fbdefd64SBryan Schumaker .show_stats = nfs_show_stats, 76fbdefd64SBryan Schumaker .remount_fs = nfs_remount, 77fbdefd64SBryan Schumaker }; 78fbdefd64SBryan Schumaker 79*ab7017a3SBryan Schumaker struct nfs_subversion nfs_v4 = { 80*ab7017a3SBryan Schumaker .owner = THIS_MODULE, 81*ab7017a3SBryan Schumaker .nfs_fs = &nfs4_fs_type, 82*ab7017a3SBryan Schumaker .rpc_vers = &nfs_version4, 83*ab7017a3SBryan Schumaker .rpc_ops = &nfs_v4_clientops, 84*ab7017a3SBryan Schumaker }; 85*ab7017a3SBryan Schumaker 86fbdefd64SBryan Schumaker /* 87fbdefd64SBryan Schumaker * Set up an NFS4 superblock 88fbdefd64SBryan Schumaker */ 89fbdefd64SBryan Schumaker static void nfs4_fill_super(struct super_block *sb, 90fbdefd64SBryan Schumaker struct nfs_mount_info *mount_info) 91fbdefd64SBryan Schumaker { 92fbdefd64SBryan Schumaker sb->s_time_gran = 1; 93fbdefd64SBryan Schumaker sb->s_op = &nfs4_sops; 94fbdefd64SBryan Schumaker /* 95fbdefd64SBryan Schumaker * The VFS shouldn't apply the umask to mode bits. We will do 96fbdefd64SBryan Schumaker * so ourselves when necessary. 97fbdefd64SBryan Schumaker */ 98fbdefd64SBryan Schumaker sb->s_flags |= MS_POSIXACL; 99fbdefd64SBryan Schumaker sb->s_xattr = nfs4_xattr_handlers; 100fbdefd64SBryan Schumaker nfs_initialise_sb(sb); 101fbdefd64SBryan Schumaker } 102fbdefd64SBryan Schumaker 103fbdefd64SBryan Schumaker /* 104fbdefd64SBryan Schumaker * Get the superblock for the NFS4 root partition 105fbdefd64SBryan Schumaker */ 106fbdefd64SBryan Schumaker static struct dentry * 107fbdefd64SBryan Schumaker nfs4_remote_mount(struct file_system_type *fs_type, int flags, 108fbdefd64SBryan Schumaker const char *dev_name, void *info) 109fbdefd64SBryan Schumaker { 110fbdefd64SBryan Schumaker struct nfs_mount_info *mount_info = info; 111fbdefd64SBryan Schumaker struct nfs_server *server; 112fbdefd64SBryan Schumaker struct dentry *mntroot = ERR_PTR(-ENOMEM); 113fbdefd64SBryan Schumaker 114fbdefd64SBryan Schumaker mount_info->fill_super = nfs4_fill_super; 115fbdefd64SBryan Schumaker mount_info->set_security = nfs_set_sb_security; 116fbdefd64SBryan Schumaker 117fbdefd64SBryan Schumaker /* Get a volume representation */ 118fbdefd64SBryan Schumaker server = nfs4_create_server(mount_info->parsed, mount_info->mntfh); 119fbdefd64SBryan Schumaker if (IS_ERR(server)) { 120fbdefd64SBryan Schumaker mntroot = ERR_CAST(server); 121fbdefd64SBryan Schumaker goto out; 122fbdefd64SBryan Schumaker } 123fbdefd64SBryan Schumaker 124*ab7017a3SBryan Schumaker mntroot = nfs_fs_mount_common(server, flags, dev_name, mount_info, &nfs_v4); 125fbdefd64SBryan Schumaker 126fbdefd64SBryan Schumaker out: 127fbdefd64SBryan Schumaker return mntroot; 128fbdefd64SBryan Schumaker } 129fbdefd64SBryan Schumaker 130fbdefd64SBryan Schumaker static struct vfsmount *nfs_do_root_mount(struct file_system_type *fs_type, 131fbdefd64SBryan Schumaker int flags, void *data, const char *hostname) 132fbdefd64SBryan Schumaker { 133fbdefd64SBryan Schumaker struct vfsmount *root_mnt; 134fbdefd64SBryan Schumaker char *root_devname; 135fbdefd64SBryan Schumaker size_t len; 136fbdefd64SBryan Schumaker 137fbdefd64SBryan Schumaker len = strlen(hostname) + 5; 138fbdefd64SBryan Schumaker root_devname = kmalloc(len, GFP_KERNEL); 139fbdefd64SBryan Schumaker if (root_devname == NULL) 140fbdefd64SBryan Schumaker return ERR_PTR(-ENOMEM); 141fbdefd64SBryan Schumaker /* Does hostname needs to be enclosed in brackets? */ 142fbdefd64SBryan Schumaker if (strchr(hostname, ':')) 143fbdefd64SBryan Schumaker snprintf(root_devname, len, "[%s]:/", hostname); 144fbdefd64SBryan Schumaker else 145fbdefd64SBryan Schumaker snprintf(root_devname, len, "%s:/", hostname); 146fbdefd64SBryan Schumaker root_mnt = vfs_kern_mount(fs_type, flags, root_devname, data); 147fbdefd64SBryan Schumaker kfree(root_devname); 148fbdefd64SBryan Schumaker return root_mnt; 149fbdefd64SBryan Schumaker } 150fbdefd64SBryan Schumaker 151fbdefd64SBryan Schumaker struct nfs_referral_count { 152fbdefd64SBryan Schumaker struct list_head list; 153fbdefd64SBryan Schumaker const struct task_struct *task; 154fbdefd64SBryan Schumaker unsigned int referral_count; 155fbdefd64SBryan Schumaker }; 156fbdefd64SBryan Schumaker 157fbdefd64SBryan Schumaker static LIST_HEAD(nfs_referral_count_list); 158fbdefd64SBryan Schumaker static DEFINE_SPINLOCK(nfs_referral_count_list_lock); 159fbdefd64SBryan Schumaker 160fbdefd64SBryan Schumaker static struct nfs_referral_count *nfs_find_referral_count(void) 161fbdefd64SBryan Schumaker { 162fbdefd64SBryan Schumaker struct nfs_referral_count *p; 163fbdefd64SBryan Schumaker 164fbdefd64SBryan Schumaker list_for_each_entry(p, &nfs_referral_count_list, list) { 165fbdefd64SBryan Schumaker if (p->task == current) 166fbdefd64SBryan Schumaker return p; 167fbdefd64SBryan Schumaker } 168fbdefd64SBryan Schumaker return NULL; 169fbdefd64SBryan Schumaker } 170fbdefd64SBryan Schumaker 171fbdefd64SBryan Schumaker #define NFS_MAX_NESTED_REFERRALS 2 172fbdefd64SBryan Schumaker 173fbdefd64SBryan Schumaker static int nfs_referral_loop_protect(void) 174fbdefd64SBryan Schumaker { 175fbdefd64SBryan Schumaker struct nfs_referral_count *p, *new; 176fbdefd64SBryan Schumaker int ret = -ENOMEM; 177fbdefd64SBryan Schumaker 178fbdefd64SBryan Schumaker new = kmalloc(sizeof(*new), GFP_KERNEL); 179fbdefd64SBryan Schumaker if (!new) 180fbdefd64SBryan Schumaker goto out; 181fbdefd64SBryan Schumaker new->task = current; 182fbdefd64SBryan Schumaker new->referral_count = 1; 183fbdefd64SBryan Schumaker 184fbdefd64SBryan Schumaker ret = 0; 185fbdefd64SBryan Schumaker spin_lock(&nfs_referral_count_list_lock); 186fbdefd64SBryan Schumaker p = nfs_find_referral_count(); 187fbdefd64SBryan Schumaker if (p != NULL) { 188fbdefd64SBryan Schumaker if (p->referral_count >= NFS_MAX_NESTED_REFERRALS) 189fbdefd64SBryan Schumaker ret = -ELOOP; 190fbdefd64SBryan Schumaker else 191fbdefd64SBryan Schumaker p->referral_count++; 192fbdefd64SBryan Schumaker } else { 193fbdefd64SBryan Schumaker list_add(&new->list, &nfs_referral_count_list); 194fbdefd64SBryan Schumaker new = NULL; 195fbdefd64SBryan Schumaker } 196fbdefd64SBryan Schumaker spin_unlock(&nfs_referral_count_list_lock); 197fbdefd64SBryan Schumaker kfree(new); 198fbdefd64SBryan Schumaker out: 199fbdefd64SBryan Schumaker return ret; 200fbdefd64SBryan Schumaker } 201fbdefd64SBryan Schumaker 202fbdefd64SBryan Schumaker static void nfs_referral_loop_unprotect(void) 203fbdefd64SBryan Schumaker { 204fbdefd64SBryan Schumaker struct nfs_referral_count *p; 205fbdefd64SBryan Schumaker 206fbdefd64SBryan Schumaker spin_lock(&nfs_referral_count_list_lock); 207fbdefd64SBryan Schumaker p = nfs_find_referral_count(); 208fbdefd64SBryan Schumaker p->referral_count--; 209fbdefd64SBryan Schumaker if (p->referral_count == 0) 210fbdefd64SBryan Schumaker list_del(&p->list); 211fbdefd64SBryan Schumaker else 212fbdefd64SBryan Schumaker p = NULL; 213fbdefd64SBryan Schumaker spin_unlock(&nfs_referral_count_list_lock); 214fbdefd64SBryan Schumaker kfree(p); 215fbdefd64SBryan Schumaker } 216fbdefd64SBryan Schumaker 217fbdefd64SBryan Schumaker static struct dentry *nfs_follow_remote_path(struct vfsmount *root_mnt, 218fbdefd64SBryan Schumaker const char *export_path) 219fbdefd64SBryan Schumaker { 220fbdefd64SBryan Schumaker struct dentry *dentry; 221fbdefd64SBryan Schumaker int err; 222fbdefd64SBryan Schumaker 223fbdefd64SBryan Schumaker if (IS_ERR(root_mnt)) 224fbdefd64SBryan Schumaker return ERR_CAST(root_mnt); 225fbdefd64SBryan Schumaker 226fbdefd64SBryan Schumaker err = nfs_referral_loop_protect(); 227fbdefd64SBryan Schumaker if (err) { 228fbdefd64SBryan Schumaker mntput(root_mnt); 229fbdefd64SBryan Schumaker return ERR_PTR(err); 230fbdefd64SBryan Schumaker } 231fbdefd64SBryan Schumaker 232fbdefd64SBryan Schumaker dentry = mount_subtree(root_mnt, export_path); 233fbdefd64SBryan Schumaker nfs_referral_loop_unprotect(); 234fbdefd64SBryan Schumaker 235fbdefd64SBryan Schumaker return dentry; 236fbdefd64SBryan Schumaker } 237fbdefd64SBryan Schumaker 238fbdefd64SBryan Schumaker struct dentry *nfs4_try_mount(int flags, const char *dev_name, 239fbdefd64SBryan Schumaker struct nfs_mount_info *mount_info) 240fbdefd64SBryan Schumaker { 241fbdefd64SBryan Schumaker char *export_path; 242fbdefd64SBryan Schumaker struct vfsmount *root_mnt; 243fbdefd64SBryan Schumaker struct dentry *res; 244fbdefd64SBryan Schumaker struct nfs_parsed_mount_data *data = mount_info->parsed; 245fbdefd64SBryan Schumaker 246fbdefd64SBryan Schumaker dfprintk(MOUNT, "--> nfs4_try_mount()\n"); 247fbdefd64SBryan Schumaker 248fbdefd64SBryan Schumaker mount_info->fill_super = nfs4_fill_super; 249fbdefd64SBryan Schumaker 250fbdefd64SBryan Schumaker export_path = data->nfs_server.export_path; 251fbdefd64SBryan Schumaker data->nfs_server.export_path = "/"; 252fbdefd64SBryan Schumaker root_mnt = nfs_do_root_mount(&nfs4_remote_fs_type, flags, mount_info, 253fbdefd64SBryan Schumaker data->nfs_server.hostname); 254fbdefd64SBryan Schumaker data->nfs_server.export_path = export_path; 255fbdefd64SBryan Schumaker 256fbdefd64SBryan Schumaker res = nfs_follow_remote_path(root_mnt, export_path); 257fbdefd64SBryan Schumaker 258fbdefd64SBryan Schumaker dfprintk(MOUNT, "<-- nfs4_try_mount() = %ld%s\n", 259fbdefd64SBryan Schumaker IS_ERR(res) ? PTR_ERR(res) : 0, 260fbdefd64SBryan Schumaker IS_ERR(res) ? " [error]" : ""); 261fbdefd64SBryan Schumaker return res; 262fbdefd64SBryan Schumaker } 263fbdefd64SBryan Schumaker 264fbdefd64SBryan Schumaker /* 265fbdefd64SBryan Schumaker * Clone an NFS4 server record on xdev traversal (FSID-change) 266fbdefd64SBryan Schumaker */ 267fbdefd64SBryan Schumaker static struct dentry * 268fbdefd64SBryan Schumaker nfs4_xdev_mount(struct file_system_type *fs_type, int flags, 269fbdefd64SBryan Schumaker const char *dev_name, void *raw_data) 270fbdefd64SBryan Schumaker { 271fbdefd64SBryan Schumaker struct nfs_mount_info mount_info = { 272fbdefd64SBryan Schumaker .fill_super = nfs_clone_super, 273fbdefd64SBryan Schumaker .set_security = nfs_clone_sb_security, 274fbdefd64SBryan Schumaker .cloned = raw_data, 275fbdefd64SBryan Schumaker }; 276fbdefd64SBryan Schumaker return nfs_xdev_mount_common(&nfs4_fs_type, flags, dev_name, &mount_info); 277fbdefd64SBryan Schumaker } 278fbdefd64SBryan Schumaker 279fbdefd64SBryan Schumaker static struct dentry * 280fbdefd64SBryan Schumaker nfs4_remote_referral_mount(struct file_system_type *fs_type, int flags, 281fbdefd64SBryan Schumaker const char *dev_name, void *raw_data) 282fbdefd64SBryan Schumaker { 283fbdefd64SBryan Schumaker struct nfs_mount_info mount_info = { 284fbdefd64SBryan Schumaker .fill_super = nfs4_fill_super, 285fbdefd64SBryan Schumaker .set_security = nfs_clone_sb_security, 286fbdefd64SBryan Schumaker .cloned = raw_data, 287fbdefd64SBryan Schumaker }; 288fbdefd64SBryan Schumaker struct nfs_server *server; 289fbdefd64SBryan Schumaker struct dentry *mntroot = ERR_PTR(-ENOMEM); 290fbdefd64SBryan Schumaker 291fbdefd64SBryan Schumaker dprintk("--> nfs4_referral_get_sb()\n"); 292fbdefd64SBryan Schumaker 293fbdefd64SBryan Schumaker mount_info.mntfh = nfs_alloc_fhandle(); 294fbdefd64SBryan Schumaker if (mount_info.cloned == NULL || mount_info.mntfh == NULL) 295fbdefd64SBryan Schumaker goto out; 296fbdefd64SBryan Schumaker 297fbdefd64SBryan Schumaker /* create a new volume representation */ 298fbdefd64SBryan Schumaker server = nfs4_create_referral_server(mount_info.cloned, mount_info.mntfh); 299fbdefd64SBryan Schumaker if (IS_ERR(server)) { 300fbdefd64SBryan Schumaker mntroot = ERR_CAST(server); 301fbdefd64SBryan Schumaker goto out; 302fbdefd64SBryan Schumaker } 303fbdefd64SBryan Schumaker 304*ab7017a3SBryan Schumaker mntroot = nfs_fs_mount_common(server, flags, dev_name, &mount_info, &nfs_v4); 305fbdefd64SBryan Schumaker out: 306fbdefd64SBryan Schumaker nfs_free_fhandle(mount_info.mntfh); 307fbdefd64SBryan Schumaker return mntroot; 308fbdefd64SBryan Schumaker } 309fbdefd64SBryan Schumaker 310fbdefd64SBryan Schumaker /* 311fbdefd64SBryan Schumaker * Create an NFS4 server record on referral traversal 312fbdefd64SBryan Schumaker */ 313fbdefd64SBryan Schumaker static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type, 314fbdefd64SBryan Schumaker int flags, const char *dev_name, void *raw_data) 315fbdefd64SBryan Schumaker { 316fbdefd64SBryan Schumaker struct nfs_clone_mount *data = raw_data; 317fbdefd64SBryan Schumaker char *export_path; 318fbdefd64SBryan Schumaker struct vfsmount *root_mnt; 319fbdefd64SBryan Schumaker struct dentry *res; 320fbdefd64SBryan Schumaker 321fbdefd64SBryan Schumaker dprintk("--> nfs4_referral_mount()\n"); 322fbdefd64SBryan Schumaker 323fbdefd64SBryan Schumaker export_path = data->mnt_path; 324fbdefd64SBryan Schumaker data->mnt_path = "/"; 325fbdefd64SBryan Schumaker 326fbdefd64SBryan Schumaker root_mnt = nfs_do_root_mount(&nfs4_remote_referral_fs_type, 327fbdefd64SBryan Schumaker flags, data, data->hostname); 328fbdefd64SBryan Schumaker data->mnt_path = export_path; 329fbdefd64SBryan Schumaker 330fbdefd64SBryan Schumaker res = nfs_follow_remote_path(root_mnt, export_path); 331fbdefd64SBryan Schumaker dprintk("<-- nfs4_referral_mount() = %ld%s\n", 332fbdefd64SBryan Schumaker IS_ERR(res) ? PTR_ERR(res) : 0, 333fbdefd64SBryan Schumaker IS_ERR(res) ? " [error]" : ""); 334fbdefd64SBryan Schumaker return res; 335fbdefd64SBryan Schumaker } 336fbdefd64SBryan Schumaker 337fbdefd64SBryan Schumaker 338129d1977SBryan Schumaker int __init init_nfs_v4(void) 339129d1977SBryan Schumaker { 340129d1977SBryan Schumaker int err; 341129d1977SBryan Schumaker 342129d1977SBryan Schumaker err = nfs_idmap_init(); 343129d1977SBryan Schumaker if (err) 344129d1977SBryan Schumaker goto out; 345129d1977SBryan Schumaker 346466bfe7fSBryan Schumaker err = nfs4_register_sysctl(); 347466bfe7fSBryan Schumaker if (err) 348466bfe7fSBryan Schumaker goto out1; 349466bfe7fSBryan Schumaker 350fbdefd64SBryan Schumaker err = register_filesystem(&nfs4_fs_type); 351fbdefd64SBryan Schumaker if (err < 0) 352fbdefd64SBryan Schumaker goto out2; 353fbdefd64SBryan Schumaker 354*ab7017a3SBryan Schumaker register_nfs_version(&nfs_v4); 355129d1977SBryan Schumaker return 0; 356fbdefd64SBryan Schumaker out2: 357fbdefd64SBryan Schumaker nfs4_unregister_sysctl(); 358466bfe7fSBryan Schumaker out1: 359466bfe7fSBryan Schumaker nfs_idmap_quit(); 360129d1977SBryan Schumaker out: 361129d1977SBryan Schumaker return err; 362129d1977SBryan Schumaker } 363129d1977SBryan Schumaker 364bb6e071fSBryan Schumaker void exit_nfs_v4(void) 365129d1977SBryan Schumaker { 366*ab7017a3SBryan Schumaker unregister_nfs_version(&nfs_v4); 367fbdefd64SBryan Schumaker unregister_filesystem(&nfs4_fs_type); 368466bfe7fSBryan Schumaker nfs4_unregister_sysctl(); 369129d1977SBryan Schumaker nfs_idmap_quit(); 370129d1977SBryan Schumaker } 371