XATTR issues on JFFS2
Subsystems (4)
PATCH 1/1 XATTR issues on JFFS2
Hello,
The attached patch provids XATTR support in JFFS2. We can apply it to mtd-snapshot-20050822.tar.bz2 tree.
I hope your worthwhile comments for improvement.
# By coincidence, two patches for similar functionality are posted in same day :) # I changed the subject of this mail a bit to avoid confusion.
This implementation added two new node types JFFS2_NODETYPE_XATTR and JFFS2_NODETYPE_XREF.JFFS2_NODETYPE_XATTR node has a set of XATTR entry which contains name and value. It's represented as jffs2_raw_xattr structure on MTD-device. JFFS2_NODETYPE_XREF node has a set of reference to associate inode with XATTR. It's represented as jffs2_raw_xref structure on MTD-device.
* Data Structure
- jffs2_xattr_cache
This object contains XATTR name/value. It must be refered by an inode at least. When the last inode which refers jffs2_xattr_cache is unlinked, jffs2_xattr_cache will be deleted.
XATTR name/value is not loaded until inode object is allocated.
- jffs2_xattr_ref
This object refers jffs2_inode_cache and jffs2_xattr_cache, and chains each other. When we walk on ref->ilist from jffs2_inode_cache, we can scan all the XATTR which is bound to this inode. Adversely, we can scan all the inode which refers this XATTR, when we walk on ref->xlist from jffs2_xattr_cache.
struct jffs2_xattr_cache
{
struct list_head xcache; <-- It's chained from struct jffs2_sb_info (global hash list). struct list_head xlist; <-- jffs2_xattr_ref is chained on this list. struct jffs2_raw_node_ref *node;
uint32_t xid; <-- Unique Identifier
uint32_t version;
uint32_t crc;
char *xname; /* XATTR name */ <--
char *xvalue; /* XATTR value */
int xsize; /* size of XATTR value */
};
struct jffs2_xattr_ref
{
uint32_t seqno; /* sequencial number */
uint32_t flags;
struct list_head ilist; /* list from jffs2_inode_cache */
struct list_head xlist; /* list from jffs2_xattr_cache */
struct jffs2_xattr_cache *xc;
struct jffs2_inode_cache *ic;
struct jffs2_raw_node_ref *node;
};* How to work
[1] FS mounting
When jffs2 is mounting, xattrcache which is array of list_head is created by kmalloc() on jffs2_sb_info first.
Then jffs2_scan_eraseblock() is called on each erase block, and jffs2_scan_xattr_node() and jffs2_scan_xref_node() are used to treat two new node-type. jffs2_scan_xattr_node() create jffs2_xattr_cache object and chain it to xattrcache. jffs2_scan_xref_node() create jffs2_xattr_ref object and chain it to temporary list.
Next, jffs2_build_xattr_caches() is called. This function associate jffs2_inode_cache with jffs2_xattr_cache by using jffs2_xattr_ref. (struct jffs2_xattr_ref *)ref->ilist ... Chained jffs2_inode_cache (struct jffs2_xattr_ref *)ref->xlist ... Chained jffs2_xattr_cache
[2] inode-creation
When inode object is created, jffs2_get_xattr_inode() will be called. It walks on ilist on inode-cache and calls do_load_xattr_cache() for related XATTR object to load XATTR name/value.
[3] getxattr/setxattr
We can refer an jffs2_inode_cache object in {get|set}xattr handler, and walks on jffs2_inode_cache->ilist for looking up target XATTR. In setxattr case, do_create_xattr_cache() is called for creation new XATTR-node, then do_delete_xattr_ref() is used for old-node.
* Example of use
[root@saba ~]# dd if=jffs2.xattr.img of=/dev/mtdblock0 8192+0 records in
8192+0 records out
[root@saba ~]# mount -t jffs2 /dev/mtdblock0 /mnt/0 [root@saba ~]# ls -lZ /mnt/0
drwxr-xr-x root root system_u:object_r:bin_t bin/ drwxr-xr-x root root system_u:object_r:mnt_t dev/ drwxr-xr-x root root system_u:object_r:etc_t etc/ -rw-r--r-- root root system_u:object_r:mnt_t hoge -rwxr-xr-x root root system_u:object_r:mnt_t init* drwxr-xr-x root root system_u:object_r:lib_t lib/ drwxr-xr-x root root system_u:object_r:mnt_t loopfs/ drwxr-xr-x root root system_u:object_r:mnt_t proc/ lrwxrwxrwx root root system_u:object_r:bin_t sbin drwxr-xr-x root root system_u:object_r:mnt_t sys/ drwxr-xr-x root root system_u:object_r:mnt_t sysroot/
[root@saba ~]#
* ToDo List
(1) stabilization
o more tests and debugging are necessary. I hope any trouble reporting. I don't have real MTD device. This implementation is developed on MTD-RAM pseudo device. Does it work on real MTD-devices ?
(2) performance & scalability
o Currently, any XATTR objects are guarded by a xattr_sem. But this implementation is not scale, I guess. To divid locking is necessary.
o When setxattr() is called, the system scans XATTR cache to look for same combination of name/value and share it.
But it's so expensive process, to reduce finding-step is necessary.
(3) more functionality
o Currently, only XATTR has "security.*" prefix is supported. It's enough to use SELinux, but that's more useful if we can use POSIX-ACL and so on.
o modifying mkfs.jffs2 command.
Thanks,
Signature · 2 lines
Linux Promotion Center, NEC KaiGai Kohei <[email protected]>
fs/Kconfig +9 -0
@@ -51,6 +51,15 @@ config JFFS2_FS_DEBUG If reporting bugs, please try to have available a full dump of the messages at debug level 1 while the misbehaviour was occurring. +config JFFS2_XATTR + bool "JFFS2 XATTR support (EXPERIMENTAL)" + depends on JFFS2_FS + default n + help + This enables the XATTR support in JFFS2. + + It's neccesary for persistent security context in SELinux. + config JFFS2_FS_WRITEBUFFER bool "JFFS2 write-buffering support" depends on JFFS2_FS
fs/jffs2/Makefile.common +1 -0
@@ -11,6 +11,7 @@ jffs2-y += read.o nodemgmt.o readinode.o jffs2-y += symlink.o build.o erase.o background.o fs.o writev.o jffs2-y += super.o debug.o +jffs2-$(CONFIG_JFFS2_XATTR) += xattr.o jffs2-$(CONFIG_JFFS2_FS_WRITEBUFFER) += wbuf.o jffs2-$(CONFIG_JFFS2_RUBIN) += compr_rubin.o jffs2-$(CONFIG_JFFS2_RTIME) += compr_rtime.o
fs/jffs2/build.c +3 -0
@@ -165,6 +165,7 @@ static int jffs2_build_filesystem(struct ic->scan_dents =NULL ;cond_resched (); } +jffs2_build_xattr_caches (c); c->flags &= ~JFFS2_SB_FLAG_BUILDING ;D1 (printk (KERN_DEBUG "Pass 3 complete\n" ));
@@ -184,6 +185,7 @@ exit:jffs2_free_full_dirent (fd); } } +jffs2_clear_xattr_caches (c); }return ret;
@@ -353,6 +355,7 @@ int jffs2_do_mount_fs(struct jffs2_sb_inif (jffs2_build_filesystem (c)) {D1 (printk (KERN_DEBUG "build_fs failed\n" )); +jffs2_clear_xattr_caches (c);jffs2_free_ino_caches (c);jffs2_free_raw_node_refs (c);#ifndef __ECOS
fs/jffs2/dir.c +8 -1
@@ -58,6 +58,10 @@ struct inode_operations jffs2_dir_inode_ .mknod = jffs2_mknod, .rename = jffs2_rename, .setattr = jffs2_setattr, + .setxattr = jffs2_setxattr, + .getxattr = jffs2_getxattr, + .listxattr = jffs2_listxattr, + .removexattr = jffs2_removexattr };/***********************************************************************/
@@ -236,8 +240,11 @@ static int jffs2_unlink(struct inode *di ret =jffs2_do_unlink (c, dir_f, dentry->d_name.name, dentry->d_name.len, dead_f, now); -if (dead_f->inocache) +if (dead_f->inocache) { dentry->d_inode->i_nlink = dead_f->inocache->nlink; +if (!dead_f->inocache->nlink) +jffs2_unlink_xattr_inode (c, dead_f->inocache); + }if (!ret) dir_i->i_mtime = dir_i->i_ctime =ITIME (now);return ret;
fs/jffs2/file.c +5 -1
@@ -57,7 +57,11 @@ struct file_operations jffs2_file_operatstruct inode_operations jffs2_file_inode_operations = { - .setattr = jffs2_setattr + .setattr = jffs2_setattr, + .setxattr = jffs2_setxattr, + .getxattr = jffs2_getxattr, + .listxattr = jffs2_listxattr, + .removexattr = jffs2_removexattr }; struct address_space_operations jffs2_file_address_operations =
fs/jffs2/fs.c +27 -0
@@ -310,6 +310,15 @@ void jffs2_read_inode (struct inode *inoprintk (KERN_WARNING "jffs2_read_inode(): Bogus imode %o for ino %lu\n" , inode->i_mode, (unsigned long )inode->i_ino); } +#ifdef CONFIG_JFFS2_XATTR + ret =jffs2_get_xattr_inode (c, f->inocache); +if (ret) { +up (&f->sem); +jffs2_do_clear_inode (c, f); +make_bad_inode (inode); +return ; + } +#endif up (&f->sem);D1 (printk (KERN_DEBUG "jffs2_read_inode() returning\n" ));
@@ -504,6 +513,20 @@ int jffs2_do_fill_super(struct super_blo }memset (c->inocache_list,0 ,INOCACHE_HASHSIZE *sizeof (struct jffs2_inode_cache *)); +#ifdef CONFIG_JFFS2_XATTR +/* Initialization of XATTR related members */ + c->xattrcache =kmalloc (XATTRCACHE_HASHSIZE *sizeof (struct list_head ),GFP_KERNEL ); +if (!c->xattrcache) { +kfree (c->inocache_list); + ret = -ENOMEM ; + goto out_wbuf; + } +for (ret=0 ; ret<XATTRCACHE_HASHSIZE ; ret++) +INIT_LIST_HEAD (&c->xattrcache[ret]); +INIT_LIST_HEAD (&c->xattr_temp); +init_rwsem (&c->xattr_sem); +#endif +if ((ret =jffs2_do_mount_fs (c))) goto out_inohash;
@@ -531,6 +554,7 @@ int jffs2_do_fill_super(struct super_blo out_root_i:iput (root_i); +jffs2_clear_xattr_caches (c);jffs2_free_ino_caches (c);jffs2_free_raw_node_refs (c);if (c->mtd->flags &MTD_NO_VIRTBLOCKS )
@@ -538,6 +562,9 @@ int jffs2_do_fill_super(struct super_bloelse kfree (c->blocks); out_inohash: +#ifdef CONFIG_JFFS2_XATTR +kfree (c->xattrcache); +#endif kfree (c->inocache_list); out_wbuf:jffs2_flash_cleanup (c);
fs/jffs2/malloc.c +60 -2
83 lines not on this page · raw message
fs/jffs2/nodelist.h +11 -0
@@ -20,6 +20,7 @@#include <linux/jffs2.h> #include <linux/jffs2_fs_sb.h> #include <linux/jffs2_fs_i.h> +#include <linux/jffs2_fs_x.h> #ifdef __ECOS#include "os-ecos.h"
@@ -111,6 +112,9 @@ struct jffs2_inode_cache {uint32_t ino;int nlink;int state; +#ifdef CONFIG_JFFS2_XATTR +struct list_head ilist; +#endif };/* Inode states for 'state' above. We need the 'GC' state to prevent
@@ -367,6 +371,13 @@ void jffs2_free_node_frag(struct jffs2_nstruct jffs2_inode_cache *jffs2_alloc_inode_cache (void );void jffs2_free_inode_cache (struct jffs2_inode_cache *); +#ifdef CONFIG_JFFS2_XATTR +struct jffs2_xattr_cache *jffs2_alloc_xattr_cache (void ); +void jffs2_free_xattr_cache (struct jffs2_xattr_cache *); +struct jffs2_xattr_ref *jffs2_alloc_xattr_ref (void ); +void jffs2_free_xattr_ref (struct jffs2_xattr_ref *); +#endif /* CONFIG_JFFS2_XATTR */ +/* gc.c */ int jffs2_garbage_collect_pass (struct jffs2_sb_info *c);
fs/jffs2/readinode.c +3 -0
@@ -902,6 +902,7 @@ int jffs2_do_read_inode(struct jffs2_sb_ f->inocache->ino = f->inocache->nlink =1 ; f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache; f->inocache->state =INO_STATE_READING ; +initxattr_jffs2_inode_cache (f->inocache);jffs2_add_ino_cache (c, f->inocache); }if (!f->inocache) {
@@ -965,6 +966,8 @@ void jffs2_do_clear_inode(struct jffs2_sjffs2_free_full_dirent (fd); } +jffs2_put_xattr_inode (c, f->inocache); +if (f->inocache && f->inocache->state !=INO_STATE_CHECKING ) {jffs2_set_inocache_state (c, f->inocache,INO_STATE_CHECKEDABSENT );if (f->inocache->nodes == (void *)f->inocache)
fs/jffs2/scan.c +219 -1
244 lines not on this page · raw message
fs/jffs2/super.c +4 -0
@@ -282,6 +282,7 @@ static void jffs2_put_super (struct supedown (&c->alloc_sem);jffs2_flush_wbuf_pad (c);up (&c->alloc_sem); +jffs2_clear_xattr_caches (c);jffs2_free_ino_caches (c);jffs2_free_raw_node_refs (c);if (c->mtd->flags &MTD_NO_VIRTBLOCKS )
@@ -290,6 +291,9 @@ static void jffs2_put_super (struct supekfree (c->blocks);jffs2_flash_cleanup (c);kfree (c->inocache_list); +#ifdef CONFIG_JFFS2_XATTR +kfree (c->xattrcache); +#endif if (c->mtd->sync) c->mtd->sync (c->mtd);
fs/jffs2/symlink.c +5 -1
@@ -24,7 +24,11 @@ struct inode_operations jffs2_symlink_in { .readlink = generic_readlink, .follow_link = jffs2_follow_link, - .setattr = jffs2_setattr + .setattr = jffs2_setattr, + .setxattr = jffs2_setxattr, + .getxattr = jffs2_getxattr, + .listxattr = jffs2_listxattr, + .removexattr = jffs2_removexattr };static int jffs2_follow_link (struct dentry *dentry,struct nameidata *nd)
fs/jffs2/write.c +1 -1
@@ -36,7 +36,7 @@ int jffs2_do_new_inode(struct jffs2_sb_i f->inocache->nlink =1 ; f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache; f->inocache->state =INO_STATE_PRESENT ; - +initxattr_jffs2_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));
fs/jffs2/xattr.c +704 -0
704 lines not on this page · raw message
include/linux/jffs2.h +33 -0
@@ -59,6 +59,8 @@#define JFFS2_NODETYPE_INODE (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 2)#define JFFS2_NODETYPE_CLEANMARKER (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3)#define JFFS2_NODETYPE_PADDING (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 4) +#define JFFS2_NODETYPE_XATTR (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 8) +#define JFFS2_NODETYPE_XREF (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 9)// Maybe later... //#define JFFS2_NODETYPE_CHECKPOINT (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3)
@@ -146,9 +148,40 @@ struct jffs2_raw_inodeuint8_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;/* XATTR version number */ +jint32_t length;/* upper 12bit = the length of xname */ +/* lower 20bit = the length of xvalue */ +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 seqno;/* sequencial number */ +jint32_t ino;/* inode number */ +jint32_t xid;/* XATTR identifier number */ +jint32_t node_crc; +} __attribute__((packed)); +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_unknown_node u; };
include/linux/jffs2_fs_sb.h +7 -0
@@ -112,6 +112,13 @@ struct jffs2_sb_info {uint32_t fsdata_len;#endif +#ifdef CONFIG_JFFS2_XATTR +uint32_t highest_xid;/* version number for XATTR-Node */ +uint32_t highest_seqno;/* seqno for XREF-Node */ +struct list_head *xattrcache; +struct list_head xattr_temp;/* temporary use in mounting */ +struct rw_semaphore xattr_sem; +#endif /* OS-private pointer for getting back to master superblock info */ void *os_priv; };
include/linux/jffs2_fs_x.h +119 -0
119 lines not on this page · raw message
Hello,
In recent days, I'm interrested in XATTR support in JFFS2.
I have started a discussion about it on MTD-ML.
http://lists.infradead.org/pipermail/linux-mtd/2005-August/013415.html
By ML-archive, an implementation use hidden-file to store XATTR was rejected finally. Thus, I adopted different approach. This implementation added two new node types JFFS2_NODETYPE_XATTR and JFFS2_NODETYPE_XREF for XATTR representation.
If your comment can be gotten, I'm so glad.
# I think it's not appropriate to discuss JFFS2 at SELinux-ML. # Please comment it on MTD-ML, if possible.
Thanks,
*---- Example of use ------------
In my desktop PC, "fs_use_xattr jffs2 system_u:object_r:fs_t;" was configured. :)
[root@saba ~]# dd if=jffs2.xattr.img of=/dev/mtdblock0 8192+0 records in
8192+0 records out
[root@saba ~]# mount -t jffs2 /dev/mtdblock0 /mnt/0 [root@saba ~]# ls -lZ /mnt/0
drwxr-xr-x root root system_u:object_r:bin_t bin/ drwxr-xr-x root root system_u:object_r:mnt_t dev/ drwxr-xr-x root root system_u:object_r:etc_t etc/ -rw-r--r-- root root system_u:object_r:mnt_t hoge -rwxr-xr-x root root system_u:object_r:mnt_t init* drwxr-xr-x root root system_u:object_r:lib_t lib/ drwxr-xr-x root root system_u:object_r:mnt_t loopfs/ drwxr-xr-x root root system_u:object_r:mnt_t proc/ lrwxrwxrwx root root system_u:object_r:bin_t sbin drwxr-xr-x root root system_u:object_r:mnt_t sys/ drwxr-xr-x root root system_u:object_r:mnt_t sysroot/
[root@saba ~]#
Signature · 8 lines
Linux Promotion Center, NEC KaiGai Kohei <[email protected]> -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 40 lines · KaiGai Kohei
Hello,
In recent days, I'm interrested in XATTR support in JFFS2.
I have started a discussion about it on MTD-ML.
http://lists.infradead.org/pipermail/linux-mtd/2005-August/013415.htmlBy ML-archive, an implementation use hidden-file to store XATTR was rejected finally. Thus, I adopted different approach. This implementation added two new node types
JFFS2_NODETYPE_XATTRandJFFS2_NODETYPE_XREFfor XATTR representation.If your comment can be gotten, I'm so glad.
# I think it's not appropriate to discuss JFFS2 at SELinux-ML. # Please comment it on MTD-ML, if possible.
Thanks,
*---- Example of use ------------
In my desktop PC, "
fs_use_xattrjffs2 system_u:object_r:fs_t;" was configured. :)[root@saba ~]# dd if=jffs2.xattr.img of=/dev/mtdblock0 8192+0 records in
8192+0 records out
[root@saba ~]# mount -t jffs2/dev/mtdblock0/mnt/0[root@saba ~]# ls -lZ/mnt/0drwxr-xr-x root root system_u:object_r:bin_t bin/ drwxr-xr-x root root system_u:object_r:mnt_t dev/ drwxr-xr-x root root system_u:object_r:etc_t etc/(quoted diff) +0
-2-rw-r--r-- root root system_u:object_r:mnt_t hoge -rwxr-xr-x root root system_u:object_r:mnt_t init*drwxr-xr-x root root system_u:object_r:lib_t lib/ drwxr-xr-x root root system_u:object_r:mnt_t loopfs/ drwxr-xr-x root root system_u:object_r:mnt_t proc/ lrwxrwxrwx root root system_u:object_r:bin_t sbin drwxr-xr-x root root system_u:object_r:mnt_t sys/ drwxr-xr-x root root system_u:object_r:mnt_t sysroot/
Quoted 1 line
[root@saba ~]#
Thanks for working on this functionality. From a very brief look at the patch, one question I had was whether you could be using the generic xattr methods introduced by James Morris' earlier xattr code consolidation patches that are now in the mainline kernel. See the generic_* functions in fs/xattr.c and how they are used by the fs code (e.g. look at the ext3 xattr implementation). Per recent discussions on linux-fsdevel, using those helpers is the preferred approach for the future. You can then just set sb->s_xattr for the specific handlers in jffs2, e.g. see the ext3 code for an example.
Might be worth mentioning this work on acl-devel as well, although you don't yet support ACLs or other xattrs. But I'm sure Andreas Gruenbacher would be interested, as he did the original xattr and ACL development work for ext[23], and he may be able to give feedback on your approach to various aspects like the attribute caching.
Signature · 8 lines
Stephen Smalley National Security Agency -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Hello,
Thanks for your comments.
The original reason not to use generic XATTR methods is that {get|set|list}_xattr methods are called with XATTR-name which prefix is omitted.
e.g, sys_getxattr("security.selinux", ...)
-> generic_getxattr("security.selinux", ...)
-> jffs2_security_getxattr("selinux", ...)
~~~~~~~<- "security." was omitted.In my implementation, the full-name is used to identify XATTR-entry.
But I noticed that we can use a combination of integer index number (such as EXT2_XATTR_INDEX_SECURITY) and omitted XATTR-name for the replacement of full-XATTR-name, and can use generic_xxxx().
I'll modify it in "take-2" patch.
(Why didn't I notice before posting...)
Quoted 9 lines
Thanks for working on this functionality. From a very brief look at the patch, one question I had was whether you could be using the generic xattr methods introduced by James Morris' earlier xattr code consolidation patches that are now in the mainline kernel. See the generic_* functions in
fs/xattr.cand how they are used by the fs code (e.g. look at the ext3 xattr implementation). Per recent discussions on linux-fsdevel, using those helpers is the preferred approach for the future. You can then just setsb->s_xattrfor the specific handlers in jffs2, e.g. see the ext3 code for an example.
Thanks for this information. I'll contact to him before ACL implementation.
Quoted 5 lines
Might be worth mentioning this work on acl-devel as well, although you don't yet support ACLs or other xattrs. But I'm sure Andreas Gruenbacher would be interested, as he did the original xattr and ACL development work for ext[23], and he may be able to give feedback on your approach to various aspects like the attribute caching.
Signature · 6 lines
KaiGai Kohei <[email protected]> -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 7 lines · KaiGai Kohei
The original reason not to use generic XATTR methods is that {get|set|list}_xattr methods are called with XATTR-name which prefix is omitted.
e.g,sys_getxattr("security.selinux", ...)-> generic_getxattr("security.selinux", ...) -> jffs2_security_getxattr("selinux", ...) ~~~~~~~<- "security." was omitted.In my implementation, the full-name is used to identify XATTR-entry.
reiserfs has the same issue, so they are proposing changing the generic functions to pass the entire name down to the fs code. See
http://marc.theaimsgroup.com/?l=linux-fsdevel&m=112448411323801&w=2
Quoted 3 lines
But I noticed that we can use a combination of integer index number (such as
EXT2_XATTR_INDEX_SECURITY) and omitted XATTR-name for the replacement of full-XATTR-name, and can usegeneric_xxxx().
Yes, that is an option as well.
Signature · 8 lines
Stephen Smalley National Security Agency -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 6 lines · Kaigai Kohei
The attached patch provids XATTR support in JFFS2. We can apply it to mtd-snapshot-20050822.tar.bz2 tree.
I hope your worthwhile comments for improvement.
# By coincidence, two patches for similar functionality are posted in same day :)
Which is quite nice. Would you two mind reading the others patch and stating what is bad at that one and why your's is better? If there is a clear winner in this batter, we should merge that one. Most likely, the result is that both patches are lacking details and a new one with elements from both should be used instead. At this moment, we just don't know yet, what those details are.
Jörn
Signature · 3 lines
Mundie uses a textbook tactic of manipulation: start with some reasonable talk, and lead the audience to an unreasonable conclusion. -- Bruce Perens
David Woodhouse
maintainerQuoted 3 lines · Jörn Engel
Which is quite nice. Would you two mind reading the others patch and stating what is bad at that one and why your's is better? If there is a clear winner in this batter, we should merge that one.
I'm happier with inventing new node types for xattrs instead of re-using existing nodes, I think. And I'd also like to make sure we can share xattr data on the medium where appropriate. In an selinux system, you'll end up with a _multitude_ of xattrs used for selinux, many of which will have precisely the same contents. Each should be stored only once on the flash, like hard links. The ext2 implementation manages this.
Signature · 1 line
dwmw2
Hello, Thanks for your comments.
Quoted 6 lines · David Woodhouse
I'm happier with inventing new node types for xattrs instead of re-using existing nodes, I think. And I'd also like to make sure we can share xattr data on the medium where appropriate. In an selinux system, you'll end up with a _multitude_ of xattrs used for selinux, many of which will have precisely the same contents. Each should be stored only once on the flash, like hard links. The ext2 implementation manages this.
Indeed, it is key concept to separate the relationship between inode and XATTR from XATTR-entry which contain name/value.
In my implementation, an increase/decrease of inode which shares XATTR-entry does not need to update the XATTR-entry. It's represented by an existance of XATTR-reference node. Therefore, it's possible to update less frequently.
If this approach is acceptable, I'm willing to implement something to do.
* Dividing the global xattr_sem semaphore into more small lock.
* Indexing the XATTR-entry by its contains, for fast looking-up shared entry. and, Stephen suggested as follows:
* Using generic_{set|get|list}xattr method like ext2/3.
Thanks,
Signature · 2 lines
Linux Promotion Center, NEC KaiGai Kohei <[email protected]>
Hi,
Today, I think about appropriate locking in JFFS2's XATTR. I hope to get some comments about dividing locking.
Quoted 1 line
* Dividing the global
xattr_semsemaphore into more small lock.
xattr_sem is a global read/write semaphore stored in jffs2_sb_info to protect any XATTR structure.
In common case, dividing lock/semaphore has good effects for scalability toward the number of CPUs. But JFFS2 is frequently used for small and embedded region in my understanding.
If global semaphore is divided into many per-entry locks, we may be able to execute setxattr() concurrently. But each locking/un-locking cost may also exceed the scalability effect.
Since I don't have much experience in this region, I hope any professional's worthwhile comments.
Now, I think one global read/write semaphore is enough for 1-2 CPUs, if assumption of the XATTR processing with wrinting does not happen so much is permitted. In almost case, we can execute get/listxattr cuncurrently with one lock/un-locking, I think.
Thanks,
Signature · 2 lines
Linux Promotion Center, NEC KaiGai Kohei <[email protected]>
Quoted 18 lines · Kaigai Kohei
Today, I think about appropriate locking in JFFS2's XATTR. I hope to get some comments about dividing locking.
Quoted 1 line
* Dividing the global
xattr_semsemaphore into more small lock.
xattr_semis a global read/write semaphore stored injffs2_sb_infoto protect any XATTR structure.
In common case, dividing lock/semaphore has good effects for scalability toward the number of CPUs. But JFFS2 is frequently used for small and embedded region in my understanding.If global semaphore is divided into many per-entry locks, we may be able to execute
setxattr()concurrently. But each locking/un-locking cost may also exceed the scalability effect.
Since I don't have much experience in this region, I hope any professional's worthwhile comments.
Quoted 4 lines
Now, I think one global read/write semaphore is enough for 1-2 CPUs, if assumption of the XATTR processing with wrinting does not happen so much is permitted. In almost case, we can execute get/listxattr cuncurrently with one lock/un-locking, I think.
Your idea to go to fine-grained locking surprised me a bit when I first saw it. JFFS2 is hardly the fs that cares much about SMP scalability. Unless you can prove real contentions around the xattr_lock in realistic benchmarks, I would ignore this issue.
Correctness is another issue. I guess you have read fs/jffs2/README.Locking and started a graph on paper to visualize locking order. This is more important, as a deadlock is about the worst performance you can get. ;)
Jörn
Signature · 2 lines
He that composes himself is wiser than he that composes a book. -- B. Franklin
Hello,
This attached patch enables XATTR support in JFFS2. (take-2) # The contribution has slowed due to the trouble related to GC :-(
The my first patch posted in Aug 23 is revised at the points as follows.
- get/setxattr are implemented as a method of generic XATTR handler.
- new methods for "user.*" and "trusted.*" prefix were added.
- Time to retrieve the duplicate XATTR-cache shortened, when setxattr(). In first implementation, we must scan all XATTR-cache to find the duplicate one, and it's so expensive. Now, we cau use the hash-list of XATTR-cache which is indexed by own contents.
- Now, Garbage Collector can deal JFFS2_NODETYPE_XATTR and JFFS2_NODETYPE_XREF. It seems to me that GC can mark unconditionally any nodes without inode as obsolete. But new JFFS2_NODETYPE_XATTR/XREF should be an exception. GC must not mark them as obsolete, although their "next_in_ino" is NULL.
----[ jffs2_garbage_collect_pass() in gc.c ]------------------------
249 if (!raw->next_in_ino) { <-- unconditionally mark it as obsolete.
250 /* Inode-less node. Clean marker, snapshot or something like that */
251 /* FIXME: If it's something that needs to be copied, including something
252 we don't grok that has JFFS2_NODETYPE_RWCOMPAT_COPY, we should do so */
253 spin_unlock(&c->erase_completion_lock); 254 jffs2_mark_node_obsolete(c, raw); 255 up(&c->alloc_sem); 256 goto eraseit_lock;
257 }
--------------------------------------------------------------------
I added a new variable 'owner' into jffs2_raw_node_ref to resolve this. It refers jffs2_xattr_cache or jffs2_xattr_ref object when raw-node reflect XATTR-node. Thus, we can distinguish XATTR-node and others by whether 'owner' is NULL or not.
- Consistency has improved.
check_xattr_ref_ilist() checks XATTRs which are binded to same inode. If multiple XATTR has same name exist, older one is marked as obsolete. In first implementation, there are possibilities to be created multiple XATTRs have same name in an inode, when system-crash happens durling setxattr()
The remaining work is as follows:
- Test & Stabilization.
- The implementation for POSIX ACL support.
- The implementation for XATTR support in mkfs.jffs2.
Thanks,
Signature · 2 lines
Linux Promotion Center, NEC KaiGai Kohei <[email protected]>
fs/Kconfig +16 -0
@@ -64,6 +64,22 @@ config JFFS2_FS_WRITEBUFFER - NOR flash with transparent ECC - DataFlash +config JFFS2_XATTR + bool "JFFS2 XATTR support (EXPERIMENTAL)" + depends on JFFS2_FS + default n + help + This enables the XATTR support in JFFS2. + + It's neccesary for persistent security context in SELinux. + Now, we can use the following kinds of prefix. + + - security.* + - user.* + - trust.* + + - system.posix_acl_{access|default} are in TODO list now. + config JFFS2_COMPRESSION_OPTIONS bool "Advanced compression options for JFFS2" default n
fs/jffs2/Makefile.common +1 -0
@@ -12,6 +12,7 @@ jffs2-y += symlink.o build.o erase.o bac jffs2-y += super.o debug.o jffs2-$(CONFIG_JFFS2_FS_WRITEBUFFER) += wbuf.o +jffs2-$(CONFIG_JFFS2_XATTR) += xattr.o jffs2-$(CONFIG_JFFS2_RUBIN) += compr_rubin.o jffs2-$(CONFIG_JFFS2_RTIME) += compr_rtime.o jffs2-$(CONFIG_JFFS2_ZLIB) += compr_zlib.o
fs/jffs2/build.c +2 -0
@@ -165,6 +165,7 @@ static int jffs2_build_filesystem(struct ic->scan_dents =NULL ;cond_resched (); } +jffs2_build_xattr_caches (c); c->flags &= ~JFFS2_SB_FLAG_BUILDING ;D1 (printk (KERN_DEBUG "Pass 3 complete\n" ));
@@ -184,6 +185,7 @@ exit:jffs2_free_full_dirent (fd); } } +jffs2_clear_xattr_caches (c); }return ret;
fs/jffs2/dir.c +5 -0
@@ -57,7 +57,12 @@ struct inode_operations jffs2_dir_inode_ .rmdir = jffs2_rmdir, .mknod = jffs2_mknod, .rename = jffs2_rename, + .permission = jffs2_permission, .setattr = jffs2_setattr, + .setxattr = jffs2_setxattr, + .getxattr = jffs2_getxattr, + .listxattr = jffs2_listxattr, + .removexattr = jffs2_removexattr };/***********************************************************************/
fs/jffs2/file.c +6 -1
@@ -57,7 +57,12 @@ struct file_operations jffs2_file_operatstruct inode_operations jffs2_file_inode_operations = { - .setattr = jffs2_setattr + .permission = jffs2_permission, + .setattr = jffs2_setattr, + .setxattr = jffs2_setxattr, + .getxattr = jffs2_getxattr, + .listxattr = jffs2_listxattr, + .removexattr = jffs2_removexattr }; struct address_space_operations jffs2_file_address_operations =
fs/jffs2/fs.c +6 -0
@@ -217,6 +217,8 @@ void jffs2_clear_inode (struct inode *inD1 (printk (KERN_DEBUG "jffs2_clear_inode(): ino #%lu mode %o\n" , inode->i_ino, inode->i_mode)); +if (f->inocache && !f->inocache->nlink) +jffs2_xattr_clear_inode (c, f->inocache);jffs2_do_clear_inode (c, f); }
@@ -504,6 +506,9 @@ int jffs2_do_fill_super(struct super_blo }memset (c->inocache_list,0 ,INOCACHE_HASHSIZE *sizeof (struct jffs2_inode_cache *)); +if ((ret =jffs2_init_xattr_caches (c))) + goto out_inohash; +if ((ret =jffs2_do_mount_fs (c))) goto out_inohash;
@@ -537,6 +542,7 @@ int jffs2_do_fill_super(struct super_blovfree (c->blocks); else kfree(c->blocks); +jffs2_clear_xattr_caches (c); out_inohash:kfree (c->inocache_list); out_wbuf:
fs/jffs2/gc.c +6 -1
@@ -251,7 +251,12 @@ int jffs2_garbage_collect_pass(struct jf/* FIXME: If it's something that needs to be copied, including something we don't grok that has JFFS2_NODETYPE_RWCOMPAT_COPY, we should do so */ spin_unlock (&c->erase_completion_lock); -jffs2_mark_node_obsolete (c, raw); +if (raw->owner) { +/* JFFS2_NODETYPE_XATTR or JFFS2_NODETYPE_XREF */ + ret =jffs2_garbage_collect_xattr (c, raw); + }else { +jffs2_mark_node_obsolete (c, raw); + }up (&c->alloc_sem); goto eraseit_lock; }
fs/jffs2/malloc.c +61 -2
90 lines not on this page · raw message
fs/jffs2/nodelist.c +1 -0
@@ -934,6 +934,7 @@ void jffs2_free_ino_caches(struct jffs2_ this = c->inocache_list[i];while (this) { next = this->next; +jffs2_xattr_free_inode (c, this);jffs2_free_inode_cache (this); this = next; }
fs/jffs2/nodelist.h +13 -0
@@ -20,6 +20,7 @@#include <linux/jffs2.h> #include <linux/jffs2_fs_sb.h> #include <linux/jffs2_fs_i.h> +#include <linux/jffs2_fs_x.h> #ifdef __ECOS#include "os-ecos.h"
@@ -80,6 +81,7 @@ struct jffs2_raw_node_refstruct jffs2_raw_node_ref *next_phys;uint32_t flash_offset;uint32_t __totlen;/* This may die; use ref_totlen(c, jeb, ) below */ +void *owner; };/* flash_offset & 3 always has to be zero, because nodes are
@@ -111,6 +113,10 @@ struct jffs2_inode_cache {uint32_t ino;int nlink;int state; +#ifdef CONFIG_JFFS2_XATTR +struct list_head ilist; +uint8_t ilist_checked; +#endif };/* Inode states for 'state' above. We need the 'GC' state to prevent
@@ -367,6 +373,13 @@ void jffs2_free_node_frag(struct jffs2_nstruct jffs2_inode_cache *jffs2_alloc_inode_cache (void );void jffs2_free_inode_cache (struct jffs2_inode_cache *); +#ifdef CONFIG_JFFS2_XATTR +struct jffs2_xattr_cache *jffs2_alloc_xattr_cache (void ); +void jffs2_free_xattr_cache (struct jffs2_xattr_cache *); +struct jffs2_xattr_ref *jffs2_alloc_xattr_ref (void ); +void jffs2_free_xattr_ref (struct jffs2_xattr_ref *); +#endif /* CONFIG_JFFS2_XATTR */ +/* gc.c */ int jffs2_garbage_collect_pass (struct jffs2_sb_info *c);
fs/jffs2/readinode.c +1 -0
@@ -902,6 +902,7 @@ int jffs2_do_read_inode(struct jffs2_sb_ f->inocache->ino = f->inocache->nlink =1 ; f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache; f->inocache->state =INO_STATE_READING ; +initxattr_jffs2_inode_cache (f->inocache);jffs2_add_ino_cache (c, f->inocache); }if (!f->inocache) {
fs/jffs2/scan.c +225 -1
250 lines not on this page · raw message
fs/jffs2/super.c +2 -0
@@ -151,6 +151,7 @@ static struct super_block *jffs2_get_sb_ sb->s_op = &jffs2_super_operations; sb->s_flags = flags |MS_NOATIME ; + sb->s_xattr = jffs2_xattr_handlers; ret =jffs2_do_fill_super (sb, data, (flags&MS_VERBOSE )?1 :0 );
@@ -290,6 +291,7 @@ static void jffs2_put_super (struct supekfree (c->blocks);jffs2_flash_cleanup (c);kfree (c->inocache_list); +jffs2_clear_xattr_caches (c);if (c->mtd->sync) c->mtd->sync (c->mtd);
fs/jffs2/symlink.c +6 -1
@@ -24,7 +24,12 @@ struct inode_operations jffs2_symlink_in { .readlink = generic_readlink, .follow_link = jffs2_follow_link, - .setattr = jffs2_setattr + .permission = jffs2_permission, + .setattr = jffs2_setattr, + .setxattr = jffs2_setxattr, + .getxattr = jffs2_getxattr, + .listxattr = jffs2_listxattr, + .removexattr = jffs2_removexattr };static int jffs2_follow_link (struct dentry *dentry,struct nameidata *nd)
fs/jffs2/write.c +1 -1
@@ -36,7 +36,7 @@ int jffs2_do_new_inode(struct jffs2_sb_i f->inocache->nlink =1 ; f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache; f->inocache->state =INO_STATE_PRESENT ; - +initxattr_jffs2_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));
fs/jffs2/xattr.c +1170 -0
1,170 lines not on this page · raw message
include/linux/jffs2.h +32 -0
@@ -59,6 +59,8 @@#define JFFS2_NODETYPE_INODE (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 2)#define JFFS2_NODETYPE_CLEANMARKER (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3)#define JFFS2_NODETYPE_PADDING (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 4) +#define JFFS2_NODETYPE_XATTR (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 8) +#define JFFS2_NODETYPE_XREF (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 9)// Maybe later... //#define JFFS2_NODETYPE_CHECKPOINT (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3)
@@ -146,9 +148,39 @@ struct jffs2_raw_inodeuint8_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 length;/* upper 12bit = length of name */ +/* lower 20bit = length of value */ +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 seqno;/* sequencial number */ +jint32_t ino;/* inode number */ +jint32_t xid;/* XATTR identifier number */ +jint32_t node_crc; +} __attribute__((packed)); +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_unknown_node u; };
include/linux/jffs2_fs_sb.h +10 -0
@@ -112,6 +112,16 @@ struct jffs2_sb_info {uint32_t fsdata_len;#endif +#ifdef CONFIG_JFFS2_XATTR +uint32_t highest_xid; +uint32_t highest_seqno; +struct list_head *xattrcache; +#define xattr_temp xattrcache[XATTRCACHE_HASHSIZE] +struct rw_semaphore xattr_sem; + +uint32_t xcache_mem_usage; +uint32_t xcache_mem_threshold; +#endif /* OS-private pointer for getting back to master superblock info */ void *os_priv; };
include/linux/jffs2_fs_x.h +140 -0
140 lines not on this page · raw message
Quoted 44 lines · Kaigai Kohei
This attached patch enables XATTR support in JFFS2. (take-2) # The contribution has slowed due to the trouble related to GC :-(
The my first patch posted in Aug 23 is revised at the points as follows.
- get/setxattr are implemented as a method of generic XATTR handler.
- new methods for "user.*" and "trusted.*" prefix were added.- Time to retrieve the duplicate XATTR-cache shortened, when
setxattr(). In first implementation, we must scan all XATTR-cache to find the duplicate
one, and it's so expensive. Now, we cau use the hash-list of XATTR-cache which is indexed by own contents.- Now, Garbage Collector can deal
JFFS2_NODETYPE_XATTRandJFFS2_NODETYPE_XREF.
It seems to me that GC can mark unconditionally any nodes without inode as obsolete. But new JFFS2_NODETYPE_XATTR/XREF should be an exception. GC must not mark them as obsolete, although their "next_in_ino" is NULL.----[
jffs2_garbage_collect_pass()ingc.c]------------------------
249 if (!raw->next_in_ino) { <-- unconditionally mark it as
obsolete.
250 /* Inode-less node. Clean marker, snapshot or something like
that */
251 /* FIXME: If it's something that needs to be copied, including
something
252 we don't grok that hasJFFS2_NODETYPE_RWCOMPAT_COPY, we
should do so */253 spin_unlock(&c->erase_completion_lock); 254 jffs2_mark_node_obsolete(c, raw); 255 up(&c->alloc_sem); 256 goto eraseit_lock;257 }
--------------------------------------------------------------------I added a new variable 'owner' into
jffs2_raw_node_refto resolve this. It refersjffs2_xattr_cacheorjffs2_xattr_refobject when raw-node reflect
XATTR-node. Thus, we can distinguish XATTR-node and others by whether 'owner'
is NULL or not.
Quoted 6 lines
- Consistency has improved.
check_xattr_ref_ilist()checks XATTRs which are binded to same inode. If multiple XATTR has same name exist, older one is marked as obsolete. In first implementation, there are possibilities to be created multiple XATTRs have same name in an inode, when system-crash happens durlingsetxattr()
Sounds good.
It appears as if your patch or something based on it will win. So let's have a look...
I notice that you make a couple of mistakes by copying them from existing jffs2 code. You are excused for that, no doubt. But I still don't want copies of old mistakes to go in, just because we have a bad example.
Review is just partial. It's late enough already and I need to get some sleep.
Quoted 93 lines
diff -rpNU3 mtd-0829/fs/Kconfig mtd-0829.xattr/fs/Kconfig
fs/Kconfig +16
-0@@ -64,6 +64,22 @@ config JFFS2_FS_WRITEBUFFER - NOR flash with transparent ECC - DataFlash +config JFFS2_XATTR + bool "JFFS2 XATTR support (EXPERIMENTAL)" + depends on JFFS2_FS + default n + help + This enables the XATTR support in JFFS2. + + It's neccesary for persistent security context in SELinux. + Now, we can use the following kinds of prefix. + + - security.* + - user.* + - trust.* + + - system.posix_acl_{access|default} are in TODO list now. + config JFFS2_COMPRESSION_OPTIONS bool "Advanced compression options for JFFS2" default ndiff -rpNU3 mtd-0829/fs/jffs2/Makefile.common mtd-0829.xattr/fs/jffs2/Makefile.common
fs/jffs2/Makefile.common +1
-0@@ -12,6 +12,7 @@ jffs2-y += symlink.o build.o erase.o bac jffs2-y += super.o debug.o jffs2-$(CONFIG_JFFS2_FS_WRITEBUFFER) += wbuf.o +jffs2-$(CONFIG_JFFS2_XATTR) += xattr.o jffs2-$(CONFIG_JFFS2_RUBIN) += compr_rubin.o jffs2-$(CONFIG_JFFS2_RTIME) += compr_rtime.o jffs2-$(CONFIG_JFFS2_ZLIB) += compr_zlib.odiff -rpNU3
mtd-0829/fs/jffs2/build.cmtd-0829.xattr/fs/jffs2/build.cfs/jffs2/build.c +2
-0@@ -165,6 +165,7 @@ static int jffs2_build_filesystem(struct ic->scan_dents =NULL ;cond_resched (); } +jffs2_build_xattr_caches (c); c->flags &= ~JFFS2_SB_FLAG_BUILDING ;D1 (printk (KERN_DEBUG "Pass 3 complete\n" ));@@ -184,6 +185,7 @@ exit:jffs2_free_full_dirent (fd); } } +jffs2_clear_xattr_caches (c); }return ret;diff -rpNU3
mtd-0829/fs/jffs2/dir.cmtd-0829.xattr/fs/jffs2/dir.cfs/jffs2/dir.c +5
-0@@ -57,7 +57,12 @@ struct inode_operations jffs2_dir_inode_ .rmdir = jffs2_rmdir, .mknod = jffs2_mknod, .rename = jffs2_rename, + .permission = jffs2_permission, .setattr = jffs2_setattr, + .setxattr = jffs2_setxattr, + .getxattr = jffs2_getxattr, + .listxattr = jffs2_listxattr, + .removexattr = jffs2_removexattr };/***********************************************************************/ diff -rpNU3
mtd-0829/fs/jffs2/file.cmtd-0829.xattr/fs/jffs2/file.cfs/jffs2/file.c +6
-1@@ -57,7 +57,12 @@ struct file_operations jffs2_file_operatstruct inode_operations jffs2_file_inode_operations = { - .setattr = jffs2_setattr + .permission = jffs2_permission, + .setattr = jffs2_setattr, + .setxattr = jffs2_setxattr, + .getxattr = jffs2_getxattr, + .listxattr = jffs2_listxattr, + .removexattr = jffs2_removexattr }; struct address_space_operations jffs2_file_address_operations =diff -rpNU3
mtd-0829/fs/jffs2/fs.cmtd-0829.xattr/fs/jffs2/fs.c
fs/jffs2/fs.c void jffs2_clear_inode (struct inode *in · line 221
Quoted 5 lines
fs/jffs2/fs.c +2
-0@@ -217,6 +217,8 @@ void jffs2_clear_inode (struct inode *inD1 (printk (KERN_DEBUG "jffs2_clear_inode(): ino #%lu mode %o\n" , inode->i_ino, inode->i_mode)); +if (f->inocache && !f->inocache->nlink) +jffs2_xattr_clear_inode (c, f->inocache);
Move the test into jffs2_xattr_clear_inode().
fs/jffs2/fs.c int jffs2_do_fill_super(struct super_blo · line 511
Quoted 10 lines
fs/jffs2/fs.c +3
-0jffs2_do_clear_inode (c, f); }@@ -504,6 +506,9 @@ int jffs2_do_fill_super(struct super_blo }memset (c->inocache_list,0 ,INOCACHE_HASHSIZE *sizeof (struct jffs2_inode_cache *)); +if ((ret =jffs2_init_xattr_caches (c))) + goto out_inohash; +
ret = jffs2_init_xattr_caches(c); if (ret) goto out_inohash;
I agree with gcc, when it warns about assignments in conditions. What I don't agree with is the proposal to use double brackets.
Quoted 83 lines
fs/jffs2/fs.c +1
-0if ((ret =jffs2_do_mount_fs (c))) goto out_inohash;@@ -537,6 +542,7 @@ int jffs2_do_fill_super(struct super_blovfree (c->blocks); else kfree(c->blocks); +jffs2_clear_xattr_caches (c); out_inohash:kfree (c->inocache_list); out_wbuf:diff -rpNU3
mtd-0829/fs/jffs2/gc.cmtd-0829.xattr/fs/jffs2/gc.cfs/jffs2/gc.c +6
-1@@ -251,7 +251,12 @@ int jffs2_garbage_collect_pass(struct jf/* FIXME: If it's something that needs to be copied, including something we don't grok that has JFFS2_NODETYPE_RWCOMPAT_COPY, we should do so */ spin_unlock (&c->erase_completion_lock); -jffs2_mark_node_obsolete (c, raw); +if (raw->owner) { +/* JFFS2_NODETYPE_XATTR or JFFS2_NODETYPE_XREF */ + ret =jffs2_garbage_collect_xattr (c, raw); + }else { +jffs2_mark_node_obsolete (c, raw); + }up (&c->alloc_sem); goto eraseit_lock; }diff -rpNU3
mtd-0829/fs/jffs2/malloc.cmtd-0829.xattr/fs/jffs2/malloc.cfs/jffs2/malloc.c +28
-2@@ -26,6 +26,10 @@ static kmem_cache_t *tmp_dnode_info_slabstatic kmem_cache_t *raw_node_ref_slab;static kmem_cache_t *node_frag_slab;static kmem_cache_t *inode_cache_slab; +#ifdef CONFIG_JFFS2_XATTR +static kmem_cache_t *xattr_cache_slab; +static kmem_cache_t *xattr_ref_slab; +#endif int __init jffs2_create_slab_caches (void ) {@@ -68,8 +72,24 @@ int __init jffs2_create_slab_caches(void inode_cache_slab =kmem_cache_create ("jffs2_inode_cache" ,sizeof (struct jffs2_inode_cache ),0 ,0 ,NULL ,NULL ); -if (inode_cache_slab) -return 0 ; +if (!inode_cache_slab) + goto err; + +#ifdef CONFIG_JFFS2_XATTR + xattr_cache_slab =kmem_cache_create ("jffs2_xattr_cache" , +sizeof (struct jffs2_xattr_cache ), +0 ,0 ,NULL ,NULL ); +if (!xattr_cache_slab) + goto err; + + xattr_ref_slab =kmem_cache_create ("jffs2_xattr_ref" , +sizeof (struct jffs2_xattr_ref ), +0 ,0 ,NULL ,NULL ); +if (!xattr_ref_slab) + goto err; +#endif + +return 0 ; err:jffs2_destroy_slab_caches ();return -ENOMEM ;@@ -91,6 +111,12 @@ void jffs2_destroy_slab_caches(void)kmem_cache_destroy (node_frag_slab);if (inode_cache_slab)kmem_cache_destroy (inode_cache_slab); +#ifdef CONFIG_JFFS2_XATTR +if (xattr_cache_slab) +kmem_cache_destroy (xattr_cache_slab); +if (xattr_ref_slab) +kmem_cache_destroy (xattr_ref_slab); +#endif }struct jffs2_full_dirent *jffs2_alloc_full_dirent (int namesize)
fs/jffs2/malloc.c struct jffs2_raw_node_ref *jffs2_alloc_r · line 198
Quoted 4 lines
fs/jffs2/malloc.c +1
-0@@ -169,6 +195,7 @@ struct jffs2_raw_node_ref *jffs2_alloc_rstruct jffs2_raw_node_ref *ret; ret =kmem_cache_alloc (raw_node_ref_slab,GFP_KERNEL );JFFS2_DBG_MEMALLOC ("%p\n" , ret); +memset (ret,0 ,sizeof (*ret));/* to guarantee owner==NULL */
This could be optimized a little by using the constructor/destructor stuff in slabs. Not too important.
fs/jffs2/malloc.c void jffs2_free_inode_cache(struct jffs2 · line 240
Quoted 13 lines
fs/jffs2/malloc.c +6
-0return ret; }@@ -205,3 +232,35 @@ void jffs2_free_inode_cache(struct jffs2JFFS2_DBG_MEMALLOC ("%p\n" , x);kmem_cache_free (inode_cache_slab, x); } + +#ifdef CONFIG_JFFS2_XATTR + +struct jffs2_xattr_cache *jffs2_alloc_xattr_cache (void ) +{ +struct jffs2_xattr_cache *xc;
^^^^^^
The name doesn't make sense. You're referring to a single object, not the complete cache. Quite confusing.
fs/jffs2/malloc.c void jffs2_free_inode_cache(struct jffs2 · line 241
Quoted 1 line
fs/jffs2/malloc.c +1
-0+ xc =kmem_cache_alloc (xattr_cache_slab,GFP_KERNEL );
^^^^^
This is the cache. A slab is just part of the cache. So please rename the two.
fs/jffs2/malloc.c void jffs2_free_inode_cache(struct jffs2 · line 254
Quoted 13 lines
fs/jffs2/malloc.c +13
-0+JFFS2_DBG_MEMALLOC ("%p\n" , xc); +return xc; +} + +void jffs2_free_xattr_cache (struct jffs2_xattr_cache *xc) +{ +JFFS2_DBG_MEMALLOC ("%p\n" , xc); +kmem_cache_free (xattr_cache_slab, xc); +} + +struct jffs2_xattr_ref *jffs2_alloc_xattr_ref (void ) +{ +struct jffs2_xattr_ref *ref;
This name makes sense.
fs/jffs2/malloc.c void jffs2_free_inode_cache(struct jffs2 · line 255
Quoted 1 line
fs/jffs2/malloc.c +1
-0+ ref =kmem_cache_alloc (xattr_ref_slab,GFP_KERNEL );
s/slab/cache/
Quoted 26 lines
fs/jffs2/malloc.c +11
-0+JFFS2_DBG_MEMALLOC ("%p\n" , ref); + return ref; +} + +void jffs2_free_xattr_ref (struct jffs2_xattr_ref *ref) +{ +JFFS2_DBG_MEMALLOC ("%p\n" , ref); +kmem_cache_free (xattr_ref_slab, ref); +} + +#endif diff -rpNU3
mtd-0829/fs/jffs2/nodelist.cmtd-0829.xattr/fs/jffs2/nodelist.cfs/jffs2/nodelist.c +1
-0@@ -934,6 +934,7 @@ void jffs2_free_ino_caches(struct jffs2_ this = c->inocache_list[i];while (this) { next = this->next; +jffs2_xattr_free_inode (c, this);jffs2_free_inode_cache (this); this = next; }diff -rpNU3
mtd-0829/fs/jffs2/nodelist.hmtd-0829.xattr/fs/jffs2/nodelist.h
fs/jffs2/nodelist.h line 23
Quoted 4 lines
fs/jffs2/nodelist.h +1
-0@@ -20,6 +20,7 @@#include <linux/jffs2.h> #include <linux/jffs2_fs_sb.h> #include <linux/jffs2_fs_i.h> +#include <linux/jffs2_fs_x.h>
I p a l n.
I prefer a longer name. jffs2_fs_xattr.h would be fine. jffs2_xattr.h would also, the "_fs" is more redundant that "attr".
fs/jffs2/nodelist.h struct jffs2_raw_node_ref · line 84
Quoted 8 lines
fs/jffs2/nodelist.h +1
-0#ifdef __ECOS#include "os-ecos.h" @@ -80,6 +81,7 @@ struct jffs2_raw_node_refstruct jffs2_raw_node_ref *next_phys;uint32_t flash_offset;uint32_t __totlen;/* This may die; use ref_totlen(c, jeb, ) below */ +void *owner;
This grows a node reference from 16/24 bytes to 20/32 bytes for 32/64 bit architectures. I'm not entirely happy about that, but don't a better solution either.
Quoted 43 lines
fs/jffs2/nodelist.h +11
-0};/* flash_offset & 3 always has to be zero, because nodes are @@ -111,6 +113,10 @@ struct jffs2_inode_cache {uint32_t ino;int nlink;int state; +#ifdef CONFIG_JFFS2_XATTR +struct list_head ilist; +uint8_t ilist_checked; +#endif };/* Inode states for 'state' above. We need the 'GC' state to prevent @@ -367,6 +373,13 @@ void jffs2_free_node_frag(struct jffs2_nstruct jffs2_inode_cache *jffs2_alloc_inode_cache (void );void jffs2_free_inode_cache (struct jffs2_inode_cache *); +#ifdef CONFIG_JFFS2_XATTR +struct jffs2_xattr_cache *jffs2_alloc_xattr_cache (void ); +void jffs2_free_xattr_cache (struct jffs2_xattr_cache *); +struct jffs2_xattr_ref *jffs2_alloc_xattr_ref (void ); +void jffs2_free_xattr_ref (struct jffs2_xattr_ref *); +#endif /* CONFIG_JFFS2_XATTR */ +/* gc.c */ int jffs2_garbage_collect_pass (struct jffs2_sb_info *c);diff -rpNU3
mtd-0829/fs/jffs2/readinode.cmtd-0829.xattr/fs/jffs2/readinode.cfs/jffs2/readinode.c +1
-0@@ -902,6 +902,7 @@ int jffs2_do_read_inode(struct jffs2_sb_ f->inocache->ino = f->inocache->nlink =1 ; f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache; f->inocache->state =INO_STATE_READING ; +initxattr_jffs2_inode_cache (f->inocache);jffs2_add_ino_cache (c, f->inocache); }if (!f->inocache) {diff -rpNU3
mtd-0829/fs/jffs2/scan.cmtd-0829.xattr/fs/jffs2/scan.c
fs/jffs2/scan.c static int jffs2_scan_inode_node(struct · line 65
Quoted 9 lines
fs/jffs2/scan.c +6
-0@@ -57,6 +57,12 @@ static int jffs2_scan_inode_node(struct struct jffs2_raw_inode *ri, uint32_t ofs);static int jffs2_scan_dirent_node (struct jffs2_sb_info *c,struct jffs2_eraseblock *jeb,struct jffs2_raw_dirent *rd,uint32_t ofs); +#ifdef CONFIG_JFFS2_XATTR +static int jffs2_scan_xattr_node (struct jffs2_sb_info *c,struct jffs2_eraseblock *jeb, +struct jffs2_raw_xattr *rx,uint32_t ofs); +static int jffs2_scan_xref_node (struct jffs2_sb_info *c,struct jffs2_eraseblock *jeb, +struct jffs2_raw_xref *rr,uint32_t ofs); +#endif
You don't need the function definitions if you change the order inside the file.
Quoted 31 lines
fs/jffs2/scan.c +24
-1#define BLK_STATE_ALLFF 0#define BLK_STATE_CLEAN 1@@ -552,7 +558,40 @@ scan_more:if (err)return err; ofs +=PAD (je32_to_cpu (node->totlen));break ; - +#ifdef CONFIG_JFFS2_XATTR +case JFFS2_NODETYPE_XATTR : +if (buf_ofs + buf_len < ofs +je32_to_cpu (node->totlen)) { + buf_len =min_t (uint32_t, buf_size, jeb->offset + c->sector_size - ofs); +D1 (printk (KERN_DEBUG "Fewer than %d bytes (xattr node) left to end of buf." +" Reading 0x%x at 0x%08x\n" ,je32_to_cpu (node->totlen), buf_len, ofs)); + err =jffs2_fill_scan_buf (c, buf, ofs, buf_len); +if (err) +return err; + buf_ofs = ofs; + node = (void *)buf; + } + err =jffs2_scan_xattr_node (c, jeb, (void *)node, ofs); +if (err) +return err; + ofs +=PAD (je32_to_cpu (node->totlen)); +break ; +case JFFS2_NODETYPE_XREF : +if (buf_ofs + buf_len < ofs +je32_to_cpu (node->totlen)) { + buf_len =min_t (uint32_t, buf_size, jeb->offset + c->sector_size - ofs); +D1 (printk (KERN_DEBUG "Fewer than %d bytes (xref node) left to end of buf." +" Reading 0x%x at 0x%08x\n" ,je32_to_cpu (node->totlen), buf_len, ofs)); + err =jffs2_fill_scan_buf (c, buf, ofs, buf_len); +if (err)
fs/jffs2/scan.c scan_more: · line 594
Quoted 10 lines
fs/jffs2/scan.c +10
-0+return err; + buf_ofs = ofs; + node = (void *)buf; + } + err =jffs2_scan_xref_node (c, jeb, (void *)node, ofs); +if (err) +return err; + ofs +=PAD (je32_to_cpu (node->totlen)); +break ; +#endif
By itself, this code is not too bad. But it add a little more crap to a function that is aching for a rewrite already. Not sure.
Quoted 25 lines
fs/jffs2/scan.c +11
-0case JFFS2_NODETYPE_CLEANMARKER :D1 (printk (KERN_DEBUG "CLEANMARKER node found at 0x%08x\n" , ofs));if (je32_to_cpu (node->totlen) != c->cleanmarker_size) {@@ -665,6 +704,7 @@ static struct jffs2_inode_cache *jffs2_s ic->ino = ino; ic->nodes = (void *)ic; +initxattr_jffs2_inode_cache (ic);jffs2_add_ino_cache (c, ic);if (ino ==1 ) ic->nlink =1 ;@@ -820,6 +860,190 @@ static int jffs2_scan_dirent_node(structreturn 0 ; } +#ifdef CONFIG_JFFS2_XATTR +static int jffs2_scan_xattr_node (struct jffs2_sb_info *c,struct jffs2_eraseblock *jeb, +struct jffs2_raw_xattr *rx,uint32_t ofs) +{ +struct jffs2_raw_node_ref *raw; +struct jffs2_xattr_cache *xc; +uint32_t crc; +int xtype, nlen, vlen; + + crc =crc32 (0 , rx,sizeof (*rx)-8 );
fs/jffs2/scan.c static int jffs2_scan_dirent_node(struct · line 882
Quoted 10 lines
fs/jffs2/scan.c +10
-0+if (crc !=je32_to_cpu (rx->node_crc)) { +printk (KERN_NOTICE "jffs2_scan_xattr_node(): Node CRC failed" +" on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n" , + ofs,je32_to_cpu (rx->node_crc), crc); +DIRTY_SPACE (PAD (je32_to_cpu (rx->totlen))); +return 0 ; + } + + nlen =JFFS2_XATTR_NAMELEN (je32_to_cpu (rx->length)); + vlen =JFFS2_XATTR_VALUELEN (je32_to_cpu (rx->length));
Types don't match. nlen and vlen should become u32.
Btw, I agree with Linus. u32 is _much_ nicer than uint32_t, not to speak of the uint32_fast_t insanity.
Quoted 14 lines
fs/jffs2/scan.c +14
-0+if (je32_to_cpu (rx->totlen) !=sizeof (*rx)+PAD (nlen+1 )+PAD (vlen)) { +printk (KERN_NOTICE "jffs2_scan_xattr_node(): length mimatch!" +" totlen=%d length=0x%08x nlen=%d vlen=%d on 0x%08x\n" , +je32_to_cpu (rx->totlen),je32_to_cpu (rx->length), nlen, vlen, ofs); +DIRTY_SPACE (PAD (je32_to_cpu (rx->totlen))); +return 0 ; + } + + crc =crc32 (0 , rx->data,PAD (nlen+1 )+PAD (vlen)); +if (crc !=je32_to_cpu (rx->data_crc)) { +printk (KERN_NOTICE "jffs2_scan_xattr_node(): Data CRC failed" +" on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n" , + ofs,je32_to_cpu (rx->data_crc), crc); +DIRTY_SPACE (PAD (je32_to_cpu (rx->totlen)));
fs/jffs2/scan.c static int jffs2_scan_dirent_node(struct · line 906
Quoted 10 lines
fs/jffs2/scan.c +10
-0+return 0 ; + } + + xc =jffs2_find_xattr_cache_xid (c,je32_to_cpu (rx->xid)); +if (xc) { +printk (KERN_NOTICE "jffs2_scan_xattr_node(): Duplicate XID Found" +" on node at 0x%08x XID=%d Later one ignored\n" , ofs, xc->xid); +DIRTY_SPACE (PAD (je32_to_cpu (rx->totlen))); +return 0 ; + }
How do you deal with xattr reference counting and lifetime?
fs/jffs2/scan.c static int jffs2_scan_dirent_node(struct · line 914
Quoted 7 lines
fs/jffs2/scan.c +7
-0+ xtype =jffs2_xattr_prefix_to_xtype (rx->data, nlen); +if (JFFS2_XATTRTYPE_INVALID ==xtype) { +printk (KERN_NOTICE "jffs2_scan_xattr_node(): Unsupported xattr type" +" on node at 0x%08x\n" , ofs); +USED_SPACE (PAD (je32_to_cpu (rx->totlen))); +return 0 ; + }
Why is it required that JFFS2 knows the type of the xattr?
Quoted 33 lines
fs/jffs2/scan.c +33
-0+ + raw =jffs2_alloc_raw_node_ref (); +if (!raw) +return -ENOMEM ; + + xc =jffs2_alloc_xattr_cache (); +if (!xc) { +jffs2_free_raw_node_ref (raw); +return -ENOMEM ; + } +initxattr_jffs2_xattr_cache (xc); + + xc->xid =je32_to_cpu (rx->xid); +if (xc->xid > c->highest_xid) + c->highest_xid = xc->xid; + xc->xtype = xtype; + xc->node = raw; + xc->name_len = nlen; + xc->value_len = vlen; + xc->data_crc = crc; + + raw->__totlen =PAD (je32_to_cpu (rx->totlen)); + raw->flash_offset = ofs |REF_PRISTINE ; + raw->next_phys =NULL ; + raw->next_in_ino =NULL ; +if (!jeb->first_node) + jeb->first_node = raw; +if (jeb->last_node) + jeb->last_node->next_phys = raw; + jeb->last_node = raw; +USED_SPACE (PAD (je32_to_cpu (rx->totlen))); + +jffs2_attach_xattr_cache (c, xc);
fs/jffs2/scan.c static int jffs2_scan_dirent_node(struct · line 957
Quoted 10 lines
fs/jffs2/scan.c +10
-0+ +D1 (printk (KERN_NOTICE "XATTR_CACHE: XID=%d inserted\n" , xc->xid)); +return 0 ; +} + +static inline int jffs2_scan_xref_node_helper (struct jffs2_sb_info *c, +struct jffs2_xattr_ref *new,struct jffs2_xattr_ref *old) +{ +/* (uint32_t)new->xc == (uint32_t)old->xc has been made sure. */ +if ((uint32_t )new->ic == (uint32_t )old->ic) {
Why the casts? How can this be safe on 64bit machines?
Quoted 34 lines
fs/jffs2/scan.c +34
-0+if (new->seqno > old->seqno) { +jffs2_mark_node_obsolete (c, old->node); + old->seqno = new->seqno; + old->node = new->node; + }else { +jffs2_mark_node_obsolete (c, new->node); + } +return 1 ;/* 'new' should be released. */ + } +return 0 ; +} + +static int jffs2_scan_xref_node (struct jffs2_sb_info *c,struct jffs2_eraseblock *jeb, +struct jffs2_raw_xref *rr,uint32_t ofs) +{ +struct jffs2_raw_node_ref *raw; +struct jffs2_xattr_ref *ref, *pos, *pos2; +uint32_t crc; + + crc =crc32 (0 , rr,sizeof (*rr)-4 ); +if (crc !=je32_to_cpu (rr->node_crc)) { +printk (KERN_NOTICE "jffs2_scan_xref_node(): Node CRC failed" +" on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n" , + ofs,je32_to_cpu (rr->node_crc), crc); +DIRTY_SPACE (PAD (je32_to_cpu (rr->totlen))); +return 0 ; + } + + ref =jffs2_alloc_xattr_ref (); +if (!ref) +return -ENOMEM ; +initxattr_jffs2_xattr_ref (ref); + + raw =jffs2_alloc_raw_node_ref ();
fs/jffs2/scan.c static int jffs2_scan_dirent_node(struct · line 1001
Quoted 10 lines
fs/jffs2/scan.c +10
-0+if (!raw) { +jffs2_free_xattr_ref (ref); +return -ENOMEM ; + } + + ref->seqno =je32_to_cpu (rr->seqno); +if (ref->seqno > c->highest_seqno) + c->highest_seqno = ref->seqno; + ref->ic = (void *)je32_to_cpu (rr->ino); + ref->xc = (void *)je32_to_cpu (rr->xid);
WTF?!?
You read a je32 from flash and use that as a pointer?!?
Please tell me I'm wrong.
Jörn
Signature · 4 lines
Don't worry about people stealing your ideas. If your ideas are any good, you'll have to ram them down people's throats. -- Howard Aiken quoted by Ken Iverson quoted by Jim Horning quoted by Raph Levien, 1979
David Woodhouse
maintainerQuoted 2 lines · Jörn Engel
I prefer a longer name.
jffs2_fs_xattr.hwould be fine.jffs2_xattr.hwould also, the "_fs" is more redundant that "attr".
Now would probably be a good time to drop jffs2_fs_i.h and jffs2_fs_sb.h anyway. We no longer have the inode and superblock unions; this stuff can be entirely contained within the fs/jffs2/ directory instead of being in include/linux/
Signature · 1 line
dwmw2
Hello,Jörn.
Thanks for reviewing in spite of so long patch.
Quoted 9 lines
Sounds good.
It appears as if your patch or something based on it will win. So let's have a look...
I notice that you make a couple of mistakes by copying them from existing jffs2 code. You are excused for that, no doubt. But I still don't want copies of old mistakes to go in, just because we have a bad example.
Is this using uint32_t, xattr scanning code and so on ?
Quoted 2 lines
Review is just partial. It's late enough already and I need to get some sleep.
Please take a rest slowly on the weekend.
I'll modify my patch during this period. ;-)
Quoted 11 lines
fs/jffs2/fs.c void jffs2_clear_inode (struct inode *in · line 221
Quoted 8 lines
fs/jffs2/fs.c +2
-0@@ -217,6 +217,8 @@ void jffs2_clear_inode (struct inode *inD1 (printk (KERN_DEBUG "jffs2_clear_inode(): ino #%lu mode %o\n" , inode->i_ino, inode->i_mode)); +if (f->inocache && !f->inocache->nlink) +jffs2_xattr_clear_inode (c, f->inocache);Move the test into
jffs2_xattr_clear_inode().
OK, I'll modify it.
Quoted 13 lines
fs/jffs2/fs.c int jffs2_do_fill_super(struct super_blo · line 511
Quoted 7 lines
fs/jffs2/fs.c +3
-0@@ -504,6 +506,9 @@ int jffs2_do_fill_super(struct super_blo }memset (c->inocache_list,0 ,INOCACHE_HASHSIZE *sizeof (struct jffs2_inode_cache *)); +if ((ret =jffs2_init_xattr_caches (c))) + goto out_inohash; +ret = jffs2_init_xattr_caches(c); if (ret) goto out_inohash;
Quoted 2 lines
I agree with gcc, when it warns about assignments in conditions. What I don't agree with is the proposal to use double brackets.
OK, I'll modify this and similar codes at different location if exist.
Quoted 10 lines
fs/jffs2/fs.c struct jffs2_raw_node_ref *jffs2_alloc_r · line 198
Quoted 6 lines
fs/jffs2/fs.c +1
-0struct jffs2_full_dirent *jffs2_alloc_full_dirent (int namesize)@@ -169,6 +195,7 @@ struct jffs2_raw_node_ref *jffs2_alloc_rstruct jffs2_raw_node_ref *ret; ret =kmem_cache_alloc (raw_node_ref_slab,GFP_KERNEL );JFFS2_DBG_MEMALLOC ("%p\n" , ret); +memset (ret,0 ,sizeof (*ret));/* to guarantee owner==NULL */ This could be optimized a little by using the constructor/destructor stuff in slabs. Not too important.
I'll prepare a tiny and obvious constructor for jffs2_raw_node_ref. NULL is set in raw->owner by default is important, the method of setting is not so, I think.
Quoted 16 lines
fs/jffs2/fs.c void jffs2_free_inode_cache(struct jffs2 · line 240
Quoted 10 lines
fs/jffs2/fs.c +6
-0@@ -205,3 +232,35 @@ void jffs2_free_inode_cache(struct jffs2JFFS2_DBG_MEMALLOC ("%p\n" , x);kmem_cache_free (inode_cache_slab, x); } + +#ifdef CONFIG_JFFS2_XATTR + +struct jffs2_xattr_cache *jffs2_alloc_xattr_cache (void ) +{ +struct jffs2_xattr_cache *xc;^^^^^^The name doesn't make sense. You're referring to a single object, not the complete cache. Quite confusing.
Quoted 5 lines
fs/jffs2/fs.c void jffs2_free_inode_cache(struct jffs2 · line 241
Quoted 1 line
fs/jffs2/fs.c +1
-0+ xc =kmem_cache_alloc (xattr_cache_slab,GFP_KERNEL );^^^^^This is the cache. A slab is just part of the cache. So please rename the two.
For example, how about the following names ? "jffs2_xattr_datum" as an alternative of jffs2_xattr_cache. "xattr_datum_cache" as an alternative of xattr_cache_slab.
In this case, "xc" defined as jffs2_xattr_cache structure should be renamed to "xd" defined as jffs2_xattr_datum.
Quoted 14 lines
fs/jffs2/fs.c void jffs2_free_inode_cache(struct jffs2 · line 250
Quoted 9 lines
fs/jffs2/fs.c +9
-0+void jffs2_free_xattr_cache (struct jffs2_xattr_cache *xc) +{ +JFFS2_DBG_MEMALLOC ("%p\n" , xc); +kmem_cache_free (xattr_cache_slab, xc); +} + +struct jffs2_xattr_ref *jffs2_alloc_xattr_ref (void ) +{ +struct jffs2_xattr_ref *ref;This name makes sense.
Quoted 4 lines
fs/jffs2/fs.c void jffs2_free_inode_cache(struct jffs2 · line 251
Quoted 1 line
fs/jffs2/fs.c +1
-0+ ref =kmem_cache_alloc (xattr_ref_slab,GFP_KERNEL );s/slab/cache/
OK, I'll rename it.
Quoted 12 lines
fs/jffs2/nodelist.h line 23
Quoted 8 lines
diff -rpNU3
mtd-0829/fs/jffs2/nodelist.hmtd-0829.xattr/fs/jffs2/nodelist.hfs/jffs2/nodelist.h +1
-0@@ -20,6 +20,7 @@#include <linux/jffs2.h> #include <linux/jffs2_fs_sb.h> #include <linux/jffs2_fs_i.h> +#include <linux/jffs2_fs_x.h> I p a l n.
Quoted 2 lines
I prefer a longer name.
jffs2_fs_xattr.hwould be fine.jffs2_xattr.hwould also, the "_fs" is more redundant that "attr".
OK, I'll rename "jffs2_fs_x.h" to "jffs2_xattr.h" and deploy it under "fs/jffs2" as David says.
Quoted 4 lines
Quoted 4 lines
fs/jffs2/nodelist.h +0
-0#ifdef __ECOS#include "os-ecos.h" @@ -80,6 +81,7 @@ struct jffs2_raw_node_refstruct jffs2_raw_node_ref *next_phys;
Quoted 8 lines
fs/jffs2/nodelist.h struct jffs2_raw_node_ref · line 84
Quoted 3 lines
fs/jffs2/nodelist.h +1
-0uint32_t flash_offset;uint32_t __totlen;/* This may die; use ref_totlen(c, jeb, ) below */ +void *owner;This grows a node reference from 16/24 bytes to 20/32 bytes for 32/64 bit architectures. I'm not entirely happy about that, but don't a better solution either.
Indeed, it's involved the growing of object size.
But we must discriminate XATTR node from other non-inode node and indicate jffs2_xattr_cache/jffs2_xattr_ref object from this. I didn't have a good idea more than this.
And, I forgot to enclose the declaration of "void *owner" by #ifdef - #endif.
Quoted 9 lines
Quoted 9 lines
diff -rpNU3
mtd-0829/fs/jffs2/scan.cmtd-0829.xattr/fs/jffs2/scan.cfs/jffs2/scan.c +2
-0@@ -57,6 +57,12 @@ static int jffs2_scan_inode_node(struct struct jffs2_raw_inode *ri, uint32_t ofs);static int jffs2_scan_dirent_node (struct jffs2_sb_info *c,struct jffs2_eraseblock *jeb,struct jffs2_raw_dirent *rd,uint32_t ofs); +#ifdef CONFIG_JFFS2_XATTR +static int jffs2_scan_xattr_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
Quoted 8 lines
fs/jffs2/scan.c static int jffs2_scan_inode_node(struct · line 65
Quoted 4 lines
fs/jffs2/scan.c +4
-0+ struct jffs2_raw_xattr *rx, uint32_t ofs); +static int jffs2_scan_xref_node (struct jffs2_sb_info *c,struct jffs2_eraseblock *jeb, +struct jffs2_raw_xref *rr,uint32_t ofs); +#endif You don't need the function definitions if you change the order inside the file.
OK, I'll change the deployment of above functions.
Quoted 37 lines
Quoted 37 lines
fs/jffs2/scan.c +30
-1#define BLK_STATE_ALLFF 0#define BLK_STATE_CLEAN 1@@ -552,7 +558,40 @@ scan_more:if (err)return err; ofs +=PAD (je32_to_cpu (node->totlen));break ; - +#ifdef CONFIG_JFFS2_XATTR +case JFFS2_NODETYPE_XATTR : +if (buf_ofs + buf_len < ofs +je32_to_cpu (node->totlen)) { + buf_len =min_t (uint32_t, buf_size, jeb->offset + c->sector_size - ofs); +D1 (printk (KERN_DEBUG "Fewer than %d bytes (xattr node) left to end of buf." +" Reading 0x%x at 0x%08x\n" ,je32_to_cpu (node->totlen), buf_len, ofs)); + err =jffs2_fill_scan_buf (c, buf, ofs, buf_len); +if (err) +return err; + buf_ofs = ofs; + node = (void *)buf; + } + err =jffs2_scan_xattr_node (c, jeb, (void *)node, ofs); +if (err) +return err; + ofs +=PAD (je32_to_cpu (node->totlen)); +break ; +case JFFS2_NODETYPE_XREF : +if (buf_ofs + buf_len < ofs +je32_to_cpu (node->totlen)) { + buf_len =min_t (uint32_t, buf_size, jeb->offset + c->sector_size - ofs); +D1 (printk (KERN_DEBUG "Fewer than %d bytes (xref node) left to end of buf." +" Reading 0x%x at 0x%08x\n" ,je32_to_cpu (node->totlen), buf_len, ofs)); + err =jffs2_fill_scan_buf (c, buf, ofs, buf_len); +if (err) +return err; + buf_ofs = ofs; + node = (void *)buf; + } + err =jffs2_scan_xref_node (c, jeb, (void *)node, ofs); +if (err)
Quoted 8 lines
fs/jffs2/scan.c scan_more: · line 594
Quoted 4 lines
fs/jffs2/scan.c +4
-0+return err; + ofs +=PAD (je32_to_cpu (node->totlen)); +break ; +#endif By itself, this code is not too bad. But it add a little more crap to a function that is aching for a rewrite already. Not sure.
Hmm,,, I wrote the above part of codes with referring to existing code. If the policy is shown, I'll follow it. How should I do ?
Quoted 19 lines
Quoted 19 lines
fs/jffs2/scan.c +15
-0@@ -820,6 +860,190 @@ static int jffs2_scan_dirent_node(structreturn 0 ; } +#ifdef CONFIG_JFFS2_XATTR +static int jffs2_scan_xattr_node (struct jffs2_sb_info *c,struct jffs2_eraseblock *jeb, +struct jffs2_raw_xattr *rx,uint32_t ofs) +{ +struct jffs2_raw_node_ref *raw; +struct jffs2_xattr_cache *xc; +uint32_t crc; +int xtype, nlen, vlen; + + crc =crc32 (0 , rx,sizeof (*rx)-8 ); +if (crc !=je32_to_cpu (rx->node_crc)) { +printk (KERN_NOTICE "jffs2_scan_xattr_node(): Node CRC failed" +" on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n" , + ofs,je32_to_cpu (rx->node_crc), crc); +DIRTY_SPACE (PAD (je32_to_cpu (rx->totlen)));
Quoted 8 lines
fs/jffs2/scan.c static int jffs2_scan_dirent_node(struct · line 882
Quoted 5 lines
fs/jffs2/scan.c +5
-0+return 0 ; + } + + nlen =JFFS2_XATTR_NAMELEN (je32_to_cpu (rx->length)); + vlen =JFFS2_XATTR_VALUELEN (je32_to_cpu (rx->length));Types don't match. nlen and vlen should become u32.
Is it enought for "int"? JFFS2_XATTR_NAMELEN has 12-bit length, and JFFS2_XATTR_VALUELEN has 20-bit length.
Quoted 2 lines
Btw, I agree with Linus. u32 is _much_ nicer than
uint32_t, not to speak of theuint32_fast_tinsanity.
Is is necessary to correct the part where other uint32_t used.
Quoted 19 lines
Quoted 19 lines
fs/jffs2/scan.c +19
-0+if (je32_to_cpu (rx->totlen) !=sizeof (*rx)+PAD (nlen+1 )+PAD (vlen)) { +printk (KERN_NOTICE "jffs2_scan_xattr_node(): length mimatch!" +" totlen=%d length=0x%08x nlen=%d vlen=%d on 0x%08x\n" , +je32_to_cpu (rx->totlen),je32_to_cpu (rx->length), nlen, vlen, ofs); +DIRTY_SPACE (PAD (je32_to_cpu (rx->totlen))); +return 0 ; + } + + crc =crc32 (0 , rx->data,PAD (nlen+1 )+PAD (vlen)); +if (crc !=je32_to_cpu (rx->data_crc)) { +printk (KERN_NOTICE "jffs2_scan_xattr_node(): Data CRC failed" +" on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n" , + ofs,je32_to_cpu (rx->data_crc), crc); +DIRTY_SPACE (PAD (je32_to_cpu (rx->totlen))); +return 0 ; + } + + xc =jffs2_find_xattr_cache_xid (c,je32_to_cpu (rx->xid)); +if (xc) {
Quoted 8 lines
fs/jffs2/scan.c static int jffs2_scan_dirent_node(struct · line 906
Quoted 5 lines
fs/jffs2/scan.c +5
-0+printk (KERN_NOTICE "jffs2_scan_xattr_node(): Duplicate XID Found" +" on node at 0x%08x XID=%d Later one ignored\n" , ofs, xc->xid); +DIRTY_SPACE (PAD (je32_to_cpu (rx->totlen))); +return 0 ; + }How do you deal with xattr reference counting and lifetime?
When xc->xlist is empty, jffs2_xattr_cache type object will be released. jffs2_xattr_ref type object is chained to xc->xlist. list_empty(xc->xlist) means nobady refers this XATTR.
Quoted 10 lines
fs/jffs2/scan.c static int jffs2_scan_dirent_node(struct · line 914
Quoted 7 lines
fs/jffs2/scan.c +7
-0+ xtype =jffs2_xattr_prefix_to_xtype (rx->data, nlen); +if (JFFS2_XATTRTYPE_INVALID ==xtype) { +printk (KERN_NOTICE "jffs2_scan_xattr_node(): Unsupported xattr type" +" on node at 0x%08x\n" , ofs); +USED_SPACE (PAD (je32_to_cpu (rx->totlen))); +return 0 ; + }Why is it required that JFFS2 knows the type of the xattr?
Hmm,,, I added this member to discriminate the prefix of xattr without strncmp(). But it might be a bit ugly design.
Quoted 8 lines
fs/jffs2/scan.c static int jffs2_scan_dirent_node(struct · line 957
Quoted 5 lines
fs/jffs2/scan.c +5
-0+static inline int jffs2_scan_xref_node_helper (struct jffs2_sb_info *c, +struct jffs2_xattr_ref *new,struct jffs2_xattr_ref *old) +{ +/* (uint32_t)new->xc == (uint32_t)old->xc has been made sure. */ +if ((uint32_t )new->ic == (uint32_t )old->ic) {Why the casts? How can this be safe on 64bit machines?
This function is called before jffs2_build_xattr_cache() while FS-mounting. In this implementation, xid (uint32 value) is stored in jffs2_xattr_ref->xc before jffs2_build_xattr_cache(), and ino (uint32 value) is stored in jffs2_xattr_ref->ic.
After calling jffs2_build_xattr_cache(), xc and ic is used as a pointer which indicate to jffs2_xattr_cache/jffs2_inode_cache.
It might be bad manner, but is the following implementation preferable ?
struct jffs2_xattr_ref {
uint32_t seqno;
struct list_head ilist;
struct list_head xlist;
union {
struct jffs2_xattr_cache *xc;
uint32_t xid;
} x;
union {
struct jffs2_inode_cache *ic;
uint32_t ino;
} i;
struct jffs2_raw_node_ref *node;
};Quoted 4 lines
fs/jffs2/scan.c static int jffs2_scan_dirent_node(struct · line 973
Quoted 4 lines
fs/jffs2/scan.c +4
-0+static int jffs2_scan_xref_node (struct jffs2_sb_info *c,struct jffs2_eraseblock *jeb, +struct jffs2_raw_xref *rr,uint32_t ofs) +{ +struct jffs2_raw_node_ref *raw;
- snip -
Quoted 9 lines
fs/jffs2/scan.c static int jffs2_scan_dirent_node(struct · line 1001
Quoted 5 lines
fs/jffs2/scan.c +5
-0+ ref->seqno =je32_to_cpu (rr->seqno); +if (ref->seqno > c->highest_seqno) + c->highest_seqno = ref->seqno; + ref->ic = (void *)je32_to_cpu (rr->ino); + ref->xc = (void *)je32_to_cpu (rr->xid);WTF?!?
Quoted 3 lines
You read a je32 from flash and use that as a pointer?!?
Please tell me I'm wrong.
If we use above emample, we can write it as follows:
ref->i.ino = je32_to_cpu(rr->ino);
ref->x.xid = je32_to_cpu(rr->xid);In jffs2_build_xattr_cache(), we find up the jffs2_inode_cache and jffs2_xattr_cache by using ino/xid as a key. Then the correct pointers are stored in ref->ic and ref->xc after jffs2_build_xattr_cache().
Is it the situation to use union ?
Thanks for attentive comments.
Signature · 2 lines
Linux Promotion Center, NEC KaiGai Kohei <[email protected]>
Quoted 7 lines · Kaigai Kohei
Thanks for reviewing in spite of so long patch.
Quoted 5 lines
Sounds good.
It appears as if your patch or something based on it will win. So let's have a look...
Quoted 6 lines
Quoted 4 lines
I notice that you make a couple of mistakes by copying them from existing jffs2 code. You are excused for that, no doubt. But I still don't want copies of old mistakes to go in, just because we have a bad example.
Is this using
uint32_t, xattr scanning code and so on ?
Yes.
Quoted 5 lines
Quoted 2 lines
Review is just partial. It's late enough already and I need to get some sleep.
Please take a rest slowly on the weekend.
I'll modify my patch during this period. ;-)
Thanks.
Quoted 11 lines
Quoted 10 lines
fs/jffs2/malloc.c struct jffs2_raw_node_ref *jffs2_alloc_r · line 198
Quoted 6 lines
struct
jffs2_full_dirent*jffs2_alloc_full_dirent(int namesize)fs/jffs2/malloc.c +1
-0@@ -169,6 +195,7 @@ struct jffs2_raw_node_ref *jffs2_alloc_rstruct jffs2_raw_node_ref *ret; ret =kmem_cache_alloc (raw_node_ref_slab,GFP_KERNEL );JFFS2_DBG_MEMALLOC ("%p\n" , ret); +memset (ret,0 ,sizeof (*ret));/* to guarantee owner==NULL */ This could be optimized a little by using the constructor/destructor stuff in slabs. Not too important.
Quoted 3 lines
I'll prepare a tiny and obvious constructor for
jffs2_raw_node_ref. NULL is set inraw->ownerby default is important, the method of setting is not so, I think.
Right. One of the least important issues I had.
Quoted 22 lines
Quoted 16 lines
fs/jffs2/malloc.c void jffs2_free_inode_cache(struct jffs2 · line 240
Quoted 10 lines
fs/jffs2/malloc.c +6
-0@@ -205,3 +232,35 @@ void jffs2_free_inode_cache(struct jffs2JFFS2_DBG_MEMALLOC ("%p\n" , x);kmem_cache_free (inode_cache_slab, x); } + +#ifdef CONFIG_JFFS2_XATTR + +struct jffs2_xattr_cache *jffs2_alloc_xattr_cache (void ) +{ +struct jffs2_xattr_cache *xc;^^^^^^The name doesn't make sense. You're referring to a single object, not the complete cache. Quite confusing.
Quoted 5 lines
fs/jffs2/malloc.c void jffs2_free_inode_cache(struct jffs2 · line 241
Quoted 1 line
fs/jffs2/malloc.c +1
-0+ xc =kmem_cache_alloc (xattr_cache_slab,GFP_KERNEL );^^^^^This is the cache. A slab is just part of the cache. So please rename the two.
Quoted 6 lines
For example, how about the following names ? "
jffs2_xattr_datum" as an alternative ofjffs2_xattr_cache. "xattr_datum_cache" as an alternative ofxattr_cache_slab.In this case, "xc" defined as
jffs2_xattr_cachestructure should be renamed to "xd" defined asjffs2_xattr_datum.
Would be fine.
Quoted 14 lines
Quoted 1 line
Quoted 1 line
diff -rpNU3
mtd-0829/fs/jffs2/nodelist.h
mtd-0829.xattr/fs/jffs2/nodelist.hQuoted 2 lines
fs/jffs2/nodelist.h
Quoted 2 lines
fs/jffs2/nodelist.h +0
-010:28:53.000000000 -0400
Quoted 9 lines
fs/jffs2/nodelist.h line 23
Quoted 5 lines
fs/jffs2/nodelist.h +1
-0@@ -20,6 +20,7 @@#include <linux/jffs2.h> #include <linux/jffs2_fs_sb.h> #include <linux/jffs2_fs_i.h> +#include <linux/jffs2_fs_x.h> I p a l n.
Quoted 5 lines
Quoted 2 lines
I prefer a longer name.
jffs2_fs_xattr.hwould be fine.jffs2_xattr.hwould also, the "_fs" is more redundant that "attr".OK, I'll rename "
jffs2_fs_x.h" to "jffs2_xattr.h" and deploy it under "fs/jffs2" as David says.
Can you rename it to xattr.h instead? The prefix has lost its meaning in fs/jffs2/.
Quoted 13 lines
Quoted 4 lines
Quoted 4 lines
fs/jffs2/nodelist.h +0
-0#ifdef __ECOS#include "os-ecos.h" @@ -80,6 +81,7 @@ struct jffs2_raw_node_refstruct jffs2_raw_node_ref *next_phys;Quoted 8 lines
fs/jffs2/nodelist.h struct jffs2_raw_node_ref · line 84
Quoted 3 lines
fs/jffs2/nodelist.h +1
-0uint32_t flash_offset;uint32_t __totlen;/* This may die; use ref_totlen(c, jeb, ) below */ +void *owner;This grows a node reference from 16/24 bytes to 20/32 bytes for 32/64 bit architectures. I'm not entirely happy about that, but don't a better solution either.
Quoted 7 lines
Indeed, it's involved the growing of object size.
But we must discriminate XATTR node from other non-inode node and indicate jffs2_xattr_cache/jffs2_xattr_ref object from this. I didn't have a good idea more than this.And, I forgot to enclose the declaration of "void *owner" by #ifdef - #endif.
True.
Most likely this idea is stupid, but let me have a try anyway. You could give your xattr/xref objects an inode number - either one per object or a special one shared for all xattr/xref objects. That would open a new bag of worms, but keep the size down.
Would it be possible to work with such an approach?
Quoted 5 lines
Quoted 2 lines
By itself, this code is not too bad. But it add a little more crap to a function that is aching for a rewrite already. Not sure.
Hmm,,, I wrote the above part of codes with referring to existing code. If the policy is shown, I'll follow it. How should I do ?
In a perfect world, you should send a cleanup patch to break jffs2_scan_eraseblock() into several smaller functions. Have the xattr patch depend on the cleanup. I might still have an old patch that I could send you for inspiration.
Quoted 9 lines
Quoted 6 lines
fs/jffs2/nodelist.h struct jffs2_raw_node_ref · line 87
Quoted 3 lines
fs/jffs2/nodelist.h +3
-0+ + nlen =JFFS2_XATTR_NAMELEN (je32_to_cpu (rx->length)); + vlen =JFFS2_XATTR_VALUELEN (je32_to_cpu (rx->length));Types don't match. nlen and vlen should become u32.
Is it enought for "int"?
JFFS2_XATTR_NAMELENhas 12-bit length, andJFFS2_XATTR_VALUELENhas 20-bit length.
Makes sense. But endianness conversions between je32 and int (which can be anything from 8-64 bit signed/unsigned per c standard) should be avoided.
Quoted 4 lines
Quoted 2 lines
Btw, I agree with Linus. u32 is _much_ nicer than
uint32_t, not to speak of theuint32_fast_tinsanity.Is is necessary to correct the part where other
uint32_tused.
Not really. Without the above ("should become u32") I wouldn't even have mentioned it. Really minor.
Quoted 13 lines
Quoted 3 lines
fs/jffs2/nodelist.h struct jffs2_raw_node_ref
Quoted 3 lines
fs/jffs2/nodelist.h +3
-0+ xc =jffs2_find_xattr_cache_xid (c,je32_to_cpu (rx->xid)); + if (xc) { + printk(KERN_NOTICE "jffs2_scan_xattr_node(): Duplicate XIDFound"
Quoted 1 line
fs/jffs2/nodelist.h
Quoted 1 line
fs/jffs2/nodelist.h +1
-0+ " on node at 0x%08x XID=%d Later one ignored\n", ofs,
xc->xid);Quoted 6 lines
fs/jffs2/nodelist.h
Quoted 3 lines
fs/jffs2/nodelist.h +3
-0+DIRTY_SPACE (PAD (je32_to_cpu (rx->totlen))); +return 0 ; + }How do you deal with xattr reference counting and lifetime?
Quoted 3 lines
When
xc->xlistis empty,jffs2_xattr_cachetype object will be released.jffs2_xattr_reftype object is chained toxc->xlist.list_empty(xc->xlist)means nobady refers this XATTR.
...at which time you also remove the xattr from medium, I assume. Ok.
Next question: How do you remove the xattr from medium? How is it garbage collected?
Quoted 12 lines
Quoted 3 lines
fs/jffs2/nodelist.h
Quoted 3 lines
fs/jffs2/nodelist.h +3
-0+ xtype =jffs2_xattr_prefix_to_xtype (rx->data, nlen); + if (JFFS2_XATTRTYPE_INVALID==xtype) { + printk(KERN_NOTICE "jffs2_scan_xattr_node(): Unsupportedxattr type"
Quoted 7 lines
fs/jffs2/nodelist.h
Quoted 4 lines
fs/jffs2/nodelist.h +4
-0+ " on node at 0x%08x\n", ofs); +USED_SPACE (PAD (je32_to_cpu (rx->totlen))); +return 0 ; + }Why is it required that JFFS2 knows the type of the xattr?
Quoted 2 lines
Hmm,,, I added this member to discriminate the prefix of xattr without
strncmp(). But it might be a bit ugly design.
Then why is it required that JFFS2 knows the prefix?
Quoted 10 lines
Quoted 2 lines
fs/jffs2/nodelist.h
Quoted 2 lines
fs/jffs2/nodelist.h +2
-0+static inline int jffs2_scan_xref_node_helper (struct jffs2_sb_info *c, + struct jffs2_xattr_ref *new, struct jffs2_xattr_ref*old)
Quoted 6 lines
fs/jffs2/nodelist.h
Quoted 3 lines
fs/jffs2/nodelist.h +3
-0+{ +/* (uint32_t)new->xc == (uint32_t)old->xc has been made sure. */ +if ((uint32_t )new->ic == (uint32_t )old->ic) {Why the casts? How can this be safe on 64bit machines?
Quoted 7 lines
This function is called before
jffs2_build_xattr_cache()while FS-mounting. In this implementation, xid (uint32 value) is stored injffs2_xattr_ref->xcbeforejffs2_build_xattr_cache(), and ino (uint32 value) is stored injffs2_xattr_ref->ic.After calling
jffs2_build_xattr_cache(), xc and ic is used as a pointer which indicate to jffs2_xattr_cache/jffs2_inode_cache.
Ok.
Quoted 1 line
It might be bad manner, but is the following implementation preferable ?
Yes. And you can use unnamed unions, just remove the "x" and "i".
Quoted 33 lines
struct jffs2_xattr_ref { uint32_t seqno; struct list_head ilist; struct list_head xlist; union { struct jffs2_xattr_cache *xc; uint32_t xid; } x; union { struct jffs2_inode_cache *ic; uint32_t ino; } i; struct jffs2_raw_node_ref *node; };Quoted 1 line
Quoted 1 line
+static int jffs2_scan_xref_node(struct
jffs2_sb_info*c, struct
jffs2_eraseblock*jeb,Quoted 3 lines
fs/jffs2/nodelist.h
Quoted 3 lines
fs/jffs2/nodelist.h +3
-0+ struct jffs2_raw_xref *rr, uint32_t ofs) +{ +struct jffs2_raw_node_ref *raw;- snip -
Quoted 9 lines
fs/jffs2/nodelist.h
Quoted 5 lines
fs/jffs2/nodelist.h +5
-0+ ref->seqno =je32_to_cpu (rr->seqno); +if (ref->seqno > c->highest_seqno) + c->highest_seqno = ref->seqno; + ref->ic = (void *)je32_to_cpu (rr->ino); + ref->xc = (void *)je32_to_cpu (rr->xid);WTF?!?
Quoted 8 lines
Quoted 3 lines
You read a je32 from flash and use that as a pointer?!?
Please tell me I'm wrong.
If we use above emample, we can write it as follows:
ref->i.ino = je32_to_cpu(rr->ino); ref->x.xid = je32_to_cpu(rr->xid);
ret->ino = je32_to_cpu(rr->ino); ...
Quoted 5 lines
In
jffs2_build_xattr_cache(), we find up thejffs2_inode_cacheandjffs2_xattr_cacheby using ino/xid as a key. Then the correct pointers are stored inref->icandref->xcafterjffs2_build_xattr_cache().Is it the situation to use union ?
Yes. Makes more sense now. Sorry about the tone.
Still, you can take it as an indication that your reuse-old-fields trick is not obvious to new readers. A comment explaining this would be useful. Maybe you already have it further down, in the part I didn't review yet.
Good stuff.
Jörn
Signature · 2 lines
All art is but imitation of nature. -- Lucius Annaeus Seneca
Hi,
Quoted 11 lines
Quoted 7 lines
Quoted 4 lines
I p a l n.
I prefer a longer name.
jffs2_fs_xattr.hwould be fine.jffs2_xattr.hwould also, the "_fs" is more redundant that "attr".OK, I'll rename "
jffs2_fs_x.h" to "jffs2_xattr.h" and deploy it under "fs/jffs2" as David says.Can you rename it to
xattr.hinstead? The prefix has lost its meaning infs/jffs2/.
Indeed, jffs2_XXX.h under fs/jffs2 is a bit redundant.
Quoted 22 lines
Quoted 13 lines
Quoted 4 lines
Quoted 4 lines
#ifdef
__ECOS
#include "os-ecos.h"fs/jffs2/nodelist.h +0
-0@@ -80,6 +81,7 @@ struct jffs2_raw_node_refstruct jffs2_raw_node_ref *next_phys;Quoted 8 lines
fs/jffs2/nodelist.h struct jffs2_raw_node_ref · line 84
Quoted 3 lines
fs/jffs2/nodelist.h +1
-0uint32_t flash_offset;uint32_t __totlen;/* This may die; use ref_totlen(c, jeb, ) below */ +void *owner;This grows a node reference from 16/24 bytes to 20/32 bytes for 32/64 bit architectures. I'm not entirely happy about that, but don't a better solution either.
Quoted 7 lines
Indeed, it's involved the growing of object size.
But we must discriminate XATTR node from other non-inode node and indicate jffs2_xattr_cache/jffs2_xattr_ref object from this. I didn't have a good idea more than this.And, I forgot to enclose the declaration of "void *owner" by #ifdef - #endif.
Quoted 8 lines
True.
Most likely this idea is stupid, but let me have a try anyway. You could give your xattr/xref objects an inode number - either one per object or a special one shared for all xattr/xref objects. That would open a new bag of worms, but keep the size down.
Would it be possible to work with such an approach?
It accompanies a so big remodeling, and hope not to do so, if possible.
I think it is important here to be able to distinguish three kinds of raw_node by a reasonable method (1. existing raw_node_ref of inode,
2. existing raw_node_ref without inode, 3. new raw_node_ref for XATTR), and to be able to refer from the third type of raw_node to the jffs2_xattr_(cache|ref) objects.
I noticed an idea to resolve it.
Any objects refered by the last next_in_ino are allocated by slab. If we can use kmem_ptr_validate() function, we can discriminate whether this pointer indicate xattr_cache/ref or not. Then, we can keep the size of jffs2_raw_node_ref.
(the member of 'owner' will go anyware.)
The issues of this method are as follows:
- If there is an adverse effect by existing of non-inode raw_node_ref whose next_in_ino is not NULL, I must resolve this.
- It's necessary to discuss in LKML, since this function is not EXPORT_SYMBOL()ed for kernel loadable modules currently.
Quoted 11 lines
Quoted 5 lines
Quoted 2 lines
By itself, this code is not too bad. But it add a little more crap to a function that is aching for a rewrite already. Not sure.
Hmm,,, I wrote the above part of codes with referring to existing code. If the policy is shown, I'll follow it. How should I do ?
In a perfect world, you should send a cleanup patch to break
jffs2_scan_eraseblock()into several smaller functions. Have the xattr patch depend on the cleanup. I might still have an old patch that I could send you for inspiration.
I have developed this functionality based on mtd-snapshot-20050829. It means I should develop this based on mtd-snapshot-XXXX + your cleanup patches, isn't it?
If so, I think my patch should be moditied for new version. Isn't it fundamental changing ?
Quoted 17 lines
Quoted 17 lines
Quoted 3 lines
fs/jffs2/scan.c static int jffs2_scan_dirent_node(struct
Quoted 3 lines
fs/jffs2/scan.c +3
-0+ xc =jffs2_find_xattr_cache_xid (c,je32_to_cpu (rx->xid)); + if (xc) { + printk(KERN_NOTICE "jffs2_scan_xattr_node(): Duplicate XIDFound"
Quoted 1 line
Review struct jffs2_raw_node_ref
Quoted 1 line
(quoted diff) +1
-0+ " on node at 0x%08x XID=%d Later one ignored\n", ofs,
xc->xid);Quoted 6 lines
fs/jffs2/scan.c static int jffs2_scan_dirent_node(struct · line 879
Quoted 3 lines
fs/jffs2/scan.c +3
-0+DIRTY_SPACE (PAD (je32_to_cpu (rx->totlen))); +return 0 ; + }How do you deal with xattr reference counting and lifetime?
Quoted 6 lines
Quoted 3 lines
When
xc->xlistis empty,jffs2_xattr_cachetype object will be released.jffs2_xattr_reftype object is chained toxc->xlist.list_empty(xc->xlist)means nobady refers this XATTR.....at which time you also remove the xattr from medium, I assume. Ok.
Yes. jffs2_mark_node_obsolete() is called at this timing.
Quoted 2 lines
Next question: How do you remove the xattr from medium? How is it garbage collected?
If my understanding is not wrong, an obsolete XATTR or XREF node is garbase collected as raw-node which does not have inode. (Becase next_in_ino of XATTR/XREF node is NULL.)
Quoted 14 lines
Quoted 14 lines
Quoted 3 lines
fs/jffs2/scan.c static int jffs2_scan_dirent_node(struct
Quoted 3 lines
fs/jffs2/scan.c +3
-0+ xtype =jffs2_xattr_prefix_to_xtype (rx->data, nlen); + if (JFFS2_XATTRTYPE_INVALID==xtype) { + printk(KERN_NOTICE "jffs2_scan_xattr_node(): Unsupportedxattr type"
Quoted 7 lines
fs/jffs2/scan.c static int jffs2_scan_dirent_node(struct · line 914
Quoted 4 lines
fs/jffs2/scan.c +4
-0+ " on node at 0x%08x\n", ofs); +USED_SPACE (PAD (je32_to_cpu (rx->totlen))); +return 0 ; + }Why is it required that JFFS2 knows the type of the xattr?
Quoted 5 lines
Quoted 2 lines
Hmm,,, I added this member to discriminate the prefix of xattr without
strncmp(). But it might be a bit ugly design.Then why is it required that JFFS2 knows the prefix?
A permittion checking policy depends on XATTR's prefix. For example, only an user has CAP_SYS_ADMIN capability can read/write "trusted.*" xattr. In the "security.*" prefix case, this checking was done in LSM module. Therefore, filesystem must know XATTR's prefix.
Quoted 41 lines
Quoted 20 lines
Quoted 1 line
Quoted 1 line
+static int jffs2_scan_xref_node(struct
jffs2_sb_info*c, struct
jffs2_eraseblock*jeb,Quoted 3 lines
fs/jffs2/scan.c static int jffs2_scan_dirent_node(struct · line 973
Quoted 3 lines
fs/jffs2/scan.c +3
-0+ struct jffs2_raw_xref *rr, uint32_t ofs) +{ +struct jffs2_raw_node_ref *raw;- snip -
Quoted 9 lines
fs/jffs2/scan.c static int jffs2_scan_dirent_node(struct · line 1001
Quoted 5 lines
fs/jffs2/scan.c +5
-0+ ref->seqno =je32_to_cpu (rr->seqno); +if (ref->seqno > c->highest_seqno) + c->highest_seqno = ref->seqno; + ref->ic = (void *)je32_to_cpu (rr->ino); + ref->xc = (void *)je32_to_cpu (rr->xid);WTF?!?
Quoted 8 lines
Quoted 3 lines
You read a je32 from flash and use that as a pointer?!?
Please tell me I'm wrong.
If we use above emample, we can write it as follows:
ref->i.ino = je32_to_cpu(rr->ino); ref->x.xid = je32_to_cpu(rr->xid);ret->ino = je32_to_cpu(rr->ino); ...Quoted 5 lines
In
jffs2_build_xattr_cache(), we find up thejffs2_inode_cacheandjffs2_xattr_cacheby using ino/xid as a key. Then the correct pointers are stored inref->icandref->xcafterjffs2_build_xattr_cache().Is it the situation to use union ?
Quoted 6 lines
Yes. Makes more sense now. Sorry about the tone.
Still, you can take it as an indication that your reuse-old-fields trick is not obvious to new readers. A comment explaining this would be useful. Maybe you already have it further down, in the part I didn't review yet.
Sorry for tricky coding without comments. I'll pay attention of such coding style.
Thanks,
Signature · 1 line
KaiGai Kohei <[email protected]>
Quoted 8 lines · KaiGai Kohei
Quoted 7 lines
Most likely this idea is stupid, but let me have a try anyway. You could give your xattr/xref objects an inode number - either one per object or a special one shared for all xattr/xref objects. That would open a new bag of worms, but keep the size down.
Would it be possible to work with such an approach?
Quoted 7 lines
It accompanies a so big remodeling, and hope not to do so, if possible.
I think it is important here to be able to distinguish three kinds of
raw_nodeby a reasonable method (1. existingraw_node_refof inode,
2. existingraw_node_refwithout inode, 3. newraw_node_reffor XATTR), and to be able to refer from the third type ofraw_nodeto thejffs2_xattr_(cache|ref)objects.
Yes. 1 and 2 are currently distinguished by next_in_ino being either either valid or NULL.
Quoted 6 lines
I noticed an idea to resolve it.
Any objects refered by the lastnext_in_inoare allocated by slab. If we can usekmem_ptr_validate()function, we can discriminate whether this pointer indicate xattr_cache/ref or not. Then, we can keep the size ofjffs2_raw_node_ref.
(the member of 'owner' will go anyware.)
Sounds scary. But in principle, you are right. In case of either 1 or 3, we attach "something" to next_in_ino. Now we only have to decide whether "something" is an inode, or the new xattr-struff.
If you add an extra field to jffs2_inode_cache (which also is grossly misnamed, old mistake), you can do so. And since inodes are a lot less frequent than raw nodes, the memory consumption should have improved quite a bit.
Or you could play some magic like reserving ino 0xffffffff for xattr_object, 0xfffffffe for xattr_ref, etc. and simply decide by jffs2_inode_cache->ino having one of the magic numbers. Then you would need the extra field only for xattr_obj or xattr_ref.
Quoted 3 lines
The issues of this method are as follows:
- If there is an adverse effect by existing of non-inoderaw_node_refwhosenext_in_inois not NULL, I must resolve this.
Yep.
Quoted 2 lines
- It's necessary to discuss in LKML, since this function is not EXPORT_SYMBOL()ed for kernel loadable modules currently.
Where it won't receive a lot of love. Do it with some variant of what I outlined above.
Quoted 7 lines
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines
By itself, this code is not too bad. But it add a little more crap to a function that is aching for a rewrite already. Not sure.
Hmm,,, I wrote the above part of codes with referring to existing code. If the policy is shown, I'll follow it. How should I do ?
Quoted 8 lines
Quoted 4 lines
In a perfect world, you should send a cleanup patch to break
jffs2_scan_eraseblock()into several smaller functions. Have the xattr patch depend on the cleanup. I might still have an old patch that I could send you for inspiration.I have developed this functionality based on mtd-snapshot-20050829. It means I should develop this based on mtd-snapshot-XXXX + your cleanup patches, isn't it?
No. You should develop two patches based on current cvs:
[PATCH 1/2] Cleanup of jffs2_scan_eraseblock() [PATCH 2/2] xattr for jffs2
And you may or may not use my previous attempt as a basis, that's your decision.
If you simply added further mess to jffs2_scan_eraseblock(), as you do today, people will see horrible code become even worse. Who likes that?
If instead you do a cleanup first, people will see that you helped make the function much more readable and maintainable. Anyone objecting your merge will have a tough time arguing now.
Quoted 6 lines
Quoted 2 lines
Next question: How do you remove the xattr from medium? How is it garbage collected?
If my understanding is not wrong, an obsolete XATTR or XREF node is garbase collected as raw-node which does not have inode. (Becase
next_in_inoof XATTR/XREF node is NULL.)
Ah, yes. Makes sense now, even to stupid people like me.
Quoted 7 lines
Quoted 1 line
Then why is it required that JFFS2 knows the prefix?
A permittion checking policy depends on XATTR's prefix. For example, only an user has
CAP_SYS_ADMINcapability can read/write "trusted.*" xattr. In the "security.*" prefix case, this checking was done in LSM module. Therefore, filesystem must know XATTR's prefix.
This is just wrong. I agree that something inside the kernel must know whether users need specific capabilities to read/write the xattr. Sure. But why in hell does it have to be JFFS2?
How do other filesystems deal with this? ext[23] and reiserfs (v3) all have xattr, I believe.
Quoted 7 lines
Quoted 4 lines
Still, you can take it as an indication that your reuse-old-fields trick is not obvious to new readers. A comment explaining this would be useful. Maybe you already have it further down, in the part I didn't review yet.
Sorry for tricky coding without comments. I'll pay attention of such coding style.
Thanks. This is one of the reasons for reviews. You, being the author, have a bad judgement about what people new to the code can and cannot easily understand. You're not new to the code. ;)
Jörn
Signature · 3 lines
Measure. Don't tune for speed until you've measured, and even then don't unless one part of the code overwhelms the rest. -- Rob Pike
Hi,
Quoted 21 lines
Quoted 7 lines
It accompanies a so big remodeling, and hope not to do so, if possible.
I think it is important here to be able to distinguish three kinds of
raw_nodeby a reasonable method (1. existingraw_node_refof inode,
2. existingraw_node_refwithout inode, 3. newraw_node_reffor XATTR), and to be able to refer from the third type ofraw_nodeto thejffs2_xattr_(cache|ref)objects.Yes. 1 and 2 are currently distinguished by
next_in_inobeing either either valid or NULL.Quoted 6 lines
I noticed an idea to resolve it.
Any objects refered by the lastnext_in_inoare allocated by slab. If we can usekmem_ptr_validate()function, we can discriminate whether this pointer indicate xattr_cache/ref or not. Then, we can keep the size ofjffs2_raw_node_ref.
(the member of 'owner' will go anyware.)
Quoted 8 lines
Sounds scary. But in principle, you are right. In case of either 1 or 3, we attach "something" to
next_in_ino. Now we only have to decide whether "something" is an inode, or the new xattr-struff.If you add an extra field to
jffs2_inode_cache(which also is grossly misnamed, old mistake), you can do so. And since inodes are a lot less frequent than raw nodes, the memory consumption should have improved quite a bit.
I prefer this kind of approach than other one. It's simple solution. I'm afraid of breaking something to be assumed implicitly by reserving some inode-numbers.
And, how about such an idea ?
Currently, the variable of 'state' in jffs2_inode_cache is defined as int type, but the range of this variable is between 0 and 6. In general case, 'int' has 32-bit width. It's so much for this field.
For example, we can redefine the 'state' as 16-bit width variable, and insert a new 16-bit width variable to discriminate own object. If acceptable, it can also keep the memory comsumption for jffs2_inode_cache.
In this plan, jffs2_inode_cahce and jffs2_xattr_datum will be defined as follows:
struct jffs2_inode_cache {
struct jffs2_full_dirent *scan_dents;
uint16_t class; /* =0 means jffs2_inode_cache */
uint16_t state;
:struct jffs2_xattr_datum {
void *dummy; /* always NULL */
uint16_t class; /* =1 means jffs2_xattr_datum */
:Quoted 10 lines
Quoted 8 lines
Quoted 4 lines
In a perfect world, you should send a cleanup patch to break
jffs2_scan_eraseblock()into several smaller functions. Have the xattr patch depend on the cleanup. I might still have an old patch that I could send you for inspiration.I have developed this functionality based on mtd-snapshot-20050829. It means I should develop this based on mtd-snapshot-XXXX + your cleanup patches, isn't it?
Quoted 6 lines
No. You should develop two patches based on current cvs:
[PATCH 1/2] Cleanup ofjffs2_scan_eraseblock()[PATCH 2/2] xattr for jffs2And you may or may not use my previous attempt as a basis, that's your decision.
I see, jffs2_scan_eraseblock() is indeed a bit long. Please send your attempt patches at first. I'll try to cleanup it for the basis of XATTR patch.
Quoted 9 lines
Quoted 7 lines
Quoted 1 line
Then why is it required that JFFS2 knows the prefix?
A permittion checking policy depends on XATTR's prefix. For example, only an user has
CAP_SYS_ADMINcapability can read/write "trusted.*" xattr. In the "security.*" prefix case, this checking was done in LSM module. Therefore, filesystem must know XATTR's prefix.
Quoted 6 lines
This is just wrong. I agree that something inside the kernel must know whether users need specific capabilities to read/write the xattr. Sure. But why in hell does it have to be JFFS2?
How do other filesystems deal with this? ext[23] and reiserfs (v3) all have xattr, I believe.
Indeed, more upper layer might be able to manage this kind of decision making as you say. But it's transferred to the filesystem currently. All of them (ext2/3, reiser and so on) have own permission checking codes like 'fs/ext2/xattr_trusted.c', and I imitated those implementations. I don't know the reason correctly.
Thanks,
Signature · 2 lines
Linux Promotion Center, NEC KaiGai Kohei <[email protected]>
Quoted 19 lines · Kaigai Kohei
Quoted 9 lines
Sounds scary. But in principle, you are right. In case of either 1 or 3, we attach "something" to
next_in_ino. Now we only have to decide whether "something" is an inode, or the new xattr-struff.If you add an extra field to
jffs2_inode_cache(which also is grossly misnamed, old mistake), you can do so. And since inodes are a lot less frequent than raw nodes, the memory consumption should have improved quite a bit.I prefer this kind of approach than other one. It's simple solution. I'm afraid of breaking something to be assumed implicitly by reserving some inode-numbers.
And, how about such an idea ?
Currently, the variable of 'state' injffs2_inode_cacheis defined as int type, but the range of this variable is between 0 and 6. In general case, 'int' has 32-bit width. It's so much for this field.
Quoted 4 lines
For example, we can redefine the 'state' as 16-bit width variable, and insert a new 16-bit width variable to discriminate own object. If acceptable, it can also keep the memory comsumption for
jffs2_inode_cache.
Yes, that sounds fine.
Quoted 8 lines
In this plan,
jffs2_inode_cahceandjffs2_xattr_datumwill be defined as follows:struct jffs2_inode_cache { struct jffs2_full_dirent *scan_dents; uint16_t class; /* =0 means jffs2_inode_cache */ uint16_t state; :
Quoted 4 lines
struct jffs2_xattr_datum {
void *dummy; /* always NULL */
uint16_t class; /* =1 means jffs2_xattr_datum */
:You could even make the class a u8. For inodes, the remaining 8 bits would just be reserved space for proper alignment. If either of your xattr object could make use of the extra byte, it would be worth it. If not, just ignore my silly idea.
Quoted 3 lines
I see,
jffs2_scan_eraseblock()is indeed a bit long. Please send your attempt patches at first. I'll try to cleanup it for the basis of XATTR patch.
It was 34 patches going over all of jffs2, actually. I guess it's easier to send the changed scan.c. The pseudo-random stuff was controversial, so I lost interest after a while.
Quoted 4 lines
Quoted 4 lines
This is just wrong. I agree that something inside the kernel must know whether users need specific capabilities to read/write the xattr. Sure. But why in hell does it have to be JFFS2?
Quoted 8 lines
Quoted 2 lines
How do other filesystems deal with this? ext[23] and reiserfs (v3) all have xattr, I believe.
Indeed, more upper layer might be able to manage this kind of decision making as you say. But it's transferred to the filesystem currently. All of them (ext2/3, reiser and so on) have own permission checking codes like '
fs/ext2/xattr_trusted.c', and I imitated those implementations. I don't know the reason correctly.
The code is not exactly easy to follow. But it appears as if they used that stuff for compression. If prefix is "trusted.", just use an e_name_index of 4 and drop the prefix. It can be reconstructed on reads.
Reiserfs doesn't worry about compression and has should-be-generic code only.
I guess it would make sense to copy the compression stuff from ext2, at least the concept.
Jörn
Signature · 2 lines
Don't patch bad code, rewrite it. -- Kernigham and Pike, according to Rusty
Hi,
Quoted 13 lines
Quoted 11 lines
In this plan,
jffs2_inode_cahceandjffs2_xattr_datumwill be defined as follows:struct jffs2_inode_cache { struct jffs2_full_dirent *scan_dents; uint16_t class; /* =0 means jffs2_inode_cache */ uint16_t state; :struct jffs2_xattr_datum { void *dummy; /* always NULL */ uint16_t class; /* =1 means jffs2_xattr_datum */ :
Quoted 4 lines
You could even make the class a u8. For inodes, the remaining 8 bits would just be reserved space for proper alignment. If either of your xattr object could make use of the extra byte, it would be worth it. If not, just ignore my silly idea.
u8 type variable has enough width for discernment, I think.
And, is it possible to name the remaining 8-bit 'flags' than 'reserved' or 'unused' in jffs2_inode_cache/jffs2_xattr_datum ?
In my implementation, 'uint8_t ilist_checked' is added in jffs2_inode_cache for flag purpose, and 'uint16_t flags' exists in jffs2_xattr_datum(jffs2_xattr_cache in old name). If we can stuff those into the remaining 8-bit, each object size will be reduced by 4-byte, I think.
Quoted 8 lines
Quoted 3 lines
I see,
jffs2_scan_eraseblock()is indeed a bit long. Please send your attempt patches at first. I'll try to cleanup it for the basis of XATTR patch.It was 34 patches going over all of jffs2, actually. I guess it's easier to send the changed
scan.c. The pseudo-random stuff was controversial, so I lost interest after a while.
'34 patches over all of jffs2' is over my expectation, orz. I prefer to pay attention on only the changed scan.c, if possible... Please send it to me,
Quoted 14 lines
Quoted 4 lines
Quoted 4 lines
This is just wrong. I agree that something inside the kernel must know whether users need specific capabilities to read/write the xattr. Sure. But why in hell does it have to be JFFS2?
Quoted 8 lines
Quoted 2 lines
How do other filesystems deal with this? ext[23] and reiserfs (v3) all have xattr, I believe.
Indeed, more upper layer might be able to manage this kind of decision making as you say. But it's transferred to the filesystem currently. All of them (ext2/3, reiser and so on) have own permission checking codes like '
fs/ext2/xattr_trusted.c', and I imitated those implementations. I don't know the reason correctly.
Quoted 4 lines
The code is not exactly easy to follow. But it appears as if they used that stuff for compression. If prefix is "trusted.", just use an
e_name_indexof 4 and drop the prefix. It can be reconstructed on reads.
Hmm, it's functionality certainly effective for reduction of memory and medium usage. It's not difficult to implement, I think. I'll modify the method of storing xattr in next.
Thanks,
Signature · 2 lines
Linux Promotion Center, NEC KaiGai Kohei <[email protected]>
Hi,
I revised the previous xattr patch in jffs2 based on some suggestions.
[1] scanning xattr related node for cleaned-up scan.c. (jffs2_xattr_scan.c-cleanup.patch)
[2] enables xattr support in jffs2.
(jffs2_xattr_take-3.patch)
(*) We can apply jffs2_xattr_take-3.patch for current CVS independently.
The following points are updated.
- jffs2_scan_xattr_node() and jffs2_scan_xref_node() are implemented with considering the cleaned-up scan.c. (jffs2_xattr_scan.c-cleanup.patch) Since I can't build the cleaned-up source, this patch has not been verified yet. But same code is included in jffs2_xattr_take-3.patch, and it works correctly.
- A deadlock problem was detected in take-2 patch.
Thus, the order of acquiring semaphore was changed.
There was down_write(&c->xattr_sem) under down(&c->alloc_sem) in take-2 patch. Now, I avoid such an implementation. In do_jffs2_setxattr(), xattr_sem is acquired after alloc_sem is done.
- "include/linux/jffs2_fs_x.h" was moved to "fs/jffs2/xattr.h".
- 'void *owner' in struct jffs2_raw_node_ref was removed.
- 'int state' in struct jffs2_inode_cache was removed, and 'u8 class' and 'u8 flags', 'uint16_t state' were added on instead.
GC uses raw->next_in_ino for reverse-reference to xattr_datum/xattr_ref from jffs_raw_node_ref.
- the declaration of jffs2_xattr_ref was changed. The strange cast was removed, and the variables not-used concurrently are defined as union type. ('uint32_t xid' and 'struct jffs2_xattr_datum *xd' are not used concurrently. 'uint32_t ino' and 'struct jffs2_inode_cache *ic' are not used concurrently.)
- A xattr prefixes like 'security.' are represented by 8bit code, and omit it from name-strings.
- jffs2_xattr_datum->xlist was removed, and 'uint32_t refcnt' was added. Scanning inodes which share the same xattr_datum is not used. Thus, this list is not necessary and enough in reference counter.
- some functions/variables/structures are renamed. struct jffs2_xattr_cache -> struct jffs2_xattr_datum
kmem_cache_t *xattr_cache_slab -> xattr_datum_cache kmem_cache_t *xattr_ref_slab -> xattr_ref_cache
jffs2_init_xattr_caches() -> jffs2_init_xattr_subsystem() jffs2_build_xattr_caches() -> jffs2_build_xattr_subsystem() jffs2_clear_xattr_caches() -> jffs2_clear_xattr_subsystem()
,,,and so on.
The remaining work is as follows:
- Additional revising besed on any comments.
- Test & Stabilization.
- The implementation for POSIX ACL support.
- The implementation for XATTR support in mkfs.jffs2.
Thanks,
Signature · 2 lines
Linux Promotion Center, NEC KaiGai Kohei <[email protected]>
fs/Kconfig +17 -0
@@ -64,6 +64,23 @@ config JFFS2_FS_WRITEBUFFER - NOR flash with transparent ECC - DataFlash +config JFFS2_XATTR + bool "JFFS2 XATTR support (EXPERIMENTAL)" + depends on JFFS2_FS && EXPERIMENTAL + default n + help + This enables the Extended Attributes(XATTR) support in JFFS2. + XATTR is name:value pairs associated with inodes by the kernel + or by users. + It's neccesary for persistent security context in SELinux. + + In addition, the following kinds of prefixes are supported now. + - security.* + - user.* + - trusted.* + + - system.posix_acl_{access|default} are in TODO list now. + config JFFS2_SUMMARY bool "JFFS2 summary support (EXPERIMENTAL)" depends on JFFS2_FS && EXPERIMENTAL
fs/jffs2/Makefile.common +1 -0
@@ -12,6 +12,7 @@ jffs2-y += symlink.o build.o erase.o bac jffs2-y += super.o debug.o jffs2-$(CONFIG_JFFS2_FS_WRITEBUFFER) += wbuf.o +jffs2-$(CONFIG_JFFS2_XATTR) += xattr.o jffs2-$(CONFIG_JFFS2_RUBIN) += compr_rubin.o jffs2-$(CONFIG_JFFS2_RTIME) += compr_rtime.o jffs2-$(CONFIG_JFFS2_ZLIB) += compr_zlib.o
fs/jffs2/build.c +2 -0
@@ -160,6 +160,7 @@ static int jffs2_build_filesystem(struct ic->scan_dents =NULL ;cond_resched (); } +jffs2_build_xattr_subsystem (c); c->flags &= ~JFFS2_SB_FLAG_BUILDING ;dbg_fsbuild ("FS build complete\n" );
@@ -178,6 +179,7 @@ exit:jffs2_free_full_dirent (fd); } } +jffs2_clear_xattr_subsystem (c); }return ret;
fs/jffs2/dir.c +5 -0
@@ -57,7 +57,12 @@ struct inode_operations jffs2_dir_inode_ .rmdir = jffs2_rmdir, .mknod = jffs2_mknod, .rename = jffs2_rename, + .permission = jffs2_permission, .setattr = jffs2_setattr, + .setxattr = jffs2_setxattr, + .getxattr = jffs2_getxattr, + .listxattr = jffs2_listxattr, + .removexattr = jffs2_removexattr };/***********************************************************************/
fs/jffs2/file.c +6 -1
@@ -57,7 +57,12 @@ struct file_operations jffs2_file_operatstruct inode_operations jffs2_file_inode_operations = { - .setattr = jffs2_setattr + .permission = jffs2_permission, + .setattr = jffs2_setattr, + .setxattr = jffs2_setxattr, + .getxattr = jffs2_getxattr, + .listxattr = jffs2_listxattr, + .removexattr = jffs2_removexattr }; struct address_space_operations jffs2_file_address_operations =
fs/jffs2/fs.c +7 -1
@@ -218,6 +218,7 @@ void jffs2_clear_inode (struct inode *inD1 (printk (KERN_DEBUG "jffs2_clear_inode(): ino #%lu mode %o\n" , inode->i_ino, inode->i_mode)); +jffs2_xattr_delete_inode (c, f->inocache);jffs2_do_clear_inode (c, f); }
@@ -490,9 +491,12 @@ int jffs2_do_fill_super(struct super_blo }memset (c->inocache_list,0 ,INOCACHE_HASHSIZE *sizeof (struct jffs2_inode_cache *)); -if ((ret =jffs2_do_mount_fs (c))) +if ((ret =jffs2_init_xattr_subsystem (c))) goto out_inohash; +if ((ret =jffs2_do_mount_fs (c))) + goto out_xattr; + ret = -EINVAL ;D1 (printk (KERN_DEBUG "jffs2_do_fill_super(): Getting root inode\n" ));
@@ -523,6 +527,8 @@ int jffs2_do_fill_super(struct super_blovfree (c->blocks); else kfree(c->blocks); + out_xattr: +jffs2_clear_xattr_subsystem (c); out_inohash:kfree (c->inocache_list); out_wbuf:
fs/jffs2/gc.c +10 -0
@@ -258,6 +258,16 @@ int jffs2_garbage_collect_pass(struct jf ic =jffs2_raw_ref_to_ic (raw); +/* When 'ic' refers xattr_datum/xattr_ref, this node is GCed as xattr. +We can decide whether this node is inode or xattr by ic->class. +ret = 0 : ic is xattr_datum/xattr_ref, and GC was SUCCESSED. +ret < 0 : ic is xattr_datum/xattr_ref, but GC was FAILED. +ret > 0 : ic is NOT xattr_datum/xattr_ref. +*/ + ret =jffs2_garbage_collect_xattr (c, ic); +if (ret <=0 ) + goto release_sem; +/* We need to hold the inocache. Either the erase_completion_lock or the inocache_lock are sufficient; we trade down since the inocache_lock causes less contention. */
fs/jffs2/malloc.c +60 -2
83 lines not on this page · raw message
fs/jffs2/nodelist.c +1 -0
@@ -937,6 +937,7 @@ void jffs2_free_ino_caches(struct jffs2_ this = c->inocache_list[i];while (this) { next = this->next; +jffs2_xattr_free_inode (c, this);jffs2_free_inode_cache (this); this = next; }
fs/jffs2/nodelist.h +16 -1
@@ -20,6 +20,7 @@#include <linux/jffs2.h> #include <linux/jffs2_fs_sb.h> #include <linux/jffs2_fs_i.h> +#include "xattr.h" #include "summary.h" #ifdef __ECOS
@@ -107,11 +108,16 @@ struct jffs2_inode_cache {temporary lists of dirents, and later must be set to NULL to mark the end of the raw_node_ref->next_in_ino chain. */ +u8 class;/* It's used for identification */ +u8 flags; +uint16_t state;struct jffs2_inode_cache *next;struct jffs2_raw_node_ref *nodes;uint32_t ino;int nlink; -int state; +#ifdef CONFIG_JFFS2_XATTR +struct list_head ilist; +#endif };/* Inode states for 'state' above. We need the 'GC' state to prevent
@@ -125,6 +131,8 @@ struct jffs2_inode_cache {#define INO_STATE_READING 5/* In read_inode() */ #define INO_STATE_CLEARING 6/* In clear_inode() */ +#define INO_FLAGS_XATTR_CHECKED 0x01/* has no duplicate xattr_ref */ +#define INOCACHE_HASHSIZE 128/*
@@ -375,6 +383,13 @@ void jffs2_free_node_frag(struct jffs2_nstruct jffs2_inode_cache *jffs2_alloc_inode_cache (void );void jffs2_free_inode_cache (struct jffs2_inode_cache *); +#ifdef CONFIG_JFFS2_XATTR +struct jffs2_xattr_datum *jffs2_alloc_xattr_datum (void ); +void jffs2_free_xattr_datum (struct jffs2_xattr_datum *); +struct jffs2_xattr_ref *jffs2_alloc_xattr_ref (void ); +void jffs2_free_xattr_ref (struct jffs2_xattr_ref *); +#endif /* CONFIG_JFFS2_XATTR */ +/* gc.c */ int jffs2_garbage_collect_pass (struct jffs2_sb_info *c);
fs/jffs2/readinode.c +1 -0
@@ -902,6 +902,7 @@ int jffs2_do_read_inode(struct jffs2_sb_ 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) {
fs/jffs2/scan.c +191 -0
209 lines not on this page · raw message
fs/jffs2/super.c +2 -0
@@ -151,6 +151,7 @@ static struct super_block *jffs2_get_sb_ sb->s_op = &jffs2_super_operations; sb->s_flags = flags |MS_NOATIME ; + sb->s_xattr = jffs2_xattr_handlers; ret =jffs2_do_fill_super (sb, data, (flags&MS_VERBOSE )?1 :0 );
@@ -293,6 +294,7 @@ static void jffs2_put_super (struct supekfree (c->blocks);jffs2_flash_cleanup (c);kfree (c->inocache_list); +jffs2_clear_xattr_subsystem (c);if (c->mtd->sync) c->mtd->sync (c->mtd);
fs/jffs2/symlink.c +6 -1
@@ -24,7 +24,12 @@ struct inode_operations jffs2_symlink_in { .readlink = generic_readlink, .follow_link = jffs2_follow_link, - .setattr = jffs2_setattr + .permission = jffs2_permission, + .setattr = jffs2_setattr, + .setxattr = jffs2_setxattr, + .getxattr = jffs2_getxattr, + .listxattr = jffs2_listxattr, + .removexattr = jffs2_removexattr };static int jffs2_follow_link (struct dentry *dentry,struct nameidata *nd)
fs/jffs2/write.c +1 -1
@@ -36,7 +36,7 @@ int jffs2_do_new_inode(struct jffs2_sb_i 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));
fs/jffs2/xattr.c +1046 -0
1,046 lines not on this page · raw message
fs/jffs2/xattr.h +137 -0
137 lines not on this page · raw message
include/linux/jffs2.h +31 -0
@@ -65,6 +65,9 @@#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) +// 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 +154,32 @@ struct jffs2_raw_inodeuint8_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 */ +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 seqno;/* sequencial number */ +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 +198,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; };
include/linux/jffs2_fs_sb.h +8 -0
@@ -115,6 +115,14 @@ struct jffs2_sb_info {struct jffs2_summary *summary;/* Summary information */ +#ifdef CONFIG_JFFS2_XATTR +uint32_t highest_xseqno; +struct list_head *xattrindex; +#define xattr_temp xattrindex[XATTRINDEX_HASHSIZE] +struct rw_semaphore xattr_sem; +uint32_t xdatum_mem_usage; +uint32_t xdatum_mem_threshold; +#endif /* OS-private pointer for getting back to master superblock info */ void *os_priv; };
cleanup-scan.xattr.c renamed from cleanup-scan.c +147 -0
159 lines not on this page · raw message
Quoted 8 lines · Kaigai Kohei
I revised the previous xattr patch in jffs2 based on some suggestions.
[1] scanning xattr related node for cleaned-up
scan.c. (jffs2_xattr_scan.c-cleanup.patch)
[2] enables xattr support in jffs2.(jffs2_xattr_take-3.patch)(*) We can apply jffs2_xattr_take-3.patch for current CVS independently.
Looks quite interesting. I'll take a closer look over the weekend.
Thanks!
Jörn
Signature · 2 lines
The strong give up and move away, while the weak give up and stay. -- unknown
E-mail with attached file has not delivered yet. (Re: [PATCH] XATTR issues on JFFS2)
Hi,
The quoted E-mail seems not to have been delivered by some reasons yet. (No E-mail with attached files has been distributed on the list since 27-Sep.)
http://www.kaigai.gr.jp/patch/jffs2_xattr_take-3.patch
The above patch was what I posted on 28-Sep, but it has not been delivered yet. (Today is 03-Oct JST!)
Are there any other E-mails which has not been delivered yet ?
Thanks,
Quoted 16 lines · Jörn Engel
Quoted 7 lines · Kaigai Kohei
I revised the previous xattr patch in jffs2 based on some suggestions.
[1] scanning xattr related node for cleaned-up
scan.c. (jffs2_xattr_scan.c-cleanup.patch)
[2] enables xattr support in jffs2. (jffs2_xattr_take-3.patch)
(*) We can apply jffs2_xattr_take-3.patch for current CVS independently.Looks quite interesting. I'll take a closer look over the weekend.
Thanks!
Jörn
Signature · 2 lines
Linux Promotion Center, NEC KaiGai Kohei <[email protected]>
Hi Jörn,
What status is the XATTR patch of JFFS2 now ??
I hope to merge it, if this patch has no problem.
Of course, I'll correct any inconvenient points which we found.
# I droped a Cc: for Ma, since his address seems to be invalid.
Quoted 16 lines · Jörn Engel
Quoted 7 lines · Kaigai Kohei
I revised the previous xattr patch in jffs2 based on some suggestions.
[1] scanning xattr related node for cleaned-up
scan.c. (jffs2_xattr_scan.c-cleanup.patch)
[2] enables xattr support in jffs2. (jffs2_xattr_take-3.patch)
(*) We can apply jffs2_xattr_take-3.patch for current CVS independently.Looks quite interesting. I'll take a closer look over the weekend.
Thanks!
Jörn
Signature · 2 lines
Linux Promotion Center, NEC KaiGai Kohei <[email protected]>
Quoted 5 lines · Kaigai Kohei
What status is the XATTR patch of JFFS2 now ??
I hope to merge it, if this patch has no problem.
Of course, I'll correct any inconvenient points which we found.
Lack of time. I still have your patch and some from Forrest lingering in my inbox. They all should receive a thorough line-by-line review - not necessarily by me, but by someone with enough knowledge.
If it helps you, your patches are already in a relatively good state. I cannot easily find problems with it.
Quoted 1 line
# I droped a Cc: for Ma, since his address seems to be invalid.
Fair enough.
Jörn
Signature · 2 lines
"Security vulnerabilities are here to stay." -- Scott Culp, Manager of the Microsoft Security Response Center, 2001
Hi,
Quoted 3 lines
Lack of time. I still have your patch and some from Forrest lingering in my inbox. They all should receive a thorough line-by-line review - not necessarily by me, but by someone with enough knowledge.
Sorry for hastening.
Quoted 2 lines
If it helps you, your patches are already in a relatively good state. I cannot easily find problems with it.
Thanks, I was hesitating whether I should begin to develop the ACL features based on XATTR.
If XATTR would be in a good state, I'm willing to begin the design and implementation.
Signature · 2 lines
Linux Promotion Center, NEC KaiGai Kohei <[email protected]>
Hi,
This attached patches are enables XATTR support on JFFS2. some new functionalities are added from take-3 patches.
# Sorry for slowing update.
[NOTICE]
We can test this patch with ONLY 2.6.14 kernel.
The previous versions of kernel do not support an new LSM hook.
[1/2] jffs2_xattr_take-4.patch
* CONFIG_JFFS2_XATTR was renamed to CONFIG_JFFS2_FS_XATTR The XATTR configuration switch are named CONFIG_<fsname>_FS_XATTR on another some filesystems which support XATTR.
I also follow this manner.
* CONFIG_JFFS2_FS_POSIX_ACL and JFFS2_FS_SECURITY are selectable. this follows another FS's manner.
* POSIX-ACL support was added.
This functionality is implemented in acl.c, acl.h.
I implemented the most part of this functionalities by referring the Ext2/3's implementation of POSIX-ACL.
If I took bad manner or misunderstanding for implementation, notice me please.
* jffs2_init_security() was added for inode initialization. At 2.6.14, new LSM hook(security_inode_init_security) was added. Because of this, any filesystems obtain security attribtues must call this this hook to set the security label for new inode. It's deployed in jffs2_create(), jffs2_symlink(), jffs2_mkdir() and jffs2_mknod().
* Some patch conflicts were fixed.
We can apply this patches for latest MTD-CVS without incident.
* An obvious bug was fixed.
In jffs2_build_xattr_subsystem(), NULL checking was omitted.
[2/2] mkfs.jffs2-xattr.patch
* --with-{xattr|selinux|posix-acl} options are added. --with-xattr enables to pack all xattr-entries into jffs2 image file. --with-selinux enables to pack security related xattr-entries which are named as 'security.*' into jffs2 image file. --with-posix-acl enables to pack ACL related xattr-entries which are names as 'system.posix_acl_access' or 'system.posix_acl_default'.
I hope to merge those functionalities into MTD's CVS tree. Thanks,
Signature · 1 line
KaiGai Kohei <[email protected]>
util/mkfs.jffs2.1 +18 -0
@@ -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
util/mkfs.jffs2.c +308 -0
392 lines not on this page · raw message
fs/jffs2/acl.c +484 -0
484 lines not on this page · raw message
fs/jffs2/acl.h +46 -0
46 lines not on this page · raw message
fs/jffs2/build.c +2 -0
@@ -160,6 +160,7 @@ static int jffs2_build_filesystem(struct ic->scan_dents =NULL ;cond_resched (); } +jffs2_build_xattr_subsystem (c); c->flags &= ~JFFS2_SB_FLAG_BUILDING ;dbg_fsbuild ("FS build complete\n" );
@@ -178,6 +179,7 @@ exit:jffs2_free_full_dirent (fd); } } +jffs2_clear_xattr_subsystem (c); }return ret;
fs/jffs2/dir.c +56 -6
99 lines not on this page · raw message
fs/jffs2/file.c +6 -1
@@ -54,7 +54,12 @@ struct file_operations jffs2_file_operatstruct inode_operations jffs2_file_inode_operations = { - .setattr = jffs2_setattr + .permission = jffs2_permission, + .setattr = jffs2_setattr, + .setxattr = jffs2_setxattr, + .getxattr = jffs2_getxattr, + .listxattr = jffs2_listxattr, + .removexattr = jffs2_removexattr }; struct address_space_operations jffs2_file_address_operations =
fs/jffs2/fs.c +13 -2
@@ -179,7 +179,12 @@ static int jffs2_do_setattr (struct inodint jffs2_setattr (struct dentry *dentry,struct iattr *iattr) { -return jffs2_do_setattr (dentry->d_inode, iattr); +int rc; + + rc =jffs2_do_setattr (dentry->d_inode, iattr); +if (!rc) + rc =jffs2_acl_chmod (dentry->d_inode); +return rc; }int jffs2_statfs (struct super_block *sb,struct kstatfs *buf)
@@ -218,6 +223,7 @@ void jffs2_clear_inode (struct inode *inD1 (printk (KERN_DEBUG "jffs2_clear_inode(): ino #%lu mode %o\n" , inode->i_ino, inode->i_mode)); +jffs2_xattr_delete_inode (c, f->inocache);jffs2_do_clear_inode (c, f); }
@@ -492,9 +498,12 @@ int jffs2_do_fill_super(struct super_blo }memset (c->inocache_list,0 ,INOCACHE_HASHSIZE *sizeof (struct jffs2_inode_cache *)); -if ((ret =jffs2_do_mount_fs (c))) +if ((ret =jffs2_init_xattr_subsystem (c))) goto out_inohash; +if ((ret =jffs2_do_mount_fs (c))) + goto out_xattr; + ret = -EINVAL ;D1 (printk (KERN_DEBUG "jffs2_do_fill_super(): Getting root inode\n" ));
@@ -522,6 +531,8 @@ int jffs2_do_fill_super(struct super_blojffs2_free_ino_caches (c);jffs2_free_raw_node_refs (c);jffs2_free_eraseblocks (c); + out_xattr: +jffs2_clear_xattr_subsystem (c); out_inohash:kfree (c->inocache_list); out_wbuf:
fs/jffs2/fs.c.orig +683 -0
683 lines not on this page · raw message
fs/jffs2/gc.c +10 -0
@@ -312,6 +312,16 @@ int jffs2_garbage_collect_pass(struct jf ic =jffs2_raw_ref_to_ic (raw); +/* When 'ic' refers xattr_datum/xattr_ref, this node is GCed as xattr. +We can decide whether this node is inode or xattr by ic->class. +ret = 0 : ic is xattr_datum/xattr_ref, and GC was SUCCESSED. +ret < 0 : ic is xattr_datum/xattr_ref, but GC was FAILED. +ret > 0 : ic is NOT xattr_datum/xattr_ref. +*/ + ret =jffs2_garbage_collect_xattr (c, ic); +if (ret <=0 ) + goto release_sem; +/* We need to hold the inocache. Either the erase_completion_lock or the inocache_lock are sufficient; we trade down since the inocache_lock causes less contention. */
fs/jffs2/Makefile.common +3 -0
@@ -12,6 +12,9 @@ jffs2-y += symlink.o build.o erase.o bac jffs2-y += super.o debug.o wear_leveling.o jffs2-$(CONFIG_JFFS2_FS_WRITEBUFFER) += wbuf.o +jffs2-$(CONFIG_JFFS2_FS_XATTR) += xattr.o +jffs2-$(CONFIG_JFFS2_FS_SECURITY) += security.o +jffs2-$(CONFIG_JFFS2_FS_POSIX_ACL) += acl.o jffs2-$(CONFIG_JFFS2_RUBIN) += compr_rubin.o jffs2-$(CONFIG_JFFS2_RTIME) += compr_rtime.o jffs2-$(CONFIG_JFFS2_ZLIB) += compr_zlib.o
fs/jffs2/malloc.c +58 -2
81 lines not on this page · raw message
fs/jffs2/nodelist.c +1 -0
@@ -919,6 +919,7 @@ void jffs2_free_ino_caches(struct jffs2_ this = c->inocache_list[i];while (this) { next = this->next; +jffs2_xattr_free_inode (c, this);jffs2_free_inode_cache (this); this = next; }
fs/jffs2/nodelist.h +17 -1
@@ -20,6 +20,8 @@#include <linux/jffs2.h> #include <linux/jffs2_fs_sb.h> #include <linux/jffs2_fs_i.h> +#include "xattr.h" +#include "acl.h" #include "summary.h" #ifdef __ECOS
@@ -107,11 +109,16 @@ struct jffs2_inode_cache {temporary lists of dirents, and later must be set to NULL to mark the end of the raw_node_ref->next_in_ino chain. */ +u8 class;/* It's used for identification */ +u8 flags; +uint16_t state;struct jffs2_inode_cache *next;struct jffs2_raw_node_ref *nodes;uint32_t ino;int nlink; -int state; +#ifdef CONFIG_JFFS2_FS_XATTR +struct list_head ilist; +#endif };/* Inode states for 'state' above. We need the 'GC' state to prevent
@@ -125,6 +132,8 @@ struct jffs2_inode_cache {#define INO_STATE_READING 5/* In read_inode() */ #define INO_STATE_CLEARING 6/* In clear_inode() */ +#define INO_FLAGS_XATTR_CHECKED 0x01/* has no duplicate xattr_ref */ +#define INOCACHE_HASHSIZE 128/*
@@ -388,6 +397,13 @@ struct jffs2_inode_cache *jffs2_alloc_invoid jffs2_free_inode_cache (struct jffs2_inode_cache *);int jffs2_alloc_eraseblocks (struct jffs2_sb_info *c);void jffs2_free_eraseblocks (struct jffs2_sb_info *c); +#ifdef CONFIG_JFFS2_FS_XATTR +struct jffs2_xattr_datum *jffs2_alloc_xattr_datum (void ); +void jffs2_free_xattr_datum (struct jffs2_xattr_datum *); +struct jffs2_xattr_ref *jffs2_alloc_xattr_ref (void ); +void jffs2_free_xattr_ref (struct jffs2_xattr_ref *); +#endif /* CONFIG_JFFS2_FS_XATTR */ +/* gc.c */ int jffs2_garbage_collect_pass (struct jffs2_sb_info *c);
fs/jffs2/os-linux.h +4 -0
@@ -60,6 +60,10 @@ static inline void jffs2_init_inode_info f->target =NULL ; f->flags =0 ; f->usercompr =0 ; +#ifdef CONFIG_JFFS2_FS_POSIX_ACL + f->i_acl_access =JFFS2_ACL_NOT_CACHED ; + f->i_acl_default =JFFS2_ACL_NOT_CACHED ; +#endif }
fs/jffs2/readinode.c +1 -0
@@ -891,6 +891,7 @@ int jffs2_do_read_inode(struct jffs2_sb_ 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) {
fs/jffs2/scan.c +191 -0
209 lines not on this page · raw message
fs/jffs2/security.c +82 -0
82 lines not on this page · raw message
fs/jffs2/super.c +5 -1
@@ -151,7 +151,10 @@ static struct super_block *jffs2_get_sb_ sb->s_op = &jffs2_super_operations; sb->s_flags = flags |MS_NOATIME ; - + sb->s_xattr = jffs2_xattr_handlers; +#ifdef CONFIG_JFFS2_FS_POSIX_ACL + sb->s_flags |=MS_POSIXACL ; +#endif ret =jffs2_do_fill_super (sb, data, (flags&MS_VERBOSE )?1 :0 );if (ret) {
@@ -290,6 +293,7 @@ static void jffs2_put_super (struct supejffs2_free_eraseblocks (c);jffs2_flash_cleanup (c);kfree (c->inocache_list); +jffs2_clear_xattr_subsystem (c);if (c->mtd->sync) c->mtd->sync (c->mtd);
fs/jffs2/symlink.c +6 -1
@@ -24,7 +24,12 @@ struct inode_operations jffs2_symlink_in { .readlink = generic_readlink, .follow_link = jffs2_follow_link, - .setattr = jffs2_setattr + .permission = jffs2_permission, + .setattr = jffs2_setattr, + .setxattr = jffs2_setxattr, + .getxattr = jffs2_getxattr, + .listxattr = jffs2_listxattr, + .removexattr = jffs2_removexattr };static void *jffs2_follow_link (struct dentry *dentry,struct nameidata *nd)
fs/jffs2/write.c +1 -1
@@ -36,7 +36,7 @@ int jffs2_do_new_inode(struct jffs2_sb_i 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));
fs/jffs2/xattr.c +1021 -0
692 lines not on this page · raw message
fs/jffs2/xattr.h +144 -0
144 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
Part of the diff is not shown here. View the raw message.
Sorry, some garbages mixed into my previous mail.
Please use those patches which are attached this mail, and discard previous one.
Quoted 50 lines · KaiGai Kohei
Hi,
This attached patches are enables XATTR support on JFFS2. some new functionalities are added from take-3 patches.
# Sorry for slowing update.
[NOTICE]
We can test this patch with ONLY 2.6.14 kernel.
The previous versions of kernel do not support an new LSM hook.[1/2] jffs2_xattr_take-4.patch
*CONFIG_JFFS2_XATTRwas renamed toCONFIG_JFFS2_FS_XATTRThe XATTR configuration switch are named CONFIG_<fsname>_FS_XATTR on another some filesystems which support XATTR.
I also follow this manner.*
CONFIG_JFFS2_FS_POSIX_ACLandJFFS2_FS_SECURITYare selectable. this follows another FS's manner.* POSIX-ACL support was added.
This functionality is implemented inacl.c,acl.h.
I implemented the most part of this functionalities by referring the Ext2/3's implementation of POSIX-ACL.
If I took bad manner or misunderstanding for implementation, notice me please.*
jffs2_init_security()was added for inode initialization. At 2.6.14, new LSMhook(security_inode_init_security)was added. Because of this, any filesystems obtain security attribtues must call this this hook to set the security label for new inode. It's deployed injffs2_create(),jffs2_symlink(),jffs2_mkdir()andjffs2_mknod().* Some patch conflicts were fixed.
We can apply this patches for latest MTD-CVS without incident.* An obvious bug was fixed.
Injffs2_build_xattr_subsystem(), NULL checking was omitted.[2/2] mkfs.jffs2-xattr.patch
* --with-{xattr|selinux|posix-acl} options are added. --with-xattr enables to pack all xattr-entries into jffs2 image file. --with-selinux enables to pack security related xattr-entries which are named as 'security.*' into jffs2 image file. --with-posix-acl enables to pack ACL related xattr-entries which are names as 'system.posix_acl_access' or 'system.posix_acl_default'.I hope to merge those functionalities into MTD's CVS tree. Thanks,
Signature · 1 line
KaiGai Kohei <[email protected]>
util/mkfs.jffs2.1 +18 -0
@@ -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
util/mkfs.jffs2.c +308 -0
392 lines not on this page · raw message
fs/jffs2/acl.c +484 -0
484 lines not on this page · raw message
fs/jffs2/acl.h +46 -0
46 lines not on this page · raw message
fs/jffs2/build.c +2 -0
@@ -160,6 +160,7 @@ static int jffs2_build_filesystem(struct ic->scan_dents =NULL ;cond_resched (); } +jffs2_build_xattr_subsystem (c); c->flags &= ~JFFS2_SB_FLAG_BUILDING ;dbg_fsbuild ("FS build complete\n" );
@@ -178,6 +179,7 @@ exit:jffs2_free_full_dirent (fd); } } +jffs2_clear_xattr_subsystem (c); }return ret;
fs/jffs2/dir.c +56 -6
99 lines not on this page · raw message
fs/jffs2/file.c +6 -1
@@ -54,7 +54,12 @@ struct file_operations jffs2_file_operatstruct inode_operations jffs2_file_inode_operations = { - .setattr = jffs2_setattr + .permission = jffs2_permission, + .setattr = jffs2_setattr, + .setxattr = jffs2_setxattr, + .getxattr = jffs2_getxattr, + .listxattr = jffs2_listxattr, + .removexattr = jffs2_removexattr }; struct address_space_operations jffs2_file_address_operations =
fs/jffs2/fs.c +13 -2
@@ -179,7 +179,12 @@ static int jffs2_do_setattr (struct inodint jffs2_setattr (struct dentry *dentry,struct iattr *iattr) { -return jffs2_do_setattr (dentry->d_inode, iattr); +int rc; + + rc =jffs2_do_setattr (dentry->d_inode, iattr); +if (!rc) + rc =jffs2_acl_chmod (dentry->d_inode); +return rc; }int jffs2_statfs (struct super_block *sb,struct kstatfs *buf)
@@ -218,6 +223,7 @@ void jffs2_clear_inode (struct inode *inD1 (printk (KERN_DEBUG "jffs2_clear_inode(): ino #%lu mode %o\n" , inode->i_ino, inode->i_mode)); +jffs2_xattr_delete_inode (c, f->inocache);jffs2_do_clear_inode (c, f); }
@@ -492,9 +498,12 @@ int jffs2_do_fill_super(struct super_blo }memset (c->inocache_list,0 ,INOCACHE_HASHSIZE *sizeof (struct jffs2_inode_cache *)); -if ((ret =jffs2_do_mount_fs (c))) +if ((ret =jffs2_init_xattr_subsystem (c))) goto out_inohash; +if ((ret =jffs2_do_mount_fs (c))) + goto out_xattr; + ret = -EINVAL ;D1 (printk (KERN_DEBUG "jffs2_do_fill_super(): Getting root inode\n" ));
@@ -522,6 +531,8 @@ int jffs2_do_fill_super(struct super_blojffs2_free_ino_caches (c);jffs2_free_raw_node_refs (c);jffs2_free_eraseblocks (c); + out_xattr: +jffs2_clear_xattr_subsystem (c); out_inohash:kfree (c->inocache_list); out_wbuf:
fs/jffs2/gc.c +10 -0
@@ -312,6 +312,16 @@ int jffs2_garbage_collect_pass(struct jf ic =jffs2_raw_ref_to_ic (raw); +/* When 'ic' refers xattr_datum/xattr_ref, this node is GCed as xattr. +We can decide whether this node is inode or xattr by ic->class. +ret = 0 : ic is xattr_datum/xattr_ref, and GC was SUCCESSED. +ret < 0 : ic is xattr_datum/xattr_ref, but GC was FAILED. +ret > 0 : ic is NOT xattr_datum/xattr_ref. +*/ + ret =jffs2_garbage_collect_xattr (c, ic); +if (ret <=0 ) + goto release_sem; +/* We need to hold the inocache. Either the erase_completion_lock or the inocache_lock are sufficient; we trade down since the inocache_lock causes less contention. */
fs/jffs2/Makefile.common +3 -0
@@ -12,6 +12,9 @@ jffs2-y += symlink.o build.o erase.o bac jffs2-y += super.o debug.o wear_leveling.o jffs2-$(CONFIG_JFFS2_FS_WRITEBUFFER) += wbuf.o +jffs2-$(CONFIG_JFFS2_FS_XATTR) += xattr.o +jffs2-$(CONFIG_JFFS2_FS_SECURITY) += security.o +jffs2-$(CONFIG_JFFS2_FS_POSIX_ACL) += acl.o jffs2-$(CONFIG_JFFS2_RUBIN) += compr_rubin.o jffs2-$(CONFIG_JFFS2_RTIME) += compr_rtime.o jffs2-$(CONFIG_JFFS2_ZLIB) += compr_zlib.o
fs/jffs2/malloc.c +58 -2
81 lines not on this page · raw message
fs/jffs2/nodelist.c +1 -0
@@ -919,6 +919,7 @@ void jffs2_free_ino_caches(struct jffs2_ this = c->inocache_list[i];while (this) { next = this->next; +jffs2_xattr_free_inode (c, this);jffs2_free_inode_cache (this); this = next; }
fs/jffs2/nodelist.h +17 -1
@@ -20,6 +20,8 @@#include <linux/jffs2.h> #include <linux/jffs2_fs_sb.h> #include <linux/jffs2_fs_i.h> +#include "xattr.h" +#include "acl.h" #include "summary.h" #ifdef __ECOS
@@ -107,11 +109,16 @@ struct jffs2_inode_cache {temporary lists of dirents, and later must be set to NULL to mark the end of the raw_node_ref->next_in_ino chain. */ +u8 class;/* It's used for identification */ +u8 flags; +uint16_t state;struct jffs2_inode_cache *next;struct jffs2_raw_node_ref *nodes;uint32_t ino;int nlink; -int state; +#ifdef CONFIG_JFFS2_FS_XATTR +struct list_head ilist; +#endif };/* Inode states for 'state' above. We need the 'GC' state to prevent
@@ -125,6 +132,8 @@ struct jffs2_inode_cache {#define INO_STATE_READING 5/* In read_inode() */ #define INO_STATE_CLEARING 6/* In clear_inode() */ +#define INO_FLAGS_XATTR_CHECKED 0x01/* has no duplicate xattr_ref */ +#define INOCACHE_HASHSIZE 128/*
@@ -388,6 +397,13 @@ struct jffs2_inode_cache *jffs2_alloc_invoid jffs2_free_inode_cache (struct jffs2_inode_cache *);int jffs2_alloc_eraseblocks (struct jffs2_sb_info *c);void jffs2_free_eraseblocks (struct jffs2_sb_info *c); +#ifdef CONFIG_JFFS2_FS_XATTR +struct jffs2_xattr_datum *jffs2_alloc_xattr_datum (void ); +void jffs2_free_xattr_datum (struct jffs2_xattr_datum *); +struct jffs2_xattr_ref *jffs2_alloc_xattr_ref (void ); +void jffs2_free_xattr_ref (struct jffs2_xattr_ref *); +#endif /* CONFIG_JFFS2_FS_XATTR */ +/* gc.c */ int jffs2_garbage_collect_pass (struct jffs2_sb_info *c);
fs/jffs2/os-linux.h +4 -0
@@ -60,6 +60,10 @@ static inline void jffs2_init_inode_info f->target =NULL ; f->flags =0 ; f->usercompr =0 ; +#ifdef CONFIG_JFFS2_FS_POSIX_ACL + f->i_acl_access =JFFS2_ACL_NOT_CACHED ; + f->i_acl_default =JFFS2_ACL_NOT_CACHED ; +#endif }
fs/jffs2/readinode.c +1 -0
@@ -891,6 +891,7 @@ int jffs2_do_read_inode(struct jffs2_sb_ 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) {
fs/jffs2/scan.c +191 -0
209 lines not on this page · raw message
fs/jffs2/security.c +82 -0
82 lines not on this page · raw message
fs/jffs2/super.c +5 -1
@@ -151,7 +151,10 @@ static struct super_block *jffs2_get_sb_ sb->s_op = &jffs2_super_operations; sb->s_flags = flags |MS_NOATIME ; - + sb->s_xattr = jffs2_xattr_handlers; +#ifdef CONFIG_JFFS2_FS_POSIX_ACL + sb->s_flags |=MS_POSIXACL ; +#endif ret =jffs2_do_fill_super (sb, data, (flags&MS_VERBOSE )?1 :0 );if (ret) {
@@ -290,6 +293,7 @@ static void jffs2_put_super (struct supejffs2_free_eraseblocks (c);jffs2_flash_cleanup (c);kfree (c->inocache_list); +jffs2_clear_xattr_subsystem (c);if (c->mtd->sync) c->mtd->sync (c->mtd);
fs/jffs2/symlink.c +6 -1
@@ -24,7 +24,12 @@ struct inode_operations jffs2_symlink_in { .readlink = generic_readlink, .follow_link = jffs2_follow_link, - .setattr = jffs2_setattr + .permission = jffs2_permission, + .setattr = jffs2_setattr, + .setxattr = jffs2_setxattr, + .getxattr = jffs2_getxattr, + .listxattr = jffs2_listxattr, + .removexattr = jffs2_removexattr };static void *jffs2_follow_link (struct dentry *dentry,struct nameidata *nd)
fs/jffs2/write.c +1 -1
@@ -36,7 +36,7 @@ int jffs2_do_new_inode(struct jffs2_sb_i 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));
fs/jffs2/xattr.c +1021 -0
1,021 lines not on this page · raw message
fs/jffs2/xattr.h +144 -0
144 lines not on this page · raw message
fs/Kconfig +38 -0
@@ -51,6 +51,44 @@ config JFFS2_FS_DEBUG If reporting bugs, please try to have available a full dump of the messages at debug level 1 while the misbehaviour was occurring. +config JFFS2_FS_XATTR + bool "JFFS2 XATTR support (EXPERIMENTAL)" + depends on JFFS2_FS && EXPERIMENTAL + default n + help + Extended attributes are name:value pairs associated with inodes by + the kernel or by users (see the attr(5) manual page, or visit + <http://acl.bestbits.at/> for details). + + If unsure, say N. + +config JFFS2_FS_POSIX_ACL + bool "JFFS2 POSIX Access Control Lists" + depends on JFFS2_FS_XATTR + default y + select FS_POSIX_ACL + help + Posix Access Control Lists (ACLs) support permissions for users and + groups beyond the owner/group/world scheme. + + To learn more about Access Control Lists, visit the Posix ACLs for + Linux website <http://acl.bestbits.at/>. + + If you don't know what Access Control Lists are, say N + +config JFFS2_FS_SECURITY + bool "JFFS2 Security Labels" + depends on JFFS2_FS_XATTR + default y + help + Security labels support alternative access control models + implemented by security modules like SELinux. This option + enables an extended attribute handler for file security + labels in the jffs2 filesystem. + + If you are not using a security module that requires using + extended attributes for file security labels, say N. + config JFFS2_FS_WRITEBUFFER bool "JFFS2 write-buffering support" depends on JFFS2_FS
include/linux/jffs2_fs_i.h +5 -0
@@ -5,6 +5,7 @@#include <linux/version.h> #include <linux/rbtree.h> +#include <linux/posix_acl.h> #include <asm/semaphore.h> struct jffs2_inode_info {
@@ -45,6 +46,10 @@ struct jffs2_inode_info {struct inode vfs_inode;#endif #endif +#ifdef CONFIG_JFFS2_FS_POSIX_ACL +struct posix_acl *i_acl_access; +struct posix_acl *i_acl_default; +#endif };#endif /* _JFFS2_FS_I */
include/linux/jffs2_fs_sb.h +8 -0
@@ -140,6 +140,14 @@ struct jffs2_sb_info {struct jffs2_blocks_bucket used_blocks[HASH_SIZE ];/* The hash table for both dirty and clean erase blocks */ struct jffs2_blocks_bucket free_blocks[HASH_SIZE ];/* The hash table for free erase blocks */ +#ifdef CONFIG_JFFS2_FS_XATTR +uint32_t highest_xseqno; +struct list_head *xattrindex; +#define xattr_temp xattrindex[XATTRINDEX_HASHSIZE] +struct rw_semaphore xattr_sem; +uint32_t xdatum_mem_usage; +uint32_t xdatum_mem_threshold; +#endif /* OS-private pointer for getting back to master superblock info */ void *os_priv; };
include/linux/jffs2.h +40 -0
@@ -71,6 +71,18 @@#define JFFS2_NODETYPE_ERASEBLOCK_HEADER (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 5)#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)
@@ -157,6 +169,32 @@ struct jffs2_raw_inodeuint8_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 */ +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 seqno;/* sequencial number */ +jint32_t ino;/* inode number */ +jint32_t xid;/* XATTR identifier number */ +jint32_t node_crc; +} __attribute__((packed)); +struct jffs2_raw_summary {jint16_t magic;
@@ -191,6 +229,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_raw_ebh eh;struct jffs2_unknown_node u;
Hello KaiGai,
to ease JFFS2 debugging I split debugging messages by subsystems and one may enable/disable debugging messages from each subsystem separately. I wonder, if it is possible to add DBG_XATTR() or the like instead of using D1()? It really makes bugs hunting easier. Please, glance at debug.h.
Thanks.
Signature · 3 lines
Best Regards, Artem B. Bityutskiy, St.-Petersburg, Russia.
Hello Artem,
Quoted 1 line
to ease JFFS2 debugging I split debugging messages by subsystems and one may enable/disable debugging messages from each subsystem separately. I wonder, if it is possible to add
DBG_XATTR()or the like instead of usingD1()? It really makes bugs hunting easier. Please, glance atdebug.h.
I agree what you say.
There is especially no reason why such a stub macro is not used.
In the next patch, I'll use some stub macros as are defined in debug.h. The following definition will be added in debug.h, and I'll use JFFS2_NOTICE() and so on instead of raw-printk().
/* Watch the XATTR subsystem */
#ifdef JFFS2_DBG_XATTR_MESSAGES
#define dbg_xattr(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) #else
#define dbg_xattr(fmt, ...)
#endif
Thanks,
Signature · 2 lines
Linux Promotion Center, NEC KaiGai Kohei <[email protected]>
Hello, Aterm.
This patch replaces any warning messages by raw-printk() with JFFS2_WARNING()/JFFS2_NOTICE() macros, and any debugging messages are replaced by dbg_xattr() which is newly defined in debug.h.
Please apply this patch after 'jffs2_xattr_take-4.patch' which
I posted at 27-Nov 2005.
Since the whole of those implementation is a bit massive, I post only difference with last time.
If you hope to get the whole of this implementation already patched, please visit http://www.kaigai.gr.jp/ and download 'jffs2_xattr_take-4.1.patch'.
[JFFS2] Provide XATTR and POSIX ACL support on JFFS2
- http://www.kaigai.gr.jp/patch/jffs2_xattr_take-4.1.patch
[JFFS2] Provide --with-{xattr|selinux|posix-acl} options for mkfs.jffs2
- http://www.kaigai.gr.jp/patch/mkfs.jffs2-xattr.patch
Thanks,
Quoted 5 lines · Artem B. Bityutskiy
Hello KaiGai,
to ease JFFS2 debugging I split debugging messages by subsystems and one may enable/disable debugging messages from each subsystem separately. I wonder, if it is possible to add
DBG_XATTR()or the like instead of usingD1()? It really makes bugs hunting easier. Please, glance atdebug.h.Thanks.
Signature · 1 line
KaiGai Kohei <[email protected]>
fs/jffs2/acl.c +4 -2
@@ -53,14 +53,16 @@ static struct posix_acl *jffs2_acl_from_ {const char *end = (char *)value + size;struct posix_acl *acl; +uint32_t ver;int i, count;if (!value)return NULL ;if (size <sizeof (jffs2_acl_header))return ERR_PTR (-EINVAL ); -if (je32_to_cpu (((jffs2_acl_header *)value)->a_version) !=JFFS2_ACL_VERSION ) { -D1 (printk (KERN_NOTICE "%s:%d invalid ACL version.\n" , __FUNCTION__, __LINE__)); + ver =je32_to_cpu (((jffs2_acl_header *)value)->a_version); +if (ver !=JFFS2_ACL_VERSION ) { +JFFS2_WARNING ("Invalid ACL version. (=%u)\n" , ver);return ERR_PTR (-EINVAL ); }
fs/jffs2/debug.h +6 -0
@@ -171,6 +171,12 @@#define dbg_memalloc (fmt, ...)#endif +/* Watch the XATTR subsystem */ +#ifdef JFFS2_DBG_XATTR_MESSAGES +#define dbg_xattr (fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) +#else +#define dbg_xattr (fmt, ...) +#endif /* "Sanity" checks */ void
fs/jffs2/scan.c +18 -12
@@ -329,27 +329,27 @@ static int jffs2_scan_xattr_node(struct crc =crc32 (0 , rx,sizeof (struct jffs2_raw_xattr )-8 );if (crc !=je32_to_cpu (rx->node_crc)) { -printk (KERN_NOTICE "%s node CRC failed on node at 0x%08x: " -"Read 0x%08x, calculated 0x%08x\n" , - __FUNCTION__, ofs,je32_to_cpu (rx->node_crc), crc); +JFFS2_WARNING ("node CRC failed on node at 0x%08x: " +"Read 0x%08x, calculated 0x%08x\n" , + ofs,je32_to_cpu (rx->node_crc), crc);dirty_space (c, jeb,je32_to_cpu (rx->totlen));return 0 ; } xd =jffs2_find_xattr_datum (c,je32_to_cpu (rx->xid));if (xd) { -printk (KERN_NOTICE "%s() duplicate xid=%u found. " -"on node at 0x%08x, later one is ignored.\n" , - __FUNCTION__,je32_to_cpu (rx->xid), ofs); +JFFS2_WARNING ("duplicate xid=%u found. " +"on node at 0x%08x, later one is ignored.\n" , +je32_to_cpu (rx->xid), ofs);dirty_space (c, jeb,je32_to_cpu (rx->totlen));return 0 ; } crc =crc32 (0 , rx->data, rx->name_len +1 +je16_to_cpu (rx->value_len));if (crc !=je32_to_cpu (rx->data_crc)) { -printk (KERN_NOTICE "%s data CRC failed on node at 0x%08x: " -"Read 0x%08x, calculated 0x%08x\n" , - __FUNCTION__, ofs,je32_to_cpu (rx->data_crc), crc); +JFFS2_WARNING ("data CRC failed on node at 0x%08x: " +"Read 0x%08x, calculated 0x%08x\n" , + ofs,je32_to_cpu (rx->data_crc), crc);dirty_space (c, jeb,je32_to_cpu (rx->totlen));return 0 ; }
@@ -388,6 +388,9 @@ static int jffs2_scan_xattr_node(structjffs2_attach_xattr_datum (c, xd); +D2 (dbg_xattr ("scan JFFS2_NODETYPE_XATTR at %#08x (xid=%u, xprefix=%d)\n" , + ofs, xd->xid, xd->xprefix)); +return 0 ; }
@@ -400,9 +403,9 @@ static int jffs2_scan_xref_node(struct j crc =crc32 (0 , rr,sizeof (*rr)-4 );if (crc !=je32_to_cpu (rr->node_crc)) { -printk (KERN_NOTICE "%s node CRC failed on node at 0x%08x: " -"Read 0x%08x, calculated 0x%08x\n" , - __FUNCTION__, ofs,je32_to_cpu (rr->node_crc), crc); +JFFS2_WARNING ("node CRC failed on node at 0x%08x: " +"Read 0x%08x, calculated 0x%08x\n" , + ofs,je32_to_cpu (rr->node_crc), crc);dirty_space (c, jeb,je32_to_cpu (rr->totlen));return 0 ; }
@@ -448,6 +451,9 @@ static int jffs2_scan_xref_node(struct jlist_add_tail (&ref->ilist, &c->xattr_temp); +D2 (dbg_xattr ("scan JFFS2_NODETYPE_XREF at %#08x (xid=%u, ino=%u)\n" , + ofs, ref->xid, ref->ino)); + return 0; }#endif
fs/jffs2/xattr.c +35 -31
175 lines not on this page · raw message
Hi,
The attached patch adds an functionality for mkfs.jffs2.
'-A' or '--with-xattr' enables to stuff up any xattr-imforamations for each files into JFFS2 image file.
This patch depends on 'jffs2_xattr_take-3.patch' I posted on 28-Sep.
In addition, some constants of JFFS2_XPREFIX_* are moved from fs/jffs2/xattr.h to include/linux/jffs2.h, because I want to use those constants in mkfs.jffs2. This change has no effects in kernel-side.
Perhaps, another style like '--with-selinux' or '--with-acl' might be better than '--with-xattr'.
Any comments please,
Thanks.
Quoted 9 lines · Kaigai Kohei
Hi,
I revised the previous xattr patch in jffs2 based on some suggestions.
[1] scanning xattr related node for cleaned-up
scan.c. (jffs2_xattr_scan.c-cleanup.patch)
[2] enables xattr support in jffs2.(jffs2_xattr_take-3.patch)(*) We can apply jffs2_xattr_take-3.patch for current CVS independently.
Signature · 2 lines
Linux Promotion Center, NEC KaiGai Kohei <[email protected]>
fs/jffs2/xattr.c +2 -0
@@ -42,6 +42,7 @@ static int do_jffs2_setxattr(struct inod const char *buffer, size_t size, int flags);/* ---- XATTR Handler for "user.*" --------------------- */ +#define XATTR_USER_PREFIX "user."static int jffs2_user_getxattr (struct inode *inode,const char *name,void *buffer,size_t size) {
@@ -97,6 +98,7 @@ static struct xattr_handler jffs2_user_x };/* ---- XATTR Handler for "trusted.*" ------------------ */ +#define XATTR_TRUSTED_PREFIX "trusted."static int jffs2_trusted_getxattr (struct inode *inode,const char *name,void *buffer,size_t size) {
fs/jffs2/xattr.h +0 -10
@@ -14,16 +14,6 @@#include <linux/xattr.h> #define XATTRINDEX_HASHSIZE (57) -#define XATTR_USER_PREFIX "user." -#define XATTR_TRUSTED_PREFIX "trusted." - -#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_XPREFIX_INVALID 6 -#define JFFS2_XDATUM_FLAGS_HOT 0x01/* This is hot xattr_datum */ #define RAWNODE_CLASS_INODE_CACHE 0
include/linux/jffs2.h +7 -0
@@ -68,6 +68,13 @@#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.*" */ +// 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)
util/mkfs.jffs2.1 +6 -0
@@ -49,6 +49,9 @@ mkfs.jffs2 \- Create a JFFS2 file system .B -P,--squash-perms ] [ +.B -A,--with-xattr +] +[ .B -m,--compression-mode=MODE ] [
@@ -178,6 +181,9 @@ Squash owners making all files be owned .B -P, --squash-perms Squash permissions, removing write permission for \'group\' and \'other\'. .TP +.B -A, --with-xattr +Include XATTR meta information. It's necessary for SELinux or ACL support. +.TP .B -m, --compression-mode=MODE Set the default compression mode. The default mode is .B priority
util/mkfs.jffs2.c +178 -3
273 lines not on this page · raw message