hugetlbfs: add O_TMPFILE support
With hugetlbfs, a common pattern for mapping anonymous huge pages is to create a temporary file first. Currently libraries like libhugetlbfs and seastar create these with a standard mkstemp+unlink trick, but it would be more robust to be able to simply pass the O_TMPFILE flag to open(). O_TMPFILE is already supported by several file systems like ext4 and xfs. The implementation simply uses the existi= ng d_tmpfile utility function to instantiate the dcache entry for the file. Tested manually by successfully creating a temporary file by opening it with (O_TMPFILE|O_RDWR) on mounted hugetlbfs and successfully mapping 2M huge pages with it. Without the patch, trying to open a file with O_TMPFILE results in -ENOSUP. Link: http://lkml.kernel.org/r/bc9383eff6e1374d79f3a92257ae829ba1e6ae60.1573285189.git.p.sarna@tlen.pl Signed-off-by: Piotr Sarna <p.sarna@tlen.pl> Reviewed-by: Mike Kravetz <mike.kravetz@oracle.com> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: Michal Hocko <mhocko@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Родитель
1f9dccb25b
Коммит
1ab5b82f54
|
@ -815,8 +815,11 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb,
|
|||
/*
|
||||
* File creation. Allocate an inode, and we're done..
|
||||
*/
|
||||
static int hugetlbfs_mknod(struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, dev_t dev)
|
||||
static int do_hugetlbfs_mknod(struct inode *dir,
|
||||
struct dentry *dentry,
|
||||
umode_t mode,
|
||||
dev_t dev,
|
||||
bool tmpfile)
|
||||
{
|
||||
struct inode *inode;
|
||||
int error = -ENOSPC;
|
||||
|
@ -824,13 +827,23 @@ static int hugetlbfs_mknod(struct inode *dir,
|
|||
inode = hugetlbfs_get_inode(dir->i_sb, dir, mode, dev);
|
||||
if (inode) {
|
||||
dir->i_ctime = dir->i_mtime = current_time(dir);
|
||||
d_instantiate(dentry, inode);
|
||||
dget(dentry); /* Extra count - pin the dentry in core */
|
||||
if (tmpfile) {
|
||||
d_tmpfile(dentry, inode);
|
||||
} else {
|
||||
d_instantiate(dentry, inode);
|
||||
dget(dentry);/* Extra count - pin the dentry in core */
|
||||
}
|
||||
error = 0;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
static int hugetlbfs_mknod(struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, dev_t dev)
|
||||
{
|
||||
return do_hugetlbfs_mknod(dir, dentry, mode, dev, false);
|
||||
}
|
||||
|
||||
static int hugetlbfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
int retval = hugetlbfs_mknod(dir, dentry, mode | S_IFDIR, 0);
|
||||
|
@ -844,6 +857,12 @@ static int hugetlbfs_create(struct inode *dir, struct dentry *dentry, umode_t mo
|
|||
return hugetlbfs_mknod(dir, dentry, mode | S_IFREG, 0);
|
||||
}
|
||||
|
||||
static int hugetlbfs_tmpfile(struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
return do_hugetlbfs_mknod(dir, dentry, mode | S_IFREG, 0, true);
|
||||
}
|
||||
|
||||
static int hugetlbfs_symlink(struct inode *dir,
|
||||
struct dentry *dentry, const char *symname)
|
||||
{
|
||||
|
@ -1102,6 +1121,7 @@ static const struct inode_operations hugetlbfs_dir_inode_operations = {
|
|||
.mknod = hugetlbfs_mknod,
|
||||
.rename = simple_rename,
|
||||
.setattr = hugetlbfs_setattr,
|
||||
.tmpfile = hugetlbfs_tmpfile,
|
||||
};
|
||||
|
||||
static const struct inode_operations hugetlbfs_inode_operations = {
|
||||
|
|
Загрузка…
Ссылка в новой задаче