diff options
| author | Miklos Szeredi <mszeredi@suse.cz> | 2011-11-21 06:11:33 -0500 |
|---|---|---|
| committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-01-06 23:20:13 -0500 |
| commit | 8e8b87964bc8dc5c14b6543fc933b7725f07d3ac (patch) | |
| tree | 9a14c135741f3a8ba960ff97f060a58597604a6d /fs | |
| parent | 7ada4db88634429f4da690ad1c4eb73c93085f0c (diff) | |
vfs: prevent remount read-only if pending removes
If there are any inodes on the super block that have been unlinked
(i_nlink == 0) but have not yet been deleted then prevent the
remounting the super block read-only.
Reported-by: Toshiyuki Okajima <toshi.okajima@jp.fujitsu.com>
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Tested-by: Toshiyuki Okajima <toshi.okajima@jp.fujitsu.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/file_table.c | 23 | ||||
| -rw-r--r-- | fs/namespace.c | 7 | ||||
| -rw-r--r-- | fs/super.c | 4 |
3 files changed, 7 insertions, 27 deletions
diff --git a/fs/file_table.c b/fs/file_table.c index c322794f7360..20002e39754d 100644 --- a/fs/file_table.c +++ b/fs/file_table.c | |||
| @@ -474,29 +474,6 @@ void file_sb_list_del(struct file *file) | |||
| 474 | 474 | ||
| 475 | #endif | 475 | #endif |
| 476 | 476 | ||
| 477 | int fs_may_remount_ro(struct super_block *sb) | ||
| 478 | { | ||
| 479 | struct file *file; | ||
| 480 | /* Check that no files are currently opened for writing. */ | ||
| 481 | lg_global_lock(files_lglock); | ||
| 482 | do_file_list_for_each_entry(sb, file) { | ||
| 483 | struct inode *inode = file->f_path.dentry->d_inode; | ||
| 484 | |||
| 485 | /* File with pending delete? */ | ||
| 486 | if (inode->i_nlink == 0) | ||
| 487 | goto too_bad; | ||
| 488 | |||
| 489 | /* Writeable file? */ | ||
| 490 | if (S_ISREG(inode->i_mode) && (file->f_mode & FMODE_WRITE)) | ||
| 491 | goto too_bad; | ||
| 492 | } while_file_list_for_each_entry; | ||
| 493 | lg_global_unlock(files_lglock); | ||
| 494 | return 1; /* Tis' cool bro. */ | ||
| 495 | too_bad: | ||
| 496 | lg_global_unlock(files_lglock); | ||
| 497 | return 0; | ||
| 498 | } | ||
| 499 | |||
| 500 | /** | 477 | /** |
| 501 | * mark_files_ro - mark all files read-only | 478 | * mark_files_ro - mark all files read-only |
| 502 | * @sb: superblock in question | 479 | * @sb: superblock in question |
diff --git a/fs/namespace.c b/fs/namespace.c index 98ebc78b21ab..7e6f2c9dc7c4 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
| @@ -449,6 +449,10 @@ int sb_prepare_remount_readonly(struct super_block *sb) | |||
| 449 | struct mount *mnt; | 449 | struct mount *mnt; |
| 450 | int err = 0; | 450 | int err = 0; |
| 451 | 451 | ||
| 452 | /* Racy optimization. Recheck the counter under MNT_WRITE_HOLD */ | ||
| 453 | if (atomic_long_read(&sb->s_remove_count)) | ||
| 454 | return -EBUSY; | ||
| 455 | |||
| 452 | br_write_lock(vfsmount_lock); | 456 | br_write_lock(vfsmount_lock); |
| 453 | list_for_each_entry(mnt, &sb->s_mounts, mnt_instance) { | 457 | list_for_each_entry(mnt, &sb->s_mounts, mnt_instance) { |
| 454 | if (!(mnt->mnt.mnt_flags & MNT_READONLY)) { | 458 | if (!(mnt->mnt.mnt_flags & MNT_READONLY)) { |
| @@ -460,6 +464,9 @@ int sb_prepare_remount_readonly(struct super_block *sb) | |||
| 460 | } | 464 | } |
| 461 | } | 465 | } |
| 462 | } | 466 | } |
| 467 | if (!err && atomic_long_read(&sb->s_remove_count)) | ||
| 468 | err = -EBUSY; | ||
| 469 | |||
| 463 | if (!err) { | 470 | if (!err) { |
| 464 | sb->s_readonly_remount = 1; | 471 | sb->s_readonly_remount = 1; |
| 465 | smp_wmb(); | 472 | smp_wmb(); |
diff --git a/fs/super.c b/fs/super.c index 6acc02237e3e..de41e1e46f09 100644 --- a/fs/super.c +++ b/fs/super.c | |||
| @@ -729,10 +729,6 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force) | |||
| 729 | retval = sb_prepare_remount_readonly(sb); | 729 | retval = sb_prepare_remount_readonly(sb); |
| 730 | if (retval) | 730 | if (retval) |
| 731 | return retval; | 731 | return retval; |
| 732 | |||
| 733 | retval = -EBUSY; | ||
| 734 | if (!fs_may_remount_ro(sb)) | ||
| 735 | goto cancel_readonly; | ||
| 736 | } | 732 | } |
| 737 | } | 733 | } |
| 738 | 734 | ||
