diff --git a/lustre/llite/dir.c b/lustre/llite/dir.c
index 5b9955ee5e084513ae9860152c60218d3ad27f88..fef5f0f4e012d3010fb3e2d8f64b23bbe8977ef4 100644
--- a/lustre/llite/dir.c
+++ b/lustre/llite/dir.c
@@ -47,32 +47,6 @@
 #include <lustre_dlm.h>
 #include "llite_internal.h"
 
-/*
- * Directory entries are currently in the same format as ext2/ext3, but will
- * be changed in the future to accomodate FIDs
- */
-#define LL_DIR_NAME_LEN (255)
-
-static const int LL_DIR_PAD = 4;
-
-struct ll_dir_entry {
-        /* number of inode, referenced by this entry */
-	__le32	lde_inode;
-        /* total record length, multiple of LL_DIR_PAD */
-	__le16	lde_rec_len;
-        /* length of name */
-	__u8	lde_name_len;
-        /* file type: regular, directory, device, etc. */
-	__u8	lde_file_type;
-        /* name. NOT NUL-terminated */
-	char	lde_name[LL_DIR_NAME_LEN];
-};
-
-static inline unsigned ll_dir_rec_len(unsigned name_len)
-{
-        return (name_len + 8 + LL_DIR_PAD - 1) & ~(LL_DIR_PAD - 1);
-}
-
 #ifndef HAVE_PAGE_CHECKED
 #ifdef HAVE_PG_FS_MISC
 #define PageChecked(page)        test_bit(PG_fs_misc, &(page)->flags)
@@ -165,11 +139,6 @@ static int ll_dir_check_entry(struct inode *dir, struct ll_dir_entry *ent,
         return -EIO;
 }
 
-static inline struct ll_dir_entry *ll_entry_at(void *base, unsigned offset)
-{
-        return (struct ll_dir_entry *)(base + offset);
-}
-
 static void ll_dir_check_page(struct inode *dir, struct page *page)
 {
         int      err;
@@ -283,20 +252,11 @@ out_unlock:
         return page;
 
 fail:
-        kunmap(page);
-        page_cache_release(page);
+        ll_put_page(page);
         page = ERR_PTR(-EIO);
         goto out_unlock;
 }
 
-/*
- * p is at least 6 bytes before the end of page
- */
-static inline struct ll_dir_entry *ll_dir_next_entry(struct ll_dir_entry *p)
-{
-        return ll_entry_at(p, le16_to_cpu(p->lde_rec_len));
-}
-
 static inline unsigned ll_dir_validate_entry(char *base, unsigned offset,
                                              unsigned mask)
 {
@@ -429,8 +389,7 @@ int ll_readdir(struct file *filp, void *dirent, filldir_t filldir)
                 }
                 done = ll_readdir_page(kaddr, idx << CFS_PAGE_SHIFT,
                                        &offset, filldir, dirent);
