[PATCH v2 makedumpfile 2/3] Dump dmesg using write_and_check_space()

Benjamin Poirier bpoirier at nvidia.com
Thu Jul 8 00:06:10 PDT 2021


Detect incomplete writes which may happen due to insufficient space on the
output filesystem.

Signed-off-by: Benjamin Poirier <bpoirier at nvidia.com>
---
 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




More information about the kexec mailing list