diff options
| author | Jan Kara <jack@suse.cz> | 2012-06-12 10:20:46 -0400 |
|---|---|---|
| committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-07-31 01:45:53 -0400 |
| commit | 1e8b212fe5dcee9d3dbb152d235f3c33458fb26e (patch) | |
| tree | c21036f86f455c6289704b35c58c8d01d7821f12 | |
| parent | b2b5ef5c8e89f19b68c174bf246f3ca212dbf0bc (diff) | |
ext2: Implement freezing
The only missing piece to make freezing work reliably with ext2 is to
stop iput() of unlinked inode from deleting the inode on frozen filesystem.
So add a necessary protection to ext2_evict_inode().
We also provide appropriate ->freeze_fs and ->unfreeze_fs functions.
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
| -rw-r--r-- | fs/ext2/inode.c | 5 | ||||
| -rw-r--r-- | fs/ext2/super.c | 33 |
2 files changed, 37 insertions, 1 deletions
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index 264d315f6c47..6363ac66fafa 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c | |||
| @@ -79,6 +79,7 @@ void ext2_evict_inode(struct inode * inode) | |||
| 79 | truncate_inode_pages(&inode->i_data, 0); | 79 | truncate_inode_pages(&inode->i_data, 0); |
| 80 | 80 | ||
| 81 | if (want_delete) { | 81 | if (want_delete) { |
| 82 | sb_start_intwrite(inode->i_sb); | ||
| 82 | /* set dtime */ | 83 | /* set dtime */ |
| 83 | EXT2_I(inode)->i_dtime = get_seconds(); | 84 | EXT2_I(inode)->i_dtime = get_seconds(); |
| 84 | mark_inode_dirty(inode); | 85 | mark_inode_dirty(inode); |
| @@ -98,8 +99,10 @@ void ext2_evict_inode(struct inode * inode) | |||
| 98 | if (unlikely(rsv)) | 99 | if (unlikely(rsv)) |
| 99 | kfree(rsv); | 100 | kfree(rsv); |
| 100 | 101 | ||
| 101 | if (want_delete) | 102 | if (want_delete) { |
| 102 | ext2_free_inode(inode); | 103 | ext2_free_inode(inode); |
| 104 | sb_end_intwrite(inode->i_sb); | ||
| 105 | } | ||
| 103 | } | 106 | } |
| 104 | 107 | ||
| 105 | typedef struct { | 108 | typedef struct { |
diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 5df3d2d8169c..15761e638dae 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c | |||
| @@ -42,6 +42,8 @@ static void ext2_sync_super(struct super_block *sb, | |||
| 42 | static int ext2_remount (struct super_block * sb, int * flags, char * data); | 42 | static int ext2_remount (struct super_block * sb, int * flags, char * data); |
| 43 | static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf); | 43 | static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf); |
| 44 | static int ext2_sync_fs(struct super_block *sb, int wait); | 44 | static int ext2_sync_fs(struct super_block *sb, int wait); |
| 45 | static int ext2_freeze(struct super_block *sb); | ||
| 46 | static int ext2_unfreeze(struct super_block *sb); | ||
| 45 | 47 | ||
| 46 | void ext2_error(struct super_block *sb, const char *function, | 48 | void ext2_error(struct super_block *sb, const char *function, |
| 47 | const char *fmt, ...) | 49 | const char *fmt, ...) |
| @@ -305,6 +307,8 @@ static const struct super_operations ext2_sops = { | |||
| 305 | .evict_inode = ext2_evict_inode, | 307 | .evict_inode = ext2_evict_inode, |
| 306 | .put_super = ext2_put_super, | 308 | .put_super = ext2_put_super, |
| 307 | .sync_fs = ext2_sync_fs, | 309 | .sync_fs = ext2_sync_fs, |
| 310 | .freeze_fs = ext2_freeze, | ||
| 311 | .unfreeze_fs = ext2_unfreeze, | ||
| 308 | .statfs = ext2_statfs, | 312 | .statfs = ext2_statfs, |
| 309 | .remount_fs = ext2_remount, | 313 | .remount_fs = ext2_remount, |
| 310 | .show_options = ext2_show_options, | 314 | .show_options = ext2_show_options, |
| @@ -1200,6 +1204,35 @@ static int ext2_sync_fs(struct super_block *sb, int wait) | |||
| 1200 | return 0; | 1204 | return 0; |
| 1201 | } | 1205 | } |
| 1202 | 1206 | ||
| 1207 | static int ext2_freeze(struct super_block *sb) | ||
| 1208 | { | ||
| 1209 | struct ext2_sb_info *sbi = EXT2_SB(sb); | ||
| 1210 | |||
| 1211 | /* | ||
| 1212 | * Open but unlinked files present? Keep EXT2_VALID_FS flag cleared | ||
| 1213 | * because we have unattached inodes and thus filesystem is not fully | ||
| 1214 | * consistent. | ||
| 1215 | */ | ||
| 1216 | if (atomic_long_read(&sb->s_remove_count)) { | ||
| 1217 | ext2_sync_fs(sb, 1); | ||
| 1218 | return 0; | ||
| 1219 | } | ||
| 1220 | /* Set EXT2_FS_VALID flag */ | ||
| 1221 | spin_lock(&sbi->s_lock); | ||
| 1222 | sbi->s_es->s_state = cpu_to_le16(sbi->s_mount_state); | ||
| 1223 | spin_unlock(&sbi->s_lock); | ||
| 1224 | ext2_sync_super(sb, sbi->s_es, 1); | ||
| 1225 | |||
| 1226 | return 0; | ||
| 1227 | } | ||
| 1228 | |||
| 1229 | static int ext2_unfreeze(struct super_block *sb) | ||
| 1230 | { | ||
| 1231 | /* Just write sb to clear EXT2_VALID_FS flag */ | ||
| 1232 | ext2_write_super(sb); | ||
| 1233 | |||
| 1234 | return 0; | ||
| 1235 | } | ||
| 1203 | 1236 | ||
| 1204 | void ext2_write_super(struct super_block *sb) | 1237 | void ext2_write_super(struct super_block *sb) |
| 1205 | { | 1238 | { |
