summaryrefslogtreecommitdiffstats
path: root/sys/ufs/ffs
diff options
context:
space:
mode:
authormckusick <mckusick@FreeBSD.org>2010-02-10 20:10:35 +0000
committermckusick <mckusick@FreeBSD.org>2010-02-10 20:10:35 +0000
commitd533f2ac8cbe133d3f794fc6d1408cd9304172f4 (patch)
tree0d2c8df7ce7d61552876d16e25300bec5c8bcda4 /sys/ufs/ffs
parentc3b530a4d96d0e1010a7ba327e912233eb4365a3 (diff)
downloadFreeBSD-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.c70
-rw-r--r--sys/ufs/ffs/fs.h52
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.
OpenPOWER on IntegriCloud