+int mdt_attr_get_pfid(struct mdt_thread_info *info,
+ struct mdt_object *o, struct lu_fid *pfid)
+{
+ struct lu_buf *buf = &info->mti_buf;
+ struct link_ea_header *leh;
+ struct link_ea_entry *lee;
+ int rc;
+ ENTRY;
+
+ buf->lb_buf = info->mti_big_lmm;
+ buf->lb_len = info->mti_big_lmmsize;
+ rc = mo_xattr_get(info->mti_env, mdt_object_child(o),
+ buf, XATTR_NAME_LINK);
+ /* ignore errors, MA_PFID won't be set and it is
+ * up to the caller to treat this as an error */
+ if (rc == -ERANGE || buf->lb_len == 0) {
+ rc = mdt_big_xattr_get(info, o, XATTR_NAME_LINK);
+ buf->lb_buf = info->mti_big_lmm;
+ buf->lb_len = info->mti_big_lmmsize;
+ }
+
+ if (rc < 0)
+ RETURN(rc);
+ if (rc < sizeof(*leh)) {
+ CERROR("short LinkEA on "DFID": rc = %d\n",
+ PFID(mdt_object_fid(o)), rc);
+ RETURN(-ENODATA);
+ }
+
+ leh = (struct link_ea_header *) buf->lb_buf;
+ lee = (struct link_ea_entry *)(leh + 1);
+ if (leh->leh_magic == __swab32(LINK_EA_MAGIC)) {
+ leh->leh_magic = LINK_EA_MAGIC;
+ leh->leh_reccount = __swab32(leh->leh_reccount);
+ leh->leh_len = __swab64(leh->leh_len);
+ }
+ if (leh->leh_magic != LINK_EA_MAGIC)
+ RETURN(-EINVAL);
+ if (leh->leh_reccount == 0)
+ RETURN(-ENODATA);
+
+ memcpy(pfid, &lee->lee_parent_fid, sizeof(*pfid));
+ fid_be_to_cpu(pfid, pfid);
+
+ RETURN(0);
+}
+