JFS: add uid, gid, and umask mount options
authorDave Kleikamp <shaggy@austin.ibm.com>
Thu, 9 Mar 2006 19:59:30 +0000 (13:59 -0600)
committerDave Kleikamp <shaggy@austin.ibm.com>
Thu, 9 Mar 2006 19:59:30 +0000 (13:59 -0600)
OS/2 doesn't initialize the uid, gid, or unix-style permission bits.  The
uid, gid, & umask mount options perform pretty much like those for the fat
file system, overriding what is stored on disk.  This is useful for users
sharing the file system with OS/2.

I implemented a little feature so that if you mask the execute bit, it
will be re-enabled on directories when the appropriate read bit is unmasked.
I didn't want to implement an fmask & dmask option.

Signed-off-by: Dave Kleikamp <shaggy@austin.ibm.com>
fs/jfs/acl.c
fs/jfs/jfs_imap.c
fs/jfs/jfs_incore.h
fs/jfs/jfs_inode.c
fs/jfs/super.c

index e0b6fdab200ce1c34d55d9e914e8b082ed966fd7..e2281300979c7b2c5e09287e28364bb25733c648 100644 (file)
@@ -183,6 +183,9 @@ cleanup:
                posix_acl_release(acl);
        } else
                inode->i_mode &= ~current->fs->umask;
+       
+       JFS_IP(inode)->mode2 = (JFS_IP(inode)->mode2 & 0xffff0000) |
+                              inode->i_mode;
 
        return rc;
 }
