lkml.org 
[lkml]   [2011]   [Aug]   [25]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 118/118] drbd: Implemented connection wide state changes
    Date
    That is used for graceful disconnect only

    Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
    Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
    ---
    drivers/block/drbd/drbd_nl.c | 28 +++++++++---------
    drivers/block/drbd/drbd_state.c | 62 +++++++++++++++++++++++++++++++++++++++
    2 files changed, 76 insertions(+), 14 deletions(-)

    diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
    index 3d8e631..d6832f8 100644
    --- a/drivers/block/drbd/drbd_nl.c
    +++ b/drivers/block/drbd/drbd_nl.c
    @@ -1572,6 +1572,7 @@ fail:
    static int drbd_nl_disconnect(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
    struct drbd_nl_cfg_reply *reply)
    {
    + struct drbd_tconn *tconn = mdev->tconn;
    int retcode;
    struct disconnect dc;

    @@ -1582,30 +1583,29 @@ static int drbd_nl_disconnect(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nl
    }

    if (dc.force) {
    - spin_lock_irq(&mdev->tconn->req_lock);
    - if (mdev->state.conn >= C_WF_CONNECTION)
    - _drbd_set_state(_NS(mdev, conn, C_DISCONNECTING), CS_HARD, NULL);
    - spin_unlock_irq(&mdev->tconn->req_lock);
    + spin_lock_irq(&tconn->req_lock);
    + if (tconn->cstate >= C_WF_CONNECTION)
    + _conn_request_state(tconn, NS(conn, C_DISCONNECTING), CS_HARD);
    + spin_unlock_irq(&tconn->req_lock);
    goto done;
    }

    - retcode = _drbd_request_state(mdev, NS(conn, C_DISCONNECTING), CS_ORDERED);
    + retcode = conn_request_state(tconn, NS(conn, C_DISCONNECTING), 0);

    if (retcode == SS_NOTHING_TO_DO)
    goto done;
    else if (retcode == SS_ALREADY_STANDALONE)
    goto done;
    else if (retcode == SS_PRIMARY_NOP) {
    - /* Our statche checking code wants to see the peer outdated. */
    - retcode = drbd_request_state(mdev, NS2(conn, C_DISCONNECTING,
    - pdsk, D_OUTDATED));
    + /* Our state checking code wants to see the peer outdated. */
    + retcode = conn_request_state(tconn, NS2(conn, C_DISCONNECTING,
    + pdsk, D_OUTDATED), CS_VERBOSE);
    } else if (retcode == SS_CW_FAILED_BY_PEER) {
    /* The peer probably wants to see us outdated. */
    - retcode = _drbd_request_state(mdev, NS2(conn, C_DISCONNECTING,
    - disk, D_OUTDATED),
    - CS_ORDERED);
    + retcode = conn_request_state(tconn, NS2(conn, C_DISCONNECTING,
    + disk, D_OUTDATED), 0);
    if (retcode == SS_IS_DISKLESS || retcode == SS_LOWER_THAN_OUTDATED) {
    - drbd_force_state(mdev, NS(conn, C_DISCONNECTING));
    + conn_request_state(tconn, NS(conn, C_DISCONNECTING), CS_HARD);
    retcode = SS_SUCCESS;
    }
    }
    @@ -1613,8 +1613,8 @@ static int drbd_nl_disconnect(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nl
    if (retcode < SS_SUCCESS)
    goto fail;

    - if (wait_event_interruptible(mdev->state_wait,
    - mdev->state.conn != C_DISCONNECTING)) {
    + if (wait_event_interruptible(tconn->ping_wait,
    + tconn->cstate != C_DISCONNECTING)) {
    /* Do not test for mdev->state.conn == C_STANDALONE, since
    someone else might connect us in the mean time! */
    retcode = ERR_INTR;
    diff --git a/drivers/block/drbd/drbd_state.c b/drivers/block/drbd/drbd_state.c
    index 81f66b3..61c65f5 100644
    --- a/drivers/block/drbd/drbd_state.c
    +++ b/drivers/block/drbd/drbd_state.c
    @@ -1366,6 +1366,62 @@ static int _set_state_itr_fn(int vnr, void *p, void *data)
    return 0;
    }

    +static enum drbd_state_rv
    +_conn_rq_cond(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state val)
    +{
    + struct _is_valid_itr_params params;
    + enum drbd_conns oc = tconn->cstate;
    + enum drbd_state_rv rv;
    +
    + if (test_and_clear_bit(CONN_WD_ST_CHG_OKAY, &tconn->flags))
    + return SS_CW_SUCCESS;
    +
    + if (test_and_clear_bit(CONN_WD_ST_CHG_FAIL, &tconn->flags))
    + return SS_CW_FAILED_BY_PEER;
    +
    + params.flags = CS_NO_CSTATE_CHG; /* öö think */
    + params.mask = mask;
    + params.val = val;
    +
    + spin_lock_irq(&tconn->req_lock);
    + rv = oc != C_WF_REPORT_PARAMS ? SS_CW_NO_NEED : SS_UNKNOWN_ERROR;
    +
    + if (rv == SS_UNKNOWN_ERROR)
    + rv = idr_for_each(&tconn->volumes, _is_valid_itr_fn, &params);
    +
    + if (rv == 0) /* idr_for_each semantics */
    + rv = SS_UNKNOWN_ERROR; /* cont waiting, otherwise fail. */
    +
    + spin_unlock_irq(&tconn->req_lock);
    +
    + return rv;
    +}
    +
    +static enum drbd_state_rv
    +conn_cl_wide(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state val,
    + enum chg_state_flags f)
    +{
    + enum drbd_state_rv rv;
    +
    + spin_unlock_irq(&tconn->req_lock);
    + mutex_lock(&tconn->cstate_mutex);
    +
    + if (!conn_send_state_req(tconn, mask, val)) {
    + rv = SS_CW_FAILED_BY_PEER;
    + /* if (f & CS_VERBOSE)
    + print_st_err(mdev, os, ns, rv); */
    + goto abort;
    + }
    +
    + wait_event(tconn->ping_wait, (rv = _conn_rq_cond(tconn, mask, val)));
    +
    +abort:
    + mutex_unlock(&tconn->cstate_mutex);
    + spin_lock_irq(&tconn->req_lock);
    +
    + return rv;
    +}
    +
    enum drbd_state_rv
    _conn_request_state(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state val,
    enum chg_state_flags flags)
    @@ -1393,6 +1449,12 @@ _conn_request_state(struct drbd_tconn *tconn, union drbd_state mask, union drbd_
    if (rv < SS_SUCCESS)
    goto abort;

    + if (oc == C_WF_REPORT_PARAMS && val.conn == C_DISCONNECTING && !(flags & CS_LOCAL_ONLY)) {
    + rv = conn_cl_wide(tconn, mask, val, flags);
    + if (rv < SS_SUCCESS)
    + goto abort;
    + }
    +
    if (params.oc_state == OC_CONSISTENT) {
    oc = params.oc;
    print_conn_state_change(tconn, oc, val.conn);
    --
    1.7.4.1
    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2011-08-25 17:35    [W:0.038 / U:148.600 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site