| .. | .. | 
|---|
| 56 | 56 | wait_on_buffer(bh); | 
|---|
| 57 | 57 | sb_end_write(sb); | 
|---|
| 58 | 58 | if (unlikely(!buffer_uptodate(bh))) | 
|---|
| 59 |  | -		return 1; | 
|---|
|  | 59 | +		return -EIO; | 
|---|
| 60 | 60 |  | 
|---|
| 61 | 61 | return 0; | 
|---|
| 62 | 62 | } | 
|---|
| .. | .. | 
|---|
| 85 | 85 | } | 
|---|
| 86 | 86 | } | 
|---|
| 87 | 87 |  | 
|---|
| 88 |  | -	get_bh(*bh); | 
|---|
| 89 | 88 | lock_buffer(*bh); | 
|---|
| 90 |  | -	(*bh)->b_end_io = end_buffer_read_sync; | 
|---|
| 91 |  | -	submit_bh(REQ_OP_READ, REQ_META | REQ_PRIO, *bh); | 
|---|
| 92 |  | -	wait_on_buffer(*bh); | 
|---|
| 93 |  | -	if (!buffer_uptodate(*bh)) { | 
|---|
| 94 |  | -		ret = -EIO; | 
|---|
|  | 89 | +	ret = ext4_read_bh(*bh, REQ_META | REQ_PRIO, NULL); | 
|---|
|  | 90 | +	if (ret) | 
|---|
| 95 | 91 | goto warn_exit; | 
|---|
| 96 |  | -	} | 
|---|
|  | 92 | + | 
|---|
| 97 | 93 | mmp = (struct mmp_struct *)((*bh)->b_data); | 
|---|
| 98 | 94 | if (le32_to_cpu(mmp->mmp_magic) != EXT4_MMP_MAGIC) { | 
|---|
| 99 | 95 | ret = -EFSCORRUPTED; | 
|---|
| .. | .. | 
|---|
| 131 | 127 | */ | 
|---|
| 132 | 128 | static int kmmpd(void *data) | 
|---|
| 133 | 129 | { | 
|---|
| 134 |  | -	struct super_block *sb = ((struct mmpd_data *) data)->sb; | 
|---|
| 135 |  | -	struct buffer_head *bh = ((struct mmpd_data *) data)->bh; | 
|---|
|  | 130 | +	struct super_block *sb = (struct super_block *) data; | 
|---|
| 136 | 131 | struct ext4_super_block *es = EXT4_SB(sb)->s_es; | 
|---|
|  | 132 | +	struct buffer_head *bh = EXT4_SB(sb)->s_mmp_bh; | 
|---|
| 137 | 133 | struct mmp_struct *mmp; | 
|---|
| 138 | 134 | ext4_fsblk_t mmp_block; | 
|---|
| 139 | 135 | u32 seq = 0; | 
|---|
| .. | .. | 
|---|
| 160 | 156 | memcpy(mmp->mmp_nodename, init_utsname()->nodename, | 
|---|
| 161 | 157 | sizeof(mmp->mmp_nodename)); | 
|---|
| 162 | 158 |  | 
|---|
| 163 |  | -	while (!kthread_should_stop()) { | 
|---|
|  | 159 | +	while (!kthread_should_stop() && !sb_rdonly(sb)) { | 
|---|
|  | 160 | +		if (!ext4_has_feature_mmp(sb)) { | 
|---|
|  | 161 | +			ext4_warning(sb, "kmmpd being stopped since MMP feature" | 
|---|
|  | 162 | +				     " has been disabled."); | 
|---|
|  | 163 | +			goto wait_to_exit; | 
|---|
|  | 164 | +		} | 
|---|
| 164 | 165 | if (++seq > EXT4_MMP_SEQ_MAX) | 
|---|
| 165 | 166 | seq = 1; | 
|---|
| 166 | 167 |  | 
|---|
| .. | .. | 
|---|
| 174 | 175 | * (s_mmp_update_interval * 60) seconds. | 
|---|
| 175 | 176 | */ | 
|---|
| 176 | 177 | if (retval) { | 
|---|
| 177 |  | -			if ((failed_writes % 60) == 0) | 
|---|
| 178 |  | -				ext4_error(sb, "Error writing to MMP block"); | 
|---|
|  | 178 | +			if ((failed_writes % 60) == 0) { | 
|---|
|  | 179 | +				ext4_error_err(sb, -retval, | 
|---|
|  | 180 | +					       "Error writing to MMP block"); | 
|---|
|  | 181 | +			} | 
|---|
| 179 | 182 | failed_writes++; | 
|---|
| 180 | 183 | } | 
|---|
| 181 |  | - | 
|---|
| 182 |  | -		if (!(le32_to_cpu(es->s_feature_incompat) & | 
|---|
| 183 |  | -		    EXT4_FEATURE_INCOMPAT_MMP)) { | 
|---|
| 184 |  | -			ext4_warning(sb, "kmmpd being stopped since MMP feature" | 
|---|
| 185 |  | -				     " has been disabled."); | 
|---|
| 186 |  | -			goto exit_thread; | 
|---|
| 187 |  | -		} | 
|---|
| 188 |  | - | 
|---|
| 189 |  | -		if (sb_rdonly(sb)) | 
|---|
| 190 |  | -			break; | 
|---|
| 191 | 184 |  | 
|---|
| 192 | 185 | diff = jiffies - last_update_time; | 
|---|
| 193 | 186 | if (diff < mmp_update_interval * HZ) | 
|---|
| .. | .. | 
|---|
| 206 | 199 |  | 
|---|
| 207 | 200 | retval = read_mmp_block(sb, &bh_check, mmp_block); | 
|---|
| 208 | 201 | if (retval) { | 
|---|
| 209 |  | -				ext4_error(sb, "error reading MMP data: %d", | 
|---|
| 210 |  | -					   retval); | 
|---|
| 211 |  | -				goto exit_thread; | 
|---|
|  | 202 | +				ext4_error_err(sb, -retval, | 
|---|
|  | 203 | +					       "error reading MMP data: %d", | 
|---|
|  | 204 | +					       retval); | 
|---|
|  | 205 | +				goto wait_to_exit; | 
|---|
| 212 | 206 | } | 
|---|
| 213 | 207 |  | 
|---|
| 214 | 208 | mmp_check = (struct mmp_struct *)(bh_check->b_data); | 
|---|
| .. | .. | 
|---|
| 219 | 213 | "Error while updating MMP info. " | 
|---|
| 220 | 214 | "The filesystem seems to have been" | 
|---|
| 221 | 215 | " multiply mounted."); | 
|---|
| 222 |  | -				ext4_error(sb, "abort"); | 
|---|
|  | 216 | +				ext4_error_err(sb, EBUSY, "abort"); | 
|---|
| 223 | 217 | put_bh(bh_check); | 
|---|
| 224 | 218 | retval = -EBUSY; | 
|---|
| 225 |  | -				goto exit_thread; | 
|---|
|  | 219 | +				goto wait_to_exit; | 
|---|
| 226 | 220 | } | 
|---|
| 227 | 221 | put_bh(bh_check); | 
|---|
| 228 | 222 | } | 
|---|
| .. | .. | 
|---|
| 245 | 239 |  | 
|---|
| 246 | 240 | retval = write_mmp_block(sb, bh); | 
|---|
| 247 | 241 |  | 
|---|
| 248 |  | -exit_thread: | 
|---|
| 249 |  | -	EXT4_SB(sb)->s_mmp_tsk = NULL; | 
|---|
| 250 |  | -	kfree(data); | 
|---|
| 251 |  | -	brelse(bh); | 
|---|
|  | 242 | +wait_to_exit: | 
|---|
|  | 243 | +	while (!kthread_should_stop()) { | 
|---|
|  | 244 | +		set_current_state(TASK_INTERRUPTIBLE); | 
|---|
|  | 245 | +		if (!kthread_should_stop()) | 
|---|
|  | 246 | +			schedule(); | 
|---|
|  | 247 | +	} | 
|---|
|  | 248 | +	set_current_state(TASK_RUNNING); | 
|---|
| 252 | 249 | return retval; | 
|---|
|  | 250 | +} | 
|---|
|  | 251 | + | 
|---|
|  | 252 | +void ext4_stop_mmpd(struct ext4_sb_info *sbi) | 
|---|
|  | 253 | +{ | 
|---|
|  | 254 | +	if (sbi->s_mmp_tsk) { | 
|---|
|  | 255 | +		kthread_stop(sbi->s_mmp_tsk); | 
|---|
|  | 256 | +		brelse(sbi->s_mmp_bh); | 
|---|
|  | 257 | +		sbi->s_mmp_tsk = NULL; | 
|---|
|  | 258 | +	} | 
|---|
| 253 | 259 | } | 
|---|
| 254 | 260 |  | 
|---|
| 255 | 261 | /* | 
|---|
| .. | .. | 
|---|
| 276 | 282 | struct ext4_super_block *es = EXT4_SB(sb)->s_es; | 
|---|
| 277 | 283 | struct buffer_head *bh = NULL; | 
|---|
| 278 | 284 | struct mmp_struct *mmp = NULL; | 
|---|
| 279 |  | -	struct mmpd_data *mmpd_data; | 
|---|
| 280 | 285 | u32 seq; | 
|---|
| 281 | 286 | unsigned int mmp_check_interval = le16_to_cpu(es->s_mmp_update_interval); | 
|---|
| 282 | 287 | unsigned int wait_time = 0; | 
|---|
| .. | .. | 
|---|
| 365 | 370 | goto failed; | 
|---|
| 366 | 371 | } | 
|---|
| 367 | 372 |  | 
|---|
| 368 |  | -	mmpd_data = kmalloc(sizeof(*mmpd_data), GFP_KERNEL); | 
|---|
| 369 |  | -	if (!mmpd_data) { | 
|---|
| 370 |  | -		ext4_warning(sb, "not enough memory for mmpd_data"); | 
|---|
| 371 |  | -		goto failed; | 
|---|
| 372 |  | -	} | 
|---|
| 373 |  | -	mmpd_data->sb = sb; | 
|---|
| 374 |  | -	mmpd_data->bh = bh; | 
|---|
|  | 373 | +	EXT4_SB(sb)->s_mmp_bh = bh; | 
|---|
| 375 | 374 |  | 
|---|
| 376 | 375 | /* | 
|---|
| 377 | 376 | * Start a kernel thread to update the MMP block periodically. | 
|---|
| 378 | 377 | */ | 
|---|
| 379 |  | -	EXT4_SB(sb)->s_mmp_tsk = kthread_run(kmmpd, mmpd_data, "kmmpd-%.*s", | 
|---|
|  | 378 | +	EXT4_SB(sb)->s_mmp_tsk = kthread_run(kmmpd, sb, "kmmpd-%.*s", | 
|---|
| 380 | 379 | (int)sizeof(mmp->mmp_bdevname), | 
|---|
| 381 | 380 | bdevname(bh->b_bdev, | 
|---|
| 382 | 381 | mmp->mmp_bdevname)); | 
|---|
| 383 | 382 | if (IS_ERR(EXT4_SB(sb)->s_mmp_tsk)) { | 
|---|
| 384 | 383 | EXT4_SB(sb)->s_mmp_tsk = NULL; | 
|---|
| 385 |  | -		kfree(mmpd_data); | 
|---|
| 386 | 384 | ext4_warning(sb, "Unable to create kmmpd thread for %s.", | 
|---|
| 387 | 385 | sb->s_id); | 
|---|
| 388 | 386 | goto failed; | 
|---|
| .. | .. | 
|---|
| 394 | 392 | brelse(bh); | 
|---|
| 395 | 393 | return 1; | 
|---|
| 396 | 394 | } | 
|---|
| 397 |  | - | 
|---|
| 398 |  | - | 
|---|