2006-05-25 12:59:13

by Takashi Sato

[permalink] [raw]
Subject: [UPDATE][22/24]ext2resize enlarge file size and filesystem size

Summary of this patch:
[22/24] enlarge max file size and max filesystem size
- With "-O huge_fs" option in mke2fs, the maximum size of
a file is (blocksize) * (2^32-1) bytes, and of a filesystem
is (pagesize) * (2^32-1).

Signed-off-by: Takashi Sato [email protected]
---
diff -upNr ext2resize-1.1.19/src/ext2.c ext2resize-1.1.19.tmp/src/ext2.c
--- ext2resize-1.1.19/src/ext2.c 2006-05-16 10:03:55.000000000 +0900
+++ ext2resize-1.1.19.tmp/src/ext2.c 2006-05-16 11:23:23.000000000 +0900
@@ -295,7 +295,6 @@ int ext2_block_iterate(struct ext2_fs *f
blk_t curblock;
int count = 0;
int i;
- int i512perblock = 1 << (fs->logsize - 9);
unsigned long long apb;

apb = fs->u32perblock;
@@ -341,7 +340,7 @@ int ext2_block_iterate(struct ext2_fs *f
inode->i_block[EXT2_DIND_BLOCK] = dindblk;
bh = ext2_bread(fs, inode->i_block[EXT2_DIND_BLOCK]);
memset(bh->data, 0, fs->blocksize);
- inode->i_blocks += i512perblock;
+ inode->i_blocks += 1 << i_blocks_shift(fs, inode);
}
else
bh = ext2_bread(fs, inode->i_block[EXT2_DIND_BLOCK]);
@@ -363,7 +362,7 @@ int ext2_block_iterate(struct ext2_fs *f
ext2_zero_blocks(fs, block, 1);
ext2_set_block_state(fs, block, 1, 1);
bh->dirty = 1;
- inode->i_blocks += i512perblock;
+ inode->i_blocks += 1 << i_blocks_shift(fs, inode);
inode->i_mtime = time(NULL);
ext2_brelse(bh, 0);
return 1;
@@ -379,7 +378,7 @@ int ext2_block_iterate(struct ext2_fs *f

bh2 = ext2_bread(fs, udata[i]);
udata2 = (__u32 *)bh2->data;
- count += i512perblock;
+ count += 1 << i_blocks_shift(fs, inode);

for (j = 0; j < fs->u32perblock; j++, curblock++) {
if (action == EXT2_ACTION_ADD && !udata2[j]) {
@@ -390,7 +389,7 @@ int ext2_block_iterate(struct ext2_fs *f
curblock, udata[i]);
bh2->dirty = 1;
udata2[j] = block;
- inode->i_blocks += i512perblock;
+ inode->i_blocks += 1 << i_blocks_shift(fs, inode);
if (new_size > inode->i_size)
inode->i_size = new_size;
inode->i_mtime = time(NULL);
@@ -407,7 +406,7 @@ int ext2_block_iterate(struct ext2_fs *f
curblock, udata[i]);
bh2->dirty = 1;
udata2[j] = 0;
- inode->i_blocks -= i512perblock;
+ inode->i_blocks -= 1 << i_blocks_shift(fs, inode);
inode->i_mtime = time(NULL);
if (!(fs->flags & FL_ONLINE))
ext2_set_block_state(fs, block,
@@ -418,7 +417,7 @@ int ext2_block_iterate(struct ext2_fs *f
return curblock;
}
if (udata2[j]) {
- count += i512perblock;
+ count += 1 << i_blocks_shift(fs, inode);
if (count >= inode->i_blocks &&
action != EXT2_ACTION_ADD)
return -1;
@@ -787,7 +786,7 @@ static blk_t ext2_get_reserved(struct ex

for (i = 0; i < fs->numgroups; i++)
sb_groups += ext2_bg_has_super(fs, i);
- resgdblocks = ((inode->i_blocks >> (fs->logsize - 9)) -
+ resgdblocks = ((inode->i_blocks >> i_blocks_shift(fs, inode)) -
(inode->i_block[EXT2_IND_BLOCK] ? 1 : 0) -
(inode->i_block[EXT2_DIND_BLOCK] ? 1 : 0)) /
sb_groups;
@@ -819,16 +818,18 @@ static blk_t ext2_get_reserved(struct ex
EXT2_FEATURE_COMPAT_EXT_ATTR | \
EXT2_FEATURE_COMPAT_RESIZE_INODE)
#define EXT2_OPEN_RO_COMPAT_UNSUPP ~(EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER | \
- EXT2_FEATURE_RO_COMPAT_LARGE_FILE)
-#define EXT2_OPEN_INCOMPAT_UNSUPP ~EXT2_FEATURE_INCOMPAT_FILETYPE
+ EXT2_FEATURE_RO_COMPAT_LARGE_FILE | \
+ EXT2_FEATURE_RO_COMPAT_HUGE_FILE)
+#define EXT2_OPEN_INCOMPAT_UNSUPP ~(EXT2_FEATURE_INCOMPAT_FILETYPE | \
+ EXT2_FEATURE_INCOMPAT_HUGE_FS)

-struct ext2_fs *ext2_open(struct ext2_dev_handle *handle, blk_t newblocks,
+struct ext2_fs *ext2_open(struct ext2_dev_handle *handle, blk64_t newblocks,
int flags)
{
struct ext2_fs *fs;
struct ext2_inode inode;
int maxgroups;
- blk_t devsize;
+ blk64_t devsize;
blk_t residue;

if (flags & FL_DEBUG)
@@ -909,6 +910,12 @@ struct ext2_fs *ext2_open(struct ext2_de
newblocks = devsize;
else if (fs->flags & FL_KB_BLOCKS)
newblocks >>= fs->logsize - 10;
+ if (newblocks > ~0U) {
+ /* actually we can't process fs over 4G-1 amount of blocks */
+ fprintf(stderr, "%s: can't resize filesystem over %uTB\n",
+ fs->prog, fs->blocksize >> (40 - 32));
+ goto error_free_bcache;
+ }

if (fs->flags & FL_VERBOSE)
printf("new filesystem size %d\n", newblocks);
@@ -926,13 +933,13 @@ struct ext2_fs *ext2_open(struct ext2_de
if (devsize < newblocks && !(fs->flags & FL_PREPARE)) {
char *junk[fs->blocksize];

- fprintf(stderr, "%s: warning - device size %u, specified %u\n",
+ fprintf(stderr, "%s: warning - device size %llu, specified %llu\n",
fs->prog, devsize, newblocks);

ext2_read_blocks(fs, junk, newblocks - 1, 1);
} else if (fs->sb.s_blocks_count > devsize) {
char *junk[fs->blocksize];
- fprintf(stderr, "%s: warning - device size %u, filesystem %u\n",
+ fprintf(stderr, "%s: warning - device size %llu, filesystem %u\n",
fs->prog, devsize, fs->sb.s_blocks_count);

ext2_read_blocks(fs, junk, fs->sb.s_blocks_count - 1, 1);
@@ -1014,7 +1021,7 @@ void ext2_fix_resize_inode(struct ext2_f

if (inode->i_block[EXT2_DIND_BLOCK]) {
ext2_zero_blocks(fs, inode->i_block[EXT2_DIND_BLOCK], 1);
- inode->i_blocks = 1 << (fs->logsize - 9);
+ inode->i_blocks = 1 << i_blocks_shift(fs, inode);
}

for (i = 0, block = fs->sb.s_first_data_block + fs->newgdblocks + 1;
diff -upNr ext2resize-1.1.19/src/ext2.h ext2resize-1.1.19.tmp/src/ext2.h
--- ext2resize-1.1.19/src/ext2.h 2006-05-16 10:03:58.000000000 +0900
+++ ext2resize-1.1.19.tmp/src/ext2.h 2006-05-16 11:21:26.000000000 +0900
@@ -51,6 +51,7 @@ static const char _ext2_h[] = "$Id: ext2
#define cpu_to_le32(a) (a)
#endif
typedef u_int32_t blk_t;
+typedef unsigned long long blk64_t; /* don't use autoheader for now */

#include "ext2_fs.h"

@@ -85,7 +86,7 @@ struct ext2_buffer_head
struct ext2_dev_ops
{
void (*close)(void *cookie);
- blk_t (*get_size)(void *cookie);
+ blk64_t (*get_size)(void *cookie);
void (*read)(void *cookie, void *ptr, blk_t block, blk_t num);
void (*set_blocksize)(void *cookie, int logsize);
void (*sync)(void *cookie);
@@ -176,7 +177,7 @@ int ext2_bg_has_super(struct ext2_fs *fs
unsigned int ext2_list_backups(struct ext2_fs *fs, unsigned int *three,
unsigned int *five, unsigned int *seven);
void ext2_move_blocks(struct ext2_fs *fs, blk_t src, blk_t num, blk_t dest);
-struct ext2_fs *ext2_open(struct ext2_dev_handle *handle, blk_t newblocks,
+struct ext2_fs *ext2_open(struct ext2_dev_handle *handle, blk64_t newblocks,
int kb_blocks);
void ext2_read_blocks(struct ext2_fs *fs, void *ptr, blk_t block,
blk_t numblocks);
@@ -248,6 +249,14 @@ void ext2_fix_resize_inode(struct ext2_f
#define clear_bit(buf, offset) buf[(offset)>>3] &= ~_bitmap[(offset)&7]
#define check_bit(buf, offset) (buf[(offset)>>3] & _bitmap[(offset)&7])

+/* convert unit */
+static int __inline__ i_blocks_shift(struct ext2_fs *fs, struct ext2_inode *inode)
+{
+ if (inode->i_flags & EXT2_HUGE_FILE_FL)
+ return 0;
+ return (fs->logsize - 9);
+}
+
#ifdef USE_EXT2_IS_DATA_BLOCK
static int __inline__ ext2_is_data_block(struct ext2_fs *fs, blk_t block)
{
diff -upNr ext2resize-1.1.19/src/ext2_fs.h ext2resize-1.1.19.tmp/src/ext2_fs.h
--- ext2resize-1.1.19/src/ext2_fs.h 2006-05-16 10:03:46.000000000 +0900
+++ ext2resize-1.1.19.tmp/src/ext2_fs.h 2006-05-16 10:04:42.000000000 +0900
@@ -223,6 +223,7 @@ struct ext2_dx_countlimit {
#define EXT2_IMAGIC_FL 0x00002000
#define EXT3_JOURNAL_DATA_FL 0x00004000 /* file data should be journaled */
#define EXT2_NOTAIL_FL 0x00008000 /* file tail should not be merged */
+#define EXT2_HUGE_FILE_FL 0x00040000 /* Set to each huge file */
#define EXT2_RESERVED_FL 0x80000000 /* reserved for ext2 lib */

#define EXT2_FL_USER_VISIBLE 0x0000DFFF /* User visible flags */
@@ -504,17 +505,21 @@ struct ext2_super_block {
#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002
#define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004
+#define EXT2_FEATURE_RO_COMPAT_HUGE_FILE 0x0008

#define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001
#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002
#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */
#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */
+/* EXT3_FEATURE_INCOMPAT_EXTENTS 0x0040 */
+#define EXT2_FEATURE_INCOMPAT_HUGE_FS 0x0080

#define EXT2_FEATURE_COMPAT_SUPP 0
#define EXT2_FEATURE_INCOMPAT_SUPP EXT2_FEATURE_INCOMPAT_FILETYPE
#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
- EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
+ EXT2_FEATURE_RO_COMPAT_BTREE_DIR| \
+ EXT2_FEATURE_RO_COMPAT_HUGE_FILE)

/*
* Default values for user and/or group using reserved blocks
diff -upNr ext2resize-1.1.19/src/ext2_unix_io.c ext2resize-1.1.19.tmp/src/ext2_unix_io.c
--- ext2resize-1.1.19/src/ext2_unix_io.c 2006-05-16 10:03:46.000000000 +0900
+++ ext2resize-1.1.19.tmp/src/ext2_unix_io.c 2006-05-16 10:04:42.000000000 +0900
@@ -96,7 +96,7 @@ static int valid_offset(int fd, __loff_t
return 1;
}

-static blk_t do_get_size(void *cookie)
+static blk64_t do_get_size(void *cookie)
{
struct my_cookie *monster = cookie;
blk_t size;
@@ -138,7 +138,7 @@ static blk_t do_get_size(void *cookie)
/* Reset filesystem position? */
ext2_llseek(monster->fdread, monster->readoff, SEEK_SET);

- size = high >> 9;
+ return high >> monster->logsize;
}

return size >> (monster->logsize - 9);
diff -upNr ext2resize-1.1.19/src/ext2online.c ext2resize-1.1.19.tmp/src/ext2online.c
--- ext2resize-1.1.19/src/ext2online.c 2006-05-16 10:03:55.000000000 +0900
+++ ext2resize-1.1.19.tmp/src/ext2online.c 2006-05-16 10:04:42.000000000 +0900
@@ -573,7 +573,8 @@ int main(int argc, char *argv[])
char *progname;
struct ext2_dev_handle *handle;
struct ext2_fs *fs;
- blk_t resize = 0, realsize = 0;
+ blk64_t resize = 0;
+ blk_t realsize = 0;
char mod = '\0';
int flags = FL_SAFE;

@@ -603,7 +604,7 @@ int main(int argc, char *argv[])

/* See if the user has specified a filesystem size */
if (argc == 2) {
- sscanf(argv[1], "%i%c", &resize, &mod);
+ sscanf(argv[1], "%lli%c", &resize, &mod);

switch (mod) { /* Order of these options is important!! */
case 't':
diff -upNr ext2resize-1.1.19/src/ext2prepare.c ext2resize-1.1.19.tmp/src/ext2prepare.c
--- ext2resize-1.1.19/src/ext2prepare.c 2006-05-16 10:03:55.000000000 +0900
+++ ext2resize-1.1.19.tmp/src/ext2prepare.c 2006-05-16 10:04:42.000000000 +0900
@@ -228,7 +228,7 @@ int main(int argc, char *argv[])
char *dev;
char *progname;
blk_t maxres;
- blk_t resize = 0;
+ blk64_t resize = 0;
char mod = '\0';
int flags = FL_SAFE;

@@ -248,7 +248,7 @@ int main(int argc, char *argv[])
if (handle == NULL)
return 1;

- sscanf(argv[1], "%i%c", &resize, &mod);
+ sscanf(argv[1], "%lli%c", &resize, &mod);

switch (mod) { /* Order of these options is important!! */
case 't':
@@ -282,11 +282,13 @@ int main(int argc, char *argv[])
"%s: won't prepare 1k block filesystem over 128GB.\n"
"\tToo much space would be wasted.\n", progname);
return 1;
- } else if ((fs->blocksize == 4096 && fs->newblocks > 1<<30) ||
- fs->newblocks > 1<<31) {
- fprintf(stderr,
- "%s: can't resize filesystem over 2TB.\n", progname);
- return 1;
+ } else if (!EXT2_HAS_INCOMPAT_FEATURE(&fs->sb, EXT2_FEATURE_INCOMPAT_HUGE_FS)) {
+ if ((fs->blocksize == 4096 && fs->newblocks > 1<<29) ||
+ fs->newblocks > 1<<31) {
+ fprintf(stderr,
+ "%s: can't resize filesystem over 2TB.\n", progname);
+ return 1;
+ }
}

maxres = (1 + fs->u32perblock) * fs->u32perblock + EXT2_NDIR_BLOCKS;
diff -upNr ext2resize-1.1.19/src/ext2resize.c ext2resize-1.1.19.tmp/src/ext2resize.c
--- ext2resize-1.1.19/src/ext2resize.c 2006-05-16 10:03:46.000000000 +0900
+++ ext2resize-1.1.19.tmp/src/ext2resize.c 2006-05-16 10:04:42.000000000 +0900
@@ -30,7 +30,7 @@ static const char _ext2resize_c[] = "$Id
void usage(FILE *outfile, char *progname)
{
fprintf(outfile,
- "usage: %s [-dfquvV] device [new_size[bkmgt]]\n\t"
+ "usage: %s [-dfquvV] device [new_size[bkmgt]]\n"
"\t-d, --debug : turn debug info on\n"
"\t-f, --force : skip safety checks\n"
"\t-q, --quiet : be quiet (print only errors)\n"
@@ -81,7 +81,7 @@ int main(int argc, char *argv[])
char *dev;
char *progname;
char mod = '\0';
- blk_t resize = 0;
+ blk64_t resize = 0;
int flags = FL_SAFE;

progname = strrchr(argv[0], '/') ? strrchr(argv[0], '/') + 1 : argv[0];
@@ -102,7 +102,7 @@ int main(int argc, char *argv[])
return 1;

if (argc == 2) {
- sscanf(argv[1], "%i%c", &resize, &mod);
+ sscanf(argv[1], "%lli%c", &resize, &mod);

switch (mod) { /* Order of these options is important!! */
case 't':