📄 client.c
字号:
* Create a general RPC client */static int nfs_init_server_rpcclient(struct nfs_server *server, rpc_authflavor_t pseudoflavour){ struct nfs_client *clp = server->nfs_client; server->client = rpc_clone_client(clp->cl_rpcclient); if (IS_ERR(server->client)) { dprintk("%s: couldn't create rpc_client!\n", __FUNCTION__); return PTR_ERR(server->client); } if (pseudoflavour != clp->cl_rpcclient->cl_auth->au_flavor) { struct rpc_auth *auth; auth = rpcauth_create(pseudoflavour, server->client); if (IS_ERR(auth)) { dprintk("%s: couldn't create credcache!\n", __FUNCTION__); return PTR_ERR(auth); } } server->client->cl_softrtry = 0; if (server->flags & NFS_MOUNT_SOFT) server->client->cl_softrtry = 1; server->client->cl_intr = 0; if (server->flags & NFS4_MOUNT_INTR) server->client->cl_intr = 1; return 0;}/* * Initialise an NFS2 or NFS3 client */static int nfs_init_client(struct nfs_client *clp, const struct nfs_parsed_mount_data *data){ int error; if (clp->cl_cons_state == NFS_CS_READY) { /* the client is already initialised */ dprintk("<-- nfs_init_client() = 0 [already %p]\n", clp); return 0; } /* Check NFS protocol revision and initialize RPC op vector */ clp->rpc_ops = &nfs_v2_clientops;#ifdef CONFIG_NFS_V3 if (clp->cl_nfsversion == 3) clp->rpc_ops = &nfs_v3_clientops;#endif /* * Create a client RPC handle for doing FSSTAT with UNIX auth only * - RFC 2623, sec 2.3.2 */ error = nfs_create_rpc_client(clp, data->nfs_server.protocol, data->timeo, data->retrans, RPC_AUTH_UNIX, 0); if (error < 0) goto error; nfs_mark_client_ready(clp, NFS_CS_READY); return 0;error: nfs_mark_client_ready(clp, error); dprintk("<-- nfs_init_client() = xerror %d\n", error); return error;}/* * Create a version 2 or 3 client */static int nfs_init_server(struct nfs_server *server, const struct nfs_parsed_mount_data *data){ struct nfs_client *clp; int error, nfsvers = 2; dprintk("--> nfs_init_server()\n");#ifdef CONFIG_NFS_V3 if (data->flags & NFS_MOUNT_VER3) nfsvers = 3;#endif /* Allocate or find a client reference we can use */ clp = nfs_get_client(data->nfs_server.hostname, &data->nfs_server.address, nfsvers); if (IS_ERR(clp)) { dprintk("<-- nfs_init_server() = error %ld\n", PTR_ERR(clp)); return PTR_ERR(clp); } error = nfs_init_client(clp, data); if (error < 0) goto error; server->nfs_client = clp; /* Initialise the client representation from the mount data */ server->flags = data->flags & NFS_MOUNT_FLAGMASK; if (data->rsize) server->rsize = nfs_block_size(data->rsize, NULL); if (data->wsize) server->wsize = nfs_block_size(data->wsize, NULL); server->acregmin = data->acregmin * HZ; server->acregmax = data->acregmax * HZ; server->acdirmin = data->acdirmin * HZ; server->acdirmax = data->acdirmax * HZ; /* Start lockd here, before we might error out */ error = nfs_start_lockd(server); if (error < 0) goto error; error = nfs_init_server_rpcclient(server, data->auth_flavors[0]); if (error < 0) goto error; server->namelen = data->namlen; /* Create a client RPC handle for the NFSv3 ACL management interface */ nfs_init_server_aclclient(server); dprintk("<-- nfs_init_server() = 0 [new %p]\n", clp); return 0;error: server->nfs_client = NULL; nfs_put_client(clp); dprintk("<-- nfs_init_server() = xerror %d\n", error); return error;}/* * Load up the server record from information gained in an fsinfo record */static void nfs_server_set_fsinfo(struct nfs_server *server, struct nfs_fsinfo *fsinfo){ unsigned long max_rpc_payload; /* Work out a lot of parameters */ if (server->rsize == 0) server->rsize = nfs_block_size(fsinfo->rtpref, NULL); if (server->wsize == 0) server->wsize = nfs_block_size(fsinfo->wtpref, NULL); if (fsinfo->rtmax >= 512 && server->rsize > fsinfo->rtmax) server->rsize = nfs_block_size(fsinfo->rtmax, NULL); if (fsinfo->wtmax >= 512 && server->wsize > fsinfo->wtmax) server->wsize = nfs_block_size(fsinfo->wtmax, NULL); max_rpc_payload = nfs_block_size(rpc_max_payload(server->client), NULL); if (server->rsize > max_rpc_payload) server->rsize = max_rpc_payload; if (server->rsize > NFS_MAX_FILE_IO_SIZE) server->rsize = NFS_MAX_FILE_IO_SIZE; server->rpages = (server->rsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; server->backing_dev_info.ra_pages = server->rpages * NFS_MAX_READAHEAD; if (server->wsize > max_rpc_payload) server->wsize = max_rpc_payload; if (server->wsize > NFS_MAX_FILE_IO_SIZE) server->wsize = NFS_MAX_FILE_IO_SIZE; server->wpages = (server->wsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; server->wtmult = nfs_block_bits(fsinfo->wtmult, NULL); server->dtsize = nfs_block_size(fsinfo->dtpref, NULL); if (server->dtsize > PAGE_CACHE_SIZE) server->dtsize = PAGE_CACHE_SIZE; if (server->dtsize > server->rsize) server->dtsize = server->rsize; if (server->flags & NFS_MOUNT_NOAC) { server->acregmin = server->acregmax = 0; server->acdirmin = server->acdirmax = 0; } server->maxfilesize = fsinfo->maxfilesize; /* We're airborne Set socket buffersize */ rpc_setbufsize(server->client, server->wsize + 100, server->rsize + 100);}/* * Probe filesystem information, including the FSID on v2/v3 */static int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *mntfh, struct nfs_fattr *fattr){ struct nfs_fsinfo fsinfo; struct nfs_client *clp = server->nfs_client; int error; dprintk("--> nfs_probe_fsinfo()\n"); if (clp->rpc_ops->set_capabilities != NULL) { error = clp->rpc_ops->set_capabilities(server, mntfh); if (error < 0) goto out_error; } fsinfo.fattr = fattr; nfs_fattr_init(fattr); error = clp->rpc_ops->fsinfo(server, mntfh, &fsinfo); if (error < 0) goto out_error; nfs_server_set_fsinfo(server, &fsinfo); error = bdi_init(&server->backing_dev_info); if (error) goto out_error; /* Get some general file system info */ if (server->namelen == 0) { struct nfs_pathconf pathinfo; pathinfo.fattr = fattr; nfs_fattr_init(fattr); if (clp->rpc_ops->pathconf(server, mntfh, &pathinfo) >= 0) server->namelen = pathinfo.max_namelen; } dprintk("<-- nfs_probe_fsinfo() = 0\n"); return 0;out_error: dprintk("nfs_probe_fsinfo: error = %d\n", -error); return error;}/* * Copy useful information when duplicating a server record */static void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_server *source){ target->flags = source->flags; target->acregmin = source->acregmin; target->acregmax = source->acregmax; target->acdirmin = source->acdirmin; target->acdirmax = source->acdirmax; target->caps = source->caps;}/* * Allocate and initialise a server record */static struct nfs_server *nfs_alloc_server(void){ struct nfs_server *server; server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL); if (!server) return NULL; server->client = server->client_acl = ERR_PTR(-EINVAL); /* Zero out the NFS state stuff */ INIT_LIST_HEAD(&server->client_link); INIT_LIST_HEAD(&server->master_link); server->io_stats = nfs_alloc_iostats(); if (!server->io_stats) { kfree(server); return NULL; } return server;}/* * Free up a server record */void nfs_free_server(struct nfs_server *server){ dprintk("--> nfs_free_server()\n"); spin_lock(&nfs_client_lock); list_del(&server->client_link); list_del(&server->master_link); spin_unlock(&nfs_client_lock); if (server->destroy != NULL) server->destroy(server); if (!IS_ERR(server->client_acl)) rpc_shutdown_client(server->client_acl); if (!IS_ERR(server->client)) rpc_shutdown_client(server->client); nfs_put_client(server->nfs_client); nfs_free_iostats(server->io_stats); bdi_destroy(&server->backing_dev_info); kfree(server); nfs_release_automount_timer(); dprintk("<-- nfs_free_server()\n");}/* * Create a version 2 or 3 volume record * - keyed on server and FSID */struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *data, struct nfs_fh *mntfh){ struct nfs_server *server; struct nfs_fattr fattr; int error; server = nfs_alloc_server(); if (!server) return ERR_PTR(-ENOMEM); /* Get a client representation */ error = nfs_init_server(server, data); if (error < 0) goto error; BUG_ON(!server->nfs_client); BUG_ON(!server->nfs_client->rpc_ops); BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); /* Probe the root fh to retrieve its FSID */ error = nfs_probe_fsinfo(server, mntfh, &fattr); if (error < 0) goto error; if (server->nfs_client->rpc_ops->version == 3) { if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN) server->namelen = NFS3_MAXNAMLEN; if (!(data->flags & NFS_MOUNT_NORDIRPLUS)) server->caps |= NFS_CAP_READDIRPLUS; } else { if (server->namelen == 0 || server->namelen > NFS2_MAXNAMLEN) server->namelen = NFS2_MAXNAMLEN; } if (!(fattr.valid & NFS_ATTR_FATTR)) { error = server->nfs_client->rpc_ops->getattr(server, mntfh, &fattr); if (error < 0) { dprintk("nfs_create_server: getattr error = %d\n", -error); goto error; } } memcpy(&server->fsid, &fattr.fsid, sizeof(server->fsid)); dprintk("Server FSID: %llx:%llx\n", (unsigned long long) server->fsid.major, (unsigned long long) server->fsid.minor); BUG_ON(!server->nfs_client); BUG_ON(!server->nfs_client->rpc_ops); BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); spin_lock(&nfs_client_lock); list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks); list_add_tail(&server->master_link, &nfs_volume_list); spin_unlock(&nfs_client_lock); server->mount_time = jiffies; return server;error: nfs_free_server(server); return ERR_PTR(error);}#ifdef CONFIG_NFS_V4/* * Initialise an NFS4 client record */static int nfs4_init_client(struct nfs_client *clp, int proto, int timeo, int retrans, const char *ip_addr, rpc_authflavor_t authflavour){ int error; if (clp->cl_cons_state == NFS_CS_READY) { /* the client is initialised already */ dprintk("<-- nfs4_init_client() = 0 [already %p]\n", clp); return 0; } /* Check NFS protocol revision and initialize RPC op vector */ clp->rpc_ops = &nfs_v4_clientops; error = nfs_create_rpc_client(clp, proto, timeo, retrans, authflavour, RPC_CLNT_CREATE_DISCRTRY); if (error < 0) goto error; memcpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr)); error = nfs_idmap_new(clp); if (error < 0) { dprintk("%s: failed to create idmapper. Error = %d\n", __FUNCTION__, error); goto error; } __set_bit(NFS_CS_IDMAP, &clp->cl_res_state); nfs_mark_client_ready(clp, NFS_CS_READY); return 0;error: nfs_mark_client_ready(clp, error); dprintk("<-- nfs4_init_client() = xerror %d\n", error); return error;}/* * Set up an NFS4 client */static int nfs4_set_client(struct nfs_server *server, const char *hostname, const struct sockaddr_in *addr, const char *ip_addr, rpc_authflavor_t authflavour, int proto, int timeo, int retrans){ struct nfs_client *clp; int error; dprintk("--> nfs4_set_client()\n"); /* Allocate or find a client reference we can use */ clp = nfs_get_client(hostname, addr, 4); if (IS_ERR(clp)) { error = PTR_ERR(clp); goto error; } error = nfs4_init_client(clp, proto, timeo, retrans, ip_addr, authflavour); if (error < 0) goto error_put; server->nfs_client = clp; dprintk("<-- nfs4_set_client() = 0 [new %p]\n", clp); return 0;error_put: nfs_put_client(clp);error: dprintk("<-- nfs4_set_client() = xerror %d\n", error); return error;}/* * Create a version 4 volume record */static int nfs4_init_server(struct nfs_server *server, const struct nfs_parsed_mount_data *data){ int error; dprintk("--> nfs4_init_server()\n"); /* Initialise the client representation from the mount data */ server->flags = data->flags & NFS_MOUNT_FLAGMASK; server->caps |= NFS_CAP_ATOMIC_OPEN; if (data->rsize) server->rsize = nfs_block_size(data->rsize, NULL); if (data->wsize) server->wsize = nfs_block_size(data->wsize, NULL); server->acregmin = data->acregmin * HZ; server->acregmax = data->acregmax * HZ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -