162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * linux/fs/nfs/proc.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 1992, 1993, 1994 Rick Sladkey 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * OS-independent nfs remote procedure call functions 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * Tuned by Alan Cox <A.Cox@swansea.ac.uk> for >3K buffers 1062306a36Sopenharmony_ci * so at last we can have decent(ish) throughput off a 1162306a36Sopenharmony_ci * Sun server. 1262306a36Sopenharmony_ci * 1362306a36Sopenharmony_ci * Coding optimized and cleaned up by Florian La Roche. 1462306a36Sopenharmony_ci * Note: Error returns are optimized for NFS_OK, which isn't translated via 1562306a36Sopenharmony_ci * nfs_stat_to_errno(), but happens to be already the right return code. 1662306a36Sopenharmony_ci * 1762306a36Sopenharmony_ci * Also, the code currently doesn't check the size of the packet, when 1862306a36Sopenharmony_ci * it decodes the packet. 1962306a36Sopenharmony_ci * 2062306a36Sopenharmony_ci * Feel free to fix it and mail me the diffs if it worries you. 2162306a36Sopenharmony_ci * 2262306a36Sopenharmony_ci * Completely rewritten to support the new RPC call interface; 2362306a36Sopenharmony_ci * rewrote and moved the entire XDR stuff to xdr.c 2462306a36Sopenharmony_ci * --Olaf Kirch June 1996 2562306a36Sopenharmony_ci * 2662306a36Sopenharmony_ci * The code below initializes all auto variables explicitly, otherwise 2762306a36Sopenharmony_ci * it will fail to work as a module (gcc generates a memset call for an 2862306a36Sopenharmony_ci * incomplete struct). 2962306a36Sopenharmony_ci */ 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci#include <linux/types.h> 3262306a36Sopenharmony_ci#include <linux/param.h> 3362306a36Sopenharmony_ci#include <linux/time.h> 3462306a36Sopenharmony_ci#include <linux/mm.h> 3562306a36Sopenharmony_ci#include <linux/errno.h> 3662306a36Sopenharmony_ci#include <linux/string.h> 3762306a36Sopenharmony_ci#include <linux/in.h> 3862306a36Sopenharmony_ci#include <linux/pagemap.h> 3962306a36Sopenharmony_ci#include <linux/sunrpc/clnt.h> 4062306a36Sopenharmony_ci#include <linux/nfs.h> 4162306a36Sopenharmony_ci#include <linux/nfs2.h> 4262306a36Sopenharmony_ci#include <linux/nfs_fs.h> 4362306a36Sopenharmony_ci#include <linux/nfs_page.h> 4462306a36Sopenharmony_ci#include <linux/lockd/bind.h> 4562306a36Sopenharmony_ci#include <linux/freezer.h> 4662306a36Sopenharmony_ci#include "internal.h" 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci#define NFSDBG_FACILITY NFSDBG_PROC 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci/* 5162306a36Sopenharmony_ci * Bare-bones access to getattr: this is for nfs_read_super. 5262306a36Sopenharmony_ci */ 5362306a36Sopenharmony_cistatic int 5462306a36Sopenharmony_cinfs_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, 5562306a36Sopenharmony_ci struct nfs_fsinfo *info) 5662306a36Sopenharmony_ci{ 5762306a36Sopenharmony_ci struct nfs_fattr *fattr = info->fattr; 5862306a36Sopenharmony_ci struct nfs2_fsstat fsinfo; 5962306a36Sopenharmony_ci struct rpc_message msg = { 6062306a36Sopenharmony_ci .rpc_proc = &nfs_procedures[NFSPROC_GETATTR], 6162306a36Sopenharmony_ci .rpc_argp = fhandle, 6262306a36Sopenharmony_ci .rpc_resp = fattr, 6362306a36Sopenharmony_ci }; 6462306a36Sopenharmony_ci int status; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci dprintk("%s: call getattr\n", __func__); 6762306a36Sopenharmony_ci nfs_fattr_init(fattr); 6862306a36Sopenharmony_ci status = rpc_call_sync(server->client, &msg, 0); 6962306a36Sopenharmony_ci /* Retry with default authentication if different */ 7062306a36Sopenharmony_ci if (status && server->nfs_client->cl_rpcclient != server->client) 7162306a36Sopenharmony_ci status = rpc_call_sync(server->nfs_client->cl_rpcclient, &msg, 0); 7262306a36Sopenharmony_ci dprintk("%s: reply getattr: %d\n", __func__, status); 7362306a36Sopenharmony_ci if (status) 7462306a36Sopenharmony_ci return status; 7562306a36Sopenharmony_ci dprintk("%s: call statfs\n", __func__); 7662306a36Sopenharmony_ci msg.rpc_proc = &nfs_procedures[NFSPROC_STATFS]; 7762306a36Sopenharmony_ci msg.rpc_resp = &fsinfo; 7862306a36Sopenharmony_ci status = rpc_call_sync(server->client, &msg, 0); 7962306a36Sopenharmony_ci /* Retry with default authentication if different */ 8062306a36Sopenharmony_ci if (status && server->nfs_client->cl_rpcclient != server->client) 8162306a36Sopenharmony_ci status = rpc_call_sync(server->nfs_client->cl_rpcclient, &msg, 0); 8262306a36Sopenharmony_ci dprintk("%s: reply statfs: %d\n", __func__, status); 8362306a36Sopenharmony_ci if (status) 8462306a36Sopenharmony_ci return status; 8562306a36Sopenharmony_ci info->rtmax = NFS_MAXDATA; 8662306a36Sopenharmony_ci info->rtpref = fsinfo.tsize; 8762306a36Sopenharmony_ci info->rtmult = fsinfo.bsize; 8862306a36Sopenharmony_ci info->wtmax = NFS_MAXDATA; 8962306a36Sopenharmony_ci info->wtpref = fsinfo.tsize; 9062306a36Sopenharmony_ci info->wtmult = fsinfo.bsize; 9162306a36Sopenharmony_ci info->dtpref = fsinfo.tsize; 9262306a36Sopenharmony_ci info->maxfilesize = 0x7FFFFFFF; 9362306a36Sopenharmony_ci info->lease_time = 0; 9462306a36Sopenharmony_ci info->change_attr_type = NFS4_CHANGE_TYPE_IS_UNDEFINED; 9562306a36Sopenharmony_ci info->xattr_support = 0; 9662306a36Sopenharmony_ci return 0; 9762306a36Sopenharmony_ci} 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci/* 10062306a36Sopenharmony_ci * One function for each procedure in the NFS protocol. 10162306a36Sopenharmony_ci */ 10262306a36Sopenharmony_cistatic int 10362306a36Sopenharmony_cinfs_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, 10462306a36Sopenharmony_ci struct nfs_fattr *fattr, struct inode *inode) 10562306a36Sopenharmony_ci{ 10662306a36Sopenharmony_ci struct rpc_message msg = { 10762306a36Sopenharmony_ci .rpc_proc = &nfs_procedures[NFSPROC_GETATTR], 10862306a36Sopenharmony_ci .rpc_argp = fhandle, 10962306a36Sopenharmony_ci .rpc_resp = fattr, 11062306a36Sopenharmony_ci }; 11162306a36Sopenharmony_ci int status; 11262306a36Sopenharmony_ci unsigned short task_flags = 0; 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci /* Is this is an attribute revalidation, subject to softreval? */ 11562306a36Sopenharmony_ci if (inode && (server->flags & NFS_MOUNT_SOFTREVAL)) 11662306a36Sopenharmony_ci task_flags |= RPC_TASK_TIMEOUT; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci dprintk("NFS call getattr\n"); 11962306a36Sopenharmony_ci nfs_fattr_init(fattr); 12062306a36Sopenharmony_ci status = rpc_call_sync(server->client, &msg, task_flags); 12162306a36Sopenharmony_ci dprintk("NFS reply getattr: %d\n", status); 12262306a36Sopenharmony_ci return status; 12362306a36Sopenharmony_ci} 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_cistatic int 12662306a36Sopenharmony_cinfs_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, 12762306a36Sopenharmony_ci struct iattr *sattr) 12862306a36Sopenharmony_ci{ 12962306a36Sopenharmony_ci struct inode *inode = d_inode(dentry); 13062306a36Sopenharmony_ci struct nfs_sattrargs arg = { 13162306a36Sopenharmony_ci .fh = NFS_FH(inode), 13262306a36Sopenharmony_ci .sattr = sattr 13362306a36Sopenharmony_ci }; 13462306a36Sopenharmony_ci struct rpc_message msg = { 13562306a36Sopenharmony_ci .rpc_proc = &nfs_procedures[NFSPROC_SETATTR], 13662306a36Sopenharmony_ci .rpc_argp = &arg, 13762306a36Sopenharmony_ci .rpc_resp = fattr, 13862306a36Sopenharmony_ci }; 13962306a36Sopenharmony_ci int status; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci /* Mask out the non-modebit related stuff from attr->ia_mode */ 14262306a36Sopenharmony_ci sattr->ia_mode &= S_IALLUGO; 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci dprintk("NFS call setattr\n"); 14562306a36Sopenharmony_ci if (sattr->ia_valid & ATTR_FILE) 14662306a36Sopenharmony_ci msg.rpc_cred = nfs_file_cred(sattr->ia_file); 14762306a36Sopenharmony_ci nfs_fattr_init(fattr); 14862306a36Sopenharmony_ci status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); 14962306a36Sopenharmony_ci if (status == 0) 15062306a36Sopenharmony_ci nfs_setattr_update_inode(inode, sattr, fattr); 15162306a36Sopenharmony_ci dprintk("NFS reply setattr: %d\n", status); 15262306a36Sopenharmony_ci return status; 15362306a36Sopenharmony_ci} 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_cistatic int 15662306a36Sopenharmony_cinfs_proc_lookup(struct inode *dir, struct dentry *dentry, 15762306a36Sopenharmony_ci struct nfs_fh *fhandle, struct nfs_fattr *fattr) 15862306a36Sopenharmony_ci{ 15962306a36Sopenharmony_ci struct nfs_diropargs arg = { 16062306a36Sopenharmony_ci .fh = NFS_FH(dir), 16162306a36Sopenharmony_ci .name = dentry->d_name.name, 16262306a36Sopenharmony_ci .len = dentry->d_name.len 16362306a36Sopenharmony_ci }; 16462306a36Sopenharmony_ci struct nfs_diropok res = { 16562306a36Sopenharmony_ci .fh = fhandle, 16662306a36Sopenharmony_ci .fattr = fattr 16762306a36Sopenharmony_ci }; 16862306a36Sopenharmony_ci struct rpc_message msg = { 16962306a36Sopenharmony_ci .rpc_proc = &nfs_procedures[NFSPROC_LOOKUP], 17062306a36Sopenharmony_ci .rpc_argp = &arg, 17162306a36Sopenharmony_ci .rpc_resp = &res, 17262306a36Sopenharmony_ci }; 17362306a36Sopenharmony_ci int status; 17462306a36Sopenharmony_ci unsigned short task_flags = 0; 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci /* Is this is an attribute revalidation, subject to softreval? */ 17762306a36Sopenharmony_ci if (nfs_lookup_is_soft_revalidate(dentry)) 17862306a36Sopenharmony_ci task_flags |= RPC_TASK_TIMEOUT; 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci dprintk("NFS call lookup %pd2\n", dentry); 18162306a36Sopenharmony_ci nfs_fattr_init(fattr); 18262306a36Sopenharmony_ci status = rpc_call_sync(NFS_CLIENT(dir), &msg, task_flags); 18362306a36Sopenharmony_ci dprintk("NFS reply lookup: %d\n", status); 18462306a36Sopenharmony_ci return status; 18562306a36Sopenharmony_ci} 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_cistatic int nfs_proc_readlink(struct inode *inode, struct page *page, 18862306a36Sopenharmony_ci unsigned int pgbase, unsigned int pglen) 18962306a36Sopenharmony_ci{ 19062306a36Sopenharmony_ci struct nfs_readlinkargs args = { 19162306a36Sopenharmony_ci .fh = NFS_FH(inode), 19262306a36Sopenharmony_ci .pgbase = pgbase, 19362306a36Sopenharmony_ci .pglen = pglen, 19462306a36Sopenharmony_ci .pages = &page 19562306a36Sopenharmony_ci }; 19662306a36Sopenharmony_ci struct rpc_message msg = { 19762306a36Sopenharmony_ci .rpc_proc = &nfs_procedures[NFSPROC_READLINK], 19862306a36Sopenharmony_ci .rpc_argp = &args, 19962306a36Sopenharmony_ci }; 20062306a36Sopenharmony_ci int status; 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci dprintk("NFS call readlink\n"); 20362306a36Sopenharmony_ci status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); 20462306a36Sopenharmony_ci dprintk("NFS reply readlink: %d\n", status); 20562306a36Sopenharmony_ci return status; 20662306a36Sopenharmony_ci} 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_cistruct nfs_createdata { 20962306a36Sopenharmony_ci struct nfs_createargs arg; 21062306a36Sopenharmony_ci struct nfs_diropok res; 21162306a36Sopenharmony_ci struct nfs_fh fhandle; 21262306a36Sopenharmony_ci struct nfs_fattr fattr; 21362306a36Sopenharmony_ci}; 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_cistatic struct nfs_createdata *nfs_alloc_createdata(struct inode *dir, 21662306a36Sopenharmony_ci struct dentry *dentry, struct iattr *sattr) 21762306a36Sopenharmony_ci{ 21862306a36Sopenharmony_ci struct nfs_createdata *data; 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci data = kmalloc(sizeof(*data), GFP_KERNEL); 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci if (data != NULL) { 22362306a36Sopenharmony_ci data->arg.fh = NFS_FH(dir); 22462306a36Sopenharmony_ci data->arg.name = dentry->d_name.name; 22562306a36Sopenharmony_ci data->arg.len = dentry->d_name.len; 22662306a36Sopenharmony_ci data->arg.sattr = sattr; 22762306a36Sopenharmony_ci nfs_fattr_init(&data->fattr); 22862306a36Sopenharmony_ci data->fhandle.size = 0; 22962306a36Sopenharmony_ci data->res.fh = &data->fhandle; 23062306a36Sopenharmony_ci data->res.fattr = &data->fattr; 23162306a36Sopenharmony_ci } 23262306a36Sopenharmony_ci return data; 23362306a36Sopenharmony_ci}; 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_cistatic void nfs_free_createdata(const struct nfs_createdata *data) 23662306a36Sopenharmony_ci{ 23762306a36Sopenharmony_ci kfree(data); 23862306a36Sopenharmony_ci} 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_cistatic int 24162306a36Sopenharmony_cinfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, 24262306a36Sopenharmony_ci int flags) 24362306a36Sopenharmony_ci{ 24462306a36Sopenharmony_ci struct nfs_createdata *data; 24562306a36Sopenharmony_ci struct rpc_message msg = { 24662306a36Sopenharmony_ci .rpc_proc = &nfs_procedures[NFSPROC_CREATE], 24762306a36Sopenharmony_ci }; 24862306a36Sopenharmony_ci int status = -ENOMEM; 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci dprintk("NFS call create %pd\n", dentry); 25162306a36Sopenharmony_ci data = nfs_alloc_createdata(dir, dentry, sattr); 25262306a36Sopenharmony_ci if (data == NULL) 25362306a36Sopenharmony_ci goto out; 25462306a36Sopenharmony_ci msg.rpc_argp = &data->arg; 25562306a36Sopenharmony_ci msg.rpc_resp = &data->res; 25662306a36Sopenharmony_ci status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); 25762306a36Sopenharmony_ci nfs_mark_for_revalidate(dir); 25862306a36Sopenharmony_ci if (status == 0) 25962306a36Sopenharmony_ci status = nfs_instantiate(dentry, data->res.fh, data->res.fattr); 26062306a36Sopenharmony_ci nfs_free_createdata(data); 26162306a36Sopenharmony_ciout: 26262306a36Sopenharmony_ci dprintk("NFS reply create: %d\n", status); 26362306a36Sopenharmony_ci return status; 26462306a36Sopenharmony_ci} 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci/* 26762306a36Sopenharmony_ci * In NFSv2, mknod is grafted onto the create call. 26862306a36Sopenharmony_ci */ 26962306a36Sopenharmony_cistatic int 27062306a36Sopenharmony_cinfs_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr, 27162306a36Sopenharmony_ci dev_t rdev) 27262306a36Sopenharmony_ci{ 27362306a36Sopenharmony_ci struct nfs_createdata *data; 27462306a36Sopenharmony_ci struct rpc_message msg = { 27562306a36Sopenharmony_ci .rpc_proc = &nfs_procedures[NFSPROC_CREATE], 27662306a36Sopenharmony_ci }; 27762306a36Sopenharmony_ci umode_t mode; 27862306a36Sopenharmony_ci int status = -ENOMEM; 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci dprintk("NFS call mknod %pd\n", dentry); 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci mode = sattr->ia_mode; 28362306a36Sopenharmony_ci if (S_ISFIFO(mode)) { 28462306a36Sopenharmony_ci sattr->ia_mode = (mode & ~S_IFMT) | S_IFCHR; 28562306a36Sopenharmony_ci sattr->ia_valid &= ~ATTR_SIZE; 28662306a36Sopenharmony_ci } else if (S_ISCHR(mode) || S_ISBLK(mode)) { 28762306a36Sopenharmony_ci sattr->ia_valid |= ATTR_SIZE; 28862306a36Sopenharmony_ci sattr->ia_size = new_encode_dev(rdev);/* get out your barf bag */ 28962306a36Sopenharmony_ci } 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci data = nfs_alloc_createdata(dir, dentry, sattr); 29262306a36Sopenharmony_ci if (data == NULL) 29362306a36Sopenharmony_ci goto out; 29462306a36Sopenharmony_ci msg.rpc_argp = &data->arg; 29562306a36Sopenharmony_ci msg.rpc_resp = &data->res; 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); 29862306a36Sopenharmony_ci nfs_mark_for_revalidate(dir); 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci if (status == -EINVAL && S_ISFIFO(mode)) { 30162306a36Sopenharmony_ci sattr->ia_mode = mode; 30262306a36Sopenharmony_ci nfs_fattr_init(data->res.fattr); 30362306a36Sopenharmony_ci status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); 30462306a36Sopenharmony_ci } 30562306a36Sopenharmony_ci if (status == 0) 30662306a36Sopenharmony_ci status = nfs_instantiate(dentry, data->res.fh, data->res.fattr); 30762306a36Sopenharmony_ci nfs_free_createdata(data); 30862306a36Sopenharmony_ciout: 30962306a36Sopenharmony_ci dprintk("NFS reply mknod: %d\n", status); 31062306a36Sopenharmony_ci return status; 31162306a36Sopenharmony_ci} 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_cistatic int 31462306a36Sopenharmony_cinfs_proc_remove(struct inode *dir, struct dentry *dentry) 31562306a36Sopenharmony_ci{ 31662306a36Sopenharmony_ci struct nfs_removeargs arg = { 31762306a36Sopenharmony_ci .fh = NFS_FH(dir), 31862306a36Sopenharmony_ci .name = dentry->d_name, 31962306a36Sopenharmony_ci }; 32062306a36Sopenharmony_ci struct rpc_message msg = { 32162306a36Sopenharmony_ci .rpc_proc = &nfs_procedures[NFSPROC_REMOVE], 32262306a36Sopenharmony_ci .rpc_argp = &arg, 32362306a36Sopenharmony_ci }; 32462306a36Sopenharmony_ci int status; 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci dprintk("NFS call remove %pd2\n",dentry); 32762306a36Sopenharmony_ci status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); 32862306a36Sopenharmony_ci nfs_mark_for_revalidate(dir); 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci dprintk("NFS reply remove: %d\n", status); 33162306a36Sopenharmony_ci return status; 33262306a36Sopenharmony_ci} 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_cistatic void 33562306a36Sopenharmony_cinfs_proc_unlink_setup(struct rpc_message *msg, 33662306a36Sopenharmony_ci struct dentry *dentry, 33762306a36Sopenharmony_ci struct inode *inode) 33862306a36Sopenharmony_ci{ 33962306a36Sopenharmony_ci msg->rpc_proc = &nfs_procedures[NFSPROC_REMOVE]; 34062306a36Sopenharmony_ci} 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_cistatic void nfs_proc_unlink_rpc_prepare(struct rpc_task *task, struct nfs_unlinkdata *data) 34362306a36Sopenharmony_ci{ 34462306a36Sopenharmony_ci rpc_call_start(task); 34562306a36Sopenharmony_ci} 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_cistatic int nfs_proc_unlink_done(struct rpc_task *task, struct inode *dir) 34862306a36Sopenharmony_ci{ 34962306a36Sopenharmony_ci nfs_mark_for_revalidate(dir); 35062306a36Sopenharmony_ci return 1; 35162306a36Sopenharmony_ci} 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_cistatic void 35462306a36Sopenharmony_cinfs_proc_rename_setup(struct rpc_message *msg, 35562306a36Sopenharmony_ci struct dentry *old_dentry, 35662306a36Sopenharmony_ci struct dentry *new_dentry) 35762306a36Sopenharmony_ci{ 35862306a36Sopenharmony_ci msg->rpc_proc = &nfs_procedures[NFSPROC_RENAME]; 35962306a36Sopenharmony_ci} 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_cistatic void nfs_proc_rename_rpc_prepare(struct rpc_task *task, struct nfs_renamedata *data) 36262306a36Sopenharmony_ci{ 36362306a36Sopenharmony_ci rpc_call_start(task); 36462306a36Sopenharmony_ci} 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_cistatic int 36762306a36Sopenharmony_cinfs_proc_rename_done(struct rpc_task *task, struct inode *old_dir, 36862306a36Sopenharmony_ci struct inode *new_dir) 36962306a36Sopenharmony_ci{ 37062306a36Sopenharmony_ci nfs_mark_for_revalidate(old_dir); 37162306a36Sopenharmony_ci nfs_mark_for_revalidate(new_dir); 37262306a36Sopenharmony_ci return 1; 37362306a36Sopenharmony_ci} 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_cistatic int 37662306a36Sopenharmony_cinfs_proc_link(struct inode *inode, struct inode *dir, const struct qstr *name) 37762306a36Sopenharmony_ci{ 37862306a36Sopenharmony_ci struct nfs_linkargs arg = { 37962306a36Sopenharmony_ci .fromfh = NFS_FH(inode), 38062306a36Sopenharmony_ci .tofh = NFS_FH(dir), 38162306a36Sopenharmony_ci .toname = name->name, 38262306a36Sopenharmony_ci .tolen = name->len 38362306a36Sopenharmony_ci }; 38462306a36Sopenharmony_ci struct rpc_message msg = { 38562306a36Sopenharmony_ci .rpc_proc = &nfs_procedures[NFSPROC_LINK], 38662306a36Sopenharmony_ci .rpc_argp = &arg, 38762306a36Sopenharmony_ci }; 38862306a36Sopenharmony_ci int status; 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci dprintk("NFS call link %s\n", name->name); 39162306a36Sopenharmony_ci status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); 39262306a36Sopenharmony_ci nfs_mark_for_revalidate(inode); 39362306a36Sopenharmony_ci nfs_mark_for_revalidate(dir); 39462306a36Sopenharmony_ci dprintk("NFS reply link: %d\n", status); 39562306a36Sopenharmony_ci return status; 39662306a36Sopenharmony_ci} 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_cistatic int 39962306a36Sopenharmony_cinfs_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page, 40062306a36Sopenharmony_ci unsigned int len, struct iattr *sattr) 40162306a36Sopenharmony_ci{ 40262306a36Sopenharmony_ci struct nfs_fh *fh; 40362306a36Sopenharmony_ci struct nfs_fattr *fattr; 40462306a36Sopenharmony_ci struct nfs_symlinkargs arg = { 40562306a36Sopenharmony_ci .fromfh = NFS_FH(dir), 40662306a36Sopenharmony_ci .fromname = dentry->d_name.name, 40762306a36Sopenharmony_ci .fromlen = dentry->d_name.len, 40862306a36Sopenharmony_ci .pages = &page, 40962306a36Sopenharmony_ci .pathlen = len, 41062306a36Sopenharmony_ci .sattr = sattr 41162306a36Sopenharmony_ci }; 41262306a36Sopenharmony_ci struct rpc_message msg = { 41362306a36Sopenharmony_ci .rpc_proc = &nfs_procedures[NFSPROC_SYMLINK], 41462306a36Sopenharmony_ci .rpc_argp = &arg, 41562306a36Sopenharmony_ci }; 41662306a36Sopenharmony_ci int status = -ENAMETOOLONG; 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci dprintk("NFS call symlink %pd\n", dentry); 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci if (len > NFS2_MAXPATHLEN) 42162306a36Sopenharmony_ci goto out; 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci fh = nfs_alloc_fhandle(); 42462306a36Sopenharmony_ci fattr = nfs_alloc_fattr(); 42562306a36Sopenharmony_ci status = -ENOMEM; 42662306a36Sopenharmony_ci if (fh == NULL || fattr == NULL) 42762306a36Sopenharmony_ci goto out_free; 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); 43062306a36Sopenharmony_ci nfs_mark_for_revalidate(dir); 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci /* 43362306a36Sopenharmony_ci * V2 SYMLINK requests don't return any attributes. Setting the 43462306a36Sopenharmony_ci * filehandle size to zero indicates to nfs_instantiate that it 43562306a36Sopenharmony_ci * should fill in the data with a LOOKUP call on the wire. 43662306a36Sopenharmony_ci */ 43762306a36Sopenharmony_ci if (status == 0) 43862306a36Sopenharmony_ci status = nfs_instantiate(dentry, fh, fattr); 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ciout_free: 44162306a36Sopenharmony_ci nfs_free_fattr(fattr); 44262306a36Sopenharmony_ci nfs_free_fhandle(fh); 44362306a36Sopenharmony_ciout: 44462306a36Sopenharmony_ci dprintk("NFS reply symlink: %d\n", status); 44562306a36Sopenharmony_ci return status; 44662306a36Sopenharmony_ci} 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_cistatic int 44962306a36Sopenharmony_cinfs_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr) 45062306a36Sopenharmony_ci{ 45162306a36Sopenharmony_ci struct nfs_createdata *data; 45262306a36Sopenharmony_ci struct rpc_message msg = { 45362306a36Sopenharmony_ci .rpc_proc = &nfs_procedures[NFSPROC_MKDIR], 45462306a36Sopenharmony_ci }; 45562306a36Sopenharmony_ci int status = -ENOMEM; 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci dprintk("NFS call mkdir %pd\n", dentry); 45862306a36Sopenharmony_ci data = nfs_alloc_createdata(dir, dentry, sattr); 45962306a36Sopenharmony_ci if (data == NULL) 46062306a36Sopenharmony_ci goto out; 46162306a36Sopenharmony_ci msg.rpc_argp = &data->arg; 46262306a36Sopenharmony_ci msg.rpc_resp = &data->res; 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); 46562306a36Sopenharmony_ci nfs_mark_for_revalidate(dir); 46662306a36Sopenharmony_ci if (status == 0) 46762306a36Sopenharmony_ci status = nfs_instantiate(dentry, data->res.fh, data->res.fattr); 46862306a36Sopenharmony_ci nfs_free_createdata(data); 46962306a36Sopenharmony_ciout: 47062306a36Sopenharmony_ci dprintk("NFS reply mkdir: %d\n", status); 47162306a36Sopenharmony_ci return status; 47262306a36Sopenharmony_ci} 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_cistatic int 47562306a36Sopenharmony_cinfs_proc_rmdir(struct inode *dir, const struct qstr *name) 47662306a36Sopenharmony_ci{ 47762306a36Sopenharmony_ci struct nfs_diropargs arg = { 47862306a36Sopenharmony_ci .fh = NFS_FH(dir), 47962306a36Sopenharmony_ci .name = name->name, 48062306a36Sopenharmony_ci .len = name->len 48162306a36Sopenharmony_ci }; 48262306a36Sopenharmony_ci struct rpc_message msg = { 48362306a36Sopenharmony_ci .rpc_proc = &nfs_procedures[NFSPROC_RMDIR], 48462306a36Sopenharmony_ci .rpc_argp = &arg, 48562306a36Sopenharmony_ci }; 48662306a36Sopenharmony_ci int status; 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_ci dprintk("NFS call rmdir %s\n", name->name); 48962306a36Sopenharmony_ci status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); 49062306a36Sopenharmony_ci nfs_mark_for_revalidate(dir); 49162306a36Sopenharmony_ci dprintk("NFS reply rmdir: %d\n", status); 49262306a36Sopenharmony_ci return status; 49362306a36Sopenharmony_ci} 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci/* 49662306a36Sopenharmony_ci * The READDIR implementation is somewhat hackish - we pass a temporary 49762306a36Sopenharmony_ci * buffer to the encode function, which installs it in the receive 49862306a36Sopenharmony_ci * the receive iovec. The decode function just parses the reply to make 49962306a36Sopenharmony_ci * sure it is syntactically correct; the entries itself are decoded 50062306a36Sopenharmony_ci * from nfs_readdir by calling the decode_entry function directly. 50162306a36Sopenharmony_ci */ 50262306a36Sopenharmony_cistatic int nfs_proc_readdir(struct nfs_readdir_arg *nr_arg, 50362306a36Sopenharmony_ci struct nfs_readdir_res *nr_res) 50462306a36Sopenharmony_ci{ 50562306a36Sopenharmony_ci struct inode *dir = d_inode(nr_arg->dentry); 50662306a36Sopenharmony_ci struct nfs_readdirargs arg = { 50762306a36Sopenharmony_ci .fh = NFS_FH(dir), 50862306a36Sopenharmony_ci .cookie = nr_arg->cookie, 50962306a36Sopenharmony_ci .count = nr_arg->page_len, 51062306a36Sopenharmony_ci .pages = nr_arg->pages, 51162306a36Sopenharmony_ci }; 51262306a36Sopenharmony_ci struct rpc_message msg = { 51362306a36Sopenharmony_ci .rpc_proc = &nfs_procedures[NFSPROC_READDIR], 51462306a36Sopenharmony_ci .rpc_argp = &arg, 51562306a36Sopenharmony_ci .rpc_cred = nr_arg->cred, 51662306a36Sopenharmony_ci }; 51762306a36Sopenharmony_ci int status; 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ci dprintk("NFS call readdir %llu\n", (unsigned long long)nr_arg->cookie); 52062306a36Sopenharmony_ci status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); 52162306a36Sopenharmony_ci nr_res->verf[0] = nr_res->verf[1] = 0; 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_ci nfs_invalidate_atime(dir); 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci dprintk("NFS reply readdir: %d\n", status); 52662306a36Sopenharmony_ci return status; 52762306a36Sopenharmony_ci} 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_cistatic int 53062306a36Sopenharmony_cinfs_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, 53162306a36Sopenharmony_ci struct nfs_fsstat *stat) 53262306a36Sopenharmony_ci{ 53362306a36Sopenharmony_ci struct nfs2_fsstat fsinfo; 53462306a36Sopenharmony_ci struct rpc_message msg = { 53562306a36Sopenharmony_ci .rpc_proc = &nfs_procedures[NFSPROC_STATFS], 53662306a36Sopenharmony_ci .rpc_argp = fhandle, 53762306a36Sopenharmony_ci .rpc_resp = &fsinfo, 53862306a36Sopenharmony_ci }; 53962306a36Sopenharmony_ci int status; 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci dprintk("NFS call statfs\n"); 54262306a36Sopenharmony_ci nfs_fattr_init(stat->fattr); 54362306a36Sopenharmony_ci status = rpc_call_sync(server->client, &msg, 0); 54462306a36Sopenharmony_ci dprintk("NFS reply statfs: %d\n", status); 54562306a36Sopenharmony_ci if (status) 54662306a36Sopenharmony_ci goto out; 54762306a36Sopenharmony_ci stat->tbytes = (u64)fsinfo.blocks * fsinfo.bsize; 54862306a36Sopenharmony_ci stat->fbytes = (u64)fsinfo.bfree * fsinfo.bsize; 54962306a36Sopenharmony_ci stat->abytes = (u64)fsinfo.bavail * fsinfo.bsize; 55062306a36Sopenharmony_ci stat->tfiles = 0; 55162306a36Sopenharmony_ci stat->ffiles = 0; 55262306a36Sopenharmony_ci stat->afiles = 0; 55362306a36Sopenharmony_ciout: 55462306a36Sopenharmony_ci return status; 55562306a36Sopenharmony_ci} 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_cistatic int 55862306a36Sopenharmony_cinfs_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, 55962306a36Sopenharmony_ci struct nfs_fsinfo *info) 56062306a36Sopenharmony_ci{ 56162306a36Sopenharmony_ci struct nfs2_fsstat fsinfo; 56262306a36Sopenharmony_ci struct rpc_message msg = { 56362306a36Sopenharmony_ci .rpc_proc = &nfs_procedures[NFSPROC_STATFS], 56462306a36Sopenharmony_ci .rpc_argp = fhandle, 56562306a36Sopenharmony_ci .rpc_resp = &fsinfo, 56662306a36Sopenharmony_ci }; 56762306a36Sopenharmony_ci int status; 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci dprintk("NFS call fsinfo\n"); 57062306a36Sopenharmony_ci nfs_fattr_init(info->fattr); 57162306a36Sopenharmony_ci status = rpc_call_sync(server->client, &msg, 0); 57262306a36Sopenharmony_ci dprintk("NFS reply fsinfo: %d\n", status); 57362306a36Sopenharmony_ci if (status) 57462306a36Sopenharmony_ci goto out; 57562306a36Sopenharmony_ci info->rtmax = NFS_MAXDATA; 57662306a36Sopenharmony_ci info->rtpref = fsinfo.tsize; 57762306a36Sopenharmony_ci info->rtmult = fsinfo.bsize; 57862306a36Sopenharmony_ci info->wtmax = NFS_MAXDATA; 57962306a36Sopenharmony_ci info->wtpref = fsinfo.tsize; 58062306a36Sopenharmony_ci info->wtmult = fsinfo.bsize; 58162306a36Sopenharmony_ci info->dtpref = fsinfo.tsize; 58262306a36Sopenharmony_ci info->maxfilesize = 0x7FFFFFFF; 58362306a36Sopenharmony_ci info->lease_time = 0; 58462306a36Sopenharmony_ciout: 58562306a36Sopenharmony_ci return status; 58662306a36Sopenharmony_ci} 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_cistatic int 58962306a36Sopenharmony_cinfs_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, 59062306a36Sopenharmony_ci struct nfs_pathconf *info) 59162306a36Sopenharmony_ci{ 59262306a36Sopenharmony_ci info->max_link = 0; 59362306a36Sopenharmony_ci info->max_namelen = NFS2_MAXNAMLEN; 59462306a36Sopenharmony_ci return 0; 59562306a36Sopenharmony_ci} 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_cistatic int nfs_read_done(struct rpc_task *task, struct nfs_pgio_header *hdr) 59862306a36Sopenharmony_ci{ 59962306a36Sopenharmony_ci struct inode *inode = hdr->inode; 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ci nfs_invalidate_atime(inode); 60262306a36Sopenharmony_ci if (task->tk_status >= 0) { 60362306a36Sopenharmony_ci nfs_refresh_inode(inode, hdr->res.fattr); 60462306a36Sopenharmony_ci /* Emulate the eof flag, which isn't normally needed in NFSv2 60562306a36Sopenharmony_ci * as it is guaranteed to always return the file attributes 60662306a36Sopenharmony_ci */ 60762306a36Sopenharmony_ci if ((hdr->res.count == 0 && hdr->args.count > 0) || 60862306a36Sopenharmony_ci hdr->args.offset + hdr->res.count >= hdr->res.fattr->size) 60962306a36Sopenharmony_ci hdr->res.eof = 1; 61062306a36Sopenharmony_ci } 61162306a36Sopenharmony_ci return 0; 61262306a36Sopenharmony_ci} 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_cistatic void nfs_proc_read_setup(struct nfs_pgio_header *hdr, 61562306a36Sopenharmony_ci struct rpc_message *msg) 61662306a36Sopenharmony_ci{ 61762306a36Sopenharmony_ci msg->rpc_proc = &nfs_procedures[NFSPROC_READ]; 61862306a36Sopenharmony_ci} 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_cistatic int nfs_proc_pgio_rpc_prepare(struct rpc_task *task, 62162306a36Sopenharmony_ci struct nfs_pgio_header *hdr) 62262306a36Sopenharmony_ci{ 62362306a36Sopenharmony_ci rpc_call_start(task); 62462306a36Sopenharmony_ci return 0; 62562306a36Sopenharmony_ci} 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_cistatic int nfs_write_done(struct rpc_task *task, struct nfs_pgio_header *hdr) 62862306a36Sopenharmony_ci{ 62962306a36Sopenharmony_ci if (task->tk_status >= 0) { 63062306a36Sopenharmony_ci hdr->res.count = hdr->args.count; 63162306a36Sopenharmony_ci nfs_writeback_update_inode(hdr); 63262306a36Sopenharmony_ci } 63362306a36Sopenharmony_ci return 0; 63462306a36Sopenharmony_ci} 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_cistatic void nfs_proc_write_setup(struct nfs_pgio_header *hdr, 63762306a36Sopenharmony_ci struct rpc_message *msg, 63862306a36Sopenharmony_ci struct rpc_clnt **clnt) 63962306a36Sopenharmony_ci{ 64062306a36Sopenharmony_ci /* Note: NFSv2 ignores @stable and always uses NFS_FILE_SYNC */ 64162306a36Sopenharmony_ci hdr->args.stable = NFS_FILE_SYNC; 64262306a36Sopenharmony_ci msg->rpc_proc = &nfs_procedures[NFSPROC_WRITE]; 64362306a36Sopenharmony_ci} 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_cistatic void nfs_proc_commit_rpc_prepare(struct rpc_task *task, struct nfs_commit_data *data) 64662306a36Sopenharmony_ci{ 64762306a36Sopenharmony_ci BUG(); 64862306a36Sopenharmony_ci} 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_cistatic void 65162306a36Sopenharmony_cinfs_proc_commit_setup(struct nfs_commit_data *data, struct rpc_message *msg, 65262306a36Sopenharmony_ci struct rpc_clnt **clnt) 65362306a36Sopenharmony_ci{ 65462306a36Sopenharmony_ci BUG(); 65562306a36Sopenharmony_ci} 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_cistatic int 65862306a36Sopenharmony_cinfs_proc_lock(struct file *filp, int cmd, struct file_lock *fl) 65962306a36Sopenharmony_ci{ 66062306a36Sopenharmony_ci struct inode *inode = file_inode(filp); 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_ci return nlmclnt_proc(NFS_SERVER(inode)->nlm_host, cmd, fl, NULL); 66362306a36Sopenharmony_ci} 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_ci/* Helper functions for NFS lock bounds checking */ 66662306a36Sopenharmony_ci#define NFS_LOCK32_OFFSET_MAX ((__s32)0x7fffffffUL) 66762306a36Sopenharmony_cistatic int nfs_lock_check_bounds(const struct file_lock *fl) 66862306a36Sopenharmony_ci{ 66962306a36Sopenharmony_ci __s32 start, end; 67062306a36Sopenharmony_ci 67162306a36Sopenharmony_ci start = (__s32)fl->fl_start; 67262306a36Sopenharmony_ci if ((loff_t)start != fl->fl_start) 67362306a36Sopenharmony_ci goto out_einval; 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci if (fl->fl_end != OFFSET_MAX) { 67662306a36Sopenharmony_ci end = (__s32)fl->fl_end; 67762306a36Sopenharmony_ci if ((loff_t)end != fl->fl_end) 67862306a36Sopenharmony_ci goto out_einval; 67962306a36Sopenharmony_ci } else 68062306a36Sopenharmony_ci end = NFS_LOCK32_OFFSET_MAX; 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_ci if (start < 0 || start > end) 68362306a36Sopenharmony_ci goto out_einval; 68462306a36Sopenharmony_ci return 0; 68562306a36Sopenharmony_ciout_einval: 68662306a36Sopenharmony_ci return -EINVAL; 68762306a36Sopenharmony_ci} 68862306a36Sopenharmony_ci 68962306a36Sopenharmony_cistatic int nfs_have_delegation(struct inode *inode, fmode_t flags) 69062306a36Sopenharmony_ci{ 69162306a36Sopenharmony_ci return 0; 69262306a36Sopenharmony_ci} 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_cistatic const struct inode_operations nfs_dir_inode_operations = { 69562306a36Sopenharmony_ci .create = nfs_create, 69662306a36Sopenharmony_ci .lookup = nfs_lookup, 69762306a36Sopenharmony_ci .link = nfs_link, 69862306a36Sopenharmony_ci .unlink = nfs_unlink, 69962306a36Sopenharmony_ci .symlink = nfs_symlink, 70062306a36Sopenharmony_ci .mkdir = nfs_mkdir, 70162306a36Sopenharmony_ci .rmdir = nfs_rmdir, 70262306a36Sopenharmony_ci .mknod = nfs_mknod, 70362306a36Sopenharmony_ci .rename = nfs_rename, 70462306a36Sopenharmony_ci .permission = nfs_permission, 70562306a36Sopenharmony_ci .getattr = nfs_getattr, 70662306a36Sopenharmony_ci .setattr = nfs_setattr, 70762306a36Sopenharmony_ci}; 70862306a36Sopenharmony_ci 70962306a36Sopenharmony_cistatic const struct inode_operations nfs_file_inode_operations = { 71062306a36Sopenharmony_ci .permission = nfs_permission, 71162306a36Sopenharmony_ci .getattr = nfs_getattr, 71262306a36Sopenharmony_ci .setattr = nfs_setattr, 71362306a36Sopenharmony_ci}; 71462306a36Sopenharmony_ci 71562306a36Sopenharmony_ciconst struct nfs_rpc_ops nfs_v2_clientops = { 71662306a36Sopenharmony_ci .version = 2, /* protocol version */ 71762306a36Sopenharmony_ci .dentry_ops = &nfs_dentry_operations, 71862306a36Sopenharmony_ci .dir_inode_ops = &nfs_dir_inode_operations, 71962306a36Sopenharmony_ci .file_inode_ops = &nfs_file_inode_operations, 72062306a36Sopenharmony_ci .file_ops = &nfs_file_operations, 72162306a36Sopenharmony_ci .getroot = nfs_proc_get_root, 72262306a36Sopenharmony_ci .submount = nfs_submount, 72362306a36Sopenharmony_ci .try_get_tree = nfs_try_get_tree, 72462306a36Sopenharmony_ci .getattr = nfs_proc_getattr, 72562306a36Sopenharmony_ci .setattr = nfs_proc_setattr, 72662306a36Sopenharmony_ci .lookup = nfs_proc_lookup, 72762306a36Sopenharmony_ci .access = NULL, /* access */ 72862306a36Sopenharmony_ci .readlink = nfs_proc_readlink, 72962306a36Sopenharmony_ci .create = nfs_proc_create, 73062306a36Sopenharmony_ci .remove = nfs_proc_remove, 73162306a36Sopenharmony_ci .unlink_setup = nfs_proc_unlink_setup, 73262306a36Sopenharmony_ci .unlink_rpc_prepare = nfs_proc_unlink_rpc_prepare, 73362306a36Sopenharmony_ci .unlink_done = nfs_proc_unlink_done, 73462306a36Sopenharmony_ci .rename_setup = nfs_proc_rename_setup, 73562306a36Sopenharmony_ci .rename_rpc_prepare = nfs_proc_rename_rpc_prepare, 73662306a36Sopenharmony_ci .rename_done = nfs_proc_rename_done, 73762306a36Sopenharmony_ci .link = nfs_proc_link, 73862306a36Sopenharmony_ci .symlink = nfs_proc_symlink, 73962306a36Sopenharmony_ci .mkdir = nfs_proc_mkdir, 74062306a36Sopenharmony_ci .rmdir = nfs_proc_rmdir, 74162306a36Sopenharmony_ci .readdir = nfs_proc_readdir, 74262306a36Sopenharmony_ci .mknod = nfs_proc_mknod, 74362306a36Sopenharmony_ci .statfs = nfs_proc_statfs, 74462306a36Sopenharmony_ci .fsinfo = nfs_proc_fsinfo, 74562306a36Sopenharmony_ci .pathconf = nfs_proc_pathconf, 74662306a36Sopenharmony_ci .decode_dirent = nfs2_decode_dirent, 74762306a36Sopenharmony_ci .pgio_rpc_prepare = nfs_proc_pgio_rpc_prepare, 74862306a36Sopenharmony_ci .read_setup = nfs_proc_read_setup, 74962306a36Sopenharmony_ci .read_done = nfs_read_done, 75062306a36Sopenharmony_ci .write_setup = nfs_proc_write_setup, 75162306a36Sopenharmony_ci .write_done = nfs_write_done, 75262306a36Sopenharmony_ci .commit_setup = nfs_proc_commit_setup, 75362306a36Sopenharmony_ci .commit_rpc_prepare = nfs_proc_commit_rpc_prepare, 75462306a36Sopenharmony_ci .lock = nfs_proc_lock, 75562306a36Sopenharmony_ci .lock_check_bounds = nfs_lock_check_bounds, 75662306a36Sopenharmony_ci .close_context = nfs_close_context, 75762306a36Sopenharmony_ci .have_delegation = nfs_have_delegation, 75862306a36Sopenharmony_ci .alloc_client = nfs_alloc_client, 75962306a36Sopenharmony_ci .init_client = nfs_init_client, 76062306a36Sopenharmony_ci .free_client = nfs_free_client, 76162306a36Sopenharmony_ci .create_server = nfs_create_server, 76262306a36Sopenharmony_ci .clone_server = nfs_clone_server, 76362306a36Sopenharmony_ci}; 764