aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jffs2/scan.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/jffs2/scan.c')
-rw-r--r--fs/jffs2/scan.c168
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
310static 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
372static 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
309static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, 439static 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;