summaryrefslogtreecommitdiff
path: root/fs/jffs2/summary.c
diff options
context:
space:
mode:
authorKaiGai Kohei <kaigai@ak.jp.nec.com>2006-05-13 15:09:47 +0900
committerKaiGai Kohei <kaigai@ak.jp.nec.com>2006-05-13 15:09:47 +0900
commitaa98d7cf59b5b0764d3502662053489585faf2fe (patch)
treee98e83f3e69ebe3a1112394a19d440419e899749 /fs/jffs2/summary.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/summary.c')
-rw-r--r--fs/jffs2/summary.c191
1 files changed, 191 insertions, 0 deletions
diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c
index 7b0ed77a4c35..5d9ec8e36528 100644
--- a/fs/jffs2/summary.c
+++ b/fs/jffs2/summary.c
@@ -5,6 +5,7 @@
* Zoltan Sogor <weth@inf.u-szeged.hu>,
* Patrik Kluba <pajko@halom.u-szeged.hu>,
* University of Szeged, Hungary
+ * 2005 KaiGai Kohei <kaigai@ak.jp.nec.com>
*
* For licensing information, see the file 'LICENCE' in this directory.
*
@@ -81,6 +82,19 @@ static int jffs2_sum_add_mem(struct jffs2_summary *s, union jffs2_sum_mem *item)
dbg_summary("dirent (%u) added to summary\n",
je32_to_cpu(item->d.ino));
break;
+#ifdef CONFIG_JFFS2_FS_XATTR
+ case JFFS2_NODETYPE_XATTR:
+ s->sum_size += JFFS2_SUMMARY_XATTR_SIZE;
+ s->sum_num++;
+ dbg_summary("xattr (xid=%u, version=%u) added to summary\n",
+ je32_to_cpu(item->x.xid), je32_to_cpu(item->x.version));
+ break;
+ case JFFS2_NODETYPE_XREF:
+ s->sum_size += JFFS2_SUMMARY_XREF_SIZE;
+ s->sum_num++;
+ dbg_summary("xref added to summary\n");
+ break;
+#endif
default:
JFFS2_WARNING("UNKNOWN node type %u\n",
je16_to_cpu(item->u.nodetype));
@@ -141,6 +155,40 @@ int jffs2_sum_add_dirent_mem(struct jffs2_summary *s, struct jffs2_raw_dirent *r
return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp);
}
+#ifdef CONFIG_JFFS2_FS_XATTR
+int jffs2_sum_add_xattr_mem(struct jffs2_summary *s, struct jffs2_raw_xattr *rx, uint32_t ofs)
+{
+ struct jffs2_sum_xattr_mem *temp;
+
+ temp = kmalloc(sizeof(struct jffs2_sum_xattr_mem), GFP_KERNEL);
+ if (!temp)
+ return -ENOMEM;
+
+ temp->nodetype = rx->nodetype;
+ temp->xid = rx->xid;
+ temp->version = rx->version;
+ temp->offset = cpu_to_je32(ofs);
+ temp->totlen = rx->totlen;
+ temp->next = NULL;
+
+ return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp);
+}
+
+int jffs2_sum_add_xref_mem(struct jffs2_summary *s, struct jffs2_raw_xref *rr, uint32_t ofs)
+{
+ struct jffs2_sum_xref_mem *temp;
+
+ temp = kmalloc(sizeof(struct jffs2_sum_xref_mem), GFP_KERNEL);
+ if (!temp)
+ return -ENOMEM;
+
+ temp->nodetype = rr->nodetype;
+ temp->offset = cpu_to_je32(ofs);
+ temp->next = NULL;
+
+ return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp);
+}
+#endif
/* Cleanup every collected summary information */
static void jffs2_sum_clean_collected(struct jffs2_summary *s)
@@ -259,7 +307,40 @@ int jffs2_sum_add_kvec(struct jffs2_sb_info *c, const struct kvec *invecs,
return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp);
}
+#ifdef CONFIG_JFFS2_FS_XATTR
+ case JFFS2_NODETYPE_XATTR: {
+ struct jffs2_sum_xattr_mem *temp;
+ if (je32_to_cpu(node->x.version) == 0xffffffff)
+ return 0;
+ temp = kmalloc(sizeof(struct jffs2_sum_xattr_mem), GFP_KERNEL);
+ if (!temp)
+ goto no_mem;
+ temp->nodetype = node->x.nodetype;
+ temp->xid = node->x.xid;
+ temp->version = node->x.version;
+ temp->totlen = node->x.totlen;
+ temp->offset = cpu_to_je32(ofs);
+ temp->next = NULL;
+
+ return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp);
+ }
+ case JFFS2_NODETYPE_XREF: {
+ struct jffs2_sum_xref_mem *temp;
+
+ if (je32_to_cpu(node->r.ino) == 0xffffffff
+ && je32_to_cpu(node->r.xid) == 0xffffffff)
+ return 0;
+ temp = kmalloc(sizeof(struct jffs2_sum_xref_mem), GFP_KERNEL);
+ if (!temp)
+ goto no_mem;
+ temp->nodetype = node->r.nodetype;
+ temp->offset = cpu_to_je32(ofs);
+ temp->next = NULL;
+
+ return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp);
+ }
+#endif
case JFFS2_NODETYPE_PADDING:
dbg_summary("node PADDING\n");
c->summary->sum_padded += je32_to_cpu(node->u.totlen);
@@ -408,8 +489,94 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
break;
}
+#ifdef CONFIG_JFFS2_FS_XATTR
+ case JFFS2_NODETYPE_XATTR: {
+ struct jffs2_xattr_datum *xd;
+ struct jffs2_sum_xattr_flash *spx;
+ uint32_t ofs;
+
+ spx = (struct jffs2_sum_xattr_flash *)sp;
+ ofs = jeb->offset + je32_to_cpu(spx->offset);
+ dbg_summary("xattr at %#08x (xid=%u, version=%u)\n", ofs,
+ je32_to_cpu(spx->xid), je32_to_cpu(spx->version));
+ raw = jffs2_alloc_raw_node_ref();
+ if (!raw) {
+ JFFS2_NOTICE("allocation of node reference failed\n");
+ kfree(summary);
+ return -ENOMEM;
+ }
+ xd = jffs2_setup_xattr_datum(c, je32_to_cpu(spx->xid),
+ je32_to_cpu(spx->version));
+ if (IS_ERR(xd)) {
+ JFFS2_NOTICE("allocation of xattr_datum failed\n");
+ jffs2_free_raw_node_ref(raw);
+ kfree(summary);
+ return PTR_ERR(xd);
+ }
+ xd->node = raw;
+ raw->flash_offset = ofs | REF_UNCHECKED;
+ raw->__totlen = PAD(je32_to_cpu(spx->totlen));
+ raw->next_phys = NULL;
+ raw->next_in_ino = (void *)xd;
+ if (!jeb->first_node)
+ jeb->first_node = raw;
+ if (jeb->last_node)
+ jeb->last_node->next_phys = raw;
+ jeb->last_node = raw;
+
+ *pseudo_random += je32_to_cpu(spx->xid);
+ UNCHECKED_SPACE(je32_to_cpu(spx->totlen));
+ sp += JFFS2_SUMMARY_XATTR_SIZE;
+
+ break;
+ }
+ case JFFS2_NODETYPE_XREF: {
+ struct jffs2_xattr_ref *ref;
+ struct jffs2_sum_xref_flash *spr;
+ uint32_t ofs;
+
+ spr = (struct jffs2_sum_xref_flash *)sp;
+ ofs = jeb->offset + je32_to_cpu(spr->offset);
+ dbg_summary("xref at %#08x (xid=%u, ino=%u)\n", ofs,
+ je32_to_cpu(spr->xid), je32_to_cpu(spr->ino));
+ raw = jffs2_alloc_raw_node_ref();
+ if (!raw) {
+ JFFS2_NOTICE("allocation of node reference failed\n");
+ kfree(summary);
+ return -ENOMEM;
+ }
+ ref = jffs2_alloc_xattr_ref();
+ if (!ref) {
+ JFFS2_NOTICE("allocation of xattr_datum failed\n");
+ jffs2_free_raw_node_ref(raw);
+ kfree(summary);
+ return -ENOMEM;
+ }
+ ref->ino = 0xfffffffe;
+ ref->xid = 0xfffffffd;
+ ref->node = raw;
+ list_add_tail(&ref->ilist, &c->xattr_temp);
+
+ raw->__totlen = PAD(sizeof(struct jffs2_raw_xref));
+ raw->flash_offset = ofs | REF_UNCHECKED;
+ raw->next_phys = NULL;
+ raw->next_in_ino = (void *)ref;
+ if (!jeb->first_node)
+ jeb->first_node = raw;
+ if (jeb->last_node)
+ jeb->last_node->next_phys = raw;
+ jeb->last_node = raw;
+
+ UNCHECKED_SPACE(PAD(sizeof(struct jffs2_raw_xref)));
+ *pseudo_random += ofs;
+ sp += JFFS2_SUMMARY_XREF_SIZE;
+
+ break;
+ }
+#endif
default : {
+printk("nodetype = %#04x\n",je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype));
JFFS2_WARNING("Unsupported node type found in summary! Exiting...");
kfree(summary);
return -EIO;
@@ -617,7 +784,31 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock
break;
}
+#ifdef CONFIG_JFFS2_FS_XATTR
+ case JFFS2_NODETYPE_XATTR: {
+ struct jffs2_sum_xattr_flash *sxattr_ptr = wpage;
+
+ temp = c->summary->sum_list_head;
+ sxattr_ptr->nodetype = temp->x.nodetype;
+ sxattr_ptr->xid = temp->x.xid;
+ sxattr_ptr->version = temp->x.version;
+ sxattr_ptr->offset = temp->x.offset;
+ sxattr_ptr->totlen = temp->x.totlen;
+
+ wpage += JFFS2_SUMMARY_XATTR_SIZE;
+ break;
+ }
+ case JFFS2_NODETYPE_XREF: {
+ struct jffs2_sum_xref_flash *sxref_ptr = wpage;
+
+ temp = c->summary->sum_list_head;
+ sxref_ptr->nodetype = temp->r.nodetype;
+ sxref_ptr->offset = temp->r.offset;
+ wpage += JFFS2_SUMMARY_XREF_SIZE;
+ break;
+ }
+#endif
default : {
BUG(); /* unknown node in summary information */
}