|
@@ -4305,12 +4305,15 @@ static int ext4_do_update_inode(handle_t *handle,
|
|
struct ext4_inode *raw_inode = ext4_raw_inode(iloc);
|
|
struct ext4_inode *raw_inode = ext4_raw_inode(iloc);
|
|
struct ext4_inode_info *ei = EXT4_I(inode);
|
|
struct ext4_inode_info *ei = EXT4_I(inode);
|
|
struct buffer_head *bh = iloc->bh;
|
|
struct buffer_head *bh = iloc->bh;
|
|
|
|
+ struct super_block *sb = inode->i_sb;
|
|
int err = 0, rc, block;
|
|
int err = 0, rc, block;
|
|
- int need_datasync = 0;
|
|
|
|
|
|
+ int need_datasync = 0, set_large_file = 0;
|
|
uid_t i_uid;
|
|
uid_t i_uid;
|
|
gid_t i_gid;
|
|
gid_t i_gid;
|
|
|
|
|
|
- /* For fields not not tracking in the in-memory inode,
|
|
|
|
|
|
+ spin_lock(&ei->i_raw_lock);
|
|
|
|
+
|
|
|
|
+ /* For fields not tracked in the in-memory inode,
|
|
* initialise them to zero for new inodes. */
|
|
* initialise them to zero for new inodes. */
|
|
if (ext4_test_inode_state(inode, EXT4_STATE_NEW))
|
|
if (ext4_test_inode_state(inode, EXT4_STATE_NEW))
|
|
memset(raw_inode, 0, EXT4_SB(inode->i_sb)->s_inode_size);
|
|
memset(raw_inode, 0, EXT4_SB(inode->i_sb)->s_inode_size);
|
|
@@ -4348,8 +4351,10 @@ static int ext4_do_update_inode(handle_t *handle,
|
|
EXT4_INODE_SET_XTIME(i_atime, inode, raw_inode);
|
|
EXT4_INODE_SET_XTIME(i_atime, inode, raw_inode);
|
|
EXT4_EINODE_SET_XTIME(i_crtime, ei, raw_inode);
|
|
EXT4_EINODE_SET_XTIME(i_crtime, ei, raw_inode);
|
|
|
|
|
|
- if (ext4_inode_blocks_set(handle, raw_inode, ei))
|
|
|
|
|
|
+ if (ext4_inode_blocks_set(handle, raw_inode, ei)) {
|
|
|
|
+ spin_unlock(&ei->i_raw_lock);
|
|
goto out_brelse;
|
|
goto out_brelse;
|
|
|
|
+ }
|
|
raw_inode->i_dtime = cpu_to_le32(ei->i_dtime);
|
|
raw_inode->i_dtime = cpu_to_le32(ei->i_dtime);
|
|
raw_inode->i_flags = cpu_to_le32(ei->i_flags & 0xFFFFFFFF);
|
|
raw_inode->i_flags = cpu_to_le32(ei->i_flags & 0xFFFFFFFF);
|
|
if (likely(!test_opt2(inode->i_sb, HURD_COMPAT)))
|
|
if (likely(!test_opt2(inode->i_sb, HURD_COMPAT)))
|
|
@@ -4361,24 +4366,11 @@ static int ext4_do_update_inode(handle_t *handle,
|
|
need_datasync = 1;
|
|
need_datasync = 1;
|
|
}
|
|
}
|
|
if (ei->i_disksize > 0x7fffffffULL) {
|
|
if (ei->i_disksize > 0x7fffffffULL) {
|
|
- struct super_block *sb = inode->i_sb;
|
|
|
|
if (!EXT4_HAS_RO_COMPAT_FEATURE(sb,
|
|
if (!EXT4_HAS_RO_COMPAT_FEATURE(sb,
|
|
EXT4_FEATURE_RO_COMPAT_LARGE_FILE) ||
|
|
EXT4_FEATURE_RO_COMPAT_LARGE_FILE) ||
|
|
EXT4_SB(sb)->s_es->s_rev_level ==
|
|
EXT4_SB(sb)->s_es->s_rev_level ==
|
|
- cpu_to_le32(EXT4_GOOD_OLD_REV)) {
|
|
|
|
- /* If this is the first large file
|
|
|
|
- * created, add a flag to the superblock.
|
|
|
|
- */
|
|
|
|
- err = ext4_journal_get_write_access(handle,
|
|
|
|
- EXT4_SB(sb)->s_sbh);
|
|
|
|
- if (err)
|
|
|
|
- goto out_brelse;
|
|
|
|
- ext4_update_dynamic_rev(sb);
|
|
|
|
- EXT4_SET_RO_COMPAT_FEATURE(sb,
|
|
|
|
- EXT4_FEATURE_RO_COMPAT_LARGE_FILE);
|
|
|
|
- ext4_handle_sync(handle);
|
|
|
|
- err = ext4_handle_dirty_super(handle, sb);
|
|
|
|
- }
|
|
|
|
|
|
+ cpu_to_le32(EXT4_GOOD_OLD_REV))
|
|
|
|
+ set_large_file = 1;
|
|
}
|
|
}
|
|
raw_inode->i_generation = cpu_to_le32(inode->i_generation);
|
|
raw_inode->i_generation = cpu_to_le32(inode->i_generation);
|
|
if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
|
|
if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
|
|
@@ -4410,12 +4402,23 @@ static int ext4_do_update_inode(handle_t *handle,
|
|
|
|
|
|
ext4_inode_csum_set(inode, raw_inode, ei);
|
|
ext4_inode_csum_set(inode, raw_inode, ei);
|
|
|
|
|
|
|
|
+ spin_unlock(&ei->i_raw_lock);
|
|
|
|
+
|
|
BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
|
|
BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
|
|
rc = ext4_handle_dirty_metadata(handle, NULL, bh);
|
|
rc = ext4_handle_dirty_metadata(handle, NULL, bh);
|
|
if (!err)
|
|
if (!err)
|
|
err = rc;
|
|
err = rc;
|
|
ext4_clear_inode_state(inode, EXT4_STATE_NEW);
|
|
ext4_clear_inode_state(inode, EXT4_STATE_NEW);
|
|
-
|
|
|
|
|
|
+ if (set_large_file) {
|
|
|
|
+ err = ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh);
|
|
|
|
+ if (err)
|
|
|
|
+ goto out_brelse;
|
|
|
|
+ ext4_update_dynamic_rev(sb);
|
|
|
|
+ EXT4_SET_RO_COMPAT_FEATURE(sb,
|
|
|
|
+ EXT4_FEATURE_RO_COMPAT_LARGE_FILE);
|
|
|
|
+ ext4_handle_sync(handle);
|
|
|
|
+ err = ext4_handle_dirty_super(handle, sb);
|
|
|
|
+ }
|
|
ext4_update_inode_fsync_trans(handle, inode, need_datasync);
|
|
ext4_update_inode_fsync_trans(handle, inode, need_datasync);
|
|
out_brelse:
|
|
out_brelse:
|
|
brelse(bh);
|
|
brelse(bh);
|