xref: /onnv-gate/usr/src/uts/common/fs/sockfs/nl7clogd.c (revision 5331:3047ad28a67b)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
54155Sfr80241  * Common Development and Distribution License (the "License").
64155Sfr80241  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
224155Sfr80241  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate 
280Sstevel@tonic-gate #include <sys/sysmacros.h>
290Sstevel@tonic-gate #include <sys/callb.h>
300Sstevel@tonic-gate #include <sys/fcntl.h>
310Sstevel@tonic-gate #include <sys/filio.h>
320Sstevel@tonic-gate #include <sys/pathname.h>
330Sstevel@tonic-gate #include <sys/cpuvar.h>
340Sstevel@tonic-gate #include <sys/promif.h>
350Sstevel@tonic-gate #include <fs/sockfs/nl7c.h>
360Sstevel@tonic-gate #include <fs/sockfs/nl7curi.h>
370Sstevel@tonic-gate 
380Sstevel@tonic-gate #include <inet/nca/ncadoorhdr.h>
390Sstevel@tonic-gate #include <inet/nca/ncalogd.h>
400Sstevel@tonic-gate 
410Sstevel@tonic-gate extern boolean_t	nl7c_logd_enabled;
420Sstevel@tonic-gate extern boolean_t	nl7c_logd_started;
430Sstevel@tonic-gate extern boolean_t	nl7c_logd_cycle;
440Sstevel@tonic-gate 
450Sstevel@tonic-gate extern void		nl7clogd_startup(void);
460Sstevel@tonic-gate 
470Sstevel@tonic-gate extern boolean_t	nl7c_http_log(uri_desc_t *, uri_desc_t *,
480Sstevel@tonic-gate 			    nca_request_log_t *, char **, char **, uint32_t *);
490Sstevel@tonic-gate 
500Sstevel@tonic-gate static void		logit_flush(void *);
510Sstevel@tonic-gate 
520Sstevel@tonic-gate /*
530Sstevel@tonic-gate  * NL7C reuses the NCA logging scheme, the directory "/var/nca" contains
540Sstevel@tonic-gate  * the symlink "current" to 1 of up to 16 NCA BLF logging files, by default
550Sstevel@tonic-gate  * a single logging file "log", optionally paths of up to 16 log files can
560Sstevel@tonic-gate  * be specified via ncalogd.conf(4), note that these log files need not be
570Sstevel@tonic-gate  * in the "/var/nca" directory.
580Sstevel@tonic-gate  *
590Sstevel@tonic-gate  * NL7C reuses the NCA logging APIs defined in <inet/nca/ncalogd.h>, at
60*5331Samw  * some future date (when NCA is deprecated or improvements are needed)
610Sstevel@tonic-gate  * these need to be moved into NL7C.
620Sstevel@tonic-gate  *
630Sstevel@tonic-gate  * NL7C implements logging differently in 2 ways, 1st the initialization
640Sstevel@tonic-gate  * is handled completely in the kernel by NL7C when it's enabled vs NCA
650Sstevel@tonic-gate  * when the kmod was loaded, 2nd a simple worker thread with a FIFO queue
660Sstevel@tonic-gate  * is used to process log_buf_t's instead of a squeue_t (this is done as
670Sstevel@tonic-gate  * squeue_t's are private to NCA and IP at some future date we may us an
680Sstevel@tonic-gate  * IP squeue_t):
690Sstevel@tonic-gate  *
700Sstevel@tonic-gate  *	logd_t - used by various functions to manage a singly linked
710Sstevel@tonic-gate  * 	grounded list of log_buf_t's and it's worker thread.
720Sstevel@tonic-gate  */
730Sstevel@tonic-gate 
740Sstevel@tonic-gate typedef struct logd_s {
750Sstevel@tonic-gate 	log_buf_t	*head;
760Sstevel@tonic-gate 	log_buf_t	*tail;
770Sstevel@tonic-gate 	kthread_t	*worker;
780Sstevel@tonic-gate 	kcondvar_t	wait;
790Sstevel@tonic-gate 	kmutex_t	lock;
800Sstevel@tonic-gate } logd_t;
810Sstevel@tonic-gate 
820Sstevel@tonic-gate /*
830Sstevel@tonic-gate  * In-kernel logging:
840Sstevel@tonic-gate  *
850Sstevel@tonic-gate  *	nl7c_logbuf_max - tunable for the number of preallocated next
860Sstevel@tonic-gate  *	log_buf_t(s) for use by log_buf_alloc(), note if the value is
870Sstevel@tonic-gate  *	0 (the default) then max_cpus worth will be allocated.
880Sstevel@tonic-gate  *
890Sstevel@tonic-gate  *	logd - global logd_t used to post log_buf_t's too.
900Sstevel@tonic-gate  *
910Sstevel@tonic-gate  *	log - global current log_buf_t that logit() logs too.
920Sstevel@tonic-gate  *
930Sstevel@tonic-gate  *	logv[] - vector of available next logbuf(s) such that when
940Sstevel@tonic-gate  *	logbuf is filled another can be used while being processed by
950Sstevel@tonic-gate  *	the logger() and kmem_cache_alloc() of a replacement is done.
960Sstevel@tonic-gate  *
970Sstevel@tonic-gate  *	logvcnt - count of logv[] vector element(s) and the index
980Sstevel@tonic-gate  *	plus 1 of the next logbuf.
990Sstevel@tonic-gate  *
1000Sstevel@tonic-gate  *	log_buf_kmc - the kmem_cache to alloc/free log_buf_t's from/to.
1010Sstevel@tonic-gate  *
1020Sstevel@tonic-gate  *	fio - the global nca_fio_t used to manage file i/o to a logfile.
1030Sstevel@tonic-gate  *
1040Sstevel@tonic-gate  *	dir - path to the directory where the current logfile symlink
1050Sstevel@tonic-gate  *	is created and the default directory for logfile(s).
1060Sstevel@tonic-gate  *
1070Sstevel@tonic-gate  *	symlink - name of the logfile symlink.
1080Sstevel@tonic-gate  *
1090Sstevel@tonic-gate  *	symlink_path - path to the logfile symlink.
1100Sstevel@tonic-gate  *
1110Sstevel@tonic-gate  *	log_lock - the kmutex_t used to guarantee atomic access of
1120Sstevel@tonic-gate  * 	all of the above.
1130Sstevel@tonic-gate  *
1140Sstevel@tonic-gate  *	flush_tid - logit_flush() timeout id.
1150Sstevel@tonic-gate  *
1160Sstevel@tonic-gate  *	LOGBUFV_ALLOC() - macro used to add log_buf_t(s) to logv[].
1170Sstevel@tonic-gate  */
1180Sstevel@tonic-gate 
1190Sstevel@tonic-gate int			nl7c_logbuf_max = 0;
1200Sstevel@tonic-gate static logd_t		logd;
1210Sstevel@tonic-gate static log_buf_t	*log = NULL;
1220Sstevel@tonic-gate static log_buf_t	**logv = NULL;
1230Sstevel@tonic-gate static int		logvcnt = 0;
1240Sstevel@tonic-gate static kmem_cache_t	*log_buf_kmc;
1250Sstevel@tonic-gate static nca_fio_t	fio;
1260Sstevel@tonic-gate static caddr_t		dir = "/var/nca/";
1270Sstevel@tonic-gate static caddr_t		symlink = "current";
1280Sstevel@tonic-gate static caddr_t		symlink_dir = "/var/nca";
1290Sstevel@tonic-gate static caddr_t		symlink_path = "/var/nca/current";
1300Sstevel@tonic-gate 
1310Sstevel@tonic-gate static kmutex_t		log_lock;
1320Sstevel@tonic-gate 
1330Sstevel@tonic-gate static timeout_id_t	flush_tid;
1340Sstevel@tonic-gate 
1350Sstevel@tonic-gate #define	LOGBUFV_ALLOC(kmflag) {						\
1360Sstevel@tonic-gate 	log_buf_t	*_p;						\
1370Sstevel@tonic-gate 									\
1380Sstevel@tonic-gate 	ASSERT(mutex_owned(&log_lock));					\
1390Sstevel@tonic-gate 	while (logvcnt < nl7c_logbuf_max) {				\
1400Sstevel@tonic-gate 		/*CONSTCOND*/						\
1410Sstevel@tonic-gate 		if (kmflag == KM_SLEEP)					\
1420Sstevel@tonic-gate 			mutex_exit(&log_lock);				\
1430Sstevel@tonic-gate 		_p = kmem_cache_alloc(log_buf_kmc, kmflag);		\
1440Sstevel@tonic-gate 		/*CONSTCOND*/						\
1450Sstevel@tonic-gate 		if (kmflag == KM_SLEEP) {				\
1460Sstevel@tonic-gate 			mutex_enter(&log_lock);				\
1470Sstevel@tonic-gate 			if (logvcnt == nl7c_logbuf_max) {		\
1480Sstevel@tonic-gate 				mutex_exit(&log_lock);			\
1490Sstevel@tonic-gate 				kmem_cache_free(log_buf_kmc, _p);	\
1500Sstevel@tonic-gate 				mutex_enter(&log_lock);			\
1510Sstevel@tonic-gate 				break;					\
1520Sstevel@tonic-gate 			}						\
1530Sstevel@tonic-gate 		} else {						\
1540Sstevel@tonic-gate 			if (_p == NULL) {				\
1550Sstevel@tonic-gate 				break;					\
1560Sstevel@tonic-gate 			}						\
1570Sstevel@tonic-gate 		}							\
1580Sstevel@tonic-gate 		logv[logvcnt++] = _p;					\
1590Sstevel@tonic-gate 	}								\
1600Sstevel@tonic-gate }
1610Sstevel@tonic-gate 
1620Sstevel@tonic-gate /*
1630Sstevel@tonic-gate  * Exports for inet/nca/ncaddi.c:
1640Sstevel@tonic-gate  */
1650Sstevel@tonic-gate 
1660Sstevel@tonic-gate nca_fio_t		*nl7c_logd_fio = &fio;
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate static void
log_buf_alloc(int kmflag)1690Sstevel@tonic-gate log_buf_alloc(int kmflag)
1700Sstevel@tonic-gate {
1710Sstevel@tonic-gate 	nca_log_buf_hdr_t	*hdr;
1720Sstevel@tonic-gate 	static	ulong_t		seq = 0;
1730Sstevel@tonic-gate 
1740Sstevel@tonic-gate 	ASSERT(mutex_owned(&log_lock));
1750Sstevel@tonic-gate 
1760Sstevel@tonic-gate 	if (logvcnt == 0) {
1770Sstevel@tonic-gate 		/*
1780Sstevel@tonic-gate 		 * No logv[] to use for the new log global logbuf,
1790Sstevel@tonic-gate 		 * try to allocate one or more before giving up.
1800Sstevel@tonic-gate 		 */
1810Sstevel@tonic-gate 		LOGBUFV_ALLOC(kmflag);
1820Sstevel@tonic-gate 		if (logvcnt == 0) {
1830Sstevel@tonic-gate 			/* No joy, just give up. */
1840Sstevel@tonic-gate 			log = NULL;
1850Sstevel@tonic-gate 			return;
1860Sstevel@tonic-gate 		}
1870Sstevel@tonic-gate 	}
1880Sstevel@tonic-gate 	log = logv[--logvcnt];
1890Sstevel@tonic-gate 
1900Sstevel@tonic-gate 	log->size = NCA_DEFAULT_LOG_BUF_SIZE;
1910Sstevel@tonic-gate 	log->cur_pos = sizeof (*hdr);
1920Sstevel@tonic-gate 
1930Sstevel@tonic-gate 	hdr = (nca_log_buf_hdr_t *)&log->buffer;
1940Sstevel@tonic-gate 	hdr->nca_loghdr.nca_version = NCA_LOG_VERSION1;
1950Sstevel@tonic-gate 	hdr->nca_loghdr.nca_op = log_op;
1960Sstevel@tonic-gate 	hdr->nca_logstats.n_log_size = NCA_DEFAULT_LOG_BUF_SIZE - sizeof (*hdr);
1970Sstevel@tonic-gate 	hdr->nca_logstats.n_log_recs = 0;
1980Sstevel@tonic-gate 	hdr->nca_logstats.n_log_upcall = seq++;
1990Sstevel@tonic-gate 
2000Sstevel@tonic-gate 	/* Try to allocate for at least the one we just used */
2010Sstevel@tonic-gate 	LOGBUFV_ALLOC(kmflag);
2020Sstevel@tonic-gate }
2030Sstevel@tonic-gate 
2040Sstevel@tonic-gate static void
logd_off()2050Sstevel@tonic-gate logd_off()
2060Sstevel@tonic-gate {
2070Sstevel@tonic-gate 	;
2080Sstevel@tonic-gate }
2090Sstevel@tonic-gate 
2100Sstevel@tonic-gate static void
logd_log_write(kmutex_t * lock,log_buf_t * lbp)2110Sstevel@tonic-gate logd_log_write(kmutex_t *lock, log_buf_t *lbp)
2120Sstevel@tonic-gate {
2130Sstevel@tonic-gate 	nca_log_buf_hdr_t *hdr = (nca_log_buf_hdr_t *)lbp->buffer;
2140Sstevel@tonic-gate 	nca_log_stat_t	*sts = &hdr->nca_logstats;
2150Sstevel@tonic-gate 	int		size = sts->n_log_size + sizeof (*hdr);
2160Sstevel@tonic-gate 	vnode_t		*vp;
2170Sstevel@tonic-gate 	uio_t		uio;
2180Sstevel@tonic-gate 	iovec_t		iov;
2190Sstevel@tonic-gate 	int		ret;
2200Sstevel@tonic-gate 	boolean_t	noretry = B_FALSE;
2210Sstevel@tonic-gate 	vattr_t		attr;
2220Sstevel@tonic-gate 
2230Sstevel@tonic-gate 	if (size & (DEV_BSIZE - 1)) {
2240Sstevel@tonic-gate 		/*
2250Sstevel@tonic-gate 		 * Not appropriately sized for directio(),
2260Sstevel@tonic-gate 		 * add some filler so it is.
2270Sstevel@tonic-gate 		 */
2280Sstevel@tonic-gate 		sts->n_log_size += DEV_BSIZE - (size & (DEV_BSIZE - 1));
2290Sstevel@tonic-gate 		size = sts->n_log_size + sizeof (*hdr);
2300Sstevel@tonic-gate 	}
2310Sstevel@tonic-gate retry:
2320Sstevel@tonic-gate 	if (nca_fio_offset(&fio) + size <= nca_fio_size(&fio)) {
2330Sstevel@tonic-gate 		/*
2340Sstevel@tonic-gate 		 * Room in the current log file so write the logbuf out,
2350Sstevel@tonic-gate 		 * exit the logd lock while doing the i/o as to not block
2360Sstevel@tonic-gate 		 * queuing.
2370Sstevel@tonic-gate 		 */
2380Sstevel@tonic-gate 		mutex_exit(lock);
2390Sstevel@tonic-gate 
2400Sstevel@tonic-gate 		vp = nca_fio_vp(&fio);
2410Sstevel@tonic-gate 		(void) VOP_RWLOCK(vp, V_WRITELOCK_TRUE, NULL);
2420Sstevel@tonic-gate 		iov.iov_base = lbp->buffer;
2430Sstevel@tonic-gate 		iov.iov_len = size;
2440Sstevel@tonic-gate 		uio.uio_iov = &iov;
2450Sstevel@tonic-gate 		uio.uio_iovcnt = 1;
2460Sstevel@tonic-gate 		uio.uio_segflg = UIO_SYSSPACE;
2470Sstevel@tonic-gate 		uio.uio_fmode = 0;
2480Sstevel@tonic-gate 		uio.uio_loffset = (u_offset_t)nca_fio_offset(&fio);
2490Sstevel@tonic-gate 		uio.uio_llimit = curproc->p_fsz_ctl;
2500Sstevel@tonic-gate 		uio.uio_resid = size;
2510Sstevel@tonic-gate 		ret = VOP_WRITE(vp, &uio, 0, kcred, NULL);
2520Sstevel@tonic-gate 		VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL);
2530Sstevel@tonic-gate 		if (ret != 0) {
2540Sstevel@tonic-gate 			if (ret == EFBIG) {
2550Sstevel@tonic-gate 				/*
2560Sstevel@tonic-gate 				 * Out of space for this file,
2570Sstevel@tonic-gate 				 * retry with the next.
2580Sstevel@tonic-gate 				 */
2590Sstevel@tonic-gate 				nca_fio_size(&fio) = nca_fio_offset(&fio);
2600Sstevel@tonic-gate 				if (noretry) {
2610Sstevel@tonic-gate 					nl7c_logd_enabled = B_FALSE;
2620Sstevel@tonic-gate 					goto done;
2630Sstevel@tonic-gate 				} else
2640Sstevel@tonic-gate 					goto next;
2650Sstevel@tonic-gate 			}
2660Sstevel@tonic-gate 		}
2670Sstevel@tonic-gate 		nca_fio_offset(&fio) = uio.uio_loffset;
2680Sstevel@tonic-gate 
2690Sstevel@tonic-gate 		mutex_enter(lock);
2700Sstevel@tonic-gate 		goto done;
2710Sstevel@tonic-gate 	}
2720Sstevel@tonic-gate 
2730Sstevel@tonic-gate 	/*
2740Sstevel@tonic-gate 	 * Current logfile doesn't have sufficient space
2750Sstevel@tonic-gate 	 * so move on to next file (if any).
2760Sstevel@tonic-gate 	 */
2770Sstevel@tonic-gate next:
2780Sstevel@tonic-gate 	mutex_exit(lock);
2790Sstevel@tonic-gate 	/* Close current file */
2800Sstevel@tonic-gate 	ret = VOP_CLOSE(nca_fio_vp(&fio), FCREAT|FWRITE|FAPPEND|FTRUNC,
281*5331Samw 			1, (offset_t)0, kcred, NULL);
2820Sstevel@tonic-gate 	nca_fio_vp(&fio) = NULL;
2830Sstevel@tonic-gate 	if (ret) {
2840Sstevel@tonic-gate 		cmn_err(CE_WARN, "nl7c_logd: close of %s failed (error %d)",
2850Sstevel@tonic-gate 		    nca_fio_name(&fio), ret);
2860Sstevel@tonic-gate 		nl7c_logd_enabled = B_FALSE;
2870Sstevel@tonic-gate 		logd_off();
2880Sstevel@tonic-gate 		return;
2890Sstevel@tonic-gate 	}
2900Sstevel@tonic-gate 
2910Sstevel@tonic-gate 	/* Go to next file */
2920Sstevel@tonic-gate 	nca_fio_ix(&fio)++;
2930Sstevel@tonic-gate 	if (nca_fio_ix(&fio) == nca_fio_cnt(&fio)) {
2940Sstevel@tonic-gate 		/*
2950Sstevel@tonic-gate 		 * We have reached the last file. If cycling
2960Sstevel@tonic-gate 		 * is not on, disable logging and bailout.
2970Sstevel@tonic-gate 		 */
2980Sstevel@tonic-gate 		if (nl7c_logd_cycle) {
2990Sstevel@tonic-gate 			/* Start from the first file */
3000Sstevel@tonic-gate 			nca_fio_ix(&fio) = 0;
3010Sstevel@tonic-gate 		} else {
3020Sstevel@tonic-gate 			nca_fio_ix(&fio)--;
3030Sstevel@tonic-gate 			nl7c_logd_enabled = B_FALSE;
3040Sstevel@tonic-gate 			logd_off();
3050Sstevel@tonic-gate 			return;
3060Sstevel@tonic-gate 		}
3070Sstevel@tonic-gate 	}
3080Sstevel@tonic-gate 
3090Sstevel@tonic-gate 	/* Open the next log file */
3100Sstevel@tonic-gate 	ret = vn_open(nca_fio_name(&fio), UIO_SYSSPACE, FCREAT|FWRITE|FTRUNC,
3110Sstevel@tonic-gate 			0600, &nca_fio_vp(&fio), 0, 0);
3120Sstevel@tonic-gate 	if (ret) {
3130Sstevel@tonic-gate 		cmn_err(CE_WARN, "nl7c_logd: vn_open of %s failed (error %d)",
3140Sstevel@tonic-gate 			nca_fio_name(&fio), ret);
3150Sstevel@tonic-gate 		nl7c_logd_enabled = B_FALSE;
3160Sstevel@tonic-gate 		logd_off();
3170Sstevel@tonic-gate 		return;
3180Sstevel@tonic-gate 	}
3190Sstevel@tonic-gate 
3200Sstevel@tonic-gate 	/* Turn on directio */
3210Sstevel@tonic-gate 	(void) VOP_IOCTL(nca_fio_vp(&fio), _FIODIRECTIO,
322*5331Samw 			DIRECTIO_ON, 0, kcred, NULL, NULL);
3230Sstevel@tonic-gate 
3240Sstevel@tonic-gate 	/* Start writing from the begining of the file */
3250Sstevel@tonic-gate 	nca_fio_offset(&fio) = 0;
3260Sstevel@tonic-gate 
3270Sstevel@tonic-gate 	/* Remove the current symlink */
328*5331Samw 	(void) VOP_REMOVE(nca_fio_dvp(&fio), symlink, kcred, NULL, 0);
3290Sstevel@tonic-gate 
3300Sstevel@tonic-gate 	attr.va_mask = AT_MODE | AT_TYPE;
3310Sstevel@tonic-gate 	attr.va_mode = 0777;
3320Sstevel@tonic-gate 	attr.va_type = VLNK;
3330Sstevel@tonic-gate 
3340Sstevel@tonic-gate 	/* Create symlink to the new log file */
3350Sstevel@tonic-gate 	ret = VOP_SYMLINK(nca_fio_dvp(&fio), symlink,
336*5331Samw 			&attr, nca_fio_name(&fio), kcred, NULL, 0);
3370Sstevel@tonic-gate 	if (ret) {
3380Sstevel@tonic-gate 		cmn_err(CE_WARN, "nl7c_logd: symlink of %s to %s failed",
3390Sstevel@tonic-gate 			symlink, nca_fio_name(&fio));
3400Sstevel@tonic-gate 		nl7c_logd_enabled = B_FALSE;
3410Sstevel@tonic-gate 		logd_off();
3420Sstevel@tonic-gate 		return;
3430Sstevel@tonic-gate 	}
3440Sstevel@tonic-gate 	mutex_enter(lock);
3450Sstevel@tonic-gate 	goto retry;
3460Sstevel@tonic-gate 
3470Sstevel@tonic-gate done:
3480Sstevel@tonic-gate 	if (logvcnt < nl7c_logbuf_max) {
3490Sstevel@tonic-gate 		/* May need to allocate some logbuf(s) for logv[] */
3500Sstevel@tonic-gate 		mutex_enter(&log_lock);
3510Sstevel@tonic-gate 		if (logvcnt < nl7c_logbuf_max) {
3520Sstevel@tonic-gate 			/*
3530Sstevel@tonic-gate 			 * After acquiring the lock still need logbuf(s),
3540Sstevel@tonic-gate 			 * if the global logbuf pointer is NULL then call
3550Sstevel@tonic-gate 			 * log_buf_alloc() as it will fill up logbugv[]
3560Sstevel@tonic-gate 			 * and initialize a new logbuf else fill up just
3570Sstevel@tonic-gate 			 * the logv[] here.
3580Sstevel@tonic-gate 			 */
3590Sstevel@tonic-gate 			if (log == NULL) {
3600Sstevel@tonic-gate 				log_buf_alloc(KM_SLEEP);
3610Sstevel@tonic-gate 			} else {
3620Sstevel@tonic-gate 				/*LINTED*/
3630Sstevel@tonic-gate 				LOGBUFV_ALLOC(KM_SLEEP);
3640Sstevel@tonic-gate 			}
3650Sstevel@tonic-gate 		}
3660Sstevel@tonic-gate 		mutex_exit(&log_lock);
3670Sstevel@tonic-gate 	}
3680Sstevel@tonic-gate }
3690Sstevel@tonic-gate 
3700Sstevel@tonic-gate static void
logd_worker(logd_t * logdp)3710Sstevel@tonic-gate logd_worker(logd_t *logdp)
3720Sstevel@tonic-gate {
3730Sstevel@tonic-gate 	log_buf_t	*lbp;
3740Sstevel@tonic-gate 	kmutex_t	*lock = &logdp->lock;
3750Sstevel@tonic-gate 	kcondvar_t	*wait = &logdp->wait;
3760Sstevel@tonic-gate 	callb_cpr_t	cprinfo;
3770Sstevel@tonic-gate 
3780Sstevel@tonic-gate 	CALLB_CPR_INIT(&cprinfo, lock, callb_generic_cpr, "nl7c");
3790Sstevel@tonic-gate 	mutex_enter(lock);
3800Sstevel@tonic-gate 
3810Sstevel@tonic-gate 	for (;;) {
3820Sstevel@tonic-gate 		/* Wait for something to do */
3830Sstevel@tonic-gate 		while ((lbp = logdp->head) == NULL) {
3840Sstevel@tonic-gate 			CALLB_CPR_SAFE_BEGIN(&cprinfo);
3850Sstevel@tonic-gate 			cv_wait(wait, lock);
3860Sstevel@tonic-gate 			CALLB_CPR_SAFE_END(&cprinfo, lock);
3870Sstevel@tonic-gate 		}
3880Sstevel@tonic-gate 		if ((logdp->head = lbp->next) == NULL)
3890Sstevel@tonic-gate 			logdp->tail = NULL;
3900Sstevel@tonic-gate 		/* Got a logbuf to write out */
3910Sstevel@tonic-gate 		if (nl7c_logd_enabled)
3920Sstevel@tonic-gate 			logd_log_write(lock, lbp);
3930Sstevel@tonic-gate 		kmem_cache_free(log_buf_kmc, lbp);
3940Sstevel@tonic-gate 	}
3950Sstevel@tonic-gate }
3960Sstevel@tonic-gate 
3970Sstevel@tonic-gate boolean_t
nl7c_logd_init(int fsz,caddr_t * fnv)3980Sstevel@tonic-gate nl7c_logd_init(int fsz, caddr_t *fnv)
3990Sstevel@tonic-gate {
4000Sstevel@tonic-gate 	vnode_t	*dvp;
4010Sstevel@tonic-gate 	vnode_t	*svp;
4020Sstevel@tonic-gate 	vnode_t	*vp;
4030Sstevel@tonic-gate 	int	ret;
4040Sstevel@tonic-gate 	caddr_t	*fnp;
4050Sstevel@tonic-gate 	vattr_t	attr;
4060Sstevel@tonic-gate 	uio_t	uio;
4070Sstevel@tonic-gate 	iovec_t	iov;
4080Sstevel@tonic-gate 	char	fbuf[TYPICALMAXPATHLEN + 1];
4090Sstevel@tonic-gate 
4100Sstevel@tonic-gate 	/*
4110Sstevel@tonic-gate 	 * Initialize the global logfio.
4120Sstevel@tonic-gate 	 */
4130Sstevel@tonic-gate 	nca_fio_cnt(&fio) = 0;
4140Sstevel@tonic-gate 	nca_fio_ix(&fio) = 0;
4150Sstevel@tonic-gate 	fnp = fnv;
4160Sstevel@tonic-gate 	while (*fnp != NULL) {
4170Sstevel@tonic-gate 		nca_fio_cnt(&fio)++;
4180Sstevel@tonic-gate 		nca_fio_name(&fio) = *fnp;
4190Sstevel@tonic-gate 		nca_fio_size(&fio) = fsz;
4200Sstevel@tonic-gate 		nca_fio_offset(&fio) = 0;
4210Sstevel@tonic-gate 		nca_fio_file(&fio) = nca_fio_ix(&fio);
4220Sstevel@tonic-gate 		nca_fio_vp(&fio) = NULL;
4230Sstevel@tonic-gate 
4240Sstevel@tonic-gate 		if (++fnp == &fnv[NCA_FIOV_SZ])
4250Sstevel@tonic-gate 			break;
4260Sstevel@tonic-gate 
4270Sstevel@tonic-gate 		nca_fio_ix(&fio)++;
4280Sstevel@tonic-gate 	}
4290Sstevel@tonic-gate 	/*
4300Sstevel@tonic-gate 	 * See if we can start logging from where we left off last time,
4310Sstevel@tonic-gate 	 * first check if the symlink exists.
4320Sstevel@tonic-gate 	 */
4330Sstevel@tonic-gate 	dvp = NULL;
4340Sstevel@tonic-gate 	ret = lookupname(symlink_path, UIO_SYSSPACE, NO_FOLLOW, &dvp, &svp);
4350Sstevel@tonic-gate 	if (ret || dvp == NULL || svp == NULL) {
4360Sstevel@tonic-gate 		if (dvp == NULL) {
4370Sstevel@tonic-gate 			/* No NCA symlink directory, create one */
4380Sstevel@tonic-gate 			attr.va_mask = AT_MODE | AT_TYPE;
4390Sstevel@tonic-gate 			attr.va_mode = 0755;
4400Sstevel@tonic-gate 			attr.va_type = VDIR;
4410Sstevel@tonic-gate 			ret = vn_create(symlink_dir, UIO_SYSSPACE, &attr,
4420Sstevel@tonic-gate 			    EXCL, 0, &dvp, CRMKDIR, 0, 0);
4430Sstevel@tonic-gate 			if (ret) {
4440Sstevel@tonic-gate 				cmn_err(CE_WARN, "nl7c_logd_init: create"
4450Sstevel@tonic-gate 				    " symlink dir of %s failed(%d).",
4460Sstevel@tonic-gate 				    symlink_dir, ret);
4470Sstevel@tonic-gate 				goto error;
4480Sstevel@tonic-gate 			}
4490Sstevel@tonic-gate 		}
4504155Sfr80241 		nca_fio_dvp(&fio) = dvp;
4510Sstevel@tonic-gate 		/* No symlink so don't know were to start from */
4520Sstevel@tonic-gate 		goto fresh_start;
4530Sstevel@tonic-gate 	}
4540Sstevel@tonic-gate 	/* Save the symlink dir vnode */
4550Sstevel@tonic-gate 	nca_fio_dvp(&fio) = dvp;
4560Sstevel@tonic-gate 
4570Sstevel@tonic-gate 	/* Check if the file pointed by the symlink exists */
4580Sstevel@tonic-gate 	ret = lookupname(symlink_path, UIO_SYSSPACE, FOLLOW, NULLVPP, &vp);
4590Sstevel@tonic-gate 	if (ret || vp == NULL)
4600Sstevel@tonic-gate 		goto fresh_start;
4610Sstevel@tonic-gate 	VN_RELE(vp);
4620Sstevel@tonic-gate 
4630Sstevel@tonic-gate 	/* Read the symlink and find it in fnv[], else fresh start */
4640Sstevel@tonic-gate 	iov.iov_len = TYPICALMAXPATHLEN;
4650Sstevel@tonic-gate 	iov.iov_base = fbuf;
4660Sstevel@tonic-gate 	uio.uio_iov = &iov;
4670Sstevel@tonic-gate 	uio.uio_iovcnt = 1;
4680Sstevel@tonic-gate 	uio.uio_resid = iov.iov_len;
4690Sstevel@tonic-gate 	uio.uio_segflg = UIO_SYSSPACE;
4700Sstevel@tonic-gate 	uio.uio_loffset = 0;
4710Sstevel@tonic-gate 	uio.uio_fmode = 0;
472*5331Samw 	ret = VOP_READLINK(svp, &uio, kcred, NULL);
4730Sstevel@tonic-gate 	if (ret) {
474*5331Samw 		(void) VOP_REMOVE(dvp, symlink, kcred, NULL, 0);
4750Sstevel@tonic-gate 		goto fresh_start;
4760Sstevel@tonic-gate 	}
4770Sstevel@tonic-gate 
4780Sstevel@tonic-gate 	/* Null terminate the buf */
4790Sstevel@tonic-gate 	fbuf[TYPICALMAXPATHLEN - (int)uio.uio_resid] = '\0';
4800Sstevel@tonic-gate 	fnp = fnv;
4810Sstevel@tonic-gate 	nca_fio_ix(&fio) = 0;
4820Sstevel@tonic-gate 	while (*fnp != NULL) {
4830Sstevel@tonic-gate 		if (strcmp(*fnp, fbuf) == 0)
4840Sstevel@tonic-gate 			break;
4850Sstevel@tonic-gate 		if (++fnp == &fnv[NCA_FIOV_SZ])
4860Sstevel@tonic-gate 			goto fresh_start;
4870Sstevel@tonic-gate 		nca_fio_ix(&fio)++;
4880Sstevel@tonic-gate 	}
4890Sstevel@tonic-gate 	if (*fnp == NULL)
4900Sstevel@tonic-gate 		goto fresh_start;
4910Sstevel@tonic-gate 
4920Sstevel@tonic-gate 	/* Start writing to the end of the file */
4930Sstevel@tonic-gate 	ret = vn_open(*fnp, UIO_SYSSPACE,
4940Sstevel@tonic-gate 	    FCREAT|FWRITE|FAPPEND, 0600, &vp, 0, 0);
4950Sstevel@tonic-gate 	if (ret) {
4960Sstevel@tonic-gate 		cmn_err(CE_WARN, "nl7c_logd_init: vn_open of "
4970Sstevel@tonic-gate 		    "%s failed (error %d)", *fnp, ret);
4980Sstevel@tonic-gate 		goto error;
4990Sstevel@tonic-gate 	}
5000Sstevel@tonic-gate 	nca_fio_vp(&fio) = vp;
501*5331Samw 	(void) VOP_IOCTL(vp, _FIODIRECTIO, DIRECTIO_ON, 0, kcred, NULL, NULL);
5020Sstevel@tonic-gate 	attr.va_mask = AT_SIZE;
503*5331Samw 	ret = VOP_GETATTR(nca_fio_vp(&fio), &attr, 0, NULL, NULL);
5040Sstevel@tonic-gate 	if (ret) {
5050Sstevel@tonic-gate 		cmn_err(CE_WARN, "nl7c_logd_init: getattr of %s failed", *fnp);
5060Sstevel@tonic-gate 		goto error;
5070Sstevel@tonic-gate 	}
5080Sstevel@tonic-gate 	nca_fio_offset(&fio) = (off64_t)attr.va_size;
5090Sstevel@tonic-gate 
5100Sstevel@tonic-gate 	goto finish;
5110Sstevel@tonic-gate 
5120Sstevel@tonic-gate fresh_start:
5130Sstevel@tonic-gate 	/*
5140Sstevel@tonic-gate 	 * Here if no previous logging environment found or if the previous
5150Sstevel@tonic-gate 	 * logging environment isn't usable or isn't consistent with the new
5160Sstevel@tonic-gate 	 * fnv[]. Remove the existing symlink (if any) then create the new
5170Sstevel@tonic-gate 	 * symlink to point to the first logfile.
5180Sstevel@tonic-gate 	 */
5190Sstevel@tonic-gate 	nca_fio_ix(&fio) = 0;
5200Sstevel@tonic-gate 	attr.va_mask = AT_MODE | AT_TYPE;
5210Sstevel@tonic-gate 	attr.va_mode = 0777;
5220Sstevel@tonic-gate 	attr.va_type = VLNK;
523*5331Samw 	(void) VOP_REMOVE(dvp, symlink, kcred, NULL, 0);
524*5331Samw 	ret = VOP_SYMLINK(dvp, symlink, &attr, nca_fio_name(&fio), kcred, NULL,
525*5331Samw 	    0);
5260Sstevel@tonic-gate 	if (ret) {
5270Sstevel@tonic-gate 		cmn_err(CE_WARN, "nl7c_logd_init: symlink of %s to %s failed",
5280Sstevel@tonic-gate 		    symlink_path, nca_fio_name(&fio));
5290Sstevel@tonic-gate 		goto error;
5300Sstevel@tonic-gate 	}
5310Sstevel@tonic-gate 	ret = vn_open(nca_fio_name(&fio), UIO_SYSSPACE,
5320Sstevel@tonic-gate 	    FCREAT|FWRITE|FTRUNC, 0600, &nca_fio_vp(&fio), 0, 0);
5330Sstevel@tonic-gate 	if (ret) {
5340Sstevel@tonic-gate 		cmn_err(CE_WARN, "nl7c_logd_init: vn_open of "
5350Sstevel@tonic-gate 		    "%s failed (error %d)", nca_fio_name(&fio), ret);
5360Sstevel@tonic-gate 		goto error;
5370Sstevel@tonic-gate 	}
5380Sstevel@tonic-gate 
5390Sstevel@tonic-gate 	/* Turn on directio */
5400Sstevel@tonic-gate 	(void) VOP_IOCTL(nca_fio_vp(&fio), _FIODIRECTIO,
541*5331Samw 			DIRECTIO_ON, 0, kcred, NULL, NULL);
5420Sstevel@tonic-gate 
5430Sstevel@tonic-gate finish:
5440Sstevel@tonic-gate 	log_buf_kmc = kmem_cache_create("NL7C_log_buf_kmc", sizeof (log_buf_t),
5450Sstevel@tonic-gate 		0, NULL, NULL, NULL, NULL, NULL, 0);
5460Sstevel@tonic-gate 
5470Sstevel@tonic-gate 	mutex_init(&log_lock, NULL, MUTEX_DEFAULT, NULL);
5480Sstevel@tonic-gate 	mutex_enter(&log_lock);
5490Sstevel@tonic-gate 
5500Sstevel@tonic-gate 	if (nl7c_logbuf_max == 0)
5510Sstevel@tonic-gate 		nl7c_logbuf_max = max_ncpus;
5520Sstevel@tonic-gate 	logv = kmem_alloc(nl7c_logbuf_max * sizeof (*logv), KM_SLEEP);
5530Sstevel@tonic-gate 	for (logvcnt = 0; logvcnt < nl7c_logbuf_max; logvcnt++) {
5540Sstevel@tonic-gate 		logv[logvcnt] = kmem_cache_alloc(log_buf_kmc, KM_SLEEP);
5550Sstevel@tonic-gate 	}
5560Sstevel@tonic-gate 
5570Sstevel@tonic-gate 	log_buf_alloc(KM_SLEEP);
5580Sstevel@tonic-gate 
5590Sstevel@tonic-gate 	mutex_init(&logd.lock, NULL, MUTEX_DEFAULT, NULL);
5600Sstevel@tonic-gate 	cv_init(&logd.wait, NULL, CV_DEFAULT, NULL);
5610Sstevel@tonic-gate 	logd.head = NULL;
5620Sstevel@tonic-gate 	logd.tail = NULL;
5630Sstevel@tonic-gate 	logd.worker = thread_create(NULL, 0, logd_worker, &logd,
5640Sstevel@tonic-gate 	    0, &p0, TS_RUN, maxclsyspri);
5650Sstevel@tonic-gate 
5660Sstevel@tonic-gate 	mutex_exit(&log_lock);
5670Sstevel@tonic-gate 
5680Sstevel@tonic-gate 	/* Last, start logger timeout flush */
5690Sstevel@tonic-gate 	logit_flush(NULL);
5700Sstevel@tonic-gate 
5710Sstevel@tonic-gate 	return (B_TRUE);
5720Sstevel@tonic-gate 
5730Sstevel@tonic-gate 	/*
5740Sstevel@tonic-gate 	 * Error of some sort, free any resources in reverse order.
5750Sstevel@tonic-gate 	 */
5760Sstevel@tonic-gate error:
5770Sstevel@tonic-gate 	nca_fio_ix(&fio) = 0;
5780Sstevel@tonic-gate 	while (nca_fio_ix(&fio) < nca_fio_cnt(&fio)) {
5790Sstevel@tonic-gate 		char *name = nca_fio_name(&fio);
5800Sstevel@tonic-gate 
5810Sstevel@tonic-gate 		if ((vp = nca_fio_vp(&fio)) != NULL)
5820Sstevel@tonic-gate 			VN_RELE(vp);
5835145Sgeorges 		kmem_free(name, (strlen(name) + 1));
5840Sstevel@tonic-gate 		nca_fio_ix(&fio)++;
5850Sstevel@tonic-gate 	}
5860Sstevel@tonic-gate 	nca_fio_cnt(&fio) = 0;
5870Sstevel@tonic-gate 
5880Sstevel@tonic-gate 	if (svp)
5890Sstevel@tonic-gate 		VN_RELE(svp);
5900Sstevel@tonic-gate 
5910Sstevel@tonic-gate 	if (dvp)
5920Sstevel@tonic-gate 		VN_RELE(dvp);
5930Sstevel@tonic-gate 
5940Sstevel@tonic-gate 	return (B_FALSE);
5950Sstevel@tonic-gate }
5960Sstevel@tonic-gate 
5970Sstevel@tonic-gate /*ARGSUSED*/
5980Sstevel@tonic-gate static void
logit_flush(void * arg)5990Sstevel@tonic-gate logit_flush(void *arg)
6000Sstevel@tonic-gate {
6010Sstevel@tonic-gate 	static log_buf_t *lastlbp = NULL;
6020Sstevel@tonic-gate 	static int	lastpos;
6030Sstevel@tonic-gate 	log_buf_t	*lbp = log;
6040Sstevel@tonic-gate 
6050Sstevel@tonic-gate 	flush_tid = 0;
6060Sstevel@tonic-gate 
6070Sstevel@tonic-gate 	mutex_enter(&log_lock);
6080Sstevel@tonic-gate 	if (log == NULL) {
6090Sstevel@tonic-gate 		/* No global logbuf ? Nothing to flush. */
6100Sstevel@tonic-gate 		goto out;
6110Sstevel@tonic-gate 	}
6120Sstevel@tonic-gate 	if (lbp != NULL && lbp->cur_pos > (sizeof (nca_log_buf_hdr_t)) &&
6130Sstevel@tonic-gate 		lastlbp == lbp && lastpos == lbp->cur_pos) {
6140Sstevel@tonic-gate 		/*
6150Sstevel@tonic-gate 		 * We have a logbuf and it has log data and it's the
6160Sstevel@tonic-gate 		 * same logbuf and pos as last time and after lock
6170Sstevel@tonic-gate 		 * still true, so flush.
6180Sstevel@tonic-gate 		 */
6190Sstevel@tonic-gate 		nca_log_stat_t	*sp;
6200Sstevel@tonic-gate 
6210Sstevel@tonic-gate 		sp = &(((nca_log_buf_hdr_t *)lbp)->nca_logstats);
6220Sstevel@tonic-gate 		sp->n_log_size = lbp->cur_pos;
6230Sstevel@tonic-gate 
6240Sstevel@tonic-gate 		/* Link new logbuf onto end of logd and wake logd up */
6250Sstevel@tonic-gate 		mutex_enter(&logd.lock);
6260Sstevel@tonic-gate 		log->next = NULL;
6270Sstevel@tonic-gate 		if (logd.tail == NULL)
6280Sstevel@tonic-gate 			logd.head = log;
6290Sstevel@tonic-gate 		else
6300Sstevel@tonic-gate 			logd.tail->next = log;
6310Sstevel@tonic-gate 		logd.tail = log;
6320Sstevel@tonic-gate 		cv_signal(&logd.wait);
6330Sstevel@tonic-gate 
6340Sstevel@tonic-gate 		mutex_exit(&logd.lock);
6350Sstevel@tonic-gate 
6360Sstevel@tonic-gate 		log_buf_alloc(KM_NOSLEEP);
6370Sstevel@tonic-gate 	}
6380Sstevel@tonic-gate 
6390Sstevel@tonic-gate 	if ((lastlbp = lbp) != NULL)
6400Sstevel@tonic-gate 		lastpos = lbp->cur_pos;
6410Sstevel@tonic-gate 
6420Sstevel@tonic-gate 	mutex_exit(&log_lock);
6430Sstevel@tonic-gate out:
6440Sstevel@tonic-gate 	/* Check again in 1 second */
6450Sstevel@tonic-gate 	flush_tid = timeout(&logit_flush, NULL, hz);
6460Sstevel@tonic-gate }
6470Sstevel@tonic-gate 
6480Sstevel@tonic-gate void
nl7c_logd_log(uri_desc_t * quri,uri_desc_t * suri,time_t rtime,ipaddr_t faddr)6490Sstevel@tonic-gate nl7c_logd_log(uri_desc_t *quri, uri_desc_t *suri, time_t rtime, ipaddr_t faddr)
6500Sstevel@tonic-gate {
6510Sstevel@tonic-gate 	nca_request_log_t *req;
6520Sstevel@tonic-gate 	char		*wp;
6530Sstevel@tonic-gate 	char		*pep;
6540Sstevel@tonic-gate 	int		sz;
6550Sstevel@tonic-gate 	uint32_t	off = 0;
6560Sstevel@tonic-gate 	int		kmflag = servicing_interrupt() ? KM_NOSLEEP : KM_SLEEP;
6570Sstevel@tonic-gate 
6580Sstevel@tonic-gate 	if (! nl7c_logd_enabled)
6590Sstevel@tonic-gate 		return;
6600Sstevel@tonic-gate 
6610Sstevel@tonic-gate 	if (! nl7c_logd_started) {
6620Sstevel@tonic-gate 		/* Startup logging */
6630Sstevel@tonic-gate 		nl7clogd_startup();
6640Sstevel@tonic-gate 	}
6650Sstevel@tonic-gate 	mutex_enter(&log_lock);
6660Sstevel@tonic-gate again:
6670Sstevel@tonic-gate 	if (log == NULL) {
6680Sstevel@tonic-gate 		/* No global logbuf, try to allocate one before giving up. */
6690Sstevel@tonic-gate 		log_buf_alloc(kmflag);
6700Sstevel@tonic-gate 		if (log == NULL) {
6710Sstevel@tonic-gate 			/* No joy, just give up. */
6720Sstevel@tonic-gate 			mutex_exit(&log_lock);
6730Sstevel@tonic-gate 			return;
6740Sstevel@tonic-gate 		}
6750Sstevel@tonic-gate 	}
6760Sstevel@tonic-gate 	/*
6770Sstevel@tonic-gate 	 * Get a pointer to an aligned write position, a pointer to past
6780Sstevel@tonic-gate 	 * the end of the logbuf, and a pointer to the request header.
6790Sstevel@tonic-gate 	 *
6800Sstevel@tonic-gate 	 * As the request header is filled in field by field addtional
6810Sstevel@tonic-gate 	 * storage is allcated following the request header.
6820Sstevel@tonic-gate 	 *
6830Sstevel@tonic-gate 	 * If at any point an allocation from the logbuf overflows (i.e.
6840Sstevel@tonic-gate 	 * resulting in a pointer > pep) the current request logging is
6850Sstevel@tonic-gate 	 * aborted, the current logbuf is posted for write, a new logbuf
6860Sstevel@tonic-gate 	 * is allocated, and start all over.
6870Sstevel@tonic-gate 	 */
6880Sstevel@tonic-gate 	pep = &((char *)log)[log->size];
6890Sstevel@tonic-gate 	wp = (log->buffer + log->cur_pos);
6900Sstevel@tonic-gate 	wp = NCA_LOG_ALIGN(wp);
6910Sstevel@tonic-gate 	req = (nca_request_log_t *)wp;
6920Sstevel@tonic-gate 	if ((wp + sizeof (*req)) >= pep) goto full;
6930Sstevel@tonic-gate 	bzero(wp, sizeof (*req));
6940Sstevel@tonic-gate 	wp += sizeof (*req);
6950Sstevel@tonic-gate 
6960Sstevel@tonic-gate 	sz = MIN((quri->path.ep - quri->path.cp), MAX_URL_LEN);
6970Sstevel@tonic-gate 	if ((wp + sz + 1) >= pep) goto full;
6980Sstevel@tonic-gate 	bcopy(quri->path.cp, wp, sz);
6990Sstevel@tonic-gate 	wp += sz;
7000Sstevel@tonic-gate 	*wp++ = 0;
7010Sstevel@tonic-gate 	sz++;
7020Sstevel@tonic-gate 	req->request_url_len = sz;
7030Sstevel@tonic-gate 	req->request_url = off;
7040Sstevel@tonic-gate 	off += sz;
7050Sstevel@tonic-gate 
7060Sstevel@tonic-gate 	/*
7070Sstevel@tonic-gate 	 * Set response length now as the scheme log function will
7080Sstevel@tonic-gate 	 * subtract out any header length as we want the entity body
7090Sstevel@tonic-gate 	 * length returned for the response_len.
7100Sstevel@tonic-gate 	 */
7110Sstevel@tonic-gate 	req->response_len = (uint_t)suri->resplen;
7120Sstevel@tonic-gate 
7130Sstevel@tonic-gate 	/* Call scheme log */
7140Sstevel@tonic-gate 	if (nl7c_http_log(quri, suri, req, &wp, &pep, &off)) goto full;
7150Sstevel@tonic-gate 
7160Sstevel@tonic-gate 	/* Update logbuf */
7170Sstevel@tonic-gate 	log->cur_pos = (wp - log->buffer);
7180Sstevel@tonic-gate 
7190Sstevel@tonic-gate 	req->response_status = HS_OK;
7200Sstevel@tonic-gate 
7210Sstevel@tonic-gate 	req->start_process_time = (time32_t)rtime;
7220Sstevel@tonic-gate 	req->end_process_time = (time32_t)gethrestime_sec();
7230Sstevel@tonic-gate 
7240Sstevel@tonic-gate 	req->remote_host = faddr;
7250Sstevel@tonic-gate 
7260Sstevel@tonic-gate 	((nca_log_buf_hdr_t *)log)->nca_logstats.n_log_recs++;
7270Sstevel@tonic-gate 	mutex_exit(&log_lock);
7280Sstevel@tonic-gate 	return;
7290Sstevel@tonic-gate 
7300Sstevel@tonic-gate full:
7310Sstevel@tonic-gate 	/*
7320Sstevel@tonic-gate 	 * The logbuf is full, zero fill from current
7330Sstevel@tonic-gate 	 * write pointer through the end of the buf.
7340Sstevel@tonic-gate 	 */
7350Sstevel@tonic-gate 	wp = (log->buffer + log->cur_pos);
7360Sstevel@tonic-gate 	sz = pep - wp;
7370Sstevel@tonic-gate 	bzero(wp, sz);
7380Sstevel@tonic-gate 	/*
7390Sstevel@tonic-gate 	 * Link new logbuf onto end of logd and wake logd up.
7400Sstevel@tonic-gate 	 */
7410Sstevel@tonic-gate 	mutex_enter(&logd.lock);
7420Sstevel@tonic-gate 	log->next = NULL;
7430Sstevel@tonic-gate 	if (logd.tail == NULL)
7440Sstevel@tonic-gate 		logd.head = log;
7450Sstevel@tonic-gate 	else
7460Sstevel@tonic-gate 		logd.tail->next = log;
7470Sstevel@tonic-gate 	logd.tail = log;
7480Sstevel@tonic-gate 	cv_signal(&logd.wait);
7490Sstevel@tonic-gate 	mutex_exit(&logd.lock);
7500Sstevel@tonic-gate 	/*
7510Sstevel@tonic-gate 	 * Try to allocate a new global logbuf.
7520Sstevel@tonic-gate 	 */
7530Sstevel@tonic-gate 	log_buf_alloc(kmflag);
7540Sstevel@tonic-gate 
7550Sstevel@tonic-gate 	goto again;
7560Sstevel@tonic-gate }
757