]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - module/os/freebsd/zfs/abd_os.c
Use wmsum for arc, abd, dbuf and zfetch statistics. (#12172)
[FreeBSD/FreeBSD.git] / module / os / freebsd / zfs / abd_os.c
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11
12 /*
13  * Copyright (c) 2014 by Chunwei Chen. All rights reserved.
14  * Copyright (c) 2016 by Delphix. All rights reserved.
15  */
16
17 /*
18  * See abd.c for a general overview of the arc buffered data (ABD).
19  *
20  * Using a large proportion of scattered ABDs decreases ARC fragmentation since
21  * when we are at the limit of allocatable space, using equal-size chunks will
22  * allow us to quickly reclaim enough space for a new large allocation (assuming
23  * it is also scattered).
24  *
25  * ABDs are allocated scattered by default unless the caller uses
26  * abd_alloc_linear() or zfs_abd_scatter_enabled is disabled.
27  */
28
29 #include <sys/abd_impl.h>
30 #include <sys/param.h>
31 #include <sys/types.h>
32 #include <sys/zio.h>
33 #include <sys/zfs_context.h>
34 #include <sys/zfs_znode.h>
35
36 typedef struct abd_stats {
37         kstat_named_t abdstat_struct_size;
38         kstat_named_t abdstat_scatter_cnt;
39         kstat_named_t abdstat_scatter_data_size;
40         kstat_named_t abdstat_scatter_chunk_waste;
41         kstat_named_t abdstat_linear_cnt;
42         kstat_named_t abdstat_linear_data_size;
43 } abd_stats_t;
44
45 static abd_stats_t abd_stats = {
46         /* Amount of memory occupied by all of the abd_t struct allocations */
47         { "struct_size",                        KSTAT_DATA_UINT64 },
48         /*
49          * The number of scatter ABDs which are currently allocated, excluding
50          * ABDs which don't own their data (for instance the ones which were
51          * allocated through abd_get_offset()).
52          */
53         { "scatter_cnt",                        KSTAT_DATA_UINT64 },
54         /* Amount of data stored in all scatter ABDs tracked by scatter_cnt */
55         { "scatter_data_size",                  KSTAT_DATA_UINT64 },
56         /*
57          * The amount of space wasted at the end of the last chunk across all
58          * scatter ABDs tracked by scatter_cnt.
59          */
60         { "scatter_chunk_waste",                KSTAT_DATA_UINT64 },
61         /*
62          * The number of linear ABDs which are currently allocated, excluding
63          * ABDs which don't own their data (for instance the ones which were
64          * allocated through abd_get_offset() and abd_get_from_buf()). If an
65          * ABD takes ownership of its buf then it will become tracked.
66          */
67         { "linear_cnt",                         KSTAT_DATA_UINT64 },
68         /* Amount of data stored in all linear ABDs tracked by linear_cnt */
69         { "linear_data_size",                   KSTAT_DATA_UINT64 },
70 };
71
72 struct {
73         wmsum_t abdstat_struct_size;
74         wmsum_t abdstat_scatter_cnt;
75         wmsum_t abdstat_scatter_data_size;
76         wmsum_t abdstat_scatter_chunk_waste;
77         wmsum_t abdstat_linear_cnt;
78         wmsum_t abdstat_linear_data_size;
79 } abd_sums;
80
81 /*
82  * The size of the chunks ABD allocates. Because the sizes allocated from the
83  * kmem_cache can't change, this tunable can only be modified at boot. Changing
84  * it at runtime would cause ABD iteration to work incorrectly for ABDs which
85  * were allocated with the old size, so a safeguard has been put in place which
86  * will cause the machine to panic if you change it and try to access the data
87  * within a scattered ABD.
88  */
89 size_t zfs_abd_chunk_size = 4096;
90
91 #if defined(_KERNEL)
92 SYSCTL_DECL(_vfs_zfs);
93
94 SYSCTL_INT(_vfs_zfs, OID_AUTO, abd_scatter_enabled, CTLFLAG_RWTUN,
95         &zfs_abd_scatter_enabled, 0, "Enable scattered ARC data buffers");
96 SYSCTL_ULONG(_vfs_zfs, OID_AUTO, abd_chunk_size, CTLFLAG_RDTUN,
97         &zfs_abd_chunk_size, 0, "The size of the chunks ABD allocates");
98 #endif
99
100 kmem_cache_t *abd_chunk_cache;
101 static kstat_t *abd_ksp;
102
103 /*
104  * We use a scattered SPA_MAXBLOCKSIZE sized ABD whose chunks are
105  * just a single zero'd sized zfs_abd_chunk_size buffer. This
106  * allows us to conserve memory by only using a single zero buffer
107  * for the scatter chunks.
108  */
109 abd_t *abd_zero_scatter = NULL;
110 static char *abd_zero_buf = NULL;
111
112 static void
113 abd_free_chunk(void *c)
114 {
115         kmem_cache_free(abd_chunk_cache, c);
116 }
117
118 static uint_t
119 abd_chunkcnt_for_bytes(size_t size)
120 {
121         return (P2ROUNDUP(size, zfs_abd_chunk_size) / zfs_abd_chunk_size);
122 }
123
124 static inline uint_t
125 abd_scatter_chunkcnt(abd_t *abd)
126 {
127         ASSERT(!abd_is_linear(abd));
128         return (abd_chunkcnt_for_bytes(
129             ABD_SCATTER(abd).abd_offset + abd->abd_size));
130 }
131
132 boolean_t
133 abd_size_alloc_linear(size_t size)
134 {
135         return (size <= zfs_abd_chunk_size ? B_TRUE : B_FALSE);
136 }
137
138 void
139 abd_update_scatter_stats(abd_t *abd, abd_stats_op_t op)
140 {
141         uint_t n = abd_scatter_chunkcnt(abd);
142         ASSERT(op == ABDSTAT_INCR || op == ABDSTAT_DECR);
143         int waste = n * zfs_abd_chunk_size - abd->abd_size;
144         if (op == ABDSTAT_INCR) {
145                 ABDSTAT_BUMP(abdstat_scatter_cnt);
146                 ABDSTAT_INCR(abdstat_scatter_data_size, abd->abd_size);
147                 ABDSTAT_INCR(abdstat_scatter_chunk_waste, waste);
148                 arc_space_consume(waste, ARC_SPACE_ABD_CHUNK_WASTE);
149         } else {
150                 ABDSTAT_BUMPDOWN(abdstat_scatter_cnt);
151                 ABDSTAT_INCR(abdstat_scatter_data_size, -(int)abd->abd_size);
152                 ABDSTAT_INCR(abdstat_scatter_chunk_waste, -waste);
153                 arc_space_return(waste, ARC_SPACE_ABD_CHUNK_WASTE);
154         }
155 }
156
157 void
158 abd_update_linear_stats(abd_t *abd, abd_stats_op_t op)
159 {
160         ASSERT(op == ABDSTAT_INCR || op == ABDSTAT_DECR);
161         if (op == ABDSTAT_INCR) {
162                 ABDSTAT_BUMP(abdstat_linear_cnt);
163                 ABDSTAT_INCR(abdstat_linear_data_size, abd->abd_size);
164         } else {
165                 ABDSTAT_BUMPDOWN(abdstat_linear_cnt);
166                 ABDSTAT_INCR(abdstat_linear_data_size, -(int)abd->abd_size);
167         }
168 }
169
170 void
171 abd_verify_scatter(abd_t *abd)
172 {
173         uint_t i, n;
174
175         /*
176          * There is no scatter linear pages in FreeBSD so there is an
177          * if an error if the ABD has been marked as a linear page.
178          */
179         ASSERT(!abd_is_linear_page(abd));
180         ASSERT3U(ABD_SCATTER(abd).abd_offset, <,
181             zfs_abd_chunk_size);
182         n = abd_scatter_chunkcnt(abd);
183         for (i = 0; i < n; i++) {
184                 ASSERT3P(ABD_SCATTER(abd).abd_chunks[i], !=, NULL);
185         }
186 }
187
188 void
189 abd_alloc_chunks(abd_t *abd, size_t size)
190 {
191         uint_t i, n;
192
193         n = abd_chunkcnt_for_bytes(size);
194         for (i = 0; i < n; i++) {
195                 void *c = kmem_cache_alloc(abd_chunk_cache, KM_PUSHPAGE);
196                 ASSERT3P(c, !=, NULL);
197                 ABD_SCATTER(abd).abd_chunks[i] = c;
198         }
199         ABD_SCATTER(abd).abd_chunk_size = zfs_abd_chunk_size;
200 }
201
202 void
203 abd_free_chunks(abd_t *abd)
204 {
205         uint_t i, n;
206
207         n = abd_scatter_chunkcnt(abd);
208         for (i = 0; i < n; i++) {
209                 abd_free_chunk(ABD_SCATTER(abd).abd_chunks[i]);
210         }
211 }
212
213 abd_t *
214 abd_alloc_struct_impl(size_t size)
215 {
216         uint_t chunkcnt = abd_chunkcnt_for_bytes(size);
217         /*
218          * In the event we are allocating a gang ABD, the size passed in
219          * will be 0. We must make sure to set abd_size to the size of an
220          * ABD struct as opposed to an ABD scatter with 0 chunks. The gang
221          * ABD struct allocation accounts for an additional 24 bytes over
222          * a scatter ABD with 0 chunks.
223          */
224         size_t abd_size = MAX(sizeof (abd_t),
225             offsetof(abd_t, abd_u.abd_scatter.abd_chunks[chunkcnt]));
226         abd_t *abd = kmem_alloc(abd_size, KM_PUSHPAGE);
227         ASSERT3P(abd, !=, NULL);
228         ABDSTAT_INCR(abdstat_struct_size, abd_size);
229
230         return (abd);
231 }
232
233 void
234 abd_free_struct_impl(abd_t *abd)
235 {
236         uint_t chunkcnt = abd_is_linear(abd) || abd_is_gang(abd) ? 0 :
237             abd_scatter_chunkcnt(abd);
238         ssize_t size = MAX(sizeof (abd_t),
239             offsetof(abd_t, abd_u.abd_scatter.abd_chunks[chunkcnt]));
240         kmem_free(abd, size);
241         ABDSTAT_INCR(abdstat_struct_size, -size);
242 }
243
244 /*
245  * Allocate scatter ABD of size SPA_MAXBLOCKSIZE, where
246  * each chunk in the scatterlist will be set to abd_zero_buf.
247  */
248 static void
249 abd_alloc_zero_scatter(void)
250 {
251         uint_t i, n;
252
253         n = abd_chunkcnt_for_bytes(SPA_MAXBLOCKSIZE);
254         abd_zero_buf = kmem_zalloc(zfs_abd_chunk_size, KM_SLEEP);
255         abd_zero_scatter = abd_alloc_struct(SPA_MAXBLOCKSIZE);
256
257         abd_zero_scatter->abd_flags |= ABD_FLAG_OWNER | ABD_FLAG_ZEROS;
258         abd_zero_scatter->abd_size = SPA_MAXBLOCKSIZE;
259
260         ABD_SCATTER(abd_zero_scatter).abd_offset = 0;
261         ABD_SCATTER(abd_zero_scatter).abd_chunk_size =
262             zfs_abd_chunk_size;
263
264         for (i = 0; i < n; i++) {
265                 ABD_SCATTER(abd_zero_scatter).abd_chunks[i] =
266                     abd_zero_buf;
267         }
268
269         ABDSTAT_BUMP(abdstat_scatter_cnt);
270         ABDSTAT_INCR(abdstat_scatter_data_size, zfs_abd_chunk_size);
271 }
272
273 static void
274 abd_free_zero_scatter(void)
275 {
276         ABDSTAT_BUMPDOWN(abdstat_scatter_cnt);
277         ABDSTAT_INCR(abdstat_scatter_data_size, -(int)zfs_abd_chunk_size);
278
279         abd_free_struct(abd_zero_scatter);
280         abd_zero_scatter = NULL;
281         kmem_free(abd_zero_buf, zfs_abd_chunk_size);
282 }
283
284 static int
285 abd_kstats_update(kstat_t *ksp, int rw)
286 {
287         abd_stats_t *as = ksp->ks_data;
288
289         if (rw == KSTAT_WRITE)
290                 return (EACCES);
291         as->abdstat_struct_size.value.ui64 =
292             wmsum_value(&abd_sums.abdstat_struct_size);
293         as->abdstat_scatter_cnt.value.ui64 =
294             wmsum_value(&abd_sums.abdstat_scatter_cnt);
295         as->abdstat_scatter_data_size.value.ui64 =
296             wmsum_value(&abd_sums.abdstat_scatter_data_size);
297         as->abdstat_scatter_chunk_waste.value.ui64 =
298             wmsum_value(&abd_sums.abdstat_scatter_chunk_waste);
299         as->abdstat_linear_cnt.value.ui64 =
300             wmsum_value(&abd_sums.abdstat_linear_cnt);
301         as->abdstat_linear_data_size.value.ui64 =
302             wmsum_value(&abd_sums.abdstat_linear_data_size);
303         return (0);
304 }
305
306 void
307 abd_init(void)
308 {
309         abd_chunk_cache = kmem_cache_create("abd_chunk", zfs_abd_chunk_size, 0,
310             NULL, NULL, NULL, NULL, 0, KMC_NODEBUG);
311
312         wmsum_init(&abd_sums.abdstat_struct_size, 0);
313         wmsum_init(&abd_sums.abdstat_scatter_cnt, 0);
314         wmsum_init(&abd_sums.abdstat_scatter_data_size, 0);
315         wmsum_init(&abd_sums.abdstat_scatter_chunk_waste, 0);
316         wmsum_init(&abd_sums.abdstat_linear_cnt, 0);
317         wmsum_init(&abd_sums.abdstat_linear_data_size, 0);
318
319         abd_ksp = kstat_create("zfs", 0, "abdstats", "misc", KSTAT_TYPE_NAMED,
320             sizeof (abd_stats) / sizeof (kstat_named_t), KSTAT_FLAG_VIRTUAL);
321         if (abd_ksp != NULL) {
322                 abd_ksp->ks_data = &abd_stats;
323                 abd_ksp->ks_update = abd_kstats_update;
324                 kstat_install(abd_ksp);
325         }
326
327         abd_alloc_zero_scatter();
328 }
329
330 void
331 abd_fini(void)
332 {
333         abd_free_zero_scatter();
334
335         if (abd_ksp != NULL) {
336                 kstat_delete(abd_ksp);
337                 abd_ksp = NULL;
338         }
339
340         wmsum_fini(&abd_sums.abdstat_struct_size);
341         wmsum_fini(&abd_sums.abdstat_scatter_cnt);
342         wmsum_fini(&abd_sums.abdstat_scatter_data_size);
343         wmsum_fini(&abd_sums.abdstat_scatter_chunk_waste);
344         wmsum_fini(&abd_sums.abdstat_linear_cnt);
345         wmsum_fini(&abd_sums.abdstat_linear_data_size);
346
347         kmem_cache_destroy(abd_chunk_cache);
348         abd_chunk_cache = NULL;
349 }
350
351 void
352 abd_free_linear_page(abd_t *abd)
353 {
354         /*
355          * FreeBSD does not have scatter linear pages
356          * so there is an error.
357          */
358         VERIFY(0);
359 }
360
361 /*
362  * If we're going to use this ABD for doing I/O using the block layer, the
363  * consumer of the ABD data doesn't care if it's scattered or not, and we don't
364  * plan to store this ABD in memory for a long period of time, we should
365  * allocate the ABD type that requires the least data copying to do the I/O.
366  *
367  * Currently this is linear ABDs, however if ldi_strategy() can ever issue I/Os
368  * using a scatter/gather list we should switch to that and replace this call
369  * with vanilla abd_alloc().
370  */
371 abd_t *
372 abd_alloc_for_io(size_t size, boolean_t is_metadata)
373 {
374         return (abd_alloc_linear(size, is_metadata));
375 }
376
377 abd_t *
378 abd_get_offset_scatter(abd_t *abd, abd_t *sabd, size_t off)
379 {
380         abd_verify(sabd);
381         ASSERT3U(off, <=, sabd->abd_size);
382
383         size_t new_offset = ABD_SCATTER(sabd).abd_offset + off;
384         uint_t chunkcnt = abd_scatter_chunkcnt(sabd) -
385             (new_offset / zfs_abd_chunk_size);
386
387         /*
388          * If an abd struct is provided, it is only the minimum size.  If we
389          * need additional chunks, we need to allocate a new struct.
390          */
391         if (abd != NULL &&
392             offsetof(abd_t, abd_u.abd_scatter.abd_chunks[chunkcnt]) >
393             sizeof (abd_t)) {
394                 abd = NULL;
395         }
396
397         if (abd == NULL)
398                 abd = abd_alloc_struct(chunkcnt * zfs_abd_chunk_size);
399
400         /*
401          * Even if this buf is filesystem metadata, we only track that
402          * if we own the underlying data buffer, which is not true in
403          * this case. Therefore, we don't ever use ABD_FLAG_META here.
404          */
405
406         ABD_SCATTER(abd).abd_offset = new_offset % zfs_abd_chunk_size;
407         ABD_SCATTER(abd).abd_chunk_size = zfs_abd_chunk_size;
408
409         /* Copy the scatterlist starting at the correct offset */
410         (void) memcpy(&ABD_SCATTER(abd).abd_chunks,
411             &ABD_SCATTER(sabd).abd_chunks[new_offset /
412             zfs_abd_chunk_size],
413             chunkcnt * sizeof (void *));
414
415         return (abd);
416 }
417
418 static inline size_t
419 abd_iter_scatter_chunk_offset(struct abd_iter *aiter)
420 {
421         ASSERT(!abd_is_linear(aiter->iter_abd));
422         return ((ABD_SCATTER(aiter->iter_abd).abd_offset +
423             aiter->iter_pos) % zfs_abd_chunk_size);
424 }
425
426 static inline size_t
427 abd_iter_scatter_chunk_index(struct abd_iter *aiter)
428 {
429         ASSERT(!abd_is_linear(aiter->iter_abd));
430         return ((ABD_SCATTER(aiter->iter_abd).abd_offset +
431             aiter->iter_pos) / zfs_abd_chunk_size);
432 }
433
434 /*
435  * Initialize the abd_iter.
436  */
437 void
438 abd_iter_init(struct abd_iter *aiter, abd_t *abd)
439 {
440         ASSERT(!abd_is_gang(abd));
441         abd_verify(abd);
442         aiter->iter_abd = abd;
443         aiter->iter_pos = 0;
444         aiter->iter_mapaddr = NULL;
445         aiter->iter_mapsize = 0;
446 }
447
448 /*
449  * This is just a helper function to see if we have exhausted the
450  * abd_iter and reached the end.
451  */
452 boolean_t
453 abd_iter_at_end(struct abd_iter *aiter)
454 {
455         return (aiter->iter_pos == aiter->iter_abd->abd_size);
456 }
457
458 /*
459  * Advance the iterator by a certain amount. Cannot be called when a chunk is
460  * in use. This can be safely called when the aiter has already exhausted, in
461  * which case this does nothing.
462  */
463 void
464 abd_iter_advance(struct abd_iter *aiter, size_t amount)
465 {
466         ASSERT3P(aiter->iter_mapaddr, ==, NULL);
467         ASSERT0(aiter->iter_mapsize);
468
469         /* There's nothing left to advance to, so do nothing */
470         if (abd_iter_at_end(aiter))
471                 return;
472
473         aiter->iter_pos += amount;
474 }
475
476 /*
477  * Map the current chunk into aiter. This can be safely called when the aiter
478  * has already exhausted, in which case this does nothing.
479  */
480 void
481 abd_iter_map(struct abd_iter *aiter)
482 {
483         void *paddr;
484         size_t offset = 0;
485
486         ASSERT3P(aiter->iter_mapaddr, ==, NULL);
487         ASSERT0(aiter->iter_mapsize);
488
489         /* Panic if someone has changed zfs_abd_chunk_size */
490         IMPLY(!abd_is_linear(aiter->iter_abd), zfs_abd_chunk_size ==
491             ABD_SCATTER(aiter->iter_abd).abd_chunk_size);
492
493         /* There's nothing left to iterate over, so do nothing */
494         if (abd_iter_at_end(aiter))
495                 return;
496
497         if (abd_is_linear(aiter->iter_abd)) {
498                 offset = aiter->iter_pos;
499                 aiter->iter_mapsize = aiter->iter_abd->abd_size - offset;
500                 paddr = ABD_LINEAR_BUF(aiter->iter_abd);
501         } else {
502                 size_t index = abd_iter_scatter_chunk_index(aiter);
503                 offset = abd_iter_scatter_chunk_offset(aiter);
504                 aiter->iter_mapsize = MIN(zfs_abd_chunk_size - offset,
505                     aiter->iter_abd->abd_size - aiter->iter_pos);
506                 paddr = ABD_SCATTER(aiter->iter_abd).abd_chunks[index];
507         }
508         aiter->iter_mapaddr = (char *)paddr + offset;
509 }
510
511 /*
512  * Unmap the current chunk from aiter. This can be safely called when the aiter
513  * has already exhausted, in which case this does nothing.
514  */
515 void
516 abd_iter_unmap(struct abd_iter *aiter)
517 {
518         /* There's nothing left to unmap, so do nothing */
519         if (abd_iter_at_end(aiter))
520                 return;
521
522         ASSERT3P(aiter->iter_mapaddr, !=, NULL);
523         ASSERT3U(aiter->iter_mapsize, >, 0);
524
525         aiter->iter_mapaddr = NULL;
526         aiter->iter_mapsize = 0;
527 }
528
529 void
530 abd_cache_reap_now(void)
531 {
532         kmem_cache_reap_soon(abd_chunk_cache);
533 }