[JFFS2][XATTR] Remove 'struct list_head ilist' from jffs2_inode_cache.

This patch can reduce 4-byte of memory usage per inode_cache.

[4/10] jffs2-xattr-v5.1-04-remove_ilist_from_ic.patch

Signed-off-by: KaiGai Kohei <kaigai@ak.jp.nec.com>
diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h
index 3b4e0ed..272fbea 100644
--- a/fs/jffs2/jffs2_fs_sb.h
+++ b/fs/jffs2/jffs2_fs_sb.h
@@ -119,8 +119,8 @@
 #define XATTRINDEX_HASHSIZE	(57)
 	uint32_t highest_xid;
 	struct list_head xattrindex[XATTRINDEX_HASHSIZE];
-	struct list_head xattr_temp;
 	struct list_head xattr_unchecked;
+	struct jffs2_xattr_ref *xref_temp;
 	struct rw_semaphore xattr_sem;
 	uint32_t xdatum_mem_usage;
 	uint32_t xdatum_mem_threshold;
diff --git a/fs/jffs2/malloc.c b/fs/jffs2/malloc.c
index 3d5b7ec..f2473fa 100644
--- a/fs/jffs2/malloc.c
+++ b/fs/jffs2/malloc.c
@@ -259,7 +259,6 @@
 
 	memset(ref, 0, sizeof(struct jffs2_xattr_ref));
 	ref->class = RAWNODE_CLASS_XATTR_REF;
-	INIT_LIST_HEAD(&ref->ilist);
 	return ref;
 }
 
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h
index 6f6279c..351d947 100644
--- a/fs/jffs2/nodelist.h
+++ b/fs/jffs2/nodelist.h
@@ -117,7 +117,7 @@
 	uint32_t ino;
 	int nlink;
 #ifdef CONFIG_JFFS2_FS_XATTR
-	struct list_head ilist;
+	struct jffs2_xattr_ref *xref;
 #endif
 };
 
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
index 61ccdf4..e1acce8 100644
--- a/fs/jffs2/readinode.c
+++ b/fs/jffs2/readinode.c
@@ -902,7 +902,6 @@
 		f->inocache->ino = f->inocache->nlink = 1;
 		f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
 		f->inocache->state = INO_STATE_READING;
-		init_xattr_inode_cache(f->inocache);
 		jffs2_add_ino_cache(c, f->inocache);
 	}
 	if (!f->inocache) {
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
index f09689e..0a79fc9 100644
--- a/fs/jffs2/scan.c
+++ b/fs/jffs2/scan.c
@@ -408,14 +408,15 @@
 	 * ref->xid is used to store 32bit xid, xd is not used
 	 * ref->ino is used to store 32bit inode-number, ic is not used
 	 * Thoes variables are declared as union, thus using those
-	 * are exclusive. In a similar way, ref->ilist is temporarily
+	 * are exclusive. In a similar way, ref->next is temporarily
 	 * used to chain all xattr_ref object. It's re-chained to
 	 * jffs2_inode_cache in jffs2_build_xattr_subsystem() correctly.
 	 */
 	ref->node = raw;
 	ref->ino = je32_to_cpu(rr->ino);
 	ref->xid = je32_to_cpu(rr->xid);
-	list_add_tail(&ref->ilist, &c->xattr_temp);
+	ref->next = c->xref_temp;
+	c->xref_temp = ref;
 
 	raw->__totlen = PAD(je32_to_cpu(rr->totlen));
 	raw->flash_offset = ofs | REF_PRISTINE;
@@ -888,7 +889,6 @@
 
 	ic->ino = ino;
 	ic->nodes = (void *)ic;
-	init_xattr_inode_cache(ic);
 	jffs2_add_ino_cache(c, ic);
 	if (ino == 1)
 		ic->nlink = 1;
diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c
index 5d9ec8e..831a42c 100644
--- a/fs/jffs2/summary.c
+++ b/fs/jffs2/summary.c
@@ -556,7 +556,8 @@
 				ref->ino = 0xfffffffe;
 				ref->xid = 0xfffffffd;
 				ref->node = raw;
-				list_add_tail(&ref->ilist, &c->xattr_temp);
+				ref->next = c->xref_temp;
+				c->xref_temp = ref;
 
 				raw->__totlen = PAD(sizeof(struct jffs2_raw_xref));
 				raw->flash_offset = ofs | REF_UNCHECKED;
diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c
index d5c7819..ff2b00b 100644
--- a/fs/jffs2/write.c
+++ b/fs/jffs2/write.c
@@ -36,7 +36,6 @@
 	f->inocache->nlink = 1;
 	f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
 	f->inocache->state = INO_STATE_PRESENT;
-	init_xattr_inode_cache(f->inocache);
 
 	jffs2_add_ino_cache(c, f->inocache);
 	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 c9a185c..b16bc71 100644
--- a/fs/jffs2/xattr.c
+++ b/fs/jffs2/xattr.c
@@ -456,7 +456,7 @@
  *   is called to remove xrefs related to obsolete inode when inode is unlinked.
  * jffs2_xattr_free_inode(c, ic)
  *   is called to release xattr related objects when unmounting. 
- * check_xattr_ref_ilist(c, ic)
+ * check_xattr_ref_inode(c, ic)
  *   is used to confirm inode does not have duplicate xattr name/value pair.
  * -------------------------------------------------- */
 static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
@@ -549,7 +549,6 @@
 	BUG_ON(!ref->node);
 	delete_xattr_ref_node(c, ref);
 
-	list_del(&ref->ilist);
 	xd = ref->xd;
 	xd->refcnt--;
 	if (!xd->refcnt)
@@ -629,7 +628,8 @@
 	}
 
 	/* Chain to inode */
