linux-um archives
 help / color / mirror / Atom feed
From: Jeff Dike <jdike@addtoit.com>
To: UML-user <user-mode-linux-user@lists.sourceforge.net>,
	uml-devel <user-mode-linux-devel@lists.sourceforge.net>
Subject: Re: [uml-devel] [RFC PATCH 0/10] SKAS4
Date: Thu, 24 Jan 2008 15:35:13 -0500	[thread overview]
Message-ID: <20080124203513.GA8525@c2.user-mode-linux.org> (raw)
In-Reply-To: <20080123171225.GA7654@c2.user-mode-linux.org>

On Wed, Jan 23, 2008 at 12:12:25PM -0500, Jeff Dike wrote:
> Major changes since version 2 -

Also forgot to tell git about a couple of new files, without which
this totally won't work.

Below is mm/mfs.c - just drop it into your tree.

				Jeff

-- 
Work email - jdike at linux dot intel dot com

#define __FRAME_OFFSETS
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/mount.h>
#include <linux/sched.h>
#include <asm/mmu_context.h>
#include <asm/ptrace.h>
#include <asm/uaccess.h>
#include <asm/user.h>

static int release_mm(struct inode *inode, struct file *file)
{
	struct mm_struct *mm = file->private_data;

	mmput(mm);
	return 0;
}

#define MM_MAGIC 0xE0AAC500

static int mm_get_sb(struct file_system_type *fs_type,
		     int flags, const char *dev_name, void *data,
		     struct vfsmount *mnt)
{
	return get_sb_pseudo(fs_type, "mm:", NULL, MM_MAGIC, mnt);
}

static struct vfsmount *mm_mnt;

static struct file_system_type mm_fs_type = {
	.name		= "mm",
	.get_sb		= mm_get_sb,
	.kill_sb	= kill_anon_super,
};

static int __init init_mm_fs(void)
{
	int err;

	err = register_filesystem(&mm_fs_type);
	if (err)
		return err;

	mm_mnt = kern_mount(&mm_fs_type);
	if (IS_ERR(mm_mnt)) {
		err = PTR_ERR(mm_mnt);
		unregister_filesystem(&mm_fs_type);
	}

	return err;
}

static void __exit exit_mm_fs(void)
{
	unregister_filesystem(&mm_fs_type);
	mntput(mm_mnt);
}

fs_initcall(init_mm_fs);
module_exit(exit_mm_fs);

static int mm_delete_dentry(struct dentry *dentry)
{
	/*
	 * At creation time, we pretended this dentry was hashed
	 * (by clearing DCACHE_UNHASHED bit in d_flags)
	 * At delete time, we restore the truth : not hashed.
	 * (so that dput() can proceed correctly)
	 */
	dentry->d_flags |= DCACHE_UNHASHED;
	return 0;
}

/*
 * pipefs_dname() is called from d_path().
 */
static char *mm_dname(struct dentry *dentry, char *buffer, int buflen)
{
	return dynamic_dname(dentry, buffer, buflen, "mm:[%lu]",
			     dentry->d_inode->i_ino);
}

static struct dentry_operations mm_dentry_operations = {
	.d_delete	= mm_delete_dentry,
	.d_dname	= mm_dname,
};

static struct file_operations mm_fops = {
	.release	= release_mm,
};

#define MM_FLAGS_MASK 1
#define MM_INIT_MASK 1

#define MM_COPY 0
#define MM_EMPTY 1

