patch-2.0.34 linux/fs/fat/cache.c

Next file: linux/fs/fat/dir.c
Previous file: linux/fs/fat/buffer.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.0.33/linux/fs/fat/cache.c linux/fs/fat/cache.c
@@ -12,6 +12,11 @@
 
 #include "msbuffer.h"
 
+#if 0
+#  define PRINTK(x) printk x
+#else
+#  define PRINTK(x)
+#endif
 
 static struct fat_cache *fat_cache,cache[FAT_CACHE];
 
@@ -22,11 +27,13 @@
 {
 	struct buffer_head *bh,*bh2,*c_bh,*c_bh2;
 	unsigned char *p_first,*p_last;
-	int first,last,next,copy,b;
+	int copy,first,last,next,b;
 
 	if ((unsigned) (nr-2) >= MSDOS_SB(sb)->clusters)
 		return 0;
-	if (MSDOS_SB(sb)->fat_bits == 16) {
+	if (MSDOS_SB(sb)->fat_bits == 32) {
+		first = last = nr*4;
+	} else if (MSDOS_SB(sb)->fat_bits == 16) {
 		first = last = nr*2;
 	} else {
 		first = nr*3/2;
@@ -46,13 +53,19 @@
 			return 0;
 		}
 	}
-	if (MSDOS_SB(sb)->fat_bits == 16) {
+	if (MSDOS_SB(sb)->fat_bits == 32) {
+		p_first = p_last = NULL; /* GCC needs that stuff */
+		next = CF_LE_L(((unsigned long *) bh->b_data)[(first &
+		    (SECTOR_SIZE-1)) >> 2]);
+		if (next >= 0xffffff7) next = -1;
+		PRINTK(("fat_bread: 0x%x, nr=0x%x, first=0x%x, next=0x%d\n", b, nr, first, next));
+
+	} else if (MSDOS_SB(sb)->fat_bits == 16) {
 		p_first = p_last = NULL; /* GCC needs that stuff */
 		next = CF_LE_W(((unsigned short *) bh->b_data)[(first &
 		    (SECTOR_SIZE-1)) >> 1]);
 		if (next >= 0xfff7) next = -1;
-	}
-	else {
+	} else {
 		p_first = &((unsigned char *) bh->b_data)[first & (SECTOR_SIZE-1)];
 		p_last = &((unsigned char *) bh2->b_data)[(first+1) &
 		    (SECTOR_SIZE-1)];
@@ -61,10 +74,13 @@
 		if (next >= 0xff7) next = -1;
 	}
 	if (new_value != -1) {
-		if (MSDOS_SB(sb)->fat_bits == 16)
+		if (MSDOS_SB(sb)->fat_bits == 32) {
+			((unsigned long *) bh->b_data)[(first & (SECTOR_SIZE-1)) >>
+			    2] = CT_LE_L(new_value);
+		} else if (MSDOS_SB(sb)->fat_bits == 16) {
 			((unsigned short *) bh->b_data)[(first & (SECTOR_SIZE-1)) >>
 			    1] = CT_LE_W(new_value);
-		else {
+		} else {
 			if (nr & 1) {
 				*p_first = (*p_first & 0xf) | (new_value << 4);
 				*p_last = new_value >> 4;
@@ -239,16 +255,17 @@
 	return nr;
 }
 
-
 int fat_smap(struct inode *inode,int sector)
 {
 	struct msdos_sb_info *sb;
 	int cluster,offset;
 
 	sb = MSDOS_SB(inode->i_sb);
-	if (inode->i_ino == MSDOS_ROOT_INO || (S_ISDIR(inode->i_mode) &&
-	    !MSDOS_I(inode)->i_start)) {
-		if (sector >= sb->dir_entries >> MSDOS_DPS_BITS) return 0;
+	if ((sb->fat_bits != 32) &&
+	    (inode->i_ino == MSDOS_ROOT_INO || (S_ISDIR(inode->i_mode) &&
+	     !MSDOS_I(inode)->i_start))) {
+		if (sector >= sb->dir_entries >> MSDOS_DPS_BITS)
+			return 0;
 		return sector+sb->dir_start;
 	}
 	cluster = sector/sb->cluster_size;
@@ -264,6 +281,7 @@
 int fat_free(struct inode *inode,int skip)
 {
 	int nr,last;
+	int fat_bits;
 
 	if (!(nr = MSDOS_I(inode)->i_start)) return 0;
 	last = 0;
@@ -275,11 +293,13 @@
 			return -EIO;
 		}
 	}
-	if (last)
-		fat_access(inode->i_sb,last,MSDOS_SB(inode->i_sb)->fat_bits ==
-		    12 ? 0xff8 : 0xfff8);
-	else {
+	if (last) {
+		fat_bits = MSDOS_SB(inode->i_sb)->fat_bits;
+		fat_access(inode->i_sb,last,fat_bits == 12 ? EOF_FAT12 :
+			   fat_bits == 16 ? EOF_FAT16 : EOF_FAT32);
+	} else {
 		MSDOS_I(inode)->i_start = 0;
+		MSDOS_I(inode)->i_logstart = 0;
 		inode->i_dirt = 1;
 	}
 	lock_fat(inode->i_sb);
@@ -288,8 +308,12 @@
 			fat_fs_panic(inode->i_sb,"fat_free: deleting beyond EOF");
 			break;
 		}
-		if (MSDOS_SB(inode->i_sb)->free_clusters != -1)
+		if (MSDOS_SB(inode->i_sb)->free_clusters != -1) {
 			MSDOS_SB(inode->i_sb)->free_clusters++;
+			if (MSDOS_SB(inode->i_sb)->fat_bits == 32) {
+				fat_clusters_flush(inode->i_sb);
+			}
+		}
 		inode->i_blocks -= MSDOS_SB(inode->i_sb)->cluster_size;
 	}
 	unlock_fat(inode->i_sb);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov