GIT e2a906cd6a10e4c0456a0e4ebfd66f7faff0ea30 git://git.infradead.org/~dedekind/ubi-2.6.git commit e2a906cd6a10e4c0456a0e4ebfd66f7faff0ea30 Author: Christoph Lameter Date: Sat May 12 14:18:18 2007 +0300 UBI: remove inverted check in ltree_entry_ctor Check is inverted and thus the ctor never does what it is supposed to do. The check is poinless since SLAB_CTOR_CONSTRUCTOR is always set. So remove. Signed-off-by: Christoph Lameter Cc: Artem Bityutskiy Cc: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Artem Bityutskiy commit 039d716b8aa22cf3bfd926125ae78d7900ad0bb1 Author: Artem Bityutskiy Date: Sun May 6 16:45:43 2007 +0300 UBI: minor comma fix Use coma at the the last elements of structure initializer. Daniel Stone's explanation: Because it turns: - .attr = foo + .attr = foo, + .bar = baz into: + .bar = baz, i.e., far less likely to screw up a merge. Signed-off-by: Artem Bityutskiy commit 399c9660fefcae1ad74a2fa7ff1597b92821ea32 Author: Artem Bityutskiy Date: Sun May 6 16:12:54 2007 +0300 UBI: use vmalloc for large buffers UBI allocates temporary buffers of PEB size, which may be 256KiB. Use vmalloc instead of kmalloc for such big temporary buffers. Signed-off-by: Artem Bityutskiy commit a25f8af0f3e2c383c407cdc584b2c4d676f21802 Author: Artem Bityutskiy Date: Sat May 5 17:36:17 2007 +0300 UBI: add few more comments Add few comments above ubi_scan_add_used() to explain why it is so complex. Requested by Satyam Sharma . Signed-off-by: Artem Bityutskiy commit 962f24709f91fe0634b3faa3cac915c66357a239 Author: Artem Bityutskiy Date: Sat May 5 16:33:13 2007 +0300 UBI: set correct gluebi device size In case of static volumes, make emulated MTD device size to be equivalent to data size, rather then volume size. Reported-by: John Smith Signed-off-by: Artem Bityutskiy commit 5448d222f0af49fd5317e77b675345f1f168ffb7 Author: Artem Bityutskiy Date: Sat May 5 14:59:23 2007 +0300 UBI: do not let to read too much In case of static volumes it is prohibited to read more data then available. Signed-off-by: Artem Bityutskiy commit 5125237efb6a3309fbf5b9a7a21aaf716787f2a2 Author: Artem Bityutskiy Date: Sat May 5 11:24:02 2007 +0300 UBI: fix error path in create_vtbl() There were several bugs in volume table creation error path. Thanks to Satyam Sharma and Florin Malita for finding and analysing them: http://lkml.org/lkml/2007/5/3/274 This patch makes ubi_scan_add_to_list() static and renames it to add_to_list(), just because it is not needed outside scan.c anymore. Signed-off-by: Artem Bityutskiy commit b550442fef066b81f37f4e70f2ecfccb13115ead Author: Artem Bityutskiy Date: Fri May 4 10:12:34 2007 +0300 UBI: fix MAINTAINERS ubi-2.6.git does not exist anymore and all changes go via git://git.infradead.org/mtd-2.6.git in future. Signed-off-by: Artem Bityutskiy commit f695aa842bbf1e069e2353f369389b1a669e2596 Author: Florin Malita Date: Thu May 3 11:49:57 2007 -0400 UBI: fix dereference after kfree Coverity (CID 1614) spotted new_seb being dereferenced after kfree() in create_vtbl's write_error path. Signed-off-by: Florin Malita Signed-off-by: Artem Bityutskiy commit bbd8932936efffd000519c14614b70712aee5354 Author: Artem Bityutskiy Date: Thu May 3 11:59:51 2007 +0300 UBI: fix memory leak in checking code Reported-by: Eric Sesterhenn / Snakebyte Signed-off-by: Artem Bityutskiy Signed-off-by: Andrew Morton --- MAINTAINERS | 2 - drivers/mtd/ubi/build.c | 2 - drivers/mtd/ubi/cdev.c | 15 ++++---- drivers/mtd/ubi/eba.c | 22 ++++++------ drivers/mtd/ubi/gluebi.c | 27 +++++++++++++++ drivers/mtd/ubi/io.c | 11 +++--- drivers/mtd/ubi/kapi.c | 11 ++++-- drivers/mtd/ubi/misc.c | 4 +- drivers/mtd/ubi/scan.c | 64 ++++++++++++++++++++++--------------- drivers/mtd/ubi/scan.h | 2 - drivers/mtd/ubi/ubi.h | 3 + drivers/mtd/ubi/upd.c | 4 +- drivers/mtd/ubi/vtbl.c | 33 ++++++++++--------- 13 files changed, 125 insertions(+), 75 deletions(-) diff -puN MAINTAINERS~git-ubi MAINTAINERS --- a/MAINTAINERS~git-ubi +++ a/MAINTAINERS @@ -2345,7 +2345,7 @@ P: Artem Bityutskiy M: dedekind@infradead.org W: http://www.linux-mtd.infradead.org/ L: linux-mtd@lists.infradead.org -T: git git://git.infradead.org/ubi-2.6.git +T: git git://git.infradead.org/mtd-2.6.git S: Maintained MICROTEK X6 SCANNER diff -puN drivers/mtd/ubi/build.c~git-ubi drivers/mtd/ubi/build.c --- a/drivers/mtd/ubi/build.c~git-ubi +++ a/drivers/mtd/ubi/build.c @@ -650,7 +650,7 @@ static void detach_mtd_dev(struct ubi_de uif_close(ubi); ubi_eba_close(ubi); ubi_wl_close(ubi); - kfree(ubi->vtbl); + vfree(ubi->vtbl); put_mtd_device(ubi->mtd); kfree(ubi_devices[ubi_num]); ubi_devices[ubi_num] = NULL; diff -puN drivers/mtd/ubi/cdev.c~git-ubi drivers/mtd/ubi/cdev.c --- a/drivers/mtd/ubi/cdev.c~git-ubi +++ a/drivers/mtd/ubi/cdev.c @@ -153,7 +153,7 @@ static int vol_cdev_release(struct inode ubi_warn("update of volume %d not finished, volume is damaged", vol->vol_id); vol->updating = 0; - kfree(vol->upd_buf); + vfree(vol->upd_buf); } ubi_close_volume(desc); @@ -232,7 +232,7 @@ static ssize_t vol_cdev_read(struct file tbuf_size = vol->usable_leb_size; if (count < tbuf_size) tbuf_size = ALIGN(count, ubi->min_io_size); - tbuf = kmalloc(tbuf_size, GFP_KERNEL); + tbuf = vmalloc(tbuf_size); if (!tbuf) return -ENOMEM; @@ -271,7 +271,7 @@ static ssize_t vol_cdev_read(struct file len = count > tbuf_size ? tbuf_size : count; } while (count); - kfree(tbuf); + vfree(tbuf); return err ? err : count_save - count; } @@ -320,7 +320,7 @@ static ssize_t vol_cdev_direct_write(str tbuf_size = vol->usable_leb_size; if (count < tbuf_size) tbuf_size = ALIGN(count, ubi->min_io_size); - tbuf = kmalloc(tbuf_size, GFP_KERNEL); + tbuf = vmalloc(tbuf_size); if (!tbuf) return -ENOMEM; @@ -355,7 +355,7 @@ static ssize_t vol_cdev_direct_write(str len = count > tbuf_size ? tbuf_size : count; } - kfree(tbuf); + vfree(tbuf); return err ? err : count_save - count; } @@ -397,6 +397,7 @@ static ssize_t vol_cdev_write(struct fil vol->corrupted = 1; } vol->checked = 1; + ubi_gluebi_updated(vol); revoke_exclusive(desc, UBI_READWRITE); } @@ -707,7 +708,7 @@ static int ubi_cdev_ioctl(struct inode * struct file_operations ubi_cdev_operations = { .owner = THIS_MODULE, .ioctl = ubi_cdev_ioctl, - .llseek = no_llseek + .llseek = no_llseek, }; /* UBI volume character device operations */ @@ -718,5 +719,5 @@ struct file_operations ubi_vol_cdev_oper .llseek = vol_cdev_llseek, .read = vol_cdev_read, .write = vol_cdev_write, - .ioctl = vol_cdev_ioctl + .ioctl = vol_cdev_ioctl, }; diff -puN drivers/mtd/ubi/eba.c~git-ubi drivers/mtd/ubi/eba.c --- a/drivers/mtd/ubi/eba.c~git-ubi +++ a/drivers/mtd/ubi/eba.c @@ -524,7 +524,7 @@ retry: goto write_error; data_size = offset + len; - new_buf = kmalloc(data_size, GFP_KERNEL); + new_buf = vmalloc(data_size); if (!new_buf) { err = -ENOMEM; goto out_put; @@ -535,7 +535,7 @@ retry: if (offset > 0) { err = ubi_io_read_data(ubi, new_buf, pnum, 0, offset); if (err && err != UBI_IO_BITFLIPS) { - kfree(new_buf); + vfree(new_buf); goto out_put; } } @@ -544,11 +544,11 @@ retry: err = ubi_io_write_data(ubi, new_buf, new_pnum, 0, data_size); if (err) { - kfree(new_buf); + vfree(new_buf); goto write_error; } - kfree(new_buf); + vfree(new_buf); ubi_free_vid_hdr(ubi, vid_hdr); vol->eba_tbl[lnum] = new_pnum; @@ -980,7 +980,7 @@ int ubi_eba_copy_leb(struct ubi_device * data_size = aldata_size = ubi->leb_size - ubi32_to_cpu(vid_hdr->data_pad); - buf = kmalloc(aldata_size, GFP_KERNEL); + buf = vmalloc(aldata_size); if (!buf) return -ENOMEM; @@ -990,7 +990,7 @@ int ubi_eba_copy_leb(struct ubi_device * */ err = leb_write_lock(ubi, vol_id, lnum); if (err) { - kfree(buf); + vfree(buf); return err; } @@ -1085,7 +1085,7 @@ int ubi_eba_copy_leb(struct ubi_device * * We've written the data and are going to read it back to make * sure it was written correctly. */ - buf1 = kmalloc(aldata_size, GFP_KERNEL); + buf1 = vmalloc(aldata_size); if (!buf1) { err = -ENOMEM; goto out_unlock; @@ -1114,15 +1114,15 @@ int ubi_eba_copy_leb(struct ubi_device * vol->eba_tbl[lnum] = to; leb_write_unlock(ubi, vol_id, lnum); - kfree(buf); - kfree(buf1); + vfree(buf); + vfree(buf1); return 0; out_unlock: leb_write_unlock(ubi, vol_id, lnum); - kfree(buf); - kfree(buf1); + vfree(buf); + vfree(buf1); return err; } diff -puN drivers/mtd/ubi/gluebi.c~git-ubi drivers/mtd/ubi/gluebi.c --- a/drivers/mtd/ubi/gluebi.c~git-ubi +++ a/drivers/mtd/ubi/gluebi.c @@ -282,7 +282,6 @@ int ubi_create_gluebi(struct ubi_device mtd->flags = MTD_WRITEABLE; mtd->writesize = ubi->min_io_size; mtd->owner = THIS_MODULE; - mtd->size = vol->usable_leb_size * vol->reserved_pebs; mtd->erasesize = vol->usable_leb_size; mtd->read = gluebi_read; mtd->write = gluebi_write; @@ -290,6 +289,15 @@ int ubi_create_gluebi(struct ubi_device mtd->get_device = gluebi_get_device; mtd->put_device = gluebi_put_device; + /* + * In case of dynamic volume, MTD device size is just volume size. In + * case of a static volume the size is equivalent to the amount of data + * bytes, which is zero at this moment and will be changed after volume + * update. + */ + if (vol->vol_type == UBI_DYNAMIC_VOLUME) + mtd->size = vol->usable_leb_size * vol->reserved_pebs; + if (add_mtd_device(mtd)) { ubi_err("cannot not add MTD device\n"); kfree(mtd->name); @@ -321,3 +329,20 @@ int ubi_destroy_gluebi(struct ubi_volume kfree(mtd->name); return 0; } + +/** + * ubi_gluebi_updated - UBI volume was updated notifier. + * @vol: volume description object + * + * This function is called every time an UBI volume is updated. This function + * does nothing if volume @vol is dynamic, and changes MTD device size if the + * volume is static. This is needed because static volumes cannot be read past + * data they contain. + */ +void ubi_gluebi_updated(struct ubi_volume *vol) +{ + struct mtd_info *mtd = &vol->gluebi_mtd; + + if (vol->vol_type == UBI_STATIC_VOLUME) + mtd->size = vol->used_bytes; +} diff -puN drivers/mtd/ubi/io.c~git-ubi drivers/mtd/ubi/io.c --- a/drivers/mtd/ubi/io.c~git-ubi +++ a/drivers/mtd/ubi/io.c @@ -382,7 +382,7 @@ static int torture_peb(const struct ubi_ void *buf; int err, i, patt_count; - buf = kmalloc(ubi->peb_size, GFP_KERNEL); + buf = vmalloc(ubi->peb_size); if (!buf) return -ENOMEM; @@ -437,7 +437,7 @@ out: * physical eraseblock which means something is wrong with it. */ err = -EIO; - kfree(buf); + vfree(buf); return err; } @@ -1224,9 +1224,10 @@ static int paranoid_check_all_ff(const s void *buf; loff_t addr = (loff_t)pnum * ubi->peb_size + offset; - buf = kzalloc(len, GFP_KERNEL); + buf = vmalloc(len); if (!buf) return -ENOMEM; + memset(buf, 0, len); err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf); if (err && err != -EUCLEAN) { @@ -1242,7 +1243,7 @@ static int paranoid_check_all_ff(const s goto fail; } - kfree(buf); + vfree(buf); return 0; fail: @@ -1252,7 +1253,7 @@ fail: err = 1; error: ubi_dbg_dump_stack(); - kfree(buf); + vfree(buf); return err; } diff -puN drivers/mtd/ubi/kapi.c~git-ubi drivers/mtd/ubi/kapi.c --- a/drivers/mtd/ubi/kapi.c~git-ubi +++ a/drivers/mtd/ubi/kapi.c @@ -319,9 +319,14 @@ int ubi_leb_read(struct ubi_volume_desc offset + len > vol->usable_leb_size) return -EINVAL; - if (vol->vol_type == UBI_STATIC_VOLUME && lnum == vol->used_ebs - 1 && - offset + len > vol->last_eb_bytes) - return -EINVAL; + if (vol->vol_type == UBI_STATIC_VOLUME) { + if (vol->used_ebs == 0) + /* Empty static UBI volume */ + return 0; + if (lnum == vol->used_ebs - 1 && + offset + len > vol->last_eb_bytes) + return -EINVAL; + } if (vol->upd_marker) return -EBADF; diff -puN drivers/mtd/ubi/misc.c~git-ubi drivers/mtd/ubi/misc.c --- a/drivers/mtd/ubi/misc.c~git-ubi +++ a/drivers/mtd/ubi/misc.c @@ -67,7 +67,7 @@ int ubi_check_volume(struct ubi_device * if (vol->vol_type != UBI_STATIC_VOLUME) return 0; - buf = kmalloc(vol->usable_leb_size, GFP_KERNEL); + buf = vmalloc(vol->usable_leb_size); if (!buf) return -ENOMEM; @@ -87,7 +87,7 @@ int ubi_check_volume(struct ubi_device * } } - kfree(buf); + vfree(buf); return err; } diff -puN drivers/mtd/ubi/scan.c~git-ubi drivers/mtd/ubi/scan.c --- a/drivers/mtd/ubi/scan.c~git-ubi +++ a/drivers/mtd/ubi/scan.c @@ -24,7 +24,7 @@ * This unit is responsible for scanning the flash media, checking UBI * headers and providing complete information about the UBI flash image. * - * The scanning information is reoresented by a &struct ubi_scan_info' object. + * The scanning information is represented by a &struct ubi_scan_info' object. * Information about found volumes is represented by &struct ubi_scan_volume * objects which are kept in volume RB-tree with root at the @volumes field. * The RB-tree is indexed by the volume ID. @@ -55,8 +55,19 @@ static int paranoid_check_si(const struc static struct ubi_ec_hdr *ech; static struct ubi_vid_hdr *vidh; -int ubi_scan_add_to_list(struct ubi_scan_info *si, int pnum, int ec, - struct list_head *list) +/** + * add_to_list - add physical eraseblock to a list. + * @si: scanning information + * @pnum: physical eraseblock number to add + * @ec: erase counter of the physical eraseblock + * @list: the list to add to + * + * This function adds physical eraseblock @pnum to free, erase, corrupted or + * alien lists. Returns zero in case of success and a negative error code in + * case of failure. + */ +static int add_to_list(struct ubi_scan_info *si, int pnum, int ec, + struct list_head *list) { struct ubi_scan_leb *seb; @@ -345,7 +356,7 @@ static int compare_lebs(const struct ubi /* Read the data of the copy and check the CRC */ len = ubi32_to_cpu(vid_hdr->data_size); - buf = kmalloc(len, GFP_KERNEL); + buf = vmalloc(len); if (!buf) { err = -ENOMEM; goto out_free_vidh; @@ -368,7 +379,7 @@ static int compare_lebs(const struct ubi bitflips = !!err; } - kfree(buf); + vfree(buf); ubi_free_vid_hdr(ubi, vidh); if (second_is_newer) @@ -379,7 +390,7 @@ static int compare_lebs(const struct ubi return second_is_newer | (bitflips << 1) | (corrupted << 2); out_free_buf: - kfree(buf); + vfree(buf); out_free_vidh: ubi_free_vid_hdr(ubi, vidh); ubi_assert(err < 0); @@ -396,8 +407,12 @@ out_free_vidh: * @vid_hdr: the volume identifier header * @bitflips: if bit-flips were detected when this physical eraseblock was read * - * This function returns zero in case of success and a negative error code in - * case of failure. + * This function adds information about a used physical eraseblock to the + * 'used' tree of the corresponding volume. The function is rather complex + * because it has to handle cases when this is not the first physical + * eraseblock belonging to the same logical eraseblock, and the newer one has + * to be picked, while the older one has to be dropped. This function returns + * zero in case of success and a negative error code in case of failure. */ int ubi_scan_add_used(const struct ubi_device *ubi, struct ubi_scan_info *si, int pnum, int ec, const struct ubi_vid_hdr *vid_hdr, @@ -492,11 +507,11 @@ int ubi_scan_add_used(const struct ubi_d return err; if (cmp_res & 4) - err = ubi_scan_add_to_list(si, seb->pnum, - seb->ec, &si->corr); + err = add_to_list(si, seb->pnum, seb->ec, + &si->corr); else - err = ubi_scan_add_to_list(si, seb->pnum, - seb->ec, &si->erase); + err = add_to_list(si, seb->pnum, seb->ec, + &si->erase); if (err) return err; @@ -517,11 +532,9 @@ int ubi_scan_add_used(const struct ubi_d * previously. */ if (cmp_res & 4) - return ubi_scan_add_to_list(si, pnum, ec, - &si->corr); + return add_to_list(si, pnum, ec, &si->corr); else - return ubi_scan_add_to_list(si, pnum, ec, - &si->erase); + return add_to_list(si, pnum, ec, &si->erase); } } @@ -754,7 +767,7 @@ struct ubi_scan_leb *ubi_scan_get_free_p * @si: scanning information * @pnum: the physical eraseblock number * - * This function returns a zero if the physical eraseblock was succesfully + * This function returns a zero if the physical eraseblock was successfully * handled and a negative error code in case of failure. */ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, int pnum) @@ -783,8 +796,7 @@ static int process_eb(struct ubi_device else if (err == UBI_IO_BITFLIPS) bitflips = 1; else if (err == UBI_IO_PEB_EMPTY) - return ubi_scan_add_to_list(si, pnum, UBI_SCAN_UNKNOWN_EC, - &si->erase); + return add_to_list(si, pnum, UBI_SCAN_UNKNOWN_EC, &si->erase); else if (err == UBI_IO_BAD_EC_HDR) { /* * We have to also look at the VID header, possibly it is not @@ -832,13 +844,13 @@ static int process_eb(struct ubi_device else if (err == UBI_IO_BAD_VID_HDR || (err == UBI_IO_PEB_FREE && ec_corr)) { /* VID header is corrupted */ - err = ubi_scan_add_to_list(si, pnum, ec, &si->corr); + err = add_to_list(si, pnum, ec, &si->corr); if (err) return err; goto adjust_mean_ec; } else if (err == UBI_IO_PEB_FREE) { /* No VID header - the physical eraseblock is free */ - err = ubi_scan_add_to_list(si, pnum, ec, &si->free); + err = add_to_list(si, pnum, ec, &si->free); if (err) return err; goto adjust_mean_ec; @@ -853,7 +865,7 @@ static int process_eb(struct ubi_device case UBI_COMPAT_DELETE: ubi_msg("\"delete\" compatible internal volume %d:%d" " found, remove it", vol_id, lnum); - err = ubi_scan_add_to_list(si, pnum, ec, &si->corr); + err = add_to_list(si, pnum, ec, &si->corr); if (err) return err; break; @@ -868,7 +880,7 @@ static int process_eb(struct ubi_device case UBI_COMPAT_PRESERVE: ubi_msg("\"preserve\" compatible internal volume %d:%d" " found", vol_id, lnum); - err = ubi_scan_add_to_list(si, pnum, ec, &si->alien); + err = add_to_list(si, pnum, ec, &si->alien); if (err) return err; si->alien_peb_count += 1; @@ -1109,7 +1121,7 @@ static int paranoid_check_si(const struc uint8_t *buf; /* - * At first, check that scanning information is ok. + * At first, check that scanning information is OK. */ ubi_rb_for_each_entry(rb1, sv, &si->volumes, rb) { int leb_count = 0; @@ -1310,8 +1322,10 @@ static int paranoid_check_si(const struc memset(buf, 1, ubi->peb_count); for (pnum = 0; pnum < ubi->peb_count; pnum++) { err = ubi_io_is_bad(ubi, pnum); - if (err < 0) + if (err < 0) { + kfree(buf); return err; + } else if (err) buf[pnum] = 0; } diff -puN drivers/mtd/ubi/scan.h~git-ubi drivers/mtd/ubi/scan.h --- a/drivers/mtd/ubi/scan.h~git-ubi +++ a/drivers/mtd/ubi/scan.h @@ -147,8 +147,6 @@ static inline void ubi_scan_move_to_list list_add_tail(&seb->u.list, list); } -int ubi_scan_add_to_list(struct ubi_scan_info *si, int pnum, int ec, - struct list_head *list); int ubi_scan_add_used(const struct ubi_device *ubi, struct ubi_scan_info *si, int pnum, int ec, const struct ubi_vid_hdr *vid_hdr, int bitflips); diff -puN drivers/mtd/ubi/ubi.h~git-ubi drivers/mtd/ubi/ubi.h --- a/drivers/mtd/ubi/ubi.h~git-ubi +++ a/drivers/mtd/ubi/ubi.h @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -374,9 +375,11 @@ void ubi_calculate_reserved(struct ubi_d #ifdef CONFIG_MTD_UBI_GLUEBI int ubi_create_gluebi(struct ubi_device *ubi, struct ubi_volume *vol); int ubi_destroy_gluebi(struct ubi_volume *vol); +void ubi_gluebi_updated(struct ubi_volume *vol); #else #define ubi_create_gluebi(ubi, vol) 0 #define ubi_destroy_gluebi(vol) 0 +#define ubi_gluebi_updated(vol) #endif /* eba.c */ diff -puN drivers/mtd/ubi/upd.c~git-ubi drivers/mtd/ubi/upd.c --- a/drivers/mtd/ubi/upd.c~git-ubi +++ a/drivers/mtd/ubi/upd.c @@ -150,7 +150,7 @@ int ubi_start_update(struct ubi_device * vol->updating = 0; } - vol->upd_buf = kmalloc(ubi->leb_size, GFP_KERNEL); + vol->upd_buf = vmalloc(ubi->leb_size); if (!vol->upd_buf) return -ENOMEM; @@ -339,7 +339,7 @@ int ubi_more_update_data(struct ubi_devi err = ubi_wl_flush(ubi); if (err == 0) { err = to_write; - kfree(vol->upd_buf); + vfree(vol->upd_buf); vol->updating = 0; } } diff -puN drivers/mtd/ubi/vtbl.c~git-ubi drivers/mtd/ubi/vtbl.c --- a/drivers/mtd/ubi/vtbl.c~git-ubi +++ a/drivers/mtd/ubi/vtbl.c @@ -317,14 +317,15 @@ retry: return err; write_error: - kfree(new_seb); - /* May be this physical eraseblock went bad, try to pick another one */ - if (++tries <= 5) { - err = ubi_scan_add_to_list(si, new_seb->pnum, new_seb->ec, - &si->corr); - if (!err) - goto retry; + if (err == -EIO && ++tries <= 5) { + /* + * Probably this physical eraseblock went bad, try to pick + * another one. + */ + list_add_tail(&new_seb->u.list, &si->corr); + goto retry; } + kfree(new_seb); out_free: ubi_free_vid_hdr(ubi, vid_hdr); return err; @@ -380,11 +381,12 @@ static struct ubi_vtbl_record *process_l /* Read both LEB 0 and LEB 1 into memory */ ubi_rb_for_each_entry(rb, seb, &sv->root, u.rb) { - leb[seb->lnum] = kzalloc(ubi->vtbl_size, GFP_KERNEL); + leb[seb->lnum] = vmalloc(ubi->vtbl_size); if (!leb[seb->lnum]) { err = -ENOMEM; goto out_free; } + memset(leb[seb->lnum], 0, ubi->vtbl_size); err = ubi_io_read_data(ubi, leb[seb->lnum], seb->pnum, 0, ubi->vtbl_size); @@ -415,7 +417,7 @@ static struct ubi_vtbl_record *process_l } /* Both LEB 1 and LEB 2 are OK and consistent */ - kfree(leb[1]); + vfree(leb[1]); return leb[0]; } else { /* LEB 0 is corrupted or does not exist */ @@ -436,13 +438,13 @@ static struct ubi_vtbl_record *process_l goto out_free; ubi_msg("volume table was restored"); - kfree(leb[0]); + vfree(leb[0]); return leb[1]; } out_free: - kfree(leb[0]); - kfree(leb[1]); + vfree(leb[0]); + vfree(leb[1]); return ERR_PTR(err); } @@ -460,9 +462,10 @@ static struct ubi_vtbl_record *create_em int i; struct ubi_vtbl_record *vtbl; - vtbl = kzalloc(ubi->vtbl_size, GFP_KERNEL); + vtbl = vmalloc(ubi->vtbl_size); if (!vtbl) return ERR_PTR(-ENOMEM); + memset(vtbl, 0, ubi->vtbl_size); for (i = 0; i < ubi->vtbl_slots; i++) memcpy(&vtbl[i], &empty_vtbl_record, UBI_VTBL_RECORD_SIZE); @@ -472,7 +475,7 @@ static struct ubi_vtbl_record *create_em err = create_vtbl(ubi, si, i, vtbl); if (err) { - kfree(vtbl); + vfree(vtbl); return ERR_PTR(err); } } @@ -783,7 +786,7 @@ int ubi_read_volume_table(struct ubi_dev return 0; out_free: - kfree(ubi->vtbl); + vfree(ubi->vtbl); for (i = 0; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) if (ubi->volumes[i]) { kfree(ubi->volumes[i]); _