diff options
Diffstat (limited to 'drivers/block/drbd/drbd_nl.c')
-rw-r--r-- | drivers/block/drbd/drbd_nl.c | 52 |
1 files changed, 30 insertions, 22 deletions
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index 6429d2b19e06..632e3245d1bb 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c | |||
@@ -510,7 +510,7 @@ void drbd_resume_io(struct drbd_conf *mdev) | |||
510 | * Returns 0 on success, negative return values indicate errors. | 510 | * Returns 0 on success, negative return values indicate errors. |
511 | * You should call drbd_md_sync() after calling this function. | 511 | * You should call drbd_md_sync() after calling this function. |
512 | */ | 512 | */ |
513 | enum determine_dev_size drbd_determin_dev_size(struct drbd_conf *mdev, int force) __must_hold(local) | 513 | enum determine_dev_size drbd_determin_dev_size(struct drbd_conf *mdev, enum dds_flags flags) __must_hold(local) |
514 | { | 514 | { |
515 | sector_t prev_first_sect, prev_size; /* previous meta location */ | 515 | sector_t prev_first_sect, prev_size; /* previous meta location */ |
516 | sector_t la_size; | 516 | sector_t la_size; |
@@ -541,12 +541,12 @@ enum determine_dev_size drbd_determin_dev_size(struct drbd_conf *mdev, int force | |||
541 | /* TODO: should only be some assert here, not (re)init... */ | 541 | /* TODO: should only be some assert here, not (re)init... */ |
542 | drbd_md_set_sector_offsets(mdev, mdev->ldev); | 542 | drbd_md_set_sector_offsets(mdev, mdev->ldev); |
543 | 543 | ||
544 | size = drbd_new_dev_size(mdev, mdev->ldev, force); | 544 | size = drbd_new_dev_size(mdev, mdev->ldev, flags & DDSF_FORCED); |
545 | 545 | ||
546 | if (drbd_get_capacity(mdev->this_bdev) != size || | 546 | if (drbd_get_capacity(mdev->this_bdev) != size || |
547 | drbd_bm_capacity(mdev) != size) { | 547 | drbd_bm_capacity(mdev) != size) { |
548 | int err; | 548 | int err; |
549 | err = drbd_bm_resize(mdev, size); | 549 | err = drbd_bm_resize(mdev, size, !(flags & DDSF_NO_RESYNC)); |
550 | if (unlikely(err)) { | 550 | if (unlikely(err)) { |
551 | /* currently there is only one error: ENOMEM! */ | 551 | /* currently there is only one error: ENOMEM! */ |
552 | size = drbd_bm_capacity(mdev)>>1; | 552 | size = drbd_bm_capacity(mdev)>>1; |
@@ -704,9 +704,6 @@ void drbd_setup_queue_param(struct drbd_conf *mdev, unsigned int max_seg_s) __mu | |||
704 | struct request_queue * const b = mdev->ldev->backing_bdev->bd_disk->queue; | 704 | struct request_queue * const b = mdev->ldev->backing_bdev->bd_disk->queue; |
705 | int max_segments = mdev->ldev->dc.max_bio_bvecs; | 705 | int max_segments = mdev->ldev->dc.max_bio_bvecs; |
706 | 706 | ||
707 | if (b->merge_bvec_fn && !mdev->ldev->dc.use_bmbv) | ||
708 | max_seg_s = PAGE_SIZE; | ||
709 | |||
710 | max_seg_s = min(queue_max_sectors(b) * queue_logical_block_size(b), max_seg_s); | 707 | max_seg_s = min(queue_max_sectors(b) * queue_logical_block_size(b), max_seg_s); |
711 | 708 | ||
712 | blk_queue_max_hw_sectors(q, max_seg_s >> 9); | 709 | blk_queue_max_hw_sectors(q, max_seg_s >> 9); |
@@ -1199,13 +1196,12 @@ static int drbd_nl_net_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, | |||
1199 | } | 1196 | } |
1200 | 1197 | ||
1201 | /* allocation not in the IO path, cqueue thread context */ | 1198 | /* allocation not in the IO path, cqueue thread context */ |
1202 | new_conf = kmalloc(sizeof(struct net_conf), GFP_KERNEL); | 1199 | new_conf = kzalloc(sizeof(struct net_conf), GFP_KERNEL); |
1203 | if (!new_conf) { | 1200 | if (!new_conf) { |
1204 | retcode = ERR_NOMEM; | 1201 | retcode = ERR_NOMEM; |
1205 | goto fail; | 1202 | goto fail; |
1206 | } | 1203 | } |
1207 | 1204 | ||
1208 | memset(new_conf, 0, sizeof(struct net_conf)); | ||
1209 | new_conf->timeout = DRBD_TIMEOUT_DEF; | 1205 | new_conf->timeout = DRBD_TIMEOUT_DEF; |
1210 | new_conf->try_connect_int = DRBD_CONNECT_INT_DEF; | 1206 | new_conf->try_connect_int = DRBD_CONNECT_INT_DEF; |
1211 | new_conf->ping_int = DRBD_PING_INT_DEF; | 1207 | new_conf->ping_int = DRBD_PING_INT_DEF; |
@@ -1477,8 +1473,8 @@ static int drbd_nl_resize(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, | |||
1477 | { | 1473 | { |
1478 | struct resize rs; | 1474 | struct resize rs; |
1479 | int retcode = NO_ERROR; | 1475 | int retcode = NO_ERROR; |
1480 | int ldsc = 0; /* local disk size changed */ | ||
1481 | enum determine_dev_size dd; | 1476 | enum determine_dev_size dd; |
1477 | enum dds_flags ddsf; | ||
1482 | 1478 | ||
1483 | memset(&rs, 0, sizeof(struct resize)); | 1479 | memset(&rs, 0, sizeof(struct resize)); |
1484 | if (!resize_from_tags(mdev, nlp->tag_list, &rs)) { | 1480 | if (!resize_from_tags(mdev, nlp->tag_list, &rs)) { |
@@ -1502,13 +1498,17 @@ static int drbd_nl_resize(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, | |||
1502 | goto fail; | 1498 | goto fail; |
1503 | } | 1499 | } |
1504 | 1500 | ||
1505 | if (mdev->ldev->known_size != drbd_get_capacity(mdev->ldev->backing_bdev)) { | 1501 | if (rs.no_resync && mdev->agreed_pro_version < 93) { |
1506 | mdev->ldev->known_size = drbd_get_capacity(mdev->ldev->backing_bdev); | 1502 | retcode = ERR_NEED_APV_93; |
1507 | ldsc = 1; | 1503 | goto fail; |
1508 | } | 1504 | } |
1509 | 1505 | ||
1506 | if (mdev->ldev->known_size != drbd_get_capacity(mdev->ldev->backing_bdev)) | ||
1507 | mdev->ldev->known_size = drbd_get_capacity(mdev->ldev->backing_bdev); | ||
1508 | |||
1510 | mdev->ldev->dc.disk_size = (sector_t)rs.resize_size; | 1509 | mdev->ldev->dc.disk_size = (sector_t)rs.resize_size; |
1511 | dd = drbd_determin_dev_size(mdev, rs.resize_force); | 1510 | ddsf = (rs.resize_force ? DDSF_FORCED : 0) | (rs.no_resync ? DDSF_NO_RESYNC : 0); |
1511 | dd = drbd_determin_dev_size(mdev, ddsf); | ||
1512 | drbd_md_sync(mdev); | 1512 | drbd_md_sync(mdev); |
1513 | put_ldev(mdev); | 1513 | put_ldev(mdev); |
1514 | if (dd == dev_size_error) { | 1514 | if (dd == dev_size_error) { |
@@ -1516,12 +1516,12 @@ static int drbd_nl_resize(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, | |||
1516 | goto fail; | 1516 | goto fail; |
1517 | } | 1517 | } |
1518 | 1518 | ||
1519 | if (mdev->state.conn == C_CONNECTED && (dd != unchanged || ldsc)) { | 1519 | if (mdev->state.conn == C_CONNECTED) { |
1520 | if (dd == grew) | 1520 | if (dd == grew) |
1521 | set_bit(RESIZE_PENDING, &mdev->flags); | 1521 | set_bit(RESIZE_PENDING, &mdev->flags); |
1522 | 1522 | ||
1523 | drbd_send_uuids(mdev); | 1523 | drbd_send_uuids(mdev); |
1524 | drbd_send_sizes(mdev, 1); | 1524 | drbd_send_sizes(mdev, 1, ddsf); |
1525 | } | 1525 | } |
1526 | 1526 | ||
1527 | fail: | 1527 | fail: |
@@ -1551,6 +1551,10 @@ static int drbd_nl_syncer_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *n | |||
1551 | sc.rate = DRBD_RATE_DEF; | 1551 | sc.rate = DRBD_RATE_DEF; |
1552 | sc.after = DRBD_AFTER_DEF; | 1552 | sc.after = DRBD_AFTER_DEF; |
1553 | sc.al_extents = DRBD_AL_EXTENTS_DEF; | 1553 | sc.al_extents = DRBD_AL_EXTENTS_DEF; |
1554 | sc.dp_volume = DRBD_DP_VOLUME_DEF; | ||
1555 | sc.dp_interval = DRBD_DP_INTERVAL_DEF; | ||
1556 | sc.throttle_th = DRBD_RS_THROTTLE_TH_DEF; | ||
1557 | sc.hold_off_th = DRBD_RS_HOLD_OFF_TH_DEF; | ||
1554 | } else | 1558 | } else |
1555 | memcpy(&sc, &mdev->sync_conf, sizeof(struct syncer_conf)); | 1559 | memcpy(&sc, &mdev->sync_conf, sizeof(struct syncer_conf)); |
1556 | 1560 | ||
@@ -2207,9 +2211,9 @@ void drbd_bcast_ee(struct drbd_conf *mdev, | |||
2207 | { | 2211 | { |
2208 | struct cn_msg *cn_reply; | 2212 | struct cn_msg *cn_reply; |
2209 | struct drbd_nl_cfg_reply *reply; | 2213 | struct drbd_nl_cfg_reply *reply; |
2210 | struct bio_vec *bvec; | ||
2211 | unsigned short *tl; | 2214 | unsigned short *tl; |
2212 | int i; | 2215 | struct page *page; |
2216 | unsigned len; | ||
2213 | 2217 | ||
2214 | if (!e) | 2218 | if (!e) |
2215 | return; | 2219 | return; |
@@ -2247,11 +2251,15 @@ void drbd_bcast_ee(struct drbd_conf *mdev, | |||
2247 | put_unaligned(T_ee_data, tl++); | 2251 | put_unaligned(T_ee_data, tl++); |
2248 | put_unaligned(e->size, tl++); | 2252 | put_unaligned(e->size, tl++); |
2249 | 2253 | ||
2250 | __bio_for_each_segment(bvec, e->private_bio, i, 0) { | 2254 | len = e->size; |
2251 | void *d = kmap(bvec->bv_page); | 2255 | page = e->pages; |
2252 | memcpy(tl, d + bvec->bv_offset, bvec->bv_len); | 2256 | page_chain_for_each(page) { |
2253 | kunmap(bvec->bv_page); | 2257 | void *d = kmap_atomic(page, KM_USER0); |
2254 | tl=(unsigned short*)((char*)tl + bvec->bv_len); | 2258 | unsigned l = min_t(unsigned, len, PAGE_SIZE); |
2259 | memcpy(tl, d, l); | ||
2260 | kunmap_atomic(d, KM_USER0); | ||
2261 | tl = (unsigned short*)((char*)tl + l); | ||
2262 | len -= l; | ||
2255 | } | 2263 | } |
2256 | put_unaligned(TT_END, tl++); /* Close the tag list */ | 2264 | put_unaligned(TT_END, tl++); /* Close the tag list */ |
2257 | 2265 | ||