diff -prNU3 mtd-utils.git/include/linux/jffs2.h mtd-utils.xattr/include/linux/jffs2.h
--- mtd-utils.git/include/linux/jffs2.h	2006-05-05 20:24:18.000000000 +0900
+++ mtd-utils.xattr/include/linux/jffs2.h	2006-05-05 21:33:48.000000000 +0900
@@ -65,6 +65,18 @@
 
 #define JFFS2_NODETYPE_SUMMARY (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 6)
 
+#define JFFS2_NODETYPE_XATTR (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 8)
+#define JFFS2_NODETYPE_XREF (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 9)
+
+/* XATTR Related */
+#define JFFS2_XPREFIX_USER		1	/* for "user." */
+#define JFFS2_XPREFIX_SECURITY		2	/* for "security." */
+#define JFFS2_XPREFIX_ACL_ACCESS	3	/* for "system.posix_acl_access" */
+#define JFFS2_XPREFIX_ACL_DEFAULT	4	/* for "system.posix_acl_default" */
+#define JFFS2_XPREFIX_TRUSTED		5	/* for "trusted.*" */
+
+#define JFFS2_ACL_VERSION		0x0001
+
 // Maybe later...
 //#define JFFS2_NODETYPE_CHECKPOINT (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3)
 //#define JFFS2_NODETYPE_OPTIONS (JFFS2_FEATURE_RWCOMPAT_COPY | JFFS2_NODE_ACCURATE | 4)
@@ -151,6 +163,32 @@ struct jffs2_raw_inode
 	uint8_t data[0];
 } __attribute__((packed));
 
+struct jffs2_raw_xattr {
+	jint16_t magic;
+	jint16_t nodetype;	/* = JFFS2_NODETYPE_XATTR */
+	jint32_t totlen;
+	jint32_t hdr_crc;
+	jint32_t xid;		/* XATTR identifier number */
+	jint32_t version;
+	uint8_t xprefix;
+	uint8_t name_len;
+	jint16_t value_len;
+	jint32_t data_crc;
+	jint32_t node_crc;
+	uint8_t data[0];
+} __attribute__((packed));
+
+struct jffs2_raw_xref
+{
+	jint16_t magic;
+	jint16_t nodetype;	/* = JFFS2_NODETYPE_XREF */
+	jint32_t totlen;
+	jint32_t hdr_crc;
+	jint32_t ino;		/* inode number */
+	jint32_t xid;		/* XATTR identifier number */
+	jint32_t node_crc;
+} __attribute__((packed));
+
 struct jffs2_raw_summary
 {
 	jint16_t magic;
@@ -169,6 +207,8 @@ union jffs2_node_union
 {
 	struct jffs2_raw_inode i;
 	struct jffs2_raw_dirent d;
+	struct jffs2_raw_xattr x;
+	struct jffs2_raw_xref r;
 	struct jffs2_raw_summary s;
 	struct jffs2_unknown_node u;
 };
diff -prNU3 mtd-utils.git/include/mtd/jffs2-user.h mtd-utils.xattr/include/mtd/jffs2-user.h
--- mtd-utils.git/include/mtd/jffs2-user.h	2006-05-05 20:24:18.000000000 +0900
+++ mtd-utils.xattr/include/mtd/jffs2-user.h	2006-05-05 23:29:13.000000000 +0900
@@ -32,4 +32,51 @@ extern int target_endian;
 #define je32_to_cpu(x) (t32((x).v32))
 #define jemode_to_cpu(x) (t32((x).m))
 
+#define le16_to_cpu(x)	(__BYTE_ORDER==__LITTLE_ENDIAN ? (x) : bswap_16(x))
+#define le32_to_cpu(x)	(__BYTE_ORDER==__LITTLE_ENDIAN ? (x) : bswap_32(x))
+#define cpu_to_le16(x)	(__BYTE_ORDER==__LITTLE_ENDIAN ? (x) : bswap_16(x))
+#define cpu_to_le32(x)	(__BYTE_ORDER==__LITTLE_ENDIAN ? (x) : bswap_32(x))
+
+/* XATTR/POSIX-ACL related definition */
+/* Namespaces copied from xattr.h and posix_acl_xattr.h */
+#define XATTR_USER_PREFIX		"user."
+#define XATTR_USER_PREFIX_LEN		(sizeof (XATTR_USER_PREFIX) - 1)
+#define XATTR_SECURITY_PREFIX		"security."
+#define XATTR_SECURITY_PREFIX_LEN	(sizeof (XATTR_SECURITY_PREFIX) - 1)
+#define POSIX_ACL_XATTR_ACCESS		"system.posix_acl_access"
+#define POSIX_ACL_XATTR_ACCESS_LEN	(sizeof (POSIX_ACL_XATTR_ACCESS) - 1)
+#define POSIX_ACL_XATTR_DEFAULT		"system.posix_acl_default"
+#define POSIX_ACL_XATTR_DEFAULT_LEN	(sizeof (POSIX_ACL_XATTR_DEFAULT) - 1)
+#define XATTR_TRUSTED_PREFIX		"trusted."
+#define XATTR_TRUSTED_PREFIX_LEN	(sizeof (XATTR_TRUSTED_PREFIX) - 1)
+
+typedef struct {
+	jint16_t	e_tag;
+	jint16_t	e_perm;
+	jint32_t	e_id;
+} jffs2_acl_entry;
+
+typedef struct {
+	jint16_t	e_tag;
+	jint16_t	e_perm;
+} jffs2_acl_entry_short;
+
+typedef struct {
+	jint32_t	a_version;
+} jffs2_acl_header;
+
+/* copied from include/linux/posix_acl_xattr.h */
+#define POSIX_ACL_XATTR_VERSION 0x0002
+
+typedef struct {
+	uint16_t		e_tag;
+	uint16_t		e_perm;
+	uint32_t		e_id;
+} posix_acl_xattr_entry;
+
+typedef struct {
+	uint32_t		a_version;
+	posix_acl_xattr_entry	a_entries[0];
+} posix_acl_xattr_header;
+
 #endif /* __JFFS2_USER_H__ */
--- mtd-utils.git/mkfs.jffs2.1	2006-05-05 20:24:18.000000000 +0900
+++ mtd-utils.xattr/mkfs.jffs2.1	2006-05-05 21:12:47.000000000 +0900
@@ -49,6 +49,15 @@ mkfs.jffs2 \- Create a JFFS2 file system
 .B -P,--squash-perms
 ]
 [
+.B --with-xattr
+]
+[
+.B --with-selinux
+]
+[
+.B --with-posix-acl
+]
+[
 .B -m,--compression-mode=MODE
 ]
 [
@@ -178,6 +187,15 @@ Squash owners making all files be owned 
 .B -P, --squash-perms
 Squash permissions, removing write permission for \'group\' and \'other\'.
 .TP
+.B --with-xattr
+Enables xattr, stuff all xattr entries into jffs2 image file.
+.TP
+.B --with-selinux
+Enables xattr, stuff only SELinux Labels into jffs2 image file.
+.TP
+.B --with-posix-acl
+Enable xattr, stuff only POSIX ACL entries into jffs2 image file.
+.TP
 .B -m, --compression-mode=MODE
 Set the default compression mode. The default mode is 
 .B priority 
--- mtd-utils.git/mkfs.jffs2.c	2006-05-05 20:24:18.000000000 +0900
+++ mtd-utils.xattr/mkfs.jffs2.c	2006-05-06 10:44:26.000000000 +0900
@@ -7,6 +7,7 @@
  *           2002 Axis Communications AB
  *           2001, 2002 Erik Andersen <andersen@codepoet.org>
  *           2004 University of Szeged, Hungary
+ *           2006 KaiGai Kohei <kaigai@ak.jp.nec.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -63,6 +64,8 @@
 #include <ctype.h>
 #include <time.h>
 #include <getopt.h>
+#include <sys/xattr.h>
+#include <sys/acl.h>
 #include <byteswap.h>
 #define crc32 __complete_crap
 #include <zlib.h>
@@ -1022,6 +1025,233 @@ static void write_special_file(struct fi
 	padword();
 }
 
+typedef struct xattr_entry {
+	struct xattr_entry *next;
+	uint32_t xid;
+	int xprefix;
+	char *xname;
+	char *xvalue;
+	int name_len;
+	int value_len;
+} xattr_entry_t;
+
+#define XATTR_BUFFER_SIZE		(64 * 1024)	/* 64KB */
+static uint32_t enable_xattr = 0;
+static uint32_t highest_xid = 0;
+
+static struct {
+	int xprefix;
+	char *string;
+	int length;
+} xprefix_tbl[] = {
+	{ JFFS2_XPREFIX_USER, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN },
+	{ JFFS2_XPREFIX_SECURITY, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN },
+	{ JFFS2_XPREFIX_ACL_ACCESS, POSIX_ACL_XATTR_ACCESS, POSIX_ACL_XATTR_ACCESS_LEN },
+	{ JFFS2_XPREFIX_ACL_DEFAULT, POSIX_ACL_XATTR_DEFAULT, POSIX_ACL_XATTR_DEFAULT_LEN },
+	{ JFFS2_XPREFIX_TRUSTED, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN },
+	{ 0, NULL, 0 }
+};
+
+static void formalize_posix_acl(char *xvalue, int *value_len)
+{
+	posix_acl_xattr_header *pacl_header;
+	posix_acl_xattr_entry *pent, *plim;
+	jffs2_acl_header *jacl_header;
+	jffs2_acl_entry *jent;
+	jffs2_acl_entry_short *jent_s;
+	char buffer[XATTR_BUFFER_SIZE];
+	int offset = 0;
+
+	pacl_header = (posix_acl_xattr_header *)xvalue;;
+	pent = pacl_header->a_entries;
+	plim = (posix_acl_xattr_entry *)(xvalue + *value_len);
+
+	jacl_header = (jffs2_acl_header *)buffer;
+	offset += sizeof(jffs2_acl_header);
+	jacl_header->a_version = cpu_to_je32(JFFS2_ACL_VERSION);
+
+	while (pent < plim) {
+		switch(le16_to_cpu(pent->e_tag)) {
+		case ACL_USER_OBJ:
+		case ACL_GROUP_OBJ:
+		case ACL_MASK:
+		case ACL_OTHER:
+			jent_s = (jffs2_acl_entry_short *)(buffer + offset);
+			offset += sizeof(jffs2_acl_entry_short);
+			jent_s->e_tag = cpu_to_je16(le16_to_cpu(pent->e_tag));
+			jent_s->e_perm = cpu_to_je16(le16_to_cpu(pent->e_perm));
+			break;
+		case ACL_USER:
+		case ACL_GROUP:
+			jent = (jffs2_acl_entry *)(buffer + offset);
+			offset += sizeof(jffs2_acl_entry);
+			jent->e_tag = cpu_to_je16(le16_to_cpu(pent->e_tag));
+			jent->e_perm = cpu_to_je16(le16_to_cpu(pent->e_perm));
+			jent->e_id = cpu_to_je32(le32_to_cpu(pent->e_id));
+			break;
+		default:
+			printf("%04x : Unknown XATTR entry tag.\n", le16_to_cpu(pent->e_tag));
+			exit(1);
+		}
+		pent++;
+	}
+	if (offset > *value_len) {
+		printf("Length of JFFS2 ACL expression(%u) is longer than general one(%u).\n",
+		       offset, *value_len);
+		exit(1);
+	}
+	memcpy(xvalue, buffer, offset);
+	*value_len = offset;
+}
+
+static xattr_entry_t *create_xattr_entry(int xprefix, char *xname, char *xvalue, int value_len)
+{
+	xattr_entry_t *xe;
+	struct jffs2_raw_xattr rx;
+	int name_len;
+
+	/* create xattr entry */
+	name_len = strlen(xname);
+	xe = xcalloc(1, sizeof(xattr_entry_t) + name_len + 1 + value_len);
+	xe->next = NULL;
+	xe->xid = ++highest_xid;
+	xe->xprefix = xprefix;
+	xe->xname = ((char *)xe) + sizeof(xattr_entry_t);
+	xe->xvalue = xe->xname + name_len + 1;
+	xe->name_len = name_len;
+	xe->value_len = value_len;
+	strcpy(xe->xname, xname);
+	memcpy(xe->xvalue, xvalue, value_len);
+
+	/* write xattr node */
+	memset(&rx, 0, sizeof(rx));
+	rx.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
+	rx.nodetype = cpu_to_je16(JFFS2_NODETYPE_XATTR);
+	rx.totlen = cpu_to_je32(PAD(sizeof(rx) + xe->name_len + 1 + xe->value_len));
+	rx.hdr_crc = cpu_to_je32(crc32(0, &rx, sizeof(struct jffs2_unknown_node) - 4));
+
+	rx.xid = cpu_to_je32(xe->xid);
+	rx.version = cpu_to_je32(1);	/* initial version */
+	rx.xprefix = xprefix;
+	rx.name_len = xe->name_len;
+	rx.value_len = cpu_to_je16(xe->value_len);
+	rx.data_crc = cpu_to_je32(crc32(0, xe->xname, xe->name_len + 1 + xe->value_len));
+	rx.node_crc = cpu_to_je32(crc32(0, &rx, sizeof(rx) - 4));
+
+	pad_block_if_less_than(sizeof(rx) + xe->name_len + 1 + xe->value_len);
+	full_write(out_fd, &rx, sizeof(rx));
+	full_write(out_fd, xe->xname, xe->name_len + 1 + xe->value_len);
+	padword();
+
+	return xe;
+}
+
+#define XATTRENTRY_HASHSIZE	57
+static xattr_entry_t *find_xattr_entry(int xprefix, char *xname, char *xvalue, int value_len)
+{
+	static xattr_entry_t **xentry_hash = NULL;
+	xattr_entry_t *xe;
+	int index, name_len;
+
+	/* create hash table */
+	if (!xentry_hash)
+		xentry_hash = xcalloc(1, sizeof(xe) * XATTRENTRY_HASHSIZE);
+
+	if (xprefix == JFFS2_XPREFIX_ACL_ACCESS
+	    || xprefix == JFFS2_XPREFIX_ACL_DEFAULT)
+		formalize_posix_acl(xvalue, &value_len);
+
+	name_len = strlen(xname);
+	index = (crc32(0, xname, name_len) ^ crc32(0, xvalue, value_len)) % XATTRENTRY_HASHSIZE;
+	for (xe = xentry_hash[index]; xe; xe = xe->next) {
+		if (xe->xprefix == xprefix
+		    && xe->value_len == value_len
+		    && !strcmp(xe->xname, xname)
+		    && !memcmp(xe->xvalue, xvalue, value_len))
+			break;
+	}
+	if (!xe) {
+		xe = create_xattr_entry(xprefix, xname, xvalue, value_len);
+		xe->next = xentry_hash[index];
+		xentry_hash[index] = xe;
+	}
+	return xe;
+}
+
+static void write_xattr_entry(struct filesystem_entry *e)
+{
+	struct jffs2_raw_xref ref;
+	struct xattr_entry *xe;
+	char xlist[XATTR_BUFFER_SIZE], xvalue[XATTR_BUFFER_SIZE];
+	char *xname, *prefix_str;
+	int i, xprefix, prefix_len;
+	int list_sz, offset, name_len, value_len;
+
+	if (!enable_xattr)
+		return;
+
+	list_sz = llistxattr(e->hostname, xlist, XATTR_BUFFER_SIZE);
+	if (list_sz < 0) {
+		if (verbose)
+			printf("llistxattr('%s') = %d : %s\n",
+			       e->hostname, errno, strerror(errno));
+		return;
+	}
+
+	for (offset = 0; offset < list_sz; offset += name_len) {
+		xname = xlist + offset;
+		name_len = strlen(xname) + 1;
+
+		for (i = 0; (xprefix = xprefix_tbl[i].xprefix); i++) {
+			prefix_str = xprefix_tbl[i].string;
+			prefix_len = xprefix_tbl[i].length;
+			if (prefix_str[prefix_len - 1] == '.') {
+				if (!strncmp(xname, prefix_str, prefix_len - 1))
+					break;
+			} else {
+				if (!strcmp(xname, prefix_str))
+					break;
+			}
+		}
+		if (!xprefix) {
+			if (verbose)
+				printf("%s: xattr '%s' is not supported.\n",
+				       e->hostname, xname);
+			continue;
+		}
+		if ((enable_xattr & (1 << xprefix)) == 0)
+			continue;
+
+		value_len = lgetxattr(e->hostname, xname, xvalue, XATTR_BUFFER_SIZE);
+		if (value_len < 0) {
+			if (verbose)
+				printf("lgetxattr('%s', '%s') = %d : %s\n",
+				       e->hostname, xname, errno, strerror(errno));
+			continue;
+		}
+		xe = find_xattr_entry(xprefix, xname + prefix_len, xvalue, value_len);
+		if (!xe) {
+			if (verbose)
+				printf("%s : xattr '%s' was ignored.\n",
+				       e->hostname, xname);
+			continue;
+		}
+
+		memset(&ref, 0, sizeof(ref));
+		ref.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
+		ref.nodetype = cpu_to_je16(JFFS2_NODETYPE_XREF);
+		ref.totlen = cpu_to_je32(sizeof(ref));
+		ref.hdr_crc = cpu_to_je32(crc32(0, &ref, sizeof(struct jffs2_unknown_node) - 4));
+		ref.ino = cpu_to_je32(e->sb.st_ino);
+		ref.xid = cpu_to_je32(xe->xid);
+		ref.node_crc = cpu_to_je32(crc32(0, &ref, sizeof(ref) - 4));
+
+		pad_block_if_less_than(sizeof(ref));
+		full_write(out_fd, &ref, sizeof(ref));
+		padword();
+	}
+}
+
 static void recursive_populate_directory(struct filesystem_entry *dir)
 {
 	struct filesystem_entry *e;
@@ -1029,6 +1259,8 @@ static void recursive_populate_directory
 	if (verbose) {
 		printf("%s\n", dir->fullname);
 	}
+	write_xattr_entry(dir);		/* for '/' */
+
 	e = dir->files;
 	while (e) {
 
@@ -1041,6 +1273,7 @@ static void recursive_populate_directory
 							e->name);
 				}
 				write_pipe(e);
+				write_xattr_entry(e);
 				break;
 			case S_IFSOCK:
 				if (verbose) {
@@ -1049,6 +1282,7 @@ static void recursive_populate_directory
 							(int) e->sb.st_uid, (int) e->sb.st_gid, e->name);
 				}
 				write_pipe(e);
