Skip to content
Snippets Groups Projects
Commit 4eaf9058 authored by Ken Sumrall's avatar Ken Sumrall
Browse files

Create a separate copy of the fsck logs

The log_target parameter of android_fork_execvp_ext() is now a
bit field, and multiple targets can be set to log to multiple
places at the same time.

The new target LOG_FILE will log to a file specified by the new
parameter file_path.

Set LOG_FILE and log to a file in /dev (the only writable filesystem
avilable when e2fsck runs) when invoking e2fsck in fs_mgr.

Bug: 10021342

Change-Id: I63baf644cc8c3afccc8345df27a74203b44d0400
parent 887f2892
Branches
Tags
No related merge requests found
...@@ -53,6 +53,8 @@ ...@@ -53,6 +53,8 @@
#define E2FSCK_BIN "/system/bin/e2fsck" #define E2FSCK_BIN "/system/bin/e2fsck"
#define MKSWAP_BIN "/system/bin/mkswap" #define MKSWAP_BIN "/system/bin/mkswap"
#define FSCK_LOG_FILE "/dev/fscklogs/log"
#define ZRAM_CONF_DEV "/sys/block/zram0/disksize" #define ZRAM_CONF_DEV "/sys/block/zram0/disksize"
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a))) #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
...@@ -484,7 +486,8 @@ static void check_fs(char *blk_device, char *fs_type, char *target) ...@@ -484,7 +486,8 @@ static void check_fs(char *blk_device, char *fs_type, char *target)
INFO("Running %s on %s\n", E2FSCK_BIN, blk_device); INFO("Running %s on %s\n", E2FSCK_BIN, blk_device);
ret = android_fork_execvp_ext(ARRAY_SIZE(e2fsck_argv), e2fsck_argv, ret = android_fork_execvp_ext(ARRAY_SIZE(e2fsck_argv), e2fsck_argv,
&status, true, LOG_KLOG, true); &status, true, LOG_KLOG | LOG_FILE,
true, FSCK_LOG_FILE);
if (ret < 0) { if (ret < 0) {
/* No need to check for error in fork, we can't really handle it now */ /* No need to check for error in fork, we can't really handle it now */
...@@ -801,7 +804,7 @@ int fs_mgr_swapon_all(struct fstab *fstab) ...@@ -801,7 +804,7 @@ int fs_mgr_swapon_all(struct fstab *fstab)
/* Initialize the swap area */ /* Initialize the swap area */
mkswap_argv[1] = fstab->recs[i].blk_device; mkswap_argv[1] = fstab->recs[i].blk_device;
err = android_fork_execvp_ext(ARRAY_SIZE(mkswap_argv), mkswap_argv, err = android_fork_execvp_ext(ARRAY_SIZE(mkswap_argv), mkswap_argv,
&status, true, LOG_KLOG, false); &status, true, LOG_KLOG, false, NULL);
if (err) { if (err) {
ERROR("mkswap failed for %s\n", fstab->recs[i].blk_device); ERROR("mkswap failed for %s\n", fstab->recs[i].blk_device);
ret = -1; ret = -1;
......
...@@ -44,11 +44,15 @@ __BEGIN_DECLS ...@@ -44,11 +44,15 @@ __BEGIN_DECLS
* send a signal twice to signal the caller (once for the child, and * send a signal twice to signal the caller (once for the child, and
* once for the caller) * once for the caller)
* log_target: Specify where to log the output of the child, either LOG_NONE, * log_target: Specify where to log the output of the child, either LOG_NONE,
* LOG_ALOG (for the Android system log) or LOG_KLOG (for the kernel * LOG_ALOG (for the Android system log), LOG_KLOG (for the kernel
* log). * log), or LOG_FILE (and you need to specify a pathname in the
* file_path argument, otherwise pass NULL). These are bit fields,
* and can be OR'ed together to log to multiple places.
* abbreviated: If true, capture up to the first 100 lines and last 4K of * abbreviated: If true, capture up to the first 100 lines and last 4K of
* output from the child. The abbreviated output is not dumped to * output from the child. The abbreviated output is not dumped to
* the specified log until the child has exited. * the specified log until the child has exited.
* file_path: if log_target has the LOG_FILE bit set, then this parameter
* must be set to the pathname of the file to log to.
* *
* Return value: * Return value:
* 0 when logwrap successfully run the child process and captured its status * 0 when logwrap successfully run the child process and captured its status
...@@ -58,13 +62,14 @@ __BEGIN_DECLS ...@@ -58,13 +62,14 @@ __BEGIN_DECLS
* *
*/ */
/* Values for the log_target parameter android_fork_exec_ext() */ /* Values for the log_target parameter android_fork_execvp_ext() */
#define LOG_NONE 0 #define LOG_NONE 0
#define LOG_ALOG 1 #define LOG_ALOG 1
#define LOG_KLOG 2 #define LOG_KLOG 2
#define LOG_FILE 4
int android_fork_execvp_ext(int argc, char* argv[], int *status, bool ignore_int_quit, int android_fork_execvp_ext(int argc, char* argv[], int *status, bool ignore_int_quit,
int log_target, bool abbreviated); int log_target, bool abbreviated, char *file_path);
/* Similar to above, except abbreviated logging is not available, and if logwrap /* Similar to above, except abbreviated logging is not available, and if logwrap
* is true, logging is to the Android system log, and if false, there is no * is true, logging is to the Android system log, and if false, there is no
...@@ -74,10 +79,9 @@ static inline int android_fork_execvp(int argc, char* argv[], int *status, ...@@ -74,10 +79,9 @@ static inline int android_fork_execvp(int argc, char* argv[], int *status,
bool ignore_int_quit, bool logwrap) bool ignore_int_quit, bool logwrap)
{ {
return android_fork_execvp_ext(argc, argv, status, ignore_int_quit, return android_fork_execvp_ext(argc, argv, status, ignore_int_quit,
(logwrap ? LOG_ALOG : LOG_NONE), false); (logwrap ? LOG_ALOG : LOG_NONE), false, NULL);
} }
__END_DECLS __END_DECLS
#endif /* __LIBS_LOGWRAP_H */ #endif /* __LIBS_LOGWRAP_H */
...@@ -93,6 +93,7 @@ struct log_info { ...@@ -93,6 +93,7 @@ struct log_info {
char klog_fmt[MAX_KLOG_TAG * 2]; char klog_fmt[MAX_KLOG_TAG * 2];
char *btag; char *btag;
bool abbreviated; bool abbreviated;
FILE *fp;
struct abbr_buf a_buf; struct abbr_buf a_buf;
}; };
...@@ -158,11 +159,15 @@ static void add_line_to_circular_buf(struct ending_buf *e_buf, ...@@ -158,11 +159,15 @@ static void add_line_to_circular_buf(struct ending_buf *e_buf,
/* Log directly to the specified log */ /* Log directly to the specified log */
static void do_log_line(struct log_info *log_info, char *line) { static void do_log_line(struct log_info *log_info, char *line) {
if (log_info->log_target == LOG_KLOG) { if (log_info->log_target & LOG_KLOG) {
klog_write(6, log_info->klog_fmt, line); klog_write(6, log_info->klog_fmt, line);
} else if (log_info->log_target == LOG_ALOG) { }
if (log_info->log_target & LOG_ALOG) {
ALOG(LOG_INFO, log_info->btag, "%s", line); ALOG(LOG_INFO, log_info->btag, "%s", line);
} }
if (log_info->log_target & LOG_FILE) {
fprintf(log_info->fp, "%s\n", line);
}
} }
/* Log to either the abbreviated buf, or directly to the specified log /* Log to either the abbreviated buf, or directly to the specified log
...@@ -290,7 +295,7 @@ static void print_abbr_buf(struct log_info *log_info) { ...@@ -290,7 +295,7 @@ static void print_abbr_buf(struct log_info *log_info) {
} }
static int parent(const char *tag, int parent_read, pid_t pid, static int parent(const char *tag, int parent_read, pid_t pid,
int *chld_sts, int log_target, bool abbreviated) { int *chld_sts, int log_target, bool abbreviated, char *file_path) {
int status = 0; int status = 0;
char buffer[4096]; char buffer[4096];
struct pollfd poll_fds[] = { struct pollfd poll_fds[] = {
...@@ -300,6 +305,7 @@ static int parent(const char *tag, int parent_read, pid_t pid, ...@@ -300,6 +305,7 @@ static int parent(const char *tag, int parent_read, pid_t pid,
}, },
}; };
int rc = 0; int rc = 0;
int fd;
struct log_info log_info; struct log_info log_info;
...@@ -309,8 +315,6 @@ static int parent(const char *tag, int parent_read, pid_t pid, ...@@ -309,8 +315,6 @@ static int parent(const char *tag, int parent_read, pid_t pid,
bool found_child = false; bool found_child = false;
char tmpbuf[256]; char tmpbuf[256];
log_info.log_target = log_target;
log_info.abbreviated = abbreviated;
log_info.btag = basename(tag); log_info.btag = basename(tag);
if (!log_info.btag) { if (!log_info.btag) {
log_info.btag = (char*) tag; log_info.btag = (char*) tag;
...@@ -323,11 +327,30 @@ static int parent(const char *tag, int parent_read, pid_t pid, ...@@ -323,11 +327,30 @@ static int parent(const char *tag, int parent_read, pid_t pid,
init_abbr_buf(&log_info.a_buf); init_abbr_buf(&log_info.a_buf);
} }
if (log_target == LOG_KLOG) { if (log_target & LOG_KLOG) {
snprintf(log_info.klog_fmt, sizeof(log_info.klog_fmt), snprintf(log_info.klog_fmt, sizeof(log_info.klog_fmt),
"<6>%.*s: %%s", MAX_KLOG_TAG, log_info.btag); "<6>%.*s: %%s", MAX_KLOG_TAG, log_info.btag);
} }
if ((log_target & LOG_FILE) && !file_path) {
/* No file_path specified, clear the LOG_FILE bit */
log_target &= ~LOG_FILE;
}
if (log_target & LOG_FILE) {
fd = open(file_path, O_WRONLY | O_CREAT, 0664);
if (fd < 0) {
ERROR("Cannot log to file %s\n", file_path);
log_target &= ~LOG_FILE;
} else {
lseek(fd, 0, SEEK_END);
log_info.fp = fdopen(fd, "a");
}
}
log_info.log_target = log_target;
log_info.abbreviated = abbreviated;
while (!found_child) { while (!found_child) {
if (TEMP_FAILURE_RETRY(poll(poll_fds, ARRAY_SIZE(poll_fds), -1)) < 0) { if (TEMP_FAILURE_RETRY(poll(poll_fds, ARRAY_SIZE(poll_fds), -1)) < 0) {
ERROR("poll failed\n"); ERROR("poll failed\n");
...@@ -432,6 +455,9 @@ static int parent(const char *tag, int parent_read, pid_t pid, ...@@ -432,6 +455,9 @@ static int parent(const char *tag, int parent_read, pid_t pid,
err_waitpid: err_waitpid:
err_poll: err_poll:
if (log_target & LOG_FILE) {
fclose(log_info.fp); /* Also closes underlying fd */
}
if (abbreviated) { if (abbreviated) {
free_abbr_buf(&log_info.a_buf); free_abbr_buf(&log_info.a_buf);
} }
...@@ -451,7 +477,7 @@ static void child(int argc, char* argv[]) { ...@@ -451,7 +477,7 @@ static void child(int argc, char* argv[]) {
} }
int android_fork_execvp_ext(int argc, char* argv[], int *status, bool ignore_int_quit, int android_fork_execvp_ext(int argc, char* argv[], int *status, bool ignore_int_quit,
int log_target, bool abbreviated) { int log_target, bool abbreviated, char *file_path) {
pid_t pid; pid_t pid;
int parent_ptty; int parent_ptty;
int child_ptty; int child_ptty;
...@@ -523,7 +549,8 @@ int android_fork_execvp_ext(int argc, char* argv[], int *status, bool ignore_int ...@@ -523,7 +549,8 @@ int android_fork_execvp_ext(int argc, char* argv[], int *status, bool ignore_int
sigaction(SIGQUIT, &ignact, &quitact); sigaction(SIGQUIT, &ignact, &quitact);
} }
rc = parent(argv[0], parent_ptty, pid, status, log_target, abbreviated); rc = parent(argv[0], parent_ptty, pid, status, log_target,
abbreviated, file_path);
} }
if (ignore_int_quit) { if (ignore_int_quit) {
......
...@@ -80,7 +80,7 @@ int main(int argc, char* argv[]) { ...@@ -80,7 +80,7 @@ int main(int argc, char* argv[]) {
} }
rc = android_fork_execvp_ext(argc, &argv[0], &status, true, rc = android_fork_execvp_ext(argc, &argv[0], &status, true,
log_target, abbreviated); log_target, abbreviated, NULL);
if (!rc) { if (!rc) {
if (WIFEXITED(status)) if (WIFEXITED(status))
rc = WEXITSTATUS(status); rc = WEXITSTATUS(status);
......
...@@ -133,6 +133,10 @@ loglevel 3 ...@@ -133,6 +133,10 @@ loglevel 3
# This is needed by any process that uses socket tagging. # This is needed by any process that uses socket tagging.
chmod 0644 /dev/xt_qtaguid chmod 0644 /dev/xt_qtaguid
# Create location for fs_mgr to store abbreviated output from filesystem
# checker programs.
mkdir /dev/fscklogs 0770 root system
on post-fs on post-fs
# once everything is setup, no need to modify / # once everything is setup, no need to modify /
mount rootfs rootfs / ro remount mount rootfs rootfs / ro remount
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment