Whamcloud - gitweb
LU-6210 utils: Use C99 struct initializer in lustre_rsync.c
[fs/lustre-release.git] / lustre / utils / lustre_rsync.c
index 8fb2734..361d2ad 100644 (file)
  *
  * You should have received a copy of the GNU General Public License
  * version 2 along with this program; If not, see
- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
+ * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * GPL HEADER END
  */
@@ -27,7 +23,7 @@
  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
- * Copyright (c) 2012, Intel Corporation.
+ * Copyright (c) 2012, 2016, Intel Corporation.
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
  *      [pfid,tfid,name] tracked from (1) is used for this.
  */
 
+#include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <getopt.h>
 #include <stdarg.h>
 #include <fcntl.h>
+#include <signal.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <errno.h>
 #include <limits.h>
 #include <utime.h>
+#include <time.h>
 #include <sys/xattr.h>
+#include <linux/types.h>
 
-#include <libcfs/libcfsutil.h>
+#include <libcfs/libcfs_debug.h>
+#include <libcfs/util/string.h>
+#include <libcfs/util/parser.h>
 #include <lustre/lustreapi.h>
-#include <lustre/lustre_idl.h>
 #include "lustre_rsync.h"
 
 #define REPLICATE_STATUS_VER 1
@@ -205,24 +206,24 @@ FILE *debug_log;
 
 /* Command line options */
 struct option long_opts[] = {
-        {"source",      required_argument, 0, 's'},
-        {"target",      required_argument, 0, 't'},
-        {"mdt",         required_argument, 0, 'm'},
-        {"user",        required_argument, 0, 'u'},
-        {"statuslog",   required_argument, 0, 'l'},
-        {"verbose",     no_argument,       0, 'v'},
-        {"xattr",       required_argument, 0, 'x'},
-        {"dry-run",     no_argument,       0, 'z'},
-        /* Undocumented options follow */
-        {"cl-clear",    required_argument, 0, 'c'},
-        {"use-rsync",   no_argument,       0, 'r'},
-        {"rsync-threshold", required_argument, 0, 'y'},
-        {"start-recno", required_argument, 0, 'n'},
-        {"abort-on-err",no_argument,       0, 'a'},
-        {"debug",       required_argument, 0, 'd'},
-       {"debuglog",    required_argument, 0, 'D'},
-       {0, 0, 0, 0}
-};
+       { .val = 'l',   .name = "statuslog",    .has_arg = required_argument },
+       { .val = 'm',   .name = "mdt",          .has_arg = required_argument },
+       { .val = 's',   .name = "source",       .has_arg = required_argument },
+       { .val = 't',   .name = "target",       .has_arg = required_argument },
+       { .val = 'u',   .name = "user",         .has_arg = required_argument },
+       { .val = 'v',   .name = "verbose",      .has_arg = no_argument },
+       { .val = 'x',   .name = "xattr",        .has_arg = required_argument },
+       { .val = 'z',   .name = "dry-run",      .has_arg = no_argument },
+       /* Undocumented options follow */
+       { .val = 'a',   .name = "abort-on-err", .has_arg = no_argument },
+       { .val = 'c',   .name = "cl-clear",     .has_arg = required_argument },
+       { .val = 'd',   .name = "debug",        .has_arg = required_argument },
+       { .val = 'D',   .name = "debuglog",     .has_arg = required_argument },
+       { .val = 'n',   .name = "start-recno",  .has_arg = required_argument },
+       { .val = 'r',   .name = "use-rsync",    .has_arg = no_argument },
+       { .val = 'y',   .name = "rsync-threshold",
+                                               .has_arg = required_argument },
+       { .name = NULL } };
 
 /* Command line usage */
 void lr_usage()
@@ -389,31 +390,39 @@ int lr_copy_data(struct lr_info *info)
                 info->bufsize = bufsize;
         }
 
-        while (1) {
-                rsize = read(fd_src, info->buf, bufsize);
-                if (rsize == 0) {
-                        break;
-                } else if (rsize < 0) {
-                        rc = -errno;
-                        goto out;
-                }
-                errno = 0;
-                if (write(fd_dest, info->buf, rsize) != rsize) {
-                        if (errno != 0)
-                                rc = -errno;
-                        else
-                                rc = -EINTR;
-                }
-        }
-        fsync(fd_dest);
+       while (1) {
+               char *buf;
+               int wsize;
+
+               buf = info->buf;
+               rsize = read(fd_src, buf, bufsize);
+               if (rsize == 0) {
+                       rc = 0;
+                       break;
+               }
+               if (rsize < 0) {
+                       rc = -errno;
+                       break;
+               }
+               do {
+                       wsize = write(fd_dest, buf, rsize);
+                       if (wsize <= 0) {
+                               rc = -errno;
+                               break;
+                       }
+                       rsize -= wsize;
+                       buf += wsize;
+               } while (rsize > 0);
+       }
+       fsync(fd_dest);
 
 out:
