From: Jian Yu Date: Fri, 15 Apr 2016 07:54:20 +0000 (-0700) Subject: LU-8015 utils: fix lr_link() to get correct src and dest X-Git-Tag: 2.8.53~46 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=a72e6ee375248636cac1ea212d517254c8850b88 LU-8015 utils: fix lr_link() to get correct src and dest The current codes in lr_link() of lustre_rsync.c can not find out the correct info->src and info->dest in the following situations: 1) the source name ends with the destination name 2) the file has two links with the same name but in different directories This patch fixes the above issue by using the path of the parent FID and target name to construct info->dest, and comparing the path of the target FID with info->dest to get the correct info->src. Test-Parameters: testlist=lustre-rsync-test Signed-off-by: Jian Yu Change-Id: Ia92b01c069bde01bd0f094017bd2502292afc7f8 Reviewed-on: http://review.whamcloud.com/19599 Tested-by: Jenkins Tested-by: Maloo Reviewed-by: John L. Hammond Reviewed-by: Jinshan Xiong Reviewed-by: Oleg Drokin --- diff --git a/lustre/tests/lustre-rsync-test.sh b/lustre/tests/lustre-rsync-test.sh index b091763..d27e93d 100644 --- a/lustre/tests/lustre-rsync-test.sh +++ b/lustre/tests/lustre-rsync-test.sh @@ -534,17 +534,18 @@ run_test 5b "Kill / restart lustre_rsync" # Test 6 - lustre_rsync large no of hard links test_6() { - init_src - init_changelog + init_src + init_changelog - local NUMLINKS=128 - touch $DIR/$tdir/link0 - local i=1 - while [ $i -lt $NUMLINKS ]; - do - ln $DIR/$tdir/link0 $DIR/$tdir/link${i} - i=$(expr $i + 1) - done + local num_links=128 + local i + + touch $DIR/$tdir/link0 + for ((i = 1; i < num_links - 1; i++)); do + ln $DIR/$tdir/link0 $DIR/$tdir/link$i + done + # create an extra hard link of src name ending with dest name + ln $DIR/$tdir/link0 $DIR/$tdir/ink0 local LRSYNC_LOG=$(generate_logname "lrsync_log") # Replicate the changes to $TGT @@ -553,15 +554,16 @@ test_6() { check_diff $DIR/$tdir $TGT/$tdir check_diff $DIR/$tdir $TGT2/$tdir - local count1=$(ls -l $TGT/$tdir/link0 | sed -r 's/ +/ /g' | cut -f 2 -d ' ') - local count2=$(ls -l $TGT/$tdir/link0 | sed -r 's/ +/ /g' | cut -f 2 -d ' ') - if [[ $count1 -ne $NUMLINKS ]] || [[ $count2 -ne $NUMLINKS ]]; then - ls -l $TGT/$tdir/link0 $TGT2/$tdir/link0 - error "Incorrect no of hard links found $count1, $count2" - fi - fini_changelog - cleanup_src_tgt - return 0 + local count1=$(stat --format=%h $TGT/$tdir/link0) + local count2=$(stat --format=%h $TGT2/$tdir/link0) + if ((count1 != num_links || count2 != num_links)); then + ls -l $TGT/$tdir/link0 $TGT2/$tdir/link0 + error "Incorrect no of hard links found $count1, $count2" + fi + + fini_changelog + cleanup_src_tgt + return 0 } run_test 6 "lustre_rsync large no of hard links" diff --git a/lustre/utils/lustre_rsync.c b/lustre/utils/lustre_rsync.c index 3e196d5..c3eab0f 100644 --- a/lustre/utils/lustre_rsync.c +++ b/lustre/utils/lustre_rsync.c @@ -989,7 +989,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; @@ -1002,42 +1001,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], @@ -1047,9 +1061,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;