Commit 69eb66d7 authored by Dave Kleikamp's avatar Dave Kleikamp

JFS: add uid, gid, and umask mount options

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: default avatarDave Kleikamp <shaggy@austin.ibm.com>
parent be0bf7da
...@@ -183,6 +183,9 @@ cleanup: ...@@ -183,6 +183,9 @@ cleanup:
posix_acl_release(acl); posix_acl_release(acl);
} else } else
inode->i_mode &= ~current->fs->umask; inode->i_mode &= ~current->fs->umask;
JFS_IP(inode)->mode2 = (JFS_IP(inode)->mode2 & 0xffff0000) |
inode->i_mode;
return rc; return rc;
} }
......
...@@ -3074,14 +3074,40 @@ static void duplicateIXtree(struct super_block *sb, s64 blkno, ...@@ -3074,14 +3074,40 @@ static void duplicateIXtree(struct super_block *sb, s64 blkno,
static int copy_from_dinode(struct dinode * dip, struct inode *ip) static int copy_from_dinode(struct dinode * dip, struct inode *ip)
{ {
struct jfs_inode_info *jfs_ip = JFS_IP(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->fileset = le32_to_cpu(dip->di_fileset);
jfs_ip->mode2 = le32_to_cpu(dip->di_mode); jfs_ip->mode2 = le32_to_cpu(dip->di_mode);
ip->i_mode = le32_to_cpu(dip->di_mode) & 0xffff; 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_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_size = le64_to_cpu(dip->di_size);
ip->i_atime.tv_sec = le32_to_cpu(dip->di_atime.tv_sec); 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); 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) ...@@ -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) static void copy_to_dinode(struct dinode * dip, struct inode *ip)
{ {
struct jfs_inode_info *jfs_ip = JFS_IP(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_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_number = cpu_to_le32(ip->i_ino);
dip->di_gen = cpu_to_le32(ip->i_generation); dip->di_gen = cpu_to_le32(ip->i_generation);
dip->di_size = cpu_to_le64(ip->i_size); dip->di_size = cpu_to_le64(ip->i_size);
dip->di_nblocks = cpu_to_le64(PBLK2LBLK(ip->i_sb, ip->i_blocks)); dip->di_nblocks = cpu_to_le64(PBLK2LBLK(ip->i_sb, ip->i_blocks));
dip->di_nlink = cpu_to_le32(ip->i_nlink); dip->di_nlink = cpu_to_le32(ip->i_nlink);
dip->di_uid = cpu_to_le32(ip->i_uid); if (sbi->uid == -1)
dip->di_gid = cpu_to_le32(ip->i_gid); 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. * mode2 is only needed for storing the higher order bits.
* Trust i_mode for the lower order ones * 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_sec = cpu_to_le32(ip->i_atime.tv_sec);
dip->di_atime.tv_nsec = cpu_to_le32(ip->i_atime.tv_nsec); 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); dip->di_ctime.tv_sec = cpu_to_le32(ip->i_ctime.tv_sec);
......
...@@ -38,6 +38,8 @@ ...@@ -38,6 +38,8 @@
struct jfs_inode_info { struct jfs_inode_info {
int fileset; /* fileset number (always 16)*/ int fileset; /* fileset number (always 16)*/
uint mode2; /* jfs-specific mode */ 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 */ pxd_t ixpxd; /* inode extent descriptor */
dxd_t acl; /* dxd describing acl */ dxd_t acl; /* dxd describing acl */
dxd_t ea; /* dxd describing ea */ dxd_t ea; /* dxd describing ea */
...@@ -170,6 +172,9 @@ struct jfs_sb_info { ...@@ -170,6 +172,9 @@ struct jfs_sb_info {
uint state; /* mount/recovery state */ uint state; /* mount/recovery state */
unsigned long flag; /* mount time flags */ unsigned long flag; /* mount time flags */
uint p_state; /* state prior to going no integrity */ 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 */ /* jfs_sb_info commit_state */
......
...@@ -82,6 +82,13 @@ struct inode *ialloc(struct inode *parent, umode_t mode) ...@@ -82,6 +82,13 @@ struct inode *ialloc(struct inode *parent, umode_t mode)
} else } else
inode->i_gid = current->fsgid; 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. * Allocate inode to quota.
*/ */
......
...@@ -194,7 +194,7 @@ static void jfs_put_super(struct super_block *sb) ...@@ -194,7 +194,7 @@ static void jfs_put_super(struct super_block *sb)
enum { enum {
Opt_integrity, Opt_nointegrity, Opt_iocharset, Opt_resize, Opt_integrity, Opt_nointegrity, Opt_iocharset, Opt_resize,
Opt_resize_nosize, Opt_errors, Opt_ignore, Opt_err, Opt_quota, 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 = { static match_table_t tokens = {
...@@ -208,6 +208,9 @@ static match_table_t tokens = { ...@@ -208,6 +208,9 @@ static match_table_t tokens = {
{Opt_ignore, "quota"}, {Opt_ignore, "quota"},
{Opt_usrquota, "usrquota"}, {Opt_usrquota, "usrquota"},
{Opt_grpquota, "grpquota"}, {Opt_grpquota, "grpquota"},
{Opt_uid, "uid=%u"},
{Opt_gid, "gid=%u"},
{Opt_umask, "umask=%u"},
{Opt_err, NULL} {Opt_err, NULL}
}; };
...@@ -312,7 +315,29 @@ static int parse_options(char *options, struct super_block *sb, s64 *newLVSize, ...@@ -312,7 +315,29 @@ static int parse_options(char *options, struct super_block *sb, s64 *newLVSize,
"JFS: quota operations not supported\n"); "JFS: quota operations not supported\n");
break; break;
#endif #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: default:
printk("jfs: Unrecognized mount option \"%s\" " printk("jfs: Unrecognized mount option \"%s\" "
" or missing value\n", p); " or missing value\n", p);
...@@ -400,6 +425,7 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -400,6 +425,7 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent)
return -ENOSPC; return -ENOSPC;
sb->s_fs_info = sbi; sb->s_fs_info = sbi;
sbi->sb = sb; sbi->sb = sb;
sbi->uid = sbi->gid = sbi->umask = -1;
/* initialize the mount flag and determine the default error handler */ /* initialize the mount flag and determine the default error handler */
flag = JFS_ERR_REMOUNT_RO; flag = JFS_ERR_REMOUNT_RO;
...@@ -562,10 +588,14 @@ static int jfs_show_options(struct seq_file *seq, struct vfsmount *vfs) ...@@ -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); 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) if (sbi->flag & JFS_NOINTEGRITY)
seq_puts(seq, ",nointegrity"); seq_puts(seq, ",nointegrity");
else
seq_puts(seq, ",integrity");
#if defined(CONFIG_QUOTA) #if defined(CONFIG_QUOTA)
if (sbi->flag & JFS_USRQUOTA) if (sbi->flag & JFS_USRQUOTA)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment