mirror of https://gitee.com/openkylin/linux.git
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 <Artem.Bityutskiy@nokia.com>
This commit is contained in:
parent
79b510c0f2
commit
92ad8f3750
|
@ -650,7 +650,7 @@ static void detach_mtd_dev(struct ubi_device *ubi)
|
||||||
uif_close(ubi);
|
uif_close(ubi);
|
||||||
ubi_eba_close(ubi);
|
ubi_eba_close(ubi);
|
||||||
ubi_wl_close(ubi);
|
ubi_wl_close(ubi);
|
||||||
kfree(ubi->vtbl);
|
vfree(ubi->vtbl);
|
||||||
put_mtd_device(ubi->mtd);
|
put_mtd_device(ubi->mtd);
|
||||||
kfree(ubi_devices[ubi_num]);
|
kfree(ubi_devices[ubi_num]);
|
||||||
ubi_devices[ubi_num] = NULL;
|
ubi_devices[ubi_num] = NULL;
|
||||||
|
|
|
@ -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",
|
ubi_warn("update of volume %d not finished, volume is damaged",
|
||||||
vol->vol_id);
|
vol->vol_id);
|
||||||
vol->updating = 0;
|
vol->updating = 0;
|
||||||
kfree(vol->upd_buf);
|
vfree(vol->upd_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
ubi_close_volume(desc);
|
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;
|
tbuf_size = vol->usable_leb_size;
|
||||||
if (count < tbuf_size)
|
if (count < tbuf_size)
|
||||||
tbuf_size = ALIGN(count, ubi->min_io_size);
|
tbuf_size = ALIGN(count, ubi->min_io_size);
|
||||||
tbuf = kmalloc(tbuf_size, GFP_KERNEL);
|
tbuf = vmalloc(tbuf_size);
|
||||||
if (!tbuf)
|
if (!tbuf)
|
||||||
return -ENOMEM;
|
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;
|
len = count > tbuf_size ? tbuf_size : count;
|
||||||
} while (count);
|
} while (count);
|
||||||
|
|
||||||
kfree(tbuf);
|
vfree(tbuf);
|
||||||
return err ? err : count_save - count;
|
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;
|
tbuf_size = vol->usable_leb_size;
|
||||||
if (count < tbuf_size)
|
if (count < tbuf_size)
|
||||||
tbuf_size = ALIGN(count, ubi->min_io_size);
|
tbuf_size = ALIGN(count, ubi->min_io_size);
|
||||||
tbuf = kmalloc(tbuf_size, GFP_KERNEL);
|
tbuf = vmalloc(tbuf_size);
|
||||||
if (!tbuf)
|
if (!tbuf)
|
||||||
return -ENOMEM;
|
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;
|
len = count > tbuf_size ? tbuf_size : count;
|
||||||
}
|
}
|
||||||
|
|
||||||
kfree(tbuf);
|
vfree(tbuf);
|
||||||
return err ? err : count_save - count;
|
return err ? err : count_save - count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -524,7 +524,7 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum,
|
||||||
goto write_error;
|
goto write_error;
|
||||||
|
|
||||||
data_size = offset + len;
|
data_size = offset + len;
|
||||||
new_buf = kmalloc(data_size, GFP_KERNEL);
|
new_buf = vmalloc(data_size);
|
||||||
if (!new_buf) {
|
if (!new_buf) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
goto out_put;
|
goto out_put;
|
||||||
|
@ -535,7 +535,7 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum,
|
||||||
if (offset > 0) {
|
if (offset > 0) {
|
||||||
err = ubi_io_read_data(ubi, new_buf, pnum, 0, offset);
|
err = ubi_io_read_data(ubi, new_buf, pnum, 0, offset);
|
||||||
if (err && err != UBI_IO_BITFLIPS) {
|
if (err && err != UBI_IO_BITFLIPS) {
|
||||||
kfree(new_buf);
|
vfree(new_buf);
|
||||||
goto out_put;
|
goto out_put;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -544,11 +544,11 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum,
|
||||||
|
|
||||||
err = ubi_io_write_data(ubi, new_buf, new_pnum, 0, data_size);
|
err = ubi_io_write_data(ubi, new_buf, new_pnum, 0, data_size);
|
||||||
if (err) {
|
if (err) {
|
||||||
kfree(new_buf);
|
vfree(new_buf);
|
||||||
goto write_error;
|
goto write_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
kfree(new_buf);
|
vfree(new_buf);
|
||||||
ubi_free_vid_hdr(ubi, vid_hdr);
|
ubi_free_vid_hdr(ubi, vid_hdr);
|
||||||
|
|
||||||
vol->eba_tbl[lnum] = new_pnum;
|
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 =
|
data_size = aldata_size =
|
||||||
ubi->leb_size - ubi32_to_cpu(vid_hdr->data_pad);
|
ubi->leb_size - ubi32_to_cpu(vid_hdr->data_pad);
|
||||||
|
|
||||||
buf = kmalloc(aldata_size, GFP_KERNEL);
|
buf = vmalloc(aldata_size);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
return -ENOMEM;
|
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);
|
err = leb_write_lock(ubi, vol_id, lnum);
|
||||||
if (err) {
|
if (err) {
|
||||||
kfree(buf);
|
vfree(buf);
|
||||||
return err;
|
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
|
* We've written the data and are going to read it back to make
|
||||||
* sure it was written correctly.
|
* sure it was written correctly.
|
||||||
*/
|
*/
|
||||||
buf1 = kmalloc(aldata_size, GFP_KERNEL);
|
buf1 = vmalloc(aldata_size);
|
||||||
if (!buf1) {
|
if (!buf1) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
goto out_unlock;
|
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;
|
vol->eba_tbl[lnum] = to;
|
||||||
|
|
||||||
leb_write_unlock(ubi, vol_id, lnum);
|
leb_write_unlock(ubi, vol_id, lnum);
|
||||||
kfree(buf);
|
vfree(buf);
|
||||||
kfree(buf1);
|
vfree(buf1);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_unlock:
|
out_unlock:
|
||||||
leb_write_unlock(ubi, vol_id, lnum);
|
leb_write_unlock(ubi, vol_id, lnum);
|
||||||
kfree(buf);
|
vfree(buf);
|
||||||
kfree(buf1);
|
vfree(buf1);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -382,7 +382,7 @@ static int torture_peb(const struct ubi_device *ubi, int pnum)
|
||||||
void *buf;
|
void *buf;
|
||||||
int err, i, patt_count;
|
int err, i, patt_count;
|
||||||
|
|
||||||
buf = kmalloc(ubi->peb_size, GFP_KERNEL);
|
buf = vmalloc(ubi->peb_size);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -437,7 +437,7 @@ static int torture_peb(const struct ubi_device *ubi, int pnum)
|
||||||
* physical eraseblock which means something is wrong with it.
|
* physical eraseblock which means something is wrong with it.
|
||||||
*/
|
*/
|
||||||
err = -EIO;
|
err = -EIO;
|
||||||
kfree(buf);
|
vfree(buf);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1224,9 +1224,10 @@ static int paranoid_check_all_ff(const struct ubi_device *ubi, int pnum,
|
||||||
void *buf;
|
void *buf;
|
||||||
loff_t addr = (loff_t)pnum * ubi->peb_size + offset;
|
loff_t addr = (loff_t)pnum * ubi->peb_size + offset;
|
||||||
|
|
||||||
buf = kzalloc(len, GFP_KERNEL);
|
buf = vmalloc(len);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
memset(buf, 0, len);
|
||||||
|
|
||||||
err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf);
|
err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf);
|
||||||
if (err && err != -EUCLEAN) {
|
if (err && err != -EUCLEAN) {
|
||||||
|
@ -1242,7 +1243,7 @@ static int paranoid_check_all_ff(const struct ubi_device *ubi, int pnum,
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
kfree(buf);
|
vfree(buf);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
@ -1252,7 +1253,7 @@ static int paranoid_check_all_ff(const struct ubi_device *ubi, int pnum,
|
||||||
err = 1;
|
err = 1;
|
||||||
error:
|
error:
|
||||||
ubi_dbg_dump_stack();
|
ubi_dbg_dump_stack();
|
||||||
kfree(buf);
|
vfree(buf);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,7 @@ int ubi_check_volume(struct ubi_device *ubi, int vol_id)
|
||||||
if (vol->vol_type != UBI_STATIC_VOLUME)
|
if (vol->vol_type != UBI_STATIC_VOLUME)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
buf = kmalloc(vol->usable_leb_size, GFP_KERNEL);
|
buf = vmalloc(vol->usable_leb_size);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ int ubi_check_volume(struct ubi_device *ubi, int vol_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
kfree(buf);
|
vfree(buf);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -356,7 +356,7 @@ static int compare_lebs(const struct ubi_device *ubi,
|
||||||
/* Read the data of the copy and check the CRC */
|
/* Read the data of the copy and check the CRC */
|
||||||
|
|
||||||
len = ubi32_to_cpu(vid_hdr->data_size);
|
len = ubi32_to_cpu(vid_hdr->data_size);
|
||||||
buf = kmalloc(len, GFP_KERNEL);
|
buf = vmalloc(len);
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
goto out_free_vidh;
|
goto out_free_vidh;
|
||||||
|
@ -379,7 +379,7 @@ static int compare_lebs(const struct ubi_device *ubi,
|
||||||
bitflips = !!err;
|
bitflips = !!err;
|
||||||
}
|
}
|
||||||
|
|
||||||
kfree(buf);
|
vfree(buf);
|
||||||
ubi_free_vid_hdr(ubi, vidh);
|
ubi_free_vid_hdr(ubi, vidh);
|
||||||
|
|
||||||
if (second_is_newer)
|
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);
|
return second_is_newer | (bitflips << 1) | (corrupted << 2);
|
||||||
|
|
||||||
out_free_buf:
|
out_free_buf:
|
||||||
kfree(buf);
|
vfree(buf);
|
||||||
out_free_vidh:
|
out_free_vidh:
|
||||||
ubi_free_vid_hdr(ubi, vidh);
|
ubi_free_vid_hdr(ubi, vidh);
|
||||||
ubi_assert(err < 0);
|
ubi_assert(err < 0);
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include <linux/cdev.h>
|
#include <linux/cdev.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
|
#include <linux/vmalloc.h>
|
||||||
#include <linux/mtd/mtd.h>
|
#include <linux/mtd/mtd.h>
|
||||||
|
|
||||||
#include <mtd/ubi-header.h>
|
#include <mtd/ubi-header.h>
|
||||||
|
|
|
@ -150,7 +150,7 @@ int ubi_start_update(struct ubi_device *ubi, int vol_id, long long bytes)
|
||||||
vol->updating = 0;
|
vol->updating = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
vol->upd_buf = kmalloc(ubi->leb_size, GFP_KERNEL);
|
vol->upd_buf = vmalloc(ubi->leb_size);
|
||||||
if (!vol->upd_buf)
|
if (!vol->upd_buf)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -339,7 +339,7 @@ int ubi_more_update_data(struct ubi_device *ubi, int vol_id,
|
||||||
err = ubi_wl_flush(ubi);
|
err = ubi_wl_flush(ubi);
|
||||||
if (err == 0) {
|
if (err == 0) {
|
||||||
err = to_write;
|
err = to_write;
|
||||||
kfree(vol->upd_buf);
|
vfree(vol->upd_buf);
|
||||||
vol->updating = 0;
|
vol->updating = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 */
|
/* Read both LEB 0 and LEB 1 into memory */
|
||||||
ubi_rb_for_each_entry(rb, seb, &sv->root, u.rb) {
|
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]) {
|
if (!leb[seb->lnum]) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
goto out_free;
|
goto out_free;
|
||||||
}
|
}
|
||||||
|
memset(leb[seb->lnum], 0, ubi->vtbl_size);
|
||||||
|
|
||||||
err = ubi_io_read_data(ubi, leb[seb->lnum], seb->pnum, 0,
|
err = ubi_io_read_data(ubi, leb[seb->lnum], seb->pnum, 0,
|
||||||
ubi->vtbl_size);
|
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 */
|
/* Both LEB 1 and LEB 2 are OK and consistent */
|
||||||
kfree(leb[1]);
|
vfree(leb[1]);
|
||||||
return leb[0];
|
return leb[0];
|
||||||
} else {
|
} else {
|
||||||
/* LEB 0 is corrupted or does not exist */
|
/* 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;
|
goto out_free;
|
||||||
ubi_msg("volume table was restored");
|
ubi_msg("volume table was restored");
|
||||||
|
|
||||||
kfree(leb[0]);
|
vfree(leb[0]);
|
||||||
return leb[1];
|
return leb[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
out_free:
|
out_free:
|
||||||
kfree(leb[0]);
|
vfree(leb[0]);
|
||||||
kfree(leb[1]);
|
vfree(leb[1]);
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -461,9 +462,10 @@ static struct ubi_vtbl_record *create_empty_lvol(const struct ubi_device *ubi,
|
||||||
int i;
|
int i;
|
||||||
struct ubi_vtbl_record *vtbl;
|
struct ubi_vtbl_record *vtbl;
|
||||||
|
|
||||||
vtbl = kzalloc(ubi->vtbl_size, GFP_KERNEL);
|
vtbl = vmalloc(ubi->vtbl_size);
|
||||||
if (!vtbl)
|
if (!vtbl)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
memset(vtbl, 0, ubi->vtbl_size);
|
||||||
|
|
||||||
for (i = 0; i < ubi->vtbl_slots; i++)
|
for (i = 0; i < ubi->vtbl_slots; i++)
|
||||||
memcpy(&vtbl[i], &empty_vtbl_record, UBI_VTBL_RECORD_SIZE);
|
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);
|
err = create_vtbl(ubi, si, i, vtbl);
|
||||||
if (err) {
|
if (err) {
|
||||||
kfree(vtbl);
|
vfree(vtbl);
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -784,7 +786,7 @@ int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_free:
|
out_free:
|
||||||
kfree(ubi->vtbl);
|
vfree(ubi->vtbl);
|
||||||
for (i = 0; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++)
|
for (i = 0; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++)
|
||||||
if (ubi->volumes[i]) {
|
if (ubi->volumes[i]) {
|
||||||
kfree(ubi->volumes[i]);
|
kfree(ubi->volumes[i]);
|
||||||
|
|
Loading…
Reference in New Issue