From owner-svn-src-all@freebsd.org Mon Apr 22 13:28:37 2019 Return-Path: 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 6B4F61599FCF; Mon, 22 Apr 2019 13:28:37 +0000 (UTC) (envelope-from kp@FreeBSD.org) Received: from smtp.freebsd.org (smtp.freebsd.org [IPv6:2610:1c1:1:606c::24b:4]) (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 "smtp.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 026EF8A7B3; Mon, 22 Apr 2019 13:28:37 +0000 (UTC) (envelope-from kp@FreeBSD.org) Received: from venus.codepro.be (venus.codepro.be [5.9.86.228]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "smtp.codepro.be", Issuer "Let's Encrypt Authority X3" (verified OK)) (Authenticated sender: kp) by smtp.freebsd.org (Postfix) with ESMTPSA id 98E81FAD7; Mon, 22 Apr 2019 13:28:36 +0000 (UTC) (envelope-from kp@FreeBSD.org) Received: from [137.50.17.195] (unknown [IPv6:2001:630:42:110:d1ea:c255:f4:4af0]) (Authenticated sender: kp) by venus.codepro.be (Postfix) with ESMTPSA id B112331010; Mon, 22 Apr 2019 15:28:34 +0200 (CEST) From: "Kristof Provost" To: "Enji Cooper" Cc: "Hans Petter Selasky" , src-committers , svn-src-all , svn-src-head , "FreeBSD CURRENT" Subject: Re: Panic with r346530 [Re: svn commit: r346530 - in head/sys: netinet netinet6] Date: Mon, 22 Apr 2019 14:28:31 +0100 X-Mailer: MailMate (2.0BETAr6135) 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> <8EAC0CFE-E22F-478F-813F-A07E68C0518D@gmail.com> MIME-Version: 1.0 X-Rspamd-Queue-Id: 026EF8A7B3 X-Spamd-Bar: ------ Authentication-Results: mx1.freebsd.org X-Spamd-Result: default: False [-6.95 / 15.00]; NEURAL_HAM_MEDIUM(-1.00)[-1.000,0]; NEURAL_HAM_SHORT(-0.95)[-0.954,0]; NEURAL_HAM_LONG(-1.00)[-1.000,0]; REPLY(-4.00)[] Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit X-Content-Filtered-By: Mailman/MimeDel 2.1.29 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" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 22 Apr 2019 13:28:37 -0000 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: 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 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" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-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 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