aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2010-10-31 11:54:14 -0400
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2011-02-06 12:19:23 -0500
commit6c1e875ca6f3a47b40dce715bd07fdfdb8388d55 (patch)
treeb30ab51df8df7c4ed9ef3adb68b234064816497f /drivers
parent7950d023c562823345892aac2e7c6a49f8de9ad1 (diff)
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mtd/ubi/build.c2
-rw-r--r--drivers/mtd/ubi/scan.c32
-rw-r--r--drivers/mtd/ubi/scan.h2
3 files changed, 25 insertions, 11 deletions
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index ef296350aa8f..ec0ad19c691a 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -923,6 +923,8 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
923 spin_lock_init(&ubi->volumes_lock); 923 spin_lock_init(&ubi->volumes_lock);
924 924
925 ubi_msg("attaching mtd%d to ubi%d", mtd->index, ubi_num); 925 ubi_msg("attaching mtd%d to ubi%d", mtd->index, ubi_num);
926 dbg_msg("sizeof(struct ubi_scan_leb) %zu", sizeof(struct ubi_scan_leb));
927 dbg_msg("sizeof(struct ubi_wl_entry) %zu", sizeof(struct ubi_wl_entry));
926 928
927 err = io_init(ubi); 929 err = io_init(ubi);
928 if (err) 930 if (err)
diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c
index 79ca304fc4db..0028bf283930 100644
--- a/drivers/mtd/ubi/scan.c
+++ b/drivers/mtd/ubi/scan.c
@@ -115,7 +115,7 @@ static int add_to_list(struct ubi_scan_info *si, int pnum, int ec, int to_head,
115 } else 115 } else
116 BUG(); 116 BUG();
117 117
118 seb = kmalloc(sizeof(struct ubi_scan_leb), GFP_KERNEL); 118 seb = kmem_cache_alloc(si->scan_leb_slab, GFP_KERNEL);
119 if (!seb) 119 if (!seb)
120 return -ENOMEM; 120 return -ENOMEM;
121 121
@@ -144,7 +144,7 @@ static int add_corrupted(struct ubi_scan_info *si, int pnum, int ec)
144 144
145 dbg_bld("add to corrupted: PEB %d, EC %d", pnum, ec); 145 dbg_bld("add to corrupted: PEB %d, EC %d", pnum, ec);
146 146
147 seb = kmalloc(sizeof(struct ubi_scan_leb), GFP_KERNEL); 147 seb = kmem_cache_alloc(si->scan_leb_slab, GFP_KERNEL);
148 if (!seb) 148 if (!seb)
149 return -ENOMEM; 149 return -ENOMEM;
150 150
@@ -553,7 +553,7 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
553 if (err) 553 if (err)
554 return err; 554 return err;
555 555
556 seb = kmalloc(sizeof(struct ubi_scan_leb), GFP_KERNEL); 556 seb = kmem_cache_alloc(si->scan_leb_slab, GFP_KERNEL);
557 if (!seb) 557 if (!seb)
558 return -ENOMEM; 558 return -ENOMEM;
559 559
@@ -1152,9 +1152,15 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi)
1152 si->volumes = RB_ROOT; 1152 si->volumes = RB_ROOT;
1153 1153
1154 err = -ENOMEM; 1154 err = -ENOMEM;
1155 si->scan_leb_slab = kmem_cache_create("ubi_scan_leb_slab",
1156 sizeof(struct ubi_scan_leb),
1157 0, 0, NULL);
1158 if (!si->scan_leb_slab)
1159 goto out_si;
1160
1155 ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL); 1161 ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL);
1156 if (!ech) 1162 if (!ech)
1157 goto out_si; 1163 goto out_slab;
1158 1164
1159 vidh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL); 1165 vidh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL);
1160 if (!vidh) 1166 if (!vidh)
@@ -1215,6 +1221,8 @@ out_vidh:
1215 ubi_free_vid_hdr(ubi, vidh); 1221 ubi_free_vid_hdr(ubi, vidh);
1216out_ech: 1222out_ech:
1217 kfree(ech); 1223 kfree(ech);
1224out_slab:
1225 kmem_cache_destroy(si->scan_leb_slab);
1218out_si: 1226out_si:
1219 ubi_scan_destroy_si(si); 1227 ubi_scan_destroy_si(si);
1220 return ERR_PTR(err); 1228 return ERR_PTR(err);
@@ -1223,11 +1231,12 @@ out_si:
1223/** 1231/**
1224 * destroy_sv - free the scanning volume information 1232 * destroy_sv - free the scanning volume information
1225 * @sv: scanning volume information 1233 * @sv: scanning volume information
1234 * @si: scanning information
1226 * 1235 *
1227 * This function destroys the volume RB-tree (@sv->root) and the scanning 1236 * This function destroys the volume RB-tree (@sv->root) and the scanning
1228 * volume information. 1237 * volume information.
1229 */ 1238 */
1230static void destroy_sv(struct ubi_scan_volume *sv) 1239static void destroy_sv(struct ubi_scan_info *si, struct ubi_scan_volume *sv)
1231{ 1240{
1232 struct ubi_scan_leb *seb; 1241 struct ubi_scan_leb *seb;
1233 struct rb_node *this = sv->root.rb_node; 1242 struct rb_node *this = sv->root.rb_node;
@@ -1247,7 +1256,7 @@ static void destroy_sv(struct ubi_scan_volume *sv)
1247 this->rb_right = NULL; 1256 this->rb_right = NULL;
1248 } 1257 }
1249 1258
1250 kfree(seb); 1259 kmem_cache_free(si->scan_leb_slab, seb);
1251 } 1260 }
1252 } 1261 }
1253 kfree(sv); 1262 kfree(sv);
@@ -1265,19 +1274,19 @@ void ubi_scan_destroy_si(struct ubi_scan_info *si)
1265 1274
1266 list_for_each_entry_safe(seb, seb_tmp, &si->alien, u.list) { 1275 list_for_each_entry_safe(seb, seb_tmp, &si->alien, u.list) {
1267 list_del(&seb->u.list); 1276 list_del(&seb->u.list);
1268 kfree(seb); 1277 kmem_cache_free(si->scan_leb_slab, seb);
1269 } 1278 }
1270 list_for_each_entry_safe(seb, seb_tmp, &si->erase, u.list) { 1279 list_for_each_entry_safe(seb, seb_tmp, &si->erase, u.list) {
1271 list_del(&seb->u.list); 1280 list_del(&seb->u.list);
1272 kfree(seb); 1281 kmem_cache_free(si->scan_leb_slab, seb);
1273 } 1282 }
1274 list_for_each_entry_safe(seb, seb_tmp, &si->corr, u.list) { 1283 list_for_each_entry_safe(seb, seb_tmp, &si->corr, u.list) {
1275 list_del(&seb->u.list); 1284 list_del(&seb->u.list);
1276 kfree(seb); 1285 kmem_cache_free(si->scan_leb_slab, seb);
1277 } 1286 }
1278 list_for_each_entry_safe(seb, seb_tmp, &si->free, u.list) { 1287 list_for_each_entry_safe(seb, seb_tmp, &si->free, u.list) {
1279 list_del(&seb->u.list); 1288 list_del(&seb->u.list);
1280 kfree(seb); 1289 kmem_cache_free(si->scan_leb_slab, seb);
1281 } 1290 }
1282 1291
1283 /* Destroy the volume RB-tree */ 1292 /* Destroy the volume RB-tree */
@@ -1298,10 +1307,11 @@ void ubi_scan_destroy_si(struct ubi_scan_info *si)
1298 rb->rb_right = NULL; 1307 rb->rb_right = NULL;
1299 } 1308 }
1300 1309
1301 destroy_sv(sv); 1310 destroy_sv(si, sv);
1302 } 1311 }
1303 } 1312 }
1304 1313
1314 kmem_cache_destroy(si->scan_leb_slab);
1305 kfree(si); 1315 kfree(si);
1306} 1316}
1307 1317
diff --git a/drivers/mtd/ubi/scan.h b/drivers/mtd/ubi/scan.h
index a3264f0bef2b..d48aef15ab5d 100644
--- a/drivers/mtd/ubi/scan.h
+++ b/drivers/mtd/ubi/scan.h
@@ -109,6 +109,7 @@ struct ubi_scan_volume {
109 * @mean_ec: mean erase counter value 109 * @mean_ec: mean erase counter value
110 * @ec_sum: a temporary variable used when calculating @mean_ec 110 * @ec_sum: a temporary variable used when calculating @mean_ec
111 * @ec_count: a temporary variable used when calculating @mean_ec 111 * @ec_count: a temporary variable used when calculating @mean_ec
112 * @scan_leb_slab: slab cache for &struct ubi_scan_leb objects
112 * 113 *
113 * This data structure contains the result of scanning and may be used by other 114 * This data structure contains the result of scanning and may be used by other
114 * UBI sub-systems to build final UBI data structures, further error-recovery 115 * UBI sub-systems to build final UBI data structures, further error-recovery
@@ -134,6 +135,7 @@ struct ubi_scan_info {
134 int mean_ec; 135 int mean_ec;
135 uint64_t ec_sum; 136 uint64_t ec_sum;
136 int ec_count; 137 int ec_count;
138 struct kmem_cache *scan_leb_slab;
137}; 139};
138 140
139struct ubi_device; 141struct ubi_device;