Detect incomplete writes which may happen due to insufficient space on the output filesystem. Signed-off-by: Benjamin Poirier <bpoirier@xxxxxxxxxx> --- makedumpfile.c | 36 ++++++++++++++++++++---------------- makedumpfile.h | 3 ++- printk.c | 24 +++++++++++++++--------- 3 files changed, 37 insertions(+), 26 deletions(-) diff --git a/makedumpfile.c b/makedumpfile.c index aa05be7..9175a6a 100644 --- a/makedumpfile.c +++ b/makedumpfile.c @@ -4713,7 +4713,8 @@ is_bigendian(void) } int -write_and_check_space(int fd, void *buf, size_t buf_size, char *file_name) +write_and_check_space(int fd, void *buf, size_t buf_size, const char* desc, + const char *file_name) { int status, written_size = 0; @@ -4731,8 +4732,8 @@ write_and_check_space(int fd, void *buf, size_t buf_size, char *file_name) } if (errno == ENOSPC) info->flag_nospace = TRUE; - MSG("\nCan't write the dump file(%s). %s\n", - file_name, strerror(errno)); + MSG("\nCan't write the %s file(%s). %s\n", desc, file_name, + strerror(errno)); return FALSE; } return TRUE; @@ -4757,7 +4758,8 @@ write_buffer(int fd, off_t offset, void *buf, size_t buf_size, char *file_name) fdh.offset = bswap_64(offset); fdh.buf_size = bswap_64(buf_size); } - if (!write_and_check_space(fd, &fdh, sizeof(fdh), file_name)) + if (!write_and_check_space(fd, &fdh, sizeof(fdh), "dump", + file_name)) return FALSE; } else if (!info->flag_dry_run && lseek(fd, offset, SEEK_SET) == failed) { @@ -4765,7 +4767,7 @@ write_buffer(int fd, off_t offset, void *buf, size_t buf_size, char *file_name) return FALSE; } - if (!write_and_check_space(fd, buf, buf_size, file_name)) + if (!write_and_check_space(fd, buf, buf_size, "dump", file_name)) return FALSE; return TRUE; @@ -5281,7 +5283,7 @@ reset_bitmap_of_free_pages(unsigned long node_zones, struct cycle *cycle) } static int -dump_log_entry(char *logptr, int fp) +dump_log_entry(char *logptr, int fp, const char *file_name) { char *msg, *p, *bufp; unsigned int i, text_len, indent_len, buf_need; @@ -5307,7 +5309,8 @@ dump_log_entry(char *logptr, int fp) for (i = 0, p = msg; i < text_len; i++, p++) { if (bufp - buf >= sizeof(buf) - buf_need) { - if (write(info->fd_dumpfile, buf, bufp - buf) < 0) + if (!write_and_check_space(fp, buf, bufp - buf, "log", + file_name)) return FALSE; bufp = buf; } @@ -5322,10 +5325,7 @@ dump_log_entry(char *logptr, int fp) *bufp++ = '\n'; - if (write(info->fd_dumpfile, buf, bufp - buf) < 0) - return FALSE; - else - return TRUE; + return write_and_check_space(fp, buf, bufp - buf, "log", file_name); } /* @@ -5507,7 +5507,9 @@ dump_dmesg() ERRMSG("Can't open output file.\n"); goto out; } - if (write(info->fd_dumpfile, log_buffer, length_log) < 0) + if (!write_and_check_space(info->fd_dumpfile, log_buffer, + length_log, "log", + info->name_dumpfile)) goto out; if (!close_files_for_creating_dumpfile()) @@ -5532,7 +5534,8 @@ dump_dmesg() idx = log_first_idx; while (idx != log_next_idx) { log_ptr = log_from_idx(idx, log_buffer); - if (!dump_log_entry(log_ptr, info->fd_dumpfile)) + if (!dump_log_entry(log_ptr, info->fd_dumpfile, + info->name_dumpfile)) goto out; idx = log_next(idx, log_buffer); } @@ -6947,8 +6950,9 @@ write_start_flat_header() memset(buf, 0, sizeof(buf)); memcpy(buf, &fh, sizeof(fh)); - if (!write_and_check_space(info->fd_dumpfile, buf, MAX_SIZE_MDF_HEADER, - info->name_dumpfile)) + if (!write_and_check_space(info->fd_dumpfile, buf, + MAX_SIZE_MDF_HEADER, "dump", + info->name_dumpfile)) return FALSE; return TRUE; @@ -6966,7 +6970,7 @@ write_end_flat_header(void) fdh.buf_size = END_FLAG_FLAT_HEADER; if (!write_and_check_space(info->fd_dumpfile, &fdh, sizeof(fdh), - info->name_dumpfile)) + "dump", info->name_dumpfile)) return FALSE; return TRUE; diff --git a/makedumpfile.h b/makedumpfile.h index 79046f2..fb23efd 100644 --- a/makedumpfile.h +++ b/makedumpfile.h @@ -2510,7 +2510,8 @@ ulong htol(char *s, int flags); int hexadecimal(char *s, int count); int decimal(char *s, int count); int file_exists(char *file); - +int write_and_check_space(int fd, void *buf, size_t buf_size, + const char* desc, const char *file_name); int open_dump_file(void); int dump_lockless_dmesg(void); diff --git a/printk.c b/printk.c index 2af8562..e8501c7 100644 --- a/printk.c +++ b/printk.c @@ -53,7 +53,7 @@ static enum desc_state get_desc_state(unsigned long id, return DESC_STATE(state_val); } -static void +static int dump_record(struct prb_map *m, unsigned long id) { unsigned long long ts_nsec; @@ -80,7 +80,7 @@ dump_record(struct prb_map *m, unsigned long id) state_var = ULONG(desc + OFFSET(prb_desc.state_var) + OFFSET(atomic_long_t.counter)); state = get_desc_state(id, state_var); if (state != desc_committed && state != desc_finalized) - return; + return TRUE; begin = ULONG(desc + OFFSET(prb_desc.text_blk_lpos) + OFFSET(prb_data_blk_lpos.begin)) % m->text_data_ring_size; @@ -89,7 +89,7 @@ dump_record(struct prb_map *m, unsigned long id) /* skip data-less text blocks */ if (begin == next) - return; + return TRUE; inf = m->infos + ((id % m->desc_ring_count) * SIZE(printk_info)); @@ -121,8 +121,10 @@ dump_record(struct prb_map *m, unsigned long id) for (i = 0, p = text; i < text_len; i++, p++) { if (bufp - buf >= sizeof(buf) - buf_need) { - if (write(info->fd_dumpfile, buf, bufp - buf) < 0) - return; + if (!write_and_check_space(info->fd_dumpfile, buf, + bufp - buf, "log", + info->name_dumpfile)) + return FALSE; bufp = buf; } @@ -136,7 +138,8 @@ dump_record(struct prb_map *m, unsigned long id) *bufp++ = '\n'; - write(info->fd_dumpfile, buf, bufp - buf); + return write_and_check_space(info->fd_dumpfile, buf, bufp - buf, + "log", info->name_dumpfile); } int @@ -219,11 +222,14 @@ dump_lockless_dmesg(void) goto out_text_data; } - for (id = tail_id; id != head_id; id = (id + 1) & DESC_ID_MASK) - dump_record(&m, id); + for (id = tail_id; id != head_id; id = (id + 1) & DESC_ID_MASK) { + if (!dump_record(&m, id)) + goto out_text_data; + } /* dump head record */ - dump_record(&m, id); + if (!dump_record(&m, id)) + goto out_text_data; if (!close_files_for_creating_dumpfile()) goto out_text_data; -- 2.32.0 _______________________________________________ kexec mailing list kexec@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/kexec