+				write_xattr_entry(e);
 				break;
 			case S_IFIFO:
 				if (verbose) {
@@ -1057,6 +1291,7 @@ static void recursive_populate_directory
 							(int) e->sb.st_uid, (int) e->sb.st_gid, e->name);
 				}
 				write_pipe(e);
+				write_xattr_entry(e);
 				break;
 			case S_IFCHR:
 				if (verbose) {
@@ -1066,6 +1301,7 @@ static void recursive_populate_directory
 							(int) e->sb.st_gid, e->name);
 				}
 				write_special_file(e);
+				write_xattr_entry(e);
 				break;
 			case S_IFBLK:
 				if (verbose) {
@@ -1075,6 +1311,7 @@ static void recursive_populate_directory
 							(int) e->sb.st_gid, e->name);
 				}
 				write_special_file(e);
+				write_xattr_entry(e);
 				break;
 			case S_IFLNK:
 				if (verbose) {
@@ -1084,6 +1321,7 @@ static void recursive_populate_directory
 							e->link);
 				}
 				write_symlink(e);
+				write_xattr_entry(e);
 				break;
 			case S_IFREG:
 				if (verbose) {
@@ -1092,6 +1330,7 @@ static void recursive_populate_directory
 							(int) e->sb.st_uid, (int) e->sb.st_gid, e->name);
 				}
 				write_regular_file(e);
