view usr/src/uts/common/fs/nfs/nfs4_common.c @ 13799:0b5d8823b20a

3133 nfs4: remove static for nfs4_max_xxx Reviewed by: Eric Schrock <eric.schrock@delphix.com> Approved by: Richard Lowe <richlowe@richlowe.net>
author Vitaliy Gusev <gusev.vitaliy@nexenta.com>
date Wed, 29 Aug 2012 01:06:55 +0000
parents 9f2cda0ed938
children
line wrap: on
line source

/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
 *
 * Copyright 2011, 2012 Nexenta Systems, Inc. All rights reserved.
 */

/*
 * This is the loadable module wrapper.
 */
#include <sys/systm.h>
#include <sys/modctl.h>
#include <sys/syscall.h>
#include <sys/ddi.h>
#include <sys/cmn_err.h>

#include <nfs/nfs.h>
#include <nfs/nfs_clnt.h>
#include <nfs/nfs4.h>
#include <nfs/rnode4.h>

/*
 * The global tag list.
 */
ctag_t nfs4_ctags[] = NFS4_TAG_INITIALIZER;

/*
 * The NFS Version 4 client VFS.
 */
static vfsdef_t vfw4 = {
	VFSDEF_VERSION,
	"nfs4",
	nfs4init,
	VSW_CANREMOUNT|VSW_NOTZONESAFE|VSW_STATS|VSW_ZMOUNT,
	NULL
};

struct modlfs modlfs4 = {
	&mod_fsops,
	"network filesystem version 4",
	&vfw4
};

uint_t nfs4_max_transfer_size = 32 * 1024;
uint_t nfs4_max_transfer_size_cots = 1024 * 1024;
uint_t nfs4_max_transfer_size_rdma = 1024 * 1024;

int
nfs4tsize(void)
{
	/*
	 * For the moment, just return nfs4_max_transfer_size until we
	 * can query the appropriate transport.
	 */
	return (nfs4_max_transfer_size);
}

uint_t
nfs4_tsize(struct knetconfig *knp)
{

	if (knp->knc_semantics == NC_TPI_COTS_ORD ||
	    knp->knc_semantics == NC_TPI_COTS)
		return (nfs4_max_transfer_size_cots);
	if (knp->knc_semantics == NC_TPI_RDMA)
		return (nfs4_max_transfer_size_rdma);
	return (nfs4_max_transfer_size);
}

uint_t
rfs4_tsize(struct svc_req *req)
{

	if (req->rq_xprt->xp_type == T_COTS_ORD ||
	    req->rq_xprt->xp_type == T_COTS)
		return (nfs4_max_transfer_size_cots);
	if (req->rq_xprt->xp_type == T_RDMA)
		return (nfs4_max_transfer_size_rdma);
	return (nfs4_max_transfer_size);
}

int
nfs4_setopts(vnode_t *vp, model_t model, struct nfs_args *buf)
{
	mntinfo4_t *mi;			/* mount info, pointed at by vfs */
	STRUCT_HANDLE(nfs_args, args);
	int flags;

#ifdef lint
	model = model;
#endif

	STRUCT_SET_HANDLE(args, model, buf);

	flags = STRUCT_FGET(args, flags);

	/*
	 * Set option fields in mount info record
	 */
	mi = VTOMI4(vp);


	if (flags & NFSMNT_NOAC) {
		mutex_enter(&mi->mi_lock);
		mi->mi_flags |= MI4_NOAC;
		mutex_exit(&mi->mi_lock);
		PURGE_ATTRCACHE4(vp);
	}

	mutex_enter(&mi->mi_lock);
	if (flags & NFSMNT_NOCTO)
		mi->mi_flags |= MI4_NOCTO;
	if (flags & NFSMNT_LLOCK)
		mi->mi_flags |= MI4_LLOCK;
	if (flags & NFSMNT_GRPID)
		mi->mi_flags |= MI4_GRPID;
	mutex_exit(&mi->mi_lock);

	if (flags & NFSMNT_RETRANS) {
		if (STRUCT_FGET(args, retrans) < 0)
			return (EINVAL);
		mi->mi_retrans = STRUCT_FGET(args, retrans);
	}
	if (flags & NFSMNT_TIMEO) {
		if (STRUCT_FGET(args, timeo) <= 0)
			return (EINVAL);
		mi->mi_timeo = STRUCT_FGET(args, timeo);
	}
	if (flags & NFSMNT_RSIZE) {
		if (STRUCT_FGET(args, rsize) <= 0)
			return (EINVAL);
		mi->mi_tsize = MIN(mi->mi_tsize, STRUCT_FGET(args, rsize));
		mi->mi_curread = MIN(mi->mi_curread, mi->mi_tsize);
	}
	if (flags & NFSMNT_WSIZE) {
		if (STRUCT_FGET(args, wsize) <= 0)
			return (EINVAL);
		mi->mi_stsize = MIN(mi->mi_stsize, STRUCT_FGET(args, wsize));
		mi->mi_curwrite = MIN(mi->mi_curwrite, mi->mi_stsize);
	}
	if (flags & NFSMNT_ACREGMIN) {
		if (STRUCT_FGET(args, acregmin) < 0)
			mi->mi_acregmin = SEC2HR(ACMINMAX);
		else
			mi->mi_acregmin = SEC2HR(MIN(STRUCT_FGET(args,
			    acregmin), ACMINMAX));
	}
	if (flags & NFSMNT_ACREGMAX) {
		if (STRUCT_FGET(args, acregmax) < 0)
			mi->mi_acregmax = SEC2HR(ACMAXMAX);
		else
			mi->mi_acregmax = SEC2HR(MIN(STRUCT_FGET(args,
			    acregmax), ACMAXMAX));
	}
	if (flags & NFSMNT_ACDIRMIN) {
		if (STRUCT_FGET(args, acdirmin) < 0)
			mi->mi_acdirmin = SEC2HR(ACMINMAX);
		else
			mi->mi_acdirmin = SEC2HR(MIN(STRUCT_FGET(args,
			    acdirmin), ACMINMAX));
	}
	if (flags & NFSMNT_ACDIRMAX) {
		if (STRUCT_FGET(args, acdirmax) < 0)
			mi->mi_acdirmax = SEC2HR(ACMAXMAX);
		else
			mi->mi_acdirmax = SEC2HR(MIN(STRUCT_FGET(args,
			    acdirmax), ACMAXMAX));
	}

	return (0);
}

