diff options
author | mckusick <mckusick@FreeBSD.org> | 2010-02-10 20:10:35 +0000 |
---|---|---|
committer | mckusick <mckusick@FreeBSD.org> | 2010-02-10 20:10:35 +0000 |
commit | d533f2ac8cbe133d3f794fc6d1408cd9304172f4 (patch) | |
tree | 0d2c8df7ce7d61552876d16e25300bec5c8bcda4 /sys/ufs/ffs | |
parent | c3b530a4d96d0e1010a7ba327e912233eb4365a3 (diff) | |
download | FreeBSD-src-d533f2ac8cbe133d3f794fc6d1408cd9304172f4.zip FreeBSD-src-d533f2ac8cbe133d3f794fc6d1408cd9304172f4.tar.gz |
This fix corrects a problem in the file system that treats large
inode numbers as negative rather than unsigned. For a default
(16K block) file system, this bug began to show up at a file system
size above about 16Tb.
To fully handle this problem, newfs must be updated to ensure that
it will never create a filesystem with more than 2^32 inodes. That
patch will be forthcoming soon.
Reported by: Scott Burns, John Kilburg, Bruce Evans
Followup by: Jeff Roberson
PR: 133980
MFC after: 2 weeks
Diffstat (limited to 'sys/ufs/ffs')
-rw-r--r-- | sys/ufs/ffs/ffs_alloc.c | 70 | ||||
-rw-r--r-- | sys/ufs/ffs/fs.h | 52 |
2 files changed, 64 insertions, 58 deletions
diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c index 1363474..36952cc 100644 --- a/sys/ufs/ffs/ffs_alloc.c +++ b/sys/ufs/ffs/ffs_alloc.c @@ -93,24 +93,25 @@ __FBSDID("$FreeBSD$"); #include <ufs/ffs/fs.h> #include <ufs/ffs/ffs_extern.h> -typedef ufs2_daddr_t allocfcn_t(struct inode *ip, int cg, ufs2_daddr_t bpref, +typedef ufs2_daddr_t allocfcn_t(struct inode *ip, u_int cg, ufs2_daddr_t bpref, int size); -static ufs2_daddr_t ffs_alloccg(struct inode *, int, ufs2_daddr_t, int); +static ufs2_daddr_t ffs_alloccg(struct inode *, u_int, ufs2_daddr_t, int); static ufs2_daddr_t ffs_alloccgblk(struct inode *, struct buf *, ufs2_daddr_t); #ifdef INVARIANTS static int ffs_checkblk(struct inode *, ufs2_daddr_t, long); #endif -static ufs2_daddr_t ffs_clusteralloc(struct inode *, int, ufs2_daddr_t, int); +static ufs2_daddr_t ffs_clusteralloc(struct inode *, u_int, ufs2_daddr_t, int); static void ffs_clusteracct(struct ufsmount *, struct fs *, struct cg *, ufs1_daddr_t, int); static ino_t ffs_dirpref(struct inode *); -static ufs2_daddr_t ffs_fragextend(struct inode *, int, ufs2_daddr_t, int, int); +static ufs2_daddr_t ffs_fragextend(struct inode *, u_int, ufs2_daddr_t, + int, int); static void ffs_fserr(struct fs *, ino_t, char *); static ufs2_daddr_t ffs_hashalloc - (struct inode *, int, ufs2_daddr_t, int, allocfcn_t *); -static ufs2_daddr_t ffs_nodealloccg(struct inode *, int, ufs2_daddr_t, int); + (struct inode *, u_int, ufs2_daddr_t, int, allocfcn_t *); +static ufs2_daddr_t ffs_nodealloccg(struct inode *, u_int, ufs2_daddr_t, int); static ufs1_daddr_t ffs_mapsearch(struct fs *, struct cg *, ufs2_daddr_t, int); static int ffs_reallocblks_ufs1(struct vop_reallocblks_args *); static int ffs_reallocblks_ufs2(struct vop_reallocblks_args *); @@ -145,7 +146,7 @@ ffs_alloc(ip, lbn, bpref, size, flags, cred, bnp) struct fs *fs; struct ufsmount *ump; ufs2_daddr_t bno; - int cg, reclaimed; + u_int cg, reclaimed; static struct timeval lastfail; static int curfail; int64_t delta; @@ -248,7 +249,8 @@ ffs_realloccg(ip, lbprev, bprev, bpref, osize, nsize, flags, cred, bpp) struct fs *fs; struct buf *bp; struct ufsmount *ump; - int cg, request, error, reclaimed; + u_int cg, request, reclaimed; + int error; ufs2_daddr_t bno; static struct timeval lastfail; static int curfail; @@ -933,7 +935,8 @@ ffs_valloc(pvp, mode, cred, vpp) struct timespec ts; struct ufsmount *ump; ino_t ino, ipref; - int cg, error, error1; + u_int cg; + int error, error1; static struct timeval lastfail; static int curfail; @@ -1043,11 +1046,11 @@ ffs_dirpref(pip) struct inode *pip; { struct fs *fs; - int cg, prefcg, dirsize, cgsize; - int avgifree, avgbfree, avgndir, curdirsize; - int minifree, minbfree, maxndir; - int mincg, minndir; - int maxcontigdirs; + u_int cg, prefcg, dirsize, cgsize; + u_int avgifree, avgbfree, avgndir, curdirsize; + u_int minifree, minbfree, maxndir; + u_int mincg, minndir; + u_int maxcontigdirs; mtx_assert(UFS_MTX(pip->i_ump), MA_OWNED); fs = pip->i_fs; @@ -1171,8 +1174,8 @@ ffs_blkpref_ufs1(ip, lbn, indx, bap) ufs1_daddr_t *bap; { struct fs *fs; - int cg; - int avgbfree, startcg; + u_int cg; + u_int avgbfree, startcg; mtx_assert(UFS_MTX(ip->i_ump), MA_OWNED); fs = ip->i_fs; @@ -1221,8 +1224,8 @@ ffs_blkpref_ufs2(ip, lbn, indx, bap) ufs2_daddr_t *bap; { struct fs *fs; - int cg; - int avgbfree, startcg; + u_int cg; + u_int avgbfree, startcg; mtx_assert(UFS_MTX(ip->i_ump), MA_OWNED); fs = ip->i_fs; @@ -1275,14 +1278,14 @@ ffs_blkpref_ufs2(ip, lbn, indx, bap) static ufs2_daddr_t ffs_hashalloc(ip, cg, pref, size, allocator) struct inode *ip; - int cg; + u_int cg; ufs2_daddr_t pref; int size; /* size for data blocks, mode for inodes */ allocfcn_t *allocator; { struct fs *fs; ufs2_daddr_t result; - int i, icg = cg; + u_int i, icg = cg; mtx_assert(UFS_MTX(ip->i_ump), MA_OWNED); #ifdef INVARIANTS @@ -1333,7 +1336,7 @@ ffs_hashalloc(ip, cg, pref, size, allocator) static ufs2_daddr_t ffs_fragextend(ip, cg, bprev, osize, nsize) struct inode *ip; - int cg; + u_int cg; ufs2_daddr_t bprev; int osize, nsize; { @@ -1416,7 +1419,7 @@ fail: static ufs2_daddr_t ffs_alloccg(ip, cg, bpref, size) struct inode *ip; - int cg; + u_int cg; ufs2_daddr_t bpref; int size; { @@ -1586,7 +1589,7 @@ gotit: static ufs2_daddr_t ffs_clusteralloc(ip, cg, bpref, len) struct inode *ip; - int cg; + u_int cg; ufs2_daddr_t bpref; int len; { @@ -1710,7 +1713,7 @@ fail: static ufs2_daddr_t ffs_nodealloccg(ip, cg, ipref, mode) struct inode *ip; - int cg; + u_int cg; ufs2_daddr_t ipref; int mode; { @@ -1811,7 +1814,7 @@ gotit: bdwrite(bp); if (ibp != NULL) bawrite(ibp); - return (cg * fs->fs_ipg + ipref); + return ((ino_t)(cg * fs->fs_ipg + ipref)); } /* @@ -1856,7 +1859,8 @@ ffs_blkfree(ump, fs, devvp, bno, size, inum) struct buf *bp; ufs1_daddr_t fragno, cgbno; ufs2_daddr_t cgblkno; - int i, cg, blk, frags, bbase; + int i, blk, frags, bbase; + u_int cg; u_int8_t *blksfree; struct cdev *dev; @@ -2054,7 +2058,8 @@ ffs_freefile(ump, fs, devvp, ino, mode) struct cg *cgp; struct buf *bp; ufs2_daddr_t cgbno; - int error, cg; + int error; + u_int cg; u_int8_t *inosused; struct cdev *dev; @@ -2068,7 +2073,7 @@ ffs_freefile(ump, fs, devvp, ino, mode) dev = devvp->v_rdev; cgbno = fsbtodb(fs, cgtod(fs, cg)); } - if ((u_int)ino >= fs->fs_ipg * fs->fs_ncg) + if (ino >= fs->fs_ipg * fs->fs_ncg) panic("ffs_freefile: range: dev = %s, ino = %lu, fs = %s", devtoname(dev), (u_long)ino, fs->fs_fsmnt); if ((error = bread(devvp, cgbno, (int)fs->fs_cgsize, NOCRED, &bp))) { @@ -2085,8 +2090,8 @@ ffs_freefile(ump, fs, devvp, ino, mode) inosused = cg_inosused(cgp); ino %= fs->fs_ipg; if (isclr(inosused, ino)) { - printf("dev = %s, ino = %lu, fs = %s\n", devtoname(dev), - (u_long)ino + cg * fs->fs_ipg, fs->fs_fsmnt); + printf("dev = %s, ino = %u, fs = %s\n", devtoname(dev), + ino + cg * fs->fs_ipg, fs->fs_fsmnt); if (fs->fs_ronly == 0) panic("ffs_freefile: freeing free inode"); } @@ -2121,7 +2126,8 @@ ffs_checkfreefile(fs, devvp, ino) struct cg *cgp; struct buf *bp; ufs2_daddr_t cgbno; - int ret, cg; + int ret; + u_int cg; u_int8_t *inosused; cg = ino_to_cg(fs, ino); @@ -2132,7 +2138,7 @@ ffs_checkfreefile(fs, devvp, ino) /* devvp is a normal disk device */ cgbno = fsbtodb(fs, cgtod(fs, cg)); } - if ((u_int)ino >= fs->fs_ipg * fs->fs_ncg) + if (ino >= fs->fs_ipg * fs->fs_ncg) return (1); if (bread(devvp, cgbno, (int)fs->fs_cgsize, NOCRED, &bp)) { brelse(bp); diff --git a/sys/ufs/ffs/fs.h b/sys/ufs/ffs/fs.h index cc1d357..c893612 100644 --- a/sys/ufs/ffs/fs.h +++ b/sys/ufs/ffs/fs.h @@ -264,7 +264,7 @@ struct fs { int32_t fs_old_time; /* last time written */ int32_t fs_old_size; /* number of blocks in fs */ int32_t fs_old_dsize; /* number of data blocks in fs */ - int32_t fs_ncg; /* number of cylinder groups */ + u_int32_t fs_ncg; /* number of cylinder groups */ int32_t fs_bsize; /* size of basic blocks in fs */ int32_t fs_fsize; /* size of frag blocks in fs */ int32_t fs_frag; /* number of frags in a block in fs */ @@ -304,7 +304,7 @@ struct fs { int32_t fs_old_spc; /* sectors per cylinder */ int32_t fs_old_ncyl; /* cylinders in filesystem */ int32_t fs_old_cpg; /* cylinders per group */ - int32_t fs_ipg; /* inodes per group */ + u_int32_t fs_ipg; /* inodes per group */ int32_t fs_fpg; /* blocks per group * fs_frag */ /* this data must be re-computed after crashes */ struct csum fs_old_cstotal; /* cylinder summary information */ @@ -335,10 +335,10 @@ struct fs { int64_t fs_dsize; /* number of data blocks in fs */ ufs2_daddr_t fs_csaddr; /* blk addr of cyl grp summary area */ int64_t fs_pendingblocks; /* (u) blocks being freed */ - int32_t fs_pendinginodes; /* (u) inodes being freed */ - int32_t fs_snapinum[FSMAXSNAP];/* list of snapshot inode numbers */ - int32_t fs_avgfilesize; /* expected average file size */ - int32_t fs_avgfpdir; /* expected # of files per directory */ + u_int32_t fs_pendinginodes; /* (u) inodes being freed */ + ino_t fs_snapinum[FSMAXSNAP];/* list of snapshot inode numbers */ + u_int32_t fs_avgfilesize; /* expected average file size */ + u_int32_t fs_avgfpdir; /* expected # of files per directory */ int32_t fs_save_cgsize; /* save real cg size to use fs_bsize */ int32_t fs_sparecon32[26]; /* reserved for future constants */ int32_t fs_flags; /* see FS_ flags below */ @@ -463,26 +463,26 @@ struct cg { int32_t cg_firstfield; /* historic cyl groups linked list */ int32_t cg_magic; /* magic number */ int32_t cg_old_time; /* time last written */ - int32_t cg_cgx; /* we are the cgx'th cylinder group */ + u_int32_t cg_cgx; /* we are the cgx'th cylinder group */ int16_t cg_old_ncyl; /* number of cyl's this cg */ int16_t cg_old_niblk; /* number of inode blocks this cg */ - int32_t cg_ndblk; /* number of data blocks this cg */ - struct csum cg_cs; /* cylinder summary information */ - int32_t cg_rotor; /* position of last used block */ - int32_t cg_frotor; /* position of last used frag */ - int32_t cg_irotor; /* position of last used inode */ - int32_t cg_frsum[MAXFRAG]; /* counts of available frags */ + u_int32_t cg_ndblk; /* number of data blocks this cg */ + struct csum cg_cs; /* cylinder summary information */ + u_int32_t cg_rotor; /* position of last used block */ + u_int32_t cg_frotor; /* position of last used frag */ + u_int32_t cg_irotor; /* position of last used inode */ + u_int32_t cg_frsum[MAXFRAG]; /* counts of available frags */ int32_t cg_old_btotoff; /* (int32) block totals per cylinder */ int32_t cg_old_boff; /* (u_int16) free block positions */ - int32_t cg_iusedoff; /* (u_int8) used inode map */ - int32_t cg_freeoff; /* (u_int8) free block map */ - int32_t cg_nextfreeoff; /* (u_int8) next available space */ - int32_t cg_clustersumoff; /* (u_int32) counts of avail clusters */ - int32_t cg_clusteroff; /* (u_int8) free cluster map */ - int32_t cg_nclusterblks; /* number of clusters this cg */ - int32_t cg_niblk; /* number of inode blocks this cg */ - int32_t cg_initediblk; /* last initialized inode */ - int32_t cg_unrefs; /* number of unreferenced inodes */ + u_int32_t cg_iusedoff; /* (u_int8) used inode map */ + u_int32_t cg_freeoff; /* (u_int8) free block map */ + u_int32_t cg_nextfreeoff; /* (u_int8) next available space */ + u_int32_t cg_clustersumoff; /* (u_int32) counts of avail clusters */ + u_int32_t cg_clusteroff; /* (u_int8) free cluster map */ + u_int32_t cg_nclusterblks; /* number of clusters this cg */ + u_int32_t cg_niblk; /* number of inode blocks this cg */ + u_int32_t cg_initediblk; /* last initialized inode */ + u_int32_t cg_unrefs; /* number of unreferenced inodes */ int32_t cg_sparecon32[2]; /* reserved for future use */ ufs_time_t cg_time; /* time last written */ int64_t cg_sparecon64[3]; /* reserved for future use */ @@ -529,11 +529,11 @@ struct cg { * inode number to cylinder group number. * inode number to filesystem block address. */ -#define ino_to_cg(fs, x) ((x) / (fs)->fs_ipg) +#define ino_to_cg(fs, x) (((ino_t)(x)) / (fs)->fs_ipg) #define ino_to_fsba(fs, x) \ - ((ufs2_daddr_t)(cgimin(fs, ino_to_cg(fs, x)) + \ - (blkstofrags((fs), (((x) % (fs)->fs_ipg) / INOPB(fs)))))) -#define ino_to_fsbo(fs, x) ((x) % INOPB(fs)) + ((ufs2_daddr_t)(cgimin(fs, ino_to_cg(fs, (ino_t)(x))) + \ + (blkstofrags((fs), ((((ino_t)(x)) % (fs)->fs_ipg) / INOPB(fs)))))) +#define ino_to_fsbo(fs, x) (((ino_t)(x)) % INOPB(fs)) /* * Give cylinder group number for a filesystem block. |