/** * ubifs_read_node - read node. * @c: UBIFS file-system description object * @buf: buffer to read to * @type: node type * @len: node length (not aligned) * @lnum: logical eraseblock number * @offs: offset within the logical eraseblock * * This function reads a node of known type and and length, checks it and * stores in @buf. Returns zero in case of success, %-EUCLEAN if CRC mismatched * and a negative error code in case of failure. */ int ubifs_read_node(const struct ubifs_info *c, void *buf, int type, int len, int lnum, int offs) { int err, l; struct ubifs_ch *ch = buf; int try_count = 0; dbg_io("LEB %d:%d, %s, length %d", lnum, offs, dbg_ntype(type), len); ubifs_assert(lnum >= 0 && lnum < c->leb_cnt && offs >= 0); ubifs_assert(len >= UBIFS_CH_SZ && offs + len <= c->leb_size); ubifs_assert(!(offs & 7) && offs < c->leb_size); ubifs_assert(type >= 0 && type < UBIFS_NODE_TYPES_CNT); try_read: err = ubi_read(c->ubi, lnum, buf, offs, len); if (err && err != -EBADMSG) { ubifs_err("cannot read node %d from LEB %d:%d, error %d", type, lnum, offs, err); return err; } if (type != ch->node_type) { ubifs_err("bad node type (%d but expected %d)", ch->node_type, type); goto out; } err = ubifs_check_node(c, buf, lnum, offs, 0, 0); if (err) { ubifs_err("expected node type %d", type); if(try_count < 3){ try_count++; udelay(100); goto try_read; } else{ return err; } } l = le32_to_cpu(ch->len); if (l != len) { ubifs_err("bad node length %d, expected %d", l, len); goto out; } return 0; out: ubifs_err("bad node at LEB %d:%d, LEB mapping status %d", lnum, offs, ubi_is_mapped(c->ubi, lnum)); dbg_dump_node(c, buf); dbg_dump_stack(); return -EINVAL; }
int ubifs_is_mapped(const struct ubifs_info *c, int lnum) { int err; err = ubi_is_mapped(c->ubi, lnum); if (err < 0) { ubifs_err("ubi_is_mapped failed for LEB %d, error %d", lnum, err); dbg_dump_stack(); } return err; }
/** * ubifs_read_node - read node. * @c: UBIFS file-system description object * @buf: buffer to read to * @type: node type * @len: node length (not aligned) * @lnum: logical eraseblock number * @offs: offset within the logical eraseblock * * This function reads a node of known type and and length, checks it and * stores in @buf. Returns zero in case of success, %-EUCLEAN if CRC mismatched * and a negative error code in case of failure. */ int ubifs_read_node(const struct ubifs_info *c, void *buf, int type, int len, int lnum, int offs) { int err, l; struct ubifs_ch *ch = buf; #if defined(FEATURE_UBIFS_PERF_INDEX) unsigned long long time1 = sched_clock(); #endif dbg_io("LEB %d:%d, %s, length %d", lnum, offs, dbg_ntype(type), len); ubifs_assert(lnum >= 0 && lnum < c->leb_cnt && offs >= 0); ubifs_assert(len >= UBIFS_CH_SZ && offs + len <= c->leb_size); ubifs_assert(!(offs & 7) && offs < c->leb_size); ubifs_assert(type >= 0 && type < UBIFS_NODE_TYPES_CNT); err = ubifs_leb_read(c, lnum, buf, offs, len, 0); if (err && err != -EBADMSG) return err; if (type != ch->node_type) { ubifs_err("bad node type (%d but expected %d)", ch->node_type, type); goto out; } err = ubifs_check_node(c, buf, lnum, offs, 0, 0); if (err) { ubifs_err("expected node type %d", type); return err; } l = le32_to_cpu(ch->len); if (l != len) { ubifs_err("bad node length %d, expected %d", l, len); goto out; } #if defined(FEATURE_UBIFS_PERF_INDEX) if(type == UBIFS_DATA_NODE) { ubifs_perf_lrcount(sched_clock() - time1, len); } #endif return 0; out: ubifs_err("bad node at LEB %d:%d, LEB mapping status %d", lnum, offs, ubi_is_mapped(c->ubi, lnum)); dbg_dump_node(c, buf); dbg_dump_stack(); return -EINVAL; }
static int do_cached_write (struct ubiblk_dev *ubiblk, unsigned long sector, int len, const char *buf) { struct ubi_volume_desc *uv = ubiblk->uv; int ppb = uv->vol->ubi->leb_size / uv->vol->ubi->min_io_size; unsigned short sectors_per_page = uv->vol->ubi->min_io_size >> 9; unsigned short page_shift = ffs(uv->vol->ubi->min_io_size) - 1; unsigned short virt_block, page, page_offset; unsigned long virt_page; virt_page = sector / sectors_per_page; page_offset = sector % sectors_per_page; virt_block = virt_page / ppb; page = virt_page % ppb; if(ubi_is_mapped(uv, virt_block ) == UNMAPPED ){ mutex_lock(&ubiblk->cache_mutex); ubiblk_flush_writecache(ubiblk); mutex_unlock(&ubiblk->cache_mutex); ubiblk_setup_writecache(ubiblk, virt_block); ubi_leb_map(uv, virt_block, UBI_UNKNOWN); } else { if ( STATE_USED == ubiblk->write_cache_state ) { if ( ubiblk->vbw != virt_block) { // Commit before we start a new cache. mutex_lock(&ubiblk->cache_mutex); ubiblk_flush_writecache(ubiblk); mutex_unlock(&ubiblk->cache_mutex); ubiblk_setup_writecache(ubiblk, virt_block); ubi_leb_unmap(uv, virt_block); ubi_leb_map(uv, virt_block, UBI_UNKNOWN); } else { //dprintk("cache hit: 0x%x\n", virt_page); } } else { // printk("with existing mapping\n"); ubiblk_setup_writecache(ubiblk, virt_block); ubi_leb_unmap(uv, virt_block); ubi_leb_map(uv, virt_block, UBI_UNKNOWN); } } memcpy(&ubiblk->write_cache[(page<<page_shift) +(page_offset<<9)], buf,len); return 0; }
/** * ubifs_read_node - read node. * @c: UBIFS file-system description object * @buf: buffer to read to * @type: node type * @len: node length (not aligned) * @lnum: logical eraseblock number * @offs: offset within the logical eraseblock * * This function reads a node of known type and and length, checks it and * stores in @buf. Returns zero in case of success, %-EUCLEAN if CRC mismatched * and a negative error code in case of failure. */ int ubifs_read_node(const struct ubifs_info *c, void *buf, int type, int len, int lnum, int offs) { int err, l; struct ubifs_ch *ch = buf; dbg_io("LEB %d:%d, %s, length %d", lnum, offs, dbg_ntype(type), len); ubifs_assert(c, lnum >= 0 && lnum < c->leb_cnt && offs >= 0); ubifs_assert(c, len >= UBIFS_CH_SZ && offs + len <= c->leb_size); ubifs_assert(c, !(offs & 7) && offs < c->leb_size); ubifs_assert(c, type >= 0 && type < UBIFS_NODE_TYPES_CNT); err = ubifs_leb_read(c, lnum, buf, offs, len, 0); if (err && err != -EBADMSG) return err; if (type != ch->node_type) { ubifs_errc(c, "bad node type (%d but expected %d)", ch->node_type, type); goto out; } err = ubifs_check_node(c, buf, lnum, offs, 0, 0); if (err) { ubifs_errc(c, "expected node type %d", type); return err; } l = le32_to_cpu(ch->len); if (l != len) { ubifs_errc(c, "bad node length %d, expected %d", l, len); goto out; } return 0; out: ubifs_errc(c, "bad node at LEB %d:%d, LEB mapping status %d", lnum, offs, ubi_is_mapped(c->ubi, lnum)); if (!c->probing) { ubifs_dump_node(c, buf); dump_stack(); } return -EINVAL; }
/** * check_volume_empty - check if the UBI volume is empty. * @c: UBIFS file-system description object * * This function checks if the UBIFS volume is empty by looking if its LEBs are * mapped or not. The result of checking is stored in the @c->empty variable. * Returns zero in case of success and a negative error code in case of * failure. */ static int check_volume_empty(struct ubifs_info *c) { int lnum, err; c->empty = 1; for (lnum = 0; lnum < c->leb_cnt; lnum++) { err = ubi_is_mapped(c->ubi, lnum); if (unlikely(err < 0)) return err; if (err == 1) { c->empty = 0; break; } cond_resched(); } return 0; }
static int do_cached_read (struct ubiblk_dev *ubiblk, unsigned long sector, int len, char *buf) { struct ubi_volume_desc *uv = ubiblk->uv; int ppb = uv->vol->ubi->leb_size / uv->vol->ubi->min_io_size; unsigned short sectors_per_page = uv->vol->ubi->min_io_size >> 9; unsigned short page_shift = ffs(uv->vol->ubi->min_io_size) - 1; unsigned short virt_block, page, page_offset; unsigned long virt_page; virt_page = sector / sectors_per_page; page_offset = sector % sectors_per_page; virt_block = virt_page / ppb; page = virt_page % ppb; if(ubiblk->vbw == virt_block){ mutex_lock(&ubiblk->cache_mutex); ubiblk_flush_writecache(ubiblk); mutex_unlock(&ubiblk->cache_mutex); } if ( ubi_is_mapped( uv, virt_block) == UNMAPPED){ // In a Flash Memory device, there might be a logical block that is // not allcated to a physical block due to the block not being used. // All data returned should be set to 0xFF when accessing this logical // block. // dprintk("address translate fail\n"); memset(buf, 0xFF, 512); } else { if( ubiblk->vbr != virt_block ||ubiblk->read_cache_state == STATE_UNUSED ){ ubiblk->vbr = virt_block; ubi_leb_read(uv, virt_block, ubiblk->read_cache, 0, uv->vol->usable_leb_size, 0); ubiblk->read_cache_state = STATE_USED; } memcpy(buf, &ubiblk->read_cache[(page<<page_shift)+(page_offset<<9)], len); } return 0; }