Commit 1816a2b4 authored by Lars Ellenberg's avatar Lars Ellenberg Committed by Philipp Reisner

drbd: properly use max_hw_sectors to limit the our bio size

To ease tracking of bios in some hash tables, we want it to
not cross certain boundaries (128k, used to be 32k).
We limit the maximum bio size using queue parameters.

Historically some defines and variables we use there have been named
max_segment_size, which was misguided. Rename them to max_bio_size,
and use [blk_]queue_max_hw_sectors where appropriate.
Signed-off-by: default avatarPhilipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: default avatarLars Ellenberg <lars.ellenberg@linbit.com>
parent 3129b1b9
...@@ -952,7 +952,7 @@ void __drbd_set_in_sync(struct drbd_conf *mdev, sector_t sector, int size, ...@@ -952,7 +952,7 @@ void __drbd_set_in_sync(struct drbd_conf *mdev, sector_t sector, int size,
int wake_up = 0; int wake_up = 0;
unsigned long flags; unsigned long flags;
if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_SEGMENT_SIZE) { if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_BIO_SIZE) {
dev_err(DEV, "drbd_set_in_sync: sector=%llus size=%d nonsense!\n", dev_err(DEV, "drbd_set_in_sync: sector=%llus size=%d nonsense!\n",
(unsigned long long)sector, size); (unsigned long long)sector, size);
return; return;
...@@ -1002,7 +1002,7 @@ void __drbd_set_in_sync(struct drbd_conf *mdev, sector_t sector, int size, ...@@ -1002,7 +1002,7 @@ void __drbd_set_in_sync(struct drbd_conf *mdev, sector_t sector, int size,
/* /*
* this is intended to set one request worth of data out of sync. * this is intended to set one request worth of data out of sync.
* affects at least 1 bit, * affects at least 1 bit,
* and at most 1+DRBD_MAX_SEGMENT_SIZE/BM_BLOCK_SIZE bits. * and at most 1+DRBD_MAX_BIO_SIZE/BM_BLOCK_SIZE bits.
* *
* called by tl_clear and drbd_send_dblock (==drbd_make_request). * called by tl_clear and drbd_send_dblock (==drbd_make_request).
* so this can be _any_ process. * so this can be _any_ process.
...@@ -1015,7 +1015,7 @@ void __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector, int size, ...@@ -1015,7 +1015,7 @@ void __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector, int size,
unsigned int enr, count; unsigned int enr, count;
struct lc_element *e; struct lc_element *e;
if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_SEGMENT_SIZE) { if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_BIO_SIZE) {
dev_err(DEV, "sector: %llus, size: %d\n", dev_err(DEV, "sector: %llus, size: %d\n",
(unsigned long long)sector, size); (unsigned long long)sector, size);
return; return;
...@@ -1387,7 +1387,7 @@ void drbd_rs_failed_io(struct drbd_conf *mdev, sector_t sector, int size) ...@@ -1387,7 +1387,7 @@ void drbd_rs_failed_io(struct drbd_conf *mdev, sector_t sector, int size)
sector_t esector, nr_sectors; sector_t esector, nr_sectors;
int wake_up = 0; int wake_up = 0;
if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_SEGMENT_SIZE) { if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_BIO_SIZE) {
dev_err(DEV, "drbd_rs_failed_io: sector=%llus size=%d nonsense!\n", dev_err(DEV, "drbd_rs_failed_io: sector=%llus size=%d nonsense!\n",
(unsigned long long)sector, size); (unsigned long long)sector, size);
return; return;
......
...@@ -512,7 +512,7 @@ struct p_sizes { ...@@ -512,7 +512,7 @@ struct p_sizes {
u64 d_size; /* size of disk */ u64 d_size; /* size of disk */
u64 u_size; /* user requested size */ u64 u_size; /* user requested size */
u64 c_size; /* current exported size */ u64 c_size; /* current exported size */
u32 max_segment_size; /* Maximal size of a BIO */ u32 max_bio_size; /* Maximal size of a BIO */
u16 queue_order_type; /* not yet implemented in DRBD*/ u16 queue_order_type; /* not yet implemented in DRBD*/
u16 dds_flags; /* use enum dds_flags here. */ u16 dds_flags; /* use enum dds_flags here. */
} __packed; } __packed;
...@@ -1398,7 +1398,7 @@ struct bm_extent { ...@@ -1398,7 +1398,7 @@ struct bm_extent {
* With a value of 8 all IO in one 128K block make it to the same slot of the * With a value of 8 all IO in one 128K block make it to the same slot of the
* hash table. */ * hash table. */
#define HT_SHIFT 8 #define HT_SHIFT 8
#define DRBD_MAX_SEGMENT_SIZE (1U<<(9+HT_SHIFT)) #define DRBD_MAX_BIO_SIZE (1U<<(9+HT_SHIFT))
#define DRBD_MAX_SIZE_H80_PACKET (1 << 15) /* The old header only allows packets up to 32Kib data */ #define DRBD_MAX_SIZE_H80_PACKET (1 << 15) /* The old header only allows packets up to 32Kib data */
......
...@@ -1924,7 +1924,7 @@ int drbd_send_sizes(struct drbd_conf *mdev, int trigger_reply, enum dds_flags fl ...@@ -1924,7 +1924,7 @@ int drbd_send_sizes(struct drbd_conf *mdev, int trigger_reply, enum dds_flags fl
p.d_size = cpu_to_be64(d_size); p.d_size = cpu_to_be64(d_size);
p.u_size = cpu_to_be64(u_size); p.u_size = cpu_to_be64(u_size);
p.c_size = cpu_to_be64(trigger_reply ? 0 : drbd_get_capacity(mdev->this_bdev)); p.c_size = cpu_to_be64(trigger_reply ? 0 : drbd_get_capacity(mdev->this_bdev));
p.max_segment_size = cpu_to_be32(queue_max_segment_size(mdev->rq_queue)); p.max_bio_size = cpu_to_be32(queue_max_hw_sectors(mdev->rq_queue) << 9);
p.queue_order_type = cpu_to_be16(q_order_type); p.queue_order_type = cpu_to_be16(q_order_type);
p.dds_flags = cpu_to_be16(flags); p.dds_flags = cpu_to_be16(flags);
...@@ -2952,7 +2952,7 @@ static void drbd_destroy_mempools(void) ...@@ -2952,7 +2952,7 @@ static void drbd_destroy_mempools(void)
static int drbd_create_mempools(void) static int drbd_create_mempools(void)
{ {
struct page *page; struct page *page;
const int number = (DRBD_MAX_SEGMENT_SIZE/PAGE_SIZE) * minor_count; const int number = (DRBD_MAX_BIO_SIZE/PAGE_SIZE) * minor_count;
int i; int i;
/* prepare our caches and mempools */ /* prepare our caches and mempools */
...@@ -3218,7 +3218,7 @@ struct drbd_conf *drbd_new_device(unsigned int minor) ...@@ -3218,7 +3218,7 @@ struct drbd_conf *drbd_new_device(unsigned int minor)
q->backing_dev_info.congested_data = mdev; q->backing_dev_info.congested_data = mdev;
blk_queue_make_request(q, drbd_make_request_26); blk_queue_make_request(q, drbd_make_request_26);
blk_queue_max_segment_size(q, DRBD_MAX_SEGMENT_SIZE); blk_queue_max_hw_sectors(q, DRBD_MAX_BIO_SIZE >> 9);
blk_queue_bounce_limit(q, BLK_BOUNCE_ANY); blk_queue_bounce_limit(q, BLK_BOUNCE_ANY);
blk_queue_merge_bvec(q, drbd_merge_bvec); blk_queue_merge_bvec(q, drbd_merge_bvec);
q->queue_lock = &mdev->req_lock; q->queue_lock = &mdev->req_lock;
......
...@@ -765,22 +765,21 @@ static int drbd_check_al_size(struct drbd_conf *mdev) ...@@ -765,22 +765,21 @@ static int drbd_check_al_size(struct drbd_conf *mdev)
return 0; return 0;
} }
void drbd_setup_queue_param(struct drbd_conf *mdev, unsigned int max_seg_s) __must_hold(local) void drbd_setup_queue_param(struct drbd_conf *mdev, unsigned int max_bio_size) __must_hold(local)
{ {
struct request_queue * const q = mdev->rq_queue; struct request_queue * const q = mdev->rq_queue;
struct request_queue * const b = mdev->ldev->backing_bdev->bd_disk->queue; struct request_queue * const b = mdev->ldev->backing_bdev->bd_disk->queue;
int max_segments = mdev->ldev->dc.max_bio_bvecs; int max_segments = mdev->ldev->dc.max_bio_bvecs;
int max_hw_sectors = min(queue_max_hw_sectors(b), max_bio_size >> 9);
max_seg_s = min(queue_max_sectors(b) * queue_logical_block_size(b), max_seg_s);
blk_queue_max_hw_sectors(q, max_seg_s >> 9);
blk_queue_max_segments(q, max_segments ? max_segments : BLK_MAX_SEGMENTS);
blk_queue_max_segment_size(q, max_seg_s);
blk_queue_logical_block_size(q, 512); blk_queue_logical_block_size(q, 512);
blk_queue_segment_boundary(q, PAGE_SIZE-1); blk_queue_max_hw_sectors(q, max_hw_sectors);
blk_stack_limits(&q->limits, &b->limits, 0); /* This is the workaround for "bio would need to, but cannot, be split" */
blk_queue_max_segments(q, max_segments ? max_segments : BLK_MAX_SEGMENTS);
blk_queue_segment_boundary(q, PAGE_CACHE_SIZE-1);
blk_queue_stack_limits(q, b);
dev_info(DEV, "max_segment_size ( = BIO size ) = %u\n", queue_max_segment_size(q)); dev_info(DEV, "max BIO size = %u\n", queue_max_hw_sectors(q) << 9);
if (q->backing_dev_info.ra_pages != b->backing_dev_info.ra_pages) { if (q->backing_dev_info.ra_pages != b->backing_dev_info.ra_pages) {
dev_info(DEV, "Adjusting my ra_pages to backing device's (%lu -> %lu)\n", dev_info(DEV, "Adjusting my ra_pages to backing device's (%lu -> %lu)\n",
...@@ -858,7 +857,7 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp ...@@ -858,7 +857,7 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
struct block_device *bdev; struct block_device *bdev;
struct lru_cache *resync_lru = NULL; struct lru_cache *resync_lru = NULL;
union drbd_state ns, os; union drbd_state ns, os;
unsigned int max_seg_s; unsigned int max_bio_size;
int rv; int rv;
int cp_discovered = 0; int cp_discovered = 0;
int logical_block_size; int logical_block_size;
...@@ -1109,20 +1108,20 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp ...@@ -1109,20 +1108,20 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
mdev->read_cnt = 0; mdev->read_cnt = 0;
mdev->writ_cnt = 0; mdev->writ_cnt = 0;
max_seg_s = DRBD_MAX_SEGMENT_SIZE; max_bio_size = DRBD_MAX_BIO_SIZE;
if (mdev->state.conn == C_CONNECTED) { if (mdev->state.conn == C_CONNECTED) {
/* We are Primary, Connected, and now attach a new local /* We are Primary, Connected, and now attach a new local
* backing store. We must not increase the user visible maximum * backing store. We must not increase the user visible maximum
* bio size on this device to something the peer may not be * bio size on this device to something the peer may not be
* able to handle. */ * able to handle. */
if (mdev->agreed_pro_version < 94) if (mdev->agreed_pro_version < 94)
max_seg_s = queue_max_segment_size(mdev->rq_queue); max_bio_size = queue_max_hw_sectors(mdev->rq_queue) << 9;
else if (mdev->agreed_pro_version == 94) else if (mdev->agreed_pro_version == 94)
max_seg_s = DRBD_MAX_SIZE_H80_PACKET; max_bio_size = DRBD_MAX_SIZE_H80_PACKET;
/* else: drbd 8.3.9 and later, stay with default */ /* else: drbd 8.3.9 and later, stay with default */
} }
drbd_setup_queue_param(mdev, max_seg_s); drbd_setup_queue_param(mdev, max_bio_size);
/* If I am currently not R_PRIMARY, /* If I am currently not R_PRIMARY,
* but meta data primary indicator is set, * but meta data primary indicator is set,
......
...@@ -277,7 +277,7 @@ static void drbd_pp_free(struct drbd_conf *mdev, struct page *page, int is_net) ...@@ -277,7 +277,7 @@ static void drbd_pp_free(struct drbd_conf *mdev, struct page *page, int is_net)
atomic_t *a = is_net ? &mdev->pp_in_use_by_net : &mdev->pp_in_use; atomic_t *a = is_net ? &mdev->pp_in_use_by_net : &mdev->pp_in_use;
int i; int i;
if (drbd_pp_vacant > (DRBD_MAX_SEGMENT_SIZE/PAGE_SIZE)*minor_count) if (drbd_pp_vacant > (DRBD_MAX_BIO_SIZE/PAGE_SIZE)*minor_count)
i = page_chain_free(page); i = page_chain_free(page);
else { else {
struct page *tmp; struct page *tmp;
...@@ -1240,7 +1240,7 @@ read_in_block(struct drbd_conf *mdev, u64 id, sector_t sector, int data_size) __ ...@@ -1240,7 +1240,7 @@ read_in_block(struct drbd_conf *mdev, u64 id, sector_t sector, int data_size) __
data_size -= dgs; data_size -= dgs;
ERR_IF(data_size & 0x1ff) return NULL; ERR_IF(data_size & 0x1ff) return NULL;
ERR_IF(data_size > DRBD_MAX_SEGMENT_SIZE) return NULL; ERR_IF(data_size > DRBD_MAX_BIO_SIZE) return NULL;
/* even though we trust out peer, /* even though we trust out peer,
* we sometimes have to double check. */ * we sometimes have to double check. */
...@@ -1917,7 +1917,7 @@ static int receive_DataRequest(struct drbd_conf *mdev, enum drbd_packets cmd, un ...@@ -1917,7 +1917,7 @@ static int receive_DataRequest(struct drbd_conf *mdev, enum drbd_packets cmd, un
sector = be64_to_cpu(p->sector); sector = be64_to_cpu(p->sector);
size = be32_to_cpu(p->blksize); size = be32_to_cpu(p->blksize);
if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_SEGMENT_SIZE) { if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_BIO_SIZE) {
dev_err(DEV, "%s:%d: sector: %llus, size: %u\n", __FILE__, __LINE__, dev_err(DEV, "%s:%d: sector: %llus, size: %u\n", __FILE__, __LINE__,
(unsigned long long)sector, size); (unsigned long long)sector, size);
return FALSE; return FALSE;
...@@ -2897,7 +2897,7 @@ static int receive_sizes(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned ...@@ -2897,7 +2897,7 @@ static int receive_sizes(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned
{ {
struct p_sizes *p = &mdev->data.rbuf.sizes; struct p_sizes *p = &mdev->data.rbuf.sizes;
enum determine_dev_size dd = unchanged; enum determine_dev_size dd = unchanged;
unsigned int max_seg_s; unsigned int max_bio_size;
sector_t p_size, p_usize, my_usize; sector_t p_size, p_usize, my_usize;
int ldsc = 0; /* local disk size changed */ int ldsc = 0; /* local disk size changed */
enum dds_flags ddsf; enum dds_flags ddsf;
...@@ -2970,14 +2970,14 @@ static int receive_sizes(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned ...@@ -2970,14 +2970,14 @@ static int receive_sizes(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned
} }
if (mdev->agreed_pro_version < 94) if (mdev->agreed_pro_version < 94)
max_seg_s = be32_to_cpu(p->max_segment_size); max_bio_size = be32_to_cpu(p->max_bio_size);
else if (mdev->agreed_pro_version == 94) else if (mdev->agreed_pro_version == 94)
max_seg_s = DRBD_MAX_SIZE_H80_PACKET; max_bio_size = DRBD_MAX_SIZE_H80_PACKET;
else /* drbd 8.3.8 onwards */ else /* drbd 8.3.8 onwards */
max_seg_s = DRBD_MAX_SEGMENT_SIZE; max_bio_size = DRBD_MAX_BIO_SIZE;
if (max_seg_s != queue_max_segment_size(mdev->rq_queue)) if (max_bio_size != queue_max_hw_sectors(mdev->rq_queue) << 9)
drbd_setup_queue_param(mdev, max_seg_s); drbd_setup_queue_param(mdev, max_bio_size);
drbd_setup_order_type(mdev, be16_to_cpu(p->queue_order_type)); drbd_setup_order_type(mdev, be16_to_cpu(p->queue_order_type));
put_ldev(mdev); put_ldev(mdev);
......
...@@ -1047,7 +1047,7 @@ int drbd_make_request_26(struct request_queue *q, struct bio *bio) ...@@ -1047,7 +1047,7 @@ int drbd_make_request_26(struct request_queue *q, struct bio *bio)
/* can this bio be split generically? /* can this bio be split generically?
* Maybe add our own split-arbitrary-bios function. */ * Maybe add our own split-arbitrary-bios function. */
if (bio->bi_vcnt != 1 || bio->bi_idx != 0 || bio->bi_size > DRBD_MAX_SEGMENT_SIZE) { if (bio->bi_vcnt != 1 || bio->bi_idx != 0 || bio->bi_size > DRBD_MAX_BIO_SIZE) {
/* rather error out here than BUG in bio_split */ /* rather error out here than BUG in bio_split */
dev_err(DEV, "bio would need to, but cannot, be split: " dev_err(DEV, "bio would need to, but cannot, be split: "
"(vcnt=%u,idx=%u,size=%u,sector=%llu)\n", "(vcnt=%u,idx=%u,size=%u,sector=%llu)\n",
...@@ -1098,7 +1098,7 @@ int drbd_make_request_26(struct request_queue *q, struct bio *bio) ...@@ -1098,7 +1098,7 @@ int drbd_make_request_26(struct request_queue *q, struct bio *bio)
} }
/* This is called by bio_add_page(). With this function we reduce /* This is called by bio_add_page(). With this function we reduce
* the number of BIOs that span over multiple DRBD_MAX_SEGMENT_SIZEs * the number of BIOs that span over multiple DRBD_MAX_BIO_SIZEs
* units (was AL_EXTENTs). * units (was AL_EXTENTs).
* *
* we do the calculation within the lower 32bit of the byte offsets, * we do the calculation within the lower 32bit of the byte offsets,
...@@ -1118,8 +1118,8 @@ int drbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bvm, struct ...@@ -1118,8 +1118,8 @@ int drbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bvm, struct
unsigned int bio_size = bvm->bi_size; unsigned int bio_size = bvm->bi_size;
int limit, backing_limit; int limit, backing_limit;
limit = DRBD_MAX_SEGMENT_SIZE limit = DRBD_MAX_BIO_SIZE
- ((bio_offset & (DRBD_MAX_SEGMENT_SIZE-1)) + bio_size); - ((bio_offset & (DRBD_MAX_BIO_SIZE-1)) + bio_size);
if (limit < 0) if (limit < 0)
limit = 0; limit = 0;
if (bio_size == 0) { if (bio_size == 0) {
......
...@@ -524,7 +524,7 @@ int w_make_resync_request(struct drbd_conf *mdev, ...@@ -524,7 +524,7 @@ int w_make_resync_request(struct drbd_conf *mdev,
unsigned long bit; unsigned long bit;
sector_t sector; sector_t sector;
const sector_t capacity = drbd_get_capacity(mdev->this_bdev); const sector_t capacity = drbd_get_capacity(mdev->this_bdev);
int max_segment_size; int max_bio_size;
int number, rollback_i, size; int number, rollback_i, size;
int align, queued, sndbuf; int align, queued, sndbuf;
int i = 0; int i = 0;
...@@ -559,9 +559,9 @@ int w_make_resync_request(struct drbd_conf *mdev, ...@@ -559,9 +559,9 @@ int w_make_resync_request(struct drbd_conf *mdev,
/* starting with drbd 8.3.8, we can handle multi-bio EEs, /* starting with drbd 8.3.8, we can handle multi-bio EEs,
* if it should be necessary */ * if it should be necessary */
max_segment_size = max_bio_size =
mdev->agreed_pro_version < 94 ? queue_max_segment_size(mdev->rq_queue) : mdev->agreed_pro_version < 94 ? queue_max_hw_sectors(mdev->rq_queue) << 9 :
mdev->agreed_pro_version < 95 ? DRBD_MAX_SIZE_H80_PACKET : DRBD_MAX_SEGMENT_SIZE; mdev->agreed_pro_version < 95 ? DRBD_MAX_SIZE_H80_PACKET : DRBD_MAX_BIO_SIZE;
number = drbd_rs_number_requests(mdev); number = drbd_rs_number_requests(mdev);
if (number == 0) if (number == 0)
...@@ -605,7 +605,7 @@ int w_make_resync_request(struct drbd_conf *mdev, ...@@ -605,7 +605,7 @@ int w_make_resync_request(struct drbd_conf *mdev,
goto next_sector; goto next_sector;
} }
#if DRBD_MAX_SEGMENT_SIZE > BM_BLOCK_SIZE #if DRBD_MAX_BIO_SIZE > BM_BLOCK_SIZE
/* try to find some adjacent bits. /* try to find some adjacent bits.
* we stop if we have already the maximum req size. * we stop if we have already the maximum req size.
* *
...@@ -615,7 +615,7 @@ int w_make_resync_request(struct drbd_conf *mdev, ...@@ -615,7 +615,7 @@ int w_make_resync_request(struct drbd_conf *mdev,
align = 1; align = 1;
rollback_i = i; rollback_i = i;
for (;;) { for (;;) {
if (size + BM_BLOCK_SIZE > max_segment_size) if (size + BM_BLOCK_SIZE > max_bio_size)
break; break;
/* Be always aligned */ /* Be always aligned */
......
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