]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/U-Boot-v2-fs-fat-read-fix-fat16-ls-read-issue.patch
kernel: update to 4.14.29
[ipfire-2.x.git] / src / patches / U-Boot-v2-fs-fat-read-fix-fat16-ls-read-issue.patch
CommitLineData
8649a31e
AF
1diff --git a/fs/fat/fat.c b/fs/fat/fat.c
2index 04a51db..bccc3e3 100644
3--- a/fs/fat/fat.c
4+++ b/fs/fat/fat.c
5@@ -823,8 +823,11 @@ int do_fat_read_at(const char *filename, loff_t pos, void *buffer,
6 int ret = -1;
7 int firsttime;
8 __u32 root_cluster = 0;
9+ __u32 read_blk;
10 int rootdir_size = 0;
11- int j;
12+ int buffer_blk_cnt;
13+ int do_read;
14+ __u8 *dir_ptr;
15
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,
19 isdir = 1;
20 }
21
22- j = 0;
23+ buffer_blk_cnt = 0;
24+ firsttime = 1;
25 while (1) {
26 int i;
27
28- if (j == 0) {
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;
33+ firsttime = 0;
34+ } else {
35+ /**
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.
43+ *
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 | ...
51+ */
52+ dir_ptr = (do_fat_read_at_block + mydata->sect_size);
53+ memcpy(do_fat_read_at_block, dir_ptr, mydata->sect_size);
54+ }
55+
56+ do_read = 1;
57+
58+ if (mydata->fatsize == 32 && buffer_blk_cnt)
59+ do_read = 0;
60+
61+ if (do_read) {
62+ read_blk = (mydata->fatsize == 32) ?
63+ mydata->clust_size : PREFETCH_BLOCKS;
64+
65+ debug("FAT read(sect=%d, cnt:%d), clust_size=%d, DIRENTSPERBLOCK=%zd\n",
66+ cursect, read_blk, mydata->clust_size, DIRENTSPERBLOCK);
67
68- if (disk_read(cursect,
69- (mydata->fatsize == 32) ?
70- (mydata->clust_size) :
71- PREFETCH_BLOCKS,
72- do_fat_read_at_block) < 0) {
73+ if (disk_read(cursect, read_blk, dir_ptr) < 0) {
74 debug("Error: reading rootdir block\n");
75 goto exit;
76 }
77
78- dentptr = (dir_entry *) do_fat_read_at_block;
79+ dentptr = (dir_entry *)dir_ptr;
80 }
81
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,
84
85 get_vfatname(mydata,
86 root_cluster,
87- do_fat_read_at_block,
88+ dir_ptr,
89 dentptr, l_name);
90
91 if (dols == LS_ROOT) {
92@@ -1062,7 +1095,7 @@ int do_fat_read_at(const char *filename, loff_t pos, void *buffer,
93
94 goto rootdir_done; /* We got a match */
95 }
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,
98 mydata->clust_size);
99
100 /*
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.
104 */
105- ++j;
106+ ++buffer_blk_cnt;
107 int rootdir_end = 0;
108 if (mydata->fatsize == 32) {
109- if (j == mydata->clust_size) {
110+ if (buffer_blk_cnt == mydata->clust_size) {
111 int nxtsect = 0;
112 int nxt_clust = 0;
113
114@@ -1086,11 +1119,11 @@ int do_fat_read_at(const char *filename, loff_t pos, void *buffer,
115 root_cluster = nxt_clust;
116
117 cursect = nxtsect;
118- j = 0;
119+ buffer_blk_cnt = 0;
120 }
121 } else {
122- if (j == PREFETCH_BLOCKS)
123- j = 0;
124+ if (buffer_blk_cnt == PREFETCH_BLOCKS)
125+ buffer_blk_cnt = 0;
126
127 rootdir_end = (++cursect - mydata->rootdir_sect >=
128 rootdir_size);