# 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
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"
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;