Whamcloud - gitweb
LU-18587 utils: allow large NID lists in mount tools 60/57560/10
authorMikhail Pershin <mpershin@whamcloud.com>
Thu, 19 Dec 2024 22:00:20 +0000 (01:00 +0300)
committerOleg Drokin <green@whamcloud.com>
Sat, 18 Jan 2025 22:05:51 +0000 (22:05 +0000)
While ldd_params are 4096 bytes long a NID lists in params
"failnode" and "mgsnode" are limited by 1024 bytes only.

Patch removes that limitation and allows as many NIDs as
can fit into ldd_params 4k total size

Signed-off-by: Mikhail Pershin <mpershin@whamcloud.com>
Change-Id: I8f3867e0f31c75e6261434d4aef48eaf4e8f4507
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/57560
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: James Simmons <jsimmons@infradead.org>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/include/uapi/linux/lustre/lustre_disk.h
lustre/include/uapi/linux/lustre/lustre_param.h
lustre/tests/conf-sanity.sh
lustre/utils/mount_utils.c

index 8d406b8..75e6fe1 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/types.h>
 #include <linux/uuid.h>
 #include <linux/lnet/lnet-types.h> /* for lnet_nid_t */
+#include <linux/lustre/lustre_param.h>   /* for LDD_PARAM_LEN */
 
 /****************** on-disk files ********************/
 
@@ -76,7 +77,7 @@ struct lustre_disk_data {
        char  ldd_userdata[1024 - 200]; /* arbitrary user string '200' */
        __u8  ldd_padding[4096 - 1024]; /* 1024 */
        char  ldd_mount_opts[4096];     /* target fs mount opts '4096' */
-       char  ldd_params[4096];         /* key=value pairs '8192' */
+       char  ldd_params[LDD_PARAM_LEN];/* key=value pairs '8192' */
 };
 
 /****************** persistent mount data *********************/
index 8b852cf..1714f76 100644 (file)
@@ -49,7 +49,7 @@
 #define PARAM_FAILMODE             "failover.mode="    /* initial mount only */
 #define PARAM_ACTIVE               "active="           /* activate/deactivate */
 #define PARAM_NETWORK              "network="          /* bind on nid */
-#define PARAM_ID_UPCALL                "identity_upcall="  /* identity upcall */
+#define PARAM_ID_UPCALL                   "identity_upcall="  /* identity upcall */
 #define PARAM_ROOTSQUASH          "root_squash="      /* root squash */
 #define PARAM_NOSQUASHNIDS        "nosquash_nids="    /* no squash nids */
 #define PARAM_AUTODEGRADE         "autodegrade="      /* autodegrade OST's */
@@ -73,6 +73,8 @@
 #define PARAM_SEC              "security."
 #define PARAM_QUOTA            "quota."        /* global */
 
+#define LDD_PARAM_LEN          4096
+
 /** @} param */
 
 #endif /* _UAPI_LUSTRE_PARAM_H */
index 63f223f..ccdc71d 100755 (executable)
@@ -6635,20 +6635,56 @@ test_72() { #LU-2634
 }
 run_test 72 "test fast symlink with extents flag enabled"
 
