Commit 39ad2bbb authored by Lars Ellenberg's avatar Lars Ellenberg Committed by Philipp Reisner

drbd: fix al-to-on-disk-bitmap for 4k logical_block_size

Up to now, applying the in-core activity-log to the on-disk
bitmap did not care for logical_block_size.

On logical_block_size != 512 byte, this very likely results
in misalligned block access and spurious "io errors".

We now simply always submit aligned whole 4k blocks, fixing this
for logical block sizes of 512, 1024, 2048 and 4096.

For even larger logical block sizes, this won't work.
But I'm not aware of devices with such properties being available.
Signed-off-by: default avatarPhilipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: default avatarLars Ellenberg <lars.ellenberg@linbit.com>
parent 1f552430
......@@ -536,7 +536,9 @@ static void atodb_endio(struct bio *bio, int error)
put_ldev(mdev);
}
/* sector to word */
#define S2W(s) ((s)<<(BM_EXT_SHIFT-BM_BLOCK_SHIFT-LN2_BPL))
/* activity log to on disk bitmap -- prepare bio unless that sector
* is already covered by previously prepared bios */
static int atodb_prepare_unless_covered(struct drbd_conf *mdev,
......@@ -546,13 +548,20 @@ static int atodb_prepare_unless_covered(struct drbd_conf *mdev,
{
struct bio *bio;
struct page *page;
sector_t on_disk_sector = enr + mdev->ldev->md.md_offset
+ mdev->ldev->md.bm_offset;
sector_t on_disk_sector;
unsigned int page_offset = PAGE_SIZE;
int offset;
int i = 0;
int err = -ENOMEM;
/* We always write aligned, full 4k blocks,
* so we can ignore the logical_block_size (for now) */
enr &= ~7U;
on_disk_sector = enr + mdev->ldev->md.md_offset
+ mdev->ldev->md.bm_offset;
D_ASSERT(!(on_disk_sector & 7U));
/* Check if that enr is already covered by an already created bio.
* Caution, bios[] is not NULL terminated,
* but only initialized to all NULL.
......@@ -588,7 +597,7 @@ static int atodb_prepare_unless_covered(struct drbd_conf *mdev,
offset = S2W(enr);
drbd_bm_get_lel(mdev, offset,
min_t(size_t, S2W(1), drbd_bm_words(mdev) - offset),
min_t(size_t, S2W(8), drbd_bm_words(mdev) - offset),
kmap(page) + page_offset);
kunmap(page);
......@@ -597,7 +606,7 @@ static int atodb_prepare_unless_covered(struct drbd_conf *mdev,
bio->bi_bdev = mdev->ldev->md_bdev;
bio->bi_sector = on_disk_sector;
if (bio_add_page(bio, page, MD_SECTOR_SIZE, page_offset) != MD_SECTOR_SIZE)
if (bio_add_page(bio, page, 4096, page_offset) != 4096)
goto out_put_page;
atomic_inc(&wc->count);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment