struct inode *search_inode_for_lustre(struct super_block *sb, const struct lu_fid *fid) { struct ll_sb_info *sbi = ll_s2sbi(sb); struct ptlrpc_request *req = NULL; struct inode *inode = NULL; int eadatalen = 0; unsigned long hash = cl_fid_build_ino(fid, ll_need_32bit_api(sbi)); struct md_op_data *op_data; int rc; CDEBUG(D_INFO, "searching inode for:(%lu,"DFID")\n", hash, PFID(fid)); inode = ilookup5(sb, hash, ll_nfs_test_inode, (void *)fid); if (inode) return inode; rc = ll_get_default_mdsize(sbi, &eadatalen); if (rc) return ERR_PTR(rc); /* Because inode is NULL, ll_prep_md_op_data can not * be used here. So we allocate op_data ourselves */ op_data = kzalloc(sizeof(*op_data), GFP_NOFS); if (!op_data) return ERR_PTR(-ENOMEM); op_data->op_fid1 = *fid; op_data->op_mode = eadatalen; op_data->op_valid = OBD_MD_FLEASIZE; /* mds_fid2dentry ignores f_type */ rc = md_getattr(sbi->ll_md_exp, op_data, &req); kfree(op_data); if (rc) { CERROR("can't get object attrs, fid "DFID", rc %d\n", PFID(fid), rc); return ERR_PTR(rc); } rc = ll_prep_inode(&inode, req, sb, NULL); ptlrpc_req_finished(req); if (rc) return ERR_PTR(rc); return inode; }
int ll_dir_read(struct inode *inode, __u64 *ppos, struct md_op_data *op_data, struct dir_context *ctx) { struct ll_sb_info *sbi = ll_i2sbi(inode); __u64 pos = *ppos; int is_api32 = ll_need_32bit_api(sbi); int is_hash64 = sbi->ll_flags & LL_SBI_64BIT_HASH; struct page *page; bool done = false; int rc = 0; page = ll_get_dir_page(inode, op_data, pos); while (rc == 0 && !done) { struct lu_dirpage *dp; struct lu_dirent *ent; __u64 hash; __u64 next; if (IS_ERR(page)) { rc = PTR_ERR(page); break; } hash = MDS_DIR_END_OFF; dp = page_address(page); for (ent = lu_dirent_start(dp); ent && !done; ent = lu_dirent_next(ent)) { __u16 type; int namelen; struct lu_fid fid; __u64 lhash; __u64 ino; hash = le64_to_cpu(ent->lde_hash); if (hash < pos) /* * Skip until we find target hash * value. */ continue; namelen = le16_to_cpu(ent->lde_namelen); if (namelen == 0) /* * Skip dummy record. */ continue; if (is_api32 && is_hash64) lhash = hash >> 32; else lhash = hash; fid_le_to_cpu(&fid, &ent->lde_fid); ino = cl_fid_build_ino(&fid, is_api32); type = ll_dirent_type_get(ent); ctx->pos = lhash; /* For 'll_nfs_get_name_filldir()', it will try * to access the 'ent' through its 'lde_name', * so the parameter 'name' for 'ctx->actor()' * must be part of the 'ent'. */ done = !dir_emit(ctx, ent->lde_name, namelen, ino, type); } if (done) { pos = hash; ll_release_page(inode, page, false); break; } next = le64_to_cpu(dp->ldp_hash_end); pos = next; if (pos == MDS_DIR_END_OFF) { /* * End of directory reached. */ done = 1; ll_release_page(inode, page, false); } else { /* * Normal case: continue to the next * page. */ ll_release_page(inode, page, le32_to_cpu(dp->ldp_flags) & LDF_COLLIDE); next = pos; page = ll_get_dir_page(inode, op_data, pos); } }