index b62a048b6881a0a309db7a6e90cf34d63bdce0ae..ccbe60aff83de64edddc27381e020c83240adb1b 100644 (file)
@@ -3074,14 +3074,40 @@ static void duplicateIXtree(struct super_block *sb, s64 blkno,
 static int copy_from_dinode(struct dinode * dip, struct inode *ip)
 {
        struct jfs_inode_info *jfs_ip = JFS_IP(ip);
+       struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb);
 
        jfs_ip->fileset = le32_to_cpu(dip->di_fileset);
        jfs_ip->mode2 = le32_to_cpu(dip->di_mode);
 
        ip->i_mode = le32_to_cpu(dip->di_mode) & 0xffff;
+       if (sbi->umask != -1) {
+               ip->i_mode = (ip->i_mode & ~0777) | (0777 & ~sbi->umask);
+               /* For directories, add x permission if r is allowed by umask */
+               if (S_ISDIR(ip->i_mode)) {
+                       if (ip->i_mode & 0400)
+                               ip->i_mode |= 0100;
+                       if (ip->i_mode & 0040)
+                               ip->i_mode |= 0010;
+                       if (ip->i_mode & 0004)
+                               ip->i_mode |= 0001;
+               }
+       }
        ip->i_nlink = le32_to_cpu(dip->di_nlink);
-       ip->i_uid = le32_to_cpu(dip->di_uid);
-       ip->i_gid = le32_to_cpu(dip->di_gid);
+
+       jfs_ip->saved_uid = le32_to_cpu(dip->di_uid);
+       if (sbi->uid == -1)
+               ip->i_uid = jfs_ip->saved_uid;
+       else {
+               ip->i_uid = sbi->uid;
+       }
+
+       jfs_ip->saved_gid = le32_to_cpu(dip->di_gid);
+       if (sbi->gid == -1)
+               ip->i_gid = jfs_ip->saved_gid;
+       else {
+               ip->i_gid = sbi->gid;
+       }
+
        ip->i_size = le64_to_cpu(dip->di_size);
        ip->i_atime.tv_sec = le32_to_cpu(dip->di_atime.tv_sec);
        ip->i_atime.tv_nsec = le32_to_cpu(dip->di_atime.tv_nsec);
@@ -3132,21 +3158,33 @@ static int copy_from_dinode(struct dinode * dip, struct inode *ip)
 static void copy_to_dinode(struct dinode * dip, struct inode *ip)
 {
        struct jfs_inode_info *jfs_ip = JFS_IP(ip);
+       struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb);
 
        dip->di_fileset = cpu_to_le32(jfs_ip->fileset);
-       dip->di_inostamp = cpu_to_le32(JFS_SBI(ip->i_sb)->inostamp);
+       dip->di_inostamp = cpu_to_le32(sbi->inostamp);
        dip->di_number = cpu_to_le32(ip->i_ino);
        dip->di_gen = cpu_to_le32(ip->i_generation);
        dip->di_size = cpu_to_le64(ip->i_size);
        dip->di_nblocks = cpu_to_le64(PBLK2LBLK(ip->i_sb, ip->i_blocks));
        dip->di_nlink = cpu_to_le32(ip->i_nlink);
-       dip->di_uid = cpu_to_le32(ip->i_uid);
-       dip->di_gid = cpu_to_le32(ip->i_gid);
+       if (sbi->uid == -1)
+               dip->di_uid = cpu_to_le32(ip->i_uid);
+       else
+               dip->di_uid = cpu_to_le32(jfs_ip->saved_uid);
+       if (sbi->gid == -1)
+               dip->di_gid = cpu_to_le32(ip->i_gid);
+       else
+               dip->di_gid = cpu_to_le32(jfs_ip->saved_gid);
        /*
         * mode2 is only needed for storing the higher order bits.
         * Trust i_mode for the lower order ones
         */
-       dip->di_mode = cpu_to_le32((jfs_ip->mode2 & 0xffff0000) | ip->i_mode);
+       if (sbi->umask == -1)
+               dip->di_mode = cpu_to_le32((jfs_ip->mode2 & 0xffff0000) |
+                                          ip->i_mode);
+       else /* Leave the original permissions alone */
+               dip->di_mode = cpu_to_le32(jfs_ip->mode2);
+
        dip->di_atime.tv_sec = cpu_to_le32(ip->i_atime.tv_sec);
        dip->di_atime.tv_nsec = cpu_to_le32(ip->i_atime.tv_nsec);
        dip->di_ctime.tv_sec = cpu_to_le32(ip->i_ctime.tv_sec);
index a97ead889a68beb2671f5a1c054671973ba7a77c..54d73716ca8c4dfbed653ae6e0c0df29dcb6da96 100644 (file)
@@ -38,6 +38,8 @@
 struct jfs_inode_info {
        int     fileset;        /* fileset number (always 16)*/
        uint    mode2;          /* jfs-specific mode            */
+       uint    saved_uid;      /* saved for uid mount option */
+       uint    saved_gid;      /* saved for gid mount option */
        pxd_t   ixpxd;          /* inode extent descriptor      */
        dxd_t   acl;            /* dxd describing acl   */
        dxd_t   ea;             /* dxd describing ea    */
@@ -170,6 +172,9 @@ struct jfs_sb_info {
        uint            state;          /* mount/recovery state */
        unsigned long   flag;           /* mount time flags */
        uint            p_state;        /* state prior to going no integrity */
+       uint            uid;            /* uid to override on-disk uid */
+       uint            gid;            /* gid to override on-disk gid */
+       uint            umask;          /* umask to override on-disk umask */
 };
 
 /* jfs_sb_info commit_state */
index ffd2a8a007871872dff7b20510dc274046aed5bf..495df402916dbf5d3ff77415aec2085e9f50daf8 100644 (file)
@@ -82,6 +82,13 @@ struct inode *ialloc(struct inode *parent, umode_t mode)
        } else
                inode->i_gid = current->fsgid;
 
+       /*
+        * New inodes need to save sane values on disk when
+        * uid & gid mount options are used
+        */
+       jfs_inode->saved_uid = inode->i_uid;
+       jfs_inode->saved_gid = inode->i_gid;
+
        /*
         * Allocate inode to quota.
         */
index ab63333470042e7874c58f8004c15ccb1ceccac6..18f69e6aa719358e793c31745cd1831b4eded107 100644 (file)
@@ -194,7 +194,7 @@ static void jfs_put_super(struct super_block *sb)
 enum {
        Opt_integrity, Opt_nointegrity, Opt_iocharset, Opt_resize,
        Opt_resize_nosize, Opt_errors, Opt_ignore, Opt_err, Opt_quota,
-       Opt_usrquota, Opt_grpquota
+       Opt_usrquota, Opt_grpquota, Opt_uid, Opt_gid, Opt_umask
 };
 
 static match_table_t tokens = {
@@ -208,6 +208,9 @@ static match_table_t tokens = {
        {Opt_ignore, "quota"},
        {Opt_usrquota, "usrquota"},
        {Opt_grpquota, "grpquota"},
+       {Opt_uid, "uid=%u"},
+       {Opt_gid, "gid=%u"},
+       {Opt_umask, "umask=%u"},
        {Opt_err, NULL}
 };
 
@@ -312,7 +315,29 @@ static int parse_options(char *options, struct super_block *sb, s64 *newLVSize,
                               "JFS: quota operations not supported\n");
                        break;
 #endif
-
+               case Opt_uid:
+               {
+                       char *uid = args[0].from;
+                       sbi->uid = simple_strtoul(uid, &uid, 0);
+                       break;
+               }
+               case Opt_gid:
+               {
+                       char *gid = args[0].from;
+                       sbi->gid = simple_strtoul(gid, &gid, 0);
+                       break;
+               }
+               case Opt_umask:
+               {
+                       char *umask = args[0].from;
+                       sbi->umask = simple_strtoul(umask, &umask, 8);
+                       if (sbi->umask & ~0777) {
+                               printk(KERN_ERR
+                                      "JFS: Invalid value of umask\n");
+                               goto cleanup;
+                       }
+                       break;
+               }
                default:
                        printk("jfs: Unrecognized mount option \"%s\" "
                                        " or missing value\n", p);
@@ -400,6 +425,7 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent)
                return -ENOSPC;
        sb->s_fs_info = sbi;
        sbi->sb = sb;
+       sbi->uid = sbi->gid = sbi->umask = -1;
 
        /* initialize the mount flag and determine the default error handler */
        flag = JFS_ERR_REMOUNT_RO;
@@ -562,10 +588,14 @@ static int jfs_show_options(struct seq_file *seq, struct vfsmount *vfs)
 {
        struct jfs_sb_info *sbi = JFS_SBI(vfs->mnt_sb);
 
+       if (sbi->uid != -1)
+               seq_printf(seq, ",uid=%d", sbi->uid);
+       if (sbi->gid != -1)
+               seq_printf(seq, ",gid=%d", sbi->gid);
+       if (sbi->umask != -1)
+               seq_printf(seq, ",umask=%03o", sbi->umask);
        if (sbi->flag & JFS_NOINTEGRITY)
                seq_puts(seq, ",nointegrity");
-       else
-               seq_puts(seq, ",integrity");
 
 #if defined(CONFIG_QUOTA)
        if (sbi->flag & JFS_USRQUOTA)