Commit ee2ffa0dfdd2db19705f2ba1c6a4c0bfe8122dd8

Authored by Nick Piggin
Committed by Al Viro
1 parent b04f784e5d

fs: cleanup files_lock locking

fs: cleanup files_lock locking

Lock tty_files with a new spinlock, tty_files_lock; provide helpers to
manipulate the per-sb files list; unexport the files_lock spinlock.

Cc: linux-kernel@vger.kernel.org
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Acked-by: Andi Kleen <ak@linux.intel.com>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

Showing 7 changed files with 48 additions and 42 deletions Side-by-side Diff

... ... @@ -676,7 +676,11 @@
676 676  
677 677 set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
678 678 filp->private_data = tty;
679   - file_move(filp, &tty->tty_files);
  679 +
  680 + file_sb_list_del(filp); /* __dentry_open has put it on the sb list */
  681 + spin_lock(&tty_files_lock);
  682 + list_add(&filp->f_u.fu_list, &tty->tty_files);
  683 + spin_unlock(&tty_files_lock);
680 684  
681 685 retval = devpts_pty_new(inode, tty->link);
682 686 if (retval)
drivers/char/tty_io.c
... ... @@ -136,6 +136,9 @@
136 136 DEFINE_MUTEX(tty_mutex);
137 137 EXPORT_SYMBOL(tty_mutex);
138 138  
  139 +/* Spinlock to protect the tty->tty_files list */
  140 +DEFINE_SPINLOCK(tty_files_lock);
  141 +
139 142 static ssize_t tty_read(struct file *, char __user *, size_t, loff_t *);
140 143 static ssize_t tty_write(struct file *, const char __user *, size_t, loff_t *);
141 144 ssize_t redirected_tty_write(struct file *, const char __user *,
142 145  
... ... @@ -235,11 +238,11 @@
235 238 struct list_head *p;
236 239 int count = 0;
237 240  
238   - file_list_lock();
  241 + spin_lock(&tty_files_lock);
239 242 list_for_each(p, &tty->tty_files) {
240 243 count++;
241 244 }
242   - file_list_unlock();
  245 + spin_unlock(&tty_files_lock);
243 246 if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
244 247 tty->driver->subtype == PTY_TYPE_SLAVE &&
245 248 tty->link && tty->link->count)
... ... @@ -519,7 +522,7 @@
519 522 workqueue with the lock held */
520 523 check_tty_count(tty, "tty_hangup");
521 524  
522   - file_list_lock();
  525 + spin_lock(&tty_files_lock);
523 526 /* This breaks for file handles being sent over AF_UNIX sockets ? */
524 527 list_for_each_entry(filp, &tty->tty_files, f_u.fu_list) {
525 528 if (filp->f_op->write == redirected_tty_write)
... ... @@ -530,7 +533,7 @@
530 533 __tty_fasync(-1, filp, 0); /* can't block */
531 534 filp->f_op = &hung_up_tty_fops;
532 535 }
533   - file_list_unlock();
  536 + spin_unlock(&tty_files_lock);
534 537  
535 538 tty_ldisc_hangup(tty);
536 539  
537 540  
... ... @@ -1424,9 +1427,9 @@
1424 1427 tty_driver_kref_put(driver);
1425 1428 module_put(driver->owner);
1426 1429  
1427   - file_list_lock();
  1430 + spin_lock(&tty_files_lock);
1428 1431 list_del_init(&tty->tty_files);
1429   - file_list_unlock();
  1432 + spin_unlock(&tty_files_lock);
1430 1433  
1431 1434 put_pid(tty->pgrp);
1432 1435 put_pid(tty->session);
... ... @@ -1671,7 +1674,10 @@
1671 1674 * - do_tty_hangup no longer sees this file descriptor as
1672 1675 * something that needs to be handled for hangups.
1673 1676 */
1674   - file_kill(filp);
  1677 + spin_lock(&tty_files_lock);
  1678 + BUG_ON(list_empty(&filp->f_u.fu_list));
  1679 + list_del_init(&filp->f_u.fu_list);
  1680 + spin_unlock(&tty_files_lock);
