public inbox for linux-serial@vger.kernel.org
 help / color / mirror / Atom feed
From: Alan Cox <alan@lxorguk.ukuu.org.uk>
To: torvalds@osdl.org, linux-serial@vger.kernel.org
Subject: [PATCH 15/75] Enable multiple instances of devpts
Date: Fri, 02 Jan 2009 13:42:27 +0000	[thread overview]
Message-ID: <20090102134225.13472.45638.stgit@localhost.localdomain> (raw)
In-Reply-To: <20090102133822.13472.53912.stgit@localhost.localdomain>

From: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>

To support containers, allow multiple instances of devpts filesystem, such
that indices of ptys allocated in one instance are independent of ptys
allocated in other instances of devpts.

But to preserve backward compatibility, enable this support for multiple
instances only if:

	- CONFIG_DEVPTS_MULTIPLE_INSTANCES is set to Y, and
	- '-o newinstance' mount option is specified while mounting devpts

To use multi-instance mount, a container startup script could:

	$ ns_exec -cm /bin/bash
	$ umount /dev/pts
	$ mount -t devpts -o newinstance lxcpts /dev/pts
	$ mount -o bind /dev/pts/ptmx /dev/ptmx
	$ /usr/sbin/sshd -p 1234

where 'ns_exec -cm /bin/bash' is calls clone() with CLONE_NEWNS flag and execs
/bin/bash in the child process. A pty created by the sshd is not visible in
the original mount of /dev/pts.

USER-SPACE-IMPACT:
	- See Documentation/fs/devpts.txt (included in next patch) for user-
	  space impact in multi-instance and mixed-mode operation.
TODO:
	- Update mount(8), pts(4) man pages. Highlight impact of not
	  redirecting /dev/ptmx to /dev/pts/ptmx after a multi-instance mount.

Changelog[v6]:
	- [Dave Hansen] Use new get_init_pts_sb() interface
	- [Serge Hallyn] Don't bother displaying 'newinstance' in show_options
	- [Serge Hallyn] Use macros (PARSE_REMOUNT/PARSE_MOUNT) instead of 0/1.
	- [Serge Hallyn] Check error return from get_sb_single() (now
	  get_init_pts_sb())
	- devpts_pty_kill(): don't dput error dentries

Changelog[v5]:
	- Move get_sb_ref() definition to earlier patch
	- Move usage info to Documentation/filesystems/devpts.txt (next patch)
	- Make ptmx node even in init_pts_ns, now that default mode is 0000
	  (defined in earlier patch, enabled here).
	- Cache ptmx dentry and use to update mode during remount
	  (defined in earlier patch, enabled here).
	- Bugfix: explicitly ignore newinstance on remount (if newinstance was
	  specified on remount of initial mount, it would be ignored but
	  /proc/mounts would imply that the option was set)

Changelog[v4]:

	- Update patch description to address H. Peter Anvin's comments
	- Consolidate multi-instance mode code under new config token,
	  CONFIG_DEVPTS_MULTIPLE_INSTANCE.
	- Move usage-details from patch description to
	  Documentation/fs/devpts.txt

Changelog[v3]:
	- Rename new mount option to 'newinstance'
	- Create ptmx nodes only in 'newinstance' mounts
	- Bugfix: parse_mount_options() modifies @data but since we need to
	  parse the @data twice (once in devpts_get_sb() and once during
	  do_remount_sb()), parse a local copy of @data in devpts_get_sb().
	  (restructured code in devpts_get_sb() to fix this)

Changelog[v2]:
	- Support both single-mount and multiple-mount semantics and
	  provide '-onewmnt' option to select the semantics.

Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Signed-off-by: Alan Cox <alan@redhat.com>
---

 fs/devpts/inode.c |  170 +++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 163 insertions(+), 7 deletions(-)


diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index 2d0eb2c..b4a89fa 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -48,10 +48,11 @@ struct pts_mount_opts {
 	gid_t   gid;
 	umode_t mode;
 	umode_t ptmxmode;
+	int newinstance;
 };
 
 enum {
-	Opt_uid, Opt_gid, Opt_mode, Opt_ptmxmode,
+	Opt_uid, Opt_gid, Opt_mode, Opt_ptmxmode, Opt_newinstance,
 	Opt_err
 };
 
