@@ -205,6 +205,19 @@ zio_init(void)
205
205
206
206
if (align != 0 ) {
207
207
char name [36 ];
208
+ if (cflags == data_cflags ) {
209
+ /*
210
+ * Resulting kmem caches would be identical.
211
+ * Save memory by creating only one.
212
+ */
213
+ (void ) snprintf (name , sizeof (name ),
214
+ "zio_buf_comb_%lu" , (ulong_t )size );
215
+ zio_buf_cache [c ] = kmem_cache_create (name ,
216
+ size , align , NULL , NULL , NULL , NULL , NULL ,
217
+ cflags );
218
+ zio_data_buf_cache [c ] = zio_buf_cache [c ];
219
+ continue ;
220
+ }
208
221
(void ) snprintf (name , sizeof (name ), "zio_buf_%lu" ,
209
222
(ulong_t )size );
210
223
zio_buf_cache [c ] = kmem_cache_create (name , size ,
@@ -235,37 +248,50 @@ zio_init(void)
235
248
void
236
249
zio_fini (void )
237
250
{
238
- size_t c ;
239
- kmem_cache_t * last_cache = NULL ;
240
- kmem_cache_t * last_data_cache = NULL ;
251
+ size_t n = SPA_MAXBLOCKSIZE >> SPA_MINBLOCKSHIFT ;
241
252
242
- for (c = 0 ; c < SPA_MAXBLOCKSIZE >> SPA_MINBLOCKSHIFT ; c ++ ) {
243
- #ifdef _ILP32
244
- /*
245
- * Cache size limited to 1M on 32-bit platforms until ARC
246
- * buffers no longer require virtual address space.
247
- */
248
- if (((c + 1 ) << SPA_MINBLOCKSHIFT ) > zfs_max_recordsize )
249
- break ;
250
- #endif
251
253
#if defined(ZFS_DEBUG ) && !defined(_KERNEL )
252
- if (zio_buf_cache_allocs [c ] != zio_buf_cache_frees [c ])
254
+ for (size_t i = 0 ; i < n ; i ++ ) {
255
+ if (zio_buf_cache_allocs [i ] != zio_buf_cache_frees [i ])
253
256
(void ) printf ("zio_fini: [%d] %llu != %llu\n" ,
254
- (int )((c + 1 ) << SPA_MINBLOCKSHIFT ),
255
- (long long unsigned )zio_buf_cache_allocs [c ],
256
- (long long unsigned )zio_buf_cache_frees [c ]);
257
+ (int )((i + 1 ) << SPA_MINBLOCKSHIFT ),
258
+ (long long unsigned )zio_buf_cache_allocs [i ],
259
+ (long long unsigned )zio_buf_cache_frees [i ]);
260
+ }
257
261
#endif
258
- if (zio_buf_cache [c ] != last_cache ) {
259
- last_cache = zio_buf_cache [c ];
260
- kmem_cache_destroy (zio_buf_cache [c ]);
262
+
263
+ /*
264
+ * The same kmem cache can show up multiple times in both zio_buf_cache
265
+ * and zio_data_buf_cache. Do a wasteful but trivially correct scan to
266
+ * sort it out.
267
+ */
268
+ for (size_t i = 0 ; i < n ; i ++ ) {
269
+ kmem_cache_t * cache = zio_buf_cache [i ];
270
+ if (cache == NULL )
271
+ continue ;
272
+ for (size_t j = i ; j < n ; j ++ ) {
273
+ if (cache == zio_buf_cache [j ])
274
+ zio_buf_cache [j ] = NULL ;
275
+ if (cache == zio_data_buf_cache [j ])
276
+ zio_data_buf_cache [j ] = NULL ;
261
277
}
262
- zio_buf_cache [c ] = NULL ;
278
+ kmem_cache_destroy (cache );
279
+ }
263
280
264
- if (zio_data_buf_cache [c ] != last_data_cache ) {
265
- last_data_cache = zio_data_buf_cache [c ];
266
- kmem_cache_destroy (zio_data_buf_cache [c ]);
281
+ for (size_t i = 0 ; i < n ; i ++ ) {
282
+ kmem_cache_t * cache = zio_data_buf_cache [i ];
283
+ if (cache == NULL )
284
+ continue ;
285
+ for (size_t j = i ; j < n ; j ++ ) {
286
+ if (cache == zio_data_buf_cache [j ])
287
+ zio_data_buf_cache [j ] = NULL ;
267
288
}
268
- zio_data_buf_cache [c ] = NULL ;
289
+ kmem_cache_destroy (cache );
290
+ }
291
+
292
+ for (size_t i = 0 ; i < n ; i ++ ) {
293
+ VERIFY3P (zio_buf_cache [i ], = = , NULL );
294
+ VERIFY3P (zio_data_buf_cache [i ], = = , NULL );
269
295
}
270
296
271
297
kmem_cache_destroy (zio_link_cache );
0 commit comments