mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [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, &params);
+		rv = conn_is_valid_transition(tconn, mask, val, CS_NO_CSTATE_CHG, &params);
 
-	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, &params);
-
-	if (rv == 0)  /* idr_for_each semantics */
-		rv = SS_SUCCESS;
-
+	rv = conn_is_valid_transition(tconn, mask, val, flags, &params);
 	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, &params);
+
+	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, &params);
+		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, &params);
+	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®