|
@@ -34,6 +34,7 @@
|
|
|
#include <linux/swap.h>
|
|
|
#include <linux/uio.h>
|
|
|
#include <linux/khugepaged.h>
|
|
|
+#include <linux/hugetlb.h>
|
|
|
|
|
|
#include <asm/tlbflush.h> /* for arch/microblaze update_mmu_cache() */
|
|
|
|
|
@@ -3652,7 +3653,7 @@ static int shmem_show_options(struct seq_file *seq, struct dentry *root)
|
|
|
#define MFD_NAME_PREFIX_LEN (sizeof(MFD_NAME_PREFIX) - 1)
|
|
|
#define MFD_NAME_MAX_LEN (NAME_MAX - MFD_NAME_PREFIX_LEN)
|
|
|
|
|
|
-#define MFD_ALL_FLAGS (MFD_CLOEXEC | MFD_ALLOW_SEALING)
|
|
|
+#define MFD_ALL_FLAGS (MFD_CLOEXEC | MFD_ALLOW_SEALING | MFD_HUGETLB)
|
|
|
|
|
|
SYSCALL_DEFINE2(memfd_create,
|
|
|
const char __user *, uname,
|
|
@@ -3664,8 +3665,18 @@ SYSCALL_DEFINE2(memfd_create,
|
|
|
char *name;
|
|
|
long len;
|
|
|
|
|
|
- if (flags & ~(unsigned int)MFD_ALL_FLAGS)
|
|
|
- return -EINVAL;
|
|
|
+ if (!(flags & MFD_HUGETLB)) {
|
|
|
+ if (flags & ~(unsigned int)MFD_ALL_FLAGS)
|
|
|
+ return -EINVAL;
|
|
|
+ } else {
|
|
|
+ /* Sealing not supported in hugetlbfs (MFD_HUGETLB) */
|
|
|
+ if (flags & MFD_ALLOW_SEALING)
|
|
|
+ return -EINVAL;
|
|
|
+ /* Allow huge page size encoding in flags. */
|
|
|
+ if (flags & ~(unsigned int)(MFD_ALL_FLAGS |
|
|
|
+ (MFD_HUGE_MASK << MFD_HUGE_SHIFT)))
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
|
|
|
/* length includes terminating zero */
|
|
|
len = strnlen_user(uname, MFD_NAME_MAX_LEN + 1);
|
|
@@ -3696,16 +3707,30 @@ SYSCALL_DEFINE2(memfd_create,
|
|
|
goto err_name;
|
|
|
}
|
|
|
|
|
|
- file = shmem_file_setup(name, 0, VM_NORESERVE);
|
|
|
+ if (flags & MFD_HUGETLB) {
|
|
|
+ struct user_struct *user = NULL;
|
|
|
+
|
|
|
+ file = hugetlb_file_setup(name, 0, VM_NORESERVE, &user,
|
|
|
+ HUGETLB_ANONHUGE_INODE,
|
|
|
+ (flags >> MFD_HUGE_SHIFT) &
|
|
|
+ MFD_HUGE_MASK);
|
|
|
+ } else
|
|
|
+ file = shmem_file_setup(name, 0, VM_NORESERVE);
|
|
|
if (IS_ERR(file)) {
|
|
|
error = PTR_ERR(file);
|
|
|
goto err_fd;
|
|
|
}
|
|
|
- info = SHMEM_I(file_inode(file));
|
|
|
file->f_mode |= FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE;
|
|
|
file->f_flags |= O_RDWR | O_LARGEFILE;
|
|
|
- if (flags & MFD_ALLOW_SEALING)
|
|
|
+
|
|
|
+ if (flags & MFD_ALLOW_SEALING) {
|
|
|
+ /*
|
|
|
+ * flags check at beginning of function ensures
|
|
|
+ * this is not a hugetlbfs (MFD_HUGETLB) file.
|
|
|
+ */
|
|
|
+ info = SHMEM_I(file_inode(file));
|
|
|
info->seals &= ~F_SEAL_SEAL;
|
|
|
+ }
|
|
|
|
|
|
fd_install(fd, file);
|
|
|
kfree(name);
|