UBI: use vmalloc for large buffers
authorArtem Bityutskiy <Artem.Bityutskiy@nokia.com>
Sun, 6 May 2007 13:12:54 +0000 (16:12 +0300)
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>
Wed, 18 Jul 2007 13:53:08 +0000 (16:53 +0300)
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 <Artem.Bityutskiy@nokia.com>
drivers/mtd/ubi/build.c
drivers/mtd/ubi/cdev.c
drivers/mtd/ubi/eba.c
drivers/mtd/ubi/io.c
drivers/mtd/ubi/misc.c
drivers/mtd/ubi/scan.c
drivers/mtd/ubi/ubi.h
drivers/mtd/ubi/upd.c
drivers/mtd/ubi/vtbl.c

index 555d594d1811d7f4bb29ddd9ac329ffff85de6af..054a88dcc7a1049bd6f2a36b0ead39c55eea6f0a 100644 (file)
@@ -650,7 +650,7 @@ static void detach_mtd_dev(struct ubi_device *ubi)
        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;
index 959044a2ddbffa0abfa7114a4b1b3b79a7ac7988..34375ee6d4a4176747202ad219cc2e1a2665bf17 100644 (file)
@@ -153,7 +153,7 @@ static int vol_cdev_release(struct inode *inode, struct file *file)
                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 *file, __user char *buf, size_t count,
        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 *file, __user char *buf, size_t count,
                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(struct file *file, const char __user *buf,
        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(struct file *file, const char __user *buf,
                len = count > tbuf_size ? tbuf_size : count;
        }
 
-       kfree(tbuf);
+       vfree(tbuf);
        return err ? err : count_save - count;
 }
 
index 7c6b223b3f8a0a22b114a5b593f1ad605b85fcc5..6964fe4ab41a57fcdc2efd7a6a56ea571be5badb 100644 (file)
@@ -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;
@@ -977,7 +977,7 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
                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;
 
@@ -987,7 +987,7 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
         */
        err = leb_write_lock(ubi, vol_id, lnum);
        if (err) {
-               kfree(buf);
+               vfree(buf);
                return err;
        }
 
@@ -1082,7 +1082,7 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
                 * 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;
@@ -1111,15 +1111,15 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
        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;
 }
 
index 438914d05151017b9fe18ad478d68eb0b64faea1..7bb473e646e3e15d720cddb610982821203034ee 100644 (file)
@@ -382,7 +382,7 @@ static int torture_peb(const struct ubi_device *ubi, int pnum)
        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 struct ubi_device *ubi, int pnum,
        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 struct ubi_device *ubi, int pnum,
                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;
 }
 
index 38d4e6757dc791590e061ae4191333b47203ef8e..9e2338c8e2cf545f097bd74d6c1d7c20d26093bc 100644 (file)
@@ -67,7 +67,7 @@ int ubi_check_volume(struct ubi_device *ubi, int vol_id)
        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 *ubi, int vol_id)
                }
        }
 
-       kfree(buf);
+       vfree(buf);
        return err;
 }
 
index b24af2104a2a865e9060c0db94c7f08607719d3a..cbd588d601687086677ab8634574a42ba488b1f0 100644 (file)
@@ -356,7 +356,7 @@ static int compare_lebs(const struct ubi_device *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;
@@ -379,7 +379,7 @@ static int compare_lebs(const struct ubi_device *ubi,
                bitflips = !!err;
        }
 
-       kfree(buf);
+       vfree(buf);
        ubi_free_vid_hdr(ubi, vidh);
 
        if (second_is_newer)
@@ -390,7 +390,7 @@ static int compare_lebs(const struct ubi_device *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);
index c26edea968182c6109a1de94fcbc6690eed75310..5959f91be240655b3219a6d6359a060d732aeaf7 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/cdev.h>
 #include <linux/device.h>
 #include <linux/string.h>
+#include <linux/vmalloc.h>
 #include <linux/mtd/mtd.h>
 
 #include <mtd/ubi-header.h>
index 8925b977e3dcc8ffc4492fd386357c547dab37ed..0efc586a83288fd5ccde9bc6b39a5ea432cf8f4c 100644 (file)
@@ -150,7 +150,7 @@ int ubi_start_update(struct ubi_device *ubi, int vol_id, long long bytes)
                        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_device *ubi, int vol_id,
                err = ubi_wl_flush(ubi);
                if (err == 0) {
                        err = to_write;
-                       kfree(vol->upd_buf);
+                       vfree(vol->upd_buf);
                        vol->updating = 0;
                }
        }
index 9926f1f9aad8d30bedb790be5fbf92d4aebab620..e3557b987efd93be0b65fdc59364aa554cf342c2 100644 (file)
@@ -381,11 +381,12 @@ static struct ubi_vtbl_record *process_lvol(const struct ubi_device *ubi,
 
        /* 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);
@@ -416,7 +417,7 @@ static struct ubi_vtbl_record *process_lvol(const struct ubi_device *ubi,
                }
 
                /* 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 */
@@ -437,13 +438,13 @@ static struct ubi_vtbl_record *process_lvol(const struct ubi_device *ubi,
                        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);
 }
 
@@ -461,9 +462,10 @@ static struct ubi_vtbl_record *create_empty_lvol(const struct ubi_device *ubi,
        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);
@@ -473,7 +475,7 @@ static struct ubi_vtbl_record *create_empty_lvol(const struct ubi_device *ubi,
 
                err = create_vtbl(ubi, si, i, vtbl);
                if (err) {
-                       kfree(vtbl);
+                       vfree(vtbl);
                        return ERR_PTR(err);
                }
        }
@@ -784,7 +786,7 @@ int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si)
        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]);