aboutsummaryrefslogtreecommitdiffstats
path: root/module/os/freebsd/zfs/abd_os.c
diff options
context:
space:
mode:
authorBrian Atkinson <[email protected]>2020-06-16 11:05:22 -0600
committerGitHub <[email protected]>2020-06-16 10:05:22 -0700
commit0a03495e3ee75b3457181910081e809dda80cec0 (patch)
treee378bb35226740775843fbeb0baece40a9989163 /module/os/freebsd/zfs/abd_os.c
parentc13facb9c4a036034ff8d898857a81c64c83dc09 (diff)
Fixing ABD struct allocation for FreeBSD
In the event we are allocating a gang ABD in FreeBSD we are passing 0 to abd_alloc_struct(); however, this led to an allocation of ABD scatter with 0 chunks. This left the gang ABD allocation 24 bytes smaller than it should have been. Reviewed-by: Matt Macy <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Co-authored-by: Matt Macy <[email protected]> Signed-off-by: Brian Atkinson <[email protected]> Closes #10431
Diffstat (limited to 'module/os/freebsd/zfs/abd_os.c')
-rw-r--r--module/os/freebsd/zfs/abd_os.c17
1 files changed, 13 insertions, 4 deletions
diff --git a/module/os/freebsd/zfs/abd_os.c b/module/os/freebsd/zfs/abd_os.c
index e87981815..500174775 100644
--- a/module/os/freebsd/zfs/abd_os.c
+++ b/module/os/freebsd/zfs/abd_os.c
@@ -198,8 +198,15 @@ abd_t *
abd_alloc_struct(size_t size)
{
size_t chunkcnt = abd_chunkcnt_for_bytes(size);
- size_t abd_size = offsetof(abd_t,
- abd_u.abd_scatter.abd_chunks[chunkcnt]);
+ /*
+ * In the event we are allocating a gang ABD, the size passed in
+ * will be 0. We must make sure to set abd_size to the size of an
+ * ABD struct as opposed to an ABD scatter with 0 chunks. The gang
+ * ABD struct allocation accounts for an additional 24 bytes over
+ * a scatter ABD with 0 chunks.
+ */
+ size_t abd_size = MAX(sizeof (abd_t),
+ offsetof(abd_t, abd_u.abd_scatter.abd_chunks[chunkcnt]));
abd_t *abd = kmem_alloc(abd_size, KM_PUSHPAGE);
ASSERT3P(abd, !=, NULL);
list_link_init(&abd->abd_gang_link);
@@ -212,8 +219,10 @@ abd_alloc_struct(size_t size)
void
abd_free_struct(abd_t *abd)
{
- size_t chunkcnt = abd_is_linear(abd) ? 0 : abd_scatter_chunkcnt(abd);
- int size = offsetof(abd_t, abd_u.abd_scatter.abd_chunks[chunkcnt]);
+ size_t chunkcnt = abd_is_linear(abd) || abd_is_gang(abd) ? 0 :
+ abd_scatter_chunkcnt(abd);
+ int size = MAX(sizeof (abd_t),
+ offsetof(abd_t, abd_u.abd_scatter.abd_chunks[chunkcnt]));
mutex_destroy(&abd->abd_mtx);
ASSERT(!list_link_active(&abd->abd_gang_link));
kmem_free(abd, size);