*
* This particular tool can also import an existing HSM archive.
*/
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <dirent.h>
"into a Lustre filesystem.\n"
" Usage:\n"
" %s [options] --import <src> <dst> <lustre_mount_point>\n"
- " import an archived subtree at\n"
- " <src> (relative to hsm_root) into the Lustre filesystem at\n"
- " <dst> (absolute)\n"
+ " import an archived subtree from\n"
+ " <src> (FID or relative path to hsm_root) into the Lustre\n"
+ " filesystem at\n"
+ " <dst> (absolute path)\n"
" %s [options] --rebind <old_FID> <new_FID> <lustre_mount_point>\n"
" rebind an entry in the HSM to a new FID\n"
" <old_FID> old FID the HSM entry is bound to\n"
int rc;
ptr = strdup(path);
+ if (ptr == NULL)
+ return -errno;
+
saved = ptr;
while (*ptr == '/')
ptr++;
rc = fsetxattr(dst_fd, XATTR_LUSTRE_LOV, lovea, lovea_size,
XATTR_CREATE);
if (rc < 0) {
- CT_ERROR(errno, "cannot set lov EA on '%s'", dst);
rc = -errno;
+ CT_ERROR(rc, "cannot set lov EA on '%s'", dst);
}
return rc;
static int ct_fini(struct hsm_copyaction_private **phcp,
const struct hsm_action_item *hai, int hp_flags, int ct_rc)
{
- char lstr[PATH_MAX];
- int rc;
+ struct hsm_copyaction_private *hcp;
+ char lstr[PATH_MAX];
+ int rc;
CT_TRACE("Action completed, notifying coordinator "
"cookie="LPX64", FID="DFID", hp_flags=%d err=%d",
hp_flags, -ct_rc);
ct_path_lustre(lstr, sizeof(lstr), opt.o_mnt, &hai->hai_fid);
+
+ if (phcp == NULL || *phcp == NULL) {
+ rc = llapi_hsm_action_begin(&hcp, ctdata, hai, -1, 0, true);
+ if (rc < 0) {
+ CT_ERROR(rc, "llapi_hsm_action_begin() on '%s' failed",
+ lstr);
+ return rc;
+ }
+ phcp = &hcp;
+ }
+
rc = llapi_hsm_action_end(phcp, &hai->hai_extent, hp_flags, abs(ct_rc));
if (rc == -ECANCELED)
CT_ERROR(rc, "completed action on '%s' has been canceled: "
if (hai->hai_extent.length == -1) {
/* whole file, write it to tmp location and atomically
* replace old archived file */
- strncat(dst, "_tmp", sizeof(dst) - strlen(dst) - 1);
+ strlcat(dst, "_tmp", sizeof(dst));
/* we cannot rely on the same test because ct_copy_data()
* updates hai_extent.length */
rename_needed = true;
src_fd = llapi_hsm_action_get_fd(hcp);
if (src_fd < 0) {
- rc = -errno;
+ rc = src_fd;
CT_ERROR(rc, "cannot open '%s' for read", src);
goto fini_major;
}
if (!(dst_fd < 0))
close(dst_fd);
- if (hcp != NULL)
- rc = ct_fini(&hcp, hai, hp_flags, rcf);
+ rc = ct_fini(&hcp, hai, hp_flags, rcf);
return rc;
}
}
dst_fd = llapi_hsm_action_get_fd(hcp);
+ if (dst_fd < 0) {
+ rc = dst_fd;
+ CT_ERROR(rc, "cannot open '%s' for write", dst);
+ goto fini;
+ }
if (set_lovea) {
/* the layout cannot be allocated through .fid so we have to
CT_TRACE("data restore from '%s' to '%s' done", src, dst);
fini:
- if (hcp != NULL)
- rc = ct_fini(&hcp, hai, hp_flags, rc);
+ rc = ct_fini(&hcp, hai, hp_flags, rc);
/* object swaping is done by cdt at copy end, so close of volatile file
* cannot be done before */
goto fini;
}
- strncat(dst, ".lov", sizeof(dst) - strlen(dst) - 1);
+ strlcat(dst, ".lov", sizeof(dst));
rc = unlink(dst);
if (rc < 0) {
rc = -errno;
}
fini:
- if (hcp != NULL)
- rc = ct_fini(&hcp, hai, 0, rc);
-
- return rc;
-}
-
-static int ct_report_error(const struct hsm_action_item *hai, int flags,
- int errval)
-{
- struct hsm_copyaction_private *hcp;
- int rc;
-
- rc = llapi_hsm_action_begin(&hcp, ctdata, hai, -1, 0, true);
- if (rc < 0)
- return rc;
-
- rc = llapi_hsm_action_end(&hcp, &hai->hai_extent, flags, abs(errval));
+ rc = ct_fini(&hcp, hai, 0, rc);
return rc;
}
CT_ERROR(rc, "unknown action %d, on '%s'", hai->hai_action,
opt.o_mnt);
err_minor++;
- ct_report_error(hai, 0, rc);
+ ct_fini(NULL, hai, 0, rc);
}
return 0;
static char *path_concat(const char *dirname, const char *basename)
{
char *result;
- int dirlen = strlen(dirname);
+ int rc;
- result = malloc(dirlen + strlen(basename) + 2);
- if (result == NULL)
+ rc = asprintf(&result, "%s/%s", dirname, basename);
+ if (rc < 0)
return NULL;
- memcpy(result, dirname, dirlen);
- result[dirlen] = '/';
- strcpy(result + dirlen + 1, basename);
-
return result;
}
+static int ct_import_fid(const lustre_fid *import_fid)
+{
+ char fid_path[PATH_MAX];
+ int rc;
+
+ ct_path_lustre(fid_path, sizeof(fid_path), opt.o_mnt, import_fid);
+ rc = access(fid_path, F_OK);
+ if (rc == 0 || errno != ENOENT) {
+ rc = (errno == 0) ? -EEXIST : -errno;
+ CT_ERROR(rc, "cannot import '"DFID"'", PFID(import_fid));
+ return rc;
+ }
+
+ ct_path_archive(fid_path, sizeof(fid_path), opt.o_hsm_root,
+ import_fid);
+
+ CT_TRACE("Resolving "DFID" to %s", PFID(import_fid), fid_path);
+
+ return ct_import_one(fid_path, opt.o_dst);
+}
+
static int ct_import_recurse(const char *relpath)
{
DIR *dir;
struct dirent ent, *cookie = NULL;
char *srcpath, *newpath;
+ lustre_fid import_fid;
int rc;
if (relpath == NULL)
return -EINVAL;
+ /* Is relpath a FID? In which case SFID should expand to three
+ * elements. */
+ rc = sscanf(relpath, SFID, RFID(&import_fid));
+ if (rc == 3)
+ return ct_import_fid(&import_fid);
+
srcpath = path_concat(opt.o_hsm_root, relpath);
if (srcpath == NULL) {
err_major++;
return -errno;
}
/* rename lov file */
- strncat(src, ".lov", sizeof(src) - strlen(src) - 1);
- strncat(dst, ".lov", sizeof(dst) - strlen(dst) - 1);
+ strlcat(src, ".lov", sizeof(src));
+ strlcat(dst, ".lov", sizeof(dst));
if (rename(src, dst))
- CT_ERROR(errno, "cannot '%s' rename to '%s'", src, dst);
+ CT_ERROR(errno, "cannot rename '%s' to '%s'", src, dst);
}
return 0;
static int ct_max_sequence(void)
{
- int rc, i;
- char path[PATH_MAX];
- __u64 seq = 0;
- __u16 subseq;
+ int rc, i;
+ char path[PATH_MAX];
+ __u64 seq = 0;
+ __u16 subseq;
- strncpy(path, opt.o_hsm_root, sizeof(path));
+ strlcpy(path, opt.o_hsm_root, sizeof(path));
/* FID sequence is stored in top-level directory names:
* hsm_root/16bits (high weight)/16 bits/16 bits/16 bits (low weight).
*/
for (i = 0; i < 4; i++) {
+ size_t path_len;
+
rc = ct_dir_level_max(path, &subseq);
if (rc != 0)
return rc;
seq |= ((__u64)subseq << ((3 - i) * 16));
- sprintf(path + strlen(path), "/%04x", subseq);
+ path_len = strlen(path);
+ rc = snprintf(path + path_len, sizeof(path) - path_len,
+ "/%04x", subseq);
+ if (rc >= (sizeof(path) - path_len))
+ return -E2BIG;
+ path[sizeof(path) - 1] = '\0';
}
- printf("max_sequence: %016Lx\n", seq);
+ printf("max_sequence: "LPX64"\n", seq);
return 0;
}
llapi_error_callback_set(llapi_hsm_log_error);
}
- rc = llapi_hsm_copytool_register(&ctdata, opt.o_mnt, 0,
- opt.o_archive_cnt, opt.o_archive_id);
+ rc = llapi_hsm_copytool_register(&ctdata, opt.o_mnt,
+ opt.o_archive_cnt,
+ opt.o_archive_id, 0);
if (rc < 0) {
CT_ERROR(rc, "cannot start copytool interface");
return rc;
if (rc == -ESHUTDOWN) {
CT_TRACE("shutting down");
break;
- } else if (rc == -EAGAIN) {
- continue; /* msg not for us */
} else if (rc < 0) {
CT_WARN("cannot receive action list: %s",
strerror(-rc));
hal->hal_fsname, hal->hal_archive_id, hal->hal_count);
if (strcmp(hal->hal_fsname, fs_name) != 0) {
- CT_ERROR(EINVAL, "'%s' invalid fs name, expecting: %s",
+ rc = -EINVAL;
+ CT_ERROR(rc, "'%s' invalid fs name, expecting: %s",
hal->hal_fsname, fs_name);
err_major++;
if (opt.o_abort_on_error)
hai = hai_next(hai);
}
- llapi_hsm_action_list_free(&hal);
-
if (opt.o_abort_on_error && err_major)
break;
}
if (rc < 0) {
CT_ERROR(rc, "cannot find a Lustre filesystem mounted at '%s'",
opt.o_mnt);
- return -rc;
+ return rc;
}
return rc;
{
int rc;
- strncpy(cmd_name, basename(argv[0]), sizeof(cmd_name));
+ strlcpy(cmd_name, basename(argv[0]), sizeof(cmd_name));
rc = ct_parseopts(argc, argv);
if (rc < 0) {
CT_WARN("try '%s --help' for more information", cmd_name);
return -rc;
}
- ct_setup();
+ rc = ct_setup();
+ if (rc < 0)
+ goto error_cleanup;
switch (opt.o_action) {
case CA_IMPORT:
" rc=%d (%s)", err_major, err_minor, rc,
strerror(-rc));
+error_cleanup:
ct_cleanup();
return -rc;