[lvm-devel] Detect unlikely write failure: persistent device cache, config file
Jim Meyering
jim at meyering.net
Tue Jul 17 14:57:05 UTC 2007
Jim Meyering <jim at meyering.net> wrote:
> Here's the patch I mentioned last week.
> The only real question is where the new (tiny) close_stream function belongs.
> Putting it in config.h is not ideal, but does work, since the two files
> that close written-to streams also include config.h.
>
> Would you like a new .h file as I did for lib/misc/last-component.h?
> This time, it'd be lib/misc/close-stream.h.
>
> Or maybe a pair of files:
> lib/misc/close-stream.c
> lib/misc/close-stream.h
There are a few more places where that was needed, and not all new
callers include config.h, so I've moved the close_stream definition
to lib.h. Here's an updated patch:
Detect write failure more reliably.
* lib/misc/lib.h (close_stream): New static inline function.
* lib/config/config.c (write_config_file): Use the new function
to detect and diagnose unlikely write failure.
* lib/filters/filter-persistent.c (persistent_filter_dump): Likewise.
* lib/format_text/archive.c (archive_vg): Likewise.
* lib/format_text/format-text.c (_vg_write_file): Likewise.
* lib/log/log.c (fin_log): Likewise.
* WHATS_NEW: Mention this.
Signed-off-by: Jim Meyering <jim at meyering.net>
---
WHATS_NEW | 1 +
lib/config/config.c | 7 +++++--
lib/filters/filter-persistent.c | 7 +++++--
lib/format_text/archive.c | 7 +++++--
lib/format_text/format-text.c | 7 +++++--
lib/log/log.c | 9 +++++++--
lib/misc/lib.h | 23 +++++++++++++++++++++++
7 files changed, 51 insertions(+), 10 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index 56f579e..b92450c 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.27 -
================================
+ Detect write failure more reliably.
Fix configure libdevmapper.h check when --with-dmdir is used.
Turn _add_pv_to_vg() into external library function add_pv_to_vg().
Add pv_by_path() external library function.
diff --git a/lib/config/config.c b/lib/config/config.c
index b5f0038..8f02e13 100644
--- a/lib/config/config.c
+++ b/lib/config/config.c
@@ -518,8 +518,11 @@ int write_config_file(struct config_tree *cft, const char *file,
argv++;
}
- if (outline.fp && fclose(outline.fp)) {
- log_sys_error("fclose", file);
+ if (outline.fp && close_stream(outline.fp) != 0) {
+ if (errno == 0)
+ log_error("%s: write error", file);
+ else
+ log_sys_error("fclose", file);
r = 0;
}
diff --git a/lib/filters/filter-persistent.c b/lib/filters/filter-persistent.c
index 91e7147..58a89ce 100644
--- a/lib/filters/filter-persistent.c
+++ b/lib/filters/filter-persistent.c
@@ -239,8 +239,11 @@ int persistent_filter_dump(struct dev_filter *f)
/* _write_array(pf, fp, "invalid_devices", PF_BAD_DEVICE); */
fprintf(fp, "}\n");
- if (fclose(fp)) {
- log_sys_error("fclose", tmp_file);
+ if (close_stream(fp) != 0) {
+ if (errno == 0)
+ log_error("%s: write error", tmp_file);
+ else
+ log_sys_error("fclose", tmp_file);
goto out;
}
diff --git a/lib/format_text/archive.c b/lib/format_text/archive.c
index c6af857..2cf0809 100644
--- a/lib/format_text/archive.c
+++ b/lib/format_text/archive.c
@@ -261,8 +261,11 @@ int archive_vg(struct volume_group *vg,
return 0;
}
- if (fclose(fp)) {
- log_sys_error("fclose", temp_file);
+ if (close_stream(fp) != 0) {
+ if (errno == 0)
+ log_error("%s: write error", temp_file);
+ else
+ log_sys_error("fclose", temp_file);
/* Leave file behind as evidence of failure */
return 0;
}
diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c
index e8bf6f6..5f280ff 100644
--- a/lib/format_text/format-text.c
+++ b/lib/format_text/format-text.c
@@ -892,8 +892,11 @@ static int _vg_write_file(struct format_instance *fid, struct volume_group *vg,
return 0;
}
- if (fclose(fp)) {
- log_sys_error("fclose", tc->path_edit);
+ if (close_stream(fp) != 0) {
+ if (errno == 0)
+ log_error("%s: write error", tc->path_edit);
+ else
+ log_sys_error("fclose", tc->path_edit);
return 0;
}
diff --git a/lib/log/log.c b/lib/log/log.c
index a67abe6..f3cac82 100644
--- a/lib/log/log.c
+++ b/lib/log/log.c
@@ -121,8 +121,13 @@ void fin_log(void)
}
if (_log_to_file) {
- if (fclose(_log_file))
- fprintf(stderr, "fclose() on log file failed: %s", strerror(errno));
+ if (close_stream(_log_file) != 0) {
+ if (errno == 0)
+ fprintf(stderr, "log file write failed");
+ else
+ fprintf(stderr, "fclose() on log file failed: %s",
+ strerror(errno));
+ }
_log_to_file = 0;
}
}
diff --git a/lib/misc/lib.h b/lib/misc/lib.h
index c3d5231..3d851cd 100644
--- a/lib/misc/lib.h
+++ b/lib/misc/lib.h
@@ -32,4 +32,27 @@
#include <libdevmapper.h>
+/*
+ * Close a stream, with nicer error checking than fclose's.
+ * Derived from gnulib's close-stream.c.
+ *
+ * Close STREAM. Return 0 if successful, nonzero (setting errno)
+ * otherwise. Upon failure, set errno to 0 if the error number
+ * cannot be determined.
+ */
+static inline int
+close_stream(FILE *stream)
+{
+ int prev_fail = ferror(stream);
+ int fclose_fail = fclose(stream);
+
+ /* If there was a previous failure, but fclose succeeded,
+ clear errno, since ferror does not set it, and its value
+ may be unrelated to the ferror-reported failure. */
+ if (prev_fail && !fclose_fail)
+ errno = 0;
+
+ return prev_fail || fclose_fail;
+}
+
#endif
--
1.5.3.rc1.27.ga5e40
More information about the lvm-devel
mailing list