summaryrefslogtreecommitdiffstats
path: root/fs/reiserfs
diff options
context:
space:
mode:
authorJeff Mahoney <jeffm@suse.com>2010-03-23 13:35:39 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2010-03-24 16:31:21 -0700
commit3f8b5ee33293d43ca360771b535dfae8c57259dc (patch)
treef533b80b6ad553882e81799b17e0cf94e41bf70e /fs/reiserfs
parent6cb4aff0a77cc0e6bae9475d62205319e3ebbf3f (diff)
downloadlinux-3f8b5ee33293d43ca360771b535dfae8c57259dc.tar.bz2
reiserfs: properly honor read-only devices
The reiserfs journal behaves inconsistently when determining whether to allow a mount of a read-only device. This is due to the use of the continue_replay variable to short circuit the journal scanning. If it's set, it's assumed that there are transactions to replay, but there may not be. If it's unset, it's assumed that there aren't any, and that may not be the case either. I've observed two failure cases: 1) Where a clean file system on a read-only device refuses to mount 2) Where a clean file system on a read-only device passes the optimization and then tries writing the journal header to update the latest mount id. The former is easily observable by using a freshly created file system on a read-only loopback device. This patch moves the check into journal_read_transaction, where it can bail out before it's about to replay a transaction. That way it can go through and skip transactions where appropriate, yet still refuse to mount a file system with outstanding transactions. Signed-off-by: Jeff Mahoney <jeffm@suse.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/reiserfs')
-rw-r--r--fs/reiserfs/journal.c15
1 files changed, 9 insertions, 6 deletions
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
index ba98546fabbd..f3de5e8a2ae8 100644
--- a/fs/reiserfs/journal.c
+++ b/fs/reiserfs/journal.c
@@ -2217,6 +2217,15 @@ static int journal_read_transaction(struct super_block *sb,
brelse(d_bh);
return 1;
}
+
+ if (bdev_read_only(sb->s_bdev)) {
+ reiserfs_warning(sb, "clm-2076",
+ "device is readonly, unable to replay log");
+ brelse(c_bh);
+ brelse(d_bh);
+ return -EROFS;
+ }
+
trans_id = get_desc_trans_id(desc);
/* now we know we've got a good transaction, and it was inside the valid time ranges */
log_blocks = kmalloc(get_desc_trans_len(desc) *
@@ -2459,12 +2468,6 @@ static int journal_read(struct super_block *sb)
goto start_log_replay;
}
- if (continue_replay && bdev_read_only(sb->s_bdev)) {
- reiserfs_warning(sb, "clm-2076",
- "device is readonly, unable to replay log");
- return -1;
- }
-
/* ok, there are transactions that need to be replayed. start with the first log block, find
** all the valid transactions, and pick out the oldest.
*/