+				write_xattr_entry(e);
 				break;
 			default:
 				error_msg("Unknown mode %o for %s", e->sb.st_mode,
@@ -1169,6 +1408,9 @@ static struct option long_options[] = {
 	{"test-compression", 0, NULL, 't'},
 	{"compressor-priority", 1, NULL, 'y'},
 	{"incremental", 1, NULL, 'i'},
+	{"with-xattr", 0, NULL, 1000 },
+	{"with-selinux", 0, NULL, 1001 },
+	{"with-posix-acl", 0, NULL, 1002 },
 	{NULL, 0, NULL, 0}
 };
 
@@ -1201,6 +1443,9 @@ static char *helptext =
 	"  -q, --squash            Squash permissions and owners making all files be owned by root\n"
 	"  -U, --squash-uids       Squash owners making all files be owned by root\n"
 	"  -P, --squash-perms      Squash permissions on all files\n"
+	"      --with-xattr        stuff all xattr entries into image\n"
+	"      --with-selinux      stuff only SELinux Labels into jffs2 image\n"
+	"      --with-posix-acl    stuff only POSIX ACL entries into jffs2 image\n"
 	"  -h, --help              Display this help text\n"
 	"  -v, --verbose           Verbose operation\n"
 	"  -V, --version           Display version information\n"
@@ -1519,6 +1764,20 @@ int main(int argc, char **argv)
 					perror_msg_and_die("cannot open (incremental) file");
 				}
 				break;
