diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 56112f201cac..9b8d35d33cb6 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -380,6 +380,17 @@ struct ext4_io_submit { #define EXT4_B2C(sbi, blk) ((blk) >> (sbi)->s_cluster_bits) /* Translate a cluster number to a block number */ #define EXT4_C2B(sbi, cluster) ((cluster) << (sbi)->s_cluster_bits) +/* + * Translate a physical block number to a cluster number using mballoc's + * cluster definition, which accounts for s_first_data_block. Use these + * when tracking partial->pclu so that the cluster numbers are consistent + * with what ext4_get_group_no_and_offset() (and thus ext4_free_blocks()) + * expects. + */ +#define EXT4_MB_B2C(sbi, nr) \ + (((nr) - le32_to_cpu((sbi)->s_es->s_first_data_block)) >> (sbi)->s_cluster_bits) +#define EXT4_MB_C2B(sbi, cluster) \ + (((cluster) << (sbi)->s_cluster_bits) + le32_to_cpu((sbi)->s_es->s_first_data_block)) /* Translate # of blks to # of clusters */ #define EXT4_NUM_B2C(sbi, blks) (((blks) + (sbi)->s_cluster_ratio - 1) >> \ (sbi)->s_cluster_bits) @@ -396,6 +407,16 @@ struct ext4_io_submit { ((ext4_fsblk_t) (s)->s_cluster_ratio - 1)) #define EXT4_LBLK_COFF(s, lblk) ((lblk) & \ ((ext4_lblk_t) (s)->s_cluster_ratio - 1)) +/* + * Cluster-offset macros that account for s_first_data_block, consistent + * with mballoc's cluster numbering. Use EXT4_MB_PBLK_COFF when aligning a + * physical block number and EXT4_MB_LBLK_COFF when aligning a block count. + */ +#define EXT4_MB_PBLK_COFF(sbi, pblk) \ + (((pblk) - le32_to_cpu((sbi)->s_es->s_first_data_block)) & \ + ((ext4_fsblk_t)(sbi)->s_cluster_ratio - 1)) +#define EXT4_MB_LBLK_COFF(sbi, lblk) \ + ((lblk) & ((ext4_lblk_t)(sbi)->s_cluster_ratio - 1)) /* * Structure of a blocks group descriptor diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 2cf5759ba689..48496094e85f 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -2499,13 +2499,13 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode, last_pblk = ext4_ext_pblock(ex) + ee_len - 1; if (partial->state != initial && - partial->pclu != EXT4_B2C(sbi, last_pblk)) { + partial->pclu != EXT4_MB_B2C(sbi, last_pblk)) { if (partial->state == tofree) { flags = get_default_free_blocks_flags(inode); if (ext4_is_pending(inode, partial->lblk)) flags |= EXT4_FREE_BLOCKS_RERESERVE_CLUSTER; ext4_free_blocks(handle, inode, NULL, - EXT4_C2B(sbi, partial->pclu), + EXT4_MB_C2B(sbi, partial->pclu), sbi->s_cluster_ratio, flags); if (flags & EXT4_FREE_BLOCKS_RERESERVE_CLUSTER) ext4_rereserve_cluster(inode, partial->lblk); @@ -2551,7 +2551,7 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode, ext4_free_blocks(handle, inode, NULL, pblk, num, flags); /* reset the partial cluster if we've freed past it */ - if (partial->state != initial && partial->pclu != EXT4_B2C(sbi, pblk)) + if (partial->state != initial && partial->pclu != EXT4_MB_B2C(sbi, pblk)) partial->state = initial; /* @@ -2566,7 +2566,7 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode, */ if (EXT4_LBLK_COFF(sbi, from) && num == ee_len) { if (partial->state == initial) { - partial->pclu = EXT4_B2C(sbi, pblk); + partial->pclu = EXT4_MB_B2C(sbi, pblk); partial->lblk = from; partial->state = tofree; } @@ -2657,7 +2657,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode, */ if (sbi->s_cluster_ratio > 1) { pblk = ext4_ext_pblock(ex); - partial->pclu = EXT4_B2C(sbi, pblk); + partial->pclu = EXT4_MB_B2C(sbi, pblk); partial->state = nofree; } ex--; @@ -2772,13 +2772,13 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode, */ if (partial->state == tofree && ex >= EXT_FIRST_EXTENT(eh)) { pblk = ext4_ext_pblock(ex) + ex_ee_len - 1; - if (partial->pclu != EXT4_B2C(sbi, pblk)) { + if (partial->pclu != EXT4_MB_B2C(sbi, pblk)) { int flags = get_default_free_blocks_flags(inode); if (ext4_is_pending(inode, partial->lblk)) flags |= EXT4_FREE_BLOCKS_RERESERVE_CLUSTER; ext4_free_blocks(handle, inode, NULL, - EXT4_C2B(sbi, partial->pclu), + EXT4_MB_C2B(sbi, partial->pclu), sbi->s_cluster_ratio, flags); if (flags & EXT4_FREE_BLOCKS_RERESERVE_CLUSTER) ext4_rereserve_cluster(inode, partial->lblk); @@ -2892,7 +2892,7 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, */ if (sbi->s_cluster_ratio > 1) { pblk = ext4_ext_pblock(ex) + end - ee_block + 1; - partial.pclu = EXT4_B2C(sbi, pblk); + partial.pclu = EXT4_MB_B2C(sbi, pblk); partial.state = nofree; } @@ -2926,7 +2926,7 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, if (err < 0) goto out; if (pblk) { - partial.pclu = EXT4_B2C(sbi, pblk); + partial.pclu = EXT4_MB_B2C(sbi, pblk); partial.state = nofree; } } @@ -3045,7 +3045,7 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, if (ext4_is_pending(inode, partial.lblk)) flags |= EXT4_FREE_BLOCKS_RERESERVE_CLUSTER; ext4_free_blocks(handle, inode, NULL, - EXT4_C2B(sbi, partial.pclu), + EXT4_MB_C2B(sbi, partial.pclu), sbi->s_cluster_ratio, flags); if (flags & EXT4_FREE_BLOCKS_RERESERVE_CLUSTER) ext4_rereserve_cluster(inode, partial.lblk); diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 56d50fd3310b..7c8b5ceff98a 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -6747,7 +6747,7 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode, * blocks at the beginning or the end unless we are explicitly * requested to avoid doing so. */ - overflow = EXT4_PBLK_COFF(sbi, block); + overflow = EXT4_MB_PBLK_COFF(sbi, block); if (overflow) { if (flags & EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER) { overflow = sbi->s_cluster_ratio - overflow; @@ -6763,7 +6763,7 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode, /* The range changed so it's no longer validated */ flags &= ~EXT4_FREE_BLOCKS_VALIDATED; } - overflow = EXT4_LBLK_COFF(sbi, count); + overflow = EXT4_MB_LBLK_COFF(sbi, count); if (overflow) { if (flags & EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER) { if (count > overflow)