|
@@ -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)
|
|
|
{
|
|
|
int err, pnum, scrub = 0, vol_id = vol->vol_id;
|
|
|
+ struct ubi_vid_io_buf *vidb;
|
|
|
struct ubi_vid_hdr *vid_hdr;
|
|
|
uint32_t uninitialized_var(crc);
|
|
|
|
|
@@ -543,13 +544,15 @@ int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
|
|
|
|
|
|
retry:
|
|
|
if (check) {
|
|
|
- vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
|
|
|
- if (!vid_hdr) {
|
|
|
+ vidb = ubi_alloc_vid_buf(ubi, GFP_NOFS);
|
|
|
+ if (!vidb) {
|
|
|
err = -ENOMEM;
|
|
|
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 > 0) {
|
|
|
/*
|
|
@@ -595,7 +598,7 @@ retry:
|
|
|
ubi_assert(len == be32_to_cpu(vid_hdr->data_size));
|
|
|
|
|
|
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);
|
|
@@ -632,7 +635,7 @@ retry:
|
|
|
return err;
|
|
|
|
|
|
out_free:
|
|
|
- ubi_free_vid_hdr(ubi, vid_hdr);
|
|
|
+ ubi_free_vid_buf(vidb);
|
|
|
out_unlock:
|
|
|
leb_read_unlock(ubi, vol_id, lnum);
|
|
|
return err;
|
|
@@ -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
|
|
|
* @offset: offset of the failed write
|
|
|
* @len: how many bytes should have been written
|
|
|
- * @vid: VID header
|
|
|
+ * @vidb: VID buffer
|
|
|
* @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
|
|
@@ -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,
|
|
|
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_vid_hdr *vid_hdr;
|
|
|
int new_pnum, err, vol_id = vol->vol_id, data_size;
|
|
|
uint32_t crc;
|
|
|
|
|
@@ -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",
|
|
|
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 > 0)
|
|
|
err = -EIO;
|
|
@@ -759,7 +763,7 @@ static int try_recover_peb(struct ubi_volume *vol, int pnum, int lnum,
|
|
|
vid_hdr->copy_flag = 1;
|
|
|
vid_hdr->data_size = cpu_to_be32(data_size);
|
|
|
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)
|
|
|
goto out_unlock;
|
|
|
|
|
@@ -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;
|
|
|
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);
|
|
|
- if (!vid_hdr)
|
|
|
+ vidb = ubi_alloc_vid_buf(ubi, GFP_NOFS);
|
|
|
+ if (!vidb)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
for (tries = 0; tries <= UBI_IO_RETRIES; tries++) {
|
|
|
bool retry;
|
|
|
|
|
|
- err = try_recover_peb(vol, pnum, lnum, buf, offset, len,
|
|
|
- vid_hdr, &retry);
|
|
|
+ err = try_recover_peb(vol, pnum, lnum, buf, offset, len, vidb,
|
|
|
+ &retry);
|
|
|
if (!err || !retry)
|
|
|
break;
|
|
|
|
|
|
ubi_msg(ubi, "try again");
|
|
|
}
|
|
|
|
|
|
- ubi_free_vid_hdr(ubi, vid_hdr);
|
|
|
+ ubi_free_vid_buf(vidb);
|
|
|
|
|
|
return err;
|
|
|
}
|
|
@@ -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.
|
|
|
* @vol: volume description object
|
|
|
* @lnum: logical eraseblock number
|
|
|
- * @vid_hdr: VID header to write
|
|
|
+ * @vidb: the VID buffer to write
|
|
|
* @buf: buffer containing the data
|
|
|
* @offset: where to start writing data
|
|
|
* @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,
|
|
|
* flash media, but may be some garbage.
|
|
|
*/
|
|
|
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)
|
|
|
{
|
|
|
struct ubi_device *ubi = vol->ubi;
|
|
@@ -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",
|
|
|
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) {
|
|
|
ubi_warn(ubi, "failed to write VID header to LEB %d:%d, PEB %d",
|
|
|
vol_id, lnum, pnum);
|
|
@@ -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)
|
|
|
{
|
|
|
int err, pnum, tries, vol_id = vol->vol_id;
|
|
|
+ struct ubi_vid_io_buf *vidb;
|
|
|
struct ubi_vid_hdr *vid_hdr;
|
|
|
|
|
|
if (ubi->ro_mode)
|
|
@@ -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
|
|
|
* eraseblock and write the volume identifier header there first.
|
|
|
*/
|
|
|
- vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
|
|
|
- if (!vid_hdr) {
|
|
|
+ vidb = ubi_alloc_vid_buf(ubi, GFP_NOFS);
|
|
|
+ if (!vidb) {
|
|
|
leb_write_unlock(ubi, vol_id, lnum);
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
|
|
|
+ vid_hdr = ubi_get_vid_hdr(vidb);
|
|
|
+
|
|
|
vid_hdr->vol_type = UBI_VID_DYNAMIC;
|
|
|
vid_hdr->sqnum = cpu_to_be64(ubi_next_sqnum(ubi));
|
|
|
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,
|
|
|
vid_hdr->data_pad = cpu_to_be32(vol->data_pad);
|
|
|
|
|
|
for (tries = 0; tries <= UBI_IO_RETRIES; tries++) {
|
|
|
- err = try_write_vid_and_data(vol, lnum, vid_hdr, buf, offset,
|
|
|
- len);
|
|
|
+ err = try_write_vid_and_data(vol, lnum, vidb, buf, offset, len);
|
|
|
if (err != -EIO || !ubi->bad_allowed)
|
|
|
break;
|
|
|
|
|
@@ -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_free_vid_hdr(ubi, vid_hdr);
|
|
|
+ ubi_free_vid_buf(vidb);
|
|
|
|
|
|
out:
|
|
|
if (err)
|
|
@@ -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 err, tries, data_size = len, vol_id = vol->vol_id;
|
|
|
+ struct ubi_vid_io_buf *vidb;
|
|
|
struct ubi_vid_hdr *vid_hdr;
|
|
|
uint32_t crc;
|
|
|
|
|
@@ -1021,10 +1028,12 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol,
|
|
|
else
|
|
|
ubi_assert(!(len & (ubi->min_io_size - 1)));
|
|
|
|
|
|
- vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
|
|
|
- if (!vid_hdr)
|
|
|
+ vidb = ubi_alloc_vid_buf(ubi, GFP_NOFS);
|
|
|
+ if (!vidb)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
+ vid_hdr = ubi_get_vid_hdr(vidb);
|
|
|
+
|
|
|
err = leb_write_lock(ubi, vol_id, lnum);
|
|
|
if (err)
|
|
|
goto out;
|
|
@@ -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);
|
|
|
|
|
|
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)
|
|
|
break;
|
|
|
|
|
@@ -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);
|
|
|
|
|
|
out:
|
|
|
- ubi_free_vid_hdr(ubi, vid_hdr);
|
|
|
+ ubi_free_vid_buf(vidb);
|
|
|
|
|
|
return err;
|
|
|
}
|
|
@@ -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 err, tries, vol_id = vol->vol_id;
|
|
|
+ struct ubi_vid_io_buf *vidb;
|
|
|
struct ubi_vid_hdr *vid_hdr;
|
|
|
uint32_t crc;
|
|
|
|
|
@@ -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);
|
|
|
}
|
|
|
|
|
|
- vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
|
|
|
- if (!vid_hdr)
|
|
|
+ vidb = ubi_alloc_vid_buf(ubi, GFP_NOFS);
|
|
|
+ if (!vidb)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
+ vid_hdr = ubi_get_vid_hdr(vidb);
|
|
|
+
|
|
|
mutex_lock(&ubi->alc_mutex);
|
|
|
err = leb_write_lock(ubi, vol_id, lnum);
|
|
|
if (err)
|
|
@@ -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);
|
|
|
|
|
|
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)
|
|
|
break;
|
|
|
|
|
@@ -1145,7 +1157,7 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
|
|
|
|
|
|
out_mutex:
|
|
|
mutex_unlock(&ubi->alc_mutex);
|
|
|
- ubi_free_vid_hdr(ubi, vid_hdr);
|
|
|
+ ubi_free_vid_buf(vidb);
|
|
|
return err;
|
|
|
}
|
|
|
|
|
@@ -1191,9 +1203,10 @@ static int is_error_sane(int err)
|
|
|
* o a negative error code in case of failure.
|
|
|
*/
|
|
|
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;
|
|
|
+ struct ubi_vid_hdr *vid_hdr = ubi_get_vid_hdr(vidb);
|
|
|
struct ubi_volume *vol;
|
|
|
uint32_t crc;
|
|
|
|
|
@@ -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));
|
|
|
|
|
|
- err = ubi_io_write_vid_hdr(ubi, to, vid_hdr);
|
|
|
+ err = ubi_io_write_vid_hdr(ubi, to, vidb);
|
|
|
if (err) {
|
|
|
if (err == -EIO)
|
|
|
err = MOVE_TARGET_WR_ERR;
|
|
@@ -1315,7 +1328,7 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
|
|
|
cond_resched();
|
|
|
|
|
|
/* 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 != UBI_IO_BITFLIPS) {
|
|
|
ubi_warn(ubi, "error %d while reading VID header back from PEB %d",
|