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> 919d87ca3SBryan Schumaker #include "delegation.h" 10fbdefd64SBryan Schumaker #include "internal.h" 11466bfe7fSBryan Schumaker #include "nfs4_fs.h" 12*c8d74d9bSTrond Myklebust #include "dns_resolve.h" 1319d87ca3SBryan Schumaker #include "pnfs.h" 14ab7017a3SBryan Schumaker #include "nfs.h" 15129d1977SBryan Schumaker 16fbdefd64SBryan Schumaker #define NFSDBG_FACILITY NFSDBG_VFS 17fbdefd64SBryan Schumaker 1819d87ca3SBryan Schumaker static int nfs4_write_inode(struct inode *inode, struct writeback_control *wbc); 1919d87ca3SBryan Schumaker static void nfs4_evict_inode(struct inode *inode); 20fbdefd64SBryan Schumaker static struct dentry *nfs4_remote_mount(struct file_system_type *fs_type, 21fbdefd64SBryan Schumaker int flags, const char *dev_name, void *raw_data); 22fbdefd64SBryan Schumaker static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type, 23fbdefd64SBryan Schumaker int flags, const char *dev_name, void *raw_data); 24fbdefd64SBryan Schumaker static struct dentry *nfs4_remote_referral_mount(struct file_system_type *fs_type, 25fbdefd64SBryan Schumaker int flags, const char *dev_name, void *raw_data); 26fbdefd64SBryan Schumaker 27fbdefd64SBryan Schumaker static struct file_system_type nfs4_remote_fs_type = { 28fbdefd64SBryan Schumaker .owner = THIS_MODULE, 29fbdefd64SBryan Schumaker .name = "nfs4", 30fbdefd64SBryan Schumaker .mount = nfs4_remote_mount, 31fbdefd64SBryan Schumaker .kill_sb = nfs_kill_super, 32ecf3d1f1SJeff Layton .fs_flags = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA, 33fbdefd64SBryan Schumaker }; 34fbdefd64SBryan Schumaker 35fbdefd64SBryan Schumaker static struct file_system_type nfs4_remote_referral_fs_type = { 36fbdefd64SBryan Schumaker .owner = THIS_MODULE, 37fbdefd64SBryan Schumaker .name = "nfs4", 38fbdefd64SBryan Schumaker .mount = nfs4_remote_referral_mount, 39fbdefd64SBryan Schumaker .kill_sb = nfs_kill_super, 40ecf3d1f1SJeff Layton .fs_flags = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA, 41fbdefd64SBryan Schumaker }; 42fbdefd64SBryan Schumaker 43fbdefd64SBryan Schumaker struct file_system_type nfs4_referral_fs_type = { 44fbdefd64SBryan Schumaker .owner = THIS_MODULE, 45fbdefd64SBryan Schumaker .name = "nfs4", 46fbdefd64SBryan Schumaker .mount = nfs4_referral_mount, 47fbdefd64SBryan Schumaker .kill_sb = nfs_kill_super, 48ecf3d1f1SJeff Layton .fs_flags = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA, 49fbdefd64SBryan Schumaker }; 50fbdefd64SBryan Schumaker 51fbdefd64SBryan Schumaker static const struct super_operations nfs4_sops = { 52fbdefd64SBryan Schumaker .alloc_inode = nfs_alloc_inode, 53fbdefd64SBryan Schumaker .destroy_inode = nfs_destroy_inode, 54fbdefd64SBryan Schumaker .write_inode = nfs4_write_inode, 55eed99357STrond Myklebust .drop_inode = nfs_drop_inode, 56fbdefd64SBryan Schumaker .put_super = nfs_put_super, 57fbdefd64SBryan Schumaker .statfs = nfs_statfs, 58fbdefd64SBryan Schumaker .evict_inode = nfs4_evict_inode, 59fbdefd64SBryan Schumaker .umount_begin = nfs_umount_begin, 60fbdefd64SBryan Schumaker .show_options = nfs_show_options, 61fbdefd64SBryan Schumaker .show_devname = nfs_show_devname, 62fbdefd64SBryan Schumaker .show_path = nfs_show_path, 63fbdefd64SBryan Schumaker .show_stats = nfs_show_stats, 64fbdefd64SBryan Schumaker .remount_fs = nfs_remount, 65fbdefd64SBryan Schumaker }; 66fbdefd64SBryan Schumaker 67ab7017a3SBryan Schumaker struct nfs_subversion nfs_v4 = { 68ab7017a3SBryan Schumaker .owner = THIS_MODULE, 69ab7017a3SBryan Schumaker .nfs_fs = &nfs4_fs_type, 70ab7017a3SBryan Schumaker .rpc_vers = &nfs_version4, 71ab7017a3SBryan Schumaker .rpc_ops = &nfs_v4_clientops, 726a74490dSBryan Schumaker .sops = &nfs4_sops, 736a74490dSBryan Schumaker .xattr = nfs4_xattr_handlers, 74ab7017a3SBryan Schumaker }; 75ab7017a3SBryan Schumaker 7619d87ca3SBryan Schumaker static int nfs4_write_inode(struct inode *inode, struct writeback_control *wbc) 7719d87ca3SBryan Schumaker { 7819d87ca3SBryan Schumaker int ret = nfs_write_inode(inode, wbc); 7919d87ca3SBryan Schumaker 8019d87ca3SBryan Schumaker if (ret >= 0 && test_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(inode)->flags)) { 8119d87ca3SBryan Schumaker int status; 8219d87ca3SBryan Schumaker bool sync = true; 8319d87ca3SBryan Schumaker 8419d87ca3SBryan Schumaker if (wbc->sync_mode == WB_SYNC_NONE) 8519d87ca3SBryan Schumaker sync = false; 8619d87ca3SBryan Schumaker 8719d87ca3SBryan Schumaker status = pnfs_layoutcommit_inode(inode, sync); 8819d87ca3SBryan Schumaker if (status < 0) 8919d87ca3SBryan Schumaker return status; 9019d87ca3SBryan Schumaker } 9119d87ca3SBryan Schumaker return ret; 9219d87ca3SBryan Schumaker } 9319d87ca3SBryan Schumaker 9419d87ca3SBryan Schumaker /* 9519d87ca3SBryan Schumaker * Clean out any remaining NFSv4 state that might be left over due 9619d87ca3SBryan Schumaker * to open() calls that passed nfs_atomic_lookup, but failed to call 9719d87ca3SBryan Schumaker * nfs_open(). 9819d87ca3SBryan Schumaker */ 9919d87ca3SBryan Schumaker static void nfs4_evict_inode(struct inode *inode) 10019d87ca3SBryan Schumaker { 10119d87ca3SBryan Schumaker truncate_inode_pages(&inode->i_data, 0); 10219d87ca3SBryan Schumaker clear_inode(inode); 10319d87ca3SBryan Schumaker pnfs_return_layout(inode); 10419d87ca3SBryan Schumaker pnfs_destroy_layout(NFS_I(inode)); 10519d87ca3SBryan Schumaker /* If we are holding a delegation, return it! */ 10619d87ca3SBryan Schumaker nfs_inode_return_delegation_noreclaim(inode); 10719d87ca3SBryan Schumaker /* First call standard NFS clear_inode() code */ 10819d87ca3SBryan Schumaker nfs_clear_inode(inode); 10919d87ca3SBryan Schumaker } 11019d87ca3SBryan Schumaker 111fbdefd64SBryan Schumaker /* 112fbdefd64SBryan Schumaker * Get the superblock for the NFS4 root partition 113fbdefd64SBryan Schumaker */ 114fbdefd64SBryan Schumaker static struct dentry * 115fbdefd64SBryan Schumaker nfs4_remote_mount(struct file_system_type *fs_type, int flags, 116fbdefd64SBryan Schumaker const char *dev_name, void *info) 117fbdefd64SBryan Schumaker { 118fbdefd64SBryan Schumaker struct nfs_mount_info *mount_info = info; 119fbdefd64SBryan Schumaker struct nfs_server *server; 120fbdefd64SBryan Schumaker struct dentry *mntroot = ERR_PTR(-ENOMEM); 121fbdefd64SBryan Schumaker 122fbdefd64SBryan Schumaker mount_info->set_security = nfs_set_sb_security; 123fbdefd64SBryan Schumaker 124fbdefd64SBryan Schumaker /* Get a volume representation */ 1251179acc6SBryan Schumaker server = nfs4_create_server(mount_info, &nfs_v4); 126fbdefd64SBryan Schumaker if (IS_ERR(server)) { 127fbdefd64SBryan Schumaker mntroot = ERR_CAST(server); 128fbdefd64SBryan Schumaker goto out; 129fbdefd64SBryan Schumaker } 130fbdefd64SBryan Schumaker 131ab7017a3SBryan Schumaker mntroot = nfs_fs_mount_common(server, flags, dev_name, mount_info, &nfs_v4); 132fbdefd64SBryan Schumaker 133fbdefd64SBryan Schumaker out: 134fbdefd64SBryan Schumaker return mntroot; 135fbdefd64SBryan Schumaker } 136fbdefd64SBryan Schumaker 137fbdefd64SBryan Schumaker static struct vfsmount *nfs_do_root_mount(struct file_system_type *fs_type, 138fbdefd64SBryan Schumaker int flags, void *data, const char *hostname) 139fbdefd64SBryan Schumaker { 140fbdefd64SBryan Schumaker struct vfsmount *root_mnt; 141fbdefd64SBryan Schumaker char *root_devname; 142fbdefd64SBryan Schumaker size_t len; 143fbdefd64SBryan Schumaker 144fbdefd64SBryan Schumaker len = strlen(hostname) + 5; 145fbdefd64SBryan Schumaker root_devname = kmalloc(len, GFP_KERNEL); 146fbdefd64SBryan Schumaker if (root_devname == NULL) 147fbdefd64SBryan Schumaker return ERR_PTR(-ENOMEM); 148fbdefd64SBryan Schumaker /* Does hostname needs to be enclosed in brackets? */ 149fbdefd64SBryan Schumaker if (strchr(hostname, ':')) 150fbdefd64SBryan Schumaker snprintf(root_devname, len, "[%s]:/", hostname); 151fbdefd64SBryan Schumaker else 152fbdefd64SBryan Schumaker snprintf(root_devname, len, "%s:/", hostname); 153fbdefd64SBryan Schumaker root_mnt = vfs_kern_mount(fs_type, flags, root_devname, data); 154fbdefd64SBryan Schumaker kfree(root_devname); 155fbdefd64SBryan Schumaker return root_mnt; 156fbdefd64SBryan Schumaker } 157fbdefd64SBryan Schumaker 158fbdefd64SBryan Schumaker struct nfs_referral_count { 159fbdefd64SBryan Schumaker struct list_head list; 160fbdefd64SBryan Schumaker const struct task_struct *task; 161fbdefd64SBryan Schumaker unsigned int referral_count; 162fbdefd64SBryan Schumaker }; 163fbdefd64SBryan Schumaker 164fbdefd64SBryan Schumaker static LIST_HEAD(nfs_referral_count_list); 165fbdefd64SBryan Schumaker static DEFINE_SPINLOCK(nfs_referral_count_list_lock); 166fbdefd64SBryan Schumaker 167fbdefd64SBryan Schumaker static struct nfs_referral_count *nfs_find_referral_count(void) 168fbdefd64SBryan Schumaker { 169fbdefd64SBryan Schumaker struct nfs_referral_count *p; 170fbdefd64SBryan Schumaker 171fbdefd64SBryan Schumaker list_for_each_entry(p, &nfs_referral_count_list, list) { 172fbdefd64SBryan Schumaker if (p->task == current) 173fbdefd64SBryan Schumaker return p; 174fbdefd64SBryan Schumaker } 175fbdefd64SBryan Schumaker return NULL; 176fbdefd64SBryan Schumaker } 177fbdefd64SBryan Schumaker 178fbdefd64SBryan Schumaker #define NFS_MAX_NESTED_REFERRALS 2 179fbdefd64SBryan Schumaker 180fbdefd64SBryan Schumaker static int nfs_referral_loop_protect(void) 181fbdefd64SBryan Schumaker { 182fbdefd64SBryan Schumaker struct nfs_referral_count *p, *new; 183fbdefd64SBryan Schumaker int ret = -ENOMEM; 184fbdefd64SBryan Schumaker 185fbdefd64SBryan Schumaker new = kmalloc(sizeof(*new), GFP_KERNEL); 186fbdefd64SBryan Schumaker if (!new) 187fbdefd64SBryan Schumaker goto out; 188fbdefd64SBryan Schumaker new->task = current; 189fbdefd64SBryan Schumaker new->referral_count = 1; 190fbdefd64SBryan Schumaker 191fbdefd64SBryan Schumaker ret = 0; 192fbdefd64SBryan Schumaker spin_lock(&nfs_referral_count_list_lock); 193fbdefd64SBryan Schumaker p = nfs_find_referral_count(); 194fbdefd64SBryan Schumaker if (p != NULL) { 195fbdefd64SBryan Schumaker if (p->referral_count >= NFS_MAX_NESTED_REFERRALS) 196fbdefd64SBryan Schumaker ret = -ELOOP; 197fbdefd64SBryan Schumaker else 198fbdefd64SBryan Schumaker p->referral_count++; 199fbdefd64SBryan Schumaker } else { 200fbdefd64SBryan Schumaker list_add(&new->list, &nfs_referral_count_list); 201fbdefd64SBryan Schumaker new = NULL; 202fbdefd64SBryan Schumaker } 203fbdefd64SBryan Schumaker spin_unlock(&nfs_referral_count_list_lock); 204fbdefd64SBryan Schumaker kfree(new); 205fbdefd64SBryan Schumaker out: 206fbdefd64SBryan Schumaker return ret; 207fbdefd64SBryan Schumaker } 208fbdefd64SBryan Schumaker 209fbdefd64SBryan Schumaker static void nfs_referral_loop_unprotect(void) 210fbdefd64SBryan Schumaker { 211fbdefd64SBryan Schumaker struct nfs_referral_count *p; 212fbdefd64SBryan Schumaker 213fbdefd64SBryan Schumaker spin_lock(&nfs_referral_count_list_lock); 214fbdefd64SBryan Schumaker p = nfs_find_referral_count(); 215fbdefd64SBryan Schumaker p->referral_count--; 216fbdefd64SBryan Schumaker if (p->referral_count == 0) 217fbdefd64SBryan Schumaker list_del(&p->list); 218fbdefd64SBryan Schumaker else 219fbdefd64SBryan Schumaker p = NULL; 220fbdefd64SBryan Schumaker spin_unlock(&nfs_referral_count_list_lock); 221fbdefd64SBryan Schumaker kfree(p); 222fbdefd64SBryan Schumaker } 223fbdefd64SBryan Schumaker 224fbdefd64SBryan Schumaker static struct dentry *nfs_follow_remote_path(struct vfsmount *root_mnt, 225fbdefd64SBryan Schumaker const char *export_path) 226fbdefd64SBryan Schumaker { 227fbdefd64SBryan Schumaker struct dentry *dentry; 228fbdefd64SBryan Schumaker int err; 229fbdefd64SBryan Schumaker 230fbdefd64SBryan Schumaker if (IS_ERR(root_mnt)) 231fbdefd64SBryan Schumaker return ERR_CAST(root_mnt); 232fbdefd64SBryan Schumaker 233fbdefd64SBryan Schumaker err = nfs_referral_loop_protect(); 234fbdefd64SBryan Schumaker if (err) { 235fbdefd64SBryan Schumaker mntput(root_mnt); 236fbdefd64SBryan Schumaker return ERR_PTR(err); 237fbdefd64SBryan Schumaker } 238fbdefd64SBryan Schumaker 239fbdefd64SBryan Schumaker dentry = mount_subtree(root_mnt, export_path); 240fbdefd64SBryan Schumaker nfs_referral_loop_unprotect(); 241fbdefd64SBryan Schumaker 242fbdefd64SBryan Schumaker return dentry; 243fbdefd64SBryan Schumaker } 244fbdefd64SBryan Schumaker 245fbdefd64SBryan Schumaker struct dentry *nfs4_try_mount(int flags, const char *dev_name, 246ff9099f2SBryan Schumaker struct nfs_mount_info *mount_info, 247ff9099f2SBryan Schumaker struct nfs_subversion *nfs_mod) 248fbdefd64SBryan Schumaker { 249fbdefd64SBryan Schumaker char *export_path; 250fbdefd64SBryan Schumaker struct vfsmount *root_mnt; 251fbdefd64SBryan Schumaker struct dentry *res; 252fbdefd64SBryan Schumaker struct nfs_parsed_mount_data *data = mount_info->parsed; 253fbdefd64SBryan Schumaker 254fbdefd64SBryan Schumaker dfprintk(MOUNT, "--> nfs4_try_mount()\n"); 255fbdefd64SBryan Schumaker 2564580a92dSChuck Lever if (data->auth_flavors[0] == RPC_AUTH_MAXFLAVOR) 2574580a92dSChuck Lever data->auth_flavors[0] = RPC_AUTH_UNIX; 258fbdefd64SBryan Schumaker export_path = data->nfs_server.export_path; 259fbdefd64SBryan Schumaker data->nfs_server.export_path = "/"; 260fbdefd64SBryan Schumaker root_mnt = nfs_do_root_mount(&nfs4_remote_fs_type, flags, mount_info, 261fbdefd64SBryan Schumaker data->nfs_server.hostname); 262fbdefd64SBryan Schumaker data->nfs_server.export_path = export_path; 263fbdefd64SBryan Schumaker 264fbdefd64SBryan Schumaker res = nfs_follow_remote_path(root_mnt, export_path); 265fbdefd64SBryan Schumaker 266fbdefd64SBryan Schumaker dfprintk(MOUNT, "<-- nfs4_try_mount() = %ld%s\n", 267fbdefd64SBryan Schumaker IS_ERR(res) ? PTR_ERR(res) : 0, 268fbdefd64SBryan Schumaker IS_ERR(res) ? " [error]" : ""); 269fbdefd64SBryan Schumaker return res; 270fbdefd64SBryan Schumaker } 271fbdefd64SBryan Schumaker 272fbdefd64SBryan Schumaker static struct dentry * 273fbdefd64SBryan Schumaker nfs4_remote_referral_mount(struct file_system_type *fs_type, int flags, 274fbdefd64SBryan Schumaker const char *dev_name, void *raw_data) 275fbdefd64SBryan Schumaker { 276fbdefd64SBryan Schumaker struct nfs_mount_info mount_info = { 2776a74490dSBryan Schumaker .fill_super = nfs_fill_super, 278fbdefd64SBryan Schumaker .set_security = nfs_clone_sb_security, 279fbdefd64SBryan Schumaker .cloned = raw_data, 280fbdefd64SBryan Schumaker }; 281fbdefd64SBryan Schumaker struct nfs_server *server; 282fbdefd64SBryan Schumaker struct dentry *mntroot = ERR_PTR(-ENOMEM); 283fbdefd64SBryan Schumaker 284fbdefd64SBryan Schumaker dprintk("--> nfs4_referral_get_sb()\n"); 285fbdefd64SBryan Schumaker 286fbdefd64SBryan Schumaker mount_info.mntfh = nfs_alloc_fhandle(); 287fbdefd64SBryan Schumaker if (mount_info.cloned == NULL || mount_info.mntfh == NULL) 288fbdefd64SBryan Schumaker goto out; 289fbdefd64SBryan Schumaker 290fbdefd64SBryan Schumaker /* create a new volume representation */ 291fbdefd64SBryan Schumaker server = nfs4_create_referral_server(mount_info.cloned, mount_info.mntfh); 292fbdefd64SBryan Schumaker if (IS_ERR(server)) { 293fbdefd64SBryan Schumaker mntroot = ERR_CAST(server); 294fbdefd64SBryan Schumaker goto out; 295fbdefd64SBryan Schumaker } 296fbdefd64SBryan Schumaker 297ab7017a3SBryan Schumaker mntroot = nfs_fs_mount_common(server, flags, dev_name, &mount_info, &nfs_v4); 298fbdefd64SBryan Schumaker out: 299fbdefd64SBryan Schumaker nfs_free_fhandle(mount_info.mntfh); 300fbdefd64SBryan Schumaker return mntroot; 301fbdefd64SBryan Schumaker } 302fbdefd64SBryan Schumaker 303fbdefd64SBryan Schumaker /* 304fbdefd64SBryan Schumaker * Create an NFS4 server record on referral traversal 305fbdefd64SBryan Schumaker */ 306fbdefd64SBryan Schumaker static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type, 307fbdefd64SBryan Schumaker int flags, const char *dev_name, void *raw_data) 308fbdefd64SBryan Schumaker { 309fbdefd64SBryan Schumaker struct nfs_clone_mount *data = raw_data; 310fbdefd64SBryan Schumaker char *export_path; 311fbdefd64SBryan Schumaker struct vfsmount *root_mnt; 312fbdefd64SBryan Schumaker struct dentry *res; 313fbdefd64SBryan Schumaker 314fbdefd64SBryan Schumaker dprintk("--> nfs4_referral_mount()\n"); 315fbdefd64SBryan Schumaker 316fbdefd64SBryan Schumaker export_path = data->mnt_path; 317fbdefd64SBryan Schumaker data->mnt_path = "/"; 318fbdefd64SBryan Schumaker 319fbdefd64SBryan Schumaker root_mnt = nfs_do_root_mount(&nfs4_remote_referral_fs_type, 320fbdefd64SBryan Schumaker flags, data, data->hostname); 321fbdefd64SBryan Schumaker data->mnt_path = export_path; 322fbdefd64SBryan Schumaker 323fbdefd64SBryan Schumaker res = nfs_follow_remote_path(root_mnt, export_path); 324fbdefd64SBryan Schumaker dprintk("<-- nfs4_referral_mount() = %ld%s\n", 325fbdefd64SBryan Schumaker IS_ERR(res) ? PTR_ERR(res) : 0, 326fbdefd64SBryan Schumaker IS_ERR(res) ? " [error]" : ""); 327fbdefd64SBryan Schumaker return res; 328fbdefd64SBryan Schumaker } 329fbdefd64SBryan Schumaker 330fbdefd64SBryan Schumaker 33189d77c8fSBryan Schumaker static int __init init_nfs_v4(void) 332129d1977SBryan Schumaker { 333129d1977SBryan Schumaker int err; 334129d1977SBryan Schumaker 335*c8d74d9bSTrond Myklebust err = nfs_dns_resolver_init(); 336129d1977SBryan Schumaker if (err) 337129d1977SBryan Schumaker goto out; 338129d1977SBryan Schumaker 339*c8d74d9bSTrond Myklebust err = nfs_idmap_init(); 340466bfe7fSBryan Schumaker if (err) 341466bfe7fSBryan Schumaker goto out1; 342466bfe7fSBryan Schumaker 343*c8d74d9bSTrond Myklebust err = nfs4_register_sysctl(); 344*c8d74d9bSTrond Myklebust if (err) 345*c8d74d9bSTrond Myklebust goto out2; 346*c8d74d9bSTrond Myklebust 347ab7017a3SBryan Schumaker register_nfs_version(&nfs_v4); 348129d1977SBryan Schumaker return 0; 349*c8d74d9bSTrond Myklebust out2: 350466bfe7fSBryan Schumaker nfs_idmap_quit(); 351*c8d74d9bSTrond Myklebust out1: 352*c8d74d9bSTrond Myklebust nfs_dns_resolver_destroy(); 353129d1977SBryan Schumaker out: 354129d1977SBryan Schumaker return err; 355129d1977SBryan Schumaker } 356129d1977SBryan Schumaker 35789d77c8fSBryan Schumaker static void __exit exit_nfs_v4(void) 358129d1977SBryan Schumaker { 359ab7017a3SBryan Schumaker unregister_nfs_version(&nfs_v4); 360466bfe7fSBryan Schumaker nfs4_unregister_sysctl(); 361129d1977SBryan Schumaker nfs_idmap_quit(); 362*c8d74d9bSTrond Myklebust nfs_dns_resolver_destroy(); 363129d1977SBryan Schumaker } 36489d77c8fSBryan Schumaker 36589d77c8fSBryan Schumaker MODULE_LICENSE("GPL"); 36689d77c8fSBryan Schumaker 36789d77c8fSBryan Schumaker module_init(init_nfs_v4); 36889d77c8fSBryan Schumaker module_exit(exit_nfs_v4); 369