aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/drbd/drbd_nl.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/block/drbd/drbd_nl.c')
-rw-r--r--drivers/block/drbd/drbd_nl.c52
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 */
513enum determine_dev_size drbd_determin_dev_size(struct drbd_conf *mdev, int force) __must_hold(local) 513enum 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