From: Sukadev Bhattiprolu <sukadev@xxxxxxxxxx> Subject: [PATCH 10/11]: Ability to internally create ptmx /dev/ptmx is closely tied to the devpts filesystem. An open of /dev/ptmx, allocates the next pty index and the associated device shows up in the devpts fs as /dev/pts/n. Wih multiple instancs of devpts filesystem, during an open of /dev/ptmx we would be unable to determine which instance of the devpts is being accessed. So we move the 'ptmx' node into /dev/pts and use the inode of the 'ptmx' node to identify the superblock and hence the devpts instance. This patch adds ability for the kernel to internally create the [ptmx, c, 5:2] device when mounting devpts filesystem. The permissions for the device node can be specified by the '-o ptmxmode=0666' option. The default 'ptmxmode' is 0666. See next patch ("PATCH [11/11] Enable multiple instances of devpts") for usage of this interface, user-space impact and backward compatibility issues Changelog[v3]: - Rename ptmx_mode to ptmxmode (for consistency with 'newinstance') Changelog[v2]: - [H. Peter Anvin] Remove mknod() system call support and create the ptmx node internally. Changelog[v1]: - Earlier version of this patch enabled creating /dev/pts/tty as well. As pointed out by Al Viro and H. Peter Anvin, that is not really necessary. Signed-off-by: Sukadev Bhattiprolu <sukadev@xxxxxxxxxx> --- fs/devpts/inode.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 2 deletions(-) Index: linux-2.6.27-rc3-tty/fs/devpts/inode.c =================================================================== --- linux-2.6.27-rc3-tty.orig/fs/devpts/inode.c 2008-09-03 21:33:46.000000000 -0700 +++ linux-2.6.27-rc3-tty/fs/devpts/inode.c 2008-09-03 21:34:36.000000000 -0700 @@ -27,6 +27,7 @@ #define DEVPTS_SUPER_MAGIC 0x1cd1 #define DEVPTS_DEFAULT_MODE 0600 +#define DEVPTS_DEFAULT_PTMX_MODE 0666 #define PTMX_MINOR 2 extern int pty_limit; /* Config limit on Unix98 ptys */ @@ -40,10 +41,11 @@ struct pts_mount_opts { uid_t uid; gid_t gid; umode_t mode; + umode_t ptmxmode; }; enum { - Opt_uid, Opt_gid, Opt_mode, + Opt_uid, Opt_gid, Opt_mode, Opt_ptmxmode, Opt_err }; @@ -51,6 +53,7 @@ static match_table_t tokens = { {Opt_uid, "uid=%u"}, {Opt_gid, "gid=%u"}, {Opt_mode, "mode=%o"}, + {Opt_ptmxmode, "ptmxmode=%o"}, {Opt_err, NULL} }; @@ -81,6 +84,7 @@ static int parse_mount_options(char *dat opts->uid = 0; opts->gid = 0; opts->mode = DEVPTS_DEFAULT_MODE; + opts->ptmxmode = DEVPTS_DEFAULT_PTMX_MODE; while ((p = strsep(&data, ",")) != NULL) { substring_t args[MAX_OPT_ARGS]; @@ -109,6 +113,11 @@ static int parse_mount_options(char *dat return -EINVAL; opts->mode = option & S_IALLUGO; break; + case Opt_ptmxmode: + if (match_octal(&args[0], &option)) + return -EINVAL; + opts->ptmxmode = option & S_IALLUGO; + break; default: printk(KERN_ERR "devpts: called with bogus options\n"); return -EINVAL; @@ -136,6 +145,7 @@ static int devpts_show_options(struct se if (opts->setgid) seq_printf(seq, ",gid=%u", opts->gid); seq_printf(seq, ",mode=%03o", opts->mode); + seq_printf(seq, ",ptmxmode=%03o", opts->ptmxmode); return 0; } @@ -156,6 +166,7 @@ static void *new_pts_fs_info(void) ida_init(&fsi->allocated_ptys); fsi->mount_opts.mode = DEVPTS_DEFAULT_MODE; + fsi->mount_opts.ptmxmode = DEVPTS_DEFAULT_PTMX_MODE; return fsi; } @@ -201,6 +212,53 @@ fail: return -ENOMEM; } +int mknod_ptmx(struct super_block *sb) +{ + struct dentry *root; + struct dentry *dentry; + struct inode *inode; + struct pts_fs_info *fsi = DEVPTS_SB(sb); + struct pts_mount_opts *opts = &fsi->mount_opts; + int mode; + + root = sb->s_root; + dentry = lookup_one_len("ptmx", root, 4); + if (IS_ERR(dentry)) { + printk(KERN_ERR "Unable to alloc dentry for ptmx node\n"); + return -ENOMEM; + } + + if (dentry->d_inode) { + printk(KERN_ERR "'ptmx' (ino %lu) exists in this devpts\n", + dentry->d_inode->i_ino); + return 0; + } + + /* + * Create a new 'ptmx' node in this mount of devpts. + */ + inode = new_inode(sb); + if (!inode) { + printk(KERN_ERR "Unable to alloc inode for ptmx node\n"); + dput(dentry); + return -ENOMEM; + } + + inode->i_uid = inode->i_gid = 0; + inode->i_blocks = 0; + inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; + + mode = S_IFCHR|opts->ptmxmode; + init_special_inode(inode, mode, MKDEV(TTYAUX_MAJOR, 2)); + + d_add(dentry, inode); // d_instantiate() should be enough ? + + printk(KERN_DEBUG "Created ptmx node in devpts ino %lu\n", + inode->i_ino); + + return 0; +} + static int devpts_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, struct vfsmount *mnt) { @@ -213,7 +271,7 @@ static void devpts_kill_sb(struct super_ struct pts_fs_info *fsi = DEVPTS_SB(sb); kfree(fsi); - kill_anon_super(sb); + kill_litter_super(sb); } static struct file_system_type devpts_fs_type = { _______________________________________________ Containers mailing list Containers@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linux-foundation.org/mailman/listinfo/containers