mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-23 04:55:18 +00:00
Use helper functions to format the journal iov array
This simplifies the top-level code, at the cost of using a little more stack space. The primary benefit is being able to send more fields without knowing in advance how many of them, and of which types, these fields will be, and without having to individually add buffer variables. The code imposes an upper limit on the total number of iovs/buffers used, and fields that wouldn't fit are silently dropped. This is not significant in this patch, but will affect the following one. Signed-off-by: Miloslav Trmač <mitr@redhat.com>
This commit is contained in:
parent
37f7a1faf1
commit
39c814ff46
@ -1043,19 +1043,78 @@ virLogAddOutputToSyslog(virLogPriority priority,
|
|||||||
|
|
||||||
|
|
||||||
# if USE_JOURNALD
|
# if USE_JOURNALD
|
||||||
# define IOVEC_SET_STRING(iov, str) \
|
# define IOVEC_SET(iov, data, size) \
|
||||||
do { \
|
do { \
|
||||||
struct iovec *_i = &(iov); \
|
struct iovec *_i = &(iov); \
|
||||||
_i->iov_base = (char*)str; \
|
_i->iov_base = (void*)(data); \
|
||||||
_i->iov_len = strlen(str); \
|
_i->iov_len = (size); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
# define IOVEC_SET_INT(iov, buf, val) \
|
# define IOVEC_SET_STRING(iov, str) IOVEC_SET(iov, str, strlen(str))
|
||||||
do { \
|
|
||||||
struct iovec *_i = &(iov); \
|
/* Used for conversion of numbers to strings, and for length of binary data */
|
||||||
_i->iov_base = virFormatIntDecimal(buf, sizeof(buf), val); \
|
# define JOURNAL_BUF_SIZE (MAX(INT_BUFSIZE_BOUND(int), sizeof(uint64_t)))
|
||||||
_i->iov_len = strlen(buf); \
|
|
||||||
} while (0)
|
struct journalState
|
||||||
|
{
|
||||||
|
struct iovec *iov, *iov_end;
|
||||||
|
char (*bufs)[JOURNAL_BUF_SIZE], (*bufs_end)[JOURNAL_BUF_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
journalAddString(struct journalState *state, const char *field,
|
||||||
|
const char *value)
|
||||||
|
{
|
||||||
|
static const char newline = '\n', equals = '=';
|
||||||
|
|
||||||
|
if (strchr(value, '\n') != NULL) {
|
||||||
|
uint64_t nstr;
|
||||||
|
|
||||||
|
/* If 'str' contains a newline, then we must
|
||||||
|
* encode the string length, since we can't
|
||||||
|
* rely on the newline for the field separator
|
||||||
|
*/
|
||||||
|
if (state->iov_end - state->iov < 5 || state->bufs == state->bufs_end)
|
||||||
|
return; /* Silently drop */
|
||||||
|
nstr = htole64(strlen(value));
|
||||||
|
memcpy(state->bufs[0], &nstr, sizeof(nstr));
|
||||||
|
|
||||||
|
IOVEC_SET_STRING(state->iov[0], field);
|
||||||
|
IOVEC_SET(state->iov[1], &newline, sizeof(newline));
|
||||||
|
IOVEC_SET(state->iov[2], state->bufs[0], sizeof(nstr));
|
||||||
|
state->bufs++;
|
||||||
|
state->iov += 3;
|
||||||
|
} else {
|
||||||
|
if (state->iov_end - state->iov < 4)
|
||||||
|
return; /* Silently drop */
|
||||||
|
IOVEC_SET_STRING(state->iov[0], field);
|
||||||
|
IOVEC_SET(state->iov[1], (void *)&equals, sizeof(equals));
|
||||||
|
state->iov += 2;
|
||||||
|
}
|
||||||
|
IOVEC_SET_STRING(state->iov[0], value);
|
||||||
|
IOVEC_SET(state->iov[1], (void *)&newline, sizeof(newline));
|
||||||
|
state->iov += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
journalAddInt(struct journalState *state, const char *field, int value)
|
||||||
|
{
|
||||||
|
static const char newline = '\n', equals = '=';
|
||||||
|
|
||||||
|
char *num;
|
||||||
|
|
||||||
|
if (state->iov_end - state->iov < 4 || state->bufs == state->bufs_end)
|
||||||
|
return; /* Silently drop */
|
||||||
|
|
||||||
|
num = virFormatIntDecimal(state->bufs[0], sizeof(state->bufs[0]), value);
|
||||||
|
|
||||||
|
IOVEC_SET_STRING(state->iov[0], field);
|
||||||
|
IOVEC_SET(state->iov[1], (void *)&equals, sizeof(equals));
|
||||||
|
IOVEC_SET_STRING(state->iov[2], num);
|
||||||
|
IOVEC_SET(state->iov[3], (void *)&newline, sizeof(newline));
|
||||||
|
state->bufs++;
|
||||||
|
state->iov += 4;
|
||||||
|
}
|
||||||
|
|
||||||
static int journalfd = -1;
|
static int journalfd = -1;
|
||||||
|
|
||||||
@ -1074,7 +1133,6 @@ virLogOutputToJournald(virLogSource source,
|
|||||||
{
|
{
|
||||||
virCheckFlags(VIR_LOG_STACK_TRACE,);
|
virCheckFlags(VIR_LOG_STACK_TRACE,);
|
||||||
int buffd = -1;
|
int buffd = -1;
|
||||||
size_t niov = 0;
|
|
||||||
struct msghdr mh;
|
struct msghdr mh;
|
||||||
struct sockaddr_un sa;
|
struct sockaddr_un sa;
|
||||||
union {
|
union {
|
||||||
@ -1086,52 +1144,24 @@ virLogOutputToJournald(virLogSource source,
|
|||||||
* be a tmpfs, and one that is available from early boot on
|
* be a tmpfs, and one that is available from early boot on
|
||||||
* and where unprivileged users can create files. */
|
* and where unprivileged users can create files. */
|
||||||
char path[] = "/dev/shm/journal.XXXXXX";
|
char path[] = "/dev/shm/journal.XXXXXX";
|
||||||
char priostr[INT_BUFSIZE_BOUND(priority)];
|
|
||||||
char linestr[INT_BUFSIZE_BOUND(linenr)];
|
|
||||||
|
|
||||||
/* First message takes up to 4 iovecs, and each
|
# define NUM_FIELDS 6
|
||||||
* other field needs 3, assuming they don't have
|
struct iovec iov[NUM_FIELDS * 5];
|
||||||
* newlines in them
|
char iov_bufs[NUM_FIELDS][JOURNAL_BUF_SIZE];
|
||||||
*/
|
struct journalState state;
|
||||||
# define IOV_SIZE (4 + (5 * 3))
|
|
||||||
struct iovec iov[IOV_SIZE];
|
|
||||||
|
|
||||||
if (strchr(rawstr, '\n')) {
|
state.iov = iov;
|
||||||
uint64_t nstr;
|
state.iov_end = iov + ARRAY_CARDINALITY(iov);
|
||||||
/* If 'str' contains a newline, then we must
|
state.bufs = iov_bufs;
|
||||||
* encode the string length, since we can't
|
state.bufs_end = iov_bufs + ARRAY_CARDINALITY(iov_bufs);
|
||||||
* rely on the newline for the field separator
|
|
||||||
*/
|
|
||||||
IOVEC_SET_STRING(iov[niov++], "MESSAGE\n");
|
|
||||||
nstr = htole64(strlen(rawstr));
|
|
||||||
iov[niov].iov_base = (char*)&nstr;
|
|
||||||
iov[niov].iov_len = sizeof(nstr);
|
|
||||||
niov++;
|
|
||||||
} else {
|
|
||||||
IOVEC_SET_STRING(iov[niov++], "MESSAGE=");
|
|
||||||
}
|
|
||||||
IOVEC_SET_STRING(iov[niov++], rawstr);
|
|
||||||
IOVEC_SET_STRING(iov[niov++], "\n");
|
|
||||||
|
|
||||||
IOVEC_SET_STRING(iov[niov++], "PRIORITY=");
|
journalAddString(&state ,"MESSAGE", rawstr);
|
||||||
IOVEC_SET_INT(iov[niov++], priostr, priority);
|
journalAddInt(&state, "PRIORITY", priority);
|
||||||
IOVEC_SET_STRING(iov[niov++], "\n");
|
journalAddString(&state, "LIBVIRT_SOURCE",
|
||||||
|
virLogSourceTypeToString(source));
|
||||||
IOVEC_SET_STRING(iov[niov++], "LIBVIRT_SOURCE=");
|
journalAddString(&state, "CODE_FILE", filename);
|
||||||
IOVEC_SET_STRING(iov[niov++], virLogSourceTypeToString(source));
|
journalAddInt(&state, "CODE_LINE", linenr);
|
||||||
IOVEC_SET_STRING(iov[niov++], "\n");
|
journalAddString(&state, "CODE_FUNC", funcname);
|
||||||
|
|
||||||
IOVEC_SET_STRING(iov[niov++], "CODE_FILE=");
|
|
||||||
IOVEC_SET_STRING(iov[niov++], filename);
|
|
||||||
IOVEC_SET_STRING(iov[niov++], "\n");
|
|
||||||
|
|
||||||
IOVEC_SET_STRING(iov[niov++], "CODE_LINE=");
|
|
||||||
IOVEC_SET_INT(iov[niov++], linestr, linenr);
|
|
||||||
IOVEC_SET_STRING(iov[niov++], "\n");
|
|
||||||
|
|
||||||
IOVEC_SET_STRING(iov[niov++], "CODE_FUNC=");
|
|
||||||
IOVEC_SET_STRING(iov[niov++], funcname);
|
|
||||||
IOVEC_SET_STRING(iov[niov++], "\n");
|
|
||||||
|
|
||||||
memset(&sa, 0, sizeof(sa));
|
memset(&sa, 0, sizeof(sa));
|
||||||
sa.sun_family = AF_UNIX;
|
sa.sun_family = AF_UNIX;
|
||||||
@ -1142,7 +1172,7 @@ virLogOutputToJournald(virLogSource source,
|
|||||||
mh.msg_name = &sa;
|
mh.msg_name = &sa;
|
||||||
mh.msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(sa.sun_path);
|
mh.msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(sa.sun_path);
|
||||||
mh.msg_iov = iov;
|
mh.msg_iov = iov;
|
||||||
mh.msg_iovlen = niov;
|
mh.msg_iovlen = state.iov - iov;
|
||||||
|
|
||||||
if (sendmsg(journalfd, &mh, MSG_NOSIGNAL) >= 0)
|
if (sendmsg(journalfd, &mh, MSG_NOSIGNAL) >= 0)
|
||||||
return;
|
return;
|
||||||
@ -1166,7 +1196,7 @@ virLogOutputToJournald(virLogSource source,
|
|||||||
if (unlink(path) < 0)
|
if (unlink(path) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if (writev(buffd, iov, niov) < 0)
|
if (writev(buffd, iov, state.iov - iov) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
mh.msg_iov = NULL;
|
mh.msg_iov = NULL;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user