diff options
Diffstat (limited to 'drivers/block/drbd/drbd_req.h')
-rw-r--r-- | drivers/block/drbd/drbd_req.h | 187 |
1 files changed, 69 insertions, 118 deletions
diff --git a/drivers/block/drbd/drbd_req.h b/drivers/block/drbd/drbd_req.h index 3d2111919486..016de6b8bb57 100644 --- a/drivers/block/drbd/drbd_req.h +++ b/drivers/block/drbd/drbd_req.h | |||
@@ -77,40 +77,41 @@ | |||
77 | */ | 77 | */ |
78 | 78 | ||
79 | enum drbd_req_event { | 79 | enum drbd_req_event { |
80 | created, | 80 | CREATED, |
81 | to_be_send, | 81 | TO_BE_SENT, |
82 | to_be_submitted, | 82 | TO_BE_SUBMITTED, |
83 | 83 | ||
84 | /* XXX yes, now I am inconsistent... | 84 | /* XXX yes, now I am inconsistent... |
85 | * these are not "events" but "actions" | 85 | * these are not "events" but "actions" |
86 | * oh, well... */ | 86 | * oh, well... */ |
87 | queue_for_net_write, | 87 | QUEUE_FOR_NET_WRITE, |
88 | queue_for_net_read, | 88 | QUEUE_FOR_NET_READ, |
89 | queue_for_send_oos, | 89 | QUEUE_FOR_SEND_OOS, |
90 | 90 | ||
91 | send_canceled, | 91 | SEND_CANCELED, |
92 | send_failed, | 92 | SEND_FAILED, |
93 | handed_over_to_network, | 93 | HANDED_OVER_TO_NETWORK, |
94 | oos_handed_to_network, | 94 | OOS_HANDED_TO_NETWORK, |
95 | connection_lost_while_pending, | 95 | CONNECTION_LOST_WHILE_PENDING, |
96 | read_retry_remote_canceled, | 96 | READ_RETRY_REMOTE_CANCELED, |
97 | recv_acked_by_peer, | 97 | RECV_ACKED_BY_PEER, |
98 | write_acked_by_peer, | 98 | WRITE_ACKED_BY_PEER, |
99 | write_acked_by_peer_and_sis, /* and set_in_sync */ | 99 | WRITE_ACKED_BY_PEER_AND_SIS, /* and set_in_sync */ |
100 | conflict_discarded_by_peer, | 100 | CONFLICT_RESOLVED, |
101 | neg_acked, | 101 | POSTPONE_WRITE, |
102 | barrier_acked, /* in protocol A and B */ | 102 | NEG_ACKED, |
103 | data_received, /* (remote read) */ | 103 | BARRIER_ACKED, /* in protocol A and B */ |
104 | 104 | DATA_RECEIVED, /* (remote read) */ | |
105 | read_completed_with_error, | 105 | |
106 | read_ahead_completed_with_error, | 106 | READ_COMPLETED_WITH_ERROR, |
107 | write_completed_with_error, | 107 | READ_AHEAD_COMPLETED_WITH_ERROR, |
108 | abort_disk_io, | 108 | WRITE_COMPLETED_WITH_ERROR, |
109 | completed_ok, | 109 | ABORT_DISK_IO, |
110 | resend, | 110 | COMPLETED_OK, |
111 | fail_frozen_disk_io, | 111 | RESEND, |
112 | restart_frozen_disk_io, | 112 | FAIL_FROZEN_DISK_IO, |
113 | nothing, /* for tracing only */ | 113 | RESTART_FROZEN_DISK_IO, |
114 | NOTHING, | ||
114 | }; | 115 | }; |
115 | 116 | ||
116 | /* encoding of request states for now. we don't actually need that many bits. | 117 | /* encoding of request states for now. we don't actually need that many bits. |
@@ -142,8 +143,8 @@ enum drbd_req_state_bits { | |||
142 | * recv_ack (B) or implicit "ack" (A), | 143 | * recv_ack (B) or implicit "ack" (A), |
143 | * still waiting for the barrier ack. | 144 | * still waiting for the barrier ack. |
144 | * master_bio may already be completed and invalidated. | 145 | * master_bio may already be completed and invalidated. |
145 | * 11100: write_acked (C), | 146 | * 11100: write acked (C), |
146 | * data_received (for remote read, any protocol) | 147 | * data received (for remote read, any protocol) |
147 | * or finally the barrier ack has arrived (B,A)... | 148 | * or finally the barrier ack has arrived (B,A)... |
148 | * request can be freed | 149 | * request can be freed |
149 | * 01100: neg-acked (write, protocol C) | 150 | * 01100: neg-acked (write, protocol C) |
@@ -198,6 +199,22 @@ enum drbd_req_state_bits { | |||
198 | 199 | ||
199 | /* Should call drbd_al_complete_io() for this request... */ | 200 | /* Should call drbd_al_complete_io() for this request... */ |
200 | __RQ_IN_ACT_LOG, | 201 | __RQ_IN_ACT_LOG, |
202 | |||
203 | /* The peer has sent a retry ACK */ | ||
204 | __RQ_POSTPONED, | ||
205 | |||
206 | /* would have been completed, | ||
207 | * but was not, because of drbd_suspended() */ | ||
208 | __RQ_COMPLETION_SUSP, | ||
209 | |||
210 | /* We expect a receive ACK (wire proto B) */ | ||
211 | __RQ_EXP_RECEIVE_ACK, | ||
212 | |||
213 | /* We expect a write ACK (wite proto C) */ | ||
214 | __RQ_EXP_WRITE_ACK, | ||
215 | |||
216 | /* waiting for a barrier ack, did an extra kref_get */ | ||
217 | __RQ_EXP_BARR_ACK, | ||
201 | }; | 218 | }; |
202 | 219 | ||
203 | #define RQ_LOCAL_PENDING (1UL << __RQ_LOCAL_PENDING) | 220 | #define RQ_LOCAL_PENDING (1UL << __RQ_LOCAL_PENDING) |
@@ -219,56 +236,16 @@ enum drbd_req_state_bits { | |||
219 | 236 | ||
220 | #define RQ_WRITE (1UL << __RQ_WRITE) | 237 | #define RQ_WRITE (1UL << __RQ_WRITE) |
221 | #define RQ_IN_ACT_LOG (1UL << __RQ_IN_ACT_LOG) | 238 | #define RQ_IN_ACT_LOG (1UL << __RQ_IN_ACT_LOG) |
239 | #define RQ_POSTPONED (1UL << __RQ_POSTPONED) | ||
240 | #define RQ_COMPLETION_SUSP (1UL << __RQ_COMPLETION_SUSP) | ||
241 | #define RQ_EXP_RECEIVE_ACK (1UL << __RQ_EXP_RECEIVE_ACK) | ||
242 | #define RQ_EXP_WRITE_ACK (1UL << __RQ_EXP_WRITE_ACK) | ||
243 | #define RQ_EXP_BARR_ACK (1UL << __RQ_EXP_BARR_ACK) | ||
222 | 244 | ||
223 | /* For waking up the frozen transfer log mod_req() has to return if the request | 245 | /* For waking up the frozen transfer log mod_req() has to return if the request |
224 | should be counted in the epoch object*/ | 246 | should be counted in the epoch object*/ |
225 | #define MR_WRITE_SHIFT 0 | 247 | #define MR_WRITE 1 |
226 | #define MR_WRITE (1 << MR_WRITE_SHIFT) | 248 | #define MR_READ 2 |
227 | #define MR_READ_SHIFT 1 | ||
228 | #define MR_READ (1 << MR_READ_SHIFT) | ||
229 | |||
230 | /* epoch entries */ | ||
231 | static inline | ||
232 | struct hlist_head *ee_hash_slot(struct drbd_conf *mdev, sector_t sector) | ||
233 | { | ||
234 | BUG_ON(mdev->ee_hash_s == 0); | ||
235 | return mdev->ee_hash + | ||
236 | ((unsigned int)(sector>>HT_SHIFT) % mdev->ee_hash_s); | ||
237 | } | ||
238 | |||
239 | /* transfer log (drbd_request objects) */ | ||
240 | static inline | ||
241 | struct hlist_head *tl_hash_slot(struct drbd_conf *mdev, sector_t sector) | ||
242 | { | ||
243 | BUG_ON(mdev->tl_hash_s == 0); | ||
244 | return mdev->tl_hash + | ||
245 | ((unsigned int)(sector>>HT_SHIFT) % mdev->tl_hash_s); | ||
246 | } | ||
247 | |||
248 | /* application reads (drbd_request objects) */ | ||
249 | static struct hlist_head *ar_hash_slot(struct drbd_conf *mdev, sector_t sector) | ||
250 | { | ||
251 | return mdev->app_reads_hash | ||
252 | + ((unsigned int)(sector) % APP_R_HSIZE); | ||
253 | } | ||
254 | |||
255 | /* when we receive the answer for a read request, | ||
256 | * verify that we actually know about it */ | ||
257 | static inline struct drbd_request *_ar_id_to_req(struct drbd_conf *mdev, | ||
258 | u64 id, sector_t sector) | ||
259 | { | ||
260 | struct hlist_head *slot = ar_hash_slot(mdev, sector); | ||
261 | struct hlist_node *n; | ||
262 | struct drbd_request *req; | ||
263 | |||
264 | hlist_for_each_entry(req, n, slot, collision) { | ||
265 | if ((unsigned long)req == (unsigned long)id) { | ||
266 | D_ASSERT(req->sector == sector); | ||
267 | return req; | ||
268 | } | ||
269 | } | ||
270 | return NULL; | ||
271 | } | ||
272 | 249 | ||
273 | static inline void drbd_req_make_private_bio(struct drbd_request *req, struct bio *bio_src) | 250 | static inline void drbd_req_make_private_bio(struct drbd_request *req, struct bio *bio_src) |
274 | { | 251 | { |
@@ -278,41 +255,10 @@ static inline void drbd_req_make_private_bio(struct drbd_request *req, struct bi | |||
278 | req->private_bio = bio; | 255 | req->private_bio = bio; |
279 | 256 | ||
280 | bio->bi_private = req; | 257 | bio->bi_private = req; |
281 | bio->bi_end_io = drbd_endio_pri; | 258 | bio->bi_end_io = drbd_request_endio; |
282 | bio->bi_next = NULL; | 259 | bio->bi_next = NULL; |
283 | } | 260 | } |
284 | 261 | ||
285 | static inline struct drbd_request *drbd_req_new(struct drbd_conf *mdev, | ||
286 | struct bio *bio_src) | ||
287 | { | ||
288 | struct drbd_request *req = | ||
289 | mempool_alloc(drbd_request_mempool, GFP_NOIO); | ||
290 | if (likely(req)) { | ||
291 | drbd_req_make_private_bio(req, bio_src); | ||
292 | |||
293 | req->rq_state = bio_data_dir(bio_src) == WRITE ? RQ_WRITE : 0; | ||
294 | req->mdev = mdev; | ||
295 | req->master_bio = bio_src; | ||
296 | req->epoch = 0; | ||
297 | req->sector = bio_src->bi_sector; | ||
298 | req->size = bio_src->bi_size; | ||
299 | INIT_HLIST_NODE(&req->collision); | ||
300 | INIT_LIST_HEAD(&req->tl_requests); | ||
301 | INIT_LIST_HEAD(&req->w.list); | ||
302 | } | ||
303 | return req; | ||
304 | } | ||
305 | |||
306 | static inline void drbd_req_free(struct drbd_request *req) | ||
307 | { | ||
308 | mempool_free(req, drbd_request_mempool); | ||
309 | } | ||
310 | |||
311 | static inline int overlaps(sector_t s1, int l1, sector_t s2, int l2) | ||
312 | { | ||
313 | return !((s1 + (l1>>9) <= s2) || (s1 >= s2 + (l2>>9))); | ||
314 | } | ||
315 | |||
316 | /* Short lived temporary struct on the stack. | 262 | /* Short lived temporary struct on the stack. |
317 | * We could squirrel the error to be returned into | 263 | * We could squirrel the error to be returned into |
318 | * bio->bi_size, or similar. But that would be too ugly. */ | 264 | * bio->bi_size, or similar. But that would be too ugly. */ |
@@ -321,6 +267,7 @@ struct bio_and_error { | |||
321 | int error; | 267 | int error; |
322 | }; | 268 | }; |
323 | 269 | ||
270 | extern void drbd_req_destroy(struct kref *kref); | ||
324 | extern void _req_may_be_done(struct drbd_request *req, | 271 | extern void _req_may_be_done(struct drbd_request *req, |
325 | struct bio_and_error *m); | 272 | struct bio_and_error *m); |
326 | extern int __req_mod(struct drbd_request *req, enum drbd_req_event what, | 273 | extern int __req_mod(struct drbd_request *req, enum drbd_req_event what, |
@@ -328,13 +275,17 @@ extern int __req_mod(struct drbd_request *req, enum drbd_req_event what, | |||
328 | extern void complete_master_bio(struct drbd_conf *mdev, | 275 | extern void complete_master_bio(struct drbd_conf *mdev, |
329 | struct bio_and_error *m); | 276 | struct bio_and_error *m); |
330 | extern void request_timer_fn(unsigned long data); | 277 | extern void request_timer_fn(unsigned long data); |
331 | extern void tl_restart(struct drbd_conf *mdev, enum drbd_req_event what); | 278 | extern void tl_restart(struct drbd_tconn *tconn, enum drbd_req_event what); |
279 | extern void _tl_restart(struct drbd_tconn *tconn, enum drbd_req_event what); | ||
280 | |||
281 | /* this is in drbd_main.c */ | ||
282 | extern void drbd_restart_request(struct drbd_request *req); | ||
332 | 283 | ||
333 | /* use this if you don't want to deal with calling complete_master_bio() | 284 | /* use this if you don't want to deal with calling complete_master_bio() |
334 | * outside the spinlock, e.g. when walking some list on cleanup. */ | 285 | * outside the spinlock, e.g. when walking some list on cleanup. */ |
335 | static inline int _req_mod(struct drbd_request *req, enum drbd_req_event what) | 286 | static inline int _req_mod(struct drbd_request *req, enum drbd_req_event what) |
336 | { | 287 | { |
337 | struct drbd_conf *mdev = req->mdev; | 288 | struct drbd_conf *mdev = req->w.mdev; |
338 | struct bio_and_error m; | 289 | struct bio_and_error m; |
339 | int rv; | 290 | int rv; |
340 | 291 | ||
@@ -354,13 +305,13 @@ static inline int req_mod(struct drbd_request *req, | |||
354 | enum drbd_req_event what) | 305 | enum drbd_req_event what) |
355 | { | 306 | { |
356 | unsigned long flags; | 307 | unsigned long flags; |
357 | struct drbd_conf *mdev = req->mdev; | 308 | struct drbd_conf *mdev = req->w.mdev; |
358 | struct bio_and_error m; | 309 | struct bio_and_error m; |
359 | int rv; | 310 | int rv; |
360 | 311 | ||
361 | spin_lock_irqsave(&mdev->req_lock, flags); | 312 | spin_lock_irqsave(&mdev->tconn->req_lock, flags); |
362 | rv = __req_mod(req, what, &m); | 313 | rv = __req_mod(req, what, &m); |
363 | spin_unlock_irqrestore(&mdev->req_lock, flags); | 314 | spin_unlock_irqrestore(&mdev->tconn->req_lock, flags); |
364 | 315 | ||
365 | if (m.bio) | 316 | if (m.bio) |
366 | complete_master_bio(mdev, &m); | 317 | complete_master_bio(mdev, &m); |
@@ -368,7 +319,7 @@ static inline int req_mod(struct drbd_request *req, | |||
368 | return rv; | 319 | return rv; |
369 | } | 320 | } |
370 | 321 | ||
371 | static inline bool drbd_should_do_remote(union drbd_state s) | 322 | static inline bool drbd_should_do_remote(union drbd_dev_state s) |
372 | { | 323 | { |
373 | return s.pdsk == D_UP_TO_DATE || | 324 | return s.pdsk == D_UP_TO_DATE || |
374 | (s.pdsk >= D_INCONSISTENT && | 325 | (s.pdsk >= D_INCONSISTENT && |
@@ -378,7 +329,7 @@ static inline bool drbd_should_do_remote(union drbd_state s) | |||
378 | That is equivalent since before 96 IO was frozen in the C_WF_BITMAP* | 329 | That is equivalent since before 96 IO was frozen in the C_WF_BITMAP* |
379 | states. */ | 330 | states. */ |
380 | } | 331 | } |
381 | static inline bool drbd_should_send_oos(union drbd_state s) | 332 | static inline bool drbd_should_send_out_of_sync(union drbd_dev_state s) |
382 | { | 333 | { |
383 | return s.conn == C_AHEAD || s.conn == C_WF_BITMAP_S; | 334 | return s.conn == C_AHEAD || s.conn == C_WF_BITMAP_S; |
384 | /* pdsk = D_INCONSISTENT as a consequence. Protocol 96 check not necessary | 335 | /* pdsk = D_INCONSISTENT as a consequence. Protocol 96 check not necessary |