summaryrefslogtreecommitdiffstats
path: root/sbin
diff options
context:
space:
mode:
authormckusick <mckusick@FreeBSD.org>2017-08-24 21:44:23 +0000
committermckusick <mckusick@FreeBSD.org>2017-08-24 21:44:23 +0000
commite2240f7f771e75e26d2b84c54a692d95802ac3c4 (patch)
treee3258b205c3cffde490a1746483c3f1587f4222f /sbin
parent5038efc5dafbefffcb449c1b3827b7fcd23183ac (diff)
downloadFreeBSD-src-e2240f7f771e75e26d2b84c54a692d95802ac3c4.zip
FreeBSD-src-e2240f7f771e75e26d2b84c54a692d95802ac3c4.tar.gz
MFC of 276737, 322200, 322201, 322271, and 322297
276737: Remove old ioctl use and support 322200: Remove (broken) search for alternate superblocks 322201: Show differences when alternate superblock fails to match 322271: Cleanup for 322200. 322297: Restore fsck_ffs ability to find alternate superblocks Discussed with: kib, imp Differential Revision: https://reviews.freebsd.org/D11589 Approved by: re (kib)
Diffstat (limited to 'sbin')
-rw-r--r--sbin/fsck_ffs/setup.c211
-rw-r--r--sbin/fsirand/fsirand.c11
-rw-r--r--sbin/newfs/mkfs.c20
-rw-r--r--sbin/newfs/newfs.c30
-rw-r--r--sbin/newfs_msdos/newfs_msdos.c38
5 files changed, 141 insertions, 169 deletions
diff --git a/sbin/fsck_ffs/setup.c b/sbin/fsck_ffs/setup.c
index 7bcaf13..12f6f0a 100644
--- a/sbin/fsck_ffs/setup.c
+++ b/sbin/fsck_ffs/setup.c
@@ -58,9 +58,9 @@ struct bufarea asblk;
#define altsblock (*asblk.b_un.b_fs)
#define POWEROF2(num) (((num) & ((num) - 1)) == 0)
-static void badsb(int listerr, const char *s);
static int calcsb(char *dev, int devfd, struct fs *fs);
-static struct disklabel *getdisklabel(char *s, int fd);
+static void saverecovery(int readfd, int writefd);
+static int chkrecovery(int devfd);
/*
* Read in a superblock finding an alternate if necessary.
@@ -236,6 +236,10 @@ setup(char *dev)
memmove(&altsblock, &sblock, (size_t)sblock.fs_sbsize);
flush(fswritefd, &asblk);
}
+ if (preen == 0 && yflag == 0 && sblock.fs_magic == FS_UFS2_MAGIC &&
+ fswritefd != -1 && chkrecovery(fsreadfd) == 0 &&
+ reply("SAVE DATA TO FIND ALTERNATE SUPERBLOCKS") != 0)
+ saverecovery(fsreadfd, fswritefd);
/*
* read in the summary info.
*/
@@ -319,7 +323,7 @@ int
readsb(int listerr)
{
ufs2_daddr_t super;
- int i;
+ int i, bad;
if (bflag) {
super = bflag;
@@ -369,39 +373,56 @@ readsb(int listerr)
dev_bsize = sblock.fs_fsize / fsbtodb(&sblock, 1);
sblk.b_bno = super / dev_bsize;
sblk.b_size = SBLOCKSIZE;
- if (bflag)
- goto out;
/*
* Compare all fields that should not differ in alternate super block.
* When an alternate super-block is specified this check is skipped.
*/
+ if (bflag)
+ goto out;
getblk(&asblk, cgsblock(&sblock, sblock.fs_ncg - 1), sblock.fs_sbsize);
if (asblk.b_errs)
return (0);
- if (altsblock.fs_sblkno != sblock.fs_sblkno ||
- altsblock.fs_cblkno != sblock.fs_cblkno ||
- altsblock.fs_iblkno != sblock.fs_iblkno ||
- altsblock.fs_dblkno != sblock.fs_dblkno ||
- altsblock.fs_ncg != sblock.fs_ncg ||
- altsblock.fs_bsize != sblock.fs_bsize ||
- altsblock.fs_fsize != sblock.fs_fsize ||
- altsblock.fs_frag != sblock.fs_frag ||
- altsblock.fs_bmask != sblock.fs_bmask ||
- altsblock.fs_fmask != sblock.fs_fmask ||
- altsblock.fs_bshift != sblock.fs_bshift ||
- altsblock.fs_fshift != sblock.fs_fshift ||
- altsblock.fs_fragshift != sblock.fs_fragshift ||
- altsblock.fs_fsbtodb != sblock.fs_fsbtodb ||
- altsblock.fs_sbsize != sblock.fs_sbsize ||
- altsblock.fs_nindir != sblock.fs_nindir ||
- altsblock.fs_inopb != sblock.fs_inopb ||
- altsblock.fs_cssize != sblock.fs_cssize ||
- altsblock.fs_ipg != sblock.fs_ipg ||
- altsblock.fs_fpg != sblock.fs_fpg ||
- altsblock.fs_magic != sblock.fs_magic) {
- badsb(listerr,
- "VALUES IN SUPER BLOCK DISAGREE WITH THOSE IN FIRST ALTERNATE");
- return (0);
+ bad = 0;
+#define CHK(x, y) \
+ if (altsblock.x != sblock.x) { \
+ bad++; \
+ if (listerr && debug) \
+ printf("SUPER BLOCK VS ALTERNATE MISMATCH %s: " y " vs " y "\n", \
+ #x, (intmax_t)sblock.x, (intmax_t)altsblock.x); \
+ }
+ CHK(fs_sblkno, "%jd");
+ CHK(fs_cblkno, "%jd");
+ CHK(fs_iblkno, "%jd");
+ CHK(fs_dblkno, "%jd");
+ CHK(fs_ncg, "%jd");
+ CHK(fs_bsize, "%jd");
+ CHK(fs_fsize, "%jd");
+ CHK(fs_frag, "%jd");
+ CHK(fs_bmask, "%#jx");
+ CHK(fs_fmask, "%#jx");
+ CHK(fs_bshift, "%jd");
+ CHK(fs_fshift, "%jd");
+ CHK(fs_fragshift, "%jd");
+ CHK(fs_fsbtodb, "%jd");
+ CHK(fs_sbsize, "%jd");
+ CHK(fs_nindir, "%jd");
+ CHK(fs_inopb, "%jd");
+ CHK(fs_cssize, "%jd");
+ CHK(fs_ipg, "%jd");
+ CHK(fs_fpg, "%jd");
+ CHK(fs_magic, "%#jx");
+#undef CHK
+ if (bad) {
+ if (listerr == 0)
+ return (0);
+ if (preen)
+ printf("%s: ", cdevname);
+ printf(
+ "VALUES IN SUPER BLOCK LSB=%jd DISAGREE WITH THOSE IN\n"
+ "LAST ALTERNATE LSB=%jd\n",
+ sblk.b_bno, asblk.b_bno);
+ if (reply("IGNORE ALTERNATE SUPER BLOCK") == 0)
+ return (0);
}
out:
/*
@@ -423,21 +444,9 @@ out:
return (1);
}
-static void
-badsb(int listerr, const char *s)
-{
-
- if (!listerr)
- return;
- if (preen)
- printf("%s: ", cdevname);
- pfatal("BAD SUPER BLOCK: %s\n", s);
-}
-
void
sblock_init(void)
{
- struct disklabel *lp;
fswritefd = -1;
fsmodified = 0;
@@ -448,14 +457,11 @@ sblock_init(void)
asblk.b_un.b_buf = Malloc(SBLOCKSIZE);
if (sblk.b_un.b_buf == NULL || asblk.b_un.b_buf == NULL)
errx(EEXIT, "cannot allocate space for superblock");
- if ((lp = getdisklabel(NULL, fsreadfd)))
- real_dev_bsize = dev_bsize = secsize = lp->d_secsize;
- else
- dev_bsize = secsize = DEV_BSIZE;
+ dev_bsize = secsize = DEV_BSIZE;
}
/*
- * Calculate a prototype superblock based on information in the disk label.
+ * Calculate a prototype superblock based on information in the boot area.
* When done the cgsblock macro can be calculated and the fs_ncg field
* can be used. Do NOT attempt to use other macros without verifying that
* their needed information is available!
@@ -463,74 +469,63 @@ sblock_init(void)
static int
calcsb(char *dev, int devfd, struct fs *fs)
{
- struct disklabel *lp;
- struct partition *pp;
- char *cp;
- int i, nspf;
+ struct fsrecovery fsr;
- cp = strchr(dev, '\0') - 1;
- if (cp == (char *)-1 || ((*cp < 'a' || *cp > 'h') && !isdigit(*cp))) {
- pfatal("%s: CANNOT FIGURE OUT FILE SYSTEM PARTITION\n", dev);
- return (0);
- }
- lp = getdisklabel(dev, devfd);
- if (isdigit(*cp))
- pp = &lp->d_partitions[0];
- else
- pp = &lp->d_partitions[*cp - 'a'];
- if (pp->p_fstype != FS_BSDFFS) {
- pfatal("%s: NOT LABELED AS A BSD FILE SYSTEM (%s)\n",
- dev, pp->p_fstype < FSMAXTYPES ?
- fstypenames[pp->p_fstype] : "unknown");
- return (0);
- }
- if (pp->p_fsize == 0 || pp->p_frag == 0 ||
- pp->p_cpg == 0 || pp->p_size == 0) {
- pfatal("%s: %s: type %s fsize %d, frag %d, cpg %d, size %d\n",
- dev, "INCOMPLETE LABEL", fstypenames[pp->p_fstype],
- pp->p_fsize, pp->p_frag, pp->p_cpg, pp->p_size);
+ /*
+ * We need fragments-per-group and the partition-size.
+ *
+ * Newfs stores these details at the end of the boot block area
+ * at the start of the filesystem partition. If they have been
+ * 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)
return (0);
- }
memset(fs, 0, sizeof(struct fs));
- fs->fs_fsize = pp->p_fsize;
- fs->fs_frag = pp->p_frag;
- fs->fs_size = pp->p_size;
- fs->fs_sblkno = roundup(
- howmany(lp->d_bbsize + lp->d_sbsize, fs->fs_fsize),
- fs->fs_frag);
- nspf = fs->fs_fsize / lp->d_secsize;
- for (fs->fs_fsbtodb = 0, i = nspf; i > 1; i >>= 1)
- fs->fs_fsbtodb++;
- dev_bsize = lp->d_secsize;
- if (fs->fs_magic == FS_UFS2_MAGIC) {
- fs->fs_fpg = pp->p_cpg;
- fs->fs_ncg = howmany(fs->fs_size, fs->fs_fpg);
- } else /* if (fs->fs_magic == FS_UFS1_MAGIC) */ {
- fs->fs_old_cpg = pp->p_cpg;
- fs->fs_old_cgmask = 0xffffffff;
- for (i = lp->d_ntracks; i > 1; i >>= 1)
- fs->fs_old_cgmask <<= 1;
- if (!POWEROF2(lp->d_ntracks))
- fs->fs_old_cgmask <<= 1;
- fs->fs_old_cgoffset = roundup(howmany(lp->d_nsectors, nspf),
- fs->fs_frag);
- fs->fs_fpg = (fs->fs_old_cpg * lp->d_secpercyl) / nspf;
- fs->fs_ncg = howmany(fs->fs_size / lp->d_secpercyl,
- fs->fs_old_cpg);
- }
+ 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;
return (1);
}
-static struct disklabel *
-getdisklabel(char *s, int fd)
+/*
+ * Check to see if recovery information exists.
+ */
+static int
+chkrecovery(int devfd)
{
- static struct disklabel lab;
+ struct fsrecovery fsr;
- if (ioctl(fd, DIOCGDINFO, (char *)&lab) < 0) {
- if (s == NULL)
- return ((struct disklabel *)NULL);
- pwarn("ioctl (GCINFO): %s\n", strerror(errno));
- errx(EEXIT, "%s: can't read disk label", s);
- }
- return (&lab);
+ if (blread(devfd, (char *)&fsr,
+ (SBLOCK_UFS2 - sizeof(fsr)) / dev_bsize, sizeof(fsr)) ||
+ fsr.fsr_magic != FS_UFS2_MAGIC)
+ return (0);
+ return (1);
+}
+
+/*
+ * Read the last sector of the boot block, replace the last
+ * 20 bytes with the recovery information, then write it back.
+ * The recovery information only works for UFS2 filesystems.
+ */
+static void
+saverecovery(int readfd, int writefd)
+{
+ struct fsrecovery fsr;
+
+ if (sblock.fs_magic != FS_UFS2_MAGIC ||
+ blread(readfd, (char *)&fsr,
+ (SBLOCK_UFS2 - sizeof(fsr)) / dev_bsize, sizeof(fsr)))
+ 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));
}
diff --git a/sbin/fsirand/fsirand.c b/sbin/fsirand/fsirand.c
index c373c5b..0fea239 100644
--- a/sbin/fsirand/fsirand.c
+++ b/sbin/fsirand/fsirand.c
@@ -36,7 +36,6 @@ static const char rcsid[] =
#endif /* not lint */
#include <sys/param.h>
-#include <sys/disklabel.h>
#include <sys/resource.h>
#include <ufs/ufs/dinode.h>
@@ -120,22 +119,12 @@ fsirand(char *device)
char sbuf[SBLOCKSIZE], sbuftmp[SBLOCKSIZE];
int i, devfd, n, cg;
u_int32_t bsize = DEV_BSIZE;
- struct disklabel label;
if ((devfd = open(device, printonly ? O_RDONLY : O_RDWR)) < 0) {
warn("can't open %s", device);
return (1);
}
- /* Get block size (usually 512) from disklabel if possible */
- if (!ignorelabel) {
- if (ioctl(devfd, DIOCGDINFO, &label) < 0)
- warn("can't read disklabel, using sector size of %d",
- bsize);
- else
- bsize = label.d_secsize;
- }
-
dp1 = NULL;
dp2 = NULL;
diff --git a/sbin/newfs/mkfs.c b/sbin/newfs/mkfs.c
index 168d81a..589ba8d 100644
--- a/sbin/newfs/mkfs.c
+++ b/sbin/newfs/mkfs.c
@@ -121,6 +121,7 @@ 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;
union {
struct fs fdummy;
char cdummy[SBLOCKSIZE];
@@ -619,6 +620,25 @@ restart:
sblock.fs_cssize - i : sblock.fs_bsize,
((char *)fscs) + i);
/*
+ * Read the last sector of the boot block, replace the last
+ * 20 bytes with the recovery information, then write it back.
+ * 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)
+ 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);
+ }
+ /*
* Update information about this partition in pack
* label, to that it may be updated on disk.
*/
diff --git a/sbin/newfs/newfs.c b/sbin/newfs/newfs.c
index 7662474..fbb0a1c 100644
--- a/sbin/newfs/newfs.c
+++ b/sbin/newfs/newfs.c
@@ -117,11 +117,9 @@ static u_char bootarea[BBSIZE];
static int is_file; /* work on a file, not a device */
static char *dkname;
static char *disktype;
-static int unlabeled;
static void getfssize(intmax_t *, const char *p, intmax_t, intmax_t);
static struct disklabel *getdisklabel(char *s);
-static void rewritelabel(char *s, struct disklabel *lp);
static void usage(void);
static int expand_number_int(const char *buf, int *num);
@@ -403,12 +401,6 @@ main(int argc, char *argv[])
pp->p_size *= secperblk;
}
mkfs(pp, special);
- if (!unlabeled) {
- if (realsectorsize != DEV_BSIZE)
- pp->p_size /= realsectorsize / DEV_BSIZE;
- if (!Nflag && bcmp(pp, &oldpartition, sizeof(oldpartition)))
- rewritelabel(special, lp);
- }
ufs_disk_close(&disk);
if (!jflag)
exit(0);
@@ -452,9 +444,6 @@ getdisklabel(char *s)
return &lab;
}
- if (ioctl(disk.d_fd, DIOCGDINFO, (char *)&lab) != -1)
- return (&lab);
- unlabeled++;
if (disktype) {
lp = getdiskbyname(disktype);
if (lp != NULL)
@@ -463,25 +452,6 @@ getdisklabel(char *s)
return (NULL);
}
-void
-rewritelabel(char *s, struct disklabel *lp)
-{
- if (unlabeled)
- return;
- lp->d_checksum = 0;
- lp->d_checksum = dkcksum(lp);
- if (is_file) {
- bsd_disklabel_le_enc(bootarea + 0 /* labeloffset */ +
- 1 /* labelsoffset */ * sectorsize, lp);
- lseek(disk.d_fd, 0, SEEK_SET);
- if (write(disk.d_fd, bootarea, BBSIZE) != BBSIZE)
- errx(1, "cannot write label");
- return;
- }
- if (ioctl(disk.d_fd, DIOCWDINFO, (char *)lp) == -1)
- warn("ioctl (WDINFO): %s: can't rewrite disk label", s);
-}
-
static void
usage()
{
diff --git a/sbin/newfs_msdos/newfs_msdos.c b/sbin/newfs_msdos/newfs_msdos.c
index f315d98..4685782 100644
--- a/sbin/newfs_msdos/newfs_msdos.c
+++ b/sbin/newfs_msdos/newfs_msdos.c
@@ -829,28 +829,26 @@ getdiskinfo(int fd, const char *fname, const char *dtype, __unused int oflag,
if (lp == NULL) {
if (bpb->bpbBytesPerSec)
dlp.d_secsize = bpb->bpbBytesPerSec;
- if (ioctl(fd, DIOCGDINFO, &dlp) == -1) {
- if (bpb->bpbBytesPerSec == 0 && ioctl(fd, DIOCGSECTORSIZE,
- &dlp.d_secsize) == -1)
- err(1, "cannot get sector size");
+ if (bpb->bpbBytesPerSec == 0 && ioctl(fd, DIOCGSECTORSIZE,
+ &dlp.d_secsize) == -1)
+ err(1, "cannot get sector size");
- dlp.d_secperunit = ms / dlp.d_secsize;
+ dlp.d_secperunit = ms / dlp.d_secsize;
- if (bpb->bpbSecPerTrack == 0 && ioctl(fd, DIOCGFWSECTORS,
- &dlp.d_nsectors) == -1) {
- warn("cannot get number of sectors per track");
- dlp.d_nsectors = 63;
- }
- if (bpb->bpbHeads == 0 &&
- ioctl(fd, DIOCGFWHEADS, &dlp.d_ntracks) == -1) {
- warn("cannot get number of heads");
- if (dlp.d_secperunit <= 63*1*1024)
- dlp.d_ntracks = 1;
- else if (dlp.d_secperunit <= 63*16*1024)
- dlp.d_ntracks = 16;
- else
- dlp.d_ntracks = 255;
- }
+ if (bpb->bpbSecPerTrack == 0 && ioctl(fd, DIOCGFWSECTORS,
+ &dlp.d_nsectors) == -1) {
+ warn("cannot get number of sectors per track");
+ dlp.d_nsectors = 63;
+ }
+ if (bpb->bpbHeads == 0 &&
+ ioctl(fd, DIOCGFWHEADS, &dlp.d_ntracks) == -1) {
+ warn("cannot get number of heads");
+ if (dlp.d_secperunit <= 63*1*1024)
+ dlp.d_ntracks = 1;
+ else if (dlp.d_secperunit <= 63*16*1024)
+ dlp.d_ntracks = 16;
+ else
+ dlp.d_ntracks = 255;
}
hs = (ms / dlp.d_secsize) - dlp.d_secperunit;
OpenPOWER on IntegriCloud