drbd: struct drbd_request: Introduce a new collision flag
This flag is set when a processes puts itself to sleep to wait for a conflicting request to complete. Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com> Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
This commit is contained in:
parent
9e204cddaf
commit
a500c2efbb
@ -1815,6 +1815,7 @@ static int receive_Data(struct drbd_conf *mdev, enum drbd_packet cmd,
|
||||
first = 1;
|
||||
for (;;) {
|
||||
struct drbd_interval *i;
|
||||
struct drbd_request *req2;
|
||||
int have_unacked = 0;
|
||||
int have_conflict = 0;
|
||||
prepare_to_wait(&mdev->misc_wait, &wait,
|
||||
@ -1822,8 +1823,7 @@ static int receive_Data(struct drbd_conf *mdev, enum drbd_packet cmd,
|
||||
|
||||
i = drbd_find_overlap(&mdev->write_requests, sector, size);
|
||||
if (i) {
|
||||
struct drbd_request *req2 =
|
||||
container_of(i, struct drbd_request, i);
|
||||
req2 = container_of(i, struct drbd_request, i);
|
||||
|
||||
/* only ALERT on first iteration,
|
||||
* we may be woken up early... */
|
||||
@ -1869,6 +1869,9 @@ static int receive_Data(struct drbd_conf *mdev, enum drbd_packet cmd,
|
||||
goto out_interrupted;
|
||||
}
|
||||
|
||||
/* Indicate to wake up mdev->misc_wait upon completion. */
|
||||
req2->rq_state |= RQ_COLLISION;
|
||||
|
||||
spin_unlock_irq(&mdev->tconn->req_lock);
|
||||
if (first) {
|
||||
first = 0;
|
||||
|
@ -176,45 +176,9 @@ static void _about_to_complete_local_write(struct drbd_conf *mdev,
|
||||
req->epoch == mdev->tconn->newest_tle->br_number)
|
||||
queue_barrier(mdev);
|
||||
|
||||
/* we need to do the conflict detection stuff,
|
||||
* if the epoch_entries tree is non-empty and
|
||||
* this request has completed on the network */
|
||||
if ((s & RQ_NET_DONE) && !RB_EMPTY_ROOT(&mdev->epoch_entries)) {
|
||||
const sector_t sector = req->i.sector;
|
||||
const int size = req->i.size;
|
||||
struct drbd_interval *i;
|
||||
|
||||
/* ASSERT:
|
||||
* there must be no conflicting requests, since
|
||||
* they must have been failed on the spot */
|
||||
|
||||
i = drbd_find_overlap(&mdev->write_requests, sector, size);
|
||||
if (i) {
|
||||
struct drbd_request *req2 =
|
||||
container_of(i, struct drbd_request, i);
|
||||
|
||||
dev_alert(DEV, "LOGIC BUG: completed: %p %llus +%u; "
|
||||
"other: %p %llus +%u\n",
|
||||
req, (unsigned long long)sector, size,
|
||||
i, (unsigned long long)req2->i.sector, req2->i.size);
|
||||
}
|
||||
|
||||
/* maybe "wake" those conflicting epoch entries
|
||||
* that wait for this request to finish.
|
||||
*
|
||||
* currently, there can be only _one_ such ee
|
||||
* (well, or some more, which would be pending
|
||||
* P_DISCARD_ACK not yet sent by the asender...),
|
||||
* since we block the receiver thread upon the
|
||||
* first conflict detection, which will wait on
|
||||
* misc_wait. maybe we want to assert that?
|
||||
*
|
||||
* anyways, if we found one,
|
||||
* we just have to do a wake_up. */
|
||||
i = drbd_find_overlap(&mdev->epoch_entries, sector, size);
|
||||
if (i)
|
||||
wake_up(&mdev->misc_wait);
|
||||
}
|
||||
/* Wake up any processes waiting for this request to complete. */
|
||||
if ((s & RQ_NET_DONE) && (s & RQ_COLLISION))
|
||||
wake_up(&mdev->misc_wait);
|
||||
}
|
||||
|
||||
void complete_master_bio(struct drbd_conf *mdev,
|
||||
|
@ -194,6 +194,12 @@ enum drbd_req_state_bits {
|
||||
|
||||
/* Should call drbd_al_complete_io() for this request... */
|
||||
__RQ_IN_ACT_LOG,
|
||||
|
||||
/*
|
||||
* Set when a processes puts itself to sleep to wait for this request
|
||||
* to complete.
|
||||
*/
|
||||
__RQ_COLLISION,
|
||||
};
|
||||
|
||||
#define RQ_LOCAL_PENDING (1UL << __RQ_LOCAL_PENDING)
|
||||
@ -214,6 +220,7 @@ enum drbd_req_state_bits {
|
||||
|
||||
#define RQ_WRITE (1UL << __RQ_WRITE)
|
||||
#define RQ_IN_ACT_LOG (1UL << __RQ_IN_ACT_LOG)
|
||||
#define RQ_COLLISION (1UL << __RQ_COLLISION)
|
||||
|
||||
/* For waking up the frozen transfer log mod_req() has to return if the request
|
||||
should be counted in the epoch object*/
|
||||
|
Loading…
Reference in New Issue
Block a user