aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jffs2/scan.c
diff options
context:
space:
mode:
authorKaiGai Kohei <kaigai@ak.jp.nec.com>2006-05-13 02:09:47 -0400
committerKaiGai Kohei <kaigai@ak.jp.nec.com>2006-05-13 02:09:47 -0400
commitaa98d7cf59b5b0764d3502662053489585faf2fe (patch)
treee98e83f3e69ebe3a1112394a19d440419e899749 /fs/jffs2/scan.c
parent4992a9e88886b0c5ebc3d27eb74d0344c873eeea (diff)
[JFFS2][XATTR] XATTR support on JFFS2 (version. 5)
This attached patches provide xattr support including POSIX-ACL and SELinux support on JFFS2 (version.5). There are some significant differences from previous version posted at last December. The biggest change is addition of EBS(Erase Block Summary) support. Currently, both kernel and usermode utility (sumtool) can recognize xattr nodes which have JFFS2_NODETYPE_XATTR/_XREF nodetype. In addition, some bugs are fixed. - A potential race condition was fixed. - Unexpected fail when updating a xattr by same name/value pair was fixed. - A bug when removing xattr name/value pair was fixed. The fundamental structures (such as using two new nodetypes and exclusion mechanism by rwsem) are unchanged. But most of implementation were reviewed and updated if necessary. Espacially, we had to change several internal implementations related to load_xattr_datum() to avoid a potential race condition. [1/2] xattr_on_jffs2.kernel.version-5.patch [2/2] xattr_on_jffs2.utils.version-5.patch Signed-off-by: KaiGai Kohei <kaigai@ak.jp.nec.com> 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 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;