+			case 1000:	/* --with-xattr  */
+				enable_xattr |= (1 << JFFS2_XPREFIX_USER)
+						| (1 << JFFS2_XPREFIX_SECURITY)
+						| (1 << JFFS2_XPREFIX_ACL_ACCESS)
+						| (1 << JFFS2_XPREFIX_ACL_DEFAULT)
+						| (1 << JFFS2_XPREFIX_TRUSTED);
+				break;
+			case 1001:	/*  --with-selinux  */
+				enable_xattr |= (1 << JFFS2_XPREFIX_SECURITY);
+				break;
+			case 1002:	/*  --with-posix-acl  */
+				enable_xattr |= (1 << JFFS2_XPREFIX_ACL_ACCESS)
+						| (1 << JFFS2_XPREFIX_ACL_DEFAULT);
+				break;
 		}
 	}
 	if (out_fd == -1) {
--- mtd-utils.git/summary.h	2006-05-05 20:24:18.000000000 +0900
+++ mtd-utils.xattr/summary.h	2006-05-06 10:15:03.000000000 +0900
@@ -45,6 +45,8 @@
 #define JFFS2_SUMMARY_NOSUM_SIZE 0xffffffff
 #define JFFS2_SUMMARY_INODE_SIZE (sizeof(struct jffs2_sum_inode_flash))
 #define JFFS2_SUMMARY_DIRENT_SIZE(x) (sizeof(struct jffs2_sum_dirent_flash) + (x))
+#define JFFS2_SUMMARY_XATTR_SIZE (sizeof(struct jffs2_sum_xattr_flash))
+#define JFFS2_SUMMARY_XREF_SIZE (sizeof(struct jffs2_sum_xref_flash))
 
 /* Summary structures used on flash */
 
@@ -75,11 +77,28 @@ struct jffs2_sum_dirent_flash
 	uint8_t name[0];	/* dirent name */
 } __attribute__((packed));
 
+struct jffs2_sum_xattr_flash
+{
+	jint16_t nodetype;	/* == JFFS2_NODETYPE_XATR */
+	jint32_t xid;		/* xattr identifier */
+	jint32_t version;	/* version number */
+	jint32_t offset;	/* offset on jeb */
+	jint32_t totlen;	/* node length */
+} __attribute__((packed));
+
+struct jffs2_sum_xref_flash
+{
+	jint16_t nodetype;	/* == JFFS2_NODETYPE_XREF */
+	jint32_t offset;	/* offset on jeb */
+} __attribute__((packed));
+
 union jffs2_sum_flash
 {
 	struct jffs2_sum_unknown_flash u;
 	struct jffs2_sum_inode_flash i;
 	struct jffs2_sum_dirent_flash d;
+	struct jffs2_sum_xattr_flash x;
+	struct jffs2_sum_xref_flash r;
 };
 
 /* Summary structures used in the memory */
@@ -114,11 +133,30 @@ struct jffs2_sum_dirent_mem
 	uint8_t name[0];	/* dirent name */
 } __attribute__((packed));
 
+struct jffs2_sum_xattr_mem
+{
+	union jffs2_sum_mem *next;
+	jint16_t nodetype;
+	jint32_t xid;
+	jint32_t version;
+	jint32_t offset;
+	jint32_t totlen;
+} __attribute__((packed));
+
+struct jffs2_sum_xref_mem
+{
+	union jffs2_sum_mem *next;
+	jint16_t nodetype;
+	jint32_t offset;
+} __attribute__((packed));
+
 union jffs2_sum_mem
 {
 	struct jffs2_sum_unknown_mem u;
 	struct jffs2_sum_inode_mem i;
 	struct jffs2_sum_dirent_mem d;
+	struct jffs2_sum_xattr_mem x;
+	struct jffs2_sum_xref_mem r;
 };
 
 struct jffs2_summary
