18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * linux/fs/nfs/proc.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 1992, 1993, 1994 Rick Sladkey 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * OS-independent nfs remote procedure call functions 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * Tuned by Alan Cox <A.Cox@swansea.ac.uk> for >3K buffers 108c2ecf20Sopenharmony_ci * so at last we can have decent(ish) throughput off a 118c2ecf20Sopenharmony_ci * Sun server. 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * Coding optimized and cleaned up by Florian La Roche. 148c2ecf20Sopenharmony_ci * Note: Error returns are optimized for NFS_OK, which isn't translated via 158c2ecf20Sopenharmony_ci * nfs_stat_to_errno(), but happens to be already the right return code. 168c2ecf20Sopenharmony_ci * 178c2ecf20Sopenharmony_ci * Also, the code currently doesn't check the size of the packet, when 188c2ecf20Sopenharmony_ci * it decodes the packet. 198c2ecf20Sopenharmony_ci * 208c2ecf20Sopenharmony_ci * Feel free to fix it and mail me the diffs if it worries you. 218c2ecf20Sopenharmony_ci * 228c2ecf20Sopenharmony_ci * Completely rewritten to support the new RPC call interface; 238c2ecf20Sopenharmony_ci * rewrote and moved the entire XDR stuff to xdr.c 248c2ecf20Sopenharmony_ci * --Olaf Kirch June 1996 258c2ecf20Sopenharmony_ci * 268c2ecf20Sopenharmony_ci * The code below initializes all auto variables explicitly, otherwise 278c2ecf20Sopenharmony_ci * it will fail to work as a module (gcc generates a memset call for an 288c2ecf20Sopenharmony_ci * incomplete struct). 298c2ecf20Sopenharmony_ci */ 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci#include <linux/types.h> 328c2ecf20Sopenharmony_ci#include <linux/param.h> 338c2ecf20Sopenharmony_ci#include <linux/time.h> 348c2ecf20Sopenharmony_ci#include <linux/mm.h> 358c2ecf20Sopenharmony_ci#include <linux/errno.h> 368c2ecf20Sopenharmony_ci#include <linux/string.h> 378c2ecf20Sopenharmony_ci#include <linux/in.h> 388c2ecf20Sopenharmony_ci#include <linux/pagemap.h> 398c2ecf20Sopenharmony_ci#include <linux/sunrpc/clnt.h> 408c2ecf20Sopenharmony_ci#include <linux/nfs.h> 418c2ecf20Sopenharmony_ci#include <linux/nfs2.h> 428c2ecf20Sopenharmony_ci#include <linux/nfs_fs.h> 438c2ecf20Sopenharmony_ci#include <linux/nfs_page.h> 448c2ecf20Sopenharmony_ci#include <linux/lockd/bind.h> 458c2ecf20Sopenharmony_ci#include <linux/freezer.h> 468c2ecf20Sopenharmony_ci#include "internal.h" 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci#define NFSDBG_FACILITY NFSDBG_PROC 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci/* 518c2ecf20Sopenharmony_ci * Bare-bones access to getattr: this is for nfs_read_super. 528c2ecf20Sopenharmony_ci */ 538c2ecf20Sopenharmony_cistatic int 548c2ecf20Sopenharmony_cinfs_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, 558c2ecf20Sopenharmony_ci struct nfs_fsinfo *info) 568c2ecf20Sopenharmony_ci{ 578c2ecf20Sopenharmony_ci struct nfs_fattr *fattr = info->fattr; 588c2ecf20Sopenharmony_ci struct nfs2_fsstat fsinfo; 598c2ecf20Sopenharmony_ci struct rpc_message msg = { 608c2ecf20Sopenharmony_ci .rpc_proc = &nfs_procedures[NFSPROC_GETATTR], 618c2ecf20Sopenharmony_ci .rpc_argp = fhandle, 628c2ecf20Sopenharmony_ci .rpc_resp = fattr, 638c2ecf20Sopenharmony_ci }; 648c2ecf20Sopenharmony_ci int status; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci dprintk("%s: call getattr\n", __func__); 678c2ecf20Sopenharmony_ci nfs_fattr_init(fattr); 688c2ecf20Sopenharmony_ci status = rpc_call_sync(server->client, &msg, 0); 698c2ecf20Sopenharmony_ci /* Retry with default authentication if different */ 708c2ecf20Sopenharmony_ci if (status && server->nfs_client->cl_rpcclient != server->client) 718c2ecf20Sopenharmony_ci status = rpc_call_sync(server->nfs_client->cl_rpcclient, &msg, 0); 728c2ecf20Sopenharmony_ci dprintk("%s: reply getattr: %d\n", __func__, status); 738c2ecf20Sopenharmony_ci if (status) 748c2ecf20Sopenharmony_ci return status; 758c2ecf20Sopenharmony_ci dprintk("%s: call statfs\n", __func__); 768c2ecf20Sopenharmony_ci msg.rpc_proc = &nfs_procedures[NFSPROC_STATFS]; 778c2ecf20Sopenharmony_ci msg.rpc_resp = &fsinfo; 788c2ecf20Sopenharmony_ci status = rpc_call_sync(server->client, &msg, 0); 798c2ecf20Sopenharmony_ci /* Retry with default authentication if different */ 808c2ecf20Sopenharmony_ci if (status && server->nfs_client->cl_rpcclient != server->client) 818c2ecf20Sopenharmony_ci status = rpc_call_sync(server->nfs_client->cl_rpcclient, &msg, 0); 828c2ecf20Sopenharmony_ci dprintk("%s: reply statfs: %d\n", __func__, status); 838c2ecf20Sopenharmony_ci if (status) 848c2ecf20Sopenharmony_ci return status; 858c2ecf20Sopenharmony_ci info->rtmax = NFS_MAXDATA; 868c2ecf20Sopenharmony_ci info->rtpref = fsinfo.tsize; 878c2ecf20Sopenharmony_ci info->rtmult = fsinfo.bsize; 888c2ecf20Sopenharmony_ci info->wtmax = NFS_MAXDATA; 898c2ecf20Sopenharmony_ci info->wtpref = fsinfo.tsize; 908c2ecf20Sopenharmony_ci info->wtmult = fsinfo.bsize; 918c2ecf20Sopenharmony_ci info->dtpref = fsinfo.tsize; 928c2ecf20Sopenharmony_ci info->maxfilesize = 0x7FFFFFFF; 938c2ecf20Sopenharmony_ci info->lease_time = 0; 948c2ecf20Sopenharmony_ci return 0; 958c2ecf20Sopenharmony_ci} 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci/* 988c2ecf20Sopenharmony_ci * One function for each procedure in the NFS protocol. 998c2ecf20Sopenharmony_ci */ 1008c2ecf20Sopenharmony_cistatic int 1018c2ecf20Sopenharmony_cinfs_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, 1028c2ecf20Sopenharmony_ci struct nfs_fattr *fattr, struct nfs4_label *label, 1038c2ecf20Sopenharmony_ci struct inode *inode) 1048c2ecf20Sopenharmony_ci{ 1058c2ecf20Sopenharmony_ci struct rpc_message msg = { 1068c2ecf20Sopenharmony_ci .rpc_proc = &nfs_procedures[NFSPROC_GETATTR], 1078c2ecf20Sopenharmony_ci .rpc_argp = fhandle, 1088c2ecf20Sopenharmony_ci .rpc_resp = fattr, 1098c2ecf20Sopenharmony_ci }; 1108c2ecf20Sopenharmony_ci int status; 1118c2ecf20Sopenharmony_ci unsigned short task_flags = 0; 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci /* Is this is an attribute revalidation, subject to softreval? */ 1148c2ecf20Sopenharmony_ci if (inode && (server->flags & NFS_MOUNT_SOFTREVAL)) 1158c2ecf20Sopenharmony_ci task_flags |= RPC_TASK_TIMEOUT; 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci dprintk("NFS call getattr\n"); 1188c2ecf20Sopenharmony_ci nfs_fattr_init(fattr); 1198c2ecf20Sopenharmony_ci status = rpc_call_sync(server->client, &msg, task_flags); 1208c2ecf20Sopenharmony_ci dprintk("NFS reply getattr: %d\n", status); 1218c2ecf20Sopenharmony_ci return status; 1228c2ecf20Sopenharmony_ci} 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_cistatic int 1258c2ecf20Sopenharmony_cinfs_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, 1268c2ecf20Sopenharmony_ci struct iattr *sattr) 1278c2ecf20Sopenharmony_ci{ 1288c2ecf20Sopenharmony_ci struct inode *inode = d_inode(dentry); 1298c2ecf20Sopenharmony_ci struct nfs_sattrargs arg = { 1308c2ecf20Sopenharmony_ci .fh = NFS_FH(inode), 1318c2ecf20Sopenharmony_ci .sattr = sattr 1328c2ecf20Sopenharmony_ci }; 1338c2ecf20Sopenharmony_ci struct rpc_message msg = { 1348c2ecf20Sopenharmony_ci .rpc_proc = &nfs_procedures[NFSPROC_SETATTR], 1358c2ecf20Sopenharmony_ci .rpc_argp = &arg, 1368c2ecf20Sopenharmony_ci .rpc_resp = fattr, 1378c2ecf20Sopenharmony_ci }; 1388c2ecf20Sopenharmony_ci int status; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci /* Mask out the non-modebit related stuff from attr->ia_mode */ 1418c2ecf20Sopenharmony_ci sattr->ia_mode &= S_IALLUGO; 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci dprintk("NFS call setattr\n"); 1448c2ecf20Sopenharmony_ci if (sattr->ia_valid & ATTR_FILE) 1458c2ecf20Sopenharmony_ci msg.rpc_cred = nfs_file_cred(sattr->ia_file); 1468c2ecf20Sopenharmony_ci nfs_fattr_init(fattr); 1478c2ecf20Sopenharmony_ci status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); 1488c2ecf20Sopenharmony_ci if (status == 0) 1498c2ecf20Sopenharmony_ci nfs_setattr_update_inode(inode, sattr, fattr); 1508c2ecf20Sopenharmony_ci dprintk("NFS reply setattr: %d\n", status); 1518c2ecf20Sopenharmony_ci return status; 1528c2ecf20Sopenharmony_ci} 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_cistatic int 1558c2ecf20Sopenharmony_cinfs_proc_lookup(struct inode *dir, struct dentry *dentry, 1568c2ecf20Sopenharmony_ci struct nfs_fh *fhandle, struct nfs_fattr *fattr, 1578c2ecf20Sopenharmony_ci struct nfs4_label *label) 1588c2ecf20Sopenharmony_ci{ 1598c2ecf20Sopenharmony_ci struct nfs_diropargs arg = { 1608c2ecf20Sopenharmony_ci .fh = NFS_FH(dir), 1618c2ecf20Sopenharmony_ci .name = dentry->d_name.name, 1628c2ecf20Sopenharmony_ci .len = dentry->d_name.len 1638c2ecf20Sopenharmony_ci }; 1648c2ecf20Sopenharmony_ci struct nfs_diropok res = { 1658c2ecf20Sopenharmony_ci .fh = fhandle, 1668c2ecf20Sopenharmony_ci .fattr = fattr 1678c2ecf20Sopenharmony_ci }; 1688c2ecf20Sopenharmony_ci struct rpc_message msg = { 1698c2ecf20Sopenharmony_ci .rpc_proc = &nfs_procedures[NFSPROC_LOOKUP], 1708c2ecf20Sopenharmony_ci .rpc_argp = &arg, 1718c2ecf20Sopenharmony_ci .rpc_resp = &res, 1728c2ecf20Sopenharmony_ci }; 1738c2ecf20Sopenharmony_ci int status; 1748c2ecf20Sopenharmony_ci unsigned short task_flags = 0; 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci /* Is this is an attribute revalidation, subject to softreval? */ 1778c2ecf20Sopenharmony_ci if (nfs_lookup_is_soft_revalidate(dentry)) 1788c2ecf20Sopenharmony_ci task_flags |= RPC_TASK_TIMEOUT; 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci dprintk("NFS call lookup %pd2\n", dentry); 1818c2ecf20Sopenharmony_ci nfs_fattr_init(fattr); 1828c2ecf20Sopenharmony_ci status = rpc_call_sync(NFS_CLIENT(dir), &msg, task_flags); 1838c2ecf20Sopenharmony_ci dprintk("NFS reply lookup: %d\n", status); 1848c2ecf20Sopenharmony_ci return status; 1858c2ecf20Sopenharmony_ci} 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_cistatic int nfs_proc_readlink(struct inode *inode, struct page *page, 1888c2ecf20Sopenharmony_ci unsigned int pgbase, unsigned int pglen) 1898c2ecf20Sopenharmony_ci{ 1908c2ecf20Sopenharmony_ci struct nfs_readlinkargs args = { 1918c2ecf20Sopenharmony_ci .fh = NFS_FH(inode), 1928c2ecf20Sopenharmony_ci .pgbase = pgbase, 1938c2ecf20Sopenharmony_ci .pglen = pglen, 1948c2ecf20Sopenharmony_ci .pages = &page 1958c2ecf20Sopenharmony_ci }; 1968c2ecf20Sopenharmony_ci struct rpc_message msg = { 1978c2ecf20Sopenharmony_ci .rpc_proc = &nfs_procedures[NFSPROC_READLINK], 1988c2ecf20Sopenharmony_ci .rpc_argp = &args, 1998c2ecf20Sopenharmony_ci }; 2008c2ecf20Sopenharmony_ci int status; 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci dprintk("NFS call readlink\n"); 2038c2ecf20Sopenharmony_ci status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); 2048c2ecf20Sopenharmony_ci dprintk("NFS reply readlink: %d\n", status); 2058c2ecf20Sopenharmony_ci return status; 2068c2ecf20Sopenharmony_ci} 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_cistruct nfs_createdata { 2098c2ecf20Sopenharmony_ci struct nfs_createargs arg; 2108c2ecf20Sopenharmony_ci struct nfs_diropok res; 2118c2ecf20Sopenharmony_ci struct nfs_fh fhandle; 2128c2ecf20Sopenharmony_ci struct nfs_fattr fattr; 2138c2ecf20Sopenharmony_ci}; 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_cistatic struct nfs_createdata *nfs_alloc_createdata(struct inode *dir, 2168c2ecf20Sopenharmony_ci struct dentry *dentry, struct iattr *sattr) 2178c2ecf20Sopenharmony_ci{ 2188c2ecf20Sopenharmony_ci struct nfs_createdata *data; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci data = kmalloc(sizeof(*data), GFP_KERNEL); 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci if (data != NULL) { 2238c2ecf20Sopenharmony_ci data->arg.fh = NFS_FH(dir); 2248c2ecf20Sopenharmony_ci data->arg.name = dentry->d_name.name; 2258c2ecf20Sopenharmony_ci data->arg.len = dentry->d_name.len; 2268c2ecf20Sopenharmony_ci data->arg.sattr = sattr; 2278c2ecf20Sopenharmony_ci nfs_fattr_init(&data->fattr); 2288c2ecf20Sopenharmony_ci data->fhandle.size = 0; 2298c2ecf20Sopenharmony_ci data->res.fh = &data->fhandle; 2308c2ecf20Sopenharmony_ci data->res.fattr = &data->fattr; 2318c2ecf20Sopenharmony_ci } 2328c2ecf20Sopenharmony_ci return data; 2338c2ecf20Sopenharmony_ci}; 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_cistatic void nfs_free_createdata(const struct nfs_createdata *data) 2368c2ecf20Sopenharmony_ci{ 2378c2ecf20Sopenharmony_ci kfree(data); 2388c2ecf20Sopenharmony_ci} 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_cistatic int 2418c2ecf20Sopenharmony_cinfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, 2428c2ecf20Sopenharmony_ci int flags) 2438c2ecf20Sopenharmony_ci{ 2448c2ecf20Sopenharmony_ci struct nfs_createdata *data; 2458c2ecf20Sopenharmony_ci struct rpc_message msg = { 2468c2ecf20Sopenharmony_ci .rpc_proc = &nfs_procedures[NFSPROC_CREATE], 2478c2ecf20Sopenharmony_ci }; 2488c2ecf20Sopenharmony_ci int status = -ENOMEM; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci dprintk("NFS call create %pd\n", dentry); 2518c2ecf20Sopenharmony_ci data = nfs_alloc_createdata(dir, dentry, sattr); 2528c2ecf20Sopenharmony_ci if (data == NULL) 2538c2ecf20Sopenharmony_ci goto out; 2548c2ecf20Sopenharmony_ci msg.rpc_argp = &data->arg; 2558c2ecf20Sopenharmony_ci msg.rpc_resp = &data->res; 2568c2ecf20Sopenharmony_ci status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); 2578c2ecf20Sopenharmony_ci nfs_mark_for_revalidate(dir); 2588c2ecf20Sopenharmony_ci if (status == 0) 2598c2ecf20Sopenharmony_ci status = nfs_instantiate(dentry, data->res.fh, data->res.fattr, NULL); 2608c2ecf20Sopenharmony_ci nfs_free_createdata(data); 2618c2ecf20Sopenharmony_ciout: 2628c2ecf20Sopenharmony_ci dprintk("NFS reply create: %d\n", status); 2638c2ecf20Sopenharmony_ci return status; 2648c2ecf20Sopenharmony_ci} 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci/* 2678c2ecf20Sopenharmony_ci * In NFSv2, mknod is grafted onto the create call. 2688c2ecf20Sopenharmony_ci */ 2698c2ecf20Sopenharmony_cistatic int 2708c2ecf20Sopenharmony_cinfs_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr, 2718c2ecf20Sopenharmony_ci dev_t rdev) 2728c2ecf20Sopenharmony_ci{ 2738c2ecf20Sopenharmony_ci struct nfs_createdata *data; 2748c2ecf20Sopenharmony_ci struct rpc_message msg = { 2758c2ecf20Sopenharmony_ci .rpc_proc = &nfs_procedures[NFSPROC_CREATE], 2768c2ecf20Sopenharmony_ci }; 2778c2ecf20Sopenharmony_ci umode_t mode; 2788c2ecf20Sopenharmony_ci int status = -ENOMEM; 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci dprintk("NFS call mknod %pd\n", dentry); 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci mode = sattr->ia_mode; 2838c2ecf20Sopenharmony_ci if (S_ISFIFO(mode)) { 2848c2ecf20Sopenharmony_ci sattr->ia_mode = (mode & ~S_IFMT) | S_IFCHR; 2858c2ecf20Sopenharmony_ci sattr->ia_valid &= ~ATTR_SIZE; 2868c2ecf20Sopenharmony_ci } else if (S_ISCHR(mode) || S_ISBLK(mode)) { 2878c2ecf20Sopenharmony_ci sattr->ia_valid |= ATTR_SIZE; 2888c2ecf20Sopenharmony_ci sattr->ia_size = new_encode_dev(rdev);/* get out your barf bag */ 2898c2ecf20Sopenharmony_ci } 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci data = nfs_alloc_createdata(dir, dentry, sattr); 2928c2ecf20Sopenharmony_ci if (data == NULL) 2938c2ecf20Sopenharmony_ci goto out; 2948c2ecf20Sopenharmony_ci msg.rpc_argp = &data->arg; 2958c2ecf20Sopenharmony_ci msg.rpc_resp = &data->res; 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); 2988c2ecf20Sopenharmony_ci nfs_mark_for_revalidate(dir); 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci if (status == -EINVAL && S_ISFIFO(mode)) { 3018c2ecf20Sopenharmony_ci sattr->ia_mode = mode; 3028c2ecf20Sopenharmony_ci nfs_fattr_init(data->res.fattr); 3038c2ecf20Sopenharmony_ci status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); 3048c2ecf20Sopenharmony_ci } 3058c2ecf20Sopenharmony_ci if (status == 0) 3068c2ecf20Sopenharmony_ci status = nfs_instantiate(dentry, data->res.fh, data->res.fattr, NULL); 3078c2ecf20Sopenharmony_ci nfs_free_createdata(data); 3088c2ecf20Sopenharmony_ciout: 3098c2ecf20Sopenharmony_ci dprintk("NFS reply mknod: %d\n", status); 3108c2ecf20Sopenharmony_ci return status; 3118c2ecf20Sopenharmony_ci} 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_cistatic int 3148c2ecf20Sopenharmony_cinfs_proc_remove(struct inode *dir, struct dentry *dentry) 3158c2ecf20Sopenharmony_ci{ 3168c2ecf20Sopenharmony_ci struct nfs_removeargs arg = { 3178c2ecf20Sopenharmony_ci .fh = NFS_FH(dir), 3188c2ecf20Sopenharmony_ci .name = dentry->d_name, 3198c2ecf20Sopenharmony_ci }; 3208c2ecf20Sopenharmony_ci struct rpc_message msg = { 3218c2ecf20Sopenharmony_ci .rpc_proc = &nfs_procedures[NFSPROC_REMOVE], 3228c2ecf20Sopenharmony_ci .rpc_argp = &arg, 3238c2ecf20Sopenharmony_ci }; 3248c2ecf20Sopenharmony_ci int status; 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci dprintk("NFS call remove %pd2\n",dentry); 3278c2ecf20Sopenharmony_ci status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); 3288c2ecf20Sopenharmony_ci nfs_mark_for_revalidate(dir); 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci dprintk("NFS reply remove: %d\n", status); 3318c2ecf20Sopenharmony_ci return status; 3328c2ecf20Sopenharmony_ci} 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_cistatic void 3358c2ecf20Sopenharmony_cinfs_proc_unlink_setup(struct rpc_message *msg, 3368c2ecf20Sopenharmony_ci struct dentry *dentry, 3378c2ecf20Sopenharmony_ci struct inode *inode) 3388c2ecf20Sopenharmony_ci{ 3398c2ecf20Sopenharmony_ci msg->rpc_proc = &nfs_procedures[NFSPROC_REMOVE]; 3408c2ecf20Sopenharmony_ci} 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_cistatic void nfs_proc_unlink_rpc_prepare(struct rpc_task *task, struct nfs_unlinkdata *data) 3438c2ecf20Sopenharmony_ci{ 3448c2ecf20Sopenharmony_ci rpc_call_start(task); 3458c2ecf20Sopenharmony_ci} 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_cistatic int nfs_proc_unlink_done(struct rpc_task *task, struct inode *dir) 3488c2ecf20Sopenharmony_ci{ 3498c2ecf20Sopenharmony_ci nfs_mark_for_revalidate(dir); 3508c2ecf20Sopenharmony_ci return 1; 3518c2ecf20Sopenharmony_ci} 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_cistatic void 3548c2ecf20Sopenharmony_cinfs_proc_rename_setup(struct rpc_message *msg, 3558c2ecf20Sopenharmony_ci struct dentry *old_dentry, 3568c2ecf20Sopenharmony_ci struct dentry *new_dentry) 3578c2ecf20Sopenharmony_ci{ 3588c2ecf20Sopenharmony_ci msg->rpc_proc = &nfs_procedures[NFSPROC_RENAME]; 3598c2ecf20Sopenharmony_ci} 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_cistatic void nfs_proc_rename_rpc_prepare(struct rpc_task *task, struct nfs_renamedata *data) 3628c2ecf20Sopenharmony_ci{ 3638c2ecf20Sopenharmony_ci rpc_call_start(task); 3648c2ecf20Sopenharmony_ci} 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_cistatic int 3678c2ecf20Sopenharmony_cinfs_proc_rename_done(struct rpc_task *task, struct inode *old_dir, 3688c2ecf20Sopenharmony_ci struct inode *new_dir) 3698c2ecf20Sopenharmony_ci{ 3708c2ecf20Sopenharmony_ci nfs_mark_for_revalidate(old_dir); 3718c2ecf20Sopenharmony_ci nfs_mark_for_revalidate(new_dir); 3728c2ecf20Sopenharmony_ci return 1; 3738c2ecf20Sopenharmony_ci} 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_cistatic int 3768c2ecf20Sopenharmony_cinfs_proc_link(struct inode *inode, struct inode *dir, const struct qstr *name) 3778c2ecf20Sopenharmony_ci{ 3788c2ecf20Sopenharmony_ci struct nfs_linkargs arg = { 3798c2ecf20Sopenharmony_ci .fromfh = NFS_FH(inode), 3808c2ecf20Sopenharmony_ci .tofh = NFS_FH(dir), 3818c2ecf20Sopenharmony_ci .toname = name->name, 3828c2ecf20Sopenharmony_ci .tolen = name->len 3838c2ecf20Sopenharmony_ci }; 3848c2ecf20Sopenharmony_ci struct rpc_message msg = { 3858c2ecf20Sopenharmony_ci .rpc_proc = &nfs_procedures[NFSPROC_LINK], 3868c2ecf20Sopenharmony_ci .rpc_argp = &arg, 3878c2ecf20Sopenharmony_ci }; 3888c2ecf20Sopenharmony_ci int status; 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci dprintk("NFS call link %s\n", name->name); 3918c2ecf20Sopenharmony_ci status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); 3928c2ecf20Sopenharmony_ci nfs_mark_for_revalidate(inode); 3938c2ecf20Sopenharmony_ci nfs_mark_for_revalidate(dir); 3948c2ecf20Sopenharmony_ci dprintk("NFS reply link: %d\n", status); 3958c2ecf20Sopenharmony_ci return status; 3968c2ecf20Sopenharmony_ci} 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_cistatic int 3998c2ecf20Sopenharmony_cinfs_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page, 4008c2ecf20Sopenharmony_ci unsigned int len, struct iattr *sattr) 4018c2ecf20Sopenharmony_ci{ 4028c2ecf20Sopenharmony_ci struct nfs_fh *fh; 4038c2ecf20Sopenharmony_ci struct nfs_fattr *fattr; 4048c2ecf20Sopenharmony_ci struct nfs_symlinkargs arg = { 4058c2ecf20Sopenharmony_ci .fromfh = NFS_FH(dir), 4068c2ecf20Sopenharmony_ci .fromname = dentry->d_name.name, 4078c2ecf20Sopenharmony_ci .fromlen = dentry->d_name.len, 4088c2ecf20Sopenharmony_ci .pages = &page, 4098c2ecf20Sopenharmony_ci .pathlen = len, 4108c2ecf20Sopenharmony_ci .sattr = sattr 4118c2ecf20Sopenharmony_ci }; 4128c2ecf20Sopenharmony_ci struct rpc_message msg = { 4138c2ecf20Sopenharmony_ci .rpc_proc = &nfs_procedures[NFSPROC_SYMLINK], 4148c2ecf20Sopenharmony_ci .rpc_argp = &arg, 4158c2ecf20Sopenharmony_ci }; 4168c2ecf20Sopenharmony_ci int status = -ENAMETOOLONG; 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci dprintk("NFS call symlink %pd\n", dentry); 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_ci if (len > NFS2_MAXPATHLEN) 4218c2ecf20Sopenharmony_ci goto out; 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_ci fh = nfs_alloc_fhandle(); 4248c2ecf20Sopenharmony_ci fattr = nfs_alloc_fattr(); 4258c2ecf20Sopenharmony_ci status = -ENOMEM; 4268c2ecf20Sopenharmony_ci if (fh == NULL || fattr == NULL) 4278c2ecf20Sopenharmony_ci goto out_free; 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); 4308c2ecf20Sopenharmony_ci nfs_mark_for_revalidate(dir); 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci /* 4338c2ecf20Sopenharmony_ci * V2 SYMLINK requests don't return any attributes. Setting the 4348c2ecf20Sopenharmony_ci * filehandle size to zero indicates to nfs_instantiate that it 4358c2ecf20Sopenharmony_ci * should fill in the data with a LOOKUP call on the wire. 4368c2ecf20Sopenharmony_ci */ 4378c2ecf20Sopenharmony_ci if (status == 0) 4388c2ecf20Sopenharmony_ci status = nfs_instantiate(dentry, fh, fattr, NULL); 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ciout_free: 4418c2ecf20Sopenharmony_ci nfs_free_fattr(fattr); 4428c2ecf20Sopenharmony_ci nfs_free_fhandle(fh); 4438c2ecf20Sopenharmony_ciout: 4448c2ecf20Sopenharmony_ci dprintk("NFS reply symlink: %d\n", status); 4458c2ecf20Sopenharmony_ci return status; 4468c2ecf20Sopenharmony_ci} 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_cistatic int 4498c2ecf20Sopenharmony_cinfs_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr) 4508c2ecf20Sopenharmony_ci{ 4518c2ecf20Sopenharmony_ci struct nfs_createdata *data; 4528c2ecf20Sopenharmony_ci struct rpc_message msg = { 4538c2ecf20Sopenharmony_ci .rpc_proc = &nfs_procedures[NFSPROC_MKDIR], 4548c2ecf20Sopenharmony_ci }; 4558c2ecf20Sopenharmony_ci int status = -ENOMEM; 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_ci dprintk("NFS call mkdir %pd\n", dentry); 4588c2ecf20Sopenharmony_ci data = nfs_alloc_createdata(dir, dentry, sattr); 4598c2ecf20Sopenharmony_ci if (data == NULL) 4608c2ecf20Sopenharmony_ci goto out; 4618c2ecf20Sopenharmony_ci msg.rpc_argp = &data->arg; 4628c2ecf20Sopenharmony_ci msg.rpc_resp = &data->res; 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_ci status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); 4658c2ecf20Sopenharmony_ci nfs_mark_for_revalidate(dir); 4668c2ecf20Sopenharmony_ci if (status == 0) 4678c2ecf20Sopenharmony_ci status = nfs_instantiate(dentry, data->res.fh, data->res.fattr, NULL); 4688c2ecf20Sopenharmony_ci nfs_free_createdata(data); 4698c2ecf20Sopenharmony_ciout: 4708c2ecf20Sopenharmony_ci dprintk("NFS reply mkdir: %d\n", status); 4718c2ecf20Sopenharmony_ci return status; 4728c2ecf20Sopenharmony_ci} 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_cistatic int 4758c2ecf20Sopenharmony_cinfs_proc_rmdir(struct inode *dir, const struct qstr *name) 4768c2ecf20Sopenharmony_ci{ 4778c2ecf20Sopenharmony_ci struct nfs_diropargs arg = { 4788c2ecf20Sopenharmony_ci .fh = NFS_FH(dir), 4798c2ecf20Sopenharmony_ci .name = name->name, 4808c2ecf20Sopenharmony_ci .len = name->len 4818c2ecf20Sopenharmony_ci }; 4828c2ecf20Sopenharmony_ci struct rpc_message msg = { 4838c2ecf20Sopenharmony_ci .rpc_proc = &nfs_procedures[NFSPROC_RMDIR], 4848c2ecf20Sopenharmony_ci .rpc_argp = &arg, 4858c2ecf20Sopenharmony_ci }; 4868c2ecf20Sopenharmony_ci int status; 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_ci dprintk("NFS call rmdir %s\n", name->name); 4898c2ecf20Sopenharmony_ci status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); 4908c2ecf20Sopenharmony_ci nfs_mark_for_revalidate(dir); 4918c2ecf20Sopenharmony_ci dprintk("NFS reply rmdir: %d\n", status); 4928c2ecf20Sopenharmony_ci return status; 4938c2ecf20Sopenharmony_ci} 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci/* 4968c2ecf20Sopenharmony_ci * The READDIR implementation is somewhat hackish - we pass a temporary 4978c2ecf20Sopenharmony_ci * buffer to the encode function, which installs it in the receive 4988c2ecf20Sopenharmony_ci * the receive iovec. The decode function just parses the reply to make 4998c2ecf20Sopenharmony_ci * sure it is syntactically correct; the entries itself are decoded 5008c2ecf20Sopenharmony_ci * from nfs_readdir by calling the decode_entry function directly. 5018c2ecf20Sopenharmony_ci */ 5028c2ecf20Sopenharmony_cistatic int 5038c2ecf20Sopenharmony_cinfs_proc_readdir(struct dentry *dentry, const struct cred *cred, 5048c2ecf20Sopenharmony_ci u64 cookie, struct page **pages, unsigned int count, bool plus) 5058c2ecf20Sopenharmony_ci{ 5068c2ecf20Sopenharmony_ci struct inode *dir = d_inode(dentry); 5078c2ecf20Sopenharmony_ci struct nfs_readdirargs arg = { 5088c2ecf20Sopenharmony_ci .fh = NFS_FH(dir), 5098c2ecf20Sopenharmony_ci .cookie = cookie, 5108c2ecf20Sopenharmony_ci .count = count, 5118c2ecf20Sopenharmony_ci .pages = pages, 5128c2ecf20Sopenharmony_ci }; 5138c2ecf20Sopenharmony_ci struct rpc_message msg = { 5148c2ecf20Sopenharmony_ci .rpc_proc = &nfs_procedures[NFSPROC_READDIR], 5158c2ecf20Sopenharmony_ci .rpc_argp = &arg, 5168c2ecf20Sopenharmony_ci .rpc_cred = cred, 5178c2ecf20Sopenharmony_ci }; 5188c2ecf20Sopenharmony_ci int status; 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_ci dprintk("NFS call readdir %d\n", (unsigned int)cookie); 5218c2ecf20Sopenharmony_ci status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_ci nfs_invalidate_atime(dir); 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_ci dprintk("NFS reply readdir: %d\n", status); 5268c2ecf20Sopenharmony_ci return status; 5278c2ecf20Sopenharmony_ci} 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_cistatic int 5308c2ecf20Sopenharmony_cinfs_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, 5318c2ecf20Sopenharmony_ci struct nfs_fsstat *stat) 5328c2ecf20Sopenharmony_ci{ 5338c2ecf20Sopenharmony_ci struct nfs2_fsstat fsinfo; 5348c2ecf20Sopenharmony_ci struct rpc_message msg = { 5358c2ecf20Sopenharmony_ci .rpc_proc = &nfs_procedures[NFSPROC_STATFS], 5368c2ecf20Sopenharmony_ci .rpc_argp = fhandle, 5378c2ecf20Sopenharmony_ci .rpc_resp = &fsinfo, 5388c2ecf20Sopenharmony_ci }; 5398c2ecf20Sopenharmony_ci int status; 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci dprintk("NFS call statfs\n"); 5428c2ecf20Sopenharmony_ci nfs_fattr_init(stat->fattr); 5438c2ecf20Sopenharmony_ci status = rpc_call_sync(server->client, &msg, 0); 5448c2ecf20Sopenharmony_ci dprintk("NFS reply statfs: %d\n", status); 5458c2ecf20Sopenharmony_ci if (status) 5468c2ecf20Sopenharmony_ci goto out; 5478c2ecf20Sopenharmony_ci stat->tbytes = (u64)fsinfo.blocks * fsinfo.bsize; 5488c2ecf20Sopenharmony_ci stat->fbytes = (u64)fsinfo.bfree * fsinfo.bsize; 5498c2ecf20Sopenharmony_ci stat->abytes = (u64)fsinfo.bavail * fsinfo.bsize; 5508c2ecf20Sopenharmony_ci stat->tfiles = 0; 5518c2ecf20Sopenharmony_ci stat->ffiles = 0; 5528c2ecf20Sopenharmony_ci stat->afiles = 0; 5538c2ecf20Sopenharmony_ciout: 5548c2ecf20Sopenharmony_ci return status; 5558c2ecf20Sopenharmony_ci} 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_cistatic int 5588c2ecf20Sopenharmony_cinfs_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, 5598c2ecf20Sopenharmony_ci struct nfs_fsinfo *info) 5608c2ecf20Sopenharmony_ci{ 5618c2ecf20Sopenharmony_ci struct nfs2_fsstat fsinfo; 5628c2ecf20Sopenharmony_ci struct rpc_message msg = { 5638c2ecf20Sopenharmony_ci .rpc_proc = &nfs_procedures[NFSPROC_STATFS], 5648c2ecf20Sopenharmony_ci .rpc_argp = fhandle, 5658c2ecf20Sopenharmony_ci .rpc_resp = &fsinfo, 5668c2ecf20Sopenharmony_ci }; 5678c2ecf20Sopenharmony_ci int status; 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_ci dprintk("NFS call fsinfo\n"); 5708c2ecf20Sopenharmony_ci nfs_fattr_init(info->fattr); 5718c2ecf20Sopenharmony_ci status = rpc_call_sync(server->client, &msg, 0); 5728c2ecf20Sopenharmony_ci dprintk("NFS reply fsinfo: %d\n", status); 5738c2ecf20Sopenharmony_ci if (status) 5748c2ecf20Sopenharmony_ci goto out; 5758c2ecf20Sopenharmony_ci info->rtmax = NFS_MAXDATA; 5768c2ecf20Sopenharmony_ci info->rtpref = fsinfo.tsize; 5778c2ecf20Sopenharmony_ci info->rtmult = fsinfo.bsize; 5788c2ecf20Sopenharmony_ci info->wtmax = NFS_MAXDATA; 5798c2ecf20Sopenharmony_ci info->wtpref = fsinfo.tsize; 5808c2ecf20Sopenharmony_ci info->wtmult = fsinfo.bsize; 5818c2ecf20Sopenharmony_ci info->dtpref = fsinfo.tsize; 5828c2ecf20Sopenharmony_ci info->maxfilesize = 0x7FFFFFFF; 5838c2ecf20Sopenharmony_ci info->lease_time = 0; 5848c2ecf20Sopenharmony_ciout: 5858c2ecf20Sopenharmony_ci return status; 5868c2ecf20Sopenharmony_ci} 5878c2ecf20Sopenharmony_ci 5888c2ecf20Sopenharmony_cistatic int 5898c2ecf20Sopenharmony_cinfs_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, 5908c2ecf20Sopenharmony_ci struct nfs_pathconf *info) 5918c2ecf20Sopenharmony_ci{ 5928c2ecf20Sopenharmony_ci info->max_link = 0; 5938c2ecf20Sopenharmony_ci info->max_namelen = NFS2_MAXNAMLEN; 5948c2ecf20Sopenharmony_ci return 0; 5958c2ecf20Sopenharmony_ci} 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_cistatic int nfs_read_done(struct rpc_task *task, struct nfs_pgio_header *hdr) 5988c2ecf20Sopenharmony_ci{ 5998c2ecf20Sopenharmony_ci struct inode *inode = hdr->inode; 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ci nfs_invalidate_atime(inode); 6028c2ecf20Sopenharmony_ci if (task->tk_status >= 0) { 6038c2ecf20Sopenharmony_ci nfs_refresh_inode(inode, hdr->res.fattr); 6048c2ecf20Sopenharmony_ci /* Emulate the eof flag, which isn't normally needed in NFSv2 6058c2ecf20Sopenharmony_ci * as it is guaranteed to always return the file attributes 6068c2ecf20Sopenharmony_ci */ 6078c2ecf20Sopenharmony_ci if ((hdr->res.count == 0 && hdr->args.count > 0) || 6088c2ecf20Sopenharmony_ci hdr->args.offset + hdr->res.count >= hdr->res.fattr->size) 6098c2ecf20Sopenharmony_ci hdr->res.eof = 1; 6108c2ecf20Sopenharmony_ci } 6118c2ecf20Sopenharmony_ci return 0; 6128c2ecf20Sopenharmony_ci} 6138c2ecf20Sopenharmony_ci 6148c2ecf20Sopenharmony_cistatic void nfs_proc_read_setup(struct nfs_pgio_header *hdr, 6158c2ecf20Sopenharmony_ci struct rpc_message *msg) 6168c2ecf20Sopenharmony_ci{ 6178c2ecf20Sopenharmony_ci msg->rpc_proc = &nfs_procedures[NFSPROC_READ]; 6188c2ecf20Sopenharmony_ci} 6198c2ecf20Sopenharmony_ci 6208c2ecf20Sopenharmony_cistatic int nfs_proc_pgio_rpc_prepare(struct rpc_task *task, 6218c2ecf20Sopenharmony_ci struct nfs_pgio_header *hdr) 6228c2ecf20Sopenharmony_ci{ 6238c2ecf20Sopenharmony_ci rpc_call_start(task); 6248c2ecf20Sopenharmony_ci return 0; 6258c2ecf20Sopenharmony_ci} 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_cistatic int nfs_write_done(struct rpc_task *task, struct nfs_pgio_header *hdr) 6288c2ecf20Sopenharmony_ci{ 6298c2ecf20Sopenharmony_ci if (task->tk_status >= 0) { 6308c2ecf20Sopenharmony_ci hdr->res.count = hdr->args.count; 6318c2ecf20Sopenharmony_ci nfs_writeback_update_inode(hdr); 6328c2ecf20Sopenharmony_ci } 6338c2ecf20Sopenharmony_ci return 0; 6348c2ecf20Sopenharmony_ci} 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_cistatic void nfs_proc_write_setup(struct nfs_pgio_header *hdr, 6378c2ecf20Sopenharmony_ci struct rpc_message *msg, 6388c2ecf20Sopenharmony_ci struct rpc_clnt **clnt) 6398c2ecf20Sopenharmony_ci{ 6408c2ecf20Sopenharmony_ci /* Note: NFSv2 ignores @stable and always uses NFS_FILE_SYNC */ 6418c2ecf20Sopenharmony_ci hdr->args.stable = NFS_FILE_SYNC; 6428c2ecf20Sopenharmony_ci msg->rpc_proc = &nfs_procedures[NFSPROC_WRITE]; 6438c2ecf20Sopenharmony_ci} 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_cistatic void nfs_proc_commit_rpc_prepare(struct rpc_task *task, struct nfs_commit_data *data) 6468c2ecf20Sopenharmony_ci{ 6478c2ecf20Sopenharmony_ci BUG(); 6488c2ecf20Sopenharmony_ci} 6498c2ecf20Sopenharmony_ci 6508c2ecf20Sopenharmony_cistatic void 6518c2ecf20Sopenharmony_cinfs_proc_commit_setup(struct nfs_commit_data *data, struct rpc_message *msg, 6528c2ecf20Sopenharmony_ci struct rpc_clnt **clnt) 6538c2ecf20Sopenharmony_ci{ 6548c2ecf20Sopenharmony_ci BUG(); 6558c2ecf20Sopenharmony_ci} 6568c2ecf20Sopenharmony_ci 6578c2ecf20Sopenharmony_cistatic int 6588c2ecf20Sopenharmony_cinfs_proc_lock(struct file *filp, int cmd, struct file_lock *fl) 6598c2ecf20Sopenharmony_ci{ 6608c2ecf20Sopenharmony_ci struct inode *inode = file_inode(filp); 6618c2ecf20Sopenharmony_ci 6628c2ecf20Sopenharmony_ci return nlmclnt_proc(NFS_SERVER(inode)->nlm_host, cmd, fl, NULL); 6638c2ecf20Sopenharmony_ci} 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_ci/* Helper functions for NFS lock bounds checking */ 6668c2ecf20Sopenharmony_ci#define NFS_LOCK32_OFFSET_MAX ((__s32)0x7fffffffUL) 6678c2ecf20Sopenharmony_cistatic int nfs_lock_check_bounds(const struct file_lock *fl) 6688c2ecf20Sopenharmony_ci{ 6698c2ecf20Sopenharmony_ci __s32 start, end; 6708c2ecf20Sopenharmony_ci 6718c2ecf20Sopenharmony_ci start = (__s32)fl->fl_start; 6728c2ecf20Sopenharmony_ci if ((loff_t)start != fl->fl_start) 6738c2ecf20Sopenharmony_ci goto out_einval; 6748c2ecf20Sopenharmony_ci 6758c2ecf20Sopenharmony_ci if (fl->fl_end != OFFSET_MAX) { 6768c2ecf20Sopenharmony_ci end = (__s32)fl->fl_end; 6778c2ecf20Sopenharmony_ci if ((loff_t)end != fl->fl_end) 6788c2ecf20Sopenharmony_ci goto out_einval; 6798c2ecf20Sopenharmony_ci } else 6808c2ecf20Sopenharmony_ci end = NFS_LOCK32_OFFSET_MAX; 6818c2ecf20Sopenharmony_ci 6828c2ecf20Sopenharmony_ci if (start < 0 || start > end) 6838c2ecf20Sopenharmony_ci goto out_einval; 6848c2ecf20Sopenharmony_ci return 0; 6858c2ecf20Sopenharmony_ciout_einval: 6868c2ecf20Sopenharmony_ci return -EINVAL; 6878c2ecf20Sopenharmony_ci} 6888c2ecf20Sopenharmony_ci 6898c2ecf20Sopenharmony_cistatic int nfs_have_delegation(struct inode *inode, fmode_t flags) 6908c2ecf20Sopenharmony_ci{ 6918c2ecf20Sopenharmony_ci return 0; 6928c2ecf20Sopenharmony_ci} 6938c2ecf20Sopenharmony_ci 6948c2ecf20Sopenharmony_cistatic const struct inode_operations nfs_dir_inode_operations = { 6958c2ecf20Sopenharmony_ci .create = nfs_create, 6968c2ecf20Sopenharmony_ci .lookup = nfs_lookup, 6978c2ecf20Sopenharmony_ci .link = nfs_link, 6988c2ecf20Sopenharmony_ci .unlink = nfs_unlink, 6998c2ecf20Sopenharmony_ci .symlink = nfs_symlink, 7008c2ecf20Sopenharmony_ci .mkdir = nfs_mkdir, 7018c2ecf20Sopenharmony_ci .rmdir = nfs_rmdir, 7028c2ecf20Sopenharmony_ci .mknod = nfs_mknod, 7038c2ecf20Sopenharmony_ci .rename = nfs_rename, 7048c2ecf20Sopenharmony_ci .permission = nfs_permission, 7058c2ecf20Sopenharmony_ci .getattr = nfs_getattr, 7068c2ecf20Sopenharmony_ci .setattr = nfs_setattr, 7078c2ecf20Sopenharmony_ci}; 7088c2ecf20Sopenharmony_ci 7098c2ecf20Sopenharmony_cistatic const struct inode_operations nfs_file_inode_operations = { 7108c2ecf20Sopenharmony_ci .permission = nfs_permission, 7118c2ecf20Sopenharmony_ci .getattr = nfs_getattr, 7128c2ecf20Sopenharmony_ci .setattr = nfs_setattr, 7138c2ecf20Sopenharmony_ci}; 7148c2ecf20Sopenharmony_ci 7158c2ecf20Sopenharmony_ciconst struct nfs_rpc_ops nfs_v2_clientops = { 7168c2ecf20Sopenharmony_ci .version = 2, /* protocol version */ 7178c2ecf20Sopenharmony_ci .dentry_ops = &nfs_dentry_operations, 7188c2ecf20Sopenharmony_ci .dir_inode_ops = &nfs_dir_inode_operations, 7198c2ecf20Sopenharmony_ci .file_inode_ops = &nfs_file_inode_operations, 7208c2ecf20Sopenharmony_ci .file_ops = &nfs_file_operations, 7218c2ecf20Sopenharmony_ci .getroot = nfs_proc_get_root, 7228c2ecf20Sopenharmony_ci .submount = nfs_submount, 7238c2ecf20Sopenharmony_ci .try_get_tree = nfs_try_get_tree, 7248c2ecf20Sopenharmony_ci .getattr = nfs_proc_getattr, 7258c2ecf20Sopenharmony_ci .setattr = nfs_proc_setattr, 7268c2ecf20Sopenharmony_ci .lookup = nfs_proc_lookup, 7278c2ecf20Sopenharmony_ci .access = NULL, /* access */ 7288c2ecf20Sopenharmony_ci .readlink = nfs_proc_readlink, 7298c2ecf20Sopenharmony_ci .create = nfs_proc_create, 7308c2ecf20Sopenharmony_ci .remove = nfs_proc_remove, 7318c2ecf20Sopenharmony_ci .unlink_setup = nfs_proc_unlink_setup, 7328c2ecf20Sopenharmony_ci .unlink_rpc_prepare = nfs_proc_unlink_rpc_prepare, 7338c2ecf20Sopenharmony_ci .unlink_done = nfs_proc_unlink_done, 7348c2ecf20Sopenharmony_ci .rename_setup = nfs_proc_rename_setup, 7358c2ecf20Sopenharmony_ci .rename_rpc_prepare = nfs_proc_rename_rpc_prepare, 7368c2ecf20Sopenharmony_ci .rename_done = nfs_proc_rename_done, 7378c2ecf20Sopenharmony_ci .link = nfs_proc_link, 7388c2ecf20Sopenharmony_ci .symlink = nfs_proc_symlink, 7398c2ecf20Sopenharmony_ci .mkdir = nfs_proc_mkdir, 7408c2ecf20Sopenharmony_ci .rmdir = nfs_proc_rmdir, 7418c2ecf20Sopenharmony_ci .readdir = nfs_proc_readdir, 7428c2ecf20Sopenharmony_ci .mknod = nfs_proc_mknod, 7438c2ecf20Sopenharmony_ci .statfs = nfs_proc_statfs, 7448c2ecf20Sopenharmony_ci .fsinfo = nfs_proc_fsinfo, 7458c2ecf20Sopenharmony_ci .pathconf = nfs_proc_pathconf, 7468c2ecf20Sopenharmony_ci .decode_dirent = nfs2_decode_dirent, 7478c2ecf20Sopenharmony_ci .pgio_rpc_prepare = nfs_proc_pgio_rpc_prepare, 7488c2ecf20Sopenharmony_ci .read_setup = nfs_proc_read_setup, 7498c2ecf20Sopenharmony_ci .read_done = nfs_read_done, 7508c2ecf20Sopenharmony_ci .write_setup = nfs_proc_write_setup, 7518c2ecf20Sopenharmony_ci .write_done = nfs_write_done, 7528c2ecf20Sopenharmony_ci .commit_setup = nfs_proc_commit_setup, 7538c2ecf20Sopenharmony_ci .commit_rpc_prepare = nfs_proc_commit_rpc_prepare, 7548c2ecf20Sopenharmony_ci .lock = nfs_proc_lock, 7558c2ecf20Sopenharmony_ci .lock_check_bounds = nfs_lock_check_bounds, 7568c2ecf20Sopenharmony_ci .close_context = nfs_close_context, 7578c2ecf20Sopenharmony_ci .have_delegation = nfs_have_delegation, 7588c2ecf20Sopenharmony_ci .alloc_client = nfs_alloc_client, 7598c2ecf20Sopenharmony_ci .init_client = nfs_init_client, 7608c2ecf20Sopenharmony_ci .free_client = nfs_free_client, 7618c2ecf20Sopenharmony_ci .create_server = nfs_create_server, 7628c2ecf20Sopenharmony_ci .clone_server = nfs_clone_server, 7638c2ecf20Sopenharmony_ci}; 764