liblog: add pstore write
Used to push the Android log messages into pstore (when available, and no propagation of error). Change-Id: I9def8cf796d35d347f502d9745d5f42ec1200253
This commit is contained in:
parent
69bdba21f6
commit
d91ab5815d
2 changed files with 59 additions and 20 deletions
|
@ -24,7 +24,17 @@
|
|||
#include <log/log.h>
|
||||
#include <log/log_read.h>
|
||||
|
||||
/* Header Structure to logd */
|
||||
#define LOGGER_MAGIC 'l'
|
||||
|
||||
/* Header Structure to pstore */
|
||||
typedef struct __attribute__((__packed__)) {
|
||||
uint8_t magic;
|
||||
uint16_t len;
|
||||
uint16_t uid;
|
||||
uint16_t pid;
|
||||
} android_pmsg_log_header_t;
|
||||
|
||||
/* Header Structure to logd, and second header for pstore */
|
||||
typedef struct __attribute__((__packed__)) {
|
||||
typeof_log_id_t id;
|
||||
uint16_t tid;
|
||||
|
|
|
@ -62,6 +62,7 @@ static pthread_mutex_t log_init_lock = PTHREAD_MUTEX_INITIALIZER;
|
|||
static int log_fds[(int)LOG_ID_MAX] = { -1, -1, -1, -1, -1 };
|
||||
#else
|
||||
static int logd_fd = -1;
|
||||
static int pstore_fd = -1;
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -110,6 +111,12 @@ static int __write_to_log_initialize()
|
|||
logd_fd = -1;
|
||||
close(i);
|
||||
}
|
||||
if (pstore_fd >= 0) {
|
||||
i = pstore_fd;
|
||||
pstore_fd = -1;
|
||||
close(i);
|
||||
}
|
||||
pstore_fd = open("/dev/pmsg0", O_WRONLY);
|
||||
|
||||
i = socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0);
|
||||
if (i < 0) {
|
||||
|
@ -156,32 +163,26 @@ static int __write_to_log_kernel(log_id_t log_id, struct iovec *vec, size_t nr)
|
|||
}
|
||||
} while (ret == -EINTR);
|
||||
#else
|
||||
static const unsigned header_length = 1;
|
||||
static const unsigned header_length = 2;
|
||||
struct iovec newVec[nr + header_length];
|
||||
struct android_log_header_t header;
|
||||
android_log_header_t header;
|
||||
android_pmsg_log_header_t pmsg_header;
|
||||
struct timespec ts;
|
||||
size_t i, payload_size;
|
||||
static uid_t last_uid = AID_ROOT; /* logd *always* starts up as AID_ROOT */
|
||||
static pid_t last_pid = (pid_t) -1;
|
||||
|
||||
if (last_uid == AID_ROOT) { /* have we called to get the UID yet? */
|
||||
last_uid = getuid();
|
||||
}
|
||||
if (last_uid == AID_LOGD) { /* logd, after initialization and priv drop */
|
||||
/*
|
||||
* ignore log messages we send to ourself (logd).
|
||||
* Such log messages are often generated by libraries we depend on
|
||||
* which use standard Android logging.
|
||||
*/
|
||||
return 0;
|
||||
if (last_pid == (pid_t) -1) {
|
||||
last_pid = getpid();
|
||||
}
|
||||
|
||||
if (logd_fd < 0) {
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
/*
|
||||
* struct {
|
||||
* // what we provide
|
||||
* // whate we provire to pstore
|
||||
* android_pmsg_log_header_t pmsg_header;
|
||||
* // what we provide to socket
|
||||
* android_log_header_t header;
|
||||
* // caller provides
|
||||
* union {
|
||||
|
@ -199,13 +200,20 @@ static int __write_to_log_kernel(log_id_t log_id, struct iovec *vec, size_t nr)
|
|||
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
|
||||
pmsg_header.magic = LOGGER_MAGIC;
|
||||
pmsg_header.len = sizeof(pmsg_header) + sizeof(header);
|
||||
pmsg_header.uid = last_uid;
|
||||
pmsg_header.pid = last_pid;
|
||||
|
||||
header.id = log_id;
|
||||
header.tid = gettid();
|
||||
header.realtime.tv_sec = ts.tv_sec;
|
||||
header.realtime.tv_nsec = ts.tv_nsec;
|
||||
|
||||
newVec[0].iov_base = (unsigned char *) &header;
|
||||
newVec[0].iov_len = sizeof(header);
|
||||
newVec[0].iov_base = (unsigned char *) &pmsg_header;
|
||||
newVec[0].iov_len = sizeof(pmsg_header);
|
||||
newVec[1].iov_base = (unsigned char *) &header;
|
||||
newVec[1].iov_len = sizeof(header);
|
||||
|
||||
for (payload_size = 0, i = header_length; i < nr + header_length; i++) {
|
||||
newVec[i].iov_base = vec[i - header_length].iov_base;
|
||||
|
@ -216,17 +224,38 @@ static int __write_to_log_kernel(log_id_t log_id, struct iovec *vec, size_t nr)
|
|||
if (newVec[i].iov_len) {
|
||||
++i;
|
||||
}
|
||||
payload_size = LOGGER_ENTRY_MAX_PAYLOAD;
|
||||
break;
|
||||
}
|
||||
}
|
||||
pmsg_header.len += payload_size;
|
||||
|
||||
if (pstore_fd >= 0) {
|
||||
TEMP_FAILURE_RETRY(writev(pstore_fd, newVec, i));
|
||||
}
|
||||
|
||||
if (last_uid == AID_LOGD) { /* logd, after initialization and priv drop */
|
||||
/*
|
||||
* ignore log messages we send to ourself (logd).
|
||||
* Such log messages are often generated by libraries we depend on
|
||||
* which use standard Android logging.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (logd_fd < 0) {
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
/*
|
||||
* The write below could be lost, but will never block.
|
||||
*
|
||||
* To logd, we drop the pmsg_header
|
||||
*
|
||||
* ENOTCONN occurs if logd dies.
|
||||
* EAGAIN occurs if logd is overloaded.
|
||||
*/
|
||||
ret = writev(logd_fd, newVec, i);
|
||||
ret = TEMP_FAILURE_RETRY(writev(logd_fd, newVec + 1, i - 1));
|
||||
if (ret < 0) {
|
||||
ret = -errno;
|
||||
if (ret == -ENOTCONN) {
|
||||
|
@ -242,7 +271,7 @@ static int __write_to_log_kernel(log_id_t log_id, struct iovec *vec, size_t nr)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = writev(logd_fd, newVec, i);
|
||||
ret = TEMP_FAILURE_RETRY(writev(logd_fd, newVec + 1, i - 1));
|
||||
if (ret < 0) {
|
||||
ret = -errno;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue