Skip to content

Commit 8179a24

Browse files
authored
Merge pull request #122 from hclee/for-next
For next
2 parents 3507467 + 7d273bc commit 8179a24

File tree

3 files changed

+60
-25
lines changed

3 files changed

+60
-25
lines changed

fsck/de_iter.c

Lines changed: 57 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,11 @@ static int read_ahead_first_blocks(struct exfat_de_iter *iter)
4545
clus_count = iter->parent->size / exfat->clus_size;
4646

4747
if (clus_count > 1) {
48-
iter->ra_begin_offset = MAX((int)exfat->clus_size -
49-
iter->ra_partial_size, 0);
48+
iter->ra_begin_offset = 0;
5049
iter->ra_next_clus = 1;
5150
size = exfat->clus_size;
5251
} else {
53-
iter->ra_begin_offset = iter->ra_partial_size;
52+
iter->ra_begin_offset = 0;
5453
iter->ra_next_clus = 0;
5554
size = iter->ra_partial_size;
5655
}
@@ -73,7 +72,7 @@ static int read_ahead_next_blocks(struct exfat_de_iter *iter,
7372
struct exfat *exfat = iter->exfat;
7473
off_t device_offset;
7574
clus_t clus_count, ra_clus, ra_p_clus;
76-
unsigned int size, ra_offset;
75+
unsigned int size;
7776
int ret = 0;
7877

7978
clus_count = iter->parent->size / exfat->clus_size;
@@ -96,18 +95,16 @@ static int read_ahead_next_blocks(struct exfat_de_iter *iter,
9695
iter->ra_begin_offset = 0;
9796
}
9897
} else {
99-
ra_offset = offset + iter->ra_partial_size;
100-
if (ra_offset >= iter->ra_begin_offset &&
101-
ra_offset + iter->ra_partial_size <=
98+
if (offset >= iter->ra_begin_offset &&
99+
offset + iter->ra_partial_size <=
102100
exfat->clus_size) {
103-
device_offset = exfat_c2o(exfat, p_clus) + ra_offset;
101+
device_offset = exfat_c2o(exfat, p_clus) +
102+
offset + iter->ra_partial_size;
104103
ret = posix_fadvise(exfat->blk_dev->dev_fd,
105104
device_offset, iter->ra_partial_size,
106105
POSIX_FADV_WILLNEED);
107-
108106
iter->ra_begin_offset =
109-
ra_offset + iter->ra_partial_size;
110-
/* TODO: read blocks of the first child directory */
107+
offset + iter->ra_partial_size;
111108
}
112109
}
113110

@@ -117,12 +114,40 @@ static int read_ahead_next_blocks(struct exfat_de_iter *iter,
117114
#endif
118115
}
119116

117+
static int read_ahead_next_dir_blocks(struct exfat_de_iter *iter)
118+
{
119+
#ifdef POSIX_FADV_WILLNEED
120+
struct exfat *exfat = iter->exfat;
121+
struct list_head *current;
122+
struct exfat_inode *next_inode;
123+
off_t offset;
124+
125+
if (list_empty(&exfat->dir_list))
126+
return -EINVAL;
127+
128+
current = exfat->dir_list.next;
129+
if (iter->parent == list_entry(current, struct exfat_inode, list) &&
130+
current->next != &exfat->dir_list) {
131+
next_inode = list_entry(current->next, struct exfat_inode,
132+
list);
133+
offset = exfat_c2o(exfat, next_inode->first_clus);
134+
return posix_fadvise(exfat->blk_dev->dev_fd, offset,
135+
iter->ra_partial_size,
136+
POSIX_FADV_WILLNEED);
137+
}
138+
139+
return 0;
140+
#else
141+
return -ENOTSUP;
142+
#endif
143+
}
144+
120145
static ssize_t read_block(struct exfat_de_iter *iter, unsigned int block)
121146
{
122147
struct exfat *exfat = iter->exfat;
123148
struct buffer_desc *desc, *prev_desc;
124149
off_t device_offset;
125-
int ret;
150+
ssize_t ret;
126151

127152
desc = &iter->buffer_desc[block & 0x01];
128153
if (block == 0) {
@@ -154,14 +179,24 @@ static ssize_t read_block(struct exfat_de_iter *iter, unsigned int block)
154179
}
155180
}
156181

157-
read_ahead_next_blocks(iter,
158-
(block * iter->read_size) / exfat->clus_size,
159-
(block * iter->read_size) % exfat->clus_size,
160-
desc->p_clus);
161-
162182
device_offset = exfat_c2o(exfat, desc->p_clus) + desc->offset;
163-
return exfat_read(exfat->blk_dev->dev_fd, desc->buffer,
183+
ret = exfat_read(exfat->blk_dev->dev_fd, desc->buffer,
164184
iter->read_size, device_offset);
185+
if (ret <= 0)
186+
return ret;
187+
188+
/*
189+
* if a buffer is filled with dentries, read blocks ahead of time,
190+
* otherwise read blocks of the next directory in advance.
191+
*/
192+
if (desc->buffer[iter->read_size - 32] != EXFAT_LAST)
193+
read_ahead_next_blocks(iter,
194+
(block * iter->read_size) / exfat->clus_size,
195+
(block * iter->read_size) % exfat->clus_size,
196+
desc->p_clus);
197+
else
198+
read_ahead_next_dir_blocks(iter);
199+
return ret;
165200
}
166201

167202
int exfat_de_iter_init(struct exfat_de_iter *iter, struct exfat *exfat,
@@ -175,10 +210,14 @@ int exfat_de_iter_init(struct exfat_de_iter *iter, struct exfat *exfat,
175210
iter->ra_partial_size = MAX(4 * KB, exfat->clus_size / 2);
176211
else
177212
iter->ra_partial_size = exfat->clus_size / 4;
213+
iter->ra_partial_size = MIN(iter->ra_partial_size, 8 * KB);
178214

179215
if (!iter->buffer_desc)
180216
iter->buffer_desc = exfat->buffer_desc;
181217

218+
if (iter->parent->size == 0)
219+
return EOF;
220+
182221
read_ahead_first_blocks(iter);
183222
if (read_block(iter, 0) != (ssize_t)iter->read_size) {
184223
exfat_err("failed to read directory entries.\n");

fsck/fsck.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1090,11 +1090,8 @@ static int read_children(struct exfat *exfat, struct exfat_inode *dir)
10901090
struct exfat_inode *node = NULL;
10911091
struct exfat_dentry *dentry;
10921092
int dentry_count;
1093-
struct list_head sub_dir_list;
10941093
struct exfat_de_iter *de_iter;
10951094

1096-
INIT_LIST_HEAD(&sub_dir_list);
1097-
10981095
de_iter = &exfat->de_iter;
10991096
ret = exfat_de_iter_init(de_iter, exfat, dir);
11001097
if (ret == EOF)
@@ -1128,7 +1125,7 @@ static int read_children(struct exfat *exfat, struct exfat_inode *dir)
11281125
if ((node->attr & ATTR_SUBDIR) && node->size) {
11291126
node->parent = dir;
11301127
list_add_tail(&node->sibling, &dir->children);
1131-
list_add_tail(&node->list, &sub_dir_list);
1128+
list_add_tail(&node->list, &exfat->dir_list);
11321129
} else
11331130
free_exfat_inode(node);
11341131
break;
@@ -1168,7 +1165,6 @@ static int read_children(struct exfat *exfat, struct exfat_inode *dir)
11681165
exfat_de_iter_advance(de_iter, dentry_count);
11691166
}
11701167
out:
1171-
list_splice(&sub_dir_list, &exfat->dir_list);
11721168
exfat_de_iter_flush(de_iter);
11731169
return 0;
11741170
err:
@@ -1413,7 +1409,7 @@ static void exfat_show_info(struct exfat *exfat, const char *dev_name,
14131409
errors ? "checking stopped" : "clean",
14141410
exfat_stat.dir_count, exfat_stat.file_count);
14151411
if (errors || exfat->dirty)
1416-
printf("%s: errors %ld, fixed %ld\n", dev_name,
1412+
printf("%s: files corrupted %ld, files fixed %ld\n", dev_name,
14171413
exfat_stat.error_count, exfat_stat.fixed_count);
14181414
}
14191415

fsck/repair.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ static struct exfat_repair_problem problems[] = {
4141
{ER_FILE_SMALLER_SIZE, ERF_DEFAULT_NO, ERP_TRUNCATE},
4242
{ER_FILE_LARGER_SIZE, ERF_DEFAULT_NO, ERP_TRUNCATE},
4343
{ER_FILE_DUPLICATED_CLUS, ERF_DEFAULT_NO, ERP_TRUNCATE},
44-
{ER_FILE_ZERO_NOFAT, ERF_DEFAULT_NO, ERP_FIX},
44+
{ER_FILE_ZERO_NOFAT, ERF_DEFAULT_YES | ERF_PREEN_YES, ERP_FIX},
4545
};
4646

4747
static struct exfat_repair_problem *find_problem(er_problem_code_t prcode)

0 commit comments

Comments
 (0)