@@ -16,6 +16,7 @@
#include <linux/fs.h>
#include <linux/fs_context.h>
+#include <linux/mman.h>
#include <linux/spinlock_types.h>
#include <uapi/linux/magic.h>
#include <uapi/linux/msharefs.h>
@@ -28,6 +29,74 @@ struct mshare_data {
struct mshare_info minfo;
};
+static int mshare_vm_op_split(struct vm_area_struct *vma, unsigned long addr)
+{
+ return -EINVAL;
+}
+
+static int mshare_vm_op_mprotect(struct vm_area_struct *vma, unsigned long start,
+ unsigned long end, unsigned long newflags)
+{
+ return -EINVAL;
+}
+
+static const struct vm_operations_struct msharefs_vm_ops = {
+ .may_split = mshare_vm_op_split,
+ .mprotect = mshare_vm_op_mprotect,
+};
+
+/*
+ * msharefs_mmap() - mmap an mshare region
+ */
+static int
+msharefs_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct mshare_data *m_data = file->private_data;
+
+ vma->vm_private_data = m_data;
+ vm_flags_set(vma, VM_MSHARE | VM_DONTEXPAND);
+ vma->vm_ops = &msharefs_vm_ops;
+
+ return 0;
+}
+
+static unsigned long
+msharefs_get_unmapped_area(struct file *file, unsigned long addr,
+ unsigned long len, unsigned long pgoff, unsigned long flags)
+{
+ struct mshare_data *m_data = file->private_data;
+ struct mm_struct *mm = current->mm;
+ unsigned long mshare_start, mshare_size;
+ const unsigned long mmap_end = arch_get_mmap_end(addr, len, flags);
+
+ mmap_assert_write_locked(mm);
+
+ if ((flags & MAP_TYPE) == MAP_PRIVATE)
+ return -EINVAL;
+
+ spin_lock(&m_data->m_lock);
+ mshare_start = m_data->minfo.start;
+ mshare_size = m_data->minfo.size;
+ spin_unlock(&m_data->m_lock);
+
+ if ((mshare_size == 0) || (len != mshare_size))
+ return -EINVAL;
+
+ if (len > mmap_end - mmap_min_addr)
+ return -ENOMEM;
+
+ if (addr && (addr != mshare_start))
+ return -EINVAL;
+
+ if (flags & MAP_FIXED)
+ return addr;
+
+ if (find_vma_intersection(mm, mshare_start, mshare_start + mshare_size))
+ return -EEXIST;
+
+ return mshare_start;
+}
+
static long
msharefs_set_size(struct mm_struct *host_mm, struct mshare_data *m_data,
struct mshare_info *minfo)
@@ -94,6 +163,8 @@ static const struct inode_operations msharefs_file_inode_ops;
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,
};