aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jffs2/scan.c
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@infradead.org>2006-05-20 12:27:32 -0400
committerDavid Woodhouse <dwmw2@infradead.org>2006-05-20 12:27:32 -0400
commit0cfc7da3ff4b39a3aac261ab3f6b1329e2485653 (patch)
tree447073fe757b42e6da63b96a26cbbc6b4c705946 /fs/jffs2/scan.c
parent1417fc44ee923418df3adadeb4846c891bba1ba5 (diff)
parent20a92fc74c5c91c7bc5693d51acc2b99aceb0465 (diff)
Merge git://git.infradead.org/jffs2-xattr-2.6
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
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 2a24b44662bb..40d62d057aa4 100644
--- a/fs/jffs2/scan.c
+++ b/fs/jffs2/scan.c
@@ -306,6 +306,137 @@ 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->next 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 ref->next = c->xref_temp;
419 c->xref_temp = ref;
420
421 raw->__totlen = PAD(je32_to_cpu(rr->totlen));
422 raw->flash_offset = ofs | REF_PRISTINE;
423 raw->next_phys = NULL;
424 raw->next_in_ino = (void *)ref;
425 if (!jeb->first_node)
426 jeb->first_node = raw;
427 if (jeb->last_node)
428 jeb->last_node->next_phys = raw;
429 jeb->last_node = raw;
430
431 USED_SPACE(PAD(je32_to_cpu(rr->totlen)));
432 if (jffs2_sum_active())
433 jffs2_sum_add_xref_mem(s, rr, ofs - jeb->offset);
434 dbg_xattr("scan xref at %#08x (xid=%u, ino=%u)\n",
435 ofs, ref->xid, ref->ino);
436 return 0;
437}
438#endif
439
309/* Called with 'buf_size == 0' if buf is in fact a pointer _directly_ into 440/* Called with 'buf_size == 0' if buf is in fact a pointer _directly_ into
310 the flash, XIP-style */ 441 the flash, XIP-style */
311static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, 442static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
@@ -641,6 +772,43 @@ scan_more:
641 ofs += PAD(je32_to_cpu(node->totlen)); 772 ofs += PAD(je32_to_cpu(node->totlen));
642 break; 773 break;
643 774
775#ifdef CONFIG_JFFS2_FS_XATTR
776 case JFFS2_NODETYPE_XATTR:
777 if (buf_ofs + buf_len < ofs + je32_to_cpu(node->totlen)) {
778 buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs);
779 D1(printk(KERN_DEBUG "Fewer than %d bytes (xattr node)"
780 " left to end of buf. Reading 0x%x at 0x%08x\n",
781 je32_to_cpu(node->totlen), buf_len, ofs));
782 err = jffs2_fill_scan_buf(c, buf, ofs, buf_len);
783 if (err)
784 return err;
785 buf_ofs = ofs;
786 node = (void *)buf;
787 }
788 err = jffs2_scan_xattr_node(c, jeb, (void *)node, ofs, s);
789 if (err)
790 return err;
791 ofs += PAD(je32_to_cpu(node->totlen));
792 break;
793 case JFFS2_NODETYPE_XREF:
794 if (buf_ofs + buf_len < ofs + je32_to_cpu(node->totlen)) {
795 buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs);
796 D1(printk(KERN_DEBUG "Fewer than %d bytes (xref node)"
797 " left to end of buf. Reading 0x%x at 0x%08x\n",
798 je32_to_cpu(node->totlen), buf_len, ofs));
799 err = jffs2_fill_scan_buf(c, buf, ofs, buf_len);
800 if (err)
801 return err;
802 buf_ofs = ofs;
803 node = (void *)buf;
804 }
805 err = jffs2_scan_xref_node(c, jeb, (void *)node, ofs, s);
806 if (err)
807 return err;
808 ofs += PAD(je32_to_cpu(node->totlen));
809 break;
810#endif /* CONFIG_JFFS2_FS_XATTR */
811
644 case JFFS2_NODETYPE_CLEANMARKER: 812 case JFFS2_NODETYPE_CLEANMARKER:
645 D1(printk(KERN_DEBUG "CLEANMARKER node found at 0x%08x\n", ofs)); 813 D1(printk(KERN_DEBUG "CLEANMARKER node found at 0x%08x\n", ofs));
646 if (je32_to_cpu(node->totlen) != c->cleanmarker_size) { 814 if (je32_to_cpu(node->totlen) != c->cleanmarker_size) {