Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 20 Jan 2020 08:28:55 +0000 (UTC)
From:      Eugene Grosbein <eugen@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r356905 - in stable/11: sbin/fsck_ffs sbin/newfs sys/ufs/ffs
Message-ID:  <202001200828.00K8SteN056855@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: eugen
Date: Mon Jan 20 08:28:54 2020
New Revision: 356905
URL: https://svnweb.freebsd.org/changeset/base/356905

Log:
  MFC r323157 by 323157: fix recovery information with sector sizes up to 64K.
  
  Original commit log:
  
    The new fsck recovery information to enable it to find backup
    superblocks created in revision 322297 only works on disks
    with sector sizes up to 4K. This update allows the recovery
    information to be created by newfs and used by fsck on disks
    with sector sizes up to 64K. Note that FFS currently limits
    filesystem to be mounted from disks with up to 8K sectors.
    Expanding this limitation will be the subject of another
    commit.
  
  For example, this allows newfs to work on GELI volumes with 8K sectors.
  
  PR:		243413
  Approved by:	mckusick
  Relnotes:	Yes

Modified:
  stable/11/sbin/fsck_ffs/setup.c
  stable/11/sbin/newfs/mkfs.c
  stable/11/sys/ufs/ffs/fs.h
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sbin/fsck_ffs/setup.c
==============================================================================
--- stable/11/sbin/fsck_ffs/setup.c	Mon Jan 20 04:01:35 2020	(r356904)
+++ stable/11/sbin/fsck_ffs/setup.c	Mon Jan 20 08:28:54 2020	(r356905)
@@ -36,6 +36,7 @@ static const char sccsid[] = "@(#)setup.c	8.10 (Berkel
 __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
+#include <sys/disk.h>
 #include <sys/stat.h>
 #define FSTYPENAMES
 #include <sys/disklabel.h>
@@ -466,7 +467,9 @@ sblock_init(void)
 static int
 calcsb(char *dev, int devfd, struct fs *fs)
 {
-	struct fsrecovery fsr;
+	struct fsrecovery *fsr;
+	char *fsrbuf;
+	u_int secsize;
 
 	/*
 	 * We need fragments-per-group and the partition-size.
@@ -476,32 +479,62 @@ calcsb(char *dev, int devfd, struct fs *fs)
 	 * overwritten by a boot block, we fail. But usually they are
 	 * there and we can use them.
 	 */
-	if (blread(devfd, (char *)&fsr,
-	    (SBLOCK_UFS2 - sizeof(fsr)) / dev_bsize, sizeof(fsr)) ||
-	    fsr.fsr_magic != FS_UFS2_MAGIC)
+	if (ioctl(devfd, DIOCGSECTORSIZE, &secsize) == -1)
 		return (0);
+	fsrbuf = Malloc(secsize);
+	if (fsrbuf == NULL)
+		errx(EEXIT, "calcsb: cannot allocate recovery buffer");
+	if (blread(devfd, fsrbuf,
+	    (SBLOCK_UFS2 - secsize) / dev_bsize, secsize) != 0)
+		return (0);
+	fsr = (struct fsrecovery *)&fsrbuf[secsize - sizeof *fsr];
+	if (fsr->fsr_magic != FS_UFS2_MAGIC)
+		return (0);
 	memset(fs, 0, sizeof(struct fs));
-	fs->fs_fpg = fsr.fsr_fpg;
-	fs->fs_fsbtodb = fsr.fsr_fsbtodb;
-	fs->fs_sblkno = fsr.fsr_sblkno;
-	fs->fs_magic = fsr.fsr_magic;
-	fs->fs_ncg = fsr.fsr_ncg;
+	fs->fs_fpg = fsr->fsr_fpg;
+	fs->fs_fsbtodb = fsr->fsr_fsbtodb;
+	fs->fs_sblkno = fsr->fsr_sblkno;
+	fs->fs_magic = fsr->fsr_magic;
+	fs->fs_ncg = fsr->fsr_ncg;
+	free(fsrbuf);
 	return (1);
 }
 
 /*
  * Check to see if recovery information exists.
+ * Return 1 if it exists or cannot be created.
+ * Return 0 if it does not exist and can be created.
  */
 static int
 chkrecovery(int devfd)
 {
-	struct fsrecovery fsr;
+	struct fsrecovery *fsr;
+	char *fsrbuf;
+	u_int secsize;
 
-	if (blread(devfd, (char *)&fsr,
-	    (SBLOCK_UFS2 - sizeof(fsr)) / dev_bsize, sizeof(fsr)) ||
-	    fsr.fsr_magic != FS_UFS2_MAGIC)
-		return (0);
-	return (1);
+	/*
+	 * Could not determine if backup material exists, so do not
+	 * offer to create it.
+	 */
+	if (ioctl(devfd, DIOCGSECTORSIZE, &secsize) == -1 ||
+	    (fsrbuf = Malloc(secsize)) == NULL ||
+	    blread(devfd, fsrbuf, (SBLOCK_UFS2 - secsize) / dev_bsize,
+	      secsize) != 0)
+		return (1);
+	/*
+	 * Recovery material has already been created, so do not
+	 * need to create it again.
+	 */
+	fsr = (struct fsrecovery *)&fsrbuf[secsize - sizeof *fsr];
+	if (fsr->fsr_magic == FS_UFS2_MAGIC) {
+		free(fsrbuf);
+		return (1);
+	}
+	/*
+	 * Recovery material has not been created and can be if desired.
+	 */
+	free(fsrbuf);
+	return (0);
 }
 
 /*
@@ -512,17 +545,24 @@ chkrecovery(int devfd)
 static void
 saverecovery(int readfd, int writefd)
 {
-	struct fsrecovery fsr;
+	struct fsrecovery *fsr;
+	char *fsrbuf;
+	u_int secsize;
 
 	if (sblock.fs_magic != FS_UFS2_MAGIC ||
-	    blread(readfd, (char *)&fsr,
-	    (SBLOCK_UFS2 - sizeof(fsr)) / dev_bsize, sizeof(fsr)))
+	    ioctl(readfd, DIOCGSECTORSIZE, &secsize) == -1 ||
+	    (fsrbuf = Malloc(secsize)) == NULL ||
+	    blread(readfd, fsrbuf, (SBLOCK_UFS2 - secsize) / dev_bsize,
+	      secsize) != 0) {
+		printf("RECOVERY DATA COULD NOT BE CREATED\n");
 		return;
-	fsr.fsr_magic = sblock.fs_magic;
-	fsr.fsr_fpg = sblock.fs_fpg;
-	fsr.fsr_fsbtodb = sblock.fs_fsbtodb;
-	fsr.fsr_sblkno = sblock.fs_sblkno;
-	fsr.fsr_ncg = sblock.fs_ncg;
-	blwrite(writefd, (char *)&fsr, (SBLOCK_UFS2 - sizeof(fsr)) / dev_bsize,
-	    sizeof(fsr));
+	}
+	fsr = (struct fsrecovery *)&fsrbuf[secsize - sizeof *fsr];
+	fsr->fsr_magic = sblock.fs_magic;
+	fsr->fsr_fpg = sblock.fs_fpg;
+	fsr->fsr_fsbtodb = sblock.fs_fsbtodb;
+	fsr->fsr_sblkno = sblock.fs_sblkno;
+	fsr->fsr_ncg = sblock.fs_ncg;
+	blwrite(writefd, fsrbuf, (SBLOCK_UFS2 - secsize) / secsize, secsize);
+	free(fsrbuf);
 }

Modified: stable/11/sbin/newfs/mkfs.c
==============================================================================
--- stable/11/sbin/newfs/mkfs.c	Mon Jan 20 04:01:35 2020	(r356904)
+++ stable/11/sbin/newfs/mkfs.c	Mon Jan 20 08:28:54 2020	(r356905)
@@ -121,7 +121,8 @@ mkfs(struct partition *pp, char *fsys)
 	ino_t maxinum;
 	int minfragsperinode;	/* minimum ratio of frags to inodes */
 	char tmpbuf[100];	/* XXX this will break in about 2,500 years */
-	struct fsrecovery fsr;
+	struct fsrecovery *fsr;
+	char *fsrbuf;
 	union {
 		struct fs fdummy;
 		char cdummy[SBLOCKSIZE];
@@ -442,6 +443,8 @@ restart:
 	sblock.fs_sbsize = fragroundup(&sblock, sizeof(struct fs));
 	if (sblock.fs_sbsize > SBLOCKSIZE)
 		sblock.fs_sbsize = SBLOCKSIZE;
+	if (sblock.fs_sbsize < realsectorsize)
+		sblock.fs_sbsize = realsectorsize;
 	sblock.fs_minfree = minfree;
 	if (metaspace > 0 && metaspace < sblock.fs_fpg / 2)
 		sblock.fs_metaspace = blknum(&sblock, metaspace);
@@ -513,7 +516,7 @@ restart:
 	/*
 	 * Wipe out old UFS1 superblock(s) if necessary.
 	 */
-	if (!Nflag && Oflag != 1) {
+	if (!Nflag && Oflag != 1 && realsectorsize <= SBLOCK_UFS1) {
 		i = bread(&disk, part_ofs + SBLOCK_UFS1 / disk.d_bsize, chdummy, SBLOCKSIZE);
 		if (i == -1)
 			err(1, "can't read old UFS1 superblock: %s", disk.d_error);
@@ -622,18 +625,20 @@ restart:
 	 * The recovery information only works for UFS2 filesystems.
 	 */
 	if (sblock.fs_magic == FS_UFS2_MAGIC) {
-		i = bread(&disk,
-		    part_ofs + (SBLOCK_UFS2 - sizeof(fsr)) / disk.d_bsize,
-		    (char *)&fsr, sizeof(fsr));
-		if (i == -1)
+		if ((fsrbuf = malloc(realsectorsize)) == NULL || bread(&disk,
+		    part_ofs + (SBLOCK_UFS2 - realsectorsize) / disk.d_bsize,
+		    fsrbuf, realsectorsize) == -1)
 			err(1, "can't read recovery area: %s", disk.d_error);
-		fsr.fsr_magic = sblock.fs_magic;
-		fsr.fsr_fpg = sblock.fs_fpg;
-		fsr.fsr_fsbtodb = sblock.fs_fsbtodb;
-		fsr.fsr_sblkno = sblock.fs_sblkno;
-		fsr.fsr_ncg = sblock.fs_ncg;
-		wtfs((SBLOCK_UFS2 - sizeof(fsr)) / disk.d_bsize, sizeof(fsr),
-		    (char *)&fsr);
+		fsr =
+		    (struct fsrecovery *)&fsrbuf[realsectorsize - sizeof *fsr];
+		fsr->fsr_magic = sblock.fs_magic;
+		fsr->fsr_fpg = sblock.fs_fpg;
+		fsr->fsr_fsbtodb = sblock.fs_fsbtodb;
+		fsr->fsr_sblkno = sblock.fs_sblkno;
+		fsr->fsr_ncg = sblock.fs_ncg;
+		wtfs((SBLOCK_UFS2 - realsectorsize) / disk.d_bsize,
+		    realsectorsize, fsrbuf);
+		free(fsrbuf);
 	}
 	/*
 	 * Update information about this partition in pack

Modified: stable/11/sys/ufs/ffs/fs.h
==============================================================================
--- stable/11/sys/ufs/ffs/fs.h	Mon Jan 20 04:01:35 2020	(r356904)
+++ stable/11/sys/ufs/ffs/fs.h	Mon Jan 20 08:28:54 2020	(r356905)
@@ -238,9 +238,7 @@ struct fsck_cmd {
  * A recovery structure placed at the end of the boot block area by newfs
  * that can be used by fsck to search for alternate superblocks.
  */
-#define RESID	(4096 - 20)	/* disk sector size minus recovery area size */
 struct fsrecovery {
-	char	block[RESID];	/* unused part of sector */
 	int32_t	fsr_magic;	/* magic number */
 	int32_t	fsr_fsbtodb;	/* fsbtodb and dbtofsb shift constant */
 	int32_t	fsr_sblkno;	/* offset of super-block in filesys */



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