1675 1681 filp->private_data = NULL;
1676 1682  
1677 1683 /*
... ... @@ -1840,7 +1846,11 @@
1840 1846 }
1841 1847  
1842 1848 filp->private_data = tty;
1843   - file_move(filp, &tty->tty_files);
  1849 + BUG_ON(list_empty(&filp->f_u.fu_list));
  1850 + file_sb_list_del(filp); /* __dentry_open has put it on the sb list */
  1851 + spin_lock(&tty_files_lock);
  1852 + list_add(&filp->f_u.fu_list, &tty->tty_files);
  1853 + spin_unlock(&tty_files_lock);
1844 1854 check_tty_count(tty, "tty_open");
1845 1855 if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
1846 1856 tty->driver->subtype == PTY_TYPE_MASTER)
... ... @@ -32,8 +32,7 @@
32 32 .max_files = NR_FILE
33 33 };
34 34  
35   -/* public. Not pretty! */
36   -__cacheline_aligned_in_smp DEFINE_SPINLOCK(files_lock);
  35 +static __cacheline_aligned_in_smp DEFINE_SPINLOCK(files_lock);
37 36  
38 37 /* SLAB cache for file structures */
39 38 static struct kmem_cache *filp_cachep __read_mostly;
... ... @@ -249,7 +248,7 @@
249 248 cdev_put(inode->i_cdev);
250 249 fops_put(file->f_op);
251 250 put_pid(file->f_owner.pid);
252   - file_kill(file);
  251 + file_sb_list_del(file);
253 252 if (file->f_mode & FMODE_WRITE)
254 253 drop_file_write_access(file);
255 254 file->f_path.dentry = NULL;
256 255  
257 256  
258 257  
259 258  
260 259  
261 260  
... ... @@ -328,31 +327,29 @@
328 327 return file;
329 328 }
330 329  
331   -
332 330 void put_filp(struct file *file)
333 331 {
334 332 if (atomic_long_dec_and_test(&file->f_count)) {
335 333 security_file_free(file);
336   - file_kill(file);
  334 + file_sb_list_del(file);
337 335 file_free(file);
338 336 }
339 337 }
340 338  
341   -void file_move(struct file *file, struct list_head *list)
  339 +void file_sb_list_add(struct file *file, struct super_block *sb)
342 340 {
343   - if (!list)
344   - return;
345   - file_list_lock();
346   - list_move(&file->f_u.fu_list, list);
347   - file_list_unlock();
  341 + spin_lock(&files_lock);
  342 + BUG_ON(!list_empty(&file->f_u.fu_list));
  343 + list_add(&file->f_u.fu_list, &sb->s_files);
  344 + spin_unlock(&files_lock);
348 345 }
349 346  
350   -void file_kill(struct file *file)
  347 +void file_sb_list_del(struct file *file)
351 348 {
352 349 if (!list_empty(&file->f_u.fu_list)) {
353   - file_list_lock();
  350 + spin_lock(&files_lock);
354 351 list_del_init(&file->f_u.fu_list);
355   - file_list_unlock();
  352 + spin_unlock(&files_lock);
356 353 }
357 354 }
358 355  
... ... @@ -361,7 +358,7 @@
361 358 struct file *file;
362 359  
363 360 /* Check that no files are currently opened for writing. */
364   - file_list_lock();
  361 + spin_lock(&files_lock);
365 362 list_for_each_entry(file, &sb->s_files, f_u.fu_list) {
366 363 struct inode *inode = file->f_path.dentry->d_inode;
367 364  
368 365  
... ... @@ -373,10 +370,10 @@
373 370 if (S_ISREG(inode->i_mode) && (file->f_mode & FMODE_WRITE))
374 371 goto too_bad;
375 372 }
376   - file_list_unlock();
  373 + spin_unlock(&files_lock);
377 374 return 1; /* Tis' cool bro. */
378 375 too_bad:
379   - file_list_unlock();
  376 + spin_unlock(&files_lock);
