The following series of patches implement API call needed to handle
64-bit block numbers. Im concentrating mainly in providing the API
call first and if the interfaces are sane, we can go ahead and start
using them in the rest of libext2fs and the user space programs.
It also introduces the changes needed in order to for mke2fs to
support larger that 32-bit blocknr devices.
Bitmap dependencies are commented with "/* FIXME-64 */" to make them
easy to find and replace with the new interface.
-JRS
From: Jose R. Santos <[email protected]>
Add ext2_off64_t type.
The ext2_off_t is u32. Creating a new 64-bit ext2_off64_t for 64bit
offsets.
Signed-off-by: Jose R. Santos <[email protected]>
--
lib/ext2fs/ext2fs.h | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
Signed-off-by: Theodore Ts'o <[email protected]>
--
lib/ext2fs/ext2fs.h | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index 04a95a2..d9337aa 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -68,6 +68,7 @@ typedef __u32 blk_t;
typedef __u64 blk64_t;
typedef __u32 dgrp_t;
typedef __u32 ext2_off_t;
+typedef __u64 ext2_off64_t;
typedef __s64 e2_blkcnt_t;
typedef __u32 ext2_dirhash_t;
From: Jose R. Santos <[email protected]>
Use blk64_t for blocks in struct ext2_file.
The ext2_file structure is never exposed through the libext2fs API so
it is safe to use 64-bit blocks for blockno and physclock without
breaking the ABI.
Signed-off-by: Jose R. Santos <[email protected]>
--
lib/ext2fs/fileio.c | 12 ++++++------
1 files changed, 6 insertions(+), 6 deletions(-)
Signed-off-by: Theodore Ts'o <[email protected]>
--
lib/ext2fs/fileio.c | 12 ++++++------
1 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/lib/ext2fs/fileio.c b/lib/ext2fs/fileio.c
index 8bf99fb..4b9e1ce 100644
--- a/lib/ext2fs/fileio.c
+++ b/lib/ext2fs/fileio.c
@@ -25,8 +25,8 @@ struct ext2_file {
struct ext2_inode inode;
int flags;
__u64 pos;
- blk_t blockno;
- blk_t physblock;
+ blk64_t blockno;
+ blk64_t physblock;
char *buf;
};
@@ -116,9 +116,9 @@ errcode_t ext2fs_file_flush(ext2_file_t file)
* Allocate it.
*/
if (!file->physblock) {
- retval = ext2fs_bmap(fs, file->ino, &file->inode,
+ retval = ext2fs_bmap2(fs, file->ino, &file->inode,
BMAP_BUFFER, file->ino ? BMAP_ALLOC : 0,
- file->blockno, &file->physblock);
+ file->blockno, 0, &file->physblock);
if (retval)
return retval;
}
@@ -168,8 +168,8 @@ static errcode_t load_buffer(ext2_file_t file, int dontfill)
errcode_t retval;
if (!(file->flags & EXT2_FILE_BUF_VALID)) {
- retval = ext2fs_bmap(fs, file->ino, &file->inode,
- BMAP_BUFFER, 0, file->blockno,
+ retval = ext2fs_bmap2(fs, file->ino, &file->inode,
+ BMAP_BUFFER, 0, file->blockno, 0,
&file->physblock);
if (retval)
return retval;
From: Jose R. Santos <[email protected]>
libext2fs: Add 64-bit support to the undo manager
Signed-off-by: "Theodore Ts'o" <[email protected]>
--
lib/ext2fs/undo_io.c | 55 +++++++++++++++++++++++++++++++++++++++++---------
1 files changed, 45 insertions(+), 10 deletions(-)
diff --git a/lib/ext2fs/undo_io.c b/lib/ext2fs/undo_io.c
index 827c038..7661b83 100644
--- a/lib/ext2fs/undo_io.c
+++ b/lib/ext2fs/undo_io.c
@@ -73,6 +73,10 @@ struct undo_private_data {
static errcode_t undo_open(const char *name, int flags, io_channel *channel);
static errcode_t undo_close(io_channel channel);
static errcode_t undo_set_blksize(io_channel channel, int blksize);
+static errcode_t undo_read_blk64(io_channel channel, unsigned long long block,
+ int count, void *data);
+static errcode_t undo_write_blk64(io_channel channel, unsigned long long block,
+ int count, const void *data);
static errcode_t undo_read_blk(io_channel channel, unsigned long block,
int count, void *data);
static errcode_t undo_write_blk(io_channel channel, unsigned long block,
@@ -82,6 +86,7 @@ static errcode_t undo_write_byte(io_channel channel, unsigned long offset,
int size, const void *data);
static errcode_t undo_set_option(io_channel channel, const char *option,
const char *arg);
+static errcode_t undo_get_stats(io_channel channel, io_stats *stats);
static struct struct_io_manager struct_undo_manager = {
EXT2_ET_MAGIC_IO_MANAGER,
@@ -93,7 +98,10 @@ static struct struct_io_manager struct_undo_manager = {
undo_write_blk,
undo_flush,
undo_write_byte,
- undo_set_option
+ undo_set_option,
+ undo_get_stats,
+ undo_read_blk64,
+ undo_write_blk64,
};
io_manager undo_io_manager = &struct_undo_manager;
@@ -190,17 +198,17 @@ static errcode_t write_block_size(TDB_CONTEXT *tdb, int block_size)
}
static errcode_t undo_write_tdb(io_channel channel,
- unsigned long block, int count)
+ unsigned long long block, int count)
{
int size, sz;
- unsigned long block_num, backing_blk_num;
+ unsigned long long block_num, backing_blk_num;
errcode_t retval = 0;
ext2_loff_t offset;
struct undo_private_data *data;
TDB_DATA tdb_key, tdb_data;
unsigned char *read_ptr;
- unsigned long end_block;
+ unsigned long long end_block;
data = (struct undo_private_data *) channel->private_data;
@@ -266,7 +274,7 @@ static errcode_t undo_write_tdb(io_channel channel,
sz = count / channel->block_size;
else
sz = -count;
- retval = io_channel_read_blk(data->real, backing_blk_num,
+ retval = io_channel_read_blk64(data->real, backing_blk_num,
sz, read_ptr);
if (retval) {
if (retval != EXT2_ET_SHORT_READ) {
@@ -285,7 +293,7 @@ static errcode_t undo_write_tdb(io_channel channel,
tdb_data.dptr = read_ptr +
((offset - data->offset) % channel->block_size);
#ifdef DEBUG
- printf("Printing with key %ld data %x and size %d\n",
+ printf("Printing with key %lld data %x and size %d\n",
block_num,
tdb_data.dptr,
tdb_data.dsize);
@@ -455,7 +463,7 @@ static errcode_t undo_set_blksize(io_channel channel, int blksize)
return retval;
}
-static errcode_t undo_read_blk(io_channel channel, unsigned long block,
+static errcode_t undo_read_blk64(io_channel channel, unsigned long long block,
int count, void *buf)
{
errcode_t retval = 0;
@@ -466,12 +474,18 @@ static errcode_t undo_read_blk(io_channel channel, unsigned long block,
EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
if (data->real)
- retval = io_channel_read_blk(data->real, block, count, buf);
+ retval = io_channel_read_blk64(data->real, block, count, buf);
return retval;
}
-static errcode_t undo_write_blk(io_channel channel, unsigned long block,
+static errcode_t undo_read_blk(io_channel channel, unsigned long block,
+ int count, void *buf)
+{
+ return undo_read_blk64(channel, block, count, buf);
+}
+
+static errcode_t undo_write_blk64(io_channel channel, unsigned long long block,
int count, const void *buf)
{
struct undo_private_data *data;
@@ -487,11 +501,17 @@ static errcode_t undo_write_blk(io_channel channel, unsigned long block,
if (retval)
return retval;
if (data->real)
- retval = io_channel_write_blk(data->real, block, count, buf);
+ retval = io_channel_write_blk64(data->real, block, count, buf);
return retval;
}
+static errcode_t undo_write_blk(io_channel channel, unsigned long block,
+ int count, const void *buf)
+{
+ return undo_write_blk64(channel, block, count, buf);
+}
+
static errcode_t undo_write_byte(io_channel channel, unsigned long offset,
int size, const void *buf)
{
@@ -584,3 +604,18 @@ static errcode_t undo_set_option(io_channel channel, const char *option,
}
return retval;
}
+
+static errcode_t undo_get_stats(io_channel channel, io_stats *stats)
+{
+ errcode_t retval;
+ struct undo_private_data *data;
+
+ EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+ data = (struct undo_private_data *) channel->private_data;
+ EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
+
+ if (data->real)
+ retval = (data->real->manager->get_stats)(data->real, stats);
+
+ return retval;
+}
From: Jose R. Santos <[email protected]>
Add 64-bit alloc_stats interface.
Add new ext2fs_block_alloc_stats2() routine that takes blk64_t as an
input.
Signed-off-by: Jose R. Santos <[email protected]>
--
lib/ext2fs/alloc_stats.c | 11 +++++++++--
lib/ext2fs/ext2fs.h | 1 +
2 files changed, 10 insertions(+), 2 deletions(-)
Signed-off-by: Theodore Ts'o <[email protected]>
--
lib/ext2fs/alloc_stats.c | 11 +++++++++--
lib/ext2fs/ext2fs.h | 1 +
2 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/lib/ext2fs/alloc_stats.c b/lib/ext2fs/alloc_stats.c
index a8514cc..7288829 100644
--- a/lib/ext2fs/alloc_stats.c
+++ b/lib/ext2fs/alloc_stats.c
@@ -54,13 +54,15 @@ void ext2fs_inode_alloc_stats(ext2_filsys fs, ext2_ino_t ino, int inuse)
ext2fs_inode_alloc_stats2(fs, ino, inuse, 0);
}
-void ext2fs_block_alloc_stats(ext2_filsys fs, blk_t blk, int inuse)
+void ext2fs_block_alloc_stats2(ext2_filsys fs, blk64_t blk, int inuse)
{
- int group = ext2fs_group_of_blk(fs, blk);
+ int group = ext2fs_group_of_blk2(fs, blk);
if (inuse > 0)
+ /* FIXME-64 */
ext2fs_mark_block_bitmap(fs->block_map, blk);
else
+ /* FIXME-64 */
ext2fs_unmark_block_bitmap(fs->block_map, blk);
fs->group_desc[group].bg_free_blocks_count -= inuse;
fs->group_desc[group].bg_flags &= ~EXT2_BG_BLOCK_UNINIT;
@@ -88,3 +90,8 @@ void ext2fs_set_block_alloc_stats_callback(ext2_filsys fs,
fs->block_alloc_stats = func;
}
+
+void ext2fs_block_alloc_stats(ext2_filsys fs, blk_t blk, int inuse)
+{
+ ext2fs_block_alloc_stats2(fs, blk, inuse);
+}
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index a643aa1..fd5b69a 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -586,6 +586,7 @@ void ext2fs_inode_alloc_stats(ext2_filsys fs, ext2_ino_t ino, int inuse);
void ext2fs_inode_alloc_stats2(ext2_filsys fs, ext2_ino_t ino,
int inuse, int isdir);
void ext2fs_block_alloc_stats(ext2_filsys fs, blk_t blk, int inuse);
+void ext2fs_block_alloc_stats2(ext2_filsys fs, blk64_t blk, int inuse);
/* alloc_tables.c */
extern errcode_t ext2fs_allocate_tables(ext2_filsys fs);
From: Jose R. Santos <[email protected]>
Add 64-bit alloc interface.
Add new ext2fs_new_block2(), ext2fs_get_free_blocks2() and
ext2fs_alloc_block2() that take and return blk64_t.
Signed-off-by: Jose R. Santos <[email protected]>
--
lib/ext2fs/alloc.c | 70 ++++++++++++++++++++++++++++++++++++++-------------
lib/ext2fs/ext2fs.h | 8 ++++++
2 files changed, 60 insertions(+), 18 deletions(-)
diff --git a/lib/ext2fs/alloc.c b/lib/ext2fs/alloc.c
index f8d8a5f..411e934 100644
--- a/lib/ext2fs/alloc.c
+++ b/lib/ext2fs/alloc.c
@@ -73,10 +73,10 @@ errcode_t ext2fs_new_inode(ext2_filsys fs, ext2_ino_t dir,
* Stupid algorithm --- we now just search forward starting from the
* goal. Should put in a smarter one someday....
*/
-errcode_t ext2fs_new_block(ext2_filsys fs, blk_t goal,
- ext2fs_block_bitmap map, blk_t *ret)
+errcode_t ext2fs_new_block2(ext2_filsys fs, blk64_t goal,
+ ext2fs_block_bitmap map, blk64_t *ret)
{
- blk_t i;
+ blk64_t i;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
@@ -88,7 +88,8 @@ errcode_t ext2fs_new_block(ext2_filsys fs, blk_t goal,
goal = fs->super->s_first_data_block;
i = goal;
do {
- if (!ext2fs_fast_test_block_bitmap(map, i)) {
+ /* FIXME-64 */
+ if (!ext2fs_fast_test_block_bitmap(map, (blk_t) i)) {
*ret = i;
return 0;
}
@@ -99,15 +100,26 @@ errcode_t ext2fs_new_block(ext2_filsys fs, blk_t goal,
return EXT2_ET_BLOCK_ALLOC_FAIL;
}
+errcode_t ext2fs_new_block(ext2_filsys fs, blk_t goal,
+ ext2fs_block_bitmap map, blk_t *ret)
+{
+ errcode_t retval;
+ blk64_t val;
+ retval = ext2fs_new_block2(fs, goal, map, &val);
+ if (!retval)
+ *ret = (blk_t) val;
+ return retval;
+}
+
/*
* This function zeros out the allocated block, and updates all of the
* appropriate filesystem records.
*/
-errcode_t ext2fs_alloc_block(ext2_filsys fs, blk_t goal,
- char *block_buf, blk_t *ret)
+errcode_t ext2fs_alloc_block2(ext2_filsys fs, blk64_t goal,
+ char *block_buf, blk64_t *ret)
{
errcode_t retval;
- blk_t block;
+ blk64_t block;
char *buf = 0;
if (!block_buf) {
@@ -119,29 +131,27 @@ errcode_t ext2fs_alloc_block(ext2_filsys fs, blk_t goal,
memset(block_buf, 0, fs->blocksize);
if (fs->get_alloc_block) {
- blk64_t new;
-
- retval = (fs->get_alloc_block)(fs, (blk64_t) goal, &new);
+ retval = (fs->get_alloc_block)(fs, goal, &block);
if (retval)
goto fail;
- block = (blk_t) new;
} else {
if (!fs->block_map) {
+ /* FIXME-64 */
retval = ext2fs_read_block_bitmap(fs);
if (retval)
goto fail;
}
- retval = ext2fs_new_block(fs, goal, 0, &block);
+ retval = ext2fs_new_block2(fs, goal, 0, &block);
if (retval)
goto fail;
}
- retval = io_channel_write_blk(fs->io, block, 1, block_buf);
+ retval = io_channel_write_blk64(fs->io, block, 1, block_buf);
if (retval)
goto fail;
- ext2fs_block_alloc_stats(fs, block, +1);
+ ext2fs_block_alloc_stats2(fs, block, +1);
*ret = block;
fail:
@@ -150,10 +160,21 @@ fail:
return retval;
}
-errcode_t ext2fs_get_free_blocks(ext2_filsys fs, blk_t start, blk_t finish,
- int num, ext2fs_block_bitmap map, blk_t *ret)
+errcode_t ext2fs_alloc_block(ext2_filsys fs, blk_t goal,
+ char *block_buf, blk_t *ret)
+{
+ errcode_t retval;
+ blk64_t val;
+ retval = ext2fs_alloc_block2(fs, goal, block_buf, &val);
+ if (!retval)
+ *ret = (blk_t) val;
+ return retval;
+}
+
+errcode_t ext2fs_get_free_blocks2(ext2_filsys fs, blk64_t start, blk64_t finish,
+ int num, ext2fs_block_bitmap map, blk64_t *ret)
{
- blk_t b = start;
+ blk64_t b = start;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
@@ -170,7 +191,9 @@ errcode_t ext2fs_get_free_blocks(ext2_filsys fs, blk_t start, blk_t finish,
do {
if (b+num-1 > fs->super->s_blocks_count)
b = fs->super->s_first_data_block;
- if (ext2fs_fast_test_block_bitmap_range(map, b, num)) {
+ /* FIXME-64 */
+ if (ext2fs_fast_test_block_bitmap_range(map, (blk_t) b,
+ (blk_t) num)) {
*ret = b;
return 0;
}
@@ -179,6 +202,17 @@ errcode_t ext2fs_get_free_blocks(ext2_filsys fs, blk_t start, blk_t finish,
return EXT2_ET_BLOCK_ALLOC_FAIL;
}
+errcode_t ext2fs_get_free_blocks(ext2_filsys fs, blk_t start, blk_t finish,
+ int num, ext2fs_block_bitmap map, blk_t *ret)
+{
+ errcode_t retval;
+ blk64_t val;
+ retval = ext2fs_get_free_blocks2(fs, start, finish, num, map, &val);
+ if(!retval)
+ *ret = (blk_t) val;
+ return retval;
+}
+
void ext2fs_set_alloc_block_callback(ext2_filsys fs,
errcode_t (*func)(ext2_filsys fs,
blk64_t goal,
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index fd5b69a..66073e8 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -555,12 +555,20 @@ extern errcode_t ext2fs_new_inode(ext2_filsys fs, ext2_ino_t dir, int mode,
ext2fs_inode_bitmap map, ext2_ino_t *ret);
extern errcode_t ext2fs_new_block(ext2_filsys fs, blk_t goal,
ext2fs_block_bitmap map, blk_t *ret);
+extern errcode_t ext2fs_new_block2(ext2_filsys fs, blk64_t goal,
+ ext2fs_block_bitmap map, blk64_t *ret);
extern errcode_t ext2fs_get_free_blocks(ext2_filsys fs, blk_t start,
blk_t finish, int num,
ext2fs_block_bitmap map,
blk_t *ret);
+extern errcode_t ext2fs_get_free_blocks2(ext2_filsys fs, blk64_t start,
+ blk64_t finish, int num,
+ ext2fs_block_bitmap map,
+ blk64_t *ret);
extern errcode_t ext2fs_alloc_block(ext2_filsys fs, blk_t goal,
char *block_buf, blk_t *ret);
+extern errcode_t ext2fs_alloc_block2(ext2_filsys fs, blk64_t goal,
+ char *block_buf, blk64_t *ret);
extern void ext2fs_set_alloc_block_callback(ext2_filsys fs,
errcode_t (*func)(ext2_filsys fs,
blk64_t goal,
From: Jose R. Santos <[email protected]>
Add 64-bit ext_attr interface.
Add ext2fs_read_ext_attr2(), ext2fs_write_ext_attr2() and
ext2fs_adjust_ea_refcount2() that take blk64_t as an input.
Signed-off-by: Jose R. Santos <[email protected]>
--
lib/ext2fs/ext2fs.h | 7 +++++++
lib/ext2fs/ext_attr.c | 31 ++++++++++++++++++++++++-------
2 files changed, 31 insertions(+), 7 deletions(-)
Signed-off-by: Theodore Ts'o <[email protected]>
--
lib/ext2fs/ext2fs.h | 7 +++++++
lib/ext2fs/ext_attr.c | 31 ++++++++++++++++++++++++-------
2 files changed, 31 insertions(+), 7 deletions(-)
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index 66073e8..d576181 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -867,11 +867,18 @@ extern errcode_t ext2fs_expand_dir(ext2_filsys fs, ext2_ino_t dir);
extern __u32 ext2fs_ext_attr_hash_entry(struct ext2_ext_attr_entry *entry,
void *data);
extern errcode_t ext2fs_read_ext_attr(ext2_filsys fs, blk_t block, void *buf);
+extern errcode_t ext2fs_read_ext_attr2(ext2_filsys fs, blk64_t block,
+ void *buf);
extern errcode_t ext2fs_write_ext_attr(ext2_filsys fs, blk_t block,
void *buf);
+extern errcode_t ext2fs_write_ext_attr2(ext2_filsys fs, blk64_t block,
+ void *buf);
extern errcode_t ext2fs_adjust_ea_refcount(ext2_filsys fs, blk_t blk,
char *block_buf,
int adjust, __u32 *newcount);
+extern errcode_t ext2fs_adjust_ea_refcount2(ext2_filsys fs, blk64_t blk,
+ char *block_buf,
+ int adjust, __u32 *newcount);
/* extent.c */
extern errcode_t ext2fs_extent_header_verify(void *ptr, int size);
diff --git a/lib/ext2fs/ext_attr.c b/lib/ext2fs/ext_attr.c
index 3d208ec..395d4c7 100644
--- a/lib/ext2fs/ext_attr.c
+++ b/lib/ext2fs/ext_attr.c
@@ -60,11 +60,11 @@ __u32 ext2fs_ext_attr_hash_entry(struct ext2_ext_attr_entry *entry, void *data)
#undef NAME_HASH_SHIFT
#undef VALUE_HASH_SHIFT
-errcode_t ext2fs_read_ext_attr(ext2_filsys fs, blk_t block, void *buf)
+errcode_t ext2fs_read_ext_attr2(ext2_filsys fs, blk64_t block, void *buf)
{
errcode_t retval;
- retval = io_channel_read_blk(fs->io, block, 1, buf);
+ retval = io_channel_read_blk64(fs->io, block, 1, buf);
if (retval)
return retval;
#ifdef WORDS_BIGENDIAN
@@ -73,7 +73,12 @@ errcode_t ext2fs_read_ext_attr(ext2_filsys fs, blk_t block, void *buf)
return 0;
}
-errcode_t ext2fs_write_ext_attr(ext2_filsys fs, blk_t block, void *inbuf)
+errcode_t ext2fs_read_ext_attr(ext2_filsys fs, blk_t block, void *buf)
+{
+ return ext2fs_read_ext_attr2(fs, block, buf);
+}
+
+errcode_t ext2fs_write_ext_attr2(ext2_filsys fs, blk64_t block, void *inbuf)
{
errcode_t retval;
char *write_buf;
@@ -88,7 +93,7 @@ errcode_t ext2fs_write_ext_attr(ext2_filsys fs, blk_t block, void *inbuf)
#else
write_buf = (char *) inbuf;
#endif
- retval = io_channel_write_blk(fs->io, block, 1, write_buf);
+ retval = io_channel_write_blk64(fs->io, block, 1, write_buf);
if (buf)
ext2fs_free_mem(&buf);
if (!retval)
@@ -96,10 +101,15 @@ errcode_t ext2fs_write_ext_attr(ext2_filsys fs, blk_t block, void *inbuf)
return retval;
}
+errcode_t ext2fs_write_ext_attr(ext2_filsys fs, blk_t block, void *inbuf)
+{
+ return ext2fs_write_ext_attr2(fs, block, inbuf);
+}
+
/*
* This function adjusts the reference count of the EA block.
*/
-errcode_t ext2fs_adjust_ea_refcount(ext2_filsys fs, blk_t blk,
+errcode_t ext2fs_adjust_ea_refcount2(ext2_filsys fs, blk64_t blk,
char *block_buf, int adjust,
__u32 *newcount)
{
@@ -118,7 +128,7 @@ errcode_t ext2fs_adjust_ea_refcount(ext2_filsys fs, blk_t blk,
block_buf = buf;
}
- retval = ext2fs_read_ext_attr(fs, blk, block_buf);
+ retval = ext2fs_read_ext_attr2(fs, blk, block_buf);
if (retval)
goto errout;
@@ -127,7 +137,7 @@ errcode_t ext2fs_adjust_ea_refcount(ext2_filsys fs, blk_t blk,
if (newcount)
*newcount = header->h_refcount;
- retval = ext2fs_write_ext_attr(fs, blk, block_buf);
+ retval = ext2fs_write_ext_attr2(fs, blk, block_buf);
if (retval)
goto errout;
@@ -136,3 +146,10 @@ errout:
ext2fs_free_mem(&buf);
return retval;
}
+
+errcode_t ext2fs_adjust_ea_refcount(ext2_filsys fs, blk_t blk,
+ char *block_buf, int adjust,
+ __u32 *newcount)
+{
+ return ext2fs_adjust_ea_refcount(fs, blk, block_buf, adjust, newcount);
+}
From: Jose R. Santos <[email protected]>
Add ext2fs_div64_ceil()
Add a new div_cell routine able to handle 64bit values
Signed-off-by: Jose R. Santos <[email protected]>
--
lib/ext2fs/ext2fs.h | 8 ++++++++
1 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index 0ca978b..3bc866e 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -1409,6 +1409,14 @@ _INLINE_ unsigned int ext2fs_div_ceil(unsigned int a, unsigned int b)
return 0;
return ((a - 1) / b) + 1;
}
+
+_INLINE_ __u64 ext2fs_div64_ceil(__u64 a, __u64 b)
+{
+ if (!a)
+ return 0;
+ return ((a - 1) / b) + 1;
+}
+
#undef _INLINE_
#endif
From: Jose R. Santos <[email protected]>
Add 64-bit openfs interface.
Add new ext2fs_descriptor_block_loc2() routine that takes blk64_t as
an input.
Signed-off-by: Jose R. Santos <[email protected]>
--
lib/ext2fs/ext2fs.h | 2 ++
lib/ext2fs/openfs.c | 12 +++++++++---
2 files changed, 11 insertions(+), 3 deletions(-)
Signed-off-by: Theodore Ts'o <[email protected]>
--
lib/ext2fs/ext2fs.h | 2 ++
lib/ext2fs/openfs.c | 12 +++++++++---
2 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index 464d323..0ca978b 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -1119,6 +1119,8 @@ extern errcode_t ext2fs_open2(const char *name, const char *io_options,
int flags, int superblock,
unsigned int block_size, io_manager manager,
ext2_filsys *ret_fs);
+extern blk64_t ext2fs_descriptor_block_loc2(ext2_filsys fs,
+ blk64_t group_block, dgrp_t i);
extern blk_t ext2fs_descriptor_block_loc(ext2_filsys fs, blk_t group_block,
dgrp_t i);
errcode_t ext2fs_get_data_io(ext2_filsys fs, io_channel *old_io);
diff --git a/lib/ext2fs/openfs.c b/lib/ext2fs/openfs.c
index 525693e..77f6442 100644
--- a/lib/ext2fs/openfs.c
+++ b/lib/ext2fs/openfs.c
@@ -29,11 +29,12 @@
#include "ext2fs.h"
#include "e2image.h"
-blk_t ext2fs_descriptor_block_loc(ext2_filsys fs, blk_t group_block, dgrp_t i)
+blk64_t ext2fs_descriptor_block_loc2(ext2_filsys fs, blk64_t group_block,
+ dgrp_t i)
{
int bg;
int has_super = 0;
- int ret_blk;
+ blk64_t ret_blk;
if (!(fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) ||
(i < fs->super->s_first_meta_bg))
@@ -42,7 +43,7 @@ blk_t ext2fs_descriptor_block_loc(ext2_filsys fs, blk_t group_block, dgrp_t i)
bg = EXT2_DESC_PER_BLOCK(fs->super) * i;
if (ext2fs_bg_has_super(fs, bg))
has_super = 1;
- ret_blk = ext2fs_group_first_block(fs, bg) + has_super;
+ ret_blk = ext2fs_group_first_block2(fs, bg) + has_super;
/*
* If group_block is not the normal value, we're trying to use
* the backup group descriptors and superblock --- so use the
@@ -58,6 +59,11 @@ blk_t ext2fs_descriptor_block_loc(ext2_filsys fs, blk_t group_block, dgrp_t i)
return ret_blk;
}
+blk_t ext2fs_descriptor_block_loc(ext2_filsys fs, blk_t group_block, dgrp_t i)
+{
+ return ext2fs_descriptor_block_loc2(fs, group_block, i);
+}
+
errcode_t ext2fs_open(const char *name, int flags, int superblock,
unsigned int block_size, io_manager manager,
ext2_filsys *ret_fs)
From: Jose R. Santos <[email protected]>
Use new ext2fs_super_and_bgd_loc2 call in libext2fs.
The new ext2fs_super_and_bgd_loc2() function has some changes aside
from just blk64_t support. Lets make sure that the interfaces are
sane by adding libext2fs support early to get the new API tested here.
Signed-off-by: Jose R. Santos <[email protected]>
--
e2fsck/pass5.c | 7 ++++---
lib/ext2fs/alloc_sb.c | 23 +++++++++++++++++++----
lib/ext2fs/closefs.c | 9 +++++----
3 files changed, 28 insertions(+), 11 deletions(-)
Signed-off-by: Theodore Ts'o <[email protected]>
--
e2fsck/pass5.c | 7 ++++---
lib/ext2fs/alloc_sb.c | 23 +++++++++++++++++++----
lib/ext2fs/closefs.c | 9 +++++----
3 files changed, 28 insertions(+), 11 deletions(-)
diff --git a/e2fsck/pass5.c b/e2fsck/pass5.c
index cc17820..a729308 100644
--- a/e2fsck/pass5.c
+++ b/e2fsck/pass5.c
@@ -111,7 +111,8 @@ static void print_bitmap_problem(e2fsck_t ctx, int problem,
static void check_block_bitmaps(e2fsck_t ctx)
{
ext2_filsys fs = ctx->fs;
- blk_t i, super;
+ blk64_t i;
+ blk_t super;
int *free_array;
int group = 0;
blk_t blocks = 0;
@@ -174,10 +175,10 @@ redo_counts:
actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i);
if (skip_group) {
- blk_t super_blk, old_desc_blk, new_desc_blk;
+ blk64_t super_blk, old_desc_blk, new_desc_blk;
int old_desc_blocks;
- ext2fs_super_and_bgd_loc(fs, group, &super_blk,
+ ext2fs_super_and_bgd_loc2(fs, group, &super_blk,
&old_desc_blk, &new_desc_blk, 0);
if (fs->super->s_feature_incompat &
diff --git a/lib/ext2fs/alloc_sb.c b/lib/ext2fs/alloc_sb.c
index cdcb866..94a79c2 100644
--- a/lib/ext2fs/alloc_sb.c
+++ b/lib/ext2fs/alloc_sb.c
@@ -44,11 +44,12 @@ int ext2fs_reserve_super_and_bgd(ext2_filsys fs,
dgrp_t group,
ext2fs_block_bitmap bmap)
{
- blk_t super_blk, old_desc_blk, new_desc_blk;
+ blk64_t super_blk, old_desc_blk, new_desc_blk;
+ blk_t used_blks;
int j, old_desc_blocks, num_blocks;
- num_blocks = ext2fs_super_and_bgd_loc(fs, group, &super_blk,
- &old_desc_blk, &new_desc_blk, 0);
+ ext2fs_super_and_bgd_loc2(fs, group, &super_blk,
+ &old_desc_blk, &new_desc_blk, &used_blks);
if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
old_desc_blocks = fs->super->s_first_meta_bg;
@@ -57,6 +58,7 @@ int ext2fs_reserve_super_and_bgd(ext2_filsys fs,
fs->desc_blocks + fs->super->s_reserved_gdt_blocks;
if (super_blk || (group == 0))
+ /* FIXME-64 */
ext2fs_mark_block_bitmap(bmap, super_blk);
if (old_desc_blk) {
@@ -64,11 +66,24 @@ int ext2fs_reserve_super_and_bgd(ext2_filsys fs,
fs->group_desc[group].bg_flags &= ~EXT2_BG_BLOCK_UNINIT;
for (j=0; j < old_desc_blocks; j++)
if (old_desc_blk + j < fs->super->s_blocks_count)
+ /* FIXME-64 */
ext2fs_mark_block_bitmap(bmap,
old_desc_blk + j);
}
if (new_desc_blk)
+ /* FIXME-64 */
ext2fs_mark_block_bitmap(bmap, new_desc_blk);
- return num_blocks;
+ if (group == fs->group_desc_count-1) {
+ num_blocks = (fs->super->s_blocks_count -
+ fs->super->s_first_data_block) %
+ fs->super->s_blocks_per_group;
+ if (!num_blocks)
+ num_blocks = fs->super->s_blocks_per_group;
+ } else
+ num_blocks = fs->super->s_blocks_per_group;
+
+ num_blocks -= 2 + fs->inode_blocks_per_group + used_blks;
+
+ return num_blocks ;
}
diff --git a/lib/ext2fs/closefs.c b/lib/ext2fs/closefs.c
index 8231ca6..b61556e 100644
--- a/lib/ext2fs/closefs.c
+++ b/lib/ext2fs/closefs.c
@@ -338,11 +338,10 @@ errcode_t ext2fs_flush(ext2_filsys fs)
old_desc_blocks = fs->desc_blocks;
for (i = 0; i < fs->group_desc_count; i++) {
- blk_t super_blk, old_desc_blk, new_desc_blk;
- int meta_bg;
+ blk64_t super_blk, old_desc_blk, new_desc_blk;
- ext2fs_super_and_bgd_loc(fs, i, &super_blk, &old_desc_blk,
- &new_desc_blk, &meta_bg);
+ ext2fs_super_and_bgd_loc2(fs, i, &super_blk, &old_desc_blk,
+ &new_desc_blk, 0);
if (!(fs->flags & EXT2_FLAG_MASTER_SB_ONLY) &&i && super_blk) {
retval = write_backup_super(fs, i, super_blk,
@@ -360,6 +359,8 @@ errcode_t ext2fs_flush(ext2_filsys fs)
goto errout;
}
if (new_desc_blk) {
+ int meta_bg = i / EXT2_DESC_PER_BLOCK(fs->super);
+
retval = io_channel_write_blk(fs->io, new_desc_blk,
1, group_ptr + (meta_bg*fs->blocksize));
if (retval)
From: Jose R. Santos <[email protected]>
Add 64-bit closefs interface.
Add new ext2fs_super_and_bgd_loc2() that returns blk64_t pointers.
The function now returns the number of blocks used by super block and
group descriptors since with flex_bg, it can no longer be assumed that
bitmaps and inode tables still resided within the block group.
Signed-off-by: Jose R. Santos <[email protected]>
--
lib/ext2fs/closefs.c | 120 +++++++++++++++++++++++++++++++++++---------------
lib/ext2fs/ext2fs.h | 6 +++
2 files changed, 90 insertions(+), 36 deletions(-)
Signed-off-by: Theodore Ts'o <[email protected]>
--
lib/ext2fs/closefs.c | 120 +++++++++++++++++++++++++++++++++++---------------
lib/ext2fs/ext2fs.h | 6 +++
2 files changed, 90 insertions(+), 36 deletions(-)
diff --git a/lib/ext2fs/closefs.c b/lib/ext2fs/closefs.c
index 206faa6..8231ca6 100644
--- a/lib/ext2fs/closefs.c
+++ b/lib/ext2fs/closefs.c
@@ -46,31 +46,33 @@ int ext2fs_bg_has_super(ext2_filsys fs, int group_block)
}
/*
- * This function returns the location of the superblock, block group
- * descriptors for a given block group. It currently returns the
- * number of free blocks assuming that inode table and allocation
- * bitmaps will be in the group. This is not necessarily the case
- * when the flex_bg feature is enabled, so callers should take care!
- * It was only really intended for use by mke2fs, and even there it's
- * not that useful. In the future, when we redo this function for
- * 64-bit block numbers, we should probably return the number of
- * blocks used by the super block and group descriptors instead.
+ * ext2fs_super_and_bgd_loc2()
+ * @fs: ext2 fs pointer
+ * @group given block group
+ * @ret_super_blk: if !NULL, returns super block location
+ * @ret_old_desc_blk: if !NULL, returns location of the old block
+ * group descriptor
+ * @ret_new_desc_blk: if !NULL, returns location of meta_bg block
+ * group descriptor
+ * @ret_used_blks: if !NULL, returns number of blocks used by
+ * super block and group_descriptors.
*
- * See also the comment for ext2fs_reserve_super_and_bgd()
+ * Returns errcode_t of 0
*/
-int ext2fs_super_and_bgd_loc(ext2_filsys fs,
- dgrp_t group,
- blk_t *ret_super_blk,
- blk_t *ret_old_desc_blk,
- blk_t *ret_new_desc_blk,
- int *ret_meta_bg)
+errcode_t ext2fs_super_and_bgd_loc2(ext2_filsys fs,
+ dgrp_t group,
+ blk64_t *ret_super_blk,
+ blk64_t *ret_old_desc_blk,
+ blk64_t *ret_new_desc_blk,
+ blk_t *ret_used_blks)
{
- blk_t group_block, super_blk = 0, old_desc_blk = 0, new_desc_blk = 0;
+ blk64_t group_block, super_blk = 0, old_desc_blk = 0, new_desc_blk = 0;
unsigned int meta_bg, meta_bg_size;
- blk_t numblocks, old_desc_blocks;
+ blk_t numblocks = 0;
+ blk64_t old_desc_blocks;
int has_super;
- group_block = ext2fs_group_first_block(fs, group);
+ group_block = ext2fs_group_first_block2(fs, group);
if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
old_desc_blocks = fs->super->s_first_meta_bg;
@@ -78,20 +80,11 @@ int ext2fs_super_and_bgd_loc(ext2_filsys fs,
old_desc_blocks =
fs->desc_blocks + fs->super->s_reserved_gdt_blocks;
- if (group == fs->group_desc_count-1) {
- numblocks = (fs->super->s_blocks_count -
- fs->super->s_first_data_block) %
- fs->super->s_blocks_per_group;
- if (!numblocks)
- numblocks = fs->super->s_blocks_per_group;
- } else
- numblocks = fs->super->s_blocks_per_group;
-
has_super = ext2fs_bg_has_super(fs, group);
if (has_super) {
super_blk = group_block;
- numblocks--;
+ numblocks++;
}
meta_bg_size = EXT2_DESC_PER_BLOCK(fs->super);
meta_bg = group / meta_bg_size;
@@ -100,7 +93,7 @@ int ext2fs_super_and_bgd_loc(ext2_filsys fs,
(meta_bg < fs->super->s_first_meta_bg)) {
if (has_super) {
old_desc_blk = group_block + 1;
- numblocks -= old_desc_blocks;
+ numblocks += old_desc_blocks;
}
} else {
if (((group % meta_bg_size) == 0) ||
@@ -109,11 +102,9 @@ int ext2fs_super_and_bgd_loc(ext2_filsys fs,
if (has_super)
has_super = 1;
new_desc_blk = group_block + has_super;
- numblocks--;
+ numblocks++;
}
}
-
- numblocks -= 2 + fs->inode_blocks_per_group;
if (ret_super_blk)
*ret_super_blk = super_blk;
@@ -121,11 +112,68 @@ int ext2fs_super_and_bgd_loc(ext2_filsys fs,
*ret_old_desc_blk = old_desc_blk;
if (ret_new_desc_blk)
*ret_new_desc_blk = new_desc_blk;
- if (ret_meta_bg)
- *ret_meta_bg = meta_bg;
- return (numblocks);
+ if (ret_used_blks)
+ *ret_used_blks = numblocks;
+
+ return 0;
}
+/*
+ * This function returns the location of the superblock, block group
+ * descriptors for a given block group. It currently returns the
+ * number of free blocks assuming that inode table and allocation
+ * bitmaps will be in the group. This is not necessarily the case
+ * when the flex_bg feature is enabled, so callers should take care!
+ * It was only really intended for use by mke2fs, and even there it's
+ * not that useful.
+ *
+ * The ext2fs_super_and_bgd_loc2() function is 64-bit block number
+ * capable and returns the number of blocks used by super block and
+ * group descriptors.
+ */
+int ext2fs_super_and_bgd_loc(ext2_filsys fs,
+ dgrp_t group,
+ blk_t *ret_super_blk,
+ blk_t *ret_old_desc_blk,
+ blk_t *ret_new_desc_blk,
+ int *ret_meta_bg)
+{
+ blk64_t ret_super_blk2;
+ blk64_t ret_old_desc_blk2;
+ blk64_t ret_new_desc_blk2;
+ blk_t ret_used_blks;
+ blk_t numblocks;
+ unsigned int meta_bg_size;
+
+ ext2fs_super_and_bgd_loc2(fs, group, &ret_super_blk2,
+ &ret_old_desc_blk2,
+ &ret_new_desc_blk2,
+ &ret_used_blks);
+
+ if (group == fs->group_desc_count-1) {
+ numblocks = (fs->super->s_blocks_count -
+ fs->super->s_first_data_block) %
+ fs->super->s_blocks_per_group;
+ if (!numblocks)
+ numblocks = fs->super->s_blocks_per_group;
+ } else
+ numblocks = fs->super->s_blocks_per_group;
+
+ if (ret_super_blk)
+ *ret_super_blk = (blk_t)ret_super_blk2;
+ if (ret_old_desc_blk)
+ *ret_old_desc_blk = (blk_t)ret_old_desc_blk2;
+ if (ret_new_desc_blk)
+ *ret_new_desc_blk = (blk_t)ret_new_desc_blk2;
+ if (ret_meta_bg) {
+ meta_bg_size = EXT2_DESC_PER_BLOCK(fs->super);
+ *ret_meta_bg = group / meta_bg_size;
+ }
+
+ numblocks -= 2 + fs->inode_blocks_per_group + ret_used_blks;
+
+ return numblocks;
+}
/*
* This function forces out the primary superblock. We need to only
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index d576181..464d323 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -763,6 +763,12 @@ extern errcode_t ext2fs_check_desc(ext2_filsys fs);
extern errcode_t ext2fs_close(ext2_filsys fs);
extern errcode_t ext2fs_flush(ext2_filsys fs);
extern int ext2fs_bg_has_super(ext2_filsys fs, int group_block);
+extern errcode_t ext2fs_super_and_bgd_loc2(ext2_filsys fs,
+ dgrp_t group,
+ blk64_t *ret_super_blk,
+ blk64_t *ret_old_desc_blk,
+ blk64_t *ret_new_desc_blk,
+ blk_t *ret_used_blks);
extern int ext2fs_super_and_bgd_loc(ext2_filsys fs,
dgrp_t group,
blk_t *ret_super_blk,
From: Jose R. Santos <[email protected]>
Add new blk64_t handling functions
Add new blknum.c file which contains funtions to handle blk64_t and
low/high values in super blocks and inodes.
Signed-off-by: Jose R. Santos <[email protected]>
--
lib/ext2fs/Makefile.in | 1
lib/ext2fs/blknum.c | 214 ++++++++++++++++++++++++++++++++++++++++++++++++
lib/ext2fs/ext2fs.h | 33 +++++--
3 files changed, 237 insertions(+), 11 deletions(-)
Signed-off-by: Theodore Ts'o <[email protected]>
--
lib/ext2fs/Makefile.in | 1
lib/ext2fs/blknum.c | 214 ++++++++++++++++++++++++++++++++++++++++++++++++
lib/ext2fs/ext2fs.h | 39 ++++++---
3 files changed, 243 insertions(+), 11 deletions(-)
diff --git a/lib/ext2fs/Makefile.in b/lib/ext2fs/Makefile.in
index 6f0ae62..3e7cbb9 100644
--- a/lib/ext2fs/Makefile.in
+++ b/lib/ext2fs/Makefile.in
@@ -26,6 +26,7 @@ OBJS= $(DEBUGFS_LIB_OBJS) $(RESIZE_LIB_OBJS) $(E2IMAGE_LIB_OBJS) \
bb_inode.o \
bitmaps.o \
bitops.o \
+ blknum.o \
block.o \
bmap.o \
check_desc.o \
diff --git a/lib/ext2fs/blknum.c b/lib/ext2fs/blknum.c
new file mode 100644
index 0000000..a09301e
--- /dev/null
+++ b/lib/ext2fs/blknum.c
@@ -0,0 +1,214 @@
+/*
+ * blknum.c --- Functions to handle blk64_t and high/low 64-bit block
+ * number.
+ *
+ * Copyright IBM Corporation, 2007
+ * Author Jose R. Santos <[email protected]>
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include "ext2fs.h"
+
+/*
+ * Return the group # of a block
+ */
+dgrp_t ext2fs_group_of_blk2(ext2_filsys fs, blk64_t blk)
+{
+ return (blk - fs->super->s_first_data_block) /
+ fs->super->s_blocks_per_group;
+}
+
+/*
+ * Return the first block (inclusive) in a group
+ */
+blk64_t ext2fs_group_first_block2(ext2_filsys fs, dgrp_t group)
+{
+ return fs->super->s_first_data_block +
+ (group * fs->super->s_blocks_per_group);
+}
+
+/*
+ * Return the last block (inclusive) in a group
+ */
+blk64_t ext2fs_group_last_block2(ext2_filsys fs, dgrp_t group)
+{
+ return (group == fs->group_desc_count - 1 ?
+ ext2fs_blocks_count(fs->super) - 1 :
+ ext2fs_group_first_block2(fs, group) +
+ (fs->super->s_blocks_per_group - 1));
+}
+
+/*
+ * Return the inode data block count
+ */
+blk64_t ext2fs_inode_data_blocks2(ext2_filsys fs,
+ struct ext2_inode *inode)
+{
+ return (inode->i_blocks |
+ (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT ?
+ (__u64)inode->osd2.linux2.l_i_blocks_hi << 32 : 0)) -
+ (inode->i_file_acl ? fs->blocksize >> 9 : 0);
+}
+
+/*
+ * Return the fs block count
+ */
+blk64_t ext2fs_blocks_count(struct ext2_super_block *super)
+{
+ return super->s_blocks_count |
+ (super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT ?
+ (__u64) super->s_blocks_count_hi << 32 : 0);
+}
+
+/*
+ * Set the fs block count
+ */
+void ext2fs_blocks_count_set(struct ext2_super_block *super, blk64_t blk)
+{
+ super->s_blocks_count = blk;
+ if (super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
+ super->s_blocks_count_hi = (__u64) blk >> 32;
+}
+
+/*
+ * Return the fs reserved block count
+ */
+blk64_t ext2fs_r_blocks_count(struct ext2_super_block *super)
+{
+ return super->s_r_blocks_count |
+ (super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT ?
+ (__u64) super->s_r_blocks_count_hi << 32 : 0);
+}
+
+/*
+ * Set the fs reserved block count
+ */
+void ext2fs_r_blocks_count_set(struct ext2_super_block *super, blk64_t blk)
+{
+ super->s_r_blocks_count = blk;
+ if (super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
+ super->s_r_blocks_count_hi = (__u64) blk >> 32;
+}
+
+/*
+ * Return the fs free block count
+ */
+blk64_t ext2fs_free_blocks_count(struct ext2_super_block *super)
+{
+ return super->s_free_blocks_count |
+ (super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT ?
+ (__u64) super->s_free_blocks_hi << 32 : 0);
+}
+
+/*
+ * Set the fs free block count
+ */
+void ext2fs_free_blocks_count_set(struct ext2_super_block *super, blk64_t blk)
+{
+ super->s_free_blocks_count = blk;
+ if (super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
+ super->s_free_blocks_hi = (__u64) blk >> 32;
+}
+
+/*
+ * Return the block bitmap block of a group
+ */
+blk64_t ext2fs_block_bitmap_loc(ext2_filsys fs, dgrp_t group)
+{
+ if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) {
+ struct ext4_group_desc *gdp;
+ gdp = (struct ext4_group_desc *) (fs->group_desc) + group;
+
+ return gdp->bg_block_bitmap |
+ (fs->super->s_feature_incompat
+ & EXT4_FEATURE_INCOMPAT_64BIT ?
+ (__u64) gdp->bg_block_bitmap_hi << 32 : 0);
+ }
+
+ return fs->group_desc[group].bg_block_bitmap;
+}
+
+/*
+ * Set the block bitmap block of a group
+ */
+void ext2fs_block_bitmap_loc_set(ext2_filsys fs, dgrp_t group, blk64_t blk)
+{
+ if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) {
+ struct ext4_group_desc *gdp;
+ gdp = (struct ext4_group_desc *) (fs->group_desc) + group;
+ gdp->bg_block_bitmap = blk;
+ if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
+ gdp->bg_block_bitmap_hi = (__u64) blk >> 32;
+ } else
+ fs->group_desc[group].bg_block_bitmap = blk;
+}
+
+/*
+ * Return the inode bitmap block of a group
+ */
+blk64_t ext2fs_inode_bitmap_loc(ext2_filsys fs, dgrp_t group)
+{
+ if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) {
+ struct ext4_group_desc *gdp;
+ gdp = (struct ext4_group_desc *) (fs->group_desc) + group;
+
+ return gdp->bg_inode_bitmap |
+ (fs->super->s_feature_incompat
+ & EXT4_FEATURE_INCOMPAT_64BIT ?
+ (__u64) gdp->bg_inode_bitmap_hi << 32 : 0);
+ }
+
+ return fs->group_desc[group].bg_inode_bitmap;
+}
+
+/*
+ * Set the inode bitmap block of a group
+ */
+void ext2fs_inode_bitmap_loc_set(ext2_filsys fs, dgrp_t group, blk64_t blk)
+{
+ if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) {
+ struct ext4_group_desc *gdp;
+ gdp = (struct ext4_group_desc *) (fs->group_desc) + group;
+ gdp->bg_inode_bitmap = blk;
+ if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
+ gdp->bg_inode_bitmap_hi = (__u64) blk >> 32;
+ } else
+ fs->group_desc[group].bg_inode_bitmap = blk;
+}
+
+/*
+ * Return the inode table block of a group
+ */
+blk64_t ext2fs_inode_table_loc(ext2_filsys fs, dgrp_t group)
+{
+ if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) {
+ struct ext4_group_desc *gdp;
+ gdp = (struct ext4_group_desc *) (fs->group_desc) + group;
+
+ return gdp->bg_inode_table |
+ (fs->super->s_feature_incompat
+ & EXT4_FEATURE_INCOMPAT_64BIT ?
+ (__u64) gdp->bg_inode_table_hi << 32 : 0);
+ }
+
+ return fs->group_desc[group].bg_inode_table;
+}
+
+/*
+ * Set the inode table block of a group
+ */
+void ext2fs_inode_table_loc_set(ext2_filsys fs, dgrp_t group, blk64_t blk)
+{
+ if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) {
+ struct ext4_group_desc *gdp;
+ gdp = (struct ext4_group_desc *) (fs->group_desc) + group;
+ gdp->bg_inode_table = blk;
+ if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
+ gdp->bg_inode_table_hi = (__u64) blk >> 32;
+ } else
+ fs->group_desc[group].bg_inode_table = blk;
+}
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index d9337aa..35cf0a3 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -682,6 +682,30 @@ extern errcode_t ext2fs_get_block_bitmap_range(ext2fs_block_bitmap bmap,
blk_t start, unsigned int num,
void *out);
+/* blknum.c */
+extern dgrp_t ext2fs_group_of_blk2(ext2_filsys fs, blk64_t);
+extern blk64_t ext2fs_group_first_block2(ext2_filsys fs, dgrp_t group);
+extern blk64_t ext2fs_group_last_block2(ext2_filsys fs, dgrp_t group);
+extern blk64_t ext2fs_inode_data_blocks2(ext2_filsys fs,
+ struct ext2_inode *inode);
+extern blk64_t ext2fs_blocks_count(struct ext2_super_block *super);
+extern void ext2fs_blocks_count_set(struct ext2_super_block *super,
+ blk64_t blk);
+extern blk64_t ext2fs_r_blocks_count(struct ext2_super_block *super);
+extern void ext2fs_r_blocks_count_set(struct ext2_super_block *super,
+ blk64_t blk);
+extern blk64_t ext2fs_free_blocks_count(struct ext2_super_block *super);
+extern void ext2fs_free_blocks_count_set(struct ext2_super_block *super,
+ blk64_t blk);
+extern blk64_t ext2fs_block_bitmap_loc(ext2_filsys fs, dgrp_t group);
+extern void ext2fs_block_bitmap_loc_set(ext2_filsys fs, dgrp_t group,
+ blk64_t blk);
+extern blk64_t ext2fs_inode_bitmap_loc(ext2_filsys fs, dgrp_t group);
+extern void ext2fs_inode_bitmap_loc_set(ext2_filsys fs, dgrp_t group,
+ blk64_t blk);
+extern blk64_t ext2fs_inode_table_loc(ext2_filsys fs, dgrp_t group);
+extern void ext2fs_inode_table_loc_set(ext2_filsys fs, dgrp_t group,
+ blk64_t blk);
/* block.c */
extern errcode_t ext2fs_block_iterate(ext2_filsys fs,
@@ -1316,10 +1340,8 @@ _INLINE_ int ext2fs_test_bb_dirty(ext2_filsys fs)
*/
_INLINE_ int ext2fs_group_of_blk(ext2_filsys fs, blk_t blk)
{
- return (blk - fs->super->s_first_data_block) /
- fs->super->s_blocks_per_group;
+ return ext2fs_group_of_blk2(fs, blk);
}
-
/*
* Return the group # of an inode number
*/
@@ -1333,8 +1355,7 @@ _INLINE_ int ext2fs_group_of_ino(ext2_filsys fs, ext2_ino_t ino)
*/
_INLINE_ blk_t ext2fs_group_first_block(ext2_filsys fs, dgrp_t group)
{
- return fs->super->s_first_data_block +
- (group * fs->super->s_blocks_per_group);
+ return ext2fs_group_first_block2(fs, group);
}
/*
@@ -1342,17 +1363,13 @@ _INLINE_ blk_t ext2fs_group_first_block(ext2_filsys fs, dgrp_t group)
*/
_INLINE_ blk_t ext2fs_group_last_block(ext2_filsys fs, dgrp_t group)
{
- return (group == fs->group_desc_count - 1 ?
- fs->super->s_blocks_count - 1 :
- ext2fs_group_first_block(fs, group) +
- (fs->super->s_blocks_per_group - 1));
+ return ext2fs_group_last_block2(fs, group);
}
_INLINE_ blk_t ext2fs_inode_data_blocks(ext2_filsys fs,
struct ext2_inode *inode)
{
- return inode->i_blocks -
- (inode->i_file_acl ? fs->blocksize >> 9 : 0);
+ return ext2fs_inode_data_blocks2(fs, inode);
}
/*
From: Jose R. Santos <[email protected]>
Add 64-bit getsize interface.
Added interface capable of opening 64-bit block device.
Signed-off-by: Jose R. Santos <[email protected]>
--
lib/ext2fs/ext2fs.h | 2 ++
lib/ext2fs/getsize.c | 15 +++++++++++++--
2 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index 3bc866e..6881c8a 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -979,6 +979,8 @@ extern errcode_t ext2fs_set_generic_bitmap_range(ext2fs_generic_bitmap bmap,
/* getsize.c */
extern errcode_t ext2fs_get_device_size(const char *file, int blocksize,
blk_t *retblocks);
+extern errcode_t ext2fs_get_device_size2(const char *file, int blocksize,
+ blk64_t *retblocks);
/* getsectsize.c */
errcode_t ext2fs_get_device_sectsize(const char *file, int *sectsize);
diff --git a/lib/ext2fs/getsize.c b/lib/ext2fs/getsize.c
index 7f6ef71..48b9eaf 100644
--- a/lib/ext2fs/getsize.c
+++ b/lib/ext2fs/getsize.c
@@ -138,8 +138,8 @@ static int valid_offset (int fd, ext2_loff_t offset)
/*
* Returns the number of blocks in a partition
*/
-errcode_t ext2fs_get_device_size(const char *file, int blocksize,
- blk_t *retblocks)
+errcode_t ext2fs_get_device_size2(const char *file, int blocksize,
+ blk64_t *retblocks)
{
int fd, rc = 0;
int valid_blkgetsize64 = 1;
@@ -293,6 +293,17 @@ out:
return rc;
}
+errcode_t ext2fs_get_device_size(const char *file, int blocksize,
+ blk_t *retblocks)
+{
+ errcode_t retval;
+ blk64_t blocks;
+ retval = ext2fs_get_device_size2(file, blocksize, &blocks);
+ if (!retval)
+ *retblocks = (blk_t) blocks;
+ return retval;
+}
+
#endif /* WIN32 */
#ifdef DEBUG
From: Jose R. Santos <[email protected]>
Add 64-bit mkjournal.c interface
Added 64-bit mkjournal.c interface. Needed to zero inode tables.
Signed-off-by: Jose R. Santos <[email protected]>
--
lib/ext2fs/ext2fs.h | 2 ++
lib/ext2fs/mkjournal.c | 18 +++++++++++++++---
2 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index 6881c8a..859f9b6 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -1104,6 +1104,8 @@ extern errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum
/* mkjournal.c */
extern errcode_t ext2fs_zero_blocks(ext2_filsys fs, blk_t blk, int num,
blk_t *ret_blk, int *ret_count);
+extern errcode_t ext2fs_zero_blocks2(ext2_filsys fs, blk64_t blk, int num,
+ blk64_t *ret_blk, int *ret_count);
extern errcode_t ext2fs_create_journal_superblock(ext2_filsys fs,
__u32 size, int flags,
char **ret_jsb);
diff --git a/lib/ext2fs/mkjournal.c b/lib/ext2fs/mkjournal.c
index e55dcbd..8c3b93f 100644
--- a/lib/ext2fs/mkjournal.c
+++ b/lib/ext2fs/mkjournal.c
@@ -145,8 +145,8 @@ errout:
* programs that check for memory leaks happy.)
*/
#define STRIDE_LENGTH 8
-errcode_t ext2fs_zero_blocks(ext2_filsys fs, blk_t blk, int num,
- blk_t *ret_blk, int *ret_count)
+errcode_t ext2fs_zero_blocks2(ext2_filsys fs, blk64_t blk, int num,
+ blk64_t *ret_blk, int *ret_count)
{
int j, count;
static char *buf;
@@ -179,7 +179,7 @@ errcode_t ext2fs_zero_blocks(ext2_filsys fs, blk_t blk, int num,
if (count > STRIDE_LENGTH)
count = STRIDE_LENGTH;
}
- retval = io_channel_write_blk(fs->io, blk, count, buf);
+ retval = io_channel_write_blk64(fs->io, blk, count, buf);
if (retval) {
if (ret_count)
*ret_count = count;
@@ -192,6 +192,18 @@ errcode_t ext2fs_zero_blocks(ext2_filsys fs, blk_t blk, int num,
return 0;
}
+errcode_t ext2fs_zero_blocks(ext2_filsys fs, blk_t blk, int num,
+ blk_t *ret_blk, int *ret_count)
+{
+ blk64_t ret_blk2;
+ errcode_t retval;
+
+ retval = ext2fs_zero_blocks2(fs, blk, num, &ret_blk2, ret_count);
+ if (retval)
+ *ret_blk = (blk_t) ret_blk2;
+ return retval;
+}
+
/*
* Helper function for creating the journal using direct I/O routines
*/
From: Jose R. Santos <[email protected]>
Add 64-bit dirblock interface.
Add new ext2fs_(read|write)_dir_block3() routines that take blk64_t as
an input.
Signed-off-by: Jose R. Santos <[email protected]>
--
lib/ext2fs/dirblock.c | 23 +++++++++++++++++------
lib/ext2fs/ext2fs.h | 4 ++++
2 files changed, 21 insertions(+), 6 deletions(-)
Signed-off-by: Theodore Ts'o <[email protected]>
--
lib/ext2fs/dirblock.c | 23 +++++++++++++++++------
lib/ext2fs/ext2fs.h | 4 ++++
2 files changed, 21 insertions(+), 6 deletions(-)
diff --git a/lib/ext2fs/dirblock.c b/lib/ext2fs/dirblock.c
index fb20fa0..c45c6ce 100644
--- a/lib/ext2fs/dirblock.c
+++ b/lib/ext2fs/dirblock.c
@@ -19,7 +19,7 @@
#include "ext2_fs.h"
#include "ext2fs.h"
-errcode_t ext2fs_read_dir_block2(ext2_filsys fs, blk_t block,
+errcode_t ext2fs_read_dir_block3(ext2_filsys fs, blk64_t block,
void *buf, int flags EXT2FS_ATTR((unused)))
{
errcode_t retval;
@@ -28,7 +28,7 @@ errcode_t ext2fs_read_dir_block2(ext2_filsys fs, blk_t block,
unsigned int name_len, rec_len;
- retval = io_channel_read_blk(fs->io, block, 1, buf);
+ retval = io_channel_read_blk64(fs->io, block, 1, buf);
if (retval)
return retval;
@@ -58,14 +58,20 @@ errcode_t ext2fs_read_dir_block2(ext2_filsys fs, blk_t block,
return retval;
}
+errcode_t ext2fs_read_dir_block2(ext2_filsys fs, blk_t block,
+ void *buf, int flags EXT2FS_ATTR((unused)))
+{
+ return ext2fs_read_dir_block3(fs, block, buf, flags);
+}
+
errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block,
void *buf)
{
- return ext2fs_read_dir_block2(fs, block, buf, 0);
+ return ext2fs_read_dir_block3(fs, block, buf, 0);
}
-errcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block,
+errcode_t ext2fs_write_dir_block3(ext2_filsys fs, blk64_t block,
void *inbuf, int flags EXT2FS_ATTR((unused)))
{
#ifdef WORDS_BIGENDIAN
@@ -95,7 +101,7 @@ errcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block,
if (flags & EXT2_DIRBLOCK_V2_STRUCT)
dirent->name_len = ext2fs_swab16(dirent->name_len);
}
- retval = io_channel_write_blk(fs->io, block, 1, buf);
+ retval = io_channel_write_blk64(fs->io, block, 1, buf);
ext2fs_free_mem(&buf);
return retval;
#else
@@ -103,10 +109,15 @@ errcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block,
#endif
}
+errcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block,
+ void *inbuf, int flags EXT2FS_ATTR((unused)))
+{
+ return ext2fs_write_dir_block3(fs, block, inbuf, flags);
+}
errcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block,
void *inbuf)
{
- return ext2fs_write_dir_block2(fs, block, inbuf, 0);
+ return ext2fs_write_dir_block3(fs, block, inbuf, 0);
}
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index 35cf0a3..a643aa1 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -808,10 +808,14 @@ extern errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block,
void *buf);
extern errcode_t ext2fs_read_dir_block2(ext2_filsys fs, blk_t block,
void *buf, int flags);
+extern errcode_t ext2fs_read_dir_block3(ext2_filsys fs, blk64_t block,
+ void *buf, int flags);
extern errcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block,
void *buf);
extern errcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block,
void *buf, int flags);
+extern errcode_t ext2fs_write_dir_block3(ext2_filsys fs, blk64_t block,
+ void *buf, int flags);
/* dirhash.c */
extern errcode_t ext2fs_dirhash(int version, const char *name, int len,
From: Jose R. Santos <[email protected]>
64-bit mke2fs cleanup
Use 64-bit interfaces in mke2fs. This should be most most of whats
needed to support creating a 64-bit filesystem. Things missing:
- 64-bit bitmap support being developed by Ted. We cant make a 64bit
fs without this.
- 64-bit badblock interface. Waiting on Ted 64-bit bitmap patches to
shamelessly steel some of his code. (particularly, the handling of
different interface through the structure magic numbers)
This is not needed to create a 64-bit filesystem, but you cant have
bad blocks above the 32bit block number boundary.
- lost+found and journal file are not created as extent mapped files.
Should not prevent from creating a 64-bit filesystem and since those
are typically at the beginning of the disk, don't know if I should
really care. Don't know much about the extent format to know for sure.
Signed-off-by: Jose R. Santos <[email protected]>
--
lib/ext2fs/alloc_tables.c | 77 +++++++++++++++++++++++++--------------------
lib/ext2fs/initialize.c | 36 ++++++++++++---------
misc/mke2fs.c | 48 +++++++++++++++-------------
3 files changed, 89 insertions(+), 72 deletions(-)
diff --git a/lib/ext2fs/alloc_tables.c b/lib/ext2fs/alloc_tables.c
index 8c0ecfc..3f7b454 100644
--- a/lib/ext2fs/alloc_tables.c
+++ b/lib/ext2fs/alloc_tables.c
@@ -33,11 +33,11 @@
* block number with a correct offset were the bitmaps and inode
* tables can be allocated continously and in order.
*/
-static blk_t flexbg_offset(ext2_filsys fs, dgrp_t group, blk_t start_blk,
+static blk64_t flexbg_offset(ext2_filsys fs, dgrp_t group, blk_t start_blk,
ext2fs_block_bitmap bmap, int offset, int size)
{
int flexbg, flexbg_size, elem_size;
- blk_t last_blk, first_free = 0;
+ blk64_t last_blk, first_free = 0;
dgrp_t last_grp;
flexbg_size = 1 << fs->super->s_log_groups_per_flex;
@@ -70,11 +70,11 @@ static blk_t flexbg_offset(ext2_filsys fs, dgrp_t group, blk_t start_blk,
last_blk = ext2fs_group_last_block(fs, last_grp);
/* Find the first available block */
- if (ext2fs_get_free_blocks(fs, start_blk, last_blk, 1, bmap,
+ if (ext2fs_get_free_blocks2(fs, start_blk, last_blk, 1, bmap,
&first_free))
return first_free;
- if (ext2fs_get_free_blocks(fs, first_free + offset, last_blk, size,
+ if (ext2fs_get_free_blocks2(fs, first_free + offset, last_blk, size,
bmap, &first_free))
return first_free;
@@ -85,12 +85,12 @@ errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group,
ext2fs_block_bitmap bmap)
{
errcode_t retval;
- blk_t group_blk, start_blk, last_blk, new_blk, blk;
+ blk64_t group_blk, start_blk, last_blk, new_blk, blk;
dgrp_t last_grp = 0;
int j, rem_grps = 0, flexbg_size = 0;
- group_blk = ext2fs_group_first_block(fs, group);
- last_blk = ext2fs_group_last_block(fs, group);
+ group_blk = ext2fs_group_first_block2(fs, group);
+ last_blk = ext2fs_group_last_block2(fs, group);
if (!bmap)
bmap = fs->block_map;
@@ -109,8 +109,8 @@ errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group,
* Allocate the block and inode bitmaps, if necessary
*/
if (fs->stride) {
- retval = ext2fs_get_free_blocks(fs, group_blk, last_blk,
- 1, bmap, &start_blk);
+ retval = ext2fs_get_free_blocks2(fs, group_blk, last_blk,
+ 1, bmap, &start_blk);
if (retval)
return retval;
start_blk += fs->inode_blocks_per_group;
@@ -123,27 +123,30 @@ errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group,
if (flexbg_size) {
int prev_block = 0;
- if (group && fs->group_desc[group-1].bg_block_bitmap)
- prev_block = fs->group_desc[group-1].bg_block_bitmap;
+ if (group && ext2fs_block_bitmap_loc(fs, group - 1))
+ prev_block = ext2fs_block_bitmap_loc(fs, group - 1);
start_blk = flexbg_offset(fs, group, prev_block, bmap,
0, rem_grps);
- last_blk = ext2fs_group_last_block(fs, last_grp);
+ last_blk = ext2fs_group_last_block2(fs, last_grp);
}
if (!fs->group_desc[group].bg_block_bitmap) {
- retval = ext2fs_get_free_blocks(fs, start_blk, last_blk,
- 1, bmap, &new_blk);
+ retval = ext2fs_get_free_blocks2(fs, start_blk, last_blk,
+ 1, bmap, &new_blk);
if (retval == EXT2_ET_BLOCK_ALLOC_FAIL)
- retval = ext2fs_get_free_blocks(fs, group_blk,
+ retval = ext2fs_get_free_blocks2(fs, group_blk,
last_blk, 1, bmap, &new_blk);
if (retval)
return retval;
+ /* FIXME-64 */
ext2fs_mark_block_bitmap(bmap, new_blk);
- fs->group_desc[group].bg_block_bitmap = new_blk;
+ ext2fs_block_bitmap_loc_set(fs, group, new_blk);
if (flexbg_size) {
- dgrp_t gr = ext2fs_group_of_blk(fs, new_blk);
+ dgrp_t gr = ext2fs_group_of_blk2(fs, new_blk);
fs->group_desc[gr].bg_free_blocks_count--;
- fs->super->s_free_blocks_count--;
+ ext2fs_free_blocks_count_set(fs->super,
+ ext2fs_free_blocks_count(
+ fs->super) - 1);
fs->group_desc[gr].bg_flags &= ~EXT2_BG_BLOCK_UNINIT;
ext2fs_group_desc_csum_set(fs, gr);
}
@@ -151,27 +154,30 @@ errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group,
if (flexbg_size) {
int prev_block = 0;
- if (group && fs->group_desc[group-1].bg_inode_bitmap)
- prev_block = fs->group_desc[group-1].bg_inode_bitmap;
+ if (group && ext2fs_inode_bitmap_loc(fs, group - 1))
+ prev_block = ext2fs_inode_bitmap_loc(fs, group - 1);
start_blk = flexbg_offset(fs, group, prev_block, bmap,
flexbg_size, rem_grps);
- last_blk = ext2fs_group_last_block(fs, last_grp);
+ last_blk = ext2fs_group_last_block2(fs, last_grp);
}
if (!fs->group_desc[group].bg_inode_bitmap) {
- retval = ext2fs_get_free_blocks(fs, start_blk, last_blk,
- 1, bmap, &new_blk);
+ retval = ext2fs_get_free_blocks2(fs, start_blk, last_blk,
+ 1, bmap, &new_blk);
if (retval == EXT2_ET_BLOCK_ALLOC_FAIL)
- retval = ext2fs_get_free_blocks(fs, group_blk,
+ retval = ext2fs_get_free_blocks2(fs, group_blk,
last_blk, 1, bmap, &new_blk);
if (retval)
return retval;
+ /* FIXME-64 */
ext2fs_mark_block_bitmap(bmap, new_blk);
- fs->group_desc[group].bg_inode_bitmap = new_blk;
+ ext2fs_inode_bitmap_loc_set(fs, group, new_blk);
if (flexbg_size) {
- dgrp_t gr = ext2fs_group_of_blk(fs, new_blk);
+ dgrp_t gr = ext2fs_group_of_blk2(fs, new_blk);
fs->group_desc[gr].bg_free_blocks_count--;
- fs->super->s_free_blocks_count--;
+ ext2fs_free_blocks_count_set(fs->super,
+ ext2fs_free_blocks_count(
+ fs->super) - 1);
fs->group_desc[gr].bg_flags &= ~EXT2_BG_BLOCK_UNINIT;
ext2fs_group_desc_csum_set(fs, gr);
}
@@ -182,17 +188,17 @@ errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group,
*/
if (flexbg_size) {
int prev_block = 0;
- if (group && fs->group_desc[group-1].bg_inode_table)
- prev_block = fs->group_desc[group-1].bg_inode_table;
+ if (group && ext2fs_inode_table_loc(fs, group - 1))
+ prev_block = ext2fs_inode_table_loc(fs, group - 1);
group_blk = flexbg_offset(fs, group, prev_block, bmap,
flexbg_size * 2,
fs->inode_blocks_per_group *
rem_grps);
- last_blk = ext2fs_group_last_block(fs, last_grp);
+ last_blk = ext2fs_group_last_block2(fs, last_grp);
}
if (!fs->group_desc[group].bg_inode_table) {
- retval = ext2fs_get_free_blocks(fs, group_blk, last_blk,
+ retval = ext2fs_get_free_blocks2(fs, group_blk, last_blk,
fs->inode_blocks_per_group,
bmap, &new_blk);
if (retval)
@@ -200,16 +206,19 @@ errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group,
for (j=0, blk = new_blk;
j < fs->inode_blocks_per_group;
j++, blk++) {
+ /* FIXME-64 */
ext2fs_mark_block_bitmap(bmap, blk);
if (flexbg_size) {
- dgrp_t gr = ext2fs_group_of_blk(fs, blk);
+ dgrp_t gr = ext2fs_group_of_blk2(fs, blk);
fs->group_desc[gr].bg_free_blocks_count--;
- fs->super->s_free_blocks_count--;
+ ext2fs_free_blocks_count_set(fs->super,
+ ext2fs_free_blocks_count(
+ fs->super) - 1);
fs->group_desc[gr].bg_flags &= ~EXT2_BG_BLOCK_UNINIT;
ext2fs_group_desc_csum_set(fs, gr);
}
}
- fs->group_desc[group].bg_inode_table = new_blk;
+ ext2fs_inode_table_loc_set(fs, group, new_blk);
}
ext2fs_group_desc_csum_set(fs, group);
return 0;
diff --git a/lib/ext2fs/initialize.c b/lib/ext2fs/initialize.c
index e9bfe49..5060fda 100644
--- a/lib/ext2fs/initialize.c
+++ b/lib/ext2fs/initialize.c
@@ -75,8 +75,8 @@ static unsigned int calc_reserved_gdt_blocks(ext2_filsys fs)
/* We set it at 1024x the current filesystem size, or
* the upper block count limit (2^32), whichever is lower.
*/
- if (sb->s_blocks_count < max_blocks / 1024)
- max_blocks = sb->s_blocks_count * 1024;
+ if (ext2fs_blocks_count(sb) < max_blocks / 1024)
+ max_blocks = ext2fs_blocks_count(sb) * 1024;
rsv_groups = ext2fs_div_ceil(max_blocks - sb->s_first_data_block, bpg);
rsv_gdb = ext2fs_div_ceil(rsv_groups, gdpb) - fs->desc_blocks;
if (rsv_gdb > EXT2_ADDR_PER_BLOCK(sb))
@@ -108,7 +108,7 @@ errcode_t ext2fs_initialize(const char *name, int flags,
char *buf = 0;
char c;
- if (!param || !param->s_blocks_count)
+ if (!param || !ext2fs_blocks_count(param))
return EXT2_ET_INVALID_ARGUMENT;
retval = ext2fs_get_mem(sizeof(struct struct_ext2_filsys), &fs);
@@ -200,9 +200,9 @@ errcode_t ext2fs_initialize(const char *name, int flags,
super->s_blocks_per_group = EXT2_MAX_BLOCKS_PER_GROUP(super);
super->s_frags_per_group = super->s_blocks_per_group * frags_per_block;
- super->s_blocks_count = param->s_blocks_count;
- super->s_r_blocks_count = param->s_r_blocks_count;
- if (super->s_r_blocks_count >= param->s_blocks_count) {
+ ext2fs_blocks_count_set(super, param->s_blocks_count);
+ ext2fs_r_blocks_count_set(super, param->s_r_blocks_count);
+ if (ext2fs_r_blocks_count(super) >= ext2fs_blocks_count(param)) {
retval = EXT2_ET_INVALID_ARGUMENT;
goto cleanup;
}
@@ -219,9 +219,9 @@ errcode_t ext2fs_initialize(const char *name, int flags,
}
retry:
- fs->group_desc_count = ext2fs_div_ceil(super->s_blocks_count -
- super->s_first_data_block,
- EXT2_BLOCKS_PER_GROUP(super));
+ fs->group_desc_count = (blk_t) ext2fs_div64_ceil(
+ ext2fs_blocks_count(super) - super->s_first_data_block,
+ EXT2_BLOCKS_PER_GROUP(super));
if (fs->group_desc_count == 0) {
retval = EXT2_ET_TOOSMALL;
goto cleanup;
@@ -230,7 +230,8 @@ retry:
EXT2_DESC_PER_BLOCK(super));
i = fs->blocksize >= 4096 ? 1 : 4096 / fs->blocksize;
- set_field(s_inodes_count, super->s_blocks_count / i);
+ /* FIXME-64 */
+ set_field(s_inodes_count, ext2fs_blocks_count(super) / i);
/*
* Make sure we have at least EXT2_FIRST_INO + 1 inodes, so
@@ -250,7 +251,8 @@ retry:
if (super->s_blocks_per_group >= 256) {
/* Try again with slightly different parameters */
super->s_blocks_per_group -= 8;
- super->s_blocks_count = param->s_blocks_count;
+ ext2fs_blocks_count_set(super,
+ ext2fs_blocks_count(param));
super->s_frags_per_group = super->s_blocks_per_group *
frags_per_block;
goto retry;
@@ -334,12 +336,14 @@ ipg_retry:
overhead = (int) (2 + fs->inode_blocks_per_group);
if (ext2fs_bg_has_super(fs, fs->group_desc_count - 1))
overhead += 1 + fs->desc_blocks + super->s_reserved_gdt_blocks;
- rem = ((super->s_blocks_count - super->s_first_data_block) %
+ rem = ((ext2fs_blocks_count(super) - super->s_first_data_block) %
super->s_blocks_per_group);
if ((fs->group_desc_count == 1) && rem && (rem < overhead))
return EXT2_ET_TOOSMALL;
if (rem && (rem < overhead+50)) {
- super->s_blocks_count -= rem;
+ ext2fs_blocks_count_set(super, ext2fs_blocks_count(super) +
+ rem);
+
goto retry;
}
@@ -383,7 +387,7 @@ ipg_retry:
* superblock and group descriptors (the inode tables and
* bitmaps will be accounted for when allocated).
*/
- super->s_free_blocks_count = 0;
+ ext2fs_free_blocks_count_set(super, 0);
csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
for (i = 0; i < fs->group_desc_count; i++) {
@@ -405,7 +409,9 @@ ipg_retry:
if (fs->super->s_log_groups_per_flex)
numblocks += 2 + fs->inode_blocks_per_group;
- super->s_free_blocks_count += numblocks;
+ ext2fs_free_blocks_count_set(super,
+ ext2fs_free_blocks_count(super) +
+ numblocks);
fs->group_desc[i].bg_free_blocks_count = numblocks;
fs->group_desc[i].bg_free_inodes_count =
fs->super->s_inodes_per_group;
diff --git a/misc/mke2fs.c b/misc/mke2fs.c
index 7171990..817be56 100644
--- a/misc/mke2fs.c
+++ b/misc/mke2fs.c
@@ -348,7 +348,7 @@ static void progress_close(struct progress_struct *progress)
static void write_inode_tables(ext2_filsys fs, int lazy_flag)
{
errcode_t retval;
- blk_t blk;
+ blk64_t blk;
dgrp_t i;
int num, ipb;
struct progress_struct progress;
@@ -362,7 +362,7 @@ static void write_inode_tables(ext2_filsys fs, int lazy_flag)
for (i = 0; i < fs->group_desc_count; i++) {
progress_update(&progress, i);
- blk = fs->group_desc[i].bg_inode_table;
+ blk = ext2fs_inode_table_loc(fs, i);
num = fs->inode_blocks_per_group;
if (lazy_flag) {
@@ -377,10 +377,10 @@ static void write_inode_tables(ext2_filsys fs, int lazy_flag)
fs->group_desc[i].bg_flags |= EXT2_BG_INODE_ZEROED;
ext2fs_group_desc_csum_set(fs, i);
}
- retval = ext2fs_zero_blocks(fs, blk, num, &blk, &num);
+ retval = ext2fs_zero_blocks2(fs, blk, num, &blk, &num);
if (retval) {
fprintf(stderr, _("\nCould not write %d "
- "blocks in inode table starting at %u: %s\n"),
+ "blocks in inode table starting at %ull: %s\n"),
num, blk, error_message(retval));
exit(1);
}
@@ -511,7 +511,7 @@ static void zap_sector(ext2_filsys fs, int sect, int nsect)
if (sect == 0) {
/* Check for a BSD disklabel, and don't erase it if so */
- retval = io_channel_read_blk(fs->io, 0, -512, buf);
+ retval = io_channel_read_blk64(fs->io, 0, -512, buf);
if (retval)
fprintf(stderr,
_("Warning: could not read block 0: %s\n"),
@@ -1074,7 +1074,7 @@ static void PRS(int argc, char *argv[])
char * extended_opts = 0;
const char * fs_type = 0;
const char * usage_types = 0;
- blk_t dev_size;
+ blk64_t dev_size;
#ifdef __linux__
struct utsname ut;
#endif
@@ -1402,12 +1402,12 @@ static void PRS(int argc, char *argv[])
fs_param.s_log_frag_size = fs_param.s_log_block_size;
- if (noaction && fs_param.s_blocks_count) {
- dev_size = fs_param.s_blocks_count;
+ if (noaction && ext2fs_blocks_count(&fs_param)) {
+ dev_size = ext2fs_blocks_count(&fs_param);
retval = 0;
} else {
retry:
- retval = ext2fs_get_device_size(device_name,
+ retval = ext2fs_get_device_size2(device_name,
EXT2_BLOCK_SIZE(&fs_param),
&dev_size);
if ((retval == EFBIG) &&
@@ -1431,7 +1431,7 @@ static void PRS(int argc, char *argv[])
_("while trying to determine filesystem size"));
exit(1);
}
- if (!fs_param.s_blocks_count) {
+ if (!ext2fs_blocks_count(&fs_param)) {
if (retval == EXT2_ET_UNIMPLEMENTED) {
com_err(program_name, 0,
_("Couldn't determine device size; you "
@@ -1451,13 +1451,16 @@ static void PRS(int argc, char *argv[])
));
exit(1);
}
- fs_param.s_blocks_count = dev_size;
- if (sys_page_size > EXT2_BLOCK_SIZE(&fs_param))
- fs_param.s_blocks_count &= ~((sys_page_size /
- EXT2_BLOCK_SIZE(&fs_param))-1);
+ ext2fs_blocks_count_set(&fs_param, dev_size);
+ if (sys_page_size > EXT2_BLOCK_SIZE(&fs_param)) {
+ blk64_t tmp = ext2fs_blocks_count(&fs_param);
+ tmp &= ~((sys_page_size /
+ EXT2_BLOCK_SIZE(&fs_param))-1);
+ ext2fs_blocks_count_set(&fs_param, tmp);
+ }
}
- } else if (!force && (fs_param.s_blocks_count > dev_size)) {
+ } else if (!force && (ext2fs_blocks_count(&fs_param) > dev_size)) {
com_err(program_name, 0,
_("Filesystem larger than apparent device size."));
proceed_question();
@@ -1667,7 +1670,7 @@ static void PRS(int argc, char *argv[])
/* Make sure number of inodes specified will fit in 32 bits */
if (num_inodes == 0) {
unsigned long long n;
- n = (unsigned long long) fs_param.s_blocks_count * blocksize / inode_ratio;
+ n = ext2fs_blocks_count(&fs_param) * blocksize / inode_ratio;
if (n > ~0U) {
com_err(program_name, 0,
_("too many inodes (%llu), raise inode ratio?"), n);
@@ -1683,29 +1686,28 @@ static void PRS(int argc, char *argv[])
* Calculate number of inodes based on the inode ratio
*/
fs_param.s_inodes_count = num_inodes ? num_inodes :
- ((__u64) fs_param.s_blocks_count * blocksize)
- / inode_ratio;
+ (ext2fs_blocks_count(&fs_param) * blocksize) / inode_ratio;
if ((((long long)fs_param.s_inodes_count) *
(inode_size ? inode_size : EXT2_GOOD_OLD_INODE_SIZE)) >=
- (((long long)fs_param.s_blocks_count) *
+ ((ext2fs_blocks_count(&fs_param)) *
EXT2_BLOCK_SIZE(&fs_param))) {
com_err(program_name, 0, _("inode_size (%u) * inodes_count "
"(%u) too big for a\n\t"
- "filesystem with %lu blocks, "
+ "filesystem with %llu blocks, "
"specify higher inode_ratio (-i)\n\t"
"or lower inode count (-N).\n"),
inode_size ? inode_size : EXT2_GOOD_OLD_INODE_SIZE,
fs_param.s_inodes_count,
- (unsigned long) fs_param.s_blocks_count);
+ (unsigned long long) ext2fs_blocks_count(&fs_param));
exit(1);
}
/*
* Calculate number of blocks to reserve
*/
- fs_param.s_r_blocks_count = (unsigned int) (reserved_ratio *
- fs_param.s_blocks_count / 100.0);
+ ext2fs_r_blocks_count_set(&fs_param, reserved_ratio *
+ ext2fs_blocks_count(&fs_param) / 100.0);
}
static int should_do_undo(const char *name)
"Jose R. Santos" <[email protected]> writes:
> From: Jose R. Santos <[email protected]>
>
> libext2fs: Add 64-bit support to the undo manager
>
> Signed-off-by: "Theodore Ts'o" <[email protected]>
> --
>
> lib/ext2fs/undo_io.c | 55 +++++++++++++++++++++++++++++++++++++++++---------
> 1 files changed, 45 insertions(+), 10 deletions(-)
>
> diff --git a/lib/ext2fs/undo_io.c b/lib/ext2fs/undo_io.c
> index 827c038..7661b83 100644
> --- a/lib/ext2fs/undo_io.c
> +++ b/lib/ext2fs/undo_io.c
> @@ -73,6 +73,10 @@ struct undo_private_data {
> static errcode_t undo_open(const char *name, int flags, io_channel *channel);
> static errcode_t undo_close(io_channel channel);
> static errcode_t undo_set_blksize(io_channel channel, int blksize);
> +static errcode_t undo_read_blk64(io_channel channel, unsigned long long block,
> + int count, void *data);
Why not this?
+static errcode_t undo_read_blk64(io_channel channel, blk64_t block,
+ int count, void *data);
libext2fs specifically has blk_t and blk64_t types to represent a
block. Why not use them? It is less to type and easier to read.
MfG
Goswin
"Jose R. Santos" <[email protected]> writes:
> diff --git a/misc/mke2fs.c b/misc/mke2fs.c
> index 7171990..817be56 100644
> --- a/misc/mke2fs.c
> +++ b/misc/mke2fs.c
> @@ -1402,12 +1402,12 @@ static void PRS(int argc, char *argv[])
>
> fs_param.s_log_frag_size = fs_param.s_log_block_size;
>
> - if (noaction && fs_param.s_blocks_count) {
> - dev_size = fs_param.s_blocks_count;
> + if (noaction && ext2fs_blocks_count(&fs_param)) {
> + dev_size = ext2fs_blocks_count(&fs_param);
> retval = 0;
> } else {
> retry:
> - retval = ext2fs_get_device_size(device_name,
> + retval = ext2fs_get_device_size2(device_name,
> EXT2_BLOCK_SIZE(&fs_param),
> &dev_size);
> if ((retval == EFBIG) &&
You should not assume that ext2fs_get_device_size2() will return EFBIG
if the size exceed 2^32 blocks. The point of ext2fs_get_device_size2()
was to be able to support more than 2^32 blocks and the library
function will certainly change to return larger numbers in the future.
So you need something like
if ((retval == EFBIG || dev_size >= (1ULL << 32)) &&
MfG
Goswin
On Wed, Jul 16, 2008 at 01:16:58PM +0200, Goswin von Brederlow wrote:
> Why not this?
>
> +static errcode_t undo_read_blk64(io_channel channel, blk64_t block,
> + int count, void *data);
>
> libext2fs specifically has blk_t and blk64_t types to represent a
> block. Why not use them? It is less to type and easier to read.
It's an abstraction layer thing. blk64_t is defined in ext2fs.h, and
the io_managers don't include it. The I/O managers are a small amount
of code, and it hasn't been worth it to explicitly define a type just
for them in the header file.
- Ted
Goswin von Brederlow <[email protected]> writes:
> "Jose R. Santos" <[email protected]> writes:
>
>> diff --git a/misc/mke2fs.c b/misc/mke2fs.c
>> index 7171990..817be56 100644
>> --- a/misc/mke2fs.c
>> +++ b/misc/mke2fs.c
>> @@ -1402,12 +1402,12 @@ static void PRS(int argc, char *argv[])
>>
>> fs_param.s_log_frag_size = fs_param.s_log_block_size;
>>
>> - if (noaction && fs_param.s_blocks_count) {
>> - dev_size = fs_param.s_blocks_count;
>> + if (noaction && ext2fs_blocks_count(&fs_param)) {
>> + dev_size = ext2fs_blocks_count(&fs_param);
>> retval = 0;
>> } else {
>> retry:
>> - retval = ext2fs_get_device_size(device_name,
>> + retval = ext2fs_get_device_size2(device_name,
>> EXT2_BLOCK_SIZE(&fs_param),
>> &dev_size);
>> if ((retval == EFBIG) &&
>
> You should not assume that ext2fs_get_device_size2() will return EFBIG
> if the size exceed 2^32 blocks. The point of ext2fs_get_device_size2()
> was to be able to support more than 2^32 blocks and the library
> function will certainly change to return larger numbers in the future.
>
> So you need something like
>
> if ((retval == EFBIG || dev_size >= (1ULL << 32)) &&
>
> MfG
> Goswin
Actualy that is already a problem. The ext2fs_get_device_size2() only
returns EFBIG if sizeof(dev_size) < sizeof(unsigned long long), which
was the case for blk_t but no longer.
As a result mke2fs no longer stops with the right error on devices >
16TiB. My test device is exactly 32 TiB large and gives the following:
root@beo-13:~# LD_LIBRARY_PATH=/tmpa/ext4 /tmpa/ext4/mke2fs -T ext4dev
-j -m0 /dev/mapper/ext4
mke2fs 1.41.0 (10-Jul-2008)
mke2fs: inode_size (256) * inodes_count (0) too big for a
filesystem with 0 blocks, specify higher inode_ratio (-i)
or lower inode count (-N).
I'm guessing somewhere along the line it converts to 32bit choping of
the higher bits.
MfG
Goswin
On Wed, 16 Jul 2008 14:50:14 +0200
Goswin von Brederlow <[email protected]> wrote:
> "Jose R. Santos" <[email protected]> writes:
>
> > diff --git a/misc/mke2fs.c b/misc/mke2fs.c
> > index 7171990..817be56 100644
> > --- a/misc/mke2fs.c
> > +++ b/misc/mke2fs.c
> > @@ -1402,12 +1402,12 @@ static void PRS(int argc, char *argv[])
> >
> > fs_param.s_log_frag_size = fs_param.s_log_block_size;
> >
> > - if (noaction && fs_param.s_blocks_count) {
> > - dev_size = fs_param.s_blocks_count;
> > + if (noaction && ext2fs_blocks_count(&fs_param)) {
> > + dev_size = ext2fs_blocks_count(&fs_param);
> > retval = 0;
> > } else {
> > retry:
> > - retval = ext2fs_get_device_size(device_name,
> > + retval = ext2fs_get_device_size2(device_name,
> > EXT2_BLOCK_SIZE(&fs_param),
> > &dev_size);
> > if ((retval == EFBIG) &&
>
> You should not assume that ext2fs_get_device_size2() will return EFBIG
> if the size exceed 2^32 blocks. The point of ext2fs_get_device_size2()
> was to be able to support more than 2^32 blocks and the library
> function will certainly change to return larger numbers in the future.
>
> So you need something like
>
> if ((retval == EFBIG || dev_size >= (1ULL << 32)) &&
No, ext2fs_get_device_size2() should return EFBIG size if the device is
larger than 48-bit. I need to fix that on ext2fs_get_device_size2() but
this check here is ok.
> MfG
> Goswin
-JRS
On Wed, 16 Jul 2008 15:52:01 +0200
Goswin von Brederlow <[email protected]> wrote:
> Goswin von Brederlow <[email protected]> writes:
>
> > "Jose R. Santos" <[email protected]> writes:
> >
> >> diff --git a/misc/mke2fs.c b/misc/mke2fs.c
> >> index 7171990..817be56 100644
> >> --- a/misc/mke2fs.c
> >> +++ b/misc/mke2fs.c
> >> @@ -1402,12 +1402,12 @@ static void PRS(int argc, char *argv[])
> >>
> >> fs_param.s_log_frag_size = fs_param.s_log_block_size;
> >>
> >> - if (noaction && fs_param.s_blocks_count) {
> >> - dev_size = fs_param.s_blocks_count;
> >> + if (noaction && ext2fs_blocks_count(&fs_param)) {
> >> + dev_size = ext2fs_blocks_count(&fs_param);
> >> retval = 0;
> >> } else {
> >> retry:
> >> - retval = ext2fs_get_device_size(device_name,
> >> + retval = ext2fs_get_device_size2(device_name,
> >> EXT2_BLOCK_SIZE(&fs_param),
> >> &dev_size);
> >> if ((retval == EFBIG) &&
> >
> > You should not assume that ext2fs_get_device_size2() will return EFBIG
> > if the size exceed 2^32 blocks. The point of ext2fs_get_device_size2()
> > was to be able to support more than 2^32 blocks and the library
> > function will certainly change to return larger numbers in the future.
> >
> > So you need something like
> >
> > if ((retval == EFBIG || dev_size >= (1ULL << 32)) &&
> >
> > MfG
> > Goswin
>
> Actualy that is already a problem. The ext2fs_get_device_size2() only
> returns EFBIG if sizeof(dev_size) < sizeof(unsigned long long), which
> was the case for blk_t but no longer.
>
> As a result mke2fs no longer stops with the right error on devices >
> 16TiB. My test device is exactly 32 TiB large and gives the following:
>
> root@beo-13:~# LD_LIBRARY_PATH=/tmpa/ext4 /tmpa/ext4/mke2fs -T ext4dev
> -j -m0 /dev/mapper/ext4
> mke2fs 1.41.0 (10-Jul-2008)
> mke2fs: inode_size (256) * inodes_count (0) too big for a
> filesystem with 0 blocks, specify higher inode_ratio (-i)
> or lower inode count (-N).
hehe, I put a FIXME-64 around this since I knew it was going to be a
problem. I just wasn't sure what was the right approach for fixing.
You'll have to specify an inode count for now.
The "filesystem with 0 blocks" surprise me though. Looks like I missed
something somewhere.
> I'm guessing somewhere along the line it converts to 32bit choping of
> the higher bits.
>
> MfG
> Goswin
-JRS
On Wed, Jul 16, 2008 at 09:09:31AM -0500, Jose R. Santos wrote:
> No, ext2fs_get_device_size2() should return EFBIG size if the device is
> larger than 48-bit. I need to fix that on ext2fs_get_device_size2() but
> this check here is ok.
No, please don't do that. Make it reuturn EFBIG if the device won't
fit in a blk64_t type (i.e., larger than 64-bits). In mke2fs, there
should be a separate check to make sure the size is no larger than
48-bits. Otherwise, at some future point, perhaps we might enhance
ext4 to support full a 64-bit physical block number, and then we would
have to make behavioural changes to ext2fs_get_device_size2() that
would necessitate renaming the function yet again.
It's really important when doing library design to think about future
expandability.
- Ted
From: Goswin von Brederlow <[email protected]>
Bring back overflow checks in mke2fs.c and remove dead code in
getsize.c
- ext2fs_get_device_size2() no longer returns EFBIG, the code path for
it is dead. remove.
- Change code to check actual dev_size against 2^32.
- Check for EXT4_FEATURE_INCOMPAT_64BIT before bailing out with
excessive size error.
- Move check, only check dev_size when it is actualy used. Not when
overridden by command line args.
FIXME: check command line args for excessive size too.
Signed-off-by: Goswin von Brederlow <[email protected]>
--
lib/ext2fs/getsize.c | 15 ---------------
misc/mke2fs.c | 30 +++++++++++++++---------------
2 files changed, 15 insertions(+), 30 deletions(-)
Index: e2fsprogs/misc/mke2fs.c
===================================================================
--- e2fsprogs.orig/misc/mke2fs.c 2008-07-16 15:59:48.000000000 +0200
+++ e2fsprogs/misc/mke2fs.c 2008-07-16 16:57:54.000000000 +0200
@@ -1410,21 +1410,6 @@ static void PRS(int argc, char *argv[])
retval = ext2fs_get_device_size2(device_name,
EXT2_BLOCK_SIZE(&fs_param),
&dev_size);
- if ((retval == EFBIG) &&
- (blocksize == 0) &&
- (fs_param.s_log_block_size == 0)) {
- fs_param.s_log_block_size = 2;
- blocksize = 4096;
- goto retry;
- }
- }
-
- if (retval == EFBIG) {
- fprintf(stderr, _("%s: Size of device %s too big "
- "to be expressed in 32 bits\n\t"
- "using a blocksize of %d.\n"),
- program_name, device_name, EXT2_BLOCK_SIZE(&fs_param));
- exit(1);
}
if (retval && (retval != EXT2_ET_UNIMPLEMENTED)) {
com_err(program_name, retval,
@@ -1451,7 +1436,22 @@ static void PRS(int argc, char *argv[])
));
exit(1);
}
+ if ((dev_size >= 1LLU << 32) &&
+ (blocksize == 0) &&
+ (fs_param.s_log_block_size == 0)) {
+ fs_param.s_log_block_size = 2;
+ blocksize = 4096;
+ goto retry;
+ }
+ if (!(fs_param.s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) && (dev_size >= 1ULL << 32)) {
+ fprintf(stderr, _("%s: Size of device %s too big "
+ "to be expressed in 32 bits\n\t"
+ "using a blocksize of %d.\n"),
+ program_name, device_name, EXT2_BLOCK_SIZE(&fs_param));
+ exit(1);
+ }
ext2fs_blocks_count_set(&fs_param, dev_size);
+fprintf(stderr, "blocks count = %llu\n", ext2fs_blocks_count(&fs_param));
if (sys_page_size > EXT2_BLOCK_SIZE(&fs_param)) {
blk64_t tmp = ext2fs_blocks_count(&fs_param);
tmp &= ~((sys_page_size /
Index: e2fsprogs/lib/ext2fs/getsize.c
===================================================================
--- e2fsprogs.orig/lib/ext2fs/getsize.c 2008-07-16 16:34:58.000000000 +0200
+++ e2fsprogs/lib/ext2fs/getsize.c 2008-07-16 16:49:03.000000000 +0200
@@ -188,11 +188,6 @@ errcode_t ext2fs_get_device_size2(const
#endif
if (valid_blkgetsize64 &&
ioctl(fd, BLKGETSIZE64, &size64) >= 0) {
- if ((sizeof(*retblocks) < sizeof(unsigned long long)) &&
- ((size64 / blocksize) > 0xFFFFFFFF)) {
- rc = EFBIG;
- goto out;
- }
*retblocks = size64 / blocksize;
goto out;
}
@@ -253,11 +248,6 @@ errcode_t ext2fs_get_device_size2(const
if (fstat(fd, &st) == 0)
#endif
if (S_ISREG(st.st_mode)) {
- if ((sizeof(*retblocks) < sizeof(unsigned long long)) &&
- ((st.st_size / blocksize) > 0xFFFFFFFF)) {
- rc = EFBIG;
- goto out;
- }
*retblocks = st.st_size / blocksize;
goto out;
}
@@ -282,11 +272,6 @@ errcode_t ext2fs_get_device_size2(const
}
valid_offset (fd, 0);
size64 = low + 1;
- if ((sizeof(*retblocks) < sizeof(unsigned long long))
- && ((size64 / blocksize) > 0xFFFFFFFF)) {
- rc = EFBIG;
- goto out;
- }
*retblocks = size64 / blocksize;
out:
close(fd);
On Wed, 16 Jul 2008 10:54:29 -0400
Theodore Tso <[email protected]> wrote:
> On Wed, Jul 16, 2008 at 09:09:31AM -0500, Jose R. Santos wrote:
> > No, ext2fs_get_device_size2() should return EFBIG size if the device is
> > larger than 48-bit. I need to fix that on ext2fs_get_device_size2() but
> > this check here is ok.
>
> No, please don't do that. Make it reuturn EFBIG if the device won't
> fit in a blk64_t type (i.e., larger than 64-bits). In mke2fs, there
> should be a separate check to make sure the size is no larger than
> 48-bits. Otherwise, at some future point, perhaps we might enhance
> ext4 to support full a 64-bit physical block number, and then we would
> have to make behavioural changes to ext2fs_get_device_size2() that
> would necessitate renaming the function yet again.
>
> It's really important when doing library design to think about future
> expandability.
This would not be a API or ABI change so I don't see why another
renaming function would be needed. It also doesn't change the
behavior of ext2fs_get_device_size2() since it returns EFBIG when a
device is larger than what e2fsprogs currently supports, whether that
48bit or 64bits. Putting the limit ext2fs_get_device_size2() avoid
folks from abusing something that probably isn't supported.
> - Ted
-JRS
"Jose R. Santos" <[email protected]> writes:
> On Wed, 16 Jul 2008 14:50:14 +0200
> Goswin von Brederlow <[email protected]> wrote:
>
>> "Jose R. Santos" <[email protected]> writes:
>>
>> > diff --git a/misc/mke2fs.c b/misc/mke2fs.c
>> > index 7171990..817be56 100644
>> > --- a/misc/mke2fs.c
>> > +++ b/misc/mke2fs.c
>> > @@ -1402,12 +1402,12 @@ static void PRS(int argc, char *argv[])
>> >
>> > fs_param.s_log_frag_size = fs_param.s_log_block_size;
>> >
>> > - if (noaction && fs_param.s_blocks_count) {
>> > - dev_size = fs_param.s_blocks_count;
>> > + if (noaction && ext2fs_blocks_count(&fs_param)) {
>> > + dev_size = ext2fs_blocks_count(&fs_param);
>> > retval = 0;
>> > } else {
>> > retry:
>> > - retval = ext2fs_get_device_size(device_name,
>> > + retval = ext2fs_get_device_size2(device_name,
>> > EXT2_BLOCK_SIZE(&fs_param),
>> > &dev_size);
>> > if ((retval == EFBIG) &&
>>
>> You should not assume that ext2fs_get_device_size2() will return EFBIG
>> if the size exceed 2^32 blocks. The point of ext2fs_get_device_size2()
>> was to be able to support more than 2^32 blocks and the library
>> function will certainly change to return larger numbers in the future.
>>
>> So you need something like
>>
>> if ((retval == EFBIG || dev_size >= (1ULL << 32)) &&
>
> No, ext2fs_get_device_size2() should return EFBIG size if the device is
> larger than 48-bit. I need to fix that on ext2fs_get_device_size2() but
> this check here is ok.
>
>> MfG
>> Goswin
>
> -JRS
Why? The decision what device size if too big depends on the features
for this filesystem. By default 32bit is the limit, with
EXT4_FEATURE_INCOMPAT_64BIT it is 48bit. (shouldn't that be named
EXT4_FEATURE_INCOMPAT_48BIT?). Maybe later there will be a true 64bit
feature.
If you make ext2fs_get_device_size2() return EFBIG for >48bit then you
have to check for EFBIG and conditionally for 2^32 which makes the
code more complex. Better to just check the actual size the device has
in mke2fs.c.
Also the user might give a size that is actually small enough while
the device would be too big. Say, with current mke2fs, you have a disk
that is 16.000001TiB large. You could tell mke2fs to only use 2^32-1
blocks. The EFBIG check prevents that.
See the patch I just send.
MfG
Goswin
"Jose R. Santos" <[email protected]> writes:
> On Wed, 16 Jul 2008 15:52:01 +0200
> Goswin von Brederlow <[email protected]> wrote:
>> My test device is exactly 32 TiB large and gives the following:
>>
>> root@beo-13:~# LD_LIBRARY_PATH=/tmpa/ext4 /tmpa/ext4/mke2fs -T ext4dev
>> -j -m0 /dev/mapper/ext4
>> mke2fs 1.41.0 (10-Jul-2008)
>> mke2fs: inode_size (256) * inodes_count (0) too big for a
>> filesystem with 0 blocks, specify higher inode_ratio (-i)
>> or lower inode count (-N).
>
> hehe, I put a FIXME-64 around this since I knew it was going to be a
> problem. I just wasn't sure what was the right approach for fixing.
> You'll have to specify an inode count for now.
>
> The "filesystem with 0 blocks" surprise me though. Looks like I missed
> something somewhere.
/*
* Set the fs block count
*/
void ext2fs_blocks_count_set(struct ext2_super_block *super, blk64_t blk)
{
super->s_blocks_count = blk;
if (super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
super->s_blocks_count_hi = (__u64) blk >> 32;
}
EXT4_FEATURE_INCOMPAT_64BIT is not set so the upper bits just get
ignored.
MfG
Goswin
PS: Should functions that chop off upper bits like that make sure they
are 0?
On Wed, 16 Jul 2008 17:21:58 +0200
Goswin von Brederlow <[email protected]> wrote:
> "Jose R. Santos" <[email protected]> writes:
>
> > On Wed, 16 Jul 2008 14:50:14 +0200
> > Goswin von Brederlow <[email protected]> wrote:
> >
> >> "Jose R. Santos" <[email protected]> writes:
> >>
> >> > diff --git a/misc/mke2fs.c b/misc/mke2fs.c
> >> > index 7171990..817be56 100644
> >> > --- a/misc/mke2fs.c
> >> > +++ b/misc/mke2fs.c
> >> > @@ -1402,12 +1402,12 @@ static void PRS(int argc, char *argv[])
> >> >
> >> > fs_param.s_log_frag_size = fs_param.s_log_block_size;
> >> >
> >> > - if (noaction && fs_param.s_blocks_count) {
> >> > - dev_size = fs_param.s_blocks_count;
> >> > + if (noaction && ext2fs_blocks_count(&fs_param)) {
> >> > + dev_size = ext2fs_blocks_count(&fs_param);
> >> > retval = 0;
> >> > } else {
> >> > retry:
> >> > - retval = ext2fs_get_device_size(device_name,
> >> > + retval = ext2fs_get_device_size2(device_name,
> >> > EXT2_BLOCK_SIZE(&fs_param),
> >> > &dev_size);
> >> > if ((retval == EFBIG) &&
> >>
> >> You should not assume that ext2fs_get_device_size2() will return EFBIG
> >> if the size exceed 2^32 blocks. The point of ext2fs_get_device_size2()
> >> was to be able to support more than 2^32 blocks and the library
> >> function will certainly change to return larger numbers in the future.
> >>
> >> So you need something like
> >>
> >> if ((retval == EFBIG || dev_size >= (1ULL << 32)) &&
> >
> > No, ext2fs_get_device_size2() should return EFBIG size if the device is
> > larger than 48-bit. I need to fix that on ext2fs_get_device_size2() but
> > this check here is ok.
> >
> >> MfG
> >> Goswin
> >
> > -JRS
>
> Why? The decision what device size if too big depends on the features
> for this filesystem. By default 32bit is the limit, with
> EXT4_FEATURE_INCOMPAT_64BIT it is 48bit. (shouldn't that be named
> EXT4_FEATURE_INCOMPAT_48BIT?). Maybe later there will be a true 64bit
> feature.
You have a point. The ext2fs_get_device_size2() should really be
concerned with what file system features are supported. That is
outside of the scope of this routine.
I retract the previous statement I just reply to Ted. :)
>
> If you make ext2fs_get_device_size2() return EFBIG for >48bit then you
> have to check for EFBIG and conditionally for 2^32 which makes the
> code more complex. Better to just check the actual size the device has
> in mke2fs.c.
>
> Also the user might give a size that is actually small enough while
> the device would be too big. Say, with current mke2fs, you have a disk
> that is 16.000001TiB large. You could tell mke2fs to only use 2^32-1
> blocks. The EFBIG check prevents that.
>
> See the patch I just send.
>
> MfG
> Goswin
-JRS
On Wed, 16 Jul 2008 17:23:45 +0200
Goswin von Brederlow <[email protected]> wrote:
> "Jose R. Santos" <[email protected]> writes:
>
> > On Wed, 16 Jul 2008 15:52:01 +0200
> > Goswin von Brederlow <[email protected]> wrote:
> >> My test device is exactly 32 TiB large and gives the following:
> >>
> >> root@beo-13:~# LD_LIBRARY_PATH=/tmpa/ext4 /tmpa/ext4/mke2fs -T ext4dev
> >> -j -m0 /dev/mapper/ext4
> >> mke2fs 1.41.0 (10-Jul-2008)
> >> mke2fs: inode_size (256) * inodes_count (0) too big for a
> >> filesystem with 0 blocks, specify higher inode_ratio (-i)
> >> or lower inode count (-N).
> >
> > hehe, I put a FIXME-64 around this since I knew it was going to be a
> > problem. I just wasn't sure what was the right approach for fixing.
> > You'll have to specify an inode count for now.
> >
> > The "filesystem with 0 blocks" surprise me though. Looks like I missed
> > something somewhere.
>
> /*
> * Set the fs block count
> */
> void ext2fs_blocks_count_set(struct ext2_super_block *super, blk64_t blk)
> {
> super->s_blocks_count = blk;
> if (super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
> super->s_blocks_count_hi = (__u64) blk >> 32;
> }
>
> EXT4_FEATURE_INCOMPAT_64BIT is not set so the upper bits just get
> ignored.
>
> MfG
> Goswin
>
> PS: Should functions that chop off upper bits like that make sure they
> are 0?
I think this is something that need to be cheched at fsck since having
these be non-zero on a non-64-bit FS should be pointing to file system
corruption. Not sure if its something that need to be done every time
we set a value on the lower bit only though.
We could add error code here but that means that the users of the
routine need to handle the error code. Determining now if we need to
return errcode_t here now would avoid the need to change the API later.
Ted. Any comment on this one?
-JRS
"Jose R. Santos" <[email protected]> writes:
> diff --git a/lib/ext2fs/initialize.c b/lib/ext2fs/initialize.c
> index e9bfe49..5060fda 100644
> --- a/lib/ext2fs/initialize.c
> +++ b/lib/ext2fs/initialize.c
> @@ -200,9 +200,9 @@ errcode_t ext2fs_initialize(const char *name, int flags,
> super->s_blocks_per_group = EXT2_MAX_BLOCKS_PER_GROUP(super);
> super->s_frags_per_group = super->s_blocks_per_group * frags_per_block;
>
> - super->s_blocks_count = param->s_blocks_count;
> - super->s_r_blocks_count = param->s_r_blocks_count;
> - if (super->s_r_blocks_count >= param->s_blocks_count) {
> + ext2fs_blocks_count_set(super, param->s_blocks_count);
> + ext2fs_r_blocks_count_set(super, param->s_r_blocks_count);
> + if (ext2fs_r_blocks_count(super) >= ext2fs_blocks_count(param)) {
> retval = EXT2_ET_INVALID_ARGUMENT;
> goto cleanup;
> }
This needs to preserve the high bits from param:
+ ext2fs_blocks_count_set(super, ext2fs_blocks_count(param));
+ ext2fs_r_blocks_count_set(super, ext2fs_r_blocks_count(param->s_r_blocks_count));
MfG
Goswin
On Wed, Jul 16, 2008 at 10:18:17AM -0500, Jose R. Santos wrote:
> > It's really important when doing library design to think about future
> > expandability.
>
> This would not be a API or ABI change so I don't see why another
> renaming function would be needed. It also doesn't change the
> behavior of ext2fs_get_device_size2() since it returns EFBIG when a
> device is larger than what e2fsprogs currently supports, whether that
> 48bit or 64bits. Putting the limit ext2fs_get_device_size2() avoid
> folks from abusing something that probably isn't supported.
E2fsprogs utilities are somewhat entitled to assume that they will be
running with a version of libext2fs which is the same as the one that
they shipped with --- although sometimes that assumption can be false,
particularly when people are building a newer version of e2fsprogs
from source and forget to install the newer libraries or forget to set
LD_LIBRARY_PATH if they are building with dynamic libraries.
However there may be other users of that interface, and they won't
know if version of that library they are calling is set to return
EFBIG on a 48bit or 64bit number. Besides, there may be other
application users of that function where it would be useful to get the
size of a device which is larger than 48-bits, even if mke2fs and ext4
today doesn't support it. This is just good library design not to
enforce limits like this in a fairly generic function.
Finally, in many programming discplines you *do* rename the function
whenever you make major semantic changes to the function, not just for
API or ABI changes. Otherwise a newer program might depend on
ext2fs_get_device_size() returning a 64-bit size, and then it might
get very confused or fail in unexpected ways if it is linked with an
older library that returns EFBIG if the number is bigger than 48 bits.
It's just a matter of how defensive you want to be in your
programming, and how general-purpose you want you library routines to
be.
Regards,
- Ted
On Wed, Jul 16, 2008 at 11:02:42AM -0500, Jose R. Santos wrote:
> > PS: Should functions that chop off upper bits like that make sure they
> > are 0?
>
> I think this is something that need to be cheched at fsck since having
> these be non-zero on a non-64-bit FS should be pointing to file system
> corruption. Not sure if its something that need to be done every time
> we set a value on the lower bit only though.
Well, to quote Postel's law (also known as the robustness principle):
"Be conservative in what you do; be liberal in what you accept from
others."
This is a generalization from what Jon Postel wrote in RFC 793: "TCP
implementations will follow a general principle of robustness: be
conservative in what you do, be liberal in what you accept from
others," but it applies here as well. So yes, the library code should
clear the upper bits even if 64-bit feature flag is not set. However,
we should not depend on the upper bits being zero if the 64-bit
feature flag is not set.
Does that make sense?
- Ted
On Wed, 16 Jul 2008 12:31:48 -0400
Theodore Tso <[email protected]> wrote:
> On Wed, Jul 16, 2008 at 10:18:17AM -0500, Jose R. Santos wrote:
> > > It's really important when doing library design to think about future
> > > expandability.
> >
> > This would not be a API or ABI change so I don't see why another
> > renaming function would be needed. It also doesn't change the
> > behavior of ext2fs_get_device_size2() since it returns EFBIG when a
> > device is larger than what e2fsprogs currently supports, whether that
> > 48bit or 64bits. Putting the limit ext2fs_get_device_size2() avoid
> > folks from abusing something that probably isn't supported.
>
> E2fsprogs utilities are somewhat entitled to assume that they will be
> running with a version of libext2fs which is the same as the one that
> they shipped with --- although sometimes that assumption can be false,
> particularly when people are building a newer version of e2fsprogs
> from source and forget to install the newer libraries or forget to set
> LD_LIBRARY_PATH if they are building with dynamic libraries.
I was mostly referring to external users of the library.
> However there may be other users of that interface, and they won't
> know if version of that library they are calling is set to return
> EFBIG on a 48bit or 64bit number. Besides, there may be other
> application users of that function where it would be useful to get the
> size of a device which is larger than 48-bits, even if mke2fs and ext4
> today doesn't support it. This is just good library design not to
> enforce limits like this in a fairly generic function.
I agree and have already retracted my previous statement base on this.
>
> Finally, in many programming discplines you *do* rename the function
> whenever you make major semantic changes to the function, not just for
> API or ABI changes. Otherwise a newer program might depend on
> ext2fs_get_device_size() returning a 64-bit size, and then it might
> get very confused or fail in unexpected ways if it is linked with an
> older library that returns EFBIG if the number is bigger than 48 bits.
While I agree that we should not put this limitation on
ext2fs_get_device_size2(), why does EFBIG (or something equivalent when
we implement this outside of get_size) have to means anything other
that the size is bigger than what the current library support. It
could be 48bit, 64bit or 1024bit, if we hit it, the current library
will not support it.
I dont see the point in having (for example) EFBIG_48 and EFBIG_64 if
we implement EFBIG right.
> It's just a matter of how defensive you want to be in your
> programming, and how general-purpose you want you library routines to
> be.
>
> Regards,
>
> - Ted
I think I'm just ranting here. Feel free to ignore :)
-JRS
On Wed, 16 Jul 2008 17:13:31 +0200
Goswin von Brederlow <[email protected]> wrote:
> From: Goswin von Brederlow <[email protected]>
>
> Bring back overflow checks in mke2fs.c and remove dead code in
> getsize.c
>
> - ext2fs_get_device_size2() no longer returns EFBIG, the code path for
> it is dead. remove.
>
> - Change code to check actual dev_size against 2^32.
>
> - Check for EXT4_FEATURE_INCOMPAT_64BIT before bailing out with
> excessive size error.
>
> - Move check, only check dev_size when it is actualy used. Not when
> overridden by command line args.
>
> FIXME: check command line args for excessive size too.
>
> Signed-off-by: Goswin von Brederlow <[email protected]>
> --
>
> lib/ext2fs/getsize.c | 15 ---------------
> misc/mke2fs.c | 30 +++++++++++++++---------------
> 2 files changed, 15 insertions(+), 30 deletions(-)
>
> Index: e2fsprogs/misc/mke2fs.c
> ===================================================================
> --- e2fsprogs.orig/misc/mke2fs.c 2008-07-16 15:59:48.000000000 +0200
> +++ e2fsprogs/misc/mke2fs.c 2008-07-16 16:57:54.000000000 +0200
> @@ -1410,21 +1410,6 @@ static void PRS(int argc, char *argv[])
> retval = ext2fs_get_device_size2(device_name,
> EXT2_BLOCK_SIZE(&fs_param),
> &dev_size);
> - if ((retval == EFBIG) &&
> - (blocksize == 0) &&
> - (fs_param.s_log_block_size == 0)) {
> - fs_param.s_log_block_size = 2;
> - blocksize = 4096;
> - goto retry;
> - }
> - }
> -
> - if (retval == EFBIG) {
> - fprintf(stderr, _("%s: Size of device %s too big "
> - "to be expressed in 32 bits\n\t"
> - "using a blocksize of %d.\n"),
> - program_name, device_name, EXT2_BLOCK_SIZE(&fs_param));
> - exit(1);
> }
> if (retval && (retval != EXT2_ET_UNIMPLEMENTED)) {
> com_err(program_name, retval,
> @@ -1451,7 +1436,22 @@ static void PRS(int argc, char *argv[])
> ));
> exit(1);
> }
> + if ((dev_size >= 1LLU << 32) &&
> + (blocksize == 0) &&
> + (fs_param.s_log_block_size == 0)) {
> + fs_param.s_log_block_size = 2;
> + blocksize = 4096;
> + goto retry;
> + }
> + if (!(fs_param.s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) && (dev_size >= 1ULL << 32)) {
> + fprintf(stderr, _("%s: Size of device %s too big "
> + "to be expressed in 32 bits\n\t"
> + "using a blocksize of %d.\n"),
> + program_name, device_name, EXT2_BLOCK_SIZE(&fs_param));
> + exit(1);
> + }
Well, EXT4_FEATURE_INCOMPAT_64BIT should be setup later in PRS() along
with setting up large group descriptors so this piece need work. This
should fail if what we are making is a ext3 filesystem and if we are
making a ext4 filesystem with > 32bit blocks, set the
EXT4_FEATURE_INCOMPAT_64BIT flag as well as the large bgd.
I'll fix this on the next release.
> ext2fs_blocks_count_set(&fs_param, dev_size);
> +fprintf(stderr, "blocks count = %llu\n", ext2fs_blocks_count(&fs_param));
> if (sys_page_size > EXT2_BLOCK_SIZE(&fs_param)) {
> blk64_t tmp = ext2fs_blocks_count(&fs_param);
> tmp &= ~((sys_page_size /
> Index: e2fsprogs/lib/ext2fs/getsize.c
> ===================================================================
> --- e2fsprogs.orig/lib/ext2fs/getsize.c 2008-07-16 16:34:58.000000000 +0200
> +++ e2fsprogs/lib/ext2fs/getsize.c 2008-07-16 16:49:03.000000000 +0200
> @@ -188,11 +188,6 @@ errcode_t ext2fs_get_device_size2(const
> #endif
> if (valid_blkgetsize64 &&
> ioctl(fd, BLKGETSIZE64, &size64) >= 0) {
> - if ((sizeof(*retblocks) < sizeof(unsigned long long)) &&
> - ((size64 / blocksize) > 0xFFFFFFFF)) {
> - rc = EFBIG;
> - goto out;
> - }
> *retblocks = size64 / blocksize;
> goto out;
> }
> @@ -253,11 +248,6 @@ errcode_t ext2fs_get_device_size2(const
> if (fstat(fd, &st) == 0)
> #endif
> if (S_ISREG(st.st_mode)) {
> - if ((sizeof(*retblocks) < sizeof(unsigned long long)) &&
> - ((st.st_size / blocksize) > 0xFFFFFFFF)) {
> - rc = EFBIG;
> - goto out;
> - }
> *retblocks = st.st_size / blocksize;
> goto out;
> }
> @@ -282,11 +272,6 @@ errcode_t ext2fs_get_device_size2(const
> }
> valid_offset (fd, 0);
> size64 = low + 1;
> - if ((sizeof(*retblocks) < sizeof(unsigned long long))
> - && ((size64 / blocksize) > 0xFFFFFFFF)) {
> - rc = EFBIG;
> - goto out;
> - }
> *retblocks = size64 / blocksize;
> out:
> close(fd);
On Wed, 16 Jul 2008 13:18:24 -0400
Theodore Tso <[email protected]> wrote:
> On Wed, Jul 16, 2008 at 11:02:42AM -0500, Jose R. Santos wrote:
> > > PS: Should functions that chop off upper bits like that make sure they
> > > are 0?
> >
> > I think this is something that need to be cheched at fsck since having
> > these be non-zero on a non-64-bit FS should be pointing to file system
> > corruption. Not sure if its something that need to be done every time
> > we set a value on the lower bit only though.
>
> Well, to quote Postel's law (also known as the robustness principle):
> "Be conservative in what you do; be liberal in what you accept from
> others."
>
> This is a generalization from what Jon Postel wrote in RFC 793: "TCP
> implementations will follow a general principle of robustness: be
> conservative in what you do, be liberal in what you accept from
> others," but it applies here as well. So yes, the library code should
> clear the upper bits even if 64-bit feature flag is not set. However,
> we should not depend on the upper bits being zero if the 64-bit
> feature flag is not set.
>
> Does that make sense?
Set it; don't check it. Got it.
I'll just check for large descriptors instead of the 64-bit feature
flag. That should set the upper bit regardless of whether we use a
64bit fs or not.
>
> - Ted
>
-JRS
"Jose R. Santos" <[email protected]> writes:
> On Wed, 16 Jul 2008 17:23:45 +0200
> Goswin von Brederlow <[email protected]> wrote:
>> /*
>> * Set the fs block count
>> */
>> void ext2fs_blocks_count_set(struct ext2_super_block *super, blk64_t blk)
>> {
>> super->s_blocks_count = blk;
>> if (super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
>> super->s_blocks_count_hi = (__u64) blk >> 32;
>> }
>>
>> EXT4_FEATURE_INCOMPAT_64BIT is not set so the upper bits just get
>> ignored.
>>
>> MfG
>> Goswin
>>
>> PS: Should functions that chop off upper bits like that make sure they
>> are 0?
>
> I think this is something that need to be cheched at fsck since having
> these be non-zero on a non-64-bit FS should be pointing to file system
> corruption. Not sure if its something that need to be done every time
> we set a value on the lower bit only though.
I ment checking the blk64_t blk < 2^32. And yes then the function has
to return an error code EINVAL.
But they should be zeroed out as well in the superblock just in case.
> We could add error code here but that means that the users of the
> routine need to handle the error code. Determining now if we need to
> return errcode_t here now would avoid the need to change the API later.
>
> Ted. Any comment on this one?
>
> -JRS
MfG
Goswin
"Jose R. Santos" <[email protected]> writes:
> On Wed, 16 Jul 2008 12:31:48 -0400
> Theodore Tso <[email protected]> wrote:
>
>> On Wed, Jul 16, 2008 at 10:18:17AM -0500, Jose R. Santos wrote:
>> > > It's really important when doing library design to think about future
>> > > expandability.
>> >
>> > This would not be a API or ABI change so I don't see why another
>> > renaming function would be needed. It also doesn't change the
>> > behavior of ext2fs_get_device_size2() since it returns EFBIG when a
>> > device is larger than what e2fsprogs currently supports, whether that
>> > 48bit or 64bits. Putting the limit ext2fs_get_device_size2() avoid
>> > folks from abusing something that probably isn't supported.
>>
>> E2fsprogs utilities are somewhat entitled to assume that they will be
>> running with a version of libext2fs which is the same as the one that
>> they shipped with --- although sometimes that assumption can be false,
>> particularly when people are building a newer version of e2fsprogs
>> from source and forget to install the newer libraries or forget to set
>> LD_LIBRARY_PATH if they are building with dynamic libraries.
>
> I was mostly referring to external users of the library.
>
>> However there may be other users of that interface, and they won't
>> know if version of that library they are calling is set to return
>> EFBIG on a 48bit or 64bit number. Besides, there may be other
>> application users of that function where it would be useful to get the
>> size of a device which is larger than 48-bits, even if mke2fs and ext4
>> today doesn't support it. This is just good library design not to
>> enforce limits like this in a fairly generic function.
>
> I agree and have already retracted my previous statement base on this.
>
>>
>> Finally, in many programming discplines you *do* rename the function
>> whenever you make major semantic changes to the function, not just for
>> API or ABI changes. Otherwise a newer program might depend on
>> ext2fs_get_device_size() returning a 64-bit size, and then it might
>> get very confused or fail in unexpected ways if it is linked with an
>> older library that returns EFBIG if the number is bigger than 48 bits.
>
> While I agree that we should not put this limitation on
> ext2fs_get_device_size2(), why does EFBIG (or something equivalent when
> we implement this outside of get_size) have to means anything other
> that the size is bigger than what the current library support. It
> could be 48bit, 64bit or 1024bit, if we hit it, the current library
> will not support it.
>
> I dont see the point in having (for example) EFBIG_48 and EFBIG_64 if
> we implement EFBIG right.
Here EFBIG means the size is bigger than what is representable in the
current datatype. Both 48bit and 64bit block counter are representable
in blk64_t. A 128bit size on the other hand would be not. As long as
the size can be represented correctly in the return type the caller
can check itself if it exceeds their own limits.
As such the ext2fs_get_device_size() function (and all other wrappers
returning a blk_t) really should do something like this:
blk64_t size64;
retval = ext2fs_get_device_size2(device_name, blocksize, &size64);
if (!retval && size64 >= 2^32) return EFBIG;
*size = size64;
return retval;
MfG
Goswin
PS: as blk64_t can represent any size we can possibly get (ioctl, stat
and llseek methods only give 64bit) I see no reason to have an EFBIG
for now.
On Wed, 16 Jul 2008 21:07:40 +0200
Goswin von Brederlow <[email protected]> wrote:
> "Jose R. Santos" <[email protected]> writes:
>
> > On Wed, 16 Jul 2008 12:31:48 -0400
> > Theodore Tso <[email protected]> wrote:
> >
> >> On Wed, Jul 16, 2008 at 10:18:17AM -0500, Jose R. Santos wrote:
> >> > > It's really important when doing library design to think about future
> >> > > expandability.
> >> >
> >> > This would not be a API or ABI change so I don't see why another
> >> > renaming function would be needed. It also doesn't change the
> >> > behavior of ext2fs_get_device_size2() since it returns EFBIG when a
> >> > device is larger than what e2fsprogs currently supports, whether that
> >> > 48bit or 64bits. Putting the limit ext2fs_get_device_size2() avoid
> >> > folks from abusing something that probably isn't supported.
> >>
> >> E2fsprogs utilities are somewhat entitled to assume that they will be
> >> running with a version of libext2fs which is the same as the one that
> >> they shipped with --- although sometimes that assumption can be false,
> >> particularly when people are building a newer version of e2fsprogs
> >> from source and forget to install the newer libraries or forget to set
> >> LD_LIBRARY_PATH if they are building with dynamic libraries.
> >
> > I was mostly referring to external users of the library.
> >
> >> However there may be other users of that interface, and they won't
> >> know if version of that library they are calling is set to return
> >> EFBIG on a 48bit or 64bit number. Besides, there may be other
> >> application users of that function where it would be useful to get the
> >> size of a device which is larger than 48-bits, even if mke2fs and ext4
> >> today doesn't support it. This is just good library design not to
> >> enforce limits like this in a fairly generic function.
> >
> > I agree and have already retracted my previous statement base on this.
> >
> >>
> >> Finally, in many programming discplines you *do* rename the function
> >> whenever you make major semantic changes to the function, not just for
> >> API or ABI changes. Otherwise a newer program might depend on
> >> ext2fs_get_device_size() returning a 64-bit size, and then it might
> >> get very confused or fail in unexpected ways if it is linked with an
> >> older library that returns EFBIG if the number is bigger than 48 bits.
> >
> > While I agree that we should not put this limitation on
> > ext2fs_get_device_size2(), why does EFBIG (or something equivalent when
> > we implement this outside of get_size) have to means anything other
> > that the size is bigger than what the current library support. It
> > could be 48bit, 64bit or 1024bit, if we hit it, the current library
> > will not support it.
> >
> > I dont see the point in having (for example) EFBIG_48 and EFBIG_64 if
> > we implement EFBIG right.
>
> Here EFBIG means the size is bigger than what is representable in the
> current datatype. Both 48bit and 64bit block counter are representable
> in blk64_t. A 128bit size on the other hand would be not. As long as
> the size can be represented correctly in the return type the caller
> can check itself if it exceeds their own limits.
>
> As such the ext2fs_get_device_size() function (and all other wrappers
> returning a blk_t) really should do something like this:
>
> blk64_t size64;
> retval = ext2fs_get_device_size2(device_name, blocksize, &size64);
> if (!retval && size64 >= 2^32) return EFBIG;
> *size = size64;
> return retval;
You've exposed another bug. I obviously was not paying to much
attention when doing mke2fs changes. I will fix in the next release.
>
> MfG
> Goswin
>
> PS: as blk64_t can represent any size we can possibly get (ioctl, stat
> and llseek methods only give 64bit) I see no reason to have an EFBIG
> for now.
Agree.
-JRS
Hi folks,
I'm posting a new version of the 64-bit mke2fs patch since it was broken
in many ways (many thanks to Goswin for having a look and pointing them
out). This one can actually handle large fs as runs until its time to
allocate table (where it barfs due bitmap issues). To make 64bit fs, I
use the following command.
mke2fs -T ext4dev -O64bit /dev/my_large_disk
Comments welcome
-JRS
64-bit mke2fs cleanup
From: Jose R. Santos <[email protected]>
Use 64-bit interfaces in mke2fs. This should be most most of whats
needed to support creating a 64-bit filesystem. Things missing:
- 64-bit bitmap support being developed by Ted. We cant make a 64bit
fs without this.
- 64-bit badblock interface. Waiting on Ted 64-bit bitmap patches to
shamelessly steel some of his code. (particularly, the handling of
different interface through the structure magic numbers)
This is not needed to create a 64-bit filesystem, but you cant have
bad blocks above the 32bit block number boundary.
- lost+found and journal file are not created as extent mapped files.
Should not prevent from creating a 64-bit filesystem and since those
are typically at the beginning of the disk, don't know if I should
really care. Don't know much about the extent format to know for sure.
Signed-off-by: Jose R. Santos <[email protected]>
---
lib/ext2fs/alloc_tables.c | 77 +++++++++++++----------
lib/ext2fs/ext2fs.h | 6 +-
lib/ext2fs/initialize.c | 44 +++++++++----
misc/mke2fs.c | 149 +++++++++++++++++++++++++--------------------
4 files changed, 158 insertions(+), 118 deletions(-)
diff --git a/lib/ext2fs/alloc_tables.c b/lib/ext2fs/alloc_tables.c
index 8c0ecfc..3f7b454 100644
--- a/lib/ext2fs/alloc_tables.c
+++ b/lib/ext2fs/alloc_tables.c
@@ -33,11 +33,11 @@
* block number with a correct offset were the bitmaps and inode
* tables can be allocated continously and in order.
*/
-static blk_t flexbg_offset(ext2_filsys fs, dgrp_t group, blk_t start_blk,
+static blk64_t flexbg_offset(ext2_filsys fs, dgrp_t group, blk_t start_blk,
ext2fs_block_bitmap bmap, int offset, int size)
{
int flexbg, flexbg_size, elem_size;
- blk_t last_blk, first_free = 0;
+ blk64_t last_blk, first_free = 0;
dgrp_t last_grp;
flexbg_size = 1 << fs->super->s_log_groups_per_flex;
@@ -70,11 +70,11 @@ static blk_t flexbg_offset(ext2_filsys fs, dgrp_t group, blk_t start_blk,
last_blk = ext2fs_group_last_block(fs, last_grp);
/* Find the first available block */
- if (ext2fs_get_free_blocks(fs, start_blk, last_blk, 1, bmap,
+ if (ext2fs_get_free_blocks2(fs, start_blk, last_blk, 1, bmap,
&first_free))
return first_free;
- if (ext2fs_get_free_blocks(fs, first_free + offset, last_blk, size,
+ if (ext2fs_get_free_blocks2(fs, first_free + offset, last_blk, size,
bmap, &first_free))
return first_free;
@@ -85,12 +85,12 @@ errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group,
ext2fs_block_bitmap bmap)
{
errcode_t retval;
- blk_t group_blk, start_blk, last_blk, new_blk, blk;
+ blk64_t group_blk, start_blk, last_blk, new_blk, blk;
dgrp_t last_grp = 0;
int j, rem_grps = 0, flexbg_size = 0;
- group_blk = ext2fs_group_first_block(fs, group);
- last_blk = ext2fs_group_last_block(fs, group);
+ group_blk = ext2fs_group_first_block2(fs, group);
+ last_blk = ext2fs_group_last_block2(fs, group);
if (!bmap)
bmap = fs->block_map;
@@ -109,8 +109,8 @@ errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group,
* Allocate the block and inode bitmaps, if necessary
*/
if (fs->stride) {
- retval = ext2fs_get_free_blocks(fs, group_blk, last_blk,
- 1, bmap, &start_blk);
+ retval = ext2fs_get_free_blocks2(fs, group_blk, last_blk,
+ 1, bmap, &start_blk);
if (retval)
return retval;
start_blk += fs->inode_blocks_per_group;
@@ -123,27 +123,30 @@ errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group,
if (flexbg_size) {
int prev_block = 0;
- if (group && fs->group_desc[group-1].bg_block_bitmap)
- prev_block = fs->group_desc[group-1].bg_block_bitmap;
+ if (group && ext2fs_block_bitmap_loc(fs, group - 1))
+ prev_block = ext2fs_block_bitmap_loc(fs, group - 1);
start_blk = flexbg_offset(fs, group, prev_block, bmap,
0, rem_grps);
- last_blk = ext2fs_group_last_block(fs, last_grp);
+ last_blk = ext2fs_group_last_block2(fs, last_grp);
}
if (!fs->group_desc[group].bg_block_bitmap) {
- retval = ext2fs_get_free_blocks(fs, start_blk, last_blk,
- 1, bmap, &new_blk);
+ retval = ext2fs_get_free_blocks2(fs, start_blk, last_blk,
+ 1, bmap, &new_blk);
if (retval == EXT2_ET_BLOCK_ALLOC_FAIL)
- retval = ext2fs_get_free_blocks(fs, group_blk,
+ retval = ext2fs_get_free_blocks2(fs, group_blk,
last_blk, 1, bmap, &new_blk);
if (retval)
return retval;
+ /* FIXME-64 */
ext2fs_mark_block_bitmap(bmap, new_blk);
- fs->group_desc[group].bg_block_bitmap = new_blk;
+ ext2fs_block_bitmap_loc_set(fs, group, new_blk);
if (flexbg_size) {
- dgrp_t gr = ext2fs_group_of_blk(fs, new_blk);
+ dgrp_t gr = ext2fs_group_of_blk2(fs, new_blk);
fs->group_desc[gr].bg_free_blocks_count--;
- fs->super->s_free_blocks_count--;
+ ext2fs_free_blocks_count_set(fs->super,
+ ext2fs_free_blocks_count(
+ fs->super) - 1);
fs->group_desc[gr].bg_flags &= ~EXT2_BG_BLOCK_UNINIT;
ext2fs_group_desc_csum_set(fs, gr);
}
@@ -151,27 +154,30 @@ errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group,
if (flexbg_size) {
int prev_block = 0;
- if (group && fs->group_desc[group-1].bg_inode_bitmap)
- prev_block = fs->group_desc[group-1].bg_inode_bitmap;
+ if (group && ext2fs_inode_bitmap_loc(fs, group - 1))
+ prev_block = ext2fs_inode_bitmap_loc(fs, group - 1);
start_blk = flexbg_offset(fs, group, prev_block, bmap,
flexbg_size, rem_grps);
- last_blk = ext2fs_group_last_block(fs, last_grp);
+ last_blk = ext2fs_group_last_block2(fs, last_grp);
}
if (!fs->group_desc[group].bg_inode_bitmap) {
- retval = ext2fs_get_free_blocks(fs, start_blk, last_blk,
- 1, bmap, &new_blk);
+ retval = ext2fs_get_free_blocks2(fs, start_blk, last_blk,
+ 1, bmap, &new_blk);
if (retval == EXT2_ET_BLOCK_ALLOC_FAIL)
- retval = ext2fs_get_free_blocks(fs, group_blk,
+ retval = ext2fs_get_free_blocks2(fs, group_blk,
last_blk, 1, bmap, &new_blk);
if (retval)
return retval;
+ /* FIXME-64 */
ext2fs_mark_block_bitmap(bmap, new_blk);
- fs->group_desc[group].bg_inode_bitmap = new_blk;
+ ext2fs_inode_bitmap_loc_set(fs, group, new_blk);
if (flexbg_size) {
- dgrp_t gr = ext2fs_group_of_blk(fs, new_blk);
+ dgrp_t gr = ext2fs_group_of_blk2(fs, new_blk);
fs->group_desc[gr].bg_free_blocks_count--;
- fs->super->s_free_blocks_count--;
+ ext2fs_free_blocks_count_set(fs->super,
+ ext2fs_free_blocks_count(
+ fs->super) - 1);
fs->group_desc[gr].bg_flags &= ~EXT2_BG_BLOCK_UNINIT;
ext2fs_group_desc_csum_set(fs, gr);
}
@@ -182,17 +188,17 @@ errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group,
*/
if (flexbg_size) {
int prev_block = 0;
- if (group && fs->group_desc[group-1].bg_inode_table)
- prev_block = fs->group_desc[group-1].bg_inode_table;
+ if (group && ext2fs_inode_table_loc(fs, group - 1))
+ prev_block = ext2fs_inode_table_loc(fs, group - 1);
group_blk = flexbg_offset(fs, group, prev_block, bmap,
flexbg_size * 2,
fs->inode_blocks_per_group *
rem_grps);
- last_blk = ext2fs_group_last_block(fs, last_grp);
+ last_blk = ext2fs_group_last_block2(fs, last_grp);
}
if (!fs->group_desc[group].bg_inode_table) {
- retval = ext2fs_get_free_blocks(fs, group_blk, last_blk,
+ retval = ext2fs_get_free_blocks2(fs, group_blk, last_blk,
fs->inode_blocks_per_group,
bmap, &new_blk);
if (retval)
@@ -200,16 +206,19 @@ errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group,
for (j=0, blk = new_blk;
j < fs->inode_blocks_per_group;
j++, blk++) {
+ /* FIXME-64 */
ext2fs_mark_block_bitmap(bmap, blk);
if (flexbg_size) {
- dgrp_t gr = ext2fs_group_of_blk(fs, blk);
+ dgrp_t gr = ext2fs_group_of_blk2(fs, blk);
fs->group_desc[gr].bg_free_blocks_count--;
- fs->super->s_free_blocks_count--;
+ ext2fs_free_blocks_count_set(fs->super,
+ ext2fs_free_blocks_count(
+ fs->super) - 1);
fs->group_desc[gr].bg_flags &= ~EXT2_BG_BLOCK_UNINIT;
ext2fs_group_desc_csum_set(fs, gr);
}
}
- fs->group_desc[group].bg_inode_table = new_blk;
+ ext2fs_inode_table_loc_set(fs, group, new_blk);
}
ext2fs_group_desc_csum_set(fs, group);
return 0;
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index 859f9b6..21b949c 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -523,14 +523,16 @@ typedef struct ext2_icount *ext2_icount_t;
EXT2_FEATURE_INCOMPAT_META_BG|\
EXT3_FEATURE_INCOMPAT_RECOVER|\
EXT3_FEATURE_INCOMPAT_EXTENTS|\
- EXT4_FEATURE_INCOMPAT_FLEX_BG)
+ EXT4_FEATURE_INCOMPAT_FLEX_BG|\
+ EXT4_FEATURE_INCOMPAT_64BIT)
#else
#define EXT2_LIB_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE|\
EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|\
EXT2_FEATURE_INCOMPAT_META_BG|\
EXT3_FEATURE_INCOMPAT_RECOVER|\
EXT3_FEATURE_INCOMPAT_EXTENTS|\
- EXT4_FEATURE_INCOMPAT_FLEX_BG)
+ EXT4_FEATURE_INCOMPAT_FLEX_BG|\
+ EXT4_FEATURE_INCOMPAT_64BIT)
#endif
#define EXT2_LIB_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|\
EXT4_FEATURE_RO_COMPAT_HUGE_FILE|\
diff --git a/lib/ext2fs/initialize.c b/lib/ext2fs/initialize.c
index e9bfe49..93b3328 100644
--- a/lib/ext2fs/initialize.c
+++ b/lib/ext2fs/initialize.c
@@ -75,8 +75,8 @@ static unsigned int calc_reserved_gdt_blocks(ext2_filsys fs)
/* We set it at 1024x the current filesystem size, or
* the upper block count limit (2^32), whichever is lower.
*/
- if (sb->s_blocks_count < max_blocks / 1024)
- max_blocks = sb->s_blocks_count * 1024;
+ if (ext2fs_blocks_count(sb) < max_blocks / 1024)
+ max_blocks = ext2fs_blocks_count(sb) * 1024;
rsv_groups = ext2fs_div_ceil(max_blocks - sb->s_first_data_block, bpg);
rsv_gdb = ext2fs_div_ceil(rsv_groups, gdpb) - fs->desc_blocks;
if (rsv_gdb > EXT2_ADDR_PER_BLOCK(sb))
@@ -108,7 +108,7 @@ errcode_t ext2fs_initialize(const char *name, int flags,
char *buf = 0;
char c;
- if (!param || !param->s_blocks_count)
+ if (!param || !ext2fs_blocks_count(param))
return EXT2_ET_INVALID_ARGUMENT;
retval = ext2fs_get_mem(sizeof(struct struct_ext2_filsys), &fs);
@@ -200,9 +200,9 @@ errcode_t ext2fs_initialize(const char *name, int flags,
super->s_blocks_per_group = EXT2_MAX_BLOCKS_PER_GROUP(super);
super->s_frags_per_group = super->s_blocks_per_group * frags_per_block;
- super->s_blocks_count = param->s_blocks_count;
- super->s_r_blocks_count = param->s_r_blocks_count;
- if (super->s_r_blocks_count >= param->s_blocks_count) {
+ ext2fs_blocks_count_set(super, ext2fs_blocks_count(param));
+ ext2fs_r_blocks_count_set(super, ext2fs_r_blocks_count(param));
+ if (ext2fs_r_blocks_count(super) >= ext2fs_blocks_count(param)) {
retval = EXT2_ET_INVALID_ARGUMENT;
goto cleanup;
}
@@ -219,18 +219,27 @@ errcode_t ext2fs_initialize(const char *name, int flags,
}
retry:
- fs->group_desc_count = ext2fs_div_ceil(super->s_blocks_count -
- super->s_first_data_block,
- EXT2_BLOCKS_PER_GROUP(super));
+ fs->group_desc_count = (blk_t) ext2fs_div64_ceil(
+ ext2fs_blocks_count(super) - super->s_first_data_block,
+ EXT2_BLOCKS_PER_GROUP(super));
if (fs->group_desc_count == 0) {
retval = EXT2_ET_TOOSMALL;
goto cleanup;
}
+
+ if (super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
+ super->s_desc_size = EXT2_MIN_DESC_SIZE_64BIT;
+
fs->desc_blocks = ext2fs_div_ceil(fs->group_desc_count,
EXT2_DESC_PER_BLOCK(super));
i = fs->blocksize >= 4096 ? 1 : 4096 / fs->blocksize;
- set_field(s_inodes_count, super->s_blocks_count / i);
+
+ if (super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT &&
+ (ext2fs_blocks_count(super) / i) > (1ULL << 32))
+ set_field(s_inodes_count, ~0U);
+ else
+ set_field(s_inodes_count, ext2fs_blocks_count(super) / i);
/*
* Make sure we have at least EXT2_FIRST_INO + 1 inodes, so
@@ -250,7 +259,8 @@ retry:
if (super->s_blocks_per_group >= 256) {
/* Try again with slightly different parameters */
super->s_blocks_per_group -= 8;
- super->s_blocks_count = param->s_blocks_count;
+ ext2fs_blocks_count_set(super,
+ ext2fs_blocks_count(param));
super->s_frags_per_group = super->s_blocks_per_group *
frags_per_block;
goto retry;
@@ -334,12 +344,14 @@ ipg_retry:
overhead = (int) (2 + fs->inode_blocks_per_group);
if (ext2fs_bg_has_super(fs, fs->group_desc_count - 1))
overhead += 1 + fs->desc_blocks + super->s_reserved_gdt_blocks;
- rem = ((super->s_blocks_count - super->s_first_data_block) %
+ rem = ((ext2fs_blocks_count(super) - super->s_first_data_block) %
super->s_blocks_per_group);
if ((fs->group_desc_count == 1) && rem && (rem < overhead))
return EXT2_ET_TOOSMALL;
if (rem && (rem < overhead+50)) {
- super->s_blocks_count -= rem;
+ ext2fs_blocks_count_set(super, ext2fs_blocks_count(super) +
+ rem);
+
goto retry;
}
@@ -383,7 +395,7 @@ ipg_retry:
* superblock and group descriptors (the inode tables and
* bitmaps will be accounted for when allocated).
*/
- super->s_free_blocks_count = 0;
+ ext2fs_free_blocks_count_set(super, 0);
csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
for (i = 0; i < fs->group_desc_count; i++) {
@@ -405,7 +417,9 @@ ipg_retry:
if (fs->super->s_log_groups_per_flex)
numblocks += 2 + fs->inode_blocks_per_group;
- super->s_free_blocks_count += numblocks;
+ ext2fs_free_blocks_count_set(super,
+ ext2fs_free_blocks_count(super) +
+ numblocks);
fs->group_desc[i].bg_free_blocks_count = numblocks;
fs->group_desc[i].bg_free_inodes_count =
fs->super->s_inodes_per_group;
diff --git a/misc/mke2fs.c b/misc/mke2fs.c
index 7171990..e8ba408 100644
--- a/misc/mke2fs.c
+++ b/misc/mke2fs.c
@@ -348,7 +348,7 @@ static void progress_close(struct progress_struct *progress)
static void write_inode_tables(ext2_filsys fs, int lazy_flag)
{
errcode_t retval;
- blk_t blk;
+ blk64_t blk;
dgrp_t i;
int num, ipb;
struct progress_struct progress;
@@ -362,7 +362,7 @@ static void write_inode_tables(ext2_filsys fs, int lazy_flag)
for (i = 0; i < fs->group_desc_count; i++) {
progress_update(&progress, i);
- blk = fs->group_desc[i].bg_inode_table;
+ blk = ext2fs_inode_table_loc(fs, i);
num = fs->inode_blocks_per_group;
if (lazy_flag) {
@@ -377,10 +377,10 @@ static void write_inode_tables(ext2_filsys fs, int lazy_flag)
fs->group_desc[i].bg_flags |= EXT2_BG_INODE_ZEROED;
ext2fs_group_desc_csum_set(fs, i);
}
- retval = ext2fs_zero_blocks(fs, blk, num, &blk, &num);
+ retval = ext2fs_zero_blocks2(fs, blk, num, &blk, &num);
if (retval) {
fprintf(stderr, _("\nCould not write %d "
- "blocks in inode table starting at %u: %s\n"),
+ "blocks in inode table starting at %ull: %s\n"),
num, blk, error_message(retval));
exit(1);
}
@@ -511,7 +511,7 @@ static void zap_sector(ext2_filsys fs, int sect, int nsect)
if (sect == 0) {
/* Check for a BSD disklabel, and don't erase it if so */
- retval = io_channel_read_blk(fs->io, 0, -512, buf);
+ retval = io_channel_read_blk64(fs->io, 0, -512, buf);
if (retval)
fprintf(stderr,
_("Warning: could not read block 0: %s\n"),
@@ -612,11 +612,11 @@ static void show_stats(ext2_filsys fs)
s->s_log_block_size);
printf(_("Fragment size=%u (log=%u)\n"), fs->fragsize,
s->s_log_frag_size);
- printf(_("%u inodes, %u blocks\n"), s->s_inodes_count,
- s->s_blocks_count);
- printf(_("%u blocks (%2.2f%%) reserved for the super user\n"),
- s->s_r_blocks_count,
- 100.0 * s->s_r_blocks_count / s->s_blocks_count);
+ printf(_("%u inodes, %llu blocks\n"), s->s_inodes_count,
+ ext2fs_blocks_count(s));
+ printf(_("%llu blocks (%2.2f%%) reserved for the super user\n"),
+ ext2fs_r_blocks_count(s),
+ 100.0 * ext2fs_r_blocks_count(s) / ext2fs_blocks_count(s));
printf(_("First data block=%u\n"), s->s_first_data_block);
if (s->s_reserved_gdt_blocks)
printf(_("Maximum filesystem blocks=%lu\n"),
@@ -838,7 +838,8 @@ static __u32 ok_features[3] = {
EXT3_FEATURE_INCOMPAT_EXTENTS|
EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|
EXT2_FEATURE_INCOMPAT_META_BG|
- EXT4_FEATURE_INCOMPAT_FLEX_BG,
+ EXT4_FEATURE_INCOMPAT_FLEX_BG|
+ EXT4_FEATURE_INCOMPAT_64BIT,
/* R/O compat */
EXT2_FEATURE_RO_COMPAT_LARGE_FILE|
EXT4_FEATURE_RO_COMPAT_HUGE_FILE|
@@ -1074,7 +1075,7 @@ static void PRS(int argc, char *argv[])
char * extended_opts = 0;
const char * fs_type = 0;
const char * usage_types = 0;
- blk_t dev_size;
+ blk64_t dev_size;
#ifdef __linux__
struct utsname ut;
#endif
@@ -1402,14 +1403,50 @@ static void PRS(int argc, char *argv[])
fs_param.s_log_frag_size = fs_param.s_log_block_size;
- if (noaction && fs_param.s_blocks_count) {
- dev_size = fs_param.s_blocks_count;
+ fs_types = parse_fs_type(fs_type, usage_types, &fs_param, argv[0]);
+ if (!fs_types) {
+ fprintf(stderr, _("Failed to parse fs types list\n"));
+ exit(1);
+ }
+
+ /* Figure out what features should be enabled */
+
+ tmp = NULL;
+ if (fs_param.s_rev_level != EXT2_GOOD_OLD_REV) {
+ tmp = get_string_from_profile(fs_types, "base_features",
+ "sparse_super,filetype,resize_inode,dir_index");
+ edit_feature(tmp, &fs_param.s_feature_compat);
+ free(tmp);
+
+ for (cpp = fs_types; *cpp; cpp++) {
+ tmp = NULL;
+ profile_get_string(profile, "fs_types", *cpp,
+ "features", "", &tmp);
+ if (tmp && *tmp)
+ edit_feature(tmp, &fs_param.s_feature_compat);
+ if (tmp)
+ free(tmp);
+ }
+ tmp = get_string_from_profile(fs_types, "default_features",
+ "");
+ }
+ edit_feature(fs_features ? fs_features : tmp,
+ &fs_param.s_feature_compat);
+ if (tmp)
+ free(tmp);
+
+ if (noaction && ext2fs_blocks_count(&fs_param)) {
+ dev_size = ext2fs_blocks_count(&fs_param);
retval = 0;
} else {
retry:
- retval = ext2fs_get_device_size(device_name,
- EXT2_BLOCK_SIZE(&fs_param),
- &dev_size);
+ retval = ext2fs_get_device_size2(device_name,
+ EXT2_BLOCK_SIZE(&fs_param),
+ &dev_size);
+ if (!(fs_param.s_feature_incompat &
+ EXT4_FEATURE_INCOMPAT_64BIT) && dev_size >= (1ULL << 32))
+ retval = EFBIG;
+
if ((retval == EFBIG) &&
(blocksize == 0) &&
(fs_param.s_log_block_size == 0)) {
@@ -1431,7 +1468,7 @@ static void PRS(int argc, char *argv[])
_("while trying to determine filesystem size"));
exit(1);
}
- if (!fs_param.s_blocks_count) {
+ if (!ext2fs_blocks_count(&fs_param)) {
if (retval == EXT2_ET_UNIMPLEMENTED) {
com_err(program_name, 0,
_("Couldn't determine device size; you "
@@ -1451,50 +1488,21 @@ static void PRS(int argc, char *argv[])
));
exit(1);
}
- fs_param.s_blocks_count = dev_size;
- if (sys_page_size > EXT2_BLOCK_SIZE(&fs_param))
- fs_param.s_blocks_count &= ~((sys_page_size /
- EXT2_BLOCK_SIZE(&fs_param))-1);
+ ext2fs_blocks_count_set(&fs_param, dev_size);
+ if (sys_page_size > EXT2_BLOCK_SIZE(&fs_param)) {
+ blk64_t tmp = ext2fs_blocks_count(&fs_param);
+ tmp &= ~((sys_page_size /
+ EXT2_BLOCK_SIZE(&fs_param))-1);
+ ext2fs_blocks_count_set(&fs_param, tmp);
+ }
}
- } else if (!force && (fs_param.s_blocks_count > dev_size)) {
+ } else if (!force && (ext2fs_blocks_count(&fs_param) > dev_size)) {
com_err(program_name, 0,
_("Filesystem larger than apparent device size."));
proceed_question();
}
- fs_types = parse_fs_type(fs_type, usage_types, &fs_param, argv[0]);
- if (!fs_types) {
- fprintf(stderr, _("Failed to parse fs types list\n"));
- exit(1);
- }
-
- /* Figure out what features should be enabled */
-
- tmp = NULL;
- if (fs_param.s_rev_level != EXT2_GOOD_OLD_REV) {
- tmp = get_string_from_profile(fs_types, "base_features",
- "sparse_super,filetype,resize_inode,dir_index");
- edit_feature(tmp, &fs_param.s_feature_compat);
- free(tmp);
-
- for (cpp = fs_types; *cpp; cpp++) {
- tmp = NULL;
- profile_get_string(profile, "fs_types", *cpp,
- "features", "", &tmp);
- if (tmp && *tmp)
- edit_feature(tmp, &fs_param.s_feature_compat);
- if (tmp)
- free(tmp);
- }
- tmp = get_string_from_profile(fs_types, "default_features",
- "");
- }
- edit_feature(fs_features ? fs_features : tmp,
- &fs_param.s_feature_compat);
- if (tmp)
- free(tmp);
-
if (fs_param.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
fs_types[0] = strdup("journal");
fs_types[1] = 0;
@@ -1583,7 +1591,9 @@ static void PRS(int argc, char *argv[])
if ((blocksize < 0) && (use_bsize < (-blocksize)))
use_bsize = -blocksize;
blocksize = use_bsize;
- fs_param.s_blocks_count /= blocksize / 1024;
+ ext2fs_blocks_count_set(&fs_param,
+ ext2fs_blocks_count(&fs_param) /
+ (blocksize / 1024));
}
if (inode_ratio == 0) {
@@ -1667,11 +1677,17 @@ static void PRS(int argc, char *argv[])
/* Make sure number of inodes specified will fit in 32 bits */
if (num_inodes == 0) {
unsigned long long n;
- n = (unsigned long long) fs_param.s_blocks_count * blocksize / inode_ratio;
+ n = ext2fs_blocks_count(&fs_param) * blocksize / inode_ratio;
if (n > ~0U) {
- com_err(program_name, 0,
- _("too many inodes (%llu), raise inode ratio?"), n);
- exit(1);
+ if (fs_param.s_feature_incompat &
+ EXT4_FEATURE_INCOMPAT_64BIT)
+ num_inodes = ~0U;
+ else {
+ com_err(program_name, 0,
+ _("too many inodes (%llu), raise"
+ "inode ratio?"), n);
+ exit(1);
+ }
}
} else if (num_inodes > ~0U) {
com_err(program_name, 0,
@@ -1683,29 +1699,28 @@ static void PRS(int argc, char *argv[])
* Calculate number of inodes based on the inode ratio
*/
fs_param.s_inodes_count = num_inodes ? num_inodes :
- ((__u64) fs_param.s_blocks_count * blocksize)
- / inode_ratio;
+ (ext2fs_blocks_count(&fs_param) * blocksize) / inode_ratio;
if ((((long long)fs_param.s_inodes_count) *
(inode_size ? inode_size : EXT2_GOOD_OLD_INODE_SIZE)) >=
- (((long long)fs_param.s_blocks_count) *
+ ((ext2fs_blocks_count(&fs_param)) *
EXT2_BLOCK_SIZE(&fs_param))) {
com_err(program_name, 0, _("inode_size (%u) * inodes_count "
"(%u) too big for a\n\t"
- "filesystem with %lu blocks, "
+ "filesystem with %llu blocks, "
"specify higher inode_ratio (-i)\n\t"
"or lower inode count (-N).\n"),
inode_size ? inode_size : EXT2_GOOD_OLD_INODE_SIZE,
fs_param.s_inodes_count,
- (unsigned long) fs_param.s_blocks_count);
+ (unsigned long long) ext2fs_blocks_count(&fs_param));
exit(1);
}
/*
* Calculate number of blocks to reserve
*/
- fs_param.s_r_blocks_count = (unsigned int) (reserved_ratio *
- fs_param.s_blocks_count / 100.0);
+ ext2fs_r_blocks_count_set(&fs_param, reserved_ratio *
+ ext2fs_blocks_count(&fs_param) / 100.0);
}
static int should_do_undo(const char *name)
"Jose R. Santos" <[email protected]> writes:
> Hi folks,
>
> I'm posting a new version of the 64-bit mke2fs patch since it was broken
> in many ways (many thanks to Goswin for having a look and pointing them
> out). This one can actually handle large fs as runs until its time to
> allocate table (where it barfs due bitmap issues). To make 64bit fs, I
> use the following command.
>
> mke2fs -T ext4dev -O64bit /dev/my_large_disk
Just like ext2/3 default to a 4k blocksize if it exceeds 2^32 1k
blocks shouldn't ext4 default to 64bit if it exceeds 2^32 4k blocks?
> Comments welcome
>
> -JRS
MfG
Goswin
On Fri, 18 Jul 2008 13:35:32 +0200
Goswin von Brederlow <[email protected]> wrote:
> "Jose R. Santos" <[email protected]> writes:
>
> > Hi folks,
> >
> > I'm posting a new version of the 64-bit mke2fs patch since it was broken
> > in many ways (many thanks to Goswin for having a look and pointing them
> > out). This one can actually handle large fs as runs until its time to
> > allocate table (where it barfs due bitmap issues). To make 64bit fs, I
> > use the following command.
> >
> > mke2fs -T ext4dev -O64bit /dev/my_large_disk
>
> Just like ext2/3 default to a 4k blocksize if it exceeds 2^32 1k
> blocks shouldn't ext4 default to 64bit if it exceeds 2^32 4k blocks?
Eventually, when the feature is stable enough, we can change the
default in mke2fs.conf to include this feature for the ext4 fs_type.
The problem of setting it only if the fs exceeds 2^32 blocks is that
you will not be able to resize an fs from 32 to 64bit due to the block
group descriptor size change. Once the feature is stable, it should
set as default regardless of the storage size.
> > Comments welcome
> >
> > -JRS
>
> MfG
> Goswin
-JRS
"Jose R. Santos" <[email protected]> writes:
> On Fri, 18 Jul 2008 13:35:32 +0200
> Goswin von Brederlow <[email protected]> wrote:
>
>> "Jose R. Santos" <[email protected]> writes:
>>
>> > Hi folks,
>> >
>> > I'm posting a new version of the 64-bit mke2fs patch since it was broken
>> > in many ways (many thanks to Goswin for having a look and pointing them
>> > out). This one can actually handle large fs as runs until its time to
>> > allocate table (where it barfs due bitmap issues). To make 64bit fs, I
>> > use the following command.
>> >
>> > mke2fs -T ext4dev -O64bit /dev/my_large_disk
>>
>> Just like ext2/3 default to a 4k blocksize if it exceeds 2^32 1k
>> blocks shouldn't ext4 default to 64bit if it exceeds 2^32 4k blocks?
>
> Eventually, when the feature is stable enough, we can change the
> default in mke2fs.conf to include this feature for the ext4 fs_type.
> The problem of setting it only if the fs exceeds 2^32 blocks is that
> you will not be able to resize an fs from 32 to 64bit due to the block
> group descriptor size change. Once the feature is stable, it should
> set as default regardless of the storage size.
Won't tune2fs be able to adjust the descriptor size? I thought all the
keeping compatibility with ext2/3 was so people could upgrade without
reformating. Or is that maxime broken with 64bit support?
MfG
Goswin
On Jul 18, 2008 21:59 +0200, Goswin von Brederlow wrote:
> Won't tune2fs be able to adjust the descriptor size? I thought all the
> keeping compatibility with ext2/3 was so people could upgrade without
> reformating. Or is that maxime broken with 64bit support?
There is definitely compatibility between ext3 and ext4 - you can mount
and use any ext3 filesystem under ext4. That doesn't mean that ext3
filesystems will have all of the features in ext4 available to them.
Some features like 65000-subdir limit, mballoc, extents will work on
all ext3 filesystems. Other features like nanosecond timestamps and
fast extended attributes will work on newer ext3 filesystems because
mke2fs was changed to default to 256-byte inodes.
Being able to transparently support 64-bit filesystems was initially
attempted, but proved to be problematic, and the likelihood of
users resizing from < 16TB to > 16TB was decided to be rare enough
that having to do an offline operation to resize the group descriptor
blocks was considered acceptable.
Cheers, Andreas
--
Andreas Dilger
Sr. Staff Engineer, Lustre Group
Sun Microsystems of Canada, Inc.