mirror of
https://github.com/torvalds/linux.git
synced 2024-11-12 07:01:57 +00:00
The main change is the way we reserve eraseblocks for bad blocks
handling. We used to reserve 2% of the partition, but now we are more aggressive and we reserve 2% of the entire chip, which is what actually manufacturers specify in data sheets. We introduced an option to users to override the default, though. There are a couple of fixes as well, and a number of cleanups. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.12 (GNU/Linux) iQIcBAABAgAGBQJQauyXAAoJECmIfjd9wqK0hLAQAL1tv4BwLUi8NlUristmO7GY qb4LvfadhYldapXQ/kw9g7DjDQduuerBaIGh7oglRG2HFtNrMD/03umTwb0P4li4 gB/YJxRlU2TdPxn6tmvldGyLUVd8DjGZBvF0l9Mzuc0pGz95UCGcWhwysTFtyxVg AmKrW55jqSImzH0L2UkVNepV4h3vXivOLlM/SFP1bgAcVfKlj8THnNgO6cAKGuV8 q2qzWmFOakiMFzxgjpfx6QtcmyOUTSgKD+jBEmsUGbCmQmOdXpyXKwP2UugoCltF j+MwwOsLD0J8WG6j4NPlzbPBSg8zJD2O6MQa0dCy+WG8ho0BloMfjLFv2qavcLYX dSrWn4Df/mIuAjNqcrgC46nnnrHDQcNzqlfsD/f1tsnDvtLZ6CzEthAqPBBCU8Uq TaF3kEKwq02JkZFAfkPEVkaFTkgBpa27EdRS+KzsRBIhsMSySC9tJOvl5QIRi9Ad bnsgXIYZUzi36CGzUHGLeCMw6APC/smBqP/o2zQGpX0DA/WOmRgIuclpap8XSt+h tBL4v785w8CzOCPSRRagr06wxDdu9vhd4GsTrg7dIIFrZnA0pZWWgSV8xlcjrWt9 VPw/DLvRPIV/b0BzNcA1gfDvo4GLwuY7eQRdBjYjLByKHJDXouH1p1CZcDJvQtio qbSA1x8NNKvIy1D8gawd =95SE -----END PGP SIGNATURE----- Merge tag 'upstream-3.7-rc1' of git://git.infradead.org/linux-ubi Pull UBI changes from Artem Bityutskiy: "The main change is the way we reserve eraseblocks for bad blocks handling. We used to reserve 2% of the partition, but now we are more aggressive and we reserve 2% of the entire chip, which is what actually manufacturers specify in data sheets. We introduced an option to users to override the default, though. There are a couple of fixes as well, and a number of cleanups." * tag 'upstream-3.7-rc1' of git://git.infradead.org/linux-ubi: (24 commits) UBI: fix trivial typo 'it' => 'is' UBI: load after mtd device drivers UBI: print less UBI: use pr_ helper instead of printk UBI: comply with coding style UBI: erase free PEB with bitflip in EC header UBI: fix autoresize handling in R/O mode UBI: add max_beb_per1024 to attach ioctl UBI: allow specifying bad PEBs limit using module parameter UBI: check max_beb_per1024 value in ubi_attach_mtd_dev UBI: prepare for max_beb_per1024 module parameter addition UBI: introduce MTD_PARAM_MAX_COUNT UBI: separate bad_peb_limit in a function arm: sam9_l9260_defconfig: correct CONFIG_MTD_UBI_BEB_LIMIT UBI: use the whole MTD device size to get bad_peb_limit mtd: mtdparts: introduce mtd_get_device_size mtd: mark mtd_is_partition argument as constant arm: sam9_l9260_defconfig: remove non-existing config option UBI: kill CONFIG_MTD_UBI_BEB_RESERVE UBI: limit amount of reserved eraseblocks for bad PEB handling ...
This commit is contained in:
commit
65b99c74fd
@ -39,7 +39,7 @@ CONFIG_MTD_NAND=y
|
||||
CONFIG_MTD_NAND_ATMEL=y
|
||||
CONFIG_MTD_NAND_PLATFORM=y
|
||||
CONFIG_MTD_UBI=y
|
||||
CONFIG_MTD_UBI_BEB_RESERVE=3
|
||||
CONFIG_MTD_UBI_BEB_LIMIT=25
|
||||
CONFIG_MTD_UBI_GLUEBI=y
|
||||
CONFIG_BLK_DEV_LOOP=y
|
||||
CONFIG_BLK_DEV_RAM=y
|
||||
|
@ -744,7 +744,7 @@ int parse_mtd_partitions(struct mtd_info *master, const char **types,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mtd_is_partition(struct mtd_info *mtd)
|
||||
int mtd_is_partition(const struct mtd_info *mtd)
|
||||
{
|
||||
struct mtd_part *part;
|
||||
int ispart = 0;
|
||||
@ -760,3 +760,13 @@ int mtd_is_partition(struct mtd_info *mtd)
|
||||
return ispart;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mtd_is_partition);
|
||||
|
||||
/* Returns the size of the entire flash chip */
|
||||
uint64_t mtd_get_device_size(const struct mtd_info *mtd)
|
||||
{
|
||||
if (!mtd_is_partition(mtd))
|
||||
return mtd->size;
|
||||
|
||||
return PART(mtd)->master->size;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mtd_get_device_size);
|
||||
|
@ -27,20 +27,34 @@ config MTD_UBI_WL_THRESHOLD
|
||||
life-cycle less than 10000, the threshold should be lessened (e.g.,
|
||||
to 128 or 256, although it does not have to be power of 2).
|
||||
|
||||
config MTD_UBI_BEB_RESERVE
|
||||
int "Percentage of reserved eraseblocks for bad eraseblocks handling"
|
||||
default 2
|
||||
range 0 25
|
||||
config MTD_UBI_BEB_LIMIT
|
||||
int "Maximum expected bad eraseblock count per 1024 eraseblocks"
|
||||
default 20
|
||||
range 0 768
|
||||
help
|
||||
If the MTD device admits of bad eraseblocks (e.g. NAND flash), UBI
|
||||
reserves some amount of physical eraseblocks to handle new bad
|
||||
eraseblocks. For example, if a flash physical eraseblock becomes bad,
|
||||
UBI uses these reserved physical eraseblocks to relocate the bad one.
|
||||
This option specifies how many physical eraseblocks will be reserved
|
||||
for bad eraseblock handling (percents of total number of good flash
|
||||
eraseblocks). If the underlying flash does not admit of bad
|
||||
eraseblocks (e.g. NOR flash), this value is ignored and nothing is
|
||||
reserved. Leave the default value if unsure.
|
||||
This option specifies the maximum bad physical eraseblocks UBI
|
||||
expects on the MTD device (per 1024 eraseblocks). If the underlying
|
||||
flash does not admit of bad eraseblocks (e.g. NOR flash), this value
|
||||
is ignored.
|
||||
|
||||
NAND datasheets often specify the minimum and maximum NVM (Number of
|
||||
Valid Blocks) for the flashes' endurance lifetime. The maximum
|
||||
expected bad eraseblocks per 1024 eraseblocks then can be calculated
|
||||
as "1024 * (1 - MinNVB / MaxNVB)", which gives 20 for most NANDs
|
||||
(MaxNVB is basically the total count of eraseblocks on the chip).
|
||||
|
||||
To put it differently, if this value is 20, UBI will try to reserve
|
||||
about 1.9% of physical eraseblocks for bad blocks handling. And that
|
||||
will be 1.9% of eraseblocks on the entire NAND chip, not just the MTD
|
||||
partition UBI attaches. This means that if you have, say, a NAND
|
||||
flash chip admits maximum 40 bad eraseblocks, and it is split on two
|
||||
MTD partitions of the same size, UBI will reserve 40 eraseblocks when
|
||||
attaching a partition.
|
||||
|
||||
This option can be overridden by the "mtd=" UBI module parameter or
|
||||
by the "attach" ioctl.
|
||||
|
||||
Leave the default value if unsure.
|
||||
|
||||
config MTD_UBI_GLUEBI
|
||||
tristate "MTD devices emulation driver (gluebi)"
|
||||
|
@ -79,7 +79,7 @@
|
||||
* NAND), it is probably a PEB which was being erased when power cut
|
||||
* happened, so this is corruption type 1. However, this is just a guess,
|
||||
* which might be wrong.
|
||||
* o Otherwise this it corruption type 2.
|
||||
* o Otherwise this is corruption type 2.
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
@ -378,8 +378,8 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_ainf_peb *aeb,
|
||||
if (err == UBI_IO_BITFLIPS)
|
||||
bitflips = 1;
|
||||
else {
|
||||
ubi_err("VID of PEB %d header is bad, but it "
|
||||
"was OK earlier, err %d", pnum, err);
|
||||
ubi_err("VID of PEB %d header is bad, but it was OK earlier, err %d",
|
||||
pnum, err);
|
||||
if (err > 0)
|
||||
err = -EIO;
|
||||
|
||||
@ -790,12 +790,12 @@ static int check_corruption(struct ubi_device *ubi, struct ubi_vid_hdr *vid_hdr,
|
||||
if (ubi_check_pattern(ubi->peb_buf, 0xFF, ubi->leb_size))
|
||||
goto out_unlock;
|
||||
|
||||
ubi_err("PEB %d contains corrupted VID header, and the data does not "
|
||||
"contain all 0xFF, this may be a non-UBI PEB or a severe VID "
|
||||
"header corruption which requires manual inspection", pnum);
|
||||
ubi_err("PEB %d contains corrupted VID header, and the data does not contain all 0xFF",
|
||||
pnum);
|
||||
ubi_err("this may be a non-UBI PEB or a severe VID header corruption which requires manual inspection");
|
||||
ubi_dump_vid_hdr(vid_hdr);
|
||||
dbg_msg("hexdump of PEB %d offset %d, length %d",
|
||||
pnum, ubi->leb_start, ubi->leb_size);
|
||||
pr_err("hexdump of PEB %d offset %d, length %d",
|
||||
pnum, ubi->leb_start, ubi->leb_size);
|
||||
ubi_dbg_print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
|
||||
ubi->peb_buf, ubi->leb_size, 1);
|
||||
err = 1;
|
||||
@ -907,8 +907,8 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai,
|
||||
ubi->image_seq = image_seq;
|
||||
if (ubi->image_seq && image_seq &&
|
||||
ubi->image_seq != image_seq) {
|
||||
ubi_err("bad image sequence number %d in PEB %d, "
|
||||
"expected %d", image_seq, pnum, ubi->image_seq);
|
||||
ubi_err("bad image sequence number %d in PEB %d, expected %d",
|
||||
image_seq, pnum, ubi->image_seq);
|
||||
ubi_dump_ec_hdr(ech);
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -975,7 +975,7 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai,
|
||||
return err;
|
||||
goto adjust_mean_ec;
|
||||
case UBI_IO_FF:
|
||||
if (ec_err)
|
||||
if (ec_err || bitflips)
|
||||
err = add_to_list(ai, pnum, UBI_UNKNOWN,
|
||||
UBI_UNKNOWN, ec, 1, &ai->erase);
|
||||
else
|
||||
@ -997,8 +997,8 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai,
|
||||
/* Unsupported internal volume */
|
||||
switch (vidh->compat) {
|
||||
case UBI_COMPAT_DELETE:
|
||||
ubi_msg("\"delete\" compatible internal volume %d:%d"
|
||||
" found, will remove it", vol_id, lnum);
|
||||
ubi_msg("\"delete\" compatible internal volume %d:%d found, will remove it",
|
||||
vol_id, lnum);
|
||||
err = add_to_list(ai, pnum, vol_id, lnum,
|
||||
ec, 1, &ai->erase);
|
||||
if (err)
|
||||
@ -1006,15 +1006,14 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai,
|
||||
return 0;
|
||||
|
||||
case UBI_COMPAT_RO:
|
||||
ubi_msg("read-only compatible internal volume %d:%d"
|
||||
" found, switch to read-only mode",
|
||||
ubi_msg("read-only compatible internal volume %d:%d found, switch to read-only mode",
|
||||
vol_id, lnum);
|
||||
ubi->ro_mode = 1;
|
||||
break;
|
||||
|
||||
case UBI_COMPAT_PRESERVE:
|
||||
ubi_msg("\"preserve\" compatible internal volume %d:%d"
|
||||
" found", vol_id, lnum);
|
||||
ubi_msg("\"preserve\" compatible internal volume %d:%d found",
|
||||
vol_id, lnum);
|
||||
err = add_to_list(ai, pnum, vol_id, lnum,
|
||||
ec, 0, &ai->alien);
|
||||
if (err)
|
||||
@ -1075,10 +1074,10 @@ static int late_analysis(struct ubi_device *ubi, struct ubi_attach_info *ai)
|
||||
if (ai->corr_peb_count) {
|
||||
ubi_err("%d PEBs are corrupted and preserved",
|
||||
ai->corr_peb_count);
|
||||
printk(KERN_ERR "Corrupted PEBs are:");
|
||||
pr_err("Corrupted PEBs are:");
|
||||
list_for_each_entry(aeb, &ai->corr, u.list)
|
||||
printk(KERN_CONT " %d", aeb->pnum);
|
||||
printk(KERN_CONT "\n");
|
||||
pr_cont(" %d", aeb->pnum);
|
||||
pr_cont("\n");
|
||||
|
||||
/*
|
||||
* If too many PEBs are corrupted, we refuse attaching,
|
||||
@ -1112,8 +1111,7 @@ static int late_analysis(struct ubi_device *ubi, struct ubi_attach_info *ai)
|
||||
get_random_bytes(&ubi->image_seq,
|
||||
sizeof(ubi->image_seq));
|
||||
} else {
|
||||
ubi_err("MTD device is not UBI-formatted and possibly "
|
||||
"contains non-UBI data - refusing it");
|
||||
ubi_err("MTD device is not UBI-formatted and possibly contains non-UBI data - refusing it");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -1172,7 +1170,7 @@ static struct ubi_attach_info *scan_all(struct ubi_device *ubi)
|
||||
goto out_vidh;
|
||||
}
|
||||
|
||||
dbg_msg("scanning is finished");
|
||||
ubi_msg("scanning is finished");
|
||||
|
||||
/* Calculate mean erase counter */
|
||||
if (ai->ec_count)
|
||||
@ -1244,7 +1242,7 @@ int ubi_attach(struct ubi_device *ubi)
|
||||
ubi->corr_peb_count = ai->corr_peb_count;
|
||||
ubi->max_ec = ai->max_ec;
|
||||
ubi->mean_ec = ai->mean_ec;
|
||||
ubi_msg("max. sequence number: %llu", ai->max_sqnum);
|
||||
dbg_gen("max. sequence number: %llu", ai->max_sqnum);
|
||||
|
||||
err = ubi_read_volume_table(ubi, ai);
|
||||
if (err)
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <linux/namei.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
#include <linux/log2.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/kernel.h>
|
||||
@ -45,6 +46,12 @@
|
||||
/* Maximum length of the 'mtd=' parameter */
|
||||
#define MTD_PARAM_LEN_MAX 64
|
||||
|
||||
/* Maximum number of comma-separated items in the 'mtd=' parameter */
|
||||
#define MTD_PARAM_MAX_COUNT 3
|
||||
|
||||
/* Maximum value for the number of bad PEBs per 1024 PEBs */
|
||||
#define MAX_MTD_UBI_BEB_LIMIT 768
|
||||
|
||||
#ifdef CONFIG_MTD_UBI_MODULE
|
||||
#define ubi_is_module() 1
|
||||
#else
|
||||
@ -56,10 +63,12 @@
|
||||
* @name: MTD character device node path, MTD device name, or MTD device number
|
||||
* string
|
||||
* @vid_hdr_offs: VID header offset
|
||||
* @max_beb_per1024: maximum expected number of bad PEBs per 1024 PEBs
|
||||
*/
|
||||
struct mtd_dev_param {
|
||||
char name[MTD_PARAM_LEN_MAX];
|
||||
int vid_hdr_offs;
|
||||
int max_beb_per1024;
|
||||
};
|
||||
|
||||
/* Numbers of elements set in the @mtd_dev_param array */
|
||||
@ -564,9 +573,38 @@ void ubi_free_internal_volumes(struct ubi_device *ubi)
|
||||
}
|
||||
}
|
||||
|
||||
static int get_bad_peb_limit(const struct ubi_device *ubi, int max_beb_per1024)
|
||||
{
|
||||
int limit, device_pebs;
|
||||
uint64_t device_size;
|
||||
|
||||
if (!max_beb_per1024)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Here we are using size of the entire flash chip and
|
||||
* not just the MTD partition size because the maximum
|
||||
* number of bad eraseblocks is a percentage of the
|
||||
* whole device and bad eraseblocks are not fairly
|
||||
* distributed over the flash chip. So the worst case
|
||||
* is that all the bad eraseblocks of the chip are in
|
||||
* the MTD partition we are attaching (ubi->mtd).
|
||||
*/
|
||||
device_size = mtd_get_device_size(ubi->mtd);
|
||||
device_pebs = mtd_div_by_eb(device_size, ubi->mtd);
|
||||
limit = mult_frac(device_pebs, max_beb_per1024, 1024);
|
||||
|
||||
/* Round it up */
|
||||
if (mult_frac(limit, 1024, max_beb_per1024) < device_pebs)
|
||||
limit += 1;
|
||||
|
||||
return limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* io_init - initialize I/O sub-system for a given UBI device.
|
||||
* @ubi: UBI device description object
|
||||
* @max_beb_per1024: maximum expected number of bad PEB per 1024 PEBs
|
||||
*
|
||||
* If @ubi->vid_hdr_offset or @ubi->leb_start is zero, default offsets are
|
||||
* assumed:
|
||||
@ -579,8 +617,11 @@ void ubi_free_internal_volumes(struct ubi_device *ubi)
|
||||
* This function returns zero in case of success and a negative error code in
|
||||
* case of failure.
|
||||
*/
|
||||
static int io_init(struct ubi_device *ubi)
|
||||
static int io_init(struct ubi_device *ubi, int max_beb_per1024)
|
||||
{
|
||||
dbg_gen("sizeof(struct ubi_ainf_peb) %zu", sizeof(struct ubi_ainf_peb));
|
||||
dbg_gen("sizeof(struct ubi_wl_entry) %zu", sizeof(struct ubi_wl_entry));
|
||||
|
||||
if (ubi->mtd->numeraseregions != 0) {
|
||||
/*
|
||||
* Some flashes have several erase regions. Different regions
|
||||
@ -607,8 +648,10 @@ static int io_init(struct ubi_device *ubi)
|
||||
ubi->peb_count = mtd_div_by_eb(ubi->mtd->size, ubi->mtd);
|
||||
ubi->flash_size = ubi->mtd->size;
|
||||
|
||||
if (mtd_can_have_bb(ubi->mtd))
|
||||
if (mtd_can_have_bb(ubi->mtd)) {
|
||||
ubi->bad_allowed = 1;
|
||||
ubi->bad_peb_limit = get_bad_peb_limit(ubi, max_beb_per1024);
|
||||
}
|
||||
|
||||
if (ubi->mtd->type == MTD_NORFLASH) {
|
||||
ubi_assert(ubi->mtd->writesize == 1);
|
||||
@ -650,11 +693,11 @@ static int io_init(struct ubi_device *ubi)
|
||||
ubi->ec_hdr_alsize = ALIGN(UBI_EC_HDR_SIZE, ubi->hdrs_min_io_size);
|
||||
ubi->vid_hdr_alsize = ALIGN(UBI_VID_HDR_SIZE, ubi->hdrs_min_io_size);
|
||||
|
||||
dbg_msg("min_io_size %d", ubi->min_io_size);
|
||||
dbg_msg("max_write_size %d", ubi->max_write_size);
|
||||
dbg_msg("hdrs_min_io_size %d", ubi->hdrs_min_io_size);
|
||||
dbg_msg("ec_hdr_alsize %d", ubi->ec_hdr_alsize);
|
||||
dbg_msg("vid_hdr_alsize %d", ubi->vid_hdr_alsize);
|
||||
dbg_gen("min_io_size %d", ubi->min_io_size);
|
||||
dbg_gen("max_write_size %d", ubi->max_write_size);
|
||||
dbg_gen("hdrs_min_io_size %d", ubi->hdrs_min_io_size);
|
||||
dbg_gen("ec_hdr_alsize %d", ubi->ec_hdr_alsize);
|
||||
dbg_gen("vid_hdr_alsize %d", ubi->vid_hdr_alsize);
|
||||
|
||||
if (ubi->vid_hdr_offset == 0)
|
||||
/* Default offset */
|
||||
@ -671,10 +714,10 @@ static int io_init(struct ubi_device *ubi)
|
||||
ubi->leb_start = ubi->vid_hdr_offset + UBI_VID_HDR_SIZE;
|
||||
ubi->leb_start = ALIGN(ubi->leb_start, ubi->min_io_size);
|
||||
|
||||
dbg_msg("vid_hdr_offset %d", ubi->vid_hdr_offset);
|
||||
dbg_msg("vid_hdr_aloffset %d", ubi->vid_hdr_aloffset);
|
||||
dbg_msg("vid_hdr_shift %d", ubi->vid_hdr_shift);
|
||||
dbg_msg("leb_start %d", ubi->leb_start);
|
||||
dbg_gen("vid_hdr_offset %d", ubi->vid_hdr_offset);
|
||||
dbg_gen("vid_hdr_aloffset %d", ubi->vid_hdr_aloffset);
|
||||
dbg_gen("vid_hdr_shift %d", ubi->vid_hdr_shift);
|
||||
dbg_gen("leb_start %d", ubi->leb_start);
|
||||
|
||||
/* The shift must be aligned to 32-bit boundary */
|
||||
if (ubi->vid_hdr_shift % 4) {
|
||||
@ -700,7 +743,7 @@ static int io_init(struct ubi_device *ubi)
|
||||
ubi->max_erroneous = ubi->peb_count / 10;
|
||||
if (ubi->max_erroneous < 16)
|
||||
ubi->max_erroneous = 16;
|
||||
dbg_msg("max_erroneous %d", ubi->max_erroneous);
|
||||
dbg_gen("max_erroneous %d", ubi->max_erroneous);
|
||||
|
||||
/*
|
||||
* It may happen that EC and VID headers are situated in one minimal
|
||||
@ -708,30 +751,18 @@ static int io_init(struct ubi_device *ubi)
|
||||
* read-only mode.
|
||||
*/
|
||||
if (ubi->vid_hdr_offset + UBI_VID_HDR_SIZE <= ubi->hdrs_min_io_size) {
|
||||
ubi_warn("EC and VID headers are in the same minimal I/O unit, "
|
||||
"switch to read-only mode");
|
||||
ubi_warn("EC and VID headers are in the same minimal I/O unit, switch to read-only mode");
|
||||
ubi->ro_mode = 1;
|
||||
}
|
||||
|
||||
ubi->leb_size = ubi->peb_size - ubi->leb_start;
|
||||
|
||||
if (!(ubi->mtd->flags & MTD_WRITEABLE)) {
|
||||
ubi_msg("MTD device %d is write-protected, attach in "
|
||||
"read-only mode", ubi->mtd->index);
|
||||
ubi_msg("MTD device %d is write-protected, attach in read-only mode",
|
||||
ubi->mtd->index);
|
||||
ubi->ro_mode = 1;
|
||||
}
|
||||
|
||||
ubi_msg("physical eraseblock size: %d bytes (%d KiB)",
|
||||
ubi->peb_size, ubi->peb_size >> 10);
|
||||
ubi_msg("logical eraseblock size: %d bytes", ubi->leb_size);
|
||||
ubi_msg("smallest flash I/O unit: %d", ubi->min_io_size);
|
||||
if (ubi->hdrs_min_io_size != ubi->min_io_size)
|
||||
ubi_msg("sub-page size: %d",
|
||||
ubi->hdrs_min_io_size);
|
||||
ubi_msg("VID header offset: %d (aligned %d)",
|
||||
ubi->vid_hdr_offset, ubi->vid_hdr_aloffset);
|
||||
ubi_msg("data offset: %d", ubi->leb_start);
|
||||
|
||||
/*
|
||||
* Note, ideally, we have to initialize @ubi->bad_peb_count here. But
|
||||
* unfortunately, MTD does not provide this information. We should loop
|
||||
@ -759,6 +790,11 @@ static int autoresize(struct ubi_device *ubi, int vol_id)
|
||||
struct ubi_volume *vol = ubi->volumes[vol_id];
|
||||
int err, old_reserved_pebs = vol->reserved_pebs;
|
||||
|
||||
if (ubi->ro_mode) {
|
||||
ubi_warn("skip auto-resize because of R/O mode");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear the auto-resize flag in the volume in-memory copy of the
|
||||
* volume table, and 'ubi_resize_volume()' will propagate this change
|
||||
@ -800,6 +836,7 @@ static int autoresize(struct ubi_device *ubi, int vol_id)
|
||||
* @mtd: MTD device description object
|
||||
* @ubi_num: number to assign to the new UBI device
|
||||
* @vid_hdr_offset: VID header offset
|
||||
* @max_beb_per1024: maximum expected number of bad PEB per 1024 PEBs
|
||||
*
|
||||
* This function attaches MTD device @mtd_dev to UBI and assign @ubi_num number
|
||||
* to the newly created UBI device, unless @ubi_num is %UBI_DEV_NUM_AUTO, in
|
||||
@ -810,11 +847,18 @@ static int autoresize(struct ubi_device *ubi, int vol_id)
|
||||
* Note, the invocations of this function has to be serialized by the
|
||||
* @ubi_devices_mutex.
|
||||
*/
|
||||
int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
|
||||
int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
|
||||
int vid_hdr_offset, int max_beb_per1024)
|
||||
{
|
||||
struct ubi_device *ubi;
|
||||
int i, err, ref = 0;
|
||||
|
||||
if (max_beb_per1024 < 0 || max_beb_per1024 > MAX_MTD_UBI_BEB_LIMIT)
|
||||
return -EINVAL;
|
||||
|
||||
if (!max_beb_per1024)
|
||||
max_beb_per1024 = CONFIG_MTD_UBI_BEB_LIMIT;
|
||||
|
||||
/*
|
||||
* Check if we already have the same MTD device attached.
|
||||
*
|
||||
@ -839,8 +883,8 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
|
||||
* no sense to attach emulated MTD devices, so we prohibit this.
|
||||
*/
|
||||
if (mtd->type == MTD_UBIVOLUME) {
|
||||
ubi_err("refuse attaching mtd%d - it is already emulated on "
|
||||
"top of UBI", mtd->index);
|
||||
ubi_err("refuse attaching mtd%d - it is already emulated on top of UBI",
|
||||
mtd->index);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -880,10 +924,8 @@ 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_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);
|
||||
err = io_init(ubi, max_beb_per1024);
|
||||
if (err)
|
||||
goto out_free;
|
||||
|
||||
@ -924,23 +966,24 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
|
||||
goto out_debugfs;
|
||||
}
|
||||
|
||||
ubi_msg("attached mtd%d to ubi%d", mtd->index, ubi_num);
|
||||
ubi_msg("MTD device name: \"%s\"", mtd->name);
|
||||
ubi_msg("MTD device size: %llu MiB", ubi->flash_size >> 20);
|
||||
ubi_msg("number of good PEBs: %d", ubi->good_peb_count);
|
||||
ubi_msg("number of bad PEBs: %d", ubi->bad_peb_count);
|
||||
ubi_msg("number of corrupted PEBs: %d", ubi->corr_peb_count);
|
||||
ubi_msg("max. allowed volumes: %d", ubi->vtbl_slots);
|
||||
ubi_msg("wear-leveling threshold: %d", CONFIG_MTD_UBI_WL_THRESHOLD);
|
||||
ubi_msg("number of internal volumes: %d", UBI_INT_VOL_COUNT);
|
||||
ubi_msg("number of user volumes: %d",
|
||||
ubi->vol_count - UBI_INT_VOL_COUNT);
|
||||
ubi_msg("available PEBs: %d", ubi->avail_pebs);
|
||||
ubi_msg("total number of reserved PEBs: %d", ubi->rsvd_pebs);
|
||||
ubi_msg("number of PEBs reserved for bad PEB handling: %d",
|
||||
ubi->beb_rsvd_pebs);
|
||||
ubi_msg("max/mean erase counter: %d/%d", ubi->max_ec, ubi->mean_ec);
|
||||
ubi_msg("image sequence number: %d", ubi->image_seq);
|
||||
ubi_msg("attached mtd%d (name \"%s\", size %llu MiB) to ubi%d",
|
||||
mtd->index, mtd->name, ubi->flash_size >> 20, ubi_num);
|
||||
ubi_msg("PEB size: %d bytes (%d KiB), LEB size: %d bytes",
|
||||
ubi->peb_size, ubi->peb_size >> 10, ubi->leb_size);
|
||||
ubi_msg("min./max. I/O unit sizes: %d/%d, sub-page size %d",
|
||||
ubi->min_io_size, ubi->max_write_size, ubi->hdrs_min_io_size);
|
||||
ubi_msg("VID header offset: %d (aligned %d), data offset: %d",
|
||||
ubi->vid_hdr_offset, ubi->vid_hdr_aloffset, ubi->leb_start);
|
||||
ubi_msg("good PEBs: %d, bad PEBs: %d, corrupted PEBs: %d",
|
||||
ubi->good_peb_count, ubi->bad_peb_count, ubi->corr_peb_count);
|
||||
ubi_msg("user volume: %d, internal volumes: %d, max. volumes count: %d",
|
||||
ubi->vol_count - UBI_INT_VOL_COUNT, UBI_INT_VOL_COUNT,
|
||||
ubi->vtbl_slots);
|
||||
ubi_msg("max/mean erase counter: %d/%d, WL threshold: %d, image sequence number: %u",
|
||||
ubi->max_ec, ubi->mean_ec, CONFIG_MTD_UBI_WL_THRESHOLD,
|
||||
ubi->image_seq);
|
||||
ubi_msg("available PEBs: %d, total reserved PEBs: %d, PEBs reserved for bad PEB handling: %d",
|
||||
ubi->avail_pebs, ubi->rsvd_pebs, ubi->beb_rsvd_pebs);
|
||||
|
||||
/*
|
||||
* The below lock makes sure we do not race with 'ubi_thread()' which
|
||||
@ -1017,7 +1060,7 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
|
||||
|
||||
ubi_assert(ubi_num == ubi->ubi_num);
|
||||
ubi_notify_all(ubi, UBI_VOLUME_REMOVED, NULL);
|
||||
dbg_msg("detaching mtd%d from ubi%d", ubi->mtd->index, ubi_num);
|
||||
ubi_msg("detaching mtd%d from ubi%d", ubi->mtd->index, ubi_num);
|
||||
|
||||
/*
|
||||
* Before freeing anything, we have to stop the background thread to
|
||||
@ -1172,7 +1215,7 @@ static int __init ubi_init(void)
|
||||
|
||||
mutex_lock(&ubi_devices_mutex);
|
||||
err = ubi_attach_mtd_dev(mtd, UBI_DEV_NUM_AUTO,
|
||||
p->vid_hdr_offs);
|
||||
p->vid_hdr_offs, p->max_beb_per1024);
|
||||
mutex_unlock(&ubi_devices_mutex);
|
||||
if (err < 0) {
|
||||
ubi_err("cannot attach mtd%d", mtd->index);
|
||||
@ -1218,7 +1261,7 @@ out:
|
||||
ubi_err("UBI error: cannot initialize UBI, error %d", err);
|
||||
return err;
|
||||
}
|
||||
module_init(ubi_init);
|
||||
late_initcall(ubi_init);
|
||||
|
||||
static void __exit ubi_exit(void)
|
||||
{
|
||||
@ -1252,8 +1295,7 @@ static int __init bytes_str_to_int(const char *str)
|
||||
|
||||
result = simple_strtoul(str, &endp, 0);
|
||||
if (str == endp || result >= INT_MAX) {
|
||||
printk(KERN_ERR "UBI error: incorrect bytes count: \"%s\"\n",
|
||||
str);
|
||||
ubi_err("UBI error: incorrect bytes count: \"%s\"\n", str);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -1269,8 +1311,7 @@ static int __init bytes_str_to_int(const char *str)
|
||||
case '\0':
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "UBI error: incorrect bytes count: \"%s\"\n",
|
||||
str);
|
||||
ubi_err("UBI error: incorrect bytes count: \"%s\"\n", str);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -1291,27 +1332,26 @@ static int __init ubi_mtd_param_parse(const char *val, struct kernel_param *kp)
|
||||
struct mtd_dev_param *p;
|
||||
char buf[MTD_PARAM_LEN_MAX];
|
||||
char *pbuf = &buf[0];
|
||||
char *tokens[2] = {NULL, NULL};
|
||||
char *tokens[MTD_PARAM_MAX_COUNT];
|
||||
|
||||
if (!val)
|
||||
return -EINVAL;
|
||||
|
||||
if (mtd_devs == UBI_MAX_DEVICES) {
|
||||
printk(KERN_ERR "UBI error: too many parameters, max. is %d\n",
|
||||
UBI_MAX_DEVICES);
|
||||
ubi_err("UBI error: too many parameters, max. is %d\n",
|
||||
UBI_MAX_DEVICES);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
len = strnlen(val, MTD_PARAM_LEN_MAX);
|
||||
if (len == MTD_PARAM_LEN_MAX) {
|
||||
printk(KERN_ERR "UBI error: parameter \"%s\" is too long, "
|
||||
"max. is %d\n", val, MTD_PARAM_LEN_MAX);
|
||||
ubi_err("UBI error: parameter \"%s\" is too long, max. is %d\n",
|
||||
val, MTD_PARAM_LEN_MAX);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
printk(KERN_WARNING "UBI warning: empty 'mtd=' parameter - "
|
||||
"ignored\n");
|
||||
pr_warn("UBI warning: empty 'mtd=' parameter - ignored\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1321,12 +1361,11 @@ static int __init ubi_mtd_param_parse(const char *val, struct kernel_param *kp)
|
||||
if (buf[len - 1] == '\n')
|
||||
buf[len - 1] = '\0';
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
for (i = 0; i < MTD_PARAM_MAX_COUNT; i++)
|
||||
tokens[i] = strsep(&pbuf, ",");
|
||||
|
||||
if (pbuf) {
|
||||
printk(KERN_ERR "UBI error: too many arguments at \"%s\"\n",
|
||||
val);
|
||||
ubi_err("UBI error: too many arguments at \"%s\"\n", val);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -1339,23 +1378,32 @@ static int __init ubi_mtd_param_parse(const char *val, struct kernel_param *kp)
|
||||
if (p->vid_hdr_offs < 0)
|
||||
return p->vid_hdr_offs;
|
||||
|
||||
if (tokens[2]) {
|
||||
int err = kstrtoint(tokens[2], 10, &p->max_beb_per1024);
|
||||
|
||||
if (err) {
|
||||
ubi_err("UBI error: bad value for max_beb_per1024 parameter: %s",
|
||||
tokens[2]);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
mtd_devs += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
module_param_call(mtd, ubi_mtd_param_parse, NULL, NULL, 000);
|
||||
MODULE_PARM_DESC(mtd, "MTD devices to attach. Parameter format: "
|
||||
"mtd=<name|num|path>[,<vid_hdr_offs>].\n"
|
||||
MODULE_PARM_DESC(mtd, "MTD devices to attach. Parameter format: mtd=<name|num|path>[,<vid_hdr_offs>[,max_beb_per1024]].\n"
|
||||
"Multiple \"mtd\" parameters may be specified.\n"
|
||||
"MTD devices may be specified by their number, name, or "
|
||||
"path to the MTD character device node.\n"
|
||||
"Optional \"vid_hdr_offs\" parameter specifies UBI VID "
|
||||
"header position to be used by UBI.\n"
|
||||
"Example 1: mtd=/dev/mtd0 - attach MTD device "
|
||||
"/dev/mtd0.\n"
|
||||
"Example 2: mtd=content,1984 mtd=4 - attach MTD device "
|
||||
"with name \"content\" using VID header offset 1984, and "
|
||||
"MTD device number 4 with default VID header offset.");
|
||||
"MTD devices may be specified by their number, name, or path to the MTD character device node.\n"
|
||||
"Optional \"vid_hdr_offs\" parameter specifies UBI VID header position to be used by UBI. (default value if 0)\n"
|
||||
"Optional \"max_beb_per1024\" parameter specifies the maximum expected bad eraseblock per 1024 eraseblocks. (default value ("
|
||||
__stringify(CONFIG_MTD_UBI_BEB_LIMIT) ") if 0)\n"
|
||||
"\n"
|
||||
"Example 1: mtd=/dev/mtd0 - attach MTD device /dev/mtd0.\n"
|
||||
"Example 2: mtd=content,1984 mtd=4 - attach MTD device with name \"content\" using VID header offset 1984, and MTD device number 4 with default VID header offset.\n"
|
||||
"Example 3: mtd=/dev/mtd1,0,25 - attach MTD device /dev/mtd1 using default VID header offset and reserve 25*nand_size_in_blocks/1024 erase blocks for bad block handling.\n"
|
||||
"\t(e.g. if the NAND *chipset* has 4096 PEB, 100 will be reserved for this UBI device).");
|
||||
|
||||
MODULE_VERSION(__stringify(UBI_VERSION));
|
||||
MODULE_DESCRIPTION("UBI - Unsorted Block Images");
|
||||
|
@ -140,9 +140,9 @@ static int vol_cdev_release(struct inode *inode, struct file *file)
|
||||
vol->updating = 0;
|
||||
vfree(vol->upd_buf);
|
||||
} else if (vol->changing_leb) {
|
||||
dbg_gen("only %lld of %lld bytes received for atomic LEB change"
|
||||
" for volume %d:%d, cancel", vol->upd_received,
|
||||
vol->upd_bytes, vol->ubi->ubi_num, vol->vol_id);
|
||||
dbg_gen("only %lld of %lld bytes received for atomic LEB change for volume %d:%d, cancel",
|
||||
vol->upd_received, vol->upd_bytes, vol->ubi->ubi_num,
|
||||
vol->vol_id);
|
||||
vol->changing_leb = 0;
|
||||
vfree(vol->upd_buf);
|
||||
}
|
||||
@ -189,7 +189,8 @@ static loff_t vol_cdev_llseek(struct file *file, loff_t offset, int origin)
|
||||
return new_offset;
|
||||
}
|
||||
|
||||
static int vol_cdev_fsync(struct file *file, loff_t start, loff_t end, int datasync)
|
||||
static int vol_cdev_fsync(struct file *file, loff_t start, loff_t end,
|
||||
int datasync)
|
||||
{
|
||||
struct ubi_volume_desc *desc = file->private_data;
|
||||
struct ubi_device *ubi = desc->vol->ubi;
|
||||
@ -753,7 +754,7 @@ static int rename_volumes(struct ubi_device *ubi,
|
||||
re->new_name_len = name_len;
|
||||
memcpy(re->new_name, name, name_len);
|
||||
list_add_tail(&re->list, &rename_list);
|
||||
dbg_msg("will rename volume %d from \"%s\" to \"%s\"",
|
||||
dbg_gen("will rename volume %d from \"%s\" to \"%s\"",
|
||||
vol_id, re->desc->vol->name, name);
|
||||
}
|
||||
|
||||
@ -811,7 +812,7 @@ static int rename_volumes(struct ubi_device *ubi,
|
||||
re1->remove = 1;
|
||||
re1->desc = desc;
|
||||
list_add(&re1->list, &rename_list);
|
||||
dbg_msg("will remove volume %d, name \"%s\"",
|
||||
dbg_gen("will remove volume %d, name \"%s\"",
|
||||
re1->desc->vol->vol_id, re1->desc->vol->name);
|
||||
}
|
||||
|
||||
@ -942,7 +943,7 @@ static long ubi_cdev_ioctl(struct file *file, unsigned int cmd,
|
||||
{
|
||||
struct ubi_rnvol_req *req;
|
||||
|
||||
dbg_msg("re-name volumes");
|
||||
dbg_gen("re-name volumes");
|
||||
req = kmalloc(sizeof(struct ubi_rnvol_req), GFP_KERNEL);
|
||||
if (!req) {
|
||||
err = -ENOMEM;
|
||||
@ -1010,7 +1011,8 @@ static long ctrl_cdev_ioctl(struct file *file, unsigned int cmd,
|
||||
* 'ubi_attach_mtd_dev()'.
|
||||
*/
|
||||
mutex_lock(&ubi_devices_mutex);
|
||||
err = ubi_attach_mtd_dev(mtd, req.ubi_num, req.vid_hdr_offset);
|
||||
err = ubi_attach_mtd_dev(mtd, req.ubi_num, req.vid_hdr_offset,
|
||||
req.max_beb_per1024);
|
||||
mutex_unlock(&ubi_devices_mutex);
|
||||
if (err < 0)
|
||||
put_mtd_device(mtd);
|
||||
|
@ -43,8 +43,8 @@ void ubi_dump_flash(struct ubi_device *ubi, int pnum, int offset, int len)
|
||||
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);
|
||||
ubi_err("error %d while reading %d bytes from PEB %d:%d, read %zd bytes",
|
||||
err, len, pnum, offset, read);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -62,21 +62,15 @@ out:
|
||||
*/
|
||||
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",
|
||||
be32_to_cpu(ec_hdr->magic));
|
||||
printk(KERN_DEBUG "\tversion %d\n", (int)ec_hdr->version);
|
||||
printk(KERN_DEBUG "\tec %llu\n",
|
||||
(long long)be64_to_cpu(ec_hdr->ec));
|
||||
printk(KERN_DEBUG "\tvid_hdr_offset %d\n",
|
||||
be32_to_cpu(ec_hdr->vid_hdr_offset));
|
||||
printk(KERN_DEBUG "\tdata_offset %d\n",
|
||||
be32_to_cpu(ec_hdr->data_offset));
|
||||
printk(KERN_DEBUG "\timage_seq %d\n",
|
||||
be32_to_cpu(ec_hdr->image_seq));
|
||||
printk(KERN_DEBUG "\thdr_crc %#08x\n",
|
||||
be32_to_cpu(ec_hdr->hdr_crc));
|
||||
printk(KERN_DEBUG "erase counter header hexdump:\n");
|
||||
pr_err("Erase counter header dump:\n");
|
||||
pr_err("\tmagic %#08x\n", be32_to_cpu(ec_hdr->magic));
|
||||
pr_err("\tversion %d\n", (int)ec_hdr->version);
|
||||
pr_err("\tec %llu\n", (long long)be64_to_cpu(ec_hdr->ec));
|
||||
pr_err("\tvid_hdr_offset %d\n", be32_to_cpu(ec_hdr->vid_hdr_offset));
|
||||
pr_err("\tdata_offset %d\n", be32_to_cpu(ec_hdr->data_offset));
|
||||
pr_err("\timage_seq %d\n", be32_to_cpu(ec_hdr->image_seq));
|
||||
pr_err("\thdr_crc %#08x\n", be32_to_cpu(ec_hdr->hdr_crc));
|
||||
pr_err("erase counter header hexdump:\n");
|
||||
print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
|
||||
ec_hdr, UBI_EC_HDR_SIZE, 1);
|
||||
}
|
||||
@ -87,21 +81,21 @@ void ubi_dump_ec_hdr(const struct ubi_ec_hdr *ec_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));
|
||||
printk(KERN_DEBUG "\tversion %d\n", (int)vid_hdr->version);
|
||||
printk(KERN_DEBUG "\tvol_type %d\n", (int)vid_hdr->vol_type);
|
||||
printk(KERN_DEBUG "\tcopy_flag %d\n", (int)vid_hdr->copy_flag);
|
||||
printk(KERN_DEBUG "\tcompat %d\n", (int)vid_hdr->compat);
|
||||
printk(KERN_DEBUG "\tvol_id %d\n", be32_to_cpu(vid_hdr->vol_id));
|
||||
printk(KERN_DEBUG "\tlnum %d\n", be32_to_cpu(vid_hdr->lnum));
|
||||
printk(KERN_DEBUG "\tdata_size %d\n", be32_to_cpu(vid_hdr->data_size));
|
||||
printk(KERN_DEBUG "\tused_ebs %d\n", be32_to_cpu(vid_hdr->used_ebs));
|
||||
printk(KERN_DEBUG "\tdata_pad %d\n", be32_to_cpu(vid_hdr->data_pad));
|
||||
printk(KERN_DEBUG "\tsqnum %llu\n",
|
||||
pr_err("Volume identifier header dump:\n");
|
||||
pr_err("\tmagic %08x\n", be32_to_cpu(vid_hdr->magic));
|
||||
pr_err("\tversion %d\n", (int)vid_hdr->version);
|
||||
pr_err("\tvol_type %d\n", (int)vid_hdr->vol_type);
|
||||
pr_err("\tcopy_flag %d\n", (int)vid_hdr->copy_flag);
|
||||
pr_err("\tcompat %d\n", (int)vid_hdr->compat);
|
||||
pr_err("\tvol_id %d\n", be32_to_cpu(vid_hdr->vol_id));
|
||||
pr_err("\tlnum %d\n", be32_to_cpu(vid_hdr->lnum));
|
||||
pr_err("\tdata_size %d\n", be32_to_cpu(vid_hdr->data_size));
|
||||
pr_err("\tused_ebs %d\n", be32_to_cpu(vid_hdr->used_ebs));
|
||||
pr_err("\tdata_pad %d\n", be32_to_cpu(vid_hdr->data_pad));
|
||||
pr_err("\tsqnum %llu\n",
|
||||
(unsigned long long)be64_to_cpu(vid_hdr->sqnum));
|
||||
printk(KERN_DEBUG "\thdr_crc %08x\n", be32_to_cpu(vid_hdr->hdr_crc));
|
||||
printk(KERN_DEBUG "Volume identifier header hexdump:\n");
|
||||
pr_err("\thdr_crc %08x\n", be32_to_cpu(vid_hdr->hdr_crc));
|
||||
pr_err("Volume identifier header hexdump:\n");
|
||||
print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
|
||||
vid_hdr, UBI_VID_HDR_SIZE, 1);
|
||||
}
|
||||
@ -112,25 +106,25 @@ void ubi_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr)
|
||||
*/
|
||||
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);
|
||||
printk(KERN_DEBUG "\treserved_pebs %d\n", vol->reserved_pebs);
|
||||
printk(KERN_DEBUG "\talignment %d\n", vol->alignment);
|
||||
printk(KERN_DEBUG "\tdata_pad %d\n", vol->data_pad);
|
||||
printk(KERN_DEBUG "\tvol_type %d\n", vol->vol_type);
|
||||
printk(KERN_DEBUG "\tname_len %d\n", vol->name_len);
|
||||
printk(KERN_DEBUG "\tusable_leb_size %d\n", vol->usable_leb_size);
|
||||
printk(KERN_DEBUG "\tused_ebs %d\n", vol->used_ebs);
|
||||
printk(KERN_DEBUG "\tused_bytes %lld\n", vol->used_bytes);
|
||||
printk(KERN_DEBUG "\tlast_eb_bytes %d\n", vol->last_eb_bytes);
|
||||
printk(KERN_DEBUG "\tcorrupted %d\n", vol->corrupted);
|
||||
printk(KERN_DEBUG "\tupd_marker %d\n", vol->upd_marker);
|
||||
pr_err("Volume information dump:\n");
|
||||
pr_err("\tvol_id %d\n", vol->vol_id);
|
||||
pr_err("\treserved_pebs %d\n", vol->reserved_pebs);
|
||||
pr_err("\talignment %d\n", vol->alignment);
|
||||
pr_err("\tdata_pad %d\n", vol->data_pad);
|
||||
pr_err("\tvol_type %d\n", vol->vol_type);
|
||||
pr_err("\tname_len %d\n", vol->name_len);
|
||||
pr_err("\tusable_leb_size %d\n", vol->usable_leb_size);
|
||||
pr_err("\tused_ebs %d\n", vol->used_ebs);
|
||||
pr_err("\tused_bytes %lld\n", vol->used_bytes);
|
||||
pr_err("\tlast_eb_bytes %d\n", vol->last_eb_bytes);
|
||||
pr_err("\tcorrupted %d\n", vol->corrupted);
|
||||
pr_err("\tupd_marker %d\n", vol->upd_marker);
|
||||
|
||||
if (vol->name_len <= UBI_VOL_NAME_MAX &&
|
||||
strnlen(vol->name, vol->name_len + 1) == vol->name_len) {
|
||||
printk(KERN_DEBUG "\tname %s\n", vol->name);
|
||||
pr_err("\tname %s\n", vol->name);
|
||||
} else {
|
||||
printk(KERN_DEBUG "\t1st 5 characters of name: %c%c%c%c%c\n",
|
||||
pr_err("\t1st 5 characters of name: %c%c%c%c%c\n",
|
||||
vol->name[0], vol->name[1], vol->name[2],
|
||||
vol->name[3], vol->name[4]);
|
||||
}
|
||||
@ -145,29 +139,28 @@ void ubi_dump_vtbl_record(const struct ubi_vtbl_record *r, int idx)
|
||||
{
|
||||
int name_len = be16_to_cpu(r->name_len);
|
||||
|
||||
printk(KERN_DEBUG "Volume table record %d dump:\n", idx);
|
||||
printk(KERN_DEBUG "\treserved_pebs %d\n",
|
||||
be32_to_cpu(r->reserved_pebs));
|
||||
printk(KERN_DEBUG "\talignment %d\n", be32_to_cpu(r->alignment));
|
||||
printk(KERN_DEBUG "\tdata_pad %d\n", be32_to_cpu(r->data_pad));
|
||||
printk(KERN_DEBUG "\tvol_type %d\n", (int)r->vol_type);
|
||||
printk(KERN_DEBUG "\tupd_marker %d\n", (int)r->upd_marker);
|
||||
printk(KERN_DEBUG "\tname_len %d\n", name_len);
|
||||
pr_err("Volume table record %d dump:\n", idx);
|
||||
pr_err("\treserved_pebs %d\n", be32_to_cpu(r->reserved_pebs));
|
||||
pr_err("\talignment %d\n", be32_to_cpu(r->alignment));
|
||||
pr_err("\tdata_pad %d\n", be32_to_cpu(r->data_pad));
|
||||
pr_err("\tvol_type %d\n", (int)r->vol_type);
|
||||
pr_err("\tupd_marker %d\n", (int)r->upd_marker);
|
||||
pr_err("\tname_len %d\n", name_len);
|
||||
|
||||
if (r->name[0] == '\0') {
|
||||
printk(KERN_DEBUG "\tname NULL\n");
|
||||
pr_err("\tname NULL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (name_len <= UBI_VOL_NAME_MAX &&
|
||||
strnlen(&r->name[0], name_len + 1) == name_len) {
|
||||
printk(KERN_DEBUG "\tname %s\n", &r->name[0]);
|
||||
pr_err("\tname %s\n", &r->name[0]);
|
||||
} else {
|
||||
printk(KERN_DEBUG "\t1st 5 characters of name: %c%c%c%c%c\n",
|
||||
pr_err("\t1st 5 characters of name: %c%c%c%c%c\n",
|
||||
r->name[0], r->name[1], r->name[2], r->name[3],
|
||||
r->name[4]);
|
||||
}
|
||||
printk(KERN_DEBUG "\tcrc %#08x\n", be32_to_cpu(r->crc));
|
||||
pr_err("\tcrc %#08x\n", be32_to_cpu(r->crc));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -176,15 +169,15 @@ void ubi_dump_vtbl_record(const struct ubi_vtbl_record *r, int idx)
|
||||
*/
|
||||
void ubi_dump_av(const struct ubi_ainf_volume *av)
|
||||
{
|
||||
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);
|
||||
pr_err("Volume attaching information dump:\n");
|
||||
pr_err("\tvol_id %d\n", av->vol_id);
|
||||
pr_err("\thighest_lnum %d\n", av->highest_lnum);
|
||||
pr_err("\tleb_count %d\n", av->leb_count);
|
||||
pr_err("\tcompat %d\n", av->compat);
|
||||
pr_err("\tvol_type %d\n", av->vol_type);
|
||||
pr_err("\tused_ebs %d\n", av->used_ebs);
|
||||
pr_err("\tlast_data_size %d\n", av->last_data_size);
|
||||
pr_err("\tdata_pad %d\n", av->data_pad);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -194,13 +187,13 @@ void ubi_dump_av(const struct ubi_ainf_volume *av)
|
||||
*/
|
||||
void ubi_dump_aeb(const struct ubi_ainf_peb *aeb, int type)
|
||||
{
|
||||
printk(KERN_DEBUG "eraseblock attaching information dump:\n");
|
||||
printk(KERN_DEBUG "\tec %d\n", aeb->ec);
|
||||
printk(KERN_DEBUG "\tpnum %d\n", aeb->pnum);
|
||||
pr_err("eraseblock attaching information dump:\n");
|
||||
pr_err("\tec %d\n", aeb->ec);
|
||||
pr_err("\tpnum %d\n", aeb->pnum);
|
||||
if (type == 0) {
|
||||
printk(KERN_DEBUG "\tlnum %d\n", aeb->lnum);
|
||||
printk(KERN_DEBUG "\tscrub %d\n", aeb->scrub);
|
||||
printk(KERN_DEBUG "\tsqnum %llu\n", aeb->sqnum);
|
||||
pr_err("\tlnum %d\n", aeb->lnum);
|
||||
pr_err("\tscrub %d\n", aeb->scrub);
|
||||
pr_err("\tsqnum %llu\n", aeb->sqnum);
|
||||
}
|
||||
}
|
||||
|
||||
@ -212,16 +205,16 @@ void ubi_dump_mkvol_req(const struct ubi_mkvol_req *req)
|
||||
{
|
||||
char nm[17];
|
||||
|
||||
printk(KERN_DEBUG "Volume creation request dump:\n");
|
||||
printk(KERN_DEBUG "\tvol_id %d\n", req->vol_id);
|
||||
printk(KERN_DEBUG "\talignment %d\n", req->alignment);
|
||||
printk(KERN_DEBUG "\tbytes %lld\n", (long long)req->bytes);
|
||||
printk(KERN_DEBUG "\tvol_type %d\n", req->vol_type);
|
||||
printk(KERN_DEBUG "\tname_len %d\n", req->name_len);
|
||||
pr_err("Volume creation request dump:\n");
|
||||
pr_err("\tvol_id %d\n", req->vol_id);
|
||||
pr_err("\talignment %d\n", req->alignment);
|
||||
pr_err("\tbytes %lld\n", (long long)req->bytes);
|
||||
pr_err("\tvol_type %d\n", req->vol_type);
|
||||
pr_err("\tname_len %d\n", req->name_len);
|
||||
|
||||
memcpy(nm, req->name, 16);
|
||||
nm[16] = 0;
|
||||
printk(KERN_DEBUG "\t1st 16 characters of name: %s\n", nm);
|
||||
pr_err("\t1st 16 characters of name: %s\n", nm);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -29,22 +29,18 @@ void ubi_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr);
|
||||
|
||||
#define ubi_assert(expr) do { \
|
||||
if (unlikely(!(expr))) { \
|
||||
printk(KERN_CRIT "UBI assert failed in %s at %u (pid %d)\n", \
|
||||
pr_crit("UBI assert failed in %s at %u (pid %d)\n", \
|
||||
__func__, __LINE__, current->pid); \
|
||||
dump_stack(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ubi_dbg_print_hex_dump(l, ps, pt, r, g, b, len, a) \
|
||||
#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)
|
||||
|
||||
#define ubi_dbg_msg(type, fmt, ...) \
|
||||
pr_debug("UBI DBG " type ": " fmt "\n", ##__VA_ARGS__)
|
||||
|
||||
/* Just a debugging messages not related to any specific UBI subsystem */
|
||||
#define dbg_msg(fmt, ...) \
|
||||
printk(KERN_DEBUG "UBI DBG (pid %d): %s: " fmt "\n", \
|
||||
current->pid, __func__, ##__VA_ARGS__)
|
||||
pr_debug("UBI DBG " type " (pid %d): " fmt "\n", current->pid, \
|
||||
##__VA_ARGS__)
|
||||
|
||||
/* General debugging messages */
|
||||
#define dbg_gen(fmt, ...) ubi_dbg_msg("gen", fmt, ##__VA_ARGS__)
|
||||
|
@ -420,9 +420,8 @@ retry:
|
||||
*/
|
||||
if (err == UBI_IO_BAD_HDR_EBADMSG ||
|
||||
err == UBI_IO_BAD_HDR) {
|
||||
ubi_warn("corrupted VID header at PEB "
|
||||
"%d, LEB %d:%d", pnum, vol_id,
|
||||
lnum);
|
||||
ubi_warn("corrupted VID header at PEB %d, LEB %d:%d",
|
||||
pnum, vol_id, lnum);
|
||||
err = -EBADMSG;
|
||||
} else
|
||||
ubi_ro_mode(ubi);
|
||||
@ -660,9 +659,8 @@ retry:
|
||||
if (len) {
|
||||
err = ubi_io_write_data(ubi, buf, pnum, offset, len);
|
||||
if (err) {
|
||||
ubi_warn("failed to write %d bytes at offset %d of "
|
||||
"LEB %d:%d, PEB %d", len, offset, vol_id,
|
||||
lnum, pnum);
|
||||
ubi_warn("failed to write %d bytes at offset %d of LEB %d:%d, PEB %d",
|
||||
len, offset, vol_id, lnum, pnum);
|
||||
goto write_error;
|
||||
}
|
||||
}
|
||||
@ -1040,9 +1038,8 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
|
||||
* cancel it.
|
||||
*/
|
||||
if (vol->eba_tbl[lnum] != from) {
|
||||
dbg_wl("LEB %d:%d is no longer mapped to PEB %d, mapped to "
|
||||
"PEB %d, cancel", vol_id, lnum, from,
|
||||
vol->eba_tbl[lnum]);
|
||||
dbg_wl("LEB %d:%d is no longer mapped to PEB %d, mapped to PEB %d, cancel",
|
||||
vol_id, lnum, from, vol->eba_tbl[lnum]);
|
||||
err = MOVE_CANCEL_RACE;
|
||||
goto out_unlock_leb;
|
||||
}
|
||||
@ -1107,8 +1104,8 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
|
||||
err = ubi_io_read_vid_hdr(ubi, to, vid_hdr, 1);
|
||||
if (err) {
|
||||
if (err != UBI_IO_BITFLIPS) {
|
||||
ubi_warn("error %d while reading VID header back from "
|
||||
"PEB %d", err, to);
|
||||
ubi_warn("error %d while reading VID header back from PEB %d",
|
||||
err, to);
|
||||
if (is_error_sane(err))
|
||||
err = MOVE_TARGET_RD_ERR;
|
||||
} else
|
||||
@ -1134,8 +1131,8 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
|
||||
err = ubi_io_read_data(ubi, ubi->peb_buf, to, 0, aldata_size);
|
||||
if (err) {
|
||||
if (err != UBI_IO_BITFLIPS) {
|
||||
ubi_warn("error %d while reading data back "
|
||||
"from PEB %d", err, to);
|
||||
ubi_warn("error %d while reading data back from PEB %d",
|
||||
err, to);
|
||||
if (is_error_sane(err))
|
||||
err = MOVE_TARGET_RD_ERR;
|
||||
} else
|
||||
@ -1146,8 +1143,8 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
|
||||
cond_resched();
|
||||
|
||||
if (crc != crc32(UBI_CRC32_INIT, ubi->peb_buf, data_size)) {
|
||||
ubi_warn("read data back from PEB %d and it is "
|
||||
"different", to);
|
||||
ubi_warn("read data back from PEB %d and it is different",
|
||||
to);
|
||||
err = -EINVAL;
|
||||
goto out_unlock_buf;
|
||||
}
|
||||
@ -1197,11 +1194,11 @@ static void print_rsvd_warning(struct ubi_device *ubi,
|
||||
return;
|
||||
}
|
||||
|
||||
ubi_warn("cannot reserve enough PEBs for bad PEB handling, reserved %d,"
|
||||
" need %d", ubi->beb_rsvd_pebs, ubi->beb_rsvd_level);
|
||||
ubi_warn("cannot reserve enough PEBs for bad PEB handling, reserved %d, need %d",
|
||||
ubi->beb_rsvd_pebs, ubi->beb_rsvd_level);
|
||||
if (ubi->corr_peb_count)
|
||||
ubi_warn("%d PEBs are corrupted and not used",
|
||||
ubi->corr_peb_count);
|
||||
ubi->corr_peb_count);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -41,7 +41,7 @@
|
||||
#include "ubi-media.h"
|
||||
|
||||
#define err_msg(fmt, ...) \
|
||||
printk(KERN_DEBUG "gluebi (pid %d): %s: " fmt "\n", \
|
||||
pr_err("gluebi (pid %d): %s: " fmt "\n", \
|
||||
current->pid, __func__, ##__VA_ARGS__)
|
||||
|
||||
/**
|
||||
@ -341,9 +341,8 @@ static int gluebi_create(struct ubi_device_info *di,
|
||||
mutex_lock(&devices_mutex);
|
||||
g = find_gluebi_nolock(vi->ubi_num, vi->vol_id);
|
||||
if (g)
|
||||
err_msg("gluebi MTD device %d form UBI device %d volume %d "
|
||||
"already exists", g->mtd.index, vi->ubi_num,
|
||||
vi->vol_id);
|
||||
err_msg("gluebi MTD device %d form UBI device %d volume %d already exists",
|
||||
g->mtd.index, vi->ubi_num, vi->vol_id);
|
||||
mutex_unlock(&devices_mutex);
|
||||
|
||||
if (mtd_device_register(mtd, NULL, 0)) {
|
||||
@ -376,8 +375,8 @@ static int gluebi_remove(struct ubi_volume_info *vi)
|
||||
mutex_lock(&devices_mutex);
|
||||
gluebi = find_gluebi_nolock(vi->ubi_num, vi->vol_id);
|
||||
if (!gluebi) {
|
||||
err_msg("got remove notification for unknown UBI device %d "
|
||||
"volume %d", vi->ubi_num, vi->vol_id);
|
||||
err_msg("got remove notification for unknown UBI device %d volume %d",
|
||||
vi->ubi_num, vi->vol_id);
|
||||
err = -ENOENT;
|
||||
} else if (gluebi->refcnt)
|
||||
err = -EBUSY;
|
||||
@ -390,9 +389,8 @@ static int gluebi_remove(struct ubi_volume_info *vi)
|
||||
mtd = &gluebi->mtd;
|
||||
err = mtd_device_unregister(mtd);
|
||||
if (err) {
|
||||
err_msg("cannot remove fake MTD device %d, UBI device %d, "
|
||||
"volume %d, error %d", mtd->index, gluebi->ubi_num,
|
||||
gluebi->vol_id, err);
|
||||
err_msg("cannot remove fake MTD device %d, UBI device %d, volume %d, error %d",
|
||||
mtd->index, gluebi->ubi_num, gluebi->vol_id, err);
|
||||
mutex_lock(&devices_mutex);
|
||||
list_add_tail(&gluebi->list, &gluebi_devices);
|
||||
mutex_unlock(&devices_mutex);
|
||||
@ -422,8 +420,8 @@ static int gluebi_updated(struct ubi_volume_info *vi)
|
||||
gluebi = find_gluebi_nolock(vi->ubi_num, vi->vol_id);
|
||||
if (!gluebi) {
|
||||
mutex_unlock(&devices_mutex);
|
||||
err_msg("got update notification for unknown UBI device %d "
|
||||
"volume %d", vi->ubi_num, vi->vol_id);
|
||||
err_msg("got update notification for unknown UBI device %d volume %d",
|
||||
vi->ubi_num, vi->vol_id);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
@ -449,8 +447,8 @@ static int gluebi_resized(struct ubi_volume_info *vi)
|
||||
gluebi = find_gluebi_nolock(vi->ubi_num, vi->vol_id);
|
||||
if (!gluebi) {
|
||||
mutex_unlock(&devices_mutex);
|
||||
err_msg("got update notification for unknown UBI device %d "
|
||||
"volume %d", vi->ubi_num, vi->vol_id);
|
||||
err_msg("got update notification for unknown UBI device %d volume %d",
|
||||
vi->ubi_num, vi->vol_id);
|
||||
return -ENOENT;
|
||||
}
|
||||
gluebi->mtd.size = vi->used_bytes;
|
||||
@ -507,9 +505,9 @@ static void __exit ubi_gluebi_exit(void)
|
||||
|
||||
err = mtd_device_unregister(mtd);
|
||||
if (err)
|
||||
err_msg("error %d while removing gluebi MTD device %d, "
|
||||
"UBI device %d, volume %d - ignoring", err,
|
||||
mtd->index, gluebi->ubi_num, gluebi->vol_id);
|
||||
err_msg("error %d while removing gluebi MTD device %d, UBI device %d, volume %d - ignoring",
|
||||
err, mtd->index, gluebi->ubi_num,
|
||||
gluebi->vol_id);
|
||||
kfree(mtd->name);
|
||||
kfree(gluebi);
|
||||
}
|
||||
|
@ -177,21 +177,20 @@ retry:
|
||||
* enabled. A corresponding message will be printed
|
||||
* later, when it is has been scrubbed.
|
||||
*/
|
||||
dbg_msg("fixable bit-flip detected at PEB %d", pnum);
|
||||
ubi_msg("fixable bit-flip detected at PEB %d", pnum);
|
||||
ubi_assert(len == read);
|
||||
return UBI_IO_BITFLIPS;
|
||||
}
|
||||
|
||||
if (retries++ < UBI_IO_RETRIES) {
|
||||
ubi_warn("error %d%s while reading %d bytes from PEB "
|
||||
"%d:%d, read only %zd bytes, retry",
|
||||
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_err("error %d%s while reading %d bytes from PEB %d:%d, read %zd bytes",
|
||||
err, errstr, len, pnum, offset, read);
|
||||
dump_stack();
|
||||
|
||||
/*
|
||||
@ -274,8 +273,8 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset,
|
||||
}
|
||||
|
||||
if (ubi_dbg_is_write_failure(ubi)) {
|
||||
ubi_err("cannot write %d bytes to PEB %d:%d "
|
||||
"(emulated)", len, pnum, offset);
|
||||
ubi_err("cannot write %d bytes to PEB %d:%d (emulated)",
|
||||
len, pnum, offset);
|
||||
dump_stack();
|
||||
return -EIO;
|
||||
}
|
||||
@ -283,8 +282,8 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset,
|
||||
addr = (loff_t)pnum * ubi->peb_size + offset;
|
||||
err = mtd_write(ubi->mtd, addr, len, &written, buf);
|
||||
if (err) {
|
||||
ubi_err("error %d while writing %d bytes to PEB %d:%d, written "
|
||||
"%zd bytes", err, len, pnum, offset, written);
|
||||
ubi_err("error %d while writing %d bytes to PEB %d:%d, written %zd bytes",
|
||||
err, len, pnum, offset, written);
|
||||
dump_stack();
|
||||
ubi_dump_flash(ubi, pnum, offset, len);
|
||||
} else
|
||||
@ -685,8 +684,7 @@ static int validate_ec_hdr(const struct ubi_device *ubi,
|
||||
leb_start = be32_to_cpu(ec_hdr->data_offset);
|
||||
|
||||
if (ec_hdr->version != UBI_VERSION) {
|
||||
ubi_err("node with incompatible UBI version found: "
|
||||
"this UBI version is %d, image version is %d",
|
||||
ubi_err("node with incompatible UBI version found: this UBI version is %d, image version is %d",
|
||||
UBI_VERSION, (int)ec_hdr->version);
|
||||
goto bad;
|
||||
}
|
||||
@ -777,10 +775,10 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
|
||||
if (ubi_check_pattern(ec_hdr, 0xFF, UBI_EC_HDR_SIZE)) {
|
||||
/* The physical eraseblock is supposedly empty */
|
||||
if (verbose)
|
||||
ubi_warn("no EC header found at PEB %d, "
|
||||
"only 0xFF bytes", pnum);
|
||||
dbg_bld("no EC header found at PEB %d, "
|
||||
"only 0xFF bytes", pnum);
|
||||
ubi_warn("no EC header found at PEB %d, only 0xFF bytes",
|
||||
pnum);
|
||||
dbg_bld("no EC header found at PEB %d, only 0xFF bytes",
|
||||
pnum);
|
||||
if (!read_err)
|
||||
return UBI_IO_FF;
|
||||
else
|
||||
@ -792,12 +790,12 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
|
||||
* 0xFF bytes. Report that the header is corrupted.
|
||||
*/
|
||||
if (verbose) {
|
||||
ubi_warn("bad magic number at PEB %d: %08x instead of "
|
||||
"%08x", pnum, magic, UBI_EC_HDR_MAGIC);
|
||||
ubi_warn("bad magic number at PEB %d: %08x instead of %08x",
|
||||
pnum, magic, UBI_EC_HDR_MAGIC);
|
||||
ubi_dump_ec_hdr(ec_hdr);
|
||||
}
|
||||
dbg_bld("bad magic number at PEB %d: %08x instead of "
|
||||
"%08x", pnum, magic, UBI_EC_HDR_MAGIC);
|
||||
dbg_bld("bad magic number at PEB %d: %08x instead of %08x",
|
||||
pnum, magic, UBI_EC_HDR_MAGIC);
|
||||
return UBI_IO_BAD_HDR;
|
||||
}
|
||||
|
||||
@ -806,12 +804,12 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
|
||||
|
||||
if (hdr_crc != crc) {
|
||||
if (verbose) {
|
||||
ubi_warn("bad EC header CRC at PEB %d, calculated "
|
||||
"%#08x, read %#08x", pnum, crc, hdr_crc);
|
||||
ubi_warn("bad EC header CRC at PEB %d, calculated %#08x, read %#08x",
|
||||
pnum, crc, hdr_crc);
|
||||
ubi_dump_ec_hdr(ec_hdr);
|
||||
}
|
||||
dbg_bld("bad EC header CRC at PEB %d, calculated "
|
||||
"%#08x, read %#08x", pnum, crc, hdr_crc);
|
||||
dbg_bld("bad EC header CRC at PEB %d, calculated %#08x, read %#08x",
|
||||
pnum, crc, hdr_crc);
|
||||
|
||||
if (!read_err)
|
||||
return UBI_IO_BAD_HDR;
|
||||
@ -1032,10 +1030,10 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
|
||||
|
||||
if (ubi_check_pattern(vid_hdr, 0xFF, UBI_VID_HDR_SIZE)) {
|
||||
if (verbose)
|
||||
ubi_warn("no VID header found at PEB %d, "
|
||||
"only 0xFF bytes", pnum);
|
||||
dbg_bld("no VID header found at PEB %d, "
|
||||
"only 0xFF bytes", pnum);
|
||||
ubi_warn("no VID header found at PEB %d, only 0xFF bytes",
|
||||
pnum);
|
||||
dbg_bld("no VID header found at PEB %d, only 0xFF bytes",
|
||||
pnum);
|
||||
if (!read_err)
|
||||
return UBI_IO_FF;
|
||||
else
|
||||
@ -1043,12 +1041,12 @@ 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_warn("bad magic number at PEB %d: %08x instead of %08x",
|
||||
pnum, magic, UBI_VID_HDR_MAGIC);
|
||||
ubi_dump_vid_hdr(vid_hdr);
|
||||
}
|
||||
dbg_bld("bad magic number at PEB %d: %08x instead of "
|
||||
"%08x", pnum, magic, UBI_VID_HDR_MAGIC);
|
||||
dbg_bld("bad magic number at PEB %d: %08x instead of %08x",
|
||||
pnum, magic, UBI_VID_HDR_MAGIC);
|
||||
return UBI_IO_BAD_HDR;
|
||||
}
|
||||
|
||||
@ -1057,12 +1055,12 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
|
||||
|
||||
if (hdr_crc != crc) {
|
||||
if (verbose) {
|
||||
ubi_warn("bad CRC at PEB %d, calculated %#08x, "
|
||||
"read %#08x", pnum, crc, hdr_crc);
|
||||
ubi_warn("bad CRC at PEB %d, calculated %#08x, read %#08x",
|
||||
pnum, crc, hdr_crc);
|
||||
ubi_dump_vid_hdr(vid_hdr);
|
||||
}
|
||||
dbg_bld("bad CRC at PEB %d, calculated %#08x, "
|
||||
"read %#08x", pnum, crc, hdr_crc);
|
||||
dbg_bld("bad CRC at PEB %d, calculated %#08x, read %#08x",
|
||||
pnum, crc, hdr_crc);
|
||||
if (!read_err)
|
||||
return UBI_IO_BAD_HDR;
|
||||
else
|
||||
@ -1300,8 +1298,8 @@ static int self_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum)
|
||||
crc = crc32(UBI_CRC32_INIT, vid_hdr, UBI_EC_HDR_SIZE_CRC);
|
||||
hdr_crc = be32_to_cpu(vid_hdr->hdr_crc);
|
||||
if (hdr_crc != crc) {
|
||||
ubi_err("bad VID header CRC at PEB %d, calculated %#08x, "
|
||||
"read %#08x", pnum, crc, hdr_crc);
|
||||
ubi_err("bad VID header CRC at PEB %d, calculated %#08x, read %#08x",
|
||||
pnum, crc, hdr_crc);
|
||||
ubi_err("self-check failed for PEB %d", pnum);
|
||||
ubi_dump_vid_hdr(vid_hdr);
|
||||
dump_stack();
|
||||
@ -1411,15 +1409,15 @@ int ubi_self_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len)
|
||||
|
||||
err = mtd_read(ubi->mtd, addr, len, &read, buf);
|
||||
if (err && !mtd_is_bitflip(err)) {
|
||||
ubi_err("error %d while reading %d bytes from PEB %d:%d, "
|
||||
"read %zd bytes", err, len, pnum, offset, read);
|
||||
ubi_err("error %d while reading %d bytes from PEB %d:%d, read %zd bytes",
|
||||
err, len, pnum, offset, read);
|
||||
goto error;
|
||||
}
|
||||
|
||||
err = ubi_check_pattern(buf, 0xFF, len);
|
||||
if (err == 0) {
|
||||
ubi_err("flash region at PEB %d:%d, length %d does not "
|
||||
"contain all 0xFF bytes", pnum, offset, len);
|
||||
ubi_err("flash region at PEB %d:%d, length %d does not contain all 0xFF bytes",
|
||||
pnum, offset, len);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -121,10 +121,16 @@ void ubi_update_reserved(struct ubi_device *ubi)
|
||||
*/
|
||||
void ubi_calculate_reserved(struct ubi_device *ubi)
|
||||
{
|
||||
ubi->beb_rsvd_level = ubi->good_peb_count/100;
|
||||
ubi->beb_rsvd_level *= CONFIG_MTD_UBI_BEB_RESERVE;
|
||||
if (ubi->beb_rsvd_level < MIN_RESEVED_PEBS)
|
||||
ubi->beb_rsvd_level = MIN_RESEVED_PEBS;
|
||||
/*
|
||||
* Calculate the actual number of PEBs currently needed to be reserved
|
||||
* for future bad eraseblock handling.
|
||||
*/
|
||||
ubi->beb_rsvd_level = ubi->bad_peb_limit - ubi->bad_peb_count;
|
||||
if (ubi->beb_rsvd_level < 0) {
|
||||
ubi->beb_rsvd_level = 0;
|
||||
ubi_warn("number of bad PEBs (%d) is above the expected limit (%d), not reserving any PEBs for bad PEB handling, will use available PEBs (if any)",
|
||||
ubi->bad_peb_count, ubi->bad_peb_limit);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -51,17 +51,14 @@
|
||||
#define UBI_NAME_STR "ubi"
|
||||
|
||||
/* Normal UBI messages */
|
||||
#define ubi_msg(fmt, ...) printk(KERN_NOTICE "UBI: " fmt "\n", ##__VA_ARGS__)
|
||||
#define ubi_msg(fmt, ...) pr_notice("UBI: " fmt "\n", ##__VA_ARGS__)
|
||||
/* UBI warning messages */
|
||||
#define ubi_warn(fmt, ...) printk(KERN_WARNING "UBI warning: %s: " fmt "\n", \
|
||||
__func__, ##__VA_ARGS__)
|
||||
#define ubi_warn(fmt, ...) pr_warn("UBI warning: %s: " fmt "\n", \
|
||||
__func__, ##__VA_ARGS__)
|
||||
/* UBI error messages */
|
||||
#define ubi_err(fmt, ...) printk(KERN_ERR "UBI error: %s: " fmt "\n", \
|
||||
#define ubi_err(fmt, ...) pr_err("UBI error: %s: " fmt "\n", \
|
||||
__func__, ##__VA_ARGS__)
|
||||
|
||||
/* Lowest number PEBs reserved for bad PEB handling */
|
||||
#define MIN_RESEVED_PEBS 2
|
||||
|
||||
/* Background thread name pattern */
|
||||
#define UBI_BGT_NAME_PATTERN "ubi_bgt%dd"
|
||||
|
||||
@ -363,6 +360,7 @@ struct ubi_wl_entry;
|
||||
* @flash_size: underlying MTD device size (in bytes)
|
||||
* @peb_count: count of physical eraseblocks on the MTD device
|
||||
* @peb_size: physical eraseblock size
|
||||
* @bad_peb_limit: top limit of expected bad physical eraseblocks
|
||||
* @bad_peb_count: count of bad physical eraseblocks
|
||||
* @good_peb_count: count of good physical eraseblocks
|
||||
* @corr_peb_count: count of corrupted physical eraseblocks (preserved and not
|
||||
@ -410,6 +408,7 @@ struct ubi_device {
|
||||
int avail_pebs;
|
||||
int beb_rsvd_pebs;
|
||||
int beb_rsvd_level;
|
||||
int bad_peb_limit;
|
||||
|
||||
int autoresize_vol_id;
|
||||
int vtbl_slots;
|
||||
@ -694,7 +693,8 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum,
|
||||
struct ubi_vid_hdr *vid_hdr);
|
||||
|
||||
/* build.c */
|
||||
int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset);
|
||||
int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
|
||||
int vid_hdr_offset, int max_beb_per1024);
|
||||
int ubi_detach_mtd_dev(int ubi_num, int anyway);
|
||||
struct ubi_device *ubi_get_device(int ubi_num);
|
||||
void ubi_put_device(struct ubi_device *ubi);
|
||||
|
@ -270,8 +270,8 @@ static int vtbl_check(const struct ubi_device *ubi,
|
||||
|
||||
if (len1 > 0 && len1 == len2 &&
|
||||
!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_err("volumes %d and %d have the same name \"%s\"",
|
||||
i, n, vtbl[i].name);
|
||||
ubi_dump_vtbl_record(&vtbl[i], i);
|
||||
ubi_dump_vtbl_record(&vtbl[n], n);
|
||||
return -EINVAL;
|
||||
@ -304,7 +304,7 @@ static int create_vtbl(struct ubi_device *ubi, struct ubi_attach_info *ai,
|
||||
struct ubi_vid_hdr *vid_hdr;
|
||||
struct ubi_ainf_peb *new_aeb;
|
||||
|
||||
ubi_msg("create volume table (copy #%d)", copy + 1);
|
||||
dbg_gen("create volume table (copy #%d)", copy + 1);
|
||||
|
||||
vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL);
|
||||
if (!vid_hdr)
|
||||
@ -562,8 +562,8 @@ static int init_volumes(struct ubi_device *ubi,
|
||||
if (vtbl[i].flags & UBI_VTBL_AUTORESIZE_FLG) {
|
||||
/* Auto re-size flag may be set only for one volume */
|
||||
if (ubi->autoresize_vol_id != -1) {
|
||||
ubi_err("more than one auto-resize volume (%d "
|
||||
"and %d)", ubi->autoresize_vol_id, i);
|
||||
ubi_err("more than one auto-resize volume (%d and %d)",
|
||||
ubi->autoresize_vol_id, i);
|
||||
kfree(vol);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -978,9 +978,10 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
|
||||
int cancel)
|
||||
{
|
||||
struct ubi_wl_entry *e = wl_wrk->e;
|
||||
int pnum = e->pnum, err, need;
|
||||
int pnum = e->pnum;
|
||||
int vol_id = wl_wrk->vol_id;
|
||||
int lnum = wl_wrk->lnum;
|
||||
int err, available_consumed = 0;
|
||||
|
||||
if (cancel) {
|
||||
dbg_wl("cancel erasure of PEB %d EC %d", pnum, e->ec);
|
||||
@ -1045,20 +1046,14 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
|
||||
}
|
||||
|
||||
spin_lock(&ubi->volumes_lock);
|
||||
need = ubi->beb_rsvd_level - ubi->beb_rsvd_pebs + 1;
|
||||
if (need > 0) {
|
||||
need = ubi->avail_pebs >= need ? need : ubi->avail_pebs;
|
||||
ubi->avail_pebs -= need;
|
||||
ubi->rsvd_pebs += need;
|
||||
ubi->beb_rsvd_pebs += need;
|
||||
if (need > 0)
|
||||
ubi_msg("reserve more %d PEBs", need);
|
||||
}
|
||||
|
||||
if (ubi->beb_rsvd_pebs == 0) {
|
||||
spin_unlock(&ubi->volumes_lock);
|
||||
ubi_err("no reserved physical eraseblocks");
|
||||
goto out_ro;
|
||||
if (ubi->avail_pebs == 0) {
|
||||
spin_unlock(&ubi->volumes_lock);
|
||||
ubi_err("no reserved/available physical eraseblocks");
|
||||
goto out_ro;
|
||||
}
|
||||
ubi->avail_pebs -= 1;
|
||||
available_consumed = 1;
|
||||
}
|
||||
spin_unlock(&ubi->volumes_lock);
|
||||
|
||||
@ -1068,19 +1063,36 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
|
||||
goto out_ro;
|
||||
|
||||
spin_lock(&ubi->volumes_lock);
|
||||
ubi->beb_rsvd_pebs -= 1;
|
||||
if (ubi->beb_rsvd_pebs > 0) {
|
||||
if (available_consumed) {
|
||||
/*
|
||||
* The amount of reserved PEBs increased since we last
|
||||
* checked.
|
||||
*/
|
||||
ubi->avail_pebs += 1;
|
||||
available_consumed = 0;
|
||||
}
|
||||
ubi->beb_rsvd_pebs -= 1;
|
||||
}
|
||||
ubi->bad_peb_count += 1;
|
||||
ubi->good_peb_count -= 1;
|
||||
ubi_calculate_reserved(ubi);
|
||||
if (ubi->beb_rsvd_pebs)
|
||||
if (available_consumed)
|
||||
ubi_warn("no PEBs in the reserved pool, used an available PEB");
|
||||
else if (ubi->beb_rsvd_pebs)
|
||||
ubi_msg("%d PEBs left in the reserve", ubi->beb_rsvd_pebs);
|
||||
else
|
||||
ubi_warn("last PEB from the reserved pool was used");
|
||||
ubi_warn("last PEB from the reserve was used");
|
||||
spin_unlock(&ubi->volumes_lock);
|
||||
|
||||
return err;
|
||||
|
||||
out_ro:
|
||||
if (available_consumed) {
|
||||
spin_lock(&ubi->volumes_lock);
|
||||
ubi->avail_pebs += 1;
|
||||
spin_unlock(&ubi->volumes_lock);
|
||||
}
|
||||
ubi_ro_mode(ubi);
|
||||
return err;
|
||||
}
|
||||
@ -1189,7 +1201,7 @@ int ubi_wl_scrub_peb(struct ubi_device *ubi, int pnum)
|
||||
{
|
||||
struct ubi_wl_entry *e;
|
||||
|
||||
dbg_msg("schedule PEB %d for scrubbing", pnum);
|
||||
ubi_msg("schedule PEB %d for scrubbing", pnum);
|
||||
|
||||
retry:
|
||||
spin_lock(&ubi->wl_lock);
|
||||
|
@ -79,9 +79,10 @@ struct mtd_part_parser {
|
||||
extern int register_mtd_parser(struct mtd_part_parser *parser);
|
||||
extern int deregister_mtd_parser(struct mtd_part_parser *parser);
|
||||
|
||||
int mtd_is_partition(struct mtd_info *mtd);
|
||||
int mtd_is_partition(const struct mtd_info *mtd);
|
||||
int mtd_add_partition(struct mtd_info *master, char *name,
|
||||
long long offset, long long length);
|
||||
int mtd_del_partition(struct mtd_info *master, int partno);
|
||||
uint64_t mtd_get_device_size(const struct mtd_info *mtd);
|
||||
|
||||
#endif
|
||||
|
@ -222,6 +222,7 @@ enum {
|
||||
* @ubi_num: UBI device number to create
|
||||
* @mtd_num: MTD device number to attach
|
||||
* @vid_hdr_offset: VID header offset (use defaults if %0)
|
||||
* @max_beb_per1024: maximum expected number of bad PEB per 1024 PEBs
|
||||
* @padding: reserved for future, not used, has to be zeroed
|
||||
*
|
||||
* This data structure is used to specify MTD device UBI has to attach and the
|
||||
@ -245,12 +246,25 @@ enum {
|
||||
* be 2KiB-64 bytes = 1984. Note, that this position is not even 512-bytes
|
||||
* aligned, which is OK, as UBI is clever enough to realize this is 4th
|
||||
* sub-page of the first page and add needed padding.
|
||||
*
|
||||
* The @max_beb_per1024 is the maximum amount of bad PEBs UBI expects on the
|
||||
* UBI device per 1024 eraseblocks. This value is often given in an other form
|
||||
* in the NAND datasheet (min NVB i.e. minimal number of valid blocks). The
|
||||
* maximum expected bad eraseblocks per 1024 is then:
|
||||
* 1024 * (1 - MinNVB / MaxNVB)
|
||||
* Which gives 20 for most NAND devices. This limit is used in order to derive
|
||||
* amount of eraseblock UBI reserves for handling new bad blocks. If the device
|
||||
* has more bad eraseblocks than this limit, UBI does not reserve any physical
|
||||
* eraseblocks for new bad eraseblocks, but attempts to use available
|
||||
* eraseblocks (if any). The accepted range is 0-768. If 0 is given, the
|
||||
* default kernel value of %CONFIG_MTD_UBI_BEB_LIMIT will be used.
|
||||
*/
|
||||
struct ubi_attach_req {
|
||||
__s32 ubi_num;
|
||||
__s32 mtd_num;
|
||||
__s32 vid_hdr_offset;
|
||||
__s8 padding[12];
|
||||
__s16 max_beb_per1024;
|
||||
__s8 padding[10];
|
||||
};
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user