From a25a84c6aa2a19987b0aeced363c4bf1dcc89ec8 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Thu, 13 Feb 2020 11:15:58 +0100 Subject: [PATCH] ext2fs: update allocation info earlier in ext2fs_mkdir() and ext2fs_symlink() Currently, ext2fs_mkdir() and ext2fs_symlink() update allocation bitmaps and other information only close to the end of the function, in particular after calling to ext2fs_link(). When ext2fs_link() will support indexed directories, it will also need to allocate blocks and that would cause filesystem corruption in case allocation info isn't properly updated. So make sure ext2fs_mkdir() and ext2fs_symlink() update allocation info before calling into ext2fs_link(). [ Added error handling so the calls to ext2fs_{block,inode}_alloc_stats() can be undone if the newly created directory or symlink can not be linked into the directory. -- TYT ] Signed-off-by: Jan Kara Signed-off-by: Theodore Ts'o --- lib/ext2fs/mkdir.c | 22 +++++++++++++++------- lib/ext2fs/symlink.c | 22 +++++++++++++++------- 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/lib/ext2fs/mkdir.c b/lib/ext2fs/mkdir.c index 2a63aad..437c8ff 100644 --- a/lib/ext2fs/mkdir.c +++ b/lib/ext2fs/mkdir.c @@ -43,6 +43,7 @@ errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum, blk64_t blk; char *block = 0; int inline_data = 0; + int drop_refcount = 0; EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); @@ -144,6 +145,14 @@ errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum, } /* + * Update accounting.... + */ + if (!inline_data) + ext2fs_block_alloc_stats2(fs, blk, +1); + ext2fs_inode_alloc_stats2(fs, ino, +1, 1); + drop_refcount = 1; + + /* * Link the directory into the filesystem hierarchy */ if (name) { @@ -174,17 +183,16 @@ errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum, if (retval) goto cleanup; } - - /* - * Update accounting.... - */ - if (!inline_data) - ext2fs_block_alloc_stats2(fs, blk, +1); - ext2fs_inode_alloc_stats2(fs, ino, +1, 1); + drop_refcount = 0; cleanup: if (block) ext2fs_free_mem(&block); + if (drop_refcount) { + if (!inline_data) + ext2fs_block_alloc_stats2(fs, blk, -1); + ext2fs_inode_alloc_stats2(fs, ino, -1, 1); + } return retval; } diff --git a/lib/ext2fs/symlink.c b/lib/ext2fs/symlink.c index 7f78c5f..a66fb7e 100644 --- a/lib/ext2fs/symlink.c +++ b/lib/ext2fs/symlink.c @@ -54,6 +54,7 @@ errcode_t ext2fs_symlink(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t ino, int fastlink, inlinelink; unsigned int target_len; char *block_buf = 0; + int drop_refcount = 0; EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); @@ -163,6 +164,14 @@ need_block: } /* + * Update accounting.... + */ + if (!fastlink && !inlinelink) + ext2fs_block_alloc_stats2(fs, blk, +1); + ext2fs_inode_alloc_stats2(fs, ino, +1, 0); + drop_refcount = 1; + + /* * Link the symlink into the filesystem hierarchy */ if (name) { @@ -178,17 +187,16 @@ need_block: if (retval) goto cleanup; } - - /* - * Update accounting.... - */ - if (!fastlink && !inlinelink) - ext2fs_block_alloc_stats2(fs, blk, +1); - ext2fs_inode_alloc_stats2(fs, ino, +1, 0); + drop_refcount = 0; cleanup: if (block_buf) ext2fs_free_mem(&block_buf); + if (drop_refcount) { + if (!fastlink && !inlinelink) + ext2fs_block_alloc_stats2(fs, blk, -1); + ext2fs_inode_alloc_stats2(fs, ino, -1, 0); + } return retval; } -- 1.8.3.1