Commit 6133308a authored by Linus Torvalds's avatar 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
  ...
parents e8650a08 62f38455
...@@ -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;
......
This diff is collapsed.
...@@ -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
This diff is collapsed.
This diff is collapsed.
...@@ -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 */
This diff is collapsed.
This diff is collapsed.
...@@ -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;
} }
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -399,8 +399,8 @@ ssize_t ubifs_getxattr(struct dentry *dentry, const char *name, void *buf, ...@@ -399,8 +399,8 @@ 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;
} }
......
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment