Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 145c3ae4 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6:
  fs: brlock vfsmount_lock
  fs: scale files_lock
  lglock: introduce special lglock and brlock spin locks
  tty: fix fu_list abuse
  fs: cleanup files_lock locking
  fs: remove extra lookup in __lookup_hash
  fs: fs_struct rwlock to spinlock
  apparmor: use task path helpers
  fs: dentry allocation consolidation
  fs: fix do_lookup false negative
  mbcache: Limit the maximum number of cache entries
  hostfs ->follow_link() braino
  hostfs: dumb (and usually harmless) tpyo - strncpy instead of strlcpy
  remove SWRITE* I/O types
  kill BH_Ordered flag
  vfs: update ctime when changing the file's permission by setfacl
  cramfs: only unlock new inodes
  fix reiserfs_evict_inode end_writeback second call
parents 81ca03a0 99b7db7b
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -675,8 +675,8 @@ static int ptmx_open(struct inode *inode, struct file *filp)
	}

	set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
	filp->private_data = tty;
	file_move(filp, &tty->tty_files);

	tty_add_file(tty, filp);

	retval = devpts_pty_new(inode, tty->link);
	if (retval)
+63 −29
Original line number Diff line number Diff line
@@ -136,6 +136,9 @@ LIST_HEAD(tty_drivers); /* linked list of tty drivers */
DEFINE_MUTEX(tty_mutex);
EXPORT_SYMBOL(tty_mutex);

/* Spinlock to protect the tty->tty_files list */
DEFINE_SPINLOCK(tty_files_lock);

static ssize_t tty_read(struct file *, char __user *, size_t, loff_t *);
static ssize_t tty_write(struct file *, const char __user *, size_t, loff_t *);
ssize_t redirected_tty_write(struct file *, const char __user *,
@@ -185,6 +188,41 @@ void free_tty_struct(struct tty_struct *tty)
	kfree(tty);
}

static inline struct tty_struct *file_tty(struct file *file)
{
	return ((struct tty_file_private *)file->private_data)->tty;
}

/* Associate a new file with the tty structure */
void tty_add_file(struct tty_struct *tty, struct file *file)
{
	struct tty_file_private *priv;

	/* XXX: must implement proper error handling in callers */
	priv = kmalloc(sizeof(*priv), GFP_KERNEL|__GFP_NOFAIL);

	priv->tty = tty;
	priv->file = file;
	file->private_data = priv;

	spin_lock(&tty_files_lock);
	list_add(&priv->list, &tty->tty_files);
	spin_unlock(&tty_files_lock);
}

/* Delete file from its tty */
void tty_del_file(struct file *file)
{
	struct tty_file_private *priv = file->private_data;

	spin_lock(&tty_files_lock);
	list_del(&priv->list);
	spin_unlock(&tty_files_lock);
	file->private_data = NULL;
	kfree(priv);
}


#define TTY_NUMBER(tty) ((tty)->index + (tty)->driver->name_base)

