Răsfoiți Sursa

fs/fat: Do not write unmodified fat entries to disk

The code caches 6 sectors of the FAT. On FAT traversal, the old contents
needs to be flushed to disk, but only if any FAT entries had been modified.
Explicitly flag the buffer on modification.

Currently, creating a new file traverses the whole FAT up to the first
free cluster and rewrites the on-disk blocks.

Signed-off-by: Stefan Brüns <stefan.bruens@rwth-aachen.de>
Reviewed-by: Lukasz Majewski <l.majewski@samsung.com>
Stefan Brüns 8 ani în urmă
părinte
comite
3c0ed9c3a5
3 a modificat fișierele cu 21 adăugiri și 12 ștergeri
  1. 1 0
      fs/fat/fat.c
  2. 19 12
      fs/fat/fat_write.c
  3. 1 0
      include/fat.h

+ 1 - 0
fs/fat/fat.c

@@ -876,6 +876,7 @@ int do_fat_read_at(const char *filename, loff_t pos, void *buffer,
 	}
 	}
 
 
 	mydata->fatbufnum = -1;
 	mydata->fatbufnum = -1;
+	mydata->fat_dirty = 0;
 	mydata->fatbuf = memalign(ARCH_DMA_MINALIGN, FATBUFSIZE);
 	mydata->fatbuf = memalign(ARCH_DMA_MINALIGN, FATBUFSIZE);
 	if (mydata->fatbuf == NULL) {
 	if (mydata->fatbuf == NULL) {
 		debug("Error: allocating memory\n");
 		debug("Error: allocating memory\n");

+ 19 - 12
fs/fat/fat_write.c

@@ -104,13 +104,19 @@ static __u8 num_of_fats;
 /*
 /*
  * Write fat buffer into block device
  * Write fat buffer into block device
  */
  */
-static int flush_fat_buffer(fsdata *mydata)
+static int flush_dirty_fat_buffer(fsdata *mydata)
 {
 {
 	int getsize = FATBUFBLOCKS;
 	int getsize = FATBUFBLOCKS;
 	__u32 fatlength = mydata->fatlength;
 	__u32 fatlength = mydata->fatlength;
 	__u8 *bufptr = mydata->fatbuf;
 	__u8 *bufptr = mydata->fatbuf;
 	__u32 startblock = mydata->fatbufnum * FATBUFBLOCKS;
 	__u32 startblock = mydata->fatbufnum * FATBUFBLOCKS;
 
 
+	debug("debug: evicting %d, dirty: %d\n", mydata->fatbufnum,
+	      (int)mydata->fat_dirty);
+
+	if ((!mydata->fat_dirty) || (mydata->fatbufnum == -1))
+		return 0;
+
 	startblock += mydata->fat_sect;
 	startblock += mydata->fat_sect;
 
 
 	if (getsize > fatlength)
 	if (getsize > fatlength)
@@ -130,6 +136,7 @@ static int flush_fat_buffer(fsdata *mydata)
 			return -1;
 			return -1;
 		}
 		}
 	}
 	}
+	mydata->fat_dirty = 0;
 
 
 	return 0;
 	return 0;
 }
 }
@@ -186,10 +193,8 @@ static __u32 get_fatent_value(fsdata *mydata, __u32 entry)
 		startblock += mydata->fat_sect;	/* Offset from start of disk */
 		startblock += mydata->fat_sect;	/* Offset from start of disk */
 
 
 		/* Write back the fatbuf to the disk */
 		/* Write back the fatbuf to the disk */
