xref: /kernel/linux/linux-6.6/fs/nfs/proc.c (revision 62306a36)
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