#include <linux/err.h>
#include <linux/crc32.h>
+#include <asm/div64.h>
#include "ubi.h"
#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
-static int paranoid_check_si(const struct ubi_device *ubi,
- struct ubi_scan_info *si);
+static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si);
#else
#define paranoid_check_si(ubi, si) 0
#endif
return 0;
}
-/**
- * commit_to_mean_value - commit intermediate results to the final mean erase
- * counter value.
- * @si: scanning information
- *
- * This is a helper function which calculates partial mean erase counter mean
- * value and adds it to the resulting mean value. As we can work only in
- * integer arithmetic and we want to calculate the mean value of erase counter
- * accurately, we first sum erase counter values in @si->ec_sum variable and
- * count these components in @si->ec_count. If this temporary @si->ec_sum is
- * going to overflow, we calculate the partial mean value
- * (@si->ec_sum/@si->ec_count) and add it to @si->mean_ec.
- */
-static void commit_to_mean_value(struct ubi_scan_info *si)
-{
- si->ec_sum /= si->ec_count;
- if (si->ec_sum % si->ec_count >= si->ec_count / 2)
- si->mean_ec += 1;
- si->mean_ec += si->ec_sum;
-}
-
/**
* validate_vid_hdr - check that volume identifier header is correct and
* consistent.
* o bit 2 is cleared: the older LEB is not corrupted;
* o bit 2 is set: the older LEB is corrupted.
*/
-static int compare_lebs(const struct ubi_device *ubi,
- const struct ubi_scan_leb *seb, int pnum,
- const struct ubi_vid_hdr *vid_hdr)
+static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb,
+ int pnum, const struct ubi_vid_hdr *vid_hdr)
{
void *buf;
int len, err, second_is_newer, bitflips = 0, corrupted = 0;
uint32_t data_crc, crc;
- struct ubi_vid_hdr *vidh = NULL;
+ struct ubi_vid_hdr *vh = NULL;
unsigned long long sqnum2 = be64_to_cpu(vid_hdr->sqnum);
if (seb->sqnum == 0 && sqnum2 == 0) {
* FIXME: but this is anyway obsolete and will be removed at
* some point.
*/
-
dbg_bld("using old crappy leb_ver stuff");
+ if (v1 == v2) {
+ ubi_err("PEB %d and PEB %d have the same version %lld",
+ seb->pnum, pnum, v1);
+ return -EINVAL;
+ }
+
abs = v1 - v2;
if (abs < 0)
abs = -abs;
} else {
pnum = seb->pnum;
- vidh = ubi_zalloc_vid_hdr(ubi);
- if (!vidh)
+ vh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL);
+ if (!vh)
return -ENOMEM;
- err = ubi_io_read_vid_hdr(ubi, pnum, vidh, 0);
+ err = ubi_io_read_vid_hdr(ubi, pnum, vh, 0);
if (err) {
if (err == UBI_IO_BITFLIPS)
bitflips = 1;
}
}
- if (!vidh->copy_flag) {
+ if (!vh->copy_flag) {
/* It is not a copy, so it is newer */
dbg_bld("first PEB %d is newer, copy_flag is unset",
pnum);
goto out_free_vidh;
}
- vid_hdr = vidh;
+ vid_hdr = vh;
}
/* Read the data of the copy and check the CRC */
}
vfree(buf);
- ubi_free_vid_hdr(ubi, vidh);
+ ubi_free_vid_hdr(ubi, vh);
if (second_is_newer)
dbg_bld("second PEB %d is newer, copy_flag is set", pnum);
out_free_buf:
vfree(buf);
out_free_vidh:
- ubi_free_vid_hdr(ubi, vidh);
- ubi_assert(err < 0);
+ ubi_free_vid_hdr(ubi, vh);
return err;
}
* to be picked, while the older one has to be dropped. This function returns
* zero in case of success and a negative error code in case of failure.
*/
-int ubi_scan_add_used(const struct ubi_device *ubi, struct ubi_scan_info *si,
+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)
{
* function returns zero in case of success and a negative error code in case
* of failure.
*/
-int ubi_scan_erase_peb(const struct ubi_device *ubi,
- const struct ubi_scan_info *si, int pnum, int ec)
+int ubi_scan_erase_peb(struct ubi_device *ubi, const struct ubi_scan_info *si,
+ int pnum, int ec)
{
int err;
struct ubi_ec_hdr *ec_hdr;
- ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL);
- if (!ec_hdr)
- return -ENOMEM;
-
if ((long long)ec >= UBI_MAX_ERASECOUNTER) {
/*
* Erase counter overflow. Upgrade UBI and use 64-bit
return -EINVAL;
}
+ ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL);
+ if (!ec_hdr)
+ return -ENOMEM;
+
ec_hdr->ec = cpu_to_be64(ec);
err = ubi_io_sync_erase(ubi, pnum, 0);
* This function returns scanning physical eraseblock information in case of
* success and an error code in case of failure.
*/
-struct ubi_scan_leb *ubi_scan_get_free_peb(const struct ubi_device *ubi,
+struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi,
struct ubi_scan_info *si)
{
int err = 0, i;
*/
static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, int pnum)
{
- long long ec;
+ long long uninitialized_var(ec);
int err, bitflips = 0, vol_id, ec_corr = 0;
dbg_bld("scan PEB %d", pnum);
}
vol_id = be32_to_cpu(vidh->vol_id);
- if (vol_id > UBI_MAX_VOLUMES && vol_id != UBI_LAYOUT_VOL_ID) {
+ if (vol_id > UBI_MAX_VOLUMES && vol_id != UBI_LAYOUT_VOLUME_ID) {
int lnum = be32_to_cpu(vidh->lnum);
/* Unsupported internal volume */
adjust_mean_ec:
if (!ec_corr) {
- if (si->ec_sum + ec < ec) {
- commit_to_mean_value(si);
- si->ec_sum = 0;
- si->ec_count = 0;
- } else {
- si->ec_sum += ec;
- si->ec_count += 1;
- }
-
+ si->ec_sum += ec;
+ si->ec_count += 1;
if (ec > si->max_ec)
si->max_ec = ec;
if (ec < si->min_ec)
if (!ech)
goto out_si;
- vidh = ubi_zalloc_vid_hdr(ubi);
+ vidh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL);
if (!vidh)
goto out_ech;
dbg_msg("scanning is finished");
- /* Finish mean erase counter calculations */
- if (si->ec_count)
- commit_to_mean_value(si);
+ /* Calculate mean erase counter */
+ if (si->ec_count) {
+ do_div(si->ec_sum, si->ec_count);
+ si->mean_ec = si->ec_sum;
+ }
if (si->is_empty)
ubi_msg("empty MTD device detected");
* This function returns zero if the scanning information is all right, %1 if
* not and a negative error code if an error occurred.
*/
-static int paranoid_check_si(const struct ubi_device *ubi,
- struct ubi_scan_info *si)
+static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si)
{
int pnum, err, vols_found = 0;
struct rb_node *rb1, *rb2;
* Make sure that all the physical eraseblocks are in one of the lists
* or trees.
*/
- buf = kmalloc(ubi->peb_count, GFP_KERNEL);
+ buf = kzalloc(ubi->peb_count, GFP_KERNEL);
if (!buf)
return -ENOMEM;
- memset(buf, 1, ubi->peb_count);
for (pnum = 0; pnum < ubi->peb_count; pnum++) {
err = ubi_io_is_bad(ubi, pnum);
if (err < 0) {
return err;
}
else if (err)
- buf[pnum] = 0;
+ buf[pnum] = 1;
}
ubi_rb_for_each_entry(rb1, sv, &si->volumes, rb)
ubi_rb_for_each_entry(rb2, seb, &sv->root, u.rb)
- buf[seb->pnum] = 0;
+ buf[seb->pnum] = 1;
list_for_each_entry(seb, &si->free, u.list)
- buf[seb->pnum] = 0;
+ buf[seb->pnum] = 1;
list_for_each_entry(seb, &si->corr, u.list)
- buf[seb->pnum] = 0;
+ buf[seb->pnum] = 1;
list_for_each_entry(seb, &si->erase, u.list)
- buf[seb->pnum] = 0;
+ buf[seb->pnum] = 1;
list_for_each_entry(seb, &si->alien, u.list)
- buf[seb->pnum] = 0;
+ buf[seb->pnum] = 1;
err = 0;
for (pnum = 0; pnum < ubi->peb_count; pnum++)
- if (buf[pnum]) {
+ if (!buf[pnum]) {
ubi_err("PEB %d is not referred", pnum);
err = 1;
}