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
This commit is contained in:
parent
b132183383
commit
e870d1e6f9
@ -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 @@ ffs_fragextend(ip, cg, bprev, osize, nsize)
|
||||
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 @@ ffs_alloccgblk(ip, bp, bpref)
|
||||
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 @@ ffs_clusteralloc(ip, cg, bpref, len)
|
||||
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 @@ ffs_nodealloccg(ip, cg, ipref, mode)
|
||||
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);
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user