From 2b8e95179655a84cf0b5421fe96cf67401b78064 Mon Sep 17 00:00:00 2001
From: Christoph Hellwig <hch@cloudius-systems.com>
Date: Mon, 11 Mar 2013 14:15:52 +0100
Subject: [PATCH] add handling of I/O errors

---
 fs/fatfs/fatfs_vnops.c | 5 +++--
 fs/vfs/kern_physio.c   | 8 +++++++-
 fs/vfs/vfs_bdev.c      | 5 ++++-
 fs/vfs/vfs_bio.c       | 5 +++--
 include/osv/bio.h      | 2 +-
 5 files changed, 18 insertions(+), 7 deletions(-)

diff --git a/fs/fatfs/fatfs_vnops.c b/fs/fatfs/fatfs_vnops.c
index 1b080ac5c..bd046f6a6 100644
--- a/fs/fatfs/fatfs_vnops.c
+++ b/fs/fatfs/fatfs_vnops.c
@@ -58,6 +58,7 @@ static int
 fat_rw_cluster(struct fatfsmount *fmp, u_long cluster, int rw)
 {
 	struct bio *bio;
+	int ret;
 
 	bio = alloc_bio();
 	if (!bio)
@@ -70,10 +71,10 @@ fat_rw_cluster(struct fatfsmount *fmp, u_long cluster, int rw)
 	bio->bio_bcount = fmp->sec_per_cl * SEC_SIZE;
 
 	bio->bio_dev->driver->devops->strategy(bio);
-	bio_wait(bio);
+	ret = bio_wait(bio);
 
 	destroy_bio(bio);
-	return 0;
+	return ret;
 }
 
 /*
diff --git a/fs/vfs/kern_physio.c b/fs/vfs/kern_physio.c
index 23c299425..ad824d721 100644
--- a/fs/vfs/kern_physio.c
+++ b/fs/vfs/kern_physio.c
@@ -28,13 +28,19 @@ destroy_bio(struct bio *bio)
 	free(bio);
 }
 
-void
+int
 bio_wait(struct bio *bio)
 {
+	int ret = 0;
+
 	pthread_mutex_lock(&bio->bio_mutex);
 	while (!(bio->bio_flags & BIO_DONE))
 		pthread_cond_wait(&bio->bio_wait, &bio->bio_mutex);
+	if (bio->bio_flags & BIO_ERROR)
+		ret = EIO;
 	pthread_mutex_unlock(&bio->bio_mutex);
+
+	return ret;
 }
 
 void
diff --git a/fs/vfs/vfs_bdev.c b/fs/vfs/vfs_bdev.c
index c16d5b491..90c415a68 100644
--- a/fs/vfs/vfs_bdev.c
+++ b/fs/vfs/vfs_bdev.c
@@ -97,6 +97,7 @@ int
 physio(struct device *dev, struct uio *uio, int ioflags)
 {
 	struct bio *bio;
+	int ret;
 
 	if (uio->uio_offset < 0)
 		return EINVAL;
@@ -125,8 +126,10 @@ physio(struct device *dev, struct uio *uio, int ioflags)
 
 		dev->driver->devops->strategy(bio);
 
-		bio_wait(bio);
+		ret = bio_wait(bio);
 		destroy_bio(bio);
+		if (ret)
+			return ret;
 
 	        uio->uio_iov++;
         	uio->uio_iovcnt--;
diff --git a/fs/vfs/vfs_bio.c b/fs/vfs/vfs_bio.c
index 33b42e6e5..fcee0028d 100755
--- a/fs/vfs/vfs_bio.c
+++ b/fs/vfs/vfs_bio.c
@@ -126,6 +126,7 @@ static int
 rw_buf(struct buf *bp, int rw)
 {
 	struct bio *bio;
+	int ret;
 
 	bio = alloc_bio();
 	if (!bio)
@@ -138,10 +139,10 @@ rw_buf(struct buf *bp, int rw)
 	bio->bio_bcount = BSIZE;
 
 	bio->bio_dev->driver->devops->strategy(bio);
-	bio_wait(bio);
+	ret = bio_wait(bio);
 
 	destroy_bio(bio);
-	return 0;
+	return ret;
 }
 
 /*
diff --git a/include/osv/bio.h b/include/osv/bio.h
index 340b1758e..183746d6f 100644
--- a/include/osv/bio.h
+++ b/include/osv/bio.h
@@ -98,7 +98,7 @@ struct bio {
 struct bio *	alloc_bio(void);
 void		destroy_bio(struct bio *bio);
 
-void		bio_wait(struct bio *bio);
+int		bio_wait(struct bio *bio);
 void		biodone(struct bio *bio, bool ok);
 
 __END_DECLS
-- 
GitLab