-		if (mydata->fatbufnum != -1) {
-			if (flush_fat_buffer(mydata) < 0)
-				return -1;
-		}
+		if (flush_dirty_fat_buffer(mydata) < 0)
+			return -1;
 
 
 		if (disk_read(startblock, getsize, bufptr) < 0) {
 		if (disk_read(startblock, getsize, bufptr) < 0) {
 			debug("Error reading FAT blocks\n");
 			debug("Error reading FAT blocks\n");
@@ -494,10 +499,8 @@ static int set_fatent_value(fsdata *mydata, __u32 entry, __u32 entry_value)
 		if (getsize > fatlength)
 		if (getsize > fatlength)
 			getsize = fatlength;
 			getsize = fatlength;
 
 
-		if (mydata->fatbufnum != -1) {
-			if (flush_fat_buffer(mydata) < 0)
-				return -1;
-		}
+		if (flush_dirty_fat_buffer(mydata) < 0)
+			return -1;
 
 
 		if (disk_read(startblock, getsize, bufptr) < 0) {
 		if (disk_read(startblock, getsize, bufptr) < 0) {
 			debug("Error reading FAT blocks\n");
 			debug("Error reading FAT blocks\n");
@@ -506,6 +509,9 @@ static int set_fatent_value(fsdata *mydata, __u32 entry, __u32 entry_value)
 		mydata->fatbufnum = bufnum;
 		mydata->fatbufnum = bufnum;
 	}
 	}
 
 
+	/* Mark as dirty */
+	mydata->fat_dirty = 1;
+
 	/* Set the actual entry */
 	/* Set the actual entry */
 	switch (mydata->fatsize) {
 	switch (mydata->fatsize) {
 	case 32:
 	case 32:
@@ -645,7 +651,7 @@ static void flush_dir_table(fsdata *mydata, dir_entry **dentptr)
 
 
 	dir_curclust = dir_newclust;
 	dir_curclust = dir_newclust;
 
 
-	if (flush_fat_buffer(mydata) < 0)
+	if (flush_dirty_fat_buffer(mydata) < 0)
 		return;
 		return;
 
 
 	memset(get_dentfromdir_block, 0x00,
 	memset(get_dentfromdir_block, 0x00,
@@ -675,7 +681,7 @@ static int clear_fatent(fsdata *mydata, __u32 entry)
 	}
 	}
 
 
 	/* Flush fat buffer */
 	/* Flush fat buffer */
-	if (flush_fat_buffer(mydata) < 0)
+	if (flush_dirty_fat_buffer(mydata) < 0)
 		return -1;
 		return -1;
 
 
 	return 0;
 	return 0;
@@ -1011,6 +1017,7 @@ static int do_fat_write(const char *filename, void *buffer, loff_t size,
 	}
 	}
 
 
 	mydata->fatbufnum = -1;
 	mydata->fatbufnum = -1;
+	mydata->fat_dirty = 0;
 	mydata->fatbuf = memalign(ARCH_DMA_MINALIGN, FATBUFSIZE);
 	mydata->fatbuf = memalign(ARCH_DMA_MINALIGN, FATBUFSIZE);
 	if (mydata->fatbuf == NULL) {
 	if (mydata->fatbuf == NULL) {
 		debug("Error: allocating memory\n");
 		debug("Error: allocating memory\n");
@@ -1111,7 +1118,7 @@ static int do_fat_write(const char *filename, void *buffer, loff_t size,
 	debug("attempt to write 0x%llx bytes\n", *actwrite);
 	debug("attempt to write 0x%llx bytes\n", *actwrite);
 
 
 	/* Flush fat buffer */
 	/* Flush fat buffer */
-	ret = flush_fat_buffer(mydata);
+	ret = flush_dirty_fat_buffer(mydata);
 	if (ret) {
 	if (ret) {
 		printf("Error: flush fat buffer\n");
 		printf("Error: flush fat buffer\n");
 		goto exit;
 		goto exit;

+ 1 - 0
include/fat.h

@@ -169,6 +169,7 @@ typedef struct {
 	int	fatsize;	/* Size of FAT in bits */
 	int	fatsize;	/* Size of FAT in bits */
 	__u32	fatlength;	/* Length of FAT in sectors */
 	__u32	fatlength;	/* Length of FAT in sectors */
 	__u16	fat_sect;	/* Starting sector of the FAT */
 	__u16	fat_sect;	/* Starting sector of the FAT */
+	__u8	fat_dirty;      /* Set if fatbuf has been modified */
 	__u32	rootdir_sect;	/* Start sector of root directory */
 	__u32	rootdir_sect;	/* Start sector of root directory */
 	__u16	sect_size;	/* Size of sectors in bytes */
 	__u16	sect_size;	/* Size of sectors in bytes */
 	__u16	clust_size;	/* Size of clusters in sectors */
 	__u16	clust_size;	/* Size of clusters in sectors */