Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 7 Jul 2017 09:23:54 +0300
From:      Konstantin Belousov <kostikbel@gmail.com>
To:        Willem Jan Withagen <wjw@digiware.nl>
Cc:        Bruce Evans <brde@optusnet.com.au>, FreeBSD Filesystems <freebsd-fs@freebsd.org>
Subject:   Re: newfs returns cg 0: bad magic number
Message-ID:  <20170707062354.GP1935@kib.kiev.ua>
In-Reply-To: <9fe3ec97-60ea-e9e6-fb65-9b163d64ac45@digiware.nl>
References:  <c98c813c-c393-9ba5-5c70-b9575fe59553@digiware.nl> <20170705051458.GU1935@kib.kiev.ua> <20170705154533.M1171@besplex.bde.org> <9fe3ec97-60ea-e9e6-fb65-9b163d64ac45@digiware.nl>

next in thread | previous in thread | raw e-mail | index | archive | help
On Fri, Jul 07, 2017 at 12:12:49AM +0200, Willem Jan Withagen wrote:
> On 5-7-2017 08:55, Bruce Evans wrote:
> > On Wed, 5 Jul 2017, Konstantin Belousov wrote:
> > 
> >> On Wed, Jul 05, 2017 at 02:00:43AM +0200, Willem Jan Withagen wrote:
> >>> Hi,
> >>>
> >>> I'm able to create a Ceph RBD backed ggate disk, in /dev/ggate0.
> >>> It looks like I can:
> >>>     run dd on it
> >>>     gpart the disk
> >>>     create a zpool on it
> >>>
> >>> But when I try to create a UFS file system on it, newfs complains
> >>> straight from the bat.
> >>>
> >>> # sudo newfs -E /dev/ggate0p1
> >>> /dev/ggate0p1: 1022.0MB (2093056 sectors) block size 32768, fragment
> >>> size 4096
> >>>         using 4 cylinder groups of 255.53MB, 8177 blks, 32768 inodes.
> >>> Erasing sectors [128...2093055]
> >>> super-block backups (for fsck_ffs -b #) at:
> >>>  192, 523520, 1046848, 1570176
> >>> cg 0: bad magic number
> >>>
> >>> Googling returns that this is on and off a problem with new devices, but
> >>> there is no generic suggestion on how to debug this....
> >>>
> >>> Any/all suggestions are welcome,
> >> Typically this error means that the drive returns wrong data, not the
> >> bytes that were written to it and expected to be read.
> > 
> > This might be for writing to a nonexistent sector.  Checking for write
> > errors was broken by libufs, so some write errors are only sometimes
> > detected as a side effect of reading back garbage.
> > 
> > I use the following quick fix (the patch also fixes some style bugs).
> > 
> > X Index: mkfs.c
> > X ===================================================================
> > X RCS file: /home/ncvs/src/sbin/newfs/mkfs.c,v
> > X retrieving revision 1.85
> > X diff -u -1 -r1.85 mkfs.c
> > X --- mkfs.c    9 Apr 2004 19:58:33 -0000    1.85
> > X +++ mkfs.c    7 Apr 2005 23:51:56 -0000
> > X @@ -437,16 +441,19 @@
> > X      if (!Nflag && Oflag != 1) {
> > X -        i = bread(&disk, SBLOCK_UFS1 / disk.d_bsize, chdummy,
> > SBLOCKSIZE);
> > X +        i = bread(&disk, SBLOCK_UFS1 / disk.d_bsize, chdummy,
> > X +            SBLOCKSIZE);
> > X          if (i == -1)
> > X -            err(1, "can't read old UFS1 superblock: %s", disk.d_error);
> > X -
> > X +            err(1, "can't read old UFS1 superblock: %s",
> > X +                disk.d_error);
> > X          if (fsdummy.fs_magic == FS_UFS1_MAGIC) {
> > X              fsdummy.fs_magic = 0;
> > X -            bwrite(&disk, SBLOCK_UFS1 / disk.d_bsize, chdummy,
> > SBLOCKSIZE);
> > X +            bwrite(&disk, SBLOCK_UFS1 / disk.d_bsize, chdummy,
> > X +                SBLOCKSIZE);
> > X              for (i = 0; i < fsdummy.fs_ncg; i++)
> > X -                bwrite(&disk, fsbtodb(&fsdummy, cgsblock(&fsdummy, i)),
> > X -                        chdummy, SBLOCKSIZE);
> > X +                bwrite(&disk,
> > X +                    fsbtodb(&fsdummy, cgsblock(&fsdummy, i)),
> > X +                    chdummy, SBLOCKSIZE);
> > X          }
> > X      }
> > X -    if (!Nflag)
> > X -        sbwrite(&disk, 0);
> > X +    if (!Nflag && sbwrite(&disk, 0) != 0)
> > X +        err(1, "sbwrite: %s", disk.d_error);
> > X      if (Eflag == 1) {
> > X @@ -518,4 +525,4 @@
> > X      }
> > X -    if (!Nflag)
> > X -        sbwrite(&disk, 0);
> > X +    if (!Nflag && sbwrite(&disk, 0) != 0)
> > X +        err(1, "sbwrite: %s", disk.d_error);
> > X      for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize)
> > 
> > libufs broke the error handling for the most important writes -- to
> > the superblock.  Error handling is still done almost correctly in
> > wtfs(), and most writes are still done using wtfs() which is now
> > just a wrapper which adds error handling to libufs's bwrite(3), but
> > writes to superblock are (were) now done internally by libufs's
> > sbwrite(3) which (like most of libufs) is too hard to use.
> > 
> > Note that -current needs a slightly different fix.  Part of libufs
> > being too hard to use is that it is a library so it can't just exit
> > for errors.  It returns errors in the string disk.d_error and the
> > fix uses that for newfs, unlike for most other calls to sbwrite(3).
> > However, newfs no longer uses sbwrite(3).  It uses a wrapper
> > do_sbwrite() which reduces to pwrite(2).  The wrapper doesn't set
> > d_error, so it is incompatible with sbwrite(3).
> > 
> > This is an example that libufs is even harder to use than might first
> > appear.  The version with the do_sbwrite() wrapper fixes a previous
> > version which replaced bwrite(3) instead of wrapping it.  bwrite()
> > in the application conflicted with bwrite(3) in libufs, since libufs
> > is not designed to have its internals replaced by inconsistent parts
> > like that.  Apparently, a special case is only needed for superblock
> > writes, and do_sbwrite() does that, and since libufs doesn't call any
> > sbwrite() function internally there is no need to replace sbwrite(3);
> > sbwrite(3) is just useless for its main application.  All that the
> > bwrite(3) and sbwrite(3) library functions do is handle the block
> > size implicitly in a way that makes them harder to use than just
> > multiplying by the block size like wtfs() used to do and do_sbwrite()
> > now does.
> 
> This is where the trouble originates:
> /usr/srcs/11/src/lib/libufs/sblock.c:148
>         /*
>          * Write superblock summary information.
>          */
>         blks = howmany(fs->fs_cssize, fs->fs_fsize);
>         space = (uint8_t *)disk->d_sbcsum;
>         for (i = 0; i < blks; i += fs->fs_frag) {
> 
> But:
> 
> (gdb) p disk->d_sbcsum
> $19 = (struct csum *) 0x0
> 
> and this pointer is later on used to write:
>     for (i = 0; i < blks; i += fs->fs_frag) {
>         size = fs->fs_bsize;
>         if (i + fs->fs_frag > blks)
>             size = (blks - i) * fs->fs_fsize;
>         if (bwrite(disk, fsbtodb(fs, fs->fs_csaddr + i), space, size)
>             == -1) {
>             ERROR(disk, "Failed to write sb summary information");
>             return (-1);
>         }
>         space += size;
>     }
> 
> But the bwrite returns error because the called pwrite() tries to write
> 4096 bytes from a null pointer. And that it does not like.
> 
> Now the question is: why isn't d_sbcsum not filled out?
> Note that the disk is filled with random data.
> 
> I've been looking for quite some time, but I just don't get it.
> Where should the superblock come from if a whole disk is being used?
> (so there no MBR or gpart written. Dangerously dedicated)

Indeed I am not sure what do you report there.  newfs(8) does not use
sbwrite() function from libufs.  Set a breakpoint on the sbwrite()
function and catch the backtrace of the call.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20170707062354.GP1935>