-                kunmap(page);
-                page_cache_release(page);
+                ll_put_page(page);
                 if (done > 0)
                         /*
                          * Some entries were sent to the user space, return
diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h
index f98f79e30d85575ffc4f45affe93c6a03e577869..65ab7f9c8948e0459519810484e461c41787ca99 100644
--- a/lustre/llite/llite_internal.h
+++ b/lustre/llite/llite_internal.h
@@ -5,7 +5,6 @@
 #ifndef LLITE_INTERNAL_H
 #define LLITE_INTERNAL_H
 
-#include <linux/ext2_fs.h>
 #ifdef CONFIG_FS_POSIX_ACL
 # include <linux/fs.h>
 #ifdef HAVE_XATTR_ACL
@@ -48,6 +47,26 @@ static inline struct lookup_intent *ll_nd2it(struct nameidata *nd)
 }
 #endif
 
+/*
+ * Directory entries are currently in the same format as ext2/ext3, but will
+ * be changed in the future to accomodate FIDs
+ */
+#define LL_DIR_NAME_LEN (255)
+#define LL_DIR_PAD      (4)
+
+struct ll_dir_entry {
+        /* number of inode, referenced by this entry */
+	__le32	lde_inode;
+        /* total record length, multiple of LL_DIR_PAD */
+	__le16	lde_rec_len;
+        /* length of name */
+	__u8	lde_name_len;
+        /* file type: regular, directory, device, etc. */
+	__u8	lde_file_type;
+        /* name. NOT NUL-terminated */
+	char	lde_name[LL_DIR_NAME_LEN];
+};
+
 struct ll_dentry_data {
         int                      lld_cwd_count;
         int                      lld_mnt_count;
@@ -504,27 +523,26 @@ extern struct file_operations ll_dir_operations;
 extern struct inode_operations ll_dir_inode_operations;
 
 struct page *ll_get_dir_page(struct inode *dir, unsigned long n);
-/*
- * p is at least 6 bytes before the end of page
- */
-typedef struct ext2_dir_entry_2 ext2_dirent;
 
-static inline ext2_dirent *ext2_next_entry(ext2_dirent *p)
+static inline unsigned ll_dir_rec_len(unsigned name_len)
 {
-        return (ext2_dirent *)((char*)p + le16_to_cpu(p->rec_len));
+        return (name_len + 8 + LL_DIR_PAD - 1) & ~(LL_DIR_PAD - 1);
 }
 
-static inline unsigned
-ext2_validate_entry(char *base, unsigned offset, unsigned mask)
+static inline struct ll_dir_entry *ll_entry_at(void *base, unsigned offset)
+{
+        return (struct ll_dir_entry *)((char *)base + offset);
+}
+
+/*
+ * p is at least 6 bytes before the end of page
+ */
+static inline struct ll_dir_entry *ll_dir_next_entry(struct ll_dir_entry *p)
 {
-        ext2_dirent *de = (ext2_dirent*)(base + offset);
-        ext2_dirent *p = (ext2_dirent*)(base + (offset&mask));
-        while ((char*)p < (char*)de)
-                p = ext2_next_entry(p);
-        return (char *)p - base;
+        return ll_entry_at(p, le16_to_cpu(p->lde_rec_len));
 }
 
-static inline void ext2_put_page(struct page *page)
+static inline void ll_put_page(struct page *page)
 {
         kunmap(page);
         page_cache_release(page);
diff --git a/lustre/llite/statahead.c b/lustre/llite/statahead.c
index 1e45dd985f6bfd2cbbc89213fd670891d451823f..6262dd08a5b4d9ce046a86a191163215bc74f38f 100644
--- a/lustre/llite/statahead.c
+++ b/lustre/llite/statahead.c
@@ -457,7 +457,7 @@ static inline void ll_name2qstr(struct qstr *this, const char *name, int namelen
         this->hash = end_name_hash(hash);
 }
 
-static int ll_statahead_one(struct dentry *parent, ext2_dirent *de)
+static int ll_statahead_one(struct dentry *parent, struct ll_dir_entry *de)
 {
         struct inode           *dir = parent->d_inode;
         struct ll_inode_info   *lli = ll_i2info(dir);
@@ -483,7 +483,7 @@ static int ll_statahead_one(struct dentry *parent, ext2_dirent *de)
         if (IS_ERR(se))
                 RETURN(PTR_ERR(se));
 
-        ll_name2qstr(&name, de->name, de->name_len);
+        ll_name2qstr(&name, de->lde_name, de->lde_name_len);
         dentry = d_lookup(parent, &name);
         if (!dentry) {
                 dentry = d_alloc(parent, &name);
@@ -569,7 +569,7 @@ static int ll_statahead_thread(void *arg)
                 struct l_wait_info lwi = { 0 };
                 unsigned long npages;
                 char *kaddr, *limit;
-                ext2_dirent *de;
+                struct ll_dir_entry *de;
                 struct page *page;
 
                 npages = dir_pages(dir);
@@ -590,18 +590,18 @@ static int ll_statahead_thread(void *arg)
                 }
 
                 kaddr = page_address(page);
-                limit = kaddr + CFS_PAGE_SIZE - EXT2_DIR_REC_LEN(1);
-                de = (ext2_dirent *)kaddr;
+                limit = kaddr + CFS_PAGE_SIZE - ll_dir_rec_len(1);
+                de = (struct ll_dir_entry *)kaddr;
                 if (!index) {
-                        de = ext2_next_entry(de); /* skip "." */
-                        de = ext2_next_entry(de); /* skip ".." */
+                        de = ll_dir_next_entry(de); /* skip "." */
+                        de = ll_dir_next_entry(de); /* skip ".." */
                 }
 
-                for (; (char*)de <= limit; de = ext2_next_entry(de)) {
-                        if (!de->inode)
+                for (; (char*)de <= limit; de = ll_dir_next_entry(de)) {
+                        if (!de->lde_inode)
                                 continue;
 
-                        if (de->name[0] == '.' && !sai->sai_ls_all) {
+                        if (de->lde_name[0] == '.' && !sai->sai_ls_all) {
                                 /* skip hidden files */
                                 sai->sai_skip_hidden++;
                                 continue;
@@ -618,17 +618,17 @@ static int ll_statahead_thread(void *arg)
                                      &lwi);
 
                         if (unlikely(sa_check_stop(sai))) {
-                                ext2_put_page(page);
+                                ll_put_page(page);
                                 GOTO(out, rc);
                         }
 
                         rc = ll_statahead_one(parent, de);
                         if (rc < 0) {
-                                ext2_put_page(page);
+                                ll_put_page(page);
                                 GOTO(out, rc);
                         }
                 }
-                ext2_put_page(page);
+                ll_put_page(page);
                 index++;
         }
         EXIT;
@@ -698,12 +698,12 @@ enum {
 
 static int is_first_dirent(struct inode *dir, struct dentry *dentry)
 {
-        struct qstr   *d_name = &dentry->d_name;
-        unsigned long  npages, index = 0;
-        struct page   *page;
-        ext2_dirent   *de;
-        char          *kaddr, *limit;
-        int            rc = LS_NONE_FIRST_DE, dot_de;
+        struct qstr         *d_name = &dentry->d_name;
+        unsigned long        npages, index = 0;
+        struct page         *page;
+        struct ll_dir_entry *de;
+        char                *kaddr, *limit;
+        int                  rc = LS_NONE_FIRST_DE, dot_de;
         ENTRY;
 
         while (1) {
@@ -724,18 +724,29 @@ static int is_first_dirent(struct inode *dir, struct dentry *dentry)
                 }
 
                 kaddr = page_address(page);
-                limit = kaddr + CFS_PAGE_SIZE - EXT2_DIR_REC_LEN(1);
-                de = (ext2_dirent *)kaddr;
+                limit = kaddr + CFS_PAGE_SIZE - ll_dir_rec_len(1);
+                de = (struct ll_dir_entry *)kaddr;
                 if (!index) {
-                        de = ext2_next_entry(de); /* skip "." */
-                        de = ext2_next_entry(de); /* skip ".." */
+                        if (unlikely(!(de->lde_name_len == 1 &&
+                                       strncmp(de->lde_name, ".", 1) == 0)))
+                                CWARN("Maybe got bad on-disk dir: %lu\n",
+                                      dir->i_ino);
+                        /* skip "." or ingore bad entry */
+                        de = ll_dir_next_entry(de);
+
+                        if (unlikely(!(de->lde_name_len == 2 &&
+                                       strncmp(de->lde_name, "..", 2) == 0)))
+                                CWARN("Maybe got bad on-disk dir: %lu\n",
+                                      dir->i_ino);
+                        /* skip ".." or ingore bad entry */
+                        de = ll_dir_next_entry(de);
                 }
 
-                for (; (char*)de <= limit; de = ext2_next_entry(de)) {
-                        if (!de->inode)
+                for (; (char*)de <= limit; de = ll_dir_next_entry(de)) {
+                        if (!de->lde_inode)
                                 continue;
 
-                        if (de->name[0] == '.')
+                        if (de->lde_name[0] == '.')
                                 dot_de = 1;
                         else
                                 dot_de = 0;
@@ -743,19 +754,19 @@ static int is_first_dirent(struct inode *dir, struct dentry *dentry)
                         if (dot_de && d_name->name[0] != '.') {
                                 CDEBUG(D_READA, "%.*s skip hidden file %.*s\n",
                                        d_name->len, d_name->name,
-                                       de->name_len, de->name);
+                                       de->lde_name_len, de->lde_name);
                                 continue;
                         }
 
-                        if (d_name->len == de->name_len &&
-                            !strncmp(d_name->name, de->name, d_name->len))
+                        if (d_name->len == de->lde_name_len &&
+                            !strncmp(d_name->name, de->lde_name, d_name->len))
                                 rc = LS_FIRST_DE + dot_de;
                         else
                                 rc = LS_NONE_FIRST_DE;
-                        ext2_put_page(page);
+                        ll_put_page(page);
                         RETURN(rc);
                 }
-                ext2_put_page(page);
+                ll_put_page(page);
                 index++;
         }
         RETURN(rc);