UBIFS:
* Always support xattrs (remove the Kconfig option) * Always support debugging (remove the Kconfig option) * A fix for a memory leak on error path * A number of clean-ups UBI: * Always support debugging (remove the Kconfig option) * Remove "data type" hint support * Huge amount of renames to prepare for the fastmap wor * A lot of clean-ups -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.12 (GNU/Linux) iQIcBAABAgAGBQJPuzTxAAoJECmIfjd9wqK0D/AP/iNOnYWnYZmmO18jDM48kKt/ Jp7VTAE0l7DBUDxtiIthq4c7YxIE1o1bN9gMmvzZibvwIrZcoAOnQpeL96s1Bc9J t0aGm8ONvrtuyFeyxPC0aplWgqWQ49qDLGV/lIVJ+BSGmXMeU4giUIXqbsjyCPR4 YVJJw6rLTC10EhuAUs99keJxxuN5ZMrCB8y47fD+bkalVxgqNh9JNkKabyjevt5C AERVWnP20hnEcwnbQWMHueGWiaqFeesTytNOy6heRi0uL3bNy5nrol7AFXKqnDc9 OpSkApH6SCO3C8X/bIep2bL9kKiW1LpClxgDIF6p7lj2t2ToPn6PZJbP60zSHQPb 0bgy1SzHccF3ihIMgCdOXYZ5EomBgKZyDyU6Ec+gAttE00ZbIigNmjFmukwMhO89 I0bGvjQdKFAFSzo+ffm8xNfYjmmNfB+edLkPaVttjMWAbQ4V831ZPDT07Q11W4TQ 2p2NDKTps3etbtkemZ/Cm1jeEWI3KuogrFhyDhpcgXc7pxlJbvMg+tt22FusoQ8T VPGGT+WhmXfF0ZG/gurI69k8opj4BUhm4EfGL6pGEoUMe1nGp2pSUNv5Kwby1wau 1wElJt2qO9xdjJ4QlLc+Ux1vm8rCS1iQst9plUX1BZt2bKja7tZaW7uu4hGKqe5u UwrosuYcmS1Ei1Rs7Sqz =+6Qi -----END PGP SIGNATURE----- Merge tag 'upstream-3.5-rc1' of git://git.infradead.org/linux-ubifs Pull UBI and UBIFS updates from Artem Bityutskiy: UBIFS: * Always support xattrs (remove the Kconfig option) * Always support debugging (remove the Kconfig option) * A fix for a memory leak on error path * A number of clean-ups UBI: * Always support debugging (remove the Kconfig option) * Remove "data type" hint support * Huge amount of renames to prepare for the fastmap wor * A lot of clean-ups * tag 'upstream-3.5-rc1' of git://git.infradead.org/linux-ubifs: (54 commits) UBI: modify ubi_wl_flush function to clear work queue for a lnum UBI: introduce UBI_ALL constant UBI: add lnum and vol_id to struct ubi_work UBI: add volume id struct ubi_ainf_peb UBI: add in hex the value for UBI_INTERNAL_VOL_START to comment UBI: rename scan.c to attach.c UBI: remove scan.h UBI: rename UBI_SCAN_UNKNOWN_EC UBI: move and rename attach_by_scanning UBI: rename _init_scan functions UBI: amend comments after all the renamings UBI: rename ubi_scan_leb_slab UBI: rename ubi_scan_move_to_list UBI: rename ubi_scan_destroy_ai UBI: rename ubi_scan_get_free_peb UBI: rename ubi_scan_rm_volume UBI: rename ubi_scan_find_av UBI: rename ubi_scan_add_used UBI: remove unused function UBI: make ubi_scan_erase_peb static and rename ...
This commit is contained in:
commit
6133308ad1
46 changed files with 1585 additions and 2095 deletions
|
@ -52,12 +52,4 @@ config MTD_UBI_GLUEBI
|
|||
work on top of UBI. Do not enable this unless you use legacy
|
||||
software.
|
||||
|
||||
config MTD_UBI_DEBUG
|
||||
bool "UBI debugging"
|
||||
depends on SYSFS
|
||||
select DEBUG_FS
|
||||
select KALLSYMS
|
||||
help
|
||||
This option enables UBI debugging.
|
||||
|
||||
endif # MTD_UBI
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
obj-$(CONFIG_MTD_UBI) += ubi.o
|
||||
|
||||
ubi-y += vtbl.o vmt.o upd.o build.o cdev.o kapi.o eba.o io.o wl.o scan.o
|
||||
ubi-y += misc.o
|
||||
ubi-y += vtbl.o vmt.o upd.o build.o cdev.o kapi.o eba.o io.o wl.o attach.o
|
||||
ubi-y += misc.o debug.o
|
||||
|
||||
ubi-$(CONFIG_MTD_UBI_DEBUG) += debug.o
|
||||
obj-$(CONFIG_MTD_UBI_GLUEBI) += gluebi.o
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -27,10 +27,6 @@
|
|||
* module load parameters or the kernel boot parameters. If MTD devices were
|
||||
* specified, UBI does not attach any MTD device, but it is possible to do
|
||||
* later using the "UBI control device".
|
||||
*
|
||||
* At the moment we only attach UBI devices by scanning, which will become a
|
||||
* bottleneck when flashes reach certain large size. Then one may improve UBI
|
||||
* and add other methods, although it does not seem to be easy to do.
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
|
@ -554,10 +550,10 @@ static void uif_close(struct ubi_device *ubi)
|
|||
}
|
||||
|
||||
/**
|
||||
* free_internal_volumes - free internal volumes.
|
||||
* ubi_free_internal_volumes - free internal volumes.
|
||||
* @ubi: UBI device description object
|
||||
*/
|
||||
static void free_internal_volumes(struct ubi_device *ubi)
|
||||
void ubi_free_internal_volumes(struct ubi_device *ubi)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -568,59 +564,6 @@ static void free_internal_volumes(struct ubi_device *ubi)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* attach_by_scanning - attach an MTD device using scanning method.
|
||||
* @ubi: UBI device descriptor
|
||||
*
|
||||
* This function returns zero in case of success and a negative error code in
|
||||
* case of failure.
|
||||
*
|
||||
* Note, currently this is the only method to attach UBI devices. Hopefully in
|
||||
* the future we'll have more scalable attaching methods and avoid full media
|
||||
* scanning. But even in this case scanning will be needed as a fall-back
|
||||
* attaching method if there are some on-flash table corruptions.
|
||||
*/
|
||||
static int attach_by_scanning(struct ubi_device *ubi)
|
||||
{
|
||||
int err;
|
||||
struct ubi_scan_info *si;
|
||||
|
||||
si = ubi_scan(ubi);
|
||||
if (IS_ERR(si))
|
||||
return PTR_ERR(si);
|
||||
|
||||
ubi->bad_peb_count = si->bad_peb_count;
|
||||
ubi->good_peb_count = ubi->peb_count - ubi->bad_peb_count;
|
||||
ubi->corr_peb_count = si->corr_peb_count;
|
||||
ubi->max_ec = si->max_ec;
|
||||
ubi->mean_ec = si->mean_ec;
|
||||
ubi_msg("max. sequence number: %llu", si->max_sqnum);
|
||||
|
||||
err = ubi_read_volume_table(ubi, si);
|
||||
if (err)
|
||||
goto out_si;
|
||||
|
||||
err = ubi_wl_init_scan(ubi, si);
|
||||
if (err)
|
||||
goto out_vtbl;
|
||||
|
||||
err = ubi_eba_init_scan(ubi, si);
|
||||
if (err)
|
||||
goto out_wl;
|
||||
|
||||
ubi_scan_destroy_si(si);
|
||||
return 0;
|
||||
|
||||
out_wl:
|
||||
ubi_wl_close(ubi);
|
||||
out_vtbl:
|
||||
free_internal_volumes(ubi);
|
||||
vfree(ubi->vtbl);
|
||||
out_si:
|
||||
ubi_scan_destroy_si(si);
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* io_init - initialize I/O sub-system for a given UBI device.
|
||||
* @ubi: UBI device description object
|
||||
|
@ -790,11 +733,11 @@ static int io_init(struct ubi_device *ubi)
|
|||
ubi_msg("data offset: %d", ubi->leb_start);
|
||||
|
||||
/*
|
||||
* Note, ideally, we have to initialize ubi->bad_peb_count here. But
|
||||
* 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 skip ubi->bad_peb_count
|
||||
* uninitialized and initialize it after scanning.
|
||||
* each physical eraseblock. So, we leave @ubi->bad_peb_count
|
||||
* uninitialized so far.
|
||||
*/
|
||||
|
||||
return 0;
|
||||
|
@ -805,7 +748,7 @@ static int io_init(struct ubi_device *ubi)
|
|||
* @ubi: UBI device description object
|
||||
* @vol_id: ID of the volume to re-size
|
||||
*
|
||||
* This function re-sizes the volume marked by the @UBI_VTBL_AUTORESIZE_FLG in
|
||||
* This function re-sizes the volume marked by the %UBI_VTBL_AUTORESIZE_FLG in
|
||||
* the volume table to the largest possible size. See comments in ubi-header.h
|
||||
* for more description of the flag. Returns zero in case of success and a
|
||||
* negative error code in case of failure.
|
||||
|
@ -881,7 +824,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
|
|||
for (i = 0; i < UBI_MAX_DEVICES; i++) {
|
||||
ubi = ubi_devices[i];
|
||||
if (ubi && mtd->index == ubi->mtd->index) {
|
||||
dbg_err("mtd%d is already attached to ubi%d",
|
||||
ubi_err("mtd%d is already attached to ubi%d",
|
||||
mtd->index, i);
|
||||
return -EEXIST;
|
||||
}
|
||||
|
@ -907,7 +850,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
|
|||
if (!ubi_devices[ubi_num])
|
||||
break;
|
||||
if (ubi_num == UBI_MAX_DEVICES) {
|
||||
dbg_err("only %d UBI devices may be created",
|
||||
ubi_err("only %d UBI devices may be created",
|
||||
UBI_MAX_DEVICES);
|
||||
return -ENFILE;
|
||||
}
|
||||
|
@ -917,7 +860,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
|
|||
|
||||
/* Make sure ubi_num is not busy */
|
||||
if (ubi_devices[ubi_num]) {
|
||||
dbg_err("ubi%d already exists", ubi_num);
|
||||
ubi_err("ubi%d already exists", ubi_num);
|
||||
return -EEXIST;
|
||||
}
|
||||
}
|
||||
|
@ -937,7 +880,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
|
|||
spin_lock_init(&ubi->volumes_lock);
|
||||
|
||||
ubi_msg("attaching mtd%d to ubi%d", mtd->index, ubi_num);
|
||||
dbg_msg("sizeof(struct ubi_scan_leb) %zu", sizeof(struct ubi_scan_leb));
|
||||
dbg_msg("sizeof(struct ubi_ainf_peb) %zu", sizeof(struct ubi_ainf_peb));
|
||||
dbg_msg("sizeof(struct ubi_wl_entry) %zu", sizeof(struct ubi_wl_entry));
|
||||
|
||||
err = io_init(ubi);
|
||||
|
@ -953,9 +896,9 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
|
|||
if (err)
|
||||
goto out_free;
|
||||
|
||||
err = attach_by_scanning(ubi);
|
||||
err = ubi_attach(ubi);
|
||||
if (err) {
|
||||
dbg_err("failed to attach by scanning, error %d", err);
|
||||
ubi_err("failed to attach mtd%d, error %d", mtd->index, err);
|
||||
goto out_debugging;
|
||||
}
|
||||
|
||||
|
@ -1020,7 +963,7 @@ out_uif:
|
|||
uif_close(ubi);
|
||||
out_detach:
|
||||
ubi_wl_close(ubi);
|
||||
free_internal_volumes(ubi);
|
||||
ubi_free_internal_volumes(ubi);
|
||||
vfree(ubi->vtbl);
|
||||
out_debugging:
|
||||
ubi_debugging_exit_dev(ubi);
|
||||
|
@ -1092,7 +1035,7 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
|
|||
ubi_debugfs_exit_dev(ubi);
|
||||
uif_close(ubi);
|
||||
ubi_wl_close(ubi);
|
||||
free_internal_volumes(ubi);
|
||||
ubi_free_internal_volumes(ubi);
|
||||
vfree(ubi->vtbl);
|
||||
put_mtd_device(ubi->mtd);
|
||||
ubi_debugging_exit_dev(ubi);
|
||||
|
|
|
@ -63,7 +63,7 @@ static int get_exclusive(struct ubi_volume_desc *desc)
|
|||
users = vol->readers + vol->writers + vol->exclusive;
|
||||
ubi_assert(users > 0);
|
||||
if (users > 1) {
|
||||
dbg_err("%d users for volume %d", users, vol->vol_id);
|
||||
ubi_err("%d users for volume %d", users, vol->vol_id);
|
||||
err = -EBUSY;
|
||||
} else {
|
||||
vol->readers = vol->writers = 0;
|
||||
|
@ -159,7 +159,7 @@ static loff_t vol_cdev_llseek(struct file *file, loff_t offset, int origin)
|
|||
|
||||
if (vol->updating) {
|
||||
/* Update is in progress, seeking is prohibited */
|
||||
dbg_err("updating");
|
||||
ubi_err("updating");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
|
@ -178,7 +178,7 @@ static loff_t vol_cdev_llseek(struct file *file, loff_t offset, int origin)
|
|||
}
|
||||
|
||||
if (new_offset < 0 || new_offset > vol->used_bytes) {
|
||||
dbg_err("bad seek %lld", new_offset);
|
||||
ubi_err("bad seek %lld", new_offset);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -216,11 +216,11 @@ static ssize_t vol_cdev_read(struct file *file, __user char *buf, size_t count,
|
|||
count, *offp, vol->vol_id);
|
||||
|
||||
if (vol->updating) {
|
||||
dbg_err("updating");
|
||||
ubi_err("updating");
|
||||
return -EBUSY;
|
||||
}
|
||||
if (vol->upd_marker) {
|
||||
dbg_err("damaged volume, update marker is set");
|
||||
ubi_err("damaged volume, update marker is set");
|
||||
return -EBADF;
|
||||
}
|
||||
if (*offp == vol->used_bytes || count == 0)
|
||||
|
@ -300,7 +300,7 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf,
|
|||
|
||||
lnum = div_u64_rem(*offp, vol->usable_leb_size, &off);
|
||||
if (off & (ubi->min_io_size - 1)) {
|
||||
dbg_err("unaligned position");
|
||||
ubi_err("unaligned position");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -309,7 +309,7 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf,
|
|||
|
||||
/* We can write only in fractions of the minimum I/O unit */
|
||||
if (count & (ubi->min_io_size - 1)) {
|
||||
dbg_err("unaligned write length");
|
||||
ubi_err("unaligned write length");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -334,8 +334,7 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf,
|
|||
break;
|
||||
}
|
||||
|
||||
err = ubi_eba_write_leb(ubi, vol, lnum, tbuf, off, len,
|
||||
UBI_UNKNOWN);
|
||||
err = ubi_eba_write_leb(ubi, vol, lnum, tbuf, off, len);
|
||||
if (err)
|
||||
break;
|
||||
|
||||
|
@ -477,9 +476,6 @@ static long vol_cdev_ioctl(struct file *file, unsigned int cmd,
|
|||
if (req.lnum < 0 || req.lnum >= vol->reserved_pebs ||
|
||||
req.bytes < 0 || req.lnum >= vol->usable_leb_size)
|
||||
break;
|
||||
if (req.dtype != UBI_LONGTERM && req.dtype != UBI_SHORTTERM &&
|
||||
req.dtype != UBI_UNKNOWN)
|
||||
break;
|
||||
|
||||
err = get_exclusive(desc);
|
||||
if (err < 0)
|
||||
|
@ -518,7 +514,7 @@ static long vol_cdev_ioctl(struct file *file, unsigned int cmd,
|
|||
if (err)
|
||||
break;
|
||||
|
||||
err = ubi_wl_flush(ubi);
|
||||
err = ubi_wl_flush(ubi, UBI_ALL, UBI_ALL);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -532,7 +528,7 @@ static long vol_cdev_ioctl(struct file *file, unsigned int cmd,
|
|||
err = -EFAULT;
|
||||
break;
|
||||
}
|
||||
err = ubi_leb_map(desc, req.lnum, req.dtype);
|
||||
err = ubi_leb_map(desc, req.lnum);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -647,8 +643,8 @@ static int verify_mkvol_req(const struct ubi_device *ubi,
|
|||
return 0;
|
||||
|
||||
bad:
|
||||
dbg_err("bad volume creation request");
|
||||
ubi_dbg_dump_mkvol_req(req);
|
||||
ubi_err("bad volume creation request");
|
||||
ubi_dump_mkvol_req(req);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -713,12 +709,12 @@ static int rename_volumes(struct ubi_device *ubi,
|
|||
for (i = 0; i < req->count - 1; i++) {
|
||||
for (n = i + 1; n < req->count; n++) {
|
||||
if (req->ents[i].vol_id == req->ents[n].vol_id) {
|
||||
dbg_err("duplicated volume id %d",
|
||||
ubi_err("duplicated volume id %d",
|
||||
req->ents[i].vol_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!strcmp(req->ents[i].name, req->ents[n].name)) {
|
||||
dbg_err("duplicated volume name \"%s\"",
|
||||
ubi_err("duplicated volume name \"%s\"",
|
||||
req->ents[i].name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -741,7 +737,7 @@ static int rename_volumes(struct ubi_device *ubi,
|
|||
re->desc = ubi_open_volume(ubi->ubi_num, vol_id, UBI_EXCLUSIVE);
|
||||
if (IS_ERR(re->desc)) {
|
||||
err = PTR_ERR(re->desc);
|
||||
dbg_err("cannot open volume %d, error %d", vol_id, err);
|
||||
ubi_err("cannot open volume %d, error %d", vol_id, err);
|
||||
kfree(re);
|
||||
goto out_free;
|
||||
}
|
||||
|
@ -800,7 +796,7 @@ static int rename_volumes(struct ubi_device *ubi,
|
|||
continue;
|
||||
|
||||
/* The volume exists but busy, or an error occurred */
|
||||
dbg_err("cannot open volume \"%s\", error %d",
|
||||
ubi_err("cannot open volume \"%s\", error %d",
|
||||
re->new_name, err);
|
||||
goto out_free;
|
||||
}
|
||||
|
|
|
@ -18,24 +18,49 @@
|
|||
* Author: Artem Bityutskiy (Битюцкий Артём)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Here we keep all the UBI debugging stuff which should normally be disabled
|
||||
* and compiled-out, but it is extremely helpful when hunting bugs or doing big
|
||||
* changes.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_MTD_UBI_DEBUG
|
||||
|
||||
#include "ubi.h"
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
|
||||
/**
|
||||
* ubi_dbg_dump_ec_hdr - dump an erase counter header.
|
||||
* ubi_dump_flash - dump a region of flash.
|
||||
* @ubi: UBI device description object
|
||||
* @pnum: the physical eraseblock number to dump
|
||||
* @offset: the starting offset within the physical eraseblock to dump
|
||||
* @len: the length of the region to dump
|
||||
*/
|
||||
void ubi_dump_flash(struct ubi_device *ubi, int pnum, int offset, int len)
|
||||
{
|
||||
int err;
|
||||
size_t read;
|
||||
void *buf;
|
||||
loff_t addr = (loff_t)pnum * ubi->peb_size + offset;
|
||||
|
||||
buf = vmalloc(len);
|
||||
if (!buf)
|
||||
return;
|
||||
err = mtd_read(ubi->mtd, addr, len, &read, buf);
|
||||
if (err && err != -EUCLEAN) {
|
||||
ubi_err("error %d while reading %d bytes from PEB %d:%d, "
|
||||
"read %zd bytes", err, len, pnum, offset, read);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ubi_msg("dumping %d bytes of data from PEB %d, offset %d",
|
||||
len, pnum, offset);
|
||||
print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, buf, len, 1);
|
||||
out:
|
||||
vfree(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* ubi_dump_ec_hdr - dump an erase counter header.
|
||||
* @ec_hdr: the erase counter header to dump
|
||||
*/
|
||||
void ubi_dbg_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr)
|
||||
void ubi_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr)
|
||||
{
|
||||
printk(KERN_DEBUG "Erase counter header dump:\n");
|
||||
printk(KERN_DEBUG "\tmagic %#08x\n",
|
||||
|
@ -57,10 +82,10 @@ void ubi_dbg_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr)
|
|||
}
|
||||
|
||||
/**
|
||||
* ubi_dbg_dump_vid_hdr - dump a volume identifier header.
|
||||
* ubi_dump_vid_hdr - dump a volume identifier header.
|
||||
* @vid_hdr: the volume identifier header to dump
|
||||
*/
|
||||
void ubi_dbg_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr)
|
||||
void ubi_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr)
|
||||
{
|
||||
printk(KERN_DEBUG "Volume identifier header dump:\n");
|
||||
printk(KERN_DEBUG "\tmagic %08x\n", be32_to_cpu(vid_hdr->magic));
|
||||
|
@ -82,10 +107,10 @@ void ubi_dbg_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr)
|
|||
}
|
||||
|
||||
/**
|
||||
* ubi_dbg_dump_vol_info- dump volume information.
|
||||
* ubi_dump_vol_info - dump volume information.
|
||||
* @vol: UBI volume description object
|
||||
*/
|
||||
void ubi_dbg_dump_vol_info(const struct ubi_volume *vol)
|
||||
void ubi_dump_vol_info(const struct ubi_volume *vol)
|
||||
{
|
||||
printk(KERN_DEBUG "Volume information dump:\n");
|
||||
printk(KERN_DEBUG "\tvol_id %d\n", vol->vol_id);
|
||||
|
@ -112,11 +137,11 @@ void ubi_dbg_dump_vol_info(const struct ubi_volume *vol)
|
|||
}
|
||||
|
||||
/**
|
||||
* ubi_dbg_dump_vtbl_record - dump a &struct ubi_vtbl_record object.
|
||||
* ubi_dump_vtbl_record - dump a &struct ubi_vtbl_record object.
|
||||
* @r: the object to dump
|
||||
* @idx: volume table index
|
||||
*/
|
||||
void ubi_dbg_dump_vtbl_record(const struct ubi_vtbl_record *r, int idx)
|
||||
void ubi_dump_vtbl_record(const struct ubi_vtbl_record *r, int idx)
|
||||
{
|
||||
int name_len = be16_to_cpu(r->name_len);
|
||||
|
||||
|
@ -146,44 +171,44 @@ void ubi_dbg_dump_vtbl_record(const struct ubi_vtbl_record *r, int idx)
|
|||
}
|
||||
|
||||
/**
|
||||
* ubi_dbg_dump_sv - dump a &struct ubi_scan_volume object.
|
||||
* @sv: the object to dump
|
||||
* ubi_dump_av - dump a &struct ubi_ainf_volume object.
|
||||
* @av: the object to dump
|
||||
*/
|
||||
void ubi_dbg_dump_sv(const struct ubi_scan_volume *sv)
|
||||
void ubi_dump_av(const struct ubi_ainf_volume *av)
|
||||
{
|
||||
printk(KERN_DEBUG "Volume scanning information dump:\n");
|
||||
printk(KERN_DEBUG "\tvol_id %d\n", sv->vol_id);
|
||||
printk(KERN_DEBUG "\thighest_lnum %d\n", sv->highest_lnum);
|
||||
printk(KERN_DEBUG "\tleb_count %d\n", sv->leb_count);
|
||||
printk(KERN_DEBUG "\tcompat %d\n", sv->compat);
|
||||
printk(KERN_DEBUG "\tvol_type %d\n", sv->vol_type);
|
||||
printk(KERN_DEBUG "\tused_ebs %d\n", sv->used_ebs);
|
||||
printk(KERN_DEBUG "\tlast_data_size %d\n", sv->last_data_size);
|
||||
printk(KERN_DEBUG "\tdata_pad %d\n", sv->data_pad);
|
||||
printk(KERN_DEBUG "Volume attaching information dump:\n");
|
||||
printk(KERN_DEBUG "\tvol_id %d\n", av->vol_id);
|
||||
printk(KERN_DEBUG "\thighest_lnum %d\n", av->highest_lnum);
|
||||
printk(KERN_DEBUG "\tleb_count %d\n", av->leb_count);
|
||||
printk(KERN_DEBUG "\tcompat %d\n", av->compat);
|
||||
printk(KERN_DEBUG "\tvol_type %d\n", av->vol_type);
|
||||
printk(KERN_DEBUG "\tused_ebs %d\n", av->used_ebs);
|
||||
printk(KERN_DEBUG "\tlast_data_size %d\n", av->last_data_size);
|
||||
printk(KERN_DEBUG "\tdata_pad %d\n", av->data_pad);
|
||||
}
|
||||
|
||||
/**
|
||||
* ubi_dbg_dump_seb - dump a &struct ubi_scan_leb object.
|
||||
* @seb: the object to dump
|
||||
* ubi_dump_aeb - dump a &struct ubi_ainf_peb object.
|
||||
* @aeb: the object to dump
|
||||
* @type: object type: 0 - not corrupted, 1 - corrupted
|
||||
*/
|
||||
void ubi_dbg_dump_seb(const struct ubi_scan_leb *seb, int type)
|
||||
void ubi_dump_aeb(const struct ubi_ainf_peb *aeb, int type)
|
||||
{
|
||||
printk(KERN_DEBUG "eraseblock scanning information dump:\n");
|
||||
printk(KERN_DEBUG "\tec %d\n", seb->ec);
|
||||
printk(KERN_DEBUG "\tpnum %d\n", seb->pnum);
|
||||
printk(KERN_DEBUG "eraseblock attaching information dump:\n");
|
||||
printk(KERN_DEBUG "\tec %d\n", aeb->ec);
|
||||
printk(KERN_DEBUG "\tpnum %d\n", aeb->pnum);
|
||||
if (type == 0) {
|
||||
printk(KERN_DEBUG "\tlnum %d\n", seb->lnum);
|
||||
printk(KERN_DEBUG "\tscrub %d\n", seb->scrub);
|
||||
printk(KERN_DEBUG "\tsqnum %llu\n", seb->sqnum);
|
||||
printk(KERN_DEBUG "\tlnum %d\n", aeb->lnum);
|
||||
printk(KERN_DEBUG "\tscrub %d\n", aeb->scrub);
|
||||
printk(KERN_DEBUG "\tsqnum %llu\n", aeb->sqnum);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ubi_dbg_dump_mkvol_req - dump a &struct ubi_mkvol_req object.
|
||||
* ubi_dump_mkvol_req - dump a &struct ubi_mkvol_req object.
|
||||
* @req: the object to dump
|
||||
*/
|
||||
void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req)
|
||||
void ubi_dump_mkvol_req(const struct ubi_mkvol_req *req)
|
||||
{
|
||||
char nm[17];
|
||||
|
||||
|
@ -199,38 +224,6 @@ void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req)
|
|||
printk(KERN_DEBUG "\t1st 16 characters of name: %s\n", nm);
|
||||
}
|
||||
|
||||
/**
|
||||
* ubi_dbg_dump_flash - dump a region of flash.
|
||||
* @ubi: UBI device description object
|
||||
* @pnum: the physical eraseblock number to dump
|
||||
* @offset: the starting offset within the physical eraseblock to dump
|
||||
* @len: the length of the region to dump
|
||||
*/
|
||||
void ubi_dbg_dump_flash(struct ubi_device *ubi, int pnum, int offset, int len)
|
||||
{
|
||||
int err;
|
||||
size_t read;
|
||||
void *buf;
|
||||
loff_t addr = (loff_t)pnum * ubi->peb_size + offset;
|
||||
|
||||
buf = vmalloc(len);
|
||||
if (!buf)
|
||||
return;
|
||||
err = mtd_read(ubi->mtd, addr, len, &read, buf);
|
||||
if (err && err != -EUCLEAN) {
|
||||
ubi_err("error %d while reading %d bytes from PEB %d:%d, "
|
||||
"read %zd bytes", err, len, pnum, offset, read);
|
||||
goto out;
|
||||
}
|
||||
|
||||
dbg_msg("dumping %d bytes of data from PEB %d, offset %d",
|
||||
len, pnum, offset);
|
||||
print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, buf, len, 1);
|
||||
out:
|
||||
vfree(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* ubi_debugging_init_dev - initialize debugging for an UBI device.
|
||||
* @ubi: UBI device description object
|
||||
|
@ -479,5 +472,3 @@ void ubi_debugfs_exit_dev(struct ubi_device *ubi)
|
|||
{
|
||||
debugfs_remove_recursive(ubi->dbg->dfs_dir);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_MTD_UBI_DEBUG */
|
||||
|
|
|
@ -21,21 +21,20 @@
|
|||
#ifndef __UBI_DEBUG_H__
|
||||
#define __UBI_DEBUG_H__
|
||||
|
||||
#ifdef CONFIG_MTD_UBI_DEBUG
|
||||
void ubi_dump_flash(struct ubi_device *ubi, int pnum, int offset, int len);
|
||||
void ubi_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr);
|
||||
void ubi_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr);
|
||||
|
||||
#include <linux/random.h>
|
||||
|
||||
#define ubi_assert(expr) do { \
|
||||
if (unlikely(!(expr))) { \
|
||||
printk(KERN_CRIT "UBI assert failed in %s at %u (pid %d)\n", \
|
||||
__func__, __LINE__, current->pid); \
|
||||
ubi_dbg_dump_stack(); \
|
||||
dump_stack(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define dbg_err(fmt, ...) ubi_err(fmt, ##__VA_ARGS__)
|
||||
|
||||
#define ubi_dbg_dump_stack() dump_stack()
|
||||
|
||||
#define ubi_dbg_print_hex_dump(l, ps, pt, r, g, b, len, a) \
|
||||
print_hex_dump(l, ps, pt, r, g, b, len, a)
|
||||
|
||||
|
@ -58,17 +57,13 @@
|
|||
/* Initialization and build messages */
|
||||
#define dbg_bld(fmt, ...) ubi_dbg_msg("bld", fmt, ##__VA_ARGS__)
|
||||
|
||||
void ubi_dbg_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr);
|
||||
void ubi_dbg_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr);
|
||||
void ubi_dbg_dump_vol_info(const struct ubi_volume *vol);
|
||||
void ubi_dbg_dump_vtbl_record(const struct ubi_vtbl_record *r, int idx);
|
||||
void ubi_dbg_dump_sv(const struct ubi_scan_volume *sv);
|
||||
void ubi_dbg_dump_seb(const struct ubi_scan_leb *seb, int type);
|
||||
void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req);
|
||||
void ubi_dbg_dump_flash(struct ubi_device *ubi, int pnum, int offset, int len);
|
||||
int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len);
|
||||
int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum,
|
||||
int offset, int len);
|
||||
void ubi_dump_vol_info(const struct ubi_volume *vol);
|
||||
void ubi_dump_vtbl_record(const struct ubi_vtbl_record *r, int idx);
|
||||
void ubi_dump_av(const struct ubi_ainf_volume *av);
|
||||
void ubi_dump_aeb(const struct ubi_ainf_peb *aeb, int type);
|
||||
void ubi_dump_mkvol_req(const struct ubi_mkvol_req *req);
|
||||
int ubi_self_check_all_ff(struct ubi_device *ubi, int pnum, int offset,
|
||||
int len);
|
||||
int ubi_debugging_init_dev(struct ubi_device *ubi);
|
||||
void ubi_debugging_exit_dev(struct ubi_device *ubi);
|
||||
int ubi_debugfs_init(void);
|
||||
|
@ -167,73 +162,4 @@ static inline int ubi_dbg_is_erase_failure(const struct ubi_device *ubi)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* Use "if (0)" to make compiler check arguments even if debugging is off */
|
||||
#define ubi_assert(expr) do { \
|
||||
if (0) { \
|
||||
printk(KERN_CRIT "UBI assert failed in %s at %u (pid %d)\n", \
|
||||
__func__, __LINE__, current->pid); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define dbg_err(fmt, ...) do { \
|
||||
if (0) \
|
||||
ubi_err(fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define ubi_dbg_msg(fmt, ...) do { \
|
||||
if (0) \
|
||||
printk(KERN_DEBUG fmt "\n", ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define dbg_msg(fmt, ...) ubi_dbg_msg(fmt, ##__VA_ARGS__)
|
||||
#define dbg_gen(fmt, ...) ubi_dbg_msg(fmt, ##__VA_ARGS__)
|
||||
#define dbg_eba(fmt, ...) ubi_dbg_msg(fmt, ##__VA_ARGS__)
|
||||
#define dbg_wl(fmt, ...) ubi_dbg_msg(fmt, ##__VA_ARGS__)
|
||||
#define dbg_io(fmt, ...) ubi_dbg_msg(fmt, ##__VA_ARGS__)
|
||||
#define dbg_bld(fmt, ...) ubi_dbg_msg(fmt, ##__VA_ARGS__)
|
||||
|
||||
static inline void ubi_dbg_dump_stack(void) { return; }
|
||||
static inline void
|
||||
ubi_dbg_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr) { return; }
|
||||
static inline void
|
||||
ubi_dbg_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr) { return; }
|
||||
static inline void
|
||||
ubi_dbg_dump_vol_info(const struct ubi_volume *vol) { return; }
|
||||
static inline void
|
||||
ubi_dbg_dump_vtbl_record(const struct ubi_vtbl_record *r, int idx) { return; }
|
||||
static inline void ubi_dbg_dump_sv(const struct ubi_scan_volume *sv) { return; }
|
||||
static inline void ubi_dbg_dump_seb(const struct ubi_scan_leb *seb,
|
||||
int type) { return; }
|
||||
static inline void
|
||||
ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req) { return; }
|
||||
static inline void ubi_dbg_dump_flash(struct ubi_device *ubi,
|
||||
int pnum, int offset, int len) { return; }
|
||||
static inline void
|
||||
ubi_dbg_print_hex_dump(const char *l, const char *ps, int pt, int r,
|
||||
int g, const void *b, size_t len, bool a) { return; }
|
||||
static inline int ubi_dbg_check_all_ff(struct ubi_device *ubi,
|
||||
int pnum, int offset,
|
||||
int len) { return 0; }
|
||||
static inline int ubi_dbg_check_write(struct ubi_device *ubi,
|
||||
const void *buf, int pnum,
|
||||
int offset, int len) { return 0; }
|
||||
|
||||
static inline int ubi_debugging_init_dev(struct ubi_device *ubi) { return 0; }
|
||||
static inline void ubi_debugging_exit_dev(struct ubi_device *ubi) { return; }
|
||||
static inline int ubi_debugfs_init(void) { return 0; }
|
||||
static inline void ubi_debugfs_exit(void) { return; }
|
||||
static inline int ubi_debugfs_init_dev(struct ubi_device *ubi) { return 0; }
|
||||
static inline void ubi_debugfs_exit_dev(struct ubi_device *ubi) { return; }
|
||||
|
||||
static inline int
|
||||
ubi_dbg_is_bgt_disabled(const struct ubi_device *ubi) { return 0; }
|
||||
static inline int ubi_dbg_is_bitflip(const struct ubi_device *ubi) { return 0; }
|
||||
static inline int
|
||||
ubi_dbg_is_write_failure(const struct ubi_device *ubi) { return 0; }
|
||||
static inline int
|
||||
ubi_dbg_is_erase_failure(const struct ubi_device *ubi) { return 0; }
|
||||
|
||||
#endif /* !CONFIG_MTD_UBI_DEBUG */
|
||||
#endif /* !__UBI_DEBUG_H__ */
|
||||
|
|
|
@ -341,7 +341,7 @@ int ubi_eba_unmap_leb(struct ubi_device *ubi, struct ubi_volume *vol,
|
|||
dbg_eba("erase LEB %d:%d, PEB %d", vol_id, lnum, pnum);
|
||||
|
||||
vol->eba_tbl[lnum] = UBI_LEB_UNMAPPED;
|
||||
err = ubi_wl_put_peb(ubi, pnum, 0);
|
||||
err = ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 0);
|
||||
|
||||
out_unlock:
|
||||
leb_write_unlock(ubi, vol_id, lnum);
|
||||
|
@ -507,7 +507,7 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum,
|
|||
return -ENOMEM;
|
||||
|
||||
retry:
|
||||
new_pnum = ubi_wl_get_peb(ubi, UBI_UNKNOWN);
|
||||
new_pnum = ubi_wl_get_peb(ubi);
|
||||
if (new_pnum < 0) {
|
||||
ubi_free_vid_hdr(ubi, vid_hdr);
|
||||
return new_pnum;
|
||||
|
@ -550,7 +550,7 @@ retry:
|
|||
ubi_free_vid_hdr(ubi, vid_hdr);
|
||||
|
||||
vol->eba_tbl[lnum] = new_pnum;
|
||||
ubi_wl_put_peb(ubi, pnum, 1);
|
||||
ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 1);
|
||||
|
||||
ubi_msg("data was successfully recovered");
|
||||
return 0;
|
||||
|
@ -558,7 +558,7 @@ retry:
|
|||
out_unlock:
|
||||
mutex_unlock(&ubi->buf_mutex);
|
||||
out_put:
|
||||
ubi_wl_put_peb(ubi, new_pnum, 1);
|
||||
ubi_wl_put_peb(ubi, vol_id, lnum, new_pnum, 1);
|
||||
ubi_free_vid_hdr(ubi, vid_hdr);
|
||||
return err;
|
||||
|
||||
|
@ -568,7 +568,7 @@ write_error:
|
|||
* get another one.
|
||||
*/
|
||||
ubi_warn("failed to write to PEB %d", new_pnum);
|
||||
ubi_wl_put_peb(ubi, new_pnum, 1);
|
||||
ubi_wl_put_peb(ubi, vol_id, lnum, new_pnum, 1);
|
||||
if (++tries > UBI_IO_RETRIES) {
|
||||
ubi_free_vid_hdr(ubi, vid_hdr);
|
||||
return err;
|
||||
|
@ -585,7 +585,6 @@ write_error:
|
|||
* @buf: the data to write
|
||||
* @offset: offset within the logical eraseblock where to write
|
||||
* @len: how many bytes to write
|
||||
* @dtype: data type
|
||||
*
|
||||
* This function writes data to logical eraseblock @lnum of a dynamic volume
|
||||
* @vol. Returns zero in case of success and a negative error code in case
|
||||
|
@ -593,7 +592,7 @@ write_error:
|
|||
* written to the flash media, but may be some garbage.
|
||||
*/
|
||||
int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
|
||||
const void *buf, int offset, int len, int dtype)
|
||||
const void *buf, int offset, int len)
|
||||
{
|
||||
int err, pnum, tries = 0, vol_id = vol->vol_id;
|
||||
struct ubi_vid_hdr *vid_hdr;
|
||||
|
@ -641,7 +640,7 @@ int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
|
|||
vid_hdr->data_pad = cpu_to_be32(vol->data_pad);
|
||||
|
||||
retry:
|
||||
pnum = ubi_wl_get_peb(ubi, dtype);
|
||||
pnum = ubi_wl_get_peb(ubi);
|
||||
if (pnum < 0) {
|
||||
ubi_free_vid_hdr(ubi, vid_hdr);
|
||||
leb_write_unlock(ubi, vol_id, lnum);
|
||||
|
@ -687,7 +686,7 @@ write_error:
|
|||
* eraseblock, so just put it and request a new one. We assume that if
|
||||
* this physical eraseblock went bad, the erase code will handle that.
|
||||
*/
|
||||
err = ubi_wl_put_peb(ubi, pnum, 1);
|
||||
err = ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 1);
|
||||
if (err || ++tries > UBI_IO_RETRIES) {
|
||||
ubi_ro_mode(ubi);
|
||||
leb_write_unlock(ubi, vol_id, lnum);
|
||||
|
@ -707,7 +706,6 @@ write_error:
|
|||
* @lnum: logical eraseblock number
|
||||
* @buf: data to write
|
||||
* @len: how many bytes to write
|
||||
* @dtype: data type
|
||||
* @used_ebs: how many logical eraseblocks will this volume contain
|
||||
*
|
||||
* This function writes data to logical eraseblock @lnum of static volume
|
||||
|
@ -724,8 +722,7 @@ write_error:
|
|||
* code in case of failure.
|
||||
*/
|
||||
int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol,
|
||||
int lnum, const void *buf, int len, int dtype,
|
||||
int used_ebs)
|
||||
int lnum, const void *buf, int len, int used_ebs)
|
||||
{
|
||||
int err, pnum, tries = 0, data_size = len, vol_id = vol->vol_id;
|
||||
struct ubi_vid_hdr *vid_hdr;
|
||||
|
@ -763,7 +760,7 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol,
|
|||
vid_hdr->data_crc = cpu_to_be32(crc);
|
||||
|
||||
retry:
|
||||
pnum = ubi_wl_get_peb(ubi, dtype);
|
||||
pnum = ubi_wl_get_peb(ubi);
|
||||
if (pnum < 0) {
|
||||
ubi_free_vid_hdr(ubi, vid_hdr);
|
||||
leb_write_unlock(ubi, vol_id, lnum);
|
||||
|
@ -807,7 +804,7 @@ write_error:
|
|||
return err;
|
||||
}
|
||||
|
||||
err = ubi_wl_put_peb(ubi, pnum, 1);
|
||||
err = ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 1);
|
||||
if (err || ++tries > UBI_IO_RETRIES) {
|
||||
ubi_ro_mode(ubi);
|
||||
leb_write_unlock(ubi, vol_id, lnum);
|
||||
|
@ -827,7 +824,6 @@ write_error:
|
|||
* @lnum: logical eraseblock number
|
||||
* @buf: data to write
|
||||
* @len: how many bytes to write
|
||||
* @dtype: data type
|
||||
*
|
||||
* This function changes the contents of a logical eraseblock atomically. @buf
|
||||
* has to contain new logical eraseblock data, and @len - the length of the
|
||||
|
@ -839,7 +835,7 @@ write_error:
|
|||
* LEB change may be done at a time. This is ensured by @ubi->alc_mutex.
|
||||
*/
|
||||
int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
|
||||
int lnum, const void *buf, int len, int dtype)
|
||||
int lnum, const void *buf, int len)
|
||||
{
|
||||
int err, pnum, tries = 0, vol_id = vol->vol_id;
|
||||
struct ubi_vid_hdr *vid_hdr;
|
||||
|
@ -856,7 +852,7 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
|
|||
err = ubi_eba_unmap_leb(ubi, vol, lnum);
|
||||
if (err)
|
||||
return err;
|
||||
return ubi_eba_write_leb(ubi, vol, lnum, NULL, 0, 0, dtype);
|
||||
return ubi_eba_write_leb(ubi, vol, lnum, NULL, 0, 0);
|
||||
}
|
||||
|
||||
vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
|
||||
|
@ -881,7 +877,7 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
|
|||
vid_hdr->data_crc = cpu_to_be32(crc);
|
||||
|
||||
retry:
|
||||
pnum = ubi_wl_get_peb(ubi, dtype);
|
||||
pnum = ubi_wl_get_peb(ubi);
|
||||
if (pnum < 0) {
|
||||
err = pnum;
|
||||
goto out_leb_unlock;
|
||||
|
@ -905,7 +901,7 @@ retry:
|
|||
}
|
||||
|
||||
if (vol->eba_tbl[lnum] >= 0) {
|
||||
err = ubi_wl_put_peb(ubi, vol->eba_tbl[lnum], 0);
|
||||
err = ubi_wl_put_peb(ubi, vol_id, lnum, vol->eba_tbl[lnum], 0);
|
||||
if (err)
|
||||
goto out_leb_unlock;
|
||||
}
|
||||
|
@ -930,7 +926,7 @@ write_error:
|
|||
goto out_leb_unlock;
|
||||
}
|
||||
|
||||
err = ubi_wl_put_peb(ubi, pnum, 1);
|
||||
err = ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 1);
|
||||
if (err || ++tries > UBI_IO_RETRIES) {
|
||||
ubi_ro_mode(ubi);
|
||||
goto out_leb_unlock;
|
||||
|
@ -1171,7 +1167,7 @@ out_unlock_leb:
|
|||
* print_rsvd_warning - warn about not having enough reserved PEBs.
|
||||
* @ubi: UBI device description object
|
||||
*
|
||||
* This is a helper function for 'ubi_eba_init_scan()' which is called when UBI
|
||||
* This is a helper function for 'ubi_eba_init()' which is called when UBI
|
||||
* cannot reserve enough PEBs for bad block handling. This function makes a
|
||||
* decision whether we have to print a warning or not. The algorithm is as
|
||||
* follows:
|
||||
|
@ -1186,13 +1182,13 @@ out_unlock_leb:
|
|||
* reported by real users.
|
||||
*/
|
||||
static void print_rsvd_warning(struct ubi_device *ubi,
|
||||
struct ubi_scan_info *si)
|
||||
struct ubi_attach_info *ai)
|
||||
{
|
||||
/*
|
||||
* The 1 << 18 (256KiB) number is picked randomly, just a reasonably
|
||||
* large number to distinguish between newly flashed and used images.
|
||||
*/
|
||||
if (si->max_sqnum > (1 << 18)) {
|
||||
if (ai->max_sqnum > (1 << 18)) {
|
||||
int min = ubi->beb_rsvd_level / 10;
|
||||
|
||||
if (!min)
|
||||
|
@ -1209,19 +1205,19 @@ static void print_rsvd_warning(struct ubi_device *ubi,
|
|||
}
|
||||
|
||||
/**
|
||||
* ubi_eba_init_scan - initialize the EBA sub-system using scanning information.
|
||||
* ubi_eba_init - initialize the EBA sub-system using attaching information.
|
||||
* @ubi: UBI device description object
|
||||
* @si: scanning information
|
||||
* @ai: attaching information
|
||||
*
|
||||
* This function returns zero in case of success and a negative error code in
|
||||
* case of failure.
|
||||
*/
|
||||
int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
|
||||
int ubi_eba_init(struct ubi_device *ubi, struct ubi_attach_info *ai)
|
||||
{
|
||||
int i, j, err, num_volumes;
|
||||
struct ubi_scan_volume *sv;
|
||||
struct ubi_ainf_volume *av;
|
||||
struct ubi_volume *vol;
|
||||
struct ubi_scan_leb *seb;
|
||||
struct ubi_ainf_peb *aeb;
|
||||
struct rb_node *rb;
|
||||
|
||||
dbg_eba("initialize EBA sub-system");
|
||||
|
@ -1230,7 +1226,7 @@ int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
|
|||
mutex_init(&ubi->alc_mutex);
|
||||
ubi->ltree = RB_ROOT;
|
||||
|
||||
ubi->global_sqnum = si->max_sqnum + 1;
|
||||
ubi->global_sqnum = ai->max_sqnum + 1;
|
||||
num_volumes = ubi->vtbl_slots + UBI_INT_VOL_COUNT;
|
||||
|
||||
for (i = 0; i < num_volumes; i++) {
|
||||
|
@ -1250,18 +1246,18 @@ int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
|
|||
for (j = 0; j < vol->reserved_pebs; j++)
|
||||
vol->eba_tbl[j] = UBI_LEB_UNMAPPED;
|
||||
|
||||
sv = ubi_scan_find_sv(si, idx2vol_id(ubi, i));
|
||||
if (!sv)
|
||||
av = ubi_find_av(ai, idx2vol_id(ubi, i));
|
||||
if (!av)
|
||||
continue;
|
||||
|
||||
ubi_rb_for_each_entry(rb, seb, &sv->root, u.rb) {
|
||||
if (seb->lnum >= vol->reserved_pebs)
|
||||
ubi_rb_for_each_entry(rb, aeb, &av->root, u.rb) {
|
||||
if (aeb->lnum >= vol->reserved_pebs)
|
||||
/*
|
||||
* This may happen in case of an unclean reboot
|
||||
* during re-size.
|
||||
*/
|
||||
ubi_scan_move_to_list(sv, seb, &si->erase);
|
||||
vol->eba_tbl[seb->lnum] = seb->pnum;
|
||||
ubi_move_aeb_to_list(av, aeb, &ai->erase);
|
||||
vol->eba_tbl[aeb->lnum] = aeb->pnum;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1283,7 +1279,7 @@ int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
|
|||
if (ubi->avail_pebs < ubi->beb_rsvd_level) {
|
||||
/* No enough free physical eraseblocks */
|
||||
ubi->beb_rsvd_pebs = ubi->avail_pebs;
|
||||
print_rsvd_warning(ubi, si);
|
||||
print_rsvd_warning(ubi, ai);
|
||||
} else
|
||||
ubi->beb_rsvd_pebs = ubi->beb_rsvd_level;
|
||||
|
||||
|
|
|
@ -227,7 +227,7 @@ static int gluebi_write(struct mtd_info *mtd, loff_t to, size_t len,
|
|||
if (to_write > total_written)
|
||||
to_write = total_written;
|
||||
|
||||
err = ubi_write(gluebi->desc, lnum, buf, offs, to_write);
|
||||
err = ubi_leb_write(gluebi->desc, lnum, buf, offs, to_write);
|
||||
if (err)
|
||||
break;
|
||||
|
||||
|
|
|
@ -91,21 +91,15 @@
|
|||
#include <linux/slab.h>
|
||||
#include "ubi.h"
|
||||
|
||||
#ifdef CONFIG_MTD_UBI_DEBUG
|
||||
static int paranoid_check_not_bad(const struct ubi_device *ubi, int pnum);
|
||||
static int paranoid_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum);
|
||||
static int paranoid_check_ec_hdr(const struct ubi_device *ubi, int pnum,
|
||||
const struct ubi_ec_hdr *ec_hdr);
|
||||
static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum);
|
||||
static int paranoid_check_vid_hdr(const struct ubi_device *ubi, int pnum,
|
||||
const struct ubi_vid_hdr *vid_hdr);
|
||||
#else
|
||||
#define paranoid_check_not_bad(ubi, pnum) 0
|
||||
#define paranoid_check_peb_ec_hdr(ubi, pnum) 0
|
||||
#define paranoid_check_ec_hdr(ubi, pnum, ec_hdr) 0
|
||||
#define paranoid_check_peb_vid_hdr(ubi, pnum) 0
|
||||
#define paranoid_check_vid_hdr(ubi, pnum, vid_hdr) 0
|
||||
#endif
|
||||
static int self_check_not_bad(const struct ubi_device *ubi, int pnum);
|
||||
static int self_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum);
|
||||
static int self_check_ec_hdr(const struct ubi_device *ubi, int pnum,
|
||||
const struct ubi_ec_hdr *ec_hdr);
|
||||
static int self_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum);
|
||||
static int self_check_vid_hdr(const struct ubi_device *ubi, int pnum,
|
||||
const struct ubi_vid_hdr *vid_hdr);
|
||||
static int self_check_write(struct ubi_device *ubi, const void *buf, int pnum,
|
||||
int offset, int len);
|
||||
|
||||
/**
|
||||
* ubi_io_read - read data from a physical eraseblock.
|
||||
|
@ -142,7 +136,7 @@ int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset,
|
|||
ubi_assert(offset >= 0 && offset + len <= ubi->peb_size);
|
||||
ubi_assert(len > 0);
|
||||
|
||||
err = paranoid_check_not_bad(ubi, pnum);
|
||||
err = self_check_not_bad(ubi, pnum);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -189,16 +183,16 @@ retry:
|
|||
}
|
||||
|
||||
if (retries++ < UBI_IO_RETRIES) {
|
||||
dbg_io("error %d%s while reading %d bytes from PEB "
|
||||
"%d:%d, read only %zd bytes, retry",
|
||||
err, errstr, len, pnum, offset, read);
|
||||
ubi_warn("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("error %d%s while reading %d bytes from PEB %d:%d, "
|
||||
"read %zd bytes", err, errstr, len, pnum, offset, read);
|
||||
ubi_dbg_dump_stack();
|
||||
dump_stack();
|
||||
|
||||
/*
|
||||
* The driver should never return -EBADMSG if it failed to read
|
||||
|
@ -257,14 +251,12 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset,
|
|||
return -EROFS;
|
||||
}
|
||||
|
||||
/* The below has to be compiled out if paranoid checks are disabled */
|
||||
|
||||
err = paranoid_check_not_bad(ubi, pnum);
|
||||
err = self_check_not_bad(ubi, pnum);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* The area we are writing to has to contain all 0xFF bytes */
|
||||
err = ubi_dbg_check_all_ff(ubi, pnum, offset, len);
|
||||
err = ubi_self_check_all_ff(ubi, pnum, offset, len);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -273,18 +265,18 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset,
|
|||
* We write to the data area of the physical eraseblock. Make
|
||||
* sure it has valid EC and VID headers.
|
||||
*/
|
||||
err = paranoid_check_peb_ec_hdr(ubi, pnum);
|
||||
err = self_check_peb_ec_hdr(ubi, pnum);
|
||||
if (err)
|
||||
return err;
|
||||
err = paranoid_check_peb_vid_hdr(ubi, pnum);
|
||||
err = self_check_peb_vid_hdr(ubi, pnum);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (ubi_dbg_is_write_failure(ubi)) {
|
||||
dbg_err("cannot write %d bytes to PEB %d:%d "
|
||||
ubi_err("cannot write %d bytes to PEB %d:%d "
|
||||
"(emulated)", len, pnum, offset);
|
||||
ubi_dbg_dump_stack();
|
||||
dump_stack();
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
@ -293,13 +285,13 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset,
|
|||
if (err) {
|
||||
ubi_err("error %d while writing %d bytes to PEB %d:%d, written "
|
||||
"%zd bytes", err, len, pnum, offset, written);
|
||||
ubi_dbg_dump_stack();
|
||||
ubi_dbg_dump_flash(ubi, pnum, offset, len);
|
||||
dump_stack();
|
||||
ubi_dump_flash(ubi, pnum, offset, len);
|
||||
} else
|
||||
ubi_assert(written == len);
|
||||
|
||||
if (!err) {
|
||||
err = ubi_dbg_check_write(ubi, buf, pnum, offset, len);
|
||||
err = self_check_write(ubi, buf, pnum, offset, len);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -310,7 +302,7 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset,
|
|||
offset += len;
|
||||
len = ubi->peb_size - offset;
|
||||
if (len)
|
||||
err = ubi_dbg_check_all_ff(ubi, pnum, offset, len);
|
||||
err = ubi_self_check_all_ff(ubi, pnum, offset, len);
|
||||
}
|
||||
|
||||
return err;
|
||||
|
@ -364,13 +356,13 @@ retry:
|
|||
err = mtd_erase(ubi->mtd, &ei);
|
||||
if (err) {
|
||||
if (retries++ < UBI_IO_RETRIES) {
|
||||
dbg_io("error %d while erasing PEB %d, retry",
|
||||
err, pnum);
|
||||
ubi_warn("error %d while erasing PEB %d, retry",
|
||||
err, pnum);
|
||||
yield();
|
||||
goto retry;
|
||||
}
|
||||
ubi_err("cannot erase PEB %d, error %d", pnum, err);
|
||||
ubi_dbg_dump_stack();
|
||||
dump_stack();
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -383,21 +375,21 @@ retry:
|
|||
|
||||
if (ei.state == MTD_ERASE_FAILED) {
|
||||
if (retries++ < UBI_IO_RETRIES) {
|
||||
dbg_io("error while erasing PEB %d, retry", pnum);
|
||||
ubi_warn("error while erasing PEB %d, retry", pnum);
|
||||
yield();
|
||||
goto retry;
|
||||
}
|
||||
ubi_err("cannot erase PEB %d", pnum);
|
||||
ubi_dbg_dump_stack();
|
||||
dump_stack();
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
err = ubi_dbg_check_all_ff(ubi, pnum, 0, ubi->peb_size);
|
||||
err = ubi_self_check_all_ff(ubi, pnum, 0, ubi->peb_size);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (ubi_dbg_is_erase_failure(ubi)) {
|
||||
dbg_err("cannot erase PEB %d (emulated)", pnum);
|
||||
ubi_err("cannot erase PEB %d (emulated)", pnum);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
@ -521,8 +513,7 @@ static int nor_erase_prepare(struct ubi_device *ubi, int pnum)
|
|||
* It is important to first invalidate the EC header, and then the VID
|
||||
* header. Otherwise a power cut may lead to valid EC header and
|
||||
* invalid VID header, in which case UBI will treat this PEB as
|
||||
* corrupted and will try to preserve it, and print scary warnings (see
|
||||
* the header comment in scan.c for more information).
|
||||
* corrupted and will try to preserve it, and print scary warnings.
|
||||
*/
|
||||
addr = (loff_t)pnum * ubi->peb_size;
|
||||
err = mtd_write(ubi->mtd, addr, 4, &written, (void *)&data);
|
||||
|
@ -563,7 +554,7 @@ static int nor_erase_prepare(struct ubi_device *ubi, int pnum)
|
|||
*/
|
||||
ubi_err("cannot invalidate PEB %d, write returned %d read returned %d",
|
||||
pnum, err, err1);
|
||||
ubi_dbg_dump_flash(ubi, pnum, 0, ubi->peb_size);
|
||||
ubi_dump_flash(ubi, pnum, 0, ubi->peb_size);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
@ -589,7 +580,7 @@ int ubi_io_sync_erase(struct ubi_device *ubi, int pnum, int torture)
|
|||
|
||||
ubi_assert(pnum >= 0 && pnum < ubi->peb_count);
|
||||
|
||||
err = paranoid_check_not_bad(ubi, pnum);
|
||||
err = self_check_not_bad(ubi, pnum);
|
||||
if (err != 0)
|
||||
return err;
|
||||
|
||||
|
@ -721,8 +712,8 @@ static int validate_ec_hdr(const struct ubi_device *ubi,
|
|||
|
||||
bad:
|
||||
ubi_err("bad EC header");
|
||||
ubi_dbg_dump_ec_hdr(ec_hdr);
|
||||
ubi_dbg_dump_stack();
|
||||
ubi_dump_ec_hdr(ec_hdr);
|
||||
dump_stack();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -803,7 +794,7 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
|
|||
if (verbose) {
|
||||
ubi_warn("bad magic number at PEB %d: %08x instead of "
|
||||
"%08x", pnum, magic, UBI_EC_HDR_MAGIC);
|
||||
ubi_dbg_dump_ec_hdr(ec_hdr);
|
||||
ubi_dump_ec_hdr(ec_hdr);
|
||||
}
|
||||
dbg_bld("bad magic number at PEB %d: %08x instead of "
|
||||
"%08x", pnum, magic, UBI_EC_HDR_MAGIC);
|
||||
|
@ -817,7 +808,7 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
|
|||
if (verbose) {
|
||||
ubi_warn("bad EC header CRC at PEB %d, calculated "
|
||||
"%#08x, read %#08x", pnum, crc, hdr_crc);
|
||||
ubi_dbg_dump_ec_hdr(ec_hdr);
|
||||
ubi_dump_ec_hdr(ec_hdr);
|
||||
}
|
||||
dbg_bld("bad EC header CRC at PEB %d, calculated "
|
||||
"%#08x, read %#08x", pnum, crc, hdr_crc);
|
||||
|
@ -874,7 +865,7 @@ int ubi_io_write_ec_hdr(struct ubi_device *ubi, int pnum,
|
|||
crc = crc32(UBI_CRC32_INIT, ec_hdr, UBI_EC_HDR_SIZE_CRC);
|
||||
ec_hdr->hdr_crc = cpu_to_be32(crc);
|
||||
|
||||
err = paranoid_check_ec_hdr(ubi, pnum, ec_hdr);
|
||||
err = self_check_ec_hdr(ubi, pnum, ec_hdr);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -905,40 +896,40 @@ static int validate_vid_hdr(const struct ubi_device *ubi,
|
|||
int usable_leb_size = ubi->leb_size - data_pad;
|
||||
|
||||
if (copy_flag != 0 && copy_flag != 1) {
|
||||
dbg_err("bad copy_flag");
|
||||
ubi_err("bad copy_flag");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (vol_id < 0 || lnum < 0 || data_size < 0 || used_ebs < 0 ||
|
||||
data_pad < 0) {
|
||||
dbg_err("negative values");
|
||||
ubi_err("negative values");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (vol_id >= UBI_MAX_VOLUMES && vol_id < UBI_INTERNAL_VOL_START) {
|
||||
dbg_err("bad vol_id");
|
||||
ubi_err("bad vol_id");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (vol_id < UBI_INTERNAL_VOL_START && compat != 0) {
|
||||
dbg_err("bad compat");
|
||||
ubi_err("bad compat");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (vol_id >= UBI_INTERNAL_VOL_START && compat != UBI_COMPAT_DELETE &&
|
||||
compat != UBI_COMPAT_RO && compat != UBI_COMPAT_PRESERVE &&
|
||||
compat != UBI_COMPAT_REJECT) {
|
||||
dbg_err("bad compat");
|
||||
ubi_err("bad compat");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (vol_type != UBI_VID_DYNAMIC && vol_type != UBI_VID_STATIC) {
|
||||
dbg_err("bad vol_type");
|
||||
ubi_err("bad vol_type");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (data_pad >= ubi->leb_size / 2) {
|
||||
dbg_err("bad data_pad");
|
||||
ubi_err("bad data_pad");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
|
@ -950,45 +941,45 @@ static int validate_vid_hdr(const struct ubi_device *ubi,
|
|||
* mapped logical eraseblocks.
|
||||
*/
|
||||
if (used_ebs == 0) {
|
||||
dbg_err("zero used_ebs");
|
||||
ubi_err("zero used_ebs");
|
||||
goto bad;
|
||||
}
|
||||
if (data_size == 0) {
|
||||
dbg_err("zero data_size");
|
||||
ubi_err("zero data_size");
|
||||
goto bad;
|
||||
}
|
||||
if (lnum < used_ebs - 1) {
|
||||
if (data_size != usable_leb_size) {
|
||||
dbg_err("bad data_size");
|
||||
ubi_err("bad data_size");
|
||||
goto bad;
|
||||
}
|
||||
} else if (lnum == used_ebs - 1) {
|
||||
if (data_size == 0) {
|
||||
dbg_err("bad data_size at last LEB");
|
||||
ubi_err("bad data_size at last LEB");
|
||||
goto bad;
|
||||
}
|
||||
} else {
|
||||
dbg_err("too high lnum");
|
||||
ubi_err("too high lnum");
|
||||
goto bad;
|
||||
}
|
||||
} else {
|
||||
if (copy_flag == 0) {
|
||||
if (data_crc != 0) {
|
||||
dbg_err("non-zero data CRC");
|
||||
ubi_err("non-zero data CRC");
|
||||
goto bad;
|
||||
}
|
||||
if (data_size != 0) {
|
||||
dbg_err("non-zero data_size");
|
||||
ubi_err("non-zero data_size");
|
||||
goto bad;
|
||||
}
|
||||
} else {
|
||||
if (data_size == 0) {
|
||||
dbg_err("zero data_size of copy");
|
||||
ubi_err("zero data_size of copy");
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
if (used_ebs != 0) {
|
||||
dbg_err("bad used_ebs");
|
||||
ubi_err("bad used_ebs");
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
|
@ -997,8 +988,8 @@ static int validate_vid_hdr(const struct ubi_device *ubi,
|
|||
|
||||
bad:
|
||||
ubi_err("bad VID header");
|
||||
ubi_dbg_dump_vid_hdr(vid_hdr);
|
||||
ubi_dbg_dump_stack();
|
||||
ubi_dump_vid_hdr(vid_hdr);
|
||||
dump_stack();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1054,7 +1045,7 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
|
|||
if (verbose) {
|
||||
ubi_warn("bad magic number at PEB %d: %08x instead of "
|
||||
"%08x", pnum, magic, UBI_VID_HDR_MAGIC);
|
||||
ubi_dbg_dump_vid_hdr(vid_hdr);
|
||||
ubi_dump_vid_hdr(vid_hdr);
|
||||
}
|
||||
dbg_bld("bad magic number at PEB %d: %08x instead of "
|
||||
"%08x", pnum, magic, UBI_VID_HDR_MAGIC);
|
||||
|
@ -1068,7 +1059,7 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
|
|||
if (verbose) {
|
||||
ubi_warn("bad CRC at PEB %d, calculated %#08x, "
|
||||
"read %#08x", pnum, crc, hdr_crc);
|
||||
ubi_dbg_dump_vid_hdr(vid_hdr);
|
||||
ubi_dump_vid_hdr(vid_hdr);
|
||||
}
|
||||
dbg_bld("bad CRC at PEB %d, calculated %#08x, "
|
||||
"read %#08x", pnum, crc, hdr_crc);
|
||||
|
@ -1112,7 +1103,7 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum,
|
|||
dbg_io("write VID header to PEB %d", pnum);
|
||||
ubi_assert(pnum >= 0 && pnum < ubi->peb_count);
|
||||
|
||||
err = paranoid_check_peb_ec_hdr(ubi, pnum);
|
||||
err = self_check_peb_ec_hdr(ubi, pnum);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -1121,7 +1112,7 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum,
|
|||
crc = crc32(UBI_CRC32_INIT, vid_hdr, UBI_VID_HDR_SIZE_CRC);
|
||||
vid_hdr->hdr_crc = cpu_to_be32(crc);
|
||||
|
||||
err = paranoid_check_vid_hdr(ubi, pnum, vid_hdr);
|
||||
err = self_check_vid_hdr(ubi, pnum, vid_hdr);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -1131,17 +1122,15 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum,
|
|||
return err;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MTD_UBI_DEBUG
|
||||
|
||||
/**
|
||||
* paranoid_check_not_bad - ensure that a physical eraseblock is not bad.
|
||||
* self_check_not_bad - ensure that a physical eraseblock is not bad.
|
||||
* @ubi: UBI device description object
|
||||
* @pnum: physical eraseblock number to check
|
||||
*
|
||||
* This function returns zero if the physical eraseblock is good, %-EINVAL if
|
||||
* it is bad and a negative error code if an error occurred.
|
||||
*/
|
||||
static int paranoid_check_not_bad(const struct ubi_device *ubi, int pnum)
|
||||
static int self_check_not_bad(const struct ubi_device *ubi, int pnum)
|
||||
{
|
||||
int err;
|
||||
|
||||
|
@ -1152,13 +1141,13 @@ static int paranoid_check_not_bad(const struct ubi_device *ubi, int pnum)
|
|||
if (!err)
|
||||
return err;
|
||||
|
||||
ubi_err("paranoid check failed for PEB %d", pnum);
|
||||
ubi_dbg_dump_stack();
|
||||
ubi_err("self-check failed for PEB %d", pnum);
|
||||
dump_stack();
|
||||
return err > 0 ? -EINVAL : err;
|
||||
}
|
||||
|
||||
/**
|
||||
* paranoid_check_ec_hdr - check if an erase counter header is all right.
|
||||
* self_check_ec_hdr - check if an erase counter header is all right.
|
||||
* @ubi: UBI device description object
|
||||
* @pnum: physical eraseblock number the erase counter header belongs to
|
||||
* @ec_hdr: the erase counter header to check
|
||||
|
@ -1166,8 +1155,8 @@ static int paranoid_check_not_bad(const struct ubi_device *ubi, int pnum)
|
|||
* This function returns zero if the erase counter header contains valid
|
||||
* values, and %-EINVAL if not.
|
||||
*/
|
||||
static int paranoid_check_ec_hdr(const struct ubi_device *ubi, int pnum,
|
||||
const struct ubi_ec_hdr *ec_hdr)
|
||||
static int self_check_ec_hdr(const struct ubi_device *ubi, int pnum,
|
||||
const struct ubi_ec_hdr *ec_hdr)
|
||||
{
|
||||
int err;
|
||||
uint32_t magic;
|
||||
|
@ -1184,27 +1173,27 @@ static int paranoid_check_ec_hdr(const struct ubi_device *ubi, int pnum,
|
|||
|
||||
err = validate_ec_hdr(ubi, ec_hdr);
|
||||
if (err) {
|
||||
ubi_err("paranoid check failed for PEB %d", pnum);
|
||||
ubi_err("self-check failed for PEB %d", pnum);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
ubi_dbg_dump_ec_hdr(ec_hdr);
|
||||
ubi_dbg_dump_stack();
|
||||
ubi_dump_ec_hdr(ec_hdr);
|
||||
dump_stack();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* paranoid_check_peb_ec_hdr - check erase counter header.
|
||||
* self_check_peb_ec_hdr - check erase counter header.
|
||||
* @ubi: UBI device description object
|
||||
* @pnum: the physical eraseblock number to check
|
||||
*
|
||||
* This function returns zero if the erase counter header is all right and and
|
||||
* a negative error code if not or if an error occurred.
|
||||
*/
|
||||
static int paranoid_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum)
|
||||
static int self_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum)
|
||||
{
|
||||
int err;
|
||||
uint32_t crc, hdr_crc;
|
||||
|
@ -1225,14 +1214,14 @@ static int paranoid_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum)
|
|||
hdr_crc = be32_to_cpu(ec_hdr->hdr_crc);
|
||||
if (hdr_crc != crc) {
|
||||
ubi_err("bad CRC, calculated %#08x, read %#08x", crc, hdr_crc);
|
||||
ubi_err("paranoid check failed for PEB %d", pnum);
|
||||
ubi_dbg_dump_ec_hdr(ec_hdr);
|
||||
ubi_dbg_dump_stack();
|
||||
ubi_err("self-check failed for PEB %d", pnum);
|
||||
ubi_dump_ec_hdr(ec_hdr);
|
||||
dump_stack();
|
||||
err = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
err = paranoid_check_ec_hdr(ubi, pnum, ec_hdr);
|
||||
err = self_check_ec_hdr(ubi, pnum, ec_hdr);
|
||||
|
||||
exit:
|
||||
kfree(ec_hdr);
|
||||
|
@ -1240,7 +1229,7 @@ exit:
|
|||
}
|
||||
|
||||
/**
|
||||
* paranoid_check_vid_hdr - check that a volume identifier header is all right.
|
||||
* self_check_vid_hdr - check that a volume identifier header is all right.
|
||||
* @ubi: UBI device description object
|
||||
* @pnum: physical eraseblock number the volume identifier header belongs to
|
||||
* @vid_hdr: the volume identifier header to check
|
||||
|
@ -1248,8 +1237,8 @@ exit:
|
|||
* This function returns zero if the volume identifier header is all right, and
|
||||
* %-EINVAL if not.
|
||||
*/
|
||||
static int paranoid_check_vid_hdr(const struct ubi_device *ubi, int pnum,
|
||||
const struct ubi_vid_hdr *vid_hdr)
|
||||
static int self_check_vid_hdr(const struct ubi_device *ubi, int pnum,
|
||||
const struct ubi_vid_hdr *vid_hdr)
|
||||
{
|
||||
int err;
|
||||
uint32_t magic;
|
||||
|
@ -1266,29 +1255,29 @@ static int paranoid_check_vid_hdr(const struct ubi_device *ubi, int pnum,
|
|||
|
||||
err = validate_vid_hdr(ubi, vid_hdr);
|
||||
if (err) {
|
||||
ubi_err("paranoid check failed for PEB %d", pnum);
|
||||
ubi_err("self-check failed for PEB %d", pnum);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return err;
|
||||
|
||||
fail:
|
||||
ubi_err("paranoid check failed for PEB %d", pnum);
|
||||
ubi_dbg_dump_vid_hdr(vid_hdr);
|
||||
ubi_dbg_dump_stack();
|
||||
ubi_err("self-check failed for PEB %d", pnum);
|
||||
ubi_dump_vid_hdr(vid_hdr);
|
||||
dump_stack();
|
||||
return -EINVAL;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* paranoid_check_peb_vid_hdr - check volume identifier header.
|
||||
* self_check_peb_vid_hdr - check volume identifier header.
|
||||
* @ubi: UBI device description object
|
||||
* @pnum: the physical eraseblock number to check
|
||||
*
|
||||
* This function returns zero if the volume identifier header is all right,
|
||||
* and a negative error code if not or if an error occurred.
|
||||
*/
|
||||
static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum)
|
||||
static int self_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum)
|
||||
{
|
||||
int err;
|
||||
uint32_t crc, hdr_crc;
|
||||
|
@ -1313,14 +1302,14 @@ static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum)
|
|||
if (hdr_crc != crc) {
|
||||
ubi_err("bad VID header CRC at PEB %d, calculated %#08x, "
|
||||
"read %#08x", pnum, crc, hdr_crc);
|
||||
ubi_err("paranoid check failed for PEB %d", pnum);
|
||||
ubi_dbg_dump_vid_hdr(vid_hdr);
|
||||
ubi_dbg_dump_stack();
|
||||
ubi_err("self-check failed for PEB %d", pnum);
|
||||
ubi_dump_vid_hdr(vid_hdr);
|
||||
dump_stack();
|
||||
err = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
err = paranoid_check_vid_hdr(ubi, pnum, vid_hdr);
|
||||
err = self_check_vid_hdr(ubi, pnum, vid_hdr);
|
||||
|
||||
exit:
|
||||
ubi_free_vid_hdr(ubi, vid_hdr);
|
||||
|
@ -1328,7 +1317,7 @@ exit:
|
|||
}
|
||||
|
||||
/**
|
||||
* ubi_dbg_check_write - make sure write succeeded.
|
||||
* self_check_write - make sure write succeeded.
|
||||
* @ubi: UBI device description object
|
||||
* @buf: buffer with data which were written
|
||||
* @pnum: physical eraseblock number the data were written to
|
||||
|
@ -1339,8 +1328,8 @@ exit:
|
|||
* the original data buffer - the data have to match. Returns zero if the data
|
||||
* match and a negative error code if not or in case of failure.
|
||||
*/
|
||||
int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum,
|
||||
int offset, int len)
|
||||
static int self_check_write(struct ubi_device *ubi, const void *buf, int pnum,
|
||||
int offset, int len)
|
||||
{
|
||||
int err, i;
|
||||
size_t read;
|
||||
|
@ -1368,7 +1357,7 @@ int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum,
|
|||
if (c == c1)
|
||||
continue;
|
||||
|
||||
ubi_err("paranoid check failed for PEB %d:%d, len %d",
|
||||
ubi_err("self-check failed for PEB %d:%d, len %d",
|
||||
pnum, offset, len);
|
||||
ubi_msg("data differ at position %d", i);
|
||||
dump_len = max_t(int, 128, len - i);
|
||||
|
@ -1380,7 +1369,7 @@ int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum,
|
|||
i, i + dump_len);
|
||||
print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
|
||||
buf1 + i, dump_len, 1);
|
||||
ubi_dbg_dump_stack();
|
||||
dump_stack();
|
||||
err = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
|
@ -1394,7 +1383,7 @@ out_free:
|
|||
}
|
||||
|
||||
/**
|
||||
* ubi_dbg_check_all_ff - check that a region of flash is empty.
|
||||
* ubi_self_check_all_ff - check that a region of flash is empty.
|
||||
* @ubi: UBI device description object
|
||||
* @pnum: the physical eraseblock number to check
|
||||
* @offset: the starting offset within the physical eraseblock to check
|
||||
|
@ -1404,7 +1393,7 @@ out_free:
|
|||
* @offset of the physical eraseblock @pnum, and a negative error code if not
|
||||
* or if an error occurred.
|
||||
*/
|
||||
int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len)
|
||||
int ubi_self_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len)
|
||||
{
|
||||
size_t read;
|
||||
int err;
|
||||
|
@ -1438,14 +1427,12 @@ int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len)
|
|||
return 0;
|
||||
|
||||
fail:
|
||||
ubi_err("paranoid check failed for PEB %d", pnum);
|
||||
ubi_err("self-check failed for PEB %d", pnum);
|
||||
ubi_msg("hex dump of the %d-%d region", offset, offset + len);
|
||||
print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, buf, len, 1);
|
||||
err = -EINVAL;
|
||||
error:
|
||||
ubi_dbg_dump_stack();
|
||||
dump_stack();
|
||||
vfree(buf);
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_MTD_UBI_DEBUG */
|
||||
|
|
|
@ -221,7 +221,7 @@ out_free:
|
|||
kfree(desc);
|
||||
out_put_ubi:
|
||||
ubi_put_device(ubi);
|
||||
dbg_err("cannot open device %d, volume %d, error %d",
|
||||
ubi_err("cannot open device %d, volume %d, error %d",
|
||||
ubi_num, vol_id, err);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
@ -426,11 +426,9 @@ EXPORT_SYMBOL_GPL(ubi_leb_read);
|
|||
* @buf: data to write
|
||||
* @offset: offset within the logical eraseblock where to write
|
||||
* @len: how many bytes to write
|
||||
* @dtype: expected data type
|
||||
*
|
||||
* This function writes @len bytes of data from @buf to offset @offset of
|
||||
* logical eraseblock @lnum. The @dtype argument describes expected lifetime of
|
||||
* the data.
|
||||
* logical eraseblock @lnum.
|
||||
*
|
||||
* This function takes care of physical eraseblock write failures. If write to
|
||||
* the physical eraseblock write operation fails, the logical eraseblock is
|
||||
|
@ -447,7 +445,7 @@ EXPORT_SYMBOL_GPL(ubi_leb_read);
|
|||
* returns immediately with %-EBADF code.
|
||||
*/
|
||||
int ubi_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
|
||||
int offset, int len, int dtype)
|
||||
int offset, int len)
|
||||
{
|
||||
struct ubi_volume *vol = desc->vol;
|
||||
struct ubi_device *ubi = vol->ubi;
|
||||
|
@ -466,17 +464,13 @@ int ubi_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
|
|||
offset & (ubi->min_io_size - 1) || len & (ubi->min_io_size - 1))
|
||||
return -EINVAL;
|
||||
|
||||
if (dtype != UBI_LONGTERM && dtype != UBI_SHORTTERM &&
|
||||
dtype != UBI_UNKNOWN)
|
||||
return -EINVAL;
|
||||
|
||||
if (vol->upd_marker)
|
||||
return -EBADF;
|
||||
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
return ubi_eba_write_leb(ubi, vol, lnum, buf, offset, len, dtype);
|
||||
return ubi_eba_write_leb(ubi, vol, lnum, buf, offset, len);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ubi_leb_write);
|
||||
|
||||
|
@ -486,7 +480,6 @@ EXPORT_SYMBOL_GPL(ubi_leb_write);
|
|||
* @lnum: logical eraseblock number to change
|
||||
* @buf: data to write
|
||||
* @len: how many bytes to write
|
||||
* @dtype: expected data type
|
||||
*
|
||||
* This function changes the contents of a logical eraseblock atomically. @buf
|
||||
* has to contain new logical eraseblock data, and @len - the length of the
|
||||
|
@ -497,7 +490,7 @@ EXPORT_SYMBOL_GPL(ubi_leb_write);
|
|||
* code in case of failure.
|
||||
*/
|
||||
int ubi_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf,
|
||||
int len, int dtype)
|
||||
int len)
|
||||
{
|
||||
struct ubi_volume *vol = desc->vol;
|
||||
struct ubi_device *ubi = vol->ubi;
|
||||
|
@ -515,17 +508,13 @@ int ubi_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf,
|
|||
len > vol->usable_leb_size || len & (ubi->min_io_size - 1))
|
||||
return -EINVAL;
|
||||
|
||||
if (dtype != UBI_LONGTERM && dtype != UBI_SHORTTERM &&
|
||||
dtype != UBI_UNKNOWN)
|
||||
return -EINVAL;
|
||||
|
||||
if (vol->upd_marker)
|
||||
return -EBADF;
|
||||
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
return ubi_eba_atomic_leb_change(ubi, vol, lnum, buf, len, dtype);
|
||||
return ubi_eba_atomic_leb_change(ubi, vol, lnum, buf, len);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ubi_leb_change);
|
||||
|
||||
|
@ -562,7 +551,7 @@ int ubi_leb_erase(struct ubi_volume_desc *desc, int lnum)
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
return ubi_wl_flush(ubi);
|
||||
return ubi_wl_flush(ubi, vol->vol_id, lnum);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ubi_leb_erase);
|
||||
|
||||
|
@ -626,7 +615,6 @@ EXPORT_SYMBOL_GPL(ubi_leb_unmap);
|
|||
* ubi_leb_map - map logical eraseblock to a physical eraseblock.
|
||||
* @desc: volume descriptor
|
||||
* @lnum: logical eraseblock number
|
||||
* @dtype: expected data type
|
||||
*
|
||||
* This function maps an un-mapped logical eraseblock @lnum to a physical
|
||||
* eraseblock. This means, that after a successful invocation of this
|
||||
|
@ -639,7 +627,7 @@ EXPORT_SYMBOL_GPL(ubi_leb_unmap);
|
|||
* 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, int dtype)
|
||||
int ubi_leb_map(struct ubi_volume_desc *desc, int lnum)
|
||||
{
|
||||
struct ubi_volume *vol = desc->vol;
|
||||
struct ubi_device *ubi = vol->ubi;
|
||||
|
@ -652,17 +640,13 @@ int ubi_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype)
|
|||
if (lnum < 0 || lnum >= vol->reserved_pebs)
|
||||
return -EINVAL;
|
||||
|
||||
if (dtype != UBI_LONGTERM && dtype != UBI_SHORTTERM &&
|
||||
dtype != UBI_UNKNOWN)
|
||||
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, dtype);
|
||||
return ubi_eba_write_leb(ubi, vol, lnum, NULL, 0, 0);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ubi_leb_map);
|
||||
|
||||
|
@ -720,6 +704,33 @@ int ubi_sync(int ubi_num)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(ubi_sync);
|
||||
|
||||
/**
|
||||
* ubi_flush - flush UBI work queue.
|
||||
* @ubi_num: UBI device to flush work queue
|
||||
* @vol_id: volume id to flush for
|
||||
* @lnum: logical eraseblock number to flush for
|
||||
*
|
||||
* This function executes all pending works for a particular volume id / logical
|
||||
* eraseblock number pair. If either value is set to %UBI_ALL, then it acts as
|
||||
* a wildcard for all of the corresponding volume numbers or logical
|
||||
* eraseblock numbers. It returns zero in case of success and a negative error
|
||||
* code in case of failure.
|
||||
*/
|
||||
int ubi_flush(int ubi_num, int vol_id, int lnum)
|
||||
{
|
||||
struct ubi_device *ubi;
|
||||
int err = 0;
|
||||
|
||||
ubi = ubi_get_device(ubi_num);
|
||||
if (!ubi)
|
||||
return -ENODEV;
|
||||
|
||||
err = ubi_wl_flush(ubi, vol_id, lnum);
|
||||
ubi_put_device(ubi);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ubi_flush);
|
||||
|
||||
BLOCKING_NOTIFIER_HEAD(ubi_notifiers);
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,174 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) International Business Machines Corp., 2006
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
|
||||
* the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Artem Bityutskiy (Битюцкий Артём)
|
||||
*/
|
||||
|
||||
#ifndef __UBI_SCAN_H__
|
||||
#define __UBI_SCAN_H__
|
||||
|
||||
/* The erase counter value for this physical eraseblock is unknown */
|
||||
#define UBI_SCAN_UNKNOWN_EC (-1)
|
||||
|
||||
/**
|
||||
* struct ubi_scan_leb - scanning information about a physical eraseblock.
|
||||
* @ec: erase counter (%UBI_SCAN_UNKNOWN_EC if it is unknown)
|
||||
* @pnum: physical eraseblock number
|
||||
* @lnum: logical eraseblock number
|
||||
* @scrub: if this physical eraseblock needs scrubbing
|
||||
* @copy_flag: this LEB is a copy (@copy_flag is set in VID header of this LEB)
|
||||
* @sqnum: sequence number
|
||||
* @u: unions RB-tree or @list links
|
||||
* @u.rb: link in the per-volume RB-tree of &struct ubi_scan_leb objects
|
||||
* @u.list: link in one of the eraseblock lists
|
||||
*
|
||||
* One object of this type is allocated for each physical eraseblock during
|
||||
* scanning.
|
||||
*/
|
||||
struct ubi_scan_leb {
|
||||
int ec;
|
||||
int pnum;
|
||||
int lnum;
|
||||
unsigned int scrub:1;
|
||||
unsigned int copy_flag:1;
|
||||
unsigned long long sqnum;
|
||||
union {
|
||||
struct rb_node rb;
|
||||
struct list_head list;
|
||||
} u;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ubi_scan_volume - scanning information about a volume.
|
||||
* @vol_id: volume ID
|
||||
* @highest_lnum: highest logical eraseblock number in this volume
|
||||
* @leb_count: number of logical eraseblocks in this volume
|
||||
* @vol_type: volume type
|
||||
* @used_ebs: number of used logical eraseblocks in this volume (only for
|
||||
* static volumes)
|
||||
* @last_data_size: amount of data in the last logical eraseblock of this
|
||||
* volume (always equivalent to the usable logical eraseblock
|
||||
* size in case of dynamic volumes)
|
||||
* @data_pad: how many bytes at the end of logical eraseblocks of this volume
|
||||
* are not used (due to volume alignment)
|
||||
* @compat: compatibility flags of this volume
|
||||
* @rb: link in the volume RB-tree
|
||||
* @root: root of the RB-tree containing all the eraseblock belonging to this
|
||||
* volume (&struct ubi_scan_leb objects)
|
||||
*
|
||||
* One object of this type is allocated for each volume during scanning.
|
||||
*/
|
||||
struct ubi_scan_volume {
|
||||
int vol_id;
|
||||
int highest_lnum;
|
||||
int leb_count;
|
||||
int vol_type;
|
||||
int used_ebs;
|
||||
int last_data_size;
|
||||
int data_pad;
|
||||
int compat;
|
||||
struct rb_node rb;
|
||||
struct rb_root root;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ubi_scan_info - UBI scanning information.
|
||||
* @volumes: root of the volume RB-tree
|
||||
* @corr: list of corrupted physical eraseblocks
|
||||
* @free: list of free physical eraseblocks
|
||||
* @erase: list of physical eraseblocks which have to be erased
|
||||
* @alien: list of physical eraseblocks which should not be used by UBI (e.g.,
|
||||
* those belonging to "preserve"-compatible internal volumes)
|
||||
* @corr_peb_count: count of PEBs in the @corr list
|
||||
* @empty_peb_count: count of PEBs which are presumably empty (contain only
|
||||
* 0xFF bytes)
|
||||
* @alien_peb_count: count of PEBs in the @alien list
|
||||
* @bad_peb_count: count of bad physical eraseblocks
|
||||
* @maybe_bad_peb_count: count of bad physical eraseblocks which are not marked
|
||||
* as bad yet, but which look like bad
|
||||
* @vols_found: number of volumes found during scanning
|
||||
* @highest_vol_id: highest volume ID
|
||||
* @is_empty: flag indicating whether the MTD device is empty or not
|
||||
* @min_ec: lowest erase counter value
|
||||
* @max_ec: highest erase counter value
|
||||
* @max_sqnum: highest sequence number value
|
||||
* @mean_ec: mean erase counter value
|
||||
* @ec_sum: a temporary variable used when calculating @mean_ec
|
||||
* @ec_count: a temporary variable used when calculating @mean_ec
|
||||
* @scan_leb_slab: slab cache for &struct ubi_scan_leb objects
|
||||
*
|
||||
* This data structure contains the result of scanning and may be used by other
|
||||
* UBI sub-systems to build final UBI data structures, further error-recovery
|
||||
* and so on.
|
||||
*/
|
||||
struct ubi_scan_info {
|
||||
struct rb_root volumes;
|
||||
struct list_head corr;
|
||||
struct list_head free;
|
||||
struct list_head erase;
|
||||
struct list_head alien;
|
||||
int corr_peb_count;
|
||||
int empty_peb_count;
|
||||
int alien_peb_count;
|
||||
int bad_peb_count;
|
||||
int maybe_bad_peb_count;
|
||||
int vols_found;
|
||||
int highest_vol_id;
|
||||
int is_empty;
|
||||
int min_ec;
|
||||
int max_ec;
|
||||
unsigned long long max_sqnum;
|
||||
int mean_ec;
|
||||
uint64_t ec_sum;
|
||||
int ec_count;
|
||||
struct kmem_cache *scan_leb_slab;
|
||||
};
|
||||
|
||||
struct ubi_device;
|
||||
struct ubi_vid_hdr;
|
||||
|
||||
/*
|
||||
* ubi_scan_move_to_list - move a PEB from the volume tree to a list.
|
||||
*
|
||||
* @sv: volume scanning information
|
||||
* @seb: scanning eraseblock information
|
||||
* @list: the list to move to
|
||||
*/
|
||||
static inline void ubi_scan_move_to_list(struct ubi_scan_volume *sv,
|
||||
struct ubi_scan_leb *seb,
|
||||
struct list_head *list)
|
||||
{
|
||||
rb_erase(&seb->u.rb, &sv->root);
|
||||
list_add_tail(&seb->u.list, list);
|
||||
}
|
||||
|
||||
int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
|
||||
int pnum, int ec, const struct ubi_vid_hdr *vid_hdr,
|
||||
int bitflips);
|
||||
struct ubi_scan_volume *ubi_scan_find_sv(const struct ubi_scan_info *si,
|
||||
int vol_id);
|
||||
struct ubi_scan_leb *ubi_scan_find_seb(const struct ubi_scan_volume *sv,
|
||||
int lnum);
|
||||
void ubi_scan_rm_volume(struct ubi_scan_info *si, struct ubi_scan_volume *sv);
|
||||
struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi,
|
||||
struct ubi_scan_info *si);
|
||||
int ubi_scan_erase_peb(struct ubi_device *ubi, const struct ubi_scan_info *si,
|
||||
int pnum, int ec);
|
||||
struct ubi_scan_info *ubi_scan(struct ubi_device *ubi);
|
||||
void ubi_scan_destroy_si(struct ubi_scan_info *si);
|
||||
|
||||
#endif /* !__UBI_SCAN_H__ */
|
|
@ -149,10 +149,10 @@ enum {
|
|||
* The @image_seq field is used to validate a UBI image that has been prepared
|
||||
* for a UBI device. The @image_seq value can be any value, but it must be the
|
||||
* same on all eraseblocks. UBI will ensure that all new erase counter headers
|
||||
* also contain this value, and will check the value when scanning at start-up.
|
||||
* also contain this value, and will check the value when attaching the flash.
|
||||
* One way to make use of @image_seq is to increase its value by one every time
|
||||
* an image is flashed over an existing image, then, if the flashing does not
|
||||
* complete, UBI will detect the error when scanning.
|
||||
* complete, UBI will detect the error when attaching the media.
|
||||
*/
|
||||
struct ubi_ec_hdr {
|
||||
__be32 magic;
|
||||
|
@ -298,8 +298,8 @@ struct ubi_vid_hdr {
|
|||
#define UBI_INT_VOL_COUNT 1
|
||||
|
||||
/*
|
||||
* Starting ID of internal volumes. There is reserved room for 4096 internal
|
||||
* volumes.
|
||||
* Starting ID of internal volumes: 0x7fffefff.
|
||||
* There is reserved room for 4096 internal volumes.
|
||||
*/
|
||||
#define UBI_INTERNAL_VOL_START (0x7FFFFFFF - 4096)
|
||||
|
||||
|
|
|
@ -43,7 +43,6 @@
|
|||
#include <asm/pgtable.h>
|
||||
|
||||
#include "ubi-media.h"
|
||||
#include "scan.h"
|
||||
|
||||
/* Maximum number of supported UBI devices */
|
||||
#define UBI_MAX_DEVICES 32
|
||||
|
@ -66,7 +65,10 @@
|
|||
/* Background thread name pattern */
|
||||
#define UBI_BGT_NAME_PATTERN "ubi_bgt%dd"
|
||||
|
||||
/* This marker in the EBA table means that the LEB is um-mapped */
|
||||
/*
|
||||
* This marker in the EBA table means that the LEB is um-mapped.
|
||||
* NOTE! It has to have the same value as %UBI_ALL.
|
||||
*/
|
||||
#define UBI_LEB_UNMAPPED -1
|
||||
|
||||
/*
|
||||
|
@ -82,6 +84,9 @@
|
|||
*/
|
||||
#define UBI_PROT_QUEUE_LEN 10
|
||||
|
||||
/* The volume ID/LEB number/erase counter is unknown */
|
||||
#define UBI_UNKNOWN -1
|
||||
|
||||
/*
|
||||
* Error codes returned by the I/O sub-system.
|
||||
*
|
||||
|
@ -222,8 +227,6 @@ struct ubi_volume_desc;
|
|||
* @upd_ebs: how many eraseblocks are expected to be updated
|
||||
* @ch_lnum: LEB number which is being changing by the atomic LEB change
|
||||
* operation
|
||||
* @ch_dtype: data persistency type which is being changing by the atomic LEB
|
||||
* change operation
|
||||
* @upd_bytes: how many bytes are expected to be received for volume update or
|
||||
* atomic LEB change
|
||||
* @upd_received: how many bytes were already received for volume update or
|
||||
|
@ -270,7 +273,6 @@ struct ubi_volume {
|
|||
|
||||
int upd_ebs;
|
||||
int ch_lnum;
|
||||
int ch_dtype;
|
||||
long long upd_bytes;
|
||||
long long upd_received;
|
||||
void *upd_buf;
|
||||
|
@ -477,6 +479,124 @@ struct ubi_device {
|
|||
struct ubi_debug_info *dbg;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ubi_ainf_peb - attach information about a physical eraseblock.
|
||||
* @ec: erase counter (%UBI_UNKNOWN if it is unknown)
|
||||
* @pnum: physical eraseblock number
|
||||
* @vol_id: ID of the volume this LEB belongs to
|
||||
* @lnum: logical eraseblock number
|
||||
* @scrub: if this physical eraseblock needs scrubbing
|
||||
* @copy_flag: this LEB is a copy (@copy_flag is set in VID header of this LEB)
|
||||
* @sqnum: sequence number
|
||||
* @u: unions RB-tree or @list links
|
||||
* @u.rb: link in the per-volume RB-tree of &struct ubi_ainf_peb objects
|
||||
* @u.list: link in one of the eraseblock lists
|
||||
*
|
||||
* One object of this type is allocated for each physical eraseblock when
|
||||
* attaching an MTD device. Note, if this PEB does not belong to any LEB /
|
||||
* volume, the @vol_id and @lnum fields are initialized to %UBI_UNKNOWN.
|
||||
*/
|
||||
struct ubi_ainf_peb {
|
||||
int ec;
|
||||
int pnum;
|
||||
int vol_id;
|
||||
int lnum;
|
||||
unsigned int scrub:1;
|
||||
unsigned int copy_flag:1;
|
||||
unsigned long long sqnum;
|
||||
union {
|
||||
struct rb_node rb;
|
||||
struct list_head list;
|
||||
} u;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ubi_ainf_volume - attaching information about a volume.
|
||||
* @vol_id: volume ID
|
||||
* @highest_lnum: highest logical eraseblock number in this volume
|
||||
* @leb_count: number of logical eraseblocks in this volume
|
||||
* @vol_type: volume type
|
||||
* @used_ebs: number of used logical eraseblocks in this volume (only for
|
||||
* static volumes)
|
||||
* @last_data_size: amount of data in the last logical eraseblock of this
|
||||
* volume (always equivalent to the usable logical eraseblock
|
||||
* size in case of dynamic volumes)
|
||||
* @data_pad: how many bytes at the end of logical eraseblocks of this volume
|
||||
* are not used (due to volume alignment)
|
||||
* @compat: compatibility flags of this volume
|
||||
* @rb: link in the volume RB-tree
|
||||
* @root: root of the RB-tree containing all the eraseblock belonging to this
|
||||
* volume (&struct ubi_ainf_peb objects)
|
||||
*
|
||||
* One object of this type is allocated for each volume when attaching an MTD
|
||||
* device.
|
||||
*/
|
||||
struct ubi_ainf_volume {
|
||||
int vol_id;
|
||||
int highest_lnum;
|
||||
int leb_count;
|
||||
int vol_type;
|
||||
int used_ebs;
|
||||
int last_data_size;
|
||||
int data_pad;
|
||||
int compat;
|
||||
struct rb_node rb;
|
||||
struct rb_root root;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ubi_attach_info - MTD device attaching information.
|
||||
* @volumes: root of the volume RB-tree
|
||||
* @corr: list of corrupted physical eraseblocks
|
||||
* @free: list of free physical eraseblocks
|
||||
* @erase: list of physical eraseblocks which have to be erased
|
||||
* @alien: list of physical eraseblocks which should not be used by UBI (e.g.,
|
||||
* those belonging to "preserve"-compatible internal volumes)
|
||||
* @corr_peb_count: count of PEBs in the @corr list
|
||||
* @empty_peb_count: count of PEBs which are presumably empty (contain only
|
||||
* 0xFF bytes)
|
||||
* @alien_peb_count: count of PEBs in the @alien list
|
||||
* @bad_peb_count: count of bad physical eraseblocks
|
||||
* @maybe_bad_peb_count: count of bad physical eraseblocks which are not marked
|
||||
* as bad yet, but which look like bad
|
||||
* @vols_found: number of volumes found
|
||||
* @highest_vol_id: highest volume ID
|
||||
* @is_empty: flag indicating whether the MTD device is empty or not
|
||||
* @min_ec: lowest erase counter value
|
||||
* @max_ec: highest erase counter value
|
||||
* @max_sqnum: highest sequence number value
|
||||
* @mean_ec: mean erase counter value
|
||||
* @ec_sum: a temporary variable used when calculating @mean_ec
|
||||
* @ec_count: a temporary variable used when calculating @mean_ec
|
||||
* @aeb_slab_cache: slab cache for &struct ubi_ainf_peb objects
|
||||
*
|
||||
* This data structure contains the result of attaching an MTD device and may
|
||||
* be used by other UBI sub-systems to build final UBI data structures, further
|
||||
* error-recovery and so on.
|
||||
*/
|
||||
struct ubi_attach_info {
|
||||
struct rb_root volumes;
|
||||
struct list_head corr;
|
||||
struct list_head free;
|
||||
struct list_head erase;
|
||||
struct list_head alien;
|
||||
int corr_peb_count;
|
||||
int empty_peb_count;
|
||||
int alien_peb_count;
|
||||
int bad_peb_count;
|
||||
int maybe_bad_peb_count;
|
||||
int vols_found;
|
||||
int highest_vol_id;
|
||||
int is_empty;
|
||||
int min_ec;
|
||||
int max_ec;
|
||||
unsigned long long max_sqnum;
|
||||
int mean_ec;
|
||||
uint64_t ec_sum;
|
||||
int ec_count;
|
||||
struct kmem_cache *aeb_slab_cache;
|
||||
};
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
extern struct kmem_cache *ubi_wl_entry_slab;
|
||||
|
@ -487,12 +607,23 @@ extern struct class *ubi_class;
|
|||
extern struct mutex ubi_devices_mutex;
|
||||
extern struct blocking_notifier_head ubi_notifiers;
|
||||
|
||||
/* scan.c */
|
||||
int ubi_add_to_av(struct ubi_device *ubi, struct ubi_attach_info *ai, int pnum,
|
||||
int ec, const struct ubi_vid_hdr *vid_hdr, int bitflips);
|
||||
struct ubi_ainf_volume *ubi_find_av(const struct ubi_attach_info *ai,
|
||||
int vol_id);
|
||||
void ubi_remove_av(struct ubi_attach_info *ai, struct ubi_ainf_volume *av);
|
||||
struct ubi_ainf_peb *ubi_early_get_peb(struct ubi_device *ubi,
|
||||
struct ubi_attach_info *ai);
|
||||
int ubi_attach(struct ubi_device *ubi);
|
||||
void ubi_destroy_ai(struct ubi_attach_info *ai);
|
||||
|
||||
/* vtbl.c */
|
||||
int ubi_change_vtbl_record(struct ubi_device *ubi, int idx,
|
||||
struct ubi_vtbl_record *vtbl_rec);
|
||||
int ubi_vtbl_rename_volumes(struct ubi_device *ubi,
|
||||
struct list_head *rename_list);
|
||||
int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si);
|
||||
int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_attach_info *ai);
|
||||
|
||||
/* vmt.c */
|
||||
int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req);
|
||||
|
@ -525,22 +656,22 @@ int ubi_eba_unmap_leb(struct ubi_device *ubi, struct ubi_volume *vol,
|
|||
int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
|
||||
void *buf, int offset, int len, int check);
|
||||
int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
|
||||
const void *buf, int offset, int len, int dtype);
|
||||
const void *buf, int offset, int len);
|
||||
int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol,
|
||||
int lnum, const void *buf, int len, int dtype,
|
||||
int used_ebs);
|
||||
int lnum, const void *buf, int len, int used_ebs);
|
||||
int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
|
||||
int lnum, const void *buf, int len, int dtype);
|
||||
int lnum, const void *buf, int len);
|
||||
int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
|
||||
struct ubi_vid_hdr *vid_hdr);
|
||||
int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si);
|
||||
int ubi_eba_init(struct ubi_device *ubi, struct ubi_attach_info *ai);
|
||||
|
||||
/* wl.c */
|
||||
int ubi_wl_get_peb(struct ubi_device *ubi, int dtype);
|
||||
int ubi_wl_put_peb(struct ubi_device *ubi, int pnum, int torture);
|
||||
int ubi_wl_flush(struct ubi_device *ubi);
|
||||
int ubi_wl_get_peb(struct ubi_device *ubi);
|
||||
int ubi_wl_put_peb(struct ubi_device *ubi, int vol_id, int lnum,
|
||||
int pnum, int torture);
|
||||
int ubi_wl_flush(struct ubi_device *ubi, int vol_id, int lnum);
|
||||
int ubi_wl_scrub_peb(struct ubi_device *ubi, int pnum);
|
||||
int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si);
|
||||
int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai);
|
||||
void ubi_wl_close(struct ubi_device *ubi);
|
||||
int ubi_thread(void *u);
|
||||
|
||||
|
@ -573,6 +704,7 @@ int ubi_volume_notify(struct ubi_device *ubi, struct ubi_volume *vol,
|
|||
int ubi_notify_all(struct ubi_device *ubi, int ntype,
|
||||
struct notifier_block *nb);
|
||||
int ubi_enumerate_volumes(struct notifier_block *nb);
|
||||
void ubi_free_internal_volumes(struct ubi_device *ubi);
|
||||
|
||||
/* kapi.c */
|
||||
void ubi_do_get_device_info(struct ubi_device *ubi, struct ubi_device_info *di);
|
||||
|
@ -593,6 +725,21 @@ void ubi_do_get_volume_info(struct ubi_device *ubi, struct ubi_volume *vol,
|
|||
rb = rb_next(rb), \
|
||||
pos = (rb ? container_of(rb, typeof(*pos), member) : NULL))
|
||||
|
||||
/*
|
||||
* ubi_move_aeb_to_list - move a PEB from the volume tree to a list.
|
||||
*
|
||||
* @av: volume attaching information
|
||||
* @aeb: attaching eraseblock information
|
||||
* @list: the list to move to
|
||||
*/
|
||||
static inline void ubi_move_aeb_to_list(struct ubi_ainf_volume *av,
|
||||
struct ubi_ainf_peb *aeb,
|
||||
struct list_head *list)
|
||||
{
|
||||
rb_erase(&aeb->u.rb, &av->root);
|
||||
list_add_tail(&aeb->u.list, list);
|
||||
}
|
||||
|
||||
/**
|
||||
* ubi_zalloc_vid_hdr - allocate a volume identifier header object.
|
||||
* @ubi: UBI device description object
|
||||
|
@ -667,7 +814,7 @@ static inline void ubi_ro_mode(struct ubi_device *ubi)
|
|||
if (!ubi->ro_mode) {
|
||||
ubi->ro_mode = 1;
|
||||
ubi_warn("switch to read-only mode");
|
||||
ubi_dbg_dump_stack();
|
||||
dump_stack();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -147,7 +147,7 @@ int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol,
|
|||
}
|
||||
|
||||
if (bytes == 0) {
|
||||
err = ubi_wl_flush(ubi);
|
||||
err = ubi_wl_flush(ubi, UBI_ALL, UBI_ALL);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -186,14 +186,12 @@ int ubi_start_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
|
|||
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,
|
||||
req->dtype);
|
||||
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->ch_dtype = req->dtype;
|
||||
|
||||
vol->upd_buf = vmalloc(req->bytes);
|
||||
if (!vol->upd_buf)
|
||||
|
@ -246,8 +244,7 @@ static int write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
|
|||
return 0;
|
||||
}
|
||||
|
||||
err = ubi_eba_write_leb(ubi, vol, lnum, buf, 0, len,
|
||||
UBI_UNKNOWN);
|
||||
err = ubi_eba_write_leb(ubi, vol, lnum, buf, 0, len);
|
||||
} else {
|
||||
/*
|
||||
* When writing static volume, and this is the last logical
|
||||
|
@ -259,8 +256,7 @@ static int write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
|
|||
* contain zeros, not random trash.
|
||||
*/
|
||||
memset(buf + len, 0, vol->usable_leb_size - len);
|
||||
err = ubi_eba_write_leb_st(ubi, vol, lnum, buf, len,
|
||||
UBI_UNKNOWN, used_ebs);
|
||||
err = ubi_eba_write_leb_st(ubi, vol, lnum, buf, len, used_ebs);
|
||||
}
|
||||
|
||||
return err;
|
||||
|
@ -365,7 +361,7 @@ int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol,
|
|||
|
||||
ubi_assert(vol->upd_received <= vol->upd_bytes);
|
||||
if (vol->upd_received == vol->upd_bytes) {
|
||||
err = ubi_wl_flush(ubi);
|
||||
err = ubi_wl_flush(ubi, UBI_ALL, UBI_ALL);
|
||||
if (err)
|
||||
return err;
|
||||
/* The update is finished, clear the update marker */
|
||||
|
@ -421,7 +417,7 @@ int ubi_more_leb_change_data(struct ubi_device *ubi, struct ubi_volume *vol,
|
|||
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, UBI_UNKNOWN);
|
||||
vol->upd_buf, len);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -29,11 +29,7 @@
|
|||
#include <linux/export.h>
|
||||
#include "ubi.h"
|
||||
|
||||
#ifdef CONFIG_MTD_UBI_DEBUG
|
||||
static int paranoid_check_volumes(struct ubi_device *ubi);
|
||||
#else
|
||||
#define paranoid_check_volumes(ubi) 0
|
||||
#endif
|
||||
static int self_check_volumes(struct ubi_device *ubi);
|
||||
|
||||
static ssize_t vol_attribute_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf);
|
||||
|
@ -227,7 +223,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
|
|||
}
|
||||
|
||||
if (vol_id == UBI_VOL_NUM_AUTO) {
|
||||
dbg_err("out of volume IDs");
|
||||
ubi_err("out of volume IDs");
|
||||
err = -ENFILE;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
@ -241,7 +237,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
|
|||
/* Ensure that this volume does not exist */
|
||||
err = -EEXIST;
|
||||
if (ubi->volumes[vol_id]) {
|
||||
dbg_err("volume %d already exists", vol_id);
|
||||
ubi_err("volume %d already exists", vol_id);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
|
@ -250,7 +246,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
|
|||
if (ubi->volumes[i] &&
|
||||
ubi->volumes[i]->name_len == req->name_len &&
|
||||
!strcmp(ubi->volumes[i]->name, req->name)) {
|
||||
dbg_err("volume \"%s\" exists (ID %d)", req->name, i);
|
||||
ubi_err("volume \"%s\" exists (ID %d)", req->name, i);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
|
@ -261,9 +257,9 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
|
|||
|
||||
/* Reserve physical eraseblocks */
|
||||
if (vol->reserved_pebs > ubi->avail_pebs) {
|
||||
dbg_err("not enough PEBs, only %d available", ubi->avail_pebs);
|
||||
ubi_err("not enough PEBs, only %d available", ubi->avail_pebs);
|
||||
if (ubi->corr_peb_count)
|
||||
dbg_err("%d PEBs are corrupted and not used",
|
||||
ubi_err("%d PEBs are corrupted and not used",
|
||||
ubi->corr_peb_count);
|
||||
err = -ENOSPC;
|
||||
goto out_unlock;
|
||||
|
@ -284,7 +280,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
|
|||
* Finish all pending erases because there may be some LEBs belonging
|
||||
* to the same volume ID.
|
||||
*/
|
||||
err = ubi_wl_flush(ubi);
|
||||
err = ubi_wl_flush(ubi, vol_id, UBI_ALL);
|
||||
if (err)
|
||||
goto out_acc;
|
||||
|
||||
|
@ -360,8 +356,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
|
|||
spin_unlock(&ubi->volumes_lock);
|
||||
|
||||
ubi_volume_notify(ubi, vol, UBI_VOLUME_ADDED);
|
||||
if (paranoid_check_volumes(ubi))
|
||||
dbg_err("check failed while creating volume %d", vol_id);
|
||||
self_check_volumes(ubi);
|
||||
return err;
|
||||
|
||||
out_sysfs:
|
||||
|
@ -461,8 +456,8 @@ int ubi_remove_volume(struct ubi_volume_desc *desc, int no_vtbl)
|
|||
spin_unlock(&ubi->volumes_lock);
|
||||
|
||||
ubi_volume_notify(ubi, vol, UBI_VOLUME_REMOVED);
|
||||
if (!no_vtbl && paranoid_check_volumes(ubi))
|
||||
dbg_err("check failed while removing volume %d", vol_id);
|
||||
if (!no_vtbl)
|
||||
self_check_volumes(ubi);
|
||||
|
||||
return err;
|
||||
|
||||
|
@ -500,7 +495,7 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs)
|
|||
|
||||
if (vol->vol_type == UBI_STATIC_VOLUME &&
|
||||
reserved_pebs < vol->used_ebs) {
|
||||
dbg_err("too small size %d, %d LEBs contain data",
|
||||
ubi_err("too small size %d, %d LEBs contain data",
|
||||
reserved_pebs, vol->used_ebs);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -529,10 +524,10 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs)
|
|||
if (pebs > 0) {
|
||||
spin_lock(&ubi->volumes_lock);
|
||||
if (pebs > ubi->avail_pebs) {
|
||||
dbg_err("not enough PEBs: requested %d, available %d",
|
||||
ubi_err("not enough PEBs: requested %d, available %d",
|
||||
pebs, ubi->avail_pebs);
|
||||
if (ubi->corr_peb_count)
|
||||
dbg_err("%d PEBs are corrupted and not used",
|
||||
ubi_err("%d PEBs are corrupted and not used",
|
||||
ubi->corr_peb_count);
|
||||
spin_unlock(&ubi->volumes_lock);
|
||||
err = -ENOSPC;
|
||||
|
@ -588,8 +583,7 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs)
|
|||
}
|
||||
|
||||
ubi_volume_notify(ubi, vol, UBI_VOLUME_RESIZED);
|
||||
if (paranoid_check_volumes(ubi))
|
||||
dbg_err("check failed while re-sizing volume %d", vol_id);
|
||||
self_check_volumes(ubi);
|
||||
return err;
|
||||
|
||||
out_acc:
|
||||
|
@ -638,8 +632,8 @@ int ubi_rename_volumes(struct ubi_device *ubi, struct list_head *rename_list)
|
|||
}
|
||||
}
|
||||
|
||||
if (!err && paranoid_check_volumes(ubi))
|
||||
;
|
||||
if (!err)
|
||||
self_check_volumes(ubi);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -686,8 +680,7 @@ int ubi_add_volume(struct ubi_device *ubi, struct ubi_volume *vol)
|
|||
return err;
|
||||
}
|
||||
|
||||
if (paranoid_check_volumes(ubi))
|
||||
dbg_err("check failed while adding volume %d", vol_id);
|
||||
self_check_volumes(ubi);
|
||||
return err;
|
||||
|
||||
out_cdev:
|
||||
|
@ -712,16 +705,14 @@ void ubi_free_volume(struct ubi_device *ubi, struct ubi_volume *vol)
|
|||
volume_sysfs_close(vol);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MTD_UBI_DEBUG
|
||||
|
||||
/**
|
||||
* paranoid_check_volume - check volume information.
|
||||
* self_check_volume - check volume information.
|
||||
* @ubi: UBI device description object
|
||||
* @vol_id: volume ID
|
||||
*
|
||||
* Returns zero if volume is all right and a a negative error code if not.
|
||||
*/
|
||||
static int paranoid_check_volume(struct ubi_device *ubi, int vol_id)
|
||||
static int self_check_volume(struct ubi_device *ubi, int vol_id)
|
||||
{
|
||||
int idx = vol_id2idx(ubi, vol_id);
|
||||
int reserved_pebs, alignment, data_pad, vol_type, name_len, upd_marker;
|
||||
|
@ -771,7 +762,7 @@ static int paranoid_check_volume(struct ubi_device *ubi, int vol_id)
|
|||
}
|
||||
|
||||
if (vol->upd_marker && vol->corrupted) {
|
||||
dbg_err("update marker and corrupted simultaneously");
|
||||
ubi_err("update marker and corrupted simultaneously");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -853,22 +844,22 @@ static int paranoid_check_volume(struct ubi_device *ubi, int vol_id)
|
|||
return 0;
|
||||
|
||||
fail:
|
||||
ubi_err("paranoid check failed for volume %d", vol_id);
|
||||
ubi_err("self-check failed for volume %d", vol_id);
|
||||
if (vol)
|
||||
ubi_dbg_dump_vol_info(vol);
|
||||
ubi_dbg_dump_vtbl_record(&ubi->vtbl[vol_id], vol_id);
|
||||
ubi_dump_vol_info(vol);
|
||||
ubi_dump_vtbl_record(&ubi->vtbl[vol_id], vol_id);
|
||||
dump_stack();
|
||||
spin_unlock(&ubi->volumes_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* paranoid_check_volumes - check information about all volumes.
|
||||
* self_check_volumes - check information about all volumes.
|
||||
* @ubi: UBI device description object
|
||||
*
|
||||
* Returns zero if volumes are all right and a a negative error code if not.
|
||||
*/
|
||||
static int paranoid_check_volumes(struct ubi_device *ubi)
|
||||
static int self_check_volumes(struct ubi_device *ubi)
|
||||
{
|
||||
int i, err = 0;
|
||||
|
||||
|
@ -876,11 +867,10 @@ static int paranoid_check_volumes(struct ubi_device *ubi)
|
|||
return 0;
|
||||
|
||||
for (i = 0; i < ubi->vtbl_slots; i++) {
|
||||
err = paranoid_check_volume(ubi, i);
|
||||
err = self_check_volume(ubi, i);
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -37,16 +37,15 @@
|
|||
* LEB 1. This scheme guarantees recoverability from unclean reboots.
|
||||
*
|
||||
* In this UBI implementation the on-flash volume table does not contain any
|
||||
* information about how many data static volumes contain. This information may
|
||||
* be found from the scanning data.
|
||||
* information about how much data static volumes contain.
|
||||
*
|
||||
* But it would still be beneficial to store this information in the volume
|
||||
* table. For example, suppose we have a static volume X, and all its physical
|
||||
* eraseblocks became bad for some reasons. Suppose we are attaching the
|
||||
* corresponding MTD device, the scanning has found no logical eraseblocks
|
||||
* corresponding MTD device, for some reason we find no logical eraseblocks
|
||||
* corresponding to the volume X. According to the volume table volume X does
|
||||
* exist. So we don't know whether it is just empty or all its physical
|
||||
* eraseblocks went bad. So we cannot alarm the user about this corruption.
|
||||
* eraseblocks went bad. So we cannot alarm the user properly.
|
||||
*
|
||||
* The volume table also stores so-called "update marker", which is used for
|
||||
* volume updates. Before updating the volume, the update marker is set, and
|
||||
|
@ -62,11 +61,7 @@
|
|||
#include <asm/div64.h>
|
||||
#include "ubi.h"
|
||||
|
||||
#ifdef CONFIG_MTD_UBI_DEBUG
|
||||
static void paranoid_vtbl_check(const struct ubi_device *ubi);
|
||||
#else
|
||||
#define paranoid_vtbl_check(ubi)
|
||||
#endif
|
||||
static void self_vtbl_check(const struct ubi_device *ubi);
|
||||
|
||||
/* Empty volume table record */
|
||||
static struct ubi_vtbl_record empty_vtbl_record;
|
||||
|
@ -106,12 +101,12 @@ int ubi_change_vtbl_record(struct ubi_device *ubi, int idx,
|
|||
return err;
|
||||
|
||||
err = ubi_eba_write_leb(ubi, layout_vol, i, ubi->vtbl, 0,
|
||||
ubi->vtbl_size, UBI_LONGTERM);
|
||||
ubi->vtbl_size);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
paranoid_vtbl_check(ubi);
|
||||
self_vtbl_check(ubi);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -158,7 +153,7 @@ int ubi_vtbl_rename_volumes(struct ubi_device *ubi,
|
|||
return err;
|
||||
|
||||
err = ubi_eba_write_leb(ubi, layout_vol, i, ubi->vtbl, 0,
|
||||
ubi->vtbl_size, UBI_LONGTERM);
|
||||
ubi->vtbl_size);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
@ -197,7 +192,7 @@ static int vtbl_check(const struct ubi_device *ubi,
|
|||
if (be32_to_cpu(vtbl[i].crc) != crc) {
|
||||
ubi_err("bad CRC at record %u: %#08x, not %#08x",
|
||||
i, crc, be32_to_cpu(vtbl[i].crc));
|
||||
ubi_dbg_dump_vtbl_record(&vtbl[i], i);
|
||||
ubi_dump_vtbl_record(&vtbl[i], i);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -229,7 +224,7 @@ static int vtbl_check(const struct ubi_device *ubi,
|
|||
|
||||
n = ubi->leb_size % alignment;
|
||||
if (data_pad != n) {
|
||||
dbg_err("bad data_pad, has to be %d", n);
|
||||
ubi_err("bad data_pad, has to be %d", n);
|
||||
err = 6;
|
||||
goto bad;
|
||||
}
|
||||
|
@ -245,7 +240,7 @@ static int vtbl_check(const struct ubi_device *ubi,
|
|||
}
|
||||
|
||||
if (reserved_pebs > ubi->good_peb_count) {
|
||||
dbg_err("too large reserved_pebs %d, good PEBs %d",
|
||||
ubi_err("too large reserved_pebs %d, good PEBs %d",
|
||||
reserved_pebs, ubi->good_peb_count);
|
||||
err = 9;
|
||||
goto bad;
|
||||
|
@ -277,8 +272,8 @@ static int vtbl_check(const struct ubi_device *ubi,
|
|||
!strncmp(vtbl[i].name, vtbl[n].name, len1)) {
|
||||
ubi_err("volumes %d and %d have the same name"
|
||||
" \"%s\"", i, n, vtbl[i].name);
|
||||
ubi_dbg_dump_vtbl_record(&vtbl[i], i);
|
||||
ubi_dbg_dump_vtbl_record(&vtbl[n], n);
|
||||
ubi_dump_vtbl_record(&vtbl[i], i);
|
||||
ubi_dump_vtbl_record(&vtbl[n], n);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
@ -288,26 +283,26 @@ static int vtbl_check(const struct ubi_device *ubi,
|
|||
|
||||
bad:
|
||||
ubi_err("volume table check failed: record %d, error %d", i, err);
|
||||
ubi_dbg_dump_vtbl_record(&vtbl[i], i);
|
||||
ubi_dump_vtbl_record(&vtbl[i], i);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* create_vtbl - create a copy of volume table.
|
||||
* @ubi: UBI device description object
|
||||
* @si: scanning information
|
||||
* @ai: attaching information
|
||||
* @copy: number of the volume table copy
|
||||
* @vtbl: contents of the volume table
|
||||
*
|
||||
* This function returns zero in case of success and a negative error code in
|
||||
* case of failure.
|
||||
*/
|
||||
static int create_vtbl(struct ubi_device *ubi, struct ubi_scan_info *si,
|
||||
static int create_vtbl(struct ubi_device *ubi, struct ubi_attach_info *ai,
|
||||
int copy, void *vtbl)
|
||||
{
|
||||
int err, tries = 0;
|
||||
struct ubi_vid_hdr *vid_hdr;
|
||||
struct ubi_scan_leb *new_seb;
|
||||
struct ubi_ainf_peb *new_aeb;
|
||||
|
||||
ubi_msg("create volume table (copy #%d)", copy + 1);
|
||||
|
||||
|
@ -316,9 +311,9 @@ static int create_vtbl(struct ubi_device *ubi, struct ubi_scan_info *si,
|
|||
return -ENOMEM;
|
||||
|
||||
retry:
|
||||
new_seb = ubi_scan_get_free_peb(ubi, si);
|
||||
if (IS_ERR(new_seb)) {
|
||||
err = PTR_ERR(new_seb);
|
||||
new_aeb = ubi_early_get_peb(ubi, ai);
|
||||
if (IS_ERR(new_aeb)) {
|
||||
err = PTR_ERR(new_aeb);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
|
@ -328,25 +323,24 @@ retry:
|
|||
vid_hdr->data_size = vid_hdr->used_ebs =
|
||||
vid_hdr->data_pad = cpu_to_be32(0);
|
||||
vid_hdr->lnum = cpu_to_be32(copy);
|
||||
vid_hdr->sqnum = cpu_to_be64(++si->max_sqnum);
|
||||
vid_hdr->sqnum = cpu_to_be64(++ai->max_sqnum);
|
||||
|
||||
/* The EC header is already there, write the VID header */
|
||||
err = ubi_io_write_vid_hdr(ubi, new_seb->pnum, vid_hdr);
|
||||
err = ubi_io_write_vid_hdr(ubi, new_aeb->pnum, vid_hdr);
|
||||
if (err)
|
||||
goto write_error;
|
||||
|
||||
/* Write the layout volume contents */
|
||||
err = ubi_io_write_data(ubi, vtbl, new_seb->pnum, 0, ubi->vtbl_size);
|
||||
err = ubi_io_write_data(ubi, vtbl, new_aeb->pnum, 0, ubi->vtbl_size);
|
||||
if (err)
|
||||
goto write_error;
|
||||
|
||||
/*
|
||||
* And add it to the scanning information. Don't delete the old version
|
||||
* of this LEB as it will be deleted and freed in 'ubi_scan_add_used()'.
|
||||
* And add it to the attaching information. Don't delete the old version
|
||||
* of this LEB as it will be deleted and freed in 'ubi_add_to_av()'.
|
||||
*/
|
||||
err = ubi_scan_add_used(ubi, si, new_seb->pnum, new_seb->ec,
|
||||
vid_hdr, 0);
|
||||
kfree(new_seb);
|
||||
err = ubi_add_to_av(ubi, ai, new_aeb->pnum, new_aeb->ec, vid_hdr, 0);
|
||||
kfree(new_aeb);
|
||||
ubi_free_vid_hdr(ubi, vid_hdr);
|
||||
return err;
|
||||
|
||||
|
@ -356,10 +350,10 @@ write_error:
|
|||
* Probably this physical eraseblock went bad, try to pick
|
||||
* another one.
|
||||
*/
|
||||
list_add(&new_seb->u.list, &si->erase);
|
||||
list_add(&new_aeb->u.list, &ai->erase);
|
||||
goto retry;
|
||||
}
|
||||
kfree(new_seb);
|
||||
kfree(new_aeb);
|
||||
out_free:
|
||||
ubi_free_vid_hdr(ubi, vid_hdr);
|
||||
return err;
|
||||
|
@ -369,20 +363,20 @@ out_free:
|
|||
/**
|
||||
* process_lvol - process the layout volume.
|
||||
* @ubi: UBI device description object
|
||||
* @si: scanning information
|
||||
* @sv: layout volume scanning information
|
||||
* @ai: attaching information
|
||||
* @av: layout volume attaching information
|
||||
*
|
||||
* This function is responsible for reading the layout volume, ensuring it is
|
||||
* not corrupted, and recovering from corruptions if needed. Returns volume
|
||||
* table in case of success and a negative error code in case of failure.
|
||||
*/
|
||||
static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi,
|
||||
struct ubi_scan_info *si,
|
||||
struct ubi_scan_volume *sv)
|
||||
struct ubi_attach_info *ai,
|
||||
struct ubi_ainf_volume *av)
|
||||
{
|
||||
int err;
|
||||
struct rb_node *rb;
|
||||
struct ubi_scan_leb *seb;
|
||||
struct ubi_ainf_peb *aeb;
|
||||
struct ubi_vtbl_record *leb[UBI_LAYOUT_VOLUME_EBS] = { NULL, NULL };
|
||||
int leb_corrupted[UBI_LAYOUT_VOLUME_EBS] = {1, 1};
|
||||
|
||||
|
@ -414,14 +408,14 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi,
|
|||
dbg_gen("check layout volume");
|
||||
|
||||
/* Read both LEB 0 and LEB 1 into memory */
|
||||
ubi_rb_for_each_entry(rb, seb, &sv->root, u.rb) {
|
||||
leb[seb->lnum] = vzalloc(ubi->vtbl_size);
|
||||
if (!leb[seb->lnum]) {
|
||||
ubi_rb_for_each_entry(rb, aeb, &av->root, u.rb) {
|
||||
leb[aeb->lnum] = vzalloc(ubi->vtbl_size);
|
||||
if (!leb[aeb->lnum]) {
|
||||
err = -ENOMEM;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
err = ubi_io_read_data(ubi, leb[seb->lnum], seb->pnum, 0,
|
||||
err = ubi_io_read_data(ubi, leb[aeb->lnum], aeb->pnum, 0,
|
||||
ubi->vtbl_size);
|
||||
if (err == UBI_IO_BITFLIPS || mtd_is_eccerr(err))
|
||||
/*
|
||||
|
@ -429,12 +423,12 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi,
|
|||
* uncorrectable ECC error, but we have our own CRC and
|
||||
* the data will be checked later. If the data is OK,
|
||||
* the PEB will be scrubbed (because we set
|
||||
* seb->scrub). If the data is not OK, the contents of
|
||||
* aeb->scrub). If the data is not OK, the contents of
|
||||
* the PEB will be recovered from the second copy, and
|
||||
* seb->scrub will be cleared in
|
||||
* 'ubi_scan_add_used()'.
|
||||
* aeb->scrub will be cleared in
|
||||
* 'ubi_add_to_av()'.
|
||||
*/
|
||||
seb->scrub = 1;
|
||||
aeb->scrub = 1;
|
||||
else if (err)
|
||||
goto out_free;
|
||||
}
|
||||
|
@ -453,7 +447,7 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi,
|
|||
ubi->vtbl_size);
|
||||
if (leb_corrupted[1]) {
|
||||
ubi_warn("volume table copy #2 is corrupted");
|
||||
err = create_vtbl(ubi, si, 1, leb[0]);
|
||||
err = create_vtbl(ubi, ai, 1, leb[0]);
|
||||
if (err)
|
||||
goto out_free;
|
||||
ubi_msg("volume table was restored");
|
||||
|
@ -476,7 +470,7 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi,
|
|||
}
|
||||
|
||||
ubi_warn("volume table copy #1 is corrupted");
|
||||
err = create_vtbl(ubi, si, 0, leb[1]);
|
||||
err = create_vtbl(ubi, ai, 0, leb[1]);
|
||||
if (err)
|
||||
goto out_free;
|
||||
ubi_msg("volume table was restored");
|
||||
|
@ -494,13 +488,13 @@ out_free:
|
|||
/**
|
||||
* create_empty_lvol - create empty layout volume.
|
||||
* @ubi: UBI device description object
|
||||
* @si: scanning information
|
||||
* @ai: attaching information
|
||||
*
|
||||
* This function returns volume table contents in case of success and a
|
||||
* negative error code in case of failure.
|
||||
*/
|
||||
static struct ubi_vtbl_record *create_empty_lvol(struct ubi_device *ubi,
|
||||
struct ubi_scan_info *si)
|
||||
struct ubi_attach_info *ai)
|
||||
{
|
||||
int i;
|
||||
struct ubi_vtbl_record *vtbl;
|
||||
|
@ -515,7 +509,7 @@ static struct ubi_vtbl_record *create_empty_lvol(struct ubi_device *ubi,
|
|||
for (i = 0; i < UBI_LAYOUT_VOLUME_EBS; i++) {
|
||||
int err;
|
||||
|
||||
err = create_vtbl(ubi, si, i, vtbl);
|
||||
err = create_vtbl(ubi, ai, i, vtbl);
|
||||
if (err) {
|
||||
vfree(vtbl);
|
||||
return ERR_PTR(err);
|
||||
|
@ -528,18 +522,19 @@ static struct ubi_vtbl_record *create_empty_lvol(struct ubi_device *ubi,
|
|||
/**
|
||||
* init_volumes - initialize volume information for existing volumes.
|
||||
* @ubi: UBI device description object
|
||||
* @si: scanning information
|
||||
* @ai: scanning information
|
||||
* @vtbl: volume table
|
||||
*
|
||||
* This function allocates volume description objects for existing volumes.
|
||||
* Returns zero in case of success and a negative error code in case of
|
||||
* failure.
|
||||
*/
|
||||
static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si,
|
||||
static int init_volumes(struct ubi_device *ubi,
|
||||
const struct ubi_attach_info *ai,
|
||||
const struct ubi_vtbl_record *vtbl)
|
||||
{
|
||||
int i, reserved_pebs = 0;
|
||||
struct ubi_scan_volume *sv;
|
||||
struct ubi_ainf_volume *av;
|
||||
struct ubi_volume *vol;
|
||||
|
||||
for (i = 0; i < ubi->vtbl_slots; i++) {
|
||||
|
@ -595,8 +590,8 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si,
|
|||
}
|
||||
|
||||
/* Static volumes only */
|
||||
sv = ubi_scan_find_sv(si, i);
|
||||
if (!sv) {
|
||||
av = ubi_find_av(ai, i);
|
||||
if (!av) {
|
||||
/*
|
||||
* No eraseblocks belonging to this volume found. We
|
||||
* don't actually know whether this static volume is
|
||||
|
@ -608,22 +603,22 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si,
|
|||
continue;
|
||||
}
|
||||
|
||||
if (sv->leb_count != sv->used_ebs) {
|
||||
if (av->leb_count != av->used_ebs) {
|
||||
/*
|
||||
* We found a static volume which misses several
|
||||
* eraseblocks. Treat it as corrupted.
|
||||
*/
|
||||
ubi_warn("static volume %d misses %d LEBs - corrupted",
|
||||
sv->vol_id, sv->used_ebs - sv->leb_count);
|
||||
av->vol_id, av->used_ebs - av->leb_count);
|
||||
vol->corrupted = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
vol->used_ebs = sv->used_ebs;
|
||||
vol->used_ebs = av->used_ebs;
|
||||
vol->used_bytes =
|
||||
(long long)(vol->used_ebs - 1) * vol->usable_leb_size;
|
||||
vol->used_bytes += sv->last_data_size;
|
||||
vol->last_eb_bytes = sv->last_data_size;
|
||||
vol->used_bytes += av->last_data_size;
|
||||
vol->last_eb_bytes = av->last_data_size;
|
||||
}
|
||||
|
||||
/* And add the layout volume */
|
||||
|
@ -664,105 +659,104 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si,
|
|||
}
|
||||
|
||||
/**
|
||||
* check_sv - check volume scanning information.
|
||||
* check_av - check volume attaching information.
|
||||
* @vol: UBI volume description object
|
||||
* @sv: volume scanning information
|
||||
* @av: volume attaching information
|
||||
*
|
||||
* This function returns zero if the volume scanning information is consistent
|
||||
* This function returns zero if the volume attaching information is consistent
|
||||
* to the data read from the volume tabla, and %-EINVAL if not.
|
||||
*/
|
||||
static int check_sv(const struct ubi_volume *vol,
|
||||
const struct ubi_scan_volume *sv)
|
||||
static int check_av(const struct ubi_volume *vol,
|
||||
const struct ubi_ainf_volume *av)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (sv->highest_lnum >= vol->reserved_pebs) {
|
||||
if (av->highest_lnum >= vol->reserved_pebs) {
|
||||
err = 1;
|
||||
goto bad;
|
||||
}
|
||||
if (sv->leb_count > vol->reserved_pebs) {
|
||||
if (av->leb_count > vol->reserved_pebs) {
|
||||
err = 2;
|
||||
goto bad;
|
||||
}
|
||||
if (sv->vol_type != vol->vol_type) {
|
||||
if (av->vol_type != vol->vol_type) {
|
||||
err = 3;
|
||||
goto bad;
|
||||
}
|
||||
if (sv->used_ebs > vol->reserved_pebs) {
|
||||
if (av->used_ebs > vol->reserved_pebs) {
|
||||
err = 4;
|
||||
goto bad;
|
||||
}
|
||||
if (sv->data_pad != vol->data_pad) {
|
||||
if (av->data_pad != vol->data_pad) {
|
||||
err = 5;
|
||||
goto bad;
|
||||
}
|
||||
return 0;
|
||||
|
||||
bad:
|
||||
ubi_err("bad scanning information, error %d", err);
|
||||
ubi_dbg_dump_sv(sv);
|
||||
ubi_dbg_dump_vol_info(vol);
|
||||
ubi_err("bad attaching information, error %d", err);
|
||||
ubi_dump_av(av);
|
||||
ubi_dump_vol_info(vol);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* check_scanning_info - check that scanning information.
|
||||
* check_attaching_info - check that attaching information.
|
||||
* @ubi: UBI device description object
|
||||
* @si: scanning information
|
||||
* @ai: attaching information
|
||||
*
|
||||
* Even though we protect on-flash data by CRC checksums, we still don't trust
|
||||
* the media. This function ensures that scanning information is consistent to
|
||||
* the information read from the volume table. Returns zero if the scanning
|
||||
* the media. This function ensures that attaching information is consistent to
|
||||
* the information read from the volume table. Returns zero if the attaching
|
||||
* information is OK and %-EINVAL if it is not.
|
||||
*/
|
||||
static int check_scanning_info(const struct ubi_device *ubi,
|
||||
struct ubi_scan_info *si)
|
||||
static int check_attaching_info(const struct ubi_device *ubi,
|
||||
struct ubi_attach_info *ai)
|
||||
{
|
||||
int err, i;
|
||||
struct ubi_scan_volume *sv;
|
||||
struct ubi_ainf_volume *av;
|
||||
struct ubi_volume *vol;
|
||||
|
||||
if (si->vols_found > UBI_INT_VOL_COUNT + ubi->vtbl_slots) {
|
||||
ubi_err("scanning found %d volumes, maximum is %d + %d",
|
||||
si->vols_found, UBI_INT_VOL_COUNT, ubi->vtbl_slots);
|
||||
if (ai->vols_found > UBI_INT_VOL_COUNT + ubi->vtbl_slots) {
|
||||
ubi_err("found %d volumes while attaching, maximum is %d + %d",
|
||||
ai->vols_found, UBI_INT_VOL_COUNT, ubi->vtbl_slots);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (si->highest_vol_id >= ubi->vtbl_slots + UBI_INT_VOL_COUNT &&
|
||||
si->highest_vol_id < UBI_INTERNAL_VOL_START) {
|
||||
ubi_err("too large volume ID %d found by scanning",
|
||||
si->highest_vol_id);
|
||||
if (ai->highest_vol_id >= ubi->vtbl_slots + UBI_INT_VOL_COUNT &&
|
||||
ai->highest_vol_id < UBI_INTERNAL_VOL_START) {
|
||||
ubi_err("too large volume ID %d found", ai->highest_vol_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) {
|
||||
cond_resched();
|
||||
|
||||
sv = ubi_scan_find_sv(si, i);
|
||||
av = ubi_find_av(ai, i);
|
||||
vol = ubi->volumes[i];
|
||||
if (!vol) {
|
||||
if (sv)
|
||||
ubi_scan_rm_volume(si, sv);
|
||||
if (av)
|
||||
ubi_remove_av(ai, av);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (vol->reserved_pebs == 0) {
|
||||
ubi_assert(i < ubi->vtbl_slots);
|
||||
|
||||
if (!sv)
|
||||
if (!av)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* During scanning we found a volume which does not
|
||||
* During attaching we found a volume which does not
|
||||
* exist according to the information in the volume
|
||||
* table. This must have happened due to an unclean
|
||||
* reboot while the volume was being removed. Discard
|
||||
* these eraseblocks.
|
||||
*/
|
||||
ubi_msg("finish volume %d removal", sv->vol_id);
|
||||
ubi_scan_rm_volume(si, sv);
|
||||
} else if (sv) {
|
||||
err = check_sv(vol, sv);
|
||||
ubi_msg("finish volume %d removal", av->vol_id);
|
||||
ubi_remove_av(ai, av);
|
||||
} else if (av) {
|
||||
err = check_av(vol, av);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
@ -774,16 +768,16 @@ static int check_scanning_info(const struct ubi_device *ubi,
|
|||
/**
|
||||
* ubi_read_volume_table - read the volume table.
|
||||
* @ubi: UBI device description object
|
||||
* @si: scanning information
|
||||
* @ai: attaching information
|
||||
*
|
||||
* This function reads volume table, checks it, recover from errors if needed,
|
||||
* or creates it if needed. Returns zero in case of success and a negative
|
||||
* error code in case of failure.
|
||||
*/
|
||||
int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si)
|
||||
int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_attach_info *ai)
|
||||
{
|
||||
int i, err;
|
||||
struct ubi_scan_volume *sv;
|
||||
struct ubi_ainf_volume *av;
|
||||
|
||||
empty_vtbl_record.crc = cpu_to_be32(0xf116c36b);
|
||||
|
||||
|
@ -798,8 +792,8 @@ int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si)
|
|||
ubi->vtbl_size = ubi->vtbl_slots * UBI_VTBL_RECORD_SIZE;
|
||||
ubi->vtbl_size = ALIGN(ubi->vtbl_size, ubi->min_io_size);
|
||||
|
||||
sv = ubi_scan_find_sv(si, UBI_LAYOUT_VOLUME_ID);
|
||||
if (!sv) {
|
||||
av = ubi_find_av(ai, UBI_LAYOUT_VOLUME_ID);
|
||||
if (!av) {
|
||||
/*
|
||||
* No logical eraseblocks belonging to the layout volume were
|
||||
* found. This could mean that the flash is just empty. In
|
||||
|
@ -808,8 +802,8 @@ int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si)
|
|||
* But if flash is not empty this must be a corruption or the
|
||||
* MTD device just contains garbage.
|
||||
*/
|
||||
if (si->is_empty) {
|
||||
ubi->vtbl = create_empty_lvol(ubi, si);
|
||||
if (ai->is_empty) {
|
||||
ubi->vtbl = create_empty_lvol(ubi, ai);
|
||||
if (IS_ERR(ubi->vtbl))
|
||||
return PTR_ERR(ubi->vtbl);
|
||||
} else {
|
||||
|
@ -817,14 +811,14 @@ int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si)
|
|||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
if (sv->leb_count > UBI_LAYOUT_VOLUME_EBS) {
|
||||
if (av->leb_count > UBI_LAYOUT_VOLUME_EBS) {
|
||||
/* This must not happen with proper UBI images */
|
||||
dbg_err("too many LEBs (%d) in layout volume",
|
||||
sv->leb_count);
|
||||
ubi_err("too many LEBs (%d) in layout volume",
|
||||
av->leb_count);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ubi->vtbl = process_lvol(ubi, si, sv);
|
||||
ubi->vtbl = process_lvol(ubi, ai, av);
|
||||
if (IS_ERR(ubi->vtbl))
|
||||
return PTR_ERR(ubi->vtbl);
|
||||
}
|
||||
|
@ -835,15 +829,15 @@ int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si)
|
|||
* The layout volume is OK, initialize the corresponding in-RAM data
|
||||
* structures.
|
||||
*/
|
||||
err = init_volumes(ubi, si, ubi->vtbl);
|
||||
err = init_volumes(ubi, ai, ubi->vtbl);
|
||||
if (err)
|
||||
goto out_free;
|
||||
|
||||
/*
|
||||
* Make sure that the scanning information is consistent to the
|
||||
* Make sure that the attaching information is consistent to the
|
||||
* information stored in the volume table.
|
||||
*/
|
||||
err = check_scanning_info(ubi, si);
|
||||
err = check_attaching_info(ubi, ai);
|
||||
if (err)
|
||||
goto out_free;
|
||||
|
||||
|
@ -858,21 +852,17 @@ out_free:
|
|||
return err;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MTD_UBI_DEBUG
|
||||
|
||||
/**
|
||||
* paranoid_vtbl_check - check volume table.
|
||||
* self_vtbl_check - check volume table.
|
||||
* @ubi: UBI device description object
|
||||
*/
|
||||
static void paranoid_vtbl_check(const struct ubi_device *ubi)
|
||||
static void self_vtbl_check(const struct ubi_device *ubi)
|
||||
{
|
||||
if (!ubi->dbg->chk_gen)
|
||||
return;
|
||||
|
||||
if (vtbl_check(ubi, ubi->vtbl)) {
|
||||
ubi_err("paranoid check failed");
|
||||
ubi_err("self-check failed");
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CONFIG_MTD_UBI_DEBUG */
|
||||
|
|
|
@ -41,12 +41,6 @@
|
|||
* physical eraseblocks with low erase counter to free physical eraseblocks
|
||||
* with high erase counter.
|
||||
*
|
||||
* The 'ubi_wl_get_peb()' function accepts data type hints which help to pick
|
||||
* an "optimal" physical eraseblock. For example, when it is known that the
|
||||
* physical eraseblock will be "put" soon because it contains short-term data,
|
||||
* the WL sub-system may pick a free physical eraseblock with low erase
|
||||
* counter, and so forth.
|
||||
*
|
||||
* If the WL sub-system fails to erase a physical eraseblock, it marks it as
|
||||
* bad.
|
||||
*
|
||||
|
@ -70,8 +64,7 @@
|
|||
* to the user; instead, we first want to let users fill them up with data;
|
||||
*
|
||||
* o there is a chance that the user will put the physical eraseblock very
|
||||
* soon, so it makes sense not to move it for some time, but wait; this is
|
||||
* especially important in case of "short term" physical eraseblocks.
|
||||
* soon, so it makes sense not to move it for some time, but wait.
|
||||
*
|
||||
* Physical eraseblocks stay protected only for limited time. But the "time" is
|
||||
* measured in erase cycles in this case. This is implemented with help of the
|
||||
|
@ -147,6 +140,8 @@
|
|||
* @list: a link in the list of pending works
|
||||
* @func: worker function
|
||||
* @e: physical eraseblock to erase
|
||||
* @vol_id: the volume ID on which this erasure is being performed
|
||||
* @lnum: the logical eraseblock number
|
||||
* @torture: if the physical eraseblock has to be tortured
|
||||
*
|
||||
* The @func pointer points to the worker function. If the @cancel argument is
|
||||
|
@ -159,21 +154,16 @@ struct ubi_work {
|
|||
int (*func)(struct ubi_device *ubi, struct ubi_work *wrk, int cancel);
|
||||
/* The below fields are only relevant to erasure works */
|
||||
struct ubi_wl_entry *e;
|
||||
int vol_id;
|
||||
int lnum;
|
||||
int torture;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_MTD_UBI_DEBUG
|
||||
static int paranoid_check_ec(struct ubi_device *ubi, int pnum, int ec);
|
||||
static int paranoid_check_in_wl_tree(const struct ubi_device *ubi,
|
||||
struct ubi_wl_entry *e,
|
||||
struct rb_root *root);
|
||||
static int paranoid_check_in_pq(const struct ubi_device *ubi,
|
||||
struct ubi_wl_entry *e);
|
||||
#else
|
||||
#define paranoid_check_ec(ubi, pnum, ec) 0
|
||||
#define paranoid_check_in_wl_tree(ubi, e, root)
|
||||
#define paranoid_check_in_pq(ubi, e) 0
|
||||
#endif
|
||||
static int self_check_ec(struct ubi_device *ubi, int pnum, int ec);
|
||||
static int self_check_in_wl_tree(const struct ubi_device *ubi,
|
||||
struct ubi_wl_entry *e, struct rb_root *root);
|
||||
static int self_check_in_pq(const struct ubi_device *ubi,
|
||||
struct ubi_wl_entry *e);
|
||||
|
||||
/**
|
||||
* wl_tree_add - add a wear-leveling entry to a WL RB-tree.
|
||||
|
@ -383,19 +373,15 @@ static struct ubi_wl_entry *find_wl_entry(struct rb_root *root, int diff)
|
|||
/**
|
||||
* ubi_wl_get_peb - get a physical eraseblock.
|
||||
* @ubi: UBI device description object
|
||||
* @dtype: type of data which will be stored in this physical eraseblock
|
||||
*
|
||||
* This function returns a physical eraseblock in case of success and a
|
||||
* negative error code in case of failure. Might sleep.
|
||||
*/
|
||||
int ubi_wl_get_peb(struct ubi_device *ubi, int dtype)
|
||||
int ubi_wl_get_peb(struct ubi_device *ubi)
|
||||
{
|
||||
int err;
|
||||
struct ubi_wl_entry *e, *first, *last;
|
||||
|
||||
ubi_assert(dtype == UBI_LONGTERM || dtype == UBI_SHORTTERM ||
|
||||
dtype == UBI_UNKNOWN);
|
||||
|
||||
retry:
|
||||
spin_lock(&ubi->wl_lock);
|
||||
if (!ubi->free.rb_node) {
|
||||
|
@ -413,45 +399,15 @@ retry:
|
|||
goto retry;
|
||||
}
|
||||
|
||||
switch (dtype) {
|
||||
case UBI_LONGTERM:
|
||||
/*
|
||||
* For long term data we pick a physical eraseblock with high
|
||||
* erase counter. But the highest erase counter we can pick is
|
||||
* bounded by the the lowest erase counter plus
|
||||
* %WL_FREE_MAX_DIFF.
|
||||
*/
|
||||
e = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF);
|
||||
break;
|
||||
case UBI_UNKNOWN:
|
||||
/*
|
||||
* For unknown data we pick a physical eraseblock with medium
|
||||
* erase counter. But we by no means can pick a physical
|
||||
* eraseblock with erase counter greater or equivalent than the
|
||||
* lowest erase counter plus %WL_FREE_MAX_DIFF/2.
|
||||
*/
|
||||
first = rb_entry(rb_first(&ubi->free), struct ubi_wl_entry,
|
||||
u.rb);
|
||||
last = rb_entry(rb_last(&ubi->free), struct ubi_wl_entry, u.rb);
|
||||
first = rb_entry(rb_first(&ubi->free), struct ubi_wl_entry, u.rb);
|
||||
last = rb_entry(rb_last(&ubi->free), struct ubi_wl_entry, u.rb);
|
||||
|
||||
if (last->ec - first->ec < WL_FREE_MAX_DIFF)
|
||||
e = rb_entry(ubi->free.rb_node,
|
||||
struct ubi_wl_entry, u.rb);
|
||||
else
|
||||
e = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF/2);
|
||||
break;
|
||||
case UBI_SHORTTERM:
|
||||
/*
|
||||
* For short term data we pick a physical eraseblock with the
|
||||
* lowest erase counter as we expect it will be erased soon.
|
||||
*/
|
||||
e = rb_entry(rb_first(&ubi->free), struct ubi_wl_entry, u.rb);
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
if (last->ec - first->ec < WL_FREE_MAX_DIFF)
|
||||
e = rb_entry(ubi->free.rb_node, struct ubi_wl_entry, u.rb);
|
||||
else
|
||||
e = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF/2);
|
||||
|
||||
paranoid_check_in_wl_tree(ubi, e, &ubi->free);
|
||||
self_check_in_wl_tree(ubi, e, &ubi->free);
|
||||
|
||||
/*
|
||||
* Move the physical eraseblock to the protection queue where it will
|
||||
|
@ -462,8 +418,8 @@ retry:
|
|||
prot_queue_add(ubi, e);
|
||||
spin_unlock(&ubi->wl_lock);
|
||||
|
||||
err = ubi_dbg_check_all_ff(ubi, e->pnum, ubi->vid_hdr_aloffset,
|
||||
ubi->peb_size - ubi->vid_hdr_aloffset);
|
||||
err = ubi_self_check_all_ff(ubi, e->pnum, ubi->vid_hdr_aloffset,
|
||||
ubi->peb_size - ubi->vid_hdr_aloffset);
|
||||
if (err) {
|
||||
ubi_err("new PEB %d does not contain all 0xFF bytes", e->pnum);
|
||||
return err;
|
||||
|
@ -488,7 +444,7 @@ static int prot_queue_del(struct ubi_device *ubi, int pnum)
|
|||
if (!e)
|
||||
return -ENODEV;
|
||||
|
||||
if (paranoid_check_in_pq(ubi, e))
|
||||
if (self_check_in_pq(ubi, e))
|
||||
return -ENODEV;
|
||||
|
||||
list_del(&e->u.list);
|
||||
|
@ -514,7 +470,7 @@ static int sync_erase(struct ubi_device *ubi, struct ubi_wl_entry *e,
|
|||
|
||||
dbg_wl("erase PEB %d, old EC %llu", e->pnum, ec);
|
||||
|
||||
err = paranoid_check_ec(ubi, e->pnum, e->ec);
|
||||
err = self_check_ec(ubi, e->pnum, e->ec);
|
||||
if (err)
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -627,13 +583,15 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
|
|||
* schedule_erase - schedule an erase work.
|
||||
* @ubi: UBI device description object
|
||||
* @e: the WL entry of the physical eraseblock to erase
|
||||
* @vol_id: the volume ID that last used this PEB
|
||||
* @lnum: the last used logical eraseblock number for the PEB
|
||||
* @torture: if the physical eraseblock has to be tortured
|
||||
*
|
||||
* This function returns zero in case of success and a %-ENOMEM in case of
|
||||
* failure.
|
||||
*/
|
||||
static int schedule_erase(struct ubi_device *ubi, struct ubi_wl_entry *e,
|
||||
int torture)
|
||||
int vol_id, int lnum, int torture)
|
||||
{
|
||||
struct ubi_work *wl_wrk;
|
||||
|
||||
|
@ -646,6 +604,8 @@ static int schedule_erase(struct ubi_device *ubi, struct ubi_wl_entry *e,
|
|||
|
||||
wl_wrk->func = &erase_worker;
|
||||
wl_wrk->e = e;
|
||||
wl_wrk->vol_id = vol_id;
|
||||
wl_wrk->lnum = lnum;
|
||||
wl_wrk->torture = torture;
|
||||
|
||||
schedule_ubi_work(ubi, wl_wrk);
|
||||
|
@ -714,7 +674,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
|
|||
e1->ec, e2->ec);
|
||||
goto out_cancel;
|
||||
}
|
||||
paranoid_check_in_wl_tree(ubi, e1, &ubi->used);
|
||||
self_check_in_wl_tree(ubi, e1, &ubi->used);
|
||||
rb_erase(&e1->u.rb, &ubi->used);
|
||||
dbg_wl("move PEB %d EC %d to PEB %d EC %d",
|
||||
e1->pnum, e1->ec, e2->pnum, e2->ec);
|
||||
|
@ -723,12 +683,12 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
|
|||
scrubbing = 1;
|
||||
e1 = rb_entry(rb_first(&ubi->scrub), struct ubi_wl_entry, u.rb);
|
||||
e2 = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF);
|
||||
paranoid_check_in_wl_tree(ubi, e1, &ubi->scrub);
|
||||
self_check_in_wl_tree(ubi, e1, &ubi->scrub);
|
||||
rb_erase(&e1->u.rb, &ubi->scrub);
|
||||
dbg_wl("scrub PEB %d to PEB %d", e1->pnum, e2->pnum);
|
||||
}
|
||||
|
||||
paranoid_check_in_wl_tree(ubi, e2, &ubi->free);
|
||||
self_check_in_wl_tree(ubi, e2, &ubi->free);
|
||||
rb_erase(&e2->u.rb, &ubi->free);
|
||||
ubi->move_from = e1;
|
||||
ubi->move_to = e2;
|
||||
|
@ -846,7 +806,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
|
|||
ubi->move_to_put = ubi->wl_scheduled = 0;
|
||||
spin_unlock(&ubi->wl_lock);
|
||||
|
||||
err = schedule_erase(ubi, e1, 0);
|
||||
err = schedule_erase(ubi, e1, vol_id, lnum, 0);
|
||||
if (err) {
|
||||
kmem_cache_free(ubi_wl_entry_slab, e1);
|
||||
if (e2)
|
||||
|
@ -861,7 +821,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
|
|||
*/
|
||||
dbg_wl("PEB %d (LEB %d:%d) was put meanwhile, erase",
|
||||
e2->pnum, vol_id, lnum);
|
||||
err = schedule_erase(ubi, e2, 0);
|
||||
err = schedule_erase(ubi, e2, vol_id, lnum, 0);
|
||||
if (err) {
|
||||
kmem_cache_free(ubi_wl_entry_slab, e2);
|
||||
goto out_ro;
|
||||
|
@ -900,7 +860,7 @@ out_not_moved:
|
|||
spin_unlock(&ubi->wl_lock);
|
||||
|
||||
ubi_free_vid_hdr(ubi, vid_hdr);
|
||||
err = schedule_erase(ubi, e2, torture);
|
||||
err = schedule_erase(ubi, e2, vol_id, lnum, torture);
|
||||
if (err) {
|
||||
kmem_cache_free(ubi_wl_entry_slab, e2);
|
||||
goto out_ro;
|
||||
|
@ -1019,6 +979,8 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
|
|||
{
|
||||
struct ubi_wl_entry *e = wl_wrk->e;
|
||||
int pnum = e->pnum, err, need;
|
||||
int vol_id = wl_wrk->vol_id;
|
||||
int lnum = wl_wrk->lnum;
|
||||
|
||||
if (cancel) {
|
||||
dbg_wl("cancel erasure of PEB %d EC %d", pnum, e->ec);
|
||||
|
@ -1027,7 +989,8 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
|
|||
return 0;
|
||||
}
|
||||
|
||||
dbg_wl("erase PEB %d EC %d", pnum, e->ec);
|
||||
dbg_wl("erase PEB %d EC %d LEB %d:%d",
|
||||
pnum, e->ec, wl_wrk->vol_id, wl_wrk->lnum);
|
||||
|
||||
err = sync_erase(ubi, e, wl_wrk->torture);
|
||||
if (!err) {
|
||||
|
@ -1057,7 +1020,7 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
|
|||
int err1;
|
||||
|
||||
/* Re-schedule the LEB for erasure */
|
||||
err1 = schedule_erase(ubi, e, 0);
|
||||
err1 = schedule_erase(ubi, e, vol_id, lnum, 0);
|
||||
if (err1) {
|
||||
err = err1;
|
||||
goto out_ro;
|
||||
|
@ -1125,6 +1088,8 @@ out_ro:
|
|||
/**
|
||||
* ubi_wl_put_peb - return a PEB to the wear-leveling sub-system.
|
||||
* @ubi: UBI device description object
|
||||
* @vol_id: the volume ID that last used this PEB
|
||||
* @lnum: the last used logical eraseblock number for the PEB
|
||||
* @pnum: physical eraseblock to return
|
||||
* @torture: if this physical eraseblock has to be tortured
|
||||
*
|
||||
|
@ -1133,7 +1098,8 @@ out_ro:
|
|||
* occurred to this @pnum and it has to be tested. This function returns zero
|
||||
* in case of success, and a negative error code in case of failure.
|
||||
*/
|
||||
int ubi_wl_put_peb(struct ubi_device *ubi, int pnum, int torture)
|
||||
int ubi_wl_put_peb(struct ubi_device *ubi, int vol_id, int lnum,
|
||||
int pnum, int torture)
|
||||
{
|
||||
int err;
|
||||
struct ubi_wl_entry *e;
|
||||
|
@ -1175,13 +1141,13 @@ retry:
|
|||
return 0;
|
||||
} else {
|
||||
if (in_wl_tree(e, &ubi->used)) {
|
||||
paranoid_check_in_wl_tree(ubi, e, &ubi->used);
|
||||
self_check_in_wl_tree(ubi, e, &ubi->used);
|
||||
rb_erase(&e->u.rb, &ubi->used);
|
||||
} else if (in_wl_tree(e, &ubi->scrub)) {
|
||||
paranoid_check_in_wl_tree(ubi, e, &ubi->scrub);
|
||||
self_check_in_wl_tree(ubi, e, &ubi->scrub);
|
||||
rb_erase(&e->u.rb, &ubi->scrub);
|
||||
} else if (in_wl_tree(e, &ubi->erroneous)) {
|
||||
paranoid_check_in_wl_tree(ubi, e, &ubi->erroneous);
|
||||
self_check_in_wl_tree(ubi, e, &ubi->erroneous);
|
||||
rb_erase(&e->u.rb, &ubi->erroneous);
|
||||
ubi->erroneous_peb_count -= 1;
|
||||
ubi_assert(ubi->erroneous_peb_count >= 0);
|
||||
|
@ -1199,7 +1165,7 @@ retry:
|
|||
}
|
||||
spin_unlock(&ubi->wl_lock);
|
||||
|
||||
err = schedule_erase(ubi, e, torture);
|
||||
err = schedule_erase(ubi, e, vol_id, lnum, torture);
|
||||
if (err) {
|
||||
spin_lock(&ubi->wl_lock);
|
||||
wl_tree_add(e, &ubi->used);
|
||||
|
@ -1248,7 +1214,7 @@ retry:
|
|||
}
|
||||
|
||||
if (in_wl_tree(e, &ubi->used)) {
|
||||
paranoid_check_in_wl_tree(ubi, e, &ubi->used);
|
||||
self_check_in_wl_tree(ubi, e, &ubi->used);
|
||||
rb_erase(&e->u.rb, &ubi->used);
|
||||
} else {
|
||||
int err;
|
||||
|
@ -1275,44 +1241,55 @@ retry:
|
|||
/**
|
||||
* ubi_wl_flush - flush all pending works.
|
||||
* @ubi: UBI device description object
|
||||
* @vol_id: the volume id to flush for
|
||||
* @lnum: the logical eraseblock number to flush for
|
||||
*
|
||||
* This function returns zero in case of success and a negative error code in
|
||||
* case of failure.
|
||||
* This function executes all pending works for a particular volume id /
|
||||
* logical eraseblock number pair. If either value is set to %UBI_ALL, then it
|
||||
* acts as a wildcard for all of the corresponding volume numbers or logical
|
||||
* eraseblock numbers. It returns zero in case of success and a negative error
|
||||
* code in case of failure.
|
||||
*/
|
||||
int ubi_wl_flush(struct ubi_device *ubi)
|
||||
int ubi_wl_flush(struct ubi_device *ubi, int vol_id, int lnum)
|
||||
{
|
||||
int err;
|
||||
int err = 0;
|
||||
int found = 1;
|
||||
|
||||
/*
|
||||
* Erase while the pending works queue is not empty, but not more than
|
||||
* the number of currently pending works.
|
||||
*/
|
||||
dbg_wl("flush (%d pending works)", ubi->works_count);
|
||||
while (ubi->works_count) {
|
||||
err = do_work(ubi);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
dbg_wl("flush pending work for LEB %d:%d (%d pending works)",
|
||||
vol_id, lnum, ubi->works_count);
|
||||
|
||||
/*
|
||||
* Make sure all the works which have been done in parallel are
|
||||
* finished.
|
||||
*/
|
||||
down_write(&ubi->work_sem);
|
||||
up_write(&ubi->work_sem);
|
||||
while (found) {
|
||||
struct ubi_work *wrk;
|
||||
found = 0;
|
||||
|
||||
/*
|
||||
* And in case last was the WL worker and it canceled the LEB
|
||||
* movement, flush again.
|
||||
*/
|
||||
while (ubi->works_count) {
|
||||
dbg_wl("flush more (%d pending works)", ubi->works_count);
|
||||
err = do_work(ubi);
|
||||
if (err)
|
||||
return err;
|
||||
spin_lock(&ubi->wl_lock);
|
||||
list_for_each_entry(wrk, &ubi->works, list) {
|
||||
if ((vol_id == UBI_ALL || wrk->vol_id == vol_id) &&
|
||||
(lnum == UBI_ALL || wrk->lnum == lnum)) {
|
||||
list_del(&wrk->list);
|
||||
ubi->works_count -= 1;
|
||||
ubi_assert(ubi->works_count >= 0);
|
||||
spin_unlock(&ubi->wl_lock);
|
||||
|
||||
err = wrk->func(ubi, wrk, 0);
|
||||
if (err)
|
||||
goto out;
|
||||
spin_lock(&ubi->wl_lock);
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock(&ubi->wl_lock);
|
||||
}
|
||||
|
||||
return 0;
|
||||
out:
|
||||
up_write(&ubi->work_sem);
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1421,26 +1398,26 @@ static void cancel_pending(struct ubi_device *ubi)
|
|||
}
|
||||
|
||||
/**
|
||||
* ubi_wl_init_scan - initialize the WL sub-system using scanning information.
|
||||
* ubi_wl_init - initialize the WL sub-system using attaching information.
|
||||
* @ubi: UBI device description object
|
||||
* @si: scanning information
|
||||
* @ai: attaching information
|
||||
*
|
||||
* This function returns zero in case of success, and a negative error code in
|
||||
* case of failure.
|
||||
*/
|
||||
int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
|
||||
int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai)
|
||||
{
|
||||
int err, i;
|
||||
struct rb_node *rb1, *rb2;
|
||||
struct ubi_scan_volume *sv;
|
||||
struct ubi_scan_leb *seb, *tmp;
|
||||
struct ubi_ainf_volume *av;
|
||||
struct ubi_ainf_peb *aeb, *tmp;
|
||||
struct ubi_wl_entry *e;
|
||||
|
||||
ubi->used = ubi->erroneous = ubi->free = ubi->scrub = RB_ROOT;
|
||||
spin_lock_init(&ubi->wl_lock);
|
||||
mutex_init(&ubi->move_mutex);
|
||||
init_rwsem(&ubi->work_sem);
|
||||
ubi->max_ec = si->max_ec;
|
||||
ubi->max_ec = ai->max_ec;
|
||||
INIT_LIST_HEAD(&ubi->works);
|
||||
|
||||
sprintf(ubi->bgt_name, UBI_BGT_NAME_PATTERN, ubi->ubi_num);
|
||||
|
@ -1454,48 +1431,48 @@ int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
|
|||
INIT_LIST_HEAD(&ubi->pq[i]);
|
||||
ubi->pq_head = 0;
|
||||
|
||||
list_for_each_entry_safe(seb, tmp, &si->erase, u.list) {
|
||||
list_for_each_entry_safe(aeb, tmp, &ai->erase, u.list) {
|
||||
cond_resched();
|
||||
|
||||
e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL);
|
||||
if (!e)
|
||||
goto out_free;
|
||||
|
||||
e->pnum = seb->pnum;
|
||||
e->ec = seb->ec;
|
||||
e->pnum = aeb->pnum;
|
||||
e->ec = aeb->ec;
|
||||
ubi->lookuptbl[e->pnum] = e;
|
||||
if (schedule_erase(ubi, e, 0)) {
|
||||
if (schedule_erase(ubi, e, aeb->vol_id, aeb->lnum, 0)) {
|
||||
kmem_cache_free(ubi_wl_entry_slab, e);
|
||||
goto out_free;
|
||||
}
|
||||
}
|
||||
|
||||
list_for_each_entry(seb, &si->free, u.list) {
|
||||
list_for_each_entry(aeb, &ai->free, u.list) {
|
||||
cond_resched();
|
||||
|
||||
e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL);
|
||||
if (!e)
|
||||
goto out_free;
|
||||
|
||||
e->pnum = seb->pnum;
|
||||
e->ec = seb->ec;
|
||||
e->pnum = aeb->pnum;
|
||||
e->ec = aeb->ec;
|
||||
ubi_assert(e->ec >= 0);
|
||||
wl_tree_add(e, &ubi->free);
|
||||
ubi->lookuptbl[e->pnum] = e;
|
||||
}
|
||||
|
||||
ubi_rb_for_each_entry(rb1, sv, &si->volumes, rb) {
|
||||
ubi_rb_for_each_entry(rb2, seb, &sv->root, u.rb) {
|
||||
ubi_rb_for_each_entry(rb1, av, &ai->volumes, rb) {
|
||||
ubi_rb_for_each_entry(rb2, aeb, &av->root, u.rb) {
|
||||
cond_resched();
|
||||
|
||||
e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL);
|
||||
if (!e)
|
||||
goto out_free;
|
||||
|
||||
e->pnum = seb->pnum;
|
||||
e->ec = seb->ec;
|
||||
e->pnum = aeb->pnum;
|
||||
e->ec = aeb->ec;
|
||||
ubi->lookuptbl[e->pnum] = e;
|
||||
if (!seb->scrub) {
|
||||
if (!aeb->scrub) {
|
||||
dbg_wl("add PEB %d EC %d to the used tree",
|
||||
e->pnum, e->ec);
|
||||
wl_tree_add(e, &ubi->used);
|
||||
|
@ -1567,10 +1544,8 @@ void ubi_wl_close(struct ubi_device *ubi)
|
|||
kfree(ubi->lookuptbl);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MTD_UBI_DEBUG
|
||||
|
||||
/**
|
||||
* paranoid_check_ec - make sure that the erase counter of a PEB is correct.
|
||||
* self_check_ec - make sure that the erase counter of a PEB is correct.
|
||||
* @ubi: UBI device description object
|
||||
* @pnum: the physical eraseblock number to check
|
||||
* @ec: the erase counter to check
|
||||
|
@ -1579,7 +1554,7 @@ void ubi_wl_close(struct ubi_device *ubi)
|
|||
* is equivalent to @ec, and a negative error code if not or if an error
|
||||
* occurred.
|
||||
*/
|
||||
static int paranoid_check_ec(struct ubi_device *ubi, int pnum, int ec)
|
||||
static int self_check_ec(struct ubi_device *ubi, int pnum, int ec)
|
||||
{
|
||||
int err;
|
||||
long long read_ec;
|
||||
|
@ -1601,9 +1576,9 @@ static int paranoid_check_ec(struct ubi_device *ubi, int pnum, int ec)
|
|||
|
||||
read_ec = be64_to_cpu(ec_hdr->ec);
|
||||
if (ec != read_ec) {
|
||||
ubi_err("paranoid check failed for PEB %d", pnum);
|
||||
ubi_err("self-check failed for PEB %d", pnum);
|
||||
ubi_err("read EC is %lld, should be %d", read_ec, ec);
|
||||
ubi_dbg_dump_stack();
|
||||
dump_stack();
|
||||
err = 1;
|
||||
} else
|
||||
err = 0;
|
||||
|
@ -1614,7 +1589,7 @@ out_free:
|
|||
}
|
||||
|
||||
/**
|
||||
* paranoid_check_in_wl_tree - check that wear-leveling entry is in WL RB-tree.
|
||||
* self_check_in_wl_tree - check that wear-leveling entry is in WL RB-tree.
|
||||
* @ubi: UBI device description object
|
||||
* @e: the wear-leveling entry to check
|
||||
* @root: the root of the tree
|
||||
|
@ -1622,9 +1597,8 @@ out_free:
|
|||
* This function returns zero if @e is in the @root RB-tree and %-EINVAL if it
|
||||
* is not.
|
||||
*/
|
||||
static int paranoid_check_in_wl_tree(const struct ubi_device *ubi,
|
||||
struct ubi_wl_entry *e,
|
||||
struct rb_root *root)
|
||||
static int self_check_in_wl_tree(const struct ubi_device *ubi,
|
||||
struct ubi_wl_entry *e, struct rb_root *root)
|
||||
{
|
||||
if (!ubi->dbg->chk_gen)
|
||||
return 0;
|
||||
|
@ -1632,22 +1606,22 @@ static int paranoid_check_in_wl_tree(const struct ubi_device *ubi,
|
|||
if (in_wl_tree(e, root))
|
||||
return 0;
|
||||
|
||||
ubi_err("paranoid check failed for PEB %d, EC %d, RB-tree %p ",
|
||||
ubi_err("self-check failed for PEB %d, EC %d, RB-tree %p ",
|
||||
e->pnum, e->ec, root);
|
||||
ubi_dbg_dump_stack();
|
||||
dump_stack();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* paranoid_check_in_pq - check if wear-leveling entry is in the protection
|
||||
* self_check_in_pq - check if wear-leveling entry is in the protection
|
||||
* queue.
|
||||
* @ubi: UBI device description object
|
||||
* @e: the wear-leveling entry to check
|
||||
*
|
||||
* This function returns zero if @e is in @ubi->pq and %-EINVAL if it is not.
|
||||
*/
|
||||
static int paranoid_check_in_pq(const struct ubi_device *ubi,
|
||||
struct ubi_wl_entry *e)
|
||||
static int self_check_in_pq(const struct ubi_device *ubi,
|
||||
struct ubi_wl_entry *e)
|
||||
{
|
||||
struct ubi_wl_entry *p;
|
||||
int i;
|
||||
|
@ -1660,10 +1634,8 @@ static int paranoid_check_in_pq(const struct ubi_device *ubi,
|
|||
if (p == e)
|
||||
return 0;
|
||||
|
||||
ubi_err("paranoid check failed for PEB %d, EC %d, Protect queue",
|
||||
ubi_err("self-check failed for PEB %d, EC %d, Protect queue",
|
||||
e->pnum, e->ec);
|
||||
ubi_dbg_dump_stack();
|
||||
dump_stack();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_MTD_UBI_DEBUG */
|
||||
|
|
|
@ -11,12 +11,6 @@ config UBIFS_FS
|
|||
help
|
||||
UBIFS is a file system for flash devices which works on top of UBI.
|
||||
|
||||
config UBIFS_FS_XATTR
|
||||
bool "Extended attributes support"
|
||||
depends on UBIFS_FS
|
||||
help
|
||||
This option enables support of extended attributes.
|
||||
|
||||
config UBIFS_FS_ADVANCED_COMPR
|
||||
bool "Advanced compression options"
|
||||
depends on UBIFS_FS
|
||||
|
@ -41,20 +35,3 @@ config UBIFS_FS_ZLIB
|
|||
default y
|
||||
help
|
||||
Zlib compresses better than LZO but it is slower. Say 'Y' if unsure.
|
||||
|
||||
# Debugging-related stuff
|
||||
config UBIFS_FS_DEBUG
|
||||
bool "Enable debugging support"
|
||||
depends on UBIFS_FS
|
||||
select DEBUG_FS
|
||||
select KALLSYMS
|
||||
help
|
||||
This option enables UBIFS debugging support. It makes sure various
|
||||
assertions, self-checks, debugging messages and test modes are compiled
|
||||
in (this all is compiled out otherwise). Assertions are light-weight
|
||||
and this option also enables them. Self-checks, debugging messages and
|
||||
test modes are switched off by default. Thus, it is safe and actually
|
||||
recommended to have debugging support enabled, and it should not slow
|
||||
down UBIFS. You can then further enable / disable individual debugging
|
||||
features using UBIFS module parameters and the corresponding sysfs
|
||||
interfaces.
|
||||
|
|
|
@ -3,7 +3,4 @@ obj-$(CONFIG_UBIFS_FS) += ubifs.o
|
|||
ubifs-y += shrinker.o journal.o file.o dir.o super.o sb.o io.o
|
||||
ubifs-y += tnc.o master.o scan.o replay.o log.o commit.o gc.o orphan.o
|
||||
ubifs-y += budget.o find.o tnc_commit.o compress.o lpt.o lprops.o
|
||||
ubifs-y += recovery.o ioctl.o lpt_commit.o tnc_misc.o
|
||||
|
||||
ubifs-$(CONFIG_UBIFS_FS_DEBUG) += debug.o
|
||||
ubifs-$(CONFIG_UBIFS_FS_XATTR) += xattr.o
|
||||
ubifs-y += recovery.o ioctl.o lpt_commit.o tnc_misc.o xattr.o debug.o
|
||||
|
|
|
@ -496,7 +496,9 @@ int ubifs_gc_should_commit(struct ubifs_info *c)
|
|||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_UBIFS_FS_DEBUG
|
||||
/*
|
||||
* Everything below is related to debugging.
|
||||
*/
|
||||
|
||||
/**
|
||||
* struct idx_node - hold index nodes during index tree traversal.
|
||||
|
@ -714,14 +716,14 @@ out:
|
|||
return 0;
|
||||
|
||||
out_dump:
|
||||
dbg_err("dumping index node (iip=%d)", i->iip);
|
||||
dbg_dump_node(c, idx);
|
||||
ubifs_err("dumping index node (iip=%d)", i->iip);
|
||||
ubifs_dump_node(c, idx);
|
||||
list_del(&i->list);
|
||||
kfree(i);
|
||||
if (!list_empty(&list)) {
|
||||
i = list_entry(list.prev, struct idx_node, list);
|
||||
dbg_err("dumping parent index node");
|
||||
dbg_dump_node(c, &i->idx);
|
||||
ubifs_err("dumping parent index node");
|
||||
ubifs_dump_node(c, &i->idx);
|
||||
}
|
||||
out_free:
|
||||
while (!list_empty(&list)) {
|
||||
|
@ -734,5 +736,3 @@ out_free:
|
|||
err = -EINVAL;
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_UBIFS_FS_DEBUG */
|
||||
|
|
158
fs/ubifs/debug.c
158
fs/ubifs/debug.c
|
@ -34,8 +34,6 @@
|
|||
#include <linux/random.h>
|
||||
#include "ubifs.h"
|
||||
|
||||
#ifdef CONFIG_UBIFS_FS_DEBUG
|
||||
|
||||
static DEFINE_SPINLOCK(dbg_lock);
|
||||
|
||||
static const char *get_key_fmt(int fmt)
|
||||
|
@ -232,7 +230,7 @@ static void dump_ch(const struct ubifs_ch *ch)
|
|||
printk(KERN_ERR "\tlen %u\n", le32_to_cpu(ch->len));
|
||||
}
|
||||
|
||||
void dbg_dump_inode(struct ubifs_info *c, const struct inode *inode)
|
||||
void ubifs_dump_inode(struct ubifs_info *c, const struct inode *inode)
|
||||
{
|
||||
const struct ubifs_inode *ui = ubifs_inode(inode);
|
||||
struct qstr nm = { .name = NULL };
|
||||
|
@ -300,7 +298,7 @@ void dbg_dump_inode(struct ubifs_info *c, const struct inode *inode)
|
|||
kfree(pdent);
|
||||
}
|
||||
|
||||
void dbg_dump_node(const struct ubifs_info *c, const void *node)
|
||||
void ubifs_dump_node(const struct ubifs_info *c, const void *node)
|
||||
{
|
||||
int i, n;
|
||||
union ubifs_key key;
|
||||
|
@ -603,7 +601,7 @@ void dbg_dump_node(const struct ubifs_info *c, const void *node)
|
|||
spin_unlock(&dbg_lock);
|
||||
}
|
||||
|
||||
void dbg_dump_budget_req(const struct ubifs_budget_req *req)
|
||||
void ubifs_dump_budget_req(const struct ubifs_budget_req *req)
|
||||
{
|
||||
spin_lock(&dbg_lock);
|
||||
printk(KERN_ERR "Budgeting request: new_ino %d, dirtied_ino %d\n",
|
||||
|
@ -620,7 +618,7 @@ void dbg_dump_budget_req(const struct ubifs_budget_req *req)
|
|||
spin_unlock(&dbg_lock);
|
||||
}
|
||||
|
||||
void dbg_dump_lstats(const struct ubifs_lp_stats *lst)
|
||||
void ubifs_dump_lstats(const struct ubifs_lp_stats *lst)
|
||||
{
|
||||
spin_lock(&dbg_lock);
|
||||
printk(KERN_ERR "(pid %d) Lprops statistics: empty_lebs %d, "
|
||||
|
@ -634,7 +632,7 @@ void dbg_dump_lstats(const struct ubifs_lp_stats *lst)
|
|||
spin_unlock(&dbg_lock);
|
||||
}
|
||||
|
||||
void dbg_dump_budg(struct ubifs_info *c, const struct ubifs_budg_info *bi)
|
||||
void ubifs_dump_budg(struct ubifs_info *c, const struct ubifs_budg_info *bi)
|
||||
{
|
||||
int i;
|
||||
struct rb_node *rb;
|
||||
|
@ -707,7 +705,7 @@ out_unlock:
|
|||
spin_unlock(&c->space_lock);
|
||||
}
|
||||
|
||||
void dbg_dump_lprop(const struct ubifs_info *c, const struct ubifs_lprops *lp)
|
||||
void ubifs_dump_lprop(const struct ubifs_info *c, const struct ubifs_lprops *lp)
|
||||
{
|
||||
int i, spc, dark = 0, dead = 0;
|
||||
struct rb_node *rb;
|
||||
|
@ -801,7 +799,7 @@ void dbg_dump_lprop(const struct ubifs_info *c, const struct ubifs_lprops *lp)
|
|||
printk(KERN_CONT ")\n");
|
||||
}
|
||||
|
||||
void dbg_dump_lprops(struct ubifs_info *c)
|
||||
void ubifs_dump_lprops(struct ubifs_info *c)
|
||||
{
|
||||
int lnum, err;
|
||||
struct ubifs_lprops lp;
|
||||
|
@ -810,20 +808,20 @@ void dbg_dump_lprops(struct ubifs_info *c)
|
|||
printk(KERN_ERR "(pid %d) start dumping LEB properties\n",
|
||||
current->pid);
|
||||
ubifs_get_lp_stats(c, &lst);
|
||||
dbg_dump_lstats(&lst);
|
||||
ubifs_dump_lstats(&lst);
|
||||
|
||||
for (lnum = c->main_first; lnum < c->leb_cnt; lnum++) {
|
||||
err = ubifs_read_one_lp(c, lnum, &lp);
|
||||
if (err)
|
||||
ubifs_err("cannot read lprops for LEB %d", lnum);
|
||||
|
||||
dbg_dump_lprop(c, &lp);
|
||||
ubifs_dump_lprop(c, &lp);
|
||||
}
|
||||
printk(KERN_ERR "(pid %d) finish dumping LEB properties\n",
|
||||
current->pid);
|
||||
}
|
||||
|
||||
void dbg_dump_lpt_info(struct ubifs_info *c)
|
||||
void ubifs_dump_lpt_info(struct ubifs_info *c)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -862,8 +860,8 @@ void dbg_dump_lpt_info(struct ubifs_info *c)
|
|||
spin_unlock(&dbg_lock);
|
||||
}
|
||||
|
||||
void dbg_dump_sleb(const struct ubifs_info *c,
|
||||
const struct ubifs_scan_leb *sleb, int offs)
|
||||
void ubifs_dump_sleb(const struct ubifs_info *c,
|
||||
const struct ubifs_scan_leb *sleb, int offs)
|
||||
{
|
||||
struct ubifs_scan_node *snod;
|
||||
|
||||
|
@ -874,11 +872,11 @@ void dbg_dump_sleb(const struct ubifs_info *c,
|
|||
cond_resched();
|
||||
printk(KERN_ERR "Dumping node at LEB %d:%d len %d\n", sleb->lnum,
|
||||
snod->offs, snod->len);
|
||||
dbg_dump_node(c, snod->node);
|
||||
ubifs_dump_node(c, snod->node);
|
||||
}
|
||||
}
|
||||
|
||||
void dbg_dump_leb(const struct ubifs_info *c, int lnum)
|
||||
void ubifs_dump_leb(const struct ubifs_info *c, int lnum)
|
||||
{
|
||||
struct ubifs_scan_leb *sleb;
|
||||
struct ubifs_scan_node *snod;
|
||||
|
@ -909,7 +907,7 @@ void dbg_dump_leb(const struct ubifs_info *c, int lnum)
|
|||
cond_resched();
|
||||
printk(KERN_ERR "Dumping node at LEB %d:%d len %d\n", lnum,
|
||||
snod->offs, snod->len);
|
||||
dbg_dump_node(c, snod->node);
|
||||
ubifs_dump_node(c, snod->node);
|
||||
}
|
||||
|
||||
printk(KERN_ERR "(pid %d) finish dumping LEB %d\n",
|
||||
|
@ -921,8 +919,8 @@ out:
|
|||
return;
|
||||
}
|
||||
|
||||
void dbg_dump_znode(const struct ubifs_info *c,
|
||||
const struct ubifs_znode *znode)
|
||||
void ubifs_dump_znode(const struct ubifs_info *c,
|
||||
const struct ubifs_znode *znode)
|
||||
{
|
||||
int n;
|
||||
const struct ubifs_zbranch *zbr;
|
||||
|
@ -965,7 +963,7 @@ void dbg_dump_znode(const struct ubifs_info *c,
|
|||
spin_unlock(&dbg_lock);
|
||||
}
|
||||
|
||||
void dbg_dump_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat)
|
||||
void ubifs_dump_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -981,8 +979,8 @@ void dbg_dump_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat)
|
|||
printk(KERN_ERR "(pid %d) finish dumping heap\n", current->pid);
|
||||
}
|
||||
|
||||
void dbg_dump_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode,
|
||||
struct ubifs_nnode *parent, int iip)
|
||||
void ubifs_dump_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode,
|
||||
struct ubifs_nnode *parent, int iip)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -999,7 +997,7 @@ void dbg_dump_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode,
|
|||
}
|
||||
}
|
||||
|
||||
void dbg_dump_tnc(struct ubifs_info *c)
|
||||
void ubifs_dump_tnc(struct ubifs_info *c)
|
||||
{
|
||||
struct ubifs_znode *znode;
|
||||
int level;
|
||||
|
@ -1014,7 +1012,7 @@ void dbg_dump_tnc(struct ubifs_info *c)
|
|||
level = znode->level;
|
||||
printk(KERN_ERR "== Level %d ==\n", level);
|
||||
}
|
||||
dbg_dump_znode(c, znode);
|
||||
ubifs_dump_znode(c, znode);
|
||||
znode = ubifs_tnc_levelorder_next(c->zroot.znode, znode);
|
||||
}
|
||||
printk(KERN_ERR "(pid %d) finish dumping TNC tree\n", current->pid);
|
||||
|
@ -1023,18 +1021,18 @@ void dbg_dump_tnc(struct ubifs_info *c)
|
|||
static int dump_znode(struct ubifs_info *c, struct ubifs_znode *znode,
|
||||
void *priv)
|
||||
{
|
||||
dbg_dump_znode(c, znode);
|
||||
ubifs_dump_znode(c, znode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* dbg_dump_index - dump the on-flash index.
|
||||
* ubifs_dump_index - dump the on-flash index.
|
||||
* @c: UBIFS file-system description object
|
||||
*
|
||||
* This function dumps whole UBIFS indexing B-tree, unlike 'dbg_dump_tnc()'
|
||||
* This function dumps whole UBIFS indexing B-tree, unlike 'ubifs_dump_tnc()'
|
||||
* which dumps only in-memory znodes and does not read znodes which from flash.
|
||||
*/
|
||||
void dbg_dump_index(struct ubifs_info *c)
|
||||
void ubifs_dump_index(struct ubifs_info *c)
|
||||
{
|
||||
dbg_walk_index(c, NULL, dump_znode, NULL);
|
||||
}
|
||||
|
@ -1120,15 +1118,15 @@ int dbg_check_space_info(struct ubifs_info *c)
|
|||
|
||||
out:
|
||||
ubifs_msg("saved lprops statistics dump");
|
||||
dbg_dump_lstats(&d->saved_lst);
|
||||
ubifs_dump_lstats(&d->saved_lst);
|
||||
ubifs_msg("saved budgeting info dump");
|
||||
dbg_dump_budg(c, &d->saved_bi);
|
||||
ubifs_dump_budg(c, &d->saved_bi);
|
||||
ubifs_msg("saved idx_gc_cnt %d", d->saved_idx_gc_cnt);
|
||||
ubifs_msg("current lprops statistics dump");
|
||||
ubifs_get_lp_stats(c, &lst);
|
||||
dbg_dump_lstats(&lst);
|
||||
ubifs_dump_lstats(&lst);
|
||||
ubifs_msg("current budgeting info dump");
|
||||
dbg_dump_budg(c, &c->bi);
|
||||
ubifs_dump_budg(c, &c->bi);
|
||||
dump_stack();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -1160,7 +1158,7 @@ int dbg_check_synced_i_size(const struct ubifs_info *c, struct inode *inode)
|
|||
"is clean", ui->ui_size, ui->synced_i_size);
|
||||
ubifs_err("i_ino %lu, i_mode %#x, i_size %lld", inode->i_ino,
|
||||
inode->i_mode, i_size_read(inode));
|
||||
dbg_dump_stack();
|
||||
dump_stack();
|
||||
err = -EINVAL;
|
||||
}
|
||||
spin_unlock(&ui->ui_lock);
|
||||
|
@ -1223,14 +1221,14 @@ int dbg_check_dir(struct ubifs_info *c, const struct inode *dir)
|
|||
"but calculated size is %llu", dir->i_ino,
|
||||
(unsigned long long)i_size_read(dir),
|
||||
(unsigned long long)size);
|
||||
dbg_dump_inode(c, dir);
|
||||
ubifs_dump_inode(c, dir);
|
||||
dump_stack();
|
||||
return -EINVAL;
|
||||
}
|
||||
if (dir->i_nlink != nlink) {
|
||||
ubifs_err("directory inode %lu has nlink %u, but calculated "
|
||||
"nlink is %u", dir->i_ino, dir->i_nlink, nlink);
|
||||
dbg_dump_inode(c, dir);
|
||||
ubifs_dump_inode(c, dir);
|
||||
dump_stack();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -1287,25 +1285,25 @@ static int dbg_check_key_order(struct ubifs_info *c, struct ubifs_zbranch *zbr1,
|
|||
err = 1;
|
||||
key_read(c, &dent1->key, &key);
|
||||
if (keys_cmp(c, &zbr1->key, &key)) {
|
||||
dbg_err("1st entry at %d:%d has key %s", zbr1->lnum,
|
||||
zbr1->offs, dbg_snprintf_key(c, &key, key_buf,
|
||||
DBG_KEY_BUF_LEN));
|
||||
dbg_err("but it should have key %s according to tnc",
|
||||
dbg_snprintf_key(c, &zbr1->key, key_buf,
|
||||
DBG_KEY_BUF_LEN));
|
||||
dbg_dump_node(c, dent1);
|
||||
ubifs_err("1st entry at %d:%d has key %s", zbr1->lnum,
|
||||
zbr1->offs, dbg_snprintf_key(c, &key, key_buf,
|
||||
DBG_KEY_BUF_LEN));
|
||||
ubifs_err("but it should have key %s according to tnc",
|
||||
dbg_snprintf_key(c, &zbr1->key, key_buf,
|
||||
DBG_KEY_BUF_LEN));
|
||||
ubifs_dump_node(c, dent1);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
key_read(c, &dent2->key, &key);
|
||||
if (keys_cmp(c, &zbr2->key, &key)) {
|
||||
dbg_err("2nd entry at %d:%d has key %s", zbr1->lnum,
|
||||
zbr1->offs, dbg_snprintf_key(c, &key, key_buf,
|
||||
DBG_KEY_BUF_LEN));
|
||||
dbg_err("but it should have key %s according to tnc",
|
||||
dbg_snprintf_key(c, &zbr2->key, key_buf,
|
||||
DBG_KEY_BUF_LEN));
|
||||
dbg_dump_node(c, dent2);
|
||||
ubifs_err("2nd entry at %d:%d has key %s", zbr1->lnum,
|
||||
zbr1->offs, dbg_snprintf_key(c, &key, key_buf,
|
||||
DBG_KEY_BUF_LEN));
|
||||
ubifs_err("but it should have key %s according to tnc",
|
||||
dbg_snprintf_key(c, &zbr2->key, key_buf,
|
||||
DBG_KEY_BUF_LEN));
|
||||
ubifs_dump_node(c, dent2);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
|
@ -1318,15 +1316,15 @@ static int dbg_check_key_order(struct ubifs_info *c, struct ubifs_zbranch *zbr1,
|
|||
goto out_free;
|
||||
}
|
||||
if (cmp == 0 && nlen1 == nlen2)
|
||||
dbg_err("2 xent/dent nodes with the same name");
|
||||
ubifs_err("2 xent/dent nodes with the same name");
|
||||
else
|
||||
dbg_err("bad order of colliding key %s",
|
||||
dbg_snprintf_key(c, &key, key_buf, DBG_KEY_BUF_LEN));
|
||||
ubifs_err("bad order of colliding key %s",
|
||||
dbg_snprintf_key(c, &key, key_buf, DBG_KEY_BUF_LEN));
|
||||
|
||||
ubifs_msg("first node at %d:%d\n", zbr1->lnum, zbr1->offs);
|
||||
dbg_dump_node(c, dent1);
|
||||
ubifs_dump_node(c, dent1);
|
||||
ubifs_msg("second node at %d:%d\n", zbr2->lnum, zbr2->offs);
|
||||
dbg_dump_node(c, dent2);
|
||||
ubifs_dump_node(c, dent2);
|
||||
|
||||
out_free:
|
||||
kfree(dent2);
|
||||
|
@ -1529,10 +1527,10 @@ static int dbg_check_znode(struct ubifs_info *c, struct ubifs_zbranch *zbr)
|
|||
out:
|
||||
ubifs_err("failed, error %d", err);
|
||||
ubifs_msg("dump of the znode");
|
||||
dbg_dump_znode(c, znode);
|
||||
ubifs_dump_znode(c, znode);
|
||||
if (zp) {
|
||||
ubifs_msg("dump of the parent znode");
|
||||
dbg_dump_znode(c, zp);
|
||||
ubifs_dump_znode(c, zp);
|
||||
}
|
||||
dump_stack();
|
||||
return -EINVAL;
|
||||
|
@ -1599,9 +1597,9 @@ int dbg_check_tnc(struct ubifs_info *c, int extra)
|
|||
return err;
|
||||
if (err) {
|
||||
ubifs_msg("first znode");
|
||||
dbg_dump_znode(c, prev);
|
||||
ubifs_dump_znode(c, prev);
|
||||
ubifs_msg("second znode");
|
||||
dbg_dump_znode(c, znode);
|
||||
ubifs_dump_znode(c, znode);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
@ -1690,7 +1688,7 @@ int dbg_walk_index(struct ubifs_info *c, dbg_leaf_callback leaf_cb,
|
|||
if (err) {
|
||||
ubifs_err("znode checking function returned "
|
||||
"error %d", err);
|
||||
dbg_dump_znode(c, znode);
|
||||
ubifs_dump_znode(c, znode);
|
||||
goto out_dump;
|
||||
}
|
||||
}
|
||||
|
@ -1758,7 +1756,7 @@ out_dump:
|
|||
else
|
||||
zbr = &c->zroot;
|
||||
ubifs_msg("dump of znode at LEB %d:%d", zbr->lnum, zbr->offs);
|
||||
dbg_dump_znode(c, znode);
|
||||
ubifs_dump_znode(c, znode);
|
||||
out_unlock:
|
||||
mutex_unlock(&c->tnc_mutex);
|
||||
return err;
|
||||
|
@ -2194,7 +2192,7 @@ out:
|
|||
|
||||
out_dump:
|
||||
ubifs_msg("dump of node at LEB %d:%d", zbr->lnum, zbr->offs);
|
||||
dbg_dump_node(c, node);
|
||||
ubifs_dump_node(c, node);
|
||||
out_free:
|
||||
kfree(node);
|
||||
return err;
|
||||
|
@ -2352,7 +2350,7 @@ out_dump:
|
|||
|
||||
ubifs_msg("dump of the inode %lu sitting in LEB %d:%d",
|
||||
(unsigned long)fscki->inum, zbr->lnum, zbr->offs);
|
||||
dbg_dump_node(c, ino);
|
||||
ubifs_dump_node(c, ino);
|
||||
kfree(ino);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -2423,12 +2421,12 @@ int dbg_check_data_nodes_order(struct ubifs_info *c, struct list_head *head)
|
|||
|
||||
if (sa->type != UBIFS_DATA_NODE) {
|
||||
ubifs_err("bad node type %d", sa->type);
|
||||
dbg_dump_node(c, sa->node);
|
||||
ubifs_dump_node(c, sa->node);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (sb->type != UBIFS_DATA_NODE) {
|
||||
ubifs_err("bad node type %d", sb->type);
|
||||
dbg_dump_node(c, sb->node);
|
||||
ubifs_dump_node(c, sb->node);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -2459,8 +2457,8 @@ int dbg_check_data_nodes_order(struct ubifs_info *c, struct list_head *head)
|
|||
return 0;
|
||||
|
||||
error_dump:
|
||||
dbg_dump_node(c, sa->node);
|
||||
dbg_dump_node(c, sb->node);
|
||||
ubifs_dump_node(c, sa->node);
|
||||
ubifs_dump_node(c, sb->node);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -2491,13 +2489,13 @@ int dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head)
|
|||
if (sa->type != UBIFS_INO_NODE && sa->type != UBIFS_DENT_NODE &&
|
||||
sa->type != UBIFS_XENT_NODE) {
|
||||
ubifs_err("bad node type %d", sa->type);
|
||||
dbg_dump_node(c, sa->node);
|
||||
ubifs_dump_node(c, sa->node);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (sa->type != UBIFS_INO_NODE && sa->type != UBIFS_DENT_NODE &&
|
||||
sa->type != UBIFS_XENT_NODE) {
|
||||
ubifs_err("bad node type %d", sb->type);
|
||||
dbg_dump_node(c, sb->node);
|
||||
ubifs_dump_node(c, sb->node);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -2547,9 +2545,9 @@ int dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head)
|
|||
|
||||
error_dump:
|
||||
ubifs_msg("dumping first node");
|
||||
dbg_dump_node(c, sa->node);
|
||||
ubifs_dump_node(c, sa->node);
|
||||
ubifs_msg("dumping second node");
|
||||
dbg_dump_node(c, sb->node);
|
||||
ubifs_dump_node(c, sb->node);
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
@ -2678,7 +2676,7 @@ static void cut_data(const void *buf, unsigned int len)
|
|||
}
|
||||
|
||||
int dbg_leb_write(struct ubifs_info *c, int lnum, const void *buf,
|
||||
int offs, int len, int dtype)
|
||||
int offs, int len)
|
||||
{
|
||||
int err, failing;
|
||||
|
||||
|
@ -2688,7 +2686,7 @@ int dbg_leb_write(struct ubifs_info *c, int lnum, const void *buf,
|
|||
failing = power_cut_emulated(c, lnum, 1);
|
||||
if (failing)
|
||||
cut_data(buf, len);
|
||||
err = ubi_leb_write(c->ubi, lnum, buf, offs, len, dtype);
|
||||
err = ubi_leb_write(c->ubi, lnum, buf, offs, len);
|
||||
if (err)
|
||||
return err;
|
||||
if (failing)
|
||||
|
@ -2697,7 +2695,7 @@ int dbg_leb_write(struct ubifs_info *c, int lnum, const void *buf,
|
|||
}
|
||||
|
||||
int dbg_leb_change(struct ubifs_info *c, int lnum, const void *buf,
|
||||
int len, int dtype)
|
||||
int len)
|
||||
{
|
||||
int err;
|
||||
|
||||
|
@ -2705,7 +2703,7 @@ int dbg_leb_change(struct ubifs_info *c, int lnum, const void *buf,
|
|||
return -EROFS;
|
||||
if (power_cut_emulated(c, lnum, 1))
|
||||
return -EROFS;
|
||||
err = ubi_leb_change(c->ubi, lnum, buf, len, dtype);
|
||||
err = ubi_leb_change(c->ubi, lnum, buf, len);
|
||||
if (err)
|
||||
return err;
|
||||
if (power_cut_emulated(c, lnum, 1))
|
||||
|
@ -2729,7 +2727,7 @@ int dbg_leb_unmap(struct ubifs_info *c, int lnum)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int dbg_leb_map(struct ubifs_info *c, int lnum, int dtype)
|
||||
int dbg_leb_map(struct ubifs_info *c, int lnum)
|
||||
{
|
||||
int err;
|
||||
|
||||
|
@ -2737,7 +2735,7 @@ int dbg_leb_map(struct ubifs_info *c, int lnum, int dtype)
|
|||
return -EROFS;
|
||||
if (power_cut_emulated(c, lnum, 0))
|
||||
return -EROFS;
|
||||
err = ubi_leb_map(c->ubi, lnum, dtype);
|
||||
err = ubi_leb_map(c->ubi, lnum);
|
||||
if (err)
|
||||
return err;
|
||||
if (power_cut_emulated(c, lnum, 0))
|
||||
|
@ -2857,16 +2855,16 @@ static ssize_t dfs_file_write(struct file *file, const char __user *u,
|
|||
* 'ubifs-debug' file-system instead.
|
||||
*/
|
||||
if (file->f_path.dentry == d->dfs_dump_lprops) {
|
||||
dbg_dump_lprops(c);
|
||||
ubifs_dump_lprops(c);
|
||||
return count;
|
||||
}
|
||||
if (file->f_path.dentry == d->dfs_dump_budg) {
|
||||
dbg_dump_budg(c, &c->bi);
|
||||
ubifs_dump_budg(c, &c->bi);
|
||||
return count;
|
||||
}
|
||||
if (file->f_path.dentry == d->dfs_dump_tnc) {
|
||||
mutex_lock(&c->tnc_mutex);
|
||||
dbg_dump_tnc(c);
|
||||
ubifs_dump_tnc(c);
|
||||
mutex_unlock(&c->tnc_mutex);
|
||||
return count;
|
||||
}
|
||||
|
@ -3189,5 +3187,3 @@ void ubifs_debugging_exit(struct ubifs_info *c)
|
|||
{
|
||||
kfree(c->dbg);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_UBIFS_FS_DEBUG */
|
||||
|
|
217
fs/ubifs/debug.h
217
fs/ubifs/debug.h
|
@ -29,8 +29,6 @@ typedef int (*dbg_leaf_callback)(struct ubifs_info *c,
|
|||
typedef int (*dbg_znode_callback)(struct ubifs_info *c,
|
||||
struct ubifs_znode *znode, void *priv);
|
||||
|
||||
#ifdef CONFIG_UBIFS_FS_DEBUG
|
||||
|
||||
/*
|
||||
* The UBIFS debugfs directory name pattern and maximum name length (3 for "ubi"
|
||||
* + 1 for "_" and plus 2x2 for 2 UBI numbers and 1 for the trailing zero byte.
|
||||
|
@ -149,7 +147,7 @@ struct ubifs_global_debug_info {
|
|||
if (unlikely(!(expr))) { \
|
||||
printk(KERN_CRIT "UBIFS assert failed in %s at %u (pid %d)\n", \
|
||||
__func__, __LINE__, current->pid); \
|
||||
dbg_dump_stack(); \
|
||||
dump_stack(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
@ -161,12 +159,6 @@ struct ubifs_global_debug_info {
|
|||
} \
|
||||
} while (0)
|
||||
|
||||
#define dbg_dump_stack() dump_stack()
|
||||
|
||||
#define dbg_err(fmt, ...) do { \
|
||||
ubifs_err(fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define ubifs_dbg_msg(type, fmt, ...) \
|
||||
pr_debug("UBIFS DBG " type ": " fmt "\n", ##__VA_ARGS__)
|
||||
|
||||
|
@ -257,27 +249,27 @@ const char *dbg_get_key_dump(const struct ubifs_info *c,
|
|||
const union ubifs_key *key);
|
||||
const char *dbg_snprintf_key(const struct ubifs_info *c,
|
||||
const union ubifs_key *key, char *buffer, int len);
|
||||
void dbg_dump_inode(struct ubifs_info *c, const struct inode *inode);
|
||||
void dbg_dump_node(const struct ubifs_info *c, const void *node);
|
||||
void dbg_dump_lpt_node(const struct ubifs_info *c, void *node, int lnum,
|
||||
int offs);
|
||||
void dbg_dump_budget_req(const struct ubifs_budget_req *req);
|
||||
void dbg_dump_lstats(const struct ubifs_lp_stats *lst);
|
||||
void dbg_dump_budg(struct ubifs_info *c, const struct ubifs_budg_info *bi);
|
||||
void dbg_dump_lprop(const struct ubifs_info *c, const struct ubifs_lprops *lp);
|
||||
void dbg_dump_lprops(struct ubifs_info *c);
|
||||
void dbg_dump_lpt_info(struct ubifs_info *c);
|
||||
void dbg_dump_leb(const struct ubifs_info *c, int lnum);
|
||||
void dbg_dump_sleb(const struct ubifs_info *c,
|
||||
const struct ubifs_scan_leb *sleb, int offs);
|
||||
void dbg_dump_znode(const struct ubifs_info *c,
|
||||
const struct ubifs_znode *znode);
|
||||
void dbg_dump_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat);
|
||||
void dbg_dump_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode,
|
||||
struct ubifs_nnode *parent, int iip);
|
||||
void dbg_dump_tnc(struct ubifs_info *c);
|
||||
void dbg_dump_index(struct ubifs_info *c);
|
||||
void dbg_dump_lpt_lebs(const struct ubifs_info *c);
|
||||
void ubifs_dump_inode(struct ubifs_info *c, const struct inode *inode);
|
||||
void ubifs_dump_node(const struct ubifs_info *c, const void *node);
|
||||
void ubifs_dump_budget_req(const struct ubifs_budget_req *req);
|
||||
void ubifs_dump_lstats(const struct ubifs_lp_stats *lst);
|
||||
void ubifs_dump_budg(struct ubifs_info *c, const struct ubifs_budg_info *bi);
|
||||
void ubifs_dump_lprop(const struct ubifs_info *c,
|
||||
const struct ubifs_lprops *lp);
|
||||
void ubifs_dump_lprops(struct ubifs_info *c);
|
||||
void ubifs_dump_lpt_info(struct ubifs_info *c);
|
||||
void ubifs_dump_leb(const struct ubifs_info *c, int lnum);
|
||||
void ubifs_dump_sleb(const struct ubifs_info *c,
|
||||
const struct ubifs_scan_leb *sleb, int offs);
|
||||
void ubifs_dump_znode(const struct ubifs_info *c,
|
||||
const struct ubifs_znode *znode);
|
||||
void ubifs_dump_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap,
|
||||
int cat);
|
||||
void ubifs_dump_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode,
|
||||
struct ubifs_nnode *parent, int iip);
|
||||
void ubifs_dump_tnc(struct ubifs_info *c);
|
||||
void ubifs_dump_index(struct ubifs_info *c);
|
||||
void ubifs_dump_lpt_lebs(const struct ubifs_info *c);
|
||||
|
||||
int dbg_walk_index(struct ubifs_info *c, dbg_leaf_callback leaf_cb,
|
||||
dbg_znode_callback znode_cb, void *priv);
|
||||
|
@ -307,11 +299,10 @@ int dbg_check_data_nodes_order(struct ubifs_info *c, struct list_head *head);
|
|||
int dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head);
|
||||
|
||||
int dbg_leb_write(struct ubifs_info *c, int lnum, const void *buf, int offs,
|
||||
int len, int dtype);
|
||||
int dbg_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len,
|
||||
int dtype);
|
||||
int len);
|
||||
int dbg_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len);
|
||||
int dbg_leb_unmap(struct ubifs_info *c, int lnum);
|
||||
int dbg_leb_map(struct ubifs_info *c, int lnum, int dtype);
|
||||
int dbg_leb_map(struct ubifs_info *c, int lnum);
|
||||
|
||||
/* Debugfs-related stuff */
|
||||
int dbg_debugfs_init(void);
|
||||
|
@ -319,162 +310,4 @@ void dbg_debugfs_exit(void);
|
|||
int dbg_debugfs_init_fs(struct ubifs_info *c);
|
||||
void dbg_debugfs_exit_fs(struct ubifs_info *c);
|
||||
|
||||
#else /* !CONFIG_UBIFS_FS_DEBUG */
|
||||
|
||||
/* Use "if (0)" to make compiler check arguments even if debugging is off */
|
||||
#define ubifs_assert(expr) do { \
|
||||
if (0) \
|
||||
printk(KERN_CRIT "UBIFS assert failed in %s at %u (pid %d)\n", \
|
||||
__func__, __LINE__, current->pid); \
|
||||
} while (0)
|
||||
|
||||
#define dbg_err(fmt, ...) do { \
|
||||
if (0) \
|
||||
ubifs_err(fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define DBGKEY(key) ((char *)(key))
|
||||
#define DBGKEY1(key) ((char *)(key))
|
||||
|
||||
#define ubifs_dbg_msg(fmt, ...) do { \
|
||||
if (0) \
|
||||
printk(KERN_DEBUG fmt "\n", ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define dbg_dump_stack()
|
||||
#define ubifs_assert_cmt_locked(c)
|
||||
|
||||
#define dbg_msg(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
|
||||
#define dbg_gen(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
|
||||
#define dbg_jnl(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
|
||||
#define dbg_jnlk(key, fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
|
||||
#define dbg_tnc(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
|
||||
#define dbg_tnck(key, fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
|
||||
#define dbg_lp(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
|
||||
#define dbg_find(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
|
||||
#define dbg_mnt(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
|
||||
#define dbg_mntk(key, fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
|
||||
#define dbg_io(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
|
||||
#define dbg_cmt(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
|
||||
#define dbg_budg(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
|
||||
#define dbg_log(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
|
||||
#define dbg_gc(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
|
||||
#define dbg_scan(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
|
||||
#define dbg_rcvry(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
|
||||
|
||||
static inline int ubifs_debugging_init(struct ubifs_info *c) { return 0; }
|
||||
static inline void ubifs_debugging_exit(struct ubifs_info *c) { return; }
|
||||
static inline const char *dbg_ntype(int type) { return ""; }
|
||||
static inline const char *dbg_cstate(int cmt_state) { return ""; }
|
||||
static inline const char *dbg_jhead(int jhead) { return ""; }
|
||||
static inline const char *
|
||||
dbg_get_key_dump(const struct ubifs_info *c,
|
||||
const union ubifs_key *key) { return ""; }
|
||||
static inline const char *
|
||||
dbg_snprintf_key(const struct ubifs_info *c,
|
||||
const union ubifs_key *key, char *buffer,
|
||||
int len) { return ""; }
|
||||
static inline void dbg_dump_inode(struct ubifs_info *c,
|
||||
const struct inode *inode) { return; }
|
||||
static inline void dbg_dump_node(const struct ubifs_info *c,
|
||||
const void *node) { return; }
|
||||
static inline void dbg_dump_lpt_node(const struct ubifs_info *c,
|
||||
void *node, int lnum,
|
||||
int offs) { return; }
|
||||
static inline void
|
||||
dbg_dump_budget_req(const struct ubifs_budget_req *req) { return; }
|
||||
static inline void
|
||||
dbg_dump_lstats(const struct ubifs_lp_stats *lst) { return; }
|
||||
static inline void
|
||||
dbg_dump_budg(struct ubifs_info *c,
|
||||
const struct ubifs_budg_info *bi) { return; }
|
||||
static inline void dbg_dump_lprop(const struct ubifs_info *c,
|
||||
const struct ubifs_lprops *lp) { return; }
|
||||
static inline void dbg_dump_lprops(struct ubifs_info *c) { return; }
|
||||
static inline void dbg_dump_lpt_info(struct ubifs_info *c) { return; }
|
||||
static inline void dbg_dump_leb(const struct ubifs_info *c,
|
||||
int lnum) { return; }
|
||||
static inline void
|
||||
dbg_dump_sleb(const struct ubifs_info *c,
|
||||
const struct ubifs_scan_leb *sleb, int offs) { return; }
|
||||
static inline void
|
||||
dbg_dump_znode(const struct ubifs_info *c,
|
||||
const struct ubifs_znode *znode) { return; }
|
||||
static inline void dbg_dump_heap(struct ubifs_info *c,
|
||||
struct ubifs_lpt_heap *heap,
|
||||
int cat) { return; }
|
||||
static inline void dbg_dump_pnode(struct ubifs_info *c,
|
||||
struct ubifs_pnode *pnode,
|
||||
struct ubifs_nnode *parent,
|
||||
int iip) { return; }
|
||||
static inline void dbg_dump_tnc(struct ubifs_info *c) { return; }
|
||||
static inline void dbg_dump_index(struct ubifs_info *c) { return; }
|
||||
static inline void dbg_dump_lpt_lebs(const struct ubifs_info *c) { return; }
|
||||
|
||||
static inline int dbg_walk_index(struct ubifs_info *c,
|
||||
dbg_leaf_callback leaf_cb,
|
||||
dbg_znode_callback znode_cb,
|
||||
void *priv) { return 0; }
|
||||
static inline void dbg_save_space_info(struct ubifs_info *c) { return; }
|
||||
static inline int dbg_check_space_info(struct ubifs_info *c) { return 0; }
|
||||
static inline int dbg_check_lprops(struct ubifs_info *c) { return 0; }
|
||||
static inline int
|
||||
dbg_old_index_check_init(struct ubifs_info *c,
|
||||
struct ubifs_zbranch *zroot) { return 0; }
|
||||
static inline int
|
||||
dbg_check_old_index(struct ubifs_info *c,
|
||||
struct ubifs_zbranch *zroot) { return 0; }
|
||||
static inline int dbg_check_cats(struct ubifs_info *c) { return 0; }
|
||||
static inline int dbg_check_ltab(struct ubifs_info *c) { return 0; }
|
||||
static inline int dbg_chk_lpt_free_spc(struct ubifs_info *c) { return 0; }
|
||||
static inline int dbg_chk_lpt_sz(struct ubifs_info *c,
|
||||
int action, int len) { return 0; }
|
||||
static inline int
|
||||
dbg_check_synced_i_size(const struct ubifs_info *c,
|
||||
struct inode *inode) { return 0; }
|
||||
static inline int dbg_check_dir(struct ubifs_info *c,
|
||||
const struct inode *dir) { return 0; }
|
||||
static inline int dbg_check_tnc(struct ubifs_info *c, int extra) { return 0; }
|
||||
static inline int dbg_check_idx_size(struct ubifs_info *c,
|
||||
long long idx_size) { return 0; }
|
||||
static inline int dbg_check_filesystem(struct ubifs_info *c) { return 0; }
|
||||
static inline void dbg_check_heap(struct ubifs_info *c,
|
||||
struct ubifs_lpt_heap *heap,
|
||||
int cat, int add_pos) { return; }
|
||||
static inline int dbg_check_lpt_nodes(struct ubifs_info *c,
|
||||
struct ubifs_cnode *cnode, int row, int col) { return 0; }
|
||||
static inline int dbg_check_inode_size(struct ubifs_info *c,
|
||||
const struct inode *inode,
|
||||
loff_t size) { return 0; }
|
||||
static inline int
|
||||
dbg_check_data_nodes_order(struct ubifs_info *c,
|
||||
struct list_head *head) { return 0; }
|
||||
static inline int
|
||||
dbg_check_nondata_nodes_order(struct ubifs_info *c,
|
||||
struct list_head *head) { return 0; }
|
||||
|
||||
static inline int dbg_leb_write(struct ubifs_info *c, int lnum,
|
||||
const void *buf, int offset,
|
||||
int len, int dtype) { return 0; }
|
||||
static inline int dbg_leb_change(struct ubifs_info *c, int lnum,
|
||||
const void *buf, int len,
|
||||
int dtype) { return 0; }
|
||||
static inline int dbg_leb_unmap(struct ubifs_info *c, int lnum) { return 0; }
|
||||
static inline int dbg_leb_map(struct ubifs_info *c, int lnum,
|
||||
int dtype) { return 0; }
|
||||
|
||||
static inline int dbg_is_chk_gen(const struct ubifs_info *c) { return 0; }
|
||||
static inline int dbg_is_chk_index(const struct ubifs_info *c) { return 0; }
|
||||
static inline int dbg_is_chk_orph(const struct ubifs_info *c) { return 0; }
|
||||
static inline int dbg_is_chk_lprops(const struct ubifs_info *c) { return 0; }
|
||||
static inline int dbg_is_chk_fs(const struct ubifs_info *c) { return 0; }
|
||||
static inline int dbg_is_tst_rcvry(const struct ubifs_info *c) { return 0; }
|
||||
static inline int dbg_is_power_cut(const struct ubifs_info *c) { return 0; }
|
||||
|
||||
static inline int dbg_debugfs_init(void) { return 0; }
|
||||
static inline void dbg_debugfs_exit(void) { return; }
|
||||
static inline int dbg_debugfs_init_fs(struct ubifs_info *c) { return 0; }
|
||||
static inline int dbg_debugfs_exit_fs(struct ubifs_info *c) { return 0; }
|
||||
|
||||
#endif /* !CONFIG_UBIFS_FS_DEBUG */
|
||||
#endif /* !__UBIFS_DEBUG_H__ */
|
||||
|
|
|
@ -170,8 +170,6 @@ struct inode *ubifs_new_inode(struct ubifs_info *c, const struct inode *dir,
|
|||
return inode;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_UBIFS_FS_DEBUG
|
||||
|
||||
static int dbg_check_name(const struct ubifs_info *c,
|
||||
const struct ubifs_dent_node *dent,
|
||||
const struct qstr *nm)
|
||||
|
@ -185,12 +183,6 @@ static int dbg_check_name(const struct ubifs_info *c,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define dbg_check_name(c, dent, nm) 0
|
||||
|
||||
#endif
|
||||
|
||||
static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry,
|
||||
struct nameidata *nd)
|
||||
{
|
||||
|
@ -1187,12 +1179,10 @@ const struct inode_operations ubifs_dir_inode_operations = {
|
|||
.rename = ubifs_rename,
|
||||
.setattr = ubifs_setattr,
|
||||
.getattr = ubifs_getattr,
|
||||
#ifdef CONFIG_UBIFS_FS_XATTR
|
||||
.setxattr = ubifs_setxattr,
|
||||
.getxattr = ubifs_getxattr,
|
||||
.listxattr = ubifs_listxattr,
|
||||
.removexattr = ubifs_removexattr,
|
||||
#endif
|
||||
};
|
||||
|
||||
const struct file_operations ubifs_dir_operations = {
|
||||
|
|
|
@ -97,7 +97,7 @@ static int read_block(struct inode *inode, void *addr, unsigned int block,
|
|||
dump:
|
||||
ubifs_err("bad data node (block %u, inode %lu)",
|
||||
block, inode->i_ino);
|
||||
dbg_dump_node(c, dn);
|
||||
ubifs_dump_node(c, dn);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -1562,12 +1562,10 @@ const struct address_space_operations ubifs_file_address_operations = {
|
|||
const struct inode_operations ubifs_file_inode_operations = {
|
||||
.setattr = ubifs_setattr,
|
||||
.getattr = ubifs_getattr,
|
||||
#ifdef CONFIG_UBIFS_FS_XATTR
|
||||
.setxattr = ubifs_setxattr,
|
||||
.getxattr = ubifs_getxattr,
|
||||
.listxattr = ubifs_listxattr,
|
||||
.removexattr = ubifs_removexattr,
|
||||
#endif
|
||||
};
|
||||
|
||||
const struct inode_operations ubifs_symlink_inode_operations = {
|
||||
|
|
|
@ -109,7 +109,7 @@ static int switch_gc_head(struct ubifs_info *c)
|
|||
return err;
|
||||
|
||||
c->gc_lnum = -1;
|
||||
err = ubifs_wbuf_seek_nolock(wbuf, gc_lnum, 0, UBI_LONGTERM);
|
||||
err = ubifs_wbuf_seek_nolock(wbuf, gc_lnum, 0);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
@ -109,13 +109,13 @@ int ubifs_leb_read(const struct ubifs_info *c, int lnum, void *buf, int offs,
|
|||
if (err && (err != -EBADMSG || even_ebadmsg)) {
|
||||
ubifs_err("reading %d bytes from LEB %d:%d failed, error %d",
|
||||
len, lnum, offs, err);
|
||||
dbg_dump_stack();
|
||||
dump_stack();
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int ubifs_leb_write(struct ubifs_info *c, int lnum, const void *buf, int offs,
|
||||
int len, int dtype)
|
||||
int len)
|
||||
{
|
||||
int err;
|
||||
|
||||
|
@ -123,20 +123,19 @@ int ubifs_leb_write(struct ubifs_info *c, int lnum, const void *buf, int offs,
|
|||
if (c->ro_error)
|
||||
return -EROFS;
|
||||
if (!dbg_is_tst_rcvry(c))
|
||||
err = ubi_leb_write(c->ubi, lnum, buf, offs, len, dtype);
|
||||
err = ubi_leb_write(c->ubi, lnum, buf, offs, len);
|
||||
else
|
||||
err = dbg_leb_write(c, lnum, buf, offs, len, dtype);
|
||||
err = dbg_leb_write(c, lnum, buf, offs, len);
|
||||
if (err) {
|
||||
ubifs_err("writing %d bytes to LEB %d:%d failed, error %d",
|
||||
len, lnum, offs, err);
|
||||
ubifs_ro_mode(c, err);
|
||||
dbg_dump_stack();
|
||||
dump_stack();
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int ubifs_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len,
|
||||
int dtype)
|
||||
int ubifs_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len)
|
||||
{
|
||||
int err;
|
||||
|
||||
|
@ -144,14 +143,14 @@ int ubifs_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len,
|
|||
if (c->ro_error)
|
||||
return -EROFS;
|
||||
if (!dbg_is_tst_rcvry(c))
|
||||
err = ubi_leb_change(c->ubi, lnum, buf, len, dtype);
|
||||
err = ubi_leb_change(c->ubi, lnum, buf, len);
|
||||
else
|
||||
err = dbg_leb_change(c, lnum, buf, len, dtype);
|
||||
err = dbg_leb_change(c, lnum, buf, len);
|
||||
if (err) {
|
||||
ubifs_err("changing %d bytes in LEB %d failed, error %d",
|
||||
len, lnum, err);
|
||||
ubifs_ro_mode(c, err);
|
||||
dbg_dump_stack();
|
||||
dump_stack();
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
@ -170,12 +169,12 @@ int ubifs_leb_unmap(struct ubifs_info *c, int lnum)
|
|||
if (err) {
|
||||
ubifs_err("unmap LEB %d failed, error %d", lnum, err);
|
||||
ubifs_ro_mode(c, err);
|
||||
dbg_dump_stack();
|
||||
dump_stack();
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int ubifs_leb_map(struct ubifs_info *c, int lnum, int dtype)
|
||||
int ubifs_leb_map(struct ubifs_info *c, int lnum)
|
||||
{
|
||||
int err;
|
||||
|
||||
|
@ -183,13 +182,13 @@ int ubifs_leb_map(struct ubifs_info *c, int lnum, int dtype)
|
|||
if (c->ro_error)
|
||||
return -EROFS;
|
||||
if (!dbg_is_tst_rcvry(c))
|
||||
err = ubi_leb_map(c->ubi, lnum, dtype);
|
||||
err = ubi_leb_map(c->ubi, lnum);
|
||||
else
|
||||
err = dbg_leb_map(c, lnum, dtype);
|
||||
err = dbg_leb_map(c, lnum);
|
||||
if (err) {
|
||||
ubifs_err("mapping LEB %d failed, error %d", lnum, err);
|
||||
ubifs_ro_mode(c, err);
|
||||
dbg_dump_stack();
|
||||
dump_stack();
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
@ -202,7 +201,7 @@ int ubifs_is_mapped(const struct ubifs_info *c, int lnum)
|
|||
if (err < 0) {
|
||||
ubifs_err("ubi_is_mapped failed for LEB %d, error %d",
|
||||
lnum, err);
|
||||
dbg_dump_stack();
|
||||
dump_stack();
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
@ -294,8 +293,8 @@ out_len:
|
|||
out:
|
||||
if (!quiet) {
|
||||
ubifs_err("bad node at LEB %d:%d", lnum, offs);
|
||||
dbg_dump_node(c, buf);
|
||||
dbg_dump_stack();
|
||||
ubifs_dump_node(c, buf);
|
||||
dump_stack();
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
@ -523,8 +522,7 @@ int ubifs_wbuf_sync_nolock(struct ubifs_wbuf *wbuf)
|
|||
dirt = sync_len - wbuf->used;
|
||||
if (dirt)
|
||||
ubifs_pad(c, wbuf->buf + wbuf->used, dirt);
|
||||
err = ubifs_leb_write(c, wbuf->lnum, wbuf->buf, wbuf->offs, sync_len,
|
||||
wbuf->dtype);
|
||||
err = ubifs_leb_write(c, wbuf->lnum, wbuf->buf, wbuf->offs, sync_len);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -562,14 +560,12 @@ int ubifs_wbuf_sync_nolock(struct ubifs_wbuf *wbuf)
|
|||
* @wbuf: write-buffer
|
||||
* @lnum: logical eraseblock number to seek to
|
||||
* @offs: logical eraseblock offset to seek to
|
||||
* @dtype: data type
|
||||
*
|
||||
* This function targets the write-buffer to logical eraseblock @lnum:@offs.
|
||||
* The write-buffer has to be empty. Returns zero in case of success and a
|
||||
* negative error code in case of failure.
|
||||
*/
|
||||
int ubifs_wbuf_seek_nolock(struct ubifs_wbuf *wbuf, int lnum, int offs,
|
||||
int dtype)
|
||||
int ubifs_wbuf_seek_nolock(struct ubifs_wbuf *wbuf, int lnum, int offs)
|
||||
{
|
||||
const struct ubifs_info *c = wbuf->c;
|
||||
|
||||
|
@ -592,7 +588,6 @@ int ubifs_wbuf_seek_nolock(struct ubifs_wbuf *wbuf, int lnum, int offs,
|
|||
wbuf->avail = wbuf->size;
|
||||
wbuf->used = 0;
|
||||
spin_unlock(&wbuf->lock);
|
||||
wbuf->dtype = dtype;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -719,8 +714,7 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
|
|||
dbg_io("flush jhead %s wbuf to LEB %d:%d",
|
||||
dbg_jhead(wbuf->jhead), wbuf->lnum, wbuf->offs);
|
||||
err = ubifs_leb_write(c, wbuf->lnum, wbuf->buf,
|
||||
wbuf->offs, wbuf->size,
|
||||
wbuf->dtype);
|
||||
wbuf->offs, wbuf->size);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
|
@ -756,7 +750,7 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
|
|||
dbg_jhead(wbuf->jhead), wbuf->lnum, wbuf->offs);
|
||||
memcpy(wbuf->buf + wbuf->used, buf, wbuf->avail);
|
||||
err = ubifs_leb_write(c, wbuf->lnum, wbuf->buf, wbuf->offs,
|
||||
wbuf->size, wbuf->dtype);
|
||||
wbuf->size);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
|
@ -775,7 +769,7 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
|
|||
dbg_io("write %d bytes to LEB %d:%d",
|
||||
wbuf->size, wbuf->lnum, wbuf->offs);
|
||||
err = ubifs_leb_write(c, wbuf->lnum, buf, wbuf->offs,
|
||||
wbuf->size, wbuf->dtype);
|
||||
wbuf->size);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
|
@ -797,7 +791,7 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
|
|||
dbg_io("write %d bytes to LEB %d:%d", n, wbuf->lnum,
|
||||
wbuf->offs);
|
||||
err = ubifs_leb_write(c, wbuf->lnum, buf + written,
|
||||
wbuf->offs, n, wbuf->dtype);
|
||||
wbuf->offs, n);
|
||||
if (err)
|
||||
goto out;
|
||||
wbuf->offs += n;
|
||||
|
@ -841,9 +835,9 @@ exit:
|
|||
out:
|
||||
ubifs_err("cannot write %d bytes to LEB %d:%d, error %d",
|
||||
len, wbuf->lnum, wbuf->offs, err);
|
||||
dbg_dump_node(c, buf);
|
||||
dbg_dump_stack();
|
||||
dbg_dump_leb(c, wbuf->lnum);
|
||||
ubifs_dump_node(c, buf);
|
||||
dump_stack();
|
||||
ubifs_dump_leb(c, wbuf->lnum);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -854,7 +848,6 @@ out:
|
|||
* @len: node length
|
||||
* @lnum: logical eraseblock number
|
||||
* @offs: offset within the logical eraseblock
|
||||
* @dtype: node life-time hint (%UBI_LONGTERM, %UBI_SHORTTERM, %UBI_UNKNOWN)
|
||||
*
|
||||
* This function automatically fills node magic number, assigns sequence
|
||||
* number, and calculates node CRC checksum. The length of the @buf buffer has
|
||||
|
@ -863,7 +856,7 @@ out:
|
|||
* success and a negative error code in case of failure.
|
||||
*/
|
||||
int ubifs_write_node(struct ubifs_info *c, void *buf, int len, int lnum,
|
||||
int offs, int dtype)
|
||||
int offs)
|
||||
{
|
||||
int err, buf_len = ALIGN(len, c->min_io_size);
|
||||
|
||||
|
@ -879,9 +872,9 @@ int ubifs_write_node(struct ubifs_info *c, void *buf, int len, int lnum,
|
|||
return -EROFS;
|
||||
|
||||
ubifs_prepare_node(c, buf, len, 1);
|
||||
err = ubifs_leb_write(c, lnum, buf, offs, buf_len, dtype);
|
||||
err = ubifs_leb_write(c, lnum, buf, offs, buf_len);
|
||||
if (err)
|
||||
dbg_dump_node(c, buf);
|
||||
ubifs_dump_node(c, buf);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -960,8 +953,8 @@ int ubifs_read_node_wbuf(struct ubifs_wbuf *wbuf, void *buf, int type, int len,
|
|||
|
||||
out:
|
||||
ubifs_err("bad node at LEB %d:%d", lnum, offs);
|
||||
dbg_dump_node(c, buf);
|
||||
dbg_dump_stack();
|
||||
ubifs_dump_node(c, buf);
|
||||
dump_stack();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -1017,8 +1010,8 @@ int ubifs_read_node(const struct ubifs_info *c, void *buf, int type, int len,
|
|||
out:
|
||||
ubifs_err("bad node at LEB %d:%d, LEB mapping status %d", lnum, offs,
|
||||
ubi_is_mapped(c->ubi, lnum));
|
||||
dbg_dump_node(c, buf);
|
||||
dbg_dump_stack();
|
||||
ubifs_dump_node(c, buf);
|
||||
dump_stack();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -1056,7 +1049,6 @@ int ubifs_wbuf_init(struct ubifs_info *c, struct ubifs_wbuf *wbuf)
|
|||
*/
|
||||
size = c->max_write_size - (c->leb_start % c->max_write_size);
|
||||
wbuf->avail = wbuf->size = size;
|
||||
wbuf->dtype = UBI_UNKNOWN;
|
||||
wbuf->sync_callback = NULL;
|
||||
mutex_init(&wbuf->io_mutex);
|
||||
spin_lock_init(&wbuf->lock);
|
||||
|
|
|
@ -214,7 +214,7 @@ out:
|
|||
err = ubifs_add_bud_to_log(c, jhead, lnum, offs);
|
||||
if (err)
|
||||
goto out_return;
|
||||
err = ubifs_wbuf_seek_nolock(wbuf, lnum, offs, wbuf->dtype);
|
||||
err = ubifs_wbuf_seek_nolock(wbuf, lnum, offs);
|
||||
if (err)
|
||||
goto out_unlock;
|
||||
|
||||
|
@ -385,9 +385,9 @@ out:
|
|||
if (err == -ENOSPC) {
|
||||
/* This are some budgeting problems, print useful information */
|
||||
down_write(&c->commit_sem);
|
||||
dbg_dump_stack();
|
||||
dbg_dump_budg(c, &c->bi);
|
||||
dbg_dump_lprops(c);
|
||||
dump_stack();
|
||||
ubifs_dump_budg(c, &c->bi);
|
||||
ubifs_dump_lprops(c);
|
||||
cmt_retries = dbg_check_lprops(c);
|
||||
up_write(&c->commit_sem);
|
||||
}
|
||||
|
@ -1267,7 +1267,6 @@ out_free:
|
|||
return err;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_UBIFS_FS_XATTR
|
||||
|
||||
/**
|
||||
* ubifs_jnl_delete_xattr - delete an extended attribute.
|
||||
|
@ -1462,4 +1461,3 @@ out_free:
|
|||
return err;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_UBIFS_FS_XATTR */
|
||||
|
|
|
@ -29,11 +29,7 @@
|
|||
|
||||
#include "ubifs.h"
|
||||
|
||||
#ifdef CONFIG_UBIFS_FS_DEBUG
|
||||
static int dbg_check_bud_bytes(struct ubifs_info *c);
|
||||
#else
|
||||
#define dbg_check_bud_bytes(c) 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* ubifs_search_bud - search bud LEB.
|
||||
|
@ -262,7 +258,7 @@ int ubifs_add_bud_to_log(struct ubifs_info *c, int jhead, int lnum, int offs)
|
|||
* an unclean reboot, because the target LEB might have been
|
||||
* unmapped, but not yet physically erased.
|
||||
*/
|
||||
err = ubifs_leb_map(c, bud->lnum, UBI_SHORTTERM);
|
||||
err = ubifs_leb_map(c, bud->lnum);
|
||||
if (err)
|
||||
goto out_unlock;
|
||||
}
|
||||
|
@ -270,7 +266,7 @@ int ubifs_add_bud_to_log(struct ubifs_info *c, int jhead, int lnum, int offs)
|
|||
dbg_log("write ref LEB %d:%d",
|
||||
c->lhead_lnum, c->lhead_offs);
|
||||
err = ubifs_write_node(c, ref, UBIFS_REF_NODE_SZ, c->lhead_lnum,
|
||||
c->lhead_offs, UBI_SHORTTERM);
|
||||
c->lhead_offs);
|
||||
if (err)
|
||||
goto out_unlock;
|
||||
|
||||
|
@ -422,7 +418,7 @@ int ubifs_log_start_commit(struct ubifs_info *c, int *ltail_lnum)
|
|||
|
||||
len = ALIGN(len, c->min_io_size);
|
||||
dbg_log("writing commit start at LEB %d:0, len %d", c->lhead_lnum, len);
|
||||
err = ubifs_leb_write(c, c->lhead_lnum, cs, 0, len, UBI_SHORTTERM);
|
||||
err = ubifs_leb_write(c, c->lhead_lnum, cs, 0, len);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
|
@ -623,7 +619,7 @@ static int add_node(struct ubifs_info *c, void *buf, int *lnum, int *offs,
|
|||
int sz = ALIGN(*offs, c->min_io_size), err;
|
||||
|
||||
ubifs_pad(c, buf + *offs, sz - *offs);
|
||||
err = ubifs_leb_change(c, *lnum, buf, sz, UBI_SHORTTERM);
|
||||
err = ubifs_leb_change(c, *lnum, buf, sz);
|
||||
if (err)
|
||||
return err;
|
||||
*lnum = ubifs_next_log_lnum(c, *lnum);
|
||||
|
@ -702,7 +698,7 @@ int ubifs_consolidate_log(struct ubifs_info *c)
|
|||
int sz = ALIGN(offs, c->min_io_size);
|
||||
|
||||
ubifs_pad(c, buf + offs, sz - offs);
|
||||
err = ubifs_leb_change(c, write_lnum, buf, sz, UBI_SHORTTERM);
|
||||
err = ubifs_leb_change(c, write_lnum, buf, sz);
|
||||
if (err)
|
||||
goto out_free;
|
||||
offs = ALIGN(offs, c->min_io_size);
|
||||
|
@ -734,8 +730,6 @@ out_free:
|
|||
return err;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_UBIFS_FS_DEBUG
|
||||
|
||||
/**
|
||||
* dbg_check_bud_bytes - make sure bud bytes calculation are all right.
|
||||
* @c: UBIFS file-system description object
|
||||
|
@ -767,5 +761,3 @@ static int dbg_check_bud_bytes(struct ubifs_info *c)
|
|||
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_UBIFS_FS_DEBUG */
|
||||
|
|
|
@ -447,7 +447,7 @@ static void change_category(struct ubifs_info *c, struct ubifs_lprops *lprops)
|
|||
int new_cat = ubifs_categorize_lprops(c, lprops);
|
||||
|
||||
if (old_cat == new_cat) {
|
||||
struct ubifs_lpt_heap *heap = &c->lpt_heap[new_cat - 1];
|
||||
struct ubifs_lpt_heap *heap;
|
||||
|
||||
/* lprops on a heap now must be moved up or down */
|
||||
if (new_cat < 1 || new_cat > LPROPS_HEAP_CNT)
|
||||
|
@ -846,7 +846,9 @@ const struct ubifs_lprops *ubifs_fast_find_frdi_idx(struct ubifs_info *c)
|
|||
return lprops;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_UBIFS_FS_DEBUG
|
||||
/*
|
||||
* Everything below is related to debugging.
|
||||
*/
|
||||
|
||||
/**
|
||||
* dbg_check_cats - check category heaps and lists.
|
||||
|
@ -1001,8 +1003,8 @@ void dbg_check_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat,
|
|||
out:
|
||||
if (err) {
|
||||
dbg_msg("failed cat %d hpos %d err %d", cat, i, err);
|
||||
dbg_dump_stack();
|
||||
dbg_dump_heap(c, heap, cat);
|
||||
dump_stack();
|
||||
ubifs_dump_heap(c, heap, cat);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1109,8 +1111,8 @@ static int scan_check_cb(struct ubifs_info *c,
|
|||
if (IS_ERR(sleb)) {
|
||||
ret = PTR_ERR(sleb);
|
||||
if (ret == -EUCLEAN) {
|
||||
dbg_dump_lprops(c);
|
||||
dbg_dump_budg(c, &c->bi);
|
||||
ubifs_dump_lprops(c);
|
||||
ubifs_dump_budg(c, &c->bi);
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
@ -1237,7 +1239,7 @@ out_print:
|
|||
ubifs_err("bad accounting of LEB %d: free %d, dirty %d flags %#x, "
|
||||
"should be free %d, dirty %d",
|
||||
lnum, lp->free, lp->dirty, lp->flags, free, dirty);
|
||||
dbg_dump_leb(c, lnum);
|
||||
ubifs_dump_leb(c, lnum);
|
||||
out_destroy:
|
||||
ubifs_scan_destroy(sleb);
|
||||
ret = -EINVAL;
|
||||
|
@ -1315,5 +1317,3 @@ int dbg_check_lprops(struct ubifs_info *c)
|
|||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_UBIFS_FS_DEBUG */
|
||||
|
|
|
@ -701,8 +701,7 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
|
|||
alen = ALIGN(len, c->min_io_size);
|
||||
set_ltab(c, lnum, c->leb_size - alen, alen - len);
|
||||
memset(p, 0xff, alen - len);
|
||||
err = ubifs_leb_change(c, lnum++, buf, alen,
|
||||
UBI_SHORTTERM);
|
||||
err = ubifs_leb_change(c, lnum++, buf, alen);
|
||||
if (err)
|
||||
goto out;
|
||||
p = buf;
|
||||
|
@ -732,8 +731,7 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
|
|||
set_ltab(c, lnum, c->leb_size - alen,
|
||||
alen - len);
|
||||
memset(p, 0xff, alen - len);
|
||||
err = ubifs_leb_change(c, lnum++, buf, alen,
|
||||
UBI_SHORTTERM);
|
||||
err = ubifs_leb_change(c, lnum++, buf, alen);
|
||||
if (err)
|
||||
goto out;
|
||||
p = buf;
|
||||
|
@ -780,8 +778,7 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
|
|||
alen = ALIGN(len, c->min_io_size);
|
||||
set_ltab(c, lnum, c->leb_size - alen, alen - len);
|
||||
memset(p, 0xff, alen - len);
|
||||
err = ubifs_leb_change(c, lnum++, buf, alen,
|
||||
UBI_SHORTTERM);
|
||||
err = ubifs_leb_change(c, lnum++, buf, alen);
|
||||
if (err)
|
||||
goto out;
|
||||
p = buf;
|
||||
|
@ -806,7 +803,7 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
|
|||
alen = ALIGN(len, c->min_io_size);
|
||||
set_ltab(c, lnum, c->leb_size - alen, alen - len);
|
||||
memset(p, 0xff, alen - len);
|
||||
err = ubifs_leb_change(c, lnum++, buf, alen, UBI_SHORTTERM);
|
||||
err = ubifs_leb_change(c, lnum++, buf, alen);
|
||||
if (err)
|
||||
goto out;
|
||||
p = buf;
|
||||
|
@ -826,7 +823,7 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
|
|||
|
||||
/* Write remaining buffer */
|
||||
memset(p, 0xff, alen - len);
|
||||
err = ubifs_leb_change(c, lnum, buf, alen, UBI_SHORTTERM);
|
||||
err = ubifs_leb_change(c, lnum, buf, alen);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
|
@ -926,7 +923,7 @@ static int check_lpt_crc(void *buf, int len)
|
|||
if (crc != calc_crc) {
|
||||
ubifs_err("invalid crc in LPT node: crc %hx calc %hx", crc,
|
||||
calc_crc);
|
||||
dbg_dump_stack();
|
||||
dump_stack();
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
|
@ -949,7 +946,7 @@ static int check_lpt_type(uint8_t **addr, int *pos, int type)
|
|||
if (node_type != type) {
|
||||
ubifs_err("invalid type (%d) in LPT node type %d", node_type,
|
||||
type);
|
||||
dbg_dump_stack();
|
||||
dump_stack();
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
|
@ -1247,7 +1244,7 @@ int ubifs_read_nnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip)
|
|||
|
||||
out:
|
||||
ubifs_err("error %d reading nnode at %d:%d", err, lnum, offs);
|
||||
dbg_dump_stack();
|
||||
dump_stack();
|
||||
kfree(nnode);
|
||||
return err;
|
||||
}
|
||||
|
@ -1312,8 +1309,8 @@ static int read_pnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip)
|
|||
|
||||
out:
|
||||
ubifs_err("error %d reading pnode at %d:%d", err, lnum, offs);
|
||||
dbg_dump_pnode(c, pnode, parent, iip);
|
||||
dbg_dump_stack();
|
||||
ubifs_dump_pnode(c, pnode, parent, iip);
|
||||
dump_stack();
|
||||
dbg_msg("calc num: %d", calc_pnode_num_from_parent(c, parent, iip));
|
||||
kfree(pnode);
|
||||
return err;
|
||||
|
@ -1740,16 +1737,20 @@ int ubifs_lpt_init(struct ubifs_info *c, int rd, int wr)
|
|||
if (rd) {
|
||||
err = lpt_init_rd(c);
|
||||
if (err)
|
||||
return err;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
if (wr) {
|
||||
err = lpt_init_wr(c);
|
||||
if (err)
|
||||
return err;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out_err:
|
||||
ubifs_lpt_free(c, 0);
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2080,8 +2081,6 @@ out:
|
|||
return err;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_UBIFS_FS_DEBUG
|
||||
|
||||
/**
|
||||
* dbg_chk_pnode - check a pnode.
|
||||
* @c: the UBIFS file-system description object
|
||||
|
@ -2096,8 +2095,8 @@ static int dbg_chk_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode,
|
|||
int i;
|
||||
|
||||
if (pnode->num != col) {
|
||||
dbg_err("pnode num %d expected %d parent num %d iip %d",
|
||||
pnode->num, col, pnode->parent->num, pnode->iip);
|
||||
ubifs_err("pnode num %d expected %d parent num %d iip %d",
|
||||
pnode->num, col, pnode->parent->num, pnode->iip);
|
||||
return -EINVAL;
|
||||
}
|
||||
for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
|
||||
|
@ -2111,14 +2110,14 @@ static int dbg_chk_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode,
|
|||
if (lnum >= c->leb_cnt)
|
||||
continue;
|
||||
if (lprops->lnum != lnum) {
|
||||
dbg_err("bad LEB number %d expected %d",
|
||||
lprops->lnum, lnum);
|
||||
ubifs_err("bad LEB number %d expected %d",
|
||||
lprops->lnum, lnum);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (lprops->flags & LPROPS_TAKEN) {
|
||||
if (cat != LPROPS_UNCAT) {
|
||||
dbg_err("LEB %d taken but not uncat %d",
|
||||
lprops->lnum, cat);
|
||||
ubifs_err("LEB %d taken but not uncat %d",
|
||||
lprops->lnum, cat);
|
||||
return -EINVAL;
|
||||
}
|
||||
continue;
|
||||
|
@ -2130,8 +2129,8 @@ static int dbg_chk_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode,
|
|||
case LPROPS_FRDI_IDX:
|
||||
break;
|
||||
default:
|
||||
dbg_err("LEB %d index but cat %d",
|
||||
lprops->lnum, cat);
|
||||
ubifs_err("LEB %d index but cat %d",
|
||||
lprops->lnum, cat);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
|
@ -2143,8 +2142,8 @@ static int dbg_chk_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode,
|
|||
case LPROPS_FREEABLE:
|
||||
break;
|
||||
default:
|
||||
dbg_err("LEB %d not index but cat %d",
|
||||
lprops->lnum, cat);
|
||||
ubifs_err("LEB %d not index but cat %d",
|
||||
lprops->lnum, cat);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
@ -2184,24 +2183,24 @@ static int dbg_chk_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode,
|
|||
break;
|
||||
}
|
||||
if (!found) {
|
||||
dbg_err("LEB %d cat %d not found in cat heap/list",
|
||||
lprops->lnum, cat);
|
||||
ubifs_err("LEB %d cat %d not found in cat heap/list",
|
||||
lprops->lnum, cat);
|
||||
return -EINVAL;
|
||||
}
|
||||
switch (cat) {
|
||||
case LPROPS_EMPTY:
|
||||
if (lprops->free != c->leb_size) {
|
||||
dbg_err("LEB %d cat %d free %d dirty %d",
|
||||
lprops->lnum, cat, lprops->free,
|
||||
lprops->dirty);
|
||||
ubifs_err("LEB %d cat %d free %d dirty %d",
|
||||
lprops->lnum, cat, lprops->free,
|
||||
lprops->dirty);
|
||||
return -EINVAL;
|
||||
}
|
||||
case LPROPS_FREEABLE:
|
||||
case LPROPS_FRDI_IDX:
|
||||
if (lprops->free + lprops->dirty != c->leb_size) {
|
||||
dbg_err("LEB %d cat %d free %d dirty %d",
|
||||
lprops->lnum, cat, lprops->free,
|
||||
lprops->dirty);
|
||||
ubifs_err("LEB %d cat %d free %d dirty %d",
|
||||
lprops->lnum, cat, lprops->free,
|
||||
lprops->dirty);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
@ -2235,9 +2234,10 @@ int dbg_check_lpt_nodes(struct ubifs_info *c, struct ubifs_cnode *cnode,
|
|||
/* cnode is a nnode */
|
||||
num = calc_nnode_num(row, col);
|
||||
if (cnode->num != num) {
|
||||
dbg_err("nnode num %d expected %d "
|
||||
"parent num %d iip %d", cnode->num, num,
|
||||
(nnode ? nnode->num : 0), cnode->iip);
|
||||
ubifs_err("nnode num %d expected %d "
|
||||
"parent num %d iip %d",
|
||||
cnode->num, num,
|
||||
(nnode ? nnode->num : 0), cnode->iip);
|
||||
return -EINVAL;
|
||||
}
|
||||
nn = (struct ubifs_nnode *)cnode;
|
||||
|
@ -2274,5 +2274,3 @@ int dbg_check_lpt_nodes(struct ubifs_info *c, struct ubifs_cnode *cnode,
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_UBIFS_FS_DEBUG */
|
||||
|
|
|
@ -30,11 +30,7 @@
|
|||
#include <linux/random.h>
|
||||
#include "ubifs.h"
|
||||
|
||||
#ifdef CONFIG_UBIFS_FS_DEBUG
|
||||
static int dbg_populate_lsave(struct ubifs_info *c);
|
||||
#else
|
||||
#define dbg_populate_lsave(c) 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* first_dirty_cnode - find first dirty cnode.
|
||||
|
@ -324,11 +320,10 @@ static int layout_cnodes(struct ubifs_info *c)
|
|||
return 0;
|
||||
|
||||
no_space:
|
||||
ubifs_err("LPT out of space");
|
||||
dbg_err("LPT out of space at LEB %d:%d needing %d, done_ltab %d, "
|
||||
"done_lsave %d", lnum, offs, len, done_ltab, done_lsave);
|
||||
dbg_dump_lpt_info(c);
|
||||
dbg_dump_lpt_lebs(c);
|
||||
ubifs_err("LPT out of space at LEB %d:%d needing %d, done_ltab %d, "
|
||||
"done_lsave %d", lnum, offs, len, done_ltab, done_lsave);
|
||||
ubifs_dump_lpt_info(c);
|
||||
ubifs_dump_lpt_lebs(c);
|
||||
dump_stack();
|
||||
return err;
|
||||
}
|
||||
|
@ -421,7 +416,7 @@ static int write_cnodes(struct ubifs_info *c)
|
|||
alen = ALIGN(wlen, c->min_io_size);
|
||||
memset(buf + offs, 0xff, alen - wlen);
|
||||
err = ubifs_leb_write(c, lnum, buf + from, from,
|
||||
alen, UBI_SHORTTERM);
|
||||
alen);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
@ -479,8 +474,7 @@ static int write_cnodes(struct ubifs_info *c)
|
|||
wlen = offs - from;
|
||||
alen = ALIGN(wlen, c->min_io_size);
|
||||
memset(buf + offs, 0xff, alen - wlen);
|
||||
err = ubifs_leb_write(c, lnum, buf + from, from, alen,
|
||||
UBI_SHORTTERM);
|
||||
err = ubifs_leb_write(c, lnum, buf + from, from, alen);
|
||||
if (err)
|
||||
return err;
|
||||
dbg_chk_lpt_sz(c, 2, c->leb_size - offs);
|
||||
|
@ -506,8 +500,7 @@ static int write_cnodes(struct ubifs_info *c)
|
|||
wlen = offs - from;
|
||||
alen = ALIGN(wlen, c->min_io_size);
|
||||
memset(buf + offs, 0xff, alen - wlen);
|
||||
err = ubifs_leb_write(c, lnum, buf + from, from, alen,
|
||||
UBI_SHORTTERM);
|
||||
err = ubifs_leb_write(c, lnum, buf + from, from, alen);
|
||||
if (err)
|
||||
return err;
|
||||
dbg_chk_lpt_sz(c, 2, c->leb_size - offs);
|
||||
|
@ -531,7 +524,7 @@ static int write_cnodes(struct ubifs_info *c)
|
|||
wlen = offs - from;
|
||||
alen = ALIGN(wlen, c->min_io_size);
|
||||
memset(buf + offs, 0xff, alen - wlen);
|
||||
err = ubifs_leb_write(c, lnum, buf + from, from, alen, UBI_SHORTTERM);
|
||||
err = ubifs_leb_write(c, lnum, buf + from, from, alen);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -552,11 +545,10 @@ static int write_cnodes(struct ubifs_info *c)
|
|||
return 0;
|
||||
|
||||
no_space:
|
||||
ubifs_err("LPT out of space mismatch");
|
||||
dbg_err("LPT out of space mismatch at LEB %d:%d needing %d, done_ltab "
|
||||
"%d, done_lsave %d", lnum, offs, len, done_ltab, done_lsave);
|
||||
dbg_dump_lpt_info(c);
|
||||
dbg_dump_lpt_lebs(c);
|
||||
ubifs_err("LPT out of space mismatch at LEB %d:%d needing %d, done_ltab "
|
||||
"%d, done_lsave %d", lnum, offs, len, done_ltab, done_lsave);
|
||||
ubifs_dump_lpt_info(c);
|
||||
ubifs_dump_lpt_lebs(c);
|
||||
dump_stack();
|
||||
return err;
|
||||
}
|
||||
|
@ -1497,7 +1489,9 @@ void ubifs_lpt_free(struct ubifs_info *c, int wr_only)
|
|||
kfree(c->lpt_nod_buf);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_UBIFS_FS_DEBUG
|
||||
/*
|
||||
* Everything below is related to debugging.
|
||||
*/
|
||||
|
||||
/**
|
||||
* dbg_is_all_ff - determine if a buffer contains only 0xFF bytes.
|
||||
|
@ -1735,7 +1729,7 @@ int dbg_check_ltab(struct ubifs_info *c)
|
|||
for (lnum = c->lpt_first; lnum <= c->lpt_last; lnum++) {
|
||||
err = dbg_check_ltab_lnum(c, lnum);
|
||||
if (err) {
|
||||
dbg_err("failed at LEB %d", lnum);
|
||||
ubifs_err("failed at LEB %d", lnum);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
@ -1767,10 +1761,10 @@ int dbg_chk_lpt_free_spc(struct ubifs_info *c)
|
|||
free += c->leb_size;
|
||||
}
|
||||
if (free < c->lpt_sz) {
|
||||
dbg_err("LPT space error: free %lld lpt_sz %lld",
|
||||
free, c->lpt_sz);
|
||||
dbg_dump_lpt_info(c);
|
||||
dbg_dump_lpt_lebs(c);
|
||||
ubifs_err("LPT space error: free %lld lpt_sz %lld",
|
||||
free, c->lpt_sz);
|
||||
ubifs_dump_lpt_info(c);
|
||||
ubifs_dump_lpt_lebs(c);
|
||||
dump_stack();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -1807,13 +1801,13 @@ int dbg_chk_lpt_sz(struct ubifs_info *c, int action, int len)
|
|||
d->chk_lpt_lebs = 0;
|
||||
d->chk_lpt_wastage = 0;
|
||||
if (c->dirty_pn_cnt > c->pnode_cnt) {
|
||||
dbg_err("dirty pnodes %d exceed max %d",
|
||||
c->dirty_pn_cnt, c->pnode_cnt);
|
||||
ubifs_err("dirty pnodes %d exceed max %d",
|
||||
c->dirty_pn_cnt, c->pnode_cnt);
|
||||
err = -EINVAL;
|
||||
}
|
||||
if (c->dirty_nn_cnt > c->nnode_cnt) {
|
||||
dbg_err("dirty nnodes %d exceed max %d",
|
||||
c->dirty_nn_cnt, c->nnode_cnt);
|
||||
ubifs_err("dirty nnodes %d exceed max %d",
|
||||
c->dirty_nn_cnt, c->nnode_cnt);
|
||||
err = -EINVAL;
|
||||
}
|
||||
return err;
|
||||
|
@ -1830,23 +1824,23 @@ int dbg_chk_lpt_sz(struct ubifs_info *c, int action, int len)
|
|||
chk_lpt_sz *= d->chk_lpt_lebs;
|
||||
chk_lpt_sz += len - c->nhead_offs;
|
||||
if (d->chk_lpt_sz != chk_lpt_sz) {
|
||||
dbg_err("LPT wrote %lld but space used was %lld",
|
||||
d->chk_lpt_sz, chk_lpt_sz);
|
||||
ubifs_err("LPT wrote %lld but space used was %lld",
|
||||
d->chk_lpt_sz, chk_lpt_sz);
|
||||
err = -EINVAL;
|
||||
}
|
||||
if (d->chk_lpt_sz > c->lpt_sz) {
|
||||
dbg_err("LPT wrote %lld but lpt_sz is %lld",
|
||||
d->chk_lpt_sz, c->lpt_sz);
|
||||
ubifs_err("LPT wrote %lld but lpt_sz is %lld",
|
||||
d->chk_lpt_sz, c->lpt_sz);
|
||||
err = -EINVAL;
|
||||
}
|
||||
if (d->chk_lpt_sz2 && d->chk_lpt_sz != d->chk_lpt_sz2) {
|
||||
dbg_err("LPT layout size %lld but wrote %lld",
|
||||
d->chk_lpt_sz, d->chk_lpt_sz2);
|
||||
ubifs_err("LPT layout size %lld but wrote %lld",
|
||||
d->chk_lpt_sz, d->chk_lpt_sz2);
|
||||
err = -EINVAL;
|
||||
}
|
||||
if (d->chk_lpt_sz2 && d->new_nhead_offs != len) {
|
||||
dbg_err("LPT new nhead offs: expected %d was %d",
|
||||
d->new_nhead_offs, len);
|
||||
ubifs_err("LPT new nhead offs: expected %d was %d",
|
||||
d->new_nhead_offs, len);
|
||||
err = -EINVAL;
|
||||
}
|
||||
lpt_sz = (long long)c->pnode_cnt * c->pnode_sz;
|
||||
|
@ -1855,13 +1849,13 @@ int dbg_chk_lpt_sz(struct ubifs_info *c, int action, int len)
|
|||
if (c->big_lpt)
|
||||
lpt_sz += c->lsave_sz;
|
||||
if (d->chk_lpt_sz - d->chk_lpt_wastage > lpt_sz) {
|
||||
dbg_err("LPT chk_lpt_sz %lld + waste %lld exceeds %lld",
|
||||
d->chk_lpt_sz, d->chk_lpt_wastage, lpt_sz);
|
||||
ubifs_err("LPT chk_lpt_sz %lld + waste %lld exceeds %lld",
|
||||
d->chk_lpt_sz, d->chk_lpt_wastage, lpt_sz);
|
||||
err = -EINVAL;
|
||||
}
|
||||
if (err) {
|
||||
dbg_dump_lpt_info(c);
|
||||
dbg_dump_lpt_lebs(c);
|
||||
ubifs_dump_lpt_info(c);
|
||||
ubifs_dump_lpt_lebs(c);
|
||||
dump_stack();
|
||||
}
|
||||
d->chk_lpt_sz2 = d->chk_lpt_sz;
|
||||
|
@ -1880,7 +1874,7 @@ int dbg_chk_lpt_sz(struct ubifs_info *c, int action, int len)
|
|||
}
|
||||
|
||||
/**
|
||||
* dbg_dump_lpt_leb - dump an LPT LEB.
|
||||
* ubifs_dump_lpt_leb - dump an LPT LEB.
|
||||
* @c: UBIFS file-system description object
|
||||
* @lnum: LEB number to dump
|
||||
*
|
||||
|
@ -1986,13 +1980,13 @@ out:
|
|||
}
|
||||
|
||||
/**
|
||||
* dbg_dump_lpt_lebs - dump LPT lebs.
|
||||
* ubifs_dump_lpt_lebs - dump LPT lebs.
|
||||
* @c: UBIFS file-system description object
|
||||
*
|
||||
* This function dumps all LPT LEBs. The caller has to make sure the LPT is
|
||||
* locked.
|
||||
*/
|
||||
void dbg_dump_lpt_lebs(const struct ubifs_info *c)
|
||||
void ubifs_dump_lpt_lebs(const struct ubifs_info *c)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -2046,5 +2040,3 @@ static int dbg_populate_lsave(struct ubifs_info *c)
|
|||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_UBIFS_FS_DEBUG */
|
||||
|
|
|
@ -241,7 +241,7 @@ static int validate_master(const struct ubifs_info *c)
|
|||
|
||||
out:
|
||||
ubifs_err("bad master node at offset %d error %d", c->mst_offs, err);
|
||||
dbg_dump_node(c, c->mst_node);
|
||||
ubifs_dump_node(c, c->mst_node);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -317,7 +317,7 @@ int ubifs_read_master(struct ubifs_info *c)
|
|||
if (c->leb_cnt < old_leb_cnt ||
|
||||
c->leb_cnt < UBIFS_MIN_LEB_CNT) {
|
||||
ubifs_err("bad leb_cnt on master node");
|
||||
dbg_dump_node(c, c->mst_node);
|
||||
ubifs_dump_node(c, c->mst_node);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -379,7 +379,7 @@ int ubifs_write_master(struct ubifs_info *c)
|
|||
c->mst_offs = offs;
|
||||
c->mst_node->highest_inum = cpu_to_le64(c->highest_inum);
|
||||
|
||||
err = ubifs_write_node(c, c->mst_node, len, lnum, offs, UBI_SHORTTERM);
|
||||
err = ubifs_write_node(c, c->mst_node, len, lnum, offs);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -390,7 +390,7 @@ int ubifs_write_master(struct ubifs_info *c)
|
|||
if (err)
|
||||
return err;
|
||||
}
|
||||
err = ubifs_write_node(c, c->mst_node, len, lnum, offs, UBI_SHORTTERM);
|
||||
err = ubifs_write_node(c, c->mst_node, len, lnum, offs);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -52,11 +52,7 @@
|
|||
* than the maximum number of orphans allowed.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_UBIFS_FS_DEBUG
|
||||
static int dbg_check_orphans(struct ubifs_info *c);
|
||||
#else
|
||||
#define dbg_check_orphans(c) 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* ubifs_add_orphan - add an orphan.
|
||||
|
@ -92,7 +88,7 @@ int ubifs_add_orphan(struct ubifs_info *c, ino_t inum)
|
|||
else if (inum > o->inum)
|
||||
p = &(*p)->rb_right;
|
||||
else {
|
||||
dbg_err("orphaned twice");
|
||||
ubifs_err("orphaned twice");
|
||||
spin_unlock(&c->orphan_lock);
|
||||
kfree(orphan);
|
||||
return 0;
|
||||
|
@ -158,8 +154,8 @@ void ubifs_delete_orphan(struct ubifs_info *c, ino_t inum)
|
|||
}
|
||||
}
|
||||
spin_unlock(&c->orphan_lock);
|
||||
dbg_err("missing orphan ino %lu", (unsigned long)inum);
|
||||
dbg_dump_stack();
|
||||
ubifs_err("missing orphan ino %lu", (unsigned long)inum);
|
||||
dump_stack();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -248,8 +244,7 @@ static int do_write_orph_node(struct ubifs_info *c, int len, int atomic)
|
|||
ubifs_assert(c->ohead_offs == 0);
|
||||
ubifs_prepare_node(c, c->orph_buf, len, 1);
|
||||
len = ALIGN(len, c->min_io_size);
|
||||
err = ubifs_leb_change(c, c->ohead_lnum, c->orph_buf, len,
|
||||
UBI_SHORTTERM);
|
||||
err = ubifs_leb_change(c, c->ohead_lnum, c->orph_buf, len);
|
||||
} else {
|
||||
if (c->ohead_offs == 0) {
|
||||
/* Ensure LEB has been unmapped */
|
||||
|
@ -258,7 +253,7 @@ static int do_write_orph_node(struct ubifs_info *c, int len, int atomic)
|
|||
return err;
|
||||
}
|
||||
err = ubifs_write_node(c, c->orph_buf, len, c->ohead_lnum,
|
||||
c->ohead_offs, UBI_SHORTTERM);
|
||||
c->ohead_offs);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
@ -569,7 +564,7 @@ static int do_kill_orphans(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
|
|||
if (snod->type != UBIFS_ORPH_NODE) {
|
||||
ubifs_err("invalid node type %d in orphan area at "
|
||||
"%d:%d", snod->type, sleb->lnum, snod->offs);
|
||||
dbg_dump_node(c, snod->node);
|
||||
ubifs_dump_node(c, snod->node);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -597,7 +592,7 @@ static int do_kill_orphans(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
|
|||
ubifs_err("out of order commit number %llu in "
|
||||
"orphan node at %d:%d",
|
||||
cmt_no, sleb->lnum, snod->offs);
|
||||
dbg_dump_node(c, snod->node);
|
||||
ubifs_dump_node(c, snod->node);
|
||||
return -EINVAL;
|
||||
}
|
||||
dbg_rcvry("out of date LEB %d", sleb->lnum);
|
||||
|
@ -725,7 +720,9 @@ int ubifs_mount_orphans(struct ubifs_info *c, int unclean, int read_only)
|
|||
return err;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_UBIFS_FS_DEBUG
|
||||
/*
|
||||
* Everything below is related to debugging.
|
||||
*/
|
||||
|
||||
struct check_orphan {
|
||||
struct rb_node rb;
|
||||
|
@ -968,5 +965,3 @@ out:
|
|||
kfree(ci.node);
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_UBIFS_FS_DEBUG */
|
||||
|
|
|
@ -213,10 +213,10 @@ static int write_rcvrd_mst_node(struct ubifs_info *c,
|
|||
mst->flags |= cpu_to_le32(UBIFS_MST_RCVRY);
|
||||
|
||||
ubifs_prepare_node(c, mst, UBIFS_MST_NODE_SZ, 1);
|
||||
err = ubifs_leb_change(c, lnum, mst, sz, UBI_SHORTTERM);
|
||||
err = ubifs_leb_change(c, lnum, mst, sz);
|
||||
if (err)
|
||||
goto out;
|
||||
err = ubifs_leb_change(c, lnum + 1, mst, sz, UBI_SHORTTERM);
|
||||
err = ubifs_leb_change(c, lnum + 1, mst, sz);
|
||||
if (err)
|
||||
goto out;
|
||||
out:
|
||||
|
@ -362,12 +362,12 @@ out_err:
|
|||
out_free:
|
||||
ubifs_err("failed to recover master node");
|
||||
if (mst1) {
|
||||
dbg_err("dumping first master node");
|
||||
dbg_dump_node(c, mst1);
|
||||
ubifs_err("dumping first master node");
|
||||
ubifs_dump_node(c, mst1);
|
||||
}
|
||||
if (mst2) {
|
||||
dbg_err("dumping second master node");
|
||||
dbg_dump_node(c, mst2);
|
||||
ubifs_err("dumping second master node");
|
||||
ubifs_dump_node(c, mst2);
|
||||
}
|
||||
vfree(buf2);
|
||||
vfree(buf1);
|
||||
|
@ -555,8 +555,7 @@ static int fix_unclean_leb(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
|
|||
ubifs_pad(c, buf, pad_len);
|
||||
}
|
||||
}
|
||||
err = ubifs_leb_change(c, lnum, sleb->buf, len,
|
||||
UBI_UNKNOWN);
|
||||
err = ubifs_leb_change(c, lnum, sleb->buf, len);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
@ -683,7 +682,7 @@ struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum,
|
|||
ret, lnum, offs);
|
||||
break;
|
||||
} else {
|
||||
dbg_err("unexpected return value %d", ret);
|
||||
ubifs_err("unexpected return value %d", ret);
|
||||
err = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
@ -789,7 +788,7 @@ struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum,
|
|||
|
||||
corrupted_rescan:
|
||||
/* Re-scan the corrupted data with verbose messages */
|
||||
dbg_err("corruptio %d", ret);
|
||||
ubifs_err("corruptio %d", ret);
|
||||
ubifs_scan_a_node(c, buf, len, lnum, offs, 1);
|
||||
corrupted:
|
||||
ubifs_scanned_corruption(c, lnum, offs, buf);
|
||||
|
@ -827,17 +826,17 @@ static int get_cs_sqnum(struct ubifs_info *c, int lnum, int offs,
|
|||
goto out_free;
|
||||
ret = ubifs_scan_a_node(c, cs_node, UBIFS_CS_NODE_SZ, lnum, offs, 0);
|
||||
if (ret != SCANNED_A_NODE) {
|
||||
dbg_err("Not a valid node");
|
||||
ubifs_err("Not a valid node");
|
||||
goto out_err;
|
||||
}
|
||||
if (cs_node->ch.node_type != UBIFS_CS_NODE) {
|
||||
dbg_err("Node a CS node, type is %d", cs_node->ch.node_type);
|
||||
ubifs_err("Node a CS node, type is %d", cs_node->ch.node_type);
|
||||
goto out_err;
|
||||
}
|
||||
if (le64_to_cpu(cs_node->cmt_no) != c->cmt_no) {
|
||||
dbg_err("CS node cmt_no %llu != current cmt_no %llu",
|
||||
(unsigned long long)le64_to_cpu(cs_node->cmt_no),
|
||||
c->cmt_no);
|
||||
ubifs_err("CS node cmt_no %llu != current cmt_no %llu",
|
||||
(unsigned long long)le64_to_cpu(cs_node->cmt_no),
|
||||
c->cmt_no);
|
||||
goto out_err;
|
||||
}
|
||||
*cs_sqnum = le64_to_cpu(cs_node->ch.sqnum);
|
||||
|
@ -941,7 +940,7 @@ static int recover_head(struct ubifs_info *c, int lnum, int offs, void *sbuf)
|
|||
err = ubifs_leb_read(c, lnum, sbuf, 0, offs, 1);
|
||||
if (err)
|
||||
return err;
|
||||
return ubifs_leb_change(c, lnum, sbuf, offs, UBI_UNKNOWN);
|
||||
return ubifs_leb_change(c, lnum, sbuf, offs);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1071,7 +1070,7 @@ static int clean_an_unclean_leb(struct ubifs_info *c,
|
|||
}
|
||||
|
||||
/* Write back the LEB atomically */
|
||||
err = ubifs_leb_change(c, lnum, sbuf, len, UBI_UNKNOWN);
|
||||
err = ubifs_leb_change(c, lnum, sbuf, len);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -1138,9 +1137,9 @@ static int grab_empty_leb(struct ubifs_info *c)
|
|||
*/
|
||||
lnum = ubifs_find_free_leb_for_idx(c);
|
||||
if (lnum < 0) {
|
||||
dbg_err("could not find an empty LEB");
|
||||
dbg_dump_lprops(c);
|
||||
dbg_dump_budg(c, &c->bi);
|
||||
ubifs_err("could not find an empty LEB");
|
||||
ubifs_dump_lprops(c);
|
||||
ubifs_dump_budg(c, &c->bi);
|
||||
return lnum;
|
||||
}
|
||||
|
||||
|
@ -1218,7 +1217,7 @@ int ubifs_rcvry_gc_commit(struct ubifs_info *c)
|
|||
}
|
||||
mutex_unlock(&wbuf->io_mutex);
|
||||
if (err < 0) {
|
||||
dbg_err("GC failed, error %d", err);
|
||||
ubifs_err("GC failed, error %d", err);
|
||||
if (err == -EAGAIN)
|
||||
err = -EINVAL;
|
||||
return err;
|
||||
|
@ -1472,7 +1471,7 @@ static int fix_size_in_place(struct ubifs_info *c, struct size_entry *e)
|
|||
len -= 1;
|
||||
len = ALIGN(len + 1, c->min_io_size);
|
||||
/* Atomically write the fixed LEB back again */
|
||||
err = ubifs_leb_change(c, lnum, c->sbuf, len, UBI_UNKNOWN);
|
||||
err = ubifs_leb_change(c, lnum, c->sbuf, len);
|
||||
if (err)
|
||||
goto out;
|
||||
dbg_rcvry("inode %lu at %d:%d size %lld -> %lld",
|
||||
|
|
|
@ -154,8 +154,7 @@ static int set_bud_lprops(struct ubifs_info *c, struct bud_entry *b)
|
|||
|
||||
/* Make sure the journal head points to the latest bud */
|
||||
err = ubifs_wbuf_seek_nolock(&c->jheads[b->bud->jhead].wbuf,
|
||||
b->bud->lnum, c->leb_size - b->free,
|
||||
UBI_SHORTTERM);
|
||||
b->bud->lnum, c->leb_size - b->free);
|
||||
|
||||
out:
|
||||
ubifs_release_lprops(c);
|
||||
|
@ -686,7 +685,7 @@ out:
|
|||
|
||||
out_dump:
|
||||
ubifs_err("bad node is at LEB %d:%d", lnum, snod->offs);
|
||||
dbg_dump_node(c, snod->node);
|
||||
ubifs_dump_node(c, snod->node);
|
||||
ubifs_scan_destroy(sleb);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -861,16 +860,16 @@ static int replay_log_leb(struct ubifs_info *c, int lnum, int offs, void *sbuf)
|
|||
* numbers.
|
||||
*/
|
||||
if (snod->type != UBIFS_CS_NODE) {
|
||||
dbg_err("first log node at LEB %d:%d is not CS node",
|
||||
lnum, offs);
|
||||
ubifs_err("first log node at LEB %d:%d is not CS node",
|
||||
lnum, offs);
|
||||
goto out_dump;
|
||||
}
|
||||
if (le64_to_cpu(node->cmt_no) != c->cmt_no) {
|
||||
dbg_err("first CS node at LEB %d:%d has wrong "
|
||||
"commit number %llu expected %llu",
|
||||
lnum, offs,
|
||||
(unsigned long long)le64_to_cpu(node->cmt_no),
|
||||
c->cmt_no);
|
||||
ubifs_err("first CS node at LEB %d:%d has wrong "
|
||||
"commit number %llu expected %llu",
|
||||
lnum, offs,
|
||||
(unsigned long long)le64_to_cpu(node->cmt_no),
|
||||
c->cmt_no);
|
||||
goto out_dump;
|
||||
}
|
||||
|
||||
|
@ -892,7 +891,7 @@ static int replay_log_leb(struct ubifs_info *c, int lnum, int offs, void *sbuf)
|
|||
|
||||
/* Make sure the first node sits at offset zero of the LEB */
|
||||
if (snod->offs != 0) {
|
||||
dbg_err("first node is not at zero offset");
|
||||
ubifs_err("first node is not at zero offset");
|
||||
goto out_dump;
|
||||
}
|
||||
|
||||
|
@ -905,8 +904,8 @@ static int replay_log_leb(struct ubifs_info *c, int lnum, int offs, void *sbuf)
|
|||
}
|
||||
|
||||
if (snod->sqnum < c->cs_sqnum) {
|
||||
dbg_err("bad sqnum %llu, commit sqnum %llu",
|
||||
snod->sqnum, c->cs_sqnum);
|
||||
ubifs_err("bad sqnum %llu, commit sqnum %llu",
|
||||
snod->sqnum, c->cs_sqnum);
|
||||
goto out_dump;
|
||||
}
|
||||
|
||||
|
@ -958,7 +957,7 @@ out:
|
|||
out_dump:
|
||||
ubifs_err("log error detected while replaying the log at LEB %d:%d",
|
||||
lnum, offs + snod->offs);
|
||||
dbg_dump_node(c, snod->node);
|
||||
ubifs_dump_node(c, snod->node);
|
||||
ubifs_scan_destroy(sleb);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
|
@ -130,7 +130,6 @@ static int create_default_filesystem(struct ubifs_info *c)
|
|||
* 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
|
||||
|
@ -138,7 +137,6 @@ static int create_default_filesystem(struct ubifs_info *c)
|
|||
* 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;
|
||||
|
@ -196,7 +194,7 @@ static int create_default_filesystem(struct ubifs_info *c)
|
|||
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);
|
||||
err = ubifs_write_node(c, sup, UBIFS_SB_NODE_SZ, 0, 0);
|
||||
kfree(sup);
|
||||
if (err)
|
||||
return err;
|
||||
|
@ -252,14 +250,13 @@ static int create_default_filesystem(struct ubifs_info *c)
|
|||
|
||||
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);
|
||||
err = ubifs_write_node(c, mst, UBIFS_MST_NODE_SZ, UBIFS_MST_LNUM, 0);
|
||||
if (err) {
|
||||
kfree(mst);
|
||||
return err;
|
||||
}
|
||||
err = ubifs_write_node(c, mst, UBIFS_MST_NODE_SZ, UBIFS_MST_LNUM + 1, 0,
|
||||
UBI_UNKNOWN);
|
||||
err = ubifs_write_node(c, mst, UBIFS_MST_NODE_SZ, UBIFS_MST_LNUM + 1,
|
||||
0);
|
||||
kfree(mst);
|
||||
if (err)
|
||||
return err;
|
||||
|
@ -282,8 +279,7 @@ static int create_default_filesystem(struct ubifs_info *c)
|
|||
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);
|
||||
err = ubifs_write_node(c, idx, tmp, main_first + DEFAULT_IDX_LEB, 0);
|
||||
kfree(idx);
|
||||
if (err)
|
||||
return err;
|
||||
|
@ -315,8 +311,7 @@ static int create_default_filesystem(struct ubifs_info *c)
|
|||
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);
|
||||
main_first + DEFAULT_DATA_LEB, 0);
|
||||
kfree(ino);
|
||||
if (err)
|
||||
return err;
|
||||
|
@ -335,8 +330,7 @@ static int create_default_filesystem(struct ubifs_info *c)
|
|||
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);
|
||||
err = ubifs_write_node(c, cs, UBIFS_CS_NODE_SZ, UBIFS_LOG_LNUM, 0);
|
||||
kfree(cs);
|
||||
|
||||
ubifs_msg("default file-system created");
|
||||
|
@ -475,7 +469,7 @@ static int validate_sb(struct ubifs_info *c, struct ubifs_sb_node *sup)
|
|||
|
||||
failed:
|
||||
ubifs_err("bad superblock, error %d", err);
|
||||
dbg_dump_node(c, sup);
|
||||
ubifs_dump_node(c, sup);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -518,7 +512,7 @@ int ubifs_write_sb_node(struct ubifs_info *c, struct ubifs_sb_node *sup)
|
|||
int len = ALIGN(UBIFS_SB_NODE_SZ, c->min_io_size);
|
||||
|
||||
ubifs_prepare_node(c, sup, UBIFS_SB_NODE_SZ, 1);
|
||||
return ubifs_leb_change(c, UBIFS_SB_LNUM, sup, len, UBI_LONGTERM);
|
||||
return ubifs_leb_change(c, UBIFS_SB_LNUM, sup, len);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -691,7 +685,7 @@ static int fixup_leb(struct ubifs_info *c, int lnum, int len)
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
return ubifs_leb_change(c, lnum, c->sbuf, len, UBI_UNKNOWN);
|
||||
return ubifs_leb_change(c, lnum, c->sbuf, len);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -101,7 +101,7 @@ int ubifs_scan_a_node(const struct ubifs_info *c, void *buf, int len, int lnum,
|
|||
if (!quiet) {
|
||||
ubifs_err("bad pad node at LEB %d:%d",
|
||||
lnum, offs);
|
||||
dbg_dump_node(c, pad);
|
||||
ubifs_dump_node(c, pad);
|
||||
}
|
||||
return SCANNED_A_BAD_PAD_NODE;
|
||||
}
|
||||
|
@ -109,8 +109,8 @@ int ubifs_scan_a_node(const struct ubifs_info *c, void *buf, int len, int lnum,
|
|||
/* Make the node pads to 8-byte boundary */
|
||||
if ((node_len + pad_len) & 7) {
|
||||
if (!quiet)
|
||||
dbg_err("bad padding length %d - %d",
|
||||
offs, offs + node_len + pad_len);
|
||||
ubifs_err("bad padding length %d - %d",
|
||||
offs, offs + node_len + pad_len);
|
||||
return SCANNED_A_BAD_PAD_NODE;
|
||||
}
|
||||
|
||||
|
@ -245,7 +245,7 @@ void ubifs_scanned_corruption(const struct ubifs_info *c, int lnum, int offs,
|
|||
len = c->leb_size - offs;
|
||||
if (len > 8192)
|
||||
len = 8192;
|
||||
dbg_err("first %d bytes from LEB %d:%d", len, lnum, offs);
|
||||
ubifs_err("first %d bytes from LEB %d:%d", len, lnum, offs);
|
||||
print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 4, buf, len, 1);
|
||||
}
|
||||
|
||||
|
@ -300,16 +300,16 @@ struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum,
|
|||
|
||||
switch (ret) {
|
||||
case SCANNED_GARBAGE:
|
||||
dbg_err("garbage");
|
||||
ubifs_err("garbage");
|
||||
goto corrupted;
|
||||
case SCANNED_A_NODE:
|
||||
break;
|
||||
case SCANNED_A_CORRUPT_NODE:
|
||||
case SCANNED_A_BAD_PAD_NODE:
|
||||
dbg_err("bad node");
|
||||
ubifs_err("bad node");
|
||||
goto corrupted;
|
||||
default:
|
||||
dbg_err("unknown");
|
||||
ubifs_err("unknown");
|
||||
err = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
|
|
@ -246,8 +246,8 @@ struct inode *ubifs_iget(struct super_block *sb, unsigned long inum)
|
|||
|
||||
out_invalid:
|
||||
ubifs_err("inode %lu validation failed, error %d", inode->i_ino, err);
|
||||
dbg_dump_node(c, ino);
|
||||
dbg_dump_inode(c, inode);
|
||||
ubifs_dump_node(c, ino);
|
||||
ubifs_dump_inode(c, inode);
|
||||
err = -EINVAL;
|
||||
out_ino:
|
||||
kfree(ino);
|
||||
|
@ -668,8 +668,8 @@ static int init_constants_sb(struct ubifs_info *c)
|
|||
tmp = UBIFS_CS_NODE_SZ + UBIFS_REF_NODE_SZ * c->jhead_cnt;
|
||||
tmp = ALIGN(tmp, c->min_io_size);
|
||||
if (tmp > c->leb_size) {
|
||||
dbg_err("too small LEB size %d, at least %d needed",
|
||||
c->leb_size, tmp);
|
||||
ubifs_err("too small LEB size %d, at least %d needed",
|
||||
c->leb_size, tmp);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -683,8 +683,8 @@ static int init_constants_sb(struct ubifs_info *c)
|
|||
tmp /= c->leb_size;
|
||||
tmp += 1;
|
||||
if (c->log_lebs < tmp) {
|
||||
dbg_err("too small log %d LEBs, required min. %d LEBs",
|
||||
c->log_lebs, tmp);
|
||||
ubifs_err("too small log %d LEBs, required min. %d LEBs",
|
||||
c->log_lebs, tmp);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -813,13 +813,10 @@ static int alloc_wbufs(struct ubifs_info *c)
|
|||
c->jheads[i].grouped = 1;
|
||||
}
|
||||
|
||||
c->jheads[BASEHD].wbuf.dtype = UBI_SHORTTERM;
|
||||
/*
|
||||
* Garbage Collector head likely contains long-term data and
|
||||
* does not need to be synchronized by timer. Also GC head nodes are
|
||||
* not grouped.
|
||||
* Garbage Collector head does not need to be synchronized by timer.
|
||||
* Also GC head nodes are not grouped.
|
||||
*/
|
||||
c->jheads[GCHD].wbuf.dtype = UBI_LONGTERM;
|
||||
c->jheads[GCHD].wbuf.no_timer = 1;
|
||||
c->jheads[GCHD].grouped = 0;
|
||||
|
||||
|
@ -863,7 +860,7 @@ static void free_orphans(struct ubifs_info *c)
|
|||
orph = list_entry(c->orph_list.next, struct ubifs_orphan, list);
|
||||
list_del(&orph->list);
|
||||
kfree(orph);
|
||||
dbg_err("orphan list not empty at unmount");
|
||||
ubifs_err("orphan list not empty at unmount");
|
||||
}
|
||||
|
||||
vfree(c->orph_buf);
|
||||
|
@ -1147,8 +1144,8 @@ static int check_free_space(struct ubifs_info *c)
|
|||
ubifs_assert(c->dark_wm > 0);
|
||||
if (c->lst.total_free + c->lst.total_dirty < c->dark_wm) {
|
||||
ubifs_err("insufficient free space to mount in R/W mode");
|
||||
dbg_dump_budg(c, &c->bi);
|
||||
dbg_dump_lprops(c);
|
||||
ubifs_dump_budg(c, &c->bi);
|
||||
ubifs_dump_lprops(c);
|
||||
return -ENOSPC;
|
||||
}
|
||||
return 0;
|
||||
|
@ -1301,7 +1298,7 @@ static int mount_ubifs(struct ubifs_info *c)
|
|||
if (!c->ro_mount && c->space_fixup) {
|
||||
err = ubifs_fixup_free_space(c);
|
||||
if (err)
|
||||
goto out_master;
|
||||
goto out_lpt;
|
||||
}
|
||||
|
||||
if (!c->ro_mount) {
|
||||
|
@ -2126,8 +2123,8 @@ static struct dentry *ubifs_mount(struct file_system_type *fs_type, int flags,
|
|||
*/
|
||||
ubi = open_ubi(name, UBI_READONLY);
|
||||
if (IS_ERR(ubi)) {
|
||||
dbg_err("cannot open \"%s\", error %d",
|
||||
name, (int)PTR_ERR(ubi));
|
||||
ubifs_err("cannot open \"%s\", error %d",
|
||||
name, (int)PTR_ERR(ubi));
|
||||
return ERR_CAST(ubi);
|
||||
}
|
||||
|
||||
|
|
|
@ -339,8 +339,8 @@ static int lnc_add(struct ubifs_info *c, struct ubifs_zbranch *zbr,
|
|||
|
||||
err = ubifs_validate_entry(c, dent);
|
||||
if (err) {
|
||||
dbg_dump_stack();
|
||||
dbg_dump_node(c, dent);
|
||||
dump_stack();
|
||||
ubifs_dump_node(c, dent);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -372,8 +372,8 @@ static int lnc_add_directly(struct ubifs_info *c, struct ubifs_zbranch *zbr,
|
|||
|
||||
err = ubifs_validate_entry(c, node);
|
||||
if (err) {
|
||||
dbg_dump_stack();
|
||||
dbg_dump_node(c, node);
|
||||
dump_stack();
|
||||
ubifs_dump_node(c, node);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -1733,8 +1733,8 @@ out_err:
|
|||
err = -EINVAL;
|
||||
out:
|
||||
ubifs_err("bad node at LEB %d:%d", zbr->lnum, zbr->offs);
|
||||
dbg_dump_node(c, buf);
|
||||
dbg_dump_stack();
|
||||
ubifs_dump_node(c, buf);
|
||||
dump_stack();
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -1775,7 +1775,7 @@ int ubifs_tnc_bulk_read(struct ubifs_info *c, struct bu_info *bu)
|
|||
if (err && err != -EBADMSG) {
|
||||
ubifs_err("failed to read from LEB %d:%d, error %d",
|
||||
lnum, offs, err);
|
||||
dbg_dump_stack();
|
||||
dump_stack();
|
||||
dbg_tnck(&bu->key, "key ");
|
||||
return err;
|
||||
}
|
||||
|
@ -2403,7 +2403,7 @@ static int tnc_delete(struct ubifs_info *c, struct ubifs_znode *znode, int n)
|
|||
|
||||
err = ubifs_add_dirt(c, zbr->lnum, zbr->len);
|
||||
if (err) {
|
||||
dbg_dump_znode(c, znode);
|
||||
ubifs_dump_znode(c, znode);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -2649,7 +2649,7 @@ int ubifs_tnc_remove_range(struct ubifs_info *c, union ubifs_key *from_key,
|
|||
err = ubifs_add_dirt(c, znode->zbranch[i].lnum,
|
||||
znode->zbranch[i].len);
|
||||
if (err) {
|
||||
dbg_dump_znode(c, znode);
|
||||
ubifs_dump_znode(c, znode);
|
||||
goto out_unlock;
|
||||
}
|
||||
dbg_tnck(key, "removing key ");
|
||||
|
@ -3275,8 +3275,6 @@ out_unlock:
|
|||
return err;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_UBIFS_FS_DEBUG
|
||||
|
||||
/**
|
||||
* dbg_check_inode_size - check if inode size is correct.
|
||||
* @c: UBIFS file-system description object
|
||||
|
@ -3335,13 +3333,11 @@ out_dump:
|
|||
(unsigned long)inode->i_ino, size,
|
||||
((loff_t)block) << UBIFS_BLOCK_SHIFT);
|
||||
mutex_unlock(&c->tnc_mutex);
|
||||
dbg_dump_inode(c, inode);
|
||||
dbg_dump_stack();
|
||||
ubifs_dump_inode(c, inode);
|
||||
dump_stack();
|
||||
return -EINVAL;
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&c->tnc_mutex);
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_UBIFS_FS_DEBUG */
|
||||
|
|
|
@ -54,18 +54,16 @@ static int make_idx_node(struct ubifs_info *c, struct ubifs_idx_node *idx,
|
|||
br->len = cpu_to_le32(zbr->len);
|
||||
if (!zbr->lnum || !zbr->len) {
|
||||
ubifs_err("bad ref in znode");
|
||||
dbg_dump_znode(c, znode);
|
||||
ubifs_dump_znode(c, znode);
|
||||
if (zbr->znode)
|
||||
dbg_dump_znode(c, zbr->znode);
|
||||
ubifs_dump_znode(c, zbr->znode);
|
||||
}
|
||||
}
|
||||
ubifs_prepare_node(c, idx, len, 0);
|
||||
|
||||
#ifdef CONFIG_UBIFS_FS_DEBUG
|
||||
znode->lnum = lnum;
|
||||
znode->offs = offs;
|
||||
znode->len = len;
|
||||
#endif
|
||||
|
||||
err = insert_old_idx_znode(c, znode);
|
||||
|
||||
|
@ -322,8 +320,7 @@ static int layout_leb_in_gaps(struct ubifs_info *c, int *p)
|
|||
0, 0, 0);
|
||||
if (err)
|
||||
return err;
|
||||
err = ubifs_leb_change(c, lnum, c->ileb_buf, c->ileb_len,
|
||||
UBI_SHORTTERM);
|
||||
err = ubifs_leb_change(c, lnum, c->ileb_buf, c->ileb_len);
|
||||
if (err)
|
||||
return err;
|
||||
dbg_gc("LEB %d wrote %d index nodes", lnum, tot_written);
|
||||
|
@ -388,8 +385,8 @@ static int layout_in_gaps(struct ubifs_info *c, int cnt)
|
|||
* option which forces in-the-gaps is enabled.
|
||||
*/
|
||||
ubifs_warn("out of space");
|
||||
dbg_dump_budg(c, &c->bi);
|
||||
dbg_dump_lprops(c);
|
||||
ubifs_dump_budg(c, &c->bi);
|
||||
ubifs_dump_lprops(c);
|
||||
}
|
||||
/* Try to commit anyway */
|
||||
err = 0;
|
||||
|
@ -456,11 +453,9 @@ static int layout_in_empty_space(struct ubifs_info *c)
|
|||
|
||||
offs = buf_offs + used;
|
||||
|
||||
#ifdef CONFIG_UBIFS_FS_DEBUG
|
||||
znode->lnum = lnum;
|
||||
znode->offs = offs;
|
||||
znode->len = len;
|
||||
#endif
|
||||
|
||||
/* Update the parent */
|
||||
zp = znode->parent;
|
||||
|
@ -536,10 +531,8 @@ static int layout_in_empty_space(struct ubifs_info *c)
|
|||
break;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_UBIFS_FS_DEBUG
|
||||
c->dbg->new_ihead_lnum = lnum;
|
||||
c->dbg->new_ihead_offs = buf_offs;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -864,9 +857,9 @@ static int write_index(struct ubifs_info *c)
|
|||
br->len = cpu_to_le32(zbr->len);
|
||||
if (!zbr->lnum || !zbr->len) {
|
||||
ubifs_err("bad ref in znode");
|
||||
dbg_dump_znode(c, znode);
|
||||
ubifs_dump_znode(c, znode);
|
||||
if (zbr->znode)
|
||||
dbg_dump_znode(c, zbr->znode);
|
||||
ubifs_dump_znode(c, zbr->znode);
|
||||
}
|
||||
}
|
||||
len = ubifs_idx_node_sz(c, znode->child_cnt);
|
||||
|
@ -881,13 +874,11 @@ static int write_index(struct ubifs_info *c)
|
|||
}
|
||||
offs = buf_offs + used;
|
||||
|
||||
#ifdef CONFIG_UBIFS_FS_DEBUG
|
||||
if (lnum != znode->lnum || offs != znode->offs ||
|
||||
len != znode->len) {
|
||||
ubifs_err("inconsistent znode posn");
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Grab some stuff from znode while we still can */
|
||||
cnext = znode->cnext;
|
||||
|
@ -959,8 +950,7 @@ static int write_index(struct ubifs_info *c)
|
|||
}
|
||||
|
||||
/* The buffer is full or there are no more znodes to do */
|
||||
err = ubifs_leb_write(c, lnum, c->cbuf, buf_offs, blen,
|
||||
UBI_SHORTTERM);
|
||||
err = ubifs_leb_write(c, lnum, c->cbuf, buf_offs, blen);
|
||||
if (err)
|
||||
return err;
|
||||
buf_offs += blen;
|
||||
|
@ -982,13 +972,11 @@ static int write_index(struct ubifs_info *c)
|
|||
break;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_UBIFS_FS_DEBUG
|
||||
if (lnum != c->dbg->new_ihead_lnum ||
|
||||
buf_offs != c->dbg->new_ihead_offs) {
|
||||
ubifs_err("inconsistent ihead");
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
c->ihead_lnum = lnum;
|
||||
c->ihead_offs = buf_offs;
|
||||
|
|
|
@ -293,10 +293,10 @@ static int read_znode(struct ubifs_info *c, int lnum, int offs, int len,
|
|||
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);
|
||||
ubifs_err("current fanout %d, branch count %d",
|
||||
c->fanout, znode->child_cnt);
|
||||
ubifs_err("max levels %d, znode level %d",
|
||||
UBIFS_MAX_LEVELS, znode->level);
|
||||
err = 1;
|
||||
goto out_dump;
|
||||
}
|
||||
|
@ -316,7 +316,7 @@ static int read_znode(struct ubifs_info *c, int lnum, int offs, int len,
|
|||
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);
|
||||
ubifs_err("bad branch %d", i);
|
||||
err = 2;
|
||||
goto out_dump;
|
||||
}
|
||||
|
@ -340,19 +340,19 @@ static int read_znode(struct ubifs_info *c, int lnum, int offs, int len,
|
|||
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);
|
||||
ubifs_err("bad target node (type %d) length (%d)",
|
||||
type, zbr->len);
|
||||
ubifs_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);
|
||||
ubifs_err("bad target node (type %d) length (%d)",
|
||||
type, zbr->len);
|
||||
ubifs_err("have to be in range of %d-%d",
|
||||
c->ranges[type].min_len,
|
||||
c->ranges[type].max_len);
|
||||
err = 5;
|
||||
goto out_dump;
|
||||
}
|
||||
|
@ -370,13 +370,13 @@ static int read_znode(struct ubifs_info *c, int lnum, int offs, int len,
|
|||
|
||||
cmp = keys_cmp(c, key1, key2);
|
||||
if (cmp > 0) {
|
||||
dbg_err("bad key order (keys %d and %d)", i, i + 1);
|
||||
ubifs_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);
|
||||
ubifs_err("keys %d and %d are not hashed but equivalent",
|
||||
i, i + 1);
|
||||
err = 7;
|
||||
goto out_dump;
|
||||
}
|
||||
|
@ -387,7 +387,7 @@ static int read_znode(struct ubifs_info *c, int lnum, int offs, int len,
|
|||
|
||||
out_dump:
|
||||
ubifs_err("bad indexing node at LEB %d:%d, error %d", lnum, offs, err);
|
||||
dbg_dump_node(c, idx);
|
||||
ubifs_dump_node(c, idx);
|
||||
kfree(idx);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -486,7 +486,7 @@ int ubifs_tnc_read_node(struct ubifs_info *c, struct ubifs_zbranch *zbr,
|
|||
zbr->lnum, zbr->offs);
|
||||
dbg_tnck(key, "looked for key ");
|
||||
dbg_tnck(&key1, "but found node's key ");
|
||||
dbg_dump_node(c, node);
|
||||
ubifs_dump_node(c, node);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
|
@ -650,8 +650,6 @@ typedef int (*ubifs_lpt_scan_callback)(struct ubifs_info *c,
|
|||
* @avail: number of bytes available in the write-buffer
|
||||
* @used: number of used bytes in the write-buffer
|
||||
* @size: write-buffer size (in [@c->min_io_size, @c->max_write_size] range)
|
||||
* @dtype: type of data stored in this LEB (%UBI_LONGTERM, %UBI_SHORTTERM,
|
||||
* %UBI_UNKNOWN)
|
||||
* @jhead: journal head the mutex belongs to (note, needed only to shut lockdep
|
||||
* up by 'mutex_lock_nested()).
|
||||
* @sync_callback: write-buffer synchronization callback
|
||||
|
@ -685,7 +683,6 @@ struct ubifs_wbuf {
|
|||
int avail;
|
||||
int used;
|
||||
int size;
|
||||
int dtype;
|
||||
int jhead;
|
||||
int (*sync_callback)(struct ubifs_info *c, int lnum, int free, int pad);
|
||||
struct mutex io_mutex;
|
||||
|
@ -762,6 +759,9 @@ struct ubifs_zbranch {
|
|||
* @offs: offset of the corresponding indexing node
|
||||
* @len: length of the corresponding indexing node
|
||||
* @zbranch: array of znode branches (@c->fanout elements)
|
||||
*
|
||||
* Note! The @lnum, @offs, and @len fields are not really needed - we have them
|
||||
* only for internal consistency check. They could be removed to save some RAM.
|
||||
*/
|
||||
struct ubifs_znode {
|
||||
struct ubifs_znode *parent;
|
||||
|
@ -772,9 +772,9 @@ struct ubifs_znode {
|
|||
int child_cnt;
|
||||
int iip;
|
||||
int alt;
|
||||
#ifdef CONFIG_UBIFS_FS_DEBUG
|
||||
int lnum, offs, len;
|
||||
#endif
|
||||
int lnum;
|
||||
int offs;
|
||||
int len;
|
||||
struct ubifs_zbranch zbranch[];
|
||||
};
|
||||
|
||||
|
@ -1444,9 +1444,7 @@ struct ubifs_info {
|
|||
struct rb_root size_tree;
|
||||
struct ubifs_mount_opts mount_opts;
|
||||
|
||||
#ifdef CONFIG_UBIFS_FS_DEBUG
|
||||
struct ubifs_debug_info *dbg;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern struct list_head ubifs_infos;
|
||||
|
@ -1468,22 +1466,20 @@ void ubifs_ro_mode(struct ubifs_info *c, int err);
|
|||
int ubifs_leb_read(const struct ubifs_info *c, int lnum, void *buf, int offs,
|
||||
int len, int even_ebadmsg);
|
||||
int ubifs_leb_write(struct ubifs_info *c, int lnum, const void *buf, int offs,
|
||||
int len, int dtype);
|
||||
int ubifs_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len,
|
||||
int dtype);
|
||||
int len);
|
||||
int ubifs_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len);
|
||||
int ubifs_leb_unmap(struct ubifs_info *c, int lnum);
|
||||
int ubifs_leb_map(struct ubifs_info *c, int lnum, int dtype);
|
||||
int ubifs_leb_map(struct ubifs_info *c, int lnum);
|
||||
int ubifs_is_mapped(const struct ubifs_info *c, int lnum);
|
||||
int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len);
|
||||
int ubifs_wbuf_seek_nolock(struct ubifs_wbuf *wbuf, int lnum, int offs,
|
||||
int dtype);
|
||||
int ubifs_wbuf_seek_nolock(struct ubifs_wbuf *wbuf, int lnum, int offs);
|
||||
int ubifs_wbuf_init(struct ubifs_info *c, struct ubifs_wbuf *wbuf);
|
||||
int ubifs_read_node(const struct ubifs_info *c, void *buf, int type, int len,
|
||||
int lnum, int offs);
|
||||
int ubifs_read_node_wbuf(struct ubifs_wbuf *wbuf, void *buf, int type, int len,
|
||||
int lnum, int offs);
|
||||
int ubifs_write_node(struct ubifs_info *c, void *node, int len, int lnum,
|
||||
int offs, int dtype);
|
||||
int offs);
|
||||
int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum,
|
||||
int offs, int quiet, int must_chk_crc);
|
||||
void ubifs_prepare_node(struct ubifs_info *c, void *buf, int len, int pad);
|
||||
|
|
|
@ -399,8 +399,8 @@ ssize_t ubifs_getxattr(struct dentry *dentry, const char *name, void *buf,
|
|||
if (buf) {
|
||||
/* If @buf is %NULL we are supposed to return the length */
|
||||
if (ui->data_len > size) {
|
||||
dbg_err("buffer size %zd, xattr len %d",
|
||||
size, ui->data_len);
|
||||
ubifs_err("buffer size %zd, xattr len %d",
|
||||
size, ui->data_len);
|
||||
err = -ERANGE;
|
||||
goto out_iput;
|
||||
}
|
||||
|
|
|
@ -25,6 +25,9 @@
|
|||
#include <linux/types.h>
|
||||
#include <mtd/ubi-user.h>
|
||||
|
||||
/* All voumes/LEBs */
|
||||
#define UBI_ALL -1
|
||||
|
||||
/*
|
||||
* enum ubi_open_mode - UBI volume open mode constants.
|
||||
*
|
||||
|
@ -208,14 +211,15 @@ void ubi_close_volume(struct ubi_volume_desc *desc);
|
|||
int ubi_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset,
|
||||
int len, int check);
|
||||
int ubi_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
|
||||
int offset, int len, int dtype);
|
||||
int offset, int len);
|
||||
int ubi_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf,
|
||||
int len, int dtype);
|
||||
int len);
|
||||
int ubi_leb_erase(struct ubi_volume_desc *desc, int lnum);
|
||||
int ubi_leb_unmap(struct ubi_volume_desc *desc, int lnum);
|
||||
int ubi_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype);
|
||||
int ubi_leb_map(struct ubi_volume_desc *desc, int lnum);
|
||||
int ubi_is_mapped(struct ubi_volume_desc *desc, int lnum);
|
||||
int ubi_sync(int ubi_num);
|
||||
int ubi_flush(int ubi_num, int vol_id, int lnum);
|
||||
|
||||
/*
|
||||
* This function is the same as the 'ubi_leb_read()' function, but it does not
|
||||
|
@ -226,25 +230,4 @@ static inline int ubi_read(struct ubi_volume_desc *desc, int lnum, char *buf,
|
|||
{
|
||||
return ubi_leb_read(desc, lnum, buf, offset, len, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is the same as the 'ubi_leb_write()' functions, but it does
|
||||
* not have the data type argument.
|
||||
*/
|
||||
static inline int ubi_write(struct ubi_volume_desc *desc, int lnum,
|
||||
const void *buf, int offset, int len)
|
||||
{
|
||||
return ubi_leb_write(desc, lnum, buf, offset, len, UBI_UNKNOWN);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is the same as the 'ubi_leb_change()' functions, but it does
|
||||
* not have the data type argument.
|
||||
*/
|
||||
static inline int ubi_change(struct ubi_volume_desc *desc, int lnum,
|
||||
const void *buf, int len)
|
||||
{
|
||||
return ubi_leb_change(desc, lnum, buf, len, UBI_UNKNOWN);
|
||||
}
|
||||
|
||||
#endif /* !__LINUX_UBI_H__ */
|
||||
|
|
|
@ -195,23 +195,6 @@
|
|||
/* Maximum amount of UBI volumes that can be re-named at one go */
|
||||
#define UBI_MAX_RNVOL 32
|
||||
|
||||
/*
|
||||
* UBI data type hint constants.
|
||||
*
|
||||
* UBI_LONGTERM: long-term data
|
||||
* UBI_SHORTTERM: short-term data
|
||||
* UBI_UNKNOWN: data persistence is unknown
|
||||
*
|
||||
* These constants are used when data is written to UBI volumes in order to
|
||||
* help the UBI wear-leveling unit to find more appropriate physical
|
||||
* eraseblocks.
|
||||
*/
|
||||
enum {
|
||||
UBI_LONGTERM = 1,
|
||||
UBI_SHORTTERM = 2,
|
||||
UBI_UNKNOWN = 3,
|
||||
};
|
||||
|
||||
/*
|
||||
* UBI volume type constants.
|
||||
*
|
||||
|
@ -375,25 +358,34 @@ struct ubi_rnvol_req {
|
|||
* requests.
|
||||
* @lnum: logical eraseblock number to change
|
||||
* @bytes: how many bytes will be written to the logical eraseblock
|
||||
* @dtype: data type (%UBI_LONGTERM, %UBI_SHORTTERM, %UBI_UNKNOWN)
|
||||
* @dtype: pass "3" for better compatibility with old kernels
|
||||
* @padding: reserved for future, not used, has to be zeroed
|
||||
*
|
||||
* The @dtype field used to inform UBI about what kind of data will be written
|
||||
* to the LEB: long term (value 1), short term (value 2), unknown (value 3).
|
||||
* UBI tried to pick a PEB with lower erase counter for short term data and a
|
||||
* PEB with higher erase counter for long term data. But this was not really
|
||||
* used because users usually do not know this and could easily mislead UBI. We
|
||||
* removed this feature in May 2012. UBI currently just ignores the @dtype
|
||||
* field. But for better compatibility with older kernels it is recommended to
|
||||
* set @dtype to 3 (unknown).
|
||||
*/
|
||||
struct ubi_leb_change_req {
|
||||
__s32 lnum;
|
||||
__s32 bytes;
|
||||
__s8 dtype;
|
||||
__s8 dtype; /* obsolete, do not use! */
|
||||
__s8 padding[7];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct ubi_map_req - a data structure used in map LEB requests.
|
||||
* @dtype: pass "3" for better compatibility with old kernels
|
||||
* @lnum: logical eraseblock number to unmap
|
||||
* @dtype: data type (%UBI_LONGTERM, %UBI_SHORTTERM, %UBI_UNKNOWN)
|
||||
* @padding: reserved for future, not used, has to be zeroed
|
||||
*/
|
||||
struct ubi_map_req {
|
||||
__s32 lnum;
|
||||
__s8 dtype;
|
||||
__s8 dtype; /* obsolete, do not use! */
|
||||
__s8 padding[3];
|
||||
} __packed;
|
||||
|
||||
|
|
Loading…
Reference in a new issue