Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1e8b212f authored by Jan Kara's avatar Jan Kara Committed by Al Viro
Browse files

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: default avatarJan Kara <jack@suse.cz>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent b2b5ef5c
Loading
Loading
Loading
Loading
+4 −1
Original line number Original line Diff line number Diff line
@@ -79,6 +79,7 @@ void ext2_evict_inode(struct inode * inode)
	truncate_inode_pages(&inode->i_data, 0);
	truncate_inode_pages(&inode->i_data, 0);


	if (want_delete) {
	if (want_delete) {
		sb_start_intwrite(inode->i_sb);
		/* set dtime */
		/* set dtime */
		EXT2_I(inode)->i_dtime	= get_seconds();
		EXT2_I(inode)->i_dtime	= get_seconds();
		mark_inode_dirty(inode);
		mark_inode_dirty(inode);
@@ -98,8 +99,10 @@ void ext2_evict_inode(struct inode * inode)
	if (unlikely(rsv))
	if (unlikely(rsv))
		kfree(rsv);
		kfree(rsv);


	if (want_delete)
	if (want_delete) {
		ext2_free_inode(inode);
		ext2_free_inode(inode);
		sb_end_intwrite(inode->i_sb);
	}
}
}


typedef struct {
typedef struct {
+33 −0
Original line number Original line Diff line number Diff line
@@ -42,6 +42,8 @@ static void ext2_sync_super(struct super_block *sb,
static int ext2_remount (struct super_block * sb, int * flags, char * data);
static int ext2_remount (struct super_block * sb, int * flags, char * data);
static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf);
static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf);
static int ext2_sync_fs(struct super_block *sb, int wait);
static int ext2_sync_fs(struct super_block *sb, int wait);
static int ext2_freeze(struct super_block *sb);
static int ext2_unfreeze(struct super_block *sb);


void ext2_error(struct super_block *sb, const char *function,
void ext2_error(struct super_block *sb, const char *function,
		const char *fmt, ...)
		const char *fmt, ...)
@@ -305,6 +307,8 @@ static const struct super_operations ext2_sops = {
	.evict_inode	= ext2_evict_inode,
	.evict_inode	= ext2_evict_inode,
	.put_super	= ext2_put_super,
	.put_super	= ext2_put_super,
	.sync_fs	= ext2_sync_fs,
	.sync_fs	= ext2_sync_fs,
	.freeze_fs	= ext2_freeze,
	.unfreeze_fs	= ext2_unfreeze,
	.statfs		= ext2_statfs,
	.statfs		= ext2_statfs,
	.remount_fs	= ext2_remount,
	.remount_fs	= ext2_remount,
	.show_options	= ext2_show_options,
	.show_options	= ext2_show_options,
@@ -1200,6 +1204,35 @@ static int ext2_sync_fs(struct super_block *sb, int wait)
	return 0;
	return 0;
}
}


static int ext2_freeze(struct super_block *sb)
{
	struct ext2_sb_info *sbi = EXT2_SB(sb);

	/*
	 * Open but unlinked files present? Keep EXT2_VALID_FS flag cleared
	 * because we have unattached inodes and thus filesystem is not fully
	 * consistent.
	 */
	if (atomic_long_read(&sb->s_remove_count)) {
		ext2_sync_fs(sb, 1);
		return 0;
	}
	/* Set EXT2_FS_VALID flag */
	spin_lock(&sbi->s_lock);
	sbi->s_es->s_state = cpu_to_le16(sbi->s_mount_state);
	spin_unlock(&sbi->s_lock);
	ext2_sync_super(sb, sbi->s_es, 1);

	return 0;
}

static int ext2_unfreeze(struct super_block *sb)
{
	/* Just write sb to clear EXT2_VALID_FS flag */
	ext2_write_super(sb);

	return 0;
}


void ext2_write_super(struct super_block *sb)
void ext2_write_super(struct super_block *sb)
{
{