xref: /illumos-gate/usr/src/uts/common/fs/nfs/nfs_log.c (revision f44e1126)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
527242a7cSthurlow  * Common Development and Distribution License (the "License").
627242a7cSthurlow  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
210dfe541eSEvan Layton 
227c478bd9Sstevel@tonic-gate /*
233ccecb66SThomas Haynes  * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
260dfe541eSEvan Layton /*
270dfe541eSEvan Layton  * Copyright 2018 Nexenta Systems, Inc.
280dfe541eSEvan Layton  */
290dfe541eSEvan Layton 
307c478bd9Sstevel@tonic-gate #include <sys/cred.h>
317c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
327c478bd9Sstevel@tonic-gate #include <sys/debug.h>
337c478bd9Sstevel@tonic-gate #include <sys/systm.h>
347c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
357c478bd9Sstevel@tonic-gate #include <sys/disp.h>
367c478bd9Sstevel@tonic-gate #include <sys/atomic.h>
377c478bd9Sstevel@tonic-gate #include <rpc/types.h>
387c478bd9Sstevel@tonic-gate #include <nfs/nfs.h>
397c478bd9Sstevel@tonic-gate #include <nfs/nfssys.h>
407c478bd9Sstevel@tonic-gate #include <nfs/export.h>
417c478bd9Sstevel@tonic-gate #include <nfs/rnode.h>
427c478bd9Sstevel@tonic-gate #include <rpc/auth.h>
437c478bd9Sstevel@tonic-gate #include <rpc/svc.h>
447c478bd9Sstevel@tonic-gate #include <rpc/xdr.h>
457c478bd9Sstevel@tonic-gate #include <rpc/clnt.h>
467c478bd9Sstevel@tonic-gate #include <nfs/nfs_log.h>
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate #define	NUM_RECORDS_TO_WRITE 256
497c478bd9Sstevel@tonic-gate #define	NUM_BYTES_TO_WRITE 65536
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate static int nfslog_num_records_to_write = NUM_RECORDS_TO_WRITE;
527c478bd9Sstevel@tonic-gate static int nfslog_num_bytes_to_write = NUM_BYTES_TO_WRITE;
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate /*
557c478bd9Sstevel@tonic-gate  * This struct is used to 'hide' the details of managing the log
567c478bd9Sstevel@tonic-gate  * records internally to the logging code.  Allocation routines
577c478bd9Sstevel@tonic-gate  * are used to obtain pieces of memory for XDR encoding.  This struct
587c478bd9Sstevel@tonic-gate  * is a 'header' to those areas and a opaque cookie is used to pass
597c478bd9Sstevel@tonic-gate  * this data structure between the allocating function and the put
607c478bd9Sstevel@tonic-gate  * function.
617c478bd9Sstevel@tonic-gate  */
627c478bd9Sstevel@tonic-gate struct lr_alloc {
637c478bd9Sstevel@tonic-gate 	struct lr_alloc		*next;		/* links for write queuing */
647c478bd9Sstevel@tonic-gate 	struct lr_alloc		*prev;
657c478bd9Sstevel@tonic-gate #define	LR_ALLOC_NOFREE	0x1			/* not present, call free */
667c478bd9Sstevel@tonic-gate 	int			lr_flags;
677c478bd9Sstevel@tonic-gate 	caddr_t			log_record;	/* address to XDR encoding */
687c478bd9Sstevel@tonic-gate 	size_t			size;		/* final size of encoding */
697c478bd9Sstevel@tonic-gate 	struct kmem_cache	*alloc_cache;	/* keep track of cache ptr */
707c478bd9Sstevel@tonic-gate 	struct exportinfo	*exi;		/* who are we related to? */
717c478bd9Sstevel@tonic-gate 	struct log_buffer	*lb;
727c478bd9Sstevel@tonic-gate };
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate struct flush_thread_params {
757c478bd9Sstevel@tonic-gate 	struct nfsl_flush_args tp_args;
767c478bd9Sstevel@tonic-gate 	int tp_error;
777c478bd9Sstevel@tonic-gate };
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate static int log_file_create(caddr_t, struct log_file **);
807c478bd9Sstevel@tonic-gate static void log_file_rele(struct log_file *);
817c478bd9Sstevel@tonic-gate static struct log_buffer *log_buffer_create(caddr_t);
827c478bd9Sstevel@tonic-gate static void log_buffer_rele(struct log_buffer *);
837c478bd9Sstevel@tonic-gate static int nfslog_record_append2all(struct lr_alloc *);
847c478bd9Sstevel@tonic-gate static int nfslog_logbuffer_rename(struct log_buffer *);
857c478bd9Sstevel@tonic-gate static void nfslog_logfile_wait(struct log_file *);
867c478bd9Sstevel@tonic-gate static int nfslog_logfile_rename(char *, char *);
877c478bd9Sstevel@tonic-gate static void nfslog_do_flush(struct flush_thread_params *);
887c478bd9Sstevel@tonic-gate static void create_buffer_header(caddr_t *, size_t *, size_t *);
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate static int nfslog_write_logrecords(struct log_file *, struct lr_alloc *, int);
917c478bd9Sstevel@tonic-gate static void nfslog_free_logrecords(struct lr_alloc *);
927c478bd9Sstevel@tonic-gate static int nfslog_records_flush_to_disk(struct log_buffer *);
937c478bd9Sstevel@tonic-gate static int nfslog_records_flush_to_disk_nolock(struct log_buffer *);
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate /*
967c478bd9Sstevel@tonic-gate  * Read/Write lock that protects 'nfslog_buffer_list'.
977c478bd9Sstevel@tonic-gate  * This lock must be held when searching or modifying 'nfslog_buffer_list'.
987c478bd9Sstevel@tonic-gate  */
997c478bd9Sstevel@tonic-gate static krwlock_t nfslog_buffer_list_lock;
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate /*
1027c478bd9Sstevel@tonic-gate  * The list of "log_buffer" structures.
1037c478bd9Sstevel@tonic-gate  */
1047c478bd9Sstevel@tonic-gate struct log_buffer *nfslog_buffer_list = NULL;
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate #define	LOG_BUFFER_HOLD(lbp)	{ \
1087c478bd9Sstevel@tonic-gate 	mutex_enter(&(lbp)->lb_lock); \
1097c478bd9Sstevel@tonic-gate 	(lbp)->lb_refcnt++; \
1107c478bd9Sstevel@tonic-gate 	mutex_exit(&(lbp)->lb_lock); \
1117c478bd9Sstevel@tonic-gate }
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate #define	LOG_FILE_HOLD(lfp)	{ \
1147c478bd9Sstevel@tonic-gate 	mutex_enter(&(lfp)->lf_lock); \
1157c478bd9Sstevel@tonic-gate 	(lfp)->lf_refcnt++; \
1167c478bd9Sstevel@tonic-gate 	mutex_exit(&(lfp)->lf_lock); \
1177c478bd9Sstevel@tonic-gate }
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate #define	LOG_FILE_RELE(lfp)	{ \
1207c478bd9Sstevel@tonic-gate 	log_file_rele(lfp); \
1217c478bd9Sstevel@tonic-gate }
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate /*
1247c478bd9Sstevel@tonic-gate  * These two macros are used to prep a logfile data structure and
1257c478bd9Sstevel@tonic-gate  * associated file for writing data.  Note that the lf_lock is
1267c478bd9Sstevel@tonic-gate  * held as a result of the call to the first macro.  This is used
1277c478bd9Sstevel@tonic-gate  * for serialization correctness between the logbuffer struct and
1287c478bd9Sstevel@tonic-gate  * the logfile struct.
1297c478bd9Sstevel@tonic-gate  */
1307c478bd9Sstevel@tonic-gate #define	LOG_FILE_LOCK_TO_WRITE(lfp)	{ \
1317c478bd9Sstevel@tonic-gate 	mutex_enter(&(lfp)->lf_lock); \
1327c478bd9Sstevel@tonic-gate 	(lfp)->lf_refcnt++; \
1337c478bd9Sstevel@tonic-gate 	(lfp)->lf_writers++; \
1347c478bd9Sstevel@tonic-gate }
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate #define	LOG_FILE_UNLOCK_FROM_WRITE(lfp)	{ \
1377c478bd9Sstevel@tonic-gate 	(lfp)->lf_writers--; \
1387c478bd9Sstevel@tonic-gate 	if ((lfp)->lf_writers == 0 && ((lfp)->lf_flags & L_WAITING)) { \
1397c478bd9Sstevel@tonic-gate 		(lfp)->lf_flags &= ~L_WAITING; \
1407c478bd9Sstevel@tonic-gate 		cv_broadcast(&(lfp)->lf_cv_waiters); \
1417c478bd9Sstevel@tonic-gate 	} \
1427c478bd9Sstevel@tonic-gate 	mutex_exit(&(lfp)->lf_lock); \
1437c478bd9Sstevel@tonic-gate 	log_file_rele(lfp); \
1447c478bd9Sstevel@tonic-gate }
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate int rfsl_log_buffer = 0;
1477c478bd9Sstevel@tonic-gate static int rfsl_log_file = 0;
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate /* This array is used for memory allocation of record encoding spaces */
1507c478bd9Sstevel@tonic-gate static struct {
1517c478bd9Sstevel@tonic-gate 	int	size;
1527c478bd9Sstevel@tonic-gate 	struct kmem_cache *mem_cache;
1537c478bd9Sstevel@tonic-gate 	char	*cache_name;
1547c478bd9Sstevel@tonic-gate } nfslog_mem_alloc[] = {
1557c478bd9Sstevel@tonic-gate #define	SMALL_INDX 0
1567c478bd9Sstevel@tonic-gate 	{ NFSLOG_SMALL_RECORD_SIZE - sizeof (struct lr_alloc),
1577c478bd9Sstevel@tonic-gate 	NULL, NFSLOG_SMALL_REC_NAME },
1587c478bd9Sstevel@tonic-gate #define	MEDIUM_INDX 1
1597c478bd9Sstevel@tonic-gate 	{ NFSLOG_MEDIUM_RECORD_SIZE - sizeof (struct lr_alloc),
1607c478bd9Sstevel@tonic-gate 	NULL, NFSLOG_MEDIUM_REC_NAME },
1617c478bd9Sstevel@tonic-gate #define	LARGE_INDX 2
1627c478bd9Sstevel@tonic-gate 	{ NFSLOG_LARGE_RECORD_SIZE - sizeof (struct lr_alloc),
1637c478bd9Sstevel@tonic-gate 	NULL, NFSLOG_LARGE_REC_NAME },
1647c478bd9Sstevel@tonic-gate 	{ (-1), NULL }
1657c478bd9Sstevel@tonic-gate };
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate /* Used to calculate the 'real' allocation size */
1687c478bd9Sstevel@tonic-gate #define	ALLOC_SIZE(index) \
1697c478bd9Sstevel@tonic-gate 	(nfslog_mem_alloc[index].size + sizeof (struct lr_alloc))
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate /*
1727c478bd9Sstevel@tonic-gate  * Initialize logging data buffer cache
1737c478bd9Sstevel@tonic-gate  */
1747c478bd9Sstevel@tonic-gate void
nfslog_init()1757c478bd9Sstevel@tonic-gate nfslog_init()
1767c478bd9Sstevel@tonic-gate {
1777c478bd9Sstevel@tonic-gate 	int indx;
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate 	rw_init(&nfslog_buffer_list_lock, NULL, RW_DEFAULT, NULL);
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate 	/*
1827c478bd9Sstevel@tonic-gate 	 * Initialize the kmem caches for encoding
1837c478bd9Sstevel@tonic-gate 	 */
1847c478bd9Sstevel@tonic-gate 	for (indx = 0; nfslog_mem_alloc[indx].size != (-1); indx++) {
1857c478bd9Sstevel@tonic-gate 		nfslog_mem_alloc[indx].mem_cache =
1869d39bb88Sbatschul 		    kmem_cache_create(nfslog_mem_alloc[indx].cache_name,
1879d39bb88Sbatschul 		    ALLOC_SIZE(indx), 0, NULL, NULL, NULL, NULL, NULL, 0);
1887c478bd9Sstevel@tonic-gate 	}
1897c478bd9Sstevel@tonic-gate }
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate /*
1927c478bd9Sstevel@tonic-gate  * Sets up the necessary log file and related buffers to enable logging
1937c478bd9Sstevel@tonic-gate  * on the given export point.
1947c478bd9Sstevel@tonic-gate  * Returns 0 on success, non-zero on failure.
1957c478bd9Sstevel@tonic-gate  */
1967c478bd9Sstevel@tonic-gate int
nfslog_setup(struct exportinfo * exi)1977c478bd9Sstevel@tonic-gate nfslog_setup(struct exportinfo *exi)
1987c478bd9Sstevel@tonic-gate {
1997c478bd9Sstevel@tonic-gate 	struct exportdata *kex;
2007c478bd9Sstevel@tonic-gate 	struct log_buffer *lbp;
2017c478bd9Sstevel@tonic-gate 	struct log_buffer *nlbp;
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate 	kex = &exi->exi_export;
2047c478bd9Sstevel@tonic-gate 	ASSERT(kex->ex_flags & EX_LOG);
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate 	/*
2077c478bd9Sstevel@tonic-gate 	 * Logging is enabled for the new export point, check
2087c478bd9Sstevel@tonic-gate 	 * the existing log_buffer structures to see if the
2097c478bd9Sstevel@tonic-gate 	 * desired buffer has already been opened. If so, point
2107c478bd9Sstevel@tonic-gate 	 * the new exportinfo's exi_logbuffer to the existing
2117c478bd9Sstevel@tonic-gate 	 * one.
2127c478bd9Sstevel@tonic-gate 	 */
2137c478bd9Sstevel@tonic-gate 	rw_enter(&nfslog_buffer_list_lock, RW_READER);
2147c478bd9Sstevel@tonic-gate 	for (lbp = nfslog_buffer_list; lbp != NULL; lbp = lbp->lb_next) {
2157c478bd9Sstevel@tonic-gate 		LOGGING_DPRINT((10,
2167c478bd9Sstevel@tonic-gate 		    "searching for buffer... found log_buffer '%s'\n",
2179d39bb88Sbatschul 		    lbp->lb_path));
2187c478bd9Sstevel@tonic-gate 		if (strcmp(lbp->lb_path, kex->ex_log_buffer) == 0) {
2197c478bd9Sstevel@tonic-gate 			/* Found our match. Ref it and return */
2207c478bd9Sstevel@tonic-gate 			LOG_BUFFER_HOLD(lbp);
2217c478bd9Sstevel@tonic-gate 			exi->exi_logbuffer = lbp;
2227c478bd9Sstevel@tonic-gate 			LOGGING_DPRINT((10,  "\tfound log_buffer for '%s'\n",
2239d39bb88Sbatschul 			    kex->ex_log_buffer));
2247c478bd9Sstevel@tonic-gate 			rw_exit(&nfslog_buffer_list_lock);
2257c478bd9Sstevel@tonic-gate 			return (0);
2267c478bd9Sstevel@tonic-gate 		}
2277c478bd9Sstevel@tonic-gate 	}
2287c478bd9Sstevel@tonic-gate 	rw_exit(&nfslog_buffer_list_lock);
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate 	/*
2317c478bd9Sstevel@tonic-gate 	 * New buffer needed, allocate it.
2327c478bd9Sstevel@tonic-gate 	 * The buffer list lock has been dropped so we will need to search
2337c478bd9Sstevel@tonic-gate 	 * the list again to ensure that another thread has not added
2347c478bd9Sstevel@tonic-gate 	 * a matching buffer.
2357c478bd9Sstevel@tonic-gate 	 */
2367c478bd9Sstevel@tonic-gate 	if ((nlbp = log_buffer_create(kex->ex_log_buffer)) == NULL) {
2377c478bd9Sstevel@tonic-gate 		/*
2387c478bd9Sstevel@tonic-gate 		 * Failed the buffer creation for some reason so we
2397c478bd9Sstevel@tonic-gate 		 * will need to return.
2407c478bd9Sstevel@tonic-gate 		 */
2417c478bd9Sstevel@tonic-gate 		return (EIO);
2427c478bd9Sstevel@tonic-gate 	}
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate 	rw_enter(&nfslog_buffer_list_lock, RW_WRITER);
2457c478bd9Sstevel@tonic-gate 	for (lbp = nfslog_buffer_list; lbp != NULL;
2469d39bb88Sbatschul 	    lbp = lbp->lb_next) {
2477c478bd9Sstevel@tonic-gate 		if (strcmp(lbp->lb_path, kex->ex_log_buffer) == 0) {
2487c478bd9Sstevel@tonic-gate 				/*
2497c478bd9Sstevel@tonic-gate 				 * A log_buffer already exists for the
2507c478bd9Sstevel@tonic-gate 				 * indicated buffer, use it instead.
2517c478bd9Sstevel@tonic-gate 				 */
2527c478bd9Sstevel@tonic-gate 			LOG_BUFFER_HOLD(lbp);
2537c478bd9Sstevel@tonic-gate 
2547c478bd9Sstevel@tonic-gate 			exi->exi_logbuffer = lbp;
2557c478bd9Sstevel@tonic-gate 
2569d39bb88Sbatschul 			LOGGING_DPRINT((10, "found log_buffer for '%s' "
2579d39bb88Sbatschul 			    "after allocation\n", kex->ex_log_buffer));
2587c478bd9Sstevel@tonic-gate 
2597c478bd9Sstevel@tonic-gate 			rw_exit(&nfslog_buffer_list_lock);
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate 			log_buffer_rele(nlbp);
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate 			return (0);
2647c478bd9Sstevel@tonic-gate 		}
2657c478bd9Sstevel@tonic-gate 	}
2667c478bd9Sstevel@tonic-gate 	/*
2677c478bd9Sstevel@tonic-gate 	 * Didn't find an existing log_buffer for this buffer,
2687c478bd9Sstevel@tonic-gate 	 * use the the newly created one, and add to list.  We
2697c478bd9Sstevel@tonic-gate 	 * increment the reference count because the node is
2707c478bd9Sstevel@tonic-gate 	 * entered into the global list.
2717c478bd9Sstevel@tonic-gate 	 */
272903a11ebSrh 	LOGGING_DPRINT((10, "exportfs: adding nlbp=%p to list\n",
273903a11ebSrh 	    (void *)nlbp));
2747c478bd9Sstevel@tonic-gate 
2757c478bd9Sstevel@tonic-gate 	nlbp->lb_next = nfslog_buffer_list;
2767c478bd9Sstevel@tonic-gate 	nfslog_buffer_list = nlbp;
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate 	LOG_BUFFER_HOLD(nlbp);	/* hold is for export entry */
2797c478bd9Sstevel@tonic-gate 	exi->exi_logbuffer = nlbp;
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate 	rw_exit(&nfslog_buffer_list_lock);
2827c478bd9Sstevel@tonic-gate 
2837c478bd9Sstevel@tonic-gate 	return (0);
2847c478bd9Sstevel@tonic-gate }
2857c478bd9Sstevel@tonic-gate 
2867c478bd9Sstevel@tonic-gate /*
2877c478bd9Sstevel@tonic-gate  * Disables logging for the given export point.
2887c478bd9Sstevel@tonic-gate  */
2897c478bd9Sstevel@tonic-gate void
nfslog_disable(struct exportinfo * exi)2907c478bd9Sstevel@tonic-gate nfslog_disable(struct exportinfo *exi)
2917c478bd9Sstevel@tonic-gate {
2927c478bd9Sstevel@tonic-gate 	log_buffer_rele(exi->exi_logbuffer);
2937c478bd9Sstevel@tonic-gate }
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate /*
2967c478bd9Sstevel@tonic-gate  * Creates the corresponding log_buffer and log_file structures
2977c478bd9Sstevel@tonic-gate  * for the the buffer named 'name'.
2987c478bd9Sstevel@tonic-gate  * Returns a pointer to the log_buffer structure with reference one.
2997c478bd9Sstevel@tonic-gate  */
3007c478bd9Sstevel@tonic-gate static struct log_buffer *
log_buffer_create(caddr_t name)3017c478bd9Sstevel@tonic-gate log_buffer_create(caddr_t name)
3027c478bd9Sstevel@tonic-gate {
3037c478bd9Sstevel@tonic-gate 	struct log_buffer *buffer;
3047c478bd9Sstevel@tonic-gate 	struct log_file *logfile;
3057c478bd9Sstevel@tonic-gate 	int namelen = strlen(name);
3067c478bd9Sstevel@tonic-gate 
3077c478bd9Sstevel@tonic-gate 	LOGGING_DPRINT((10,  "log_buffer_create: %s\n", name));
3087c478bd9Sstevel@tonic-gate 	if (log_file_create(name, &logfile))
3097c478bd9Sstevel@tonic-gate 		return (NULL);
3107c478bd9Sstevel@tonic-gate 
3117c478bd9Sstevel@tonic-gate 	buffer = (struct log_buffer *)kmem_alloc(sizeof (*buffer), KM_SLEEP);
3127c478bd9Sstevel@tonic-gate 	buffer->lb_refcnt = 1;
3137c478bd9Sstevel@tonic-gate 	buffer->lb_rec_id = 0;
3147c478bd9Sstevel@tonic-gate 	buffer->lb_path = (caddr_t)kmem_alloc(namelen + 1, KM_SLEEP);
3157c478bd9Sstevel@tonic-gate 	bcopy(name, buffer->lb_path, namelen + 1);
3167c478bd9Sstevel@tonic-gate 	buffer->lb_logfile = logfile;
3177c478bd9Sstevel@tonic-gate 	buffer->lb_records = NULL;
3187c478bd9Sstevel@tonic-gate 	buffer->lb_num_recs = 0;
3197c478bd9Sstevel@tonic-gate 	buffer->lb_size_queued = 0;
3207c478bd9Sstevel@tonic-gate 	mutex_init(&buffer->lb_lock, NULL, MUTEX_DEFAULT, NULL);
3217c478bd9Sstevel@tonic-gate 	rfsl_log_buffer++;
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate 	return (buffer);
3247c478bd9Sstevel@tonic-gate }
3257c478bd9Sstevel@tonic-gate 
3267c478bd9Sstevel@tonic-gate /*
3277c478bd9Sstevel@tonic-gate  * Release a log_buffer structure
3287c478bd9Sstevel@tonic-gate  */
3297c478bd9Sstevel@tonic-gate static void
log_buffer_rele(struct log_buffer * lbp)3307c478bd9Sstevel@tonic-gate log_buffer_rele(struct log_buffer *lbp)
3317c478bd9Sstevel@tonic-gate {
3327c478bd9Sstevel@tonic-gate 	int len;
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate 	mutex_enter(&lbp->lb_lock);
3357c478bd9Sstevel@tonic-gate 	if (--lbp->lb_refcnt > 1) {
3367c478bd9Sstevel@tonic-gate 		mutex_exit(&lbp->lb_lock);
3377c478bd9Sstevel@tonic-gate 		return;
3387c478bd9Sstevel@tonic-gate 	}
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate 	if (lbp->lb_refcnt < 0) {
3417c478bd9Sstevel@tonic-gate 		panic("log_rele: log_buffer refcnt < 0");
3427c478bd9Sstevel@tonic-gate 		/*NOTREACHED*/
3437c478bd9Sstevel@tonic-gate 	}
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate 	/*
3467c478bd9Sstevel@tonic-gate 	 * Need to drop the lb_lock before acquiring the
3477c478bd9Sstevel@tonic-gate 	 * nfslog_buffer_list_lock. To avoid double free we need
3487c478bd9Sstevel@tonic-gate 	 * to hold an additional reference to the log buffer.
3497c478bd9Sstevel@tonic-gate 	 * This will ensure that no two threads will simultaneously
3507c478bd9Sstevel@tonic-gate 	 * be trying to free the same log buffer.
3517c478bd9Sstevel@tonic-gate 	 */
3527c478bd9Sstevel@tonic-gate 
3537c478bd9Sstevel@tonic-gate 	if (lbp->lb_refcnt == 1) {
3547c478bd9Sstevel@tonic-gate 
3557c478bd9Sstevel@tonic-gate 		/*
3567c478bd9Sstevel@tonic-gate 		 * If the ref count is 1, then the last
3577c478bd9Sstevel@tonic-gate 		 * unshare/reference has been given up and we need to
3587c478bd9Sstevel@tonic-gate 		 * clean up the buffer and remove it from the buffer
3597c478bd9Sstevel@tonic-gate 		 * list.
3607c478bd9Sstevel@tonic-gate 		 */
3617c478bd9Sstevel@tonic-gate 		LOGGING_DPRINT((10,
362903a11ebSrh 		    "log_buffer_rele lbp=%p disconnecting\n", (void *)lbp));
3637c478bd9Sstevel@tonic-gate 		/*
3647c478bd9Sstevel@tonic-gate 		 * Hold additional reference before dropping the lb_lock
3657c478bd9Sstevel@tonic-gate 		 */
3667c478bd9Sstevel@tonic-gate 
3677c478bd9Sstevel@tonic-gate 		lbp->lb_refcnt++;
3687c478bd9Sstevel@tonic-gate 		mutex_exit(&lbp->lb_lock);
3697c478bd9Sstevel@tonic-gate 
3707c478bd9Sstevel@tonic-gate 		/*
3717c478bd9Sstevel@tonic-gate 		 * Make sure that all of the buffered records are written.
3727c478bd9Sstevel@tonic-gate 		 * Don't bother checking the write return value since there
3737c478bd9Sstevel@tonic-gate 		 * isn't much we can do at this point.
3747c478bd9Sstevel@tonic-gate 		 */
3757c478bd9Sstevel@tonic-gate 		(void) nfslog_records_flush_to_disk(lbp);
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate 		rw_enter(&nfslog_buffer_list_lock, RW_WRITER);
3787c478bd9Sstevel@tonic-gate 		mutex_enter(&lbp->lb_lock);
3797c478bd9Sstevel@tonic-gate 		/*
3807c478bd9Sstevel@tonic-gate 		 * Drop the reference count held above.
3817c478bd9Sstevel@tonic-gate 		 * If the ref count is still > 1 then someone has
3827c478bd9Sstevel@tonic-gate 		 * stepped in to use this log buffer.  unlock and return.
3837c478bd9Sstevel@tonic-gate 		 */
3847c478bd9Sstevel@tonic-gate 		if (--lbp->lb_refcnt > 1) {
3857c478bd9Sstevel@tonic-gate 			mutex_exit(&lbp->lb_lock);
3867c478bd9Sstevel@tonic-gate 			rw_exit(&nfslog_buffer_list_lock);
3877c478bd9Sstevel@tonic-gate 			return;
3887c478bd9Sstevel@tonic-gate 		}
3897c478bd9Sstevel@tonic-gate 
3907c478bd9Sstevel@tonic-gate 		if (lbp == nfslog_buffer_list) {
3917c478bd9Sstevel@tonic-gate 			nfslog_buffer_list = lbp->lb_next;
3927c478bd9Sstevel@tonic-gate 		} else {
3937c478bd9Sstevel@tonic-gate 			struct log_buffer *tlbp;
3947c478bd9Sstevel@tonic-gate 
3957c478bd9Sstevel@tonic-gate 			/* Drop the log_buffer from the master list */
3967c478bd9Sstevel@tonic-gate 			for (tlbp = nfslog_buffer_list; tlbp->lb_next != NULL;
3979d39bb88Sbatschul 			    tlbp = tlbp->lb_next) {
3987c478bd9Sstevel@tonic-gate 				if (tlbp->lb_next == lbp) {
3997c478bd9Sstevel@tonic-gate 					tlbp->lb_next = lbp->lb_next;
4007c478bd9Sstevel@tonic-gate 					break;
4017c478bd9Sstevel@tonic-gate 				}
4027c478bd9Sstevel@tonic-gate 			}
4037c478bd9Sstevel@tonic-gate 		}
4047c478bd9Sstevel@tonic-gate 
4057c478bd9Sstevel@tonic-gate 		mutex_exit(&lbp->lb_lock);
4067c478bd9Sstevel@tonic-gate 		rw_exit(&nfslog_buffer_list_lock);
4077c478bd9Sstevel@tonic-gate 	}
4087c478bd9Sstevel@tonic-gate 	/*
4097c478bd9Sstevel@tonic-gate 	 * ref count zero; finish clean up.
4107c478bd9Sstevel@tonic-gate 	 */
411903a11ebSrh 	LOGGING_DPRINT((10, "log_buffer_rele lbp=%p freeing\n", (void *)lbp));
4127c478bd9Sstevel@tonic-gate 
4137c478bd9Sstevel@tonic-gate 	log_file_rele(lbp->lb_logfile);
4147c478bd9Sstevel@tonic-gate 	len = strlen(lbp->lb_path) + 1;
4157c478bd9Sstevel@tonic-gate 	kmem_free(lbp->lb_path, len);
4167c478bd9Sstevel@tonic-gate 	kmem_free(lbp, sizeof (*lbp));
4177c478bd9Sstevel@tonic-gate 	rfsl_log_buffer--;
4187c478bd9Sstevel@tonic-gate }
4197c478bd9Sstevel@tonic-gate 
4207c478bd9Sstevel@tonic-gate /*
4217c478bd9Sstevel@tonic-gate  * Creates the corresponding log_file structure for the buffer
4227c478bd9Sstevel@tonic-gate  * named 'log_file_name'.
4237c478bd9Sstevel@tonic-gate  * 'log_file_name' is created by concatenating 'origname' and LOG_INPROG_STRING.
4247c478bd9Sstevel@tonic-gate  * 'logfile' is set to be the log_file structure with reference one.
4257c478bd9Sstevel@tonic-gate  */
4267c478bd9Sstevel@tonic-gate static int
log_file_create(caddr_t origname,struct log_file ** lfpp)4277c478bd9Sstevel@tonic-gate log_file_create(caddr_t origname, struct log_file **lfpp)
4287c478bd9Sstevel@tonic-gate {
4297c478bd9Sstevel@tonic-gate 	vnode_t *vp = NULL;
4307c478bd9Sstevel@tonic-gate 	char *name;
4317c478bd9Sstevel@tonic-gate 	int namelen;
4327c478bd9Sstevel@tonic-gate 	int error;
4337c478bd9Sstevel@tonic-gate 	struct log_file *logfile = NULL;
4347c478bd9Sstevel@tonic-gate 	vattr_t va;
4357c478bd9Sstevel@tonic-gate 	caddr_t loghdr = NULL;
4367c478bd9Sstevel@tonic-gate 	size_t loghdr_len = 0;
4377c478bd9Sstevel@tonic-gate 	size_t loghdr_free = 0;
4387c478bd9Sstevel@tonic-gate 
4397c478bd9Sstevel@tonic-gate 	namelen = strlen(origname) + strlen(LOG_INPROG_STRING);
4407c478bd9Sstevel@tonic-gate 	name = (caddr_t)kmem_alloc(namelen + 1, KM_SLEEP);
4417c478bd9Sstevel@tonic-gate 	(void) sprintf(name, "%s%s", origname, LOG_INPROG_STRING);
4427c478bd9Sstevel@tonic-gate 
4437c478bd9Sstevel@tonic-gate 	LOGGING_DPRINT((3, "log_file_create: %s\n", name));
444*bd3561fbSToomas Soome 	error = vn_open(name, UIO_SYSSPACE, FCREAT|FWRITE|FOFFMAX,
445*bd3561fbSToomas Soome 	    LOG_MODE, &vp, CRCREAT, 0);
446*bd3561fbSToomas Soome 	if (error != 0) {
4477c478bd9Sstevel@tonic-gate 		nfs_cmn_err(error, CE_WARN,
4489d39bb88Sbatschul 		    "log_file_create: Can not open %s - error %m", name);
4497c478bd9Sstevel@tonic-gate 		goto out;
4507c478bd9Sstevel@tonic-gate 	}
4517c478bd9Sstevel@tonic-gate 	LOGGING_DPRINT((3, "log_file_create: %s vp=%p v_count=%d\n",
452903a11ebSrh 	    name, (void *)vp, vp->v_count));
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate 	logfile = (struct log_file *)kmem_zalloc(sizeof (*logfile), KM_SLEEP);
4557c478bd9Sstevel@tonic-gate 	logfile->lf_path = name;
4567c478bd9Sstevel@tonic-gate 	/*
4577c478bd9Sstevel@tonic-gate 	 * No need to bump the vnode reference count since it is set
4587c478bd9Sstevel@tonic-gate 	 * to one by vn_open().
4597c478bd9Sstevel@tonic-gate 	 */
4607c478bd9Sstevel@tonic-gate 	logfile->lf_vp = vp;
4617c478bd9Sstevel@tonic-gate 	logfile->lf_refcnt = 1;
4627c478bd9Sstevel@tonic-gate 	mutex_init(&logfile->lf_lock, NULL, MUTEX_DEFAULT, NULL);
4637c478bd9Sstevel@tonic-gate 	rfsl_log_file++;
4647c478bd9Sstevel@tonic-gate 
4657c478bd9Sstevel@tonic-gate 	va.va_mask = AT_SIZE;
466da6c28aaSamw 	error = VOP_GETATTR(vp, &va, 0, CRED(), NULL);
4677c478bd9Sstevel@tonic-gate 	if (error) {
4687c478bd9Sstevel@tonic-gate 		nfs_cmn_err(error, CE_WARN,
4699d39bb88Sbatschul 		    "log_file_create: Can not stat %s - error = %m",  name);
4707c478bd9Sstevel@tonic-gate 		goto out;
4717c478bd9Sstevel@tonic-gate 	}
4727c478bd9Sstevel@tonic-gate 
4737c478bd9Sstevel@tonic-gate 	if (va.va_size == 0) {
4747c478bd9Sstevel@tonic-gate 		struct lr_alloc lr;
4757c478bd9Sstevel@tonic-gate 
4767c478bd9Sstevel@tonic-gate 		/*
4777c478bd9Sstevel@tonic-gate 		 * Write Header.
4787c478bd9Sstevel@tonic-gate 		 */
4797c478bd9Sstevel@tonic-gate 		create_buffer_header(&loghdr, &loghdr_len, &loghdr_free);
4807c478bd9Sstevel@tonic-gate 		/*
4817c478bd9Sstevel@tonic-gate 		 * Dummy up a lr_alloc struct for the write
4827c478bd9Sstevel@tonic-gate 		 */
4837c478bd9Sstevel@tonic-gate 		lr.next = lr.prev = &lr;
4847c478bd9Sstevel@tonic-gate 		lr.lr_flags = 0;
4857c478bd9Sstevel@tonic-gate 		lr.log_record = loghdr;
4867c478bd9Sstevel@tonic-gate 		lr.size = loghdr_len;
4877c478bd9Sstevel@tonic-gate 		lr.alloc_cache = NULL;
4887c478bd9Sstevel@tonic-gate 		lr.exi = NULL;
4897c478bd9Sstevel@tonic-gate 		lr.lb = NULL;
4907c478bd9Sstevel@tonic-gate 
4917c478bd9Sstevel@tonic-gate 		mutex_enter(&logfile->lf_lock);
4927c478bd9Sstevel@tonic-gate 
4937c478bd9Sstevel@tonic-gate 		error = nfslog_write_logrecords(logfile, &lr, 1);
4947c478bd9Sstevel@tonic-gate 
4957c478bd9Sstevel@tonic-gate 		mutex_exit(&logfile->lf_lock);
4967c478bd9Sstevel@tonic-gate 
4977c478bd9Sstevel@tonic-gate 		if (error != 0) {
4987c478bd9Sstevel@tonic-gate 			nfs_cmn_err(error, CE_WARN,
4999d39bb88Sbatschul 			    "log_file_create: Can not write header "
5009d39bb88Sbatschul 			    "on %s - error = %m", name);
5017c478bd9Sstevel@tonic-gate 			goto out;
5027c478bd9Sstevel@tonic-gate 		}
5037c478bd9Sstevel@tonic-gate 	}
5047c478bd9Sstevel@tonic-gate 	*lfpp = logfile;
5057c478bd9Sstevel@tonic-gate 
5067c478bd9Sstevel@tonic-gate 	if (loghdr != NULL)
5077c478bd9Sstevel@tonic-gate 		kmem_free(loghdr, loghdr_free);
5087c478bd9Sstevel@tonic-gate 
5097c478bd9Sstevel@tonic-gate 	return (0);
5107c478bd9Sstevel@tonic-gate 
5117c478bd9Sstevel@tonic-gate out:
5127c478bd9Sstevel@tonic-gate 	if (vp != NULL) {
5137c478bd9Sstevel@tonic-gate 		int error1;
5147c478bd9Sstevel@tonic-gate 		error1 = VOP_CLOSE(vp, FCREAT|FWRITE|FOFFMAX, 1, (offset_t)0,
515da6c28aaSamw 		    CRED(), NULL);
5167c478bd9Sstevel@tonic-gate 		if (error1) {
5177c478bd9Sstevel@tonic-gate 			nfs_cmn_err(error1, CE_WARN,
5189d39bb88Sbatschul 			    "log_file_create: Can not close %s - "
5199d39bb88Sbatschul 			    "error = %m", name);
5207c478bd9Sstevel@tonic-gate 		}
5217c478bd9Sstevel@tonic-gate 		VN_RELE(vp);
5227c478bd9Sstevel@tonic-gate 	}
5237c478bd9Sstevel@tonic-gate 
5247c478bd9Sstevel@tonic-gate 	kmem_free(name, namelen + 1);
5257c478bd9Sstevel@tonic-gate 	if (logfile != NULL) {
5267c478bd9Sstevel@tonic-gate 		mutex_destroy(&logfile->lf_lock);
5277c478bd9Sstevel@tonic-gate 		kmem_free(logfile, sizeof (*logfile));
5287c478bd9Sstevel@tonic-gate 		rfsl_log_file--;
5297c478bd9Sstevel@tonic-gate 	}
5307c478bd9Sstevel@tonic-gate 	if (loghdr != NULL)
5317c478bd9Sstevel@tonic-gate 		kmem_free(loghdr, loghdr_free);
5327c478bd9Sstevel@tonic-gate 
5337c478bd9Sstevel@tonic-gate 	return (error);
5347c478bd9Sstevel@tonic-gate }
5357c478bd9Sstevel@tonic-gate 
5367c478bd9Sstevel@tonic-gate /*
5377c478bd9Sstevel@tonic-gate  * Release a log_file structure
5387c478bd9Sstevel@tonic-gate  */
5397c478bd9Sstevel@tonic-gate static void
log_file_rele(struct log_file * lfp)5407c478bd9Sstevel@tonic-gate log_file_rele(struct log_file *lfp)
5417c478bd9Sstevel@tonic-gate {
5427c478bd9Sstevel@tonic-gate 	int len;
5437c478bd9Sstevel@tonic-gate 	int error;
5447c478bd9Sstevel@tonic-gate 
5457c478bd9Sstevel@tonic-gate 	mutex_enter(&lfp->lf_lock);
5467c478bd9Sstevel@tonic-gate 	if (--lfp->lf_refcnt > 0) {
5477c478bd9Sstevel@tonic-gate 		LOGGING_DPRINT((10,
5489d39bb88Sbatschul 		    "log_file_rele lfp=%p decremented refcnt to %d\n",
549903a11ebSrh 		    (void *)lfp, lfp->lf_refcnt));
5507c478bd9Sstevel@tonic-gate 		mutex_exit(&lfp->lf_lock);
5517c478bd9Sstevel@tonic-gate 		return;
5527c478bd9Sstevel@tonic-gate 	}
5537c478bd9Sstevel@tonic-gate 	if (lfp->lf_refcnt < 0) {
5547c478bd9Sstevel@tonic-gate 		panic("log_file_rele: log_file refcnt < 0");
5557c478bd9Sstevel@tonic-gate 		/*NOTREACHED*/
5567c478bd9Sstevel@tonic-gate 	}
5577c478bd9Sstevel@tonic-gate 
558903a11ebSrh 	LOGGING_DPRINT((10, "log_file_rele lfp=%p freeing node\n",
559903a11ebSrh 	    (void *)lfp));
5607c478bd9Sstevel@tonic-gate 
5617c478bd9Sstevel@tonic-gate 	lfp->lf_flags &= ~(L_PRINTED | L_ERROR);
5627c478bd9Sstevel@tonic-gate 
5637c478bd9Sstevel@tonic-gate 	ASSERT(lfp->lf_flags == 0);
5647c478bd9Sstevel@tonic-gate 	ASSERT(lfp->lf_writers == 0);
5657c478bd9Sstevel@tonic-gate 
566*bd3561fbSToomas Soome 	error = VOP_CLOSE(lfp->lf_vp, FCREAT|FWRITE|FOFFMAX, 1, (offset_t)0,
567*bd3561fbSToomas Soome 	    CRED(), NULL);
568*bd3561fbSToomas Soome 	if (error != 0) {
5697c478bd9Sstevel@tonic-gate 		nfs_cmn_err(error, CE_WARN,
5709d39bb88Sbatschul 		    "NFS: Could not close log buffer %s - error = %m",
5719d39bb88Sbatschul 		    lfp->lf_path);
5727c478bd9Sstevel@tonic-gate #ifdef DEBUG
5737c478bd9Sstevel@tonic-gate 	} else {
5747c478bd9Sstevel@tonic-gate 		LOGGING_DPRINT((3,
5759d39bb88Sbatschul 		    "log_file_rele: %s has been closed vp=%p v_count=%d\n",
576903a11ebSrh 		    lfp->lf_path, (void *)lfp->lf_vp, lfp->lf_vp->v_count));
5777c478bd9Sstevel@tonic-gate #endif
5787c478bd9Sstevel@tonic-gate 	}
5797c478bd9Sstevel@tonic-gate 	VN_RELE(lfp->lf_vp);
5807c478bd9Sstevel@tonic-gate 
5817c478bd9Sstevel@tonic-gate 	len = strlen(lfp->lf_path) + 1;
5827c478bd9Sstevel@tonic-gate 	kmem_free(lfp->lf_path, len);
5837c478bd9Sstevel@tonic-gate 	kmem_free(lfp, sizeof (*lfp));
5847c478bd9Sstevel@tonic-gate 	rfsl_log_file--;
5857c478bd9Sstevel@tonic-gate }
5867c478bd9Sstevel@tonic-gate 
5877c478bd9Sstevel@tonic-gate /*
5887c478bd9Sstevel@tonic-gate  * Allocates a record of the size specified.
5897c478bd9Sstevel@tonic-gate  * 'exi' identifies the exportinfo structure being logged.
5907c478bd9Sstevel@tonic-gate  * 'size' indicates how much memory should be allocated
5917c478bd9Sstevel@tonic-gate  * 'cookie' is used to store an opaque value for the caller for later use
5927c478bd9Sstevel@tonic-gate  * 'flags' currently ignored.
5937c478bd9Sstevel@tonic-gate  *
5947c478bd9Sstevel@tonic-gate  * Returns a pointer to the beginning of the allocated memory.
5957c478bd9Sstevel@tonic-gate  * 'cookie' is a pointer to the 'lr_alloc' struct; this will be used
5967c478bd9Sstevel@tonic-gate  * to keep track of the encoded record and contains all the info
5977c478bd9Sstevel@tonic-gate  * for enqueuing the record on the log buffer for later writing.
5987c478bd9Sstevel@tonic-gate  *
5997c478bd9Sstevel@tonic-gate  * nfslog_record_put() must be used to 'free' this record or allocation.
6007c478bd9Sstevel@tonic-gate  */
6017c478bd9Sstevel@tonic-gate /* ARGSUSED */
6027c478bd9Sstevel@tonic-gate void *
nfslog_record_alloc(struct exportinfo * exi,int alloc_indx,void ** cookie,int flags)6030dfe541eSEvan Layton nfslog_record_alloc(struct exportinfo *exi, int alloc_indx, void **cookie,
6040dfe541eSEvan Layton     int flags)
6057c478bd9Sstevel@tonic-gate {
6067c478bd9Sstevel@tonic-gate 	struct lr_alloc *lrp;
6077c478bd9Sstevel@tonic-gate 
6087c478bd9Sstevel@tonic-gate 	lrp = (struct lr_alloc *)
6099d39bb88Sbatschul 	    kmem_cache_alloc(nfslog_mem_alloc[alloc_indx].mem_cache,
6109d39bb88Sbatschul 	    KM_NOSLEEP);
6117c478bd9Sstevel@tonic-gate 
6127c478bd9Sstevel@tonic-gate 	if (lrp == NULL) {
6137c478bd9Sstevel@tonic-gate 		*cookie = NULL;
6147c478bd9Sstevel@tonic-gate 		return (NULL);
6157c478bd9Sstevel@tonic-gate 	}
6167c478bd9Sstevel@tonic-gate 
6177c478bd9Sstevel@tonic-gate 	lrp->next = lrp;
6187c478bd9Sstevel@tonic-gate 	lrp->prev = lrp;
6197c478bd9Sstevel@tonic-gate 	lrp->lr_flags = 0;
6207c478bd9Sstevel@tonic-gate 
6217c478bd9Sstevel@tonic-gate 	lrp->log_record = (caddr_t)((uintptr_t)lrp +
6229d39bb88Sbatschul 	    (uintptr_t)sizeof (struct lr_alloc));
6237c478bd9Sstevel@tonic-gate 	lrp->size = nfslog_mem_alloc[alloc_indx].size;
6247c478bd9Sstevel@tonic-gate 	lrp->alloc_cache = nfslog_mem_alloc[alloc_indx].mem_cache;
6257c478bd9Sstevel@tonic-gate 	lrp->exi = exi;
6267c478bd9Sstevel@tonic-gate 
6277c478bd9Sstevel@tonic-gate 	if (exi->exi_export.ex_flags & EX_LOG) {
6287c478bd9Sstevel@tonic-gate 		LOG_BUFFER_HOLD(exi->exi_logbuffer);
6297c478bd9Sstevel@tonic-gate 		lrp->lb = exi->exi_logbuffer;
6307c478bd9Sstevel@tonic-gate 	} else {
6317c478bd9Sstevel@tonic-gate 		lrp->lb = NULL;
6327c478bd9Sstevel@tonic-gate 	}
6337c478bd9Sstevel@tonic-gate 
6347c478bd9Sstevel@tonic-gate 	*cookie = (void *)lrp;
6357c478bd9Sstevel@tonic-gate 
6367c478bd9Sstevel@tonic-gate 	LOGGING_DPRINT((3,
6379d39bb88Sbatschul 	    "nfslog_record_alloc(log_buffer=%p mem=%p size=%lu)\n",
638903a11ebSrh 	    (void *)exi->exi_logbuffer, (void *)lrp->log_record, lrp->size));
6397c478bd9Sstevel@tonic-gate 	return (lrp->log_record);
6407c478bd9Sstevel@tonic-gate }
6417c478bd9Sstevel@tonic-gate 
6427c478bd9Sstevel@tonic-gate /*
6437c478bd9Sstevel@tonic-gate  * After the above nfslog_record_alloc() has been called and a record
6447c478bd9Sstevel@tonic-gate  * encoded into the buffer that was returned, this function is called
6457c478bd9Sstevel@tonic-gate  * to handle appropriate disposition of the newly created record.
6467c478bd9Sstevel@tonic-gate  * The cookie value is the one that was returned from nfslog_record_alloc().
6477c478bd9Sstevel@tonic-gate  * Size is the actual size of the record that was encoded.  This is
6487c478bd9Sstevel@tonic-gate  * passed in because the size used for the alloc was just an approximation.
6497c478bd9Sstevel@tonic-gate  * The sync parameter is used to tell us if we need to force this record
6507c478bd9Sstevel@tonic-gate  * to disk and if not it will be queued for later writing.
6517c478bd9Sstevel@tonic-gate  *
6527c478bd9Sstevel@tonic-gate  * Note that if the size parameter has a value of 0, then the record is
6537c478bd9Sstevel@tonic-gate  * not written to the log and the associated data structures are released.
6547c478bd9Sstevel@tonic-gate  */
6557c478bd9Sstevel@tonic-gate void
nfslog_record_put(void * cookie,size_t size,bool_t sync,unsigned int which_buffers)6567c478bd9Sstevel@tonic-gate nfslog_record_put(void *cookie, size_t size, bool_t sync,
6570dfe541eSEvan Layton     unsigned int which_buffers)
6587c478bd9Sstevel@tonic-gate {
6597c478bd9Sstevel@tonic-gate 	struct lr_alloc *lrp = (struct lr_alloc *)cookie;
6607c478bd9Sstevel@tonic-gate 	struct log_buffer *lbp = lrp->lb;
6617c478bd9Sstevel@tonic-gate 
6627c478bd9Sstevel@tonic-gate 	/*
6637c478bd9Sstevel@tonic-gate 	 * If the caller has nothing to write or if there is
6647c478bd9Sstevel@tonic-gate 	 * an apparent error, rele the buffer and free.
6657c478bd9Sstevel@tonic-gate 	 */
6667c478bd9Sstevel@tonic-gate 	if (size == 0 || size > lrp->size) {
6677c478bd9Sstevel@tonic-gate 		nfslog_free_logrecords(lrp);
6687c478bd9Sstevel@tonic-gate 		return;
6697c478bd9Sstevel@tonic-gate 	}
6707c478bd9Sstevel@tonic-gate 
6717c478bd9Sstevel@tonic-gate 	/*
6727c478bd9Sstevel@tonic-gate 	 * Reset the size to what actually needs to be written
6737c478bd9Sstevel@tonic-gate 	 * This is used later on when the iovec is built for
6747c478bd9Sstevel@tonic-gate 	 * writing the records to the log file.
6757c478bd9Sstevel@tonic-gate 	 */
6767c478bd9Sstevel@tonic-gate 	lrp->size = size;
6777c478bd9Sstevel@tonic-gate 
6787c478bd9Sstevel@tonic-gate 	/* append to all if public exi */
6797c478bd9Sstevel@tonic-gate 	if (which_buffers == NFSLOG_ALL_BUFFERS) {
6807c478bd9Sstevel@tonic-gate 		(void) nfslog_record_append2all(lrp);
6817c478bd9Sstevel@tonic-gate 		nfslog_free_logrecords(lrp);
6827c478bd9Sstevel@tonic-gate 		return;
6837c478bd9Sstevel@tonic-gate 	}
6847c478bd9Sstevel@tonic-gate 
6857c478bd9Sstevel@tonic-gate 	/* Insert the record on the list to be written */
6867c478bd9Sstevel@tonic-gate 	mutex_enter(&lbp->lb_lock);
6877c478bd9Sstevel@tonic-gate 	if (lbp->lb_records == NULL) {
6887c478bd9Sstevel@tonic-gate 		lbp->lb_records = (caddr_t)lrp;
6897c478bd9Sstevel@tonic-gate 		lbp->lb_num_recs = 1;
6907c478bd9Sstevel@tonic-gate 		lbp->lb_size_queued = lrp->size;
6917c478bd9Sstevel@tonic-gate 	} else {
6927c478bd9Sstevel@tonic-gate 		insque(lrp, ((struct lr_alloc *)lbp->lb_records)->prev);
6937c478bd9Sstevel@tonic-gate 		lbp->lb_num_recs++;
6947c478bd9Sstevel@tonic-gate 		lbp->lb_size_queued += lrp->size;
6957c478bd9Sstevel@tonic-gate 	}
6967c478bd9Sstevel@tonic-gate 
6977c478bd9Sstevel@tonic-gate 	/*
6987c478bd9Sstevel@tonic-gate 	 * Determine if the queue for this log buffer should be flushed.
6997c478bd9Sstevel@tonic-gate 	 * This is done by either the number of records queued, the total
7007c478bd9Sstevel@tonic-gate 	 * size of all records queued or by the request of the caller
7017c478bd9Sstevel@tonic-gate 	 * via the sync parameter.
7027c478bd9Sstevel@tonic-gate 	 */
7037c478bd9Sstevel@tonic-gate 	if (lbp->lb_size_queued >= nfslog_num_bytes_to_write ||
7049d39bb88Sbatschul 	    lbp->lb_num_recs > nfslog_num_records_to_write || sync == TRUE) {
7057c478bd9Sstevel@tonic-gate 		mutex_exit(&lbp->lb_lock);
7067c478bd9Sstevel@tonic-gate 		(void) nfslog_records_flush_to_disk(lbp);
7077c478bd9Sstevel@tonic-gate 	} else {
7087c478bd9Sstevel@tonic-gate 		mutex_exit(&lbp->lb_lock);
7097c478bd9Sstevel@tonic-gate 	}
7107c478bd9Sstevel@tonic-gate 
7117c478bd9Sstevel@tonic-gate }
7127c478bd9Sstevel@tonic-gate 
7137c478bd9Sstevel@tonic-gate /*
7147c478bd9Sstevel@tonic-gate  * Examine the log_buffer struct to see if there are queue log records
7157c478bd9Sstevel@tonic-gate  * that need to be written to disk.  If some exist, pull them off of
7167c478bd9Sstevel@tonic-gate  * the log buffer and write them to the log file.
7177c478bd9Sstevel@tonic-gate  */
7187c478bd9Sstevel@tonic-gate static int
nfslog_records_flush_to_disk(struct log_buffer * lbp)7197c478bd9Sstevel@tonic-gate nfslog_records_flush_to_disk(struct log_buffer *lbp)
7207c478bd9Sstevel@tonic-gate {
7217c478bd9Sstevel@tonic-gate 
7227c478bd9Sstevel@tonic-gate 	mutex_enter(&lbp->lb_lock);
7237c478bd9Sstevel@tonic-gate 
7247c478bd9Sstevel@tonic-gate 	if (lbp->lb_records == NULL) {
7257c478bd9Sstevel@tonic-gate 		mutex_exit(&lbp->lb_lock);
7267c478bd9Sstevel@tonic-gate 		return (0);
7277c478bd9Sstevel@tonic-gate 	}
7287c478bd9Sstevel@tonic-gate 	return	(nfslog_records_flush_to_disk_nolock(lbp));
7297c478bd9Sstevel@tonic-gate }
7307c478bd9Sstevel@tonic-gate 
7317c478bd9Sstevel@tonic-gate /*
7327c478bd9Sstevel@tonic-gate  * Function requires that the caller holds lb_lock.
7337c478bd9Sstevel@tonic-gate  * Function flushes any records in the log buffer to the disk.
7347c478bd9Sstevel@tonic-gate  * Function drops the lb_lock on return.
7357c478bd9Sstevel@tonic-gate  */
7367c478bd9Sstevel@tonic-gate 
7377c478bd9Sstevel@tonic-gate static int
nfslog_records_flush_to_disk_nolock(struct log_buffer * lbp)7387c478bd9Sstevel@tonic-gate nfslog_records_flush_to_disk_nolock(struct log_buffer *lbp)
7397c478bd9Sstevel@tonic-gate {
7407c478bd9Sstevel@tonic-gate 	struct log_file *lfp = NULL;
7417c478bd9Sstevel@tonic-gate 	struct lr_alloc *lrp_writers;
7427c478bd9Sstevel@tonic-gate 	int num_recs;
7437c478bd9Sstevel@tonic-gate 	int error = 0;
7447c478bd9Sstevel@tonic-gate 
7457c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&lbp->lb_lock));
7467c478bd9Sstevel@tonic-gate 
7477c478bd9Sstevel@tonic-gate 	lfp = lbp->lb_logfile;
7487c478bd9Sstevel@tonic-gate 
7497c478bd9Sstevel@tonic-gate 	LOG_FILE_LOCK_TO_WRITE(lfp);
7507c478bd9Sstevel@tonic-gate 	ASSERT(lbp->lb_records != NULL);
7517c478bd9Sstevel@tonic-gate 
7527c478bd9Sstevel@tonic-gate 	lrp_writers = (struct lr_alloc *)lbp->lb_records;
7537c478bd9Sstevel@tonic-gate 	lbp->lb_records = NULL;
7547c478bd9Sstevel@tonic-gate 	num_recs = lbp->lb_num_recs;
7557c478bd9Sstevel@tonic-gate 	lbp->lb_num_recs = 0;
7567c478bd9Sstevel@tonic-gate 	lbp->lb_size_queued = 0;
7577c478bd9Sstevel@tonic-gate 	mutex_exit(&lbp->lb_lock);
7587c478bd9Sstevel@tonic-gate 	error = nfslog_write_logrecords(lfp, lrp_writers, num_recs);
7597c478bd9Sstevel@tonic-gate 
7607c478bd9Sstevel@tonic-gate 	LOG_FILE_UNLOCK_FROM_WRITE(lfp);
7617c478bd9Sstevel@tonic-gate 
7627c478bd9Sstevel@tonic-gate 	nfslog_free_logrecords(lrp_writers);
7637c478bd9Sstevel@tonic-gate 	return (error);
7647c478bd9Sstevel@tonic-gate }
7657c478bd9Sstevel@tonic-gate 
7667c478bd9Sstevel@tonic-gate 
7677c478bd9Sstevel@tonic-gate /*
7687c478bd9Sstevel@tonic-gate  * Take care of writing the provided log record(s) to the log file.
7697c478bd9Sstevel@tonic-gate  * We group the log records with an iovec and use VOP_WRITE to append
7707c478bd9Sstevel@tonic-gate  * them to the end of the log file.
7717c478bd9Sstevel@tonic-gate  */
7727c478bd9Sstevel@tonic-gate static int
nfslog_write_logrecords(struct log_file * lfp,struct lr_alloc * lrp_writers,int num_recs)7730dfe541eSEvan Layton nfslog_write_logrecords(struct log_file *lfp, struct lr_alloc *lrp_writers,
7740dfe541eSEvan Layton     int num_recs)
7757c478bd9Sstevel@tonic-gate {
7767c478bd9Sstevel@tonic-gate 	struct uio uio;
7777c478bd9Sstevel@tonic-gate 	struct iovec *iovp;
7787c478bd9Sstevel@tonic-gate 	int size_iovecs;
7797c478bd9Sstevel@tonic-gate 	vnode_t *vp;
7807c478bd9Sstevel@tonic-gate 	struct vattr va;
7817c478bd9Sstevel@tonic-gate 	struct lr_alloc *lrp;
7827c478bd9Sstevel@tonic-gate 	int i;
7837c478bd9Sstevel@tonic-gate 	ssize_t len;
7847c478bd9Sstevel@tonic-gate 	int ioflag = FAPPEND;
7857c478bd9Sstevel@tonic-gate 	int error = 0;
7867c478bd9Sstevel@tonic-gate 
7877c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&lfp->lf_lock));
7887c478bd9Sstevel@tonic-gate 
7897c478bd9Sstevel@tonic-gate 	vp = lfp->lf_vp;
7907c478bd9Sstevel@tonic-gate 
7917c478bd9Sstevel@tonic-gate 	size_iovecs = sizeof (struct iovec) * num_recs;
7927c478bd9Sstevel@tonic-gate 	iovp = (struct iovec *)kmem_alloc(size_iovecs, KM_NOSLEEP);
7937c478bd9Sstevel@tonic-gate 
7947c478bd9Sstevel@tonic-gate 	if (iovp == NULL) {
7957c478bd9Sstevel@tonic-gate 		error = ENOMEM;
7967c478bd9Sstevel@tonic-gate 		goto out;
7977c478bd9Sstevel@tonic-gate 	}
7987c478bd9Sstevel@tonic-gate 
7997c478bd9Sstevel@tonic-gate 	/* Build the iovec based on the list of log records */
8007c478bd9Sstevel@tonic-gate 	i = 0;
8017c478bd9Sstevel@tonic-gate 	len = 0;
8027c478bd9Sstevel@tonic-gate 	lrp = lrp_writers;
8037c478bd9Sstevel@tonic-gate 	do {
8047c478bd9Sstevel@tonic-gate 		iovp[i].iov_base = lrp->log_record;
8057c478bd9Sstevel@tonic-gate 		iovp[i].iov_len = lrp->size;
8067c478bd9Sstevel@tonic-gate 		len += lrp->size;
8077c478bd9Sstevel@tonic-gate 		lrp = lrp->next;
8087c478bd9Sstevel@tonic-gate 		i++;
8097c478bd9Sstevel@tonic-gate 	} while (lrp != lrp_writers);
8107c478bd9Sstevel@tonic-gate 
8117c478bd9Sstevel@tonic-gate 	ASSERT(i == num_recs);
8127c478bd9Sstevel@tonic-gate 
8137c478bd9Sstevel@tonic-gate 	uio.uio_iov = iovp;
8147c478bd9Sstevel@tonic-gate 	uio.uio_iovcnt = num_recs;
8157c478bd9Sstevel@tonic-gate 	uio.uio_loffset = 0;
8167c478bd9Sstevel@tonic-gate 	uio.uio_segflg = (short)UIO_SYSSPACE;
8177c478bd9Sstevel@tonic-gate 	uio.uio_resid = len;
8187c478bd9Sstevel@tonic-gate 	uio.uio_llimit = (rlim64_t)MAXOFFSET_T;
8197c478bd9Sstevel@tonic-gate 	uio.uio_fmode = FWRITE;
8207c478bd9Sstevel@tonic-gate 	uio.uio_extflg = UIO_COPY_DEFAULT;
8217c478bd9Sstevel@tonic-gate 
8227c478bd9Sstevel@tonic-gate 	/*
8237c478bd9Sstevel@tonic-gate 	 * Save the size. If the write fails, reset the size to avoid
8247c478bd9Sstevel@tonic-gate 	 * corrupted log buffer files.
8257c478bd9Sstevel@tonic-gate 	 */
8267c478bd9Sstevel@tonic-gate 	va.va_mask = AT_SIZE;
8277c478bd9Sstevel@tonic-gate 
8287c478bd9Sstevel@tonic-gate 	(void) VOP_RWLOCK(vp, V_WRITELOCK_TRUE, NULL);  /* UIO_WRITE */
829da6c28aaSamw 	if ((error = VOP_GETATTR(vp, &va, 0, CRED(), NULL)) == 0) {
8307c478bd9Sstevel@tonic-gate 		if ((len + va.va_size) < (MAXOFF32_T)) {
8317c478bd9Sstevel@tonic-gate 			error = VOP_WRITE(vp, &uio, ioflag, CRED(), NULL);
832d19d8227Spf 			VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL);
8337c478bd9Sstevel@tonic-gate 			if (uio.uio_resid)
8347c478bd9Sstevel@tonic-gate 				error = ENOSPC;
8357c478bd9Sstevel@tonic-gate 			if (error)
8367c478bd9Sstevel@tonic-gate 				(void) VOP_SETATTR(vp, &va, 0, CRED(), NULL);
8377c478bd9Sstevel@tonic-gate 		} else {
838d19d8227Spf 			VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL);
8397c478bd9Sstevel@tonic-gate 			if (!(lfp->lf_flags & L_PRINTED)) {
8407c478bd9Sstevel@tonic-gate 				cmn_err(CE_WARN,
8417c478bd9Sstevel@tonic-gate 				    "NFS Logging: buffer file %s exceeds 2GB; "
8427c478bd9Sstevel@tonic-gate 				    "stopped writing buffer \n", lfp->lf_path);
8437c478bd9Sstevel@tonic-gate 			}
8447c478bd9Sstevel@tonic-gate 			error = ENOSPC;
8457c478bd9Sstevel@tonic-gate 		}
846d19d8227Spf 	} else {
847d19d8227Spf 		VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL);
8487c478bd9Sstevel@tonic-gate 	}
8497c478bd9Sstevel@tonic-gate 
8507c478bd9Sstevel@tonic-gate 	kmem_free(iovp, size_iovecs);
8517c478bd9Sstevel@tonic-gate 
8527c478bd9Sstevel@tonic-gate out:
8537c478bd9Sstevel@tonic-gate 	if (error) {
8547c478bd9Sstevel@tonic-gate 		if (!(lfp->lf_flags & L_PRINTED)) {
8557c478bd9Sstevel@tonic-gate 			nfs_cmn_err(error, CE_WARN,
8569d39bb88Sbatschul 			    "NFS Logging disabled for buffer %s - "
8579d39bb88Sbatschul 			    "write error = %m\n", lfp->lf_path);
8587c478bd9Sstevel@tonic-gate 			lfp->lf_flags |= L_PRINTED;
8597c478bd9Sstevel@tonic-gate 		}
8607c478bd9Sstevel@tonic-gate 	} else if (lfp->lf_flags & (L_ERROR | L_PRINTED)) {
8617c478bd9Sstevel@tonic-gate 		lfp->lf_flags &= ~(L_ERROR | L_PRINTED);
8627c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN,
8639d39bb88Sbatschul 		    "NFS Logging re-enabled for buffer %s\n", lfp->lf_path);
8647c478bd9Sstevel@tonic-gate 	}
8657c478bd9Sstevel@tonic-gate 
8667c478bd9Sstevel@tonic-gate 	return (error);
8677c478bd9Sstevel@tonic-gate }
8687c478bd9Sstevel@tonic-gate 
8697c478bd9Sstevel@tonic-gate static void
nfslog_free_logrecords(struct lr_alloc * lrp_writers)8707c478bd9Sstevel@tonic-gate nfslog_free_logrecords(struct lr_alloc *lrp_writers)
8717c478bd9Sstevel@tonic-gate {
8727c478bd9Sstevel@tonic-gate 	struct lr_alloc *lrp = lrp_writers;
8737c478bd9Sstevel@tonic-gate 	struct lr_alloc *lrp_free;
8747c478bd9Sstevel@tonic-gate 
8757c478bd9Sstevel@tonic-gate 	do {
8767c478bd9Sstevel@tonic-gate 		lrp_free = lrp;
8777c478bd9Sstevel@tonic-gate 
8787c478bd9Sstevel@tonic-gate 		lrp = lrp->next;
8797c478bd9Sstevel@tonic-gate 
8807c478bd9Sstevel@tonic-gate 		/*
8817c478bd9Sstevel@tonic-gate 		 * Check to see if we are supposed to free this structure
8827c478bd9Sstevel@tonic-gate 		 * and relese the log_buffer ref count.
8837c478bd9Sstevel@tonic-gate 		 * It may be the case that the caller does not want this
8847c478bd9Sstevel@tonic-gate 		 * structure and its record contents freed just yet.
8857c478bd9Sstevel@tonic-gate 		 */
8867c478bd9Sstevel@tonic-gate 		if ((lrp_free->lr_flags & LR_ALLOC_NOFREE) == 0) {
8877c478bd9Sstevel@tonic-gate 			if (lrp_free->lb != NULL)
8887c478bd9Sstevel@tonic-gate 				log_buffer_rele(lrp_free->lb);
8897c478bd9Sstevel@tonic-gate 			if (lrp_free->alloc_cache) /* double check */
8907c478bd9Sstevel@tonic-gate 				kmem_cache_free(lrp_free->alloc_cache,
8919d39bb88Sbatschul 				    (void *)lrp_free);
8927c478bd9Sstevel@tonic-gate 		} else {
8937c478bd9Sstevel@tonic-gate 			/*
8947c478bd9Sstevel@tonic-gate 			 * after being pulled from the list the
8957c478bd9Sstevel@tonic-gate 			 * pointers need to be reinitialized.
8967c478bd9Sstevel@tonic-gate 			 */
8977c478bd9Sstevel@tonic-gate 			lrp_free->next = lrp_free;
8987c478bd9Sstevel@tonic-gate 			lrp_free->prev = lrp_free;
8997c478bd9Sstevel@tonic-gate 		}
9007c478bd9Sstevel@tonic-gate 
9017c478bd9Sstevel@tonic-gate 	} while (lrp != lrp_writers);
9027c478bd9Sstevel@tonic-gate }
9037c478bd9Sstevel@tonic-gate 
9047c478bd9Sstevel@tonic-gate /*
9057c478bd9Sstevel@tonic-gate  * Rename lbp->lb_logfile to reflect the true name requested by 'share'
9067c478bd9Sstevel@tonic-gate  */
9077c478bd9Sstevel@tonic-gate static int
nfslog_logbuffer_rename(struct log_buffer * lbp)9087c478bd9Sstevel@tonic-gate nfslog_logbuffer_rename(struct log_buffer *lbp)
9097c478bd9Sstevel@tonic-gate {
9107c478bd9Sstevel@tonic-gate 	struct log_file *lf;
9117c478bd9Sstevel@tonic-gate 	int error;
9127c478bd9Sstevel@tonic-gate 	struct log_file *logfile;
9137c478bd9Sstevel@tonic-gate 
9147c478bd9Sstevel@tonic-gate 	/*
9157c478bd9Sstevel@tonic-gate 	 * Try our best to get the cache records into the log file
9167c478bd9Sstevel@tonic-gate 	 * before the rename occurs.
9177c478bd9Sstevel@tonic-gate 	 */
9187c478bd9Sstevel@tonic-gate 	(void) nfslog_records_flush_to_disk(lbp);
9197c478bd9Sstevel@tonic-gate 
9207c478bd9Sstevel@tonic-gate 	/*
9217c478bd9Sstevel@tonic-gate 	 * Hold lb_lock before retrieving
9227c478bd9Sstevel@tonic-gate 	 * lb_logfile.
9237c478bd9Sstevel@tonic-gate 	 * Hold a reference to the
9247c478bd9Sstevel@tonic-gate 	 * "lf" structure. this is
9257c478bd9Sstevel@tonic-gate 	 * same as LOG_FILE_HOLD()
9267c478bd9Sstevel@tonic-gate 	 */
9277c478bd9Sstevel@tonic-gate 	mutex_enter(&(lbp)->lb_lock);
9287c478bd9Sstevel@tonic-gate 	lf = lbp->lb_logfile;
9297c478bd9Sstevel@tonic-gate 	mutex_enter(&(lf)->lf_lock);
9307c478bd9Sstevel@tonic-gate 	mutex_exit(&(lbp)->lb_lock);
9317c478bd9Sstevel@tonic-gate 	lf->lf_refcnt++;
9327c478bd9Sstevel@tonic-gate 	mutex_exit(&(lf)->lf_lock);
9337c478bd9Sstevel@tonic-gate 
9347c478bd9Sstevel@tonic-gate 	LOGGING_DPRINT((10, "nfslog_logbuffer_rename: renaming %s to %s\n",
9359d39bb88Sbatschul 	    lf->lf_path, lbp->lb_path));
9367c478bd9Sstevel@tonic-gate 
9377c478bd9Sstevel@tonic-gate 	/*
9387c478bd9Sstevel@tonic-gate 	 * rename the current buffer to what the daemon expects
9397c478bd9Sstevel@tonic-gate 	 */
940*bd3561fbSToomas Soome 	error = nfslog_logfile_rename(lf->lf_path, lbp->lb_path);
941*bd3561fbSToomas Soome 	if (error != 0)
9427c478bd9Sstevel@tonic-gate 		goto out;
9437c478bd9Sstevel@tonic-gate 
9447c478bd9Sstevel@tonic-gate 	/*
9457c478bd9Sstevel@tonic-gate 	 * Create a new working buffer file and have all new data sent there.
9467c478bd9Sstevel@tonic-gate 	 */
947*bd3561fbSToomas Soome 	error = log_file_create(lbp->lb_path, &logfile);
948*bd3561fbSToomas Soome 	if (error != 0) {
9497c478bd9Sstevel@tonic-gate 		/* Attempt to rename to original */
9507c478bd9Sstevel@tonic-gate 		(void) nfslog_logfile_rename(lbp->lb_path, lf->lf_path);
9517c478bd9Sstevel@tonic-gate 		goto out;
9527c478bd9Sstevel@tonic-gate 	}
9537c478bd9Sstevel@tonic-gate 
9547c478bd9Sstevel@tonic-gate 	/*
9557c478bd9Sstevel@tonic-gate 	 * Hold the lb_lock here, this will make
9567c478bd9Sstevel@tonic-gate 	 * all the threads trying to access lb->logfile block
9577c478bd9Sstevel@tonic-gate 	 * and get a new logfile structure instead of old one.
9587c478bd9Sstevel@tonic-gate 	 */
9597c478bd9Sstevel@tonic-gate 	mutex_enter(&(lbp)->lb_lock);
9607c478bd9Sstevel@tonic-gate 	lbp->lb_logfile = logfile;
9617c478bd9Sstevel@tonic-gate 	mutex_exit(&(lbp)->lb_lock);
9627c478bd9Sstevel@tonic-gate 
9637c478bd9Sstevel@tonic-gate 	LOG_FILE_RELE(lf);	/* release log_buffer's reference */
9647c478bd9Sstevel@tonic-gate 
9657c478bd9Sstevel@tonic-gate 	/*
9667c478bd9Sstevel@tonic-gate 	 * Wait for log_file to be in a quiescent state before we
9677c478bd9Sstevel@tonic-gate 	 * return to our caller to let it proceed with the reading of
9687c478bd9Sstevel@tonic-gate 	 * this file.
9697c478bd9Sstevel@tonic-gate 	 */
9707c478bd9Sstevel@tonic-gate 	nfslog_logfile_wait(lf);
9717c478bd9Sstevel@tonic-gate 
9727c478bd9Sstevel@tonic-gate out:
9737c478bd9Sstevel@tonic-gate 	/*
9747c478bd9Sstevel@tonic-gate 	 * Release our reference on "lf" in two different cases.
9757c478bd9Sstevel@tonic-gate 	 * 1. Error condition, release only the reference
9767c478bd9Sstevel@tonic-gate 	 *    that we held at the begining of this
9777c478bd9Sstevel@tonic-gate 	 *    routine on "lf" structure.
9787c478bd9Sstevel@tonic-gate 	 * 2. Fall through condition, no errors but the old
9797c478bd9Sstevel@tonic-gate 	 *    logfile structure "lf" has been replaced with
9807c478bd9Sstevel@tonic-gate 	 *    the new "logfile" structure, so release the
9817c478bd9Sstevel@tonic-gate 	 *    reference that was part of the creation of
9827c478bd9Sstevel@tonic-gate 	 *    "lf" structure to free up the resources.
9837c478bd9Sstevel@tonic-gate 	 */
9847c478bd9Sstevel@tonic-gate 
9857c478bd9Sstevel@tonic-gate 	LOG_FILE_RELE(lf);
9867c478bd9Sstevel@tonic-gate 
9877c478bd9Sstevel@tonic-gate 	return (error);
9887c478bd9Sstevel@tonic-gate }
9897c478bd9Sstevel@tonic-gate 
9907c478bd9Sstevel@tonic-gate /*
9917c478bd9Sstevel@tonic-gate  * Renames the 'from' file to 'new'.
9927c478bd9Sstevel@tonic-gate  */
9937c478bd9Sstevel@tonic-gate static int
nfslog_logfile_rename(char * from,char * new)9947c478bd9Sstevel@tonic-gate nfslog_logfile_rename(char *from, char *new)
9957c478bd9Sstevel@tonic-gate {
9967c478bd9Sstevel@tonic-gate 	int error;
9977c478bd9Sstevel@tonic-gate 
998*bd3561fbSToomas Soome 	error = vn_rename(from, new, UIO_SYSSPACE);
999*bd3561fbSToomas Soome 	if (error != 0) {
10007c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN,
10019d39bb88Sbatschul 		    "nfslog_logfile_rename: couldn't rename %s to %s\n",
10029d39bb88Sbatschul 		    from, new);
10037c478bd9Sstevel@tonic-gate 	}
10047c478bd9Sstevel@tonic-gate 	return (error);
10057c478bd9Sstevel@tonic-gate }
10067c478bd9Sstevel@tonic-gate 
10077c478bd9Sstevel@tonic-gate /*
10087c478bd9Sstevel@tonic-gate  * Wait for the log_file writers to finish before returning
10097c478bd9Sstevel@tonic-gate  */
10107c478bd9Sstevel@tonic-gate static void
nfslog_logfile_wait(struct log_file * lf)10117c478bd9Sstevel@tonic-gate nfslog_logfile_wait(struct log_file *lf)
10127c478bd9Sstevel@tonic-gate {
10137c478bd9Sstevel@tonic-gate 	mutex_enter(&lf->lf_lock);
10147c478bd9Sstevel@tonic-gate 	while (lf->lf_writers > 0) {
10157c478bd9Sstevel@tonic-gate 		lf->lf_flags |= L_WAITING;
10167c478bd9Sstevel@tonic-gate 		(void) cv_wait_sig(&lf->lf_cv_waiters, &lf->lf_lock);
10177c478bd9Sstevel@tonic-gate 	}
10187c478bd9Sstevel@tonic-gate 	mutex_exit(&lf->lf_lock);
10197c478bd9Sstevel@tonic-gate }
10207c478bd9Sstevel@tonic-gate 
10217c478bd9Sstevel@tonic-gate static int
nfslog_record_append2all(struct lr_alloc * lrp)10227c478bd9Sstevel@tonic-gate nfslog_record_append2all(struct lr_alloc *lrp)
10237c478bd9Sstevel@tonic-gate {
10247c478bd9Sstevel@tonic-gate 	struct log_buffer *lbp, *nlbp;
10257c478bd9Sstevel@tonic-gate 	int error, ret_error = 0;
10267c478bd9Sstevel@tonic-gate 	int lr_flags = lrp->lr_flags;
10277c478bd9Sstevel@tonic-gate 
10287c478bd9Sstevel@tonic-gate 	rw_enter(&nfslog_buffer_list_lock, RW_READER);
10297c478bd9Sstevel@tonic-gate 	if ((lbp = nfslog_buffer_list) != NULL)
10307c478bd9Sstevel@tonic-gate 		LOG_BUFFER_HOLD(lbp);
10317c478bd9Sstevel@tonic-gate 	for (nlbp = NULL; lbp != NULL; lbp = nlbp) {
10327c478bd9Sstevel@tonic-gate 		if ((nlbp = lbp->lb_next) != NULL) {
10337c478bd9Sstevel@tonic-gate 			/*
10347c478bd9Sstevel@tonic-gate 			 * Remember next element in the list
10357c478bd9Sstevel@tonic-gate 			 */
10367c478bd9Sstevel@tonic-gate 			LOG_BUFFER_HOLD(nlbp);
10377c478bd9Sstevel@tonic-gate 		}
10387c478bd9Sstevel@tonic-gate 		rw_exit(&nfslog_buffer_list_lock);
10397c478bd9Sstevel@tonic-gate 
10407c478bd9Sstevel@tonic-gate 		/*
10417c478bd9Sstevel@tonic-gate 		 * Insert the record on the buffer's list to be written
10427c478bd9Sstevel@tonic-gate 		 * and then flush the records to the log file.
10437c478bd9Sstevel@tonic-gate 		 * Make sure to set the no free flag so that the
10447c478bd9Sstevel@tonic-gate 		 * record can be used for the next write
10457c478bd9Sstevel@tonic-gate 		 */
10467c478bd9Sstevel@tonic-gate 		lrp->lr_flags = LR_ALLOC_NOFREE;
10477c478bd9Sstevel@tonic-gate 
10487c478bd9Sstevel@tonic-gate 		ASSERT(lbp != NULL);
10497c478bd9Sstevel@tonic-gate 		mutex_enter(&lbp->lb_lock);
10507c478bd9Sstevel@tonic-gate 		if (lbp->lb_records == NULL) {
10517c478bd9Sstevel@tonic-gate 			lbp->lb_records = (caddr_t)lrp;
10527c478bd9Sstevel@tonic-gate 			lbp->lb_num_recs = 1;
10537c478bd9Sstevel@tonic-gate 			lbp->lb_size_queued = lrp->size;
10547c478bd9Sstevel@tonic-gate 		} else {
10557c478bd9Sstevel@tonic-gate 			insque(lrp, ((struct lr_alloc *)lbp->lb_records)->prev);
10567c478bd9Sstevel@tonic-gate 			lbp->lb_num_recs++;
10577c478bd9Sstevel@tonic-gate 			lbp->lb_size_queued += lrp->size;
10587c478bd9Sstevel@tonic-gate 		}
10597c478bd9Sstevel@tonic-gate 
10607c478bd9Sstevel@tonic-gate 		/*
10617c478bd9Sstevel@tonic-gate 		 * Flush log records to disk.
10627c478bd9Sstevel@tonic-gate 		 * Function is called with lb_lock held.
10637c478bd9Sstevel@tonic-gate 		 * Function drops the lb_lock on return.
10647c478bd9Sstevel@tonic-gate 		 */
10657c478bd9Sstevel@tonic-gate 		error = nfslog_records_flush_to_disk_nolock(lbp);
10667c478bd9Sstevel@tonic-gate 
10677c478bd9Sstevel@tonic-gate 		if (error) {
10687c478bd9Sstevel@tonic-gate 			ret_error = -1;
10697c478bd9Sstevel@tonic-gate 			nfs_cmn_err(error, CE_WARN,
10709d39bb88Sbatschul 			    "rfsl_log_pubfh: could not append record to "
10719d39bb88Sbatschul 			    "\"%s\" error = %m\n", lbp->lb_path);
10727c478bd9Sstevel@tonic-gate 		}
10737c478bd9Sstevel@tonic-gate 		log_buffer_rele(lbp);
10747c478bd9Sstevel@tonic-gate 		rw_enter(&nfslog_buffer_list_lock, RW_READER);
10757c478bd9Sstevel@tonic-gate 	}
10767c478bd9Sstevel@tonic-gate 	rw_exit(&nfslog_buffer_list_lock);
10777c478bd9Sstevel@tonic-gate 
10787c478bd9Sstevel@tonic-gate 	lrp->lr_flags = lr_flags;
10797c478bd9Sstevel@tonic-gate 
10807c478bd9Sstevel@tonic-gate 	return (ret_error);
10817c478bd9Sstevel@tonic-gate }
10827c478bd9Sstevel@tonic-gate 
10837c478bd9Sstevel@tonic-gate #ifdef DEBUG
10847c478bd9Sstevel@tonic-gate static int logging_debug = 0;
10857c478bd9Sstevel@tonic-gate 
10867c478bd9Sstevel@tonic-gate /*
10877c478bd9Sstevel@tonic-gate  * 0) no debugging
10887c478bd9Sstevel@tonic-gate  * 3) current test software
10897c478bd9Sstevel@tonic-gate  * 10) random stuff
10907c478bd9Sstevel@tonic-gate  */
10917c478bd9Sstevel@tonic-gate void
nfslog_dprint(const int level,const char * fmt,...)10927c478bd9Sstevel@tonic-gate nfslog_dprint(const int level, const char *fmt, ...)
10937c478bd9Sstevel@tonic-gate {
10947c478bd9Sstevel@tonic-gate 	va_list args;
10957c478bd9Sstevel@tonic-gate 
10967c478bd9Sstevel@tonic-gate 	if (logging_debug == level ||
10977c478bd9Sstevel@tonic-gate 	    (logging_debug > 10 && (logging_debug - 10) >= level)) {
10987c478bd9Sstevel@tonic-gate 		va_start(args, fmt);
10997c478bd9Sstevel@tonic-gate 		(void) vprintf(fmt, args);
11007c478bd9Sstevel@tonic-gate 		va_end(args);
11017c478bd9Sstevel@tonic-gate 	}
11027c478bd9Sstevel@tonic-gate }
11037c478bd9Sstevel@tonic-gate 
11047c478bd9Sstevel@tonic-gate #endif /* DEBUG */
11057c478bd9Sstevel@tonic-gate 
11067c478bd9Sstevel@tonic-gate /*
11077c478bd9Sstevel@tonic-gate  * NFS Log Flush system call
11087c478bd9Sstevel@tonic-gate  * Caller must check privileges.
11097c478bd9Sstevel@tonic-gate  */
11107c478bd9Sstevel@tonic-gate /* ARGSUSED */
11117c478bd9Sstevel@tonic-gate int
nfsl_flush(struct nfsl_flush_args * args,model_t model)11127c478bd9Sstevel@tonic-gate nfsl_flush(struct nfsl_flush_args *args, model_t model)
11137c478bd9Sstevel@tonic-gate {
11147c478bd9Sstevel@tonic-gate 	struct flush_thread_params *tparams;
11157c478bd9Sstevel@tonic-gate 	struct nfsl_flush_args *nfsl_args;
11167c478bd9Sstevel@tonic-gate 	int error = 0;
11177c478bd9Sstevel@tonic-gate 	ulong_t buffer_len;
11187c478bd9Sstevel@tonic-gate 	STRUCT_HANDLE(nfsl_flush_args, uap);
11197c478bd9Sstevel@tonic-gate 
11207c478bd9Sstevel@tonic-gate 	STRUCT_SET_HANDLE(uap, model, args);
11217c478bd9Sstevel@tonic-gate 
11227c478bd9Sstevel@tonic-gate 	tparams = (struct flush_thread_params *)
11239d39bb88Sbatschul 	    kmem_zalloc(sizeof (*tparams), KM_SLEEP);
11247c478bd9Sstevel@tonic-gate 
11257c478bd9Sstevel@tonic-gate 	nfsl_args = &tparams->tp_args;
11267c478bd9Sstevel@tonic-gate 	nfsl_args->version =  STRUCT_FGET(uap, version);
11277c478bd9Sstevel@tonic-gate 	if (nfsl_args->version != NFSL_FLUSH_ARGS_VERS) {
11287c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "nfsl_flush: exected version %d, got %d",
11299d39bb88Sbatschul 		    NFSL_FLUSH_ARGS_VERS, nfsl_args->version);
11307c478bd9Sstevel@tonic-gate 		return (EIO);
11317c478bd9Sstevel@tonic-gate 	}
11327c478bd9Sstevel@tonic-gate 
11337c478bd9Sstevel@tonic-gate 	nfsl_args->directive = STRUCT_FGET(uap, directive);
11347c478bd9Sstevel@tonic-gate 	if ((nfsl_args->directive & NFSL_ALL) == 0) {
11357c478bd9Sstevel@tonic-gate 		/*
11367c478bd9Sstevel@tonic-gate 		 * Process a specific buffer
11377c478bd9Sstevel@tonic-gate 		 */
11387c478bd9Sstevel@tonic-gate 		nfsl_args->buff_len = STRUCT_FGET(uap, buff_len);
11397c478bd9Sstevel@tonic-gate 
11407c478bd9Sstevel@tonic-gate 		nfsl_args->buff = (char *)
11419d39bb88Sbatschul 		    kmem_alloc(nfsl_args->buff_len, KM_NOSLEEP);
11427c478bd9Sstevel@tonic-gate 		if (nfsl_args->buff == NULL)
11437c478bd9Sstevel@tonic-gate 			return (ENOMEM);
11447c478bd9Sstevel@tonic-gate 
11457c478bd9Sstevel@tonic-gate 		error = copyinstr((const char *)STRUCT_FGETP(uap, buff),
11469d39bb88Sbatschul 		    nfsl_args->buff, nfsl_args->buff_len, &buffer_len);
11477c478bd9Sstevel@tonic-gate 		if (error)
11487c478bd9Sstevel@tonic-gate 			return (EFAULT);
11497c478bd9Sstevel@tonic-gate 
11507c478bd9Sstevel@tonic-gate 		if (nfsl_args->buff_len != buffer_len)
11517c478bd9Sstevel@tonic-gate 			return (EFAULT);
11527c478bd9Sstevel@tonic-gate 	}
11537c478bd9Sstevel@tonic-gate 
11547c478bd9Sstevel@tonic-gate 	LOGGING_DPRINT((10, "nfsl_flush: Flushing %s buffer(s)\n",
11559d39bb88Sbatschul 	    nfsl_args->directive & NFSL_ALL ? "all" : nfsl_args->buff));
11567c478bd9Sstevel@tonic-gate 
11577c478bd9Sstevel@tonic-gate 	if (nfsl_args->directive & NFSL_SYNC) {
11587c478bd9Sstevel@tonic-gate 		/*
11597c478bd9Sstevel@tonic-gate 		 * Do the work synchronously
11607c478bd9Sstevel@tonic-gate 		 */
11617c478bd9Sstevel@tonic-gate 		nfslog_do_flush(tparams);
11627c478bd9Sstevel@tonic-gate 		error = tparams->tp_error;
11637c478bd9Sstevel@tonic-gate 		kmem_free(nfsl_args->buff, nfsl_args->buff_len);
11647c478bd9Sstevel@tonic-gate 		kmem_free(tparams, sizeof (*tparams));
11657c478bd9Sstevel@tonic-gate 	} else {
11667c478bd9Sstevel@tonic-gate 		/*
11677c478bd9Sstevel@tonic-gate 		 * Do the work asynchronously
11687c478bd9Sstevel@tonic-gate 		 */
11690dfe541eSEvan Layton 		(void) zthread_create(NULL, 0, nfslog_do_flush,
11700dfe541eSEvan Layton 		    tparams, 0, minclsyspri);
11717c478bd9Sstevel@tonic-gate 	}
11727c478bd9Sstevel@tonic-gate 
11737c478bd9Sstevel@tonic-gate 	return (error);
11747c478bd9Sstevel@tonic-gate }
11757c478bd9Sstevel@tonic-gate 
11767c478bd9Sstevel@tonic-gate /*
11777c478bd9Sstevel@tonic-gate  * This is where buffer flushing would occur, but there is no buffering
11787c478bd9Sstevel@tonic-gate  * at this time.
11797c478bd9Sstevel@tonic-gate  * Possibly rename the log buffer for processing.
1180da6c28aaSamw  * Sets tparams->ta_error equal to the value of the error that occurred,
11817c478bd9Sstevel@tonic-gate  * 0 otherwise.
11827c478bd9Sstevel@tonic-gate  * Returns ENOENT if the buffer is not found.
11837c478bd9Sstevel@tonic-gate  */
11847c478bd9Sstevel@tonic-gate static void
nfslog_do_flush(struct flush_thread_params * tparams)11857c478bd9Sstevel@tonic-gate nfslog_do_flush(struct flush_thread_params *tparams)
11867c478bd9Sstevel@tonic-gate {
11877c478bd9Sstevel@tonic-gate 	struct nfsl_flush_args *args;
11889d39bb88Sbatschul 	struct log_buffer *lbp, *nlbp;
11897c478bd9Sstevel@tonic-gate 	int error = ENOENT;
11907c478bd9Sstevel@tonic-gate 	int found = 0;
11917c478bd9Sstevel@tonic-gate 	char *buf_inprog;	/* name of buff in progress */
11927c478bd9Sstevel@tonic-gate 	int buf_inprog_len;
11937c478bd9Sstevel@tonic-gate 
11947c478bd9Sstevel@tonic-gate 	/*
11957c478bd9Sstevel@tonic-gate 	 * Sanity check on the arguments.
11967c478bd9Sstevel@tonic-gate 	 */
11977c478bd9Sstevel@tonic-gate 	if (!tparams)
11987c478bd9Sstevel@tonic-gate 		return;
11997c478bd9Sstevel@tonic-gate 	args = &tparams->tp_args;
12007c478bd9Sstevel@tonic-gate 	if (!args)
12017c478bd9Sstevel@tonic-gate 		return;
12027c478bd9Sstevel@tonic-gate 
12037c478bd9Sstevel@tonic-gate 	rw_enter(&nfslog_buffer_list_lock, RW_READER);
12049d39bb88Sbatschul 	if ((lbp = nfslog_buffer_list) != NULL) {
12059d39bb88Sbatschul 		LOG_BUFFER_HOLD(lbp);
12069d39bb88Sbatschul 	}
12079d39bb88Sbatschul 	for (nlbp = NULL; lbp != NULL; lbp = nlbp) {
12089d39bb88Sbatschul 		if ((nlbp = lbp->lb_next) != NULL) {
12099d39bb88Sbatschul 			LOG_BUFFER_HOLD(nlbp);
12109d39bb88Sbatschul 		}
12119d39bb88Sbatschul 		rw_exit(&nfslog_buffer_list_lock);
12127c478bd9Sstevel@tonic-gate 		if (args->directive & NFSL_ALL) {
12137c478bd9Sstevel@tonic-gate 			(void) nfslog_records_flush_to_disk(lbp);
12147c478bd9Sstevel@tonic-gate 		} else {
12157c478bd9Sstevel@tonic-gate 			if ((strcmp(lbp->lb_path, args->buff) == 0) &&
12169d39bb88Sbatschul 			    (args->directive & NFSL_RENAME)) {
12177c478bd9Sstevel@tonic-gate 				error = nfslog_logbuffer_rename(lbp);
12187c478bd9Sstevel@tonic-gate 				found++;
12199d39bb88Sbatschul 				if (nlbp != NULL)
12209d39bb88Sbatschul 					log_buffer_rele(nlbp);
12219d39bb88Sbatschul 				log_buffer_rele(lbp);
12227c478bd9Sstevel@tonic-gate 				break;
12237c478bd9Sstevel@tonic-gate 			}
12247c478bd9Sstevel@tonic-gate 		}
12259d39bb88Sbatschul 		log_buffer_rele(lbp);
12269d39bb88Sbatschul 		rw_enter(&nfslog_buffer_list_lock, RW_READER);
12277c478bd9Sstevel@tonic-gate 	}
12289d39bb88Sbatschul 	if (!found)
12299d39bb88Sbatschul 		rw_exit(&nfslog_buffer_list_lock);
12307c478bd9Sstevel@tonic-gate 
12317c478bd9Sstevel@tonic-gate 	if (!found && ((args->directive & NFSL_ALL) == 0) &&
12327c478bd9Sstevel@tonic-gate 	    (args->directive & NFSL_RENAME)) {
12337c478bd9Sstevel@tonic-gate 		/*
12347c478bd9Sstevel@tonic-gate 		 * The specified buffer is not currently in use,
12357c478bd9Sstevel@tonic-gate 		 * simply rename the file indicated.
12367c478bd9Sstevel@tonic-gate 		 */
12377c478bd9Sstevel@tonic-gate 		buf_inprog_len = strlen(args->buff) +
12389d39bb88Sbatschul 		    strlen(LOG_INPROG_STRING) + 1;
12397c478bd9Sstevel@tonic-gate 		buf_inprog = (caddr_t)kmem_alloc(buf_inprog_len, KM_SLEEP);
12407c478bd9Sstevel@tonic-gate 		(void) sprintf(buf_inprog, "%s%s",
12419d39bb88Sbatschul 		    args->buff, LOG_INPROG_STRING);
12427c478bd9Sstevel@tonic-gate 
12437c478bd9Sstevel@tonic-gate 		error = nfslog_logfile_rename(buf_inprog, args->buff);
12447c478bd9Sstevel@tonic-gate 
12457c478bd9Sstevel@tonic-gate 		kmem_free(buf_inprog, buf_inprog_len);
12467c478bd9Sstevel@tonic-gate 	}
12477c478bd9Sstevel@tonic-gate 
12487c478bd9Sstevel@tonic-gate 	if ((args->directive & NFSL_SYNC) == 0) {
12497c478bd9Sstevel@tonic-gate 		/*
12507c478bd9Sstevel@tonic-gate 		 * Work was performed asynchronously, the caller is
12517c478bd9Sstevel@tonic-gate 		 * no longer waiting for us.
12527c478bd9Sstevel@tonic-gate 		 * Free the thread arguments and exit.
12537c478bd9Sstevel@tonic-gate 		 */
12547c478bd9Sstevel@tonic-gate 		kmem_free(args->buff, args->buff_len);
12557c478bd9Sstevel@tonic-gate 		kmem_free(tparams, sizeof (*tparams));
12560dfe541eSEvan Layton 		zthread_exit();
12577c478bd9Sstevel@tonic-gate 	}
12587c478bd9Sstevel@tonic-gate 
12597c478bd9Sstevel@tonic-gate 	tparams->tp_error = error;
12607c478bd9Sstevel@tonic-gate }
12617c478bd9Sstevel@tonic-gate 
12627c478bd9Sstevel@tonic-gate /*
12637c478bd9Sstevel@tonic-gate  * Generate buffer_header.
12647c478bd9Sstevel@tonic-gate  * 'loghdr' points the the buffer_header, and *reclen
12657c478bd9Sstevel@tonic-gate  * contains the length of the buffer.
12667c478bd9Sstevel@tonic-gate  */
12677c478bd9Sstevel@tonic-gate static void
create_buffer_header(caddr_t * loghdr,size_t * reclen,size_t * freesize)12687c478bd9Sstevel@tonic-gate create_buffer_header(caddr_t *loghdr, size_t *reclen, size_t *freesize)
12697c478bd9Sstevel@tonic-gate {
12707c478bd9Sstevel@tonic-gate 	timestruc_t		now;
12717c478bd9Sstevel@tonic-gate 	nfslog_buffer_header	lh;
12727c478bd9Sstevel@tonic-gate 	XDR			xdrs;
12737c478bd9Sstevel@tonic-gate 	unsigned int		final_size;
12747c478bd9Sstevel@tonic-gate 
12757c478bd9Sstevel@tonic-gate 
12767c478bd9Sstevel@tonic-gate 	/* pick some size that will hold the buffer_header */
12777c478bd9Sstevel@tonic-gate 	*freesize = NFSLOG_SMALL_RECORD_SIZE;
12787c478bd9Sstevel@tonic-gate 
12797c478bd9Sstevel@tonic-gate 	/*
12807c478bd9Sstevel@tonic-gate 	 * Fill header
12817c478bd9Sstevel@tonic-gate 	 */
12827c478bd9Sstevel@tonic-gate 	lh.bh_length = 0;	/* don't know yet how large it will be */
12837c478bd9Sstevel@tonic-gate 	lh.bh_version = NFSLOG_BUF_VERSION;
12847c478bd9Sstevel@tonic-gate 	lh.bh_flags = 0;
12857c478bd9Sstevel@tonic-gate 	lh.bh_offset = 0;
12867c478bd9Sstevel@tonic-gate 	gethrestime(&now);
12877c478bd9Sstevel@tonic-gate 	TIMESPEC_TO_TIMESPEC32(&lh.bh_timestamp, &now);
12887c478bd9Sstevel@tonic-gate 
12897c478bd9Sstevel@tonic-gate 	/*
12907c478bd9Sstevel@tonic-gate 	 * Encode the header
12917c478bd9Sstevel@tonic-gate 	 */
12927c478bd9Sstevel@tonic-gate 	*loghdr = (caddr_t)kmem_alloc(*freesize, KM_SLEEP);
12937c478bd9Sstevel@tonic-gate 	xdrmem_create(&xdrs, *loghdr, *freesize, XDR_ENCODE);
12947c478bd9Sstevel@tonic-gate 
12957c478bd9Sstevel@tonic-gate 	(void) xdr_nfslog_buffer_header(&xdrs, &lh);
12967c478bd9Sstevel@tonic-gate 
12977c478bd9Sstevel@tonic-gate 	/*
12987c478bd9Sstevel@tonic-gate 	 * Reset with final size of the encoded data
12997c478bd9Sstevel@tonic-gate 	 */
13007c478bd9Sstevel@tonic-gate 	final_size = xdr_getpos(&xdrs);
13017c478bd9Sstevel@tonic-gate 	xdr_setpos(&xdrs, 0);
13027c478bd9Sstevel@tonic-gate 	(void) xdr_u_int(&xdrs, &final_size);
13037c478bd9Sstevel@tonic-gate 
13047c478bd9Sstevel@tonic-gate 	*reclen = (size_t)final_size;
13057c478bd9Sstevel@tonic-gate }
13067c478bd9Sstevel@tonic-gate 
13077c478bd9Sstevel@tonic-gate /*
13087c478bd9Sstevel@tonic-gate  * ****************************************************************
13097c478bd9Sstevel@tonic-gate  * RPC dispatch table for logging
13107c478bd9Sstevel@tonic-gate  * Indexed by program, version, proc
13117c478bd9Sstevel@tonic-gate  * Based on NFS dispatch table.
13127c478bd9Sstevel@tonic-gate  */
13137c478bd9Sstevel@tonic-gate struct nfslog_proc_disp {
13147c478bd9Sstevel@tonic-gate 	bool_t	(*xdrargs)();
13157c478bd9Sstevel@tonic-gate 	bool_t	(*xdrres)();
13167c478bd9Sstevel@tonic-gate 	bool_t	affects_transactions;	/* Operation affects transaction */
13177c478bd9Sstevel@tonic-gate 					/* processing */
13187c478bd9Sstevel@tonic-gate };
13197c478bd9Sstevel@tonic-gate 
13207c478bd9Sstevel@tonic-gate struct nfslog_vers_disp {
13217c478bd9Sstevel@tonic-gate 	int	nfslog_dis_nprocs;			/* number of procs */
13227c478bd9Sstevel@tonic-gate 	struct nfslog_proc_disp	*nfslog_dis_proc_table;	/* proc array */
13237c478bd9Sstevel@tonic-gate };
13247c478bd9Sstevel@tonic-gate 
13257c478bd9Sstevel@tonic-gate struct nfslog_prog_disp {
13267c478bd9Sstevel@tonic-gate 	int	nfslog_dis_prog;		/* program number */
13277c478bd9Sstevel@tonic-gate 	int	nfslog_dis_versmin;		/* Minimum version value */
13287c478bd9Sstevel@tonic-gate 	int	nfslog_dis_nvers;		/* Number of version values */
13297c478bd9Sstevel@tonic-gate 	struct nfslog_vers_disp	*nfslog_dis_vers_table;	/* versions array */
13307c478bd9Sstevel@tonic-gate };
13317c478bd9Sstevel@tonic-gate 
13327c478bd9Sstevel@tonic-gate static int rfs_log_bad = 0;	/* incremented on bad log attempts */
13337c478bd9Sstevel@tonic-gate static int rfs_log_good = 0;	/* incremented on successful log attempts */
13347c478bd9Sstevel@tonic-gate 
13357c478bd9Sstevel@tonic-gate /*
13367c478bd9Sstevel@tonic-gate  * Define the actions taken per prog/vers/proc:
13377c478bd9Sstevel@tonic-gate  *
13387c478bd9Sstevel@tonic-gate  * In some cases, the nl types are the same as the nfs types and a simple
13397c478bd9Sstevel@tonic-gate  * bcopy should suffice. Rather that define tens of identical procedures,
13407c478bd9Sstevel@tonic-gate  * simply define these to bcopy. Similarly this takes care of different
13417c478bd9Sstevel@tonic-gate  * procs that use same parameter struct.
13427c478bd9Sstevel@tonic-gate  */
13437c478bd9Sstevel@tonic-gate 
13447c478bd9Sstevel@tonic-gate static struct nfslog_proc_disp nfslog_proc_v2[] = {
13457c478bd9Sstevel@tonic-gate 	/*
13467c478bd9Sstevel@tonic-gate 	 * NFS VERSION 2
13477c478bd9Sstevel@tonic-gate 	 */
13487c478bd9Sstevel@tonic-gate 
13497c478bd9Sstevel@tonic-gate 	/* RFS_NULL = 0 */
13507c478bd9Sstevel@tonic-gate 	{xdr_void, xdr_void, FALSE},
13517c478bd9Sstevel@tonic-gate 
13527c478bd9Sstevel@tonic-gate 	/* RFS_GETATTR = 1 */
13537c478bd9Sstevel@tonic-gate 	{xdr_fhandle, xdr_nfslog_getattrres, FALSE},
13547c478bd9Sstevel@tonic-gate 
13557c478bd9Sstevel@tonic-gate 	/* RFS_SETATTR = 2 */
13567c478bd9Sstevel@tonic-gate 	{xdr_nfslog_setattrargs, xdr_nfsstat, TRUE},
13577c478bd9Sstevel@tonic-gate 
13587c478bd9Sstevel@tonic-gate 	/* RFS_ROOT = 3 *** NO LONGER SUPPORTED *** */
13597c478bd9Sstevel@tonic-gate 	{xdr_void, xdr_void, FALSE},
13607c478bd9Sstevel@tonic-gate 
13617c478bd9Sstevel@tonic-gate 	/* RFS_LOOKUP = 4 */
13627c478bd9Sstevel@tonic-gate 	{xdr_nfslog_diropargs, xdr_nfslog_diropres, TRUE},
13637c478bd9Sstevel@tonic-gate 
13647c478bd9Sstevel@tonic-gate 	/* RFS_READLINK = 5 */
13657c478bd9Sstevel@tonic-gate 	{xdr_fhandle, xdr_nfslog_rdlnres, FALSE},
13667c478bd9Sstevel@tonic-gate 
13677c478bd9Sstevel@tonic-gate 	/* RFS_READ = 6 */
13687c478bd9Sstevel@tonic-gate 	{xdr_nfslog_nfsreadargs, xdr_nfslog_rdresult, TRUE},
13697c478bd9Sstevel@tonic-gate 
13707c478bd9Sstevel@tonic-gate 	/* RFS_WRITECACHE = 7 *** NO LONGER SUPPORTED *** */
13717c478bd9Sstevel@tonic-gate 	{xdr_void, xdr_void, FALSE},
13727c478bd9Sstevel@tonic-gate 
13737c478bd9Sstevel@tonic-gate 	/* RFS_WRITE = 8 */
13747c478bd9Sstevel@tonic-gate 	{xdr_nfslog_writeargs, xdr_nfslog_writeresult, TRUE},
13757c478bd9Sstevel@tonic-gate 
13767c478bd9Sstevel@tonic-gate 	/* RFS_CREATE = 9 */
13777c478bd9Sstevel@tonic-gate 	{xdr_nfslog_createargs, xdr_nfslog_diropres, TRUE},
13787c478bd9Sstevel@tonic-gate 
13797c478bd9Sstevel@tonic-gate 	/* RFS_REMOVE = 10 */
13807c478bd9Sstevel@tonic-gate 	{xdr_nfslog_diropargs, xdr_nfsstat, TRUE},
13817c478bd9Sstevel@tonic-gate 
13827c478bd9Sstevel@tonic-gate 	/* RFS_RENAME = 11 */
13837c478bd9Sstevel@tonic-gate 	{xdr_nfslog_rnmargs, xdr_nfsstat, TRUE},
13847c478bd9Sstevel@tonic-gate 
13857c478bd9Sstevel@tonic-gate 	/* RFS_LINK = 12 */
13867c478bd9Sstevel@tonic-gate 	{xdr_nfslog_linkargs, xdr_nfsstat, TRUE},
13877c478bd9Sstevel@tonic-gate 
13887c478bd9Sstevel@tonic-gate 	/* RFS_SYMLINK = 13 */
13897c478bd9Sstevel@tonic-gate 	{xdr_nfslog_symlinkargs, xdr_nfsstat, TRUE},
13907c478bd9Sstevel@tonic-gate 
13917c478bd9Sstevel@tonic-gate 	/* RFS_MKDIR = 14 */
13927c478bd9Sstevel@tonic-gate 	{xdr_nfslog_createargs, xdr_nfslog_diropres, TRUE},
13937c478bd9Sstevel@tonic-gate 
13947c478bd9Sstevel@tonic-gate 	/* RFS_RMDIR = 15 */
13957c478bd9Sstevel@tonic-gate 	{xdr_nfslog_diropargs, xdr_nfsstat, TRUE},
13967c478bd9Sstevel@tonic-gate 
13977c478bd9Sstevel@tonic-gate 	/* RFS_READDIR = 16 */
13987c478bd9Sstevel@tonic-gate 	{xdr_nfslog_rddirargs, xdr_nfslog_rddirres, TRUE},
13997c478bd9Sstevel@tonic-gate 
14007c478bd9Sstevel@tonic-gate 	/* RFS_STATFS = 17 */
14017c478bd9Sstevel@tonic-gate 	{xdr_fhandle, xdr_nfslog_statfs, FALSE},
14027c478bd9Sstevel@tonic-gate };
14037c478bd9Sstevel@tonic-gate 
14047c478bd9Sstevel@tonic-gate 
14057c478bd9Sstevel@tonic-gate /*
14067c478bd9Sstevel@tonic-gate  * NFS VERSION 3
14077c478bd9Sstevel@tonic-gate  */
14087c478bd9Sstevel@tonic-gate 
14097c478bd9Sstevel@tonic-gate static struct nfslog_proc_disp nfslog_proc_v3[] = {
14107c478bd9Sstevel@tonic-gate 
14117c478bd9Sstevel@tonic-gate 	/* NFSPROC3_NULL = 0 */
14127c478bd9Sstevel@tonic-gate 	{xdr_void, xdr_void, FALSE},
14137c478bd9Sstevel@tonic-gate 
14147c478bd9Sstevel@tonic-gate 	/* NFSPROC3_GETATTR = 1 */
141527242a7cSthurlow 	{xdr_nfslog_nfs_fh3, xdr_nfslog_GETATTR3res, FALSE},
14167c478bd9Sstevel@tonic-gate 
14177c478bd9Sstevel@tonic-gate 	/* NFSPROC3_SETATTR = 2 */
14187c478bd9Sstevel@tonic-gate 	{xdr_nfslog_SETATTR3args, xdr_nfslog_SETATTR3res, TRUE},
14197c478bd9Sstevel@tonic-gate 
14207c478bd9Sstevel@tonic-gate 	/* NFSPROC3_LOOKUP = 3 */
14217c478bd9Sstevel@tonic-gate 	{xdr_nfslog_diropargs3, xdr_nfslog_LOOKUP3res, TRUE},
14227c478bd9Sstevel@tonic-gate 
14237c478bd9Sstevel@tonic-gate 	/* NFSPROC3_ACCESS = 4 */
14247c478bd9Sstevel@tonic-gate 	{xdr_nfslog_ACCESS3args, xdr_nfslog_ACCESS3res, FALSE},
14257c478bd9Sstevel@tonic-gate 
14267c478bd9Sstevel@tonic-gate 	/* NFSPROC3_READLINK = 5 */
142727242a7cSthurlow 	{xdr_nfslog_nfs_fh3, xdr_nfslog_READLINK3res, FALSE},
14287c478bd9Sstevel@tonic-gate 
14297c478bd9Sstevel@tonic-gate 	/* NFSPROC3_READ = 6 */
14307c478bd9Sstevel@tonic-gate 	{xdr_nfslog_READ3args, xdr_nfslog_READ3res, TRUE},
14317c478bd9Sstevel@tonic-gate 
14327c478bd9Sstevel@tonic-gate 	/* NFSPROC3_WRITE = 7 */
14337c478bd9Sstevel@tonic-gate 	{xdr_nfslog_WRITE3args, xdr_nfslog_WRITE3res, TRUE},
14347c478bd9Sstevel@tonic-gate 
14357c478bd9Sstevel@tonic-gate 	/* NFSPROC3_CREATE = 8 */
14367c478bd9Sstevel@tonic-gate 	{xdr_nfslog_CREATE3args, xdr_nfslog_CREATE3res, TRUE},
14377c478bd9Sstevel@tonic-gate 
14387c478bd9Sstevel@tonic-gate 	/* NFSPROC3_MKDIR = 9 */
14397c478bd9Sstevel@tonic-gate 	{xdr_nfslog_MKDIR3args, xdr_nfslog_MKDIR3res, TRUE},
14407c478bd9Sstevel@tonic-gate 
14417c478bd9Sstevel@tonic-gate 	/* NFSPROC3_SYMLINK = 10 */
14427c478bd9Sstevel@tonic-gate 	{xdr_nfslog_SYMLINK3args, xdr_nfslog_SYMLINK3res, TRUE},
14437c478bd9Sstevel@tonic-gate 
14447c478bd9Sstevel@tonic-gate 	/* NFSPROC3_MKNOD = 11 */
14457c478bd9Sstevel@tonic-gate 	{xdr_nfslog_MKNOD3args, xdr_nfslog_MKNOD3res, TRUE},
14467c478bd9Sstevel@tonic-gate 
14477c478bd9Sstevel@tonic-gate 	/* NFSPROC3_REMOVE = 12 */
14487c478bd9Sstevel@tonic-gate 	{xdr_nfslog_REMOVE3args, xdr_nfslog_REMOVE3res, TRUE},
14497c478bd9Sstevel@tonic-gate 
14507c478bd9Sstevel@tonic-gate 	/* NFSPROC3_RMDIR = 13 */
14517c478bd9Sstevel@tonic-gate 	{xdr_nfslog_RMDIR3args, xdr_nfslog_RMDIR3res, TRUE},
14527c478bd9Sstevel@tonic-gate 
14537c478bd9Sstevel@tonic-gate 	/* NFSPROC3_RENAME = 14 */
14547c478bd9Sstevel@tonic-gate 	{xdr_nfslog_RENAME3args, xdr_nfslog_RENAME3res, TRUE},
14557c478bd9Sstevel@tonic-gate 
14567c478bd9Sstevel@tonic-gate 	/* NFSPROC3_LINK = 15 */
14577c478bd9Sstevel@tonic-gate 	{xdr_nfslog_LINK3args, xdr_nfslog_LINK3res, TRUE},
14587c478bd9Sstevel@tonic-gate 
14597c478bd9Sstevel@tonic-gate 	/* NFSPROC3_READDIR = 16 */
14607c478bd9Sstevel@tonic-gate 	{xdr_nfslog_READDIR3args, xdr_nfslog_READDIR3res, TRUE},
14617c478bd9Sstevel@tonic-gate 
14627c478bd9Sstevel@tonic-gate 	/* NFSPROC3_READDIRPLUS = 17 */
14637c478bd9Sstevel@tonic-gate 	{xdr_nfslog_READDIRPLUS3args, xdr_nfslog_READDIRPLUS3res, TRUE},
14647c478bd9Sstevel@tonic-gate 
14657c478bd9Sstevel@tonic-gate 	/* NFSPROC3_FSSTAT = 18 */
14667c478bd9Sstevel@tonic-gate 	{xdr_nfslog_FSSTAT3args, xdr_nfslog_FSSTAT3res, FALSE},
14677c478bd9Sstevel@tonic-gate 
14687c478bd9Sstevel@tonic-gate 	/* NFSPROC3_FSINFO = 19 */
14697c478bd9Sstevel@tonic-gate 	{xdr_nfslog_FSINFO3args, xdr_nfslog_FSINFO3res, FALSE},
14707c478bd9Sstevel@tonic-gate 
14717c478bd9Sstevel@tonic-gate 	/* NFSPROC3_PATHCONF = 20 */
14727c478bd9Sstevel@tonic-gate 	{xdr_nfslog_PATHCONF3args, xdr_nfslog_PATHCONF3res, FALSE},
14737c478bd9Sstevel@tonic-gate 
14747c478bd9Sstevel@tonic-gate 	/* NFSPROC3_COMMIT = 21 */
14757c478bd9Sstevel@tonic-gate 	{xdr_nfslog_COMMIT3args, xdr_nfslog_COMMIT3res, FALSE},
14767c478bd9Sstevel@tonic-gate };
14777c478bd9Sstevel@tonic-gate 
14787c478bd9Sstevel@tonic-gate static struct nfslog_proc_disp nfslog_proc_v1[] = {
14797c478bd9Sstevel@tonic-gate 	/*
14807c478bd9Sstevel@tonic-gate 	 * NFSLOG VERSION 1
14817c478bd9Sstevel@tonic-gate 	 */
14827c478bd9Sstevel@tonic-gate 
14837c478bd9Sstevel@tonic-gate 	/* NFSLOG_NULL = 0 */
14847c478bd9Sstevel@tonic-gate 	{xdr_void, xdr_void, TRUE},
14857c478bd9Sstevel@tonic-gate 
14867c478bd9Sstevel@tonic-gate 	/* NFSLOG_SHARE = 1 */
14877c478bd9Sstevel@tonic-gate 	{xdr_nfslog_sharefsargs, xdr_nfslog_sharefsres, TRUE},
14887c478bd9Sstevel@tonic-gate 
14897c478bd9Sstevel@tonic-gate 	/* NFSLOG_UNSHARE = 2 */
14907c478bd9Sstevel@tonic-gate 	{xdr_nfslog_sharefsargs, xdr_nfslog_sharefsres, TRUE},
14917c478bd9Sstevel@tonic-gate 
14927c478bd9Sstevel@tonic-gate 	/* NFSLOG_LOOKUP = 3 */
14937c478bd9Sstevel@tonic-gate 	{xdr_nfslog_diropargs3, xdr_nfslog_LOOKUP3res, TRUE},
14947c478bd9Sstevel@tonic-gate 
14957c478bd9Sstevel@tonic-gate 	/* NFSLOG_GETFH = 4 */
14967c478bd9Sstevel@tonic-gate 	{xdr_nfslog_getfhargs, xdr_nfsstat, TRUE},
14977c478bd9Sstevel@tonic-gate };
14987c478bd9Sstevel@tonic-gate 
14997c478bd9Sstevel@tonic-gate static struct nfslog_vers_disp nfslog_vers_disptable[] = {
15007c478bd9Sstevel@tonic-gate 	{sizeof (nfslog_proc_v2) / sizeof (nfslog_proc_v2[0]),
15017c478bd9Sstevel@tonic-gate 	    nfslog_proc_v2},
15027c478bd9Sstevel@tonic-gate 	{sizeof (nfslog_proc_v3) / sizeof (nfslog_proc_v3[0]),
15037c478bd9Sstevel@tonic-gate 	    nfslog_proc_v3},
15047c478bd9Sstevel@tonic-gate };
15057c478bd9Sstevel@tonic-gate 
15067c478bd9Sstevel@tonic-gate static struct nfslog_vers_disp nfslog_nfslog_vers_disptable[] = {
15077c478bd9Sstevel@tonic-gate 	{sizeof (nfslog_proc_v1) / sizeof (nfslog_proc_v1[0]),
15087c478bd9Sstevel@tonic-gate 	    nfslog_proc_v1},
15097c478bd9Sstevel@tonic-gate };
15107c478bd9Sstevel@tonic-gate 
15117c478bd9Sstevel@tonic-gate static struct nfslog_prog_disp nfslog_dispatch_table[] = {
15127c478bd9Sstevel@tonic-gate 	{NFS_PROGRAM, NFS_VERSMIN,
15137c478bd9Sstevel@tonic-gate 		(sizeof (nfslog_vers_disptable) /
15147c478bd9Sstevel@tonic-gate 		sizeof (nfslog_vers_disptable[0])),
15157c478bd9Sstevel@tonic-gate 		nfslog_vers_disptable},
15167c478bd9Sstevel@tonic-gate 
15177c478bd9Sstevel@tonic-gate 	{NFSLOG_PROGRAM, NFSLOG_VERSMIN,
15187c478bd9Sstevel@tonic-gate 		(sizeof (nfslog_nfslog_vers_disptable) /
15197c478bd9Sstevel@tonic-gate 		sizeof (nfslog_nfslog_vers_disptable[0])),
15207c478bd9Sstevel@tonic-gate 		nfslog_nfslog_vers_disptable},
15217c478bd9Sstevel@tonic-gate };
15227c478bd9Sstevel@tonic-gate 
15237c478bd9Sstevel@tonic-gate static int	nfslog_dispatch_table_arglen = sizeof (nfslog_dispatch_table) /
15247c478bd9Sstevel@tonic-gate 					sizeof (nfslog_dispatch_table[0]);
15257c478bd9Sstevel@tonic-gate 
15267c478bd9Sstevel@tonic-gate /*
15277c478bd9Sstevel@tonic-gate  * This function will determine the appropriate export info struct to use
15287c478bd9Sstevel@tonic-gate  * and allocate a record id to be used in the written log buffer.
15297c478bd9Sstevel@tonic-gate  * Usually this is a straightforward operation but the existence of the
15307c478bd9Sstevel@tonic-gate  * multicomponent lookup and its semantics of crossing file system
15317c478bd9Sstevel@tonic-gate  * boundaries add to the complexity.  See the comments below...
15327c478bd9Sstevel@tonic-gate  */
15337c478bd9Sstevel@tonic-gate struct exportinfo *
nfslog_get_exi(nfs_export_t * ne,struct exportinfo * exi,struct svc_req * req,caddr_t res,unsigned int * nfslog_rec_id)15347c478bd9Sstevel@tonic-gate nfslog_get_exi(
15350dfe541eSEvan Layton 	nfs_export_t *ne,
15367c478bd9Sstevel@tonic-gate 	struct exportinfo *exi,
15377c478bd9Sstevel@tonic-gate 	struct svc_req *req,
15387c478bd9Sstevel@tonic-gate 	caddr_t res,
15397c478bd9Sstevel@tonic-gate 	unsigned int *nfslog_rec_id)
15407c478bd9Sstevel@tonic-gate {
15417c478bd9Sstevel@tonic-gate 	struct log_buffer *lb;
15427c478bd9Sstevel@tonic-gate 	struct exportinfo *exi_ret = NULL;
154327242a7cSthurlow 	fhandle_t		*fh;
15447c478bd9Sstevel@tonic-gate 	nfs_fh3			*fh3;
15457c478bd9Sstevel@tonic-gate 
15467c478bd9Sstevel@tonic-gate 	if (exi == NULL)
15477c478bd9Sstevel@tonic-gate 		return (NULL);
15487c478bd9Sstevel@tonic-gate 
15497c478bd9Sstevel@tonic-gate 	/*
15507c478bd9Sstevel@tonic-gate 	 * If the exi is marked for logging, allocate a record id and return
15517c478bd9Sstevel@tonic-gate 	 */
15527c478bd9Sstevel@tonic-gate 	if (exi->exi_export.ex_flags & EX_LOG) {
15537c478bd9Sstevel@tonic-gate 		lb = exi->exi_logbuffer;
15547c478bd9Sstevel@tonic-gate 
15557c478bd9Sstevel@tonic-gate 		/* obtain the unique record id for the caller */
15567c478bd9Sstevel@tonic-gate 		*nfslog_rec_id = atomic_add_32_nv(&lb->lb_rec_id, (int32_t)1);
15577c478bd9Sstevel@tonic-gate 
15587c478bd9Sstevel@tonic-gate 		/*
15597c478bd9Sstevel@tonic-gate 		 * The caller will expect to be able to exi_rele() it,
15607c478bd9Sstevel@tonic-gate 		 * so exi->exi_count must be incremented before it can
15617c478bd9Sstevel@tonic-gate 		 * be returned, to make it uniform with exi_ret->exi_count
15627c478bd9Sstevel@tonic-gate 		 */
15633ccecb66SThomas Haynes 		exi_hold(exi);
15647c478bd9Sstevel@tonic-gate 		return (exi);
15657c478bd9Sstevel@tonic-gate 	}
15667c478bd9Sstevel@tonic-gate 
15670dfe541eSEvan Layton 	if (exi != ne->exi_public)
15687c478bd9Sstevel@tonic-gate 		return (NULL);
15697c478bd9Sstevel@tonic-gate 
15707c478bd9Sstevel@tonic-gate 	/*
15717c478bd9Sstevel@tonic-gate 	 * Here we have an exi that is not marked for logging.
15727c478bd9Sstevel@tonic-gate 	 * It is possible that this request is a multicomponent lookup
15737c478bd9Sstevel@tonic-gate 	 * that was done from the public file handle (not logged) and
15747c478bd9Sstevel@tonic-gate 	 * the resulting file handle being returned to the client exists
15757c478bd9Sstevel@tonic-gate 	 * in a file system that is being logged.  If this is the case
15767c478bd9Sstevel@tonic-gate 	 * we need to log this multicomponent lookup to the appropriate
15777c478bd9Sstevel@tonic-gate 	 * log buffer.  This will allow for the appropriate path name
15787c478bd9Sstevel@tonic-gate 	 * mapping to occur at user level.
15797c478bd9Sstevel@tonic-gate 	 */
15807c478bd9Sstevel@tonic-gate 	if (req->rq_prog == NFS_PROGRAM) {
15817c478bd9Sstevel@tonic-gate 		switch (req->rq_vers) {
15827c478bd9Sstevel@tonic-gate 		case NFS_V3:
15837c478bd9Sstevel@tonic-gate 			if ((req->rq_proc == NFSPROC3_LOOKUP) &&
15849d39bb88Sbatschul 			    (((LOOKUP3res *)res)->status == NFS3_OK)) {
15857c478bd9Sstevel@tonic-gate 				fh3 = &((LOOKUP3res *)res)->res_u.ok.object;
158627242a7cSthurlow 				exi_ret = checkexport(&fh3->fh3_fsid,
15879d39bb88Sbatschul 				    FH3TOXFIDP(fh3));
15887c478bd9Sstevel@tonic-gate 			}
15897c478bd9Sstevel@tonic-gate 			break;
15907c478bd9Sstevel@tonic-gate 
15917c478bd9Sstevel@tonic-gate 		case NFS_VERSION:
15927c478bd9Sstevel@tonic-gate 			if ((req->rq_proc == RFS_LOOKUP) &&
15939d39bb88Sbatschul 			    (((struct nfsdiropres *)
15949d39bb88Sbatschul 			    res)->dr_status == NFS_OK)) {
15959d39bb88Sbatschul 				fh =  &((struct nfsdiropres *)res)->
15969d39bb88Sbatschul 				    dr_u.dr_drok_u.drok_fhandle;
159727242a7cSthurlow 				exi_ret = checkexport(&fh->fh_fsid,
15989d39bb88Sbatschul 				    (fid_t *)&fh->fh_xlen);
15997c478bd9Sstevel@tonic-gate 			}
16007c478bd9Sstevel@tonic-gate 			break;
16017c478bd9Sstevel@tonic-gate 		default:
16027c478bd9Sstevel@tonic-gate 			break;
16037c478bd9Sstevel@tonic-gate 		}
16047c478bd9Sstevel@tonic-gate 	}
16057c478bd9Sstevel@tonic-gate 
16067c478bd9Sstevel@tonic-gate 	if (exi_ret != NULL && exi_ret->exi_export.ex_flags & EX_LOG) {
16077c478bd9Sstevel@tonic-gate 		lb = exi_ret->exi_logbuffer;
16087c478bd9Sstevel@tonic-gate 		/* obtain the unique record id for the caller */
16097c478bd9Sstevel@tonic-gate 		*nfslog_rec_id = atomic_add_32_nv(&lb->lb_rec_id, (int32_t)1);
16107c478bd9Sstevel@tonic-gate 
16117c478bd9Sstevel@tonic-gate 		return (exi_ret);
16127c478bd9Sstevel@tonic-gate 	}
16137c478bd9Sstevel@tonic-gate 	return (NULL);
16147c478bd9Sstevel@tonic-gate }
16157c478bd9Sstevel@tonic-gate 
16167c478bd9Sstevel@tonic-gate #ifdef DEBUG
16177c478bd9Sstevel@tonic-gate static long long rfslog_records_ignored = 0;
16187c478bd9Sstevel@tonic-gate #endif
16197c478bd9Sstevel@tonic-gate 
16207c478bd9Sstevel@tonic-gate /*
16217c478bd9Sstevel@tonic-gate  * nfslog_write_record - Fill in the record buffer for writing out.
16227c478bd9Sstevel@tonic-gate  * If logrecp is null, log it, otherwise, malloc the record and return it.
16237c478bd9Sstevel@tonic-gate  *
16247c478bd9Sstevel@tonic-gate  * It is the responsibility of the caller to check whether this exportinfo
16257c478bd9Sstevel@tonic-gate  * has logging enabled.
16267c478bd9Sstevel@tonic-gate  * Note that nfslog_share_public_record() only needs to check for the
16277c478bd9Sstevel@tonic-gate  * existence of at least one logbuffer to which the public filehandle record
16287c478bd9Sstevel@tonic-gate  * needs to be logged.
16297c478bd9Sstevel@tonic-gate  */
16307c478bd9Sstevel@tonic-gate void
nfslog_write_record(struct exportinfo * exi,struct svc_req * req,caddr_t args,caddr_t res,cred_t * cr,struct netbuf * pnb,unsigned int record_id,unsigned int which_buffers)16317c478bd9Sstevel@tonic-gate nfslog_write_record(struct exportinfo *exi, struct svc_req *req,
16320dfe541eSEvan Layton     caddr_t args, caddr_t res, cred_t *cr, struct netbuf *pnb,
16330dfe541eSEvan Layton     unsigned int record_id, unsigned int which_buffers)
16347c478bd9Sstevel@tonic-gate {
16357c478bd9Sstevel@tonic-gate 	struct nfslog_prog_disp	*progtable;	/* prog struct */
16367c478bd9Sstevel@tonic-gate 	struct nfslog_vers_disp	*verstable;	/* version struct */
16377c478bd9Sstevel@tonic-gate 	struct nfslog_proc_disp	*disp = NULL;	/* proc struct */
16387c478bd9Sstevel@tonic-gate 	int			i, vers;
16397c478bd9Sstevel@tonic-gate 	void			*log_cookie;	/* for logrecord if */
16407c478bd9Sstevel@tonic-gate 	caddr_t			buffer;
16417c478bd9Sstevel@tonic-gate 	XDR			xdrs;
16427c478bd9Sstevel@tonic-gate 	unsigned int		final_size;
16437c478bd9Sstevel@tonic-gate 	int			encode_ok;
16447c478bd9Sstevel@tonic-gate 	int			alloc_indx;
16457c478bd9Sstevel@tonic-gate 
16467c478bd9Sstevel@tonic-gate 	ASSERT(exi != NULL); ASSERT(req != NULL); ASSERT(args != NULL);
16477c478bd9Sstevel@tonic-gate 	ASSERT(res != NULL); ASSERT(cr != NULL);
16487c478bd9Sstevel@tonic-gate 
16497c478bd9Sstevel@tonic-gate 	/*
16507c478bd9Sstevel@tonic-gate 	 * Find program element
16517c478bd9Sstevel@tonic-gate 	 * Search the list since program can not be used as index
16527c478bd9Sstevel@tonic-gate 	 */
16537c478bd9Sstevel@tonic-gate 	for (i = 0; (i < nfslog_dispatch_table_arglen); i++) {
16547c478bd9Sstevel@tonic-gate 		if (req->rq_prog == nfslog_dispatch_table[i].nfslog_dis_prog)
16557c478bd9Sstevel@tonic-gate 			break;
16567c478bd9Sstevel@tonic-gate 	}
16577c478bd9Sstevel@tonic-gate 	if (i >= nfslog_dispatch_table_arglen) {	/* program not logged */
16587c478bd9Sstevel@tonic-gate 		/* not an error */
16597c478bd9Sstevel@tonic-gate 		return;
16607c478bd9Sstevel@tonic-gate 	}
16617c478bd9Sstevel@tonic-gate 
16627c478bd9Sstevel@tonic-gate 	/*
16637c478bd9Sstevel@tonic-gate 	 * Extract the dispatch functions based on program/version
16647c478bd9Sstevel@tonic-gate 	 */
16657c478bd9Sstevel@tonic-gate 	progtable = &nfslog_dispatch_table[i];
16667c478bd9Sstevel@tonic-gate 	vers = req->rq_vers - progtable->nfslog_dis_versmin;
16677c478bd9Sstevel@tonic-gate 	verstable = &progtable->nfslog_dis_vers_table[vers];
16687c478bd9Sstevel@tonic-gate 	disp = &verstable->nfslog_dis_proc_table[req->rq_proc];
16697c478bd9Sstevel@tonic-gate 
16707c478bd9Sstevel@tonic-gate 	if (!(exi->exi_export.ex_flags & EX_LOG_ALLOPS) &&
16717c478bd9Sstevel@tonic-gate 	    !disp->affects_transactions) {
16727c478bd9Sstevel@tonic-gate 		/*
16737c478bd9Sstevel@tonic-gate 		 * Only interested in logging operations affecting
16747c478bd9Sstevel@tonic-gate 		 * transaction generation. This is not one of them.
16757c478bd9Sstevel@tonic-gate 		 */
16767c478bd9Sstevel@tonic-gate #ifdef DEBUG
16777c478bd9Sstevel@tonic-gate 		rfslog_records_ignored++;
16787c478bd9Sstevel@tonic-gate #endif
16797c478bd9Sstevel@tonic-gate 		return;
16807c478bd9Sstevel@tonic-gate 	}
16817c478bd9Sstevel@tonic-gate 
16827c478bd9Sstevel@tonic-gate 	switch (req->rq_prog) {
16837c478bd9Sstevel@tonic-gate 	case NFS_PROGRAM:
16847c478bd9Sstevel@tonic-gate 		switch (req->rq_vers) {
16857c478bd9Sstevel@tonic-gate 		case NFS_V3:
16867c478bd9Sstevel@tonic-gate 			switch (req->rq_proc) {
16877c478bd9Sstevel@tonic-gate 			case NFSPROC3_READDIRPLUS:
16887c478bd9Sstevel@tonic-gate 				alloc_indx = MEDIUM_INDX;
16897c478bd9Sstevel@tonic-gate 				break;
16907c478bd9Sstevel@tonic-gate 			default:
16917c478bd9Sstevel@tonic-gate 				alloc_indx = SMALL_INDX;
16927c478bd9Sstevel@tonic-gate 				break;
16937c478bd9Sstevel@tonic-gate 			}
16947c478bd9Sstevel@tonic-gate 			break;
16957c478bd9Sstevel@tonic-gate 		default:
16967c478bd9Sstevel@tonic-gate 			alloc_indx = SMALL_INDX;
16977c478bd9Sstevel@tonic-gate 			break;
16987c478bd9Sstevel@tonic-gate 		}
16997c478bd9Sstevel@tonic-gate 		break;
17007c478bd9Sstevel@tonic-gate 	case NFSLOG_PROGRAM:
17017c478bd9Sstevel@tonic-gate 		alloc_indx = MEDIUM_INDX;
17027c478bd9Sstevel@tonic-gate 		break;
17037c478bd9Sstevel@tonic-gate 	default:
17047c478bd9Sstevel@tonic-gate 		alloc_indx = SMALL_INDX;
17057c478bd9Sstevel@tonic-gate 		break;
17067c478bd9Sstevel@tonic-gate 	}
17077c478bd9Sstevel@tonic-gate 
17087c478bd9Sstevel@tonic-gate 	do {
17097c478bd9Sstevel@tonic-gate 		encode_ok = FALSE;
17107c478bd9Sstevel@tonic-gate 
17117c478bd9Sstevel@tonic-gate 		/* Pick the size to alloc; end of the road - return */
17127c478bd9Sstevel@tonic-gate 		if (nfslog_mem_alloc[alloc_indx].size == (-1)) {
17137c478bd9Sstevel@tonic-gate 			cmn_err(CE_WARN,
17149d39bb88Sbatschul 			    "NFSLOG: unable to encode record - prog=%d "
17159d39bb88Sbatschul 			    "proc = %d", req->rq_prog, req->rq_proc);
17167c478bd9Sstevel@tonic-gate 			return;
17177c478bd9Sstevel@tonic-gate 		}
17187c478bd9Sstevel@tonic-gate 
17197c478bd9Sstevel@tonic-gate 		buffer = nfslog_record_alloc(exi, alloc_indx, &log_cookie, 0);
17207c478bd9Sstevel@tonic-gate 		if (buffer == NULL) {
17217c478bd9Sstevel@tonic-gate 			/* Error processing - no space alloced */
17227c478bd9Sstevel@tonic-gate 			rfs_log_bad++;
17237c478bd9Sstevel@tonic-gate 			cmn_err(CE_WARN, "NFSLOG: can't get record");
17247c478bd9Sstevel@tonic-gate 			return;
17257c478bd9Sstevel@tonic-gate 		}
17267c478bd9Sstevel@tonic-gate 
17277c478bd9Sstevel@tonic-gate 		xdrmem_create(&xdrs, buffer,
17289d39bb88Sbatschul 		    nfslog_mem_alloc[alloc_indx].size, XDR_ENCODE);
17297c478bd9Sstevel@tonic-gate 
17307c478bd9Sstevel@tonic-gate 		/*
17317c478bd9Sstevel@tonic-gate 		 * Encode the header, args and results of the record
17327c478bd9Sstevel@tonic-gate 		 */
17337c478bd9Sstevel@tonic-gate 		if (xdr_nfslog_request_record(&xdrs, exi, req, cr, pnb,
17349d39bb88Sbatschul 		    nfslog_mem_alloc[alloc_indx].size, record_id) &&
17359d39bb88Sbatschul 		    (*disp->xdrargs)(&xdrs, args) &&
17369d39bb88Sbatschul 		    (*disp->xdrres)(&xdrs, res)) {
17377c478bd9Sstevel@tonic-gate 				encode_ok = TRUE;
17387c478bd9Sstevel@tonic-gate 
17397c478bd9Sstevel@tonic-gate 				rfs_log_good++;
17407c478bd9Sstevel@tonic-gate 				/*
17417c478bd9Sstevel@tonic-gate 				 * Get the final size of the encoded
17427c478bd9Sstevel@tonic-gate 				 * data and insert that length at the
17437c478bd9Sstevel@tonic-gate 				 * beginning.
17447c478bd9Sstevel@tonic-gate 				 */
17457c478bd9Sstevel@tonic-gate 				final_size = xdr_getpos(&xdrs);
17467c478bd9Sstevel@tonic-gate 				xdr_setpos(&xdrs, 0);
17477c478bd9Sstevel@tonic-gate 				(void) xdr_u_int(&xdrs, &final_size);
17487c478bd9Sstevel@tonic-gate 		} else {
17497c478bd9Sstevel@tonic-gate 			/* Oops, the encode failed so we need to free memory */
17507c478bd9Sstevel@tonic-gate 			nfslog_record_put(log_cookie, 0, FALSE, which_buffers);
17517c478bd9Sstevel@tonic-gate 			alloc_indx++;
17527c478bd9Sstevel@tonic-gate 		}
17537c478bd9Sstevel@tonic-gate 
17547c478bd9Sstevel@tonic-gate 	} while (encode_ok == FALSE);
17557c478bd9Sstevel@tonic-gate 
17567c478bd9Sstevel@tonic-gate 
17577c478bd9Sstevel@tonic-gate 	/*
17587c478bd9Sstevel@tonic-gate 	 * Take the final log record and put it in the log file.
17597c478bd9Sstevel@tonic-gate 	 * This may be queued to the file internally and written
17607c478bd9Sstevel@tonic-gate 	 * later unless the last parameter is TRUE.
17617c478bd9Sstevel@tonic-gate 	 * If the record_id is 0 then this is most likely a share/unshare
17627c478bd9Sstevel@tonic-gate 	 * request and it should be written synchronously to the log file.
17637c478bd9Sstevel@tonic-gate 	 */
17649d39bb88Sbatschul 	nfslog_record_put(log_cookie,
17659d39bb88Sbatschul 	    final_size, (record_id == 0), which_buffers);
17667c478bd9Sstevel@tonic-gate }
17677c478bd9Sstevel@tonic-gate 
17687c478bd9Sstevel@tonic-gate static char *
get_publicfh_path(int * alloc_length)17697c478bd9Sstevel@tonic-gate get_publicfh_path(int *alloc_length)
17707c478bd9Sstevel@tonic-gate {
17717c478bd9Sstevel@tonic-gate 	char *pubpath;
17720dfe541eSEvan Layton 	nfs_export_t *ne = nfs_get_export();
17737c478bd9Sstevel@tonic-gate 
17740dfe541eSEvan Layton 	rw_enter(&ne->exported_lock, RW_READER);
17757c478bd9Sstevel@tonic-gate 
17760dfe541eSEvan Layton 	*alloc_length = ne->exi_public->exi_export.ex_pathlen + 1;
17777c478bd9Sstevel@tonic-gate 	pubpath = kmem_alloc(*alloc_length, KM_SLEEP);
17787c478bd9Sstevel@tonic-gate 
17790dfe541eSEvan Layton 	(void) strcpy(pubpath, ne->exi_public->exi_export.ex_path);
17807c478bd9Sstevel@tonic-gate 
17810dfe541eSEvan Layton 	rw_exit(&ne->exported_lock);
17827c478bd9Sstevel@tonic-gate 
17837c478bd9Sstevel@tonic-gate 	return (pubpath);
17847c478bd9Sstevel@tonic-gate }
17857c478bd9Sstevel@tonic-gate 
17867c478bd9Sstevel@tonic-gate static void
log_public_record(struct exportinfo * exi,cred_t * cr)17877c478bd9Sstevel@tonic-gate log_public_record(struct exportinfo *exi, cred_t *cr)
17887c478bd9Sstevel@tonic-gate {
17897c478bd9Sstevel@tonic-gate 	struct svc_req	req;
17907c478bd9Sstevel@tonic-gate 	struct netbuf	nb = {0, 0, NULL};
17917c478bd9Sstevel@tonic-gate 	int free_length = 0;
17927c478bd9Sstevel@tonic-gate 	diropargs3 args;
17937c478bd9Sstevel@tonic-gate 	LOOKUP3res res;
17947c478bd9Sstevel@tonic-gate 
17957c478bd9Sstevel@tonic-gate 	bzero(&req, sizeof (req));
17967c478bd9Sstevel@tonic-gate 	req.rq_prog = NFSLOG_PROGRAM;
17977c478bd9Sstevel@tonic-gate 	req.rq_vers = NFSLOG_VERSION;
17987c478bd9Sstevel@tonic-gate 	req.rq_proc = NFSLOG_LOOKUP;
17997c478bd9Sstevel@tonic-gate 	req.rq_cred.oa_flavor = AUTH_NONE;
18007c478bd9Sstevel@tonic-gate 
18017c478bd9Sstevel@tonic-gate 	bzero(&args, sizeof (diropargs3));
18027c478bd9Sstevel@tonic-gate 	bzero(&res, sizeof (LOOKUP3res));
18037c478bd9Sstevel@tonic-gate 
18047c478bd9Sstevel@tonic-gate 	args.dir.fh3_length = 0;
18057c478bd9Sstevel@tonic-gate 	if ((args.name = get_publicfh_path(&free_length)) == NULL)
18067c478bd9Sstevel@tonic-gate 		return;
18077c478bd9Sstevel@tonic-gate 	args.dirp = &args.dir;
18087c478bd9Sstevel@tonic-gate 
18097c478bd9Sstevel@tonic-gate 	res.status = NFS3_OK;
18107c478bd9Sstevel@tonic-gate 	res.res_u.ok.object.fh3_length = 0;
18117c478bd9Sstevel@tonic-gate 
18127c478bd9Sstevel@tonic-gate 	/*
18137c478bd9Sstevel@tonic-gate 	 * Calling this function with the exi_public
18147c478bd9Sstevel@tonic-gate 	 * will have the effect of appending the record
18157c478bd9Sstevel@tonic-gate 	 * to each of the open log buffers
18167c478bd9Sstevel@tonic-gate 	 */
18177c478bd9Sstevel@tonic-gate 	nfslog_write_record(exi, &req,
18189d39bb88Sbatschul 	    (caddr_t)&args, (caddr_t)&res, cr, &nb, 0, NFSLOG_ALL_BUFFERS);
18197c478bd9Sstevel@tonic-gate 
18207c478bd9Sstevel@tonic-gate 	kmem_free(args.name, free_length);
18217c478bd9Sstevel@tonic-gate }
18227c478bd9Sstevel@tonic-gate 
18237c478bd9Sstevel@tonic-gate /*
18247c478bd9Sstevel@tonic-gate  * nfslog_share_record - logs a share request.
18257c478bd9Sstevel@tonic-gate  * This is not an NFS request, but we pretend here...
18267c478bd9Sstevel@tonic-gate  */
18277c478bd9Sstevel@tonic-gate void
nfslog_share_record(struct exportinfo * exi,cred_t * cr)18287c478bd9Sstevel@tonic-gate nfslog_share_record(struct exportinfo *exi, cred_t *cr)
18297c478bd9Sstevel@tonic-gate {
18307c478bd9Sstevel@tonic-gate 	struct svc_req	req;
18317c478bd9Sstevel@tonic-gate 	int		res = 0;
18327c478bd9Sstevel@tonic-gate 	struct netbuf	nb = {0, 0, NULL};
18337c478bd9Sstevel@tonic-gate 
18347c478bd9Sstevel@tonic-gate 	ASSERT(exi != NULL);
18357c478bd9Sstevel@tonic-gate 
18367c478bd9Sstevel@tonic-gate 	if (nfslog_buffer_list == NULL)
18377c478bd9Sstevel@tonic-gate 		return;
18387c478bd9Sstevel@tonic-gate 
18397c478bd9Sstevel@tonic-gate 	if (exi->exi_export.ex_flags & EX_LOG) {
18407c478bd9Sstevel@tonic-gate 		bzero(&req, sizeof (req));
18417c478bd9Sstevel@tonic-gate 		req.rq_prog = NFSLOG_PROGRAM;
18427c478bd9Sstevel@tonic-gate 		req.rq_vers = NFSLOG_VERSION;
18437c478bd9Sstevel@tonic-gate 		req.rq_proc = NFSLOG_SHARE;
18447c478bd9Sstevel@tonic-gate 		req.rq_cred.oa_flavor = AUTH_NONE;
18459d39bb88Sbatschul 		nfslog_write_record(exi, &req, (caddr_t)exi, (caddr_t)&res, cr,
18469d39bb88Sbatschul 		    &nb, 0, NFSLOG_ONE_BUFFER);
18477c478bd9Sstevel@tonic-gate 	}
18487c478bd9Sstevel@tonic-gate 
18497c478bd9Sstevel@tonic-gate 	log_public_record(exi, cr);
18507c478bd9Sstevel@tonic-gate }
18517c478bd9Sstevel@tonic-gate 
18527c478bd9Sstevel@tonic-gate /*
18537c478bd9Sstevel@tonic-gate  * nfslog_unshare_record - logs an unshare request.
18547c478bd9Sstevel@tonic-gate  * This is not an NFS request, but we pretend here...
18557c478bd9Sstevel@tonic-gate  */
18567c478bd9Sstevel@tonic-gate void
nfslog_unshare_record(struct exportinfo * exi,cred_t * cr)18577c478bd9Sstevel@tonic-gate nfslog_unshare_record(struct exportinfo *exi, cred_t *cr)
18587c478bd9Sstevel@tonic-gate {
18597c478bd9Sstevel@tonic-gate 	struct svc_req	req;
18607c478bd9Sstevel@tonic-gate 	int		res = 0;
18617c478bd9Sstevel@tonic-gate 	struct netbuf	nb = {0, 0, NULL};
18627c478bd9Sstevel@tonic-gate 
18637c478bd9Sstevel@tonic-gate 	ASSERT(exi != NULL);
18647c478bd9Sstevel@tonic-gate 	ASSERT(exi->exi_export.ex_flags & EX_LOG);
18657c478bd9Sstevel@tonic-gate 
18667c478bd9Sstevel@tonic-gate 	bzero(&req, sizeof (req));
18677c478bd9Sstevel@tonic-gate 	req.rq_prog = NFSLOG_PROGRAM;
18687c478bd9Sstevel@tonic-gate 	req.rq_vers = NFSLOG_VERSION;
18697c478bd9Sstevel@tonic-gate 	req.rq_proc = NFSLOG_UNSHARE;
18707c478bd9Sstevel@tonic-gate 	req.rq_cred.oa_flavor = AUTH_NONE;
18717c478bd9Sstevel@tonic-gate 	nfslog_write_record(exi, &req,
18729d39bb88Sbatschul 	    (caddr_t)exi, (caddr_t)&res, cr, &nb, 0, NFSLOG_ONE_BUFFER);
18737c478bd9Sstevel@tonic-gate }
18747c478bd9Sstevel@tonic-gate 
18757c478bd9Sstevel@tonic-gate 
18767c478bd9Sstevel@tonic-gate void
nfslog_getfh(struct exportinfo * exi,fhandle * fh,char * fname,enum uio_seg seg,cred_t * cr)18770dfe541eSEvan Layton nfslog_getfh(struct exportinfo *exi, fhandle *fh, char *fname, enum uio_seg seg,
18780dfe541eSEvan Layton     cred_t *cr)
18797c478bd9Sstevel@tonic-gate {
18807c478bd9Sstevel@tonic-gate 	struct svc_req	req;
18817c478bd9Sstevel@tonic-gate 	int		res = 0;
18827c478bd9Sstevel@tonic-gate 	struct netbuf	nb = {0, 0, NULL};
18837c478bd9Sstevel@tonic-gate 	int		error = 0;
18847c478bd9Sstevel@tonic-gate 	char		*namebuf;
18857c478bd9Sstevel@tonic-gate 	size_t		len;
18867c478bd9Sstevel@tonic-gate 	nfslog_getfhargs gfh;
18877c478bd9Sstevel@tonic-gate 
18887c478bd9Sstevel@tonic-gate 	ASSERT(exi != NULL);
18897c478bd9Sstevel@tonic-gate 	ASSERT(exi->exi_export.ex_flags & EX_LOG);
18907c478bd9Sstevel@tonic-gate 
18917c478bd9Sstevel@tonic-gate 	bzero(&req, sizeof (req));
18927c478bd9Sstevel@tonic-gate 	req.rq_prog = NFSLOG_PROGRAM;
18937c478bd9Sstevel@tonic-gate 	req.rq_vers = NFSLOG_VERSION;
18947c478bd9Sstevel@tonic-gate 	req.rq_proc = NFSLOG_GETFH;
18957c478bd9Sstevel@tonic-gate 	req.rq_cred.oa_flavor = AUTH_NONE;
18967c478bd9Sstevel@tonic-gate 
18977c478bd9Sstevel@tonic-gate 	namebuf = kmem_alloc(MAXPATHLEN + 4, KM_SLEEP);
18987c478bd9Sstevel@tonic-gate 	if (seg == UIO_USERSPACE) {
18997c478bd9Sstevel@tonic-gate 		error = copyinstr(fname, namebuf, MAXPATHLEN, &len);
19007c478bd9Sstevel@tonic-gate 	} else {
19017c478bd9Sstevel@tonic-gate 		error = copystr(fname, namebuf, MAXPATHLEN, &len);
19027c478bd9Sstevel@tonic-gate 	}
19037c478bd9Sstevel@tonic-gate 
19047c478bd9Sstevel@tonic-gate 	if (!error) {
19057c478bd9Sstevel@tonic-gate 		gfh.gfh_fh_buf = *fh;
19067c478bd9Sstevel@tonic-gate 		gfh.gfh_path = namebuf;
19077c478bd9Sstevel@tonic-gate 
19089d39bb88Sbatschul 		nfslog_write_record(exi, &req, (caddr_t)&gfh, (caddr_t)&res,
19099d39bb88Sbatschul 		    cr, &nb, 0, NFSLOG_ONE_BUFFER);
19107c478bd9Sstevel@tonic-gate 	}
19117c478bd9Sstevel@tonic-gate 	kmem_free(namebuf, MAXPATHLEN + 4);
19127c478bd9Sstevel@tonic-gate }
1913