*
* 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
*/
* 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, 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 <errno.h>
#include <limits.h>
#include <utime.h>
+#include <time.h>
#include <sys/xattr.h>
+#include <linux/types.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
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 */
} 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) {
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)
int lr_link(struct lr_info *info)
{
int i;
- int len;
int rc;
int rc1;
struct stat st;
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],
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;
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)
/* 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);