Move the pointers stored in the superblock into a separate

fs_summary_info structure. This change was originally done
by the CheriBSD project as they need larger pointers that
do not fit in the existing superblock.

This cleanup of the superblock eases the task of the commit
that immediately follows this one.

Suggested by: brooks
Reviewed by:  kib
PR:           246983
Sponsored by: Netflix
This commit is contained in:
Kirk McKusick 2020-06-19 01:02:53 +00:00
parent 349eddbd07
commit 34816cb9ae
10 changed files with 92 additions and 32 deletions

View File

@ -134,6 +134,10 @@ mkfs(struct partition *pp, char *fsys)
utime = 1000000000;
else
time(&utime);
if ((sblock.fs_si = malloc(sizeof(struct fs_summary_info))) == NULL) {
printf("Superblock summary info allocation failed.\n");
exit(18);
}
sblock.fs_old_flags = FS_FLAGS_UPDATED;
sblock.fs_flags = 0;
if (Uflag)
@ -548,6 +552,10 @@ mkfs(struct partition *pp, char *fsys)
}
}
}
/*
* Reference the summary information so it will also be written.
*/
sblock.fs_csp = fscs;
if (!Nflag && sbput(disk.d_fd, &disk.d_fs, 0) != 0)
err(1, "sbput: %s", disk.d_error);
if (Xflag == 1) {
@ -611,10 +619,6 @@ mkfs(struct partition *pp, char *fsys)
printf("** Exiting on Xflag 3\n");
exit(0);
}
/*
* Reference the summary information so it will also be written.
*/
sblock.fs_csp = fscs;
if (sbput(disk.d_fd, &disk.d_fs, 0) != 0)
err(1, "sbput: %s", disk.d_error);
/*

View File

@ -678,7 +678,11 @@ ufs_open(upath, f)
if (rc) {
if (fp->f_buf)
free(fp->f_buf);
free(fp->f_fs);
if (fp->f_fs != NULL) {
free(fp->f_fs->fs_csp);
free(fp->f_fs->fs_si);
free(fp->f_fs);
}
free(fp);
}
return (rc);
@ -723,7 +727,11 @@ ufs_close(f)
}
if (fp->f_buf)
free(fp->f_buf);
free(fp->f_fs);
if (fp->f_fs != NULL) {
free(fp->f_fs->fs_csp);
free(fp->f_fs->fs_si);
free(fp->f_fs);
}
free(fp);
return (0);
}

View File

@ -68,6 +68,7 @@ g_journal_ufs_clean(struct mount *mp)
static void
g_journal_ufs_dirty(struct g_consumer *cp)
{
struct fs_summary_info *fs_si;
struct fs *fs;
int error;
@ -83,8 +84,12 @@ g_journal_ufs_dirty(struct g_consumer *cp)
GJ_DEBUG(0, "clean=%d flags=0x%x", fs->fs_clean, fs->fs_flags);
fs->fs_clean = 0;
fs->fs_flags |= FS_NEEDSFSCK | FS_UNCLEAN;
fs_si = fs->fs_si;
fs->fs_si = NULL;
error = ffs_sbput(cp, fs, fs->fs_sblockloc, g_use_g_write_data);
fs->fs_si = fs_si;
g_free(fs->fs_csp);
g_free(fs->fs_si);
g_free(fs);
if (error != 0) {
GJ_DEBUG(0, "Cannot mark file system %s as dirty "

View File

@ -122,6 +122,7 @@ g_label_ufs_taste_common(struct g_consumer *cp, char *label, size_t size, int wh
}
out:
g_free(fs->fs_csp);
g_free(fs->fs_si);
g_free(fs);
}

View File

@ -480,6 +480,8 @@ ffs_snapshot(mp, snapfile)
*/
copy_fs = malloc((u_long)fs->fs_bsize, M_UFSMNT, M_WAITOK);
bcopy(fs, copy_fs, fs->fs_sbsize);
copy_fs->fs_si = malloc(sizeof(struct fs_summary_info), M_UFSMNT,
M_ZERO | M_WAITOK);
if ((fs->fs_flags & (FS_UNCLEAN | FS_NEEDSFSCK)) == 0)
copy_fs->fs_clean = 1;
size = fs->fs_bsize < SBLOCKSIZE ? fs->fs_bsize : SBLOCKSIZE;
@ -501,6 +503,7 @@ ffs_snapshot(mp, snapfile)
len, KERNCRED, &bp)) != 0) {
brelse(bp);
free(copy_fs->fs_csp, M_UFSMNT);
free(copy_fs->fs_si, M_UFSMNT);
free(copy_fs, M_UFSMNT);
copy_fs = NULL;
goto out1;
@ -611,6 +614,7 @@ ffs_snapshot(mp, snapfile)
vdrop(xvp);
if (error) {
free(copy_fs->fs_csp, M_UFSMNT);
free(copy_fs->fs_si, M_UFSMNT);
free(copy_fs, M_UFSMNT);
copy_fs = NULL;
MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp);
@ -624,6 +628,7 @@ ffs_snapshot(mp, snapfile)
error = softdep_journal_lookup(mp, &xvp);
if (error) {
free(copy_fs->fs_csp, M_UFSMNT);
free(copy_fs->fs_si, M_UFSMNT);
free(copy_fs, M_UFSMNT);
copy_fs = NULL;
goto out1;
@ -842,6 +847,7 @@ ffs_snapshot(mp, snapfile)
}
done:
free(copy_fs->fs_csp, M_UFSMNT);
free(copy_fs->fs_si, M_UFSMNT);
free(copy_fs, M_UFSMNT);
copy_fs = NULL;
out:

View File

@ -158,6 +158,7 @@ ffs_sbget(void *devfd, struct fs **fsp, off_t altsblock,
int (*readfunc)(void *devfd, off_t loc, void **bufp, int size))
{
struct fs *fs;
struct fs_summary_info *fs_si;
int i, error, size, blks;
uint8_t *space;
int32_t *lp;
@ -201,7 +202,14 @@ ffs_sbget(void *devfd, struct fs **fsp, off_t altsblock,
size += fs->fs_ncg * sizeof(int32_t);
size += fs->fs_ncg * sizeof(u_int8_t);
/* When running in libufs or libsa, UFS_MALLOC may fail */
if ((fs_si = UFS_MALLOC(sizeof(*fs_si), filltype, M_WAITOK)) == NULL) {
UFS_FREE(fs, filltype);
return (ENOSPC);
}
bzero(fs_si, sizeof(*fs_si));
fs->fs_si = fs_si;
if ((space = UFS_MALLOC(size, filltype, M_WAITOK)) == NULL) {
UFS_FREE(fs->fs_si, filltype);
UFS_FREE(fs, filltype);
return (ENOSPC);
}
@ -217,6 +225,7 @@ ffs_sbget(void *devfd, struct fs **fsp, off_t altsblock,
if (buf != NULL)
UFS_FREE(buf, filltype);
UFS_FREE(fs->fs_csp, filltype);
UFS_FREE(fs->fs_si, filltype);
UFS_FREE(fs, filltype);
return (error);
}
@ -299,7 +308,7 @@ readsuper(void *devfd, struct fs **fsp, off_t sblockloc, int isaltsblk,
/* Have to set for old filesystems that predate this field */
fs->fs_sblockactualloc = sblockloc;
/* Not yet any summary information */
fs->fs_csp = NULL;
fs->fs_si = NULL;
return (0);
}
return (ENOENT);
@ -325,7 +334,7 @@ ffs_sbput(void *devfd, struct fs *fs, off_t loc,
* If there is summary information, write it first, so if there
* is an error, the superblock will not be marked as clean.
*/
if (fs->fs_csp != NULL) {
if (fs->fs_si != NULL && fs->fs_csp != NULL) {
blks = howmany(fs->fs_cssize, fs->fs_fsize);
space = (uint8_t *)fs->fs_csp;
for (i = 0; i < blks; i += fs->fs_frag) {

View File

@ -885,14 +885,11 @@ ffs_reload(struct mount *mp, struct thread *td, int flags)
return (EIO); /* XXX needs translation */
}
/*
* Copy pointer fields back into superblock before copying in XXX
* new superblock. These should really be in the ufsmount. XXX
* Note that important parameters (eg fs_ncg) are unchanged.
* Preserve the summary information, read-only status, and
* superblock location by copying these fields into our new
* superblock before using it to update the existing superblock.
*/
newfs->fs_csp = fs->fs_csp;
newfs->fs_maxcluster = fs->fs_maxcluster;
newfs->fs_contigdirs = fs->fs_contigdirs;
newfs->fs_active = fs->fs_active;
newfs->fs_si = fs->fs_si;
newfs->fs_ronly = fs->fs_ronly;
sblockloc = fs->fs_sblockloc;
bcopy(newfs, fs, (u_int)fs->fs_sbsize);
@ -1309,6 +1306,7 @@ ffs_mountfs(odevvp, mp, td)
out:
if (fs != NULL) {
free(fs->fs_csp, M_UFSMNT);
free(fs->fs_si, M_UFSMNT);
free(fs, M_UFSMNT);
}
if (cp != NULL) {
@ -1546,6 +1544,7 @@ ffs_unmount(mp, mntflags)
mp->mnt_gjprovider = NULL;
}
free(fs->fs_csp, M_UFSMNT);
free(fs->fs_si, M_UFSMNT);
free(fs, M_UFSMNT);
if (ump->um_fsfail_task != NULL)
free(ump->um_fsfail_task, M_UFSMNT);
@ -2294,10 +2293,7 @@ ffs_use_bwrite(void *devfd, off_t loc, void *buf, int size)
bcopy((caddr_t)fs, bp->b_data, (u_int)fs->fs_sbsize);
fs = (struct fs *)bp->b_data;
ffs_oldfscompat_write(fs, ump);
/*
* Because we may have made changes to the superblock, we need to
* recompute its check-hash.
*/
/* Recalculate the superblock hash */
fs->fs_ckhash = ffs_calc_sbhash(fs);
if (devfdp->suspended)
bp->b_flags |= B_VALIDSUSPWRT;

View File

@ -132,16 +132,18 @@
* of pointers to blocks of struct csum; now there are just a few
* pointers and the remaining space is padded with fs_ocsp[].
*
* NOCSPTRS determines the size of this padding. One pointer (fs_csp)
* is taken away to point to a contiguous array of struct csum for
* all cylinder groups; a second (fs_maxcluster) points to an array
* of cluster sizes that is computed as cylinder groups are inspected,
* and the third points to an array that tracks the creation of new
* directories. A fourth pointer, fs_active, is used when creating
* snapshots; it points to a bitmap of cylinder groups for which the
* free-block bitmap has changed since the snapshot operation began.
* NOCSPTRS determines the size of this padding. Historically this
* space was used to store pointers to structures that summaried
* filesystem usage and layout information. However, these pointers
* left various kernel pointers in the superblock which made otherwise
* identical superblocks appear to have differences. So, all the
* pointers in the superblock were moved to a fs_summary_info structure
* reducing the superblock to having only a single pointer to this
* structure. When writing the superblock to disk, this pointer is
* temporarily NULL'ed out so that the kernel pointer will not appear
* in the on-disk copy of the superblock.
*/
#define NOCSPTRS ((128 / sizeof(void *)) - 4)
#define NOCSPTRS ((128 / sizeof(void *)) - 1)
/*
* A summary of contiguous blocks of various sizes is maintained
@ -269,6 +271,32 @@ struct csum_total {
int64_t cs_spare[3]; /* future expansion */
};
/*
* Pointers to super block summary information. Placed in a separate
* structure so there is just one pointer in the superblock.
*
* The pointers in this structure are used as follows:
* fs_contigdirs references an array that tracks the creation of new
* directories
* fs_csp references a contiguous array of struct csum for
* all cylinder groups
* fs_maxcluster references an array of cluster sizes that is computed
* as cylinder groups are inspected
* fs_active is used when creating snapshots; it points to a bitmap
* of cylinder groups for which the free-block bitmap has changed
* since the snapshot operation began.
*/
struct fs_summary_info {
uint8_t *si_contigdirs; /* (u) # of contig. allocated dirs */
struct csum *si_csp; /* (u) cg summary info buffer */
int32_t *si_maxcluster; /* (u) max cluster in each cyl group */
u_int *si_active; /* (u) used by snapshots to track fs */
};
#define fs_contigdirs fs_si->si_contigdirs
#define fs_csp fs_si->si_csp
#define fs_maxcluster fs_si->si_maxcluster
#define fs_active fs_si->si_active
/*
* Super block for an FFS filesystem.
*/
@ -340,10 +368,7 @@ struct fs {
/* these fields retain the current block allocation info */
int32_t fs_cgrotor; /* last cg searched */
void *fs_ocsp[NOCSPTRS]; /* padding; was list of fs_cs buffers */
u_int8_t *fs_contigdirs; /* (u) # of contig. allocated dirs */
struct csum *fs_csp; /* (u) cg summary info buffer */
int32_t *fs_maxcluster; /* (u) max cluster in each cyl group */
u_int *fs_active; /* (u) used by snapshots to track fs */
struct fs_summary_info *fs_si;/* In-core pointer to summary info */
int32_t fs_old_cpc; /* cyl per cycle in postbl */
int32_t fs_maxbsize; /* maximum blocking factor permitted */
int64_t fs_unrefs; /* number of unreferenced inodes */

View File

@ -53,6 +53,9 @@ fstyp_ufs(FILE *fp, char *label, size_t labelsize)
switch (sbget(fileno(fp), &fs, STDSB)) {
case 0:
strlcpy(label, fs->fs_volname, labelsize);
free(fs->fs_csp);
free(fs->fs_si);
free(fs);
return (0);
case ENOENT:
/* Cannot find file system superblock */

View File

@ -567,6 +567,9 @@ quot(char *name, char *mp)
printf(" (%s)",mp);
putchar('\n');
(*func)(fd, fs, name);
free(fs->fs_csp);
free(fs->fs_si);
free(fs);
close(fd);
}