Allocate a new mm to store shared page table. Add a read operation to file created by mshare syscall to return the starting address and size of region shared by the corresponding range. Signed-off-by: Khalid Aziz <khalid.aziz@xxxxxxxxxx> --- mm/mshare.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 61 insertions(+), 5 deletions(-) diff --git a/mm/mshare.c b/mm/mshare.c index e48d0f615f9f..d998b23c25ab 100644 --- a/mm/mshare.c +++ b/mm/mshare.c @@ -16,14 +16,37 @@ #include <linux/uaccess.h> #include <linux/pseudo_fs.h> #include <linux/fileattr.h> +#include <linux/refcount.h> #include <uapi/linux/magic.h> #include <uapi/linux/limits.h> +struct mshare_data { + struct mm_struct *mm; + refcount_t refcnt; +}; + static struct super_block *msharefs_sb; +static ssize_t +mshare_read(struct kiocb *iocb, struct iov_iter *iov) +{ + struct mshare_data *info = iocb->ki_filp->private_data; + struct mm_struct *mm = info->mm; + size_t ret; + unsigned long tmp[2]; + + tmp[0] = mm->mmap_base; + tmp[1] = mm->task_size - mm->mmap_base; + ret = copy_to_iter(&tmp, sizeof(tmp), iov); + if (!ret) + return -EFAULT; + return ret; +} + static const struct file_operations msharefs_file_operations = { - .open = simple_open, - .llseek = no_llseek, + .open = simple_open, + .read_iter = mshare_read, + .llseek = no_llseek, }; static int @@ -77,7 +100,12 @@ static struct inode inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode); inode->i_fop = &msharefs_file_operations; - inode->i_size = 0; + + /* + * A read from this file will return two unsigned long + */ + inode->i_size = 2 * sizeof(unsigned long); + inode->i_uid = current_fsuid(); inode->i_gid = current_fsgid(); } @@ -86,7 +114,8 @@ static struct inode } static int -mshare_file_create(const char *name, unsigned long flags) +mshare_file_create(const char *name, unsigned long flags, + struct mshare_data *info) { struct inode *inode; struct dentry *root, *dentry; @@ -98,6 +127,8 @@ mshare_file_create(const char *name, unsigned long flags) if (IS_ERR(inode)) return PTR_ERR(inode); + inode->i_private = info; + dentry = msharefs_alloc_dentry(root, name); if (IS_ERR(dentry)) { err = PTR_ERR(dentry); @@ -120,6 +151,8 @@ SYSCALL_DEFINE5(mshare, const char __user *, name, unsigned long, addr, unsigned long, len, int, oflag, mode_t, mode) { char mshare_name[NAME_MAX]; + struct mshare_data *info; + struct mm_struct *mm; int err; /* @@ -133,8 +166,31 @@ SYSCALL_DEFINE5(mshare, const char __user *, name, unsigned long, addr, if (err) goto err_out; - err = mshare_file_create(mshare_name, oflag); + mm = mm_alloc(); + if (!mm) + return -ENOMEM; + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) { + err = -ENOMEM; + goto err_relmm; + } + mm->mmap_base = addr; + mm->task_size = addr + len; + if (!mm->task_size) + mm->task_size--; + info->mm = mm; + refcount_set(&info->refcnt, 1); + + err = mshare_file_create(mshare_name, oflag, info); + if (err) + goto err_relinfo; + + return 0; +err_relinfo: + kfree(info); +err_relmm: + mmput(mm); err_out: return err; } -- 2.32.0