Re: 'df' uninterruptible (kern_getfsstat -> vfs_busy -> sleep)

Peter Eriksson <[email protected]> Tue, 28 Jul 2026 10:42:30 +0200
Newsgroups gmane.os.freebsd.devel.file-systems
Message-ID <[email protected]>
--Apple-Mail=_C12B7F4B-5D1B-40DC-B613-5CB7994A4A93
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain;
	charset=utf-8

Ah, I think I see what=E2=80=99s happening with df and the blocking. The =
=E2=80=9Cproblem" is not in getfstat, but this code in df.c:

     if (!*argv) {
                /* everything (modulo -t) */
                mntsize =3D getmntinfo(&mntbuf, MNT_NOWAIT);
                mntsize =3D regetmntinfo(&mntbuf, mntsize);

The first call to getmntinfo() uses MNT_NOWAIT correctly, and then call =
regetmntinfo which causes a second call to getmntinfo():

static size_t
regetmntinfo(struct statfs **mntbufp, long mntsize)
{
        int error, i, j;
        struct statfs *mntbuf;

        if (vfslist_l =3D=3D NULL && vfslist_t =3D=3D NULL)
                return (nflag ? mntsize : getmntinfo(mntbufp, =
MNT_WAIT));

And since I didn=E2=80=99t use =E2=80=9C-n=E2=80=9D (nflag) for df then =
it will block due to MNT_WAIT. :-)

Anyway, it=E2=80=99s still nice to be able to abort df if one forgets to =
run it with =E2=80=9C-n=E2=80=9D :-)

- Peter


> On 28 Jul 2026, at 09:20, Peter Eriksson <[email protected]> wrote:
>=20
> I=E2=80=99ll test your fix and it=E2=80=99s good to be able to abort =
long running operations.
>=20
> However, I just read the source for df(1) and I wonder if it really =
should block at all - it calls getmntinfo() with MNT_NOWAIT. That is =
just a wrapper to getfsstat() and according to the manual page =
MNT_NOWAIT should skip =E2=80=9Cbusy=E2=80=9D filesystem:
>=20
> >     Normally mode should be specified as MNT_WAIT.  If mode is set =
to
> >     MNT_NOWAIT, getfsstat() will return the information it has =
available
> >     without requesting an update from each file system.  Thus, some =
of the
> >     information will be out of date, but getfsstat() will not block =
waiting
> >     for information from a file system that is unable to respond.  =
It will
> >     also skip any file system that is in the process of being =
unmounted, even
> >     if the unmount would eventually fail.
>=20
> So perhaps some more logic is needed in getfsstat() to avoid blocking =
:-)
>=20
> - Peter
>=20
>=20
>> On 27 Jul 2026, at 15:46, Konstantin Belousov <[email protected]> =
wrote:
>>=20
>> On Mon, Jul 27, 2026 at 03:17:11PM +0200, Peter Eriksson wrote:
>>> I just noticed (FreeBSD 15.1) that it seems that df is =
uninterruptible in the kernel if vfs_busy() is waiting for some =
lock/sleeping.=20
>>>=20
>>> Output from procstat:
>>>=20
>>> 54468 105116 df                  -                   mi_switch+0xbc =
_sleep+0x19e vfs_busy+0x203 kern_getfsstat+0x1e8 sys_getfsstat+0x22 =
amd64_syscall+0x126 fast_syscall_common+0xf8=20
>>>=20
>>>=20
>>> I=E2=80=99m running a =E2=80=9Czpool destroy=E2=80=9D on a pretty =
large ZFS spool which is taking some time so it=E2=80=99s probably =
waiting for some internal lock, but I don=E2=80=99t see why =
df/kern_getfsstat has to uninterruptible?
>>>=20
>>> (I originally did =E2=80=9Czfs destroy -t $POOL=E2=80=9D then after =
some time aborted that an run =E2=80=9Czpool destroy $POOL=E2=80=9D =
instead so there are probably a lot of internal zfs deletions running, =
=E2=80=9Czpool get freeing $POOL=E2=80=9D gives that there are around =
10TB being deleted.)
>>>=20
>>=20
>> Yes, this is reasonable, and I wanted to be able to interrupt the =
busy
>> for some time, but forget about it.
>>=20
>> Try https://reviews.freebsd.org/D58477
>=20


--Apple-Mail=_C12B7F4B-5D1B-40DC-B613-5CB7994A4A93
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html;
	charset=utf-8