/*
 * This returns 1 if the seqid should be bumped upon receiving this
 * 'res->status' for a seqid dependent operation; otherwise return 0.
 */
int
nfs4_need_to_bump_seqid(COMPOUND4res_clnt *res)
{
	int i, seqid_dep_op = 0;
	nfs_resop4 *resop;

	resop = res->array;

	for (i = 0; i < res->array_len; i++) {
		switch (resop[i].resop) {
		case OP_CLOSE:
		case OP_OPEN:
		case OP_OPEN_CONFIRM:
		case OP_OPEN_DOWNGRADE:
		case OP_LOCK:
		case OP_LOCKU:
			seqid_dep_op = 1;
			break;
		default:
			continue;
		}
	}

	if (!seqid_dep_op)
		return (0);

	switch (res->status) {
	case NFS4ERR_STALE_CLIENTID:
	case NFS4ERR_STALE_STATEID:
	case NFS4ERR_BAD_STATEID:
	case NFS4ERR_BAD_SEQID:
	case NFS4ERR_BADXDR:
	case NFS4ERR_OLD_STATEID:
	case NFS4ERR_RESOURCE:
	case NFS4ERR_NOFILEHANDLE:
		return (0);
	default:
		return (1);
	}
}

/*
 * Returns 1 if the error is a RPC error that we should retry.
 */
int
nfs4_rpc_retry_error(int error)
{
	switch (error) {
	case ETIMEDOUT:
	case ECONNREFUSED:
	case ENETDOWN:
	case ENETUNREACH:
	case ENETRESET:
	case ECONNABORTED:
	case EHOSTUNREACH:
	case ECONNRESET:
		return (1);
	default:
		return (0);
	}
}

