diff options
Diffstat (limited to 'drivers/lightnvm/pblk-write.c')
-rw-r--r-- | drivers/lightnvm/pblk-write.c | 353 |
1 files changed, 278 insertions, 75 deletions
diff --git a/drivers/lightnvm/pblk-write.c b/drivers/lightnvm/pblk-write.c index aef6fd7c4a0c..d62a8f4faaf4 100644 --- a/drivers/lightnvm/pblk-write.c +++ b/drivers/lightnvm/pblk-write.c | |||
@@ -17,18 +17,6 @@ | |||
17 | 17 | ||
18 | #include "pblk.h" | 18 | #include "pblk.h" |
19 | 19 | ||
20 | static void pblk_sync_line(struct pblk *pblk, struct pblk_line *line) | ||
21 | { | ||
22 | #ifdef CONFIG_NVM_DEBUG | ||
23 | atomic_long_inc(&pblk->sync_writes); | ||
24 | #endif | ||
25 | |||
26 | /* Counter protected by rb sync lock */ | ||
27 | line->left_ssecs--; | ||
28 | if (!line->left_ssecs) | ||
29 | pblk_line_run_ws(pblk, line, NULL, pblk_line_close_ws); | ||
30 | } | ||
31 | |||
32 | static unsigned long pblk_end_w_bio(struct pblk *pblk, struct nvm_rq *rqd, | 20 | static unsigned long pblk_end_w_bio(struct pblk *pblk, struct nvm_rq *rqd, |
33 | struct pblk_c_ctx *c_ctx) | 21 | struct pblk_c_ctx *c_ctx) |
34 | { | 22 | { |
@@ -39,21 +27,14 @@ static unsigned long pblk_end_w_bio(struct pblk *pblk, struct nvm_rq *rqd, | |||
39 | 27 | ||
40 | for (i = 0; i < c_ctx->nr_valid; i++) { | 28 | for (i = 0; i < c_ctx->nr_valid; i++) { |
41 | struct pblk_w_ctx *w_ctx; | 29 | struct pblk_w_ctx *w_ctx; |
42 | struct ppa_addr p; | ||
43 | struct pblk_line *line; | ||
44 | 30 | ||
45 | w_ctx = pblk_rb_w_ctx(&pblk->rwb, c_ctx->sentry + i); | 31 | w_ctx = pblk_rb_w_ctx(&pblk->rwb, c_ctx->sentry + i); |
46 | |||
47 | p = rqd->ppa_list[i]; | ||
48 | line = &pblk->lines[pblk_dev_ppa_to_line(p)]; | ||
49 | pblk_sync_line(pblk, line); | ||
50 | |||
51 | while ((original_bio = bio_list_pop(&w_ctx->bios))) | 32 | while ((original_bio = bio_list_pop(&w_ctx->bios))) |
52 | bio_endio(original_bio); | 33 | bio_endio(original_bio); |
53 | } | 34 | } |
54 | 35 | ||
55 | #ifdef CONFIG_NVM_DEBUG | 36 | #ifdef CONFIG_NVM_DEBUG |
56 | atomic_long_add(c_ctx->nr_valid, &pblk->compl_writes); | 37 | atomic_long_add(c_ctx->nr_valid, &pblk->sync_writes); |
57 | #endif | 38 | #endif |
58 | 39 | ||
59 | ret = pblk_rb_sync_advance(&pblk->rwb, c_ctx->nr_valid); | 40 | ret = pblk_rb_sync_advance(&pblk->rwb, c_ctx->nr_valid); |
@@ -169,7 +150,7 @@ static void pblk_end_w_fail(struct pblk *pblk, struct nvm_rq *rqd) | |||
169 | } | 150 | } |
170 | 151 | ||
171 | INIT_WORK(&recovery->ws_rec, pblk_submit_rec); | 152 | INIT_WORK(&recovery->ws_rec, pblk_submit_rec); |
172 | queue_work(pblk->kw_wq, &recovery->ws_rec); | 153 | queue_work(pblk->close_wq, &recovery->ws_rec); |
173 | 154 | ||
174 | out: | 155 | out: |
175 | pblk_complete_write(pblk, rqd, c_ctx); | 156 | pblk_complete_write(pblk, rqd, c_ctx); |
@@ -186,14 +167,50 @@ static void pblk_end_io_write(struct nvm_rq *rqd) | |||
186 | } | 167 | } |
187 | #ifdef CONFIG_NVM_DEBUG | 168 | #ifdef CONFIG_NVM_DEBUG |
188 | else | 169 | else |
189 | WARN_ONCE(rqd->bio->bi_error, "pblk: corrupted write error\n"); | 170 | WARN_ONCE(rqd->bio->bi_status, "pblk: corrupted write error\n"); |
190 | #endif | 171 | #endif |
191 | 172 | ||
192 | pblk_complete_write(pblk, rqd, c_ctx); | 173 | pblk_complete_write(pblk, rqd, c_ctx); |
174 | atomic_dec(&pblk->inflight_io); | ||
175 | } | ||
176 | |||
177 | static void pblk_end_io_write_meta(struct nvm_rq *rqd) | ||
178 | { | ||
179 | struct pblk *pblk = rqd->private; | ||
180 | struct nvm_tgt_dev *dev = pblk->dev; | ||
181 | struct nvm_geo *geo = &dev->geo; | ||
182 | struct pblk_g_ctx *m_ctx = nvm_rq_to_pdu(rqd); | ||
183 | struct pblk_line *line = m_ctx->private; | ||
184 | struct pblk_emeta *emeta = line->emeta; | ||
185 | int pos = pblk_ppa_to_pos(geo, rqd->ppa_list[0]); | ||
186 | struct pblk_lun *rlun = &pblk->luns[pos]; | ||
187 | int sync; | ||
188 | |||
189 | up(&rlun->wr_sem); | ||
190 | |||
191 | if (rqd->error) { | ||
192 | pblk_log_write_err(pblk, rqd); | ||
193 | pr_err("pblk: metadata I/O failed. Line %d\n", line->id); | ||
194 | } | ||
195 | #ifdef CONFIG_NVM_DEBUG | ||
196 | else | ||
197 | WARN_ONCE(rqd->bio->bi_status, "pblk: corrupted write error\n"); | ||
198 | #endif | ||
199 | |||
200 | sync = atomic_add_return(rqd->nr_ppas, &emeta->sync); | ||
201 | if (sync == emeta->nr_entries) | ||
202 | pblk_line_run_ws(pblk, line, NULL, pblk_line_close_ws, | ||
203 | pblk->close_wq); | ||
204 | |||
205 | bio_put(rqd->bio); | ||
206 | pblk_free_rqd(pblk, rqd, READ); | ||
207 | |||
208 | atomic_dec(&pblk->inflight_io); | ||
193 | } | 209 | } |
194 | 210 | ||
195 | static int pblk_alloc_w_rq(struct pblk *pblk, struct nvm_rq *rqd, | 211 | static int pblk_alloc_w_rq(struct pblk *pblk, struct nvm_rq *rqd, |
196 | unsigned int nr_secs) | 212 | unsigned int nr_secs, |
213 | nvm_end_io_fn(*end_io)) | ||
197 | { | 214 | { |
198 | struct nvm_tgt_dev *dev = pblk->dev; | 215 | struct nvm_tgt_dev *dev = pblk->dev; |
199 | 216 | ||
@@ -202,7 +219,7 @@ static int pblk_alloc_w_rq(struct pblk *pblk, struct nvm_rq *rqd, | |||
202 | rqd->nr_ppas = nr_secs; | 219 | rqd->nr_ppas = nr_secs; |
203 | rqd->flags = pblk_set_progr_mode(pblk, WRITE); | 220 | rqd->flags = pblk_set_progr_mode(pblk, WRITE); |
204 | rqd->private = pblk; | 221 | rqd->private = pblk; |
205 | rqd->end_io = pblk_end_io_write; | 222 | rqd->end_io = end_io; |
206 | 223 | ||
207 | rqd->meta_list = nvm_dev_dma_alloc(dev->parent, GFP_KERNEL, | 224 | rqd->meta_list = nvm_dev_dma_alloc(dev->parent, GFP_KERNEL, |
208 | &rqd->dma_meta_list); | 225 | &rqd->dma_meta_list); |
@@ -219,11 +236,10 @@ static int pblk_alloc_w_rq(struct pblk *pblk, struct nvm_rq *rqd, | |||
219 | } | 236 | } |
220 | 237 | ||
221 | static int pblk_setup_w_rq(struct pblk *pblk, struct nvm_rq *rqd, | 238 | static int pblk_setup_w_rq(struct pblk *pblk, struct nvm_rq *rqd, |
222 | struct pblk_c_ctx *c_ctx) | 239 | struct pblk_c_ctx *c_ctx, struct ppa_addr *erase_ppa) |
223 | { | 240 | { |
224 | struct pblk_line_meta *lm = &pblk->lm; | 241 | struct pblk_line_meta *lm = &pblk->lm; |
225 | struct pblk_line *e_line = pblk_line_get_data_next(pblk); | 242 | struct pblk_line *e_line = pblk_line_get_erase(pblk); |
226 | struct ppa_addr erase_ppa; | ||
227 | unsigned int valid = c_ctx->nr_valid; | 243 | unsigned int valid = c_ctx->nr_valid; |
228 | unsigned int padded = c_ctx->nr_padded; | 244 | unsigned int padded = c_ctx->nr_padded; |
229 | unsigned int nr_secs = valid + padded; | 245 | unsigned int nr_secs = valid + padded; |
@@ -231,40 +247,23 @@ static int pblk_setup_w_rq(struct pblk *pblk, struct nvm_rq *rqd, | |||
231 | int ret = 0; | 247 | int ret = 0; |
232 | 248 | ||
233 | lun_bitmap = kzalloc(lm->lun_bitmap_len, GFP_KERNEL); | 249 | lun_bitmap = kzalloc(lm->lun_bitmap_len, GFP_KERNEL); |
234 | if (!lun_bitmap) { | 250 | if (!lun_bitmap) |
235 | ret = -ENOMEM; | 251 | return -ENOMEM; |
236 | goto out; | ||
237 | } | ||
238 | c_ctx->lun_bitmap = lun_bitmap; | 252 | c_ctx->lun_bitmap = lun_bitmap; |
239 | 253 | ||
240 | ret = pblk_alloc_w_rq(pblk, rqd, nr_secs); | 254 | ret = pblk_alloc_w_rq(pblk, rqd, nr_secs, pblk_end_io_write); |
241 | if (ret) { | 255 | if (ret) { |
242 | kfree(lun_bitmap); | 256 | kfree(lun_bitmap); |
243 | goto out; | 257 | return ret; |
244 | } | 258 | } |
245 | 259 | ||
246 | ppa_set_empty(&erase_ppa); | ||
247 | if (likely(!e_line || !atomic_read(&e_line->left_eblks))) | 260 | if (likely(!e_line || !atomic_read(&e_line->left_eblks))) |
248 | pblk_map_rq(pblk, rqd, c_ctx->sentry, lun_bitmap, valid, 0); | 261 | pblk_map_rq(pblk, rqd, c_ctx->sentry, lun_bitmap, valid, 0); |
249 | else | 262 | else |
250 | pblk_map_erase_rq(pblk, rqd, c_ctx->sentry, lun_bitmap, | 263 | pblk_map_erase_rq(pblk, rqd, c_ctx->sentry, lun_bitmap, |
251 | valid, &erase_ppa); | 264 | valid, erase_ppa); |
252 | |||
253 | out: | ||
254 | if (unlikely(e_line && !ppa_empty(erase_ppa))) { | ||
255 | if (pblk_blk_erase_async(pblk, erase_ppa)) { | ||
256 | struct nvm_tgt_dev *dev = pblk->dev; | ||
257 | struct nvm_geo *geo = &dev->geo; | ||
258 | int bit; | ||
259 | |||
260 | atomic_inc(&e_line->left_eblks); | ||
261 | bit = erase_ppa.g.lun * geo->nr_chnls + erase_ppa.g.ch; | ||
262 | WARN_ON(!test_and_clear_bit(bit, e_line->erase_bitmap)); | ||
263 | up(&pblk->erase_sem); | ||
264 | } | ||
265 | } | ||
266 | 265 | ||
267 | return ret; | 266 | return 0; |
268 | } | 267 | } |
269 | 268 | ||
270 | int pblk_setup_w_rec_rq(struct pblk *pblk, struct nvm_rq *rqd, | 269 | int pblk_setup_w_rec_rq(struct pblk *pblk, struct nvm_rq *rqd, |
@@ -280,7 +279,7 @@ int pblk_setup_w_rec_rq(struct pblk *pblk, struct nvm_rq *rqd, | |||
280 | 279 | ||
281 | c_ctx->lun_bitmap = lun_bitmap; | 280 | c_ctx->lun_bitmap = lun_bitmap; |
282 | 281 | ||
283 | ret = pblk_alloc_w_rq(pblk, rqd, rqd->nr_ppas); | 282 | ret = pblk_alloc_w_rq(pblk, rqd, rqd->nr_ppas, pblk_end_io_write); |
284 | if (ret) | 283 | if (ret) |
285 | return ret; | 284 | return ret; |
286 | 285 | ||
@@ -311,16 +310,237 @@ static int pblk_calc_secs_to_sync(struct pblk *pblk, unsigned int secs_avail, | |||
311 | return secs_to_sync; | 310 | return secs_to_sync; |
312 | } | 311 | } |
313 | 312 | ||
313 | static inline int pblk_valid_meta_ppa(struct pblk *pblk, | ||
314 | struct pblk_line *meta_line, | ||
315 | struct ppa_addr *ppa_list, int nr_ppas) | ||
316 | { | ||
317 | struct nvm_tgt_dev *dev = pblk->dev; | ||
318 | struct nvm_geo *geo = &dev->geo; | ||
319 | struct pblk_line *data_line; | ||
320 | struct ppa_addr ppa, ppa_opt; | ||
321 | u64 paddr; | ||
322 | int i; | ||
323 | |||
324 | data_line = &pblk->lines[pblk_dev_ppa_to_line(ppa_list[0])]; | ||
325 | paddr = pblk_lookup_page(pblk, meta_line); | ||
326 | ppa = addr_to_gen_ppa(pblk, paddr, 0); | ||
327 | |||
328 | if (test_bit(pblk_ppa_to_pos(geo, ppa), data_line->blk_bitmap)) | ||
329 | return 1; | ||
330 | |||
331 | /* Schedule a metadata I/O that is half the distance from the data I/O | ||
332 | * with regards to the number of LUNs forming the pblk instance. This | ||
333 | * balances LUN conflicts across every I/O. | ||
334 | * | ||
335 | * When the LUN configuration changes (e.g., due to GC), this distance | ||
336 | * can align, which would result on a LUN deadlock. In this case, modify | ||
337 | * the distance to not be optimal, but allow metadata I/Os to succeed. | ||
338 | */ | ||
339 | ppa_opt = addr_to_gen_ppa(pblk, paddr + data_line->meta_distance, 0); | ||
340 | if (unlikely(ppa_opt.ppa == ppa.ppa)) { | ||
341 | data_line->meta_distance--; | ||
342 | return 0; | ||
343 | } | ||
344 | |||
345 | for (i = 0; i < nr_ppas; i += pblk->min_write_pgs) | ||
346 | if (ppa_list[i].g.ch == ppa_opt.g.ch && | ||
347 | ppa_list[i].g.lun == ppa_opt.g.lun) | ||
348 | return 1; | ||
349 | |||
350 | if (test_bit(pblk_ppa_to_pos(geo, ppa_opt), data_line->blk_bitmap)) { | ||
351 | for (i = 0; i < nr_ppas; i += pblk->min_write_pgs) | ||
352 | if (ppa_list[i].g.ch == ppa.g.ch && | ||
353 | ppa_list[i].g.lun == ppa.g.lun) | ||
354 | return 0; | ||
355 | |||
356 | return 1; | ||
357 | } | ||
358 | |||
359 | return 0; | ||
360 | } | ||
361 | |||
362 | int pblk_submit_meta_io(struct pblk *pblk, struct pblk_line *meta_line) | ||
363 | { | ||
364 | struct nvm_tgt_dev *dev = pblk->dev; | ||
365 | struct nvm_geo *geo = &dev->geo; | ||
366 | struct pblk_line_mgmt *l_mg = &pblk->l_mg; | ||
367 | struct pblk_line_meta *lm = &pblk->lm; | ||
368 | struct pblk_emeta *emeta = meta_line->emeta; | ||
369 | struct pblk_g_ctx *m_ctx; | ||
370 | struct pblk_lun *rlun; | ||
371 | struct bio *bio; | ||
372 | struct nvm_rq *rqd; | ||
373 | void *data; | ||
374 | u64 paddr; | ||
375 | int rq_ppas = pblk->min_write_pgs; | ||
376 | int id = meta_line->id; | ||
377 | int rq_len; | ||
378 | int i, j; | ||
379 | int ret; | ||
380 | |||
381 | rqd = pblk_alloc_rqd(pblk, READ); | ||
382 | if (IS_ERR(rqd)) { | ||
383 | pr_err("pblk: cannot allocate write req.\n"); | ||
384 | return PTR_ERR(rqd); | ||
385 | } | ||
386 | m_ctx = nvm_rq_to_pdu(rqd); | ||
387 | m_ctx->private = meta_line; | ||
388 | |||
389 | rq_len = rq_ppas * geo->sec_size; | ||
390 | data = ((void *)emeta->buf) + emeta->mem; | ||
391 | |||
392 | bio = pblk_bio_map_addr(pblk, data, rq_ppas, rq_len, | ||
393 | l_mg->emeta_alloc_type, GFP_KERNEL); | ||
394 | if (IS_ERR(bio)) { | ||
395 | ret = PTR_ERR(bio); | ||
396 | goto fail_free_rqd; | ||
397 | } | ||
398 | bio->bi_iter.bi_sector = 0; /* internal bio */ | ||
399 | bio_set_op_attrs(bio, REQ_OP_WRITE, 0); | ||
400 | rqd->bio = bio; | ||
401 | |||
402 | ret = pblk_alloc_w_rq(pblk, rqd, rq_ppas, pblk_end_io_write_meta); | ||
403 | if (ret) | ||
404 | goto fail_free_bio; | ||
405 | |||
406 | for (i = 0; i < rqd->nr_ppas; ) { | ||
407 | spin_lock(&meta_line->lock); | ||
408 | paddr = __pblk_alloc_page(pblk, meta_line, rq_ppas); | ||
409 | spin_unlock(&meta_line->lock); | ||
410 | for (j = 0; j < rq_ppas; j++, i++, paddr++) | ||
411 | rqd->ppa_list[i] = addr_to_gen_ppa(pblk, paddr, id); | ||
412 | } | ||
413 | |||
414 | rlun = &pblk->luns[pblk_ppa_to_pos(geo, rqd->ppa_list[0])]; | ||
415 | ret = down_timeout(&rlun->wr_sem, msecs_to_jiffies(5000)); | ||
416 | if (ret) { | ||
417 | pr_err("pblk: lun semaphore timed out (%d)\n", ret); | ||
418 | goto fail_free_bio; | ||
419 | } | ||
420 | |||
421 | emeta->mem += rq_len; | ||
422 | if (emeta->mem >= lm->emeta_len[0]) { | ||
423 | spin_lock(&l_mg->close_lock); | ||
424 | list_del(&meta_line->list); | ||
425 | WARN(!bitmap_full(meta_line->map_bitmap, lm->sec_per_line), | ||
426 | "pblk: corrupt meta line %d\n", meta_line->id); | ||
427 | spin_unlock(&l_mg->close_lock); | ||
428 | } | ||
429 | |||
430 | ret = pblk_submit_io(pblk, rqd); | ||
431 | if (ret) { | ||
432 | pr_err("pblk: emeta I/O submission failed: %d\n", ret); | ||
433 | goto fail_rollback; | ||
434 | } | ||
435 | |||
436 | return NVM_IO_OK; | ||
437 | |||
438 | fail_rollback: | ||
439 | spin_lock(&l_mg->close_lock); | ||
440 | pblk_dealloc_page(pblk, meta_line, rq_ppas); | ||
441 | list_add(&meta_line->list, &meta_line->list); | ||
442 | spin_unlock(&l_mg->close_lock); | ||
443 | fail_free_bio: | ||
444 | if (likely(l_mg->emeta_alloc_type == PBLK_VMALLOC_META)) | ||
445 | bio_put(bio); | ||
446 | fail_free_rqd: | ||
447 | pblk_free_rqd(pblk, rqd, READ); | ||
448 | return ret; | ||
449 | } | ||
450 | |||
451 | static int pblk_sched_meta_io(struct pblk *pblk, struct ppa_addr *prev_list, | ||
452 | int prev_n) | ||
453 | { | ||
454 | struct pblk_line_meta *lm = &pblk->lm; | ||
455 | struct pblk_line_mgmt *l_mg = &pblk->l_mg; | ||
456 | struct pblk_line *meta_line; | ||
457 | |||
458 | spin_lock(&l_mg->close_lock); | ||
459 | retry: | ||
460 | if (list_empty(&l_mg->emeta_list)) { | ||
461 | spin_unlock(&l_mg->close_lock); | ||
462 | return 0; | ||
463 | } | ||
464 | meta_line = list_first_entry(&l_mg->emeta_list, struct pblk_line, list); | ||
465 | if (bitmap_full(meta_line->map_bitmap, lm->sec_per_line)) | ||
466 | goto retry; | ||
467 | spin_unlock(&l_mg->close_lock); | ||
468 | |||
469 | if (!pblk_valid_meta_ppa(pblk, meta_line, prev_list, prev_n)) | ||
470 | return 0; | ||
471 | |||
472 | return pblk_submit_meta_io(pblk, meta_line); | ||
473 | } | ||
474 | |||
475 | static int pblk_submit_io_set(struct pblk *pblk, struct nvm_rq *rqd) | ||
476 | { | ||
477 | struct pblk_c_ctx *c_ctx = nvm_rq_to_pdu(rqd); | ||
478 | struct ppa_addr erase_ppa; | ||
479 | int err; | ||
480 | |||
481 | ppa_set_empty(&erase_ppa); | ||
482 | |||
483 | /* Assign lbas to ppas and populate request structure */ | ||
484 | err = pblk_setup_w_rq(pblk, rqd, c_ctx, &erase_ppa); | ||
485 | if (err) { | ||
486 | pr_err("pblk: could not setup write request: %d\n", err); | ||
487 | return NVM_IO_ERR; | ||
488 | } | ||
489 | |||
490 | if (likely(ppa_empty(erase_ppa))) { | ||
491 | /* Submit metadata write for previous data line */ | ||
492 | err = pblk_sched_meta_io(pblk, rqd->ppa_list, rqd->nr_ppas); | ||
493 | if (err) { | ||
494 | pr_err("pblk: metadata I/O submission failed: %d", err); | ||
495 | return NVM_IO_ERR; | ||
496 | } | ||
497 | |||
498 | /* Submit data write for current data line */ | ||
499 | err = pblk_submit_io(pblk, rqd); | ||
500 | if (err) { | ||
501 | pr_err("pblk: data I/O submission failed: %d\n", err); | ||
502 | return NVM_IO_ERR; | ||
503 | } | ||
504 | } else { | ||
505 | /* Submit data write for current data line */ | ||
506 | err = pblk_submit_io(pblk, rqd); | ||
507 | if (err) { | ||
508 | pr_err("pblk: data I/O submission failed: %d\n", err); | ||
509 | return NVM_IO_ERR; | ||
510 | } | ||
511 | |||
512 | /* Submit available erase for next data line */ | ||
513 | if (pblk_blk_erase_async(pblk, erase_ppa)) { | ||
514 | struct pblk_line *e_line = pblk_line_get_erase(pblk); | ||
515 | struct nvm_tgt_dev *dev = pblk->dev; | ||
516 | struct nvm_geo *geo = &dev->geo; | ||
517 | int bit; | ||
518 | |||
519 | atomic_inc(&e_line->left_eblks); | ||
520 | bit = pblk_ppa_to_pos(geo, erase_ppa); | ||
521 | WARN_ON(!test_and_clear_bit(bit, e_line->erase_bitmap)); | ||
522 | } | ||
523 | } | ||
524 | |||
525 | return NVM_IO_OK; | ||
526 | } | ||
527 | |||
528 | static void pblk_free_write_rqd(struct pblk *pblk, struct nvm_rq *rqd) | ||
529 | { | ||
530 | struct pblk_c_ctx *c_ctx = nvm_rq_to_pdu(rqd); | ||
531 | struct bio *bio = rqd->bio; | ||
532 | |||
533 | if (c_ctx->nr_padded) | ||
534 | pblk_bio_free_pages(pblk, bio, rqd->nr_ppas, c_ctx->nr_padded); | ||
535 | } | ||
536 | |||
314 | static int pblk_submit_write(struct pblk *pblk) | 537 | static int pblk_submit_write(struct pblk *pblk) |
315 | { | 538 | { |
316 | struct bio *bio; | 539 | struct bio *bio; |
317 | struct nvm_rq *rqd; | 540 | struct nvm_rq *rqd; |
318 | struct pblk_c_ctx *c_ctx; | ||
319 | unsigned int pgs_read; | ||
320 | unsigned int secs_avail, secs_to_sync, secs_to_com; | 541 | unsigned int secs_avail, secs_to_sync, secs_to_com; |
321 | unsigned int secs_to_flush; | 542 | unsigned int secs_to_flush; |
322 | unsigned long pos; | 543 | unsigned long pos; |
323 | int err; | ||
324 | 544 | ||
325 | /* If there are no sectors in the cache, flushes (bios without data) | 545 | /* If there are no sectors in the cache, flushes (bios without data) |
326 | * will be cleared on the cache threads | 546 | * will be cleared on the cache threads |
@@ -338,7 +558,6 @@ static int pblk_submit_write(struct pblk *pblk) | |||
338 | pr_err("pblk: cannot allocate write req.\n"); | 558 | pr_err("pblk: cannot allocate write req.\n"); |
339 | return 1; | 559 | return 1; |
340 | } | 560 | } |
341 | c_ctx = nvm_rq_to_pdu(rqd); | ||
342 | 561 | ||
343 | bio = bio_alloc(GFP_KERNEL, pblk->max_write_pgs); | 562 | bio = bio_alloc(GFP_KERNEL, pblk->max_write_pgs); |
344 | if (!bio) { | 563 | if (!bio) { |
@@ -358,29 +577,14 @@ static int pblk_submit_write(struct pblk *pblk) | |||
358 | secs_to_com = (secs_to_sync > secs_avail) ? secs_avail : secs_to_sync; | 577 | secs_to_com = (secs_to_sync > secs_avail) ? secs_avail : secs_to_sync; |
359 | pos = pblk_rb_read_commit(&pblk->rwb, secs_to_com); | 578 | pos = pblk_rb_read_commit(&pblk->rwb, secs_to_com); |
360 | 579 | ||
361 | pgs_read = pblk_rb_read_to_bio(&pblk->rwb, bio, c_ctx, pos, | 580 | if (pblk_rb_read_to_bio(&pblk->rwb, rqd, bio, pos, secs_to_sync, |
362 | secs_to_sync, secs_avail); | 581 | secs_avail)) { |
363 | if (!pgs_read) { | ||
364 | pr_err("pblk: corrupted write bio\n"); | 582 | pr_err("pblk: corrupted write bio\n"); |
365 | goto fail_put_bio; | 583 | goto fail_put_bio; |
366 | } | 584 | } |
367 | 585 | ||
368 | if (c_ctx->nr_padded) | 586 | if (pblk_submit_io_set(pblk, rqd)) |
369 | if (pblk_bio_add_pages(pblk, bio, GFP_KERNEL, c_ctx->nr_padded)) | ||
370 | goto fail_put_bio; | ||
371 | |||
372 | /* Assign lbas to ppas and populate request structure */ | ||
373 | err = pblk_setup_w_rq(pblk, rqd, c_ctx); | ||
374 | if (err) { | ||
375 | pr_err("pblk: could not setup write request\n"); | ||
376 | goto fail_free_bio; | ||
377 | } | ||
378 | |||
379 | err = pblk_submit_io(pblk, rqd); | ||
380 | if (err) { | ||
381 | pr_err("pblk: I/O submission failed: %d\n", err); | ||
382 | goto fail_free_bio; | 587 | goto fail_free_bio; |
383 | } | ||
384 | 588 | ||
385 | #ifdef CONFIG_NVM_DEBUG | 589 | #ifdef CONFIG_NVM_DEBUG |
386 | atomic_long_add(secs_to_sync, &pblk->sub_writes); | 590 | atomic_long_add(secs_to_sync, &pblk->sub_writes); |
@@ -389,8 +593,7 @@ static int pblk_submit_write(struct pblk *pblk) | |||
389 | return 0; | 593 | return 0; |
390 | 594 | ||
391 | fail_free_bio: | 595 | fail_free_bio: |
392 | if (c_ctx->nr_padded) | 596 | pblk_free_write_rqd(pblk, rqd); |
393 | pblk_bio_free_pages(pblk, bio, secs_to_sync, c_ctx->nr_padded); | ||
394 | fail_put_bio: | 597 | fail_put_bio: |
395 | bio_put(bio); | 598 | bio_put(bio); |
396 | fail_free_rqd: | 599 | fail_free_rqd: |