- offset = (char*) de - addr;
- over = filldir(buf, nbytes, de->name, de->name_len,
- (pgidx << PAGE_CACHE_SHIFT) | offset,
- le32_to_cpu(de->inode), d_type, &filled);
- if (over) {
- free_page(page);
- GOTO(done, 0);
+ if (pos == MDS_DIR_END_OFF)
+ /*
+ * end-of-file.
+ */
+ RETURN(0);
+
+ rc = 0;
+ done = 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 = MDS_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, 0);
+ 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 == MDS_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 {
+ /*
+ * go into overflow page.
+ */