<html aria-label=3D"message body"><head><meta http-equiv=3D"content-type" =
content=3D"text/html; charset=3Dutf-8"></head><body =
style=3D"overflow-wrap: break-word; -webkit-nbsp-mode: space; =
line-break: after-white-space;">Ah, I think I see what=E2=80=99s =
happening with df and the blocking. The =E2=80=9Cproblem" is not in =
getfstat, but this code in df.c:<div><br></div><div><div>&nbsp; &nbsp; =
&nbsp;if (!*argv) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; =
&nbsp; &nbsp; /* everything (modulo -t) */</div><div>&nbsp; &nbsp; =
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mntsize =3D =
getmntinfo(&amp;mntbuf, MNT_NOWAIT);</div><div>&nbsp; &nbsp; &nbsp; =
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mntsize =3D regetmntinfo(&amp;mntbuf, =
mntsize);</div><div><br></div><div>The first call to getmntinfo() uses =
MNT_NOWAIT correctly, and then call regetmntinfo which causes a second =
call to getmntinfo():</div><div><br></div><div><div>static =
size_t</div><div>regetmntinfo(struct statfs **mntbufp, long =
mntsize)</div><div>{</div><div>&nbsp; &nbsp; &nbsp; &nbsp; int error, i, =
j;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; struct statfs =
*mntbuf;</div><div><br></div><div>&nbsp; &nbsp; &nbsp; &nbsp; if =
(vfslist_l =3D=3D NULL &amp;&amp; vfslist_t =3D=3D =
NULL)</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; =
return (nflag ? mntsize : getmntinfo(mntbufp, =
MNT_WAIT));</div><div><br></div></div><div>And since I didn=E2=80=99t =
use =E2=80=9C-n=E2=80=9D (nflag) for df then it will block due to =
MNT_WAIT. :-)</div><div><br></div><div>Anyway, it=E2=80=99s still nice =
to be able to abort df if one forgets to run it with =E2=80=9C-n=E2=80=9D =
:-)</div><div><br></div><div>- =
Peter</div><div><br></div><div><br></div><div><blockquote =
type=3D"cite"><div>On 28 Jul 2026, at 09:20, Peter Eriksson =
&lt;[email protected]&gt; wrote:</div><br =
class=3D"Apple-interchange-newline"><div><meta http-equiv=3D"content-type"=
 content=3D"text/html; charset=3Dutf-8"><div style=3D"overflow-wrap: =
