mirror of
https://github.com/torvalds/linux.git
synced 2024-12-29 14:21:47 +00:00
Miscellaneous ext4 bug fixes for 5.1.
-----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEEK2m5VNv+CHkogTfJ8vlZVpUNgaMFAlyX1hcACgkQ8vlZVpUN gaOkAAf8Cx3fIkMhBQ6iZABkE8om8LCw0cd1eBi06ode9mV/GQK3mSWrfTmaPzPn 3OysYuBUmKSB4Bbzq8pty6yujlUOhTVFIL+wL3GCbRfYhS2a4u9hCJ5jyVsXCo+M IPIxGlgnDiYEppj3Ok3r6HgijSzLRw1jIgSCLW5N22aYikpTETWekFDNMoAHraYF ew6VRATCMhqa5CTWjEl+v9dnQ13jPzcWSW8BiHQCHBMV98NFciszPlnBHH45PUzF 90ktCxYySopfpaegECAsRp5TgvfK32ZnxlbcRgTjaj5P7u+KkGOPp7DGLiyS3Ih7 fK/MFaWytT7/IVOGlC07rpmYq7T2ww== =9gOf -----END PGP SIGNATURE----- Merge tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4 Pull ext4 fixes from Ted Ts'o: "Miscellaneous ext4 bug fixes for 5.1" * tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: ext4: prohibit fstrim in norecovery mode ext4: cleanup bh release code in ext4_ind_remove_space() ext4: brelse all indirect buffer in ext4_ind_remove_space() ext4: report real fs size after failed resize ext4: add missing brelse() in add_new_gdb_meta_bg() ext4: remove useless ext4_pin_inode() ext4: avoid panic during forced reboot ext4: fix data corruption caused by unaligned direct AIO ext4: fix NULL pointer dereference while journal is aborted
This commit is contained in:
commit
17403fa277
@ -384,7 +384,7 @@ static inline void ext4_update_inode_fsync_trans(handle_t *handle,
|
||||
{
|
||||
struct ext4_inode_info *ei = EXT4_I(inode);
|
||||
|
||||
if (ext4_handle_valid(handle)) {
|
||||
if (ext4_handle_valid(handle) && !is_handle_aborted(handle)) {
|
||||
ei->i_sync_tid = handle->h_transaction->t_tid;
|
||||
if (datasync)
|
||||
ei->i_datasync_tid = handle->h_transaction->t_tid;
|
||||
|
@ -125,7 +125,7 @@ ext4_unaligned_aio(struct inode *inode, struct iov_iter *from, loff_t pos)
|
||||
struct super_block *sb = inode->i_sb;
|
||||
int blockmask = sb->s_blocksize - 1;
|
||||
|
||||
if (pos >= i_size_read(inode))
|
||||
if (pos >= ALIGN(i_size_read(inode), sb->s_blocksize))
|
||||
return 0;
|
||||
|
||||
if ((pos | iov_iter_alignment(from)) & blockmask)
|
||||
|
@ -1222,6 +1222,7 @@ int ext4_ind_remove_space(handle_t *handle, struct inode *inode,
|
||||
ext4_lblk_t offsets[4], offsets2[4];
|
||||
Indirect chain[4], chain2[4];
|
||||
Indirect *partial, *partial2;
|
||||
Indirect *p = NULL, *p2 = NULL;
|
||||
ext4_lblk_t max_block;
|
||||
__le32 nr = 0, nr2 = 0;
|
||||
int n = 0, n2 = 0;
|
||||
@ -1263,7 +1264,7 @@ int ext4_ind_remove_space(handle_t *handle, struct inode *inode,
|
||||
}
|
||||
|
||||
|
||||
partial = ext4_find_shared(inode, n, offsets, chain, &nr);
|
||||
partial = p = ext4_find_shared(inode, n, offsets, chain, &nr);
|
||||
if (nr) {
|
||||
if (partial == chain) {
|
||||
/* Shared branch grows from the inode */
|
||||
@ -1288,13 +1289,11 @@ int ext4_ind_remove_space(handle_t *handle, struct inode *inode,
|
||||
partial->p + 1,
|
||||
(__le32 *)partial->bh->b_data+addr_per_block,
|
||||
(chain+n-1) - partial);
|
||||
BUFFER_TRACE(partial->bh, "call brelse");
|
||||
brelse(partial->bh);
|
||||
partial--;
|
||||
}
|
||||
|
||||
end_range:
|
||||
partial2 = ext4_find_shared(inode, n2, offsets2, chain2, &nr2);
|
||||
partial2 = p2 = ext4_find_shared(inode, n2, offsets2, chain2, &nr2);
|
||||
if (nr2) {
|
||||
if (partial2 == chain2) {
|
||||
/*
|
||||
@ -1324,16 +1323,14 @@ end_range:
|
||||
(__le32 *)partial2->bh->b_data,
|
||||
partial2->p,
|
||||
(chain2+n2-1) - partial2);
|
||||
BUFFER_TRACE(partial2->bh, "call brelse");
|
||||
brelse(partial2->bh);
|
||||
partial2--;
|
||||
}
|
||||
goto do_indirects;
|
||||
}
|
||||
|
||||
/* Punch happened within the same level (n == n2) */
|
||||
partial = ext4_find_shared(inode, n, offsets, chain, &nr);
|
||||
partial2 = ext4_find_shared(inode, n2, offsets2, chain2, &nr2);
|
||||
partial = p = ext4_find_shared(inode, n, offsets, chain, &nr);
|
||||
partial2 = p2 = ext4_find_shared(inode, n2, offsets2, chain2, &nr2);
|
||||
|
||||
/* Free top, but only if partial2 isn't its subtree. */
|
||||
if (nr) {
|
||||
@ -1390,11 +1387,7 @@ end_range:
|
||||
partial->p + 1,
|
||||
partial2->p,
|
||||
(chain+n-1) - partial);
|
||||
BUFFER_TRACE(partial->bh, "call brelse");
|
||||
brelse(partial->bh);
|
||||
BUFFER_TRACE(partial2->bh, "call brelse");
|
||||
brelse(partial2->bh);
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1409,8 +1402,6 @@ end_range:
|
||||
partial->p + 1,
|
||||
(__le32 *)partial->bh->b_data+addr_per_block,
|
||||
(chain+n-1) - partial);
|
||||
BUFFER_TRACE(partial->bh, "call brelse");
|
||||
brelse(partial->bh);
|
||||
partial--;
|
||||
}
|
||||
if (partial2 > chain2 && depth2 <= depth) {
|
||||
@ -1418,11 +1409,21 @@ end_range:
|
||||
(__le32 *)partial2->bh->b_data,
|
||||
partial2->p,
|
||||
(chain2+n2-1) - partial2);
|
||||
BUFFER_TRACE(partial2->bh, "call brelse");
|
||||
brelse(partial2->bh);
|
||||
partial2--;
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
while (p && p > chain) {
|
||||
BUFFER_TRACE(p->bh, "call brelse");
|
||||
brelse(p->bh);
|
||||
p--;
|
||||
}
|
||||
while (p2 && p2 > chain2) {
|
||||
BUFFER_TRACE(p2->bh, "call brelse");
|
||||
brelse(p2->bh);
|
||||
p2--;
|
||||
}
|
||||
return 0;
|
||||
|
||||
do_indirects:
|
||||
@ -1430,7 +1431,7 @@ do_indirects:
|
||||
switch (offsets[0]) {
|
||||
default:
|
||||
if (++n >= n2)
|
||||
return 0;
|
||||
break;
|
||||
nr = i_data[EXT4_IND_BLOCK];
|
||||
if (nr) {
|
||||
ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 1);
|
||||
@ -1439,7 +1440,7 @@ do_indirects:
|
||||
/* fall through */
|
||||
case EXT4_IND_BLOCK:
|
||||
if (++n >= n2)
|
||||
return 0;
|
||||
break;
|
||||
nr = i_data[EXT4_DIND_BLOCK];
|
||||
if (nr) {
|
||||
ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 2);
|
||||
@ -1448,7 +1449,7 @@ do_indirects:
|
||||
/* fall through */
|
||||
case EXT4_DIND_BLOCK:
|
||||
if (++n >= n2)
|
||||
return 0;
|
||||
break;
|
||||
nr = i_data[EXT4_TIND_BLOCK];
|
||||
if (nr) {
|
||||
ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 3);
|
||||
@ -1458,5 +1459,5 @@ do_indirects:
|
||||
case EXT4_TIND_BLOCK:
|
||||
;
|
||||
}
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
|
@ -6080,36 +6080,6 @@ out:
|
||||
return;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Bind an inode's backing buffer_head into this transaction, to prevent
|
||||
* it from being flushed to disk early. Unlike
|
||||
* ext4_reserve_inode_write, this leaves behind no bh reference and
|
||||
* returns no iloc structure, so the caller needs to repeat the iloc
|
||||
* lookup to mark the inode dirty later.
|
||||
*/
|
||||
static int ext4_pin_inode(handle_t *handle, struct inode *inode)
|
||||
{
|
||||
struct ext4_iloc iloc;
|
||||
|
||||
int err = 0;
|
||||
if (handle) {
|
||||
err = ext4_get_inode_loc(inode, &iloc);
|
||||
if (!err) {
|
||||
BUFFER_TRACE(iloc.bh, "get_write_access");
|
||||
err = jbd2_journal_get_write_access(handle, iloc.bh);
|
||||
if (!err)
|
||||
err = ext4_handle_dirty_metadata(handle,
|
||||
NULL,
|
||||
iloc.bh);
|
||||
brelse(iloc.bh);
|
||||
}
|
||||
}
|
||||
ext4_std_error(inode->i_sb, err);
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
int ext4_change_inode_journal_flag(struct inode *inode, int val)
|
||||
{
|
||||
journal_t *journal;
|
||||
|
@ -1000,6 +1000,13 @@ resizefs_out:
|
||||
if (!blk_queue_discard(q))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/*
|
||||
* We haven't replayed the journal, so we cannot use our
|
||||
* block-bitmap-guided storage zapping commands.
|
||||
*/
|
||||
if (test_opt(sb, NOLOAD) && ext4_has_feature_journal(sb))
|
||||
return -EROFS;
|
||||
|
||||
if (copy_from_user(&range, (struct fstrim_range __user *)arg,
|
||||
sizeof(range)))
|
||||
return -EFAULT;
|
||||
|
@ -932,11 +932,18 @@ static int add_new_gdb_meta_bg(struct super_block *sb,
|
||||
memcpy(n_group_desc, o_group_desc,
|
||||
EXT4_SB(sb)->s_gdb_count * sizeof(struct buffer_head *));
|
||||
n_group_desc[gdb_num] = gdb_bh;
|
||||
|
||||
BUFFER_TRACE(gdb_bh, "get_write_access");
|
||||
err = ext4_journal_get_write_access(handle, gdb_bh);
|
||||
if (err) {
|
||||
kvfree(n_group_desc);
|
||||
brelse(gdb_bh);
|
||||
return err;
|
||||
}
|
||||
|
||||
EXT4_SB(sb)->s_group_desc = n_group_desc;
|
||||
EXT4_SB(sb)->s_gdb_count++;
|
||||
kvfree(o_group_desc);
|
||||
BUFFER_TRACE(gdb_bh, "get_write_access");
|
||||
err = ext4_journal_get_write_access(handle, gdb_bh);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -2073,6 +2080,10 @@ out:
|
||||
free_flex_gd(flex_gd);
|
||||
if (resize_inode != NULL)
|
||||
iput(resize_inode);
|
||||
ext4_msg(sb, KERN_INFO, "resized filesystem to %llu", n_blocks_count);
|
||||
if (err)
|
||||
ext4_warning(sb, "error (%d) occurred during "
|
||||
"file system resize", err);
|
||||
ext4_msg(sb, KERN_INFO, "resized filesystem to %llu",
|
||||
ext4_blocks_count(es));
|
||||
return err;
|
||||
}
|
||||
|
@ -430,6 +430,12 @@ static void ext4_journal_commit_callback(journal_t *journal, transaction_t *txn)
|
||||
spin_unlock(&sbi->s_md_lock);
|
||||
}
|
||||
|
||||
static bool system_going_down(void)
|
||||
{
|
||||
return system_state == SYSTEM_HALT || system_state == SYSTEM_POWER_OFF
|
||||
|| system_state == SYSTEM_RESTART;
|
||||
}
|
||||
|
||||
/* Deal with the reporting of failure conditions on a filesystem such as
|
||||
* inconsistencies detected or read IO failures.
|
||||
*
|
||||
@ -460,7 +466,12 @@ static void ext4_handle_error(struct super_block *sb)
|
||||
if (journal)
|
||||
jbd2_journal_abort(journal, -EIO);
|
||||
}
|
||||
if (test_opt(sb, ERRORS_RO)) {
|
||||
/*
|
||||
* We force ERRORS_RO behavior when system is rebooting. Otherwise we
|
||||
* could panic during 'reboot -f' as the underlying device got already
|
||||
* disabled.
|
||||
*/
|
||||
if (test_opt(sb, ERRORS_RO) || system_going_down()) {
|
||||
ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only");
|
||||
/*
|
||||
* Make sure updated value of ->s_mount_flags will be visible
|
||||
@ -468,8 +479,7 @@ static void ext4_handle_error(struct super_block *sb)
|
||||
*/
|
||||
smp_wmb();
|
||||
sb->s_flags |= SB_RDONLY;
|
||||
}
|
||||
if (test_opt(sb, ERRORS_PANIC)) {
|
||||
} else if (test_opt(sb, ERRORS_PANIC)) {
|
||||
if (EXT4_SB(sb)->s_journal &&
|
||||
!(EXT4_SB(sb)->s_journal->j_flags & JBD2_REC_ERR))
|
||||
return;
|
||||
|
Loading…
Reference in New Issue
Block a user