380 377 return 0;
381 378 }
382 379  
... ... @@ -392,7 +389,7 @@
392 389 struct file *f;
393 390  
394 391 retry:
395   - file_list_lock();
  392 + spin_lock(&files_lock);
396 393 list_for_each_entry(f, &sb->s_files, f_u.fu_list) {
397 394 struct vfsmount *mnt;
398 395 if (!S_ISREG(f->f_path.dentry->d_inode->i_mode))
399 396  
... ... @@ -408,16 +405,13 @@
408 405 continue;
409 406 file_release_write(f);
410 407 mnt = mntget(f->f_path.mnt);
411   - file_list_unlock();
412   - /*
413   - * This can sleep, so we can't hold
414   - * the file_list_lock() spinlock.
415   - */
  408 + /* This can sleep, so we can't hold the spinlock. */
  409 + spin_unlock(&files_lock);
416 410 mnt_drop_write(mnt);
417 411 mntput(mnt);
418 412 goto retry;
419 413 }
420   - file_list_unlock();
  414 + spin_unlock(&files_lock);
421 415 }
422 416  
423 417 void __init files_init(unsigned long mempages)
... ... @@ -675,7 +675,7 @@
675 675 f->f_path.mnt = mnt;
676 676 f->f_pos = 0;
677 677 f->f_op = fops_get(inode->i_fop);
678   - file_move(f, &inode->i_sb->s_files);
  678 + file_sb_list_add(f, inode->i_sb);
679 679  
680 680 error = security_dentry_open(f, cred);
681 681 if (error)
... ... @@ -721,7 +721,7 @@
721 721 mnt_drop_write(mnt);
722 722 }
723 723 }
724   - file_kill(f);
  724 + file_sb_list_del(f);
725 725 f->f_path.dentry = NULL;
726 726 f->f_path.mnt = NULL;
727 727 cleanup_file:
... ... @@ -944,9 +944,6 @@
944 944 unsigned long f_mnt_write_state;
945 945 #endif
946 946 };
947   -extern spinlock_t files_lock;
948   -#define file_list_lock() spin_lock(&files_lock);
949   -#define file_list_unlock() spin_unlock(&files_lock);
950 947  
951 948 #define get_file(x) atomic_long_inc(&(x)->f_count)
952 949 #define fput_atomic(x) atomic_long_add_unless(&(x)->f_count, -1, 1)
... ... @@ -2188,8 +2185,8 @@
2188 2185 __insert_inode_hash(inode, inode->i_ino);
2189 2186 }
2190 2187  
2191   -extern void file_move(struct file *f, struct list_head *list);
2192   -extern void file_kill(struct file *f);
  2188 +extern void file_sb_list_add(struct file *f, struct super_block *sb);
  2189 +extern void file_sb_list_del(struct file *f);
2193 2190 #ifdef CONFIG_BLOCK
2194 2191 extern void submit_bio(int, struct bio *);
2195 2192 extern int bdev_read_only(struct block_device *);
... ... @@ -470,6 +470,7 @@
470 470 extern struct tty_struct *tty_pair_get_pty(struct tty_struct *tty);
471 471  
472 472 extern struct mutex tty_mutex;
  473 +extern spinlock_t tty_files_lock;
473 474  
474 475 extern void tty_write_unlock(struct tty_struct *tty);
475 476 extern int tty_write_lock(struct tty_struct *tty, int ndelay);
security/selinux/hooks.c
... ... @@ -2170,7 +2170,7 @@
2170 2170  
2171 2171 tty = get_current_tty();
2172 2172 if (tty) {
2173   - file_list_lock();
  2173 + spin_lock(&tty_files_lock);
2174 2174 if (!list_empty(&tty->tty_files)) {
2175 2175 struct inode *inode;
2176 2176  
... ... @@ -2186,7 +2186,7 @@
2186 2186 drop_tty = 1;
2187 2187 }
2188 2188 }
2189   - file_list_unlock();
  2189 + spin_unlock(&tty_files_lock);
2190 2190 tty_kref_put(tty);
2191 2191 }
2192 2192 /* Reset controlling tty. */