On Tue, Aug 29 2017, Zhilong Liu wrote: > Hi, Neil; > Thanks for your pointing and sorry for the incorrect dmesg for last > mail. > > Here update the pure steps and paste the dmesg. > > ENV: > OS: 4.13-rc7 upstream > linux-apta:~/mdadm-test # df -T /mnt/ > Filesystem Type 1K-blocks Used Available Use% Mounted on > /dev/sda2 ext4 44248848 24416952 18778472 57% / > > Reproduce: 100% > > Steps: > linux-apta:~/mdadm-test # ./mdadm -CR /dev/md0 -l1 -b /mnt/3 -n2 -x1 > /dev/loop[0-2] --force > mdadm: Note: this array has metadata at the start and > may not be suitable as a boot device. If you plan to > store '/boot' on this device please ensure that > your boot-loader understands md/v1.x metadata, or use > --metadata=0.90 > mdadm: Defaulting to version 1.2 metadata > mdadm: array /dev/md0 started. > linux-apta:~/mdadm-test # cat /proc/mdstat > Personalities : [raid1] > md0 : active raid1 loop2[2](S) loop1[1] loop0[0] > 18944 blocks super 1.2 [2/2] [UU] > bitmap: 3/3 pages [12KB], 4KB chunk, file: /mnt/3 > > unused devices: > linux-apta:~/mdadm-test # dmesg -c > [ 181.378209] md/raid1:md0: not clean -- starting background reconstruction > [ 181.378211] md/raid1:md0: active with 2 out of 2 mirrors > [ 181.379354] md0: detected capacity change from 0 to 19398656 > [ 181.379773] md: resync of RAID array md0 > [ 190.396162] md: md0: resync done. > > linux-apta:~/mdadm-test # ./mdadm --grow /dev/md0 --size 128 > Segmentation fault > linux-apta:~/mdadm-test # cat /sys/block/md0/md/component_size > 18944 "here is incorrect also." > linux-apta:~/mdadm-test # dmesg -c > [ 208.027505] ------------[ cut here ]------------ > [ 208.027508] kernel BUG at drivers/md/bitmap.c:298! Thanks. Less confusing now. The problem is that when the bitmap is resized, new pages are allocated to store the on-disk copy, but these are not read from the file, the contents are set from the in-memory bitmap. So read_page() isn't called and particularly bh = alloc_page_buffers(page, 1<i_blkbits, 0); ... attach_page_buffers(page, bh); doesn't happen. Maybe something like this will work. Can you test it? Thanks, NeilBrown diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 40f3cd7eab0f..52fe93fa4598 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -368,12 +368,7 @@ static int read_page(struct file *file, unsigned long index, pr_debug("read bitmap file (%dB @ %llu)\n", (int)PAGE_SIZE, (unsigned long long)index << PAGE_SHIFT); - bh = alloc_page_buffers(page, 1<i_blkbits, 0); - if (!bh) { - ret = -ENOMEM; - goto out; - } - attach_page_buffers(page, bh); + bh = page_buffers(page); block = index << (PAGE_SHIFT - inode->i_blkbits); while (bh) { if (count == 0) @@ -771,12 +766,18 @@ static inline struct page *filemap_get_page(struct bitmap_storage *store, } static int bitmap_storage_alloc(struct bitmap_storage *store, - unsigned long chunks, int with_super, + unsigned long chunks, + struct file *file, + int with_super, int slot_number) { int pnum, offset = 0; unsigned long num_pages; unsigned long bytes; + struct inode *inode = NULL; + + if (file) + inode = file_inode(file); bytes = DIV_ROUND_UP(chunks, 8); if (with_super) @@ -804,12 +805,21 @@ static int bitmap_storage_alloc(struct bitmap_storage *store, } for ( ; pnum < num_pages; pnum++) { - store->filemap[pnum] = alloc_page(GFP_KERNEL|__GFP_ZERO); - if (!store->filemap[pnum]) { + struct page *p = alloc_page(GFP_KERNEL|__GFP_ZERO); + store->filemap[pnum] = p; + if (!p) { store->file_pages = pnum; return -ENOMEM; } - store->filemap[pnum]->index = pnum + offset; + if (inode) { + struct buffer_head *bh; + bh = alloc_page_buffers(p, 1 << inode->i_blkbits, 0); + if (bh) + attach_page_buffers(p, bh); + else + return -ENOMEM; + } + p->index = pnum + offset; } store->file_pages = pnum; @@ -2091,7 +2101,7 @@ int bitmap_resize(struct bitmap *bitmap, sector_t blocks, chunks = DIV_ROUND_UP_SECTOR_T(blocks, 1 << chunkshift); memset(&store, 0, sizeof(store)); if (bitmap->mddev->bitmap_info.offset || bitmap->mddev->bitmap_info.file) - ret = bitmap_storage_alloc(&store, chunks, + ret = bitmap_storage_alloc(&store, chunks, bitmap->mddev->bitmap_info.file, !bitmap->mddev->bitmap_info.external, mddev_is_clustered(bitmap->mddev) ? bitmap->cluster_slot : 0);