Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/openzfs/cmd/zed/zed_log.c
48380 views
1
// SPDX-License-Identifier: CDDL-1.0
2
/*
3
* This file is part of the ZFS Event Daemon (ZED).
4
*
5
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
6
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
7
* Refer to the OpenZFS git commit log for authoritative copyright attribution.
8
*
9
* The contents of this file are subject to the terms of the
10
* Common Development and Distribution License Version 1.0 (CDDL-1.0).
11
* You can obtain a copy of the license from the top-level file
12
* "OPENSOLARIS.LICENSE" or at <http://opensource.org/licenses/CDDL-1.0>.
13
* You may not use this file except in compliance with the license.
14
*/
15
16
#include <assert.h>
17
#include <errno.h>
18
#include <stdarg.h>
19
#include <stdio.h>
20
#include <stdlib.h>
21
#include <string.h>
22
#include <sys/types.h>
23
#include <syslog.h>
24
#include <unistd.h>
25
#include "zed_log.h"
26
27
#define ZED_LOG_MAX_LOG_LEN 1024
28
29
static struct {
30
unsigned do_stderr:1;
31
unsigned do_syslog:1;
32
const char *identity;
33
int priority;
34
int pipe_fd[2];
35
} _ctx;
36
37
/*
38
* Initialize the logging subsystem.
39
*/
40
void
41
zed_log_init(const char *identity)
42
{
43
if (identity) {
44
const char *p = strrchr(identity, '/');
45
_ctx.identity = (p != NULL) ? p + 1 : identity;
46
} else {
47
_ctx.identity = NULL;
48
}
49
_ctx.pipe_fd[0] = -1;
50
_ctx.pipe_fd[1] = -1;
51
}
52
53
/*
54
* Shutdown the logging subsystem.
55
*/
56
void
57
zed_log_fini(void)
58
{
59
zed_log_stderr_close();
60
zed_log_syslog_close();
61
}
62
63
/*
64
* Create pipe for communicating daemonization status between the parent and
65
* child processes across the double-fork().
66
*/
67
void
68
zed_log_pipe_open(void)
69
{
70
if ((_ctx.pipe_fd[0] != -1) || (_ctx.pipe_fd[1] != -1))
71
zed_log_die("Invalid use of zed_log_pipe_open in PID %d",
72
(int)getpid());
73
74
if (pipe(_ctx.pipe_fd) < 0)
75
zed_log_die("Failed to create daemonize pipe in PID %d: %s",
76
(int)getpid(), strerror(errno));
77
}
78
79
/*
80
* Close the read-half of the daemonize pipe.
81
*
82
* This should be called by the child after fork()ing from the parent since
83
* the child will never read from this pipe.
84
*/
85
void
86
zed_log_pipe_close_reads(void)
87
{
88
if (_ctx.pipe_fd[0] < 0)
89
zed_log_die(
90
"Invalid use of zed_log_pipe_close_reads in PID %d",
91
(int)getpid());
92
93
if (close(_ctx.pipe_fd[0]) < 0)
94
zed_log_die(
95
"Failed to close reads on daemonize pipe in PID %d: %s",
96
(int)getpid(), strerror(errno));
97
98
_ctx.pipe_fd[0] = -1;
99
}
100
101
/*
102
* Close the write-half of the daemonize pipe.
103
*
104
* This should be called by the parent after fork()ing its child since the
105
* parent will never write to this pipe.
106
*
107
* This should also be called by the child once initialization is complete
108
* in order to signal the parent that it can safely exit.
109
*/
110
void
111
zed_log_pipe_close_writes(void)
112
{
113
if (_ctx.pipe_fd[1] < 0)
114
zed_log_die(
115
"Invalid use of zed_log_pipe_close_writes in PID %d",
116
(int)getpid());
117
118
if (close(_ctx.pipe_fd[1]) < 0)
119
zed_log_die(
120
"Failed to close writes on daemonize pipe in PID %d: %s",
121
(int)getpid(), strerror(errno));
122
123
_ctx.pipe_fd[1] = -1;
124
}
125
126
/*
127
* Block on reading from the daemonize pipe until signaled by the child
128
* (via zed_log_pipe_close_writes()) that initialization is complete.
129
*
130
* This should only be called by the parent while waiting to exit after
131
* fork()ing the child.
132
*/
133
void
134
zed_log_pipe_wait(void)
135
{
136
ssize_t n;
137
char c;
138
139
if (_ctx.pipe_fd[0] < 0)
140
zed_log_die("Invalid use of zed_log_pipe_wait in PID %d",
141
(int)getpid());
142
143
for (;;) {
144
n = read(_ctx.pipe_fd[0], &c, sizeof (c));
145
if (n < 0) {
146
if (errno == EINTR)
147
continue;
148
zed_log_die(
149
"Failed to read from daemonize pipe in PID %d: %s",
150
(int)getpid(), strerror(errno));
151
}
152
if (n == 0) {
153
break;
154
}
155
}
156
}
157
158
/*
159
* Start logging messages at the syslog [priority] level or higher to stderr.
160
* Refer to syslog(3) for valid priority values.
161
*/
162
void
163
zed_log_stderr_open(int priority)
164
{
165
_ctx.do_stderr = 1;
166
_ctx.priority = priority;
167
}
168
169
/*
170
* Stop logging messages to stderr.
171
*/
172
void
173
zed_log_stderr_close(void)
174
{
175
if (_ctx.do_stderr)
176
_ctx.do_stderr = 0;
177
}
178
179
/*
180
* Start logging messages to syslog.
181
* Refer to syslog(3) for valid option/facility values.
182
*/
183
void
184
zed_log_syslog_open(int facility)
185
{
186
_ctx.do_syslog = 1;
187
openlog(_ctx.identity, LOG_NDELAY | LOG_PID, facility);
188
}
189
190
/*
191
* Stop logging messages to syslog.
192
*/
193
void
194
zed_log_syslog_close(void)
195
{
196
if (_ctx.do_syslog) {
197
_ctx.do_syslog = 0;
198
closelog();
199
}
200
}
201
202
/*
203
* Auxiliary function to log a message to syslog and/or stderr.
204
*/
205
static void
206
_zed_log_aux(int priority, const char *fmt, va_list vargs)
207
{
208
char buf[ZED_LOG_MAX_LOG_LEN];
209
int n;
210
211
if (!fmt)
212
return;
213
214
n = vsnprintf(buf, sizeof (buf), fmt, vargs);
215
if ((n < 0) || (n >= sizeof (buf))) {
216
buf[sizeof (buf) - 2] = '+';
217
buf[sizeof (buf) - 1] = '\0';
218
}
219
220
if (_ctx.do_syslog)
221
syslog(priority, "%s", buf);
222
223
if (_ctx.do_stderr && (priority <= _ctx.priority))
224
fprintf(stderr, "%s\n", buf);
225
}
226
227
/*
228
* Log a message at the given [priority] level specified by the printf-style
229
* format string [fmt].
230
*/
231
void
232
zed_log_msg(int priority, const char *fmt, ...)
233
{
234
va_list vargs;
235
236
if (fmt) {
237
va_start(vargs, fmt);
238
_zed_log_aux(priority, fmt, vargs);
239
va_end(vargs);
240
}
241
}
242
243
/*
244
* Log a fatal error message specified by the printf-style format string [fmt].
245
*/
246
void
247
zed_log_die(const char *fmt, ...)
248
{
249
va_list vargs;
250
251
if (fmt) {
252
va_start(vargs, fmt);
253
_zed_log_aux(LOG_ERR, fmt, vargs);
254
va_end(vargs);
255
}
256
exit(EXIT_FAILURE);
257
}
258
259