+/**
+ * The data that link search is done on.
+ */
+struct mdd_link_data {
+ /**
+ * Buffer to keep link EA body.
+ */
+ struct lu_buf *ml_buf;
+ /**
+ * The matched header, entry and its lenght in the EA
+ */
+ struct link_ea_header *ml_leh;
+ struct link_ea_entry *ml_lee;
+ int ml_reclen;
+};
+
+static int mdd_links_new(const struct lu_env *env,
+ struct mdd_link_data *ldata)
+{
+ ldata->ml_buf = mdd_buf_alloc(env, CFS_PAGE_SIZE);
+ if (ldata->ml_buf->lb_buf == NULL)
+ return -ENOMEM;
+ ldata->ml_leh = ldata->ml_buf->lb_buf;
+ ldata->ml_leh->leh_magic = LINK_EA_MAGIC;
+ ldata->ml_leh->leh_len = sizeof(struct link_ea_header);
+ ldata->ml_leh->leh_reccount = 0;
+ return 0;
+}
+
+/** Read the link EA into a temp buffer.
+ * Uses the mdd_thread_info::mti_big_buf since it is generally large.
+ * A pointer to the buffer is stored in \a ldata::ml_buf.
+ *
+ * \retval 0 or error
+ */
+int mdd_links_read(const struct lu_env *env,
+ struct mdd_object *mdd_obj,
+ struct mdd_link_data *ldata)
+{
+ struct lustre_capa *capa;
+ struct link_ea_header *leh;
+ int rc;
+
+ /* First try a small buf */
+ LASSERT(env != NULL);
+ ldata->ml_buf = mdd_buf_alloc(env, CFS_PAGE_SIZE);
+ if (ldata->ml_buf->lb_buf == NULL)
+ return -ENOMEM;
+
+ if (!mdd_object_exists(mdd_obj))
+ return -ENODATA;
+
+ capa = mdd_object_capa(env, mdd_obj);
+ rc = mdo_xattr_get(env, mdd_obj, ldata->ml_buf,
+ XATTR_NAME_LINK, capa);
+ if (rc == -ERANGE) {
+ /* Buf was too small, figure out what we need. */
+ mdd_buf_put(ldata->ml_buf);
+ rc = mdo_xattr_get(env, mdd_obj, ldata->ml_buf,
+ XATTR_NAME_LINK, capa);
+ if (rc < 0)
+ return rc;
+ ldata->ml_buf = mdd_buf_alloc(env, rc);
+ if (ldata->ml_buf->lb_buf == NULL)
+ return -ENOMEM;
+ rc = mdo_xattr_get(env, mdd_obj, ldata->ml_buf,
+ XATTR_NAME_LINK, capa);
+ }
+ if (rc < 0)
+ return rc;
+
+ leh = ldata->ml_buf->lb_buf;
+ 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);
+ /* entries are swabbed by mdd_lee_unpack */
+ }
+ if (leh->leh_magic != LINK_EA_MAGIC)
+ return -EINVAL;
+ if (leh->leh_reccount == 0)
+ return -ENODATA;
+
+ ldata->ml_leh = leh;
+ return 0;
+}