From 88de645de49ff732e6ba362dd0681ec0d3b2b184 Mon Sep 17 00:00:00 2001
From: Hannes Reinecke <hare@suse.de>
Date: Tue, 21 Jan 2014 09:16:46 +0100
Subject: [PATCH 1/2] blkid: stop scanning on I/O error

Whenever we fail to read from a device it's pointless to
continue with probing; we should be failing immediately.
Otherwise the system will continue logging I/O errors.

Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 shlibs/blkid/src/partitions/partitions.c   |  5 ++--
 shlibs/blkid/src/probe.c                   | 14 ++++++++--
 shlibs/blkid/src/superblocks/linux_raid.c  | 41 ++++++++++++++++++++----------
 shlibs/blkid/src/superblocks/superblocks.c | 23 +++++++++++------
 4 files changed, 57 insertions(+), 26 deletions(-)

diff --git a/shlibs/blkid/src/partitions/partitions.c b/shlibs/blkid/src/partitions/partitions.c
index 759d083..3bebc2a 100644
--- a/shlibs/blkid/src/partitions/partitions.c
+++ b/shlibs/blkid/src/partitions/partitions.c
@@ -524,7 +524,8 @@ static int idinfo_probe(blkid_probe pr, const struct blkid_idinfo *id)
 	if (pr->size <= 0 || (id->minsz && id->minsz > pr->size))
 		goto nothing;	/* the device is too small */
 
-	if (blkid_probe_get_idmag(pr, id, NULL, &mag))
+	rc = blkid_probe_get_idmag(pr, id, NULL, &mag);
+	if (rc != 0)
 		goto nothing;
 
 	/* final check by probing function */
@@ -532,7 +533,7 @@ static int idinfo_probe(blkid_probe pr, const struct blkid_idinfo *id)
 		DBG(DEBUG_LOWPROBE, printf(
 			"%s: ---> call probefunc()\n", id->name));
 		rc = id->probefunc(pr, mag);
