Cc: Andrew On 10/15/19 2:01 AM, Piotr Sarna wrote: > 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 existing > d_tmpfile utility function to instantiate the dcache entry for the file. Let's drop the mention of anonymous mapping to avoid any confusion. If we include use cases, the above paragraph could be rewritten as: O_TMPFILE is an option used to create an unnamed temporary regular file. Currently, libhugetlbfs and Seastar use a combination of mkstemp and unlink to accomplish similar functionality on hugetlbfs. Add O_TMPFILE support to hugetlbfs so that it can potentially be used by existing users (Seastar) and new users (Oracle DB). Support is added by simply using the d_tmpfile utility function to instantiate the dcache entry for a temporary 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. > > Signed-off-by: Piotr Sarna <p.sarna@xxxxxxx> The code looks good, Reviewed-by: Mike Kravetz <mike.kravetz@xxxxxxxxxx> -- Mike Kravetz > --- > fs/hugetlbfs/inode.c | 25 ++++++++++++++++++++++--- > 1 file changed, 22 insertions(+), 3 deletions(-) > > diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c > index 1dcc57189382..277b7d231db8 100644 > --- a/fs/hugetlbfs/inode.c > +++ b/fs/hugetlbfs/inode.c > @@ -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,22 @@ 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); > + 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 +856,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 +1120,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 = { >