aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/char/pty.c6
-rw-r--r--drivers/char/tty_io.c27
-rw-r--r--fs/file_table.c42
-rw-r--r--fs/open.c4
-rw-r--r--include/linux/fs.h9
-rw-r--r--include/linux/tty.h1
-rw-r--r--security/selinux/hooks.c4
7 files changed, 50 insertions, 43 deletions
diff --git a/drivers/char/pty.c b/drivers/char/pty.c
index 385c44b3034f..8fa273e76bb3 100644
--- a/drivers/char/pty.c
+++ b/drivers/char/pty.c
@@ -649,7 +649,11 @@ static int __ptmx_open(struct inode *inode, struct file *filp)
649 649
650 set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ 650 set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
651 filp->private_data = tty; 651 filp->private_data = tty;
652 file_move(filp, &tty->tty_files); 652
653 file_sb_list_del(filp); /* __dentry_open has put it on the sb list */
654 spin_lock(&tty_files_lock);
655 list_add(&filp->f_u.fu_list, &tty->tty_files);
656 spin_unlock(&tty_files_lock);
653 657
654 retval = devpts_pty_new(inode, tty->link); 658 retval = devpts_pty_new(inode, tty->link);
655 if (retval) 659 if (retval)
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 76253cf27028..38ddfa404fb1 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -136,6 +136,9 @@ LIST_HEAD(tty_drivers); /* linked list of tty drivers */
136DEFINE_MUTEX(tty_mutex); 136DEFINE_MUTEX(tty_mutex);
137EXPORT_SYMBOL(tty_mutex); 137EXPORT_SYMBOL(tty_mutex);
138 138
139/* Spinlock to protect the tty->tty_files list */
140DEFINE_SPINLOCK(tty_files_lock);
141
139static ssize_t tty_read(struct file *, char __user *, size_t, loff_t *); 142static ssize_t tty_read(struct file *, char __user *, size_t, loff_t *);
140static ssize_t tty_write(struct file *, const char __user *, size_t, loff_t *); 143static ssize_t tty_write(struct file *, const char __user *, size_t, loff_t *);
141ssize_t redirected_tty_write(struct file *, const char __user *, 144ssize_t redirected_tty_write(struct file *, const char __user *,
@@ -234,11 +237,11 @@ static int check_tty_count(struct tty_struct *tty, const char *routine)
234 struct list_head *p; 237 struct list_head *p;
235 int count = 0; 238 int count = 0;
236 239
237 file_list_lock(); 240 spin_lock(&tty_files_lock);
238 list_for_each(p, &tty->tty_files) { 241 list_for_each(p, &tty->tty_files) {
239 count++; 242 count++;
240 } 243 }
241 file_list_unlock(); 244 spin_unlock(&tty_files_lock);
242 if (tty->driver->type == TTY_DRIVER_TYPE_PTY && 245 if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
243 tty->driver->subtype == PTY_TYPE_SLAVE && 246 tty->driver->subtype == PTY_TYPE_SLAVE &&
244 tty->link && tty->link->count) 247 tty->link && tty->link->count)
@@ -516,8 +519,7 @@ static void do_tty_hangup(struct work_struct *work)
516 /* inuse_filps is protected by the single kernel lock */ 519 /* inuse_filps is protected by the single kernel lock */
517 lock_kernel(); 520 lock_kernel();
518 check_tty_count(tty, "do_tty_hangup"); 521 check_tty_count(tty, "do_tty_hangup");
519 522 spin_lock(&tty_files_lock);
520 file_list_lock();
521 /* This breaks for file handles being sent over AF_UNIX sockets ? */ 523 /* This breaks for file handles being sent over AF_UNIX sockets ? */
522 list_for_each_entry(filp, &tty->tty_files, f_u.fu_list) { 524 list_for_each_entry(filp, &tty->tty_files, f_u.fu_list) {
523 if (filp->f_op->write == redirected_tty_write) 525 if (filp->f_op->write == redirected_tty_write)
@@ -528,7 +530,7 @@ static void do_tty_hangup(struct work_struct *work)
528 tty_fasync(-1, filp, 0); /* can't block */ 530 tty_fasync(-1, filp, 0); /* can't block */
529 filp->f_op = &hung_up_tty_fops; 531 filp->f_op = &hung_up_tty_fops;
530 } 532 }
531 file_list_unlock(); 533 spin_unlock(&tty_files_lock);
532 534
533 tty_ldisc_hangup(tty); 535 tty_ldisc_hangup(tty);
534 536
@@ -1419,9 +1421,9 @@ static void release_one_tty(struct work_struct *work)
1419 tty_driver_kref_put(driver); 1421 tty_driver_kref_put(driver);
1420 module_put(driver->owner); 1422 module_put(driver->owner);
1421 1423
1422 file_list_lock(); 1424 spin_lock(&tty_files_lock);
1423 list_del_init(&tty->tty_files); 1425 list_del_init(&tty->tty_files);
1424 file_list_unlock(); 1426 spin_unlock(&tty_files_lock);
1425 1427
1426 put_pid(tty->pgrp); 1428 put_pid(tty->pgrp);
1427 put_pid(tty->session); 1429 put_pid(tty->session);
@@ -1666,7 +1668,10 @@ int tty_release(struct inode *inode, struct file *filp)
1666 * - do_tty_hangup no longer sees this file descriptor as 1668 * - do_tty_hangup no longer sees this file descriptor as
1667 * something that needs to be handled for hangups. 1669 * something that needs to be handled for hangups.
1668 */ 1670 */
1669 file_kill(filp); 1671 spin_lock(&tty_files_lock);
1672 BUG_ON(list_empty(&filp->f_u.fu_list));
1673 list_del_init(&filp->f_u.fu_list);
1674 spin_unlock(&tty_files_lock);
1670 filp->private_data = NULL; 1675 filp->private_data = NULL;
1671 1676
1672 /* 1677 /*
@@ -1835,7 +1840,11 @@ got_driver:
1835 } 1840 }
1836 1841
1837 filp->private_data = tty; 1842 filp->private_data = tty;
1838 file_move(filp, &tty->tty_files); 1843 BUG_ON(list_empty(&filp->f_u.fu_list));
1844 file_sb_list_del(filp); /* __dentry_open has put it on the sb list */
1845 spin_lock(&tty_files_lock);
1846 list_add(&filp->f_u.fu_list, &tty->tty_files);
1847 spin_unlock(&tty_files_lock);
1839 check_tty_count(tty, "tty_open"); 1848 check_tty_count(tty, "tty_open");
1840 if (tty->driver->type == TTY_DRIVER_TYPE_PTY && 1849 if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
1841 tty->driver->subtype == PTY_TYPE_MASTER) 1850 tty->driver->subtype == PTY_TYPE_MASTER)
diff --git a/fs/file_table.c b/fs/file_table.c
index 32d12b78bac8..ce00b6e03a06 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -32,8 +32,7 @@ struct files_stat_struct files_stat = {
32 .max_files = NR_FILE 32 .max_files = NR_FILE
33}; 33};
34 34
35/* public. Not pretty! */ 35static __cacheline_aligned_in_smp DEFINE_SPINLOCK(files_lock);
36__cacheline_aligned_in_smp DEFINE_SPINLOCK(files_lock);
37 36
38/* SLAB cache for file structures */ 37/* SLAB cache for file structures */
39static struct kmem_cache *filp_cachep __read_mostly; 38static struct kmem_cache *filp_cachep __read_mostly;
@@ -258,7 +257,7 @@ void __fput(struct file *file)
258 cdev_put(inode->i_cdev); 257 cdev_put(inode->i_cdev);
259 fops_put(file->f_op); 258 fops_put(file->f_op);
260 put_pid(file->f_owner.pid); 259 put_pid(file->f_owner.pid);
261 file_kill(file); 260 file_sb_list_del(file);
262 if (file->f_mode & FMODE_WRITE) 261 if (file->f_mode & FMODE_WRITE)
263 drop_file_write_access(file); 262 drop_file_write_access(file);
264 file->f_path.dentry = NULL; 263 file->f_path.dentry = NULL;
@@ -320,31 +319,29 @@ struct file *fget_light(unsigned int fd, int *fput_needed)
320 return file; 319 return file;
321} 320}
322 321
323
324void put_filp(struct file *file) 322void put_filp(struct file *file)
325{ 323{
326 if (atomic_long_dec_and_test(&file->f_count)) { 324 if (atomic_long_dec_and_test(&file->f_count)) {
327 security_file_free(file); 325 security_file_free(file);
328 file_kill(file); 326 file_sb_list_del(file);
329 file_free(file); 327 file_free(file);
330 } 328 }
331} 329}
332 330
333void file_move(struct file *file, struct list_head *list) 331void file_sb_list_add(struct file *file, struct super_block *sb)
334{ 332{
335 if (!list) 333 spin_lock(&files_lock);
336 return; 334 BUG_ON(!list_empty(&file->f_u.fu_list));
337 file_list_lock(); 335 list_add(&file->f_u.fu_list, &sb->s_files);
338 list_move(&file->f_u.fu_list, list); 336 spin_unlock(&files_lock);
339 file_list_unlock();
340} 337}
341 338
342void file_kill(struct file *file) 339void file_sb_list_del(struct file *file)
343{ 340{
344 if (!list_empty(&file->f_u.fu_list)) { 341 if (!list_empty(&file->f_u.fu_list)) {
345 file_list_lock(); 342 spin_lock(&files_lock);
346 list_del_init(&file->f_u.fu_list); 343 list_del_init(&file->f_u.fu_list);
347 file_list_unlock(); 344 spin_unlock(&files_lock);
348 } 345 }
349} 346}
350 347
@@ -353,7 +350,7 @@ int fs_may_remount_ro(struct super_block *sb)
353 struct file *file; 350 struct file *file;
354 351
355 /* Check that no files are currently opened for writing. */ 352 /* Check that no files are currently opened for writing. */
356 file_list_lock(); 353 spin_lock(&files_lock);
357 list_for_each_entry(file, &sb->s_files, f_u.fu_list) { 354 list_for_each_entry(file, &sb->s_files, f_u.fu_list) {
358 struct inode *inode = file->f_path.dentry->d_inode; 355 struct inode *inode = file->f_path.dentry->d_inode;
359 356
@@ -365,10 +362,10 @@ int fs_may_remount_ro(struct super_block *sb)
365 if (S_ISREG(inode->i_mode) && (file->f_mode & FMODE_WRITE)) 362 if (S_ISREG(inode->i_mode) && (file->f_mode & FMODE_WRITE))
366 goto too_bad; 363 goto too_bad;
367 } 364 }
368 file_list_unlock(); 365 spin_unlock(&files_lock);
369 return 1; /* Tis' cool bro. */ 366 return 1; /* Tis' cool bro. */
370too_bad: 367too_bad:
371 file_list_unlock(); 368 spin_unlock(&files_lock);
372 return 0; 369 return 0;
373} 370}
374 371
@@ -384,7 +381,7 @@ void mark_files_ro(struct super_block *sb)
384 struct file *f; 381 struct file *f;
385 382
386retry: 383retry:
387 file_list_lock(); 384 spin_lock(&files_lock);
388 list_for_each_entry(f, &sb->s_files, f_u.fu_list) { 385 list_for_each_entry(f, &sb->s_files, f_u.fu_list) {
389 struct vfsmount *mnt; 386 struct vfsmount *mnt;
390 if (!S_ISREG(f->f_path.dentry->d_inode->i_mode)) 387 if (!S_ISREG(f->f_path.dentry->d_inode->i_mode))
@@ -400,16 +397,13 @@ retry:
400 continue; 397 continue;
401 file_release_write(f); 398 file_release_write(f);
402 mnt = mntget(f->f_path.mnt); 399 mnt = mntget(f->f_path.mnt);
403 file_list_unlock(); 400 /* This can sleep, so we can't hold the spinlock. */
404 /* 401 spin_unlock(&files_lock);
405 * This can sleep, so we can't hold
406 * the file_list_lock() spinlock.
407 */
408 mnt_drop_write(mnt); 402 mnt_drop_write(mnt);
409 mntput(mnt); 403 mntput(mnt);
410 goto retry; 404 goto retry;
411 } 405 }
412 file_list_unlock(); 406 spin_unlock(&files_lock);
413} 407}
414 408
415void __init files_init(unsigned long mempages) 409void __init files_init(unsigned long mempages)
diff --git a/fs/open.c b/fs/open.c
index 040cef72bc00..9f57c39c921e 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -844,7 +844,7 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
844 f->f_path.mnt = mnt; 844 f->f_path.mnt = mnt;
845 f->f_pos = 0; 845 f->f_pos = 0;
846 f->f_op = fops_get(inode->i_fop); 846 f->f_op = fops_get(inode->i_fop);
847 file_move(f, &inode->i_sb->s_files); 847 file_sb_list_add(f, inode->i_sb);
848 848
849 error = security_dentry_open(f, cred); 849 error = security_dentry_open(f, cred);
850 if (error) 850 if (error)
@@ -890,7 +890,7 @@ cleanup_all:
890 mnt_drop_write(mnt); 890 mnt_drop_write(mnt);
891 } 891 }
892 } 892 }
893 file_kill(f); 893 file_sb_list_del(f);
894 f->f_path.dentry = NULL; 894 f->f_path.dentry = NULL;
895 f->f_path.mnt = NULL; 895 f->f_path.mnt = NULL;
896cleanup_file: 896cleanup_file:
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 5191f49c2fec..fc515b423fae 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -948,9 +948,6 @@ struct file {
948 unsigned long f_mnt_write_state; 948 unsigned long f_mnt_write_state;
949#endif 949#endif
950}; 950};
951extern spinlock_t files_lock;
952#define file_list_lock() spin_lock(&files_lock);
953#define file_list_unlock() spin_unlock(&files_lock);
954 951
955#define get_file(x) atomic_long_inc(&(x)->f_count) 952#define get_file(x) atomic_long_inc(&(x)->f_count)
956#define file_count(x) atomic_long_read(&(x)->f_count) 953#define file_count(x) atomic_long_read(&(x)->f_count)
@@ -2037,6 +2034,7 @@ extern const struct file_operations read_pipefifo_fops;
2037extern const struct file_operations write_pipefifo_fops; 2034extern const struct file_operations write_pipefifo_fops;
2038extern const struct file_operations rdwr_pipefifo_fops; 2035extern const struct file_operations rdwr_pipefifo_fops;
2039 2036
2037extern void mark_files_ro(struct super_block *sb);
2040extern int fs_may_remount_ro(struct super_block *); 2038extern int fs_may_remount_ro(struct super_block *);
2041 2039
2042#ifdef CONFIG_BLOCK 2040#ifdef CONFIG_BLOCK
@@ -2183,8 +2181,9 @@ static inline void insert_inode_hash(struct inode *inode) {
2183 __insert_inode_hash(inode, inode->i_ino); 2181 __insert_inode_hash(inode, inode->i_ino);
2184} 2182}
2185 2183
2186extern void file_move(struct file *f, struct list_head *list); 2184extern struct file * get_empty_filp(void);
2187extern void file_kill(struct file *f); 2185extern void file_sb_list_add(struct file *f, struct super_block *sb);
2186extern void file_sb_list_del(struct file *f);
2188#ifdef CONFIG_BLOCK 2187#ifdef CONFIG_BLOCK
2189struct bio; 2188struct bio;
2190extern void submit_bio(int, struct bio *); 2189extern void submit_bio(int, struct bio *);
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 42f207676016..e5c5ba2327f1 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -465,6 +465,7 @@ extern struct tty_struct *tty_pair_get_tty(struct tty_struct *tty);
465extern struct tty_struct *tty_pair_get_pty(struct tty_struct *tty); 465extern struct tty_struct *tty_pair_get_pty(struct tty_struct *tty);
466 466
467extern struct mutex tty_mutex; 467extern struct mutex tty_mutex;
468extern spinlock_t tty_files_lock;
468 469
469extern void tty_write_unlock(struct tty_struct *tty); 470extern void tty_write_unlock(struct tty_struct *tty);
470extern int tty_write_lock(struct tty_struct *tty, int ndelay); 471extern int tty_write_lock(struct tty_struct *tty, int ndelay);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 9a2ee845e9d4..f013de205ea8 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2246,7 +2246,7 @@ static inline void flush_unauthorized_files(const struct cred *cred,
2246 2246
2247 tty = get_current_tty(); 2247 tty = get_current_tty();
2248 if (tty) { 2248 if (tty) {
2249 file_list_lock(); 2249 spin_lock(&tty_files_lock);
2250 if (!list_empty(&tty->tty_files)) { 2250 if (!list_empty(&tty->tty_files)) {
2251 struct inode *inode; 2251 struct inode *inode;
2252 2252
@@ -2262,7 +2262,7 @@ static inline void flush_unauthorized_files(const struct cred *cred,
2262 drop_tty = 1; 2262 drop_tty = 1;
2263 } 2263 }
2264 } 2264 }
2265 file_list_unlock(); 2265 spin_unlock(&tty_files_lock);
2266 tty_kref_put(tty); 2266 tty_kref_put(tty);
2267 } 2267 }
2268 /* Reset controlling tty. */ 2268 /* Reset controlling tty. */