[PATCH v2 16/20] mm/mshare: Add an ioctl for mapping objects in an mshare region

From: Anthony Yznaga
Date: Thu Apr 03 2025 - 22:24:04 EST


From: Khalid Aziz <khalid@xxxxxxxxxx>

Reserve a range of ioctls for msharefs and add an ioctl for mapping
objects within an mshare region. The arguments are the same as mmap()
except that the start of the mapping is specified as an offset into
the mshare region instead of as an address. For now system-selected
addresses are disallowed so MAP_FIXED must be specified. Only shared
anonymous memory is supported initially.

Signed-off-by: Khalid Aziz <khalid@xxxxxxxxxx>
Signed-off-by: Anthony Yznaga <anthony.yznaga@xxxxxxxxxx>
---
.../userspace-api/ioctl/ioctl-number.rst | 1 +
include/uapi/linux/msharefs.h | 31 ++++++++
mm/mshare.c | 74 +++++++++++++++++++
3 files changed, 106 insertions(+)
create mode 100644 include/uapi/linux/msharefs.h

diff --git a/Documentation/userspace-api/ioctl/ioctl-number.rst b/Documentation/userspace-api/ioctl/ioctl-number.rst
index 3d1cd7ad9d67..250dd58ebdba 100644
--- a/Documentation/userspace-api/ioctl/ioctl-number.rst
+++ b/Documentation/userspace-api/ioctl/ioctl-number.rst
@@ -306,6 +306,7 @@ Code Seq# Include File Comments
'v' 20-27 arch/powerpc/include/uapi/asm/vas-api.h VAS API
'v' C0-FF linux/meye.h conflict!
'w' all CERN SCI driver
+'x' 00-1F linux/msharefs.h msharefs filesystem
'y' 00-1F packet based user level communications
<mailto:zapman@xxxxxxxxxxxx>
'z' 00-3F CAN bus card conflict!
diff --git a/include/uapi/linux/msharefs.h b/include/uapi/linux/msharefs.h
new file mode 100644
index 000000000000..ad129beeef62
--- /dev/null
+++ b/include/uapi/linux/msharefs.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * msharefs defines a memory region that is shared across processes.
+ * ioctl is used on files created under msharefs to set various
+ * attributes on these shared memory regions
+ *
+ *
+ * Copyright (C) 2024 Oracle Corp. All rights reserved.
+ * Author: Khalid Aziz <khalid@xxxxxxxxxx>
+ */
+
+#ifndef _UAPI_LINUX_MSHAREFS_H
+#define _UAPI_LINUX_MSHAREFS_H
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+/*
+ * msharefs specific ioctl commands
+ */
+#define MSHAREFS_CREATE_MAPPING _IOW('x', 0, struct mshare_create)
+
+struct mshare_create {
+ __u64 region_offset;
+ __u64 size;
+ __u64 offset;
+ __u32 prot;
+ __u32 flags;
+ __u32 fd;
+};
+#endif
diff --git a/mm/mshare.c b/mm/mshare.c
index 4ddaa0d41070..be0aaa894963 100644
--- a/mm/mshare.c
+++ b/mm/mshare.c
@@ -10,6 +10,7 @@
*
* Copyright (C) 2024 Oracle Corp. All rights reserved.
* Author: Khalid Aziz <khalid@xxxxxxxxxx>
+ * Author: Matthew Wilcox <willy@xxxxxxxxxxxxx>
*
*/

@@ -18,6 +19,7 @@
#include <linux/mman.h>
#include <linux/mmu_notifier.h>
#include <uapi/linux/magic.h>
+#include <uapi/linux/msharefs.h>
#include <linux/falloc.h>
#include <asm/tlbflush.h>

@@ -230,6 +232,77 @@ msharefs_get_unmapped_area(struct file *file, unsigned long addr,
pgoff, flags);
}

+static long
+msharefs_create_mapping(struct mshare_data *m_data, struct mshare_create *mcreate)
+{
+ struct mm_struct *host_mm = m_data->mm;
+ unsigned long mshare_start, mshare_end;
+ unsigned long region_offset = mcreate->region_offset;
+ unsigned long size = mcreate->size;
+ unsigned int fd = mcreate->fd;
+ int flags = mcreate->flags;
+ int prot = mcreate->prot;
+ unsigned long populate = 0;
+ unsigned long mapped_addr;
+ unsigned long addr;
+ vm_flags_t vm_flags;
+ int error = -EINVAL;
+
+ mshare_start = m_data->start;
+ mshare_end = mshare_start + m_data->size;
+ addr = mshare_start + region_offset;
+
+ if ((addr < mshare_start) || (addr >= mshare_end) ||
+ (addr + size > mshare_end))
+ goto out;
+
+ /*
+ * Only anonymous shared memory at fixed addresses is allowed for now.
+ */
+ if ((flags & (MAP_SHARED | MAP_FIXED)) != (MAP_SHARED | MAP_FIXED))
+ goto out;
+ if (fd != -1)
+ goto out;
+
+ if (mmap_write_lock_killable(host_mm)) {
+ error = -EINTR;
+ goto out;
+ }
+
+ error = 0;
+ mapped_addr = __do_mmap(NULL, addr, size, prot, flags, vm_flags,
+ 0, &populate, NULL, host_mm);
+
+ if (IS_ERR_VALUE(mapped_addr))
+ error = (long)mapped_addr;
+
+ mmap_write_unlock(host_mm);
+out:
+ return error;
+}
+
+static long
+msharefs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ struct mshare_data *m_data = filp->private_data;
+ struct mshare_create mcreate;
+
+ switch (cmd) {
+ case MSHAREFS_CREATE_MAPPING:
+ if (copy_from_user(&mcreate, (struct mshare_create __user *)arg,
+ sizeof(mcreate)))
+ return -EFAULT;
+
+ if (!test_bit(MSHARE_INITIALIZED, &m_data->flags))
+ return -EINVAL;
+
+ return msharefs_create_mapping(m_data, &mcreate);
+
+ default:
+ return -ENOTTY;
+ }
+}
+
static int msharefs_set_size(struct mshare_data *m_data, unsigned long size)
{
int error = -EINVAL;
@@ -285,6 +358,7 @@ static const struct file_operations msharefs_file_operations = {
.open = simple_open,
.mmap = msharefs_mmap,
.get_unmapped_area = msharefs_get_unmapped_area,
+ .unlocked_ioctl = msharefs_ioctl,
.fallocate = msharefs_fallocate,
};

--
2.43.5