Date: Fri, 12 Jan 2001 23:25:41 +0000 From: Ian Dowse <iedowse@maths.tcd.ie> To: freebsd-fs@FreeBSD.ORG Cc: iedowse@maths.tcd.ie Subject: Re: fsck problem on large vinum volume Message-ID: <200101122325.aa07194@salmon.maths.tcd.ie>
next in thread | raw e-mail | index | archive | help
Here is an updated patch which I shall commit in a few days (Kirk has already said in a private mail that he is in agreement with these changes). This patch modifies the declaration of the 128-byte summary pointer area in the superblock from struct csum *fs_csp[MAXCSBUFS]; int32_t *fs_maxcluster; to void *fs_ocsp[NOCSPTRS]; /* padding */ struct csum *fs_csp; /* cg summary info buffer */ int32_t *fs_maxcluster; and updates all files and utilities to match. A summary of the other changes is: * Use fs_csp to store a pointer to the start of a single contiguous array of cylinder group summary information (struct csum). This is done in the kernel (ffs_vfsops.c, ffs_snapshot.c) and in the userland utilities dumpfs, fsck_ffs, fsck_ifs. * Update the 'fs_cs' macro to access elements in this array directly i.e. as fs_csp[cg] instead of: fs_csp[cg summary block][cg summary block offset] * Add a comment in newfs/mkfs.c to indicate that while fs_csmask and fs_csshift are no longer used, we do need to initialise them for compatibility with old kernels. (Just to be clear before someone asks, this region of the superblock is used only for temporary in-core storage - this change introduces no filesystem compatibility issues). Ian Index: sbin/dumpfs/dumpfs.c =================================================================== RCS file: /FreeBSD/FreeBSD-CVS/src/sbin/dumpfs/dumpfs.c,v retrieving revision 1.13 diff -u -r1.13 dumpfs.c --- sbin/dumpfs/dumpfs.c 1999/08/28 00:12:42 1.13 +++ sbin/dumpfs/dumpfs.c 2001/01/09 22:54:16 @@ -205,15 +205,15 @@ } } printf("\ncs[].cs_(nbfree,ndir,nifree,nffree):\n\t"); + afs.fs_csp = calloc(1, afs.fs_cssize); for (i = 0, j = 0; i < afs.fs_cssize; i += afs.fs_bsize, j++) { size = afs.fs_cssize - i < afs.fs_bsize ? afs.fs_cssize - i : afs.fs_bsize; - afs.fs_csp[j] = calloc(1, size); if (lseek(fd, (off_t)(fsbtodb(&afs, (afs.fs_csaddr + j * afs.fs_frag))) * (off_t)dev_bsize, SEEK_SET) == (off_t)-1) goto err; - if (read(fd, afs.fs_csp[j], size) != size) + if (read(fd, (char *)afs.fs_csp + i, size) != size) goto err; } for (i = 0; i < afs.fs_ncg; i++) { Index: sbin/fsck_ffs/fsutil.c =================================================================== RCS file: /FreeBSD/FreeBSD-CVS/src/sbin/fsck_ffs/fsutil.c,v retrieving revision 1.2 diff -u -r1.2 fsutil.c --- sbin/fsck_ffs/fsutil.c 2000/10/09 09:42:51 1.2 +++ sbin/fsck_ffs/fsutil.c 2001/01/09 22:58:57 @@ -249,7 +249,7 @@ if (bp != &sblk) return; for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) { - bwrite(fswritefd, (char *)sblock.fs_csp[j], + bwrite(fswritefd, (char *)sblock.fs_csp + i, fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag), sblock.fs_cssize - i < sblock.fs_bsize ? sblock.fs_cssize - i : sblock.fs_bsize); Index: sbin/fsck_ffs/setup.c =================================================================== RCS file: /FreeBSD/FreeBSD-CVS/src/sbin/fsck_ffs/setup.c,v retrieving revision 1.18 diff -u -r1.18 setup.c --- sbin/fsck_ffs/setup.c 2000/07/06 02:03:11 1.18 +++ sbin/fsck_ffs/setup.c 2001/01/09 22:57:34 @@ -258,11 +258,11 @@ * read in the summary info. */ asked = 0; + sblock.fs_csp = calloc(1, sblock.fs_cssize); for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) { size = sblock.fs_cssize - i < sblock.fs_bsize ? sblock.fs_cssize - i : sblock.fs_bsize; - sblock.fs_csp[j] = (struct csum *)calloc(1, (unsigned)size); - if (bread(fsreadfd, (char *)sblock.fs_csp[j], + if (bread(fsreadfd, (char *)sblock.fs_csp + i, fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag), size) != 0 && !asked) { pfatal("BAD SUMMARY INFORMATION"); @@ -380,7 +380,8 @@ altsblock.fs_optim = sblock.fs_optim; altsblock.fs_rotdelay = sblock.fs_rotdelay; altsblock.fs_maxbpg = sblock.fs_maxbpg; - memmove(altsblock.fs_csp, sblock.fs_csp, sizeof sblock.fs_csp); + memmove(altsblock.fs_ocsp, sblock.fs_ocsp, sizeof sblock.fs_ocsp); + altsblock.fs_csp = sblock.fs_csp; altsblock.fs_maxcluster = sblock.fs_maxcluster; memmove(altsblock.fs_fsmnt, sblock.fs_fsmnt, sizeof sblock.fs_fsmnt); memmove(altsblock.fs_snapinum, sblock.fs_snapinum, Index: sbin/fsck_ifs/fsutil.c =================================================================== RCS file: /FreeBSD/FreeBSD-CVS/src/sbin/fsck_ifs/fsutil.c,v retrieving revision 1.2 diff -u -r1.2 fsutil.c --- sbin/fsck_ifs/fsutil.c 2000/10/09 09:42:51 1.2 +++ sbin/fsck_ifs/fsutil.c 2001/01/12 19:33:52 @@ -249,7 +249,7 @@ if (bp != &sblk) return; for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) { - bwrite(fswritefd, (char *)sblock.fs_csp[j], + bwrite(fswritefd, (char *)sblock.fs_csp + i, fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag), sblock.fs_cssize - i < sblock.fs_bsize ? sblock.fs_cssize - i : sblock.fs_bsize); Index: sbin/fsck_ifs/setup.c =================================================================== RCS file: /FreeBSD/FreeBSD-CVS/src/sbin/fsck_ifs/setup.c,v retrieving revision 1.19 diff -u -r1.19 setup.c --- sbin/fsck_ifs/setup.c 2000/10/14 02:44:53 1.19 +++ sbin/fsck_ifs/setup.c 2001/01/12 19:35:18 @@ -258,11 +258,11 @@ * read in the summary info. */ asked = 0; + sblock.fs_csp = calloc(1, sblock.fs_cssize); for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) { size = sblock.fs_cssize - i < sblock.fs_bsize ? sblock.fs_cssize - i : sblock.fs_bsize; - sblock.fs_csp[j] = (struct csum *)calloc(1, (unsigned)size); - if (bread(fsreadfd, (char *)sblock.fs_csp[j], + if (bread(fsreadfd, (char *)sblock.fs_csp + i, fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag), size) != 0 && !asked) { pfatal("BAD SUMMARY INFORMATION"); @@ -382,7 +382,8 @@ altsblock.fs_optim = sblock.fs_optim; altsblock.fs_rotdelay = sblock.fs_rotdelay; altsblock.fs_maxbpg = sblock.fs_maxbpg; - memmove(altsblock.fs_csp, sblock.fs_csp, sizeof sblock.fs_csp); + memmove(altsblock.fs_ocsp, sblock.fs_ocsp, sizeof sblock.fs_ocsp); + altsblock.fs_csp = sblock.fs_csp; altsblock.fs_maxcluster = sblock.fs_maxcluster; memmove(altsblock.fs_fsmnt, sblock.fs_fsmnt, sizeof sblock.fs_fsmnt); memmove(altsblock.fs_snapinum, sblock.fs_snapinum, Index: sbin/newfs/mkfs.c =================================================================== RCS file: /FreeBSD/FreeBSD-CVS/src/sbin/newfs/mkfs.c,v retrieving revision 1.32 diff -u -r1.32 mkfs.c --- sbin/newfs/mkfs.c 2000/10/24 03:28:59 1.32 +++ sbin/newfs/mkfs.c 2001/01/12 22:55:00 @@ -633,6 +633,11 @@ sblock.fs_csaddr = cgdmin(&sblock, 0); sblock.fs_cssize = fragroundup(&sblock, sblock.fs_ncg * sizeof(struct csum)); + /* + * The superblock fields 'fs_csmask' and 'fs_csshift' are no + * longer used. However, we still initialise them so that the + * filesystem remains compatible with old kernels. + */ i = sblock.fs_bsize / sizeof(struct csum); sblock.fs_csmask = ~(i - 1); for (sblock.fs_csshift = 0; i > 1; i >>= 1) Index: sys/ufs/ffs/ffs_snapshot.c =================================================================== RCS file: /FreeBSD/FreeBSD-CVS/src/sys/ufs/ffs/ffs_snapshot.c,v retrieving revision 1.8 diff -u -r1.8 ffs_snapshot.c --- sys/ufs/ffs/ffs_snapshot.c 2001/01/12 21:56:55 1.8 +++ sys/ufs/ffs/ffs_snapshot.c 2001/01/12 22:40:25 @@ -83,6 +83,7 @@ int error, cg, snaploc, indiroff, numblks; int i, size, base, len, loc, inoblkcnt; int blksperindir, flag = mp->mnt_flag; + void *space; struct fs *copy_fs, *fs = VFSTOUFS(mp)->um_fs; struct proc *p = CURPROC; struct inode *devip, *ip, *xp; @@ -346,6 +347,7 @@ blkno = fragstoblks(fs, fs->fs_csaddr); len = howmany(fs->fs_cssize, fs->fs_bsize) - 1; size = fs->fs_bsize; + space = fs->fs_csp; for (loc = 0; loc <= len; loc++) { error = VOP_BALLOC(vp, lblktosize(fs, (off_t)(blkno + loc)), fs->fs_bsize, KERNCRED, 0, &nbp); @@ -355,7 +357,8 @@ readblock(nbp, blkno + loc); size = fs->fs_cssize - loc * fs->fs_bsize; } - bcopy(fs->fs_csp[loc], nbp->b_data, size); + bcopy(space, nbp->b_data, size); + space = (char *)space + size; nbp->b_flags |= B_VALIDSUSPWRT; bawrite(nbp); } Index: sys/ufs/ffs/ffs_vfsops.c =================================================================== RCS file: /FreeBSD/FreeBSD-CVS/src/sys/ufs/ffs/ffs_vfsops.c,v retrieving revision 1.134 diff -u -r1.134 ffs_vfsops.c --- sys/ufs/ffs/ffs_vfsops.c 2000/12/13 10:03:52 1.134 +++ sys/ufs/ffs/ffs_vfsops.c 2001/01/09 22:48:28 @@ -365,7 +365,7 @@ { register struct vnode *vp, *nvp, *devvp; struct inode *ip; - struct csum *space; + void *space; struct buf *bp; struct fs *fs, *newfs; struct partinfo dpart; @@ -419,7 +419,7 @@ * new superblock. These should really be in the ufsmount. XXX * Note that important parameters (eg fs_ncg) are unchanged. */ - bcopy(&fs->fs_csp[0], &newfs->fs_csp[0], sizeof(fs->fs_csp)); + newfs->fs_csp = fs->fs_csp; newfs->fs_maxcluster = fs->fs_maxcluster; bcopy(newfs, fs, (u_int)fs->fs_sbsize); if (fs->fs_sbsize < SBSIZE) @@ -432,7 +432,7 @@ * Step 3: re-read summary information from disk. */ blks = howmany(fs->fs_cssize, fs->fs_fsize); - space = fs->fs_csp[0]; + space = fs->fs_csp; for (i = 0; i < blks; i += fs->fs_frag) { size = fs->fs_bsize; if (i + fs->fs_frag > blks) @@ -441,7 +441,8 @@ NOCRED, &bp); if (error) return (error); - bcopy(bp->b_data, fs->fs_csp[fragstoblks(fs, i)], (u_int)size); + bcopy(bp->b_data, space, (u_int)size); + space = (char *)space + size; brelse(bp); } /* @@ -513,7 +514,7 @@ register struct fs *fs; dev_t dev; struct partinfo dpart; - caddr_t base, space; + void *space; int error, i, blks, size, ronly; int32_t *lp; struct ucred *cred; @@ -623,24 +624,24 @@ blks = howmany(size, fs->fs_fsize); if (fs->fs_contigsumsize > 0) size += fs->fs_ncg * sizeof(int32_t); - base = space = malloc((u_long)size, M_UFSMNT, M_WAITOK); + space = malloc((u_long)size, M_UFSMNT, M_WAITOK); + fs->fs_csp = space; for (i = 0; i < blks; i += fs->fs_frag) { size = fs->fs_bsize; if (i + fs->fs_frag > blks) size = (blks - i) * fs->fs_fsize; if ((error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size, cred, &bp)) != 0) { - free(base, M_UFSMNT); + free(fs->fs_csp, M_UFSMNT); goto out; } bcopy(bp->b_data, space, (u_int)size); - fs->fs_csp[fragstoblks(fs, i)] = (struct csum *)space; - space += size; + space = (char *)space + size; brelse(bp); bp = NULL; } if (fs->fs_contigsumsize > 0) { - fs->fs_maxcluster = lp = (int32_t *)space; + fs->fs_maxcluster = lp = space; for (i = 0; i < fs->fs_ncg; i++) *lp++ = fs->fs_contigsumsize; } @@ -691,7 +692,7 @@ if (ronly == 0) { if ((fs->fs_flags & FS_DOSOFTDEP) && (error = softdep_mount(devvp, mp, fs, cred)) != 0) { - free(base, M_UFSMNT); + free(fs->fs_csp, M_UFSMNT); goto out; } if (fs->fs_snapinum[0] != 0) @@ -808,7 +809,7 @@ vrele(ump->um_devvp); - free(fs->fs_csp[0], M_UFSMNT); + free(fs->fs_csp, M_UFSMNT); free(fs, M_UFSMNT); free(ump, M_UFSMNT); mp->mnt_data = (qaddr_t)0; @@ -1263,14 +1264,14 @@ register struct fs *dfs, *fs = mp->um_fs; register struct buf *bp; int blks; - caddr_t space; + void *space; int i, size, error, allerror = 0; /* * First write back the summary information. */ blks = howmany(fs->fs_cssize, fs->fs_fsize); - space = (caddr_t)fs->fs_csp[0]; + space = fs->fs_csp; for (i = 0; i < blks; i += fs->fs_frag) { size = fs->fs_bsize; if (i + fs->fs_frag > blks) @@ -1278,7 +1279,7 @@ bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i), size, 0, 0); bcopy(space, bp->b_data, (u_int)size); - space += size; + space = (char *)space + size; if (waitfor != MNT_WAIT) bawrite(bp); else if ((error = bwrite(bp)) != 0) Index: sys/ufs/ffs/fs.h =================================================================== RCS file: /FreeBSD/FreeBSD-CVS/src/sys/ufs/ffs/fs.h,v retrieving revision 1.16 diff -u -r1.16 fs.h --- sys/ufs/ffs/fs.h 2000/07/04 04:55:48 1.16 +++ sys/ufs/ffs/fs.h 2001/01/12 22:42:44 @@ -106,14 +106,17 @@ #define MAXMNTLEN 512 /* - * The limit on the amount of summary information per file system - * is defined by MAXCSBUFS. It is currently parameterized for a - * size of 128 bytes (2 million cylinder groups on machines with - * 32-bit pointers, and 1 million on 64-bit machines). One pointer - * is taken away to point to an array of cluster sizes that is - * computed as cylinder groups are inspected. + * There is a 128-byte region in the superblock reserved for in-core + * pointers to summary information. Originally this included an array + * of pointers to blocks of struct csum; now there are just two + * 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. */ -#define MAXCSBUFS ((128 / sizeof(void *)) - 1) +#define NOCSPTRS ((128 / sizeof(void *)) - 2) /* * A summary of contiguous blocks of various sizes is maintained @@ -167,9 +170,6 @@ * from first cylinder group data blocks. These blocks have to be * read in from fs_csaddr (size fs_cssize) in addition to the * super block. - * - * N.B. sizeof(struct csum) must be a power of two in order for - * the ``fs_cs'' macro to work (see below). */ struct csum { int32_t cs_ndir; /* number of directories */ @@ -213,8 +213,8 @@ int32_t fs_fragshift; /* block to frag shift */ int32_t fs_fsbtodb; /* fsbtodb and dbtofsb shift constant */ int32_t fs_sbsize; /* actual size of super block */ - int32_t fs_csmask; /* csum block offset */ - int32_t fs_csshift; /* csum block number */ + int32_t fs_csmask; /* csum block offset (now unused) */ + int32_t fs_csshift; /* csum block number (now unused) */ int32_t fs_nindir; /* value of NINDIR */ int32_t fs_inopb; /* value of INOPB */ int32_t fs_nspf; /* value of NSPF */ @@ -250,8 +250,9 @@ u_char fs_fsmnt[MAXMNTLEN]; /* name mounted on */ /* these fields retain the current block allocation info */ int32_t fs_cgrotor; /* last cg searched */ - struct csum *fs_csp[MAXCSBUFS];/* list of fs_cs info buffers */ - int32_t *fs_maxcluster; /* max cluster in each cyl group */ + void *fs_ocsp[NOCSPTRS]; /* padding; was list of fs_cs buffers */ + struct csum *fs_csp; /* cg summary info buffer for fs_cs */ + int32_t *fs_maxcluster; /* max cluster in each cyl group */ int32_t fs_cpc; /* cyl per cycle in postbl */ int16_t fs_opostbl[16][8]; /* old rotation block list head */ int32_t fs_snapinum[FSMAXSNAP];/* list of snapshot inode numbers */ @@ -328,11 +329,8 @@ /* * Convert cylinder group to base address of its global summary info. - * - * N.B. This macro assumes that sizeof(struct csum) is a power of two. */ -#define fs_cs(fs, indx) \ - fs_csp[(indx) >> (fs)->fs_csshift][(indx) & ~(fs)->fs_csmask] +#define fs_cs(fs, indx) fs_csp[indx] /* * Cylinder group block for a file system. To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-fs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi? <200101122325.aa07194>