aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/jffs2/jffs2_fs_sb.h2
-rw-r--r--fs/jffs2/malloc.c1
-rw-r--r--fs/jffs2/nodelist.h2
-rw-r--r--fs/jffs2/readinode.c1
-rw-r--r--fs/jffs2/scan.c6
-rw-r--r--fs/jffs2/summary.c3
-rw-r--r--fs/jffs2/write.c1
-rw-r--r--fs/jffs2/xattr.c75
-rw-r--r--fs/jffs2/xattr.h7
9 files changed, 55 insertions, 43 deletions
diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h
index 3b4e0edd6dbb..272fbea55192 100644
--- a/fs/jffs2/jffs2_fs_sb.h
+++ b/fs/jffs2/jffs2_fs_sb.h
@@ -119,8 +119,8 @@ struct jffs2_sb_info {
119#define XATTRINDEX_HASHSIZE (57) 119#define XATTRINDEX_HASHSIZE (57)
120 uint32_t highest_xid; 120 uint32_t highest_xid;
121 struct list_head xattrindex[XATTRINDEX_HASHSIZE]; 121 struct list_head xattrindex[XATTRINDEX_HASHSIZE];
122 struct list_head xattr_temp;
123 struct list_head xattr_unchecked; 122 struct list_head xattr_unchecked;
123 struct jffs2_xattr_ref *xref_temp;
124 struct rw_semaphore xattr_sem; 124 struct rw_semaphore xattr_sem;
125 uint32_t xdatum_mem_usage; 125 uint32_t xdatum_mem_usage;
126 uint32_t xdatum_mem_threshold; 126 uint32_t xdatum_mem_threshold;
diff --git a/fs/jffs2/malloc.c b/fs/jffs2/malloc.c
index 3d5b7ecfbf8d..f2473fa2fd16 100644
--- a/fs/jffs2/malloc.c
+++ b/fs/jffs2/malloc.c
@@ -259,7 +259,6 @@ struct jffs2_xattr_ref *jffs2_alloc_xattr_ref(void)
259 259
260 memset(ref, 0, sizeof(struct jffs2_xattr_ref)); 260 memset(ref, 0, sizeof(struct jffs2_xattr_ref));
261 ref->class = RAWNODE_CLASS_XATTR_REF; 261 ref->class = RAWNODE_CLASS_XATTR_REF;
262 INIT_LIST_HEAD(&ref->ilist);
263 return ref; 262 return ref;
264} 263}
265 264
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h
index 6f6279cf4909..351d947c9375 100644
--- a/fs/jffs2/nodelist.h
+++ b/fs/jffs2/nodelist.h
@@ -117,7 +117,7 @@ struct jffs2_inode_cache {
117 uint32_t ino; 117 uint32_t ino;
118 int nlink; 118 int nlink;
119#ifdef CONFIG_JFFS2_FS_XATTR 119#ifdef CONFIG_JFFS2_FS_XATTR
120 struct list_head ilist; 120 struct jffs2_xattr_ref *xref;
121#endif 121#endif
122}; 122};
123 123
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
index 61ccdf4f1042..e1acce8fb2bf 100644
--- a/fs/jffs2/readinode.c
+++ b/fs/jffs2/readinode.c
@@ -902,7 +902,6 @@ int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
902 f->inocache->ino = f->inocache->nlink = 1; 902 f->inocache->ino = f->inocache->nlink = 1;
903 f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache; 903 f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
904 f->inocache->state = INO_STATE_READING; 904 f->inocache->state = INO_STATE_READING;
905 init_xattr_inode_cache(f->inocache);
906 jffs2_add_ino_cache(c, f->inocache); 905 jffs2_add_ino_cache(c, f->inocache);
907 } 906 }
908 if (!f->inocache) { 907 if (!f->inocache) {
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
index f09689e320fe..0a79fc921e9f 100644
--- a/fs/jffs2/scan.c
+++ b/fs/jffs2/scan.c
@@ -408,14 +408,15 @@ static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock
408 * ref->xid is used to store 32bit xid, xd is not used 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 409 * ref->ino is used to store 32bit inode-number, ic is not used
410 * Thoes variables are declared as union, thus using those 410 * Thoes variables are declared as union, thus using those
411 * are exclusive. In a similar way, ref->ilist is temporarily 411 * are exclusive. In a similar way, ref->next is temporarily
412 * used to chain all xattr_ref object. It's re-chained to 412 * used to chain all xattr_ref object. It's re-chained to
413 * jffs2_inode_cache in jffs2_build_xattr_subsystem() correctly. 413 * jffs2_inode_cache in jffs2_build_xattr_subsystem() correctly.
414 */ 414 */
415 ref->node = raw; 415 ref->node = raw;
416 ref->ino = je32_to_cpu(rr->ino); 416 ref->ino = je32_to_cpu(rr->ino);
417 ref->xid = je32_to_cpu(rr->xid); 417 ref->xid = je32_to_cpu(rr->xid);
418 list_add_tail(&ref->ilist, &c->xattr_temp); 418 ref->next = c->xref_temp;
419 c->xref_temp = ref;
419 420
420 raw->__totlen = PAD(je32_to_cpu(rr->totlen)); 421 raw->__totlen = PAD(je32_to_cpu(rr->totlen));
421 raw->flash_offset = ofs | REF_PRISTINE; 422 raw->flash_offset = ofs | REF_PRISTINE;
@@ -888,7 +889,6 @@ struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uin
888 889
889 ic->ino = ino; 890 ic->ino = ino;
890 ic->nodes = (void *)ic; 891 ic->nodes = (void *)ic;
891 init_xattr_inode_cache(ic);
892 jffs2_add_ino_cache(c, ic); 892 jffs2_add_ino_cache(c, ic);
893 if (ino == 1) 893 if (ino == 1)
894 ic->nlink = 1; 894 ic->nlink = 1;
diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c
index 5d9ec8e36528..831a42c13059 100644
--- a/fs/jffs2/summary.c
+++ b/fs/jffs2/summary.c
@@ -556,7 +556,8 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
556 ref->ino = 0xfffffffe; 556 ref->ino = 0xfffffffe;
557 ref->xid = 0xfffffffd; 557 ref->xid = 0xfffffffd;
558 ref->node = raw; 558 ref->node = raw;
559 list_add_tail(&ref->ilist, &c->xattr_temp); 559 ref->next = c->xref_temp;
560 c->xref_temp = ref;
560 561
561 raw->__totlen = PAD(sizeof(struct jffs2_raw_xref)); 562 raw->__totlen = PAD(sizeof(struct jffs2_raw_xref));
562 raw->flash_offset = ofs | REF_UNCHECKED; 563 raw->flash_offset = ofs | REF_UNCHECKED;
diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c
index d5c78195f3b8..ff2b00b604ec 100644
--- a/fs/jffs2/write.c
+++ b/fs/jffs2/write.c
@@ -36,7 +36,6 @@ int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint
36 f->inocache->nlink = 1; 36 f->inocache->nlink = 1;
37 f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache; 37 f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
38 f->inocache->state = INO_STATE_PRESENT; 38 f->inocache->state = INO_STATE_PRESENT;
39 init_xattr_inode_cache(f->inocache);
40 39
41 jffs2_add_ino_cache(c, f->inocache); 40 jffs2_add_ino_cache(c, f->inocache);
42 D1(printk(KERN_DEBUG "jffs2_do_new_inode(): Assigned ino# %d\n", f->inocache->ino)); 41 D1(printk(KERN_DEBUG "jffs2_do_new_inode(): Assigned ino# %d\n", f->inocache->ino));
diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c
index c9a185c54ce7..b16bc71c9cd2 100644
--- a/fs/jffs2/xattr.c
+++ b/fs/jffs2/xattr.c
@@ -456,7 +456,7 @@ static struct jffs2_xattr_datum *create_xattr_datum(struct jffs2_sb_info *c,
456 * is called to remove xrefs related to obsolete inode when inode is unlinked. 456 * is called to remove xrefs related to obsolete inode when inode is unlinked.
457 * jffs2_xattr_free_inode(c, ic) 457 * jffs2_xattr_free_inode(c, ic)
458 * is called to release xattr related objects when unmounting. 458 * is called to release xattr related objects when unmounting.
459 * check_xattr_ref_ilist(c, ic) 459 * check_xattr_ref_inode(c, ic)
460 * is used to confirm inode does not have duplicate xattr name/value pair. 460 * is used to confirm inode does not have duplicate xattr name/value pair.
461 * -------------------------------------------------- */ 461 * -------------------------------------------------- */
462static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) 462static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
@@ -549,7 +549,6 @@ static void delete_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *re
549 BUG_ON(!ref->node); 549 BUG_ON(!ref->node);
550 delete_xattr_ref_node(c, ref); 550 delete_xattr_ref_node(c, ref);
551 551
552 list_del(&ref->ilist);
553 xd = ref->xd; 552 xd = ref->xd;
554 xd->refcnt--; 553 xd->refcnt--;
555 if (!xd->refcnt) 554 if (!xd->refcnt)
@@ -629,7 +628,8 @@ static struct jffs2_xattr_ref *create_xattr_ref(struct jffs2_sb_info *c, struct
629 } 628 }
630 629
631 /* Chain to inode */ 630 /* Chain to inode */
632 list_add(&ref->ilist, &ic->ilist); 631 ref->next = ic->xref;
632 ic->xref = ref;
633 633
634 return ref; /* success */ 634 return ref; /* success */
635} 635}
@@ -644,8 +644,11 @@ void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache
644 return; 644 return;
645 645
646 down_write(&c->xattr_sem); 646 down_write(&c->xattr_sem);
647 list_for_each_entry_safe(ref, _ref, &ic->ilist, ilist) 647 for (ref = ic->xref; ref; ref = _ref) {
648 _ref = ref->next;
648 delete_xattr_ref(c, ref); 649 delete_xattr_ref(c, ref);
650 }
651 ic->xref = NULL;
649 up_write(&c->xattr_sem); 652 up_write(&c->xattr_sem);
650} 653}
651 654
@@ -656,8 +659,8 @@ void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *i
656 struct jffs2_xattr_ref *ref, *_ref; 659 struct jffs2_xattr_ref *ref, *_ref;
657 660
658 down_write(&c->xattr_sem); 661 down_write(&c->xattr_sem);
659 list_for_each_entry_safe(ref, _ref, &ic->ilist, ilist) { 662 for (ref = ic->xref; ref; ref = _ref) {
660 list_del(&ref->ilist); 663 _ref = ref->next;
661 xd = ref->xd; 664 xd = ref->xd;
662 xd->refcnt--; 665 xd->refcnt--;
663 if (!xd->refcnt) { 666 if (!xd->refcnt) {
@@ -666,16 +669,17 @@ void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *i
666 } 669 }
667 jffs2_free_xattr_ref(ref); 670 jffs2_free_xattr_ref(ref);
668 } 671 }
672 ic->xref = NULL;
669 up_write(&c->xattr_sem); 673 up_write(&c->xattr_sem);
670} 674}
671 675
672static int check_xattr_ref_ilist(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) 676static int check_xattr_ref_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
673{ 677{
674 /* success of check_xattr_ref_ilist() means taht inode (ic) dose not have 678 /* success of check_xattr_ref_inode() means taht inode (ic) dose not have
675 * duplicate name/value pairs. If duplicate name/value pair would be found, 679 * duplicate name/value pairs. If duplicate name/value pair would be found,
676 * one will be removed. 680 * one will be removed.
677 */ 681 */
678 struct jffs2_xattr_ref *ref, *cmp; 682 struct jffs2_xattr_ref *ref, *cmp, **pref;
679 int rc = 0; 683 int rc = 0;
680 684
681 if (likely(ic->flags & INO_FLAGS_XATTR_CHECKED)) 685 if (likely(ic->flags & INO_FLAGS_XATTR_CHECKED))
@@ -683,22 +687,23 @@ static int check_xattr_ref_ilist(struct jffs2_sb_info *c, struct jffs2_inode_cac
683 down_write(&c->xattr_sem); 687 down_write(&c->xattr_sem);
684 retry: 688 retry:
685 rc = 0; 689 rc = 0;
686 list_for_each_entry(ref, &ic->ilist, ilist) { 690 for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) {
687 if (!ref->xd->xname) { 691 if (!ref->xd->xname) {
688 rc = load_xattr_datum(c, ref->xd); 692 rc = load_xattr_datum(c, ref->xd);
689 if (unlikely(rc > 0)) { 693 if (unlikely(rc > 0)) {
694 *pref = ref->next;
690 delete_xattr_ref(c, ref); 695 delete_xattr_ref(c, ref);
691 goto retry; 696 goto retry;
692 } else if (unlikely(rc < 0)) 697 } else if (unlikely(rc < 0))
693 goto out; 698 goto out;
694 } 699 }
695 cmp = ref; 700 for (cmp=ref->next, pref=&ref->next; cmp; pref=&cmp->next, cmp=cmp->next) {
696 list_for_each_entry_continue(cmp, &ic->ilist, ilist) {
697 if (!cmp->xd->xname) { 701 if (!cmp->xd->xname) {
698 ref->xd->flags |= JFFS2_XFLAGS_BIND; 702 ref->xd->flags |= JFFS2_XFLAGS_BIND;
699 rc = load_xattr_datum(c, cmp->xd); 703 rc = load_xattr_datum(c, cmp->xd);
700 ref->xd->flags &= ~JFFS2_XFLAGS_BIND; 704 ref->xd->flags &= ~JFFS2_XFLAGS_BIND;
701 if (unlikely(rc > 0)) { 705 if (unlikely(rc > 0)) {
706 *pref = cmp->next;
702 delete_xattr_ref(c, cmp); 707 delete_xattr_ref(c, cmp);
703 goto retry; 708 goto retry;
704 } else if (unlikely(rc < 0)) 709 } else if (unlikely(rc < 0))
@@ -706,6 +711,7 @@ static int check_xattr_ref_ilist(struct jffs2_sb_info *c, struct jffs2_inode_cac
706 } 711 }
707 if (ref->xd->xprefix == cmp->xd->xprefix 712 if (ref->xd->xprefix == cmp->xd->xprefix
708 && !strcmp(ref->xd->xname, cmp->xd->xname)) { 713 && !strcmp(ref->xd->xname, cmp->xd->xname)) {
714 *pref = cmp->next;
709 delete_xattr_ref(c, cmp); 715 delete_xattr_ref(c, cmp);
710 goto retry; 716 goto retry;
711 } 717 }
@@ -736,8 +742,8 @@ void jffs2_init_xattr_subsystem(struct jffs2_sb_info *c)
736 742
737 for (i=0; i < XATTRINDEX_HASHSIZE; i++) 743 for (i=0; i < XATTRINDEX_HASHSIZE; i++)
738 INIT_LIST_HEAD(&c->xattrindex[i]); 744 INIT_LIST_HEAD(&c->xattrindex[i]);
739 INIT_LIST_HEAD(&c->xattr_temp);
740 INIT_LIST_HEAD(&c->xattr_unchecked); 745 INIT_LIST_HEAD(&c->xattr_unchecked);
746 c->xref_temp = NULL;
741 747
742 init_rwsem(&c->xattr_sem); 748 init_rwsem(&c->xattr_sem);
743 c->xdatum_mem_usage = 0; 749 c->xdatum_mem_usage = 0;
@@ -765,8 +771,11 @@ void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c)
765 struct jffs2_xattr_ref *ref, *_ref; 771 struct jffs2_xattr_ref *ref, *_ref;
766 int i; 772 int i;
767 773
768 list_for_each_entry_safe(ref, _ref, &c->xattr_temp, ilist) 774 for (ref=c->xref_temp; ref; ref = _ref) {
775 _ref = ref->next;
769 jffs2_free_xattr_ref(ref); 776 jffs2_free_xattr_ref(ref);
777 }
778 c->xref_temp = NULL;
770 779
771 for (i=0; i < XATTRINDEX_HASHSIZE; i++) { 780 for (i=0; i < XATTRINDEX_HASHSIZE; i++) {
772 list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) { 781 list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) {
@@ -788,8 +797,8 @@ void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c)
788 BUG_ON(!(c->flags & JFFS2_SB_FLAG_BUILDING)); 797 BUG_ON(!(c->flags & JFFS2_SB_FLAG_BUILDING));
789 798
790 /* Phase.1 */ 799 /* Phase.1 */
791 list_for_each_entry_safe(ref, _ref, &c->xattr_temp, ilist) { 800 for (ref=c->xref_temp; ref; ref=_ref) {
792 list_del_init(&ref->ilist); 801 _ref = ref->next;
793 /* checking REF_UNCHECKED nodes */ 802 /* checking REF_UNCHECKED nodes */
794 if (ref_flags(ref->node) != REF_PRISTINE) { 803 if (ref_flags(ref->node) != REF_PRISTINE) {
795 if (verify_xattr_ref(c, ref)) { 804 if (verify_xattr_ref(c, ref)) {
@@ -813,9 +822,11 @@ void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c)
813 ref->xd = xd; 822 ref->xd = xd;
814 ref->ic = ic; 823 ref->ic = ic;
815 xd->refcnt++; 824 xd->refcnt++;
816 list_add_tail(&ref->ilist, &ic->ilist); 825 ref->next = ic->xref;
826 ic->xref = ref;
817 xref_count++; 827 xref_count++;
818 } 828 }
829 c->xref_temp = NULL;
819 /* After this, ref->xid/ino are NEVER used. */ 830 /* After this, ref->xid/ino are NEVER used. */
820 831
821 /* Phase.2 */ 832 /* Phase.2 */
@@ -931,20 +942,20 @@ ssize_t jffs2_listxattr(struct dentry *dentry, char *buffer, size_t size)
931 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); 942 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
932 struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); 943 struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
933 struct jffs2_inode_cache *ic = f->inocache; 944 struct jffs2_inode_cache *ic = f->inocache;
934 struct jffs2_xattr_ref *ref; 945 struct jffs2_xattr_ref *ref, **pref;
935 struct jffs2_xattr_datum *xd; 946 struct jffs2_xattr_datum *xd;
936 struct xattr_handler *xhandle; 947 struct xattr_handler *xhandle;
937 ssize_t len, rc; 948 ssize_t len, rc;
938 int retry = 0; 949 int retry = 0;
939 950
940 rc = check_xattr_ref_ilist(c, ic); 951 rc = check_xattr_ref_inode(c, ic);
941 if (unlikely(rc)) 952 if (unlikely(rc))
942 return rc; 953 return rc;
943 954
944 down_read(&c->xattr_sem); 955 down_read(&c->xattr_sem);
945 retry: 956 retry:
946 len = 0; 957 len = 0;
947 list_for_each_entry(ref, &ic->ilist, ilist) { 958 for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) {
948 BUG_ON(ref->ic != ic); 959 BUG_ON(ref->ic != ic);
949 xd = ref->xd; 960 xd = ref->xd;
950 if (!xd->xname) { 961 if (!xd->xname) {
@@ -957,6 +968,7 @@ ssize_t jffs2_listxattr(struct dentry *dentry, char *buffer, size_t size)
957 } else { 968 } else {
958 rc = load_xattr_datum(c, xd); 969 rc = load_xattr_datum(c, xd);
959 if (unlikely(rc > 0)) { 970 if (unlikely(rc > 0)) {
971 *pref = ref->next;
960 delete_xattr_ref(c, ref); 972 delete_xattr_ref(c, ref);
961 goto retry; 973 goto retry;
962 } else if (unlikely(rc < 0)) 974 } else if (unlikely(rc < 0))
@@ -992,16 +1004,16 @@ int do_jffs2_getxattr(struct inode *inode, int xprefix, const char *xname,
992 struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); 1004 struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
993 struct jffs2_inode_cache *ic = f->inocache; 1005 struct jffs2_inode_cache *ic = f->inocache;
994 struct jffs2_xattr_datum *xd; 1006 struct jffs2_xattr_datum *xd;
995 struct jffs2_xattr_ref *ref; 1007 struct jffs2_xattr_ref *ref, **pref;
996 int rc, retry = 0; 1008 int rc, retry = 0;
997 1009
998 rc = check_xattr_ref_ilist(c, ic); 1010 rc = check_xattr_ref_inode(c, ic);
999 if (unlikely(rc)) 1011 if (unlikely(rc))
1000 return rc; 1012 return rc;
1001 1013
1002 down_read(&c->xattr_sem); 1014 down_read(&c->xattr_sem);
1003 retry: 1015 retry:
1004 list_for_each_entry(ref, &ic->ilist, ilist) { 1016 for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) {
1005 BUG_ON(ref->ic!=ic); 1017 BUG_ON(ref->ic!=ic);
1006 1018
1007 xd = ref->xd; 1019 xd = ref->xd;
@@ -1017,6 +1029,7 @@ int do_jffs2_getxattr(struct inode *inode, int xprefix, const char *xname,
1017 } else { 1029 } else {
1018 rc = load_xattr_datum(c, xd); 1030 rc = load_xattr_datum(c, xd);
1019 if (unlikely(rc > 0)) { 1031 if (unlikely(rc > 0)) {
1032 *pref = ref->next;
1020 delete_xattr_ref(c, ref); 1033 delete_xattr_ref(c, ref);
1021 goto retry; 1034 goto retry;
1022 } else if (unlikely(rc < 0)) { 1035 } else if (unlikely(rc < 0)) {
@@ -1053,11 +1066,11 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
1053 struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); 1066 struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
1054 struct jffs2_inode_cache *ic = f->inocache; 1067 struct jffs2_inode_cache *ic = f->inocache;
1055 struct jffs2_xattr_datum *xd; 1068 struct jffs2_xattr_datum *xd;
1056 struct jffs2_xattr_ref *ref, *newref; 1069 struct jffs2_xattr_ref *ref, *newref, **pref;
1057 uint32_t phys_ofs, length, request; 1070 uint32_t phys_ofs, length, request;
1058 int rc; 1071 int rc;
1059 1072
1060 rc = check_xattr_ref_ilist(c, ic); 1073 rc = check_xattr_ref_inode(c, ic);
1061 if (unlikely(rc)) 1074 if (unlikely(rc))
1062 return rc; 1075 return rc;
1063 1076
@@ -1072,13 +1085,14 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
1072 /* Find existing xattr */ 1085 /* Find existing xattr */
1073 down_write(&c->xattr_sem); 1086 down_write(&c->xattr_sem);
1074 retry: 1087 retry:
1075 list_for_each_entry(ref, &ic->ilist, ilist) { 1088 for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) {
1076 xd = ref->xd; 1089 xd = ref->xd;
1077 if (xd->xprefix != xprefix) 1090 if (xd->xprefix != xprefix)
1078 continue; 1091 continue;
1079 if (!xd->xname) { 1092 if (!xd->xname) {
1080 rc = load_xattr_datum(c, xd); 1093 rc = load_xattr_datum(c, xd);
1081 if (unlikely(rc > 0)) { 1094 if (unlikely(rc > 0)) {
1095 *pref = ref->next;
1082 delete_xattr_ref(c, ref); 1096 delete_xattr_ref(c, ref);
1083 goto retry; 1097 goto retry;
1084 } else if (unlikely(rc < 0)) 1098 } else if (unlikely(rc < 0))
@@ -1090,6 +1104,7 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
1090 goto out; 1104 goto out;
1091 } 1105 }
1092 if (!buffer) { 1106 if (!buffer) {
1107 *pref = ref->next;
1093 delete_xattr_ref(c, ref); 1108 delete_xattr_ref(c, ref);
1094 rc = 0; 1109 rc = 0;
1095 goto out; 1110 goto out;
@@ -1098,7 +1113,6 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
1098 } 1113 }
1099 } 1114 }
1100 /* not found */ 1115 /* not found */
1101 ref = NULL;
1102 if (flags & XATTR_REPLACE) { 1116 if (flags & XATTR_REPLACE) {
1103 rc = -ENODATA; 1117 rc = -ENODATA;
1104 goto out; 1118 goto out;
@@ -1130,14 +1144,19 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
1130 return rc; 1144 return rc;
1131 } 1145 }
1132 down_write(&c->xattr_sem); 1146 down_write(&c->xattr_sem);
1147 if (ref)
1148 *pref = ref->next;
1133 newref = create_xattr_ref(c, ic, xd, phys_ofs); 1149 newref = create_xattr_ref(c, ic, xd, phys_ofs);
1134 if (IS_ERR(newref)) { 1150 if (IS_ERR(newref)) {
1151 if (ref) {
1152 ref->next = ic->xref;
1153 ic->xref = ref;
1154 }
1135 rc = PTR_ERR(newref); 1155 rc = PTR_ERR(newref);
1136 xd->refcnt--; 1156 xd->refcnt--;
1137 if (!xd->refcnt) 1157 if (!xd->refcnt)
1138 delete_xattr_datum(c, xd); 1158 delete_xattr_datum(c, xd);
1139 } else if (ref) { 1159 } else if (ref) {
1140 /* If replaced xattr_ref exists */
1141 delete_xattr_ref(c, ref); 1160 delete_xattr_ref(c, ref);
1142 } 1161 }
1143 out: 1162 out:
diff --git a/fs/jffs2/xattr.h b/fs/jffs2/xattr.h
index d157ad641ed4..0360097e5933 100644
--- a/fs/jffs2/xattr.h
+++ b/fs/jffs2/xattr.h
@@ -54,7 +54,7 @@ struct jffs2_xattr_ref
54 struct jffs2_xattr_datum *xd; /* reference to jffs2_xattr_datum */ 54 struct jffs2_xattr_datum *xd; /* reference to jffs2_xattr_datum */
55 uint32_t xid; /* only used in sccanning/building */ 55 uint32_t xid; /* only used in sccanning/building */
56 }; 56 };
57 struct list_head ilist; /* chained from ic->ilist */ 57 struct jffs2_xattr_ref *next; /* chained from ic->xref_list */
58}; 58};
59 59
60#ifdef CONFIG_JFFS2_FS_XATTR 60#ifdef CONFIG_JFFS2_FS_XATTR
@@ -86,9 +86,6 @@ extern ssize_t jffs2_listxattr(struct dentry *, char *, size_t);
86#define jffs2_setxattr generic_setxattr 86#define jffs2_setxattr generic_setxattr
87#define jffs2_removexattr generic_removexattr 87#define jffs2_removexattr generic_removexattr
88 88
89/*---- Any inline initialize functions ----*/
90#define init_xattr_inode_cache(x) INIT_LIST_HEAD(&((x)->ilist))
91
92#else 89#else
93 90
94#define jffs2_init_xattr_subsystem(c) 91#define jffs2_init_xattr_subsystem(c)
@@ -106,8 +103,6 @@ extern ssize_t jffs2_listxattr(struct dentry *, char *, size_t);
106#define jffs2_setxattr NULL 103#define jffs2_setxattr NULL
107#define jffs2_removexattr NULL 104#define jffs2_removexattr NULL
108 105
109#define init_xattr_inode_cache(x)
110
111#endif /* CONFIG_JFFS2_FS_XATTR */ 106#endif /* CONFIG_JFFS2_FS_XATTR */
112 107
113#ifdef CONFIG_JFFS2_FS_SECURITY 108#ifdef CONFIG_JFFS2_FS_SECURITY