[lvm-devel] Detect unlikely write failure: persistent device cache, config file

Jim Meyering jim at meyering.net
Mon Jul 16 12:16:36 UTC 2007


Hi Alasdair,

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

Here's the patch with the new static inline function in config.h:

-----------------------------------------------
Detect unlikely write failure: persistent device cache, config file
 * lib/config/config.h (close_stream): New static inline function.
 * lib/filters/filter-persistent.c (persistent_filter_dump): Use the
 new function to detect and diagnose unlikely write failure.
 * lib/config/config.c (write_config_file): Likewise.
 * WHATS_NEW: Mention this.


Signed-off-by: Jim Meyering <jim at meyering.net>
---
 WHATS_NEW                       |    1 +
 lib/config/config.c             |    7 +++++--
 lib/config/config.h             |   21 +++++++++++++++++++++
 lib/filters/filter-persistent.c |    7 +++++--
 4 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/WHATS_NEW b/WHATS_NEW
index 56f579e..8b44142 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
 Version 2.02.27 - 
 ================================
+  Detect unlikely write failure: persistent device cache, config file
   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/config/config.h b/lib/config/config.h
index ad27b0f..5658ecc 100644
--- a/lib/config/config.h
+++ b/lib/config/config.h
@@ -110,4 +110,25 @@ int get_config_str(const struct config_node *cn, const char *path,
 
 unsigned maybe_config_section(const char *str, unsigned len);
 
+/* 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
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;
 	}
 
-- 
1.5.3.rc1.27.ga5e40




More information about the lvm-devel mailing list