]> granicus.if.org Git - zfs/commit
Tricky semantics of ms_max_size in metaslab_should_allocate()
authorSerapheim Dimitropoulos <serapheim@delphix.com>
Fri, 19 Jul 2019 18:19:50 +0000 (11:19 -0700)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Fri, 19 Jul 2019 18:19:50 +0000 (11:19 -0700)
commit7f31908913592b3075306daf403f2a334602493e
treef344e3d64241744587a44197f5b5720f5f759a21
parent43a8536260e76dab4a615164f9e6d6397c6b7778
Tricky semantics of ms_max_size in metaslab_should_allocate()

metaslab_should_allocate() is used in two places:
[1] When trying to select a metaslab to allocate from
[2] When trying to allocate from a metaslab

In [2] we always expect the metaslab to be loaded, and after
the refactoring of the log spacemap changes, whenever we load
a metaslab we set ms_max_size to the biggest range in the
ms_allocatable tree. Thus, when it is used in [2], if that
field is 0, it means that the metaslab doesn't have any
segments that can be used for allocations now (though it may
have some free space but that space can be in the freeing,
freed, or deferred trees).

In [1] a metaslab can be loaded or unloaded at which point 0
can either mean the metaslab doesn't have any space or the
metaslab is just not loaded thus we go ahead and try to make
an estimation based on its weight.

The issue here is when we call the above function for [2] and
the metaslab doesn't have any allocatable space, we still go
ahead and check its ms_weight which may be out of date because
we haven't ran metaslab_sync_done() yet. At that point we are
allowing an allocation to be attempted even though we know
there is no range that is allocatable.

This patch fixes this issue by explicitly checking if the
metaslab is loaded and if it is, the ms_max_size is used.

Reviewed-by: Matt Ahrens <mahrens@delphix.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Serapheim Dimitropoulos <serapheim@delphix.com>
Closes #9045
module/zfs/metaslab.c