diff options
Diffstat (limited to 'libglusterfs/src/glusterfs')
-rw-r--r-- | libglusterfs/src/glusterfs/common-utils.h | 122 | ||||
-rw-r--r-- | libglusterfs/src/glusterfs/dict.h | 10 | ||||
-rw-r--r-- | libglusterfs/src/glusterfs/fd.h | 3 | ||||
-rw-r--r-- | libglusterfs/src/glusterfs/gf-event.h | 4 | ||||
-rw-r--r-- | libglusterfs/src/glusterfs/globals.h | 8 | ||||
-rw-r--r-- | libglusterfs/src/glusterfs/glusterfs-acl.h | 2 | ||||
-rw-r--r-- | libglusterfs/src/glusterfs/glusterfs.h | 17 | ||||
-rw-r--r-- | libglusterfs/src/glusterfs/latency.h | 22 | ||||
-rw-r--r-- | libglusterfs/src/glusterfs/libglusterfs-messages.h | 130 | ||||
-rw-r--r-- | libglusterfs/src/glusterfs/mem-pool.h | 58 | ||||
-rw-r--r-- | libglusterfs/src/glusterfs/mem-types.h | 1 | ||||
-rw-r--r-- | libglusterfs/src/glusterfs/stack.h | 14 | ||||
-rw-r--r-- | libglusterfs/src/glusterfs/statedump.h | 2 | ||||
-rw-r--r-- | libglusterfs/src/glusterfs/store.h | 2 | ||||
-rw-r--r-- | libglusterfs/src/glusterfs/syncop.h | 80 | ||||
-rw-r--r-- | libglusterfs/src/glusterfs/syscall.h | 18 | ||||
-rw-r--r-- | libglusterfs/src/glusterfs/xlator.h | 6 |
17 files changed, 425 insertions, 74 deletions
diff --git a/libglusterfs/src/glusterfs/common-utils.h b/libglusterfs/src/glusterfs/common-utils.h index f6d82cc0b85..f297fdab5c9 100644 --- a/libglusterfs/src/glusterfs/common-utils.h +++ b/libglusterfs/src/glusterfs/common-utils.h @@ -18,6 +18,7 @@ #include <string.h> #include <assert.h> #include <pthread.h> +#include <unistd.h> #include <openssl/md5.h> #ifndef GF_BSD_HOST_OS #include <alloca.h> @@ -26,6 +27,11 @@ #include <fnmatch.h> #include <uuid/uuid.h> +/* FreeBSD, etc. */ +#ifndef __BITS_PER_LONG +#define __BITS_PER_LONG (CHAR_BIT * (sizeof(long))) +#endif + #ifndef ffsll #define ffsll(x) __builtin_ffsll(x) #endif @@ -123,6 +129,7 @@ trap(void); /* Default value of signing waiting time to sign a file for bitrot */ #define SIGNING_TIMEOUT "120" +#define BR_WORKERS "4" /* xxhash */ #define GF_XXH64_DIGEST_LENGTH 8 @@ -147,6 +154,9 @@ trap(void); #define GF_THREAD_NAME_LIMIT 16 #define GF_THREAD_NAME_PREFIX "glfs_" +/* Advisory buffer size for formatted timestamps (see gf_time_fmt) */ +#define GF_TIMESTR_SIZE 256 + /* * we could have initialized these as +ve values and treated * them as negative while comparing etc.. (which would have @@ -166,7 +176,8 @@ enum _gf_special_pid { GF_CLIENT_PID_SCRUB = -9, GF_CLIENT_PID_TIER_DEFRAG = -10, GF_SERVER_PID_TRASH = -11, - GF_CLIENT_PID_ADD_REPLICA_MOUNT = -12 + GF_CLIENT_PID_ADD_REPLICA_MOUNT = -12, + GF_CLIENT_PID_SET_UTIME = -13, }; enum _gf_xlator_ipc_targets { @@ -178,6 +189,12 @@ enum _gf_xlator_ipc_targets { typedef enum _gf_special_pid gf_special_pid_t; typedef enum _gf_xlator_ipc_targets _gf_xlator_ipc_targets_t; +/* Array to hold custom xattr keys */ +extern char *xattrs_to_heal[]; + +char ** +get_xattrs_to_heal(); + /* The DHT file rename operation is not a straightforward rename. * It involves creating linkto and linkfiles, and can unlink or rename the * source file depending on the hashed and cached subvols for the source @@ -238,6 +255,8 @@ list_node_del(struct list_node *node); struct dnscache * gf_dnscache_init(time_t ttl); +void +gf_dnscache_deinit(struct dnscache *cache); struct dnscache_entry * gf_dnscache_entry_init(void); void @@ -436,6 +455,15 @@ BIT_VALUE(unsigned char *array, unsigned int index) } while (0) #endif +/* Compile-time assert, borrowed from Linux kernel. */ +#ifdef HAVE_STATIC_ASSERT +#define GF_STATIC_ASSERT(expr, ...) \ + __gf_static_assert(expr, ##__VA_ARGS__, #expr) +#define __gf_static_assert(expr, msg, ...) _Static_assert(expr, msg) +#else +#define GF_STATIC_ASSERT(expr, ...) +#endif + #define GF_ABORT(msg...) \ do { \ gf_msg_callingfn("", GF_LOG_CRITICAL, 0, LG_MSG_ASSERTION_FAILED, \ @@ -466,18 +494,15 @@ union gf_sock_union { #define IOV_MIN(n) min(IOV_MAX, n) -#define GF_SKIP_IRRELEVANT_ENTRIES(entry, dir, scr) \ - do { \ - entry = NULL; \ - if (dir) { \ - entry = sys_readdir(dir, scr); \ - while (entry && (!strcmp(entry->d_name, ".") || \ - !fnmatch("*.tmp", entry->d_name, 0) || \ - !strcmp(entry->d_name, ".."))) { \ - entry = sys_readdir(dir, scr); \ - } \ - } \ - } while (0) +static inline gf_boolean_t +gf_irrelevant_entry(struct dirent *entry) +{ + GF_ASSERT(entry); + + return (!strcmp(entry->d_name, ".") || + !fnmatch("*.tmp", entry->d_name, 0) || + !strcmp(entry->d_name, "..")); +} static inline void iov_free(struct iovec *vector, int count) @@ -788,7 +813,7 @@ typedef enum { } gf_timefmts; static inline char * -gf_time_fmt(char *dst, size_t sz_dst, time_t utime, unsigned int fmt) +gf_time_fmt_tv(char *dst, size_t sz_dst, struct timeval *tv, unsigned int fmt) { extern void _gf_timestuff(const char ***, const char ***); static gf_timefmts timefmt_last = (gf_timefmts)-1; @@ -796,6 +821,8 @@ gf_time_fmt(char *dst, size_t sz_dst, time_t utime, unsigned int fmt) static const char **zeros; struct tm tm, *res; int localtime = 0; + int len = 0; + int pos = 0; if (timefmt_last == ((gf_timefmts)-1)) { _gf_timestuff(&fmts, &zeros); @@ -805,15 +832,35 @@ gf_time_fmt(char *dst, size_t sz_dst, time_t utime, unsigned int fmt) fmt = gf_timefmt_default; } localtime = gf_log_get_localtime(); - res = localtime ? localtime_r(&utime, &tm) : gmtime_r(&utime, &tm); - if (utime && (res != NULL)) { - strftime(dst, sz_dst, fmts[fmt], &tm); + res = localtime ? localtime_r(&tv->tv_sec, &tm) + : gmtime_r(&tv->tv_sec, &tm); + if (tv->tv_sec && (res != NULL)) { + len = strftime(dst, sz_dst, fmts[fmt], &tm); + if (len == 0) + return dst; + pos += len; + if (tv->tv_usec >= 0) { + len = snprintf(dst + pos, sz_dst - pos, ".%" GF_PRI_SUSECONDS, + tv->tv_usec); + if (len >= sz_dst - pos) + return dst; + pos += len; + } + strftime(dst + pos, sz_dst - pos, " %z", &tm); } else { strncpy(dst, "N/A", sz_dst); } return dst; } +static inline char * +gf_time_fmt(char *dst, size_t sz_dst, time_t utime, unsigned int fmt) +{ + struct timeval tv = {utime, -1}; + + return gf_time_fmt_tv(dst, sz_dst, &tv, fmt); +} + /* This function helps us use gfid (unique identity) to generate inode's unique * number in glusterfs. */ @@ -1163,6 +1210,47 @@ int gf_d_type_from_ia_type(ia_type_t type); int +gf_syncfs(int fd); + +int gf_nanosleep(uint64_t nsec); +static inline time_t +gf_time(void) +{ + return time(NULL); +} + +/* Return delta value in microseconds. */ + +static inline double +gf_tvdiff(struct timeval *start, struct timeval *end) +{ + struct timeval t; + + if (start->tv_usec > end->tv_usec) + t.tv_sec = end->tv_sec - 1, t.tv_usec = end->tv_usec + 1000000; + else + t.tv_sec = end->tv_sec, t.tv_usec = end->tv_usec; + + return (double)(t.tv_sec - start->tv_sec) * 1e6 + + (double)(t.tv_usec - start->tv_usec); +} + +/* Return delta value in nanoseconds. */ + +static inline double +gf_tsdiff(struct timespec *start, struct timespec *end) +{ + struct timespec t; + + if (start->tv_nsec > end->tv_nsec) + t.tv_sec = end->tv_sec - 1, t.tv_nsec = end->tv_nsec + 1000000000; + else + t.tv_sec = end->tv_sec, t.tv_nsec = end->tv_nsec; + + return (double)(t.tv_sec - start->tv_sec) * 1e9 + + (double)(t.tv_nsec - start->tv_nsec); +} + #endif /* _COMMON_UTILS_H */ diff --git a/libglusterfs/src/glusterfs/dict.h b/libglusterfs/src/glusterfs/dict.h index ce1c2100276..d0467c6dfb6 100644 --- a/libglusterfs/src/glusterfs/dict.h +++ b/libglusterfs/src/glusterfs/dict.h @@ -25,9 +25,6 @@ typedef struct _data_pair data_pair_t; #define dict_add_sizen(this, key, value) dict_addn(this, key, SLEN(key), value) -#define dict_get_with_ref_sizen(this, key, value) \ - dict_get_with_refn(this, key, SLEN(key), value) - #define dict_get_sizen(this, key) dict_getn(this, key, SLEN(key)) #define dict_del_sizen(this, key) dict_deln(this, key, SLEN(key)) @@ -98,7 +95,7 @@ struct _data { char *data; gf_atomic_t refcount; gf_dict_data_type_t data_type; - int32_t len; + uint32_t len; gf_boolean_t is_static; }; @@ -122,6 +119,8 @@ struct _dict { gf_lock_t lock; data_pair_t *members_internal; data_pair_t free_pair; + /* Variable to store total keylen + value->len */ + uint32_t totkvlen; }; typedef gf_boolean_t (*dict_match_t)(dict_t *d, char *k, data_t *v, void *data); @@ -136,6 +135,7 @@ int32_t dict_set(dict_t *this, char *key, data_t *value); int32_t dict_setn(dict_t *this, char *key, const int keylen, data_t *value); + /* function to set a new key/value pair (without checking for duplicate) */ int32_t dict_add(dict_t *this, char *key, data_t *value); @@ -143,8 +143,6 @@ int32_t dict_addn(dict_t *this, char *key, const int keylen, data_t *value); int dict_get_with_ref(dict_t *this, char *key, data_t **data); -int -dict_get_with_refn(dict_t *this, char *key, const int keylen, data_t **data); data_t * dict_get(dict_t *this, char *key); data_t * diff --git a/libglusterfs/src/glusterfs/fd.h b/libglusterfs/src/glusterfs/fd.h index 28906d34e4d..3ffaaa60504 100644 --- a/libglusterfs/src/glusterfs/fd.h +++ b/libglusterfs/src/glusterfs/fd.h @@ -106,6 +106,9 @@ fd_ref(fd_t *fd); void fd_unref(fd_t *fd); +void +fd_close(fd_t *fd); + fd_t * fd_create(struct _inode *inode, pid_t pid); diff --git a/libglusterfs/src/glusterfs/gf-event.h b/libglusterfs/src/glusterfs/gf-event.h index c0f05e7c83b..40f8fbdf10a 100644 --- a/libglusterfs/src/glusterfs/gf-event.h +++ b/libglusterfs/src/glusterfs/gf-event.h @@ -12,6 +12,7 @@ #define _GF_EVENT_H_ #include <pthread.h> +#include "common-utils.h" #include "list.h" struct event_pool; @@ -31,6 +32,9 @@ typedef void (*event_handler_t)(int fd, int idx, int gen, void *data, #define EVENT_EPOLL_SLOTS 1024 #define EVENT_MAX_THREADS 1024 +/* See rpcsvc.h to check why. */ +GF_STATIC_ASSERT(EVENT_MAX_THREADS % __BITS_PER_LONG == 0); + struct event_pool { struct event_ops *ops; diff --git a/libglusterfs/src/glusterfs/globals.h b/libglusterfs/src/glusterfs/globals.h index f0c7395b4cb..b22eaae6c2f 100644 --- a/libglusterfs/src/glusterfs/globals.h +++ b/libglusterfs/src/glusterfs/globals.h @@ -45,7 +45,7 @@ 1 /* MIN is the fresh start op-version, mostly \ should not change */ #define GD_OP_VERSION_MAX \ - GD_OP_VERSION_8_0 /* MAX VERSION is the maximum \ + GD_OP_VERSION_9_0 /* MAX VERSION is the maximum \ count in VME table, should \ keep changing with \ introduction of newer \ @@ -118,9 +118,12 @@ #define GD_OP_VERSION_7_0 70000 /* Op-version for GlusterFS 7.0 */ #define GD_OP_VERSION_7_1 70100 /* Op-version for GlusterFS 7.1 */ #define GD_OP_VERSION_7_2 70200 /* Op-version for GlusterFS 7.2 */ +#define GD_OP_VERSION_7_3 70300 /* Op-version for GlusterFS 7.3 */ #define GD_OP_VERSION_8_0 80000 /* Op-version for GlusterFS 8.0 */ +#define GD_OP_VERSION_9_0 90000 /* Op-version for GlusterFS 9.0 */ + #define GD_OP_VER_PERSISTENT_AFR_XATTRS GD_OP_VERSION_3_6_0 #include "glusterfs/xlator.h" @@ -166,6 +169,9 @@ glusterfs_leaseid_exist(void); int glusterfs_globals_init(glusterfs_ctx_t *ctx); +void +gf_thread_needs_cleanup(void); + struct tvec_base * glusterfs_ctx_tw_get(glusterfs_ctx_t *ctx); void diff --git a/libglusterfs/src/glusterfs/glusterfs-acl.h b/libglusterfs/src/glusterfs/glusterfs-acl.h index cae55e8062f..987bf5fab0b 100644 --- a/libglusterfs/src/glusterfs/glusterfs-acl.h +++ b/libglusterfs/src/glusterfs/glusterfs-acl.h @@ -143,7 +143,7 @@ gf_posix_acl_get_key(const acl_type_t type) return acl_key; } -static inline const acl_type_t +static inline acl_type_t gf_posix_acl_get_type(const char *key) { acl_type_t type = 0; diff --git a/libglusterfs/src/glusterfs/glusterfs.h b/libglusterfs/src/glusterfs/glusterfs.h index bbb66d264eb..e6425618b7f 100644 --- a/libglusterfs/src/glusterfs/glusterfs.h +++ b/libglusterfs/src/glusterfs/glusterfs.h @@ -43,6 +43,9 @@ #define GF_YES 1 #define GF_NO 0 +#define IS_ERROR(ret) ((ret) < 0) +#define IS_SUCCESS(ret) ((ret) >= 0) + #ifndef O_LARGEFILE /* savannah bug #20053, patch for compiling on darwin */ #define O_LARGEFILE 0100000 /* from bits/fcntl.h */ @@ -422,7 +425,7 @@ static const char *const FOP_PRI_STRINGS[] = {"HIGH", "NORMAL", "LOW", "LEAST"}; static inline const char * fop_pri_to_string(gf_fop_pri_t pri) { - if (pri < 0) + if (IS_ERROR(pri)) return "UNSPEC"; if (pri >= GF_FOP_PRI_MAX) @@ -463,6 +466,8 @@ typedef struct _server_cmdline server_cmdline_t; #define GF_OPTION_DISABLE _gf_false #define GF_OPTION_DEFERRED 2 +typedef enum { _gf_none, _gf_memcheck, _gf_drd } gf_valgrind_tool; + struct _cmd_args { /* basic options */ char *volfile_server; @@ -555,7 +560,8 @@ struct _cmd_args { /* Run this process with valgrind? Might want to prevent calling * functions that prevent valgrind from working correctly, like * dlclose(). */ - int valgrind; + gf_valgrind_tool vgtool; + int localtime_logging; /* For the subdir mount */ @@ -727,12 +733,13 @@ struct _glusterfs_ctx { } stats; struct list_head volfile_list; - /* Add members to manage janitor threads for cleanup fd */ struct list_head janitor_fds; - pthread_cond_t janitor_cond; - pthread_mutex_t janitor_lock; + pthread_cond_t fd_cond; + pthread_mutex_t fd_lock; pthread_t janitor; + /* The variable is use to save total posix xlator count */ + uint32_t pxl_count; char volume_id[GF_UUID_BUF_SIZE]; /* Used only in protocol/client */ }; diff --git a/libglusterfs/src/glusterfs/latency.h b/libglusterfs/src/glusterfs/latency.h index ed47b1f0cbc..4d601bbcbd6 100644 --- a/libglusterfs/src/glusterfs/latency.h +++ b/libglusterfs/src/glusterfs/latency.h @@ -11,13 +11,23 @@ #ifndef __LATENCY_H__ #define __LATENCY_H__ -#include "glusterfs/glusterfs.h" +#include <inttypes.h> +#include <time.h> -typedef struct fop_latency { - double min; /* min time for the call (microseconds) */ - double max; /* max time for the call (microseconds) */ - double total; /* total time (microseconds) */ +typedef struct _gf_latency { + uint64_t min; /* min time for the call (nanoseconds) */ + uint64_t max; /* max time for the call (nanoseconds) */ + uint64_t total; /* total time (nanoseconds) */ uint64_t count; -} fop_latency_t; +} gf_latency_t; +gf_latency_t * +gf_latency_new(size_t n); + +void +gf_latency_reset(gf_latency_t *lat); + +void +gf_latency_update(gf_latency_t *lat, struct timespec *begin, + struct timespec *end); #endif /* __LATENCY_H__ */ diff --git a/libglusterfs/src/glusterfs/libglusterfs-messages.h b/libglusterfs/src/glusterfs/libglusterfs-messages.h index 7e0eebbe535..cb31dd7614b 100644 --- a/libglusterfs/src/glusterfs/libglusterfs-messages.h +++ b/libglusterfs/src/glusterfs/libglusterfs-messages.h @@ -112,6 +112,134 @@ GLFS_MSGID( LG_MSG_XXH64_TO_GFID_FAILED, LG_MSG_ASYNC_WARNING, LG_MSG_ASYNC_FAILURE, LG_MSG_GRAPH_CLEANUP_FAILED, LG_MSG_GRAPH_SETUP_FAILED, LG_MSG_GRAPH_DETACH_STARTED, LG_MSG_GRAPH_ATTACH_FAILED, - LG_MSG_GRAPH_ATTACH_PID_FILE_UPDATED); + LG_MSG_GRAPH_ATTACH_PID_FILE_UPDATED, LG_MSG_DUPLICATE_ENTRY, + LG_MSG_THREAD_NAME_TOO_LONG, LG_MSG_SET_THREAD_FAILED, + LG_MSG_THREAD_CREATE_FAILED, LG_MSG_FILE_DELETE_FAILED, LG_MSG_WRONG_VALUE, + LG_MSG_PATH_OPEN_FAILED, LG_MSG_DISPATCH_HANDLER_FAILED, + LG_MSG_READ_FILE_FAILED, LG_MSG_ENTRIES_NOT_PROVIDED, + LG_MSG_ENTRIES_PROVIDED, LG_MSG_UNKNOWN_OPTION_TYPE, + LG_MSG_OPTION_DEPRECATED, LG_MSG_INVALID_INIT, LG_MSG_OBJECT_NULL, + LG_MSG_GRAPH_NOT_SET, LG_MSG_FILENAME_NOT_SPECIFIED, LG_MSG_STRUCT_MISS, + LG_MSG_METHOD_MISS, LG_MSG_INPUT_DATA_NULL, LG_MSG_OPEN_LOGFILE_FAILED); + +#define LG_MSG_EPOLL_FD_CREATE_FAILED_STR "epoll fd creation failed" +#define LG_MSG_INVALID_POLL_IN_STR "invalid poll_in value" +#define LG_MSG_INVALID_POLL_OUT_STR "invalid poll_out value" +#define LG_MSG_SLOT_NOT_FOUND_STR "could not find slot" +#define LG_MSG_EPOLL_FD_ADD_FAILED_STR "failed to add fd to epoll" +#define LG_MSG_EPOLL_FD_DEL_FAILED_STR "fail to delete fd to epoll" +#define LG_MSG_EPOLL_FD_MODIFY_FAILED_STR "failed to modify fd events" +#define LG_MSG_STALE_FD_FOUND_STR "stale fd found" +#define LG_MSG_GENERATION_MISMATCH_STR "generation mismatch" +#define LG_MSG_STARTED_EPOLL_THREAD_STR "Started thread with index" +#define LG_MSG_EXITED_EPOLL_THREAD_STR "Exited thread" +#define LG_MSG_DISPATCH_HANDLER_FAILED_STR "Failed to dispatch handler" +#define LG_MSG_START_EPOLL_THREAD_FAILED_STR "Failed to start thread" +#define LG_MSG_PIPE_CREATE_FAILED_STR "pipe creation failed" +#define LG_MSG_SET_PIPE_FAILED_STR "could not set pipe to non blocking mode" +#define LG_MSG_REGISTER_PIPE_FAILED_STR \ + "could not register pipe fd with poll event loop" +#define LG_MSG_POLL_IGNORE_MULTIPLE_THREADS_STR \ + "Currently poll does not use multiple event processing threads, count " \ + "ignored" +#define LG_MSG_INDEX_NOT_FOUND_STR "index not found" +#define LG_MSG_READ_FILE_FAILED_STR "read on file returned error" +#define LG_MSG_RB_TABLE_CREATE_FAILED_STR "Failed to create rb table bucket" +#define LG_MSG_HASH_FUNC_ERROR_STR "Hash function not given" +#define LG_MSG_ENTRIES_NOT_PROVIDED_STR \ + "Both mem-pool and expected entries not provided" +#define LG_MSG_ENTRIES_PROVIDED_STR \ + "Both mem-pool and expected entries are provided" +#define LG_MSG_RBTHASH_INIT_BUCKET_FAILED_STR "failed to init buckets" +#define LG_MSG_RBTHASH_GET_ENTRY_FAILED_STR "Failed to get entry from mem-pool" +#define LG_MSG_RBTHASH_GET_BUCKET_FAILED_STR "Failed to get bucket" +#define LG_MSG_RBTHASH_INSERT_FAILED_STR "Failed to insert entry" +#define LG_MSG_RBTHASH_INIT_ENTRY_FAILED_STR "Failed to init entry" +#define LG_MSG_FILE_STAT_FAILED_STR "failed to stat" +#define LG_MSG_INET_PTON_FAILED_STR "inet_pton() failed" +#define LG_MSG_INVALID_ENTRY_STR "Invalid arguments" +#define LG_MSG_NEGATIVE_NUM_PASSED_STR "negative number passed" +#define LG_MSG_PATH_ERROR_STR "Path manipulation failed" +#define LG_MSG_FILE_OP_FAILED_STR "could not open/read file, getting ports info" +#define LG_MSG_RESERVED_PORTS_ERROR_STR \ + "Not able to get reserved ports, hence there is a possibility that " \ + "glusterfs may consume reserved port" +#define LG_MSG_INVALID_PORT_STR "invalid port" +#define LG_MSG_GETNAMEINFO_FAILED_STR "Could not lookup hostname" +#define LG_MSG_GETIFADDRS_FAILED_STR "getifaddrs() failed" +#define LG_MSG_INVALID_FAMILY_STR "Invalid family" +#define LG_MSG_CONVERSION_FAILED_STR "String conversion failed" +#define LG_MSG_GETADDRINFO_FAILED_STR "error in getaddrinfo" +#define LG_MSG_DUPLICATE_ENTRY_STR "duplicate entry for volfile-server" +#define LG_MSG_PTHREAD_NAMING_FAILED_STR "Failed to compose thread name" +#define LG_MSG_THREAD_NAME_TOO_LONG_STR \ + "Thread name is too long. It has been truncated" +#define LG_MSG_SET_THREAD_FAILED_STR "Could not set thread name" +#define LG_MSG_THREAD_CREATE_FAILED_STR "Thread creation failed" +#define LG_MSG_PTHREAD_ATTR_INIT_FAILED_STR \ + "Thread attribute initialization failed" +#define LG_MSG_SKIP_HEADER_FAILED_STR "Failed to skip header section" +#define LG_MSG_INVALID_LOG_STR "Invalid log-format" +#define LG_MSG_UTIMENSAT_FAILED_STR "utimenstat failed" +#define LG_MSG_UTIMES_FAILED_STR "utimes failed" +#define LG_MSG_FILE_DELETE_FAILED_STR "Unable to delete file" +#define LG_MSG_BACKTRACE_SAVE_FAILED_STR "Failed to save the backtrace" +#define LG_MSG_WRONG_VALUE_STR "wrong value" +#define LG_MSG_DIR_OP_FAILED_STR "Failed to create directory" +#define LG_MSG_DIR_IS_SYMLINK_STR "dir is symlink" +#define LG_MSG_RESOLVE_HOSTNAME_FAILED_STR "couldnot resolve hostname" +#define LG_MSG_PATH_OPEN_FAILED_STR "Unable to open path" +#define LG_MSG_NO_MEMORY_STR "Error allocating memory" +#define LG_MSG_EVENT_NOTIFY_FAILED_STR "notification failed" +#define LG_MSG_PER_DENTRY_FAILED_STR "per dentry fn returned" +#define LG_MSG_PARENT_DENTRY_NOT_FOUND_STR "parent not found" +#define LG_MSG_DENTRY_CYCLIC_LOOP_STR \ + "detected cyclic loop formation during inode linkage" +#define LG_MSG_CTX_NULL_STR "_ctx not found" +#define LG_MSG_DENTRY_NOT_FOUND_STR "dentry not found" +#define LG_MSG_OUT_OF_RANGE_STR "out of range" +#define LG_MSG_UNKNOWN_OPTION_TYPE_STR "unknown option type" +#define LG_MSG_VALIDATE_RETURNS_STR "validate of returned" +#define LG_MSG_OPTION_DEPRECATED_STR \ + "option is deprecated, continuing with correction" +#define LG_MSG_VALIDATE_REC_FAILED_STR "validate_rec failed" +#define LG_MSG_MAPPING_FAILED_STR "mapping failed" +#define LG_MSG_INIT_IOBUF_FAILED_STR "init failed" +#define LG_MSG_ARENA_NOT_FOUND_STR "arena not found" +#define LG_MSG_PAGE_SIZE_EXCEEDED_STR \ + "page_size of iobufs in arena being added is greater than max available" +#define LG_MSG_POOL_NOT_FOUND_STR "pool not found" +#define LG_MSG_IOBUF_NOT_FOUND_STR "iobuf not found" +#define LG_MSG_DLOPEN_FAILED_STR "DL open failed" +#define LG_MSG_DLSYM_ERROR_STR "dlsym missing" +#define LG_MSG_LOAD_FAILED_STR "Failed to load xlator options table" +#define LG_MSG_INPUT_DATA_NULL_STR \ + "input data is null. cannot update the lru limit of the inode table. " \ + "continuing with older value." +#define LG_MSG_INIT_FAILED_STR "No init() found" +#define LG_MSG_VOLUME_ERROR_STR \ + "Initialization of volume failed. review your volfile again." +#define LG_MSG_TREE_NOT_FOUND_STR "Translator tree not found" +#define LG_MSG_SET_LOG_LEVEL_STR "setting log level" +#define LG_MSG_INVALID_INIT_STR \ + "Invalid log-level. possible values are DEBUG|WARNING|ERROR|NONE|TRACE" +#define LG_MSG_OBJECT_NULL_STR "object is null, returning false." +#define LG_MSG_GRAPH_NOT_SET_STR "Graph is not set for xlator" +#define LG_MSG_OPEN_LOGFILE_FAILED_STR "failed to open logfile" +#define LG_MSG_STRDUP_ERROR_STR "failed to create metrics dir" +#define LG_MSG_FILENAME_NOT_SPECIFIED_STR "no filename specified" +#define LG_MSG_UNDERSIZED_BUF_STR "data value is smaller than expected" +#define LG_MSG_DICT_SET_FAILED_STR "unable to set dict" +#define LG_MSG_COUNT_LESS_THAN_ZERO_STR "count < 0!" +#define LG_MSG_PAIRS_LESS_THAN_COUNT_STR "less than count data pairs found" +#define LG_MSG_NULL_PTR_STR "pair->key is null!" +#define LG_MSG_VALUE_LENGTH_LESS_THAN_ZERO_STR "value->len < 0" +#define LG_MSG_INVALID_ARG_STR "buf is null" +#define LG_MSG_KEY_OR_VALUE_NULL_STR "key or value is null" +#define LG_MSG_NULL_VALUE_IN_DICT_STR "null value found in dict" +#define LG_MSG_FAILED_TO_LOG_DICT_STR "Failed to log dictionary" +#define LG_MSG_DICT_ERROR_STR "dict error" +#define LG_MSG_STRUCT_MISS_STR "struct missing" +#define LG_MSG_METHOD_MISS_STR "method missing(init)" #endif /* !_LG_MESSAGES_H_ */ diff --git a/libglusterfs/src/glusterfs/mem-pool.h b/libglusterfs/src/glusterfs/mem-pool.h index e0441756be7..e5b3276d047 100644 --- a/libglusterfs/src/glusterfs/mem-pool.h +++ b/libglusterfs/src/glusterfs/mem-pool.h @@ -202,6 +202,24 @@ out: return dup_mem; } +#ifdef GF_DISABLE_MEMPOOL + +/* No-op memory pool enough to fit current API without massive redesign. */ + +struct mem_pool { + unsigned long sizeof_type; +}; + +#define mem_pools_init() \ + do { \ + } while (0) +#define mem_pools_fini() \ + do { \ + } while (0) +#define mem_pool_thread_destructor(pool_list) (void)pool_list + +#else /* !GF_DISABLE_MEMPOOL */ + /* kind of 'header' for the actual mem_pool_shared structure, this might make * it possible to dump some more details in a statedump */ struct mem_pool { @@ -209,10 +227,11 @@ struct mem_pool { unsigned long sizeof_type; unsigned long count; /* requested pool size (unused) */ char *name; - gf_atomic_t active; /* current allocations */ + char *xl_name; + gf_atomic_t active; /* current allocations */ #ifdef DEBUG - gf_atomic_t hit; /* number of allocations served from pt_pool */ - gf_atomic_t miss; /* number of std allocs due to miss */ + gf_atomic_t hit; /* number of allocations served from pt_pool */ + gf_atomic_t miss; /* number of std allocs due to miss */ #endif struct list_head owner; /* glusterfs_ctx_t->mempool_list */ glusterfs_ctx_t *ctx; /* take ctx->lock when updating owner */ @@ -244,24 +263,26 @@ typedef struct per_thread_pool { } per_thread_pool_t; typedef struct per_thread_pool_list { - /* - * These first two members are protected by the global pool lock. When - * a thread first tries to use any pool, we create one of these. We - * link it into the global list using thr_list so the pool-sweeper - * thread can find it, and use pthread_setspecific so this thread can - * find it. When the per-thread destructor runs, we "poison" the pool - * list to prevent further allocations. This also signals to the - * pool-sweeper thread that the list should be detached and freed after - * the next time it's swept. - */ + /* thr_list is used to place the TLS pool_list into the active global list + * (pool_threads) or the inactive global list (pool_free_threads). It's + * protected by the global pool_lock. */ struct list_head thr_list; - unsigned int poison; + + /* This lock is used to update poison and the hot/cold lists of members + * of 'pools' array. */ + pthread_spinlock_t lock; + + /* This field is used to mark a pool_list as not being owned by any thread. + * This means that the sweeper thread won't be cleaning objects stored in + * its pools. mem_put() uses it to decide if the object being released is + * placed into its original pool_list or directly destroyed. */ + bool poison; + /* * There's really more than one pool, but the actual number is hidden * in the implementation code so we just make it a single-element array * here. */ - pthread_spinlock_t lock; per_thread_pool_t pools[1]; } per_thread_pool_list_t; @@ -284,6 +305,10 @@ void mem_pools_init(void); /* start the pool_sweeper thread */ void mem_pools_fini(void); /* cleanup memory pools */ +void +mem_pool_thread_destructor(per_thread_pool_list_t *pool_list); + +#endif /* GF_DISABLE_MEMPOOL */ struct mem_pool * mem_pool_new_fn(glusterfs_ctx_t *ctx, unsigned long sizeof_type, @@ -306,9 +331,6 @@ void mem_pool_destroy(struct mem_pool *pool); void -mem_pool_thread_destructor(void); - -void gf_mem_acct_enable_set(void *ctx); #endif /* _MEM_POOL_H */ diff --git a/libglusterfs/src/glusterfs/mem-types.h b/libglusterfs/src/glusterfs/mem-types.h index 36cf7820ad5..d45d5b68c91 100644 --- a/libglusterfs/src/glusterfs/mem-types.h +++ b/libglusterfs/src/glusterfs/mem-types.h @@ -133,6 +133,7 @@ enum gf_common_mem_types_ { gf_common_volfile_t, gf_common_mt_mgmt_v3_lock_timer_t, /* used only in one location */ gf_common_mt_server_cmdline_t, /* used only in one location */ + gf_common_mt_latency_t, gf_common_mt_end }; #endif diff --git a/libglusterfs/src/glusterfs/stack.h b/libglusterfs/src/glusterfs/stack.h index 17585508a22..536a330d38b 100644 --- a/libglusterfs/src/glusterfs/stack.h +++ b/libglusterfs/src/glusterfs/stack.h @@ -45,6 +45,9 @@ typedef int32_t (*ret_fn_t)(call_frame_t *frame, call_frame_t *prev_frame, xlator_t *this, int32_t op_ret, int32_t op_errno, ...); +void +gf_frame_latency_update(call_frame_t *frame); + struct call_pool { union { struct list_head all_frames; @@ -149,8 +152,6 @@ struct _call_stack { } while (0); struct xlator_fops; -void -gf_update_latency(call_frame_t *frame); static inline void FRAME_DESTROY(call_frame_t *frame) @@ -158,7 +159,7 @@ FRAME_DESTROY(call_frame_t *frame) void *local = NULL; if (frame->root->ctx->measure_latency) - gf_update_latency(frame); + gf_frame_latency_update(frame); list_del_init(&frame->frames); if (frame->local) { @@ -429,6 +430,7 @@ call_stack_alloc_groups(call_stack_t *stack, int ngrps) if (ngrps <= SMALL_GROUP_COUNT) { stack->groups = stack->groups_small; } else { + GF_FREE(stack->groups_large); stack->groups_large = GF_CALLOC(ngrps, sizeof(gid_t), gf_common_mt_groups_t); if (!stack->groups_large) @@ -442,6 +444,12 @@ call_stack_alloc_groups(call_stack_t *stack, int ngrps) } static inline int +call_stack_groups_capacity(call_stack_t *stack) +{ + return max(stack->ngrps, SMALL_GROUP_COUNT); +} + +static inline int call_frames_count(call_stack_t *call_stack) { call_frame_t *pos; diff --git a/libglusterfs/src/glusterfs/statedump.h b/libglusterfs/src/glusterfs/statedump.h index 89d04f94587..ce082706bdf 100644 --- a/libglusterfs/src/glusterfs/statedump.h +++ b/libglusterfs/src/glusterfs/statedump.h @@ -127,4 +127,6 @@ gf_proc_dump_xlator_meminfo(xlator_t *this, strfd_t *strfd); void gf_proc_dump_xlator_profile(xlator_t *this, strfd_t *strfd); +void +gf_latency_statedump_and_reset(char *key, gf_latency_t *lat); #endif /* STATEDUMP_H */ diff --git a/libglusterfs/src/glusterfs/store.h b/libglusterfs/src/glusterfs/store.h index c8be544e164..a1f70c7b840 100644 --- a/libglusterfs/src/glusterfs/store.h +++ b/libglusterfs/src/glusterfs/store.h @@ -95,7 +95,7 @@ int32_t gf_store_iter_get_matching(gf_store_iter_t *iter, char *key, char **value); int32_t -gf_store_iter_destroy(gf_store_iter_t *iter); +gf_store_iter_destroy(gf_store_iter_t **iter); char * gf_store_strerror(gf_store_op_errno_t op_errno); diff --git a/libglusterfs/src/glusterfs/syncop.h b/libglusterfs/src/glusterfs/syncop.h index 3614d969264..4e9241a32fc 100644 --- a/libglusterfs/src/glusterfs/syncop.h +++ b/libglusterfs/src/glusterfs/syncop.h @@ -16,6 +16,8 @@ #include <ucontext.h> #include "glusterfs/dict.h" // for dict_t #include "glusterfs/stack.h" // for call_frame_t, STACK_DESTROY, STACK_... +#include "glusterfs/timer.h" + #define SYNCENV_PROC_MAX 16 #define SYNCENV_PROC_MIN 2 #define SYNCPROC_IDLE_TIME 600 @@ -29,9 +31,15 @@ #define SYNCOPCTX_PID 0x00000008 #define SYNCOPCTX_LKOWNER 0x00000010 +#ifdef HAVE_TSAN_API +/* Currently hardcoded within thread context maintained by the sanitizer. */ +#define TSAN_THREAD_NAMELEN 64 +#endif + struct synctask; struct syncproc; struct syncenv; +struct synccond; typedef int (*synctask_cbk_t)(int ret, call_frame_t *frame, void *opaque); @@ -55,9 +63,12 @@ struct synctask { call_frame_t *opframe; synctask_cbk_t synccbk; synctask_fn_t syncfn; - synctask_state_t state; + struct timespec *delta; + gf_timer_t *timer; + struct synccond *synccond; void *opaque; void *stack; + synctask_state_t state; int woken; int slept; int ret; @@ -65,6 +76,13 @@ struct synctask { uid_t uid; gid_t gid; +#ifdef HAVE_TSAN_API + struct { + void *fiber; + char name[TSAN_THREAD_NAMELEN]; + } tsan; +#endif + ucontext_t ctx; struct syncproc *proc; @@ -77,6 +95,14 @@ struct synctask { struct syncproc { pthread_t processor; + +#ifdef HAVE_TSAN_API + struct { + void *fiber; + char name[TSAN_THREAD_NAMELEN]; + } tsan; +#endif + ucontext_t sched; struct syncenv *env; struct synctask *current; @@ -85,19 +111,21 @@ struct syncproc { /* hosts the scheduler thread and framework for executing synctasks */ struct syncenv { struct syncproc proc[SYNCENV_PROC_MAX]; - int procs; + + pthread_mutex_t mutex; + pthread_cond_t cond; struct list_head runq; - int runcount; struct list_head waitq; - int waitcount; + + int procs; + int procs_idle; + + int runcount; int procmin; int procmax; - pthread_mutex_t mutex; - pthread_cond_t cond; - size_t stacksize; int destroy; /* FLAG to mark syncenv is in destroy mode @@ -123,6 +151,13 @@ struct synclock { }; typedef struct synclock synclock_t; +struct synccond { + pthread_mutex_t pmutex; + pthread_cond_t pcond; + struct list_head waitq; +}; +typedef struct synccond synccond_t; + struct syncbarrier { gf_boolean_t initialized; /*Set on successful initialization*/ pthread_mutex_t guard; /* guard the remaining members, pair @cond */ @@ -219,7 +254,7 @@ struct syncopctx { #define __yield(args) \ do { \ if (args->task) { \ - synctask_yield(args->task); \ + synctask_yield(args->task, NULL); \ } else { \ pthread_mutex_lock(&args->mutex); \ { \ @@ -240,7 +275,7 @@ struct syncopctx { task = synctask_get(); \ stb->task = task; \ if (task) \ - frame = task->opframe; \ + frame = copy_frame(task->opframe); \ else \ frame = syncop_create_frame(THIS); \ \ @@ -261,10 +296,7 @@ struct syncopctx { STACK_WIND_COOKIE(frame, cbk, (void *)stb, subvol, fn_op, params); \ \ __yield(stb); \ - if (task) \ - STACK_RESET(frame->root); \ - else \ - STACK_DESTROY(frame->root); \ + STACK_DESTROY(frame->root); \ } while (0) /* @@ -313,7 +345,9 @@ synctask_join(struct synctask *task); void synctask_wake(struct synctask *task); void -synctask_yield(struct synctask *task); +synctask_yield(struct synctask *task, struct timespec *delta); +void +synctask_sleep(int32_t secs); void synctask_waitfor(struct synctask *task, int count); @@ -411,6 +445,24 @@ synclock_trylock(synclock_t *lock); int synclock_unlock(synclock_t *lock); +int32_t +synccond_init(synccond_t *cond); + +void +synccond_destroy(synccond_t *cond); + +int +synccond_wait(synccond_t *cond, synclock_t *lock); + +int +synccond_timedwait(synccond_t *cond, synclock_t *lock, struct timespec *delta); + +void +synccond_signal(synccond_t *cond); + +void +synccond_broadcast(synccond_t *cond); + int syncbarrier_init(syncbarrier_t *barrier); int diff --git a/libglusterfs/src/glusterfs/syscall.h b/libglusterfs/src/glusterfs/syscall.h index 6b33c141a5e..b6d3ab4f2ad 100644 --- a/libglusterfs/src/glusterfs/syscall.h +++ b/libglusterfs/src/glusterfs/syscall.h @@ -96,18 +96,27 @@ int sys_unlink(const char *pathname); int +sys_unlinkat(int dfd, const char *pathname); + +int sys_rmdir(const char *pathname); int sys_symlink(const char *oldpath, const char *newpath); int +sys_symlinkat(const char *oldpath, int dirfd, const char *newpath); + +int sys_rename(const char *oldpath, const char *newpath); int sys_link(const char *oldpath, const char *newpath); int +sys_linkat(int oldfd, const char *oldpath, int newfd, const char *newpath); + +int sys_chmod(const char *path, mode_t mode); int @@ -257,4 +266,13 @@ ssize_t sys_copy_file_range(int fd_in, off64_t *off_in, int fd_out, off64_t *off_out, size_t len, unsigned int flags); +int +sys_kill(pid_t pid, int sig); + +#ifdef __FreeBSD__ +int +sys_sysctl(const int *name, u_int namelen, void *oldp, size_t *oldlenp, + const void *newp, size_t newlen); +#endif + #endif /* __SYSCALL_H__ */ diff --git a/libglusterfs/src/glusterfs/xlator.h b/libglusterfs/src/glusterfs/xlator.h index c94bd75cf1c..4fd3abdaeff 100644 --- a/libglusterfs/src/glusterfs/xlator.h +++ b/libglusterfs/src/glusterfs/xlator.h @@ -702,6 +702,8 @@ typedef size_t (*cbk_inodectx_size_t)(xlator_t *this, inode_t *inode); typedef size_t (*cbk_fdctx_size_t)(xlator_t *this, fd_t *fd); +typedef void (*cbk_fdclose_t)(xlator_t *this, fd_t *fd); + struct xlator_cbks { cbk_forget_t forget; cbk_release_t release; @@ -712,6 +714,8 @@ struct xlator_cbks { cbk_ictxmerge_t ictxmerge; cbk_inodectx_size_t ictxsize; cbk_fdctx_size_t fdctxsize; + cbk_fdclose_t fdclose; + cbk_fdclose_t fdclosedir; }; typedef int32_t (*dumpop_priv_t)(xlator_t *this); @@ -801,7 +805,7 @@ struct _xlator { struct { /* for latency measurement */ - fop_latency_t latencies[GF_FOP_MAXVALUE]; + gf_latency_t latencies[GF_FOP_MAXVALUE]; /* for latency measurement */ fop_metrics_t metrics[GF_FOP_MAXVALUE]; |