DONE.
:)

If seriously, it's first working prototype for comments and objections.

It's working as follow:

Mount first ptyfs instance in /dev/pts(or other path) you can get access to 
master side
through ptm{x} device.

Mount second ptyfs instance inside chroot(Example: /var/chroot/test/dev/pts), 
create ptm{x}
device inside chroot(Ex. /var/chroot/test/dev/ptm{x}). 
Chroot: chroot /var/chroot/test /rescue/sh,
now you can see only second instance in /dev/pts.

 ptyfs_vfsops.c |   47 +++++++++++++++++++++++++++++++++++------------
 1 file changed, 35 insertions(+), 12 deletions(-)

I'm leaving for the weekend till Monday.
Best regards.
Ilya.

Index: fs/ptyfs/ptyfs_vfsops.c
===================================================================
RCS file: /cvsil/nbcur/src/sys/fs/ptyfs/ptyfs_vfsops.c,v
retrieving revision 1.9
diff -u -r1.9 ptyfs_vfsops.c
--- fs/ptyfs/ptyfs_vfsops.c	19 Mar 2014 21:00:16 -0000	1.9
+++ fs/ptyfs/ptyfs_vfsops.c	21 Mar 2014 17:55:54 -0000
@@ -83,6 +83,8 @@
  */
 struct ptm_pty *ptyfs_save_ptm;
 static int ptyfs_count;
+#define PTYFS_MINSTANCE 16
+static struct mount *ptyfs_mp[PTYFS_MINSTANCE] = { NULL };
 
 struct ptm_pty ptm_ptyfspty = {
 	ptyfs__allocvp,
@@ -124,13 +126,25 @@
 	return rv;
 }
 
+static struct mount *
+ptyfs__mpget(struct lwp *l) {
+	int i;
+	for (i = 0; i < PTYFS_MINSTANCE; i++)
+		if (ptyfs_mp[i] != NULL &&
+			ptyfs__getpath(l, ptyfs_mp[i]) != NULL)
+			return ptyfs_mp[i];
+	return NULL;
+}
+
 static int
 ptyfs__makename(struct ptm_pty *pt, struct lwp *l, char *tbuf, size_t bufsiz,
     dev_t dev, char ms)
 {
-	struct mount *mp = pt->arg;
 	size_t len;
 	const char *np;
+	struct mount *mp = ptyfs__mpget(l);
+	if (mp == NULL)
+		return EOPNOTSUPP;
 
 	switch (ms) {
 	case 'p':
@@ -157,8 +171,10 @@
 ptyfs__allocvp(struct ptm_pty *pt, struct lwp *l, struct vnode **vpp,
     dev_t dev, char ms)
 {
-	struct mount *mp = pt->arg;
 	ptyfstype type;
+	struct mount *mp = ptyfs__mpget(l);
+	if (mp == NULL)
+		return EOPNOTSUPP;
 
 	switch (ms) {
 	case 'p':
@@ -178,7 +194,7 @@
 static void
 ptyfs__getvattr(struct ptm_pty *pt, struct lwp *l, struct vattr *vattr)
 {
-	struct mount *mp = pt->arg;
+	struct mount *mp = ptyfs__mpget(l);
 	struct ptyfsmount *pmnt = VFSTOPTY(mp);
 	vattr_null(vattr);
 	/* get real uid */
@@ -220,7 +236,7 @@
 ptyfs_mount(struct mount *mp, const char *path, void *data, size_t *data_len)
 {
 	struct lwp *l = curlwp;
-	int error = 0;
+	int i, error = 0;
 	struct ptyfsmount *pmnt;
 	struct ptyfs_args *args = data;
 
@@ -247,11 +263,9 @@
 		return 0;
 	}
 
-#if 0
-	/* Don't allow more than one mount */
-	if (ptyfs_count)
+	/* Don't allow more than PTYFS_MINSTANCE mount */
+	if (PTYFS_MINSTANCE <= ptyfs_count)
 		return EBUSY;
-#endif
 
 	if (mp->mnt_flag & MNT_UPDATE)
 		return EOPNOTSUPP;
@@ -278,10 +292,13 @@
 	}
 
 	/* Point pty access to us */
-	if (ptyfs_count == 0) {
-		ptm_ptyfspty.arg = mp;
+	if (ptyfs_count == 0)
 		ptyfs_save_ptm = pty_sethandler(&ptm_ptyfspty);
-	}
+	for (i = 0; i < PTYFS_MINSTANCE; i++)
+		if (ptyfs_mp[i] == NULL) {
+			ptyfs_mp[i] = mp;
+			break;
+		}
 	ptyfs_count++;
 	return 0;
 }
@@ -297,7 +314,7 @@
 int
 ptyfs_unmount(struct mount *mp, int mntflags)
 {
-	int error;
+	int error, i;
 	int flags = 0;
 
 	if (mntflags & MNT_FORCE)
@@ -306,6 +323,12 @@
 	if ((error = vflush(mp, 0, flags)) != 0)
 		return error;
 
+	for (i = 0; i < PTYFS_MINSTANCE; i++)
+		if (ptyfs_mp[i] == mp) {
+			ptyfs_mp[i] = NULL;
+			break;
+		}
+
 	ptyfs_count--;
 	if (ptyfs_count == 0) {
 		/* Restore where pty access was pointing */

Reply via email to