提交 6133308a 编写于 作者: L Linus Torvalds

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
  ...
...@@ -52,12 +52,4 @@ config MTD_UBI_GLUEBI ...@@ -52,12 +52,4 @@ config MTD_UBI_GLUEBI
work on top of UBI. Do not enable this unless you use legacy work on top of UBI. Do not enable this unless you use legacy
software. 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 endif # MTD_UBI
obj-$(CONFIG_MTD_UBI) += ubi.o 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 += vtbl.o vmt.o upd.o build.o cdev.o kapi.o eba.o io.o wl.o attach.o
ubi-y += misc.o ubi-y += misc.o debug.o
ubi-$(CONFIG_MTD_UBI_DEBUG) += debug.o
obj-$(CONFIG_MTD_UBI_GLUEBI) += gluebi.o obj-$(CONFIG_MTD_UBI_GLUEBI) += gluebi.o
...@@ -27,10 +27,6 @@ ...@@ -27,10 +27,6 @@
* module load parameters or the kernel boot parameters. If MTD devices were * 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 * specified, UBI does not attach any MTD device, but it is possible to do
* later using the "UBI control device". * 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> #include <linux/err.h>
...@@ -554,10 +550,10 @@ static void uif_close(struct ubi_device *ubi) ...@@ -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 * @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; int i;
...@@ -568,59 +564,6 @@ static void free_internal_volumes(struct ubi_device *ubi) ...@@ -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. * io_init - initialize I/O sub-system for a given UBI device.
* @ubi: UBI device description object * @ubi: UBI device description object
...@@ -790,11 +733,11 @@ static int io_init(struct ubi_device *ubi) ...@@ -790,11 +733,11 @@ static int io_init(struct ubi_device *ubi)
ubi_msg("data offset: %d", ubi->leb_start); 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 * unfortunately, MTD does not provide this information. We should loop
* over all physical eraseblocks and invoke mtd->block_is_bad() for * over all physical eraseblocks and invoke mtd->block_is_bad() for
* each physical eraseblock. So, we skip ubi->bad_peb_count * each physical eraseblock. So, we leave @ubi->bad_peb_count
* uninitialized and initialize it after scanning. * uninitialized so far.
*/ */
return 0; return 0;
...@@ -805,7 +748,7 @@ static int io_init(struct ubi_device *ubi) ...@@ -805,7 +748,7 @@ static int io_init(struct ubi_device *ubi)
* @ubi: UBI device description object * @ubi: UBI device description object
* @vol_id: ID of the volume to re-size * @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 * 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 * for more description of the flag. Returns zero in case of success and a
* negative error code in case of failure. * 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) ...@@ -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++) { for (i = 0; i < UBI_MAX_DEVICES; i++) {
ubi = ubi_devices[i]; ubi = ubi_devices[i];
if (ubi && mtd->index == ubi->mtd->index) { 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); mtd->index, i);
return -EEXIST; return -EEXIST;
} }
...@@ -907,7 +850,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) ...@@ -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]) if (!ubi_devices[ubi_num])
break; break;
if (ubi_num == UBI_MAX_DEVICES) { 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); UBI_MAX_DEVICES);
return -ENFILE; return -ENFILE;
} }
...@@ -917,7 +860,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) ...@@ -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 */ /* Make sure ubi_num is not busy */
if (ubi_devices[ubi_num]) { if (ubi_devices[ubi_num]) {
dbg_err("ubi%d already exists", ubi_num); ubi_err("ubi%d already exists", ubi_num);
return -EEXIST; return -EEXIST;
} }
} }
...@@ -937,7 +880,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) ...@@ -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); spin_lock_init(&ubi->volumes_lock);
ubi_msg("attaching mtd%d to ubi%d", mtd->index, ubi_num); 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)); dbg_msg("sizeof(struct ubi_wl_entry) %zu", sizeof(struct ubi_wl_entry));
err = io_init(ubi); err = io_init(ubi);
...@@ -953,9 +896,9 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) ...@@ -953,9 +896,9 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
if (err) if (err)
goto out_free; goto out_free;
err = attach_by_scanning(ubi); err = ubi_attach(ubi);
if (err) { 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; goto out_debugging;
} }
...@@ -1020,7 +963,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) ...@@ -1020,7 +963,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
uif_close(ubi); uif_close(ubi);
out_detach: out_detach:
ubi_wl_close(ubi); ubi_wl_close(ubi);
free_internal_volumes(ubi); ubi_free_internal_volumes(ubi);
vfree(ubi->vtbl); vfree(ubi->vtbl);
out_debugging: out_debugging:
ubi_debugging_exit_dev(ubi); ubi_debugging_exit_dev(ubi);
...@@ -1092,7 +1035,7 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway) ...@@ -1092,7 +1035,7 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
ubi_debugfs_exit_dev(ubi); ubi_debugfs_exit_dev(ubi);
uif_close(ubi); uif_close(ubi);
ubi_wl_close(ubi); ubi_wl_close(ubi);
free_internal_volumes(ubi); ubi_free_internal_volumes(ubi);
vfree(ubi->vtbl); vfree(ubi->vtbl);
put_mtd_device(ubi->mtd); put_mtd_device(ubi->mtd);
ubi_debugging_exit_dev(ubi); ubi_debugging_exit_dev(ubi);
......
...@@ -63,7 +63,7 @@ static int get_exclusive(struct ubi_volume_desc *desc) ...@@ -63,7 +63,7 @@ static int get_exclusive(struct ubi_volume_desc *desc)
users = vol->readers + vol->writers + vol->exclusive; users = vol->readers + vol->writers + vol->exclusive;
ubi_assert(users > 0); ubi_assert(users > 0);
if (users > 1) { 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; err = -EBUSY;
} else { } else {
vol->readers = vol->writers = 0; vol->readers = vol->writers = 0;
...@@ -159,7 +159,7 @@ static loff_t vol_cdev_llseek(struct file *file, loff_t offset, int origin) ...@@ -159,7 +159,7 @@ static loff_t vol_cdev_llseek(struct file *file, loff_t offset, int origin)
if (vol->updating) { if (vol->updating) {
/* Update is in progress, seeking is prohibited */ /* Update is in progress, seeking is prohibited */
dbg_err("updating"); ubi_err("updating");
return -EBUSY; return -EBUSY;
} }
...@@ -178,7 +178,7 @@ static loff_t vol_cdev_llseek(struct file *file, loff_t offset, int origin) ...@@ -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) { 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; return -EINVAL;
} }
...@@ -216,11 +216,11 @@ static ssize_t vol_cdev_read(struct file *file, __user char *buf, size_t count, ...@@ -216,11 +216,11 @@ static ssize_t vol_cdev_read(struct file *file, __user char *buf, size_t count,
count, *offp, vol->vol_id); count, *offp, vol->vol_id);
if (vol->updating) { if (vol->updating) {
dbg_err("updating"); ubi_err("updating");
return -EBUSY; return -EBUSY;
} }
if (vol->upd_marker) { if (vol->upd_marker) {
dbg_err("damaged volume, update marker is set"); ubi_err("damaged volume, update marker is set");
return -EBADF; return -EBADF;
} }
if (*offp == vol->used_bytes || count == 0) 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, ...@@ -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); lnum = div_u64_rem(*offp, vol->usable_leb_size, &off);
if (off & (ubi->min_io_size - 1)) { if (off & (ubi->min_io_size - 1)) {
dbg_err("unaligned position"); ubi_err("unaligned position");
return -EINVAL; return -EINVAL;
} }
...@@ -309,7 +309,7 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf, ...@@ -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 */ /* We can write only in fractions of the minimum I/O unit */
if (count & (ubi->min_io_size - 1)) { if (count & (ubi->min_io_size - 1)) {
dbg_err("unaligned write length"); ubi_err("unaligned write length");
return -EINVAL; return -EINVAL;
} }
...@@ -334,8 +334,7 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf, ...@@ -334,8 +334,7 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf,
break; break;
} }
err = ubi_eba_write_leb(ubi, vol, lnum, tbuf, off, len, err = ubi_eba_write_leb(ubi, vol, lnum, tbuf, off, len);
UBI_UNKNOWN);
if (err) if (err)
break; break;
...@@ -477,9 +476,6 @@ static long vol_cdev_ioctl(struct file *file, unsigned int cmd, ...@@ -477,9 +476,6 @@ static long vol_cdev_ioctl(struct file *file, unsigned int cmd,
if (req.lnum < 0 || req.lnum >= vol->reserved_pebs || if (req.lnum < 0 || req.lnum >= vol->reserved_pebs ||
req.bytes < 0 || req.lnum >= vol->usable_leb_size) req.bytes < 0 || req.lnum >= vol->usable_leb_size)
break; break;
if (req.dtype != UBI_LONGTERM && req.dtype != UBI_SHORTTERM &&
req.dtype != UBI_UNKNOWN)
break;
err = get_exclusive(desc); err = get_exclusive(desc);
if (err < 0) if (err < 0)
...@@ -518,7 +514,7 @@ static long vol_cdev_ioctl(struct file *file, unsigned int cmd, ...@@ -518,7 +514,7 @@ static long vol_cdev_ioctl(struct file *file, unsigned int cmd,
if (err) if (err)
break; break;
err = ubi_wl_flush(ubi); err = ubi_wl_flush(ubi, UBI_ALL, UBI_ALL);
break; break;
} }
...@@ -532,7 +528,7 @@ static long vol_cdev_ioctl(struct file *file, unsigned int cmd, ...@@ -532,7 +528,7 @@ static long vol_cdev_ioctl(struct file *file, unsigned int cmd,
err = -EFAULT; err = -EFAULT;
break; break;
} }
err = ubi_leb_map(desc, req.lnum, req.dtype); err = ubi_leb_map(desc, req.lnum);
break; break;
} }
...@@ -647,8 +643,8 @@ static int verify_mkvol_req(const struct ubi_device *ubi, ...@@ -647,8 +643,8 @@ static int verify_mkvol_req(const struct ubi_device *ubi,
return 0; return 0;
bad: bad:
dbg_err("bad volume creation request"); ubi_err("bad volume creation request");
ubi_dbg_dump_mkvol_req(req); ubi_dump_mkvol_req(req);
return err; return err;
} }
...@@ -713,12 +709,12 @@ static int rename_volumes(struct ubi_device *ubi, ...@@ -713,12 +709,12 @@ static int rename_volumes(struct ubi_device *ubi,
for (i = 0; i < req->count - 1; i++) { for (i = 0; i < req->count - 1; i++) {
for (n = i + 1; n < req->count; n++) { for (n = i + 1; n < req->count; n++) {
if (req->ents[i].vol_id == req->ents[n].vol_id) { 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); req->ents[i].vol_id);
return -EINVAL; return -EINVAL;
} }
if (!strcmp(req->ents[i].name, req->ents[n].name)) { 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); req->ents[i].name);
return -EINVAL; return -EINVAL;
} }
...@@ -741,7 +737,7 @@ static int rename_volumes(struct ubi_device *ubi, ...@@ -741,7 +737,7 @@ static int rename_volumes(struct ubi_device *ubi,
re->desc = ubi_open_volume(ubi->ubi_num, vol_id, UBI_EXCLUSIVE); re->desc = ubi_open_volume(ubi->ubi_num, vol_id, UBI_EXCLUSIVE);
if (IS_ERR(re->desc)) { if (IS_ERR(re->desc)) {
err = PTR_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); kfree(re);
goto out_free; goto out_free;
} }
...@@ -800,7 +796,7 @@ static int rename_volumes(struct ubi_device *ubi, ...@@ -800,7 +796,7 @@ static int rename_volumes(struct ubi_device *ubi,
continue; continue;
/* The volume exists but busy, or an error occurred */ /* 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); re->new_name, err);
goto out_free; goto out_free;
} }
......
...@@ -18,24 +18,49 @@ ...@@ -18,24 +18,49 @@
* Author: Artem Bityutskiy (Битюцкий Артём) * 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 "ubi.h"
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/module.h> #include <linux/module.h>
/**
* 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_dbg_dump_ec_hdr - dump an erase counter header. * ubi_dump_ec_hdr - dump an erase counter header.
* @ec_hdr: the erase counter header to dump * @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 "Erase counter header dump:\n");
printk(KERN_DEBUG "\tmagic %#08x\n", printk(KERN_DEBUG "\tmagic %#08x\n",
...@@ -57,10 +82,10 @@ void ubi_dbg_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr) ...@@ -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 * @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 "Volume identifier header dump:\n");
printk(KERN_DEBUG "\tmagic %08x\n", be32_to_cpu(vid_hdr->magic)); 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) ...@@ -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 * @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 "Volume information dump:\n");
printk(KERN_DEBUG "\tvol_id %d\n", vol->vol_id); 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) ...@@ -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 * @r: the object to dump
* @idx: volume table index * @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); 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) ...@@ -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. * ubi_dump_av - dump a &struct ubi_ainf_volume object.
* @sv: the object to dump * @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 "Volume attaching information dump:\n");
printk(KERN_DEBUG "\tvol_id %d\n", sv->vol_id); printk(KERN_DEBUG "\tvol_id %d\n", av->vol_id);
printk(KERN_DEBUG "\thighest_lnum %d\n", sv->highest_lnum); printk(KERN_DEBUG "\thighest_lnum %d\n", av->highest_lnum);
printk(KERN_DEBUG "\tleb_count %d\n", sv->leb_count); printk(KERN_DEBUG "\tleb_count %d\n", av->leb_count);
printk(KERN_DEBUG "\tcompat %d\n", sv->compat); printk(KERN_DEBUG "\tcompat %d\n", av->compat);
printk(KERN_DEBUG "\tvol_type %d\n", sv->vol_type); printk(KERN_DEBUG "\tvol_type %d\n", av->vol_type);
printk(KERN_DEBUG "\tused_ebs %d\n", sv->used_ebs); printk(KERN_DEBUG "\tused_ebs %d\n", av->used_ebs);
printk(KERN_DEBUG "\tlast_data_size %d\n", sv->last_data_size); printk(KERN_DEBUG "\tlast_data_size %d\n", av->last_data_size);
printk(KERN_DEBUG "\tdata_pad %d\n", sv->data_pad); printk(KERN_DEBUG "\tdata_pad %d\n", av->data_pad);
} }
/** /**
* ubi_dbg_dump_seb - dump a &struct ubi_scan_leb object. * ubi_dump_aeb - dump a &struct ubi_ainf_peb object.
* @seb: the object to dump * @aeb: the object to dump
* @type: object type: 0 - not corrupted, 1 - corrupted * @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 "eraseblock attaching information dump:\n");
printk(KERN_DEBUG "\tec %d\n", seb->ec); printk(KERN_DEBUG "\tec %d\n", aeb->ec);
printk(KERN_DEBUG "\tpnum %d\n", seb->pnum); printk(KERN_DEBUG "\tpnum %d\n", aeb->pnum);
if (type == 0) { if (type == 0) {
printk(KERN_DEBUG "\tlnum %d\n", seb->lnum); printk(KERN_DEBUG "\tlnum %d\n", aeb->lnum);
printk(KERN_DEBUG "\tscrub %d\n", seb->scrub); printk(KERN_DEBUG "\tscrub %d\n", aeb->scrub);
printk(KERN_DEBUG "\tsqnum %llu\n", seb->sqnum); 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 * @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]; char nm[17];
...@@ -199,38 +224,6 @@ void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req) ...@@ -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); 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_debugging_init_dev - initialize debugging for an UBI device.
* @ubi: UBI device description object * @ubi: UBI device description object
...@@ -479,5 +472,3 @@ void ubi_debugfs_exit_dev(struct ubi_device *ubi) ...@@ -479,5 +472,3 @@ void ubi_debugfs_exit_dev(struct ubi_device *ubi)
{ {
debugfs_remove_recursive(ubi->dbg->dfs_dir); debugfs_remove_recursive(ubi->dbg->dfs_dir);
} }
#endif /* CONFIG_MTD_UBI_DEBUG */
...@@ -21,21 +21,20 @@ ...@@ -21,21 +21,20 @@
#ifndef __UBI_DEBUG_H__ #ifndef __UBI_DEBUG_H__
#define __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> #include <linux/random.h>
#define ubi_assert(expr) do { \ #define ubi_assert(expr) do { \
if (unlikely(!(expr))) { \ if (unlikely(!(expr))) { \
printk(KERN_CRIT "UBI assert failed in %s at %u (pid %d)\n", \ printk(KERN_CRIT "UBI assert failed in %s at %u (pid %d)\n", \
__func__, __LINE__, current->pid); \ __func__, __LINE__, current->pid); \
ubi_dbg_dump_stack(); \ dump_stack(); \
} \ } \
} while (0) } 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) \ #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) print_hex_dump(l, ps, pt, r, g, b, len, a)
...@@ -58,17 +57,13 @@ ...@@ -58,17 +57,13 @@
/* Initialization and build messages */ /* Initialization and build messages */
#define dbg_bld(fmt, ...) ubi_dbg_msg("bld", fmt, ##__VA_ARGS__) #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_dump_vol_info(const struct ubi_volume *vol);
void ubi_dbg_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr); void ubi_dump_vtbl_record(const struct ubi_vtbl_record *r, int idx);
void ubi_dbg_dump_vol_info(const struct ubi_volume *vol); void ubi_dump_av(const struct ubi_ainf_volume *av);
void ubi_dbg_dump_vtbl_record(const struct ubi_vtbl_record *r, int idx); void ubi_dump_aeb(const struct ubi_ainf_peb *aeb, int type);
void ubi_dbg_dump_sv(const struct ubi_scan_volume *sv); void ubi_dump_mkvol_req(const struct ubi_mkvol_req *req);
void ubi_dbg_dump_seb(const struct ubi_scan_leb *seb, int type); int ubi_self_check_all_ff(struct ubi_device *ubi, int pnum, int offset,
void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req); int len);
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);
int ubi_debugging_init_dev(struct ubi_device *ubi); int ubi_debugging_init_dev(struct ubi_device *ubi);
void ubi_debugging_exit_dev(struct ubi_device *ubi); void ubi_debugging_exit_dev(struct ubi_device *ubi);
int ubi_debugfs_init(void); int ubi_debugfs_init(void);
...@@ -167,73 +162,4 @@ static inline int ubi_dbg_is_erase_failure(const struct ubi_device *ubi) ...@@ -167,73 +162,4 @@ static inline int ubi_dbg_is_erase_failure(const struct ubi_device *ubi)
return 0; 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__ */ #endif /* !__UBI_DEBUG_H__ */
...@@ -341,7 +341,7 @@ int ubi_eba_unmap_leb(struct ubi_device *ubi, struct ubi_volume *vol, ...@@ -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); dbg_eba("erase LEB %d:%d, PEB %d", vol_id, lnum, pnum);
vol->eba_tbl[lnum] = UBI_LEB_UNMAPPED; 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: out_unlock:
leb_write_unlock(ubi, vol_id, lnum); 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, ...@@ -507,7 +507,7 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum,
return -ENOMEM; return -ENOMEM;
retry: retry:
new_pnum = ubi_wl_get_peb(ubi, UBI_UNKNOWN); new_pnum = ubi_wl_get_peb(ubi);
if (new_pnum < 0) { if (new_pnum < 0) {
ubi_free_vid_hdr(ubi, vid_hdr); ubi_free_vid_hdr(ubi, vid_hdr);
return new_pnum; return new_pnum;
...@@ -550,7 +550,7 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum, ...@@ -550,7 +550,7 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum,
ubi_free_vid_hdr(ubi, vid_hdr); ubi_free_vid_hdr(ubi, vid_hdr);
vol->eba_tbl[lnum] = new_pnum; 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"); ubi_msg("data was successfully recovered");
return 0; return 0;
...@@ -558,7 +558,7 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum, ...@@ -558,7 +558,7 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum,
out_unlock: out_unlock:
mutex_unlock(&ubi->buf_mutex); mutex_unlock(&ubi->buf_mutex);
out_put: 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); ubi_free_vid_hdr(ubi, vid_hdr);
return err; return err;
...@@ -568,7 +568,7 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum, ...@@ -568,7 +568,7 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum,
* get another one. * get another one.
*/ */
ubi_warn("failed to write to PEB %d", new_pnum); 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) { if (++tries > UBI_IO_RETRIES) {
ubi_free_vid_hdr(ubi, vid_hdr); ubi_free_vid_hdr(ubi, vid_hdr);
return err; return err;
...@@ -585,7 +585,6 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum, ...@@ -585,7 +585,6 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum,
* @buf: the data to write * @buf: the data to write
* @offset: offset within the logical eraseblock where to write * @offset: offset within the logical eraseblock where to write
* @len: how many bytes to write * @len: how many bytes to write
* @dtype: data type
* *
* This function writes data to logical eraseblock @lnum of a dynamic volume * 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 * @vol. Returns zero in case of success and a negative error code in case
...@@ -593,7 +592,7 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum, ...@@ -593,7 +592,7 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum,
* written to the flash media, but may be some garbage. * 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, 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; int err, pnum, tries = 0, vol_id = vol->vol_id;
struct ubi_vid_hdr *vid_hdr; 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, ...@@ -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); vid_hdr->data_pad = cpu_to_be32(vol->data_pad);
retry: retry:
pnum = ubi_wl_get_peb(ubi, dtype); pnum = ubi_wl_get_peb(ubi);
if (pnum < 0) { if (pnum < 0) {
ubi_free_vid_hdr(ubi, vid_hdr); ubi_free_vid_hdr(ubi, vid_hdr);
leb_write_unlock(ubi, vol_id, lnum); leb_write_unlock(ubi, vol_id, lnum);
...@@ -687,7 +686,7 @@ int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, ...@@ -687,7 +686,7 @@ int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
* eraseblock, so just put it and request a new one. We assume that if * 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. * 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) { if (err || ++tries > UBI_IO_RETRIES) {
ubi_ro_mode(ubi); ubi_ro_mode(ubi);
leb_write_unlock(ubi, vol_id, lnum); leb_write_unlock(ubi, vol_id, lnum);
...@@ -707,7 +706,6 @@ int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, ...@@ -707,7 +706,6 @@ int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
* @lnum: logical eraseblock number * @lnum: logical eraseblock number
* @buf: data to write * @buf: data to write
* @len: how many bytes to write * @len: how many bytes to write
* @dtype: data type
* @used_ebs: how many logical eraseblocks will this volume contain * @used_ebs: how many logical eraseblocks will this volume contain
* *
* This function writes data to logical eraseblock @lnum of static volume * This function writes data to logical eraseblock @lnum of static volume
...@@ -724,8 +722,7 @@ int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, ...@@ -724,8 +722,7 @@ int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
* code in case of failure. * code in case of failure.
*/ */
int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol, int ubi_eba_write_leb_st(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 used_ebs)
int used_ebs)
{ {
int err, pnum, tries = 0, data_size = len, vol_id = vol->vol_id; int err, pnum, tries = 0, data_size = len, vol_id = vol->vol_id;
struct ubi_vid_hdr *vid_hdr; struct ubi_vid_hdr *vid_hdr;
...@@ -763,7 +760,7 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol, ...@@ -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); vid_hdr->data_crc = cpu_to_be32(crc);
retry: retry:
pnum = ubi_wl_get_peb(ubi, dtype); pnum = ubi_wl_get_peb(ubi);
if (pnum < 0) { if (pnum < 0) {
ubi_free_vid_hdr(ubi, vid_hdr); ubi_free_vid_hdr(ubi, vid_hdr);
leb_write_unlock(ubi, vol_id, lnum); leb_write_unlock(ubi, vol_id, lnum);
...@@ -807,7 +804,7 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol, ...@@ -807,7 +804,7 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol,
return err; 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) { if (err || ++tries > UBI_IO_RETRIES) {
ubi_ro_mode(ubi); ubi_ro_mode(ubi);
leb_write_unlock(ubi, vol_id, lnum); leb_write_unlock(ubi, vol_id, lnum);
...@@ -827,7 +824,6 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol, ...@@ -827,7 +824,6 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol,
* @lnum: logical eraseblock number * @lnum: logical eraseblock number
* @buf: data to write * @buf: data to write
* @len: how many bytes to write * @len: how many bytes to write
* @dtype: data type
* *
* This function changes the contents of a logical eraseblock atomically. @buf * This function changes the contents of a logical eraseblock atomically. @buf
* has to contain new logical eraseblock data, and @len - the length of the * has to contain new logical eraseblock data, and @len - the length of the
...@@ -839,7 +835,7 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol, ...@@ -839,7 +835,7 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol,
* LEB change may be done at a time. This is ensured by @ubi->alc_mutex. * 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 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; int err, pnum, tries = 0, vol_id = vol->vol_id;
struct ubi_vid_hdr *vid_hdr; struct ubi_vid_hdr *vid_hdr;
...@@ -856,7 +852,7 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol, ...@@ -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); err = ubi_eba_unmap_leb(ubi, vol, lnum);
if (err) if (err)
return 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); 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, ...@@ -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); vid_hdr->data_crc = cpu_to_be32(crc);
retry: retry:
pnum = ubi_wl_get_peb(ubi, dtype); pnum = ubi_wl_get_peb(ubi);
if (pnum < 0) { if (pnum < 0) {
err = pnum; err = pnum;
goto out_leb_unlock; goto out_leb_unlock;
...@@ -905,7 +901,7 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol, ...@@ -905,7 +901,7 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
} }
if (vol->eba_tbl[lnum] >= 0) { 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) if (err)
goto out_leb_unlock; goto out_leb_unlock;
} }
...@@ -930,7 +926,7 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol, ...@@ -930,7 +926,7 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
goto out_leb_unlock; 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) { if (err || ++tries > UBI_IO_RETRIES) {
ubi_ro_mode(ubi); ubi_ro_mode(ubi);
goto out_leb_unlock; goto out_leb_unlock;
...@@ -1171,7 +1167,7 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, ...@@ -1171,7 +1167,7 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
* print_rsvd_warning - warn about not having enough reserved PEBs. * print_rsvd_warning - warn about not having enough reserved PEBs.
* @ubi: UBI device description object * @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 * 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 * decision whether we have to print a warning or not. The algorithm is as
* follows: * follows:
...@@ -1186,13 +1182,13 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, ...@@ -1186,13 +1182,13 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
* reported by real users. * reported by real users.
*/ */
static void print_rsvd_warning(struct ubi_device *ubi, 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 * The 1 << 18 (256KiB) number is picked randomly, just a reasonably
* large number to distinguish between newly flashed and used images. * 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; int min = ubi->beb_rsvd_level / 10;
if (!min) if (!min)
...@@ -1209,19 +1205,19 @@ static void print_rsvd_warning(struct ubi_device *ubi, ...@@ -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 * @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 * This function returns zero in case of success and a negative error code in
* case of failure. * 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; int i, j, err, num_volumes;
struct ubi_scan_volume *sv; struct ubi_ainf_volume *av;
struct ubi_volume *vol; struct ubi_volume *vol;
struct ubi_scan_leb *seb; struct ubi_ainf_peb *aeb;
struct rb_node *rb; struct rb_node *rb;
dbg_eba("initialize EBA sub-system"); dbg_eba("initialize EBA sub-system");
...@@ -1230,7 +1226,7 @@ int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si) ...@@ -1230,7 +1226,7 @@ int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
mutex_init(&ubi->alc_mutex); mutex_init(&ubi->alc_mutex);
ubi->ltree = RB_ROOT; 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; num_volumes = ubi->vtbl_slots + UBI_INT_VOL_COUNT;
for (i = 0; i < num_volumes; i++) { 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) ...@@ -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++) for (j = 0; j < vol->reserved_pebs; j++)
vol->eba_tbl[j] = UBI_LEB_UNMAPPED; vol->eba_tbl[j] = UBI_LEB_UNMAPPED;
sv = ubi_scan_find_sv(si, idx2vol_id(ubi, i)); av = ubi_find_av(ai, idx2vol_id(ubi, i));
if (!sv) if (!av)
continue; continue;
ubi_rb_for_each_entry(rb, seb, &sv->root, u.rb) { ubi_rb_for_each_entry(rb, aeb, &av->root, u.rb) {
if (seb->lnum >= vol->reserved_pebs) if (aeb->lnum >= vol->reserved_pebs)
/* /*
* This may happen in case of an unclean reboot * This may happen in case of an unclean reboot
* during re-size. * during re-size.
*/ */
ubi_scan_move_to_list(sv, seb, &si->erase); ubi_move_aeb_to_list(av, aeb, &ai->erase);
vol->eba_tbl[seb->lnum] = seb->pnum; 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) ...@@ -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) { if (ubi->avail_pebs < ubi->beb_rsvd_level) {
/* No enough free physical eraseblocks */ /* No enough free physical eraseblocks */
ubi->beb_rsvd_pebs = ubi->avail_pebs; ubi->beb_rsvd_pebs = ubi->avail_pebs;
print_rsvd_warning(ubi, si); print_rsvd_warning(ubi, ai);
} else } else
ubi->beb_rsvd_pebs = ubi->beb_rsvd_level; 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, ...@@ -227,7 +227,7 @@ static int gluebi_write(struct mtd_info *mtd, loff_t to, size_t len,
if (to_write > total_written) if (to_write > total_written)
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) if (err)
break; break;
......
此差异已折叠。
...@@ -221,7 +221,7 @@ struct ubi_volume_desc *ubi_open_volume(int ubi_num, int vol_id, int mode) ...@@ -221,7 +221,7 @@ struct ubi_volume_desc *ubi_open_volume(int ubi_num, int vol_id, int mode)
kfree(desc); kfree(desc);
out_put_ubi: out_put_ubi:
ubi_put_device(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); ubi_num, vol_id, err);
return ERR_PTR(err); return ERR_PTR(err);
} }
...@@ -426,11 +426,9 @@ EXPORT_SYMBOL_GPL(ubi_leb_read); ...@@ -426,11 +426,9 @@ EXPORT_SYMBOL_GPL(ubi_leb_read);
* @buf: data to write * @buf: data to write
* @offset: offset within the logical eraseblock where to write * @offset: offset within the logical eraseblock where to write
* @len: how many bytes 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 * This function writes @len bytes of data from @buf to offset @offset of
* logical eraseblock @lnum. The @dtype argument describes expected lifetime of * logical eraseblock @lnum.
* the data.
* *
* This function takes care of physical eraseblock write failures. If write to * This function takes care of physical eraseblock write failures. If write to
* the physical eraseblock write operation fails, the logical eraseblock is * the physical eraseblock write operation fails, the logical eraseblock is
...@@ -447,7 +445,7 @@ EXPORT_SYMBOL_GPL(ubi_leb_read); ...@@ -447,7 +445,7 @@ EXPORT_SYMBOL_GPL(ubi_leb_read);
* returns immediately with %-EBADF code. * returns immediately with %-EBADF code.
*/ */
int ubi_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf, 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_volume *vol = desc->vol;
struct ubi_device *ubi = vol->ubi; struct ubi_device *ubi = vol->ubi;
...@@ -466,17 +464,13 @@ int ubi_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf, ...@@ -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)) offset & (ubi->min_io_size - 1) || len & (ubi->min_io_size - 1))
return -EINVAL; return -EINVAL;
if (dtype != UBI_LONGTERM && dtype != UBI_SHORTTERM &&
dtype != UBI_UNKNOWN)
return -EINVAL;
if (vol->upd_marker) if (vol->upd_marker)
return -EBADF; return -EBADF;
if (len == 0) if (len == 0)
return 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); EXPORT_SYMBOL_GPL(ubi_leb_write);
...@@ -486,7 +480,6 @@ EXPORT_SYMBOL_GPL(ubi_leb_write); ...@@ -486,7 +480,6 @@ EXPORT_SYMBOL_GPL(ubi_leb_write);
* @lnum: logical eraseblock number to change * @lnum: logical eraseblock number to change
* @buf: data to write * @buf: data to write
* @len: how many bytes to write * @len: how many bytes to write
* @dtype: expected data type
* *
* This function changes the contents of a logical eraseblock atomically. @buf * This function changes the contents of a logical eraseblock atomically. @buf
* has to contain new logical eraseblock data, and @len - the length of the * has to contain new logical eraseblock data, and @len - the length of the
...@@ -497,7 +490,7 @@ EXPORT_SYMBOL_GPL(ubi_leb_write); ...@@ -497,7 +490,7 @@ EXPORT_SYMBOL_GPL(ubi_leb_write);
* code in case of failure. * code in case of failure.
*/ */
int ubi_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf, 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_volume *vol = desc->vol;
struct ubi_device *ubi = vol->ubi; struct ubi_device *ubi = vol->ubi;
...@@ -515,17 +508,13 @@ int ubi_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf, ...@@ -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)) len > vol->usable_leb_size || len & (ubi->min_io_size - 1))
return -EINVAL; return -EINVAL;
if (dtype != UBI_LONGTERM && dtype != UBI_SHORTTERM &&
dtype != UBI_UNKNOWN)
return -EINVAL;
if (vol->upd_marker) if (vol->upd_marker)
return -EBADF; return -EBADF;
if (len == 0) if (len == 0)
return 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); EXPORT_SYMBOL_GPL(ubi_leb_change);
...@@ -562,7 +551,7 @@ int ubi_leb_erase(struct ubi_volume_desc *desc, int lnum) ...@@ -562,7 +551,7 @@ int ubi_leb_erase(struct ubi_volume_desc *desc, int lnum)
if (err) if (err)
return err; return err;
return ubi_wl_flush(ubi); return ubi_wl_flush(ubi, vol->vol_id, lnum);
} }
EXPORT_SYMBOL_GPL(ubi_leb_erase); EXPORT_SYMBOL_GPL(ubi_leb_erase);
...@@ -626,7 +615,6 @@ EXPORT_SYMBOL_GPL(ubi_leb_unmap); ...@@ -626,7 +615,6 @@ EXPORT_SYMBOL_GPL(ubi_leb_unmap);
* ubi_leb_map - map logical eraseblock to a physical eraseblock. * ubi_leb_map - map logical eraseblock to a physical eraseblock.
* @desc: volume descriptor * @desc: volume descriptor
* @lnum: logical eraseblock number * @lnum: logical eraseblock number
* @dtype: expected data type
* *
* This function maps an un-mapped logical eraseblock @lnum to a physical * This function maps an un-mapped logical eraseblock @lnum to a physical
* eraseblock. This means, that after a successful invocation of this * eraseblock. This means, that after a successful invocation of this
...@@ -639,7 +627,7 @@ EXPORT_SYMBOL_GPL(ubi_leb_unmap); ...@@ -639,7 +627,7 @@ EXPORT_SYMBOL_GPL(ubi_leb_unmap);
* eraseblock is already mapped, and other negative error codes in case of * eraseblock is already mapped, and other negative error codes in case of
* other failures. * 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_volume *vol = desc->vol;
struct ubi_device *ubi = vol->ubi; struct ubi_device *ubi = vol->ubi;
...@@ -652,17 +640,13 @@ int ubi_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype) ...@@ -652,17 +640,13 @@ int ubi_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype)
if (lnum < 0 || lnum >= vol->reserved_pebs) if (lnum < 0 || lnum >= vol->reserved_pebs)
return -EINVAL; return -EINVAL;
if (dtype != UBI_LONGTERM && dtype != UBI_SHORTTERM &&
dtype != UBI_UNKNOWN)
return -EINVAL;
if (vol->upd_marker) if (vol->upd_marker)
return -EBADF; return -EBADF;
if (vol->eba_tbl[lnum] >= 0) if (vol->eba_tbl[lnum] >= 0)
return -EBADMSG; 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); EXPORT_SYMBOL_GPL(ubi_leb_map);
...@@ -720,6 +704,33 @@ int ubi_sync(int ubi_num) ...@@ -720,6 +704,33 @@ int ubi_sync(int ubi_num)
} }
EXPORT_SYMBOL_GPL(ubi_sync); 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); BLOCKING_NOTIFIER_HEAD(ubi_notifiers);
/** /**
......
/*
* 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 { ...@@ -149,10 +149,10 @@ enum {
* The @image_seq field is used to validate a UBI image that has been prepared * 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 * 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 * 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 * 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 * 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 { struct ubi_ec_hdr {
__be32 magic; __be32 magic;
...@@ -298,8 +298,8 @@ struct ubi_vid_hdr { ...@@ -298,8 +298,8 @@ struct ubi_vid_hdr {
#define UBI_INT_VOL_COUNT 1 #define UBI_INT_VOL_COUNT 1
/* /*
* Starting ID of internal volumes. There is reserved room for 4096 internal * Starting ID of internal volumes: 0x7fffefff.
* volumes. * There is reserved room for 4096 internal volumes.
*/ */
#define UBI_INTERNAL_VOL_START (0x7FFFFFFF - 4096) #define UBI_INTERNAL_VOL_START (0x7FFFFFFF - 4096)
......
...@@ -43,7 +43,6 @@ ...@@ -43,7 +43,6 @@
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include "ubi-media.h" #include "ubi-media.h"
#include "scan.h"
/* Maximum number of supported UBI devices */ /* Maximum number of supported UBI devices */
#define UBI_MAX_DEVICES 32 #define UBI_MAX_DEVICES 32
...@@ -66,7 +65,10 @@ ...@@ -66,7 +65,10 @@
/* Background thread name pattern */ /* Background thread name pattern */
#define UBI_BGT_NAME_PATTERN "ubi_bgt%dd" #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 #define UBI_LEB_UNMAPPED -1
/* /*
...@@ -82,6 +84,9 @@ ...@@ -82,6 +84,9 @@
*/ */
#define UBI_PROT_QUEUE_LEN 10 #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. * Error codes returned by the I/O sub-system.
* *
...@@ -222,8 +227,6 @@ struct ubi_volume_desc; ...@@ -222,8 +227,6 @@ struct ubi_volume_desc;
* @upd_ebs: how many eraseblocks are expected to be updated * @upd_ebs: how many eraseblocks are expected to be updated
* @ch_lnum: LEB number which is being changing by the atomic LEB change * @ch_lnum: LEB number which is being changing by the atomic LEB change
* operation * 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 * @upd_bytes: how many bytes are expected to be received for volume update or
* atomic LEB change * atomic LEB change
* @upd_received: how many bytes were already received for volume update or * @upd_received: how many bytes were already received for volume update or
...@@ -270,7 +273,6 @@ struct ubi_volume { ...@@ -270,7 +273,6 @@ struct ubi_volume {
int upd_ebs; int upd_ebs;
int ch_lnum; int ch_lnum;
int ch_dtype;
long long upd_bytes; long long upd_bytes;
long long upd_received; long long upd_received;
void *upd_buf; void *upd_buf;
...@@ -477,6 +479,124 @@ struct ubi_device { ...@@ -477,6 +479,124 @@ struct ubi_device {
struct ubi_debug_info *dbg; 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" #include "debug.h"
extern struct kmem_cache *ubi_wl_entry_slab; extern struct kmem_cache *ubi_wl_entry_slab;
...@@ -487,12 +607,23 @@ extern struct class *ubi_class; ...@@ -487,12 +607,23 @@ extern struct class *ubi_class;
extern struct mutex ubi_devices_mutex; extern struct mutex ubi_devices_mutex;
extern struct blocking_notifier_head ubi_notifiers; 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 */ /* vtbl.c */
int ubi_change_vtbl_record(struct ubi_device *ubi, int idx, int ubi_change_vtbl_record(struct ubi_device *ubi, int idx,
struct ubi_vtbl_record *vtbl_rec); struct ubi_vtbl_record *vtbl_rec);
int ubi_vtbl_rename_volumes(struct ubi_device *ubi, int ubi_vtbl_rename_volumes(struct ubi_device *ubi,
struct list_head *rename_list); 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 */ /* vmt.c */
int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req); 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, ...@@ -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, int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
void *buf, int offset, int len, int check); void *buf, int offset, int len, int check);
int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, 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 ubi_eba_write_leb_st(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 used_ebs);
int used_ebs);
int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol, 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, int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
struct ubi_vid_hdr *vid_hdr); 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 */ /* wl.c */
int ubi_wl_get_peb(struct ubi_device *ubi, int dtype); int ubi_wl_get_peb(struct ubi_device *ubi);
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 ubi_wl_flush(struct ubi_device *ubi); 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_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); void ubi_wl_close(struct ubi_device *ubi);
int ubi_thread(void *u); int ubi_thread(void *u);
...@@ -573,6 +704,7 @@ int ubi_volume_notify(struct ubi_device *ubi, struct ubi_volume *vol, ...@@ -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, int ubi_notify_all(struct ubi_device *ubi, int ntype,
struct notifier_block *nb); struct notifier_block *nb);
int ubi_enumerate_volumes(struct notifier_block *nb); int ubi_enumerate_volumes(struct notifier_block *nb);
void ubi_free_internal_volumes(struct ubi_device *ubi);
/* kapi.c */ /* kapi.c */
void ubi_do_get_device_info(struct ubi_device *ubi, struct ubi_device_info *di); 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, ...@@ -593,6 +725,21 @@ void ubi_do_get_volume_info(struct ubi_device *ubi, struct ubi_volume *vol,
rb = rb_next(rb), \ rb = rb_next(rb), \
pos = (rb ? container_of(rb, typeof(*pos), member) : NULL)) 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_zalloc_vid_hdr - allocate a volume identifier header object.
* @ubi: UBI device description object * @ubi: UBI device description object
...@@ -667,7 +814,7 @@ static inline void ubi_ro_mode(struct ubi_device *ubi) ...@@ -667,7 +814,7 @@ static inline void ubi_ro_mode(struct ubi_device *ubi)
if (!ubi->ro_mode) { if (!ubi->ro_mode) {
ubi->ro_mode = 1; ubi->ro_mode = 1;
ubi_warn("switch to read-only mode"); 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, ...@@ -147,7 +147,7 @@ int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol,
} }
if (bytes == 0) { if (bytes == 0) {
err = ubi_wl_flush(ubi); err = ubi_wl_flush(ubi, UBI_ALL, UBI_ALL);
if (err) if (err)
return err; return err;
...@@ -186,14 +186,12 @@ int ubi_start_leb_change(struct ubi_device *ubi, struct ubi_volume *vol, ...@@ -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", dbg_gen("start changing LEB %d:%d, %u bytes",
vol->vol_id, req->lnum, req->bytes); vol->vol_id, req->lnum, req->bytes);
if (req->bytes == 0) if (req->bytes == 0)
return ubi_eba_atomic_leb_change(ubi, vol, req->lnum, NULL, 0, return ubi_eba_atomic_leb_change(ubi, vol, req->lnum, NULL, 0);
req->dtype);
vol->upd_bytes = req->bytes; vol->upd_bytes = req->bytes;
vol->upd_received = 0; vol->upd_received = 0;
vol->changing_leb = 1; vol->changing_leb = 1;
vol->ch_lnum = req->lnum; vol->ch_lnum = req->lnum;
vol->ch_dtype = req->dtype;
vol->upd_buf = vmalloc(req->bytes); vol->upd_buf = vmalloc(req->bytes);
if (!vol->upd_buf) if (!vol->upd_buf)
...@@ -246,8 +244,7 @@ static int write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, ...@@ -246,8 +244,7 @@ static int write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
return 0; return 0;
} }
err = ubi_eba_write_leb(ubi, vol, lnum, buf, 0, len, err = ubi_eba_write_leb(ubi, vol, lnum, buf, 0, len);
UBI_UNKNOWN);
} else { } else {
/* /*
* When writing static volume, and this is the last logical * 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, ...@@ -259,8 +256,7 @@ static int write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
* contain zeros, not random trash. * contain zeros, not random trash.
*/ */
memset(buf + len, 0, vol->usable_leb_size - len); memset(buf + len, 0, vol->usable_leb_size - len);
err = ubi_eba_write_leb_st(ubi, vol, lnum, buf, len, err = ubi_eba_write_leb_st(ubi, vol, lnum, buf, len, used_ebs);
UBI_UNKNOWN, used_ebs);
} }
return err; return err;
...@@ -365,7 +361,7 @@ int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol, ...@@ -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); ubi_assert(vol->upd_received <= vol->upd_bytes);
if (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) if (err)
return err; return err;
/* The update is finished, clear the update marker */ /* 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, ...@@ -421,7 +417,7 @@ int ubi_more_leb_change_data(struct ubi_device *ubi, struct ubi_volume *vol,
len - vol->upd_bytes); len - vol->upd_bytes);
len = ubi_calc_data_len(ubi, vol->upd_buf, len); len = ubi_calc_data_len(ubi, vol->upd_buf, len);
err = ubi_eba_atomic_leb_change(ubi, vol, vol->ch_lnum, err = ubi_eba_atomic_leb_change(ubi, vol, vol->ch_lnum,
vol->upd_buf, len, UBI_UNKNOWN); vol->upd_buf, len);
if (err) if (err)
return err; return err;
} }
......
...@@ -29,11 +29,7 @@ ...@@ -29,11 +29,7 @@
#include <linux/export.h> #include <linux/export.h>
#include "ubi.h" #include "ubi.h"
#ifdef CONFIG_MTD_UBI_DEBUG static int self_check_volumes(struct ubi_device *ubi);
static int paranoid_check_volumes(struct ubi_device *ubi);
#else
#define paranoid_check_volumes(ubi) 0
#endif
static ssize_t vol_attribute_show(struct device *dev, static ssize_t vol_attribute_show(struct device *dev,
struct device_attribute *attr, char *buf); struct device_attribute *attr, char *buf);
...@@ -227,7 +223,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) ...@@ -227,7 +223,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
} }
if (vol_id == UBI_VOL_NUM_AUTO) { if (vol_id == UBI_VOL_NUM_AUTO) {
dbg_err("out of volume IDs"); ubi_err("out of volume IDs");
err = -ENFILE; err = -ENFILE;
goto out_unlock; goto out_unlock;
} }
...@@ -241,7 +237,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) ...@@ -241,7 +237,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
/* Ensure that this volume does not exist */ /* Ensure that this volume does not exist */
err = -EEXIST; err = -EEXIST;
if (ubi->volumes[vol_id]) { if (ubi->volumes[vol_id]) {
dbg_err("volume %d already exists", vol_id); ubi_err("volume %d already exists", vol_id);
goto out_unlock; goto out_unlock;
} }
...@@ -250,7 +246,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) ...@@ -250,7 +246,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
if (ubi->volumes[i] && if (ubi->volumes[i] &&
ubi->volumes[i]->name_len == req->name_len && ubi->volumes[i]->name_len == req->name_len &&
!strcmp(ubi->volumes[i]->name, req->name)) { !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; goto out_unlock;
} }
...@@ -261,9 +257,9 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) ...@@ -261,9 +257,9 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
/* Reserve physical eraseblocks */ /* Reserve physical eraseblocks */
if (vol->reserved_pebs > ubi->avail_pebs) { 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) 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); ubi->corr_peb_count);
err = -ENOSPC; err = -ENOSPC;
goto out_unlock; goto out_unlock;
...@@ -284,7 +280,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) ...@@ -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 * Finish all pending erases because there may be some LEBs belonging
* to the same volume ID. * to the same volume ID.
*/ */
err = ubi_wl_flush(ubi); err = ubi_wl_flush(ubi, vol_id, UBI_ALL);
if (err) if (err)
goto out_acc; goto out_acc;
...@@ -360,8 +356,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) ...@@ -360,8 +356,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
spin_unlock(&ubi->volumes_lock); spin_unlock(&ubi->volumes_lock);
ubi_volume_notify(ubi, vol, UBI_VOLUME_ADDED); ubi_volume_notify(ubi, vol, UBI_VOLUME_ADDED);
if (paranoid_check_volumes(ubi)) self_check_volumes(ubi);
dbg_err("check failed while creating volume %d", vol_id);
return err; return err;
out_sysfs: out_sysfs:
...@@ -461,8 +456,8 @@ int ubi_remove_volume(struct ubi_volume_desc *desc, int no_vtbl) ...@@ -461,8 +456,8 @@ int ubi_remove_volume(struct ubi_volume_desc *desc, int no_vtbl)
spin_unlock(&ubi->volumes_lock); spin_unlock(&ubi->volumes_lock);
ubi_volume_notify(ubi, vol, UBI_VOLUME_REMOVED); ubi_volume_notify(ubi, vol, UBI_VOLUME_REMOVED);
if (!no_vtbl && paranoid_check_volumes(ubi)) if (!no_vtbl)
dbg_err("check failed while removing volume %d", vol_id); self_check_volumes(ubi);
return err; return err;
...@@ -500,7 +495,7 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs) ...@@ -500,7 +495,7 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs)
if (vol->vol_type == UBI_STATIC_VOLUME && if (vol->vol_type == UBI_STATIC_VOLUME &&
reserved_pebs < vol->used_ebs) { 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); reserved_pebs, vol->used_ebs);
return -EINVAL; return -EINVAL;
} }
...@@ -529,10 +524,10 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs) ...@@ -529,10 +524,10 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs)
if (pebs > 0) { if (pebs > 0) {
spin_lock(&ubi->volumes_lock); spin_lock(&ubi->volumes_lock);
if (pebs > ubi->avail_pebs) { 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); pebs, ubi->avail_pebs);
if (ubi->corr_peb_count) 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); ubi->corr_peb_count);
spin_unlock(&ubi->volumes_lock); spin_unlock(&ubi->volumes_lock);
err = -ENOSPC; err = -ENOSPC;
...@@ -588,8 +583,7 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs) ...@@ -588,8 +583,7 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs)
} }
ubi_volume_notify(ubi, vol, UBI_VOLUME_RESIZED); ubi_volume_notify(ubi, vol, UBI_VOLUME_RESIZED);
if (paranoid_check_volumes(ubi)) self_check_volumes(ubi);
dbg_err("check failed while re-sizing volume %d", vol_id);
return err; return err;
out_acc: out_acc:
...@@ -638,8 +632,8 @@ int ubi_rename_volumes(struct ubi_device *ubi, struct list_head *rename_list) ...@@ -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; return err;
} }
...@@ -686,8 +680,7 @@ int ubi_add_volume(struct ubi_device *ubi, struct ubi_volume *vol) ...@@ -686,8 +680,7 @@ int ubi_add_volume(struct ubi_device *ubi, struct ubi_volume *vol)
return err; return err;
} }
if (paranoid_check_volumes(ubi)) self_check_volumes(ubi);
dbg_err("check failed while adding volume %d", vol_id);
return err; return err;
out_cdev: out_cdev:
...@@ -712,16 +705,14 @@ void ubi_free_volume(struct ubi_device *ubi, struct ubi_volume *vol) ...@@ -712,16 +705,14 @@ void ubi_free_volume(struct ubi_device *ubi, struct ubi_volume *vol)
volume_sysfs_close(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 * @ubi: UBI device description object
* @vol_id: volume ID * @vol_id: volume ID
* *
* Returns zero if volume is all right and a a negative error code if not. * 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 idx = vol_id2idx(ubi, vol_id);
int reserved_pebs, alignment, data_pad, vol_type, name_len, upd_marker; 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) ...@@ -771,7 +762,7 @@ static int paranoid_check_volume(struct ubi_device *ubi, int vol_id)
} }
if (vol->upd_marker && vol->corrupted) { if (vol->upd_marker && vol->corrupted) {
dbg_err("update marker and corrupted simultaneously"); ubi_err("update marker and corrupted simultaneously");
goto fail; goto fail;
} }
...@@ -853,22 +844,22 @@ static int paranoid_check_volume(struct ubi_device *ubi, int vol_id) ...@@ -853,22 +844,22 @@ static int paranoid_check_volume(struct ubi_device *ubi, int vol_id)
return 0; return 0;
fail: fail:
ubi_err("paranoid check failed for volume %d", vol_id); ubi_err("self-check failed for volume %d", vol_id);
if (vol) if (vol)
ubi_dbg_dump_vol_info(vol); ubi_dump_vol_info(vol);
ubi_dbg_dump_vtbl_record(&ubi->vtbl[vol_id], vol_id); ubi_dump_vtbl_record(&ubi->vtbl[vol_id], vol_id);
dump_stack(); dump_stack();
spin_unlock(&ubi->volumes_lock); spin_unlock(&ubi->volumes_lock);
return -EINVAL; return -EINVAL;
} }
/** /**
* paranoid_check_volumes - check information about all volumes. * self_check_volumes - check information about all volumes.
* @ubi: UBI device description object * @ubi: UBI device description object
* *
* Returns zero if volumes are all right and a a negative error code if not. * 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; int i, err = 0;
...@@ -876,11 +867,10 @@ static int paranoid_check_volumes(struct ubi_device *ubi) ...@@ -876,11 +867,10 @@ static int paranoid_check_volumes(struct ubi_device *ubi)
return 0; return 0;
for (i = 0; i < ubi->vtbl_slots; i++) { for (i = 0; i < ubi->vtbl_slots; i++) {
err = paranoid_check_volume(ubi, i); err = self_check_volume(ubi, i);
if (err) if (err)
break; break;
} }
return err; return err;
} }
#endif
...@@ -37,16 +37,15 @@ ...@@ -37,16 +37,15 @@
* LEB 1. This scheme guarantees recoverability from unclean reboots. * LEB 1. This scheme guarantees recoverability from unclean reboots.
* *
* In this UBI implementation the on-flash volume table does not contain any * In this UBI implementation the on-flash volume table does not contain any
* information about how many data static volumes contain. This information may * information about how much data static volumes contain.
* be found from the scanning data.
* *
* But it would still be beneficial to store this information in the volume * 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 * 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 * 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 * 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 * 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 * 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 * volume updates. Before updating the volume, the update marker is set, and
...@@ -62,11 +61,7 @@ ...@@ -62,11 +61,7 @@
#include <asm/div64.h> #include <asm/div64.h>
#include "ubi.h" #include "ubi.h"
#ifdef CONFIG_MTD_UBI_DEBUG static void self_vtbl_check(const struct ubi_device *ubi);
static void paranoid_vtbl_check(const struct ubi_device *ubi);
#else
#define paranoid_vtbl_check(ubi)
#endif
/* Empty volume table record */ /* Empty volume table record */
static struct ubi_vtbl_record empty_vtbl_record; static struct ubi_vtbl_record empty_vtbl_record;
...@@ -106,12 +101,12 @@ int ubi_change_vtbl_record(struct ubi_device *ubi, int idx, ...@@ -106,12 +101,12 @@ int ubi_change_vtbl_record(struct ubi_device *ubi, int idx,
return err; return err;
err = ubi_eba_write_leb(ubi, layout_vol, i, ubi->vtbl, 0, err = ubi_eba_write_leb(ubi, layout_vol, i, ubi->vtbl, 0,
ubi->vtbl_size, UBI_LONGTERM); ubi->vtbl_size);
if (err) if (err)
return err; return err;
} }
paranoid_vtbl_check(ubi); self_vtbl_check(ubi);
return 0; return 0;
} }
...@@ -158,7 +153,7 @@ int ubi_vtbl_rename_volumes(struct ubi_device *ubi, ...@@ -158,7 +153,7 @@ int ubi_vtbl_rename_volumes(struct ubi_device *ubi,
return err; return err;
err = ubi_eba_write_leb(ubi, layout_vol, i, ubi->vtbl, 0, err = ubi_eba_write_leb(ubi, layout_vol, i, ubi->vtbl, 0,
ubi->vtbl_size, UBI_LONGTERM); ubi->vtbl_size);
if (err) if (err)
return err; return err;
} }
...@@ -197,7 +192,7 @@ static int vtbl_check(const struct ubi_device *ubi, ...@@ -197,7 +192,7 @@ static int vtbl_check(const struct ubi_device *ubi,
if (be32_to_cpu(vtbl[i].crc) != crc) { if (be32_to_cpu(vtbl[i].crc) != crc) {
ubi_err("bad CRC at record %u: %#08x, not %#08x", ubi_err("bad CRC at record %u: %#08x, not %#08x",
i, crc, be32_to_cpu(vtbl[i].crc)); 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; return 1;
} }
...@@ -229,7 +224,7 @@ static int vtbl_check(const struct ubi_device *ubi, ...@@ -229,7 +224,7 @@ static int vtbl_check(const struct ubi_device *ubi,
n = ubi->leb_size % alignment; n = ubi->leb_size % alignment;
if (data_pad != n) { 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; err = 6;
goto bad; goto bad;
} }
...@@ -245,7 +240,7 @@ static int vtbl_check(const struct ubi_device *ubi, ...@@ -245,7 +240,7 @@ static int vtbl_check(const struct ubi_device *ubi,
} }
if (reserved_pebs > ubi->good_peb_count) { 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); reserved_pebs, ubi->good_peb_count);
err = 9; err = 9;
goto bad; goto bad;
...@@ -277,8 +272,8 @@ static int vtbl_check(const struct ubi_device *ubi, ...@@ -277,8 +272,8 @@ static int vtbl_check(const struct ubi_device *ubi,
!strncmp(vtbl[i].name, vtbl[n].name, len1)) { !strncmp(vtbl[i].name, vtbl[n].name, len1)) {
ubi_err("volumes %d and %d have the same name" ubi_err("volumes %d and %d have the same name"
" \"%s\"", i, n, vtbl[i].name); " \"%s\"", i, n, vtbl[i].name);
ubi_dbg_dump_vtbl_record(&vtbl[i], i); ubi_dump_vtbl_record(&vtbl[i], i);
ubi_dbg_dump_vtbl_record(&vtbl[n], n); ubi_dump_vtbl_record(&vtbl[n], n);
return -EINVAL; return -EINVAL;
} }
} }
...@@ -288,26 +283,26 @@ static int vtbl_check(const struct ubi_device *ubi, ...@@ -288,26 +283,26 @@ static int vtbl_check(const struct ubi_device *ubi,
bad: bad:
ubi_err("volume table check failed: record %d, error %d", i, err); 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; return -EINVAL;
} }
/** /**
* create_vtbl - create a copy of volume table. * create_vtbl - create a copy of volume table.
* @ubi: UBI device description object * @ubi: UBI device description object
* @si: scanning information * @ai: attaching information
* @copy: number of the volume table copy * @copy: number of the volume table copy
* @vtbl: contents of the volume table * @vtbl: contents of the volume table
* *
* This function returns zero in case of success and a negative error code in * This function returns zero in case of success and a negative error code in
* case of failure. * 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 copy, void *vtbl)
{ {
int err, tries = 0; int err, tries = 0;
struct ubi_vid_hdr *vid_hdr; 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); 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, ...@@ -316,9 +311,9 @@ static int create_vtbl(struct ubi_device *ubi, struct ubi_scan_info *si,
return -ENOMEM; return -ENOMEM;
retry: retry:
new_seb = ubi_scan_get_free_peb(ubi, si); new_aeb = ubi_early_get_peb(ubi, ai);
if (IS_ERR(new_seb)) { if (IS_ERR(new_aeb)) {
err = PTR_ERR(new_seb); err = PTR_ERR(new_aeb);
goto out_free; goto out_free;
} }
...@@ -328,25 +323,24 @@ static int create_vtbl(struct ubi_device *ubi, struct ubi_scan_info *si, ...@@ -328,25 +323,24 @@ static int create_vtbl(struct ubi_device *ubi, struct ubi_scan_info *si,
vid_hdr->data_size = vid_hdr->used_ebs = vid_hdr->data_size = vid_hdr->used_ebs =
vid_hdr->data_pad = cpu_to_be32(0); vid_hdr->data_pad = cpu_to_be32(0);
vid_hdr->lnum = cpu_to_be32(copy); 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 */ /* 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) if (err)
goto write_error; goto write_error;
/* Write the layout volume contents */ /* 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) if (err)
goto write_error; goto write_error;
/* /*
* And add it to the scanning information. Don't delete the old version * 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_scan_add_used()'. * 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, err = ubi_add_to_av(ubi, ai, new_aeb->pnum, new_aeb->ec, vid_hdr, 0);
vid_hdr, 0); kfree(new_aeb);
kfree(new_seb);
ubi_free_vid_hdr(ubi, vid_hdr); ubi_free_vid_hdr(ubi, vid_hdr);
return err; return err;
...@@ -356,10 +350,10 @@ static int create_vtbl(struct ubi_device *ubi, struct ubi_scan_info *si, ...@@ -356,10 +350,10 @@ static int create_vtbl(struct ubi_device *ubi, struct ubi_scan_info *si,
* Probably this physical eraseblock went bad, try to pick * Probably this physical eraseblock went bad, try to pick
* another one. * another one.
*/ */
list_add(&new_seb->u.list, &si->erase); list_add(&new_aeb->u.list, &ai->erase);
goto retry; goto retry;
} }
kfree(new_seb); kfree(new_aeb);
out_free: out_free:
ubi_free_vid_hdr(ubi, vid_hdr); ubi_free_vid_hdr(ubi, vid_hdr);
return err; return err;
...@@ -369,20 +363,20 @@ static int create_vtbl(struct ubi_device *ubi, struct ubi_scan_info *si, ...@@ -369,20 +363,20 @@ static int create_vtbl(struct ubi_device *ubi, struct ubi_scan_info *si,
/** /**
* process_lvol - process the layout volume. * process_lvol - process the layout volume.
* @ubi: UBI device description object * @ubi: UBI device description object
* @si: scanning information * @ai: attaching information
* @sv: layout volume scanning information * @av: layout volume attaching information
* *
* This function is responsible for reading the layout volume, ensuring it is * This function is responsible for reading the layout volume, ensuring it is
* not corrupted, and recovering from corruptions if needed. Returns volume * not corrupted, and recovering from corruptions if needed. Returns volume
* table in case of success and a negative error code in case of failure. * 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, static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi,
struct ubi_scan_info *si, struct ubi_attach_info *ai,
struct ubi_scan_volume *sv) struct ubi_ainf_volume *av)
{ {
int err; int err;
struct rb_node *rb; 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 }; struct ubi_vtbl_record *leb[UBI_LAYOUT_VOLUME_EBS] = { NULL, NULL };
int leb_corrupted[UBI_LAYOUT_VOLUME_EBS] = {1, 1}; int leb_corrupted[UBI_LAYOUT_VOLUME_EBS] = {1, 1};
...@@ -414,14 +408,14 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi, ...@@ -414,14 +408,14 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi,
dbg_gen("check layout volume"); dbg_gen("check layout volume");
/* Read both LEB 0 and LEB 1 into memory */ /* Read both LEB 0 and LEB 1 into memory */
ubi_rb_for_each_entry(rb, seb, &sv->root, u.rb) { ubi_rb_for_each_entry(rb, aeb, &av->root, u.rb) {
leb[seb->lnum] = vzalloc(ubi->vtbl_size); leb[aeb->lnum] = vzalloc(ubi->vtbl_size);
if (!leb[seb->lnum]) { if (!leb[aeb->lnum]) {
err = -ENOMEM; err = -ENOMEM;
goto out_free; 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); ubi->vtbl_size);
if (err == UBI_IO_BITFLIPS || mtd_is_eccerr(err)) if (err == UBI_IO_BITFLIPS || mtd_is_eccerr(err))
/* /*
...@@ -429,12 +423,12 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi, ...@@ -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 * uncorrectable ECC error, but we have our own CRC and
* the data will be checked later. If the data is OK, * the data will be checked later. If the data is OK,
* the PEB will be scrubbed (because we set * 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 * the PEB will be recovered from the second copy, and
* seb->scrub will be cleared in * aeb->scrub will be cleared in
* 'ubi_scan_add_used()'. * 'ubi_add_to_av()'.
*/ */
seb->scrub = 1; aeb->scrub = 1;
else if (err) else if (err)
goto out_free; goto out_free;
} }
...@@ -453,7 +447,7 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi, ...@@ -453,7 +447,7 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi,
ubi->vtbl_size); ubi->vtbl_size);
if (leb_corrupted[1]) { if (leb_corrupted[1]) {
ubi_warn("volume table copy #2 is corrupted"); 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) if (err)
goto out_free; goto out_free;
ubi_msg("volume table was restored"); ubi_msg("volume table was restored");
...@@ -476,7 +470,7 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi, ...@@ -476,7 +470,7 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi,
} }
ubi_warn("volume table copy #1 is corrupted"); 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) if (err)
goto out_free; goto out_free;
ubi_msg("volume table was restored"); ubi_msg("volume table was restored");
...@@ -494,13 +488,13 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi, ...@@ -494,13 +488,13 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi,
/** /**
* create_empty_lvol - create empty layout volume. * create_empty_lvol - create empty layout volume.
* @ubi: UBI device description object * @ubi: UBI device description object
* @si: scanning information * @ai: attaching information
* *
* This function returns volume table contents in case of success and a * This function returns volume table contents in case of success and a
* negative error code in case of failure. * negative error code in case of failure.
*/ */
static struct ubi_vtbl_record *create_empty_lvol(struct ubi_device *ubi, static struct ubi_vtbl_record *create_empty_lvol(struct ubi_device *ubi,
struct ubi_scan_info *si) struct ubi_attach_info *ai)
{ {
int i; int i;
struct ubi_vtbl_record *vtbl; struct ubi_vtbl_record *vtbl;
...@@ -515,7 +509,7 @@ static struct ubi_vtbl_record *create_empty_lvol(struct ubi_device *ubi, ...@@ -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++) { for (i = 0; i < UBI_LAYOUT_VOLUME_EBS; i++) {
int err; int err;
err = create_vtbl(ubi, si, i, vtbl); err = create_vtbl(ubi, ai, i, vtbl);
if (err) { if (err) {
vfree(vtbl); vfree(vtbl);
return ERR_PTR(err); return ERR_PTR(err);
...@@ -528,18 +522,19 @@ static struct ubi_vtbl_record *create_empty_lvol(struct ubi_device *ubi, ...@@ -528,18 +522,19 @@ static struct ubi_vtbl_record *create_empty_lvol(struct ubi_device *ubi,
/** /**
* init_volumes - initialize volume information for existing volumes. * init_volumes - initialize volume information for existing volumes.
* @ubi: UBI device description object * @ubi: UBI device description object
* @si: scanning information * @ai: scanning information
* @vtbl: volume table * @vtbl: volume table
* *
* This function allocates volume description objects for existing volumes. * This function allocates volume description objects for existing volumes.
* Returns zero in case of success and a negative error code in case of * Returns zero in case of success and a negative error code in case of
* failure. * 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) const struct ubi_vtbl_record *vtbl)
{ {
int i, reserved_pebs = 0; int i, reserved_pebs = 0;
struct ubi_scan_volume *sv; struct ubi_ainf_volume *av;
struct ubi_volume *vol; struct ubi_volume *vol;
for (i = 0; i < ubi->vtbl_slots; i++) { 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, ...@@ -595,8 +590,8 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si,
} }
/* Static volumes only */ /* Static volumes only */
sv = ubi_scan_find_sv(si, i); av = ubi_find_av(ai, i);
if (!sv) { if (!av) {
/* /*
* No eraseblocks belonging to this volume found. We * No eraseblocks belonging to this volume found. We
* don't actually know whether this static volume is * 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, ...@@ -608,22 +603,22 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si,
continue; continue;
} }
if (sv->leb_count != sv->used_ebs) { if (av->leb_count != av->used_ebs) {
/* /*
* We found a static volume which misses several * We found a static volume which misses several
* eraseblocks. Treat it as corrupted. * eraseblocks. Treat it as corrupted.
*/ */
ubi_warn("static volume %d misses %d LEBs - 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; vol->corrupted = 1;
continue; continue;
} }
vol->used_ebs = sv->used_ebs; vol->used_ebs = av->used_ebs;
vol->used_bytes = vol->used_bytes =
(long long)(vol->used_ebs - 1) * vol->usable_leb_size; (long long)(vol->used_ebs - 1) * vol->usable_leb_size;
vol->used_bytes += sv->last_data_size; vol->used_bytes += av->last_data_size;
vol->last_eb_bytes = sv->last_data_size; vol->last_eb_bytes = av->last_data_size;
} }
/* And add the layout volume */ /* And add the layout volume */
...@@ -664,105 +659,104 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si, ...@@ -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 * @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. * to the data read from the volume tabla, and %-EINVAL if not.
*/ */
static int check_sv(const struct ubi_volume *vol, static int check_av(const struct ubi_volume *vol,
const struct ubi_scan_volume *sv) const struct ubi_ainf_volume *av)
{ {
int err; int err;
if (sv->highest_lnum >= vol->reserved_pebs) { if (av->highest_lnum >= vol->reserved_pebs) {
err = 1; err = 1;
goto bad; goto bad;
} }
if (sv->leb_count > vol->reserved_pebs) { if (av->leb_count > vol->reserved_pebs) {
err = 2; err = 2;
goto bad; goto bad;
} }
if (sv->vol_type != vol->vol_type) { if (av->vol_type != vol->vol_type) {
err = 3; err = 3;
goto bad; goto bad;
} }
if (sv->used_ebs > vol->reserved_pebs) { if (av->used_ebs > vol->reserved_pebs) {
err = 4; err = 4;
goto bad; goto bad;
} }
if (sv->data_pad != vol->data_pad) { if (av->data_pad != vol->data_pad) {
err = 5; err = 5;
goto bad; goto bad;
} }
return 0; return 0;
bad: bad:
ubi_err("bad scanning information, error %d", err); ubi_err("bad attaching information, error %d", err);
ubi_dbg_dump_sv(sv); ubi_dump_av(av);
ubi_dbg_dump_vol_info(vol); ubi_dump_vol_info(vol);
return -EINVAL; return -EINVAL;
} }
/** /**
* check_scanning_info - check that scanning information. * check_attaching_info - check that attaching information.
* @ubi: UBI device description object * @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 * 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 media. This function ensures that attaching information is consistent to
* the information read from the volume table. Returns zero if the scanning * the information read from the volume table. Returns zero if the attaching
* information is OK and %-EINVAL if it is not. * information is OK and %-EINVAL if it is not.
*/ */
static int check_scanning_info(const struct ubi_device *ubi, static int check_attaching_info(const struct ubi_device *ubi,
struct ubi_scan_info *si) struct ubi_attach_info *ai)
{ {
int err, i; int err, i;
struct ubi_scan_volume *sv; struct ubi_ainf_volume *av;
struct ubi_volume *vol; struct ubi_volume *vol;
if (si->vols_found > UBI_INT_VOL_COUNT + ubi->vtbl_slots) { if (ai->vols_found > UBI_INT_VOL_COUNT + ubi->vtbl_slots) {
ubi_err("scanning found %d volumes, maximum is %d + %d", ubi_err("found %d volumes while attaching, maximum is %d + %d",
si->vols_found, UBI_INT_VOL_COUNT, ubi->vtbl_slots); ai->vols_found, UBI_INT_VOL_COUNT, ubi->vtbl_slots);
return -EINVAL; return -EINVAL;
} }
if (si->highest_vol_id >= ubi->vtbl_slots + UBI_INT_VOL_COUNT && if (ai->highest_vol_id >= ubi->vtbl_slots + UBI_INT_VOL_COUNT &&
si->highest_vol_id < UBI_INTERNAL_VOL_START) { ai->highest_vol_id < UBI_INTERNAL_VOL_START) {
ubi_err("too large volume ID %d found by scanning", ubi_err("too large volume ID %d found", ai->highest_vol_id);
si->highest_vol_id);
return -EINVAL; return -EINVAL;
} }
for (i = 0; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) { for (i = 0; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) {
cond_resched(); cond_resched();
sv = ubi_scan_find_sv(si, i); av = ubi_find_av(ai, i);
vol = ubi->volumes[i]; vol = ubi->volumes[i];
if (!vol) { if (!vol) {
if (sv) if (av)
ubi_scan_rm_volume(si, sv); ubi_remove_av(ai, av);
continue; continue;
} }
if (vol->reserved_pebs == 0) { if (vol->reserved_pebs == 0) {
ubi_assert(i < ubi->vtbl_slots); ubi_assert(i < ubi->vtbl_slots);
if (!sv) if (!av)
continue; 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 * exist according to the information in the volume
* table. This must have happened due to an unclean * table. This must have happened due to an unclean
* reboot while the volume was being removed. Discard * reboot while the volume was being removed. Discard
* these eraseblocks. * these eraseblocks.
*/ */
ubi_msg("finish volume %d removal", sv->vol_id); ubi_msg("finish volume %d removal", av->vol_id);
ubi_scan_rm_volume(si, sv); ubi_remove_av(ai, av);
} else if (sv) { } else if (av) {
err = check_sv(vol, sv); err = check_av(vol, av);
if (err) if (err)
return err; return err;
} }
...@@ -774,16 +768,16 @@ static int check_scanning_info(const struct ubi_device *ubi, ...@@ -774,16 +768,16 @@ static int check_scanning_info(const struct ubi_device *ubi,
/** /**
* ubi_read_volume_table - read the volume table. * ubi_read_volume_table - read the volume table.
* @ubi: UBI device description object * @ubi: UBI device description object
* @si: scanning information * @ai: attaching information
* *
* This function reads volume table, checks it, recover from errors if needed, * 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 * or creates it if needed. Returns zero in case of success and a negative
* error code in case of failure. * 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; int i, err;
struct ubi_scan_volume *sv; struct ubi_ainf_volume *av;
empty_vtbl_record.crc = cpu_to_be32(0xf116c36b); 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) ...@@ -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 = ubi->vtbl_slots * UBI_VTBL_RECORD_SIZE;
ubi->vtbl_size = ALIGN(ubi->vtbl_size, ubi->min_io_size); ubi->vtbl_size = ALIGN(ubi->vtbl_size, ubi->min_io_size);
sv = ubi_scan_find_sv(si, UBI_LAYOUT_VOLUME_ID); av = ubi_find_av(ai, UBI_LAYOUT_VOLUME_ID);
if (!sv) { if (!av) {
/* /*
* No logical eraseblocks belonging to the layout volume were * No logical eraseblocks belonging to the layout volume were
* found. This could mean that the flash is just empty. In * 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) ...@@ -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 * But if flash is not empty this must be a corruption or the
* MTD device just contains garbage. * MTD device just contains garbage.
*/ */
if (si->is_empty) { if (ai->is_empty) {
ubi->vtbl = create_empty_lvol(ubi, si); ubi->vtbl = create_empty_lvol(ubi, ai);
if (IS_ERR(ubi->vtbl)) if (IS_ERR(ubi->vtbl))
return PTR_ERR(ubi->vtbl); return PTR_ERR(ubi->vtbl);
} else { } else {
...@@ -817,14 +811,14 @@ int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si) ...@@ -817,14 +811,14 @@ int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si)
return -EINVAL; return -EINVAL;
} }
} else { } 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 */ /* This must not happen with proper UBI images */
dbg_err("too many LEBs (%d) in layout volume", ubi_err("too many LEBs (%d) in layout volume",
sv->leb_count); av->leb_count);
return -EINVAL; return -EINVAL;
} }
ubi->vtbl = process_lvol(ubi, si, sv); ubi->vtbl = process_lvol(ubi, ai, av);
if (IS_ERR(ubi->vtbl)) if (IS_ERR(ubi->vtbl))
return PTR_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) ...@@ -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 * The layout volume is OK, initialize the corresponding in-RAM data
* structures. * structures.
*/ */
err = init_volumes(ubi, si, ubi->vtbl); err = init_volumes(ubi, ai, ubi->vtbl);
if (err) if (err)
goto out_free; 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. * information stored in the volume table.
*/ */
err = check_scanning_info(ubi, si); err = check_attaching_info(ubi, ai);
if (err) if (err)
goto out_free; goto out_free;
...@@ -858,21 +852,17 @@ int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si) ...@@ -858,21 +852,17 @@ int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si)
return err; return err;
} }
#ifdef CONFIG_MTD_UBI_DEBUG
/** /**
* paranoid_vtbl_check - check volume table. * self_vtbl_check - check volume table.
* @ubi: UBI device description object * @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) if (!ubi->dbg->chk_gen)
return; return;
if (vtbl_check(ubi, ubi->vtbl)) { if (vtbl_check(ubi, ubi->vtbl)) {
ubi_err("paranoid check failed"); ubi_err("self-check failed");
BUG(); BUG();
} }
} }
#endif /* CONFIG_MTD_UBI_DEBUG */
此差异已折叠。
...@@ -11,12 +11,6 @@ config UBIFS_FS ...@@ -11,12 +11,6 @@ config UBIFS_FS
help help
UBIFS is a file system for flash devices which works on top of UBI. 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 config UBIFS_FS_ADVANCED_COMPR
bool "Advanced compression options" bool "Advanced compression options"
depends on UBIFS_FS depends on UBIFS_FS
...@@ -41,20 +35,3 @@ config UBIFS_FS_ZLIB ...@@ -41,20 +35,3 @@ config UBIFS_FS_ZLIB
default y default y
help help
Zlib compresses better than LZO but it is slower. Say 'Y' if unsure. 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 ...@@ -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 += 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 += 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 += 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-y += recovery.o ioctl.o lpt_commit.o tnc_misc.o xattr.o debug.o
ubifs-$(CONFIG_UBIFS_FS_DEBUG) += debug.o
ubifs-$(CONFIG_UBIFS_FS_XATTR) += xattr.o
...@@ -496,7 +496,9 @@ int ubifs_gc_should_commit(struct ubifs_info *c) ...@@ -496,7 +496,9 @@ int ubifs_gc_should_commit(struct ubifs_info *c)
return ret; return ret;
} }
#ifdef CONFIG_UBIFS_FS_DEBUG /*
* Everything below is related to debugging.
*/
/** /**
* struct idx_node - hold index nodes during index tree traversal. * struct idx_node - hold index nodes during index tree traversal.
...@@ -714,14 +716,14 @@ int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot) ...@@ -714,14 +716,14 @@ int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot)
return 0; return 0;
out_dump: out_dump:
dbg_err("dumping index node (iip=%d)", i->iip); ubifs_err("dumping index node (iip=%d)", i->iip);
dbg_dump_node(c, idx); ubifs_dump_node(c, idx);
list_del(&i->list); list_del(&i->list);
kfree(i); kfree(i);
if (!list_empty(&list)) { if (!list_empty(&list)) {
i = list_entry(list.prev, struct idx_node, list); i = list_entry(list.prev, struct idx_node, list);
dbg_err("dumping parent index node"); ubifs_err("dumping parent index node");
dbg_dump_node(c, &i->idx); ubifs_dump_node(c, &i->idx);
} }
out_free: out_free:
while (!list_empty(&list)) { while (!list_empty(&list)) {
...@@ -734,5 +736,3 @@ int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot) ...@@ -734,5 +736,3 @@ int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot)
err = -EINVAL; err = -EINVAL;
return err; return err;
} }
#endif /* CONFIG_UBIFS_FS_DEBUG */
此差异已折叠。
...@@ -29,8 +29,6 @@ typedef int (*dbg_leaf_callback)(struct ubifs_info *c, ...@@ -29,8 +29,6 @@ typedef int (*dbg_leaf_callback)(struct ubifs_info *c,
typedef int (*dbg_znode_callback)(struct ubifs_info *c, typedef int (*dbg_znode_callback)(struct ubifs_info *c,
struct ubifs_znode *znode, void *priv); struct ubifs_znode *znode, void *priv);
#ifdef CONFIG_UBIFS_FS_DEBUG
/* /*
* The UBIFS debugfs directory name pattern and maximum name length (3 for "ubi" * 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. * + 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 { ...@@ -149,7 +147,7 @@ struct ubifs_global_debug_info {
if (unlikely(!(expr))) { \ if (unlikely(!(expr))) { \
printk(KERN_CRIT "UBIFS assert failed in %s at %u (pid %d)\n", \ printk(KERN_CRIT "UBIFS assert failed in %s at %u (pid %d)\n", \
__func__, __LINE__, current->pid); \ __func__, __LINE__, current->pid); \
dbg_dump_stack(); \ dump_stack(); \
} \ } \
} while (0) } while (0)
...@@ -161,12 +159,6 @@ struct ubifs_global_debug_info { ...@@ -161,12 +159,6 @@ struct ubifs_global_debug_info {
} \ } \
} while (0) } 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, ...) \ #define ubifs_dbg_msg(type, fmt, ...) \
pr_debug("UBIFS DBG " type ": " fmt "\n", ##__VA_ARGS__) pr_debug("UBIFS DBG " type ": " fmt "\n", ##__VA_ARGS__)
...@@ -257,27 +249,27 @@ const char *dbg_get_key_dump(const struct ubifs_info *c, ...@@ -257,27 +249,27 @@ const char *dbg_get_key_dump(const struct ubifs_info *c,
const union ubifs_key *key); const union ubifs_key *key);
const char *dbg_snprintf_key(const struct ubifs_info *c, const char *dbg_snprintf_key(const struct ubifs_info *c,
const union ubifs_key *key, char *buffer, int len); const union ubifs_key *key, char *buffer, int 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);
void dbg_dump_node(const struct ubifs_info *c, const void *node); void ubifs_dump_node(const struct ubifs_info *c, const void *node);
void dbg_dump_lpt_node(const struct ubifs_info *c, void *node, int lnum, void ubifs_dump_budget_req(const struct ubifs_budget_req *req);
int offs); void ubifs_dump_lstats(const struct ubifs_lp_stats *lst);
void dbg_dump_budget_req(const struct ubifs_budget_req *req); void ubifs_dump_budg(struct ubifs_info *c, const struct ubifs_budg_info *bi);
void dbg_dump_lstats(const struct ubifs_lp_stats *lst); void ubifs_dump_lprop(const struct ubifs_info *c,
void dbg_dump_budg(struct ubifs_info *c, const struct ubifs_budg_info *bi); const struct ubifs_lprops *lp);
void dbg_dump_lprop(const struct ubifs_info *c, const struct ubifs_lprops *lp); void ubifs_dump_lprops(struct ubifs_info *c);
void dbg_dump_lprops(struct ubifs_info *c); void ubifs_dump_lpt_info(struct ubifs_info *c);
void dbg_dump_lpt_info(struct ubifs_info *c); void ubifs_dump_leb(const struct ubifs_info *c, int lnum);
void dbg_dump_leb(const struct ubifs_info *c, int lnum); void ubifs_dump_sleb(const struct ubifs_info *c,
void dbg_dump_sleb(const struct ubifs_info *c,
const struct ubifs_scan_leb *sleb, int offs); const struct ubifs_scan_leb *sleb, int offs);
void dbg_dump_znode(const struct ubifs_info *c, void ubifs_dump_znode(const struct ubifs_info *c,
const struct ubifs_znode *znode); const struct ubifs_znode *znode);
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,
void dbg_dump_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode, int cat);
void ubifs_dump_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode,
struct ubifs_nnode *parent, int iip); struct ubifs_nnode *parent, int iip);
void dbg_dump_tnc(struct ubifs_info *c); void ubifs_dump_tnc(struct ubifs_info *c);
void dbg_dump_index(struct ubifs_info *c); void ubifs_dump_index(struct ubifs_info *c);
void dbg_dump_lpt_lebs(const 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, int dbg_walk_index(struct ubifs_info *c, dbg_leaf_callback leaf_cb,
dbg_znode_callback znode_cb, void *priv); 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); ...@@ -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_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 dbg_leb_write(struct ubifs_info *c, int lnum, const void *buf, int offs,
int len, int dtype); int len);
int dbg_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len, int dbg_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len);
int dtype);
int dbg_leb_unmap(struct ubifs_info *c, int lnum); 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 */ /* Debugfs-related stuff */
int dbg_debugfs_init(void); int dbg_debugfs_init(void);
...@@ -319,162 +310,4 @@ void dbg_debugfs_exit(void); ...@@ -319,162 +310,4 @@ void dbg_debugfs_exit(void);
int dbg_debugfs_init_fs(struct ubifs_info *c); int dbg_debugfs_init_fs(struct ubifs_info *c);
void dbg_debugfs_exit_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__ */ #endif /* !__UBIFS_DEBUG_H__ */
...@@ -170,8 +170,6 @@ struct inode *ubifs_new_inode(struct ubifs_info *c, const struct inode *dir, ...@@ -170,8 +170,6 @@ struct inode *ubifs_new_inode(struct ubifs_info *c, const struct inode *dir,
return inode; return inode;
} }
#ifdef CONFIG_UBIFS_FS_DEBUG
static int dbg_check_name(const struct ubifs_info *c, static int dbg_check_name(const struct ubifs_info *c,
const struct ubifs_dent_node *dent, const struct ubifs_dent_node *dent,
const struct qstr *nm) const struct qstr *nm)
...@@ -185,12 +183,6 @@ static int dbg_check_name(const struct ubifs_info *c, ...@@ -185,12 +183,6 @@ static int dbg_check_name(const struct ubifs_info *c,
return 0; return 0;
} }
#else
#define dbg_check_name(c, dent, nm) 0
#endif
static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry, static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry,
struct nameidata *nd) struct nameidata *nd)
{ {
...@@ -1187,12 +1179,10 @@ const struct inode_operations ubifs_dir_inode_operations = { ...@@ -1187,12 +1179,10 @@ const struct inode_operations ubifs_dir_inode_operations = {
.rename = ubifs_rename, .rename = ubifs_rename,
.setattr = ubifs_setattr, .setattr = ubifs_setattr,
.getattr = ubifs_getattr, .getattr = ubifs_getattr,
#ifdef CONFIG_UBIFS_FS_XATTR
.setxattr = ubifs_setxattr, .setxattr = ubifs_setxattr,
.getxattr = ubifs_getxattr, .getxattr = ubifs_getxattr,
.listxattr = ubifs_listxattr, .listxattr = ubifs_listxattr,
.removexattr = ubifs_removexattr, .removexattr = ubifs_removexattr,
#endif
}; };
const struct file_operations ubifs_dir_operations = { const struct file_operations ubifs_dir_operations = {
......
...@@ -97,7 +97,7 @@ static int read_block(struct inode *inode, void *addr, unsigned int block, ...@@ -97,7 +97,7 @@ static int read_block(struct inode *inode, void *addr, unsigned int block,
dump: dump:
ubifs_err("bad data node (block %u, inode %lu)", ubifs_err("bad data node (block %u, inode %lu)",
block, inode->i_ino); block, inode->i_ino);
dbg_dump_node(c, dn); ubifs_dump_node(c, dn);
return -EINVAL; return -EINVAL;
} }
...@@ -1562,12 +1562,10 @@ const struct address_space_operations ubifs_file_address_operations = { ...@@ -1562,12 +1562,10 @@ const struct address_space_operations ubifs_file_address_operations = {
const struct inode_operations ubifs_file_inode_operations = { const struct inode_operations ubifs_file_inode_operations = {
.setattr = ubifs_setattr, .setattr = ubifs_setattr,
.getattr = ubifs_getattr, .getattr = ubifs_getattr,
#ifdef CONFIG_UBIFS_FS_XATTR
.setxattr = ubifs_setxattr, .setxattr = ubifs_setxattr,
.getxattr = ubifs_getxattr, .getxattr = ubifs_getxattr,
.listxattr = ubifs_listxattr, .listxattr = ubifs_listxattr,
.removexattr = ubifs_removexattr, .removexattr = ubifs_removexattr,
#endif
}; };
const struct inode_operations ubifs_symlink_inode_operations = { const struct inode_operations ubifs_symlink_inode_operations = {
......
...@@ -109,7 +109,7 @@ static int switch_gc_head(struct ubifs_info *c) ...@@ -109,7 +109,7 @@ static int switch_gc_head(struct ubifs_info *c)
return err; return err;
c->gc_lnum = -1; 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; return err;
} }
......
此差异已折叠。
...@@ -214,7 +214,7 @@ static int reserve_space(struct ubifs_info *c, int jhead, int len) ...@@ -214,7 +214,7 @@ static int reserve_space(struct ubifs_info *c, int jhead, int len)
err = ubifs_add_bud_to_log(c, jhead, lnum, offs); err = ubifs_add_bud_to_log(c, jhead, lnum, offs);
if (err) if (err)
goto out_return; goto out_return;
err = ubifs_wbuf_seek_nolock(wbuf, lnum, offs, wbuf->dtype); err = ubifs_wbuf_seek_nolock(wbuf, lnum, offs);
if (err) if (err)
goto out_unlock; goto out_unlock;
...@@ -385,9 +385,9 @@ static int make_reservation(struct ubifs_info *c, int jhead, int len) ...@@ -385,9 +385,9 @@ static int make_reservation(struct ubifs_info *c, int jhead, int len)
if (err == -ENOSPC) { if (err == -ENOSPC) {
/* This are some budgeting problems, print useful information */ /* This are some budgeting problems, print useful information */
down_write(&c->commit_sem); down_write(&c->commit_sem);
dbg_dump_stack(); dump_stack();
dbg_dump_budg(c, &c->bi); ubifs_dump_budg(c, &c->bi);
dbg_dump_lprops(c); ubifs_dump_lprops(c);
cmt_retries = dbg_check_lprops(c); cmt_retries = dbg_check_lprops(c);
up_write(&c->commit_sem); up_write(&c->commit_sem);
} }
...@@ -1267,7 +1267,6 @@ int ubifs_jnl_truncate(struct ubifs_info *c, const struct inode *inode, ...@@ -1267,7 +1267,6 @@ int ubifs_jnl_truncate(struct ubifs_info *c, const struct inode *inode,
return err; return err;
} }
#ifdef CONFIG_UBIFS_FS_XATTR
/** /**
* ubifs_jnl_delete_xattr - delete an extended attribute. * ubifs_jnl_delete_xattr - delete an extended attribute.
...@@ -1462,4 +1461,3 @@ int ubifs_jnl_change_xattr(struct ubifs_info *c, const struct inode *inode, ...@@ -1462,4 +1461,3 @@ int ubifs_jnl_change_xattr(struct ubifs_info *c, const struct inode *inode,
return err; return err;
} }
#endif /* CONFIG_UBIFS_FS_XATTR */
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
...@@ -399,7 +399,7 @@ ssize_t ubifs_getxattr(struct dentry *dentry, const char *name, void *buf, ...@@ -399,7 +399,7 @@ ssize_t ubifs_getxattr(struct dentry *dentry, const char *name, void *buf,
if (buf) { if (buf) {
/* If @buf is %NULL we are supposed to return the length */ /* If @buf is %NULL we are supposed to return the length */
if (ui->data_len > size) { if (ui->data_len > size) {
dbg_err("buffer size %zd, xattr len %d", ubifs_err("buffer size %zd, xattr len %d",
size, ui->data_len); size, ui->data_len);
err = -ERANGE; err = -ERANGE;
goto out_iput; goto out_iput;
......
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册