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

Commit 03046886 authored by vikram.jadhav07's avatar vikram.jadhav07 Committed by Theodore Ts'o
Browse files

ext4: clean up error handling in the MMP support



There is memory leak as both caller function kmmpd() and callee
read_mmp_block() not releasing bh_check  (i.e buffer_head).
Given patch fixes this problem.

[ Additional changes suggested by Andreas Dilger -- TYT ]

Signed-off-by: default avatarJadhav Vikram <vikramjadhavpucsd2007@gmail.com>
Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
parent 490c1b44
Loading
Loading
Loading
Loading
+17 −17
Original line number Original line Diff line number Diff line
@@ -91,21 +91,22 @@ static int read_mmp_block(struct super_block *sb, struct buffer_head **bh,
	submit_bh(READ_SYNC | REQ_META | REQ_PRIO, *bh);
	submit_bh(READ_SYNC | REQ_META | REQ_PRIO, *bh);
	wait_on_buffer(*bh);
	wait_on_buffer(*bh);
	if (!buffer_uptodate(*bh)) {
	if (!buffer_uptodate(*bh)) {
		brelse(*bh);
		*bh = NULL;
		ret = -EIO;
		ret = -EIO;
		goto warn_exit;
		goto warn_exit;
	}
	}

	mmp = (struct mmp_struct *)((*bh)->b_data);
	mmp = (struct mmp_struct *)((*bh)->b_data);
	if (le32_to_cpu(mmp->mmp_magic) != EXT4_MMP_MAGIC)
	if (le32_to_cpu(mmp->mmp_magic) != EXT4_MMP_MAGIC) {
		ret = -EFSCORRUPTED;
		ret = -EFSCORRUPTED;
	else if (!ext4_mmp_csum_verify(sb, mmp))
		goto warn_exit;
	}
	if (!ext4_mmp_csum_verify(sb, mmp)) {
		ret = -EFSBADCRC;
		ret = -EFSBADCRC;
	else
		goto warn_exit;
	}
	return 0;
	return 0;

warn_exit:
warn_exit:
	brelse(*bh);
	*bh = NULL;
	ext4_warning(sb, "Error %d while reading MMP block %llu",
	ext4_warning(sb, "Error %d while reading MMP block %llu",
		     ret, mmp_block);
		     ret, mmp_block);
	return ret;
	return ret;
@@ -181,15 +182,13 @@ static int kmmpd(void *data)
		    EXT4_FEATURE_INCOMPAT_MMP)) {
		    EXT4_FEATURE_INCOMPAT_MMP)) {
			ext4_warning(sb, "kmmpd being stopped since MMP feature"
			ext4_warning(sb, "kmmpd being stopped since MMP feature"
				     " has been disabled.");
				     " has been disabled.");
			EXT4_SB(sb)->s_mmp_tsk = NULL;
			goto exit_thread;
			goto failed;
		}
		}


		if (sb->s_flags & MS_RDONLY) {
		if (sb->s_flags & MS_RDONLY) {
			ext4_warning(sb, "kmmpd being stopped since filesystem "
			ext4_warning(sb, "kmmpd being stopped since filesystem "
				     "has been remounted as readonly.");
				     "has been remounted as readonly.");
			EXT4_SB(sb)->s_mmp_tsk = NULL;
			goto exit_thread;
			goto failed;
		}
		}


		diff = jiffies - last_update_time;
		diff = jiffies - last_update_time;
@@ -211,9 +210,7 @@ static int kmmpd(void *data)
			if (retval) {
			if (retval) {
				ext4_error(sb, "error reading MMP data: %d",
				ext4_error(sb, "error reading MMP data: %d",
					   retval);
					   retval);

				goto exit_thread;
				EXT4_SB(sb)->s_mmp_tsk = NULL;
				goto failed;
			}
			}


			mmp_check = (struct mmp_struct *)(bh_check->b_data);
			mmp_check = (struct mmp_struct *)(bh_check->b_data);
@@ -225,7 +222,9 @@ static int kmmpd(void *data)
					     "The filesystem seems to have been"
					     "The filesystem seems to have been"
					     " multiply mounted.");
					     " multiply mounted.");
				ext4_error(sb, "abort");
				ext4_error(sb, "abort");
				goto failed;
				put_bh(bh_check);
				retval = -EBUSY;
				goto exit_thread;
			}
			}
			put_bh(bh_check);
			put_bh(bh_check);
		}
		}
@@ -248,7 +247,8 @@ static int kmmpd(void *data)


	retval = write_mmp_block(sb, bh);
	retval = write_mmp_block(sb, bh);


failed:
exit_thread:
	EXT4_SB(sb)->s_mmp_tsk = NULL;
	kfree(data);
	kfree(data);
	brelse(bh);
	brelse(bh);
	return retval;
	return retval;