+ snprintf(strfid, sizeof(strfid), DFID_NOBRACE, PFID(fid));
+
+ rc = llapi_fid2path(mnt, strfid, file, sizeof(file),
+ &recno, &linkno);
+ if (rc < 0)
+ return rc;
+
+ /* fid2path returns a relative path */
+ rc = snprintf(parent, parent_len, "%s/%s", mnt, file);
+ if (rc >= parent_len)
+ return -ENAMETOOLONG;
+
+ /* remove file name */
+ ptr = strrchr(parent, '/');
+ if (ptr == NULL || ptr == parent) {
+ rc = -EINVAL;
+ } else {
+ *ptr = '\0';
+ rc = 0;
+ }
+
+ return rc;
+}
+
+static int ct_open_by_fid(const struct hsm_copytool_private *ct,
+ const struct lu_fid *fid, int open_flags)
+{
+ char fid_name[FID_NOBRACE_LEN + 1];
+
+ snprintf(fid_name, sizeof(fid_name), DFID_NOBRACE, PFID(fid));
+
+ return openat(ct->open_by_fid_fd, fid_name, open_flags);
+}
+
+static int ct_stat_by_fid(const struct hsm_copytool_private *ct,
+ const struct lu_fid *fid,
+ struct stat *buf)
+{
+ char fid_name[FID_NOBRACE_LEN + 1];
+
+ snprintf(fid_name, sizeof(fid_name), DFID_NOBRACE, PFID(fid));
+
+ return fstatat(ct->open_by_fid_fd, fid_name, buf, 0);
+}
+
+/** Create the destination volatile file for a restore operation.
+ *
+ * \param hcp Private copyaction handle.
+ * \param mdt_index MDT index where to create the volatile file.
+ * \param flags Volatile file creation flags.
+ * \return 0 on success.
+ */
+static int create_restore_volatile(struct hsm_copyaction_private *hcp,
+ int mdt_index, int open_flags)
+{
+ int rc;
+ int fd;
+ char parent[PATH_MAX + 1];
+ const char *mnt = hcp->ct_priv->mnt;
+ struct hsm_action_item *hai = &hcp->copy.hc_hai;
+
+ rc = fid_parent(mnt, &hai->hai_fid, parent, sizeof(parent));
+ if (rc < 0) {
+ /* fid_parent() failed, try to keep on going */
+ llapi_error(LLAPI_MSG_ERROR, rc,
+ "cannot get parent path to restore "DFID" "
+ "using '%s'", PFID(&hai->hai_fid), mnt);
+ snprintf(parent, sizeof(parent), "%s", mnt);
+ }
+
+ fd = llapi_create_volatile_idx(parent, mdt_index, open_flags);
+ if (fd < 0)
+ return fd;
+
+ rc = fchown(fd, hcp->stat.st_uid, hcp->stat.st_gid);
+ if (rc < 0)
+ goto err_cleanup;
+
+ rc = llapi_fd2fid(fd, &hai->hai_dfid);
+ if (rc < 0)
+ goto err_cleanup;
+
+ hcp->data_fd = fd;
+
+ return 0;
+
+err_cleanup:
+ hcp->data_fd = -1;
+ close(fd);
+
+ return rc;
+}
+
+/** Start processing an HSM action.