Miscellaneous ext4 bug fixes for v5.13
-----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEEK2m5VNv+CHkogTfJ8vlZVpUNgaMFAmC82AQACgkQ8vlZVpUN gaOkAgf+KH57P/P0sB6aVBHpAzqa9jTKJWMA5kpCqYUDkYlfF7n2hwsjMzWpJ5MY ZvFpKAflmRnve/ULUZQX6+zrcbieNs3e+6VFZrZ0PmxN0dupyISLY7jnvCRDleA7 BFO34AcH+QEst9zXJmgta9eoy3LA8sawhQ/d7ujVY+IRFk40m26fuAMiaGznlQJ5 dmrx7pHZWKFIDFIg2TdFlP+Voqbxs2VTT16gmWpGBdTyWYHKjbSOLKJFc9DwYeE9 aANf6iIzwXz7y9pZiOnTrGuKDEJcIZNESkbIqw62YgqsoObLbsbCZNmNcqxyHpYQ Mh3L59KtmjANW3iOxQfyxkNTugxchw== =BSnf -----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" * tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: ext4: Only advertise encrypted_casefold when encryption and unicode are enabled ext4: fix no-key deletion for encrypt+casefold ext4: fix memory leak in ext4_fill_super ext4: fix fast commit alignment issues ext4: fix bug on in ext4_es_cache_extent as ext4_split_extent_at failed ext4: fix accessing uninit percpu counter variable with fast_commit ext4: fix memory leak in ext4_mb_init_backend on error path.
This commit is contained in:
commit
20e41d9bc8
|
@ -3206,7 +3206,10 @@ static int ext4_split_extent_at(handle_t *handle,
|
|||
ext4_ext_mark_unwritten(ex2);
|
||||
|
||||
err = ext4_ext_insert_extent(handle, inode, ppath, &newex, flags);
|
||||
if (err == -ENOSPC && (EXT4_EXT_MAY_ZEROOUT & split_flag)) {
|
||||
if (err != -ENOSPC && err != -EDQUOT)
|
||||
goto out;
|
||||
|
||||
if (EXT4_EXT_MAY_ZEROOUT & split_flag) {
|
||||
if (split_flag & (EXT4_EXT_DATA_VALID1|EXT4_EXT_DATA_VALID2)) {
|
||||
if (split_flag & EXT4_EXT_DATA_VALID1) {
|
||||
err = ext4_ext_zeroout(inode, ex2);
|
||||
|
@ -3232,25 +3235,22 @@ static int ext4_split_extent_at(handle_t *handle,
|
|||
ext4_ext_pblock(&orig_ex));
|
||||
}
|
||||
|
||||
if (err)
|
||||
goto fix_extent_len;
|
||||
/* update the extent length and mark as initialized */
|
||||
ex->ee_len = cpu_to_le16(ee_len);
|
||||
ext4_ext_try_to_merge(handle, inode, path, ex);
|
||||
err = ext4_ext_dirty(handle, inode, path + path->p_depth);
|
||||
if (err)
|
||||
goto fix_extent_len;
|
||||
|
||||
/* update extent status tree */
|
||||
err = ext4_zeroout_es(inode, &zero_ex);
|
||||
|
||||
goto out;
|
||||
} else if (err)
|
||||
goto fix_extent_len;
|
||||
|
||||
out:
|
||||
ext4_ext_show_leaf(inode, path);
|
||||
return err;
|
||||
if (!err) {
|
||||
/* update the extent length and mark as initialized */
|
||||
ex->ee_len = cpu_to_le16(ee_len);
|
||||
ext4_ext_try_to_merge(handle, inode, path, ex);
|
||||
err = ext4_ext_dirty(handle, inode, path + path->p_depth);
|
||||
if (!err)
|
||||
/* update extent status tree */
|
||||
err = ext4_zeroout_es(inode, &zero_ex);
|
||||
/* If we failed at this point, we don't know in which
|
||||
* state the extent tree exactly is so don't try to fix
|
||||
* length of the original extent as it may do even more
|
||||
* damage.
|
||||
*/
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
fix_extent_len:
|
||||
ex->ee_len = orig_ex.ee_len;
|
||||
|
@ -3260,6 +3260,9 @@ fix_extent_len:
|
|||
*/
|
||||
ext4_ext_dirty(handle, inode, path + path->p_depth);
|
||||
return err;
|
||||
out:
|
||||
ext4_ext_show_leaf(inode, path);
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1288,28 +1288,29 @@ struct dentry_info_args {
|
|||
};
|
||||
|
||||
static inline void tl_to_darg(struct dentry_info_args *darg,
|
||||
struct ext4_fc_tl *tl)
|
||||
struct ext4_fc_tl *tl, u8 *val)
|
||||
{
|
||||
struct ext4_fc_dentry_info *fcd;
|
||||
struct ext4_fc_dentry_info fcd;
|
||||
|
||||
fcd = (struct ext4_fc_dentry_info *)ext4_fc_tag_val(tl);
|
||||
memcpy(&fcd, val, sizeof(fcd));
|
||||
|
||||
darg->parent_ino = le32_to_cpu(fcd->fc_parent_ino);
|
||||
darg->ino = le32_to_cpu(fcd->fc_ino);
|
||||
darg->dname = fcd->fc_dname;
|
||||
darg->dname_len = ext4_fc_tag_len(tl) -
|
||||
sizeof(struct ext4_fc_dentry_info);
|
||||
darg->parent_ino = le32_to_cpu(fcd.fc_parent_ino);
|
||||
darg->ino = le32_to_cpu(fcd.fc_ino);
|
||||
darg->dname = val + offsetof(struct ext4_fc_dentry_info, fc_dname);
|
||||
darg->dname_len = le16_to_cpu(tl->fc_len) -
|
||||
sizeof(struct ext4_fc_dentry_info);
|
||||
}
|
||||
|
||||
/* Unlink replay function */
|
||||
static int ext4_fc_replay_unlink(struct super_block *sb, struct ext4_fc_tl *tl)
|
||||
static int ext4_fc_replay_unlink(struct super_block *sb, struct ext4_fc_tl *tl,
|
||||
u8 *val)
|
||||
{
|
||||
struct inode *inode, *old_parent;
|
||||
struct qstr entry;
|
||||
struct dentry_info_args darg;
|
||||
int ret = 0;
|
||||
|
||||
tl_to_darg(&darg, tl);
|
||||
tl_to_darg(&darg, tl, val);
|
||||
|
||||
trace_ext4_fc_replay(sb, EXT4_FC_TAG_UNLINK, darg.ino,
|
||||
darg.parent_ino, darg.dname_len);
|
||||
|
@ -1399,13 +1400,14 @@ out:
|
|||
}
|
||||
|
||||
/* Link replay function */
|
||||
static int ext4_fc_replay_link(struct super_block *sb, struct ext4_fc_tl *tl)
|
||||
static int ext4_fc_replay_link(struct super_block *sb, struct ext4_fc_tl *tl,
|
||||
u8 *val)
|
||||
{
|
||||
struct inode *inode;
|
||||
struct dentry_info_args darg;
|
||||
int ret = 0;
|
||||
|
||||
tl_to_darg(&darg, tl);
|
||||
tl_to_darg(&darg, tl, val);
|
||||
trace_ext4_fc_replay(sb, EXT4_FC_TAG_LINK, darg.ino,
|
||||
darg.parent_ino, darg.dname_len);
|
||||
|
||||
|
@ -1450,9 +1452,10 @@ static int ext4_fc_record_modified_inode(struct super_block *sb, int ino)
|
|||
/*
|
||||
* Inode replay function
|
||||
*/
|
||||
static int ext4_fc_replay_inode(struct super_block *sb, struct ext4_fc_tl *tl)
|
||||
static int ext4_fc_replay_inode(struct super_block *sb, struct ext4_fc_tl *tl,
|
||||
u8 *val)
|
||||
{
|
||||
struct ext4_fc_inode *fc_inode;
|
||||
struct ext4_fc_inode fc_inode;
|
||||
struct ext4_inode *raw_inode;
|
||||
struct ext4_inode *raw_fc_inode;
|
||||
struct inode *inode = NULL;
|
||||
|
@ -1460,9 +1463,9 @@ static int ext4_fc_replay_inode(struct super_block *sb, struct ext4_fc_tl *tl)
|
|||
int inode_len, ino, ret, tag = le16_to_cpu(tl->fc_tag);
|
||||
struct ext4_extent_header *eh;
|
||||
|
||||
fc_inode = (struct ext4_fc_inode *)ext4_fc_tag_val(tl);
|
||||
memcpy(&fc_inode, val, sizeof(fc_inode));
|
||||
|
||||
ino = le32_to_cpu(fc_inode->fc_ino);
|
||||
ino = le32_to_cpu(fc_inode.fc_ino);
|
||||
trace_ext4_fc_replay(sb, tag, ino, 0, 0);
|
||||
|
||||
inode = ext4_iget(sb, ino, EXT4_IGET_NORMAL);
|
||||
|
@ -1474,12 +1477,13 @@ static int ext4_fc_replay_inode(struct super_block *sb, struct ext4_fc_tl *tl)
|
|||
|
||||
ext4_fc_record_modified_inode(sb, ino);
|
||||
|
||||
raw_fc_inode = (struct ext4_inode *)fc_inode->fc_raw_inode;
|
||||
raw_fc_inode = (struct ext4_inode *)
|
||||
(val + offsetof(struct ext4_fc_inode, fc_raw_inode));
|
||||
ret = ext4_get_fc_inode_loc(sb, ino, &iloc);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
inode_len = ext4_fc_tag_len(tl) - sizeof(struct ext4_fc_inode);
|
||||
inode_len = le16_to_cpu(tl->fc_len) - sizeof(struct ext4_fc_inode);
|
||||
raw_inode = ext4_raw_inode(&iloc);
|
||||
|
||||
memcpy(raw_inode, raw_fc_inode, offsetof(struct ext4_inode, i_block));
|
||||
|
@ -1547,14 +1551,15 @@ out:
|
|||
* inode for which we are trying to create a dentry here, should already have
|
||||
* been replayed before we start here.
|
||||
*/
|
||||
static int ext4_fc_replay_create(struct super_block *sb, struct ext4_fc_tl *tl)
|
||||
static int ext4_fc_replay_create(struct super_block *sb, struct ext4_fc_tl *tl,
|
||||
u8 *val)
|
||||
{
|
||||
int ret = 0;
|
||||
struct inode *inode = NULL;
|
||||
struct inode *dir = NULL;
|
||||
struct dentry_info_args darg;
|
||||
|
||||
tl_to_darg(&darg, tl);
|
||||
tl_to_darg(&darg, tl, val);
|
||||
|
||||
trace_ext4_fc_replay(sb, EXT4_FC_TAG_CREAT, darg.ino,
|
||||
darg.parent_ino, darg.dname_len);
|
||||
|
@ -1633,9 +1638,9 @@ static int ext4_fc_record_regions(struct super_block *sb, int ino,
|
|||
|
||||
/* Replay add range tag */
|
||||
static int ext4_fc_replay_add_range(struct super_block *sb,
|
||||
struct ext4_fc_tl *tl)
|
||||
struct ext4_fc_tl *tl, u8 *val)
|
||||
{
|
||||
struct ext4_fc_add_range *fc_add_ex;
|
||||
struct ext4_fc_add_range fc_add_ex;
|
||||
struct ext4_extent newex, *ex;
|
||||
struct inode *inode;
|
||||
ext4_lblk_t start, cur;
|
||||
|
@ -1645,15 +1650,14 @@ static int ext4_fc_replay_add_range(struct super_block *sb,
|
|||
struct ext4_ext_path *path = NULL;
|
||||
int ret;
|
||||
|
||||
fc_add_ex = (struct ext4_fc_add_range *)ext4_fc_tag_val(tl);
|
||||
ex = (struct ext4_extent *)&fc_add_ex->fc_ex;
|
||||
memcpy(&fc_add_ex, val, sizeof(fc_add_ex));
|
||||
ex = (struct ext4_extent *)&fc_add_ex.fc_ex;
|
||||
|
||||
trace_ext4_fc_replay(sb, EXT4_FC_TAG_ADD_RANGE,
|
||||
le32_to_cpu(fc_add_ex->fc_ino), le32_to_cpu(ex->ee_block),
|
||||
le32_to_cpu(fc_add_ex.fc_ino), le32_to_cpu(ex->ee_block),
|
||||
ext4_ext_get_actual_len(ex));
|
||||
|
||||
inode = ext4_iget(sb, le32_to_cpu(fc_add_ex->fc_ino),
|
||||
EXT4_IGET_NORMAL);
|
||||
inode = ext4_iget(sb, le32_to_cpu(fc_add_ex.fc_ino), EXT4_IGET_NORMAL);
|
||||
if (IS_ERR(inode)) {
|
||||
jbd_debug(1, "Inode not found.");
|
||||
return 0;
|
||||
|
@ -1762,32 +1766,33 @@ next:
|
|||
|
||||
/* Replay DEL_RANGE tag */
|
||||
static int
|
||||
ext4_fc_replay_del_range(struct super_block *sb, struct ext4_fc_tl *tl)
|
||||
ext4_fc_replay_del_range(struct super_block *sb, struct ext4_fc_tl *tl,
|
||||
u8 *val)
|
||||
{
|
||||
struct inode *inode;
|
||||
struct ext4_fc_del_range *lrange;
|
||||
struct ext4_fc_del_range lrange;
|
||||
struct ext4_map_blocks map;
|
||||
ext4_lblk_t cur, remaining;
|
||||
int ret;
|
||||
|
||||
lrange = (struct ext4_fc_del_range *)ext4_fc_tag_val(tl);
|
||||
cur = le32_to_cpu(lrange->fc_lblk);
|
||||
remaining = le32_to_cpu(lrange->fc_len);
|
||||
memcpy(&lrange, val, sizeof(lrange));
|
||||
cur = le32_to_cpu(lrange.fc_lblk);
|
||||
remaining = le32_to_cpu(lrange.fc_len);
|
||||
|
||||
trace_ext4_fc_replay(sb, EXT4_FC_TAG_DEL_RANGE,
|
||||
le32_to_cpu(lrange->fc_ino), cur, remaining);
|
||||
le32_to_cpu(lrange.fc_ino), cur, remaining);
|
||||
|
||||
inode = ext4_iget(sb, le32_to_cpu(lrange->fc_ino), EXT4_IGET_NORMAL);
|
||||
inode = ext4_iget(sb, le32_to_cpu(lrange.fc_ino), EXT4_IGET_NORMAL);
|
||||
if (IS_ERR(inode)) {
|
||||
jbd_debug(1, "Inode %d not found", le32_to_cpu(lrange->fc_ino));
|
||||
jbd_debug(1, "Inode %d not found", le32_to_cpu(lrange.fc_ino));
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = ext4_fc_record_modified_inode(sb, inode->i_ino);
|
||||
|
||||
jbd_debug(1, "DEL_RANGE, inode %ld, lblk %d, len %d\n",
|
||||
inode->i_ino, le32_to_cpu(lrange->fc_lblk),
|
||||
le32_to_cpu(lrange->fc_len));
|
||||
inode->i_ino, le32_to_cpu(lrange.fc_lblk),
|
||||
le32_to_cpu(lrange.fc_len));
|
||||
while (remaining > 0) {
|
||||
map.m_lblk = cur;
|
||||
map.m_len = remaining;
|
||||
|
@ -1808,8 +1813,8 @@ ext4_fc_replay_del_range(struct super_block *sb, struct ext4_fc_tl *tl)
|
|||
}
|
||||
|
||||
ret = ext4_punch_hole(inode,
|
||||
le32_to_cpu(lrange->fc_lblk) << sb->s_blocksize_bits,
|
||||
le32_to_cpu(lrange->fc_len) << sb->s_blocksize_bits);
|
||||
le32_to_cpu(lrange.fc_lblk) << sb->s_blocksize_bits,
|
||||
le32_to_cpu(lrange.fc_len) << sb->s_blocksize_bits);
|
||||
if (ret)
|
||||
jbd_debug(1, "ext4_punch_hole returned %d", ret);
|
||||
ext4_ext_replay_shrink_inode(inode,
|
||||
|
@ -1925,11 +1930,11 @@ static int ext4_fc_replay_scan(journal_t *journal,
|
|||
struct ext4_sb_info *sbi = EXT4_SB(sb);
|
||||
struct ext4_fc_replay_state *state;
|
||||
int ret = JBD2_FC_REPLAY_CONTINUE;
|
||||
struct ext4_fc_add_range *ext;
|
||||
struct ext4_fc_tl *tl;
|
||||
struct ext4_fc_tail *tail;
|
||||
__u8 *start, *end;
|
||||
struct ext4_fc_head *head;
|
||||
struct ext4_fc_add_range ext;
|
||||
struct ext4_fc_tl tl;
|
||||
struct ext4_fc_tail tail;
|
||||
__u8 *start, *end, *cur, *val;
|
||||
struct ext4_fc_head head;
|
||||
struct ext4_extent *ex;
|
||||
|
||||
state = &sbi->s_fc_replay_state;
|
||||
|
@ -1956,15 +1961,17 @@ static int ext4_fc_replay_scan(journal_t *journal,
|
|||
}
|
||||
|
||||
state->fc_replay_expected_off++;
|
||||
fc_for_each_tl(start, end, tl) {
|
||||
for (cur = start; cur < end; cur = cur + sizeof(tl) + le16_to_cpu(tl.fc_len)) {
|
||||
memcpy(&tl, cur, sizeof(tl));
|
||||
val = cur + sizeof(tl);
|
||||
jbd_debug(3, "Scan phase, tag:%s, blk %lld\n",
|
||||
tag2str(le16_to_cpu(tl->fc_tag)), bh->b_blocknr);
|
||||
switch (le16_to_cpu(tl->fc_tag)) {
|
||||
tag2str(le16_to_cpu(tl.fc_tag)), bh->b_blocknr);
|
||||
switch (le16_to_cpu(tl.fc_tag)) {
|
||||
case EXT4_FC_TAG_ADD_RANGE:
|
||||
ext = (struct ext4_fc_add_range *)ext4_fc_tag_val(tl);
|
||||
ex = (struct ext4_extent *)&ext->fc_ex;
|
||||
memcpy(&ext, val, sizeof(ext));
|
||||
ex = (struct ext4_extent *)&ext.fc_ex;
|
||||
ret = ext4_fc_record_regions(sb,
|
||||
le32_to_cpu(ext->fc_ino),
|
||||
le32_to_cpu(ext.fc_ino),
|
||||
le32_to_cpu(ex->ee_block), ext4_ext_pblock(ex),
|
||||
ext4_ext_get_actual_len(ex));
|
||||
if (ret < 0)
|
||||
|
@ -1978,18 +1985,18 @@ static int ext4_fc_replay_scan(journal_t *journal,
|
|||
case EXT4_FC_TAG_INODE:
|
||||
case EXT4_FC_TAG_PAD:
|
||||
state->fc_cur_tag++;
|
||||
state->fc_crc = ext4_chksum(sbi, state->fc_crc, tl,
|
||||
sizeof(*tl) + ext4_fc_tag_len(tl));
|
||||
state->fc_crc = ext4_chksum(sbi, state->fc_crc, cur,
|
||||
sizeof(tl) + le16_to_cpu(tl.fc_len));
|
||||
break;
|
||||
case EXT4_FC_TAG_TAIL:
|
||||
state->fc_cur_tag++;
|
||||
tail = (struct ext4_fc_tail *)ext4_fc_tag_val(tl);
|
||||
state->fc_crc = ext4_chksum(sbi, state->fc_crc, tl,
|
||||
sizeof(*tl) +
|
||||
memcpy(&tail, val, sizeof(tail));
|
||||
state->fc_crc = ext4_chksum(sbi, state->fc_crc, cur,
|
||||
sizeof(tl) +
|
||||
offsetof(struct ext4_fc_tail,
|
||||
fc_crc));
|
||||
if (le32_to_cpu(tail->fc_tid) == expected_tid &&
|
||||
le32_to_cpu(tail->fc_crc) == state->fc_crc) {
|
||||
if (le32_to_cpu(tail.fc_tid) == expected_tid &&
|
||||
le32_to_cpu(tail.fc_crc) == state->fc_crc) {
|
||||
state->fc_replay_num_tags = state->fc_cur_tag;
|
||||
state->fc_regions_valid =
|
||||
state->fc_regions_used;
|
||||
|
@ -2000,19 +2007,19 @@ static int ext4_fc_replay_scan(journal_t *journal,
|
|||
state->fc_crc = 0;
|
||||
break;
|
||||
case EXT4_FC_TAG_HEAD:
|
||||
head = (struct ext4_fc_head *)ext4_fc_tag_val(tl);
|
||||
if (le32_to_cpu(head->fc_features) &
|
||||
memcpy(&head, val, sizeof(head));
|
||||
if (le32_to_cpu(head.fc_features) &
|
||||
~EXT4_FC_SUPPORTED_FEATURES) {
|
||||
ret = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
if (le32_to_cpu(head->fc_tid) != expected_tid) {
|
||||
if (le32_to_cpu(head.fc_tid) != expected_tid) {
|
||||
ret = JBD2_FC_REPLAY_STOP;
|
||||
break;
|
||||
}
|
||||
state->fc_cur_tag++;
|
||||
state->fc_crc = ext4_chksum(sbi, state->fc_crc, tl,
|
||||
sizeof(*tl) + ext4_fc_tag_len(tl));
|
||||
state->fc_crc = ext4_chksum(sbi, state->fc_crc, cur,
|
||||
sizeof(tl) + le16_to_cpu(tl.fc_len));
|
||||
break;
|
||||
default:
|
||||
ret = state->fc_replay_num_tags ?
|
||||
|
@ -2036,11 +2043,11 @@ static int ext4_fc_replay(journal_t *journal, struct buffer_head *bh,
|
|||
{
|
||||
struct super_block *sb = journal->j_private;
|
||||
struct ext4_sb_info *sbi = EXT4_SB(sb);
|
||||
struct ext4_fc_tl *tl;
|
||||
__u8 *start, *end;
|
||||
struct ext4_fc_tl tl;
|
||||
__u8 *start, *end, *cur, *val;
|
||||
int ret = JBD2_FC_REPLAY_CONTINUE;
|
||||
struct ext4_fc_replay_state *state = &sbi->s_fc_replay_state;
|
||||
struct ext4_fc_tail *tail;
|
||||
struct ext4_fc_tail tail;
|
||||
|
||||
if (pass == PASS_SCAN) {
|
||||
state->fc_current_pass = PASS_SCAN;
|
||||
|
@ -2067,49 +2074,52 @@ static int ext4_fc_replay(journal_t *journal, struct buffer_head *bh,
|
|||
start = (u8 *)bh->b_data;
|
||||
end = (__u8 *)bh->b_data + journal->j_blocksize - 1;
|
||||
|
||||
fc_for_each_tl(start, end, tl) {
|
||||
for (cur = start; cur < end; cur = cur + sizeof(tl) + le16_to_cpu(tl.fc_len)) {
|
||||
memcpy(&tl, cur, sizeof(tl));
|
||||
val = cur + sizeof(tl);
|
||||
|
||||
if (state->fc_replay_num_tags == 0) {
|
||||
ret = JBD2_FC_REPLAY_STOP;
|
||||
ext4_fc_set_bitmaps_and_counters(sb);
|
||||
break;
|
||||
}
|
||||
jbd_debug(3, "Replay phase, tag:%s\n",
|
||||
tag2str(le16_to_cpu(tl->fc_tag)));
|
||||
tag2str(le16_to_cpu(tl.fc_tag)));
|
||||
state->fc_replay_num_tags--;
|
||||
switch (le16_to_cpu(tl->fc_tag)) {
|
||||
switch (le16_to_cpu(tl.fc_tag)) {
|
||||
case EXT4_FC_TAG_LINK:
|
||||
ret = ext4_fc_replay_link(sb, tl);
|
||||
ret = ext4_fc_replay_link(sb, &tl, val);
|
||||
break;
|
||||
case EXT4_FC_TAG_UNLINK:
|
||||
ret = ext4_fc_replay_unlink(sb, tl);
|
||||
ret = ext4_fc_replay_unlink(sb, &tl, val);
|
||||
break;
|
||||
case EXT4_FC_TAG_ADD_RANGE:
|
||||
ret = ext4_fc_replay_add_range(sb, tl);
|
||||
ret = ext4_fc_replay_add_range(sb, &tl, val);
|
||||
break;
|
||||
case EXT4_FC_TAG_CREAT:
|
||||
ret = ext4_fc_replay_create(sb, tl);
|
||||
ret = ext4_fc_replay_create(sb, &tl, val);
|
||||
break;
|
||||
case EXT4_FC_TAG_DEL_RANGE:
|
||||
ret = ext4_fc_replay_del_range(sb, tl);
|
||||
ret = ext4_fc_replay_del_range(sb, &tl, val);
|
||||
break;
|
||||
case EXT4_FC_TAG_INODE:
|
||||
ret = ext4_fc_replay_inode(sb, tl);
|
||||
ret = ext4_fc_replay_inode(sb, &tl, val);
|
||||
break;
|
||||
case EXT4_FC_TAG_PAD:
|
||||
trace_ext4_fc_replay(sb, EXT4_FC_TAG_PAD, 0,
|
||||
ext4_fc_tag_len(tl), 0);
|
||||
le16_to_cpu(tl.fc_len), 0);
|
||||
break;
|
||||
case EXT4_FC_TAG_TAIL:
|
||||
trace_ext4_fc_replay(sb, EXT4_FC_TAG_TAIL, 0,
|
||||
ext4_fc_tag_len(tl), 0);
|
||||
tail = (struct ext4_fc_tail *)ext4_fc_tag_val(tl);
|
||||
WARN_ON(le32_to_cpu(tail->fc_tid) != expected_tid);
|
||||
le16_to_cpu(tl.fc_len), 0);
|
||||
memcpy(&tail, val, sizeof(tail));
|
||||
WARN_ON(le32_to_cpu(tail.fc_tid) != expected_tid);
|
||||
break;
|
||||
case EXT4_FC_TAG_HEAD:
|
||||
break;
|
||||
default:
|
||||
trace_ext4_fc_replay(sb, le16_to_cpu(tl->fc_tag), 0,
|
||||
ext4_fc_tag_len(tl), 0);
|
||||
trace_ext4_fc_replay(sb, le16_to_cpu(tl.fc_tag), 0,
|
||||
le16_to_cpu(tl.fc_len), 0);
|
||||
ret = -ECANCELED;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -153,13 +153,6 @@ struct ext4_fc_replay_state {
|
|||
#define region_last(__region) (((__region)->lblk) + ((__region)->len) - 1)
|
||||
#endif
|
||||
|
||||
#define fc_for_each_tl(__start, __end, __tl) \
|
||||
for (tl = (struct ext4_fc_tl *)(__start); \
|
||||
(__u8 *)tl < (__u8 *)(__end); \
|
||||
tl = (struct ext4_fc_tl *)((__u8 *)tl + \
|
||||
sizeof(struct ext4_fc_tl) + \
|
||||
+ le16_to_cpu(tl->fc_len)))
|
||||
|
||||
static inline const char *tag2str(__u16 tag)
|
||||
{
|
||||
switch (tag) {
|
||||
|
@ -186,16 +179,4 @@ static inline const char *tag2str(__u16 tag)
|
|||
}
|
||||
}
|
||||
|
||||
/* Get length of a particular tlv */
|
||||
static inline int ext4_fc_tag_len(struct ext4_fc_tl *tl)
|
||||
{
|
||||
return le16_to_cpu(tl->fc_len);
|
||||
}
|
||||
|
||||
/* Get a pointer to "value" of a tlv */
|
||||
static inline __u8 *ext4_fc_tag_val(struct ext4_fc_tl *tl)
|
||||
{
|
||||
return (__u8 *)tl + sizeof(*tl);
|
||||
}
|
||||
|
||||
#endif /* __FAST_COMMIT_H__ */
|
||||
|
|
|
@ -322,14 +322,16 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
|
|||
if (is_directory) {
|
||||
count = ext4_used_dirs_count(sb, gdp) - 1;
|
||||
ext4_used_dirs_set(sb, gdp, count);
|
||||
percpu_counter_dec(&sbi->s_dirs_counter);
|
||||
if (percpu_counter_initialized(&sbi->s_dirs_counter))
|
||||
percpu_counter_dec(&sbi->s_dirs_counter);
|
||||
}
|
||||
ext4_inode_bitmap_csum_set(sb, block_group, gdp, bitmap_bh,
|
||||
EXT4_INODES_PER_GROUP(sb) / 8);
|
||||
ext4_group_desc_csum_set(sb, block_group, gdp);
|
||||
ext4_unlock_group(sb, block_group);
|
||||
|
||||
percpu_counter_inc(&sbi->s_freeinodes_counter);
|
||||
if (percpu_counter_initialized(&sbi->s_freeinodes_counter))
|
||||
percpu_counter_inc(&sbi->s_freeinodes_counter);
|
||||
if (sbi->s_log_groups_per_flex) {
|
||||
struct flex_groups *fg;
|
||||
|
||||
|
|
|
@ -3217,7 +3217,7 @@ static int ext4_mb_init_backend(struct super_block *sb)
|
|||
*/
|
||||
if (sbi->s_es->s_log_groups_per_flex >= 32) {
|
||||
ext4_msg(sb, KERN_ERR, "too many log groups per flexible block group");
|
||||
goto err_freesgi;
|
||||
goto err_freebuddy;
|
||||
}
|
||||
sbi->s_mb_prefetch = min_t(uint, 1 << sbi->s_es->s_log_groups_per_flex,
|
||||
BLK_MAX_SEGMENT_SIZE >> (sb->s_blocksize_bits - 9));
|
||||
|
|
|
@ -1376,7 +1376,8 @@ int ext4_fname_setup_ci_filename(struct inode *dir, const struct qstr *iname,
|
|||
struct dx_hash_info *hinfo = &name->hinfo;
|
||||
int len;
|
||||
|
||||
if (!IS_CASEFOLDED(dir) || !dir->i_sb->s_encoding) {
|
||||
if (!IS_CASEFOLDED(dir) || !dir->i_sb->s_encoding ||
|
||||
(IS_ENCRYPTED(dir) && !fscrypt_has_encryption_key(dir))) {
|
||||
cf_name->name = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
@ -1427,7 +1428,8 @@ static bool ext4_match(struct inode *parent,
|
|||
#endif
|
||||
|
||||
#ifdef CONFIG_UNICODE
|
||||
if (parent->i_sb->s_encoding && IS_CASEFOLDED(parent)) {
|
||||
if (parent->i_sb->s_encoding && IS_CASEFOLDED(parent) &&
|
||||
(!IS_ENCRYPTED(parent) || fscrypt_has_encryption_key(parent))) {
|
||||
if (fname->cf_name.name) {
|
||||
struct qstr cf = {.name = fname->cf_name.name,
|
||||
.len = fname->cf_name.len};
|
||||
|
|
|
@ -4462,14 +4462,20 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|||
}
|
||||
|
||||
if (sb->s_blocksize != blocksize) {
|
||||
/*
|
||||
* bh must be released before kill_bdev(), otherwise
|
||||
* it won't be freed and its page also. kill_bdev()
|
||||
* is called by sb_set_blocksize().
|
||||
*/
|
||||
brelse(bh);
|
||||
/* Validate the filesystem blocksize */
|
||||
if (!sb_set_blocksize(sb, blocksize)) {
|
||||
ext4_msg(sb, KERN_ERR, "bad block size %d",
|
||||
blocksize);
|
||||
bh = NULL;
|
||||
goto failed_mount;
|
||||
}
|
||||
|
||||
brelse(bh);
|
||||
logical_sb_block = sb_block * EXT4_MIN_BLOCK_SIZE;
|
||||
offset = do_div(logical_sb_block, blocksize);
|
||||
bh = ext4_sb_bread_unmovable(sb, logical_sb_block);
|
||||
|
@ -5202,8 +5208,9 @@ failed_mount:
|
|||
kfree(get_qf_name(sb, sbi, i));
|
||||
#endif
|
||||
fscrypt_free_dummy_policy(&sbi->s_dummy_enc_policy);
|
||||
ext4_blkdev_remove(sbi);
|
||||
/* ext4_blkdev_remove() calls kill_bdev(), release bh before it. */
|
||||
brelse(bh);
|
||||
ext4_blkdev_remove(sbi);
|
||||
out_fail:
|
||||
sb->s_fs_info = NULL;
|
||||
kfree(sbi->s_blockgroup_lock);
|
||||
|
|
|
@ -315,7 +315,9 @@ EXT4_ATTR_FEATURE(verity);
|
|||
#endif
|
||||
EXT4_ATTR_FEATURE(metadata_csum_seed);
|
||||
EXT4_ATTR_FEATURE(fast_commit);
|
||||
#if defined(CONFIG_UNICODE) && defined(CONFIG_FS_ENCRYPTION)
|
||||
EXT4_ATTR_FEATURE(encrypted_casefold);
|
||||
#endif
|
||||
|
||||
static struct attribute *ext4_feat_attrs[] = {
|
||||
ATTR_LIST(lazy_itable_init),
|
||||
|
@ -333,7 +335,9 @@ static struct attribute *ext4_feat_attrs[] = {
|
|||
#endif
|
||||
ATTR_LIST(metadata_csum_seed),
|
||||
ATTR_LIST(fast_commit),
|
||||
#if defined(CONFIG_UNICODE) && defined(CONFIG_FS_ENCRYPTION)
|
||||
ATTR_LIST(encrypted_casefold),
|
||||
#endif
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(ext4_feat);
|
||||
|
|
Loading…
Reference in New Issue