static int ptmx_open(struct inode *inode, struct file *filp) { struct tty_struct *tty; int retval; int index; nonseekable_open(inode, filp); /* We refuse fsnotify events on ptmx, since it's a shared resource */ filp->f_mode |= FMODE_NONOTIFY; retval = tty_alloc_file(filp); if (retval) return retval; /* find a device that is not in use. */ tty_lock(); index = devpts_new_index(inode); tty_unlock(); if (index < 0) { retval = index; goto err_file; } mutex_lock(&tty_mutex); tty_lock(); tty = tty_init_dev(ptm_driver, index, 1); mutex_unlock(&tty_mutex); if (IS_ERR(tty)) { retval = PTR_ERR(tty); goto out; } set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ tty_add_file(tty, filp); retval = devpts_pty_new(inode, tty->link); if (retval) goto err_release; retval = ptm_driver->ops->open(tty, filp); if (retval) goto err_release; tty_unlock(); return 0; err_release: tty_unlock(); tty_release(inode, filp); return retval; out: devpts_kill_index(inode, index); tty_unlock(); err_file: tty_free_file(filp); return retval; }
/* this is called once with whichever end is closed last */ static void pty_unix98_shutdown(struct tty_struct *tty) { struct inode *ptmx_inode; if (tty->driver->subtype == PTY_TYPE_MASTER) ptmx_inode = tty->driver_data; else ptmx_inode = tty->link->driver_data; devpts_kill_index(ptmx_inode, tty->index); devpts_del_ref(ptmx_inode); }
/* this is called once with whichever end is closed last */ static void pty_unix98_remove(struct tty_driver *driver, struct tty_struct *tty) { struct pts_fs_info *fsi; if (tty->driver->subtype == PTY_TYPE_MASTER) fsi = tty->driver_data; else fsi = tty->link->driver_data; if (fsi) { devpts_kill_index(fsi, tty->index); devpts_release(fsi); } }
static int ptmx_open(struct inode *inode, struct file *filp) { struct tty_struct *tty; int retval; int index; nonseekable_open(inode, filp); /* find a device that is not in use. */ tty_lock(); index = devpts_new_index(inode); tty_unlock(); if (index < 0) return index; mutex_lock(&tty_mutex); tty_lock(); tty = tty_init_dev(ptm_driver, index, 1); mutex_unlock(&tty_mutex); if (IS_ERR(tty)) { retval = PTR_ERR(tty); goto out; } set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ tty_add_file(tty, filp); retval = devpts_pty_new(inode, tty->link); if (retval) goto out1; retval = ptm_driver->ops->open(tty, filp); if (retval) goto out2; out1: tty_unlock(); return retval; out2: tty_unlock(); tty_release(inode, filp); return retval; out: devpts_kill_index(inode, index); tty_unlock(); return retval; }
static int ptmx_open(struct inode *inode, struct file *filp) { struct tty_struct *tty; struct inode *slave_inode; int retval; int index; nonseekable_open(inode, filp); /* We refuse fsnotify events on ptmx, since it's a shared resource */ filp->f_mode |= FMODE_NONOTIFY; retval = tty_alloc_file(filp); if (retval) return retval; /* find a device that is not in use. */ mutex_lock(&devpts_mutex); index = devpts_new_index(inode); if (index < 0) { retval = index; mutex_unlock(&devpts_mutex); goto err_file; } mutex_unlock(&devpts_mutex); mutex_lock(&tty_mutex); tty = tty_init_dev(ptm_driver, index); if (IS_ERR(tty)) { retval = PTR_ERR(tty); goto out; } /* The tty returned here is locked so we can safely drop the mutex */ mutex_unlock(&tty_mutex); set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ tty->driver_data = inode; /* * In the case where all references to ptmx inode are dropped and we * still have /dev/tty opened pointing to the master/slave pair (ptmx * is closed/released before /dev/tty), we must make sure that the inode * is still valid when we call the final pty_unix98_shutdown, thus we * hold an additional reference to the ptmx inode. For the same /dev/tty * last close case, we also need to make sure the super_block isn't * destroyed (devpts instance unmounted), before /dev/tty is closed and * on its release devpts_kill_index is called. */ devpts_add_ref(inode); tty_add_file(tty, filp); slave_inode = devpts_pty_new(inode, MKDEV(UNIX98_PTY_SLAVE_MAJOR, index), index, tty->link); if (IS_ERR(slave_inode)) { retval = PTR_ERR(slave_inode); goto err_release; } tty->link->driver_data = slave_inode; retval = ptm_driver->ops->open(tty, filp); if (retval) goto err_release; tty_unlock(tty); return 0; err_release: tty_unlock(tty); tty_release(inode, filp); return retval; out: mutex_unlock(&tty_mutex); devpts_kill_index(inode, index); err_file: tty_free_file(filp); return retval; }
static int ptmx_open(struct inode *inode, struct file *filp) { struct tty_struct *tty; struct inode *slave_inode; int retval; int index; nonseekable_open(inode, filp); /* We refuse fsnotify events on ptmx, since it's a shared resource */ filp->f_mode |= FMODE_NONOTIFY; retval = tty_alloc_file(filp); if (retval) return retval; /* find a device that is not in use. */ mutex_lock(&devpts_mutex); index = devpts_new_index(inode); if (index < 0) { retval = index; mutex_unlock(&devpts_mutex); goto err_file; } mutex_unlock(&devpts_mutex); mutex_lock(&tty_mutex); tty = tty_init_dev(ptm_driver, index); if (IS_ERR(tty)) { retval = PTR_ERR(tty); goto out; } /* The tty returned here is locked so we can safely drop the mutex */ mutex_unlock(&tty_mutex); set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ tty->driver_data = inode; tty_add_file(tty, filp); slave_inode = devpts_pty_new(inode, MKDEV(UNIX98_PTY_SLAVE_MAJOR, index), index, tty->link); if (IS_ERR(slave_inode)) { retval = PTR_ERR(slave_inode); goto err_release; } tty->link->driver_data = slave_inode; retval = ptm_driver->ops->open(tty, filp); if (retval) goto err_release; tty_unlock(tty); return 0; err_release: tty_unlock(tty); tty_release(inode, filp); return retval; out: mutex_unlock(&tty_mutex); devpts_kill_index(inode, index); err_file: tty_free_file(filp); return retval; }
/* this is called once with whichever end is closed last */ static void pty_unix98_shutdown(struct tty_struct *tty) { devpts_kill_index(tty->driver_data, tty->index); }
static int ptmx_open(struct inode *inode, struct file *filp) { struct pts_fs_info *fsi; struct tty_struct *tty; struct dentry *dentry; int retval; int index; nonseekable_open(inode, filp); /* We refuse fsnotify events on ptmx, since it's a shared resource */ filp->f_mode |= FMODE_NONOTIFY; retval = tty_alloc_file(filp); if (retval) return retval; fsi = devpts_acquire(filp); if (IS_ERR(fsi)) { retval = PTR_ERR(fsi); goto out_free_file; } /* find a device that is not in use. */ mutex_lock(&devpts_mutex); index = devpts_new_index(fsi); mutex_unlock(&devpts_mutex); retval = index; if (index < 0) goto out_put_fsi; mutex_lock(&tty_mutex); tty = tty_init_dev(ptm_driver, index); /* The tty returned here is locked so we can safely drop the mutex */ mutex_unlock(&tty_mutex); retval = PTR_ERR(tty); if (IS_ERR(tty)) goto out; /* * From here on out, the tty is "live", and the index and * fsi will be killed/put by the tty_release() */ set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ tty->driver_data = fsi; tty_add_file(tty, filp); dentry = devpts_pty_new(fsi, index, tty->link); if (IS_ERR(dentry)) { retval = PTR_ERR(dentry); goto err_release; } tty->link->driver_data = dentry; retval = ptm_driver->ops->open(tty, filp); if (retval) goto err_release; tty_debug_hangup(tty, "opening (count=%d)\n", tty->count); tty_unlock(tty); return 0; err_release: tty_unlock(tty); // This will also put-ref the fsi tty_release(inode, filp); return retval; out: devpts_kill_index(fsi, index); out_put_fsi: devpts_release(fsi); out_free_file: tty_free_file(filp); return retval; }