xref: /onnv-gate/usr/src/cmd/fs.d/nfs/nfslog/process_buffer.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright (c) 1999 by Sun Microsystems, Inc.
24*0Sstevel@tonic-gate  * All rights reserved.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #include <strings.h>
30*0Sstevel@tonic-gate #include <string.h>
31*0Sstevel@tonic-gate #include <syslog.h>
32*0Sstevel@tonic-gate #include <locale.h>
33*0Sstevel@tonic-gate #include <nfs/nfs.h>
34*0Sstevel@tonic-gate #include <nfs/export.h>
35*0Sstevel@tonic-gate #include <nfs/nfssys.h>
36*0Sstevel@tonic-gate #include <nfs/nfs_log.h>
37*0Sstevel@tonic-gate #include <sys/types.h>
38*0Sstevel@tonic-gate #include <sys/stat.h>
39*0Sstevel@tonic-gate #include <stdio.h>
40*0Sstevel@tonic-gate #include <errno.h>
41*0Sstevel@tonic-gate #include <assert.h>
42*0Sstevel@tonic-gate #include <stdlib.h>
43*0Sstevel@tonic-gate #include <unistd.h>
44*0Sstevel@tonic-gate #include <nfs/nfs_log.h>
45*0Sstevel@tonic-gate #include "../lib/nfslog_config.h"
46*0Sstevel@tonic-gate #include "buffer_list.h"
47*0Sstevel@tonic-gate #include "nfslogd.h"
48*0Sstevel@tonic-gate 
49*0Sstevel@tonic-gate extern int _nfssys(int, void *);
50*0Sstevel@tonic-gate 
51*0Sstevel@tonic-gate /*
52*0Sstevel@tonic-gate  * simple list used to keep track of bad tag messages syslogged.
53*0Sstevel@tonic-gate  */
54*0Sstevel@tonic-gate struct list {
55*0Sstevel@tonic-gate 	char *l_name;
56*0Sstevel@tonic-gate 	struct list *l_next;
57*0Sstevel@tonic-gate };
58*0Sstevel@tonic-gate 
59*0Sstevel@tonic-gate static void badtag_notify(char *tag);
60*0Sstevel@tonic-gate static struct list *badtag_list = NULL;
61*0Sstevel@tonic-gate 
62*0Sstevel@tonic-gate static void cleanup_elf_state(nfsl_config_t *);
63*0Sstevel@tonic-gate static void cleanup_trans_state(nfsl_config_t *);
64*0Sstevel@tonic-gate 
65*0Sstevel@tonic-gate /*
66*0Sstevel@tonic-gate  * Read the contents of the 'bufferpath', process them and store the
67*0Sstevel@tonic-gate  * user-readable log in 'elfpath', updating the 'fhpath' filehandle
68*0Sstevel@tonic-gate  * table.
69*0Sstevel@tonic-gate  * The contents of the configuration list (*config_list) may be
70*0Sstevel@tonic-gate  * modified if the configuration file has been updated and we can not
71*0Sstevel@tonic-gate  * find the configuration entry in the currently loaded list.
72*0Sstevel@tonic-gate  *
73*0Sstevel@tonic-gate  * Returns 0 on success and sets *buffer_processed to 1.
74*0Sstevel@tonic-gate  *	   non zero error on failure and *buffer_processed set to 0.
75*0Sstevel@tonic-gate  */
76*0Sstevel@tonic-gate int
77*0Sstevel@tonic-gate process_buffer(
78*0Sstevel@tonic-gate 	struct buffer_ent *bep,
79*0Sstevel@tonic-gate 	nfsl_config_t **config_list,
80*0Sstevel@tonic-gate 	int min_size,
81*0Sstevel@tonic-gate 	int idle_time,
82*0Sstevel@tonic-gate 	int *buffer_processed)
83*0Sstevel@tonic-gate {
84*0Sstevel@tonic-gate 	struct stat st;
85*0Sstevel@tonic-gate 	struct nfsl_flush_args nfa;
86*0Sstevel@tonic-gate 	struct nfslog_buf *lbp = NULL;
87*0Sstevel@tonic-gate 	struct nfslog_lr *lrp;
88*0Sstevel@tonic-gate 	char *path1 = NULL;
89*0Sstevel@tonic-gate 	char *path2 = NULL;
90*0Sstevel@tonic-gate 	char *buffer_inprog = NULL;
91*0Sstevel@tonic-gate 	int buffer_inprog_len;
92*0Sstevel@tonic-gate 	int error = 0;
93*0Sstevel@tonic-gate 	nfsl_config_t *ncp = NULL, *last_good_ncp;
94*0Sstevel@tonic-gate 	char *bufferpath = bep->be_name;
95*0Sstevel@tonic-gate 	char *tag;
96*0Sstevel@tonic-gate 	boolean_t elf_checked = B_FALSE;
97*0Sstevel@tonic-gate 	boolean_t trans_checked = B_FALSE;
98*0Sstevel@tonic-gate 
99*0Sstevel@tonic-gate 	assert(buffer_processed != NULL);
100*0Sstevel@tonic-gate 	assert(bufferpath != NULL);
101*0Sstevel@tonic-gate 
102*0Sstevel@tonic-gate 	if (stat(bufferpath, &st) == -1) {
103*0Sstevel@tonic-gate 		error = errno;
104*0Sstevel@tonic-gate 		if (error == ENOENT) {
105*0Sstevel@tonic-gate 			error = 0;
106*0Sstevel@tonic-gate 			buffer_inprog_len = strlen(bufferpath) +
107*0Sstevel@tonic-gate 				strlen(LOG_INPROG_STRING) + 1;
108*0Sstevel@tonic-gate 			buffer_inprog = (char *)malloc(buffer_inprog_len);
109*0Sstevel@tonic-gate 			if (buffer_inprog == NULL) {
110*0Sstevel@tonic-gate 				syslog(LOG_ERR, gettext(
111*0Sstevel@tonic-gate 					"process_buffer: malloc failed"));
112*0Sstevel@tonic-gate 				return (ENOMEM);
113*0Sstevel@tonic-gate 			}
114*0Sstevel@tonic-gate 			(void) sprintf(buffer_inprog, "%s%s", bufferpath,
115*0Sstevel@tonic-gate 				LOG_INPROG_STRING);
116*0Sstevel@tonic-gate 
117*0Sstevel@tonic-gate 			if (stat(buffer_inprog, &st) == -1) {
118*0Sstevel@tonic-gate 				error = errno;
119*0Sstevel@tonic-gate 				if (bep->be_error != error) {
120*0Sstevel@tonic-gate 					syslog(LOG_ERR, gettext(
121*0Sstevel@tonic-gate 						"Can not stat %s: %s"),
122*0Sstevel@tonic-gate 						buffer_inprog, strerror(error));
123*0Sstevel@tonic-gate 				}
124*0Sstevel@tonic-gate 				free(buffer_inprog);
125*0Sstevel@tonic-gate 				return (error);
126*0Sstevel@tonic-gate 			}
127*0Sstevel@tonic-gate 
128*0Sstevel@tonic-gate 			free(buffer_inprog);
129*0Sstevel@tonic-gate 
130*0Sstevel@tonic-gate 			/*
131*0Sstevel@tonic-gate 			 * Does the buffer in progress meet our minimum
132*0Sstevel@tonic-gate 			 * processing requirements? or has it been around
133*0Sstevel@tonic-gate 			 * longer than we're willing to wait for more
134*0Sstevel@tonic-gate 			 * data to be logged?
135*0Sstevel@tonic-gate 			 */
136*0Sstevel@tonic-gate 			if ((st.st_size < min_size) &&
137*0Sstevel@tonic-gate 			    ((time(0) - bep->be_lastprocessed) < idle_time)) {
138*0Sstevel@tonic-gate 				/*
139*0Sstevel@tonic-gate 				 * The buffer does not meet the minimum
140*0Sstevel@tonic-gate 				 * size processing requirements, and it has not
141*0Sstevel@tonic-gate 				 * been around longer than we're willing to
142*0Sstevel@tonic-gate 				 * wait for more data collection.
143*0Sstevel@tonic-gate 				 * We return now without processing it.
144*0Sstevel@tonic-gate 				 */
145*0Sstevel@tonic-gate 				return (0);
146*0Sstevel@tonic-gate 			}
147*0Sstevel@tonic-gate 
148*0Sstevel@tonic-gate 			/*
149*0Sstevel@tonic-gate 			 * Issue the LOG_FLUSH system call to flush the
150*0Sstevel@tonic-gate 			 * buffer and process it.
151*0Sstevel@tonic-gate 			 */
152*0Sstevel@tonic-gate 			(void) memset((void *)&nfa, 0, sizeof (nfa));
153*0Sstevel@tonic-gate 			nfa.version = NFSL_FLUSH_ARGS_VERS;
154*0Sstevel@tonic-gate 			nfa.directive = NFSL_RENAME | NFSL_SYNC;
155*0Sstevel@tonic-gate 			nfa.buff = bufferpath;
156*0Sstevel@tonic-gate 			nfa.buff_len = strlen(bufferpath) + 1;
157*0Sstevel@tonic-gate 
158*0Sstevel@tonic-gate 			if (_nfssys(LOG_FLUSH, &nfa) < 0) {
159*0Sstevel@tonic-gate 				error = errno;
160*0Sstevel@tonic-gate 				if (bep->be_error != error) {
161*0Sstevel@tonic-gate 					syslog(LOG_ERR, gettext(
162*0Sstevel@tonic-gate 						"_nfssys(%s) failed: %s"),
163*0Sstevel@tonic-gate 						nfa.buff, strerror(error));
164*0Sstevel@tonic-gate 				}
165*0Sstevel@tonic-gate 				return (error);
166*0Sstevel@tonic-gate 			}
167*0Sstevel@tonic-gate 		} else {
168*0Sstevel@tonic-gate 			if (bep->be_error != error) {
169*0Sstevel@tonic-gate 				syslog(LOG_ERR, gettext("Can not stat %s: %s"),
170*0Sstevel@tonic-gate 					bufferpath, strerror(error));
171*0Sstevel@tonic-gate 			}
172*0Sstevel@tonic-gate 			return (error);
173*0Sstevel@tonic-gate 		}
174*0Sstevel@tonic-gate 	}
175*0Sstevel@tonic-gate 
176*0Sstevel@tonic-gate 	/*
177*0Sstevel@tonic-gate 	 * Open and lock input buffer.
178*0Sstevel@tonic-gate 	 * Passes in the value of the last error so that it will not
179*0Sstevel@tonic-gate 	 * print it again if it is still hitting the same error condition.
180*0Sstevel@tonic-gate 	 */
181*0Sstevel@tonic-gate 	error = bep->be_error;
182*0Sstevel@tonic-gate 	if ((lbp = nfslog_open_buf(bufferpath, &error)) == NULL)
183*0Sstevel@tonic-gate 		goto done;
184*0Sstevel@tonic-gate 
185*0Sstevel@tonic-gate 	if ((ncp = last_good_ncp =
186*0Sstevel@tonic-gate 	    nfsl_findconfig(*config_list, "global", &error)) == NULL) {
187*0Sstevel@tonic-gate 		assert(error != 0);
188*0Sstevel@tonic-gate 		nfsl_freeconfig_list(config_list);
189*0Sstevel@tonic-gate 		if (error != bep->be_error) {
190*0Sstevel@tonic-gate 			syslog(LOG_ERR, gettext(
191*0Sstevel@tonic-gate 				"Could not search config list: %s"),
192*0Sstevel@tonic-gate 			strerror(error));
193*0Sstevel@tonic-gate 		}
194*0Sstevel@tonic-gate 		goto done;
195*0Sstevel@tonic-gate 	}
196*0Sstevel@tonic-gate 
197*0Sstevel@tonic-gate 	assert(error == 0);
198*0Sstevel@tonic-gate 	while ((lrp = nfslog_get_logrecord(lbp)) != NULL && keep_running) {
199*0Sstevel@tonic-gate 
200*0Sstevel@tonic-gate 		if (*buffer_processed == 0)
201*0Sstevel@tonic-gate 			(*buffer_processed)++;
202*0Sstevel@tonic-gate 
203*0Sstevel@tonic-gate 		/*
204*0Sstevel@tonic-gate 		 * Get the matching config entry.
205*0Sstevel@tonic-gate 		 */
206*0Sstevel@tonic-gate 		tag = lrp->log_record.re_tag;
207*0Sstevel@tonic-gate 		if (strcmp(tag, last_good_ncp->nc_name) != 0) {
208*0Sstevel@tonic-gate 			ncp = nfsl_findconfig(*config_list, tag, &error);
209*0Sstevel@tonic-gate 			if (error) {
210*0Sstevel@tonic-gate 				if (error != bep->be_error) {
211*0Sstevel@tonic-gate 					syslog(LOG_ERR, gettext(
212*0Sstevel@tonic-gate 					"Could not search config list: %s"),
213*0Sstevel@tonic-gate 					strerror(error));
214*0Sstevel@tonic-gate 				}
215*0Sstevel@tonic-gate 				nfsl_freeconfig_list(config_list);
216*0Sstevel@tonic-gate 				goto done;
217*0Sstevel@tonic-gate 			}
218*0Sstevel@tonic-gate 			if (ncp == NULL) {
219*0Sstevel@tonic-gate 				badtag_notify(tag);
220*0Sstevel@tonic-gate 				ncp = last_good_ncp;
221*0Sstevel@tonic-gate 				goto skip;
222*0Sstevel@tonic-gate 			}
223*0Sstevel@tonic-gate 			last_good_ncp = ncp;
224*0Sstevel@tonic-gate 		}
225*0Sstevel@tonic-gate 
226*0Sstevel@tonic-gate 		if (ncp->nc_flags & NC_UPDATED) {
227*0Sstevel@tonic-gate 			/*
228*0Sstevel@tonic-gate 			 * The location of the log files may have changed,
229*0Sstevel@tonic-gate 			 * we need to close transactions and invalidate
230*0Sstevel@tonic-gate 			 * cookies so that the log files can be reopened
231*0Sstevel@tonic-gate 			 * further down.
232*0Sstevel@tonic-gate 			 */
233*0Sstevel@tonic-gate 			cleanup_elf_state(ncp);
234*0Sstevel@tonic-gate 			cleanup_trans_state(ncp);
235*0Sstevel@tonic-gate 
236*0Sstevel@tonic-gate 			ncp->nc_flags &= ~NC_UPDATED;
237*0Sstevel@tonic-gate 
238*0Sstevel@tonic-gate 			/*
239*0Sstevel@tonic-gate 			 * Force cookies to be recreated if necessary.
240*0Sstevel@tonic-gate 			 */
241*0Sstevel@tonic-gate 			elf_checked = trans_checked = B_FALSE;
242*0Sstevel@tonic-gate 		}
243*0Sstevel@tonic-gate 
244*0Sstevel@tonic-gate 		/*
245*0Sstevel@tonic-gate 		 * Open output files.
246*0Sstevel@tonic-gate 		 */
247*0Sstevel@tonic-gate 		if (ncp->nc_rpclogpath != NULL) {
248*0Sstevel@tonic-gate 			/*
249*0Sstevel@tonic-gate 			 * Log rpc requests in W3C-ELF format.
250*0Sstevel@tonic-gate 			 */
251*0Sstevel@tonic-gate 			if (!elf_checked && ncp->nc_elfcookie != NULL) {
252*0Sstevel@tonic-gate 				/*
253*0Sstevel@tonic-gate 				 * Make sure file still exists.
254*0Sstevel@tonic-gate 				 * Do this once per buffer.
255*0Sstevel@tonic-gate 				 */
256*0Sstevel@tonic-gate 				if (stat(ncp->nc_rpclogpath, &st) == -1 &&
257*0Sstevel@tonic-gate 				    errno == ENOENT) {
258*0Sstevel@tonic-gate 					/*
259*0Sstevel@tonic-gate 					 * The open rpclogfile has been
260*0Sstevel@tonic-gate 					 * deleted.  Get new one below.
261*0Sstevel@tonic-gate 					 */
262*0Sstevel@tonic-gate 					cleanup_elf_state(ncp);
263*0Sstevel@tonic-gate 				}
264*0Sstevel@tonic-gate 				elf_checked = B_TRUE;
265*0Sstevel@tonic-gate 			}
266*0Sstevel@tonic-gate 			if (ncp->nc_elfcookie == NULL) {
267*0Sstevel@tonic-gate 				error = bep->be_error;
268*0Sstevel@tonic-gate 				ncp->nc_elfcookie = nfslog_open_elf_file(
269*0Sstevel@tonic-gate 					ncp->nc_rpclogpath,
270*0Sstevel@tonic-gate 					&lbp->bh, &error);
271*0Sstevel@tonic-gate 				if (ncp->nc_elfcookie == NULL) {
272*0Sstevel@tonic-gate 					bep->be_error = error;
273*0Sstevel@tonic-gate 					goto done;
274*0Sstevel@tonic-gate 				}
275*0Sstevel@tonic-gate 			}
276*0Sstevel@tonic-gate 		}
277*0Sstevel@tonic-gate 
278*0Sstevel@tonic-gate 		if (ncp->nc_logpath != NULL) {
279*0Sstevel@tonic-gate 			/*
280*0Sstevel@tonic-gate 			 * Log rpc reqs in trans/ftp format.
281*0Sstevel@tonic-gate 			 */
282*0Sstevel@tonic-gate 			if (!trans_checked && ncp->nc_transcookie != NULL) {
283*0Sstevel@tonic-gate 				/*
284*0Sstevel@tonic-gate 				 * Do this once per buffer.
285*0Sstevel@tonic-gate 				 */
286*0Sstevel@tonic-gate 				if (stat(ncp->nc_logpath, &st) == -1 &&
287*0Sstevel@tonic-gate 				    errno == ENOENT) {
288*0Sstevel@tonic-gate 					/*
289*0Sstevel@tonic-gate 					 * The open transaction file has been
290*0Sstevel@tonic-gate 					 * deleted. Close pending transaction
291*0Sstevel@tonic-gate 					 * work. A new transaction log will be
292*0Sstevel@tonic-gate 					 * opened by nfslog_open_trans_file()
293*0Sstevel@tonic-gate 					 * below.
294*0Sstevel@tonic-gate 					 */
295*0Sstevel@tonic-gate 					cleanup_trans_state(ncp);
296*0Sstevel@tonic-gate 				}
297*0Sstevel@tonic-gate 				trans_checked = B_TRUE;
298*0Sstevel@tonic-gate 			}
299*0Sstevel@tonic-gate 			if (ncp->nc_transcookie == NULL) {
300*0Sstevel@tonic-gate 				int transtolog;
301*0Sstevel@tonic-gate 
302*0Sstevel@tonic-gate 				transtolog =
303*0Sstevel@tonic-gate 				(ncp->nc_logformat == TRANSLOG_BASIC) ?
304*0Sstevel@tonic-gate 					TRANSTOLOG_OPER_READWRITE :
305*0Sstevel@tonic-gate 					TRANSTOLOG_ALL;
306*0Sstevel@tonic-gate 				error = bep->be_error;
307*0Sstevel@tonic-gate 				ncp->nc_transcookie = nfslog_open_trans_file(
308*0Sstevel@tonic-gate 					ncp->nc_logpath,
309*0Sstevel@tonic-gate 					ncp->nc_logformat,
310*0Sstevel@tonic-gate 					transtolog, &error);
311*0Sstevel@tonic-gate 				if (ncp->nc_transcookie == NULL) {
312*0Sstevel@tonic-gate 					bep->be_error = error;
313*0Sstevel@tonic-gate 					goto done;
314*0Sstevel@tonic-gate 				}
315*0Sstevel@tonic-gate 			}
316*0Sstevel@tonic-gate 		}
317*0Sstevel@tonic-gate 
318*0Sstevel@tonic-gate 		assert(ncp->nc_fhpath != NULL);
319*0Sstevel@tonic-gate 
320*0Sstevel@tonic-gate 		if (nfslog_process_fh_rec(lrp, ncp->nc_fhpath, &path1, &path2,
321*0Sstevel@tonic-gate 		    ncp->nc_elfcookie != NULL)) {
322*0Sstevel@tonic-gate 			/*
323*0Sstevel@tonic-gate 			 * Make sure there is room.
324*0Sstevel@tonic-gate 			 */
325*0Sstevel@tonic-gate 			if (ncp->nc_elfcookie != NULL) {
326*0Sstevel@tonic-gate 				(void) nfslog_process_elf_rec(ncp->nc_elfcookie,
327*0Sstevel@tonic-gate 					&lrp->log_record, path1, path2);
328*0Sstevel@tonic-gate 			}
329*0Sstevel@tonic-gate 
330*0Sstevel@tonic-gate 			if (ncp->nc_transcookie != NULL) {
331*0Sstevel@tonic-gate 				(void) nfslog_process_trans_rec(
332*0Sstevel@tonic-gate 					ncp->nc_transcookie,
333*0Sstevel@tonic-gate 					&lrp->log_record, ncp->nc_fhpath,
334*0Sstevel@tonic-gate 					path1, path2);
335*0Sstevel@tonic-gate 			}
336*0Sstevel@tonic-gate 		}
337*0Sstevel@tonic-gate 
338*0Sstevel@tonic-gate skip:		if (path1 != NULL)
339*0Sstevel@tonic-gate 			free(path1);
340*0Sstevel@tonic-gate 		if (path2 != NULL)
341*0Sstevel@tonic-gate 			free(path2);
342*0Sstevel@tonic-gate 
343*0Sstevel@tonic-gate 		path1 = path2 = NULL;
344*0Sstevel@tonic-gate 		nfslog_free_logrecord(lrp, TRUE);
345*0Sstevel@tonic-gate 	} /* while */
346*0Sstevel@tonic-gate 
347*0Sstevel@tonic-gate 	if (!error && keep_running) {
348*0Sstevel@tonic-gate 		/*
349*0Sstevel@tonic-gate 		 * Keep track of when this buffer was last processed.
350*0Sstevel@tonic-gate 		 */
351*0Sstevel@tonic-gate 		bep->be_lastprocessed = time(0);
352*0Sstevel@tonic-gate 
353*0Sstevel@tonic-gate 		if (test && *buffer_processed != 0) {
354*0Sstevel@tonic-gate 			/*
355*0Sstevel@tonic-gate 			 * Save the buffer for future debugging. We do this
356*0Sstevel@tonic-gate 			 * by following the log cycling policy, with a maximum
357*0Sstevel@tonic-gate 			 * of 'max_logs_preserve' to save.
358*0Sstevel@tonic-gate 			 */
359*0Sstevel@tonic-gate 			if (cycle_log(bufferpath, max_logs_preserve)) {
360*0Sstevel@tonic-gate 				syslog(LOG_ERR, gettext(
361*0Sstevel@tonic-gate 					"could not save copy of buffer \"%s\""),
362*0Sstevel@tonic-gate 					bufferpath);
363*0Sstevel@tonic-gate 			}
364*0Sstevel@tonic-gate 		} else {
365*0Sstevel@tonic-gate 			/*
366*0Sstevel@tonic-gate 			 * Remove buffer since it has been processed.
367*0Sstevel@tonic-gate 			 */
368*0Sstevel@tonic-gate 			if (unlink(bufferpath)) {
369*0Sstevel@tonic-gate 				error = errno;
370*0Sstevel@tonic-gate 				syslog(LOG_ERR, gettext(
371*0Sstevel@tonic-gate 					"could not unlink %s: %s"),
372*0Sstevel@tonic-gate 					bufferpath, strerror(error));
373*0Sstevel@tonic-gate 				/*
374*0Sstevel@tonic-gate 				 * Buffer was processed correctly.
375*0Sstevel@tonic-gate 				 */
376*0Sstevel@tonic-gate 				error = 0;
377*0Sstevel@tonic-gate 			}
378*0Sstevel@tonic-gate 		}
379*0Sstevel@tonic-gate 	}
380*0Sstevel@tonic-gate 
381*0Sstevel@tonic-gate done:
382*0Sstevel@tonic-gate 	if (lbp != NULL)
383*0Sstevel@tonic-gate 		nfslog_close_buf(lbp, quick_cleaning);
384*0Sstevel@tonic-gate 	if (ncp && !quick_cleaning)
385*0Sstevel@tonic-gate 		cleanup_elf_state(ncp);
386*0Sstevel@tonic-gate 
387*0Sstevel@tonic-gate 	return (error);
388*0Sstevel@tonic-gate }
389*0Sstevel@tonic-gate 
390*0Sstevel@tonic-gate static void
391*0Sstevel@tonic-gate cleanup_elf_state(nfsl_config_t *ncp)
392*0Sstevel@tonic-gate {
393*0Sstevel@tonic-gate 	if (ncp->nc_elfcookie != NULL) {
394*0Sstevel@tonic-gate 		nfslog_close_elf_file(&ncp->nc_elfcookie);
395*0Sstevel@tonic-gate 		assert(ncp->nc_elfcookie == NULL);
396*0Sstevel@tonic-gate 	}
397*0Sstevel@tonic-gate }
398*0Sstevel@tonic-gate 
399*0Sstevel@tonic-gate static void
400*0Sstevel@tonic-gate cleanup_trans_state(nfsl_config_t *ncp)
401*0Sstevel@tonic-gate {
402*0Sstevel@tonic-gate 	if (ncp->nc_transcookie != NULL) {
403*0Sstevel@tonic-gate 		nfslog_close_transactions(&ncp->nc_transcookie);
404*0Sstevel@tonic-gate 		assert(ncp->nc_transcookie == NULL);
405*0Sstevel@tonic-gate 	}
406*0Sstevel@tonic-gate }
407*0Sstevel@tonic-gate 
408*0Sstevel@tonic-gate /*
409*0Sstevel@tonic-gate  * Searches the list of previously seen bad tags. Note that this
410*0Sstevel@tonic-gate  * list is never pruned. This should not be a problem since the
411*0Sstevel@tonic-gate  * list of bad tags should be fairl small. New entries are inserted
412*0Sstevel@tonic-gate  * at the beginning of the list assuming it will be accessed more
413*0Sstevel@tonic-gate  * frequently since we have just seen it.
414*0Sstevel@tonic-gate  */
415*0Sstevel@tonic-gate static void
416*0Sstevel@tonic-gate badtag_notify(char *tag)
417*0Sstevel@tonic-gate {
418*0Sstevel@tonic-gate 	struct list *lp, *p;
419*0Sstevel@tonic-gate 	int error;
420*0Sstevel@tonic-gate 
421*0Sstevel@tonic-gate 	for (p = badtag_list; p != NULL; p = p->l_next) {
422*0Sstevel@tonic-gate 		if (strcmp(tag, p->l_name) == 0) {
423*0Sstevel@tonic-gate 			/*
424*0Sstevel@tonic-gate 			 * We've seen this before, nothing to do.
425*0Sstevel@tonic-gate 			 */
426*0Sstevel@tonic-gate 			return;
427*0Sstevel@tonic-gate 		}
428*0Sstevel@tonic-gate 	}
429*0Sstevel@tonic-gate 
430*0Sstevel@tonic-gate 	/*
431*0Sstevel@tonic-gate 	 * Not on the list, add it.
432*0Sstevel@tonic-gate 	 */
433*0Sstevel@tonic-gate 	syslog(LOG_ERR, gettext(
434*0Sstevel@tonic-gate 		"tag \"%s\" not found in %s - "
435*0Sstevel@tonic-gate 		"ignoring records referencing such tag."),
436*0Sstevel@tonic-gate 		tag, NFSL_CONFIG_FILE_PATH);
437*0Sstevel@tonic-gate 
438*0Sstevel@tonic-gate 	if ((lp = (struct list *)malloc(sizeof (*lp))) != NULL) {
439*0Sstevel@tonic-gate 		if ((lp->l_name = strdup(tag)) != NULL) {
440*0Sstevel@tonic-gate 			lp->l_next = badtag_list;
441*0Sstevel@tonic-gate 			badtag_list = lp;
442*0Sstevel@tonic-gate 			return;		/* done */
443*0Sstevel@tonic-gate 		}
444*0Sstevel@tonic-gate 	}
445*0Sstevel@tonic-gate 
446*0Sstevel@tonic-gate 	if (lp->l_name != NULL)
447*0Sstevel@tonic-gate 		free(lp->l_name);
448*0Sstevel@tonic-gate 	if (lp)
449*0Sstevel@tonic-gate 		free(lp);
450*0Sstevel@tonic-gate 	error = errno;
451*0Sstevel@tonic-gate 	syslog(LOG_ERR, gettext(
452*0Sstevel@tonic-gate 	    "Cannot add \"%s\" to bad tag list: %s"), tag, strerror(error));
453*0Sstevel@tonic-gate }
454