Commit 0bc9bc1d authored by Linus Torvalds's avatar Linus Torvalds

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:
 "A number of bug fixes for ext4:

   - Fix for the new fast_commit feature

   - Fix some error handling codepaths in whiteout handling and
     mountpoint sampling

   - Fix how we write ext4_error information so it goes through the
     journal when journalling is active, to avoid races that can lead to
     lost error information, superblock checksum failures, or DIF/DIX
     features"

* tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4:
  ext4: remove expensive flush on fast commit
  ext4: fix bug for rename with RENAME_WHITEOUT
  ext4: fix wrong list_splice in ext4_fc_cleanup
  ext4: use IS_ERR instead of IS_ERR_OR_NULL and set inode null when IS_ERR
  ext4: don't leak old mountpoint samples
  ext4: drop ext4_handle_dirty_super()
  ext4: fix superblock checksum failure when setting password salt
  ext4: use sbi instead of EXT4_SB(sb) in ext4_update_super()
  ext4: save error info to sb through journal if available
  ext4: protect superblock modifications with a buffer lock
  ext4: drop sync argument of ext4_commit_super()
  ext4: combine ext4_handle_error() and save_error_info()
parents 7cd3c412 e9f53353
...@@ -372,20 +372,3 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line, ...@@ -372,20 +372,3 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
} }
return err; return err;
} }
int __ext4_handle_dirty_super(const char *where, unsigned int line,
handle_t *handle, struct super_block *sb)
{
struct buffer_head *bh = EXT4_SB(sb)->s_sbh;
int err = 0;
ext4_superblock_csum_set(sb);
if (ext4_handle_valid(handle)) {
err = jbd2_journal_dirty_metadata(handle, bh);
if (err)
ext4_journal_abort_handle(where, line, __func__,
bh, handle, err);
} else
mark_buffer_dirty(bh);
return err;
}
...@@ -244,9 +244,6 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line, ...@@ -244,9 +244,6 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
handle_t *handle, struct inode *inode, handle_t *handle, struct inode *inode,
struct buffer_head *bh); struct buffer_head *bh);
int __ext4_handle_dirty_super(const char *where, unsigned int line,
handle_t *handle, struct super_block *sb);
#define ext4_journal_get_write_access(handle, bh) \ #define ext4_journal_get_write_access(handle, bh) \
__ext4_journal_get_write_access(__func__, __LINE__, (handle), (bh)) __ext4_journal_get_write_access(__func__, __LINE__, (handle), (bh))
#define ext4_forget(handle, is_metadata, inode, bh, block_nr) \ #define ext4_forget(handle, is_metadata, inode, bh, block_nr) \
...@@ -257,8 +254,6 @@ int __ext4_handle_dirty_super(const char *where, unsigned int line, ...@@ -257,8 +254,6 @@ int __ext4_handle_dirty_super(const char *where, unsigned int line,
#define ext4_handle_dirty_metadata(handle, inode, bh) \ #define ext4_handle_dirty_metadata(handle, inode, bh) \
__ext4_handle_dirty_metadata(__func__, __LINE__, (handle), (inode), \ __ext4_handle_dirty_metadata(__func__, __LINE__, (handle), (inode), \
(bh)) (bh))
#define ext4_handle_dirty_super(handle, sb) \
__ext4_handle_dirty_super(__func__, __LINE__, (handle), (sb))
handle_t *__ext4_journal_start_sb(struct super_block *sb, unsigned int line, handle_t *__ext4_journal_start_sb(struct super_block *sb, unsigned int line,
int type, int blocks, int rsv_blocks, int type, int blocks, int rsv_blocks,
......
...@@ -604,13 +604,13 @@ void ext4_fc_track_range(handle_t *handle, struct inode *inode, ext4_lblk_t star ...@@ -604,13 +604,13 @@ void ext4_fc_track_range(handle_t *handle, struct inode *inode, ext4_lblk_t star
trace_ext4_fc_track_range(inode, start, end, ret); trace_ext4_fc_track_range(inode, start, end, ret);
} }
static void ext4_fc_submit_bh(struct super_block *sb) static void ext4_fc_submit_bh(struct super_block *sb, bool is_tail)
{ {
int write_flags = REQ_SYNC; int write_flags = REQ_SYNC;
struct buffer_head *bh = EXT4_SB(sb)->s_fc_bh; struct buffer_head *bh = EXT4_SB(sb)->s_fc_bh;
/* TODO: REQ_FUA | REQ_PREFLUSH is unnecessarily expensive. */ /* Add REQ_FUA | REQ_PREFLUSH only its tail */
if (test_opt(sb, BARRIER)) if (test_opt(sb, BARRIER) && is_tail)
write_flags |= REQ_FUA | REQ_PREFLUSH; write_flags |= REQ_FUA | REQ_PREFLUSH;
lock_buffer(bh); lock_buffer(bh);
set_buffer_dirty(bh); set_buffer_dirty(bh);
...@@ -684,7 +684,7 @@ static u8 *ext4_fc_reserve_space(struct super_block *sb, int len, u32 *crc) ...@@ -684,7 +684,7 @@ static u8 *ext4_fc_reserve_space(struct super_block *sb, int len, u32 *crc)
*crc = ext4_chksum(sbi, *crc, tl, sizeof(*tl)); *crc = ext4_chksum(sbi, *crc, tl, sizeof(*tl));
if (pad_len > 0) if (pad_len > 0)
ext4_fc_memzero(sb, tl + 1, pad_len, crc); ext4_fc_memzero(sb, tl + 1, pad_len, crc);
ext4_fc_submit_bh(sb); ext4_fc_submit_bh(sb, false);
ret = jbd2_fc_get_buf(EXT4_SB(sb)->s_journal, &bh); ret = jbd2_fc_get_buf(EXT4_SB(sb)->s_journal, &bh);
if (ret) if (ret)
...@@ -741,7 +741,7 @@ static int ext4_fc_write_tail(struct super_block *sb, u32 crc) ...@@ -741,7 +741,7 @@ static int ext4_fc_write_tail(struct super_block *sb, u32 crc)
tail.fc_crc = cpu_to_le32(crc); tail.fc_crc = cpu_to_le32(crc);
ext4_fc_memcpy(sb, dst, &tail.fc_crc, sizeof(tail.fc_crc), NULL); ext4_fc_memcpy(sb, dst, &tail.fc_crc, sizeof(tail.fc_crc), NULL);
ext4_fc_submit_bh(sb); ext4_fc_submit_bh(sb, true);
return 0; return 0;
} }
...@@ -1268,7 +1268,7 @@ static void ext4_fc_cleanup(journal_t *journal, int full) ...@@ -1268,7 +1268,7 @@ static void ext4_fc_cleanup(journal_t *journal, int full)
list_splice_init(&sbi->s_fc_dentry_q[FC_Q_STAGING], list_splice_init(&sbi->s_fc_dentry_q[FC_Q_STAGING],
&sbi->s_fc_dentry_q[FC_Q_MAIN]); &sbi->s_fc_dentry_q[FC_Q_MAIN]);
list_splice_init(&sbi->s_fc_q[FC_Q_STAGING], list_splice_init(&sbi->s_fc_q[FC_Q_STAGING],
&sbi->s_fc_q[FC_Q_STAGING]); &sbi->s_fc_q[FC_Q_MAIN]);
ext4_clear_mount_flag(sb, EXT4_MF_FC_COMMITTING); ext4_clear_mount_flag(sb, EXT4_MF_FC_COMMITTING);
ext4_clear_mount_flag(sb, EXT4_MF_FC_INELIGIBLE); ext4_clear_mount_flag(sb, EXT4_MF_FC_INELIGIBLE);
...@@ -1318,14 +1318,14 @@ static int ext4_fc_replay_unlink(struct super_block *sb, struct ext4_fc_tl *tl) ...@@ -1318,14 +1318,14 @@ static int ext4_fc_replay_unlink(struct super_block *sb, struct ext4_fc_tl *tl)
entry.len = darg.dname_len; entry.len = darg.dname_len;
inode = ext4_iget(sb, darg.ino, EXT4_IGET_NORMAL); inode = ext4_iget(sb, darg.ino, EXT4_IGET_NORMAL);
if (IS_ERR_OR_NULL(inode)) { if (IS_ERR(inode)) {
jbd_debug(1, "Inode %d not found", darg.ino); jbd_debug(1, "Inode %d not found", darg.ino);
return 0; return 0;
} }
old_parent = ext4_iget(sb, darg.parent_ino, old_parent = ext4_iget(sb, darg.parent_ino,
EXT4_IGET_NORMAL); EXT4_IGET_NORMAL);
if (IS_ERR_OR_NULL(old_parent)) { if (IS_ERR(old_parent)) {
jbd_debug(1, "Dir with inode %d not found", darg.parent_ino); jbd_debug(1, "Dir with inode %d not found", darg.parent_ino);
iput(inode); iput(inode);
return 0; return 0;
...@@ -1410,7 +1410,7 @@ static int ext4_fc_replay_link(struct super_block *sb, struct ext4_fc_tl *tl) ...@@ -1410,7 +1410,7 @@ static int ext4_fc_replay_link(struct super_block *sb, struct ext4_fc_tl *tl)
darg.parent_ino, darg.dname_len); darg.parent_ino, darg.dname_len);
inode = ext4_iget(sb, darg.ino, EXT4_IGET_NORMAL); inode = ext4_iget(sb, darg.ino, EXT4_IGET_NORMAL);
if (IS_ERR_OR_NULL(inode)) { if (IS_ERR(inode)) {
jbd_debug(1, "Inode not found."); jbd_debug(1, "Inode not found.");
return 0; return 0;
} }
...@@ -1466,10 +1466,11 @@ static int ext4_fc_replay_inode(struct super_block *sb, struct ext4_fc_tl *tl) ...@@ -1466,10 +1466,11 @@ static int ext4_fc_replay_inode(struct super_block *sb, struct ext4_fc_tl *tl)
trace_ext4_fc_replay(sb, tag, ino, 0, 0); trace_ext4_fc_replay(sb, tag, ino, 0, 0);
inode = ext4_iget(sb, ino, EXT4_IGET_NORMAL); inode = ext4_iget(sb, ino, EXT4_IGET_NORMAL);
if (!IS_ERR_OR_NULL(inode)) { if (!IS_ERR(inode)) {
ext4_ext_clear_bb(inode); ext4_ext_clear_bb(inode);
iput(inode); iput(inode);
} }
inode = NULL;
ext4_fc_record_modified_inode(sb, ino); ext4_fc_record_modified_inode(sb, ino);
...@@ -1512,7 +1513,7 @@ static int ext4_fc_replay_inode(struct super_block *sb, struct ext4_fc_tl *tl) ...@@ -1512,7 +1513,7 @@ static int ext4_fc_replay_inode(struct super_block *sb, struct ext4_fc_tl *tl)
/* Given that we just wrote the inode on disk, this SHOULD succeed. */ /* Given that we just wrote the inode on disk, this SHOULD succeed. */
inode = ext4_iget(sb, ino, EXT4_IGET_NORMAL); inode = ext4_iget(sb, ino, EXT4_IGET_NORMAL);
if (IS_ERR_OR_NULL(inode)) { if (IS_ERR(inode)) {
jbd_debug(1, "Inode not found."); jbd_debug(1, "Inode not found.");
return -EFSCORRUPTED; return -EFSCORRUPTED;
} }
...@@ -1564,7 +1565,7 @@ static int ext4_fc_replay_create(struct super_block *sb, struct ext4_fc_tl *tl) ...@@ -1564,7 +1565,7 @@ static int ext4_fc_replay_create(struct super_block *sb, struct ext4_fc_tl *tl)
goto out; goto out;
inode = ext4_iget(sb, darg.ino, EXT4_IGET_NORMAL); inode = ext4_iget(sb, darg.ino, EXT4_IGET_NORMAL);
if (IS_ERR_OR_NULL(inode)) { if (IS_ERR(inode)) {
jbd_debug(1, "inode %d not found.", darg.ino); jbd_debug(1, "inode %d not found.", darg.ino);
inode = NULL; inode = NULL;
ret = -EINVAL; ret = -EINVAL;
...@@ -1577,7 +1578,7 @@ static int ext4_fc_replay_create(struct super_block *sb, struct ext4_fc_tl *tl) ...@@ -1577,7 +1578,7 @@ static int ext4_fc_replay_create(struct super_block *sb, struct ext4_fc_tl *tl)
* dot and dot dot dirents are setup properly. * dot and dot dot dirents are setup properly.
*/ */
dir = ext4_iget(sb, darg.parent_ino, EXT4_IGET_NORMAL); dir = ext4_iget(sb, darg.parent_ino, EXT4_IGET_NORMAL);
if (IS_ERR_OR_NULL(dir)) { if (IS_ERR(dir)) {
jbd_debug(1, "Dir %d not found.", darg.ino); jbd_debug(1, "Dir %d not found.", darg.ino);
goto out; goto out;
} }
...@@ -1653,7 +1654,7 @@ static int ext4_fc_replay_add_range(struct super_block *sb, ...@@ -1653,7 +1654,7 @@ static int ext4_fc_replay_add_range(struct super_block *sb,
inode = ext4_iget(sb, le32_to_cpu(fc_add_ex->fc_ino), inode = ext4_iget(sb, le32_to_cpu(fc_add_ex->fc_ino),
EXT4_IGET_NORMAL); EXT4_IGET_NORMAL);
if (IS_ERR_OR_NULL(inode)) { if (IS_ERR(inode)) {
jbd_debug(1, "Inode not found."); jbd_debug(1, "Inode not found.");
return 0; return 0;
} }
...@@ -1777,7 +1778,7 @@ ext4_fc_replay_del_range(struct super_block *sb, struct ext4_fc_tl *tl) ...@@ -1777,7 +1778,7 @@ ext4_fc_replay_del_range(struct super_block *sb, struct ext4_fc_tl *tl)
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_OR_NULL(inode)) { 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; return 0;
} }
...@@ -1832,7 +1833,7 @@ static void ext4_fc_set_bitmaps_and_counters(struct super_block *sb) ...@@ -1832,7 +1833,7 @@ static void ext4_fc_set_bitmaps_and_counters(struct super_block *sb)
for (i = 0; i < state->fc_modified_inodes_used; i++) { for (i = 0; i < state->fc_modified_inodes_used; i++) {
inode = ext4_iget(sb, state->fc_modified_inodes[i], inode = ext4_iget(sb, state->fc_modified_inodes[i],
EXT4_IGET_NORMAL); EXT4_IGET_NORMAL);
if (IS_ERR_OR_NULL(inode)) { if (IS_ERR(inode)) {
jbd_debug(1, "Inode %d not found.", jbd_debug(1, "Inode %d not found.",
state->fc_modified_inodes[i]); state->fc_modified_inodes[i]);
continue; continue;
...@@ -1849,7 +1850,7 @@ static void ext4_fc_set_bitmaps_and_counters(struct super_block *sb) ...@@ -1849,7 +1850,7 @@ static void ext4_fc_set_bitmaps_and_counters(struct super_block *sb)
if (ret > 0) { if (ret > 0) {
path = ext4_find_extent(inode, map.m_lblk, NULL, 0); path = ext4_find_extent(inode, map.m_lblk, NULL, 0);
if (!IS_ERR_OR_NULL(path)) { if (!IS_ERR(path)) {
for (j = 0; j < path->p_depth; j++) for (j = 0; j < path->p_depth; j++)
ext4_mb_mark_bb(inode->i_sb, ext4_mb_mark_bb(inode->i_sb,
path[j].p_block, 1, 1); path[j].p_block, 1, 1);
......
...@@ -809,9 +809,12 @@ static int ext4_sample_last_mounted(struct super_block *sb, ...@@ -809,9 +809,12 @@ static int ext4_sample_last_mounted(struct super_block *sb,
err = ext4_journal_get_write_access(handle, sbi->s_sbh); err = ext4_journal_get_write_access(handle, sbi->s_sbh);
if (err) if (err)
goto out_journal; goto out_journal;
strlcpy(sbi->s_es->s_last_mounted, cp, lock_buffer(sbi->s_sbh);
strncpy(sbi->s_es->s_last_mounted, cp,
sizeof(sbi->s_es->s_last_mounted)); sizeof(sbi->s_es->s_last_mounted));
ext4_handle_dirty_super(handle, sb); ext4_superblock_csum_set(sb);
unlock_buffer(sbi->s_sbh);
ext4_handle_dirty_metadata(handle, NULL, sbi->s_sbh);
out_journal: out_journal:
ext4_journal_stop(handle); ext4_journal_stop(handle);
out: out:
......
...@@ -5150,9 +5150,13 @@ static int ext4_do_update_inode(handle_t *handle, ...@@ -5150,9 +5150,13 @@ static int ext4_do_update_inode(handle_t *handle,
err = ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh); err = ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh);
if (err) if (err)
goto out_brelse; goto out_brelse;
lock_buffer(EXT4_SB(sb)->s_sbh);
ext4_set_feature_large_file(sb); ext4_set_feature_large_file(sb);
ext4_superblock_csum_set(sb);
unlock_buffer(EXT4_SB(sb)->s_sbh);
ext4_handle_sync(handle); ext4_handle_sync(handle);
err = ext4_handle_dirty_super(handle, sb); err = ext4_handle_dirty_metadata(handle, NULL,
EXT4_SB(sb)->s_sbh);
} }
ext4_update_inode_fsync_trans(handle, inode, need_datasync); ext4_update_inode_fsync_trans(handle, inode, need_datasync);
out_brelse: out_brelse:
......
...@@ -1157,7 +1157,10 @@ static long __ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ...@@ -1157,7 +1157,10 @@ static long __ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
err = ext4_journal_get_write_access(handle, sbi->s_sbh); err = ext4_journal_get_write_access(handle, sbi->s_sbh);
if (err) if (err)
goto pwsalt_err_journal; goto pwsalt_err_journal;
lock_buffer(sbi->s_sbh);
generate_random_uuid(sbi->s_es->s_encrypt_pw_salt); generate_random_uuid(sbi->s_es->s_encrypt_pw_salt);
ext4_superblock_csum_set(sb);
unlock_buffer(sbi->s_sbh);
err = ext4_handle_dirty_metadata(handle, NULL, err = ext4_handle_dirty_metadata(handle, NULL,
sbi->s_sbh); sbi->s_sbh);
pwsalt_err_journal: pwsalt_err_journal:
......
...@@ -2976,14 +2976,17 @@ int ext4_orphan_add(handle_t *handle, struct inode *inode) ...@@ -2976,14 +2976,17 @@ int ext4_orphan_add(handle_t *handle, struct inode *inode)
(le32_to_cpu(sbi->s_es->s_inodes_count))) { (le32_to_cpu(sbi->s_es->s_inodes_count))) {
/* Insert this inode at the head of the on-disk orphan list */ /* Insert this inode at the head of the on-disk orphan list */
NEXT_ORPHAN(inode) = le32_to_cpu(sbi->s_es->s_last_orphan); NEXT_ORPHAN(inode) = le32_to_cpu(sbi->s_es->s_last_orphan);
lock_buffer(sbi->s_sbh);
sbi->s_es->s_last_orphan = cpu_to_le32(inode->i_ino); sbi->s_es->s_last_orphan = cpu_to_le32(inode->i_ino);
ext4_superblock_csum_set(sb);
unlock_buffer(sbi->s_sbh);
dirty = true; dirty = true;
} }
list_add(&EXT4_I(inode)->i_orphan, &sbi->s_orphan); list_add(&EXT4_I(inode)->i_orphan, &sbi->s_orphan);
mutex_unlock(&sbi->s_orphan_lock); mutex_unlock(&sbi->s_orphan_lock);
if (dirty) { if (dirty) {
err = ext4_handle_dirty_super(handle, sb); err = ext4_handle_dirty_metadata(handle, NULL, sbi->s_sbh);
rc = ext4_mark_iloc_dirty(handle, inode, &iloc); rc = ext4_mark_iloc_dirty(handle, inode, &iloc);
if (!err) if (!err)
err = rc; err = rc;
...@@ -3059,9 +3062,12 @@ int ext4_orphan_del(handle_t *handle, struct inode *inode) ...@@ -3059,9 +3062,12 @@ int ext4_orphan_del(handle_t *handle, struct inode *inode)
mutex_unlock(&sbi->s_orphan_lock); mutex_unlock(&sbi->s_orphan_lock);
goto out_brelse; goto out_brelse;
} }
lock_buffer(sbi->s_sbh);
sbi->s_es->s_last_orphan = cpu_to_le32(ino_next); sbi->s_es->s_last_orphan = cpu_to_le32(ino_next);
ext4_superblock_csum_set(inode->i_sb);
unlock_buffer(sbi->s_sbh);
mutex_unlock(&sbi->s_orphan_lock); mutex_unlock(&sbi->s_orphan_lock);
err = ext4_handle_dirty_super(handle, inode->i_sb); err = ext4_handle_dirty_metadata(handle, NULL, sbi->s_sbh);
} else { } else {
struct ext4_iloc iloc2; struct ext4_iloc iloc2;
struct inode *i_prev = struct inode *i_prev =
...@@ -3593,9 +3599,6 @@ static int ext4_setent(handle_t *handle, struct ext4_renament *ent, ...@@ -3593,9 +3599,6 @@ static int ext4_setent(handle_t *handle, struct ext4_renament *ent,
return retval2; return retval2;
} }
} }
brelse(ent->bh);
ent->bh = NULL;
return retval; return retval;
} }
...@@ -3794,6 +3797,7 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -3794,6 +3797,7 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
} }
} }
old_file_type = old.de->file_type;
if (IS_DIRSYNC(old.dir) || IS_DIRSYNC(new.dir)) if (IS_DIRSYNC(old.dir) || IS_DIRSYNC(new.dir))
ext4_handle_sync(handle); ext4_handle_sync(handle);
...@@ -3821,7 +3825,6 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -3821,7 +3825,6 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
force_reread = (new.dir->i_ino == old.dir->i_ino && force_reread = (new.dir->i_ino == old.dir->i_ino &&
ext4_test_inode_flag(new.dir, EXT4_INODE_INLINE_DATA)); ext4_test_inode_flag(new.dir, EXT4_INODE_INLINE_DATA));
old_file_type = old.de->file_type;
if (whiteout) { if (whiteout) {
/* /*
* Do this before adding a new entry, so the old entry is sure * Do this before adding a new entry, so the old entry is sure
...@@ -3919,15 +3922,19 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -3919,15 +3922,19 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
retval = 0; retval = 0;
end_rename: end_rename:
brelse(old.dir_bh);
brelse(old.bh);
brelse(new.bh);
if (whiteout) { if (whiteout) {
if (retval) if (retval) {
ext4_setent(handle, &old,
old.inode->i_ino, old_file_type);
drop_nlink(whiteout); drop_nlink(whiteout);
}
unlock_new_inode(whiteout); unlock_new_inode(whiteout);
iput(whiteout); iput(whiteout);
} }
brelse(old.dir_bh);
brelse(old.bh);
brelse(new.bh);
if (handle) if (handle)
ext4_journal_stop(handle); ext4_journal_stop(handle);
return retval; return retval;
......
...@@ -899,8 +899,11 @@ static int add_new_gdb(handle_t *handle, struct inode *inode, ...@@ -899,8 +899,11 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
EXT4_SB(sb)->s_gdb_count++; EXT4_SB(sb)->s_gdb_count++;
ext4_kvfree_array_rcu(o_group_desc); ext4_kvfree_array_rcu(o_group_desc);
lock_buffer(EXT4_SB(sb)->s_sbh);
le16_add_cpu(&es->s_reserved_gdt_blocks, -1); le16_add_cpu(&es->s_reserved_gdt_blocks, -1);
err = ext4_handle_dirty_super(handle, sb); ext4_superblock_csum_set(sb);
unlock_buffer(EXT4_SB(sb)->s_sbh);
err = ext4_handle_dirty_metadata(handle, NULL, EXT4_SB(sb)->s_sbh);
if (err) if (err)
ext4_std_error(sb, err); ext4_std_error(sb, err);
return err; return err;
...@@ -1384,6 +1387,7 @@ static void ext4_update_super(struct super_block *sb, ...@@ -1384,6 +1387,7 @@ static void ext4_update_super(struct super_block *sb,
reserved_blocks *= blocks_count; reserved_blocks *= blocks_count;
do_div(reserved_blocks, 100); do_div(reserved_blocks, 100);
lock_buffer(sbi->s_sbh);
ext4_blocks_count_set(es, ext4_blocks_count(es) + blocks_count); ext4_blocks_count_set(es, ext4_blocks_count(es) + blocks_count);
ext4_free_blocks_count_set(es, ext4_free_blocks_count(es) + free_blocks); ext4_free_blocks_count_set(es, ext4_free_blocks_count(es) + free_blocks);
le32_add_cpu(&es->s_inodes_count, EXT4_INODES_PER_GROUP(sb) * le32_add_cpu(&es->s_inodes_count, EXT4_INODES_PER_GROUP(sb) *
...@@ -1421,6 +1425,8 @@ static void ext4_update_super(struct super_block *sb, ...@@ -1421,6 +1425,8 @@ static void ext4_update_super(struct super_block *sb,
* active. */ * active. */
ext4_r_blocks_count_set(es, ext4_r_blocks_count(es) + ext4_r_blocks_count_set(es, ext4_r_blocks_count(es) +
reserved_blocks); reserved_blocks);
ext4_superblock_csum_set(sb);
unlock_buffer(sbi->s_sbh);
/* Update the free space counts */ /* Update the free space counts */
percpu_counter_add(&sbi->s_freeclusters_counter, percpu_counter_add(&sbi->s_freeclusters_counter,
...@@ -1515,7 +1521,7 @@ static int ext4_flex_group_add(struct super_block *sb, ...@@ -1515,7 +1521,7 @@ static int ext4_flex_group_add(struct super_block *sb,
ext4_update_super(sb, flex_gd); ext4_update_super(sb, flex_gd);
err = ext4_handle_dirty_super(handle, sb); err = ext4_handle_dirty_metadata(handle, NULL, sbi->s_sbh);
exit_journal: exit_journal:
err2 = ext4_journal_stop(handle); err2 = ext4_journal_stop(handle);
...@@ -1717,15 +1723,18 @@ static int ext4_group_extend_no_check(struct super_block *sb, ...@@ -1717,15 +1723,18 @@ static int ext4_group_extend_no_check(struct super_block *sb,
goto errout; goto errout;
} }
lock_buffer(EXT4_SB(sb)->s_sbh);
ext4_blocks_count_set(es, o_blocks_count + add); ext4_blocks_count_set(es, o_blocks_count + add);
ext4_free_blocks_count_set(es, ext4_free_blocks_count(es) + add); ext4_free_blocks_count_set(es, ext4_free_blocks_count(es) + add);
ext4_superblock_csum_set(sb);
unlock_buffer(EXT4_SB(sb)->s_sbh);
ext4_debug("freeing blocks %llu through %llu\n", o_blocks_count, ext4_debug("freeing blocks %llu through %llu\n", o_blocks_count,
o_blocks_count + add); o_blocks_count + add);
/* We add the blocks to the bitmap and set the group need init bit */ /* We add the blocks to the bitmap and set the group need init bit */
err = ext4_group_add_blocks(handle, sb, o_blocks_count, add); err = ext4_group_add_blocks(handle, sb, o_blocks_count, add);
if (err) if (err)
goto errout; goto errout;
ext4_handle_dirty_super(handle, sb); ext4_handle_dirty_metadata(handle, NULL, EXT4_SB(sb)->s_sbh);
ext4_debug("freed blocks %llu through %llu\n", o_blocks_count, ext4_debug("freed blocks %llu through %llu\n", o_blocks_count,
o_blocks_count + add); o_blocks_count + add);
errout: errout:
...@@ -1874,12 +1883,15 @@ static int ext4_convert_meta_bg(struct super_block *sb, struct inode *inode) ...@@ -1874,12 +1883,15 @@ static int ext4_convert_meta_bg(struct super_block *sb, struct inode *inode)
if (err) if (err)
goto errout; goto errout;
lock_buffer(sbi->s_sbh);
ext4_clear_feature_resize_inode(sb); ext4_clear_feature_resize_inode(sb);
ext4_set_feature_meta_bg(sb); ext4_set_feature_meta_bg(sb);
sbi->s_es->s_first_meta_bg = sbi->s_es->s_first_meta_bg =
cpu_to_le32(num_desc_blocks(sb, sbi->s_groups_count)); cpu_to_le32(num_desc_blocks(sb, sbi->s_groups_count));
ext4_superblock_csum_set(sb);
unlock_buffer(sbi->s_sbh);
err = ext4_handle_dirty_super(handle, sb); err = ext4_handle_dirty_metadata(handle, NULL, sbi->s_sbh);
if (err) { if (err) {
ext4_std_error(sb, err); ext4_std_error(sb, err);
goto errout; goto errout;
......
This diff is collapsed.
...@@ -792,8 +792,11 @@ static void ext4_xattr_update_super_block(handle_t *handle, ...@@ -792,8 +792,11 @@ static void ext4_xattr_update_super_block(handle_t *handle,
BUFFER_TRACE(EXT4_SB(sb)->s_sbh, "get_write_access"); BUFFER_TRACE(EXT4_SB(sb)->s_sbh, "get_write_access");
if (ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh) == 0) { if (ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh) == 0) {
lock_buffer(EXT4_SB(sb)->s_sbh);
ext4_set_feature_xattr(sb); ext4_set_feature_xattr(sb);
ext4_handle_dirty_super(handle, sb); ext4_superblock_csum_set(sb);
unlock_buffer(EXT4_SB(sb)->s_sbh);
ext4_handle_dirty_metadata(handle, NULL, EXT4_SB(sb)->s_sbh);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment