diff options
author | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2010-10-31 11:54:14 -0400 |
---|---|---|
committer | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2011-02-06 12:19:23 -0500 |
commit | 6c1e875ca6f3a47b40dce715bd07fdfdb8388d55 (patch) | |
tree | b30ab51df8df7c4ed9ef3adb68b234064816497f /drivers/mtd/ubi | |
parent | 7950d023c562823345892aac2e7c6a49f8de9ad1 (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/mtd/ubi')
-rw-r--r-- | drivers/mtd/ubi/build.c | 2 | ||||
-rw-r--r-- | drivers/mtd/ubi/scan.c | 32 | ||||
-rw-r--r-- | drivers/mtd/ubi/scan.h | 2 |
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); |
1216 | out_ech: | 1222 | out_ech: |
1217 | kfree(ech); | 1223 | kfree(ech); |
1224 | out_slab: | ||
1225 | kmem_cache_destroy(si->scan_leb_slab); | ||
1218 | out_si: | 1226 | out_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 | */ |
1230 | static void destroy_sv(struct ubi_scan_volume *sv) | 1239 | static 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 | ||
139 | struct ubi_device; | 141 | struct ubi_device; |