]> git.ipfire.org Git - ipfire-2.x.git/blob - src/patches/U-Boot-v2-fs-fat-read-fix-fat16-ls-read-issue.patch
Update libvirt to 2.1
[ipfire-2.x.git] / src / patches / U-Boot-v2-fs-fat-read-fix-fat16-ls-read-issue.patch
1 diff --git a/fs/fat/fat.c b/fs/fat/fat.c
2 index 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);