/*
* hugetlbpage-backed filesystem. Based on ramfs.
*
* Nadia Yvette Chambers, 2002
*
* Copyright (C) 2002 Linus Torvalds.
* License: GPL
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/thread_info.h>
#include <asm/current.h>
#include <linux/falloc.h>
#include <linux/fs.h>
#include <linux/mount.h>
#include <linux/file.h>
#include <linux/kernel.h>
#include <linux/writeback.h>
#include <linux/pagemap.h>
#include <linux/highmem.h>
#include <linux/init.h>
#include <linux/string.h>
#include <linux/capability.h>
#include <linux/ctype.h>
#include <linux/backing-dev.h>
#include <linux/hugetlb.h>
#include <linux/pagevec.h>
#include <linux/fs_parser.h>
#include <linux/mman.h>
#include <linux/slab.h>
#include <linux/dnotify.h>
#include <linux/statfs.h>
#include <linux/security.h>
#include <linux/magic.h>
#include <linux/migrate.h>
#include <linux/uio.h>
#include <linux/uaccess.h>
#include <linux/sched/mm.h>
#define CREATE_TRACE_POINTS
#include <trace/events/hugetlbfs.h>
static const struct address_space_operations hugetlbfs_aops;
static const struct file_operations hugetlbfs_file_operations;
static const struct inode_operations hugetlbfs_dir_inode_operations;
static const struct inode_operations hugetlbfs_inode_operations;
enum hugetlbfs_size_type { NO_SIZE, SIZE_STD, SIZE_PERCENT };
struct hugetlbfs_fs_context {
struct hstate *hstate;
unsigned long long max_size_opt;
unsigned long long min_size_opt;
long max_hpages;
long nr_inodes;
long min_hpages;
enum hugetlbfs_size_type max_val_type;
enum hugetlbfs_size_type min_val_type;
kuid_t uid;
kgid_t gid;
umode_t mode;
};
int sysctl_hugetlb_shm_group;
enum hugetlb_param {
Opt_gid,
Opt_min_size,
Opt_mode,
Opt_nr_inodes,
Opt_pagesize,
Opt_size,
Opt_uid,
};
static const struct fs_parameter_spec hugetlb_fs_parameters[] = {
fsparam_gid ("gid", Opt_gid),
fsparam_string("min_size", Opt_min_size),
fsparam_u32oct("mode", Opt_mode),
fsparam_string("nr_inodes", Opt_nr_inodes),
fsparam_string("pagesize", Opt_pagesize),
fsparam_string("size", Opt_size),
fsparam_uid ("uid", Opt_uid),
{}
};
/*
* Mask used when checking the page offset value passed in via system
* calls. This value will be converted to a loff_t which is signed.
* Therefore, we want to check the upper PAGE_SHIFT + 1 bits of the
* value. The extra bit (- 1 in the shift value) is to take the sign
* bit into account.
*/
#define PGOFF_LOFFT_MAX \
(((1UL << (PAGE_SHIFT + 1)) - 1) << (BITS_PER_LONG - (PAGE_SHIFT + 1)))
static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
{
struct inode *inode = file_inode(file);
loff_t len, vma_len;
int ret;
struct hstate *h = hstate_file(file);
vm_flags_t vm_flags;
/*
* vma address alignment (but not the pgoff alignment) has
* already been checked by prepare_hugepage_range. If you add
* any error returns here, do so after setting VM_HUGETLB, so
* is_vm_hugetlb_page tests below unmap_region go the right
* way when do_mmap unwinds (may be important on powerpc
* and ia64).
*/
vm_flags_set(vma, VM_HUGETLB | VM_DONTEXPAND);
vma->vm_ops = &hugetlb_vm_ops;
/*
* page based offset in vm_pgoff could be sufficiently large to
* overflow
|