tools/llvm: Do not build with symbols
[minix3.git] / sys / ufs / chfs / ebh.c
blob47b33cb599234fc876233cfc814c52d2073e3970
1 /* $NetBSD: ebh.c,v 1.3 2012/08/10 09:26:58 ttoth Exp $ */
3 /*-
4 * Copyright (c) 2010 Department of Software Engineering,
5 * University of Szeged, Hungary
6 * Copyright (C) 2009 Ferenc Havasi <havasi@inf.u-szeged.hu>
7 * Copyright (C) 2009 Zoltan Sogor <weth@inf.u-szeged.hu>
8 * Copyright (C) 2009 David Tengeri <dtengeri@inf.u-szeged.hu>
9 * Copyright (C) 2009 Tamas Toth <ttoth@inf.u-szeged.hu>
10 * Copyright (C) 2010 Adam Hoka <ahoka@NetBSD.org>
11 * All rights reserved.
13 * This code is derived from software contributed to The NetBSD Foundation
14 * by the Department of Software Engineering, University of Szeged, Hungary
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
26 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
32 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
33 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
38 #include "ebh.h"
40 /*****************************************************************************/
41 /* Flash specific operations */
42 /*****************************************************************************/
43 int nor_create_eb_hdr(struct chfs_eb_hdr *ebhdr, int lnr);
44 int nand_create_eb_hdr(struct chfs_eb_hdr *ebhdr, int lnr);
45 int nor_calc_data_offs(struct chfs_ebh *ebh, int pebnr, int offset);
46 int nand_calc_data_offs(struct chfs_ebh *ebh, int pebnr, int offset);
47 int nor_read_eb_hdr(struct chfs_ebh *ebh, int pebnr, struct chfs_eb_hdr *ebhdr);
48 int nand_read_eb_hdr(struct chfs_ebh *ebh, int pebnr, struct chfs_eb_hdr *ebhdr);
49 int nor_write_eb_hdr(struct chfs_ebh *ebh, int pebnr, struct chfs_eb_hdr *ebhdr);
50 int nand_write_eb_hdr(struct chfs_ebh *ebh, int pebnr,struct chfs_eb_hdr *ebhdr);
51 int nor_check_eb_hdr(struct chfs_ebh *ebh, void *buf);
52 int nand_check_eb_hdr(struct chfs_ebh *ebh, void *buf);
53 int nor_mark_eb_hdr_dirty_flash(struct chfs_ebh *ebh, int pebnr, int lid);
54 int nor_invalidate_eb_hdr(struct chfs_ebh *ebh, int pebnr);
55 int mark_eb_hdr_free(struct chfs_ebh *ebh, int pebnr, int ec);
57 int ltree_entry_cmp(struct chfs_ltree_entry *le1, struct chfs_ltree_entry *le2);
58 int peb_in_use_cmp(struct chfs_peb *peb1, struct chfs_peb *peb2);
59 int peb_free_cmp(struct chfs_peb *peb1, struct chfs_peb *peb2);
60 int add_peb_to_erase_queue(struct chfs_ebh *ebh, int pebnr, int ec,struct peb_queue *queue);
61 struct chfs_peb * find_peb_in_use(struct chfs_ebh *ebh, int pebnr);
62 int add_peb_to_free(struct chfs_ebh *ebh, int pebnr, int ec);
63 int add_peb_to_in_use(struct chfs_ebh *ebh, int pebnr, int ec);
64 void erase_callback(struct flash_erase_instruction *ei);
65 int free_peb(struct chfs_ebh *ebh);
66 int release_peb(struct chfs_ebh *ebh, int pebnr);
67 void erase_thread(void *data);
68 static void erase_thread_start(struct chfs_ebh *ebh);
69 static void erase_thread_stop(struct chfs_ebh *ebh);
70 int scan_leb_used_cmp(struct chfs_scan_leb *sleb1, struct chfs_scan_leb *sleb2);
71 int nor_scan_add_to_used(struct chfs_ebh *ebh, struct chfs_scan_info *si,struct chfs_eb_hdr *ebhdr, int pebnr, int leb_status);
72 int nor_process_eb(struct chfs_ebh *ebh, struct chfs_scan_info *si,
73 int pebnr, struct chfs_eb_hdr *ebhdr);
74 int nand_scan_add_to_used(struct chfs_ebh *ebh, struct chfs_scan_info *si,struct chfs_eb_hdr *ebhdr, int pebnr);
75 int nand_process_eb(struct chfs_ebh *ebh, struct chfs_scan_info *si,
76 int pebnr, struct chfs_eb_hdr *ebhdr);
77 struct chfs_scan_info *chfs_scan(struct chfs_ebh *ebh);
78 void scan_info_destroy(struct chfs_scan_info *si);
79 int scan_media(struct chfs_ebh *ebh);
80 int get_peb(struct chfs_ebh *ebh);
81 /**
82 * nor_create_eb_hdr - creates an eraseblock header for NOR flash
83 * @ebhdr: ebhdr to set
84 * @lnr: LEB number
86 int
87 nor_create_eb_hdr(struct chfs_eb_hdr *ebhdr, int lnr)
89 ebhdr->u.nor_hdr.lid = htole32(lnr);
90 return 0;
93 /**
94 * nand_create_eb_hdr - creates an eraseblock header for NAND flash
95 * @ebhdr: ebhdr to set
96 * @lnr: LEB number
98 int
99 nand_create_eb_hdr(struct chfs_eb_hdr *ebhdr, int lnr)
101 ebhdr->u.nand_hdr.lid = htole32(lnr);
102 return 0;
106 * nor_calc_data_offs - calculates data offset on NOR flash
107 * @ebh: chfs eraseblock handler
108 * @pebnr: eraseblock number
109 * @offset: offset within the eraseblock
112 nor_calc_data_offs(struct chfs_ebh *ebh, int pebnr, int offset)
114 return pebnr * ebh->flash_if->erasesize + offset +
115 CHFS_EB_EC_HDR_SIZE + CHFS_EB_HDR_NOR_SIZE;
119 * nand_calc_data_offs - calculates data offset on NAND flash
120 * @ebh: chfs eraseblock handler
121 * @pebnr: eraseblock number
122 * @offset: offset within the eraseblock
125 nand_calc_data_offs(struct chfs_ebh *ebh, int pebnr, int offset)
127 return pebnr * ebh->flash_if->erasesize + offset +
128 2 * ebh->flash_if->page_size;
132 * nor_read_eb_hdr - read ereaseblock header from NOR flash
134 * @ebh: chfs eraseblock handler
135 * @pebnr: eraseblock number
136 * @ebhdr: whereto store the data
138 * Reads the eraseblock header from media.
139 * Returns zero in case of success, error code in case of fail.
142 nor_read_eb_hdr(struct chfs_ebh *ebh,
143 int pebnr, struct chfs_eb_hdr *ebhdr)
145 int ret;
146 size_t retlen;
147 off_t ofs = pebnr * ebh->flash_if->erasesize;
149 KASSERT(pebnr >= 0 && pebnr < ebh->peb_nr);
151 ret = flash_read(ebh->flash_dev,
152 ofs, CHFS_EB_EC_HDR_SIZE,
153 &retlen, (unsigned char *) &ebhdr->ec_hdr);
155 if (ret || retlen != CHFS_EB_EC_HDR_SIZE)
156 return ret;
158 ofs += CHFS_EB_EC_HDR_SIZE;
159 ret = flash_read(ebh->flash_dev,
160 ofs, CHFS_EB_HDR_NOR_SIZE,
161 &retlen, (unsigned char *) &ebhdr->u.nor_hdr);
163 if (ret || retlen != CHFS_EB_HDR_NOR_SIZE)
164 return ret;
166 return 0;
170 * nand_read_eb_hdr - read ereaseblock header from NAND flash
172 * @ebh: chfs eraseblock handler
173 * @pebnr: eraseblock number
174 * @ebhdr: whereto store the data
176 * Reads the eraseblock header from media. It is on the first two page.
177 * Returns zero in case of success, error code in case of fail.
180 nand_read_eb_hdr(struct chfs_ebh *ebh, int pebnr,
181 struct chfs_eb_hdr *ebhdr)
183 int ret;
184 size_t retlen;
185 off_t ofs;
187 KASSERT(pebnr >= 0 && pebnr < ebh->peb_nr);
189 /* Read erase counter header from the first page. */
190 ofs = pebnr * ebh->flash_if->erasesize;
191 ret = flash_read(ebh->flash_dev,
192 ofs, CHFS_EB_EC_HDR_SIZE, &retlen,
193 (unsigned char *) &ebhdr->ec_hdr);
194 if (ret || retlen != CHFS_EB_EC_HDR_SIZE)
195 return ret;
197 /* Read NAND eraseblock header from the second page */
198 ofs += ebh->flash_if->page_size;
199 ret = flash_read(ebh->flash_dev,
200 ofs, CHFS_EB_HDR_NAND_SIZE, &retlen,
201 (unsigned char *) &ebhdr->u.nand_hdr);
202 if (ret || retlen != CHFS_EB_HDR_NAND_SIZE)
203 return ret;
205 return 0;
209 * nor_write_eb_hdr - write ereaseblock header to NOR flash
211 * @ebh: chfs eraseblock handler
212 * @pebnr: eraseblock number whereto write
213 * @ebh: ebh to write
215 * Writes the eraseblock header to media.
216 * Returns zero in case of success, error code in case of fail.
219 nor_write_eb_hdr(struct chfs_ebh *ebh, int pebnr, struct chfs_eb_hdr *ebhdr)
221 int ret, crc;
222 size_t retlen;
224 off_t ofs = pebnr * ebh->flash_if->erasesize + CHFS_EB_EC_HDR_SIZE;
226 ebhdr->u.nor_hdr.lid = ebhdr->u.nor_hdr.lid
227 | htole32(CHFS_LID_NOT_DIRTY_BIT);
229 crc = crc32(0, (uint8_t *)&ebhdr->u.nor_hdr + 4,
230 CHFS_EB_HDR_NOR_SIZE - 4);
231 ebhdr->u.nand_hdr.crc = htole32(crc);
233 KASSERT(pebnr >= 0 && pebnr < ebh->peb_nr);
235 ret = flash_write(ebh->flash_dev,
236 ofs, CHFS_EB_HDR_NOR_SIZE, &retlen,
237 (unsigned char *) &ebhdr->u.nor_hdr);
239 if (ret || retlen != CHFS_EB_HDR_NOR_SIZE)
240 return ret;
242 return 0;
246 * nand_write_eb_hdr - write ereaseblock header to NAND flash
248 * @ebh: chfs eraseblock handler
249 * @pebnr: eraseblock number whereto write
250 * @ebh: ebh to write
252 * Writes the eraseblock header to media.
253 * Returns zero in case of success, error code in case of fail.
256 nand_write_eb_hdr(struct chfs_ebh *ebh, int pebnr,
257 struct chfs_eb_hdr *ebhdr)
259 int ret, crc;
260 size_t retlen;
261 flash_off_t ofs;
263 KASSERT(pebnr >= 0 && pebnr < ebh->peb_nr);
265 ofs = pebnr * ebh->flash_if->erasesize +
266 ebh->flash_if->page_size;
268 ebhdr->u.nand_hdr.serial = htole64(++(*ebh->max_serial));
270 crc = crc32(0, (uint8_t *)&ebhdr->u.nand_hdr + 4,
271 CHFS_EB_HDR_NAND_SIZE - 4);
272 ebhdr->u.nand_hdr.crc = htole32(crc);
274 ret = flash_write(ebh->flash_dev, ofs,
275 CHFS_EB_HDR_NAND_SIZE, &retlen,
276 (unsigned char *) &ebhdr->u.nand_hdr);
278 if (ret || retlen != CHFS_EB_HDR_NAND_SIZE)
279 return ret;
281 return 0;
285 * nor_check_eb_hdr - check ereaseblock header read from NOR flash
287 * @ebh: chfs eraseblock handler
288 * @buf: eraseblock header to check
290 * Returns eraseblock header status.
293 nor_check_eb_hdr(struct chfs_ebh *ebh, void *buf)
295 uint32_t magic, crc, hdr_crc;
296 struct chfs_eb_hdr *ebhdr = buf;
297 le32 lid_save;
299 //check is there a header
300 if (check_pattern((void *) &ebhdr->ec_hdr,
301 0xFF, 0, CHFS_EB_EC_HDR_SIZE)) {
302 dbg_ebh("no header found\n");
303 return EBHDR_LEB_NO_HDR;
306 // check magic
307 magic = le32toh(ebhdr->ec_hdr.magic);
308 if (magic != CHFS_MAGIC_BITMASK) {
309 dbg_ebh("bad magic bitmask(exp: %x found %x)\n",
310 CHFS_MAGIC_BITMASK, magic);
311 return EBHDR_LEB_BADMAGIC;
314 // check CRC_EC
315 hdr_crc = le32toh(ebhdr->ec_hdr.crc_ec);
316 crc = crc32(0, (uint8_t *) &ebhdr->ec_hdr + 8, 4);
317 if (hdr_crc != crc) {
318 dbg_ebh("bad crc_ec found\n");
319 return EBHDR_LEB_BADCRC;
322 /* check if the PEB is free: magic, crc_ec and erase_cnt is good and
323 * everything else is FFF..
325 if (check_pattern((void *) &ebhdr->u.nor_hdr, 0xFF, 0,
326 CHFS_EB_HDR_NOR_SIZE)) {
327 dbg_ebh("free peb found\n");
328 return EBHDR_LEB_FREE;
331 // check invalidated (CRC == LID == 0)
332 if (ebhdr->u.nor_hdr.crc == 0 && ebhdr->u.nor_hdr.lid == 0) {
333 dbg_ebh("invalidated ebhdr found\n");
334 return EBHDR_LEB_INVALIDATED;
337 // check CRC
338 hdr_crc = le32toh(ebhdr->u.nor_hdr.crc);
339 lid_save = ebhdr->u.nor_hdr.lid;
341 // mark lid as not dirty for crc calc
342 ebhdr->u.nor_hdr.lid = ebhdr->u.nor_hdr.lid | htole32(
343 CHFS_LID_NOT_DIRTY_BIT);
344 crc = crc32(0, (uint8_t *) &ebhdr->u.nor_hdr + 4,
345 CHFS_EB_HDR_NOR_SIZE - 4);
346 // restore the original lid value in ebh
347 ebhdr->u.nor_hdr.lid = lid_save;
349 if (crc != hdr_crc) {
350 dbg_ebh("bad crc found\n");
351 return EBHDR_LEB_BADCRC;
354 // check dirty
355 if (!(le32toh(lid_save) & CHFS_LID_NOT_DIRTY_BIT)) {
356 dbg_ebh("dirty ebhdr found\n");
357 return EBHDR_LEB_DIRTY;
360 return EBHDR_LEB_OK;
364 * nand_check_eb_hdr - check ereaseblock header read from NAND flash
366 * @ebh: chfs eraseblock handler
367 * @buf: eraseblock header to check
369 * Returns eraseblock header status.
372 nand_check_eb_hdr(struct chfs_ebh *ebh, void *buf)
374 uint32_t magic, crc, hdr_crc;
375 struct chfs_eb_hdr *ebhdr = buf;
377 //check is there a header
378 if (check_pattern((void *) &ebhdr->ec_hdr,
379 0xFF, 0, CHFS_EB_EC_HDR_SIZE)) {
380 dbg_ebh("no header found\n");
381 return EBHDR_LEB_NO_HDR;
384 // check magic
385 magic = le32toh(ebhdr->ec_hdr.magic);
386 if (magic != CHFS_MAGIC_BITMASK) {
387 dbg_ebh("bad magic bitmask(exp: %x found %x)\n",
388 CHFS_MAGIC_BITMASK, magic);
389 return EBHDR_LEB_BADMAGIC;
392 // check CRC_EC
393 hdr_crc = le32toh(ebhdr->ec_hdr.crc_ec);
394 crc = crc32(0, (uint8_t *) &ebhdr->ec_hdr + 8, 4);
395 if (hdr_crc != crc) {
396 dbg_ebh("bad crc_ec found\n");
397 return EBHDR_LEB_BADCRC;
400 /* check if the PEB is free: magic, crc_ec and erase_cnt is good and
401 * everything else is FFF..
403 if (check_pattern((void *) &ebhdr->u.nand_hdr, 0xFF, 0,
404 CHFS_EB_HDR_NAND_SIZE)) {
405 dbg_ebh("free peb found\n");
406 return EBHDR_LEB_FREE;
409 // check CRC
410 hdr_crc = le32toh(ebhdr->u.nand_hdr.crc);
412 crc = crc32(0, (uint8_t *) &ebhdr->u.nand_hdr + 4,
413 CHFS_EB_HDR_NAND_SIZE - 4);
415 if (crc != hdr_crc) {
416 dbg_ebh("bad crc found\n");
417 return EBHDR_LEB_BADCRC;
420 return EBHDR_LEB_OK;
424 * nor_mark_eb_hdr_dirty_flash- mark ereaseblock header dirty on NOR flash
426 * @ebh: chfs eraseblock handler
427 * @pebnr: eraseblock number
428 * @lid: leb id (it's bit number 31 will be set to 0)
430 * It pulls the CHFS_LID_NOT_DIRTY_BIT to zero on flash.
432 * Returns zero in case of success, error code in case of fail.
435 nor_mark_eb_hdr_dirty_flash(struct chfs_ebh *ebh, int pebnr, int lid)
437 int ret;
438 size_t retlen;
439 off_t ofs;
441 /* mark leb id dirty */
442 lid = htole32(lid & CHFS_LID_DIRTY_BIT_MASK);
444 /* calculate position */
445 ofs = pebnr * ebh->flash_if->erasesize + CHFS_EB_EC_HDR_SIZE
446 + CHFS_GET_MEMBER_POS(struct chfs_nor_eb_hdr , lid);
448 ret = flash_write(ebh->flash_dev, ofs, sizeof(lid), &retlen,
449 (unsigned char *) &lid);
450 if (ret || retlen != sizeof(lid)) {
451 chfs_err("can't mark peb dirty");
452 return ret;
455 return 0;
459 * nor_invalidate_eb_hdr - invalidate ereaseblock header on NOR flash
461 * @ebh: chfs eraseblock handler
462 * @pebnr: eraseblock number
464 * Sets crc and lip field to zero.
465 * Returns zero in case of success, error code in case of fail.
468 nor_invalidate_eb_hdr(struct chfs_ebh *ebh, int pebnr)
470 int ret;
471 size_t retlen;
472 off_t ofs;
473 char zero_buf[CHFS_INVALIDATE_SIZE];
475 /* fill with zero */
476 memset(zero_buf, 0x0, CHFS_INVALIDATE_SIZE);
478 /* calculate position (!!! lid is directly behind crc !!!) */
479 ofs = pebnr * ebh->flash_if->erasesize + CHFS_EB_EC_HDR_SIZE
480 + CHFS_GET_MEMBER_POS(struct chfs_nor_eb_hdr, crc);
482 ret = flash_write(ebh->flash_dev,
483 ofs, CHFS_INVALIDATE_SIZE, &retlen,
484 (unsigned char *) &zero_buf);
485 if (ret || retlen != CHFS_INVALIDATE_SIZE) {
486 chfs_err("can't invalidate peb");
487 return ret;
490 return 0;
494 * mark_eb_hdr_free - free ereaseblock header on NOR or NAND flash
496 * @ebh: chfs eraseblock handler
497 * @pebnr: eraseblock number
498 * @ec: erase counter of PEB
500 * Write out the magic and erase counter to the physical eraseblock.
501 * Returns zero in case of success, error code in case of fail.
504 mark_eb_hdr_free(struct chfs_ebh *ebh, int pebnr, int ec)
506 int ret, crc;
507 size_t retlen;
508 off_t ofs;
509 struct chfs_eb_hdr *ebhdr;
510 ebhdr = kmem_alloc(sizeof(struct chfs_eb_hdr), KM_SLEEP);
512 ebhdr->ec_hdr.magic = htole32(CHFS_MAGIC_BITMASK);
513 ebhdr->ec_hdr.erase_cnt = htole32(ec);
514 crc = crc32(0, (uint8_t *) &ebhdr->ec_hdr + 8, 4);
515 ebhdr->ec_hdr.crc_ec = htole32(crc);
517 ofs = pebnr * ebh->flash_if->erasesize;
519 KASSERT(sizeof(ebhdr->ec_hdr) == CHFS_EB_EC_HDR_SIZE);
521 ret = flash_write(ebh->flash_dev,
522 ofs, CHFS_EB_EC_HDR_SIZE, &retlen,
523 (unsigned char *) &ebhdr->ec_hdr);
525 if (ret || retlen != CHFS_EB_EC_HDR_SIZE) {
526 chfs_err("can't mark peb as free: %d\n", pebnr);
527 kmem_free(ebhdr, sizeof(struct chfs_eb_hdr));
528 return ret;
531 kmem_free(ebhdr, sizeof(struct chfs_eb_hdr));
532 return 0;
535 /*****************************************************************************/
536 /* End of Flash specific operations */
537 /*****************************************************************************/
539 /*****************************************************************************/
540 /* Lock Tree */
541 /*****************************************************************************/
544 ltree_entry_cmp(struct chfs_ltree_entry *le1,
545 struct chfs_ltree_entry *le2)
547 return (le1->lnr - le2->lnr);
550 /* Generate functions for Lock tree's red-black tree */
551 RB_PROTOTYPE( ltree_rbtree, chfs_ltree_entry, rb, ltree_entry_cmp);
552 RB_GENERATE( ltree_rbtree, chfs_ltree_entry, rb, ltree_entry_cmp);
556 * ltree_lookup - looks up a logical eraseblock in the lock tree
557 * @ebh: chfs eraseblock handler
558 * @lid: identifier of the logical eraseblock
560 * This function returns a pointer to the wanted &struct chfs_ltree_entry
561 * if the logical eraseblock is in the lock tree, so it is locked, NULL
562 * otherwise.
563 * @ebh->ltree_lock has to be locked!
565 static struct chfs_ltree_entry *
566 ltree_lookup(struct chfs_ebh *ebh, int lnr)
568 struct chfs_ltree_entry le, *result;
569 le.lnr = lnr;
570 result = RB_FIND(ltree_rbtree, &ebh->ltree, &le);
571 return result;
575 * ltree_add_entry - add an entry to the lock tree
576 * @ebh: chfs eraseblock handler
577 * @lnr: identifier of the logical eraseblock
579 * This function adds a new logical eraseblock entry identified with @lnr to the
580 * lock tree. If the entry is already in the tree, it increases the user
581 * counter.
582 * Returns NULL if can not allocate memory for lock tree entry, or a pointer
583 * to the inserted entry otherwise.
585 static struct chfs_ltree_entry *
586 ltree_add_entry(struct chfs_ebh *ebh, int lnr)
588 struct chfs_ltree_entry *le, *result;
590 le = kmem_alloc(sizeof(struct chfs_ltree_entry), KM_SLEEP);
592 le->lnr = lnr;
593 le->users = 1;
594 rw_init(&le->mutex);
596 //dbg_ebh("enter ltree lock\n");
597 mutex_enter(&ebh->ltree_lock);
598 //dbg_ebh("insert\n");
599 result = RB_INSERT(ltree_rbtree, &ebh->ltree, le);
600 //dbg_ebh("inserted\n");
601 if (result) {
602 //The entry is already in the tree
603 result->users++;
604 kmem_free(le, sizeof(struct chfs_ltree_entry));
606 else {
607 result = le;
609 mutex_exit(&ebh->ltree_lock);
611 return result;
615 * leb_read_lock - lock a logical eraseblock for read
616 * @ebh: chfs eraseblock handler
617 * @lnr: identifier of the logical eraseblock
619 * Returns zero in case of success, error code in case of fail.
621 static int
622 leb_read_lock(struct chfs_ebh *ebh, int lnr)
624 struct chfs_ltree_entry *le;
626 le = ltree_add_entry(ebh, lnr);
627 if (!le)
628 return ENOMEM;
630 rw_enter(&le->mutex, RW_READER);
631 return 0;
635 * leb_read_unlock - unlock a logical eraseblock from read
636 * @ebh: chfs eraseblock handler
637 * @lnr: identifier of the logical eraseblock
639 * This function unlocks a logical eraseblock from read and delete it from the
640 * lock tree is there are no more users of it.
642 static void
643 leb_read_unlock(struct chfs_ebh *ebh, int lnr)
645 struct chfs_ltree_entry *le;
647 mutex_enter(&ebh->ltree_lock);
648 //dbg_ebh("LOCK: ebh->ltree_lock spin locked in leb_read_unlock()\n");
649 le = ltree_lookup(ebh, lnr);
650 if (!le)
651 goto out;
653 le->users -= 1;
654 KASSERT(le->users >= 0);
655 rw_exit(&le->mutex);
656 if (le->users == 0) {
657 le = RB_REMOVE(ltree_rbtree, &ebh->ltree, le);
658 if (le) {
659 KASSERT(!rw_lock_held(&le->mutex));
660 rw_destroy(&le->mutex);
662 kmem_free(le, sizeof(struct chfs_ltree_entry));
666 out:
667 mutex_exit(&ebh->ltree_lock);
668 //dbg_ebh("UNLOCK: ebh->ltree_lock spin unlocked in leb_read_unlock()\n");
672 * leb_write_lock - lock a logical eraseblock for write
673 * @ebh: chfs eraseblock handler
674 * @lnr: identifier of the logical eraseblock
676 * Returns zero in case of success, error code in case of fail.
678 static int
679 leb_write_lock(struct chfs_ebh *ebh, int lnr)
681 struct chfs_ltree_entry *le;
683 le = ltree_add_entry(ebh, lnr);
684 if (!le)
685 return ENOMEM;
687 rw_enter(&le->mutex, RW_WRITER);
688 return 0;
692 * leb_write_unlock - unlock a logical eraseblock from write
693 * @ebh: chfs eraseblock handler
694 * @lnr: identifier of the logical eraseblock
696 * This function unlocks a logical eraseblock from write and delete it from the
697 * lock tree is there are no more users of it.
699 static void
700 leb_write_unlock(struct chfs_ebh *ebh, int lnr)
702 struct chfs_ltree_entry *le;
704 mutex_enter(&ebh->ltree_lock);
705 //dbg_ebh("LOCK: ebh->ltree_lock spin locked in leb_write_unlock()\n");
706 le = ltree_lookup(ebh, lnr);
707 if (!le)
708 goto out;
710 le->users -= 1;
711 KASSERT(le->users >= 0);
712 rw_exit(&le->mutex);
713 if (le->users == 0) {
714 RB_REMOVE(ltree_rbtree, &ebh->ltree, le);
716 KASSERT(!rw_lock_held(&le->mutex));
717 rw_destroy(&le->mutex);
719 kmem_free(le, sizeof(struct chfs_ltree_entry));
722 out:
723 mutex_exit(&ebh->ltree_lock);
724 //dbg_ebh("UNLOCK: ebh->ltree_lock spin unlocked in leb_write_unlock()\n");
727 /*****************************************************************************/
728 /* End of Lock Tree */
729 /*****************************************************************************/
731 /*****************************************************************************/
732 /* Erase related operations */
733 /*****************************************************************************/
736 * If the first argument is smaller than the second, the function
737 * returns a value smaller than zero. If they are equal, the function re-
738 * turns zero. Otherwise, it should return a value greater than zero.
741 peb_in_use_cmp(struct chfs_peb *peb1, struct chfs_peb *peb2)
743 return (peb1->pebnr - peb2->pebnr);
747 peb_free_cmp(struct chfs_peb *peb1, struct chfs_peb *peb2)
749 int comp;
751 comp = peb1->erase_cnt - peb2->erase_cnt;
752 if (0 == comp)
753 comp = peb1->pebnr - peb2->pebnr;
755 return comp;
758 /* Generate functions for in use PEB's red-black tree */
759 RB_PROTOTYPE(peb_in_use_rbtree, chfs_peb, u.rb, peb_in_use_cmp);
760 RB_GENERATE(peb_in_use_rbtree, chfs_peb, u.rb, peb_in_use_cmp);
761 RB_PROTOTYPE(peb_free_rbtree, chfs_peb, u.rb, peb_free_cmp);
762 RB_GENERATE(peb_free_rbtree, chfs_peb, u.rb, peb_free_cmp);
765 * add_peb_to_erase_queue: adds a PEB to to_erase/fully_erased queue
766 * @ebh - chfs eraseblock handler
767 * @pebnr - physical eraseblock's number
768 * @ec - erase counter of PEB
769 * @queue: the queue to add to
771 * This function adds a PEB to the erase queue specified by @queue.
772 * The @ebh->erase_lock must be locked before using this.
773 * Returns zero in case of success, error code in case of fail.
776 add_peb_to_erase_queue(struct chfs_ebh *ebh, int pebnr, int ec,
777 struct peb_queue *queue)
779 struct chfs_peb *peb;
781 peb = kmem_alloc(sizeof(struct chfs_peb), KM_SLEEP);
783 peb->erase_cnt = ec;
784 peb->pebnr = pebnr;
786 TAILQ_INSERT_TAIL(queue, peb, u.queue);
788 return 0;
791 //TODO
793 * find_peb_in_use - looks up a PEB in the RB-tree of used blocks
794 * @ebh - chfs eraseblock handler
796 * This function returns a pointer to the PEB found in the tree,
797 * NULL otherwise.
798 * The @ebh->erase_lock must be locked before using this.
800 struct chfs_peb *
801 find_peb_in_use(struct chfs_ebh *ebh, int pebnr)
803 struct chfs_peb peb, *result;
804 peb.pebnr = pebnr;
805 result = RB_FIND(peb_in_use_rbtree, &ebh->in_use, &peb);
806 return result;
810 * add_peb_to_free - adds a PEB to the RB-tree of free PEBs
811 * @ebh - chfs eraseblock handler
812 * @pebnr - physical eraseblock's number
813 * @ec - erase counter of PEB
816 * This function adds a physical eraseblock to the RB-tree of free PEBs
817 * stored in the @ebh. The key is the erase counter and pebnr.
818 * The @ebh->erase_lock must be locked before using this.
819 * Returns zero in case of success, error code in case of fail.
822 add_peb_to_free(struct chfs_ebh *ebh, int pebnr, int ec)
824 struct chfs_peb *peb, *result;
826 peb = kmem_alloc(sizeof(struct chfs_peb), KM_SLEEP);
828 peb->erase_cnt = ec;
829 peb->pebnr = pebnr;
830 result = RB_INSERT(peb_free_rbtree, &ebh->free, peb);
831 if (result)
832 return 1;
834 return 0;
838 * add_peb_to_in_use - adds a PEB to the RB-tree of used PEBs
839 * @ebh - chfs eraseblock handler
840 * @pebnr - physical eraseblock's number
841 * @ec - erase counter of PEB
844 * This function adds a physical eraseblock to the RB-tree of used PEBs
845 * stored in the @ebh. The key is pebnr.
846 * The @ebh->erase_lock must be locked before using this.
847 * Returns zero in case of success, error code in case of fail.
850 add_peb_to_in_use(struct chfs_ebh *ebh, int pebnr, int ec)
852 struct chfs_peb *peb, *result;
854 peb = kmem_alloc(sizeof(struct chfs_peb), KM_SLEEP);
856 peb->erase_cnt = ec;
857 peb->pebnr = pebnr;
858 result = RB_INSERT(peb_in_use_rbtree, &ebh->in_use, peb);
859 if (result)
860 return 1;
862 return 0;
866 * erase_callback - callback function for flash erase
867 * @ei: erase information
869 void
870 erase_callback(struct flash_erase_instruction *ei)
872 int err;
873 struct chfs_erase_info_priv *priv = (void *) ei->ei_priv;
874 //dbg_ebh("ERASE_CALLBACK() CALLED\n");
875 struct chfs_ebh *ebh = priv->ebh;
876 struct chfs_peb *peb = priv->peb;
878 peb->erase_cnt += 1;
880 if (ei->ei_state == FLASH_ERASE_DONE) {
882 /* Write out erase counter */
883 err = ebh->ops->mark_eb_hdr_free(ebh,
884 peb->pebnr, peb->erase_cnt);
885 if (err) {
886 /* cannot mark PEB as free,so erase it again */
887 chfs_err(
888 "cannot mark eraseblock as free, PEB: %d\n",
889 peb->pebnr);
890 mutex_enter(&ebh->erase_lock);
891 /*dbg_ebh("LOCK: ebh->erase_lock spin locked in erase_callback() "
892 "after mark ebhdr free\n");*/
893 add_peb_to_erase_queue(ebh, peb->pebnr, peb->erase_cnt,
894 &ebh->to_erase);
895 mutex_exit(&ebh->erase_lock);
896 /*dbg_ebh("UNLOCK: ebh->erase_lock spin unlocked in erase_callback() "
897 "after mark ebhdr free\n");*/
898 kmem_free(peb, sizeof(struct chfs_peb));
899 return;
902 mutex_enter(&ebh->erase_lock);
903 /*dbg_ebh("LOCK: ebh->erase_lock spin locked in erase_callback()\n");*/
904 err = add_peb_to_free(ebh, peb->pebnr, peb->erase_cnt);
905 mutex_exit(&ebh->erase_lock);
906 /*dbg_ebh("UNLOCK: ebh->erase_lock spin unlocked in erase_callback()\n");*/
907 kmem_free(peb, sizeof(struct chfs_peb));
908 } else {
910 * Erase is finished, but there was a problem,
911 * so erase PEB again
913 chfs_err("erase failed, state is: 0x%x\n", ei->ei_state);
914 add_peb_to_erase_queue(ebh, peb->pebnr, peb->erase_cnt, &ebh->to_erase);
915 kmem_free(peb, sizeof(struct chfs_peb));
920 * free_peb: free a PEB
921 * @ebh: chfs eraseblock handler
923 * This function erases the first physical eraseblock from one of the erase
924 * lists and adds to the RB-tree of free PEBs.
925 * Returns zero in case of succes, error code in case of fail.
928 free_peb(struct chfs_ebh *ebh)
930 int err, retries = 0;
931 off_t ofs;
932 struct chfs_peb *peb = NULL;
933 struct flash_erase_instruction *ei;
935 KASSERT(mutex_owned(&ebh->erase_lock));
937 if (!TAILQ_EMPTY(&ebh->fully_erased)) {
938 //dbg_ebh("[FREE PEB] got a fully erased block\n");
939 peb = TAILQ_FIRST(&ebh->fully_erased);
940 TAILQ_REMOVE(&ebh->fully_erased, peb, u.queue);
941 err = ebh->ops->mark_eb_hdr_free(ebh,
942 peb->pebnr, peb->erase_cnt);
943 if (err) {
944 goto out_free;
946 err = add_peb_to_free(ebh, peb->pebnr, peb->erase_cnt);
947 goto out_free;
949 /* Erase PEB */
950 //dbg_ebh("[FREE PEB] eraseing a block\n");
951 peb = TAILQ_FIRST(&ebh->to_erase);
952 TAILQ_REMOVE(&ebh->to_erase, peb, u.queue);
953 mutex_exit(&ebh->erase_lock);
954 //dbg_ebh("UNLOCK: ebh->erase_lock spin unlocked in free_peb()\n");
955 ofs = peb->pebnr * ebh->flash_if->erasesize;
957 /* XXX where do we free this? */
958 ei = kmem_alloc(sizeof(struct flash_erase_instruction)
959 + sizeof(struct chfs_erase_info_priv), KM_SLEEP);
960 retry:
961 memset(ei, 0, sizeof(*ei));
963 // ei->ei_if = ebh->flash_if;
964 ei->ei_addr = ofs;
965 ei->ei_len = ebh->flash_if->erasesize;
966 ei->ei_callback = erase_callback;
967 ei->ei_priv = (unsigned long) (&ei[1]);
969 ((struct chfs_erase_info_priv *) ei->ei_priv)->ebh = ebh;
970 ((struct chfs_erase_info_priv *) ei->ei_priv)->peb = peb;
972 err = flash_erase(ebh->flash_dev, ei);
973 dbg_ebh("erased peb: %d\n", peb->pebnr);
975 /* einval would mean we did something wrong */
976 KASSERT(err != EINVAL);
978 if (err) {
979 dbg_ebh("errno: %d, ei->ei_state: %d\n", err, ei->ei_state);
980 if (CHFS_MAX_GET_PEB_RETRIES < ++retries &&
981 ei->ei_state == FLASH_ERASE_FAILED) {
982 /* The block went bad mark it */
983 dbg_ebh("ebh markbad! 0x%jx\n", (uintmax_t )ofs);
984 err = flash_block_markbad(ebh->flash_dev, ofs);
985 if (!err) {
986 ebh->peb_nr--;
989 goto out;
991 chfs_err("can not erase PEB: %d, try again\n", peb->pebnr);
992 goto retry;
995 out:
996 /* lock the erase_lock, because it was locked
997 * when the function was called */
998 mutex_enter(&ebh->erase_lock);
999 return err;
1001 out_free:
1002 kmem_free(peb, sizeof(struct chfs_peb));
1003 return err;
1007 * release_peb - schedule an erase for the PEB
1008 * @ebh: chfs eraseblock handler
1009 * @pebnr: physical eraseblock number
1011 * This function get the peb identified by @pebnr from the in_use RB-tree of
1012 * @ebh, removes it and schedule an erase for it.
1014 * Returns zero on success, error code in case of fail.
1017 release_peb(struct chfs_ebh *ebh, int pebnr)
1019 int err = 0;
1020 struct chfs_peb *peb;
1022 mutex_enter(&ebh->erase_lock);
1024 //dbg_ebh("LOCK: ebh->erase_lock spin locked in release_peb()\n");
1025 peb = find_peb_in_use(ebh, pebnr);
1026 if (!peb) {
1027 chfs_err("LEB is mapped, but is not in the 'in_use' "
1028 "tree of ebh\n");
1029 goto out_unlock;
1031 err = add_peb_to_erase_queue(ebh, peb->pebnr, peb->erase_cnt,
1032 &ebh->to_erase);
1034 if (err)
1035 goto out_unlock;
1037 RB_REMOVE(peb_in_use_rbtree, &ebh->in_use, peb);
1038 out_unlock:
1039 mutex_exit(&ebh->erase_lock);
1040 //dbg_ebh("UNLOCK: ebh->erase_lock spin unlocked in release_peb()"
1041 // " at out_unlock\n");
1042 return err;
1046 * erase_thread - background thread for erasing PEBs
1047 * @data: pointer to the eraseblock handler
1049 /*void
1050 erase_thread(void *data)
1052 struct chfs_ebh *ebh = data;
1054 dbg_ebh("erase thread started\n");
1055 while (ebh->bg_erase.eth_running) {
1056 int err;
1058 mutex_enter(&ebh->erase_lock);
1059 dbg_ebh("LOCK: ebh->erase_lock spin locked in erase_thread()\n");
1060 if (TAILQ_EMPTY(&ebh->to_erase) && TAILQ_EMPTY(&ebh->fully_erased)) {
1061 dbg_ebh("thread has nothing to do\n");
1062 mutex_exit(&ebh->erase_lock);
1063 mutex_enter(&ebh->bg_erase.eth_thread_mtx);
1064 cv_timedwait_sig(&ebh->bg_erase.eth_wakeup,
1065 &ebh->bg_erase.eth_thread_mtx, mstohz(100));
1066 mutex_exit(&ebh->bg_erase.eth_thread_mtx);
1068 dbg_ebh("UNLOCK: ebh->erase_lock spin unlocked in erase_thread()\n");
1069 continue;
1071 mutex_exit(&ebh->erase_lock);
1072 dbg_ebh("UNLOCK: ebh->erase_lock spin unlocked in erase_thread()\n");
1074 err = free_peb(ebh);
1075 if (err)
1076 chfs_err("freeing PEB failed in the background thread: %d\n", err);
1079 dbg_ebh("erase thread stopped\n");
1080 kthread_exit(0);
1084 * erase_thread - background thread for erasing PEBs
1085 * @data: pointer to the eraseblock handler
1087 void
1088 erase_thread(void *data) {
1089 dbg_ebh("[EBH THREAD] erase thread started\n");
1091 struct chfs_ebh *ebh = data;
1092 int err;
1094 mutex_enter(&ebh->erase_lock);
1095 while (ebh->bg_erase.eth_running) {
1096 if (TAILQ_EMPTY(&ebh->to_erase) &&
1097 TAILQ_EMPTY(&ebh->fully_erased)) {
1098 cv_timedwait_sig(&ebh->bg_erase.eth_wakeup,
1099 &ebh->erase_lock, mstohz(100));
1100 } else {
1101 /* XXX exiting this mutex is a bit odd here as
1102 * free_peb instantly reenters it...
1104 err = free_peb(ebh);
1105 mutex_exit(&ebh->erase_lock);
1106 if (err) {
1107 chfs_err("freeing PEB failed in the"
1108 " background thread: %d\n", err);
1110 mutex_enter(&ebh->erase_lock);
1113 mutex_exit(&ebh->erase_lock);
1115 dbg_ebh("[EBH THREAD] erase thread stopped\n");
1116 kthread_exit(0);
1120 * erase_thread_start - init and start erase thread
1121 * @ebh: eraseblock handler
1123 static void
1124 erase_thread_start(struct chfs_ebh *ebh)
1126 cv_init(&ebh->bg_erase.eth_wakeup, "ebheracv");
1128 ebh->bg_erase.eth_running = true;
1129 kthread_create(PRI_NONE, KTHREAD_MPSAFE | KTHREAD_MUSTJOIN, NULL,
1130 erase_thread, ebh, &ebh->bg_erase.eth_thread, "ebherase");
1134 * erase_thread_stop - stop background erase thread
1135 * @ebh: eraseblock handler
1137 static void
1138 erase_thread_stop(struct chfs_ebh *ebh)
1140 ebh->bg_erase.eth_running = false;
1141 cv_signal(&ebh->bg_erase.eth_wakeup);
1142 dbg_ebh("[EBH THREAD STOP] signaled\n");
1144 kthread_join(ebh->bg_erase.eth_thread);
1145 #ifdef BROKEN_KTH_JOIN
1146 kpause("chfsebhjointh", false, mstohz(1000), NULL);
1147 #endif
1149 cv_destroy(&ebh->bg_erase.eth_wakeup);
1152 /*****************************************************************************/
1153 /* End of Erase related operations */
1154 /*****************************************************************************/
1156 /*****************************************************************************/
1157 /* Scan related operations */
1158 /*****************************************************************************/
1160 scan_leb_used_cmp(struct chfs_scan_leb *sleb1, struct chfs_scan_leb *sleb2)
1162 return (sleb1->lnr - sleb2->lnr);
1165 RB_PROTOTYPE(scan_leb_used_rbtree, chfs_scan_leb, u.rb, scan_leb_used_cmp);
1166 RB_GENERATE(scan_leb_used_rbtree, chfs_scan_leb, u.rb, scan_leb_used_cmp);
1169 * scan_add_to_queue - adds a physical eraseblock to one of the
1170 * eraseblock queue
1171 * @si: chfs scanning information
1172 * @pebnr: physical eraseblock number
1173 * @erase_cnt: erase counter of the physical eraseblock
1174 * @list: the list to add to
1176 * This function adds a physical eraseblock to one of the lists in the scanning
1177 * information.
1178 * Returns zero in case of success, negative error code in case of fail.
1180 static int
1181 scan_add_to_queue(struct chfs_scan_info *si, int pebnr, int erase_cnt,
1182 struct scan_leb_queue *queue)
1184 struct chfs_scan_leb *sleb;
1186 sleb = kmem_alloc(sizeof(struct chfs_scan_leb), KM_SLEEP);
1188 sleb->pebnr = pebnr;
1189 sleb->erase_cnt = erase_cnt;
1190 TAILQ_INSERT_TAIL(queue, sleb, u.queue);
1191 return 0;
1195 * nor_scan_add_to_used - add a physical eraseblock to the
1196 * used tree of scan info
1197 * @ebh: chfs eraseblock handler
1198 * @si: chfs scanning information
1199 * @ebhdr: eraseblock header
1200 * @pebnr: physical eraseblock number
1201 * @leb_status: the status of the PEB's eraseblock header
1203 * This function adds a PEB to the used tree of the scanning information.
1204 * It handles the situations if there are more physical eraseblock referencing
1205 * to the same logical eraseblock.
1206 * Returns zero in case of success, error code in case of fail.
1209 nor_scan_add_to_used(struct chfs_ebh *ebh, struct chfs_scan_info *si,
1210 struct chfs_eb_hdr *ebhdr, int pebnr, int leb_status)
1212 int err, lnr, ec;
1213 struct chfs_scan_leb *sleb, *old;
1215 lnr = CHFS_GET_LID(ebhdr->u.nor_hdr.lid);
1216 ec = le32toh(ebhdr->ec_hdr.erase_cnt);
1218 sleb = kmem_alloc(sizeof(struct chfs_scan_leb), KM_SLEEP);
1220 sleb->erase_cnt = ec;
1221 sleb->lnr = lnr;
1222 sleb->pebnr = pebnr;
1223 sleb->info = leb_status;
1225 old = RB_INSERT(scan_leb_used_rbtree, &si->used, sleb);
1226 if (old) {
1227 kmem_free(sleb, sizeof(struct chfs_scan_leb));
1228 /* There is already an eraseblock in the used tree */
1229 /* If the new one is bad */
1230 if (EBHDR_LEB_DIRTY == leb_status &&
1231 EBHDR_LEB_OK == old->info) {
1232 return scan_add_to_queue(si, pebnr, ec, &si->erase);
1233 } else {
1234 err = scan_add_to_queue(si, old->pebnr,
1235 old->erase_cnt, &si->erase);
1236 if (err) {
1237 return err;
1240 old->erase_cnt = ec;
1241 old->lnr = lnr;
1242 old->pebnr = pebnr;
1243 old->info = leb_status;
1244 return 0;
1247 return 0;
1251 * nor_process eb -read the headers from NOR flash, check them and add to
1252 * the scanning information
1253 * @ebh: chfs eraseblock handler
1254 * @si: chfs scanning information
1255 * @pebnr: physical eraseblock number
1257 * Returns zero in case of success, error code in case of fail.
1260 nor_process_eb(struct chfs_ebh *ebh, struct chfs_scan_info *si,
1261 int pebnr, struct chfs_eb_hdr *ebhdr)
1263 int err, erase_cnt, leb_status;
1265 err = ebh->ops->read_eb_hdr(ebh, pebnr, ebhdr);
1266 if (err)
1267 return err;
1269 erase_cnt = le32toh(ebhdr->ec_hdr.erase_cnt);
1270 dbg_ebh("erase_cnt: %d\n", erase_cnt);
1271 leb_status = ebh->ops->check_eb_hdr(ebh, ebhdr);
1272 if (EBHDR_LEB_BADMAGIC == leb_status ||
1273 EBHDR_LEB_BADCRC == leb_status) {
1274 err = scan_add_to_queue(si, pebnr, erase_cnt, &si->corrupted);
1275 return err;
1277 else if (EBHDR_LEB_FREE == leb_status) {
1278 err = scan_add_to_queue(si, pebnr, erase_cnt, &si->free);
1279 goto count_mean;
1281 else if (EBHDR_LEB_NO_HDR == leb_status) {
1282 err = scan_add_to_queue(si, pebnr, erase_cnt, &si->erased);
1283 return err;
1285 else if (EBHDR_LEB_INVALIDATED == leb_status) {
1286 err = scan_add_to_queue(si, pebnr, erase_cnt, &si->erase);
1287 return err;
1290 err = nor_scan_add_to_used(ebh, si, ebhdr, pebnr, leb_status);
1291 if (err)
1292 return err;
1295 count_mean:
1296 si->sum_of_ec += erase_cnt;
1297 si->num_of_eb++;
1299 return err;
1303 * nand_scan_add_to_used - add a physical eraseblock to the
1304 * used tree of scan info
1305 * @ebh: chfs eraseblock handler
1306 * @si: chfs scanning information
1307 * @ebhdr: eraseblock header
1308 * @pebnr: physical eraseblock number
1309 * @leb_status: the status of the PEB's eraseblock header
1311 * This function adds a PEB to the used tree of the scanning information.
1312 * It handles the situations if there are more physical eraseblock referencing
1313 * to the same logical eraseblock.
1314 * Returns zero in case of success, error code in case of fail.
1317 nand_scan_add_to_used(struct chfs_ebh *ebh, struct chfs_scan_info *si,
1318 struct chfs_eb_hdr *ebhdr, int pebnr)
1320 int err, lnr, ec;
1321 struct chfs_scan_leb *sleb, *old;
1322 uint64_t serial = le64toh(ebhdr->u.nand_hdr.serial);
1324 lnr = CHFS_GET_LID(ebhdr->u.nor_hdr.lid);
1325 ec = le32toh(ebhdr->ec_hdr.erase_cnt);
1327 sleb = kmem_alloc(sizeof(struct chfs_scan_leb), KM_SLEEP);
1329 sleb->erase_cnt = ec;
1330 sleb->lnr = lnr;
1331 sleb->pebnr = pebnr;
1332 sleb->info = serial;
1334 old = RB_INSERT(scan_leb_used_rbtree, &si->used, sleb);
1335 if (old) {
1336 kmem_free(sleb, sizeof(struct chfs_scan_leb));
1337 /* There is already an eraseblock in the used tree */
1338 /* If the new one is bad */
1339 if (serial < old->info)
1340 return scan_add_to_queue(si, pebnr, ec, &si->erase);
1341 else {
1342 err = scan_add_to_queue(si,
1343 old->pebnr, old->erase_cnt, &si->erase);
1344 if (err)
1345 return err;
1347 old->erase_cnt = ec;
1348 old->lnr = lnr;
1349 old->pebnr = pebnr;
1350 old->info = serial;
1351 return 0;
1354 return 0;
1358 * nand_process eb -read the headers from NAND flash, check them and add to the
1359 * scanning information
1360 * @ebh: chfs eraseblock handler
1361 * @si: chfs scanning information
1362 * @pebnr: physical eraseblock number
1364 * Returns zero in case of success, error code in case of fail.
1367 nand_process_eb(struct chfs_ebh *ebh, struct chfs_scan_info *si,
1368 int pebnr, struct chfs_eb_hdr *ebhdr)
1370 int err, erase_cnt, leb_status;
1371 uint64_t max_serial;
1372 /* isbad() is defined on some ancient platforms, heh */
1373 bool is_bad;
1375 /* Check block is bad */
1376 err = flash_block_isbad(ebh->flash_dev,
1377 pebnr * ebh->flash_if->erasesize, &is_bad);
1378 if (err) {
1379 chfs_err("checking block is bad failed\n");
1380 return err;
1382 if (is_bad) {
1383 si->bad_peb_cnt++;
1384 return 0;
1387 err = ebh->ops->read_eb_hdr(ebh, pebnr, ebhdr);
1388 if (err)
1389 return err;
1391 erase_cnt = le32toh(ebhdr->ec_hdr.erase_cnt);
1392 leb_status = ebh->ops->check_eb_hdr(ebh, ebhdr);
1393 if (EBHDR_LEB_BADMAGIC == leb_status ||
1394 EBHDR_LEB_BADCRC == leb_status) {
1395 err = scan_add_to_queue(si, pebnr, erase_cnt, &si->corrupted);
1396 return err;
1398 else if (EBHDR_LEB_FREE == leb_status) {
1399 err = scan_add_to_queue(si, pebnr, erase_cnt, &si->free);
1400 goto count_mean;
1402 else if (EBHDR_LEB_NO_HDR == leb_status) {
1403 err = scan_add_to_queue(si, pebnr, erase_cnt, &si->erased);
1404 return err;
1407 err = nand_scan_add_to_used(ebh, si, ebhdr, pebnr);
1408 if (err)
1409 return err;
1411 max_serial = le64toh(ebhdr->u.nand_hdr.serial);
1412 if (max_serial > *ebh->max_serial) {
1413 *ebh->max_serial = max_serial;
1416 count_mean:
1417 si->sum_of_ec += erase_cnt;
1418 si->num_of_eb++;
1420 return err;
1424 * chfs_scan - scans the media and returns informations about it
1425 * @ebh: chfs eraseblock handler
1427 * This function scans through the media and returns information about it or if
1428 * it fails NULL will be returned.
1430 struct chfs_scan_info *
1431 chfs_scan(struct chfs_ebh *ebh)
1433 struct chfs_scan_info *si;
1434 struct chfs_eb_hdr *ebhdr;
1435 int pebnr, err;
1437 si = kmem_alloc(sizeof(*si), KM_SLEEP);
1439 TAILQ_INIT(&si->corrupted);
1440 TAILQ_INIT(&si->free);
1441 TAILQ_INIT(&si->erase);
1442 TAILQ_INIT(&si->erased);
1443 RB_INIT(&si->used);
1444 si->bad_peb_cnt = 0;
1445 si->num_of_eb = 0;
1446 si->sum_of_ec = 0;
1448 ebhdr = kmem_alloc(sizeof(*ebhdr), KM_SLEEP);
1450 for (pebnr = 0; pebnr < ebh->peb_nr; pebnr++) {
1451 dbg_ebh("processing PEB %d\n", pebnr);
1452 err = ebh->ops->process_eb(ebh, si, pebnr, ebhdr);
1453 if (err < 0)
1454 goto out_ebhdr;
1456 kmem_free(ebhdr, sizeof(*ebhdr));
1457 dbg_ebh("[CHFS_SCAN] scanning information collected\n");
1458 return si;
1460 out_ebhdr:
1461 kmem_free(ebhdr, sizeof(*ebhdr));
1462 kmem_free(si, sizeof(*si));
1463 return NULL;
1467 * scan_info_destroy - frees all lists and trees in the scanning information
1468 * @si: the scanning information
1470 void
1471 scan_info_destroy(struct chfs_scan_info *si)
1473 EBH_QUEUE_DESTROY(&si->corrupted,
1474 struct chfs_scan_leb, u.queue);
1476 EBH_QUEUE_DESTROY(&si->erase,
1477 struct chfs_scan_leb, u.queue);
1479 EBH_QUEUE_DESTROY(&si->erased,
1480 struct chfs_scan_leb, u.queue);
1482 EBH_QUEUE_DESTROY(&si->free,
1483 struct chfs_scan_leb, u.queue);
1485 EBH_TREE_DESTROY(scan_leb_used_rbtree,
1486 &si->used, struct chfs_scan_leb);
1488 kmem_free(si, sizeof(*si));
1489 dbg_ebh("[SCAN_INFO_DESTROY] scanning information destroyed\n");
1493 * scan_media - scan media
1495 * @ebh - chfs eraseblock handler
1497 * Returns zero in case of success, error code in case of fail.
1501 scan_media(struct chfs_ebh *ebh)
1503 int err, i, avg_ec;
1504 struct chfs_scan_info *si;
1505 struct chfs_scan_leb *sleb;
1507 si = chfs_scan(ebh);
1509 * Process the scan info, manage the eraseblock lists
1511 mutex_init(&ebh->ltree_lock, MUTEX_DEFAULT, IPL_NONE);
1512 mutex_init(&ebh->erase_lock, MUTEX_DEFAULT, IPL_NONE);
1513 RB_INIT(&ebh->ltree);
1514 RB_INIT(&ebh->free);
1515 RB_INIT(&ebh->in_use);
1516 TAILQ_INIT(&ebh->to_erase);
1517 TAILQ_INIT(&ebh->fully_erased);
1518 mutex_init(&ebh->alc_mutex, MUTEX_DEFAULT, IPL_NONE);
1520 ebh->peb_nr -= si->bad_peb_cnt;
1523 * Create background thread for erasing
1525 erase_thread_start(ebh);
1527 ebh->lmap = kmem_alloc(ebh->peb_nr * sizeof(int), KM_SLEEP);
1529 for (i = 0; i < ebh->peb_nr; i++) {
1530 ebh->lmap[i] = EBH_LEB_UNMAPPED;
1533 if (si->num_of_eb == 0) {
1534 /* The flash contains no data. */
1535 avg_ec = 0;
1537 else {
1538 avg_ec = (int) (si->sum_of_ec / si->num_of_eb);
1540 dbg_ebh("num_of_eb: %d\n", si->num_of_eb);
1542 mutex_enter(&ebh->erase_lock);
1544 RB_FOREACH(sleb, scan_leb_used_rbtree, &si->used) {
1545 ebh->lmap[sleb->lnr] = sleb->pebnr;
1546 err = add_peb_to_in_use(ebh, sleb->pebnr, sleb->erase_cnt);
1547 if (err)
1548 goto out_free;
1551 TAILQ_FOREACH(sleb, &si->erased, u.queue) {
1552 err = add_peb_to_erase_queue(ebh, sleb->pebnr, avg_ec,
1553 &ebh->fully_erased);
1554 if (err)
1555 goto out_free;
1558 TAILQ_FOREACH(sleb, &si->erase, u.queue) {
1559 err = add_peb_to_erase_queue(ebh, sleb->pebnr, avg_ec,
1560 &ebh->to_erase);
1561 if (err)
1562 goto out_free;
1565 TAILQ_FOREACH(sleb, &si->free, u.queue) {
1566 err = add_peb_to_free(ebh, sleb->pebnr, sleb->erase_cnt);
1567 if (err)
1568 goto out_free;
1571 TAILQ_FOREACH(sleb, &si->corrupted, u.queue) {
1572 err = add_peb_to_erase_queue(ebh, sleb->pebnr, avg_ec,
1573 &ebh->to_erase);
1574 if (err)
1575 goto out_free;
1577 mutex_exit(&ebh->erase_lock);
1578 scan_info_destroy(si);
1579 return 0;
1581 out_free:
1582 mutex_exit(&ebh->erase_lock);
1583 kmem_free(ebh->lmap, ebh->peb_nr * sizeof(int));
1584 scan_info_destroy(si);
1585 dbg_ebh("[SCAN_MEDIA] returning with error: %d\n", err);
1586 return err;
1589 /*****************************************************************************/
1590 /* End of Scan related operations */
1591 /*****************************************************************************/
1594 * ebh_open - opens mtd device and init ereaseblock header
1595 * @ebh: eraseblock handler
1596 * @flash_nr: flash device number to use
1598 * Returns zero in case of success, error code in case of fail.
1601 ebh_open(struct chfs_ebh *ebh, dev_t dev)
1603 int err;
1605 ebh->flash_dev = flash_get_device(dev);
1606 if (!ebh->flash_dev) {
1607 aprint_error("ebh_open: cant get flash device\n");
1608 return ENODEV;
1611 ebh->flash_if = flash_get_interface(dev);
1612 if (!ebh->flash_if) {
1613 aprint_error("ebh_open: cant get flash interface\n");
1614 return ENODEV;
1617 ebh->flash_size = flash_get_size(dev);
1618 ebh->peb_nr = ebh->flash_size / ebh->flash_if->erasesize;
1619 // ebh->peb_nr = ebh->flash_if->size / ebh->flash_if->erasesize;
1620 /* Set up flash operations based on flash type */
1621 ebh->ops = kmem_alloc(sizeof(struct chfs_ebh_ops), KM_SLEEP);
1623 switch (ebh->flash_if->type) {
1624 case FLASH_TYPE_NOR:
1625 ebh->eb_size = ebh->flash_if->erasesize -
1626 CHFS_EB_EC_HDR_SIZE - CHFS_EB_HDR_NOR_SIZE;
1628 ebh->ops->read_eb_hdr = nor_read_eb_hdr;
1629 ebh->ops->write_eb_hdr = nor_write_eb_hdr;
1630 ebh->ops->check_eb_hdr = nor_check_eb_hdr;
1631 ebh->ops->mark_eb_hdr_dirty_flash =
1632 nor_mark_eb_hdr_dirty_flash;
1633 ebh->ops->invalidate_eb_hdr = nor_invalidate_eb_hdr;
1634 ebh->ops->mark_eb_hdr_free = mark_eb_hdr_free;
1636 ebh->ops->process_eb = nor_process_eb;
1638 ebh->ops->create_eb_hdr = nor_create_eb_hdr;
1639 ebh->ops->calc_data_offs = nor_calc_data_offs;
1641 ebh->max_serial = NULL;
1642 break;
1643 case FLASH_TYPE_NAND:
1644 ebh->eb_size = ebh->flash_if->erasesize -
1645 2 * ebh->flash_if->page_size;
1647 ebh->ops->read_eb_hdr = nand_read_eb_hdr;
1648 ebh->ops->write_eb_hdr = nand_write_eb_hdr;
1649 ebh->ops->check_eb_hdr = nand_check_eb_hdr;
1650 ebh->ops->mark_eb_hdr_free = mark_eb_hdr_free;
1651 ebh->ops->mark_eb_hdr_dirty_flash = NULL;
1652 ebh->ops->invalidate_eb_hdr = NULL;
1654 ebh->ops->process_eb = nand_process_eb;
1656 ebh->ops->create_eb_hdr = nand_create_eb_hdr;
1657 ebh->ops->calc_data_offs = nand_calc_data_offs;
1659 ebh->max_serial = kmem_alloc(sizeof(uint64_t), KM_SLEEP);
1661 *ebh->max_serial = 0;
1662 break;
1663 default:
1664 return 1;
1666 printf("opening ebh: eb_size: %zu\n", ebh->eb_size);
1667 err = scan_media(ebh);
1668 if (err) {
1669 dbg_ebh("Scan failed.");
1670 kmem_free(ebh->ops, sizeof(struct chfs_ebh_ops));
1671 kmem_free(ebh, sizeof(struct chfs_ebh));
1672 return err;
1674 return 0;
1678 * ebh_close - close ebh
1679 * @ebh: eraseblock handler
1680 * Returns zero in case of success, error code in case of fail.
1683 ebh_close(struct chfs_ebh *ebh)
1685 erase_thread_stop(ebh);
1687 EBH_TREE_DESTROY(peb_free_rbtree, &ebh->free, struct chfs_peb);
1688 EBH_TREE_DESTROY(peb_in_use_rbtree, &ebh->in_use, struct chfs_peb);
1690 EBH_QUEUE_DESTROY(&ebh->fully_erased, struct chfs_peb, u.queue);
1691 EBH_QUEUE_DESTROY(&ebh->to_erase, struct chfs_peb, u.queue);
1693 /* XXX HACK, see ebh.h */
1694 EBH_TREE_DESTROY_MUTEX(ltree_rbtree, &ebh->ltree,
1695 struct chfs_ltree_entry);
1697 KASSERT(!mutex_owned(&ebh->ltree_lock));
1698 KASSERT(!mutex_owned(&ebh->alc_mutex));
1699 KASSERT(!mutex_owned(&ebh->erase_lock));
1701 mutex_destroy(&ebh->ltree_lock);
1702 mutex_destroy(&ebh->alc_mutex);
1703 mutex_destroy(&ebh->erase_lock);
1705 kmem_free(ebh->ops, sizeof(struct chfs_ebh_ops));
1706 kmem_free(ebh, sizeof(struct chfs_ebh));
1708 return 0;
1712 * ebh_read_leb - read data from leb
1713 * @ebh: eraseblock handler
1714 * @lnr: logical eraseblock number
1715 * @buf: buffer to read to
1716 * @offset: offset from where to read
1717 * @len: bytes number to read
1719 * Returns zero in case of success, error code in case of fail.
1722 ebh_read_leb(struct chfs_ebh *ebh, int lnr, char *buf, uint32_t offset,
1723 size_t len, size_t *retlen)
1725 int err, pebnr;
1726 off_t data_offset;
1728 KASSERT(offset + len <= ebh->eb_size);
1730 err = leb_read_lock(ebh, lnr);
1731 if (err)
1732 return err;
1734 pebnr = ebh->lmap[lnr];
1735 /* If PEB is not mapped the buffer is filled with 0xFF */
1736 if (EBH_LEB_UNMAPPED == pebnr) {
1737 leb_read_unlock(ebh, lnr);
1738 memset(buf, 0xFF, len);
1739 return 0;
1742 /* Read data */
1743 data_offset = ebh->ops->calc_data_offs(ebh, pebnr, offset);
1744 err = flash_read(ebh->flash_dev, data_offset, len, retlen,
1745 (unsigned char *) buf);
1746 if (err)
1747 goto out_free;
1749 KASSERT(len == *retlen);
1751 out_free:
1752 leb_read_unlock(ebh, lnr);
1753 return err;
1757 * get_peb: get a free physical eraseblock
1758 * @ebh - chfs eraseblock handler
1760 * This function gets a free eraseblock from the ebh->free RB-tree.
1761 * The fist entry will be returned and deleted from the tree.
1762 * The entries sorted by the erase counters, so the PEB with the smallest
1763 * erase counter will be added back.
1764 * If something goes bad a negative value will be returned.
1767 get_peb(struct chfs_ebh *ebh)
1769 int err, pebnr;
1770 struct chfs_peb *peb;
1772 retry:
1773 mutex_enter(&ebh->erase_lock);
1774 //dbg_ebh("LOCK: ebh->erase_lock spin locked in get_peb()\n");
1775 if (RB_EMPTY(&ebh->free)) {
1776 /*There is no more free PEBs in the tree*/
1777 if (TAILQ_EMPTY(&ebh->to_erase) &&
1778 TAILQ_EMPTY(&ebh->fully_erased)) {
1779 mutex_exit(&ebh->erase_lock);
1780 //dbg_ebh("UNLOCK: ebh->erase_lock spin unlocked in get_peb()\n");
1781 return ENOSPC;
1783 err = free_peb(ebh);
1785 mutex_exit(&ebh->erase_lock);
1786 //dbg_ebh("UNLOCK: ebh->erase_lock spin unlocked in get_peb()\n");
1788 if (err)
1789 return err;
1790 goto retry;
1792 peb = RB_MIN(peb_free_rbtree, &ebh->free);
1793 pebnr = peb->pebnr;
1794 RB_REMOVE(peb_free_rbtree, &ebh->free, peb);
1795 err = add_peb_to_in_use(ebh, peb->pebnr, peb->erase_cnt);
1796 if (err)
1797 pebnr = err;
1799 kmem_free(peb, sizeof(struct chfs_peb));
1801 mutex_exit(&ebh->erase_lock);
1802 //dbg_ebh("UNLOCK: ebh->erase_lock spin unlocked in get_peb()\n");
1804 return pebnr;
1808 * ebh_write_leb - write data to leb
1809 * @ebh: eraseblock handler
1810 * @lnr: logical eraseblock number
1811 * @buf: data to write
1812 * @offset: offset where to write
1813 * @len: bytes number to write
1815 * Returns zero in case of success, error code in case of fail.
1818 ebh_write_leb(struct chfs_ebh *ebh, int lnr, char *buf, uint32_t offset,
1819 size_t len, size_t *retlen)
1821 int err, pebnr, retries = 0;
1822 off_t data_offset;
1823 struct chfs_eb_hdr *ebhdr;
1825 dbg("offset: %d | len: %zu | (offset+len): %zu "
1826 " | ebsize: %zu\n", offset, len, (offset+len), ebh->eb_size);
1828 KASSERT(offset + len <= ebh->eb_size);
1830 err = leb_write_lock(ebh, lnr);
1831 if (err)
1832 return err;
1834 pebnr = ebh->lmap[lnr];
1835 /* If the LEB is mapped write out data */
1836 if (pebnr != EBH_LEB_UNMAPPED) {
1837 data_offset = ebh->ops->calc_data_offs(ebh, pebnr, offset);
1838 err = flash_write(ebh->flash_dev, data_offset, len, retlen,
1839 (unsigned char *) buf);
1841 if (err) {
1842 chfs_err("error %d while writing %zu bytes to PEB "
1843 "%d:%ju, written %zu bytes\n",
1844 err, len, pebnr, (uintmax_t )offset, *retlen);
1845 } else {
1846 KASSERT(len == *retlen);
1849 leb_write_unlock(ebh, lnr);
1850 return err;
1854 * If the LEB is unmapped, get a free PEB and write the
1855 * eraseblock header first
1857 ebhdr = kmem_alloc(sizeof(struct chfs_eb_hdr), KM_SLEEP);
1859 /* Setting up eraseblock header properties */
1860 ebh->ops->create_eb_hdr(ebhdr, lnr);
1862 retry:
1863 /* Getting a physical eraseblock from the wear leveling system */
1864 pebnr = get_peb(ebh);
1865 if (pebnr < 0) {
1866 leb_write_unlock(ebh, lnr);
1867 kmem_free(ebhdr, sizeof(struct chfs_eb_hdr));
1868 return pebnr;
1871 /* Write the eraseblock header to the media */
1872 err = ebh->ops->write_eb_hdr(ebh, pebnr, ebhdr);
1873 if (err) {
1874 chfs_warn(
1875 "error writing eraseblock header: LEB %d , PEB %d\n",
1876 lnr, pebnr);
1877 goto write_error;
1880 /* Write out data */
1881 if (len) {
1882 data_offset = ebh->ops->calc_data_offs(ebh, pebnr, offset);
1883 err = flash_write(ebh->flash_dev,
1884 data_offset, len, retlen, (unsigned char *) buf);
1885 if (err) {
1886 chfs_err("error %d while writing %zu bytes to PEB "
1887 " %d:%ju, written %zu bytes\n",
1888 err, len, pebnr, (uintmax_t )offset, *retlen);
1889 goto write_error;
1893 ebh->lmap[lnr] = pebnr;
1894 leb_write_unlock(ebh, lnr);
1895 kmem_free(ebhdr, sizeof(struct chfs_eb_hdr));
1897 return 0;
1899 write_error: err = release_peb(ebh, pebnr);
1900 // max retries (NOW: 2)
1901 if (err || CHFS_MAX_GET_PEB_RETRIES < ++retries) {
1902 leb_write_unlock(ebh, lnr);
1903 kmem_free(ebhdr, sizeof(struct chfs_eb_hdr));
1904 return err;
1906 goto retry;
1910 * ebh_erase_leb - erase a leb
1911 * @ebh: eraseblock handler
1912 * @lnr: leb number
1914 * Returns zero in case of success, error code in case of fail.
1917 ebh_erase_leb(struct chfs_ebh *ebh, int lnr)
1919 int err, pebnr;
1921 leb_write_lock(ebh, lnr);
1923 pebnr = ebh->lmap[lnr];
1924 if (pebnr < 0) {
1925 leb_write_unlock(ebh, lnr);
1926 return EBH_LEB_UNMAPPED;
1928 err = release_peb(ebh, pebnr);
1929 if (err)
1930 goto out_unlock;
1932 ebh->lmap[lnr] = EBH_LEB_UNMAPPED;
1933 cv_signal(&ebh->bg_erase.eth_wakeup);
1934 out_unlock:
1935 leb_write_unlock(ebh, lnr);
1936 return err;
1940 * ebh_map_leb - maps a PEB to LEB
1941 * @ebh: eraseblock handler
1942 * @lnr: leb number
1944 * Returns zero on success, error code in case of fail
1947 ebh_map_leb(struct chfs_ebh *ebh, int lnr)
1949 int err, pebnr, retries = 0;
1950 struct chfs_eb_hdr *ebhdr;
1952 ebhdr = kmem_alloc(sizeof(struct chfs_eb_hdr), KM_SLEEP);
1954 err = leb_write_lock(ebh, lnr);
1955 if (err)
1956 return err;
1958 retry:
1959 pebnr = get_peb(ebh);
1960 if (pebnr < 0) {
1961 err = pebnr;
1962 goto out_unlock;
1965 ebh->ops->create_eb_hdr(ebhdr, lnr);
1967 err = ebh->ops->write_eb_hdr(ebh, pebnr, ebhdr);
1968 if (err) {
1969 chfs_warn(
1970 "error writing eraseblock header: LEB %d , PEB %d\n",
1971 lnr, pebnr);
1972 goto write_error;
1975 ebh->lmap[lnr] = pebnr;
1977 out_unlock:
1978 leb_write_unlock(ebh, lnr);
1979 return err;
1981 write_error:
1982 err = release_peb(ebh, pebnr);
1983 // max retries (NOW: 2)
1984 if (err || CHFS_MAX_GET_PEB_RETRIES < ++retries) {
1985 leb_write_unlock(ebh, lnr);
1986 kmem_free(ebhdr, sizeof(struct chfs_eb_hdr));
1987 return err;
1989 goto retry;
1993 * ebh_unmap_leb -
1994 * @ebh: eraseblock handler
1995 * @lnr: leb number
1997 * Retruns zero on success, error code in case of fail.
2000 ebh_unmap_leb(struct chfs_ebh *ebh, int lnr)
2002 int err;
2004 if (ebh_is_mapped(ebh, lnr) < 0)
2005 /* If the eraseblock already unmapped */
2006 return 0;
2008 err = ebh_erase_leb(ebh, lnr);
2010 return err;
2014 * ebh_is_mapped - check if a PEB is mapped to @lnr
2015 * @ebh: eraseblock handler
2016 * @lnr: leb number
2018 * Retruns 0 if the logical eraseblock is mapped, negative error code otherwise.
2021 ebh_is_mapped(struct chfs_ebh *ebh, int lnr)
2023 int err, result;
2024 err = leb_read_lock(ebh, lnr);
2025 if (err)
2026 return err;
2028 result = ebh->lmap[lnr];
2029 leb_read_unlock(ebh, lnr);
2031 return result;
2035 * ebh_change_leb - write the LEB to another PEB
2036 * @ebh: eraseblock handler
2037 * @lnr: leb number
2038 * @buf: data to write
2039 * @len: length of data
2040 * Returns zero in case of success, error code in case of fail.
2043 ebh_change_leb(struct chfs_ebh *ebh, int lnr, char *buf, size_t len,
2044 size_t *retlen)
2046 int err, pebnr, pebnr_old, retries = 0;
2047 off_t data_offset;
2049 struct chfs_peb *peb = NULL;
2050 struct chfs_eb_hdr *ebhdr;
2052 if (ebh_is_mapped(ebh, lnr) < 0)
2053 return EBH_LEB_UNMAPPED;
2055 if (len == 0) {
2056 err = ebh_unmap_leb(ebh, lnr);
2057 if (err)
2058 return err;
2059 return ebh_map_leb(ebh, lnr);
2062 ebhdr = kmem_alloc(sizeof(struct chfs_eb_hdr), KM_SLEEP);
2064 pebnr_old = ebh->lmap[lnr];
2066 mutex_enter(&ebh->alc_mutex);
2067 err = leb_write_lock(ebh, lnr);
2068 if (err)
2069 goto out_mutex;
2071 if (ebh->ops->mark_eb_hdr_dirty_flash) {
2072 err = ebh->ops->mark_eb_hdr_dirty_flash(ebh, pebnr_old, lnr);
2073 if (err)
2074 goto out_unlock;
2077 /* Setting up eraseblock header properties */
2078 ebh->ops->create_eb_hdr(ebhdr, lnr);
2080 retry:
2081 /* Getting a physical eraseblock from the wear leveling system */
2082 pebnr = get_peb(ebh);
2083 if (pebnr < 0) {
2084 leb_write_unlock(ebh, lnr);
2085 mutex_exit(&ebh->alc_mutex);
2086 kmem_free(ebhdr, sizeof(struct chfs_eb_hdr));
2087 return pebnr;
2090 err = ebh->ops->write_eb_hdr(ebh, pebnr, ebhdr);
2091 if (err) {
2092 chfs_warn(
2093 "error writing eraseblock header: LEB %d , PEB %d",
2094 lnr, pebnr);
2095 goto write_error;
2098 /* Write out data */
2099 data_offset = ebh->ops->calc_data_offs(ebh, pebnr, 0);
2100 err = flash_write(ebh->flash_dev, data_offset, len, retlen,
2101 (unsigned char *) buf);
2102 if (err) {
2103 chfs_err("error %d while writing %zu bytes to PEB %d:%ju,"
2104 " written %zu bytes",
2105 err, len, pebnr, (uintmax_t)data_offset, *retlen);
2106 goto write_error;
2109 ebh->lmap[lnr] = pebnr;
2111 if (ebh->ops->invalidate_eb_hdr) {
2112 err = ebh->ops->invalidate_eb_hdr(ebh, pebnr_old);
2113 if (err)
2114 goto out_unlock;
2116 peb = find_peb_in_use(ebh, pebnr_old);
2117 err = release_peb(ebh, peb->pebnr);
2119 out_unlock:
2120 leb_write_unlock(ebh, lnr);
2122 out_mutex:
2123 mutex_exit(&ebh->alc_mutex);
2124 kmem_free(ebhdr, sizeof(struct chfs_eb_hdr));
2125 kmem_free(peb, sizeof(struct chfs_peb));
2126 return err;
2128 write_error:
2129 err = release_peb(ebh, pebnr);
2130 //max retries (NOW: 2)
2131 if (err || CHFS_MAX_GET_PEB_RETRIES < ++retries) {
2132 leb_write_unlock(ebh, lnr);
2133 mutex_exit(&ebh->alc_mutex);
2134 kmem_free(ebhdr, sizeof(struct chfs_eb_hdr));
2135 return err;
2137 goto retry;