lkml.org 
[lkml]   [2011]   [Oct]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH 13/13] vfs: prevent remount read-only if pending removes
Date
From: Miklos Szeredi <mszeredi@suse.cz>

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>
---
fs/file_table.c | 26 --------------------------
fs/namespace.c | 7 +++++++
fs/super.c | 4 ----
include/linux/fs.h | 2 --
4 files changed, 7 insertions(+), 32 deletions(-)

diff --git a/fs/file_table.c b/fs/file_table.c
index dc9f437..20002e3 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -474,32 +474,6 @@ void file_sb_list_del(struct file *file)

#endif

-int fs_may_remount_ro(struct super_block *sb)
-{
- struct file *file;
- /* Check that no files are currently opened for writing. */
- lg_global_lock(files_lglock);
- do_file_list_for_each_entry(sb, file) {
- struct inode *inode = file->f_path.dentry->d_inode;
-
- /* File with pending delete? */
- if (inode->i_nlink == 0)
- goto too_bad;
-
- /*
- * Writable file?
- * Should be caught by sb_prepare_remount_readonly().
- */
- if (WARN_ON(S_ISREG(inode->i_mode) && (file->f_mode & FMODE_WRITE)))
- goto too_bad;
- } while_file_list_for_each_entry;
- lg_global_unlock(files_lglock);
- return 1; /* Tis' cool bro. */
-too_bad:
- lg_global_unlock(files_lglock);
- return 0;
-}
-
/**
* mark_files_ro - mark all files read-only
* @sb: superblock in question
diff --git a/fs/namespace.c b/fs/namespace.c
index 85838f5..617705f 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -480,6 +480,10 @@ int sb_prepare_remount_readonly(struct super_block *sb)
struct vfsmount *mnt;
int err = 0;

+ /* Racy optimization. Recheck the counter under MNT_WRITE_HOLD */
+ if (atomic_long_read(&sb->s_remove_count))
+ return -EBUSY;
+
br_write_lock(vfsmount_lock);
list_for_each_entry(mnt, &sb->s_mounts, mnt_instance) {
if (!(mnt->mnt_flags & MNT_READONLY)) {
@@ -491,6 +495,9 @@ int sb_prepare_remount_readonly(struct super_block *sb)
}
}
}
+ if (!err && atomic_long_read(&sb->s_remove_count))
+ err = -EBUSY;
+
if (!err) {
sb->s_readonly_remount = 1;
smp_wmb();
diff --git a/fs/super.c b/fs/super.c
index 94c8ace..7b28dae 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -727,10 +727,6 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
retval = sb_prepare_remount_readonly(sb);
if (retval)
return retval;
-
- retval = -EBUSY;
- if (!fs_may_remount_ro(sb))
- goto cancel_readonly;
}
}

diff --git a/include/linux/fs.h b/include/linux/fs.h
index 71bacce..c791aa8b 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2135,8 +2135,6 @@ extern const struct file_operations read_pipefifo_fops;
extern const struct file_operations write_pipefifo_fops;
extern const struct file_operations rdwr_pipefifo_fops;

-extern int fs_may_remount_ro(struct super_block *);
-
#ifdef CONFIG_BLOCK
/*
* return READ, READA, or WRITE
--
1.7.3.4


\
 
 \ /
  Last update: 2011-10-12 16:53    [W:0.073 / U:2.236 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site