mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-24 17:59:32 +00:00
UBI: do not use vmalloc on I/O path
Similar reason as in case of the previous patch: it causes deadlocks if a filesystem with writeback support works on top of UBI. So pre-allocate needed buffers when attaching MTD device. We also need mutexes to protect the buffers, but they do not cause much contantion because they are used in recovery, torture, and WL copy routines, which are called seldom. Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
This commit is contained in:
parent
33818bbb84
commit
e88d6e10e5
8 changed files with 119 additions and 112 deletions
|
@ -565,7 +565,7 @@ static int attach_mtd_dev(const char *mtd_dev, int vid_hdr_offset,
|
|||
}
|
||||
|
||||
ubi = ubi_devices[ubi_devices_cnt] = kzalloc(sizeof(struct ubi_device),
|
||||
GFP_KERNEL);
|
||||
GFP_KERNEL);
|
||||
if (!ubi) {
|
||||
err = -ENOMEM;
|
||||
goto out_mtd;
|
||||
|
@ -583,6 +583,22 @@ static int attach_mtd_dev(const char *mtd_dev, int vid_hdr_offset,
|
|||
if (err)
|
||||
goto out_free;
|
||||
|
||||
mutex_init(&ubi->buf_mutex);
|
||||
ubi->peb_buf1 = vmalloc(ubi->peb_size);
|
||||
if (!ubi->peb_buf1)
|
||||
goto out_free;
|
||||
|
||||
ubi->peb_buf2 = vmalloc(ubi->peb_size);
|
||||
if (!ubi->peb_buf2)
|
||||
goto out_free;
|
||||
|
||||
#ifdef CONFIG_MTD_UBI_DEBUG
|
||||
mutex_init(&ubi->dbg_buf_mutex);
|
||||
ubi->dbg_peb_buf = vmalloc(ubi->peb_size);
|
||||
if (!ubi->dbg_peb_buf)
|
||||
goto out_free;
|
||||
#endif
|
||||
|
||||
err = attach_by_scanning(ubi);
|
||||
if (err) {
|
||||
dbg_err("failed to attach by scanning, error %d", err);
|
||||
|
@ -630,6 +646,11 @@ static int attach_mtd_dev(const char *mtd_dev, int vid_hdr_offset,
|
|||
ubi_wl_close(ubi);
|
||||
vfree(ubi->vtbl);
|
||||
out_free:
|
||||
vfree(ubi->peb_buf1);
|
||||
vfree(ubi->peb_buf2);
|
||||
#ifdef CONFIG_MTD_UBI_DEBUG
|
||||
vfree(ubi->dbg_peb_buf);
|
||||
#endif
|
||||
kfree(ubi);
|
||||
out_mtd:
|
||||
put_mtd_device(mtd);
|
||||
|
@ -651,6 +672,11 @@ static void detach_mtd_dev(struct ubi_device *ubi)
|
|||
ubi_wl_close(ubi);
|
||||
vfree(ubi->vtbl);
|
||||
put_mtd_device(ubi->mtd);
|
||||
vfree(ubi->peb_buf1);
|
||||
vfree(ubi->peb_buf2);
|
||||
#ifdef CONFIG_MTD_UBI_DEBUG
|
||||
vfree(ubi->dbg_peb_buf);
|
||||
#endif
|
||||
kfree(ubi_devices[ubi_num]);
|
||||
ubi_devices[ubi_num] = NULL;
|
||||
ubi_devices_cnt -= 1;
|
||||
|
|
|
@ -495,16 +495,18 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum,
|
|||
int err, idx = vol_id2idx(ubi, vol_id), new_pnum, data_size, tries = 0;
|
||||
struct ubi_volume *vol = ubi->volumes[idx];
|
||||
struct ubi_vid_hdr *vid_hdr;
|
||||
unsigned char *new_buf;
|
||||
|
||||
vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
|
||||
if (!vid_hdr) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
mutex_lock(&ubi->buf_mutex);
|
||||
|
||||
retry:
|
||||
new_pnum = ubi_wl_get_peb(ubi, UBI_UNKNOWN);
|
||||
if (new_pnum < 0) {
|
||||
mutex_unlock(&ubi->buf_mutex);
|
||||
ubi_free_vid_hdr(ubi, vid_hdr);
|
||||
return new_pnum;
|
||||
}
|
||||
|
@ -524,31 +526,22 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum,
|
|||
goto write_error;
|
||||
|
||||
data_size = offset + len;
|
||||
new_buf = vmalloc(data_size);
|
||||
if (!new_buf) {
|
||||
err = -ENOMEM;
|
||||
goto out_put;
|
||||
}
|
||||
memset(new_buf + offset, 0xFF, len);
|
||||
memset(ubi->peb_buf1 + offset, 0xFF, len);
|
||||
|
||||
/* Read everything before the area where the write failure happened */
|
||||
if (offset > 0) {
|
||||
err = ubi_io_read_data(ubi, new_buf, pnum, 0, offset);
|
||||
if (err && err != UBI_IO_BITFLIPS) {
|
||||
vfree(new_buf);
|
||||
err = ubi_io_read_data(ubi, ubi->peb_buf1, pnum, 0, offset);
|
||||
if (err && err != UBI_IO_BITFLIPS)
|
||||
goto out_put;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(new_buf + offset, buf, len);
|
||||
memcpy(ubi->peb_buf1 + offset, buf, len);
|
||||
|
||||
err = ubi_io_write_data(ubi, new_buf, new_pnum, 0, data_size);
|
||||
if (err) {
|
||||
vfree(new_buf);
|
||||
err = ubi_io_write_data(ubi, ubi->peb_buf1, new_pnum, 0, data_size);
|
||||
if (err)
|
||||
goto write_error;
|
||||
}
|
||||
|
||||
vfree(new_buf);
|
||||
mutex_unlock(&ubi->buf_mutex);
|
||||
ubi_free_vid_hdr(ubi, vid_hdr);
|
||||
|
||||
vol->eba_tbl[lnum] = new_pnum;
|
||||
|
@ -558,6 +551,7 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum,
|
|||
return 0;
|
||||
|
||||
out_put:
|
||||
mutex_unlock(&ubi->buf_mutex);
|
||||
ubi_wl_put_peb(ubi, new_pnum, 1);
|
||||
ubi_free_vid_hdr(ubi, vid_hdr);
|
||||
return err;
|
||||
|
@ -570,6 +564,7 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum,
|
|||
ubi_warn("failed to write to PEB %d", new_pnum);
|
||||
ubi_wl_put_peb(ubi, new_pnum, 1);
|
||||
if (++tries > UBI_IO_RETRIES) {
|
||||
mutex_unlock(&ubi->buf_mutex);
|
||||
ubi_free_vid_hdr(ubi, vid_hdr);
|
||||
return err;
|
||||
}
|
||||
|
@ -965,7 +960,6 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
|
|||
int err, vol_id, lnum, data_size, aldata_size, pnum, idx;
|
||||
struct ubi_volume *vol;
|
||||
uint32_t crc;
|
||||
void *buf, *buf1 = NULL;
|
||||
|
||||
vol_id = be32_to_cpu(vid_hdr->vol_id);
|
||||
lnum = be32_to_cpu(vid_hdr->lnum);
|
||||
|
@ -979,19 +973,15 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
|
|||
data_size = aldata_size =
|
||||
ubi->leb_size - be32_to_cpu(vid_hdr->data_pad);
|
||||
|
||||
buf = vmalloc(aldata_size);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* We do not want anybody to write to this logical eraseblock while we
|
||||
* are moving it, so we lock it.
|
||||
*/
|
||||
err = leb_write_lock(ubi, vol_id, lnum);
|
||||
if (err) {
|
||||
vfree(buf);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
mutex_lock(&ubi->buf_mutex);
|
||||
|
||||
/*
|
||||
* But the logical eraseblock might have been put by this time.
|
||||
|
@ -1023,7 +1013,7 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
|
|||
/* OK, now the LEB is locked and we can safely start moving it */
|
||||
|
||||
dbg_eba("read %d bytes of data", aldata_size);
|
||||
err = ubi_io_read_data(ubi, buf, from, 0, aldata_size);
|
||||
err = ubi_io_read_data(ubi, ubi->peb_buf1, from, 0, aldata_size);
|
||||
if (err && err != UBI_IO_BITFLIPS) {
|
||||
ubi_warn("error %d while reading data from PEB %d",
|
||||
err, from);
|
||||
|
@ -1042,10 +1032,10 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
|
|||
*/
|
||||
if (vid_hdr->vol_type == UBI_VID_DYNAMIC)
|
||||
aldata_size = data_size =
|
||||
ubi_calc_data_len(ubi, buf, data_size);
|
||||
ubi_calc_data_len(ubi, ubi->peb_buf1, data_size);
|
||||
|
||||
cond_resched();
|
||||
crc = crc32(UBI_CRC32_INIT, buf, data_size);
|
||||
crc = crc32(UBI_CRC32_INIT, ubi->peb_buf1, data_size);
|
||||
cond_resched();
|
||||
|
||||
/*
|
||||
|
@ -1076,23 +1066,18 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
|
|||
}
|
||||
|
||||
if (data_size > 0) {
|
||||
err = ubi_io_write_data(ubi, buf, to, 0, aldata_size);
|
||||
err = ubi_io_write_data(ubi, ubi->peb_buf1, to, 0, aldata_size);
|
||||
if (err)
|
||||
goto out_unlock;
|
||||
|
||||
cond_resched();
|
||||
|
||||
/*
|
||||
* We've written the data and are going to read it back to make
|
||||
* sure it was written correctly.
|
||||
*/
|
||||
buf1 = vmalloc(aldata_size);
|
||||
if (!buf1) {
|
||||
err = -ENOMEM;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
cond_resched();
|
||||
|
||||
err = ubi_io_read_data(ubi, buf1, to, 0, aldata_size);
|
||||
err = ubi_io_read_data(ubi, ubi->peb_buf2, to, 0, aldata_size);
|
||||
if (err) {
|
||||
if (err != UBI_IO_BITFLIPS)
|
||||
ubi_warn("cannot read data back from PEB %d",
|
||||
|
@ -1102,7 +1087,7 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
|
|||
|
||||
cond_resched();
|
||||
|
||||
if (memcmp(buf, buf1, aldata_size)) {
|
||||
if (memcmp(ubi->peb_buf1, ubi->peb_buf2, aldata_size)) {
|
||||
ubi_warn("read data back from PEB %d - it is different",
|
||||
to);
|
||||
goto out_unlock;
|
||||
|
@ -1112,16 +1097,9 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
|
|||
ubi_assert(vol->eba_tbl[lnum] == from);
|
||||
vol->eba_tbl[lnum] = to;
|
||||
|
||||
leb_write_unlock(ubi, vol_id, lnum);
|
||||
vfree(buf);
|
||||
vfree(buf1);
|
||||
|
||||
return 0;
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&ubi->buf_mutex);
|
||||
leb_write_unlock(ubi, vol_id, lnum);
|
||||
vfree(buf);
|
||||
vfree(buf1);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
@ -98,8 +98,8 @@ static int paranoid_check_ec_hdr(const struct ubi_device *ubi, int pnum,
|
|||
static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum);
|
||||
static int paranoid_check_vid_hdr(const struct ubi_device *ubi, int pnum,
|
||||
const struct ubi_vid_hdr *vid_hdr);
|
||||
static int paranoid_check_all_ff(const struct ubi_device *ubi, int pnum,
|
||||
int offset, int len);
|
||||
static int paranoid_check_all_ff(struct ubi_device *ubi, int pnum, int offset,
|
||||
int len);
|
||||
#else
|
||||
#define paranoid_check_not_bad(ubi, pnum) 0
|
||||
#define paranoid_check_peb_ec_hdr(ubi, pnum) 0
|
||||
|
@ -202,8 +202,8 @@ int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset,
|
|||
* Note, in case of an error, it is possible that something was still written
|
||||
* to the flash media, but may be some garbage.
|
||||
*/
|
||||
int ubi_io_write(const struct ubi_device *ubi, const void *buf, int pnum,
|
||||
int offset, int len)
|
||||
int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset,
|
||||
int len)
|
||||
{
|
||||
int err;
|
||||
size_t written;
|
||||
|
@ -285,7 +285,7 @@ static void erase_callback(struct erase_info *ei)
|
|||
* zero in case of success and a negative error code in case of failure. If
|
||||
* %-EIO is returned, the physical eraseblock most probably went bad.
|
||||
*/
|
||||
static int do_sync_erase(const struct ubi_device *ubi, int pnum)
|
||||
static int do_sync_erase(struct ubi_device *ubi, int pnum)
|
||||
{
|
||||
int err, retries = 0;
|
||||
struct erase_info ei;
|
||||
|
@ -377,29 +377,25 @@ static uint8_t patterns[] = {0xa5, 0x5a, 0x0};
|
|||
* test, a positive number of erase operations done if the test was
|
||||
* successfully passed, and other negative error codes in case of other errors.
|
||||
*/
|
||||
static int torture_peb(const struct ubi_device *ubi, int pnum)
|
||||
static int torture_peb(struct ubi_device *ubi, int pnum)
|
||||
{
|
||||
void *buf;
|
||||
int err, i, patt_count;
|
||||
|
||||
buf = vmalloc(ubi->peb_size);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
patt_count = ARRAY_SIZE(patterns);
|
||||
ubi_assert(patt_count > 0);
|
||||
|
||||
mutex_lock(&ubi->buf_mutex);
|
||||
for (i = 0; i < patt_count; i++) {
|
||||
err = do_sync_erase(ubi, pnum);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
/* Make sure the PEB contains only 0xFF bytes */
|
||||
err = ubi_io_read(ubi, buf, pnum, 0, ubi->peb_size);
|
||||
err = ubi_io_read(ubi, ubi->peb_buf1, pnum, 0, ubi->peb_size);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = check_pattern(buf, 0xFF, ubi->peb_size);
|
||||
err = check_pattern(ubi->peb_buf1, 0xFF, ubi->peb_size);
|
||||
if (err == 0) {
|
||||
ubi_err("erased PEB %d, but a non-0xFF byte found",
|
||||
pnum);
|
||||
|
@ -408,17 +404,17 @@ static int torture_peb(const struct ubi_device *ubi, int pnum)
|
|||
}
|
||||
|
||||
/* Write a pattern and check it */
|
||||
memset(buf, patterns[i], ubi->peb_size);
|
||||
err = ubi_io_write(ubi, buf, pnum, 0, ubi->peb_size);
|
||||
memset(ubi->peb_buf1, patterns[i], ubi->peb_size);
|
||||
err = ubi_io_write(ubi, ubi->peb_buf1, pnum, 0, ubi->peb_size);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
memset(buf, ~patterns[i], ubi->peb_size);
|
||||
err = ubi_io_read(ubi, buf, pnum, 0, ubi->peb_size);
|
||||
memset(ubi->peb_buf1, ~patterns[i], ubi->peb_size);
|
||||
err = ubi_io_read(ubi, ubi->peb_buf1, pnum, 0, ubi->peb_size);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = check_pattern(buf, patterns[i], ubi->peb_size);
|
||||
err = check_pattern(ubi->peb_buf1, patterns[i], ubi->peb_size);
|
||||
if (err == 0) {
|
||||
ubi_err("pattern %x checking failed for PEB %d",
|
||||
patterns[i], pnum);
|
||||
|
@ -430,6 +426,7 @@ static int torture_peb(const struct ubi_device *ubi, int pnum)
|
|||
err = patt_count;
|
||||
|
||||
out:
|
||||
mutex_unlock(&ubi->buf_mutex);
|
||||
if (err == UBI_IO_BITFLIPS || err == -EBADMSG) {
|
||||
/*
|
||||
* If a bit-flip or data integrity error was detected, the test
|
||||
|
@ -440,7 +437,6 @@ static int torture_peb(const struct ubi_device *ubi, int pnum)
|
|||
pnum);
|
||||
err = -EIO;
|
||||
}
|
||||
vfree(buf);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -460,7 +456,7 @@ static int torture_peb(const struct ubi_device *ubi, int pnum)
|
|||
* codes in case of other errors. Note, %-EIO means that the physical
|
||||
* eraseblock is bad.
|
||||
*/
|
||||
int ubi_io_sync_erase(const struct ubi_device *ubi, int pnum, int torture)
|
||||
int ubi_io_sync_erase(struct ubi_device *ubi, int pnum, int torture)
|
||||
{
|
||||
int err, ret = 0;
|
||||
|
||||
|
@ -617,7 +613,7 @@ static int validate_ec_hdr(const struct ubi_device *ubi,
|
|||
* o %UBI_IO_PEB_EMPTY if the physical eraseblock is empty;
|
||||
* o a negative error code in case of failure.
|
||||
*/
|
||||
int ubi_io_read_ec_hdr(const struct ubi_device *ubi, int pnum,
|
||||
int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
|
||||
struct ubi_ec_hdr *ec_hdr, int verbose)
|
||||
{
|
||||
int err, read_err = 0;
|
||||
|
@ -723,7 +719,7 @@ int ubi_io_read_ec_hdr(const struct ubi_device *ubi, int pnum,
|
|||
* case of failure. If %-EIO is returned, the physical eraseblock most probably
|
||||
* went bad.
|
||||
*/
|
||||
int ubi_io_write_ec_hdr(const struct ubi_device *ubi, int pnum,
|
||||
int ubi_io_write_ec_hdr(struct ubi_device *ubi, int pnum,
|
||||
struct ubi_ec_hdr *ec_hdr)
|
||||
{
|
||||
int err;
|
||||
|
@ -889,7 +885,7 @@ static int validate_vid_hdr(const struct ubi_device *ubi,
|
|||
* header there);
|
||||
* o a negative error code in case of failure.
|
||||
*/
|
||||
int ubi_io_read_vid_hdr(const struct ubi_device *ubi, int pnum,
|
||||
int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
|
||||
struct ubi_vid_hdr *vid_hdr, int verbose)
|
||||
{
|
||||
int err, read_err = 0;
|
||||
|
@ -996,7 +992,7 @@ int ubi_io_read_vid_hdr(const struct ubi_device *ubi, int pnum,
|
|||
* case of failure. If %-EIO is returned, the physical eraseblock probably went
|
||||
* bad.
|
||||
*/
|
||||
int ubi_io_write_vid_hdr(const struct ubi_device *ubi, int pnum,
|
||||
int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum,
|
||||
struct ubi_vid_hdr *vid_hdr)
|
||||
{
|
||||
int err;
|
||||
|
@ -1219,44 +1215,40 @@ static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum)
|
|||
* @offset of the physical eraseblock @pnum, %1 if not, and a negative error
|
||||
* code if an error occurred.
|
||||
*/
|
||||
static int paranoid_check_all_ff(const struct ubi_device *ubi, int pnum,
|
||||
int offset, int len)
|
||||
static int paranoid_check_all_ff(struct ubi_device *ubi, int pnum, int offset,
|
||||
int len)
|
||||
{
|
||||
size_t read;
|
||||
int err;
|
||||
void *buf;
|
||||
loff_t addr = (loff_t)pnum * ubi->peb_size + offset;
|
||||
|
||||
buf = vmalloc(len);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
memset(buf, 0, len);
|
||||
|
||||
err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf);
|
||||
mutex_lock(&ubi->dbg_buf_mutex);
|
||||
err = ubi->mtd->read(ubi->mtd, addr, len, &read, ubi->dbg_peb_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 error;
|
||||
}
|
||||
|
||||
err = check_pattern(buf, 0xFF, len);
|
||||
err = check_pattern(ubi->dbg_peb_buf, 0xFF, len);
|
||||
if (err == 0) {
|
||||
ubi_err("flash region at PEB %d:%d, length %d does not "
|
||||
"contain all 0xFF bytes", pnum, offset, len);
|
||||
goto fail;
|
||||
}
|
||||
mutex_unlock(&ubi->dbg_buf_mutex);
|
||||
|
||||
vfree(buf);
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
ubi_err("paranoid check failed for PEB %d", pnum);
|
||||
dbg_msg("hex dump of the %d-%d region", offset, offset + len);
|
||||
print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 4, buf, len, 1);
|
||||
print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 4,
|
||||
ubi->dbg_peb_buf, len, 1);
|
||||
err = 1;
|
||||
error:
|
||||
ubi_dbg_dump_stack();
|
||||
vfree(buf);
|
||||
mutex_unlock(&ubi->dbg_buf_mutex);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,8 +45,7 @@
|
|||
#include "ubi.h"
|
||||
|
||||
#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
|
||||
static int paranoid_check_si(const struct ubi_device *ubi,
|
||||
struct ubi_scan_info *si);
|
||||
static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si);
|
||||
#else
|
||||
#define paranoid_check_si(ubi, si) 0
|
||||
#endif
|
||||
|
@ -259,9 +258,8 @@ static struct ubi_scan_volume *add_volume(struct ubi_scan_info *si, int vol_id,
|
|||
* o bit 2 is cleared: the older LEB is not corrupted;
|
||||
* o bit 2 is set: the older LEB is corrupted.
|
||||
*/
|
||||
static int compare_lebs(const struct ubi_device *ubi,
|
||||
const struct ubi_scan_leb *seb, int pnum,
|
||||
const struct ubi_vid_hdr *vid_hdr)
|
||||
static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb,
|
||||
int pnum, const struct ubi_vid_hdr *vid_hdr)
|
||||
{
|
||||
void *buf;
|
||||
int len, err, second_is_newer, bitflips = 0, corrupted = 0;
|
||||
|
@ -413,7 +411,7 @@ static int compare_lebs(const struct ubi_device *ubi,
|
|||
* to be picked, while the older one has to be dropped. This function returns
|
||||
* zero in case of success and a negative error code in case of failure.
|
||||
*/
|
||||
int ubi_scan_add_used(const struct ubi_device *ubi, struct ubi_scan_info *si,
|
||||
int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
|
||||
int pnum, int ec, const struct ubi_vid_hdr *vid_hdr,
|
||||
int bitflips)
|
||||
{
|
||||
|
@ -667,8 +665,8 @@ void ubi_scan_rm_volume(struct ubi_scan_info *si, struct ubi_scan_volume *sv)
|
|||
* function returns zero in case of success and a negative error code in case
|
||||
* of failure.
|
||||
*/
|
||||
int ubi_scan_erase_peb(const struct ubi_device *ubi,
|
||||
const struct ubi_scan_info *si, int pnum, int ec)
|
||||
int ubi_scan_erase_peb(struct ubi_device *ubi, const struct ubi_scan_info *si,
|
||||
int pnum, int ec)
|
||||
{
|
||||
int err;
|
||||
struct ubi_ec_hdr *ec_hdr;
|
||||
|
@ -712,7 +710,7 @@ int ubi_scan_erase_peb(const struct ubi_device *ubi,
|
|||
* This function returns scanning physical eraseblock information in case of
|
||||
* success and an error code in case of failure.
|
||||
*/
|
||||
struct ubi_scan_leb *ubi_scan_get_free_peb(const struct ubi_device *ubi,
|
||||
struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi,
|
||||
struct ubi_scan_info *si)
|
||||
{
|
||||
int err = 0, i;
|
||||
|
@ -1110,8 +1108,7 @@ void ubi_scan_destroy_si(struct ubi_scan_info *si)
|
|||
* This function returns zero if the scanning information is all right, %1 if
|
||||
* not and a negative error code if an error occurred.
|
||||
*/
|
||||
static int paranoid_check_si(const struct ubi_device *ubi,
|
||||
struct ubi_scan_info *si)
|
||||
static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si)
|
||||
{
|
||||
int pnum, err, vols_found = 0;
|
||||
struct rb_node *rb1, *rb2;
|
||||
|
|
|
@ -147,7 +147,7 @@ static inline void ubi_scan_move_to_list(struct ubi_scan_volume *sv,
|
|||
list_add_tail(&seb->u.list, list);
|
||||
}
|
||||
|
||||
int ubi_scan_add_used(const struct ubi_device *ubi, struct ubi_scan_info *si,
|
||||
int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
|
||||
int pnum, int ec, const struct ubi_vid_hdr *vid_hdr,
|
||||
int bitflips);
|
||||
struct ubi_scan_volume *ubi_scan_find_sv(const struct ubi_scan_info *si,
|
||||
|
@ -155,10 +155,10 @@ struct ubi_scan_volume *ubi_scan_find_sv(const struct ubi_scan_info *si,
|
|||
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(const struct ubi_device *ubi,
|
||||
struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi,
|
||||
struct ubi_scan_info *si);
|
||||
int ubi_scan_erase_peb(const struct ubi_device *ubi,
|
||||
const struct ubi_scan_info *si, int pnum, int ec);
|
||||
int ubi_scan_erase_peb(struct ubi_device *ubi, const struct ubi_scan_info *si,
|
||||
int pnum, int ec);
|
||||
struct ubi_scan_info *ubi_scan(struct ubi_device *ubi);
|
||||
void ubi_scan_destroy_si(struct ubi_scan_info *si);
|
||||
|
||||
|
|
|
@ -274,6 +274,12 @@ struct ubi_wl_entry;
|
|||
* @bad_allowed: whether the MTD device admits of bad physical eraseblocks or
|
||||
* not
|
||||
* @mtd: MTD device descriptor
|
||||
*
|
||||
* @peb_buf1: a buffer of PEB size used for different purposes
|
||||
* @peb_buf2: another buffer of PEB size used for different purposes
|
||||
* @buf_mutex: proptects @peb_buf1 and @peb_buf2
|
||||
* @dbg_peb_buf: buffer of PEB size used for debugging
|
||||
* @dbg_buf_mutex: proptects @dbg_peb_buf
|
||||
*/
|
||||
struct ubi_device {
|
||||
struct cdev cdev;
|
||||
|
@ -343,6 +349,14 @@ struct ubi_device {
|
|||
int vid_hdr_shift;
|
||||
int bad_allowed;
|
||||
struct mtd_info *mtd;
|
||||
|
||||
void *peb_buf1;
|
||||
void *peb_buf2;
|
||||
struct mutex buf_mutex;
|
||||
#ifdef CONFIG_MTD_UBI_DEBUG
|
||||
void *dbg_peb_buf;
|
||||
struct mutex dbg_buf_mutex;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern struct file_operations ubi_cdev_operations;
|
||||
|
@ -409,18 +423,18 @@ void ubi_wl_close(struct ubi_device *ubi);
|
|||
/* io.c */
|
||||
int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset,
|
||||
int len);
|
||||
int ubi_io_write(const struct ubi_device *ubi, const void *buf, int pnum,
|
||||
int offset, int len);
|
||||
int ubi_io_sync_erase(const struct ubi_device *ubi, int pnum, int torture);
|
||||
int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset,
|
||||
int len);
|
||||
int ubi_io_sync_erase(struct ubi_device *ubi, int pnum, int torture);
|
||||
int ubi_io_is_bad(const struct ubi_device *ubi, int pnum);
|
||||
int ubi_io_mark_bad(const struct ubi_device *ubi, int pnum);
|
||||
int ubi_io_read_ec_hdr(const struct ubi_device *ubi, int pnum,
|
||||
int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
|
||||
struct ubi_ec_hdr *ec_hdr, int verbose);
|
||||
int ubi_io_write_ec_hdr(const struct ubi_device *ubi, int pnum,
|
||||
int ubi_io_write_ec_hdr(struct ubi_device *ubi, int pnum,
|
||||
struct ubi_ec_hdr *ec_hdr);
|
||||
int ubi_io_read_vid_hdr(const struct ubi_device *ubi, int pnum,
|
||||
int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
|
||||
struct ubi_vid_hdr *vid_hdr, int verbose);
|
||||
int ubi_io_write_vid_hdr(const struct ubi_device *ubi, int pnum,
|
||||
int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum,
|
||||
struct ubi_vid_hdr *vid_hdr);
|
||||
|
||||
/*
|
||||
|
@ -494,7 +508,7 @@ static inline int ubi_io_read_data(const struct ubi_device *ubi, void *buf,
|
|||
* the beginning of the logical eraseblock, not to the beginning of the
|
||||
* physical eraseblock.
|
||||
*/
|
||||
static inline int ubi_io_write_data(const struct ubi_device *ubi, const void *buf,
|
||||
static inline int ubi_io_write_data(struct ubi_device *ubi, const void *buf,
|
||||
int pnum, int offset, int len)
|
||||
{
|
||||
ubi_assert(offset >= 0);
|
||||
|
|
|
@ -254,7 +254,7 @@ static int vtbl_check(const struct ubi_device *ubi,
|
|||
* This function returns zero in case of success and a negative error code in
|
||||
* case of failure.
|
||||
*/
|
||||
static int create_vtbl(const struct ubi_device *ubi, struct ubi_scan_info *si,
|
||||
static int create_vtbl(struct ubi_device *ubi, struct ubi_scan_info *si,
|
||||
int copy, void *vtbl)
|
||||
{
|
||||
int err, tries = 0;
|
||||
|
@ -339,7 +339,7 @@ static int create_vtbl(const struct ubi_device *ubi, struct ubi_scan_info *si,
|
|||
* not corrupted, and recovering from corruptions if needed. Returns volume
|
||||
* table in case of success and a negative error code in case of failure.
|
||||
*/
|
||||
static struct ubi_vtbl_record *process_lvol(const struct ubi_device *ubi,
|
||||
static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi,
|
||||
struct ubi_scan_info *si,
|
||||
struct ubi_scan_volume *sv)
|
||||
{
|
||||
|
@ -453,7 +453,7 @@ static struct ubi_vtbl_record *process_lvol(const struct ubi_device *ubi,
|
|||
* This function returns volume table contents in case of success and a
|
||||
* negative error code in case of failure.
|
||||
*/
|
||||
static struct ubi_vtbl_record *create_empty_lvol(const struct ubi_device *ubi,
|
||||
static struct ubi_vtbl_record *create_empty_lvol(struct ubi_device *ubi,
|
||||
struct ubi_scan_info *si)
|
||||
{
|
||||
int i;
|
||||
|
|
|
@ -208,7 +208,7 @@ struct ubi_work {
|
|||
};
|
||||
|
||||
#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
|
||||
static int paranoid_check_ec(const struct ubi_device *ubi, int pnum, int ec);
|
||||
static int paranoid_check_ec(struct ubi_device *ubi, int pnum, int ec);
|
||||
static int paranoid_check_in_wl_tree(struct ubi_wl_entry *e,
|
||||
struct rb_root *root);
|
||||
#else
|
||||
|
@ -1625,7 +1625,7 @@ void ubi_wl_close(struct ubi_device *ubi)
|
|||
* is equivalent to @ec, %1 if not, and a negative error code if an error
|
||||
* occurred.
|
||||
*/
|
||||
static int paranoid_check_ec(const struct ubi_device *ubi, int pnum, int ec)
|
||||
static int paranoid_check_ec(struct ubi_device *ubi, int pnum, int ec)
|
||||
{
|
||||
int err;
|
||||
long long read_ec;
|
||||
|
|
Loading…
Reference in a new issue