Whamcloud - gitweb
LU-3693 utils: Posix copytool fixes. 37/7237/4
authorHenri Doreau <henri.doreau@cea.fr>
Mon, 5 Aug 2013 14:01:16 +0000 (16:01 +0200)
committerOleg Drokin <oleg.drokin@intel.com>
Sat, 17 Aug 2013 05:19:56 +0000 (05:19 +0000)
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 <henri.doreau@cea.fr>
Change-Id: I7e855b42ef459e453a16c94bfe33e9db885fe2d5
Reviewed-on: http://review.whamcloud.com/7237
Tested-by: Hudson
Tested-by: Maloo <whamcloud.maloo@gmail.com>
Reviewed-by: John L. Hammond <john.hammond@intel.com>
Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lustre/include/lustre/lustreapi.h
lustre/utils/lhsmtool_posix.c
lustre/utils/liblustreapi_hsm.c

index ea88e07..4ba382e 100644 (file)
@@ -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,
index 269a077..c2b4df4 100644 (file)
@@ -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;
        }
 
index 751680d..d9867ee 100644 (file)
@@ -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;
        }