* [PATCH 1/2 e2fsprogs] support for large EAs
@ 2008-11-17 20:36 Kalpak Shah
0 siblings, 0 replies; only message in thread
From: Kalpak Shah @ 2008-11-17 20:36 UTC (permalink / raw)
To: linux-ext4; +Cc: TheodoreTso, Andreas Dilger
[-- Attachment #1: Type: text/plain, Size: 1234 bytes --]
Hi,
This patch adds large EA support for e2fsprogs.
- add EXT4_FEATURE_INCOMPAT_EA_INODE feature
- inode_ea_map bitmap is added for tracking non-orphan EA inodes. Orphan EA inodes get linked to lost+found.
- xattr handling is needed for deleting corrupt EA entries
Ted, this patch is actually based on top of the e2fsprogs-expand-extra-isize.patch I had sent about a month back. If you are satisfied with the approach, I can send a patch series which applies to the tip of the e2fsprogs tree.
Signed-off-by: Andreas Dilger <adilger@sun.com>
Signed-off-by: Kalpak Shah <kalpak.shah@sun.com>
e2fsck/e2fsck.h | 1
e2fsck/pass1.c | 199 ++++++++++++++++++++++++++++++++++++---------
e2fsck/pass4.c | 17 +++
e2fsck/problem.c | 24 +++++
e2fsck/problem.h | 13 ++
lib/blkid/probe.h | 1
lib/e2p/feature.c | 2
lib/ext2fs/ext2_ext_attr.h | 5 -
lib/ext2fs/ext2_fs.h | 5 -
lib/ext2fs/ext2fs.h | 6 -
lib/ext2fs/ext_attr.c | 27 ++++--
lib/ext2fs/swapfs.c | 2
misc/mke2fs.c | 3
misc/tune2fs.c | 6 +
14 files changed, 259 insertions(+), 52 deletions(-)
Thanks,
Kalpak
[-- Attachment #2: e2fsprogs-large-xattrs.patch --]
[-- Type: text/x-patch, Size: 22355 bytes --]
Index: e2fsprogs-1.41.1/lib/blkid/probe.h
===================================================================
--- e2fsprogs-1.41.1.orig/lib/blkid/probe.h
+++ e2fsprogs-1.41.1/lib/blkid/probe.h
@@ -119,6 +119,7 @@ struct ext2_super_block {
#define EXT4_FEATURE_INCOMPAT_64BIT 0x0080
#define EXT4_FEATURE_INCOMPAT_MMP 0x0100
#define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200
+#define EXT4_FEATURE_INCOMPAT_EA_INODE 0x0400
#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
Index: e2fsprogs-1.41.1/lib/e2p/feature.c
===================================================================
--- e2fsprogs-1.41.1.orig/lib/e2p/feature.c
+++ e2fsprogs-1.41.1/lib/e2p/feature.c
@@ -75,6 +75,8 @@ static struct feature feature_list[] = {
"flex_bg"},
{ E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_MMP,
"mmp" },
+ { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_EA_INODE,
+ "large_xattr" },
{ 0, 0, 0 },
};
Index: e2fsprogs-1.41.1/lib/ext2fs/ext2_fs.h
===================================================================
--- e2fsprogs-1.41.1.orig/lib/ext2fs/ext2_fs.h
+++ e2fsprogs-1.41.1/lib/ext2fs/ext2_fs.h
@@ -273,6 +273,7 @@ struct ext2_dx_countlimit {
#define EXT2_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/
#define EXT4_HUGE_FILE_FL 0x00040000 /* Set to each huge file */
#define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */
+#define EXT4_EA_INODE_FL 0x00200000 /* Inode used for large EA */
#define EXT2_RESERVED_FL 0x80000000 /* reserved for ext2 lib */
#define EXT2_FL_USER_VISIBLE 0x000BDFFF /* User visible flags */
@@ -649,11 +650,13 @@ struct ext2_super_block {
#define EXT4_FEATURE_INCOMPAT_64BIT 0x0080
#define EXT4_FEATURE_INCOMPAT_MMP 0x0100
#define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200
+#define EXT4_FEATURE_INCOMPAT_EA_INODE 0x0400
#define EXT2_FEATURE_COMPAT_SUPP 0
#define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE| \
- EXT4_FEATURE_INCOMPAT_MMP)
+ EXT4_FEATURE_INCOMPAT_MMP| \
+ EXT4_FEATURE_INCOMPAT_EA_INODE)
#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
EXT4_FEATURE_RO_COMPAT_DIR_NLINK| \
Index: e2fsprogs-1.41.1/misc/mke2fs.c
===================================================================
--- e2fsprogs-1.41.1.orig/misc/mke2fs.c
+++ e2fsprogs-1.41.1/misc/mke2fs.c
@@ -841,7 +841,8 @@ static __u32 ok_features[3] = {
EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|
EXT2_FEATURE_INCOMPAT_META_BG|
EXT4_FEATURE_INCOMPAT_FLEX_BG|
- EXT4_FEATURE_INCOMPAT_MMP,
+ EXT4_FEATURE_INCOMPAT_MMP|
+ EXT4_FEATURE_INCOMPAT_EA_INODE,
/* R/O compat */
EXT2_FEATURE_RO_COMPAT_LARGE_FILE|
EXT4_FEATURE_RO_COMPAT_HUGE_FILE|
Index: e2fsprogs-1.41.1/misc/tune2fs.c
===================================================================
--- e2fsprogs-1.41.1.orig/misc/tune2fs.c
+++ e2fsprogs-1.41.1/misc/tune2fs.c
@@ -122,7 +122,8 @@ static __u32 ok_features[3] = {
EXT2_FEATURE_INCOMPAT_FILETYPE |
EXT3_FEATURE_INCOMPAT_EXTENTS |
EXT4_FEATURE_INCOMPAT_FLEX_BG |
- EXT4_FEATURE_INCOMPAT_MMP,
+ EXT4_FEATURE_INCOMPAT_MMP |
+ EXT4_FEATURE_INCOMPAT_EA_INODE,
/* R/O compat */
EXT2_FEATURE_RO_COMPAT_LARGE_FILE |
EXT4_FEATURE_RO_COMPAT_HUGE_FILE|
@@ -477,6 +478,9 @@ mmp_error:
ext2fs_free_mem(&buf);
}
+ if (FEATURE_ON(E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_EA_INODE))
+ sb->s_feature_incompat |= EXT4_FEATURE_INCOMPAT_EA_INODE;
+
if (FEATURE_ON(E2P_FEATURE_COMPAT, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
/*
* If adding a journal flag, let the create journal
Index: e2fsprogs-1.41.1/e2fsck/pass1.c
===================================================================
--- e2fsprogs-1.41.1.orig/e2fsck/pass1.c
+++ e2fsprogs-1.41.1/e2fsck/pass1.c
@@ -28,6 +28,7 @@
* - A bitmap of which blocks are in use. (block_found_map)
* - A bitmap of which blocks are in use by two inodes (block_dup_map)
* - The data blocks of the directory inodes. (dir_map)
+ * - A bitmap of EA inodes. (inode_ea_map)
*
* Pass 1 is designed to stash away enough information so that the
* other passes should not need to read in the inode information
@@ -269,6 +270,125 @@ static void check_size(e2fsck_t ctx, str
e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
}
+extern char *ext2_attr_index_prefix[];
+
+static void e2fsck_block_alloc_stats(ext2_filsys fs, blk64_t blk, int inuse)
+{
+ e2fsck_t ctx = (e2fsck_t) fs->priv_data;
+
+ if (ctx->block_found_map) {
+ if (inuse > 0)
+ ext2fs_mark_block_bitmap(ctx->block_found_map,
+ (blk_t) blk);
+ else
+ ext2fs_unmark_block_bitmap(ctx->block_found_map,
+ (blk_t) blk);
+ }
+}
+
+static void mark_inode_ea_map(e2fsck_t ctx, struct problem_context *pctx,
+ ext2_ino_t ino)
+{
+ if (!ctx->inode_ea_map) {
+ pctx->errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
+ _("EA inode map"),
+ &ctx->inode_ea_map);
+ if (pctx->errcode) {
+ fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR,
+ pctx);
+ exit(1);
+ }
+ }
+
+ ext2fs_mark_inode_bitmap(ctx->inode_ea_map, ino);
+}
+
+/*
+ * Delete an EA entry. If this is the last entry to be deleted, then i_file_acl
+ * must have been freed, so we must update e2fsck block statistics and set
+ * i_file_acl_deleted.
+ * When we delete the entry successfully, this function returns 0, else
+ * non-zero value.
+ */
+static int e2fsck_ea_entry_delete(e2fsck_t ctx, struct ext2_ext_attr_entry *entry,
+ struct problem_context *pctx,
+ int *i_file_acl_deleted, problem_t prob)
+{
+ blk_t i_file_acl = pctx->inode->i_file_acl;
+ int err = 1;
+
+ pctx->num = entry->e_value_inum;
+
+ if (fix_problem(ctx, prob, pctx)) {
+ /* Delete corrupt EA entry */
+ err = ext2fs_attr_set(ctx->fs, pctx->ino, pctx->inode,
+ entry->e_name_index, entry->e_name,
+ 0, 0, 0);
+ if (err == 0) {
+ if (i_file_acl && pctx->inode->i_file_acl == 0) {
+ e2fsck_block_alloc_stats(ctx->fs, i_file_acl, -1);
+ *i_file_acl_deleted = 1;
+ }
+ return 0;
+ }
+ }
+
+ return err;
+}
+
+/*
+ * Check validity of EA inode. Return 0 if EA inode is valid, nonzero otherwise.
+ */
+static int check_large_ea_inode(e2fsck_t ctx, struct ext2_ext_attr_entry *entry,
+ struct problem_context *pctx,
+ int *i_file_acl_deleted)
+{
+ struct ext2_inode inode;
+ int ret;
+
+ /* Check if inode is within valid range */
+ if ((entry->e_value_inum < EXT2_FIRST_INODE(ctx->fs->super)) ||
+ (entry->e_value_inum > ctx->fs->super->s_inodes_count)) {
+ ret = e2fsck_ea_entry_delete(ctx, entry, pctx,
+ i_file_acl_deleted,
+ PR_1_ATTR_VALUE_EA_INODE);
+ /* If user refuses to delete this entry, caller may try to set
+ * the bit for this out-of-bound inode in inode_ea_map, so
+ * always return failure */
+ return 1;
+ }
+
+ e2fsck_read_inode(ctx, entry->e_value_inum, &inode, "pass1");
+ if (!(inode.i_flags & EXT4_EA_INODE_FL)) {
+ /* If EXT4_EA_INODE_FL flag is not present but back-pointer
+ * matches then we should set this flag */
+ if (inode.i_mtime == pctx->ino &&
+ inode.i_generation == pctx->inode->i_generation &&
+ fix_problem(ctx, PR_1_ATTR_SET_EA_INODE_FL, pctx)) {
+ inode.i_flags |= EXT4_EA_INODE_FL;
+ ext2fs_write_inode(ctx->fs, entry->e_value_inum, &inode);
+
+ return 0;
+ }
+
+ ret = e2fsck_ea_entry_delete(ctx, entry, pctx,
+ i_file_acl_deleted,
+ PR_1_ATTR_NO_EA_INODE_FL);
+ return ret;
+ }
+
+ /* Validate the inode back-pointer */
+ if (inode.i_mtime != pctx->ino ||
+ inode.i_generation != pctx->inode->i_generation) {
+ ret = e2fsck_ea_entry_delete(ctx, entry, pctx,
+ i_file_acl_deleted,
+ PR_1_ATTR_INVAL_EA_INODE);
+ return ret;
+ }
+
+ return 0;
+}
+
static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
{
struct ext2_super_block *sb = ctx->fs->super;
@@ -307,18 +427,25 @@ static void check_ea_in_inode(e2fsck_t c
/* attribute len eats this space */
remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len);
- /* check value size */
- if (entry->e_value_size == 0 || entry->e_value_size > remain) {
+ if (entry->e_value_size == 0) {
pctx->num = entry->e_value_size;
problem = PR_1_ATTR_VALUE_SIZE;
goto fix;
}
- /* e_value_block must be 0 in inode's ea */
- if (entry->e_value_block != 0) {
- pctx->num = entry->e_value_block;
- problem = PR_1_ATTR_VALUE_BLOCK;
- goto fix;
+ if (entry->e_value_inum == 0) {
+ /* check value size */
+ if (entry->e_value_size > remain) {
+ pctx->num = entry->e_value_size;
+ problem = PR_1_ATTR_VALUE_SIZE;
+ goto fix;
+ }
+ } else {
+ int ret, tmp;
+
+ ret = check_large_ea_inode(ctx, entry, pctx, &tmp);
+ if (ret == 0)
+ mark_inode_ea_map(ctx, pctx, entry->e_value_inum);
}
hash = ext2fs_ext_attr_hash_entry(entry,
@@ -331,7 +458,10 @@ static void check_ea_in_inode(e2fsck_t c
goto fix;
}
- remain -= entry->e_value_size;
+ /* If EA value is stored in external inode then it does not
+ * consume space here */
+ if (entry->e_value_inum == 0)
+ remain -= entry->e_value_size;
entry = EXT2_EXT_ATTR_NEXT(entry);
}
@@ -510,8 +640,6 @@ extern void e2fsck_setup_tdb_icount(e2fs
*ret = 0;
}
-extern char *ext2_attr_index_prefix[];
-
int e2fsck_pass1_delete_attr(e2fsck_t ctx, struct ext2_inode_large *inode,
struct problem_context *pctx, int needed_size)
{
@@ -568,7 +696,7 @@ int e2fsck_pass1_delete_attr(e2fsck_t ct
if (EXT2_EXT_IS_LAST_ENTRY(entry)) {
if (in_inode) {
entry = entry_blk;
- len = sizeof(entry->e_name);
+ len = sizeof(entry->e_name);
entry_size = ext2fs_attr_get_next_attr(entry,
index, name, len, 1);
in_inode = 0;
@@ -1609,6 +1737,7 @@ static int check_ext_attr(e2fsck_t ctx,
struct ext2_ext_attr_entry *entry;
int count;
region_t region = 0;
+ int ret;
blk = inode->i_file_acl;
if (blk == 0)
@@ -1730,19 +1859,27 @@ static int check_ext_attr(e2fsck_t ctx,
goto clear_extattr;
break;
}
- if (entry->e_value_block != 0) {
- if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx))
- goto clear_extattr;
- }
- if (entry->e_value_offs + entry->e_value_size > fs->blocksize) {
- if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx))
- goto clear_extattr;
- break;
- }
- if (entry->e_value_size &&
- region_allocate(region, entry->e_value_offs,
- EXT2_EXT_ATTR_SIZE(entry->e_value_size))) {
- if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
+ if (entry->e_value_inum == 0) {
+ if (entry->e_value_offs + entry->e_value_size > fs->blocksize) {
+ if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx))
+ goto clear_extattr;
+ break;
+ }
+ if (entry->e_value_size &&
+ region_allocate(region, entry->e_value_offs,
+ EXT2_EXT_ATTR_SIZE(entry->e_value_size))) {
+ if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
+ goto clear_extattr;
+ }
+ } else {
+ int i_file_acl_deleted = 0;
+
+ ret = check_large_ea_inode(ctx, entry, pctx,
+ &i_file_acl_deleted);
+ if (ret == 0)
+ mark_inode_ea_map(ctx, pctx, entry->e_value_inum);
+
+ if (i_file_acl_deleted)
goto clear_extattr;
}
@@ -2883,20 +3020,6 @@ static errcode_t e2fsck_get_alloc_block(
return (0);
}
-static void e2fsck_block_alloc_stats(ext2_filsys fs, blk64_t blk, int inuse)
-{
- e2fsck_t ctx = (e2fsck_t) fs->priv_data;
-
- if (ctx->block_found_map) {
- if (inuse > 0)
- ext2fs_mark_block_bitmap(ctx->block_found_map,
- (blk_t) blk);
- else
- ext2fs_unmark_block_bitmap(ctx->block_found_map,
- (blk_t) blk);
- }
-}
-
void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool)
{
ext2_filsys fs = ctx->fs;
Index: e2fsprogs-1.41.1/e2fsck/problem.c
===================================================================
--- e2fsprogs-1.41.1.orig/e2fsck/problem.c
+++ e2fsprogs-1.41.1/e2fsck/problem.c
@@ -928,6 +928,30 @@ static struct e2fsck_problem problem_tab
"without deletion of an EA.\n"),
PROMPT_FIX, 0 },
+ /* Inode has illegal EA value inode */
+ { PR_1_ATTR_VALUE_EA_INODE,
+ N_("@i %i has @I EA @i %N.\n"),
+ PROMPT_FIX, PR_PREEN_OK },
+
+ /* Invalid back-pointer from EA-inode to parent inode */
+ { PR_1_ATTR_INVAL_EA_INODE,
+ N_("@I backpointer from EA @i %N to parent @i %i. "
+ "Delete EA inode?\n"),
+ PROMPT_FIX, PR_PREEN_OK },
+
+ /* Parent inode has invalid EA entry. EA inode does not have
+ * EXT4_EA_INODE_FL flag */
+ { PR_1_ATTR_NO_EA_INODE_FL,
+ N_("Parent @i %i has @I EA entry. EA @i %N does not have "
+ "EXT4_EA_INODE_FL flag. Delete EA entry?\n"),
+ PROMPT_FIX, PR_PREEN_OK },
+
+ /* EA inode for parent inode does not have EXT4_EA_INODE_FL flag */
+ { PR_1_ATTR_SET_EA_INODE_FL,
+ N_("EA @i %N for parent @i %i does not have EXT4_EA_INODE_FL flag. "
+ "Set the flag?\n"),
+ PROMPT_FIX, PR_PREEN_OK },
+
/* Pass 1b errors */
Index: e2fsprogs-1.41.1/e2fsck/problem.h
===================================================================
--- e2fsprogs-1.41.1.orig/e2fsck/problem.h
+++ e2fsprogs-1.41.1/e2fsck/problem.h
@@ -548,6 +548,19 @@ struct problem_context {
*/
#define PR_1_CLEAR_EXTRA_ISIZE 0x01006C
+/* Inode has illegal EA value inode */
+#define PR_1_ATTR_VALUE_EA_INODE 0x01006D
+
+/* Invalid back-pointer from EA-inode to parent inode */
+#define PR_1_ATTR_INVAL_EA_INODE 0x01006E
+
+/* Parent inode has invalid EA entry. EA inode does not have
+ * EXT4_EA_INODE_FL flag */
+#define PR_1_ATTR_NO_EA_INODE_FL 0x01006F
+
+/* EA inode for parent inode does not have EXT4_EA_INODE_FL flag */
+#define PR_1_ATTR_SET_EA_INODE_FL 0x010070
+
/*
* Pass 1b errors
*/
Index: e2fsprogs-1.41.1/lib/ext2fs/ext2_ext_attr.h
===================================================================
--- e2fsprogs-1.41.1.orig/lib/ext2fs/ext2_ext_attr.h
+++ e2fsprogs-1.41.1/lib/ext2fs/ext2_ext_attr.h
@@ -30,7 +30,7 @@ struct ext2_ext_attr_entry {
__u8 e_name_len; /* length of name */
__u8 e_name_index; /* attribute name index */
__u16 e_value_offs; /* offset in disk block of value */
- __u32 e_value_block; /* disk block attribute is stored on (n/i) */
+ __u32 e_value_inum; /* inode in which the value is stored */
__u32 e_value_size; /* size of attribute value */
__u32 e_hash; /* hash value of name and value */
#if 1
@@ -38,6 +38,9 @@ struct ext2_ext_attr_entry {
#endif
};
+#define EXT4_XATTR_MIN_LARGE_EA_SIZE(b) ((b) >> 1)
+#define EXT4_XATTR_MAX_LARGE_EA_SIZE (1024 * 1024)
+
#define BHDR(block) ((struct ext2_ext_attr_header *) block)
#define IHDR(inode) \
((__u32 *) ((char *)inode + \
Index: e2fsprogs-1.41.1/lib/ext2fs/ext_attr.c
===================================================================
--- e2fsprogs-1.41.1.orig/lib/ext2fs/ext_attr.c
+++ e2fsprogs-1.41.1/lib/ext2fs/ext_attr.c
@@ -45,7 +45,7 @@ __u32 ext2fs_ext_attr_hash_entry(struct
}
/* The hash needs to be calculated on the data in little-endian. */
- if (entry->e_value_block == 0 && entry->e_value_size != 0) {
+ if (entry->e_value_inum == 0 && entry->e_value_size != 0) {
__u32 *value = (__u32 *)data;
for (n = (entry->e_value_size + EXT2_EXT_ATTR_ROUND) >>
EXT2_EXT_ATTR_PAD_BITS; n; n--) {
@@ -190,6 +190,7 @@ struct ext2_attr_ibody_find {
};
struct ext2_attr_block_find {
+ ext2_ino_t ino;
struct ext2_attr_search s;
char *block;
};
@@ -202,7 +203,7 @@ void ext2fs_attr_shift_entries(struct ex
/* Adjust the value offsets of the entries */
for (; !EXT2_EXT_IS_LAST_ENTRY(last); last = EXT2_EXT_ATTR_NEXT(last)) {
- if (!last->e_value_block && last->e_value_size) {
+ if (last->e_value_inum == 0 && last->e_value_size) {
last->e_value_offs = last->e_value_offs +
value_offs_shift;
}
@@ -221,7 +222,7 @@ int ext2fs_attr_free_space(struct ext2_e
{
for (; !EXT2_EXT_IS_LAST_ENTRY(last); last = EXT2_EXT_ATTR_NEXT(last)) {
*total += EXT2_EXT_ATTR_LEN(last->e_name_len);
- if (!last->e_value_block && last->e_value_size) {
+ if (last->e_value_inum == 0 && last->e_value_size) {
int offs = last->e_value_offs;
if (offs < *min_offs)
*min_offs = offs;
@@ -360,7 +361,7 @@ static errcode_t ext2fs_attr_set_entry(e
/* Compute min_offs and last. */
for (last = s->first; !EXT2_EXT_IS_LAST_ENTRY(last);
last = EXT2_EXT_ATTR_NEXT(last)) {
- if (!last->e_value_block && last->e_value_size) {
+ if (last->e_value_inum == 0 && last->e_value_size) {
int offs = last->e_value_offs;
if (offs < min_offs)
@@ -370,7 +371,7 @@ static errcode_t ext2fs_attr_set_entry(e
free = min_offs - ((char *)last - s->base) - sizeof(__u32);
if (!s->not_found) {
- if (!s->here->e_value_block && s->here->e_value_size) {
+ if (s->here->e_value_inum == 0 && s->here->e_value_size) {
int size = s->here->e_value_size;
free += EXT2_EXT_ATTR_SIZE(size);
}
@@ -393,7 +394,7 @@ static errcode_t ext2fs_attr_set_entry(e
s->here->e_name_len = name_len;
memcpy(s->here->e_name, i->name, name_len);
} else {
- if (!s->here->e_value_block && s->here->e_value_size) {
+ if (s->here->e_value_inum == 0 && s->here->e_value_size) {
char *first_val = s->base + min_offs;
int offs = s->here->e_value_offs;
char *val = s->base + offs;
@@ -422,7 +423,7 @@ static errcode_t ext2fs_attr_set_entry(e
while (!EXT2_EXT_IS_LAST_ENTRY(last)) {
int o = last->e_value_offs;
- if (!last->e_value_block &&
+ if (last->e_value_inum == 0 &&
last->e_value_size && o < offs)
last->e_value_offs = o + size;
last = EXT2_EXT_ATTR_NEXT(last);
@@ -540,9 +541,20 @@ static errcode_t ext2fs_attr_block_set(e
/* Update the i_blocks if we added a new EA block */
if (!inode->i_file_acl && new_buf)
inode->i_blocks += fs->blocksize / 512;
+
+ /* Drop the previous xattr block. */
+ if (!new_buf) {
+ if (!fs->block_map)
+ ext2fs_read_block_bitmap(fs);
+ ext2fs_block_alloc_stats(fs, inode->i_file_acl, -1);
+ inode->i_blocks -= fs->blocksize / 512;
+ }
+
/* Update the inode. */
inode->i_file_acl = new_buf ? blk : 0;
+ ext2fs_write_inode(fs, bs->ino, inode);
+
cleanup:
if (clear_flag)
ext2fs_free_mem(&s->base);
@@ -829,6 +841,7 @@ errcode_t ext2fs_expand_extra_isize(ext2
.s = { .not_found = EXT2_ET_EA_NO_SPACE, },
};
struct ext2_attr_block_find bs = {
+ .ino = ino,
.s = { .not_found = EXT2_ET_EA_NO_SPACE, },
};
char *start, *end, *block_buf = NULL, *buffer =NULL, *b_entry_name=NULL;
Index: e2fsprogs-1.41.1/lib/ext2fs/swapfs.c
===================================================================
--- e2fsprogs-1.41.1.orig/lib/ext2fs/swapfs.c
+++ e2fsprogs-1.41.1/lib/ext2fs/swapfs.c
@@ -110,7 +110,7 @@ void ext2fs_swap_ext_attr_entry(struct e
struct ext2_ext_attr_entry *from_entry)
{
to_entry->e_value_offs = ext2fs_swab16(from_entry->e_value_offs);
- to_entry->e_value_block = ext2fs_swab32(from_entry->e_value_block);
+ to_entry->e_value_inum = ext2fs_swab32(from_entry->e_value_inum);
to_entry->e_value_size = ext2fs_swab32(from_entry->e_value_size);
to_entry->e_hash = ext2fs_swab32(from_entry->e_hash);
}
Index: e2fsprogs-1.41.1/e2fsck/pass4.c
===================================================================
--- e2fsprogs-1.41.1.orig/e2fsck/pass4.c
+++ e2fsprogs-1.41.1/e2fsck/pass4.c
@@ -11,6 +11,7 @@
* Pass 4 frees the following data structures:
* - A bitmap of which inodes are in bad blocks. (inode_bb_map)
* - A bitmap of which inodes are imagic inodes. (inode_imagic_map)
+ * - A bitmap of EA inodes. (inode_ea_map)
*/
#include "e2fsck.h"
@@ -39,6 +40,20 @@ static int disconnect_inode(e2fsck_t ctx
} else {
e2fsck_read_inode(ctx, i, inode, "pass4: disconnect_inode");
}
+
+ if (inode->i_flags & EXT4_EA_INODE_FL) {
+ if (ext2fs_test_inode_bitmap(ctx->inode_ea_map, i)) {
+ ext2fs_icount_store(ctx->inode_count, i, 1);
+ return 0;
+ } else {
+ /* Zero the link count so that when inode is linked to
+ * lost+found it has correct link count */
+ inode->i_links_count = 0;
+ e2fsck_write_inode(ctx, i, inode, "disconnect_inode");
+ ext2fs_icount_store(ctx->inode_link_info, i, 0);
+ }
+ }
+
clear_problem_context(&pctx);
pctx.ino = i;
pctx.inode = inode;
@@ -182,6 +197,8 @@ void e2fsck_pass4(e2fsck_t ctx)
ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
ext2fs_free_icount(ctx->inode_badness); ctx->inode_badness = 0;
+ ext2fs_free_inode_bitmap(ctx->inode_ea_map);
+ ctx->inode_ea_map = 0;
ext2fs_free_inode_bitmap(ctx->inode_bb_map);
ctx->inode_bb_map = 0;
ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
Index: e2fsprogs-1.41.1/lib/ext2fs/ext2fs.h
===================================================================
--- e2fsprogs-1.41.1.orig/lib/ext2fs/ext2fs.h
+++ e2fsprogs-1.41.1/lib/ext2fs/ext2fs.h
@@ -550,7 +550,8 @@ typedef struct ext2_icount *ext2_icount_
EXT3_FEATURE_INCOMPAT_RECOVER|\
EXT3_FEATURE_INCOMPAT_EXTENTS|\
EXT4_FEATURE_INCOMPAT_FLEX_BG|\
- EXT4_FEATURE_INCOMPAT_MMP)
+ EXT4_FEATURE_INCOMPAT_MMP|\
+ EXT4_FEATURE_INCOMPAT_EA_INODE)
#else
#define EXT2_LIB_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE|\
EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|\
@@ -558,7 +559,8 @@ typedef struct ext2_icount *ext2_icount_
EXT3_FEATURE_INCOMPAT_RECOVER|\
EXT3_FEATURE_INCOMPAT_EXTENTS|\
EXT4_FEATURE_INCOMPAT_FLEX_BG|\
- EXT4_FEATURE_INCOMPAT_MMP)
+ EXT4_FEATURE_INCOMPAT_MMP|\
+ EXT4_FEATURE_INCOMPAT_EA_INODE)
#endif
#define EXT2_LIB_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|\
EXT4_FEATURE_RO_COMPAT_HUGE_FILE|\
Index: e2fsprogs-1.41.1/e2fsck/e2fsck.h
===================================================================
--- e2fsprogs-1.41.1.orig/e2fsck/e2fsck.h
+++ e2fsprogs-1.41.1/e2fsck/e2fsck.h
@@ -251,6 +251,7 @@ struct e2fsck_struct {
ext2fs_inode_bitmap inode_bb_map; /* Inodes which are in bad blocks */
ext2fs_inode_bitmap inode_imagic_map; /* AFS inodes */
ext2fs_inode_bitmap inode_reg_map; /* Inodes which are regular files*/
+ ext2fs_inode_bitmap inode_ea_map; /* EA inodes which are non-orphan */
ext2fs_block_bitmap block_found_map; /* Blocks which are in use */
ext2fs_block_bitmap block_dup_map; /* Blks referenced more than once */
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2008-11-17 20:46 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-11-17 20:36 [PATCH 1/2 e2fsprogs] support for large EAs Kalpak Shah
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.