"Fossies" - the Fresh Open Source Software Archive

Member "glusterfs-8.2/libglusterfs/src/glusterfs/common-utils.h" (16 Sep 2020, 35876 Bytes) of package /linux/misc/glusterfs-8.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "common-utils.h" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 8.1_vs_8.2.

    1 /*
    2   Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com>
    3   This file is part of GlusterFS.
    4 
    5   This file is licensed to you under your choice of the GNU Lesser
    6   General Public License, version 3 or any later version (LGPLv3 or
    7   later), or the GNU General Public License, version 2 (GPLv2), in all
    8   cases as published by the Free Software Foundation.
    9 */
   10 
   11 #ifndef _COMMON_UTILS_H
   12 #define _COMMON_UTILS_H
   13 
   14 #include <stdint.h>
   15 #include <sys/uio.h>
   16 #include <netdb.h>
   17 #include <stdlib.h>
   18 #include <string.h>
   19 #include <assert.h>
   20 #include <pthread.h>
   21 #include <openssl/md5.h>
   22 #ifndef GF_BSD_HOST_OS
   23 #include <alloca.h>
   24 #endif
   25 #include <limits.h>
   26 #include <fnmatch.h>
   27 #include <uuid/uuid.h>
   28 
   29 #ifndef ffsll
   30 #define ffsll(x) __builtin_ffsll(x)
   31 #endif
   32 
   33 void
   34 trap(void);
   35 
   36 #define GF_UNIVERSAL_ANSWER 42 /* :O */
   37 
   38 /* To solve type punned error */
   39 #define VOID(ptr) ((void **)((void *)ptr))
   40 
   41 #include "glusterfs/mem-pool.h"
   42 #include "glusterfs/compat-uuid.h"
   43 #include "glusterfs/iatt.h"
   44 #include "glusterfs/libglusterfs-messages.h"
   45 
   46 #define STRINGIFY(val) #val
   47 #define TOSTRING(val) STRINGIFY(val)
   48 
   49 #define alloca0(size)                                                          \
   50     ({                                                                         \
   51         void *__ptr;                                                           \
   52         __ptr = alloca(size);                                                  \
   53         memset(__ptr, 0, size);                                                \
   54         __ptr;                                                                 \
   55     })
   56 
   57 #define min(a, b) ((a) < (b) ? (a) : (b))
   58 #define max(a, b) ((a) > (b) ? (a) : (b))
   59 #define gf_roof(a, b) ((((a) + (b)-1) / ((b != 0) ? (b) : 1)) * (b))
   60 #define gf_floor(a, b) (((a) / ((b != 0) ? (b) : 1)) * (b))
   61 
   62 #define IPv4_ADDR_SIZE 32
   63 
   64 #define GF_UNIT_KB 1024ULL
   65 #define GF_UNIT_MB 1048576ULL
   66 #define GF_UNIT_GB 1073741824ULL
   67 #define GF_UNIT_TB 1099511627776ULL
   68 #define GF_UNIT_PB 1125899906842624ULL
   69 
   70 #define GF_UNIT_B_STRING "B"
   71 #define GF_UNIT_KB_STRING "KB"
   72 #define GF_UNIT_MB_STRING "MB"
   73 #define GF_UNIT_GB_STRING "GB"
   74 #define GF_UNIT_TB_STRING "TB"
   75 #define GF_UNIT_PB_STRING "PB"
   76 
   77 #define GF_UNIT_PERCENT_STRING "%"
   78 
   79 #define GEOREP "geo-replication"
   80 #define GLUSTERD_NAME "glusterd"
   81 
   82 #define GF_SELINUX_XATTR_KEY "security.selinux"
   83 
   84 #define WIPE(statp)                                                            \
   85     do {                                                                       \
   86         typeof(*statp) z = {                                                   \
   87             0,                                                                 \
   88         };                                                                     \
   89         if (statp)                                                             \
   90             *statp = z;                                                        \
   91     } while (0)
   92 
   93 #define IS_EXT_FS(fs_name)                                                     \
   94     (!strcmp(fs_name, "ext2") || !strcmp(fs_name, "ext3") ||                   \
   95      !strcmp(fs_name, "ext4"))
   96 
   97 /* process mode definitions */
   98 #define GF_SERVER_PROCESS 0
   99 #define GF_CLIENT_PROCESS 1
  100 #define GF_GLUSTERD_PROCESS 2
  101 
  102 /* Defining this here as it is needed by glusterd for setting
  103  * nfs port in volume status.
  104  */
  105 #define GF_NFS3_PORT 2049
  106 
  107 #define GF_CLIENT_PORT_CEILING 1024
  108 #define GF_IANA_PRIV_PORTS_START 49152 /* RFC 6335 */
  109 #define GF_CLNT_INSECURE_PORT_CEILING (GF_IANA_PRIV_PORTS_START - 1)
  110 #define GF_PORT_MAX 65535
  111 #define GF_PORT_ARRAY_SIZE ((GF_PORT_MAX + 7) / 8)
  112 #define GF_LOCK_TIMER 180
  113 #define GF_MINUTE_IN_SECONDS 60
  114 #define GF_HOUR_IN_SECONDS (60 * 60)
  115 #define GF_DAY_IN_SECONDS (24 * 60 * 60)
  116 #define GF_WEEK_IN_SECONDS (7 * 24 * 60 * 60)
  117 #define GF_SEC_IN_NS 1000000000
  118 #define GF_MS_IN_NS 1000000
  119 #define GF_US_IN_NS 1000
  120 
  121 /* Default timeout for both barrier and changelog translator */
  122 #define BARRIER_TIMEOUT "120"
  123 
  124 /* Default value of signing waiting time to sign a file for bitrot */
  125 #define SIGNING_TIMEOUT "120"
  126 #define BR_WORKERS "4"
  127 
  128 /* xxhash */
  129 #define GF_XXH64_DIGEST_LENGTH 8
  130 #define GF_XXHSUM64_DEFAULT_SEED 0
  131 
  132 /* Shard */
  133 #define GF_XATTR_SHARD_FILE_SIZE "trusted.glusterfs.shard.file-size"
  134 #define SHARD_ROOT_GFID "be318638-e8a0-4c6d-977d-7a937aa84806"
  135 #define DOT_SHARD_REMOVE_ME_GFID "77dd5a45-dbf5-4592-b31b-b440382302e9"
  136 
  137 /* Lease: buffer length for stringified lease id
  138  * Format: 4hexnum-4hexnum-4hexnum-4hexnum-4hexnum-4hexnum-4hexnum-4hexnum
  139  * Eg:6c69-6431-2d63-6c6e-7431-0000-0000-0000
  140  */
  141 #define GF_LEASE_ID_BUF_SIZE ((LEASE_ID_SIZE * 2) + (LEASE_ID_SIZE / 2))
  142 
  143 #define GF_PERCENTAGE(val, total) (((val)*100) / (total))
  144 
  145 /* pthread related */
  146 /* as per the man page, thread-name should be at max 16 bytes */
  147 /* with prefix of 'glfs_' (5), we are left with 11 more bytes */
  148 #define GF_THREAD_NAME_LIMIT 16
  149 #define GF_THREAD_NAME_PREFIX "glfs_"
  150 
  151 /*
  152  * we could have initialized these as +ve values and treated
  153  * them as negative while comparing etc.. (which would have
  154  * saved us with the pain of assigning values), but since we
  155  * only have a few clients that use this feature, it's okay.
  156  */
  157 enum _gf_special_pid {
  158     GF_CLIENT_PID_MAX = 0,
  159     GF_CLIENT_PID_GSYNCD = -1,
  160     GF_CLIENT_PID_HADOOP = -2,
  161     GF_CLIENT_PID_DEFRAG = -3,
  162     GF_CLIENT_PID_NO_ROOT_SQUASH = -4,
  163     GF_CLIENT_PID_QUOTA_MOUNT = -5,
  164     GF_CLIENT_PID_SELF_HEALD = -6,
  165     GF_CLIENT_PID_GLFS_HEAL = -7,
  166     GF_CLIENT_PID_BITD = -8,
  167     GF_CLIENT_PID_SCRUB = -9,
  168     GF_CLIENT_PID_TIER_DEFRAG = -10,
  169     GF_SERVER_PID_TRASH = -11,
  170     GF_CLIENT_PID_ADD_REPLICA_MOUNT = -12,
  171     GF_CLIENT_PID_SET_UTIME = -13,
  172 };
  173 
  174 enum _gf_xlator_ipc_targets {
  175     GF_IPC_TARGET_CHANGELOG = 0,
  176     GF_IPC_TARGET_CTR = 1,
  177     GF_IPC_TARGET_UPCALL = 2
  178 };
  179 
  180 typedef enum _gf_special_pid gf_special_pid_t;
  181 typedef enum _gf_xlator_ipc_targets _gf_xlator_ipc_targets_t;
  182 
  183 /* The DHT file rename operation is not a straightforward rename.
  184  * It involves creating linkto and linkfiles, and can unlink or rename the
  185  * source file depending on the hashed and cached subvols for the source
  186  * and target files. this makes it difficult for geo-rep to figure out that
  187  * a rename operation has taken place.
  188  *
  189  * We now send a special key and the values of the source and target pargfids
  190  * and basenames to indicate to changelog that the operation in question
  191  * should be treated as a rename. We are explicitly filling and sending this
  192  * as a binary value in the dictionary as the unlink op will not have the
  193  * source file information. The lengths of the src and target basenames
  194  * are used to calculate where to start reading the names in the structure.
  195  * XFS allows a max of 255 chars for filenames but other file systems might
  196  * not have such restrictions
  197  */
  198 typedef struct dht_changelog_rename_info {
  199     uuid_t old_pargfid;
  200     uuid_t new_pargfid;
  201     int32_t oldname_len;
  202     int32_t newname_len;
  203     char buffer[1];
  204 } dht_changelog_rename_info_t;
  205 
  206 typedef int (*gf_cmp)(void *, void *);
  207 
  208 struct _dict;
  209 
  210 struct dnscache {
  211     struct _dict *cache_dict;
  212     time_t ttl;
  213 };
  214 
  215 struct dnscache_entry {
  216     char *ip;
  217     char *fqdn;
  218     time_t timestamp;
  219 };
  220 
  221 struct dnscache6 {
  222     struct addrinfo *first;
  223     struct addrinfo *next;
  224 };
  225 
  226 struct list_node {
  227     void *ptr;
  228     struct list_head list;
  229 };
  230 
  231 extern char *vol_type_str[];
  232 
  233 struct list_node *
  234 list_node_add(void *ptr, struct list_head *list);
  235 struct list_node *
  236 list_node_add_order(void *ptr, struct list_head *list,
  237                     int (*compare)(struct list_head *, struct list_head *));
  238 void
  239 list_node_del(struct list_node *node);
  240 
  241 struct dnscache *
  242 gf_dnscache_init(time_t ttl);
  243 void
  244 gf_dnscache_deinit(struct dnscache *cache);
  245 struct dnscache_entry *
  246 gf_dnscache_entry_init(void);
  247 void
  248 gf_dnscache_entry_deinit(struct dnscache_entry *entry);
  249 char *
  250 gf_rev_dns_lookup_cached(const char *ip, struct dnscache *dnscache);
  251 
  252 char *
  253 gf_resolve_path_parent(const char *path);
  254 
  255 void
  256 gf_global_variable_init(void);
  257 
  258 int32_t
  259 gf_resolve_ip6(const char *hostname, uint16_t port, int family, void **dnscache,
  260                struct addrinfo **addr_info);
  261 
  262 void
  263 gf_log_dump_graph(FILE *specfp, glusterfs_graph_t *graph);
  264 void
  265 gf_print_trace(int32_t signal, glusterfs_ctx_t *ctx);
  266 int
  267 gf_set_log_file_path(cmd_args_t *cmd_args, glusterfs_ctx_t *ctx);
  268 int
  269 gf_set_log_ident(cmd_args_t *cmd_args);
  270 
  271 int
  272 gf_process_getspec_servers_list(cmd_args_t *cmd_args, const char *servers_list);
  273 int
  274 gf_set_volfile_server_common(cmd_args_t *cmd_args, const char *host,
  275                              const char *transport, int port);
  276 
  277 static inline void
  278 BIT_SET(unsigned char *array, unsigned int index)
  279 {
  280     unsigned int offset = index / 8;
  281     unsigned int shift = index % 8;
  282 
  283     array[offset] |= (1 << shift);
  284 }
  285 
  286 static inline void
  287 BIT_CLEAR(unsigned char *array, unsigned int index)
  288 {
  289     unsigned int offset = index / 8;
  290     unsigned int shift = index % 8;
  291 
  292     array[offset] &= ~(1 << shift);
  293 }
  294 
  295 static inline unsigned int
  296 BIT_VALUE(unsigned char *array, unsigned int index)
  297 {
  298     unsigned int offset = index / 8;
  299     unsigned int shift = index % 8;
  300 
  301     return (array[offset] >> shift) & 0x1;
  302 }
  303 
  304 #define VECTORSIZE(count) (count * (sizeof(struct iovec)))
  305 
  306 #define STRLEN_0(str) (strlen(str) + 1)
  307 
  308 #define VALIDATE_OR_GOTO(arg, label)                                           \
  309     do {                                                                       \
  310         if (!arg) {                                                            \
  311             errno = EINVAL;                                                    \
  312             gf_msg_callingfn((this ? (this->name) : "(Govinda! Govinda!)"),    \
  313                              GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,       \
  314                              "invalid argument: " #arg);                       \
  315             goto label;                                                        \
  316         }                                                                      \
  317     } while (0)
  318 
  319 #define GF_VALIDATE_OR_GOTO(name, arg, label)                                  \
  320     do {                                                                       \
  321         if (!arg) {                                                            \
  322             errno = EINVAL;                                                    \
  323             gf_msg_callingfn(name, GF_LOG_ERROR, errno, LG_MSG_INVALID_ARG,    \
  324                              "invalid argument: " #arg);                       \
  325             goto label;                                                        \
  326         }                                                                      \
  327     } while (0)
  328 
  329 #define GF_VALIDATE_OR_GOTO_WITH_ERROR(name, arg, label, errno, error)         \
  330     do {                                                                       \
  331         if (!arg) {                                                            \
  332             errno = error;                                                     \
  333             gf_msg_callingfn(name, GF_LOG_ERROR, EINVAL, LG_MSG_INVALID_ARG,   \
  334                              "invalid argument: " #arg);                       \
  335             goto label;                                                        \
  336         }                                                                      \
  337     } while (0)
  338 
  339 #define GF_CHECK_ALLOC(arg, retval, label)                                     \
  340     do {                                                                       \
  341         if (!(arg)) {                                                          \
  342             retval = -ENOMEM;                                                  \
  343             goto label;                                                        \
  344         }                                                                      \
  345     } while (0)
  346 
  347 #define GF_CHECK_ALLOC_AND_LOG(name, item, retval, msg, errlabel)              \
  348     do {                                                                       \
  349         if (!(item)) {                                                         \
  350             (retval) = -ENOMEM;                                                \
  351             gf_msg(name, GF_LOG_CRITICAL, ENOMEM, LG_MSG_NO_MEMORY, (msg));    \
  352             goto errlabel;                                                     \
  353         }                                                                      \
  354     } while (0)
  355 
  356 #define GF_ASSERT_AND_GOTO_WITH_ERROR(name, arg, label, errno, error)          \
  357     do {                                                                       \
  358         if (!arg) {                                                            \
  359             GF_ASSERT(0);                                                      \
  360             errno = error;                                                     \
  361             goto label;                                                        \
  362         }                                                                      \
  363     } while (0)
  364 
  365 #define GF_VALIDATE_ABSOLUTE_PATH_OR_GOTO(name, arg, label)                    \
  366     do {                                                                       \
  367         GF_VALIDATE_OR_GOTO(name, arg, label);                                 \
  368         if ((arg[0]) != '/') {                                                 \
  369             errno = EINVAL;                                                    \
  370             gf_msg_callingfn(name, GF_LOG_ERROR, EINVAL, LG_MSG_INVALID_ARG,   \
  371                              "invalid argument: " #arg);                       \
  372             goto label;                                                        \
  373         }                                                                      \
  374     } while (0)
  375 
  376 #define GF_REMOVE_SLASH_FROM_PATH(path, string)                                \
  377     do {                                                                       \
  378         int i = 0;                                                             \
  379         for (i = 1; i < strlen(path); i++) {                                   \
  380             string[i - 1] = path[i];                                           \
  381             if (string[i - 1] == '/')                                          \
  382                 string[i - 1] = '-';                                           \
  383         }                                                                      \
  384     } while (0)
  385 
  386 #define GF_REMOVE_INTERNAL_XATTR(pattern, dict)                                \
  387     do {                                                                       \
  388         if (!dict) {                                                           \
  389             gf_msg(this->name, GF_LOG_ERROR, 0, LG_MSG_DICT_NULL,              \
  390                    "dict is null");                                            \
  391             break;                                                             \
  392         }                                                                      \
  393         dict_foreach_fnmatch(dict, pattern, dict_remove_foreach_fn, NULL);     \
  394     } while (0)
  395 
  396 #define GF_IF_INTERNAL_XATTR_GOTO(pattern, dict, op_errno, label)              \
  397     do {                                                                       \
  398         if (!dict) {                                                           \
  399             gf_msg(this->name, GF_LOG_ERROR, 0, LG_MSG_DICT_NULL,              \
  400                    "setxattr dict is null");                                   \
  401             goto label;                                                        \
  402         }                                                                      \
  403         if (dict_foreach_fnmatch(dict, pattern, dict_null_foreach_fn, NULL) >  \
  404             0) {                                                               \
  405             op_errno = EPERM;                                                  \
  406             gf_msg(this->name, GF_LOG_ERROR, op_errno, LG_MSG_NO_PERM,         \
  407                    "attempt to set internal"                                   \
  408                    " xattr: %s",                                               \
  409                    pattern);                                                   \
  410             goto label;                                                        \
  411         }                                                                      \
  412     } while (0)
  413 
  414 #define GF_IF_NATIVE_XATTR_GOTO(pattern, key, op_errno, label)                 \
  415     do {                                                                       \
  416         if (!key) {                                                            \
  417             gf_msg(this->name, GF_LOG_ERROR, 0, LG_MSG_NO_KEY,                 \
  418                    "no key for removexattr");                                  \
  419             goto label;                                                        \
  420         }                                                                      \
  421         if (!fnmatch(pattern, key, 0)) {                                       \
  422             op_errno = EPERM;                                                  \
  423             gf_msg(this->name, GF_LOG_ERROR, op_errno, LG_MSG_NO_PERM,         \
  424                    "attempt to remove internal "                               \
  425                    "xattr: %s",                                                \
  426                    key);                                                       \
  427             goto label;                                                        \
  428         }                                                                      \
  429     } while (0)
  430 
  431 #ifdef DEBUG
  432 #define GF_ASSERT(x) assert(x);
  433 #else
  434 #define GF_ASSERT(x)                                                           \
  435     do {                                                                       \
  436         if (!(x)) {                                                            \
  437             gf_msg_callingfn("", GF_LOG_ERROR, 0, LG_MSG_ASSERTION_FAILED,     \
  438                              "Assertion failed: " #x);                         \
  439         }                                                                      \
  440     } while (0)
  441 #endif
  442 
  443 #define GF_ABORT(msg...)                                                       \
  444     do {                                                                       \
  445         gf_msg_callingfn("", GF_LOG_CRITICAL, 0, LG_MSG_ASSERTION_FAILED,      \
  446                          "Assertion failed: " msg);                            \
  447         abort();                                                               \
  448     } while (0)
  449 
  450 #define GF_UUID_ASSERT(u)                                                      \
  451     if (gf_uuid_is_null(u))                                                    \
  452         GF_ASSERT(!"uuid null");
  453 
  454 #define GF_IGNORE_IF_GSYNCD_SAFE_ERROR(frame, op_errno)                        \
  455     (((frame->root->pid == GF_CLIENT_PID_GSYNCD) &&                            \
  456       (op_errno == EEXIST || op_errno == ENOENT))                              \
  457          ? 0                                                                   \
  458          : 1)
  459 
  460 union gf_sock_union {
  461     struct sockaddr_storage storage;
  462     struct sockaddr_in6 sin6;
  463     struct sockaddr_in sin;
  464     struct sockaddr sa;
  465 };
  466 
  467 #define GF_HIDDEN_PATH ".glusterfs"
  468 #define GF_UNLINK_PATH GF_HIDDEN_PATH "/unlink"
  469 #define GF_LANDFILL_PATH GF_HIDDEN_PATH "/landfill"
  470 
  471 #define IOV_MIN(n) min(IOV_MAX, n)
  472 
  473 #define GF_SKIP_IRRELEVANT_ENTRIES(entry, dir, scr)                            \
  474     do {                                                                       \
  475         entry = NULL;                                                          \
  476         if (dir) {                                                             \
  477             entry = sys_readdir(dir, scr);                                     \
  478             while (entry && (!strcmp(entry->d_name, ".") ||                    \
  479                              !fnmatch("*.tmp", entry->d_name, 0) ||            \
  480                              !strcmp(entry->d_name, ".."))) {                  \
  481                 entry = sys_readdir(dir, scr);                                 \
  482             }                                                                  \
  483         }                                                                      \
  484     } while (0)
  485 
  486 static inline void
  487 iov_free(struct iovec *vector, int count)
  488 {
  489     int i;
  490 
  491     for (i = 0; i < count; i++)
  492         FREE(vector[i].iov_base);
  493 
  494     GF_FREE(vector);
  495 }
  496 
  497 static inline int
  498 iov_length(const struct iovec *vector, int count)
  499 {
  500     int i = 0;
  501     size_t size = 0;
  502 
  503     for (i = 0; i < count; i++)
  504         size += vector[i].iov_len;
  505 
  506     return size;
  507 }
  508 
  509 static inline struct iovec *
  510 iov_dup(const struct iovec *vector, int count)
  511 {
  512     int bytecount = 0;
  513     struct iovec *newvec = NULL;
  514 
  515     bytecount = (count * sizeof(struct iovec));
  516     newvec = GF_MALLOC(bytecount, gf_common_mt_iovec);
  517     if (newvec != NULL) {
  518         memcpy(newvec, vector, bytecount);
  519     }
  520 
  521     return newvec;
  522 }
  523 
  524 typedef struct _iov_iter {
  525     const struct iovec *iovec;
  526     void *ptr;
  527     uint32_t len;
  528     uint32_t count;
  529 } iov_iter_t;
  530 
  531 static inline bool
  532 iov_iter_init(iov_iter_t *iter, const struct iovec *iovec, uint32_t count,
  533               uint32_t offset)
  534 {
  535     uint32_t len;
  536 
  537     while (count > 0) {
  538         count--;
  539         len = iovec->iov_len;
  540         if (offset < len) {
  541             iter->ptr = iovec->iov_base + offset;
  542             iter->len = len - offset;
  543             iter->iovec = iovec + 1;
  544             iter->count = count;
  545 
  546             return true;
  547         }
  548         offset -= len;
  549     }
  550 
  551     memset(iter, 0, sizeof(*iter));
  552 
  553     return false;
  554 }
  555 
  556 static inline bool
  557 iov_iter_end(iov_iter_t *iter)
  558 {
  559     return iter->count == 0;
  560 }
  561 
  562 static inline bool
  563 iov_iter_next(iov_iter_t *iter, uint32_t size)
  564 {
  565     GF_ASSERT(size <= iter->len);
  566 
  567     if (iter->len > size) {
  568         iter->len -= size;
  569         iter->ptr += size;
  570 
  571         return true;
  572     }
  573     if (iter->count > 0) {
  574         iter->count--;
  575         iter->ptr = iter->iovec->iov_base;
  576         iter->len = iter->iovec->iov_len;
  577         iter->iovec++;
  578 
  579         return true;
  580     }
  581 
  582     memset(iter, 0, sizeof(*iter));
  583 
  584     return false;
  585 }
  586 
  587 static inline uint32_t
  588 iov_iter_copy(iov_iter_t *dst, iov_iter_t *src, uint32_t size)
  589 {
  590     uint32_t len;
  591 
  592     len = src->len;
  593     if (len > dst->len) {
  594         len = dst->len;
  595     }
  596     if (len > size) {
  597         len = size;
  598     }
  599     memcpy(dst->ptr, src->ptr, len);
  600 
  601     return len;
  602 }
  603 
  604 static inline uint32_t
  605 iov_iter_to_iovec(iov_iter_t *iter, struct iovec *iovec, int32_t idx,
  606                   uint32_t size)
  607 {
  608     uint32_t len;
  609 
  610     len = iter->len;
  611     if (len > size) {
  612         len = size;
  613     }
  614     iovec[idx].iov_base = iter->ptr;
  615     iovec[idx].iov_len = len;
  616 
  617     return len;
  618 }
  619 
  620 static inline int
  621 iov_subset(struct iovec *src, int src_count, uint32_t start, uint32_t size,
  622            struct iovec **dst, int32_t dst_count)
  623 {
  624     struct iovec iovec[src_count];
  625     iov_iter_t iter;
  626     uint32_t len;
  627     int32_t idx;
  628 
  629     if ((size == 0) || !iov_iter_init(&iter, src, src_count, start)) {
  630         return 0;
  631     }
  632 
  633     idx = 0;
  634     do {
  635         len = iov_iter_to_iovec(&iter, iovec, idx, size);
  636         idx++;
  637         size -= len;
  638     } while ((size > 0) && iov_iter_next(&iter, len));
  639 
  640     if (*dst == NULL) {
  641         *dst = iov_dup(iovec, idx);
  642         if (*dst == NULL) {
  643             return -1;
  644         }
  645     } else if (idx > dst_count) {
  646         return -1;
  647     } else {
  648         memcpy(*dst, iovec, idx * sizeof(struct iovec));
  649     }
  650 
  651     return idx;
  652 }
  653 
  654 static inline int
  655 iov_skip(struct iovec *iovec, uint32_t count, uint32_t size)
  656 {
  657     uint32_t len, idx;
  658 
  659     idx = 0;
  660     while ((size > 0) && (idx < count)) {
  661         len = iovec[idx].iov_len;
  662         if (len > size) {
  663             iovec[idx].iov_len -= size;
  664             iovec[idx].iov_base += size;
  665             break;
  666         }
  667         idx++;
  668         size -= len;
  669     }
  670 
  671     if (idx > 0) {
  672         memmove(iovec, iovec + idx, (count - idx) * sizeof(struct iovec));
  673     }
  674 
  675     return count - idx;
  676 }
  677 
  678 static inline size_t
  679 iov_range_copy(const struct iovec *dst, uint32_t dst_count, uint32_t dst_offset,
  680                const struct iovec *src, uint32_t src_count, uint32_t src_offset,
  681                uint32_t size)
  682 {
  683     iov_iter_t src_iter, dst_iter;
  684     uint32_t len, total;
  685 
  686     if ((size == 0) || !iov_iter_init(&src_iter, src, src_count, src_offset) ||
  687         !iov_iter_init(&dst_iter, dst, dst_count, dst_offset)) {
  688         return 0;
  689     }
  690 
  691     total = 0;
  692     do {
  693         len = iov_iter_copy(&dst_iter, &src_iter, size);
  694         total += len;
  695         size -= len;
  696     } while ((size > 0) && iov_iter_next(&src_iter, len) &&
  697              iov_iter_next(&dst_iter, len));
  698 
  699     return total;
  700 }
  701 
  702 static inline void
  703 iov_unload(char *buf, const struct iovec *vector, int count)
  704 {
  705     int i;
  706     int copied = 0;
  707 
  708     for (i = 0; i < count; i++) {
  709         memcpy(buf + copied, vector[i].iov_base, vector[i].iov_len);
  710         copied += vector[i].iov_len;
  711     }
  712 }
  713 
  714 static inline size_t
  715 iov_load(const struct iovec *vector, int count, char *buf, int size)
  716 {
  717     size_t left = size;
  718     size_t cp = 0;
  719     int ret = 0;
  720     int i = 0;
  721 
  722     while (left && i < count) {
  723         cp = min(vector[i].iov_len, left);
  724         if (vector[i].iov_base != buf + (size - left))
  725             memcpy(vector[i].iov_base, buf + (size - left), cp);
  726         ret += cp;
  727         left -= cp;
  728         if (left)
  729             i++;
  730     }
  731 
  732     return ret;
  733 }
  734 
  735 static inline size_t
  736 iov_copy(const struct iovec *dst, int dcnt, const struct iovec *src, int scnt)
  737 {
  738     return iov_range_copy(dst, dcnt, 0, src, scnt, 0, UINT32_MAX);
  739 }
  740 
  741 /* based on the amusing discussion @ https://rusty.ozlabs.org/?p=560 */
  742 static bool
  743 memeqzero(const void *data, size_t length)
  744 {
  745     const unsigned char *p = data;
  746     size_t len;
  747 
  748     /* Check first 16 bytes manually */
  749     for (len = 0; len < 16; len++) {
  750         if (!length)
  751             return true;
  752         if (*p)
  753             return false;
  754         p++;
  755         length--;
  756     }
  757 
  758     /* Now we know that's zero, memcmp with self. */
  759     return memcmp(data, p, length) == 0;
  760 }
  761 
  762 static inline int
  763 mem_0filled(const char *buf, size_t size)
  764 {
  765     return !memeqzero(buf, size);
  766 }
  767 
  768 static inline int
  769 iov_0filled(const struct iovec *vector, int count)
  770 {
  771     int i = 0;
  772     int ret = 0;
  773 
  774     for (i = 0; i < count; i++) {
  775         ret = mem_0filled(vector[i].iov_base, vector[i].iov_len);
  776         if (ret)
  777             break;
  778     }
  779 
  780     return ret;
  781 }
  782 
  783 typedef enum {
  784     gf_timefmt_default = 0,
  785     gf_timefmt_FT = 0, /* YYYY-MM-DD hh:mm:ss */
  786     gf_timefmt_Ymd_T,  /* YYYY/MM-DD-hh:mm:ss */
  787     gf_timefmt_bdT,    /* MMM DD hh:mm:ss */
  788     gf_timefmt_F_HMS,  /* YYYY-MM-DD hhmmss */
  789     gf_timefmt_dirent,
  790     gf_timefmt_s,
  791     gf_timefmt_last
  792 } gf_timefmts;
  793 
  794 static inline char *
  795 gf_time_fmt(char *dst, size_t sz_dst, time_t utime, unsigned int fmt)
  796 {
  797     extern void _gf_timestuff(const char ***, const char ***);
  798     static gf_timefmts timefmt_last = (gf_timefmts)-1;
  799     static const char **fmts;
  800     static const char **zeros;
  801     struct tm tm, *res;
  802     int localtime = 0;
  803 
  804     if (timefmt_last == ((gf_timefmts)-1)) {
  805         _gf_timestuff(&fmts, &zeros);
  806         timefmt_last = gf_timefmt_last;
  807     }
  808     if (timefmt_last <= fmt) {
  809         fmt = gf_timefmt_default;
  810     }
  811     localtime = gf_log_get_localtime();
  812     res = localtime ? localtime_r(&utime, &tm) : gmtime_r(&utime, &tm);
  813     if (utime && (res != NULL)) {
  814         strftime(dst, sz_dst, fmts[fmt], &tm);
  815     } else {
  816         strncpy(dst, "N/A", sz_dst);
  817     }
  818     return dst;
  819 }
  820 
  821 /* This function helps us use gfid (unique identity) to generate inode's unique
  822  * number in glusterfs.
  823  */
  824 ino_t
  825 gfid_to_ino(uuid_t gfid);
  826 
  827 int
  828 mkdir_p(char *path, mode_t mode, gf_boolean_t allow_symlinks);
  829 /*
  830  * rounds up nr to power of two. If nr is already a power of two, just returns
  831  * nr
  832  */
  833 
  834 int
  835 gf_lstat_dir(const char *path, struct stat *stbuf_in);
  836 
  837 int32_t
  838 gf_roundup_power_of_two(int32_t nr);
  839 
  840 /*
  841  * rounds up nr to next power of two. If nr is already a power of two, next
  842  * power of two is returned.
  843  */
  844 
  845 int32_t
  846 gf_roundup_next_power_of_two(int32_t nr);
  847 
  848 char *
  849 gf_trim(char *string);
  850 int
  851 gf_volume_name_validate(const char *volume_name);
  852 
  853 int
  854 gf_string2long(const char *str, long *n);
  855 int
  856 gf_string2ulong(const char *str, unsigned long *n);
  857 int
  858 gf_string2int(const char *str, int *n);
  859 int
  860 gf_string2uint(const char *str, unsigned int *n);
  861 int
  862 gf_string2double(const char *str, double *n);
  863 int
  864 gf_string2longlong(const char *str, long long *n);
  865 int
  866 gf_string2ulonglong(const char *str, unsigned long long *n);
  867 
  868 int
  869 gf_string2int8(const char *str, int8_t *n);
  870 int
  871 gf_string2int16(const char *str, int16_t *n);
  872 int
  873 gf_string2int32(const char *str, int32_t *n);
  874 int
  875 gf_string2int64(const char *str, int64_t *n);
  876 int
  877 gf_string2uint8(const char *str, uint8_t *n);
  878 int
  879 gf_string2uint16(const char *str, uint16_t *n);
  880 int
  881 gf_string2uint32(const char *str, uint32_t *n);
  882 int
  883 gf_string2uint64(const char *str, uint64_t *n);
  884 
  885 int
  886 gf_strstr(const char *str, const char *delim, const char *match);
  887 
  888 int
  889 gf_string2ulong_base10(const char *str, unsigned long *n);
  890 int
  891 gf_string2uint_base10(const char *str, unsigned int *n);
  892 int
  893 gf_string2uint8_base10(const char *str, uint8_t *n);
  894 int
  895 gf_string2uint16_base10(const char *str, uint16_t *n);
  896 int
  897 gf_string2uint32_base10(const char *str, uint32_t *n);
  898 int
  899 gf_string2uint64_base10(const char *str, uint64_t *n);
  900 int
  901 gf_string2bytesize_uint64(const char *str, uint64_t *n);
  902 int
  903 gf_string2bytesize_int64(const char *str, int64_t *n);
  904 int
  905 gf_string2percent_or_bytesize(const char *str, double *n,
  906                               gf_boolean_t *is_percent);
  907 
  908 int
  909 gf_string2boolean(const char *str, gf_boolean_t *b);
  910 int
  911 gf_strn2boolean(const char *str, const int len, gf_boolean_t *b);
  912 int
  913 gf_string2percent(const char *str, double *n);
  914 int
  915 gf_string2time(const char *str, uint32_t *n);
  916 
  917 int
  918 gf_lockfd(int fd);
  919 int
  920 gf_unlockfd(int fd);
  921 
  922 int
  923 get_checksum_for_file(int fd, uint32_t *checksum, int op_version);
  924 int
  925 log_base2(unsigned long x);
  926 
  927 int
  928 get_checksum_for_path(char *path, uint32_t *checksum, int op_version);
  929 int
  930 get_file_mtime(const char *path, time_t *stamp);
  931 char *
  932 gf_resolve_path_parent(const char *path);
  933 
  934 char *
  935 strtail(char *str, const char *pattern);
  936 void
  937 skipwhite(char **s);
  938 char *
  939 nwstrtail(char *str, char *pattern);
  940 /* returns a new string with nth word of given string. n>=1 */
  941 
  942 typedef struct token_iter {
  943     char *end;
  944     char sep;
  945 } token_iter_t;
  946 char *
  947 token_iter_init(char *str, char sep, token_iter_t *tit);
  948 gf_boolean_t
  949 next_token(char **tokenp, token_iter_t *tit);
  950 void
  951 drop_token(char *token, token_iter_t *tit);
  952 
  953 gf_boolean_t
  954 mask_match(const uint32_t a, const uint32_t b, const uint32_t m);
  955 gf_boolean_t
  956 gf_is_ip_in_net(const char *network, const char *ip_str);
  957 char
  958 valid_host_name(char *address, int length);
  959 char
  960 valid_ipv4_address(char *address, int length, gf_boolean_t wildcard_acc);
  961 char
  962 valid_ipv6_address(char *address, int length, gf_boolean_t wildcard_acc);
  963 char
  964 valid_internet_address(char *address, gf_boolean_t wildcard_acc,
  965                        gf_boolean_t cidr);
  966 gf_boolean_t
  967 valid_mount_auth_address(char *address);
  968 gf_boolean_t
  969 valid_ipv4_subnetwork(const char *address);
  970 gf_boolean_t
  971 gf_sock_union_equal_addr(union gf_sock_union *a, union gf_sock_union *b);
  972 char *
  973 gf_rev_dns_lookup(const char *ip);
  974 
  975 char *
  976 uuid_utoa(uuid_t uuid);
  977 char *
  978 uuid_utoa_r(uuid_t uuid, char *dst);
  979 char *
  980 lkowner_utoa(gf_lkowner_t *lkowner);
  981 char *
  982 lkowner_utoa_r(gf_lkowner_t *lkowner, char *dst, int len);
  983 char *
  984 leaseid_utoa(const char *lease_id);
  985 gf_boolean_t
  986 is_valid_lease_id(const char *lease_id);
  987 char *
  988 gf_leaseid_get(void);
  989 char *
  990 gf_existing_leaseid(void);
  991 
  992 void
  993 gf_array_insertionsort(void *a, int l, int r, size_t elem_size, gf_cmp cmp);
  994 int
  995 gf_is_str_int(const char *value);
  996 
  997 char *gf_uint64_2human_readable(uint64_t);
  998 int
  999 validate_brick_name(char *brick);
 1000 char *
 1001 get_host_name(char *word, char **host);
 1002 char *
 1003 get_path_name(char *word, char **path);
 1004 void
 1005 gf_path_strip_trailing_slashes(char *path);
 1006 uint64_t
 1007 get_mem_size(void);
 1008 int
 1009 gf_strip_whitespace(char *str, int len);
 1010 int
 1011 gf_canonicalize_path(char *path);
 1012 char *
 1013 generate_glusterfs_ctx_id(void);
 1014 char *
 1015 gf_get_reserved_ports(void);
 1016 int
 1017 gf_process_reserved_ports(unsigned char *ports, uint32_t ceiling);
 1018 gf_boolean_t
 1019 gf_ports_reserved(char *blocked_port, unsigned char *ports, uint32_t ceiling);
 1020 int
 1021 gf_get_hostname_from_ip(char *client_ip, char **hostname);
 1022 gf_boolean_t
 1023 gf_is_local_addr(char *hostname);
 1024 gf_boolean_t
 1025 gf_is_same_address(char *host1, char *host2);
 1026 void
 1027 gf_xxh64_wrapper(const unsigned char *data, size_t const len,
 1028                  unsigned long long const seed, char *xxh64);
 1029 int
 1030 gf_gfid_generate_from_xxh64(uuid_t gfid, char *key);
 1031 
 1032 int
 1033 gf_set_timestamp(const char *src, const char *dest);
 1034 
 1035 int
 1036 gf_thread_create(pthread_t *thread, const pthread_attr_t *attr,
 1037                  void *(*start_routine)(void *), void *arg, const char *name,
 1038                  ...) __attribute__((__format__(__printf__, 5, 6)));
 1039 
 1040 int
 1041 gf_thread_vcreate(pthread_t *thread, const pthread_attr_t *attr,
 1042                   void *(*start_routine)(void *), void *arg, const char *name,
 1043                   va_list args);
 1044 int
 1045 gf_thread_create_detached(pthread_t *thread, void *(*start_routine)(void *),
 1046                           void *arg, const char *name, ...)
 1047     __attribute__((__format__(__printf__, 4, 5)));
 1048 
 1049 void
 1050 gf_thread_set_name(pthread_t thread, const char *name, ...)
 1051     __attribute__((__format__(__printf__, 2, 3)));
 1052 
 1053 void
 1054 gf_thread_set_vname(pthread_t thread, const char *name, va_list args);
 1055 gf_boolean_t
 1056 gf_is_pid_running(int pid);
 1057 gf_boolean_t
 1058 gf_is_service_running(char *pidfile, int *pid);
 1059 gf_boolean_t
 1060 gf_valid_pid(const char *pid, int length);
 1061 int
 1062 gf_skip_header_section(int fd, int header_len);
 1063 
 1064 struct iatt;
 1065 struct _dict;
 1066 
 1067 gf_boolean_t
 1068 dht_is_linkfile(struct iatt *buf, struct _dict *dict);
 1069 
 1070 int
 1071 gf_check_log_format(const char *value);
 1072 
 1073 int
 1074 gf_check_logger(const char *value);
 1075 
 1076 gf_boolean_t
 1077 gf_compare_sockaddr(const struct sockaddr *addr1, const struct sockaddr *addr2);
 1078 
 1079 char *
 1080 gf_backtrace_save(char *buf);
 1081 
 1082 void
 1083 gf_backtrace_done(char *buf);
 1084 
 1085 gf_loglevel_t
 1086 fop_log_level(glusterfs_fop_t fop, int op_errno);
 1087 
 1088 int32_t
 1089 gf_build_absolute_path(char *current_path, char *relative_path, char **path);
 1090 
 1091 int
 1092 recursive_rmdir(const char *delete_path);
 1093 
 1094 int
 1095 gf_get_index_by_elem(char **array, char *elem);
 1096 
 1097 int
 1098 glusterfs_is_local_pathinfo(char *pathinfo, gf_boolean_t *local);
 1099 
 1100 int
 1101 gf_thread_cleanup_xint(pthread_t thread);
 1102 
 1103 ssize_t
 1104 gf_nread(int fd, void *buf, size_t count);
 1105 
 1106 ssize_t
 1107 gf_nwrite(int fd, const void *buf, size_t count);
 1108 
 1109 void
 1110 _mask_cancellation(void);
 1111 void
 1112 _unmask_cancellation(void);
 1113 
 1114 gf_boolean_t
 1115 gf_is_zero_filled_stat(struct iatt *buf);
 1116 
 1117 void
 1118 gf_zero_fill_stat(struct iatt *buf);
 1119 
 1120 gf_boolean_t
 1121 gf_is_valid_xattr_namespace(char *k);
 1122 
 1123 const char *
 1124 gf_inode_type_to_str(ia_type_t type);
 1125 
 1126 int32_t
 1127 gf_bits_count(uint64_t n);
 1128 
 1129 int32_t
 1130 gf_bits_index(uint64_t n);
 1131 
 1132 const char *
 1133 gf_fop_string(glusterfs_fop_t fop);
 1134 
 1135 int
 1136 gf_fop_int(char *fop);
 1137 
 1138 char *
 1139 get_ip_from_addrinfo(struct addrinfo *addr, char **ip);
 1140 
 1141 int
 1142 close_fds_except(int *fdv, size_t count);
 1143 
 1144 int
 1145 gf_getgrouplist(const char *user, gid_t group, gid_t **groups);
 1146 
 1147 int
 1148 glusterfs_compute_sha256(const unsigned char *content, size_t size,
 1149                          char *sha256_hash);
 1150 
 1151 char *
 1152 gf_strncpy(char *dest, const char *src, const size_t dest_size);
 1153 
 1154 void
 1155 gf_strTrim(char **s);
 1156 
 1157 int
 1158 gf_replace_old_iatt_in_dict(struct _dict *);
 1159 
 1160 int
 1161 gf_replace_new_iatt_in_dict(struct _dict *);
 1162 
 1163 xlator_cmdline_option_t *
 1164 find_xlator_option_in_cmd_args_t(const char *option_name, cmd_args_t *args);
 1165 
 1166 int
 1167 gf_d_type_from_ia_type(ia_type_t type);
 1168 
 1169 int
 1170 gf_nanosleep(uint64_t nsec);
 1171 
 1172 #endif /* _COMMON_UTILS_H */