From: Luis Henriques Subject: Re: Don't detach volumes that have mounted partitions To: "Theo de Raadt" Cc: tech@openbsd.org Date: Wed, 06 Mar 2024 22:54:06 +0000 "Theo de Raadt" writes: > That's not good enough. > > One issue is swap. > > But I suspect there are other in-use circumstances this won't catch. > > Sometimes doing nothing is better, because it encourages people to be > paranoid and careful of bear the consequences. Hmm... yeah, makes sense. Adding a check for a swap device should be easy. Below is an _untested_ (and probably buggy) patch that adds the check for swap, stolen from swapctl(8). If that's something worth pursuing I can give it some more thought and testing tomorrow. Otherwise... I'll just drop it. Cheers, -- Luís diff --git sbin/bioctl/bioctl.8 sbin/bioctl/bioctl.8 index a187daf36edd..6dc06b8503d4 100644 --- sbin/bioctl/bioctl.8 +++ sbin/bioctl/bioctl.8 @@ -245,6 +245,9 @@ they become part of the array again. .It Fl d Detach volume specified by .Ar device . +It will fail if +.Ar device +has a mounted partition. .It Fl k Ar keydisk Use special device .Ar keydisk diff --git sbin/bioctl/bioctl.c sbin/bioctl/bioctl.c index 2e25d5801d9e..2d0a82ec35af 100644 --- sbin/bioctl/bioctl.c +++ sbin/bioctl/bioctl.c @@ -31,6 +31,9 @@ #include #include #include +#include +#include +#include #include #include @@ -39,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -1080,6 +1084,48 @@ void bio_deleteraid(char *dev) { struct bioc_deleteraid bd; + struct statfs *fs; + struct swapent *sep, *fsep; + int len, n, nswap; + char *s; + + n = getmntinfo(&fs, MNT_NOWAIT); + if (n == 0) + errx(1, "getmntinfo"); + len = sizeof(_PATH_DEV) - 1; + while (--n >= 0) { + s = fs[n].f_mntfromname; + if (strncmp(_PATH_DEV, s, len) == 0) + s += len; + if (strncmp(dev, s, strlen(dev)) == 0) + errx(1, "%s is still mounted on %s", + fs[n].f_mntfromname, fs[n].f_mntonname); + } + + n = swapctl(SWAP_NSWAP, 0, 0); + if (len < 0) + errx(1, "swapctl"); + + fsep = sep = calloc(n, sizeof(*sep)); + if (sep == NULL) + errx(1, "calloc"); + + nswap = swapctl(SWAP_STATS, (void *)sep, n); + if (n == -1) + errx(1, "swapctl"); + if (nswap != n) + warnx("SWAP_STATS different to SWAP_NSWAP (%d != %d)", + nswap, n); + for (; nswap-- > 0; sep++) { + s = sep->se_path; + if (strncmp(_PATH_DEV, s, len) == 0) + s += len; + if (strncmp(dev, s, strlen(dev)) == 0) + errx(1, "%s is being used as swap", + sep->se_path); + } + free(fsep); + memset(&bd, 0, sizeof(bd)); bd.bd_bio.bio_cookie = bio_cookie;