Skip to content

Commit 1320700

Browse files
committed
fix(thin_pool): reclaim a stale dm pool on init
An unclean shutdown (SIGKILL, so terminate/2 never ran) leaves hyper-thinpool behind; the next boot failed with "device-mapper: create ioctl ... Device or resource busy". Best-effort remove any pre-existing pool before rebuilding, ahead of zero_metadata so a still-live pool is never corrupted.
1 parent 8dc61d3 commit 1320700

1 file changed

Lines changed: 12 additions & 0 deletions

File tree

lib/hyper/node/img/thin_pool.ex

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ defmodule Hyper.Node.Img.ThinPool do
5353
with :ok <- File.mkdir_p(Hyper.Config.scratch_dir()),
5454
{:ok, meta} <- ensure_backing(@meta_file, ImgConfig.thin_pool_meta_size()),
5555
{:ok, data} <- ensure_backing(@data_file, ImgConfig.thin_pool_data_size()),
56+
:ok <- reclaim_stale_pool(),
5657
:ok <- zero_metadata(meta),
5758
{:ok, meta_loop} <- SuidHelper.Losetup.attach_rw(meta),
5859
{:ok, data_loop} <- SuidHelper.Losetup.attach_rw(data),
@@ -118,6 +119,17 @@ defmodule Hyper.Node.Img.ThinPool do
118119
@spec id_free(map(), non_neg_integer()) :: map()
119120
def id_free(%{freed: freed} = s, id), do: %{s | freed: [id | freed]}
120121

122+
# A run that did not shut down cleanly (e.g. SIGKILL, so `terminate/2` never
123+
# ran) leaves the dm pool behind, and recreating it fails with "Device or
124+
# resource busy". Best-effort remove any stale pool of our name so this boot
125+
# can build a fresh one. Runs before `zero_metadata`, which would otherwise
126+
# corrupt a still-live pool.
127+
@spec reclaim_stale_pool() :: :ok
128+
defp reclaim_stale_pool do
129+
_ = SuidHelper.Dmsetup.remove(@pool_name)
130+
:ok
131+
end
132+
121133
# Create a sparse file of `size` if absent; reuse it if already present.
122134
@spec ensure_backing(String.t(), Information.t()) :: {:ok, Path.t()} | {:error, term()}
123135
defp ensure_backing(file, size) do

0 commit comments

Comments
 (0)