1 diff --git a/fs/fat/fat.c b/fs/fat/fat.c
2 index 04a51db..bccc3e3 100644
5 @@ -823,8 +823,11 @@ int do_fat_read_at(const char *filename, loff_t pos, void *buffer,
8 __u32 root_cluster = 0;
16 if (read_bootsectandvi(&bs, &volinfo, &mydata->fatsize)) {
17 debug("Error: reading boot sector\n");
18 @@ -909,24 +912,54 @@ int do_fat_read_at(const char *filename, loff_t pos, void *buffer,
29 - debug("FAT read sect=%d, clust_size=%d, DIRENTSPERBLOCK=%zd\n",
30 - cursect, mydata->clust_size, DIRENTSPERBLOCK);
31 + if (mydata->fatsize == 32 || firsttime) {
32 + dir_ptr = do_fat_read_at_block;
36 + * FAT16 sector buffer modification:
37 + * Each loop, the second buffered block is moved to
38 + * the buffer begin, and two next sectors are read
39 + * next to the previously moved one. So the sector
40 + * buffer keeps always 3 sectors for fat16.
41 + * And the current sector is the buffer second sector
42 + * beside the "firsttime" read, when it is the first one.
44 + * PREFETCH_BLOCKS is 2 for FAT16 == loop[0:1]
45 + * n = computed root dir sector
46 + * loop | cursect-1 | cursect | cursect+1 |
47 + * 0 | sector n+0 | sector n+1 | none |
48 + * 1 | none | sector n+0 | sector n+1 |
49 + * 0 | sector n+1 | sector n+2 | sector n+3 |
50 + * 1 | sector n+3 | ...
52 + dir_ptr = (do_fat_read_at_block + mydata->sect_size);
53 + memcpy(do_fat_read_at_block, dir_ptr, mydata->sect_size);
58 + if (mydata->fatsize == 32 && buffer_blk_cnt)
62 + read_blk = (mydata->fatsize == 32) ?
63 + mydata->clust_size : PREFETCH_BLOCKS;
65 + debug("FAT read(sect=%d, cnt:%d), clust_size=%d, DIRENTSPERBLOCK=%zd\n",
66 + cursect, read_blk, mydata->clust_size, DIRENTSPERBLOCK);
68 - if (disk_read(cursect,
69 - (mydata->fatsize == 32) ?
70 - (mydata->clust_size) :
72 - do_fat_read_at_block) < 0) {
73 + if (disk_read(cursect, read_blk, dir_ptr) < 0) {
74 debug("Error: reading rootdir block\n");
78 - dentptr = (dir_entry *) do_fat_read_at_block;
79 + dentptr = (dir_entry *)dir_ptr;
82 for (i = 0; i < DIRENTSPERBLOCK; i++) {
83 @@ -951,7 +984,7 @@ int do_fat_read_at(const char *filename, loff_t pos, void *buffer,
87 - do_fat_read_at_block,
91 if (dols == LS_ROOT) {
92 @@ -1062,7 +1095,7 @@ int do_fat_read_at(const char *filename, loff_t pos, void *buffer,
94 goto rootdir_done; /* We got a match */
96 - debug("END LOOP: j=%d clust_size=%d\n", j,
97 + debug("END LOOP: buffer_blk_cnt=%d clust_size=%d\n", buffer_blk_cnt,
101 @@ -1070,10 +1103,10 @@ int do_fat_read_at(const char *filename, loff_t pos, void *buffer,
102 * root directory clusters when a cluster has been
103 * completely processed.
108 if (mydata->fatsize == 32) {
109 - if (j == mydata->clust_size) {
110 + if (buffer_blk_cnt == mydata->clust_size) {
114 @@ -1086,11 +1119,11 @@ int do_fat_read_at(const char *filename, loff_t pos, void *buffer,
115 root_cluster = nxt_clust;
119 + buffer_blk_cnt = 0;
122 - if (j == PREFETCH_BLOCKS)
124 + if (buffer_blk_cnt == PREFETCH_BLOCKS)
125 + buffer_blk_cnt = 0;
127 rootdir_end = (++cursect - mydata->rootdir_sect >=