/*
* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright (c) 2012, Intel Corporation.
*/
/*
* This file is part of Lustre, http://www.lustre.org/
#include <libcfs/libcfsutil.h>
#include <lustre/lustreapi.h>
+#include <lustre/lustre_idl.h>
#include "lustre_rsync.h"
#define REPLICATE_STATUS_VER 1
char rsync_ver[PATH_MAX];
struct lr_parent_child_list *parents;
+FILE *debug_log;
+
/* Command line options */
struct option long_opts[] = {
{"source", required_argument, 0, 's'},
{"start-recno", required_argument, 0, 'n'},
{"abort-on-err",no_argument, 0, 'a'},
{"debug", required_argument, 0, 'd'},
- {0, 0, 0, 0}
+ {"debuglog", required_argument, 0, 'D'},
+ {0, 0, 0, 0}
};
/* Command line 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, ...)
{
- va_list ap;
+ va_list ap;
- if (level > debug)
- return;
+ if (level > debug)
+ return;
- va_start(ap, fmt);
- vprintf(fmt, ap);
- va_end(ap);
+ va_start(ap, fmt);
+ if (debug_log != NULL)
+ vfprintf(debug_log, fmt, ap);
+ else
+ vfprintf(stdout, fmt, ap);
+ va_end(ap);
}
if (rc1)
rc = rc1;
}
- return rc;
+ return rc;
}
/* Replicate a file remove (rmdir/unlink) operation */
continue;
}
}
- return rc;
+ return rc;
}
/* Replicate a rename/move operation. */
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",
status->ls_targets[info->target_no],
SPECIAL_DIR, info->sfid);
special_dest = 1;
+ lr_debug(DINFO, "special dest %s\n", info->dest);
}
- if (!rc_src)
- snprintf(info->src, PATH_MAX, "%s/%s/%s",
- status->ls_targets[info->target_no],
+ if (!rc_src) {
+ snprintf(info->src, PATH_MAX, "%s/%s/%s",
+ status->ls_targets[info->target_no],
srcpath, info->sname);
+ lr_debug(DINFO, "src path %s rc_src=%d\n", info->src,
+ rc_src);
+ }
if (rc_src == -ENOENT || (access(info->src, F_OK) != 0 &&
errno == ENOENT)) {
snprintf(info->src, PATH_MAX, "%s/%s/%s",
status->ls_targets[info->target_no],
SPECIAL_DIR, info->sfid);
special_src = 1;
+ lr_debug(DINFO, "special src %s\n", info->src);
}
rc1 = 0;
+ errno = 0;
if (strcmp(info->src, info->dest) != 0) {
rc1 = rename(info->src, info->dest);
if (rc1 == -1)
rc1 = -errno;
+ lr_debug(DINFO, "rename returns %d\n", rc1);
}
if (special_src) {
- lr_remove_pc(info->spfid, info->sfid);
+ rc1 = lr_remove_pc(info->spfid, info->sfid);
if (!special_dest)
lr_cascade_move(info->sfid, info->dest, info);
}
if (special_dest)
- lr_add_pc(info->pfid, info->sfid, info->name);
+ rc1 = lr_add_pc(info->pfid, info->sfid, info->name);
lr_debug(DINFO, "move: %s [to] %s rc1=%d, errno=%d\n",
info->src, info->dest, rc1, errno);
if (rc1)
rc = rc1;
}
- return rc;
+ return rc;
}
/* Replicate a hard link */
if (rc1)
rc = rc1;
}
- return rc;
+ return rc;
}
/* Replicate file attributes */
if (rc1)
rc = rc1;
}
- return rc;
+ return rc;
}
/* Replicate xattrs */
rc = rc1;
}
- return rc;
+ return rc;
}
/* Parse a line of changelog entry */
/* Initialize the replication parameters */
int lr_init_status()
{
- size_t size = sizeof(struct lustre_rsync_status) + PATH_MAX;
+ size_t size = sizeof(struct lustre_rsync_status) + PATH_MAX + 1;
if (status != NULL)
return 0;
struct lustre_rsync_status *s;
int fd = -1;
size_t size;
- size_t read_size = sizeof(struct lustre_rsync_status) + PATH_MAX;
+ size_t read_size = sizeof(struct lustre_rsync_status) + PATH_MAX + 1;
int rc = 0;
if (statuslog == NULL)
}
status->ls_num_targets = s->ls_num_targets;
memcpy(status->ls_targets, s->ls_targets,
- PATH_MAX * s->ls_num_targets);
+ (PATH_MAX + 1) * s->ls_num_targets);
}
if (status->ls_last_recno == -1)
status->ls_last_recno = s->ls_last_recno;
if (dryrun)
continue;
+ DEBUG_ENTRY(info);
+
switch(info->type) {
case CL_CREATE:
case CL_MKDIR:
case CL_XATTR:
rc = lr_setxattr(info);
break;
- case CL_CLOSE:
- case CL_EXT:
- case CL_OPEN:
- case CL_IOCTL:
- case CL_MARK:
- /* Nothing needs to be done for these entries */
- default:
- break;
- }
+ case CL_CLOSE:
+ case CL_EXT:
+ case CL_OPEN:
+ case CL_LAYOUT:
+ case CL_MARK:
+ /* Nothing needs to be done for these entries */
+ /* fallthrough */
+ default:
+ break;
+ }
+ DEBUG_EXIT(info, rc);
if (rc && rc != -ENOENT) {
lr_print_failure(info, rc);
errors++;
if ((rc = lr_init_status()) != 0)
return rc;
- while ((rc = getopt_long(argc, argv, "as:t:m:u:l:vx:zc:ry:n:d:",
- long_opts, NULL)) >= 0) {
+ while ((rc = getopt_long(argc, argv, "as:t:m:u:l:vx:zc:ry:n:d:D:",
+ long_opts, NULL)) >= 0) {
switch (rc) {
case 'a':
/* Assume absolute paths */
status->ls_num_targets = numtargets;
}
newsize = sizeof (struct lustre_rsync_status) +
- (status->ls_num_targets * PATH_MAX);
+ (status->ls_num_targets * (PATH_MAX + 1));
if (status->ls_size != newsize) {
status->ls_size = newsize;
status = lr_grow_buf(status, newsize);
if (debug < 0 || debug > 2)
debug = 0;
break;
+ case 'D':
+ /* Undocumented option debug log file */
+ debug_log = fopen(optarg, "a");
+ if (debug_log == NULL) {
+ printf("Cannot open %s for debug log\n",
+ optarg);
+ return -1;
+ }
+ break;
default:
fprintf(stderr, "error: %s: option '%s' "
"unrecognized.\n", argv[0], argv[optind - 1]);
rc = lr_replicate();
- return rc;
+ if (debug_log != NULL)
+ fclose(debug_log);
+ return rc;
}