CA_IMPORT = 1,
CA_REBIND,
CA_MAXSEQ,
- CA_DAEMON,
};
struct options {
int o_copy_attrs;
+ int o_daemonize;
int o_dry_run;
int o_abort_on_error;
int o_shadow_tree;
"to copy files to and from an HSM archive system.\n"
"This POSIX-flavored daemon makes regular POSIX filesystem calls\n"
"to an HSM mounted at a given hsm_root.\n"
- " -d, --daemon Daemon mode, run in background\n"
+ " --daemon Daemon mode, run in background\n"
" Options:\n"
" --no-attr Don't copy file attributes\n"
" --no-shadow Don't create shadow namespace in archive\n"
{"bandwidth", required_argument, NULL, 'b'},
{"chunk-size", required_argument, NULL, 'c'},
{"chunk_size", required_argument, NULL, 'c'},
- {"daemon", no_argument, NULL, 'd'},
+ {"daemon", no_argument, &opt.o_daemonize, 1},
{"dry-run", no_argument, &opt.o_dry_run, 1},
{"help", no_argument, NULL, 'h'},
{"hsm-root", required_argument, NULL, 'p'},
unsigned long long unit;
optind = 0;
- while ((c = getopt_long(argc, argv, "A:b:c:dhiMp:qruv",
+ while ((c = getopt_long(argc, argv, "A:b:c:hiMp:qrv",
long_opts, NULL)) != -1) {
switch (c) {
case 'A':
else
opt.o_bandwidth = value;
break;
- case 'd':
- opt.o_action = CA_DAEMON;
- break;
case 'h':
usage(argv[0], 0);
case 'i':
rc = mkdir(saved, DIR_PERM);
*ptr = '/';
if (rc < 0 && errno != EEXIST) {
+ rc = -errno;
CT_ERROR("'%s' mkdir failed (%s)\n", path,
- strerror(errno));
+ strerror(-rc));
free(saved);
- return -errno;
+ return rc;
}
ptr++;
}
xattr_size = fgetxattr(src_fd, XATTR_LUSTRE_LOV, lov_buf,
sizeof(lov_buf));
if (xattr_size < 0) {
+ rc = -errno;
CT_ERROR("'%s' cannot get stripe info on (%s)\n", src,
- strerror(errno));
- return -errno;
+ strerror(-rc));
+ return rc;
}
lum = (struct lov_user_md *)lov_buf;
fd = open(lov_file, O_TRUNC | O_CREAT | O_WRONLY, FILE_PERM);
if (fd < 0) {
- CT_ERROR("'%s' cannot open (%s)\n", lov_file, strerror(errno));
- return -errno;
+ rc = -errno;
+ CT_ERROR("'%s' cannot open (%s)\n", lov_file, strerror(-rc));
+ goto err_cleanup;
}
rc = write(fd, lum, xattr_size);
if (rc < 0) {
- CT_ERROR("'%s' cannot write %d bytes (%s)\n",
- lov_file, xattr_size, strerror(errno));
+ rc = -errno;
+ CT_ERROR("'%s' cannot write %zd bytes (%s)\n",
+ lov_file, xattr_size, strerror(-rc));
close(fd);
- return -errno;
+ goto err_cleanup;
}
rc = close(fd);
if (rc < 0) {
- CT_ERROR("'%s' cannot close (%s)\n", lov_file, strerror(errno));
- return -errno;
+ rc = -errno;
+ CT_ERROR("'%s' cannot close (%s)\n", lov_file, strerror(-rc));
+ goto err_cleanup;
}
return 0;
+
+err_cleanup:
+ unlink(lov_file);
+
+ return rc;
}
-static int ct_load_stripe(const char *src, struct lov_user_md_v3 *lum,
- size_t *lum_size)
+static int ct_load_stripe(const char *src, void *lovea, size_t *lovea_size)
{
char lov_file[PATH_MAX];
int rc;
return -ENODATA;
}
- rc = read(fd, lum, *lum_size);
+ rc = read(fd, lovea, *lovea_size);
if (rc < 0) {
- CT_ERROR("'%s' cannot read %lu bytes (%s)\n", lov_file,
- lum_size, strerror(errno));
+ CT_ERROR("'%s' cannot read %zu bytes (%s)\n", lov_file,
+ *lovea_size, strerror(errno));
close(fd);
return -ENODATA;
}
- *lum_size = (size_t)rc;
+ *lovea_size = rc;
close(fd);
return 0;
}
-static int ct_restore_stripe(const char *src, const char *dst, int dst_fd)
+static int ct_restore_stripe(const char *src, const char *dst, int dst_fd,
+ const void *lovea, size_t lovea_size)
{
- int rc;
- char lov_buf[XATTR_SIZE_MAX];
- size_t lum_size = sizeof(lov_buf);
-
- rc = ct_load_stripe(src, (struct lov_user_md_v3 *)lov_buf, &lum_size);
- if (rc) {
- CT_WARN("'%s' cannot get stripe rules (%s), use default\n",
- src, strerror(-rc));
- return 0;
- }
+ int rc;
- rc = fsetxattr(dst_fd, XATTR_LUSTRE_LOV, lov_buf, lum_size, XATTR_CREATE);
+ rc = fsetxattr(dst_fd, XATTR_LUSTRE_LOV, lovea, lovea_size,
+ XATTR_CREATE);
if (rc < 0) {
CT_ERROR("'%s' cannot set striping (%s)\n",
dst, strerror(errno));
- return -errno;
+ rc = -errno;
}
- return 0;
+ return rc;
}
/* non-blocking read or write */
he.offset = hai->hai_extent.offset;
he.length = 0;
rc = llapi_hsm_action_progress(hcp, &he, 0);
- if (rc) {
+ if (rc < 0) {
/* Action has been canceled or something wrong
* is happening. Stop copying data. */
CT_ERROR("%s->'%s' progress returned err %d\n", src, dst, rc);
CT_TRACE("%%"LPU64" ", 100 * wpos / rlen);
he.length = wpos;
rc = llapi_hsm_action_progress(hcp, &he, 0);
- if (rc) {
+ if (rc < 0) {
/* Action has been canceled or something wrong
* is happening. Stop copying data. */
CT_ERROR("%s->'%s' progress returned err %d\n",
return err == -ETIMEDOUT;
}
-static int ct_begin(struct hsm_copyaction_private **phcp,
- const struct hsm_action_item *hai)
+static int ct_begin_restore(struct hsm_copyaction_private **phcp,
+ const struct hsm_action_item *hai,
+ int mdt_index, int open_flags)
{
char src[PATH_MAX];
int rc;
- rc = llapi_hsm_action_begin(phcp, ctdata, hai, false);
+ rc = llapi_hsm_action_begin(phcp, ctdata, hai, mdt_index, open_flags,
+ false);
if (rc < 0) {
ct_path_lustre(src, sizeof(src), opt.o_mnt, &hai->hai_fid);
CT_ERROR("'%s' copy start failed (%s)\n", src, strerror(-rc));
return rc;
}
+static int ct_begin(struct hsm_copyaction_private **phcp,
+ const struct hsm_action_item *hai)
+{
+ /* Restore takes specific parameters. Call the same function w/ default
+ * values for all other operations. */
+ return ct_begin_restore(phcp, hai, -1, 0);
+}
+
static int ct_fini(struct hsm_copyaction_private **phcp,
const struct hsm_action_item *hai, int flags, int ct_rc)
{
struct hsm_copyaction_private *hcp = NULL;
char src[PATH_MAX];
char dst[PATH_MAX];
+ char lov_buf[XATTR_SIZE_MAX];
+ size_t lov_size = sizeof(lov_buf);
int rc;
int flags = 0;
int src_fd = -1;
int dst_fd = -1;
+ int mdt_index = -1; /* Not implemented */
+ int open_flags = 0;
+ bool set_lovea;
lustre_fid dfid;
- rc = ct_begin(&hcp, hai);
- if (rc)
- goto fini;
-
/* we fill lustre so:
* source = lustre FID in the backend
* destination = data FID = volatile file
/* build backend file name from released file FID */
ct_path_archive(src, sizeof(src), opt.o_hsm_root, &hai->hai_fid);
+ /* restore loads and sets the LOVEA w/o interpreting it to avoid
+ * dependency on the structure format. */
+ rc = ct_load_stripe(src, lov_buf, &lov_size);
+ if (rc < 0) {
+ CT_WARN("'%s' cannot get stripe rules (%s), use default\n",
+ src, strerror(-rc));
+ set_lovea = false;
+ } else {
+ open_flags |= O_LOV_DELAY_CREATE;
+ set_lovea = true;
+ }
+
+ rc = ct_begin_restore(&hcp, hai, mdt_index, open_flags);
+ if (rc < 0)
+ goto fini;
+
/* get the FID of the volatile file */
rc = llapi_hsm_action_get_dfid(hcp, &dfid);
if (rc < 0) {
dst_fd = llapi_hsm_action_get_fd(hcp);
- /* the layout cannot be allocated through .fid so we have to
- * restore a layout */
- rc = ct_restore_stripe(src, dst, dst_fd);
- if (rc) {
- CT_ERROR("'%s' cannot restore file striping info from '%s'"
- " (%s)\n", dst, src, strerror(-rc));
- err_major++;
- goto fini;
+ if (set_lovea) {
+ /* the layout cannot be allocated through .fid so we have to
+ * restore a layout */
+ rc = ct_restore_stripe(src, dst, dst_fd, lov_buf, lov_size);
+ if (rc < 0) {
+ CT_ERROR("'%s' cannot restore file striping info from "
+ "'%s' (%s)\n", dst, src, strerror(-rc));
+ err_major++;
+ goto fini;
+ }
}
rc = ct_copy_data(hcp, src, dst, src_fd, dst_fd, hai, hal_flags);
goto fini;
}
+ strncat(dst, ".lov", sizeof(dst) - strlen(dst) - 1);
+ rc = unlink(dst);
+ if (rc < 0) {
+ rc = -errno;
+ CT_ERROR("'%s' unlink failed (%s)\n", dst, strerror(-rc));
+ err_minor++;
+ goto fini;
+ }
+
fini:
if (hcp != NULL)
rc = ct_fini(&hcp, hai, 0, rc);
struct hsm_copyaction_private *hcp;
int rc;
- rc = llapi_hsm_action_begin(&hcp, ctdata, hai, true);
- if (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));
}
/* Daemon waits for messages from the kernel; run it in the background. */
-static int ct_daemon(void)
+static int ct_run(void)
{
int rc;
- rc = daemon(1, 1);
- if (rc < 0) {
- CT_ERROR("%d: cannot start as daemon (%s)", getpid(),
- strerror(errno));
- return -errno;
+ if (opt.o_daemonize) {
+ rc = daemon(1, 1);
+ if (rc < 0) {
+ CT_ERROR("%d: cannot start as daemon (%s)", getpid(),
+ strerror(errno));
+ return -errno;
+ }
}
rc = llapi_hsm_copytool_register(&ctdata, opt.o_mnt, 0,
}
rc = llapi_search_fsname(opt.o_mnt, fs_name);
- if (rc) {
+ if (rc < 0) {
CT_ERROR("cannot find a Lustre filesystem mounted at: %s\n",
opt.o_mnt);
return -rc;
strncpy(cmd_name, basename(argv[0]), sizeof(cmd_name));
rc = ct_parseopts(argc, argv);
- if (rc) {
+ if (rc < 0) {
CT_ERROR("try '%s --help' for more information.\n", cmd_name);
return -rc;
}
case CA_MAXSEQ:
rc = ct_max_sequence();
break;
- case CA_DAEMON:
- rc = ct_daemon();
- break;
default:
- CT_ERROR("no action specified. Try '%s --help' for more "
- "information.\n", cmd_name);
- rc = -EINVAL;
+ rc = ct_run();
break;
}
/** Create the destination volatile file for a restore operation.
*
- * \param hcp Private copyaction handle.
+ * \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)
+static int create_restore_volatile(struct hsm_copyaction_private *hcp,
+ int mdt_index, int flags)
{
int rc;
int fd;
snprintf(parent, sizeof(parent), "%s", mnt);
}
- fd = llapi_create_volatile_idx(parent, 0, O_LOV_DELAY_CREATE);
+ fd = llapi_create_volatile_idx(parent, mdt_index, flags);
if (fd < 0)
return fd;
* It could be skipped if copytool only want to directly report an error,
* \see llapi_hsm_action_end().
*
- * \param hcp Opaque action handle to be passed to
- * llapi_hsm_action_progress and llapi_hsm_action_end.
- * \param ct Copytool handle acquired at registration.
- * \param hai The hsm_action_item describing the request.
- * \param is_error Whether this call is just to report an error.
+ * \param hcp Opaque action handle to be passed to
+ * llapi_hsm_action_progress and llapi_hsm_action_end.
+ * \param ct Copytool handle acquired at registration.
+ * \param hai The hsm_action_item describing the request.
+ * \param restore_mdt_index On restore: MDT index where to create the volatile
+ * file. Use -1 for default.
+ * \param restore_open_flags On restore: volatile file creation mode. Use
+ * O_LOV_DELAY_CREATE to manually set the LOVEA
+ * afterwards.
+ * \param is_error Whether this call is just to report an error.
*
* \return 0 on success.
*/
int llapi_hsm_action_begin(struct hsm_copyaction_private **phcp,
const struct hsm_copytool_private *ct,
- const struct hsm_action_item *hai, bool is_error)
+ const struct hsm_action_item *hai,
+ int restore_mdt_index, int restore_open_flags,
+ bool is_error)
{
struct hsm_copyaction_private *hcp;
int rc;
goto ok_out;
if (hai->hai_action == HSMA_RESTORE) {
- rc = create_restore_volatile(hcp);
+ rc = create_restore_volatile(hcp, restore_mdt_index,
+ restore_open_flags);
if (rc < 0)
goto err_out;
}