示例#1
0
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;
}
示例#2
0
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;
}
示例#3
0
文件: pty.c 项目: 7799/linux
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;
}
示例#4
0
文件: pty.c 项目: 513855417/linux
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;
}