]>
Commit | Line | Data |
---|---|---|
8649a31e AF |
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); |