git » libjio » commit 840d25e

Let the user know when jfsck() has failed because of an I/O error

author Alberto Bertogli
2009-07-12 22:46:01 UTC
committer Alberto Bertogli
2009-07-12 23:09:54 UTC
parent 263a5e1d54f567aa76ba80fa752decbe1edca425

Let the user know when jfsck() has failed because of an I/O error

Currently, real I/O errors in some places inside jfsck() will be reported
as different things, and some of them, like J_ENOJOURNAL, may let the user
believe the file is consistent while it's not.

This patch fixes that behaviour by adding a new return value, J_EIO, that
jfsck() will use to report real I/O errors.

Signed-off-by: Alberto Bertogli <albertito@blitiri.com.ar>

libjio/check.c +37 -10
libjio/libjio.3 +6 -3
libjio/libjio.h +3 -0

diff --git a/libjio/check.c b/libjio/check.c
index 70a9f32..6a47a4f 100644
--- a/libjio/check.c
+++ b/libjio/check.c
@@ -115,7 +115,9 @@ enum jfsck_return jfsck(const char *name, const char *jdir,
 
 	fs.fd = open(name, O_RDWR | O_SYNC);
 	if (fs.fd < 0) {
-		ret = J_ENOENT;
+		ret = J_EIO;
+		if (errno == ENOENT)
+			ret = J_ENOENT;
 		goto exit;
 	}
 
@@ -141,14 +143,22 @@ enum jfsck_return jfsck(const char *name, const char *jdir,
 	}
 
 	rv = lstat(fs.jdir, &sinfo);
-	if (rv < 0 || !S_ISDIR(sinfo.st_mode)) {
+	if (rv < 0) {
+		ret = J_EIO;
+		if (errno == ENOENT)
+			ret = J_ENOJOURNAL;
+		goto exit;
+	}
+	if (!S_ISDIR(sinfo.st_mode)) {
 		ret = J_ENOJOURNAL;
 		goto exit;
 	}
 
 	fs.jdirfd = open(fs.jdir, O_RDONLY);
 	if (fs.jdirfd < 0) {
-		ret = J_ENOJOURNAL;
+		ret = J_EIO;
+		if (errno == ENOENT)
+			ret = J_ENOJOURNAL;
 		goto exit;
 	}
 
@@ -157,7 +167,9 @@ enum jfsck_return jfsck(const char *name, const char *jdir,
 	snprintf(jlockfile, PATH_MAX, "%s/%s", fs.jdir, "lock");
 	rv = open(jlockfile, O_RDWR | O_CREAT, 0600);
 	if (rv < 0) {
-		ret = J_ENOJOURNAL;
+		ret = J_EIO;
+		if (errno == ENOENT)
+			ret = J_ENOJOURNAL;
 		goto exit;
 	}
 	fs.jfd = rv;
@@ -165,13 +177,15 @@ enum jfsck_return jfsck(const char *name, const char *jdir,
 	fs.jmap = (unsigned int *) mmap(NULL, sizeof(unsigned int),
 			PROT_READ | PROT_WRITE, MAP_SHARED, fs.jfd, 0);
 	if (fs.jmap == MAP_FAILED) {
-		ret = J_ENOJOURNAL;
+		ret = J_EIO;
 		goto exit;
 	}
 
 	dir = opendir(fs.jdir);
 	if (dir == NULL) {
-		ret = J_ENOJOURNAL;
+		ret = J_EIO;
+		if (errno == ENOENT)
+			ret = J_ENOJOURNAL;
 		goto exit;
 	}
 
@@ -214,8 +228,13 @@ enum jfsck_return jfsck(const char *name, const char *jdir,
 		get_jtfile(&fs, i, tname);
 		tfd = open(tname, O_RDWR | O_SYNC, 0600);
 		if (tfd < 0) {
-			res->invalid++;
-			goto loop;
+			if (errno == ENOENT) {
+				res->invalid++;
+				goto loop;
+			} else {
+				ret = J_EIO;
+				goto exit;
+			}
 		}
 
 		/* try to lock the transaction file, if it's locked then it is
@@ -227,13 +246,21 @@ enum jfsck_return jfsck(const char *name, const char *jdir,
 		}
 
 		filelen = lseek(tfd, 0, SEEK_END);
+		if (filelen == 0) {
+			res->broken++;
+			goto loop;
+		} else if (filelen < 0) {
+			ret = J_EIO;
+			goto exit;
+		}
+
 		/* no overflow problems because we know the transaction size
 		 * is limited to SSIZE_MAX */
 		map = mmap((void *) 0, filelen, PROT_READ, MAP_SHARED, tfd, 0);
 		if (map == MAP_FAILED) {
-			res->broken++;
 			map = NULL;
-			goto loop;
+			ret = J_EIO;
+			goto exit;
 		}
 
 		rv = fill_trans(map, filelen, curts);
diff --git a/libjio/libjio.3 b/libjio/libjio.3
index b996839..9c89b7f 100644
--- a/libjio/libjio.3
+++ b/libjio/libjio.3
@@ -53,6 +53,7 @@ libjio - A library for Journaled I/O
     J_ENOJOURNAL = -2,	/* No journal associated with the given file */
     J_ENOMEM = -3,	/* Not enough free memory */
     J_ECLEANUP = -4,	/* Error cleaning the journal directory */
+    J_EIO = -5,		/* I/O error */
 };
 
 
@@ -146,11 +147,13 @@ summarizing the outcome of the operation. The error codes can be either
 .I J_ENOENT
 (no such file),
 .I J_ENOJOURNAL
-(no journal associated with that file) or
+(no journal associated with that file),
 .I J_ENOMEM
-(not enough free memory), and
+(not enough free memory),
 .I J_ECLEANUP
-(error cleaning the journal directory). There is also a program named
+(error cleaning the journal directory), and
+.I J_EIO
+(I/O error). There is also a program named
 .I jiofsck
 which is just a simple human frontend to this function.
 
diff --git a/libjio/libjio.h b/libjio/libjio.h
index 36cb299..562c8db 100644
--- a/libjio/libjio.h
+++ b/libjio/libjio.h
@@ -86,6 +86,9 @@ enum jfsck_return {
 
 	/** Error cleaning the journal directory */
 	J_ECLEANUP = -4,
+
+	/** I/O error */
+	J_EIO = -5,
 };