📄 super.c
字号:
if (server->flags & NFS_MOUNT_UNSHARED) compare_super = NULL; /* Get a superblock - note that we may end up sharing one that already exists */ s = sget(&nfs_fs_type, compare_super, nfs_set_super, &sb_mntdata); if (IS_ERR(s)) { error = PTR_ERR(s); goto out_err_nosb; } if (s->s_fs_info != server) { nfs_free_server(server); server = NULL; } if (!s->s_root) { /* initial superblock/root creation */ nfs_clone_super(s, data->sb); } mntroot = nfs_get_root(s, data->fh); if (IS_ERR(mntroot)) { error = PTR_ERR(mntroot); goto error_splat_super; } if (mntroot->d_inode->i_op != NFS_SB(s)->nfs_client->rpc_ops->dir_inode_ops) { dput(mntroot); error = -ESTALE; goto error_splat_super; } s->s_flags |= MS_ACTIVE; mnt->mnt_sb = s; mnt->mnt_root = mntroot; dprintk("<-- nfs_xdev_get_sb() = 0\n"); return 0;out_err_nosb: nfs_free_server(server);out_err_noserver: dprintk("<-- nfs_xdev_get_sb() = %d [error]\n", error); return error;error_splat_super: up_write(&s->s_umount); deactivate_super(s); dprintk("<-- nfs_xdev_get_sb() = %d [splat]\n", error); return error;}#ifdef CONFIG_NFS_V4/* * Finish setting up a cloned NFS4 superblock */static void nfs4_clone_super(struct super_block *sb, const struct super_block *old_sb){ sb->s_blocksize_bits = old_sb->s_blocksize_bits; sb->s_blocksize = old_sb->s_blocksize; sb->s_maxbytes = old_sb->s_maxbytes; sb->s_time_gran = 1; sb->s_op = old_sb->s_op; nfs_initialise_sb(sb);}/* * Set up an NFS4 superblock */static void nfs4_fill_super(struct super_block *sb){ sb->s_time_gran = 1; sb->s_op = &nfs4_sops; nfs_initialise_sb(sb);}/* * Validate NFSv4 mount options */static int nfs4_validate_mount_data(void *options, struct nfs_parsed_mount_data *args, const char *dev_name){ struct nfs4_mount_data *data = (struct nfs4_mount_data *)options; char *c; memset(args, 0, sizeof(*args)); if (data == NULL) goto out_no_data; args->rsize = NFS_MAX_FILE_IO_SIZE; args->wsize = NFS_MAX_FILE_IO_SIZE; args->timeo = 600; args->retrans = 2; args->acregmin = 3; args->acregmax = 60; args->acdirmin = 30; args->acdirmax = 60; args->nfs_server.protocol = XPRT_TRANSPORT_TCP; switch (data->version) { case 1: if (data->host_addrlen != sizeof(args->nfs_server.address)) goto out_no_address; if (copy_from_user(&args->nfs_server.address, data->host_addr, sizeof(args->nfs_server.address))) return -EFAULT; if (args->nfs_server.address.sin_port == 0) args->nfs_server.address.sin_port = htons(NFS_PORT); if (!nfs_verify_server_address((struct sockaddr *) &args->nfs_server.address)) goto out_no_address; switch (data->auth_flavourlen) { case 0: args->auth_flavors[0] = RPC_AUTH_UNIX; break; case 1: if (copy_from_user(&args->auth_flavors[0], data->auth_flavours, sizeof(args->auth_flavors[0]))) return -EFAULT; break; default: goto out_inval_auth; } c = strndup_user(data->hostname.data, NFS4_MAXNAMLEN); if (IS_ERR(c)) return PTR_ERR(c); args->nfs_server.hostname = c; c = strndup_user(data->mnt_path.data, NFS4_MAXPATHLEN); if (IS_ERR(c)) return PTR_ERR(c); args->nfs_server.export_path = c; dfprintk(MOUNT, "NFS: MNTPATH: '%s'\n", c); c = strndup_user(data->client_addr.data, 16); if (IS_ERR(c)) return PTR_ERR(c); args->client_address = c; /* * Translate to nfs_parsed_mount_data, which nfs4_fill_super * can deal with. */ args->flags = data->flags & NFS4_MOUNT_FLAGMASK; args->rsize = data->rsize; args->wsize = data->wsize; args->timeo = data->timeo; args->retrans = data->retrans; args->acregmin = data->acregmin; args->acregmax = data->acregmax; args->acdirmin = data->acdirmin; args->acdirmax = data->acdirmax; args->nfs_server.protocol = data->proto; break; default: { unsigned int len; if (nfs_parse_mount_options((char *)options, args) == 0) return -EINVAL; if (!nfs_verify_server_address((struct sockaddr *) &args->nfs_server.address)) return -EINVAL; switch (args->auth_flavor_len) { case 0: args->auth_flavors[0] = RPC_AUTH_UNIX; break; case 1: break; default: goto out_inval_auth; } /* * Split "dev_name" into "hostname:mntpath". */ c = strchr(dev_name, ':'); if (c == NULL) return -EINVAL; /* while calculating len, pretend ':' is '\0' */ len = c - dev_name; if (len > NFS4_MAXNAMLEN) return -ENAMETOOLONG; args->nfs_server.hostname = kzalloc(len, GFP_KERNEL); if (args->nfs_server.hostname == NULL) return -ENOMEM; strncpy(args->nfs_server.hostname, dev_name, len - 1); c++; /* step over the ':' */ len = strlen(c); if (len > NFS4_MAXPATHLEN) return -ENAMETOOLONG; args->nfs_server.export_path = kzalloc(len + 1, GFP_KERNEL); if (args->nfs_server.export_path == NULL) return -ENOMEM; strncpy(args->nfs_server.export_path, c, len); dprintk("MNTPATH: %s\n", args->nfs_server.export_path); if (args->client_address == NULL) goto out_no_client_address; break; } } return 0;out_no_data: dfprintk(MOUNT, "NFS4: mount program didn't pass any mount data\n"); return -EINVAL;out_inval_auth: dfprintk(MOUNT, "NFS4: Invalid number of RPC auth flavours %d\n", data->auth_flavourlen); return -EINVAL;out_no_address: dfprintk(MOUNT, "NFS4: mount program didn't pass remote address\n"); return -EINVAL;out_no_client_address: dfprintk(MOUNT, "NFS4: mount program didn't pass callback address\n"); return -EINVAL;}/* * 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 nfs_parsed_mount_data data; struct super_block *s; struct nfs_server *server; struct nfs_fh mntfh; struct dentry *mntroot; int (*compare_super)(struct super_block *, void *) = nfs_compare_super; struct nfs_sb_mountdata sb_mntdata = { .mntflags = flags, }; int error; /* Validate the mount data */ error = nfs4_validate_mount_data(raw_data, &data, dev_name); if (error < 0) goto out; /* Get a volume representation */ server = nfs4_create_server(&data, &mntfh); if (IS_ERR(server)) { error = PTR_ERR(server); goto out; } sb_mntdata.server = server; if (server->flags & NFS4_MOUNT_UNSHARED) compare_super = NULL; /* Get a superblock - note that we may end up sharing one that already exists */ s = sget(fs_type, compare_super, nfs_set_super, &sb_mntdata); 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 */ 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; error = 0;out: kfree(data.client_address); kfree(data.nfs_server.export_path); kfree(data.nfs_server.hostname); return error;out_free: nfs_free_server(server); goto out;error_splat_super: up_write(&s->s_umount); deactivate_super(s); goto out;}static void nfs4_kill_super(struct super_block *sb){ struct nfs_server *server = NFS_SB(sb); nfs_return_all_delegations(sb); kill_anon_super(sb); nfs4_renewd_prepare_shutdown(server); nfs_free_server(server);}/* * Clone an NFS4 server record on xdev traversal (FSID-change) */static int nfs4_xdev_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt){ struct nfs_clone_mount *data = raw_data; struct super_block *s; struct nfs_server *server; struct dentry *mntroot; int (*compare_super)(struct super_block *, void *) = nfs_compare_super; struct nfs_sb_mountdata sb_mntdata = { .mntflags = flags, }; int error; dprintk("--> nfs4_xdev_get_sb()\n"); /* create a new volume representation */ server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr); if (IS_ERR(server)) { error = PTR_ERR(server); goto out_err_noserver; } sb_mntdata.server = server; if (server->flags & NFS4_MOUNT_UNSHARED) compare_super = NULL; /* Get a superblock - note that we may end up sharing one that already exists */ s = sget(&nfs_fs_type, compare_super, nfs_set_super, &sb_mntdata); if (IS_ERR(s)) { error = PTR_ERR(s); goto out_err_nosb; } if (s->s_fs_info != server) { nfs_free_server(server); server = NULL; } if (!s->s_root) { /* initial superblock/root creation */ nfs4_clone_super(s, data->sb); } mntroot = nfs4_get_root(s, data->fh); if (IS_ERR(mntroot)) { error = PTR_ERR(mntroot); goto error_splat_super; } if (mntroot->d_inode->i_op != NFS_SB(s)->nfs_client->rpc_ops->dir_inode_ops) { dput(mntroot); error = -ESTALE; goto error_splat_super; } s->s_flags |= MS_ACTIVE; mnt->mnt_sb = s; mnt->mnt_root = mntroot; dprintk("<-- nfs4_xdev_get_sb() = 0\n"); return 0;out_err_nosb: nfs_free_server(server);out_err_noserver: dprintk("<-- nfs4_xdev_get_sb() = %d [error]\n", error); return error;error_splat_super: up_write(&s->s_umount); deactivate_super(s); dprintk("<-- nfs4_xdev_get_sb() = %d [splat]\n", error); return error;}/* * Create an NFS4 server record on referral traversal */static int nfs4_referral_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt){ struct nfs_clone_mount *data = raw_data; struct super_block *s; struct nfs_server *server; struct dentry *mntroot; struct nfs_fh mntfh; int (*compare_super)(struct super_block *, void *) = nfs_compare_super; struct nfs_sb_mountdata sb_mntdata = { .mntflags = flags, }; int error; dprintk("--> nfs4_referral_get_sb()\n"); /* create a new volume representation */ server = nfs4_create_referral_server(data, &mntfh); if (IS_ERR(server)) { error = PTR_ERR(server); goto out_err_noserver; } sb_mntdata.server = server; if (server->flags & NFS4_MOUNT_UNSHARED) compare_super = NULL; /* Get a superblock - note that we may end up sharing one that already exists */ s = sget(&nfs_fs_type, compare_super, nfs_set_super, &sb_mntdata); if (IS_ERR(s)) { error = PTR_ERR(s); goto out_err_nosb; } if (s->s_fs_info != server) { nfs_free_server(server); server = NULL; } if (!s->s_root) { /* initial superblock/root creation */ nfs4_fill_super(s); } mntroot = nfs4_get_root(s, &mntfh); if (IS_ERR(mntroot)) { error = PTR_ERR(mntroot); goto error_splat_super; } if (mntroot->d_inode->i_op != NFS_SB(s)->nfs_client->rpc_ops->dir_inode_ops) { dput(mntroot); error = -ESTALE; goto error_splat_super; } s->s_flags |= MS_ACTIVE; mnt->mnt_sb = s; mnt->mnt_root = mntroot; dprintk("<-- nfs4_referral_get_sb() = 0\n"); return 0;out_err_nosb: nfs_free_server(server);out_err_noserver: dprintk("<-- nfs4_referral_get_sb() = %d [error]\n", error); return error;error_splat_super: up_write(&s->s_umount); deactivate_super(s); dprintk("<-- nfs4_referral_get_sb() = %d [splat]\n", error); return error;}#endif /* CONFIG_NFS_V4 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -