diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/block/drbd/drbd_interval.h | 1 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_receiver.c | 35 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_req.c | 23 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_req.h | 7 |
4 files changed, 41 insertions, 25 deletions
diff --git a/drivers/block/drbd/drbd_interval.h b/drivers/block/drbd/drbd_interval.h index a847b4a07b25..9d1e5eb2d7eb 100644 --- a/drivers/block/drbd/drbd_interval.h +++ b/drivers/block/drbd/drbd_interval.h | |||
@@ -9,6 +9,7 @@ struct drbd_interval { | |||
9 | sector_t sector; /* start sector of the interval */ | 9 | sector_t sector; /* start sector of the interval */ |
10 | unsigned int size; /* size in bytes */ | 10 | unsigned int size; /* size in bytes */ |
11 | sector_t end; /* highest interval end in subtree */ | 11 | sector_t end; /* highest interval end in subtree */ |
12 | int waiting:1; | ||
12 | }; | 13 | }; |
13 | 14 | ||
14 | static inline void drbd_clear_interval(struct drbd_interval *i) | 15 | static inline void drbd_clear_interval(struct drbd_interval *i) |
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index d9f3f7fd9bb2..b84a9c9fd3f8 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c | |||
@@ -334,13 +334,15 @@ struct drbd_epoch_entry *drbd_alloc_ee(struct drbd_conf *mdev, | |||
334 | goto fail; | 334 | goto fail; |
335 | 335 | ||
336 | drbd_clear_interval(&e->i); | 336 | drbd_clear_interval(&e->i); |
337 | e->i.size = data_size; | ||
338 | e->i.sector = sector; | ||
339 | e->i.waiting = false; | ||
340 | |||
337 | e->epoch = NULL; | 341 | e->epoch = NULL; |
338 | e->mdev = mdev; | 342 | e->mdev = mdev; |
339 | e->pages = page; | 343 | e->pages = page; |
340 | atomic_set(&e->pending_bios, 0); | 344 | atomic_set(&e->pending_bios, 0); |
341 | e->i.size = data_size; | ||
342 | e->flags = 0; | 345 | e->flags = 0; |
343 | e->i.sector = sector; | ||
344 | /* | 346 | /* |
345 | * The block_id is opaque to the receiver. It is not endianness | 347 | * The block_id is opaque to the receiver. It is not endianness |
346 | * converted, and sent back to the sender unchanged. | 348 | * converted, and sent back to the sender unchanged. |
@@ -1172,6 +1174,19 @@ fail: | |||
1172 | return err; | 1174 | return err; |
1173 | } | 1175 | } |
1174 | 1176 | ||
1177 | static void drbd_remove_epoch_entry_interval(struct drbd_conf *mdev, | ||
1178 | struct drbd_epoch_entry *e) | ||
1179 | { | ||
1180 | struct drbd_interval *i = &e->i; | ||
1181 | |||
1182 | drbd_remove_interval(&mdev->write_requests, i); | ||
1183 | drbd_clear_interval(i); | ||
1184 | |||
1185 | /* Wake up any processes waiting for this epoch entry to complete. */ | ||
1186 | if (i->waiting) | ||
1187 | wake_up(&mdev->misc_wait); | ||
1188 | } | ||
1189 | |||
1175 | static int receive_Barrier(struct drbd_conf *mdev, enum drbd_packet cmd, | 1190 | static int receive_Barrier(struct drbd_conf *mdev, enum drbd_packet cmd, |
1176 | unsigned int data_size) | 1191 | unsigned int data_size) |
1177 | { | 1192 | { |
@@ -1591,8 +1606,7 @@ static int e_end_block(struct drbd_conf *mdev, struct drbd_work *w, int cancel) | |||
1591 | if (mdev->tconn->net_conf->two_primaries) { | 1606 | if (mdev->tconn->net_conf->two_primaries) { |
1592 | spin_lock_irq(&mdev->tconn->req_lock); | 1607 | spin_lock_irq(&mdev->tconn->req_lock); |
1593 | D_ASSERT(!drbd_interval_empty(&e->i)); | 1608 | D_ASSERT(!drbd_interval_empty(&e->i)); |
1594 | drbd_remove_interval(&mdev->epoch_entries, &e->i); | 1609 | drbd_remove_epoch_entry_interval(mdev, e); |
1595 | drbd_clear_interval(&e->i); | ||
1596 | spin_unlock_irq(&mdev->tconn->req_lock); | 1610 | spin_unlock_irq(&mdev->tconn->req_lock); |
1597 | } else | 1611 | } else |
1598 | D_ASSERT(drbd_interval_empty(&e->i)); | 1612 | D_ASSERT(drbd_interval_empty(&e->i)); |
@@ -1612,8 +1626,7 @@ static int e_send_discard_ack(struct drbd_conf *mdev, struct drbd_work *w, int u | |||
1612 | 1626 | ||
1613 | spin_lock_irq(&mdev->tconn->req_lock); | 1627 | spin_lock_irq(&mdev->tconn->req_lock); |
1614 | D_ASSERT(!drbd_interval_empty(&e->i)); | 1628 | D_ASSERT(!drbd_interval_empty(&e->i)); |
1615 | drbd_remove_interval(&mdev->epoch_entries, &e->i); | 1629 | drbd_remove_epoch_entry_interval(mdev, e); |
1616 | drbd_clear_interval(&e->i); | ||
1617 | spin_unlock_irq(&mdev->tconn->req_lock); | 1630 | spin_unlock_irq(&mdev->tconn->req_lock); |
1618 | 1631 | ||
1619 | dec_unacked(mdev); | 1632 | dec_unacked(mdev); |
@@ -1860,17 +1873,14 @@ static int receive_Data(struct drbd_conf *mdev, enum drbd_packet cmd, | |||
1860 | } | 1873 | } |
1861 | 1874 | ||
1862 | if (signal_pending(current)) { | 1875 | if (signal_pending(current)) { |
1863 | drbd_remove_interval(&mdev->epoch_entries, &e->i); | 1876 | drbd_remove_epoch_entry_interval(mdev, e); |
1864 | drbd_clear_interval(&e->i); | ||
1865 | |||
1866 | spin_unlock_irq(&mdev->tconn->req_lock); | 1877 | spin_unlock_irq(&mdev->tconn->req_lock); |
1867 | |||
1868 | finish_wait(&mdev->misc_wait, &wait); | 1878 | finish_wait(&mdev->misc_wait, &wait); |
1869 | goto out_interrupted; | 1879 | goto out_interrupted; |
1870 | } | 1880 | } |
1871 | 1881 | ||
1872 | /* Indicate to wake up mdev->misc_wait upon completion. */ | 1882 | /* Indicate to wake up mdev->misc_wait upon completion. */ |
1873 | req2->rq_state |= RQ_COLLISION; | 1883 | i->waiting = true; |
1874 | 1884 | ||
1875 | spin_unlock_irq(&mdev->tconn->req_lock); | 1885 | spin_unlock_irq(&mdev->tconn->req_lock); |
1876 | if (first) { | 1886 | if (first) { |
@@ -1922,8 +1932,7 @@ static int receive_Data(struct drbd_conf *mdev, enum drbd_packet cmd, | |||
1922 | dev_err(DEV, "submit failed, triggering re-connect\n"); | 1932 | dev_err(DEV, "submit failed, triggering re-connect\n"); |
1923 | spin_lock_irq(&mdev->tconn->req_lock); | 1933 | spin_lock_irq(&mdev->tconn->req_lock); |
1924 | list_del(&e->w.list); | 1934 | list_del(&e->w.list); |
1925 | drbd_remove_interval(&mdev->epoch_entries, &e->i); | 1935 | drbd_remove_epoch_entry_interval(mdev, e); |
1926 | drbd_clear_interval(&e->i); | ||
1927 | spin_unlock_irq(&mdev->tconn->req_lock); | 1936 | spin_unlock_irq(&mdev->tconn->req_lock); |
1928 | if (e->flags & EE_CALL_AL_COMPLETE_IO) | 1937 | if (e->flags & EE_CALL_AL_COMPLETE_IO) |
1929 | drbd_al_complete_io(mdev, e->i.sector); | 1938 | drbd_al_complete_io(mdev, e->i.sector); |
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index 8b4ba94538bd..078f77ba68fb 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c | |||
@@ -70,9 +70,12 @@ static struct drbd_request *drbd_req_new(struct drbd_conf *mdev, | |||
70 | req->mdev = mdev; | 70 | req->mdev = mdev; |
71 | req->master_bio = bio_src; | 71 | req->master_bio = bio_src; |
72 | req->epoch = 0; | 72 | req->epoch = 0; |
73 | |||
73 | drbd_clear_interval(&req->i); | 74 | drbd_clear_interval(&req->i); |
74 | req->i.sector = bio_src->bi_sector; | 75 | req->i.sector = bio_src->bi_sector; |
75 | req->i.size = bio_src->bi_size; | 76 | req->i.size = bio_src->bi_size; |
77 | req->i.waiting = false; | ||
78 | |||
76 | INIT_LIST_HEAD(&req->tl_requests); | 79 | INIT_LIST_HEAD(&req->tl_requests); |
77 | INIT_LIST_HEAD(&req->w.list); | 80 | INIT_LIST_HEAD(&req->w.list); |
78 | 81 | ||
@@ -175,10 +178,6 @@ static void _about_to_complete_local_write(struct drbd_conf *mdev, | |||
175 | (s & RQ_NET_SENT) != 0 && | 178 | (s & RQ_NET_SENT) != 0 && |
176 | req->epoch == mdev->tconn->newest_tle->br_number) | 179 | req->epoch == mdev->tconn->newest_tle->br_number) |
177 | queue_barrier(mdev); | 180 | queue_barrier(mdev); |
178 | |||
179 | /* Wake up any processes waiting for this request to complete. */ | ||
180 | if ((s & RQ_NET_DONE) && (s & RQ_COLLISION)) | ||
181 | wake_up(&mdev->misc_wait); | ||
182 | } | 181 | } |
183 | 182 | ||
184 | void complete_master_bio(struct drbd_conf *mdev, | 183 | void complete_master_bio(struct drbd_conf *mdev, |
@@ -188,6 +187,20 @@ void complete_master_bio(struct drbd_conf *mdev, | |||
188 | dec_ap_bio(mdev); | 187 | dec_ap_bio(mdev); |
189 | } | 188 | } |
190 | 189 | ||
190 | |||
191 | static void drbd_remove_request_interval(struct rb_root *root, | ||
192 | struct drbd_request *req) | ||
193 | { | ||
194 | struct drbd_conf *mdev = req->mdev; | ||
195 | struct drbd_interval *i = &req->i; | ||
196 | |||
197 | drbd_remove_interval(root, i); | ||
198 | |||
199 | /* Wake up any processes waiting for this request to complete. */ | ||
200 | if (i->waiting) | ||
201 | wake_up(&mdev->misc_wait); | ||
202 | } | ||
203 | |||
191 | /* Helper for __req_mod(). | 204 | /* Helper for __req_mod(). |
192 | * Set m->bio to the master bio, if it is fit to be completed, | 205 | * Set m->bio to the master bio, if it is fit to be completed, |
193 | * or leave it alone (it is initialized to NULL in __req_mod), | 206 | * or leave it alone (it is initialized to NULL in __req_mod), |
@@ -251,7 +264,7 @@ void _req_may_be_done(struct drbd_request *req, struct bio_and_error *m) | |||
251 | root = &mdev->write_requests; | 264 | root = &mdev->write_requests; |
252 | else | 265 | else |
253 | root = &mdev->read_requests; | 266 | root = &mdev->read_requests; |
254 | drbd_remove_interval(root, &req->i); | 267 | drbd_remove_request_interval(root, req); |
255 | } else | 268 | } else |
256 | D_ASSERT((s & (RQ_NET_MASK & ~RQ_NET_DONE)) == 0); | 269 | D_ASSERT((s & (RQ_NET_MASK & ~RQ_NET_DONE)) == 0); |
257 | 270 | ||
diff --git a/drivers/block/drbd/drbd_req.h b/drivers/block/drbd/drbd_req.h index 7a7464a2b3a6..431e3f962c3a 100644 --- a/drivers/block/drbd/drbd_req.h +++ b/drivers/block/drbd/drbd_req.h | |||
@@ -194,12 +194,6 @@ enum drbd_req_state_bits { | |||
194 | 194 | ||
195 | /* Should call drbd_al_complete_io() for this request... */ | 195 | /* Should call drbd_al_complete_io() for this request... */ |
196 | __RQ_IN_ACT_LOG, | 196 | __RQ_IN_ACT_LOG, |
197 | |||
198 | /* | ||
199 | * Set when a processes puts itself to sleep to wait for this request | ||
200 | * to complete. | ||
201 | */ | ||
202 | __RQ_COLLISION, | ||
203 | }; | 197 | }; |
204 | 198 | ||
205 | #define RQ_LOCAL_PENDING (1UL << __RQ_LOCAL_PENDING) | 199 | #define RQ_LOCAL_PENDING (1UL << __RQ_LOCAL_PENDING) |
@@ -220,7 +214,6 @@ enum drbd_req_state_bits { | |||
220 | 214 | ||
221 | #define RQ_WRITE (1UL << __RQ_WRITE) | 215 | #define RQ_WRITE (1UL << __RQ_WRITE) |
222 | #define RQ_IN_ACT_LOG (1UL << __RQ_IN_ACT_LOG) | 216 | #define RQ_IN_ACT_LOG (1UL << __RQ_IN_ACT_LOG) |
223 | #define RQ_COLLISION (1UL << __RQ_COLLISION) | ||
224 | 217 | ||
225 | /* For waking up the frozen transfer log mod_req() has to return if the request | 218 | /* For waking up the frozen transfer log mod_req() has to return if the request |
226 | should be counted in the epoch object*/ | 219 | should be counted in the epoch object*/ |