Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 68649
b: refs/heads/master
c: e88d6e1
h: refs/heads/master
i:
  68647: 6bbad98
v: v3
  • Loading branch information
Artem Bityutskiy authored and Artem Bityutskiy committed Oct 14, 2007
1 parent 326a72d commit c778e42
Show file tree
Hide file tree
Showing 9 changed files with 120 additions and 113 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 33818bbb84cd371b63ed8849cc5264d24c8b3aa2
refs/heads/master: e88d6e10e5c848fd5be8f89e09e3bce2570886b7
28 changes: 27 additions & 1 deletion trunk/drivers/mtd/ubi/build.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand All @@ -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;
Expand Down
70 changes: 24 additions & 46 deletions trunk/drivers/mtd/ubi/eba.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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;
}
Expand Down Expand Up @@ -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);
Expand All @@ -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.
Expand Down Expand Up @@ -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);
Expand All @@ -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();

/*
Expand Down Expand Up @@ -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",
Expand All @@ -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;
Expand All @@ -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;
}

Expand Down
Loading

0 comments on commit c778e42

Please sign in to comment.