* [RFC 00/16] drbd: part 8 of adding multiple volume support to drbd
@ 2011-09-08 12:45 Philipp Reisner
2011-09-08 12:45 ` [PATCH 01/16] drbd: Use the idr_for_each_entry() iterator instead of idr_for_each() Philipp Reisner
` (15 more replies)
0 siblings, 16 replies; 17+ messages in thread
From: Philipp Reisner @ 2011-09-08 12:45 UTC (permalink / raw)
To: linux-kernel, Jens Axboe; +Cc: drbd-dev
This the first request for review of drbd-8.4. The complete set has
478 patches. This is the eighth installment containing 16 patches.
The whole set is available here:
git://git.drbd.org/linux-2.6-drbd.git for-jens
and is jens_for-3.2_drivers...for-jens
and this part is a62c954^...9c7c195
This patch series contains:
* Nicer logging of state transitions
* Cleanups and restructuring asender receive functions
* Multi-slot transactions for the activity log
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 01/16] drbd: Use the idr_for_each_entry() iterator instead of idr_for_each()
2011-09-08 12:45 [RFC 00/16] drbd: part 8 of adding multiple volume support to drbd Philipp Reisner
@ 2011-09-08 12:45 ` Philipp Reisner
2011-09-08 12:45 ` [PATCH 02/16] drbd: Fixed logging of old connection state Philipp Reisner
` (14 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Philipp Reisner @ 2011-09-08 12:45 UTC (permalink / raw)
To: linux-kernel, Jens Axboe; +Cc: drbd-dev
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
---
drivers/block/drbd/drbd_state.c | 149 +++++++++++++++++++--------------------
1 files changed, 74 insertions(+), 75 deletions(-)
diff --git a/drivers/block/drbd/drbd_state.c b/drivers/block/drbd/drbd_state.c
index 9159043..e712da7 100644
--- a/drivers/block/drbd/drbd_state.c
+++ b/drivers/block/drbd/drbd_state.c
@@ -1360,9 +1360,6 @@ static void print_conn_state_change(struct drbd_tconn *tconn, enum drbd_conns oc
}
struct _is_valid_itr_params {
- enum chg_state_flags flags;
- union drbd_state mask, val;
- union drbd_state ms; /* maximal state, over all mdevs */
enum drbd_conns oc;
enum {
OC_UNINITIALIZED,
@@ -1371,69 +1368,85 @@ struct _is_valid_itr_params {
} oc_state;
};
-static int _is_valid_itr_fn(int vnr, void *p, void *data)
+static enum drbd_state_rv
+conn_is_valid_transition(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state val,
+ enum chg_state_flags flags, struct _is_valid_itr_params *params)
{
- struct drbd_conf *mdev = (struct drbd_conf *)p;
- struct _is_valid_itr_params *params = (struct _is_valid_itr_params *)data;
- enum chg_state_flags flags = params->flags;
+ enum drbd_state_rv rv = SS_SUCCESS;
union drbd_state ns, os;
- enum drbd_state_rv rv;
-
- os = mdev->state;
- ns = apply_mask_val(os, params->mask, params->val);
- ns = sanitize_state(mdev, ns, NULL);
- rv = is_valid_state(mdev, ns);
+ struct drbd_conf *mdev;
+ int vnr;
- if (rv < SS_SUCCESS) {
- /* If the old state was illegal as well, then let this happen...*/
+ params->oc_state = OC_UNINITIALIZED;
+ idr_for_each_entry(&tconn->volumes, mdev, vnr) {
+ os = mdev->state;
+ ns = sanitize_state(mdev, apply_mask_val(os, mask, val), NULL);
+
+ switch (params->oc_state) {
+ case OC_UNINITIALIZED:
+ params->oc = os.conn;
+ params->oc_state = OC_CONSISTENT;
+ break;
+ case OC_CONSISTENT:
+ if (params->oc != os.conn)
+ params->oc_state = OC_INCONSISTENT;
+ break;
+ case OC_INCONSISTENT:
+ break;
+ }
- if (is_valid_state(mdev, os) == rv)
- rv = is_valid_soft_transition(os, ns);
- } else
- rv = is_valid_soft_transition(os, ns);
+ if (ns.i == os.i)
+ continue;
- switch (params->oc_state) {
- case OC_UNINITIALIZED:
- params->oc = os.conn;
- params->oc_state = OC_CONSISTENT;
- break;
- case OC_CONSISTENT:
- if (params->oc != os.conn)
- params->oc_state = OC_INCONSISTENT;
- break;
- case OC_INCONSISTENT:
- break;
+ rv = is_valid_transition(os, ns);
+ if (rv < SS_SUCCESS)
+ break;
+
+ if (!(flags & CS_HARD)) {
+ rv = is_valid_state(mdev, ns);
+ if (rv < SS_SUCCESS) {
+ if (is_valid_state(mdev, os) == rv)
+ rv = is_valid_soft_transition(os, ns);
+ } else
+ rv = is_valid_soft_transition(os, ns);
+ }
+ if (rv < SS_SUCCESS)
+ break;
}
- if (rv < SS_SUCCESS) {
- if (flags & CS_VERBOSE)
- print_st_err(mdev, os, ns, rv);
- return rv;
- } else
- return 0;
+ if (rv < SS_SUCCESS && flags & CS_VERBOSE)
+ print_st_err(mdev, os, ns, rv);
+
+ return rv;
}
-static int _set_state_itr_fn(int vnr, void *p, void *data)
+static union drbd_state
+conn_set_state(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state val,
+ enum chg_state_flags flags)
{
- struct drbd_conf *mdev = (struct drbd_conf *)p;
- struct _is_valid_itr_params *params = (struct _is_valid_itr_params *)data;
- enum chg_state_flags flags = params->flags;
- union drbd_state os, ns, ms = params->ms;
+ union drbd_state ns, os, ms = { };
+ struct drbd_conf *mdev;
enum drbd_state_rv rv;
+ int vnr;
- os = mdev->state;
- ns = apply_mask_val(os, params->mask, params->val);
- ns = sanitize_state(mdev, ns, NULL);
+ tconn->cstate = val.conn;
- rv = __drbd_set_state(mdev, ns, flags, NULL);
+ idr_for_each_entry(&tconn->volumes, mdev, vnr) {
+ os = mdev->state;
+ ns = apply_mask_val(os, mask, val);
+ ns = sanitize_state(mdev, ns, NULL);
- ms.role = max_t(enum drbd_role, mdev->state.role, ms.role);
- ms.peer = max_t(enum drbd_role, mdev->state.peer, ms.peer);
- ms.disk = max_t(enum drbd_role, mdev->state.disk, ms.disk);
- ms.pdsk = max_t(enum drbd_role, mdev->state.pdsk, ms.pdsk);
- params->ms = ms;
+ rv = __drbd_set_state(mdev, ns, flags, NULL);
+ if (rv < SS_SUCCESS)
+ BUG();
- return 0;
+ ms.role = max_t(enum drbd_role, mdev->state.role, ms.role);
+ ms.peer = max_t(enum drbd_role, mdev->state.peer, ms.peer);
+ ms.disk = max_t(enum drbd_disk_state, mdev->state.disk, ms.disk);
+ ms.pdsk = max_t(enum drbd_disk_state, mdev->state.pdsk, ms.pdsk);
+ }
+
+ return ms;
}
static enum drbd_state_rv
@@ -1449,18 +1462,14 @@ _conn_rq_cond(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state
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, ¶ms);
+ rv = conn_is_valid_transition(tconn, mask, val, CS_NO_CSTATE_CHG, ¶ms);
- if (rv == 0) /* idr_for_each semantics */
- rv = SS_UNKNOWN_ERROR; /* cont waiting, otherwise fail. */
+ if (rv == SS_SUCCESS)
+ rv = SS_UNKNOWN_ERROR; /* cont waiting, otherwise fail. */
spin_unlock_irq(&tconn->req_lock);
@@ -1500,22 +1509,13 @@ _conn_request_state(struct drbd_tconn *tconn, union drbd_state mask, union drbd_
struct _is_valid_itr_params params;
struct after_conn_state_chg_work *acscw;
enum drbd_conns oc = tconn->cstate;
+ union drbd_state ms;
rv = is_valid_conn_transition(oc, val.conn);
if (rv < SS_SUCCESS)
goto abort;
- params.flags = flags;
- params.mask = mask;
- params.val = val;
- params.oc_state = OC_UNINITIALIZED;
-
- if (!(flags & CS_HARD))
- rv = idr_for_each(&tconn->volumes, _is_valid_itr_fn, ¶ms);
-
- if (rv == 0) /* idr_for_each semantics */
- rv = SS_SUCCESS;
-
+ rv = conn_is_valid_transition(tconn, mask, val, flags, ¶ms);
if (rv < SS_SUCCESS)
goto abort;
@@ -1528,17 +1528,16 @@ _conn_request_state(struct drbd_tconn *tconn, union drbd_state mask, union drbd_
if (params.oc_state == OC_CONSISTENT) {
oc = params.oc;
print_conn_state_change(tconn, oc, val.conn);
- params.flags |= CS_NO_CSTATE_CHG;
+ flags |= CS_NO_CSTATE_CHG;
}
- tconn->cstate = val.conn;
- params.ms.i = 0;
- params.ms.conn = val.conn;
- idr_for_each(&tconn->volumes, _set_state_itr_fn, ¶ms);
+
+ ms = conn_set_state(tconn, mask, val, flags);
+ ms.conn = val.conn;
acscw = kmalloc(sizeof(*acscw), GFP_ATOMIC);
if (acscw) {
acscw->oc = oc;
- acscw->nms = params.ms;
+ acscw->nms = ms;
acscw->flags = flags;
acscw->w.cb = w_after_conn_state_ch;
acscw->w.tconn = tconn;
--
1.7.4.1
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 02/16] drbd: Fixed logging of old connection state
2011-09-08 12:45 [RFC 00/16] drbd: part 8 of adding multiple volume support to drbd Philipp Reisner
2011-09-08 12:45 ` [PATCH 01/16] drbd: Use the idr_for_each_entry() iterator instead of idr_for_each() Philipp Reisner
@ 2011-09-08 12:45 ` Philipp Reisner
2011-09-08 12:45 ` [PATCH 03/16] drbd: Print common state changes of all volumes as connection state changes Philipp Reisner
` (13 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Philipp Reisner @ 2011-09-08 12:45 UTC (permalink / raw)
To: linux-kernel, Jens Axboe; +Cc: drbd-dev
During a disconnect the oc variable in _conn_request_state()
could become outdated. Determin the common old state after
sleeping.
While at it, I implemented that for all parts of the state
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
---
drivers/block/drbd/drbd_state.c | 117 +++++++++++++++++++++++++++++----------
1 files changed, 87 insertions(+), 30 deletions(-)
diff --git a/drivers/block/drbd/drbd_state.c b/drivers/block/drbd/drbd_state.c
index e712da7..3c3c141 100644
--- a/drivers/block/drbd/drbd_state.c
+++ b/drivers/block/drbd/drbd_state.c
@@ -1359,42 +1359,100 @@ static void print_conn_state_change(struct drbd_tconn *tconn, enum drbd_conns oc
conn_info(tconn, "%s\n", pb);
}
-struct _is_valid_itr_params {
- enum drbd_conns oc;
- enum {
- OC_UNINITIALIZED,
- OC_CONSISTENT,
- OC_INCONSISTENT,
- } oc_state;
-};
+enum sp_state {
+ OC_UNINITIALIZED,
+ OC_CONSISTENT,
+ OC_INCONSISTENT,
+} oc_state;
+
+static void common_state_part(enum sp_state *sps, int *sp, int nsp)
+{
+ switch (*sps) {
+ case OC_UNINITIALIZED:
+ *sp = nsp;
+ *sps = OC_CONSISTENT;
+ break;
+ case OC_CONSISTENT:
+ if (*sp != nsp)
+ *sps = OC_INCONSISTENT;
+ break;
+ case OC_INCONSISTENT:
+ break;
+ }
+}
+
+void conn_old_common_state(struct drbd_tconn *tconn, union drbd_state *pcs, union drbd_state *pmask)
+{
+ union drbd_state css = {}; /* common state state */
+ union drbd_state os, cs = {}; /* old_state, common_state */
+ union drbd_state mask = {};
+ enum sp_state sps; /* state part state */
+ int sp; /* state part */
+ struct drbd_conf *mdev;
+ int vnr;
+
+ idr_for_each_entry(&tconn->volumes, mdev, vnr) {
+ os = mdev->state;
+
+ sps = css.role;
+ sp = cs.role;
+ common_state_part(&sps, &sp, os.role);
+ css.role = sps;
+ cs.role = sp;
+
+ sps = css.peer;
+ sp = cs.peer;
+ common_state_part(&sps, &sp, os.peer);
+ css.peer = sps;
+ cs.peer = sp;
+
+ sps = css.conn;
+ sp = cs.conn;
+ common_state_part(&sps, &sp, os.conn);
+ css.conn = sps;
+ cs.conn = sp;
+
+ sps = css.disk;
+ sp = cs.disk;
+ common_state_part(&sps, &sp, os.disk);
+ css.disk = sps;
+ cs.disk = sp;
+
+ sps = css.pdsk;
+ sp = cs.pdsk;
+ common_state_part(&sps, &sp, os.pdsk);
+ css.pdsk = sps;
+ cs.pdsk = sp;
+ }
+
+ if (css.role == OC_CONSISTENT)
+ mask.role = R_MASK;
+ if (css.peer == OC_CONSISTENT)
+ mask.peer = R_MASK;
+ if (css.conn == OC_CONSISTENT)
+ mask.conn = C_MASK;
+ if (css.disk == OC_CONSISTENT)
+ mask.disk = D_MASK;
+ if (css.pdsk == OC_CONSISTENT)
+ mask.pdsk = D_MASK;
+
+ *pcs = cs;
+ *pmask = mask;
+}
static enum drbd_state_rv
conn_is_valid_transition(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state val,
- enum chg_state_flags flags, struct _is_valid_itr_params *params)
+ enum chg_state_flags flags)
{
enum drbd_state_rv rv = SS_SUCCESS;
union drbd_state ns, os;
struct drbd_conf *mdev;
int vnr;
- params->oc_state = OC_UNINITIALIZED;
idr_for_each_entry(&tconn->volumes, mdev, vnr) {
os = mdev->state;
ns = sanitize_state(mdev, apply_mask_val(os, mask, val), NULL);
- switch (params->oc_state) {
- case OC_UNINITIALIZED:
- params->oc = os.conn;
- params->oc_state = OC_CONSISTENT;
- break;
- case OC_CONSISTENT:
- if (params->oc != os.conn)
- params->oc_state = OC_INCONSISTENT;
- break;
- case OC_INCONSISTENT:
- break;
- }
-
if (ns.i == os.i)
continue;
@@ -1452,7 +1510,6 @@ conn_set_state(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state
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;
@@ -1466,7 +1523,7 @@ _conn_rq_cond(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state
rv = oc != C_WF_REPORT_PARAMS ? SS_CW_NO_NEED : SS_UNKNOWN_ERROR;
if (rv == SS_UNKNOWN_ERROR)
- rv = conn_is_valid_transition(tconn, mask, val, CS_NO_CSTATE_CHG, ¶ms);
+ rv = conn_is_valid_transition(tconn, mask, val, CS_NO_CSTATE_CHG);
if (rv == SS_SUCCESS)
rv = SS_UNKNOWN_ERROR; /* cont waiting, otherwise fail. */
@@ -1506,16 +1563,15 @@ _conn_request_state(struct drbd_tconn *tconn, union drbd_state mask, union drbd_
enum chg_state_flags flags)
{
enum drbd_state_rv rv = SS_SUCCESS;
- struct _is_valid_itr_params params;
struct after_conn_state_chg_work *acscw;
enum drbd_conns oc = tconn->cstate;
- union drbd_state ms;
+ union drbd_state ms, os_val, os_mask;
rv = is_valid_conn_transition(oc, val.conn);
if (rv < SS_SUCCESS)
goto abort;
- rv = conn_is_valid_transition(tconn, mask, val, flags, ¶ms);
+ rv = conn_is_valid_transition(tconn, mask, val, flags);
if (rv < SS_SUCCESS)
goto abort;
@@ -1525,8 +1581,9 @@ _conn_request_state(struct drbd_tconn *tconn, union drbd_state mask, union drbd_
goto abort;
}
- if (params.oc_state == OC_CONSISTENT) {
- oc = params.oc;
+ conn_old_common_state(tconn, &os_val, &os_mask);
+ if (os_mask.conn == C_MASK) {
+ oc = os_val.conn;
print_conn_state_change(tconn, oc, val.conn);
flags |= CS_NO_CSTATE_CHG;
}
--
1.7.4.1
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 03/16] drbd: Print common state changes of all volumes as connection state changes
2011-09-08 12:45 [RFC 00/16] drbd: part 8 of adding multiple volume support to drbd Philipp Reisner
2011-09-08 12:45 ` [PATCH 01/16] drbd: Use the idr_for_each_entry() iterator instead of idr_for_each() Philipp Reisner
2011-09-08 12:45 ` [PATCH 02/16] drbd: Fixed logging of old connection state Philipp Reisner
@ 2011-09-08 12:45 ` Philipp Reisner
2011-09-08 12:45 ` [PATCH 04/16] drbd: Allow to disconnect if one volume is diskless Philipp Reisner
` (12 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Philipp Reisner @ 2011-09-08 12:45 UTC (permalink / raw)
To: linux-kernel, Jens Axboe; +Cc: drbd-dev
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
---
drivers/block/drbd/drbd_state.c | 159 ++++++++++++++-------------------------
drivers/block/drbd/drbd_state.h | 19 +++--
2 files changed, 70 insertions(+), 108 deletions(-)
diff --git a/drivers/block/drbd/drbd_state.c b/drivers/block/drbd/drbd_state.c
index 3c3c141..ea2bf74 100644
--- a/drivers/block/drbd/drbd_state.c
+++ b/drivers/block/drbd/drbd_state.c
@@ -332,29 +332,29 @@ void print_st_err(struct drbd_conf *mdev, union drbd_state os,
print_st(mdev, "wanted", ns);
}
-static void print_state_change(struct drbd_conf *mdev, union drbd_state os, union drbd_state ns,
+static long print_state_change(char *pb, union drbd_state os, union drbd_state ns,
enum chg_state_flags flags)
{
- char *pbp, pb[300];
+ char *pbp;
pbp = pb;
*pbp = 0;
- if (ns.role != os.role)
+ if (ns.role != os.role && flags & CS_DC_ROLE)
pbp += sprintf(pbp, "role( %s -> %s ) ",
drbd_role_str(os.role),
drbd_role_str(ns.role));
- if (ns.peer != os.peer)
+ if (ns.peer != os.peer && flags & CS_DC_PEER)
pbp += sprintf(pbp, "peer( %s -> %s ) ",
drbd_role_str(os.peer),
drbd_role_str(ns.peer));
- if (ns.conn != os.conn && !(flags & CS_NO_CSTATE_CHG))
+ if (ns.conn != os.conn && flags & CS_DC_CONN)
pbp += sprintf(pbp, "conn( %s -> %s ) ",
drbd_conn_str(os.conn),
drbd_conn_str(ns.conn));
- if (ns.disk != os.disk)
+ if (ns.disk != os.disk && flags & CS_DC_DISK)
pbp += sprintf(pbp, "disk( %s -> %s ) ",
drbd_disk_str(os.disk),
drbd_disk_str(ns.disk));
- if (ns.pdsk != os.pdsk)
+ if (ns.pdsk != os.pdsk && flags & CS_DC_PDSK)
pbp += sprintf(pbp, "pdsk( %s -> %s ) ",
drbd_disk_str(os.pdsk),
drbd_disk_str(ns.pdsk));
@@ -374,10 +374,29 @@ static void print_state_change(struct drbd_conf *mdev, union drbd_state os, unio
pbp += sprintf(pbp, "user_isp( %d -> %d ) ",
os.user_isp,
ns.user_isp);
- if (pbp != pb)
+
+ return pbp - pb;
+}
+
+static void drbd_pr_state_change(struct drbd_conf *mdev, union drbd_state os, union drbd_state ns,
+ enum chg_state_flags flags)
+{
+ char pb[300];
+
+ if (print_state_change(pb, os, ns, flags ^ CS_DC_MASK))
dev_info(DEV, "%s\n", pb);
}
+static void conn_pr_state_change(struct drbd_tconn *tconn, union drbd_state os, union drbd_state ns,
+ enum chg_state_flags flags)
+{
+ char pb[300];
+
+ if (print_state_change(pb, os, ns, flags))
+ conn_info(tconn, "%s\n", pb);
+}
+
+
/**
* is_valid_state() - Returns an SS_ error code if ns is not valid
* @mdev: DRBD device.
@@ -809,7 +828,7 @@ __drbd_set_state(struct drbd_conf *mdev, union drbd_state ns,
if (warn_sync_abort)
dev_warn(DEV, "%s aborted.\n", warn_sync_abort);
- print_state_change(mdev, os, ns, flags);
+ drbd_pr_state_change(mdev, os, ns, flags);
/* if we are going -> D_FAILED or D_DISKLESS, grab one extra reference
* on the ldev here, to be sure the transition -> D_DISKLESS resp.
@@ -1346,98 +1365,41 @@ static int w_after_conn_state_ch(struct drbd_work *w, int unused)
return 0;
}
-static void print_conn_state_change(struct drbd_tconn *tconn, enum drbd_conns oc, enum drbd_conns nc)
-{
- char *pbp, pb[300];
- pbp = pb;
- *pbp = 0;
- if (nc != oc)
- pbp += sprintf(pbp, "conn( %s -> %s ) ",
- drbd_conn_str(oc),
- drbd_conn_str(nc));
-
- conn_info(tconn, "%s\n", pb);
-}
-
-enum sp_state {
- OC_UNINITIALIZED,
- OC_CONSISTENT,
- OC_INCONSISTENT,
-} oc_state;
-
-static void common_state_part(enum sp_state *sps, int *sp, int nsp)
-{
- switch (*sps) {
- case OC_UNINITIALIZED:
- *sp = nsp;
- *sps = OC_CONSISTENT;
- break;
- case OC_CONSISTENT:
- if (*sp != nsp)
- *sps = OC_INCONSISTENT;
- break;
- case OC_INCONSISTENT:
- break;
- }
-}
-
-void conn_old_common_state(struct drbd_tconn *tconn, union drbd_state *pcs, union drbd_state *pmask)
+void conn_old_common_state(struct drbd_tconn *tconn, union drbd_state *pcs, enum chg_state_flags *pf)
{
- union drbd_state css = {}; /* common state state */
+ enum chg_state_flags flags = ~0;
union drbd_state os, cs = {}; /* old_state, common_state */
- union drbd_state mask = {};
- enum sp_state sps; /* state part state */
- int sp; /* state part */
struct drbd_conf *mdev;
- int vnr;
+ int vnr, first_vol = 1;
idr_for_each_entry(&tconn->volumes, mdev, vnr) {
os = mdev->state;
- sps = css.role;
- sp = cs.role;
- common_state_part(&sps, &sp, os.role);
- css.role = sps;
- cs.role = sp;
-
- sps = css.peer;
- sp = cs.peer;
- common_state_part(&sps, &sp, os.peer);
- css.peer = sps;
- cs.peer = sp;
-
- sps = css.conn;
- sp = cs.conn;
- common_state_part(&sps, &sp, os.conn);
- css.conn = sps;
- cs.conn = sp;
-
- sps = css.disk;
- sp = cs.disk;
- common_state_part(&sps, &sp, os.disk);
- css.disk = sps;
- cs.disk = sp;
-
- sps = css.pdsk;
- sp = cs.pdsk;
- common_state_part(&sps, &sp, os.pdsk);
- css.pdsk = sps;
- cs.pdsk = sp;
- }
+ if (first_vol) {
+ cs = os;
+ first_vol = 0;
+ continue;
+ }
+
+ if (cs.role != os.role)
+ flags &= ~CS_DC_ROLE;
+
+ if (cs.peer != os.peer)
+ flags &= ~CS_DC_PEER;
+
+ if (cs.conn != os.conn)
+ flags &= ~CS_DC_CONN;
- if (css.role == OC_CONSISTENT)
- mask.role = R_MASK;
- if (css.peer == OC_CONSISTENT)
- mask.peer = R_MASK;
- if (css.conn == OC_CONSISTENT)
- mask.conn = C_MASK;
- if (css.disk == OC_CONSISTENT)
- mask.disk = D_MASK;
- if (css.pdsk == OC_CONSISTENT)
- mask.pdsk = D_MASK;
+ if (cs.disk != os.disk)
+ flags &= ~CS_DC_DISK;
+ if (cs.pdsk != os.pdsk)
+ flags &= ~CS_DC_PDSK;
+ }
+
+ *pf |= CS_DC_MASK;
+ *pf &= flags;
*pcs = cs;
- *pmask = mask;
}
static enum drbd_state_rv
@@ -1523,7 +1485,7 @@ _conn_rq_cond(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state
rv = oc != C_WF_REPORT_PARAMS ? SS_CW_NO_NEED : SS_UNKNOWN_ERROR;
if (rv == SS_UNKNOWN_ERROR)
- rv = conn_is_valid_transition(tconn, mask, val, CS_NO_CSTATE_CHG);
+ rv = conn_is_valid_transition(tconn, mask, val, 0);
if (rv == SS_SUCCESS)
rv = SS_UNKNOWN_ERROR; /* cont waiting, otherwise fail. */
@@ -1565,7 +1527,7 @@ _conn_request_state(struct drbd_tconn *tconn, union drbd_state mask, union drbd_
enum drbd_state_rv rv = SS_SUCCESS;
struct after_conn_state_chg_work *acscw;
enum drbd_conns oc = tconn->cstate;
- union drbd_state ms, os_val, os_mask;
+ union drbd_state ms, os;
rv = is_valid_conn_transition(oc, val.conn);
if (rv < SS_SUCCESS)
@@ -1581,19 +1543,14 @@ _conn_request_state(struct drbd_tconn *tconn, union drbd_state mask, union drbd_
goto abort;
}
- conn_old_common_state(tconn, &os_val, &os_mask);
- if (os_mask.conn == C_MASK) {
- oc = os_val.conn;
- print_conn_state_change(tconn, oc, val.conn);
- flags |= CS_NO_CSTATE_CHG;
- }
-
+ conn_old_common_state(tconn, &os, &flags);
ms = conn_set_state(tconn, mask, val, flags);
ms.conn = val.conn;
+ conn_pr_state_change(tconn, os, ms, flags);
acscw = kmalloc(sizeof(*acscw), GFP_ATOMIC);
if (acscw) {
- acscw->oc = oc;
+ acscw->oc = os.conn;
acscw->nms = ms;
acscw->flags = flags;
acscw->w.cb = w_after_conn_state_ch;
diff --git a/drivers/block/drbd/drbd_state.h b/drivers/block/drbd/drbd_state.h
index 394a199..11fd0f8 100644
--- a/drivers/block/drbd/drbd_state.h
+++ b/drivers/block/drbd/drbd_state.h
@@ -57,13 +57,18 @@ struct drbd_tconn;
__ns.T2 = (S2); __ns.T3 = (S3); __ns; })
enum chg_state_flags {
- CS_HARD = 1,
- CS_VERBOSE = 2,
- CS_WAIT_COMPLETE = 4,
- CS_SERIALIZE = 8,
- CS_ORDERED = CS_WAIT_COMPLETE + CS_SERIALIZE,
- CS_NO_CSTATE_CHG = 16, /* Do not display changes in cstate. Internal to drbd_state.c */
- CS_LOCAL_ONLY = 32, /* Do not consider a device pair wide state change */
+ CS_HARD = 1 << 0,
+ CS_VERBOSE = 1 << 1,
+ CS_WAIT_COMPLETE = 1 << 2,
+ CS_SERIALIZE = 1 << 3,
+ CS_ORDERED = CS_WAIT_COMPLETE + CS_SERIALIZE,
+ CS_LOCAL_ONLY = 1 << 4, /* Do not consider a device pair wide state change */
+ CS_DC_ROLE = 1 << 5, /* DC = display as connection state change */
+ CS_DC_PEER = 1 << 6,
+ CS_DC_CONN = 1 << 7,
+ CS_DC_DISK = 1 << 8,
+ CS_DC_PDSK = 1 << 9,
+ CS_DC_MASK = CS_DC_ROLE + CS_DC_PEER + CS_DC_CONN + CS_DC_DISK + CS_DC_PDSK,
};
extern enum drbd_state_rv drbd_change_state(struct drbd_conf *mdev,
--
1.7.4.1
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 04/16] drbd: Allow to disconnect if one volume is diskless
2011-09-08 12:45 [RFC 00/16] drbd: part 8 of adding multiple volume support to drbd Philipp Reisner
` (2 preceding siblings ...)
2011-09-08 12:45 ` [PATCH 03/16] drbd: Print common state changes of all volumes as connection state changes Philipp Reisner
@ 2011-09-08 12:45 ` Philipp Reisner
2011-09-08 12:45 ` [PATCH 05/16] drbd: Do not segfault if a sync dependency reaches a diskless device Philipp Reisner
` (11 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Philipp Reisner @ 2011-09-08 12:45 UTC (permalink / raw)
To: linux-kernel, Jens Axboe; +Cc: drbd-dev
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
---
drivers/block/drbd/drbd_receiver.c | 2 +-
drivers/block/drbd/drbd_state.c | 6 ++++++
drivers/block/drbd/drbd_state.h | 1 +
3 files changed, 8 insertions(+), 1 deletions(-)
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index 0301775..e45a417 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -3450,7 +3450,7 @@ static int receive_req_conn_state(struct drbd_tconn *tconn, struct packet_info *
mask = convert_state(mask);
val = convert_state(val);
- rv = conn_request_state(tconn, mask, val, CS_VERBOSE | CS_LOCAL_ONLY);
+ rv = conn_request_state(tconn, mask, val, CS_VERBOSE | CS_LOCAL_ONLY | CS_IGN_OUTD_FAIL);
conn_send_sr_reply(tconn, rv);
return 0;
diff --git a/drivers/block/drbd/drbd_state.c b/drivers/block/drbd/drbd_state.c
index ea2bf74..c73be9e 100644
--- a/drivers/block/drbd/drbd_state.c
+++ b/drivers/block/drbd/drbd_state.c
@@ -1415,6 +1415,9 @@ conn_is_valid_transition(struct drbd_tconn *tconn, union drbd_state mask, union
os = mdev->state;
ns = sanitize_state(mdev, apply_mask_val(os, mask, val), NULL);
+ if (flags & CS_IGN_OUTD_FAIL && ns.disk == D_OUTDATED && os.disk < D_OUTDATED)
+ ns.disk = os.disk;
+
if (ns.i == os.i)
continue;
@@ -1456,6 +1459,9 @@ conn_set_state(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state
ns = apply_mask_val(os, mask, val);
ns = sanitize_state(mdev, ns, NULL);
+ if (flags & CS_IGN_OUTD_FAIL && ns.disk == D_OUTDATED && os.disk < D_OUTDATED)
+ ns.disk = os.disk;
+
rv = __drbd_set_state(mdev, ns, flags, NULL);
if (rv < SS_SUCCESS)
BUG();
diff --git a/drivers/block/drbd/drbd_state.h b/drivers/block/drbd/drbd_state.h
index 11fd0f8..c0331f1 100644
--- a/drivers/block/drbd/drbd_state.h
+++ b/drivers/block/drbd/drbd_state.h
@@ -69,6 +69,7 @@ enum chg_state_flags {
CS_DC_DISK = 1 << 8,
CS_DC_PDSK = 1 << 9,
CS_DC_MASK = CS_DC_ROLE + CS_DC_PEER + CS_DC_CONN + CS_DC_DISK + CS_DC_PDSK,
+ CS_IGN_OUTD_FAIL = 1 << 10,
};
extern enum drbd_state_rv drbd_change_state(struct drbd_conf *mdev,
--
1.7.4.1
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 05/16] drbd: Do not segfault if a sync dependency reaches a diskless device
2011-09-08 12:45 [RFC 00/16] drbd: part 8 of adding multiple volume support to drbd Philipp Reisner
` (3 preceding siblings ...)
2011-09-08 12:45 ` [PATCH 04/16] drbd: Allow to disconnect if one volume is diskless Philipp Reisner
@ 2011-09-08 12:45 ` Philipp Reisner
2011-09-08 12:45 ` [PATCH 06/16] drbd: Pass struct packet_info down to the asender receive functions Philipp Reisner
` (10 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Philipp Reisner @ 2011-09-08 12:45 UTC (permalink / raw)
To: linux-kernel, Jens Axboe; +Cc: drbd-dev
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
---
drivers/block/drbd/drbd_worker.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c
index ed12cdf..829a2ce 100644
--- a/drivers/block/drbd/drbd_worker.c
+++ b/drivers/block/drbd/drbd_worker.c
@@ -1321,6 +1321,8 @@ static int _drbd_may_sync_now(struct drbd_conf *mdev)
struct drbd_conf *odev = mdev;
while (1) {
+ if (!odev->ldev)
+ return 1;
if (odev->ldev->dc.resync_after == -1)
return 1;
odev = minor_to_mdev(odev->ldev->dc.resync_after);
--
1.7.4.1
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 06/16] drbd: Pass struct packet_info down to the asender receive functions
2011-09-08 12:45 [RFC 00/16] drbd: part 8 of adding multiple volume support to drbd Philipp Reisner
` (4 preceding siblings ...)
2011-09-08 12:45 ` [PATCH 05/16] drbd: Do not segfault if a sync dependency reaches a diskless device Philipp Reisner
@ 2011-09-08 12:45 ` Philipp Reisner
2011-09-08 12:45 ` [PATCH 07/16] drbd: Map from (connection, volume number) to device in the asender handlers Philipp Reisner
` (9 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Philipp Reisner @ 2011-09-08 12:45 UTC (permalink / raw)
To: linux-kernel, Jens Axboe; +Cc: drbd-dev
From: Andreas Gruenbacher <agruen@linbit.com>
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
---
drivers/block/drbd/drbd_receiver.c | 36 ++++++++++++++++++------------------
1 files changed, 18 insertions(+), 18 deletions(-)
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index e45a417..5e464a7 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -4462,7 +4462,7 @@ int drbdd_init(struct drbd_thread *thi)
/* ********* acknowledge sender ******** */
-static int got_conn_RqSReply(struct drbd_tconn *tconn, enum drbd_packet cmd)
+static int got_conn_RqSReply(struct drbd_tconn *tconn, struct packet_info *pi)
{
struct p_req_state_reply *p = tconn->meta.rbuf;
int retcode = be32_to_cpu(p->retcode);
@@ -4479,7 +4479,7 @@ static int got_conn_RqSReply(struct drbd_tconn *tconn, enum drbd_packet cmd)
return true;
}
-static int got_RqSReply(struct drbd_conf *mdev, enum drbd_packet cmd)
+static int got_RqSReply(struct drbd_conf *mdev, struct packet_info *pi)
{
struct p_req_state_reply *p = mdev->tconn->meta.rbuf;
int retcode = be32_to_cpu(p->retcode);
@@ -4496,13 +4496,13 @@ static int got_RqSReply(struct drbd_conf *mdev, enum drbd_packet cmd)
return true;
}
-static int got_Ping(struct drbd_tconn *tconn, enum drbd_packet cmd)
+static int got_Ping(struct drbd_tconn *tconn, struct packet_info *pi)
{
return drbd_send_ping_ack(tconn);
}
-static int got_PingAck(struct drbd_tconn *tconn, enum drbd_packet cmd)
+static int got_PingAck(struct drbd_tconn *tconn, struct packet_info *pi)
{
/* restore idle timeout */
tconn->meta.socket->sk->sk_rcvtimeo = tconn->net_conf->ping_int*HZ;
@@ -4512,7 +4512,7 @@ static int got_PingAck(struct drbd_tconn *tconn, enum drbd_packet cmd)
return true;
}
-static int got_IsInSync(struct drbd_conf *mdev, enum drbd_packet cmd)
+static int got_IsInSync(struct drbd_conf *mdev, struct packet_info *pi)
{
struct p_block_ack *p = mdev->tconn->meta.rbuf;
sector_t sector = be64_to_cpu(p->sector);
@@ -4557,7 +4557,7 @@ validate_req_change_req_state(struct drbd_conf *mdev, u64 id, sector_t sector,
return true;
}
-static int got_BlockAck(struct drbd_conf *mdev, enum drbd_packet cmd)
+static int got_BlockAck(struct drbd_conf *mdev, struct packet_info *pi)
{
struct p_block_ack *p = mdev->tconn->meta.rbuf;
sector_t sector = be64_to_cpu(p->sector);
@@ -4571,7 +4571,7 @@ static int got_BlockAck(struct drbd_conf *mdev, enum drbd_packet cmd)
dec_rs_pending(mdev);
return true;
}
- switch (cmd) {
+ switch (pi->cmd) {
case P_RS_WRITE_ACK:
D_ASSERT(mdev->tconn->net_conf->wire_protocol == DRBD_PROT_C);
what = WRITE_ACKED_BY_PEER_AND_SIS;
@@ -4602,7 +4602,7 @@ static int got_BlockAck(struct drbd_conf *mdev, enum drbd_packet cmd)
what, false);
}
-static int got_NegAck(struct drbd_conf *mdev, enum drbd_packet cmd)
+static int got_NegAck(struct drbd_conf *mdev, struct packet_info *pi)
{
struct p_block_ack *p = mdev->tconn->meta.rbuf;
sector_t sector = be64_to_cpu(p->sector);
@@ -4635,7 +4635,7 @@ static int got_NegAck(struct drbd_conf *mdev, enum drbd_packet cmd)
return true;
}
-static int got_NegDReply(struct drbd_conf *mdev, enum drbd_packet cmd)
+static int got_NegDReply(struct drbd_conf *mdev, struct packet_info *pi)
{
struct p_block_ack *p = mdev->tconn->meta.rbuf;
sector_t sector = be64_to_cpu(p->sector);
@@ -4650,7 +4650,7 @@ static int got_NegDReply(struct drbd_conf *mdev, enum drbd_packet cmd)
NEG_ACKED, false);
}
-static int got_NegRSDReply(struct drbd_conf *mdev, enum drbd_packet cmd)
+static int got_NegRSDReply(struct drbd_conf *mdev, struct packet_info *pi)
{
sector_t sector;
int size;
@@ -4665,7 +4665,7 @@ static int got_NegRSDReply(struct drbd_conf *mdev, enum drbd_packet cmd)
if (get_ldev_if_state(mdev, D_FAILED)) {
drbd_rs_complete_io(mdev, sector);
- switch (cmd) {
+ switch (pi->cmd) {
case P_NEG_RS_DREPLY:
drbd_rs_failed_io(mdev, sector, size);
case P_RS_CANCEL:
@@ -4681,7 +4681,7 @@ static int got_NegRSDReply(struct drbd_conf *mdev, enum drbd_packet cmd)
return true;
}
-static int got_BarrierAck(struct drbd_conf *mdev, enum drbd_packet cmd)
+static int got_BarrierAck(struct drbd_conf *mdev, struct packet_info *pi)
{
struct p_barrier_ack *p = mdev->tconn->meta.rbuf;
@@ -4697,7 +4697,7 @@ static int got_BarrierAck(struct drbd_conf *mdev, enum drbd_packet cmd)
return true;
}
-static int got_OVResult(struct drbd_conf *mdev, enum drbd_packet cmd)
+static int got_OVResult(struct drbd_conf *mdev, struct packet_info *pi)
{
struct p_block_ack *p = mdev->tconn->meta.rbuf;
struct drbd_work *w;
@@ -4742,7 +4742,7 @@ static int got_OVResult(struct drbd_conf *mdev, enum drbd_packet cmd)
return true;
}
-static int got_skip(struct drbd_conf *mdev, enum drbd_packet cmd)
+static int got_skip(struct drbd_conf *mdev, struct packet_info *pi)
{
return true;
}
@@ -4777,8 +4777,8 @@ struct asender_cmd {
size_t pkt_size;
enum mdev_or_conn fa_type; /* first argument's type */
union {
- int (*mdev_fn)(struct drbd_conf *mdev, enum drbd_packet cmd);
- int (*conn_fn)(struct drbd_tconn *tconn, enum drbd_packet cmd);
+ int (*mdev_fn)(struct drbd_conf *mdev, struct packet_info *);
+ int (*conn_fn)(struct drbd_tconn *tconn, struct packet_info *);
};
};
@@ -4905,10 +4905,10 @@ int drbd_asender(struct drbd_thread *thi)
bool rv;
if (cmd->fa_type == CONN) {
- rv = cmd->conn_fn(tconn, pi.cmd);
+ rv = cmd->conn_fn(tconn, &pi);
} else {
struct drbd_conf *mdev = vnr_to_mdev(tconn, pi.vnr);
- rv = cmd->mdev_fn(mdev, pi.cmd);
+ rv = cmd->mdev_fn(mdev, &pi);
}
if (!rv)
--
1.7.4.1
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 07/16] drbd: Map from (connection, volume number) to device in the asender handlers
2011-09-08 12:45 [RFC 00/16] drbd: part 8 of adding multiple volume support to drbd Philipp Reisner
` (5 preceding siblings ...)
2011-09-08 12:45 ` [PATCH 06/16] drbd: Pass struct packet_info down to the asender receive functions Philipp Reisner
@ 2011-09-08 12:45 ` Philipp Reisner
2011-09-08 12:45 ` [PATCH 08/16] drbd: drbd_connect(): Initialize struct drbd_socket before sending anything Philipp Reisner
` (8 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Philipp Reisner @ 2011-09-08 12:45 UTC (permalink / raw)
To: linux-kernel, Jens Axboe; +Cc: drbd-dev
From: Andreas Gruenbacher <agruen@linbit.com>
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
---
drivers/block/drbd/drbd_receiver.c | 137 +++++++++++++++++++++--------------
1 files changed, 82 insertions(+), 55 deletions(-)
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index 5e464a7..cc236d7 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -60,11 +60,6 @@ enum finish_epoch {
FE_RECYCLED,
};
-enum mdev_or_conn {
- MDEV,
- CONN,
-};
-
static int drbd_do_handshake(struct drbd_tconn *tconn);
static int drbd_do_auth(struct drbd_tconn *tconn);
static int drbd_disconnected(int vnr, void *p, void *data);
@@ -4479,11 +4474,16 @@ static int got_conn_RqSReply(struct drbd_tconn *tconn, struct packet_info *pi)
return true;
}
-static int got_RqSReply(struct drbd_conf *mdev, struct packet_info *pi)
+static int got_RqSReply(struct drbd_tconn *tconn, struct packet_info *pi)
{
- struct p_req_state_reply *p = mdev->tconn->meta.rbuf;
+ struct drbd_conf *mdev;
+ struct p_req_state_reply *p = tconn->meta.rbuf;
int retcode = be32_to_cpu(p->retcode);
+ mdev = vnr_to_mdev(tconn, pi->vnr);
+ if (!mdev)
+ return false;
+
if (retcode >= SS_SUCCESS) {
set_bit(CL_ST_CHG_SUCCESS, &mdev->flags);
} else {
@@ -4512,12 +4512,17 @@ static int got_PingAck(struct drbd_tconn *tconn, struct packet_info *pi)
return true;
}
-static int got_IsInSync(struct drbd_conf *mdev, struct packet_info *pi)
+static int got_IsInSync(struct drbd_tconn *tconn, struct packet_info *pi)
{
- struct p_block_ack *p = mdev->tconn->meta.rbuf;
+ struct drbd_conf *mdev;
+ struct p_block_ack *p = tconn->meta.rbuf;
sector_t sector = be64_to_cpu(p->sector);
int blksize = be32_to_cpu(p->blksize);
+ mdev = vnr_to_mdev(tconn, pi->vnr);
+ if (!mdev)
+ return false;
+
D_ASSERT(mdev->tconn->agreed_pro_version >= 89);
update_peer_seq(mdev, be32_to_cpu(p->seq_num));
@@ -4557,13 +4562,18 @@ validate_req_change_req_state(struct drbd_conf *mdev, u64 id, sector_t sector,
return true;
}
-static int got_BlockAck(struct drbd_conf *mdev, struct packet_info *pi)
+static int got_BlockAck(struct drbd_tconn *tconn, struct packet_info *pi)
{
- struct p_block_ack *p = mdev->tconn->meta.rbuf;
+ struct drbd_conf *mdev;
+ struct p_block_ack *p = tconn->meta.rbuf;
sector_t sector = be64_to_cpu(p->sector);
int blksize = be32_to_cpu(p->blksize);
enum drbd_req_event what;
+ mdev = vnr_to_mdev(tconn, pi->vnr);
+ if (!mdev)
+ return false;
+
update_peer_seq(mdev, be32_to_cpu(p->seq_num));
if (p->block_id == ID_SYNCER) {
@@ -4602,15 +4612,20 @@ static int got_BlockAck(struct drbd_conf *mdev, struct packet_info *pi)
what, false);
}
-static int got_NegAck(struct drbd_conf *mdev, struct packet_info *pi)
+static int got_NegAck(struct drbd_tconn *tconn, struct packet_info *pi)
{
- struct p_block_ack *p = mdev->tconn->meta.rbuf;
+ struct drbd_conf *mdev;
+ struct p_block_ack *p = tconn->meta.rbuf;
sector_t sector = be64_to_cpu(p->sector);
int size = be32_to_cpu(p->blksize);
- bool missing_ok = mdev->tconn->net_conf->wire_protocol == DRBD_PROT_A ||
- mdev->tconn->net_conf->wire_protocol == DRBD_PROT_B;
+ bool missing_ok = tconn->net_conf->wire_protocol == DRBD_PROT_A ||
+ tconn->net_conf->wire_protocol == DRBD_PROT_B;
bool found;
+ mdev = vnr_to_mdev(tconn, pi->vnr);
+ if (!mdev)
+ return false;
+
update_peer_seq(mdev, be32_to_cpu(p->seq_num));
if (p->block_id == ID_SYNCER) {
@@ -4635,11 +4650,16 @@ static int got_NegAck(struct drbd_conf *mdev, struct packet_info *pi)
return true;
}
-static int got_NegDReply(struct drbd_conf *mdev, struct packet_info *pi)
+static int got_NegDReply(struct drbd_tconn *tconn, struct packet_info *pi)
{
- struct p_block_ack *p = mdev->tconn->meta.rbuf;
+ struct drbd_conf *mdev;
+ struct p_block_ack *p = tconn->meta.rbuf;
sector_t sector = be64_to_cpu(p->sector);
+ mdev = vnr_to_mdev(tconn, pi->vnr);
+ if (!mdev)
+ return false;
+
update_peer_seq(mdev, be32_to_cpu(p->seq_num));
dev_err(DEV, "Got NegDReply; Sector %llus, len %u; Fail original request.\n",
@@ -4650,11 +4670,16 @@ static int got_NegDReply(struct drbd_conf *mdev, struct packet_info *pi)
NEG_ACKED, false);
}
-static int got_NegRSDReply(struct drbd_conf *mdev, struct packet_info *pi)
+static int got_NegRSDReply(struct drbd_tconn *tconn, struct packet_info *pi)
{
+ struct drbd_conf *mdev;
sector_t sector;
int size;
- struct p_block_ack *p = mdev->tconn->meta.rbuf;
+ struct p_block_ack *p = tconn->meta.rbuf;
+
+ mdev = vnr_to_mdev(tconn, pi->vnr);
+ if (!mdev)
+ return false;
sector = be64_to_cpu(p->sector);
size = be32_to_cpu(p->blksize);
@@ -4681,9 +4706,14 @@ static int got_NegRSDReply(struct drbd_conf *mdev, struct packet_info *pi)
return true;
}
-static int got_BarrierAck(struct drbd_conf *mdev, struct packet_info *pi)
+static int got_BarrierAck(struct drbd_tconn *tconn, struct packet_info *pi)
{
- struct p_barrier_ack *p = mdev->tconn->meta.rbuf;
+ struct drbd_conf *mdev;
+ struct p_barrier_ack *p = tconn->meta.rbuf;
+
+ mdev = vnr_to_mdev(tconn, pi->vnr);
+ if (!mdev)
+ return false;
tl_release(mdev->tconn, p->barrier, be32_to_cpu(p->set_size));
@@ -4697,13 +4727,18 @@ static int got_BarrierAck(struct drbd_conf *mdev, struct packet_info *pi)
return true;
}
-static int got_OVResult(struct drbd_conf *mdev, struct packet_info *pi)
+static int got_OVResult(struct drbd_tconn *tconn, struct packet_info *pi)
{
- struct p_block_ack *p = mdev->tconn->meta.rbuf;
+ struct drbd_conf *mdev;
+ struct p_block_ack *p = tconn->meta.rbuf;
struct drbd_work *w;
sector_t sector;
int size;
+ mdev = vnr_to_mdev(tconn, pi->vnr);
+ if (!mdev)
+ return false;
+
sector = be64_to_cpu(p->sector);
size = be32_to_cpu(p->blksize);
@@ -4742,7 +4777,7 @@ static int got_OVResult(struct drbd_conf *mdev, struct packet_info *pi)
return true;
}
-static int got_skip(struct drbd_conf *mdev, struct packet_info *pi)
+static int got_skip(struct drbd_tconn *tconn, struct packet_info *pi)
{
return true;
}
@@ -4775,31 +4810,27 @@ static int tconn_process_done_ee(struct drbd_tconn *tconn)
struct asender_cmd {
size_t pkt_size;
- enum mdev_or_conn fa_type; /* first argument's type */
- union {
- int (*mdev_fn)(struct drbd_conf *mdev, struct packet_info *);
- int (*conn_fn)(struct drbd_tconn *tconn, struct packet_info *);
- };
+ int (*fn)(struct drbd_tconn *tconn, struct packet_info *);
};
static struct asender_cmd asender_tbl[] = {
- [P_PING] = { sizeof(struct p_header), CONN, { .conn_fn = got_Ping } },
- [P_PING_ACK] = { sizeof(struct p_header), CONN, { .conn_fn = got_PingAck } },
- [P_RECV_ACK] = { sizeof(struct p_block_ack), MDEV, { got_BlockAck } },
- [P_WRITE_ACK] = { sizeof(struct p_block_ack), MDEV, { got_BlockAck } },
- [P_RS_WRITE_ACK] = { sizeof(struct p_block_ack), MDEV, { got_BlockAck } },
- [P_DISCARD_WRITE] = { sizeof(struct p_block_ack), MDEV, { got_BlockAck } },
- [P_NEG_ACK] = { sizeof(struct p_block_ack), MDEV, { got_NegAck } },
- [P_NEG_DREPLY] = { sizeof(struct p_block_ack), MDEV, { got_NegDReply } },
- [P_NEG_RS_DREPLY] = { sizeof(struct p_block_ack), MDEV, { got_NegRSDReply } },
- [P_OV_RESULT] = { sizeof(struct p_block_ack), MDEV, { got_OVResult } },
- [P_BARRIER_ACK] = { sizeof(struct p_barrier_ack), MDEV, { got_BarrierAck } },
- [P_STATE_CHG_REPLY] = { sizeof(struct p_req_state_reply), MDEV, { got_RqSReply } },
- [P_RS_IS_IN_SYNC] = { sizeof(struct p_block_ack), MDEV, { got_IsInSync } },
- [P_DELAY_PROBE] = { sizeof(struct p_delay_probe93), MDEV, { got_skip } },
- [P_RS_CANCEL] = { sizeof(struct p_block_ack), MDEV, { got_NegRSDReply } },
- [P_CONN_ST_CHG_REPLY]={ sizeof(struct p_req_state_reply), CONN, {.conn_fn = got_conn_RqSReply}},
- [P_RETRY_WRITE] = { sizeof(struct p_block_ack), MDEV, { got_BlockAck } },
+ [P_PING] = { sizeof(struct p_header), got_Ping },
+ [P_PING_ACK] = { sizeof(struct p_header), got_PingAck },
+ [P_RECV_ACK] = { sizeof(struct p_block_ack), got_BlockAck },
+ [P_WRITE_ACK] = { sizeof(struct p_block_ack), got_BlockAck },
+ [P_RS_WRITE_ACK] = { sizeof(struct p_block_ack), got_BlockAck },
+ [P_DISCARD_WRITE] = { sizeof(struct p_block_ack), got_BlockAck },
+ [P_NEG_ACK] = { sizeof(struct p_block_ack), got_NegAck },
+ [P_NEG_DREPLY] = { sizeof(struct p_block_ack), got_NegDReply },
+ [P_NEG_RS_DREPLY] = { sizeof(struct p_block_ack), got_NegRSDReply },
+ [P_OV_RESULT] = { sizeof(struct p_block_ack), got_OVResult },
+ [P_BARRIER_ACK] = { sizeof(struct p_barrier_ack), got_BarrierAck },
+ [P_STATE_CHG_REPLY] = { sizeof(struct p_req_state_reply), got_RqSReply },
+ [P_RS_IS_IN_SYNC] = { sizeof(struct p_block_ack), got_IsInSync },
+ [P_DELAY_PROBE] = { sizeof(struct p_delay_probe93), got_skip },
+ [P_RS_CANCEL] = { sizeof(struct p_block_ack), got_NegRSDReply },
+ [P_CONN_ST_CHG_REPLY]={ sizeof(struct p_req_state_reply), got_conn_RqSReply },
+ [P_RETRY_WRITE] = { sizeof(struct p_block_ack), got_BlockAck },
};
int drbd_asender(struct drbd_thread *thi)
@@ -4889,7 +4920,7 @@ int drbd_asender(struct drbd_thread *thi)
if (decode_header(tconn, h, &pi))
goto reconnect;
cmd = &asender_tbl[pi.cmd];
- if (pi.cmd >= ARRAY_SIZE(asender_tbl) || !cmd) {
+ if (pi.cmd >= ARRAY_SIZE(asender_tbl) || !cmd->fn) {
conn_err(tconn, "unknown command %d on meta (l: %d)\n",
pi.cmd, pi.size);
goto disconnect;
@@ -4904,15 +4935,11 @@ int drbd_asender(struct drbd_thread *thi)
if (received == expect) {
bool rv;
- if (cmd->fa_type == CONN) {
- rv = cmd->conn_fn(tconn, &pi);
- } else {
- struct drbd_conf *mdev = vnr_to_mdev(tconn, pi.vnr);
- rv = cmd->mdev_fn(mdev, &pi);
- }
-
- if (!rv)
+ rv = cmd->fn(tconn, &pi);
+ if (!rv) {
+ conn_err(tconn, "%pf failed\n", cmd->fn);
goto reconnect;
+ }
tconn->last_received = jiffies;
--
1.7.4.1
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 08/16] drbd: drbd_connect(): Initialize struct drbd_socket before sending anything
2011-09-08 12:45 [RFC 00/16] drbd: part 8 of adding multiple volume support to drbd Philipp Reisner
` (6 preceding siblings ...)
2011-09-08 12:45 ` [PATCH 07/16] drbd: Map from (connection, volume number) to device in the asender handlers Philipp Reisner
@ 2011-09-08 12:45 ` Philipp Reisner
2011-09-08 12:45 ` [PATCH 09/16] drbd: _conn_send_cmd(), _drbd_send_cmd(): Pass a struct drbd_socket instead of a plain socket Philipp Reisner
` (7 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Philipp Reisner @ 2011-09-08 12:45 UTC (permalink / raw)
To: linux-kernel, Jens Axboe; +Cc: drbd-dev
From: Andreas Gruenbacher <agruen@linbit.com>
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
---
drivers/block/drbd/drbd_receiver.c | 66 ++++++++++++++++++-----------------
1 files changed, 34 insertions(+), 32 deletions(-)
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index cc236d7..830b107 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -807,7 +807,7 @@ int drbd_connected(int vnr, void *p, void *data)
*/
static int drbd_connect(struct drbd_tconn *tconn)
{
- struct socket *s, *sock, *msock;
+ struct socket *sock, *msock;
int try, h, ok;
if (conn_request_state(tconn, NS(conn, C_WF_CONNECTION), CS_VERBOSE) < SS_SUCCESS)
@@ -818,10 +818,9 @@ static int drbd_connect(struct drbd_tconn *tconn)
/* Assume that the peer only understands protocol 80 until we know better. */
tconn->agreed_pro_version = 80;
- sock = NULL;
- msock = NULL;
-
do {
+ struct socket *s;
+
for (try = 0;;) {
/* 3 tries, this should take less than a second! */
s = drbd_try_connect(tconn);
@@ -832,24 +831,22 @@ static int drbd_connect(struct drbd_tconn *tconn)
}
if (s) {
- if (!sock) {
- drbd_send_fp(tconn, s, P_HAND_SHAKE_S);
- sock = s;
- s = NULL;
- } else if (!msock) {
- drbd_send_fp(tconn, s, P_HAND_SHAKE_M);
- msock = s;
- s = NULL;
+ if (!tconn->data.socket) {
+ tconn->data.socket = s;
+ drbd_send_fp(tconn, tconn->data.socket, P_HAND_SHAKE_S);
+ } else if (!tconn->meta.socket) {
+ tconn->meta.socket = s;
+ drbd_send_fp(tconn, tconn->meta.socket, P_HAND_SHAKE_M);
} else {
conn_err(tconn, "Logic error in drbd_connect()\n");
goto out_release_sockets;
}
}
- if (sock && msock) {
+ if (tconn->data.socket && tconn->meta.socket) {
schedule_timeout_interruptible(tconn->net_conf->ping_timeo*HZ/10);
- ok = drbd_socket_okay(&sock);
- ok = drbd_socket_okay(&msock) && ok;
+ ok = drbd_socket_okay(&tconn->data.socket);
+ ok = drbd_socket_okay(&tconn->meta.socket) && ok;
if (ok)
break;
}
@@ -858,22 +855,22 @@ retry:
s = drbd_wait_for_connect(tconn);
if (s) {
try = drbd_recv_fp(tconn, s);
- drbd_socket_okay(&sock);
- drbd_socket_okay(&msock);
+ drbd_socket_okay(&tconn->data.socket);
+ drbd_socket_okay(&tconn->meta.socket);
switch (try) {
case P_HAND_SHAKE_S:
- if (sock) {
+ if (tconn->data.socket) {
conn_warn(tconn, "initial packet S crossed\n");
- sock_release(sock);
+ sock_release(tconn->data.socket);
}
- sock = s;
+ tconn->data.socket = s;
break;
case P_HAND_SHAKE_M:
- if (msock) {
+ if (tconn->meta.socket) {
conn_warn(tconn, "initial packet M crossed\n");
- sock_release(msock);
+ sock_release(tconn->meta.socket);
}
- msock = s;
+ tconn->meta.socket = s;
set_bit(DISCARD_CONCURRENT, &tconn->flags);
break;
default:
@@ -893,14 +890,17 @@ retry:
goto out_release_sockets;
}
- if (sock && msock) {
- ok = drbd_socket_okay(&sock);
- ok = drbd_socket_okay(&msock) && ok;
+ if (tconn->data.socket && &tconn->meta.socket) {
+ ok = drbd_socket_okay(&tconn->data.socket);
+ ok = drbd_socket_okay(&tconn->meta.socket) && ok;
if (ok)
break;
}
} while (1);
+ sock = tconn->data.socket;
+ msock = tconn->meta.socket;
+
msock->sk->sk_reuse = 1; /* SO_REUSEADDR */
sock->sk->sk_reuse = 1; /* SO_REUSEADDR */
@@ -926,8 +926,6 @@ retry:
drbd_tcp_nodelay(sock);
drbd_tcp_nodelay(msock);
- tconn->data.socket = sock;
- tconn->meta.socket = msock;
tconn->last_received = jiffies;
h = drbd_do_handshake(tconn);
@@ -960,10 +958,14 @@ retry:
return !idr_for_each(&tconn->volumes, drbd_connected, tconn);
out_release_sockets:
- if (sock)
- sock_release(sock);
- if (msock)
- sock_release(msock);
+ if (tconn->data.socket) {
+ sock_release(tconn->data.socket);
+ tconn->data.socket = NULL;
+ }
+ if (tconn->meta.socket) {
+ sock_release(tconn->meta.socket);
+ tconn->meta.socket = NULL;
+ }
return -1;
}
--
1.7.4.1
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 09/16] drbd: _conn_send_cmd(), _drbd_send_cmd(): Pass a struct drbd_socket instead of a plain socket
2011-09-08 12:45 [RFC 00/16] drbd: part 8 of adding multiple volume support to drbd Philipp Reisner
` (7 preceding siblings ...)
2011-09-08 12:45 ` [PATCH 08/16] drbd: drbd_connect(): Initialize struct drbd_socket before sending anything Philipp Reisner
@ 2011-09-08 12:45 ` Philipp Reisner
2011-09-08 12:45 ` [PATCH 10/16] drbd: Change how the initial packets are called Philipp Reisner
` (6 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Philipp Reisner @ 2011-09-08 12:45 UTC (permalink / raw)
To: linux-kernel, Jens Axboe; +Cc: drbd-dev
From: Andreas Gruenbacher <agruen@linbit.com>
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
---
drivers/block/drbd/drbd_int.h | 4 ++--
drivers/block/drbd/drbd_main.c | 22 +++++++++++-----------
drivers/block/drbd/drbd_receiver.c | 16 ++++++++--------
drivers/block/drbd/drbd_worker.c | 2 +-
4 files changed, 22 insertions(+), 22 deletions(-)
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index 984b2a3..4ee6fc5 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -1113,7 +1113,7 @@ extern int _conn_send_state_req(struct drbd_tconn *, int vnr, enum drbd_packet c
union drbd_state, union drbd_state);
extern int _drbd_send_state(struct drbd_conf *mdev);
extern int drbd_send_state(struct drbd_conf *mdev);
-extern int _conn_send_cmd(struct drbd_tconn *tconn, int vnr, struct socket *sock,
+extern int _conn_send_cmd(struct drbd_tconn *tconn, int vnr, struct drbd_socket *sock,
enum drbd_packet cmd, struct p_header *h, size_t size,
unsigned msg_flags);
extern int conn_send_cmd(struct drbd_tconn *tconn, int vnr, struct drbd_socket *sock,
@@ -1860,7 +1860,7 @@ static inline void request_ping(struct drbd_tconn *tconn)
wake_asender(tconn);
}
-static inline int _drbd_send_cmd(struct drbd_conf *mdev, struct socket *sock,
+static inline int _drbd_send_cmd(struct drbd_conf *mdev, struct drbd_socket *sock,
enum drbd_packet cmd, struct p_header *h, size_t size,
unsigned msg_flags)
{
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index ea06d31..05960ab 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -719,14 +719,14 @@ static void prepare_header(struct drbd_conf *mdev, struct p_header *h,
}
/* the appropriate socket mutex must be held already */
-int _conn_send_cmd(struct drbd_tconn *tconn, int vnr, struct socket *sock,
+int _conn_send_cmd(struct drbd_tconn *tconn, int vnr, struct drbd_socket *sock,
enum drbd_packet cmd, struct p_header *h, size_t size,
unsigned msg_flags)
{
int err;
_prepare_header(tconn, vnr, h, cmd, size - sizeof(struct p_header));
- err = drbd_send_all(tconn, sock, h, size, msg_flags);
+ err = drbd_send_all(tconn, sock->socket, h, size, msg_flags);
if (err && !signal_pending(current))
conn_warn(tconn, "short send %s size=%d\n",
cmdname(cmd), (int)size);
@@ -743,7 +743,7 @@ int conn_send_cmd(struct drbd_tconn *tconn, int vnr, struct drbd_socket *sock,
mutex_lock(&sock->mutex);
if (sock->socket)
- err = _conn_send_cmd(tconn, vnr, sock->socket, cmd, h, size, 0);
+ err = _conn_send_cmd(tconn, vnr, sock, cmd, h, size, 0);
mutex_unlock(&sock->mutex);
return err;
}
@@ -780,7 +780,7 @@ int drbd_send_ping_ack(struct drbd_tconn *tconn)
int drbd_send_sync_param(struct drbd_conf *mdev)
{
struct p_rs_param_95 *p;
- struct socket *sock;
+ struct drbd_socket *sock;
int size, err;
const int apv = mdev->tconn->agreed_pro_version;
@@ -791,9 +791,9 @@ int drbd_send_sync_param(struct drbd_conf *mdev)
: /* apv >= 95 */ sizeof(struct p_rs_param_95);
mutex_lock(&mdev->tconn->data.mutex);
- sock = mdev->tconn->data.socket;
+ sock = &mdev->tconn->data;
- if (likely(sock != NULL)) {
+ if (likely(sock->socket != NULL)) {
enum drbd_packet cmd =
apv >= 89 ? P_SYNC_PARAM89 : P_SYNC_PARAM;
@@ -979,16 +979,16 @@ int drbd_send_sizes(struct drbd_conf *mdev, int trigger_reply, enum dds_flags fl
*/
int drbd_send_state(struct drbd_conf *mdev)
{
- struct socket *sock;
+ struct drbd_socket *sock;
struct p_state p;
int err = -EIO;
mutex_lock(&mdev->tconn->data.mutex);
p.state = cpu_to_be32(mdev->state.i); /* Within the send mutex */
- sock = mdev->tconn->data.socket;
+ sock = &mdev->tconn->data;
- if (likely(sock != NULL))
+ if (likely(sock->socket != NULL))
err = _drbd_send_cmd(mdev, sock, P_STATE, &p.head, sizeof(p), 0);
mutex_unlock(&mdev->tconn->data.mutex);
@@ -1157,7 +1157,7 @@ send_bitmap_rle_or_plain(struct drbd_conf *mdev, struct bm_xfer_ctx *c)
if (len) {
dcbp_set_code(p, RLE_VLI_Bits);
- err = _drbd_send_cmd(mdev, mdev->tconn->data.socket,
+ err = _drbd_send_cmd(mdev, &mdev->tconn->data,
P_COMPRESSED_BITMAP, &p->head,
sizeof(*p) + len, 0);
@@ -1175,7 +1175,7 @@ send_bitmap_rle_or_plain(struct drbd_conf *mdev, struct bm_xfer_ctx *c)
if (len)
drbd_bm_get_lel(mdev, c->word_offset, num_words,
(unsigned long *)h->payload);
- err = _drbd_send_cmd(mdev, mdev->tconn->data.socket, P_BITMAP,
+ err = _drbd_send_cmd(mdev, &mdev->tconn->data, P_BITMAP,
h, sizeof(struct p_header80) + len, 0);
c->word_offset += num_words;
c->bit_offset = c->word_offset * BITS_PER_LONG;
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index 830b107..80d85af 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -729,7 +729,7 @@ out:
return s_estab;
}
-static int drbd_send_fp(struct drbd_tconn *tconn, struct socket *sock, enum drbd_packet cmd)
+static int drbd_send_fp(struct drbd_tconn *tconn, struct drbd_socket *sock, enum drbd_packet cmd)
{
struct p_header *h = tconn->data.sbuf;
@@ -738,13 +738,13 @@ static int drbd_send_fp(struct drbd_tconn *tconn, struct socket *sock, enum drbd
static enum drbd_packet drbd_recv_fp(struct drbd_tconn *tconn, struct socket *sock)
{
- struct p_header80 *h = tconn->data.rbuf;
+ struct p_header80 h;
int rr;
- rr = drbd_recv_short(sock, h, sizeof(*h), 0);
+ rr = drbd_recv_short(sock, &h, sizeof(h), 0);
- if (rr == sizeof(*h) && h->magic == cpu_to_be32(DRBD_MAGIC))
- return be16_to_cpu(h->command);
+ if (rr == sizeof(h) && h.magic == cpu_to_be32(DRBD_MAGIC))
+ return be16_to_cpu(h.command);
return 0xffff;
}
@@ -833,10 +833,10 @@ static int drbd_connect(struct drbd_tconn *tconn)
if (s) {
if (!tconn->data.socket) {
tconn->data.socket = s;
- drbd_send_fp(tconn, tconn->data.socket, P_HAND_SHAKE_S);
+ drbd_send_fp(tconn, &tconn->data, P_HAND_SHAKE_S);
} else if (!tconn->meta.socket) {
tconn->meta.socket = s;
- drbd_send_fp(tconn, tconn->meta.socket, P_HAND_SHAKE_M);
+ drbd_send_fp(tconn, &tconn->meta, P_HAND_SHAKE_M);
} else {
conn_err(tconn, "Logic error in drbd_connect()\n");
goto out_release_sockets;
@@ -4198,7 +4198,7 @@ static int drbd_send_handshake(struct drbd_tconn *tconn)
memset(p, 0, sizeof(*p));
p->protocol_min = cpu_to_be32(PRO_VERSION_MIN);
p->protocol_max = cpu_to_be32(PRO_VERSION_MAX);
- err = _conn_send_cmd(tconn, 0, tconn->data.socket, P_HAND_SHAKE,
+ err = _conn_send_cmd(tconn, 0, &tconn->data, P_HAND_SHAKE,
&p->head, sizeof(*p), 0);
mutex_unlock(&tconn->data.mutex);
return err;
diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c
index 829a2ce..3f7d27c 100644
--- a/drivers/block/drbd/drbd_worker.c
+++ b/drivers/block/drbd/drbd_worker.c
@@ -1217,7 +1217,7 @@ int w_send_barrier(struct drbd_work *w, int cancel)
/* inc_ap_pending was done where this was queued.
* dec_ap_pending will be done in got_BarrierAck
* or (on connection loss) in w_clear_epoch. */
- err = _drbd_send_cmd(mdev, mdev->tconn->data.socket, P_BARRIER,
+ err = _drbd_send_cmd(mdev, &mdev->tconn->data, P_BARRIER,
&p->head, sizeof(*p), 0);
drbd_put_data_sock(mdev->tconn);
--
1.7.4.1
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 10/16] drbd: Change how the initial packets are called
2011-09-08 12:45 [RFC 00/16] drbd: part 8 of adding multiple volume support to drbd Philipp Reisner
` (8 preceding siblings ...)
2011-09-08 12:45 ` [PATCH 09/16] drbd: _conn_send_cmd(), _drbd_send_cmd(): Pass a struct drbd_socket instead of a plain socket Philipp Reisner
@ 2011-09-08 12:45 ` Philipp Reisner
2011-09-08 12:45 ` [PATCH 11/16] drbd: Change how the "handshake" " Philipp Reisner
` (5 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Philipp Reisner @ 2011-09-08 12:45 UTC (permalink / raw)
To: linux-kernel, Jens Axboe; +Cc: drbd-dev
From: Andreas Gruenbacher <agruen@linbit.com>
The first packets exchanged when a connection is established are
referred to as P_HAND_SHAKE_S and P_HAND_SHAKE_M in the code, followed
by P_HAND_SHAKE packets. To avoid confusion between these two unrelated
things, call the initial packets P_INITIAL_DATA and P_INITIAL_META.
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
---
drivers/block/drbd/drbd_int.h | 4 ++--
drivers/block/drbd/drbd_main.c | 8 ++++----
drivers/block/drbd/drbd_receiver.c | 8 ++++----
3 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index 4ee6fc5..33cc132 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -232,8 +232,8 @@ enum drbd_packet {
/* special command ids for handshake */
- P_HAND_SHAKE_M = 0xfff1, /* First Packet on the MetaSock */
- P_HAND_SHAKE_S = 0xfff2, /* First Packet on the Socket */
+ P_INITIAL_META = 0xfff1, /* First Packet on the MetaSock */
+ P_INITIAL_DATA = 0xfff2, /* First Packet on the Socket */
P_HAND_SHAKE = 0xfffe /* FIXED for the next century! */
};
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index 05960ab..3df84ad 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -3147,10 +3147,10 @@ const char *cmdname(enum drbd_packet cmd)
[P_RETRY_WRITE] = "RetryWrite",
};
- if (cmd == P_HAND_SHAKE_M)
- return "HandShakeM";
- if (cmd == P_HAND_SHAKE_S)
- return "HandShakeS";
+ if (cmd == P_INITIAL_META)
+ return "InitialMeta";
+ if (cmd == P_INITIAL_DATA)
+ return "InitialData";
if (cmd == P_HAND_SHAKE)
return "HandShake";
if (cmd >= ARRAY_SIZE(cmdnames))
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index 80d85af..865c6e9 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -833,10 +833,10 @@ static int drbd_connect(struct drbd_tconn *tconn)
if (s) {
if (!tconn->data.socket) {
tconn->data.socket = s;
- drbd_send_fp(tconn, &tconn->data, P_HAND_SHAKE_S);
+ drbd_send_fp(tconn, &tconn->data, P_INITIAL_DATA);
} else if (!tconn->meta.socket) {
tconn->meta.socket = s;
- drbd_send_fp(tconn, &tconn->meta, P_HAND_SHAKE_M);
+ drbd_send_fp(tconn, &tconn->meta, P_INITIAL_META);
} else {
conn_err(tconn, "Logic error in drbd_connect()\n");
goto out_release_sockets;
@@ -858,14 +858,14 @@ retry:
drbd_socket_okay(&tconn->data.socket);
drbd_socket_okay(&tconn->meta.socket);
switch (try) {
- case P_HAND_SHAKE_S:
+ case P_INITIAL_DATA:
if (tconn->data.socket) {
conn_warn(tconn, "initial packet S crossed\n");
sock_release(tconn->data.socket);
}
tconn->data.socket = s;
break;
- case P_HAND_SHAKE_M:
+ case P_INITIAL_META:
if (tconn->meta.socket) {
conn_warn(tconn, "initial packet M crossed\n");
sock_release(tconn->meta.socket);
--
1.7.4.1
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 11/16] drbd: Change how the "handshake" packets are called
2011-09-08 12:45 [RFC 00/16] drbd: part 8 of adding multiple volume support to drbd Philipp Reisner
` (9 preceding siblings ...)
2011-09-08 12:45 ` [PATCH 10/16] drbd: Change how the initial packets are called Philipp Reisner
@ 2011-09-08 12:45 ` Philipp Reisner
2011-09-08 12:45 ` [PATCH 12/16] drbd: introduce the "initialized" activity log transaction type Philipp Reisner
` (4 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Philipp Reisner @ 2011-09-08 12:45 UTC (permalink / raw)
To: linux-kernel, Jens Axboe; +Cc: drbd-dev
From: Andreas Gruenbacher <agruen@linbit.com>
Packets of type P_HAND_SHAKE define which protocol versions and features
a node supports. For clarity, call those packets P_CONNECTION_FEATURES
instead.
(This does not determine the features that a specific drbd device
supports, such as drbd protocol A, B, C.)
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
---
drivers/block/drbd/drbd_int.h | 6 +++---
drivers/block/drbd/drbd_main.c | 6 +++---
drivers/block/drbd/drbd_receiver.c | 26 +++++++++++++-------------
3 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index 33cc132..7b4203c 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -235,7 +235,7 @@ enum drbd_packet {
P_INITIAL_META = 0xfff1, /* First Packet on the MetaSock */
P_INITIAL_DATA = 0xfff2, /* First Packet on the Socket */
- P_HAND_SHAKE = 0xfffe /* FIXED for the next century! */
+ P_CONNECTION_FEATURES = 0xfffe /* FIXED for the next century! */
};
extern const char *cmdname(enum drbd_packet cmd);
@@ -374,14 +374,14 @@ struct p_block_req {
/*
* commands with their own struct for additional fields:
- * P_HAND_SHAKE
+ * P_CONNECTION_FEATURES
* P_BARRIER
* P_BARRIER_ACK
* P_SYNC_PARAM
* ReportParams
*/
-struct p_handshake {
+struct p_connection_features {
struct p_header head; /* Note: vnr will be ignored */
u32 protocol_min;
u32 feature_flags;
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index 3df84ad..a773d73 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -2499,7 +2499,7 @@ int __init drbd_init(void)
int err;
BUILD_BUG_ON(sizeof(struct p_header80) != sizeof(struct p_header95));
- BUILD_BUG_ON(sizeof(struct p_handshake) != 80);
+ BUILD_BUG_ON(sizeof(struct p_connection_features) != 80);
if (minor_count < DRBD_MINOR_COUNT_MIN || minor_count > DRBD_MINOR_COUNT_MAX) {
printk(KERN_ERR
@@ -3151,8 +3151,8 @@ const char *cmdname(enum drbd_packet cmd)
return "InitialMeta";
if (cmd == P_INITIAL_DATA)
return "InitialData";
- if (cmd == P_HAND_SHAKE)
- return "HandShake";
+ if (cmd == P_CONNECTION_FEATURES)
+ return "ConnectionFeatures";
if (cmd >= ARRAY_SIZE(cmdnames))
return "Unknown";
return cmdnames[cmd];
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index 865c6e9..619a172 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -60,7 +60,7 @@ enum finish_epoch {
FE_RECYCLED,
};
-static int drbd_do_handshake(struct drbd_tconn *tconn);
+static int drbd_do_features(struct drbd_tconn *tconn);
static int drbd_do_auth(struct drbd_tconn *tconn);
static int drbd_disconnected(int vnr, void *p, void *data);
@@ -913,7 +913,7 @@ retry:
/* NOT YET ...
* sock->sk->sk_sndtimeo = tconn->net_conf->timeout*HZ/10;
* sock->sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT;
- * first set it to the P_HAND_SHAKE timeout,
+ * first set it to the P_CONNECTION_FEATURES timeout,
* which we set to 4x the configured ping_timeout. */
sock->sk->sk_sndtimeo =
sock->sk->sk_rcvtimeo = tconn->net_conf->ping_timeo*4*HZ/10;
@@ -928,7 +928,7 @@ retry:
tconn->last_received = jiffies;
- h = drbd_do_handshake(tconn);
+ h = drbd_do_features(tconn);
if (h <= 0)
return h;
@@ -4179,10 +4179,10 @@ static int drbd_disconnected(int vnr, void *p, void *data)
*
* for now, they are expected to be zero, but ignored.
*/
-static int drbd_send_handshake(struct drbd_tconn *tconn)
+static int drbd_send_features(struct drbd_tconn *tconn)
{
/* ASSERT current == mdev->tconn->receiver ... */
- struct p_handshake *p = tconn->data.sbuf;
+ struct p_connection_features *p = tconn->data.sbuf;
int err;
if (mutex_lock_interruptible(&tconn->data.mutex)) {
@@ -4198,7 +4198,7 @@ static int drbd_send_handshake(struct drbd_tconn *tconn)
memset(p, 0, sizeof(*p));
p->protocol_min = cpu_to_be32(PRO_VERSION_MIN);
p->protocol_max = cpu_to_be32(PRO_VERSION_MAX);
- err = _conn_send_cmd(tconn, 0, &tconn->data, P_HAND_SHAKE,
+ err = _conn_send_cmd(tconn, 0, &tconn->data, P_CONNECTION_FEATURES,
&p->head, sizeof(*p), 0);
mutex_unlock(&tconn->data.mutex);
return err;
@@ -4211,15 +4211,15 @@ static int drbd_send_handshake(struct drbd_tconn *tconn)
* -1 peer talks different language,
* no point in trying again, please go standalone.
*/
-static int drbd_do_handshake(struct drbd_tconn *tconn)
+static int drbd_do_features(struct drbd_tconn *tconn)
{
/* ASSERT current == tconn->receiver ... */
- struct p_handshake *p = tconn->data.rbuf;
- const int expect = sizeof(struct p_handshake) - sizeof(struct p_header80);
+ struct p_connection_features *p = tconn->data.rbuf;
+ const int expect = sizeof(struct p_connection_features) - sizeof(struct p_header80);
struct packet_info pi;
int err;
- err = drbd_send_handshake(tconn);
+ err = drbd_send_features(tconn);
if (err)
return 0;
@@ -4227,14 +4227,14 @@ static int drbd_do_handshake(struct drbd_tconn *tconn)
if (err)
return 0;
- if (pi.cmd != P_HAND_SHAKE) {
- conn_err(tconn, "expected HandShake packet, received: %s (0x%04x)\n",
+ if (pi.cmd != P_CONNECTION_FEATURES) {
+ conn_err(tconn, "expected ConnectionFeatures packet, received: %s (0x%04x)\n",
cmdname(pi.cmd), pi.cmd);
return -1;
}
if (pi.size != expect) {
- conn_err(tconn, "expected HandShake length: %u, received: %u\n",
+ conn_err(tconn, "expected ConnectionFeatures length: %u, received: %u\n",
expect, pi.size);
return -1;
}
--
1.7.4.1
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 12/16] drbd: introduce the "initialized" activity log transaction type
2011-09-08 12:45 [RFC 00/16] drbd: part 8 of adding multiple volume support to drbd Philipp Reisner
` (10 preceding siblings ...)
2011-09-08 12:45 ` [PATCH 11/16] drbd: Change how the "handshake" " Philipp Reisner
@ 2011-09-08 12:45 ` Philipp Reisner
2011-09-08 12:45 ` [PATCH 13/16] drbd: preparation commit, pass drbd_interval to drbd_al_begin/complete_io Philipp Reisner
` (3 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Philipp Reisner @ 2011-09-08 12:45 UTC (permalink / raw)
To: linux-kernel, Jens Axboe; +Cc: drbd-dev
From: Lars Ellenberg <lars.ellenberg@linbit.com>
So we can initialize a clean on disk activity log area,
without the module complaining with loud assert messages
because of checksum or magic value mismatches.
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
---
drivers/block/drbd/drbd_actlog.c | 16 ++++++++++++++--
1 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c
index 9c9929a..643a7bd 100644
--- a/drivers/block/drbd/drbd_actlog.c
+++ b/drivers/block/drbd/drbd_actlog.c
@@ -31,6 +31,11 @@
#include "drbd_int.h"
#include "drbd_wrappers.h"
+
+enum al_transaction_types {
+ AL_TR_UPDATE = 0,
+ AL_TR_INITIALIZED = 0xffff
+};
/* all fields on disc in big endian */
struct __packed al_transaction_on_disk {
/* don't we all like magic */
@@ -44,7 +49,8 @@ struct __packed al_transaction_on_disk {
__be32 crc32c;
/* type of transaction, special transaction types like:
- * purge-all, set-all-idle, set-all-active, ... to-be-defined */
+ * purge-all, set-all-idle, set-all-active, ... to-be-defined
+ * see also enum al_transaction_types */
__be16 transaction_type;
/* we currently allow only a few thousand extents,
@@ -466,6 +472,7 @@ int drbd_al_read_log(struct drbd_conf *mdev, struct drbd_backing_dev *bdev)
int active_extents = 0;
int transactions = 0;
int found_valid = 0;
+ int found_initialized = 0;
int from = 0;
int to = 0;
u32 from_tnr = 0;
@@ -494,6 +501,10 @@ int drbd_al_read_log(struct drbd_conf *mdev, struct drbd_backing_dev *bdev)
/* invalid data in that block */
if (rv == 0)
continue;
+ if (be16_to_cpu(b->transaction_type) == AL_TR_INITIALIZED) {
+ ++found_initialized;
+ continue;
+ }
/* IO error */
if (rv == -1) {
@@ -525,7 +536,8 @@ int drbd_al_read_log(struct drbd_conf *mdev, struct drbd_backing_dev *bdev)
}
if (!found_valid) {
- dev_warn(DEV, "No usable activity log found.\n");
+ if (found_initialized != mx)
+ dev_warn(DEV, "No usable activity log found.\n");
mutex_unlock(&mdev->md_io_mutex);
return 1;
}
--
1.7.4.1
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 13/16] drbd: preparation commit, pass drbd_interval to drbd_al_begin/complete_io
2011-09-08 12:45 [RFC 00/16] drbd: part 8 of adding multiple volume support to drbd Philipp Reisner
` (11 preceding siblings ...)
2011-09-08 12:45 ` [PATCH 12/16] drbd: introduce the "initialized" activity log transaction type Philipp Reisner
@ 2011-09-08 12:45 ` Philipp Reisner
2011-09-08 12:45 ` [PATCH 14/16] drbd: prepare to activate two activity log extents at once Philipp Reisner
` (2 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Philipp Reisner @ 2011-09-08 12:45 UTC (permalink / raw)
To: linux-kernel, Jens Axboe; +Cc: drbd-dev
From: Lars Ellenberg <lars.ellenberg@linbit.com>
We want to avoid bio_split for bios crossing activity log boundaries.
So we may need to activate two activity log extents "atomically".
drbd_al_begin_io() needs to know more than just the start sector.
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
---
drivers/block/drbd/drbd_actlog.c | 8 ++++----
drivers/block/drbd/drbd_int.h | 4 ++--
drivers/block/drbd/drbd_receiver.c | 4 ++--
drivers/block/drbd/drbd_req.c | 12 ++++++------
drivers/block/drbd/drbd_worker.c | 10 +++++-----
5 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c
index 643a7bd..df78810 100644
--- a/drivers/block/drbd/drbd_actlog.c
+++ b/drivers/block/drbd/drbd_actlog.c
@@ -205,9 +205,9 @@ static struct lc_element *_al_get(struct drbd_conf *mdev, unsigned int enr)
return al_ext;
}
-void drbd_al_begin_io(struct drbd_conf *mdev, sector_t sector)
+void drbd_al_begin_io(struct drbd_conf *mdev, struct drbd_interval *i)
{
- unsigned int enr = (sector >> (AL_EXTENT_SHIFT-9));
+ unsigned int enr = (i->sector >> (AL_EXTENT_SHIFT-9));
struct lc_element *al_ext;
struct update_al_work al_work;
@@ -254,9 +254,9 @@ void drbd_al_begin_io(struct drbd_conf *mdev, sector_t sector)
}
}
-void drbd_al_complete_io(struct drbd_conf *mdev, sector_t sector)
+void drbd_al_complete_io(struct drbd_conf *mdev, struct drbd_interval *i)
{
- unsigned int enr = (sector >> (AL_EXTENT_SHIFT-9));
+ unsigned int enr = (i->sector >> (AL_EXTENT_SHIFT-9));
struct lc_element *extent;
unsigned long flags;
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index 7b4203c..218e2c3 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -1584,8 +1584,8 @@ extern const char *drbd_conn_str(enum drbd_conns s);
extern const char *drbd_role_str(enum drbd_role s);
/* drbd_actlog.c */
-extern void drbd_al_begin_io(struct drbd_conf *mdev, sector_t sector);
-extern void drbd_al_complete_io(struct drbd_conf *mdev, sector_t sector);
+extern void drbd_al_begin_io(struct drbd_conf *mdev, struct drbd_interval *i);
+extern void drbd_al_complete_io(struct drbd_conf *mdev, struct drbd_interval *i);
extern void drbd_rs_complete_io(struct drbd_conf *mdev, sector_t sector);
extern int drbd_rs_begin_io(struct drbd_conf *mdev, sector_t sector);
extern int drbd_try_rs_begin_io(struct drbd_conf *mdev, sector_t sector);
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index 619a172..0b51f29 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -2064,7 +2064,7 @@ static int receive_Data(struct drbd_tconn *tconn, struct packet_info *pi)
drbd_set_out_of_sync(mdev, peer_req->i.sector, peer_req->i.size);
peer_req->flags |= EE_CALL_AL_COMPLETE_IO;
peer_req->flags &= ~EE_MAY_SET_IN_SYNC;
- drbd_al_begin_io(mdev, peer_req->i.sector);
+ drbd_al_begin_io(mdev, &peer_req->i);
}
err = drbd_submit_peer_request(mdev, peer_req, rw, DRBD_FAULT_DT_WR);
@@ -2078,7 +2078,7 @@ static int receive_Data(struct drbd_tconn *tconn, struct packet_info *pi)
drbd_remove_epoch_entry_interval(mdev, peer_req);
spin_unlock_irq(&mdev->tconn->req_lock);
if (peer_req->flags & EE_CALL_AL_COMPLETE_IO)
- drbd_al_complete_io(mdev, peer_req->i.sector);
+ drbd_al_complete_io(mdev, &peer_req->i);
out_interrupted:
drbd_may_finish_epoch(mdev, peer_req->epoch, EV_PUT + EV_CLEANUP);
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index e380ffb..4406d82 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -128,12 +128,12 @@ static void _req_is_done(struct drbd_conf *mdev, struct drbd_request *req, const
if (s & RQ_LOCAL_MASK) {
if (get_ldev_if_state(mdev, D_FAILED)) {
if (s & RQ_IN_ACT_LOG)
- drbd_al_complete_io(mdev, req->i.sector);
+ drbd_al_complete_io(mdev, &req->i);
put_ldev(mdev);
} else if (__ratelimit(&drbd_ratelimit_state)) {
- dev_warn(DEV, "Should have called drbd_al_complete_io(, %llu), "
- "but my Disk seems to have failed :(\n",
- (unsigned long long) req->i.sector);
+ dev_warn(DEV, "Should have called drbd_al_complete_io(, %llu, %u), "
+ "but my Disk seems to have failed :(\n",
+ (unsigned long long) req->i.sector, req->i.size);
}
}
}
@@ -782,7 +782,7 @@ int __drbd_make_request(struct drbd_conf *mdev, struct bio *bio, unsigned long s
* of transactional on-disk meta data updates. */
if (rw == WRITE && local && !test_bit(AL_SUSPENDED, &mdev->flags)) {
req->rq_state |= RQ_IN_ACT_LOG;
- drbd_al_begin_io(mdev, sector);
+ drbd_al_begin_io(mdev, &req->i);
}
remote = remote && drbd_should_do_remote(mdev->state);
@@ -979,7 +979,7 @@ allocate_barrier:
fail_free_complete:
if (req->rq_state & RQ_IN_ACT_LOG)
- drbd_al_complete_io(mdev, sector);
+ drbd_al_complete_io(mdev, &req->i);
fail_and_free_req:
if (local) {
bio_put(req->private_bio);
diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c
index 3f7d27c..640d04a 100644
--- a/drivers/block/drbd/drbd_worker.c
+++ b/drivers/block/drbd/drbd_worker.c
@@ -101,7 +101,7 @@ static void drbd_endio_write_sec_final(struct drbd_peer_request *peer_req) __rel
{
unsigned long flags = 0;
struct drbd_conf *mdev = peer_req->w.mdev;
- sector_t e_sector;
+ struct drbd_interval i;
int do_wake;
u64 block_id;
int do_al_complete_io;
@@ -110,7 +110,7 @@ static void drbd_endio_write_sec_final(struct drbd_peer_request *peer_req) __rel
* we may no longer access it,
* it may be freed/reused already!
* (as soon as we release the req_lock) */
- e_sector = peer_req->i.sector;
+ i = peer_req->i;
do_al_complete_io = peer_req->flags & EE_CALL_AL_COMPLETE_IO;
block_id = peer_req->block_id;
@@ -134,13 +134,13 @@ static void drbd_endio_write_sec_final(struct drbd_peer_request *peer_req) __rel
spin_unlock_irqrestore(&mdev->tconn->req_lock, flags);
if (block_id == ID_SYNCER)
- drbd_rs_complete_io(mdev, e_sector);
+ drbd_rs_complete_io(mdev, i.sector);
if (do_wake)
wake_up(&mdev->ee_wait);
if (do_al_complete_io)
- drbd_al_complete_io(mdev, e_sector);
+ drbd_al_complete_io(mdev, &i);
wake_asender(mdev->tconn);
put_ldev(mdev);
@@ -1303,7 +1303,7 @@ int w_restart_disk_io(struct drbd_work *w, int cancel)
struct drbd_conf *mdev = w->mdev;
if (bio_data_dir(req->master_bio) == WRITE && req->rq_state & RQ_IN_ACT_LOG)
- drbd_al_begin_io(mdev, req->i.sector);
+ drbd_al_begin_io(mdev, &req->i);
/* Calling drbd_al_begin_io() out of the worker might deadlocks
theoretically. Practically it can not deadlock, since this is
only used when unfreezing IOs. All the extents of the requests
--
1.7.4.1
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 14/16] drbd: prepare to activate two activity log extents at once
2011-09-08 12:45 [RFC 00/16] drbd: part 8 of adding multiple volume support to drbd Philipp Reisner
` (12 preceding siblings ...)
2011-09-08 12:45 ` [PATCH 13/16] drbd: preparation commit, pass drbd_interval to drbd_al_begin/complete_io Philipp Reisner
@ 2011-09-08 12:45 ` Philipp Reisner
2011-09-08 12:45 ` [PATCH 15/16] drbd: get rid of bio_split, allow bios of "arbitrary" size Philipp Reisner
2011-09-08 12:45 ` [PATCH 16/16] drbd: improvements to activate/deactivate multiple activity log extents Philipp Reisner
15 siblings, 0 replies; 17+ messages in thread
From: Philipp Reisner @ 2011-09-08 12:45 UTC (permalink / raw)
To: linux-kernel, Jens Axboe; +Cc: drbd-dev
From: Lars Ellenberg <lars.ellenberg@linbit.com>
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
---
drivers/block/drbd/drbd_actlog.c | 18 +++++++++++++-----
1 files changed, 13 insertions(+), 5 deletions(-)
diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c
index df78810..1e3ddd7 100644
--- a/drivers/block/drbd/drbd_actlog.c
+++ b/drivers/block/drbd/drbd_actlog.c
@@ -207,15 +207,22 @@ static struct lc_element *_al_get(struct drbd_conf *mdev, unsigned int enr)
void drbd_al_begin_io(struct drbd_conf *mdev, struct drbd_interval *i)
{
- unsigned int enr = (i->sector >> (AL_EXTENT_SHIFT-9));
- struct lc_element *al_ext;
+ /* for bios crossing activity log extent boundaries,
+ * we may need to activate two extents in one go */
+ unsigned int enr[2];
+ struct lc_element *al_ext[2] = { NULL, NULL };
struct update_al_work al_work;
D_ASSERT(atomic_read(&mdev->local_cnt) > 0);
- wait_event(mdev->al_wait, (al_ext = _al_get(mdev, enr)));
+ enr[0] = i->sector >> (AL_EXTENT_SHIFT-9);
+ enr[1] = (i->sector + (i->size >> 9) - 1) >> (AL_EXTENT_SHIFT-9);
+ wait_event(mdev->al_wait, (al_ext[0] = _al_get(mdev, enr[0])));
+ if (enr[0] != enr[1])
+ wait_event(mdev->al_wait, (al_ext[1] = _al_get(mdev, enr[1])));
- if (al_ext->lc_number != enr) {
+ if (al_ext[0]->lc_number != enr[0] ||
+ (al_ext[1] && al_ext[1]->lc_number != enr[1])) {
/* drbd_al_write_transaction(mdev,al_ext,enr);
* recurses into generic_make_request(), which
* disallows recursion, bios being serialized on the
@@ -232,7 +239,8 @@ void drbd_al_begin_io(struct drbd_conf *mdev, struct drbd_interval *i)
/* Double check: it may have been committed by someone else,
* while we have been waiting for the lock. */
- if (al_ext->lc_number != enr) {
+ if (al_ext[0]->lc_number != enr[0] ||
+ (al_ext[1] && al_ext[1]->lc_number != enr[1])) {
init_completion(&al_work.event);
al_work.w.cb = w_al_write_transaction;
al_work.w.mdev = mdev;
--
1.7.4.1
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 15/16] drbd: get rid of bio_split, allow bios of "arbitrary" size
2011-09-08 12:45 [RFC 00/16] drbd: part 8 of adding multiple volume support to drbd Philipp Reisner
` (13 preceding siblings ...)
2011-09-08 12:45 ` [PATCH 14/16] drbd: prepare to activate two activity log extents at once Philipp Reisner
@ 2011-09-08 12:45 ` Philipp Reisner
2011-09-08 12:45 ` [PATCH 16/16] drbd: improvements to activate/deactivate multiple activity log extents Philipp Reisner
15 siblings, 0 replies; 17+ messages in thread
From: Philipp Reisner @ 2011-09-08 12:45 UTC (permalink / raw)
To: linux-kernel, Jens Axboe; +Cc: drbd-dev
From: Lars Ellenberg <lars.ellenberg@linbit.com>
Where "arbitrary" size is currently 1 MiB, which is the BIO_MAX_SIZE
for architectures with 4k PAGE_CACHE_SIZE (most).
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
---
drivers/block/drbd/drbd_int.h | 20 ++++++---
drivers/block/drbd/drbd_req.c | 92 ++++++----------------------------------
2 files changed, 28 insertions(+), 84 deletions(-)
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index 218e2c3..54eb96a 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -1326,8 +1326,16 @@ struct bm_extent {
#endif
#endif
-#define HT_SHIFT 8
-#define DRBD_MAX_BIO_SIZE (1U<<(9+HT_SHIFT))
+/* BIO_MAX_SIZE is 256 * PAGE_CACHE_SIZE,
+ * so for typical PAGE_CACHE_SIZE of 4k, that is (1<<20) Byte.
+ * Since we may live in a mixed-platform cluster,
+ * we limit us to a platform agnostic constant here for now.
+ * A followup commit may allow even bigger BIO sizes,
+ * once we thought that through. */
+#define DRBD_MAX_BIO_SIZE (1 << 20)
+#if DRBD_MAX_BIO_SIZE > BIO_MAX_SIZE
+#error Architecture not supported: DRBD_MAX_BIO_SIZE > BIO_MAX_SIZE
+#endif
#define DRBD_MAX_BIO_SIZE_SAFE (1 << 12) /* Works always = 4k */
#define DRBD_MAX_SIZE_H80_PACKET (1 << 15) /* The old header only allows packets up to 32Kib data */
@@ -2231,20 +2239,20 @@ static inline bool may_inc_ap_bio(struct drbd_conf *mdev)
return true;
}
-static inline bool inc_ap_bio_cond(struct drbd_conf *mdev, int count)
+static inline bool inc_ap_bio_cond(struct drbd_conf *mdev)
{
bool rv = false;
spin_lock_irq(&mdev->tconn->req_lock);
rv = may_inc_ap_bio(mdev);
if (rv)
- atomic_add(count, &mdev->ap_bio_cnt);
+ atomic_inc(&mdev->ap_bio_cnt);
spin_unlock_irq(&mdev->tconn->req_lock);
return rv;
}
-static inline void inc_ap_bio(struct drbd_conf *mdev, int count)
+static inline void inc_ap_bio(struct drbd_conf *mdev)
{
/* we wait here
* as long as the device is suspended
@@ -2254,7 +2262,7 @@ static inline void inc_ap_bio(struct drbd_conf *mdev, int count)
* to avoid races with the reconnect code,
* we need to atomic_inc within the spinlock. */
- wait_event(mdev->misc_wait, inc_ap_bio_cond(mdev, count));
+ wait_event(mdev->misc_wait, inc_ap_bio_cond(mdev));
}
static inline void dec_ap_bio(struct drbd_conf *mdev)
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index 4406d82..6e0e3bb 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -998,7 +998,6 @@ fail_and_free_req:
int drbd_make_request(struct request_queue *q, struct bio *bio)
{
- unsigned int s_enr, e_enr;
struct drbd_conf *mdev = (struct drbd_conf *) q->queuedata;
unsigned long start_time;
@@ -1010,93 +1009,30 @@ int drbd_make_request(struct request_queue *q, struct bio *bio)
D_ASSERT(bio->bi_size > 0);
D_ASSERT(IS_ALIGNED(bio->bi_size, 512));
- /* to make some things easier, force alignment of requests within the
- * granularity of our hash tables */
- s_enr = bio->bi_sector >> HT_SHIFT;
- e_enr = (bio->bi_sector+(bio->bi_size>>9)-1) >> HT_SHIFT;
-
- if (likely(s_enr == e_enr)) {
- inc_ap_bio(mdev, 1);
- return __drbd_make_request(mdev, bio, start_time);
- }
-
- /* can this bio be split generically?
- * Maybe add our own split-arbitrary-bios function. */
- if (bio->bi_vcnt != 1 || bio->bi_idx != 0 || bio->bi_size > DRBD_MAX_BIO_SIZE) {
- /* rather error out here than BUG in bio_split */
- dev_err(DEV, "bio would need to, but cannot, be split: "
- "(vcnt=%u,idx=%u,size=%u,sector=%llu)\n",
- bio->bi_vcnt, bio->bi_idx, bio->bi_size,
- (unsigned long long)bio->bi_sector);
- bio_endio(bio, -EINVAL);
- } else {
- /* This bio crosses some boundary, so we have to split it. */
- struct bio_pair *bp;
- /* works for the "do not cross hash slot boundaries" case
- * e.g. sector 262269, size 4096
- * s_enr = 262269 >> 6 = 4097
- * e_enr = (262269+8-1) >> 6 = 4098
- * HT_SHIFT = 6
- * sps = 64, mask = 63
- * first_sectors = 64 - (262269 & 63) = 3
- */
- const sector_t sect = bio->bi_sector;
- const int sps = 1 << HT_SHIFT; /* sectors per slot */
- const int mask = sps - 1;
- const sector_t first_sectors = sps - (sect & mask);
- bp = bio_split(bio, first_sectors);
-
- /* we need to get a "reference count" (ap_bio_cnt)
- * to avoid races with the disconnect/reconnect/suspend code.
- * In case we need to split the bio here, we need to get three references
- * atomically, otherwise we might deadlock when trying to submit the
- * second one! */
- inc_ap_bio(mdev, 3);
-
- D_ASSERT(e_enr == s_enr + 1);
-
- while (__drbd_make_request(mdev, &bp->bio1, start_time))
- inc_ap_bio(mdev, 1);
-
- while (__drbd_make_request(mdev, &bp->bio2, start_time))
- inc_ap_bio(mdev, 1);
-
- dec_ap_bio(mdev);
-
- bio_pair_release(bp);
- }
- return 0;
+ inc_ap_bio(mdev);
+ return __drbd_make_request(mdev, bio, start_time);
}
-/* This is called by bio_add_page(). With this function we reduce
- * the number of BIOs that span over multiple DRBD_MAX_BIO_SIZEs
- * units (was AL_EXTENTs).
+/* This is called by bio_add_page().
+ *
+ * q->max_hw_sectors and other global limits are already enforced there.
*
- * we do the calculation within the lower 32bit of the byte offsets,
- * since we don't care for actual offset, but only check whether it
- * would cross "activity log extent" boundaries.
+ * We need to call down to our lower level device,
+ * in case it has special restrictions.
+ *
+ * We also may need to enforce configured max-bio-bvecs limits.
*
* As long as the BIO is empty we have to allow at least one bvec,
- * regardless of size and offset. so the resulting bio may still
- * cross extent boundaries. those are dealt with (bio_split) in
- * drbd_make_request.
+ * regardless of size and offset, so no need to ask lower levels.
*/
int drbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bvm, struct bio_vec *bvec)
{
struct drbd_conf *mdev = (struct drbd_conf *) q->queuedata;
- unsigned int bio_offset =
- (unsigned int)bvm->bi_sector << 9; /* 32 bit */
unsigned int bio_size = bvm->bi_size;
- int limit, backing_limit;
-
- limit = DRBD_MAX_BIO_SIZE
- - ((bio_offset & (DRBD_MAX_BIO_SIZE-1)) + bio_size);
- if (limit < 0)
- limit = 0;
- if (bio_size == 0) {
- if (limit <= bvec->bv_len)
- limit = bvec->bv_len;
- } else if (limit && get_ldev(mdev)) {
+ int limit = DRBD_MAX_BIO_SIZE;
+ int backing_limit;
+
+ if (bio_size && get_ldev(mdev)) {
struct request_queue * const b =
mdev->ldev->backing_bdev->bd_disk->queue;
if (b->merge_bvec_fn) {
--
1.7.4.1
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 16/16] drbd: improvements to activate/deactivate multiple activity log extents
2011-09-08 12:45 [RFC 00/16] drbd: part 8 of adding multiple volume support to drbd Philipp Reisner
` (14 preceding siblings ...)
2011-09-08 12:45 ` [PATCH 15/16] drbd: get rid of bio_split, allow bios of "arbitrary" size Philipp Reisner
@ 2011-09-08 12:45 ` Philipp Reisner
15 siblings, 0 replies; 17+ messages in thread
From: Philipp Reisner @ 2011-09-08 12:45 UTC (permalink / raw)
To: linux-kernel, Jens Axboe; +Cc: drbd-dev
From: Lars Ellenberg <lars.ellenberg@linbit.com>
Recent commit drbd: get rid of bio_split, allow bios of "arbitrary" size
had a reference count leak: it only deactivated the first of several
activity log extents for intervals crossing extent boundaries.
This commit generalizes on bios spanning multiple activity log extents
in drbd_al_begin_io, and adds the necessary loop around lc_put in
drbd_al_complete_io as well.
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
---
drivers/block/drbd/drbd_actlog.c | 46 +++++++++++++++++++-------------------
1 files changed, 23 insertions(+), 23 deletions(-)
diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c
index 1e3ddd7..7eacc03 100644
--- a/drivers/block/drbd/drbd_actlog.c
+++ b/drivers/block/drbd/drbd_actlog.c
@@ -209,20 +209,16 @@ void drbd_al_begin_io(struct drbd_conf *mdev, struct drbd_interval *i)
{
/* for bios crossing activity log extent boundaries,
* we may need to activate two extents in one go */
- unsigned int enr[2];
- struct lc_element *al_ext[2] = { NULL, NULL };
- struct update_al_work al_work;
+ unsigned first = i->sector >> (AL_EXTENT_SHIFT-9);
+ unsigned last = (i->sector + (i->size >> 9) - 1) >> (AL_EXTENT_SHIFT-9);
+ unsigned enr;
D_ASSERT(atomic_read(&mdev->local_cnt) > 0);
- enr[0] = i->sector >> (AL_EXTENT_SHIFT-9);
- enr[1] = (i->sector + (i->size >> 9) - 1) >> (AL_EXTENT_SHIFT-9);
- wait_event(mdev->al_wait, (al_ext[0] = _al_get(mdev, enr[0])));
- if (enr[0] != enr[1])
- wait_event(mdev->al_wait, (al_ext[1] = _al_get(mdev, enr[1])));
+ for (enr = first; enr <= last; enr++)
+ wait_event(mdev->al_wait, _al_get(mdev, enr) != NULL);
- if (al_ext[0]->lc_number != enr[0] ||
- (al_ext[1] && al_ext[1]->lc_number != enr[1])) {
+ if (mdev->act_log->pending_changes) {
/* drbd_al_write_transaction(mdev,al_ext,enr);
* recurses into generic_make_request(), which
* disallows recursion, bios being serialized on the
@@ -239,8 +235,8 @@ void drbd_al_begin_io(struct drbd_conf *mdev, struct drbd_interval *i)
/* Double check: it may have been committed by someone else,
* while we have been waiting for the lock. */
- if (al_ext[0]->lc_number != enr[0] ||
- (al_ext[1] && al_ext[1]->lc_number != enr[1])) {
+ if (mdev->act_log->pending_changes) {
+ struct update_al_work al_work;
init_completion(&al_work.event);
al_work.w.cb = w_al_write_transaction;
al_work.w.mdev = mdev;
@@ -264,24 +260,28 @@ void drbd_al_begin_io(struct drbd_conf *mdev, struct drbd_interval *i)
void drbd_al_complete_io(struct drbd_conf *mdev, struct drbd_interval *i)
{
- unsigned int enr = (i->sector >> (AL_EXTENT_SHIFT-9));
+ /* for bios crossing activity log extent boundaries,
+ * we may need to activate two extents in one go */
+ unsigned first = i->sector >> (AL_EXTENT_SHIFT-9);
+ unsigned last = (i->sector + (i->size >> 9) - 1) >> (AL_EXTENT_SHIFT-9);
+ unsigned enr;
struct lc_element *extent;
unsigned long flags;
+ bool wake = false;
spin_lock_irqsave(&mdev->al_lock, flags);
- extent = lc_find(mdev->act_log, enr);
-
- if (!extent) {
- spin_unlock_irqrestore(&mdev->al_lock, flags);
- dev_err(DEV, "al_complete_io() called on inactive extent %u\n", enr);
- return;
+ for (enr = first; enr <= last; enr++) {
+ extent = lc_find(mdev->act_log, enr);
+ if (!extent) {
+ dev_err(DEV, "al_complete_io() called on inactive extent %u\n", enr);
+ continue;
+ }
+ if (lc_put(mdev->act_log, extent) == 0)
+ wake = true;
}
-
- if (lc_put(mdev->act_log, extent) == 0)
- wake_up(&mdev->al_wait);
-
spin_unlock_irqrestore(&mdev->al_lock, flags);
+ wake_up(&mdev->al_wait);
}
#if (PAGE_SHIFT + 3) < (AL_EXTENT_SHIFT - BM_BLOCK_SHIFT)
--
1.7.4.1
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2011-09-08 12:50 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-09-08 12:45 [RFC 00/16] drbd: part 8 of adding multiple volume support to drbd Philipp Reisner
2011-09-08 12:45 ` [PATCH 01/16] drbd: Use the idr_for_each_entry() iterator instead of idr_for_each() Philipp Reisner
2011-09-08 12:45 ` [PATCH 02/16] drbd: Fixed logging of old connection state Philipp Reisner
2011-09-08 12:45 ` [PATCH 03/16] drbd: Print common state changes of all volumes as connection state changes Philipp Reisner
2011-09-08 12:45 ` [PATCH 04/16] drbd: Allow to disconnect if one volume is diskless Philipp Reisner
2011-09-08 12:45 ` [PATCH 05/16] drbd: Do not segfault if a sync dependency reaches a diskless device Philipp Reisner
2011-09-08 12:45 ` [PATCH 06/16] drbd: Pass struct packet_info down to the asender receive functions Philipp Reisner
2011-09-08 12:45 ` [PATCH 07/16] drbd: Map from (connection, volume number) to device in the asender handlers Philipp Reisner
2011-09-08 12:45 ` [PATCH 08/16] drbd: drbd_connect(): Initialize struct drbd_socket before sending anything Philipp Reisner
2011-09-08 12:45 ` [PATCH 09/16] drbd: _conn_send_cmd(), _drbd_send_cmd(): Pass a struct drbd_socket instead of a plain socket Philipp Reisner
2011-09-08 12:45 ` [PATCH 10/16] drbd: Change how the initial packets are called Philipp Reisner
2011-09-08 12:45 ` [PATCH 11/16] drbd: Change how the "handshake" " Philipp Reisner
2011-09-08 12:45 ` [PATCH 12/16] drbd: introduce the "initialized" activity log transaction type Philipp Reisner
2011-09-08 12:45 ` [PATCH 13/16] drbd: preparation commit, pass drbd_interval to drbd_al_begin/complete_io Philipp Reisner
2011-09-08 12:45 ` [PATCH 14/16] drbd: prepare to activate two activity log extents at once Philipp Reisner
2011-09-08 12:45 ` [PATCH 15/16] drbd: get rid of bio_split, allow bios of "arbitrary" size Philipp Reisner
2011-09-08 12:45 ` [PATCH 16/16] drbd: improvements to activate/deactivate multiple activity log extents Philipp Reisner
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®