-test_73() { #LU-3006
-       [ "$ost1_FSTYPE" == zfs ] && import_zpool ost1
-       do_facet ost1 "$TUNEFS --failnode=1.2.3.4@$NETTYPE $(ostdevname 1)" ||
+test_73a() { #LU-3006
+       [[ "$ost1_FSTYPE" == zfs ]] && import_zpool ost1
+       local ostdev=$(ostdevname 1)
+
+       do_facet ost1 "$TUNEFS --failnode=1.2.3.4@$NETTYPE $ostdev" ||
                error "1st tunefs failed"
        start_mgsmds || error "start mds failed"
        start_ost || error "start ost failed"
        mount_client $MOUNT || error "mount client failed"
-       $LCTL get_param -n osc.*OST0000-osc-[^M]*.import | grep failover_nids |
-               grep 1.2.3.4@$NETTYPE || error "failover nids haven't changed"
+       $LCTL get_param -n osc.*OST0000-osc-[^M]*.import |
+               grep "failover_nids.*1.2.3.4@$NETTYPE" ||
+               error "failover nids haven't changed"
        umount_client $MOUNT || error "umount client failed"
        stop_ost
+       do_facet ost1 "$TUNEFS --erase-param failover.node $ostdev"
        stop_mds
 }
-run_test 73 "failnode to update from mountdata properly"
+run_test 73a "failnode to update from mountdata properly"
+
+test_73b() {
+       (( $OST1_VERSION >= $(version_code 2.16.50) )) ||
+               skip "need OST >= 2.16.50 for many NID support"
+       [[ "$ost1_FSTYPE" == zfs ]] && import_zpool ost1
+
+       local ostdev=$(ostdevname 1)
+       local nids="111.222.173._@$NETTYPE,111.222.142._@$NETTYPE"
+       local min=160
+       local iter=$((min * 14 / 20))
+
+       do_facet ost1 "$TUNEFS --comment='just a comment for tail' $ostdev" ||
+               error "1st tunefs failed"
+
+       # 4K can fit ~180 IPv4 NIDs, try more for checking failure case too
+       # add in pairs just to reduce test time
+       for ((i = 1; i <= $iter; i++)); do
+               do_facet ost1 "$TUNEFS --failnode=${nids//_/$i} $ostdev" >/dev/null ||
+                       break
+       done
+       echo "added $i/$iter NID failover pairs"
+       # count the actual number of failover NIDs configured in failover.node
+       # there may be some previously configured, so they should also count
+       local count=$(do_facet ost1 $TUNEFS --dryrun $ostdev | grep "^Param" |
+                     sed -e "s/.*failover.node=//" -e "s/[:,]/\n/g" |
+                     grep -c $NETTYPE)
+       do_facet ost1 "$TUNEFS --erase-param failover.node $ostdev"
+
+       # expect to fit more that 160 NIDs at least
+       ((count >= min)) || error "Only $count NIDs configured, need >= $min"
+}
+run_test 73b "Large failnode NID list in mountdata"
 
 # LU-15246
 test_74() {
index bdd4015..d0095b9 100644 (file)
@@ -120,10 +120,12 @@ int run_command(char *cmd, int cmdsz)
        return rc;
 }
 
+#define MAXNIDSTR LDD_PARAM_LEN
+
 #ifdef HAVE_SERVER_SUPPORT
 int add_param(char *buf, char *key, char *val)
 {
-       int end = sizeof(((struct lustre_disk_data *)0)->ldd_params);
+       int end = MAXNIDSTR;
        int start = strlen(buf);
        int keylen = 0;
 
@@ -139,32 +141,11 @@ int add_param(char *buf, char *key, char *val)
        return 0;
 }
 
-int get_param(char *buf, char *key, char **val)
-{
-       int i, key_len = strlen(key);
-       char *ptr;
-
-       ptr = strstr(buf, key);
-       if (ptr) {
-               *val = strdup(ptr + key_len);
-               if (!(*val))
-                       return ENOMEM;
-
-               for (i = 0; i < strlen(*val); i++)
-                       if (((*val)[i] == ' ') || ((*val)[i] == '\0'))
-                               break;
-
-               (*val)[i] = '\0';
-               return 0;
-       }
-
-       return ENOENT;
-}
-
 int append_param(char *buf, char *key, char *val, char sep)
 {
-       int key_len, i, offset, old_val_len;
-       char *ptr = NULL, str[1024];
+       char *ptr = NULL, *next, *cur;
+       int bufsize = MAXNIDSTR;
+       int buflen = strlen(buf), vallen = strlen(val);
 
        if (key)
                ptr = strstr(buf, key);
@@ -173,30 +154,24 @@ int append_param(char *buf, char *key, char *val, char sep)
        if (!ptr)
                return add_param(buf, key, val);
 
-       key_len = strlen(key);
-
-       /* Copy previous values to str */
-       for (i = 0; i < sizeof(str); ++i) {
-               if ((ptr[i + key_len] == ' ') || (ptr[i + key_len] == '\0'))
-                       break;
-               str[i] = ptr[i + key_len];
-       }
-       if (i == sizeof(str))
+       /* check extra new val + sep can fit */
+       if (bufsize <= buflen + vallen + 1) {
+               fprintf(stderr, "%s: params are too long:\n%s +%s=%s\n",
+                       progname, buf, key, val);
                return E2BIG;
-       old_val_len = i;
-
-       offset = old_val_len + key_len;
-
-       /* Move rest of buf to overwrite previous key and value */
-       for (i = 0; ptr[i + offset] != '\0'; ++i)
-               ptr[i] = ptr[i + offset];
+       }
 
-       ptr[i] = '\0';
+       next = strchrnul(ptr, ' ');
+       cur = buf + buflen;
+       /* shift tail further at vallen + sep */
+       while (cur-- > next)
+               *(cur + vallen + 1) = *cur;
 
-       snprintf(str + old_val_len, sizeof(str) - old_val_len,
-                "%c%s", sep, val);
+       /* fill gap with sep + new values */
+       *next = sep;
+       memcpy(next + 1, val, vallen);
 
-       return add_param(buf, key, str);
+       return 0;
 }
 #endif
 
@@ -946,13 +921,12 @@ int file_create(char *path, __u64 size)
 }
 
 /* Get rid of symbolic hostnames for tcp, since kernel can't do lookups */
-#define MAXNIDSTR 1024
-
 char *convert_hostnames(char *buf, bool mount)
 {
        char *converted, *c, *end, sep;
        char *delimiter = buf;
-       int left = MAXNIDSTR;
+       int bufsize = MAXNIDSTR;
+       int left = bufsize;
        struct lnet_nid nid;
 
        converted = malloc(left);
@@ -1008,7 +982,7 @@ char *convert_hostnames(char *buf, bool mount)
                else
                        c += scnprintf(c, left, "%s", libcfs_nidstr(&nid));
 
-               left = converted + MAXNIDSTR - c;
+               left = converted + bufsize - c;
                buf = delimiter + 1;
        }