X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=fs%2Fdevpts%2Finode.c;h=285b64a8b06e125b1aee42a8317cfd0873d69f20;hb=706546d02384b64e083bd9130c56eaa599c66038;hp=643e57b622bd64c9e88d09f61355e55fd0220a8e;hpb=81450b73dde07f473a4a7208b209b4c8b7251d90;p=linux-2.6-omap-h63xx.git diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c index 643e57b622b..285b64a8b06 100644 --- a/fs/devpts/inode.c +++ b/fs/devpts/inode.c @@ -17,11 +17,21 @@ #include #include #include +#include +#include #include #include +#include +#include #define DEVPTS_SUPER_MAGIC 0x1cd1 +#define DEVPTS_DEFAULT_MODE 0600 + +extern int pty_limit; /* Config limit on Unix98 ptys */ +static DEFINE_IDR(allocated_ptys); +static DEFINE_MUTEX(allocated_ptys_lock); + static struct vfsmount *devpts_mnt; static struct dentry *devpts_root; @@ -31,7 +41,7 @@ static struct { uid_t uid; gid_t gid; umode_t mode; -} config = {.mode = 0600}; +} config = {.mode = DEVPTS_DEFAULT_MODE}; enum { Opt_uid, Opt_gid, Opt_mode, @@ -53,7 +63,7 @@ static int devpts_remount(struct super_block *sb, int *flags, char *data) config.setgid = 0; config.uid = 0; config.gid = 0; - config.mode = 0600; + config.mode = DEVPTS_DEFAULT_MODE; while ((p = strsep(&data, ",")) != NULL) { substring_t args[MAX_OPT_ARGS]; @@ -80,7 +90,7 @@ static int devpts_remount(struct super_block *sb, int *flags, char *data) case Opt_mode: if (match_octal(&args[0], &option)) return -EINVAL; - config.mode = option & ~S_IFMT; + config.mode = option & S_IALLUGO; break; default: printk(KERN_ERR "devpts: called with bogus options\n"); @@ -91,9 +101,21 @@ static int devpts_remount(struct super_block *sb, int *flags, char *data) return 0; } +static int devpts_show_options(struct seq_file *seq, struct vfsmount *vfs) +{ + if (config.setuid) + seq_printf(seq, ",uid=%u", config.uid); + if (config.setgid) + seq_printf(seq, ",gid=%u", config.gid); + seq_printf(seq, ",mode=%03o", config.mode); + + return 0; +} + static const struct super_operations devpts_sops = { .statfs = simple_statfs, .remount_fs = devpts_remount, + .show_options = devpts_show_options, }; static int @@ -155,9 +177,44 @@ static struct dentry *get_node(int num) return lookup_one_len(s, root, sprintf(s, "%d", num)); } +int devpts_new_index(void) +{ + int index; + int idr_ret; + +retry: + if (!idr_pre_get(&allocated_ptys, GFP_KERNEL)) { + return -ENOMEM; + } + + mutex_lock(&allocated_ptys_lock); + idr_ret = idr_get_new(&allocated_ptys, NULL, &index); + if (idr_ret < 0) { + mutex_unlock(&allocated_ptys_lock); + if (idr_ret == -EAGAIN) + goto retry; + return -EIO; + } + + if (index >= pty_limit) { + idr_remove(&allocated_ptys, index); + mutex_unlock(&allocated_ptys_lock); + return -EIO; + } + mutex_unlock(&allocated_ptys_lock); + return index; +} + +void devpts_kill_index(int idx) +{ + mutex_lock(&allocated_ptys_lock); + idr_remove(&allocated_ptys, idx); + mutex_unlock(&allocated_ptys_lock); +} + int devpts_pty_new(struct tty_struct *tty) { - int number = tty->index; + int number = tty->index; /* tty layer puts index from devpts_new_index() in here */ struct tty_driver *driver = tty->driver; dev_t device = MKDEV(driver->major, driver->minor_start+number); struct dentry *dentry; @@ -178,8 +235,10 @@ int devpts_pty_new(struct tty_struct *tty) inode->i_private = tty; dentry = get_node(number); - if (!IS_ERR(dentry) && !dentry->d_inode) + if (!IS_ERR(dentry) && !dentry->d_inode) { d_instantiate(dentry, inode); + fsnotify_create(devpts_root->d_inode, dentry); + } mutex_unlock(&devpts_root->d_inode->i_mutex);