aboutsummaryrefslogtreecommitdiff
path: root/sbin/fsck_ffs/setup.c
diff options
context:
space:
mode:
authorKirk McKusick <mckusick@FreeBSD.org>2017-09-04 20:19:36 +0000
committerKirk McKusick <mckusick@FreeBSD.org>2017-09-04 20:19:36 +0000
commit855662c61184b1e6ffaec8057ad3c41418cb6790 (patch)
tree126d1c27aa92a12bcb89cd2f60e7d564326f0f9e /sbin/fsck_ffs/setup.c
parent77e430c6860d54ff08e044b63bcc2a6683af5359 (diff)
downloadsrc-855662c61184b1e6ffaec8057ad3c41418cb6790.tar.gz
src-855662c61184b1e6ffaec8057ad3c41418cb6790.zip
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. Reported by: Peter Holm Reviewed with: kib
Notes
Notes: svn path=/head/; revision=323157
Diffstat (limited to 'sbin/fsck_ffs/setup.c')
-rw-r--r--sbin/fsck_ffs/setup.c90
1 files changed, 65 insertions, 25 deletions
diff --git a/sbin/fsck_ffs/setup.c b/sbin/fsck_ffs/setup.c
index f97a3fed0f83..62e27053a2b8 100644
--- a/sbin/fsck_ffs/setup.c
+++ b/sbin/fsck_ffs/setup.c
@@ -36,6 +36,7 @@ static const char sccsid[] = "@(#)setup.c 8.10 (Berkeley) 5/9/95";
__FBSDID("$FreeBSD$");
#include <sys/param.h>
+#include <sys/disk.h>
#include <sys/stat.h>
#define FSTYPENAMES
#include <sys/disklabel.h>
@@ -465,7 +466,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.
@@ -475,32 +478,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);
}
/*
@@ -511,17 +544,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);
}