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 */