asmlinkage long sys_new_mm(int flags)
{
	struct file *file;
	struct mm_struct *mm;
	struct inode *inode;
	struct dentry *dentry;
	struct qstr name = { .name = "" };
	int err, fd;

	if ((flags & ~MM_FLAGS_MASK) != 0)
		return -EINVAL;

	if ((flags & MM_INIT_MASK) == MM_COPY) {
		mm = dup_mm(current);
		if (mm == NULL)
			return -ENOMEM;
	}
	else
		return -EINVAL;

	fd = get_unused_fd();
	if (fd < 0) {
		err = fd;
		goto out_free;
	}

	err = -ENOMEM;
	dentry = d_alloc(mm_mnt->mnt_sb->s_root, &name);
	if (dentry == NULL)
		goto out_put;

	dentry->d_op = &mm_dentry_operations;
	dentry->d_flags &= ~DCACHE_UNHASHED;

	inode = new_inode(mm_mnt->mnt_sb);
	if (inode == NULL)
		goto out_dput;

	inode->i_mode = S_IRUSR;
	inode->i_uid = current->fsuid;
	inode->i_gid = current->fsgid;
	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;

	d_instantiate(dentry, inode);

	file = alloc_file(mm_mnt, dentry, FMODE_READ, &mm_fops);
	if (file == NULL)
		goto out_dput;

	file->f_flags = O_RDONLY;
	file->private_data = mm;

	fd_install(fd, file);

	return fd;

 out_dput:
	dput(dentry);
 out_put:
	put_unused_fd(fd);
 out_free:
	mmput(mm);
	return err;
}

extern const struct file_operations proc_pid_mm_operations;

/* Returns with an extra reference on mm */
struct mm_struct *fd_to_mm(int fd)
{
	struct mm_struct *mm;
	struct file *file = fget(fd);

	if (!file)
		return ERR_PTR(-EBADF);

	if ((file->f_op != &mm_fops) &&
	    (file->f_op != &proc_pid_mm_operations))
		mm = ERR_PTR(-EINVAL);
	else {
		mm = file->private_data;
		atomic_inc(&mm->mm_users);
	}

	fput(file);

	return mm;
}

void do_switch(struct task_struct *task, struct mm_struct *mm)
{
	struct mm_struct *old = task->mm;

	task_lock(task);

	atomic_inc(&mm->mm_users);
	task->mm = mm;
	task->active_mm = mm;

	if(task == current)
		switch_mm(old, task->mm, task);

	task_unlock(task);

	mmput(old);
}

#define MM_SWITCH_MASK 3
#define MM_REGS_MASK 3

#define MM_ALL_REGS 0
#define MM_SP_IP 1
#define MM_SAME 2

long do_switch_mm(int fd, unsigned long flags, long __user *new,
		  long __user *save, struct pt_regs *regs)
{
	struct user_regs new_regs;
	struct mm_struct *old_mm, *new_mm;
	int regs_init, ret = 0;

	if ((flags & ~MM_SWITCH_MASK) != 0)
		return -EINVAL;

	regs_init = flags & MM_SWITCH_MASK;
	if (regs_init > MM_SAME)
		return -EINVAL;

	old_mm = current->mm;
	if (old_mm == NULL)
		return -EINVAL;

	if ((new == NULL) && (regs_init != MM_SAME))
		return -EINVAL;
	if (copyin_user_regs(&new_regs, new))
		return -EFAULT;

	new_mm = fd_to_mm(fd);
	if (IS_ERR(new_mm))
		return PTR_ERR(new_mm);

	atomic_inc(&old_mm->mm_users);
	do_switch(current, new_mm);

	mmput(new_mm);

	if ((save != NULL) && pt_regs_to_ptrace(save, regs)) {
		do_switch(current, old_mm);
		ret = EFAULT;
		goto out;
	}

	if (regs_init == MM_SP_IP) {
		pt_regs_ip(*regs) = ptrace_ip(&new_regs);
		pt_regs_sp(*regs) = ptrace_sp(&new_regs);
	}
	else if (regs_init == MM_SAME)
		ret = 1;
	else
		ret = ptrace_to_pt_regs(regs, &new_regs);

 out:
	mmput(old_mm);
	return ret;
}

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
User-mode-linux-devel mailing list
User-mode-linux-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel

  reply	other threads:[~2008-01-24 20:35 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-01-23 17:12 [uml-devel] [RFC PATCH 0/10] SKAS4 Jeff Dike
2008-01-24 20:35 ` Jeff Dike [this message]
2008-01-24 20:36 ` Jeff Dike
  -- strict thread matches above, loose matches on Subject: below --
2008-01-28 21:38 Jeff Dike
2008-01-14 21:36 Jeff Dike

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20080124203513.GA8525@c2.user-mode-linux.org \
    --to=jdike@addtoit.com \
    --cc=user-mode-linux-devel@lists.sourceforge.net \
    --cc=user-mode-linux-user@lists.sourceforge.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox