Whamcloud - gitweb
LU-9329 utils: add large xattr support for lustre_rsync.c 97/50997/3
authorLi Xi <lixi@ddn.com>
Mon, 15 May 2023 15:12:00 +0000 (23:12 +0800)
committerOleg Drokin <green@whamcloud.com>
Wed, 31 May 2023 19:15:15 +0000 (19:15 +0000)
lustre_rsync.c had the problem of not able to get the desired
xattr buffer size, thus is not able to support large xattr
(> PATH_MAX).

lustre-rsync-test:1A would fail if /tmp file system on the
test client supports large xattr.

The following lustre_rsync log shows that lgetxattr keeps
on failing on large xattr (user.foo):

(trusted.lma,14307984) rc=0x18
lsetxattr(), rc=0, errno=0
(trusted.lov,14307984) rc=0x38
lsetxattr(), rc=0, errno=0
(trusted.link,14307984) rc=0x2f
lsetxattr(), rc=0, errno=0
(trusted.som,14307984) rc=0x18
lsetxattr(), rc=0, errno=0
(user.foo,14307984) rc=0xffffffff
(lustre.lov,14307984) rc=0x38
lsetxattr(), rc=-1, errno=95

Test-Parameters: trivial testlist=lustre-rsync-test
Signed-off-by: Li Xi <lixi@ddn.com>
Change-Id: I3ff49721b88dd31aa8af76da8932d5004c82ea09
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/50997
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Emoly Liu <emoly@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/tests/lustre-rsync-test.sh
lustre/utils/lustre_rsync.c

index 06c3a21..55eed52 100644 (file)
@@ -85,21 +85,22 @@ cleanup_src_tgt() {
 # "small" - large xattr is unsupported but small xattr is supported
 # "no"    - xattr is unsupported
 check_xattr() {
-    local tgt=$1
-    local xattr="no"
+       local tgt=$1
+       local xattr="no"
 
-    touch $tgt
+       touch $tgt
 
-    local val="$(generate_string $(max_xattr_size))"
-    if large_xattr_enabled &&
-       setfattr -n user.foo -v $val $tgt 2>/dev/null; then
-            xattr="large"
-    else
-        setfattr -n user.foo -v bar $tgt 2>/dev/null && xattr="small"
-    fi
+       local val="$(generate_string $(max_xattr_size))"
 
-    rm -f $tgt
-    echo $xattr
+       if large_xattr_enabled &&
+               setfattr -n user.foo -v $val $tgt 2>/dev/null; then
+               xattr="large"
+       else
+               setfattr -n user.foo -v bar $tgt 2>/dev/null && xattr="small"
+       fi
+
+       rm -f $tgt
+       echo $xattr
 }
 
 check_diff() {
@@ -149,38 +150,38 @@ stop_procs() {
 
 # Test 1A - test basic operations
 test_1A() { # was test_1
-    init_src
-    init_changelog
-    local xattr=$(check_xattr $TGT/foo)
+       init_src
+       init_changelog
+       local xattr=$(check_xattr $TGT/foo)
 
-    # Directory create
-    mkdir $DIR/$tdir/d1
-    mkdir $DIR/$tdir/d2
+       # Directory create
+       mkdir $DIR/$tdir/d1
+       mkdir $DIR/$tdir/d2
 
-    # File create
-    touch $DIR/$tdir/file1
-    cp /etc/hosts  $DIR/$tdir/d1/
-    touch  $DIR/$tdir/d1/"space in filename"
-    touch  $DIR/$tdir/d1/file2
+       # File create
+       touch $DIR/$tdir/file1
+       cp /etc/hosts  $DIR/$tdir/d1/
+       touch $DIR/$tdir/d1/"space in filename"
+       touch $DIR/$tdir/d1/file2
 
-    # File rename
-    mv $DIR/$tdir/d1/file2 $DIR/$tdir/d2/file3
+       # File rename
+       mv $DIR/$tdir/d1/file2 $DIR/$tdir/d2/file3
 
-    # File and directory delete
-    touch $DIR/$tdir/d1/file4
-    mkdir $DIR/$tdir/d1/del
-    touch  $DIR/$tdir/d1/del/del1
-    touch  $DIR/$tdir/d1/del/del2
-    rm -rf $DIR/$tdir/d1/del
-    rm $DIR/$tdir/d1/file4
+       # File and directory delete
+       touch $DIR/$tdir/d1/file4
+       mkdir $DIR/$tdir/d1/del
+       touch $DIR/$tdir/d1/del/del1
+       touch $DIR/$tdir/d1/del/del2
+       rm -rf $DIR/$tdir/d1/del
+       rm $DIR/$tdir/d1/file4
 
-    #hard and soft links
-    cat /etc/hosts > $DIR/$tdir/d1/link1
-    ln  $DIR/$tdir/d1/link1  $DIR/$tdir/d1/link2
-    ln -s $DIR/$tdir/d1/link1  $DIR/$tdir/d1/link3
+       # Hard and soft links
+       cat /etc/hosts > $DIR/$tdir/d1/link1
+       ln $DIR/$tdir/d1/link1  $DIR/$tdir/d1/link2
+       ln -s $DIR/$tdir/d1/link1  $DIR/$tdir/d1/link3
 
-    # Device files
-    #mknod $DIR/$tdir/dev1 b 8 1
+       # Device files
+       #mknod $DIR/$tdir/dev1 b 8 1
 
        # Replicate
        local LRSYNC_LOG=$(generate_logname "lrsync_log")
@@ -188,18 +189,19 @@ test_1A() { # was test_1
        $LRSYNC -s $DIR -t $TGT -t $TGT2 -m $MDT0 -u $CL_USER -l $LREPL_LOG \
                -D $LRSYNC_LOG
 
-    # Set attributes
-    chmod 000 $DIR/$tdir/d2/file3
-    chown nobody:$GROUP $DIR/$tdir/d2/file3
-
-    # Set xattrs
-    if [[ "$xattr" != "no" ]]; then
-        local value
-        touch $DIR/$tdir/file5
-        [[ "$xattr" = "large" ]] &&
-            value="$(generate_string $(max_xattr_size))" || value="bar"
-        setfattr -n user.foo -v $value $DIR/$tdir/file5
-    fi
+       # Set attributes
+       chmod 000 $DIR/$tdir/d2/file3
+       chown nobody:$GROUP $DIR/$tdir/d2/file3
+
+       # Set xattrs
+       if [[ "$xattr" != "no" ]]; then
+               local value
+               touch $DIR/$tdir/file5
+               [[ "$xattr" = "large" ]] &&
+                       value="$(generate_string $(max_xattr_size))" || value="bar"
+               setfattr -n user.foo -v $value $DIR/$tdir/file5 ||
+                       error "setfattr failed"
+       fi
 
        echo "Replication #2"
        $LRSYNC -l $LREPL_LOG -D $LRSYNC_LOG
index b333b77..944ec2e 100644 (file)
@@ -482,16 +482,27 @@ int lr_copy_xattr(struct lr_info *info)
        while (start < len) {
                size = info->xvsize;
                rc = lgetxattr(info->src, info->xlist + start,
-                              info->xvalue, size);
-               if (!info->xvalue || errno == ERANGE) {
-                       size = rc > PATH_MAX ? rc : PATH_MAX;
+                              NULL, 0);
+               if (rc < 0) {
+                       lr_debug(DTRACE, "\t(%s,0) rc=%d, errno=%d\n",
+                                info->xlist + start, rc, errno);
+                       start += strlen(info->xlist + start) + 1;
+                       continue;
+               }
+               if (rc > size) {
+                       /*
+                        * XATTR_SIZE_MAX should be the upper limit, but
+                        * just in case.
+                        */
+                       size = rc > XATTR_SIZE_MAX ? rc : XATTR_SIZE_MAX;
                        info->xvalue = lr_grow_buf(info->xvalue, size);
                        if (!info->xvalue)
                                return -ENOMEM;
                        info->xvsize = size;
-                       rc = lgetxattr(info->src, info->xlist + start,
-                                      info->xvalue, size);
                }
+
+               rc = lgetxattr(info->src, info->xlist + start,
+                              info->xvalue, size);
                lr_debug(DTRACE, "\t(%s,%d) rc=%p\n", info->xlist + start,
                         info->xvalue, rc);
                if (rc > 0) {