@@ -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+
120145static 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
167202int 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" );
0 commit comments