Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+25 -11
+2
drivers/mtd/ubi/build.c
··· 923 923 spin_lock_init(&ubi->volumes_lock); 924 924 925 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 929 err = io_init(ubi); 928 930 if (err)
+21 -11
drivers/mtd/ubi/scan.c
··· 115 115 } else 116 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 119 if (!seb) 120 120 return -ENOMEM; 121 121 ··· 144 144 145 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 148 if (!seb) 149 149 return -ENOMEM; 150 150 ··· 553 553 if (err) 554 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 557 if (!seb) 558 558 return -ENOMEM; 559 559 ··· 1152 1152 si->volumes = RB_ROOT; 1153 1153 1154 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 1161 ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL); 1156 1162 if (!ech) 1157 - goto out_si; 1163 + goto out_slab; 1158 1164 1159 1165 vidh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL); 1160 1166 if (!vidh) ··· 1221 1215 ubi_free_vid_hdr(ubi, vidh); 1222 1216 out_ech: 1223 1217 kfree(ech); 1218 + out_slab: 1219 + kmem_cache_destroy(si->scan_leb_slab); 1224 1220 out_si: 1225 1221 ubi_scan_destroy_si(si); 1226 1222 return ERR_PTR(err); ··· 1231 1223 /** 1232 1224 * destroy_sv - free the scanning volume information 1233 1225 * @sv: scanning volume information 1226 + * @si: scanning information 1234 1227 * 1235 1228 * This function destroys the volume RB-tree (@sv->root) and the scanning 1236 1229 * volume information. 1237 1230 */ 1238 - static void destroy_sv(struct ubi_scan_volume *sv) 1231 + static void destroy_sv(struct ubi_scan_info *si, struct ubi_scan_volume *sv) 1239 1232 { 1240 1233 struct ubi_scan_leb *seb; 1241 1234 struct rb_node *this = sv->root.rb_node; ··· 1256 1247 this->rb_right = NULL; 1257 1248 } 1258 1249 1259 - kfree(seb); 1250 + kmem_cache_free(si->scan_leb_slab, seb); 1260 1251 } 1261 1252 } 1262 1253 kfree(sv); ··· 1274 1265 1275 1266 list_for_each_entry_safe(seb, seb_tmp, &si->alien, u.list) { 1276 1267 list_del(&seb->u.list); 1277 - kfree(seb); 1268 + kmem_cache_free(si->scan_leb_slab, seb); 1278 1269 } 1279 1270 list_for_each_entry_safe(seb, seb_tmp, &si->erase, u.list) { 1280 1271 list_del(&seb->u.list); 1281 - kfree(seb); 1272 + kmem_cache_free(si->scan_leb_slab, seb); 1282 1273 } 1283 1274 list_for_each_entry_safe(seb, seb_tmp, &si->corr, u.list) { 1284 1275 list_del(&seb->u.list); 1285 - kfree(seb); 1276 + kmem_cache_free(si->scan_leb_slab, seb); 1286 1277 } 1287 1278 list_for_each_entry_safe(seb, seb_tmp, &si->free, u.list) { 1288 1279 list_del(&seb->u.list); 1289 - kfree(seb); 1280 + kmem_cache_free(si->scan_leb_slab, seb); 1290 1281 } 1291 1282 1292 1283 /* Destroy the volume RB-tree */ ··· 1307 1298 rb->rb_right = NULL; 1308 1299 } 1309 1300 1310 - destroy_sv(sv); 1301 + destroy_sv(si, sv); 1311 1302 } 1312 1303 } 1313 1304 1305 + kmem_cache_destroy(si->scan_leb_slab); 1314 1306 kfree(si); 1315 1307 } 1316 1308
+2
drivers/mtd/ubi/scan.h
··· 109 109 * @mean_ec: mean erase counter value 110 110 * @ec_sum: a temporary variable used when calculating @mean_ec 111 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 114 * This data structure contains the result of scanning and may be used by other 114 115 * UBI sub-systems to build final UBI data structures, further error-recovery ··· 135 134 int mean_ec; 136 135 uint64_t ec_sum; 137 136 int ec_count; 137 + struct kmem_cache *scan_leb_slab; 138 138 }; 139 139 140 140 struct ubi_device;