break-word; -webkit-nbsp-mode: space; line-break: =
after-white-space;">I=E2=80=99ll test your fix and it=E2=80=99s good to =
be able to abort long running operations.<div><br></div><div>However, I =
just read the source for df(1) and I wonder if it really should block at =
all - it calls getmntinfo() with MNT_NOWAIT. That is just a wrapper to =
getfsstat() and according to the manual page MNT_NOWAIT should skip =
=E2=80=9Cbusy=E2=80=9D filesystem:<div><br></div><div><div>&gt; &nbsp; =
&nbsp; Normally mode should be specified as MNT_WAIT. &nbsp;If mode is =
set to</div><div>&gt; &nbsp; &nbsp; MNT_NOWAIT, getfsstat() will return =
the information it has available</div><div>&gt; &nbsp; &nbsp; without =
requesting an update from each file system. &nbsp;Thus, some of =
the</div><div>&gt; &nbsp; &nbsp; information will be out of date, but =
getfsstat() will not block waiting</div><div>&gt; &nbsp; &nbsp; for =
information from a file system that is unable to respond. &nbsp;It =
will</div><div>&gt; &nbsp; &nbsp; also skip any file system that is in =
the process of being unmounted, even</div><div>&gt; &nbsp; &nbsp; if the =
unmount would eventually fail.</div><div><br></div><div>So perhaps some =
more logic is needed in getfsstat() to avoid blocking =
:-)</div><div><br></div><div>- =
Peter</div><div><br></div><div><br></div><div><blockquote =
type=3D"cite"><div>On 27 Jul 2026, at 15:46, Konstantin Belousov =
&lt;[email protected]&gt; wrote:</div><br =
class=3D"Apple-interchange-newline"><div><meta charset=3D"UTF-8"><span =
style=3D"caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: =
12px; font-style: normal; font-variant-caps: normal; font-weight: 400; =
letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; =
text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; =
-webkit-text-stroke-width: 0px; text-decoration: none; float: none; =
display: inline !important;">On Mon, Jul 27, 2026 at 03:17:11PM +0200, =
Peter Eriksson wrote:</span><br style=3D"caret-color: rgb(0, 0, 0); =
font-family: Helvetica; font-size: 12px; font-style: normal; =
font-variant-caps: normal; font-weight: 400; letter-spacing: normal; =
orphans: 2; text-align: start; text-indent: 0px; text-transform: none; =
white-space: normal; widows: 2; word-spacing: 0px; =
-webkit-text-stroke-width: 0px; text-decoration-line: none; =
text-decoration-thickness: auto; text-decoration-style: =
solid;"><blockquote type=3D"cite" style=3D"font-family: Helvetica; =
font-size: 12px; font-style: normal; font-variant-caps: normal; =
font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; =
text-indent: 0px; text-transform: none; white-space: normal; widows: 2; =
word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-line: =
none; text-decoration-thickness: auto; text-decoration-style: solid;">I =
just noticed (FreeBSD 15.1) that it seems that df is uninterruptible in =
the kernel if vfs_busy() is waiting for some lock/sleeping.<span =
class=3D"Apple-converted-space">&nbsp;</span><br><br>Output from =
procstat:<br><br>54468 105116 df =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&n=
bsp;&nbsp;&nbsp;&nbsp;&nbsp;- =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&n=
bsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mi_switch+0xbc _sleep+0x19e =
vfs_busy+0x203 kern_getfsstat+0x1e8 sys_getfsstat+0x22 =
amd64_syscall+0x126 fast_syscall_common+0xf8<span =
class=3D"Apple-converted-space">&nbsp;</span><br><br><br>I=E2=80=99m =
running a =E2=80=9Czpool destroy=E2=80=9D on a pretty large ZFS spool =
which is taking some time so it=E2=80=99s probably waiting for some =
internal lock, but I don=E2=80=99t see why df/kern_getfsstat has to =
uninterruptible?<br><br>(I originally did =E2=80=9Czfs destroy -t =
$POOL=E2=80=9D then after some time aborted that an run =E2=80=9Czpool =
destroy $POOL=E2=80=9D instead so there are probably a lot of internal =
zfs deletions running, =E2=80=9Czpool get freeing $POOL=E2=80=9D gives =
that there are around 10TB being deleted.)<br><br></blockquote><br =
style=3D"caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: =
12px; font-style: normal; font-variant-caps: normal; font-weight: 400; =
letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; =
text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; =
-webkit-text-stroke-width: 0px; text-decoration-line: none; =
text-decoration-thickness: auto; text-decoration-style: solid;"><span =
style=3D"caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: =
12px; font-style: normal; font-variant-caps: normal; font-weight: 400; =
letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; =
text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; =
-webkit-text-stroke-width: 0px; text-decoration: none; float: none; =
display: inline !important;">Yes, this is reasonable, and I wanted to be =
able to interrupt the busy</span><br style=3D"caret-color: rgb(0, 0, 0); =
font-family: Helvetica; font-size: 12px; font-style: normal; =
font-variant-caps: normal; font-weight: 400; letter-spacing: normal; =
orphans: 2; text-align: start; text-indent: 0px; text-transform: none; =
white-space: normal; widows: 2; word-spacing: 0px; =
-webkit-text-stroke-width: 0px; text-decoration-line: none; =
text-decoration-thickness: auto; text-decoration-style: solid;"><span =
style=3D"caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: =
12px; font-style: normal; font-variant-caps: normal; font-weight: 400; =
letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; =
text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; =
-webkit-text-stroke-width: 0px; text-decoration: none; float: none; =
display: inline !important;">for some time, but forget about =
it.</span><br style=3D"caret-color: rgb(0, 0, 0); font-family: =
Helvetica; font-size: 12px; font-style: normal; font-variant-caps: =
normal; font-weight: 400; letter-spacing: normal; orphans: 2; =
text-align: start; text-indent: 0px; text-transform: none; white-space: =
normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; =
text-decoration-line: none; text-decoration-thickness: auto; =
text-decoration-style: solid;"><br style=3D"caret-color: rgb(0, 0, 0); =
font-family: Helvetica; font-size: 12px; font-style: normal; =
font-variant-caps: normal; font-weight: 400; letter-spacing: normal; =
orphans: 2; text-align: start; text-indent: 0px; text-transform: none; =
white-space: normal; widows: 2; word-spacing: 0px; =
-webkit-text-stroke-width: 0px; text-decoration-line: none; =
text-decoration-thickness: auto; text-decoration-style: solid;"><span =
style=3D"caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: =
12px; font-style: normal; font-variant-caps: normal; font-weight: 400; =
letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; =
text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; =
-webkit-text-stroke-width: 0px; text-decoration: none; float: none; =
display: inline !important;">Try<span =
class=3D"Apple-converted-space">&nbsp;</span></span><a =
href=3D"https://reviews.freebsd.org/D58477" style=3D"font-family: =
Helvetica; font-size: 12px; font-style: normal; font-variant-caps: =
normal; font-weight: 400; letter-spacing: normal; orphans: 2; =
text-align: start; text-indent: 0px; text-transform: none; white-space: =
normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: =
0px;">https://reviews.freebsd.org/D58477</a></div></blockquote></div><br><=
/div></div></div></div></blockquote></div><br></div></body></html>=

--Apple-Mail=_C12B7F4B-5D1B-40DC-B613-5CB7994A4A93--