diff options
Diffstat (limited to 'libglusterfs/src/glusterfs')
64 files changed, 14313 insertions, 0 deletions
diff --git a/libglusterfs/src/glusterfs/atomic.h b/libglusterfs/src/glusterfs/atomic.h new file mode 100644 index 00000000000..ced81748218 --- /dev/null +++ b/libglusterfs/src/glusterfs/atomic.h @@ -0,0 +1,459 @@ +/* + Copyright (c) 2017 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _ATOMIC_H +#define _ATOMIC_H + +#include <inttypes.h> +#include <stdbool.h> + +#include "glusterfs/locking.h" + +/* Macros used to join two arguments and generate a new macro name. */ +#define GF_ATOMIC_MACRO_1(_macro) _macro +#define GF_ATOMIC_MACRO(_base, _name) GF_ATOMIC_MACRO_1(_base##_name) + +/* There's a problem on 32-bit architectures when we try to use atomic + * builtins with 64-bit types. Only way to solve the problem is to use + * a mutex to protect the access to the atomic, but we don't want to + * use mutexes for other smaller types that could work with the atomic + * builtins. + * + * So on each atomic type we add a field for the mutex if atomic operation + * is not supported and a dummy zero size field if it's supported. This way + * we can have different atomic types, some with a mutex and some without. + * + * To define these types, we use two macros: + * + * GF_ATOMIC_MUTEX_FIELD_0 = char lk[0] + * GF_ATOMIC_MUTEX_FILED_1 = gf_lock_t lk + * + * Both macros define the 'lk' field that will be used in the atomic + * structure. One when the atomic is supported by the architecture and + * another when not. We need to define the field even if it won't be + * used. Otherwise the compiler will return an error. + * + * Now we need to take the mutex or not depending on the existence of + * the mutex field in the structure. To do so we check the size of the + * structure, and if it's bigger than uint64_t (all structures with a + * mutex will be bigger), we use the mutex-based version. Otherwise we + * use the atomic builtin. This check is easily optimized out by the + * compiler, leaving a clean and efficient compiled code. */ + +#define GF_ATOMIC_MUTEX_FIELD_0 char lk[0] +#define GF_ATOMIC_MUTEX_FIELD_1 gf_lock_t lk + +/* We'll use SIZEOF_LONG to determine the architecture. 32-bit machines + * will have 4 here, while 64-bit machines will have 8. If additional + * needs or restrictions appear on other platforms, these tests can be + * extended to handle them. */ + +/* GF_ATOMIC_SIZE_X macros map each type size to one of the + * GF_ATOMIC_MUTEX_FIELD_X macros, depending on detected conditions. */ + +#if defined(HAVE_ATOMIC_BUILTINS) || defined(HAVE_SYNC_BUILTINS) + +#define GF_ATOMIC_SIZE_1 GF_ATOMIC_MUTEX_FIELD_0 +#define GF_ATOMIC_SIZE_2 GF_ATOMIC_MUTEX_FIELD_0 +#define GF_ATOMIC_SIZE_4 GF_ATOMIC_MUTEX_FIELD_0 + +#if SIZEOF_LONG >= 8 +#define GF_ATOMIC_SIZE_8 GF_ATOMIC_MUTEX_FIELD_0 +#endif + +#endif /* HAVE_(ATOMIC|SYNC)_BUILTINS */ + +/* Any GF_ATOMIC_SIZE_X macro not yet defined will use the mutex version */ +#ifndef GF_ATOMIC_SIZE_1 +#define GF_ATOMIC_SIZE_1 GF_ATOMIC_MUTEX_FIELD_1 +#endif + +#ifndef GF_ATOMIC_SIZE_2 +#define GF_ATOMIC_SIZE_2 GF_ATOMIC_MUTEX_FIELD_1 +#endif + +#ifndef GF_ATOMIC_SIZE_4 +#define GF_ATOMIC_SIZE_4 GF_ATOMIC_MUTEX_FIELD_1 +#endif + +#ifndef GF_ATOMIC_SIZE_8 +#define GF_ATOMIC_SIZE_8 GF_ATOMIC_MUTEX_FIELD_1 +#endif + +/* This macro is used to define all atomic types supported. First field + * represents the size of the type in bytes, and the second one the name. */ +#define GF_ATOMIC_TYPE(_size, _name) \ + typedef struct _gf_atomic_##_name##_t { \ + GF_ATOMIC_MACRO(GF_ATOMIC_SIZE_, _size); \ + _name##_t value; \ + } gf_atomic_##_name##_t + +/* The atomic types we support */ +GF_ATOMIC_TYPE(1, int8); /* gf_atomic_int8_t */ +GF_ATOMIC_TYPE(2, int16); /* gf_atomic_int16_t */ +GF_ATOMIC_TYPE(4, int32); /* gf_atomic_int32_t */ +GF_ATOMIC_TYPE(8, int64); /* gf_atomic_int64_t */ +GF_ATOMIC_TYPE(SIZEOF_LONG, intptr); /* gf_atomic_intptr_t */ +GF_ATOMIC_TYPE(1, uint8); /* gf_atomic_uint8_t */ +GF_ATOMIC_TYPE(2, uint16); /* gf_atomic_uint16_t */ +GF_ATOMIC_TYPE(4, uint32); /* gf_atomic_uint32_t */ +GF_ATOMIC_TYPE(8, uint64); /* gf_atomic_uint64_t */ +GF_ATOMIC_TYPE(SIZEOF_LONG, uintptr); /* gf_atomic_uintptr_t */ + +/* Define the default atomic type as int64_t */ +#define gf_atomic_t gf_atomic_int64_t + +/* This macro will choose between the mutex based version and the atomic + * builtin version depending on the size of the atomic structure. */ +#define GF_ATOMIC_CHOOSE(_atomic, _op, _args...) \ + ((sizeof(_atomic) > sizeof(uint64_t)) \ + ? ({ \ + GF_ATOMIC_MACRO(GF_ATOMIC_LOCK_, _op) \ + (_atomic, ##_args); \ + }) \ + : ({ \ + GF_ATOMIC_MACRO(GF_ATOMIC_BASE_, _op) \ + (_atomic, ##_args); \ + })) + +/* Macros to implement the mutex-based atomics. */ +#define GF_ATOMIC_OP_PREPARE(_atomic, _name) \ + typeof(_atomic) *__atomic = &(_atomic); \ + gf_lock_t *__lock = (gf_lock_t *)&__atomic->lk; \ + LOCK(__lock); \ + typeof(__atomic->value) _name = __atomic->value + +#define GF_ATOMIC_OP_STORE(_value) (__atomic->value = (_value)) + +#define GF_ATOMIC_OP_RETURN(_value) \ + ({ \ + UNLOCK(__lock); \ + _value; \ + }) + +#define GF_ATOMIC_LOCK_INIT(_atomic, _value) \ + do { \ + typeof(_atomic) *__atomic = &(_atomic); \ + LOCK_INIT((gf_lock_t *)&__atomic->lk); \ + __atomic->value = (_value); \ + } while (0) + +#define GF_ATOMIC_LOCK_GET(_atomic) \ + ({ \ + GF_ATOMIC_OP_PREPARE(_atomic, __value); \ + GF_ATOMIC_OP_RETURN(__value); \ + }) + +#define GF_ATOMIC_LOCK_ADD(_atomic, _value) \ + ({ \ + GF_ATOMIC_OP_PREPARE(_atomic, __value); \ + GF_ATOMIC_OP_STORE(__value += (_value)); \ + GF_ATOMIC_OP_RETURN(__value); \ + }) + +#define GF_ATOMIC_LOCK_SUB(_atomic, _value) \ + ({ \ + GF_ATOMIC_OP_PREPARE(_atomic, __value); \ + GF_ATOMIC_OP_STORE(__value -= (_value)); \ + GF_ATOMIC_OP_RETURN(__value); \ + }) + +#define GF_ATOMIC_LOCK_AND(_atomic, _value) \ + ({ \ + GF_ATOMIC_OP_PREPARE(_atomic, __value); \ + GF_ATOMIC_OP_STORE(__value &= (_value)); \ + GF_ATOMIC_OP_RETURN(__value); \ + }) + +#define GF_ATOMIC_LOCK_OR(_atomic, _value) \ + ({ \ + GF_ATOMIC_OP_PREPARE(_atomic, __value); \ + GF_ATOMIC_OP_STORE(__value |= (_value)); \ + GF_ATOMIC_OP_RETURN(__value); \ + }) + +#define GF_ATOMIC_LOCK_XOR(_atomic, _value) \ + ({ \ + GF_ATOMIC_OP_PREPARE(_atomic, __value); \ + GF_ATOMIC_OP_STORE(__value ^= (_value)); \ + GF_ATOMIC_OP_RETURN(__value); \ + }) + +#define GF_ATOMIC_LOCK_NAND(_atomic, _value) \ + ({ \ + GF_ATOMIC_OP_PREPARE(_atomic, __value); \ + GF_ATOMIC_OP_STORE(__value = ~(__value & (_value))); \ + GF_ATOMIC_OP_RETURN(__value); \ + }) + +#define GF_ATOMIC_LOCK_FETCH_ADD(_atomic, _value) \ + ({ \ + GF_ATOMIC_OP_PREPARE(_atomic, __value); \ + GF_ATOMIC_OP_STORE(__value + (_value)); \ + GF_ATOMIC_OP_RETURN(__value); \ + }) + +#define GF_ATOMIC_LOCK_FETCH_SUB(_atomic, _value) \ + ({ \ + GF_ATOMIC_OP_PREPARE(_atomic, __value); \ + GF_ATOMIC_OP_STORE(__value - (_value)); \ + GF_ATOMIC_OP_RETURN(__value); \ + }) + +#define GF_ATOMIC_LOCK_FETCH_AND(_atomic, _value) \ + ({ \ + GF_ATOMIC_OP_PREPARE(_atomic, __value); \ + GF_ATOMIC_OP_STORE(__value &(_value)); \ + GF_ATOMIC_OP_RETURN(__value); \ + }) + +#define GF_ATOMIC_LOCK_FETCH_OR(_atomic, _value) \ + ({ \ + GF_ATOMIC_OP_PREPARE(_atomic, __value); \ + GF_ATOMIC_OP_STORE(__value | (_value)); \ + GF_ATOMIC_OP_RETURN(__value); \ + }) + +#define GF_ATOMIC_LOCK_FETCH_XOR(_atomic, _value) \ + ({ \ + GF_ATOMIC_OP_PREPARE(_atomic, __value); \ + GF_ATOMIC_OP_STORE(__value ^ (_value)); \ + GF_ATOMIC_OP_RETURN(__value); \ + }) + +#define GF_ATOMIC_LOCK_FETCH_NAND(_atomic, _value) \ + ({ \ + GF_ATOMIC_OP_PREPARE(_atomic, __value); \ + GF_ATOMIC_OP_STORE(~(__value & (_value))); \ + GF_ATOMIC_OP_RETURN(__value); \ + }) + +#define GF_ATOMIC_LOCK_SWAP(_atomic, _value) \ + ({ \ + GF_ATOMIC_OP_PREPARE(_atomic, __value); \ + GF_ATOMIC_OP_STORE(_value); \ + GF_ATOMIC_OP_RETURN(__value); \ + }) + +#define GF_ATOMIC_LOCK_CMP_SWAP(_atomic, _expected, _value) \ + ({ \ + GF_ATOMIC_OP_PREPARE(_atomic, __value); \ + bool __ret = (__value == (_expected)); \ + if (__ret) { \ + GF_ATOMIC_OP_STORE(_value); \ + } \ + GF_ATOMIC_OP_RETURN(__ret); \ + }) + +#if defined(HAVE_ATOMIC_BUILTINS) + +/* If compiler supports __atomic builtins, we use them. */ + +#define GF_ATOMIC_BASE_INIT(_atomic, _value) \ + __atomic_store_n(&(_atomic).value, (_value), __ATOMIC_RELEASE) + +#define GF_ATOMIC_BASE_GET(_atomic) \ + __atomic_load_n(&(_atomic).value, __ATOMIC_ACQUIRE) + +#define GF_ATOMIC_BASE_ADD(_atomic, _value) \ + __atomic_add_fetch(&(_atomic).value, (_value), __ATOMIC_ACQ_REL) + +#define GF_ATOMIC_BASE_SUB(_atomic, _value) \ + __atomic_sub_fetch(&(_atomic).value, (_value), __ATOMIC_ACQ_REL) + +#define GF_ATOMIC_BASE_AND(_atomic, _value) \ + __atomic_and_fetch(&(_atomic).value, (_value), __ATOMIC_ACQ_REL) + +#define GF_ATOMIC_BASE_OR(_atomic, _value) \ + __atomic_or_fetch(&(_atomic).value, (_value), __ATOMIC_ACQ_REL) + +#define GF_ATOMIC_BASE_XOR(_atomic, _value) \ + __atomic_xor_fetch(&(_atomic).value, (_value), __ATOMIC_ACQ_REL) + +#define GF_ATOMIC_BASE_NAND(_atomic, _value) \ + __atomic_nand_fetch(&(_atomic).value, (_value), __ATOMIC_ACQ_REL) + +#define GF_ATOMIC_BASE_FETCH_ADD(_atomic, _value) \ + __atomic_fetch_add(&(_atomic).value, (_value), __ATOMIC_ACQ_REL) + +#define GF_ATOMIC_BASE_FETCH_SUB(_atomic, _value) \ + __atomic_fetch_sub(&(_atomic).value, (_value), __ATOMIC_ACQ_REL) + +#define GF_ATOMIC_BASE_FETCH_AND(_atomic, _value) \ + __atomic_fetch_and(&(_atomic).value, (_value), __ATOMIC_ACQ_REL) + +#define GF_ATOMIC_BASE_FETCH_OR(_atomic, _value) \ + __atomic_fetch_or(&(_atomic).value, (_value), __ATOMIC_ACQ_REL) + +#define GF_ATOMIC_BASE_FETCH_XOR(_atomic, _value) \ + __atomic_fetch_xor(&(_atomic).value, (_value), __ATOMIC_ACQ_REL) + +#define GF_ATOMIC_BASE_FETCH_NAND(_atomic, _value) \ + __atomic_fetch_nand(&(_atomic).value, (_value), __ATOMIC_ACQ_REL) + +#define GF_ATOMIC_BASE_SWAP(_atomic, _value) \ + __atomic_exchange_n(&(_atomic).value, (_value), __ATOMIC_ACQ_REL) + +#define GF_ATOMIC_BASE_CMP_SWAP(_atomic, _expected, _value) \ + ({ \ + typeof((_atomic).value) __expected = (_expected); \ + __atomic_compare_exchange_n(&(_atomic).value, &__expected, (_value), \ + 0, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE); \ + }) + +#elif defined(HAVE_SYNC_BUILTINS) + +/* If compiler doesn't support __atomic builtins but supports __sync builtins, + * we use them. */ + +#define GF_ATOMIC_BASE_INIT(_atomic, _value) \ + do { \ + (_atomic).value = (_value); \ + __sync_synchronize(); \ + } while (0) + +#define GF_ATOMIC_BASE_ADD(_atomic, _value) \ + __sync_add_and_fetch(&(_atomic).value, (_value)) + +#define GF_ATOMIC_BASE_SUB(_atomic, _value) \ + __sync_sub_and_fetch(&(_atomic).value, (_value)) + +#define GF_ATOMIC_BASE_AND(_atomic, _value) \ + __sync_and_and_fetch(&(_atomic).value, (_value)) + +#define GF_ATOMIC_BASE_OR(_atomic, _value) \ + __sync_or_and_fetch(&(_atomic).value, (_value)) + +#define GF_ATOMIC_BASE_XOR(_atomic, _value) \ + __sync_xor_and_fetch(&(_atomic).value, (_value)) + +#define GF_ATOMIC_BASE_NAND(_atomic, _value) \ + __sync_nand_and_fetch(&(_atomic).value, (_value)) + +#define GF_ATOMIC_BASE_FETCH_ADD(_atomic, _value) \ + __sync_fetch_and_add(&(_atomic).value, (_value)) + +#define GF_ATOMIC_BASE_FETCH_SUB(_atomic, _value) \ + __sync_fetch_and_sub(&(_atomic).value, (_value)) + +#define GF_ATOMIC_BASE_FETCH_AND(_atomic, _value) \ + __sync_fetch_and_and(&(_atomic).value, (_value)) + +#define GF_ATOMIC_BASE_FETCH_OR(_atomic, _value) \ + __sync_fetch_and_or(&(_atomic).value, (_value)) + +#define GF_ATOMIC_BASE_FETCH_XOR(_atomic, _value) \ + __sync_fetch_and_xor(&(_atomic).value, (_value)) + +#define GF_ATOMIC_BASE_FETCH_NAND(_atomic, _value) \ + __sync_fetch_and_nand(&(_atomic).value, (_value)) + +#define GF_ATOMIC_BASE_SWAP(_atomic, _value) \ + ({ \ + __sync_synchronize(); \ + __sync_lock_test_and_set(&(_atomic).value, (_value)); \ + }) + +#define GF_ATOMIC_BASE_CMP_SWAP(_atomic, _expected, _value) \ + __sync_bool_compare_and_swap(&(_atomic).value, (_expected), (_value)) + +#define GF_ATOMIC_BASE_GET(_atomic) GF_ATOMIC_BASE_ADD(_atomic, 0) + +#else /* !HAVE_ATOMIC_BUILTINS && !HAVE_SYNC_BUILTINS */ + +/* The compiler doesn't support any atomic builtin. We fallback to the + * mutex-based implementation. */ + +#define GF_ATOMIC_BASE_INIT(_atomic, _value) \ + GF_ATOMIC_LOCK_INIT(_atomic, _value) + +#define GF_ATOMIC_BASE_GET(_atomic) GF_ATOMIC_LOCK_GET(_atomic) + +#define GF_ATOMIC_BASE_ADD(_atomic, _value) GF_ATOMIC_LOCK_ADD(_atomic, _value) + +#define GF_ATOMIC_BASE_SUB(_atomic, _value) GF_ATOMIC_LOCK_SUB(_atomic, _value) + +#define GF_ATOMIC_BASE_AND(_atomic, _value) GF_ATOMIC_LOCK_AND(_atomic, _value) + +#define GF_ATOMIC_BASE_OR(_atomic, _value) GF_ATOMIC_LOCK_OR(_atomic, _value) + +#define GF_ATOMIC_BASE_XOR(_atomic, _value) GF_ATOMIC_LOCK_XOR(_atomic, _value) + +#define GF_ATOMIC_BASE_NAND(_atomic, _value) \ + GF_ATOMIC_LOCK_NAND(_atomic, _value) + +#define GF_ATOMIC_BASE_FETCH_ADD(_atomic, _value) \ + GF_ATOMIC_LOCK_FETCH_ADD(_atomic, _value) + +#define GF_ATOMIC_BASE_FETCH_SUB(_atomic, _value) \ + GF_ATOMIC_LOCK_FETCH_SUB(_atomic, _value) + +#define GF_ATOMIC_BASE_FETCH_AND(_atomic, _value) \ + GF_ATOMIC_LOCK_FETCH_AND(_atomic, _value) + +#define GF_ATOMIC_BASE_FETCH_OR(_atomic, _value) \ + GF_ATOMIC_LOCK_FETCH_OR(_atomic, _value) + +#define GF_ATOMIC_BASE_FETCH_XOR(_atomic, _value) \ + GF_ATOMIC_LOCK_FETCH_XOR(_atomic, _value) + +#define GF_ATOMIC_BASE_FETCH_NAND(_atomic, _value) \ + GF_ATOMIC_LOCK_FETCH_NAND(_atomic, _value) + +#define GF_ATOMIC_BASE_SWAP(_atomic, _value) \ + GF_ATOMIC_LOCK_SWAP(_atomic, _value) + +#define GF_ATOMIC_BASE_CMP_SWAP(_atomic, _expected, _value) \ + GF_ATOMIC_LOCK_CMP_SWAP(_atomic, _expected, _value) + +#endif /* HAVE_(ATOMIC|SYNC)_BUILTINS */ + +/* Here we declare the real atomic macros available to the user. */ + +/* All macros have a 'gf_atomic_xxx' as 1st argument */ + +#define GF_ATOMIC_INIT(_atomic, _value) GF_ATOMIC_CHOOSE(_atomic, INIT, _value) +#define GF_ATOMIC_GET(_atomic) GF_ATOMIC_CHOOSE(_atomic, GET) +#define GF_ATOMIC_ADD(_atomic, _value) GF_ATOMIC_CHOOSE(_atomic, ADD, _value) +#define GF_ATOMIC_SUB(_atomic, _value) GF_ATOMIC_CHOOSE(_atomic, SUB, _value) +#define GF_ATOMIC_AND(_atomic, _value) GF_ATOMIC_CHOOSE(_atomic, AND, _value) +#define GF_ATOMIC_OR(_atomic, _value) GF_ATOMIC_CHOOSE(_atomic, OR, _value) +#define GF_ATOMIC_XOR(_atomic, _value) GF_ATOMIC_CHOOSE(_atomic, XOR, _value) +#define GF_ATOMIC_NAND(_atomic, _value) GF_ATOMIC_CHOOSE(_atomic, NAND, _value) + +#define GF_ATOMIC_FETCH_ADD(_atomic, _value) \ + GF_ATOMIC_CHOOSE(_atomic, FETCH_ADD, _value) + +#define GF_ATOMIC_FETCH_SUB(_atomic, _value) \ + GF_ATOMIC_CHOOSE(_atomic, FETCH_SUB, _value) + +#define GF_ATOMIC_FETCH_AND(_atomic, _value) \ + GF_ATOMIC_CHOOSE(_atomic, FETCH_AND, _value) + +#define GF_ATOMIC_FETCH_OR(_atomic, _value) \ + GF_ATOMIC_CHOOSE(_atomic, FETCH_OR, _value) + +#define GF_ATOMIC_FETCH_XOR(_atomic, _value) \ + GF_ATOMIC_CHOOSE(_atomic, FETCH_XOR, _value) + +#define GF_ATOMIC_FETCH_NAND(_atomic, _value) \ + GF_ATOMIC_CHOOSE(_atomic, FETCH_NAND, _value) + +#define GF_ATOMIC_SWAP(_atomic, _value) GF_ATOMIC_CHOOSE(_atomic, SWAP, _value) + +#define GF_ATOMIC_CMP_SWAP(_atomic, _expected, _value) \ + GF_ATOMIC_CHOOSE(_atomic, CMP_SWAP, _expected, _value) + +#define GF_ATOMIC_INC(_atomic) GF_ATOMIC_ADD(_atomic, 1) +#define GF_ATOMIC_DEC(_atomic) GF_ATOMIC_SUB(_atomic, 1) +#define GF_ATOMIC_FETCH_INC(_atomic) GF_ATOMIC_FETCH_ADD(_atomic, 1) +#define GF_ATOMIC_FETCH_DEC(_atomic) GF_ATOMIC_FETCH_SUB(_atomic, 1) + +#endif /* _ATOMIC_H */ diff --git a/libglusterfs/src/glusterfs/byte-order.h b/libglusterfs/src/glusterfs/byte-order.h new file mode 100644 index 00000000000..fd8cef9e58d --- /dev/null +++ b/libglusterfs/src/glusterfs/byte-order.h @@ -0,0 +1,279 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _BYTE_ORDER_H +#define _BYTE_ORDER_H + +#include <inttypes.h> + +#define LS1 0x00ffU +#define MS1 0xff00U +#define LS2 0x0000ffffU +#define MS2 0xffff0000U +#define LS4 0x00000000ffffffffULL +#define MS4 0xffffffff00000000ULL + +static uint16_t (*hton16)(uint16_t); +static uint32_t (*hton32)(uint32_t); +static uint64_t (*hton64)(uint64_t); + +#define ntoh16 hton16 +#define ntoh32 hton32 +#define ntoh64 hton64 + +static uint16_t (*htole16)(uint16_t); +static uint32_t (*htole32)(uint32_t); +static uint64_t (*htole64)(uint64_t); + +#define letoh16 htole16 +#define letoh32 htole32 +#define letoh64 htole64 + +static uint16_t (*htobe16)(uint16_t); +static uint32_t (*htobe32)(uint32_t); +static uint64_t (*htobe64)(uint64_t); + +#define betoh16 htobe16 +#define betoh32 htobe32 +#define betoh64 htobe64 + +#define do_swap2(x) (((x & LS1) << 8) | (((x & MS1) >> 8))) +#define do_swap4(x) ((do_swap2(x & LS2) << 16) | (do_swap2((x & MS2) >> 16))) +#define do_swap8(x) ((do_swap4(x & LS4) << 32) | (do_swap4((x & MS4) >> 32))) + +static inline uint16_t +__swap16(uint16_t x) +{ + return do_swap2(x); +} + +static inline uint32_t +__swap32(uint32_t x) +{ + return do_swap4(x); +} + +static inline uint64_t +__swap64(uint64_t x) +{ + return do_swap8(x); +} + +static inline uint16_t +__noswap16(uint16_t x) +{ + return x; +} + +static inline uint32_t +__noswap32(uint32_t x) +{ + return x; +} + +static inline uint64_t +__noswap64(uint64_t x) +{ + return x; +} + +static inline uint16_t +__byte_order_n16(uint16_t i) +{ + uint32_t num = 1; + + if (((char *)(&num))[0] == 1) { + /* cpu is le */ + hton16 = __swap16; + hton32 = __swap32; + hton64 = __swap64; + } else { + /* cpu is be */ + hton16 = __noswap16; + hton32 = __noswap32; + hton64 = __noswap64; + } + + return hton16(i); +} + +static inline uint32_t +__byte_order_n32(uint32_t i) +{ + uint32_t num = 1; + + if (((char *)(&num))[0] == 1) { + /* cpu is le */ + hton16 = __swap16; + hton32 = __swap32; + hton64 = __swap64; + } else { + /* cpu is be */ + hton16 = __noswap16; + hton32 = __noswap32; + hton64 = __noswap64; + } + + return hton32(i); +} + +static inline uint64_t +__byte_order_n64(uint64_t i) +{ + uint32_t num = 1; + + if (((char *)(&num))[0] == 1) { + /* cpu is le */ + hton16 = __swap16; + hton32 = __swap32; + hton64 = __swap64; + } else { + /* cpu is be */ + hton16 = __noswap16; + hton32 = __noswap32; + hton64 = __noswap64; + } + + return hton64(i); +} + +static uint16_t (*hton16)(uint16_t) = __byte_order_n16; +static uint32_t (*hton32)(uint32_t) = __byte_order_n32; +static uint64_t (*hton64)(uint64_t) = __byte_order_n64; + +static inline uint16_t +__byte_order_le16(uint16_t i) +{ + uint32_t num = 1; + + if (((char *)(&num))[0] == 1) { + /* cpu is le */ + htole16 = __noswap16; + htole32 = __noswap32; + htole64 = __noswap64; + } else { + /* cpu is be */ + htole16 = __swap16; + htole32 = __swap32; + htole64 = __swap64; + } + + return htole16(i); +} + +static inline uint32_t +__byte_order_le32(uint32_t i) +{ + uint32_t num = 1; + + if (((char *)(&num))[0] == 1) { + /* cpu is le */ + htole16 = __noswap16; + htole32 = __noswap32; + htole64 = __noswap64; + } else { + /* cpu is be */ + htole16 = __swap16; + htole32 = __swap32; + htole64 = __swap64; + } + + return htole32(i); +} + +static inline uint64_t +__byte_order_le64(uint64_t i) +{ + uint32_t num = 1; + + if (((char *)(&num))[0] == 1) { + /* cpu is le */ + htole16 = __noswap16; + htole32 = __noswap32; + htole64 = __noswap64; + } else { + /* cpu is be */ + htole16 = __swap16; + htole32 = __swap32; + htole64 = __swap64; + } + + return htole64(i); +} + +static uint16_t (*htole16)(uint16_t) = __byte_order_le16; +static uint32_t (*htole32)(uint32_t) = __byte_order_le32; +static uint64_t (*htole64)(uint64_t) = __byte_order_le64; + +static inline uint16_t +__byte_order_be16(uint16_t i) +{ + uint32_t num = 1; + + if (((char *)(&num))[0] == 1) { + /* cpu is le */ + htobe16 = __swap16; + htobe32 = __swap32; + htobe64 = __swap64; + } else { + /* cpu is be */ + htobe16 = __noswap16; + htobe32 = __noswap32; + htobe64 = __noswap64; + } + + return htobe16(i); +} + +static inline uint32_t +__byte_order_be32(uint32_t i) +{ + uint32_t num = 1; + + if (((char *)(&num))[0] == 1) { + /* cpu is le */ + htobe16 = __swap16; + htobe32 = __swap32; + htobe64 = __swap64; + } else { + /* cpu is be */ + htobe16 = __noswap16; + htobe32 = __noswap32; + htobe64 = __noswap64; + } + + return htobe32(i); +} + +static inline uint64_t +__byte_order_be64(uint64_t i) +{ + uint32_t num = 1; + + if (((char *)(&num))[0] == 1) { + /* cpu is le */ + htobe16 = __swap16; + htobe32 = __swap32; + htobe64 = __swap64; + } else { + /* cpu is be */ + htobe16 = __noswap16; + htobe32 = __noswap32; + htobe64 = __noswap64; + } + + return htobe64(i); +} + +static uint16_t (*htobe16)(uint16_t) = __byte_order_be16; +static uint32_t (*htobe32)(uint32_t) = __byte_order_be32; +static uint64_t (*htobe64)(uint64_t) = __byte_order_be64; + +#endif /* _BYTE_ORDER_H */ diff --git a/libglusterfs/src/glusterfs/call-stub.h b/libglusterfs/src/glusterfs/call-stub.h new file mode 100644 index 00000000000..bfed0fbc14a --- /dev/null +++ b/libglusterfs/src/glusterfs/call-stub.h @@ -0,0 +1,610 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _CALL_STUB_H_ +#define _CALL_STUB_H_ + +#include "glusterfs/xlator.h" +#include "glusterfs/defaults.h" +#include "glusterfs/default-args.h" +#include "glusterfs/stack.h" +#include "glusterfs/list.h" + +typedef struct _call_stub { + struct list_head list; + char wind; + call_frame_t *frame; + glusterfs_fop_t fop; + gf_boolean_t poison; + struct mem_pool *stub_mem_pool; /* pointer to stub mempool in ctx_t */ + uint32_t jnl_meta_len; + uint32_t jnl_data_len; + void (*serialize)(struct _call_stub *, char *, char *); + + union { + fop_lookup_t lookup; + fop_stat_t stat; + fop_fstat_t fstat; + fop_truncate_t truncate; + fop_ftruncate_t ftruncate; + fop_access_t access; + fop_readlink_t readlink; + fop_mknod_t mknod; + fop_mkdir_t mkdir; + fop_unlink_t unlink; + fop_rmdir_t rmdir; + fop_symlink_t symlink; + fop_rename_t rename; + fop_link_t link; + fop_create_t create; + fop_open_t open; + fop_readv_t readv; + fop_writev_t writev; + fop_flush_t flush; + fop_fsync_t fsync; + fop_opendir_t opendir; + fop_fsyncdir_t fsyncdir; + fop_statfs_t statfs; + fop_setxattr_t setxattr; + fop_getxattr_t getxattr; + fop_fgetxattr_t fgetxattr; + fop_fsetxattr_t fsetxattr; + fop_removexattr_t removexattr; + fop_fremovexattr_t fremovexattr; + fop_lk_t lk; + fop_inodelk_t inodelk; + fop_finodelk_t finodelk; + fop_entrylk_t entrylk; + fop_fentrylk_t fentrylk; + fop_readdir_t readdir; + fop_readdirp_t readdirp; + fop_rchecksum_t rchecksum; + fop_xattrop_t xattrop; + fop_fxattrop_t fxattrop; + fop_setattr_t setattr; + fop_fsetattr_t fsetattr; + fop_fallocate_t fallocate; + fop_discard_t discard; + fop_zerofill_t zerofill; + fop_ipc_t ipc; + fop_seek_t seek; + fop_lease_t lease; + fop_getactivelk_t getactivelk; + fop_setactivelk_t setactivelk; + fop_put_t put; + fop_icreate_t icreate; + fop_namelink_t namelink; + } fn; + + union { + fop_lookup_cbk_t lookup; + fop_stat_cbk_t stat; + fop_fstat_cbk_t fstat; + fop_truncate_cbk_t truncate; + fop_ftruncate_cbk_t ftruncate; + fop_access_cbk_t access; + fop_readlink_cbk_t readlink; + fop_mknod_cbk_t mknod; + fop_mkdir_cbk_t mkdir; + fop_unlink_cbk_t unlink; + fop_rmdir_cbk_t rmdir; + fop_symlink_cbk_t symlink; + fop_rename_cbk_t rename; + fop_link_cbk_t link; + fop_create_cbk_t create; + fop_open_cbk_t open; + fop_readv_cbk_t readv; + fop_writev_cbk_t writev; + fop_flush_cbk_t flush; + fop_fsync_cbk_t fsync; + fop_opendir_cbk_t opendir; + fop_fsyncdir_cbk_t fsyncdir; + fop_statfs_cbk_t statfs; + fop_setxattr_cbk_t setxattr; + fop_getxattr_cbk_t getxattr; + fop_fgetxattr_cbk_t fgetxattr; + fop_fsetxattr_cbk_t fsetxattr; + fop_removexattr_cbk_t removexattr; + fop_fremovexattr_cbk_t fremovexattr; + fop_lk_cbk_t lk; + fop_inodelk_cbk_t inodelk; + fop_finodelk_cbk_t finodelk; + fop_entrylk_cbk_t entrylk; + fop_fentrylk_cbk_t fentrylk; + fop_readdir_cbk_t readdir; + fop_readdirp_cbk_t readdirp; + fop_rchecksum_cbk_t rchecksum; + fop_xattrop_cbk_t xattrop; + fop_fxattrop_cbk_t fxattrop; + fop_setattr_cbk_t setattr; + fop_fsetattr_cbk_t fsetattr; + fop_fallocate_cbk_t fallocate; + fop_discard_cbk_t discard; + fop_zerofill_cbk_t zerofill; + fop_ipc_cbk_t ipc; + fop_seek_cbk_t seek; + fop_lease_cbk_t lease; + fop_getactivelk_cbk_t getactivelk; + fop_setactivelk_cbk_t setactivelk; + fop_put_cbk_t put; + fop_icreate_cbk_t icreate; + fop_namelink_cbk_t namelink; + } fn_cbk; + + default_args_t args; + default_args_cbk_t args_cbk; +} call_stub_t; + +call_stub_t * +fop_lookup_stub(call_frame_t *frame, fop_lookup_t fn, loc_t *loc, + dict_t *xdata); + +call_stub_t * +fop_lookup_cbk_stub(call_frame_t *frame, fop_lookup_cbk_t fn, int32_t op_ret, + int32_t op_errno, inode_t *inode, struct iatt *buf, + dict_t *xdata, struct iatt *postparent); +call_stub_t * +fop_stat_stub(call_frame_t *frame, fop_stat_t fn, loc_t *loc, dict_t *xdata); +call_stub_t * +fop_stat_cbk_stub(call_frame_t *frame, fop_stat_cbk_t fn, int32_t op_ret, + int32_t op_errno, struct iatt *buf, dict_t *xdata); +call_stub_t * +fop_fstat_stub(call_frame_t *frame, fop_fstat_t fn, fd_t *fd, dict_t *xdata); +call_stub_t * +fop_fstat_cbk_stub(call_frame_t *frame, fop_fstat_cbk_t fn, int32_t op_ret, + int32_t op_errno, struct iatt *buf, dict_t *xdata); + +call_stub_t * +fop_truncate_stub(call_frame_t *frame, fop_truncate_t fn, loc_t *loc, off_t off, + dict_t *xdata); + +call_stub_t * +fop_truncate_cbk_stub(call_frame_t *frame, fop_truncate_cbk_t fn, + int32_t op_ret, int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata); + +call_stub_t * +fop_ftruncate_stub(call_frame_t *frame, fop_ftruncate_t fn, fd_t *fd, off_t off, + dict_t *xdata); + +call_stub_t * +fop_ftruncate_cbk_stub(call_frame_t *frame, fop_ftruncate_cbk_t fn, + int32_t op_ret, int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata); + +call_stub_t * +fop_access_stub(call_frame_t *frame, fop_access_t fn, loc_t *loc, int32_t mask, + dict_t *xdata); + +call_stub_t * +fop_access_cbk_stub(call_frame_t *frame, fop_access_cbk_t fn, int32_t op_ret, + int32_t op_errno, dict_t *xdata); + +call_stub_t * +fop_readlink_stub(call_frame_t *frame, fop_readlink_t fn, loc_t *loc, + size_t size, dict_t *xdata); + +call_stub_t * +fop_readlink_cbk_stub(call_frame_t *frame, fop_readlink_cbk_t fn, + int32_t op_ret, int32_t op_errno, const char *path, + struct iatt *buf, dict_t *xdata); + +call_stub_t * +fop_mknod_stub(call_frame_t *frame, fop_mknod_t fn, loc_t *loc, mode_t mode, + dev_t rdev, mode_t umask, dict_t *xdata); + +call_stub_t * +fop_mknod_cbk_stub(call_frame_t *frame, fop_mknod_cbk_t fn, int32_t op_ret, + int32_t op_errno, inode_t *inode, struct iatt *buf, + struct iatt *preparent, struct iatt *postparent, + dict_t *xdata); + +call_stub_t * +fop_mkdir_stub(call_frame_t *frame, fop_mkdir_t fn, loc_t *loc, mode_t mode, + mode_t umask, dict_t *xdata); + +call_stub_t * +fop_mkdir_cbk_stub(call_frame_t *frame, fop_mkdir_cbk_t fn, int32_t op_ret, + int32_t op_errno, inode_t *inode, struct iatt *buf, + struct iatt *preparent, struct iatt *postparent, + dict_t *xdata); + +call_stub_t * +fop_unlink_stub(call_frame_t *frame, fop_unlink_t fn, loc_t *loc, int xflag, + dict_t *xdata); + +call_stub_t * +fop_unlink_cbk_stub(call_frame_t *frame, fop_unlink_cbk_t fn, int32_t op_ret, + int32_t op_errno, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); + +call_stub_t * +fop_rmdir_stub(call_frame_t *frame, fop_rmdir_t fn, loc_t *loc, int flags, + dict_t *xdata); + +call_stub_t * +fop_rmdir_cbk_stub(call_frame_t *frame, fop_rmdir_cbk_t fn, int32_t op_ret, + int32_t op_errno, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); + +call_stub_t * +fop_symlink_stub(call_frame_t *frame, fop_symlink_t fn, const char *linkname, + loc_t *loc, mode_t umask, dict_t *xdata); + +call_stub_t * +fop_symlink_cbk_stub(call_frame_t *frame, fop_symlink_cbk_t fn, int32_t op_ret, + int32_t op_errno, inode_t *inode, struct iatt *buf, + struct iatt *preparent, struct iatt *postparent, + dict_t *xdata); + +call_stub_t * +fop_rename_stub(call_frame_t *frame, fop_rename_t fn, loc_t *oldloc, + loc_t *newloc, dict_t *xdata); + +call_stub_t * +fop_rename_cbk_stub(call_frame_t *frame, fop_rename_cbk_t fn, int32_t op_ret, + int32_t op_errno, struct iatt *buf, + struct iatt *preoldparent, struct iatt *postoldparent, + struct iatt *prenewparent, struct iatt *postnewparent, + dict_t *xdata); + +call_stub_t * +fop_link_stub(call_frame_t *frame, fop_link_t fn, loc_t *oldloc, loc_t *newloc, + dict_t *xdata); + +call_stub_t * +fop_link_cbk_stub(call_frame_t *frame, fop_link_cbk_t fn, int32_t op_ret, + int32_t op_errno, inode_t *inode, struct iatt *buf, + struct iatt *preparent, struct iatt *postparent, + dict_t *xdata); + +call_stub_t * +fop_create_stub(call_frame_t *frame, fop_create_t fn, loc_t *loc, int32_t flags, + mode_t mode, mode_t umask, fd_t *fd, dict_t *xdata); + +call_stub_t * +fop_create_cbk_stub(call_frame_t *frame, fop_create_cbk_t fn, int32_t op_ret, + int32_t op_errno, fd_t *fd, inode_t *inode, + struct iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); + +call_stub_t * +fop_open_stub(call_frame_t *frame, fop_open_t fn, loc_t *loc, int32_t flags, + fd_t *fd, dict_t *xdata); + +call_stub_t * +fop_open_cbk_stub(call_frame_t *frame, fop_open_cbk_t fn, int32_t op_ret, + int32_t op_errno, fd_t *fd, dict_t *xdata); + +call_stub_t * +fop_readv_stub(call_frame_t *frame, fop_readv_t fn, fd_t *fd, size_t size, + off_t off, uint32_t flags, dict_t *xdata); + +call_stub_t * +fop_readv_cbk_stub(call_frame_t *frame, fop_readv_cbk_t fn, int32_t op_ret, + int32_t op_errno, struct iovec *vector, int32_t count, + struct iatt *stbuf, struct iobref *iobref, dict_t *xdata); + +call_stub_t * +fop_writev_stub(call_frame_t *frame, fop_writev_t fn, fd_t *fd, + struct iovec *vector, int32_t count, off_t off, uint32_t flags, + struct iobref *iobref, dict_t *xdata); + +call_stub_t * +fop_writev_cbk_stub(call_frame_t *frame, fop_writev_cbk_t fn, int32_t op_ret, + int32_t op_errno, struct iatt *prebuf, struct iatt *postbuf, + dict_t *xdata); + +call_stub_t * +fop_flush_stub(call_frame_t *frame, fop_flush_t fn, fd_t *fd, dict_t *xdata); + +call_stub_t * +fop_flush_cbk_stub(call_frame_t *frame, fop_flush_cbk_t fn, int32_t op_ret, + int32_t op_errno, dict_t *xdata); + +call_stub_t * +fop_fsync_stub(call_frame_t *frame, fop_fsync_t fn, fd_t *fd, int32_t datasync, + dict_t *xdata); + +call_stub_t * +fop_fsync_cbk_stub(call_frame_t *frame, fop_fsync_cbk_t fn, int32_t op_ret, + int32_t op_errno, struct iatt *prebuf, struct iatt *postbuf, + dict_t *xdata); + +call_stub_t * +fop_opendir_stub(call_frame_t *frame, fop_opendir_t fn, loc_t *loc, fd_t *fd, + dict_t *xdata); + +call_stub_t * +fop_opendir_cbk_stub(call_frame_t *frame, fop_opendir_cbk_t fn, int32_t op_ret, + int32_t op_errno, fd_t *fd, dict_t *xdata); + +call_stub_t * +fop_fsyncdir_stub(call_frame_t *frame, fop_fsyncdir_t fn, fd_t *fd, + int32_t datasync, dict_t *xdata); + +call_stub_t * +fop_fsyncdir_cbk_stub(call_frame_t *frame, fop_fsyncdir_cbk_t fn, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + +call_stub_t * +fop_statfs_stub(call_frame_t *frame, fop_statfs_t fn, loc_t *loc, + dict_t *xdata); + +call_stub_t * +fop_statfs_cbk_stub(call_frame_t *frame, fop_statfs_cbk_t fn, int32_t op_ret, + int32_t op_errno, struct statvfs *buf, dict_t *xdata); + +call_stub_t * +fop_setxattr_stub(call_frame_t *frame, fop_setxattr_t fn, loc_t *loc, + dict_t *dict, int32_t flags, dict_t *xdata); + +call_stub_t * +fop_setxattr_cbk_stub(call_frame_t *frame, fop_setxattr_cbk_t fn, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + +call_stub_t * +fop_getxattr_stub(call_frame_t *frame, fop_getxattr_t fn, loc_t *loc, + const char *name, dict_t *xdata); + +call_stub_t * +fop_getxattr_cbk_stub(call_frame_t *frame, fop_getxattr_cbk_t fn, + int32_t op_ret, int32_t op_errno, dict_t *value, + dict_t *xdata); + +call_stub_t * +fop_fsetxattr_stub(call_frame_t *frame, fop_fsetxattr_t fn, fd_t *fd, + dict_t *dict, int32_t flags, dict_t *xdata); + +call_stub_t * +fop_fsetxattr_cbk_stub(call_frame_t *frame, fop_fsetxattr_cbk_t fn, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + +call_stub_t * +fop_fgetxattr_stub(call_frame_t *frame, fop_fgetxattr_t fn, fd_t *fd, + const char *name, dict_t *xdata); + +call_stub_t * +fop_fgetxattr_cbk_stub(call_frame_t *frame, fop_fgetxattr_cbk_t fn, + int32_t op_ret, int32_t op_errno, dict_t *value, + dict_t *xdata); + +call_stub_t * +fop_removexattr_stub(call_frame_t *frame, fop_removexattr_t fn, loc_t *loc, + const char *name, dict_t *xdata); + +call_stub_t * +fop_removexattr_cbk_stub(call_frame_t *frame, fop_removexattr_cbk_t fn, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + +call_stub_t * +fop_fremovexattr_stub(call_frame_t *frame, fop_fremovexattr_t fn, fd_t *fd, + const char *name, dict_t *xdata); + +call_stub_t * +fop_fremovexattr_cbk_stub(call_frame_t *frame, fop_fremovexattr_cbk_t fn, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + +call_stub_t * +fop_lk_stub(call_frame_t *frame, fop_lk_t fn, fd_t *fd, int32_t cmd, + struct gf_flock *lock, dict_t *xdata); + +call_stub_t * +fop_lk_cbk_stub(call_frame_t *frame, fop_lk_cbk_t fn, int32_t op_ret, + int32_t op_errno, struct gf_flock *lock, dict_t *xdata); + +call_stub_t * +fop_inodelk_stub(call_frame_t *frame, fop_inodelk_t fn, const char *volume, + loc_t *loc, int32_t cmd, struct gf_flock *lock, dict_t *xdata); + +call_stub_t * +fop_finodelk_stub(call_frame_t *frame, fop_finodelk_t fn, const char *volume, + fd_t *fd, int32_t cmd, struct gf_flock *lock, dict_t *xdata); + +call_stub_t * +fop_entrylk_stub(call_frame_t *frame, fop_entrylk_t fn, const char *volume, + loc_t *loc, const char *basename, entrylk_cmd cmd, + entrylk_type type, dict_t *xdata); + +call_stub_t * +fop_fentrylk_stub(call_frame_t *frame, fop_fentrylk_t fn, const char *volume, + fd_t *fd, const char *basename, entrylk_cmd cmd, + entrylk_type type, dict_t *xdata); + +call_stub_t * +fop_inodelk_cbk_stub(call_frame_t *frame, fop_inodelk_cbk_t fn, int32_t op_ret, + int32_t op_errno, dict_t *xdata); + +call_stub_t * +fop_finodelk_cbk_stub(call_frame_t *frame, fop_inodelk_cbk_t fn, int32_t op_ret, + int32_t op_errno, dict_t *xdata); + +call_stub_t * +fop_entrylk_cbk_stub(call_frame_t *frame, fop_entrylk_cbk_t fn, int32_t op_ret, + int32_t op_errno, dict_t *xdata); + +call_stub_t * +fop_fentrylk_cbk_stub(call_frame_t *frame, fop_entrylk_cbk_t fn, int32_t op_ret, + int32_t op_errno, dict_t *xdata); + +call_stub_t * +fop_readdir_stub(call_frame_t *frame, fop_readdir_t fn, fd_t *fd, size_t size, + off_t off, dict_t *xdata); + +call_stub_t * +fop_readdirp_stub(call_frame_t *frame, fop_readdirp_t fn, fd_t *fd, size_t size, + off_t off, dict_t *xdata); + +call_stub_t * +fop_readdirp_cbk_stub(call_frame_t *frame, fop_readdir_cbk_t fn, int32_t op_ret, + int32_t op_errno, gf_dirent_t *entries, dict_t *xdata); + +call_stub_t * +fop_readdir_cbk_stub(call_frame_t *frame, fop_readdir_cbk_t fn, int32_t op_ret, + int32_t op_errno, gf_dirent_t *entries, dict_t *xdata); + +call_stub_t * +fop_rchecksum_stub(call_frame_t *frame, fop_rchecksum_t fn, fd_t *fd, + off_t offset, int32_t len, dict_t *xdata); + +call_stub_t * +fop_rchecksum_cbk_stub(call_frame_t *frame, fop_rchecksum_cbk_t fn, + int32_t op_ret, int32_t op_errno, uint32_t weak_checksum, + uint8_t *strong_checksum, dict_t *xdata); + +call_stub_t * +fop_xattrop_stub(call_frame_t *frame, fop_xattrop_t fn, loc_t *loc, + gf_xattrop_flags_t optype, dict_t *xattr, dict_t *xdata); + +call_stub_t * +fop_xattrop_stub_cbk_stub(call_frame_t *frame, fop_xattrop_cbk_t fn, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + +call_stub_t * +fop_fxattrop_stub(call_frame_t *frame, fop_fxattrop_t fn, fd_t *fd, + gf_xattrop_flags_t optype, dict_t *xattr, dict_t *xdata); + +call_stub_t * +fop_fxattrop_stub_cbk_stub(call_frame_t *frame, fop_xattrop_cbk_t fn, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + +call_stub_t * +fop_setattr_stub(call_frame_t *frame, fop_setattr_t fn, loc_t *loc, + struct iatt *stbuf, int32_t valid, dict_t *xdata); + +call_stub_t * +fop_setattr_cbk_stub(call_frame_t *frame, fop_setattr_cbk_t fn, int32_t op_ret, + int32_t op_errno, struct iatt *statpre, + struct iatt *statpost, dict_t *xdata); + +call_stub_t * +fop_fsetattr_stub(call_frame_t *frame, fop_fsetattr_t fn, fd_t *fd, + struct iatt *stbuf, int32_t valid, dict_t *xdata); + +call_stub_t * +fop_fsetattr_cbk_stub(call_frame_t *frame, fop_setattr_cbk_t fn, int32_t op_ret, + int32_t op_errno, struct iatt *statpre, + struct iatt *statpost, dict_t *xdata); + +call_stub_t * +fop_fallocate_stub(call_frame_t *frame, fop_fallocate_t fn, fd_t *fd, + int32_t mode, off_t offset, size_t len, dict_t *xdata); + +call_stub_t * +fop_fallocate_cbk_stub(call_frame_t *frame, fop_fallocate_cbk_t fn, + int32_t op_ret, int32_t op_errno, struct iatt *statpre, + struct iatt *statpost, dict_t *xdata); + +call_stub_t * +fop_discard_stub(call_frame_t *frame, fop_discard_t fn, fd_t *fd, off_t offset, + size_t len, dict_t *xdata); + +call_stub_t * +fop_discard_cbk_stub(call_frame_t *frame, fop_discard_cbk_t fn, int32_t op_ret, + int32_t op_errno, struct iatt *statpre, + struct iatt *statpost, dict_t *xdata); + +call_stub_t * +fop_zerofill_stub(call_frame_t *frame, fop_zerofill_t fn, fd_t *fd, + off_t offset, off_t len, dict_t *xdata); + +call_stub_t * +fop_zerofill_cbk_stub(call_frame_t *frame, fop_zerofill_cbk_t fn, + int32_t op_ret, int32_t op_errno, struct iatt *statpre, + struct iatt *statpost, dict_t *xdata); + +call_stub_t * +fop_ipc_stub(call_frame_t *frame, fop_ipc_t fn, int32_t op, dict_t *xdata); + +call_stub_t * +fop_ipc_cbk_stub(call_frame_t *frame, fop_ipc_cbk_t fn, int32_t op_ret, + int32_t op_errno, dict_t *xdata); + +call_stub_t * +fop_seek_stub(call_frame_t *frame, fop_seek_t fn, fd_t *fd, off_t offset, + gf_seek_what_t what, dict_t *xdata); + +call_stub_t * +fop_seek_cbk_stub(call_frame_t *frame, fop_seek_cbk_t fn, int32_t op_ret, + int32_t op_errno, off_t offset, dict_t *xdata); + +call_stub_t * +fop_lease_stub(call_frame_t *frame, fop_lease_t fn, loc_t *loc, + struct gf_lease *lease, dict_t *xdata); + +call_stub_t * +fop_lease_cbk_stub(call_frame_t *frame, fop_lease_cbk_t fn, int32_t op_ret, + int32_t op_errno, struct gf_lease *lease, dict_t *xdata); + +call_stub_t * +fop_getactivelk_stub(call_frame_t *frame, fop_getactivelk_t fn, loc_t *loc, + dict_t *xdata); + +call_stub_t * +fop_getactivelk_cbk_stub(call_frame_t *frame, fop_getactivelk_cbk_t fn, + int32_t op_ret, int32_t op_errno, + lock_migration_info_t *lmi, dict_t *xdata); + +call_stub_t * +fop_setactivelk_stub(call_frame_t *frame, fop_setactivelk_t fn, loc_t *loc, + lock_migration_info_t *locklist, dict_t *xdata); + +call_stub_t * +fop_setactivelk_cbk_stub(call_frame_t *frame, fop_setactivelk_cbk_t fn, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + +call_stub_t * +fop_put_stub(call_frame_t *frame, fop_put_t fn, loc_t *loc, mode_t mode, + mode_t umask, uint32_t flags, struct iovec *vector, int32_t count, + off_t offset, struct iobref *iobref, dict_t *xattr, dict_t *xdata); + +call_stub_t * +fop_put_cbk_stub(call_frame_t *frame, fop_put_cbk_t fn, int32_t op_ret, + int32_t op_errno, inode_t *inode, struct iatt *buf, + struct iatt *preparent, struct iatt *postparent, + dict_t *xdata); + +call_stub_t * +fop_icreate_stub(call_frame_t *frame, fop_icreate_t fn, loc_t *loc, mode_t mode, + dict_t *xdata); + +call_stub_t * +fop_namelink_stub(call_frame_t *frame, fop_namelink_t fn, loc_t *loc, + dict_t *xdata); + +call_stub_t * +fop_icreate_cbk_stub(call_frame_t *frame, fop_icreate_cbk_t fn, int32_t op_ret, + int32_t op_errno, inode_t *inode, struct iatt *buf, + dict_t *xdata); + +call_stub_t * +fop_namelink_cbk_stub(call_frame_t *frame, fop_namelink_cbk_t fn, + int32_t op_ret, int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata); + +void +call_resume(call_stub_t *stub); +void +call_resume_keep_stub(call_stub_t *stub); +void +call_stub_destroy(call_stub_t *stub); +void +call_unwind_error(call_stub_t *stub, int op_ret, int op_errno); +void +call_unwind_error_keep_stub(call_stub_t *stub, int op_ret, int op_errno); + +/* + * Sometimes we might want to call just this, perhaps repeatedly, without + * having (or being able) to destroy and recreate it. + */ +void +call_resume_wind(call_stub_t *stub); + +#endif diff --git a/libglusterfs/src/glusterfs/checksum.h b/libglusterfs/src/glusterfs/checksum.h new file mode 100644 index 00000000000..019bb14df71 --- /dev/null +++ b/libglusterfs/src/glusterfs/checksum.h @@ -0,0 +1,22 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef __CHECKSUM_H__ +#define __CHECKSUM_H__ + +uint32_t +gf_rsync_weak_checksum(unsigned char *buf, size_t len); + +void +gf_rsync_strong_checksum(unsigned char *buf, size_t len, unsigned char *sum); + +void +gf_rsync_md5_checksum(unsigned char *data, size_t len, unsigned char *md5); +#endif /* __CHECKSUM_H__ */ diff --git a/libglusterfs/src/glusterfs/circ-buff.h b/libglusterfs/src/glusterfs/circ-buff.h new file mode 100644 index 00000000000..4453b8487cd --- /dev/null +++ b/libglusterfs/src/glusterfs/circ-buff.h @@ -0,0 +1,63 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _CB_H +#define _CB_H + +#include "glusterfs/common-utils.h" +#include "glusterfs/logging.h" +#include "glusterfs/mem-types.h" + +#define BUFFER_SIZE 10 +#define TOTAL_SIZE BUFFER_SIZE + 1 + +struct _circular_buffer { + struct timeval tv; + void *data; +}; + +typedef struct _circular_buffer circular_buffer_t; + +struct _buffer { + unsigned int w_index; + size_t size_buffer; + gf_boolean_t use_once; + /* This variable is assigned the proper value at the time of initing */ + /* the buffer. It indicates, whether the buffer should be used once */ + /* it becomes full. */ + + int used_len; + /* indicates the amount of circular buffer used. */ + + circular_buffer_t **cb; + void (*destroy_buffer_data)(void *data); + pthread_mutex_t lock; +}; + +typedef struct _buffer buffer_t; + +int +cb_add_entry_buffer(buffer_t *buffer, void *item); + +void +cb_buffer_show(buffer_t *buffer); + +buffer_t * +cb_buffer_new(size_t buffer_size, gf_boolean_t use_buffer_once, + void (*destroy_data)(void *data)); + +void +cb_buffer_destroy(buffer_t *buffer); + +void +cb_buffer_dump(buffer_t *buffer, void *data, + int(fn)(circular_buffer_t *buffer, void *data)); + +#endif /* _CB_H */ diff --git a/libglusterfs/src/glusterfs/client_t.h b/libglusterfs/src/glusterfs/client_t.h new file mode 100644 index 00000000000..29f50daf03b --- /dev/null +++ b/libglusterfs/src/glusterfs/client_t.h @@ -0,0 +1,139 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _CLIENT_T_H +#define _CLIENT_T_H + +#include "glusterfs/glusterfs.h" +#include "glusterfs/locking.h" /* for gf_lock_t, not included by glusterfs.h */ +#include "glusterfs/atomic.h" /* for gf_atomic_t */ + +struct client_ctx { + void *ctx_key; + void *ctx_value; +}; + +typedef struct _client { + struct { + /* e.g. protocol/server stashes its ctx here */ + gf_lock_t lock; + unsigned short count; + struct client_ctx *ctx; + } scratch_ctx; + gf_atomic_t bind; + gf_atomic_t count; + xlator_t *bound_xl; + xlator_t *this; + int tbl_index; + char *client_uid; + char *client_name; + struct { + int flavour; + size_t len; + char *data; + char *username; + char *passwd; + } auth; + + /* subdir_mount */ + char *subdir_mount; + inode_t *subdir_inode; + uuid_t subdir_gfid; + int32_t opversion; +} client_t; + +#define GF_CLIENTCTX_INITIAL_SIZE 8 + +struct client_table_entry { + client_t *client; + int next_free; +}; +typedef struct client_table_entry cliententry_t; + +struct clienttable { + unsigned int max_clients; + gf_lock_t lock; + cliententry_t *cliententries; + int first_free; + client_t *local; +}; +typedef struct clienttable clienttable_t; + +#define GF_CLIENTTABLE_INITIAL_SIZE 128 + +/* Signifies no more entries in the client table. */ +#define GF_CLIENTTABLE_END -1 + +/* This is used to invalidate + * the next_free value in an cliententry that has been allocated + */ +#define GF_CLIENTENTRY_ALLOCATED -2 + +struct rpcsvc_auth_data; + +client_t * +gf_client_get(xlator_t *this, struct rpcsvc_auth_data *cred, char *client_uid, + char *subdir_mount); + +void +gf_client_put(client_t *client, gf_boolean_t *detached); + +clienttable_t * +gf_clienttable_alloc(void); + +void +gf_client_clienttable_destroy(clienttable_t *clienttable); + +client_t * +gf_client_ref(client_t *client); + +void +gf_client_unref(client_t *client); + +int +gf_client_dump_fdtable_to_dict(xlator_t *this, dict_t *dict); + +int +gf_client_dump_fdtable(xlator_t *this); + +int +gf_client_dump_inodes_to_dict(xlator_t *this, dict_t *dict); + +int +gf_client_dump_inodes(xlator_t *this); + +void * +client_ctx_set(client_t *client, void *key, void *value); + +int +client_ctx_get(client_t *client, void *key, void **value); + +int +client_ctx_del(client_t *client, void *key, void **value); + +void +client_ctx_dump(client_t *client, char *prefix); + +int +gf_client_dump_fdtables_to_dict(xlator_t *this, dict_t *dict); + +int +gf_client_dump_fdtables(xlator_t *this); + +int +gf_client_dump_inodes_to_dict(xlator_t *this, dict_t *dict); + +int +gf_client_dump_inodes(xlator_t *this); + +int +gf_client_disconnect(client_t *client); + +#endif /* _CLIENT_T_H */ diff --git a/libglusterfs/src/glusterfs/cluster-syncop.h b/libglusterfs/src/glusterfs/cluster-syncop.h new file mode 100644 index 00000000000..cfd3c338683 --- /dev/null +++ b/libglusterfs/src/glusterfs/cluster-syncop.h @@ -0,0 +1,227 @@ +/* + Copyright (c) 2015 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _CLUSTER_SYNCOP_H +#define _CLUSTER_SYNCOP_H + +#include "glusterfs/xlator.h" +#include <sys/time.h> +#include <pthread.h> +#include <ucontext.h> +#include "glusterfs/defaults.h" +#include "glusterfs/default-args.h" +#include "glusterfs/syncop.h" + +/********************************************************************* + * + * PARALLEL_FOP_ONLIST: + * Performs file operations in parallel on bricks. + * This macro expects a helper function(func) to implement the + * functionality. + * + ********************************************************************/ +#define PARALLEL_FOP_ONLIST(subvols, on, numsubvols, replies, frame, func, \ + args...) \ + do { \ + int __i = 0; \ + int __count = 0; \ + cluster_local_t __local = { \ + 0, \ + }; \ + void *__old_local = frame->local; \ + \ + __local.replies = replies; \ + cluster_replies_wipe(replies, numsubvols); \ + for (__i = 0; __i < numsubvols; __i++) \ + INIT_LIST_HEAD(&replies[__i].entries.list); \ + if (syncbarrier_init(&__local.barrier)) \ + break; \ + frame->local = &__local; \ + for (__i = 0; __i < numsubvols; __i++) { \ + if (on[__i]) { \ + __count++; \ + } \ + } \ + __local.barrier.waitfor = __count; \ + for (__i = 0; __i < numsubvols; __i++) { \ + if (on[__i]) { \ + func(frame, subvols[__i], __i, ##args); \ + } \ + } \ + syncbarrier_wait(&__local.barrier, __count); \ + syncbarrier_destroy(&__local.barrier); \ + frame->local = __old_local; \ + STACK_RESET(frame->root); \ + } while (0) + +typedef struct cluster_local_ { + default_args_cbk_t *replies; + syncbarrier_t barrier; +} cluster_local_t; + +int32_t +cluster_lookup(xlator_t **subvols, unsigned char *on, int numsubvols, + default_args_cbk_t *replies, unsigned char *output, + call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata); +int32_t +cluster_setattr(xlator_t **subvols, unsigned char *on, int numsubvols, + default_args_cbk_t *replies, unsigned char *output, + call_frame_t *frame, xlator_t *this, loc_t *loc, + struct iatt *stbuf, int32_t valid, dict_t *xdata); +int32_t +cluster_getxattr(xlator_t **subvols, unsigned char *on, int numsubvols, + default_args_cbk_t *replies, unsigned char *output, + call_frame_t *frame, xlator_t *this, loc_t *loc, + const char *name, dict_t *xdata); +int32_t +cluster_setxattr(xlator_t **subvols, unsigned char *on, int numsubvols, + default_args_cbk_t *replies, unsigned char *output, + call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *dict, + int32_t flags, dict_t *xdata); + +int +cluster_inodelk(xlator_t **subvols, unsigned char *on, int numsubvols, + default_args_cbk_t *replies, unsigned char *locked_on, + call_frame_t *frame, xlator_t *this, char *dom, inode_t *inode, + off_t off, size_t size); + +int +cluster_uninodelk(xlator_t **subvols, unsigned char *locked_on, int numsubvols, + default_args_cbk_t *replies, unsigned char *output, + call_frame_t *frame, xlator_t *this, char *dom, + inode_t *inode, off_t off, size_t size); + +int +cluster_entrylk(xlator_t **subvols, unsigned char *on, int numsubvols, + default_args_cbk_t *replies, unsigned char *locked_on, + call_frame_t *frame, xlator_t *this, char *dom, inode_t *inode, + const char *name); + +int32_t +cluster_rmdir(xlator_t **subvols, unsigned char *on, int numsubvols, + default_args_cbk_t *replies, unsigned char *output, + call_frame_t *frame, xlator_t *this, loc_t *loc, int flags, + dict_t *xdata); + +int32_t +cluster_unlink(xlator_t **subvols, unsigned char *on, int numsubvols, + default_args_cbk_t *replies, unsigned char *output, + call_frame_t *frame, xlator_t *this, loc_t *loc, int xflag, + dict_t *xdata); + +int +cluster_mkdir(xlator_t **subvols, unsigned char *on, int numsubvols, + default_args_cbk_t *replies, unsigned char *output, + call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, + mode_t umask, dict_t *xdata); + +int32_t +cluster_readlink(xlator_t **subvols, unsigned char *on, int numsubvols, + default_args_cbk_t *replies, unsigned char *output, + call_frame_t *frame, xlator_t *this, loc_t *loc, size_t size, + dict_t *xdata); + +int +cluster_symlink(xlator_t **subvols, unsigned char *on, int numsubvols, + default_args_cbk_t *replies, unsigned char *output, + call_frame_t *frame, xlator_t *this, const char *linkpath, + loc_t *loc, mode_t umask, dict_t *xdata); + +int32_t +cluster_link(xlator_t **subvols, unsigned char *on, int numsubvols, + default_args_cbk_t *replies, unsigned char *output, + call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc, + dict_t *xdata); + +int +cluster_mknod(xlator_t **subvols, unsigned char *on, int numsubvols, + default_args_cbk_t *replies, unsigned char *output, + call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, + dev_t rdev, mode_t umask, dict_t *xdata); + +int +cluster_unentrylk(xlator_t **subvols, unsigned char *locked_on, int numsubvols, + default_args_cbk_t *replies, unsigned char *output, + call_frame_t *frame, xlator_t *this, char *dom, + inode_t *inode, const char *name); + +int +cluster_tryentrylk(xlator_t **subvols, unsigned char *on, int numsubvols, + default_args_cbk_t *replies, unsigned char *locked_on, + call_frame_t *frame, xlator_t *this, char *dom, + inode_t *inode, const char *name); + +int32_t +cluster_fxattrop(xlator_t **subvols, unsigned char *on, int numsubvols, + default_args_cbk_t *replies, unsigned char *output, + call_frame_t *frame, xlator_t *this, fd_t *fd, + gf_xattrop_flags_t flags, dict_t *dict, dict_t *xdata); + +int32_t +cluster_xattrop(xlator_t **subvols, unsigned char *on, int numsubvols, + default_args_cbk_t *replies, unsigned char *output, + call_frame_t *frame, xlator_t *this, loc_t *loc, + gf_xattrop_flags_t flags, dict_t *dict, dict_t *xdata); + +int32_t +cluster_fstat(xlator_t **subvols, unsigned char *on, int numsubvols, + default_args_cbk_t *replies, unsigned char *output, + call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdata); + +int32_t +cluster_ftruncate(xlator_t **subvols, unsigned char *on, int numsubvols, + default_args_cbk_t *replies, unsigned char *output, + call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, + dict_t *xdata); + +int32_t +cluster_open(xlator_t **subvols, unsigned char *on, int numsubvols, + default_args_cbk_t *replies, unsigned char *output, + call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, + fd_t *fd, dict_t *xdata); + +int +cluster_tryinodelk(xlator_t **subvols, unsigned char *on, int numsubvols, + default_args_cbk_t *replies, unsigned char *locked_on, + call_frame_t *frame, xlator_t *this, char *dom, + inode_t *inode, off_t off, size_t size); + +int32_t +cluster_fsetattr(xlator_t **subvols, unsigned char *on, int numsubvols, + default_args_cbk_t *replies, unsigned char *output, + call_frame_t *frame, xlator_t *this, fd_t *fd, + struct iatt *stbuf, int32_t valid, dict_t *xdata); + +int32_t +cluster_put(xlator_t **subvols, unsigned char *on, int numsubvols, + default_args_cbk_t *replies, unsigned char *output, + call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, + mode_t umask, uint32_t flags, struct iovec *vector, int32_t count, + off_t offset, struct iobref *iobref, dict_t *xattr, dict_t *xdata); + +void +cluster_replies_wipe(default_args_cbk_t *replies, int num_subvols); + +int32_t +cluster_fop_success_fill(default_args_cbk_t *replies, int numsubvols, + unsigned char *success); + +int32_t +cluster_xattrop_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *dict, + dict_t *xdata); + +int +cluster_tiebreaker_inodelk(xlator_t **subvols, unsigned char *on, + int numsubvols, default_args_cbk_t *replies, + unsigned char *locked_on, call_frame_t *frame, + xlator_t *this, char *dom, inode_t *inode, off_t off, + size_t size); +#endif /* !_CLUSTER_SYNCOP_H */ diff --git a/libglusterfs/src/glusterfs/common-utils.h b/libglusterfs/src/glusterfs/common-utils.h new file mode 100644 index 00000000000..075a355f786 --- /dev/null +++ b/libglusterfs/src/glusterfs/common-utils.h @@ -0,0 +1,1070 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _COMMON_UTILS_H +#define _COMMON_UTILS_H + +#include <stdint.h> +#include <sys/uio.h> +#include <netdb.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <pthread.h> +#include <openssl/md5.h> +#ifndef GF_BSD_HOST_OS +#include <alloca.h> +#endif +#include <limits.h> +#include <fnmatch.h> +#include <uuid/uuid.h> + +#ifndef ffsll +#define ffsll(x) __builtin_ffsll(x) +#endif + +void +trap(void); + +#define GF_UNIVERSAL_ANSWER 42 /* :O */ + +/* To solve type punned error */ +#define VOID(ptr) ((void **)((void *)ptr)) + +#include "glusterfs/logging.h" +#include "glusterfs/glusterfs.h" +#include "glusterfs/locking.h" +#include "glusterfs/mem-pool.h" +#include "glusterfs/compat-uuid.h" +#include "glusterfs/iatt.h" +#include "glusterfs/libglusterfs-messages.h" +#include "protocol-common.h" +#include "glusterfs/iobuf.h" + +#define STRINGIFY(val) #val +#define TOSTRING(val) STRINGIFY(val) + +#define alloca0(size) \ + ({ \ + void *__ptr; \ + __ptr = alloca(size); \ + memset(__ptr, 0, size); \ + __ptr; \ + }) + +#define min(a, b) ((a) < (b) ? (a) : (b)) +#define max(a, b) ((a) > (b) ? (a) : (b)) +#define gf_roof(a, b) ((((a) + (b)-1) / ((b != 0) ? (b) : 1)) * (b)) +#define gf_floor(a, b) (((a) / ((b != 0) ? (b) : 1)) * (b)) + +#define IPv4_ADDR_SIZE 32 + +#define GF_UNIT_KB 1024ULL +#define GF_UNIT_MB 1048576ULL +#define GF_UNIT_GB 1073741824ULL +#define GF_UNIT_TB 1099511627776ULL +#define GF_UNIT_PB 1125899906842624ULL + +#define GF_UNIT_B_STRING "B" +#define GF_UNIT_KB_STRING "KB" +#define GF_UNIT_MB_STRING "MB" +#define GF_UNIT_GB_STRING "GB" +#define GF_UNIT_TB_STRING "TB" +#define GF_UNIT_PB_STRING "PB" + +#define GF_UNIT_PERCENT_STRING "%" + +#define GEOREP "geo-replication" +#define GHADOOP "glusterfs-hadoop" +#define GLUSTERD_NAME "glusterd" + +#define GF_SELINUX_XATTR_KEY "security.selinux" + +#define WIPE(statp) \ + do { \ + typeof(*statp) z = { \ + 0, \ + }; \ + if (statp) \ + *statp = z; \ + } while (0) + +#define IS_EXT_FS(fs_name) \ + (!strcmp(fs_name, "ext2") || !strcmp(fs_name, "ext3") || \ + !strcmp(fs_name, "ext4")) + +/* process mode definitions */ +#define GF_SERVER_PROCESS 0 +#define GF_CLIENT_PROCESS 1 +#define GF_GLUSTERD_PROCESS 2 + +/* Defining this here as it is needed by glusterd for setting + * nfs port in volume status. + */ +#define GF_NFS3_PORT 2049 + +#define GF_CLIENT_PORT_CEILING 1024 +#define GF_IANA_PRIV_PORTS_START 49152 /* RFC 6335 */ +#define GF_CLNT_INSECURE_PORT_CEILING (GF_IANA_PRIV_PORTS_START - 1) +#define GF_PORT_MAX 65535 +#define GF_PORT_ARRAY_SIZE ((GF_PORT_MAX + 7) / 8) +#define GF_LOCK_TIMER 180 +#define GF_MINUTE_IN_SECONDS 60 +#define GF_HOUR_IN_SECONDS (60 * 60) +#define GF_DAY_IN_SECONDS (24 * 60 * 60) +#define GF_WEEK_IN_SECONDS (7 * 24 * 60 * 60) + +/* Default timeout for both barrier and changelog translator */ +#define BARRIER_TIMEOUT "120" + +/* Default value of signing waiting time to sign a file for bitrot */ +#define SIGNING_TIMEOUT "120" + +/* xxhash */ +#define GF_XXH64_DIGEST_LENGTH 8 +#define GF_XXHSUM64_DEFAULT_SEED 0 + +/* Shard */ +#define GF_XATTR_SHARD_FILE_SIZE "trusted.glusterfs.shard.file-size" +#define SHARD_ROOT_GFID "be318638-e8a0-4c6d-977d-7a937aa84806" +#define DOT_SHARD_REMOVE_ME_GFID "77dd5a45-dbf5-4592-b31b-b440382302e9" + +/* Lease: buffer length for stringified lease id + * Format: 4hexnum-4hexnum-4hexnum-4hexnum-4hexnum-4hexnum-4hexnum-4hexnum + * Eg:6c69-6431-2d63-6c6e-7431-0000-0000-0000 + */ +#define GF_LEASE_ID_BUF_SIZE ((LEASE_ID_SIZE * 2) + (LEASE_ID_SIZE / 2)) + +#define GF_PERCENTAGE(val, total) (((val)*100) / (total)) + +/* pthread related */ +/* as per the man page, thread-name should be at max 16 bytes */ +/* with prefix of 'glfs_' (5), we are left with 11 more bytes */ +#define GF_THREAD_NAMEMAX 11 +#define GF_THREAD_NAME_PREFIX "glfs_" +#define GF_THREAD_NAME_PREFIX_LEN 5 + +#include <stdbool.h> +#define gf_boolean_t bool +#define _gf_false false +#define _gf_true true + +/* + * we could have initialized these as +ve values and treated + * them as negative while comparing etc.. (which would have + * saved us with the pain of assigning values), but since we + * only have a few clients that use this feature, it's okay. + */ +enum _gf_special_pid { + GF_CLIENT_PID_MAX = 0, + GF_CLIENT_PID_GSYNCD = -1, + GF_CLIENT_PID_HADOOP = -2, + GF_CLIENT_PID_DEFRAG = -3, + GF_CLIENT_PID_NO_ROOT_SQUASH = -4, + GF_CLIENT_PID_QUOTA_MOUNT = -5, + GF_CLIENT_PID_SELF_HEALD = -6, + GF_CLIENT_PID_GLFS_HEAL = -7, + GF_CLIENT_PID_BITD = -8, + GF_CLIENT_PID_SCRUB = -9, + GF_CLIENT_PID_TIER_DEFRAG = -10, + GF_SERVER_PID_TRASH = -11 +}; + +enum _gf_xlator_ipc_targets { + GF_IPC_TARGET_CHANGELOG = 0, + GF_IPC_TARGET_CTR = 1, + GF_IPC_TARGET_UPCALL = 2 +}; + +typedef enum _gf_special_pid gf_special_pid_t; +typedef enum _gf_xlator_ipc_targets _gf_xlator_ipc_targets_t; + +/* 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 + * and target files. this makes it difficult for geo-rep to figure out that + * a rename operation has taken place. + * + * We now send a special key and the values of the source and target pargfids + * and basenames to indicate to changelog that the operation in question + * should be treated as a rename. We are explicitly filling and sending this + * as a binary value in the dictionary as the unlink op will not have the + * source file information. The lengths of the src and target basenames + * are used to calculate where to start reading the names in the structure. + * XFS allows a max of 255 chars for filenames but other file systems might + * not have such restrictions + */ +typedef struct dht_changelog_rename_info { + uuid_t old_pargfid; + uuid_t new_pargfid; + int32_t oldname_len; + int32_t newname_len; + char buffer[1]; +} dht_changelog_rename_info_t; + +typedef int (*gf_cmp)(void *, void *); + +struct _dict; + +struct dnscache { + struct _dict *cache_dict; + time_t ttl; +}; + +struct dnscache_entry { + char *ip; + char *fqdn; + time_t timestamp; +}; + +struct dnscache6 { + struct addrinfo *first; + struct addrinfo *next; +}; + +struct list_node { + void *ptr; + struct list_head list; +}; + +extern char *vol_type_str[]; + +struct list_node * +list_node_add(void *ptr, struct list_head *list); +struct list_node * +list_node_add_order(void *ptr, struct list_head *list, + int (*compare)(struct list_head *, struct list_head *)); +void +list_node_del(struct list_node *node); + +struct dnscache * +gf_dnscache_init(time_t ttl); +struct dnscache_entry * +gf_dnscache_entry_init(void); +void +gf_dnscache_entry_deinit(struct dnscache_entry *entry); +char * +gf_rev_dns_lookup_cached(const char *ip, struct dnscache *dnscache); + +char * +gf_resolve_path_parent(const char *path); + +void +gf_global_variable_init(void); + +int32_t +gf_resolve_ip6(const char *hostname, uint16_t port, int family, void **dnscache, + struct addrinfo **addr_info); + +void +gf_log_dump_graph(FILE *specfp, glusterfs_graph_t *graph); +void +gf_print_trace(int32_t signal, glusterfs_ctx_t *ctx); +int +gf_set_log_file_path(cmd_args_t *cmd_args, glusterfs_ctx_t *ctx); +int +gf_set_log_ident(cmd_args_t *cmd_args); + +int +gf_process_getspec_servers_list(cmd_args_t *cmd_args, const char *servers_list); +int +gf_set_volfile_server_common(cmd_args_t *cmd_args, const char *host, + const char *transport, int port); + +static inline void +BIT_SET(unsigned char *array, unsigned int index) +{ + unsigned int offset = index / 8; + unsigned int shift = index % 8; + + array[offset] |= (1 << shift); +} + +static inline void +BIT_CLEAR(unsigned char *array, unsigned int index) +{ + unsigned int offset = index / 8; + unsigned int shift = index % 8; + + array[offset] &= ~(1 << shift); +} + +static inline unsigned int +BIT_VALUE(unsigned char *array, unsigned int index) +{ + unsigned int offset = index / 8; + unsigned int shift = index % 8; + + return (array[offset] >> shift) & 0x1; +} + +#define VECTORSIZE(count) (count * (sizeof(struct iovec))) + +#define STRLEN_0(str) (strlen(str) + 1) + +#define VALIDATE_OR_GOTO(arg, label) \ + do { \ + if (!arg) { \ + errno = EINVAL; \ + gf_msg_callingfn((this ? (this->name) : "(Govinda! Govinda!)"), \ + GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG, \ + "invalid argument: " #arg); \ + goto label; \ + } \ + } while (0) + +#define GF_VALIDATE_OR_GOTO(name, arg, label) \ + do { \ + if (!arg) { \ + errno = EINVAL; \ + gf_msg_callingfn(name, GF_LOG_ERROR, errno, LG_MSG_INVALID_ARG, \ + "invalid argument: " #arg); \ + goto label; \ + } \ + } while (0) + +#define GF_VALIDATE_OR_GOTO_WITH_ERROR(name, arg, label, errno, error) \ + do { \ + if (!arg) { \ + errno = error; \ + gf_msg_callingfn(name, GF_LOG_ERROR, EINVAL, LG_MSG_INVALID_ARG, \ + "invalid argument: " #arg); \ + goto label; \ + } \ + } while (0) + +#define GF_CHECK_ALLOC(arg, retval, label) \ + do { \ + if (!(arg)) { \ + retval = -ENOMEM; \ + goto label; \ + } \ + } while (0) + +#define GF_CHECK_ALLOC_AND_LOG(name, item, retval, msg, errlabel) \ + do { \ + if (!(item)) { \ + (retval) = -ENOMEM; \ + gf_msg(name, GF_LOG_CRITICAL, ENOMEM, LG_MSG_NO_MEMORY, (msg)); \ + goto errlabel; \ + } \ + } while (0) + +#define GF_ASSERT_AND_GOTO_WITH_ERROR(name, arg, label, errno, error) \ + do { \ + if (!arg) { \ + GF_ASSERT(0); \ + errno = error; \ + goto label; \ + } \ + } while (0) + +#define GF_VALIDATE_ABSOLUTE_PATH_OR_GOTO(name, arg, label) \ + do { \ + GF_VALIDATE_OR_GOTO(name, arg, label); \ + if ((arg[0]) != '/') { \ + errno = EINVAL; \ + gf_msg_callingfn(name, GF_LOG_ERROR, EINVAL, LG_MSG_INVALID_ARG, \ + "invalid argument: " #arg); \ + goto label; \ + } \ + } while (0) + +#define GF_REMOVE_SLASH_FROM_PATH(path, string) \ + do { \ + int i = 0; \ + for (i = 1; i < strlen(path); i++) { \ + string[i - 1] = path[i]; \ + if (string[i - 1] == '/') \ + string[i - 1] = '-'; \ + } \ + } while (0) + +#define GF_REMOVE_INTERNAL_XATTR(pattern, dict) \ + do { \ + if (!dict) { \ + gf_msg(this->name, GF_LOG_ERROR, 0, LG_MSG_DICT_NULL, \ + "dict is null"); \ + break; \ + } \ + dict_foreach_fnmatch(dict, pattern, dict_remove_foreach_fn, NULL); \ + } while (0) + +#define GF_IF_INTERNAL_XATTR_GOTO(pattern, dict, op_errno, label) \ + do { \ + if (!dict) { \ + gf_msg(this->name, GF_LOG_ERROR, 0, LG_MSG_DICT_NULL, \ + "setxattr dict is null"); \ + goto label; \ + } \ + if (dict_foreach_fnmatch(dict, pattern, dict_null_foreach_fn, NULL) > \ + 0) { \ + op_errno = EPERM; \ + gf_msg(this->name, GF_LOG_ERROR, op_errno, LG_MSG_NO_PERM, \ + "attempt to set internal" \ + " xattr: %s", \ + pattern); \ + goto label; \ + } \ + } while (0) + +#define GF_IF_NATIVE_XATTR_GOTO(pattern, key, op_errno, label) \ + do { \ + if (!key) { \ + gf_msg(this->name, GF_LOG_ERROR, 0, LG_MSG_NO_KEY, \ + "no key for removexattr"); \ + goto label; \ + } \ + if (!fnmatch(pattern, key, 0)) { \ + op_errno = EPERM; \ + gf_msg(this->name, GF_LOG_ERROR, op_errno, LG_MSG_NO_PERM, \ + "attempt to remove internal " \ + "xattr: %s", \ + key); \ + goto label; \ + } \ + } while (0) + +#define GF_FILE_CONTENT_REQUESTED(_xattr_req, _content_limit) \ + (dict_get_uint64(_xattr_req, "glusterfs.content", _content_limit) == 0) + +#ifdef DEBUG +#define GF_ASSERT(x) assert(x); +#else +#define GF_ASSERT(x) \ + do { \ + if (!(x)) { \ + gf_msg_callingfn("", GF_LOG_ERROR, 0, LG_MSG_ASSERTION_FAILED, \ + "Assertion failed: " #x); \ + } \ + } while (0) +#endif + +#define GF_ABORT(msg) \ + do { \ + gf_msg_callingfn("", GF_LOG_CRITICAL, 0, LG_MSG_ASSERTION_FAILED, \ + "Assertion failed: " msg); \ + abort(); \ + } while (0) + +#define GF_UUID_ASSERT(u) \ + if (gf_uuid_is_null(u)) \ + GF_ASSERT(!"uuid null"); + +#define GF_IGNORE_IF_GSYNCD_SAFE_ERROR(frame, op_errno) \ + (((frame->root->pid == GF_CLIENT_PID_GSYNCD) && \ + (op_errno == EEXIST || op_errno == ENOENT)) \ + ? 0 \ + : 1) + +union gf_sock_union { + struct sockaddr_storage storage; + struct sockaddr_in6 sin6; + struct sockaddr_in sin; + struct sockaddr sa; +}; + +#define GF_HIDDEN_PATH ".glusterfs" +#define GF_UNLINK_PATH GF_HIDDEN_PATH "/unlink" +#define GF_LANDFILL_PATH GF_HIDDEN_PATH "/landfill" + +#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 void +iov_free(struct iovec *vector, int count) +{ + int i; + + for (i = 0; i < count; i++) + FREE(vector[i].iov_base); + + GF_FREE(vector); +} + +static inline int +iov_length(const struct iovec *vector, int count) +{ + int i = 0; + size_t size = 0; + + for (i = 0; i < count; i++) + size += vector[i].iov_len; + + return size; +} + +static inline struct iovec * +iov_dup(const struct iovec *vector, int count) +{ + int bytecount = 0; + int i; + struct iovec *newvec = NULL; + + bytecount = (count * sizeof(struct iovec)); + newvec = GF_MALLOC(bytecount, gf_common_mt_iovec); + if (!newvec) + return NULL; + + for (i = 0; i < count; i++) { + newvec[i].iov_len = vector[i].iov_len; + newvec[i].iov_base = vector[i].iov_base; + } + + return newvec; +} + +static inline int +iov_subset(struct iovec *orig, int orig_count, off_t src_offset, + off_t dst_offset, struct iovec *new) +{ + int new_count = 0; + int i; + off_t offset = 0; + size_t start_offset = 0; + size_t end_offset = 0, origin_iov_len = 0; + + for (i = 0; i < orig_count; i++) { + origin_iov_len = orig[i].iov_len; + + if ((offset + orig[i].iov_len < src_offset) || (offset > dst_offset)) { + goto not_subset; + } + + if (!new) { + goto count_only; + } + + start_offset = 0; + end_offset = orig[i].iov_len; + + if (src_offset >= offset) { + start_offset = (src_offset - offset); + } + + if (dst_offset <= (offset + orig[i].iov_len)) { + end_offset = (dst_offset - offset); + } + + new[new_count].iov_base = orig[i].iov_base + start_offset; + new[new_count].iov_len = end_offset - start_offset; + + count_only: + new_count++; + + not_subset: + offset += origin_iov_len; + } + + return new_count; +} + +static inline void +iov_unload(char *buf, const struct iovec *vector, int count) +{ + int i; + int copied = 0; + + for (i = 0; i < count; i++) { + memcpy(buf + copied, vector[i].iov_base, vector[i].iov_len); + copied += vector[i].iov_len; + } +} + +static inline size_t +iov_load(const struct iovec *vector, int count, char *buf, int size) +{ + size_t left = size; + size_t cp = 0; + int ret = 0; + int i = 0; + + while (left && i < count) { + cp = min(vector[i].iov_len, left); + if (vector[i].iov_base != buf + (size - left)) + memcpy(vector[i].iov_base, buf + (size - left), cp); + ret += cp; + left -= cp; + if (left) + i++; + } + + return ret; +} + +static inline size_t +iov_copy(const struct iovec *dst, int dcnt, const struct iovec *src, int scnt) +{ + size_t ret = 0; + size_t left = 0; + size_t min_i = 0; + int s_i = 0, s_ii = 0; + int d_i = 0, d_ii = 0; + + ret = min(iov_length(dst, dcnt), iov_length(src, scnt)); + left = ret; + + while (left) { + min_i = min(dst[d_i].iov_len - d_ii, src[s_i].iov_len - s_ii); + memcpy(dst[d_i].iov_base + d_ii, src[s_i].iov_base + s_ii, min_i); + + d_ii += min_i; + if (d_ii == dst[d_i].iov_len) { + d_ii = 0; + d_i++; + } + + s_ii += min_i; + if (s_ii == src[s_i].iov_len) { + s_ii = 0; + s_i++; + } + + left -= min_i; + } + + return ret; +} + +/* based on the amusing discussion @ https://rusty.ozlabs.org/?p=560 */ +static bool +memeqzero(const void *data, size_t length) +{ + const unsigned char *p = data; + size_t len; + + /* Check first 16 bytes manually */ + for (len = 0; len < 16; len++) { + if (!length) + return true; + if (*p) + return false; + p++; + length--; + } + + /* Now we know that's zero, memcmp with self. */ + return memcmp(data, p, length) == 0; +} + +static inline int +mem_0filled(const char *buf, size_t size) +{ + return !memeqzero(buf, size); +} + +static inline int +iov_0filled(struct iovec *vector, int count) +{ + int i = 0; + int ret = 0; + + for (i = 0; i < count; i++) { + ret = mem_0filled(vector[i].iov_base, vector[i].iov_len); + if (ret) + break; + } + + return ret; +} + +static inline void * +memdup(const void *ptr, size_t size) +{ + void *newptr = NULL; + + newptr = GF_MALLOC(size, gf_common_mt_memdup); + if (!newptr) + return NULL; + + memcpy(newptr, ptr, size); + return newptr; +} + +typedef enum { + gf_timefmt_default = 0, + gf_timefmt_FT = 0, /* YYYY-MM-DD hh:mm:ss */ + gf_timefmt_Ymd_T, /* YYYY/MM-DD-hh:mm:ss */ + gf_timefmt_bdT, /* MMM DD hh:mm:ss */ + gf_timefmt_F_HMS, /* YYYY-MM-DD hhmmss */ + gf_timefmt_dirent, + gf_timefmt_s, + gf_timefmt_last +} gf_timefmts; + +static inline char * +gf_time_fmt(char *dst, size_t sz_dst, time_t utime, unsigned int fmt) +{ + extern void _gf_timestuff(const char ***, const char ***); + static gf_timefmts timefmt_last = (gf_timefmts)-1; + static const char **fmts; + static const char **zeros; + struct tm tm, *res; + int localtime = 0; + + if (timefmt_last == ((gf_timefmts)-1)) { + _gf_timestuff(&fmts, &zeros); + timefmt_last = gf_timefmt_last; + } + if (timefmt_last <= 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); + } else { + strncpy(dst, "N/A", sz_dst); + } + return dst; +} + +/* This function helps us use gfid (unique identity) to generate inode's unique + * number in glusterfs. + */ +ino_t +gfid_to_ino(uuid_t gfid); + +int +mkdir_p(char *path, mode_t mode, gf_boolean_t allow_symlinks); +/* + * rounds up nr to power of two. If nr is already a power of two, just returns + * nr + */ + +int +gf_lstat_dir(const char *path, struct stat *stbuf_in); + +int32_t +gf_roundup_power_of_two(int32_t nr); + +/* + * rounds up nr to next power of two. If nr is already a power of two, next + * power of two is returned. + */ + +int32_t +gf_roundup_next_power_of_two(int32_t nr); + +char * +gf_trim(char *string); +int +gf_volume_name_validate(const char *volume_name); + +int +gf_string2long(const char *str, long *n); +int +gf_string2ulong(const char *str, unsigned long *n); +int +gf_string2int(const char *str, int *n); +int +gf_string2uint(const char *str, unsigned int *n); +int +gf_string2double(const char *str, double *n); +int +gf_string2longlong(const char *str, long long *n); +int +gf_string2ulonglong(const char *str, unsigned long long *n); + +int +gf_string2int8(const char *str, int8_t *n); +int +gf_string2int16(const char *str, int16_t *n); +int +gf_string2int32(const char *str, int32_t *n); +int +gf_string2int64(const char *str, int64_t *n); +int +gf_string2uint8(const char *str, uint8_t *n); +int +gf_string2uint16(const char *str, uint16_t *n); +int +gf_string2uint32(const char *str, uint32_t *n); +int +gf_string2uint64(const char *str, uint64_t *n); + +int +gf_strstr(const char *str, const char *delim, const char *match); + +int +gf_string2ulong_base10(const char *str, unsigned long *n); +int +gf_string2uint_base10(const char *str, unsigned int *n); +int +gf_string2uint8_base10(const char *str, uint8_t *n); +int +gf_string2uint16_base10(const char *str, uint16_t *n); +int +gf_string2uint32_base10(const char *str, uint32_t *n); +int +gf_string2uint64_base10(const char *str, uint64_t *n); +int +gf_string2bytesize_uint64(const char *str, uint64_t *n); +int +gf_string2bytesize_int64(const char *str, int64_t *n); +int +gf_string2percent_or_bytesize(const char *str, double *n, + gf_boolean_t *is_percent); + +int +gf_string2boolean(const char *str, gf_boolean_t *b); +int +gf_string2percent(const char *str, double *n); +int +gf_string2time(const char *str, uint32_t *n); + +int +gf_lockfd(int fd); +int +gf_unlockfd(int fd); + +int +get_checksum_for_file(int fd, uint32_t *checksum); +int +log_base2(unsigned long x); + +int +get_checksum_for_path(char *path, uint32_t *checksum); +int +get_file_mtime(const char *path, time_t *stamp); +char * +gf_resolve_path_parent(const char *path); + +char * +strtail(char *str, const char *pattern); +void +skipwhite(char **s); +char * +nwstrtail(char *str, char *pattern); +/* returns a new string with nth word of given string. n>=1 */ + +typedef struct token_iter { + char *end; + char sep; +} token_iter_t; +char * +token_iter_init(char *str, char sep, token_iter_t *tit); +gf_boolean_t +next_token(char **tokenp, token_iter_t *tit); +void +drop_token(char *token, token_iter_t *tit); + +gf_boolean_t +mask_match(const uint32_t a, const uint32_t b, const uint32_t m); +gf_boolean_t +gf_is_ip_in_net(const char *network, const char *ip_str); +char +valid_host_name(char *address, int length); +char +valid_ipv4_address(char *address, int length, gf_boolean_t wildcard_acc); +char +valid_ipv6_address(char *address, int length, gf_boolean_t wildcard_acc); +char +valid_internet_address(char *address, gf_boolean_t wildcard_acc); +gf_boolean_t +valid_mount_auth_address(char *address); +gf_boolean_t +valid_ipv4_subnetwork(const char *address); +gf_boolean_t +gf_sock_union_equal_addr(union gf_sock_union *a, union gf_sock_union *b); +char * +gf_rev_dns_lookup(const char *ip); + +char * +uuid_utoa(uuid_t uuid); +char * +uuid_utoa_r(uuid_t uuid, char *dst); +char * +lkowner_utoa(gf_lkowner_t *lkowner); +char * +lkowner_utoa_r(gf_lkowner_t *lkowner, char *dst, int len); +char * +leaseid_utoa(const char *lease_id); +gf_boolean_t +is_valid_lease_id(const char *lease_id); +char * +gf_leaseid_get(void); +char * +gf_existing_leaseid(void); + +void +gf_array_insertionsort(void *a, int l, int r, size_t elem_size, gf_cmp cmp); +int +gf_is_str_int(const char *value); + +char *gf_uint64_2human_readable(uint64_t); +int +get_vol_type(int type, int dist_count, int brick_count); +int +validate_brick_name(char *brick); +char * +get_host_name(char *word, char **host); +char * +get_path_name(char *word, char **path); +void +gf_path_strip_trailing_slashes(char *path); +uint64_t +get_mem_size(void); +int +gf_strip_whitespace(char *str, int len); +int +gf_canonicalize_path(char *path); +char * +generate_glusterfs_ctx_id(void); +char * +gf_get_reserved_ports(void); +int +gf_process_reserved_ports(unsigned char *ports, uint32_t ceiling); +gf_boolean_t +gf_ports_reserved(char *blocked_port, unsigned char *ports, uint32_t ceiling); +int +gf_get_hostname_from_ip(char *client_ip, char **hostname); +gf_boolean_t +gf_is_local_addr(char *hostname); +gf_boolean_t +gf_is_same_address(char *host1, char *host2); +void +gf_xxh64_wrapper(const unsigned char *data, size_t const len, + unsigned long long const seed, char *xxh64); +int +gf_gfid_generate_from_xxh64(uuid_t gfid, char *key); + +int +gf_set_timestamp(const char *src, const char *dest); + +int +gf_thread_create(pthread_t *thread, const pthread_attr_t *attr, + void *(*start_routine)(void *), void *arg, const char *name); +int +gf_thread_create_detached(pthread_t *thread, void *(*start_routine)(void *), + void *arg, const char *name); +gf_boolean_t +gf_is_pid_running(int pid); +gf_boolean_t +gf_is_service_running(char *pidfile, int *pid); +gf_boolean_t +gf_valid_pid(const char *pid, int length); +int +gf_skip_header_section(int fd, int header_len); + +struct iatt; +struct _dict; + +gf_boolean_t +dht_is_linkfile(struct iatt *buf, struct _dict *dict); + +int +gf_check_log_format(const char *value); + +int +gf_check_logger(const char *value); + +gf_boolean_t +gf_compare_sockaddr(const struct sockaddr *addr1, const struct sockaddr *addr2); + +char * +gf_backtrace_save(char *buf); + +void +gf_backtrace_done(char *buf); + +gf_loglevel_t +fop_log_level(glusterfs_fop_t fop, int op_errno); + +int32_t +gf_build_absolute_path(char *current_path, char *relative_path, char **path); + +int +recursive_rmdir(const char *delete_path); + +int +gf_get_index_by_elem(char **array, char *elem); + +int +glusterfs_is_local_pathinfo(char *pathinfo, gf_boolean_t *local); + +int +gf_thread_cleanup_xint(pthread_t thread); + +ssize_t +gf_nread(int fd, void *buf, size_t count); + +ssize_t +gf_nwrite(int fd, const void *buf, size_t count); + +void +_mask_cancellation(void); +void +_unmask_cancellation(void); + +gf_boolean_t +gf_is_zero_filled_stat(struct iatt *buf); + +void +gf_zero_fill_stat(struct iatt *buf); + +gf_boolean_t +gf_is_valid_xattr_namespace(char *k); + +const char * +gf_inode_type_to_str(ia_type_t type); + +int32_t +gf_bits_count(uint64_t n); + +int32_t +gf_bits_index(uint64_t n); + +const char * +gf_fop_string(glusterfs_fop_t fop); + +int +gf_fop_int(char *fop); + +char * +get_ip_from_addrinfo(struct addrinfo *addr, char **ip); + +int +close_fds_except(int *fdv, size_t count); + +int +gf_getgrouplist(const char *user, gid_t group, gid_t **groups); + +int +glusterfs_compute_sha256(const unsigned char *content, size_t size, + char *sha256_hash); +char * +get_struct_variable(int mem_num, gf_gsync_status_t *sts_val); + +char * +gf_strncpy(char *dest, const char *src, const size_t dest_size); + +void +gf_strTrim(char **s); + +int +gf_replace_old_iatt_in_dict(struct _dict *); + +int +gf_replace_new_iatt_in_dict(struct _dict *); + +#endif /* _COMMON_UTILS_H */ diff --git a/libglusterfs/src/glusterfs/compat-errno.h b/libglusterfs/src/glusterfs/compat-errno.h new file mode 100644 index 00000000000..c4ab09ab0d5 --- /dev/null +++ b/libglusterfs/src/glusterfs/compat-errno.h @@ -0,0 +1,238 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef __COMPAT_ERRNO_H__ +#define __COMPAT_ERRNO_H__ + +#include <errno.h> + +#define GF_ERROR_CODE_SUCCESS 0 +#define GF_ERROR_CODE_UNKNOWN 1024 +#define GF_ERRNO_UNKNOWN 1024 + +#define GF_ERROR_CODE_PERM 1 /* Operation not permitted */ +#define GF_ERROR_CODE_NOENT 2 /* No such file or directory */ +#define GF_ERROR_CODE_SRCH 3 /* No such process */ +#define GF_ERROR_CODE_INTR 4 /* Interrupted system call */ +#define GF_ERROR_CODE_IO 5 /* I/O error */ +#define GF_ERROR_CODE_NXIO 6 /* No such device or address */ +#define GF_ERROR_CODE_2BIG 7 /* Argument list too long */ +#define GF_ERROR_CODE_NOEXEC 8 /* Exec format error */ +#define GF_ERROR_CODE_BADF 9 /* Bad file number */ +#define GF_ERROR_CODE_CHILD 10 /* No child processes */ +#define GF_ERROR_CODE_AGAIN 11 /* Try again */ +#define GF_ERROR_CODE_NOMEM 12 /* Out of memory */ +#define GF_ERROR_CODE_ACCES 13 /* Permission denied */ +#define GF_ERROR_CODE_FAULT 14 /* Bad address */ +#define GF_ERROR_CODE_NOTBLK 15 /* Block device required */ +#define GF_ERROR_CODE_BUSY 16 /* Device or resource busy */ +#define GF_ERROR_CODE_EXIST 17 /* File exists */ +#define GF_ERROR_CODE_XDEV 18 /* Cross-device link */ +#define GF_ERROR_CODE_NODEV 19 /* No such device */ +#define GF_ERROR_CODE_NOTDIR 20 /* Not a directory */ +#define GF_ERROR_CODE_ISDIR 21 /* Is a directory */ +#define GF_ERROR_CODE_INVAL 22 /* Invalid argument */ +#define GF_ERROR_CODE_NFILE 23 /* File table overflow */ +#define GF_ERROR_CODE_MFILE 24 /* Too many open files */ +#define GF_ERROR_CODE_NOTTY 25 /* Not a typewriter */ +#define GF_ERROR_CODE_TXTBSY 26 /* Text file busy */ +#define GF_ERROR_CODE_FBIG 27 /* File too large */ +#define GF_ERROR_CODE_NOSPC 28 /* No space left on device */ +#define GF_ERROR_CODE_SPIPE 29 /* Illegal seek */ +#define GF_ERROR_CODE_ROFS 30 /* Read-only file system */ +#define GF_ERROR_CODE_MLINK 31 /* Too many links */ +#define GF_ERROR_CODE_PIPE 32 /* Broken pipe */ +#define GF_ERROR_CODE_DOM 33 /* Math argument out of domain of func */ +#define GF_ERROR_CODE_RANGE 34 /* Math result not representable */ +#define GF_ERROR_CODE_DEADLK 35 /* Resource deadlock would occur */ +#define GF_ERROR_CODE_NAMETOOLONG 36 /* File name too long */ +#define GF_ERROR_CODE_NOLCK 37 /* No record locks available */ +#define GF_ERROR_CODE_NOSYS 38 /* Function not implemented */ +#define GF_ERROR_CODE_NOTEMPTY 39 /* Directory not empty */ +#define GF_ERROR_CODE_LOOP 40 /* Too many symbolic links encountered */ + +#define GF_ERROR_CODE_NOMSG 42 /* No message of desired type */ +#define GF_ERROR_CODE_IDRM 43 /* Identifier removed */ +#define GF_ERROR_CODE_CHRNG 44 /* Channel number out of range */ +#define GF_ERROR_CODE_L2NSYNC 45 /* Level 2 not synchronized */ +#define GF_ERROR_CODE_L3HLT 46 /* Level 3 halted */ +#define GF_ERROR_CODE_L3RST 47 /* Level 3 reset */ +#define GF_ERROR_CODE_LNRNG 48 /* Link number out of range */ +#define GF_ERROR_CODE_UNATCH 49 /* Protocol driver not attached */ +#define GF_ERROR_CODE_NOCSI 50 /* No CSI structure available */ +#define GF_ERROR_CODE_L2HLT 51 /* Level 2 halted */ +#define GF_ERROR_CODE_BADE 52 /* Invalid exchange */ +#define GF_ERROR_CODE_BADR 53 /* Invalid request descriptor */ +#define GF_ERROR_CODE_XFULL 54 /* Exchange full */ +#define GF_ERROR_CODE_NOANO 55 /* No anode */ +#define GF_ERROR_CODE_BADRQC 56 /* Invalid request code */ +#define GF_ERROR_CODE_BADSLT 57 /* Invalid slot */ +#define GF_ERROR_CODE_BFONT 59 /* Bad font file format */ +#define GF_ERROR_CODE_NOSTR 60 /* Device not a stream */ +#define GF_ERROR_CODE_NODATA 61 /* No data available */ +#define GF_ERROR_CODE_TIME 62 /* Timer expired */ +#define GF_ERROR_CODE_NOSR 63 /* Out of streams resources */ +#define GF_ERROR_CODE_NONET 64 /* Machine is not on the network */ +#define GF_ERROR_CODE_NOPKG 65 /* Package not installed */ +#define GF_ERROR_CODE_REMOTE 66 /* Object is remote */ +#define GF_ERROR_CODE_NOLINK 67 /* Link has been severed */ +#define GF_ERROR_CODE_ADV 68 /* Advertise error */ +#define GF_ERROR_CODE_SRMNT 69 /* Srmount error */ +#define GF_ERROR_CODE_COMM 70 /* Communication error on send */ +#define GF_ERROR_CODE_PROTO 71 /* Protocol error */ +#define GF_ERROR_CODE_MULTIHOP 72 /* Multihop attempted */ +#define GF_ERROR_CODE_DOTDOT 73 /* RFS specific error */ +#define GF_ERROR_CODE_BADMSG 74 /* Not a data message */ +#define GF_ERROR_CODE_OVERFLOW 75 /* Value too large for defined data type */ +#define GF_ERROR_CODE_NOTUNIQ 76 /* Name not unique on network */ +#define GF_ERROR_CODE_BADFD 77 /* File descriptor in bad state */ +#define GF_ERROR_CODE_REMCHG 78 /* Remote address changed */ +#define GF_ERROR_CODE_LIBACC 79 /* Can not access a needed shared library */ +#define GF_ERROR_CODE_LIBBAD 80 /* Accessing a corrupted shared library */ +#define GF_ERROR_CODE_LIBSCN 81 /* .lib section in a.out corrupted */ +#define GF_ERROR_CODE_LIBMAX \ + 82 /* Attempting to link in too many shared libraries */ +#define GF_ERROR_CODE_LIBEXEC 83 /* Cannot exec a shared library directly */ +#define GF_ERROR_CODE_ILSEQ 84 /* Illegal byte sequence */ +#define GF_ERROR_CODE_RESTART \ + 85 /* Interrupted system call should be restarted */ +#define GF_ERROR_CODE_STRPIPE 86 /* Streams pipe error */ +#define GF_ERROR_CODE_USERS 87 /* Too many users */ +#define GF_ERROR_CODE_NOTSOCK 88 /* Socket operation on non-socket */ +#define GF_ERROR_CODE_DESTADDRREQ 89 /* Destination address required */ +#define GF_ERROR_CODE_MSGSIZE 90 /* Message too long */ +#define GF_ERROR_CODE_PROTOTYPE 91 /* Protocol wrong type for socket */ +#define GF_ERROR_CODE_NOPROTOOPT 92 /* Protocol not available */ +#define GF_ERROR_CODE_PROTONOSUPPORT 93 /* Protocol not supported */ +#define GF_ERROR_CODE_SOCKTNOSUPPORT 94 /* Socket type not supported */ +#define GF_ERROR_CODE_OPNOTSUPP \ + 95 /* Operation not supported on transport endpoint */ +#define GF_ERROR_CODE_PFNOSUPPORT 96 /* Protocol family not supported */ +#define GF_ERROR_CODE_AFNOSUPPORT \ + 97 /* Address family not supported by protocol */ +#define GF_ERROR_CODE_ADDRINUSE 98 /* Address already in use */ +#define GF_ERROR_CODE_ADDRNOTAVAIL 99 /* Cannot assign requested address */ +#define GF_ERROR_CODE_NETDOWN 100 /* Network is down */ +#define GF_ERROR_CODE_NETUNREACH 101 /* Network is unreachable */ +#define GF_ERROR_CODE_NETRESET \ + 102 /* Network dropped connection because of reset */ +#define GF_ERROR_CODE_CONNABORTED 103 /* Software caused connection abort */ +#define GF_ERROR_CODE_CONNRESET 104 /* Connection reset by peer */ +#define GF_ERROR_CODE_NOBUFS 105 /* No buffer space available */ +#define GF_ERROR_CODE_ISCONN 106 /* Transport endpoint is already connected */ +#define GF_ERROR_CODE_NOTCONN 107 /* Transport endpoint is not connected */ +#define GF_ERROR_CODE_SHUTDOWN \ + 108 /* Cannot send after transport endpoint shutdown */ +#define GF_ERROR_CODE_TOOMANYREFS 109 /* Too many references: cannot splice */ +#define GF_ERROR_CODE_TIMEDOUT 110 /* Connection timed out */ +#define GF_ERROR_CODE_CONNREFUSED 111 /* Connection refused */ +#define GF_ERROR_CODE_HOSTDOWN 112 /* Host is down */ +#define GF_ERROR_CODE_HOSTUNREACH 113 /* No route to host */ +#define GF_ERROR_CODE_ALREADY 114 /* Operation already in progress */ +#define GF_ERROR_CODE_INPROGRESS 115 /* Operation now in progress */ +#define GF_ERROR_CODE_ALREADY 114 /* Operation already in progress */ +#define GF_ERROR_CODE_INPROGRESS 115 /* Operation now in progress */ +#define GF_ERROR_CODE_STALE 116 /* Stale NFS file handle */ +#define GF_ERROR_CODE_UCLEAN 117 /* Structure needs cleaning */ +#define GF_ERROR_CODE_NOTNAM 118 /* Not a XENIX named type file */ +#define GF_ERROR_CODE_NAVAIL 119 /* No XENIX semaphores available */ +#define GF_ERROR_CODE_ISNAM 120 /* Is a named type file */ +#define GF_ERROR_CODE_REMOTEIO 121 /* Remote I/O error */ +#define GF_ERROR_CODE_DQUOT 122 /* Quota exceeded */ +#define GF_ERROR_CODE_NOMEDIUM 123 /* No medium found */ +#define GF_ERROR_CODE_MEDIUMTYPE 124 /* Wrong medium type */ +#define GF_ERROR_CODE_CANCELED 125 /* Operation Canceled */ +#define GF_ERROR_CODE_NOKEY 126 /* Required key not available */ +#define GF_ERROR_CODE_KEYEXPIRED 127 /* Key has expired */ +#define GF_ERROR_CODE_KEYREVOKED 128 /* Key has been revoked */ +#define GF_ERROR_CODE_KEYREJECTED 129 /* Key was rejected by service */ + +/* for robust mutexes */ +#define GF_ERROR_CODE_OWNERDEAD 130 /* Owner died */ +#define GF_ERROR_CODE_NOTRECOVERABLE 131 /* State not recoverable */ + +/* Should never be seen by user programs */ +#define GF_ERROR_CODE_RESTARTSYS 512 +#define GF_ERROR_CODE_RESTARTNOINTR 513 +#define GF_ERROR_CODE_RESTARTNOHAND 514 /* restart if no handler.. */ +#define GF_ERROR_CODE_NOIOCTLCMD 515 /* No ioctl command */ +#define GF_ERROR_CODE_RESTART_RESTARTBLOCK \ + 516 /* restart by calling sys_restart_syscall */ + +/* Defined for the NFSv3 protocol */ +#define GF_ERROR_CODE_BADHANDLE 521 /* Illegal NFS file handle */ +#define GF_ERROR_CODE_NOTSYNC 522 /* Update synchronization mismatch */ +#define GF_ERROR_CODE_BADCOOKIE 523 /* Cookie is stale */ +#define GF_ERROR_CODE_NOTSUPP 524 /* Operation is not supported */ +#define GF_ERROR_CODE_TOOSMALL 525 /* Buffer or request is too small */ +#define GF_ERROR_CODE_SERVERFAULT 526 /* An untranslatable error occurred */ +#define GF_ERROR_CODE_BADTYPE 527 /* Type not supported by server */ +#define GF_ERROR_CODE_JUKEBOX \ + 528 /* Request initiated, but will not complete before timeout */ +#define GF_ERROR_CODE_IOCBQUEUED \ + 529 /* iocb queued, will get completion event */ +#define GF_ERROR_CODE_IOCBRETRY 530 /* iocb queued, will trigger a retry */ + +/* Darwin OS X */ +#define GF_ERROR_CODE_NOPOLICY 701 +#define GF_ERROR_CODE_BADMACHO 702 +#define GF_ERROR_CODE_PWROFF 703 +#define GF_ERROR_CODE_DEVERR 704 +#define GF_ERROR_CODE_BADARCH 705 +#define GF_ERROR_CODE_BADEXEC 706 +#define GF_ERROR_CODE_SHLIBVERS 707 + +/* Solaris */ +/* ENOTACTIVE 73 / * Facility is not active */ +#define GF_ERROR_CODE_NOTACTIVE 801 +/* ELOCKUNMAPPED 72 / * locked lock was unmapped */ +#define GF_ERROR_CODE_LOCKUNMAPPED 802 + +/* BSD system */ +#define GF_ERROR_CODE_PROCLIM 901 /* Too many processes */ +#define GF_ERROR_CODE_BADRPC 902 /* RPC struct is bad */ +#define GF_ERROR_CODE_RPCMISMATCH 903 /* RPC version wrong */ +#define GF_ERROR_CODE_PROGUNAVAIL 904 /* RPC prog. not avail */ +#define GF_ERROR_CODE_PROGMISMATCH 905 /* Program version wrong */ +#define GF_ERROR_CODE_PROCUNAVAIL 905 /* Bad procedure for program */ +#define GF_ERROR_CODE_FTYPE 906 /* Inappropriate file type or format */ +#define GF_ERROR_CODE_AUTH 907 /* Authentication error */ +#define GF_ERROR_CODE_NEEDAUTH 908 /* Need authenticator */ +#define GF_ERROR_CODE_DOOFUS 909 /* Programming error */ + +#define GF_ERROR_CODE_NOATTR GF_ERROR_CODE_NODATA /* Attribute not found */ + +/* Either one of enodata or enoattr will be there in system */ +#ifndef ENOATTR +#define ENOATTR ENODATA +#endif /* ENOATTR */ + +#ifndef ENODATA +#define ENODATA ENOATTR +#endif /* ENODATA */ + +#ifndef EBADFD +#define EBADFD EBADRPC +#endif /* EBADFD */ + +#if !defined(ENODATA) +/* This happens on FreeBSD. Value borrowed from Linux. */ +#define ENODATA 61 +#endif + +/* These functions are defined for all the OS flags, but content will + * be different for each OS flag. + */ +int32_t +gf_errno_to_error(int32_t op_errno); +int32_t +gf_error_to_errno(int32_t error); + +#endif /* __COMPAT_ERRNO_H__ */ diff --git a/libglusterfs/src/glusterfs/compat-uuid.h b/libglusterfs/src/glusterfs/compat-uuid.h new file mode 100644 index 00000000000..6e7fdefbfab --- /dev/null +++ b/libglusterfs/src/glusterfs/compat-uuid.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2015 Red Hat, Inc. <http://www.redhat.com> + * This file is part of GlusterFS. + * + * This file is licensed to you under your choice of the GNU Lesser + * General Public License, version 3 or any later version (LGPLv3 or + * later), or the GNU General Public License, version 2 (GPLv2), in all + * cases as published by the Free Software Foundation. + */ + +#ifndef _GF_UUID_H +#define _GF_UUID_H + +#include <uuid/uuid.h> + +static inline void +gf_uuid_clear(uuid_t uuid) +{ + uuid_clear(uuid); +} + +static inline int +gf_uuid_compare(uuid_t u1, uuid_t u2) +{ + return uuid_compare(u1, u2); +} + +static inline void +gf_uuid_copy(uuid_t dst, const uuid_t src) +{ + uuid_copy(dst, src); +} + +static inline void +gf_uuid_generate(uuid_t uuid) +{ + uuid_generate(uuid); +} + +static inline int +gf_uuid_is_null(uuid_t uuid) +{ + return uuid_is_null(uuid); +} + +static inline int +gf_uuid_parse(const char *in, uuid_t uuid) +{ + return uuid_parse(in, uuid); +} + +static inline void +gf_uuid_unparse(const uuid_t uuid, char *out) +{ + uuid_unparse(uuid, out); +} + +/* TODO: add more uuid APIs, use constructs like this: +#if defined(__NetBSD__) * NetBSD libc * + +#include <string.h> + +static inline void +gf_uuid_clear (uuid_t uuid) +{ + memset (uuid, 0, sizeof (uuid_t)); +} +#endif +*/ + +#endif /* _GF_UUID_H */ diff --git a/libglusterfs/src/glusterfs/compat.h b/libglusterfs/src/glusterfs/compat.h new file mode 100644 index 00000000000..38c07b5ae7c --- /dev/null +++ b/libglusterfs/src/glusterfs/compat.h @@ -0,0 +1,526 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef __COMPAT_H__ +#define __COMPAT_H__ + +#include <stdint.h> + +#ifndef LLONG_MAX +#define LLONG_MAX __LONG_LONG_MAX__ /* compat with old gcc */ +#endif /* LLONG_MAX */ + +#ifdef GF_LINUX_HOST_OS + +#define UNIX_PATH_MAX 108 + +#include <sys/un.h> +#include <linux/limits.h> +#include <sys/xattr.h> +#include <linux/xattr.h> +#include <endian.h> +#ifdef HAVE_LINUX_FALLOC_H +#include <linux/falloc.h> +#endif + +#ifdef HAVE_ENDIAN_H +#include <endian.h> +#endif + +#ifndef _PATH_UMOUNT +#define _PATH_UMOUNT "/bin/umount" +#endif +#define GF_XATTR_NAME_MAX XATTR_NAME_MAX +#endif /* GF_LINUX_HOST_OS */ + +#ifdef HAVE_XATTR_H +#include <sys/xattr.h> +#endif + +/* + * Define the fallocate flags in case we do not have the header. This also + * accounts for older systems that do not define FALLOC_FL_PUNCH_HOLE. + */ + +#ifndef FALLOC_FL_KEEP_SIZE +#define FALLOC_FL_KEEP_SIZE 0x01 /* default is extend size */ +#endif +#ifndef FALLOC_FL_PUNCH_HOLE +#define FALLOC_FL_PUNCH_HOLE 0x02 /* de-allocates range */ +#endif +#ifndef FALLOC_FL_ZERO_RANGE +#define FALLOC_FL_ZERO_RANGE 0x10 /* zeroes out range */ +#endif +#ifndef FALLOC_FL_COLLAPSE_RANGE +#define FALLOC_FL_COLLAPSE_RANGE 0x08 /* reduces the size */ +#endif +#ifndef FALLOC_FL_INSERT_RANGE +#define FALLOC_FL_INSERT_RANGE 0x20 /* expands the size */ +#endif + +#ifndef HAVE_LLISTXATTR + +/* This part is valid only in case of old glibc which doesn't support + * 'llistxattr()' system calls. + */ + +#define lremovexattr(path, key) removexattr(path, key) +#define llistxattr(path, key, size) listxattr(path, key, size) +#define lgetxattr(path, key, value, size) getxattr(path, key, value, size) +#define lsetxattr(path, key, value, size, flags) \ + setxattr(path, key, value, size, flags) + +#endif /* HAVE_LLISTXATTR */ + +#ifdef GF_DARWIN_HOST_OS +#include <machine/endian.h> +#include <libkern/OSByteOrder.h> +#include <sys/xattr.h> + +#define htobe16(x) OSSwapHostToBigInt16(x) +#define htole16(x) OSSwapHostToLittleInt16(x) +#define be16toh(x) OSSwapBigToHostInt16(x) +#define le16toh(x) OSSwapLittleToHostInt16(x) + +#define htobe32(x) OSSwapHostToBigInt32(x) +#define htole32(x) OSSwapHostToLittleInt32(x) +#define be32toh(x) OSSwapBigToHostInt32(x) +#define le32toh(x) OSSwapLittleToHostInt32(x) + +#define htobe64(x) OSSwapHostToBigInt64(x) +#define htole64(x) OSSwapHostToLittleInt64(x) +#define be64toh(x) OSSwapBigToHostInt64(x) +#define le64toh(x) OSSwapLittleToHostInt64(x) + +#endif + +#ifdef GF_BSD_HOST_OS +/* In case of FreeBSD and NetBSD */ + +#define UNIX_PATH_MAX 104 +#include <sys/types.h> + +#include <sys/un.h> +#include <sys/endian.h> +#include <sys/extattr.h> +#ifdef HAVE_SYS_XATTR_H +#include <sys/xattr.h> +#endif /* HAVE_SYS_XATTR_H */ +#include <limits.h> + +#include <libgen.h> + +#ifndef XATTR_CREATE +enum { + ATTR_CREATE = 1, +#define XATTR_CREATE ATTR_CREATE + ATTR_REPLACE = 2 +#define XATTR_REPLACE ATTR_REPLACE +}; +#endif /* XATTR_CREATE */ + +#ifndef sighandler_t +#define sighandler_t sig_t +#endif + +#ifdef __FreeBSD__ +#undef ino_t +#define ino_t uint64_t +#include <sys/types.h> +#include <sys/extattr.h> +/* Using NAME_MAX since EXTATTR_MAXNAMELEN is inside a preprocessor conditional + * for the kernel + */ +#define GF_XATTR_NAME_MAX NAME_MAX +#endif /* __FreeBSD__ */ + +#ifdef __NetBSD__ +#define GF_XATTR_NAME_MAX XATTR_NAME_MAX +#endif + +#ifndef ino64_t +#define ino64_t ino_t +#endif + +#ifndef EUCLEAN +#define EUCLEAN 0 +#endif + +#include <netinet/in.h> +#ifndef s6_addr16 +#define s6_addr16 __u6_addr.__u6_addr16 +#endif +#ifndef s6_addr32 +#define s6_addr32 __u6_addr.__u6_addr32 +#endif + +#ifndef LOGIN_NAME_MAX +#define LOGIN_NAME_MAX 256 +#endif + +/* Posix dictates NAME_MAX to be used */ +#ifndef NAME_MAX +#ifdef MAXNAMLEN +#define NAME_MAX MAXNAMLEN +#else +#define NAME_MAX 255 +#endif +#endif + +#define F_GETLK64 F_GETLK +#define F_SETLK64 F_SETLK +#define F_SETLKW64 F_SETLKW +#define FALLOC_FL_KEEP_SIZE 0x01 /* default is extend size */ +#define FALLOC_FL_PUNCH_HOLE 0x02 /* de-allocates range */ +#define FALLOC_FL_ZERO_RANGE 0x10 /* zeroes out range */ +#define FALLOC_FL_INSERT_RANGE 0x20 /* Expands the size */ +#define FALLOC_FL_COLLAPSE_RANGE 0x08 /* Reduces the size */ + +#ifndef _PATH_UMOUNT +#define _PATH_UMOUNT "/sbin/umount" +#endif + +void +gf_extattr_list_reshape(char *list, ssize_t size); + +#endif /* GF_BSD_HOST_OS */ + +#ifdef GF_DARWIN_HOST_OS +#include <machine/endian.h> +#include <libkern/OSByteOrder.h> + +#define htobe16(x) OSSwapHostToBigInt16(x) +#define htole16(x) OSSwapHostToLittleInt16(x) +#define be16toh(x) OSSwapBigToHostInt16(x) +#define le16toh(x) OSSwapLittleToHostInt16(x) + +#define htobe32(x) OSSwapHostToBigInt32(x) +#define htole32(x) OSSwapHostToLittleInt32(x) +#define be32toh(x) OSSwapBigToHostInt32(x) +#define le32toh(x) OSSwapLittleToHostInt32(x) + +#define htobe64(x) OSSwapHostToBigInt64(x) +#define htole64(x) OSSwapHostToLittleInt64(x) +#define be64toh(x) OSSwapBigToHostInt64(x) +#define le64toh(x) OSSwapLittleToHostInt64(x) + +#define UNIX_PATH_MAX 104 +/* OSX Yosemite now has this defined */ +#ifndef AT_SYMLINK_NOFOLLOW +#define AT_SYMLINK_NOFOLLOW 0x100 +#endif +#include <sys/types.h> + +#include <sys/un.h> +#include <sys/xattr.h> +#include <limits.h> + +#include <libgen.h> + +#if __DARWIN_64_BIT_INO_T == 0 +#error '64 bit ino_t is must for GlusterFS to work, Compile with "CFLAGS=-D__DARWIN_64_BIT_INO_T"' +#endif /* __DARWIN_64_BIT_INO_T */ + +#if __DARWIN_64_BIT_INO_T == 0 +#error '64 bit ino_t is must for GlusterFS to work, Compile with "CFLAGS=-D__DARWIN_64_BIT_INO_T"' +#endif /* __DARWIN_64_BIT_INO_T */ + +#ifndef sighandler_t +#define sighandler_t sig_t +#endif + +#ifndef EUCLEAN +#define EUCLEAN 0 +#endif + +#include <netinet/in.h> +#ifndef s6_addr16 +#define s6_addr16 __u6_addr.__u6_addr16 +#endif +#ifndef s6_addr32 +#define s6_addr32 __u6_addr.__u6_addr32 +#endif + +/* Posix dictates NAME_MAX to be used */ +#ifndef NAME_MAX +#ifdef MAXNAMLEN +#define NAME_MAX MAXNAMLEN +#else +#define NAME_MAX 255 +#endif +#endif + +#define F_GETLK64 F_GETLK +#define F_SETLK64 F_SETLK +#define F_SETLKW64 F_SETLKW + +#ifndef FTW_CONTINUE +#define FTW_CONTINUE 0 +#endif + +#ifndef _PATH_UMOUNT +#define _PATH_UMOUNT "/sbin/umount" +#endif +#endif /* GF_DARWIN_HOST_OS */ + +#ifdef GF_SOLARIS_HOST_OS + +#define UNIX_PATH_MAX 108 +#define EUCLEAN 117 + +#include <sys/un.h> +#include <limits.h> +#include <sys/stat.h> +#include <unistd.h> +#include <sys/fcntl.h> +#include <libgen.h> +#include <sys/mkdev.h> + +#ifndef lchmod +#define lchmod chmod +#endif + +#define lgetxattr(path, key, value, size) \ + solaris_getxattr(path, key, value, size) +enum { + ATTR_CREATE = 1, +#define XATTR_CREATE ATTR_CREATE + ATTR_REPLACE = 2 +#define XATTR_REPLACE ATTR_REPLACE +}; + +/* This patch is not present in Solaris 10 and before */ +#ifndef dirfd +#define dirfd(dirp) ((dirp)->dd_fd) +#endif + +/* Posix dictates NAME_MAX to be used */ +#ifndef NAME_MAX +#ifdef MAXNAMLEN +#define NAME_MAX MAXNAMLEN +#else +#define NAME_MAX 255 +#endif +#endif + +#include <netinet/in.h> +#ifndef s6_addr16 +#define S6_ADDR16(x) ((uint16_t *)((char *)&(x).s6_addr)) +#endif +#ifndef s6_addr32 +#define s6_addr32 _S6_un._S6_u32 +#endif + +#define lutimes(filename, times) utimes(filename, times) + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +enum { + DT_UNKNOWN = 0, +#define DT_UNKNOWN DT_UNKNOWN + DT_FIFO = 1, +#define DT_FIFO DT_FIFO + DT_CHR = 2, +#define DT_CHR DT_CHR + DT_DIR = 4, +#define DT_DIR DT_DIR + DT_BLK = 6, +#define DT_BLK DT_BLK + DT_REG = 8, +#define DT_REG DT_REG + DT_LNK = 10, +#define DT_LNK DT_LNK + DT_SOCK = 12, +#define DT_SOCK DT_SOCK + DT_WHT = 14 +#define DT_WHT DT_WHT +}; + +#ifndef _PATH_MOUNTED +#define _PATH_MOUNTED "/etc/mtab" +#endif +#ifndef _PATH_UMOUNT +#define _PATH_UMOUNT "/sbin/umount" +#endif + +#ifndef O_ASYNC +#ifdef FASYNC +#define O_ASYNC FASYNC +#else +#define O_ASYNC 0 +#endif +#endif + +#ifndef FTW_CONTINUE +#define FTW_CONTINUE 0 +#endif + +int +asprintf(char **string_ptr, const char *format, ...); + +int +vasprintf(char **result, const char *format, va_list args); +char * +strsep(char **str, const char *delims); +int +solaris_listxattr(const char *path, char *list, size_t size); +int +solaris_removexattr(const char *path, const char *key); +int +solaris_getxattr(const char *path, const char *key, char *value, size_t size); +int +solaris_setxattr(const char *path, const char *key, const char *value, + size_t size, int flags); +int +solaris_fgetxattr(int fd, const char *key, char *value, size_t size); +int +solaris_fsetxattr(int fd, const char *key, const char *value, size_t size, + int flags); +int +solaris_flistxattr(int fd, char *list, size_t size); + +int +solaris_rename(const char *oldpath, const char *newpath); + +int +solaris_unlink(const char *pathname); + +char * +mkdtemp(char *temp); + +#define GF_SOLARIS_XATTR_DIR ".glusterfs_xattr_inode" + +int +solaris_xattr_resolve_path(const char *real_path, char **path); + +#endif /* GF_SOLARIS_HOST_OS */ + +#ifndef HAVE_ARGP +#include "argp.h" +#else +#include <argp.h> +#endif /* HAVE_ARGP */ + +#ifndef HAVE_STRNLEN +size_t +strnlen(const char *string, size_t maxlen); +#endif /* STRNLEN */ + +#ifndef strdupa +#define strdupa(s) \ + (__extension__({ \ + __const char *__old = (s); \ + size_t __len = strlen(__old) + 1; \ + char *__new = (char *)__builtin_alloca(__len); \ + (char *)memcpy(__new, __old, __len); \ + })) +#endif + +#define GF_DIR_ALIGN(x) (((x) + sizeof(uint64_t) - 1) & ~(sizeof(uint64_t) - 1)) + +#include <sys/types.h> +#include <dirent.h> + +static inline int32_t +dirent_size(struct dirent *entry) +{ + int32_t size = -1; + +#ifdef GF_BSD_HOST_OS + size = GF_DIR_ALIGN(24 /* FIX MEEEE!!! */ + entry->d_namlen); +#endif +#ifdef GF_DARWIN_HOST_OS + size = GF_DIR_ALIGN(24 /* FIX MEEEE!!! */ + entry->d_namlen); +#endif +#ifdef GF_LINUX_HOST_OS + size = GF_DIR_ALIGN(24 /* FIX MEEEE!!! */ + entry->d_reclen); +#endif +#ifdef GF_SOLARIS_HOST_OS + size = GF_DIR_ALIGN(24 /* FIX MEEEE!!! */ + entry->d_reclen); +#endif + return size; +} + +#ifdef THREAD_UNSAFE_BASENAME +char * +basename_r(const char *); +#define basename(path) basename_r(path) +#endif /* THREAD_UNSAFE_BASENAME */ + +#ifdef THREAD_UNSAFE_DIRNAME +char * +dirname_r(char *path); +#define dirname(path) dirname_r(path) +#endif /* THREAD_UNSAFE_DIRNAME */ + +#ifdef HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC +/* Linux, Solaris, Cygwin */ +#define ST_ATIM_SEC(stbuf) ((stbuf)->st_atim.tv_sec) +#define ST_CTIM_SEC(stbuf) ((stbuf)->st_ctim.tv_sec) +#define ST_MTIM_SEC(stbuf) ((stbuf)->st_mtim.tv_sec) +#define ST_ATIM_SEC_SET(stbuf, val) ((stbuf)->st_atim.tv_sec = (val)) +#define ST_MTIM_SEC_SET(stbuf, val) ((stbuf)->st_mtim.tv_sec = (val)) +#define ST_CTIM_SEC_SET(stbuf, val) ((stbuf)->st_ctim.tv_sec = (val)) +#define ST_ATIM_NSEC(stbuf) ((stbuf)->st_atim.tv_nsec) +#define ST_CTIM_NSEC(stbuf) ((stbuf)->st_ctim.tv_nsec) +#define ST_MTIM_NSEC(stbuf) ((stbuf)->st_mtim.tv_nsec) +#define ST_ATIM_NSEC_SET(stbuf, val) ((stbuf)->st_atim.tv_nsec = (val)) +#define ST_MTIM_NSEC_SET(stbuf, val) ((stbuf)->st_mtim.tv_nsec = (val)) +#define ST_CTIM_NSEC_SET(stbuf, val) ((stbuf)->st_ctim.tv_nsec = (val)) +#elif defined(HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC) +/* FreeBSD, NetBSD */ +#define ST_ATIM_SEC(stbuf) ((stbuf)->st_atimespec.tv_sec) +#define ST_CTIM_SEC(stbuf) ((stbuf)->st_ctimespec.tv_sec) +#define ST_MTIM_SEC(stbuf) ((stbuf)->st_mtimespec.tv_sec) +#define ST_ATIM_SEC_SET(stbuf, val) ((stbuf)->st_atimespec.tv_sec = (val)) +#define ST_MTIM_SEC_SET(stbuf, val) ((stbuf)->st_mtimespec.tv_sec = (val)) +#define ST_CTIM_SEC_SET(stbuf, val) ((stbuf)->st_ctimespec.tv_sec = (val)) +#define ST_ATIM_NSEC(stbuf) ((stbuf)->st_atimespec.tv_nsec) +#define ST_CTIM_NSEC(stbuf) ((stbuf)->st_ctimespec.tv_nsec) +#define ST_MTIM_NSEC(stbuf) ((stbuf)->st_mtimespec.tv_nsec) +#define ST_ATIM_NSEC_SET(stbuf, val) ((stbuf)->st_atimespec.tv_nsec = (val)) +#define ST_MTIM_NSEC_SET(stbuf, val) ((stbuf)->st_mtimespec.tv_nsec = (val)) +#define ST_CTIM_NSEC_SET(stbuf, val) ((stbuf)->st_ctimespec.tv_nsec = (val)) +#else +#define ST_ATIM_NSEC(stbuf) (0) +#define ST_CTIM_NSEC(stbuf) (0) +#define ST_MTIM_NSEC(stbuf) (0) +#define ST_ATIM_NSEC_SET(stbuf, val) \ + do { \ + } while (0); +#define ST_MTIM_NSEC_SET(stbuf, val) \ + do { \ + } while (0); +#define ST_CTIM_NSEC_SET(stbuf, val) \ + do { \ + } while (0); +#endif + +#ifdef GF_BSD_HOST_OS +#define CLOCK_REALTIME_COARSE CLOCK_REALTIME +#endif + +#if defined(__GNUC__) && !defined(RELAX_POISONING) +/* Use run API, see run.h */ +#include <stdlib.h> /* system(), mkostemp() */ +#include <stdio.h> /* popen() */ +#pragma GCC poison system mkostemp popen +#endif + +int +gf_umount_lazy(char *xlname, char *path, int rmdir); + +#ifndef GF_XATTR_NAME_MAX +#error 'Please define GF_XATTR_NAME_MAX for your OS distribution.' +#endif + +#endif /* __COMPAT_H__ */ diff --git a/libglusterfs/src/glusterfs/compound-fop-utils.h b/libglusterfs/src/glusterfs/compound-fop-utils.h new file mode 100644 index 00000000000..1226e328704 --- /dev/null +++ b/libglusterfs/src/glusterfs/compound-fop-utils.h @@ -0,0 +1,36 @@ +/* + Copyright (c) 2016 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef __COMPOUND_FOP_UTILS_H__ +#define __COMPOUND_FOP_UTILS_H__ + +#include "glusterfs/defaults.h" +#include "glusterfs/default-args.h" +#include "glusterfs/mem-types.h" +#include "glusterfs/dict.h" + +#define COMPOUND_PACK_ARGS(fop, fop_enum, args, counter, params...) \ + do { \ + args->enum_list[counter] = fop_enum; \ + args_##fop##_store(&args->req_list[counter], params); \ + } while (0) + +compound_args_t * +compound_fop_alloc(int length, glusterfs_compound_fop_t fop, dict_t *xdata); + +void +compound_args_cleanup(compound_args_t *args); + +void +compound_args_cbk_cleanup(compound_args_cbk_t *args_cbk); + +compound_args_cbk_t * +compound_args_cbk_alloc(int length, dict_t *xdata); +#endif /* __COMPOUND_FOP_UTILS_H__ */ diff --git a/libglusterfs/src/glusterfs/daemon.h b/libglusterfs/src/glusterfs/daemon.h new file mode 100644 index 00000000000..48850800b5e --- /dev/null +++ b/libglusterfs/src/glusterfs/daemon.h @@ -0,0 +1,20 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _DAEMON_H +#define _DAEMON_H + +#define DEVNULLPATH "/dev/null" + +int +os_daemon_return(int nochdir, int noclose); +int +os_daemon(int nochdir, int noclose); +#endif /*_DAEMON_H */ diff --git a/libglusterfs/src/glusterfs/default-args.h b/libglusterfs/src/glusterfs/default-args.h new file mode 100644 index 00000000000..f15f558202b --- /dev/null +++ b/libglusterfs/src/glusterfs/default-args.h @@ -0,0 +1,444 @@ +/* + Copyright (c) 2008-2015 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +/* libglusterfs/src/defaults.h: + This file contains definition of default fops and mops functions. +*/ + +#ifndef _DEFAULT_ARGS_H +#define _DEFAULT_ARGS_H + +#include "glusterfs/xlator.h" + +int +args_lookup_cbk_store(default_args_cbk_t *args, int32_t op_ret, + int32_t op_errno, inode_t *inode, struct iatt *buf, + dict_t *xdata, struct iatt *postparent); + +int +args_stat_cbk_store(default_args_cbk_t *args, int32_t op_ret, int32_t op_errno, + struct iatt *buf, dict_t *xdata); + +int +args_fstat_cbk_store(default_args_cbk_t *args, int32_t op_ret, int32_t op_errno, + struct iatt *buf, dict_t *xdata); + +int +args_truncate_cbk_store(default_args_cbk_t *args, int32_t op_ret, + int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata); + +int +args_ftruncate_cbk_store(default_args_cbk_t *args, int32_t op_ret, + int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata); + +int +args_access_cbk_store(default_args_cbk_t *args, int32_t op_ret, + int32_t op_errno, dict_t *xdata); + +int +args_readlink_cbk_store(default_args_cbk_t *args, int32_t op_ret, + int32_t op_errno, const char *path, struct iatt *stbuf, + dict_t *xdata); + +int +args_mknod_cbk_store(default_args_cbk_t *args, int32_t op_ret, int32_t op_errno, + inode_t *inode, struct iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); + +int +args_mkdir_cbk_store(default_args_cbk_t *args, int32_t op_ret, int32_t op_errno, + inode_t *inode, struct iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); + +int +args_unlink_cbk_store(default_args_cbk_t *args, int32_t op_ret, + int32_t op_errno, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); + +int +args_rmdir_cbk_store(default_args_cbk_t *args, int32_t op_ret, int32_t op_errno, + struct iatt *preparent, struct iatt *postparent, + dict_t *xdata); + +int +args_symlink_cbk_store(default_args_cbk_t *args, int32_t op_ret, + int32_t op_errno, inode_t *inode, struct iatt *buf, + struct iatt *preparent, struct iatt *postparent, + dict_t *xdata); + +int +args_rename_cbk_store(default_args_cbk_t *args, int32_t op_ret, + int32_t op_errno, struct iatt *buf, + struct iatt *preoldparent, struct iatt *postoldparent, + struct iatt *prenewparent, struct iatt *postnewparent, + dict_t *xdata); + +int +args_link_cbk_store(default_args_cbk_t *args, int32_t op_ret, int32_t op_errno, + inode_t *inode, struct iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); + +int +args_create_cbk_store(default_args_cbk_t *args, int32_t op_ret, + int32_t op_errno, fd_t *fd, inode_t *inode, + struct iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); + +int +args_open_cbk_store(default_args_cbk_t *args, int32_t op_ret, int32_t op_errno, + fd_t *fd, dict_t *xdata); + +int +args_readv_cbk_store(default_args_cbk_t *args, int32_t op_ret, int32_t op_errno, + struct iovec *vector, int32_t count, struct iatt *stbuf, + struct iobref *iobref, dict_t *xdata); + +int +args_writev_cbk_store(default_args_cbk_t *args, int32_t op_ret, + int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata); + +int +args_put_cbk_store(default_args_cbk_t *args, int32_t op_ret, int32_t op_errno, + inode_t *inode, struct iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); + +int +args_flush_cbk_store(default_args_cbk_t *args, int32_t op_ret, int32_t op_errno, + dict_t *xdata); + +int +args_fsync_cbk_store(default_args_cbk_t *args, int32_t op_ret, int32_t op_errno, + struct iatt *prebuf, struct iatt *postbuf, dict_t *xdata); + +int +args_opendir_cbk_store(default_args_cbk_t *args, int32_t op_ret, + int32_t op_errno, fd_t *fd, dict_t *xdata); + +int +args_fsyncdir_cbk_store(default_args_cbk_t *args, int32_t op_ret, + int32_t op_errno, dict_t *xdata); + +int +args_statfs_cbk_store(default_args_cbk_t *args, int32_t op_ret, + int32_t op_errno, struct statvfs *buf, dict_t *xdata); + +int +args_setxattr_cbk_store(default_args_cbk_t *args, int32_t op_ret, + int32_t op_errno, dict_t *xdata); + +int +args_getxattr_cbk_store(default_args_cbk_t *args, int32_t op_ret, + int32_t op_errno, dict_t *dict, dict_t *xdata); + +int +args_fsetxattr_cbk_store(default_args_cbk_t *args, int32_t op_ret, + int32_t op_errno, dict_t *xdata); + +int +args_fgetxattr_cbk_store(default_args_cbk_t *args, int32_t op_ret, + int32_t op_errno, dict_t *dict, dict_t *xdata); + +int +args_removexattr_cbk_store(default_args_cbk_t *args, int32_t op_ret, + int32_t op_errno, dict_t *xdata); + +int +args_fremovexattr_cbk_store(default_args_cbk_t *args, int32_t op_ret, + int32_t op_errno, dict_t *xdata); + +int +args_lk_cbk_store(default_args_cbk_t *args, int32_t op_ret, int32_t op_errno, + struct gf_flock *lock, dict_t *xdata); + +int +args_inodelk_cbk_store(default_args_cbk_t *args, int32_t op_ret, + int32_t op_errno, dict_t *xdata); + +int +args_finodelk_cbk_store(default_args_cbk_t *args, int32_t op_ret, + int32_t op_errno, dict_t *xdata); + +int +args_entrylk_cbk_store(default_args_cbk_t *args, int32_t op_ret, + int32_t op_errno, dict_t *xdata); + +int +args_fentrylk_cbk_store(default_args_cbk_t *args, int32_t op_ret, + int32_t op_errno, dict_t *xdata); + +int +args_readdirp_cbk_store(default_args_cbk_t *args, int32_t op_ret, + int32_t op_errno, gf_dirent_t *entries, dict_t *xdata); + +int +args_readdir_cbk_store(default_args_cbk_t *args, int32_t op_ret, + int32_t op_errno, gf_dirent_t *entries, dict_t *xdata); + +int +args_rchecksum_cbk_store(default_args_cbk_t *args, int32_t op_ret, + int32_t op_errno, uint32_t weak_checksum, + uint8_t *strong_checksum, dict_t *xdata); + +int +args_xattrop_cbk_store(default_args_cbk_t *args, int32_t op_ret, + int32_t op_errno, dict_t *xattr, dict_t *xdata); + +int +args_fxattrop_cbk_store(default_args_cbk_t *args, int32_t op_ret, + int32_t op_errno, dict_t *xattr, dict_t *xdata); + +int +args_setattr_cbk_store(default_args_cbk_t *args, int32_t op_ret, + int32_t op_errno, struct iatt *statpre, + struct iatt *statpost, dict_t *xdata); + +int +args_fsetattr_cbk_store(default_args_cbk_t *args, int32_t op_ret, + int32_t op_errno, struct iatt *statpre, + struct iatt *statpost, dict_t *xdata); + +int +args_fallocate_cbk_store(default_args_cbk_t *args, int32_t op_ret, + int32_t op_errno, struct iatt *statpre, + struct iatt *statpost, dict_t *xdata); + +int +args_discard_cbk_store(default_args_cbk_t *args, int32_t op_ret, + int32_t op_errno, struct iatt *statpre, + struct iatt *statpost, dict_t *xdata); + +int +args_zerofill_cbk_store(default_args_cbk_t *args, int32_t op_ret, + int32_t op_errno, struct iatt *statpre, + struct iatt *statpost, dict_t *xdata); + +int +args_ipc_cbk_store(default_args_cbk_t *args, int32_t op_ret, int32_t op_errno, + dict_t *xdata); + +int +args_seek_cbk_store(default_args_cbk_t *args, int32_t op_ret, int32_t op_errno, + off_t offset, dict_t *xdata); + +void +args_lease_cbk_store(default_args_cbk_t *args, int32_t op_ret, int32_t op_errno, + struct gf_lease *lease, dict_t *xdata); + +void +args_cbk_wipe(default_args_cbk_t *args_cbk); + +void +args_wipe(default_args_t *args); + +int +args_lookup_store(default_args_t *args, loc_t *loc, dict_t *xdata); + +int +args_stat_store(default_args_t *args, loc_t *loc, dict_t *xdata); + +int +args_fstat_store(default_args_t *args, fd_t *fd, dict_t *xdata); + +int +args_truncate_store(default_args_t *args, loc_t *loc, off_t off, dict_t *xdata); +int +args_ftruncate_store(default_args_t *args, fd_t *fd, off_t off, dict_t *xdata); + +int +args_access_store(default_args_t *args, loc_t *loc, int32_t mask, + dict_t *xdata); + +int +args_readlink_store(default_args_t *args, loc_t *loc, size_t size, + dict_t *xdata); + +int +args_mknod_store(default_args_t *args, loc_t *loc, mode_t mode, dev_t rdev, + mode_t umask, dict_t *xdata); + +int +args_mkdir_store(default_args_t *args, loc_t *loc, mode_t mode, mode_t umask, + dict_t *xdata); + +int +args_unlink_store(default_args_t *args, loc_t *loc, int xflag, dict_t *xdata); + +int +args_rmdir_store(default_args_t *args, loc_t *loc, int flags, dict_t *xdata); + +int +args_symlink_store(default_args_t *args, const char *linkname, loc_t *loc, + mode_t umask, dict_t *xdata); + +int +args_rename_store(default_args_t *args, loc_t *oldloc, loc_t *newloc, + dict_t *xdata); + +int +args_link_store(default_args_t *args, loc_t *oldloc, loc_t *newloc, + dict_t *xdata); + +int +args_create_store(default_args_t *args, loc_t *loc, int32_t flags, mode_t mode, + mode_t umask, fd_t *fd, dict_t *xdata); + +int +args_open_store(default_args_t *args, loc_t *loc, int32_t flags, fd_t *fd, + dict_t *xdata); + +int +args_readv_store(default_args_t *args, fd_t *fd, size_t size, off_t off, + uint32_t flags, dict_t *xdata); + +int +args_writev_store(default_args_t *args, fd_t *fd, struct iovec *vector, + int32_t count, off_t off, uint32_t flags, + struct iobref *iobref, dict_t *xdata); + +int +args_put_store(default_args_t *args, loc_t *loc, mode_t mode, mode_t umask, + uint32_t flags, struct iovec *vector, int32_t count, off_t off, + struct iobref *iobref, dict_t *xattr, dict_t *xdata); + +int +args_flush_store(default_args_t *args, fd_t *fd, dict_t *xdata); + +int +args_fsync_store(default_args_t *args, fd_t *fd, int32_t datasync, + dict_t *xdata); + +int +args_opendir_store(default_args_t *args, loc_t *loc, fd_t *fd, dict_t *xdata); + +int +args_fsyncdir_store(default_args_t *args, fd_t *fd, int32_t datasync, + dict_t *xdata); + +int +args_statfs_store(default_args_t *args, loc_t *loc, dict_t *xdata); + +int +args_setxattr_store(default_args_t *args, loc_t *loc, dict_t *dict, + int32_t flags, dict_t *xdata); + +int +args_getxattr_store(default_args_t *args, loc_t *loc, const char *name, + dict_t *xdata); + +int +args_fsetxattr_store(default_args_t *args, fd_t *fd, dict_t *dict, + int32_t flags, dict_t *xdata); + +int +args_fgetxattr_store(default_args_t *args, fd_t *fd, const char *name, + dict_t *xdata); + +int +args_removexattr_store(default_args_t *args, loc_t *loc, const char *name, + dict_t *xdata); + +int +args_fremovexattr_store(default_args_t *args, fd_t *fd, const char *name, + dict_t *xdata); + +int +args_lk_store(default_args_t *args, fd_t *fd, int32_t cmd, + struct gf_flock *lock, dict_t *xdata); + +int +args_inodelk_store(default_args_t *args, const char *volume, loc_t *loc, + int32_t cmd, struct gf_flock *lock, dict_t *xdata); + +int +args_finodelk_store(default_args_t *args, const char *volume, fd_t *fd, + int32_t cmd, struct gf_flock *lock, dict_t *xdata); + +int +args_entrylk_store(default_args_t *args, const char *volume, loc_t *loc, + const char *name, entrylk_cmd cmd, entrylk_type type, + dict_t *xdata); + +int +args_fentrylk_store(default_args_t *args, const char *volume, fd_t *fd, + const char *name, entrylk_cmd cmd, entrylk_type type, + dict_t *xdata); +int +args_readdirp_store(default_args_t *args, fd_t *fd, size_t size, off_t off, + dict_t *xdata); + +int +args_readdir_store(default_args_t *args, fd_t *fd, size_t size, off_t off, + dict_t *xdata); + +int +args_rchecksum_store(default_args_t *args, fd_t *fd, off_t offset, int32_t len, + dict_t *xdata); + +int +args_xattrop_store(default_args_t *args, loc_t *loc, gf_xattrop_flags_t optype, + dict_t *xattr, dict_t *xdata); + +int +args_fxattrop_store(default_args_t *args, fd_t *fd, gf_xattrop_flags_t optype, + dict_t *xattr, dict_t *xdata); + +int +args_setattr_store(default_args_t *args, loc_t *loc, struct iatt *stbuf, + int32_t valid, dict_t *xdata); + +int +args_fsetattr_store(default_args_t *args, fd_t *fd, struct iatt *stbuf, + int32_t valid, dict_t *xdata); + +int +args_fallocate_store(default_args_t *args, fd_t *fd, int32_t mode, off_t offset, + size_t len, dict_t *xdata); + +int +args_discard_store(default_args_t *args, fd_t *fd, off_t offset, size_t len, + dict_t *xdata); + +int +args_zerofill_store(default_args_t *args, fd_t *fd, off_t offset, off_t len, + dict_t *xdata); + +int +args_ipc_store(default_args_t *args, int32_t op, dict_t *xdata); + +int +args_seek_store(default_args_t *args, fd_t *fd, off_t offset, + gf_seek_what_t what, dict_t *xdata); + +void +args_lease_store(default_args_t *args, loc_t *loc, struct gf_lease *lease, + dict_t *xdata); + +int +args_getactivelk_cbk_store(default_args_cbk_t *args, int32_t op_ret, + int32_t op_errno, lock_migration_info_t *locklist, + dict_t *xdata); + +int +args_setactivelk_store(default_args_t *args, loc_t *loc, + lock_migration_info_t *locklist, dict_t *xdata); + +int +args_icreate_store(default_args_t *args, loc_t *loc, mode_t mode, + dict_t *xdata); + +int +args_namelink_store(default_args_t *args, loc_t *loc, dict_t *xdata); + +void +args_cbk_init(default_args_cbk_t *args_cbk); +#endif /* _DEFAULT_ARGS_H */ diff --git a/libglusterfs/src/glusterfs/defaults.h b/libglusterfs/src/glusterfs/defaults.h new file mode 100644 index 00000000000..5d6b8e28a51 --- /dev/null +++ b/libglusterfs/src/glusterfs/defaults.h @@ -0,0 +1,1239 @@ +/* + Copyright (c) 2008-2015 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +/* libglusterfs/src/defaults.h: + This file contains definition of default fops and mops functions. +*/ + +#ifndef _DEFAULTS_H +#define _DEFAULTS_H + +#include "glusterfs/xlator.h" + +typedef struct { + int op_ret; + int op_errno; + inode_t *inode; + struct iatt stat; + struct iatt prestat; + struct iatt poststat; + struct iatt preparent; /* @preoldparent in rename_cbk */ + struct iatt postparent; /* @postoldparent in rename_cbk */ + struct iatt preparent2; /* @prenewparent in rename_cbk */ + struct iatt postparent2; /* @postnewparent in rename_cbk */ + const char *buf; + struct iovec *vector; + int count; + struct iobref *iobref; + fd_t *fd; + struct statvfs statvfs; + dict_t *xattr; + struct gf_flock lock; + uint32_t weak_checksum; + uint8_t *strong_checksum; + dict_t *xdata; + gf_dirent_t entries; + off_t offset; /* seek hole/data */ + int valid; /* If the response is valid or not. For call-stub it is + always valid irrespective of this */ + struct gf_lease lease; + lock_migration_info_t locklist; +} default_args_cbk_t; + +typedef struct { + loc_t loc; /* @old in rename(), link() */ + loc_t loc2; /* @new in rename(), link() */ + fd_t *fd; + off_t offset; + int mask; + size_t size; + mode_t mode; + dev_t rdev; + mode_t umask; + int xflag; + int flags; + const char *linkname; + struct iovec *vector; + int count; + struct iobref *iobref; + int datasync; + dict_t *xattr; + const char *name; + int cmd; + struct gf_flock lock; + const char *volume; + entrylk_cmd entrylkcmd; + entrylk_type entrylktype; + gf_xattrop_flags_t optype; + int valid; + struct iatt stat; + gf_seek_what_t what; + dict_t *xdata; + struct gf_lease lease; + lock_migration_info_t locklist; +} default_args_t; + +typedef struct { + int fop_enum; + unsigned int fop_length; + int *enum_list; + default_args_t *req_list; + dict_t *xdata; +} compound_args_t; + +typedef struct { + int fop_enum; + unsigned int fop_length; + int *enum_list; + default_args_cbk_t *rsp_list; + dict_t *xdata; +} compound_args_cbk_t; + +int32_t +default_notify(xlator_t *this, int32_t event, void *data, ...); + +int32_t +default_forget(xlator_t *this, inode_t *inode); + +int32_t +default_release(xlator_t *this, fd_t *fd); + +int32_t +default_releasedir(xlator_t *this, fd_t *fd); + +extern struct xlator_fops *default_fops; + +/* Management Operations */ + +int32_t +default_getspec(call_frame_t *frame, xlator_t *this, const char *key, + int32_t flag); + +int32_t +default_rchecksum(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, + int32_t len, dict_t *xdata); + +/* FileSystem operations */ +int32_t +default_lookup(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata); + +int32_t +default_stat(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata); + +int32_t +default_fstat(call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdata); + +int32_t +default_truncate(call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset, + dict_t *xdata); + +int32_t +default_ftruncate(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, + dict_t *xdata); + +int32_t +default_access(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t mask, + dict_t *xdata); + +int32_t +default_readlink(call_frame_t *frame, xlator_t *this, loc_t *loc, size_t size, + dict_t *xdata); + +int32_t +default_mknod(call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, + dev_t rdev, mode_t umask, dict_t *xdata); + +int32_t +default_mkdir(call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, + mode_t umask, dict_t *xdata); + +int32_t +default_unlink(call_frame_t *frame, xlator_t *this, loc_t *loc, int xflag, + dict_t *xdata); + +int32_t +default_rmdir(call_frame_t *frame, xlator_t *this, loc_t *loc, int xflag, + dict_t *xdata); + +int32_t +default_symlink(call_frame_t *frame, xlator_t *this, const char *linkpath, + loc_t *loc, mode_t umask, dict_t *xdata); + +int32_t +default_rename(call_frame_t *frame, xlator_t *this, loc_t *oldloc, + loc_t *newloc, dict_t *xdata); + +int32_t +default_link(call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc, + dict_t *xdata); + +int32_t +default_create(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, + mode_t mode, mode_t umask, fd_t *fd, dict_t *xdata); + +int32_t +default_open(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, + fd_t *fd, dict_t *xdata); + +int32_t +default_readv(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, + off_t offset, uint32_t flags, dict_t *xdata); + +int32_t +default_writev(call_frame_t *frame, xlator_t *this, fd_t *fd, + struct iovec *vector, int32_t count, off_t offset, + uint32_t flags, struct iobref *iobref, dict_t *xdata); + +int32_t +default_flush(call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdata); + +int32_t +default_fsync(call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t datasync, + dict_t *xdata); + +int32_t +default_opendir(call_frame_t *frame, xlator_t *this, loc_t *loc, fd_t *fd, + dict_t *xdata); + +int32_t +default_fsyncdir(call_frame_t *frame, xlator_t *this, fd_t *fd, + int32_t datasync, dict_t *xdata); + +int32_t +default_statfs(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata); + +int32_t +default_setxattr(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *dict, + int32_t flags, dict_t *xdata); + +int32_t +default_getxattr(call_frame_t *frame, xlator_t *this, loc_t *loc, + const char *name, dict_t *xdata); + +int32_t +default_fsetxattr(call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *dict, + int32_t flags, dict_t *xdata); + +int32_t +default_fgetxattr(call_frame_t *frame, xlator_t *this, fd_t *fd, + const char *name, dict_t *xdata); + +int32_t +default_removexattr(call_frame_t *frame, xlator_t *this, loc_t *loc, + const char *name, dict_t *xdata); + +int32_t +default_fremovexattr(call_frame_t *frame, xlator_t *this, fd_t *fd, + const char *name, dict_t *xdata); + +int32_t +default_lk(call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t cmd, + struct gf_flock *flock, dict_t *xdata); + +int32_t +default_inodelk(call_frame_t *frame, xlator_t *this, const char *volume, + loc_t *loc, int32_t cmd, struct gf_flock *flock, dict_t *xdata); + +int32_t +default_finodelk(call_frame_t *frame, xlator_t *this, const char *volume, + fd_t *fd, int32_t cmd, struct gf_flock *flock, dict_t *xdata); + +int32_t +default_entrylk(call_frame_t *frame, xlator_t *this, const char *volume, + loc_t *loc, const char *basename, entrylk_cmd cmd, + entrylk_type type, dict_t *xdata); + +int32_t +default_fentrylk(call_frame_t *frame, xlator_t *this, const char *volume, + fd_t *fd, const char *basename, entrylk_cmd cmd, + entrylk_type type, dict_t *xdata); + +int32_t +default_readdir(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, + off_t off, dict_t *xdata); + +int32_t +default_readdirp(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, + off_t off, dict_t *xdata); + +int32_t +default_xattrop(call_frame_t *frame, xlator_t *this, loc_t *loc, + gf_xattrop_flags_t flags, dict_t *dict, dict_t *xdata); + +int32_t +default_fxattrop(call_frame_t *frame, xlator_t *this, fd_t *fd, + gf_xattrop_flags_t flags, dict_t *dict, dict_t *xdata); + +int32_t +default_setattr(call_frame_t *frame, xlator_t *this, loc_t *loc, + struct iatt *stbuf, int32_t valid, dict_t *xdata); + +int32_t +default_fsetattr(call_frame_t *frame, xlator_t *this, fd_t *fd, + struct iatt *stbuf, int32_t valid, dict_t *xdata); + +int32_t +default_fallocate(call_frame_t *frame, xlator_t *this, fd_t *fd, + int32_t keep_size, off_t offset, size_t len, dict_t *xdata); + +int32_t +default_discard(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, + size_t len, dict_t *xdata); + +int32_t +default_zerofill(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, + off_t len, dict_t *xdata); + +int32_t +default_ipc(call_frame_t *frame, xlator_t *this, int32_t op, dict_t *xdata); + +int32_t +default_seek(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, + gf_seek_what_t what, dict_t *xdata); + +int32_t +default_lease(call_frame_t *frame, xlator_t *this, loc_t *loc, + struct gf_lease *lease, dict_t *xdata); + +int32_t +default_getactivelk(call_frame_t *frame, xlator_t *this, loc_t *loc, + dict_t *xdata); + +int32_t +default_setactivelk(call_frame_t *frame, xlator_t *this, loc_t *loc, + lock_migration_info_t *locklist, dict_t *xdata); + +int32_t +default_put(call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, + mode_t umask, uint32_t flags, struct iovec *vector, int32_t count, + off_t off, struct iobref *iobref, dict_t *xattr, dict_t *xdata); + +int32_t +default_icreate(call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, + dict_t *xdata); + +int32_t +default_namelink(call_frame_t *frame, xlator_t *this, loc_t *loc, + dict_t *xdata); + +/* Resume */ +int32_t +default_getspec_resume(call_frame_t *frame, xlator_t *this, const char *key, + int32_t flag); + +int32_t +default_rchecksum_resume(call_frame_t *frame, xlator_t *this, fd_t *fd, + off_t offset, int32_t len, dict_t *xdata); + +/* FileSystem operations */ +int32_t +default_lookup_resume(call_frame_t *frame, xlator_t *this, loc_t *loc, + dict_t *xdata); + +int32_t +default_stat_resume(call_frame_t *frame, xlator_t *this, loc_t *loc, + dict_t *xdata); + +int32_t +default_fstat_resume(call_frame_t *frame, xlator_t *this, fd_t *fd, + dict_t *xdata); + +int32_t +default_truncate_resume(call_frame_t *frame, xlator_t *this, loc_t *loc, + off_t offset, dict_t *xdata); + +int32_t +default_ftruncate_resume(call_frame_t *frame, xlator_t *this, fd_t *fd, + off_t offset, dict_t *xdata); + +int32_t +default_access_resume(call_frame_t *frame, xlator_t *this, loc_t *loc, + int32_t mask, dict_t *xdata); + +int32_t +default_readlink_resume(call_frame_t *frame, xlator_t *this, loc_t *loc, + size_t size, dict_t *xdata); + +int32_t +default_mknod_resume(call_frame_t *frame, xlator_t *this, loc_t *loc, + mode_t mode, dev_t rdev, mode_t umask, dict_t *xdata); + +int32_t +default_mkdir_resume(call_frame_t *frame, xlator_t *this, loc_t *loc, + mode_t mode, mode_t umask, dict_t *xdata); + +int32_t +default_unlink_resume(call_frame_t *frame, xlator_t *this, loc_t *loc, + int xflag, dict_t *xdata); + +int32_t +default_rmdir_resume(call_frame_t *frame, xlator_t *this, loc_t *loc, int xflag, + dict_t *xdata); + +int32_t +default_symlink_resume(call_frame_t *frame, xlator_t *this, + const char *linkpath, loc_t *loc, mode_t umask, + dict_t *xdata); + +int32_t +default_rename_resume(call_frame_t *frame, xlator_t *this, loc_t *oldloc, + loc_t *newloc, dict_t *xdata); + +int32_t +default_link_resume(call_frame_t *frame, xlator_t *this, loc_t *oldloc, + loc_t *newloc, dict_t *xdata); + +int32_t +default_create_resume(call_frame_t *frame, xlator_t *this, loc_t *loc, + int32_t flags, mode_t mode, mode_t umask, fd_t *fd, + dict_t *xdata); + +int32_t +default_open_resume(call_frame_t *frame, xlator_t *this, loc_t *loc, + int32_t flags, fd_t *fd, dict_t *xdata); + +int32_t +default_readv_resume(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, + off_t offset, uint32_t flags, dict_t *xdata); + +int32_t +default_writev_resume(call_frame_t *frame, xlator_t *this, fd_t *fd, + struct iovec *vector, int32_t count, off_t offset, + uint32_t flags, struct iobref *iobref, dict_t *xdata); + +int32_t +default_flush_resume(call_frame_t *frame, xlator_t *this, fd_t *fd, + dict_t *xdata); + +int32_t +default_fsync_resume(call_frame_t *frame, xlator_t *this, fd_t *fd, + int32_t datasync, dict_t *xdata); + +int32_t +default_opendir_resume(call_frame_t *frame, xlator_t *this, loc_t *loc, + fd_t *fd, dict_t *xdata); + +int32_t +default_fsyncdir_resume(call_frame_t *frame, xlator_t *this, fd_t *fd, + int32_t datasync, dict_t *xdata); + +int32_t +default_statfs_resume(call_frame_t *frame, xlator_t *this, loc_t *loc, + dict_t *xdata); + +int32_t +default_setxattr_resume(call_frame_t *frame, xlator_t *this, loc_t *loc, + dict_t *dict, int32_t flags, dict_t *xdata); + +int32_t +default_getxattr_resume(call_frame_t *frame, xlator_t *this, loc_t *loc, + const char *name, dict_t *xdata); + +int32_t +default_fsetxattr_resume(call_frame_t *frame, xlator_t *this, fd_t *fd, + dict_t *dict, int32_t flags, dict_t *xdata); + +int32_t +default_fgetxattr_resume(call_frame_t *frame, xlator_t *this, fd_t *fd, + const char *name, dict_t *xdata); + +int32_t +default_removexattr_resume(call_frame_t *frame, xlator_t *this, loc_t *loc, + const char *name, dict_t *xdata); + +int32_t +default_fremovexattr_resume(call_frame_t *frame, xlator_t *this, fd_t *fd, + const char *name, dict_t *xdata); + +int32_t +default_lk_resume(call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t cmd, + struct gf_flock *flock, dict_t *xdata); + +int32_t +default_inodelk_resume(call_frame_t *frame, xlator_t *this, const char *volume, + loc_t *loc, int32_t cmd, struct gf_flock *flock, + dict_t *xdata); + +int32_t +default_finodelk_resume(call_frame_t *frame, xlator_t *this, const char *volume, + fd_t *fd, int32_t cmd, struct gf_flock *flock, + dict_t *xdata); + +int32_t +default_entrylk_resume(call_frame_t *frame, xlator_t *this, const char *volume, + loc_t *loc, const char *basename, entrylk_cmd cmd, + entrylk_type type, dict_t *xdata); + +int32_t +default_fentrylk_resume(call_frame_t *frame, xlator_t *this, const char *volume, + fd_t *fd, const char *basename, entrylk_cmd cmd, + entrylk_type type, dict_t *xdata); + +int32_t +default_readdir_resume(call_frame_t *frame, xlator_t *this, fd_t *fd, + size_t size, off_t off, dict_t *xdata); + +int32_t +default_readdirp_resume(call_frame_t *frame, xlator_t *this, fd_t *fd, + size_t size, off_t off, dict_t *xdata); + +int32_t +default_xattrop_resume(call_frame_t *frame, xlator_t *this, loc_t *loc, + gf_xattrop_flags_t flags, dict_t *dict, dict_t *xdata); + +int32_t +default_fxattrop_resume(call_frame_t *frame, xlator_t *this, fd_t *fd, + gf_xattrop_flags_t flags, dict_t *dict, dict_t *xdata); +int32_t +default_rchecksum_resume(call_frame_t *frame, xlator_t *this, fd_t *fd, + off_t offset, int32_t len, dict_t *xdata); + +int32_t +default_setattr_resume(call_frame_t *frame, xlator_t *this, loc_t *loc, + struct iatt *stbuf, int32_t valid, dict_t *xdata); + +int32_t +default_fsetattr_resume(call_frame_t *frame, xlator_t *this, fd_t *fd, + struct iatt *stbuf, int32_t valid, dict_t *xdata); + +int32_t +default_fallocate_resume(call_frame_t *frame, xlator_t *this, fd_t *fd, + int32_t keep_size, off_t offset, size_t len, + dict_t *xdata); + +int32_t +default_discard_resume(call_frame_t *frame, xlator_t *this, fd_t *fd, + off_t offset, size_t len, dict_t *xdata); + +int32_t +default_zerofill_resume(call_frame_t *frame, xlator_t *this, fd_t *fd, + off_t offset, off_t len, dict_t *xdata); + +int32_t +default_ipc_resume(call_frame_t *frame, xlator_t *this, int32_t op, + dict_t *xdata); + +int32_t +default_seek_resume(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, + gf_seek_what_t what, dict_t *xdata); + +int32_t +default_lease_resume(call_frame_t *frame, xlator_t *this, loc_t *loc, + struct gf_lease *lease, dict_t *xdata); + +int32_t +default_getactivelk_resume(call_frame_t *frame, xlator_t *this, loc_t *loc, + dict_t *xdata); + +int32_t +default_setactivelk_resume(call_frame_t *frame, xlator_t *this, loc_t *loc, + lock_migration_info_t *locklist, dict_t *xdata); + +int32_t +default_put_resume(call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, + mode_t umask, uint32_t flags, struct iovec *vector, + int32_t count, off_t off, struct iobref *iobref, + dict_t *xattr, dict_t *xdata); + +/* _cbk_resume */ + +int32_t +default_lookup_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *buf, dict_t *xdata, + struct iatt *postparent); + +int32_t +default_stat_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *buf, + dict_t *xdata); + +int32_t +default_truncate_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, + struct iatt *prebuf, struct iatt *postbuf, + dict_t *xdata); + +int32_t +default_ftruncate_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, + struct iatt *prebuf, struct iatt *postbuf, + dict_t *xdata); + +int32_t +default_access_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + +int32_t +default_readlink_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, const char *path, + struct iatt *buf, dict_t *xdata); + +int32_t +default_mknod_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); + +int32_t +default_mkdir_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); + +int32_t +default_unlink_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, + struct iatt *preparent, struct iatt *postparent, + dict_t *xdata); + +int32_t +default_rmdir_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, + struct iatt *preparent, struct iatt *postparent, + dict_t *xdata); + +int32_t +default_symlink_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); + +int32_t +default_rename_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *buf, + struct iatt *preoldparent, struct iatt *postoldparent, + struct iatt *prenewparent, struct iatt *postnewparent, + dict_t *xdata); + +int32_t +default_link_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); + +int32_t +default_create_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, fd_t *fd, + inode_t *inode, struct iatt *buf, + struct iatt *preparent, struct iatt *postparent, + dict_t *xdata); + +int32_t +default_open_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, fd_t *fd, + dict_t *xdata); + +int32_t +default_readv_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iovec *vector, + int32_t count, struct iatt *stbuf, + struct iobref *iobref, dict_t *xdata); + +int32_t +default_writev_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata); + +int32_t +default_flush_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + +int32_t +default_fsync_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata); + +int32_t +default_fstat_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *buf, + dict_t *xdata); + +int32_t +default_opendir_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, fd_t *fd, + dict_t *xdata); + +int32_t +default_fsyncdir_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + +int32_t +default_statfs_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct statvfs *buf, + dict_t *xdata); + +int32_t +default_setxattr_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + +int32_t +default_fsetxattr_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + +int32_t +default_fgetxattr_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *dict, + dict_t *xdata); + +int32_t +default_getxattr_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *dict, + dict_t *xdata); + +int32_t +default_xattrop_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *dict, + dict_t *xdata); + +int32_t +default_fxattrop_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *dict, + dict_t *xdata); + +int32_t +default_removexattr_cbk_resume(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, int32_t op_errno, + dict_t *xdata); + +int32_t +default_fremovexattr_cbk_resume(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, dict_t *xdata); + +int32_t +default_lk_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct gf_flock *lock, + dict_t *xdata); + +int32_t +default_inodelk_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + +int32_t +default_finodelk_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + +int32_t +default_entrylk_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + +int32_t +default_fentrylk_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + +int32_t +default_rchecksum_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, + uint32_t weak_checksum, uint8_t *strong_checksum, + dict_t *xdata); + +int32_t +default_readdir_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, + gf_dirent_t *entries, dict_t *xdata); + +int32_t +default_readdirp_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, + gf_dirent_t *entries, dict_t *xdata); + +int32_t +default_setattr_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, + struct iatt *statpre, struct iatt *statpost, + dict_t *xdata); + +int32_t +default_fsetattr_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, + struct iatt *statpre, struct iatt *statpost, + dict_t *xdata); + +int32_t +default_fallocate_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *pre, + struct iatt *post, dict_t *xdata); + +int32_t +default_discard_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *pre, + struct iatt *post, dict_t *xdata); + +int32_t +default_zerofill_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *pre, + struct iatt *post, dict_t *xdata); +int32_t +default_ipc_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + +int32_t +default_seek_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, off_t offset, + dict_t *xdata); + +int32_t +default_getspec_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, char *spec_data); + +int32_t +default_lease_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, + struct gf_lease *lease, dict_t *xdata); + +int32_t +default_getactivelk_cbk_resume(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, int32_t op_errno, + lock_migration_info_t *locklist, dict_t *xdata); + +int32_t +default_setactivelk_cbk_resume(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, int32_t op_errno, + dict_t *xdata); + +int32_t +default_put_cbk_resume(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); + +int32_t +default_icreate_resume(call_frame_t *frame, xlator_t *this, loc_t *loc, + mode_t mode, dict_t *xdata); + +int32_t +default_namelink_resume(call_frame_t *frame, xlator_t *this, loc_t *loc, + dict_t *xdata); + +/* _CBK */ +int32_t +default_lookup_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *buf, dict_t *xdata, struct iatt *postparent); + +int32_t +default_stat_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *buf, + dict_t *xdata); + +int32_t +default_truncate_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata); + +int32_t +default_ftruncate_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata); + +int32_t +default_access_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + +int32_t +default_readlink_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, const char *path, + struct iatt *buf, dict_t *xdata); + +int32_t +default_mknod_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); + +int32_t +default_mkdir_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); + +int32_t +default_unlink_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); + +int32_t +default_rmdir_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); + +int32_t +default_symlink_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); + +int32_t +default_rename_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *buf, + struct iatt *preoldparent, struct iatt *postoldparent, + struct iatt *prenewparent, struct iatt *postnewparent, + dict_t *xdata); + +int32_t +default_link_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); + +int32_t +default_create_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, fd_t *fd, inode_t *inode, + struct iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); + +int32_t +default_open_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, fd_t *fd, dict_t *xdata); + +int32_t +default_readv_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iovec *vector, + int32_t count, struct iatt *stbuf, struct iobref *iobref, + dict_t *xdata); + +int32_t +default_writev_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata); + +int32_t +default_flush_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + +int32_t +default_fsync_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata); + +int32_t +default_fstat_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *buf, + dict_t *xdata); + +int32_t +default_opendir_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, fd_t *fd, dict_t *xdata); + +int32_t +default_fsyncdir_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + +int32_t +default_statfs_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct statvfs *buf, + dict_t *xdata); + +int32_t +default_setxattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + +int32_t +default_fsetxattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + +int32_t +default_fgetxattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *dict, + dict_t *xdata); + +int32_t +default_getxattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *dict, + dict_t *xdata); + +int32_t +default_xattrop_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *dict, + dict_t *xdata); + +int32_t +default_fxattrop_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *dict, + dict_t *xdata); + +int32_t +default_removexattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + +int32_t +default_fremovexattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + +int32_t +default_lk_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct gf_flock *lock, + dict_t *xdata); + +int32_t +default_inodelk_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + +int32_t +default_finodelk_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + +int32_t +default_entrylk_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + +int32_t +default_fentrylk_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + +int32_t +default_rchecksum_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, uint32_t weak_checksum, + uint8_t *strong_checksum, dict_t *xdata); + +int32_t +default_readdir_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, gf_dirent_t *entries, + dict_t *xdata); + +int32_t +default_readdirp_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, gf_dirent_t *entries, + dict_t *xdata); + +int32_t +default_setattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *statpre, + struct iatt *statpost, dict_t *xdata); + +int32_t +default_fsetattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *statpre, + struct iatt *statpost, dict_t *xdata); + +int32_t +default_fallocate_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *pre, + struct iatt *post, dict_t *xdata); + +int32_t +default_discard_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *pre, + struct iatt *post, dict_t *xdata); + +int32_t +default_zerofill_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *pre, + struct iatt *post, dict_t *xdata); + +int32_t +default_ipc_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + +int32_t +default_seek_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, off_t offset, dict_t *xdata); + +int32_t +default_getspec_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, char *spec_data); + +int32_t +default_lease_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct gf_lease *lease, + dict_t *xdata); + +int32_t +default_getactivelk_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, + lock_migration_info_t *locklist, dict_t *xdata); + +int32_t +default_setactivelk_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + +int32_t +default_put_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); + +int32_t +default_icreate_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *buf, dict_t *xdata); + +int32_t +default_namelink_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata); + +int32_t +default_lookup_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_stat_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_truncate_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_ftruncate_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_access_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_readlink_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_mknod_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_mkdir_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_unlink_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_rmdir_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_symlink_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_rename_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_link_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_create_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_open_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_readv_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_writev_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_flush_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_fsync_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_fstat_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_opendir_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_fsyncdir_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_statfs_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_setxattr_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_fsetxattr_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_fgetxattr_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_getxattr_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_xattrop_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_fxattrop_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_removexattr_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_fremovexattr_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_lk_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_inodelk_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_finodelk_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_entrylk_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_fentrylk_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_rchecksum_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_readdir_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_readdirp_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_setattr_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_fsetattr_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_fallocate_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_discard_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_zerofill_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_getspec_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_ipc_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_seek_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_lease_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_getactivelk_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_setactivelk_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_put_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_icreate_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_namelink_failure_cbk(call_frame_t *frame, int32_t op_errno); + +int32_t +default_mem_acct_init(xlator_t *this); + +void +default_fini(xlator_t *this); + +#endif /* _DEFAULTS_H */ diff --git a/libglusterfs/src/glusterfs/dict.h b/libglusterfs/src/glusterfs/dict.h new file mode 100644 index 00000000000..161362bb5cb --- /dev/null +++ b/libglusterfs/src/glusterfs/dict.h @@ -0,0 +1,417 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _DICT_H +#define _DICT_H + +#include <inttypes.h> +#include <sys/uio.h> +#include <pthread.h> + +#include "glusterfs/common-utils.h" +#include "glusterfs/libglusterfs-messages.h" + +typedef struct _data data_t; +typedef struct _dict dict_t; +typedef struct _data_pair data_pair_t; + +#define dict_set_sizen(this, key, value) dict_setn(this, key, SLEN(key), value) + +#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)) + +#define dict_set_str_sizen(this, key, str) \ + dict_set_strn(this, key, SLEN(key), str) + +#define dict_set_sizen_str_sizen(this, key, str) \ + dict_set_nstrn(this, key, SLEN(key), str, SLEN(str)) + +#define dict_set_dynstr_sizen(this, key, str) \ + dict_set_dynstrn(this, key, SLEN(key), str) + +#define dict_get_str_sizen(this, key, str) \ + dict_get_strn(this, key, SLEN(key), str) + +#define dict_get_int32_sizen(this, key, val) \ + dict_get_int32n(this, key, SLEN(key), val) + +#define dict_set_int32_sizen(this, key, val) \ + dict_set_int32n(this, key, SLEN(key), val) + +#define GF_PROTOCOL_DICT_SERIALIZE(this, from_dict, to, len, ope, labl) \ + do { \ + int _ret = 0; \ + \ + if (!from_dict) \ + break; \ + \ + _ret = dict_allocate_and_serialize(from_dict, to, &len); \ + if (_ret < 0) { \ + gf_msg(this->name, GF_LOG_WARNING, 0, LG_MSG_DICT_SERIAL_FAILED, \ + "failed to get serialized dict (%s)", (#from_dict)); \ + ope = EINVAL; \ + goto labl; \ + } \ + } while (0) + +#define GF_PROTOCOL_DICT_UNSERIALIZE(xl, to, buff, len, ret, ope, labl) \ + do { \ + if (!len) \ + break; \ + to = dict_new(); \ + GF_VALIDATE_OR_GOTO(xl->name, to, labl); \ + \ + ret = dict_unserialize(buff, len, &to); \ + if (ret < 0) { \ + gf_msg(xl->name, GF_LOG_WARNING, 0, LG_MSG_DICT_UNSERIAL_FAILED, \ + "failed to unserialize dictionary (%s)", (#to)); \ + \ + ope = EINVAL; \ + goto labl; \ + } \ + \ + } while (0) + +#define dict_foreach_inline(d, c) for (c = d->members_list; c; c = c->next) + +#define DICT_KEY_VALUE_MAX_SIZE 1048576 +#define DICT_MAX_FLAGS 256 +#define DICT_FLAG_SET 1 +#define DICT_FLAG_CLEAR 0 + +struct _data { + char *data; + gf_atomic_t refcount; + gf_lock_t lock; + gf_dict_data_type_t data_type; + int32_t len; + gf_boolean_t is_static; +}; + +struct _data_pair { + struct _data_pair *hash_next; + struct _data_pair *prev; + struct _data_pair *next; + data_t *value; + char *key; + uint32_t key_hash; +}; + +struct _dict { + uint64_t max_count; + int32_t hash_size; + int32_t count; + gf_atomic_t refcount; + data_pair_t **members; + data_pair_t *members_list; + char *extra_free; + char *extra_stdfree; + gf_lock_t lock; + data_pair_t *members_internal; + data_pair_t free_pair; + gf_boolean_t free_pair_in_use; +}; + +typedef gf_boolean_t (*dict_match_t)(dict_t *d, char *k, data_t *v, void *data); + +int32_t +is_data_equal(data_t *one, data_t *two); +void +data_destroy(data_t *data); + +/* function to set a key/value pair (overwrite existing if matches the key */ +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); +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 * +dict_getn(dict_t *this, char *key, const int keylen); +void +dict_del(dict_t *this, char *key); +void +dict_deln(dict_t *this, char *key, const int keylen); +int +dict_reset(dict_t *dict); + +int +dict_key_count(dict_t *this); + +int32_t +dict_serialized_length(dict_t *dict); +int32_t +dict_serialize(dict_t *dict, char *buf); +int32_t +dict_unserialize(char *buf, int32_t size, dict_t **fill); + +int32_t +dict_allocate_and_serialize(dict_t *this, char **buf, u_int *length); + +void +dict_unref(dict_t *dict); +dict_t * +dict_ref(dict_t *dict); +data_t * +data_ref(data_t *data); +void +data_unref(data_t *data); + +int32_t +dict_lookup(dict_t *this, char *key, data_t **data); +/* + TODO: provide converts for different byte sizes, signedness, and void * + */ +data_t * +int_to_data(int64_t value); +data_t * +str_to_data(char *value); +data_t * +strn_to_data(char *value, const int vallen); +data_t * +data_from_dynptr(void *value, int32_t len); +data_t * +bin_to_data(void *value, int32_t len); +data_t * +static_str_to_data(char *value); +data_t * +static_bin_to_data(void *value); + +int64_t +data_to_int64(data_t *data); +int32_t +data_to_int32(data_t *data); +int16_t +data_to_int16(data_t *data); +int8_t +data_to_int8(data_t *data); + +uint64_t +data_to_uint64(data_t *data); +uint32_t +data_to_uint32(data_t *data); +uint16_t +data_to_uint16(data_t *data); +uint8_t +data_to_uint8(data_t *data); + +data_t * +data_from_int64(int64_t value); +data_t * +data_from_int32(int32_t value); +data_t * +data_from_int16(int16_t value); +data_t * +data_from_int8(int8_t value); + +data_t * +data_from_uint64(uint64_t value); +data_t * +data_from_uint32(uint32_t value); +data_t * +data_from_uint16(uint16_t value); + +char * +data_to_str(data_t *data); +void * +data_to_bin(data_t *data); +void * +data_to_ptr(data_t *data); +data_t * +data_copy(data_t *old); +struct iatt * +data_to_iatt(data_t *data, char *key); + +int +dict_foreach(dict_t *this, + int (*fn)(dict_t *this, char *key, data_t *value, void *data), + void *data); + +int +dict_foreach_fnmatch(dict_t *dict, char *pattern, + int (*fn)(dict_t *this, char *key, data_t *value, + void *data), + void *data); + +int +dict_foreach_match(dict_t *dict, + gf_boolean_t (*match)(dict_t *this, char *key, data_t *value, + void *mdata), + void *match_data, + int (*action)(dict_t *this, char *key, data_t *value, + void *adata), + void *action_data); + +int +dict_null_foreach_fn(dict_t *d, char *k, data_t *v, void *tmp); +int +dict_remove_foreach_fn(dict_t *d, char *k, data_t *v, void *tmp); +dict_t * +dict_copy(dict_t *this, dict_t *new); +dict_t * +get_new_dict(void); +int +dict_keys_join(void *value, int size, dict_t *dict, + int (*filter_fn)(char *key)); + +/* CLEANED UP FUNCTIONS DECLARATIONS */ +GF_MUST_CHECK dict_t * +dict_new(void); +dict_t * +dict_copy_with_ref(dict_t *this, dict_t *new); + +GF_MUST_CHECK int +dict_reset(dict_t *dict); + +GF_MUST_CHECK int +dict_get_int8(dict_t *this, char *key, int8_t *val); +GF_MUST_CHECK int +dict_set_int8(dict_t *this, char *key, int8_t val); + +GF_MUST_CHECK int +dict_get_int16(dict_t *this, char *key, int16_t *val); +GF_MUST_CHECK int +dict_set_int16(dict_t *this, char *key, int16_t val); + +GF_MUST_CHECK int +dict_get_int32(dict_t *this, char *key, int32_t *val); +GF_MUST_CHECK int +dict_get_int32n(dict_t *this, char *key, const int keylen, int32_t *val); +GF_MUST_CHECK int +dict_set_int32(dict_t *this, char *key, int32_t val); +GF_MUST_CHECK int +dict_set_int32n(dict_t *this, char *key, const int keylen, int32_t val); + +GF_MUST_CHECK int +dict_get_int64(dict_t *this, char *key, int64_t *val); +GF_MUST_CHECK int +dict_set_int64(dict_t *this, char *key, int64_t val); + +GF_MUST_CHECK int +dict_get_uint16(dict_t *this, char *key, uint16_t *val); +GF_MUST_CHECK int +dict_set_uint16(dict_t *this, char *key, uint16_t val); + +GF_MUST_CHECK int +dict_get_uint32(dict_t *this, char *key, uint32_t *val); +GF_MUST_CHECK int +dict_set_uint32(dict_t *this, char *key, uint32_t val); + +GF_MUST_CHECK int +dict_get_uint64(dict_t *this, char *key, uint64_t *val); +GF_MUST_CHECK int +dict_set_uint64(dict_t *this, char *key, uint64_t val); + +GF_MUST_CHECK int +dict_check_flag(dict_t *this, char *key, int flag); +GF_MUST_CHECK int +dict_set_flag(dict_t *this, char *key, int flag); +GF_MUST_CHECK int +dict_clear_flag(dict_t *this, char *key, int flag); + +GF_MUST_CHECK int +dict_get_double(dict_t *this, char *key, double *val); +GF_MUST_CHECK int +dict_set_double(dict_t *this, char *key, double val); + +GF_MUST_CHECK int +dict_set_static_ptr(dict_t *this, char *key, void *ptr); +GF_MUST_CHECK int +dict_get_ptr(dict_t *this, char *key, void **ptr); +GF_MUST_CHECK int +dict_get_ptr_and_len(dict_t *this, char *key, void **ptr, int *len); +GF_MUST_CHECK int +dict_set_dynptr(dict_t *this, char *key, void *ptr, size_t size); + +GF_MUST_CHECK int +dict_get_bin(dict_t *this, char *key, void **ptr); +GF_MUST_CHECK int +dict_set_bin(dict_t *this, char *key, void *ptr, size_t size); +GF_MUST_CHECK int +dict_set_static_bin(dict_t *this, char *key, void *ptr, size_t size); + +GF_MUST_CHECK int +dict_set_option(dict_t *this, char *key, char *str); +GF_MUST_CHECK int +dict_set_str(dict_t *this, char *key, char *str); +GF_MUST_CHECK int +dict_set_strn(dict_t *this, char *key, const int keylen, char *str); +GF_MUST_CHECK int +dict_set_nstrn(dict_t *this, char *key, const int keylen, char *str, + const int vallen); +GF_MUST_CHECK int +dict_set_dynstr(dict_t *this, char *key, char *str); +GF_MUST_CHECK int +dict_set_dynstrn(dict_t *this, char *key, const int keylen, char *str); +GF_MUST_CHECK int +dict_set_dynstr_with_alloc(dict_t *this, char *key, const char *str); +GF_MUST_CHECK int +dict_add_dynstr_with_alloc(dict_t *this, char *key, char *str); +GF_MUST_CHECK int +dict_get_str(dict_t *this, char *key, char **str); +GF_MUST_CHECK int +dict_get_strn(dict_t *this, char *key, const int keylen, char **str); + +GF_MUST_CHECK int +dict_get_str_boolean(dict_t *this, char *key, int default_val); +GF_MUST_CHECK int +dict_rename_key(dict_t *this, char *key, char *replace_key); +GF_MUST_CHECK int +dict_serialize_value_with_delim(dict_t *this, char *buf, int32_t *serz_len, + char delimiter); + +GF_MUST_CHECK int +dict_set_gfuuid(dict_t *this, char *key, uuid_t uuid, bool is_static); +GF_MUST_CHECK int +dict_get_gfuuid(dict_t *this, char *key, uuid_t *uuid); + +GF_MUST_CHECK int +dict_set_iatt(dict_t *this, char *key, struct iatt *iatt, bool is_static); +GF_MUST_CHECK int +dict_get_iatt(dict_t *this, char *key, struct iatt *iatt); + +void +dict_dump_to_statedump(dict_t *dict, char *dict_name, char *domain); + +void +dict_dump_to_log(dict_t *dict); + +int +dict_dump_to_str(dict_t *dict, char *dump, int dumpsize, char *format); +gf_boolean_t +dict_match_everything(dict_t *d, char *k, data_t *v, void *data); + +dict_t * +dict_for_key_value(const char *name, const char *value, size_t size, + gf_boolean_t is_static); + +gf_boolean_t +are_dicts_equal(dict_t *one, dict_t *two, + gf_boolean_t (*match)(dict_t *d, char *k, data_t *v, + void *data), + gf_boolean_t (*value_ignore)(char *k)); +int +dict_has_key_from_array(dict_t *dict, char **strings, gf_boolean_t *result); +#endif diff --git a/libglusterfs/src/glusterfs/event-history.h b/libglusterfs/src/glusterfs/event-history.h new file mode 100644 index 00000000000..c1af8934c03 --- /dev/null +++ b/libglusterfs/src/glusterfs/event-history.h @@ -0,0 +1,38 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _EH_H +#define _EH_H + +#include "glusterfs/mem-types.h" +#include "glusterfs/circ-buff.h" + +struct event_hist { + buffer_t *buffer; + pthread_mutex_t lock; +}; + +typedef struct event_hist eh_t; + +void +eh_dump(eh_t *event, void *data, + int(fn)(circular_buffer_t *buffer, void *data)); + +eh_t * +eh_new(size_t buffer_size, gf_boolean_t use_buffer_once, + void (*destroy_data)(void *data)); + +int +eh_save_history(eh_t *history, void *string); + +int +eh_destroy(eh_t *history); + +#endif /* _EH_H */ diff --git a/libglusterfs/src/glusterfs/events.h b/libglusterfs/src/glusterfs/events.h new file mode 100644 index 00000000000..74c5326427b --- /dev/null +++ b/libglusterfs/src/glusterfs/events.h @@ -0,0 +1,34 @@ +/* + Copyright (c) 2016 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef __EVENTS_H__ +#define __EVENTS_H__ + +#include "eventtypes.h" + +#ifdef USE_EVENTS +int +_gf_event(eventtypes_t event, const char *fmt, ...) + __attribute__((__format__(__printf__, 2, 3))); +#else +__attribute__((__format__(__printf__, 2, 3))) static inline int +_gf_event(eventtypes_t event, const char *fmt, ...) +{ + return 0; +} +#endif /* USE_EVENTS */ + +#define gf_event(event, fmt...) \ + do { \ + FMT_WARN(fmt); \ + _gf_event(event, ##fmt); \ + } while (0) + +#endif /* __EVENTS_H__ */ diff --git a/libglusterfs/src/glusterfs/fd-lk.h b/libglusterfs/src/glusterfs/fd-lk.h new file mode 100644 index 00000000000..6465e6d3f58 --- /dev/null +++ b/libglusterfs/src/glusterfs/fd-lk.h @@ -0,0 +1,63 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _FD_LK_H +#define _FD_LK_H + +#include "glusterfs/fd.h" +#include "glusterfs/locking.h" +#include "glusterfs/list.h" +#include "glusterfs/logging.h" +#include "glusterfs/mem-pool.h" +#include "glusterfs/mem-types.h" +#include "glusterfs/glusterfs.h" +#include "glusterfs/common-utils.h" + +#define get_lk_type(type) \ + type == F_UNLCK ? "F_UNLCK" : (type == F_RDLCK ? "F_RDLCK" : "F_WRLCK") + +#define get_lk_cmd(cmd) \ + cmd == F_SETLKW ? "F_SETLKW" : (cmd == F_SETLK ? "F_SETLK" : "F_GETLK") + +struct _fd; + +struct fd_lk_ctx { + struct list_head lk_list; + gf_atomic_t ref; + gf_lock_t lock; +}; +typedef struct fd_lk_ctx fd_lk_ctx_t; + +struct fd_lk_ctx_node { + int32_t cmd; + struct gf_flock user_flock; + off_t fl_start; + off_t fl_end; + short fl_type; + struct list_head next; +}; +typedef struct fd_lk_ctx_node fd_lk_ctx_node_t; + +fd_lk_ctx_t * +fd_lk_ctx_ref(fd_lk_ctx_t *lk_ctx); + +fd_lk_ctx_t * +fd_lk_ctx_create(void); + +int +fd_lk_insert_and_merge(struct _fd *lk_ctx, int32_t cmd, struct gf_flock *flock); + +int +fd_lk_ctx_unref(fd_lk_ctx_t *lk_ctx); + +gf_boolean_t +fd_lk_ctx_empty(fd_lk_ctx_t *lk_ctx); + +#endif /* _FD_LK_H */ diff --git a/libglusterfs/src/glusterfs/fd.h b/libglusterfs/src/glusterfs/fd.h new file mode 100644 index 00000000000..cdbe2894bc3 --- /dev/null +++ b/libglusterfs/src/glusterfs/fd.h @@ -0,0 +1,167 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _FD_H +#define _FD_H + +#include "glusterfs/list.h" +#include <sys/types.h> +#include <unistd.h> +#include "glusterfs/glusterfs.h" +#include "glusterfs/locking.h" +#include "glusterfs/fd-lk.h" +#include "glusterfs/common-utils.h" + +#define GF_ANON_FD_NO -2 +#define GF_ANON_FD_FLAGS (O_RDWR | O_LARGEFILE) + +struct _inode; +struct _dict; +struct fd_lk_ctx; + +struct _fd_ctx { + union { + uint64_t key; + void *xl_key; + }; + union { + uint64_t value1; + void *ptr1; + }; +}; + +struct _fd { + uint64_t pid; + int32_t flags; + gf_atomic_t refcount; + struct list_head inode_list; + struct _inode *inode; + gf_lock_t lock; /* used ONLY for manipulating + 'struct _fd_ctx' array (_ctx).*/ + struct _fd_ctx *_ctx; + int xl_count; /* Number of xl referred in this fd */ + struct fd_lk_ctx *lk_ctx; + gf_boolean_t anonymous; /* fd which does not have counterpart open + fd on backend (server for client, posix + for server). */ +}; +typedef struct _fd fd_t; + +struct fd_table_entry { + fd_t *fd; + int next_free; +}; +typedef struct fd_table_entry fdentry_t; + +struct _fdtable { + int refcount; + uint32_t max_fds; + pthread_rwlock_t lock; + fdentry_t *fdentries; + int first_free; +}; +typedef struct _fdtable fdtable_t; + +/* Signifies no more entries in the fd table. */ +#define GF_FDTABLE_END -1 + +/* This is used to invalidated + * the next_free value in an fdentry that has been allocated + */ +#define GF_FDENTRY_ALLOCATED -2 + +#include "glusterfs/logging.h" +#include "glusterfs/xlator.h" + +void +gf_fd_put(fdtable_t *fdtable, int32_t fd); + +fd_t * +gf_fd_fdptr_get(fdtable_t *fdtable, int64_t fd); + +fdtable_t * +gf_fd_fdtable_alloc(void); + +int +gf_fd_unused_get(fdtable_t *fdtable, fd_t *fdptr); + +fdentry_t * +gf_fd_fdtable_get_all_fds(fdtable_t *fdtable, uint32_t *count); + +void +gf_fd_fdtable_destroy(fdtable_t *fdtable); + +fd_t * +__fd_ref(fd_t *fd); + +fd_t * +fd_ref(fd_t *fd); + +void +fd_unref(fd_t *fd); + +fd_t * +fd_create(struct _inode *inode, pid_t pid); + +fd_t * +fd_create_uint64(struct _inode *inode, uint64_t pid); + +fd_t * +fd_lookup(struct _inode *inode, pid_t pid); + +fd_t * +fd_lookup_uint64(struct _inode *inode, uint64_t pid); + +fd_t * +fd_lookup_anonymous(inode_t *inode, int32_t flags); + +fd_t * +fd_anonymous(inode_t *inode); + +fd_t * +fd_anonymous_with_flags(inode_t *inode, int32_t flags); + +gf_boolean_t +fd_is_anonymous(fd_t *fd); + +uint8_t +fd_list_empty(struct _inode *inode); + +fd_t * +fd_bind(fd_t *fd); + +int +fd_ctx_set(fd_t *fd, xlator_t *xlator, uint64_t value); + +int +fd_ctx_get(fd_t *fd, xlator_t *xlator, uint64_t *value); + +int +fd_ctx_del(fd_t *fd, xlator_t *xlator, uint64_t *value); + +int +__fd_ctx_del(fd_t *fd, xlator_t *xlator, uint64_t *value); + +int +__fd_ctx_set(fd_t *fd, xlator_t *xlator, uint64_t value); + +int +__fd_ctx_get(fd_t *fd, xlator_t *xlator, uint64_t *value); + +void +fd_ctx_dump(fd_t *fd, char *prefix); + +fdentry_t * +gf_fd_fdtable_copy_all_fds(fdtable_t *fdtable, uint32_t *count); + +void +gf_fdptr_put(fdtable_t *fdtable, fd_t *fd); + +#endif /* _FD_H */ diff --git a/libglusterfs/src/glusterfs/gf-dirent.h b/libglusterfs/src/glusterfs/gf-dirent.h new file mode 100644 index 00000000000..e358da30f58 --- /dev/null +++ b/libglusterfs/src/glusterfs/gf-dirent.h @@ -0,0 +1,71 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _GF_DIRENT_H +#define _GF_DIRENT_H + +#include "glusterfs/iatt.h" +#include "glusterfs/inode.h" + +#define gf_dirent_size(name) (sizeof(gf_dirent_t) + strlen(name) + 1) + +int +gf_deitransform(xlator_t *this, uint64_t y); + +int +gf_itransform(xlator_t *this, uint64_t x, uint64_t *y_p, int client_id); + +uint64_t +gf_dirent_orig_offset(xlator_t *this, uint64_t offset); + +struct _dir_entry { + struct _dir_entry *next; + char *name; + char *link; + struct iatt buf; +}; + +struct _gf_dirent { + union { + struct list_head list; + struct { + struct _gf_dirent *next; + struct _gf_dirent *prev; + }; + }; + uint64_t d_ino; + uint64_t d_off; + uint32_t d_len; + uint32_t d_type; + struct iatt d_stat; + dict_t *dict; + inode_t *inode; + char d_name[]; +}; + +#define DT_ISDIR(mode) (mode == DT_DIR) + +gf_dirent_t * +gf_dirent_for_name(const char *name); +gf_dirent_t * +entry_copy(gf_dirent_t *source); +void +gf_dirent_entry_free(gf_dirent_t *entry); +void +gf_dirent_free(gf_dirent_t *entries); +int +gf_link_inodes_from_dirent(xlator_t *this, inode_t *parent, + gf_dirent_t *entries); +int +gf_fill_iatt_for_dirent(gf_dirent_t *entry, inode_t *parent, xlator_t *subvol); + +void +gf_link_inode_from_dirent(xlator_t *this, inode_t *parent, gf_dirent_t *entry); +#endif /* _GF_DIRENT_H */ diff --git a/libglusterfs/src/glusterfs/gf-event.h b/libglusterfs/src/glusterfs/gf-event.h new file mode 100644 index 00000000000..5d92a2dd285 --- /dev/null +++ b/libglusterfs/src/glusterfs/gf-event.h @@ -0,0 +1,135 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _GF_EVENT_H_ +#define _GF_EVENT_H_ + +#include <pthread.h> +#include "list.h" + +struct event_pool; +struct event_ops; +struct event_slot_poll; +struct event_slot_epoll; +struct event_data { + int idx; + int gen; +} __attribute__((__packed__, __may_alias__)); + +typedef int (*event_handler_t)(int fd, int idx, int gen, void *data, + int poll_in, int poll_out, int poll_err, + char event_thread_exit); + +#define EVENT_EPOLL_TABLES 1024 +#define EVENT_EPOLL_SLOTS 1024 +#define EVENT_MAX_THREADS 1024 + +struct event_pool { + struct event_ops *ops; + + int fd; + int breaker[2]; + + int count; + struct event_slot_poll *reg; + struct event_slot_epoll *ereg[EVENT_EPOLL_TABLES]; + int slots_used[EVENT_EPOLL_TABLES]; + + struct list_head poller_death; + int poller_death_sliced; /* track whether the list of fds interested + * poller_death is sliced. If yes, new thread death + * notification has to wait till the list is added + * back + */ + int poller_gen; + int used; + int changed; + + pthread_mutex_t mutex; + pthread_cond_t cond; + + void *evcache; + int evcache_size; + + /* NOTE: Currently used only when event processing is done using + * epoll. */ + int eventthreadcount; /* number of event threads to execute. */ + pthread_t pollers[EVENT_MAX_THREADS]; /* poller thread_id store, and live + status */ + int destroy; + int activethreadcount; + + /* + * Number of threads created by auto-scaling, *in addition to* the + * configured number of threads. This is only applicable on the + * server, where we try to keep the number of threads around the number + * of bricks. In that case, the configured number is just "extra" + * threads to handle requests in excess of one per brick (including + * requests on the GlusterD connection). For clients or GlusterD, this + * number will always be zero, so the "extra" is all we have. + * + * TBD: consider auto-scaling for clients as well + */ + int auto_thread_count; +}; + +struct event_destroy_data { + int readfd; + struct event_pool *pool; +}; + +struct event_ops { + struct event_pool *(*new)(int count, int eventthreadcount); + + int (*event_register)(struct event_pool *event_pool, int fd, + event_handler_t handler, void *data, int poll_in, + int poll_out, char notify_poller_death); + + int (*event_select_on)(struct event_pool *event_pool, int fd, int idx, + int poll_in, int poll_out); + + int (*event_unregister)(struct event_pool *event_pool, int fd, int idx); + + int (*event_unregister_close)(struct event_pool *event_pool, int fd, + int idx); + + int (*event_dispatch)(struct event_pool *event_pool); + + int (*event_reconfigure_threads)(struct event_pool *event_pool, + int newcount); + int (*event_pool_destroy)(struct event_pool *event_pool); + int (*event_handled)(struct event_pool *event_pool, int fd, int idx, + int gen); +}; + +struct event_pool * +event_pool_new(int count, int eventthreadcount); +int +event_select_on(struct event_pool *event_pool, int fd, int idx, int poll_in, + int poll_out); +int +event_register(struct event_pool *event_pool, int fd, event_handler_t handler, + void *data, int poll_in, int poll_out, char notify_poller_death); +int +event_unregister(struct event_pool *event_pool, int fd, int idx); +int +event_unregister_close(struct event_pool *event_pool, int fd, int idx); +int +event_dispatch(struct event_pool *event_pool); +int +event_reconfigure_threads(struct event_pool *event_pool, int value); +int +event_pool_destroy(struct event_pool *event_pool); +int +event_dispatch_destroy(struct event_pool *event_pool); +int +event_handled(struct event_pool *event_pool, int fd, int idx, int gen); + +#endif /* _GF_EVENT_H_ */ diff --git a/libglusterfs/src/glusterfs/gidcache.h b/libglusterfs/src/glusterfs/gidcache.h new file mode 100644 index 00000000000..ddaabd765b5 --- /dev/null +++ b/libglusterfs/src/glusterfs/gidcache.h @@ -0,0 +1,60 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef __GIDCACHE_H__ +#define __GIDCACHE_H__ + +#include "glusterfs/glusterfs.h" +#include "glusterfs/locking.h" + +/* + * TBD: make the cache size tunable + * + * The current size represents a pretty trivial amount of memory, and should + * provide good hit rates even for quite busy systems. If we ever want to + * support really large cache sizes, we'll need to do dynamic allocation + * instead of just defining an array within a private structure. It doesn't make + * a whole lot of sense to change the associativity, because it won't improve + * hit rates all that much and will increase the maintenance cost as we have + * to scan more entries with every lookup/update. + */ + +#define AUX_GID_CACHE_ASSOC 4 +#define AUX_GID_CACHE_BUCKETS 256 +#define AUX_GID_CACHE_SIZE (AUX_GID_CACHE_ASSOC * AUX_GID_CACHE_BUCKETS) + +typedef struct { + uint64_t gl_id; + uint64_t gl_uid; + uint64_t gl_gid; + int gl_count; + gid_t *gl_list; + time_t gl_deadline; +} gid_list_t; + +typedef struct { + gf_lock_t gc_lock; + uint32_t gc_max_age; + unsigned int gc_nbuckets; + gid_list_t gc_cache[AUX_GID_CACHE_SIZE]; +} gid_cache_t; + +int +gid_cache_init(gid_cache_t *, uint32_t); +int +gid_cache_reconf(gid_cache_t *, uint32_t); +const gid_list_t * +gid_cache_lookup(gid_cache_t *, uint64_t, uint64_t, uint64_t); +void +gid_cache_release(gid_cache_t *, const gid_list_t *); +int +gid_cache_add(gid_cache_t *, gid_list_t *); + +#endif /* __GIDCACHE_H__ */ diff --git a/libglusterfs/src/glusterfs/glfs-message-id.h b/libglusterfs/src/glusterfs/glfs-message-id.h new file mode 100644 index 00000000000..001f4abdf67 --- /dev/null +++ b/libglusterfs/src/glusterfs/glfs-message-id.h @@ -0,0 +1,101 @@ +/* + Copyright (c) 2015-2016 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _GLFS_MESSAGE_ID_H_ +#define _GLFS_MESSAGE_ID_H_ + +/* Base of all message IDs, all message IDs would be + * greater than this */ +#define GLFS_MSGID_BASE 100000 + +/* Segment size of allocated range. Any component needing more than this + * segment size should take multiple segments (at times non contiguous, + * if extensions are being made post the next segment already allocated) */ +#define GLFS_MSGID_SEGMENT 1000 + +/* Macro to define a range of messages for a component. The first argument is + * the name of the component. The second argument is the number of segments + * to allocate. The defined values will be GLFS_MSGID_COMP_<name> and + * GLFS_MSGID_COMP_<name>_END. */ +#define GLFS_MSGID_COMP(_name, _blocks) \ + GLFS_MSGID_COMP_##_name, \ + GLFS_MSGID_COMP_##_name##_END = (GLFS_MSGID_COMP_##_name + \ + (GLFS_MSGID_SEGMENT * (_blocks)) - 1) + +#define GLFS_MSGID(_name, _msgs...) \ + enum _msgid_table_##_name \ + { \ + GLFS_##_name##_COMP_BASE = GLFS_MSGID_COMP_##_name, ##_msgs, \ + GLGS_##_name##_COMP_END \ + } + +/* Per module message segments allocated */ +/* NOTE: For any new module add to the end the modules */ +enum _msgid_comp { + GLFS_MSGID_RESERVED = GLFS_MSGID_BASE - 1, + + GLFS_MSGID_COMP(GLUSTERFSD, 1), + GLFS_MSGID_COMP(LIBGLUSTERFS, 1), + GLFS_MSGID_COMP(RPC_LIB, 1), + GLFS_MSGID_COMP(RPC_TRANS_RDMA, 1), + GLFS_MSGID_COMP(API, 1), + GLFS_MSGID_COMP(CLI, 1), + /* glusterd has a lot of messages, taking 2 segments for the same */ + GLFS_MSGID_COMP(GLUSTERD, 2), + GLFS_MSGID_COMP(AFR, 1), + GLFS_MSGID_COMP(DHT, 1), + /* there is no component called 'common', however reserving this segment + * for common actions/errors like dict_{get/set}, memory accounting*/ + GLFS_MSGID_COMP(COMMON, 1), + GLFS_MSGID_COMP(UPCALL, 1), + GLFS_MSGID_COMP(NFS, 1), + GLFS_MSGID_COMP(POSIX, 1), + GLFS_MSGID_COMP(PC, 1), + GLFS_MSGID_COMP(PS, 1), + GLFS_MSGID_COMP(BITROT_STUB, 1), + GLFS_MSGID_COMP(CHANGELOG, 1), + GLFS_MSGID_COMP(BITROT_BITD, 1), + GLFS_MSGID_COMP(RPC_TRANS_SOCKET, 1), + GLFS_MSGID_COMP(QUOTA, 1), + GLFS_MSGID_COMP(CTR, 1), + GLFS_MSGID_COMP(EC, 1), + GLFS_MSGID_COMP(IO_CACHE, 1), + GLFS_MSGID_COMP(IO_THREADS, 1), + GLFS_MSGID_COMP(MD_CACHE, 1), + GLFS_MSGID_COMP(OPEN_BEHIND, 1), + GLFS_MSGID_COMP(QUICK_READ, 1), + GLFS_MSGID_COMP(READ_AHEAD, 1), + GLFS_MSGID_COMP(READDIR_AHEAD, 1), + GLFS_MSGID_COMP(SYMLINK_CACHE, 1), + GLFS_MSGID_COMP(WRITE_BEHIND, 1), + GLFS_MSGID_COMP(CHANGELOG_LIB, 1), + GLFS_MSGID_COMP(SHARD, 1), + GLFS_MSGID_COMP(JBR, 1), + GLFS_MSGID_COMP(PL, 1), + GLFS_MSGID_COMP(DC, 1), + GLFS_MSGID_COMP(LEASES, 1), + GLFS_MSGID_COMP(INDEX, 1), + GLFS_MSGID_COMP(POSIX_ACL, 1), + GLFS_MSGID_COMP(NLC, 1), + GLFS_MSGID_COMP(SL, 1), + GLFS_MSGID_COMP(HAM, 1), + GLFS_MSGID_COMP(SDFS, 1), + GLFS_MSGID_COMP(QUIESCE, 1), + GLFS_MSGID_COMP(TA, 1), + GLFS_MSGID_COMP(SNAPVIEW_CLIENT, 1), + GLFS_MSGID_COMP(TEMPLATE, 1), + GLFS_MSGID_COMP(UTIME, 1), + GLFS_MSGID_COMP(SNAPVIEW_SERVER, 1), + /* --- new segments for messages goes above this line --- */ + + GLFS_MSGID_END +}; + +#endif /* !_GLFS_MESSAGE_ID_H_ */ diff --git a/libglusterfs/src/glusterfs/globals.h b/libglusterfs/src/glusterfs/globals.h new file mode 100644 index 00000000000..9a2f5324afc --- /dev/null +++ b/libglusterfs/src/glusterfs/globals.h @@ -0,0 +1,176 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _GLOBALS_H +#define _GLOBALS_H + +#define GF_DEFAULT_BASE_PORT 24007 +#define GF_DEFAULT_VOLFILE_TRANSPORT "tcp" + +#define GF_GLOBAL_XLATOR_NAME "global" +#define GD_OP_VERSION_KEY "operating-version" +#define GD_MIN_OP_VERSION_KEY "minimum-operating-version" +#define GD_MAX_OP_VERSION_KEY "maximum-operating-version" + +#define GF_PROTECT_FROM_EXTERNAL_WRITES "trusted.glusterfs.protect.writes" +#define GF_AVOID_OVERWRITE "glusterfs.avoid.overwrite" +#define GF_CLEAN_WRITE_PROTECTION "glusterfs.clean.writexattr" + +/* Gluster versions - OP-VERSION mapping + * + * 3.3.x - 1 + * 3.4.x - 2 + * 3.5.0 - 3 + * 3.5.1 - 30501 + * 3.6.0 - 30600 + * 3.7.0 - 30700 + * 3.7.1 - 30701 + * 3.7.2 - 30702 + * + * Starting with Gluster v3.6, the op-version will be multi-digit integer values + * based on the Glusterfs version, instead of a simply incrementing integer + * value. The op-version for a given X.Y.Z release will be an integer XYZ, with + * Y and Z 2 digit always 2 digits wide and padded with 0 when needed. This + * should allow for some gaps between two Y releases for backports of features + * in Z releases. + */ +#define GD_OP_VERSION_MIN \ + 1 /* MIN is the fresh start op-version, mostly \ + should not change */ +#define GD_OP_VERSION_MAX \ + GD_OP_VERSION_6_0 /* MAX VERSION is the maximum \ + count in VME table, should \ + keep changing with \ + introduction of newer \ + versions */ + +#define GD_OP_VERSION_3_6_0 30600 /* Op-Version for GlusterFS 3.6.0 */ + +#define GD_OP_VERSION_3_7_0 30700 /* Op-version for GlusterFS 3.7.0 */ + +#define GD_OP_VERSION_3_7_1 30701 /* Op-version for GlusterFS 3.7.1 */ + +#define GD_OP_VERSION_3_7_2 30702 /* Op-version for GlusterFS 3.7.2 */ + +#define GD_OP_VERSION_3_7_3 30703 /* Op-version for GlusterFS 3.7.3 */ + +#define GD_OP_VERSION_3_7_4 30704 /* Op-version for GlusterFS 3.7.4 */ + +#define GD_OP_VERSION_3_7_5 30705 /* Op-version for GlusterFS 3.7.5 */ + +#define GD_OP_VERSION_3_7_6 30706 /* Op-version for GlusterFS 3.7.6 */ + +#define GD_OP_VERSION_3_7_7 30707 /* Op-version for GlusterFS 3.7.7 */ + +#define GD_OP_VERSION_3_7_10 30710 /* Op-version for GlusterFS 3.7.10 */ + +#define GD_OP_VERSION_3_7_12 30712 /* Op-version for GlusterFS 3.7.12 */ + +#define GD_OP_VERSION_3_8_0 30800 /* Op-version for GlusterFS 3.8.0 */ + +#define GD_OP_VERSION_3_8_3 30803 /* Op-version for GlusterFS 3.8.3 */ + +#define GD_OP_VERSION_3_8_4 30804 /* Op-version for GlusterFS 3.8.4 */ + +#define GD_OP_VERSION_3_9_0 30900 /* Op-version for GlusterFS 3.9.0 */ + +#define GD_OP_VERSION_3_9_1 30901 /* Op-version for GlusterFS 3.9.1 */ + +#define GD_OP_VERSION_3_10_0 31000 /* Op-version for GlusterFS 3.10.0 */ + +#define GD_OP_VERSION_3_10_1 31001 /* Op-version for GlusterFS 3.10.1 */ + +#define GD_OP_VERSION_3_10_2 31002 /* Op-version for GlusterFS 3.10.2 */ + +#define GD_OP_VERSION_3_11_0 31100 /* Op-version for GlusterFS 3.11.0 */ + +#define GD_OP_VERSION_3_11_1 31101 /* Op-version for GlusterFS 3.11.1 */ + +#define GD_OP_VERSION_3_12_0 31200 /* Op-version for GlusterFS 3.12.0 */ + +#define GD_OP_VERSION_3_12_2 31202 /* Op-version for GlusterFS 3.12.2 */ + +#define GD_OP_VERSION_3_12_3 31203 /* Op-version for GlusterFS 3.12.3 */ + +#define GD_OP_VERSION_3_13_0 31300 /* Op-version for GlusterFS 3.13.0 */ + +#define GD_OP_VERSION_3_13_1 31301 /* Op-version for GlusterFS 3.13.1 */ + +#define GD_OP_VERSION_3_13_2 31302 /* Op-version for GlusterFS 3.13.2 */ + +#define GD_OP_VERSION_4_0_0 40000 /* Op-version for GlusterFS 4.0.0 */ + +#define GD_OP_VERSION_4_1_0 40100 /* Op-version for GlusterFS 4.1.0 */ + +#define GD_OP_VERSION_5_0 50000 /* Op-version for GlusterFS 5.0 */ + +#define GD_OP_VERSION_6_0 60000 /* Op-version for GlusterFS 6.0 */ + +#define GD_OP_VER_PERSISTENT_AFR_XATTRS GD_OP_VERSION_3_6_0 + +#include "glusterfs/xlator.h" +#include "glusterfs/options.h" + +/* THIS */ +#define THIS (*__glusterfs_this_location()) +#define DECLARE_OLD_THIS xlator_t *old_THIS = THIS + +xlator_t ** +__glusterfs_this_location(void); +xlator_t * +glusterfs_this_get(void); +int +glusterfs_this_set(xlator_t *); + +extern xlator_t global_xlator; +extern struct volume_options global_xl_options[]; + +/* syncopctx */ +void * +syncopctx_getctx(void); +int +syncopctx_setctx(void *ctx); + +/* task */ +void * +synctask_get(void); +int +synctask_set(void *); + +/* uuid_buf */ +char * +glusterfs_uuid_buf_get(void); +/* lkowner_buf */ +char * +glusterfs_lkowner_buf_get(void); +/* leaseid buf */ +char * +glusterfs_leaseid_buf_get(void); +char * +glusterfs_leaseid_exist(void); + +/* init */ +int +glusterfs_globals_init(glusterfs_ctx_t *ctx); + +struct tvec_base * +glusterfs_ctx_tw_get(glusterfs_ctx_t *ctx); +void +glusterfs_ctx_tw_put(glusterfs_ctx_t *ctx); + +extern const char *gf_fop_list[]; +extern const char *gf_upcall_list[]; + +/* mem acct enable/disable */ +int +gf_global_mem_acct_enable_get(void); +int +gf_global_mem_acct_enable_set(int val); +#endif /* !_GLOBALS_H */ diff --git a/libglusterfs/src/glusterfs/glusterfs-acl.h b/libglusterfs/src/glusterfs/glusterfs-acl.h new file mode 100644 index 00000000000..cae55e8062f --- /dev/null +++ b/libglusterfs/src/glusterfs/glusterfs-acl.h @@ -0,0 +1,162 @@ +/* + Copyright (c) 2013 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _GLUSTERFS_ACL_H +#define _GLUSTERFS_ACL_H + +/* WARNING: Much if this code is restricted to Linux usage. + * + * It would be much cleaner to replace the code with something that is based on + * libacl (or its libc implementation on *BSD). + * + * Initial work for replacing this Linux specific implementation has been + * started as part of the "Improve POSIX ACLs" feature. Functionality for this + * feature has been added to the end of this file. + */ + +#include <stdint.h> +#include <sys/types.h> /* For uid_t */ + +#include "glusterfs/locking.h" /* For gf_lock_t in struct posix_acl_conf */ + +#define ACL_PROGRAM 100227 +#define ACLV3_VERSION 3 + +#define POSIX_ACL_MINIMAL_ACE_COUNT 3 + +#define POSIX_ACL_READ (0x04) +#define POSIX_ACL_WRITE (0x02) +#define POSIX_ACL_EXECUTE (0x01) + +#define POSIX_ACL_UNDEFINED_TAG (0x00) +#define POSIX_ACL_USER_OBJ (0x01) +#define POSIX_ACL_USER (0x02) +#define POSIX_ACL_GROUP_OBJ (0x04) +#define POSIX_ACL_GROUP (0x08) +#define POSIX_ACL_MASK (0x10) +#define POSIX_ACL_OTHER (0x20) + +#define POSIX_ACL_UNDEFINED_ID (-1) + +#define POSIX_ACL_XATTR_VERSION (0x02) + +#define POSIX_ACL_ACCESS_XATTR "system.posix_acl_access" +#define POSIX_ACL_DEFAULT_XATTR "system.posix_acl_default" + +struct posix_acl_xattr_entry { + uint16_t tag; + uint16_t perm; + uint32_t id; +}; + +struct posix_acl_xattr_header { + uint32_t version; + struct posix_acl_xattr_entry entries[]; +}; + +typedef struct posix_acl_xattr_entry posix_acl_xattr_entry; +typedef struct posix_acl_xattr_header posix_acl_xattr_header; + +static inline size_t +posix_acl_xattr_size(unsigned int count) +{ + return (sizeof(posix_acl_xattr_header) + + (count * sizeof(posix_acl_xattr_entry))); +} + +static inline ssize_t +posix_acl_xattr_count(size_t size) +{ + if (size < sizeof(posix_acl_xattr_header)) + return (-1); + size -= sizeof(posix_acl_xattr_header); + if (size % sizeof(posix_acl_xattr_entry)) + return (-1); + return (size / sizeof(posix_acl_xattr_entry)); +} + +struct posix_ace { + uint16_t tag; + uint16_t perm; + uint32_t id; +}; + +struct posix_acl { + int refcnt; + int count; + struct posix_ace entries[]; +}; + +struct posix_acl_ctx { + uid_t uid; + gid_t gid; + mode_t perm; + glusterfs_fop_t fop; + struct posix_acl *acl_access; + struct posix_acl *acl_default; +}; + +struct posix_acl_conf { + gf_lock_t acl_lock; + uid_t super_uid; + struct posix_acl *minimal_acl; +}; + +/* Above this comment, the legacy POSIX ACL support is kept until it is not + * used anymore. Below you will find the more portable version to support POSIX + * ACls based on the implementation of libacl (see sys/acl.h). */ + +/* virtual xattrs passed over RPC, not stored on disk */ +#define GF_POSIX_ACL_ACCESS "glusterfs.posix.acl" +#define GF_POSIX_ACL_DEFAULT "glusterfs.posix.default_acl" +#define GF_POSIX_ACL_REQUEST(key) \ + (!strncmp(key, GF_POSIX_ACL_ACCESS, SLEN(GF_POSIX_ACL_ACCESS)) || \ + !strncmp(key, GF_POSIX_ACL_DEFAULT, SLEN(GF_POSIX_ACL_DEFAULT))) + +#ifdef HAVE_SYS_ACL_H /* only NetBSD does not support POSIX ACLs */ + +#include <sys/acl.h> + +static inline const char * +gf_posix_acl_get_key(const acl_type_t type) +{ + char *acl_key = NULL; + + switch (type) { + case ACL_TYPE_ACCESS: + acl_key = GF_POSIX_ACL_ACCESS; + break; + case ACL_TYPE_DEFAULT: + acl_key = GF_POSIX_ACL_DEFAULT; + break; + default: + errno = EINVAL; + } + + return acl_key; +} + +static inline const acl_type_t +gf_posix_acl_get_type(const char *key) +{ + acl_type_t type = 0; + + if (!strncmp(key, GF_POSIX_ACL_ACCESS, SLEN(GF_POSIX_ACL_ACCESS))) + type = ACL_TYPE_ACCESS; + else if (!strncmp(key, GF_POSIX_ACL_DEFAULT, SLEN(GF_POSIX_ACL_DEFAULT))) + type = ACL_TYPE_DEFAULT; + else + errno = EINVAL; + + return type; +} + +#endif /* HAVE_SYS_ACL_H */ +#endif /* _GLUSTERFS_ACL_H */ diff --git a/libglusterfs/src/glusterfs/glusterfs.h b/libglusterfs/src/glusterfs/glusterfs.h new file mode 100644 index 00000000000..908a0ce774f --- /dev/null +++ b/libglusterfs/src/glusterfs/glusterfs.h @@ -0,0 +1,803 @@ +/* + Copyright (c) 2008-2016 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _GLUSTERFS_H +#define _GLUSTERFS_H + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <netinet/in.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/statvfs.h> +#include <netdb.h> +#include <errno.h> +#include <dirent.h> +#include <unistd.h> +#include <fcntl.h> +#include <arpa/inet.h> +#include <sys/poll.h> +#include <pthread.h> +#include <limits.h> /* For PATH_MAX */ +#include <openssl/sha.h> + +#include "glusterfs-fops.h" /* generated XDR values for FOPs */ + +#ifndef IXDR_GET_LONG +#define IXDR_GET_LONG(buf) ((long)IXDR_GET_U_INT32(buf)) +#endif +#ifndef IXDR_PUT_LONG +#define IXDR_PUT_LONG(buf, v) ((long)IXDR_PUT_INT32(buf, (long)(v))) +#endif +#ifndef IXDR_GET_U_LONG +#define IXDR_GET_U_LONG(buf) ((u_long)IXDR_GET_LONG(buf)) +#endif +#ifndef IXDR_PUT_U_LONG +#define IXDR_PUT_U_LONG(buf, v) IXDR_PUT_LONG(buf, (long)(v)) +#endif + +#include "glusterfs/list.h" +#include "glusterfs/locking.h" +#include "glusterfs/logging.h" +#include "glusterfs/lkowner.h" +#include "glusterfs/compat-uuid.h" +#include "glusterfs/refcount.h" +#include "glusterfs/atomic.h" + +#define GF_YES 1 +#define GF_NO 0 + +#ifndef O_LARGEFILE +/* savannah bug #20053, patch for compiling on darwin */ +#define O_LARGEFILE 0100000 /* from bits/fcntl.h */ +#endif + +#ifndef O_FMODE_EXEC +/* redhat bug 843080, added from linux/fs.h */ +#define O_FMODE_EXEC 040 // 0x20 +#endif + +#ifndef O_DIRECT +/* savannah bug #20050, #20052 */ +#define O_DIRECT 0 /* From asm/fcntl.h */ +#endif + +#ifndef O_DIRECTORY +/* FreeBSD does not need O_DIRECTORY */ +#define O_DIRECTORY 0 +#endif + +#ifndef EBADFD +/* Mac OS X does not have EBADFD */ +#define EBADFD EBADF +#endif + +#ifndef FNM_EXTMATCH +#define FNM_EXTMATCH 0 +#endif + +/*gets max-offset on all architectures correctly*/ +#define GF_OFF_MAX ((1ULL << (sizeof(off_t) * 8 - 1)) - 1ULL) + +#define GLUSTERD_MAX_SNAP_NAME 255 +#define GLUSTERFS_SOCKET_LISTEN_BACKLOG 1024 + +#define SLEN(str) (sizeof(str) - 1) + +#define ZR_MOUNTPOINT_OPT "mountpoint" +#define ZR_ATTR_TIMEOUT_OPT "attribute-timeout" +#define ZR_ENTRY_TIMEOUT_OPT "entry-timeout" +#define ZR_NEGATIVE_TIMEOUT_OPT "negative-timeout" +#define ZR_DIRECT_IO_OPT "direct-io-mode" +#define ZR_STRICT_VOLFILE_CHECK "strict-volfile-check" +#define ZR_DUMP_FUSE "dump-fuse" +#define ZR_FUSE_MOUNTOPTS "fuse-mountopts" +#define IO_THREADS_QUEUE_SIZE_KEY "io-thread-queue-size" + +#define GF_XATTR_CLRLK_CMD "glusterfs.clrlk" +#define GF_XATTR_PATHINFO_KEY "trusted.glusterfs.pathinfo" +#define GF_XATTR_NODE_UUID_KEY "trusted.glusterfs.node-uuid" +#define GF_XATTR_LIST_NODE_UUIDS_KEY "trusted.glusterfs.list-node-uuids" +#define GF_REBAL_FIND_LOCAL_SUBVOL "glusterfs.find-local-subvol" +#define GF_REBAL_OLD_FIND_LOCAL_SUBVOL "glusterfs.old-find-local-subvol" +#define GF_XATTR_VOL_ID_KEY "trusted.glusterfs.volume-id" +#define GF_XATTR_LOCKINFO_KEY "trusted.glusterfs.lockinfo" +#define GF_META_LOCK_KEY "glusterfs.lock-migration-meta-lock" +#define GF_META_UNLOCK_KEY "glusterfs.lock-migration-meta-unlock" +#define GF_XATTR_GET_REAL_FILENAME_KEY "glusterfs.get_real_filename:" +#define GF_XATTR_USER_PATHINFO_KEY "glusterfs.pathinfo" +#define GF_INTERNAL_IGNORE_DEEM_STATFS "ignore-deem-statfs" +#define GF_XATTR_IOSTATS_DUMP_KEY "trusted.io-stats-dump" + +#define GF_READDIR_SKIP_DIRS "readdir-filter-directories" +#define GF_MDC_LOADED_KEY_NAMES "glusterfs.mdc.loaded.key.names" + +#define BD_XATTR_KEY "user.glusterfs" +#define GF_PREOP_PARENT_KEY "glusterfs.preop.parent.key" +#define GF_PREOP_CHECK_FAILED "glusterfs.preop.check.failed" + +#define XATTR_IS_PATHINFO(x) \ + ((strncmp(x, GF_XATTR_PATHINFO_KEY, strlen(x)) == 0) || \ + (strncmp(x, GF_XATTR_USER_PATHINFO_KEY, strlen(x)) == 0)) +#define XATTR_IS_NODE_UUID(x) \ + (strncmp(x, GF_XATTR_NODE_UUID_KEY, SLEN(GF_XATTR_NODE_UUID_KEY)) == 0) +#define XATTR_IS_NODE_UUID_LIST(x) \ + (strncmp(x, GF_XATTR_LIST_NODE_UUIDS_KEY, \ + SLEN(GF_XATTR_LIST_NODE_UUIDS_KEY)) == 0) +#define XATTR_IS_LOCKINFO(x) \ + (strncmp(x, GF_XATTR_LOCKINFO_KEY, SLEN(GF_XATTR_LOCKINFO_KEY)) == 0) + +#define XATTR_IS_BD(x) (strncmp(x, BD_XATTR_KEY, SLEN(BD_XATTR_KEY)) == 0) + +#define GF_XATTR_LINKINFO_KEY "trusted.distribute.linkinfo" +#define GFID_XATTR_KEY "trusted.gfid" +#define PGFID_XATTR_KEY_PREFIX "trusted.pgfid." +#define GFID2PATH_VIRT_XATTR_KEY "glusterfs.gfidtopath" +#define GFID2PATH_XATTR_KEY_PREFIX "trusted.gfid2path." +#define GFID2PATH_XATTR_KEY_PREFIX_LENGTH 18 +#define VIRTUAL_GFID_XATTR_KEY_STR "glusterfs.gfid.string" +#define VIRTUAL_GFID_XATTR_KEY "glusterfs.gfid" +#define GF_XATTR_MDATA_KEY "trusted.glusterfs.mdata" +#define UUID_CANONICAL_FORM_LEN 36 + +#define GET_ANCESTRY_PATH_KEY "glusterfs.ancestry.path" +#define GET_ANCESTRY_DENTRY_KEY "glusterfs.ancestry.dentry" + +#define BITROT_DEFAULT_CURRENT_VERSION (unsigned long)1 +#define BITROT_DEFAULT_SIGNING_VERSION (unsigned long)0 + +/* on-disk object signature keys */ +#define BITROT_OBJECT_BAD_KEY "trusted.bit-rot.bad-file" +#define BITROT_CURRENT_VERSION_KEY "trusted.bit-rot.version" +#define BITROT_SIGNING_VERSION_KEY "trusted.bit-rot.signature" + +/* globally usable bad file marker */ +#define GLUSTERFS_BAD_INODE "glusterfs.bad-inode" + +/* on-disk size of signing xattr (not the signature itself) */ +#define BITROT_SIGNING_XATTR_SIZE_KEY "trusted.glusterfs.bit-rot.size" + +/* GET/SET object signature */ +#define GLUSTERFS_GET_OBJECT_SIGNATURE "trusted.glusterfs.get-signature" +#define GLUSTERFS_SET_OBJECT_SIGNATURE "trusted.glusterfs.set-signature" + +/* operation needs to be durable on-disk */ +#define GLUSTERFS_DURABLE_OP "trusted.glusterfs.durable-op" + +/* key for version exchange b/w bitrot stub and changelog */ +#define GLUSTERFS_VERSION_XCHG_KEY "glusterfs.version.xchg" + +#define GLUSTERFS_INTERNAL_FOP_KEY "glusterfs-internal-fop" + +/* GlusterFS Internal FOP Indicator flags + * (To pass information on the context in which a paritcular + * fop is performed between translators) + * The presence of a particular flag must be treated as an + * indicator of the context, however the flag is added only in + * a scenario where there is a need for such context across translators. + * So it cannot be an absolute information on context. + */ +#define GF_INTERNAL_CTX_KEY "glusterfs.internal-ctx" + +/* + * Always append entries to end of the enum, do not delete entries. + * Currently dict_set_flag allows to set up to 256 flag, if the enum + * needs to grow beyond this dict_set_flag has to be changed accordingly + */ +enum gf_internal_fop_indicator { + GF_DHT_HEAL_DIR /* Index 0 in bit array*/ +}; + +/* Todo: + * Add GF_FOP_LINK_FILE 0x2ULL + * address GLUSTERFS_MARKER_DONT_ACCOUNT_KEY and + * GLUSTERFS_INTERNAL_FOP_KEY with this flag + */ + +#define DHT_CHANGELOG_RENAME_OP_KEY "changelog.rename-op" + +#define GLUSTERFS_WRITE_IS_APPEND "glusterfs.write-is-append" +#define GLUSTERFS_WRITE_UPDATE_ATOMIC "glusterfs.write-update-atomic" +#define GLUSTERFS_OPEN_FD_COUNT "glusterfs.open-fd-count" +#define GLUSTERFS_ACTIVE_FD_COUNT "glusterfs.open-active-fd-count" +#define GLUSTERFS_INODELK_COUNT "glusterfs.inodelk-count" +#define GLUSTERFS_ENTRYLK_COUNT "glusterfs.entrylk-count" +#define GLUSTERFS_POSIXLK_COUNT "glusterfs.posixlk-count" +#define GLUSTERFS_PARENT_ENTRYLK "glusterfs.parent-entrylk" +#define GLUSTERFS_INODELK_DOM_COUNT "glusterfs.inodelk-dom-count" +#define GFID_TO_PATH_KEY "glusterfs.gfid2path" +#define GF_XATTR_STIME_PATTERN "trusted.glusterfs.*.stime" +#define GF_XATTR_XTIME_PATTERN "trusted.glusterfs.*.xtime" +#define GF_XATTR_TRIGGER_SYNC "glusterfs.geo-rep.trigger-sync" + +/* quota xattrs */ +#define QUOTA_SIZE_KEY "trusted.glusterfs.quota.size" +#define QUOTA_LIMIT_KEY "trusted.glusterfs.quota.limit-set" +#define QUOTA_LIMIT_OBJECTS_KEY "trusted.glusterfs.quota.limit-objects" +#define VIRTUAL_QUOTA_XATTR_CLEANUP_KEY "glusterfs.quota-xattr-cleanup" +#define QUOTA_READ_ONLY_KEY "trusted.glusterfs.quota.read-only" + +/* afr related */ +#define AFR_XATTR_PREFIX "trusted.afr" + +/* Index xlator related */ +#define GF_XATTROP_INDEX_GFID "glusterfs.xattrop_index_gfid" +#define GF_XATTROP_ENTRY_CHANGES_GFID "glusterfs.xattrop_entry_changes_gfid" +#define GF_XATTROP_INDEX_COUNT "glusterfs.xattrop_index_count" +#define GF_XATTROP_DIRTY_GFID "glusterfs.xattrop_dirty_gfid" +#define GF_XATTROP_DIRTY_COUNT "glusterfs.xattrop_dirty_count" +#define GF_XATTROP_ENTRY_IN_KEY "glusterfs.xattrop-entry-create" +#define GF_XATTROP_ENTRY_OUT_KEY "glusterfs.xattrop-entry-delete" +#define GF_INDEX_IA_TYPE_GET_REQ "glusterfs.index-ia-type-get-req" +#define GF_INDEX_IA_TYPE_GET_RSP "glusterfs.index-ia-type-get-rsp" + +#define GF_HEAL_INFO "glusterfs.heal-info" +#define GF_AFR_HEAL_SBRAIN "glusterfs.heal-sbrain" +#define GF_AFR_SBRAIN_STATUS "replica.split-brain-status" +#define GF_AFR_SBRAIN_CHOICE "replica.split-brain-choice" +#define GF_AFR_SPB_CHOICE_TIMEOUT "replica.split-brain-choice-timeout" +#define GF_AFR_SBRAIN_RESOLVE "replica.split-brain-heal-finalize" +#define GF_AFR_ADD_BRICK "trusted.add-brick" +#define GF_AFR_REPLACE_BRICK "trusted.replace-brick" +#define GF_AFR_DIRTY "trusted.afr.dirty" +#define GF_XATTROP_ENTRY_OUT "glusterfs.xattrop-entry-delete" +#define GF_XATTROP_PURGE_INDEX "glusterfs.xattrop-purge-index" + +#define GF_GFIDLESS_LOOKUP "gfidless-lookup" +/* replace-brick and pump related internal xattrs */ +#define RB_PUMP_CMD_START "glusterfs.pump.start" +#define RB_PUMP_CMD_PAUSE "glusterfs.pump.pause" +#define RB_PUMP_CMD_COMMIT "glusterfs.pump.commit" +#define RB_PUMP_CMD_ABORT "glusterfs.pump.abort" +#define RB_PUMP_CMD_STATUS "glusterfs.pump.status" + +#define GLUSTERFS_MARKER_DONT_ACCOUNT_KEY "glusters.marker.dont-account" +#define GLUSTERFS_RDMA_INLINE_THRESHOLD (2048) +#define GLUSTERFS_RDMA_MAX_HEADER_SIZE \ + (228) /* (sizeof (rdma_header_t) \ + + RDMA_MAX_SEGMENTS \ + * sizeof (rdma_read_chunk_t)) \ + */ + +#define GLUSTERFS_RPC_REPLY_SIZE 24 + +#define STARTING_EVENT_THREADS 2 + +#define DEFAULT_VAR_RUN_DIRECTORY DATADIR "/run/gluster" +#define DEFAULT_GLUSTERFSD_MISC_DIRETORY DATADIR "/lib/misc/glusterfsd" +#ifdef GF_LINUX_HOST_OS +#define GLUSTERD_DEFAULT_WORKDIR DATADIR "/lib/glusterd" +#else +#define GLUSTERD_DEFAULT_WORKDIR DATADIR "/db/glusterd" +#endif +#define GF_REPLICATE_TRASH_DIR ".landfill" + +/* GlusterFS's maximum supported Auxiliary GIDs */ +#define GF_MAX_AUX_GROUPS 65535 + +#define GF_UUID_BUF_SIZE 37 /* UUID_CANONICAL_FORM_LEN + NULL */ +#define GF_UUID_BNAME_BUF_SIZE (320) /* (64 + 256) */ + +#define GF_REBALANCE_TID_KEY "rebalance-id" +#define GF_REMOVE_BRICK_TID_KEY "remove-brick-id" +#define GF_TIER_TID_KEY "tier-id" +#define GF_TIER_ENABLED "tier-enabled" + +#define UUID_CANONICAL_FORM_LEN 36 + +/* Adding this here instead of any glusterd*.h files as it is also required by + * cli + */ +#define DEFAULT_GLUSTERD_SOCKFILE DATADIR "/run/glusterd.socket" + +/* features/marker-quota also needs to have knowledge of link-files so as to + * exclude them from accounting. + */ +#define DHT_LINKFILE_MODE (S_ISVTX) + +#define IS_DHT_LINKFILE_MODE(iabuf) \ + ((st_mode_from_ia((iabuf)->ia_prot, (iabuf)->ia_type) & ~S_IFMT) == \ + DHT_LINKFILE_MODE) +#define DHT_LINKFILE_STR "linkto" +#define DHT_COMMITHASH_STR "commithash" + +#define DHT_SKIP_NON_LINKTO_UNLINK "unlink-only-if-dht-linkto-file" +#define TIER_SKIP_NON_LINKTO_UNLINK "unlink-only-if-tier-linkto-file" +#define TIER_LINKFILE_GFID "tier-linkfile-gfid" +#define DHT_SKIP_OPEN_FD_UNLINK "dont-unlink-for-open-fd" +#define DHT_IATT_IN_XDATA_KEY "dht-get-iatt-in-xattr" +#define DHT_MODE_IN_XDATA_KEY "dht-get-mode-in-xattr" +#define GET_LINK_COUNT "get-link-count" +#define GF_GET_SIZE "get-size" +#define GF_PRESTAT "virt-gf-prestat" +#define GF_POSTSTAT "virt-gf-poststat" + +/*CTR and Marker requires inode dentry link count from posix*/ +#define GF_RESPONSE_LINK_COUNT_XDATA "gf_response_link_count" +#define GF_REQUEST_LINK_COUNT_XDATA "gf_request_link_count" + +#define CTR_ATTACH_TIER_LOOKUP "ctr_attach_tier_lookup" + +#define CLIENT_CMD_CONNECT "trusted.glusterfs.client-connect" +#define CLIENT_CMD_DISCONNECT "trusted.glusterfs.client-disconnect" + +#define GF_LOG_LRU_BUFSIZE_DEFAULT 5 +#define GF_LOG_LRU_BUFSIZE_MIN 0 +#define GF_LOG_LRU_BUFSIZE_MAX 20 +#define GF_LOG_LRU_BUFSIZE_MIN_STR "0" +#define GF_LOG_LRU_BUFSIZE_MAX_STR "20" + +#define GF_LOG_FLUSH_TIMEOUT_DEFAULT 120 +#define GF_LOG_FLUSH_TIMEOUT_MIN 30 +#define GF_LOG_FLUSH_TIMEOUT_MAX 300 +#define GF_LOG_FLUSH_TIMEOUT_MIN_STR "30" +#define GF_LOG_FLUSH_TIMEOUT_MAX_STR "300" +#define GF_LOG_LOCALTIME_DEFAULT 0 + +#define GF_NETWORK_TIMEOUT 42 + +#define GF_BACKTRACE_LEN 4096 +#define GF_BACKTRACE_FRAME_COUNT 7 + +#define GF_LK_ADVISORY 0 /* maps to GLFS_LK_ADVISORY from libgfapi*/ +#define GF_LK_MANDATORY 1 /* maps to GLFS_LK_MANDATORY from libgfapi*/ +#define GF_LOCK_MODE "glusterfs.lk.lkmode" + +#define GF_CHECK_XATTR_KEY_AND_GOTO(key, cmpkey, errval, lbl) \ + do { \ + if (key && strcmp(key, cmpkey) == 0) { \ + errval = -EINVAL; \ + goto lbl; \ + } \ + } while (0) + +#define GF_CS_OBJECT_SIZE "trusted.glusterfs.cs.object_size" + +#define GF_CS_OBJECT_UPLOAD_COMPLETE "trusted.glusterfs.csou.complete" +#define GF_CS_OBJECT_REMOTE "trusted.glusterfs.cs.remote" +#define GF_CS_OBJECT_DOWNLOADING "trusted.glusterfs.cs.downloading" +#define GF_CS_OBJECT_DOWNLOADED "trusted.glusterfs.cs.downloaded" +#define GF_CS_OBJECT_STATUS "trusted.glusterfs.cs.status" +#define GF_CS_OBJECT_REPAIR "trusted.glusterfs.cs.repair" + +typedef enum { + GF_CS_LOCAL = 1, + GF_CS_REMOTE = 2, + GF_CS_REPAIR = 4, + GF_CS_DOWNLOADING = 8, + GF_CS_ERROR = 16, +} gf_cs_obj_state; + +typedef enum { + GF_FOP_PRI_UNSPEC = -1, /* Priority not specified */ + GF_FOP_PRI_HI = 0, /* low latency */ + GF_FOP_PRI_NORMAL, /* normal */ + GF_FOP_PRI_LO, /* bulk */ + GF_FOP_PRI_LEAST, /* least */ + GF_FOP_PRI_MAX, /* Highest */ +} gf_fop_pri_t; + +typedef enum { + /* The 'component' (xlator / option) is not yet setting the flag */ + GF_UNCLASSIFIED = 0, + /* The 'component' is experimental, should not be recommened + in production mode */ + GF_EXPERIMENTAL, + /* The 'component' is tech preview, ie, it is 'mostly' working as + expected, but can have some of the corner cases, which is not + handled. */ + GF_TECH_PREVIEW, + /* The 'component' is good to run. Has good enough test and + documentation coverage. */ + GF_MAINTAINED, + /* The component is: + - no more a focus + - no more solving a valid use case + - no more maintained, no volunteers to maintain + - there is 'maintained' or 'tech-preview' feature, + which does the same thing, better. + */ + GF_DEPRECATED, + /* The 'component' is no more 'built'. */ + GF_OBSOLETE, + /* The 'component' exist for Documentation purposes. + No real usecase */ + GF_DOCUMENT_PURPOSE, +} gf_category_t; + +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) + return "UNSPEC"; + + if (pri >= GF_FOP_PRI_MAX) + return "INVALID"; + + return FOP_PRI_STRINGS[pri]; +} + +const char * +fop_enum_to_pri_string(glusterfs_fop_t fop); + +#define GF_SET_IF_NOT_PRESENT 0x1 /* default behaviour */ +#define GF_SET_OVERWRITE 0x2 /* Overwrite with the buf given */ +#define GF_SET_DIR_ONLY 0x4 +#define GF_SET_EPOCH_TIME 0x8 /* used by afr dir lookup selfheal */ +#define GF_AUXILLARY_PARGFID 0xd /* RIO dummy parent gfid */ + +/* key value which quick read uses to get small files in lookup cbk */ +#define GF_CONTENT_KEY "glusterfs.content" + +struct _xlator_cmdline_option { + struct list_head cmd_args; + char *volume; + char *key; + char *value; +}; +typedef struct _xlator_cmdline_option xlator_cmdline_option_t; + +struct _server_cmdline { + struct list_head list; + char *volfile_server; + char *transport; + int port; +}; +typedef struct _server_cmdline server_cmdline_t; + +#define GF_OPTION_ENABLE _gf_true +#define GF_OPTION_DISABLE _gf_false +#define GF_OPTION_DEFERRED 2 + +struct _cmd_args { + /* basic options */ + char *volfile_server; + server_cmdline_t *curr_server; + /* List of backup volfile servers, including original */ + struct list_head volfile_servers; + char *volfile; + char *log_server; + gf_loglevel_t log_level; + char *log_file; + char *log_ident; + gf_log_logger_t logger; + gf_log_format_t log_format; + uint32_t log_buf_size; + uint32_t log_flush_timeout; + int32_t max_connect_attempts; + char *print_exports; + char *print_netgroups; + int print_xlatordir; + int print_statedumpdir; + int print_logdir; + int print_libexecdir; + /* advanced options */ + uint32_t volfile_server_port; + char *volfile_server_transport; + uint32_t log_server_port; + char *pid_file; + char *sock_file; + int no_daemon_mode; + char *run_id; + int debug_mode; + int read_only; + int acl; + int selinux; + int capability; + int enable_ino32; + int worm; + int mac_compat; + int fopen_keep_cache; + int gid_timeout; + char gid_timeout_set; + int aux_gfid_mount; + + /* need a process wide timer-wheel? */ + int global_timer_wheel; + + /* list of xlator_option_t */ + struct list_head xlator_options; + + /* fuse options */ + int fuse_direct_io_mode; + char *use_readdirp; + int no_root_squash; + int volfile_check; + double fuse_entry_timeout; + double fuse_negative_timeout; + double fuse_attribute_timeout; + char *volume_name; + int fuse_nodev; + int fuse_nosuid; + char *dump_fuse; + pid_t client_pid; + int client_pid_set; + unsigned uid_map_root; + int background_qlen; + int congestion_threshold; + char *fuse_mountopts; + int mem_acct; + int resolve_gids; + + /* key args */ + char *mount_point; + char *volfile_id; + + /* required for portmap */ + int brick_port; + char *brick_name; + int brick_port2; + + /* Should management connections use SSL? */ + int secure_mgmt; + + /* Linux-only OOM killer adjustment */ +#ifdef GF_LINUX_HOST_OS + char *oom_score_adj; +#endif + + /* Run this process with valgrind? Might want to prevent calling + * functions that prevent valgrind from working correctly, like + * dlclose(). */ + int valgrind; + int localtime_logging; + + /* For the subdir mount */ + char *subdir_mount; + + char *process_name; + char *event_history; + int thin_client; + uint32_t reader_thread_count; + + /* FUSE writeback cache support */ + int kernel_writeback_cache; + uint32_t attr_times_granularity; + + int fuse_flush_handle_interrupt; +}; +typedef struct _cmd_args cmd_args_t; + +struct _glusterfs_graph { + struct list_head list; + char graph_uuid[128]; + struct timeval dob; + void *first; + void *top; /* selected by -n */ + uint32_t leaf_count; + int xl_count; + int id; /* Used in logging */ + int used; /* Should be set when fuse gets + first CHILD_UP */ + uint32_t volfile_checksum; +}; +typedef struct _glusterfs_graph glusterfs_graph_t; + +typedef int32_t (*glusterfsd_mgmt_event_notify_fn_t)(int32_t event, void *data, + ...); + +typedef enum { + MGMT_SSL_NEVER = 0, + MGMT_SSL_COPY_IO, + MGMT_SSL_ALWAYS +} mgmt_ssl_t; + +struct tvec_base; + +/* reference counting for the global (per ctx) timer-wheel */ +struct gf_ctx_tw { + GF_REF_DECL; + struct tvec_base *timer_wheel; /* global timer-wheel instance */ +}; + +struct _glusterfs_ctx { + cmd_args_t cmd_args; + char *process_uuid; + FILE *pidfp; + char fin; + void *timer; + void *ib; + struct call_pool *pool; + void *event_pool; + void *iobuf_pool; + void *logbuf_pool; + gf_lock_t lock; + size_t page_size; + + /* one per volfile parse */ + struct list_head graphs; + + /* the latest graph in use */ + glusterfs_graph_t *active; + + /* fuse or nfs (but not protocol/server) */ + void *master; + + /* xlator implementing MOPs for centralized logging, volfile server */ + void *mgmt; + + /* listener of the commands from glusterd */ + void *listener; + + /* toggle switch for latency measurement */ + unsigned char measure_latency; + pthread_t sigwaiter; + char *cmdlinestr; + struct mem_pool *stub_mem_pool; + unsigned char cleanup_started; + int graph_id; /* Incremented per graph, value should + indicate how many times the graph has + got changed */ + pid_t mnt_pid; /* pid of the mount agent */ + int process_mode; /*mode in which process is runninng*/ + struct syncenv *env; /* The env pointer to the synctasks */ + + struct list_head mempool_list; /* used to keep a global list of + mempools, used to log details of + mempool in statedump */ + char *statedump_path; + + struct mem_pool *dict_pool; + struct mem_pool *dict_pair_pool; + struct mem_pool *dict_data_pool; + + glusterfsd_mgmt_event_notify_fn_t notify; /* Used for xlators to make + call to fsd-mgmt */ + gf_log_handle_t log; /* all logging related variables */ + + int mem_acct_enable; + + int daemon_pipe[2]; + + struct clienttable *clienttable; + + /* + * Should management connections use SSL? This is the only place we + * can put it where both daemon-startup and socket code will see it. + * + * Why is it an int? Because we're included before common-utils.h, + * which defines gf_boolean_t (what we really want). It doesn't make + * any sense, but it's not worth turning the codebase upside-down to + * fix it. Thus, an int. + */ + int secure_mgmt; + + /* The option is use to set cert_depth while management connection + use SSL + */ + int ssl_cert_depth; + + /* + * Should *our* server/inbound connections use SSL? This is only true + * if we're glusterd and secure_mgmt is set, or if we're glusterfsd + * and SSL is set on the I/O path. It should never be set e.g. for + * NFS. + */ + mgmt_ssl_t secure_srvr; + /* Buffer to 'save' backtrace even under OOM-kill like situations*/ + char btbuf[GF_BACKTRACE_LEN]; + + pthread_mutex_t notify_lock; + pthread_mutex_t cleanup_lock; + pthread_cond_t notify_cond; + int notifying; + + struct gf_ctx_tw *tw; /* refcounted timer_wheel */ + + gf_lock_t volfile_lock; + + /* configuration related elements, which gets changed + from global xlator */ + struct { + char *metrics_dumppath; + } config; + + struct { + gf_atomic_t max_dict_pairs; + gf_atomic_t total_pairs_used; + gf_atomic_t total_dicts_used; + } stats; + + struct list_head volfile_list; +}; +typedef struct _glusterfs_ctx glusterfs_ctx_t; + +typedef struct { + char volfile_checksum[SHA256_DIGEST_LENGTH]; + char vol_id[NAME_MAX + 1]; + struct list_head volfile_list; + +} gf_volfile_t; + +glusterfs_ctx_t * +glusterfs_ctx_new(void); + +struct gf_flock { + short l_type; + short l_whence; + off_t l_start; + off_t l_len; + pid_t l_pid; + gf_lkowner_t l_owner; +}; + +typedef struct lock_migration_info { + struct list_head list; + struct gf_flock flock; + char *client_uid; + uint32_t lk_flags; +} lock_migration_info_t; + +#define GF_MUST_CHECK __attribute__((warn_unused_result)) +/* + * Some macros (e.g. ALLOC_OR_GOTO) set variables in function scope, but the + * calling function might not only declare the variable to keep the macro happy + * and not use it otherwise. In such cases, the following can be used to + * suppress the "set but not used" warning that would otherwise occur. + */ +#define GF_UNUSED __attribute__((unused)) + +/* + * If present, this has the following effects: + * + * glusterd enables privileged commands over TCP + * + * all code enables SSL for outbound connections to management port + * + * glusterd enables SSL for inbound connections + * + * Servers and clients enable/disable SSL among themselves by other means. + * Making secure management connections conditional on a file is a bit of a + * hack, but we don't have any other place for such global settings across + * all of the affected components. Making it a compile-time option would + * reduce functionality, both for users and for testing (which can now be + * done using secure connections for all tests without change elsewhere). + * + */ +#define SECURE_ACCESS_FILE GLUSTERD_DEFAULT_WORKDIR "/secure-access" + +int +glusterfs_graph_prepare(glusterfs_graph_t *graph, glusterfs_ctx_t *ctx, + char *volume_name); +int +glusterfs_graph_destroy_residual(glusterfs_graph_t *graph); +int +glusterfs_graph_deactivate(glusterfs_graph_t *graph); +int +glusterfs_graph_destroy(glusterfs_graph_t *graph); +int +glusterfs_get_leaf_count(glusterfs_graph_t *graph); +int +glusterfs_graph_activate(glusterfs_graph_t *graph, glusterfs_ctx_t *ctx); +glusterfs_graph_t * +glusterfs_graph_construct(FILE *fp); +int +glusterfs_graph_init(glusterfs_graph_t *graph); +glusterfs_graph_t * +glusterfs_graph_new(void); +int +glusterfs_graph_reconfigure(glusterfs_graph_t *oldgraph, + glusterfs_graph_t *newgraph); +int +glusterfs_graph_attach(glusterfs_graph_t *orig_graph, char *path, + glusterfs_graph_t **newgraph); +int +glusterfs_graph_parent_up(glusterfs_graph_t *graph); + +void +gf_free_mig_locks(lock_migration_info_t *locks); + +int +glusterfs_read_secure_access_file(void); +#endif /* _GLUSTERFS_H */ diff --git a/libglusterfs/src/glusterfs/graph-utils.h b/libglusterfs/src/glusterfs/graph-utils.h new file mode 100644 index 00000000000..c0e87268c5c --- /dev/null +++ b/libglusterfs/src/glusterfs/graph-utils.h @@ -0,0 +1,24 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _GRAPH_H_ +#define _GRAPH_H_ + +int +glusterfs_graph_print_file(FILE *file, glusterfs_graph_t *graph); + +char * +glusterfs_graph_print_buf(glusterfs_graph_t *graph); + +int +glusterfs_xlator_link(xlator_t *pxl, xlator_t *cxl); +void +glusterfs_graph_set_first(glusterfs_graph_t *graph, xlator_t *xl); +#endif diff --git a/libglusterfs/src/glusterfs/hashfn.h b/libglusterfs/src/glusterfs/hashfn.h new file mode 100644 index 00000000000..a4cb33f072a --- /dev/null +++ b/libglusterfs/src/glusterfs/hashfn.h @@ -0,0 +1,25 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef __HASHFN_H__ +#define __HASHFN_H__ + +#include <sys/types.h> +#include <stdint.h> + +uint32_t +SuperFastHash(const char *data, int32_t len); + +uint32_t +gf_dm_hashfn(const char *msg, int len); + +uint32_t +ReallySimpleHash(char *path, int len); +#endif /* __HASHFN_H__ */ diff --git a/libglusterfs/src/glusterfs/iatt.h b/libglusterfs/src/glusterfs/iatt.h new file mode 100644 index 00000000000..339c84ccc45 --- /dev/null +++ b/libglusterfs/src/glusterfs/iatt.h @@ -0,0 +1,460 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _IATT_H +#define _IATT_H + +#if defined(GF_LINUX_HOST_OS) +#include <sys/sysmacros.h> /* for makedev(3), major(3), minor(3) */ +#endif +#include <sys/types.h> +#include <sys/stat.h> /* for iatt <--> stat conversions */ +#include <unistd.h> + +#include "glusterfs/compat.h" +#include "glusterfs/compat-uuid.h" + +typedef enum { + IA_INVAL = 0, + IA_IFREG, + IA_IFDIR, + IA_IFLNK, + IA_IFBLK, + IA_IFCHR, + IA_IFIFO, + IA_IFSOCK +} ia_type_t; + +typedef struct { + uint8_t suid : 1; + uint8_t sgid : 1; + uint8_t sticky : 1; + struct { + uint8_t read : 1; + uint8_t write : 1; + uint8_t exec : 1; + } owner, group, other; +} ia_prot_t; + +struct iatt { + uint64_t ia_flags; + uint64_t ia_ino; /* inode number */ + uint64_t ia_dev; /* backing device ID */ + uint64_t ia_rdev; /* device ID (if special file) */ + uint64_t ia_size; /* file size in bytes */ + uint32_t ia_nlink; /* Link count */ + uint32_t ia_uid; /* user ID of owner */ + uint32_t ia_gid; /* group ID of owner */ + uint32_t ia_blksize; /* blocksize for filesystem I/O */ + uint64_t ia_blocks; /* number of 512B blocks allocated */ + int64_t ia_atime; /* last access time */ + int64_t ia_mtime; /* last modification time */ + int64_t ia_ctime; /* last status change time */ + int64_t ia_btime; /* creation time. Fill using statx */ + uint32_t ia_atime_nsec; + uint32_t ia_mtime_nsec; + uint32_t ia_ctime_nsec; + uint32_t ia_btime_nsec; + uint64_t ia_attributes; /* chattr related:compressed, immutable, + * append only, encrypted etc.*/ + uint64_t ia_attributes_mask; /* Mask for the attributes */ + + uuid_t ia_gfid; + ia_type_t ia_type; /* type of file */ + ia_prot_t ia_prot; /* protection */ +}; + +struct old_iatt { + uint64_t ia_ino; /* inode number */ + uuid_t ia_gfid; + uint64_t ia_dev; /* backing device ID */ + ia_type_t ia_type; /* type of file */ + ia_prot_t ia_prot; /* protection */ + uint32_t ia_nlink; /* Link count */ + uint32_t ia_uid; /* user ID of owner */ + uint32_t ia_gid; /* group ID of owner */ + uint64_t ia_rdev; /* device ID (if special file) */ + uint64_t ia_size; /* file size in bytes */ + uint32_t ia_blksize; /* blocksize for filesystem I/O */ + uint64_t ia_blocks; /* number of 512B blocks allocated */ + uint32_t ia_atime; /* last access time */ + uint32_t ia_atime_nsec; + uint32_t ia_mtime; /* last modification time */ + uint32_t ia_mtime_nsec; + uint32_t ia_ctime; /* last status change time */ + uint32_t ia_ctime_nsec; +}; + +/* 64-bit mask for valid members in struct iatt. */ +#define IATT_TYPE 0x0000000000000001U +#define IATT_MODE 0x0000000000000002U +#define IATT_NLINK 0x0000000000000004U +#define IATT_UID 0x0000000000000008U +#define IATT_GID 0x0000000000000010U +#define IATT_ATIME 0x0000000000000020U +#define IATT_MTIME 0x0000000000000040U +#define IATT_CTIME 0x0000000000000080U +#define IATT_INO 0x0000000000000100U +#define IATT_SIZE 0x0000000000000200U +#define IATT_BLOCKS 0x0000000000000400U +#define IATT_BTIME 0x0000000000000800U +#define IATT_GFID 0x0000000000001000U + +/* Macros for checking validity of struct iatt members.*/ +#define IATT_TYPE_VALID(iaflags) (iaflags & IATT_TYPE) +#define IATT_MODE_VALID(iaflags) (iaflags & IATT_MODE) +#define IATT_NLINK_VALID(iaflags) (iaflags & IATT_NLINK) +#define IATT_UID_VALID(iaflags) (iaflags & IATT_UID) +#define IATT_GID_VALID(iaflags) (iaflags & IATT_GID) +#define IATT_ATIME_VALID(iaflags) (iaflags & IATT_ATIME) +#define IATT_MTIME_VALID(iaflags) (iaflags & IATT_MTIME) +#define IATT_CTIME_VALID(iaflags) (iaflags & IATT_CTIME) +#define IATT_INO_VALID(iaflags) (iaflags & IATT_INO) +#define IATT_SIZE_VALID(iaflags) (iaflags & IATT_SIZE) +#define IATT_BLOCKS_VALID(iaflags) (iaflags & IATT_BLOCKS) +#define IATT_BTIME_VALID(iaflags) (iaflags & IATT_BTIME) +#define IATT_GFID_VALID(iaflags) (iaflags & IATT_GFID) + +#define IA_ISREG(t) (t == IA_IFREG) +#define IA_ISDIR(t) (t == IA_IFDIR) +#define IA_ISLNK(t) (t == IA_IFLNK) +#define IA_ISBLK(t) (t == IA_IFBLK) +#define IA_ISCHR(t) (t == IA_IFCHR) +#define IA_ISFIFO(t) (t == IA_IFIFO) +#define IA_ISSOCK(t) (t == IA_IFSOCK) +#define IA_ISINVAL(t) (t == IA_INVAL) + +#define IA_PROT_RUSR(prot) ((prot).owner.read == 1) +#define IA_PROT_WUSR(prot) ((prot).owner.write == 1) +#define IA_PROT_XUSR(prot) ((prot).owner.exec == 1) + +#define IA_PROT_RGRP(prot) ((prot).group.read == 1) +#define IA_PROT_WGRP(prot) ((prot).group.write == 1) +#define IA_PROT_XGRP(prot) ((prot).group.exec == 1) + +#define IA_PROT_ROTH(prot) ((prot).other.read == 1) +#define IA_PROT_WOTH(prot) ((prot).other.write == 1) +#define IA_PROT_XOTH(prot) ((prot).other.exec == 1) + +#define IA_PROT_SUID(prot) ((prot).suid == 1) +#define IA_PROT_SGID(prot) ((prot).sgid == 1) +#define IA_PROT_STCKY(prot) ((prot).sticky == 1) + +#define IA_FILE_OR_DIR(t) (IA_ISREG(t) || IA_ISDIR(t)) + +static inline uint32_t +ia_major(uint64_t ia_dev) +{ + return (uint32_t)(ia_dev >> 32); +} + +static inline uint32_t +ia_minor(uint64_t ia_dev) +{ + return (uint32_t)(ia_dev & 0xffffffff); +} + +static inline uint64_t +ia_makedev(uint32_t ia_maj, uint32_t ia_min) +{ + return ((((uint64_t)ia_maj) << 32) | ia_min); +} + +static inline ia_prot_t +ia_prot_from_st_mode(mode_t mode) +{ + ia_prot_t ia_prot = { + 0, + }; + + if (mode & S_ISUID) + ia_prot.suid = 1; + if (mode & S_ISGID) + ia_prot.sgid = 1; + if (mode & S_ISVTX) + ia_prot.sticky = 1; + + if (mode & S_IRUSR) + ia_prot.owner.read = 1; + if (mode & S_IWUSR) + ia_prot.owner.write = 1; + if (mode & S_IXUSR) + ia_prot.owner.exec = 1; + + if (mode & S_IRGRP) + ia_prot.group.read = 1; + if (mode & S_IWGRP) + ia_prot.group.write = 1; + if (mode & S_IXGRP) + ia_prot.group.exec = 1; + + if (mode & S_IROTH) + ia_prot.other.read = 1; + if (mode & S_IWOTH) + ia_prot.other.write = 1; + if (mode & S_IXOTH) + ia_prot.other.exec = 1; + + return ia_prot; +} + +static inline ia_type_t +ia_type_from_st_mode(mode_t mode) +{ + ia_type_t type = IA_INVAL; + + if (S_ISREG(mode)) + type = IA_IFREG; + if (S_ISDIR(mode)) + type = IA_IFDIR; + if (S_ISLNK(mode)) + type = IA_IFLNK; + if (S_ISBLK(mode)) + type = IA_IFBLK; + if (S_ISCHR(mode)) + type = IA_IFCHR; + if (S_ISFIFO(mode)) + type = IA_IFIFO; + if (S_ISSOCK(mode)) + type = IA_IFSOCK; + + return type; +} + +static inline uint32_t +st_mode_prot_from_ia(ia_prot_t prot) +{ + uint32_t prot_bit = 0; + + if (prot.suid) + prot_bit |= S_ISUID; + if (prot.sgid) + prot_bit |= S_ISGID; + if (prot.sticky) + prot_bit |= S_ISVTX; + + if (prot.owner.read) + prot_bit |= S_IRUSR; + if (prot.owner.write) + prot_bit |= S_IWUSR; + if (prot.owner.exec) + prot_bit |= S_IXUSR; + + if (prot.group.read) + prot_bit |= S_IRGRP; + if (prot.group.write) + prot_bit |= S_IWGRP; + if (prot.group.exec) + prot_bit |= S_IXGRP; + + if (prot.other.read) + prot_bit |= S_IROTH; + if (prot.other.write) + prot_bit |= S_IWOTH; + if (prot.other.exec) + prot_bit |= S_IXOTH; + + return prot_bit; +} + +static inline mode_t +st_mode_from_ia(ia_prot_t prot, ia_type_t type) +{ + mode_t st_mode = 0; + uint32_t type_bit = 0; + uint32_t prot_bit = 0; + + switch (type) { + case IA_IFREG: + type_bit = S_IFREG; + break; + case IA_IFDIR: + type_bit = S_IFDIR; + break; + case IA_IFLNK: + type_bit = S_IFLNK; + break; + case IA_IFBLK: + type_bit = S_IFBLK; + break; + case IA_IFCHR: + type_bit = S_IFCHR; + break; + case IA_IFIFO: + type_bit = S_IFIFO; + break; + case IA_IFSOCK: + type_bit = S_IFSOCK; + break; + case IA_INVAL: + break; + } + + prot_bit = st_mode_prot_from_ia(prot); + + st_mode = (type_bit | prot_bit); + + return st_mode; +} + +static inline int +iatt_from_stat(struct iatt *iatt, struct stat *stat) +{ + iatt->ia_dev = stat->st_dev; + iatt->ia_ino = stat->st_ino; + + iatt->ia_type = ia_type_from_st_mode(stat->st_mode); + iatt->ia_prot = ia_prot_from_st_mode(stat->st_mode); + + iatt->ia_nlink = stat->st_nlink; + iatt->ia_uid = stat->st_uid; + iatt->ia_gid = stat->st_gid; + + iatt->ia_rdev = ia_makedev(major(stat->st_rdev), minor(stat->st_rdev)); + + iatt->ia_size = stat->st_size; + iatt->ia_blksize = stat->st_blksize; + iatt->ia_blocks = stat->st_blocks; + + /* There is a possibility that the backend FS (like XFS) can + allocate blocks beyond EOF for better performance reasons, which + results in 'st_blocks' with higher values than what is consumed by + the file descriptor. This would break few logic inside GlusterFS, + like quota behavior etc, thus we need the exact number of blocks + which are consumed by the file to the higher layers inside GlusterFS. + Currently, this logic won't work for sparse files (ie, file with + holes) + */ + { + uint64_t maxblocks; + + maxblocks = (iatt->ia_size + 511) / 512; + + if (iatt->ia_blocks > maxblocks) + iatt->ia_blocks = maxblocks; + } + + iatt->ia_atime = stat->st_atime; + iatt->ia_atime_nsec = ST_ATIM_NSEC(stat); + + iatt->ia_mtime = stat->st_mtime; + iatt->ia_mtime_nsec = ST_MTIM_NSEC(stat); + + iatt->ia_ctime = stat->st_ctime; + iatt->ia_ctime_nsec = ST_CTIM_NSEC(stat); + + /* Setting IATT_INO in ia_flags is done in posix_fill_ino_from_gfid. */ + iatt->ia_flags = iatt->ia_flags | IATT_TYPE | IATT_MODE | IATT_NLINK | + IATT_UID | IATT_GID | IATT_SIZE | IATT_BLOCKS | + IATT_ATIME | IATT_MTIME | IATT_CTIME; + + return 0; +} + +static inline int +iatt_to_stat(struct iatt *iatt, struct stat *stat) +{ + stat->st_dev = iatt->ia_dev; + stat->st_ino = iatt->ia_ino; + + stat->st_mode = st_mode_from_ia(iatt->ia_prot, iatt->ia_type); + + stat->st_nlink = iatt->ia_nlink; + stat->st_uid = iatt->ia_uid; + stat->st_gid = iatt->ia_gid; + + stat->st_rdev = makedev(ia_major(iatt->ia_rdev), ia_minor(iatt->ia_rdev)); + + stat->st_size = iatt->ia_size; + stat->st_blksize = iatt->ia_blksize; + stat->st_blocks = iatt->ia_blocks; + + stat->st_atime = iatt->ia_atime; + ST_ATIM_NSEC_SET(stat, iatt->ia_atime_nsec); + + stat->st_mtime = iatt->ia_mtime; + ST_MTIM_NSEC_SET(stat, iatt->ia_mtime_nsec); + + stat->st_ctime = iatt->ia_ctime; + ST_CTIM_NSEC_SET(stat, iatt->ia_ctime_nsec); + + return 0; +} + +static inline void +oldiatt_from_iatt(struct old_iatt *o_iatt, struct iatt *c_iatt) +{ + o_iatt->ia_dev = c_iatt->ia_dev; + o_iatt->ia_ino = c_iatt->ia_ino; + o_iatt->ia_type = c_iatt->ia_type; + o_iatt->ia_prot = c_iatt->ia_prot; + o_iatt->ia_nlink = c_iatt->ia_nlink; + o_iatt->ia_uid = c_iatt->ia_uid; + o_iatt->ia_gid = c_iatt->ia_gid; + o_iatt->ia_rdev = c_iatt->ia_rdev; + o_iatt->ia_size = c_iatt->ia_size; + o_iatt->ia_blksize = c_iatt->ia_blksize; + o_iatt->ia_blocks = c_iatt->ia_blocks; + o_iatt->ia_atime = c_iatt->ia_atime; + o_iatt->ia_atime_nsec = c_iatt->ia_atime_nsec; + o_iatt->ia_mtime = c_iatt->ia_mtime; + o_iatt->ia_mtime_nsec = c_iatt->ia_mtime_nsec; + o_iatt->ia_ctime = c_iatt->ia_ctime; + o_iatt->ia_ctime_nsec = c_iatt->ia_ctime_nsec; + + gf_uuid_copy(o_iatt->ia_gfid, c_iatt->ia_gfid); + + return; +} + +static inline void +iatt_from_oldiatt(struct iatt *c_iatt, struct old_iatt *o_iatt) +{ + c_iatt->ia_dev = o_iatt->ia_dev; + c_iatt->ia_ino = o_iatt->ia_ino; + c_iatt->ia_type = o_iatt->ia_type; + c_iatt->ia_prot = o_iatt->ia_prot; + c_iatt->ia_nlink = o_iatt->ia_nlink; + c_iatt->ia_uid = o_iatt->ia_uid; + c_iatt->ia_gid = o_iatt->ia_gid; + c_iatt->ia_rdev = o_iatt->ia_rdev; + c_iatt->ia_size = o_iatt->ia_size; + c_iatt->ia_blksize = o_iatt->ia_blksize; + c_iatt->ia_blocks = o_iatt->ia_blocks; + c_iatt->ia_atime = o_iatt->ia_atime; + c_iatt->ia_atime_nsec = o_iatt->ia_atime_nsec; + c_iatt->ia_mtime = o_iatt->ia_mtime; + c_iatt->ia_mtime_nsec = o_iatt->ia_mtime_nsec; + c_iatt->ia_ctime = o_iatt->ia_ctime; + c_iatt->ia_ctime_nsec = o_iatt->ia_ctime_nsec; + + gf_uuid_copy(c_iatt->ia_gfid, o_iatt->ia_gfid); + + c_iatt->ia_attributes = 0; + + c_iatt->ia_flags = IATT_TYPE | IATT_MODE | IATT_NLINK | IATT_INO | + IATT_UID | IATT_GID | IATT_SIZE | IATT_BLOCKS | + IATT_ATIME | IATT_MTIME | IATT_CTIME | IATT_GFID; + + return; +} + +static inline int +is_same_mode(ia_prot_t prot1, ia_prot_t prot2) +{ + int ret = 0; + + if (st_mode_prot_from_ia(prot1) != st_mode_prot_from_ia(prot2)) + ret = -1; + + return ret; +} + +#endif /* _IATT_H */ diff --git a/libglusterfs/src/glusterfs/inode.h b/libglusterfs/src/glusterfs/inode.h new file mode 100644 index 00000000000..5934373ec5b --- /dev/null +++ b/libglusterfs/src/glusterfs/inode.h @@ -0,0 +1,289 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _INODE_H +#define _INODE_H + +#include <stdint.h> +#include <sys/types.h> + +#define LOOKUP_NEEDED 1 +#define LOOKUP_NOT_NEEDED 2 + +#define DEFAULT_INODE_MEMPOOL_ENTRIES 32 * 1024 +#define INODE_PATH_FMT "<gfid:%s>" +struct _inode_table; +typedef struct _inode_table inode_table_t; + +struct _inode; +typedef struct _inode inode_t; + +struct _dentry; +typedef struct _dentry dentry_t; + +#include "glusterfs/list.h" +#include "glusterfs/iatt.h" +#include "glusterfs/compat-uuid.h" +#include "glusterfs/fd.h" + +struct _inode_table { + pthread_mutex_t lock; + size_t hashsize; /* bucket size of inode hash and dentry hash */ + char *name; /* name of the inode table, just for gf_log() */ + inode_t *root; /* root directory inode, with number 1 */ + xlator_t *xl; /* xlator to be called to do purge */ + uint32_t lru_limit; /* maximum LRU cache size */ + struct list_head *inode_hash; /* buckets for inode hash table */ + struct list_head *name_hash; /* buckets for dentry hash table */ + struct list_head active; /* list of inodes currently active (in an fop) */ + uint32_t active_size; /* count of inodes in active list */ + struct list_head lru; /* list of inodes recently used. + lru.next most recent */ + uint32_t lru_size; /* count of inodes in lru list */ + struct list_head purge; /* list of inodes to be purged soon */ + uint32_t purge_size; /* count of inodes in purge list */ + + struct mem_pool *inode_pool; /* memory pool for inodes */ + struct mem_pool *dentry_pool; /* memory pool for dentrys */ + struct mem_pool *fd_mem_pool; /* memory pool for fd_t */ + int ctxcount; /* number of slots in inode->ctx */ +}; + +struct _dentry { + struct list_head inode_list; /* list of dentries of inode */ + struct list_head hash; /* hash table pointers */ + inode_t *inode; /* inode of this directory entry */ + char *name; /* name of the directory entry */ + inode_t *parent; /* directory of the entry */ +}; + +struct _inode_ctx { + union { + uint64_t key; + xlator_t *xl_key; + }; + /* if value1 is 0, then field is not set.. */ + union { + uint64_t value1; + void *ptr1; + }; + /* if value2 is 0, then field is not set.. */ + union { + uint64_t value2; + void *ptr2; + }; + int ref; /* This is for debugging inode ref leaks, + basically helps in identifying the xlator + causing th ref leak, it is printed in + statedump */ +}; + +struct _inode { + inode_table_t *table; /* the table this inode belongs to */ + uuid_t gfid; + gf_lock_t lock; + gf_atomic_t nlookup; + uint32_t fd_count; /* Open fd count */ + uint32_t active_fd_count; /* Active open fd count */ + uint32_t ref; /* reference count on this inode */ + ia_type_t ia_type; /* what kind of file */ + struct list_head fd_list; /* list of open files on this inode */ + struct list_head dentry_list; /* list of directory entries for this inode */ + struct list_head hash; /* hash table pointers */ + struct list_head list; /* active/lru/purge */ + + struct _inode_ctx *_ctx; /* replacement for dict_t *(inode->ctx) */ +}; + +#define UUID0_STR "00000000-0000-0000-0000-000000000000" +#define GFID_STR_PFX "<gfid:" UUID0_STR ">" +#define GFID_STR_PFX_LEN (sizeof(GFID_STR_PFX) - 1) + +inode_table_t * +inode_table_new(size_t lru_limit, xlator_t *xl); + +void +inode_table_destroy_all(glusterfs_ctx_t *ctx); + +void +inode_table_destroy(inode_table_t *inode_table); + +inode_t * +inode_new(inode_table_t *table); + +inode_t * +inode_link(inode_t *inode, inode_t *parent, const char *name, + struct iatt *stbuf); + +void +inode_unlink(inode_t *inode, inode_t *parent, const char *name); + +inode_t * +inode_parent(inode_t *inode, uuid_t pargfid, const char *name); + +inode_t * +inode_ref(inode_t *inode); + +inode_t * +inode_unref(inode_t *inode); + +int +inode_lookup(inode_t *inode); + +int +inode_forget(inode_t *inode, uint64_t nlookup); + +int +inode_ref_reduce_by_n(inode_t *inode, uint64_t nref); + +int +inode_invalidate(inode_t *inode); + +int +inode_rename(inode_table_t *table, inode_t *olddir, const char *oldname, + inode_t *newdir, const char *newname, inode_t *inode, + struct iatt *stbuf); + +dentry_t * +__dentry_grep(inode_table_t *table, inode_t *parent, const char *name); + +inode_t * +inode_grep(inode_table_t *table, inode_t *parent, const char *name); + +int +inode_grep_for_gfid(inode_table_t *table, inode_t *parent, const char *name, + uuid_t gfid, ia_type_t *type); + +inode_t * +inode_find(inode_table_t *table, uuid_t gfid); + +int +inode_path(inode_t *inode, const char *name, char **bufp); + +int +__inode_path(inode_t *inode, const char *name, char **bufp); + +inode_t * +inode_from_path(inode_table_t *table, const char *path); + +inode_t * +inode_resolve(inode_table_t *table, char *path); + +/* deal with inode ctx's both values */ + +int +inode_ctx_set2(inode_t *inode, xlator_t *xlator, uint64_t *value1, + uint64_t *value2); +int +__inode_ctx_set2(inode_t *inode, xlator_t *xlator, uint64_t *value1, + uint64_t *value2); + +int +inode_ctx_get2(inode_t *inode, xlator_t *xlator, uint64_t *value1, + uint64_t *value2); +int +__inode_ctx_get2(inode_t *inode, xlator_t *xlator, uint64_t *value1, + uint64_t *value2); + +int +inode_ctx_del2(inode_t *inode, xlator_t *xlator, uint64_t *value1, + uint64_t *value2); + +int +inode_ctx_reset2(inode_t *inode, xlator_t *xlator, uint64_t *value1, + uint64_t *value2); + +/* deal with inode ctx's 1st value */ + +int +inode_ctx_set0(inode_t *inode, xlator_t *xlator, uint64_t *value1); + +int +__inode_ctx_set0(inode_t *inode, xlator_t *xlator, uint64_t *value1); + +int +inode_ctx_get0(inode_t *inode, xlator_t *xlator, uint64_t *value1); +int +__inode_ctx_get0(inode_t *inode, xlator_t *xlator, uint64_t *value1); + +int +inode_ctx_reset0(inode_t *inode, xlator_t *xlator, uint64_t *value1); + +/* deal with inode ctx's 2st value */ + +int +inode_ctx_set1(inode_t *inode, xlator_t *xlator, uint64_t *value2); + +int +__inode_ctx_set1(inode_t *inode, xlator_t *xlator, uint64_t *value2); + +int +inode_ctx_get1(inode_t *inode, xlator_t *xlator, uint64_t *value2); +int +__inode_ctx_get1(inode_t *inode, xlator_t *xlator, uint64_t *value2); + +int +inode_ctx_reset1(inode_t *inode, xlator_t *xlator, uint64_t *value2); + +static inline int +__inode_ctx_put(inode_t *inode, xlator_t *this, uint64_t v) +{ + return __inode_ctx_set0(inode, this, &v); +} + +static inline int +inode_ctx_put(inode_t *inode, xlator_t *this, uint64_t v) +{ + return inode_ctx_set0(inode, this, &v); +} + +#define __inode_ctx_set(i, x, v_p) __inode_ctx_set0(i, x, v_p) + +#define inode_ctx_set(i, x, v_p) inode_ctx_set0(i, x, v_p) + +#define inode_ctx_reset(i, x, v) inode_ctx_reset0(i, x, v) + +#define __inode_ctx_get(i, x, v) __inode_ctx_get0(i, x, v) + +#define inode_ctx_get(i, x, v) inode_ctx_get0(i, x, v) + +#define inode_ctx_del(i, x, v) inode_ctx_del2(i, x, v, 0) +#define inode_ctx_del1(i, x, v) inode_ctx_del2(i, x, 0, v) + +gf_boolean_t +__is_root_gfid(uuid_t gfid); + +void +__inode_table_set_lru_limit(inode_table_t *table, uint32_t lru_limit); + +void +inode_table_set_lru_limit(inode_table_t *table, uint32_t lru_limit); + +void +inode_ctx_merge(fd_t *fd, inode_t *inode, inode_t *linked_inode); + +int +inode_is_linked(inode_t *inode); + +void +inode_set_need_lookup(inode_t *inode, xlator_t *this); + +gf_boolean_t +inode_needs_lookup(inode_t *inode, xlator_t *this); + +int +inode_has_dentry(inode_t *inode); + +size_t +inode_ctx_size(inode_t *inode); + +void +inode_find_directory_name(inode_t *inode, const char **name); +#endif /* _INODE_H */ diff --git a/libglusterfs/src/glusterfs/iobuf.h b/libglusterfs/src/glusterfs/iobuf.h new file mode 100644 index 00000000000..6de0f13ae36 --- /dev/null +++ b/libglusterfs/src/glusterfs/iobuf.h @@ -0,0 +1,193 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _IOBUF_H_ +#define _IOBUF_H_ + +#include "glusterfs/list.h" +#include "glusterfs/common-utils.h" +#include <pthread.h> +#include <sys/mman.h> +#include <sys/uio.h> + +#define GF_VARIABLE_IOBUF_COUNT 32 + +#define GF_RDMA_DEVICE_COUNT 8 + +/* Lets try to define the new anonymous mapping + * flag, in case the system is still using the + * now deprecated MAP_ANON flag. + * + * Also, this should ideally be in a centralized/common + * header which can be used by other source files also. + */ +#ifndef MAP_ANONYMOUS +#define MAP_ANONYMOUS MAP_ANON +#endif + +#define GF_ALIGN_BUF(ptr, bound) \ + ((void *)((unsigned long)(ptr + bound - 1) & (unsigned long)(~(bound - 1)))) + +#define GF_IOBUF_ALIGN_SIZE 512 + +/* one allocatable unit for the consumers of the IOBUF API */ +/* each unit hosts @page_size bytes of memory */ +struct iobuf; + +/* one region of memory mapped from the operating system */ +/* each region MMAPs @arena_size bytes of memory */ +/* each arena hosts @arena_size / @page_size IOBUFs */ +struct iobuf_arena; + +/* expandable and contractable pool of memory, internally broken into arenas */ +struct iobuf_pool; + +struct iobuf_init_config { + size_t pagesize; + int32_t num_pages; +}; + +struct iobuf { + union { + struct list_head list; + struct { + struct iobuf *next; + struct iobuf *prev; + }; + }; + struct iobuf_arena *iobuf_arena; + + gf_lock_t lock; /* for ->ptr and ->ref */ + gf_atomic_t ref; /* 0 == passive, >0 == active */ + + void *ptr; /* usable memory region by the consumer */ + + void *free_ptr; /* in case of stdalloc, this is the + one to be freed */ +}; + +struct iobuf_arena { + union { + struct list_head list; + struct { + struct iobuf_arena *next; + struct iobuf_arena *prev; + }; + }; + + struct list_head all_list; + size_t page_size; /* size of all iobufs in this arena */ + size_t arena_size; + /* this is equal to rounded_size * num_iobufs. + (rounded_size comes with gf_iobuf_get_pagesize().) */ + size_t page_count; + + struct iobuf_pool *iobuf_pool; + + void *mem_base; + struct iobuf *iobufs; /* allocated iobufs list */ + + int active_cnt; + struct iobuf active; /* head node iobuf + (unused by itself) */ + int passive_cnt; + struct iobuf passive; /* head node iobuf + (unused by itself) */ + uint64_t alloc_cnt; /* total allocs in this pool */ + int max_active; /* max active buffers at a given time */ +}; + +struct iobuf_pool { + pthread_mutex_t mutex; + size_t arena_size; /* size of memory region in + arena */ + size_t default_page_size; /* default size of iobuf */ + + int arena_cnt; + struct list_head all_arenas; + struct list_head arenas[GF_VARIABLE_IOBUF_COUNT]; + /* array of arenas. Each element of the array is a list of arenas + holding iobufs of particular page_size */ + + struct list_head filled[GF_VARIABLE_IOBUF_COUNT]; + /* array of arenas without free iobufs */ + + struct list_head purge[GF_VARIABLE_IOBUF_COUNT]; + /* array of of arenas which can be purged */ + + uint64_t request_misses; /* mostly the requests for higher + value of iobufs */ + int rdma_device_count; + struct list_head *mr_list[GF_RDMA_DEVICE_COUNT]; + void *device[GF_RDMA_DEVICE_COUNT]; + int (*rdma_registration)(void **, void *); + int (*rdma_deregistration)(struct list_head **, struct iobuf_arena *); +}; + +struct iobuf_pool * +iobuf_pool_new(void); +void +iobuf_pool_destroy(struct iobuf_pool *iobuf_pool); +struct iobuf * +iobuf_get(struct iobuf_pool *iobuf_pool); +void +iobuf_unref(struct iobuf *iobuf); +struct iobuf * +iobuf_ref(struct iobuf *iobuf); +void +iobuf_pool_destroy(struct iobuf_pool *iobuf_pool); +void +iobuf_to_iovec(struct iobuf *iob, struct iovec *iov); + +#define iobuf_ptr(iob) ((iob)->ptr) +#define iobpool_default_pagesize(iobpool) ((iobpool)->default_page_size) +#define iobuf_pagesize(iob) (iob->iobuf_arena->page_size) + +struct iobref { + gf_lock_t lock; + gf_atomic_t ref; + struct iobuf **iobrefs; + int allocated; + int used; +}; + +struct iobref * +iobref_new(void); +struct iobref * +iobref_ref(struct iobref *iobref); +void +iobref_unref(struct iobref *iobref); +int +iobref_add(struct iobref *iobref, struct iobuf *iobuf); +int +iobref_merge(struct iobref *to, struct iobref *from); +void +iobref_clear(struct iobref *iobref); + +size_t +iobuf_size(struct iobuf *iobuf); +size_t +iobref_size(struct iobref *iobref); +void +iobuf_stats_dump(struct iobuf_pool *iobuf_pool); + +struct iobuf * +iobuf_get2(struct iobuf_pool *iobuf_pool, size_t page_size); + +struct iobuf * +iobuf_get_page_aligned(struct iobuf_pool *iobuf_pool, size_t page_size, + size_t align_size); + +int +iobuf_copy(struct iobuf_pool *iobuf_pool, const struct iovec *iovec_src, + int iovcnt, struct iobref **iobref, struct iobuf **iobuf, + struct iovec *iov_dst); + +#endif /* !_IOBUF_H_ */ diff --git a/libglusterfs/src/glusterfs/latency.h b/libglusterfs/src/glusterfs/latency.h new file mode 100644 index 00000000000..ed47b1f0cbc --- /dev/null +++ b/libglusterfs/src/glusterfs/latency.h @@ -0,0 +1,23 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef __LATENCY_H__ +#define __LATENCY_H__ + +#include "glusterfs/glusterfs.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) */ + uint64_t count; +} fop_latency_t; + +#endif /* __LATENCY_H__ */ diff --git a/libglusterfs/src/glusterfs/libglusterfs-messages.h b/libglusterfs/src/glusterfs/libglusterfs-messages.h new file mode 100644 index 00000000000..1b72f6df5be --- /dev/null +++ b/libglusterfs/src/glusterfs/libglusterfs-messages.h @@ -0,0 +1,114 @@ +/* + Copyright (c) 2015 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. + */ + +#ifndef _LG_MESSAGES_H_ +#define _LG_MESSAGES_H_ + +#include "glusterfs/glfs-message-id.h" + +/* To add new message IDs, append new identifiers at the end of the list. + * + * Never remove a message ID. If it's not used anymore, you can rename it or + * leave it as it is, but not delete it. This is to prevent reutilization of + * IDs by other messages. + * + * The component name must match one of the entries defined in + * glfs-message-id.h. + */ + +GLFS_MSGID( + LIBGLUSTERFS, LG_MSG_ASPRINTF_FAILED, LG_MSG_INVALID_ENTRY, + LG_MSG_COUNT_LESS_THAN_ZERO, LG_MSG_COUNT_LESS_THAN_DATA_PAIRS, + LG_MSG_VALUE_LENGTH_LESS_THAN_ZERO, LG_MSG_PAIRS_LESS_THAN_COUNT, + LG_MSG_KEY_OR_VALUE_NULL, LG_MSG_FAILED_TO_LOG_DICT, + LG_MSG_NULL_VALUE_IN_DICT, LG_MSG_DIR_OP_FAILED, + LG_MSG_STORE_HANDLE_CREATE_FAILED, LG_MSG_FILE_OP_FAILED, + LG_MSG_FILE_STAT_FAILED, LG_MSG_LOCK_FAILED, LG_MSG_UNLOCK_FAILED, + LG_MSG_DICT_SERIAL_FAILED, LG_MSG_DICT_UNSERIAL_FAILED, LG_MSG_NO_MEMORY, + LG_MSG_VOLUME_ERROR, LG_MSG_SUB_VOLUME_ERROR, LG_MSG_SYNTAX_ERROR, + LG_MSG_BACKTICK_PARSE_FAILED, LG_MSG_BUFFER_ERROR, LG_MSG_STRDUP_ERROR, + LG_MSG_HASH_FUNC_ERROR, LG_MSG_GET_BUCKET_FAILED, LG_MSG_INSERT_FAILED, + LG_MSG_OUT_OF_RANGE, LG_MSG_VALIDATE_RETURNS, LG_MSG_VALIDATE_REC_FAILED, + LG_MSG_RB_TABLE_CREATE_FAILED, LG_MSG_PATH_NOT_FOUND, + LG_MSG_EXPAND_FD_TABLE_FAILED, LG_MSG_MAPPING_FAILED, + LG_MSG_INIT_IOBUF_FAILED, LG_MSG_PAGE_SIZE_EXCEEDED, LG_MSG_ARENA_NOT_FOUND, + LG_MSG_IOBUF_NOT_FOUND, LG_MSG_POOL_NOT_FOUND, LG_MSG_SET_ATTRIBUTE_FAILED, + LG_MSG_READ_ATTRIBUTE_FAILED, LG_MSG_UNMOUNT_FAILED, + LG_MSG_LATENCY_MEASUREMENT_STATE, LG_MSG_NO_PERM, LG_MSG_NO_KEY, + LG_MSG_DICT_NULL, LG_MSG_INIT_TIMER_FAILED, LG_MSG_FD_ANONYMOUS_FAILED, + LG_MSG_FD_CREATE_FAILED, LG_MSG_BUFFER_FULL, LG_MSG_FWRITE_FAILED, + LG_MSG_PRINT_FAILED, LG_MSG_MEM_POOL_DESTROY, + LG_MSG_EXPAND_CLIENT_TABLE_FAILED, LG_MSG_DISCONNECT_CLIENT, + LG_MSG_PIPE_CREATE_FAILED, LG_MSG_SET_PIPE_FAILED, + LG_MSG_REGISTER_PIPE_FAILED, LG_MSG_POLL_IGNORE_MULTIPLE_THREADS, + LG_MSG_INDEX_NOT_FOUND, LG_MSG_EPOLL_FD_CREATE_FAILED, + LG_MSG_SLOT_NOT_FOUND, LG_MSG_STALE_FD_FOUND, LG_MSG_GENERATION_MISMATCH, + LG_MSG_PTHREAD_KEY_CREATE_FAILED, LG_MSG_TRANSLATOR_INIT_FAILED, + LG_MSG_UUID_BUF_INIT_FAILED, LG_MSG_LKOWNER_BUF_INIT_FAILED, + LG_MSG_SYNCTASK_INIT_FAILED, LG_MSG_SYNCOPCTX_INIT_FAILED, + LG_MSG_GLOBAL_INIT_FAILED, LG_MSG_PTHREAD_FAILED, LG_MSG_DIR_IS_SYMLINK, + LG_MSG_RESOLVE_HOSTNAME_FAILED, LG_MSG_GETADDRINFO_FAILED, + LG_MSG_GETNAMEINFO_FAILED, LG_MSG_PATH_ERROR, LG_MSG_INET_PTON_FAILED, + LG_MSG_NEGATIVE_NUM_PASSED, LG_MSG_GETHOSTNAME_FAILED, + LG_MSG_RESERVED_PORTS_ERROR, LG_MSG_INVALID_PORT, LG_MSG_INVALID_FAMILY, + LG_MSG_CONVERSION_FAILED, LG_MSG_SKIP_HEADER_FAILED, LG_MSG_INVALID_LOG, + LG_MSG_UTIMES_FAILED, LG_MSG_BACKTRACE_SAVE_FAILED, LG_MSG_INIT_FAILED, + LG_MSG_VALIDATION_FAILED, LG_MSG_GRAPH_ERROR, LG_MSG_UNKNOWN_OPTIONS_FAILED, + LG_MSG_CTX_NULL, LG_MSG_TMPFILE_CREATE_FAILED, LG_MSG_DLOPEN_FAILED, + LG_MSG_LOAD_FAILED, LG_MSG_DLSYM_ERROR, LG_MSG_TREE_NOT_FOUND, + LG_MSG_PER_DENTRY, LG_MSG_DENTRY, LG_MSG_GETIFADDRS_FAILED, + LG_MSG_REGEX_OP_FAILED, LG_MSG_FRAME_ERROR, LG_MSG_SET_PARAM_FAILED, + LG_MSG_GET_PARAM_FAILED, LG_MSG_PREPARE_FAILED, LG_MSG_EXEC_FAILED, + LG_MSG_BINDING_FAILED, LG_MSG_DELETE_FAILED, LG_MSG_GET_ID_FAILED, + LG_MSG_CREATE_FAILED, LG_MSG_PARSE_FAILED, LG_MSG_GETCONTEXT_FAILED, + LG_MSG_UPDATE_FAILED, LG_MSG_QUERY_CALL_BACK_FAILED, + LG_MSG_GET_RECORD_FAILED, LG_MSG_DB_ERROR, LG_MSG_CONNECTION_ERROR, + LG_MSG_NOT_MULTITHREAD_MODE, LG_MSG_SKIP_PATH, LG_MSG_INVALID_FOP, + LG_MSG_QUERY_FAILED, LG_MSG_CLEAR_COUNTER_FAILED, LG_MSG_LOCK_LIST_FAILED, + LG_MSG_UNLOCK_LIST_FAILED, LG_MSG_ADD_TO_LIST_FAILED, LG_MSG_INIT_DB_FAILED, + LG_MSG_DELETE_FROM_LIST_FAILED, LG_MSG_CLOSE_CONNECTION_FAILED, + LG_MSG_INSERT_OR_UPDATE_FAILED, LG_MSG_FIND_OP_FAILED, + LG_MSG_CONNECTION_INIT_FAILED, LG_MSG_COMPLETED_TASK, LG_MSG_WAKE_UP_ZOMBIE, + LG_MSG_REWAITING_TASK, LG_MSG_SLEEP_ZOMBIE, LG_MSG_SWAPCONTEXT_FAILED, + LG_MSG_UNSUPPORTED_PLUGIN, LG_MSG_INVALID_DB_TYPE, LG_MSG_UNDERSIZED_BUF, + LG_MSG_DATA_CONVERSION_ERROR, LG_MSG_DICT_ERROR, LG_MSG_IOBUFS_NOT_FOUND, + LG_MSG_ENTRIES_NULL, LG_MSG_FD_NOT_FOUND_IN_FDTABLE, + LG_MSG_REALLOC_FOR_FD_PTR_FAILED, LG_MSG_DICT_SET_FAILED, LG_MSG_NULL_PTR, + LG_MSG_RBTHASH_INIT_BUCKET_FAILED, LG_MSG_ASSERTION_FAILED, + LG_MSG_HOSTNAME_NULL, LG_MSG_INVALID_IPV4_FORMAT, + LG_MSG_CTX_CLEANUP_STARTED, LG_MSG_TIMER_REGISTER_ERROR, + LG_MSG_PTR_HEADER_CORRUPTED, LG_MSG_INVALID_UPLINK, LG_MSG_CLIENT_NULL, + LG_MSG_XLATOR_DOES_NOT_IMPLEMENT, LG_MSG_DENTRY_NOT_FOUND, + LG_MSG_INODE_NOT_FOUND, LG_MSG_INODE_TABLE_NOT_FOUND, + LG_MSG_DENTRY_CREATE_FAILED, LG_MSG_INODE_CONTEXT_FREED, + LG_MSG_UNKNOWN_LOCK_TYPE, LG_MSG_UNLOCK_BEFORE_LOCK, + LG_MSG_LOCK_OWNER_ERROR, LG_MSG_MEMPOOL_PTR_NULL, + LG_MSG_QUOTA_XATTRS_MISSING, LG_MSG_INVALID_STRING, LG_MSG_BIND_REF, + LG_MSG_REF_COUNT, LG_MSG_INVALID_ARG, LG_MSG_VOL_OPTION_ADD, + LG_MSG_XLATOR_OPTION_INVALID, LG_MSG_GETTIMEOFDAY_FAILED, + LG_MSG_GRAPH_INIT_FAILED, LG_MSG_EVENT_NOTIFY_FAILED, + LG_MSG_ACTIVE_GRAPH_NULL, LG_MSG_VOLFILE_PARSE_ERROR, LG_MSG_FD_INODE_NULL, + LG_MSG_INVALID_VOLFILE_ENTRY, LG_MSG_PER_DENTRY_FAILED, + LG_MSG_PARENT_DENTRY_NOT_FOUND, LG_MSG_DENTRY_CYCLIC_LOOP, + LG_MSG_INVALID_POLL_IN, LG_MSG_INVALID_POLL_OUT, LG_MSG_EPOLL_FD_ADD_FAILED, + LG_MSG_EPOLL_FD_DEL_FAILED, LG_MSG_EPOLL_FD_MODIFY_FAILED, + LG_MSG_STARTED_EPOLL_THREAD, LG_MSG_EXITED_EPOLL_THREAD, + LG_MSG_START_EPOLL_THREAD_FAILED, LG_MSG_FALLBACK_TO_POLL, + LG_MSG_QUOTA_CONF_ERROR, LG_MSG_RBTHASH_GET_ENTRY_FAILED, + LG_MSG_RBTHASH_GET_BUCKET_FAILED, LG_MSG_RBTHASH_INSERT_FAILED, + LG_MSG_RBTHASH_INIT_ENTRY_FAILED, LG_MSG_TMPFILE_DELETE_FAILED, + LG_MSG_MEMPOOL_INVALID_FREE, LG_MSG_LOCK_FAILURE, LG_MSG_SET_LOG_LEVEL, + LG_MSG_VERIFY_PLATFORM, LG_MSG_RUNNER_LOG, LG_MSG_LEASEID_BUF_INIT_FAILED, + LG_MSG_PTHREAD_ATTR_INIT_FAILED, LG_MSG_INVALID_INODE_LIST, + LG_MSG_COMPACT_FAILED, LG_MSG_COMPACT_STATUS, LG_MSG_UTIMENSAT_FAILED, + LG_MSG_PTHREAD_NAMING_FAILED, LG_MSG_SYSCALL_RETURNS_WRONG, + LG_MSG_XXH64_TO_GFID_FAILED); + +#endif /* !_LG_MESSAGES_H_ */ diff --git a/libglusterfs/src/glusterfs/list.h b/libglusterfs/src/glusterfs/list.h new file mode 100644 index 00000000000..221a710ca30 --- /dev/null +++ b/libglusterfs/src/glusterfs/list.h @@ -0,0 +1,273 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _LLIST_H +#define _LLIST_H + +struct list_head { + struct list_head *next; + struct list_head *prev; +}; + +#define INIT_LIST_HEAD(head) \ + do { \ + (head)->next = (head)->prev = head; \ + } while (0) + +static inline void +list_add(struct list_head *new, struct list_head *head) +{ + new->prev = head; + new->next = head->next; + + new->prev->next = new; + new->next->prev = new; +} + +static inline void +list_add_tail(struct list_head *new, struct list_head *head) +{ + new->next = head; + new->prev = head->prev; + + new->prev->next = new; + new->next->prev = new; +} + +/* This function will insert the element to the list in a order. + Order will be based on the compare function provided as a input. + If element to be inserted in ascending order compare should return: + 0: if both the arguments are equal + >0: if first argument is greater than second argument + <0: if first argument is less than second argument */ +static inline void +list_add_order(struct list_head *new, struct list_head *head, + int (*compare)(struct list_head *, struct list_head *)) +{ + struct list_head *pos = head->prev; + + while (pos != head) { + if (compare(new, pos) >= 0) + break; + + /* Iterate the list in the reverse order. This will have + better efficiency if the elements are inserted in the + ascending order */ + pos = pos->prev; + } + + list_add(new, pos); +} + +static inline void +list_del(struct list_head *old) +{ + old->prev->next = old->next; + old->next->prev = old->prev; + + old->next = (void *)0xbabebabe; + old->prev = (void *)0xcafecafe; +} + +static inline void +list_del_init(struct list_head *old) +{ + old->prev->next = old->next; + old->next->prev = old->prev; + + old->next = old; + old->prev = old; +} + +static inline void +list_move(struct list_head *list, struct list_head *head) +{ + list_del(list); + list_add(list, head); +} + +static inline void +list_move_tail(struct list_head *list, struct list_head *head) +{ + list_del(list); + list_add_tail(list, head); +} + +static inline int +list_empty(struct list_head *head) +{ + return (head->next == head); +} + +static inline void +__list_splice(struct list_head *list, struct list_head *head) +{ + (list->prev)->next = (head->next); + (head->next)->prev = (list->prev); + + (head)->next = (list->next); + (list->next)->prev = (head); +} + +static inline void +list_splice(struct list_head *list, struct list_head *head) +{ + if (list_empty(list)) + return; + + __list_splice(list, head); +} + +/* Splice moves @list to the head of the list at @head. */ +static inline void +list_splice_init(struct list_head *list, struct list_head *head) +{ + if (list_empty(list)) + return; + + __list_splice(list, head); + INIT_LIST_HEAD(list); +} + +static inline void +__list_append(struct list_head *list, struct list_head *head) +{ + (head->prev)->next = (list->next); + (list->next)->prev = (head->prev); + (head->prev) = (list->prev); + (list->prev)->next = head; +} + +static inline void +list_append(struct list_head *list, struct list_head *head) +{ + if (list_empty(list)) + return; + + __list_append(list, head); +} + +/* Append moves @list to the end of @head */ +static inline void +list_append_init(struct list_head *list, struct list_head *head) +{ + if (list_empty(list)) + return; + + __list_append(list, head); + INIT_LIST_HEAD(list); +} + +static inline int +list_is_last(struct list_head *list, struct list_head *head) +{ + return (list->next == head); +} + +static inline int +list_is_singular(struct list_head *head) +{ + return !list_empty(head) && (head->next == head->prev); +} + +/** + * list_replace - replace old entry by new one + * @old : the element to be replaced + * @new : the new element to insert + * + * If @old was empty, it will be overwritten. + */ +static inline void +list_replace(struct list_head *old, struct list_head *new) +{ + new->next = old->next; + new->next->prev = new; + new->prev = old->prev; + new->prev->next = new; +} + +static inline void +list_replace_init(struct list_head *old, struct list_head *new) +{ + list_replace(old, new); + INIT_LIST_HEAD(old); +} + +/** + * list_rotate_left - rotate the list to the left + * @head: the head of the list + */ +static inline void +list_rotate_left(struct list_head *head) +{ + struct list_head *first; + + if (!list_empty(head)) { + first = head->next; + list_move_tail(first, head); + } +} + +#define list_entry(ptr, type, member) \ + ((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member))) + +#define list_first_entry(ptr, type, member) \ + list_entry((ptr)->next, type, member) + +#define list_last_entry(ptr, type, member) list_entry((ptr)->prev, type, member) + +#define list_next_entry(pos, member) \ + list_entry((pos)->member.next, typeof(*(pos)), member) + +#define list_prev_entry(pos, member) \ + list_entry((pos)->member.prev, typeof(*(pos)), member) + +#define list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +#define list_for_each_entry(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +#define list_for_each_entry_reverse(pos, head, member) \ + for (pos = list_entry((head)->prev, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.prev, typeof(*pos), member)) + +#define list_for_each_entry_safe_reverse(pos, n, head, member) \ + for (pos = list_entry((head)->prev, typeof(*pos), member), \ + n = list_entry(pos->member.prev, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.prev, typeof(*n), member)) + +/* + * This list implementation has some advantages, but one disadvantage: you + * can't use NULL to check whether you're at the head or tail. Thus, the + * address of the head has to be an argument for these macros. + */ + +#define list_next(ptr, head, type, member) \ + (((ptr)->member.next == head) \ + ? NULL \ + : list_entry((ptr)->member.next, type, member)) + +#define list_prev(ptr, head, type, member) \ + (((ptr)->member.prev == head) \ + ? NULL \ + : list_entry((ptr)->member.prev, type, member)) + +#endif /* _LLIST_H */ diff --git a/libglusterfs/src/glusterfs/lkowner.h b/libglusterfs/src/glusterfs/lkowner.h new file mode 100644 index 00000000000..b49e9af6bcb --- /dev/null +++ b/libglusterfs/src/glusterfs/lkowner.h @@ -0,0 +1,93 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _LK_OWNER_H +#define _LK_OWNER_H + +#include "glusterfs-fops.h" + +/* LKOWNER to string functions */ +static inline void +lkowner_unparse(gf_lkowner_t *lkowner, char *buf, int buf_len) +{ + int i = 0; + int j = 0; + + for (i = 0; i < lkowner->len; i++) { + if (i && !(i % 8)) { + buf[j] = '-'; + j++; + } + sprintf(&buf[j], "%02hhx", lkowner->data[i]); + j += 2; + if (j == buf_len) + break; + } + if (j < buf_len) + buf[j] = '\0'; +} + +static inline void +set_lk_owner_from_ptr(gf_lkowner_t *lkowner, void *data) +{ + int i = 0; + int j = 0; + + lkowner->len = sizeof(unsigned long); + for (i = 0, j = 0; i < lkowner->len; i++, j += 8) { + lkowner->data[i] = (char)((((unsigned long)data) >> j) & 0xff); + } +} + +static inline void +set_lk_owner_from_uint64(gf_lkowner_t *lkowner, uint64_t data) +{ + int i = 0; + int j = 0; + + lkowner->len = 8; + for (i = 0, j = 0; i < lkowner->len; i++, j += 8) { + lkowner->data[i] = (char)((data >> j) & 0xff); + } +} + +/* Return true if the locks have the same owner */ +static inline int +is_same_lkowner(gf_lkowner_t *l1, gf_lkowner_t *l2) +{ + return ((l1->len == l2->len) && !memcmp(l1->data, l2->data, l1->len)); +} + +static inline int +is_lk_owner_null(gf_lkowner_t *lkowner) +{ + int is_null = 1; + int i = 0; + + if (lkowner == NULL || lkowner->len == 0) + goto out; + + for (i = 0; i < lkowner->len; i++) { + if (lkowner->data[i] != 0) { + is_null = 0; + break; + } + } +out: + return is_null; +} + +static inline void +lk_owner_copy(gf_lkowner_t *dst, gf_lkowner_t *src) +{ + dst->len = src->len; + memcpy(dst->data, src->data, src->len); +} +#endif /* _LK_OWNER_H */ diff --git a/libglusterfs/src/glusterfs/locking.h b/libglusterfs/src/glusterfs/locking.h new file mode 100644 index 00000000000..43cc87735d1 --- /dev/null +++ b/libglusterfs/src/glusterfs/locking.h @@ -0,0 +1,84 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _LOCKING_H +#define _LOCKING_H + +#include <pthread.h> + +#if defined(GF_DARWIN_HOST_OS) +#include <libkern/OSAtomic.h> +#define pthread_spinlock_t OSSpinLock +#define pthread_spin_lock(l) OSSpinLockLock(l) +#define pthread_spin_unlock(l) OSSpinLockUnlock(l) +#define pthread_spin_destroy(l) 0 +#define pthread_spin_init(l, v) (*l = v) +#endif + +#if defined(HAVE_SPINLOCK) + +typedef union { + pthread_spinlock_t spinlock; + pthread_mutex_t mutex; +} gf_lock_t; + +#if !defined(LOCKING_IMPL) +extern int use_spinlocks; + +/* + * Using a dispatch table would be unpleasant because we're dealing with two + * different types. If the dispatch contains direct pointers to pthread_xx + * or mutex_xxx then we have to hope that every possible union alternative + * starts at the same address as the union itself. I'm old enough to remember + * compilers where this was not the case (for alignment reasons) so I'm a bit + * paranoid about that. Also, I don't like casting arguments through "void *" + * which we'd also have to do to avoid type errors. The other alternative would + * be to define actual functions which pick out the right union member, and put + * those in the dispatch tables. Now we have a pointer dereference through the + * dispatch table plus a function call, which is likely to be worse than the + * branching here from the ?: construct. If it were a clear win it might be + * worth the extra complexity, but for now this way seems preferable. + */ + +#define LOCK_INIT(x) \ + (use_spinlocks ? pthread_spin_init(&((x)->spinlock), 0) \ + : pthread_mutex_init(&((x)->mutex), 0)) + +#define LOCK(x) \ + (use_spinlocks ? pthread_spin_lock(&((x)->spinlock)) \ + : pthread_mutex_lock(&((x)->mutex))) + +#define TRY_LOCK(x) \ + (use_spinlocks ? pthread_spin_trylock(&((x)->spinlock)) \ + : pthread_mutex_trylock(&((x)->mutex))) + +#define UNLOCK(x) \ + (use_spinlocks ? pthread_spin_unlock(&((x)->spinlock)) \ + : pthread_mutex_unlock(&((x)->mutex))) + +#define LOCK_DESTROY(x) \ + (use_spinlocks ? pthread_spin_destroy(&((x)->spinlock)) \ + : pthread_mutex_destroy(&((x)->mutex))) + +#endif + +#else + +typedef pthread_mutex_t gf_lock_t; + +#define LOCK_INIT(x) pthread_mutex_init(x, 0) +#define LOCK(x) pthread_mutex_lock(x) +#define TRY_LOCK(x) pthread_mutex_trylock(x) +#define UNLOCK(x) pthread_mutex_unlock(x) +#define LOCK_DESTROY(x) pthread_mutex_destroy(x) + +#endif /* HAVE_SPINLOCK */ + +#endif /* _LOCKING_H */ diff --git a/libglusterfs/src/glusterfs/logging.h b/libglusterfs/src/glusterfs/logging.h new file mode 100644 index 00000000000..c81e19bef32 --- /dev/null +++ b/libglusterfs/src/glusterfs/logging.h @@ -0,0 +1,392 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef __LOGGING_H__ +#define __LOGGING_H__ + +#include <sys/time.h> +#include <stdint.h> +#include <stdio.h> +#include <stdarg.h> +#include <pthread.h> +#include "glusterfs/list.h" + +#ifdef GF_DARWIN_HOST_OS +#define GF_PRI_FSBLK "u" +#define GF_PRI_DEV PRId32 +#define GF_PRI_INODE PRIu64 +#define GF_PRI_NLINK PRIu32 +#define GF_PRI_SECOND "ld" +#define GF_PRI_SUSECONDS "06d" +#define GF_PRI_SNSECONDS "09ld" +#define GF_PRI_USEC "d" +#else +#define GF_PRI_FSBLK PRIu64 +#define GF_PRI_DEV PRIu64 +#define GF_PRI_INODE PRIu64 +#define GF_PRI_NLINK PRIu32 +#define GF_PRI_SECOND "lu" +#define GF_PRI_SUSECONDS "06ld" +#define GF_PRI_SNSECONDS "09ld" +#define GF_PRI_USEC "ld" +#endif +#define GF_PRI_BLKSIZE PRId32 +#define GF_PRI_SIZET "zu" +#define GF_PRI_ATOMIC PRIu64 + +#ifdef GF_DARWIN_HOST_OS +#define GF_PRI_TIME "ld" +#else +#define GF_PRI_TIME PRIu64 +#endif + +#if 0 +/* Syslog definitions :-) */ +#define LOG_EMERG 0 /* system is unusable */ +#define LOG_ALERT 1 /* action must be taken immediately */ +#define LOG_CRIT 2 /* critical conditions */ +#define LOG_ERR 3 /* error conditions */ +#define LOG_WARNING 4 /* warning conditions */ +#define LOG_NOTICE 5 /* normal but significant condition */ +#define LOG_INFO 6 /* informational */ +#define LOG_DEBUG 7 /* debug-level messages */ +#endif + +#define GF_LOG_FORMAT_NO_MSG_ID "no-msg-id" +#define GF_LOG_FORMAT_WITH_MSG_ID "with-msg-id" + +#define GF_LOGGER_GLUSTER_LOG "gluster-log" +#define GF_LOGGER_SYSLOG "syslog" + +typedef enum { + GF_LOG_NONE, + GF_LOG_EMERG, + GF_LOG_ALERT, + GF_LOG_CRITICAL, /* fatal errors */ + GF_LOG_ERROR, /* major failures (not necessarily fatal) */ + GF_LOG_WARNING, /* info about normal operation */ + GF_LOG_NOTICE, + GF_LOG_INFO, /* Normal information */ + GF_LOG_DEBUG, /* internal errors */ + GF_LOG_TRACE, /* full trace of operation */ +} gf_loglevel_t; + +/* format for the logs */ +typedef enum { + gf_logformat_traditional = 0, /* Format as in gluster 3.5 */ + gf_logformat_withmsgid, /* Format enhanced with MsgID, ident, errstr */ + gf_logformat_cee /* log enhanced format in cee */ +} gf_log_format_t; + +/* log infrastructure to log to */ +typedef enum { + gf_logger_glusterlog = 0, /* locations and files as in gluster 3.5 */ + gf_logger_syslog /* log to (r)syslog, based on (r)syslog conf */ + /* NOTE: In the future journald, lumberjack, next new thing here */ +} gf_log_logger_t; + +#define DEFAULT_LOG_FILE_DIRECTORY DATADIR "/log/glusterfs" +#define DEFAULT_QUOTA_CRAWL_LOG_DIRECTORY DATADIR "/log/glusterfs/quota_crawl" +#define DEFAULT_LOG_LEVEL GF_LOG_INFO + +typedef struct gf_log_handle_ { + pthread_mutex_t logfile_mutex; + uint8_t logrotate; + uint8_t cmd_history_logrotate; + gf_loglevel_t loglevel; + int gf_log_syslog; + gf_loglevel_t sys_log_level; + char *filename; + FILE *logfile; + FILE *gf_log_logfile; + char *cmd_log_filename; + FILE *cmdlogfile; + gf_log_logger_t logger; + gf_log_format_t logformat; + char *ident; + int log_control_file_found; + struct list_head lru_queue; + uint32_t lru_size; + uint32_t lru_cur_size; + uint32_t timeout; + pthread_mutex_t log_buf_lock; + struct _gf_timer *log_flush_timer; + int localtime; +} gf_log_handle_t; + +typedef struct log_buf_ { + char *msg; + uint64_t msg_id; + int errnum; + struct timeval oldest; + struct timeval latest; + char *domain; + char *file; + char *function; + int32_t line; + gf_loglevel_t level; + int refcount; + int graph_id; + struct list_head msg_list; +} log_buf_t; + +void +gf_log_globals_init(void *ctx, gf_loglevel_t level); +int +gf_log_init(void *data, const char *filename, const char *ident); + +void +gf_log_logrotate(int signum); + +void +gf_log_cleanup(void); + +/* Internal interfaces to log messages with message IDs */ +int +_gf_msg(const char *domain, const char *file, const char *function, + int32_t line, gf_loglevel_t level, int errnum, int trace, + uint64_t msgid, const char *fmt, ...) + __attribute__((__format__(__printf__, 9, 10))); + +void +_gf_msg_backtrace_nomem(gf_loglevel_t level, int stacksize); + +int +_gf_msg_plain(gf_loglevel_t level, const char *fmt, ...) + __attribute__((__format__(__printf__, 2, 3))); + +int +_gf_msg_plain_nomem(gf_loglevel_t level, const char *msg); + +int +_gf_msg_vplain(gf_loglevel_t level, const char *fmt, va_list ap); + +int +_gf_msg_nomem(const char *domain, const char *file, const char *function, + int line, gf_loglevel_t level, size_t size); + +int +_gf_log(const char *domain, const char *file, const char *function, + int32_t line, gf_loglevel_t level, const char *fmt, ...) + __attribute__((__format__(__printf__, 6, 7))); + +int +_gf_log_callingfn(const char *domain, const char *file, const char *function, + int32_t line, gf_loglevel_t level, const char *fmt, ...) + __attribute__((__format__(__printf__, 6, 7))); + +int +_gf_log_eh(const char *function, const char *fmt, ...) + __attribute__((__format__(__printf__, 2, 3))); + +/* treat GF_LOG_TRACE and GF_LOG_NONE as LOG_DEBUG and + * other level as is */ +#define SET_LOG_PRIO(level, priority) \ + do { \ + if (GF_LOG_TRACE == (level) || GF_LOG_NONE == (level)) { \ + priority = LOG_DEBUG; \ + } else { \ + priority = (level)-1; \ + } \ + } while (0) + +/* extract just the file name from the path */ +#define GET_FILE_NAME_TO_LOG(file, basename) \ + do { \ + basename = strrchr((file), '/'); \ + if (basename) \ + basename++; \ + else \ + basename = (file); \ + } while (0) + +#define PRINT_SIZE_CHECK(ret, label, strsize) \ + do { \ + if (ret < 0) \ + goto label; \ + if ((strsize - ret) > 0) { \ + strsize -= ret; \ + } else { \ + ret = 0; \ + goto label; \ + } \ + } while (0) + +#define FMT_WARN(fmt...) \ + do { \ + if (0) \ + printf(fmt); \ + } while (0) + +/* Interface to log messages with message IDs */ +#define gf_msg(dom, level, errnum, msgid, fmt...) \ + do { \ + _gf_msg(dom, __FILE__, __FUNCTION__, __LINE__, level, errnum, 0, \ + msgid, ##fmt); \ + } while (0) + +/* no frills, no thrills, just a vanilla message, used to print the graph */ +#define gf_msg_plain(level, fmt...) \ + do { \ + _gf_msg_plain(level, ##fmt); \ + } while (0) + +#define gf_msg_plain_nomem(level, msg) \ + do { \ + _gf_msg_plain_nomem(level, msg); \ + } while (0) + +#define gf_msg_vplain(level, fmt, va) \ + do { \ + _gf_msg_vplain(level, fmt, va); \ + } while (0) + +#define gf_msg_backtrace_nomem(level, stacksize) \ + do { \ + _gf_msg_backtrace_nomem(level, stacksize); \ + } while (0) + +#define gf_msg_callingfn(dom, level, errnum, msgid, fmt...) \ + do { \ + _gf_msg(dom, __FILE__, __FUNCTION__, __LINE__, level, errnum, 1, \ + msgid, ##fmt); \ + } while (0) + +/* No malloc or calloc should be called in this function */ +#define gf_msg_nomem(dom, level, size) \ + do { \ + _gf_msg_nomem(dom, __FILE__, __FUNCTION__, __LINE__, level, size); \ + } while (0) + +/* Debug or trace messages do not need message IDs as these are more developer + * related. Hence, the following abstractions are provided for the same */ +#define gf_msg_debug(dom, errnum, fmt...) \ + do { \ + _gf_msg(dom, __FILE__, __FUNCTION__, __LINE__, GF_LOG_DEBUG, errnum, \ + 0, 0, ##fmt); \ + } while (0) + +#define gf_msg_trace(dom, errnum, fmt...) \ + do { \ + _gf_msg(dom, __FILE__, __FUNCTION__, __LINE__, GF_LOG_TRACE, errnum, \ + 0, 0, ##fmt); \ + } while (0) + +#define gf_log(dom, level, fmt...) \ + do { \ + FMT_WARN(fmt); \ + _gf_log(dom, __FILE__, __FUNCTION__, __LINE__, level, ##fmt); \ + } while (0) + +#define gf_log_eh(fmt...) \ + do { \ + FMT_WARN(fmt); \ + _gf_log_eh(__FUNCTION__, ##fmt); \ + } while (0) + +#define gf_log_callingfn(dom, level, fmt...) \ + do { \ + FMT_WARN(fmt); \ + _gf_log_callingfn(dom, __FILE__, __FUNCTION__, __LINE__, level, \ + ##fmt); \ + } while (0) + +/* Log once in GF_UNIVERSAL_ANSWER times */ +#define GF_LOG_OCCASIONALLY(var, args...) \ + if (!(var++ % GF_UNIVERSAL_ANSWER)) { \ + gf_log(args); \ + } + +struct _glusterfs_ctx; + +void +gf_log_disable_syslog(void); +void +gf_log_enable_syslog(void); +gf_loglevel_t +gf_log_get_loglevel(void); +void +gf_log_set_loglevel(struct _glusterfs_ctx *ctx, gf_loglevel_t level); +int +gf_log_get_localtime(void); +void +gf_log_set_localtime(int); +void +gf_log_flush(void); +gf_loglevel_t +gf_log_get_xl_loglevel(void *xl); +void +gf_log_set_xl_loglevel(void *xl, gf_loglevel_t level); + +int +gf_cmd_log(const char *domain, const char *fmt, ...) + __attribute__((__format__(__printf__, 2, 3))); + +int +gf_cmd_log_init(const char *filename); + +void +set_sys_log_level(gf_loglevel_t level); + +int +gf_log_fini(void *data); + +void +gf_log_set_logger(gf_log_logger_t logger); + +void +gf_log_set_logformat(gf_log_format_t format); + +void +gf_log_set_log_buf_size(uint32_t buf_size); + +void +gf_log_set_log_flush_timeout(uint32_t timeout); + +void +gf_log_flush_msgs(struct _glusterfs_ctx *ctx); + +int +gf_log_inject_timer_event(struct _glusterfs_ctx *ctx); + +void +gf_log_disable_suppression_before_exit(struct _glusterfs_ctx *ctx); + +#define GF_DEBUG(xl, format, args...) \ + gf_log((xl)->name, GF_LOG_DEBUG, format, ##args) +#define GF_INFO(xl, format, args...) \ + gf_log((xl)->name, GF_LOG_INFO, format, ##args) +#define GF_WARNING(xl, format, args...) \ + gf_log((xl)->name, GF_LOG_WARNING, format, ##args) +#define GF_ERROR(xl, format, args...) \ + gf_log((xl)->name, GF_LOG_ERROR, format, ##args) + +int +_gf_slog(const char *domain, const char *file, const char *function, int line, + gf_loglevel_t level, const char *event, ...); + +int +_gf_smsg(const char *domain, const char *file, const char *function, + int32_t line, gf_loglevel_t level, int errnum, int trace, + uint64_t msgid, const char *event, ...); + +/* Interface to log messages with message IDs */ +#define gf_smsg(dom, level, errnum, msgid, event...) \ + do { \ + _gf_smsg(dom, __FILE__, __FUNCTION__, __LINE__, level, errnum, 0, \ + msgid, ##event); \ + } while (0) + +#define gf_slog(dom, level, event...) \ + do { \ + _gf_slog(dom, __FILE__, __FUNCTION__, __LINE__, level, ##event); \ + } while (0) + +#endif /* __LOGGING_H__ */ diff --git a/libglusterfs/src/glusterfs/lvm-defaults.h b/libglusterfs/src/glusterfs/lvm-defaults.h new file mode 100644 index 00000000000..32feebf3f6e --- /dev/null +++ b/libglusterfs/src/glusterfs/lvm-defaults.h @@ -0,0 +1,20 @@ +/* + Copyright (c) 2014 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _LVM_DEFAULTS_H +#define _LVM_DEFAULTS_H + +#define LVM_RESIZE "/sbin/lvresize" +#define LVM_CREATE "/sbin/lvcreate" +#define LVM_CONVERT "/sbin/lvconvert" +#define LVM_REMOVE "/sbin/lvremove" +#define LVS "/sbin/lvs" + +#endif /* _LVM_DEFAULTS_H */ diff --git a/libglusterfs/src/glusterfs/mem-pool.h b/libglusterfs/src/glusterfs/mem-pool.h new file mode 100644 index 00000000000..1c7e868ab75 --- /dev/null +++ b/libglusterfs/src/glusterfs/mem-pool.h @@ -0,0 +1,304 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _MEM_POOL_H_ +#define _MEM_POOL_H_ + +#include "glusterfs/list.h" +#include "glusterfs/locking.h" +#include "glusterfs/atomic.h" +#include "glusterfs/logging.h" +#include "glusterfs/mem-types.h" +#include "glusterfs/glusterfs.h" /* for glusterfs_ctx_t */ +#include <stdlib.h> +#include <inttypes.h> +#include <string.h> +#include <stdarg.h> + +/* + * Need this for unit tests since inline functions + * access memory allocation and need to use the + * unit test versions + */ +#ifdef UNIT_TESTING +#include <stddef.h> +#include <setjmp.h> +#include <cmocka.h> +#endif + +#define GF_MEM_TRAILER_SIZE 8 +#define GF_MEM_HEADER_MAGIC 0xCAFEBABE +#define GF_MEM_TRAILER_MAGIC 0xBAADF00D +#define GF_MEM_INVALID_MAGIC 0xDEADC0DE + +struct mem_acct_rec { + const char *typestr; + uint64_t size; + uint64_t max_size; + uint64_t total_allocs; + uint32_t num_allocs; + uint32_t max_num_allocs; + gf_lock_t lock; +#ifdef DEBUG + struct list_head obj_list; +#endif +}; + +struct mem_acct { + uint32_t num_types; + gf_atomic_t refcnt; + struct mem_acct_rec rec[0]; +}; + +struct mem_header { + uint32_t type; + size_t size; + struct mem_acct *mem_acct; + uint32_t magic; +#ifdef DEBUG + struct list_head acct_list; +#endif + int padding[8]; +}; + +#define GF_MEM_HEADER_SIZE (sizeof(struct mem_header)) + +#ifdef DEBUG +struct mem_invalid { + uint32_t magic; + void *mem_acct; + uint32_t type; + size_t size; + void *baseaddr; +}; +#endif + +void * +__gf_calloc(size_t cnt, size_t size, uint32_t type, const char *typestr); + +void * +__gf_malloc(size_t size, uint32_t type, const char *typestr); + +void * +__gf_realloc(void *ptr, size_t size); + +int +gf_vasprintf(char **string_ptr, const char *format, va_list arg); + +int +gf_asprintf(char **string_ptr, const char *format, ...) + __attribute__((__format__(__printf__, 2, 3))); + +void +__gf_free(void *ptr); + +static inline void * +__gf_default_malloc(size_t size) +{ + void *ptr = NULL; + + ptr = malloc(size); + if (!ptr) + gf_msg_nomem("", GF_LOG_ALERT, size); + + return ptr; +} + +static inline void * +__gf_default_calloc(int cnt, size_t size) +{ + void *ptr = NULL; + + ptr = calloc(cnt, size); + if (!ptr) + gf_msg_nomem("", GF_LOG_ALERT, (cnt * size)); + + return ptr; +} + +static inline void * +__gf_default_realloc(void *oldptr, size_t size) +{ + void *ptr = NULL; + + ptr = realloc(oldptr, size); + if (!ptr) + gf_msg_nomem("", GF_LOG_ALERT, size); + + return ptr; +} + +#define MALLOC(size) __gf_default_malloc(size) +#define CALLOC(cnt, size) __gf_default_calloc(cnt, size) +#define REALLOC(ptr, size) __gf_default_realloc(ptr, size) + +#define FREE(ptr) \ + do { \ + if (ptr != NULL) { \ + free((void *)ptr); \ + ptr = (void *)0xeeeeeeee; \ + } \ + } while (0) + +#define GF_CALLOC(nmemb, size, type) __gf_calloc(nmemb, size, type, #type) + +#define GF_MALLOC(size, type) __gf_malloc(size, type, #type) + +#define GF_REALLOC(ptr, size) __gf_realloc(ptr, size) + +#define GF_FREE(free_ptr) __gf_free(free_ptr) + +static inline char * +gf_strndup(const char *src, size_t len) +{ + char *dup_str = NULL; + + if (!src) { + goto out; + } + + dup_str = GF_MALLOC(len + 1, gf_common_mt_strdup); + if (!dup_str) { + goto out; + } + + memcpy(dup_str, src, len); + dup_str[len] = '\0'; +out: + return dup_str; +} + +static inline char * +gf_strdup(const char *src) +{ + if (!src) + return NULL; + + return gf_strndup(src, strlen(src)); +} + +static inline void * +gf_memdup(const void *src, size_t size) +{ + void *dup_mem = NULL; + + dup_mem = GF_MALLOC(size, gf_common_mt_strdup); + if (!dup_mem) + goto out; + + memcpy(dup_mem, src, size); + +out: + return dup_mem; +} + +/* 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 { + /* object size, without pooled_obj_hdr_t */ + unsigned long sizeof_type; + unsigned long count; /* requested pool size (unused) */ + char *name; + gf_atomic_t active; /* current allocations */ + + struct list_head owner; /* glusterfs_ctx_t->mempool_list */ + glusterfs_ctx_t *ctx; /* take ctx->lock when updating owner */ + + struct mem_pool_shared *pool; /* the initial pool that was returned */ +}; + +typedef struct pooled_obj_hdr { + unsigned long magic; + struct pooled_obj_hdr *next; + struct per_thread_pool_list *pool_list; + unsigned int power_of_two; + + /* track the pool that was used to request this object */ + struct mem_pool *pool; +} pooled_obj_hdr_t; + +#define AVAILABLE_SIZE(p2) ((1 << (p2)) - sizeof(pooled_obj_hdr_t)) + +typedef struct per_thread_pool { + /* the pool that was used to request this allocation */ + struct mem_pool_shared *parent; + /* Everything else is protected by our own lock. */ + pooled_obj_hdr_t *hot_list; + pooled_obj_hdr_t *cold_list; +} 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. + */ + struct list_head thr_list; + unsigned int 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; + +/* actual pool structure, shared between different mem_pools */ +struct mem_pool_shared { + unsigned int power_of_two; + /* + * Updates to these are *not* protected by a global lock, so races + * could occur and the numbers might be slightly off. Don't expect + * them to line up exactly. It's the general trends that matter, and + * it's not worth the locked-bus-cycle overhead to make these precise. + */ + gf_atomic_t allocs_hot; + gf_atomic_t allocs_cold; + gf_atomic_t allocs_stdc; + gf_atomic_t frees_to_list; +}; + +void +mem_pools_init_early(void); /* basic initialization of memory pools */ +void +mem_pools_init_late(void); /* start the pool_sweeper thread */ +void +mem_pools_fini(void); /* cleanup memory pools */ + +struct mem_pool * +mem_pool_new_fn(glusterfs_ctx_t *ctx, unsigned long sizeof_type, + unsigned long count, char *name); + +#define mem_pool_new(type, count) \ + mem_pool_new_fn(THIS->ctx, sizeof(type), count, #type) + +#define mem_pool_new_ctx(ctx, type, count) \ + mem_pool_new_fn(ctx, sizeof(type), count, #type) + +void +mem_put(void *ptr); +void * +mem_get(struct mem_pool *pool); +void * +mem_get0(struct mem_pool *pool); + +void +mem_pool_destroy(struct mem_pool *pool); + +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 new file mode 100644 index 00000000000..4f6ca4e0e84 --- /dev/null +++ b/libglusterfs/src/glusterfs/mem-types.h @@ -0,0 +1,181 @@ +/* + Copyright (c) 2008-2016 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef __MEM_TYPES_H__ +#define __MEM_TYPES_H__ + +enum gf_common_mem_types_ { + gf_common_mt_call_stub_t, + gf_common_mt_dnscache6, + gf_common_mt_data_pair_t, + gf_common_mt_data_t, + gf_common_mt_dict_t, + gf_common_mt_event_pool, + gf_common_mt_reg, + gf_common_mt_pollfd, + gf_common_mt_epoll_event, + gf_common_mt_fdentry_t, + gf_common_mt_fdtable_t, + gf_common_mt_fd_t, + gf_common_mt_fd_ctx, + gf_common_mt_gf_dirent_t, + gf_common_mt_glusterfs_ctx_t, + gf_common_mt_dentry_t, + gf_common_mt_inode_t, + gf_common_mt_inode_ctx, + gf_common_mt_list_head, + gf_common_mt_inode_table_t, + gf_common_mt_xlator_t, + gf_common_mt_xlator_list_t, + gf_common_mt_log_msg, + gf_common_mt_client_log, + gf_common_mt_volume_opt_list_t, + gf_common_mt_gf_hdr_common_t, + gf_common_mt_call_frame_t, + gf_common_mt_call_stack_t, + gf_common_mt_gf_timer_t, + gf_common_mt_gf_timer_registry_t, + gf_common_mt_transport, + gf_common_mt_transport_msg, + gf_common_mt_auth_handle_t, + gf_common_mt_iobuf, + gf_common_mt_iobuf_arena, + gf_common_mt_iobref, + gf_common_mt_iobuf_pool, + gf_common_mt_iovec, + gf_common_mt_memdup, + gf_common_mt_asprintf, + gf_common_mt_strdup, + gf_common_mt_socket_private_t, + gf_common_mt_ioq, + gf_common_mt_transport_t, + gf_common_mt_socket_local_t, + gf_common_mt_char, + gf_common_mt_rbthash_table_t, + gf_common_mt_rbthash_bucket, + gf_common_mt_mem_pool, + gf_common_mt_long, + gf_common_mt_rpcsvc_auth_list, + gf_common_mt_rpcsvc_t, + gf_common_mt_rpcsvc_conn_t, + gf_common_mt_rpcsvc_program_t, + gf_common_mt_rpcsvc_listener_t, + gf_common_mt_rpcsvc_wrapper_t, + gf_common_mt_rpcsvc_stage_t, + gf_common_mt_rpcclnt_t, + gf_common_mt_rpcclnt_savedframe_t, + gf_common_mt_rpc_trans_t, + gf_common_mt_rpc_trans_pollin_t, + gf_common_mt_rpc_trans_handover_t, + gf_common_mt_rpc_trans_reqinfo_t, + gf_common_mt_rpc_trans_rsp_t, + gf_common_mt_glusterfs_graph_t, + gf_common_mt_rdma_private_t, + gf_common_mt_rdma_ioq_t, + gf_common_mt_rpc_transport_t, + gf_common_mt_rdma_local_t, + gf_common_mt_rdma_post_t, + gf_common_mt_qpent, + gf_common_mt_rdma_device_t, + gf_common_mt_rdma_context_t, + gf_common_mt_sge, + gf_common_mt_rpcclnt_cb_program_t, + gf_common_mt_libxl_marker_local, + gf_common_mt_graph_buf, + gf_common_mt_trie_trie, + gf_common_mt_trie_data, + gf_common_mt_trie_node, + gf_common_mt_trie_buf, + gf_common_mt_trie_end, + gf_common_mt_run_argv, + gf_common_mt_run_logbuf, + gf_common_mt_fd_lk_ctx_t, + gf_common_mt_fd_lk_ctx_node_t, + gf_common_mt_buffer_t, + gf_common_mt_circular_buffer_t, + gf_common_mt_eh_t, + gf_common_mt_store_handle_t, + gf_common_mt_store_iter_t, + gf_common_mt_drc_client_t, + gf_common_mt_drc_globals_t, + gf_common_mt_drc_rbtree_node_t, + gf_common_mt_iov_base_t, + gf_common_mt_groups_t, + gf_common_mt_cliententry_t, + gf_common_mt_clienttable_t, + gf_common_mt_client_t, + gf_common_mt_client_ctx, + gf_common_mt_lock_table, + gf_common_mt_locker, + gf_common_mt_auxgids, + gf_common_mt_syncopctx, + gf_common_mt_iobrefs, + gf_common_mt_gsync_status_t, + gf_common_mt_uuid_t, + gf_common_mt_mgmt_v3_lock_obj_t, + gf_common_mt_txn_opinfo_obj_t, + gf_common_mt_strfd_t, + gf_common_mt_strfd_data_t, + gf_common_mt_regex_t, + gf_common_mt_ereg, + gf_common_mt_wr, + gf_common_mt_rdma_arena_mr, + gf_common_mt_dnscache = 115, + gf_common_mt_dnscache_entry = 116, + gf_common_mt_parser_t, + gf_common_quota_meta_t, + /*related to gfdb library*/ + gfdb_mt_time_t, + gf_mt_sql_cbk_args_t, + gf_mt_gfdb_query_record_t, + gf_mt_gfdb_link_info_t, + gf_mt_gfdb_db_operations_t, + gf_mt_sql_connection_t, + gf_mt_sql_conn_node_t, + gf_mt_db_conn_node_t, + gf_mt_db_connection_t, + gfdb_mt_db_record_t, + /*related to gfdb library*/ + gf_common_mt_rbuf_t, + gf_common_mt_rlist_t, + gf_common_mt_rvec_t, + /* glusterd can load the nfs-xlator dynamically and needs these two */ + gf_common_mt_nfs_netgroups, + gf_common_mt_nfs_exports, + gf_common_mt_gf_brick_spec_t, + gf_common_mt_gf_timer_entry_t, + gf_common_mt_int, + gf_common_mt_pointer, + gf_common_mt_synctask, + gf_common_mt_syncstack, + gf_common_mt_syncenv, + gf_common_mt_scan_data, + gf_common_list_node, + gf_mt_default_args_t, + gf_mt_default_args_cbk_t, + /*used for compound fops*/ + gf_mt_compound_req_t, + gf_mt_compound_rsp_t, + gf_common_mt_tw_ctx, + gf_common_mt_tw_timer_list, + /*lock migration*/ + gf_common_mt_lock_mig, + /* throttle */ + gf_common_mt_tbf_t, + gf_common_mt_tbf_bucket_t, + gf_common_mt_tbf_throttle_t, + gf_common_mt_pthread_t, + gf_common_ping_local_t, + gf_common_volfile_t, + gf_common_mt_mgmt_v3_lock_timer_t, + gf_common_mt_server_cmdline_t, + gf_common_mt_end +}; +#endif diff --git a/libglusterfs/src/glusterfs/monitoring.h b/libglusterfs/src/glusterfs/monitoring.h new file mode 100644 index 00000000000..09d9f54e734 --- /dev/null +++ b/libglusterfs/src/glusterfs/monitoring.h @@ -0,0 +1,21 @@ +/* + Copyright (c) 2017 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef __MONITORING_H__ +#define __MONITORING_H__ + +#include "glusterfs/glusterfs.h" + +#define GLUSTER_METRICS_DIR "/var/run/gluster/metrics" + +char * +gf_monitor_metrics(glusterfs_ctx_t *ctx); + +#endif /* __MONITORING_H__ */ diff --git a/libglusterfs/src/glusterfs/options.h b/libglusterfs/src/glusterfs/options.h new file mode 100644 index 00000000000..0e683d780df --- /dev/null +++ b/libglusterfs/src/glusterfs/options.h @@ -0,0 +1,339 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _OPTIONS_H +#define _OPTIONS_H + +#include <stdio.h> +#include <stdint.h> +#include <inttypes.h> + +#include "glusterfs/xlator.h" +#include "glusterfs/libglusterfs-messages.h" +/* Add possible new type of option you may need */ +typedef enum { + GF_OPTION_TYPE_ANY = 0, + GF_OPTION_TYPE_STR, + GF_OPTION_TYPE_INT, + GF_OPTION_TYPE_SIZET, + GF_OPTION_TYPE_PERCENT, + GF_OPTION_TYPE_PERCENT_OR_SIZET, + GF_OPTION_TYPE_BOOL, + GF_OPTION_TYPE_XLATOR, + GF_OPTION_TYPE_PATH, + GF_OPTION_TYPE_TIME, + GF_OPTION_TYPE_DOUBLE, + GF_OPTION_TYPE_INTERNET_ADDRESS, + GF_OPTION_TYPE_INTERNET_ADDRESS_LIST, + GF_OPTION_TYPE_PRIORITY_LIST, + GF_OPTION_TYPE_SIZE_LIST, + GF_OPTION_TYPE_CLIENT_AUTH_ADDR, + GF_OPTION_TYPE_MAX, +} volume_option_type_t; + +typedef enum { + GF_OPT_VALIDATE_BOTH = 0, + GF_OPT_VALIDATE_MIN, + GF_OPT_VALIDATE_MAX, +} opt_validate_type_t; + +typedef enum { + OPT_FLAG_NONE = 0, + OPT_FLAG_SETTABLE = 1 << 0, /* can be set using volume set */ + OPT_FLAG_CLIENT_OPT = 1 << 1, /* affects clients */ + OPT_FLAG_GLOBAL = 1 + << 2, /* affects all instances of the particular xlator */ + OPT_FLAG_FORCE = 1 << 3, /* needs force to be reset */ + OPT_FLAG_NEVER_RESET = 1 << 4, /* which should not be reset */ + OPT_FLAG_DOC = 1 << 5, /* can be shown in volume set help */ +} opt_flags_t; + +typedef enum { + OPT_STATUS_ADVANCED = 0, + OPT_STATUS_BASIC = 1, + OPT_STATUS_EXPERIMENTAL = 2, + OPT_STATUS_DEPRECATED = 3, +} opt_level_t; + +#define ZR_VOLUME_MAX_NUM_KEY 4 +#define ZR_OPTION_MAX_ARRAY_SIZE 64 +/* The maximum number of releases that an option could be backported to + * based on the release schedule as in August 2017 (3), plus one more + * Refer comment on volume_options.op_version for more information. + */ +#define GF_MAX_RELEASES 4 + +/* Custom validation functoins for options + * TODO: Need to check what sorts of validation is being done, and decide if + * passing the volinfo is actually required. If it is, then we should possibly + * try a solution in GD2 for this. + */ +/* typedef int (*option_validation_fn) (glusterd_volinfo_t *volinfo, dict_t + *dict, char *key, char *value, char **op_errstr); + */ + +/* Each translator should define this structure */ +/* XXX: This structure is in use by GD2, and SHOULD NOT be modified. + * If there is a need to add new members, add them to the end of the structure. + * If the struct must be modified, GD2 MUST be updated as well + */ +typedef struct volume_options { + char *key[ZR_VOLUME_MAX_NUM_KEY]; + /* different key, same meaning */ + volume_option_type_t type; + double min; /* 0 means no range */ + double max; /* 0 means no range */ + char *value[ZR_OPTION_MAX_ARRAY_SIZE]; + /* If specified, will check for one of + the value from this array */ + char *default_value; + char *description; /* about the key */ + /* Required for int options where only the min value + * is given and is 0. This will cause validation not to + * happen + */ + opt_validate_type_t validate; + + /* The op-version at which this option was introduced. + * This is an array to support options that get backported to supported + * releases. + * Normally, an option introduced for a major release just has a single + * entry in the array, with op-version of the major release + * For an option that is backported, the op-versions of the all the + * releases it was ported to should be added, starting from the newest, + * to the oldest. + */ + uint32_t op_version[GF_MAX_RELEASES]; + /* The op-version at which this option was deprecated. + * Follows the same rules as above. + */ + uint32_t deprecated[GF_MAX_RELEASES]; + /* Additional flags for an option + * Check the OPT_FLAG_* enums for available flags + */ + uint32_t flags; + /* Tags applicable to this option, which can be used to group similar + * options + */ + char *tags[ZR_OPTION_MAX_ARRAY_SIZE]; + /* A custom validation function if required + * TODO: See todo above for option_validation_fn + */ + /* option_validation_fn validate_fn; */ + /* This is actual key that should be set in the options dict. Can + * contain varstrings + */ + char *setkey; + + /* A 'level' is about the technical depth / understanding one + needs to handle the option. 'category' is based on + quality (ie, tests, people behind it, documentation available) */ + + /* The level at which the option is classified */ + opt_level_t level; + + /* Flag to understand how this option is categorized */ + gf_category_t category; +} volume_option_t; + +typedef struct vol_opt_list { + struct list_head list; + volume_option_t *given_opt; +} volume_opt_list_t; + +int +xlator_tree_reconfigure(xlator_t *old_xl, xlator_t *new_xl); +int +xlator_validate_rec(xlator_t *xlator, char **op_errstr); +int +graph_reconf_validateopt(glusterfs_graph_t *graph, char **op_errstr); +int +xlator_option_info_list(volume_opt_list_t *list, char *key, char **def_val, + char **descr); +/* +int validate_xlator_volume_options (xlator_t *xl, dict_t *options, + volume_option_t *opt, char **op_errstr); +*/ +int +xlator_options_validate_list(xlator_t *xl, dict_t *options, + volume_opt_list_t *list, char **op_errstr); +int +xlator_option_validate(xlator_t *xl, char *key, char *value, + volume_option_t *opt, char **op_errstr); +int +xlator_options_validate(xlator_t *xl, dict_t *options, char **errstr); + +int +xlator_option_validate_addr_list(xlator_t *xl, const char *key, + const char *value, volume_option_t *opt, + char **op_errstr); + +volume_option_t * +xlator_volume_option_get(xlator_t *xl, const char *key); + +volume_option_t * +xlator_volume_option_get_list(volume_opt_list_t *vol_list, const char *key); + +#define DECLARE_INIT_OPT(type_t, type) \ + int xlator_option_init_##type(xlator_t *this, dict_t *options, char *key, \ + type_t *val_p); + +DECLARE_INIT_OPT(char *, str); +DECLARE_INIT_OPT(uint64_t, uint64); +DECLARE_INIT_OPT(int64_t, int64); +DECLARE_INIT_OPT(uint32_t, uint32); +DECLARE_INIT_OPT(int32_t, int32); +DECLARE_INIT_OPT(uint64_t, size); +DECLARE_INIT_OPT(uint64_t, size_uint64); +DECLARE_INIT_OPT(double, percent); +DECLARE_INIT_OPT(double, percent_or_size); +DECLARE_INIT_OPT(gf_boolean_t, bool); +DECLARE_INIT_OPT(xlator_t *, xlator); +DECLARE_INIT_OPT(char *, path); +DECLARE_INIT_OPT(double, double); +DECLARE_INIT_OPT(uint32_t, time); + +#define DEFINE_INIT_OPT(type_t, type, conv) \ + int xlator_option_init_##type(xlator_t *this, dict_t *options, char *key, \ + type_t *val_p) \ + { \ + int ret = 0; \ + volume_option_t *opt = NULL; \ + char *def_value = NULL; \ + char *set_value = NULL; \ + char *value = NULL; \ + xlator_t *old_THIS = NULL; \ + \ + opt = xlator_volume_option_get(this, key); \ + if (!opt) { \ + gf_msg(this->name, GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ENTRY, \ + "unknown option: %s", key); \ + ret = -1; \ + return ret; \ + } \ + def_value = opt->default_value; \ + ret = dict_get_str(options, key, &set_value); \ + \ + if (def_value) \ + value = def_value; \ + if (set_value) \ + value = set_value; \ + if (!value) { \ + gf_msg_trace(this->name, 0, "option %s not set", key); \ + *val_p = (type_t)0; \ + return 0; \ + } \ + if (value == def_value) { \ + gf_msg_trace(this->name, 0, \ + "option %s using default" \ + " value %s", \ + key, value); \ + } else { \ + gf_msg_debug(this->name, 0, \ + "option %s using set" \ + " value %s", \ + key, value); \ + } \ + old_THIS = THIS; \ + THIS = this; \ + ret = conv(value, val_p); \ + THIS = old_THIS; \ + if (ret) { \ + gf_msg(this->name, GF_LOG_INFO, 0, LG_MSG_CONVERSION_FAILED, \ + "option %s conversion failed value %s", key, value); \ + return ret; \ + } \ + ret = xlator_option_validate(this, key, value, opt, NULL); \ + return ret; \ + } + +#define GF_OPTION_INIT(key, val, type, err_label) \ + do { \ + int val_ret = 0; \ + val_ret = xlator_option_init_##type(THIS, THIS->options, key, &(val)); \ + if (val_ret) \ + goto err_label; \ + } while (0) + +#define DECLARE_RECONF_OPT(type_t, type) \ + int xlator_option_reconf_##type(xlator_t *this, dict_t *options, \ + char *key, type_t *val_p); + +DECLARE_RECONF_OPT(char *, str); +DECLARE_RECONF_OPT(uint64_t, uint64); +DECLARE_RECONF_OPT(int64_t, int64); +DECLARE_RECONF_OPT(uint32_t, uint32); +DECLARE_RECONF_OPT(int32_t, int32); +DECLARE_RECONF_OPT(uint64_t, size); +DECLARE_RECONF_OPT(uint64_t, size_uint64); +DECLARE_RECONF_OPT(double, percent); +DECLARE_RECONF_OPT(double, percent_or_size); +DECLARE_RECONF_OPT(gf_boolean_t, bool); +DECLARE_RECONF_OPT(xlator_t *, xlator); +DECLARE_RECONF_OPT(char *, path); +DECLARE_RECONF_OPT(double, double); +DECLARE_RECONF_OPT(uint32_t, time); + +#define DEFINE_RECONF_OPT(type_t, type, conv) \ + int xlator_option_reconf_##type(xlator_t *this, dict_t *options, \ + char *key, type_t *val_p) \ + { \ + int ret = 0; \ + volume_option_t *opt = NULL; \ + char *def_value = NULL; \ + char *set_value = NULL; \ + char *value = NULL; \ + xlator_t *old_THIS = NULL; \ + \ + opt = xlator_volume_option_get(this, key); \ + if (!opt) { \ + gf_msg(this->name, GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ENTRY, \ + "unknown option: %s", key); \ + ret = -1; \ + return ret; \ + } \ + def_value = opt->default_value; \ + ret = dict_get_str(options, key, &set_value); \ + \ + if (def_value) \ + value = def_value; \ + if (set_value) \ + value = set_value; \ + if (!value) { \ + gf_msg_trace(this->name, 0, "option %s not set", key); \ + *val_p = (type_t)0; \ + return 0; \ + } \ + if (value == def_value) { \ + gf_msg_trace(this->name, 0, "option %s using default value %s", \ + key, value); \ + } else { \ + gf_msg(this->name, GF_LOG_INFO, 0, 0, \ + "option %s using set value %s", key, value); \ + } \ + old_THIS = THIS; \ + THIS = this; \ + ret = conv(value, val_p); \ + THIS = old_THIS; \ + if (ret) \ + return ret; \ + ret = xlator_option_validate(this, key, value, opt, NULL); \ + return ret; \ + } + +#define GF_OPTION_RECONF(key, val, opt, type, err_label) \ + do { \ + int val_ret = 0; \ + val_ret = xlator_option_reconf_##type(THIS, opt, key, &(val)); \ + if (val_ret) \ + goto err_label; \ + } while (0) + +#endif /* !_OPTIONS_H */ diff --git a/libglusterfs/src/glusterfs/parse-utils.h b/libglusterfs/src/glusterfs/parse-utils.h new file mode 100644 index 00000000000..8653b9dd180 --- /dev/null +++ b/libglusterfs/src/glusterfs/parse-utils.h @@ -0,0 +1,50 @@ +/* + Copyright 2014-present Facebook. All Rights Reserved + + This file is part of GlusterFS. + + Author : + Shreyas Siravara <shreyas.siravara@gmail.com> + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _PARSE_UTILS_H +#define _PARSE_UTILS_H + +#include <regex.h> + +#define GF_PARSE "parse-utils" + +struct parser { + regex_t preg; /* Compiled regex */ + regmatch_t pmatch[1]; /* The match */ + char *complete_str; /* The string we are parsing */ + char *regex; /* Regex used to parse the string */ + char *_rstr; /* Temp string to hold offsets */ +}; + +/* Initializes some of the parsers variables */ +struct parser * +parser_init(const char *regex); + +/* Sets the string to parse */ +int +parser_set_string(struct parser *parser, const char *complete_str); + +/* Frees memory used by the string after all matches are found */ +int +parser_unset_string(struct parser *parser); + +/* Free memory used by the parser */ +void +parser_deinit(struct parser *ptr); + +/* Get the next matching string */ +char * +parser_get_next_match(struct parser *parser); + +#endif /* _PARSE_UTILS_H */ diff --git a/libglusterfs/src/glusterfs/quota-common-utils.h b/libglusterfs/src/glusterfs/quota-common-utils.h new file mode 100644 index 00000000000..0096e340756 --- /dev/null +++ b/libglusterfs/src/glusterfs/quota-common-utils.h @@ -0,0 +1,68 @@ +/* + Copyright (c) 2015 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _QUOTA_COMMON_UTILS_H +#define _QUOTA_COMMON_UTILS_H + +#include "glusterfs/iatt.h" + +#define GF_QUOTA_CONF_VERSION 1.2 +#define QUOTA_CONF_HEADER "GlusterFS Quota conf | version: v1.2\n" +#define QUOTA_CONF_HEADER_1_1 "GlusterFS Quota conf | version: v1.1\n" + +typedef enum { + GF_QUOTA_CONF_TYPE_USAGE = 1, + GF_QUOTA_CONF_TYPE_OBJECTS +} gf_quota_conf_type_t; + +struct _quota_limits { + int64_t hl; + int64_t sl; +} __attribute__((__packed__)); +typedef struct _quota_limits quota_limits_t; + +struct _quota_meta { + int64_t size; + int64_t file_count; + int64_t dir_count; +} __attribute__((__packed__)); +typedef struct _quota_meta quota_meta_t; + +gf_boolean_t +quota_meta_is_null(const quota_meta_t *meta); + +int32_t +quota_data_to_meta(data_t *data, quota_meta_t *meta); + +int32_t +quota_dict_get_inode_meta(dict_t *dict, char *key, const int keylen, + quota_meta_t *meta); + +int32_t +quota_dict_get_meta(dict_t *dict, char *key, const int keylen, + quota_meta_t *meta); + +int32_t +quota_dict_set_meta(dict_t *dict, char *key, const quota_meta_t *meta, + ia_type_t ia_type); + +int32_t +quota_conf_read_header(int fd, char *buf); + +int32_t +quota_conf_read_version(int fd, float *version); + +int32_t +quota_conf_read_gfid(int fd, void *buf, char *type, float version); + +int32_t +quota_conf_skip_header(int fd); + +#endif /* _QUOTA_COMMON_UTILS_H */ diff --git a/libglusterfs/src/glusterfs/rbthash.h b/libglusterfs/src/glusterfs/rbthash.h new file mode 100644 index 00000000000..3327ebf73c5 --- /dev/null +++ b/libglusterfs/src/glusterfs/rbthash.h @@ -0,0 +1,77 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef __RBTHASH_TABLE_H_ +#define __RBTHASH_TABLE_H_ +#include "rb.h" +#include "glusterfs/locking.h" +#include "glusterfs/mem-pool.h" +#include "glusterfs/logging.h" +#include "glusterfs/common-utils.h" +#include "glusterfs/list.h" + +#include <pthread.h> + +#define GF_RBTHASH_MEMPOOL 16384 // 1048576 +#define GF_RBTHASH "rbthash" + +struct rbthash_bucket { + struct rb_table *bucket; + gf_lock_t bucketlock; +}; + +typedef struct rbthash_entry { + void *data; + void *key; + int keylen; + uint32_t keyhash; + struct list_head list; +} rbthash_entry_t; + +typedef uint32_t (*rbt_hasher_t)(void *data, int len); +typedef void (*rbt_data_destroyer_t)(void *data); +typedef void (*rbt_traverse_t)(void *data, void *mydata); + +typedef struct rbthash_table { + int size; + int numbuckets; + struct mem_pool *entrypool; + gf_lock_t tablelock; + struct rbthash_bucket *buckets; + rbt_hasher_t hashfunc; + rbt_data_destroyer_t dfunc; + gf_boolean_t pool_alloced; + struct list_head list; +} rbthash_table_t; + +extern rbthash_table_t * +rbthash_table_init(glusterfs_ctx_t *ctx, int buckets, rbt_hasher_t hfunc, + rbt_data_destroyer_t dfunc, unsigned long expected_entries, + struct mem_pool *entrypool); + +extern int +rbthash_insert(rbthash_table_t *tbl, void *data, void *key, int keylen); + +extern void * +rbthash_get(rbthash_table_t *tbl, void *key, int keylen); + +extern void * +rbthash_remove(rbthash_table_t *tbl, void *key, int keylen); + +extern void * +rbthash_replace(rbthash_table_t *tbl, void *key, int keylen, void *newdata); + +extern void +rbthash_table_destroy(rbthash_table_t *tbl); + +extern void +rbthash_table_traverse(rbthash_table_t *tbl, rbt_traverse_t traverse, + void *mydata); +#endif diff --git a/libglusterfs/src/glusterfs/refcount.h b/libglusterfs/src/glusterfs/refcount.h new file mode 100644 index 00000000000..cf922dabb05 --- /dev/null +++ b/libglusterfs/src/glusterfs/refcount.h @@ -0,0 +1,101 @@ +/* + Copyright (c) 2015 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _REFCOUNT_H +#define _REFCOUNT_H + +/* check for compiler support for __sync_*_and_fetch() + * + * a more comprehensive feature test is shown at + * http://lists.iptel.org/pipermail/semsdev/2010-October/005075.html + * this is sufficient for RHEL5 i386 builds + */ +#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) && \ + !defined(__i386__) +#undef REFCOUNT_NEEDS_LOCK +#else +#define REFCOUNT_NEEDS_LOCK +#include "glusterfs/locking.h" +#endif /* compiler support for __sync_*_and_fetch() */ + +typedef void (*gf_ref_release_t)(void *data); + +struct _gf_ref { +#ifdef REFCOUNT_NEEDS_LOCK + gf_lock_t lk; /* lock for atomically adjust cnt */ +#endif + unsigned int cnt; /* number of users, free on 0 */ + + gf_ref_release_t release; /* cleanup when cnt == 0 */ + void *data; /* parameter passed to release() */ +}; +typedef struct _gf_ref gf_ref_t; + +/* _gf_ref_get -- increase the refcount + * + * @return: greater then 0 when a reference was taken, 0 when not + */ +void * +_gf_ref_get(gf_ref_t *ref); + +/* _gf_ref_put -- decrease the refcount + * + * @return: greater then 0 when there are still references, 0 when cleanup + * should be done, gf_ref_release_t is called on cleanup + */ +unsigned int +_gf_ref_put(gf_ref_t *ref); + +/* _gf_ref_init -- initialize an embedded refcount object + * + * @release: function to call when the refcount == 0 + * @data: parameter to be passed to @release + */ +void +_gf_ref_init(gf_ref_t *ref, gf_ref_release_t release, void *data); + +/* + * Strong suggestion to use the simplified GF_REF_* API. + */ + +/* GF_REF_DECL -- declaration to put inside your structure + * + * Example: + * struct my_struct { + * GF_REF_DECL; + * + * ... // additional members + * }; + */ +#define GF_REF_DECL gf_ref_t _ref + +/* GF_REF_INIT -- initialize a GF_REF_DECL structure + * + * @p: allocated structure with GF_REF_DECL + * @d: destructor to call once refcounting reaches 0 + * + * Sets the refcount to 1. + */ +#define GF_REF_INIT(p, d) _gf_ref_init(&(p)->_ref, (gf_ref_release_t)d, p) + +/* GF_REF_GET -- increase the refcount of a GF_REF_DECL structure + * + * @return: greater then 0 when a reference was taken, 0 when not + */ +#define GF_REF_GET(p) _gf_ref_get(&(p)->_ref) + +/* GF_REF_PUT -- decrease the refcount of a GF_REF_DECL structure + * + * @return: greater then 0 when there are still references, 0 when cleanup + * should be done, gf_ref_release_t is called on cleanup + */ +#define GF_REF_PUT(p) _gf_ref_put(&(p)->_ref) + +#endif /* _REFCOUNT_H */ diff --git a/libglusterfs/src/glusterfs/revision.h b/libglusterfs/src/glusterfs/revision.h new file mode 100644 index 00000000000..3c404d30e78 --- /dev/null +++ b/libglusterfs/src/glusterfs/revision.h @@ -0,0 +1 @@ +#define GLUSTERFS_REPOSITORY_REVISION "git://git.gluster.org/glusterfs.git" diff --git a/libglusterfs/src/glusterfs/rot-buffs.h b/libglusterfs/src/glusterfs/rot-buffs.h new file mode 100644 index 00000000000..9dc227d58b8 --- /dev/null +++ b/libglusterfs/src/glusterfs/rot-buffs.h @@ -0,0 +1,125 @@ +/* + Copyright (c) 2008-2015 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef __ROT_BUFFS_H +#define __ROT_BUFFS_H + +#include "glusterfs/list.h" +#include "glusterfs/locking.h" +#include "glusterfs/common-utils.h" + +typedef struct rbuf_iovec { + struct iovec iov; + + struct list_head list; +} rbuf_iovec_t; + +#define RBUF_IOVEC_SIZE (sizeof(rbuf_iovec_t)) + +typedef struct rbuf_list { + gf_lock_t c_lock; + + pthread_mutex_t b_lock; /* protects this structure */ + pthread_cond_t b_cond; /* signal for writer completion */ + + gf_boolean_t awaiting; + + unsigned long long pending; /* pending writers */ + unsigned long long completed; /* completed writers */ + + rbuf_iovec_t *rvec; /* currently used IO vector */ + + struct list_head veclist; /* list of attached rbuf_iov */ + + unsigned long long used; /* consumable entries + attached in ->veclist */ + unsigned long long total; /* total entries in ->veclist (used + during deallocation) */ + + unsigned long seq[2]; /* if interested, this whould store + the start sequence number and the + range */ + + struct list_head list; /* attachment to rbuf_t */ +} rbuf_list_t; + +struct rlist_iter { + struct list_head veclist; + + unsigned long long iter; +}; + +#define RLIST_ENTRY_COUNT(rlist) rlist->used + +#define rlist_iter_init(riter, rlist) \ + do { \ + (riter)->iter = rlist->used; \ + (riter)->veclist = rlist->veclist; \ + } while (0) + +#define rvec_for_each_entry(pos, riter) \ + for (pos = list_entry((riter)->veclist.next, typeof(*pos), list); \ + (riter)->iter > 0; \ + pos = list_entry(pos->list.next, typeof(*pos), list), \ + --((riter)->iter)) + +/** + * Sequence number assignment routine is called during buffer + * switch under rbuff ->lock. + */ +typedef void(sequence_fn)(rbuf_list_t *, void *); + +#define RLIST_STORE_SEQ(rlist, start, range) \ + do { \ + rlist->seq[0] = start; \ + rlist->seq[1] = range; \ + } while (0) + +#define RLIST_GET_SEQ(rlist, start, range) \ + do { \ + start = rlist->seq[0]; \ + range = rlist->seq[1]; \ + } while (0) + +typedef struct rbuf { + gf_lock_t lock; /* protects "current" rlist */ + + rbuf_list_t *current; /* cached pointer to first free rlist */ + + struct list_head freelist; +} rbuf_t; + +typedef enum { + RBUF_CONSUMABLE = 1, + RBUF_BUSY, + RBUF_EMPTY, + RBUF_WOULD_STARVE, +} rlist_retval_t; + +/* Initialization/Destruction */ +rbuf_t * +rbuf_init(int); +void +rbuf_dtor(rbuf_t *); + +/* Producer API */ +char * +rbuf_reserve_write_area(rbuf_t *, size_t, void **); +int +rbuf_write_complete(void *); + +/* Consumer API */ +int +rbuf_get_buffer(rbuf_t *, void **, sequence_fn *, void *); +int +rbuf_wait_for_completion(rbuf_t *, void *, void (*)(rbuf_list_t *, void *), + void *); + +#endif diff --git a/libglusterfs/src/glusterfs/run.h b/libglusterfs/src/glusterfs/run.h new file mode 100644 index 00000000000..76af95fd27f --- /dev/null +++ b/libglusterfs/src/glusterfs/run.h @@ -0,0 +1,207 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef __RUN_H__ +#define __RUN_H__ + +#define RUN_PIPE -1 + +struct runner { + char **argv; + unsigned argvlen; + int runerr; + pid_t chpid; + int chfd[3]; + FILE *chio[3]; +}; + +typedef struct runner runner_t; + +/** + * initialize runner_t instance. + * + * @param runner pointer to runner_t instance + */ +void +runinit(runner_t *runner); + +/** + * get FILE pointer to which child's stdio is redirected. + * + * @param runner pointer to runner_t instance + * @param fd specifies which standard file descriptor is + * is asked for + * + * @see runner_redir() + */ +FILE * +runner_chio(runner_t *runner, int fd); + +/** + * add an argument. + * + * 'arg' is duplicated. + * + * Errors are deferred, no error handling is necessary. + * + * @param runner pointer to runner_t instance + * @param arg command line argument + */ +void +runner_add_arg(runner_t *runner, const char *arg); + +/** + * add a sequence of arguments. + * + * Variadic function, calls runner_add_arg() on each vararg. + * Argument sequence MUST be NULL terminated. + * + * Errors are deferred, no error handling is necessary. + * + * @param runner pointer to runner_t instance + * + * @see runner_add_arg() + */ +void +runner_add_args(runner_t *runner, ...); + +/** + * add an argument with printf style formatting. + * + * Errors are deferred, no error handling is necessary. + * + * @param runner pointer to runner_t instance + * @param format printf style format specifier + */ +void +runner_argprintf(runner_t *runner, const char *format, ...) + __attribute__((__format__(__printf__, 2, 3))); +/** + * log a message about the command to be run. + * + * @param runner pointer to runner_t instance + * + * @param dom log domain + * @param lvl log level + * @param msg message with which the command is prefixed in log + * + * @see gf_log() + */ +void +runner_log(runner_t *runner, const char *dom, gf_loglevel_t lvl, + const char *msg); + +/** + * set up redirection for child. + * + * @param runner pointer to runner_t instance + * + * @param fd fd of child to redirect (0, 1, or 2) + * @param tgt_fd fd on parent side to redirect to. + * Note that runner_end() will close tgt_fd, + * if user needs it in another context it should + * be dup'd beforehand. + * RUN_PIPE can be used for requiring a + * pipe from child to parent. The FILE + * created for this purpose will be + * accessible via runner_chio() (after + * runner_start() has been invoked). + * + * @see runner_start(), dup(2), runner_chio(), runner_start() + */ +void +runner_redir(runner_t *runner, int fd, int tgt_fd); + +/** + * spawn child with accumulated arg list. + * + * @param runner pointer to runner_t instance + * + * @return 0 on successful spawn + * -1 on failure (either due to earlier errors or execve(2) failing) + * + * @see runner_cout() + */ +int +runner_start(runner_t *runner); + +/** + * complete operation and free resources. + * + * If child exists, waits for it. Redirections will be closed. + * Dynamically allocated memory shall be freed. + * + * @param runner pointer to runner_t instance + * + * @return 0 if child terminated successfully + * -1 if there is no running child + * n > 0 if child failed; value to be interpreted as status + * in waitpid(2) + * + * @see waitpid(2) + */ +int +runner_end(runner_t *runner); + +/** + * variant of runner_end() which does not free internal data + * so that the runner instance can be run again. + * + * @see runner_end() + */ +int +runner_end_reuse(runner_t *runner); + +/** + * spawn and child, take it to completion and free resources. + * + * Essentially it's a concatenation of runner_start() and runner_end() + * with simplified return semantics. + * + * @param runner pointer to runner_t instance + * + * @return 0 on success + * -1 on failuire + * + * @see runner_start(), runner_end() + */ +int +runner_run(runner_t *runner); + +/** + * variant for runner_run() which does not wait for acknowledgement + * from child, and always assumes it succeeds. + */ +int +runner_run_nowait(runner_t *runner); + +/** + * variant of runner_run() which does not free internal data + * so that the runner instance can be run again. + * + * @see runner_run() + */ +int +runner_run_reuse(runner_t *runner); + +/** + * run a command with args. + * + * Variadic function, child process is spawned with + * the given sequence of args and waited for. + * Argument sequence MUST be NULL terminated. + * + * @return 0 on success + * -1 on failure + */ +int +runcmd(const char *arg, ...); + +#endif diff --git a/libglusterfs/src/glusterfs/stack.h b/libglusterfs/src/glusterfs/stack.h new file mode 100644 index 00000000000..17585508a22 --- /dev/null +++ b/libglusterfs/src/glusterfs/stack.h @@ -0,0 +1,547 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +/* + This file defines MACROS and static inlines used to emulate a function + call over asynchronous communication with remote server +*/ + +#ifndef _STACK_H +#define _STACK_H + +struct _call_stack; +typedef struct _call_stack call_stack_t; +struct _call_frame; +typedef struct _call_frame call_frame_t; +struct call_pool; +typedef struct call_pool call_pool_t; + +#include <sys/time.h> + +#include "glusterfs/xlator.h" +#include "glusterfs/dict.h" +#include "glusterfs/list.h" +#include "glusterfs/common-utils.h" +#include "glusterfs/lkowner.h" +#include "glusterfs/client_t.h" +#include "glusterfs/libglusterfs-messages.h" +#include "glusterfs/timespec.h" + +#define NFS_PID 1 +#define LOW_PRIO_PROC_PID -1 + +#define STACK_ERR_XL_NAME(stack) (stack->err_xl ? stack->err_xl->name : "-") +#define STACK_CLIENT_NAME(stack) \ + (stack->client ? stack->client->client_uid : "-") + +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, + ...); + +struct call_pool { + union { + struct list_head all_frames; + struct { + call_stack_t *next_call; + call_stack_t *prev_call; + } all_stacks; + }; + int64_t cnt; + gf_atomic_t total_count; + gf_lock_t lock; + struct mem_pool *frame_mem_pool; + struct mem_pool *stack_mem_pool; +}; + +struct _call_frame { + call_stack_t *root; /* stack root */ + call_frame_t *parent; /* previous BP */ + struct list_head frames; + void *local; /* local variables */ + xlator_t *this; /* implicit object */ + ret_fn_t ret; /* op_return address */ + int32_t ref_count; + gf_lock_t lock; + void *cookie; /* unique cookie */ + gf_boolean_t complete; + + glusterfs_fop_t op; + struct timespec begin; /* when this frame was created */ + struct timespec end; /* when this frame completed */ + const char *wind_from; + const char *wind_to; + const char *unwind_from; + const char *unwind_to; +}; + +struct _ns_info { + uint32_t hash; /* Hash of the namespace from SuperFastHash */ + gf_boolean_t found; /* Set to true if we found a namespace */ +}; + +typedef struct _ns_info ns_info_t; + +#define SMALL_GROUP_COUNT 128 + +struct _call_stack { + union { + struct list_head all_frames; + struct { + call_stack_t *next_call; + call_stack_t *prev_call; + }; + }; + call_pool_t *pool; + gf_lock_t stack_lock; + client_t *client; + uint64_t unique; + void *state; /* pointer to request state */ + uid_t uid; + gid_t gid; + pid_t pid; + char identifier[UNIX_PATH_MAX]; + uint16_t ngrps; + uint32_t groups_small[SMALL_GROUP_COUNT]; + uint32_t *groups_large; + uint32_t *groups; + gf_lkowner_t lk_owner; + glusterfs_ctx_t *ctx; + + struct list_head myframes; /* List of call_frame_t that go + to make the call stack */ + + int32_t op; + int8_t type; + struct timespec tv; + xlator_t *err_xl; + int32_t error; + + uint32_t flags; /* use it wisely, think of it as a mechanism to + send information over the wire too */ + struct timespec ctime; /* timestamp, most probably set at + creation of stack. */ + + ns_info_t ns_info; +}; + +/* call_stack flags field users */ +#define MDATA_CTIME (1 << 0) +#define MDATA_MTIME (1 << 1) +#define MDATA_ATIME (1 << 2) +#define MDATA_PAR_CTIME (1 << 3) +#define MDATA_PAR_MTIME (1 << 4) +#define MDATA_PAR_ATIME (1 << 5) + +#define frame_set_uid_gid(frm, u, g) \ + do { \ + if (frm) { \ + (frm)->root->uid = u; \ + (frm)->root->gid = g; \ + (frm)->root->ngrps = 0; \ + } \ + } while (0); + +struct xlator_fops; +void +gf_update_latency(call_frame_t *frame); + +static inline void +FRAME_DESTROY(call_frame_t *frame) +{ + void *local = NULL; + + if (frame->root->ctx->measure_latency) + gf_update_latency(frame); + + list_del_init(&frame->frames); + if (frame->local) { + local = frame->local; + frame->local = NULL; + } + + LOCK_DESTROY(&frame->lock); + mem_put(frame); + + if (local) + mem_put(local); +} + +static inline void +STACK_DESTROY(call_stack_t *stack) +{ + call_frame_t *frame = NULL; + call_frame_t *tmp = NULL; + + LOCK(&stack->pool->lock); + { + list_del_init(&stack->all_frames); + stack->pool->cnt--; + } + UNLOCK(&stack->pool->lock); + + LOCK_DESTROY(&stack->stack_lock); + + list_for_each_entry_safe(frame, tmp, &stack->myframes, frames) + { + FRAME_DESTROY(frame); + } + + GF_FREE(stack->groups_large); + + mem_put(stack); +} + +static inline void +STACK_RESET(call_stack_t *stack) +{ + call_frame_t *frame = NULL; + call_frame_t *tmp = NULL; + call_frame_t *last = NULL; + struct list_head toreset = {0}; + + INIT_LIST_HEAD(&toreset); + + /* We acquire call_pool->lock only to remove the frames from this stack + * to preserve atomicity. This synchronizes across concurrent requests + * like statedump, STACK_DESTROY etc. */ + + LOCK(&stack->pool->lock); + { + last = list_last_entry(&stack->myframes, call_frame_t, frames); + list_del_init(&last->frames); + list_splice_init(&stack->myframes, &toreset); + list_add(&last->frames, &stack->myframes); + } + UNLOCK(&stack->pool->lock); + + list_for_each_entry_safe(frame, tmp, &toreset, frames) + { + FRAME_DESTROY(frame); + } +} + +#define FRAME_SU_DO(frm, local_type) \ + do { \ + local_type *__local = (frm)->local; \ + __local->uid = frm->root->uid; \ + __local->gid = frm->root->gid; \ + __local->pid = frm->root->pid; \ + frm->root->uid = 0; \ + frm->root->gid = 0; \ + frm->root->pid = GF_CLIENT_PID_NO_ROOT_SQUASH; \ + } while (0); + +#define FRAME_SU_UNDO(frm, local_type) \ + do { \ + local_type *__local = (frm)->local; \ + frm->root->uid = __local->uid; \ + frm->root->gid = __local->gid; \ + frm->root->pid = __local->pid; \ + } while (0); + +/* NOTE: make sure to keep this as an macro, mainly because, we need 'fn' + field here to be the proper fn ptr, so its address is valid entry in + 'xlator_fops' struct. + To understand this, check the `xlator.h:struct xlator_fops`, and then + see a STACK_WIND call, which generally calls `subvol->fops->fop`, so + the address offset should give the index */ + +/* +1 is required as 0 means NULL fop, and we don't have a variable for it */ +#define get_fop_index_from_fn(xl, fn) \ + (1 + (((long)&(fn) - (long)&((xl)->fops->stat)) / sizeof(void *))) + +/* NOTE: the above reason holds good here too. But notice that we are getting + the base address of the 'stat' fop, which is the first entry in the fop + structure. All we need to do is move as much as 'idx' fields, and get the + actual pointer from that field. */ + +static inline void * +get_the_pt_fop(void *base_fop, int fop_idx) +{ + void *target_addr = (base_fop + ((fop_idx - 1) * sizeof(void *))); + /* all below type casting is for not getting warning. */ + return (void *)*(unsigned long *)target_addr; +} + +/* make a call without switching frames */ +#define STACK_WIND_TAIL(frame, obj, fn, params...) \ + do { \ + xlator_t *old_THIS = NULL; \ + xlator_t *next_xl = obj; \ + typeof(fn) next_xl_fn = fn; \ + int opn = get_fop_index_from_fn((next_xl), (fn)); \ + \ + frame->this = next_xl; \ + frame->wind_to = #fn; \ + old_THIS = THIS; \ + THIS = next_xl; \ + gf_msg_trace("stack-trace", 0, \ + "stack-address: %p, " \ + "winding from %s to %s", \ + frame->root, old_THIS->name, THIS->name); \ + /* Need to capture counts at leaf node */ \ + if (!next_xl->pass_through && !next_xl->children) { \ + GF_ATOMIC_INC(next_xl->stats.total.metrics[opn].fop); \ + GF_ATOMIC_INC(next_xl->stats.interval.metrics[opn].fop); \ + GF_ATOMIC_INC(next_xl->stats.total.count); \ + GF_ATOMIC_INC(next_xl->stats.interval.count); \ + } \ + \ + if (next_xl->pass_through) { \ + next_xl_fn = get_the_pt_fop(&next_xl->pass_through_fops->stat, \ + opn); \ + } \ + next_xl_fn(frame, next_xl, params); \ + THIS = old_THIS; \ + } while (0) + +/* make a call */ +#define STACK_WIND(frame, rfn, obj, fn, params...) \ + STACK_WIND_COMMON(frame, rfn, 0, NULL, obj, fn, params) + +/* make a call with a cookie */ +#define STACK_WIND_COOKIE(frame, rfn, cky, obj, fn, params...) \ + STACK_WIND_COMMON(frame, rfn, 1, cky, obj, fn, params) + +/* Cookie passed as the argument can be NULL (ptr) or 0 (int). Hence we + have to have a mechanism to separate out the two STACK_WIND formats. + Needed a common macro, as other than for cookie, all the other code + is common across. + */ +#define STACK_WIND_COMMON(frame, rfn, has_cookie, cky, obj, fn, params...) \ + do { \ + call_frame_t *_new = NULL; \ + xlator_t *old_THIS = NULL; \ + typeof(fn) next_xl_fn = fn; \ + \ + _new = mem_get0(frame->root->pool->frame_mem_pool); \ + if (!_new) { \ + break; \ + } \ + typeof(fn##_cbk) tmp_cbk = rfn; \ + _new->root = frame->root; \ + _new->this = obj; \ + _new->ret = (ret_fn_t)tmp_cbk; \ + _new->parent = frame; \ + /* (void *) is required for avoiding gcc warning */ \ + _new->cookie = ((has_cookie == 1) ? (void *)(cky) : (void *)_new); \ + _new->wind_from = __FUNCTION__; \ + _new->wind_to = #fn; \ + _new->unwind_to = #rfn; \ + LOCK_INIT(&_new->lock); \ + LOCK(&frame->root->stack_lock); \ + { \ + list_add(&_new->frames, &frame->root->myframes); \ + frame->ref_count++; \ + } \ + UNLOCK(&frame->root->stack_lock); \ + fn##_cbk = rfn; \ + old_THIS = THIS; \ + THIS = obj; \ + gf_msg_trace("stack-trace", 0, \ + "stack-address: %p, " \ + "winding from %s to %s", \ + frame->root, old_THIS->name, THIS->name); \ + if (obj->ctx->measure_latency) \ + timespec_now(&_new->begin); \ + _new->op = get_fop_index_from_fn((_new->this), (fn)); \ + if (!obj->pass_through) { \ + GF_ATOMIC_INC(obj->stats.total.metrics[_new->op].fop); \ + GF_ATOMIC_INC(obj->stats.interval.metrics[_new->op].fop); \ + GF_ATOMIC_INC(obj->stats.total.count); \ + GF_ATOMIC_INC(obj->stats.interval.count); \ + } else { \ + /* we want to get to the actual fop to call */ \ + next_xl_fn = get_the_pt_fop(&obj->pass_through_fops->stat, \ + _new->op); \ + } \ + next_xl_fn(_new, obj, params); \ + THIS = old_THIS; \ + } while (0) + +#define STACK_UNWIND STACK_UNWIND_STRICT + +/* return from function in type-safe way */ +#define STACK_UNWIND_STRICT(fop, frame, op_ret, op_errno, params...) \ + do { \ + fop_##fop##_cbk_t fn = NULL; \ + call_frame_t *_parent = NULL; \ + xlator_t *old_THIS = NULL; \ + \ + if (!frame) { \ + gf_msg("stack", GF_LOG_CRITICAL, 0, LG_MSG_FRAME_ERROR, "!frame"); \ + break; \ + } \ + if ((op_ret) < 0) { \ + gf_msg_debug("stack-trace", op_errno, \ + "stack-address: %p, " \ + "%s returned %d error: %s", \ + frame->root, THIS->name, (int32_t)(op_ret), \ + strerror(op_errno)); \ + } else { \ + gf_msg_trace("stack-trace", 0, \ + "stack-address: %p, " \ + "%s returned %d", \ + frame->root, THIS->name, (int32_t)(op_ret)); \ + } \ + fn = (fop_##fop##_cbk_t)frame->ret; \ + _parent = frame->parent; \ + LOCK(&frame->root->stack_lock); \ + { \ + _parent->ref_count--; \ + if ((op_ret) < 0 && (op_errno) != frame->root->error) { \ + frame->root->err_xl = frame->this; \ + frame->root->error = (op_errno); \ + } else if ((op_ret) == 0) { \ + frame->root->err_xl = NULL; \ + frame->root->error = 0; \ + } \ + } \ + UNLOCK(&frame->root->stack_lock); \ + old_THIS = THIS; \ + THIS = _parent->this; \ + frame->complete = _gf_true; \ + frame->unwind_from = __FUNCTION__; \ + if (frame->this->ctx->measure_latency) { \ + timespec_now(&frame->end); \ + /* required for top most xlator */ \ + if (_parent->ret == NULL) \ + timespec_now(&_parent->end); \ + } \ + if (op_ret < 0) { \ + GF_ATOMIC_INC(THIS->stats.total.metrics[frame->op].cbk); \ + GF_ATOMIC_INC(THIS->stats.interval.metrics[frame->op].cbk); \ + } \ + fn(_parent, frame->cookie, _parent->this, op_ret, op_errno, params); \ + THIS = old_THIS; \ + } while (0) + +static inline int +call_stack_alloc_groups(call_stack_t *stack, int ngrps) +{ + if (ngrps <= SMALL_GROUP_COUNT) { + stack->groups = stack->groups_small; + } else { + stack->groups_large = GF_CALLOC(ngrps, sizeof(gid_t), + gf_common_mt_groups_t); + if (!stack->groups_large) + return -1; + stack->groups = stack->groups_large; + } + + stack->ngrps = ngrps; + + return 0; +} + +static inline int +call_frames_count(call_stack_t *call_stack) +{ + call_frame_t *pos; + int32_t count = 0; + + if (!call_stack) + return count; + + list_for_each_entry(pos, &call_stack->myframes, frames) count++; + + return count; +} + +static inline call_frame_t * +copy_frame(call_frame_t *frame) +{ + call_stack_t *newstack = NULL; + call_stack_t *oldstack = NULL; + call_frame_t *newframe = NULL; + + if (!frame) { + return NULL; + } + + newstack = mem_get0(frame->root->pool->stack_mem_pool); + if (newstack == NULL) { + return NULL; + } + + INIT_LIST_HEAD(&newstack->myframes); + + newframe = mem_get0(frame->root->pool->frame_mem_pool); + if (!newframe) { + mem_put(newstack); + return NULL; + } + + newframe->this = frame->this; + newframe->root = newstack; + INIT_LIST_HEAD(&newframe->frames); + list_add(&newframe->frames, &newstack->myframes); + + oldstack = frame->root; + + newstack->uid = oldstack->uid; + newstack->gid = oldstack->gid; + newstack->pid = oldstack->pid; + newstack->op = oldstack->op; + newstack->type = oldstack->type; + newstack->ctime = oldstack->ctime; + newstack->flags = oldstack->flags; + if (call_stack_alloc_groups(newstack, oldstack->ngrps) != 0) { + mem_put(newstack); + return NULL; + } + if (!oldstack->groups) { + gf_msg_debug("stack", EINVAL, "groups is null (ngrps: %d)", + oldstack->ngrps); + /* Considering 'groups' is NULL, set ngrps to 0 */ + oldstack->ngrps = 0; + + if (oldstack->groups_large) + oldstack->groups = oldstack->groups_large; + else + oldstack->groups = oldstack->groups_small; + } + newstack->ngrps = oldstack->ngrps; + memcpy(newstack->groups, oldstack->groups, sizeof(gid_t) * oldstack->ngrps); + newstack->unique = oldstack->unique; + newstack->pool = oldstack->pool; + newstack->lk_owner = oldstack->lk_owner; + newstack->ctx = oldstack->ctx; + + if (newstack->ctx->measure_latency) { + timespec_now(&newstack->tv); + memcpy(&newframe->begin, &newstack->tv, sizeof(newstack->tv)); + } + + LOCK_INIT(&newframe->lock); + LOCK_INIT(&newstack->stack_lock); + + LOCK(&oldstack->pool->lock); + { + list_add(&newstack->all_frames, &oldstack->all_frames); + newstack->pool->cnt++; + } + UNLOCK(&oldstack->pool->lock); + GF_ATOMIC_INC(newstack->pool->total_count); + + return newframe; +} + +void +call_stack_set_groups(call_stack_t *stack, int ngrps, gid_t **groupbuf_p); +void +gf_proc_dump_pending_frames(call_pool_t *call_pool); +void +gf_proc_dump_pending_frames_to_dict(call_pool_t *call_pool, dict_t *dict); +call_frame_t * +create_frame(xlator_t *xl, call_pool_t *pool); +gf_boolean_t +__is_fuse_call(call_frame_t *frame); +#endif /* _STACK_H */ diff --git a/libglusterfs/src/glusterfs/statedump.h b/libglusterfs/src/glusterfs/statedump.h new file mode 100644 index 00000000000..89d04f94587 --- /dev/null +++ b/libglusterfs/src/glusterfs/statedump.h @@ -0,0 +1,130 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef STATEDUMP_H +#define STATEDUMP_H + +#include <stdarg.h> +#include "glusterfs/inode.h" +#include "glusterfs/strfd.h" + +#define GF_DUMP_MAX_BUF_LEN 4096 + +typedef struct gf_dump_xl_options_ { + gf_boolean_t dump_priv; + gf_boolean_t dump_inode; + gf_boolean_t dump_fd; + gf_boolean_t dump_inodectx; + gf_boolean_t dump_fdctx; + gf_boolean_t dump_history; +} gf_dump_xl_options_t; + +typedef struct gf_dump_options_ { + gf_boolean_t dump_mem; + gf_boolean_t dump_iobuf; + gf_boolean_t dump_callpool; + gf_dump_xl_options_t xl_options; // options for all xlators + char *dump_path; +} gf_dump_options_t; + +extern gf_dump_options_t dump_options; + +__attribute__((__format__(__printf__, 3, 4))) static inline void +_gf_proc_dump_build_key(char *key, const char *prefix, const char *fmt, ...) +{ + va_list ap; + int32_t len; + + len = snprintf(key, GF_DUMP_MAX_BUF_LEN, "%s.", prefix); + if (len >= 0) { + va_start(ap, fmt); + len = vsnprintf(key + len, GF_DUMP_MAX_BUF_LEN - len, fmt, ap); + va_end(ap); + } + if (len < 0) { + *key = 0; + } +} + +#define gf_proc_dump_build_key(key, key_prefix, fmt...) \ + { \ + _gf_proc_dump_build_key(key, key_prefix, ##fmt); \ + } + +#define GF_PROC_DUMP_SET_OPTION(opt, val) opt = val + +#define GF_CHECK_DUMP_OPTION_ENABLED(option_dump, var, label) \ + do { \ + if (option_dump == _gf_true) { \ + var = _gf_false; \ + goto label; \ + } \ + } while (0); + +void +gf_proc_dump_init(); + +void +gf_proc_dump_fini(void); + +void +gf_proc_dump_cleanup(void); + +void +gf_proc_dump_info(int signum, glusterfs_ctx_t *ctx); + +int +gf_proc_dump_add_section(char *key, ...) + __attribute__((__format__(__printf__, 1, 2))); + +int +gf_proc_dump_write(char *key, char *value, ...) + __attribute__((__format__(__printf__, 2, 3))); + +void +inode_table_dump(inode_table_t *itable, char *prefix); + +void +inode_table_dump_to_dict(inode_table_t *itable, char *prefix, dict_t *dict); + +void +fdtable_dump(fdtable_t *fdtable, char *prefix); + +void +fdtable_dump_to_dict(fdtable_t *fdtable, char *prefix, dict_t *dict); + +void +inode_dump(inode_t *inode, char *prefix); + +void +gf_proc_dump_mem_info_to_dict(dict_t *dict); + +void +gf_proc_dump_mempool_info_to_dict(glusterfs_ctx_t *ctx, dict_t *dict); + +void +glusterd_init(int sig); + +void +gf_proc_dump_xlator_private(xlator_t *this, strfd_t *strfd); + +void +gf_proc_dump_mallinfo(strfd_t *strfd); + +void +gf_proc_dump_xlator_history(xlator_t *this, strfd_t *strfd); + +void +gf_proc_dump_xlator_meminfo(xlator_t *this, strfd_t *strfd); + +void +gf_proc_dump_xlator_profile(xlator_t *this, strfd_t *strfd); + +#endif /* STATEDUMP_H */ diff --git a/libglusterfs/src/glusterfs/store.h b/libglusterfs/src/glusterfs/store.h new file mode 100644 index 00000000000..3b3a24c38f8 --- /dev/null +++ b/libglusterfs/src/glusterfs/store.h @@ -0,0 +1,109 @@ +/* + Copyright (c) 2013 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ +#ifndef _GLUSTERD_STORE_H_ +#define _GLUSTERD_STORE_H_ + +#include "glusterfs/compat.h" +#include "glusterfs/glusterfs.h" + +struct gf_store_handle_ { + char *path; + int fd; + int tmp_fd; + FILE *read; + int locked; /* state of lockf() */ +}; + +typedef struct gf_store_handle_ gf_store_handle_t; + +struct gf_store_iter_ { + FILE *file; + char filepath[PATH_MAX]; +}; + +typedef struct gf_store_iter_ gf_store_iter_t; + +typedef enum { + GD_STORE_SUCCESS, + GD_STORE_KEY_NULL, + GD_STORE_VALUE_NULL, + GD_STORE_KEY_VALUE_NULL, + GD_STORE_EOF, + GD_STORE_ENOMEM, + GD_STORE_STAT_FAILED +} gf_store_op_errno_t; + +int32_t +gf_store_mkdir(char *path); + +int32_t +gf_store_handle_create_on_absence(gf_store_handle_t **shandle, char *path); + +int32_t +gf_store_mkstemp(gf_store_handle_t *shandle); + +int +gf_store_sync_direntry(char *path); + +int32_t +gf_store_rename_tmppath(gf_store_handle_t *shandle); + +int32_t +gf_store_unlink_tmppath(gf_store_handle_t *shandle); + +int +gf_store_read_and_tokenize(FILE *file, char *str, int size, char **iter_key, + char **iter_val, gf_store_op_errno_t *store_errno); + +int32_t +gf_store_retrieve_value(gf_store_handle_t *handle, char *key, char **value); + +int32_t +gf_store_save_value(int fd, char *key, char *value); + +int32_t +gf_store_handle_new(const char *path, gf_store_handle_t **handle); + +int +gf_store_handle_retrieve(char *path, gf_store_handle_t **handle); + +int32_t +gf_store_handle_destroy(gf_store_handle_t *handle); + +int32_t +gf_store_iter_new(gf_store_handle_t *shandle, gf_store_iter_t **iter); + +int32_t +gf_store_validate_key_value(char *storepath, char *key, char *val, + gf_store_op_errno_t *op_errno); + +int32_t +gf_store_iter_get_next(gf_store_iter_t *iter, char **key, char **value, + gf_store_op_errno_t *op_errno); + +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); + +char * +gf_store_strerror(gf_store_op_errno_t op_errno); + +int +gf_store_lock(gf_store_handle_t *sh); + +void +gf_store_unlock(gf_store_handle_t *sh); + +int +gf_store_locked_local(gf_store_handle_t *sh); + +#endif diff --git a/libglusterfs/src/glusterfs/strfd.h b/libglusterfs/src/glusterfs/strfd.h new file mode 100644 index 00000000000..861cd02e005 --- /dev/null +++ b/libglusterfs/src/glusterfs/strfd.h @@ -0,0 +1,34 @@ +/* + Copyright (c) 2014 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _STRFD_H +#define _STRFD_H + +typedef struct { + void *data; + size_t alloc_size; + size_t size; + off_t pos; +} strfd_t; + +strfd_t * +strfd_open(); + +int +strprintf(strfd_t *strfd, const char *fmt, ...) + __attribute__((__format__(__printf__, 2, 3))); + +int +strvprintf(strfd_t *strfd, const char *fmt, va_list ap); + +int +strfd_close(strfd_t *strfd); + +#endif diff --git a/libglusterfs/src/glusterfs/syncop-utils.h b/libglusterfs/src/glusterfs/syncop-utils.h new file mode 100644 index 00000000000..1f3ee403edc --- /dev/null +++ b/libglusterfs/src/glusterfs/syncop-utils.h @@ -0,0 +1,54 @@ +/* + Copyright (c) 2015, Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _SYNCOP_UTILS_H +#define _SYNCOP_UTILS_H + +typedef int (*syncop_dir_scan_fn_t)(xlator_t *subvol, gf_dirent_t *entry, + loc_t *parent, void *data); +int +syncop_ftw(xlator_t *subvol, loc_t *loc, int pid, void *data, + int (*fn)(xlator_t *subvol, gf_dirent_t *entry, loc_t *parent, + void *data)); + +int +syncop_mt_dir_scan(call_frame_t *frame, xlator_t *subvol, loc_t *loc, int pid, + void *data, syncop_dir_scan_fn_t fn, dict_t *xdata, + uint32_t max_jobs, uint32_t max_qlen); + +int +syncop_dir_scan(xlator_t *subvol, loc_t *loc, int pid, void *data, + int (*fn)(xlator_t *subvol, gf_dirent_t *entry, loc_t *parent, + void *data)); + +int +syncop_dirfd(xlator_t *subvol, loc_t *loc, fd_t **fd, int pid); + +int +syncop_is_subvol_local(xlator_t *this, loc_t *loc, gf_boolean_t *is_local); + +int +syncop_gfid_to_path(inode_table_t *itable, xlator_t *subvol, uuid_t gfid, + char **path_p); + +int +syncop_ftw_throttle(xlator_t *subvol, loc_t *loc, int pid, void *data, + int (*fn)(xlator_t *subvol, gf_dirent_t *entry, + loc_t *parent, void *data), + int count, int sleep_time); +int +syncop_inode_find(xlator_t *this, xlator_t *subvol, uuid_t gfid, + inode_t **inode, dict_t *xdata, dict_t **rsp_dict); + +int +syncop_gfid_to_path_hard(inode_table_t *itable, xlator_t *subvol, uuid_t gfid, + inode_t *inode, char **path_p, + gf_boolean_t hard_resolve); +#endif /* _SYNCOP_H */ diff --git a/libglusterfs/src/glusterfs/syncop.h b/libglusterfs/src/glusterfs/syncop.h new file mode 100644 index 00000000000..203abe92b57 --- /dev/null +++ b/libglusterfs/src/glusterfs/syncop.h @@ -0,0 +1,637 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _SYNCOP_H +#define _SYNCOP_H + +#include "glusterfs/xlator.h" +#include <sys/time.h> +#include <pthread.h> +#include <ucontext.h> + +#define SYNCENV_PROC_MAX 16 +#define SYNCENV_PROC_MIN 2 +#define SYNCPROC_IDLE_TIME 600 + +/* + * Flags for syncopctx valid elements + */ +#define SYNCOPCTX_UID 0x00000001 +#define SYNCOPCTX_GID 0x00000002 +#define SYNCOPCTX_GROUPS 0x00000004 +#define SYNCOPCTX_PID 0x00000008 +#define SYNCOPCTX_LKOWNER 0x00000010 + +struct synctask; +struct syncproc; +struct syncenv; + +typedef int (*synctask_cbk_t)(int ret, call_frame_t *frame, void *opaque); + +typedef int (*synctask_fn_t)(void *opaque); + +typedef enum { + SYNCTASK_INIT = 0, + SYNCTASK_RUN, + SYNCTASK_SUSPEND, + SYNCTASK_WAIT, + SYNCTASK_DONE, + SYNCTASK_ZOMBIE, +} synctask_state_t; + +/* for one sequential execution of @syncfn */ +struct synctask { + struct list_head all_tasks; + struct syncenv *env; + xlator_t *xl; + call_frame_t *frame; + call_frame_t *opframe; + synctask_cbk_t synccbk; + synctask_fn_t syncfn; + synctask_state_t state; + void *opaque; + void *stack; + int woken; + int slept; + int ret; + + uid_t uid; + gid_t gid; + + ucontext_t ctx; + struct syncproc *proc; + + pthread_mutex_t mutex; /* for synchronous spawning of synctask */ + pthread_cond_t cond; + int done; + + struct list_head waitq; /* can wait only "once" at a time */ + char btbuf[GF_BACKTRACE_LEN]; +}; + +struct syncproc { + pthread_t processor; + ucontext_t sched; + struct syncenv *env; + struct synctask *current; +}; + +/* hosts the scheduler thread and framework for executing synctasks */ +struct syncenv { + struct syncproc proc[SYNCENV_PROC_MAX]; + int procs; + + struct list_head runq; + int runcount; + struct list_head waitq; + int waitcount; + + 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 + so that no more synctasks are accepted*/ +}; + +typedef enum { LOCK_NULL = 0, LOCK_TASK, LOCK_THREAD } lock_type_t; + +typedef enum { + SYNC_LOCK_DEFAULT = 0, + SYNC_LOCK_RECURSIVE, /*it allows recursive locking*/ +} lock_attr_t; + +struct synclock { + pthread_mutex_t guard; /* guard the remaining members, pair @cond */ + pthread_cond_t cond; /* waiting non-synctasks */ + struct list_head waitq; /* waiting synctasks */ + volatile int lock; /* true(non zero) or false(zero), lock status */ + lock_attr_t attr; + struct synctask *owner; /* NULL if current owner is not a synctask */ + pthread_t owner_tid; + lock_type_t type; +}; +typedef struct synclock synclock_t; + +struct syncbarrier { + gf_boolean_t initialized; /*Set on successful initialization*/ + pthread_mutex_t guard; /* guard the remaining members, pair @cond */ + pthread_cond_t cond; /* waiting non-synctasks */ + struct list_head waitq; /* waiting synctasks */ + int count; /* count the number of wakes */ + int waitfor; /* no. of wakes until which task can be in + waitq before being woken up. */ +}; +typedef struct syncbarrier syncbarrier_t; + +struct syncargs { + int op_ret; + int op_errno; + struct iatt iatt1; + struct iatt iatt2; + dict_t *xattr; + struct statvfs statvfs_buf; + struct iovec *vector; + int count; + struct iobref *iobref; + char *buffer; + dict_t *xdata; + struct gf_flock flock; + struct gf_lease lease; + dict_t *dict_out; + + /* some more _cbk needs */ + uuid_t uuid; + char *errstr; + dict_t *dict; + pthread_mutex_t lock_dict; + + syncbarrier_t barrier; + + /* do not touch */ + struct synctask *task; + pthread_mutex_t mutex; + pthread_cond_t cond; + int done; + + gf_dirent_t entries; + off_t offset; + + lock_migration_info_t locklist; +}; + +struct syncopctx { + unsigned int valid; /* valid flags for elements that are set */ + uid_t uid; + gid_t gid; + int grpsize; + int ngrps; + gid_t *groups; + pid_t pid; + gf_lkowner_t lk_owner; +}; + +#define __yawn(args) \ + do { \ + args->task = synctask_get(); \ + if (args->task) \ + break; \ + pthread_mutex_init(&args->mutex, NULL); \ + pthread_cond_init(&args->cond, NULL); \ + args->done = 0; \ + } while (0) + +#define __wake(args) \ + do { \ + if (args->task) { \ + synctask_wake(args->task); \ + } else { \ + pthread_mutex_lock(&args->mutex); \ + { \ + args->done = 1; \ + pthread_cond_signal(&args->cond); \ + } \ + pthread_mutex_unlock(&args->mutex); \ + } \ + } while (0) + +#define __yield(args) \ + do { \ + if (args->task) { \ + synctask_yield(args->task); \ + } else { \ + pthread_mutex_lock(&args->mutex); \ + { \ + while (!args->done) \ + pthread_cond_wait(&args->cond, &args->mutex); \ + } \ + pthread_mutex_unlock(&args->mutex); \ + pthread_mutex_destroy(&args->mutex); \ + pthread_cond_destroy(&args->cond); \ + } \ + } while (0) + +#define SYNCOP(subvol, stb, cbk, fn_op, params...) \ + do { \ + struct synctask *task = NULL; \ + call_frame_t *frame = NULL; \ + \ + task = synctask_get(); \ + stb->task = task; \ + if (task) \ + frame = task->opframe; \ + else \ + frame = syncop_create_frame(THIS); \ + \ + if (task) { \ + frame->root->uid = task->uid; \ + frame->root->gid = task->gid; \ + } \ + \ + __yawn(stb); \ + \ + frame->op = get_fop_index_from_fn(subvol, fn_op); \ + STACK_WIND_COOKIE(frame, cbk, (void *)stb, subvol, fn_op, params); \ + \ + __yield(stb); \ + if (task) \ + STACK_RESET(frame->root); \ + else \ + STACK_DESTROY(frame->root); \ + } while (0) + +/* + * syncop_xxx() calls are executed in two ways, one is inside a synctask where + * the executing function will do 'swapcontext' and the other is without + * synctask where the executing thread is made to wait using pthread_cond_wait. + * Executing thread may change when syncop_xxx() is executed inside a synctask. + * This leads to errno_location change i.e. errno may give errno of + * non-executing thread. So errno is not touched inside a synctask execution. + * All gfapi calls are executed using the second way of executing syncop_xxx() + * where the executing thread waits using pthread_cond_wait so it is ok to set + * errno in these cases. The following macro makes syncop_xxx() behave just + * like a system call, where -1 is returned and errno is set when a failure + * occurs. + */ +#define DECODE_SYNCOP_ERR(ret) \ + do { \ + if (ret < 0) { \ + errno = -ret; \ + ret = -1; \ + } else { \ + errno = 0; \ + } \ + } while (0) + +#define SYNCENV_DEFAULT_STACKSIZE (2 * 1024 * 1024) + +struct syncenv * +syncenv_new(size_t stacksize, int procmin, int procmax); +void +syncenv_destroy(struct syncenv *); +void +syncenv_scale(struct syncenv *env); + +int +synctask_new1(struct syncenv *, size_t stacksize, synctask_fn_t, synctask_cbk_t, + call_frame_t *frame, void *); +int +synctask_new(struct syncenv *, synctask_fn_t, synctask_cbk_t, + call_frame_t *frame, void *); +struct synctask * +synctask_create(struct syncenv *, size_t stacksize, synctask_fn_t, + synctask_cbk_t, call_frame_t *, void *); +int +synctask_join(struct synctask *task); +void +synctask_wake(struct synctask *task); +void +synctask_yield(struct synctask *task); +void +synctask_waitfor(struct synctask *task, int count); + +#define synctask_barrier_init(args) syncbarrier_init(&args->barrier) +#define synctask_barrier_wait(args, n) syncbarrier_wait(&args->barrier, n) +#define synctask_barrier_wake(args) syncbarrier_wake(&args->barrier) + +int +synctask_setid(struct synctask *task, uid_t uid, gid_t gid); +#define SYNCTASK_SETID(uid, gid) synctask_setid(synctask_get(), uid, gid); + +int +syncopctx_setfsuid(void *uid); +int +syncopctx_setfsgid(void *gid); +int +syncopctx_setfsgroups(int count, const void *groups); +int +syncopctx_setfspid(void *pid); +int +syncopctx_setfslkowner(gf_lkowner_t *lk_owner); + +static inline call_frame_t * +syncop_create_frame(xlator_t *this) +{ + call_frame_t *frame = NULL; + int ngrps = -1; + struct syncopctx *opctx = NULL; + + frame = create_frame(this, this->ctx->pool); + if (!frame) + return NULL; + + frame->root->type = GF_OP_TYPE_FOP; + opctx = syncopctx_getctx(); + + if (opctx && (opctx->valid & SYNCOPCTX_PID)) + frame->root->pid = opctx->pid; + else + frame->root->pid = getpid(); + + if (opctx && (opctx->valid & SYNCOPCTX_UID)) + frame->root->uid = opctx->uid; + else + frame->root->uid = geteuid(); + + if (opctx && (opctx->valid & SYNCOPCTX_GID)) + frame->root->gid = opctx->gid; + else + frame->root->gid = getegid(); + + if (opctx && (opctx->valid & SYNCOPCTX_GROUPS)) { + ngrps = opctx->ngrps; + + if (ngrps != 0 && opctx->groups != NULL) { + if (call_stack_alloc_groups(frame->root, ngrps) != 0) { + STACK_DESTROY(frame->root); + return NULL; + } + + memcpy(frame->root->groups, opctx->groups, (sizeof(gid_t) * ngrps)); + } + } else { + ngrps = getgroups(0, 0); + if (ngrps < 0) { + STACK_DESTROY(frame->root); + return NULL; + } + + if (call_stack_alloc_groups(frame->root, ngrps) != 0) { + STACK_DESTROY(frame->root); + return NULL; + } + + if (getgroups(ngrps, frame->root->groups) < 0) { + STACK_DESTROY(frame->root); + return NULL; + } + } + + if (opctx && (opctx->valid & SYNCOPCTX_LKOWNER)) + frame->root->lk_owner = opctx->lk_owner; + + return frame; +} + +int +synclock_init(synclock_t *lock, lock_attr_t attr); +int +synclock_destroy(synclock_t *lock); +int +synclock_lock(synclock_t *lock); +int +synclock_trylock(synclock_t *lock); +int +synclock_unlock(synclock_t *lock); + +int +syncbarrier_init(syncbarrier_t *barrier); +int +syncbarrier_wait(syncbarrier_t *barrier, int waitfor); +int +syncbarrier_wake(syncbarrier_t *barrier); +int +syncbarrier_destroy(syncbarrier_t *barrier); + +int +syncop_lookup(xlator_t *subvol, loc_t *loc, + /* out */ + struct iatt *iatt, struct iatt *parent, + /* xdata */ + dict_t *xdata_in, dict_t **xdata_out); + +int +syncop_readdirp(xlator_t *subvol, fd_t *fd, size_t size, off_t off, + /* out */ + gf_dirent_t *entries, dict_t *xdata_in, dict_t **xdata_out); + +int +syncop_readdir(xlator_t *subvol, fd_t *fd, size_t size, off_t off, + gf_dirent_t *entries, dict_t *xdata_in, dict_t **xdata_out); + +int +syncop_opendir(xlator_t *subvol, loc_t *loc, fd_t *fd, dict_t *xdata_in, + dict_t **xdata_out); + +int +syncop_setattr(xlator_t *subvol, loc_t *loc, struct iatt *iatt, int valid, + /* out */ + struct iatt *preop, struct iatt *postop, dict_t *xdata_in, + dict_t **xdata_out); + +int +syncop_fsetattr(xlator_t *subvol, fd_t *fd, struct iatt *iatt, int valid, + /* out */ + struct iatt *preop, struct iatt *postop, dict_t *xdata_in, + dict_t **xdata_out); + +int +syncop_statfs(xlator_t *subvol, loc_t *loc, + /* out */ + struct statvfs *buf, dict_t *xdata_in, dict_t **xdata_out); + +int +syncop_setxattr(xlator_t *subvol, loc_t *loc, dict_t *dict, int32_t flags, + dict_t *xdata_in, dict_t **xdata_out); + +int +syncop_fsetxattr(xlator_t *subvol, fd_t *fd, dict_t *dict, int32_t flags, + dict_t *xdata_in, dict_t **xdata_out); + +int +syncop_listxattr(xlator_t *subvol, loc_t *loc, dict_t **dict, dict_t *xdata_in, + dict_t **xdata_out); + +int +syncop_getxattr(xlator_t *xl, loc_t *loc, dict_t **dict, const char *key, + dict_t *xdata_in, dict_t **xdata_out); + +int +syncop_fgetxattr(xlator_t *xl, fd_t *fd, dict_t **dict, const char *key, + dict_t *xdata_in, dict_t **xdata_out); + +int +syncop_removexattr(xlator_t *subvol, loc_t *loc, const char *name, + dict_t *xdata_in, dict_t **xdata_out); + +int +syncop_fremovexattr(xlator_t *subvol, fd_t *fd, const char *name, + dict_t *xdata_in, dict_t **xdata_out); + +int +syncop_create(xlator_t *subvol, loc_t *loc, int32_t flags, mode_t mode, + fd_t *fd, struct iatt *iatt, dict_t *xdata_in, + dict_t **xdata_out); + +int +syncop_open(xlator_t *subvol, loc_t *loc, int32_t flags, fd_t *fd, + dict_t *xdata_in, dict_t **xdata_out); + +int +syncop_close(fd_t *fd); + +int +syncop_write(xlator_t *subvol, fd_t *fd, const char *buf, int size, + off_t offset, struct iobref *iobref, uint32_t flags, + dict_t *xdata_in, dict_t **xdata_out); + +int +syncop_writev(xlator_t *subvol, fd_t *fd, const struct iovec *vector, + int32_t count, off_t offset, struct iobref *iobref, + uint32_t flags, struct iatt *preiatt, struct iatt *postiatt, + dict_t *xdata_in, dict_t **xdata_out); + +int +syncop_readv(xlator_t *subvol, fd_t *fd, size_t size, off_t off, uint32_t flags, + /* out */ + struct iovec **vector, int *count, struct iobref **iobref, + struct iatt *iatt, dict_t *xdata_in, dict_t **xdata_out); + +int +syncop_ftruncate(xlator_t *subvol, fd_t *fd, off_t offset, struct iatt *preiatt, + struct iatt *postiatt, dict_t *xdata_in, dict_t **xdata_out); + +int +syncop_truncate(xlator_t *subvol, loc_t *loc, off_t offset, dict_t *xdata_in, + dict_t **xdata_out); + +int +syncop_unlink(xlator_t *subvol, loc_t *loc, dict_t *xdata_in, + dict_t **xdata_out); + +int +syncop_rmdir(xlator_t *subvol, loc_t *loc, int flags, dict_t *xdata_in, + dict_t **xdata_out); + +int +syncop_fsync(xlator_t *subvol, fd_t *fd, int dataonly, struct iatt *preiatt, + struct iatt *postiatt, dict_t *xdata_in, dict_t **xdata_out); + +int +syncop_flush(xlator_t *subvol, fd_t *fd, dict_t *xdata_in, dict_t **xdata_out); + +int +syncop_fstat(xlator_t *subvol, fd_t *fd, struct iatt *stbuf, dict_t *xdata_in, + dict_t **xdata_out); + +int +syncop_stat(xlator_t *subvol, loc_t *loc, struct iatt *stbuf, dict_t *xdata_in, + dict_t **xdata_out); + +int +syncop_symlink(xlator_t *subvol, loc_t *loc, const char *newpath, + struct iatt *iatt, dict_t *xdata_in, dict_t **xdata_out); + +int +syncop_readlink(xlator_t *subvol, loc_t *loc, char **buffer, size_t size, + dict_t *xdata_in, dict_t **xdata_out); + +int +syncop_mknod(xlator_t *subvol, loc_t *loc, mode_t mode, dev_t rdev, + struct iatt *iatt, dict_t *xdata_in, dict_t **xdata_out); + +int +syncop_mkdir(xlator_t *subvol, loc_t *loc, mode_t mode, struct iatt *iatt, + dict_t *xdata_in, dict_t **xdata_out); + +int +syncop_link(xlator_t *subvol, loc_t *oldloc, loc_t *newloc, struct iatt *iatt, + dict_t *xdata_in, dict_t **xdata_out); + +int +syncop_fsyncdir(xlator_t *subvol, fd_t *fd, int datasync, dict_t *xdata_in, + dict_t **xdata_out); + +int +syncop_access(xlator_t *subvol, loc_t *loc, int32_t mask, dict_t *xdata_in, + dict_t **xdata_out); + +int +syncop_fallocate(xlator_t *subvol, fd_t *fd, int32_t keep_size, off_t offset, + size_t len, dict_t *xdata_in, dict_t **xdata_out); + +int +syncop_discard(xlator_t *subvol, fd_t *fd, off_t offset, size_t len, + dict_t *xdata_in, dict_t **xdata_out); + +int +syncop_zerofill(xlator_t *subvol, fd_t *fd, off_t offset, off_t len, + dict_t *xdata_in, dict_t **xdata_out); + +int +syncop_rename(xlator_t *subvol, loc_t *oldloc, loc_t *newloc, dict_t *xdata_in, + dict_t **xdata_out); + +int +syncop_lk(xlator_t *subvol, fd_t *fd, int cmd, struct gf_flock *flock, + dict_t *xdata_in, dict_t **xdata_out); + +int +syncop_inodelk(xlator_t *subvol, const char *volume, loc_t *loc, int32_t cmd, + struct gf_flock *lock, dict_t *xdata_in, dict_t **xdata_out); + +int +syncop_lease(xlator_t *subvol, loc_t *loc, struct gf_lease *lease, + dict_t *xdata_in, dict_t **xdata_out); + +int +syncop_ipc(xlator_t *subvol, int op, dict_t *xdata_in, dict_t **xdata_out); + +int +syncop_xattrop(xlator_t *subvol, loc_t *loc, gf_xattrop_flags_t flags, + dict_t *dict, dict_t *xdata_in, dict_t **dict_out, + dict_t **xdata_out); + +int +syncop_fxattrop(xlator_t *subvol, fd_t *fd, gf_xattrop_flags_t flags, + dict_t *dict, dict_t *xdata_in, dict_t **dict_out, + dict_t **xdata_out); + +int +syncop_seek(xlator_t *subvol, fd_t *fd, off_t offset, gf_seek_what_t what, + dict_t *xdata_in, off_t *off); + +int +syncop_getactivelk(xlator_t *subvol, loc_t *loc, + lock_migration_info_t *locklist, dict_t *xdata_in, + dict_t **xdata_out); + +int +syncop_setactivelk_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + +int +syncop_setactivelk(xlator_t *subvol, loc_t *loc, + lock_migration_info_t *locklist, dict_t *xdata_in, + dict_t **xdata_out); + +int +syncop_put(xlator_t *subvol, loc_t *loc, mode_t mode, mode_t umask, + uint32_t flags, struct iovec *vector, int32_t count, off_t offset, + struct iobref *iobref, dict_t *xattr, struct iatt *iatt, + dict_t *xdata_in, dict_t **xdata_out); + +int +syncop_setactivelk_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + +int +syncop_icreate(xlator_t *subvol, loc_t *loc, mode_t mode, dict_t *xdata_out); + +int +syncop_entrylk(xlator_t *subvol, const char *volume, loc_t *loc, + const char *basename, entrylk_cmd cmd, entrylk_type type, + dict_t *xdata_in, dict_t **xdata_out); + +#endif /* _SYNCOP_H */ diff --git a/libglusterfs/src/glusterfs/syscall.h b/libglusterfs/src/glusterfs/syscall.h new file mode 100644 index 00000000000..faaf694b22c --- /dev/null +++ b/libglusterfs/src/glusterfs/syscall.h @@ -0,0 +1,231 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef __SYSCALL_H__ +#define __SYSCALL_H__ + +#include <dirent.h> +#include <sys/uio.h> +#include <sys/statvfs.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <sys/socket.h> + +/* GF follows the Linux XATTR definition, which differs in Darwin. */ +#define GF_XATTR_CREATE 0x1 /* set value, fail if attr already exists */ +#define GF_XATTR_REPLACE 0x2 /* set value, fail if attr does not exist */ + +/* Linux kernel version 2.6.x don't have these defined + define if not defined */ + +#ifndef XATTR_SECURITY_PREFIX +#define XATTR_SECURITY_PREFIX "security." +#define XATTR_SECURITY_PREFIX_LEN (sizeof(XATTR_SECURITY_PREFIX) - 1) +#endif + +#ifndef XATTR_SYSTEM_PREFIX +#define XATTR_SYSTEM_PREFIX "system." +#define XATTR_SYSTEM_PREFIX_LEN (sizeof(XATTR_SYSTEM_PREFIX) - 1) +#endif + +#ifndef XATTR_TRUSTED_PREFIX +#define XATTR_TRUSTED_PREFIX "trusted." +#define XATTR_TRUSTED_PREFIX_LEN (sizeof(XATTR_TRUSTED_PREFIX) - 1) +#endif + +#ifndef XATTR_USER_PREFIX +#define XATTR_USER_PREFIX "user." +#define XATTR_USER_PREFIX_LEN (sizeof(XATTR_USER_PREFIX) - 1) +#endif + +#if defined(GF_DARWIN_HOST_OS) +#include <sys/xattr.h> +#define XATTR_DARWIN_NOSECURITY XATTR_NOSECURITY +#define XATTR_DARWIN_NODEFAULT XATTR_NODEFAULT +#define XATTR_DARWIN_SHOWCOMPRESSION XATTR_SHOWCOMPRESSION +#endif + +int +sys_lstat(const char *path, struct stat *buf); + +int +sys_stat(const char *path, struct stat *buf); + +int +sys_fstat(int fd, struct stat *buf); + +int +sys_fstatat(int dirfd, const char *pathname, struct stat *buf, int flags); + +int +sys_open(const char *pathname, int flags, int mode); + +int +sys_openat(int dirfd, const char *pathname, int flags, int mode); + +DIR * +sys_opendir(const char *name); + +struct dirent * +sys_readdir(DIR *dir, struct dirent *de); + +ssize_t +sys_readlink(const char *path, char *buf, size_t bufsiz); + +int +sys_closedir(DIR *dir); + +int +sys_mknod(const char *pathname, mode_t mode, dev_t dev); + +int +sys_mkdir(const char *pathname, mode_t mode); + +int +sys_mkdirat(int dirfd, const char *pathname, mode_t mode); + +int +sys_unlink(const char *pathname); + +int +sys_rmdir(const char *pathname); + +int +sys_symlink(const char *oldpath, const char *newpath); + +int +sys_rename(const char *oldpath, const char *newpath); + +int +sys_link(const char *oldpath, const char *newpath); + +int +sys_chmod(const char *path, mode_t mode); + +int +sys_fchmod(int fd, mode_t mode); + +int +sys_chown(const char *path, uid_t owner, gid_t group); + +int +sys_fchown(int fd, uid_t owner, gid_t group); + +int +sys_lchown(const char *path, uid_t owner, gid_t group); + +int +sys_truncate(const char *path, off_t length); + +int +sys_ftruncate(int fd, off_t length); + +int +sys_utimes(const char *filename, const struct timeval times[2]); + +#if defined(HAVE_UTIMENSAT) +int +sys_utimensat(int dirfd, const char *filename, const struct timespec times[2], + int flags); +#endif + +int +sys_futimes(int fd, const struct timeval times[2]); + +int +sys_creat(const char *pathname, mode_t mode); + +ssize_t +sys_readv(int fd, const struct iovec *iov, int iovcnt); + +ssize_t +sys_writev(int fd, const struct iovec *iov, int iovcnt); + +ssize_t +sys_read(int fd, void *buf, size_t count); + +ssize_t +sys_write(int fd, const void *buf, size_t count); + +off_t +sys_lseek(int fd, off_t offset, int whence); + +int +sys_statvfs(const char *path, struct statvfs *buf); + +int +sys_fstatvfs(int fd, struct statvfs *buf); + +int +sys_close(int fd); + +int +sys_fsync(int fd); + +int +sys_fdatasync(int fd); + +void +gf_add_prefix(const char *ns, const char *key, char **newkey); + +void +gf_remove_prefix(const char *ns, const char *key, char **newkey); + +int +sys_lsetxattr(const char *path, const char *name, const void *value, + size_t size, int flags); + +ssize_t +sys_llistxattr(const char *path, char *list, size_t size); + +ssize_t +sys_lgetxattr(const char *path, const char *name, void *value, size_t size); + +ssize_t +sys_fgetxattr(int filedes, const char *name, void *value, size_t size); + +int +sys_fsetxattr(int filedes, const char *name, const void *value, size_t size, + int flags); + +ssize_t +sys_flistxattr(int filedes, char *list, size_t size); + +int +sys_lremovexattr(const char *path, const char *name); + +int +sys_fremovexattr(int filedes, const char *name); + +int +sys_access(const char *pathname, int mode); + +int +sys_fallocate(int fd, int mode, off_t offset, off_t len); + +ssize_t +sys_preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset); + +ssize_t +sys_pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset); + +ssize_t +sys_pread(int fd, void *buf, size_t count, off_t offset); + +ssize_t +sys_pwrite(int fd, const void *buf, size_t count, off_t offset); + +int +sys_socket(int domain, int type, int protocol); + +int +sys_accept(int sock, struct sockaddr *sockaddr, socklen_t *socklen, int flags); + +#endif /* __SYSCALL_H__ */ diff --git a/libglusterfs/src/glusterfs/template-component-messages.h b/libglusterfs/src/glusterfs/template-component-messages.h new file mode 100644 index 00000000000..aa7ad3d1baa --- /dev/null +++ b/libglusterfs/src/glusterfs/template-component-messages.h @@ -0,0 +1,28 @@ +/* + Copyright (c) 2013 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. + */ + +#ifndef _component_MESSAGES_H_ +#define _component_MESSAGES_H_ + +#include "glusterfs/glfs-message-id.h" + +/* To add new message IDs, append new identifiers at the end of the list. + * + * Never remove a message ID. If it's not used anymore, you can rename it or + * leave it as it is, but not delete it. This is to prevent reutilization of + * IDs by other messages. + * + * The component name must match one of the entries defined in + * glfs-message-id.h. + */ + +GLFS_MSGID(component, message id, message id, ...); + +#endif /* !_component_MESSAGES_H_ */ diff --git a/libglusterfs/src/glusterfs/throttle-tbf.h b/libglusterfs/src/glusterfs/throttle-tbf.h new file mode 100644 index 00000000000..cccb13c83d9 --- /dev/null +++ b/libglusterfs/src/glusterfs/throttle-tbf.h @@ -0,0 +1,74 @@ +/* + Copyright (c) 2015 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#include "glusterfs/list.h" +#include "glusterfs/xlator.h" +#include "glusterfs/locking.h" + +#ifndef THROTTLE_TBF_H__ +#define THROTTLE_TBF_H__ + +typedef enum tbf_ops { + TBF_OP_MIN = -1, + TBF_OP_HASH = 0, /* checksum calculation */ + TBF_OP_READ = 1, /* inode read(s) */ + TBF_OP_READDIR = 2, /* dentry read(s) */ + TBF_OP_MAX = 3, +} tbf_ops_t; + +/** + * Operation rate specification + */ +typedef struct tbf_opspec { + tbf_ops_t op; + + unsigned long rate; + + unsigned long maxlimit; + + unsigned long token_gen_interval; /* Token generation interval in usec */ +} tbf_opspec_t; + +/** + * Token bucket for each operation type + */ +typedef struct tbf_bucket { + gf_lock_t lock; + + pthread_t tokener; /* token generator thread */ + + unsigned long tokenrate; /* token generation rate */ + + unsigned long tokens; /* number of current tokens */ + + unsigned long maxtokens; /* maximum token in the bucket */ + + struct list_head queued; /* list of non-conformant requests */ + + unsigned long token_gen_interval; /* Token generation interval in usec */ +} tbf_bucket_t; + +typedef struct tbf { + tbf_bucket_t **bucket; +} tbf_t; + +tbf_t * +tbf_init(tbf_opspec_t *, unsigned int); + +int +tbf_mod(tbf_t *, tbf_opspec_t *); + +void +tbf_throttle(tbf_t *, tbf_ops_t, unsigned long); + +#define TBF_THROTTLE_BEGIN(tbf, op, tokens) (tbf_throttle(tbf, op, tokens)) +#define TBF_THROTTLE_END(tbf, op, tokens) + +#endif /** THROTTLE_TBF_H__ */ diff --git a/libglusterfs/src/glusterfs/timer.h b/libglusterfs/src/glusterfs/timer.h new file mode 100644 index 00000000000..1af33031851 --- /dev/null +++ b/libglusterfs/src/glusterfs/timer.h @@ -0,0 +1,55 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _TIMER_H +#define _TIMER_H + +#include "glusterfs/glusterfs.h" +#include "glusterfs/xlator.h" +#include <sys/time.h> +#include <pthread.h> + +typedef void (*gf_timer_cbk_t)(void *); + +struct _gf_timer { + union { + struct list_head list; + struct { + struct _gf_timer *next; + struct _gf_timer *prev; + }; + }; + struct timespec at; + gf_timer_cbk_t callbk; + void *data; + xlator_t *xl; + gf_boolean_t fired; +}; + +struct _gf_timer_registry { + pthread_t th; + char fin; + struct list_head active; + gf_lock_t lock; +}; + +typedef struct _gf_timer gf_timer_t; +typedef struct _gf_timer_registry gf_timer_registry_t; + +gf_timer_t * +gf_timer_call_after(glusterfs_ctx_t *ctx, struct timespec delta, + gf_timer_cbk_t cbk, void *data); + +int32_t +gf_timer_call_cancel(glusterfs_ctx_t *ctx, gf_timer_t *event); + +void +gf_timer_registry_destroy(glusterfs_ctx_t *ctx); +#endif /* _TIMER_H */ diff --git a/libglusterfs/src/glusterfs/timespec.h b/libglusterfs/src/glusterfs/timespec.h new file mode 100644 index 00000000000..871871d538c --- /dev/null +++ b/libglusterfs/src/glusterfs/timespec.h @@ -0,0 +1,31 @@ +/* + Copyright (c) 2013 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef __INCLUDE_TIMESPEC_H__ +#define __INCLUDE_TIMESPEC_H__ + +#include <stdint.h> +#include <sys/time.h> + +#define TS(ts) ((ts.tv_sec * 1000000000LL) + ts.tv_nsec) +#define NANO (+1.0E-9) +#define GIGA UINT64_C(1000000000) + +void +timespec_now(struct timespec *ts); +void +timespec_adjust_delta(struct timespec *ts, struct timespec delta); +void +timespec_sub(const struct timespec *begin, const struct timespec *end, + struct timespec *res); +int +timespec_cmp(const struct timespec *lhs_ts, const struct timespec *rhs_ts); + +#endif /* __INCLUDE_TIMESPEC_H__ */ diff --git a/libglusterfs/src/glusterfs/trie.h b/libglusterfs/src/glusterfs/trie.h new file mode 100644 index 00000000000..6d2d8015964 --- /dev/null +++ b/libglusterfs/src/glusterfs/trie.h @@ -0,0 +1,52 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _TRIE_H_ +#define _TRIE_H_ + +struct trienode; +typedef struct trienode trienode_t; + +struct trie; +typedef struct trie trie_t; + +struct trienodevec { + trienode_t **nodes; + unsigned cnt; +}; + +trie_t * +trie_new(); + +int +trie_add(trie_t *trie, const char *word); + +void +trie_destroy(trie_t *trie); + +void +trie_destroy_bynode(trienode_t *node); + +int +trie_measure(trie_t *trie, const char *word, trienode_t **nodes, int nodecnt); + +int +trie_measure_vec(trie_t *trie, const char *word, struct trienodevec *nodevec); + +void +trie_reset_search(trie_t *trie); + +int +trienode_get_dist(trienode_t *node); + +int +trienode_get_word(trienode_t *node, char **buf); + +#endif diff --git a/libglusterfs/src/glusterfs/upcall-utils.h b/libglusterfs/src/glusterfs/upcall-utils.h new file mode 100644 index 00000000000..0de8428c5fc --- /dev/null +++ b/libglusterfs/src/glusterfs/upcall-utils.h @@ -0,0 +1,110 @@ +/* + Copyright (c) 2015, Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _UPCALL_UTILS_H +#define _UPCALL_UTILS_H + +#include "glusterfs/iatt.h" +#include "glusterfs/compat-uuid.h" +#include "glusterfs/compat.h" + +/* Flags sent for cache_invalidation */ +#define UP_NLINK 0x00000001 /* update nlink */ +#define UP_MODE 0x00000002 /* update mode and ctime */ +#define UP_OWN 0x00000004 /* update mode,uid,gid and ctime */ +#define UP_SIZE 0x00000008 /* update fsize */ +#define UP_TIMES 0x00000010 /* update all times */ +#define UP_ATIME 0x00000020 /* update atime only */ +#define UP_PERM \ + 0x00000040 /* update fields needed for permission \ + checking */ +#define UP_RENAME \ + 0x00000080 /* this is a rename op - delete the cache \ + entry */ +#define UP_FORGET \ + 0x00000100 /* inode_forget on server side - \ + invalidate the cache entry */ +#define UP_PARENT_TIMES 0x00000200 /* update parent dir times */ + +#define UP_XATTR 0x00000400 /* update the xattrs and ctime */ +#define UP_XATTR_RM 0x00000800 /* Remove the xattrs and update ctime */ + +#define UP_EXPLICIT_LOOKUP 0x00001000 /* Request an explicit lookup */ + +#define UP_INVAL_ATTR 0x00002000 /* Request to invalidate iatt and xatt */ + +/* for fops - open, read, lk, */ +#define UP_UPDATE_CLIENT (UP_ATIME) + +/* for fop - write, truncate */ +#define UP_WRITE_FLAGS (UP_SIZE | UP_TIMES) + +/* for fop - setattr */ +#define UP_ATTR_FLAGS (UP_SIZE | UP_TIMES | UP_OWN | UP_MODE | UP_PERM) +/* for fop - rename */ +#define UP_RENAME_FLAGS (UP_RENAME) + +/* to invalidate parent directory entries for fops -rename, unlink, rmdir, + * mkdir, create */ +#define UP_PARENT_DENTRY_FLAGS (UP_PARENT_TIMES) + +/* for fop - unlink, link, rmdir, mkdir */ +#define UP_NLINK_FLAGS (UP_NLINK | UP_TIMES) + +#define IATT_UPDATE_FLAGS \ + (UP_NLINK | UP_MODE | UP_OWN | UP_SIZE | UP_TIMES | UP_ATIME | UP_PERM) + +typedef enum { + GF_UPCALL_EVENT_NULL, + GF_UPCALL_CACHE_INVALIDATION, + GF_UPCALL_RECALL_LEASE, + GF_UPCALL_INODELK_CONTENTION, + GF_UPCALL_ENTRYLK_CONTENTION, +} gf_upcall_event_t; + +struct gf_upcall { + char *client_uid; + uuid_t gfid; + uint32_t event_type; + void *data; +}; + +struct gf_upcall_cache_invalidation { + uint32_t flags; + uint32_t expire_time_attr; + struct iatt stat; + struct iatt p_stat; /* parent dir stat */ + struct iatt oldp_stat; /* oldparent dir stat */ + dict_t *dict; /* For xattrs */ +}; + +struct gf_upcall_recall_lease { + uint32_t lease_type; /* Lease type to which client can downgrade to*/ + uuid_t tid; /* transaction id of the fop that caused + the recall */ + dict_t *dict; +}; + +struct gf_upcall_inodelk_contention { + struct gf_flock flock; + pid_t pid; + const char *domain; + dict_t *xdata; +}; + +struct gf_upcall_entrylk_contention { + uint32_t type; + pid_t pid; + const char *name; + const char *domain; + dict_t *xdata; +}; + +#endif /* _UPCALL_UTILS_H */ diff --git a/libglusterfs/src/glusterfs/xlator.h b/libglusterfs/src/glusterfs/xlator.h new file mode 100644 index 00000000000..4137d12eb27 --- /dev/null +++ b/libglusterfs/src/glusterfs/xlator.h @@ -0,0 +1,1087 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _XLATOR_H +#define _XLATOR_H + +#include <stdio.h> +#include <stdint.h> +#include <inttypes.h> + +#include "glusterfs/event-history.h" +#include "glusterfs/logging.h" +#include "glusterfs/common-utils.h" +#include "glusterfs/dict.h" +#include "glusterfs/compat.h" +#include "glusterfs/list.h" +#include "glusterfs/latency.h" +#include "glusterfs/compat-uuid.h" + +#define FIRST_CHILD(xl) (xl->children->xlator) +#define SECOND_CHILD(xl) (xl->children->next->xlator) + +#define GF_SET_ATTR_MODE 0x1 +#define GF_SET_ATTR_UID 0x2 +#define GF_SET_ATTR_GID 0x4 +#define GF_SET_ATTR_SIZE 0x8 +#define GF_SET_ATTR_ATIME 0x10 +#define GF_SET_ATTR_MTIME 0x20 +#define GF_SET_ATTR_CTIME 0x40 + +#define gf_attr_mode_set(mode) ((mode)&GF_SET_ATTR_MODE) +#define gf_attr_uid_set(mode) ((mode)&GF_SET_ATTR_UID) +#define gf_attr_gid_set(mode) ((mode)&GF_SET_ATTR_GID) +#define gf_attr_size_set(mode) ((mode)&GF_SET_ATTR_SIZE) +#define gf_attr_atime_set(mode) ((mode)&GF_SET_ATTR_ATIME) +#define gf_attr_mtime_set(mode) ((mode)&GF_SET_ATTR_MTIME) + +struct _xlator; +typedef struct _xlator xlator_t; +struct _dir_entry; +typedef struct _dir_entry dir_entry_t; +struct _gf_dirent; +typedef struct _gf_dirent gf_dirent_t; +struct _loc; +typedef struct _loc loc_t; + +typedef int32_t (*event_notify_fn_t)(xlator_t *this, int32_t event, void *data, + ...); + +#include "glusterfs/list.h" +#include "glusterfs/gf-dirent.h" +#include "glusterfs/stack.h" +#include "glusterfs/iobuf.h" +#include "glusterfs/globals.h" +#include "glusterfs/iatt.h" +#include "glusterfs/options.h" +#include "glusterfs/client_t.h" + +struct _loc { + const char *path; + const char *name; + inode_t *inode; + inode_t *parent; + /* Currently all location based operations are through 'gfid' of inode. + * But the 'inode->gfid' only gets set in higher most layer (as in, + * 'fuse', 'protocol/server', or 'nfs/server'). So if translators want + * to send fops on a inode before the 'inode->gfid' is set, they have to + * make use of below 'gfid' fields + */ + uuid_t gfid; + uuid_t pargfid; +}; + +typedef int32_t (*fop_getspec_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, char *spec_data); + +typedef int32_t (*fop_rchecksum_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, uint32_t weak_checksum, + uint8_t *strong_checksum, dict_t *xdata); + +typedef int32_t (*fop_getspec_t)(call_frame_t *frame, xlator_t *this, + const char *key, int32_t flag); + +typedef int32_t (*fop_rchecksum_t)(call_frame_t *frame, xlator_t *this, + fd_t *fd, off_t offset, int32_t len, + dict_t *xdata); + +typedef int32_t (*fop_lookup_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, inode_t *inode, + struct iatt *buf, dict_t *xdata, + struct iatt *postparent); + +typedef int32_t (*fop_stat_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, struct iatt *buf, + dict_t *xdata); + +typedef int32_t (*fop_fstat_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, struct iatt *buf, + dict_t *xdata); + +typedef int32_t (*fop_truncate_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata); + +typedef int32_t (*fop_ftruncate_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata); + +typedef int32_t (*fop_access_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, dict_t *xdata); + +typedef int32_t (*fop_readlink_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, const char *path, + struct iatt *buf, dict_t *xdata); + +typedef int32_t (*fop_mknod_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, inode_t *inode, + struct iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); + +typedef int32_t (*fop_mkdir_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, inode_t *inode, + struct iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); + +typedef int32_t (*fop_unlink_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); + +typedef int32_t (*fop_rmdir_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); + +typedef int32_t (*fop_symlink_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, inode_t *inode, + struct iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); + +typedef int32_t (*fop_rename_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, struct iatt *buf, + struct iatt *preoldparent, + struct iatt *postoldparent, + struct iatt *prenewparent, + struct iatt *postnewparent, dict_t *xdata); + +typedef int32_t (*fop_link_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, inode_t *inode, + struct iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); + +typedef int32_t (*fop_create_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, fd_t *fd, inode_t *inode, + struct iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); + +typedef int32_t (*fop_open_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, fd_t *fd, dict_t *xdata); + +typedef int32_t (*fop_readv_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, struct iovec *vector, + int32_t count, struct iatt *stbuf, + struct iobref *iobref, dict_t *xdata); + +typedef int32_t (*fop_writev_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata); + +typedef int32_t (*fop_flush_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, dict_t *xdata); + +typedef int32_t (*fop_fsync_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata); + +typedef int32_t (*fop_opendir_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, fd_t *fd, dict_t *xdata); + +typedef int32_t (*fop_fsyncdir_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, dict_t *xdata); + +typedef int32_t (*fop_statfs_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, struct statvfs *buf, + dict_t *xdata); + +typedef int32_t (*fop_setxattr_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, dict_t *xdata); + +typedef int32_t (*fop_getxattr_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, dict_t *dict, + dict_t *xdata); + +typedef int32_t (*fop_fsetxattr_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, dict_t *xdata); + +typedef int32_t (*fop_fgetxattr_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, dict_t *dict, + dict_t *xdata); + +typedef int32_t (*fop_removexattr_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, dict_t *xdata); + +typedef int32_t (*fop_fremovexattr_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, dict_t *xdata); + +typedef int32_t (*fop_lk_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, struct gf_flock *flock, + dict_t *xdata); + +typedef int32_t (*fop_inodelk_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, dict_t *xdata); + +typedef int32_t (*fop_finodelk_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, dict_t *xdata); + +typedef int32_t (*fop_entrylk_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, dict_t *xdata); + +typedef int32_t (*fop_fentrylk_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, dict_t *xdata); + +typedef int32_t (*fop_readdir_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, gf_dirent_t *entries, + dict_t *xdata); + +typedef int32_t (*fop_readdirp_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, gf_dirent_t *entries, + dict_t *xdata); + +typedef int32_t (*fop_xattrop_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, dict_t *xattr, + dict_t *xdata); + +typedef int32_t (*fop_fxattrop_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, dict_t *xattr, + dict_t *xdata); + +typedef int32_t (*fop_setattr_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, struct iatt *preop_stbuf, + struct iatt *postop_stbuf, dict_t *xdata); + +typedef int32_t (*fop_fsetattr_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, + struct iatt *preop_stbuf, + struct iatt *postop_stbuf, dict_t *xdata); + +typedef int32_t (*fop_fallocate_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, + struct iatt *preop_stbuf, + struct iatt *postop_stbuf, + dict_t *xdata); + +typedef int32_t (*fop_discard_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, struct iatt *preop_stbuf, + struct iatt *postop_stbuf, dict_t *xdata); + +typedef int32_t (*fop_zerofill_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, + struct iatt *preop_stbuf, + struct iatt *postop_stbuf, dict_t *xdata); + +typedef int32_t (*fop_ipc_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, dict_t *xdata); + +typedef int32_t (*fop_seek_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, off_t offset, + dict_t *xdata); + +typedef int32_t (*fop_lease_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, struct gf_lease *lease, + dict_t *xdata); +typedef int32_t (*fop_compound_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, void *data, + dict_t *xdata); + +typedef int32_t (*fop_getactivelk_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, + lock_migration_info_t *locklist, + dict_t *xdata); + +typedef int32_t (*fop_setactivelk_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, dict_t *xdata); + +typedef int32_t (*fop_put_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, inode_t *inode, + struct iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); + +typedef int32_t (*fop_icreate_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, inode_t *inode, + struct iatt *buf, dict_t *xdata); + +typedef int32_t (*fop_namelink_cbk_t)(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata); + +typedef int32_t (*fop_lookup_t)(call_frame_t *frame, xlator_t *this, loc_t *loc, + dict_t *xdata); + +typedef int32_t (*fop_stat_t)(call_frame_t *frame, xlator_t *this, loc_t *loc, + dict_t *xdata); + +typedef int32_t (*fop_fstat_t)(call_frame_t *frame, xlator_t *this, fd_t *fd, + dict_t *xdata); + +typedef int32_t (*fop_truncate_t)(call_frame_t *frame, xlator_t *this, + loc_t *loc, off_t offset, dict_t *xdata); + +typedef int32_t (*fop_ftruncate_t)(call_frame_t *frame, xlator_t *this, + fd_t *fd, off_t offset, dict_t *xdata); + +typedef int32_t (*fop_access_t)(call_frame_t *frame, xlator_t *this, loc_t *loc, + int32_t mask, dict_t *xdata); + +typedef int32_t (*fop_readlink_t)(call_frame_t *frame, xlator_t *this, + loc_t *loc, size_t size, dict_t *xdata); + +typedef int32_t (*fop_mknod_t)(call_frame_t *frame, xlator_t *this, loc_t *loc, + mode_t mode, dev_t rdev, mode_t umask, + dict_t *xdata); + +typedef int32_t (*fop_mkdir_t)(call_frame_t *frame, xlator_t *this, loc_t *loc, + mode_t mode, mode_t umask, dict_t *xdata); + +typedef int32_t (*fop_unlink_t)(call_frame_t *frame, xlator_t *this, loc_t *loc, + int xflags, dict_t *xdata); + +typedef int32_t (*fop_rmdir_t)(call_frame_t *frame, xlator_t *this, loc_t *loc, + int xflags, dict_t *xdata); + +typedef int32_t (*fop_symlink_t)(call_frame_t *frame, xlator_t *this, + const char *linkname, loc_t *loc, mode_t umask, + dict_t *xdata); + +typedef int32_t (*fop_rename_t)(call_frame_t *frame, xlator_t *this, + loc_t *oldloc, loc_t *newloc, dict_t *xdata); + +typedef int32_t (*fop_link_t)(call_frame_t *frame, xlator_t *this, + loc_t *oldloc, loc_t *newloc, dict_t *xdata); + +typedef int32_t (*fop_create_t)(call_frame_t *frame, xlator_t *this, loc_t *loc, + int32_t flags, mode_t mode, mode_t umask, + fd_t *fd, dict_t *xdata); + +/* Tell subsequent writes on the fd_t to fsync after every writev fop without + * requiring a fsync fop. + */ +#define GF_OPEN_FSYNC 0x01 + +/* Tell write-behind to disable writing behind despite O_SYNC not being set. + */ +#define GF_OPEN_NOWB 0x02 + +typedef int32_t (*fop_open_t)(call_frame_t *frame, xlator_t *this, loc_t *loc, + int32_t flags, fd_t *fd, dict_t *xdata); + +typedef int32_t (*fop_readv_t)(call_frame_t *frame, xlator_t *this, fd_t *fd, + size_t size, off_t offset, uint32_t flags, + dict_t *xdata); + +typedef int32_t (*fop_writev_t)(call_frame_t *frame, xlator_t *this, fd_t *fd, + struct iovec *vector, int32_t count, + off_t offset, uint32_t flags, + struct iobref *iobref, dict_t *xdata); + +typedef int32_t (*fop_flush_t)(call_frame_t *frame, xlator_t *this, fd_t *fd, + dict_t *xdata); + +typedef int32_t (*fop_fsync_t)(call_frame_t *frame, xlator_t *this, fd_t *fd, + int32_t datasync, dict_t *xdata); + +typedef int32_t (*fop_opendir_t)(call_frame_t *frame, xlator_t *this, + loc_t *loc, fd_t *fd, dict_t *xdata); + +typedef int32_t (*fop_fsyncdir_t)(call_frame_t *frame, xlator_t *this, fd_t *fd, + int32_t datasync, dict_t *xdata); + +typedef int32_t (*fop_statfs_t)(call_frame_t *frame, xlator_t *this, loc_t *loc, + dict_t *xdata); + +typedef int32_t (*fop_setxattr_t)(call_frame_t *frame, xlator_t *this, + loc_t *loc, dict_t *dict, int32_t flags, + dict_t *xdata); + +typedef int32_t (*fop_getxattr_t)(call_frame_t *frame, xlator_t *this, + loc_t *loc, const char *name, dict_t *xdata); + +typedef int32_t (*fop_fsetxattr_t)(call_frame_t *frame, xlator_t *this, + fd_t *fd, dict_t *dict, int32_t flags, + dict_t *xdata); + +typedef int32_t (*fop_fgetxattr_t)(call_frame_t *frame, xlator_t *this, + fd_t *fd, const char *name, dict_t *xdata); + +typedef int32_t (*fop_removexattr_t)(call_frame_t *frame, xlator_t *this, + loc_t *loc, const char *name, + dict_t *xdata); + +typedef int32_t (*fop_fremovexattr_t)(call_frame_t *frame, xlator_t *this, + fd_t *fd, const char *name, + dict_t *xdata); + +typedef int32_t (*fop_lk_t)(call_frame_t *frame, xlator_t *this, fd_t *fd, + int32_t cmd, struct gf_flock *flock, dict_t *xdata); + +typedef int32_t (*fop_inodelk_t)(call_frame_t *frame, xlator_t *this, + const char *volume, loc_t *loc, int32_t cmd, + struct gf_flock *flock, dict_t *xdata); + +typedef int32_t (*fop_finodelk_t)(call_frame_t *frame, xlator_t *this, + const char *volume, fd_t *fd, int32_t cmd, + struct gf_flock *flock, dict_t *xdata); + +typedef int32_t (*fop_entrylk_t)(call_frame_t *frame, xlator_t *this, + const char *volume, loc_t *loc, + const char *basename, entrylk_cmd cmd, + entrylk_type type, dict_t *xdata); + +typedef int32_t (*fop_fentrylk_t)(call_frame_t *frame, xlator_t *this, + const char *volume, fd_t *fd, + const char *basename, entrylk_cmd cmd, + entrylk_type type, dict_t *xdata); + +typedef int32_t (*fop_readdir_t)(call_frame_t *frame, xlator_t *this, fd_t *fd, + size_t size, off_t offset, dict_t *xdata); + +typedef int32_t (*fop_readdirp_t)(call_frame_t *frame, xlator_t *this, fd_t *fd, + size_t size, off_t offset, dict_t *xdata); + +typedef int32_t (*fop_xattrop_t)(call_frame_t *frame, xlator_t *this, + loc_t *loc, gf_xattrop_flags_t optype, + dict_t *xattr, dict_t *xdata); + +typedef int32_t (*fop_fxattrop_t)(call_frame_t *frame, xlator_t *this, fd_t *fd, + gf_xattrop_flags_t optype, dict_t *xattr, + dict_t *xdata); + +typedef int32_t (*fop_setattr_t)(call_frame_t *frame, xlator_t *this, + loc_t *loc, struct iatt *stbuf, int32_t valid, + dict_t *xdata); + +typedef int32_t (*fop_fsetattr_t)(call_frame_t *frame, xlator_t *this, fd_t *fd, + struct iatt *stbuf, int32_t valid, + dict_t *xdata); + +typedef int32_t (*fop_fallocate_t)(call_frame_t *frame, xlator_t *this, + fd_t *fd, int32_t keep_size, off_t offset, + size_t len, dict_t *xdata); + +typedef int32_t (*fop_discard_t)(call_frame_t *frame, xlator_t *this, fd_t *fd, + off_t offset, size_t len, dict_t *xdata); + +typedef int32_t (*fop_zerofill_t)(call_frame_t *frame, xlator_t *this, fd_t *fd, + off_t offset, off_t len, dict_t *xdata); + +typedef int32_t (*fop_ipc_t)(call_frame_t *frame, xlator_t *this, int32_t op, + dict_t *xdata); + +typedef int32_t (*fop_seek_t)(call_frame_t *frame, xlator_t *this, fd_t *fd, + off_t offset, gf_seek_what_t what, dict_t *xdata); + +typedef int32_t (*fop_lease_t)(call_frame_t *frame, xlator_t *this, loc_t *loc, + struct gf_lease *lease, dict_t *xdata); + +typedef int32_t (*fop_compound_t)(call_frame_t *frame, xlator_t *this, + void *args, dict_t *xdata); + +typedef int32_t (*fop_getactivelk_t)(call_frame_t *frame, xlator_t *this, + loc_t *loc, dict_t *xdata); + +typedef int32_t (*fop_setactivelk_t)(call_frame_t *frame, xlator_t *this, + loc_t *loc, + lock_migration_info_t *locklist, + dict_t *xdata); + +typedef int32_t (*fop_put_t)(call_frame_t *frame, xlator_t *this, loc_t *loc, + mode_t mode, mode_t umask, uint32_t flags, + struct iovec *vector, int32_t count, off_t offset, + struct iobref *iobref, dict_t *xattr, + dict_t *xdata); + +typedef int32_t (*fop_icreate_t)(call_frame_t *frame, xlator_t *this, + loc_t *loc, mode_t mode, dict_t *xdata); + +typedef int32_t (*fop_namelink_t)(call_frame_t *frame, xlator_t *this, + loc_t *loc, dict_t *xdata); + +/* WARNING: make sure the list is in order with FOP definition in + `rpc/xdr/src/glusterfs-fops.x`. + If it is not in order, mainly the metrics related feature would be broken */ +struct xlator_fops { + fop_stat_t stat; + fop_readlink_t readlink; + fop_mknod_t mknod; + fop_mkdir_t mkdir; + fop_unlink_t unlink; + fop_rmdir_t rmdir; + fop_symlink_t symlink; + fop_rename_t rename; + fop_link_t link; + fop_truncate_t truncate; + fop_open_t open; + fop_readv_t readv; + fop_writev_t writev; + fop_statfs_t statfs; + fop_flush_t flush; + fop_fsync_t fsync; + fop_setxattr_t setxattr; + fop_getxattr_t getxattr; + fop_removexattr_t removexattr; + fop_opendir_t opendir; + fop_fsyncdir_t fsyncdir; + fop_access_t access; + fop_create_t create; + fop_ftruncate_t ftruncate; + fop_fstat_t fstat; + fop_lk_t lk; + fop_lookup_t lookup; + fop_readdir_t readdir; + fop_inodelk_t inodelk; + fop_finodelk_t finodelk; + fop_entrylk_t entrylk; + fop_fentrylk_t fentrylk; + fop_xattrop_t xattrop; + fop_fxattrop_t fxattrop; + fop_fgetxattr_t fgetxattr; + fop_fsetxattr_t fsetxattr; + fop_rchecksum_t rchecksum; + fop_setattr_t setattr; + fop_fsetattr_t fsetattr; + fop_readdirp_t readdirp; + + /* These 3 are required to keep the index same as GF_FOP_##FOP */ + void *forget_placeholder; + void *release_placeholder; + void *releasedir_placeholder; + + fop_getspec_t getspec; + fop_fremovexattr_t fremovexattr; + fop_fallocate_t fallocate; + fop_discard_t discard; + fop_zerofill_t zerofill; + fop_ipc_t ipc; + fop_seek_t seek; + fop_lease_t lease; + fop_compound_t compound; + fop_getactivelk_t getactivelk; + fop_setactivelk_t setactivelk; + fop_put_t put; + fop_icreate_t icreate; + fop_namelink_t namelink; + + /* these entries are used for a typechecking hack in STACK_WIND _only_ */ + /* make sure to add _cbk variables only after defining regular fops as + its relative position is used to get the index */ + fop_stat_cbk_t stat_cbk; + fop_readlink_cbk_t readlink_cbk; + fop_mknod_cbk_t mknod_cbk; + fop_mkdir_cbk_t mkdir_cbk; + fop_unlink_cbk_t unlink_cbk; + fop_rmdir_cbk_t rmdir_cbk; + fop_symlink_cbk_t symlink_cbk; + fop_rename_cbk_t rename_cbk; + fop_link_cbk_t link_cbk; + fop_truncate_cbk_t truncate_cbk; + fop_open_cbk_t open_cbk; + fop_readv_cbk_t readv_cbk; + fop_writev_cbk_t writev_cbk; + fop_statfs_cbk_t statfs_cbk; + fop_flush_cbk_t flush_cbk; + fop_fsync_cbk_t fsync_cbk; + fop_setxattr_cbk_t setxattr_cbk; + fop_getxattr_cbk_t getxattr_cbk; + fop_removexattr_cbk_t removexattr_cbk; + fop_opendir_cbk_t opendir_cbk; + fop_fsyncdir_cbk_t fsyncdir_cbk; + fop_access_cbk_t access_cbk; + fop_create_cbk_t create_cbk; + fop_ftruncate_cbk_t ftruncate_cbk; + fop_fstat_cbk_t fstat_cbk; + fop_lk_cbk_t lk_cbk; + fop_lookup_cbk_t lookup_cbk; + fop_readdir_cbk_t readdir_cbk; + fop_inodelk_cbk_t inodelk_cbk; + fop_finodelk_cbk_t finodelk_cbk; + fop_entrylk_cbk_t entrylk_cbk; + fop_fentrylk_cbk_t fentrylk_cbk; + fop_xattrop_cbk_t xattrop_cbk; + fop_fxattrop_cbk_t fxattrop_cbk; + fop_fgetxattr_cbk_t fgetxattr_cbk; + fop_fsetxattr_cbk_t fsetxattr_cbk; + fop_rchecksum_cbk_t rchecksum_cbk; + fop_setattr_cbk_t setattr_cbk; + fop_fsetattr_cbk_t fsetattr_cbk; + fop_readdirp_cbk_t readdirp_cbk; + + /* These 3 are required to keep the index same as GF_FOP_##FOP */ + void *forget_placeholder_cbk; + void *release_placeholder_cbk; + void *releasedir_placeholder_cbk; + + fop_getspec_cbk_t getspec_cbk; + fop_fremovexattr_cbk_t fremovexattr_cbk; + fop_fallocate_cbk_t fallocate_cbk; + fop_discard_cbk_t discard_cbk; + fop_zerofill_cbk_t zerofill_cbk; + fop_ipc_cbk_t ipc_cbk; + fop_seek_cbk_t seek_cbk; + fop_lease_cbk_t lease_cbk; + fop_compound_cbk_t compound_cbk; + fop_getactivelk_cbk_t getactivelk_cbk; + fop_setactivelk_cbk_t setactivelk_cbk; + fop_put_cbk_t put_cbk; + fop_icreate_cbk_t icreate_cbk; + fop_namelink_cbk_t namelink_cbk; +}; + +typedef int32_t (*cbk_forget_t)(xlator_t *this, inode_t *inode); + +typedef int32_t (*cbk_release_t)(xlator_t *this, fd_t *fd); + +typedef int32_t (*cbk_invalidate_t)(xlator_t *this, inode_t *inode); + +typedef int32_t (*cbk_client_t)(xlator_t *this, client_t *client); + +typedef void (*cbk_ictxmerge_t)(xlator_t *this, fd_t *fd, inode_t *inode, + inode_t *linked_inode); + +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); + +struct xlator_cbks { + cbk_forget_t forget; + cbk_release_t release; + cbk_release_t releasedir; + cbk_invalidate_t invalidate; + cbk_client_t client_destroy; + cbk_client_t client_disconnect; + cbk_ictxmerge_t ictxmerge; + cbk_inodectx_size_t ictxsize; + cbk_fdctx_size_t fdctxsize; +}; + +typedef int32_t (*dumpop_priv_t)(xlator_t *this); + +typedef int32_t (*dumpop_inode_t)(xlator_t *this); + +typedef int32_t (*dumpop_fd_t)(xlator_t *this); + +typedef int32_t (*dumpop_inodectx_t)(xlator_t *this, inode_t *ino); + +typedef int32_t (*dumpop_fdctx_t)(xlator_t *this, fd_t *fd); + +typedef int32_t (*dumpop_priv_to_dict_t)(xlator_t *this, dict_t *dict, + char *brickname); + +typedef int32_t (*dumpop_inode_to_dict_t)(xlator_t *this, dict_t *dict); + +typedef int32_t (*dumpop_fd_to_dict_t)(xlator_t *this, dict_t *dict); + +typedef int32_t (*dumpop_inodectx_to_dict_t)(xlator_t *this, inode_t *ino, + dict_t *dict); + +typedef int32_t (*dumpop_fdctx_to_dict_t)(xlator_t *this, fd_t *fd, + dict_t *dict); + +typedef int32_t (*dumpop_eh_t)(xlator_t *this); + +struct xlator_dumpops { + dumpop_priv_t priv; + dumpop_inode_t inode; + dumpop_fd_t fd; + dumpop_inodectx_t inodectx; + dumpop_fdctx_t fdctx; + dumpop_priv_to_dict_t priv_to_dict; + dumpop_inode_to_dict_t inode_to_dict; + dumpop_fd_to_dict_t fd_to_dict; + dumpop_inodectx_to_dict_t inodectx_to_dict; + dumpop_fdctx_to_dict_t fdctx_to_dict; + dumpop_eh_t history; +}; + +typedef struct xlator_list { + xlator_t *xlator; + struct xlator_list *next; +} xlator_list_t; + +typedef struct fop_metrics { + gf_atomic_t fop; + gf_atomic_t cbk; /* only updaed when there is failure */ +} fop_metrics_t; + +struct _xlator { + /* Built during parsing */ + char *name; + char *type; + char *instance_name; /* Used for multi NFSd */ + xlator_t *next; + xlator_t *prev; + xlator_list_t *parents; + xlator_list_t *children; + dict_t *options; + + /* Set after doing dlopen() */ + void *dlhandle; + struct xlator_fops *fops; + struct xlator_cbks *cbks; + struct xlator_dumpops *dumpops; + struct list_head volume_options; /* list of volume_option_t */ + + void (*fini)(xlator_t *this); + int32_t (*init)(xlator_t *this); + int32_t (*reconfigure)(xlator_t *this, dict_t *options); + int32_t (*mem_acct_init)(xlator_t *this); + int32_t (*dump_metrics)(xlator_t *this, int fd); + + event_notify_fn_t notify; + + gf_loglevel_t loglevel; /* Log level for translator */ + + struct { + struct { + /* for latency measurement */ + fop_metrics_t metrics[GF_FOP_MAXVALUE]; + + gf_atomic_t count; + } total; + + struct { + /* for latency measurement */ + fop_latency_t latencies[GF_FOP_MAXVALUE]; + /* for latency measurement */ + fop_metrics_t metrics[GF_FOP_MAXVALUE]; + + gf_atomic_t count; + } interval; + } stats; + + /* Misc */ + eh_t *history; /* event history context */ + glusterfs_ctx_t *ctx; + glusterfs_graph_t *graph; /* not set for fuse */ + inode_table_t *itable; + char init_succeeded; + void *private; + struct mem_acct *mem_acct; + uint64_t winds; + char switched; + + /* for the memory pool of 'frame->local' */ + struct mem_pool *local_pool; + gf_boolean_t is_autoloaded; + + /* Saved volfile ID (used for multiplexing) */ + char *volfile_id; + + /* Its used as an index to inode_ctx*/ + uint32_t xl_id; + + /* op_version: initialized in xlator code itself */ + uint32_t op_version[GF_MAX_RELEASES]; + + /* flags: initialized in xlator code itself */ + uint32_t flags; + + /* id: unique, initialized in xlator code itself */ + uint32_t id; + + /* identifier: a full string which can unique identify the xlator */ + char *identifier; + + /* Is this pass_through? */ + gf_boolean_t pass_through; + struct xlator_fops *pass_through_fops; + + /* cleanup flag to avoid races during xlator cleanup */ + uint32_t cleanup_starting; + + /* flag to avoid recall of xlator_mem_cleanup for xame xlator */ + uint32_t call_cleanup; + + /* Flag to understand how this xlator is categorized */ + gf_category_t category; + + /* Variable to save fd_count for detach brick */ + gf_atomic_t fd_cnt; + + /* Variable to save xprt associated for detach brick */ + gf_atomic_t xprtrefcnt; + + /* Flag to notify got CHILD_DOWN event for detach brick */ + uint32_t notify_down; +}; + +typedef struct { + int32_t (*init)(xlator_t *this); + void (*fini)(xlator_t *this); + int32_t (*reconfigure)(xlator_t *this, dict_t *options); + event_notify_fn_t notify; +} class_methods_t; + +/* This would be the only structure which needs to be exported by + the translators. For the backward compatibility, in 4.x series + even the old exported fields will be supported */ +/* XXX: This struct is in use by GD2, and hence SHOULD NOT be modified. + * If the struct must be modified, see instructions at the comment with + * GD2MARKER below. + */ +typedef struct { + /* op_version: will be used by volume generation logic to figure + out whether to insert it in graph or no, based on cluster's + operating version. + default value: 0, which means good to insert always */ + uint32_t op_version[GF_MAX_RELEASES]; + + /* flags: will be used by volume generation logic to optimize the + placements etc. + default value: 0, which means don't treat it specially */ + uint32_t flags; + + /* xlator_id: unique per xlator. make sure to have no collission + in this ID */ + uint32_t xlator_id; + + /* identifier: a string constant */ + char *identifier; + + /* struct options: if the translator takes any 'options' from the + volume file, then that should be defined here. optional. */ + volume_option_t *options; + + /* Flag to understand how this xlator is categorized */ + gf_category_t category; + + /* XXX: GD2MARKER + * If a new member that needs to be visible to GD2 is introduced, + * add it above this comment. + * Any other new members need to be added below this comment, or at the + * end of the struct + */ + + /* init(): mandatory method, will be called during the + graph initialization */ + int32_t (*init)(xlator_t *this); + + /* fini(): optional method, will be initialized to default + method which would just free the 'xlator->private' variable. + This method is called when the graph is no more in use, and + is being destroyed. Also when SIGTERM is received */ + void (*fini)(xlator_t *this); + + /* reconfigure(): optional method, will be initialized to default + method in case not provided by xlator. This method is called + when there are only option changes in xlator, and no graph change. + eg., a 'gluster volume set' command */ + int32_t (*reconfigure)(xlator_t *this, dict_t *options); + + /* mem_acct_init(): used for memory accounting inside of the xlator. + optional. called during translator initialization */ + int32_t (*mem_acct_init)(xlator_t *this); + + /* dump_metrics(): used for providing internal metrics. optional */ + int32_t (*dump_metrics)(xlator_t *this, int fd); + + /* notify(): used for handling the notification of events from either + the parent or child in the graph. optional. */ + event_notify_fn_t notify; + + /* struct fops: mandatory. provides all the filesystem operations + methods of the xlator */ + struct xlator_fops *fops; + /* struct cbks: optional. provides methods to handle + inode forgets, and fd releases */ + struct xlator_cbks *cbks; + + /* dumpops: a structure again, with methods to dump the details. + optional. */ + struct xlator_dumpops *dumpops; + + /* struct pass_through_fops: optional. provides all the filesystem + operations which should be used if the xlator is marked as pass_through + */ + /* by default, the default_fops would be used */ + struct xlator_fops *pass_through_fops; +} xlator_api_t; + +#define xlator_has_parent(xl) (xl->parents != NULL) + +#define XLATOR_NOTIFY(ret, _xl, params...) \ + do { \ + xlator_t *_old_THIS = NULL; \ + \ + _old_THIS = THIS; \ + THIS = _xl; \ + \ + ret = _xl->notify(_xl, params); \ + \ + THIS = _old_THIS; \ + } while (0); + +int32_t +xlator_set_type_virtual(xlator_t *xl, const char *type); + +int32_t +xlator_set_type(xlator_t *xl, const char *type); + +int32_t +xlator_dynload(xlator_t *xl); + +xlator_t * +file_to_xlator_tree(glusterfs_ctx_t *ctx, FILE *fp); + +int +xlator_notify(xlator_t *this, int32_t event, void *data, ...); +int +xlator_init(xlator_t *this); +int +xlator_destroy(xlator_t *xl); + +int32_t +xlator_tree_init(xlator_t *xl); +int32_t +xlator_tree_free_members(xlator_t *xl); +int32_t +xlator_tree_free_memacct(xlator_t *xl); + +void +xlator_tree_fini(xlator_t *xl); + +void +xlator_foreach(xlator_t *this, void (*fn)(xlator_t *each, void *data), + void *data); + +void +xlator_foreach_depth_first(xlator_t *this, + void (*fn)(xlator_t *each, void *data), void *data); + +xlator_t * +xlator_search_by_name(xlator_t *any, const char *name); +xlator_t * +get_xlator_by_name(xlator_t *this, char *target); +xlator_t * +get_xlator_by_type(xlator_t *this, char *target); + +void +xlator_set_inode_lru_limit(xlator_t *this, void *data); + +void +inode_destroy_notify(inode_t *inode, const char *xlname); + +int +loc_copy(loc_t *dst, loc_t *src); +int +loc_copy_overload_parent(loc_t *dst, loc_t *src, inode_t *parent); +#define loc_dup(src, dst) loc_copy(dst, src) +void +loc_wipe(loc_t *loc); +int +loc_path(loc_t *loc, const char *bname); +void +loc_gfid(loc_t *loc, uuid_t gfid); +void +loc_pargfid(loc_t *loc, uuid_t pargfid); +char * +loc_gfid_utoa(loc_t *loc); +gf_boolean_t +loc_is_root(loc_t *loc); +int32_t +loc_build_child(loc_t *child, loc_t *parent, char *name); +gf_boolean_t +loc_is_nameless(loc_t *loc); +int +xlator_mem_acct_init(xlator_t *xl, int num_types); +int +is_gf_log_command(xlator_t *trans, const char *name, char *value); +int +glusterd_check_log_level(const char *value); +int +xlator_volopt_dynload(char *xlator_type, void **dl_handle, + volume_opt_list_t *vol_opt_handle); +enum gf_hdsk_event_notify_op { + GF_EN_DEFRAG_STATUS, + GF_EN_MAX, +}; +gf_boolean_t +is_graph_topology_equal(glusterfs_graph_t *graph1, glusterfs_graph_t *graph2); +int +glusterfs_volfile_reconfigure(FILE *newvolfile_fp, glusterfs_ctx_t *ctx); + +int +gf_volfile_reconfigure(int oldvollen, FILE *newvolfile_fp, glusterfs_ctx_t *ctx, + const char *oldvolfile); + +int +loc_touchup(loc_t *loc, const char *name); + +int +glusterfs_leaf_position(xlator_t *tgt); + +int +glusterfs_reachable_leaves(xlator_t *base, dict_t *leaves); + +int +xlator_subvolume_count(xlator_t *this); + +void +xlator_init_lock(void); +void +xlator_init_unlock(void); +int +copy_opts_to_child(xlator_t *src, xlator_t *dst, char *glob); + +int +glusterfs_delete_volfile_checksum(glusterfs_ctx_t *ctx, const char *volfile_id); +int +xlator_memrec_free(xlator_t *xl); + +void +xlator_mem_cleanup(xlator_t *this); + +void +handle_default_options(xlator_t *xl, dict_t *options); + +void +gluster_graph_take_reference(xlator_t *tree); +#endif /* _XLATOR_H */ |