Blame view

drivers/lightnvm/pblk-write.c 15.8 KB
a4bd217b4   Javier González   lightnvm: physica...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  /*
   * Copyright (C) 2016 CNEX Labs
   * Initial release: Javier Gonzalez <javier@cnexlabs.com>
   *                  Matias Bjorling <matias@cnexlabs.com>
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License version
   * 2 as published by the Free Software Foundation.
   *
   * This program is distributed in the hope that it will be useful, but
   * WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * General Public License for more details.
   *
   * pblk-write.c - pblk's write path from write buffer to media
   */
  
  #include "pblk.h"
a4bd217b4   Javier González   lightnvm: physica...
19
20
21
22
23
24
25
26
27
28
  static unsigned long pblk_end_w_bio(struct pblk *pblk, struct nvm_rq *rqd,
  				    struct pblk_c_ctx *c_ctx)
  {
  	struct nvm_tgt_dev *dev = pblk->dev;
  	struct bio *original_bio;
  	unsigned long ret;
  	int i;
  
  	for (i = 0; i < c_ctx->nr_valid; i++) {
  		struct pblk_w_ctx *w_ctx;
a4bd217b4   Javier González   lightnvm: physica...
29
30
  
  		w_ctx = pblk_rb_w_ctx(&pblk->rwb, c_ctx->sentry + i);
a4bd217b4   Javier González   lightnvm: physica...
31
32
33
  		while ((original_bio = bio_list_pop(&w_ctx->bios)))
  			bio_endio(original_bio);
  	}
1508043c3   Javier González   lightnvm: pblk: f...
34
35
36
  	if (c_ctx->nr_padded)
  		pblk_bio_free_pages(pblk, rqd->bio, c_ctx->nr_valid,
  							c_ctx->nr_padded);
a4bd217b4   Javier González   lightnvm: physica...
37
  #ifdef CONFIG_NVM_DEBUG
0880a9aa2   Javier González   lightnvm: pblk: d...
38
  	atomic_long_add(c_ctx->nr_valid, &pblk->sync_writes);
a4bd217b4   Javier González   lightnvm: physica...
39
40
41
  #endif
  
  	ret = pblk_rb_sync_advance(&pblk->rwb, c_ctx->nr_valid);
56c76417a   Javier González   lightnvm: pblk: r...
42
  	nvm_dev_dma_free(dev->parent, rqd->meta_list, rqd->dma_meta_list);
a4bd217b4   Javier González   lightnvm: physica...
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
  
  	bio_put(rqd->bio);
  	pblk_free_rqd(pblk, rqd, WRITE);
  
  	return ret;
  }
  
  static unsigned long pblk_end_queued_w_bio(struct pblk *pblk,
  					   struct nvm_rq *rqd,
  					   struct pblk_c_ctx *c_ctx)
  {
  	list_del(&c_ctx->list);
  	return pblk_end_w_bio(pblk, rqd, c_ctx);
  }
  
  static void pblk_complete_write(struct pblk *pblk, struct nvm_rq *rqd,
  				struct pblk_c_ctx *c_ctx)
  {
  	struct pblk_c_ctx *c, *r;
  	unsigned long flags;
  	unsigned long pos;
  
  #ifdef CONFIG_NVM_DEBUG
  	atomic_long_sub(c_ctx->nr_valid, &pblk->inflight_writes);
  #endif
  
  	pblk_up_rq(pblk, rqd->ppa_list, rqd->nr_ppas, c_ctx->lun_bitmap);
  
  	pos = pblk_rb_sync_init(&pblk->rwb, &flags);
  	if (pos == c_ctx->sentry) {
  		pos = pblk_end_w_bio(pblk, rqd, c_ctx);
  
  retry:
  		list_for_each_entry_safe(c, r, &pblk->compl_list, list) {
  			rqd = nvm_rq_from_c_ctx(c);
  			if (c->sentry == pos) {
  				pos = pblk_end_queued_w_bio(pblk, rqd, c);
  				goto retry;
  			}
  		}
  	} else {
  		WARN_ON(nvm_rq_from_c_ctx(c_ctx) != rqd);
  		list_add_tail(&c_ctx->list, &pblk->compl_list);
  	}
  	pblk_rb_sync_end(&pblk->rwb, &flags);
  }
  
  /* When a write fails, we are not sure whether the block has grown bad or a page
   * range is more susceptible to write errors. If a high number of pages fail, we
   * assume that the block is bad and we mark it accordingly. In all cases, we
   * remap and resubmit the failed entries as fast as possible; if a flush is
   * waiting on a completion, the whole stack would stall otherwise.
   */
  static void pblk_end_w_fail(struct pblk *pblk, struct nvm_rq *rqd)
  {
  	void *comp_bits = &rqd->ppa_status;
  	struct pblk_c_ctx *c_ctx = nvm_rq_to_pdu(rqd);
  	struct pblk_rec_ctx *recovery;
  	struct ppa_addr *ppa_list = rqd->ppa_list;
  	int nr_ppas = rqd->nr_ppas;
  	unsigned int c_entries;
  	int bit, ret;
  
  	if (unlikely(nr_ppas == 1))
  		ppa_list = &rqd->ppa_addr;
  
  	recovery = mempool_alloc(pblk->rec_pool, GFP_ATOMIC);
  	if (!recovery) {
  		pr_err("pblk: could not allocate recovery context
  ");
  		return;
  	}
  	INIT_LIST_HEAD(&recovery->failed);
  
  	bit = -1;
  	while ((bit = find_next_bit(comp_bits, nr_ppas, bit + 1)) < nr_ppas) {
  		struct pblk_rb_entry *entry;
  		struct ppa_addr ppa;
  
  		/* Logic error */
  		if (bit > c_ctx->nr_valid) {
2a79efd83   Dan Carpenter   lightnvm: fix som...
124
125
  			WARN_ONCE(1, "pblk: corrupted write request
  ");
33db9fd46   Javier González   lightnvm: pblk: f...
126
  			mempool_free(recovery, pblk->rec_pool);
a4bd217b4   Javier González   lightnvm: physica...
127
128
129
130
131
132
133
134
  			goto out;
  		}
  
  		ppa = ppa_list[bit];
  		entry = pblk_rb_sync_scan_entry(&pblk->rwb, &ppa);
  		if (!entry) {
  			pr_err("pblk: could not scan entry on write failure
  ");
33db9fd46   Javier González   lightnvm: pblk: f...
135
  			mempool_free(recovery, pblk->rec_pool);
a4bd217b4   Javier González   lightnvm: physica...
136
137
138
139
140
141
142
143
144
145
146
147
148
149
  			goto out;
  		}
  
  		/* The list is filled first and emptied afterwards. No need for
  		 * protecting it with a lock
  		 */
  		list_add_tail(&entry->index, &recovery->failed);
  	}
  
  	c_entries = find_first_bit(comp_bits, nr_ppas);
  	ret = pblk_recov_setup_rq(pblk, c_ctx, recovery, comp_bits, c_entries);
  	if (ret) {
  		pr_err("pblk: could not recover from write failure
  ");
33db9fd46   Javier González   lightnvm: pblk: f...
150
  		mempool_free(recovery, pblk->rec_pool);
a4bd217b4   Javier González   lightnvm: physica...
151
152
153
154
  		goto out;
  	}
  
  	INIT_WORK(&recovery->ws_rec, pblk_submit_rec);
ef5764946   Javier González   lightnvm: pblk: s...
155
  	queue_work(pblk->close_wq, &recovery->ws_rec);
a4bd217b4   Javier González   lightnvm: physica...
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
  
  out:
  	pblk_complete_write(pblk, rqd, c_ctx);
  }
  
  static void pblk_end_io_write(struct nvm_rq *rqd)
  {
  	struct pblk *pblk = rqd->private;
  	struct pblk_c_ctx *c_ctx = nvm_rq_to_pdu(rqd);
  
  	if (rqd->error) {
  		pblk_log_write_err(pblk, rqd);
  		return pblk_end_w_fail(pblk, rqd);
  	}
  #ifdef CONFIG_NVM_DEBUG
  	else
4e4cbee93   Christoph Hellwig   block: switch bio...
172
173
  		WARN_ONCE(rqd->bio->bi_status, "pblk: corrupted write error
  ");
a4bd217b4   Javier González   lightnvm: physica...
174
175
176
  #endif
  
  	pblk_complete_write(pblk, rqd, c_ctx);
588726d3e   Javier González   lightnvm: pblk: f...
177
  	atomic_dec(&pblk->inflight_io);
a4bd217b4   Javier González   lightnvm: physica...
178
  }
dd2a43437   Javier González   lightnvm: pblk: s...
179
180
181
182
  static void pblk_end_io_write_meta(struct nvm_rq *rqd)
  {
  	struct pblk *pblk = rqd->private;
  	struct nvm_tgt_dev *dev = pblk->dev;
dd2a43437   Javier González   lightnvm: pblk: s...
183
184
185
  	struct pblk_g_ctx *m_ctx = nvm_rq_to_pdu(rqd);
  	struct pblk_line *line = m_ctx->private;
  	struct pblk_emeta *emeta = line->emeta;
dd2a43437   Javier González   lightnvm: pblk: s...
186
  	int sync;
3eaa11e27   Javier González   lightnvm: pblk: c...
187
  	pblk_up_page(pblk, rqd->ppa_list, rqd->nr_ppas);
dd2a43437   Javier González   lightnvm: pblk: s...
188
189
190
  
  	if (rqd->error) {
  		pblk_log_write_err(pblk, rqd);
ee8d5c1ad   Javier González   lightnvm: pblk: r...
191
192
  		pr_err("pblk: metadata I/O failed. Line %d
  ", line->id);
dd2a43437   Javier González   lightnvm: pblk: s...
193
194
195
196
197
198
199
200
201
  	}
  #ifdef CONFIG_NVM_DEBUG
  	else
  		WARN_ONCE(rqd->bio->bi_status, "pblk: corrupted write error
  ");
  #endif
  
  	sync = atomic_add_return(rqd->nr_ppas, &emeta->sync);
  	if (sync == emeta->nr_entries)
ef5764946   Javier González   lightnvm: pblk: s...
202
203
  		pblk_line_run_ws(pblk, line, NULL, pblk_line_close_ws,
  								pblk->close_wq);
dd2a43437   Javier González   lightnvm: pblk: s...
204
205
  
  	bio_put(rqd->bio);
3eaa11e27   Javier González   lightnvm: pblk: c...
206
  	nvm_dev_dma_free(dev->parent, rqd->meta_list, rqd->dma_meta_list);
dd2a43437   Javier González   lightnvm: pblk: s...
207
  	pblk_free_rqd(pblk, rqd, READ);
588726d3e   Javier González   lightnvm: pblk: f...
208
209
  
  	atomic_dec(&pblk->inflight_io);
dd2a43437   Javier González   lightnvm: pblk: s...
210
  }
a4bd217b4   Javier González   lightnvm: physica...
211
  static int pblk_alloc_w_rq(struct pblk *pblk, struct nvm_rq *rqd,
dd2a43437   Javier González   lightnvm: pblk: s...
212
213
  			   unsigned int nr_secs,
  			   nvm_end_io_fn(*end_io))
a4bd217b4   Javier González   lightnvm: physica...
214
215
216
217
218
219
220
221
  {
  	struct nvm_tgt_dev *dev = pblk->dev;
  
  	/* Setup write request */
  	rqd->opcode = NVM_OP_PWRITE;
  	rqd->nr_ppas = nr_secs;
  	rqd->flags = pblk_set_progr_mode(pblk, WRITE);
  	rqd->private = pblk;
dd2a43437   Javier González   lightnvm: pblk: s...
222
  	rqd->end_io = end_io;
a4bd217b4   Javier González   lightnvm: physica...
223
224
225
226
227
  
  	rqd->meta_list = nvm_dev_dma_alloc(dev->parent, GFP_KERNEL,
  							&rqd->dma_meta_list);
  	if (!rqd->meta_list)
  		return -ENOMEM;
a4bd217b4   Javier González   lightnvm: physica...
228
229
230
231
232
233
234
  	rqd->ppa_list = rqd->meta_list + pblk_dma_meta_size;
  	rqd->dma_ppa_list = rqd->dma_meta_list + pblk_dma_meta_size;
  
  	return 0;
  }
  
  static int pblk_setup_w_rq(struct pblk *pblk, struct nvm_rq *rqd,
d624f371d   Javier González   lightnvm: pblk: g...
235
  			   struct pblk_c_ctx *c_ctx, struct ppa_addr *erase_ppa)
a4bd217b4   Javier González   lightnvm: physica...
236
237
  {
  	struct pblk_line_meta *lm = &pblk->lm;
d624f371d   Javier González   lightnvm: pblk: g...
238
  	struct pblk_line *e_line = pblk_line_get_erase(pblk);
a4bd217b4   Javier González   lightnvm: physica...
239
240
241
242
243
244
245
  	unsigned int valid = c_ctx->nr_valid;
  	unsigned int padded = c_ctx->nr_padded;
  	unsigned int nr_secs = valid + padded;
  	unsigned long *lun_bitmap;
  	int ret = 0;
  
  	lun_bitmap = kzalloc(lm->lun_bitmap_len, GFP_KERNEL);
d624f371d   Javier González   lightnvm: pblk: g...
246
247
  	if (!lun_bitmap)
  		return -ENOMEM;
a4bd217b4   Javier González   lightnvm: physica...
248
  	c_ctx->lun_bitmap = lun_bitmap;
dd2a43437   Javier González   lightnvm: pblk: s...
249
  	ret = pblk_alloc_w_rq(pblk, rqd, nr_secs, pblk_end_io_write);
a4bd217b4   Javier González   lightnvm: physica...
250
251
  	if (ret) {
  		kfree(lun_bitmap);
d624f371d   Javier González   lightnvm: pblk: g...
252
  		return ret;
a4bd217b4   Javier González   lightnvm: physica...
253
  	}
588726d3e   Javier González   lightnvm: pblk: f...
254
  	if (likely(!e_line || !atomic_read(&e_line->left_eblks)))
a4bd217b4   Javier González   lightnvm: physica...
255
256
257
  		pblk_map_rq(pblk, rqd, c_ctx->sentry, lun_bitmap, valid, 0);
  	else
  		pblk_map_erase_rq(pblk, rqd, c_ctx->sentry, lun_bitmap,
d624f371d   Javier González   lightnvm: pblk: g...
258
  							valid, erase_ppa);
a4bd217b4   Javier González   lightnvm: physica...
259

d624f371d   Javier González   lightnvm: pblk: g...
260
  	return 0;
a4bd217b4   Javier González   lightnvm: physica...
261
262
263
264
265
266
267
268
269
270
271
272
273
274
  }
  
  int pblk_setup_w_rec_rq(struct pblk *pblk, struct nvm_rq *rqd,
  			struct pblk_c_ctx *c_ctx)
  {
  	struct pblk_line_meta *lm = &pblk->lm;
  	unsigned long *lun_bitmap;
  	int ret;
  
  	lun_bitmap = kzalloc(lm->lun_bitmap_len, GFP_KERNEL);
  	if (!lun_bitmap)
  		return -ENOMEM;
  
  	c_ctx->lun_bitmap = lun_bitmap;
dd2a43437   Javier González   lightnvm: pblk: s...
275
  	ret = pblk_alloc_w_rq(pblk, rqd, rqd->nr_ppas, pblk_end_io_write);
a4bd217b4   Javier González   lightnvm: physica...
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
  	if (ret)
  		return ret;
  
  	pblk_map_rq(pblk, rqd, c_ctx->sentry, lun_bitmap, c_ctx->nr_valid, 0);
  
  	rqd->ppa_status = (u64)0;
  	rqd->flags = pblk_set_progr_mode(pblk, WRITE);
  
  	return ret;
  }
  
  static int pblk_calc_secs_to_sync(struct pblk *pblk, unsigned int secs_avail,
  				  unsigned int secs_to_flush)
  {
  	int secs_to_sync;
  
  	secs_to_sync = pblk_calc_secs(pblk, secs_avail, secs_to_flush);
  
  #ifdef CONFIG_NVM_DEBUG
  	if ((!secs_to_sync && secs_to_flush)
  			|| (secs_to_sync < 0)
  			|| (secs_to_sync > secs_avail && !secs_to_flush)) {
  		pr_err("pblk: bad sector calculation (a:%d,s:%d,f:%d)
  ",
  				secs_avail, secs_to_sync, secs_to_flush);
  	}
  #endif
  
  	return secs_to_sync;
  }
dd2a43437   Javier González   lightnvm: pblk: s...
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
  static inline int pblk_valid_meta_ppa(struct pblk *pblk,
  				      struct pblk_line *meta_line,
  				      struct ppa_addr *ppa_list, int nr_ppas)
  {
  	struct nvm_tgt_dev *dev = pblk->dev;
  	struct nvm_geo *geo = &dev->geo;
  	struct pblk_line *data_line;
  	struct ppa_addr ppa, ppa_opt;
  	u64 paddr;
  	int i;
  
  	data_line = &pblk->lines[pblk_dev_ppa_to_line(ppa_list[0])];
  	paddr = pblk_lookup_page(pblk, meta_line);
  	ppa = addr_to_gen_ppa(pblk, paddr, 0);
  
  	if (test_bit(pblk_ppa_to_pos(geo, ppa), data_line->blk_bitmap))
  		return 1;
  
  	/* Schedule a metadata I/O that is half the distance from the data I/O
  	 * with regards to the number of LUNs forming the pblk instance. This
  	 * balances LUN conflicts across every I/O.
  	 *
  	 * When the LUN configuration changes (e.g., due to GC), this distance
  	 * can align, which would result on a LUN deadlock. In this case, modify
  	 * the distance to not be optimal, but allow metadata I/Os to succeed.
  	 */
  	ppa_opt = addr_to_gen_ppa(pblk, paddr + data_line->meta_distance, 0);
  	if (unlikely(ppa_opt.ppa == ppa.ppa)) {
  		data_line->meta_distance--;
  		return 0;
  	}
  
  	for (i = 0; i < nr_ppas; i += pblk->min_write_pgs)
  		if (ppa_list[i].g.ch == ppa_opt.g.ch &&
  					ppa_list[i].g.lun == ppa_opt.g.lun)
  			return 1;
  
  	if (test_bit(pblk_ppa_to_pos(geo, ppa_opt), data_line->blk_bitmap)) {
  		for (i = 0; i < nr_ppas; i += pblk->min_write_pgs)
  			if (ppa_list[i].g.ch == ppa.g.ch &&
  						ppa_list[i].g.lun == ppa.g.lun)
  				return 0;
  
  		return 1;
  	}
  
  	return 0;
  }
  
  int pblk_submit_meta_io(struct pblk *pblk, struct pblk_line *meta_line)
  {
  	struct nvm_tgt_dev *dev = pblk->dev;
  	struct nvm_geo *geo = &dev->geo;
  	struct pblk_line_mgmt *l_mg = &pblk->l_mg;
  	struct pblk_line_meta *lm = &pblk->lm;
  	struct pblk_emeta *emeta = meta_line->emeta;
  	struct pblk_g_ctx *m_ctx;
dd2a43437   Javier González   lightnvm: pblk: s...
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
  	struct bio *bio;
  	struct nvm_rq *rqd;
  	void *data;
  	u64 paddr;
  	int rq_ppas = pblk->min_write_pgs;
  	int id = meta_line->id;
  	int rq_len;
  	int i, j;
  	int ret;
  
  	rqd = pblk_alloc_rqd(pblk, READ);
  	if (IS_ERR(rqd)) {
  		pr_err("pblk: cannot allocate write req.
  ");
  		return PTR_ERR(rqd);
  	}
  	m_ctx = nvm_rq_to_pdu(rqd);
  	m_ctx->private = meta_line;
  
  	rq_len = rq_ppas * geo->sec_size;
  	data = ((void *)emeta->buf) + emeta->mem;
de54e703a   Javier González   lightnvm: pblk: u...
384
385
  	bio = pblk_bio_map_addr(pblk, data, rq_ppas, rq_len,
  					l_mg->emeta_alloc_type, GFP_KERNEL);
dd2a43437   Javier González   lightnvm: pblk: s...
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
  	if (IS_ERR(bio)) {
  		ret = PTR_ERR(bio);
  		goto fail_free_rqd;
  	}
  	bio->bi_iter.bi_sector = 0; /* internal bio */
  	bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
  	rqd->bio = bio;
  
  	ret = pblk_alloc_w_rq(pblk, rqd, rq_ppas, pblk_end_io_write_meta);
  	if (ret)
  		goto fail_free_bio;
  
  	for (i = 0; i < rqd->nr_ppas; ) {
  		spin_lock(&meta_line->lock);
  		paddr = __pblk_alloc_page(pblk, meta_line, rq_ppas);
  		spin_unlock(&meta_line->lock);
  		for (j = 0; j < rq_ppas; j++, i++, paddr++)
  			rqd->ppa_list[i] = addr_to_gen_ppa(pblk, paddr, id);
  	}
dd2a43437   Javier González   lightnvm: pblk: s...
405
406
407
408
409
410
411
412
413
  	emeta->mem += rq_len;
  	if (emeta->mem >= lm->emeta_len[0]) {
  		spin_lock(&l_mg->close_lock);
  		list_del(&meta_line->list);
  		WARN(!bitmap_full(meta_line->map_bitmap, lm->sec_per_line),
  				"pblk: corrupt meta line %d
  ", meta_line->id);
  		spin_unlock(&l_mg->close_lock);
  	}
3eaa11e27   Javier González   lightnvm: pblk: c...
414
  	pblk_down_page(pblk, rqd->ppa_list, rqd->nr_ppas);
dd2a43437   Javier González   lightnvm: pblk: s...
415
416
417
418
419
420
421
422
423
424
  	ret = pblk_submit_io(pblk, rqd);
  	if (ret) {
  		pr_err("pblk: emeta I/O submission failed: %d
  ", ret);
  		goto fail_rollback;
  	}
  
  	return NVM_IO_OK;
  
  fail_rollback:
3eaa11e27   Javier González   lightnvm: pblk: c...
425
  	pblk_up_page(pblk, rqd->ppa_list, rqd->nr_ppas);
dd2a43437   Javier González   lightnvm: pblk: s...
426
427
428
429
  	spin_lock(&l_mg->close_lock);
  	pblk_dealloc_page(pblk, meta_line, rq_ppas);
  	list_add(&meta_line->list, &meta_line->list);
  	spin_unlock(&l_mg->close_lock);
3eaa11e27   Javier González   lightnvm: pblk: c...
430
431
  
  	nvm_dev_dma_free(dev->parent, rqd->meta_list, rqd->dma_meta_list);
dd2a43437   Javier González   lightnvm: pblk: s...
432
  fail_free_bio:
f680f19aa   Javier González   lightnvm: pblk: s...
433
434
  	if (likely(l_mg->emeta_alloc_type == PBLK_VMALLOC_META))
  		bio_put(bio);
dd2a43437   Javier González   lightnvm: pblk: s...
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
  fail_free_rqd:
  	pblk_free_rqd(pblk, rqd, READ);
  	return ret;
  }
  
  static int pblk_sched_meta_io(struct pblk *pblk, struct ppa_addr *prev_list,
  			       int prev_n)
  {
  	struct pblk_line_meta *lm = &pblk->lm;
  	struct pblk_line_mgmt *l_mg = &pblk->l_mg;
  	struct pblk_line *meta_line;
  
  	spin_lock(&l_mg->close_lock);
  retry:
  	if (list_empty(&l_mg->emeta_list)) {
  		spin_unlock(&l_mg->close_lock);
  		return 0;
  	}
  	meta_line = list_first_entry(&l_mg->emeta_list, struct pblk_line, list);
  	if (bitmap_full(meta_line->map_bitmap, lm->sec_per_line))
  		goto retry;
  	spin_unlock(&l_mg->close_lock);
  
  	if (!pblk_valid_meta_ppa(pblk, meta_line, prev_list, prev_n))
  		return 0;
  
  	return pblk_submit_meta_io(pblk, meta_line);
  }
d624f371d   Javier González   lightnvm: pblk: g...
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
  static int pblk_submit_io_set(struct pblk *pblk, struct nvm_rq *rqd)
  {
  	struct pblk_c_ctx *c_ctx = nvm_rq_to_pdu(rqd);
  	struct ppa_addr erase_ppa;
  	int err;
  
  	ppa_set_empty(&erase_ppa);
  
  	/* Assign lbas to ppas and populate request structure */
  	err = pblk_setup_w_rq(pblk, rqd, c_ctx, &erase_ppa);
  	if (err) {
  		pr_err("pblk: could not setup write request: %d
  ", err);
  		return NVM_IO_ERR;
  	}
dd2a43437   Javier González   lightnvm: pblk: s...
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
  	if (likely(ppa_empty(erase_ppa))) {
  		/* Submit metadata write for previous data line */
  		err = pblk_sched_meta_io(pblk, rqd->ppa_list, rqd->nr_ppas);
  		if (err) {
  			pr_err("pblk: metadata I/O submission failed: %d", err);
  			return NVM_IO_ERR;
  		}
  
  		/* Submit data write for current data line */
  		err = pblk_submit_io(pblk, rqd);
  		if (err) {
  			pr_err("pblk: data I/O submission failed: %d
  ", err);
  			return NVM_IO_ERR;
  		}
  	} else {
  		/* Submit data write for current data line */
  		err = pblk_submit_io(pblk, rqd);
  		if (err) {
  			pr_err("pblk: data I/O submission failed: %d
  ", err);
  			return NVM_IO_ERR;
  		}
d624f371d   Javier González   lightnvm: pblk: g...
501

dd2a43437   Javier González   lightnvm: pblk: s...
502
503
504
505
506
507
508
509
510
511
512
  		/* Submit available erase for next data line */
  		if (pblk_blk_erase_async(pblk, erase_ppa)) {
  			struct pblk_line *e_line = pblk_line_get_erase(pblk);
  			struct nvm_tgt_dev *dev = pblk->dev;
  			struct nvm_geo *geo = &dev->geo;
  			int bit;
  
  			atomic_inc(&e_line->left_eblks);
  			bit = pblk_ppa_to_pos(geo, erase_ppa);
  			WARN_ON(!test_and_clear_bit(bit, e_line->erase_bitmap));
  		}
d624f371d   Javier González   lightnvm: pblk: g...
513
514
515
516
517
518
519
520
521
522
523
  	}
  
  	return NVM_IO_OK;
  }
  
  static void pblk_free_write_rqd(struct pblk *pblk, struct nvm_rq *rqd)
  {
  	struct pblk_c_ctx *c_ctx = nvm_rq_to_pdu(rqd);
  	struct bio *bio = rqd->bio;
  
  	if (c_ctx->nr_padded)
1508043c3   Javier González   lightnvm: pblk: f...
524
525
  		pblk_bio_free_pages(pblk, bio, c_ctx->nr_valid,
  							c_ctx->nr_padded);
d624f371d   Javier González   lightnvm: pblk: g...
526
  }
a4bd217b4   Javier González   lightnvm: physica...
527
528
529
530
  static int pblk_submit_write(struct pblk *pblk)
  {
  	struct bio *bio;
  	struct nvm_rq *rqd;
a4bd217b4   Javier González   lightnvm: physica...
531
532
533
  	unsigned int secs_avail, secs_to_sync, secs_to_com;
  	unsigned int secs_to_flush;
  	unsigned long pos;
a4bd217b4   Javier González   lightnvm: physica...
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
  
  	/* If there are no sectors in the cache, flushes (bios without data)
  	 * will be cleared on the cache threads
  	 */
  	secs_avail = pblk_rb_read_count(&pblk->rwb);
  	if (!secs_avail)
  		return 1;
  
  	secs_to_flush = pblk_rb_sync_point_count(&pblk->rwb);
  	if (!secs_to_flush && secs_avail < pblk->min_write_pgs)
  		return 1;
  
  	rqd = pblk_alloc_rqd(pblk, WRITE);
  	if (IS_ERR(rqd)) {
  		pr_err("pblk: cannot allocate write req.
  ");
  		return 1;
  	}
a4bd217b4   Javier González   lightnvm: physica...
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
  
  	bio = bio_alloc(GFP_KERNEL, pblk->max_write_pgs);
  	if (!bio) {
  		pr_err("pblk: cannot allocate write bio
  ");
  		goto fail_free_rqd;
  	}
  	bio->bi_iter.bi_sector = 0; /* internal bio */
  	bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
  	rqd->bio = bio;
  
  	secs_to_sync = pblk_calc_secs_to_sync(pblk, secs_avail, secs_to_flush);
  	if (secs_to_sync > pblk->max_write_pgs) {
  		pr_err("pblk: bad buffer sync calculation
  ");
  		goto fail_put_bio;
  	}
  
  	secs_to_com = (secs_to_sync > secs_avail) ? secs_avail : secs_to_sync;
  	pos = pblk_rb_read_commit(&pblk->rwb, secs_to_com);
d624f371d   Javier González   lightnvm: pblk: g...
572
573
  	if (pblk_rb_read_to_bio(&pblk->rwb, rqd, bio, pos, secs_to_sync,
  								secs_avail)) {
a4bd217b4   Javier González   lightnvm: physica...
574
575
576
577
  		pr_err("pblk: corrupted write bio
  ");
  		goto fail_put_bio;
  	}
d624f371d   Javier González   lightnvm: pblk: g...
578
  	if (pblk_submit_io_set(pblk, rqd))
a4bd217b4   Javier González   lightnvm: physica...
579
  		goto fail_free_bio;
a4bd217b4   Javier González   lightnvm: physica...
580
581
582
583
584
585
586
587
  
  #ifdef CONFIG_NVM_DEBUG
  	atomic_long_add(secs_to_sync, &pblk->sub_writes);
  #endif
  
  	return 0;
  
  fail_free_bio:
d624f371d   Javier González   lightnvm: pblk: g...
588
  	pblk_free_write_rqd(pblk, rqd);
a4bd217b4   Javier González   lightnvm: physica...
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
  fail_put_bio:
  	bio_put(bio);
  fail_free_rqd:
  	pblk_free_rqd(pblk, rqd, WRITE);
  
  	return 1;
  }
  
  int pblk_write_ts(void *data)
  {
  	struct pblk *pblk = data;
  
  	while (!kthread_should_stop()) {
  		if (!pblk_submit_write(pblk))
  			continue;
  		set_current_state(TASK_INTERRUPTIBLE);
  		io_schedule();
  	}
  
  	return 0;
  }