From: "Seth, Rohit" This patch enables system administrators to more flexibly assign read/write permissions to files in hugetlbfs. Mount options are added which will specify the uid, gid and mode of the filesystem's root directory. This patch also enables super users to do chown/chgrp on files in hugetlbfs. Also included in this patch is the support for uid, gid and mode command line options for mount command for hugetlbfs. The following mount options are added to hugetlbfs: uid=value gid=value mode=value The values may be specified in hex (0xNNN), decimal or octal (0NNN). Documentation/vm/hugetlbpage.txt | 13 ++++- fs/hugetlbfs/inode.c | 85 ++++++++++++++++++++++++++++++--------- include/linux/hugetlb.h | 6 ++ 3 files changed, 82 insertions(+), 22 deletions(-) diff -puN fs/hugetlbfs/inode.c~hugetlbfs-mount-options fs/hugetlbfs/inode.c --- 25/fs/hugetlbfs/inode.c~hugetlbfs-mount-options 2003-05-31 20:19:16.000000000 -0700 +++ 25-akpm/fs/hugetlbfs/inode.c 2003-05-31 20:19:16.000000000 -0700 @@ -48,9 +48,6 @@ static int hugetlbfs_file_mmap(struct fi loff_t len; int ret; - if (!capable(CAP_IPC_LOCK)) - return -EPERM; - if (vma->vm_start & ~HPAGE_MASK) return -EINVAL; @@ -231,6 +228,7 @@ out_truncate: spin_unlock(&inode_lock); if (inode->i_data.nrpages) truncate_hugepages(&inode->i_data, 0); + clear_inode(inode); destroy_inode(inode); } @@ -317,7 +315,6 @@ static int hugetlbfs_setattr(struct dent struct inode *inode = dentry->d_inode; int error; unsigned int ia_valid = attr->ia_valid; - unsigned long dn_mask; BUG_ON(!inode); @@ -335,26 +332,21 @@ static int hugetlbfs_setattr(struct dent if (error) goto out; attr->ia_valid &= ~ATTR_SIZE; - error = inode_setattr(inode, attr); } - if (error) - goto out; - dn_mask = setattr_mask(ia_valid); - if (dn_mask) - dnotify_parent(dentry, dn_mask); + error = inode_setattr(inode, attr); out: return error; } -static struct inode *hugetlbfs_get_inode(struct super_block *sb, - int mode, dev_t dev) +static struct inode *hugetlbfs_get_inode(struct super_block *sb, uid_t uid, + gid_t gid, int mode, dev_t dev) { struct inode * inode = new_inode(sb); if (inode) { inode->i_mode = mode; - inode->i_uid = current->fsuid; - inode->i_gid = current->fsgid; + inode->i_uid = uid; + inode->i_gid = gid; inode->i_blksize = PAGE_CACHE_SIZE; inode->i_blocks = 0; inode->i_rdev = NODEV; @@ -391,7 +383,8 @@ static struct inode *hugetlbfs_get_inode static int hugetlbfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) { - struct inode * inode = hugetlbfs_get_inode(dir->i_sb, mode, dev); + struct inode * inode = hugetlbfs_get_inode(dir->i_sb, current->fsuid, + current->fsgid, mode, dev); int error = -ENOSPC; if (inode) { @@ -421,7 +414,8 @@ static int hugetlbfs_symlink(struct inod struct inode *inode; int error = -ENOSPC; - inode = hugetlbfs_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0); + inode = hugetlbfs_get_inode(dir->i_sb, current->fsuid, + current->fsgid, S_IFLNK|S_IRWXUGO, 0); if (inode) { int l = strlen(symname)+1; error = page_symlink(inode, symname, l); @@ -478,16 +472,68 @@ static struct super_operations hugetlbfs }; static int -hugetlbfs_fill_super(struct super_block * sb, void * data, int silent) +hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig) +{ + char *opt, *value; + int ret = 0; + + if (!options) + goto out; + while ((opt = strsep(&options, ",")) != NULL) { + if (!*opt) + continue; + + value = strchr(opt, '='); + if (!value || !*value) { + ret = -EINVAL; + goto out; + } else { + *value++ = '\0'; + } + + if (!strcmp(opt, "uid")) + pconfig->uid = simple_strtoul(value, &value, 0); + else if (!strcmp(opt, "gid")) + pconfig->gid = simple_strtoul(value, &value, 0); + else if (!strcmp(opt, "mode")) + pconfig->mode = simple_strtoul(value,&value,0) & 0777U; + else { + ret = -EINVAL; + goto out; + } + + if (*value) { + ret = -EINVAL; + goto out; + } + } + return 0; +out: + pconfig->uid = current->fsuid; + pconfig->gid = current->fsgid; + pconfig->mode = 0755; + return ret; +} + +static int +hugetlbfs_fill_super(struct super_block *sb, void *data, int silent) { struct inode * inode; struct dentry * root; + int ret; + struct hugetlbfs_config config; + ret = hugetlbfs_parse_options(data, &config); + if (ret) { + printk("hugetlbfs: invalid mount options: %s.\n", data); + return ret; + } sb->s_blocksize = PAGE_CACHE_SIZE; sb->s_blocksize_bits = PAGE_CACHE_SHIFT; sb->s_magic = HUGETLBFS_MAGIC; sb->s_op = &hugetlbfs_ops; - inode = hugetlbfs_get_inode(sb, S_IFDIR | 0755, 0); + inode = hugetlbfs_get_inode(sb, config.uid, config.gid, + S_IFDIR | config.mode, 0); if (!inode) return -ENOMEM; @@ -548,7 +594,8 @@ struct file *hugetlb_zero_setup(size_t s goto out_dentry; error = -ENOSPC; - inode = hugetlbfs_get_inode(root->d_sb, S_IFREG | S_IRWXUGO, 0); + inode = hugetlbfs_get_inode(root->d_sb, current->fsuid, + current->fsgid, S_IFREG | S_IRWXUGO, 0); if (!inode) goto out_file; diff -puN include/linux/hugetlb.h~hugetlbfs-mount-options include/linux/hugetlb.h --- 25/include/linux/hugetlb.h~hugetlbfs-mount-options 2003-05-31 20:19:16.000000000 -0700 +++ 25-akpm/include/linux/hugetlb.h 2003-05-31 20:19:16.000000000 -0700 @@ -72,6 +72,12 @@ static inline int is_vm_hugetlb_page(str #endif /* !CONFIG_HUGETLB_PAGE */ #ifdef CONFIG_HUGETLBFS +struct hugetlbfs_config { + uid_t uid; + gid_t gid; + umode_t mode; +}; + extern struct file_operations hugetlbfs_file_operations; extern struct vm_operations_struct hugetlb_vm_ops; struct file *hugetlb_zero_setup(size_t); diff -puN Documentation/vm/hugetlbpage.txt~hugetlbfs-mount-options Documentation/vm/hugetlbpage.txt --- 25/Documentation/vm/hugetlbpage.txt~hugetlbfs-mount-options 2003-05-31 20:19:16.000000000 -0700 +++ 25-akpm/Documentation/vm/hugetlbpage.txt 2003-05-31 20:19:16.000000000 -0700 @@ -67,15 +67,22 @@ If the user applications are going to re call, then it is required that system administrator mount a file system of type hugetlbfs: - mount none /mnt/huge -t hugetlbfs + mount none /mnt/huge -t hugetlbfs This command mounts a (pseudo) filesystem of type hugetlbfs on the directory -/mnt/huge. Any files created on /mnt/huge uses hugepages. An example is -given at the end of this document. +/mnt/huge. Any files created on /mnt/huge uses hugepages. The uid and gid +options sets the owner and group of the root of the file system. By default +the uid and gid of the current process are taken. The mode option sets the +mode of root of file system to value & 0777. This value is given in octal. +By default the value 0755 is picked. An example is given at the end of this +document. read and write system calls are not supported on files that reside on hugetlb file systems. +A regular chown, chgrp and chmod commands (with right permissions) could be +used to change the file attributes on hugetlbfs. + Also, it is important to note that no such mount command is required if the applications are going to use only shmat/shmget system calls. It is possible for same or different applications to use any combination of mmaps and shm* _