/** * dbg_check_old_index - check the old copy of the index. * @c: UBIFS file-system description object * @zroot: root of the new index * * In order to be able to recover from an unclean unmount, a complete copy of * the index must exist on flash. This is the "old" index. The commit process * must write the "new" index to flash without overwriting or destroying any * part of the old index. This function is run at commit end in order to check * that the old index does indeed exist completely intact. * * This function returns %0 on success and a negative error code on failure. */ int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot) { int lnum, offs, len, err = 0, uninitialized_var(last_level), child_cnt; int first = 1, iip; struct ubifs_debug_info *d = c->dbg; union ubifs_key lower_key, upper_key, l_key, u_key; unsigned long long uninitialized_var(last_sqnum); struct ubifs_idx_node *idx; struct list_head list; struct idx_node *i; size_t sz; if (!(ubifs_chk_flags & UBIFS_CHK_OLD_IDX)) goto out; INIT_LIST_HEAD(&list); sz = sizeof(struct idx_node) + ubifs_idx_node_sz(c, c->fanout) - UBIFS_IDX_NODE_SZ; /* Start at the old zroot */ lnum = d->old_zroot.lnum; offs = d->old_zroot.offs; len = d->old_zroot.len; iip = 0; /* * Traverse the index tree preorder depth-first i.e. do a node and then * its subtrees from left to right. */ while (1) { struct ubifs_branch *br; /* Get the next index node */ i = kmalloc(sz, GFP_NOFS); if (!i) { err = -ENOMEM; goto out_free; } i->iip = iip; /* Keep the index nodes on our path in a linked list */ list_add_tail(&i->list, &list); /* Read the index node */ idx = &i->idx; err = ubifs_read_node(c, idx, UBIFS_IDX_NODE, len, lnum, offs); if (err) goto out_free; /* Validate index node */ child_cnt = le16_to_cpu(idx->child_cnt); if (child_cnt < 1 || child_cnt > c->fanout) { err = 1; goto out_dump; } if (first) { first = 0; /* Check root level and sqnum */ if (le16_to_cpu(idx->level) != d->old_zroot_level) { err = 2; goto out_dump; } if (le64_to_cpu(idx->ch.sqnum) != d->old_zroot_sqnum) { err = 3; goto out_dump; } /* Set last values as though root had a parent */ last_level = le16_to_cpu(idx->level) + 1; last_sqnum = le64_to_cpu(idx->ch.sqnum) + 1; key_read(c, ubifs_idx_key(c, idx), &lower_key); highest_ino_key(c, &upper_key, INUM_WATERMARK); } key_copy(c, &upper_key, &i->upper_key); if (le16_to_cpu(idx->level) != last_level - 1) { err = 3; goto out_dump; } /* * The index is always written bottom up hence a child's sqnum * is always less than the parents. */ if (le64_to_cpu(idx->ch.sqnum) >= last_sqnum) { err = 4; goto out_dump; } /* Check key range */ key_read(c, ubifs_idx_key(c, idx), &l_key); br = ubifs_idx_branch(c, idx, child_cnt - 1); key_read(c, &br->key, &u_key); if (keys_cmp(c, &lower_key, &l_key) > 0) { err = 5; goto out_dump; } if (keys_cmp(c, &upper_key, &u_key) < 0) { err = 6; goto out_dump; } if (keys_cmp(c, &upper_key, &u_key) == 0) if (!is_hash_key(c, &u_key)) { err = 7; goto out_dump; } /* Go to next index node */ if (le16_to_cpu(idx->level) == 0) { /* At the bottom, so go up until can go right */ while (1) { /* Drop the bottom of the list */ list_del(&i->list); kfree(i); /* No more list means we are done */ if (list_empty(&list)) goto out; /* Look at the new bottom */ i = list_entry(list.prev, struct idx_node, list); idx = &i->idx; /* Can we go right */ if (iip + 1 < le16_to_cpu(idx->child_cnt)) { iip = iip + 1; break; } else /* Nope, so go up again */ iip = i->iip; } } else /* Go down left */ iip = 0; /* * We have the parent in 'idx' and now we set up for reading the * child pointed to by slot 'iip'. */ last_level = le16_to_cpu(idx->level); last_sqnum = le64_to_cpu(idx->ch.sqnum); br = ubifs_idx_branch(c, idx, iip); lnum = le32_to_cpu(br->lnum); offs = le32_to_cpu(br->offs); len = le32_to_cpu(br->len); key_read(c, &br->key, &lower_key); if (iip + 1 < le16_to_cpu(idx->child_cnt)) { br = ubifs_idx_branch(c, idx, iip + 1); key_read(c, &br->key, &upper_key); } else key_copy(c, &i->upper_key, &upper_key); }
/** * create_default_filesystem - format empty UBI volume. * @c: UBIFS file-system description object * * This function creates default empty file-system. Returns zero in case of * success and a negative error code in case of failure. */ static int create_default_filesystem(struct ubifs_info *c) { struct ubifs_sb_node *sup; struct ubifs_mst_node *mst; struct ubifs_idx_node *idx; struct ubifs_branch *br; struct ubifs_ino_node *ino; struct ubifs_cs_node *cs; union ubifs_key key; int err, tmp, jnl_lebs, log_lebs, max_buds, main_lebs, main_first; int lpt_lebs, lpt_first, orph_lebs, big_lpt, ino_waste, sup_flags = 0; int min_leb_cnt = UBIFS_MIN_LEB_CNT; long long tmp64, main_bytes; __le64 tmp_le64; /* Some functions called from here depend on the @c->key_len filed */ c->key_len = UBIFS_SK_LEN; /* * First of all, we have to calculate default file-system geometry - * log size, journal size, etc. */ if (c->leb_cnt < 0x7FFFFFFF / DEFAULT_JNL_PERCENT) /* We can first multiply then divide and have no overflow */ jnl_lebs = c->leb_cnt * DEFAULT_JNL_PERCENT / 100; else jnl_lebs = (c->leb_cnt / 100) * DEFAULT_JNL_PERCENT; if (jnl_lebs < UBIFS_MIN_JNL_LEBS) jnl_lebs = UBIFS_MIN_JNL_LEBS; if (jnl_lebs * c->leb_size > DEFAULT_MAX_JNL) jnl_lebs = DEFAULT_MAX_JNL / c->leb_size; /* * The log should be large enough to fit reference nodes for all bud * LEBs. Because buds do not have to start from the beginning of LEBs * (half of the LEB may contain committed data), the log should * generally be larger, make it twice as large. */ tmp = 2 * (c->ref_node_alsz * jnl_lebs) + c->leb_size - 1; log_lebs = tmp / c->leb_size; /* Plus one LEB reserved for commit */ log_lebs += 1; if (c->leb_cnt - min_leb_cnt > 8) { /* And some extra space to allow writes while committing */ log_lebs += 1; min_leb_cnt += 1; } max_buds = jnl_lebs - log_lebs; if (max_buds < UBIFS_MIN_BUD_LEBS) max_buds = UBIFS_MIN_BUD_LEBS; /* * Orphan nodes are stored in a separate area. One node can store a lot * of orphan inode numbers, but when new orphan comes we just add a new * orphan node. At some point the nodes are consolidated into one * orphan node. */ orph_lebs = UBIFS_MIN_ORPH_LEBS; #ifdef CONFIG_UBIFS_FS_DEBUG if (c->leb_cnt - min_leb_cnt > 1) /* * For debugging purposes it is better to have at least 2 * orphan LEBs, because the orphan subsystem would need to do * consolidations and would be stressed more. */ orph_lebs += 1; #endif main_lebs = c->leb_cnt - UBIFS_SB_LEBS - UBIFS_MST_LEBS - log_lebs; main_lebs -= orph_lebs; lpt_first = UBIFS_LOG_LNUM + log_lebs; c->lsave_cnt = DEFAULT_LSAVE_CNT; c->max_leb_cnt = c->leb_cnt; err = ubifs_create_dflt_lpt(c, &main_lebs, lpt_first, &lpt_lebs, &big_lpt); if (err) return err; dbg_gen("LEB Properties Tree created (LEBs %d-%d)", lpt_first, lpt_first + lpt_lebs - 1); main_first = c->leb_cnt - main_lebs; /* Create default superblock */ tmp = ALIGN(UBIFS_SB_NODE_SZ, c->min_io_size); sup = kzalloc(tmp, GFP_KERNEL); if (!sup) return -ENOMEM; tmp64 = (long long)max_buds * c->leb_size; if (big_lpt) sup_flags |= UBIFS_FLG_BIGLPT; sup->ch.node_type = UBIFS_SB_NODE; sup->key_hash = UBIFS_KEY_HASH_R5; sup->flags = cpu_to_le32(sup_flags); sup->min_io_size = cpu_to_le32(c->min_io_size); sup->leb_size = cpu_to_le32(c->leb_size); sup->leb_cnt = cpu_to_le32(c->leb_cnt); sup->max_leb_cnt = cpu_to_le32(c->max_leb_cnt); sup->max_bud_bytes = cpu_to_le64(tmp64); sup->log_lebs = cpu_to_le32(log_lebs); sup->lpt_lebs = cpu_to_le32(lpt_lebs); sup->orph_lebs = cpu_to_le32(orph_lebs); sup->jhead_cnt = cpu_to_le32(DEFAULT_JHEADS_CNT); sup->fanout = cpu_to_le32(DEFAULT_FANOUT); sup->lsave_cnt = cpu_to_le32(c->lsave_cnt); sup->fmt_version = cpu_to_le32(UBIFS_FORMAT_VERSION); sup->time_gran = cpu_to_le32(DEFAULT_TIME_GRAN); if (c->mount_opts.override_compr) sup->default_compr = cpu_to_le16(c->mount_opts.compr_type); else sup->default_compr = cpu_to_le16(UBIFS_COMPR_LZO); generate_random_uuid(sup->uuid); main_bytes = (long long)main_lebs * c->leb_size; tmp64 = div_u64(main_bytes * DEFAULT_RP_PERCENT, 100); if (tmp64 > DEFAULT_MAX_RP_SIZE) tmp64 = DEFAULT_MAX_RP_SIZE; sup->rp_size = cpu_to_le64(tmp64); sup->ro_compat_version = cpu_to_le32(UBIFS_RO_COMPAT_VERSION); err = ubifs_write_node(c, sup, UBIFS_SB_NODE_SZ, 0, 0, UBI_LONGTERM); kfree(sup); if (err) return err; dbg_gen("default superblock created at LEB 0:0"); /* Create default master node */ mst = kzalloc(c->mst_node_alsz, GFP_KERNEL); if (!mst) return -ENOMEM; mst->ch.node_type = UBIFS_MST_NODE; mst->log_lnum = cpu_to_le32(UBIFS_LOG_LNUM); mst->highest_inum = cpu_to_le64(UBIFS_FIRST_INO); mst->cmt_no = 0; mst->root_lnum = cpu_to_le32(main_first + DEFAULT_IDX_LEB); mst->root_offs = 0; tmp = ubifs_idx_node_sz(c, 1); mst->root_len = cpu_to_le32(tmp); mst->gc_lnum = cpu_to_le32(main_first + DEFAULT_GC_LEB); mst->ihead_lnum = cpu_to_le32(main_first + DEFAULT_IDX_LEB); mst->ihead_offs = cpu_to_le32(ALIGN(tmp, c->min_io_size)); mst->index_size = cpu_to_le64(ALIGN(tmp, 8)); mst->lpt_lnum = cpu_to_le32(c->lpt_lnum); mst->lpt_offs = cpu_to_le32(c->lpt_offs); mst->nhead_lnum = cpu_to_le32(c->nhead_lnum); mst->nhead_offs = cpu_to_le32(c->nhead_offs); mst->ltab_lnum = cpu_to_le32(c->ltab_lnum); mst->ltab_offs = cpu_to_le32(c->ltab_offs); mst->lsave_lnum = cpu_to_le32(c->lsave_lnum); mst->lsave_offs = cpu_to_le32(c->lsave_offs); mst->lscan_lnum = cpu_to_le32(main_first); mst->empty_lebs = cpu_to_le32(main_lebs - 2); mst->idx_lebs = cpu_to_le32(1); mst->leb_cnt = cpu_to_le32(c->leb_cnt); /* Calculate lprops statistics */ tmp64 = main_bytes; tmp64 -= ALIGN(ubifs_idx_node_sz(c, 1), c->min_io_size); tmp64 -= ALIGN(UBIFS_INO_NODE_SZ, c->min_io_size); mst->total_free = cpu_to_le64(tmp64); tmp64 = ALIGN(ubifs_idx_node_sz(c, 1), c->min_io_size); ino_waste = ALIGN(UBIFS_INO_NODE_SZ, c->min_io_size) - UBIFS_INO_NODE_SZ; tmp64 += ino_waste; tmp64 -= ALIGN(ubifs_idx_node_sz(c, 1), 8); mst->total_dirty = cpu_to_le64(tmp64); /* The indexing LEB does not contribute to dark space */ tmp64 = (c->main_lebs - 1) * c->dark_wm; mst->total_dark = cpu_to_le64(tmp64); mst->total_used = cpu_to_le64(UBIFS_INO_NODE_SZ); err = ubifs_write_node(c, mst, UBIFS_MST_NODE_SZ, UBIFS_MST_LNUM, 0, UBI_UNKNOWN); if (err) { kfree(mst); return err; } err = ubifs_write_node(c, mst, UBIFS_MST_NODE_SZ, UBIFS_MST_LNUM + 1, 0, UBI_UNKNOWN); kfree(mst); if (err) return err; dbg_gen("default master node created at LEB %d:0", UBIFS_MST_LNUM); /* Create the root indexing node */ tmp = ubifs_idx_node_sz(c, 1); idx = kzalloc(ALIGN(tmp, c->min_io_size), GFP_KERNEL); if (!idx) return -ENOMEM; c->key_fmt = UBIFS_SIMPLE_KEY_FMT; c->key_hash = key_r5_hash; idx->ch.node_type = UBIFS_IDX_NODE; idx->child_cnt = cpu_to_le16(1); ino_key_init(c, &key, UBIFS_ROOT_INO); br = ubifs_idx_branch(c, idx, 0); key_write_idx(c, &key, &br->key); br->lnum = cpu_to_le32(main_first + DEFAULT_DATA_LEB); br->len = cpu_to_le32(UBIFS_INO_NODE_SZ); err = ubifs_write_node(c, idx, tmp, main_first + DEFAULT_IDX_LEB, 0, UBI_UNKNOWN); kfree(idx); if (err) return err; dbg_gen("default root indexing node created LEB %d:0", main_first + DEFAULT_IDX_LEB); /* Create default root inode */ tmp = ALIGN(UBIFS_INO_NODE_SZ, c->min_io_size); ino = kzalloc(tmp, GFP_KERNEL); if (!ino) return -ENOMEM; ino_key_init_flash(c, &ino->key, UBIFS_ROOT_INO); ino->ch.node_type = UBIFS_INO_NODE; ino->creat_sqnum = cpu_to_le64(++c->max_sqnum); ino->nlink = cpu_to_le32(2); tmp_le64 = cpu_to_le64(CURRENT_TIME_SEC.tv_sec); ino->atime_sec = tmp_le64; ino->ctime_sec = tmp_le64; ino->mtime_sec = tmp_le64; ino->atime_nsec = 0; ino->ctime_nsec = 0; ino->mtime_nsec = 0; ino->mode = cpu_to_le32(S_IFDIR | S_IRUGO | S_IWUSR | S_IXUGO); ino->size = cpu_to_le64(UBIFS_INO_NODE_SZ); /* Set compression enabled by default */ ino->flags = cpu_to_le32(UBIFS_COMPR_FL); err = ubifs_write_node(c, ino, UBIFS_INO_NODE_SZ, main_first + DEFAULT_DATA_LEB, 0, UBI_UNKNOWN); kfree(ino); if (err) return err; dbg_gen("root inode created at LEB %d:0", main_first + DEFAULT_DATA_LEB); /* * The first node in the log has to be the commit start node. This is * always the case during normal file-system operation. Write a fake * commit start node to the log. */ tmp = ALIGN(UBIFS_CS_NODE_SZ, c->min_io_size); cs = kzalloc(tmp, GFP_KERNEL); if (!cs) return -ENOMEM; cs->ch.node_type = UBIFS_CS_NODE; err = ubifs_write_node(c, cs, UBIFS_CS_NODE_SZ, UBIFS_LOG_LNUM, 0, UBI_UNKNOWN); kfree(cs); ubifs_msg("default file-system created"); return 0; }
/** * read_znode - read an indexing node from flash and fill znode. * @c: UBIFS file-system description object * @lnum: LEB of the indexing node to read * @offs: node offset * @len: node length * @znode: znode to read to * * This function reads an indexing node from the flash media and fills znode * with the read data. Returns zero in case of success and a negative error * code in case of failure. The read indexing node is validated and if anything * is wrong with it, this function prints complaint messages and returns * %-EINVAL. */ static int read_znode(struct ubifs_info *c, int lnum, int offs, int len, struct ubifs_znode *znode) { int i, err, type, cmp; struct ubifs_idx_node *idx; idx = kmalloc(c->max_idx_node_sz, GFP_NOFS); if (!idx) return -ENOMEM; err = ubifs_read_node(c, idx, UBIFS_IDX_NODE, len, lnum, offs); if (err < 0) { kfree(idx); return err; } znode->child_cnt = le16_to_cpu(idx->child_cnt); znode->level = le16_to_cpu(idx->level); dbg_tnc("LEB %d:%d, level %d, %d branch", lnum, offs, znode->level, znode->child_cnt); if (znode->child_cnt > c->fanout || znode->level > UBIFS_MAX_LEVELS) { dbg_err("current fanout %d, branch count %d", c->fanout, znode->child_cnt); dbg_err("max levels %d, znode level %d", UBIFS_MAX_LEVELS, znode->level); err = 1; goto out_dump; } for (i = 0; i < znode->child_cnt; i++) { const struct ubifs_branch *br = ubifs_idx_branch(c, idx, i); struct ubifs_zbranch *zbr = &znode->zbranch[i]; key_read(c, &br->key, &zbr->key); zbr->lnum = le32_to_cpu(br->lnum); zbr->offs = le32_to_cpu(br->offs); zbr->len = le32_to_cpu(br->len); zbr->znode = NULL; /* Validate branch */ if (zbr->lnum < c->main_first || zbr->lnum >= c->leb_cnt || zbr->offs < 0 || zbr->offs + zbr->len > c->leb_size || zbr->offs & 7) { dbg_err("bad branch %d", i); err = 2; goto out_dump; } switch (key_type(c, &zbr->key)) { case UBIFS_INO_KEY: case UBIFS_DATA_KEY: case UBIFS_DENT_KEY: case UBIFS_XENT_KEY: break; default: dbg_msg("bad key type at slot %d: %s", i, DBGKEY(&zbr->key)); err = 3; goto out_dump; } if (znode->level) continue; type = key_type(c, &zbr->key); if (c->ranges[type].max_len == 0) { if (zbr->len != c->ranges[type].len) { dbg_err("bad target node (type %d) length (%d)", type, zbr->len); dbg_err("have to be %d", c->ranges[type].len); err = 4; goto out_dump; } } else if (zbr->len < c->ranges[type].min_len || zbr->len > c->ranges[type].max_len) { dbg_err("bad target node (type %d) length (%d)", type, zbr->len); dbg_err("have to be in range of %d-%d", c->ranges[type].min_len, c->ranges[type].max_len); err = 5; goto out_dump; } } /* * Ensure that the next key is greater or equivalent to the * previous one. */ for (i = 0; i < znode->child_cnt - 1; i++) { const union ubifs_key *key1, *key2; key1 = &znode->zbranch[i].key; key2 = &znode->zbranch[i + 1].key; cmp = keys_cmp(c, key1, key2); if (cmp > 0) { dbg_err("bad key order (keys %d and %d)", i, i + 1); err = 6; goto out_dump; } else if (cmp == 0 && !is_hash_key(c, key1)) { /* These can only be keys with colliding hash */ dbg_err("keys %d and %d are not hashed but equivalent", i, i + 1); err = 7; goto out_dump; } } kfree(idx); return 0; out_dump: ubifs_err("bad indexing node at LEB %d:%d, error %d", lnum, offs, err); dbg_dump_node(c, idx); kfree(idx); return -EINVAL; }