Refactoring of reading and writing of the UFS/FFS superblock.
Specifically reading is done if ffs_sbget() and writing is done in ffs_sbput(). These functions are exported to libufs via the sbget() and sbput() functions which then used in the various filesystem utilities. This work is in preparation for adding subperblock check hashes. No functional change intended. Reviewed by: kib
This commit is contained in:
+51
-74
@@ -66,6 +66,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <paths.h>
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <fstab.h>
|
||||
#include <inttypes.h>
|
||||
@@ -95,12 +96,6 @@ static union {
|
||||
#define sblock fsun1.fs /* the new superblock */
|
||||
#define osblock fsun2.fs /* the old superblock */
|
||||
|
||||
/*
|
||||
* Possible superblock locations ordered from most to least likely.
|
||||
*/
|
||||
static int sblock_try[] = SBLOCKSEARCH;
|
||||
static ufs2_daddr_t sblockloc;
|
||||
|
||||
static union {
|
||||
struct cg cg;
|
||||
char pad[MAXBSIZE];
|
||||
@@ -156,11 +151,10 @@ growfs(int fsi, int fso, unsigned int Nflag)
|
||||
fscs = (struct csum *)calloc((size_t)1, (size_t)sblock.fs_cssize);
|
||||
if (fscs == NULL)
|
||||
errx(1, "calloc failed");
|
||||
for (i = 0; i < osblock.fs_cssize; i += osblock.fs_bsize) {
|
||||
rdfs(fsbtodb(&osblock, osblock.fs_csaddr +
|
||||
numfrags(&osblock, i)), (size_t)MIN(osblock.fs_cssize - i,
|
||||
osblock.fs_bsize), (void *)(((char *)fscs) + i), fsi);
|
||||
}
|
||||
memcpy(fscs, osblock.fs_csp, osblock.fs_cssize);
|
||||
free(osblock.fs_csp);
|
||||
osblock.fs_csp = NULL;
|
||||
sblock.fs_csp = fscs;
|
||||
|
||||
#ifdef FS_DEBUG
|
||||
{
|
||||
@@ -234,13 +228,41 @@ growfs(int fsi, int fso, unsigned int Nflag)
|
||||
updcsloc(modtime, fsi, fso, Nflag);
|
||||
|
||||
/*
|
||||
* Now write the cylinder summary back to disk.
|
||||
* Clean up the dynamic fields in our superblock.
|
||||
*
|
||||
* XXX
|
||||
* The following fields are currently distributed from the superblock
|
||||
* to the copies:
|
||||
* fs_minfree
|
||||
* fs_rotdelay
|
||||
* fs_maxcontig
|
||||
* fs_maxbpg
|
||||
* fs_minfree,
|
||||
* fs_optim
|
||||
* fs_flags
|
||||
*
|
||||
* We probably should rather change the summary for the cylinder group
|
||||
* statistics here to the value of what would be in there, if the file
|
||||
* system were created initially with the new size. Therefor we still
|
||||
* need to find an easy way of calculating that.
|
||||
* Possibly we can try to read the first superblock copy and apply the
|
||||
* "diffed" stats between the old and new superblock by still copying
|
||||
* certain parameters onto that.
|
||||
*/
|
||||
for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize) {
|
||||
wtfs(fsbtodb(&sblock, sblock.fs_csaddr + numfrags(&sblock, i)),
|
||||
(size_t)MIN(sblock.fs_cssize - i, sblock.fs_bsize),
|
||||
(void *)(((char *)fscs) + i), fso, Nflag);
|
||||
}
|
||||
sblock.fs_time = modtime;
|
||||
sblock.fs_fmod = 0;
|
||||
sblock.fs_clean = 1;
|
||||
sblock.fs_ronly = 0;
|
||||
sblock.fs_cgrotor = 0;
|
||||
sblock.fs_state = 0;
|
||||
memset((void *)&sblock.fs_fsmnt, 0, sizeof(sblock.fs_fsmnt));
|
||||
|
||||
/*
|
||||
* Now write the new superblock, its summary information,
|
||||
* and all the alternates back to disk.
|
||||
*/
|
||||
if (!Nflag && sbput(fso, &sblock, sblock.fs_ncg) != 0)
|
||||
errc(2, EIO, "could not write updated superblock");
|
||||
DBG_PRINT0("fscs written\n");
|
||||
|
||||
#ifdef FS_DEBUG
|
||||
@@ -258,53 +280,9 @@ growfs(int fsi, int fso, unsigned int Nflag)
|
||||
}
|
||||
#endif /* FS_DEBUG */
|
||||
|
||||
/*
|
||||
* Now write the new superblock back to disk.
|
||||
*/
|
||||
sblock.fs_time = modtime;
|
||||
wtfs(sblockloc, (size_t)SBLOCKSIZE, (void *)&sblock, fso, Nflag);
|
||||
DBG_PRINT0("sblock written\n");
|
||||
DBG_DUMP_FS(&sblock, "new initial sblock");
|
||||
|
||||
/*
|
||||
* Clean up the dynamic fields in our superblock copies.
|
||||
*/
|
||||
sblock.fs_fmod = 0;
|
||||
sblock.fs_clean = 1;
|
||||
sblock.fs_ronly = 0;
|
||||
sblock.fs_cgrotor = 0;
|
||||
sblock.fs_state = 0;
|
||||
memset((void *)&sblock.fs_fsmnt, 0, sizeof(sblock.fs_fsmnt));
|
||||
sblock.fs_flags &= FS_DOSOFTDEP;
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* The following fields are currently distributed from the superblock
|
||||
* to the copies:
|
||||
* fs_minfree
|
||||
* fs_rotdelay
|
||||
* fs_maxcontig
|
||||
* fs_maxbpg
|
||||
* fs_minfree,
|
||||
* fs_optim
|
||||
* fs_flags regarding SOFTPDATES
|
||||
*
|
||||
* We probably should rather change the summary for the cylinder group
|
||||
* statistics here to the value of what would be in there, if the file
|
||||
* system were created initially with the new size. Therefor we still
|
||||
* need to find an easy way of calculating that.
|
||||
* Possibly we can try to read the first superblock copy and apply the
|
||||
* "diffed" stats between the old and new superblock by still copying
|
||||
* certain parameters onto that.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Write out the duplicate super blocks.
|
||||
*/
|
||||
for (cylno = 0; cylno < sblock.fs_ncg; cylno++) {
|
||||
wtfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)),
|
||||
(size_t)SBLOCKSIZE, (void *)&sblock, fso, Nflag);
|
||||
}
|
||||
DBG_PRINT0("sblock copies written\n");
|
||||
DBG_DUMP_FS(&sblock, "new other sblocks");
|
||||
|
||||
@@ -1374,11 +1352,12 @@ int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
DBG_FUNC("main")
|
||||
struct fs *fs;
|
||||
const char *device;
|
||||
const struct statfs *statfsp;
|
||||
uint64_t size = 0;
|
||||
off_t mediasize;
|
||||
int error, i, j, fsi, fso, ch, Nflag = 0, yflag = 0;
|
||||
int error, j, fsi, fso, ch, ret, Nflag = 0, yflag = 0;
|
||||
char *p, reply[5], oldsizebuf[6], newsizebuf[6];
|
||||
void *testbuf;
|
||||
|
||||
@@ -1452,19 +1431,17 @@ main(int argc, char **argv)
|
||||
/*
|
||||
* Read the current superblock, and take a backup.
|
||||
*/
|
||||
for (i = 0; sblock_try[i] != -1; i++) {
|
||||
sblockloc = sblock_try[i] / DEV_BSIZE;
|
||||
rdfs(sblockloc, (size_t)SBLOCKSIZE, (void *)&(osblock), fsi);
|
||||
if ((osblock.fs_magic == FS_UFS1_MAGIC ||
|
||||
(osblock.fs_magic == FS_UFS2_MAGIC &&
|
||||
osblock.fs_sblockloc == sblock_try[i])) &&
|
||||
osblock.fs_bsize <= MAXBSIZE &&
|
||||
osblock.fs_bsize >= (int32_t) sizeof(struct fs))
|
||||
break;
|
||||
if ((ret = sbget(fsi, &fs, -1)) != 0) {
|
||||
switch (ret) {
|
||||
case ENOENT:
|
||||
errx(1, "superblock not recognized");
|
||||
default:
|
||||
errc(1, ret, "unable to read superblock");
|
||||
}
|
||||
}
|
||||
if (sblock_try[i] == -1)
|
||||
errx(1, "superblock not recognized");
|
||||
memcpy((void *)&fsun1, (void *)&fsun2, sizeof(fsun2));
|
||||
memcpy(&osblock, fs, fs->fs_sbsize);
|
||||
free(fs);
|
||||
memcpy((void *)&fsun1, (void *)&fsun2, osblock.fs_sbsize);
|
||||
|
||||
DBG_OPEN("/tmp/growfs.debug"); /* already here we need a superblock */
|
||||
DBG_DUMP_FS(&sblock, "old sblock");
|
||||
|
||||
Reference in New Issue
Block a user