Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 30 May 2022 16:33:47 -0600
From:      Warner Losh <imp@bsdimp.com>
To:        Cy Schubert <Cy.Schubert@cschubert.com>
Cc:        Kirk McKusick <mckusick@freebsd.org>, src-committers <src-committers@freebsd.org>,  "<dev-commits-src-all@freebsd.org>" <dev-commits-src-all@freebsd.org>, dev-commits-src-main@freebsd.org,  David Wolfskill <david@catwhisker.org>, Toomas Soome <tsoome@me.com>
Subject:   Re: git: 076002f24d35 - main - Do comprehensive UFS/FFS superblock integrity checks when reading a superblock.
Message-ID:  <CANCZdfoqpDO9-APZytimd9TpPGsnaj0%2BwJBfdxv%2Bo2NnOX5ZUQ@mail.gmail.com>
In-Reply-To: <20220530222402.E22C7114@slippy.cwsent.com>
References:  <202205271922.24RJMOJ2039923@gitrepo.freebsd.org> <20220530215552.EE5432C@slippy.cwsent.com> <CANCZdfpovXadsxcS_YC2-NpJJX8S62YTfNTSfE9VHqoE6KsJPA@mail.gmail.com> <20220530222402.E22C7114@slippy.cwsent.com>

next in thread | previous in thread | raw e-mail | index | archive | help
--0000000000008603c305e04240eb
Content-Type: text/plain; charset="UTF-8"

On Mon, May 30, 2022 at 4:24 PM Cy Schubert <Cy.Schubert@cschubert.com>
wrote:

> Upgrading boot blocks didn't help either.
>
> It only happened on one of four machines. Likely because the other three
> are AMD on Asus MBs while the problem machine is an Acer laptop running
> Intel.
>

David Wolfskill reported the same: some are affected, others not.
It's unclear why, exactly, but all the other details you gave track
with the troubleshooting tsoome and I have been doing with him.

The issue is inside of loader.efi or /boot/loader, not in the earlier
boot blocks.

Warner


