Commit f248488b authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge git://git.infradead.org/mtd-2.6

* git://git.infradead.org/mtd-2.6:
  [MTD] fix mtdconcat for subpage-write NAND
  [MTD] [OneNAND] Avoid deadlock in erase callback; release chip lock first.
  [MTD] [OneNAND] Return only negative error codes
  [MTD] [OneNAND] Synchronize block locking operations
  UBI: return correct error code
  UBI: remove useless inlines
  UBI: fix atomic LEB change problems
  UBI: use byte hexdump
  UBI: do not use vmalloc on I/O path
  UBI: allocate memory with GFP_NOFS
  UBI: use linux print_hex_dump(), not home-grown one
  UBI: don't use array index before testing if it is negative
  UBI: add more prints
  UBI: fix sparse warnings
  UBI: fix leak in ubi_scan_erase_peb
parents cbe619b1 e3d18658
......@@ -726,6 +726,7 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c
concat->mtd.size = subdev[0]->size;
concat->mtd.erasesize = subdev[0]->erasesize;
concat->mtd.writesize = subdev[0]->writesize;
concat->mtd.subpage_sft = subdev[0]->subpage_sft;
concat->mtd.oobsize = subdev[0]->oobsize;
concat->mtd.oobavail = subdev[0]->oobavail;
if (subdev[0]->writev)
......
......@@ -327,7 +327,7 @@ static int onenand_wait(struct mtd_info *mtd, int state)
printk(KERN_ERR "onenand_wait: controller error = 0x%04x\n", ctrl);
if (ctrl & ONENAND_CTRL_LOCK)
printk(KERN_ERR "onenand_wait: it's locked error.\n");
return ctrl;
return -EIO;
}
if (interrupt & ONENAND_INT_READ) {
......@@ -336,7 +336,7 @@ static int onenand_wait(struct mtd_info *mtd, int state)
if (ecc & ONENAND_ECC_2BIT_ALL) {
printk(KERN_ERR "onenand_wait: ECC error = 0x%04x\n", ecc);
mtd->ecc_stats.failed++;
return ecc;
return -EBADMSG;
} else if (ecc & ONENAND_ECC_1BIT_ALL) {
printk(KERN_INFO "onenand_wait: correctable ECC error = 0x%04x\n", ecc);
mtd->ecc_stats.corrected++;
......@@ -1711,13 +1711,14 @@ static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
erase_exit:
ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;
/* Do call back function */
if (!ret)
mtd_erase_callback(instr);
/* Deselect and wake up anyone waiting on the device */
onenand_release_device(mtd);
/* Do call back function */
if (!ret)
mtd_erase_callback(instr);
return ret;
}
......@@ -1904,7 +1905,12 @@ static int onenand_do_lock_cmd(struct mtd_info *mtd, loff_t ofs, size_t len, int
*/
static int onenand_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
{
return onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_LOCK);
int ret;
onenand_get_device(mtd, FL_LOCKING);
ret = onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_LOCK);
onenand_release_device(mtd);
return ret;
}
/**
......@@ -1917,7 +1923,12 @@ static int onenand_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
*/
static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
{
return onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_UNLOCK);
int ret;
onenand_get_device(mtd, FL_LOCKING);
ret = onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_UNLOCK);
onenand_release_device(mtd);
return ret;
}
/**
......@@ -1979,7 +1990,7 @@ static int onenand_unlock_all(struct mtd_info *mtd)
loff_t ofs = this->chipsize >> 1;
size_t len = mtd->erasesize;
onenand_unlock(mtd, ofs, len);
onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_UNLOCK);
}
onenand_check_lock_status(this);
......@@ -1987,7 +1998,7 @@ static int onenand_unlock_all(struct mtd_info *mtd)
return 0;
}
onenand_unlock(mtd, 0x0, this->chipsize);
onenand_do_lock_cmd(mtd, 0x0, this->chipsize, ONENAND_CMD_UNLOCK);
return 0;
}
......
......@@ -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 @@ out_detach:
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;
......
......@@ -42,7 +42,8 @@ void ubi_dbg_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr)
dbg_msg("data_offset %d", be32_to_cpu(ec_hdr->data_offset));
dbg_msg("hdr_crc %#08x", be32_to_cpu(ec_hdr->hdr_crc));
dbg_msg("erase counter header hexdump:");
ubi_dbg_hexdump(ec_hdr, UBI_EC_HDR_SIZE);
print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
ec_hdr, UBI_EC_HDR_SIZE, 1);
}
/**
......@@ -187,38 +188,4 @@ void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req)
dbg_msg("the 1st 16 characters of the name: %s", nm);
}
#define BYTES_PER_LINE 32
/**
* ubi_dbg_hexdump - dump a buffer.
* @ptr: the buffer to dump
* @size: buffer size which must be multiple of 4 bytes
*/
void ubi_dbg_hexdump(const void *ptr, int size)
{
int i, k = 0, rows, columns;
const uint8_t *p = ptr;
size = ALIGN(size, 4);
rows = size/BYTES_PER_LINE + size % BYTES_PER_LINE;
for (i = 0; i < rows; i++) {
int j;
cond_resched();
columns = min(size - k, BYTES_PER_LINE) / 4;
if (columns == 0)
break;
printk(KERN_DEBUG "%5d: ", i * BYTES_PER_LINE);
for (j = 0; j < columns; j++) {
int n, N;
N = size - k > 4 ? 4 : size - k;
for (n = 0; n < N; n++)
printk("%02x", p[k++]);
printk(" ");
}
printk("\n");
}
}
#endif /* CONFIG_MTD_UBI_DEBUG_MSG */
......@@ -59,7 +59,6 @@ void ubi_dbg_dump_vtbl_record(const struct ubi_vtbl_record *r, int idx);
void ubi_dbg_dump_sv(const struct ubi_scan_volume *sv);
void ubi_dbg_dump_seb(const struct ubi_scan_leb *seb, int type);
void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req);
void ubi_dbg_hexdump(const void *buf, int size);
#else
......@@ -72,7 +71,6 @@ void ubi_dbg_hexdump(const void *buf, int size);
#define ubi_dbg_dump_sv(sv) ({})
#define ubi_dbg_dump_seb(seb, type) ({})
#define ubi_dbg_dump_mkvol_req(req) ({})
#define ubi_dbg_hexdump(buf, size) ({})
#endif /* CONFIG_MTD_UBI_DEBUG_MSG */
......
......@@ -46,6 +46,9 @@
#include <linux/err.h>
#include "ubi.h"
/* Number of physical eraseblocks reserved for atomic LEB change operation */
#define EBA_RESERVED_PEBS 1
/**
* struct ltree_entry - an entry in the lock tree.
* @rb: links RB-tree nodes
......@@ -157,7 +160,7 @@ static struct ltree_entry *ltree_add_entry(struct ubi_device *ubi, int vol_id,
{
struct ltree_entry *le, *le1, *le_free;
le = kmem_cache_alloc(ltree_slab, GFP_KERNEL);
le = kmem_cache_alloc(ltree_slab, GFP_NOFS);
if (!le)
return ERR_PTR(-ENOMEM);
......@@ -397,7 +400,7 @@ int ubi_eba_read_leb(struct ubi_device *ubi, int vol_id, int lnum, void *buf,
retry:
if (check) {
vid_hdr = ubi_zalloc_vid_hdr(ubi);
vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
if (!vid_hdr) {
err = -ENOMEM;
goto out_unlock;
......@@ -495,16 +498,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);
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 +529,22 @@ retry:
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 +554,7 @@ retry:
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 +567,7 @@ write_error:
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;
}
......@@ -627,7 +625,7 @@ int ubi_eba_write_leb(struct ubi_device *ubi, int vol_id, int lnum,
* The logical eraseblock is not mapped. We have to get a free physical
* eraseblock and write the volume identifier header there first.
*/
vid_hdr = ubi_zalloc_vid_hdr(ubi);
vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
if (!vid_hdr) {
leb_write_unlock(ubi, vol_id, lnum);
return -ENOMEM;
......@@ -738,7 +736,7 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, int vol_id, int lnum,
else
ubi_assert(len % ubi->min_io_size == 0);
vid_hdr = ubi_zalloc_vid_hdr(ubi);
vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
if (!vid_hdr)
return -ENOMEM;
......@@ -832,6 +830,9 @@ write_error:
* data, which has to be aligned. This function guarantees that in case of an
* unclean reboot the old contents is preserved. Returns zero in case of
* success and a negative error code in case of failure.
*
* UBI reserves one LEB for the "atomic LEB change" operation, so only one
* 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, int vol_id, int lnum,
const void *buf, int len, int dtype)
......@@ -844,15 +845,14 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, int vol_id, int lnum,
if (ubi->ro_mode)
return -EROFS;
vid_hdr = ubi_zalloc_vid_hdr(ubi);
vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
if (!vid_hdr)
return -ENOMEM;
mutex_lock(&ubi->alc_mutex);
err = leb_write_lock(ubi, vol_id, lnum);
if (err) {
ubi_free_vid_hdr(ubi, vid_hdr);
return err;
}
if (err)
goto out_mutex;
vid_hdr->sqnum = cpu_to_be64(next_sqnum(ubi));
vid_hdr->vol_id = cpu_to_be32(vol_id);
......@@ -869,9 +869,8 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, int vol_id, int lnum,
retry:
pnum = ubi_wl_get_peb(ubi, dtype);
if (pnum < 0) {
ubi_free_vid_hdr(ubi, vid_hdr);
leb_write_unlock(ubi, vol_id, lnum);
return pnum;
err = pnum;
goto out_leb_unlock;
}
dbg_eba("change LEB %d:%d, PEB %d, write VID hdr to PEB %d",
......@@ -893,17 +892,18 @@ retry:
if (vol->eba_tbl[lnum] >= 0) {
err = ubi_wl_put_peb(ubi, vol->eba_tbl[lnum], 1);
if (err) {
ubi_free_vid_hdr(ubi, vid_hdr);
leb_write_unlock(ubi, vol_id, lnum);
return err;
}
if (err)
goto out_leb_unlock;
}
vol->eba_tbl[lnum] = pnum;
out_leb_unlock:
leb_write_unlock(ubi, vol_id, lnum);
out_mutex:
mutex_unlock(&ubi->alc_mutex);
ubi_free_vid_hdr(ubi, vid_hdr);
return 0;
return err;
write_error:
if (err != -EIO || !ubi->bad_allowed) {
......@@ -913,17 +913,13 @@ write_error:
* mode just in case.
*/
ubi_ro_mode(ubi);
leb_write_unlock(ubi, vol_id, lnum);
ubi_free_vid_hdr(ubi, vid_hdr);
return err;
goto out_leb_unlock;
}
err = ubi_wl_put_peb(ubi, pnum, 1);
if (err || ++tries > UBI_IO_RETRIES) {
ubi_ro_mode(ubi);
leb_write_unlock(ubi, vol_id, lnum);
ubi_free_vid_hdr(ubi, vid_hdr);
return err;
goto out_leb_unlock;
}
vid_hdr->sqnum = cpu_to_be64(next_sqnum(ubi));
......@@ -965,7 +961,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 +974,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 +1014,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 +1033,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 +1067,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 +1088,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 +1098,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;
}
......@@ -1144,6 +1123,7 @@ int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
dbg_eba("initialize EBA unit");
spin_lock_init(&ubi->ltree_lock);
mutex_init(&ubi->alc_mutex);
ubi->ltree = RB_ROOT;
if (ubi_devices_cnt == 0) {
......@@ -1205,6 +1185,15 @@ int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
ubi->rsvd_pebs += ubi->beb_rsvd_pebs;
}
if (ubi->avail_pebs < EBA_RESERVED_PEBS) {
ubi_err("no enough physical eraseblocks (%d, need %d)",
ubi->avail_pebs, EBA_RESERVED_PEBS);
err = -ENOSPC;
goto out_free;
}
ubi->avail_pebs -= EBA_RESERVED_PEBS;
ubi->rsvd_pebs += EBA_RESERVED_PEBS;
dbg_eba("EBA unit is initialized");
return 0;
......
......@@ -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 @@ retry:
* 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_buf<