aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jffs2
diff options
context:
space:
mode:
authorKaiGai Kohei <kaigai@ak.jp.nec.com>2006-06-23 20:14:13 -0400
committerDavid Woodhouse <dwmw2@infradead.org>2006-06-27 11:18:02 -0400
commit8a13695cbe4e8311b363f9bd25162904b984ca74 (patch)
tree2ff6ecca99d5b6185e1b3df0f3ab1447a3fdff9b /fs/jffs2
parenta1ae76e96a18edf4b8a4d4e102762060c26d1c6a (diff)
[JFFS2][XATTR] rid unnecessary writing of delete marker.
In the followinf situation, an explicit delete marker is not necessary, because we can certainlly detect those obsolete xattr_datum or xattr_ref on next mounting. - When to delete xattr_datum node. - When to delete xattr_ref node on removing inode. - When to delete xattr_ref node on updating xattr. This patch rids writing delete marker in those situations. Signed-off-by: KaiGai Kohei <kaigai@ak.jp.nec.com> Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Diffstat (limited to 'fs/jffs2')
-rw-r--r--fs/jffs2/scan.c6
-rw-r--r--fs/jffs2/xattr.c303
-rw-r--r--fs/jffs2/xattr.h23
3 files changed, 105 insertions, 227 deletions
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
index 79638f56c5ea..2bfdc33752d3 100644
--- a/fs/jffs2/scan.c
+++ b/fs/jffs2/scan.c
@@ -332,10 +332,8 @@ static int jffs2_scan_xattr_node(struct jffs2_sb_info *c, struct jffs2_erasebloc
332 xid = je32_to_cpu(rx->xid); 332 xid = je32_to_cpu(rx->xid);
333 version = je32_to_cpu(rx->version); 333 version = je32_to_cpu(rx->version);
334 334
335 totlen = sizeof(struct jffs2_raw_xattr); 335 totlen = PAD(sizeof(struct jffs2_raw_xattr)
336 if (version != XDATUM_DELETE_MARKER) 336 + rx->name_len + 1 + je16_to_cpu(rx->value_len));
337 totlen += rx->name_len + 1 + je16_to_cpu(rx->value_len);
338 totlen = PAD(totlen);
339 if (totlen != je32_to_cpu(rx->totlen)) { 337 if (totlen != je32_to_cpu(rx->totlen)) {
340 JFFS2_WARNING("node length mismatch at %#08x, read=%u, calc=%u\n", 338 JFFS2_WARNING("node length mismatch at %#08x, read=%u, calc=%u\n",
341 ofs, je32_to_cpu(rx->totlen), totlen); 339 ofs, je32_to_cpu(rx->totlen), totlen);
diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c
index 03871ab7c26d..7622f79cb5b4 100644
--- a/fs/jffs2/xattr.c
+++ b/fs/jffs2/xattr.c
@@ -50,12 +50,9 @@
50 * is used to write xdatum to medium. xd->version will be incremented. 50 * is used to write xdatum to medium. xd->version will be incremented.
51 * create_xattr_datum(c, xprefix, xname, xvalue, xsize) 51 * create_xattr_datum(c, xprefix, xname, xvalue, xsize)
52 * is used to create new xdatum and write to medium. 52 * is used to create new xdatum and write to medium.
53 * delete_xattr_datum_delay(c, xd)
54 * is used to delete a xdatum without 'delete marker'. It has a possibility to detect
55 * orphan xdatum on next mounting.
56 * delete_xattr_datum(c, xd) 53 * delete_xattr_datum(c, xd)
57 * is used to delete a xdatum with 'delete marker'. Calling jffs2_reserve_space() is 54 * is used to delete a xdatum. It marks xd JFFS2_XFLAGS_DEAD, and allows
58 * necessary before this function. 55 * GC to reclaim those physical nodes.
59 * -------------------------------------------------- */ 56 * -------------------------------------------------- */
60static uint32_t xattr_datum_hashkey(int xprefix, const char *xname, const char *xvalue, int xsize) 57static uint32_t xattr_datum_hashkey(int xprefix, const char *xname, const char *xvalue, int xsize)
61{ 58{
@@ -154,10 +151,7 @@ static int do_verify_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_dat
154 xd->flags |= JFFS2_XFLAGS_INVALID; 151 xd->flags |= JFFS2_XFLAGS_INVALID;
155 return EIO; 152 return EIO;
156 } 153 }
157 totlen = sizeof(rx); 154 totlen = PAD(sizeof(rx) + rx.name_len + 1 + je16_to_cpu(rx.value_len));
158 if (xd->version != XDATUM_DELETE_MARKER)
159 totlen += rx.name_len + 1 + je16_to_cpu(rx.value_len);
160 totlen = PAD(totlen);
161 if (je16_to_cpu(rx.magic) != JFFS2_MAGIC_BITMASK 155 if (je16_to_cpu(rx.magic) != JFFS2_MAGIC_BITMASK
162 || je16_to_cpu(rx.nodetype) != JFFS2_NODETYPE_XATTR 156 || je16_to_cpu(rx.nodetype) != JFFS2_NODETYPE_XATTR
163 || je32_to_cpu(rx.totlen) != totlen 157 || je32_to_cpu(rx.totlen) != totlen
@@ -268,6 +262,7 @@ static int load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x
268 */ 262 */
269 int rc = 0; 263 int rc = 0;
270 264
265 BUG_ON(xd->flags & JFFS2_XFLAGS_DEAD);
271 if (xd->xname) 266 if (xd->xname)
272 return 0; 267 return 0;
273 if (xd->flags & JFFS2_XFLAGS_INVALID) 268 if (xd->flags & JFFS2_XFLAGS_INVALID)
@@ -285,20 +280,18 @@ static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x
285 struct jffs2_raw_xattr rx; 280 struct jffs2_raw_xattr rx;
286 struct kvec vecs[2]; 281 struct kvec vecs[2];
287 size_t length; 282 size_t length;
288 int rc, totlen, nvecs = 1; 283 int rc, totlen;
289 uint32_t phys_ofs = write_ofs(c); 284 uint32_t phys_ofs = write_ofs(c);
290 285
291 BUG_ON(is_xattr_datum_dead(xd) || (xd->flags & JFFS2_XFLAGS_INVALID) 286 BUG_ON(!xd->xname);
292 ? !!xd->xname : !xd->xname); 287 BUG_ON(xd->flags & (JFFS2_XFLAGS_DEAD|JFFS2_XFLAGS_INVALID));
293 288
294 vecs[0].iov_base = &rx; 289 vecs[0].iov_base = &rx;
295 vecs[0].iov_len = totlen = sizeof(rx); 290 vecs[0].iov_len = sizeof(rx);
296 if (!is_xattr_datum_dead(xd) && !(xd->flags & JFFS2_XFLAGS_INVALID)) { 291 vecs[1].iov_base = xd->xname;
297 nvecs++; 292 vecs[1].iov_len = xd->name_len + 1 + xd->value_len;
298 vecs[1].iov_base = xd->xname; 293 totlen = vecs[0].iov_len + vecs[1].iov_len;
299 vecs[1].iov_len = xd->name_len + 1 + xd->value_len; 294
300 totlen += vecs[1].iov_len;
301 }
302 /* Setup raw-xattr */ 295 /* Setup raw-xattr */
303 memset(&rx, 0, sizeof(rx)); 296 memset(&rx, 0, sizeof(rx));
304 rx.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); 297 rx.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
@@ -307,18 +300,14 @@ static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x
307 rx.hdr_crc = cpu_to_je32(crc32(0, &rx, sizeof(struct jffs2_unknown_node) - 4)); 300 rx.hdr_crc = cpu_to_je32(crc32(0, &rx, sizeof(struct jffs2_unknown_node) - 4));
308 301
309 rx.xid = cpu_to_je32(xd->xid); 302 rx.xid = cpu_to_je32(xd->xid);
310 if (!is_xattr_datum_dead(xd) && !(xd->flags & JFFS2_XFLAGS_INVALID)) { 303 rx.version = cpu_to_je32(++xd->version);
311 rx.version = cpu_to_je32(++xd->version); 304 rx.xprefix = xd->xprefix;
312 rx.xprefix = xd->xprefix; 305 rx.name_len = xd->name_len;
313 rx.name_len = xd->name_len; 306 rx.value_len = cpu_to_je16(xd->value_len);
314 rx.value_len = cpu_to_je16(xd->value_len); 307 rx.data_crc = cpu_to_je32(crc32(0, vecs[1].iov_base, vecs[1].iov_len));
315 rx.data_crc = cpu_to_je32(crc32(0, vecs[1].iov_base, vecs[1].iov_len));
316 } else {
317 rx.version = cpu_to_je32(XDATUM_DELETE_MARKER);
318 }
319 rx.node_crc = cpu_to_je32(crc32(0, &rx, sizeof(struct jffs2_raw_xattr) - 4)); 308 rx.node_crc = cpu_to_je32(crc32(0, &rx, sizeof(struct jffs2_raw_xattr) - 4));
320 309
321 rc = jffs2_flash_writev(c, vecs, nvecs, phys_ofs, &length, 0); 310 rc = jffs2_flash_writev(c, vecs, 2, phys_ofs, &length, 0);
322 if (rc || totlen != length) { 311 if (rc || totlen != length) {
323 JFFS2_WARNING("jffs2_flash_writev()=%d, req=%u, wrote=%zu, at %#08x\n", 312 JFFS2_WARNING("jffs2_flash_writev()=%d, req=%u, wrote=%zu, at %#08x\n",
324 rc, totlen, length, phys_ofs); 313 rc, totlen, length, phys_ofs);
@@ -405,53 +394,36 @@ static struct jffs2_xattr_datum *create_xattr_datum(struct jffs2_sb_info *c,
405 return xd; 394 return xd;
406} 395}
407 396
408static void delete_xattr_datum_delay(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) 397static void delete_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
409{ 398{
410 /* must be called under down_write(xattr_sem) */ 399 /* must be called under down_write(xattr_sem) */
411 BUG_ON(xd->refcnt); 400 BUG_ON(xd->refcnt);
412 401
413 unload_xattr_datum(c, xd); 402 unload_xattr_datum(c, xd);
414 set_xattr_datum_dead(xd); 403 xd->flags |= JFFS2_XFLAGS_DEAD;
415 spin_lock(&c->erase_completion_lock); 404 spin_lock(&c->erase_completion_lock);
416 list_add(&xd->xindex, &c->xattr_dead_list); 405 if (xd->node == (void *)xd) {
417 spin_unlock(&c->erase_completion_lock); 406 BUG_ON(!(xd->flags & JFFS2_XFLAGS_INVALID));
418 JFFS2_NOTICE("xdatum(xid=%u) was removed without delete marker. " 407 jffs2_free_xattr_datum(xd);
419 "An orphan xdatum may be detected on next mounting.\n", xd->xid); 408 } else {
420} 409 list_add(&xd->xindex, &c->xattr_dead_list);
421
422static void delete_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
423{
424 /* must be called under jffs2_reserve_space() and down_write(xattr_sem) */
425 int rc;
426 BUG_ON(xd->refcnt);
427
428 unload_xattr_datum(c, xd);
429 set_xattr_datum_dead(xd);
430 rc = save_xattr_datum(c, xd);
431 if (rc) {
432 JFFS2_NOTICE("xdatum(xid=%u) was removed without delete marker. "
433 "An orphan xdatum may be detected on next mounting.\n",
434 xd->xid);
435 } 410 }
436 spin_lock(&c->erase_completion_lock);
437 list_add(&xd->xindex, &c->xattr_dead_list);
438 spin_unlock(&c->erase_completion_lock); 411 spin_unlock(&c->erase_completion_lock);
412 dbg_xattr("xdatum(xid=%u, version=%u) was removed.\n", xd->xid, xd->version);
439} 413}
440 414
441/* -------- xref related functions ------------------ 415/* -------- xref related functions ------------------
442 * verify_xattr_ref(c, ref) 416 * verify_xattr_ref(c, ref)
443 * is used to load xref information from medium. Because summary data does not 417 * is used to load xref information from medium. Because summary data does not
444 * contain xid/ino, it's necessary to verify once while mounting process. 418 * contain xid/ino, it's necessary to verify once while mounting process.
445 * delete_xattr_ref_node(c, ref)
446 * is used to delete a jffs2 node is dominated by xref. When EBS is enabled,
447 * it overwrites the obsolete node by myself.
448 * delete_xattr_ref(c, ref)
449 * is used to delete jffs2_xattr_ref object. If the reference counter of xdatum
450 * is refered by this xref become 0, delete_xattr_datum() is called later.
451 * save_xattr_ref(c, ref) 419 * save_xattr_ref(c, ref)
452 * is used to write xref to medium. 420 * is used to write xref to medium. If delete marker is marked, it write
421 * a delete marker of xref into medium.
453 * create_xattr_ref(c, ic, xd) 422 * create_xattr_ref(c, ic, xd)
454 * is used to create a new xref and write to medium. 423 * is used to create a new xref and write to medium.
424 * delete_xattr_ref(c, ref)
425 * is used to delete jffs2_xattr_ref. It marks xref XREF_DELETE_MARKER,
426 * and allows GC to reclaim those physical nodes.
455 * jffs2_xattr_delete_inode(c, ic) 427 * jffs2_xattr_delete_inode(c, ic)
456 * is called to remove xrefs related to obsolete inode when inode is unlinked. 428 * is called to remove xrefs related to obsolete inode when inode is unlinked.
457 * jffs2_xattr_free_inode(c, ic) 429 * jffs2_xattr_free_inode(c, ic)
@@ -591,13 +563,13 @@ static struct jffs2_xattr_ref *create_xattr_ref(struct jffs2_sb_info *c, struct
591 return ref; /* success */ 563 return ref; /* success */
592} 564}
593 565
594static void delete_xattr_ref_delay(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) 566static void delete_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
595{ 567{
596 /* must be called under down_write(xattr_sem) */ 568 /* must be called under down_write(xattr_sem) */
597 struct jffs2_xattr_datum *xd; 569 struct jffs2_xattr_datum *xd;
598 570
599 set_xattr_ref_dead(ref);
600 xd = ref->xd; 571 xd = ref->xd;
572 ref->xseqno |= XREF_DELETE_MARKER;
601 ref->ino = ref->ic->ino; 573 ref->ino = ref->ic->ino;
602 ref->xid = ref->xd->xid; 574 ref->xid = ref->xd->xid;
603 spin_lock(&c->erase_completion_lock); 575 spin_lock(&c->erase_completion_lock);
@@ -605,102 +577,29 @@ static void delete_xattr_ref_delay(struct jffs2_sb_info *c, struct jffs2_xattr_r
605 c->xref_dead_list = ref; 577 c->xref_dead_list = ref;
606 spin_unlock(&c->erase_completion_lock); 578 spin_unlock(&c->erase_completion_lock);
607 579
608 JFFS2_NOTICE("xref(ino=%u, xid=%u) was removed without delete marker. " 580 dbg_xattr("xref(ino=%u, xid=%u, xseqno=%u) was removed.\n",
609 "An orphan xref may be detected on next mounting.\n", 581 ref->ino, ref->xid, ref->xseqno);
610 ref->ino, ref->xid);
611 582
612 if (!--xd->refcnt) 583 if (!--xd->refcnt)
613 delete_xattr_datum_delay(c, xd);
614}
615
616static int delete_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref, int enforce)
617{
618 /* must be called under jffs2_reserve_space() and down_write(xattr_sem) */
619 struct jffs2_inode_cache *ic;
620 struct jffs2_xattr_datum *xd;
621 uint32_t length;
622 int rc;
623
624 set_xattr_ref_dead(ref);
625 ic = ref->ic;
626 xd = ref->xd;
627 ref->ino = ic->ino;
628 ref->xid = xd->xid;
629 rc = save_xattr_ref(c, ref);
630 if (rc) {
631 if (!enforce) {
632 clr_xattr_ref_dead(ref);
633 ref->ic = ic;
634 ref->xd = xd;
635 return rc;
636 }
637 JFFS2_WARNING("could not write delete marker of xref(ino=%u, xid=%u). "
638 "An orphan xref may be detected on next mounting.\n",
639 ref->ic->ino, ref->xd->xid);
640 }
641 spin_lock(&c->erase_completion_lock);
642 ref->next = c->xref_dead_list;
643 c->xref_dead_list = ref;
644 spin_unlock(&c->erase_completion_lock);
645
646 xd->refcnt--;
647 if (xd->refcnt)
648 return 0;
649
650 /* delete xdatum */
651 unload_xattr_datum(c, xd);
652 up_write(&c->xattr_sem);
653 jffs2_complete_reservation(c);
654
655 rc = jffs2_reserve_space(c, PAD(sizeof(struct jffs2_raw_xattr)), &length,
656 ALLOC_DELETION, JFFS2_SUMMARY_XATTR_SIZE);
657 if (rc) {
658 down(&c->alloc_sem);
659 down_write(&c->xattr_sem);
660 delete_xattr_datum_delay(c, xd);
661 } else {
662 down_write(&c->xattr_sem);
663 delete_xattr_datum(c, xd); 584 delete_xattr_datum(c, xd);
664 }
665 return 0;
666} 585}
667 586
668void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) 587void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
669{ 588{
670 /* It's called from jffs2_clear_inode() on inode removing. 589 /* It's called from jffs2_clear_inode() on inode removing.
671 When an inode with XATTR is removed, those XATTRs must be removed. */ 590 When an inode with XATTR is removed, those XATTRs must be removed. */
672 struct jffs2_xattr_ref *ref; 591 struct jffs2_xattr_ref *ref, *_ref;
673 uint32_t length;
674 int rc, retry;
675 592
676 if (!ic || ic->nlink > 0) 593 if (!ic || ic->nlink > 0)
677 return; 594 return;
678 595
679 down_read(&c->xattr_sem);
680 if (!ic->xref) {
681 up_read(&c->xattr_sem);
682 return;
683 }
684 up_read(&c->xattr_sem);
685 retry:
686 rc = jffs2_reserve_space(c, PAD(sizeof(struct jffs2_raw_xref)), &length,
687 ALLOC_DELETION, JFFS2_SUMMARY_XREF_SIZE);
688 down_write(&c->xattr_sem); 596 down_write(&c->xattr_sem);
689 if (ic->xref) { 597 for (ref = ic->xref; ref; ref = _ref) {
690 ref = ic->xref; 598 _ref = ref->next;
691 ic->xref = ref->next; 599 delete_xattr_ref(c, ref);
692 if (rc) {
693 delete_xattr_ref_delay(c, ref);
694 } else {
695 delete_xattr_ref(c, ref, 1);
696 }
697 } 600 }
698 retry = ic->xref ? 1 : 0; 601 ic->xref = NULL;
699 up_write(&c->xattr_sem); 602 up_write(&c->xattr_sem);
700 if (!rc)
701 jffs2_complete_reservation(c);
702 if (retry)
703 goto retry;
704} 603}
705 604
706void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) 605void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
@@ -743,7 +642,7 @@ static int check_xattr_ref_inode(struct jffs2_sb_info *c, struct jffs2_inode_cac
743 rc = load_xattr_datum(c, ref->xd); 642 rc = load_xattr_datum(c, ref->xd);
744 if (unlikely(rc > 0)) { 643 if (unlikely(rc > 0)) {
745 *pref = ref->next; 644 *pref = ref->next;
746 delete_xattr_ref_delay(c, ref); 645 delete_xattr_ref(c, ref);
747 goto retry; 646 goto retry;
748 } else if (unlikely(rc < 0)) 647 } else if (unlikely(rc < 0))
749 goto out; 648 goto out;
@@ -755,7 +654,7 @@ static int check_xattr_ref_inode(struct jffs2_sb_info *c, struct jffs2_inode_cac
755 ref->xd->flags &= ~JFFS2_XFLAGS_BIND; 654 ref->xd->flags &= ~JFFS2_XFLAGS_BIND;
756 if (unlikely(rc > 0)) { 655 if (unlikely(rc > 0)) {
757 *pcmp = cmp->next; 656 *pcmp = cmp->next;
758 delete_xattr_ref_delay(c, cmp); 657 delete_xattr_ref(c, cmp);
759 goto retry; 658 goto retry;
760 } else if (unlikely(rc < 0)) 659 } else if (unlikely(rc < 0))
761 goto out; 660 goto out;
@@ -764,10 +663,10 @@ static int check_xattr_ref_inode(struct jffs2_sb_info *c, struct jffs2_inode_cac
764 && !strcmp(ref->xd->xname, cmp->xd->xname)) { 663 && !strcmp(ref->xd->xname, cmp->xd->xname)) {
765 if (ref->xseqno > cmp->xseqno) { 664 if (ref->xseqno > cmp->xseqno) {
766 *pcmp = cmp->next; 665 *pcmp = cmp->next;
767 delete_xattr_ref_delay(c, cmp); 666 delete_xattr_ref(c, cmp);
768 } else { 667 } else {
769 *pref = ref->next; 668 *pref = ref->next;
770 delete_xattr_ref_delay(c, ref); 669 delete_xattr_ref(c, ref);
771 } 670 }
772 goto retry; 671 goto retry;
773 } 672 }
@@ -865,20 +764,11 @@ void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c)
865 struct jffs2_inode_cache *ic; 764 struct jffs2_inode_cache *ic;
866 struct jffs2_raw_node_ref *raw; 765 struct jffs2_raw_node_ref *raw;
867 int i, xdatum_count = 0, xdatum_unchecked_count = 0, xref_count = 0; 766 int i, xdatum_count = 0, xdatum_unchecked_count = 0, xref_count = 0;
767 int xdatum_orphan_count = 0, xref_orphan_count = 0, xref_dead_count = 0;
868 768
869 BUG_ON(!(c->flags & JFFS2_SB_FLAG_BUILDING)); 769 BUG_ON(!(c->flags & JFFS2_SB_FLAG_BUILDING));
870 /* Phase.1 : Drop dead xdatum */
871 for (i=0; i < XATTRINDEX_HASHSIZE; i++) {
872 list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) {
873 BUG_ON(xd->node == (void *)xd);
874 if (is_xattr_datum_dead(xd)) {
875 list_del_init(&xd->xindex);
876 list_add(&xd->xindex, &c->xattr_unchecked);
877 }
878 }
879 }
880 770
881 /* Phase.2 : Merge same xref */ 771 /* Phase.1 : Merge same xref */
882 for (i=0; i < XREF_TMPHASH_SIZE; i++) 772 for (i=0; i < XREF_TMPHASH_SIZE; i++)
883 xref_tmphash[i] = NULL; 773 xref_tmphash[i] = NULL;
884 for (ref=c->xref_temp; ref; ref=_ref) { 774 for (ref=c->xref_temp; ref; ref=_ref) {
@@ -919,13 +809,15 @@ void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c)
919 } 809 }
920 c->xref_temp = NULL; 810 c->xref_temp = NULL;
921 811
922 /* Phase.3 : Bind xref with inode_cache and xattr_datum */ 812 /* Phase.2 : Bind xref with inode_cache and xattr_datum */
923 for (i=0; i < XREF_TMPHASH_SIZE; i++) { 813 for (i=0; i < XREF_TMPHASH_SIZE; i++) {
924 for (ref=xref_tmphash[i]; ref; ref=_ref) { 814 for (ref=xref_tmphash[i]; ref; ref=_ref) {
815 xref_count++;
925 _ref = ref->next; 816 _ref = ref->next;
926 if (is_xattr_ref_dead(ref)) { 817 if (is_xattr_ref_dead(ref)) {
927 ref->next = c->xref_dead_list; 818 ref->next = c->xref_dead_list;
928 c->xref_dead_list = ref; 819 c->xref_dead_list = ref;
820 xref_dead_count++;
929 continue; 821 continue;
930 } 822 }
931 /* At this point, ref->xid and ref->ino contain XID and inode number. 823 /* At this point, ref->xid and ref->ino contain XID and inode number.
@@ -933,11 +825,12 @@ void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c)
933 xd = jffs2_find_xattr_datum(c, ref->xid); 825 xd = jffs2_find_xattr_datum(c, ref->xid);
934 ic = jffs2_get_ino_cache(c, ref->ino); 826 ic = jffs2_get_ino_cache(c, ref->ino);
935 if (!xd || !ic) { 827 if (!xd || !ic) {
936 JFFS2_WARNING("xref(ino=%u, xid=%u, xseqno=%u) is orphan. \n", 828 dbg_xattr("xref(ino=%u, xid=%u, xseqno=%u) is orphan.\n",
937 ref->ino, ref->xid, ref->xseqno); 829 ref->ino, ref->xid, ref->xseqno);
938 set_xattr_ref_dead(ref); 830 ref->xseqno |= XREF_DELETE_MARKER;
939 ref->next = c->xref_dead_list; 831 ref->next = c->xref_dead_list;
940 c->xref_dead_list = ref; 832 c->xref_dead_list = ref;
833 xref_orphan_count++;
941 continue; 834 continue;
942 } 835 }
943 ref->xd = xd; 836 ref->xd = xd;
@@ -945,19 +838,20 @@ void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c)
945 xd->refcnt++; 838 xd->refcnt++;
946 ref->next = ic->xref; 839 ref->next = ic->xref;
947 ic->xref = ref; 840 ic->xref = ref;
948 xref_count++;
949 } 841 }
950 } 842 }
951 843
952 /* Phase.4 : Link unchecked xdatum to xattr_unchecked list */ 844 /* Phase.3 : Link unchecked xdatum to xattr_unchecked list */
953 for (i=0; i < XATTRINDEX_HASHSIZE; i++) { 845 for (i=0; i < XATTRINDEX_HASHSIZE; i++) {
954 list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) { 846 list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) {
847 xdatum_count++;
955 list_del_init(&xd->xindex); 848 list_del_init(&xd->xindex);
956 if (!xd->refcnt) { 849 if (!xd->refcnt) {
957 JFFS2_WARNING("orphan xdatum(xid=%u, version=%u)\n", 850 dbg_xattr("xdatum(xid=%u, version=%u) is orphan.\n",
958 xd->xid, xd->version); 851 xd->xid, xd->version);
959 set_xattr_datum_dead(xd); 852 xd->flags |= JFFS2_XFLAGS_DEAD;
960 list_add(&xd->xindex, &c->xattr_unchecked); 853 list_add(&xd->xindex, &c->xattr_unchecked);
854 xdatum_orphan_count++;
961 continue; 855 continue;
962 } 856 }
963 if (is_xattr_datum_unchecked(c, xd)) { 857 if (is_xattr_datum_unchecked(c, xd)) {
@@ -966,12 +860,14 @@ void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c)
966 list_add(&xd->xindex, &c->xattr_unchecked); 860 list_add(&xd->xindex, &c->xattr_unchecked);
967 xdatum_unchecked_count++; 861 xdatum_unchecked_count++;
968 } 862 }
969 xdatum_count++;
970 } 863 }
971 } 864 }
972 /* build complete */ 865 /* build complete */
973 JFFS2_NOTICE("complete building xattr subsystem, %u of xdatum (%u unchecked) and " 866 JFFS2_NOTICE("complete building xattr subsystem, %u of xdatum"
974 "%u of xref found.\n", xdatum_count, xdatum_unchecked_count, xref_count); 867 " (%u unchecked, %u orphan) and "
868 "%u of xref (%u dead, %u orphan) found.\n",
869 xdatum_count, xdatum_unchecked_count, xdatum_orphan_count,
870 xref_count, xref_dead_count, xref_orphan_count);
975} 871}
976 872
977struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c, 873struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c,
@@ -1079,7 +975,7 @@ ssize_t jffs2_listxattr(struct dentry *dentry, char *buffer, size_t size)
1079 rc = load_xattr_datum(c, xd); 975 rc = load_xattr_datum(c, xd);
1080 if (unlikely(rc > 0)) { 976 if (unlikely(rc > 0)) {
1081 *pref = ref->next; 977 *pref = ref->next;
1082 delete_xattr_ref_delay(c, ref); 978 delete_xattr_ref(c, ref);
1083 goto retry; 979 goto retry;
1084 } else if (unlikely(rc < 0)) 980 } else if (unlikely(rc < 0))
1085 goto out; 981 goto out;
@@ -1140,7 +1036,7 @@ int do_jffs2_getxattr(struct inode *inode, int xprefix, const char *xname,
1140 rc = load_xattr_datum(c, xd); 1036 rc = load_xattr_datum(c, xd);
1141 if (unlikely(rc > 0)) { 1037 if (unlikely(rc > 0)) {
1142 *pref = ref->next; 1038 *pref = ref->next;
1143 delete_xattr_ref_delay(c, ref); 1039 delete_xattr_ref(c, ref);
1144 goto retry; 1040 goto retry;
1145 } else if (unlikely(rc < 0)) { 1041 } else if (unlikely(rc < 0)) {
1146 goto out; 1042 goto out;
@@ -1203,7 +1099,7 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
1203 rc = load_xattr_datum(c, xd); 1099 rc = load_xattr_datum(c, xd);
1204 if (unlikely(rc > 0)) { 1100 if (unlikely(rc > 0)) {
1205 *pref = ref->next; 1101 *pref = ref->next;
1206 delete_xattr_ref_delay(c, ref); 1102 delete_xattr_ref(c, ref);
1207 goto retry; 1103 goto retry;
1208 } else if (unlikely(rc < 0)) 1104 } else if (unlikely(rc < 0))
1209 goto out; 1105 goto out;
@@ -1214,8 +1110,23 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
1214 goto out; 1110 goto out;
1215 } 1111 }
1216 if (!buffer) { 1112 if (!buffer) {
1217 *pref = ref->next; 1113 ref->ino = ic->ino;
1218 rc = delete_xattr_ref(c, ref, 0); 1114 ref->xid = xd->xid;
1115 ref->xseqno |= XREF_DELETE_MARKER;
1116 rc = save_xattr_ref(c, ref);
1117 if (!rc) {
1118 *pref = ref->next;
1119 spin_lock(&c->erase_completion_lock);
1120 ref->next = c->xref_dead_list;
1121 c->xref_dead_list = ref;
1122 spin_unlock(&c->erase_completion_lock);
1123 if (!--xd->refcnt)
1124 delete_xattr_datum(c, xd);
1125 } else {
1126 ref->ic = ic;
1127 ref->xd = xd;
1128 ref->xseqno &= ~XREF_DELETE_MARKER;
1129 }
1219 goto out; 1130 goto out;
1220 } 1131 }
1221 goto found; 1132 goto found;
@@ -1248,7 +1159,7 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
1248 JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, request); 1159 JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, request);
1249 xd->refcnt--; 1160 xd->refcnt--;
1250 if (!xd->refcnt) 1161 if (!xd->refcnt)
1251 delete_xattr_datum_delay(c, xd); 1162 delete_xattr_datum(c, xd);
1252 up_write(&c->xattr_sem); 1163 up_write(&c->xattr_sem);
1253 return rc; 1164 return rc;
1254 } 1165 }
@@ -1263,21 +1174,9 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
1263 rc = PTR_ERR(newref); 1174 rc = PTR_ERR(newref);
1264 xd->refcnt--; 1175 xd->refcnt--;
1265 if (!xd->refcnt) 1176 if (!xd->refcnt)
1266 delete_xattr_datum_delay(c, xd); 1177 delete_xattr_datum(c, xd);
1267 } else if (ref) { 1178 } else if (ref) {
1268 up_write(&c->xattr_sem); 1179 delete_xattr_ref(c, ref);
1269 jffs2_complete_reservation(c);
1270
1271 rc = jffs2_reserve_space(c, request, &length,
1272 ALLOC_DELETION, JFFS2_SUMMARY_XREF_SIZE);
1273 down_write(&c->xattr_sem);
1274 if (rc) {
1275 JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, request);
1276 delete_xattr_ref_delay(c, ref);
1277 up_write(&c->xattr_sem);
1278 return 0;
1279 }
1280 delete_xattr_ref(c, ref, 1);
1281 } 1180 }
1282 out: 1181 out:
1283 up_write(&c->xattr_sem); 1182 up_write(&c->xattr_sem);
@@ -1292,6 +1191,10 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
1292 * is used to move xref into new node. 1191 * is used to move xref into new node.
1293 * jffs2_verify_xattr(c) 1192 * jffs2_verify_xattr(c)
1294 * is used to call do_verify_xattr_datum() before garbage collecting. 1193 * is used to call do_verify_xattr_datum() before garbage collecting.
1194 * jffs2_release_xattr_datum(c, xd)
1195 * is used to release an in-memory object of xdatum.
1196 * jffs2_release_xattr_ref(c, ref)
1197 * is used to release an in-memory object of xref.
1295 * -------------------------------------------------- */ 1198 * -------------------------------------------------- */
1296int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd, 1199int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd,
1297 struct jffs2_raw_node_ref *raw) 1200 struct jffs2_raw_node_ref *raw)
@@ -1302,18 +1205,17 @@ int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xatt
1302 down_write(&c->xattr_sem); 1205 down_write(&c->xattr_sem);
1303 if (xd->node != raw) 1206 if (xd->node != raw)
1304 goto out; 1207 goto out;
1305 if (is_xattr_datum_dead(xd) && (raw->next_in_ino == (void *)xd)) 1208 if (xd->flags & (JFFS2_XFLAGS_DEAD|JFFS2_XFLAGS_INVALID))
1306 goto out; 1209 goto out;
1307 1210
1308 old_ofs = ref_offset(xd->node); 1211 rc = load_xattr_datum(c, xd);
1309 totlen = ref_totlen(c, c->gcblock, xd->node); 1212 if (unlikely(rc)) {
1310 1213 rc = (rc > 0) ? 0 : rc;
1311 if (!is_xattr_datum_dead(xd)) { 1214 goto out;
1312 rc = load_xattr_datum(c, xd);
1313 if (unlikely(rc < 0))
1314 goto out;
1315 } 1215 }
1316 1216 old_ofs = ref_offset(xd->node);
1217 totlen = PAD(sizeof(struct jffs2_raw_xattr)
1218 + xd->name_len + 1 + xd->value_len);
1317 rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XATTR_SIZE); 1219 rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XATTR_SIZE);
1318 if (rc) { 1220 if (rc) {
1319 JFFS2_WARNING("jffs2_reserve_space_gc()=%d, request=%u\n", rc, totlen); 1221 JFFS2_WARNING("jffs2_reserve_space_gc()=%d, request=%u\n", rc, totlen);
@@ -1331,7 +1233,6 @@ int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xatt
1331 return rc; 1233 return rc;
1332} 1234}
1333 1235
1334
1335int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref, 1236int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref,
1336 struct jffs2_raw_node_ref *raw) 1237 struct jffs2_raw_node_ref *raw)
1337{ 1238{
@@ -1392,7 +1293,7 @@ int jffs2_verify_xattr(struct jffs2_sb_info *c)
1392 raw->flash_offset = ref_offset(raw) 1293 raw->flash_offset = ref_offset(raw)
1393 | ((xd->node == (void *)raw) ? REF_PRISTINE : REF_NORMAL); 1294 | ((xd->node == (void *)raw) ? REF_PRISTINE : REF_NORMAL);
1394 } 1295 }
1395 if (is_xattr_datum_dead(xd)) 1296 if (xd->flags & JFFS2_XFLAGS_DEAD)
1396 list_add(&xd->xindex, &c->xattr_dead_list); 1297 list_add(&xd->xindex, &c->xattr_dead_list);
1397 spin_unlock(&c->erase_completion_lock); 1298 spin_unlock(&c->erase_completion_lock);
1398 } 1299 }
@@ -1403,7 +1304,7 @@ int jffs2_verify_xattr(struct jffs2_sb_info *c)
1403void jffs2_release_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) 1304void jffs2_release_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
1404{ 1305{
1405 /* must be called under spin_lock(&c->erase_completion_lock) */ 1306 /* must be called under spin_lock(&c->erase_completion_lock) */
1406 if (xd->node != (void *)xd) 1307 if (xd->refcnt > 0 || xd->node != (void *)xd)
1407 return; 1308 return;
1408 1309
1409 list_del(&xd->xindex); 1310 list_del(&xd->xindex);
@@ -1421,8 +1322,8 @@ void jffs2_release_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *re
1421 for (tmp=c->xref_dead_list, ptmp=&c->xref_dead_list; tmp; ptmp=&tmp->next, tmp=tmp->next) { 1322 for (tmp=c->xref_dead_list, ptmp=&c->xref_dead_list; tmp; ptmp=&tmp->next, tmp=tmp->next) {
1422 if (ref == tmp) { 1323 if (ref == tmp) {
1423 *ptmp = tmp->next; 1324 *ptmp = tmp->next;
1424 jffs2_free_xattr_ref(ref);
1425 break; 1325 break;
1426 } 1326 }
1427 } 1327 }
1328 jffs2_free_xattr_ref(ref);
1428} 1329}
diff --git a/fs/jffs2/xattr.h b/fs/jffs2/xattr.h
index 06ab7b880212..4a10abc6d917 100644
--- a/fs/jffs2/xattr.h
+++ b/fs/jffs2/xattr.h
@@ -16,6 +16,7 @@
16 16
17#define JFFS2_XFLAGS_HOT (0x01) /* This datum is HOT */ 17#define JFFS2_XFLAGS_HOT (0x01) /* This datum is HOT */
18#define JFFS2_XFLAGS_BIND (0x02) /* This datum is not reclaimed */ 18#define JFFS2_XFLAGS_BIND (0x02) /* This datum is not reclaimed */
19#define JFFS2_XFLAGS_DEAD (0x40) /* This datum is already dead */
19#define JFFS2_XFLAGS_INVALID (0x80) /* This datum contains crc error */ 20#define JFFS2_XFLAGS_INVALID (0x80) /* This datum contains crc error */
20 21
21struct jffs2_xattr_datum 22struct jffs2_xattr_datum
@@ -60,34 +61,12 @@ struct jffs2_xattr_ref
60 struct jffs2_xattr_ref *next; /* chained from ic->xref_list */ 61 struct jffs2_xattr_ref *next; /* chained from ic->xref_list */
61}; 62};
62 63
63#define XDATUM_DELETE_MARKER (0xffffffff)
64#define XREF_DELETE_MARKER (0x00000001) 64#define XREF_DELETE_MARKER (0x00000001)
65static inline int is_xattr_datum_dead(struct jffs2_xattr_datum *xd)
66{
67 return (xd->version == XDATUM_DELETE_MARKER);
68}
69
70static inline void set_xattr_datum_dead(struct jffs2_xattr_datum *xd)
71{
72 xd->version = XDATUM_DELETE_MARKER;
73}
74
75static inline int is_xattr_ref_dead(struct jffs2_xattr_ref *ref) 65static inline int is_xattr_ref_dead(struct jffs2_xattr_ref *ref)
76{ 66{
77 return ((ref->xseqno & XREF_DELETE_MARKER) != 0); 67 return ((ref->xseqno & XREF_DELETE_MARKER) != 0);
78} 68}
79 69
80static inline void set_xattr_ref_dead(struct jffs2_xattr_ref *ref)
81{
82 ref->xseqno |= XREF_DELETE_MARKER;
83}
84
85static inline void clr_xattr_ref_dead(struct jffs2_xattr_ref *ref)
86{
87 ref->xseqno &= ~XREF_DELETE_MARKER;
88}
89
90
91#ifdef CONFIG_JFFS2_FS_XATTR 70#ifdef CONFIG_JFFS2_FS_XATTR
92 71
93extern void jffs2_init_xattr_subsystem(struct jffs2_sb_info *c); 72extern void jffs2_init_xattr_subsystem(struct jffs2_sb_info *c);