@@ -61,6 +62,7 @@ static const match_table_t tokens = {
 	{Opt_mode, "mode=%o"},
 #ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
 	{Opt_ptmxmode, "ptmxmode=%o"},
+	{Opt_newinstance, "newinstance"},
 #endif
 	{Opt_err, NULL}
 };
@@ -78,13 +80,17 @@ static inline struct pts_fs_info *DEVPTS_SB(struct super_block *sb)
 
 static inline struct super_block *pts_sb_from_inode(struct inode *inode)
 {
+#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
 	if (inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC)
 		return inode->i_sb;
-
+#endif
 	return devpts_mnt->mnt_sb;
 }
 
-static int parse_mount_options(char *data, struct pts_mount_opts *opts)
+#define PARSE_MOUNT	0
+#define PARSE_REMOUNT	1
+
+static int parse_mount_options(char *data, int op, struct pts_mount_opts *opts)
 {
 	char *p;
 
@@ -95,6 +101,10 @@ static int parse_mount_options(char *data, struct pts_mount_opts *opts)
 	opts->mode    = DEVPTS_DEFAULT_MODE;
 	opts->ptmxmode = DEVPTS_DEFAULT_PTMX_MODE;
 
+	/* newinstance makes sense only on initial mount */
+	if (op == PARSE_MOUNT)
+		opts->newinstance = 0;
+
 	while ((p = strsep(&data, ",")) != NULL) {
 		substring_t args[MAX_OPT_ARGS];
 		int token;
@@ -128,6 +138,11 @@ static int parse_mount_options(char *data, struct pts_mount_opts *opts)
 				return -EINVAL;
 			opts->ptmxmode = option & S_IALLUGO;
 			break;
+		case Opt_newinstance:
+			/* newinstance makes sense only on initial mount */
+			if (op == PARSE_MOUNT)
+				opts->newinstance = 1;
+			break;
 #endif
 		default:
 			printk(KERN_ERR "devpts: called with bogus options\n");
@@ -214,7 +229,7 @@ static int devpts_remount(struct super_block *sb, int *flags, char *data)
 	struct pts_fs_info *fsi = DEVPTS_SB(sb);
 	struct pts_mount_opts *opts = &fsi->mount_opts;
 
-	err = parse_mount_options(data, opts);
+	err = parse_mount_options(data, PARSE_REMOUNT, opts);
 
 	/*
 	 * parse_mount_options() restores options to default values
@@ -309,8 +324,100 @@ static int compare_init_pts_sb(struct super_block *s, void *p)
 {
 	if (devpts_mnt)
 		return devpts_mnt->mnt_sb == s;
+	return 0;
+}
+
+#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
+/*
+ * Safely parse the mount options in @data and update @opts.
+ *
+ * devpts ends up parsing options two times during mount, due to the
+ * two modes of operation it supports. The first parse occurs in
+ * devpts_get_sb() when determining the mode (single-instance or
+ * multi-instance mode). The second parse happens in devpts_remount()
+ * or new_pts_mount() depending on the mode.
+ *
+ * Parsing of options modifies the @data making subsequent parsing
+ * incorrect. So make a local copy of @data and parse it.
+ *
+ * Return: 0 On success, -errno on error
+ */
+static int safe_parse_mount_options(void *data, struct pts_mount_opts *opts)
+{
+	int rc;
+	void *datacp;
+
+	if (!data)
+		return 0;
+
+	/* Use kstrdup() ?  */
+	datacp = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!datacp)
+		return -ENOMEM;
+
+	memcpy(datacp, data, PAGE_SIZE);
+	rc = parse_mount_options((char *)datacp, PARSE_MOUNT, opts);
+	kfree(datacp);
+
+	return rc;
+}
+
+/*
+ * Mount a new (private) instance of devpts.  PTYs created in this
+ * instance are independent of the PTYs in other devpts instances.
+ */
+static int new_pts_mount(struct file_system_type *fs_type, int flags,
+		void *data, struct vfsmount *mnt)
+{
+	int err;
+	struct pts_fs_info *fsi;
+	struct pts_mount_opts *opts;
+
+	printk(KERN_NOTICE "devpts: newinstance mount\n");
+
+	err = get_sb_nodev(fs_type, flags, data, devpts_fill_super, mnt);
+	if (err)
+		return err;
+
+	fsi = DEVPTS_SB(mnt->mnt_sb);
+	opts = &fsi->mount_opts;
+
+	err = parse_mount_options(data, PARSE_MOUNT, opts);
+	if (err)
+		goto fail;
+
+	err = mknod_ptmx(mnt->mnt_sb);
+	if (err)
+		goto fail;
 
 	return 0;
+
+fail:
+	dput(mnt->mnt_sb->s_root);
+	deactivate_super(mnt->mnt_sb);
+	return err;
+}
+
+/*
+ * Check if 'newinstance' mount option was specified in @data.
+ *
+ * Return: -errno  	on error (eg: invalid mount options specified)
+ * 	 : 1 		if 'newinstance' mount option was specified
+ * 	 : 0 		if 'newinstance' mount option was NOT specified
+ */
+static int is_new_instance_mount(void *data)
+{
+	int rc;
+	struct pts_mount_opts opts;
+
+	if (!data)
+		return 0;
+
+	rc = safe_parse_mount_options(data, &opts);
+	if (!rc)
+		rc = opts.newinstance;
+
+	return rc;
 }
 
 /*
@@ -358,11 +465,54 @@ static int get_init_pts_sb(struct file_system_type *fs_type, int flags,
         return simple_set_mnt(mnt, s);
 }
 
+/*
+ * Mount or remount the initial kernel mount of devpts. This type of
+ * mount maintains the legacy, single-instance semantics, while the
+ * kernel still allows multiple-instances.
+ */
+static int init_pts_mount(struct file_system_type *fs_type, int flags,
+		void *data, struct vfsmount *mnt)
+{
+	int err;
+
+	err = get_init_pts_sb(fs_type, flags, data, mnt);
+	if (err)
+		 return err;
+
+	err = mknod_ptmx(mnt->mnt_sb);
+	if (err) {
+		dput(mnt->mnt_sb->s_root);
+		deactivate_super(mnt->mnt_sb);
+	}
+
+	return err;
+}
+
 static int devpts_get_sb(struct file_system_type *fs_type,
 	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_init_pts_sb(fs_type, flags, data, mnt);
+	int new;
+
+	new = is_new_instance_mount(data);
+	if (new < 0)
+		return new;
+
+	if (new)
+		return new_pts_mount(fs_type, flags, data, mnt);
+
+	return init_pts_mount(fs_type, flags, data, mnt);
 }
+#else
+/*
+ * This supports only the legacy single-instance semantics (no
+ * multiple-instance semantics)
+ */
+static int devpts_get_sb(struct file_system_type *fs_type, int flags,
+		const char *dev_name, void *data, struct vfsmount *mnt)
+{
+	return get_sb_single(fs_type, flags, data, devpts_fill_super, mnt);
+}
+#endif
 
 static void devpts_kill_sb(struct super_block *sb)
 {
@@ -488,12 +638,18 @@ void devpts_pty_kill(struct tty_struct *tty)
 	mutex_lock(&root->d_inode->i_mutex);
 
 	dentry = d_find_alias(inode);
-	if (dentry && !IS_ERR(dentry)) {
+	if (IS_ERR(dentry))
+		goto out;
+
+	if (dentry) {
 		inode->i_nlink--;
 		d_delete(dentry);
-		dput(dentry);
+		dput(dentry);	// d_alloc_name() in devpts_pty_new()
 	}
 
+	dput(dentry);		// d_find_alias above
+
+out:
 	mutex_unlock(&root->d_inode->i_mutex);
 }
 


  parent reply	other threads:[~2009-01-02 13:42 UTC|newest]

Thread overview: 79+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-01-02 13:40 [PATCH 00/75] TTY updates for 2.6.29-rc Alan Cox
2009-01-02 13:40 ` [PATCH 01/75] Blackfin Serial Driver: updates kgdb over Blackfin serial driver with kgdb framework Alan Cox
2009-01-02 13:40 ` [PATCH 02/75] Blackfin Serial Driver: fix bug - SIR driver stop receiving randomly Alan Cox
2009-01-02 13:40 ` [PATCH 03/75] Blackfin Serial Driver: Clean serial console and early prink code Alan Cox
2009-01-02 13:40 ` [PATCH 04/75] Blackfin Serial Driver: Fix bug - BF527-EZKIT unable to receive large files over UART in DMA mode Alan Cox
2009-01-02 13:40 ` [PATCH 05/75] Blackfin Serial Driver: Remove BI status for known_good_char Alan Cox
2009-01-02 13:40 ` [PATCH 06/75] n_tty: Fix loss of echoed characters and remove bkl from n_tty Alan Cox
2009-01-02 13:41 ` [PATCH 07/75] n_tty: clean up coding style Alan Cox
2009-01-02 13:41 ` [PATCH 08/75] Remove devpts_root global Alan Cox
2009-01-02 13:41 ` [PATCH 09/75] Per-mount allocated_ptys Alan Cox
2009-01-02 19:47   ` Michał Mirosław
2009-01-02 13:41 ` [PATCH 10/75] Per-mount 'config' object Alan Cox
2009-01-02 13:41 ` [PATCH 11/75] Extract option parsing to new function Alan Cox
2009-01-02 13:41 ` [PATCH 12/75] Add DEVPTS_MULTIPLE_INSTANCES config token Alan Cox
2009-01-02 13:42 ` [PATCH 13/75] Define mknod_ptmx() Alan Cox
2009-01-02 13:42 ` [PATCH 14/75] Define get_init_pts_sb() Alan Cox
2009-01-02 13:42 ` Alan Cox [this message]
2009-01-02 13:42 ` [PATCH 16/75] Document usage of multiple-instances of devpts Alan Cox
2009-01-02 13:42 ` [PATCH 17/75] devpts: Coding style clean up Alan Cox
2009-01-02 13:42 ` [PATCH 18/75] sierra: Fix formatting Alan Cox
2009-01-02 13:43 ` [PATCH 19/75] tty: Fix sparse static warning for tty_driver_lookup_tty Alan Cox
2009-01-02 13:43 ` [PATCH 20/75] pty: simplify resize Alan Cox
2009-01-02 13:43 ` [PATCH 21/75] n_tty: Fix handling of control characters and continuations Alan Cox
2009-01-02 13:43 ` [PATCH 22/75] n_tty: Fix hanfling of buffer full corner cases Alan Cox
2009-01-02 13:43 ` [PATCH 23/75] n_tty: Output bells immediately on a full buffer Alan Cox
2009-01-02 13:44 ` [PATCH 24/75] tty: Fix close races in USB serial Alan Cox
2009-01-02 13:44 ` [PATCH 25/75] devpts: fix unused function warning Alan Cox
2009-01-02 13:44 ` [PATCH 26/75] Convert the oxsemi tornado special cases to use the quirk interface and not Alan Cox
2009-01-02 13:44 ` [PATCH 27/75] And here's a patch (to be applied on top of the last) which prevents Alan Cox
2009-01-02 13:44 ` [PATCH 28/75] Add device function for USB serial console Alan Cox
2009-01-02 13:44 ` [PATCH 29/75] CRED: Wrap task credential accesses in the devpts filesystem Alan Cox
2009-01-02 13:44 ` [PATCH 30/75] tty: Fix PPP hang under load Alan Cox
2009-01-02 13:45 ` [PATCH 31/75] tty_port: Add a port level carrier detect operation Alan Cox
2009-01-02 13:45 ` [PATCH 32/75] rio: Kill off ckmalloc Alan Cox
2009-01-02 13:45 ` [PATCH 33/75] tty: Pull the dtr raise into tty port Alan Cox
2009-01-02 13:45 ` [PATCH 34/75] isicom: redo locking to use tty port locks Alan Cox
2009-01-02 13:45 ` [PATCH 35/75] tty: relock generic_serial Alan Cox
2009-01-02 13:45 ` [PATCH 36/75] tty: rocketport uses different port flags to everyone else Alan Cox
2009-01-02 13:45 ` [PATCH 37/75] tty: relock riscom8 using port locks Alan Cox
2009-01-02 13:45 ` [PATCH 38/75] tty: relock the mxser driver Alan Cox
2009-01-02 13:46 ` [PATCH 39/75] tty: Introduce a tty_port generic block_til_ready Alan Cox
2009-01-02 13:46 ` [PATCH 40/75] tty: Rework istallion to use the tty port changes Alan Cox
2009-01-02 13:46 ` [PATCH 41/75] tty: rework stallion to use the tty_port bits Alan Cox
2009-01-02 13:46 ` [PATCH 42/75] tty: ESP has been broken for locking etc forver Alan Cox
2009-01-02 13:46 ` [PATCH 43/75] tty: tty port zero baud open Alan Cox
2009-01-02 13:46 ` [PATCH 44/75] tty: Introduce some close helpers for ports Alan Cox
2009-01-02 13:46 ` [PATCH 45/75] serial: set correct baud_base for Oxford Semiconductor Ltd EXSYS EX-41092 Dual 16950 Serial adapter Alan Cox
2009-01-02 13:47 ` [PATCH 46/75] tty: USB tty devices can block in tcdrain when unplugged Alan Cox
2009-01-02 13:47 ` [PATCH 47/75] tty: N_TTY SIGIO only works for read Alan Cox
2009-01-02 13:47 ` [PATCH 48/75] tty: PTYs set TTY_DO_WRITE_WAKEUP when they don't need to Alan Cox
2009-01-02 13:47 ` [PATCH 49/75] tty: Remove some pointless casts Alan Cox
2009-01-02 13:47 ` [PATCH 50/75] tty: kref nozomi Alan Cox
2009-01-02 13:47 ` [PATCH 51/75] hso: net driver using tty without locking Alan Cox
2009-01-02 13:47 ` [PATCH 52/75] tty: Fix the HSO termios handling a bit Alan Cox
2009-01-02 13:47 ` [PATCH 53/75] tty: Modem functions for the HSO driver Alan Cox
2009-01-02 13:47 ` [PATCH 54/75] tty: relock epca Alan Cox
2009-01-02 13:48 ` [PATCH 55/75] tty: refcount the epca driver Alan Cox
2009-01-02 13:48 ` [PATCH 56/75] tty: Make epca use the port helpers Alan Cox
2009-01-02 13:48 ` [PATCH 57/75] tty: Redo the rocket driver locking Alan Cox
2009-01-02 13:48 ` [PATCH 58/75] tty: make rocketport use standard port->flags Alan Cox
2009-01-02 13:48 ` [PATCH 59/75] tty: kref the rocket driver Alan Cox
2009-01-02 13:48 ` [PATCH 60/75] tty: use port methods for " Alan Cox
2009-01-02 13:48 ` [PATCH 61/75] synclink_cs: Convert to tty_port Alan Cox
2009-01-02 13:48 ` [PATCH 62/75] tty: Drop the lock_kernel in the private ioctl hook Alan Cox
2009-01-02 13:49 ` [PATCH 63/75] serial: RS485 ioctl structure uses __u32 include linux/types.h Alan Cox
2009-01-02 13:49 ` [PATCH 64/75] __FUNCTION__ is gcc-specific, use __func__ Alan Cox
2009-01-02 13:49 ` [PATCH 65/75] tty: We want the port object to be persistent Alan Cox
2009-01-02 13:49 ` [PATCH 66/75] fix for tty-serial-move-port Alan Cox
2009-01-02 13:49 ` [PATCH 67/75] 8250: Don't clobber spinlocks Alan Cox
2009-01-02 13:49 ` [PATCH 68/75] 8250: Serial driver changes to support future Cavium OCTEON serial patches Alan Cox
2009-01-02 13:49 ` [PATCH 69/75] Serial: Allow port type to be specified when calling serial8250_register_port Alan Cox
2009-01-02 13:50 ` [PATCH 70/75] Serial: UART driver changes for Cavium OCTEON Alan Cox
2009-01-02 13:50 ` [PATCH 71/75] drivers/char/cyclades.c: cy_pci_probe: fix error path Alan Cox
2009-01-02 13:50 ` [PATCH 72/75] tty: Fix an ircomm warning and note another bug Alan Cox
2009-01-05 17:42   ` Wolfram Sang
2009-01-05 18:01     ` Alan Cox
2009-01-02 13:50 ` [PATCH 73/75] hso modem detect fix patch against Alan Cox'es tty tree Alan Cox
2009-01-02 13:50 ` [PATCH 74/75] hso maintainers update patch Alan Cox
2009-01-02 13:50 ` [PATCH 75/75] serial_8250: support for Sealevel Systems Model 7803 COMM+8 Alan Cox

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=20090102134225.13472.45638.stgit@localhost.localdomain \
    --to=alan@lxorguk.ukuu.org.uk \
    --cc=linux-serial@vger.kernel.org \
    --cc=torvalds@osdl.org \
    /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