static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
{
struct ext2_super_block *sb = ctx->fs->super;
-@@ -307,18 +420,25 @@ static void check_ea_in_inode(e2fsck_t c
+@@ -307,23 +420,31 @@ static void check_ea_in_inode(e2fsck_t c
/* attribute len eats this space */
remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len);
}
/* Value size cannot be larger than EA space in inode */
-@@ -338,7 +458,10 @@ static void check_ea_in_inode(e2fsck_t c
+ if (entry->e_value_offs > storage_size ||
+- entry->e_value_offs + entry->e_value_size > storage_size) {
++ (entry->e_value_inum == 0 &&
++ entry->e_value_offs + entry->e_value_size > storage_size)) {
+ problem = PR_1_INODE_EA_BAD_VALUE;
+ goto fix;
+ }
+@@ -338,7 +459,10 @@ static void check_ea_in_inode(e2fsck_t c
goto fix;
}
entry = EXT2_EXT_ATTR_NEXT(entry);
}
-@@ -627,7 +750,7 @@ int e2fsck_pass1_delete_attr(e2fsck_t ct
+@@ -627,7 +751,7 @@ int e2fsck_pass1_delete_attr(e2fsck_t ct
if (EXT2_EXT_IS_LAST_ENTRY(entry)) {
if (in_inode) {
entry = entry_blk;
entry_size = ext2fs_attr_get_next_attr(entry,
index, name, len, 1);
in_inode = 0;
-@@ -1654,6 +1777,7 @@ static int check_ext_attr(e2fsck_t ctx,
+@@ -1654,6 +1778,7 @@ static int check_ext_attr(e2fsck_t ctx,
struct ext2_ext_attr_entry *entry;
int count;
region_t region = 0;
blk = ext2fs_file_acl_block(inode);
if (blk == 0)
-@@ -1775,19 +1899,27 @@ static int check_ext_attr(e2fsck_t ctx,
+@@ -1775,19 +1900,27 @@ static int check_ext_attr(e2fsck_t ctx,
goto clear_extattr;
break;
}
goto clear_extattr;
}
-@@ -2996,18 +3128,6 @@ static errcode_t e2fsck_get_alloc_block(
+@@ -2996,18 +3129,6 @@ static errcode_t e2fsck_get_alloc_block(
return (0);
}
===================================================================
--- e2fsprogs.orig/lib/ext2fs/ext2fs.h
+++ e2fsprogs/lib/ext2fs/ext2fs.h
-@@ -571,6 +571,7 @@ typedef struct ext2_icount *ext2_icount_
+@@ -570,6 +570,7 @@ typedef struct ext2_icount *ext2_icount_
EXT3_FEATURE_INCOMPAT_EXTENTS|\
EXT4_FEATURE_INCOMPAT_FLEX_BG|\
EXT4_FEATURE_INCOMPAT_MMP|\
EXT4_FEATURE_INCOMPAT_64BIT)
#else
#define EXT2_LIB_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE|\
-@@ -580,6 +581,7 @@ typedef struct ext2_icount *ext2_icount_
+@@ -579,6 +580,7 @@ typedef struct ext2_icount *ext2_icount_
EXT3_FEATURE_INCOMPAT_EXTENTS|\
EXT4_FEATURE_INCOMPAT_FLEX_BG|\
EXT4_FEATURE_INCOMPAT_MMP|\
if (FEATURE_ON(E2P_FEATURE_COMPAT, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
/*
* If adding a journal flag, let the create journal
+Index: e2fsprogs/debugfs/debugfs.c
+===================================================================
+--- e2fsprogs.orig/debugfs/debugfs.c
++++ e2fsprogs/debugfs/debugfs.c
+@@ -502,6 +502,7 @@ static void internal_dump_inode_extra(FI
+ struct ext2_ext_attr_entry *entry;
+ __u32 *magic;
+ char *start, *end;
++ int inode_xattr;
+ unsigned int storage_size;
+
+ fprintf(out, "Size of extra inode fields: %u\n", inode->i_extra_isize);
+@@ -524,17 +525,28 @@ static void internal_dump_inode_extra(FI
+ while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
+ struct ext2_ext_attr_entry *next =
+ EXT2_EXT_ATTR_NEXT(entry);
+- if (entry->e_value_size > storage_size ||
+- (char *) next >= end) {
++ inode_xattr =
++ EXT2_HAS_INCOMPAT_FEATURE(current_fs->super,
++ EXT4_FEATURE_INCOMPAT_EA_INODE) &&
++ entry->e_value_offs == 0 &&
++ entry->e_value_inum != 0;
++ if ((entry->e_value_size > storage_size &&
++ !inode_xattr) || (char *)next >= end) {
+ fprintf(out, "invalid EA entry in inode\n");
+ return;
+ }
+ fprintf(out, " ");
++
+ dump_xattr_string(out, EXT2_EXT_ATTR_NAME(entry),
+ entry->e_name_len);
+ fprintf(out, " = \"");
+- dump_xattr_string(out, start + entry->e_value_offs,
+- entry->e_value_size);
++ if (inode_xattr)
++ fprintf(out, "inode <%u>",
++ entry->e_value_inum);
++ else
++ dump_xattr_string(out,
++ start + entry->e_value_offs,
++ entry->e_value_size);
+ fprintf(out, "\" (%u)\n", entry->e_value_size);
+ entry = next;
+ }
dnl handle --enable-compression
dnl
AC_ARG_ENABLE([compression],
-@@ -763,6 +811,7 @@ AC_CHECK_HEADERS(net/if.h,,,
+@@ -763,6 +819,7 @@ AC_CHECK_HEADERS(net/if.h,,,
#include <sys/socket.h>
#endif
]])
AC_FUNC_VPRINTF
dnl Check to see if dirent has member d_reclen. On cygwin those d_reclen
dnl is not decleared.
-@@ -880,6 +929,31 @@ SOCKET_LIB=''
+@@ -880,6 +937,31 @@ SOCKET_LIB=''
AC_CHECK_LIB(socket, socket, [SOCKET_LIB=-lsocket])
AC_SUBST(SOCKET_LIB)
dnl
int problem = 0;
inode = (struct ext2_inode_large *) pctx->inode;
-@@ -458,6 +461,9 @@ static void check_ea_in_inode(e2fsck_t c
+@@ -459,6 +462,9 @@ static void check_ea_in_inode(e2fsck_t c
goto fix;
}
/* If EA value is stored in external inode then it does not
* consume space here */
if (entry->e_value_inum == 0)
-@@ -465,6 +471,10 @@ static void check_ea_in_inode(e2fsck_t c
+@@ -466,8 +472,16 @@ static void check_ea_in_inode(e2fsck_t c
entry = EXT2_EXT_ATTR_NEXT(entry);
}
+ e2fsck_lfsck_save_ea(ctx, pctx->ino, inode->i_generation,
+ lmm, lma);
fix:
- /*
+- /*
++ if (lmm)
++ ext2fs_free_mem(&lmm);
++ if (lma)
++ ext2fs_free_mem(&lma);
++ /*
* it seems like a corruption. it's very unlikely we could repair
-@@ -1005,6 +1015,12 @@ void e2fsck_pass1(e2fsck_t ctx)
+ * EA(s) in automatic fashion -bzzz
+ */
+@@ -1006,6 +1020,12 @@ void e2fsck_pass1(e2fsck_t ctx)
ext2fs_mark_block_bitmap2(ctx->block_found_map,
- fs->super->s_mmp_block);
+ fs->super->s_mmp_block);
+ if (!(ctx->options & E2F_OPT_READONLY) &&
+ (ctx->lustre_devtype & LUSTRE_TYPE) == LUSTRE_MDS) {
+
while (1) {
if (ino % EXT2_MMP_INODE_INTERVAL == 0) {
- if (e2fsck_mmp_update(fs))
-@@ -1513,6 +1529,9 @@ void e2fsck_pass1(e2fsck_t ctx)
+ if (e2fsck_mmp_update(fs))
+@@ -1511,6 +1531,9 @@ void e2fsck_pass1(e2fsck_t ctx)
}
e2fsck_pass1_dupblocks(ctx, block_buf);
}
ext2fs_free_mem(&inodes_to_process);
endit:
e2fsck_use_inode_shortcuts(ctx, 0);
-@@ -1780,6 +1799,8 @@ static int check_ext_attr(e2fsck_t ctx,
+@@ -1778,6 +1801,8 @@ static int check_ext_attr(e2fsck_t ctx,
struct ext2_ext_attr_entry *entry;
int count;
region_t region = 0;
int ret;
blk = ext2fs_file_acl_block(inode);
-@@ -1936,8 +1957,19 @@ static int check_ext_attr(e2fsck_t ctx,
+@@ -1934,13 +1959,28 @@ static int check_ext_attr(e2fsck_t ctx,
entry->e_hash = hash;
}
if (region_allocate(region, (char *)entry - (char *)header, 4)) {
if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
goto clear_extattr;
+ }
+ region_free(region);
++ if (lmm)
++ ext2fs_free_mem(&lmm);
++ if (lma)
++ ext2fs_free_mem(&lma);
+
+ count = header->h_refcount - 1;
+ if (count)
+@@ -1950,6 +1990,11 @@ static int check_ext_attr(e2fsck_t ctx,
+ return 1;
+
+ clear_extattr:
++ if (lmm)
++ ext2fs_free_mem(&lmm);
++ if (lma)
++ ext2fs_free_mem(&lma);
++
+ if (region)
+ region_free(region);
+ ext2fs_file_acl_block_set(inode, 0);
Index: e2fsprogs/e2fsck/unix.c
===================================================================
--- e2fsprogs.orig/e2fsck/unix.c
===================================================================
--- e2fsprogs.orig/misc/mke2fs.c
+++ e2fsprogs/misc/mke2fs.c
-@@ -1398,7 +1398,7 @@ profile_error:
+@@ -1401,7 +1401,7 @@ profile_error:
}
break;
case 'v':
Provides: e2fsprogs-libs = %{version} ldiskfsprogs = %{version}
Obsoletes: e4fsprogs e2fsprogs-libs < %{version}
%endif
-@@ -72,7 +76,8 @@ SMP systems.
+@@ -72,6 +76,7 @@ SMP systems.
%build
%configure --enable-elf-shlibs --enable-nls --disable-defrag \
-- %{?extra_config_flags:%extra_config_flags}
+ @WITH_LUSTRE@ @ENABLE_LFSCK@ \
-+ %{?extra_config_flags:%extra_config_flags}
+ %{?extra_config_flags:%extra_config_flags}
make
make check
-
-@@ -142,6 +146,7 @@ exit 0
+@@ -142,6 +147,7 @@ exit 0
%{_root_sbindir}/resize2fs
%{_root_sbindir}/tune2fs
%{_sbindir}/filefrag
%{_sbindir}/mklost+found
%{_sbindir}/e2freefrag
-@@ -170,6 +175,7 @@ exit 0
+@@ -169,6 +175,7 @@ exit 0
%{_mandir}/man8/debugfs.8*
%{_mandir}/man8/dumpe2fs.8*
%{_mandir}/man8/e2fsck.8*
===================================================================
--- /dev/null
+++ e2fsprogs/e2fsck/pass6.c
-@@ -0,0 +1,1511 @@
+@@ -0,0 +1,1551 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim:shiftwidth=8:tabstop=8:
+ *
+ struct lov_user_md **lmm,
+ struct lustre_mdt_attrs **lma)
+{
++ char *ea = NULL;
++ int retval;
++ unsigned int got;
++ ext2_file_t file;
++
+ /* This ensures that we don't open the file here if traversing an OST */
+ if ((ctx->lustre_devtype & LUSTRE_TYPE) != LUSTRE_MDS)
+ return 0;
+ entry->e_name_index == EXT3_XATTR_INDEX_LUSTRE)
+ return 0;
+
++ ea = e2fsck_allocate_memory(ctx, entry->e_value_size,
++ "EA");
++
++ if (entry->e_value_inum != 0) {
++ /* EA in external inode */
++ retval = ext2fs_file_open(ctx->fs, entry->e_value_inum,
++ 0, &file);
++ if (!retval) {
++ retval = ext2fs_file_read(file, ea,
++ entry->e_value_size, &got);
++ ext2fs_file_close(file);
++ if (retval != 0) {
++ ext2fs_free_mem(&ea);
++ return 0;
++ }
++ } else {
++ ext2fs_free_mem(&ea);
++ return 0;
++ }
++ } else {
++ memcpy(ea, value, entry->e_value_size);
++ }
++
+ if (strncmp(entry->e_name, XATTR_LUSTRE_MDS_LOV_EA,
+ entry->e_name_len) == 0) {
-+ *lmm = value;
++ if (*lmm) {
++ ext2fs_free_mem(&ea);
++ return -EINVAL;
++ }
++ *lmm = ea;
+ letocpu_lov_user_md(*lmm);
+
+ if (lfsck_check_lov_ea(ctx, *lmm)) {
+ *lmm = NULL;
+ ctx->flags |= E2F_FLAG_ABORT;
++ ext2fs_free_mem(&ea);
+ return -EINVAL;
+ }
+ } else if (strncmp(entry->e_name, XATTR_LUSTRE_MDT_LMA_EA,
+ entry->e_name_len) == 0) {
-+ *lma = value;
++ if (*lma) {
++ ext2fs_free_mem(&ea);
++ return -EINVAL;
++ }
++ *lma = ea;
+ if (lfsck_check_lma_ea(ctx, *lma)) {
+ *lma = NULL;
+ ctx->flags |= E2F_FLAG_ABORT;
++ ext2fs_free_mem(&ea);
+ return -EINVAL;
+ }
++ } else {
++ ext2fs_free_mem(&ea);
+ }
+
+ return 0;