NetBSD Problem Report #60383
From www@netbsd.org Mon Jun 29 02:26:53 2026
Return-Path: <www@netbsd.org>
Received: from mail.netbsd.org (mail.netbsd.org [199.233.217.200])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256
client-signature RSA-PSS (2048 bits) client-digest SHA256)
(Client CN "mail.netbsd.org", Issuer "R13" (not verified))
by mollari.NetBSD.org (Postfix) with ESMTPS id DB3BE1A923A
for <gnats-bugs@gnats.NetBSD.org>; Mon, 29 Jun 2026 02:26:52 +0000 (UTC)
Message-Id: <20260629022651.D75CB1A923B@mollari.NetBSD.org>
Date: Mon, 29 Jun 2026 02:26:51 +0000 (UTC)
From: campbell+netbsd@mumble.net
Reply-To: campbell+netbsd@mumble.net
To: gnats-bugs@NetBSD.org
Subject: fssconfig(8): distinguish between taking and loading a snapshot
X-Send-Pr-Version: www-1.0
X-From4GNATS: "campbell+netbsd@mumble.net via gnats" <gnats-admin@NetBSD.org>
>Number: 60383
>Category: bin
>Synopsis: fssconfig(8): distinguish between taking and loading a snapshot
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: bin-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Mon Jun 29 02:30:00 +0000 2026
>Last-Modified: Sat Jul 25 19:30:02 +0000 2026
>Originator: Taylor R Campbell
>Release: current, 11, 10, 9, ...
>Organization:
The NetFSS Foundasnapshot, Inc.
>Environment:
>Description:
The way to create a new snapshot /fs/.snap/20260628 archiving
the current state of a file system /fs, and configure fss0 to
point at it, is:
fssconfig fss0 /fs /fs/.snap/20260628
The way to load an existing snapshot /fs/.snap/20260628
recovering a past state of the file system /fs is:
fssconfig fss0 /fs /fs/.snap/20260628
Yes, those are the same command.
This is confusing and error-prone: what operation we are
_trying_ to do should not depend on what files exist on disk.
When _creating_ a snapshot, fssconfig(8) should be able to
report an error if the file already exists.
When _loading_ a snapshot, fssconfig(8) should be able to
report an error if the file does not actually exist.
>How-To-Repeat:
try to use ffs fss snapshots (say that five times fast!)
>Fix:
Yes, please!
Perhaps we should have separate options like -C and -L for
`create' and `load'.
>Audit-Trail:
From: "Taylor R Campbell" <riastradh@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc:
Subject: PR/60383 CVS commit: src/share/man/man4
Date: Mon, 6 Jul 2026 13:37:08 +0000
Module Name: src
Committed By: riastradh
Date: Mon Jul 6 13:37:08 UTC 2026
Modified Files:
src/share/man/man4: fss.4
Log Message:
fss(4): Clarify FSSIOCSET operation for persistent snapshots.
Prompted by the persistent confusion on my part that led to:
PR bin/60383: fssconfig(8): distinguish between taking and loading a
snapshot
To generate a diff of this commit:
cvs rdiff -u -r1.15 -r1.16 src/share/man/man4/fss.4
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
From: "Taylor R Campbell" <riastradh@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc:
Subject: PR/60383 CVS commit: src/usr.sbin/fssconfig
Date: Mon, 6 Jul 2026 16:52:32 +0000
Module Name: src
Committed By: riastradh
Date: Mon Jul 6 16:52:32 UTC 2026
Modified Files:
src/usr.sbin/fssconfig: fssconfig.8
Log Message:
fssconfig(8) Rework man page and give more practical examples.
Prompted by the persistent confusion on my part that led to:
PR bin/60383: fssconfig(8): distinguish between taking and loading a
snapshot
To generate a diff of this commit:
cvs rdiff -u -r1.12 -r1.13 src/usr.sbin/fssconfig/fssconfig.8
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
From: "Taylor R Campbell" <riastradh@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc:
Subject: PR/60383 CVS commit: src/usr.sbin/fssconfig
Date: Mon, 6 Jul 2026 16:53:56 +0000
Module Name: src
Committed By: riastradh
Date: Mon Jul 6 16:53:56 UTC 2026
Modified Files:
src/usr.sbin/fssconfig: fssconfig.8
Log Message:
fssconfig(8): Fix punctuation-o noticed milliseconds after commit.
Prompted by the persistent confusion on my part that led to:
PR bin/60383: fssconfig(8): distinguish between taking and loading a
snapshot
To generate a diff of this commit:
cvs rdiff -u -r1.13 -r1.14 src/usr.sbin/fssconfig/fssconfig.8
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
From: Taylor R Campbell <riastradh@NetBSD.org>
To: gnats-bugs@NetBSD.org, netbsd-bugs@NetBSD.org
Cc:
Subject: Re: bin/60383: fssconfig(8): distinguish between taking and loading a snapshot
Date: Sat, 18 Jul 2026 20:30:28 +0000
Would also be nice if creating and mounting a snapshot didn't require
specifying an fssN device, just like dumping a snapshot with dump(8)
doesn't require that.
For example, perhaps the interface could look something like:
- Take a snapshot without mounting it:
# snapfs /home /home/.snap/20260718
- Mount a snapshot:
# mount -t snapshot /home/.snap/20260718 /mnt
Under the hood, it might be nice if /dev/fss were a cloning device so
programs could just open("/dev/fss") without having to allocate an
fssN unit themselves.
From: Robert Elz <kre@munnari.OZ.AU>
To: Taylor R Campbell <riastradh@NetBSD.org>
Cc: gnats-bugs@NetBSD.org, netbsd-bugs@NetBSD.org
Subject: Re: bin/60383: fssconfig(8): distinguish between taking and loading a snapshot
Date: Sun, 19 Jul 2026 19:08:33 +0700
This is a multipart MIME message.
--==_Exmh_1784462650_178700
Content-Type: text/plain; charset=us-ascii
Date: Sat, 18 Jul 2026 20:30:28 +0000
From: Taylor R Campbell <riastradh@NetBSD.org>
Message-ID: <20260718203030.422B284DA5@mail.netbsd.org>
| - Mount a snapshot:
| # mount -t snapshot /home/.snap/20260718 /mnt
If you're meaning to mount an existing snapshot that way, then fine,
just needs a mount_snapshot command to make it work I expect. But
if you expect that to create the snapshot, and mount it, the same way
that dump -x creates the snapshot and dumps it, it would need more or
perhaps just different, information than that - in what you give there
there's no information about what filesystem to snapshot.
You can't assume it is /home as there is no requirement the snapshot
backing file is on the same filesystem as is being snapshot (snapshotted?)
What could be done, and would be more akin to what dump does is
mount -t snapshot /home /mnt
which would make a snapshot of /home in some unnamed file on its
filesystem, and mount that on /mnt - destroying the snapshot when
/mnt is umounted, just as dump destroys its when the backup has
completed.
I kind of agree on making fss into a cloner - the only issue is that
this one (like cgd and raid etc) is one where the user (or script)
needs to know what it is getting, because it needs to be able to use
the same one again later, most users of cloning devices don't care
which minor dev is assigned to them, whatever it is just gets used,
and closed.
I have a script (which I will attach below) that I find useful when
dealing with all these pseudo-disk type devices (vnd, cgd, ...) which
finds the first free one, and prints its name - it isn't race proof,
two instances of it run at once will return the same name, but for most
normal uses it works just fine. Usage is just something like "next_avail ffs"
and it will output fss0 (or fss3 or whatever is the first free).
kre
ps: I don't expect the attachment will survive into gnats, and perhaps
not even to netbsd-bugs, if anyone, if anyone else wants a copy, let me
know, I will either e-mail them, or make it available on munnari.oz.au
for anon ftp (no http servers there).
--==_Exmh_1784462650_178700
Content-Type: application/octet-stream ; name="next_avail"
Content-Description: next_avail
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment; filename="next_avail"
#! /bin/sh
# Usage: next_avail cloner-type-disk
# eg: next_avail vnd
# (or cgd or raid ...)
usage()
{
printf >&2 'Usage: %s xxx ...\n' "${0##*/}"
if [ -n "$1" ]
then
printf >&2 "$@"
else
printf >&2 ' where xxx is a disk-type driver name\n'
fi
exit 2
}
case "$#" in
0) usage;;
esac
E=3D
for A
do
case "${A}" in
(*[0-9]) E=3D"${E} ${A}";;
esac
done
if [ -n "${E}" ]
then
usage ' Do not include unit numbers:%s\n' "${E}"
fi
# Note that while this script works for any disk type device
# it is only useful for those that can be created on demand by
# some config command ... "next_avail wd" might reveal that wd3
# is the next, indicating that wd0 wd1 and wd2 are all in use,
# but there is nothing much that can be done about that, should
# a new wd arrive (hot plugged) the kernel will simply assign the
# id at that time, there is nothing another script (or a human)
# using this script can do to influence that.
# Any specific units of devices that are never to be made available
# via this script, should be listed here. These are typically ones
# known in fstab, or some other config file, and so should not be
# simply usurped for casual use (there is no requirement that they
# actually be in use at any particular time).
RESERVED=3D'cgd0 ccd0'
# The script (temporarily, just while executing) appends assigned
# units to the RESERVED list, so if request asks for 'raid raid' (etc)
# 2 different (currently free) raid unit numbers will be returned.
next_avail ()
{
local dev=3D"$1"
local N=3D$(( ${#dev} + 1 ))
local unit units
sysctl -n kern.drivers |
tr , '\012' |
tr -d '][' | =
grep " ${dev}\$" >/dev/null 2>&1 || {
printf >&2 'No %s driver in booted kernel\n' "${dev}"
printf \\n
return 1
}
# Discover which units are currently known to the kernel
# (ie: in use already). To those we add any reserved
# units that we are to assume are (or might be) in use,
# whether they actually are or not (ie: never asign).
units=3D$(
{
sysctl -n hw.disknames
printf '%s\n' "${RESERVED}"
} |
tr ' ' '\012' |
grep '^'"${dev}"'[0-9]' |
sort -u -n -k "1.$N" )
test -z "${units}" && {
# Currently, ${dev} is not in hw.disknames, so
# no units are in use. That means that as long
# as the entry for ${dev}0 is in /dev, that one
# is free, and obviously is the first, nothing
# more to do, we found it.
test -e "/dev/${dev}0" ||
test -e "/dev/${dev}0a" || {
printf >&2 "No %s's available!\\n" "${dev}"
printf \\n
return 1
}
RESERVED=3D"${RESERVED} ${dev}0"
printf '%s\n' "${dev}0"
return
}
# Now fine the lowest free unit number.
# Note we just need to scan the list once. units is sorted,
# and contains those which are in use, 0 1 2 4 5 7
# N runs 0 1 2 3 4 ... as long as the two match, the unit
# is in use, onto the next, when N and the unit are different,
# then dev$N is not currently in use, which is all we need.
N=3D0
for unit in ${units}
do
if [ "${unit}" !=3D "${dev}${N}" ]
then
break
fi
N=3D$(( N + 1 ))
done
# If the first one not in use we found has no /dev
# entry, then we failed, no available ${dev} is free.
test -e "/dev/${dev}${N}" ||
test -e /dev/"${dev}${N}a" || {
printf >&2 "All %s's in use\\n" "${dev}"
printf \\n
return 1
}
# Success!
RESERVED=3D"${RESERVED} ${dev}${N}"
printf '%s\n' "${dev}${N}"
}
X=3D0
for A
do
next_avail "${A}"
: $(( X |=3D $? ))
done
exit $X
--==_Exmh_1784462650_178700--
From: Taylor R Campbell <riastradh@NetBSD.org>
To: Robert Elz <kre@munnari.OZ.AU>
Cc: gnats-bugs@NetBSD.org, netbsd-bugs@NetBSD.org
Subject: Re: bin/60383: fssconfig(8): distinguish between taking and loading a snapshot
Date: Sun, 19 Jul 2026 12:25:09 +0000
> Date: Sun, 19 Jul 2026 19:08:33 +0700
> From: Robert Elz <kre@munnari.OZ.AU>
>
> Date: Sat, 18 Jul 2026 20:30:28 +0000
> From: Taylor R Campbell <riastradh@NetBSD.org>
> Message-ID: <20260718203030.422B284DA5@mail.netbsd.org>
>
> | - Mount a snapshot:
> | # mount -t snapshot /home/.snap/20260718 /mnt
>
> If you're meaning to mount an existing snapshot that way, then fine,
> just needs a mount_snapshot command to make it work I expect.
Yes, that is exactly what I meant, which would make sense in the
context of the first part I suggested:
- Take a snapshot without mounting it:
# snapfs /home /home/.snap/20260718
> What could be done, and would be more akin to what dump does is
>
> mount -t snapshot /home /mnt
>
> which would make a snapshot of /home in some unnamed file on its
> filesystem, and mount that on /mnt - destroying the snapshot when
> /mnt is umounted, just as dump destroys its when the backup has
> completed.
Yes, that would also be nice. If /home is not ffs, it would need a
temporary place for the storage to go, something like:
mount -t snapshot -o snapstore=/var/tmp /home /mnt
From: Robert Elz <kre@munnari.OZ.AU>
To: Taylor R Campbell <riastradh@NetBSD.org>
Cc: gnats-bugs@NetBSD.org, netbsd-bugs@NetBSD.org
Subject: Re: bin/60383: fssconfig(8): distinguish between taking and loading a snapshot
Date: Wed, 22 Jul 2026 14:16:06 +0700
Date: Sun, 19 Jul 2026 12:25:09 +0000
From: Taylor R Campbell <riastradh@NetBSD.org>
Message-ID: <20260719122511.54CC984D41@mail.netbsd.org>
| Yes, that is exactly what I meant, which would make sense in the
| context of the first part I suggested:
|
| - Take a snapshot without mounting it:
|
| # snapfs /home /home/.snap/20260718
Except it didn't, there wasn't enough explanation, it might just
have meant first "this is how one simply makes a snapshot" (that one
was clear enough) and second, "this is what you do if you want to make
a snapshot and have it mounted".
If "Mount a snapshot" had been "Mount an existing snapshot" or words
to that effect, it would have been clearer. That's why I asked which
meaning you intended.
kre
From: Taylor R Campbell <riastradh@NetBSD.org>
To: gnats-bugs@NetBSD.org, netbsd-bugs@NetBSD.org
Cc: Robert Elz <kre@munnari.OZ.AU>
Subject: Re: bin/60383: fssconfig(8): distinguish between taking and loading a snapshot
Date: Sat, 25 Jul 2026 19:28:30 +0000
Another thing that would be nice: mount a snapshot -- or any file
system, really -- just for the duration of a command, so that you
could, e.g., easily write a cron job that rsyncs a snapshot without
having to teach rsync(1) (or tar(1) or tarsnap(1) or borg(1) or
whatever) how to create snapshots on NetBSD:
withsnapmount /fs /fs/.snap/snapname /mnt \
rsync -aH /mnt/. backuphost:/backups/$(hostname)/.
(How to distinguish taking a new snapshot from loading an existing
snapshot in this operation is left as an exercise for the reader's
imagination.)
Also, for comparison, here's the interface on FreeBSD:
1. Create a snapshot /fs/.snap/snapname of the file system /fs
(assuming that is, in fact, the mount point) using the
mksnap_ffs(8) command:
# mksnap_ffs /fs/.snap/snapname
2. Create a snapshot /fs/.snap/snapname of the file system /fs, using
the mount(8) command -- but this doesn't actually mount it,
apparently:
# mount -u -o snapshot /fs/.snap/snapname /fs
3. Given a snapshot that was previously created, mount it at /mnt:
# mdconfig -a -t vnode -o readonly -f /fs/.snap/snapname -u 4
# mount -r /dev/md4 /mnt
Except for mksnap_ffs(8), this strikes me as very confusing! I'm not
sure we want to copy it.
https://web.archive.org/web/20260722195637/https://docs.freebsd.org/en/book=
s/handbook/disks/#snapshots
https://web.archive.org/web/20251118192326/https://man.freebsd.org/cgi/man.=
cgi?query=3Dmksnap_ffs&sektion=3D8&format=3Dhtml
https://web.archive.org/web/20260220073336/https://man.freebsd.org/cgi/man.=
cgi?format=3Dhtml&query=3Dmount&sektion=3D8
(Contact us)
$NetBSD: query-full-pr,v 1.51 2026/08/10 02:28:17 riastradh Exp $
$NetBSD: gnats_config.sh,v 1.10 2026/05/13 22:00:09 riastradh Exp $
Copyright © 1994-2026
The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.