From: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>

The fatfs was ignoreing the I/O error on two points. If I/O error
happen while checking a free block entries, this checks the all
entries, and reports an I/O error on each entry.

This problem became cause of the disk full by syslogd.



 fs/fat/inode.c |   11 ++++++++---
 fs/fat/misc.c  |   22 +++++++++++++++++-----
 2 files changed, 25 insertions(+), 8 deletions(-)

diff -puN fs/fat/inode.c~fatfs-log-storm-fix fs/fat/inode.c
--- 25/fs/fat/inode.c~fatfs-log-storm-fix	2003-12-20 07:22:29.000000000 -0800
+++ 25-akpm/fs/fat/inode.c	2003-12-20 07:22:29.000000000 -0800
@@ -1047,7 +1047,7 @@ out_fail:
 
 int fat_statfs(struct super_block *sb, struct kstatfs *buf)
 {
-	int free, nr;
+	int free, nr, ret;
        
 	if (MSDOS_SB(sb)->free_clusters != -1)
 		free = MSDOS_SB(sb)->free_clusters;
@@ -1057,9 +1057,14 @@ int fat_statfs(struct super_block *sb, s
 			free = MSDOS_SB(sb)->free_clusters;
 		else {
 			free = 0;
-			for (nr = 2; nr < MSDOS_SB(sb)->clusters + 2; nr++)
-				if (fat_access(sb, nr, -1) == FAT_ENT_FREE)
+			for (nr = 2; nr < MSDOS_SB(sb)->clusters + 2; nr++) {
+				ret = fat_access(sb, nr, -1);
+				if (ret < 0) {
+					unlock_fat(sb);
+					return ret;
+				} else if (ret == FAT_ENT_FREE)
 					free++;
+			}
 			MSDOS_SB(sb)->free_clusters = free;
 		}
 		unlock_fat(sb);
diff -puN fs/fat/misc.c~fatfs-log-storm-fix fs/fat/misc.c
--- 25/fs/fat/misc.c~fatfs-log-storm-fix	2003-12-20 07:22:29.000000000 -0800
+++ 25-akpm/fs/fat/misc.c	2003-12-20 07:22:29.000000000 -0800
@@ -88,7 +88,7 @@ void fat_clusters_flush(struct super_blo
 int fat_add_cluster(struct inode *inode)
 {
 	struct super_block *sb = inode->i_sb;
-	int count, limit, new_dclus, new_fclus, last;
+	int ret, count, limit, new_dclus, new_fclus, last;
 	int cluster_bits = MSDOS_SB(sb)->cluster_bits;
 	
 	/* 
@@ -123,7 +123,12 @@ int fat_add_cluster(struct inode *inode)
 		new_dclus = new_dclus % limit;
 		if (new_dclus < 2)
 			new_dclus = 2;
-		if (fat_access(sb, new_dclus, -1) == FAT_ENT_FREE)
+
+		ret = fat_access(sb, new_dclus, -1);
+		if (ret < 0) {
+			unlock_fat(sb);
+			return ret;
+		} else if (ret == FAT_ENT_FREE)
 			break;
 	}
 	if (count >= MSDOS_SB(sb)->clusters) {
@@ -131,9 +136,14 @@ int fat_add_cluster(struct inode *inode)
 		unlock_fat(sb);
 		return -ENOSPC;
 	}
-	MSDOS_SB(sb)->prev_free = new_dclus;
 
-	fat_access(sb, new_dclus, FAT_ENT_EOF);
+	ret = fat_access(sb, new_dclus, FAT_ENT_EOF);
+	if (ret < 0) {
+		unlock_fat(sb);
+		return ret;
+	}
+
+	MSDOS_SB(sb)->prev_free = new_dclus;
 	if (MSDOS_SB(sb)->free_clusters != -1)
 		MSDOS_SB(sb)->free_clusters--;
 	fat_clusters_flush(sb);
@@ -142,7 +152,9 @@ int fat_add_cluster(struct inode *inode)
 
 	/* add new one to the last of the cluster chain */
 	if (last) {
-		fat_access(sb, last, new_dclus);
+		ret = fat_access(sb, last, new_dclus);
+		if (ret < 0)
+			return ret;
 		fat_cache_add(inode, new_fclus, new_dclus);
 	} else {
 		MSDOS_I(inode)->i_start = new_dclus;

_