-        if (fd_src != -1)
-                close(fd_src);
-        if (fd_dest != -1)
-                close(fd_dest);
+       if (fd_src != -1)
+               close(fd_src);
+       if (fd_dest != -1)
+               close(fd_dest);
 
-        return rc;
+       return rc;
 }
 
 /* Copy data from source to destination */
@@ -601,8 +610,13 @@ int lr_mkfile(struct lr_info *info)
         } else {
                 rc = mknod(info->dest, S_IFREG | 0777, 0);
         }
-        if (rc)
-                return -errno;
+
+       if (rc < 0) {
+               if (errno == EEXIST)
+                       rc = 0;
+               else
+                       return -errno;
+       }
 
         /* Sync data and attributes */
         if (info->type == CL_CREATE || info->type == CL_MKDIR) {
@@ -674,11 +688,11 @@ void lr_cascade_move(const char *fid, const char *dest, struct lr_info *info)
                                         info->src, d, errno);
                                 errors++;
                         }
-                        lr_cascade_move(curr->pc_log.pcl_tfid, d, info);
                         if (curr == parents)
                                 parents = curr->pc_next;
                         else
                                 prev->pc_next = curr->pc_next;
+                       lr_cascade_move(curr->pc_log.pcl_tfid, d, info);
                         free(curr);
                         prev = curr = parents;
 
@@ -897,7 +911,7 @@ int lr_move(struct lr_info *info)
         int special_dest = 0;
        char srcpath[PATH_MAX + 1] = "";
 
-       LASSERT(info->is_extended);
+       assert(info->is_extended);
 
        rc_src = lr_get_path(info, info->spfid);
        if (rc_src < 0 && rc_src != -ENOENT)
@@ -958,12 +972,12 @@ int lr_move(struct lr_info *info)
                        lr_debug(DINFO, "rename returns %d\n", rc1);
                 }
 
