am 91581f19: Merge "liblog: add pstore write"
* commit '91581f19906ade01eabc6e10a7dac209e710117a': liblog: add pstore write
This commit is contained in:
commit
982421df45
2 changed files with 59 additions and 20 deletions
|
|
@ -24,7 +24,17 @@
|
||||||
#include <log/log.h>
|
#include <log/log.h>
|
||||||
#include <log/log_read.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__)) {
|
typedef struct __attribute__((__packed__)) {
|
||||||
typeof_log_id_t id;
|
typeof_log_id_t id;
|
||||||
uint16_t tid;
|
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 };
|
static int log_fds[(int)LOG_ID_MAX] = { -1, -1, -1, -1, -1 };
|
||||||
#else
|
#else
|
||||||
static int logd_fd = -1;
|
static int logd_fd = -1;
|
||||||
|
static int pstore_fd = -1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -110,6 +111,12 @@ static int __write_to_log_initialize()
|
||||||
logd_fd = -1;
|
logd_fd = -1;
|
||||||
close(i);
|
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);
|
i = socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0);
|
||||||
if (i < 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);
|
} while (ret == -EINTR);
|
||||||
#else
|
#else
|
||||||
static const unsigned header_length = 1;
|
static const unsigned header_length = 2;
|
||||||
struct iovec newVec[nr + header_length];
|
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;
|
struct timespec ts;
|
||||||
size_t i, payload_size;
|
size_t i, payload_size;
|
||||||
static uid_t last_uid = AID_ROOT; /* logd *always* starts up as AID_ROOT */
|
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? */
|
if (last_uid == AID_ROOT) { /* have we called to get the UID yet? */
|
||||||
last_uid = getuid();
|
last_uid = getuid();
|
||||||
}
|
}
|
||||||
if (last_uid == AID_LOGD) { /* logd, after initialization and priv drop */
|
if (last_pid == (pid_t) -1) {
|
||||||
/*
|
last_pid = getpid();
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* struct {
|
* 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;
|
* android_log_header_t header;
|
||||||
* // caller provides
|
* // caller provides
|
||||||
* union {
|
* 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);
|
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.id = log_id;
|
||||||
header.tid = gettid();
|
header.tid = gettid();
|
||||||
header.realtime.tv_sec = ts.tv_sec;
|
header.realtime.tv_sec = ts.tv_sec;
|
||||||
header.realtime.tv_nsec = ts.tv_nsec;
|
header.realtime.tv_nsec = ts.tv_nsec;
|
||||||
|
|
||||||
newVec[0].iov_base = (unsigned char *) &header;
|
newVec[0].iov_base = (unsigned char *) &pmsg_header;
|
||||||
newVec[0].iov_len = sizeof(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++) {
|
for (payload_size = 0, i = header_length; i < nr + header_length; i++) {
|
||||||
newVec[i].iov_base = vec[i - header_length].iov_base;
|
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) {
|
if (newVec[i].iov_len) {
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
payload_size = LOGGER_ENTRY_MAX_PAYLOAD;
|
||||||
break;
|
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.
|
* The write below could be lost, but will never block.
|
||||||
*
|
*
|
||||||
|
* To logd, we drop the pmsg_header
|
||||||
|
*
|
||||||
* ENOTCONN occurs if logd dies.
|
* ENOTCONN occurs if logd dies.
|
||||||
* EAGAIN occurs if logd is overloaded.
|
* 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) {
|
if (ret < 0) {
|
||||||
ret = -errno;
|
ret = -errno;
|
||||||
if (ret == -ENOTCONN) {
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = writev(logd_fd, newVec, i);
|
ret = TEMP_FAILURE_RETRY(writev(logd_fd, newVec + 1, i - 1));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
ret = -errno;
|
ret = -errno;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue