Page MenuHomeFreeBSD

D11530.id36802.diff
No OneTemporary

D11530.id36802.diff

Index: fs/ext2fs/ext2_alloc.c
===================================================================
--- fs/ext2fs/ext2_alloc.c
+++ fs/ext2fs/ext2_alloc.c
@@ -103,12 +103,12 @@
if (cred == NOCRED)
panic("ext2_alloc: missing credential");
#endif /* INVARIANTS */
- if (size == fs->e2fs_bsize && fs->e2fs->e2fs_fbcount == 0)
+ if (size == fs->e2fs_bsize && fs->e2fs_fbcount == 0)
goto nospace;
if (cred->cr_uid != 0 &&
- fs->e2fs->e2fs_fbcount < fs->e2fs->e2fs_rbcount)
+ fs->e2fs_fbcount < fs->e2fs_rbcount)
goto nospace;
- if (bpref >= fs->e2fs->e2fs_bcount)
+ if (bpref >= fs->e2fs_bcount)
bpref = 0;
if (bpref == 0)
cg = ino_to_cg(fs, ip->i_number);
@@ -179,6 +179,15 @@
SYSCTL_INT(_vfs_ext2fs, OID_AUTO, doreallocblks, CTLFLAG_RW, &doreallocblks, 0, "");
+/*
+ * Just for TESTING and DEBUG 64bit feature purposes, should be removed later.
+ * Force to allocate cylinder gruoups more then UINT_MAX blocks numbers.
+ */
+
+static int force_64bit_alloc = 0;
+
+SYSCTL_INT(_vfs_ext2fs, OID_AUTO, force_64bit_alloc, CTLFLAG_RW, &force_64bit_alloc, 0, "");
+
int
ext2_reallocblks(struct vop_reallocblks_args *ap)
{
@@ -404,7 +413,6 @@
}
ipref = cg * fs->e2fs->e2fs_ipg + 1;
ino = (ino_t)ext2_hashalloc(pip, cg, (long)ipref, mode, ext2_nodealloccg);
-
if (ino == 0)
goto noinodes;
error = VFS_VGET(pvp->v_mount, ino, LK_EXCLUSIVE, vpp);
@@ -455,6 +463,96 @@
}
/*
+ * 64-bit compatible getters and setters for struct ext2_gd from ext2fs.h
+ */
+static uint64_t
+e2fs_gd_get_b_bitmap(struct ext2_gd *gd)
+{
+
+ return (((uint64_t)(gd->ext4bgd_b_bitmap_hi) << 32) |
+ gd->ext2bgd_b_bitmap);
+}
+
+static uint64_t
+e2fs_gd_get_i_bitmap(struct ext2_gd *gd)
+{
+
+ return (((uint64_t)(gd->ext4bgd_i_bitmap_hi) << 32) |
+ gd->ext2bgd_i_bitmap);
+}
+
+uint64_t
+e2fs_gd_get_i_tables(struct ext2_gd *gd)
+{
+
+ return (((uint64_t)(gd->ext4bgd_i_tables_hi) << 32) |
+ gd->ext2bgd_i_tables);
+}
+
+static uint32_t
+e2fs_gd_get_nbfree(struct ext2_gd *gd)
+{
+
+ return (((uint32_t)(gd->ext4bgd_nbfree_hi) << 16) |
+ gd->ext2bgd_nbfree);
+}
+
+static void
+e2fs_gd_set_nbfree(struct ext2_gd *gd, uint32_t val)
+{
+
+ gd->ext2bgd_nbfree = val & 0xffff;
+ gd->ext4bgd_nbfree_hi = val >> 16;
+}
+
+static uint32_t
+e2fs_gd_get_nifree(struct ext2_gd *gd)
+{
+
+ return (((uint32_t)(gd->ext4bgd_nifree_hi) << 16) |
+ gd->ext2bgd_nifree);
+}
+
+static void
+e2fs_gd_set_nifree(struct ext2_gd *gd, uint32_t val)
+{
+
+ gd->ext2bgd_nifree = val & 0xffff;
+ gd->ext4bgd_nifree_hi = val >> 16;
+}
+
+uint32_t
+e2fs_gd_get_ndirs(struct ext2_gd *gd)
+{
+
+ return (((uint32_t)(gd->ext4bgd_ndirs_hi) << 16) |
+ gd->ext2bgd_ndirs);
+}
+
+static void
+e2fs_gd_set_ndirs(struct ext2_gd *gd, uint32_t val)
+{
+
+ gd->ext2bgd_ndirs = val & 0xffff;
+ gd->ext4bgd_ndirs_hi = val >> 16;
+}
+
+static uint32_t
+e2fs_gd_get_i_unused(struct ext2_gd *gd)
+{
+ return (((uint32_t)(gd->ext4bgd_i_unused_hi) << 16) |
+ gd->ext4bgd_i_unused);
+}
+
+static void
+e2fs_gd_set_i_unused(struct ext2_gd *gd, uint32_t val)
+{
+
+ gd->ext4bgd_i_unused = val & 0xffff;
+ gd->ext4bgd_i_unused_hi = val >> 16;
+}
+
+/*
* Find a cylinder to place a directory.
*
* The policy implemented by this algorithm is to allocate a
@@ -473,8 +571,9 @@
{
struct m_ext2fs *fs;
int cg, prefcg, cgsize;
- u_int avgifree, avgbfree, avgndir, curdirsize;
- u_int minifree, minbfree, maxndir;
+ uint64_t avgbfree, minbfree;
+ u_int avgifree, avgndir, curdirsize;
+ u_int minifree, maxndir;
u_int mincg, minndir;
u_int dirsize, maxcontigdirs;
@@ -482,7 +581,7 @@
fs = pip->i_e2fs;
avgifree = fs->e2fs->e2fs_ficount / fs->e2fs_gcount;
- avgbfree = fs->e2fs->e2fs_fbcount / fs->e2fs_gcount;
+ avgbfree = fs->e2fs_fbcount / fs->e2fs_gcount;
avgndir = fs->e2fs_total_dir / fs->e2fs_gcount;
/*
@@ -494,18 +593,18 @@
mincg = prefcg;
minndir = fs->e2fs_ipg;
for (cg = prefcg; cg < fs->e2fs_gcount; cg++)
- if (fs->e2fs_gd[cg].ext2bgd_ndirs < minndir &&
- fs->e2fs_gd[cg].ext2bgd_nifree >= avgifree &&
- fs->e2fs_gd[cg].ext2bgd_nbfree >= avgbfree) {
+ if (e2fs_gd_get_ndirs(&fs->e2fs_gd[cg]) < minndir &&
+ e2fs_gd_get_nifree(&fs->e2fs_gd[cg]) >= avgifree &&
+ e2fs_gd_get_nbfree(&fs->e2fs_gd[cg]) >= avgbfree) {
mincg = cg;
- minndir = fs->e2fs_gd[cg].ext2bgd_ndirs;
+ minndir = e2fs_gd_get_ndirs(&fs->e2fs_gd[cg]);
}
for (cg = 0; cg < prefcg; cg++)
- if (fs->e2fs_gd[cg].ext2bgd_ndirs < minndir &&
- fs->e2fs_gd[cg].ext2bgd_nifree >= avgifree &&
- fs->e2fs_gd[cg].ext2bgd_nbfree >= avgbfree) {
+ if (e2fs_gd_get_ndirs(&fs->e2fs_gd[cg]) < minndir &&
+ e2fs_gd_get_nifree(&fs->e2fs_gd[cg]) >= avgifree &&
+ e2fs_gd_get_nbfree(&fs->e2fs_gd[cg]) >= avgbfree) {
mincg = cg;
- minndir = fs->e2fs_gd[cg].ext2bgd_ndirs;
+ minndir = e2fs_gd_get_ndirs(&fs->e2fs_gd[cg]);
}
return (mincg);
}
@@ -537,16 +636,16 @@
*/
prefcg = ino_to_cg(fs, pip->i_number);
for (cg = prefcg; cg < fs->e2fs_gcount; cg++)
- if (fs->e2fs_gd[cg].ext2bgd_ndirs < maxndir &&
- fs->e2fs_gd[cg].ext2bgd_nifree >= minifree &&
- fs->e2fs_gd[cg].ext2bgd_nbfree >= minbfree) {
+ if (e2fs_gd_get_ndirs(&fs->e2fs_gd[cg]) < maxndir &&
+ e2fs_gd_get_nifree(&fs->e2fs_gd[cg]) >= minifree &&
+ e2fs_gd_get_nbfree(&fs->e2fs_gd[cg]) >= minbfree) {
if (fs->e2fs_contigdirs[cg] < maxcontigdirs)
return (cg);
}
for (cg = 0; cg < prefcg; cg++)
- if (fs->e2fs_gd[cg].ext2bgd_ndirs < maxndir &&
- fs->e2fs_gd[cg].ext2bgd_nifree >= minifree &&
- fs->e2fs_gd[cg].ext2bgd_nbfree >= minbfree) {
+ if (e2fs_gd_get_ndirs(&fs->e2fs_gd[cg]) < maxndir &&
+ e2fs_gd_get_nifree(&fs->e2fs_gd[cg]) >= minifree &&
+ e2fs_gd_get_nbfree(&fs->e2fs_gd[cg]) >= minbfree) {
if (fs->e2fs_contigdirs[cg] < maxcontigdirs)
return (cg);
}
@@ -554,10 +653,10 @@
* This is a backstop when we have deficit in space.
*/
for (cg = prefcg; cg < fs->e2fs_gcount; cg++)
- if (fs->e2fs_gd[cg].ext2bgd_nifree >= avgifree)
+ if (e2fs_gd_get_nifree(&fs->e2fs_gd[cg]) >= avgifree)
return (cg);
for (cg = 0; cg < prefcg; cg++)
- if (fs->e2fs_gd[cg].ext2bgd_nifree >= avgifree)
+ if (e2fs_gd_get_nifree(&fs->e2fs_gd[cg]) >= avgifree)
break;
return (cg);
}
@@ -626,9 +725,44 @@
struct m_ext2fs *fs;
e4fs_daddr_t result;
int i, icg = cg;
+ static int force_64_bit_indicator;
mtx_assert(EXT2_MTX(ip->i_ump), MA_OWNED);
fs = ip->i_e2fs;
+
+ /*
+ * ONLY FOR TESTING PURPOSES:
+ * HACK to allow allocate cg blocks outside of UINT_MAX range.
+ * Use brute force search from starting cg to end of the drive
+ * in this case.
+ * TODO: REMOVE IT.
+ */
+ if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_64BIT) &&
+ force_64bit_alloc) {
+ icg = cg = ((((uint64_t)0xFFFFFFFF) + 0xFFFF)) /
+ EXT2_BLOCKS_PER_GROUP(fs);
+
+ if (force_64_bit_indicator++ == 0)
+ printf("force_64bit: allocation => FORCED\n");
+
+ for (i = cg; cg < fs->e2fs_gcount; i++) {
+ result = (*allocator)(ip, cg, 0, size);
+ if (result) {
+
+ if (0 == (force_64_bit_indicator % 10000))
+ printf("force_64bit: allocated %lx\n",
+ result);
+
+ return (result);
+ }
+ cg++;
+ }
+
+ printf("force_64bit: allocated => 0\n");
+
+ return (0);
+ }
+
/*
* 1: preferred cylinder group
*/
@@ -709,19 +843,6 @@
return (num);
}
-static int
-ext2_get_cg_number(struct m_ext2fs *fs, daddr_t blk)
-{
- int cg;
-
- if (fs->e2fs->e2fs_bpg == fs->e2fs_bsize * 8)
- cg = (blk - fs->e2fs->e2fs_first_dblock) / (fs->e2fs_bsize * 8);
- else
- cg = blk - fs->e2fs->e2fs_first_dblock;
-
- return (cg);
-}
-
static void
ext2_mark_bitmap_end(int start_bit, int end_bit, char *bitmap)
{
@@ -740,10 +861,9 @@
ext2_cg_block_bitmap_init(struct m_ext2fs *fs, int cg, struct buf *bp)
{
int bit, bit_max, inodes_per_block;
- uint32_t start, tmp;
+ uint64_t start, tmp;
- if (!EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_GDT_CSUM) ||
- !(fs->e2fs_gd[cg].ext4bgd_flags & EXT2_BG_BLOCK_UNINIT))
+ if (!(fs->e2fs_gd[cg].ext4bgd_flags & EXT2_BG_BLOCK_UNINIT))
return (0);
memset(bp->b_data, 0, fs->e2fs_bsize);
@@ -755,25 +875,25 @@
for (bit = 0; bit < bit_max; bit++)
setbit(bp->b_data, bit);
- start = cg * fs->e2fs->e2fs_bpg + fs->e2fs->e2fs_first_dblock;
+ start = (uint64_t)cg * fs->e2fs->e2fs_bpg + fs->e2fs->e2fs_first_dblock;
- /* Set bits for block and inode bitmaps, and inode table */
- tmp = fs->e2fs_gd[cg].ext2bgd_b_bitmap;
+ /* Set bits for block and inode bitmaps, and inode table. */
+ tmp = e2fs_gd_get_b_bitmap(&fs->e2fs_gd[cg]);
if (!EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_FLEX_BG) ||
- tmp == ext2_get_cg_number(fs, cg))
+ cg == dtogd(fs, tmp))
setbit(bp->b_data, tmp - start);
- tmp = fs->e2fs_gd[cg].ext2bgd_i_bitmap;
+ tmp = e2fs_gd_get_i_bitmap(&fs->e2fs_gd[cg]);
if (!EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_FLEX_BG) ||
- tmp == ext2_get_cg_number(fs, cg))
+ cg == dtogd(fs, tmp))
setbit(bp->b_data, tmp - start);
- tmp = fs->e2fs_gd[cg].ext2bgd_i_tables;
+ tmp = e2fs_gd_get_i_tables(&fs->e2fs_gd[cg]);
inodes_per_block = fs->e2fs_bsize/EXT2_INODE_SIZE(fs);
- while( tmp < fs->e2fs_gd[cg].ext2bgd_i_tables +
+ while( tmp < e2fs_gd_get_i_tables(&fs->e2fs_gd[cg]) +
fs->e2fs->e2fs_ipg / inodes_per_block ) {
if (!EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_FLEX_BG) ||
- tmp == ext2_get_cg_number(fs, cg))
+ cg == dtogd(fs, tmp))
setbit(bp->b_data, tmp - start);
tmp++;
}
@@ -810,11 +930,11 @@
/* XXX ondisk32 */
fs = ip->i_e2fs;
ump = ip->i_ump;
- if (fs->e2fs_gd[cg].ext2bgd_nbfree == 0)
+ if (e2fs_gd_get_nbfree(&fs->e2fs_gd[cg]) == 0)
return (0);
EXT2_UNLOCK(ump);
error = bread(ip->i_devvp, fsbtodb(fs,
- fs->e2fs_gd[cg].ext2bgd_b_bitmap),
+ e2fs_gd_get_b_bitmap(&fs->e2fs_gd[cg])),
(int)fs->e2fs_bsize, NOCRED, &bp);
if (error) {
brelse(bp);
@@ -829,7 +949,7 @@
return (0);
}
}
- if (fs->e2fs_gd[cg].ext2bgd_nbfree == 0) {
+ if (e2fs_gd_get_nbfree(&fs->e2fs_gd[cg]) == 0) {
/*
* Another thread allocated the last block in this
* group while we were waiting for the buffer.
@@ -926,12 +1046,13 @@
setbit(bbp, bno);
EXT2_LOCK(ump);
ext2_clusteracct(fs, bbp, cg, bno, -1);
- fs->e2fs->e2fs_fbcount--;
- fs->e2fs_gd[cg].ext2bgd_nbfree--;
+ fs->e2fs_fbcount--;
+ e2fs_gd_set_nbfree(&fs->e2fs_gd[cg],
+ e2fs_gd_get_nbfree(&fs->e2fs_gd[cg]) - 1);
fs->e2fs_fmod = 1;
EXT2_UNLOCK(ump);
bdwrite(bp);
- return (cg * fs->e2fs->e2fs_fpg + fs->e2fs->e2fs_first_dblock + bno);
+ return (((uint64_t)cg) * fs->e2fs->e2fs_fpg + fs->e2fs->e2fs_first_dblock + bno);
}
/*
@@ -956,7 +1077,7 @@
EXT2_UNLOCK(ump);
error = bread(ip->i_devvp,
- fsbtodb(fs, fs->e2fs_gd[cg].ext2bgd_b_bitmap),
+ fsbtodb(fs, e2fs_gd_get_b_bitmap(&fs->e2fs_gd[cg])),
(int)fs->e2fs_bsize, NOCRED, &bp);
if (error)
goto fail_lock;
@@ -1026,8 +1147,9 @@
for (i = 0; i < len; i += fs->e2fs_fpb) {
setbit(bbp, bno + i);
ext2_clusteracct(fs, bbp, cg, bno + i, -1);
- fs->e2fs->e2fs_fbcount--;
- fs->e2fs_gd[cg].ext2bgd_nbfree--;
+ fs->e2fs_fbcount--;
+ e2fs_gd_set_nbfree(&fs->e2fs_gd[cg],
+ e2fs_gd_get_nbfree(&fs->e2fs_gd[cg]) - 1);
}
fs->e2fs_fmod = 1;
EXT2_UNLOCK(ump);
@@ -1058,12 +1180,12 @@
fs->e2fs_bsize;
used_blks = howmany(fs->e2fs->e2fs_ipg -
- fs->e2fs_gd[cg].ext4bgd_i_unused,
+ e2fs_gd_get_i_unused(&fs->e2fs_gd[cg]),
fs->e2fs_bsize / EXT2_INODE_SIZE(fs));
for (i = 0; i < all_blks - used_blks; i++) {
bp = getblk(ip->i_devvp, fsbtodb(fs,
- fs->e2fs_gd[cg].ext2bgd_i_tables + used_blks + i),
+ e2fs_gd_get_i_tables(&fs->e2fs_gd[cg]) + used_blks + i),
fs->e2fs_bsize, 0, 0, 0);
if (!bp)
return (EIO);
@@ -1097,11 +1219,11 @@
ipref = 0;
fs = ip->i_e2fs;
ump = ip->i_ump;
- if (fs->e2fs_gd[cg].ext2bgd_nifree == 0)
+ if (e2fs_gd_get_nifree(&fs->e2fs_gd[cg]) == 0)
return (0);
EXT2_UNLOCK(ump);
error = bread(ip->i_devvp, fsbtodb(fs,
- fs->e2fs_gd[cg].ext2bgd_i_bitmap),
+ e2fs_gd_get_i_bitmap(&fs->e2fs_gd[cg])),
(int)fs->e2fs_bsize, NOCRED, &bp);
if (error) {
brelse(bp);
@@ -1120,7 +1242,7 @@
return (0);
}
}
- if (fs->e2fs_gd[cg].ext2bgd_nifree == 0) {
+ if (e2fs_gd_get_nifree(&fs->e2fs_gd[cg]) == 0) {
/*
* Another thread allocated the last i-node in this
* group while we were waiting for the buffer.
@@ -1153,18 +1275,21 @@
gotit:
setbit(ibp, ipref);
EXT2_LOCK(ump);
- fs->e2fs_gd[cg].ext2bgd_nifree--;
+ e2fs_gd_set_nifree(&fs->e2fs_gd[cg],
+ e2fs_gd_get_nifree(&fs->e2fs_gd[cg]) - 1);
if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_GDT_CSUM))
- fs->e2fs_gd[cg].ext4bgd_i_unused--;
+ e2fs_gd_set_i_unused(&fs->e2fs_gd[cg],
+ e2fs_gd_get_i_unused(&fs->e2fs_gd[cg]) - 1);
fs->e2fs->e2fs_ficount--;
fs->e2fs_fmod = 1;
if ((mode & IFMT) == IFDIR) {
- fs->e2fs_gd[cg].ext2bgd_ndirs++;
+ e2fs_gd_set_ndirs(&fs->e2fs_gd[cg],
+ e2fs_gd_get_ndirs(&fs->e2fs_gd[cg]) + 1);
fs->e2fs_total_dir++;
}
EXT2_UNLOCK(ump);
bdwrite(bp);
- return (cg * fs->e2fs->e2fs_ipg + ipref + 1);
+ return ((uint64_t)cg * fs->e2fs_ipg + ipref + 1);
}
/*
@@ -1183,14 +1308,14 @@
fs = ip->i_e2fs;
ump = ip->i_ump;
cg = dtog(fs, bno);
- if (bno >= fs->e2fs->e2fs_bcount) {
+ if (bno >= fs->e2fs_bcount) {
printf("bad block %lld, ino %ju\n", (long long)bno,
(uintmax_t)ip->i_number);
ext2_fserr(fs, ip->i_uid, "bad block");
return;
}
error = bread(ip->i_devvp,
- fsbtodb(fs, fs->e2fs_gd[cg].ext2bgd_b_bitmap),
+ fsbtodb(fs, e2fs_gd_get_b_bitmap(&fs->e2fs_gd[cg])),
(int)fs->e2fs_bsize, NOCRED, &bp);
if (error) {
brelse(bp);
@@ -1206,8 +1331,9 @@
clrbit(bbp, bno);
EXT2_LOCK(ump);
ext2_clusteracct(fs, bbp, cg, bno, 1);
- fs->e2fs->e2fs_fbcount++;
- fs->e2fs_gd[cg].ext2bgd_nbfree++;
+ fs->e2fs_fbcount++;
+ e2fs_gd_set_nbfree(&fs->e2fs_gd[cg],
+ e2fs_gd_get_nbfree(&fs->e2fs_gd[cg]) + 1);
fs->e2fs_fmod = 1;
EXT2_UNLOCK(ump);
bdwrite(bp);
@@ -1236,7 +1362,7 @@
cg = ino_to_cg(fs, ino);
error = bread(pip->i_devvp,
- fsbtodb(fs, fs->e2fs_gd[cg].ext2bgd_i_bitmap),
+ fsbtodb(fs, e2fs_gd_get_i_bitmap(&fs->e2fs_gd[cg])),
(int)fs->e2fs_bsize, NOCRED, &bp);
if (error) {
brelse(bp);
@@ -1253,11 +1379,14 @@
clrbit(ibp, ino);
EXT2_LOCK(ump);
fs->e2fs->e2fs_ficount++;
- fs->e2fs_gd[cg].ext2bgd_nifree++;
+ e2fs_gd_set_nifree(&fs->e2fs_gd[cg],
+ e2fs_gd_get_nifree(&fs->e2fs_gd[cg]) + 1);
if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_GDT_CSUM))
- fs->e2fs_gd[cg].ext4bgd_i_unused++;
+ e2fs_gd_set_i_unused(&fs->e2fs_gd[cg],
+ e2fs_gd_get_i_unused(&fs->e2fs_gd[cg]) + 1);
if ((mode & IFMT) == IFDIR) {
- fs->e2fs_gd[cg].ext2bgd_ndirs--;
+ e2fs_gd_set_ndirs(&fs->e2fs_gd[cg],
+ e2fs_gd_get_ndirs(&fs->e2fs_gd[cg]) - 1);
fs->e2fs_total_dir--;
}
fs->e2fs_fmod = 1;
Index: fs/ext2fs/ext2_balloc.c
===================================================================
--- fs/ext2fs/ext2_balloc.c
+++ fs/ext2fs/ext2_balloc.c
@@ -42,6 +42,7 @@
#include <sys/systm.h>
#include <sys/bio.h>
#include <sys/buf.h>
+#include <sys/limits.h>
#include <sys/lock.h>
#include <sys/mount.h>
#include <sys/vnode.h>
@@ -60,13 +61,13 @@
struct m_ext2fs *fs;
struct buf *bp = NULL;
struct vnode *vp = ITOV(ip);
- uint32_t nb;
+ daddr_t newblk;
int osize, nsize, blks, error, allocated;
fs = ip->i_e2fs;
blks = howmany(size, fs->e2fs_bsize);
- error = ext4_ext_get_blocks(ip, lbn, blks, cred, NULL, &allocated, &nb);
+ error = ext4_ext_get_blocks(ip, lbn, blks, cred, NULL, &allocated, &newblk);
if (error)
return (error);
@@ -80,7 +81,7 @@
if(!bp)
return (EIO);
- bp->b_blkno = fsbtodb(fs, nb);
+ bp->b_blkno = fsbtodb(fs, newblk);
if (flags & BA_CLRBUF)
vfs_bio_clrbuf(bp);
} else {
@@ -91,7 +92,7 @@
brelse(bp);
return (error);
}
- bp->b_blkno = fsbtodb(fs, nb);
+ bp->b_blkno = fsbtodb(fs, newblk);
*bpp = bp;
return (0);
}
@@ -101,21 +102,15 @@
*/
osize = fragroundup(fs, blkoff(fs, ip->i_size));
nsize = fragroundup(fs, size);
- if (nsize <= osize) {
+ if (nsize <= osize)
error = bread(vp, lbn, osize, NOCRED, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
- bp->b_blkno = fsbtodb(fs, nb);
- } else {
+ else
error = bread(vp, lbn, fs->e2fs_bsize, NOCRED, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
- bp->b_blkno = fsbtodb(fs, nb);
+ if (error) {
+ brelse(bp);
+ return (error);
}
+ bp->b_blkno = fsbtodb(fs, newblk);
}
*bpp = bp;
@@ -218,6 +213,12 @@
nsize, cred, &newb);
if (error)
return (error);
+ /*
+ * If the newly allocated block exceeds 32-bit limit,
+ * we can not use it in file block maps.
+ */
+ if (newb > UINT_MAX)
+ return (EFBIG);
bp = getblk(vp, lbn, nsize, 0, 0, 0);
bp->b_blkno = fsbtodb(fs, newb);
if (flags & BA_CLRBUF)
@@ -250,6 +251,8 @@
if ((error = ext2_alloc(ip, lbn, pref, fs->e2fs_bsize, cred,
&newb)))
return (error);
+ if (newb > UINT_MAX)
+ return (EFBIG);
nb = newb;
bp = getblk(vp, indirs[1].in_lbn, fs->e2fs_bsize, 0, 0, 0);
bp->b_blkno = fsbtodb(fs, newb);
@@ -293,6 +296,8 @@
brelse(bp);
return (error);
}
+ if (newb > UINT_MAX)
+ return (EFBIG);
nb = newb;
nbp = getblk(vp, indirs[i].in_lbn, fs->e2fs_bsize, 0, 0, 0);
nbp->b_blkno = fsbtodb(fs, nb);
@@ -332,6 +337,8 @@
brelse(bp);
return (error);
}
+ if (newb > UINT_MAX)
+ return (EFBIG);
nb = newb;
nbp = getblk(vp, lbn, fs->e2fs_bsize, 0, 0, 0);
nbp->b_blkno = fsbtodb(fs, nb);
Index: fs/ext2fs/ext2_csum.c
===================================================================
--- fs/ext2fs/ext2_csum.c
+++ fs/ext2fs/ext2_csum.c
@@ -110,7 +110,7 @@
if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_64BIT) &&
offset < fs->e2fs->e3fs_desc_size)
crc = ext2_crc16(crc, (uint8_t *)gd + offset,
- fs->e2fs->e3fs_desc_size - offset);
+ fs->e2fs->e3fs_desc_size - offset);
return (crc);
}
Index: fs/ext2fs/ext2_extents.h
===================================================================
--- fs/ext2fs/ext2_extents.h
+++ fs/ext2fs/ext2_extents.h
@@ -120,7 +120,8 @@
int ext4_ext_remove_space(struct inode *ip, off_t length, int flags,
struct ucred *cred, struct thread *td);
int ext4_ext_get_blocks(struct inode *ip, int64_t iblock,
- unsigned long max_blocks, struct ucred *cred, struct buf **bpp, int *allocate, uint32_t *);
+ unsigned long max_blocks, struct ucred *cred, struct buf **bpp,
+ int *allocate, daddr_t *);
#ifdef EXT2FS_DEBUG
void ext4_ext_print_extent_tree_status(struct inode * ip);
#endif
Index: fs/ext2fs/ext2_extents.c
===================================================================
--- fs/ext2fs/ext2_extents.c
+++ fs/ext2fs/ext2_extents.c
@@ -1188,7 +1188,7 @@
int
ext4_ext_get_blocks(struct inode *ip, e4fs_daddr_t iblk,
unsigned long max_blocks, struct ucred *cred, struct buf **bpp,
- int *pallocated, uint32_t *nb)
+ int *pallocated, daddr_t *nb)
{
struct m_ext2fs *fs;
struct buf *bp = NULL;
Index: fs/ext2fs/ext2_extern.h
===================================================================
--- fs/ext2fs/ext2_extern.h
+++ fs/ext2fs/ext2_extern.h
@@ -102,6 +102,8 @@
int *, doff_t *, doff_t *, doff_t *, struct ext2fs_searchslot *);
int ext2_search_dirblock(struct inode *, void *, int *, const char *, int,
int *, doff_t *, doff_t *, doff_t *, struct ext2fs_searchslot *);
+uint32_t e2fs_gd_get_ndirs(struct ext2_gd *gd);
+uint64_t e2fs_gd_get_i_tables(struct ext2_gd *gd);
int ext2_gd_csum_verify(struct m_ext2fs *fs, struct cdev *dev);
void ext2_gd_csum_set(struct m_ext2fs *fs);
Index: fs/ext2fs/ext2_hash.c
===================================================================
--- fs/ext2fs/ext2_hash.c
+++ fs/ext2fs/ext2_hash.c
@@ -60,6 +60,7 @@
#include <sys/stat.h>
#include <sys/mount.h>
+#include <fs/ext2fs/ext2fs.h>
#include <fs/ext2fs/htree.h>
#include <fs/ext2fs/inode.h>
#include <fs/ext2fs/ext2_mount.h>
Index: fs/ext2fs/ext2_subr.c
===================================================================
--- fs/ext2fs/ext2_subr.c
+++ fs/ext2fs/ext2_subr.c
@@ -49,8 +49,8 @@
#include <sys/vnode.h>
#include <fs/ext2fs/inode.h>
-#include <fs/ext2fs/ext2_extern.h>
#include <fs/ext2fs/ext2fs.h>
+#include <fs/ext2fs/ext2_extern.h>
#include <fs/ext2fs/fs.h>
#include <fs/ext2fs/ext2_extents.h>
#include <fs/ext2fs/ext2_mount.h>
Index: fs/ext2fs/ext2_vfsops.c
===================================================================
--- fs/ext2fs/ext2_vfsops.c
+++ fs/ext2fs/ext2_vfsops.c
@@ -315,6 +315,17 @@
return (1);
}
}
+ /*
+ * Unfortunately, the extents with 64k block size are not supported
+ * for writing, there is a possibility to corrupt filesystem.
+ */
+ if (!ronly && (es->e2fs_features_incompat & EXT2F_INCOMPAT_EXTENTS) &&
+ es->e2fs_log_bsize == 6) {
+ printf("WARNING: R/W mount of %s denied due to "
+ "unsupported extents with 64k block size.\n",
+ devtoname(dev));
+ return (1);
+ }
return (0);
}
@@ -326,12 +337,20 @@
compute_sb_data(struct vnode *devvp, struct ext2fs *es,
struct m_ext2fs *fs)
{
- int db_count, error;
- int i;
+ int g_count = 0, error;
+ int i, j;
int logic_sb_block = 1; /* XXX for now */
struct buf *bp;
- uint32_t e2fs_descpb;
-
+ uint32_t e2fs_descpb, e2fs_gdbcount_alloc;
+
+ fs->e2fs_bcount = es->e2fs_bcount;
+ fs->e2fs_rbcount = es->e2fs_rbcount;
+ fs->e2fs_fbcount = es->e2fs_fbcount;
+ if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_64BIT)) {
+ fs->e2fs_bcount |= (uint64_t)(es->e4fs_bcount_hi) << 32;
+ fs->e2fs_rbcount |= (uint64_t)(es->e4fs_rbcount_hi) << 32;
+ fs->e2fs_fbcount |= (uint64_t)(es->e4fs_fbcount_hi) << 32;
+ }
fs->e2fs_bshift = EXT2_MIN_BLOCK_LOG_SIZE + es->e2fs_log_bsize;
fs->e2fs_bsize = 1U << fs->e2fs_bshift;
fs->e2fs_fsbtodb = es->e2fs_log_bsize + 1;
@@ -375,13 +394,19 @@
fs->e2fs_ipb = fs->e2fs_bsize / EXT2_INODE_SIZE(fs);
fs->e2fs_itpg = fs->e2fs_ipg / fs->e2fs_ipb;
/* s_resuid / s_resgid ? */
- fs->e2fs_gcount = howmany(es->e2fs_bcount - es->e2fs_first_dblock,
+ fs->e2fs_gcount = howmany(fs->e2fs_bcount - es->e2fs_first_dblock,
EXT2_BLOCKS_PER_GROUP(fs));
- e2fs_descpb = fs->e2fs_bsize / sizeof(struct ext2_gd);
- db_count = howmany(fs->e2fs_gcount, e2fs_descpb);
- fs->e2fs_gdbcount = db_count;
- fs->e2fs_gd = malloc(db_count * fs->e2fs_bsize,
- M_EXT2MNT, M_WAITOK);
+ if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_64BIT)) {
+ e2fs_descpb = fs->e2fs_bsize / sizeof(struct ext2_gd);
+ e2fs_gdbcount_alloc = howmany(fs->e2fs_gcount, e2fs_descpb);
+ } else {
+ e2fs_descpb = fs->e2fs_bsize / E2FS_REV0_GD_SIZE;
+ e2fs_gdbcount_alloc = howmany(fs->e2fs_gcount,
+ fs->e2fs_bsize / sizeof(struct ext2_gd));
+ }
+ fs->e2fs_gdbcount = howmany(fs->e2fs_gcount, e2fs_descpb);
+ fs->e2fs_gd = malloc(e2fs_gdbcount_alloc * fs->e2fs_bsize,
+ M_EXT2MNT, M_WAITOK | M_ZERO);
fs->e2fs_contigdirs = malloc(fs->e2fs_gcount *
sizeof(*fs->e2fs_contigdirs), M_EXT2MNT, M_WAITOK | M_ZERO);
@@ -392,7 +417,7 @@
*/
if (fs->e2fs_bsize > SBSIZE)
logic_sb_block = 0;
- for (i = 0; i < db_count; i++) {
+ for (i = 0; i < fs->e2fs_gdbcount; i++) {
error = bread(devvp,
fsbtodb(fs, logic_sb_block + i + 1),
fs->e2fs_bsize, NOCRED, &bp);
@@ -402,10 +427,17 @@
brelse(bp);
return (error);
}
- e2fs_cgload((struct ext2_gd *)bp->b_data,
- &fs->e2fs_gd[
- i * fs->e2fs_bsize / sizeof(struct ext2_gd)],
- fs->e2fs_bsize);
+ if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_64BIT)) {
+ memcpy(&fs->e2fs_gd[
+ i * fs->e2fs_bsize / sizeof(struct ext2_gd)],
+ bp->b_data, fs->e2fs_bsize);
+ } else {
+ for (j = 0; j < e2fs_descpb &&
+ g_count < fs->e2fs_gcount; j++, g_count++)
+ memcpy(&fs->e2fs_gd[g_count],
+ bp->b_data + j * E2FS_REV0_GD_SIZE,
+ E2FS_REV0_GD_SIZE);
+ }
brelse(bp);
bp = NULL;
}
@@ -823,9 +855,9 @@
sbp->f_bsize = EXT2_FRAG_SIZE(fs);
sbp->f_iosize = EXT2_BLOCK_SIZE(fs);
- sbp->f_blocks = fs->e2fs->e2fs_bcount - overhead;
- sbp->f_bfree = fs->e2fs->e2fs_fbcount;
- sbp->f_bavail = sbp->f_bfree - fs->e2fs->e2fs_rbcount;
+ sbp->f_blocks = fs->e2fs_bcount - overhead;
+ sbp->f_bfree = fs->e2fs_fbcount;
+ sbp->f_bavail = sbp->f_bfree - fs->e2fs_rbcount;
sbp->f_files = fs->e2fs->e2fs_icount;
sbp->f_ffree = fs->e2fs->e2fs_ficount;
return (0);
@@ -1069,6 +1101,15 @@
struct buf *bp;
int error = 0;
+ es->e2fs_bcount = fs->e2fs_bcount & 0xffffffff;
+ es->e2fs_rbcount = fs->e2fs_rbcount & 0xffffffff;
+ es->e2fs_fbcount = fs->e2fs_fbcount & 0xffffffff;
+ if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_64BIT)) {
+ es->e4fs_bcount_hi = fs->e2fs_bcount >> 32;
+ es->e4fs_rbcount_hi = fs->e2fs_rbcount >> 32;
+ es->e4fs_fbcount_hi = fs->e2fs_fbcount >> 32;
+ }
+
bp = getblk(mp->um_devvp, SBLOCK, SBSIZE, 0, 0, 0);
bcopy((caddr_t)es, bp->b_data, (u_int)sizeof(struct ext2fs));
if (waitfor == MNT_WAIT)
@@ -1088,7 +1129,7 @@
{
struct m_ext2fs *fs = mp->um_e2fs;
struct buf *bp;
- int i, error = 0, allerror = 0;
+ int i, j, g_count = 0, error = 0, allerror = 0;
allerror = ext2_sbupdate(mp, waitfor);
@@ -1100,9 +1141,16 @@
bp = getblk(mp->um_devvp, fsbtodb(fs,
fs->e2fs->e2fs_first_dblock +
1 /* superblock */ + i), fs->e2fs_bsize, 0, 0, 0);
- e2fs_cgsave(&fs->e2fs_gd[
- i * fs->e2fs_bsize / sizeof(struct ext2_gd)],
- (struct ext2_gd *)bp->b_data, fs->e2fs_bsize);
+ if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_64BIT)) {
+ memcpy(bp->b_data, &fs->e2fs_gd[
+ i * fs->e2fs_bsize / sizeof(struct ext2_gd)],
+ fs->e2fs_bsize);
+ } else {
+ for (j = 0; j < fs->e2fs_bsize / E2FS_REV0_GD_SIZE &&
+ g_count < fs->e2fs_gcount; j++, g_count++)
+ memcpy(bp->b_data + j * E2FS_REV0_GD_SIZE,
+ &fs->e2fs_gd[g_count], E2FS_REV0_GD_SIZE);
+ }
if (waitfor == MNT_WAIT)
error = bwrite(bp);
else
Index: fs/ext2fs/ext2_vnops.c
===================================================================
--- fs/ext2fs/ext2_vnops.c
+++ fs/ext2fs/ext2_vnops.c
@@ -84,8 +84,8 @@
#include <fs/ext2fs/fs.h>
#include <fs/ext2fs/inode.h>
#include <fs/ext2fs/ext2_acl.h>
-#include <fs/ext2fs/ext2_extern.h>
#include <fs/ext2fs/ext2fs.h>
+#include <fs/ext2fs/ext2_extern.h>
#include <fs/ext2fs/ext2_dinode.h>
#include <fs/ext2fs/ext2_dir.h>
#include <fs/ext2fs/ext2_mount.h>
Index: fs/ext2fs/ext2fs.h
===================================================================
--- fs/ext2fs/ext2fs.h
+++ fs/ext2fs/ext2fs.h
@@ -156,6 +156,9 @@
char e2fs_fsmnt[MAXMNTLEN];/* name mounted on */
char e2fs_ronly; /* mounted read-only flag */
char e2fs_fmod; /* super block modified flag */
+ uint64_t e2fs_bcount; /* blocks count */
+ uint64_t e2fs_rbcount; /* reserved blocks count */
+ uint64_t e2fs_fbcount; /* free blocks count */
uint32_t e2fs_bsize; /* Block size */
uint32_t e2fs_bshift; /* calc of logical block no */
uint32_t e2fs_bpg; /* Number of blocks per group */
@@ -323,11 +326,10 @@
EXT2F_ROCOMPAT_DIR_NLINK | \
EXT2F_ROCOMPAT_HUGE_FILE | \
EXT2F_ROCOMPAT_EXTRA_ISIZE)
-#define EXT2F_INCOMPAT_SUPP EXT2F_INCOMPAT_FTYPE
+#define EXT2F_INCOMPAT_SUPP (EXT2F_INCOMPAT_FTYPE | \
+ EXT2F_INCOMPAT_64BIT)
#define EXT4F_RO_INCOMPAT_SUPP (EXT2F_INCOMPAT_EXTENTS | \
- EXT2F_INCOMPAT_RECOVER | \
- EXT2F_INCOMPAT_FLEX_BG | \
- EXT2F_INCOMPAT_META_BG )
+ EXT2F_INCOMPAT_RECOVER)
/* Assume that user mode programs are passing in an ext2fs superblock, not
* a kernel struct super_block. This will allow us to call the feature-test
@@ -375,14 +377,20 @@
uint16_t ext4bgd_i_bmap_csum; /* inode bitmap checksum */
uint16_t ext4bgd_i_unused; /* unused inode count */
uint16_t ext4bgd_csum; /* group descriptor checksum */
+ uint32_t ext4bgd_b_bitmap_hi; /* high bits of blocks bitmap block */
+ uint32_t ext4bgd_i_bitmap_hi; /* high bits of inodes bitmap block */
+ uint32_t ext4bgd_i_tables_hi; /* high bits of inodes table block */
+ uint16_t ext4bgd_nbfree_hi; /* high bits of number of free blocks */
+ uint16_t ext4bgd_nifree_hi; /* high bits of number of free inodes */
+ uint16_t ext4bgd_ndirs_hi; /* high bits of number of directories */
+ uint16_t ext4bgd_i_unused_hi; /* high bits of unused inode count */
+ uint32_t ext4bgd_x_bitmap_hi; /* high bits of snapshot exclusion */
+ uint16_t ext4bgd_b_bmap_csum_hi;/* high bits of block bitmap checksum */
+ uint16_t ext4bgd_i_bmap_csum_hi;/* high bits of inode bitmap checksum */
+ uint32_t ext4bgd_reserved;
};
-/* EXT2FS metadata is stored in little-endian byte order. These macros
- * help reading it.
- */
-
-#define e2fs_cgload(old, new, size) memcpy((new), (old), (size));
-#define e2fs_cgsave(old, new, size) memcpy((new), (old), (size));
+#define E2FS_REV0_GD_SIZE (sizeof(struct ext2_gd) / 2)
/*
* Macro-instructions used to manage several block sizes
Index: fs/ext2fs/fs.h
===================================================================
--- fs/ext2fs/fs.h
+++ fs/ext2fs/fs.h
@@ -108,7 +108,7 @@
/* get block containing inode from its number x */
#define ino_to_fsba(fs, x) \
- ((fs)->e2fs_gd[ino_to_cg((fs), (x))].ext2bgd_i_tables + \
+ (e2fs_gd_get_i_tables(&(fs)->e2fs_gd[ino_to_cg((fs), (x))]) + \
(((x) - 1) % (fs)->e2fs->e2fs_ipg) / (fs)->e2fs_ipb)
/* get offset for inode in block */

File Metadata

Mime Type
text/plain
Expires
Tue, Apr 21, 3:23 PM (2 h, 10 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31917849
Default Alt Text
D11530.id36802.diff (28 KB)

Event Timeline