char *
nfs4_stat_to_str(nfsstat4 error)
{
	static char	buf[40];

	switch (error) {
	case NFS4_OK:
		return ("NFS4_OK");
	case NFS4ERR_PERM:
		return ("NFS4ERR_PERM");
	case NFS4ERR_NOENT:
		return ("NFS4ERR_NOENT");
	case NFS4ERR_IO:
		return ("NFS4ERR_IO");
	case NFS4ERR_NXIO:
		return ("NFS4ERR_NXIO");
	case NFS4ERR_ACCESS:
		return ("NFS4ERR_ACCESS");
	case NFS4ERR_EXIST:
		return ("NFS4ERR_EXIST");
	case NFS4ERR_XDEV:
		return ("NFS4ERR_XDEV");
	case NFS4ERR_NOTDIR:
		return ("NFS4ERR_NOTDIR");
	case NFS4ERR_ISDIR:
		return ("NFS4ERR_ISDIR");
	case NFS4ERR_INVAL:
		return ("NFS4ERR_INVAL");
	case NFS4ERR_FBIG:
		return ("NFS4ERR_FBIG");
	case NFS4ERR_NOSPC:
		return ("NFS4ERR_NOSPC");
	case NFS4ERR_ROFS:
		return ("NFS4ERR_ROFS");
	case NFS4ERR_MLINK:
		return ("NFS4ERR_MLINK");
	case NFS4ERR_NAMETOOLONG:
		return ("NFS4ERR_NAMETOOLONG");
	case NFS4ERR_NOTEMPTY:
		return ("NFSS4ERR_NOTEMPTY");
	case NFS4ERR_DQUOT:
		return ("NFS4ERR_DQUOT");
	case NFS4ERR_STALE:
		return ("NFS4ERR_STALE");
	case NFS4ERR_BADHANDLE:
		return ("NFS4ERR_BADHANDLE");
	case NFS4ERR_BAD_COOKIE:
		return ("NFS4ERR_BAD_COOKIE");
	case NFS4ERR_NOTSUPP:
		return ("NFS4ERR_NOTSUPP");
	case NFS4ERR_TOOSMALL:
		return ("NFS4ERR_TOOSMALL");
	case NFS4ERR_SERVERFAULT:
		return ("NFS4ERR_SERVERFAULT");
	case NFS4ERR_BADTYPE:
		return ("NFS4ERR_BADTYPE");
	case NFS4ERR_DELAY:
		return ("NFS4ERR_DELAY");
	case NFS4ERR_SAME:
		return ("NFS4ERR_SAME");
	case NFS4ERR_DENIED:
		return ("NFS4ERR_DENIED");
	case NFS4ERR_EXPIRED:
		return ("NFS4ERR_EXPIRED");
	case NFS4ERR_LOCKED:
		return ("NFS4ERR_LOCKED");
	case NFS4ERR_GRACE:
		return ("NFS4ERR_GRACE");
	case NFS4ERR_FHEXPIRED:
		return ("NFS4ERR_FHEXPIRED");
	case NFS4ERR_SHARE_DENIED:
		return ("NFS4ERR_SHARE_DENIED");
	case NFS4ERR_WRONGSEC:
		return ("NFS4ERR_WRONGSEC");
	case NFS4ERR_CLID_INUSE:
		return ("NFS4ERR_CLID_INUSE");
	case NFS4ERR_RESOURCE:
		return ("NFS4ERR_RESOURCE");
	case NFS4ERR_MOVED:
		return ("NFS4ERR_MOVED");
	case NFS4ERR_NOFILEHANDLE:
		return ("NFS4ERR_NOFILEHANDLE");
	case NFS4ERR_MINOR_VERS_MISMATCH:
		return ("NFS4ERR_MINOR_VERS_MISMATCH");
	case NFS4ERR_STALE_CLIENTID:
		return ("NFS4ERR_STALE_CLIENTID");
	case NFS4ERR_STALE_STATEID:
		return ("NFS4ERR_STALE_STATEID");
	case NFS4ERR_OLD_STATEID:
		return ("NFS4ERR_OLD_STATEID");
	case NFS4ERR_BAD_STATEID:
		return ("NFS4ERR_BAD_STATEID");
	case NFS4ERR_BAD_SEQID:
		return ("NFS4ERR_BAD_SEQID");
	case NFS4ERR_NOT_SAME:
		return ("NFS4ERR_NOT_SAME");
	case NFS4ERR_LOCK_RANGE:
		return ("NFS4ERR_LOCK_RANGE");
	case NFS4ERR_SYMLINK:
		return ("NFS4ERR_SYMLINK");
	case NFS4ERR_RESTOREFH:
		return ("NFS4ERR_RESTOREFH");
	case NFS4ERR_LEASE_MOVED:
		return ("NFS4ERR_LEASE_MOVED");
	case NFS4ERR_ATTRNOTSUPP:
		return ("NFS4ERR_ATTRNOTSUPP");
	case NFS4ERR_NO_GRACE:
		return ("NFS4ERR_NO_GRACE");
	case NFS4ERR_RECLAIM_BAD:
		return ("NFS4ERR_RECLAIM_BAD");
	case NFS4ERR_RECLAIM_CONFLICT:
		return ("NFS4ERR_RECLAIM_CONFLICT");
	case NFS4ERR_BADXDR:
		return ("NFS4ERR_BADXDR");
	case NFS4ERR_LOCKS_HELD:
		return ("NFS4ERR_LOCKS_HELD");
	case NFS4ERR_OPENMODE:
		return ("NFS4ERR_OPENMODE");
	case NFS4ERR_BADOWNER:
		return ("NFS4ERR_BADOWNER");
	case NFS4ERR_BADCHAR:
		return ("NFS4ERR_BADCHAR");
	case NFS4ERR_BADNAME:
		return ("NFS4ERR_BADNAME");
	case NFS4ERR_BAD_RANGE:
		return ("NFS4ERR_BAD_RANGE");
	case NFS4ERR_LOCK_NOTSUPP:
		return ("NFS4ERR_LOCK_NOTSUPP");
	case NFS4ERR_OP_ILLEGAL:
		return ("NFS4ERR_OP_ILLEGAL");
	case NFS4ERR_DEADLOCK:
		return ("NFS4ERR_DEADLOCK");
	case NFS4ERR_FILE_OPEN:
		return ("NFS4ERR_FILE_OPEN");
	case NFS4ERR_ADMIN_REVOKED:
		return ("NFS4ERR_ADMIN_REVOKED");
	case NFS4ERR_CB_PATH_DOWN:
		return ("NFS4ERR_CB_PATH_DOWN");
	default:
		(void) snprintf(buf, 40, "Unknown error %d", (int)error);
		return (buf);
	}
}

char *
nfs4_recov_action_to_str(nfs4_recov_t what)
{
	static char buf[40];

	switch (what) {
	case NR_STALE:
		return ("NR_STALE");
	case NR_FAILOVER:
		return ("NR_FAILOVER");
	case NR_CLIENTID:
		return ("NR_CLIENTID");
	case NR_OPENFILES:
		return ("NR_OPENFILES");
	case NR_WRONGSEC:
		return ("NR_WRONGSEC");
	case NR_EXPIRED:
		return ("NR_EXPIRED");
	case NR_BAD_STATEID:
		return ("NR_BAD_STATEID");
	case NR_FHEXPIRED:
		return ("NR_FHEXPIRED");
	case NR_BADHANDLE:
		return ("NR_BADHANDLE");
	case NR_BAD_SEQID:
		return ("NR_BAD_SEQID");
	case NR_OLDSTATEID:
		return ("NR_OLDSTATEID");
	case NR_GRACE:
		return ("NR_GRACE");
	case NR_DELAY:
		return ("NR_DELAY");
	case NR_LOST_LOCK:
		return ("NR_LOST_LOCK");
	case NR_LOST_STATE_RQST:
		return ("NR_LOST_STATE_RQST");
	case NR_MOVED:
		return ("NR_MOVED");
	default:
		(void) snprintf(buf, 40, "Unknown, code %d", (int)what);
		return (buf);
	}
}

char *
nfs4_op_to_str(nfs_opnum4 op)
{
	static char buf[40];

	switch (REAL_OP4(op)) {
	case OP_ACCESS:
		return ("OP_ACCESS");
	case OP_CLOSE:
		return ("OP_CLOSE");
	case OP_COMMIT:
		return ("OP_COMMIT");
	case OP_CREATE:
		return ("OP_CREATE");
	case OP_DELEGPURGE:
		return ("OP_DELEGPURGE");
	case OP_DELEGRETURN:
		return ("OP_DELEGRETURN");
	case OP_GETATTR:
		return ("OP_GETATTR");
	case OP_GETFH:
		return ("OP_GETFH");
	case OP_LINK:
		return ("OP_LINK");
	case OP_LOCK:
		return ("OP_LOCK");
	case OP_LOCKT:
		return ("OP_LOCKT");
	case OP_LOCKU:
		return ("OP_LOCKU");
	case OP_LOOKUP:
		return ("OP_LOOKUP");
	case OP_LOOKUPP:
		return ("OP_LOOKUPP");
	case OP_NVERIFY:
		return ("OP_NVERIFY");
	case OP_OPEN:
		return ("OP_OPEN");
	case OP_OPENATTR:
		return ("OP_OPENATTR");
	case OP_OPEN_CONFIRM:
		return ("OP_OPEN_CONFIRM");
	case OP_OPEN_DOWNGRADE:
		return ("OP_OPEN_DOWNGRADE");
	case OP_PUTFH:
		return ("OP_PUTFH");
	case OP_PUTPUBFH:
		return ("OP_PUTPUBFH");
	case OP_PUTROOTFH:
		return ("OP_PUTROOTFH");
	case OP_READ:
		return ("OP_READ");
	case OP_READDIR:
		return ("OP_READDIR");
	case OP_READLINK:
		return ("OP_READLINK");
	case OP_REMOVE:
		return ("OP_REMOVE");
	case OP_RENAME:
		return ("OP_RENAME");
	case OP_RENEW:
		return ("OP_RENEW");
	case OP_RESTOREFH:
		return ("OP_RESTOREFH");
	case OP_SAVEFH:
		return ("OP_SAVEFH");
	case OP_SECINFO:
		return ("OP_SECINFO");
	case OP_SETATTR:
		return ("OP_SETATTR");
	case OP_SETCLIENTID:
		return ("OP_SETCLIENTID");
	case OP_SETCLIENTID_CONFIRM:
		return ("OP_SETCLIENTID_CONFIRM");
	case OP_VERIFY:
		return ("OP_VERIFY");
	case OP_WRITE:
		return ("OP_WRITE");
	case OP_RELEASE_LOCKOWNER:
		return ("OP_RELEASE_LOCKOWNER");
	case OP_ILLEGAL:
		return ("OP_ILLEGAL");
	default:
		(void) snprintf(buf, 40, "Unknown op %d", (int)op);
		return (buf);
	}
}