[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <1185275096.3789.71.camel@dhcp4.linsyssoft.com>
Date: Tue, 24 Jul 2007 16:34:56 +0530
From: Girish Shilamkar <girish@...sterfs.com>
To: Ext4 Mailing List <linux-ext4@...r.kernel.org>
Cc: Andreas Dilger <adilger@...sterfs.com>,
Theodore Tso <tytso@....edu>
Subject: [Patch 6/13] Allow more than 32000 subdirectories
This patch includes the changes required to e2fsck to understand the
nlink count changes made in the kernel. In pass2, while counting the
links for a directory, if the link count exceeds 65000, its permanently
set to EXT2_NLINK_MAXED (EXT2_LINK_MAX + 100). In pass4, when the
counted and actual nlink counts are compared, e2fsck does not flag
an error if counted links = EXT2_NLINK_MAXED and existing link count is 1.
It also handles the case when a directory had more than 65000 subdirs
and they were later deleted. The nlink count of such a directory remains
1. In pass4 if counted links are 2 and if existing nlink count = 1,
e2fsck corrects the nlink count without displaying any errors.
Signed-off-by: Andreas Dilger <adilger@...sterfs.com>
Signed-off-by: Kalpak Shah <kalpak@...sterfs.com>
Index: e2fsprogs-1.40.1/e2fsck/pass2.c
===================================================================
--- e2fsprogs-1.40.1.orig/e2fsck/pass2.c
+++ e2fsprogs-1.40.1/e2fsck/pass2.c
@@ -717,7 +717,7 @@ static int check_dir_block(ext2_filsys f
blk_t block_nr = db->blk;
ext2_ino_t ino = db->ino;
ext2_ino_t subdir_parent;
- __u16 links;
+ __u32 links;
struct check_dir_struct *cd;
char *buf;
e2fsck_t ctx;
@@ -1024,9 +1024,11 @@ static int check_dir_block(ext2_filsys f
dups_found++;
} else
dict_alloc_insert(&de_dict, dirent, dirent);
-
- ext2fs_icount_increment(ctx->inode_count, dirent->inode,
- &links);
+
+ ext2fs_icount_inc32(ctx->inode_count, dirent->inode, &links,
+ ext2fs_test_inode_bitmap(ctx->inode_dir_map,
+ dirent->inode) ?
+ EXT2_LINK_MAX : (__u32)~0U);
if (links > 1)
ctx->fs_links_count++;
ctx->fs_total_count++;
Index: e2fsprogs-1.40.1/e2fsck/pass4.c
===================================================================
--- e2fsprogs-1.40.1.orig/e2fsck/pass4.c
+++ e2fsprogs-1.40.1/e2fsck/pass4.c
@@ -99,7 +99,8 @@ void e2fsck_pass4(e2fsck_t ctx)
struct resource_track rtrack;
#endif
struct problem_context pctx;
- __u16 link_count, link_counted;
+ __u16 link_count;
+ __u32 link_counted;
char *buf = 0;
int group, maxgroup;
@@ -145,7 +146,7 @@ void e2fsck_pass4(e2fsck_t ctx)
ext2fs_test_inode_bitmap(ctx->inode_bb_map, i)))
continue;
ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
- ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
+ ext2fs_icount_fetch32(ctx->inode_count, i, &link_counted);
if (link_counted == 0) {
if (!buf)
buf = e2fsck_allocate_memory(ctx,
@@ -156,10 +157,12 @@ void e2fsck_pass4(e2fsck_t ctx)
continue;
ext2fs_icount_fetch(ctx->inode_link_info, i,
&link_count);
- ext2fs_icount_fetch(ctx->inode_count, i,
- &link_counted);
+ ext2fs_icount_fetch32(ctx->inode_count, i,
+ &link_counted);
}
- if (link_counted != link_count) {
+ if (link_counted != link_count &&
+ !(ext2fs_test_inode_bitmap(ctx->inode_dir_map, i) &&
+ link_count == 1 && link_counted > EXT2_LINK_MAX)) {
e2fsck_read_inode(ctx, i, inode, "pass4");
pctx.ino = i;
pctx.inode = inode;
@@ -169,7 +172,12 @@ void e2fsck_pass4(e2fsck_t ctx)
PR_4_INCONSISTENT_COUNT, &pctx);
}
pctx.num = link_counted;
- if (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
+ /* i_link_count was previously exceeded, but no longer
+ * is, fix this but don't consider it an error */
+ if ((LINUX_S_ISDIR(inode->i_mode) && link_counted > 1 &&
+ (inode->i_flags & EXT2_INDEX_FL) &&
+ link_count == 1 && !(ctx->options & E2F_OPT_NO)) ||
+ (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx))) {
inode->i_links_count = link_counted;
e2fsck_write_inode(ctx, i, inode, "pass4");
}
Index: e2fsprogs-1.40.1/lib/ext2fs/ext2_fs.h
===================================================================
--- e2fsprogs-1.40.1.orig/lib/ext2fs/ext2_fs.h
+++ e2fsprogs-1.40.1/lib/ext2fs/ext2_fs.h
@@ -646,6 +646,7 @@ struct ext2_super_block {
#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| \
+ EXT4_FEATURE_RO_COMPAT_DIR_NLINK| \
EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
/*
Index: e2fsprogs-1.40.1/lib/ext2fs/ext2fs.h
===================================================================
--- e2fsprogs-1.40.1.orig/lib/ext2fs/ext2fs.h
+++ e2fsprogs-1.40.1/lib/ext2fs/ext2fs.h
@@ -462,7 +462,8 @@ typedef struct ext2_icount *ext2_icount_
EXT3_FEATURE_INCOMPAT_RECOVER)
#endif
#define EXT2_LIB_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|\
- EXT2_FEATURE_RO_COMPAT_LARGE_FILE)
+ EXT2_FEATURE_RO_COMPAT_LARGE_FILE|\
+ EXT4_FEATURE_RO_COMPAT_DIR_NLINK)
/*
* These features are only allowed if EXT2_FLAG_SOFTSUPP_FEATURES is passed
@@ -471,7 +472,6 @@ typedef struct ext2_icount *ext2_icount_
#define EXT2_LIB_SOFTSUPP_INCOMPAT (EXT3_FEATURE_INCOMPAT_EXTENTS)
#define EXT2_LIB_SOFTSUPP_RO_COMPAT (EXT4_FEATURE_RO_COMPAT_HUGE_FILE|\
EXT4_FEATURE_RO_COMPAT_GDT_CSUM|\
- EXT4_FEATURE_RO_COMPAT_DIR_NLINK|\
EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE)
/*
@@ -795,12 +795,20 @@ extern errcode_t ext2fs_create_icount2(e
extern errcode_t ext2fs_create_icount(ext2_filsys fs, int flags,
unsigned int size,
ext2_icount_t *ret);
+extern errcode_t ext2fs_icount_fetch32(ext2_icount_t icount, ext2_ino_t ino,
+ __u32 *ret);
extern errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ext2_ino_t ino,
__u16 *ret);
+extern errcode_t ext2fs_icount_inc32(ext2_icount_t icount, ext2_ino_t ino,
+ __u32 *ret, __u32 overflow);
extern errcode_t ext2fs_icount_increment(ext2_icount_t icount, ext2_ino_t ino,
__u16 *ret);
+extern errcode_t ext2fs_icount_dec32(ext2_icount_t icount, ext2_ino_t ino,
+ __u32 *ret);
extern errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ext2_ino_t ino,
__u16 *ret);
+extern errcode_t ext2fs_icount_store32(ext2_icount_t icount, ext2_ino_t ino,
+ __u32 count);
extern errcode_t ext2fs_icount_store(ext2_icount_t icount, ext2_ino_t ino,
__u16 count);
extern ext2_ino_t ext2fs_get_icount_size(ext2_icount_t icount);
Index: e2fsprogs-1.40.1/lib/ext2fs/icount.c
===================================================================
--- e2fsprogs-1.40.1.orig/lib/ext2fs/icount.c
+++ e2fsprogs-1.40.1/lib/ext2fs/icount.c
@@ -43,7 +43,7 @@
struct ext2_icount_el {
ext2_ino_t ino;
- __u16 count;
+ __u32 count;
};
struct ext2_icount {
@@ -397,16 +397,16 @@ static struct ext2_icount_el *get_icount
}
static errcode_t set_inode_count(ext2_icount_t icount, ext2_ino_t ino,
- __u16 count)
+ __u32 count)
{
- struct ext2_icount_el *el;
+ struct ext2_icount_el *el;
TDB_DATA key, data;
if (icount->tdb) {
key.dptr = (unsigned char *) &ino;
key.dsize = sizeof(ext2_ino_t);
data.dptr = (unsigned char *) &count;
- data.dsize = sizeof(__u16);
+ data.dsize = sizeof(__u32);
if (count) {
if (tdb_store(icount->tdb, key, data, TDB_REPLACE))
return tdb_error(icount->tdb) +
@@ -428,9 +428,9 @@ static errcode_t set_inode_count(ext2_ic
}
static errcode_t get_inode_count(ext2_icount_t icount, ext2_ino_t ino,
- __u16 *count)
+ __u32 *count)
{
- struct ext2_icount_el *el;
+ struct ext2_icount_el *el;
TDB_DATA key, data;
if (icount->tdb) {
@@ -443,7 +443,7 @@ static errcode_t get_inode_count(ext2_ic
return tdb_error(icount->tdb) + EXT2_ET_TDB_SUCCESS;
}
- *count = *((__u16 *) data.dptr);
+ *count = *((__u32 *) data.dptr);
free(data.dptr);
return 0;
}
@@ -480,7 +480,7 @@ errcode_t ext2fs_icount_validate(ext2_ic
return ret;
}
-errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ext2_ino_t ino, __u16 *ret)
+errcode_t ext2fs_icount_fetch32(ext2_icount_t icount, ext2_ino_t ino, __u32 *ret)
{
EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
@@ -500,10 +500,21 @@ errcode_t ext2fs_icount_fetch(ext2_icoun
return 0;
}
-errcode_t ext2fs_icount_increment(ext2_icount_t icount, ext2_ino_t ino,
- __u16 *ret)
+errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ext2_ino_t ino, __u16 *ret)
{
- __u16 curr_value;
+ __u32 ret32 = ret ? *ret : 0;
+ errcode_t err;
+
+ err = ext2fs_icount_fetch32(icount, ino, &ret32);
+ *ret = (__u16)ret32;
+
+ return err;
+}
+
+errcode_t ext2fs_icount_inc32(ext2_icount_t icount, ext2_ino_t ino,
+ __u32 *ret, __u32 overflow)
+{
+ __u32 curr_value;
EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
@@ -528,6 +539,8 @@ errcode_t ext2fs_icount_increment(ext2_i
if (ext2fs_test_inode_bitmap(icount->multiple, ino)) {
get_inode_count(icount, ino, &curr_value);
curr_value++;
+ if (curr_value >= overflow)
+ curr_value = overflow + 10;
if (set_inode_count(icount, ino, curr_value))
return EXT2_ET_NO_MEMORY;
} else {
@@ -547,6 +560,8 @@ errcode_t ext2fs_icount_increment(ext2_i
*/
get_inode_count(icount, ino, &curr_value);
curr_value++;
+ if (curr_value >= overflow)
+ curr_value = overflow + 10;
if (set_inode_count(icount, ino, curr_value))
return EXT2_ET_NO_MEMORY;
}
@@ -557,10 +572,23 @@ errcode_t ext2fs_icount_increment(ext2_i
return 0;
}
-errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ext2_ino_t ino,
+errcode_t ext2fs_icount_increment(ext2_icount_t icount, ext2_ino_t ino,
__u16 *ret)
{
- __u16 curr_value;
+ __u32 ret32 = ret ? *ret : 0;
+ errcode_t err;
+
+ err = ext2fs_icount_inc32(icount, ino, &ret32, (__u16)~0U);
+ if (ret)
+ *ret = ret32;
+
+ return err;
+}
+
+errcode_t ext2fs_icount_dec32(ext2_icount_t icount, ext2_ino_t ino,
+ __u32 *ret)
+{
+ __u32 curr_value;
if (!ino || (ino > icount->num_inodes))
return EXT2_ET_INVALID_ARGUMENT;
@@ -600,8 +628,21 @@ errcode_t ext2fs_icount_decrement(ext2_i
return 0;
}
-errcode_t ext2fs_icount_store(ext2_icount_t icount, ext2_ino_t ino,
- __u16 count)
+errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ext2_ino_t ino,
+ __u16 *ret)
+{
+ __u32 ret32 = ret ? *ret : 0;
+ errcode_t err;
+
+ err = ext2fs_icount_dec32(icount, ino, &ret32);
+ if (ret)
+ *ret = ret32;
+
+ return err;
+}
+
+errcode_t ext2fs_icount_store32(ext2_icount_t icount, ext2_ino_t ino,
+ __u32 count)
{
if (!ino || (ino > icount->num_inodes))
return EXT2_ET_INVALID_ARGUMENT;
@@ -635,6 +676,12 @@ errcode_t ext2fs_icount_store(ext2_icoun
return 0;
}
+errcode_t ext2fs_icount_store(ext2_icount_t icount, ext2_ino_t ino,
+ __u16 count)
+{
+ return ext2fs_icount_store32(icount, ino, count);
+}
+
ext2_ino_t ext2fs_get_icount_size(ext2_icount_t icount)
{
if (!icount || icount->magic != EXT2_ET_MAGIC_ICOUNT)
Index: e2fsprogs-1.40.1/e2fsck/pass3.c
===================================================================
--- e2fsprogs-1.40.1.orig/e2fsck/pass3.c
+++ e2fsprogs-1.40.1/e2fsck/pass3.c
@@ -581,19 +581,22 @@ errcode_t e2fsck_adjust_inode_count(e2fs
#endif
if (adj == 1) {
- ext2fs_icount_increment(ctx->inode_count, ino, 0);
+ ext2fs_icount_inc32(ctx->inode_count, ino, 0,
+ ext2fs_test_inode_bitmap(ctx->inode_dir_map,
+ ino) ?
+ EXT2_LINK_MAX : ~0U);
if (inode.i_links_count == (__u16) ~0)
return 0;
ext2fs_icount_increment(ctx->inode_link_info, ino, 0);
inode.i_links_count++;
} else if (adj == -1) {
- ext2fs_icount_decrement(ctx->inode_count, ino, 0);
+ ext2fs_icount_dec32(ctx->inode_count, ino, 0);
if (inode.i_links_count == 0)
return 0;
ext2fs_icount_decrement(ctx->inode_link_info, ino, 0);
inode.i_links_count--;
}
-
+
retval = ext2fs_write_inode(fs, ino, &inode);
if (retval)
return retval;
-
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists