xref: /onnv-gate/usr/src/uts/common/fs/nfs/nfs_dump.c (revision 11066:cebb50cbe4f9)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
55331Samw  * Common Development and Distribution License (the "License").
65331Samw  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*11066Srafael.vanoni@sun.com  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate /*
270Sstevel@tonic-gate  * Dump memory to NFS swap file after a panic.
280Sstevel@tonic-gate  * We have no timeouts, context switches, etc.
290Sstevel@tonic-gate  */
30*11066Srafael.vanoni@sun.com 
310Sstevel@tonic-gate #include <rpc/types.h>
320Sstevel@tonic-gate #include <sys/param.h>
330Sstevel@tonic-gate #include <sys/errno.h>
340Sstevel@tonic-gate #include <sys/vnode.h>
350Sstevel@tonic-gate #include <sys/bootconf.h>
360Sstevel@tonic-gate #include <nfs/nfs.h>
370Sstevel@tonic-gate #include <rpc/auth.h>
380Sstevel@tonic-gate #include <rpc/xdr.h>
390Sstevel@tonic-gate #include <rpc/rpc_msg.h>
400Sstevel@tonic-gate #include <rpc/clnt.h>
410Sstevel@tonic-gate #include <netinet/in.h>
420Sstevel@tonic-gate #include <sys/tiuser.h>
430Sstevel@tonic-gate #include <nfs/nfs_clnt.h>
440Sstevel@tonic-gate #include <sys/t_kuser.h>
450Sstevel@tonic-gate #include <sys/file.h>
460Sstevel@tonic-gate #include <sys/netconfig.h>
470Sstevel@tonic-gate #include <sys/utsname.h>
480Sstevel@tonic-gate #include <sys/sysmacros.h>
490Sstevel@tonic-gate #include <sys/thread.h>
500Sstevel@tonic-gate #include <sys/cred.h>
510Sstevel@tonic-gate #include <sys/strsubr.h>
520Sstevel@tonic-gate #include <nfs/rnode.h>
530Sstevel@tonic-gate #include <sys/varargs.h>
540Sstevel@tonic-gate #include <sys/cmn_err.h>
550Sstevel@tonic-gate #include <sys/systm.h>
560Sstevel@tonic-gate #include <sys/dumphdr.h>
570Sstevel@tonic-gate #include <sys/debug.h>
580Sstevel@tonic-gate #include <sys/sunddi.h>
590Sstevel@tonic-gate 
600Sstevel@tonic-gate #define	TIMEOUT		(2 * hz)
610Sstevel@tonic-gate #define	RETRIES		(5)
620Sstevel@tonic-gate #define	HDR_SIZE	(256)
630Sstevel@tonic-gate 
640Sstevel@tonic-gate static struct knetconfig	nfsdump_cf;
650Sstevel@tonic-gate static struct netbuf		nfsdump_addr;
660Sstevel@tonic-gate static fhandle_t		nfsdump_fhandle2;
670Sstevel@tonic-gate static nfs_fh3			nfsdump_fhandle3;
680Sstevel@tonic-gate static int			nfsdump_maxcount;
690Sstevel@tonic-gate static rpcvers_t		nfsdump_version;
700Sstevel@tonic-gate 
710Sstevel@tonic-gate /*
720Sstevel@tonic-gate  * nonzero dumplog enables nd_log messages
730Sstevel@tonic-gate  */
740Sstevel@tonic-gate static int 	dumplog = 0;
750Sstevel@tonic-gate 
760Sstevel@tonic-gate static int	nd_init(vnode_t *, TIUSER **);
770Sstevel@tonic-gate static int	nd_poll(TIUSER *, int, int *);
780Sstevel@tonic-gate static int	nd_send_data(TIUSER *, caddr_t, int, XDR *, uint32_t *);
790Sstevel@tonic-gate static int	nd_get_reply(TIUSER *, XDR *, uint32_t, int *);
800Sstevel@tonic-gate static int	nd_auth_marshall(XDR *);
810Sstevel@tonic-gate 
820Sstevel@tonic-gate static void nd_log(const char *, ...) __KPRINTFLIKE(1);
830Sstevel@tonic-gate 
840Sstevel@tonic-gate /*PRINTFLIKE1*/
850Sstevel@tonic-gate static void
nd_log(const char * fmt,...)860Sstevel@tonic-gate nd_log(const char *fmt, ...)
870Sstevel@tonic-gate {
880Sstevel@tonic-gate 	if (dumplog) {
890Sstevel@tonic-gate 		va_list adx;
900Sstevel@tonic-gate 
910Sstevel@tonic-gate 		va_start(adx, fmt);
920Sstevel@tonic-gate 		vprintf(fmt, adx);
930Sstevel@tonic-gate 		va_end(adx);
940Sstevel@tonic-gate 	}
950Sstevel@tonic-gate }
960Sstevel@tonic-gate 
975331Samw /* ARGSUSED */
980Sstevel@tonic-gate int
nfs_dump(vnode_t * dumpvp,caddr_t addr,offset_t bn,offset_t count,caller_context_t * ct)996264Srm15945 nfs_dump(vnode_t *dumpvp, caddr_t addr, offset_t bn, offset_t count,
1006264Srm15945     caller_context_t *ct)
1010Sstevel@tonic-gate {
1020Sstevel@tonic-gate 	static TIUSER	*tiptr;
1030Sstevel@tonic-gate 	XDR		xdrs;
1040Sstevel@tonic-gate 	int		reply;
1050Sstevel@tonic-gate 	int		badmsg;
1060Sstevel@tonic-gate 	uint32_t	call_xid;
1070Sstevel@tonic-gate 	int		retry = 0;
1080Sstevel@tonic-gate 	int		error;
1090Sstevel@tonic-gate 	int		i;
1100Sstevel@tonic-gate 
1116264Srm15945 	nd_log("nfs_dump: addr=%p bn=%lld count=%lld\n",
1126264Srm15945 	    (void *)addr, bn, count);
1130Sstevel@tonic-gate 
1140Sstevel@tonic-gate 	if (error = nd_init(dumpvp, &tiptr))
1150Sstevel@tonic-gate 		return (error);
1160Sstevel@tonic-gate 
1170Sstevel@tonic-gate 	for (i = 0; i < count; i += ptod(1), addr += ptob(1)) {
1180Sstevel@tonic-gate 		do {
1190Sstevel@tonic-gate 			error = nd_send_data(tiptr, addr, (int)dbtob(bn + i),
1200Sstevel@tonic-gate 			    &xdrs, &call_xid);
1210Sstevel@tonic-gate 			if (error)
1220Sstevel@tonic-gate 				return (error);
1230Sstevel@tonic-gate 
1240Sstevel@tonic-gate 			do {
1250Sstevel@tonic-gate 				if (error = nd_poll(tiptr, retry, &reply))
1260Sstevel@tonic-gate 					return (error);
1270Sstevel@tonic-gate 
1280Sstevel@tonic-gate 				if (!reply) {
1290Sstevel@tonic-gate 					retry++;
1300Sstevel@tonic-gate 					break;
1310Sstevel@tonic-gate 				}
1320Sstevel@tonic-gate 				retry = 0;
1330Sstevel@tonic-gate 
1340Sstevel@tonic-gate 				error = nd_get_reply(tiptr, &xdrs, call_xid,
1350Sstevel@tonic-gate 				    &badmsg);
1360Sstevel@tonic-gate 				if (error)
1370Sstevel@tonic-gate 					return (error);
1380Sstevel@tonic-gate 			} while (badmsg);
1390Sstevel@tonic-gate 		} while (retry);
1400Sstevel@tonic-gate 	}
1410Sstevel@tonic-gate 
1420Sstevel@tonic-gate 	return (0);
1430Sstevel@tonic-gate }
1440Sstevel@tonic-gate 
1450Sstevel@tonic-gate static int
nd_init(vnode_t * dumpvp,TIUSER ** tiptr)1460Sstevel@tonic-gate nd_init(vnode_t *dumpvp, TIUSER **tiptr)
1470Sstevel@tonic-gate {
1480Sstevel@tonic-gate 	int 		error;
1490Sstevel@tonic-gate 
1500Sstevel@tonic-gate 	if (*tiptr)
1510Sstevel@tonic-gate 		return (0);
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate 	/*
1540Sstevel@tonic-gate 	 * If dump info hasn't yet been initialized (because dump
1550Sstevel@tonic-gate 	 * device was chosen at user-level, rather than at boot time
1560Sstevel@tonic-gate 	 * in nfs_swapvp) fill it in now.
1570Sstevel@tonic-gate 	 */
1580Sstevel@tonic-gate 	if (nfsdump_maxcount == 0) {
1590Sstevel@tonic-gate 		nfsdump_version = VTOMI(dumpvp)->mi_vers;
1600Sstevel@tonic-gate 		switch (nfsdump_version) {
1610Sstevel@tonic-gate 		case NFS_VERSION:
1620Sstevel@tonic-gate 			nfsdump_fhandle2 = *VTOFH(dumpvp);
1630Sstevel@tonic-gate 			break;
1640Sstevel@tonic-gate 		case NFS_V3:
1650Sstevel@tonic-gate 			nfsdump_fhandle3 = *VTOFH3(dumpvp);
1660Sstevel@tonic-gate 			break;
1670Sstevel@tonic-gate 		default:
1680Sstevel@tonic-gate 			return (EIO);
1690Sstevel@tonic-gate 		}
1700Sstevel@tonic-gate 		nfsdump_maxcount = (int)dumpvp_size;
1710Sstevel@tonic-gate 		nfsdump_addr = VTOMI(dumpvp)->mi_curr_serv->sv_addr;
1720Sstevel@tonic-gate 		nfsdump_cf = *(VTOMI(dumpvp)->mi_curr_serv->sv_knconf);
1730Sstevel@tonic-gate 		if (nfsdump_cf.knc_semantics != NC_TPI_CLTS) {
1740Sstevel@tonic-gate 			int v6 = 1;
1750Sstevel@tonic-gate 			nd_log("nfs_dump: not connectionless!\n");
1760Sstevel@tonic-gate 			if ((strcmp(nfsdump_cf.knc_protofmly, NC_INET) == 0) ||
1770Sstevel@tonic-gate 			    ((v6 = strcmp(nfsdump_cf.knc_protofmly, NC_INET6))\
1786264Srm15945 			    == 0)) {
1790Sstevel@tonic-gate 				major_t clone_maj;
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate 				nfsdump_cf.knc_proto = NC_UDP;
1820Sstevel@tonic-gate 				nfsdump_cf.knc_semantics = NC_TPI_CLTS;
1830Sstevel@tonic-gate 				nd_log("nfs_dump: grabbing UDP major number\n");
1840Sstevel@tonic-gate 				clone_maj = ddi_name_to_major("clone");
1850Sstevel@tonic-gate 				nd_log("nfs_dump: making UDP device\n");
1860Sstevel@tonic-gate 				nfsdump_cf.knc_rdev = makedevice(clone_maj,
1876264Srm15945 				    ddi_name_to_major(v6?"udp":"udp6"));
1880Sstevel@tonic-gate 			} else {
1890Sstevel@tonic-gate 				error = EIO;
1900Sstevel@tonic-gate 				nfs_perror(error, "\nnfs_dump: cannot dump over"
1910Sstevel@tonic-gate 				    " protocol %s: %m\n", nfsdump_cf.knc_proto);
1920Sstevel@tonic-gate 				return (error);
1930Sstevel@tonic-gate 			}
1940Sstevel@tonic-gate 		}
1950Sstevel@tonic-gate 	}
1960Sstevel@tonic-gate 
1970Sstevel@tonic-gate 	nd_log("nfs_dump: calling t_kopen\n");
1980Sstevel@tonic-gate 
1990Sstevel@tonic-gate 	if (error = t_kopen(NULL, nfsdump_cf.knc_rdev,
2006264Srm15945 	    FREAD|FWRITE|FNDELAY, tiptr, CRED())) {
2010Sstevel@tonic-gate 		nfs_perror(error, "\nnfs_dump: t_kopen failed: %m\n");
2020Sstevel@tonic-gate 		return (EIO);
2030Sstevel@tonic-gate 	}
2040Sstevel@tonic-gate 
2050Sstevel@tonic-gate 	if ((strcmp(nfsdump_cf.knc_protofmly, NC_INET) == 0) ||
2060Sstevel@tonic-gate 	    (strcmp(nfsdump_cf.knc_protofmly, NC_INET6) == 0)) {
2070Sstevel@tonic-gate 		nd_log("nfs_dump: calling bindresvport\n");
2080Sstevel@tonic-gate 		if (error = bindresvport(*tiptr, NULL, NULL, FALSE)) {
2090Sstevel@tonic-gate 			nfs_perror(error,
2106264Srm15945 			    "\nnfs_dump: bindresvport failed: %m\n");
2110Sstevel@tonic-gate 			return (EIO);
2120Sstevel@tonic-gate 		}
2130Sstevel@tonic-gate 	} else {
2140Sstevel@tonic-gate 		nd_log("nfs_dump: calling t_kbind\n");
2150Sstevel@tonic-gate 		if ((error = t_kbind(*tiptr, NULL, NULL)) != 0) {
2160Sstevel@tonic-gate 			nfs_perror(error, "\nnfs_dump: t_kbind failed: %m\n");
2170Sstevel@tonic-gate 			return (EIO);
2180Sstevel@tonic-gate 		}
2190Sstevel@tonic-gate 	}
2200Sstevel@tonic-gate 	return (0);
2210Sstevel@tonic-gate }
2220Sstevel@tonic-gate 
2230Sstevel@tonic-gate static int
nd_send_data(TIUSER * tiptr,caddr_t addr,int offset,XDR * xdrp,uint32_t * xidp)2240Sstevel@tonic-gate nd_send_data(TIUSER *tiptr, caddr_t addr, int offset, XDR *xdrp, uint32_t *xidp)
2250Sstevel@tonic-gate {
2260Sstevel@tonic-gate 	static struct rpc_msg		call_msg;
2270Sstevel@tonic-gate 	static uchar_t			header[HDR_SIZE];
2280Sstevel@tonic-gate 	static struct t_kunitdata	sudata;
2290Sstevel@tonic-gate 	static uchar_t			*dumpbuf;
2300Sstevel@tonic-gate 	int				procnum;
2310Sstevel@tonic-gate 	stable_how			stable = FILE_SYNC;
2320Sstevel@tonic-gate 	mblk_t				*mblk_p;
2330Sstevel@tonic-gate 	int				error;
2340Sstevel@tonic-gate 	int				tsize = ptob(1);
2350Sstevel@tonic-gate 	uint64				offset3;
2360Sstevel@tonic-gate 
2370Sstevel@tonic-gate 	if (!dumpbuf) {
2380Sstevel@tonic-gate 		call_msg.rm_direction = CALL;
2390Sstevel@tonic-gate 		call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
2400Sstevel@tonic-gate 		call_msg.rm_call.cb_prog = NFS_PROGRAM;
2410Sstevel@tonic-gate 		call_msg.rm_call.cb_vers = nfsdump_version;
2420Sstevel@tonic-gate 
2430Sstevel@tonic-gate 		if (!(dumpbuf = kmem_alloc(ptob(1), KM_NOSLEEP))) {
2440Sstevel@tonic-gate 		cmn_err(CE_WARN, "\tnfs_dump: cannot allocate dump buffer");
2450Sstevel@tonic-gate 			return (ENOMEM);
2460Sstevel@tonic-gate 		}
2470Sstevel@tonic-gate 	}
2480Sstevel@tonic-gate 
2490Sstevel@tonic-gate 	nd_log("nfs_dump: calling esballoc for header\n");
2500Sstevel@tonic-gate 
2510Sstevel@tonic-gate 	if (!(mblk_p = esballoc(header, HDR_SIZE, BPRI_HI, &frnop))) {
2520Sstevel@tonic-gate 		cmn_err(CE_WARN, "\tnfs_dump: out of mblks");
2530Sstevel@tonic-gate 		return (ENOBUFS);
2540Sstevel@tonic-gate 	}
2550Sstevel@tonic-gate 
2560Sstevel@tonic-gate 	xdrmem_create(xdrp, (caddr_t)header, HDR_SIZE, XDR_ENCODE);
2570Sstevel@tonic-gate 
2580Sstevel@tonic-gate 	call_msg.rm_xid = alloc_xid();
2590Sstevel@tonic-gate 	*xidp = call_msg.rm_xid;
2600Sstevel@tonic-gate 
2610Sstevel@tonic-gate 	if (!xdr_callhdr(xdrp, &call_msg)) {
2620Sstevel@tonic-gate 		cmn_err(CE_WARN, "\tnfs_dump: cannot serialize header");
2630Sstevel@tonic-gate 		return (EIO);
2640Sstevel@tonic-gate 	}
2650Sstevel@tonic-gate 
2660Sstevel@tonic-gate 	if (nfsdump_maxcount) {
2670Sstevel@tonic-gate 		/*
2680Sstevel@tonic-gate 		 * Do not extend the dump file if it is also
2690Sstevel@tonic-gate 		 * the swap file.
2700Sstevel@tonic-gate 		 */
2710Sstevel@tonic-gate 		if (offset >= nfsdump_maxcount) {
2720Sstevel@tonic-gate 			cmn_err(CE_WARN, "\tnfs_dump: end of file");
2730Sstevel@tonic-gate 			return (EIO);
2740Sstevel@tonic-gate 		}
2750Sstevel@tonic-gate 		if (offset + tsize > nfsdump_maxcount)
2760Sstevel@tonic-gate 			tsize = nfsdump_maxcount - offset;
2770Sstevel@tonic-gate 	}
2780Sstevel@tonic-gate 	switch (nfsdump_version) {
2790Sstevel@tonic-gate 	case NFS_VERSION:
2800Sstevel@tonic-gate 		procnum = RFS_WRITE;
2810Sstevel@tonic-gate 		if (!XDR_PUTINT32(xdrp, (int32_t *)&procnum) ||
2820Sstevel@tonic-gate 		    !nd_auth_marshall(xdrp) ||
2830Sstevel@tonic-gate 		    !xdr_fhandle(xdrp, &nfsdump_fhandle2) ||
2840Sstevel@tonic-gate 			/*
2850Sstevel@tonic-gate 			 *  Following four values are:
2860Sstevel@tonic-gate 			 *	beginoffset
2870Sstevel@tonic-gate 			 *	offset
2880Sstevel@tonic-gate 			 *	length
2890Sstevel@tonic-gate 			 *	bytes array length
2900Sstevel@tonic-gate 			 */
2910Sstevel@tonic-gate 		    !XDR_PUTINT32(xdrp, (int32_t *)&offset) ||
2920Sstevel@tonic-gate 		    !XDR_PUTINT32(xdrp, (int32_t *)&offset) ||
2930Sstevel@tonic-gate 		    !XDR_PUTINT32(xdrp, (int32_t *)&tsize) ||
2940Sstevel@tonic-gate 		    !XDR_PUTINT32(xdrp, (int32_t *)&tsize)) {
2950Sstevel@tonic-gate 			cmn_err(CE_WARN, "\tnfs_dump: serialization failed");
2960Sstevel@tonic-gate 			return (EIO);
2970Sstevel@tonic-gate 		}
2980Sstevel@tonic-gate 		break;
2990Sstevel@tonic-gate 	case NFS_V3:
3000Sstevel@tonic-gate 		procnum = NFSPROC3_WRITE;
3010Sstevel@tonic-gate 		offset3 = offset;
3020Sstevel@tonic-gate 		if (!XDR_PUTINT32(xdrp, (int32_t *)&procnum) ||
3030Sstevel@tonic-gate 		    !nd_auth_marshall(xdrp) ||
3040Sstevel@tonic-gate 		    !xdr_nfs_fh3(xdrp, &nfsdump_fhandle3) ||
3050Sstevel@tonic-gate 			/*
3060Sstevel@tonic-gate 			 *  Following four values are:
3070Sstevel@tonic-gate 			 *	offset
3080Sstevel@tonic-gate 			 *	count
3090Sstevel@tonic-gate 			 *	stable
3100Sstevel@tonic-gate 			 *	bytes array length
3110Sstevel@tonic-gate 			 */
3120Sstevel@tonic-gate 		    !xdr_u_longlong_t(xdrp, &offset3) ||
3130Sstevel@tonic-gate 		    !XDR_PUTINT32(xdrp, (int32_t *)&tsize) ||
3140Sstevel@tonic-gate 		    !XDR_PUTINT32(xdrp, (int32_t *)&stable) ||
3150Sstevel@tonic-gate 		    !XDR_PUTINT32(xdrp, (int32_t *)&tsize)) {
3160Sstevel@tonic-gate 			cmn_err(CE_WARN, "\tnfs_dump: serialization failed");
3170Sstevel@tonic-gate 			return (EIO);
3180Sstevel@tonic-gate 		}
3190Sstevel@tonic-gate 		break;
3200Sstevel@tonic-gate 	default:
3210Sstevel@tonic-gate 		return (EIO);
3220Sstevel@tonic-gate 	}
3230Sstevel@tonic-gate 
3240Sstevel@tonic-gate 	bcopy(addr, (caddr_t)dumpbuf, tsize);
3250Sstevel@tonic-gate 
3260Sstevel@tonic-gate 	mblk_p->b_wptr += (int)XDR_GETPOS(xdrp);
3270Sstevel@tonic-gate 
3280Sstevel@tonic-gate 	mblk_p->b_cont = esballoc((uchar_t *)dumpbuf, ptob(1), BPRI_HI, &frnop);
3290Sstevel@tonic-gate 
3300Sstevel@tonic-gate 	if (!mblk_p->b_cont) {
3310Sstevel@tonic-gate 		cmn_err(CE_WARN, "\tnfs_dump: out of mblks");
3320Sstevel@tonic-gate 		return (ENOBUFS);
3330Sstevel@tonic-gate 	}
3340Sstevel@tonic-gate 	mblk_p->b_cont->b_wptr += ptob(1);
3350Sstevel@tonic-gate 
3360Sstevel@tonic-gate 	sudata.addr = nfsdump_addr;		/* structure copy */
3370Sstevel@tonic-gate 	sudata.udata.buf = (char *)NULL;
3380Sstevel@tonic-gate 	sudata.udata.maxlen = 0;
3390Sstevel@tonic-gate 	sudata.udata.len = 1;			/* needed for t_ksndudata */
3400Sstevel@tonic-gate 	sudata.udata.udata_mp = mblk_p;
3410Sstevel@tonic-gate 
3420Sstevel@tonic-gate 	nd_log("nfs_dump: calling t_ksndudata\n");
3430Sstevel@tonic-gate 
3440Sstevel@tonic-gate 	if (error = t_ksndudata(tiptr, &sudata, (frtn_t *)NULL)) {
3450Sstevel@tonic-gate 		nfs_perror(error, "\nnfs_dump: t_ksndudata failed: %m\n");
3460Sstevel@tonic-gate 		return (error);
3470Sstevel@tonic-gate 	}
3480Sstevel@tonic-gate 	return (0);
3490Sstevel@tonic-gate }
3500Sstevel@tonic-gate 
3510Sstevel@tonic-gate static int
nd_get_reply(TIUSER * tiptr,XDR * xdrp,uint32_t call_xid,int * badmsg)3520Sstevel@tonic-gate nd_get_reply(TIUSER *tiptr, XDR *xdrp, uint32_t call_xid, int *badmsg)
3530Sstevel@tonic-gate {
3540Sstevel@tonic-gate 	static struct rpc_msg		reply_msg;
3550Sstevel@tonic-gate 	static struct rpc_err		rpc_err;
3560Sstevel@tonic-gate 	static struct nfsattrstat	na;
3570Sstevel@tonic-gate 	static struct WRITE3res		wres;
3580Sstevel@tonic-gate 	static struct t_kunitdata	rudata;
3590Sstevel@tonic-gate 	int				uderr;
3600Sstevel@tonic-gate 	int				type;
3610Sstevel@tonic-gate 	int				error;
3620Sstevel@tonic-gate 
3630Sstevel@tonic-gate 	*badmsg = 0;
3640Sstevel@tonic-gate 
3650Sstevel@tonic-gate 	rudata.addr.maxlen = 0;
3660Sstevel@tonic-gate 	rudata.opt.maxlen = 0;
3670Sstevel@tonic-gate 	rudata.udata.udata_mp = (mblk_t *)NULL;
3680Sstevel@tonic-gate 
3690Sstevel@tonic-gate 	nd_log("nfs_dump: calling t_krcvudata\n");
3700Sstevel@tonic-gate 
3710Sstevel@tonic-gate 	if (error = t_krcvudata(tiptr, &rudata, &type, &uderr)) {
3720Sstevel@tonic-gate 		nfs_perror(error, "\nnfs_dump: t_krcvudata failed: %m\n");
3730Sstevel@tonic-gate 		return (EIO);
3740Sstevel@tonic-gate 	}
3750Sstevel@tonic-gate 	if (type != T_DATA) {
3760Sstevel@tonic-gate 		cmn_err(CE_WARN, "\tnfs_dump:  received type %d", type);
3770Sstevel@tonic-gate 		*badmsg = 1;
3780Sstevel@tonic-gate 		return (0);
3790Sstevel@tonic-gate 	}
3800Sstevel@tonic-gate 	if (!rudata.udata.udata_mp) {
3810Sstevel@tonic-gate 		cmn_err(CE_WARN, "\tnfs_dump: null receive");
3820Sstevel@tonic-gate 		*badmsg = 1;
3830Sstevel@tonic-gate 		return (0);
3840Sstevel@tonic-gate 	}
3850Sstevel@tonic-gate 
3860Sstevel@tonic-gate 	/*
3870Sstevel@tonic-gate 	 * Decode results.
3880Sstevel@tonic-gate 	 */
3890Sstevel@tonic-gate 	xdrmblk_init(xdrp, rudata.udata.udata_mp, XDR_DECODE, 0);
3900Sstevel@tonic-gate 
3910Sstevel@tonic-gate 	reply_msg.acpted_rply.ar_verf = _null_auth;
3920Sstevel@tonic-gate 	switch (nfsdump_version) {
3930Sstevel@tonic-gate 	case NFS_VERSION:
3940Sstevel@tonic-gate 		reply_msg.acpted_rply.ar_results.where = (caddr_t)&na;
3950Sstevel@tonic-gate 		reply_msg.acpted_rply.ar_results.proc = xdr_attrstat;
3960Sstevel@tonic-gate 		break;
3970Sstevel@tonic-gate 	case NFS_V3:
3980Sstevel@tonic-gate 		reply_msg.acpted_rply.ar_results.where = (caddr_t)&wres;
3990Sstevel@tonic-gate 		reply_msg.acpted_rply.ar_results.proc = xdr_WRITE3res;
4000Sstevel@tonic-gate 		break;
4010Sstevel@tonic-gate 	default:
4020Sstevel@tonic-gate 		return (EIO);
4030Sstevel@tonic-gate 	}
4040Sstevel@tonic-gate 
4050Sstevel@tonic-gate 	if (!xdr_replymsg(xdrp, &reply_msg)) {
4060Sstevel@tonic-gate 		cmn_err(CE_WARN, "\tnfs_dump: xdr_replymsg failed");
4070Sstevel@tonic-gate 		return (EIO);
4080Sstevel@tonic-gate 	}
4090Sstevel@tonic-gate 
4100Sstevel@tonic-gate 	if (reply_msg.rm_xid != call_xid) {
4110Sstevel@tonic-gate 		*badmsg = 1;
4120Sstevel@tonic-gate 		return (0);
4130Sstevel@tonic-gate 	}
4140Sstevel@tonic-gate 
4150Sstevel@tonic-gate 	_seterr_reply(&reply_msg, &rpc_err);
4160Sstevel@tonic-gate 
4170Sstevel@tonic-gate 	if (rpc_err.re_status != RPC_SUCCESS) {
4180Sstevel@tonic-gate 		cmn_err(CE_WARN, "\tnfs_dump: RPC error %d (%s)",
4190Sstevel@tonic-gate 		    rpc_err.re_status, clnt_sperrno(rpc_err.re_status));
4200Sstevel@tonic-gate 		return (EIO);
4210Sstevel@tonic-gate 	}
4220Sstevel@tonic-gate 
4230Sstevel@tonic-gate 	switch (nfsdump_version) {
4240Sstevel@tonic-gate 	case NFS_VERSION:
4250Sstevel@tonic-gate 		if (na.ns_status) {
4260Sstevel@tonic-gate 			cmn_err(CE_WARN, "\tnfs_dump: status %d", na.ns_status);
4270Sstevel@tonic-gate 			return (EIO);
4280Sstevel@tonic-gate 		}
4290Sstevel@tonic-gate 		break;
4300Sstevel@tonic-gate 	case NFS_V3:
4310Sstevel@tonic-gate 		if (wres.status != NFS3_OK) {
4320Sstevel@tonic-gate 			cmn_err(CE_WARN, "\tnfs_dump: status %d", wres.status);
4330Sstevel@tonic-gate 			return (EIO);
4340Sstevel@tonic-gate 		}
4350Sstevel@tonic-gate 		break;
4360Sstevel@tonic-gate 	default:
4370Sstevel@tonic-gate 		return (EIO);
4380Sstevel@tonic-gate 	}
4390Sstevel@tonic-gate 
4400Sstevel@tonic-gate 	if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) {
4410Sstevel@tonic-gate 		/* free auth handle */
4420Sstevel@tonic-gate 		xdrp->x_op = XDR_FREE;
4430Sstevel@tonic-gate 		(void) xdr_opaque_auth(xdrp, &(reply_msg.acpted_rply.ar_verf));
4440Sstevel@tonic-gate 	}
4450Sstevel@tonic-gate 
4460Sstevel@tonic-gate 	freemsg(rudata.udata.udata_mp);
4470Sstevel@tonic-gate 
4480Sstevel@tonic-gate 	return (0);
4490Sstevel@tonic-gate }
4500Sstevel@tonic-gate 
4510Sstevel@tonic-gate static int
nd_poll(TIUSER * tiptr,int retry,int * eventp)4520Sstevel@tonic-gate nd_poll(TIUSER *tiptr, int retry, int *eventp)
4530Sstevel@tonic-gate {
454*11066Srafael.vanoni@sun.com 	clock_t		start_bolt = ddi_get_lbolt();
4550Sstevel@tonic-gate 	clock_t		timout = TIMEOUT * (retry + 1);
4560Sstevel@tonic-gate 	int		error;
4570Sstevel@tonic-gate 
4580Sstevel@tonic-gate 	nd_log("nfs_dump: calling t_kspoll\n");
4590Sstevel@tonic-gate 
4600Sstevel@tonic-gate 	*eventp = 0;
4610Sstevel@tonic-gate 
462*11066Srafael.vanoni@sun.com 	while (!*eventp && ((ddi_get_lbolt() - start_bolt) < timout)) {
4630Sstevel@tonic-gate 		/*
4640Sstevel@tonic-gate 		 * Briefly enable interrupts before checking for a reply;
4650Sstevel@tonic-gate 		 * the network transports do not yet support do_polled_io.
4660Sstevel@tonic-gate 		 */
4670Sstevel@tonic-gate 		int s = spl0();
4680Sstevel@tonic-gate 		splx(s);
4690Sstevel@tonic-gate 
4700Sstevel@tonic-gate 		if (error = t_kspoll(tiptr, 0, READWAIT, eventp)) {
4710Sstevel@tonic-gate 			nfs_perror(error,
4720Sstevel@tonic-gate 			    "\nnfs_dump: t_kspoll failed: %m\n");
4730Sstevel@tonic-gate 			return (EIO);
4740Sstevel@tonic-gate 		}
4750Sstevel@tonic-gate 		runqueues();
4760Sstevel@tonic-gate 	}
4770Sstevel@tonic-gate 
4780Sstevel@tonic-gate 	if (retry == RETRIES && !*eventp) {
4790Sstevel@tonic-gate 		cmn_err(CE_WARN, "\tnfs_dump: server not responding");
4800Sstevel@tonic-gate 		return (EIO);
4810Sstevel@tonic-gate 	}
4820Sstevel@tonic-gate 
4830Sstevel@tonic-gate 	return (0);
4840Sstevel@tonic-gate }
4850Sstevel@tonic-gate 
4860Sstevel@tonic-gate static int
nd_auth_marshall(XDR * xdrp)4870Sstevel@tonic-gate nd_auth_marshall(XDR *xdrp)
4880Sstevel@tonic-gate {
4890Sstevel@tonic-gate 	int credsize;
4900Sstevel@tonic-gate 	int32_t *ptr;
4910Sstevel@tonic-gate 	int hostnamelen;
4920Sstevel@tonic-gate 
4930Sstevel@tonic-gate 	hostnamelen = (int)strlen(utsname.nodename);
4940Sstevel@tonic-gate 	credsize = 4 + 4 + roundup(hostnamelen, 4) + 4 + 4 + 4;
4950Sstevel@tonic-gate 
4960Sstevel@tonic-gate 	ptr = XDR_INLINE(xdrp, 4 + 4 + credsize + 4 + 4);
4970Sstevel@tonic-gate 	if (!ptr) {
4980Sstevel@tonic-gate 		cmn_err(CE_WARN, "\tnfs_dump: auth_marshall failed");
4990Sstevel@tonic-gate 		return (0);
5000Sstevel@tonic-gate 	}
5010Sstevel@tonic-gate 	/*
5020Sstevel@tonic-gate 	 * We can do the fast path.
5030Sstevel@tonic-gate 	 */
5040Sstevel@tonic-gate 	IXDR_PUT_INT32(ptr, AUTH_UNIX);	/* cred flavor */
5050Sstevel@tonic-gate 	IXDR_PUT_INT32(ptr, credsize);	/* cred len */
5060Sstevel@tonic-gate 	IXDR_PUT_INT32(ptr, gethrestime_sec());
5070Sstevel@tonic-gate 	IXDR_PUT_INT32(ptr, hostnamelen);
5080Sstevel@tonic-gate 
5090Sstevel@tonic-gate 	bcopy(utsname.nodename, ptr, hostnamelen);
5100Sstevel@tonic-gate 	ptr += roundup(hostnamelen, 4) / 4;
5110Sstevel@tonic-gate 
5120Sstevel@tonic-gate 	IXDR_PUT_INT32(ptr, 0);		/* uid */
5130Sstevel@tonic-gate 	IXDR_PUT_INT32(ptr, 0);		/* gid */
5140Sstevel@tonic-gate 	IXDR_PUT_INT32(ptr, 0);		/* gid list length (empty) */
5150Sstevel@tonic-gate 	IXDR_PUT_INT32(ptr, AUTH_NULL);	/* verf flavor */
5160Sstevel@tonic-gate 	IXDR_PUT_INT32(ptr, 0);		/* verf len */
5170Sstevel@tonic-gate 
5180Sstevel@tonic-gate 	return (1);
5190Sstevel@tonic-gate }
520