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: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
This commit is contained in:
parent
7950d023c5
commit
6c1e875ca6
3 changed files with 25 additions and 11 deletions
|
@ -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,
|
||||||
} 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)
|
||||||
|
|
||||||
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,
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
/**
|
/**
|
||||||
* 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)
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
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 {
|
||||||
* @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 {
|
||||||
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;
|
||||||
|
|
Loading…
Reference in a new issue