>
> --
> Cheers,
> Cy Schubert <Cy.Schubert@komquats.com> or <Cy.Schubert@cschubert.com>
> FreeBSD UNIX:  <cy@FreeBSD.org>   Web:  http://www.FreeBSD.org
> NTP:           <cy@nwtime.org>    Web:  https://nwtime.org
>
>                         e**(i*pi)+1=0
>
>
> In message
> <CANCZdfpovXadsxcS_YC2-NpJJX8S62YTfNTSfE9VHqoE6KsJPA@mail.gmail.c
> om>
> , Warner Losh writes:
> > --00000000000059353005e041e22c
> > Content-Type: text/plain; charset="UTF-8"
> >
> > David Woofskill also reported this...
> >
> > Warner
> >
> > On Mon, May 30, 2022, 3:56 PM Cy Schubert <Cy.Schubert@cschubert.com>
> wrote:
> >
> > > In message <202205271922.24RJMOJ2039923@gitrepo.freebsd.org>, Kirk
> > > McKusick
> > > wri
> > > tes:
> > > > The branch main has been updated by mckusick:
> > > >
> > > > URL:
> > >
> https://cgit.FreeBSD.org/src/commit/?id=076002f24d35962f0d21f44bfddd34ee
> > > > 4d7f015d
> > > >
> > > > commit 076002f24d35962f0d21f44bfddd34ee4d7f015d
> > > > Author:     Kirk McKusick <mckusick@FreeBSD.org>
> > > > AuthorDate: 2022-05-27 19:21:11 +0000
> > > > Commit:     Kirk McKusick <mckusick@FreeBSD.org>
> > > > CommitDate: 2022-05-27 19:22:07 +0000
> > > >
> > > >     Do comprehensive UFS/FFS superblock integrity checks when
> reading a
> > > super
> > > > block.
> > > >
> > > >     Historically only minimal checks were made of a superblock when
> it
> > > >     was read in as it was assumed that fsck would have been run to
> > > >     correct any errors before attempting to use the filesystem.
> Recently
> > > >     several bug reports have been submitted reporting kernel panics
> > > >     that can be triggered by deliberately corrupting filesystem
> > > superblocks,
> > > >     see Bug 263979 - [meta] UFS / FFS / GEOM crash (panic) tracking
> > > >     which is tracking the reported corruption bugs.
> > > >
> > > >     This change upgrades the checks that are performed. These
> additional
> > > >     checks should prevent panics from a corrupted superblock.
> Although
> > > >     it appears in only one place, the new code will apply to the
> kernel
> > > >     modules and (through libufs) user applications that read in
> > > superblocks.
> > > >
> > > >     Reported by:  Robert Morris and Neeraj
> > > >     Reviewed by:  kib
> > > >     Tested by:    Peter Holm
> > > >     PR:           263979
> > > >     MFC after:    1 month
> > > >     Differential Revision: https://reviews.freebsd.org/D35219
> > > > ---
> > > >  sys/ufs/ffs/ffs_subr.c | 163
> > > +++++++++++++++++++++++++++++++++++++++++++----
> > > > --
> > > >  1 file changed, 146 insertions(+), 17 deletions(-)
> > > >
> > > > diff --git a/sys/ufs/ffs/ffs_subr.c b/sys/ufs/ffs/ffs_subr.c
> > > > index 01e9f45e1205..28c2fee1cb37 100644
> > > > --- a/sys/ufs/ffs/ffs_subr.c
> > > > +++ b/sys/ufs/ffs/ffs_subr.c
> > > > @@ -35,6 +35,7 @@
> > > >  __FBSDID("$FreeBSD$");
> > > >
> > > >  #include <sys/param.h>
> > > > +#include <sys/limits.h>
> > > >
> > > >  #ifndef _KERNEL
> > > >  #include <stdio.h>
> > > > @@ -50,6 +51,7 @@ uint32_t ffs_calc_sbhash(struct fs *);
> > > >  struct malloc_type;
> > > >  #define UFS_MALLOC(size, type, flags) malloc(size)
> > > >  #define UFS_FREE(ptr, type) free(ptr)
> > > > +#define maxphys MAXPHYS
> > > >
> > > >  #else /* _KERNEL */
> > > >  #include <sys/systm.h>
> > > > @@ -125,6 +127,7 @@ ffs_update_dinode_ckhash(struct fs *fs, struct
> > > ufs2_dinod
> > > > e *dip)
> > > >  static off_t sblock_try[] = SBLOCKSEARCH;
> > > >  static int readsuper(void *, struct fs **, off_t, int, int,
> > > >       int (*)(void *, off_t, void **, int));
> > > > +static int validate_sblock(struct fs *, int);
> > > >
> > > >  /*
> > > >   * Read a superblock from the devfd device.
> > > > @@ -141,7 +144,7 @@ static int readsuper(void *, struct fs **, off_t,
> > > int, in
> > > > t,
> > > >   *     EIO: non-existent or truncated superblock.
> > > >   *     EIO: error reading summary information.
> > > >   *     ENOENT: no usable known superblock found.
> > > > - *     ENOSPC: failed to allocate space for the superblock.
> > > > + *     ENOMEM: failed to allocate space for the superblock.
> > > >   *     EINVAL: The previous newfs operation on this volume did not
> > > complete.
> > > >   *         The administrator must complete newfs before using this
> > > volume.
> > > >   */
> > > > @@ -152,7 +155,8 @@ ffs_sbget(void *devfd, struct fs **fsp, off_t
> > > altsblock,
> > > >  {
> > > >       struct fs *fs;
> > > >       struct fs_summary_info *fs_si;
> > > > -     int i, error, size, blks;
> > > > +     int i, error;
> > > > +     uint64_t size, blks;
> > > >       uint8_t *space;
> > > >       int32_t *lp;
> > > >       char *buf;
> > > > @@ -190,17 +194,16 @@ ffs_sbget(void *devfd, struct fs **fsp, off_t
> > > altsblock
> > > > ,
> > > >       if (fs->fs_contigsumsize > 0)
> > > >               size += fs->fs_ncg * sizeof(int32_t);
> > > >       size += fs->fs_ncg * sizeof(u_int8_t);
> > > > -     /* When running in libufs or libsa, UFS_MALLOC may fail */
> > > > -     if ((fs_si = UFS_MALLOC(sizeof(*fs_si), filltype, M_WAITOK)) ==
> > > NULL) {
> > > > +     if ((fs_si = UFS_MALLOC(sizeof(*fs_si), filltype, M_NOWAIT)) ==
> > > NULL) {
> > > >               UFS_FREE(fs, filltype);
> > > > -             return (ENOSPC);
> > > > +             return (ENOMEM);
> > > >       }
> > > >       bzero(fs_si, sizeof(*fs_si));
> > > >       fs->fs_si = fs_si;
> > > > -     if ((space = UFS_MALLOC(size, filltype, M_WAITOK)) == NULL) {
> > > > +     if ((space = UFS_MALLOC(size, filltype, M_NOWAIT)) == NULL) {
> > > >               UFS_FREE(fs->fs_si, filltype);
> > > >               UFS_FREE(fs, filltype);
> > > > -             return (ENOSPC);
> > > > +             return (ENOMEM);
> > > >       }
> > > >       fs->fs_csp = (struct csum *)space;
> > > >       for (i = 0; i < blks; i += fs->fs_frag) {
> > > > @@ -253,16 +256,8 @@ readsuper(void *devfd, struct fs **fsp, off_t
> > > sblockloc,
> > > >  int isaltsblk,
> > > >       fs = *fsp;
> > > >       if (fs->fs_magic == FS_BAD_MAGIC)
> > > >               return (EINVAL);
> > > > -     if (!(((fs->fs_magic == FS_UFS1_MAGIC && (isaltsblk ||
> > > > -           sblockloc <= SBLOCK_UFS1)) ||
> > > > -          (fs->fs_magic == FS_UFS2_MAGIC && (isaltsblk ||
> > > > -           sblockloc == fs->fs_sblockloc))) &&
> > > > -         fs->fs_ncg >= 1 &&
> > > > -         fs->fs_bsize >= MINBSIZE &&
> > > > -         fs->fs_bsize <= MAXBSIZE &&
> > > > -         fs->fs_bsize >= roundup(sizeof(struct fs), DEV_BSIZE) &&
> > > > -         fs->fs_sbsize <= SBLOCKSIZE))
> > > > -             return (ENOENT);
> > > > +     if ((error = validate_sblock(fs, isaltsblk)) != 0)
> > > > +             return (error);
> > > >       /*
> > > >        * If the filesystem has been run on a kernel without
> > > >        * metadata check hashes, disable them.
> > > > @@ -310,6 +305,140 @@ readsuper(void *devfd, struct fs **fsp, off_t
> > > sblockloc
> > > > , int isaltsblk,
> > > >       return (0);
> > > >  }
> > > >
> > > > +/*
> > > > + * Verify the filesystem values.
> > > > + */
> > > > +#define ILOG2(num) (fls(num) - 1)
> > > > +
> > > > +static int
> > > > +validate_sblock(struct fs *fs, int isaltsblk)
> > > > +{
> > > > +     int i, sectorsize;
> > > > +     u_int64_t maxfilesize, minfpg, sizepb;
> > > > +
> > > > +     sectorsize = dbtob(1);
> > > > +     if (fs->fs_magic == FS_UFS2_MAGIC) {
> > > > +             if ((!isaltsblk && (fs->fs_sblockloc != SBLOCK_UFS2 ||
> > > > +                 fs->fs_sblockactualloc != SBLOCK_UFS2)) ||
> > > > +                 fs->fs_maxsymlinklen != ((UFS_NDADDR + UFS_NIADDR)
> *
> > > > +                     sizeof(ufs2_daddr_t)) ||
> > > > +                 fs->fs_nindir != fs->fs_bsize /
> sizeof(ufs2_daddr_t) ||
> > > > +                 fs->fs_inopb != fs->fs_bsize / sizeof(struct
> > > ufs2_dinode))
> > > > +                     return (ENOENT);
> > > > +     } else if (fs->fs_magic == FS_UFS1_MAGIC) {
> > > > +             if ((!isaltsblk && (fs->fs_sblockloc > SBLOCK_UFS1 ||
> > > > +                 fs->fs_sblockactualloc != SBLOCK_UFS1)) ||
> > > > +                 fs->fs_nindir != fs->fs_bsize /
> sizeof(ufs1_daddr_t) ||
> > > > +                 fs->fs_inopb != fs->fs_bsize / sizeof(struct
> > > ufs1_dinode) |
> > > > |
> > > > +                 fs->fs_maxsymlinklen != ((UFS_NDADDR + UFS_NIADDR)
> *
> > > > +                     sizeof(ufs1_daddr_t)) ||
> > > > +                 fs->fs_old_inodefmt != FS_44INODEFMT ||
> > > > +                 fs->fs_old_cgoffset != 0 ||
> > > > +                 fs->fs_old_cgmask != 0xffffffff ||
> > > > +                 fs->fs_old_size != fs->fs_size ||
> > > > +                 fs->fs_old_rotdelay != 0 ||
> > > > +                 fs->fs_old_rps != 60 ||
> > > > +                 fs->fs_old_nspf != fs->fs_fsize / sectorsize ||
> > > > +                 fs->fs_old_cpg != 1 ||
> > > > +                 fs->fs_old_interleave != 1 ||
> > > > +                 fs->fs_old_trackskew != 0 ||
> > > > +                 fs->fs_old_cpc != 0 ||
> > > > +                 fs->fs_old_postblformat != 1 ||
> > > > +                 fs->fs_old_nrpos != 1 ||
> > > > +                 fs->fs_old_spc != fs->fs_fpg * fs->fs_old_nspf ||
> > > > +                 fs->fs_old_nsect != fs->fs_old_spc ||
> > > > +                 fs->fs_old_npsect != fs->fs_old_spc ||
> > > > +                 fs->fs_old_dsize != fs->fs_dsize ||
> > > > +                 fs->fs_old_ncyl != fs->fs_ncg)
> > > > +                     return (ENOENT);
> > > > +     } else {
> > > > +             return (ENOENT);
> > > > +     }
> > > > +     if (fs->fs_bsize < MINBSIZE || fs->fs_bsize > MAXBSIZE ||
> > > > +         fs->fs_bsize < roundup(sizeof(struct fs), DEV_BSIZE) ||
> > > > +         fs->fs_sbsize > SBLOCKSIZE || fs->fs_sbsize < fs->fs_fsize
> ||
> > > > +         !powerof2(fs->fs_bsize))
> > > > +             return (ENOENT);
> > > > +     if (fs->fs_fsize < sectorsize || fs->fs_fsize > fs->fs_bsize ||
> > > > +         fs->fs_fsize * MAXFRAG < fs->fs_bsize ||
> > > !powerof2(fs->fs_fsize))
> > > > +             return (ENOENT);
> > > > +     if (fs->fs_maxbsize < fs->fs_bsize ||
> !powerof2(fs->fs_maxbsize) ||
> > > > +         fs->fs_maxbsize > FS_MAXCONTIG * fs->fs_bsize)
> > > > +             return (ENOENT);
> > > > +     if (fs->fs_bmask != ~(fs->fs_bsize - 1) ||
> > > > +         fs->fs_fmask != ~(fs->fs_fsize - 1) ||
> > > > +         fs->fs_qbmask != ~fs->fs_bmask ||
> > > > +         fs->fs_qfmask != ~fs->fs_fmask ||
> > > > +         fs->fs_bshift != ILOG2(fs->fs_bsize) ||
> > > > +         fs->fs_fshift != ILOG2(fs->fs_fsize) ||
> > > > +         fs->fs_frag != numfrags(fs, fs->fs_bsize) ||
> > > > +         fs->fs_fragshift != ILOG2(fs->fs_frag) ||
> > > > +         fs->fs_frag > MAXFRAG ||
> > > > +         fs->fs_fsbtodb != ILOG2(fs->fs_fsize / sectorsize))
> > > > +             return (ENOENT);
> > > > +     if (fs->fs_sblkno !=
> > > > +             roundup(howmany(fs->fs_sblockloc + SBLOCKSIZE,
> > > fs->fs_fsize),
> > > > +                 fs->fs_frag) ||
> > > > +         fs->fs_cblkno != fs->fs_sblkno +
> > > > +             roundup(howmany(SBLOCKSIZE, fs->fs_fsize),
> fs->fs_frag) ||
> > > > +         fs->fs_iblkno != fs->fs_cblkno + fs->fs_frag ||
> > > > +         fs->fs_dblkno != fs->fs_iblkno + fs->fs_ipg / INOPF(fs) ||
> > > > +         fs->fs_cgsize != fragroundup(fs, CGSIZE(fs)))
> > > > +             return (ENOENT);
> > > > +     if (fs->fs_csaddr != cgdmin(fs, 0) ||
> > > > +         fs->fs_cssize !=
> > > > +             fragroundup(fs, fs->fs_ncg * sizeof(struct csum)) ||
> > > > +         fs->fs_dsize != fs->fs_size - fs->fs_sblkno -
> > > > +             fs->fs_ncg * (fs->fs_dblkno - fs->fs_sblkno) -
> > > > +             howmany(fs->fs_cssize, fs->fs_fsize) ||
> > > > +         fs->fs_metaspace < 0 || fs->fs_metaspace > fs->fs_fpg / 2
> ||
> > > > +         fs->fs_minfree > 99)
> > > > +             return (ENOENT);
> > > > +     maxfilesize = fs->fs_bsize * UFS_NDADDR - 1;
> > > > +     for (sizepb = fs->fs_bsize, i = 0; i < UFS_NIADDR; i++) {
> > > > +             sizepb *= NINDIR(fs);
> > > > +             maxfilesize += sizepb;
> > > > +     }
> > > > +     if (fs->fs_maxfilesize != maxfilesize)
> > > > +             return (ENOENT);
> > > > +     /*
> > > > +      * These values have a tight interaction with each other that
> > > > +      * makes it hard to tightly bound them. So we can only check
> > > > +      * that they are within a broader possible range.
> > > > +      *
> > > > +      * Calculate minfpg, the minimum number of fragments that can
> be
> > > > +      * in a cylinder group. The value 12289 is calculated in
> newfs(8)
> > > > +      * when creating the smallest block size UFS version 1
> filesystem
> > > > +      * (4096 block size) with no fragments (4096 fragment size).
> That
> > > > +      * number may be depressed even further for very small
> filesystems
> > > > +      * since newfs(8) strives to have at least four cylinder
> groups.
> > > > +      */
> > > > +     minfpg = MIN(12289, fs->fs_size / 4);
> > > > +     if (fs->fs_ncg < 1 || fs->fs_ncg > (fs->fs_size / minfpg) + 1
> ||
> > > > +         fs->fs_fpg < minfpg || fs->fs_fpg > fs->fs_size ||
> > > > +         fs->fs_ipg * fs->fs_ncg > (((int64_t)(1)) << 32) -
> INOPB(fs) ||
> > > > +         fs->fs_ipg > fs->fs_fpg || fs->fs_size < 8 * fs->fs_frag)
> > > > +             return (ENOENT);
> > > > +     if (fs->fs_size <= (fs->fs_ncg - 1) * fs->fs_fpg ||
> > > > +         fs->fs_size > fs->fs_ncg * fs->fs_fpg)
> > > > +             return (ENOENT);
> > > > +     /*
> > > > +      * Maxcontig sets the default for the maximum number of blocks
> > > > +      * that may be allocated sequentially. With file system
> clustering
> > > > +      * it is possible to allocate contiguous blocks up to the
> maximum
> > > > +      * transfer size permitted by the controller or buffering.
> > > > +      */
> > > > +     if (fs->fs_maxcontig < 1 ||
> > > > +         fs->fs_maxcontig > MAX(1, maxphys / fs->fs_bsize))
> > > > +             return (ENOENT);
> > > > +     if (fs->fs_maxcontig < 0 ||
> > > > +         (fs->fs_maxcontig == 0 && fs->fs_contigsumsize != 0) ||
> > > > +         (fs->fs_maxcontig > 1 &&
> > > > +         fs->fs_contigsumsize != MIN(fs->fs_maxcontig,
> FS_MAXCONTIG)))
> > > > +             return (ENOENT);
> > > > +     return (0);
> > > > +}
> > > > +
> > > >  /*
> > > >   * Write a superblock to the devfd device from the memory pointed
> to by
> > > fs.
> > > >   * Write out the superblock summary information if it is present.
> > > >
> > >
> > > Hi Kirk,
> > >
> > > This patch broke loader on one of my machines.
> > >
> > > I get the following error:
> > >
> > > LUA ERROR: Cannot open /boot/lua/loader.lua: no such file or directory"
> > > can't load kernel
> > >
> > > Of course booting from my rescue worked.
> > >
> > > Copying loader* from /boot on the rescue disk to /boot works around the
> > > problem.
> > >
> > > Backing up, newfs, and restoring the root filesystem, using my rescue
> disk
> > > also didn't work around the problem.
> > >
> > > Reverting this patch provided permanent relief.
> > >
> > > Loader could read the filesystems on my rescue disk, which had
> blocksizes
> > > of 16K but not those on my boot disk which had blocksizes of 32K.
> > >
> > > My three machines downstairs, all AMD gear with UFS blocksize of 32K,
> had
> > > no no problems with this whereas my laptop, an Intel, had the problem.
> > >
> > > To repeat, a newly created filesystem restored from backup using my
> rescue
> > > disk didn't resolve the problem.
> > >
> > >
> > > --
> > > Cheers,
> > > Cy Schubert <Cy.Schubert@komquats.com> or <Cy.Schubert@cschubert.com>
> > > FreeBSD UNIX:  <cy@FreeBSD.org>   Web:  http://www.FreeBSD.org
> > > NTP:           <cy@nwtime.org>    Web:  https://nwtime.org
> > >
> > >                         e**(i*pi)+1=0
> > >
> > >
> > >
>
>
>

--0000000000008603c305e04240eb
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div dir=3D"ltr"><br></div><br><div class=3D"gmail_quote">=
<div dir=3D"ltr" class=3D"gmail_attr">On Mon, May 30, 2022 at 4:24 PM Cy Sc=
hubert &lt;<a href=3D"mailto:Cy.Schubert@cschubert.com">Cy.Schubert@cschube=
rt.com</a>&gt; wrote:<br></div><blockquote class=3D"gmail_quote" style=3D"m=
argin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left=
:1ex">Upgrading boot blocks didn&#39;t help either.<br>
<br>
It only happened on one of four machines. Likely because the other three <b=
r>
are AMD on Asus MBs while the problem machine is an Acer laptop running <br=
>
Intel.<br></blockquote><div><br></div><div>David Wolfskill reported the sam=
e: some are affected, others not.</div><div>It&#39;s unclear why, exactly, =
but all the other details you gave track</div><div>with the troubleshooting=
 tsoome and I have been doing with him.</div><div><br></div><div>The issue =
is inside of loader.efi or /boot/loader, not in the earlier</div><div>boot =
blocks.</div><div><br></div><div>Warner</div><div>=C2=A0</div><blockquote c=
lass=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px soli=
d rgb(204,204,204);padding-left:1ex">
<br>
-- <br>
Cheers,<br>
Cy Schubert &lt;<a href=3D"mailto:Cy.Schubert@komquats.com" target=3D"_blan=
k">Cy.Schubert@komquats.com</a>&gt; or &lt;<a href=3D"mailto:Cy.Schubert@cs=
chubert.com" target=3D"_blank">Cy.Schubert@cschubert.com</a>&gt;<br>
FreeBSD UNIX:=C2=A0 &lt;cy@FreeBSD.org&gt;=C2=A0 =C2=A0Web:=C2=A0 <a href=
=3D"http://www.FreeBSD.org" rel=3D"noreferrer" target=3D"_blank">http://www=
.FreeBSD.org</a><br>
NTP:=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&lt;<a href=3D"mailto:cy@nwtim=
e.org" target=3D"_blank">cy@nwtime.org</a>&gt;=C2=A0 =C2=A0 Web:=C2=A0 <a h=
ref=3D"https://nwtime.org" rel=3D"noreferrer" target=3D"_blank">https://nwt=
ime.org</a><br>
<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 e**(i*pi)+1=3D0<br>
<br>
<br>
In message &lt;CANCZdfpovXadsxcS_YC2-NpJJX8S62YTfNTSfE9VHqoE6KsJPA@mail.gma=
il.c<br>
om&gt;<br>
, Warner Losh writes:<br>
&gt; --00000000000059353005e041e22c<br>
&gt; Content-Type: text/plain; charset=3D&quot;UTF-8&quot;<br>
&gt;<br>
&gt; David Woofskill also reported this...<br>
&gt;<br>
&gt; Warner<br>
&gt;<br>
&gt; On Mon, May 30, 2022, 3:56 PM Cy Schubert &lt;<a href=3D"mailto:Cy.Sch=
ubert@cschubert.com" target=3D"_blank">Cy.Schubert@cschubert.com</a>&gt; wr=
ote:<br>
&gt;<br>
&gt; &gt; In message &lt;<a href=3D"mailto:202205271922.24RJMOJ2039923@gitr=
epo.freebsd.org" target=3D"_blank">202205271922.24RJMOJ2039923@gitrepo.free=
bsd.org</a>&gt;, Kirk<br>
&gt; &gt; McKusick<br>
&gt; &gt; wri<br>
&gt; &gt; tes:<br>
&gt; &gt; &gt; The branch main has been updated by mckusick:<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; URL:<br>
&gt; &gt; <a href=3D"https://cgit.FreeBSD.org/src/commit/?id=3D076002f24d35=
962f0d21f44bfddd34ee" rel=3D"noreferrer" target=3D"_blank">https://cgit.Fre=
eBSD.org/src/commit/?id=3D076002f24d35962f0d21f44bfddd34ee</a><br>
&gt; &gt; &gt; 4d7f015d<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; commit 076002f24d35962f0d21f44bfddd34ee4d7f015d<br>
&gt; &gt; &gt; Author:=C2=A0 =C2=A0 =C2=A0Kirk McKusick &lt;mckusick@FreeBS=
D.org&gt;<br>
&gt; &gt; &gt; AuthorDate: 2022-05-27 19:21:11 +0000<br>
&gt; &gt; &gt; Commit:=C2=A0 =C2=A0 =C2=A0Kirk McKusick &lt;mckusick@FreeBS=
D.org&gt;<br>
&gt; &gt; &gt; CommitDate: 2022-05-27 19:22:07 +0000<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0Do comprehensive UFS/FFS superblock integ=
rity checks when reading a<br>
&gt; &gt; super<br>
&gt; &gt; &gt; block.<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0Historically only minimal checks were mad=
e of a superblock when it<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0was read in as it was assumed that fsck w=
ould have been run to<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0correct any errors before attempting to u=
se the filesystem. Recently<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0several bug reports have been submitted r=
eporting kernel panics<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0that can be triggered by deliberately cor=
rupting filesystem<br>
&gt; &gt; superblocks,<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0see Bug 263979 - [meta] UFS / FFS / GEOM =
crash (panic) tracking<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0which is tracking the reported corruption=
 bugs.<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0This change upgrades the checks that are =
performed. These additional<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0checks should prevent panics from a corru=
pted superblock. Although<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0it appears in only one place, the new cod=
e will apply to the kernel<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0modules and (through libufs) user applica=
tions that read in<br>
&gt; &gt; superblocks.<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0Reported by:=C2=A0 Robert Morris and Neer=
aj<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0Reviewed by:=C2=A0 kib<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0Tested by:=C2=A0 =C2=A0 Peter Holm<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0PR:=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0263979<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0MFC after:=C2=A0 =C2=A0 1 month<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0Differential Revision: <a href=3D"https:/=
/reviews.freebsd.org/D35219" rel=3D"noreferrer" target=3D"_blank">https://r=
eviews.freebsd.org/D35219</a><br>
&gt; &gt; &gt; ---<br>
&gt; &gt; &gt;=C2=A0 sys/ufs/ffs/ffs_subr.c | 163<br>
&gt; &gt; +++++++++++++++++++++++++++++++++++++++++++----<br>
&gt; &gt; &gt; --<br>
&gt; &gt; &gt;=C2=A0 1 file changed, 146 insertions(+), 17 deletions(-)<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; diff --git a/sys/ufs/ffs/ffs_subr.c b/sys/ufs/ffs/ffs_subr.c=
<br>
&gt; &gt; &gt; index 01e9f45e1205..28c2fee1cb37 100644<br>
&gt; &gt; &gt; --- a/sys/ufs/ffs/ffs_subr.c<br>
&gt; &gt; &gt; +++ b/sys/ufs/ffs/ffs_subr.c<br>
&gt; &gt; &gt; @@ -35,6 +35,7 @@<br>
&gt; &gt; &gt;=C2=A0 __FBSDID(&quot;$FreeBSD$&quot;);<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt;=C2=A0 #include &lt;sys/param.h&gt;<br>
&gt; &gt; &gt; +#include &lt;sys/limits.h&gt;<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt;=C2=A0 #ifndef _KERNEL<br>
&gt; &gt; &gt;=C2=A0 #include &lt;stdio.h&gt;<br>
&gt; &gt; &gt; @@ -50,6 +51,7 @@ uint32_t ffs_calc_sbhash(struct fs *);<br>
&gt; &gt; &gt;=C2=A0 struct malloc_type;<br>
&gt; &gt; &gt;=C2=A0 #define UFS_MALLOC(size, type, flags) malloc(size)<br>
&gt; &gt; &gt;=C2=A0 #define UFS_FREE(ptr, type) free(ptr)<br>
&gt; &gt; &gt; +#define maxphys MAXPHYS<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt;=C2=A0 #else /* _KERNEL */<br>
&gt; &gt; &gt;=C2=A0 #include &lt;sys/systm.h&gt;<br>
&gt; &gt; &gt; @@ -125,6 +127,7 @@ ffs_update_dinode_ckhash(struct fs *fs, =
struct<br>
&gt; &gt; ufs2_dinod<br>
&gt; &gt; &gt; e *dip)<br>
&gt; &gt; &gt;=C2=A0 static off_t sblock_try[] =3D SBLOCKSEARCH;<br>
&gt; &gt; &gt;=C2=A0 static int readsuper(void *, struct fs **, off_t, int,=
 int,<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0int (*)(void *, off_t, void **, in=
t));<br>
&gt; &gt; &gt; +static int validate_sblock(struct fs *, int);<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt;=C2=A0 /*<br>
&gt; &gt; &gt;=C2=A0 =C2=A0* Read a superblock from the devfd device.<br>
&gt; &gt; &gt; @@ -141,7 +144,7 @@ static int readsuper(void *, struct fs *=
*, off_t,<br>
&gt; &gt; int, in<br>
&gt; &gt; &gt; t,<br>
&gt; &gt; &gt;=C2=A0 =C2=A0*=C2=A0 =C2=A0 =C2=A0EIO: non-existent or trunca=
ted superblock.<br>
&gt; &gt; &gt;=C2=A0 =C2=A0*=C2=A0 =C2=A0 =C2=A0EIO: error reading summary =
information.<br>
&gt; &gt; &gt;=C2=A0 =C2=A0*=C2=A0 =C2=A0 =C2=A0ENOENT: no usable known sup=
erblock found.<br>
&gt; &gt; &gt; - *=C2=A0 =C2=A0 =C2=A0ENOSPC: failed to allocate space for =
the superblock.<br>
&gt; &gt; &gt; + *=C2=A0 =C2=A0 =C2=A0ENOMEM: failed to allocate space for =
the superblock.<br>
&gt; &gt; &gt;=C2=A0 =C2=A0*=C2=A0 =C2=A0 =C2=A0EINVAL: The previous newfs =
operation on this volume did not<br>
&gt; &gt; complete.<br>
&gt; &gt; &gt;=C2=A0 =C2=A0*=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The administr=
ator must complete newfs before using this<br>
&gt; &gt; volume.<br>
&gt; &gt; &gt;=C2=A0 =C2=A0*/<br>
&gt; &gt; &gt; @@ -152,7 +155,8 @@ ffs_sbget(void *devfd, struct fs **fsp, =
off_t<br>
&gt; &gt; altsblock,<br>
&gt; &gt; &gt;=C2=A0 {<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0struct fs *fs;<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0struct fs_summary_info *fs_si;<br>
&gt; &gt; &gt; -=C2=A0 =C2=A0 =C2=A0int i, error, size, blks;<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0int i, error;<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0uint64_t size, blks;<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0uint8_t *space;<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0int32_t *lp;<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0char *buf;<br>
&gt; &gt; &gt; @@ -190,17 +194,16 @@ ffs_sbget(void *devfd, struct fs **fsp=
, off_t<br>
&gt; &gt; altsblock<br>
&gt; &gt; &gt; ,<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0if (fs-&gt;fs_contigsumsize &gt; 0=
)<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0size +=
=3D fs-&gt;fs_ncg * sizeof(int32_t);<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0size +=3D fs-&gt;fs_ncg * sizeof(u=
_int8_t);<br>
&gt; &gt; &gt; -=C2=A0 =C2=A0 =C2=A0/* When running in libufs or libsa, UFS=
_MALLOC may fail */<br>
&gt; &gt; &gt; -=C2=A0 =C2=A0 =C2=A0if ((fs_si =3D UFS_MALLOC(sizeof(*fs_si=
), filltype, M_WAITOK)) =3D=3D<br>
&gt; &gt; NULL) {<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0if ((fs_si =3D UFS_MALLOC(sizeof(*fs_si=
), filltype, M_NOWAIT)) =3D=3D<br>
&gt; &gt; NULL) {<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0UFS_FR=
EE(fs, filltype);<br>
&gt; &gt; &gt; -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (ENO=
SPC);<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (ENO=
MEM);<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0}<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0bzero(fs_si, sizeof(*fs_si));<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0fs-&gt;fs_si =3D fs_si;<br>
&gt; &gt; &gt; -=C2=A0 =C2=A0 =C2=A0if ((space =3D UFS_MALLOC(size, filltyp=
e, M_WAITOK)) =3D=3D NULL) {<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0if ((space =3D UFS_MALLOC(size, filltyp=
e, M_NOWAIT)) =3D=3D NULL) {<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0UFS_FR=
EE(fs-&gt;fs_si, filltype);<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0UFS_FR=
EE(fs, filltype);<br>
&gt; &gt; &gt; -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (ENO=
SPC);<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (ENO=
MEM);<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0}<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0fs-&gt;fs_csp =3D (struct csum *)s=
pace;<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0for (i =3D 0; i &lt; blks; i +=3D =
fs-&gt;fs_frag) {<br>
&gt; &gt; &gt; @@ -253,16 +256,8 @@ readsuper(void *devfd, struct fs **fsp,=
 off_t<br>
&gt; &gt; sblockloc,<br>
&gt; &gt; &gt;=C2=A0 int isaltsblk,<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0fs =3D *fsp;<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0if (fs-&gt;fs_magic =3D=3D FS_BAD_=
MAGIC)<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return=
 (EINVAL);<br>
&gt; &gt; &gt; -=C2=A0 =C2=A0 =C2=A0if (!(((fs-&gt;fs_magic =3D=3D FS_UFS1_=
MAGIC &amp;&amp; (isaltsblk ||<br>
&gt; &gt; &gt; -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0sblockloc &lt;=3D =
SBLOCK_UFS1)) ||<br>
&gt; &gt; &gt; -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (fs-&gt;fs_magic =3D=3D =
FS_UFS2_MAGIC &amp;&amp; (isaltsblk ||<br>
&gt; &gt; &gt; -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0sblockloc =3D=3D f=
s-&gt;fs_sblockloc))) &amp;&amp;<br>
&gt; &gt; &gt; -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs-&gt;fs_ncg &gt;=3D 1 &=
amp;&amp;<br>
&gt; &gt; &gt; -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs-&gt;fs_bsize &gt;=3D M=
INBSIZE &amp;&amp;<br>
&gt; &gt; &gt; -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs-&gt;fs_bsize &lt;=3D M=
AXBSIZE &amp;&amp;<br>
&gt; &gt; &gt; -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs-&gt;fs_bsize &gt;=3D r=
oundup(sizeof(struct fs), DEV_BSIZE) &amp;&amp;<br>
&gt; &gt; &gt; -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs-&gt;fs_sbsize &lt;=3D =
SBLOCKSIZE))<br>
&gt; &gt; &gt; -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (ENO=
ENT);<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0if ((error =3D validate_sblock(fs, isal=
tsblk)) !=3D 0)<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (err=
or);<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0/*<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 * If the filesystem has been run =
on a kernel without<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 * metadata check hashes, disable =
them.<br>
&gt; &gt; &gt; @@ -310,6 +305,140 @@ readsuper(void *devfd, struct fs **fsp=
, off_t<br>
&gt; &gt; sblockloc<br>
&gt; &gt; &gt; , int isaltsblk,<br>
&gt; &gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0return (0);<br>
&gt; &gt; &gt;=C2=A0 }<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; +/*<br>
&gt; &gt; &gt; + * Verify the filesystem values.<br>
&gt; &gt; &gt; + */<br>
&gt; &gt; &gt; +#define ILOG2(num) (fls(num) - 1)<br>
&gt; &gt; &gt; +<br>
&gt; &gt; &gt; +static int<br>
&gt; &gt; &gt; +validate_sblock(struct fs *fs, int isaltsblk)<br>
&gt; &gt; &gt; +{<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0int i, sectorsize;<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0u_int64_t maxfilesize, minfpg, sizepb;<=
br>
&gt; &gt; &gt; +<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0sectorsize =3D dbtob(1);<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0if (fs-&gt;fs_magic =3D=3D FS_UFS2_MAGI=
C) {<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if ((!isalt=
sblk &amp;&amp; (fs-&gt;fs_sblockloc !=3D SBLOCK_UFS2 ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0fs-&gt;fs_sblockactualloc !=3D SBLOCK_UFS2)) ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0fs-&gt;fs_maxsymlinklen !=3D ((UFS_NDADDR + UFS_NIADDR) *<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0sizeof(ufs2_daddr_t)) ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0fs-&gt;fs_nindir !=3D fs-&gt;fs_bsize / sizeof(ufs2_daddr_t) ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0fs-&gt;fs_inopb !=3D fs-&gt;fs_bsize / sizeof(struct<br>
&gt; &gt; ufs2_dinode))<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0return (ENOENT);<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0} else if (fs-&gt;fs_magic =3D=3D FS_UF=
S1_MAGIC) {<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if ((!isalt=
sblk &amp;&amp; (fs-&gt;fs_sblockloc &gt; SBLOCK_UFS1 ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0fs-&gt;fs_sblockactualloc !=3D SBLOCK_UFS1)) ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0fs-&gt;fs_nindir !=3D fs-&gt;fs_bsize / sizeof(ufs1_daddr_t) ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0fs-&gt;fs_inopb !=3D fs-&gt;fs_bsize / sizeof(struct<br>
&gt; &gt; ufs1_dinode) |<br>
&gt; &gt; &gt; |<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0fs-&gt;fs_maxsymlinklen !=3D ((UFS_NDADDR + UFS_NIADDR) *<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0sizeof(ufs1_daddr_t)) ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0fs-&gt;fs_old_inodefmt !=3D FS_44INODEFMT ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0fs-&gt;fs_old_cgoffset !=3D 0 ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0fs-&gt;fs_old_cgmask !=3D 0xffffffff ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0fs-&gt;fs_old_size !=3D fs-&gt;fs_size ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0fs-&gt;fs_old_rotdelay !=3D 0 ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0fs-&gt;fs_old_rps !=3D 60 ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0fs-&gt;fs_old_nspf !=3D fs-&gt;fs_fsize / sectorsize ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0fs-&gt;fs_old_cpg !=3D 1 ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0fs-&gt;fs_old_interleave !=3D 1 ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0fs-&gt;fs_old_trackskew !=3D 0 ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0fs-&gt;fs_old_cpc !=3D 0 ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0fs-&gt;fs_old_postblformat !=3D 1 ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0fs-&gt;fs_old_nrpos !=3D 1 ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0fs-&gt;fs_old_spc !=3D fs-&gt;fs_fpg * fs-&gt;fs_old_nspf ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0fs-&gt;fs_old_nsect !=3D fs-&gt;fs_old_spc ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0fs-&gt;fs_old_npsect !=3D fs-&gt;fs_old_spc ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0fs-&gt;fs_old_dsize !=3D fs-&gt;fs_dsize ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0fs-&gt;fs_old_ncyl !=3D fs-&gt;fs_ncg)<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0return (ENOENT);<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0} else {<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (ENO=
ENT);<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0}<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0if (fs-&gt;fs_bsize &lt; MINBSIZE || fs=
-&gt;fs_bsize &gt; MAXBSIZE ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs-&gt;fs_bsize &lt; roun=
dup(sizeof(struct fs), DEV_BSIZE) ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs-&gt;fs_sbsize &gt; SBL=
OCKSIZE || fs-&gt;fs_sbsize &lt; fs-&gt;fs_fsize ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0!powerof2(fs-&gt;fs_bsize=
))<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (ENO=
ENT);<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0if (fs-&gt;fs_fsize &lt; sectorsize || =
fs-&gt;fs_fsize &gt; fs-&gt;fs_bsize ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs-&gt;fs_fsize * MAXFRAG=
 &lt; fs-&gt;fs_bsize ||<br>
&gt; &gt; !powerof2(fs-&gt;fs_fsize))<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (ENO=
ENT);<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0if (fs-&gt;fs_maxbsize &lt; fs-&gt;fs_b=
size || !powerof2(fs-&gt;fs_maxbsize) ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs-&gt;fs_maxbsize &gt; F=
S_MAXCONTIG * fs-&gt;fs_bsize)<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (ENO=
ENT);<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0if (fs-&gt;fs_bmask !=3D ~(fs-&gt;fs_bs=
ize - 1) ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs-&gt;fs_fmask !=3D ~(fs=
-&gt;fs_fsize - 1) ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs-&gt;fs_qbmask !=3D ~fs=
-&gt;fs_bmask ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs-&gt;fs_qfmask !=3D ~fs=
-&gt;fs_fmask ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs-&gt;fs_bshift !=3D ILO=
G2(fs-&gt;fs_bsize) ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs-&gt;fs_fshift !=3D ILO=
G2(fs-&gt;fs_fsize) ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs-&gt;fs_frag !=3D numfr=
ags(fs, fs-&gt;fs_bsize) ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs-&gt;fs_fragshift !=3D =
ILOG2(fs-&gt;fs_frag) ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs-&gt;fs_frag &gt; MAXFR=
AG ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs-&gt;fs_fsbtodb !=3D IL=
OG2(fs-&gt;fs_fsize / sectorsize))<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (ENO=
ENT);<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0if (fs-&gt;fs_sblkno !=3D<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0roundup(how=
many(fs-&gt;fs_sblockloc + SBLOCKSIZE,<br>
&gt; &gt; fs-&gt;fs_fsize),<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0fs-&gt;fs_frag) ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs-&gt;fs_cblkno !=3D fs-=
&gt;fs_sblkno +<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0roundup(how=
many(SBLOCKSIZE, fs-&gt;fs_fsize), fs-&gt;fs_frag) ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs-&gt;fs_iblkno !=3D fs-=
&gt;fs_cblkno + fs-&gt;fs_frag ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs-&gt;fs_dblkno !=3D fs-=
&gt;fs_iblkno + fs-&gt;fs_ipg / INOPF(fs) ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs-&gt;fs_cgsize !=3D fra=
groundup(fs, CGSIZE(fs)))<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (ENO=
ENT);<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0if (fs-&gt;fs_csaddr !=3D cgdmin(fs, 0)=
 ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs-&gt;fs_cssize !=3D<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fragroundup=
(fs, fs-&gt;fs_ncg * sizeof(struct csum)) ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs-&gt;fs_dsize !=3D fs-&=
gt;fs_size - fs-&gt;fs_sblkno -<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs-&gt;fs_n=
cg * (fs-&gt;fs_dblkno - fs-&gt;fs_sblkno) -<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0howmany(fs-=
&gt;fs_cssize, fs-&gt;fs_fsize) ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs-&gt;fs_metaspace &lt; =
0 || fs-&gt;fs_metaspace &gt; fs-&gt;fs_fpg / 2 ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs-&gt;fs_minfree &gt; 99=
)<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (ENO=
ENT);<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0maxfilesize =3D fs-&gt;fs_bsize * UFS_N=
DADDR - 1;<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0for (sizepb =3D fs-&gt;fs_bsize, i =3D =
0; i &lt; UFS_NIADDR; i++) {<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0sizepb *=3D=
 NINDIR(fs);<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0maxfilesize=
 +=3D sizepb;<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0}<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0if (fs-&gt;fs_maxfilesize !=3D maxfiles=
ize)<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (ENO=
ENT);<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0/*<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 * These values have a tight interactio=
n with each other that<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 * makes it hard to tightly bound them.=
 So we can only check<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 * that they are within a broader possi=
ble range.<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 *<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 * Calculate minfpg, the minimum number=
 of fragments that can be<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 * in a cylinder group. The value 12289=
 is calculated in newfs(8)<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 * when creating the smallest block siz=
e UFS version 1 filesystem<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 * (4096 block size) with no fragments =
(4096 fragment size). That<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 * number may be depressed even further=
 for very small filesystems<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 * since newfs(8) strives to have at le=
ast four cylinder groups.<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 */<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0minfpg =3D MIN(12289, fs-&gt;fs_size / =
4);<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0if (fs-&gt;fs_ncg &lt; 1 || fs-&gt;fs_n=
cg &gt; (fs-&gt;fs_size / minfpg) + 1 ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs-&gt;fs_fpg &lt; minfpg=
 || fs-&gt;fs_fpg &gt; fs-&gt;fs_size ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs-&gt;fs_ipg * fs-&gt;fs=
_ncg &gt; (((int64_t)(1)) &lt;&lt; 32) - INOPB(fs) ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs-&gt;fs_ipg &gt; fs-&gt=
;fs_fpg || fs-&gt;fs_size &lt; 8 * fs-&gt;fs_frag)<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (ENO=
ENT);<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0if (fs-&gt;fs_size &lt;=3D (fs-&gt;fs_n=
cg - 1) * fs-&gt;fs_fpg ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs-&gt;fs_size &gt; fs-&g=
t;fs_ncg * fs-&gt;fs_fpg)<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (ENO=
ENT);<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0/*<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 * Maxcontig sets the default for the m=
aximum number of blocks<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 * that may be allocated sequentially. =
With file system clustering<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 * it is possible to allocate contiguou=
s blocks up to the maximum<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 * transfer size permitted by the contr=
oller or buffering.<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 */<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0if (fs-&gt;fs_maxcontig &lt; 1 ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs-&gt;fs_maxcontig &gt; =
MAX(1, maxphys / fs-&gt;fs_bsize))<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (ENO=
ENT);<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0if (fs-&gt;fs_maxcontig &lt; 0 ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(fs-&gt;fs_maxcontig =3D=
=3D 0 &amp;&amp; fs-&gt;fs_contigsumsize !=3D 0) ||<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(fs-&gt;fs_maxcontig &gt;=
 1 &amp;&amp;<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs-&gt;fs_contigsumsize !=
=3D MIN(fs-&gt;fs_maxcontig, FS_MAXCONTIG)))<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (ENO=
ENT);<br>
&gt; &gt; &gt; +=C2=A0 =C2=A0 =C2=A0return (0);<br>
&gt; &gt; &gt; +}<br>
&gt; &gt; &gt; +<br>
&gt; &gt; &gt;=C2=A0 /*<br>
&gt; &gt; &gt;=C2=A0 =C2=A0* Write a superblock to the devfd device from th=
e memory pointed to by<br>
&gt; &gt; fs.<br>
&gt; &gt; &gt;=C2=A0 =C2=A0* Write out the superblock summary information i=
f it is present.<br>
&gt; &gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt; Hi Kirk,<br>
&gt; &gt;<br>
&gt; &gt; This patch broke loader on one of my machines.<br>
&gt; &gt;<br>
&gt; &gt; I get the following error:<br>
&gt; &gt;<br>
&gt; &gt; LUA ERROR: Cannot open /boot/lua/loader.lua: no such file or dire=
ctory&quot;<br>
&gt; &gt; can&#39;t load kernel<br>
&gt; &gt;<br>
&gt; &gt; Of course booting from my rescue worked.<br>
&gt; &gt;<br>
&gt; &gt; Copying loader* from /boot on the rescue disk to /boot works arou=
nd the<br>
&gt; &gt; problem.<br>
&gt; &gt;<br>
&gt; &gt; Backing up, newfs, and restoring the root filesystem, using my re=
scue disk<br>
&gt; &gt; also didn&#39;t work around the problem.<br>
&gt; &gt;<br>
&gt; &gt; Reverting this patch provided permanent relief.<br>
&gt; &gt;<br>
&gt; &gt; Loader could read the filesystems on my rescue disk, which had bl=
ocksizes<br>
&gt; &gt; of 16K but not those on my boot disk which had blocksizes of 32K.=
<br>
&gt; &gt;<br>
&gt; &gt; My three machines downstairs, all AMD gear with UFS blocksize of =
32K, had<br>
&gt; &gt; no no problems with this whereas my laptop, an Intel, had the pro=
blem.<br>
&gt; &gt;<br>
&gt; &gt; To repeat, a newly created filesystem restored from backup using =
my rescue<br>
&gt; &gt; disk didn&#39;t resolve the problem.<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt; --<br>
&gt; &gt; Cheers,<br>
&gt; &gt; Cy Schubert &lt;<a href=3D"mailto:Cy.Schubert@komquats.com" targe=
t=3D"_blank">Cy.Schubert@komquats.com</a>&gt; or &lt;<a href=3D"mailto:Cy.S=
chubert@cschubert.com" target=3D"_blank">Cy.Schubert@cschubert.com</a>&gt;<=
br>
&gt; &gt; FreeBSD UNIX:=C2=A0 &lt;cy@FreeBSD.org&gt;=C2=A0 =C2=A0Web:=C2=A0=
 <a href=3D"http://www.FreeBSD.org" rel=3D"noreferrer" target=3D"_blank">ht=
tp://www.FreeBSD.org</a><br>
&gt; &gt; NTP:=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&lt;<a href=3D"mailt=
o:cy@nwtime.org" target=3D"_blank">cy@nwtime.org</a>&gt;=C2=A0 =C2=A0 Web:=
=C2=A0 <a href=3D"https://nwtime.org" rel=3D"noreferrer" target=3D"_blank">=
https://nwtime.org</a><br>;
&gt; &gt;<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0e**(i*pi)+1=3D0<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
<br>
<br>
</blockquote></div></div>

--0000000000008603c305e04240eb--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CANCZdfoqpDO9-APZytimd9TpPGsnaj0%2BwJBfdxv%2Bo2NnOX5ZUQ>