diff options
author | Andreas Gruenbacher <agruen@linbit.com> | 2011-07-06 09:03:31 -0400 |
---|---|---|
committer | Philipp Reisner <philipp.reisner@linbit.com> | 2014-02-17 10:46:44 -0500 |
commit | b6f85ef9538b2111a8ba0bbfae9aaebabfc94961 (patch) | |
tree | ada222b0aff93fc6848d7365e92f933be9a29d84 | |
parent | 270eb5c97258b9ae157d768fb19a42a685b41740 (diff) |
drbd: Iterate over all connections
in drbd_adm_down(), drbd_create_device() and drbd_set_role()
Signed-off-by: Andreas Gruenbacher <agruen@linbit.com>
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
-rw-r--r-- | drivers/block/drbd/drbd_main.c | 55 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_nl.c | 68 |
2 files changed, 70 insertions, 53 deletions
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index b00a8d74f6cb..54df98fa2881 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c | |||
@@ -2661,9 +2661,9 @@ static int init_submitter(struct drbd_device *device) | |||
2661 | 2661 | ||
2662 | enum drbd_ret_code drbd_create_device(struct drbd_resource *resource, unsigned int minor, int vnr) | 2662 | enum drbd_ret_code drbd_create_device(struct drbd_resource *resource, unsigned int minor, int vnr) |
2663 | { | 2663 | { |
2664 | struct drbd_connection *connection = first_connection(resource); | 2664 | struct drbd_connection *connection; |
2665 | struct drbd_device *device; | 2665 | struct drbd_device *device; |
2666 | struct drbd_peer_device *peer_device; | 2666 | struct drbd_peer_device *peer_device, *tmp_peer_device; |
2667 | struct gendisk *disk; | 2667 | struct gendisk *disk; |
2668 | struct request_queue *q; | 2668 | struct request_queue *q; |
2669 | int id; | 2669 | int id; |
@@ -2679,18 +2679,8 @@ enum drbd_ret_code drbd_create_device(struct drbd_resource *resource, unsigned i | |||
2679 | return ERR_NOMEM; | 2679 | return ERR_NOMEM; |
2680 | kref_init(&device->kref); | 2680 | kref_init(&device->kref); |
2681 | 2681 | ||
2682 | peer_device = kzalloc(sizeof(struct drbd_peer_device), GFP_KERNEL); | ||
2683 | if (!peer_device) | ||
2684 | goto out_no_peer_device; | ||
2685 | |||
2686 | INIT_LIST_HEAD(&device->peer_devices); | ||
2687 | list_add(&peer_device->peer_devices, &device->peer_devices); | ||
2688 | kref_get(&resource->kref); | 2682 | kref_get(&resource->kref); |
2689 | device->resource = resource; | 2683 | device->resource = resource; |
2690 | kref_get(&connection->kref); | ||
2691 | peer_device->connection = connection; | ||
2692 | peer_device->device = device; | ||
2693 | |||
2694 | device->minor = minor; | 2684 | device->minor = minor; |
2695 | device->vnr = vnr; | 2685 | device->vnr = vnr; |
2696 | 2686 | ||
@@ -2761,15 +2751,27 @@ enum drbd_ret_code drbd_create_device(struct drbd_resource *resource, unsigned i | |||
2761 | } | 2751 | } |
2762 | kref_get(&device->kref); | 2752 | kref_get(&device->kref); |
2763 | 2753 | ||
2764 | id = idr_alloc(&connection->peer_devices, peer_device, vnr, vnr + 1, GFP_KERNEL); | 2754 | INIT_LIST_HEAD(&device->peer_devices); |
2765 | if (id < 0) { | 2755 | for_each_connection(connection, resource) { |
2766 | if (id == -ENOSPC) { | 2756 | peer_device = kzalloc(sizeof(struct drbd_peer_device), GFP_KERNEL); |
2767 | err = ERR_INVALID_REQUEST; | 2757 | if (!peer_device) |
2768 | drbd_msg_put_info("requested volume exists already"); | 2758 | goto out_idr_remove_from_resource; |
2759 | peer_device->connection = connection; | ||
2760 | peer_device->device = device; | ||
2761 | |||
2762 | list_add(&peer_device->peer_devices, &device->peer_devices); | ||
2763 | kref_get(&device->kref); | ||
2764 | |||
2765 | id = idr_alloc(&connection->peer_devices, peer_device, vnr, vnr + 1, GFP_KERNEL); | ||
2766 | if (id < 0) { | ||
2767 | if (id == -ENOSPC) { | ||
2768 | err = ERR_INVALID_REQUEST; | ||
2769 | drbd_msg_put_info("requested volume exists already"); | ||
2770 | } | ||
2771 | goto out_idr_remove_from_resource; | ||
2769 | } | 2772 | } |
2770 | goto out_idr_remove_from_resource; | 2773 | kref_get(&connection->kref); |
2771 | } | 2774 | } |
2772 | kref_get(&device->kref); | ||
2773 | 2775 | ||
2774 | if (init_submitter(device)) { | 2776 | if (init_submitter(device)) { |
2775 | err = ERR_NOMEM; | 2777 | err = ERR_NOMEM; |
@@ -2780,7 +2782,7 @@ enum drbd_ret_code drbd_create_device(struct drbd_resource *resource, unsigned i | |||
2780 | add_disk(disk); | 2782 | add_disk(disk); |
2781 | 2783 | ||
2782 | /* inherit the connection state */ | 2784 | /* inherit the connection state */ |
2783 | device->state.conn = connection->cstate; | 2785 | device->state.conn = first_connection(resource)->cstate; |
2784 | if (device->state.conn == C_WF_REPORT_PARAMS) | 2786 | if (device->state.conn == C_WF_REPORT_PARAMS) |
2785 | drbd_connected(device); | 2787 | drbd_connected(device); |
2786 | 2788 | ||
@@ -2789,6 +2791,17 @@ enum drbd_ret_code drbd_create_device(struct drbd_resource *resource, unsigned i | |||
2789 | out_idr_remove_vol: | 2791 | out_idr_remove_vol: |
2790 | idr_remove(&connection->peer_devices, vnr); | 2792 | idr_remove(&connection->peer_devices, vnr); |
2791 | out_idr_remove_from_resource: | 2793 | out_idr_remove_from_resource: |
2794 | for_each_connection(connection, resource) { | ||
2795 | peer_device = idr_find(&connection->peer_devices, vnr); | ||
2796 | if (peer_device) { | ||
2797 | idr_remove(&connection->peer_devices, vnr); | ||
2798 | kref_put(&connection->kref, drbd_destroy_connection); | ||
2799 | } | ||
2800 | } | ||
2801 | for_each_peer_device_safe(peer_device, tmp_peer_device, device) { | ||
2802 | list_del(&peer_device->peer_devices); | ||
2803 | kfree(peer_device); | ||
2804 | } | ||
2792 | idr_remove(&resource->devices, vnr); | 2805 | idr_remove(&resource->devices, vnr); |
2793 | out_idr_remove_minor: | 2806 | out_idr_remove_minor: |
2794 | idr_remove(&drbd_devices, minor); | 2807 | idr_remove(&drbd_devices, minor); |
@@ -2802,9 +2815,7 @@ out_no_io_page: | |||
2802 | out_no_disk: | 2815 | out_no_disk: |
2803 | blk_cleanup_queue(q); | 2816 | blk_cleanup_queue(q); |
2804 | out_no_q: | 2817 | out_no_q: |
2805 | kref_put(&connection->kref, drbd_destroy_connection); | ||
2806 | kref_put(&resource->kref, drbd_destroy_resource); | 2818 | kref_put(&resource->kref, drbd_destroy_resource); |
2807 | out_no_peer_device: | ||
2808 | kfree(device); | 2819 | kfree(device); |
2809 | return err; | 2820 | return err; |
2810 | } | 2821 | } |
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index 33bc23fc55bb..8ebcf88b0c1b 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c | |||
@@ -560,8 +560,16 @@ drbd_set_role(struct drbd_device *device, enum drbd_role new_role, int force) | |||
560 | int forced = 0; | 560 | int forced = 0; |
561 | union drbd_state mask, val; | 561 | union drbd_state mask, val; |
562 | 562 | ||
563 | if (new_role == R_PRIMARY) | 563 | if (new_role == R_PRIMARY) { |
564 | request_ping(first_peer_device(device)->connection); /* Detect a dead peer ASAP */ | 564 | struct drbd_connection *connection; |
565 | |||
566 | /* Detect dead peers as soon as possible. */ | ||
567 | |||
568 | rcu_read_lock(); | ||
569 | for_each_connection(connection, device->resource) | ||
570 | request_ping(connection); | ||
571 | rcu_read_unlock(); | ||
572 | } | ||
565 | 573 | ||
566 | mutex_lock(device->state_mutex); | 574 | mutex_lock(device->state_mutex); |
567 | 575 | ||
@@ -3387,8 +3395,10 @@ out: | |||
3387 | 3395 | ||
3388 | int drbd_adm_down(struct sk_buff *skb, struct genl_info *info) | 3396 | int drbd_adm_down(struct sk_buff *skb, struct genl_info *info) |
3389 | { | 3397 | { |
3398 | struct drbd_resource *resource; | ||
3399 | struct drbd_connection *connection; | ||
3400 | struct drbd_device *device; | ||
3390 | int retcode; /* enum drbd_ret_code rsp. enum drbd_state_rv */ | 3401 | int retcode; /* enum drbd_ret_code rsp. enum drbd_state_rv */ |
3391 | struct drbd_peer_device *peer_device; | ||
3392 | unsigned i; | 3402 | unsigned i; |
3393 | 3403 | ||
3394 | retcode = drbd_adm_prepare(skb, info, DRBD_ADM_NEED_RESOURCE); | 3404 | retcode = drbd_adm_prepare(skb, info, DRBD_ADM_NEED_RESOURCE); |
@@ -3397,24 +3407,29 @@ int drbd_adm_down(struct sk_buff *skb, struct genl_info *info) | |||
3397 | if (retcode != NO_ERROR) | 3407 | if (retcode != NO_ERROR) |
3398 | goto out; | 3408 | goto out; |
3399 | 3409 | ||
3410 | resource = adm_ctx.resource; | ||
3400 | /* demote */ | 3411 | /* demote */ |
3401 | idr_for_each_entry(&adm_ctx.connection->peer_devices, peer_device, i) { | 3412 | for_each_connection(connection, resource) { |
3402 | retcode = drbd_set_role(peer_device->device, R_SECONDARY, 0); | 3413 | struct drbd_peer_device *peer_device; |
3414 | |||
3415 | idr_for_each_entry(&connection->peer_devices, peer_device, i) { | ||
3416 | retcode = drbd_set_role(peer_device->device, R_SECONDARY, 0); | ||
3417 | if (retcode < SS_SUCCESS) { | ||
3418 | drbd_msg_put_info("failed to demote"); | ||
3419 | goto out; | ||
3420 | } | ||
3421 | } | ||
3422 | |||
3423 | retcode = conn_try_disconnect(connection, 0); | ||
3403 | if (retcode < SS_SUCCESS) { | 3424 | if (retcode < SS_SUCCESS) { |
3404 | drbd_msg_put_info("failed to demote"); | 3425 | drbd_msg_put_info("failed to disconnect"); |
3405 | goto out; | 3426 | goto out; |
3406 | } | 3427 | } |
3407 | } | 3428 | } |
3408 | 3429 | ||
3409 | retcode = conn_try_disconnect(adm_ctx.connection, 0); | ||
3410 | if (retcode < SS_SUCCESS) { | ||
3411 | drbd_msg_put_info("failed to disconnect"); | ||
3412 | goto out; | ||
3413 | } | ||
3414 | |||
3415 | /* detach */ | 3430 | /* detach */ |
3416 | idr_for_each_entry(&adm_ctx.connection->peer_devices, peer_device, i) { | 3431 | idr_for_each_entry(&resource->devices, device, i) { |
3417 | retcode = adm_detach(peer_device->device, 0); | 3432 | retcode = adm_detach(device, 0); |
3418 | if (retcode < SS_SUCCESS || retcode > NO_ERROR) { | 3433 | if (retcode < SS_SUCCESS || retcode > NO_ERROR) { |
3419 | drbd_msg_put_info("failed to detach"); | 3434 | drbd_msg_put_info("failed to detach"); |
3420 | goto out; | 3435 | goto out; |
@@ -3424,13 +3439,14 @@ int drbd_adm_down(struct sk_buff *skb, struct genl_info *info) | |||
3424 | /* If we reach this, all volumes (of this connection) are Secondary, | 3439 | /* If we reach this, all volumes (of this connection) are Secondary, |
3425 | * Disconnected, Diskless, aka Unconfigured. Make sure all threads have | 3440 | * Disconnected, Diskless, aka Unconfigured. Make sure all threads have |
3426 | * actually stopped, state handling only does drbd_thread_stop_nowait(). */ | 3441 | * actually stopped, state handling only does drbd_thread_stop_nowait(). */ |
3427 | drbd_thread_stop(&adm_ctx.connection->worker); | 3442 | for_each_connection(connection, resource) |
3443 | drbd_thread_stop(&connection->worker); | ||
3428 | 3444 | ||
3429 | /* Now, nothing can fail anymore */ | 3445 | /* Now, nothing can fail anymore */ |
3430 | 3446 | ||
3431 | /* delete volumes */ | 3447 | /* delete volumes */ |
3432 | idr_for_each_entry(&adm_ctx.connection->peer_devices, peer_device, i) { | 3448 | idr_for_each_entry(&resource->devices, device, i) { |
3433 | retcode = adm_del_minor(peer_device->device); | 3449 | retcode = adm_del_minor(device); |
3434 | if (retcode != NO_ERROR) { | 3450 | if (retcode != NO_ERROR) { |
3435 | /* "can not happen" */ | 3451 | /* "can not happen" */ |
3436 | drbd_msg_put_info("failed to delete volume"); | 3452 | drbd_msg_put_info("failed to delete volume"); |
@@ -3438,21 +3454,11 @@ int drbd_adm_down(struct sk_buff *skb, struct genl_info *info) | |||
3438 | } | 3454 | } |
3439 | } | 3455 | } |
3440 | 3456 | ||
3441 | /* delete connection */ | 3457 | list_del_rcu(&resource->resources); |
3442 | if (conn_lowest_minor(adm_ctx.connection) < 0) { | 3458 | synchronize_rcu(); |
3443 | struct drbd_resource *resource = adm_ctx.connection->resource; | 3459 | drbd_free_resource(resource); |
3444 | 3460 | retcode = NO_ERROR; | |
3445 | list_del_rcu(&resource->resources); | ||
3446 | synchronize_rcu(); | ||
3447 | drbd_free_resource(resource); | ||
3448 | 3461 | ||
3449 | retcode = NO_ERROR; | ||
3450 | } else { | ||
3451 | /* "can not happen" */ | ||
3452 | retcode = ERR_RES_IN_USE; | ||
3453 | drbd_msg_put_info("failed to delete connection"); | ||
3454 | } | ||
3455 | goto out; | ||
3456 | out: | 3462 | out: |
3457 | drbd_adm_finish(info, retcode); | 3463 | drbd_adm_finish(info, retcode); |
3458 | return 0; | 3464 | return 0; |