aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext3
diff options
context:
space:
mode:
authorTakashi Sato <t-sato@yk.jp.nec.com>2009-01-09 19:40:58 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-01-09 19:54:42 -0500
commitc4be0c1dc4cdc37b175579be1460f15ac6495e9a (patch)
tree716ea88318211ed27cadcebda0fd85c1f8246edb /fs/ext3
parent69347a236b22c3962ea812511495e502dedfd50c (diff)
filesystem freeze: add error handling of write_super_lockfs/unlockfs
Currently, ext3 in mainline Linux doesn't have the freeze feature which suspends write requests. So, we cannot take a backup which keeps the filesystem's consistency with the storage device's features (snapshot and replication) while it is mounted. In many case, a commercial filesystem (e.g. VxFS) has the freeze feature and it would be used to get the consistent backup. If Linux's standard filesystem ext3 has the freeze feature, we can do it without a commercial filesystem. So I have implemented the ioctls of the freeze feature. I think we can take the consistent backup with the following steps. 1. Freeze the filesystem with the freeze ioctl. 2. Separate the replication volume or create the snapshot with the storage device's feature. 3. Unfreeze the filesystem with the unfreeze ioctl. 4. Take the backup from the separated replication volume or the snapshot. This patch: VFS: Changed the type of write_super_lockfs and unlockfs from "void" to "int" so that they can return an error. Rename write_super_lockfs and unlockfs of the super block operation freeze_fs and unfreeze_fs to avoid a confusion. ext3, ext4, xfs, gfs2, jfs: Changed the type of write_super_lockfs and unlockfs from "void" to "int" so that write_super_lockfs returns an error if needed, and unlockfs always returns 0. reiserfs: Changed the type of write_super_lockfs and unlockfs from "void" to "int" so that they always return 0 (success) to keep a current behavior. Signed-off-by: Takashi Sato <t-sato@yk.jp.nec.com> Signed-off-by: Masayuki Hamaguchi <m-hamaguchi@ys.jp.nec.com> Cc: <xfs-masters@oss.sgi.com> Cc: <linux-ext4@vger.kernel.org> Cc: Christoph Hellwig <hch@lst.de> Cc: Dave Kleikamp <shaggy@austin.ibm.com> Cc: Dave Chinner <david@fromorbit.com> Cc: Alasdair G Kergon <agk@redhat.com> Cc: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/ext3')
-rw-r--r--fs/ext3/super.c45
1 files changed, 29 insertions, 16 deletions
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 5d047a030a73..b70d90e08a3c 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -48,8 +48,8 @@ static int ext3_load_journal(struct super_block *, struct ext3_super_block *,
48 unsigned long journal_devnum); 48 unsigned long journal_devnum);
49static int ext3_create_journal(struct super_block *, struct ext3_super_block *, 49static int ext3_create_journal(struct super_block *, struct ext3_super_block *,
50 unsigned int); 50 unsigned int);
51static void ext3_commit_super (struct super_block * sb, 51static int ext3_commit_super(struct super_block *sb,
52 struct ext3_super_block * es, 52 struct ext3_super_block *es,
53 int sync); 53 int sync);
54static void ext3_mark_recovery_complete(struct super_block * sb, 54static void ext3_mark_recovery_complete(struct super_block * sb,
55 struct ext3_super_block * es); 55 struct ext3_super_block * es);
@@ -60,9 +60,9 @@ static const char *ext3_decode_error(struct super_block * sb, int errno,
60 char nbuf[16]); 60 char nbuf[16]);
61static int ext3_remount (struct super_block * sb, int * flags, char * data); 61static int ext3_remount (struct super_block * sb, int * flags, char * data);
62static int ext3_statfs (struct dentry * dentry, struct kstatfs * buf); 62static int ext3_statfs (struct dentry * dentry, struct kstatfs * buf);
63static void ext3_unlockfs(struct super_block *sb); 63static int ext3_unfreeze(struct super_block *sb);
64static void ext3_write_super (struct super_block * sb); 64static void ext3_write_super (struct super_block * sb);
65static void ext3_write_super_lockfs(struct super_block *sb); 65static int ext3_freeze(struct super_block *sb);
66 66
67/* 67/*
68 * Wrappers for journal_start/end. 68 * Wrappers for journal_start/end.
@@ -759,8 +759,8 @@ static const struct super_operations ext3_sops = {
759 .put_super = ext3_put_super, 759 .put_super = ext3_put_super,
760 .write_super = ext3_write_super, 760 .write_super = ext3_write_super,
761 .sync_fs = ext3_sync_fs, 761 .sync_fs = ext3_sync_fs,
762 .write_super_lockfs = ext3_write_super_lockfs, 762 .freeze_fs = ext3_freeze,
763 .unlockfs = ext3_unlockfs, 763 .unfreeze_fs = ext3_unfreeze,
764 .statfs = ext3_statfs, 764 .statfs = ext3_statfs,
765 .remount_fs = ext3_remount, 765 .remount_fs = ext3_remount,
766 .clear_inode = ext3_clear_inode, 766 .clear_inode = ext3_clear_inode,
@@ -2311,21 +2311,23 @@ static int ext3_create_journal(struct super_block * sb,
2311 return 0; 2311 return 0;
2312} 2312}
2313 2313
2314static void ext3_commit_super (struct super_block * sb, 2314static int ext3_commit_super(struct super_block *sb,
2315 struct ext3_super_block * es, 2315 struct ext3_super_block *es,
2316 int sync) 2316 int sync)
2317{ 2317{
2318 struct buffer_head *sbh = EXT3_SB(sb)->s_sbh; 2318 struct buffer_head *sbh = EXT3_SB(sb)->s_sbh;
2319 int error = 0;
2319 2320
2320 if (!sbh) 2321 if (!sbh)
2321 return; 2322 return error;
2322 es->s_wtime = cpu_to_le32(get_seconds()); 2323 es->s_wtime = cpu_to_le32(get_seconds());
2323 es->s_free_blocks_count = cpu_to_le32(ext3_count_free_blocks(sb)); 2324 es->s_free_blocks_count = cpu_to_le32(ext3_count_free_blocks(sb));
2324 es->s_free_inodes_count = cpu_to_le32(ext3_count_free_inodes(sb)); 2325 es->s_free_inodes_count = cpu_to_le32(ext3_count_free_inodes(sb));
2325 BUFFER_TRACE(sbh, "marking dirty"); 2326 BUFFER_TRACE(sbh, "marking dirty");
2326 mark_buffer_dirty(sbh); 2327 mark_buffer_dirty(sbh);
2327 if (sync) 2328 if (sync)
2328 sync_dirty_buffer(sbh); 2329 error = sync_dirty_buffer(sbh);
2330 return error;
2329} 2331}
2330 2332
2331 2333
@@ -2439,12 +2441,14 @@ static int ext3_sync_fs(struct super_block *sb, int wait)
2439 * LVM calls this function before a (read-only) snapshot is created. This 2441 * LVM calls this function before a (read-only) snapshot is created. This
2440 * gives us a chance to flush the journal completely and mark the fs clean. 2442 * gives us a chance to flush the journal completely and mark the fs clean.
2441 */ 2443 */
2442static void ext3_write_super_lockfs(struct super_block *sb) 2444static int ext3_freeze(struct super_block *sb)
2443{ 2445{
2446 int error = 0;
2447 journal_t *journal;
2444 sb->s_dirt = 0; 2448 sb->s_dirt = 0;
2445 2449
2446 if (!(sb->s_flags & MS_RDONLY)) { 2450 if (!(sb->s_flags & MS_RDONLY)) {
2447 journal_t *journal = EXT3_SB(sb)->s_journal; 2451 journal = EXT3_SB(sb)->s_journal;
2448 2452
2449 /* Now we set up the journal barrier. */ 2453 /* Now we set up the journal barrier. */
2450 journal_lock_updates(journal); 2454 journal_lock_updates(journal);
@@ -2453,20 +2457,28 @@ static void ext3_write_super_lockfs(struct super_block *sb)
2453 * We don't want to clear needs_recovery flag when we failed 2457 * We don't want to clear needs_recovery flag when we failed
2454 * to flush the journal. 2458 * to flush the journal.
2455 */ 2459 */
2456 if (journal_flush(journal) < 0) 2460 error = journal_flush(journal);
2457 return; 2461 if (error < 0)
2462 goto out;
2458 2463
2459 /* Journal blocked and flushed, clear needs_recovery flag. */ 2464 /* Journal blocked and flushed, clear needs_recovery flag. */
2460 EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER); 2465 EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
2461 ext3_commit_super(sb, EXT3_SB(sb)->s_es, 1); 2466 error = ext3_commit_super(sb, EXT3_SB(sb)->s_es, 1);
2467 if (error)
2468 goto out;
2462 } 2469 }
2470 return 0;
2471
2472out:
2473 journal_unlock_updates(journal);
2474 return error;
2463} 2475}
2464 2476
2465/* 2477/*
2466 * Called by LVM after the snapshot is done. We need to reset the RECOVER 2478 * Called by LVM after the snapshot is done. We need to reset the RECOVER
2467 * flag here, even though the filesystem is not technically dirty yet. 2479 * flag here, even though the filesystem is not technically dirty yet.
2468 */ 2480 */
2469static void ext3_unlockfs(struct super_block *sb) 2481static int ext3_unfreeze(struct super_block *sb)
2470{ 2482{
2471 if (!(sb->s_flags & MS_RDONLY)) { 2483 if (!(sb->s_flags & MS_RDONLY)) {
2472 lock_super(sb); 2484 lock_super(sb);
@@ -2476,6 +2488,7 @@ static void ext3_unlockfs(struct super_block *sb)
2476 unlock_super(sb); 2488 unlock_super(sb);
2477 journal_unlock_updates(EXT3_SB(sb)->s_journal); 2489 journal_unlock_updates(EXT3_SB(sb)->s_journal);
2478 } 2490 }
2491 return 0;
2479} 2492}
2480 2493
2481static int ext3_remount (struct super_block * sb, int * flags, char * data) 2494static int ext3_remount (struct super_block * sb, int * flags, char * data)