Date: Mon, 22 Apr 2019 14:28:31 +0100 From: "Kristof Provost" <kp@FreeBSD.org> To: "Enji Cooper" <yaneurabeya@gmail.com> Cc: "Hans Petter Selasky" <hps@selasky.org>, src-committers <src-committers@freebsd.org>, svn-src-all <svn-src-all@freebsd.org>, svn-src-head <svn-src-head@freebsd.org>, "FreeBSD CURRENT" <freebsd-current@freebsd.org> Subject: Re: Panic with r346530 [Re: svn commit: r346530 - in head/sys: netinet netinet6] Message-ID: <1342BBD2-EE0F-4457-8752-659EA7F01725@FreeBSD.org> In-Reply-To: <8EAC0CFE-E22F-478F-813F-A07E68C0518D@gmail.com> References: <201904220727.x3M7ROpR009729@repo.freebsd.org> <2F3D6B17-AF4F-4B0F-B20E-5EF41DE851F9@gmail.com> <87917500-0381-79d8-a34b-819848abed32@selasky.org> <f2567fc6-fd5b-67c9-a994-5a48d65d1278@selasky.org> <8EAC0CFE-E22F-478F-813F-A07E68C0518D@gmail.com>
next in thread | previous in thread | raw e-mail | index | archive | help
On 22 Apr 2019, at 12:25, Enji Cooper wrote:
> Either the sys/netinet/ or sys/netipsec/ tests triggered the panic.
> Not sure which right now.
>
That looks to be happening during a vnet jail teardown, so it’s likely
the sys/netipsec or sys/netpfil/pf tests.
I’ve done a quick test with the pf tests, and they provoke this panic:
panic: mtx_lock() of destroyed mutex @
/usr/src/sys/netinet/ip_reass.c:628
cpuid = 0
time = 1555939645
KDB: stack backtrace:
db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame
0xfffffe0091d68530
vpanic() at vpanic+0x19d/frame 0xfffffe0091d68580
panic() at panic+0x43/frame 0xfffffe0091d685e0
__mtx_lock_flags() at __mtx_lock_flags+0x12e/frame 0xfffffe0091d68630
ipreass_cleanup() at ipreass_cleanup+0x86/frame 0xfffffe0091d68670
if_detach_internal() at if_detach_internal+0x786/frame
0xfffffe0091d686f0
if_detach() at if_detach+0x3d/frame 0xfffffe0091d68710
lo_clone_destroy() at lo_clone_destroy+0x16/frame 0xfffffe0091d68730
if_clone_destroyif() at if_clone_destroyif+0x21f/frame
0xfffffe0091d68780
if_clone_detach() at if_clone_detach+0xb8/frame 0xfffffe0091d687b0
vnet_loif_uninit() at vnet_loif_uninit+0x26/frame 0xfffffe0091d687d0
vnet_destroy() at vnet_destroy+0x124/frame 0xfffffe0091d68800
prison_deref() at prison_deref+0x29d/frame 0xfffffe0091d68840
sys_jail_remove() at sys_jail_remove+0x28f/frame 0xfffffe0091d68890
amd64_syscall() at amd64_syscall+0x276/frame 0xfffffe0091d689b0
fast_syscall_common() at fast_syscall_common+0x101/frame
0xfffffe0091d689b0
--- syscall (508, FreeBSD ELF64, sys_jail_remove), rip = 0x80031e12a,
rsp = 0x7fffffffe848, rbp = 0x7fffffffe8d0 ---
KDB: enter: panic
[ thread pid 1223 tid 100501 ]
Stopped at kdb_enter+0x3b: movq $0,kdb_why
db>
To reproduce:
kldload pfsync
cd /usr/tests/sys/netpfil/pf
sudo kyua test
Regards,
Kristof
From owner-svn-src-all@freebsd.org Mon Apr 22 13:43:40 2019
Return-Path: <owner-svn-src-all@freebsd.org>
Delivered-To: svn-src-all@mailman.ysv.freebsd.org
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1])
by mailman.ysv.freebsd.org (Postfix) with ESMTP id 8703E159A5D6;
Mon, 22 Apr 2019 13:43:40 +0000 (UTC)
(envelope-from kevans@FreeBSD.org)
Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org
[IPv6:2610:1c1:1:606c::19:3])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
server-signature RSA-PSS (4096 bits)
client-signature RSA-PSS (4096 bits) client-digest SHA256)
(Client CN "mxrelay.nyi.freebsd.org",
Issuer "Let's Encrypt Authority X3" (verified OK))
by mx1.freebsd.org (Postfix) with ESMTPS id 29E2A8B2F0;
Mon, 22 Apr 2019 13:43:40 +0000 (UTC)
(envelope-from kevans@FreeBSD.org)
Received: from repo.freebsd.org (repo.freebsd.org
[IPv6:2610:1c1:1:6068::e6a:0])
(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
(Client did not present a certificate)
by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 05602DC10;
Mon, 22 Apr 2019 13:43:40 +0000 (UTC)
(envelope-from kevans@FreeBSD.org)
Received: from repo.freebsd.org ([127.0.1.37])
by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id x3MDhdTw018848;
Mon, 22 Apr 2019 13:43:39 GMT (envelope-from kevans@FreeBSD.org)
Received: (from kevans@localhost)
by repo.freebsd.org (8.15.2/8.15.2/Submit) id x3MDhdvd018842;
Mon, 22 Apr 2019 13:43:39 GMT (envelope-from kevans@FreeBSD.org)
Message-Id: <201904221343.x3MDhdvd018842@repo.freebsd.org>
X-Authentication-Warning: repo.freebsd.org: kevans set sender to
kevans@FreeBSD.org using -f
From: Kyle Evans <kevans@FreeBSD.org>
Date: Mon, 22 Apr 2019 13:43:39 +0000 (UTC)
To: src-committers@freebsd.org, svn-src-all@freebsd.org,
svn-src-head@freebsd.org
Subject: svn commit: r346545 - head/lib/libbe
X-SVN-Group: head
X-SVN-Commit-Author: kevans
X-SVN-Commit-Paths: head/lib/libbe
X-SVN-Commit-Revision: 346545
X-SVN-Commit-Repository: base
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
X-Rspamd-Queue-Id: 29E2A8B2F0
X-Spamd-Bar: --
Authentication-Results: mx1.freebsd.org
X-Spamd-Result: default: False [-2.94 / 15.00];
local_wl_from(0.00)[FreeBSD.org];
NEURAL_HAM_MEDIUM(-1.00)[-1.000,0];
NEURAL_HAM_SHORT(-0.94)[-0.943,0];
ASN(0.00)[asn:11403, ipnet:2610:1c1:1::/48, country:US];
NEURAL_HAM_LONG(-1.00)[-1.000,0]
X-BeenThere: svn-src-all@freebsd.org
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: "SVN commit messages for the entire src tree \(except for "
user" and " projects" \)" <svn-src-all.freebsd.org>
List-Unsubscribe: <https://lists.freebsd.org/mailman/options/svn-src-all>,
<mailto:svn-src-all-request@freebsd.org?subject=unsubscribe>
List-Archive: <http://lists.freebsd.org/pipermail/svn-src-all/>
List-Post: <mailto:svn-src-all@freebsd.org>
List-Help: <mailto:svn-src-all-request@freebsd.org?subject=help>
List-Subscribe: <https://lists.freebsd.org/mailman/listinfo/svn-src-all>,
<mailto:svn-src-all-request@freebsd.org?subject=subscribe>
X-List-Received-Date: Mon, 22 Apr 2019 13:43:40 -0000
Author: kevans
Date: Mon Apr 22 13:43:38 2019
New Revision: 346545
URL: https://svnweb.freebsd.org/changeset/base/346545
Log:
libbe(3): allow creation of arbitrary depth boot environments
libbe currently only provides an API to create a recursive boot environment,
without any formal support for intentionally limiting the depth. This
changeset adds an API, be_create_depth, that may be used to arbitrarily
restrict the depth of the new BE.
Submitted by: Rob Fairbanks <rob.fx907 gmail com>
MFC after: 1 week
Differential Revision: https://reviews.freebsd.org/D18564
Modified:
head/lib/libbe/be.c
head/lib/libbe/be.h
head/lib/libbe/be_impl.h
head/lib/libbe/libbe.3
Modified: head/lib/libbe/be.c
==============================================================================
--- head/lib/libbe/be.c Mon Apr 22 11:31:13 2019 (r346544)
+++ head/lib/libbe/be.c Mon Apr 22 13:43:38 2019 (r346545)
@@ -372,7 +372,6 @@ be_snapshot(libbe_handle_t *lbh, const char *source, c
sizeof(buf)) >= sizeof(buf))
return (set_error(lbh, BE_ERR_INVALIDNAME));
}
-
if ((err = zfs_snapshot(lbh->lzh, buf, recursive, NULL)) != 0) {
switch (err) {
case EZFS_INVALIDNAME:
@@ -446,43 +445,78 @@ be_deep_clone_prop(int prop, void *cb)
return (ZPROP_CONT);
}
+/*
+ * Return the corresponding boot environment path for a given
+ * dataset path, the constructed path is placed in 'result'.
+ *
+ * example: say our new boot environment name is 'bootenv' and
+ * the dataset path is 'zroot/ROOT/default/data/set'.
+ *
+ * result should produce: 'zroot/ROOT/bootenv/data/set'
+ */
static int
-be_deep_clone(zfs_handle_t *ds, void *data)
+be_get_path(struct libbe_deep_clone *ldc, const char *dspath, char *result, int result_size)
{
+ char *pos;
+ char *child_dataset;
+
+ /* match the root path for the boot environments */
+ pos = strstr(dspath, ldc->lbh->root);
+
+ /* no match, different pools? */
+ if (pos == NULL)
+ return (BE_ERR_BADPATH);
+
+ /* root path of the new boot environment */
+ snprintf(result, result_size, "%s/%s", ldc->lbh->root, ldc->bename);
+
+ /* gets us to the parent dataset, the +1 consumes a trailing slash */
+ pos += strlen(ldc->lbh->root) + 1;
+
+ /* skip the parent dataset */
+ if ((child_dataset = strchr(pos, '/')) != NULL)
+ strlcat(result, child_dataset, result_size);
+
+ return (BE_ERR_SUCCESS);
+}
+
+static int
+be_clone_cb(zfs_handle_t *ds, void *data)
+{
int err;
char be_path[BE_MAXPATHLEN];
char snap_path[BE_MAXPATHLEN];
const char *dspath;
- char *dsname;
zfs_handle_t *snap_hdl;
nvlist_t *props;
- struct libbe_deep_clone *isdc, sdc;
+ struct libbe_deep_clone *ldc;
struct libbe_dccb dccb;
- isdc = (struct libbe_deep_clone *)data;
+ ldc = (struct libbe_deep_clone *)data;
dspath = zfs_get_name(ds);
- if ((dsname = strrchr(dspath, '/')) == NULL)
- return (BE_ERR_UNKNOWN);
- dsname++;
- if (isdc->bename == NULL)
- snprintf(be_path, sizeof(be_path), "%s/%s", isdc->be_root, dsname);
- else
- snprintf(be_path, sizeof(be_path), "%s/%s", isdc->be_root, isdc->bename);
+ snprintf(snap_path, sizeof(snap_path), "%s@%s", dspath, ldc->snapname);
- snprintf(snap_path, sizeof(snap_path), "%s@%s", dspath, isdc->snapname);
+ /* construct the boot environment path from the dataset we're cloning */
+ if (be_get_path(ldc, dspath, be_path, sizeof(be_path)) != BE_ERR_SUCCESS)
+ return (set_error(ldc->lbh, BE_ERR_UNKNOWN));
- if (zfs_dataset_exists(isdc->lbh->lzh, be_path, ZFS_TYPE_DATASET))
- return (set_error(isdc->lbh, BE_ERR_EXISTS));
+ /* the dataset to be created (i.e. the boot environment) already exists */
+ if (zfs_dataset_exists(ldc->lbh->lzh, be_path, ZFS_TYPE_DATASET))
+ return (set_error(ldc->lbh, BE_ERR_EXISTS));
+ /* no snapshot found for this dataset, silently skip it */
+ if (!zfs_dataset_exists(ldc->lbh->lzh, snap_path, ZFS_TYPE_SNAPSHOT))
+ return (0);
+
if ((snap_hdl =
- zfs_open(isdc->lbh->lzh, snap_path, ZFS_TYPE_SNAPSHOT)) == NULL)
- return (set_error(isdc->lbh, BE_ERR_ZFSOPEN));
+ zfs_open(ldc->lbh->lzh, snap_path, ZFS_TYPE_SNAPSHOT)) == NULL)
+ return (set_error(ldc->lbh, BE_ERR_ZFSOPEN));
nvlist_alloc(&props, NV_UNIQUE_NAME, KM_SLEEP);
nvlist_add_string(props, "canmount", "noauto");
- dccb.lbh = isdc->lbh;
+ dccb.lbh = ldc->lbh;
dccb.zhp = ds;
dccb.props = props;
if (zprop_iter(be_deep_clone_prop, &dccb, B_FALSE, B_FALSE,
@@ -490,58 +524,55 @@ be_deep_clone(zfs_handle_t *ds, void *data)
return (-1);
if ((err = zfs_clone(snap_hdl, be_path, props)) != 0)
- err = BE_ERR_ZFSCLONE;
+ return (set_error(ldc->lbh, BE_ERR_ZFSCLONE));
nvlist_free(props);
zfs_close(snap_hdl);
- /* Failed to clone */
- if (err != BE_ERR_SUCCESS)
- return (set_error(isdc->lbh, err));
+ if (ldc->depth_limit == -1 || ldc->depth < ldc->depth_limit) {
+ ldc->depth++;
+ err = zfs_iter_filesystems(ds, be_clone_cb, ldc);
+ ldc->depth--;
+ }
- sdc.lbh = isdc->lbh;
- sdc.bename = NULL;
- sdc.snapname = isdc->snapname;
- sdc.be_root = (char *)&be_path;
-
- err = zfs_iter_filesystems(ds, be_deep_clone, &sdc);
-
- return (err);
+ return (set_error(ldc->lbh, err));
}
/*
- * Create the boot environment from pre-existing snapshot
- */
-int
-be_create_from_existing_snap(libbe_handle_t *lbh, const char *name,
- const char *snap)
+ * Create a boot environment with a given name from a given snapshot.
+ * Snapshots can be in the format 'zroot/ROOT/default@snapshot' or
+ * 'default@snapshot'. In the latter case, 'default@snapshot' will be prepended
+ * with the root path that libbe was initailized with.
+*/
+static int
+be_clone(libbe_handle_t *lbh, const char *bename, const char *snapshot, int depth)
{
int err;
- char be_path[BE_MAXPATHLEN];
char snap_path[BE_MAXPATHLEN];
- const char *bename;
char *parentname, *snapname;
zfs_handle_t *parent_hdl;
- struct libbe_deep_clone sdc;
+ struct libbe_deep_clone ldc;
- if ((err = be_validate_name(lbh, name)) != 0)
+ /* ensure the boot environment name is valid */
+ if ((err = be_validate_name(lbh, bename)) != 0)
return (set_error(lbh, err));
- if ((err = be_root_concat(lbh, snap, snap_path)) != 0)
+
+ /*
+ * prepend the boot environment root path if we're
+ * given a partial snapshot name.
+ */
+ if ((err = be_root_concat(lbh, snapshot, snap_path)) != 0)
return (set_error(lbh, err));
+
+ /* ensure the snapshot exists */
if ((err = be_validate_snap(lbh, snap_path)) != 0)
return (set_error(lbh, err));
- if ((err = be_root_concat(lbh, name, be_path)) != 0)
- return (set_error(lbh, err));
-
- if ((bename = strrchr(name, '/')) == NULL)
- bename = name;
- else
- bename++;
-
+ /* get a copy of the snapshot path so we can disect it */
if ((parentname = strdup(snap_path)) == NULL)
return (set_error(lbh, BE_ERR_UNKNOWN));
+ /* split dataset name from snapshot name */
snapname = strchr(parentname, '@');
if (snapname == NULL) {
free(parentname);
@@ -550,32 +581,56 @@ be_create_from_existing_snap(libbe_handle_t *lbh, cons
*snapname = '\0';
snapname++;
- sdc.lbh = lbh;
- sdc.bename = bename;
- sdc.snapname = snapname;
- sdc.be_root = lbh->root;
+ /* set-up the boot environment */
+ ldc.lbh = lbh;
+ ldc.bename = bename;
+ ldc.snapname = snapname;
+ ldc.depth = 0;
+ ldc.depth_limit = depth;
+ /* the boot environment will be cloned from this dataset */
parent_hdl = zfs_open(lbh->lzh, parentname, ZFS_TYPE_DATASET);
- err = be_deep_clone(parent_hdl, &sdc);
+ /* create the boot environment */
+ err = be_clone_cb(parent_hdl, &ldc);
+
free(parentname);
return (set_error(lbh, err));
}
+/*
+ * Create a boot environment from pre-existing snapshot, specifying a depth.
+ */
+int be_create_depth(libbe_handle_t *lbh, const char *bename,
+ const char *snap, int depth)
+{
+ return (be_clone(lbh, bename, snap, depth));
+}
/*
+ * Create the boot environment from pre-existing snapshot
+ */
+int
+be_create_from_existing_snap(libbe_handle_t *lbh, const char *bename,
+ const char *snap)
+{
+ return (be_clone(lbh, bename, snap, -1));
+}
+
+
+/*
* Create a boot environment from an existing boot environment
*/
int
-be_create_from_existing(libbe_handle_t *lbh, const char *name, const char *old)
+be_create_from_existing(libbe_handle_t *lbh, const char *bename, const char *old)
{
int err;
- char buf[BE_MAXPATHLEN];
+ char snap[BE_MAXPATHLEN];
- if ((err = be_snapshot(lbh, old, NULL, true, (char *)&buf)) != 0)
+ if ((err = be_snapshot(lbh, old, NULL, true, snap)) != 0)
return (set_error(lbh, err));
- err = be_create_from_existing_snap(lbh, name, (char *)buf);
+ err = be_clone(lbh, bename, snap, -1);
return (set_error(lbh, err));
}
Modified: head/lib/libbe/be.h
==============================================================================
--- head/lib/libbe/be.h Mon Apr 22 11:31:13 2019 (r346544)
+++ head/lib/libbe/be.h Mon Apr 22 13:43:38 2019 (r346545)
@@ -84,6 +84,7 @@ int be_activate(libbe_handle_t *, const char *, bool);
/* Bootenv creation functions */
int be_create(libbe_handle_t *, const char *);
+int be_create_depth(libbe_handle_t *, const char *, const char *, int);
int be_create_from_existing(libbe_handle_t *, const char *, const char *);
int be_create_from_existing_snap(libbe_handle_t *, const char *, const char *);
int be_snapshot(libbe_handle_t *, const char *, const char *, bool, char *);
Modified: head/lib/libbe/be_impl.h
==============================================================================
--- head/lib/libbe/be_impl.h Mon Apr 22 11:31:13 2019 (r346544)
+++ head/lib/libbe/be_impl.h Mon Apr 22 13:43:38 2019 (r346545)
@@ -50,7 +50,8 @@ struct libbe_deep_clone {
libbe_handle_t *lbh;
const char *bename;
const char *snapname;
- const char *be_root;
+ int depth;
+ int depth_limit;
};
struct libbe_dccb {
Modified: head/lib/libbe/libbe.3
==============================================================================
--- head/lib/libbe/libbe.3 Mon Apr 22 11:31:13 2019 (r346544)
+++ head/lib/libbe/libbe.3 Mon Apr 22 13:43:38 2019 (r346545)
@@ -28,7 +28,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd February 12, 2019
+.Dd April 22, 2019
.Dt LIBBE 3
.Os
.Sh NAME
@@ -63,6 +63,9 @@
.Fn be_create "libbe_handle_t *hdl" "const char *be_name"
.Pp
.Ft int
+.Fn be_create_depth "libbe_handle_t *hdl" "const char *be_name" "const char *snap" "int depth"
+.Pp
+.Ft int
.Fn be_create_from_existing "libbe_handle_t *hdl" "const char *be_name" "const char *be_origin"
.Pp
.Ft int
@@ -213,19 +216,29 @@ function returns the boot environment root path.
The
.Fn be_create
function creates a boot environment with the given name.
-It will be created from a snapshot of the currently booted boot environment.
+The new boot environment will be created from a recursive snapshot of the
+currently booted boot environment.
.Pp
The
+.Fn be_create_depth
+function creates a boot environment with the given name from an existing
+snapshot.
+The depth parameter specifies the depth of recursion that will be cloned from
+the existing snapshot.
+A depth of '0' is no recursion and '-1' is unlimited (i.e., a recursive boot
+environment).
+.Pp
+The
.Fn be_create_from_existing
function creates a boot environment with the given name from the name of an
existing boot environment.
-A snapshot will be made of the base boot environment, and the new boot
-environment will be created from that.
+A recursive snapshot will be made of the origin boot environment, and the new
+boot environment will be created from that.
.Pp
The
.Fn be_create_from_existing_snap
-function creates a boot environment with the given name from an existing
-snapshot.
+function creates a recursive boot environment with the given name from an
+existing snapshot.
.Pp
The
.Fn be_rename
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1342BBD2-EE0F-4457-8752-659EA7F01725>
