/** * ubi_more_leb_change_data - accept more data for atomic LEB change. * @ubi: UBI device description object * @vol: volume description object * @buf: write data (user-space memory buffer) * @count: how much bytes to write * * This function accepts more data to the volume which is being under the * "atomic LEB change" operation. It may be called arbitrary number of times * until all data arrives. This function returns %0 in case of success, number * of bytes written during the last call if the whole "atomic LEB change" * operation has been successfully finished, and a negative error code in case * of failure. */ int ubi_more_leb_change_data(struct ubi_device *ubi, struct ubi_volume *vol, const void __user *buf, int count) { int err; dbg_gen("write %d of %lld bytes, %lld already passed", count, vol->upd_bytes, vol->upd_received); if (ubi->ro_mode) return -EROFS; if (vol->upd_received + count > vol->upd_bytes) count = vol->upd_bytes - vol->upd_received; err = copy_from_user(vol->upd_buf + vol->upd_received, buf, count); if (err) return -EFAULT; vol->upd_received += count; if (vol->upd_received == vol->upd_bytes) { int len = ALIGN((int)vol->upd_bytes, ubi->min_io_size); memset(vol->upd_buf + vol->upd_bytes, 0xFF, len - vol->upd_bytes); len = ubi_calc_data_len(ubi, vol->upd_buf, len); err = ubi_eba_atomic_leb_change(ubi, vol, vol->ch_lnum, vol->upd_buf, len); if (err) return err; } ubi_assert(vol->upd_received <= vol->upd_bytes); if (vol->upd_received == vol->upd_bytes) { vol->changing_leb = 0; err = count; vfree(vol->upd_buf); } return err; }
/** * ubi_leb_map - map logical eraseblock to a physical eraseblock. * @desc: volume descriptor * @lnum: logical eraseblock number * * This function maps an un-mapped logical eraseblock @lnum to a physical * eraseblock. This means, that after a successful invocation of this * function the logical eraseblock @lnum will be empty (contain only %0xFF * bytes) and be mapped to a physical eraseblock, even if an unclean reboot * happens. * * This function returns zero in case of success, %-EBADF if the volume is * damaged because of an interrupted update, %-EBADMSG if the logical * eraseblock is already mapped, and other negative error codes in case of * other failures. */ int ubi_leb_map(struct ubi_volume_desc *desc, int lnum) { struct ubi_volume *vol = desc->vol; struct ubi_device *ubi = vol->ubi; dbg_gen("unmap LEB %d:%d", vol->vol_id, lnum); if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME) return -EROFS; if (lnum < 0 || lnum >= vol->reserved_pebs) return -EINVAL; if (vol->upd_marker) return -EBADF; if (vol->eba_tbl[lnum] >= 0) return -EBADMSG; return ubi_eba_write_leb(ubi, vol, lnum, NULL, 0, 0); }
/** * ubi_leb_map - map logical eraseblock to a physical eraseblock. * @desc: volume descriptor * @lnum: logical eraseblock number * * This function maps an un-mapped logical eraseblock @lnum to a physical * eraseblock. This means, that after a successful invocation of this * function the logical eraseblock @lnum will be empty (contain only %0xFF * bytes) and be mapped to a physical eraseblock, even if an unclean reboot * happens. * * This function returns zero in case of success, %-EBADF if the volume is * damaged because of an interrupted update, %-EBADMSG if the logical * eraseblock is already mapped, and other negative error codes in case of * other failures. */ int ubi_leb_map(struct ubi_volume_desc *desc, int lnum) { struct ubi_volume *vol = desc->vol; struct ubi_device *ubi = vol->ubi; dbg_gen("map LEB %d:%d", vol->vol_id, lnum); if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME) return -EROFS; if (!ubi_leb_valid(vol, lnum)) return -EINVAL; if (vol->upd_marker) return -EBADF; if (ubi_eba_is_mapped(vol, lnum)) return -EBADMSG; return ubi_eba_write_leb(ubi, vol, lnum, NULL, 0, 0); }
/** * ubi_start_leb_change - start atomic LEB change. * @ubi: UBI device description object * @vol: volume description object * @req: operation request * * This function starts atomic LEB change operation. Returns zero in case of * success and a negative error code in case of failure. */ int ubi_start_leb_change(struct ubi_device *ubi, struct ubi_volume *vol, const struct ubi_leb_change_req *req) { ubi_assert(!vol->updating && !vol->changing_leb); dbg_gen("start changing LEB %d:%d, %u bytes", vol->vol_id, req->lnum, req->bytes); if (req->bytes == 0) return ubi_eba_atomic_leb_change(ubi, vol, req->lnum, NULL, 0); vol->upd_bytes = req->bytes; vol->upd_received = 0; vol->changing_leb = 1; vol->ch_lnum = req->lnum; vol->upd_buf = vmalloc(req->bytes); if (!vol->upd_buf) return -ENOMEM; return 0; }
/** * ubi_create_gluebi - initialize gluebi for an UBI volume. * @ubi: UBI device description object * @vol: volume description object * * This function is called when an UBI volume is created in order to create * corresponding fake MTD device. Returns zero in case of success and a * negative error code in case of failure. */ int ubi_create_gluebi(struct ubi_device *ubi, struct ubi_volume *vol) { struct mtd_info *mtd = &vol->gluebi_mtd; mtd->name = kmemdup(vol->name, vol->name_len + 1, GFP_KERNEL); if (!mtd->name) return -ENOMEM; mtd->type = MTD_UBIVOLUME; if (!ubi->ro_mode) mtd->flags = MTD_WRITEABLE; mtd->writesize = ubi->min_io_size; mtd->owner = THIS_MODULE; mtd->erasesize = vol->usable_leb_size; mtd->read = gluebi_read; mtd->write = gluebi_write; mtd->erase = gluebi_erase; mtd->get_device = gluebi_get_device; mtd->put_device = gluebi_put_device; /* * In case of dynamic volume, MTD device size is just volume size. In * case of a static volume the size is equivalent to the amount of data * bytes. */ if (vol->vol_type == UBI_DYNAMIC_VOLUME) mtd->size = (long long)vol->usable_leb_size * vol->reserved_pebs; else mtd->size = vol->used_bytes; if (add_mtd_device(mtd)) { ubi_err("cannot not add MTD device"); kfree(mtd->name); return -ENFILE; } dbg_gen("added mtd%d (\"%s\"), size %llu, EB size %u", mtd->index, mtd->name, (unsigned long long)mtd->size, mtd->erasesize); return 0; }
/** * ubi_start_update - start volume update. * @ubi: UBI device description object * @vol: volume description object * @bytes: update bytes * * This function starts volume update operation. If @bytes is zero, the volume * is just wiped out. Returns zero in case of success and a negative error code * in case of failure. */ int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol, long long bytes) { int i, err; dbg_gen("start update of volume %d, %llu bytes", vol->vol_id, bytes); ubi_assert(!vol->updating && !vol->changing_leb); vol->updating = 1; err = set_update_marker(ubi, vol); if (err) return err; /* Before updating - wipe out the volume */ for (i = 0; i < vol->reserved_pebs; i++) { err = ubi_eba_unmap_leb(ubi, vol, i); if (err) return err; } if (bytes == 0) { err = clear_update_marker(ubi, vol, 0); if (err) return err; err = ubi_wl_flush(ubi); if (!err) vol->updating = 0; } vol->upd_buf = vmalloc(ubi->leb_size); if (!vol->upd_buf) return -ENOMEM; vol->upd_ebs = div_u64(bytes + vol->usable_leb_size - 1, vol->usable_leb_size); vol->upd_bytes = bytes; vol->upd_received = 0; return 0; }
/** * compr_init - initialize a compressor. * @compr: compressor description object * * This function initializes the requested compressor and returns zero in case * of success or a negative error code in case of failure. */ static int __init compr_init(struct ubifs_compressor *compr) { ubifs_compressors[compr->compr_type] = compr; #ifdef CONFIG_NEEDS_MANUAL_RELOC ubifs_compressors[compr->compr_type]->name += gd->reloc_off; ubifs_compressors[compr->compr_type]->capi_name += gd->reloc_off; ubifs_compressors[compr->compr_type]->decompress += gd->reloc_off; #endif if (compr->capi_name) { compr->cc = crypto_alloc_comp(compr->capi_name, 0, 0); if (IS_ERR(compr->cc)) { dbg_gen("cannot initialize compressor %s," " error %ld", compr->name, PTR_ERR(compr->cc)); return PTR_ERR(compr->cc); } } return 0; }
/** * ubifs_umount - un-mount UBIFS file-system. * @c: UBIFS file-system description object * * Note, this function is called to free allocated resourced when un-mounting, * as well as free resources when an error occurred while we were half way * through mounting (error path cleanup function). So it has to make sure the * resource was actually allocated before freeing it. */ void ubifs_umount(struct ubifs_info *c) { dbg_gen("un-mounting UBI device %d, volume %d", c->vi.ubi_num, c->vi.vol_id); spin_lock(&ubifs_infos_lock); list_del(&c->infos_list); spin_unlock(&ubifs_infos_lock); if (c->bgt) kthread_stop(c->bgt); free_orphans(c); ubifs_lpt_free(c, 0); kfree(c->cbuf); kfree(c->rcvrd_mst_node); kfree(c->mst_node); vfree(c->ileb_buf); vfree(c->sbuf); kfree(c->bottom_up_buf); ubifs_debugging_exit(c); }
/** * ubi_leb_erase - erase logical eraseblock. * @desc: volume descriptor * @lnum: logical eraseblock number * * This function un-maps logical eraseblock @lnum and synchronously erases the * correspondent physical eraseblock. Returns zero in case of success and a * negative error code in case of failure. * * If the volume is damaged because of an interrupted update this function just * returns immediately with %-EBADF code. */ int ubi_leb_erase(struct ubi_volume_desc *desc, int lnum) { struct ubi_volume *vol = desc->vol; struct ubi_device *ubi = vol->ubi; int err; dbg_gen("erase LEB %d:%d", vol->vol_id, lnum); if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME) return -EROFS; if (lnum < 0 || lnum >= vol->reserved_pebs) return -EINVAL; if (vol->upd_marker) return -EBADF; err = ubi_eba_unmap_leb(ubi, vol, lnum); if (err) return err; return ubi_wl_flush(ubi); }
/** * gluebi_read - read operation of emulated MTD devices. * @mtd: MTD device description object * @from: absolute offset from where to read * @len: how many bytes to read * @retlen: count of read bytes is returned here * @buf: buffer to store the read data * * This function returns zero in case of success and a negative error code in * case of failure. */ static int gluebi_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, unsigned char *buf) { int err = 0, lnum, offs, total_read; struct ubi_volume *vol; struct ubi_device *ubi; dbg_gen("read %zd bytes from offset %lld", len, from); if (len < 0 || from < 0 || from + len > mtd->size) return -EINVAL; vol = container_of(mtd, struct ubi_volume, gluebi_mtd); ubi = vol->ubi; lnum = div_u64_rem(from, mtd->erasesize, &offs); total_read = len; while (total_read) { size_t to_read = mtd->erasesize - offs; if (to_read > total_read) to_read = total_read; err = ubi_eba_read_leb(ubi, vol, lnum, buf, offs, to_read, 0); if (err) break; lnum += 1; offs = 0; total_read -= to_read; buf += to_read; } *retlen = len - total_read; return err; }
/** * ubi_open_volume_path - open UBI volume by its character device node path. * @pathname: volume character device node path * @mode: open mode * * This function is similar to 'ubi_open_volume()', but opens a volume the path * to its character device node. */ struct ubi_volume_desc *ubi_open_volume_path(const char *pathname, int mode) { int error, ubi_num, vol_id; struct kstat stat; dbg_gen("open volume %s, mode %d", pathname, mode); if (!pathname || !*pathname) return ERR_PTR(-EINVAL); error = vfs_stat(pathname, &stat); if (error) return ERR_PTR(error); if (!S_ISCHR(stat.mode)) return ERR_PTR(-EINVAL); ubi_num = ubi_major2num(MAJOR(stat.rdev)); vol_id = MINOR(stat.rdev) - 1; if (vol_id >= 0 && ubi_num >= 0) return ubi_open_volume(ubi_num, vol_id, mode); return ERR_PTR(-ENODEV); }
/** * ubi_leb_read_sg - read data into a scatter gather list. * @desc: volume descriptor * @lnum: logical eraseblock number to read from * @buf: buffer where to store the read data * @offset: offset within the logical eraseblock to read from * @len: how many bytes to read * @check: whether UBI has to check the read data's CRC or not. * * This function works exactly like ubi_leb_read_sg(). But instead of * storing the read data into a buffer it writes to an UBI scatter gather * list. */ int ubi_leb_read_sg(struct ubi_volume_desc *desc, int lnum, struct ubi_sgl *sgl, int offset, int len, int check) { struct ubi_volume *vol = desc->vol; struct ubi_device *ubi = vol->ubi; int err, vol_id = vol->vol_id; dbg_gen("read %d bytes from LEB %d:%d:%d", len, vol_id, lnum, offset); err = leb_read_sanity_check(desc, lnum, offset, len); if (err < 0) return err; if (len == 0) return 0; err = ubi_eba_read_leb_sg(ubi, vol, sgl, lnum, offset, len, check); if (err && mtd_is_eccerr(err) && vol->vol_type == UBI_STATIC_VOLUME) { ubi_warn(ubi, "mark volume %d as corrupted", vol_id); vol->corrupted = 1; } return err; }
/** * ubi_leb_read - read data. * @desc: volume descriptor * @lnum: logical eraseblock number to read from * @buf: buffer where to store the read data * @offset: offset within the logical eraseblock to read from * @len: how many bytes to read * @check: whether UBI has to check the read data's CRC or not. * * This function reads data from offset @offset of logical eraseblock @lnum and * stores the data at @buf. When reading from static volumes, @check specifies * whether the data has to be checked or not. If yes, the whole logical * eraseblock will be read and its CRC checksum will be checked (i.e., the CRC * checksum is per-eraseblock). So checking may substantially slow down the * read speed. The @check argument is ignored for dynamic volumes. * * In case of success, this function returns zero. In case of failure, this * function returns a negative error code. * * %-EBADMSG error code is returned: * o for both static and dynamic volumes if MTD driver has detected a data * integrity problem (unrecoverable ECC checksum mismatch in case of NAND); * o for static volumes in case of data CRC mismatch. * * If the volume is damaged because of an interrupted update this function just * returns immediately with %-EBADF error code. */ int ubi_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset, int len, int check) { struct ubi_volume *vol = desc->vol; struct ubi_device *ubi = vol->ubi; int err, vol_id = vol->vol_id; dbg_gen("read %d bytes from LEB %d:%d:%d", len, vol_id, lnum, offset); if (vol_id < 0 || vol_id >= ubi->vtbl_slots || lnum < 0 || lnum >= vol->used_ebs || offset < 0 || len < 0 || offset + len > vol->usable_leb_size) return -EINVAL; if (vol->vol_type == UBI_STATIC_VOLUME) { if (vol->used_ebs == 0) /* Empty static UBI volume */ return 0; if (lnum == vol->used_ebs - 1 && offset + len > vol->last_eb_bytes) return -EINVAL; } if (vol->upd_marker) return -EBADF; if (len == 0) return 0; err = ubi_eba_read_leb(ubi, vol, lnum, buf, offset, len, check); if (err && err == -EBADMSG && vol->vol_type == UBI_STATIC_VOLUME) { ubi_warn("mark volume %d as corrupted", vol_id); vol->corrupted = 1; } return err; }
static int do_readpage(struct ubifs_info *c, struct inode *inode, struct page *page, int last_block_size) { void *addr; int err = 0, i; unsigned int block, beyond; struct ubifs_data_node *dn; loff_t i_size = inode->i_size; dbg_gen("ino %lu, pg %lu, i_size %lld", inode->i_ino, page->index, i_size); addr = kmap(page); block = page->index << UBIFS_BLOCKS_PER_PAGE_SHIFT; beyond = (i_size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT; if (block >= beyond) { /* Reading beyond inode */ memset(addr, 0, PAGE_CACHE_SIZE); goto out; } dn = kmalloc(UBIFS_MAX_DATA_NODE_SZ, GFP_NOFS); if (!dn) return -ENOMEM; i = 0; while (1) { int ret; if (block >= beyond) { /* Reading beyond inode */ err = -ENOENT; memset(addr, 0, UBIFS_BLOCK_SIZE); } else { /* * Reading last block? Make sure to not write beyond * the requested size in the destination buffer. */ if (((block + 1) == beyond) || last_block_size) { void *buff; int dlen; /* * We need to buffer the data locally for the * last block. This is to not pad the * destination area to a multiple of * UBIFS_BLOCK_SIZE. */ buff = malloc(UBIFS_BLOCK_SIZE); if (!buff) { printf("%s: Error, malloc fails!\n", __func__); err = -ENOMEM; break; } /* Read block-size into temp buffer */ ret = read_block(inode, buff, block, dn); if (ret) { err = ret; if (err != -ENOENT) { free(buff); break; } } if (last_block_size) dlen = last_block_size; else dlen = le32_to_cpu(dn->size); /* Now copy required size back to dest */ memcpy(addr, buff, dlen); free(buff); } else { ret = read_block(inode, addr, block, dn); if (ret) { err = ret; if (err != -ENOENT) break; } } } if (++i >= UBIFS_BLOCKS_PER_PAGE) break; block += 1; addr += UBIFS_BLOCK_SIZE; } if (err) { if (err == -ENOENT) { /* Not found, so it must be a hole */ dbg_gen("hole"); goto out_free; } ubifs_err("cannot read page %lu of inode %lu, error %d", page->index, inode->i_ino, err); goto error; } out_free: kfree(dn); out: return 0; error: kfree(dn); return err; }
static int ubifs_finddir(struct super_block *sb, char *dirname, unsigned long root_inum, unsigned long *inum) { int err; struct qstr nm; union ubifs_key key; struct ubifs_dent_node *dent; struct ubifs_info *c; struct file *file; struct dentry *dentry; struct inode *dir; file = kzalloc(sizeof(struct file), 0); dentry = kzalloc(sizeof(struct dentry), 0); dir = kzalloc(sizeof(struct inode), 0); if (!file || !dentry || !dir) { printf("%s: Error, no memory for malloc!\n", __func__); err = -ENOMEM; goto out; } dir->i_sb = sb; file->f_path.dentry = dentry; file->f_path.dentry->d_parent = dentry; file->f_path.dentry->d_inode = dir; file->f_path.dentry->d_inode->i_ino = root_inum; c = sb->s_fs_info; dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, file->f_pos); /* Find the first entry in TNC and save it */ lowest_dent_key(c, &key, dir->i_ino); nm.name = NULL; dent = ubifs_tnc_next_ent(c, &key, &nm); if (IS_ERR(dent)) { err = PTR_ERR(dent); goto out; } file->f_pos = key_hash_flash(c, &dent->key); file->private_data = dent; while (1) { dbg_gen("feed '%s', ino %llu, new f_pos %#x", dent->name, (unsigned long long)le64_to_cpu(dent->inum), key_hash_flash(c, &dent->key)); ubifs_assert(le64_to_cpu(dent->ch.sqnum) > ubifs_inode(dir)->creat_sqnum); nm.len = le16_to_cpu(dent->nlen); if ((strncmp(dirname, (char *)dent->name, nm.len) == 0) && (strlen(dirname) == nm.len)) { *inum = le64_to_cpu(dent->inum); return 1; } /* Switch to the next entry */ key_read(c, &dent->key, &key); nm.name = (char *)dent->name; dent = ubifs_tnc_next_ent(c, &key, &nm); if (IS_ERR(dent)) { err = PTR_ERR(dent); goto out; } kfree(file->private_data); file->f_pos = key_hash_flash(c, &dent->key); file->private_data = dent; cond_resched(); } out: if (err != -ENOENT) { ubifs_err("cannot find next direntry, error %d", err); return err; } if (file) free(file); if (dentry) free(dentry); if (dir) free(dir); if (file->private_data) kfree(file->private_data); file->private_data = NULL; file->f_pos = 2; return 0; }
static int ubifs_printdir(struct file *file, void *dirent) { int err, over = 0; struct qstr nm; union ubifs_key key; struct ubifs_dent_node *dent; struct inode *dir = file->f_path.dentry->d_inode; struct ubifs_info *c = dir->i_sb->s_fs_info; dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, file->f_pos); if (file->f_pos > UBIFS_S_KEY_HASH_MASK || file->f_pos == 2) /* * The directory was seek'ed to a senseless position or there * are no more entries. */ return 0; if (file->f_pos == 1) { /* Find the first entry in TNC and save it */ lowest_dent_key(c, &key, dir->i_ino); nm.name = NULL; dent = ubifs_tnc_next_ent(c, &key, &nm); if (IS_ERR(dent)) { err = PTR_ERR(dent); goto out; } file->f_pos = key_hash_flash(c, &dent->key); file->private_data = dent; } dent = file->private_data; if (!dent) { /* * The directory was seek'ed to and is now readdir'ed. * Find the entry corresponding to @file->f_pos or the * closest one. */ dent_key_init_hash(c, &key, dir->i_ino, file->f_pos); nm.name = NULL; dent = ubifs_tnc_next_ent(c, &key, &nm); if (IS_ERR(dent)) { err = PTR_ERR(dent); goto out; } file->f_pos = key_hash_flash(c, &dent->key); file->private_data = dent; } while (1) { dbg_gen("feed '%s', ino %llu, new f_pos %#x", dent->name, (unsigned long long)le64_to_cpu(dent->inum), key_hash_flash(c, &dent->key)); ubifs_assert(le64_to_cpu(dent->ch.sqnum) > ubifs_inode(dir)->creat_sqnum); nm.len = le16_to_cpu(dent->nlen); over = filldir(c, (char *)dent->name, nm.len, le64_to_cpu(dent->inum), dent->type); if (over) return 0; /* Switch to the next entry */ key_read(c, &dent->key, &key); nm.name = (char *)dent->name; dent = ubifs_tnc_next_ent(c, &key, &nm); if (IS_ERR(dent)) { err = PTR_ERR(dent); goto out; } kfree(file->private_data); file->f_pos = key_hash_flash(c, &dent->key); file->private_data = dent; cond_resched(); } out: if (err != -ENOENT) { ubifs_err("cannot find next direntry, error %d", err); return err; } kfree(file->private_data); file->private_data = NULL; file->f_pos = 2; return 0; }
struct inode *ubifs_iget(struct super_block *sb, unsigned long inum) { int err; union ubifs_key key; struct ubifs_ino_node *ino; struct ubifs_info *c = sb->s_fs_info; struct inode *inode; struct ubifs_inode *ui; int i; dbg_gen("inode %lu", inum); /* * U-Boot special handling of locked down inodes via recovery * e.g. ubifs_recover_size() */ for (i = 0; i < INODE_LOCKED_MAX; i++) { /* * Exit on last entry (NULL), inode not found in list */ if (inodes_locked_down[i] == NULL) break; if (inodes_locked_down[i]->i_ino == inum) { /* * We found the locked down inode in our array, * so just return this pointer instead of creating * a new one. */ return inodes_locked_down[i]; } } inode = iget_locked(sb, inum); if (!inode) return ERR_PTR(-ENOMEM); if (!(inode->i_state & I_NEW)) return inode; ui = ubifs_inode(inode); ino = kmalloc(UBIFS_MAX_INO_NODE_SZ, GFP_NOFS); if (!ino) { err = -ENOMEM; goto out; } ino_key_init(c, &key, inode->i_ino); err = ubifs_tnc_lookup(c, &key, ino); if (err) goto out_ino; inode->i_flags |= (S_NOCMTIME | S_NOATIME); inode->i_nlink = le32_to_cpu(ino->nlink); inode->i_uid = le32_to_cpu(ino->uid); inode->i_gid = le32_to_cpu(ino->gid); inode->i_atime.tv_sec = (int64_t)le64_to_cpu(ino->atime_sec); inode->i_atime.tv_nsec = le32_to_cpu(ino->atime_nsec); inode->i_mtime.tv_sec = (int64_t)le64_to_cpu(ino->mtime_sec); inode->i_mtime.tv_nsec = le32_to_cpu(ino->mtime_nsec); inode->i_ctime.tv_sec = (int64_t)le64_to_cpu(ino->ctime_sec); inode->i_ctime.tv_nsec = le32_to_cpu(ino->ctime_nsec); inode->i_mode = le32_to_cpu(ino->mode); inode->i_size = le64_to_cpu(ino->size); ui->data_len = le32_to_cpu(ino->data_len); ui->flags = le32_to_cpu(ino->flags); ui->compr_type = le16_to_cpu(ino->compr_type); ui->creat_sqnum = le64_to_cpu(ino->creat_sqnum); ui->synced_i_size = ui->ui_size = inode->i_size; err = validate_inode(c, inode); if (err) goto out_invalid; if ((inode->i_mode & S_IFMT) == S_IFLNK) { if (ui->data_len <= 0 || ui->data_len > UBIFS_MAX_INO_DATA) { err = 12; goto out_invalid; } ui->data = kmalloc(ui->data_len + 1, GFP_NOFS); if (!ui->data) { err = -ENOMEM; goto out_ino; } memcpy(ui->data, ino->data, ui->data_len); ((char *)ui->data)[ui->data_len] = '\0'; } kfree(ino); inode->i_state &= ~(I_LOCK | I_NEW); return inode; out_invalid: ubifs_err("inode %lu validation failed, error %d", inode->i_ino, err); dbg_dump_node(c, ino); dbg_dump_inode(c, inode); err = -EINVAL; out_ino: kfree(ino); out: ubifs_err("failed to read inode %lu, error %d", inode->i_ino, err); return ERR_PTR(err); }
/** * ubi_io_read - read data from a physical eraseblock. * @ubi: UBI device description object * @buf: buffer where to store the read data * @pnum: physical eraseblock number to read from * @offset: offset within the physical eraseblock from where to read * @len: how many bytes to read * * This function reads data from offset @offset of physical eraseblock @pnum * and stores the read data in the @buf buffer. The following return codes are * possible: * * o %0 if all the requested data were successfully read; * o %UBI_IO_BITFLIPS if all the requested data were successfully read, but * correctable bit-flips were detected; this is harmless but may indicate * that this eraseblock may become bad soon (but do not have to); * o %-EBADMSG if the MTD subsystem reported about data integrity problems, for * example it can be an ECC error in case of NAND; this most probably means * that the data is corrupted; * o %-EIO if some I/O error occurred; * o other negative error codes in case of other errors. */ int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset, int len) { int err, retries = 0; size_t read; loff_t addr; dbg_io("read %d bytes from PEB %d:%d", len, pnum, offset); ubi_assert(pnum >= 0 && pnum < ubi->peb_count); ubi_assert(offset >= 0 && offset + len <= ubi->peb_size); ubi_assert(len > 0); err = paranoid_check_not_bad(ubi, pnum); if (err) return err; addr = (loff_t)pnum * ubi->peb_size + offset; retry: err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf); if (err == -EUCLEAN) err = 0; //added by Elvis, for ignore EUCLEAN if (err) { if (err == -EUCLEAN) { /* * -EUCLEAN is reported if there was a bit-flip which * was corrected, so this is harmless. * * We do not report about it here unless debugging is * enabled. A corresponding message will be printed * later, when it is has been scrubbed. */ dbg_msg("fixable bit-flip detected at PEB %d", pnum); ubi_assert(len == read); return UBI_IO_BITFLIPS; } if (read != len && retries++ < UBI_IO_RETRIES) { dbg_io("error %d while reading %d bytes from PEB %d:%d," " read only %zd bytes, retry", err, len, pnum, offset, read); yield(); goto retry; } ubi_err("error %d while reading %d bytes from PEB %d:%d, " "read %zd bytes", err, len, pnum, offset, read); ubi_dbg_dump_stack(); /* * The driver should never return -EBADMSG if it failed to read * all the requested data. But some buggy drivers might do * this, so we change it to -EIO. */ if (read != len && err == -EBADMSG) { ubi_assert(0); err = -EIO; } } else { ubi_assert(len == read); if (ubi_dbg_is_bitflip()) { dbg_gen("bit-flip (emulated)"); err = UBI_IO_BITFLIPS; } } return err; }
/** * ubi_open_volume - open UBI volume. * @ubi_num: UBI device number * @vol_id: volume ID * @mode: open mode * * The @mode parameter specifies if the volume should be opened in read-only * mode, read-write mode, or exclusive mode. The exclusive mode guarantees that * nobody else will be able to open this volume. UBI allows to have many volume * readers and one writer at a time. * * If a static volume is being opened for the first time since boot, it will be * checked by this function, which means it will be fully read and the CRC * checksum of each logical eraseblock will be checked. * * This function returns volume descriptor in case of success and a negative * error code in case of failure. */ struct ubi_volume_desc *ubi_open_volume(int ubi_num, int vol_id, int mode) { int err; struct ubi_volume_desc *desc; struct ubi_device *ubi; struct ubi_volume *vol; dbg_gen("open device %d, volume %d, mode %d", ubi_num, vol_id, mode); if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES) return ERR_PTR(-EINVAL); if (mode != UBI_READONLY && mode != UBI_READWRITE && mode != UBI_EXCLUSIVE) return ERR_PTR(-EINVAL); /* * First of all, we have to get the UBI device to prevent its removal. */ ubi = ubi_get_device(ubi_num); if (!ubi) return ERR_PTR(-ENODEV); if (vol_id < 0 || vol_id >= ubi->vtbl_slots) { err = -EINVAL; goto out_put_ubi; } desc = kmalloc(sizeof(struct ubi_volume_desc), GFP_KERNEL); if (!desc) { err = -ENOMEM; goto out_put_ubi; } err = -ENODEV; if (!try_module_get(THIS_MODULE)) goto out_free; spin_lock(&ubi->volumes_lock); vol = ubi->volumes[vol_id]; if (!vol) goto out_unlock; err = -EBUSY; switch (mode) { case UBI_READONLY: if (vol->exclusive) goto out_unlock; vol->readers += 1; break; case UBI_READWRITE: if (vol->exclusive || vol->writers > 0) goto out_unlock; vol->writers += 1; break; case UBI_EXCLUSIVE: if (vol->exclusive || vol->writers || vol->readers) goto out_unlock; vol->exclusive = 1; break; } get_device(&vol->dev); vol->ref_count += 1; spin_unlock(&ubi->volumes_lock); desc->vol = vol; desc->mode = mode; mutex_lock(&ubi->ckvol_mutex); if (!vol->checked) { /* This is the first open - check the volume */ err = ubi_check_volume(ubi, vol_id); if (err < 0) { mutex_unlock(&ubi->ckvol_mutex); ubi_close_volume(desc); return ERR_PTR(err); } if (err == 1) { ubi_warn("volume %d on UBI device %d is corrupted", vol_id, ubi->ubi_num); vol->corrupted = 1; } vol->checked = 1; } mutex_unlock(&ubi->ckvol_mutex); return desc; out_unlock: spin_unlock(&ubi->volumes_lock); module_put(THIS_MODULE); out_free: kfree(desc); out_put_ubi: ubi_put_device(ubi); dbg_err("cannot open device %d, volume %d, error %d", ubi_num, vol_id, err); return ERR_PTR(err); }
static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) { int err; union ubifs_key key; struct inode *inode = NULL; struct ubifs_dent_node *dent; struct ubifs_info *c = dir->i_sb->s_fs_info; dbg_gen("'%.*s' in dir ino %lu", dentry->d_name.len, dentry->d_name.name, dir->i_ino); if (dentry->d_name.len > UBIFS_MAX_NLEN) return ERR_PTR(-ENAMETOOLONG); dent = kmalloc(UBIFS_MAX_DENT_NODE_SZ, GFP_NOFS); if (!dent) return ERR_PTR(-ENOMEM); dent_key_init(c, &key, dir->i_ino, &dentry->d_name); err = ubifs_tnc_lookup_nm(c, &key, dent, &dentry->d_name); if (err) { if (err == -ENOENT) { dbg_gen("not found"); goto done; } goto out; } if (dbg_check_name(c, dent, &dentry->d_name)) { err = -EINVAL; goto out; } inode = ubifs_iget(dir->i_sb, le64_to_cpu(dent->inum)); if (IS_ERR(inode)) { /* * This should not happen. Probably the file-system needs * checking. */ err = PTR_ERR(inode); ubifs_err("dead directory entry '%.*s', error %d", dentry->d_name.len, dentry->d_name.name, err); ubifs_ro_mode(c, err); goto out; } done: kfree(dent); /* * Note, d_splice_alias() would be required instead if we supported * NFS. */ d_add(dentry, inode); return NULL; out: kfree(dent); return ERR_PTR(err); }
/** * ubi_resize_volume - re-size volume. * @desc: volume descriptor * @reserved_pebs: new size in physical eraseblocks * * This function re-sizes the volume and returns zero in case of success, and a * negative error code in case of failure. The caller has to have the * @ubi->device_mutex locked. */ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs) { int i, err, pebs, *new_mapping; struct ubi_volume *vol = desc->vol; struct ubi_device *ubi = vol->ubi; struct ubi_vtbl_record vtbl_rec; int vol_id = vol->vol_id; if (ubi->ro_mode) return -EROFS; dbg_gen("re-size device %d, volume %d to from %d to %d PEBs", ubi->ubi_num, vol_id, vol->reserved_pebs, reserved_pebs); if (vol->vol_type == UBI_STATIC_VOLUME && reserved_pebs < vol->used_ebs) { ubi_err(ubi, "too small size %d, %d LEBs contain data", reserved_pebs, vol->used_ebs); return -EINVAL; } /* If the size is the same, we have nothing to do */ if (reserved_pebs == vol->reserved_pebs) return 0; new_mapping = kmalloc(reserved_pebs * sizeof(int), GFP_KERNEL); if (!new_mapping) return -ENOMEM; for (i = 0; i < reserved_pebs; i++) new_mapping[i] = UBI_LEB_UNMAPPED; if (vol->ref_count > 1) { err = -EBUSY; goto out_free; } /* Reserve physical eraseblocks */ pebs = reserved_pebs - vol->reserved_pebs; if (pebs > 0) { if (pebs > ubi->avail_pebs) { ubi_err(ubi, "not enough PEBs: requested %d, available %d", pebs, ubi->avail_pebs); if (ubi->corr_peb_count) ubi_err(ubi, "%d PEBs are corrupted and not used", ubi->corr_peb_count); err = -ENOSPC; goto out_free; } ubi->avail_pebs -= pebs; ubi->rsvd_pebs += pebs; for (i = 0; i < vol->reserved_pebs; i++) new_mapping[i] = vol->eba_tbl[i]; kfree(vol->eba_tbl); vol->eba_tbl = new_mapping; } /* Change volume table record */ vtbl_rec = ubi->vtbl[vol_id]; vtbl_rec.reserved_pebs = cpu_to_be32(reserved_pebs); err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec); if (err) goto out_acc; if (pebs < 0) { for (i = 0; i < -pebs; i++) { err = ubi_eba_unmap_leb(ubi, vol, reserved_pebs + i); if (err) goto out_acc; } ubi->rsvd_pebs += pebs; ubi->avail_pebs -= pebs; ubi_update_reserved(ubi); for (i = 0; i < reserved_pebs; i++) new_mapping[i] = vol->eba_tbl[i]; kfree(vol->eba_tbl); vol->eba_tbl = new_mapping; } vol->reserved_pebs = reserved_pebs; if (vol->vol_type == UBI_DYNAMIC_VOLUME) { vol->used_ebs = reserved_pebs; vol->last_eb_bytes = vol->usable_leb_size; vol->used_bytes = (long long)vol->used_ebs * vol->usable_leb_size; } ubi_volume_notify(ubi, vol, UBI_VOLUME_RESIZED); self_check_volumes(ubi); return err; out_acc: if (pebs > 0) { ubi->rsvd_pebs -= pebs; ubi->avail_pebs += pebs; } out_free: kfree(new_mapping); return err; }
/** * ubi_create_volume - create volume. * @ubi: UBI device description object * @req: volume creation request * * This function creates volume described by @req. If @req->vol_id id * %UBI_VOL_NUM_AUTO, this function automatically assign ID to the new volume * and saves it in @req->vol_id. Returns zero in case of success and a negative * error code in case of failure. Note, the caller has to have the * @ubi->device_mutex locked. */ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) { int i, err, vol_id = req->vol_id, do_free = 1; struct ubi_volume *vol; struct ubi_vtbl_record vtbl_rec; if (ubi->ro_mode) return -EROFS; vol = kzalloc(sizeof(struct ubi_volume), GFP_KERNEL); if (!vol) return -ENOMEM; if (vol_id == UBI_VOL_NUM_AUTO) { /* Find unused volume ID */ dbg_gen("search for vacant volume ID"); for (i = 0; i < ubi->vtbl_slots; i++) if (!ubi->volumes[i]) { vol_id = i; break; } if (vol_id == UBI_VOL_NUM_AUTO) { ubi_err(ubi, "out of volume IDs"); err = -ENFILE; goto out_unlock; } req->vol_id = vol_id; } dbg_gen("create device %d, volume %d, %llu bytes, type %d, name %s", ubi->ubi_num, vol_id, (unsigned long long)req->bytes, (int)req->vol_type, req->name); /* Ensure that this volume does not exist */ err = -EEXIST; if (ubi->volumes[vol_id]) { ubi_err(ubi, "volume %d already exists", vol_id); goto out_unlock; } /* Ensure that the name is unique */ for (i = 0; i < ubi->vtbl_slots; i++) if (ubi->volumes[i] && ubi->volumes[i]->name_len == req->name_len && !strcmp(ubi->volumes[i]->name, req->name)) { ubi_err(ubi, "volume \"%s\" exists (ID %d)", req->name, i); goto out_unlock; } /* Calculate how many eraseblocks are requested */ vol->usable_leb_size = ubi->leb_size - ubi->leb_size % req->alignment; vol->reserved_pebs = div_u64(req->bytes + vol->usable_leb_size - 1, vol->usable_leb_size); /* Reserve physical eraseblocks */ if (vol->reserved_pebs > ubi->avail_pebs) { ubi_err(ubi, "not enough PEBs, only %d available", ubi->avail_pebs); if (ubi->corr_peb_count) ubi_err(ubi, "%d PEBs are corrupted and not used", ubi->corr_peb_count); err = -ENOSPC; goto out_unlock; } ubi->avail_pebs -= vol->reserved_pebs; ubi->rsvd_pebs += vol->reserved_pebs; vol->vol_id = vol_id; vol->alignment = req->alignment; vol->data_pad = ubi->leb_size % vol->alignment; vol->vol_type = req->vol_type; vol->name_len = req->name_len; memcpy(vol->name, req->name, vol->name_len); vol->ubi = ubi; /* * Finish all pending erases because there may be some LEBs belonging * to the same volume ID. */ err = ubi_wl_flush(ubi, vol_id, UBI_ALL); if (err) goto out_acc; vol->eba_tbl = kmalloc(vol->reserved_pebs * sizeof(int), GFP_KERNEL); if (!vol->eba_tbl) { err = -ENOMEM; goto out_acc; } for (i = 0; i < vol->reserved_pebs; i++) vol->eba_tbl[i] = UBI_LEB_UNMAPPED; if (vol->vol_type == UBI_DYNAMIC_VOLUME) { vol->used_ebs = vol->reserved_pebs; vol->last_eb_bytes = vol->usable_leb_size; vol->used_bytes = (long long)vol->used_ebs * vol->usable_leb_size; } else { vol->used_ebs = div_u64_rem(vol->used_bytes, vol->usable_leb_size, &vol->last_eb_bytes); if (vol->last_eb_bytes != 0) vol->used_ebs += 1; else vol->last_eb_bytes = vol->usable_leb_size; } sprintf(vol->dev.name, "%s.%s", dev_name(&ubi->dev), vol->name); vol->dev.id = DEVICE_ID_SINGLE; vol->dev.parent = &ubi->dev; err = register_device(&vol->dev); if (err) goto out_acc; /* Register character device for the volume */ err = ubi_volume_cdev_add(ubi, vol); if (err) { ubi_err(ubi, "cannot add character device"); goto out_mapping; } /* Fill volume table record */ memset(&vtbl_rec, 0, sizeof(struct ubi_vtbl_record)); vtbl_rec.reserved_pebs = cpu_to_be32(vol->reserved_pebs); vtbl_rec.alignment = cpu_to_be32(vol->alignment); vtbl_rec.data_pad = cpu_to_be32(vol->data_pad); vtbl_rec.name_len = cpu_to_be16(vol->name_len); if (vol->vol_type == UBI_DYNAMIC_VOLUME) vtbl_rec.vol_type = UBI_VID_DYNAMIC; else vtbl_rec.vol_type = UBI_VID_STATIC; memcpy(vtbl_rec.name, vol->name, vol->name_len); err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec); if (err) goto out_sysfs; ubi->volumes[vol_id] = vol; ubi->vol_count += 1; ubi_volume_notify(ubi, vol, UBI_VOLUME_ADDED); self_check_volumes(ubi); return err; out_sysfs: /* * We have registered our device, we should not free the volume * description object in this function in case of an error - it is * freed by the release function. * * Get device reference to prevent the release function from being * called just after sysfs has been closed. */ do_free = 0; out_mapping: if (do_free) kfree(vol->eba_tbl); unregister_device(&vol->dev); out_acc: ubi->rsvd_pebs -= vol->reserved_pebs; ubi->avail_pebs += vol->reserved_pebs; out_unlock: if (do_free) kfree(vol); ubi_err(ubi, "cannot create volume %d, error %d", vol_id, err); return err; }
static int do_readpage(struct ubifs_info *c, struct inode *inode, struct page *page) { void *addr; int err = 0, i; unsigned int block, beyond; struct ubifs_data_node *dn; loff_t i_size = inode->i_size; dbg_gen("ino %lu, pg %lu, i_size %lld", inode->i_ino, page->index, i_size); addr = kmap(page); block = page->index << UBIFS_BLOCKS_PER_PAGE_SHIFT; beyond = (i_size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT; if (block >= beyond) { /* Reading beyond inode */ memset(addr, 0, PAGE_CACHE_SIZE); goto out; } dn = kmalloc(UBIFS_MAX_DATA_NODE_SZ, GFP_NOFS); if (!dn) { err = -ENOMEM; goto error; } i = 0; while (1) { int ret; if (block >= beyond) { /* Reading beyond inode */ err = -ENOENT; memset(addr, 0, UBIFS_BLOCK_SIZE); } else { ret = read_block(inode, addr, block, dn); if (ret) { err = ret; if (err != -ENOENT) break; } else if (block + 1 == beyond) { int dlen = le32_to_cpu(dn->size); int ilen = i_size & (UBIFS_BLOCK_SIZE - 1); if (ilen && ilen < dlen) memset(addr + ilen, 0, dlen - ilen); } } if (++i >= UBIFS_BLOCKS_PER_PAGE) break; block += 1; addr += UBIFS_BLOCK_SIZE; } if (err) { if (err == -ENOENT) { /* Not found, so it must be a hole */ dbg_gen("hole"); goto out_free; } ubifs_err("cannot read page %lu of inode %lu, error %d", page->index, inode->i_ino, err); goto error; } out_free: kfree(dn); out: return 0; error: kfree(dn); return err; }
static int ubifs_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool excl) { struct inode *inode; struct ubifs_info *c = dir->i_sb->s_fs_info; int err, sz_change = CALC_DENT_SIZE(dentry->d_name.len); struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1, .dirtied_ino = 1 }; struct ubifs_inode *dir_ui = ubifs_inode(dir); /* * Budget request settings: new inode, new direntry, changing the * parent directory inode. */ dbg_gen("dent '%pd', mode %#hx in dir ino %lu", dentry, mode, dir->i_ino); err = ubifs_budget_space(c, &req); if (err) return err; inode = ubifs_new_inode(c, dir, mode); if (IS_ERR(inode)) { err = PTR_ERR(inode); goto out_budg; } err = ubifs_init_security(dir, inode, &dentry->d_name); if (err) goto out_inode; mutex_lock(&dir_ui->ui_mutex); dir->i_size += sz_change; dir_ui->ui_size = dir->i_size; dir->i_mtime = dir->i_ctime = inode->i_ctime; err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 0, 0); if (err) goto out_cancel; mutex_unlock(&dir_ui->ui_mutex); ubifs_release_budget(c, &req); insert_inode_hash(inode); d_instantiate(dentry, inode); return 0; out_cancel: dir->i_size -= sz_change; dir_ui->ui_size = dir->i_size; mutex_unlock(&dir_ui->ui_mutex); out_inode: make_bad_inode(inode); iput(inode); out_budg: ubifs_release_budget(c, &req); ubifs_err(c, "cannot create regular file, error %d", err); return err; } /** * vfs_dent_type - get VFS directory entry type. * @type: UBIFS directory entry type * * This function converts UBIFS directory entry type into VFS directory entry * type. */ static unsigned int vfs_dent_type(uint8_t type) { switch (type) { case UBIFS_ITYPE_REG: return DT_REG; case UBIFS_ITYPE_DIR: return DT_DIR; case UBIFS_ITYPE_LNK: return DT_LNK; case UBIFS_ITYPE_BLK: return DT_BLK; case UBIFS_ITYPE_CHR: return DT_CHR; case UBIFS_ITYPE_FIFO: return DT_FIFO; case UBIFS_ITYPE_SOCK: return DT_SOCK; default: BUG(); } return 0; } /* * The classical Unix view for directory is that it is a linear array of * (name, inode number) entries. Linux/VFS assumes this model as well. * Particularly, 'readdir()' call wants us to return a directory entry offset * which later may be used to continue 'readdir()'ing the directory or to * 'seek()' to that specific direntry. Obviously UBIFS does not really fit this * model because directory entries are identified by keys, which may collide. * * UBIFS uses directory entry hash value for directory offsets, so * 'seekdir()'/'telldir()' may not always work because of possible key * collisions. But UBIFS guarantees that consecutive 'readdir()' calls work * properly by means of saving full directory entry name in the private field * of the file description object. * * This means that UBIFS cannot support NFS which requires full * 'seekdir()'/'telldir()' support. */ static int ubifs_readdir(struct file *file, struct dir_context *ctx) { int err; struct qstr nm; union ubifs_key key; struct ubifs_dent_node *dent; struct inode *dir = file_inode(file); struct ubifs_info *c = dir->i_sb->s_fs_info; dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, ctx->pos); if (ctx->pos > UBIFS_S_KEY_HASH_MASK || ctx->pos == 2) /* * The directory was seek'ed to a senseless position or there * are no more entries. */ return 0; if (file->f_version == 0) { /* * The file was seek'ed, which means that @file->private_data * is now invalid. This may also be just the first * 'ubifs_readdir()' invocation, in which case * @file->private_data is NULL, and the below code is * basically a no-op. */ kfree(file->private_data); file->private_data = NULL; } /* * 'generic_file_llseek()' unconditionally sets @file->f_version to * zero, and we use this for detecting whether the file was seek'ed. */ file->f_version = 1; /* File positions 0 and 1 correspond to "." and ".." */ if (ctx->pos < 2) { ubifs_assert(!file->private_data); if (!dir_emit_dots(file, ctx)) return 0; /* Find the first entry in TNC and save it */ lowest_dent_key(c, &key, dir->i_ino); nm.name = NULL; dent = ubifs_tnc_next_ent(c, &key, &nm); if (IS_ERR(dent)) { err = PTR_ERR(dent); goto out; } ctx->pos = key_hash_flash(c, &dent->key); file->private_data = dent; } dent = file->private_data; if (!dent) { /* * The directory was seek'ed to and is now readdir'ed. * Find the entry corresponding to @ctx->pos or the closest one. */ dent_key_init_hash(c, &key, dir->i_ino, ctx->pos); nm.name = NULL; dent = ubifs_tnc_next_ent(c, &key, &nm); if (IS_ERR(dent)) { err = PTR_ERR(dent); goto out; } ctx->pos = key_hash_flash(c, &dent->key); file->private_data = dent; } while (1) { dbg_gen("feed '%s', ino %llu, new f_pos %#x", dent->name, (unsigned long long)le64_to_cpu(dent->inum), key_hash_flash(c, &dent->key)); ubifs_assert(le64_to_cpu(dent->ch.sqnum) > ubifs_inode(dir)->creat_sqnum); nm.len = le16_to_cpu(dent->nlen); if (!dir_emit(ctx, dent->name, nm.len, le64_to_cpu(dent->inum), vfs_dent_type(dent->type))) return 0; /* Switch to the next entry */ key_read(c, &dent->key, &key); nm.name = dent->name; dent = ubifs_tnc_next_ent(c, &key, &nm); if (IS_ERR(dent)) { err = PTR_ERR(dent); goto out; } kfree(file->private_data); ctx->pos = key_hash_flash(c, &dent->key); file->private_data = dent; cond_resched(); } out: if (err != -ENOENT) { ubifs_err(c, "cannot find next direntry, error %d", err); return err; } kfree(file->private_data); file->private_data = NULL; /* 2 is a special value indicating that there are no more direntries */ ctx->pos = 2; return 0; }
static int ubifs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) { struct ubifs_info *c = dir->i_sb->s_fs_info; struct inode *inode = d_inode(old_dentry); struct ubifs_inode *ui = ubifs_inode(inode); struct ubifs_inode *dir_ui = ubifs_inode(dir); int err, sz_change = CALC_DENT_SIZE(dentry->d_name.len); struct ubifs_budget_req req = { .new_dent = 1, .dirtied_ino = 2, .dirtied_ino_d = ALIGN(ui->data_len, 8) }; /* * Budget request settings: new direntry, changing the target inode, * changing the parent inode. */ dbg_gen("dent '%pd' to ino %lu (nlink %d) in dir ino %lu", dentry, inode->i_ino, inode->i_nlink, dir->i_ino); ubifs_assert(mutex_is_locked(&dir->i_mutex)); ubifs_assert(mutex_is_locked(&inode->i_mutex)); err = dbg_check_synced_i_size(c, inode); if (err) return err; err = ubifs_budget_space(c, &req); if (err) return err; lock_2_inodes(dir, inode); inc_nlink(inode); ihold(inode); inode->i_ctime = ubifs_current_time(inode); dir->i_size += sz_change; dir_ui->ui_size = dir->i_size; dir->i_mtime = dir->i_ctime = inode->i_ctime; err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 0, 0); if (err) goto out_cancel; unlock_2_inodes(dir, inode); ubifs_release_budget(c, &req); d_instantiate(dentry, inode); return 0; out_cancel: dir->i_size -= sz_change; dir_ui->ui_size = dir->i_size; drop_nlink(inode); unlock_2_inodes(dir, inode); ubifs_release_budget(c, &req); iput(inode); return err; } static int ubifs_unlink(struct inode *dir, struct dentry *dentry) { struct ubifs_info *c = dir->i_sb->s_fs_info; struct inode *inode = d_inode(dentry); struct ubifs_inode *dir_ui = ubifs_inode(dir); int sz_change = CALC_DENT_SIZE(dentry->d_name.len); int err, budgeted = 1; struct ubifs_budget_req req = { .mod_dent = 1, .dirtied_ino = 2 }; unsigned int saved_nlink = inode->i_nlink; /* * Budget request settings: deletion direntry, deletion inode (+1 for * @dirtied_ino), changing the parent directory inode. If budgeting * fails, go ahead anyway because we have extra space reserved for * deletions. */ dbg_gen("dent '%pd' from ino %lu (nlink %d) in dir ino %lu", dentry, inode->i_ino, inode->i_nlink, dir->i_ino); ubifs_assert(mutex_is_locked(&dir->i_mutex)); ubifs_assert(mutex_is_locked(&inode->i_mutex)); err = dbg_check_synced_i_size(c, inode); if (err) return err; err = ubifs_budget_space(c, &req); if (err) { if (err != -ENOSPC) return err; budgeted = 0; } lock_2_inodes(dir, inode); inode->i_ctime = ubifs_current_time(dir); drop_nlink(inode); dir->i_size -= sz_change; dir_ui->ui_size = dir->i_size; dir->i_mtime = dir->i_ctime = inode->i_ctime; err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 1, 0); if (err) goto out_cancel; unlock_2_inodes(dir, inode); if (budgeted) ubifs_release_budget(c, &req); else { /* We've deleted something - clean the "no space" flags */ c->bi.nospace = c->bi.nospace_rp = 0; smp_wmb(); } return 0; out_cancel: dir->i_size += sz_change; dir_ui->ui_size = dir->i_size; set_nlink(inode, saved_nlink); unlock_2_inodes(dir, inode); if (budgeted) ubifs_release_budget(c, &req); return err; } /** * check_dir_empty - check if a directory is empty or not. * @c: UBIFS file-system description object * @dir: VFS inode object of the directory to check * * This function checks if directory @dir is empty. Returns zero if the * directory is empty, %-ENOTEMPTY if it is not, and other negative error codes * in case of of errors. */ static int check_dir_empty(struct ubifs_info *c, struct inode *dir) { struct qstr nm = { .name = NULL }; struct ubifs_dent_node *dent; union ubifs_key key; int err; lowest_dent_key(c, &key, dir->i_ino); dent = ubifs_tnc_next_ent(c, &key, &nm); if (IS_ERR(dent)) { err = PTR_ERR(dent); if (err == -ENOENT) err = 0; } else { kfree(dent); err = -ENOTEMPTY; } return err; } static int ubifs_rmdir(struct inode *dir, struct dentry *dentry) { struct ubifs_info *c = dir->i_sb->s_fs_info; struct inode *inode = d_inode(dentry); int sz_change = CALC_DENT_SIZE(dentry->d_name.len); int err, budgeted = 1; struct ubifs_inode *dir_ui = ubifs_inode(dir); struct ubifs_budget_req req = { .mod_dent = 1, .dirtied_ino = 2 }; /* * Budget request settings: deletion direntry, deletion inode and * changing the parent inode. If budgeting fails, go ahead anyway * because we have extra space reserved for deletions. */ dbg_gen("directory '%pd', ino %lu in dir ino %lu", dentry, inode->i_ino, dir->i_ino); ubifs_assert(mutex_is_locked(&dir->i_mutex)); ubifs_assert(mutex_is_locked(&inode->i_mutex)); err = check_dir_empty(c, d_inode(dentry)); if (err) return err; err = ubifs_budget_space(c, &req); if (err) { if (err != -ENOSPC) return err; budgeted = 0; } lock_2_inodes(dir, inode); inode->i_ctime = ubifs_current_time(dir); clear_nlink(inode); drop_nlink(dir); dir->i_size -= sz_change; dir_ui->ui_size = dir->i_size; dir->i_mtime = dir->i_ctime = inode->i_ctime; err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 1, 0); if (err) goto out_cancel; unlock_2_inodes(dir, inode); if (budgeted) ubifs_release_budget(c, &req); else { /* We've deleted something - clean the "no space" flags */ c->bi.nospace = c->bi.nospace_rp = 0; smp_wmb(); } return 0; out_cancel: dir->i_size += sz_change; dir_ui->ui_size = dir->i_size; inc_nlink(dir); set_nlink(inode, 2); unlock_2_inodes(dir, inode); if (budgeted) ubifs_release_budget(c, &req); return err; } static int ubifs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) { struct inode *inode; struct ubifs_inode *dir_ui = ubifs_inode(dir); struct ubifs_info *c = dir->i_sb->s_fs_info; int err, sz_change = CALC_DENT_SIZE(dentry->d_name.len); struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1 }; /* * Budget request settings: new inode, new direntry and changing parent * directory inode. */ dbg_gen("dent '%pd', mode %#hx in dir ino %lu", dentry, mode, dir->i_ino); err = ubifs_budget_space(c, &req); if (err) return err; inode = ubifs_new_inode(c, dir, S_IFDIR | mode); if (IS_ERR(inode)) { err = PTR_ERR(inode); goto out_budg; } err = ubifs_init_security(dir, inode, &dentry->d_name); if (err) goto out_inode; mutex_lock(&dir_ui->ui_mutex); insert_inode_hash(inode); inc_nlink(inode); inc_nlink(dir); dir->i_size += sz_change; dir_ui->ui_size = dir->i_size; dir->i_mtime = dir->i_ctime = inode->i_ctime; err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 0, 0); if (err) { ubifs_err(c, "cannot create directory, error %d", err); goto out_cancel; } mutex_unlock(&dir_ui->ui_mutex); ubifs_release_budget(c, &req); d_instantiate(dentry, inode); return 0; out_cancel: dir->i_size -= sz_change; dir_ui->ui_size = dir->i_size; drop_nlink(dir); mutex_unlock(&dir_ui->ui_mutex); out_inode: make_bad_inode(inode); iput(inode); out_budg: ubifs_release_budget(c, &req); return err; } static int ubifs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t rdev) { struct inode *inode; struct ubifs_inode *ui; struct ubifs_inode *dir_ui = ubifs_inode(dir); struct ubifs_info *c = dir->i_sb->s_fs_info; union ubifs_dev_desc *dev = NULL; int sz_change = CALC_DENT_SIZE(dentry->d_name.len); int err, devlen = 0; struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1, .new_ino_d = ALIGN(devlen, 8), .dirtied_ino = 1 }; /* * Budget request settings: new inode, new direntry and changing parent * directory inode. */ dbg_gen("dent '%pd' in dir ino %lu", dentry, dir->i_ino); if (!new_valid_dev(rdev)) return -EINVAL; if (S_ISBLK(mode) || S_ISCHR(mode)) { dev = kmalloc(sizeof(union ubifs_dev_desc), GFP_NOFS); if (!dev) return -ENOMEM; devlen = ubifs_encode_dev(dev, rdev); } err = ubifs_budget_space(c, &req); if (err) { kfree(dev); return err; } inode = ubifs_new_inode(c, dir, mode); if (IS_ERR(inode)) { kfree(dev); err = PTR_ERR(inode); goto out_budg; } init_special_inode(inode, inode->i_mode, rdev); inode->i_size = ubifs_inode(inode)->ui_size = devlen; ui = ubifs_inode(inode); ui->data = dev; ui->data_len = devlen; err = ubifs_init_security(dir, inode, &dentry->d_name); if (err) goto out_inode; mutex_lock(&dir_ui->ui_mutex); dir->i_size += sz_change; dir_ui->ui_size = dir->i_size; dir->i_mtime = dir->i_ctime = inode->i_ctime; err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 0, 0); if (err) goto out_cancel; mutex_unlock(&dir_ui->ui_mutex); ubifs_release_budget(c, &req); insert_inode_hash(inode); d_instantiate(dentry, inode); return 0; out_cancel: dir->i_size -= sz_change; dir_ui->ui_size = dir->i_size; mutex_unlock(&dir_ui->ui_mutex); out_inode: make_bad_inode(inode); iput(inode); out_budg: ubifs_release_budget(c, &req); return err; } static int ubifs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) { struct inode *inode; struct ubifs_inode *ui; struct ubifs_inode *dir_ui = ubifs_inode(dir); struct ubifs_info *c = dir->i_sb->s_fs_info; int err, len = strlen(symname); int sz_change = CALC_DENT_SIZE(dentry->d_name.len); struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1, .new_ino_d = ALIGN(len, 8), .dirtied_ino = 1 }; /* * Budget request settings: new inode, new direntry and changing parent * directory inode. */ dbg_gen("dent '%pd', target '%s' in dir ino %lu", dentry, symname, dir->i_ino); if (len > UBIFS_MAX_INO_DATA) return -ENAMETOOLONG; err = ubifs_budget_space(c, &req); if (err) return err; inode = ubifs_new_inode(c, dir, S_IFLNK | S_IRWXUGO); if (IS_ERR(inode)) { err = PTR_ERR(inode); goto out_budg; } ui = ubifs_inode(inode); ui->data = kmalloc(len + 1, GFP_NOFS); if (!ui->data) { err = -ENOMEM; goto out_inode; } memcpy(ui->data, symname, len); ((char *)ui->data)[len] = '\0'; inode->i_link = ui->data; /* * The terminating zero byte is not written to the flash media and it * is put just to make later in-memory string processing simpler. Thus, * data length is @len, not @len + %1. */ ui->data_len = len; inode->i_size = ubifs_inode(inode)->ui_size = len; err = ubifs_init_security(dir, inode, &dentry->d_name); if (err) goto out_inode; mutex_lock(&dir_ui->ui_mutex); dir->i_size += sz_change; dir_ui->ui_size = dir->i_size; dir->i_mtime = dir->i_ctime = inode->i_ctime; err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 0, 0); if (err) goto out_cancel; mutex_unlock(&dir_ui->ui_mutex); ubifs_release_budget(c, &req); insert_inode_hash(inode); d_instantiate(dentry, inode); return 0; out_cancel: dir->i_size -= sz_change; dir_ui->ui_size = dir->i_size; mutex_unlock(&dir_ui->ui_mutex); out_inode: make_bad_inode(inode); iput(inode); out_budg: ubifs_release_budget(c, &req); return err; } /** * lock_3_inodes - a wrapper for locking three UBIFS inodes. * @inode1: first inode * @inode2: second inode * @inode3: third inode * * This function is used for 'ubifs_rename()' and @inode1 may be the same as * @inode2 whereas @inode3 may be %NULL. * * We do not implement any tricks to guarantee strict lock ordering, because * VFS has already done it for us on the @i_mutex. So this is just a simple * wrapper function. */ static void lock_3_inodes(struct inode *inode1, struct inode *inode2, struct inode *inode3) { mutex_lock_nested(&ubifs_inode(inode1)->ui_mutex, WB_MUTEX_1); if (inode2 != inode1) mutex_lock_nested(&ubifs_inode(inode2)->ui_mutex, WB_MUTEX_2); if (inode3) mutex_lock_nested(&ubifs_inode(inode3)->ui_mutex, WB_MUTEX_3); } /** * unlock_3_inodes - a wrapper for unlocking three UBIFS inodes for rename. * @inode1: first inode * @inode2: second inode * @inode3: third inode */ static void unlock_3_inodes(struct inode *inode1, struct inode *inode2, struct inode *inode3) { if (inode3) mutex_unlock(&ubifs_inode(inode3)->ui_mutex); if (inode1 != inode2) mutex_unlock(&ubifs_inode(inode2)->ui_mutex); mutex_unlock(&ubifs_inode(inode1)->ui_mutex); } static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry) { struct ubifs_info *c = old_dir->i_sb->s_fs_info; struct inode *old_inode = d_inode(old_dentry); struct inode *new_inode = d_inode(new_dentry); struct ubifs_inode *old_inode_ui = ubifs_inode(old_inode); int err, release, sync = 0, move = (new_dir != old_dir); int is_dir = S_ISDIR(old_inode->i_mode); int unlink = !!new_inode; int new_sz = CALC_DENT_SIZE(new_dentry->d_name.len); int old_sz = CALC_DENT_SIZE(old_dentry->d_name.len); struct ubifs_budget_req req = { .new_dent = 1, .mod_dent = 1, .dirtied_ino = 3 }; struct ubifs_budget_req ino_req = { .dirtied_ino = 1, .dirtied_ino_d = ALIGN(old_inode_ui->data_len, 8) }; struct timespec time; unsigned int uninitialized_var(saved_nlink); /* * Budget request settings: deletion direntry, new direntry, removing * the old inode, and changing old and new parent directory inodes. * * However, this operation also marks the target inode as dirty and * does not write it, so we allocate budget for the target inode * separately. */ dbg_gen("dent '%pd' ino %lu in dir ino %lu to dent '%pd' in dir ino %lu", old_dentry, old_inode->i_ino, old_dir->i_ino, new_dentry, new_dir->i_ino); ubifs_assert(mutex_is_locked(&old_dir->i_mutex)); ubifs_assert(mutex_is_locked(&new_dir->i_mutex)); if (unlink) ubifs_assert(mutex_is_locked(&new_inode->i_mutex)); if (unlink && is_dir) { err = check_dir_empty(c, new_inode); if (err) return err; } err = ubifs_budget_space(c, &req); if (err) return err; err = ubifs_budget_space(c, &ino_req); if (err) { ubifs_release_budget(c, &req); return err; } lock_3_inodes(old_dir, new_dir, new_inode); /* * Like most other Unix systems, set the @i_ctime for inodes on a * rename. */ time = ubifs_current_time(old_dir); old_inode->i_ctime = time; /* We must adjust parent link count when renaming directories */ if (is_dir) { if (move) { /* * @old_dir loses a link because we are moving * @old_inode to a different directory. */ drop_nlink(old_dir); /* * @new_dir only gains a link if we are not also * overwriting an existing directory. */ if (!unlink) inc_nlink(new_dir); } else { /* * @old_inode is not moving to a different directory, * but @old_dir still loses a link if we are * overwriting an existing directory. */ if (unlink) drop_nlink(old_dir); } } old_dir->i_size -= old_sz; ubifs_inode(old_dir)->ui_size = old_dir->i_size; old_dir->i_mtime = old_dir->i_ctime = time; new_dir->i_mtime = new_dir->i_ctime = time; /* * And finally, if we unlinked a direntry which happened to have the * same name as the moved direntry, we have to decrement @i_nlink of * the unlinked inode and change its ctime. */ if (unlink) { /* * Directories cannot have hard-links, so if this is a * directory, just clear @i_nlink. */ saved_nlink = new_inode->i_nlink; if (is_dir) clear_nlink(new_inode); else drop_nlink(new_inode); new_inode->i_ctime = time; } else { new_dir->i_size += new_sz; ubifs_inode(new_dir)->ui_size = new_dir->i_size; } /* * Do not ask 'ubifs_jnl_rename()' to flush write-buffer if @old_inode * is dirty, because this will be done later on at the end of * 'ubifs_rename()'. */ if (IS_SYNC(old_inode)) { sync = IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir); if (unlink && IS_SYNC(new_inode)) sync = 1; } err = ubifs_jnl_rename(c, old_dir, old_dentry, new_dir, new_dentry, sync); if (err) goto out_cancel; unlock_3_inodes(old_dir, new_dir, new_inode); ubifs_release_budget(c, &req); mutex_lock(&old_inode_ui->ui_mutex); release = old_inode_ui->dirty; mark_inode_dirty_sync(old_inode); mutex_unlock(&old_inode_ui->ui_mutex); if (release) ubifs_release_budget(c, &ino_req); if (IS_SYNC(old_inode)) err = old_inode->i_sb->s_op->write_inode(old_inode, NULL); return err; out_cancel: if (unlink) { set_nlink(new_inode, saved_nlink); } else { new_dir->i_size -= new_sz; ubifs_inode(new_dir)->ui_size = new_dir->i_size; } old_dir->i_size += old_sz; ubifs_inode(old_dir)->ui_size = old_dir->i_size; if (is_dir) { if (move) { inc_nlink(old_dir); if (!unlink) drop_nlink(new_dir); } else { if (unlink) inc_nlink(old_dir); } } unlock_3_inodes(old_dir, new_dir, new_inode); ubifs_release_budget(c, &ino_req); ubifs_release_budget(c, &req); return err; } int ubifs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) { loff_t size; struct inode *inode = d_inode(dentry); struct ubifs_inode *ui = ubifs_inode(inode); mutex_lock(&ui->ui_mutex); generic_fillattr(inode, stat); stat->blksize = UBIFS_BLOCK_SIZE; stat->size = ui->ui_size; /* * Unfortunately, the 'stat()' system call was designed for block * device based file systems, and it is not appropriate for UBIFS, * because UBIFS does not have notion of "block". For example, it is * difficult to tell how many block a directory takes - it actually * takes less than 300 bytes, but we have to round it to block size, * which introduces large mistake. This makes utilities like 'du' to * report completely senseless numbers. This is the reason why UBIFS * goes the same way as JFFS2 - it reports zero blocks for everything * but regular files, which makes more sense than reporting completely * wrong sizes. */ if (S_ISREG(inode->i_mode)) { size = ui->xattr_size; size += stat->size; size = ALIGN(size, UBIFS_BLOCK_SIZE); /* * Note, user-space expects 512-byte blocks count irrespectively * of what was reported in @stat->size. */ stat->blocks = size >> 9; } else stat->blocks = 0; mutex_unlock(&ui->ui_mutex); return 0; } const struct inode_operations ubifs_dir_inode_operations = { .lookup = ubifs_lookup, .create = ubifs_create, .link = ubifs_link, .symlink = ubifs_symlink, .unlink = ubifs_unlink, .mkdir = ubifs_mkdir, .rmdir = ubifs_rmdir, .mknod = ubifs_mknod, .rename = ubifs_rename, .setattr = ubifs_setattr, .getattr = ubifs_getattr, .setxattr = ubifs_setxattr, .getxattr = ubifs_getxattr, .listxattr = ubifs_listxattr, .removexattr = ubifs_removexattr, }; const struct file_operations ubifs_dir_operations = { .llseek = generic_file_llseek, .release = ubifs_dir_release, .read = generic_read_dir, .iterate = ubifs_readdir, .fsync = ubifs_fsync, .unlocked_ioctl = ubifs_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = ubifs_compat_ioctl, #endif };
static int setflags(struct inode *inode, int flags) { int oldflags, err, release; struct ubifs_inode *ui = ubifs_inode(inode); struct ubifs_info *c = inode->i_sb->s_fs_info; struct ubifs_budget_req req = { .dirtied_ino = 1, .dirtied_ino_d = ui->data_len }; err = ubifs_budget_space(c, &req); if (err) return err; /* * The IMMUTABLE and APPEND_ONLY flags can only be changed by * the relevant capability. */ mutex_lock(&ui->ui_mutex); oldflags = ubifs2ioctl(ui->flags); if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) { if (!capable(CAP_LINUX_IMMUTABLE)) { err = -EPERM; goto out_unlock; } } ui->flags = ioctl2ubifs(flags); ubifs_set_inode_flags(inode); inode->i_ctime = ubifs_current_time(inode); release = ui->dirty; mark_inode_dirty_sync(inode); mutex_unlock(&ui->ui_mutex); if (release) ubifs_release_budget(c, &req); if (IS_SYNC(inode)) err = write_inode_now(inode, 1); return err; out_unlock: ubifs_err("can't modify inode %lu attributes", inode->i_ino); mutex_unlock(&ui->ui_mutex); ubifs_release_budget(c, &req); return err; } long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int flags, err; struct inode *inode = file->f_path.dentry->d_inode; switch (cmd) { case FS_IOC_GETFLAGS: flags = ubifs2ioctl(ubifs_inode(inode)->flags); dbg_gen("get flags: %#x, i_flags %#x", flags, inode->i_flags); return put_user(flags, (int __user *) arg); case FS_IOC_SETFLAGS: { if (IS_RDONLY(inode)) return -EROFS; if (!inode_owner_or_capable(inode)) return -EACCES; if (get_user(flags, (int __user *) arg)) return -EFAULT; if (!S_ISDIR(inode->i_mode)) flags &= ~FS_DIRSYNC_FL; /* * Make sure the file-system is read-write and make sure it * will not become read-only while we are changing the flags. */ err = mnt_want_write(file->f_path.mnt); if (err) return err; dbg_gen("set flags: %#x, i_flags %#x", flags, inode->i_flags); err = setflags(inode, flags); mnt_drop_write(file->f_path.mnt); return err; } default: return -ENOTTY; } }
/** * ubi_io_read - read data from a physical eraseblock. * @ubi: UBI device description object * @buf: buffer where to store the read data * @pnum: physical eraseblock number to read from * @offset: offset within the physical eraseblock from where to read * @len: how many bytes to read * * This function reads data from offset @offset of physical eraseblock @pnum * and stores the read data in the @buf buffer. The following return codes are * possible: * * o %0 if all the requested data were successfully read; * o %UBI_IO_BITFLIPS if all the requested data were successfully read, but * correctable bit-flips were detected; this is harmless but may indicate * that this eraseblock may become bad soon (but do not have to); * o %-EBADMSG if the MTD subsystem reported about data integrity problems, for * example it can be an ECC error in case of NAND; this most probably means * that the data is corrupted; * o %-EIO if some I/O error occurred; * o other negative error codes in case of other errors. */ int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset, int len) { int err, retries = 0; size_t read; loff_t addr; dbg_io("read %d bytes from PEB %d:%d", len, pnum, offset); ubi_assert(pnum >= 0 && pnum < ubi->peb_count); ubi_assert(offset >= 0 && offset + len <= ubi->peb_size); ubi_assert(len > 0); err = self_check_not_bad(ubi, pnum); if (err) return err; /* * Deliberately corrupt the buffer to improve robustness. Indeed, if we * do not do this, the following may happen: * 1. The buffer contains data from previous operation, e.g., read from * another PEB previously. The data looks like expected, e.g., if we * just do not read anything and return - the caller would not * notice this. E.g., if we are reading a VID header, the buffer may * contain a valid VID header from another PEB. * 2. The driver is buggy and returns us success or -EBADMSG or * -EUCLEAN, but it does not actually put any data to the buffer. * * This may confuse UBI or upper layers - they may think the buffer * contains valid data while in fact it is just old data. This is * especially possible because UBI (and UBIFS) relies on CRC, and * treats data as correct even in case of ECC errors if the CRC is * correct. * * Try to prevent this situation by changing the first byte of the * buffer. */ *((uint8_t *)buf) ^= 0xFF; addr = (loff_t)pnum * ubi->peb_size + offset; retry: err = mtd_read(ubi->mtd, addr, len, &read, buf); if (err) { const char *errstr = mtd_is_eccerr(err) ? " (ECC error)" : ""; if (mtd_is_bitflip(err)) { /* * -EUCLEAN is reported if there was a bit-flip which * was corrected, so this is harmless. * * We do not report about it here unless debugging is * enabled. A corresponding message will be printed * later, when it is has been scrubbed. */ ubi_msg(ubi, "fixable bit-flip detected at PEB %d", pnum); ubi_assert(len == read); return UBI_IO_BITFLIPS; } if (retries++ < UBI_IO_RETRIES) { ubi_warn(ubi, "error %d%s while reading %d bytes from PEB %d:%d, read only %zd bytes, retry", err, errstr, len, pnum, offset, read); yield(); goto retry; } ubi_err(ubi, "error %d%s while reading %d bytes from PEB %d:%d, read %zd bytes", err, errstr, len, pnum, offset, read); dump_stack(); /* * The driver should never return -EBADMSG if it failed to read * all the requested data. But some buggy drivers might do * this, so we change it to -EIO. */ if (read != len && mtd_is_eccerr(err)) { ubi_assert(0); err = -EIO; } } else { ubi_assert(len == read); if (ubi_dbg_is_bitflip(ubi)) { dbg_gen("bit-flip (emulated)"); err = UBI_IO_BITFLIPS; } } return err; }
/** * io_init - initialize I/O sub-system for a given UBI device. * @ubi: UBI device description object * @max_beb_per1024: maximum expected number of bad PEB per 1024 PEBs * * If @ubi->vid_hdr_offset or @ubi->leb_start is zero, default offsets are * assumed: * o EC header is always at offset zero - this cannot be changed; * o VID header starts just after the EC header at the closest address * aligned to @io->hdrs_min_io_size; * o data starts just after the VID header at the closest address aligned to * @io->min_io_size * * This function returns zero in case of success and a negative error code in * case of failure. */ static int io_init(struct ubi_device *ubi, int max_beb_per1024) { dbg_gen("sizeof(struct ubi_ainf_peb) %zu", sizeof(struct ubi_ainf_peb)); dbg_gen("sizeof(struct ubi_wl_entry) %zu", sizeof(struct ubi_wl_entry)); if (ubi->mtd->numeraseregions != 0) { /* * Some flashes have several erase regions. Different regions * may have different eraseblock size and other * characteristics. It looks like mostly multi-region flashes * have one "main" region and one or more small regions to * store boot loader code or boot parameters or whatever. I * guess we should just pick the largest region. But this is * not implemented. */ ubi_err("multiple regions, not implemented"); return -EINVAL; } if (ubi->vid_hdr_offset < 0) return -EINVAL; /* * Note, in this implementation we support MTD devices with 0x7FFFFFFF * physical eraseblocks maximum. */ ubi->peb_size = ubi->mtd->erasesize; ubi->peb_count = mtd_div_by_eb(ubi->mtd->size, ubi->mtd); ubi->flash_size = ubi->mtd->size; if (mtd_can_have_bb(ubi->mtd)) { ubi->bad_allowed = 1; ubi->bad_peb_limit = get_bad_peb_limit(ubi, max_beb_per1024); } if (ubi->mtd->type == MTD_NORFLASH) { ubi_assert(ubi->mtd->writesize == 1); ubi->nor_flash = 1; } ubi->min_io_size = ubi->mtd->writesize; ubi->hdrs_min_io_size = ubi->mtd->writesize >> ubi->mtd->subpage_sft; /* * Make sure minimal I/O unit is power of 2. Note, there is no * fundamental reason for this assumption. It is just an optimization * which allows us to avoid costly division operations. */ if (!is_power_of_2(ubi->min_io_size)) { ubi_err("min. I/O unit (%d) is not power of 2", ubi->min_io_size); return -EINVAL; } ubi_assert(ubi->hdrs_min_io_size > 0); ubi_assert(ubi->hdrs_min_io_size <= ubi->min_io_size); ubi_assert(ubi->min_io_size % ubi->hdrs_min_io_size == 0); ubi->max_write_size = ubi->mtd->writesize; /* FIXME: writebufsize */ /* * Maximum write size has to be greater or equivalent to min. I/O * size, and be multiple of min. I/O size. */ if (ubi->max_write_size < ubi->min_io_size || ubi->max_write_size % ubi->min_io_size || !is_power_of_2(ubi->max_write_size)) { ubi_err("bad write buffer size %d for %d min. I/O unit", ubi->max_write_size, ubi->min_io_size); return -EINVAL; } /* Calculate default aligned sizes of EC and VID headers */ ubi->ec_hdr_alsize = ALIGN(UBI_EC_HDR_SIZE, ubi->hdrs_min_io_size); ubi->vid_hdr_alsize = ALIGN(UBI_VID_HDR_SIZE, ubi->hdrs_min_io_size); dbg_gen("min_io_size %d", ubi->min_io_size); dbg_gen("max_write_size %d", ubi->max_write_size); dbg_gen("hdrs_min_io_size %d", ubi->hdrs_min_io_size); dbg_gen("ec_hdr_alsize %d", ubi->ec_hdr_alsize); dbg_gen("vid_hdr_alsize %d", ubi->vid_hdr_alsize); if (ubi->vid_hdr_offset == 0) /* Default offset */ ubi->vid_hdr_offset = ubi->vid_hdr_aloffset = ubi->ec_hdr_alsize; else { ubi->vid_hdr_aloffset = ubi->vid_hdr_offset & ~(ubi->hdrs_min_io_size - 1); ubi->vid_hdr_shift = ubi->vid_hdr_offset - ubi->vid_hdr_aloffset; } /* Similar for the data offset */ ubi->leb_start = ubi->vid_hdr_offset + UBI_VID_HDR_SIZE; ubi->leb_start = ALIGN(ubi->leb_start, ubi->min_io_size); dbg_gen("vid_hdr_offset %d", ubi->vid_hdr_offset); dbg_gen("vid_hdr_aloffset %d", ubi->vid_hdr_aloffset); dbg_gen("vid_hdr_shift %d", ubi->vid_hdr_shift); dbg_gen("leb_start %d", ubi->leb_start); /* The shift must be aligned to 32-bit boundary */ if (ubi->vid_hdr_shift % 4) { ubi_err("unaligned VID header shift %d", ubi->vid_hdr_shift); return -EINVAL; } /* Check sanity */ if (ubi->vid_hdr_offset < UBI_EC_HDR_SIZE || ubi->leb_start < ubi->vid_hdr_offset + UBI_VID_HDR_SIZE || ubi->leb_start > ubi->peb_size - UBI_VID_HDR_SIZE || ubi->leb_start & (ubi->min_io_size - 1)) { ubi_err("bad VID header (%d) or data offsets (%d)", ubi->vid_hdr_offset, ubi->leb_start); return -EINVAL; } /* * Set maximum amount of physical erroneous eraseblocks to be 10%. * Erroneous PEB are those which have read errors. */ ubi->max_erroneous = ubi->peb_count / 10; if (ubi->max_erroneous < 16) ubi->max_erroneous = 16; dbg_gen("max_erroneous %d", ubi->max_erroneous); /* * It may happen that EC and VID headers are situated in one minimal * I/O unit. In this case we can only accept this UBI image in * read-only mode. */ if (ubi->vid_hdr_offset + UBI_VID_HDR_SIZE <= ubi->hdrs_min_io_size) { ubi_warn("EC and VID headers are in the same minimal I/O unit, switch to read-only mode"); ubi->ro_mode = 1; } ubi->leb_size = ubi->peb_size - ubi->leb_start; if (!(ubi->mtd->flags & MTD_WRITEABLE)) { ubi_msg("MTD device %d is write-protected, attach in read-only mode", ubi->mtd->index); ubi->ro_mode = 1; } /* * Note, ideally, we have to initialize @ubi->bad_peb_count here. But * unfortunately, MTD does not provide this information. We should loop * over all physical eraseblocks and invoke mtd->block_is_bad() for * each physical eraseblock. So, we leave @ubi->bad_peb_count * uninitialized so far. */ return 0; }
/** * 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; }
/** * ubi_more_update_data - write more update data. * @ubi: UBI device description object * @vol: volume description object * @buf: write data (user-space memory buffer) * @count: how much bytes to write * * This function writes more data to the volume which is being updated. It may * be called arbitrary number of times until all the update data arriveis. This * function returns %0 in case of success, number of bytes written during the * last call if the whole volume update has been successfully finished, and a * negative error code in case of failure. */ int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol, const void __user *buf, int count) { #ifndef __UBOOT__ int lnum, offs, err = 0, len, to_write = count; #else int lnum, err = 0, len, to_write = count; u32 offs; #endif dbg_gen("write %d of %lld bytes, %lld already passed", count, vol->upd_bytes, vol->upd_received); if (ubi->ro_mode) return -EROFS; lnum = div_u64_rem(vol->upd_received, vol->usable_leb_size, &offs); if (vol->upd_received + count > vol->upd_bytes) to_write = count = vol->upd_bytes - vol->upd_received; /* * When updating volumes, we accumulate whole logical eraseblock of * data and write it at once. */ if (offs != 0) { /* * This is a write to the middle of the logical eraseblock. We * copy the data to our update buffer and wait for more data or * flush it if the whole eraseblock is written or the update * is finished. */ len = vol->usable_leb_size - offs; if (len > count) len = count; err = copy_from_user(vol->upd_buf + offs, buf, len); if (err) return -EFAULT; if (offs + len == vol->usable_leb_size || vol->upd_received + len == vol->upd_bytes) { int flush_len = offs + len; /* * OK, we gathered either the whole eraseblock or this * is the last chunk, it's time to flush the buffer. */ ubi_assert(flush_len <= vol->usable_leb_size); err = write_leb(ubi, vol, lnum, vol->upd_buf, flush_len, vol->upd_ebs); if (err) return err; } vol->upd_received += len; count -= len; buf += len; lnum += 1; } /* * If we've got more to write, let's continue. At this point we know we * are starting from the beginning of an eraseblock. */ while (count) { if (count > vol->usable_leb_size) len = vol->usable_leb_size; else len = count; err = copy_from_user(vol->upd_buf, buf, len); if (err) return -EFAULT; if (len == vol->usable_leb_size || vol->upd_received + len == vol->upd_bytes) { err = write_leb(ubi, vol, lnum, vol->upd_buf, len, vol->upd_ebs); if (err) break; } vol->upd_received += len; count -= len; lnum += 1; buf += len; } ubi_assert(vol->upd_received <= vol->upd_bytes); if (vol->upd_received == vol->upd_bytes) { err = ubi_wl_flush(ubi, UBI_ALL, UBI_ALL); if (err) return err; /* The update is finished, clear the update marker */ err = clear_update_marker(ubi, vol, vol->upd_bytes); if (err) return err; vol->updating = 0; err = to_write; vfree(vol->upd_buf); } return err; }