/* * 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; }
/* * Get the superblock for an NFS4 mountpoint */ static int nfs4_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) { struct nfs4_mount_data *data = raw_data; struct super_block *s; struct nfs_server *server; struct sockaddr_in addr; rpc_authflavor_t authflavour; struct nfs_fh mntfh; struct dentry *mntroot; char *mntpath = NULL, *hostname = NULL, ip_addr[16]; void *p; int error; if (data == NULL) { dprintk("%s: missing data argument\n", __FUNCTION__); return -EINVAL; } if (data->version <= 0 || data->version > NFS4_MOUNT_VERSION) { dprintk("%s: bad mount version\n", __FUNCTION__); return -EINVAL; } /* We now require that the mount process passes the remote address */ if (data->host_addrlen != sizeof(addr)) return -EINVAL; if (copy_from_user(&addr, data->host_addr, sizeof(addr))) return -EFAULT; if (addr.sin_family != AF_INET || addr.sin_addr.s_addr == INADDR_ANY ) { dprintk("%s: mount program didn't pass remote IP address!\n", __FUNCTION__); return -EINVAL; } /* RFC3530: The default port for NFS is 2049 */ if (addr.sin_port == 0) addr.sin_port = htons(NFS_PORT); /* Grab the authentication type */ authflavour = RPC_AUTH_UNIX; if (data->auth_flavourlen != 0) { if (data->auth_flavourlen != 1) { dprintk("%s: Invalid number of RPC auth flavours %d.\n", __FUNCTION__, data->auth_flavourlen); error = -EINVAL; goto out_err_noserver; } if (copy_from_user(&authflavour, data->auth_flavours, sizeof(authflavour))) { error = -EFAULT; goto out_err_noserver; } } p = nfs_copy_user_string(NULL, &data->hostname, 256); if (IS_ERR(p)) goto out_err; hostname = p; p = nfs_copy_user_string(NULL, &data->mnt_path, 1024); if (IS_ERR(p)) goto out_err; mntpath = p; dprintk("MNTPATH: %s\n", mntpath); p = nfs_copy_user_string(ip_addr, &data->client_addr, sizeof(ip_addr) - 1); if (IS_ERR(p)) goto out_err; /* Get a volume representation */ server = nfs4_create_server(data, hostname, &addr, mntpath, ip_addr, authflavour, &mntfh); if (IS_ERR(server)) { error = PTR_ERR(server); goto out_err_noserver; } /* Get a superblock - note that we may end up sharing one that already exists */ s = sget(fs_type, nfs_compare_super, nfs_set_super, server); if (IS_ERR(s)) { error = PTR_ERR(s); goto out_free; } if (s->s_fs_info != server) { nfs_free_server(server); server = NULL; } if (!s->s_root) { /* initial superblock/root creation */ s->s_flags = flags; nfs4_fill_super(s); } mntroot = nfs4_get_root(s, &mntfh); if (IS_ERR(mntroot)) { error = PTR_ERR(mntroot); goto error_splat_super; } s->s_flags |= MS_ACTIVE; mnt->mnt_sb = s; mnt->mnt_root = mntroot; kfree(mntpath); kfree(hostname); return 0; out_err: error = PTR_ERR(p); goto out_err_noserver; out_free: nfs_free_server(server); out_err_noserver: kfree(mntpath); kfree(hostname); return error; error_splat_super: up_write(&s->s_umount); deactivate_super(s); goto out_err_noserver; }