[U-Boot] [PATCH V3 05/10] fat: ff: read max contiguous file data

Stephen Warren swarren at wwwdotorg.org
Fri Oct 2 08:06:08 CEST 2015


Enhance f_read() to find the maximum contiguous set of clusters to read,
and read it all at once (which is fast) rather one by one (which is
slow).

Signed-off-by: Stephen Warren <swarren at wwwdotorg.org>
---
V3: New patch.
---
 fs/fat/ff.c | 45 ++++++++++++++++++++++++++++++++-------------
 1 file changed, 32 insertions(+), 13 deletions(-)

diff --git a/fs/fat/ff.c b/fs/fat/ff.c
index 478daa7d6b0b..0df5a9ddcf7c 100644
--- a/fs/fat/ff.c
+++ b/fs/fat/ff.c
@@ -2593,7 +2593,7 @@ FRESULT f_read (
 )
 {
 	FRESULT res;
-	DWORD clst, sect, remain;
+	DWORD clst, sect, remain, cfptr, cclst, maxclust;
 	UINT rcnt, cc;
 	BYTE csect, *rbuff = (BYTE*)buff;
 
@@ -2614,27 +2614,46 @@ FRESULT f_read (
 		if ((fp->fptr % SS(fp->fs)) == 0) {		/* On the sector boundary? */
 			csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1));	/* Sector offset in the cluster */
 			if (!csect) {						/* On the cluster boundary? */
-				if (fp->fptr == 0) {			/* On the top of the file? */
-					clst = fp->sclust;			/* Follow from the origin */
-				} else {						/* Middle or end of the file */
+				maxclust = 0;
+				cfptr = fp->fptr;
+				cclst = fp->clust;
+				for (;;) {
+					if (cfptr == 0) {			/* On the top of the file? */
+						clst = fp->sclust;			/* Follow from the origin */
+					} else {						/* Middle or end of the file */
 #if _USE_FASTSEEK
-					if (fp->cltbl)
-						clst = clmt_clust(fp, fp->fptr);	/* Get cluster# from the CLMT */
-					else
+						if (fp->cltbl)
+							clst = clmt_clust(fp, cfptr);	/* Get cluster# from the CLMT */
+						else
 #endif
-						clst = get_fat(fp->fs, fp->clust);	/* Follow cluster chain on the FAT */
+							clst = get_fat(fp->fs, cclst);	/* Follow cluster chain on the FAT */
+					}
+					if (clst < 2) ABORT(fp->fs, FR_INT_ERR);
+					if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
+					if (!maxclust) {
+						fp->clust = clst;				/* Update current cluster */
+					} else {
+						if (clst != (cclst + 1))
+							break;
+					}
+					maxclust++;
+					if ((maxclust * fp->fs->csize * SS(fp->fs)) >= btr)
+						break;
+					cclst = clst;
+					cfptr += fp->fs->csize * SS(fp->fs);
 				}
-				if (clst < 2) ABORT(fp->fs, FR_INT_ERR);
-				if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
-				fp->clust = clst;				/* Update current cluster */
+			} else {
+				maxclust = 1;
 			}
 			sect = clust2sect(fp->fs, fp->clust);	/* Get current sector */
+			if (maxclust > 1)
+				fp->clust += (maxclust - 1);
 			if (!sect) ABORT(fp->fs, FR_INT_ERR);
 			sect += csect;
 			cc = btr / SS(fp->fs);				/* When remaining bytes >= sector size, */
 			if (cc) {							/* Read maximum contiguous sectors directly */
-				if (csect + cc > fp->fs->csize)	/* Clip at cluster boundary */
-					cc = fp->fs->csize - csect;
+				if (csect + cc > (fp->fs->csize * maxclust))	/* Clip at cluster boundary */
+					cc = (fp->fs->csize * maxclust) - csect;
 				if (disk_read(fp->fs->drv, rbuff, sect, cc) != RES_OK)
 					ABORT(fp->fs, FR_DISK_ERR);
 #if !_FS_READONLY && _FS_MINIMIZE <= 2			/* Replace one of the read sectors with cached data if it contains a dirty sector */
-- 
1.9.1



More information about the U-Boot mailing list