+/*
+ * In DNE environment, the object and its name entry may reside on different
+ * MDTs. Under such case, we will create an agent object on the MDT where the
+ * name entry resides. The agent object is empty, and indicates that the real
+ * object for the name entry resides on another MDT. If without agent object,
+ * related name entry will be skipped when perform MDT side file level backup
+ * and restore via ZPL by userspace tool, such as 'tar'.
+ */
+static int osd_create_agent_object(const struct lu_env *env,
+ struct osd_device *osd,
+ struct luz_direntry *zde,
+ uint64_t parent, dmu_tx_t *tx)
+{
+ struct osd_thread_info *info = osd_oti_get(env);
+ struct lustre_mdt_attrs *lma = &info->oti_mdt_attrs;
+ struct lu_attr *la = &info->oti_la;
+ nvlist_t *nvbuf = NULL;
+ dnode_t *dn = NULL;
+ sa_handle_t *hdl;
+ int rc = 0;
+ ENTRY;
+
+ if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_NO_AGENTOBJ))
+ RETURN(0);
+
+ rc = -nvlist_alloc(&nvbuf, NV_UNIQUE_NAME, KM_SLEEP);
+ if (rc)
+ RETURN(rc);
+
+ lustre_lma_init(lma, &zde->lzd_fid, 0, LMAI_AGENT);
+ lustre_lma_swab(lma);
+ rc = -nvlist_add_byte_array(nvbuf, XATTR_NAME_LMA, (uchar_t *)lma,
+ sizeof(*lma));
+ if (rc)
+ GOTO(out, rc);
+
+ la->la_valid = LA_TYPE | LA_MODE;
+ la->la_mode = (DTTOIF(zde->lzd_reg.zde_type) & S_IFMT) |
+ S_IRUGO | S_IWUSR | S_IXUGO;
+
+ if (S_ISDIR(la->la_mode))
+ rc = __osd_zap_create(env, osd, &dn, tx, la,
+ osd_find_dnsize(osd, OSD_BASE_EA_IN_BONUS), 0);
+ else
+ rc = __osd_object_create(env, osd, NULL, &zde->lzd_fid,
+ &dn, tx, la);
+ if (rc)
+ GOTO(out, rc);
+
+ zde->lzd_reg.zde_dnode = dn->dn_object;
+ rc = -sa_handle_get(osd->od_os, dn->dn_object, NULL,
+ SA_HDL_PRIVATE, &hdl);
+ if (!rc) {
+ rc = __osd_attr_init(env, osd, NULL, hdl, tx,
+ la, parent, nvbuf);
+ sa_handle_destroy(hdl);
+ }
+
+ GOTO(out, rc);
+
+out:
+ if (dn) {
+ if (rc)
+ dmu_object_free(osd->od_os, dn->dn_object, tx);
+ osd_dnode_rele(dn);
+ }
+
+ if (nvbuf)
+ nvlist_free(nvbuf);
+
+ return rc;
+}
+