Commit 3291b52f authored by Boris Brezillon's avatar Boris Brezillon Committed by Richard Weinberger

UBI: introduce the VID buffer concept

Currently, all VID headers are allocated and freed using the
ubi_zalloc_vid_hdr() and ubi_free_vid_hdr() function. These functions
make sure to align allocation on ubi->vid_hdr_alsize and adjust the
vid_hdr pointer to match the ubi->vid_hdr_shift requirements.
This works fine, but is a bit convoluted.
Moreover, the future introduction of LEB consolidation (needed to support
MLC/TLC NANDs) will allows a VID buffer to contain more than one VID
header.

Hence the creation of a ubi_vid_io_buf struct to attach extra information
to the VID header.

We currently only store the actual pointer of the underlying buffer, but
will soon add the number of VID headers contained in the buffer.
Signed-off-by: default avatarBoris Brezillon <boris.brezillon@free-electrons.com>
Signed-off-by: default avatarRichard Weinberger <richard@nod.at>
parent 799dca34
...@@ -453,7 +453,7 @@ int ubi_compare_lebs(struct ubi_device *ubi, const struct ubi_ainf_peb *aeb, ...@@ -453,7 +453,7 @@ int ubi_compare_lebs(struct ubi_device *ubi, const struct ubi_ainf_peb *aeb,
{ {
int len, err, second_is_newer, bitflips = 0, corrupted = 0; int len, err, second_is_newer, bitflips = 0, corrupted = 0;
uint32_t data_crc, crc; uint32_t data_crc, crc;
struct ubi_vid_hdr *vh = NULL; struct ubi_vid_io_buf *vidb = NULL;
unsigned long long sqnum2 = be64_to_cpu(vid_hdr->sqnum); unsigned long long sqnum2 = be64_to_cpu(vid_hdr->sqnum);
if (sqnum2 == aeb->sqnum) { if (sqnum2 == aeb->sqnum) {
...@@ -496,12 +496,12 @@ int ubi_compare_lebs(struct ubi_device *ubi, const struct ubi_ainf_peb *aeb, ...@@ -496,12 +496,12 @@ int ubi_compare_lebs(struct ubi_device *ubi, const struct ubi_ainf_peb *aeb,
return bitflips << 1; return bitflips << 1;
} }
vh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL); vidb = ubi_alloc_vid_buf(ubi, GFP_KERNEL);
if (!vh) if (!vidb)
return -ENOMEM; return -ENOMEM;
pnum = aeb->pnum; pnum = aeb->pnum;
err = ubi_io_read_vid_hdr(ubi, pnum, vh, 0); err = ubi_io_read_vid_hdr(ubi, pnum, vidb, 0);
if (err) { if (err) {
if (err == UBI_IO_BITFLIPS) if (err == UBI_IO_BITFLIPS)
bitflips = 1; bitflips = 1;
...@@ -515,7 +515,7 @@ int ubi_compare_lebs(struct ubi_device *ubi, const struct ubi_ainf_peb *aeb, ...@@ -515,7 +515,7 @@ int ubi_compare_lebs(struct ubi_device *ubi, const struct ubi_ainf_peb *aeb,
} }
} }
vid_hdr = vh; vid_hdr = ubi_get_vid_hdr(vidb);
} }
/* Read the data of the copy and check the CRC */ /* Read the data of the copy and check the CRC */
...@@ -541,7 +541,7 @@ int ubi_compare_lebs(struct ubi_device *ubi, const struct ubi_ainf_peb *aeb, ...@@ -541,7 +541,7 @@ int ubi_compare_lebs(struct ubi_device *ubi, const struct ubi_ainf_peb *aeb,
} }
mutex_unlock(&ubi->buf_mutex); mutex_unlock(&ubi->buf_mutex);
ubi_free_vid_hdr(ubi, vh); ubi_free_vid_buf(vidb);
if (second_is_newer) if (second_is_newer)
dbg_bld("second PEB %d is newer, copy_flag is set", pnum); dbg_bld("second PEB %d is newer, copy_flag is set", pnum);
...@@ -553,7 +553,7 @@ int ubi_compare_lebs(struct ubi_device *ubi, const struct ubi_ainf_peb *aeb, ...@@ -553,7 +553,7 @@ int ubi_compare_lebs(struct ubi_device *ubi, const struct ubi_ainf_peb *aeb,
out_unlock: out_unlock:
mutex_unlock(&ubi->buf_mutex); mutex_unlock(&ubi->buf_mutex);
out_free_vidh: out_free_vidh:
ubi_free_vid_hdr(ubi, vh); ubi_free_vid_buf(vidb);
return err; return err;
} }
...@@ -955,7 +955,8 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai, ...@@ -955,7 +955,8 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai,
int pnum, bool fast) int pnum, bool fast)
{ {
struct ubi_ec_hdr *ech = ai->ech; struct ubi_ec_hdr *ech = ai->ech;
struct ubi_vid_hdr *vidh = ai->vidh; struct ubi_vid_io_buf *vidb = ai->vidb;
struct ubi_vid_hdr *vidh = ubi_get_vid_hdr(vidb);
long long ec; long long ec;
int err, bitflips = 0, vol_id = -1, ec_err = 0; int err, bitflips = 0, vol_id = -1, ec_err = 0;
...@@ -1053,7 +1054,7 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai, ...@@ -1053,7 +1054,7 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai,
/* OK, we've done with the EC header, let's look at the VID header */ /* OK, we've done with the EC header, let's look at the VID header */
err = ubi_io_read_vid_hdr(ubi, pnum, vidh, 0); err = ubi_io_read_vid_hdr(ubi, pnum, vidb, 0);
if (err < 0) if (err < 0)
return err; return err;
switch (err) { switch (err) {
...@@ -1396,8 +1397,8 @@ static int scan_all(struct ubi_device *ubi, struct ubi_attach_info *ai, ...@@ -1396,8 +1397,8 @@ static int scan_all(struct ubi_device *ubi, struct ubi_attach_info *ai,
if (!ai->ech) if (!ai->ech)
return err; return err;
ai->vidh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL); ai->vidb = ubi_alloc_vid_buf(ubi, GFP_KERNEL);
if (!ai->vidh) if (!ai->vidb)
goto out_ech; goto out_ech;
for (pnum = start; pnum < ubi->peb_count; pnum++) { for (pnum = start; pnum < ubi->peb_count; pnum++) {
...@@ -1446,13 +1447,13 @@ static int scan_all(struct ubi_device *ubi, struct ubi_attach_info *ai, ...@@ -1446,13 +1447,13 @@ static int scan_all(struct ubi_device *ubi, struct ubi_attach_info *ai,
if (err) if (err)
goto out_vidh; goto out_vidh;
ubi_free_vid_hdr(ubi, ai->vidh); ubi_free_vid_buf(ai->vidb);
kfree(ai->ech); kfree(ai->ech);
return 0; return 0;
out_vidh: out_vidh:
ubi_free_vid_hdr(ubi, ai->vidh); ubi_free_vid_buf(ai->vidb);
out_ech: out_ech:
kfree(ai->ech); kfree(ai->ech);
return err; return err;
...@@ -1510,8 +1511,8 @@ static int scan_fast(struct ubi_device *ubi, struct ubi_attach_info **ai) ...@@ -1510,8 +1511,8 @@ static int scan_fast(struct ubi_device *ubi, struct ubi_attach_info **ai)
if (!scan_ai->ech) if (!scan_ai->ech)
goto out_ai; goto out_ai;
scan_ai->vidh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL); scan_ai->vidb = ubi_alloc_vid_buf(ubi, GFP_KERNEL);
if (!scan_ai->vidh) if (!scan_ai->vidb)
goto out_ech; goto out_ech;
for (pnum = 0; pnum < UBI_FM_MAX_START; pnum++) { for (pnum = 0; pnum < UBI_FM_MAX_START; pnum++) {
...@@ -1523,7 +1524,7 @@ static int scan_fast(struct ubi_device *ubi, struct ubi_attach_info **ai) ...@@ -1523,7 +1524,7 @@ static int scan_fast(struct ubi_device *ubi, struct ubi_attach_info **ai)
goto out_vidh; goto out_vidh;
} }
ubi_free_vid_hdr(ubi, scan_ai->vidh); ubi_free_vid_buf(scan_ai->vidb);
kfree(scan_ai->ech); kfree(scan_ai->ech);
if (scan_ai->force_full_scan) if (scan_ai->force_full_scan)
...@@ -1544,7 +1545,7 @@ static int scan_fast(struct ubi_device *ubi, struct ubi_attach_info **ai) ...@@ -1544,7 +1545,7 @@ static int scan_fast(struct ubi_device *ubi, struct ubi_attach_info **ai)
return err; return err;
out_vidh: out_vidh:
ubi_free_vid_hdr(ubi, scan_ai->vidh); ubi_free_vid_buf(scan_ai->vidb);
out_ech: out_ech:
kfree(scan_ai->ech); kfree(scan_ai->ech);
out_ai: out_ai:
...@@ -1668,7 +1669,8 @@ int ubi_attach(struct ubi_device *ubi, int force_scan) ...@@ -1668,7 +1669,8 @@ int ubi_attach(struct ubi_device *ubi, int force_scan)
*/ */
static int self_check_ai(struct ubi_device *ubi, struct ubi_attach_info *ai) static int self_check_ai(struct ubi_device *ubi, struct ubi_attach_info *ai)
{ {
struct ubi_vid_hdr *vidh = ai->vidh; struct ubi_vid_io_buf *vidb = ai->vidb;
struct ubi_vid_hdr *vidh = ubi_get_vid_hdr(vidb);
int pnum, err, vols_found = 0; int pnum, err, vols_found = 0;
struct rb_node *rb1, *rb2; struct rb_node *rb1, *rb2;
struct ubi_ainf_volume *av; struct ubi_ainf_volume *av;
...@@ -1804,7 +1806,7 @@ static int self_check_ai(struct ubi_device *ubi, struct ubi_attach_info *ai) ...@@ -1804,7 +1806,7 @@ static int self_check_ai(struct ubi_device *ubi, struct ubi_attach_info *ai)
last_aeb = aeb; last_aeb = aeb;
err = ubi_io_read_vid_hdr(ubi, aeb->pnum, vidh, 1); err = ubi_io_read_vid_hdr(ubi, aeb->pnum, vidb, 1);
if (err && err != UBI_IO_BITFLIPS) { if (err && err != UBI_IO_BITFLIPS) {
ubi_err(ubi, "VID header is not OK (%d)", ubi_err(ubi, "VID header is not OK (%d)",
err); err);
......
...@@ -513,6 +513,7 @@ int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, ...@@ -513,6 +513,7 @@ 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 err, pnum, scrub = 0, vol_id = vol->vol_id; int err, pnum, scrub = 0, vol_id = vol->vol_id;
struct ubi_vid_io_buf *vidb;
struct ubi_vid_hdr *vid_hdr; struct ubi_vid_hdr *vid_hdr;
uint32_t uninitialized_var(crc); uint32_t uninitialized_var(crc);
...@@ -543,13 +544,15 @@ int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, ...@@ -543,13 +544,15 @@ int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
retry: retry:
if (check) { if (check) {
vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS); vidb = ubi_alloc_vid_buf(ubi, GFP_NOFS);
if (!vid_hdr) { if (!vidb) {
err = -ENOMEM; err = -ENOMEM;
goto out_unlock; goto out_unlock;
} }
err = ubi_io_read_vid_hdr(ubi, pnum, vid_hdr, 1); vid_hdr = ubi_get_vid_hdr(vidb);
err = ubi_io_read_vid_hdr(ubi, pnum, vidb, 1);
if (err && err != UBI_IO_BITFLIPS) { if (err && err != UBI_IO_BITFLIPS) {
if (err > 0) { if (err > 0) {
/* /*
...@@ -595,7 +598,7 @@ int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, ...@@ -595,7 +598,7 @@ int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
ubi_assert(len == be32_to_cpu(vid_hdr->data_size)); ubi_assert(len == be32_to_cpu(vid_hdr->data_size));
crc = be32_to_cpu(vid_hdr->data_crc); crc = be32_to_cpu(vid_hdr->data_crc);
ubi_free_vid_hdr(ubi, vid_hdr); ubi_free_vid_buf(vidb);
} }
err = ubi_io_read_data(ubi, buf, pnum, offset, len); err = ubi_io_read_data(ubi, buf, pnum, offset, len);
...@@ -632,7 +635,7 @@ int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, ...@@ -632,7 +635,7 @@ int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
return err; return err;
out_free: out_free:
ubi_free_vid_hdr(ubi, vid_hdr); ubi_free_vid_buf(vidb);
out_unlock: out_unlock:
leb_read_unlock(ubi, vol_id, lnum); leb_read_unlock(ubi, vol_id, lnum);
return err; return err;
...@@ -701,7 +704,7 @@ int ubi_eba_read_leb_sg(struct ubi_device *ubi, struct ubi_volume *vol, ...@@ -701,7 +704,7 @@ int ubi_eba_read_leb_sg(struct ubi_device *ubi, struct ubi_volume *vol,
* @buf: data which was not written because of the write failure * @buf: data which was not written because of the write failure
* @offset: offset of the failed write * @offset: offset of the failed write
* @len: how many bytes should have been written * @len: how many bytes should have been written
* @vid: VID header * @vidb: VID buffer
* @retry: whether the caller should retry in case of failure * @retry: whether the caller should retry in case of failure
* *
* This function is called in case of a write failure and moves all good data * This function is called in case of a write failure and moves all good data
...@@ -713,9 +716,10 @@ int ubi_eba_read_leb_sg(struct ubi_device *ubi, struct ubi_volume *vol, ...@@ -713,9 +716,10 @@ int ubi_eba_read_leb_sg(struct ubi_device *ubi, struct ubi_volume *vol,
*/ */
static int try_recover_peb(struct ubi_volume *vol, int pnum, int lnum, static int try_recover_peb(struct ubi_volume *vol, int pnum, int lnum,
const void *buf, int offset, int len, const void *buf, int offset, int len,
struct ubi_vid_hdr *vid_hdr, bool *retry) struct ubi_vid_io_buf *vidb, bool *retry)
{ {
struct ubi_device *ubi = vol->ubi; struct ubi_device *ubi = vol->ubi;
struct ubi_vid_hdr *vid_hdr;
int new_pnum, err, vol_id = vol->vol_id, data_size; int new_pnum, err, vol_id = vol->vol_id, data_size;
uint32_t crc; uint32_t crc;
...@@ -730,7 +734,7 @@ static int try_recover_peb(struct ubi_volume *vol, int pnum, int lnum, ...@@ -730,7 +734,7 @@ static int try_recover_peb(struct ubi_volume *vol, int pnum, int lnum,
ubi_msg(ubi, "recover PEB %d, move data to PEB %d", ubi_msg(ubi, "recover PEB %d, move data to PEB %d",
pnum, new_pnum); pnum, new_pnum);
err = ubi_io_read_vid_hdr(ubi, pnum, vid_hdr, 1); err = ubi_io_read_vid_hdr(ubi, pnum, vidb, 1);
if (err && err != UBI_IO_BITFLIPS) { if (err && err != UBI_IO_BITFLIPS) {
if (err > 0) if (err > 0)
err = -EIO; err = -EIO;
...@@ -759,7 +763,7 @@ static int try_recover_peb(struct ubi_volume *vol, int pnum, int lnum, ...@@ -759,7 +763,7 @@ static int try_recover_peb(struct ubi_volume *vol, int pnum, int lnum,
vid_hdr->copy_flag = 1; vid_hdr->copy_flag = 1;
vid_hdr->data_size = cpu_to_be32(data_size); vid_hdr->data_size = cpu_to_be32(data_size);
vid_hdr->data_crc = cpu_to_be32(crc); vid_hdr->data_crc = cpu_to_be32(crc);
err = ubi_io_write_vid_hdr(ubi, new_pnum, vid_hdr); err = ubi_io_write_vid_hdr(ubi, new_pnum, vidb);
if (err) if (err)
goto out_unlock; goto out_unlock;
...@@ -810,24 +814,24 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum, ...@@ -810,24 +814,24 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum,
{ {
int err, idx = vol_id2idx(ubi, vol_id), tries; int err, idx = vol_id2idx(ubi, vol_id), tries;
struct ubi_volume *vol = ubi->volumes[idx]; struct ubi_volume *vol = ubi->volumes[idx];
struct ubi_vid_hdr *vid_hdr; struct ubi_vid_io_buf *vidb;
vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS); vidb = ubi_alloc_vid_buf(ubi, GFP_NOFS);
if (!vid_hdr) if (!vidb)
return -ENOMEM; return -ENOMEM;
for (tries = 0; tries <= UBI_IO_RETRIES; tries++) { for (tries = 0; tries <= UBI_IO_RETRIES; tries++) {
bool retry; bool retry;
err = try_recover_peb(vol, pnum, lnum, buf, offset, len, err = try_recover_peb(vol, pnum, lnum, buf, offset, len, vidb,
vid_hdr, &retry); &retry);
if (!err || !retry) if (!err || !retry)
break; break;
ubi_msg(ubi, "try again"); ubi_msg(ubi, "try again");
} }
ubi_free_vid_hdr(ubi, vid_hdr); ubi_free_vid_buf(vidb);
return err; return err;
} }
...@@ -836,7 +840,7 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum, ...@@ -836,7 +840,7 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum,
* try_write_vid_and_data - try to write VID header and data to a new PEB. * try_write_vid_and_data - try to write VID header and data to a new PEB.
* @vol: volume description object * @vol: volume description object
* @lnum: logical eraseblock number * @lnum: logical eraseblock number
* @vid_hdr: VID header to write * @vidb: the VID buffer to write
* @buf: buffer containing the data * @buf: buffer containing the data
* @offset: where to start writing data * @offset: where to start writing data
* @len: how many bytes should be written * @len: how many bytes should be written
...@@ -848,7 +852,7 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum, ...@@ -848,7 +852,7 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum,
* flash media, but may be some garbage. * flash media, but may be some garbage.
*/ */
static int try_write_vid_and_data(struct ubi_volume *vol, int lnum, static int try_write_vid_and_data(struct ubi_volume *vol, int lnum,
struct ubi_vid_hdr *vid_hdr, const void *buf, struct ubi_vid_io_buf *vidb, const void *buf,
int offset, int len) int offset, int len)
{ {
struct ubi_device *ubi = vol->ubi; struct ubi_device *ubi = vol->ubi;
...@@ -865,7 +869,7 @@ static int try_write_vid_and_data(struct ubi_volume *vol, int lnum, ...@@ -865,7 +869,7 @@ static int try_write_vid_and_data(struct ubi_volume *vol, int lnum,
dbg_eba("write VID hdr and %d bytes at offset %d of LEB %d:%d, PEB %d", dbg_eba("write VID hdr and %d bytes at offset %d of LEB %d:%d, PEB %d",
len, offset, vol_id, lnum, pnum); len, offset, vol_id, lnum, pnum);
err = ubi_io_write_vid_hdr(ubi, pnum, vid_hdr); err = ubi_io_write_vid_hdr(ubi, pnum, vidb);
if (err) { if (err) {
ubi_warn(ubi, "failed to write VID header to LEB %d:%d, PEB %d", ubi_warn(ubi, "failed to write VID header to LEB %d:%d, PEB %d",
vol_id, lnum, pnum); vol_id, lnum, pnum);
...@@ -914,6 +918,7 @@ int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, ...@@ -914,6 +918,7 @@ int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
const void *buf, int offset, int len) const void *buf, int offset, int len)
{ {
int err, pnum, tries, vol_id = vol->vol_id; int err, pnum, tries, vol_id = vol->vol_id;
struct ubi_vid_io_buf *vidb;
struct ubi_vid_hdr *vid_hdr; struct ubi_vid_hdr *vid_hdr;
if (ubi->ro_mode) if (ubi->ro_mode)
...@@ -943,12 +948,14 @@ int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, ...@@ -943,12 +948,14 @@ int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
* The logical eraseblock is not mapped. We have to get a free physical * The logical eraseblock is not mapped. We have to get a free physical
* eraseblock and write the volume identifier header there first. * eraseblock and write the volume identifier header there first.
*/ */
vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS); vidb = ubi_alloc_vid_buf(ubi, GFP_NOFS);
if (!vid_hdr) { if (!vidb) {
leb_write_unlock(ubi, vol_id, lnum); leb_write_unlock(ubi, vol_id, lnum);
return -ENOMEM; return -ENOMEM;
} }
vid_hdr = ubi_get_vid_hdr(vidb);
vid_hdr->vol_type = UBI_VID_DYNAMIC; vid_hdr->vol_type = UBI_VID_DYNAMIC;
vid_hdr->sqnum = cpu_to_be64(ubi_next_sqnum(ubi)); vid_hdr->sqnum = cpu_to_be64(ubi_next_sqnum(ubi));
vid_hdr->vol_id = cpu_to_be32(vol_id); vid_hdr->vol_id = cpu_to_be32(vol_id);
...@@ -957,8 +964,7 @@ int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, ...@@ -957,8 +964,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);
for (tries = 0; tries <= UBI_IO_RETRIES; tries++) { for (tries = 0; tries <= UBI_IO_RETRIES; tries++) {
err = try_write_vid_and_data(vol, lnum, vid_hdr, buf, offset, err = try_write_vid_and_data(vol, lnum, vidb, buf, offset, len);
len);
if (err != -EIO || !ubi->bad_allowed) if (err != -EIO || !ubi->bad_allowed)
break; break;
...@@ -972,7 +978,7 @@ int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, ...@@ -972,7 +978,7 @@ int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
ubi_msg(ubi, "try another PEB"); ubi_msg(ubi, "try another PEB");
} }
ubi_free_vid_hdr(ubi, vid_hdr); ubi_free_vid_buf(vidb);
out: out:
if (err) if (err)
...@@ -1009,6 +1015,7 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol, ...@@ -1009,6 +1015,7 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol,
int lnum, const void *buf, int len, int used_ebs) int lnum, const void *buf, int len, int used_ebs)
{ {
int err, tries, data_size = len, vol_id = vol->vol_id; int err, tries, data_size = len, vol_id = vol->vol_id;
struct ubi_vid_io_buf *vidb;
struct ubi_vid_hdr *vid_hdr; struct ubi_vid_hdr *vid_hdr;
uint32_t crc; uint32_t crc;
...@@ -1021,10 +1028,12 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol, ...@@ -1021,10 +1028,12 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol,
else else
ubi_assert(!(len & (ubi->min_io_size - 1))); ubi_assert(!(len & (ubi->min_io_size - 1)));
vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS); vidb = ubi_alloc_vid_buf(ubi, GFP_NOFS);
if (!vid_hdr) if (!vidb)
return -ENOMEM; return -ENOMEM;
vid_hdr = ubi_get_vid_hdr(vidb);
err = leb_write_lock(ubi, vol_id, lnum); err = leb_write_lock(ubi, vol_id, lnum);
if (err) if (err)
goto out; goto out;
...@@ -1044,7 +1053,7 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol, ...@@ -1044,7 +1053,7 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol,
ubi_assert(vol->eba_tbl->entries[lnum].pnum < 0); ubi_assert(vol->eba_tbl->entries[lnum].pnum < 0);
for (tries = 0; tries <= UBI_IO_RETRIES; tries++) { for (tries = 0; tries <= UBI_IO_RETRIES; tries++) {
err = try_write_vid_and_data(vol, lnum, vid_hdr, buf, 0, len); err = try_write_vid_and_data(vol, lnum, vidb, buf, 0, len);
if (err != -EIO || !ubi->bad_allowed) if (err != -EIO || !ubi->bad_allowed)
break; break;
...@@ -1058,7 +1067,7 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol, ...@@ -1058,7 +1067,7 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol,
leb_write_unlock(ubi, vol_id, lnum); leb_write_unlock(ubi, vol_id, lnum);
out: out:
ubi_free_vid_hdr(ubi, vid_hdr); ubi_free_vid_buf(vidb);
return err; return err;
} }
...@@ -1084,6 +1093,7 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol, ...@@ -1084,6 +1093,7 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
int lnum, const void *buf, int len) int lnum, const void *buf, int len)
{ {
int err, tries, vol_id = vol->vol_id; int err, tries, vol_id = vol->vol_id;
struct ubi_vid_io_buf *vidb;
struct ubi_vid_hdr *vid_hdr; struct ubi_vid_hdr *vid_hdr;
uint32_t crc; uint32_t crc;
...@@ -1101,10 +1111,12 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol, ...@@ -1101,10 +1111,12 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
return ubi_eba_write_leb(ubi, vol, lnum, NULL, 0, 0); return ubi_eba_write_leb(ubi, vol, lnum, NULL, 0, 0);
} }
vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS); vidb = ubi_alloc_vid_buf(ubi, GFP_NOFS);
if (!vid_hdr) if (!vidb)
return -ENOMEM; return -ENOMEM;
vid_hdr = ubi_get_vid_hdr(vidb);
mutex_lock(&ubi->alc_mutex); mutex_lock(&ubi->alc_mutex);
err = leb_write_lock(ubi, vol_id, lnum); err = leb_write_lock(ubi, vol_id, lnum);
if (err) if (err)
...@@ -1125,7 +1137,7 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol, ...@@ -1125,7 +1137,7 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
dbg_eba("change LEB %d:%d", vol_id, lnum); dbg_eba("change LEB %d:%d", vol_id, lnum);
for (tries = 0; tries <= UBI_IO_RETRIES; tries++) { for (tries = 0; tries <= UBI_IO_RETRIES; tries++) {
err = try_write_vid_and_data(vol, lnum, vid_hdr, buf, 0, len); err = try_write_vid_and_data(vol, lnum, vidb, buf, 0, len);
if (err != -EIO || !ubi->bad_allowed) if (err != -EIO || !ubi->bad_allowed)
break; break;
...@@ -1145,7 +1157,7 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol, ...@@ -1145,7 +1157,7 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
out_mutex: out_mutex:
mutex_unlock(&ubi->alc_mutex); mutex_unlock(&ubi->alc_mutex);
ubi_free_vid_hdr(ubi, vid_hdr); ubi_free_vid_buf(vidb);
return err; return err;
} }
...@@ -1191,9 +1203,10 @@ static int is_error_sane(int err) ...@@ -1191,9 +1203,10 @@ static int is_error_sane(int err)
* o a negative error code in case of failure. * o a negative error code in case of failure.
*/ */
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_io_buf *vidb)
{ {
int err, vol_id, lnum, data_size, aldata_size, idx; int err, vol_id, lnum, data_size, aldata_size, idx;
struct ubi_vid_hdr *vid_hdr = ubi_get_vid_hdr(vidb);
struct ubi_volume *vol; struct ubi_volume *vol;
uint32_t crc; uint32_t crc;
...@@ -1305,7 +1318,7 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, ...@@ -1305,7 +1318,7 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
} }
vid_hdr->sqnum = cpu_to_be64(ubi_next_sqnum(ubi)); vid_hdr->sqnum = cpu_to_be64(ubi_next_sqnum(ubi));
err = ubi_io_write_vid_hdr(ubi, to, vid_hdr); err = ubi_io_write_vid_hdr(ubi, to, vidb);
if (err) { if (err) {
if (err == -EIO) if (err == -EIO)
err = MOVE_TARGET_WR_ERR; err = MOVE_TARGET_WR_ERR;
...@@ -1315,7 +1328,7 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, ...@@ -1315,7 +1328,7 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
cond_resched(); cond_resched();
/* Read the VID header back and check if it was written correctly */ /* Read the VID header back and check if it was written correctly */
err = ubi_io_read_vid_hdr(ubi, to, vid_hdr, 1); err = ubi_io_read_vid_hdr(ubi, to, vidb, 1);
if (err) { if (err) {
if (err != UBI_IO_BITFLIPS) { if (err != UBI_IO_BITFLIPS) {
ubi_warn(ubi, "error %d while reading VID header back from PEB %d", ubi_warn(ubi, "error %d while reading VID header back from PEB %d",
......
...@@ -110,21 +110,23 @@ size_t ubi_calc_fm_size(struct ubi_device *ubi) ...@@ -110,21 +110,23 @@ size_t ubi_calc_fm_size(struct ubi_device *ubi)
* Returns a new struct ubi_vid_hdr on success. * Returns a new struct ubi_vid_hdr on success.
* NULL indicates out of memory. * NULL indicates out of memory.
*/ */
static struct ubi_vid_hdr *new_fm_vhdr(struct ubi_device *ubi, int vol_id) static struct ubi_vid_io_buf *new_fm_vbuf(struct ubi_device *ubi, int vol_id)
{ {
struct ubi_vid_hdr *new; struct ubi_vid_io_buf *new;
struct ubi_vid_hdr *vh;
new = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL); new = ubi_alloc_vid_buf(ubi, GFP_KERNEL);
if (!new) if (!new)
goto out; goto out;
new->vol_type = UBI_VID_DYNAMIC; vh = ubi_get_vid_hdr(new);
new->vol_id = cpu_to_be32(vol_id); vh->vol_type = UBI_VID_DYNAMIC;
vh->vol_id = cpu_to_be32(vol_id);
/* UBI implementations without fastmap support have to delete the /* UBI implementations without fastmap support have to delete the
* fastmap. * fastmap.
*/ */
new->compat = UBI_COMPAT_DELETE; vh->compat = UBI_COMPAT_DELETE;
out: out:
return new; return new;
...@@ -408,6 +410,7 @@ static int scan_pool(struct ubi_device *ubi, struct ubi_attach_info *ai, ...@@ -408,6 +410,7 @@ static int scan_pool(struct ubi_device *ubi, struct ubi_attach_info *ai,
__be32 *pebs, int pool_size, unsigned long long *max_sqnum, __be32 *pebs, int pool_size, unsigned long long *max_sqnum,
struct list_head *free) struct list_head *free)
{ {
struct ubi_vid_io_buf *vb;
struct ubi_vid_hdr *vh; struct ubi_vid_hdr *vh;
struct ubi_ec_hdr *ech; struct ubi_ec_hdr *ech;
struct ubi_ainf_peb *new_aeb; struct ubi_ainf_peb *new_aeb;
...@@ -417,12 +420,14 @@ static int scan_pool(struct ubi_device *ubi, struct ubi_attach_info *ai, ...@@ -417,12 +420,14 @@ static int scan_pool(struct ubi_device *ubi, struct ubi_attach_info *ai,
if (!ech) if (!ech)
return -ENOMEM; return -ENOMEM;
vh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL); vb = ubi_alloc_vid_buf(ubi, GFP_KERNEL);
if (!vh) { if (!vb) {
kfree(ech); kfree(ech);
return -ENOMEM; return -ENOMEM;
} }
vh = ubi_get_vid_hdr(vb);
dbg_bld("scanning fastmap pool: size = %i", pool_size); dbg_bld("scanning fastmap pool: size = %i", pool_size);
/* /*
...@@ -463,7 +468,7 @@ static int scan_pool(struct ubi_device *ubi, struct ubi_attach_info *ai, ...@@ -463,7 +468,7 @@ static int scan_pool(struct ubi_device *ubi, struct ubi_attach_info *ai,
goto out; goto out;
} }
err = ubi_io_read_vid_hdr(ubi, pnum, vh, 0); err = ubi_io_read_vid_hdr(ubi, pnum, vb, 0);
if (err == UBI_IO_FF || err == UBI_IO_FF_BITFLIPS) { if (err == UBI_IO_FF || err == UBI_IO_FF_BITFLIPS) {
unsigned long long ec = be64_to_cpu(ech->ec); unsigned long long ec = be64_to_cpu(ech->ec);
unmap_peb(ai, pnum); unmap_peb(ai, pnum);
...@@ -509,7 +514,7 @@ static int scan_pool(struct ubi_device *ubi, struct ubi_attach_info *ai, ...@@ -509,7 +514,7 @@ static int scan_pool(struct ubi_device *ubi, struct ubi_attach_info *ai,
} }
out: out:
ubi_free_vid_hdr(ubi, vh); ubi_free_vid_buf(vb);
kfree(ech); kfree(ech);
return ret; return ret;
} }
...@@ -837,6 +842,7 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai, ...@@ -837,6 +842,7 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai,
struct ubi_attach_info *scan_ai) struct ubi_attach_info *scan_ai)
{ {
struct ubi_fm_sb *fmsb, *fmsb2; struct ubi_fm_sb *fmsb, *fmsb2;
struct ubi_vid_io_buf *vb;
struct ubi_vid_hdr *vh; struct ubi_vid_hdr *vh;
struct ubi_ec_hdr *ech; struct ubi_ec_hdr *ech;
struct ubi_fastmap_layout *fm; struct ubi_fastmap_layout *fm;
...@@ -912,12 +918,14 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai, ...@@ -912,12 +918,14 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai,
goto free_fm_sb; goto free_fm_sb;
} }
vh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL); vb = ubi_alloc_vid_buf(ubi, GFP_KERNEL);
if (!vh) { if (!vb) {
ret = -ENOMEM; ret = -ENOMEM;
goto free_hdr; goto free_hdr;
} }
vh = ubi_get_vid_hdr(vb);
for (i = 0; i < used_blocks; i++) { for (i = 0; i < used_blocks; i++) {
int image_seq; int image_seq;
...@@ -960,7 +968,7 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai, ...@@ -960,7 +968,7 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai,
goto free_hdr; goto free_hdr;
} }
ret = ubi_io_read_vid_hdr(ubi, pnum, vh, 0); ret = ubi_io_read_vid_hdr(ubi, pnum, vb, 0);
if (ret && ret != UBI_IO_BITFLIPS) { if (ret && ret != UBI_IO_BITFLIPS) {
ubi_err(ubi, "unable to read fastmap block# %i (PEB: %i)", ubi_err(ubi, "unable to read fastmap block# %i (PEB: %i)",
i, pnum); i, pnum);
...@@ -1050,7 +1058,7 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai, ...@@ -1050,7 +1058,7 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai,
ubi->fm_disabled = 0; ubi->fm_disabled = 0;
ubi->fast_attach = 1; ubi->fast_attach = 1;
ubi_free_vid_hdr(ubi, vh); ubi_free_vid_buf(vb);
kfree(ech); kfree(ech);
out: out:
up_write(&ubi->fm_protect); up_write(&ubi->fm_protect);
...@@ -1059,7 +1067,7 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai, ...@@ -1059,7 +1067,7 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai,
return ret; return ret;
free_hdr: free_hdr:
ubi_free_vid_hdr(ubi, vh); ubi_free_vid_buf(vb);
kfree(ech); kfree(ech);
free_fm_sb: free_fm_sb:
kfree(fmsb); kfree(fmsb);
...@@ -1087,6 +1095,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi, ...@@ -1087,6 +1095,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi,
struct ubi_fm_eba *feba; struct ubi_fm_eba *feba;
struct ubi_wl_entry *wl_e; struct ubi_wl_entry *wl_e;
struct ubi_volume *vol; struct ubi_volume *vol;
struct ubi_vid_io_buf *avbuf, *dvbuf;
struct ubi_vid_hdr *avhdr, *dvhdr; struct ubi_vid_hdr *avhdr, *dvhdr;
struct ubi_work *ubi_wrk; struct ubi_work *ubi_wrk;
struct rb_node *tmp_rb; struct rb_node *tmp_rb;
...@@ -1097,18 +1106,21 @@ static int ubi_write_fastmap(struct ubi_device *ubi, ...@@ -1097,18 +1106,21 @@ static int ubi_write_fastmap(struct ubi_device *ubi,
fm_raw = ubi->fm_buf; fm_raw = ubi->fm_buf;
memset(ubi->fm_buf, 0, ubi->fm_size); memset(ubi->fm_buf, 0, ubi->fm_size);
avhdr = new_fm_vhdr(ubi, UBI_FM_SB_VOLUME_ID); avbuf = new_fm_vbuf(ubi, UBI_FM_SB_VOLUME_ID);
if (!avhdr) { if (!avbuf) {
ret = -ENOMEM; ret = -ENOMEM;
goto out; goto out;
} }
dvhdr = new_fm_vhdr(ubi, UBI_FM_DATA_VOLUME_ID); dvbuf = new_fm_vbuf(ubi, UBI_FM_DATA_VOLUME_ID);
if (!dvhdr) { if (!dvbuf) {
ret = -ENOMEM; ret = -ENOMEM;
goto out_kfree; goto out_kfree;
} }
avhdr = ubi_get_vid_hdr(avbuf);
dvhdr = ubi_get_vid_hdr(dvbuf);
seen_pebs = init_seen(ubi); seen_pebs = init_seen(ubi);
if (IS_ERR(seen_pebs)) { if (IS_ERR(seen_pebs)) {
ret = PTR_ERR(seen_pebs); ret = PTR_ERR(seen_pebs);
...@@ -1277,7 +1289,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi, ...@@ -1277,7 +1289,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi,
spin_unlock(&ubi->volumes_lock); spin_unlock(&ubi->volumes_lock);
dbg_bld("writing fastmap SB to PEB %i", new_fm->e[0]->pnum); dbg_bld("writing fastmap SB to PEB %i", new_fm->e[0]->pnum);
ret = ubi_io_write_vid_hdr(ubi, new_fm->e[0]->pnum, avhdr); ret = ubi_io_write_vid_hdr(ubi, new_fm->e[0]->pnum, avbuf);
if (ret) { if (ret) {
ubi_err(ubi, "unable to write vid_hdr to fastmap SB!"); ubi_err(ubi, "unable to write vid_hdr to fastmap SB!");
goto out_kfree; goto out_kfree;
...@@ -1298,7 +1310,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi, ...@@ -1298,7 +1310,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi,
dvhdr->lnum = cpu_to_be32(i); dvhdr->lnum = cpu_to_be32(i);
dbg_bld("writing fastmap data to PEB %i sqnum %llu", dbg_bld("writing fastmap data to PEB %i sqnum %llu",
new_fm->e[i]->pnum, be64_to_cpu(dvhdr->sqnum)); new_fm->e[i]->pnum, be64_to_cpu(dvhdr->sqnum));
ret = ubi_io_write_vid_hdr(ubi, new_fm->e[i]->pnum, dvhdr); ret = ubi_io_write_vid_hdr(ubi, new_fm->e[i]->pnum, dvbuf);
if (ret) { if (ret) {
ubi_err(ubi, "unable to write vid_hdr to PEB %i!", ubi_err(ubi, "unable to write vid_hdr to PEB %i!",
new_fm->e[i]->pnum); new_fm->e[i]->pnum);
...@@ -1323,8 +1335,8 @@ static int ubi_write_fastmap(struct ubi_device *ubi, ...@@ -1323,8 +1335,8 @@ static int ubi_write_fastmap(struct ubi_device *ubi,
dbg_bld("fastmap written!"); dbg_bld("fastmap written!");
out_kfree: out_kfree:
ubi_free_vid_hdr(ubi, avhdr); ubi_free_vid_buf(avbuf);
ubi_free_vid_hdr(ubi, dvhdr); ubi_free_vid_buf(dvbuf);
free_seen(seen_pebs); free_seen(seen_pebs);
out: out:
return ret; return ret;
...@@ -1394,7 +1406,8 @@ static int invalidate_fastmap(struct ubi_device *ubi) ...@@ -1394,7 +1406,8 @@ static int invalidate_fastmap(struct ubi_device *ubi)
int ret; int ret;
struct ubi_fastmap_layout *fm; struct ubi_fastmap_layout *fm;
struct ubi_wl_entry *e; struct ubi_wl_entry *e;
struct ubi_vid_hdr *vh = NULL; struct ubi_vid_io_buf *vb = NULL;
struct ubi_vid_hdr *vh;
if (!ubi->fm) if (!ubi->fm)
return 0; return 0;
...@@ -1406,10 +1419,12 @@ static int invalidate_fastmap(struct ubi_device *ubi) ...@@ -1406,10 +1419,12 @@ static int invalidate_fastmap(struct ubi_device *ubi)
if (!fm) if (!fm)
goto out; goto out;
vh = new_fm_vhdr(ubi, UBI_FM_SB_VOLUME_ID); vb = new_fm_vbuf(ubi, UBI_FM_SB_VOLUME_ID);
if (!vh) if (!vb)
goto out_free_fm; goto out_free_fm;
vh = ubi_get_vid_hdr(vb);
ret = -ENOSPC; ret = -ENOSPC;
e = ubi_wl_get_fm_peb(ubi, 1); e = ubi_wl_get_fm_peb(ubi, 1);
if (!e) if (!e)
...@@ -1420,7 +1435,7 @@ static int invalidate_fastmap(struct ubi_device *ubi) ...@@ -1420,7 +1435,7 @@ static int invalidate_fastmap(struct ubi_device *ubi)
* to scanning mode. * to scanning mode.
*/ */
vh->sqnum = cpu_to_be64(ubi_next_sqnum(ubi)); vh->sqnum = cpu_to_be64(ubi_next_sqnum(ubi));
ret = ubi_io_write_vid_hdr(ubi, e->pnum, vh); ret = ubi_io_write_vid_hdr(ubi, e->pnum, vb);
if (ret < 0) { if (ret < 0) {
ubi_wl_put_fm_peb(ubi, e, 0, 0); ubi_wl_put_fm_peb(ubi, e, 0, 0);
goto out_free_fm; goto out_free_fm;
...@@ -1432,7 +1447,7 @@ static int invalidate_fastmap(struct ubi_device *ubi) ...@@ -1432,7 +1447,7 @@ static int invalidate_fastmap(struct ubi_device *ubi)
ubi->fm = fm; ubi->fm = fm;
out: out:
ubi_free_vid_hdr(ubi, vh); ubi_free_vid_buf(vb);
return ret; return ret;
out_free_fm: out_free_fm:
......
...@@ -502,6 +502,7 @@ static int nor_erase_prepare(struct ubi_device *ubi, int pnum) ...@@ -502,6 +502,7 @@ static int nor_erase_prepare(struct ubi_device *ubi, int pnum)
loff_t addr; loff_t addr;
uint32_t data = 0; uint32_t data = 0;
struct ubi_ec_hdr ec_hdr; struct ubi_ec_hdr ec_hdr;
struct ubi_vid_io_buf vidb;
/* /*
* Note, we cannot generally define VID header buffers on stack, * Note, we cannot generally define VID header buffers on stack,
...@@ -528,7 +529,10 @@ static int nor_erase_prepare(struct ubi_device *ubi, int pnum) ...@@ -528,7 +529,10 @@ static int nor_erase_prepare(struct ubi_device *ubi, int pnum)
goto error; goto error;
} }
err = ubi_io_read_vid_hdr(ubi, pnum, &vid_hdr, 0); ubi_init_vid_buf(ubi, &vidb, &vid_hdr);
ubi_assert(&vid_hdr == ubi_get_vid_hdr(&vidb));
err = ubi_io_read_vid_hdr(ubi, pnum, &vidb, 0);
if (err != UBI_IO_BAD_HDR_EBADMSG && err != UBI_IO_BAD_HDR && if (err != UBI_IO_BAD_HDR_EBADMSG && err != UBI_IO_BAD_HDR &&
err != UBI_IO_FF){ err != UBI_IO_FF){
addr += ubi->vid_hdr_aloffset; addr += ubi->vid_hdr_aloffset;
...@@ -995,12 +999,11 @@ static int validate_vid_hdr(const struct ubi_device *ubi, ...@@ -995,12 +999,11 @@ static int validate_vid_hdr(const struct ubi_device *ubi,
* ubi_io_read_vid_hdr - read and check a volume identifier header. * ubi_io_read_vid_hdr - read and check a volume identifier header.
* @ubi: UBI device description object * @ubi: UBI device description object
* @pnum: physical eraseblock number to read from * @pnum: physical eraseblock number to read from
* @vid_hdr: &struct ubi_vid_hdr object where to store the read volume * @vidb: the volume identifier buffer to store data in
* identifier header
* @verbose: be verbose if the header is corrupted or wasn't found * @verbose: be verbose if the header is corrupted or wasn't found
* *
* This function reads the volume identifier header from physical eraseblock * This function reads the volume identifier header from physical eraseblock
* @pnum and stores it in @vid_hdr. It also checks CRC checksum of the read * @pnum and stores it in @vidb. It also checks CRC checksum of the read
* volume identifier header. The error codes are the same as in * volume identifier header. The error codes are the same as in
* 'ubi_io_read_ec_hdr()'. * 'ubi_io_read_ec_hdr()'.
* *
...@@ -1008,16 +1011,16 @@ static int validate_vid_hdr(const struct ubi_device *ubi, ...@@ -1008,16 +1011,16 @@ static int validate_vid_hdr(const struct ubi_device *ubi,
* 'ubi_io_read_ec_hdr()', so refer commentaries in 'ubi_io_read_ec_hdr()'. * 'ubi_io_read_ec_hdr()', so refer commentaries in 'ubi_io_read_ec_hdr()'.
*/ */
int ubi_io_read_vid_hdr(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) struct ubi_vid_io_buf *vidb, int verbose)
{ {
int err, read_err; int err, read_err;
uint32_t crc, magic, hdr_crc; uint32_t crc, magic, hdr_crc;
void *p; struct ubi_vid_hdr *vid_hdr = ubi_get_vid_hdr(vidb);
void *p = vidb->buffer;
dbg_io("read VID header from PEB %d", pnum); dbg_io("read VID header from PEB %d", pnum);
ubi_assert(pnum >= 0 && pnum < ubi->peb_count); ubi_assert(pnum >= 0 && pnum < ubi->peb_count);
p = (char *)vid_hdr - ubi->vid_hdr_shift;
read_err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset, read_err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset,
ubi->vid_hdr_shift + UBI_VID_HDR_SIZE); ubi->vid_hdr_shift + UBI_VID_HDR_SIZE);
if (read_err && read_err != UBI_IO_BITFLIPS && !mtd_is_eccerr(read_err)) if (read_err && read_err != UBI_IO_BITFLIPS && !mtd_is_eccerr(read_err))
...@@ -1080,23 +1083,24 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum, ...@@ -1080,23 +1083,24 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
* ubi_io_write_vid_hdr - write a volume identifier header. * ubi_io_write_vid_hdr - write a volume identifier header.
* @ubi: UBI device description object * @ubi: UBI device description object
* @pnum: the physical eraseblock number to write to * @pnum: the physical eraseblock number to write to
* @vid_hdr: the volume identifier header to write * @vidb: the volume identifier buffer to write
* *
* This function writes the volume identifier header described by @vid_hdr to * This function writes the volume identifier header described by @vid_hdr to
* physical eraseblock @pnum. This function automatically fills the * physical eraseblock @pnum. This function automatically fills the
* @vid_hdr->magic and the @vid_hdr->version fields, as well as calculates * @vidb->hdr->magic and the @vidb->hdr->version fields, as well as calculates
* header CRC checksum and stores it at vid_hdr->hdr_crc. * header CRC checksum and stores it at vidb->hdr->hdr_crc.
* *
* 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. If %-EIO is returned, the physical eraseblock probably went * case of failure. If %-EIO is returned, the physical eraseblock probably went
* bad. * bad.
*/ */
int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum, int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum,
struct ubi_vid_hdr *vid_hdr) struct ubi_vid_io_buf *vidb)
{ {
struct ubi_vid_hdr *vid_hdr = ubi_get_vid_hdr(vidb);
int err; int err;
uint32_t crc; uint32_t crc;
void *p; void *p = vidb->buffer;
dbg_io("write VID header to PEB %d", pnum); dbg_io("write VID header to PEB %d", pnum);
ubi_assert(pnum >= 0 && pnum < ubi->peb_count); ubi_assert(pnum >= 0 && pnum < ubi->peb_count);
...@@ -1117,7 +1121,6 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum, ...@@ -1117,7 +1121,6 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum,
if (ubi_dbg_power_cut(ubi, POWER_CUT_VID_WRITE)) if (ubi_dbg_power_cut(ubi, POWER_CUT_VID_WRITE))
return -EROFS; return -EROFS;
p = (char *)vid_hdr - ubi->vid_hdr_shift;
err = ubi_io_write(ubi, p, pnum, ubi->vid_hdr_aloffset, err = ubi_io_write(ubi, p, pnum, ubi->vid_hdr_aloffset,
ubi->vid_hdr_alsize); ubi->vid_hdr_alsize);
return err; return err;
...@@ -1283,17 +1286,19 @@ static int self_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum) ...@@ -1283,17 +1286,19 @@ static int self_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum)
{ {
int err; int err;
uint32_t crc, hdr_crc; uint32_t crc, hdr_crc;
struct ubi_vid_io_buf *vidb;
struct ubi_vid_hdr *vid_hdr; struct ubi_vid_hdr *vid_hdr;
void *p; void *p;
if (!ubi_dbg_chk_io(ubi)) if (!ubi_dbg_chk_io(ubi))
return 0; return 0;
vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS); vidb = ubi_alloc_vid_buf(ubi, GFP_NOFS);
if (!vid_hdr) if (!vidb)
return -ENOMEM; return -ENOMEM;
p = (char *)vid_hdr - ubi->vid_hdr_shift; vid_hdr = ubi_get_vid_hdr(vidb);
p = vidb->buffer;
err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset, err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset,
ubi->vid_hdr_alsize); ubi->vid_hdr_alsize);
if (err && err != UBI_IO_BITFLIPS && !mtd_is_eccerr(err)) if (err && err != UBI_IO_BITFLIPS && !mtd_is_eccerr(err))
...@@ -1314,7 +1319,7 @@ static int self_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum) ...@@ -1314,7 +1319,7 @@ static int self_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum)
err = self_check_vid_hdr(ubi, pnum, vid_hdr); err = self_check_vid_hdr(ubi, pnum, vid_hdr);
exit: exit:
ubi_free_vid_hdr(ubi, vid_hdr); ubi_free_vid_buf(vidb);
return err; return err;
} }
......
...@@ -166,6 +166,17 @@ enum { ...@@ -166,6 +166,17 @@ enum {
POWER_CUT_VID_WRITE = 0x02, POWER_CUT_VID_WRITE = 0x02,
}; };
/**
* struct ubi_vid_io_buf - VID buffer used to read/write VID info to/from the
* flash.
* @hdr: a pointer to the VID header stored in buffer
* @buffer: underlying buffer
*/
struct ubi_vid_io_buf {
struct ubi_vid_hdr *hdr;
void *buffer;
};
/** /**
* struct ubi_wl_entry - wear-leveling entry. * struct ubi_wl_entry - wear-leveling entry.
* @u.rb: link in the corresponding (free/used) RB-tree * @u.rb: link in the corresponding (free/used) RB-tree
...@@ -740,7 +751,7 @@ struct ubi_ainf_volume { ...@@ -740,7 +751,7 @@ struct ubi_ainf_volume {
* @ec_count: 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 * @aeb_slab_cache: slab cache for &struct ubi_ainf_peb objects
* @ech: temporary EC header. Only available during scan * @ech: temporary EC header. Only available during scan
* @vidh: temporary VID header. Only available during scan * @vidh: temporary VID buffer. Only available during scan
* *
* This data structure contains the result of attaching an MTD device and may * 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 * be used by other UBI sub-systems to build final UBI data structures, further
...@@ -770,7 +781,7 @@ struct ubi_attach_info { ...@@ -770,7 +781,7 @@ struct ubi_attach_info {
int ec_count; int ec_count;
struct kmem_cache *aeb_slab_cache; struct kmem_cache *aeb_slab_cache;
struct ubi_ec_hdr *ech; struct ubi_ec_hdr *ech;
struct ubi_vid_hdr *vidh; struct ubi_vid_io_buf *vidb;
}; };
/** /**
...@@ -887,7 +898,7 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol, ...@@ -887,7 +898,7 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol,
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 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_io_buf *vidb);
int ubi_eba_init(struct ubi_device *ubi, struct ubi_attach_info *ai); int ubi_eba_init(struct ubi_device *ubi, struct ubi_attach_info *ai);
unsigned long long ubi_next_sqnum(struct ubi_device *ubi); unsigned long long ubi_next_sqnum(struct ubi_device *ubi);
int self_check_eba(struct ubi_device *ubi, struct ubi_attach_info *ai_fastmap, int self_check_eba(struct ubi_device *ubi, struct ubi_attach_info *ai_fastmap,
...@@ -922,9 +933,9 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum, ...@@ -922,9 +933,9 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
int ubi_io_write_ec_hdr(struct ubi_device *ubi, int pnum, int ubi_io_write_ec_hdr(struct ubi_device *ubi, int pnum,
struct ubi_ec_hdr *ec_hdr); struct ubi_ec_hdr *ec_hdr);
int ubi_io_read_vid_hdr(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); struct ubi_vid_io_buf *vidb, int verbose);
int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum, int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum,
struct ubi_vid_hdr *vid_hdr); struct ubi_vid_io_buf *vidb);
/* build.c */ /* build.c */
int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
...@@ -1045,44 +1056,68 @@ static inline void ubi_move_aeb_to_list(struct ubi_ainf_volume *av, ...@@ -1045,44 +1056,68 @@ static inline void ubi_move_aeb_to_list(struct ubi_ainf_volume *av,
} }
/** /**
* ubi_zalloc_vid_hdr - allocate a volume identifier header object. * ubi_init_vid_buf - Initialize a VID buffer
* @ubi: UBI device description object * @ubi: the UBI device
* @gfp_flags: GFP flags to allocate with * @vidb: the VID buffer to initialize
* * @buf: the underlying buffer
* This function returns a pointer to the newly allocated and zero-filled */
* volume identifier header object in case of success and %NULL in case of static inline void ubi_init_vid_buf(const struct ubi_device *ubi,
* failure. struct ubi_vid_io_buf *vidb,
void *buf)
{
if (buf)
memset(buf, 0, ubi->vid_hdr_alsize);
vidb->buffer = buf;
vidb->hdr = buf + ubi->vid_hdr_shift;
}
/**
* ubi_init_vid_buf - Allocate a VID buffer
* @ubi: the UBI device
* @gfp_flags: GFP flags to use for the allocation
*/ */
static inline struct ubi_vid_hdr * static inline struct ubi_vid_io_buf *
ubi_zalloc_vid_hdr(const struct ubi_device *ubi, gfp_t gfp_flags) ubi_alloc_vid_buf(const struct ubi_device *ubi, gfp_t gfp_flags)
{ {
void *vid_hdr; struct ubi_vid_io_buf *vidb;
void *buf;
vid_hdr = kzalloc(ubi->vid_hdr_alsize, gfp_flags); vidb = kzalloc(sizeof(*vidb), gfp_flags);
if (!vid_hdr) if (!vidb)
return NULL; return NULL;
/* buf = kmalloc(ubi->vid_hdr_alsize, gfp_flags);
* VID headers may be stored at un-aligned flash offsets, so we shift if (!buf) {
* the pointer. kfree(vidb);
*/ return NULL;
return vid_hdr + ubi->vid_hdr_shift; }
ubi_init_vid_buf(ubi, vidb, buf);
return vidb;
} }
/** /**
* ubi_free_vid_hdr - free a volume identifier header object. * ubi_free_vid_buf - Free a VID buffer
* @ubi: UBI device description object * @vidb: the VID buffer to free
* @vid_hdr: the object to free
*/ */
static inline void ubi_free_vid_hdr(const struct ubi_device *ubi, static inline void ubi_free_vid_buf(struct ubi_vid_io_buf *vidb)
struct ubi_vid_hdr *vid_hdr)
{ {
void *p = vid_hdr; if (!vidb)
if (!p)
return; return;
kfree(p - ubi->vid_hdr_shift); kfree(vidb->buffer);
kfree(vidb);
}
/**
* ubi_get_vid_hdr - Get the VID header attached to a VID buffer
* @vidb: VID buffer
*/
static inline struct ubi_vid_hdr *ubi_get_vid_hdr(struct ubi_vid_io_buf *vidb)
{
return vidb->hdr;
} }
/* /*
......
...@@ -299,15 +299,18 @@ static int create_vtbl(struct ubi_device *ubi, struct ubi_attach_info *ai, ...@@ -299,15 +299,18 @@ static int create_vtbl(struct ubi_device *ubi, struct ubi_attach_info *ai,
int copy, void *vtbl) int copy, void *vtbl)
{ {
int err, tries = 0; int err, tries = 0;
struct ubi_vid_io_buf *vidb;
struct ubi_vid_hdr *vid_hdr; struct ubi_vid_hdr *vid_hdr;
struct ubi_ainf_peb *new_aeb; struct ubi_ainf_peb *new_aeb;
dbg_gen("create volume table (copy #%d)", copy + 1); dbg_gen("create volume table (copy #%d)", copy + 1);
vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL); vidb = ubi_alloc_vid_buf(ubi, GFP_KERNEL);
if (!vid_hdr) if (!vidb)
return -ENOMEM; return -ENOMEM;
vid_hdr = ubi_get_vid_hdr(vidb);
retry: retry:
new_aeb = ubi_early_get_peb(ubi, ai); new_aeb = ubi_early_get_peb(ubi, ai);
if (IS_ERR(new_aeb)) { if (IS_ERR(new_aeb)) {
...@@ -324,7 +327,7 @@ static int create_vtbl(struct ubi_device *ubi, struct ubi_attach_info *ai, ...@@ -324,7 +327,7 @@ static int create_vtbl(struct ubi_device *ubi, struct ubi_attach_info *ai,
vid_hdr->sqnum = cpu_to_be64(++ai->max_sqnum); vid_hdr->sqnum = cpu_to_be64(++ai->max_sqnum);
/* The EC header is already there, write the VID header */ /* The EC header is already there, write the VID header */
err = ubi_io_write_vid_hdr(ubi, new_aeb->pnum, vid_hdr); err = ubi_io_write_vid_hdr(ubi, new_aeb->pnum, vidb);
if (err) if (err)
goto write_error; goto write_error;
...@@ -339,7 +342,7 @@ static int create_vtbl(struct ubi_device *ubi, struct ubi_attach_info *ai, ...@@ -339,7 +342,7 @@ static int create_vtbl(struct ubi_device *ubi, struct ubi_attach_info *ai,
*/ */
err = ubi_add_to_av(ubi, ai, new_aeb->pnum, new_aeb->ec, vid_hdr, 0); err = ubi_add_to_av(ubi, ai, new_aeb->pnum, new_aeb->ec, vid_hdr, 0);
ubi_free_aeb(ai, new_aeb); ubi_free_aeb(ai, new_aeb);
ubi_free_vid_hdr(ubi, vid_hdr); ubi_free_vid_buf(vidb);
return err; return err;
write_error: write_error:
...@@ -353,7 +356,7 @@ static int create_vtbl(struct ubi_device *ubi, struct ubi_attach_info *ai, ...@@ -353,7 +356,7 @@ static int create_vtbl(struct ubi_device *ubi, struct ubi_attach_info *ai,
} }
ubi_free_aeb(ai, new_aeb); ubi_free_aeb(ai, new_aeb);
out_free: out_free:
ubi_free_vid_hdr(ubi, vid_hdr); ubi_free_vid_buf(vidb);
return err; return err;
} }
......
...@@ -649,6 +649,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, ...@@ -649,6 +649,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
int anchor = wrk->anchor; int anchor = wrk->anchor;
#endif #endif
struct ubi_wl_entry *e1, *e2; struct ubi_wl_entry *e1, *e2;
struct ubi_vid_io_buf *vidb;
struct ubi_vid_hdr *vid_hdr; struct ubi_vid_hdr *vid_hdr;
int dst_leb_clean = 0; int dst_leb_clean = 0;
...@@ -656,10 +657,12 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, ...@@ -656,10 +657,12 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
if (shutdown) if (shutdown)
return 0; return 0;
vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS); vidb = ubi_alloc_vid_buf(ubi, GFP_NOFS);
if (!vid_hdr) if (!vidb)
return -ENOMEM; return -ENOMEM;
vid_hdr = ubi_get_vid_hdr(vidb);
mutex_lock(&ubi->move_mutex); mutex_lock(&ubi->move_mutex);
spin_lock(&ubi->wl_lock); spin_lock(&ubi->wl_lock);
ubi_assert(!ubi->move_from && !ubi->move_to); ubi_assert(!ubi->move_from && !ubi->move_to);
...@@ -753,7 +756,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, ...@@ -753,7 +756,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
* which is being moved was unmapped. * which is being moved was unmapped.
*/ */
err = ubi_io_read_vid_hdr(ubi, e1->pnum, vid_hdr, 0); err = ubi_io_read_vid_hdr(ubi, e1->pnum, vidb, 0);
if (err && err != UBI_IO_BITFLIPS) { if (err && err != UBI_IO_BITFLIPS) {
dst_leb_clean = 1; dst_leb_clean = 1;
if (err == UBI_IO_FF) { if (err == UBI_IO_FF) {
...@@ -790,7 +793,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, ...@@ -790,7 +793,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
vol_id = be32_to_cpu(vid_hdr->vol_id); vol_id = be32_to_cpu(vid_hdr->vol_id);
lnum = be32_to_cpu(vid_hdr->lnum); lnum = be32_to_cpu(vid_hdr->lnum);
err = ubi_eba_copy_leb(ubi, e1->pnum, e2->pnum, vid_hdr); err = ubi_eba_copy_leb(ubi, e1->pnum, e2->pnum, vidb);
if (err) { if (err) {
if (err == MOVE_CANCEL_RACE) { if (err == MOVE_CANCEL_RACE) {
/* /*
...@@ -847,7 +850,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, ...@@ -847,7 +850,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
if (scrubbing) if (scrubbing)
ubi_msg(ubi, "scrubbed PEB %d (LEB %d:%d), data moved to PEB %d", ubi_msg(ubi, "scrubbed PEB %d (LEB %d:%d), data moved to PEB %d",
e1->pnum, vol_id, lnum, e2->pnum); e1->pnum, vol_id, lnum, e2->pnum);
ubi_free_vid_hdr(ubi, vid_hdr); ubi_free_vid_buf(vidb);
spin_lock(&ubi->wl_lock); spin_lock(&ubi->wl_lock);
if (!ubi->move_to_put) { if (!ubi->move_to_put) {
...@@ -913,7 +916,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, ...@@ -913,7 +916,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
ubi->wl_scheduled = 0; ubi->wl_scheduled = 0;
spin_unlock(&ubi->wl_lock); spin_unlock(&ubi->wl_lock);
ubi_free_vid_hdr(ubi, vid_hdr); ubi_free_vid_buf(vidb);
if (dst_leb_clean) { if (dst_leb_clean) {
ensure_wear_leveling(ubi, 1); ensure_wear_leveling(ubi, 1);
} else { } else {
...@@ -937,7 +940,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, ...@@ -937,7 +940,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
ubi->move_to_put = ubi->wl_scheduled = 0; ubi->move_to_put = ubi->wl_scheduled = 0;
spin_unlock(&ubi->wl_lock); spin_unlock(&ubi->wl_lock);
ubi_free_vid_hdr(ubi, vid_hdr); ubi_free_vid_buf(vidb);
wl_entry_destroy(ubi, e1); wl_entry_destroy(ubi, e1);
wl_entry_destroy(ubi, e2); wl_entry_destroy(ubi, e2);
...@@ -951,7 +954,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, ...@@ -951,7 +954,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
ubi->wl_scheduled = 0; ubi->wl_scheduled = 0;
spin_unlock(&ubi->wl_lock); spin_unlock(&ubi->wl_lock);
mutex_unlock(&ubi->move_mutex); mutex_unlock(&ubi->move_mutex);
ubi_free_vid_hdr(ubi, vid_hdr); ubi_free_vid_buf(vidb);
return 0; return 0;
} }
......
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