Bug fix for uid/gid in jffs2
As we kown that uid is u32(__kernel_uid32_t) in linux, but uid is u16(jint16_t) in jffs2 ,so jffs2 has the following problem,
mount -t jffs2 /dev/mtdblock0 /mnt
touch /mnt/a
chown 65535.65535 /mnt/a;ls -n /mnt
total 1
-rw-r--r-- 1 65535 65535 2 Mar 1 11:53 a
chown 65536.65536 /mnt/a;ls -n /mnt
total 1
-rw-r--r-- 1 0 0 2 Mar 1 11:53 a
chown 65537.65537 /mnt/a;ls -n /mnt
total 1
-rw-r--r-- 1 1 1 2 Mar 1 11:53 a
The patch bellow will fix it.
From 0ab0c9a341e642345b8cf02a029ddc44421379c3 Mon Sep 17 00:00:00 2001
From: Shukui Yang <[email protected]>
Date: Wed, 1 Mar 2017 16:06:33 +0800
Subject: [PATCH] uid/gid use jint32_t in jffs2
--- fs/jffs2/debug.c | 4 ++-- fs/jffs2/file.c | 8 ++++---- fs/jffs2/fs.c | 22 +++++++++++----------- fs/jffs2/gc.c | 12 ++++++------ fs/jffs2/readinode.c | 4 ++-- fs/jffs2/super.c | 2 +- include/uapi/linux/jffs2.h | 4 ++-- 7 files changed, 28 insertions(+), 28 deletions(-)
fs/jffs2/debug.c +0 -0
@@ -814,8 +814,8 @@ void __jffs2_dbg_superblock_counts(struct jffs2_sb_info *c)printk (JFFS2_DBG "ino:\t%#08x\n" ,je32_to_cpu (node.i.ino)); printk(JFFS2_DBG "version:\t%#08x\n",
je32_to_cpu(node.i.version));
printk(JFFS2_DBG "mode:\t%#08x\n", node.i.mode.m);
- printk(JFFS2_DBG "uid:\t%#04x\n", je16_to_cpu(node.i.uid));
- printk(JFFS2_DBG "gid:\t%#04x\n", je16_to_cpu(node.i.gid));
+ printk(JFFS2_DBG "uid:\t%#08x\n", je32_to_cpu(node.i.uid));
+ printk(JFFS2_DBG "gid:\t%#08x\n", je32_to_cpu(node.i.gid));
printk(JFFS2_DBG "isize:\t%#08x\n", je32_to_cpu(node.i.isize));
printk(JFFS2_DBG "atime:\t%#08x\n", je32_to_cpu(node.i.atime));
printk(JFFS2_DBG "mtime:\t%#08x\n", je32_to_cpu(node.i.mtime));fs/jffs2/file.c +2 -2
@@ -172,8 +172,8 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping, ri.ino =cpu_to_je32 (f->inocache->ino); ri.version =cpu_to_je32 (++f->highest_version); ri.mode =cpu_to_jemode (inode->i_mode); - ri.uid =cpu_to_je16 (i_uid_read (inode)); - ri.gid =cpu_to_je16 (i_gid_read (inode)); + ri.uid =cpu_to_je32 (i_uid_read (inode)); + ri.gid =cpu_to_je32 (i_gid_read (inode)); ri.isize =cpu_to_je32 (max ((uint32_t )inode->i_size, pageofs)); ri.atime = ri.ctime = ri.mtime =cpu_to_je32 (get_seconds ()); ri.offset =cpu_to_je32 (inode->i_size);
@@ -280,8 +280,8 @@ static int jffs2_write_end(struct file *filp, struct address_space *mapping,/* Set the fields that the generic jffs2_write_inode_range() code
can't find */
ri->ino = cpu_to_je32(inode->i_ino);
ri->mode = cpu_to_jemode(inode->i_mode);
- ri->uid = cpu_to_je16(i_uid_read(inode));
- ri->gid = cpu_to_je16(i_gid_read(inode));
+ ri->uid = cpu_to_je32(i_uid_read(inode));
+ ri->gid = cpu_to_je32(i_gid_read(inode));
ri->isize = cpu_to_je32((uint32_t)inode->i_size);
ri->atime = ri->ctime = ri->mtime = cpu_to_je32(get_seconds());fs/jffs2/fs.c +11 -11
@@ -99,9 +99,9 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) ri->ino =cpu_to_je32 (inode->i_ino); ri->version =cpu_to_je32 (++f->highest_version); - ri->uid =cpu_to_je16 ((ivalid &ATTR_UID )? + ri->uid =cpu_to_je32 ((ivalid &ATTR_UID )?from_kuid (&init_user_ns, iattr->ia_uid):i_uid_read (inode)); - ri->gid =cpu_to_je16 ((ivalid &ATTR_GID )? + ri->gid =cpu_to_je32 ((ivalid &ATTR_GID )?from_kgid (&init_user_ns, iattr->ia_gid):i_gid_read (inode));if (ivalid &ATTR_MODE )
@@ -149,8 +149,8 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) inode->i_ctime =ITIME (je32_to_cpu (ri->ctime)); inode->i_mtime =ITIME (je32_to_cpu (ri->mtime)); inode->i_mode =jemode_to_cpu (ri->mode); -i_uid_write (inode,je16_to_cpu (ri->uid)); -i_gid_write (inode,je16_to_cpu (ri->gid)); +i_uid_write (inode,je32_to_cpu (ri->uid)); +i_gid_write (inode,je32_to_cpu (ri->gid)); old_metadata = f->metadata;
@@ -276,8 +276,8 @@ struct inode *jffs2_iget(struct super_block *sb, unsigned long ino) goto error; inode->i_mode =jemode_to_cpu (latest_node.mode); -i_uid_write (inode,je16_to_cpu (latest_node.uid)); -i_gid_write (inode,je16_to_cpu (latest_node.gid)); +i_uid_write (inode,je32_to_cpu (latest_node.uid)); +i_gid_write (inode,je32_to_cpu (latest_node.gid)); inode->i_size =je32_to_cpu (latest_node.isize); inode->i_atime =ITIME (je32_to_cpu (latest_node.atime)); inode->i_mtime =ITIME (je32_to_cpu (latest_node.mtime));
@@ -441,14 +441,14 @@ struct inode *jffs2_new_inode (struct inode *dir_i, umode_t mode, struct jffs2_rmemset (ri,0 ,sizeof (*ri));/* Set OS-specific defaults for new inodes */ - ri->uid =cpu_to_je16 (from_kuid (&init_user_ns,current_fsuid ())); + ri->uid =cpu_to_je32 (from_kuid (&init_user_ns,current_fsuid ()));if (dir_i->i_mode &S_ISGID ) { - ri->gid =cpu_to_je16 (i_gid_read (dir_i)); + ri->gid =cpu_to_je32 (i_gid_read (dir_i));if (S_ISDIR (mode)) mode |=S_ISGID ; }else { - ri->gid =cpu_to_je16 (from_kgid (&init_user_ns,current_fsgid ())); + ri->gid =cpu_to_je32 (from_kgid (&init_user_ns,current_fsgid ())); }/* POSIX ACLs have to be processed now, at least partly.
@@ -470,8 +470,8 @@ struct inode *jffs2_new_inode (struct inode *dir_i, umode_t mode, struct jffs2_rset_nlink (inode,1 ); inode->i_ino =je32_to_cpu (ri->ino); inode->i_mode =jemode_to_cpu (ri->mode); -i_gid_write (inode,je16_to_cpu (ri->gid)); -i_uid_write (inode,je16_to_cpu (ri->uid)); +i_gid_write (inode,je32_to_cpu (ri->gid)); +i_uid_write (inode,je32_to_cpu (ri->uid)); inode->i_atime = inode->i_ctime = inode->i_mtime =
current_time(inode);
ri->atime = ri->mtime = ri->ctime = cpu_to_je32(I_SEC(inode->i_mtime));
fs/jffs2/gc.c +6 -6
@@ -818,8 +818,8 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_ ri.ino =cpu_to_je32 (f->inocache->ino); ri.version =cpu_to_je32 (++f->highest_version); ri.mode =cpu_to_jemode (JFFS2_F_I_MODE (f)); - ri.uid =cpu_to_je16 (JFFS2_F_I_UID (f)); - ri.gid =cpu_to_je16 (JFFS2_F_I_GID (f)); + ri.uid =cpu_to_je32 (JFFS2_F_I_UID (f)); + ri.gid =cpu_to_je32 (JFFS2_F_I_GID (f)); ri.isize =cpu_to_je32 (ilen); ri.atime =cpu_to_je32 (JFFS2_F_I_ATIME (f)); ri.ctime =cpu_to_je32 (JFFS2_F_I_CTIME (f));
@@ -1089,8 +1089,8 @@ static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eras ilen =JFFS2_F_I_SIZE (f); ri.mode =cpu_to_jemode (JFFS2_F_I_MODE (f)); - ri.uid =cpu_to_je16 (JFFS2_F_I_UID (f)); - ri.gid =cpu_to_je16 (JFFS2_F_I_GID (f)); + ri.uid =cpu_to_je32 (JFFS2_F_I_UID (f)); + ri.gid =cpu_to_je32 (JFFS2_F_I_GID (f)); ri.isize =cpu_to_je32 (ilen); ri.atime =cpu_to_je32 (JFFS2_F_I_ATIME (f)); ri.ctime =cpu_to_je32 (JFFS2_F_I_CTIME (f));
@@ -1363,8 +1363,8 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era ri.ino =cpu_to_je32 (f->inocache->ino); ri.version =cpu_to_je32 (++f->highest_version); ri.mode =cpu_to_jemode (JFFS2_F_I_MODE (f)); - ri.uid =cpu_to_je16 (JFFS2_F_I_UID (f)); - ri.gid =cpu_to_je16 (JFFS2_F_I_GID (f)); + ri.uid =cpu_to_je32 (JFFS2_F_I_UID (f)); + ri.gid =cpu_to_je32 (JFFS2_F_I_GID (f)); ri.isize =cpu_to_je32 (JFFS2_F_I_SIZE (f)); ri.atime =cpu_to_je32 (JFFS2_F_I_ATIME (f)); ri.ctime =cpu_to_je32 (JFFS2_F_I_CTIME (f));
fs/jffs2/readinode.c +0 -0
@@ -1195,8 +1195,8 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, latest_node->version =cpu_to_je32 (0 ); latest_node->atime = latest_node->ctime = latest_node->mtime =
cpu_to_je32(0);
latest_node->isize = cpu_to_je32(0);
- latest_node->gid = cpu_to_je16(0);
- latest_node->uid = cpu_to_je16(0);
+ latest_node->gid = cpu_to_je32(0);
+ latest_node->uid = cpu_to_je32(0);
if (f->inocache->state == INO_STATE_READING)
jffs2_set_inocache_state(c, f->inocache, INO_STATE_PRESENT);
return 0;fs/jffs2/super.c +1 -1
@@ -369,7 +369,7 @@ static int __init init_jffs2_fs(void)hope the structs are the right sizes, instead. */ BUILD_BUG_ON (sizeof (struct jffs2_unknown_node ) !=12 );BUILD_BUG_ON (sizeof (struct jffs2_raw_dirent ) !=40 ); -BUILD_BUG_ON (sizeof (struct jffs2_raw_inode ) !=68 ); +BUILD_BUG_ON (sizeof (struct jffs2_raw_inode ) !=72 );BUILD_BUG_ON (sizeof (struct jffs2_raw_summary ) !=32 ); pr_info("version 2.2."
include/uapi/linux/jffs2.h +2 -2
@@ -146,8 +146,8 @@ struct jffs2_raw_inodejint32_t ino;/* Inode number. */ jint32_t version;/* Version number. */ jmode_t mode;/* The file's type or mode. */ -jint16_t uid;/* The file's owner. */ -jint16_t gid;/* The file's group. */ +jint32_t uid;/* The file's owner. */ +jint32_t gid;/* The file's group. */ jint32_t isize;/* Total resultant size of this inode (used
for truncations) */
jint32_t atime; /* Last access time. */
jint32_t mtime; /* Last modification time. */
Signature · 1 line
1.9.1
David Woodhouse
maintainerQuoted 9 lines · yangshukui
(quoted diff) +0
-0@@ -146,8 +146,8 @@ struct jffs2_raw_inode
jint32_tino; /* Inode number. */jint32_tversion; /* Version number. */jmode_tmode; /* The file's type or mode. */ -jint16_tuid; /* The file's owner. */ -jint16_tgid; /* The file's group. */ +jint32_tuid; /* The file's owner. */ +jint32_tgid; /* The file's group. */
This is changing the binary data structures on the flash, and breaking compatibility with all existing file systems. Your modified kernel won't be able to mount existing JFFS2 images.
The way to do this, if we really do need 32-bit ugid support in JFFS2, is to define a *new* node (JFFS2_NODE_INCOMPAT) type, and then support reading both. You could even contrive a way to make it JFFS2_NODE_ROCOMPAT; perhaps a new node type which contains *only* the (32-bit) ownership information and overrides the 16-bit ones in the original data nodes?
PATCH 1/1 fs/jffs2: Fix a Invalid argument error when mkdir in jffs2 which is mounted as overlayfs
In reply to yangshukuiIn jffs2 filesystem, I mount a overlayfs, after rmdir and mkdir, 'Invalid argument' error will appear. It can be reproduced like this,
[root@localhost mnt]# mkdir -p overlay-mkdir [root@localhost overlay-mkdir]# pwd;mount|grep jffs2 /root/mnt/overlay-mkdir/dev/mtdblock0 on /root/mnt type jffs2 (rw,relatime)
[root@localhost mnt]# cd overlay-mkdir/
[root@localhost overlay-mkdir]# mkdir -p merged lower/hello upper work
[root@localhost overlay-mkdir]# mount -t overlay overlay -olowerdir=lower,upperdir=upper,workdir=work merged [root@localhost overlay-mkdir]# rmdir merged/hello
[root@localhost overlay-mkdir]# mkdir merged/hello
mkdir: cannot create directory merged/hello Invalid argument
From: Shukui Yang <[email protected]>
Date: Wed, 14 Jun 2017 14:03:51 +0800
Subject: [PATCH] fs/jffs2: fix a Invalid argument error when mkdir in jffs2 which is
mounted as overlayfs
--- fs/jffs2/dir.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
fs/jffs2/dir.c +8 -3
@@ -34,8 +34,8 @@ static int jffs2_symlink (struct inode *,struct dentry *,const char *);static int jffs2_mkdir (struct inode *,struct dentry *,umode_t );static int jffs2_rmdir (struct inode *,struct dentry *);static int jffs2_mknod (struct inode *,struct dentry *,umode_t ,dev_t ); -static int jffs2_rename (struct inode *,struct dentry *, -struct inode *,struct dentry *); +static int jffs2_rename2 (struct inode *,struct dentry *, +struct inode *,struct dentry *,unsigned int );const struct file_operations jffs2_dir_operations = {
@@ -57,7 +57,7 @@ const struct inode_operations jffs2_dir_inode_operations = .mkdir = jffs2_mkdir, .rmdir = jffs2_rmdir, .mknod = jffs2_mknod, - .rename = jffs2_rename, + .rename2 = jffs2_rename2, .get_acl = jffs2_get_acl, .set_acl = jffs2_set_acl, .setattr = jffs2_setattr,
@@ -865,3 +865,8 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,return 0 ; } +static int jffs2_rename2 (struct inode *old_dir_i,struct dentry *old_dentry, +struct inode *new_dir_i,struct dentry *new_dentry,unsigned int flags) +{ +return jffs2_rename (old_dir_i, old_dentry, new_dir_i, new_dentry); +}
Signature · 1 line
2.6.2
Re: [PATCH] fs/jffs2: Fix a Invalid argument error when mkdir in jffs2 which is mounted as overlayfs
.yangshukui,
Quoted 45 lines · yangshukui
In jffs2 filesystem, I mount a overlayfs, after rmdir and mkdir, 'Invalid argument' error will appear.
It can be reproduced like this,[root@localhost mnt]# mkdir -p overlay-mkdir [root@localhost overlay-mkdir]# pwd;mount|grep jffs2
/root/mnt/overlay-mkdir/dev/mtdblock0on/root/mnttype jffs2 (rw,relatime)[root@localhost mnt]# cd overlay-mkdir/
[root@localhost overlay-mkdir]# mkdir -p merged lower/hello upper work [root@localhost overlay-mkdir]# mount -t overlay overlay -olowerdir=lower,upperdir=upper,workdir=work merged [root@localhost overlay-mkdir]# rmdir merged/hello [root@localhost overlay-mkdir]# mkdir merged/hello
mkdir: cannot create directory merged/hello Invalid argumentFrom: Shukui Yang <[email protected]>
Date: Wed, 14 Jun 2017 14:03:51 +0800
Subject: [PATCH] fs/jffs2: fix a Invalid argument error when mkdir in jffs2 which is
mounted as overlayfsSigned-off-by Shukui Yang <[email protected]>--- fs/jffs2/dir.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)fs/jffs2/dir.c +2
-2@@ -34,8 +34,8 @@ static int jffs2_symlink (struct inode *,struct dentry *,const char *);static int jffs2_mkdir (struct inode *,struct dentry *,umode_t );static int jffs2_rmdir (struct inode *,struct dentry *);static int jffs2_mknod (struct inode *,struct dentry *,umode_t ,dev_t ); -static int jffs2_rename (struct inode *,struct dentry *, -struct inode *,struct dentry *); +static int jffs2_rename2 (struct inode *,struct dentry *, +struct inode *,struct dentry *,unsigned int ); const struct file_operations jffs2_dir_operations ={
fs/jffs2/dir.c const struct inode_operations jffs2_dir_inode_operations = · line 60
Quoted 5 lines
fs/jffs2/dir.c +1
-1@@ -57,7 +57,7 @@ const struct inode_operations jffs2_dir_inode_operations = .mkdir = jffs2_mkdir, .rmdir = jffs2_rmdir, .mknod = jffs2_mknod, - .rename = jffs2_rename, + .rename2 = jffs2_rename2,
->rename2 is no longer available, did you develop against an old kernel?
Quoted 12 lines
fs/jffs2/dir.c +1
-0.get_acl = jffs2_get_acl, .set_acl = jffs2_set_acl, .setattr = jffs2_setattr,@@ -865,3 +865,8 @@ static int jffs2_rename (struct inode *old_dir_i, structdentry *old_dentry, return 0; } +static int jffs2_rename2 (struct inode *old_dir_i, struct dentry
*old_dentry,
+ struct inode*new_dir_i, struct dentry*new_dentry,
unsigned int flags)
fs/jffs2/dir.c static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, · line 872
Quoted 3 lines
fs/jffs2/dir.c +3
-0+{ +return jffs2_rename (old_dir_i, old_dentry, new_dir_i, new_dentry); +}
I fear this is not correct. You cannot ignore rename flags. For proper overlayfs support you need to implement RENAME_WHITEOUT and RENAME_EXCHANGE features.
Signature · 2 lines
Thanks, //richard