Commit 6c1e875c authored by Artem Bityutskiy's avatar Artem Bityutskiy

UBI: add slab cache for ubi_scan_leb objects

During scanning UBI allocates one struct ubi_scan_leb object for each PEB,
so it can end up allocating thousands of them. Use slab cache to reduce
memory consumption for these 48-byte objects, because currently used
'kmalloc()' ends up allocating 64 bytes per object, instead of 48.
Signed-off-by: default avatarArtem Bityutskiy <Artem.Bityutskiy@nokia.com>
parent 7950d023
...@@ -923,6 +923,8 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) ...@@ -923,6 +923,8 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
spin_lock_init(&ubi->volumes_lock); spin_lock_init(&ubi->volumes_lock);
ubi_msg("attaching mtd%d to ubi%d", mtd->index, ubi_num); ubi_msg("attaching mtd%d to ubi%d", mtd->index, ubi_num);
dbg_msg("sizeof(struct ubi_scan_leb) %zu", sizeof(struct ubi_scan_leb));
dbg_msg("sizeof(struct ubi_wl_entry) %zu", sizeof(struct ubi_wl_entry));
err = io_init(ubi); err = io_init(ubi);
if (err) if (err)
......
...@@ -115,7 +115,7 @@ static int add_to_list(struct ubi_scan_info *si, int pnum, int ec, int to_head, ...@@ -115,7 +115,7 @@ static int add_to_list(struct ubi_scan_info *si, int pnum, int ec, int to_head,
} else } else
BUG(); BUG();
seb = kmalloc(sizeof(struct ubi_scan_leb), GFP_KERNEL); seb = kmem_cache_alloc(si->scan_leb_slab, GFP_KERNEL);
if (!seb) if (!seb)
return -ENOMEM; return -ENOMEM;
...@@ -144,7 +144,7 @@ static int add_corrupted(struct ubi_scan_info *si, int pnum, int ec) ...@@ -144,7 +144,7 @@ static int add_corrupted(struct ubi_scan_info *si, int pnum, int ec)
dbg_bld("add to corrupted: PEB %d, EC %d", pnum, ec); dbg_bld("add to corrupted: PEB %d, EC %d", pnum, ec);
seb = kmalloc(sizeof(struct ubi_scan_leb), GFP_KERNEL); seb = kmem_cache_alloc(si->scan_leb_slab, GFP_KERNEL);
if (!seb) if (!seb)
return -ENOMEM; return -ENOMEM;
...@@ -553,7 +553,7 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si, ...@@ -553,7 +553,7 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
if (err) if (err)
return err; return err;
seb = kmalloc(sizeof(struct ubi_scan_leb), GFP_KERNEL); seb = kmem_cache_alloc(si->scan_leb_slab, GFP_KERNEL);
if (!seb) if (!seb)
return -ENOMEM; return -ENOMEM;
...@@ -1152,9 +1152,15 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi) ...@@ -1152,9 +1152,15 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi)
si->volumes = RB_ROOT; si->volumes = RB_ROOT;
err = -ENOMEM; err = -ENOMEM;
si->scan_leb_slab = kmem_cache_create("ubi_scan_leb_slab",
sizeof(struct ubi_scan_leb),
0, 0, NULL);
if (!si->scan_leb_slab)
goto out_si;
ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL); ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL);
if (!ech) if (!ech)
goto out_si; goto out_slab;
vidh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL); vidh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL);
if (!vidh) if (!vidh)
...@@ -1215,6 +1221,8 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi) ...@@ -1215,6 +1221,8 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi)
ubi_free_vid_hdr(ubi, vidh); ubi_free_vid_hdr(ubi, vidh);
out_ech: out_ech:
kfree(ech); kfree(ech);
out_slab:
kmem_cache_destroy(si->scan_leb_slab);
out_si: out_si:
ubi_scan_destroy_si(si); ubi_scan_destroy_si(si);
return ERR_PTR(err); return ERR_PTR(err);
...@@ -1223,11 +1231,12 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi) ...@@ -1223,11 +1231,12 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi)
/** /**
* destroy_sv - free the scanning volume information * destroy_sv - free the scanning volume information
* @sv: scanning volume information * @sv: scanning volume information
* @si: scanning information
* *
* This function destroys the volume RB-tree (@sv->root) and the scanning * This function destroys the volume RB-tree (@sv->root) and the scanning
* volume information. * volume information.
*/ */
static void destroy_sv(struct ubi_scan_volume *sv) static void destroy_sv(struct ubi_scan_info *si, struct ubi_scan_volume *sv)
{ {
struct ubi_scan_leb *seb; struct ubi_scan_leb *seb;
struct rb_node *this = sv->root.rb_node; struct rb_node *this = sv->root.rb_node;
...@@ -1247,7 +1256,7 @@ static void destroy_sv(struct ubi_scan_volume *sv) ...@@ -1247,7 +1256,7 @@ static void destroy_sv(struct ubi_scan_volume *sv)
this->rb_right = NULL; this->rb_right = NULL;
} }
kfree(seb); kmem_cache_free(si->scan_leb_slab, seb);
} }
} }
kfree(sv); kfree(sv);
...@@ -1265,19 +1274,19 @@ void ubi_scan_destroy_si(struct ubi_scan_info *si) ...@@ -1265,19 +1274,19 @@ void ubi_scan_destroy_si(struct ubi_scan_info *si)
list_for_each_entry_safe(seb, seb_tmp, &si->alien, u.list) { list_for_each_entry_safe(seb, seb_tmp, &si->alien, u.list) {
list_del(&seb->u.list); list_del(&seb->u.list);
kfree(seb); kmem_cache_free(si->scan_leb_slab, seb);
} }
list_for_each_entry_safe(seb, seb_tmp, &si->erase, u.list) { list_for_each_entry_safe(seb, seb_tmp, &si->erase, u.list) {
list_del(&seb->u.list); list_del(&seb->u.list);
kfree(seb); kmem_cache_free(si->scan_leb_slab, seb);
} }
list_for_each_entry_safe(seb, seb_tmp, &si->corr, u.list) { list_for_each_entry_safe(seb, seb_tmp, &si->corr, u.list) {
list_del(&seb->u.list); list_del(&seb->u.list);
kfree(seb); kmem_cache_free(si->scan_leb_slab, seb);
} }
list_for_each_entry_safe(seb, seb_tmp, &si->free, u.list) { list_for_each_entry_safe(seb, seb_tmp, &si->free, u.list) {
list_del(&seb->u.list); list_del(&seb->u.list);
kfree(seb); kmem_cache_free(si->scan_leb_slab, seb);
} }
/* Destroy the volume RB-tree */ /* Destroy the volume RB-tree */
...@@ -1298,10 +1307,11 @@ void ubi_scan_destroy_si(struct ubi_scan_info *si) ...@@ -1298,10 +1307,11 @@ void ubi_scan_destroy_si(struct ubi_scan_info *si)
rb->rb_right = NULL; rb->rb_right = NULL;
} }
destroy_sv(sv); destroy_sv(si, sv);
} }
} }
kmem_cache_destroy(si->scan_leb_slab);
kfree(si); kfree(si);
} }
......
...@@ -109,6 +109,7 @@ struct ubi_scan_volume { ...@@ -109,6 +109,7 @@ struct ubi_scan_volume {
* @mean_ec: mean erase counter value * @mean_ec: mean erase counter value
* @ec_sum: a temporary variable used when calculating @mean_ec * @ec_sum: a temporary variable used when calculating @mean_ec
* @ec_count: a temporary variable used when calculating @mean_ec * @ec_count: a temporary variable used when calculating @mean_ec
* @scan_leb_slab: slab cache for &struct ubi_scan_leb objects
* *
* This data structure contains the result of scanning and may be used by other * This data structure contains the result of scanning and may be used by other
* UBI sub-systems to build final UBI data structures, further error-recovery * UBI sub-systems to build final UBI data structures, further error-recovery
...@@ -134,6 +135,7 @@ struct ubi_scan_info { ...@@ -134,6 +135,7 @@ struct ubi_scan_info {
int mean_ec; int mean_ec;
uint64_t ec_sum; uint64_t ec_sum;
int ec_count; int ec_count;
struct kmem_cache *scan_leb_slab;
}; };
struct ubi_device; struct ubi_device;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment