From bce2530b91ac7e12620b88a9a4ab698204860531 Mon Sep 17 00:00:00 2001 From: Henri Doreau Date: Mon, 5 Aug 2013 16:01:16 +0200 Subject: [PATCH] LU-3693 utils: Posix copytool fixes. Fixed several defects in the HSM posix copytool. - Fixed two invalid format strings. - Made --daemon optional. - Remove .lov entries from the archive when removing the corresponding files. - When restoring a file for which no LOV EA has been saved we must not create the volatile with O_LOV_DELAY_CREATE. Additionally, the caller should be able to specify the MDT index where to create the volatile file. Added parameters to llapi_hsm_action_begin() accordingly. Signed-off-by: Henri Doreau Change-Id: I7e855b42ef459e453a16c94bfe33e9db885fe2d5 Reviewed-on: http://review.whamcloud.com/7237 Tested-by: Hudson Tested-by: Maloo Reviewed-by: John L. Hammond Reviewed-by: Jinshan Xiong Reviewed-by: Oleg Drokin --- lustre/include/lustre/lustreapi.h | 7 +- lustre/utils/lhsmtool_posix.c | 176 +++++++++++++++++++++++--------------- lustre/utils/liblustreapi_hsm.c | 31 ++++--- 3 files changed, 130 insertions(+), 84 deletions(-) diff --git a/lustre/include/lustre/lustreapi.h b/lustre/include/lustre/lustreapi.h index ea88e07..4ba382e 100644 --- a/lustre/include/lustre/lustreapi.h +++ b/lustre/include/lustre/lustreapi.h @@ -307,11 +307,12 @@ extern int llapi_hsm_copytool_unregister(struct hsm_copytool_private **priv); extern int llapi_hsm_copytool_recv(struct hsm_copytool_private *priv, struct hsm_action_list **hal, int *msgsize); extern void llapi_hsm_action_list_free(struct hsm_action_list **hal); -extern int llapi_hsm_action_begin(struct hsm_copyaction_private **hcp, - const struct hsm_copytool_private *ct_priv, +extern int llapi_hsm_action_begin(struct hsm_copyaction_private **phcp, + const struct hsm_copytool_private *ct, const struct hsm_action_item *hai, + int restore_mdt_index, int restore_open_flags, bool is_error); -extern int llapi_hsm_action_end(struct hsm_copyaction_private **hcp, +extern int llapi_hsm_action_end(struct hsm_copyaction_private **phcp, const struct hsm_extent *he, int flags, int errval); extern int llapi_hsm_action_progress(struct hsm_copyaction_private *hcp, diff --git a/lustre/utils/lhsmtool_posix.c b/lustre/utils/lhsmtool_posix.c index 269a077..c2b4df4 100644 --- a/lustre/utils/lhsmtool_posix.c +++ b/lustre/utils/lhsmtool_posix.c @@ -60,11 +60,11 @@ enum ct_action { 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; @@ -125,7 +125,7 @@ static void usage(const char *name, int rc) "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" @@ -172,7 +172,7 @@ static int ct_parseopts(int argc, char * const *argv) {"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'}, @@ -197,7 +197,7 @@ static int ct_parseopts(int argc, char * const *argv) 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': @@ -222,9 +222,6 @@ static int ct_parseopts(int argc, char * const *argv) else opt.o_bandwidth = value; break; - case 'd': - opt.o_action = CA_DAEMON; - break; case 'h': usage(argv[0], 0); case 'i': @@ -329,10 +326,11 @@ static int ct_mkdir_p(const char *path) 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++; } @@ -357,9 +355,10 @@ static int ct_save_stripe(int src_fd, const char *src, const char *dst) 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; @@ -373,29 +372,36 @@ static int ct_save_stripe(int src_fd, const char *src, const char *dst) 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; @@ -410,41 +416,34 @@ static int ct_load_stripe(const char *src, struct lov_user_md_v3 *lum, 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 */ @@ -552,7 +551,7 @@ static int ct_copy_data(struct hsm_copyaction_private *hcp, const char *src, 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); @@ -648,7 +647,7 @@ static int ct_copy_data(struct hsm_copyaction_private *hcp, const char *src, 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", @@ -787,13 +786,15 @@ static bool ct_is_retryable(int err) 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)); @@ -802,6 +803,14 @@ static int ct_begin(struct hsm_copyaction_private **phcp, 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) { @@ -1064,16 +1073,17 @@ static int ct_restore(const struct hsm_action_item *hai, const long hal_flags) 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 @@ -1082,6 +1092,22 @@ static int ct_restore(const struct hsm_action_item *hai, const long hal_flags) /* 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) { @@ -1110,14 +1136,16 @@ static int ct_restore(const struct hsm_action_item *hai, const long hal_flags) 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); @@ -1174,6 +1202,15 @@ static int ct_remove(const struct hsm_action_item *hai, const long 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); @@ -1187,8 +1224,8 @@ static int ct_report_error(const struct hsm_action_item *hai, int flags, 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)); @@ -1677,15 +1714,17 @@ static void handler(int signal) } /* 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, @@ -1781,7 +1820,7 @@ static int ct_setup(void) } 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; @@ -1809,7 +1848,7 @@ int main(int argc, char **argv) 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; } @@ -1826,13 +1865,8 @@ int main(int argc, char **argv) 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; } diff --git a/lustre/utils/liblustreapi_hsm.c b/lustre/utils/liblustreapi_hsm.c index 751680d..d9867ee 100644 --- a/lustre/utils/liblustreapi_hsm.c +++ b/lustre/utils/liblustreapi_hsm.c @@ -340,10 +340,13 @@ static int fid_parent(const char *mnt, const lustre_fid *fid, char *parent, /** 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; @@ -360,7 +363,7 @@ static int create_restore_volatile(struct hsm_copyaction_private *hcp) 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; @@ -384,17 +387,24 @@ err_cleanup: * 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; @@ -412,7 +422,8 @@ int llapi_hsm_action_begin(struct hsm_copyaction_private **phcp, 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; } -- 1.8.3.1