-	list_add(&ref->ilist, &ic->ilist);
+	ref->next = ic->xref;
+	ic->xref = ref;
 
 	return ref; /* success */
 }
@@ -644,8 +644,11 @@
 		return;
 
 	down_write(&c->xattr_sem);
-	list_for_each_entry_safe(ref, _ref, &ic->ilist, ilist)
+	for (ref = ic->xref; ref; ref = _ref) {
+		_ref = ref->next;
 		delete_xattr_ref(c, ref);
+	}
+	ic->xref = NULL;
 	up_write(&c->xattr_sem);
 }
 
@@ -656,8 +659,8 @@
 	struct jffs2_xattr_ref *ref, *_ref;
 
 	down_write(&c->xattr_sem);
-	list_for_each_entry_safe(ref, _ref, &ic->ilist, ilist) {
-		list_del(&ref->ilist);
+	for (ref = ic->xref; ref; ref = _ref) {
+		_ref = ref->next;
 		xd = ref->xd;
 		xd->refcnt--;
 		if (!xd->refcnt) {
@@ -666,16 +669,17 @@
 		}
 		jffs2_free_xattr_ref(ref);
 	}
+	ic->xref = NULL;
 	up_write(&c->xattr_sem);
 }
 
-static int check_xattr_ref_ilist(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
+static int check_xattr_ref_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
 {
-	/* success of check_xattr_ref_ilist() means taht inode (ic) dose not have
+	/* success of check_xattr_ref_inode() means taht inode (ic) dose not have
 	 * duplicate name/value pairs. If duplicate name/value pair would be found,
 	 * one will be removed.
 	 */
-	struct jffs2_xattr_ref *ref, *cmp;
+	struct jffs2_xattr_ref *ref, *cmp, **pref;
 	int rc = 0;
 
 	if (likely(ic->flags & INO_FLAGS_XATTR_CHECKED))
@@ -683,22 +687,23 @@
 	down_write(&c->xattr_sem);
  retry:
 	rc = 0;
-	list_for_each_entry(ref, &ic->ilist, ilist) {
+	for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) {
 		if (!ref->xd->xname) {
 			rc = load_xattr_datum(c, ref->xd);
 			if (unlikely(rc > 0)) {
+				*pref = ref->next;
 				delete_xattr_ref(c, ref);
 				goto retry;
 			} else if (unlikely(rc < 0))
 				goto out;
 		}
-		cmp = ref;
-		list_for_each_entry_continue(cmp, &ic->ilist, ilist) {
+		for (cmp=ref->next, pref=&ref->next; cmp; pref=&cmp->next, cmp=cmp->next) {
 			if (!cmp->xd->xname) {
 				ref->xd->flags |= JFFS2_XFLAGS_BIND;
 				rc = load_xattr_datum(c, cmp->xd);
 				ref->xd->flags &= ~JFFS2_XFLAGS_BIND;
 				if (unlikely(rc > 0)) {
+					*pref = cmp->next;
 					delete_xattr_ref(c, cmp);
 					goto retry;
 				} else if (unlikely(rc < 0))
@@ -706,6 +711,7 @@
 			}
 			if (ref->xd->xprefix == cmp->xd->xprefix
 			    && !strcmp(ref->xd->xname, cmp->xd->xname)) {
+				*pref = cmp->next;
 				delete_xattr_ref(c, cmp);
 				goto retry;
 			}
@@ -736,8 +742,8 @@
 
 	for (i=0; i < XATTRINDEX_HASHSIZE; i++)
 		INIT_LIST_HEAD(&c->xattrindex[i]);
-	INIT_LIST_HEAD(&c->xattr_temp);
 	INIT_LIST_HEAD(&c->xattr_unchecked);
+	c->xref_temp = NULL;
 
 	init_rwsem(&c->xattr_sem);
 	c->xdatum_mem_usage = 0;
@@ -765,8 +771,11 @@
 	struct jffs2_xattr_ref *ref, *_ref;
 	int i;
 
-	list_for_each_entry_safe(ref, _ref, &c->xattr_temp, ilist)
+	for (ref=c->xref_temp; ref; ref = _ref) {
+		_ref = ref->next;
 		jffs2_free_xattr_ref(ref);
+	}
+	c->xref_temp = NULL;
 
 	for (i=0; i < XATTRINDEX_HASHSIZE; i++) {
 		list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) {
@@ -788,8 +797,8 @@
 	BUG_ON(!(c->flags & JFFS2_SB_FLAG_BUILDING));
 
 	/* Phase.1 */
-	list_for_each_entry_safe(ref, _ref, &c->xattr_temp, ilist) {
-		list_del_init(&ref->ilist);
+	for (ref=c->xref_temp; ref; ref=_ref) {
+		_ref = ref->next;
 		/* checking REF_UNCHECKED nodes */
 		if (ref_flags(ref->node) != REF_PRISTINE) {
 			if (verify_xattr_ref(c, ref)) {
@@ -813,9 +822,11 @@
 		ref->xd = xd;
 		ref->ic = ic;
 		xd->refcnt++;
-		list_add_tail(&ref->ilist, &ic->ilist);
+		ref->next = ic->xref;
+		ic->xref = ref;
 		xref_count++;
 	}
+	c->xref_temp = NULL;
 	/* After this, ref->xid/ino are NEVER used. */
 
 	/* Phase.2 */
@@ -931,20 +942,20 @@
 	struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
 	struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
 	struct jffs2_inode_cache *ic = f->inocache;
-	struct jffs2_xattr_ref *ref;
+	struct jffs2_xattr_ref *ref, **pref;
 	struct jffs2_xattr_datum *xd;
 	struct xattr_handler *xhandle;
 	ssize_t len, rc;
 	int retry = 0;
 
-	rc = check_xattr_ref_ilist(c, ic);
+	rc = check_xattr_ref_inode(c, ic);
 	if (unlikely(rc))
 		return rc;
 
 	down_read(&c->xattr_sem);
  retry:
 	len = 0;
-	list_for_each_entry(ref, &ic->ilist, ilist) {
+	for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) {
 		BUG_ON(ref->ic != ic);
 		xd = ref->xd;
 		if (!xd->xname) {
@@ -957,6 +968,7 @@
 			} else {
 				rc = load_xattr_datum(c, xd);
 				if (unlikely(rc > 0)) {
+					*pref = ref->next;
 					delete_xattr_ref(c, ref);
 					goto retry;
 				} else if (unlikely(rc < 0))
@@ -992,16 +1004,16 @@
 	struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
 	struct jffs2_inode_cache *ic = f->inocache;
 	struct jffs2_xattr_datum *xd;
-	struct jffs2_xattr_ref *ref;
+	struct jffs2_xattr_ref *ref, **pref;
 	int rc, retry = 0;
 
-	rc = check_xattr_ref_ilist(c, ic);
+	rc = check_xattr_ref_inode(c, ic);
 	if (unlikely(rc))
 		return rc;
 
 	down_read(&c->xattr_sem);
  retry:
-	list_for_each_entry(ref, &ic->ilist, ilist) {
+	for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) {
 		BUG_ON(ref->ic!=ic);
 
 		xd = ref->xd;
@@ -1017,6 +1029,7 @@
 			} else {
 				rc = load_xattr_datum(c, xd);
 				if (unlikely(rc > 0)) {
+					*pref = ref->next;
 					delete_xattr_ref(c, ref);
 					goto retry;
 				} else if (unlikely(rc < 0)) {
@@ -1053,11 +1066,11 @@
 	struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
 	struct jffs2_inode_cache *ic = f->inocache;
 	struct jffs2_xattr_datum *xd;
-	struct jffs2_xattr_ref *ref, *newref;
+	struct jffs2_xattr_ref *ref, *newref, **pref;
 	uint32_t phys_ofs, length, request;
 	int rc;
 
-	rc = check_xattr_ref_ilist(c, ic);
+	rc = check_xattr_ref_inode(c, ic);
 	if (unlikely(rc))
 		return rc;
 
@@ -1072,13 +1085,14 @@
 	/* Find existing xattr */
 	down_write(&c->xattr_sem);
  retry:
-	list_for_each_entry(ref, &ic->ilist, ilist) {
+	for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) {
 		xd = ref->xd;
 		if (xd->xprefix != xprefix)
 			continue;
 		if (!xd->xname) {
 			rc = load_xattr_datum(c, xd);
 			if (unlikely(rc > 0)) {
+				*pref = ref->next;
 				delete_xattr_ref(c, ref);
 				goto retry;
 			} else if (unlikely(rc < 0))
@@ -1090,6 +1104,7 @@
 				goto out;
 			}
 			if (!buffer) {
+				*pref = ref->next;
 				delete_xattr_ref(c, ref);
 				rc = 0;
 				goto out;
@@ -1098,7 +1113,6 @@
 		}
 	}
 	/* not found */
-	ref = NULL;
 	if (flags & XATTR_REPLACE) {
 		rc = -ENODATA;
 		goto out;
@@ -1130,14 +1144,19 @@
 		return rc;
 	}
 	down_write(&c->xattr_sem);
+	if (ref)
+		*pref = ref->next;
 	newref = create_xattr_ref(c, ic, xd, phys_ofs);
 	if (IS_ERR(newref)) {
+		if (ref) {
+			ref->next = ic->xref;
+			ic->xref = ref;
+		}
 		rc = PTR_ERR(newref);
 		xd->refcnt--;
 		if (!xd->refcnt)
 			delete_xattr_datum(c, xd);
 	} else if (ref) {
-		/* If replaced xattr_ref exists */
 		delete_xattr_ref(c, ref);
 	}
  out:
diff --git a/fs/jffs2/xattr.h b/fs/jffs2/xattr.h
index d157ad6..0360097 100644
--- a/fs/jffs2/xattr.h
+++ b/fs/jffs2/xattr.h
@@ -54,7 +54,7 @@
 		struct jffs2_xattr_datum *xd;	/* reference to jffs2_xattr_datum */
 		uint32_t xid;			/* only used in sccanning/building */
 	};
-	struct list_head ilist;			/* chained from ic->ilist */
+	struct jffs2_xattr_ref *next;		/* chained from ic->xref_list */
 };
 
 #ifdef CONFIG_JFFS2_FS_XATTR
@@ -86,9 +86,6 @@
 #define jffs2_setxattr		generic_setxattr
 #define jffs2_removexattr	generic_removexattr
 
-/*---- Any inline initialize functions ----*/
-#define init_xattr_inode_cache(x) INIT_LIST_HEAD(&((x)->ilist))
-
 #else
 
 #define jffs2_init_xattr_subsystem(c)
@@ -106,8 +103,6 @@
 #define jffs2_setxattr		NULL
 #define jffs2_removexattr	NULL
 
-#define init_xattr_inode_cache(x)
-
 #endif /* CONFIG_JFFS2_FS_XATTR */
 
 #ifdef CONFIG_JFFS2_FS_SECURITY