Commit 07b71f8c authored by Andrew Morton's avatar Andrew Morton Committed by David Mosberger

[PATCH] hugetlbfs: mount options and permissions

From: "Seth, Rohit" <rohit.seth@intel.com>

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).
parent 1e559269
...@@ -67,15 +67,22 @@ If the user applications are going to request hugepages using mmap system ...@@ -67,15 +67,22 @@ If the user applications are going to request hugepages using mmap system
call, then it is required that system administrator mount a file system of call, then it is required that system administrator mount a file system of
type hugetlbfs: type hugetlbfs:
mount none /mnt/huge -t hugetlbfs mount none /mnt/huge -t hugetlbfs <uid=value> <gid=value> <mode=value>
This command mounts a (pseudo) filesystem of type hugetlbfs on the directory 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 /mnt/huge. Any files created on /mnt/huge uses hugepages. The uid and gid
given at the end of this document. 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 read and write system calls are not supported on files that reside on hugetlb
file systems. 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 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 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* for same or different applications to use any combination of mmaps and shm*
......
...@@ -48,9 +48,6 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma) ...@@ -48,9 +48,6 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
loff_t len; loff_t len;
int ret; int ret;
if (!capable(CAP_IPC_LOCK))
return -EPERM;
if (vma->vm_start & ~HPAGE_MASK) if (vma->vm_start & ~HPAGE_MASK)
return -EINVAL; return -EINVAL;
...@@ -231,6 +228,7 @@ static void hugetlbfs_forget_inode(struct inode *inode) ...@@ -231,6 +228,7 @@ static void hugetlbfs_forget_inode(struct inode *inode)
spin_unlock(&inode_lock); spin_unlock(&inode_lock);
if (inode->i_data.nrpages) if (inode->i_data.nrpages)
truncate_hugepages(&inode->i_data, 0); truncate_hugepages(&inode->i_data, 0);
clear_inode(inode); clear_inode(inode);
destroy_inode(inode); destroy_inode(inode);
} }
...@@ -317,7 +315,6 @@ static int hugetlbfs_setattr(struct dentry *dentry, struct iattr *attr) ...@@ -317,7 +315,6 @@ static int hugetlbfs_setattr(struct dentry *dentry, struct iattr *attr)
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
int error; int error;
unsigned int ia_valid = attr->ia_valid; unsigned int ia_valid = attr->ia_valid;
unsigned long dn_mask;
BUG_ON(!inode); BUG_ON(!inode);
...@@ -335,26 +332,21 @@ static int hugetlbfs_setattr(struct dentry *dentry, struct iattr *attr) ...@@ -335,26 +332,21 @@ static int hugetlbfs_setattr(struct dentry *dentry, struct iattr *attr)
if (error) if (error)
goto out; goto out;
attr->ia_valid &= ~ATTR_SIZE; attr->ia_valid &= ~ATTR_SIZE;
error = inode_setattr(inode, attr);
} }
if (error) error = inode_setattr(inode, attr);
goto out;
dn_mask = setattr_mask(ia_valid);
if (dn_mask)
dnotify_parent(dentry, dn_mask);
out: out:
return error; return error;
} }
static struct inode *hugetlbfs_get_inode(struct super_block *sb, static struct inode *hugetlbfs_get_inode(struct super_block *sb, uid_t uid,
int mode, dev_t dev) gid_t gid, int mode, dev_t dev)
{ {
struct inode * inode = new_inode(sb); struct inode * inode = new_inode(sb);
if (inode) { if (inode) {
inode->i_mode = mode; inode->i_mode = mode;
inode->i_uid = current->fsuid; inode->i_uid = uid;
inode->i_gid = current->fsgid; inode->i_gid = gid;
inode->i_blksize = PAGE_CACHE_SIZE; inode->i_blksize = PAGE_CACHE_SIZE;
inode->i_blocks = 0; inode->i_blocks = 0;
inode->i_rdev = NODEV; inode->i_rdev = NODEV;
...@@ -391,7 +383,8 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb, ...@@ -391,7 +383,8 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb,
static int hugetlbfs_mknod(struct inode *dir, static int hugetlbfs_mknod(struct inode *dir,
struct dentry *dentry, int mode, dev_t dev) 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; int error = -ENOSPC;
if (inode) { if (inode) {
...@@ -421,7 +414,8 @@ static int hugetlbfs_symlink(struct inode *dir, ...@@ -421,7 +414,8 @@ static int hugetlbfs_symlink(struct inode *dir,
struct inode *inode; struct inode *inode;
int error = -ENOSPC; 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) { if (inode) {
int l = strlen(symname)+1; int l = strlen(symname)+1;
error = page_symlink(inode, symname, l); error = page_symlink(inode, symname, l);
...@@ -478,16 +472,68 @@ static struct super_operations hugetlbfs_ops = { ...@@ -478,16 +472,68 @@ static struct super_operations hugetlbfs_ops = {
}; };
static int 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 inode * inode;
struct dentry * root; 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 = PAGE_CACHE_SIZE;
sb->s_blocksize_bits = PAGE_CACHE_SHIFT; sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
sb->s_magic = HUGETLBFS_MAGIC; sb->s_magic = HUGETLBFS_MAGIC;
sb->s_op = &hugetlbfs_ops; 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) if (!inode)
return -ENOMEM; return -ENOMEM;
...@@ -548,7 +594,8 @@ struct file *hugetlb_zero_setup(size_t size) ...@@ -548,7 +594,8 @@ struct file *hugetlb_zero_setup(size_t size)
goto out_dentry; goto out_dentry;
error = -ENOSPC; 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) if (!inode)
goto out_file; goto out_file;
......
...@@ -72,6 +72,12 @@ static inline int is_vm_hugetlb_page(struct vm_area_struct *vma) ...@@ -72,6 +72,12 @@ static inline int is_vm_hugetlb_page(struct vm_area_struct *vma)
#endif /* !CONFIG_HUGETLB_PAGE */ #endif /* !CONFIG_HUGETLB_PAGE */
#ifdef CONFIG_HUGETLBFS #ifdef CONFIG_HUGETLBFS
struct hugetlbfs_config {
uid_t uid;
gid_t gid;
umode_t mode;
};
extern struct file_operations hugetlbfs_file_operations; extern struct file_operations hugetlbfs_file_operations;
extern struct vm_operations_struct hugetlb_vm_ops; extern struct vm_operations_struct hugetlb_vm_ops;
struct file *hugetlb_zero_setup(size_t); struct file *hugetlb_zero_setup(size_t);
......
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