- if (pos == -1)
- pos = lli->lli_dir_pos;
-
- maxpages = (st->st_size + CFS_PAGE_SIZE - 1) >> CFS_PAGE_SHIFT;
- pgidx = pos >> CFS_PAGE_SHIFT;
- offset = pos & ~CFS_PAGE_MASK;
-
- for ( ; pgidx < maxpages ; pgidx++, offset = 0) {
- struct page *page;
- struct ext2_dirent *de;
- char *addr, *limit;
-
- page = llu_dir_read_page(ino, pgidx);
- if (IS_ERR(page))
- continue;
-
- /* size might have been updated by md_readpage */
- maxpages = (st->st_size + CFS_PAGE_SIZE - 1) >> CFS_PAGE_SHIFT;
-
- /* fill in buffer */
- addr = page->addr;
- limit = addr + CFS_PAGE_SIZE - EXT2_DIR_REC_LEN(1);
- de = (struct ext2_dirent *) (addr + offset);
-
- for ( ; (char*) de <= limit; de = ext2_next_entry(de)) {
- if (de->inode) {
- int over;
- unsigned char d_type = DT_UNKNOWN;
-
- if (de->file_type < EXT2_FT_MAX)
- d_type = ext2_filetype_table[de->file_type];
-
- offset = (char*) de - addr;
- over = filldir(buf, nbytes, de->name, de->name_len,
- (((__u64)pgidx << PAGE_SHIFT) | offset) +
- le16_to_cpu(de->rec_len),
- le32_to_cpu(de->inode), d_type, &filled);
- if (over) {
- free_page(page);
+ if (pos == DIR_END_OFF)
+ /*
+ * end-of-file.
+ */
+ RETURN(0);
+
+ rc = 0;
+ done = 0;
+ shift = 0;
+ ll_dir_chain_init(&chain);
+
+ page = llu_dir_read_page(dir, pos, 0, &chain);
+ while (rc == 0 && !done) {
+ struct lu_dirpage *dp;
+ struct lu_dirent *ent;
+
+ if (!IS_ERR(page)) {
+ /*
+ * If page is empty (end of directoryis reached),
+ * use this value.
+ */
+ __u64 hash = DIR_END_OFF;
+ __u64 next;
+
+ dp = page->addr;
+ for (ent = lu_dirent_start(dp); ent != NULL && !done;
+ ent = lu_dirent_next(ent)) {
+ char *name;
+ int namelen;
+ struct lu_fid fid;
+ __u64 ino;
+
+ hash = le64_to_cpu(ent->lde_hash);
+ namelen = le16_to_cpu(ent->lde_namelen);
+
+ if (hash < pos)
+ /*
+ * Skip until we find target hash
+ * value.
+ */
+ continue;
+
+ if (namelen == 0)
+ /*
+ * Skip dummy record.
+ */
+ continue;
+
+ fid = ent->lde_fid;
+ name = ent->lde_name;
+ fid_le_to_cpu(&fid, &fid);
+ ino = cl_fid_build_ino(&fid);
+ type = ll_dirent_type_get(ent);
+ done = filldir(buf, nbytes, name, namelen,
+ (loff_t)hash, ino, type,
+ &filled);
+ }
+ next = le64_to_cpu(dp->ldp_hash_end);
+ OBD_PAGE_FREE(page);
+ if (!done) {
+ pos = next;
+ if (pos == DIR_END_OFF)
+ /*
+ * End of directory reached.
+ */
+ done = 1;
+ else if (1 /* chain is exhausted*/)
+ /*
+ * Normal case: continue to the next
+ * page.
+ */
+ page = llu_dir_read_page(dir, pos, 1,
+ &chain);
+ else {