-	        if (rc == -1) {
+		if (rc == -1) {
 			/* reset after error */
 			reset_partlist(pr, blkid_probe_get_partlist(pr));
 			DBG(DEBUG_LOWPROBE, printf(
diff --git a/shlibs/blkid/src/probe.c b/shlibs/blkid/src/probe.c
index 3429277..ad47b73 100644
--- a/shlibs/blkid/src/probe.c
+++ b/shlibs/blkid/src/probe.c
@@ -507,13 +507,18 @@ unsigned char *blkid_probe_get_buffer(blkid_probe pr,
 	if (!bf) {
 		ssize_t ret;
 
-		if (blkid_llseek(pr->fd, pr->off + off, SEEK_SET) < 0)
+		errno = 0;
+		if (blkid_llseek(pr->fd, pr->off + off, SEEK_SET) < 0) {
+			errno = 0;
 			return NULL;
+		}
 
 		/* allocate info and space for data by why call */
 		bf = calloc(1, sizeof(struct blkid_bufinfo) + len);
-		if (!bf)
+		if (!bf) {
+			errno = 0;
 			return NULL;
+		}
 
 		bf->data = ((unsigned char *) bf) + sizeof(struct blkid_bufinfo);
 		bf->len = len;
@@ -523,9 +528,12 @@ unsigned char *blkid_probe_get_buffer(blkid_probe pr,
 		DBG(DEBUG_LOWPROBE,
 			printf("\tbuffer read: off=%jd len=%jd\n", off, len));
 
+		errno = 0;
 		ret = read(pr->fd, bf->data, len);
 		if (ret != (ssize_t) len) {
 			free(bf);
+			if (ret >= 0)
+				errno = 0;
 			return NULL;
 		}
 		list_add_tail(&bf->bufs, &pr->buffers);
@@ -726,6 +734,8 @@ int blkid_probe_get_idmag(blkid_probe pr, const struct blkid_idinfo *id,
 		off = (mag->kboff + (mag->sboff >> 10)) << 10;
 		buf = blkid_probe_get_buffer(pr, off, 1024);
 
+		if (!buf && errno)
+			return -1;
 		if (buf && !memcmp(mag->magic,
 				buf + (mag->sboff & 0x3ff), mag->len)) {
 			DBG(DEBUG_LOWPROBE, printf(
diff --git a/shlibs/blkid/src/superblocks/linux_raid.c b/shlibs/blkid/src/superblocks/linux_raid.c
index e74f57d..2e9de29 100644
--- a/shlibs/blkid/src/superblocks/linux_raid.c
+++ b/shlibs/blkid/src/superblocks/linux_raid.c
@@ -12,6 +12,7 @@
 #include <unistd.h>
 #include <string.h>
 #include <stdint.h>
+#include <errno.h>
 
 #include "superblocks.h"
 
@@ -110,13 +111,17 @@ static int probe_raid0(blkid_probe pr, blkid_loff_t off)
 	uint64_t size;
 
 	if (pr->size < MD_RESERVED_BYTES)
-		return -1;
+		return 1;
 	mdp0 = (struct mdp0_super_block *)
 			blkid_probe_get_buffer(pr,
 				off,
 				sizeof(struct mdp0_super_block));
-	if (!mdp0)
-		return -1;
+	if (!mdp0) {
+		if (errno)
+			return -1;
+		else
+			return 1;
+	}
 
 	memset(uuid.ints, 0, sizeof(uuid.ints));
 
@@ -190,14 +195,18 @@ static int probe_raid1(blkid_probe pr, off_t off)
 			blkid_probe_get_buffer(pr,
 				off,
 				sizeof(struct mdp1_super_block));
-	if (!mdp1)
-		return -1;
+	if (!mdp1) {
+		if (errno)
+			return -1;
+		else
+			return 1;
+	}
 	if (le32_to_cpu(mdp1->magic) != MD_SB_MAGIC)
-		return -1;
+		return 1;
 	if (le32_to_cpu(mdp1->major_version) != 1)
-		return -1;
+		return 1;
 	if (le64_to_cpu(mdp1->super_offset) != off >> 9)
-		return -1;
+		return 1;
 	if (blkid_probe_set_uuid(pr, (unsigned char *) mdp1->set_uuid) != 0)
 		return -1;
 	if (blkid_probe_set_uuid_as(pr,
@@ -215,13 +224,15 @@ static int probe_raid1(blkid_probe pr, off_t off)
 int probe_raid(blkid_probe pr, const struct blkid_idmag *mag)
 {
 	const char *ver = NULL;
+	int rc = 1;
 
 	if (pr->size > MD_RESERVED_BYTES) {
 		/* version 0 at the end of the device */
 		uint64_t sboff = (pr->size & ~(MD_RESERVED_BYTES - 1))
-			         - MD_RESERVED_BYTES;
-		if (probe_raid0(pr, sboff) == 0)
-			return 0;
+				- MD_RESERVED_BYTES;
+		rc = probe_raid0(pr, sboff);
+		if (rc < 1)
+			return rc;
 
 		/* version 1.0 at the end of the device */
 		sboff = (pr->size & ~(0x1000 - 1)) - 0x2000;
@@ -231,9 +242,11 @@ int probe_raid(blkid_probe pr, const struct blkid_idmag *mag)
 
 	if (!ver) {
 		/* version 1.1 at the start of the device */
-		if (probe_raid1(pr, 0) == 0)
+		rc = probe_raid1(pr, 0);
+		if (rc < 0)
+			return rc;
+		if (rc == 0)
 			ver = "1.1";
-
 		/* version 1.2 at 4k offset from the start */
 		else if (probe_raid1(pr, 0x1000) == 0)
 			ver = "1.2";
@@ -243,7 +256,7 @@ int probe_raid(blkid_probe pr, const struct blkid_idmag *mag)
 		blkid_probe_set_version(pr, ver);
 		return 0;
 	}
-	return -1;
+	return rc;
 }
 
 
diff --git a/shlibs/blkid/src/superblocks/superblocks.c b/shlibs/blkid/src/superblocks/superblocks.c
index c3fbce8..5338f32 100644
--- a/shlibs/blkid/src/superblocks/superblocks.c
+++ b/shlibs/blkid/src/superblocks/superblocks.c
@@ -300,7 +300,7 @@ int blkid_known_fstype(const char *fstype)
  */
 static int superblocks_probe(blkid_probe pr, struct blkid_chain *chn)
 {
-	int i = 0;
+	int i = 0, rc = 1;
 
 	if (!pr || chn->idx < -1)
 		return -1;
@@ -346,19 +346,26 @@ static int superblocks_probe(blkid_probe pr, struct blkid_chain *chn)
 
 		DBG(DEBUG_LOWPROBE, printf("[%d] %s:\n", i, id->name));
 
-		if (blkid_probe_get_idmag(pr, id, &off, &mag))
+		rc = blkid_probe_get_idmag(pr, id, &off, &mag);
+		if (rc < 0)
+			break;
+		if (rc > 0)
 			continue;
 
 		/* final check by probing function */
 		if (id->probefunc) {
 			DBG(DEBUG_LOWPROBE, printf("\tcall probefunc()\n"));
-			if (id->probefunc(pr, mag) != 0) {
+			rc = id->probefunc(pr, mag);
+			if (rc != 0) {
 				blkid_probe_chain_reset_vals(pr, chn);
-				continue;
+				if (rc < 0)
+					break;
+				else
+					continue;
 			}
 		}
 
-		/* all cheks passed */
+		/* all checks passed */
 		if (chn->flags & BLKID_SUBLKS_TYPE)
 			blkid_probe_set_value(pr, "TYPE",
 				(unsigned char *) id->name,
@@ -378,9 +385,9 @@ static int superblocks_probe(blkid_probe pr, struct blkid_chain *chn)
 
 nothing:
 	DBG(DEBUG_LOWPROBE,
-		printf("<-- leaving probing loop (failed) [SUBLKS idx=%d]\n",
-		chn->idx));
-	return 1;
+		printf("<-- leaving probing loop (rc=%d) [SUBLKS idx=%d]\n",
+		       rc, chn->idx));
+	return rc;
 }
 
 /*
-- 
1.7.12.4