--- mtd-utils.git/sumtool.c	2006-05-05 20:24:18.000000000 +0900
+++ mtd-utils.xattr/sumtool.c	2006-05-06 10:27:50.000000000 +0900
@@ -4,6 +4,7 @@
  *  Copyright (C) 2004 Zoltan Sogor <weth@inf.u-szeged.hu>,
  *                     Ferenc Havasi <havasi@inf.u-szeged.hu>
  *                     University of Szeged, Hungary
+ *                2006 KaiGai Kohei <kaigai@ak.jp.nec.com>
  *
  * $Id: sumtool.c,v 1.9 2006/01/23 08:22:45 havasi Exp $
  *
@@ -442,6 +443,29 @@ void dump_sum_records()
 				break;
 			}
 
+			case JFFS2_NODETYPE_XATTR: {
+				struct jffs2_sum_xattr_flash *sxattr_ptr = wpage;
+
+				sxattr_ptr->nodetype = sum_collected->sum_list_head->x.nodetype;
+				sxattr_ptr->xid = sum_collected->sum_list_head->x.xid;
+				sxattr_ptr->version = sum_collected->sum_list_head->x.version;
+				sxattr_ptr->offset = sum_collected->sum_list_head->x.offset;
+				sxattr_ptr->totlen = sum_collected->sum_list_head->x.totlen;
+
+				wpage += JFFS2_SUMMARY_XATTR_SIZE;
+				break;
+			}
+
+			case JFFS2_NODETYPE_XREF: {
+				struct jffs2_sum_xref_flash *sxref_ptr = wpage;
+
+				sxref_ptr->nodetype = sum_collected->sum_list_head->r.nodetype;
+				sxref_ptr->offset = sum_collected->sum_list_head->r.offset;
+
+				wpage += JFFS2_SUMMARY_XREF_SIZE;
+				break;
+			}
+
 			default : {
 				printf("Unknown node type!\n");
 			}
@@ -577,6 +601,16 @@ int add_sum_mem(union jffs2_sum_mem *ite
 			sum_collected->sum_num++;
 			break;
 
+		case JFFS2_NODETYPE_XATTR:
+			sum_collected->sum_size += JFFS2_SUMMARY_XATTR_SIZE;
+			sum_collected->sum_num++;
+			break;
+
+		case JFFS2_NODETYPE_XREF:
+			sum_collected->sum_size += JFFS2_SUMMARY_XREF_SIZE;
+			sum_collected->sum_num++;
+			break;
+
 		default:
 			error_msg_and_die("__jffs2_add_sum_mem(): UNKNOWN node type %d\n", je16_to_cpu(item->u.nodetype));
 	}
@@ -622,6 +656,37 @@ void add_sum_dirent_mem(union jffs2_node
 	add_sum_mem((union jffs2_sum_mem *) temp);
 }
 