-               if (special_src) {
+               if (special_src)
                        rc1 = lr_remove_pc(info->spfid, info->sfid);
-                       if (!special_dest)
-                               lr_cascade_move(info->sfid, info->dest, info);
-                }
-               if (special_dest)
+
+               if (!special_dest)
+                       lr_cascade_move(info->sfid, info->dest, info);
+               else
                        rc1 = lr_add_pc(info->pfid, info->sfid, info->name);
 
                 lr_debug(DINFO, "move: %s [to] %s rc1=%d, errno=%d\n",
@@ -978,7 +992,6 @@ int lr_move(struct lr_info *info)
 int lr_link(struct lr_info *info)
 {
         int i;
-        int len;
         int rc;
         int rc1;
         struct stat st;
@@ -991,42 +1004,57 @@ int lr_link(struct lr_info *info)
         for (info->target_no = 0; info->target_no < status->ls_num_targets;
              info->target_no++) {
 
-                info->src[0] = 0;
-                info->dest[0] = 0;
-                rc1 = 0;
+               info->src[0] = 0;
+               info->dest[0] = 0;
+               rc1 = 0;
+
+               /*
+                * The changelog record has the new parent directory FID and
+                * name of the target file. So info->dest can be constructed
+                * by getting the path of the new parent directory and
+                * appending the target file name.
+                */
+               rc1 = lr_get_path(info, info->pfid);
+               lr_debug(rc1 ? 0 : DTRACE, "\tparent fid2path %s, %s, rc=%d\n",
+                        info->path, info->name, rc1);
+
+               if (rc1 == 0) {
+                       snprintf(info->dest, sizeof(info->dest), "%s/%s/%s",
+                                status->ls_targets[info->target_no],
+                                info->path, info->name);
+                       lr_debug(DINFO, "link destination is %s\n", info->dest);
+               }
 
-                /* Search through the hardlinks to get the src and dest */
-                for (i = 0; i < st.st_nlink && (info->src[0] == 0 ||
-                                                info->dest[0] == 0); i++) {
+               /* Search through the hardlinks to get the src */
+               for (i = 0; i < st.st_nlink && info->src[0] == 0; i++) {
                         rc1 = lr_get_path_ln(info, info->tfid, i);
                         lr_debug(rc1 ? 0:DTRACE, "\tfid2path %s, %s, %d rc=%d\n",
                                  info->path, info->name, i, rc1);
                         if (rc1)
                                 break;
 
-                        len = strlen(info->path) - strlen(info->name);
-                        if (len > 0 && strcmp(info->path + len,
-                                              info->name) == 0)
-                                snprintf(info->dest, PATH_MAX, "%s/%s",
-                                        status->ls_targets[info->target_no],
-                                        info->path);
-                        else if (info->src[0] == 0)
-                                snprintf(info->src, PATH_MAX, "%s/%s",
-                                        status->ls_targets[info->target_no],
-                                        info->path);
-                }
+                       /*
+                        * Compare the path of target FID with info->dest
+                        * to find out info->src.
+                        */
+                       char srcpath[PATH_MAX];
+
+                       snprintf(srcpath, sizeof(srcpath), "%s/%s",
+                                status->ls_targets[info->target_no],
+                                info->path);
+
+                       if (strcmp(srcpath, info->dest) != 0) {
+                               strlcpy(info->src, srcpath, sizeof(info->src));
+                               lr_debug(DINFO, "link source is %s\n",
+                                        info->src);
+                       }
+               }
 
                 if (rc1) {
                         rc = rc1;
                         continue;
                 }
 
-                if (info->src[0] == 0 || info->dest[0] == 0)
-                        /* Could not find the source or destination.
-                         This can happen when some links don't exist
-                         anymore. */
-                        return -EINVAL;
-
                 if (info->src[0] == 0)
                         snprintf(info->src, PATH_MAX, "%s/%s/%s",
                                 status->ls_targets[info->target_no],
@@ -1036,9 +1064,10 @@ int lr_link(struct lr_info *info)
                                 status->ls_targets[info->target_no],
                                 SPECIAL_DIR, info->tfid);
 
-                rc1 = link(info->src, info->dest);
-                lr_debug(rc1?0:DINFO, "link: %s [to] %s; rc1=%d %s\n",
-                         info->src, info->dest, rc1, strerror(errno));
+               rc1 = link(info->src, info->dest);
+               lr_debug(DINFO, "link: %s [to] %s; rc1=%d %s\n",
+                        info->src, info->dest, rc1,
+                        strerror(rc1 ? errno : 0));
 
                 if (rc1)
                         rc = rc1;
@@ -1113,28 +1142,36 @@ int lr_parse_line(void *priv, struct lr_info *info)
 {
        struct changelog_rec            *rec;
        struct changelog_ext_rename     *rnm;
+       size_t                           namelen;
+       size_t                           copylen = sizeof(info->name);
 
-        if (llapi_changelog_recv(priv, &rec) != 0)
-                return -1;
+       if (llapi_changelog_recv(priv, &rec) != 0)
+               return -1;
 
        info->is_extended = !!(rec->cr_flags & CLF_RENAME);
-        info->recno = rec->cr_index;
-        info->type = rec->cr_type;
-        sprintf(info->tfid, DFID, PFID(&rec->cr_tfid));
-        sprintf(info->pfid, DFID, PFID(&rec->cr_pfid));
-       strncpy(info->name, changelog_rec_name(rec), rec->cr_namelen);
-       info->name[rec->cr_namelen] = '\0';
+       info->recno = rec->cr_index;
+       info->type = rec->cr_type;
+       snprintf(info->tfid, sizeof(info->tfid), DFID, PFID(&rec->cr_tfid));
+       snprintf(info->pfid, sizeof(info->pfid), DFID, PFID(&rec->cr_pfid));
+
+       namelen = strnlen(changelog_rec_name(rec), rec->cr_namelen);
+       if (copylen > namelen + 1)
+               copylen = namelen + 1;
+       strlcpy(info->name, changelog_rec_name(rec), copylen);
 
        /* Don't use rnm if CLF_RENAME isn't set */
        rnm = changelog_rec_rename(rec);
        if (rec->cr_flags & CLF_RENAME && !fid_is_zero(&rnm->cr_sfid)) {
+               copylen = sizeof(info->sname);
+
                snprintf(info->sfid, sizeof(info->sfid), DFID,
                         PFID(&rnm->cr_sfid));
                snprintf(info->spfid, sizeof(info->spfid), DFID,
                         PFID(&rnm->cr_spfid));
-               strncpy(info->sname, changelog_rec_sname(rec),
-                       changelog_rec_snamelen(rec));
-               info->sname[changelog_rec_snamelen(rec)] = '\0';
+               namelen = changelog_rec_snamelen(rec);
+               if (copylen > namelen + 1)
+                       copylen = namelen + 1;
+               strlcpy(info->sname, changelog_rec_sname(rec), copylen);
 
                if (verbose > 1)
                        printf("Rec %lld: %d %s %s\n", info->recno, info->type,
@@ -1427,7 +1464,8 @@ void lr_print_status(struct lr_info *info)
         if (statuslog != NULL)
                 printf("Statuslog: %s\n", statuslog);
         printf("Changelog registration: %s\n", status->ls_registration);
-        printf("Starting changelog record: "LPD64"\n", status->ls_last_recno);
+       printf("Starting changelog record: %jd\n",
+              (uintmax_t)status->ls_last_recno);
         if (noxattr)
                 printf("Replicate xattrs: no\n");
         if (noclear)
@@ -1502,8 +1540,8 @@ int lr_replicate()
 
        /* Open changelogs for consumption*/
        rc = llapi_changelog_start(&changelog_priv,
-                                  CHANGELOG_FLAG_BLOCK | CHANGELOG_FLAG_JOBID,
-                                  status->ls_source_fs, status->ls_last_recno);
+                               CHANGELOG_FLAG_BLOCK | CHANGELOG_FLAG_JOBID,
+                               status->ls_mdt_device, status->ls_last_recno);
         if (rc < 0) {
                 fprintf(stderr, "Error opening changelog file for fs %s.\n",
                         status->ls_source_fs);