#ifndef COMMON_H_ #define COMMON_H_ #include #include #include #include /* for TASK_COMM_LEN */ #include #include #include #include #include #include #include #include #ifdef KERNEL_HAS_LINUX_FILELOCK_H #include #endif #ifdef KERNEL_HAS_LINUX_STDARG_H #include #else #include #endif #include #include #include #include #ifdef KERNEL_HAS_SCHED_SIG_H #include #endif #include #include /** * NOTE: These timeouts can now be overridden by the connMessagingTimeouts * option in the configuration file. If that option is unset or set to <=0, we * still default to these constants. */ #define CONN_LONG_TIMEOUT 600000 #define CONN_MEDIUM_TIMEOUT 90000 #define CONN_SHORT_TIMEOUT 30000 #ifndef MIN #define MIN(a, b) \ ( ( (a) < (b) ) ? (a) : (b) ) #endif #ifndef MAX #define MAX(a, b) \ ( ( (a) < (b) ) ? (b) : (a) ) #endif #define SAFE_VFREE(p) \ do{ if(p) {vfree(p); (p)=NULL;} } while(0) #define SAFE_VFREE_NOSET(p) \ do{ if(p) vfree(p); } while(0) #define SAFE_KFREE(p) \ do{ if(p) {kfree(p); (p)=NULL;} } while(0) #define SAFE_KFREE_NOSET(p) \ do{ if(p) kfree(p); } while(0) #define SAFE_DESTRUCT(p, destructor) \ do{if(p) {destructor(p); (p)=NULL;} } while(0) #define SAFE_DESTRUCT_NOSET(p, destructor) \ do{if(p) destructor(p); } while(0) // typically used for optional out-args #define SAFE_ASSIGN(destPointer, sourceValue) \ do{ if(destPointer) {*(destPointer) = (sourceValue);} } while(0) // module name #ifndef BEEGFS_MODULE_NAME_STR #define BEEGFS_MODULE_NAME_STR "beegfs" #endif #define BEEGFS_THREAD_NAME_PREFIX_STR BEEGFS_MODULE_NAME_STR "_" // a printk-version that adds the module name and comm name #define printk_fhgfs(levelStr, fmtStr, ...) \ printk(levelStr BEEGFS_MODULE_NAME_STR ": " "%s(%u): " fmtStr, current->comm, \ (unsigned)current->pid, ## __VA_ARGS__) // for interrupt handling routines (does not print "current") #define printk_fhgfs_ir(levelStr, fmtStr, ...) \ printk(levelStr BEEGFS_MODULE_NAME_STR ": " fmtStr, ## __VA_ARGS__) // dumps stack in case of a buggy condition #define BEEGFS_BUG_ON(condition, msgStr) \ do { \ if(unlikely(condition) ) { \ printk_fhgfs(KERN_ERR, "%s:%d: BUG: %s (dumping stack...)\n", \ __func__, __LINE__, msgStr); \ dump_stack(); \ } \ } while(0) #ifdef LOG_DEBUG_MESSAGES #define printk_fhgfs_debug(levelStr, fmtStr, ...) \ printk(levelStr BEEGFS_MODULE_NAME_STR ": " "%s(%u): " fmtStr, current->comm, \ (unsigned)current->pid, ## __VA_ARGS__) #define printk_fhgfs_ir_debug(levelStr, fmtStr, ...) \ printk_fhgfs_ir(levelStr, fmtStr, ## __VA_ARGS__) #define BEEGFS_BUG_ON_DEBUG(condition, msgStr) BEEGFS_BUG_ON(condition, msgStr) #else // !LOG_DEBUG_MESSAGES #define printk_fhgfs_debug(levelStr, fmtStr, ...) \ do { /* nothing */ } while(0) #define printk_fhgfs_ir_debug(levelStr, fmtStr, ...) \ do { /* nothing */ } while(0) #define BEEGFS_BUG_ON_DEBUG(condition, msgStr) \ do { /* nothing */ } while(0) #endif // LOG_DEBUG_MESSAGES #ifdef BEEGFS_OPENTK_LOG_CONN_ERRORS #define printk_fhgfs_connerr(levelStr, fmtStr, ...) \ printk_fhgfs(levelStr, fmtStr, ## __VA_ARGS__) #else #define printk_fhgfs_connerr(levelStr, fmtStr, ...) /* logging of conn errors disabled */ #endif // BEEGFS_OPENTK_LOG_CONN_ERRORS // this macro mutes warnings about unused variables #define IGNORE_UNUSED_VARIABLE(a) do{ if( ((long)a)==1) {} } while(0) // this macro mutes warnings about unsused variables that are only used in debug build #ifdef BEEGFS_DEBUG #define IGNORE_UNUSED_DEBUG_VARIABLE(a) do{ /* do nothing */ } while(0) #else #define IGNORE_UNUSED_DEBUG_VARIABLE(a) do{ if( ((long)a)==1) {} } while(0) #endif //////////////////////////////////////////////////////// /* set_fs() / get_fs() macro hackery. * * set_fs() and get_fs() have disappeared with Linux kernel 5.10. * For older kernels, we employ some macros to make their use less of a hassle. */ //////////////////////////////////////////////////////// #define BEEGFS_CONCAT_(x, y) x ## y #define BEEGFS_CONCAT(x, y) BEEGFS_CONCAT_(x, y) #define BEEGFS_UNIQUE_NAME(prefix) BEEGFS_CONCAT(prefix, __LINE__) // Lifted from Linux 5.10 #if __has_attribute(__fallthrough__) #define BEEGFS_FALLTHROUGH __attribute__((__fallthrough__)) #else #define BEEGFS_FALLTHROUGH do {} while (0) /* FALLTHROUGH */ #endif /* Preprocessor hack to add statements that are executed on scope cleanup. * A for-loop that runs exactly 1 time is misused to execute the cleanup * statement. An assertion ensures that we didn't break from the inner loop, * to ensure the cleanup statement is executed. */ #define BEEGFS_FOR_SCOPE_(begin_stmt, end_stmt, name) \ for (int name = 0; !name; ({BUG_ON(!name);})) \ for (begin_stmt; !name++; end_stmt) #define BEEGFS_FOR_SCOPE(begin_stmt, end_stmt) \ BEEGFS_FOR_SCOPE_(begin_stmt, end_stmt, BEEGFS_UNIQUE_NAME(scope)) #ifdef KERNEL_HAS_GET_FS static inline mm_segment_t BEEGFS_BEGIN_PROCESS_CONTEXT(void) { mm_segment_t out = get_fs(); set_fs(KERNEL_DS); return out; } static inline void BEEGFS_END_PROCESS_CONTEXT(mm_segment_t *backup) { set_fs(*backup); } #define WITH_PROCESS_CONTEXT \ BEEGFS_FOR_SCOPE( \ mm_segment_t segment = BEEGFS_BEGIN_PROCESS_CONTEXT(), \ BEEGFS_END_PROCESS_CONTEXT(&segment)) #else #define WITH_PROCESS_CONTEXT #endif //////////////////////////////////////////////////////// // in 4.13 wait_queue_t got renamed to wait_queue_entry_t #if defined(KERNEL_HAS_WAIT_QUEUE_ENTRY_T) typedef wait_queue_entry_t wait_queue_t; #endif #if defined(KERNEL_HAS_64BIT_TIMESTAMPS) static inline struct timespec64 current_fs_time(struct super_block *sb) { struct timespec64 now; #if defined(KERNEL_HAS_KTIME_GET_COARSE_REAL_TS64) ktime_get_coarse_real_ts64(&now); return now; #elif defined(KERNEL_HAS_KTIME_GET_REAL_TS64) ktime_get_real_ts64(&now); return timespec64_trunc(now, sb->s_time_gran); #else now = current_kernel_time64(); return timespec64_trunc(now, sb->s_time_gran); #endif } #elif !defined(KERNEL_HAS_CURRENT_FS_TIME) static inline struct timespec current_fs_time(struct super_block *sb) { struct timespec now = current_kernel_time(); return timespec_trunc(now, sb->s_time_gran); } #endif /* Defined by and already included by one of the headers, so * no KernelFeatureDetection.mk detection required. * Note: Not in OsCompat.h, as OsCompat depends on Common.h. */ #ifndef _LINUX_UIDGID_H typedef unsigned kuid_t; typedef unsigned kgid_t; #define from_kuid(a, b) (b) #define from_kgid(a, b) (b) #define make_kuid(a, b) (b) #define make_kgid(a, b) (b) #endif #ifndef swap #define swap(a, b) do { typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; } while (0) #endif #undef BEEGFS_RDMA #ifndef BEEGFS_NO_RDMA #if defined(CONFIG_INFINIBAND) || defined(CONFIG_INFINIBAND_MODULE) #define BEEGFS_RDMA 1 #endif #endif static inline unsigned FhgfsCommon_getCurrentUserID(void); static inline unsigned FhgfsCommon_getCurrentGroupID(void); unsigned FhgfsCommon_getCurrentUserID(void) { return from_kuid(&init_user_ns, current_fsuid()); } unsigned FhgfsCommon_getCurrentGroupID(void) { return from_kgid(&init_user_ns, current_fsgid()); } // Helper function for getting file pointer static inline struct file * FhgfsCommon_getFileLock(struct file_lock *fileLock) { #if defined(KERNEL_HAS_FILE_LOCK_CORE) return fileLock->c.flc_file; #else return fileLock->fl_file; #endif } // Helper function to get PID from file lock static inline pid_t FhgfsCommon_getFileLockPID(struct file_lock *fileLock) { #if defined(KERNEL_HAS_FILE_LOCK_CORE) return fileLock->c.flc_pid; #else return fileLock->fl_pid; #endif } // Helper function to get lock type static inline unsigned char FhgfsCommon_getFileLockType(struct file_lock *flock) { #if defined(KERNEL_HAS_FILE_LOCK_CORE) return flock->c.flc_type; #else return flock->fl_type; #endif } // Helper function to get lock flags static inline unsigned int FhgfsCommon_getFileLockFlags(struct file_lock *fileLock) { #if defined(KERNEL_HAS_FILE_LOCK_CORE) return fileLock->c.flc_flags; #else return fileLock->fl_flags; #endif } /* * Debug definitions: * - LOG_DEBUG_MESSAGES: Enables logging of some extra debug messages that will not be * available otherwise. * - DEBUG_REFCOUNT: Enables debugging of ObjectReferencer::refCount. Error messages will * be logged if refCount is less than zero. */ /** * BEEGFS_KFREE_LIST() - destroys and kfree()s all element of a list, leaving an empty list * * expands to ``BEEGFS_KFREE_LIST_DTOR(List, ElemType, Member, (void))``, ie no destructor is * called. */ #define BEEGFS_KFREE_LIST(List, ElemType, Member) \ BEEGFS_KFREE_LIST_DTOR(List, ElemType, Member, (void)) /** * BEEGFS_KFREE_LIST_DTOR() - destroys and kfree()s all element of a list, leaving an empty list * @List the &struct list_head to free * @ElemType type of elements contained in the list * @Member name of the &struct list_head in @ElemType that links to the next element of the list * @Dtor for each element of the list, ``Dtor(entry)`` is evaluated before the entry is freed */ #define BEEGFS_KFREE_LIST_DTOR(List, ElemType, Member, Dtor) \ do { \ ElemType* entry; \ ElemType* n; \ list_for_each_entry_safe(entry, n, List, Member) \ { \ Dtor(entry); \ kfree(entry); \ } \ INIT_LIST_HEAD(List); \ } while (0) /** * Generic key comparison function for integer types and pointers, to be used by the * RBTREE_FUNCTIONS as KeyCmp. */ #define BEEGFS_RB_KEYCMP_LT_INTEGRAL(lhs, rhs) \ ( lhs < rhs ? -1 : (lhs == rhs ? 0 : 1) ) /** * BEEGFS_KFREE_RBTREE() - destroys and kfree()s all elements an rbtree * * expands to ``BEEGFS_KFREE_RBTREE_DTOR(TreeRoot, ElemType, Member, (void))``, ie no destructor is * called. */ #define BEEGFS_KFREE_RBTREE(TreeRoot, ElemType, Member) \ BEEGFS_KFREE_RBTREE_DTOR(TreeRoot, ElemType, Member, (void)) /** * BEEGFS_KFREE_RBTREE_DTOR() - destroys and kfree()s all elements an rbtree, leaving an empty tree * @TreeRoot &struct rb_root to free * @ElemType type of elements contained in the tree * @Member name of the &struct rb_node in @ElemType that links to further entries in the tree * @Dtor for each element of the tree, ``Dtor(elem)`` is evaluated before the entry is freed */ #define BEEGFS_KFREE_RBTREE_DTOR(TreeRoot, ElemType, Member, Dtor) \ do { \ ElemType* pos; \ ElemType* n; \ rbtree_postorder_for_each_entry_safe(pos, n, TreeRoot, Member) \ { \ Dtor(pos); \ kfree(pos); \ } \ *(TreeRoot) = RB_ROOT; \ } while (0) /** * BEEGFS_RBTREE_FUNCTIONS() - defines a default set of rbtree functions * @Access access modifier of generated functions * @NS namespace prefix for all defined functions * @RootTy type of the struct that contains the tree we are building functions for * @RootNode name of the &struct rb_root of our tree in @RootTy * @KeyTy type of the trees sort key * @ElemTy type of the tree element. must contain a field of type @KeyTy * @ElemKey name of the key member in @ElemTy (must be of type @KeyTy) * @ElemNode node of the &struct rb_node of our tree in @ElemTy * @KeyCmp function or macro used to compare to @KeyTy values for tree ordering * * This macro declares a number of functions with names prefixed by @NS: * * * ``Access ElemTy* NS##_find(const RootTy*, KeyTy key)`` finds the @ElemTy with key ``key`` and * returns it. If none exists, %NULL is returned. * * ``Access bool NS##_insert(RootTy*, ElemTy* data)`` inserts the element ``data`` into the tree * if no element with the same key exists and return %true. If an element with the same key does * exist, returns %false. * * ``Access ElemTy* NS##_insertOrReplace(RootTy*, ElemTy* data)`` inserts ``data`` into the tree * if no element with the same key exists or replaced the existing item with the same key. If no * item existed %NULL is returned, otherwise the pointer to the previous element is returned. * This is analogous to how std::map::operator[] works in C++. * * ``access void NS##_erase(RootTy*, ElemTy* data)`` removes ``data`` from the tree. ``data`` is * not freed or otherwise processed, this function only removes the item and rebalances the tree * if necessary. */ #define BEEGFS_RBTREE_FUNCTIONS(Access, NS, RootTy, RootNode, KeyTy, ElemTy, ElemKey, ElemNode, \ KeyCmp) \ __attribute__((unused)) \ Access ElemTy* NS##_find(const RootTy* root, KeyTy key) \ { \ struct rb_node* node = root->RootNode.rb_node; \ while (node) \ { \ ElemTy* data = rb_entry(node, ElemTy, ElemNode); \ int cmp = KeyCmp(key, data->ElemKey); \ \ if (cmp < 0) \ node = node->rb_left; \ else if (cmp > 0) \ node = node->rb_right; \ else \ return data; \ } \ return NULL; \ } \ __attribute__((unused)) \ Access bool NS##_insert(RootTy* root, ElemTy* data) \ { \ struct rb_node** new = &root->RootNode.rb_node; \ struct rb_node* parent = NULL; \ while (*new) \ { \ ElemTy* cur = container_of(*new, ElemTy, ElemNode); \ int cmp = KeyCmp(data->ElemKey, cur->ElemKey); \ \ parent = *new; \ if (cmp < 0) \ new = &(*new)->rb_left; \ else if (cmp > 0) \ new = &(*new)->rb_right; \ else \ return false; \ } \ rb_link_node(&data->ElemNode, parent, new); \ rb_insert_color(&data->ElemNode, &root->RootNode); \ return true; \ } \ __attribute__((unused)) \ Access ElemTy* NS##_insertOrReplace(RootTy* root, ElemTy* data) \ { \ ElemTy* existing; \ if (NS##_insert(root, data)) \ return NULL; \ \ existing = NS##_find(root, data->ElemKey); \ rb_replace_node(&existing->ElemNode, &data->ElemNode, &root->RootNode); \ return existing; \ } \ __attribute__((unused)) \ Access void NS##_erase(RootTy* root, ElemTy* data) \ { \ rb_erase(&data->ElemNode, &root->RootNode); \ } #define BEEGFS_RBTREE_FOR_EACH_ENTRY(Pos, Root, Node) \ for (Pos = rb_entry_safe(rb_first(Root), typeof(*Pos), Node); \ Pos; \ Pos = rb_entry_safe(rb_next(&Pos->Node), typeof(*Pos), Node)) /* version number of both the network protocol and the on-disk data structures that are versioned. * must be kept in sync with userspace. */ #define BEEGFS_DATA_VERSION ((uint32_t)0) #endif /*COMMON_H_*/