#endif
#include "debugfs.h"
+#include "ext2fs/lfsck.h"
/*
* list directory
#define LONG_OPT 0x0001
#define DELETED_OPT 0x0002
#define PARSE_OPT 0x0004
+#define DIRDATA_OPT 0x0008
struct list_dir_struct {
FILE *f;
static const char *monstr[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
+static void list_dirdata(struct list_dir_struct *ls,
+ struct ext2_dir_entry *dirent)
+{
+ unsigned char *data;
+ int dlen;
+ __u8 dirdata_mask;
+ __u8 file_type = dirent->name_len >> 8;
+
+ data = (unsigned char *)dirent->name +
+ (dirent->name_len & EXT2_NAME_LEN) + 1;
+
+ for (dirdata_mask = EXT2_FT_MASK + 1;
+ dirdata_mask != 0; dirdata_mask <<= 1) {
+ if ((dirdata_mask & file_type) == 0)
+ continue;
+
+ dlen = data[0];
+ fprintf(ls->f, " ");
+
+ if (dirdata_mask == EXT2_DIRENT_LUFID) {
+ struct lu_fid *fid = (struct lu_fid *)(data + 1);
+
+ fid_be_to_cpu(fid, fid);
+ fprintf(ls->f, DFID, PFID(fid));
+ } else {
+ int i;
+
+ for (i = 1; i < dlen; i++)
+ fprintf(ls->f, "%02x", data[i]);
+ }
+ data += dlen;
+ }
+}
+
static int list_dir_proc(ext2_ino_t dir EXT2FS_ATTR((unused)),
int entry,
struct ext2_dir_entry *dirent,
fprintf(ls->f, "%5d", inode.i_size);
else
fprintf(ls->f, "%5llu", EXT2_I_SIZE(&inode));
- fprintf (ls->f, " %s %s\n", datestr, name);
+ fprintf(ls->f, " %s", datestr);
+ if ((ls->options & DIRDATA_OPT) != 0)
+ list_dirdata(ls, dirent);
+ fprintf(ls->f, " %s\n", name);
} else {
sprintf(tmp, "%c%u%c (%d) %s ", lbr, dirent->inode, rbr,
dirent->rec_len, name);
return;
reset_getopt();
- while ((c = getopt (argc, argv, "dlp")) != EOF) {
+ while ((c = getopt (argc, argv, "dDlp")) != EOF) {
switch (c) {
case 'l':
ls.options |= LONG_OPT;
break;
+ case 'D':
+ ls.options |= DIRDATA_OPT;
+ break;
case 'd':
ls.options |= DELETED_OPT;
break;
}
/* XXX should check that beginning matches a directory */
- root = (struct ext2_dx_root_info *) (block_buf + 24);
+ root = get_ext2_dx_root_info(fs, block_buf);
if ((root->reserved_zero || root->info_length < 8) &&
fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
return (int) (db_a->blockcnt - db_b->blockcnt);
}
+void ext2_fix_dirent_dirdata(struct ext2_dir_entry *de)
+{
+ __u16 file_type = de->name_len & (EXT2_FT_MASK << 8);
+ __u8 de_flags = (de->name_len >> 8) & ~EXT2_FT_MASK;
+ __u8 name_len = de->name_len & EXT2_NAME_LEN;
+ __u8 new_flag = 0;
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ __u8 flags = new_flag | (1 << i) << 4;
+
+ /* new_flag is accumulating flags that are set in de_flags
+ * and still fit inside rec_len. ext2_get_dirent_dirdata_size()
+ * returns the size of all the dirdata entries in flags, and
+ * chops off any that are beyond rec_len. */
+ if ((de_flags & flags) == flags) {
+ int dirdatalen = ext2_get_dirent_dirdata_size(de,flags);
+ int rlen = __EXT2_DIR_REC_LEN(name_len + dirdatalen);
+
+ if (rlen > de->rec_len)
+ break;
+
+ new_flag |= flags;
+ }
+ }
+ de->name_len = name_len | file_type | (new_flag << 8);
+}
+
+/*
+ * check for dirent data in ext3 dirent.
+ * return 0 if dirent data is ok.
+ * return 1 if dirent data does not exist.
+ * return 2 if dirent was modified due to error.
+ */
+int e2fsck_check_dirent_data(e2fsck_t ctx, struct ext2_dir_entry *de,
+ unsigned int offset, struct problem_context *pctx)
+{
+ if (!(ctx->fs->super->s_feature_incompat &
+ EXT4_FEATURE_INCOMPAT_DIRDATA)) {
+ if ((de->name_len >> 8) & ~EXT2_FT_MASK) {
+ /* clear dirent extra data flags. */
+ if (fix_problem(ctx, PR_2_CLEAR_DIRDATA, pctx)) {
+ de->name_len &= (EXT2_FT_MASK << 8) |
+ EXT2_NAME_LEN;
+ return 2;
+ }
+ }
+ return 1;
+ }
+ if ((de->name_len >> 8) & ~EXT2_FT_MASK) {
+ if (de->rec_len >= EXT2_DIR_REC_LEN(de) ||
+ de->rec_len + offset == EXT2_BLOCK_SIZE(ctx->fs->super)) {
+ if (ext2_get_dirent_dirdata_size(de,
+ EXT2_DIRENT_LUFID) ==
+ EXT2_DIRENT_LUFID_SIZE)
+ return 0;
+ }
+ /* just clear dirent data flags for now, we should fix FID data
+ * in lustre specific pass.
+ */
+ if (fix_problem(ctx, PR_2_CLEAR_DIRDATA, pctx)) {
+ ext2_fix_dirent_dirdata(de);
+ if (ext2_get_dirent_dirdata_size(de,
+ EXT2_DIRENT_LUFID) !=
+ EXT2_DIRENT_LUFID_SIZE)
+ de->name_len &= ~(EXT2_DIRENT_LUFID << 8);
+
+ return 2;
+ }
+ }
+ return 1;
+}
/*
* Make sure the first entry in the directory is '.', and that the
* directory entry is sane.
*/
static int check_dot(e2fsck_t ctx,
- struct ext2_dir_entry *dirent,
+ struct ext2_dir_entry *dirent, unsigned int offset,
ext2_ino_t ino, struct problem_context *pctx)
{
struct ext2_dir_entry *nextdir;
int status = 0;
int created = 0;
problem_t problem = 0;
+ int dir_data_error;
if (!dirent->inode)
problem = PR_2_MISSING_DOT;
else if (dirent->name[1] != '\0')
problem = PR_2_DOT_NULL_TERM;
+ dir_data_error = e2fsck_check_dirent_data(ctx, dirent, offset, pctx);
+
(void) ext2fs_get_rec_len(ctx->fs, dirent, &rec_len);
if (problem) {
if (fix_problem(ctx, problem, pctx)) {
- if (rec_len < 12)
+ if (rec_len < 12 && dir_data_error)
rec_len = dirent->rec_len = 12;
dirent->inode = ino;
dirent->name_len = 1;
status = 1;
}
}
- if (rec_len > 12) {
+ if (rec_len > 12 && dir_data_error) {
new_len = rec_len - 12;
if (new_len > 12) {
if (created ||
* here; this gets done in pass 3.
*/
static int check_dotdot(e2fsck_t ctx,
- struct ext2_dir_entry *dirent,
+ struct ext2_dir_entry *dirent, unsigned int offset,
ext2_ino_t ino, struct problem_context *pctx)
{
problem_t problem = 0;
unsigned int rec_len;
+ int dir_data_error;
if (!dirent->inode)
problem = PR_2_MISSING_DOT_DOT;
else if (dirent->name[2] != '\0')
problem = PR_2_DOT_DOT_NULL_TERM;
+ dir_data_error = e2fsck_check_dirent_data(ctx, dirent, offset, pctx);
+
(void) ext2fs_get_rec_len(ctx->fs, dirent, &rec_len);
if (problem) {
if (fix_problem(ctx, problem, pctx)) {
- if (rec_len < 12)
+ if (rec_len < 12 && dir_data_error)
dirent->rec_len = 12;
/*
* Note: we don't have the parent inode just
int should_be = EXT2_FT_UNKNOWN;
__u16 result;
struct ext2_inode inode;
+ __u8 dirdata = 0;
+
+ if (ctx->fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_DIRDATA) {
+ dirdata = filetype & ~EXT2_FT_MASK;
+ filetype = filetype & EXT2_FT_MASK;
+ }
if (!(ctx->fs->super->s_feature_incompat &
EXT2_FEATURE_INCOMPAT_FILETYPE)) {
pctx) == 0)
return 0;
- dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8;
+ dirent->name_len = (dirent->name_len & 0xFF) |
+ (dirdata | should_be) << 8;
return 1;
}
ext2_dirhash_t hash = 0, prev_hash;
if (db->blockcnt == 0) {
- root = (struct ext2_dx_root_info *) (block_buf + 24);
+ root = get_ext2_dx_root_info(fs, block_buf);
#ifdef DX_DEBUG
printf("Root node dump:\n");
printf("\t Flags: %d\n", root->unused_flags);
#endif
- ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length);
+ ent = (struct ext2_dx_entry *)((char *)root +
+ root->info_length);
} else {
- ent = (struct ext2_dx_entry *) (block_buf+8);
+ ent = (struct ext2_dx_entry *)(block_buf + 8);
}
- limit = (struct ext2_dx_countlimit *) ent;
+ limit = (struct ext2_dx_countlimit *)ent;
#ifdef DX_DEBUG
printf("Number of entries (count): %d\n",
(void) ext2fs_get_rec_len(fs, dirent, &rec_len);
limit = (struct ext2_dx_countlimit *) (buf+8);
if (db->blockcnt == 0) {
- root = (struct ext2_dx_root_info *) (buf + 24);
+ root = get_ext2_dx_root_info(fs, buf);
dx_db->type = DX_DIRBLOCK_ROOT;
dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST;
if ((root->reserved_zero ||
}
if (dot_state == 0) {
- if (check_dot(ctx, dirent, ino, &cd->pctx))
+ if (check_dot(ctx, dirent, offset, ino, &cd->pctx))
dir_modified++;
} else if (dot_state == 1) {
- ret = check_dotdot(ctx, dirent, ino, &cd->pctx);
+ ret = check_dotdot(ctx, dirent, offset, ino, &cd->pctx);
if (ret < 0)
goto abort_free_dict;
if (ret)
if (!dirent->inode)
goto next;
+ ret = e2fsck_check_dirent_data(ctx, dirent, offset, &cd->pctx);
+ if (ret == 2)
+ dir_modified++;
+
/*
* Make sure the inode listed is a legal one.
*/
struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) priv_data;
errcode_t retval;
struct problem_context pctx;
+ __u16 dirdata = 0;
if ((dirent->name_len & 0xFF) != 2)
return 0;
fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
}
dirent->inode = fp->parent;
+
+ dirdata = dirent->name_len & (~EXT2_FT_MASK << 8);
+
if (fp->ctx->fs->super->s_feature_incompat &
EXT2_FEATURE_INCOMPAT_FILETYPE)
dirent->name_len = (dirent->name_len & 0xFF) |
else
dirent->name_len = dirent->name_len & 0xFF;
+ if (fp->ctx->fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_DIRDATA)
+ dirent->name_len |= dirdata;
+
fp->done++;
return DIRENT_ABORT | DIRENT_CHANGED;
}
N_("@i %i is badly corrupt (badness value = %N). "),
PROMPT_CLEAR, PR_PREEN_OK },
+ /* Directory entry dirdata length set incorrectly */
+ { PR_2_CLEAR_DIRDATA,
+ N_("@E dirdata length set incorrectly.\n"),
+ PROMPT_CLEAR, PR_PREEN_OK },
+
/* Pass 3 errors */
/* Pass 3: Checking directory connectivity */
/* Inode completely corrupt */
#define PR_2_INODE_TOOBAD 0x020049
+/* Directory dirdata flag set */
+#define PR_2_CLEAR_DIRDATA 0x02f000
+
/*
* Pass 3 errors
*/
unsigned int dir_size;
int compress;
ino_t parent;
+ struct ext2_dir_entry *dot_de;
+ struct ext2_dir_entry *dotdot_de;
};
struct hash_entry {
dir_offset += rec_len;
if (dirent->inode == 0)
continue;
- if (!fd->compress && ((dirent->name_len&0xFF) == 1) &&
- (dirent->name[0] == '.'))
+ if (!fd->compress && ((dirent->name_len & 0xFF) == 1) &&
+ (dirent->name[0] == '.')) {
+ fd->dot_de = dirent;
continue;
- if (!fd->compress && ((dirent->name_len&0xFF) == 2) &&
+ }
+ if (!fd->compress && ((dirent->name_len & 0xFF) == 2) &&
(dirent->name[0] == '.') && (dirent->name[1] == '.')) {
fd->parent = dirent->inode;
+ fd->dotdot_de = dirent;
continue;
}
if (fd->num_array >= fd->max_array) {
}
ent = fd->harray + fd->num_array++;
ent->dir = dirent;
- fd->dir_size += EXT2_DIR_REC_LEN(dirent->name_len & 0xFF);
+ fd->dir_size += EXT2_DIR_REC_LEN(dirent);
ent->ino = dirent->inode;
if (fd->compress)
ent->hash = ent->minor_hash = 0;
ent = fd->harray + i;
if (ent->dir->inode == 0)
continue;
- rec_len = EXT2_DIR_REC_LEN(ent->dir->name_len & 0xFF);
+ rec_len = EXT2_DIR_REC_LEN(ent->dir);
if (rec_len > left) {
if (left) {
left += prev_rec_len;
if (retval)
return retval;
prev_rec_len = rec_len;
- memcpy(dirent->name, ent->dir->name, dirent->name_len & 0xFF);
+ memcpy(dirent->name, ent->dir->name, rec_len);
offset += rec_len;
left -= rec_len;
if (left < slack) {
static struct ext2_dx_root_info *set_root_node(ext2_filsys fs, char *buf,
- ext2_ino_t ino, ext2_ino_t parent)
+ ext2_ino_t ino, ext2_ino_t parent,
+ struct ext2_dir_entry *dot_de,
+ struct ext2_dir_entry *dotdot_de)
{
- struct ext2_dir_entry *dir;
- struct ext2_dx_root_info *root;
+ struct ext2_dir_entry *dir;
+ struct ext2_dx_root_info *root;
struct ext2_dx_countlimit *limits;
- int filetype = 0;
-
- if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
- filetype = EXT2_FT_DIR << 8;
+ int offset;
+ int rec_len;
memset(buf, 0, fs->blocksize);
dir = (struct ext2_dir_entry *) buf;
dir->inode = ino;
- dir->name[0] = '.';
- dir->name_len = 1 | filetype;
- dir->rec_len = 12;
- dir = (struct ext2_dir_entry *) (buf + 12);
+ dir->name_len = dot_de->name_len;
+ dir->rec_len = dot_de->rec_len;
+ rec_len = EXT2_DIR_REC_LEN(dot_de);
+ memcpy(dir->name, dot_de->name, rec_len);
+ offset = rec_len;
+
+ dir = (struct ext2_dir_entry *) (buf + offset);
+ /* set to jump over the index block */
dir->inode = parent;
- dir->name[0] = '.';
- dir->name[1] = '.';
- dir->name_len = 2 | filetype;
- dir->rec_len = fs->blocksize - 12;
+ dir->name_len = dotdot_de->name_len;
+ dir->rec_len = fs->blocksize - rec_len;
+ rec_len = EXT2_DIR_REC_LEN(dotdot_de);
+ memcpy(dir->name, dotdot_de->name, rec_len);
+ offset += rec_len;
- root = (struct ext2_dx_root_info *) (buf+24);
+ root = (struct ext2_dx_root_info *) (buf + offset);
root->reserved_zero = 0;
root->hash_version = fs->super->s_def_hash_version;
- root->info_length = 8;
+ root->info_length = sizeof(struct ext2_dx_root_info);
root->indirect_levels = 0;
root->unused_flags = 0;
+ offset += sizeof(struct ext2_dx_root_info);
- limits = (struct ext2_dx_countlimit *) (buf+32);
- limits->limit = (fs->blocksize - 32) / sizeof(struct ext2_dx_entry);
+ limits = (struct ext2_dx_countlimit *) (buf + offset);
+ limits->limit = (fs->blocksize - offset) / sizeof(struct ext2_dx_entry);
limits->count = 0;
return root;
static errcode_t calculate_tree(ext2_filsys fs,
struct out_dir *outdir,
ext2_ino_t ino,
- ext2_ino_t parent)
+ ext2_ino_t parent,
+ struct ext2_dir_entry *dot_de,
+ struct ext2_dir_entry *dotdot_de)
{
struct ext2_dx_root_info *root_info;
struct ext2_dx_entry *root, *dx_ent = 0;
int i, c1, c2, nblks;
int limit_offset, root_offset;
- root_info = set_root_node(fs, outdir->buf, ino, parent);
+ root_info = set_root_node(fs, outdir->buf, ino, parent, dot_de,
+ dotdot_de);
root_offset = limit_offset = ((char *) root_info - outdir->buf) +
root_info->info_length;
root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
if (retval)
goto errout;
- free(dir_buf); dir_buf = 0;
-
if (!fd.compress) {
/* Calculate the interior nodes */
- retval = calculate_tree(fs, &outdir, ino, fd.parent);
+ retval = calculate_tree(fs, &outdir, ino, fd.parent,
+ fd.dot_de, fd.dotdot_de);
if (retval)
goto errout;
}
struct ext2_dir_entry *dirent;
unsigned int name_len, rec_len;
-
retval = io_channel_read_blk64(fs->io, block, 1, buf);
if (retval)
return retval;
return retval;
}
+/*
+ * Compute the total directory entry data length.
+ * This includes the filename and an implicit NUL terminator (always present),
+ * and optional extensions. Each extension has a bit set in the high 4 bits of
+ * de->file_type, and the extension length is the first byte in each entry.
+ */
+int ext2_get_dirent_dirdata_size(struct ext2_dir_entry *de,
+ char dirdata_flags)
+{
+ char *len = de->name + (de->name_len & EXT2_NAME_LEN) + 1 /* NUL */;
+ __u8 extra_data_flags = (de->name_len & ~(EXT2_FT_MASK << 8)) >> 12;
+ int dlen = 0;
+
+ dirdata_flags >>= 4;
+ while ((extra_data_flags & dirdata_flags) != 0) {
+ if (extra_data_flags & 1) {
+ if (dirdata_flags & 1)
+ dlen += *len;
+
+ len += *len;
+ }
+ extra_data_flags >>= 1;
+ dirdata_flags >>= 1;
+ }
+
+ /* add NUL terminator byte to dirdata length */
+ return dlen + (dlen != 0);
+}
+
+int ext2_get_dirent_size(struct ext2_dir_entry *de)
+{
+ return ext2_get_dirent_dirdata_size(de, ~EXT2_FT_MASK);
+}
+
errcode_t ext2fs_read_dir_block2(ext2_filsys fs, blk_t block,
void *buf, int flags EXT2FS_ATTR((unused)))
{
#define EXT2_FEATURE_COMPAT_SUPP 0
#define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE| \
EXT4_FEATURE_INCOMPAT_MMP| \
- EXT4_FEATURE_INCOMPAT_EA_INODE)
+ EXT4_FEATURE_INCOMPAT_EA_INODE| \
+ EXT4_FEATURE_INCOMPAT_DIRDATA)
#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
EXT4_FEATURE_RO_COMPAT_DIR_NLINK| \
#define EXT2_FT_SYMLINK 7
#define EXT2_FT_MAX 8
+#define EXT2_FT_MASK 0x0f
/*
* EXT2_DIR_PAD defines the directory entries boundaries
*/
#define EXT2_DIR_PAD 4
#define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1)
-#define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \
+#define __EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \
~EXT2_DIR_ROUND)
+#define EXT2_DIR_REC_LEN(de) (__EXT2_DIR_REC_LEN(((de)->name_len & \
+ EXT2_NAME_LEN) + \
+ ext2_get_dirent_size(de)))
+/* lu_fid size and NUL char */
+#define EXT2_DIRENT_LUFID_SIZE (17 + 1)
+#define EXT2_DIRENT_LUFID 0x10
+
/*
* This structure is used for multiple mount protection. It is written
* into the block number saved in the s_mmp_block field in the superblock.
*/
#define EXT4_MMP_MIN_CHECK_INTERVAL 5
+int ext2_get_dirent_dirdata_size(struct ext2_dir_entry *de, char dirdata_flags);
+int ext2_get_dirent_size(struct ext2_dir_entry *de);
+
#endif /* _LINUX_EXT2_FS_H */
EXT4_FEATURE_INCOMPAT_FLEX_BG|\
EXT4_FEATURE_INCOMPAT_MMP|\
EXT4_FEATURE_INCOMPAT_EA_INODE|\
+ EXT4_FEATURE_INCOMPAT_DIRDATA|\
EXT4_FEATURE_INCOMPAT_64BIT)
#else
#define EXT2_LIB_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE|\
EXT4_FEATURE_INCOMPAT_FLEX_BG|\
EXT4_FEATURE_INCOMPAT_MMP|\
EXT4_FEATURE_INCOMPAT_EA_INODE|\
+ EXT4_FEATURE_INCOMPAT_DIRDATA|\
EXT4_FEATURE_INCOMPAT_64BIT)
#endif
#ifdef CONFIG_QUOTA
return (blk_t) ext2fs_inode_data_blocks2(fs, inode);
}
+_INLINE_ struct ext2_dx_root_info *get_ext2_dx_root_info(ext2_filsys fs,
+ char *buf)
+{
+ struct ext2_dir_entry *de = (struct ext2_dir_entry *)buf;
+
+ if (!(fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_DIRDATA))
+ return (struct ext2_dx_root_info *)(buf +
+ __EXT2_DIR_REC_LEN(1) +
+ __EXT2_DIR_REC_LEN(2));
+
+ /* get dotdot first */
+ de = (struct ext2_dir_entry *)((char *)de + de->rec_len);
+
+ /* dx root info is after dotdot entry */
+ de = (struct ext2_dir_entry *)((char *)de + EXT2_DIR_REC_LEN(de));
+
+ return (struct ext2_dx_root_info *)de;
+}
+
/*
* This is an efficient, overflow safe way of calculating ceil((1.0 * a) / b)
*/
--- /dev/null
+#ifndef LFSCK_H
+#define LFSCK_H
+
+/* This is unfortunately needed for older lustre_user.h to be usable */
+#define LASSERT(cond) do { } while (0)
+
+#ifdef HAVE_LUSTRE_LUSTREAPI_H
+#include <lustre/lustreapi.h>
+#elif HAVE_LUSTRE_LIBLUSTREAPI_H
+#include <lustre/liblustreapi.h>
+#endif
+
+#ifndef DFID
+#define DFID "[%#llx:0x%x:0x%x]"
+#define PFID(fid) (unsigned long long)fid_seq(fid), fid_oid(fid), fid_ver(fid)
+struct lu_fid {
+ __u64 f_seq;
+ __u32 f_oid;
+ __u32 f_ver;
+};
+#endif /* !DFID */
+
+/* Unfortunately, neither the 1.8 or 2.x lustre_idl.h file is suitable
+ * for inclusion by userspace programs because of external dependencies.
+ * Define the minimum set of replacement functions here until that is fixed. */
+#ifndef HAVE_LUSTRE_LUSTRE_IDL_H
+#define fid_seq(fid) ((fid)->f_seq)
+#define fid_oid(fid) ((fid)->f_oid)
+#define fid_ver(fid) ((fid)->f_ver)
+
+static inline void fid_be_to_cpu(struct lu_fid *dst, struct lu_fid *src)
+{
+ dst->f_seq = ext2fs_be64_to_cpu(src->f_seq);
+ dst->f_oid = ext2fs_be32_to_cpu(src->f_oid);
+ dst->f_ver = ext2fs_be32_to_cpu(src->f_ver);
+}
+#endif
+
+#endif /* LFSCK_H */
if (ls->done)
return DIRENT_ABORT;
- rec_len = EXT2_DIR_REC_LEN(ls->namelen);
+ rec_len = __EXT2_DIR_REC_LEN(ls->namelen);
ls->err = ext2fs_get_rec_len(ls->fs, dirent, &curr_rec_len);
if (ls->err)
* truncate it and return.
*/
if (dirent->inode) {
- min_rec_len = EXT2_DIR_REC_LEN(dirent->name_len & 0xFF);
+ min_rec_len = EXT2_DIR_REC_LEN(dirent);
if (curr_rec_len < (min_rec_len + rec_len))
return ret;
rec_len = curr_rec_len - min_rec_len;
dirent->name_len = ls->namelen;
strncpy(dirent->name, ls->name, ls->namelen);
if (ls->sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
- dirent->name_len |= (ls->flags & 0x7) << 8;
+ dirent->name_len |= (ls->flags & EXT2_FT_MASK) << 8;
ls->done++;
return DIRENT_ABORT|DIRENT_CHANGED;
dir->inode = dir_ino;
dir->name_len = 1 | filetype;
dir->name[0] = '.';
- rec_len = fs->blocksize - EXT2_DIR_REC_LEN(1);
- dir->rec_len = EXT2_DIR_REC_LEN(1);
+ rec_len = fs->blocksize - __EXT2_DIR_REC_LEN(1);
+ dir->rec_len = __EXT2_DIR_REC_LEN(1);
/*
* Set up entry for '..'
EXT4_FEATURE_INCOMPAT_FLEX_BG|
EXT4_FEATURE_INCOMPAT_EA_INODE|
EXT4_FEATURE_INCOMPAT_MMP |
+ EXT4_FEATURE_INCOMPAT_DIRDATA|
EXT4_FEATURE_INCOMPAT_64BIT,
/* R/O compat */
EXT2_FEATURE_RO_COMPAT_LARGE_FILE|
EXT3_FEATURE_INCOMPAT_EXTENTS |
EXT4_FEATURE_INCOMPAT_FLEX_BG |
EXT4_FEATURE_INCOMPAT_EA_INODE|
- EXT4_FEATURE_INCOMPAT_MMP,
+ EXT4_FEATURE_INCOMPAT_MMP|
+ EXT4_FEATURE_INCOMPAT_DIRDATA,
/* R/O compat */
EXT2_FEATURE_RO_COMPAT_LARGE_FILE |
EXT4_FEATURE_RO_COMPAT_HUGE_FILE|
EXT2_FEATURE_INCOMPAT_FILETYPE |
EXT4_FEATURE_INCOMPAT_FLEX_BG |
EXT4_FEATURE_INCOMPAT_EA_INODE|
- EXT4_FEATURE_INCOMPAT_MMP,
+ EXT4_FEATURE_INCOMPAT_MMP|
+ EXT4_FEATURE_INCOMPAT_DIRDATA,
/* R/O compat */
EXT2_FEATURE_RO_COMPAT_LARGE_FILE |
EXT4_FEATURE_RO_COMPAT_HUGE_FILE|