diff options
author | David Woodhouse <dwmw2@infradead.org> | 2006-05-20 11:13:34 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@infradead.org> | 2006-05-20 11:13:34 -0400 |
commit | 9641b784ff82cf0a48a6c70ef9867f5fd728de67 (patch) | |
tree | 40d7bbc06ee5e54560ea7e7dabe75ac01a72e00c /fs/jffs2/scan.c | |
parent | 6c8b44abc86a3e23dd1a22c0ee187f06bd7c7f5d (diff) |
[JFFS2] Optimise reading of eraseblock summary nodes
This improves the time to mount 512MiB of NAND flash on my OLPC prototype
by about 4%. We used to read the last page of the eraseblock twice -- once
to find the offset of the summary node, and again to actually _read_ the
summary node. Now we read the last page only once, and read more only if
we need to.
We also don't allocate a new buffer just for the summary code -- we use
the buffer which was already allocated for the scan. Better still, if the
'buffer' for the scan is actually just a pointer directly into NOR flash,
we use that too, avoiding the memcpy() which we used to do.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Diffstat (limited to 'fs/jffs2/scan.c')
-rw-r--r-- | fs/jffs2/scan.c | 74 |
1 files changed, 56 insertions, 18 deletions
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index 352ada892f3e..2a24b44662bb 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c | |||
@@ -306,11 +306,12 @@ int jffs2_scan_classify_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *je | |||
306 | return BLK_STATE_ALLDIRTY; | 306 | return BLK_STATE_ALLDIRTY; |
307 | } | 307 | } |
308 | 308 | ||
309 | /* Called with 'buf_size == 0' if buf is in fact a pointer _directly_ into | ||
310 | the flash, XIP-style */ | ||
309 | static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, | 311 | static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, |
310 | unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s) { | 312 | unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s) { |
311 | struct jffs2_unknown_node *node; | 313 | struct jffs2_unknown_node *node; |
312 | struct jffs2_unknown_node crcnode; | 314 | struct jffs2_unknown_node crcnode; |
313 | struct jffs2_sum_marker *sm; | ||
314 | uint32_t ofs, prevofs; | 315 | uint32_t ofs, prevofs; |
315 | uint32_t hdr_crc, buf_ofs, buf_len; | 316 | uint32_t hdr_crc, buf_ofs, buf_len; |
316 | int err; | 317 | int err; |
@@ -344,32 +345,69 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo | |||
344 | #endif | 345 | #endif |
345 | 346 | ||
346 | if (jffs2_sum_active()) { | 347 | if (jffs2_sum_active()) { |
347 | sm = kmalloc(sizeof(struct jffs2_sum_marker), GFP_KERNEL); | 348 | struct jffs2_sum_marker *sm; |
348 | if (!sm) { | 349 | void *sumptr = NULL; |
349 | return -ENOMEM; | 350 | uint32_t sumlen; |
350 | } | 351 | |
352 | if (!buf_size) { | ||
353 | /* XIP case. Just look, point at the summary if it's there */ | ||
354 | sm = (void *)buf + jeb->offset - sizeof(*sm); | ||
355 | if (je32_to_cpu(sm->magic) == JFFS2_SUM_MAGIC) { | ||
356 | sumptr = buf + je32_to_cpu(sm->offset); | ||
357 | sumlen = c->sector_size - je32_to_cpu(sm->offset); | ||
358 | } | ||
359 | } else { | ||
360 | /* If NAND flash, read a whole page of it. Else just the end */ | ||
361 | if (c->wbuf_pagesize) | ||
362 | buf_len = c->wbuf_pagesize; | ||
363 | else | ||
364 | buf_len = sizeof(*sm); | ||
365 | |||
366 | /* Read as much as we want into the _end_ of the preallocated buffer */ | ||
367 | err = jffs2_fill_scan_buf(c, buf + buf_size - buf_len, | ||
368 | jeb->offset + c->sector_size - buf_len, | ||
369 | buf_len); | ||
370 | if (err) | ||
371 | return err; | ||
372 | |||
373 | sm = (void *)buf + buf_size - sizeof(*sm); | ||
374 | if (je32_to_cpu(sm->magic) == JFFS2_SUM_MAGIC) { | ||
375 | sumlen = c->sector_size - je32_to_cpu(sm->offset); | ||
376 | sumptr = buf + buf_size - sumlen; | ||
377 | |||
378 | /* Now, make sure the summary itself is available */ | ||
379 | if (sumlen > buf_size) { | ||
380 | /* Need to kmalloc for this. */ | ||
381 | sumptr = kmalloc(sumlen, GFP_KERNEL); | ||
382 | if (!sumptr) | ||
383 | return -ENOMEM; | ||
384 | memcpy(sumptr + sumlen - buf_len, buf + buf_size - buf_len, buf_len); | ||
385 | } | ||
386 | if (buf_len < sumlen) { | ||
387 | /* Need to read more so that the entire summary node is present */ | ||
388 | err = jffs2_fill_scan_buf(c, sumptr, | ||
389 | jeb->offset + c->sector_size - sumlen, | ||
390 | sumlen - buf_len); | ||
391 | if (err) | ||
392 | return err; | ||
393 | } | ||
394 | } | ||
351 | 395 | ||
352 | err = jffs2_fill_scan_buf(c, (unsigned char *) sm, jeb->offset + c->sector_size - | ||
353 | sizeof(struct jffs2_sum_marker), sizeof(struct jffs2_sum_marker)); | ||
354 | if (err) { | ||
355 | kfree(sm); | ||
356 | return err; | ||
357 | } | 396 | } |
358 | 397 | ||
359 | if (je32_to_cpu(sm->magic) == JFFS2_SUM_MAGIC ) { | 398 | if (sumptr) { |
360 | err = jffs2_sum_scan_sumnode(c, jeb, je32_to_cpu(sm->offset), &pseudo_random); | 399 | err = jffs2_sum_scan_sumnode(c, jeb, sumptr, sumlen, &pseudo_random); |
361 | if (err) { | 400 | if (err) |
362 | kfree(sm); | ||
363 | return err; | 401 | return err; |
364 | } | 402 | if (buf_size && sumlen > buf_size) |
403 | kfree(sumptr); | ||
365 | } | 404 | } |
366 | |||
367 | kfree(sm); | ||
368 | } | 405 | } |
369 | 406 | ||
370 | buf_ofs = jeb->offset; | 407 | buf_ofs = jeb->offset; |
371 | 408 | ||
372 | if (!buf_size) { | 409 | if (!buf_size) { |
410 | /* This is the XIP case -- we're reading _directly_ from the flash chip */ | ||
373 | buf_len = c->sector_size; | 411 | buf_len = c->sector_size; |
374 | } else { | 412 | } else { |
375 | buf_len = EMPTY_SCAN_SIZE(c->sector_size); | 413 | buf_len = EMPTY_SCAN_SIZE(c->sector_size); |