- repbody = req_capsule_server_get(info->mti_pill, &RMF_MDT_BODY);
- repbody->mbo_fid1 = *child_fid;
- repbody->mbo_valid = OBD_MD_FLID;
- mdt_set_disposition(info, ldlm_rep, DISP_LOOKUP_POS);
- } else if (rc == -ENOENT) {
- mdt_set_disposition(info, ldlm_rep, DISP_LOOKUP_NEG);
+ repbody = req_capsule_server_get(info->mti_pill, &RMF_MDT_BODY);
+ repbody->mbo_fid1 = *fid;
+ repbody->mbo_valid = OBD_MD_FLID;
+
+ RETURN(rc);
+}
+
+/**
+ * Find name matching hash
+ *
+ * We search \a child LinkEA for a name whose hash matches \a lname
+ * (it contains an encoded hash).
+ *
+ * \param info mdt thread info
+ * \param lname encoded hash to find
+ * \param parent parent object
+ * \param child object to search with LinkEA
+ * \param force_check true to check hash even if LinkEA has only one entry
+ *
+ * \retval 1 match found
+ * \retval 0 no match found
+ * \retval -ev negative errno upon error
+ */
+int find_name_matching_hash(struct mdt_thread_info *info, struct lu_name *lname,
+ struct mdt_object *parent, struct mdt_object *child,
+ bool force_check)
+{
+ /* Here, lname is an encoded hash of on-disk name, and
+ * client is doing access without encryption key.
+ * So we need to get LinkEA, check parent fid is correct and
+ * compare name hash with the one in the request.
+ */
+ struct lu_buf *buf = &info->mti_big_buf;
+ struct lu_name name;
+ struct lu_fid pfid;
+ struct linkea_data ldata = { NULL };
+ struct link_ea_header *leh;
+ struct link_ea_entry *lee;
+ struct lu_buf link = { 0 };
+ char *hash = NULL;
+ int reclen, count, rc;
+
+ ENTRY;
+
+ if (lname->ln_namelen < LLCRYPT_FNAME_DIGEST_SIZE)
+ RETURN(-EINVAL);
+
+ buf = lu_buf_check_and_alloc(buf, PATH_MAX);
+ if (!buf->lb_buf)
+ RETURN(-ENOMEM);
+
+ ldata.ld_buf = buf;
+ rc = mdt_links_read(info, child, &ldata);
+ if (rc < 0)
+ RETURN(rc);
+
+ leh = buf->lb_buf;
+ if (force_check || leh->leh_reccount > 1) {
+ hash = kmalloc(lname->ln_namelen, GFP_NOFS);
+ if (!hash)
+ RETURN(-ENOMEM);
+ rc = critical_decode(lname->ln_name, lname->ln_namelen, hash);