diff options
Diffstat (limited to 'drivers/block/drbd/drbd_nl.c')
-rw-r--r-- | drivers/block/drbd/drbd_nl.c | 185 |
1 files changed, 143 insertions, 42 deletions
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index 9e3f441e7e84..8cc1e640f485 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c | |||
@@ -417,6 +417,7 @@ static enum drbd_fencing_p highest_fencing_policy(struct drbd_tconn *tconn) | |||
417 | 417 | ||
418 | bool conn_try_outdate_peer(struct drbd_tconn *tconn) | 418 | bool conn_try_outdate_peer(struct drbd_tconn *tconn) |
419 | { | 419 | { |
420 | unsigned int connect_cnt; | ||
420 | union drbd_state mask = { }; | 421 | union drbd_state mask = { }; |
421 | union drbd_state val = { }; | 422 | union drbd_state val = { }; |
422 | enum drbd_fencing_p fp; | 423 | enum drbd_fencing_p fp; |
@@ -428,6 +429,10 @@ bool conn_try_outdate_peer(struct drbd_tconn *tconn) | |||
428 | return false; | 429 | return false; |
429 | } | 430 | } |
430 | 431 | ||
432 | spin_lock_irq(&tconn->req_lock); | ||
433 | connect_cnt = tconn->connect_cnt; | ||
434 | spin_unlock_irq(&tconn->req_lock); | ||
435 | |||
431 | fp = highest_fencing_policy(tconn); | 436 | fp = highest_fencing_policy(tconn); |
432 | switch (fp) { | 437 | switch (fp) { |
433 | case FP_NOT_AVAIL: | 438 | case FP_NOT_AVAIL: |
@@ -492,8 +497,14 @@ bool conn_try_outdate_peer(struct drbd_tconn *tconn) | |||
492 | here, because we might were able to re-establish the connection in the | 497 | here, because we might were able to re-establish the connection in the |
493 | meantime. */ | 498 | meantime. */ |
494 | spin_lock_irq(&tconn->req_lock); | 499 | spin_lock_irq(&tconn->req_lock); |
495 | if (tconn->cstate < C_WF_REPORT_PARAMS && !test_bit(STATE_SENT, &tconn->flags)) | 500 | if (tconn->cstate < C_WF_REPORT_PARAMS && !test_bit(STATE_SENT, &tconn->flags)) { |
496 | _conn_request_state(tconn, mask, val, CS_VERBOSE); | 501 | if (tconn->connect_cnt != connect_cnt) |
502 | /* In case the connection was established and droped | ||
503 | while the fence-peer handler was running, ignore it */ | ||
504 | conn_info(tconn, "Ignoring fence-peer exit code\n"); | ||
505 | else | ||
506 | _conn_request_state(tconn, mask, val, CS_VERBOSE); | ||
507 | } | ||
497 | spin_unlock_irq(&tconn->req_lock); | 508 | spin_unlock_irq(&tconn->req_lock); |
498 | 509 | ||
499 | return conn_highest_pdsk(tconn) <= D_OUTDATED; | 510 | return conn_highest_pdsk(tconn) <= D_OUTDATED; |
@@ -816,15 +827,20 @@ void drbd_resume_io(struct drbd_conf *mdev) | |||
816 | * Returns 0 on success, negative return values indicate errors. | 827 | * Returns 0 on success, negative return values indicate errors. |
817 | * You should call drbd_md_sync() after calling this function. | 828 | * You should call drbd_md_sync() after calling this function. |
818 | */ | 829 | */ |
819 | enum determine_dev_size drbd_determine_dev_size(struct drbd_conf *mdev, enum dds_flags flags) __must_hold(local) | 830 | enum determine_dev_size |
831 | drbd_determine_dev_size(struct drbd_conf *mdev, enum dds_flags flags, struct resize_parms *rs) __must_hold(local) | ||
820 | { | 832 | { |
821 | sector_t prev_first_sect, prev_size; /* previous meta location */ | 833 | sector_t prev_first_sect, prev_size; /* previous meta location */ |
822 | sector_t la_size_sect, u_size; | 834 | sector_t la_size_sect, u_size; |
835 | struct drbd_md *md = &mdev->ldev->md; | ||
836 | u32 prev_al_stripe_size_4k; | ||
837 | u32 prev_al_stripes; | ||
823 | sector_t size; | 838 | sector_t size; |
824 | char ppb[10]; | 839 | char ppb[10]; |
840 | void *buffer; | ||
825 | 841 | ||
826 | int md_moved, la_size_changed; | 842 | int md_moved, la_size_changed; |
827 | enum determine_dev_size rv = unchanged; | 843 | enum determine_dev_size rv = DS_UNCHANGED; |
828 | 844 | ||
829 | /* race: | 845 | /* race: |
830 | * application request passes inc_ap_bio, | 846 | * application request passes inc_ap_bio, |
@@ -836,6 +852,11 @@ enum determine_dev_size drbd_determine_dev_size(struct drbd_conf *mdev, enum dds | |||
836 | * still lock the act_log to not trigger ASSERTs there. | 852 | * still lock the act_log to not trigger ASSERTs there. |
837 | */ | 853 | */ |
838 | drbd_suspend_io(mdev); | 854 | drbd_suspend_io(mdev); |
855 | buffer = drbd_md_get_buffer(mdev); /* Lock meta-data IO */ | ||
856 | if (!buffer) { | ||
857 | drbd_resume_io(mdev); | ||
858 | return DS_ERROR; | ||
859 | } | ||
839 | 860 | ||
840 | /* no wait necessary anymore, actually we could assert that */ | 861 | /* no wait necessary anymore, actually we could assert that */ |
841 | wait_event(mdev->al_wait, lc_try_lock(mdev->act_log)); | 862 | wait_event(mdev->al_wait, lc_try_lock(mdev->act_log)); |
@@ -844,7 +865,17 @@ enum determine_dev_size drbd_determine_dev_size(struct drbd_conf *mdev, enum dds | |||
844 | prev_size = mdev->ldev->md.md_size_sect; | 865 | prev_size = mdev->ldev->md.md_size_sect; |
845 | la_size_sect = mdev->ldev->md.la_size_sect; | 866 | la_size_sect = mdev->ldev->md.la_size_sect; |
846 | 867 | ||
847 | /* TODO: should only be some assert here, not (re)init... */ | 868 | if (rs) { |
869 | /* rs is non NULL if we should change the AL layout only */ | ||
870 | |||
871 | prev_al_stripes = md->al_stripes; | ||
872 | prev_al_stripe_size_4k = md->al_stripe_size_4k; | ||
873 | |||
874 | md->al_stripes = rs->al_stripes; | ||
875 | md->al_stripe_size_4k = rs->al_stripe_size / 4; | ||
876 | md->al_size_4k = (u64)rs->al_stripes * rs->al_stripe_size / 4; | ||
877 | } | ||
878 | |||
848 | drbd_md_set_sector_offsets(mdev, mdev->ldev); | 879 | drbd_md_set_sector_offsets(mdev, mdev->ldev); |
849 | 880 | ||
850 | rcu_read_lock(); | 881 | rcu_read_lock(); |
@@ -852,6 +883,21 @@ enum determine_dev_size drbd_determine_dev_size(struct drbd_conf *mdev, enum dds | |||
852 | rcu_read_unlock(); | 883 | rcu_read_unlock(); |
853 | size = drbd_new_dev_size(mdev, mdev->ldev, u_size, flags & DDSF_FORCED); | 884 | size = drbd_new_dev_size(mdev, mdev->ldev, u_size, flags & DDSF_FORCED); |
854 | 885 | ||
886 | if (size < la_size_sect) { | ||
887 | if (rs && u_size == 0) { | ||
888 | /* Remove "rs &&" later. This check should always be active, but | ||
889 | right now the receiver expects the permissive behavior */ | ||
890 | dev_warn(DEV, "Implicit shrink not allowed. " | ||
891 | "Use --size=%llus for explicit shrink.\n", | ||
892 | (unsigned long long)size); | ||
893 | rv = DS_ERROR_SHRINK; | ||
894 | } | ||
895 | if (u_size > size) | ||
896 | rv = DS_ERROR_SPACE_MD; | ||
897 | if (rv != DS_UNCHANGED) | ||
898 | goto err_out; | ||
899 | } | ||
900 | |||
855 | if (drbd_get_capacity(mdev->this_bdev) != size || | 901 | if (drbd_get_capacity(mdev->this_bdev) != size || |
856 | drbd_bm_capacity(mdev) != size) { | 902 | drbd_bm_capacity(mdev) != size) { |
857 | int err; | 903 | int err; |
@@ -867,7 +913,7 @@ enum determine_dev_size drbd_determine_dev_size(struct drbd_conf *mdev, enum dds | |||
867 | "Leaving size unchanged at size = %lu KB\n", | 913 | "Leaving size unchanged at size = %lu KB\n", |
868 | (unsigned long)size); | 914 | (unsigned long)size); |
869 | } | 915 | } |
870 | rv = dev_size_error; | 916 | rv = DS_ERROR; |
871 | } | 917 | } |
872 | /* racy, see comments above. */ | 918 | /* racy, see comments above. */ |
873 | drbd_set_my_capacity(mdev, size); | 919 | drbd_set_my_capacity(mdev, size); |
@@ -875,38 +921,57 @@ enum determine_dev_size drbd_determine_dev_size(struct drbd_conf *mdev, enum dds | |||
875 | dev_info(DEV, "size = %s (%llu KB)\n", ppsize(ppb, size>>1), | 921 | dev_info(DEV, "size = %s (%llu KB)\n", ppsize(ppb, size>>1), |
876 | (unsigned long long)size>>1); | 922 | (unsigned long long)size>>1); |
877 | } | 923 | } |
878 | if (rv == dev_size_error) | 924 | if (rv <= DS_ERROR) |
879 | goto out; | 925 | goto err_out; |
880 | 926 | ||
881 | la_size_changed = (la_size_sect != mdev->ldev->md.la_size_sect); | 927 | la_size_changed = (la_size_sect != mdev->ldev->md.la_size_sect); |
882 | 928 | ||
883 | md_moved = prev_first_sect != drbd_md_first_sector(mdev->ldev) | 929 | md_moved = prev_first_sect != drbd_md_first_sector(mdev->ldev) |
884 | || prev_size != mdev->ldev->md.md_size_sect; | 930 | || prev_size != mdev->ldev->md.md_size_sect; |
885 | 931 | ||
886 | if (la_size_changed || md_moved) { | 932 | if (la_size_changed || md_moved || rs) { |
887 | int err; | 933 | u32 prev_flags; |
888 | 934 | ||
889 | drbd_al_shrink(mdev); /* All extents inactive. */ | 935 | drbd_al_shrink(mdev); /* All extents inactive. */ |
936 | |||
937 | prev_flags = md->flags; | ||
938 | md->flags &= ~MDF_PRIMARY_IND; | ||
939 | drbd_md_write(mdev, buffer); | ||
940 | |||
890 | dev_info(DEV, "Writing the whole bitmap, %s\n", | 941 | dev_info(DEV, "Writing the whole bitmap, %s\n", |
891 | la_size_changed && md_moved ? "size changed and md moved" : | 942 | la_size_changed && md_moved ? "size changed and md moved" : |
892 | la_size_changed ? "size changed" : "md moved"); | 943 | la_size_changed ? "size changed" : "md moved"); |
893 | /* next line implicitly does drbd_suspend_io()+drbd_resume_io() */ | 944 | /* next line implicitly does drbd_suspend_io()+drbd_resume_io() */ |
894 | err = drbd_bitmap_io(mdev, md_moved ? &drbd_bm_write_all : &drbd_bm_write, | 945 | drbd_bitmap_io(mdev, md_moved ? &drbd_bm_write_all : &drbd_bm_write, |
895 | "size changed", BM_LOCKED_MASK); | 946 | "size changed", BM_LOCKED_MASK); |
896 | if (err) { | 947 | drbd_initialize_al(mdev, buffer); |
897 | rv = dev_size_error; | 948 | |
898 | goto out; | 949 | md->flags = prev_flags; |
899 | } | 950 | drbd_md_write(mdev, buffer); |
900 | drbd_md_mark_dirty(mdev); | 951 | |
952 | if (rs) | ||
953 | dev_info(DEV, "Changed AL layout to al-stripes = %d, al-stripe-size-kB = %d\n", | ||
954 | md->al_stripes, md->al_stripe_size_4k * 4); | ||
901 | } | 955 | } |
902 | 956 | ||
903 | if (size > la_size_sect) | 957 | if (size > la_size_sect) |
904 | rv = grew; | 958 | rv = DS_GREW; |
905 | if (size < la_size_sect) | 959 | if (size < la_size_sect) |
906 | rv = shrunk; | 960 | rv = DS_SHRUNK; |
907 | out: | 961 | |
962 | if (0) { | ||
963 | err_out: | ||
964 | if (rs) { | ||
965 | md->al_stripes = prev_al_stripes; | ||
966 | md->al_stripe_size_4k = prev_al_stripe_size_4k; | ||
967 | md->al_size_4k = (u64)prev_al_stripes * prev_al_stripe_size_4k; | ||
968 | |||
969 | drbd_md_set_sector_offsets(mdev, mdev->ldev); | ||
970 | } | ||
971 | } | ||
908 | lc_unlock(mdev->act_log); | 972 | lc_unlock(mdev->act_log); |
909 | wake_up(&mdev->al_wait); | 973 | wake_up(&mdev->al_wait); |
974 | drbd_md_put_buffer(mdev); | ||
910 | drbd_resume_io(mdev); | 975 | drbd_resume_io(mdev); |
911 | 976 | ||
912 | return rv; | 977 | return rv; |
@@ -1607,11 +1672,11 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info) | |||
1607 | !drbd_md_test_flag(mdev->ldev, MDF_CONNECTED_IND)) | 1672 | !drbd_md_test_flag(mdev->ldev, MDF_CONNECTED_IND)) |
1608 | set_bit(USE_DEGR_WFC_T, &mdev->flags); | 1673 | set_bit(USE_DEGR_WFC_T, &mdev->flags); |
1609 | 1674 | ||
1610 | dd = drbd_determine_dev_size(mdev, 0); | 1675 | dd = drbd_determine_dev_size(mdev, 0, NULL); |
1611 | if (dd == dev_size_error) { | 1676 | if (dd <= DS_ERROR) { |
1612 | retcode = ERR_NOMEM_BITMAP; | 1677 | retcode = ERR_NOMEM_BITMAP; |
1613 | goto force_diskless_dec; | 1678 | goto force_diskless_dec; |
1614 | } else if (dd == grew) | 1679 | } else if (dd == DS_GREW) |
1615 | set_bit(RESYNC_AFTER_NEG, &mdev->flags); | 1680 | set_bit(RESYNC_AFTER_NEG, &mdev->flags); |
1616 | 1681 | ||
1617 | if (drbd_md_test_flag(mdev->ldev, MDF_FULL_SYNC) || | 1682 | if (drbd_md_test_flag(mdev->ldev, MDF_FULL_SYNC) || |
@@ -2305,6 +2370,7 @@ int drbd_adm_resize(struct sk_buff *skb, struct genl_info *info) | |||
2305 | struct drbd_conf *mdev; | 2370 | struct drbd_conf *mdev; |
2306 | enum drbd_ret_code retcode; | 2371 | enum drbd_ret_code retcode; |
2307 | enum determine_dev_size dd; | 2372 | enum determine_dev_size dd; |
2373 | bool change_al_layout = false; | ||
2308 | enum dds_flags ddsf; | 2374 | enum dds_flags ddsf; |
2309 | sector_t u_size; | 2375 | sector_t u_size; |
2310 | int err; | 2376 | int err; |
@@ -2315,31 +2381,33 @@ int drbd_adm_resize(struct sk_buff *skb, struct genl_info *info) | |||
2315 | if (retcode != NO_ERROR) | 2381 | if (retcode != NO_ERROR) |
2316 | goto fail; | 2382 | goto fail; |
2317 | 2383 | ||
2384 | mdev = adm_ctx.mdev; | ||
2385 | if (!get_ldev(mdev)) { | ||
2386 | retcode = ERR_NO_DISK; | ||
2387 | goto fail; | ||
2388 | } | ||
2389 | |||
2318 | memset(&rs, 0, sizeof(struct resize_parms)); | 2390 | memset(&rs, 0, sizeof(struct resize_parms)); |
2391 | rs.al_stripes = mdev->ldev->md.al_stripes; | ||
2392 | rs.al_stripe_size = mdev->ldev->md.al_stripe_size_4k * 4; | ||
2319 | if (info->attrs[DRBD_NLA_RESIZE_PARMS]) { | 2393 | if (info->attrs[DRBD_NLA_RESIZE_PARMS]) { |
2320 | err = resize_parms_from_attrs(&rs, info); | 2394 | err = resize_parms_from_attrs(&rs, info); |
2321 | if (err) { | 2395 | if (err) { |
2322 | retcode = ERR_MANDATORY_TAG; | 2396 | retcode = ERR_MANDATORY_TAG; |
2323 | drbd_msg_put_info(from_attrs_err_to_txt(err)); | 2397 | drbd_msg_put_info(from_attrs_err_to_txt(err)); |
2324 | goto fail; | 2398 | goto fail_ldev; |
2325 | } | 2399 | } |
2326 | } | 2400 | } |
2327 | 2401 | ||
2328 | mdev = adm_ctx.mdev; | ||
2329 | if (mdev->state.conn > C_CONNECTED) { | 2402 | if (mdev->state.conn > C_CONNECTED) { |
2330 | retcode = ERR_RESIZE_RESYNC; | 2403 | retcode = ERR_RESIZE_RESYNC; |
2331 | goto fail; | 2404 | goto fail_ldev; |
2332 | } | 2405 | } |
2333 | 2406 | ||
2334 | if (mdev->state.role == R_SECONDARY && | 2407 | if (mdev->state.role == R_SECONDARY && |
2335 | mdev->state.peer == R_SECONDARY) { | 2408 | mdev->state.peer == R_SECONDARY) { |
2336 | retcode = ERR_NO_PRIMARY; | 2409 | retcode = ERR_NO_PRIMARY; |
2337 | goto fail; | 2410 | goto fail_ldev; |
2338 | } | ||
2339 | |||
2340 | if (!get_ldev(mdev)) { | ||
2341 | retcode = ERR_NO_DISK; | ||
2342 | goto fail; | ||
2343 | } | 2411 | } |
2344 | 2412 | ||
2345 | if (rs.no_resync && mdev->tconn->agreed_pro_version < 93) { | 2413 | if (rs.no_resync && mdev->tconn->agreed_pro_version < 93) { |
@@ -2358,6 +2426,28 @@ int drbd_adm_resize(struct sk_buff *skb, struct genl_info *info) | |||
2358 | } | 2426 | } |
2359 | } | 2427 | } |
2360 | 2428 | ||
2429 | if (mdev->ldev->md.al_stripes != rs.al_stripes || | ||
2430 | mdev->ldev->md.al_stripe_size_4k != rs.al_stripe_size / 4) { | ||
2431 | u32 al_size_k = rs.al_stripes * rs.al_stripe_size; | ||
2432 | |||
2433 | if (al_size_k > (16 * 1024 * 1024)) { | ||
2434 | retcode = ERR_MD_LAYOUT_TOO_BIG; | ||
2435 | goto fail_ldev; | ||
2436 | } | ||
2437 | |||
2438 | if (al_size_k < MD_32kB_SECT/2) { | ||
2439 | retcode = ERR_MD_LAYOUT_TOO_SMALL; | ||
2440 | goto fail_ldev; | ||
2441 | } | ||
2442 | |||
2443 | if (mdev->state.conn != C_CONNECTED) { | ||
2444 | retcode = ERR_MD_LAYOUT_CONNECTED; | ||
2445 | goto fail_ldev; | ||
2446 | } | ||
2447 | |||
2448 | change_al_layout = true; | ||
2449 | } | ||
2450 | |||
2361 | if (mdev->ldev->known_size != drbd_get_capacity(mdev->ldev->backing_bdev)) | 2451 | if (mdev->ldev->known_size != drbd_get_capacity(mdev->ldev->backing_bdev)) |
2362 | mdev->ldev->known_size = drbd_get_capacity(mdev->ldev->backing_bdev); | 2452 | mdev->ldev->known_size = drbd_get_capacity(mdev->ldev->backing_bdev); |
2363 | 2453 | ||
@@ -2373,16 +2463,22 @@ int drbd_adm_resize(struct sk_buff *skb, struct genl_info *info) | |||
2373 | } | 2463 | } |
2374 | 2464 | ||
2375 | ddsf = (rs.resize_force ? DDSF_FORCED : 0) | (rs.no_resync ? DDSF_NO_RESYNC : 0); | 2465 | ddsf = (rs.resize_force ? DDSF_FORCED : 0) | (rs.no_resync ? DDSF_NO_RESYNC : 0); |
2376 | dd = drbd_determine_dev_size(mdev, ddsf); | 2466 | dd = drbd_determine_dev_size(mdev, ddsf, change_al_layout ? &rs : NULL); |
2377 | drbd_md_sync(mdev); | 2467 | drbd_md_sync(mdev); |
2378 | put_ldev(mdev); | 2468 | put_ldev(mdev); |
2379 | if (dd == dev_size_error) { | 2469 | if (dd == DS_ERROR) { |
2380 | retcode = ERR_NOMEM_BITMAP; | 2470 | retcode = ERR_NOMEM_BITMAP; |
2381 | goto fail; | 2471 | goto fail; |
2472 | } else if (dd == DS_ERROR_SPACE_MD) { | ||
2473 | retcode = ERR_MD_LAYOUT_NO_FIT; | ||
2474 | goto fail; | ||
2475 | } else if (dd == DS_ERROR_SHRINK) { | ||
2476 | retcode = ERR_IMPLICIT_SHRINK; | ||
2477 | goto fail; | ||
2382 | } | 2478 | } |
2383 | 2479 | ||
2384 | if (mdev->state.conn == C_CONNECTED) { | 2480 | if (mdev->state.conn == C_CONNECTED) { |
2385 | if (dd == grew) | 2481 | if (dd == DS_GREW) |
2386 | set_bit(RESIZE_PENDING, &mdev->flags); | 2482 | set_bit(RESIZE_PENDING, &mdev->flags); |
2387 | 2483 | ||
2388 | drbd_send_uuids(mdev); | 2484 | drbd_send_uuids(mdev); |
@@ -2658,7 +2754,6 @@ int nla_put_status_info(struct sk_buff *skb, struct drbd_conf *mdev, | |||
2658 | const struct sib_info *sib) | 2754 | const struct sib_info *sib) |
2659 | { | 2755 | { |
2660 | struct state_info *si = NULL; /* for sizeof(si->member); */ | 2756 | struct state_info *si = NULL; /* for sizeof(si->member); */ |
2661 | struct net_conf *nc; | ||
2662 | struct nlattr *nla; | 2757 | struct nlattr *nla; |
2663 | int got_ldev; | 2758 | int got_ldev; |
2664 | int err = 0; | 2759 | int err = 0; |
@@ -2688,13 +2783,19 @@ int nla_put_status_info(struct sk_buff *skb, struct drbd_conf *mdev, | |||
2688 | goto nla_put_failure; | 2783 | goto nla_put_failure; |
2689 | 2784 | ||
2690 | rcu_read_lock(); | 2785 | rcu_read_lock(); |
2691 | if (got_ldev) | 2786 | if (got_ldev) { |
2692 | if (disk_conf_to_skb(skb, rcu_dereference(mdev->ldev->disk_conf), exclude_sensitive)) | 2787 | struct disk_conf *disk_conf; |
2693 | goto nla_put_failure; | ||
2694 | 2788 | ||
2695 | nc = rcu_dereference(mdev->tconn->net_conf); | 2789 | disk_conf = rcu_dereference(mdev->ldev->disk_conf); |
2696 | if (nc) | 2790 | err = disk_conf_to_skb(skb, disk_conf, exclude_sensitive); |
2697 | err = net_conf_to_skb(skb, nc, exclude_sensitive); | 2791 | } |
2792 | if (!err) { | ||
2793 | struct net_conf *nc; | ||
2794 | |||
2795 | nc = rcu_dereference(mdev->tconn->net_conf); | ||
2796 | if (nc) | ||
2797 | err = net_conf_to_skb(skb, nc, exclude_sensitive); | ||
2798 | } | ||
2698 | rcu_read_unlock(); | 2799 | rcu_read_unlock(); |
2699 | if (err) | 2800 | if (err) |
2700 | goto nla_put_failure; | 2801 | goto nla_put_failure; |