/**
@@ -235,11 +273,11 @@ static int check_tty_count(struct tty_struct *tty, const char *routine)
	struct list_head *p;
	int count = 0;

	file_list_lock();
	spin_lock(&tty_files_lock);
	list_for_each(p, &tty->tty_files) {
		count++;
	}
	file_list_unlock();
	spin_unlock(&tty_files_lock);
	if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
	    tty->driver->subtype == PTY_TYPE_SLAVE &&
	    tty->link && tty->link->count)
@@ -497,6 +535,7 @@ void __tty_hangup(struct tty_struct *tty)
	struct file *cons_filp = NULL;
	struct file *filp, *f = NULL;
	struct task_struct *p;
	struct tty_file_private *priv;
	int    closecount = 0, n;
	unsigned long flags;
	int refs = 0;
@@ -506,7 +545,7 @@ void __tty_hangup(struct tty_struct *tty)


	spin_lock(&redirect_lock);
	if (redirect && redirect->private_data == tty) {
	if (redirect && file_tty(redirect) == tty) {
		f = redirect;
		redirect = NULL;
	}
@@ -519,9 +558,10 @@ void __tty_hangup(struct tty_struct *tty)
	   workqueue with the lock held */
	check_tty_count(tty, "tty_hangup");

	file_list_lock();
	spin_lock(&tty_files_lock);
	/* This breaks for file handles being sent over AF_UNIX sockets ? */
	list_for_each_entry(filp, &tty->tty_files, f_u.fu_list) {
	list_for_each_entry(priv, &tty->tty_files, list) {
		filp = priv->file;
		if (filp->f_op->write == redirected_tty_write)
			cons_filp = filp;
		if (filp->f_op->write != tty_write)
@@ -530,7 +570,7 @@ void __tty_hangup(struct tty_struct *tty)
		__tty_fasync(-1, filp, 0);	/* can't block */
		filp->f_op = &hung_up_tty_fops;
	}
	file_list_unlock();
	spin_unlock(&tty_files_lock);

	tty_ldisc_hangup(tty);

@@ -889,12 +929,10 @@ static ssize_t tty_read(struct file *file, char __user *buf, size_t count,
			loff_t *ppos)
{
	int i;
	struct tty_struct *tty;
	struct inode *inode;
	struct inode *inode = file->f_path.dentry->d_inode;
	struct tty_struct *tty = file_tty(file);
	struct tty_ldisc *ld;

	tty = file->private_data;
	inode = file->f_path.dentry->d_inode;
	if (tty_paranoia_check(tty, inode, "tty_read"))
		return -EIO;
	if (!tty || (test_bit(TTY_IO_ERROR, &tty->flags)))
@@ -1065,12 +1103,11 @@ void tty_write_message(struct tty_struct *tty, char *msg)
static ssize_t tty_write(struct file *file, const char __user *buf,
						size_t count, loff_t *ppos)
{
	struct tty_struct *tty;
	struct inode *inode = file->f_path.dentry->d_inode;
	ssize_t ret;
	struct tty_struct *tty = file_tty(file);
 	struct tty_ldisc *ld;
	ssize_t ret;

	tty = file->private_data;
	if (tty_paranoia_check(tty, inode, "tty_write"))
		return -EIO;
	if (!tty || !tty->ops->write ||
@@ -1424,9 +1461,9 @@ static void release_one_tty(struct work_struct *work)
	tty_driver_kref_put(driver);
	module_put(driver->owner);

	file_list_lock();
	spin_lock(&tty_files_lock);
	list_del_init(&tty->tty_files);
	file_list_unlock();
	spin_unlock(&tty_files_lock);

	put_pid(tty->pgrp);
	put_pid(tty->session);
@@ -1507,13 +1544,13 @@ static void release_tty(struct tty_struct *tty, int idx)

int tty_release(struct inode *inode, struct file *filp)
{
	struct tty_struct *tty, *o_tty;
	struct tty_struct *tty = file_tty(filp);
	struct tty_struct *o_tty;
	int	pty_master, tty_closing, o_tty_closing, do_sleep;
	int	devpts;
	int	idx;
	char	buf[64];

	tty = filp->private_data;
	if (tty_paranoia_check(tty, inode, "tty_release_dev"))
		return 0;

@@ -1671,8 +1708,7 @@ int tty_release(struct inode *inode, struct file *filp)
	 *  - do_tty_hangup no longer sees this file descriptor as
	 *    something that needs to be handled for hangups.
	 */
	file_kill(filp);
	filp->private_data = NULL;
	tty_del_file(filp);

	/*
	 * Perform some housekeeping before deciding whether to return.
@@ -1839,8 +1875,8 @@ static int tty_open(struct inode *inode, struct file *filp)
		return PTR_ERR(tty);
	}

	filp->private_data = tty;
	file_move(filp, &tty->tty_files);
	tty_add_file(tty, filp);

	check_tty_count(tty, "tty_open");
	if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
	    tty->driver->subtype == PTY_TYPE_MASTER)
@@ -1916,11 +1952,10 @@ static int tty_open(struct inode *inode, struct file *filp)

static unsigned int tty_poll(struct file *filp, poll_table *wait)
{
	struct tty_struct *tty;
	struct tty_struct *tty = file_tty(filp);
	struct tty_ldisc *ld;
	int ret = 0;

	tty = filp->private_data;
	if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_poll"))
		return 0;

@@ -1933,11 +1968,10 @@ static unsigned int tty_poll(struct file *filp, poll_table *wait)

static int __tty_fasync(int fd, struct file *filp, int on)
{
	struct tty_struct *tty;
	struct tty_struct *tty = file_tty(filp);
	unsigned long flags;
	int retval = 0;

	tty = filp->private_data;
	if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_fasync"))
		goto out;

@@ -2491,13 +2525,13 @@ EXPORT_SYMBOL(tty_pair_get_pty);
 */
long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	struct tty_struct *tty, *real_tty;
	struct tty_struct *tty = file_tty(file);
	struct tty_struct *real_tty;
	void __user *p = (void __user *)arg;
	int retval;
	struct tty_ldisc *ld;
	struct inode *inode = file->f_dentry->d_inode;

	tty = file->private_data;
	if (tty_paranoia_check(tty, inode, "tty_ioctl"))
		return -EINVAL;

@@ -2619,7 +2653,7 @@ static long tty_compat_ioctl(struct file *file, unsigned int cmd,
				unsigned long arg)
{
	struct inode *inode = file->f_dentry->d_inode;
	struct tty_struct *tty = file->private_data;
	struct tty_struct *tty = file_tty(file);
	struct tty_ldisc *ld;
	int retval = -ENOIOCTLCMD;

@@ -2711,7 +2745,7 @@ void __do_SAK(struct tty_struct *tty)
				if (!filp)
					continue;
				if (filp->f_op->read == tty_read &&
				    filp->private_data == tty) {
				    file_tty(filp) == tty) {
					printk(KERN_NOTICE "SAK: killed process %d"
					    " (%s): fd#%d opened to the tty\n",
					    task_pid_nr(p), p->comm, i);
+4 −4
Original line number Diff line number Diff line
@@ -44,9 +44,9 @@ int pohmelfs_construct_path_string(struct pohmelfs_inode *pi, void *data, int le
		return -ENOENT;
	}

	read_lock(&current->fs->lock);
	spin_lock(&current->fs->lock);
	path.mnt = mntget(current->fs->root.mnt);
	read_unlock(&current->fs->lock);
	spin_unlock(&current->fs->lock);

	path.dentry = d;

@@ -91,9 +91,9 @@ int pohmelfs_path_length(struct pohmelfs_inode *pi)
		return -ENOENT;
	}

	read_lock(&current->fs->lock);
	spin_lock(&current->fs->lock);
	root = dget(current->fs->root.dentry);
	read_unlock(&current->fs->lock);
	spin_unlock(&current->fs->lock);

	spin_lock(&dcache_lock);

+37 −32
Original line number Diff line number Diff line
@@ -770,11 +770,12 @@ static int fsync_buffers_list(spinlock_t *lock, struct list_head *list)
				spin_unlock(lock);
				/*
				 * Ensure any pending I/O completes so that
				 * ll_rw_block() actually writes the current
				 * contents - it is a noop if I/O is still in
				 * flight on potentially older contents.
				 * write_dirty_buffer() actually writes the
				 * current contents - it is a noop if I/O is
				 * still in flight on potentially older
				 * contents.
				 */
				ll_rw_block(SWRITE_SYNC_PLUG, 1, &bh);
				write_dirty_buffer(bh, WRITE_SYNC_PLUG);

				/*
				 * Kick off IO for the previous mapping. Note
@@ -2911,13 +2912,6 @@ int submit_bh(int rw, struct buffer_head * bh)
	BUG_ON(buffer_delay(bh));
	BUG_ON(buffer_unwritten(bh));

	/*
	 * Mask in barrier bit for a write (could be either a WRITE or a
	 * WRITE_SYNC
	 */
	if (buffer_ordered(bh) && (rw & WRITE))
		rw |= WRITE_BARRIER;

	/*
	 * Only clear out a write error when rewriting
	 */
@@ -2956,22 +2950,21 @@ EXPORT_SYMBOL(submit_bh);

/**
 * ll_rw_block: low-level access to block devices (DEPRECATED)
 * @rw: whether to %READ or %WRITE or %SWRITE or maybe %READA (readahead)
 * @rw: whether to %READ or %WRITE or maybe %READA (readahead)
 * @nr: number of &struct buffer_heads in the array
 * @bhs: array of pointers to &struct buffer_head
 *
 * ll_rw_block() takes an array of pointers to &struct buffer_heads, and
 * requests an I/O operation on them, either a %READ or a %WRITE.  The third
 * %SWRITE is like %WRITE only we make sure that the *current* data in buffers
 * are sent to disk. The fourth %READA option is described in the documentation
 * for generic_make_request() which ll_rw_block() calls.
 * %READA option is described in the documentation for generic_make_request()
 * which ll_rw_block() calls.
 *
 * This function drops any buffer that it cannot get a lock on (with the
 * BH_Lock state bit) unless SWRITE is required, any buffer that appears to be
 * clean when doing a write request, and any buffer that appears to be
 * up-to-date when doing read request.  Further it marks as clean buffers that
 * are processed for writing (the buffer cache won't assume that they are
 * actually clean until the buffer gets unlocked).
 * BH_Lock state bit), any buffer that appears to be clean when doing a write
 * request, and any buffer that appears to be up-to-date when doing read
 * request.  Further it marks as clean buffers that are processed for
 * writing (the buffer cache won't assume that they are actually clean
 * until the buffer gets unlocked).
 *
 * ll_rw_block sets b_end_io to simple completion handler that marks
 * the buffer up-to-date (if approriate), unlocks the buffer and wakes
@@ -2987,19 +2980,12 @@ void ll_rw_block(int rw, int nr, struct buffer_head *bhs[])
	for (i = 0; i < nr; i++) {
		struct buffer_head *bh = bhs[i];

		if (rw == SWRITE || rw == SWRITE_SYNC || rw == SWRITE_SYNC_PLUG)
			lock_buffer(bh);
		else if (!trylock_buffer(bh))
		if (!trylock_buffer(bh))
			continue;

		if (rw == WRITE || rw == SWRITE || rw == SWRITE_SYNC ||
		    rw == SWRITE_SYNC_PLUG) {
		if (rw == WRITE) {
			if (test_clear_buffer_dirty(bh)) {
				bh->b_end_io = end_buffer_write_sync;
				get_bh(bh);
				if (rw == SWRITE_SYNC)
					submit_bh(WRITE_SYNC, bh);
				else
				submit_bh(WRITE, bh);
				continue;
			}
@@ -3016,12 +3002,25 @@ void ll_rw_block(int rw, int nr, struct buffer_head *bhs[])
}
EXPORT_SYMBOL(ll_rw_block);

void write_dirty_buffer(struct buffer_head *bh, int rw)
{
	lock_buffer(bh);
	if (!test_clear_buffer_dirty(bh)) {
		unlock_buffer(bh);
		return;
	}
	bh->b_end_io = end_buffer_write_sync;
	get_bh(bh);
	submit_bh(rw, bh);
}
EXPORT_SYMBOL(write_dirty_buffer);

/*
 * For a data-integrity writeout, we need to wait upon any in-progress I/O
 * and then start new I/O and then wait upon it.  The caller must have a ref on
 * the buffer_head.
 */
int sync_dirty_buffer(struct buffer_head *bh)
int __sync_dirty_buffer(struct buffer_head *bh, int rw)
{
	int ret = 0;

@@ -3030,7 +3029,7 @@ int sync_dirty_buffer(struct buffer_head *bh)
	if (test_clear_buffer_dirty(bh)) {
		get_bh(bh);
		bh->b_end_io = end_buffer_write_sync;
		ret = submit_bh(WRITE_SYNC, bh);
		ret = submit_bh(rw, bh);
		wait_on_buffer(bh);
		if (buffer_eopnotsupp(bh)) {
			clear_buffer_eopnotsupp(bh);
@@ -3043,6 +3042,12 @@ int sync_dirty_buffer(struct buffer_head *bh)
	}
	return ret;
}
EXPORT_SYMBOL(__sync_dirty_buffer);

int sync_dirty_buffer(struct buffer_head *bh)
{
	return __sync_dirty_buffer(bh, WRITE_SYNC);
}
EXPORT_SYMBOL(sync_dirty_buffer);

/*
+1 −1
Original line number Diff line number Diff line
@@ -80,7 +80,7 @@ static struct inode *get_cramfs_inode(struct super_block *sb,
		}
	} else {
		inode = iget_locked(sb, CRAMINO(cramfs_inode));
		if (inode) {
		if (inode && (inode->i_state & I_NEW)) {
			setup_inode(inode, cramfs_inode);
			unlock_new_inode(inode);
		}
Loading