+void add_sum_xattr_mem(union jffs2_node_union *node)
+{
+	struct jffs2_sum_xattr_mem *temp = (struct jffs2_sum_xattr_mem *)
+			malloc(sizeof(struct jffs2_sum_xattr_mem));
+	if (!temp)
+		error_msg_and_die("Can't allocate memory for summary information!\n");
+
+	temp->nodetype = node->x.nodetype;
+	temp->xid = node->x.xid;
+	temp->version = node->x.version;
+	temp->offset = cpu_to_je32(data_ofs);
+	temp->totlen = node->x.totlen;
+	temp->next = NULL;
+
+	add_sum_mem((union jffs2_sum_mem *) temp);
+}
+
+void add_sum_xref_mem(union jffs2_node_union *node)
+{
+	struct jffs2_sum_xref_mem *temp = (struct jffs2_sum_xref_mem *)
+			malloc(sizeof(struct jffs2_sum_xref_mem));
+	if (!temp)
+		error_msg_and_die("Can't allocate memory for summary information!\n");
+
+	temp->nodetype = node->r.nodetype;
+	temp->offset = cpu_to_je32(data_ofs);
+	temp->next = NULL;
+
+	add_sum_mem((union jffs2_sum_mem *) temp);
+}
+
 void write_dirent_to_buff(union jffs2_node_union *node)
 {
 	pad_block_if_less_than(je32_to_cpu (node->d.totlen),JFFS2_SUMMARY_DIRENT_SIZE(node->d.nsize));
@@ -639,11 +704,27 @@ void write_inode_to_buff(union jffs2_nod
 	padword();
 }
 
+void write_xattr_to_buff(union jffs2_node_union *node)
+{
+	pad_block_if_less_than(je32_to_cpu(node->x.totlen), JFFS2_SUMMARY_XATTR_SIZE);
+	add_sum_xattr_mem(node);	/* Add xdatum summary mem to summary list */
+	full_write(data_buffer + data_ofs, &(node->x), je32_to_cpu(node->x.totlen));
+	padword();
+}
+
+void write_xref_to_buff(union jffs2_node_union *node)
+{
+	pad_block_if_less_than(je32_to_cpu(node->r.totlen), JFFS2_SUMMARY_XREF_SIZE);
+	add_sum_xref_mem(node);		/* Add xref summary mem to summary list */
+	full_write(data_buffer + data_ofs, &(node->r), je32_to_cpu(node->r.totlen));
+	padword();
+}
+
 void create_summed_image(int inp_size)
 {
 	uint8_t *p = file_buffer;
 	union jffs2_node_union *node;
-	uint32_t crc;
+	uint32_t crc, length;
 	uint16_t type;
 	int bitchbitmask = 0;
 	int obsolete;
@@ -743,6 +824,56 @@ void create_summed_image(int inp_size)
 				p += PAD(je32_to_cpu (node->d.totlen));
 				break;
 
+			case JFFS2_NODETYPE_XATTR:
+				if (je32_to_cpu(node->x.node_crc) == 0xffffffff)
+					obsolete = 1;
+				if (verbose)
+					printf("%8s Xdatum     node at 0x%08x, totlen 0x%08x, "
+					       "#xid  %5u, version %5u\n",
+					       obsolete ? "Obsolete" : "",
+					       p - file_buffer, je32_to_cpu (node->x.totlen),
+					       je32_to_cpu(node->x.xid), je32_to_cpu(node->x.version));
+				crc = crc32(0, node, sizeof (struct jffs2_raw_xattr) - 4);
+				if (crc != je32_to_cpu(node->x.node_crc)) {
+					printf("Wrong node_crc at 0x%08x, 0x%08x instead of 0x%08x\n",
+					       p - file_buffer, je32_to_cpu(node->x.node_crc), crc);
+					p += PAD(je32_to_cpu (node->x.totlen));
+					continue;
+				}
+				length = node->x.name_len + 1 + je16_to_cpu(node->x.value_len);
+				crc = crc32(0, node->x.data, length);
+				if (crc != je32_to_cpu(node->x.data_crc)) {
+					printf("Wrong data_crc at 0x%08x, 0x%08x instead of 0x%08x\n",
+					       p - file_buffer, je32_to_cpu(node->x.data_crc), crc);
+					p += PAD(je32_to_cpu (node->x.totlen));
+					continue;
+				}
+
+				write_xattr_to_buff(node);
+				p += PAD(je32_to_cpu (node->x.totlen));
+				break;
+
+			case JFFS2_NODETYPE_XREF:
+				if (je32_to_cpu(node->r.node_crc) == 0xffffffff)
+					obsolete = 1;
+				if (verbose)
+					printf("%8s Xref       node at 0x%08x, totlen 0x%08x, "
+					       "#ino  %5u, xid     %5u\n",
+					       obsolete ? "Obsolete" : "",
+					       p - file_buffer, je32_to_cpu(node->r.totlen),
+					       je32_to_cpu(node->r.ino), je32_to_cpu(node->r.xid));
+				crc = crc32(0, node, sizeof (struct jffs2_raw_xref) - 4);
+				if (crc != je32_to_cpu(node->r.node_crc)) {
+					printf("Wrong node_crc at 0x%08x, 0x%08x instead of 0x%08x\n",
+					       p - file_buffer, je32_to_cpu(node->r.node_crc), crc);
+					p += PAD(je32_to_cpu (node->r.totlen));
+					continue;
+				}
+
+				write_xref_to_buff(node);
+				p += PAD(je32_to_cpu (node->r.totlen));
+				break;
+
 			case JFFS2_NODETYPE_CLEANMARKER:
 				if (verbose) {
 					printf ("%8s Cleanmarker     at 0x%08x, totlen 0x%08x\n",