4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
31 #include <nfs/export.h>
32 #include <nfs/nfssys.h>
33 #include <nfs/nfs_log.h>
34 #include <sys/types.h>
41 #include <nfs/nfs_log.h>
42 #include "../lib/nfslog_config.h"
43 #include "buffer_list.h"
46 extern int _nfssys(int, void *);
49 * simple list used to keep track of bad tag messages syslogged.
53 struct nfs_log_list
*l_next
;
56 static void badtag_notify(char *tag
);
57 static struct nfs_log_list
*badtag_list
= NULL
;
59 static void cleanup_elf_state(nfsl_config_t
*);
60 static void cleanup_trans_state(nfsl_config_t
*);
63 * Read the contents of the 'bufferpath', process them and store the
64 * user-readable log in 'elfpath', updating the 'fhpath' filehandle
66 * The contents of the configuration list (*config_list) may be
67 * modified if the configuration file has been updated and we can not
68 * find the configuration entry in the currently loaded list.
70 * Returns 0 on success and sets *buffer_processed to 1.
71 * non zero error on failure and *buffer_processed set to 0.
75 struct buffer_ent
*bep
,
76 nfsl_config_t
**config_list
,
79 int *buffer_processed
)
82 struct nfsl_flush_args nfa
;
83 struct nfslog_buf
*lbp
= NULL
;
84 struct nfslog_lr
*lrp
;
87 char *buffer_inprog
= NULL
;
88 int buffer_inprog_len
;
90 nfsl_config_t
*ncp
= NULL
, *last_good_ncp
;
91 char *bufferpath
= bep
->be_name
;
93 boolean_t elf_checked
= B_FALSE
;
94 boolean_t trans_checked
= B_FALSE
;
96 assert(buffer_processed
!= NULL
);
97 assert(bufferpath
!= NULL
);
99 if (stat(bufferpath
, &st
) == -1) {
101 if (error
== ENOENT
) {
103 buffer_inprog_len
= strlen(bufferpath
) +
104 strlen(LOG_INPROG_STRING
) + 1;
105 buffer_inprog
= (char *)malloc(buffer_inprog_len
);
106 if (buffer_inprog
== NULL
) {
107 syslog(LOG_ERR
, gettext(
108 "process_buffer: malloc failed"));
111 (void) sprintf(buffer_inprog
, "%s%s", bufferpath
,
114 if (stat(buffer_inprog
, &st
) == -1) {
116 if (bep
->be_error
!= error
) {
117 syslog(LOG_ERR
, gettext(
118 "Can not stat %s: %s"),
119 buffer_inprog
, strerror(error
));
128 * Does the buffer in progress meet our minimum
129 * processing requirements? or has it been around
130 * longer than we're willing to wait for more
133 if ((st
.st_size
< min_size
) &&
134 ((time(0) - bep
->be_lastprocessed
) < idle_time
)) {
136 * The buffer does not meet the minimum
137 * size processing requirements, and it has not
138 * been around longer than we're willing to
139 * wait for more data collection.
140 * We return now without processing it.
146 * Issue the LOG_FLUSH system call to flush the
147 * buffer and process it.
149 (void) memset(&nfa
, 0, sizeof (nfa
));
150 nfa
.version
= NFSL_FLUSH_ARGS_VERS
;
151 nfa
.directive
= NFSL_RENAME
| NFSL_SYNC
;
152 nfa
.buff
= bufferpath
;
153 nfa
.buff_len
= strlen(bufferpath
) + 1;
155 if (_nfssys(LOG_FLUSH
, &nfa
) < 0) {
157 if (bep
->be_error
!= error
) {
158 syslog(LOG_ERR
, gettext(
159 "_nfssys(%s) failed: %s"),
160 nfa
.buff
, strerror(error
));
165 if (bep
->be_error
!= error
) {
166 syslog(LOG_ERR
, gettext("Can not stat %s: %s"),
167 bufferpath
, strerror(error
));
174 * Open and lock input buffer.
175 * Passes in the value of the last error so that it will not
176 * print it again if it is still hitting the same error condition.
178 error
= bep
->be_error
;
179 if ((lbp
= nfslog_open_buf(bufferpath
, &error
)) == NULL
)
182 if ((ncp
= last_good_ncp
=
183 nfsl_findconfig(*config_list
, "global", &error
)) == NULL
) {
185 nfsl_freeconfig_list(config_list
);
186 if (error
!= bep
->be_error
) {
187 syslog(LOG_ERR
, gettext(
188 "Could not search config list: %s"),
195 while ((lrp
= nfslog_get_logrecord(lbp
)) != NULL
&& keep_running
) {
197 if (*buffer_processed
== 0)
198 (*buffer_processed
)++;
201 * Get the matching config entry.
203 tag
= lrp
->log_record
.re_tag
;
204 if (strcmp(tag
, last_good_ncp
->nc_name
) != 0) {
205 ncp
= nfsl_findconfig(*config_list
, tag
, &error
);
207 if (error
!= bep
->be_error
) {
208 syslog(LOG_ERR
, gettext(
209 "Could not search config list: %s"),
212 nfsl_freeconfig_list(config_list
);
223 if (ncp
->nc_flags
& NC_UPDATED
) {
225 * The location of the log files may have changed,
226 * we need to close transactions and invalidate
227 * cookies so that the log files can be reopened
230 cleanup_elf_state(ncp
);
231 cleanup_trans_state(ncp
);
233 ncp
->nc_flags
&= ~NC_UPDATED
;
236 * Force cookies to be recreated if necessary.
238 elf_checked
= trans_checked
= B_FALSE
;
244 if (ncp
->nc_rpclogpath
!= NULL
) {
246 * Log rpc requests in W3C-ELF format.
248 if (!elf_checked
&& ncp
->nc_elfcookie
!= NULL
) {
250 * Make sure file still exists.
251 * Do this once per buffer.
253 if (stat(ncp
->nc_rpclogpath
, &st
) == -1 &&
256 * The open rpclogfile has been
257 * deleted. Get new one below.
259 cleanup_elf_state(ncp
);
261 elf_checked
= B_TRUE
;
263 if (ncp
->nc_elfcookie
== NULL
) {
264 error
= bep
->be_error
;
265 ncp
->nc_elfcookie
= nfslog_open_elf_file(
266 ncp
->nc_rpclogpath
, &lbp
->bh
, &error
);
267 if (ncp
->nc_elfcookie
== NULL
) {
268 bep
->be_error
= error
;
274 if (ncp
->nc_logpath
!= NULL
) {
276 * Log rpc reqs in trans/ftp format.
278 if (!trans_checked
&& ncp
->nc_transcookie
!= NULL
) {
280 * Do this once per buffer.
282 if (stat(ncp
->nc_logpath
, &st
) == -1 &&
285 * The open transaction file has been
286 * deleted. Close pending transaction
287 * work. A new transaction log will be
288 * opened by nfslog_open_trans_file()
291 cleanup_trans_state(ncp
);
293 trans_checked
= B_TRUE
;
295 if (ncp
->nc_transcookie
== NULL
) {
299 (ncp
->nc_logformat
== TRANSLOG_BASIC
) ?
300 TRANSTOLOG_OPER_READWRITE
: TRANSTOLOG_ALL
;
301 error
= bep
->be_error
;
302 ncp
->nc_transcookie
= nfslog_open_trans_file(
303 ncp
->nc_logpath
, ncp
->nc_logformat
,
305 if (ncp
->nc_transcookie
== NULL
) {
306 bep
->be_error
= error
;
312 assert(ncp
->nc_fhpath
!= NULL
);
314 if (nfslog_process_fh_rec(lrp
, ncp
->nc_fhpath
, &path1
, &path2
,
315 ncp
->nc_elfcookie
!= NULL
)) {
317 * Make sure there is room.
319 if (ncp
->nc_elfcookie
!= NULL
) {
320 (void) nfslog_process_elf_rec(ncp
->nc_elfcookie
,
321 &lrp
->log_record
, path1
, path2
);
324 if (ncp
->nc_transcookie
!= NULL
) {
325 (void) nfslog_process_trans_rec(
327 &lrp
->log_record
, ncp
->nc_fhpath
,
335 path1
= path2
= NULL
;
336 nfslog_free_logrecord(lrp
, TRUE
);
339 if (!error
&& keep_running
) {
341 * Keep track of when this buffer was last processed.
343 bep
->be_lastprocessed
= time(0);
345 if (test
&& *buffer_processed
!= 0) {
347 * Save the buffer for future debugging. We do this
348 * by following the log cycling policy, with a maximum
349 * of 'max_logs_preserve' to save.
351 if (cycle_log(bufferpath
, max_logs_preserve
)) {
352 syslog(LOG_ERR
, gettext(
353 "could not save copy of buffer \"%s\""),
358 * Remove buffer since it has been processed.
360 if (unlink(bufferpath
)) {
362 syslog(LOG_ERR
, gettext(
363 "could not unlink %s: %s"),
364 bufferpath
, strerror(error
));
366 * Buffer was processed correctly.
375 nfslog_close_buf(lbp
, quick_cleaning
);
376 if (ncp
&& !quick_cleaning
)
377 cleanup_elf_state(ncp
);
383 cleanup_elf_state(nfsl_config_t
*ncp
)
385 if (ncp
->nc_elfcookie
!= NULL
) {
386 nfslog_close_elf_file(&ncp
->nc_elfcookie
);
387 assert(ncp
->nc_elfcookie
== NULL
);
392 cleanup_trans_state(nfsl_config_t
*ncp
)
394 if (ncp
->nc_transcookie
!= NULL
) {
395 nfslog_close_transactions(&ncp
->nc_transcookie
);
396 assert(ncp
->nc_transcookie
== NULL
);
401 * Searches the list of previously seen bad tags. Note that this
402 * list is never pruned. This should not be a problem since the
403 * list of bad tags should be fairl small. New entries are inserted
404 * at the beginning of the list assuming it will be accessed more
405 * frequently since we have just seen it.
408 badtag_notify(char *tag
)
410 struct nfs_log_list
*lp
, *p
;
413 for (p
= badtag_list
; p
!= NULL
; p
= p
->l_next
) {
414 if (strcmp(tag
, p
->l_name
) == 0) {
416 * We've seen this before, nothing to do.
423 * Not on the list, add it.
425 syslog(LOG_ERR
, gettext("tag \"%s\" not found in %s - "
426 "ignoring records referencing such tag."),
427 tag
, NFSL_CONFIG_FILE_PATH
);
429 if ((lp
= (struct nfs_log_list
*)malloc(sizeof (*lp
))) != NULL
) {
430 if ((lp
->l_name
= strdup(tag
)) != NULL
) {
431 lp
->l_next
= badtag_list
;
440 syslog(LOG_ERR
, gettext(
441 "Cannot add \"%s\" to bad tag list: %s"), tag
, strerror(error
));