From c3f122a5f188c6e91a6d4c3155ed1fccb1f02592 Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Thu, 17 Nov 2016 15:03:22 -0800 Subject: [PATCH] Fix mkfs buddy initialization mkfs was starting setting free blk bits from 0 instead of from the blkno offset of the first free block. This resulted in the highest order above a used blkno being marked free. Freeing that blkno would set its lowest order blkno. Now that blkno can be allocated from two orders. That, eventually, can lead to blocks being doubly allocated and users trampling on each other. While auditing the code to chase this bug down I also noticed that write_buddy_blocks() was using a min() that makes no sense at all. Here 'blk' is inclusive, the modulo math works on its own. Signed-off-by: Zach Brown --- utils/src/mkfs.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/utils/src/mkfs.c b/utils/src/mkfs.c index c671d08d..7023b409 100644 --- a/utils/src/mkfs.c +++ b/utils/src/mkfs.c @@ -232,8 +232,7 @@ static int write_buddy_blocks(int fd, struct scoutfs_super_block *super, last = SCOUTFS_BUDDY_ORDER0_BITS - 1; } else { first = 0; - last = min(blk % SCOUTFS_BUDDY_ORDER0_BITS, - SCOUTFS_BUDDY_ORDER0_BITS); + last = blk % SCOUTFS_BUDDY_ORDER0_BITS; } /* write the leaf block */ @@ -396,7 +395,9 @@ static int write_new_fs(char *path, int fd) super->free_blocks = cpu_to_le64(total_blocks - blkno); /* write left-most buddy block and all full parents, not root */ - ret = write_buddy_blocks(fd, super, &binf, buf, 0, 1, &free_orders); + ret = write_buddy_blocks(fd, super, &binf, buf, + blkno - first_blkno(super), + 1, &free_orders); if (ret) goto out;