diff options
Diffstat (limited to 'fs/jffs2/scan.c')
-rw-r--r-- | fs/jffs2/scan.c | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index cf55b221fc2b..f09689e320fe 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c | |||
@@ -306,6 +306,136 @@ 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 | #ifdef CONFIG_JFFS2_FS_XATTR | ||
310 | static int jffs2_scan_xattr_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, | ||
311 | struct jffs2_raw_xattr *rx, uint32_t ofs, | ||
312 | struct jffs2_summary *s) | ||
313 | { | ||
314 | struct jffs2_xattr_datum *xd; | ||
315 | struct jffs2_raw_node_ref *raw; | ||
316 | uint32_t totlen, crc; | ||
317 | |||
318 | crc = crc32(0, rx, sizeof(struct jffs2_raw_xattr) - 4); | ||
319 | if (crc != je32_to_cpu(rx->node_crc)) { | ||
320 | if (je32_to_cpu(rx->node_crc) != 0xffffffff) | ||
321 | JFFS2_WARNING("node CRC failed at %#08x, read=%#08x, calc=%#08x\n", | ||
322 | ofs, je32_to_cpu(rx->node_crc), crc); | ||
323 | DIRTY_SPACE(je32_to_cpu(rx->totlen)); | ||
324 | return 0; | ||
325 | } | ||
326 | |||
327 | totlen = PAD(sizeof(*rx) + rx->name_len + 1 + je16_to_cpu(rx->value_len)); | ||
328 | if (totlen != je32_to_cpu(rx->totlen)) { | ||
329 | JFFS2_WARNING("node length mismatch at %#08x, read=%u, calc=%u\n", | ||
330 | ofs, je32_to_cpu(rx->totlen), totlen); | ||
331 | DIRTY_SPACE(je32_to_cpu(rx->totlen)); | ||
332 | return 0; | ||
333 | } | ||
334 | |||
335 | raw = jffs2_alloc_raw_node_ref(); | ||
336 | if (!raw) | ||
337 | return -ENOMEM; | ||
338 | |||
339 | xd = jffs2_setup_xattr_datum(c, je32_to_cpu(rx->xid), je32_to_cpu(rx->version)); | ||
340 | if (IS_ERR(xd)) { | ||
341 | jffs2_free_raw_node_ref(raw); | ||
342 | if (PTR_ERR(xd) == -EEXIST) { | ||
343 | DIRTY_SPACE(PAD(je32_to_cpu(rx->totlen))); | ||
344 | return 0; | ||
345 | } | ||
346 | return PTR_ERR(xd); | ||
347 | } | ||
348 | xd->xprefix = rx->xprefix; | ||
349 | xd->name_len = rx->name_len; | ||
350 | xd->value_len = je16_to_cpu(rx->value_len); | ||
351 | xd->data_crc = je32_to_cpu(rx->data_crc); | ||
352 | xd->node = raw; | ||
353 | |||
354 | raw->__totlen = totlen; | ||
355 | raw->flash_offset = ofs | REF_PRISTINE; | ||
356 | raw->next_phys = NULL; | ||
357 | raw->next_in_ino = (void *)xd; | ||
358 | if (!jeb->first_node) | ||
359 | jeb->first_node = raw; | ||
360 | if (jeb->last_node) | ||
361 | jeb->last_node->next_phys = raw; | ||
362 | jeb->last_node = raw; | ||
363 | |||
364 | USED_SPACE(PAD(je32_to_cpu(rx->totlen))); | ||
365 | if (jffs2_sum_active()) | ||
366 | jffs2_sum_add_xattr_mem(s, rx, ofs - jeb->offset); | ||
367 | dbg_xattr("scaning xdatum at %#08x (xid=%u, version=%u)\n", | ||
368 | ofs, xd->xid, xd->version); | ||
369 | return 0; | ||
370 | } | ||
371 | |||
372 | static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, | ||
373 | struct jffs2_raw_xref *rr, uint32_t ofs, | ||
374 | struct jffs2_summary *s) | ||
375 | { | ||
376 | struct jffs2_xattr_ref *ref; | ||
377 | struct jffs2_raw_node_ref *raw; | ||
378 | uint32_t crc; | ||
379 | |||
380 | crc = crc32(0, rr, sizeof(*rr) - 4); | ||
381 | if (crc != je32_to_cpu(rr->node_crc)) { | ||
382 | if (je32_to_cpu(rr->node_crc) != 0xffffffff) | ||
383 | JFFS2_WARNING("node CRC failed at %#08x, read=%#08x, calc=%#08x\n", | ||
384 | ofs, je32_to_cpu(rr->node_crc), crc); | ||
385 | DIRTY_SPACE(PAD(je32_to_cpu(rr->totlen))); | ||
386 | return 0; | ||
387 | } | ||
388 | |||
389 | if (PAD(sizeof(struct jffs2_raw_xref)) != je32_to_cpu(rr->totlen)) { | ||
390 | JFFS2_WARNING("node length mismatch at %#08x, read=%u, calc=%u\n", | ||
391 | ofs, je32_to_cpu(rr->totlen), | ||
392 | PAD(sizeof(struct jffs2_raw_xref))); | ||
393 | DIRTY_SPACE(je32_to_cpu(rr->totlen)); | ||
394 | return 0; | ||
395 | } | ||
396 | |||
397 | ref = jffs2_alloc_xattr_ref(); | ||
398 | if (!ref) | ||
399 | return -ENOMEM; | ||
400 | |||
401 | raw = jffs2_alloc_raw_node_ref(); | ||
402 | if (!raw) { | ||
403 | jffs2_free_xattr_ref(ref); | ||
404 | return -ENOMEM; | ||
405 | } | ||
406 | |||
407 | /* BEFORE jffs2_build_xattr_subsystem() called, | ||
408 | * ref->xid is used to store 32bit xid, xd is not used | ||
409 | * ref->ino is used to store 32bit inode-number, ic is not used | ||
410 | * Thoes variables are declared as union, thus using those | ||
411 | * are exclusive. In a similar way, ref->ilist is temporarily | ||
412 | * used to chain all xattr_ref object. It's re-chained to | ||
413 | * jffs2_inode_cache in jffs2_build_xattr_subsystem() correctly. | ||
414 | */ | ||
415 | ref->node = raw; | ||
416 | ref->ino = je32_to_cpu(rr->ino); | ||
417 | ref->xid = je32_to_cpu(rr->xid); | ||
418 | list_add_tail(&ref->ilist, &c->xattr_temp); | ||
419 | |||
420 | raw->__totlen = PAD(je32_to_cpu(rr->totlen)); | ||
421 | raw->flash_offset = ofs | REF_PRISTINE; | ||
422 | raw->next_phys = NULL; | ||
423 | raw->next_in_ino = (void *)ref; | ||
424 | if (!jeb->first_node) | ||
425 | jeb->first_node = raw; | ||
426 | if (jeb->last_node) | ||
427 | jeb->last_node->next_phys = raw; | ||
428 | jeb->last_node = raw; | ||
429 | |||
430 | USED_SPACE(PAD(je32_to_cpu(rr->totlen))); | ||
431 | if (jffs2_sum_active()) | ||
432 | jffs2_sum_add_xref_mem(s, rr, ofs - jeb->offset); | ||
433 | dbg_xattr("scan xref at %#08x (xid=%u, ino=%u)\n", | ||
434 | ofs, ref->xid, ref->ino); | ||
435 | return 0; | ||
436 | } | ||
437 | #endif | ||
438 | |||
309 | static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, | 439 | 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) { | 440 | unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s) { |
311 | struct jffs2_unknown_node *node; | 441 | struct jffs2_unknown_node *node; |
@@ -614,6 +744,43 @@ scan_more: | |||
614 | ofs += PAD(je32_to_cpu(node->totlen)); | 744 | ofs += PAD(je32_to_cpu(node->totlen)); |
615 | break; | 745 | break; |
616 | 746 | ||
747 | #ifdef CONFIG_JFFS2_FS_XATTR | ||
748 | case JFFS2_NODETYPE_XATTR: | ||
749 | if (buf_ofs + buf_len < ofs + je32_to_cpu(node->totlen)) { | ||
750 | buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs); | ||
751 | D1(printk(KERN_DEBUG "Fewer than %d bytes (xattr node)" | ||
752 | " left to end of buf. Reading 0x%x at 0x%08x\n", | ||
753 | je32_to_cpu(node->totlen), buf_len, ofs)); | ||
754 | err = jffs2_fill_scan_buf(c, buf, ofs, buf_len); | ||
755 | if (err) | ||
756 | return err; | ||
757 | buf_ofs = ofs; | ||
758 | node = (void *)buf; | ||
759 | } | ||
760 | err = jffs2_scan_xattr_node(c, jeb, (void *)node, ofs, s); | ||
761 | if (err) | ||
762 | return err; | ||
763 | ofs += PAD(je32_to_cpu(node->totlen)); | ||
764 | break; | ||
765 | case JFFS2_NODETYPE_XREF: | ||
766 | if (buf_ofs + buf_len < ofs + je32_to_cpu(node->totlen)) { | ||
767 | buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs); | ||
768 | D1(printk(KERN_DEBUG "Fewer than %d bytes (xref node)" | ||
769 | " left to end of buf. Reading 0x%x at 0x%08x\n", | ||
770 | je32_to_cpu(node->totlen), buf_len, ofs)); | ||
771 | err = jffs2_fill_scan_buf(c, buf, ofs, buf_len); | ||
772 | if (err) | ||
773 | return err; | ||
774 | buf_ofs = ofs; | ||
775 | node = (void *)buf; | ||
776 | } | ||
777 | err = jffs2_scan_xref_node(c, jeb, (void *)node, ofs, s); | ||
778 | if (err) | ||
779 | return err; | ||
780 | ofs += PAD(je32_to_cpu(node->totlen)); | ||
781 | break; | ||
782 | #endif /* CONFIG_JFFS2_FS_XATTR */ | ||
783 | |||
617 | case JFFS2_NODETYPE_CLEANMARKER: | 784 | case JFFS2_NODETYPE_CLEANMARKER: |
618 | D1(printk(KERN_DEBUG "CLEANMARKER node found at 0x%08x\n", ofs)); | 785 | D1(printk(KERN_DEBUG "CLEANMARKER node found at 0x%08x\n", ofs)); |
619 | if (je32_to_cpu(node->totlen) != c->cleanmarker_size) { | 786 | if (je32_to_cpu(node->totlen) != c->cleanmarker_size) { |
@@ -721,6 +888,7 @@ struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uin | |||
721 | 888 | ||
722 | ic->ino = ino; | 889 | ic->ino = ino; |
723 | ic->nodes = (void *)ic; | 890 | ic->nodes = (void *)ic; |
891 | init_xattr_inode_cache(ic); | ||
724 | jffs2_add_ino_cache(c, ic); | 892 | jffs2_add_ino_cache(c, ic); |
725 | if (ino == 1) | 893 | if (ino == 1) |
726 | ic->nlink = 1; | 894 | ic->nlink = 1; |