X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Futils%2Flustre_rsync.c;h=550ffddbf33aa63b500b395258f1cdbb2733a712;hb=refs%2Fchanges%2F15%2F35815%2F2;hp=b12a2d992b6deb6d5ea19a561390b231cdaa8940;hpb=4a0ec1d7621cc42e3139d067969e37b8285f7c06;p=fs%2Flustre-release.git diff --git a/lustre/utils/lustre_rsync.c b/lustre/utils/lustre_rsync.c index b12a2d9..550ffdd 100644 --- a/lustre/utils/lustre_rsync.c +++ b/lustre/utils/lustre_rsync.c @@ -15,11 +15,7 @@ * * 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, 2014, Intel Corporation. + * Copyright (c) 2012, 2017, Intel Corporation. */ /* * This file is part of Lustre, http://www.lustre.org/ @@ -107,6 +103,7 @@ * [pfid,tfid,name] tracked from (1) is used for this. */ +#include #include #include #include @@ -120,13 +117,14 @@ #include #include #include +#include #include +#include #include -#include #include -#include #include "lustre_rsync.h" +#include "callvpe.h" #define REPLICATE_STATUS_VER 1 #define CLEAR_INTERVAL 100 @@ -143,10 +141,6 @@ #define DINFO 1 #define DTRACE 2 -/* Not used; declared for fulfilling obd.c's dependency. */ -command_t cmdlist[0]; -extern int obd_initialize(int argc, char **argv); - /* Information for processing a changelog record. This structure is allocated on the heap instead of allocating large variables on the stack. */ @@ -161,13 +155,12 @@ struct lr_info { char spfid[LR_FID_STR_LEN]; char sname[NAME_MAX + 1]; char name[NAME_MAX + 1]; - char src[PATH_MAX + 1]; - char dest[PATH_MAX + 1]; + char src[3 * PATH_MAX + 1]; + char dest[3 * PATH_MAX + 1]; char path[PATH_MAX + 1]; char savedpath[PATH_MAX + 1]; char link[PATH_MAX + 1]; char linktmp[PATH_MAX + 1]; - char cmd[PATH_MAX]; int bufsize; char *buf; @@ -199,32 +192,32 @@ int quit; /* Flag to stop processing the changelog; set on the receipt of a signal */ int abort_on_err = 0; -char rsync[PATH_MAX]; -char rsync_ver[PATH_MAX]; +char rsync[PATH_MAX + 128]; +char rsync_ver[PATH_MAX * 2]; struct lr_parent_child_list *parents; 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() @@ -241,16 +234,6 @@ void lr_usage() "\t--dry-run don't write anything\n"); } -#define DEBUG_ENTRY(info) \ - lr_debug(D_TRACE, "***** Start %lld %s (%d) %s %s %s *****\n", \ - (info)->recno, changelog_type2str((info)->type), \ - (info)->type, (info)->tfid, (info)->pfid, (info)->name); - -#define DEBUG_EXIT(info, rc) \ - lr_debug(D_TRACE, "##### End %lld %s (%d) %s %s %s rc=%d #####\n", \ - (info)->recno, changelog_type2str((info)->type), \ - (info)->type, (info)->tfid, (info)->pfid, (info)->name, rc); - /* Print debug information. This is controlled by the value of the global variable 'debug' */ void lr_debug(int level, const char *fmt, ...) @@ -283,9 +266,8 @@ void * lr_grow_buf(void *buf, int size) /* Use rsync to replicate file data */ int lr_rsync_data(struct lr_info *info) { - int rc; - struct stat st_src, st_dest; - char cmd[PATH_MAX]; + struct stat st_src, st_dest; + int rc; lr_debug(DTRACE, "Syncing data%s\n", info->tfid); @@ -307,18 +289,28 @@ int lr_rsync_data(struct lr_info *info) if (st_src.st_mtime != st_dest.st_mtime || st_src.st_size != st_dest.st_size) { - /* XXX spawning off an rsync for every data sync and - * waiting synchronously is bad for performance. - * librsync could possibly used here. But it does not - * seem to be of production grade. Multi-threaded - * replication is also to be considered. - */ - int status; - snprintf(cmd, PATH_MAX, "%s --inplace %s %s", rsync, info->src, - info->dest); - lr_debug(DTRACE, "\t%s %s\n", cmd, info->tfid); - status = system(cmd); - if (status == -1) { + /* XXX spawning off an rsync for every data sync and + * waiting synchronously is bad for performance. + * librsync could possibly used here. But it does not + * seem to be of production grade. Multi-threaded + * replication is also to be considered. + */ + char *args[] = { + rsync, + "--inplace", + "--", + info->src, + info->dest, + NULL, + }; + extern char **environ; + int status; + + lr_debug(DTRACE, "\t%s %s %s %s %s %s\n", args[0], args[1], + args[2], args[3], args[4], info->tfid); + + status = callvpe(rsync, args, environ); + if (status < 0) { rc = -errno; } else if (WIFEXITED(status)) { status = WEXITSTATUS(status); @@ -436,7 +428,7 @@ int lr_sync_data(struct lr_info *info) } /* Copy all attributes from file src to file dest */ -int lr_copy_attr(char *src, char *dest) +int lr_copy_attr(const char *src, const char *dest) { struct stat st; struct utimbuf time; @@ -506,9 +498,10 @@ int lr_copy_xattr(struct lr_info *info) rc, errno); if (rc == -1) { if (errno != ENOTSUP) { - fprintf(stderr, "Error replicating " - " xattr for %s: %d\n", - info->dest, errno); + fprintf(stderr, + "cannot replicate xattrs from '%s' to '%s': %s\n", + info->src, info->dest, + strerror(errno)); errors++; } rc = 0; @@ -573,14 +566,15 @@ int lr_get_symlink(struct lr_info *info) strlen(status->ls_source)) == 0) { /* Strip source fs path and replace with target fs path. */ link = info->linktmp + strlen(status->ls_source); - snprintf(info->src, PATH_MAX, "%s%s", + snprintf(info->src, sizeof(info->src), "%s%s", status->ls_targets[info->target_no], link); link = info->src; } else { link = info->linktmp; } - strlcpy(info->link, link, sizeof(info->link)); - + rc = snprintf(info->link, sizeof(info->link), "%s", link); + if (rc >= sizeof(info->link)) + rc = -E2BIG; return rc; } @@ -611,8 +605,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) { @@ -643,13 +642,16 @@ int lr_add_pc(const char *pfid, const char *tfid, const char *name) p = calloc(1, sizeof(*p)); if (p == NULL) return -ENOMEM; - len = strlcpy(p->pc_log.pcl_pfid, pfid, sizeof(p->pc_log.pcl_pfid)); + len = snprintf(p->pc_log.pcl_pfid, sizeof(p->pc_log.pcl_pfid), + "%s", pfid); if (len >= sizeof(p->pc_log.pcl_pfid)) goto out_err; - len = strlcpy(p->pc_log.pcl_tfid, tfid, sizeof(p->pc_log.pcl_tfid)); + len = snprintf(p->pc_log.pcl_tfid, sizeof(p->pc_log.pcl_tfid), + "%s", tfid); if (len >= sizeof(p->pc_log.pcl_tfid)) goto out_err; - len = strlcpy(p->pc_log.pcl_name, name, sizeof(p->pc_log.pcl_name)); + len = snprintf(p->pc_log.pcl_name, sizeof(p->pc_log.pcl_name), + "%s", name); if (len >= sizeof(p->pc_log.pcl_name)) goto out_err; @@ -665,18 +667,22 @@ out_err: void lr_cascade_move(const char *fid, const char *dest, struct lr_info *info) { struct lr_parent_child_list *curr, *prev; - char *d; + char d[4 * PATH_MAX + 1]; int rc; - d = calloc(1, PATH_MAX + 1); prev = curr = parents; while (curr) { if (strcmp(curr->pc_log.pcl_pfid, fid) == 0) { - snprintf(d, PATH_MAX, "%s/%s", dest, - curr->pc_log.pcl_name); - snprintf(info->src, PATH_MAX, "%s/%s/%s", - status->ls_targets[info->target_no], - SPECIAL_DIR, curr->pc_log.pcl_tfid); + if (snprintf(d, sizeof(d), "%s/%s", dest, + curr->pc_log.pcl_name) >= sizeof(d)) { + fprintf(stderr, "Buffer truncated\n"); + return; + } + if (snprintf(info->src, sizeof(info->src), "%s/%s/%s", + status->ls_targets[info->target_no], + SPECIAL_DIR, curr->pc_log.pcl_tfid) >= + sizeof(info->src)) + return; rc = rename(info->src, d); if (rc == -1) { fprintf(stderr, "Error renaming file " @@ -697,8 +703,6 @@ void lr_cascade_move(const char *fid, const char *dest, struct lr_info *info) curr = curr->pc_next; } } - - free(d); } /* remove [info->spfid, info->sfid] from parents */ @@ -725,7 +729,7 @@ int lr_mk_special(struct lr_info *info) { int rc; - snprintf(info->dest, PATH_MAX, "%s/%s/%s", + snprintf(info->dest, sizeof(info->dest), "%s/%s/%s", status->ls_targets[info->target_no], SPECIAL_DIR, info->tfid); @@ -754,14 +758,26 @@ int lr_rmfile(struct lr_info *info) /* Recursively remove directory and its contents */ int lr_rm_recursive(struct lr_info *info) { - int rc; - - snprintf(info->cmd, PATH_MAX, "rm -rf %s", info->dest); - rc = system(info->cmd); - if (rc == -1) - rc = -errno; + char *args[] = { + "rm", + "-rf", + "--", + info->dest, + NULL, + }; + extern char **environ; + int status; + int rc; + + status = callvpe("/bin/rm", args, environ); + if (status < 0) + rc = -errno; + else if (WIFEXITED(status)) + rc = WEXITSTATUS(status) == 0 ? 0 : -EINVAL; + else + rc = -EINTR; - return rc; + return rc; } /* Remove a file under SPECIAL_DIR with its tfid as its name. */ @@ -769,7 +785,7 @@ int lr_rm_special(struct lr_info *info) { int rc; - snprintf(info->dest, PATH_MAX, "%s/%s/%s", + snprintf(info->dest, sizeof(info->dest), "%s/%s/%s", status->ls_targets[info->target_no], SPECIAL_DIR, info->tfid); rc = lr_rmfile(info); @@ -813,11 +829,13 @@ int lr_create(struct lr_info *info) /* Is f2p(pfid)+name != f2p(tfid)? If not the file has moved. */ len = strlen(info->path); if (len == 1 && info->path[0] == '/') - snprintf(info->dest, PATH_MAX, "%s", info->name); + snprintf(info->dest, sizeof(info->dest), "%s", info->name); else if (len - 1 > 0 && info->path[len - 1] == '/') - snprintf(info->dest, PATH_MAX, "%s%s", info->path, info->name); + snprintf(info->dest, sizeof(info->dest), "%s%s", info->path, + info->name); else - snprintf(info->dest, PATH_MAX, "%s/%s", info->path, info->name); + snprintf(info->dest, sizeof(info->dest), "%s/%s", info->path, + info->name); lr_debug(DTRACE, "dest = %s; savedpath = %s\n", info->dest, info->savedpath); @@ -830,8 +848,8 @@ int lr_create(struct lr_info *info) /* Is f2p(pfid) present on the target? If not, the parent has moved */ if (!mkspecial) { - snprintf(info->dest, PATH_MAX, "%s/%s", status->ls_targets[0], - info->path); + snprintf(info->dest, sizeof(info->dest), "%s/%s", + status->ls_targets[0], info->path); if (access(info->dest, F_OK) != 0) { lr_debug(DTRACE, "create: parent %s not found\n", info->dest); @@ -840,10 +858,10 @@ int lr_create(struct lr_info *info) } for (info->target_no = 0; info->target_no < status->ls_num_targets; info->target_no++) { - snprintf(info->dest, PATH_MAX, "%s/%s", + snprintf(info->dest, sizeof(info->dest), "%s/%s", status->ls_targets[info->target_no], info->savedpath); lr_get_FID_PATH(status->ls_source, info->tfid, info->src, - PATH_MAX); + PATH_MAX); if (!mkspecial) rc1 = lr_mkfile(info); @@ -879,7 +897,7 @@ int lr_remove(struct lr_info *info) rc = rc1; continue; } - snprintf(info->dest, PATH_MAX, "%s/%s/%s", + snprintf(info->dest, sizeof(info->dest), "%s/%s/%s", status->ls_targets[info->target_no], info->path, info->name); @@ -907,7 +925,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) @@ -922,21 +940,22 @@ int lr_move(struct lr_info *info) info->target_no++) { if (!rc_dest) { - snprintf(info->dest, PATH_MAX, "%s/%s", + snprintf(info->dest, sizeof(info->dest), "%s/%s", status->ls_targets[info->target_no], info->path); if (access(info->dest, F_OK) != 0) { rc_dest = -errno; } else { - snprintf(info->dest, PATH_MAX, "%s/%s/%s", - status->ls_targets[info->target_no], - info->path, info->name); + snprintf(info->dest, sizeof(info->dest), + "%s/%s/%s", + status->ls_targets[info->target_no], + info->path, info->name); } lr_debug(DINFO, "dest path %s rc_dest=%d\n", info->dest, rc_dest); } if (rc_dest == -ENOENT) { - snprintf(info->dest, PATH_MAX, "%s/%s/%s", + snprintf(info->dest, sizeof(info->dest), "%s/%s/%s", status->ls_targets[info->target_no], SPECIAL_DIR, info->sfid); special_dest = 1; @@ -944,7 +963,7 @@ int lr_move(struct lr_info *info) } if (!rc_src) { - snprintf(info->src, PATH_MAX, "%s/%s/%s", + snprintf(info->src, sizeof(info->src), "%s/%s/%s", status->ls_targets[info->target_no], srcpath, info->sname); lr_debug(DINFO, "src path %s rc_src=%d\n", info->src, @@ -952,7 +971,7 @@ int lr_move(struct lr_info *info) } if (rc_src == -ENOENT || (access(info->src, F_OK) != 0 && errno == ENOENT)) { - snprintf(info->src, PATH_MAX, "%s/%s/%s", + snprintf(info->src, sizeof(info->src), "%s/%s/%s", status->ls_targets[info->target_no], SPECIAL_DIR, info->sfid); special_src = 1; @@ -988,7 +1007,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; @@ -1001,54 +1019,75 @@ 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 */ + for (i = 0; i < st.st_nlink && info->src[0] == 0; i++) { + size_t len; - /* 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++) { 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. + */ + len = sizeof(status->ls_targets[info->target_no]) + + sizeof(info->path); + char srcpath[len + 1]; + + snprintf(srcpath, sizeof(srcpath), "%s/%s", + status->ls_targets[info->target_no], + info->path); + + if (strcmp(srcpath, info->dest) != 0) { + snprintf(info->src, sizeof(info->src), "%s", + srcpath); + 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", + snprintf(info->src, sizeof(info->src), "%s/%s/%s", status->ls_targets[info->target_no], SPECIAL_DIR, info->tfid); else if (info->dest[0] == 0) - snprintf(info->dest, PATH_MAX, "%s/%s/%s", + snprintf(info->dest, sizeof(info->dest), "%s/%s/%s", 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; @@ -1056,6 +1095,30 @@ int lr_link(struct lr_info *info) return rc; } +int lr_set_dest_for_attr(struct lr_info *info) +{ + int rc; + + snprintf(info->dest, sizeof(info->dest), "%s/%s", + status->ls_targets[info->target_no], info->path); + rc = access(info->dest, F_OK); + if (rc < 0) + rc = -errno; + + if (rc != -ENOENT) + return rc; + + snprintf(info->dest, sizeof(info->dest), "%s/%s/%s", + status->ls_targets[info->target_no], SPECIAL_DIR, + info->tfid); + + rc = access(info->dest, F_OK); + if (rc < 0) + return -errno; + + return 0; +} + /* Replicate file attributes */ int lr_setattr(struct lr_info *info) { @@ -1073,9 +1136,10 @@ int lr_setattr(struct lr_info *info) for (info->target_no = 0; info->target_no < status->ls_num_targets; info->target_no++) { + rc = lr_set_dest_for_attr(info); + if (rc < 0) + continue; - snprintf(info->dest, PATH_MAX, "%s/%s", - status->ls_targets[info->target_no], info->path); lr_debug(DINFO, "setattr: %s %s %s", info->src, info->dest, info->tfid); @@ -1104,9 +1168,10 @@ int lr_setxattr(struct lr_info *info) for (info->target_no = 0; info->target_no < status->ls_num_targets; info->target_no++) { + rc = lr_set_dest_for_attr(info); + if (rc < 0) + continue; - snprintf(info->dest, PATH_MAX, "%s/%s", - status->ls_targets[info->target_no], info->path); lr_debug(DINFO, "setxattr: %s %s %s\n", info->src, info->dest, info->tfid); @@ -1138,7 +1203,7 @@ int lr_parse_line(void *priv, struct lr_info *info) namelen = strnlen(changelog_rec_name(rec), rec->cr_namelen); if (copylen > namelen + 1) copylen = namelen + 1; - strlcpy(info->name, changelog_rec_name(rec), copylen); + snprintf(info->name, copylen, "%s", changelog_rec_name(rec)); /* Don't use rnm if CLF_RENAME isn't set */ rnm = changelog_rec_rename(rec); @@ -1152,7 +1217,7 @@ int lr_parse_line(void *priv, struct lr_info *info) namelen = changelog_rec_snamelen(rec); if (copylen > namelen + 1) copylen = namelen + 1; - strlcpy(info->sname, changelog_rec_sname(rec), copylen); + snprintf(info->sname, copylen, "%s", changelog_rec_sname(rec)); if (verbose > 1) printf("Rec %lld: %d %s %s\n", info->recno, info->type, @@ -1192,7 +1257,7 @@ void lr_backup_log() if (logbackedup) return; - snprintf(backupfile, PATH_MAX, "%s.old", statuslog); + snprintf(backupfile, sizeof(backupfile), "%s.old", statuslog); (void) rename(statuslog, backupfile); logbackedup = 1; @@ -1326,20 +1391,24 @@ int lr_read_log() status->ls_last_recno = s->ls_last_recno; if (status->ls_registration[0] == '\0') - strlcpy(status->ls_registration, s->ls_registration, - sizeof(status->ls_registration)); + snprintf(status->ls_registration, + sizeof(status->ls_registration), "%s", + s->ls_registration); if (status->ls_mdt_device[0] == '\0') - strlcpy(status->ls_mdt_device, s->ls_mdt_device, - sizeof(status->ls_mdt_device)); + snprintf(status->ls_mdt_device, + sizeof(status->ls_mdt_device), "%s", + s->ls_mdt_device); if (status->ls_source_fs[0] == '\0') - strlcpy(status->ls_source_fs, s->ls_source_fs, - sizeof(status->ls_source_fs)); + snprintf(status->ls_source_fs, + sizeof(status->ls_source_fs), "%s", + s->ls_source_fs); if (status->ls_source[0] == '\0') - strlcpy(status->ls_source, s->ls_source, - sizeof(status->ls_source)); + snprintf(status->ls_source, + sizeof(status->ls_source), "%s", + s->ls_source); out: if (fd != -1) @@ -1354,37 +1423,33 @@ int lr_read_log() int lr_clear_cl(struct lr_info *info, int force) { char mdt_device[LR_NAME_MAXLEN + 1]; - long long rec; int rc = 0; if (force || info->recno > status->ls_last_recno + CLEAR_INTERVAL) { - if (info->type == CL_RENAME) - rec = info->recno + 1; - else - rec = info->recno; if (!noclear && !dryrun) { /* llapi_changelog_clear modifies the mdt * device name so make a copy of it until this * is fixed. - */ - strlcpy(mdt_device, status->ls_mdt_device, - sizeof(mdt_device)); + */ + snprintf(mdt_device, sizeof(mdt_device), "%s", + status->ls_mdt_device); rc = llapi_changelog_clear(mdt_device, status->ls_registration, - rec); + info->recno); if (rc) - printf("Changelog clear (%s, %s, %lld) " - "returned %d\n", status->ls_mdt_device, - status->ls_registration, rec, rc); - } - if (!rc && !dryrun) { - status->ls_last_recno = rec; - lr_write_log(); + printf("Changelog clear (%s, %s, %lld) " + "returned %d\n", status->ls_mdt_device, + status->ls_registration, info->recno, + rc); + } - } - } + if (!rc && !dryrun) { + status->ls_last_recno = info->recno; + lr_write_log(); + } + } - return rc; + return rc; } /* Locate a usable version of rsync. At this point we'll use any @@ -1395,12 +1460,12 @@ int lr_locate_rsync() int len; /* Locate rsync */ - snprintf(rsync, PATH_MAX, "%s -p %s", TYPE, RSYNC); + snprintf(rsync, sizeof(rsync), "%s -p %s", TYPE, RSYNC); fp = popen(rsync, "r"); if (fp == NULL) return -1; - if (fgets(rsync, PATH_MAX, fp) == NULL) { + if (fgets(rsync, sizeof(rsync), fp) == NULL) { fclose(fp); return -1; } @@ -1411,12 +1476,12 @@ int lr_locate_rsync() fclose(fp); /* Determine the version of rsync */ - snprintf(rsync_ver, PATH_MAX, "%s --version", rsync); + snprintf(rsync_ver, sizeof(rsync_ver), "%s --version", rsync); fp = popen(rsync_ver, "r"); if (fp == NULL) return -1; - if (fgets(rsync_ver, PATH_MAX, fp) == NULL) { + if (fgets(rsync_ver, sizeof(rsync_ver), fp) == NULL) { fclose(fp); return -1; } @@ -1486,9 +1551,18 @@ int lr_replicate() "mountpoint.\n"); goto out; } - if (status->ls_mdt_device[0] == '\0') - snprintf(status->ls_mdt_device, LR_NAME_MAXLEN, "%s%s", - status->ls_source_fs, DEFAULT_MDT); + + if (status->ls_mdt_device[0] == '\0') { + int len; + + len = snprintf(status->ls_mdt_device, + sizeof(status->ls_mdt_device), "%s%s", + status->ls_source_fs, DEFAULT_MDT); + if (len >= sizeof(status->ls_mdt_device)) { + rc = -E2BIG; + goto out; + } + } ext = calloc(1, sizeof(struct lr_info)); if (ext == NULL) { @@ -1497,8 +1571,8 @@ int lr_replicate() } for (i = 0, xattr_not_supp = 0; i < status->ls_num_targets; i++) { - snprintf(info->dest, PATH_MAX, "%s/%s", status->ls_targets[i], - SPECIAL_DIR); + snprintf(info->dest, sizeof(info->dest), "%s/%s", + status->ls_targets[i], SPECIAL_DIR); rc = mkdir(info->dest, 0777); if (rc == -1 && errno != EEXIST) { fprintf(stderr, "Error writing to target path %s.\n", @@ -1521,14 +1595,27 @@ 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 | + CHANGELOG_FLAG_EXTRA_FLAGS, + 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); goto out; } + rc = llapi_changelog_set_xflags(changelog_priv, + CHANGELOG_EXTRA_FLAG_UIDGID | + CHANGELOG_EXTRA_FLAG_NID | + CHANGELOG_EXTRA_FLAG_OMODE | + CHANGELOG_EXTRA_FLAG_XATTR); + if (rc < 0) { + fprintf(stderr, "Error setting xflag in changelog for fs %s.\n", + status->ls_source_fs); + goto out; + } + while (!quit && lr_parse_line(changelog_priv, info) == 0) { rc = 0; if (info->type == CL_RENAME && !info->is_extended) { @@ -1542,15 +1629,20 @@ int lr_replicate() memcpy(info->spfid, info->pfid, sizeof(info->spfid)); memcpy(info->tfid, ext->tfid, sizeof(info->tfid)); memcpy(info->pfid, ext->pfid, sizeof(info->pfid)); - strlcpy(info->sname, info->name, sizeof(info->sname)); - strlcpy(info->name, ext->name, sizeof(info->name)); + snprintf(info->sname, sizeof(info->sname), "%s", + info->name); + snprintf(info->name, sizeof(info->name), "%s", + ext->name); info->is_extended = 1; + info->recno = ext->recno; /* For lr_clear_cl(). */ } if (dryrun) continue; - DEBUG_ENTRY(info); + lr_debug(DTRACE, "***** Start %lld %s (%d) %s %s %s *****\n", + info->recno, changelog_type2str(info->type), + info->type, info->tfid, info->pfid, info->name); switch(info->type) { case CL_CREATE: @@ -1573,12 +1665,14 @@ int lr_replicate() case CL_SETATTR: rc = lr_setattr(info); break; - case CL_XATTR: + case CL_SETXATTR: rc = lr_setxattr(info); break; case CL_CLOSE: case CL_EXT: case CL_OPEN: + case CL_GETXATTR: + case CL_DN_OPEN: case CL_LAYOUT: case CL_MARK: /* Nothing needs to be done for these entries */ @@ -1586,7 +1680,11 @@ int lr_replicate() default: break; } - DEBUG_EXIT(info, rc); + + lr_debug(DTRACE, "##### End %lld %s (%d) %s %s %s rc=%d #####\n", + info->recno, changelog_type2str(info->type), + info->type, info->tfid, info->pfid, info->name, rc); + if (rc && rc != -ENOENT) { lr_print_failure(info, rc); errors++; @@ -1594,10 +1692,6 @@ int lr_replicate() break; } lr_clear_cl(info, 0); - if (debug) { - bzero(info, sizeof(struct lr_info)); - bzero(ext, sizeof(struct lr_info)); - } } llapi_changelog_fini(&changelog_priv); @@ -1650,8 +1744,8 @@ int main(int argc, char *argv[]) break; case 's': /* Assume absolute paths */ - strlcpy(status->ls_source, optarg, - sizeof(status->ls_source)); + snprintf(status->ls_source, sizeof(status->ls_source), + "%s", optarg); break; case 't': status->ls_num_targets++; @@ -1672,16 +1766,18 @@ int main(int argc, char *argv[]) if (status == NULL) return -ENOMEM; } - strlcpy(status->ls_targets[status->ls_num_targets - 1], - optarg, sizeof(status->ls_targets[0])); + snprintf(status->ls_targets[status->ls_num_targets - 1], + sizeof(status->ls_targets[0]), "%s", optarg); break; case 'm': - strlcpy(status->ls_mdt_device, optarg, - sizeof(status->ls_mdt_device)); + snprintf(status->ls_mdt_device, + sizeof(status->ls_mdt_device), + "%s", optarg); break; case 'u': - strlcpy(status->ls_registration, optarg, - sizeof(status->ls_registration)); + snprintf(status->ls_registration, + sizeof(status->ls_registration), + "%s", optarg); break; case 'l': statuslog = optarg; @@ -1771,13 +1867,6 @@ int main(int argc, char *argv[]) return -1; } - /* This plumbing is needed for some of the ioctls behind - llapi calls to work. */ - if (obd_initialize(argc, argv) < 0) { - fprintf(stderr, "obd_initialize failed.\n"); - exit(-1); - } - rc = lr_locate_rsync(); if (use_rsync && rc != 0) { fprintf(stderr, "Error: unable to locate %s.\n", RSYNC);