#define _OBD_SUPPORT
#include <libcfs/kp30.h>
+#include <lvfs.h>
/* global variables */
extern atomic_t obd_memory;
extern int obd_memmax;
extern unsigned int obd_fail_loc;
+extern unsigned int obd_fail_val;
extern unsigned int obd_debug_peer_on_timeout;
extern unsigned int obd_dump_on_timeout;
extern unsigned int obd_dump_on_eviction;
extern atomic_t obd_dirty_pages;
extern cfs_waitq_t obd_race_waitq;
extern int obd_race_state;
+extern unsigned int obd_alloc_fail_rate;
#define OBD_FAIL_MDS 0x100
#define OBD_FAIL_MDS_FS_SETUP 0x135
#define OBD_FAIL_MDS_RESEND 0x136
#define OBD_FAIL_MDS_LLOG_CREATE_FAILED 0x137
+#define OBD_FAIL_MDS_LOV_SYNC_RACE 0x138
+#define OBD_FAIL_MDS_OSC_PRECREATE 0x139
+#define OBD_FAIL_MDS_LLOG_SYNC_TIMEOUT 0x13a
#define OBD_FAIL_OST 0x200
#define OBD_FAIL_OST_CONNECT_NET 0x201
#define OBD_FAIL_OST_DROP_REQ 0x21d
#define OBD_FAIL_OST_SETATTR_CREDITS 0x21e
#define OBD_FAIL_OST_HOLD_WRITE_RPC 0x21f
+#define OBD_FAIL_OST_BRW_WRITE_BULK2 0x220
+#define OBD_FAIL_OST_LLOG_RECOVERY_TIMEOUT 0x221
+#define OBD_FAIL_OST_CANCEL_COOKIE_TIMEOUT 0x222
#define OBD_FAIL_LDLM 0x300
#define OBD_FAIL_LDLM_NAMESPACE_NEW 0x301
#define OBD_FAIL_LDLM_RECOV_CLIENTS 0x30d
#define OBD_FAIL_LDLM_ENQUEUE_OLD_EXPORT 0x30e
#define OBD_FAIL_LDLM_GLIMPSE 0x30f
+#define OBD_FAIL_LDLM_CANCEL_RACE 0x310
+#define OBD_FAIL_LDLM_CANCEL_EVICT_RACE 0x311
#define OBD_FAIL_OSC 0x400
#define OBD_FAIL_OSC_BRW_READ_BULK 0x401
#define OBD_FAIL_OSC_SHUTDOWN 0x407
#define OBD_FAIL_OSC_CHECKSUM_RECEIVE 0x408
#define OBD_FAIL_OSC_CHECKSUM_SEND 0x409
+#define OBD_FAIL_OSC_BRW_PREP_REQ2 0x40a
#define OBD_FAIL_PTLRPC 0x500
#define OBD_FAIL_PTLRPC_ACK 0x501
#define OBD_FAIL_PTLRPC_DROP_RPC 0x505
#define OBD_FAIL_PTLRPC_DELAY_SEND 0x506
#define OBD_FAIL_PTLRPC_DELAY_RECOV 0x507
+#define OBD_FAIL_PTLRPC_CLIENT_BULK_CB 0x508
#define OBD_FAIL_OBD_PING_NET 0x600
#define OBD_FAIL_OBD_LOG_CANCEL_NET 0x601
#define OBD_FAIL_MDC_REVALIDATE_PAUSE 0x800
#define OBD_FAIL_MDC_ENQUEUE_PAUSE 0x801
+#define OBD_FAIL_MDC_OLD_EXT_FLAGS 0x802
#define OBD_FAIL_MGS 0x900
#define OBD_FAIL_MGS_ALL_REQUEST_NET 0x901
#define OBD_FAIL_LPROC_REMOVE 0xB00
-/* preparation for a more advanced failure testbed (not functional yet) */
+#define OBD_FAIL_GENERAL_ALLOC 0xC00
+
+/* Failure injection control */
#define OBD_FAIL_MASK_SYS 0x0000FF00
-#define OBD_FAIL_MASK_LOC (0x000000FF | OBD_FAIL_MASK_SYS)
+#define OBD_FAIL_MASK_LOC (0x000000FF | OBD_FAIL_MASK_SYS)
#define OBD_FAIL_ONCE 0x80000000
#define OBD_FAILED 0x40000000
-
-#define OBD_FAIL_CHECK(id) (((obd_fail_loc & OBD_FAIL_MASK_LOC) == \
- ((id) & OBD_FAIL_MASK_LOC)) && \
- ((obd_fail_loc & (OBD_FAILED | OBD_FAIL_ONCE))!= \
- (OBD_FAILED | OBD_FAIL_ONCE)))
-
-#define OBD_FAIL_CHECK_ONCE(id) \
-({ int _ret_ = 0; \
- if (OBD_FAIL_CHECK(id)) { \
+/* The following flags aren't made to be combined */
+#define OBD_FAIL_SKIP 0x20000000 /* skip N then fail */
+#define OBD_FAIL_SOME 0x10000000 /* fail N times */
+#define OBD_FAIL_RAND 0x08000000 /* fail 1/N of the time */
+#define OBD_FAIL_USR1 0x04000000 /* user flag */
+
+static inline int obd_fail_check(__u32 id)
+{
+ static int count = 0;
+ if (likely((obd_fail_loc & OBD_FAIL_MASK_LOC) !=
+ (id & OBD_FAIL_MASK_LOC)))
+ return 0;
+
+ if ((obd_fail_loc & (OBD_FAILED | OBD_FAIL_ONCE)) ==
+ (OBD_FAILED | OBD_FAIL_ONCE)) {
+ count = 0; /* paranoia */
+ return 0;
+ }
+
+ if (obd_fail_loc & OBD_FAIL_RAND) {
+ unsigned int ll_rand(void);
+ if (obd_fail_val < 2)
+ return 0;
+ if (ll_rand() % obd_fail_val > 0)
+ return 0;
+ }
+
+ if (obd_fail_loc & OBD_FAIL_SKIP) {
+ count++;
+ if (count < obd_fail_val)
+ return 0;
+ count = 0;
+ }
+
+ /* Overridden by FAIL_ONCE */
+ if (obd_fail_loc & OBD_FAIL_SOME) {
+ count++;
+ if (count >= obd_fail_val) {
+ count = 0;
+ /* Don't fail anymore */
+ obd_fail_loc |= OBD_FAIL_ONCE;
+ }
+ }
+
+ obd_fail_loc |= OBD_FAILED;
+ /* Handle old checks that OR in this */
+ if (id & OBD_FAIL_ONCE)
+ obd_fail_loc |= OBD_FAIL_ONCE;
+
+ return 1;
+}
+
+#define OBD_FAIL_CHECK(id) \
+({ \
+ int _ret_ = 0; \
+ if (unlikely(obd_fail_loc && (_ret_ = obd_fail_check(id)))) { \
CERROR("*** obd_fail_loc=%x ***\n", id); \
- obd_fail_loc |= OBD_FAILED; \
- if ((id) & OBD_FAIL_ONCE) \
- obd_fail_loc |= OBD_FAIL_ONCE; \
- _ret_ = 1; \
} \
_ret_; \
})
+/* deprecated - just use OBD_FAIL_CHECK */
+#define OBD_FAIL_CHECK_ONCE OBD_FAIL_CHECK
+
#define OBD_FAIL_RETURN(id, ret) \
do { \
- if (OBD_FAIL_CHECK_ONCE(id)) { \
+ if (unlikely(obd_fail_loc && obd_fail_check(id))) { \
+ CERROR("*** obd_fail_return=%x rc=%d ***\n", id, ret); \
RETURN(ret); \
} \
} while(0)
#define OBD_FAIL_TIMEOUT(id, secs) \
-do { \
- if (OBD_FAIL_CHECK_ONCE(id)) { \
+({ int _ret_ = 0; \
+ if (unlikely(obd_fail_loc && (_ret_ = obd_fail_check(id)))) { \
CERROR("obd_fail_timeout id %x sleeping for %d secs\n", \
(id), (secs)); \
set_current_state(TASK_UNINTERRUPTIBLE); \
cfs_time_seconds(secs)); \
set_current_state(TASK_RUNNING); \
CERROR("obd_fail_timeout id %x awake\n", (id)); \
- } \
-} while(0)
+ } \
+ _ret_; \
+})
+
+#define OBD_FAIL_TIMEOUT_MS(id, ms) \
+({ int _ret_ = 0; \
+ if (unlikely(obd_fail_loc && (_ret_ = obd_fail_check(id)))) { \
+ CERROR("obd_fail_timeout id %x sleeping for %d ms\n", \
+ (id), (ms)); \
+ set_current_state(TASK_UNINTERRUPTIBLE); \
+ cfs_schedule_timeout(CFS_TASK_UNINT, \
+ cfs_time_seconds(ms)/1000); \
+ set_current_state(TASK_RUNNING); \
+ CERROR("obd_fail_timeout id %x awake\n", (id)); \
+ } \
+ _ret_; \
+})
#ifdef __KERNEL__
/* The idea here is to synchronise two threads to force a race. The
* the first and continues. */
#define OBD_RACE(id) \
do { \
- if (OBD_FAIL_CHECK_ONCE(id)) { \
+ if (unlikely(obd_fail_loc && obd_fail_check(id))) { \
obd_race_state = 0; \
CERROR("obd_race id %x sleeping\n", (id)); \
OBD_SLEEP_ON(obd_race_waitq, obd_race_state != 0); \
extern atomic_t libcfs_kmemory;
+#ifdef RANDOM_FAIL_ALLOC
+#define HAS_FAIL_ALLOC_FLAG OBD_FAIL_CHECK(OBD_FAIL_GENERAL_ALLOC)
+#else
+#define HAS_FAIL_ALLOC_FLAG 0
+#endif
+
+#define OBD_ALLOC_FAIL_BITS 24
+#define OBD_ALLOC_FAIL_MASK ((1 << OBD_ALLOC_FAIL_BITS) - 1)
+#define OBD_ALLOC_FAIL_MULT (OBD_ALLOC_FAIL_MASK / 100)
+
#if defined(LUSTRE_UTILS) /* this version is for utils only */
#define OBD_ALLOC_GFP(ptr, size, gfp_mask) \
do { \
} \
} while (0)
#else /* this version is for the kernel and liblustre */
+#define OBD_FREE_RTN0(ptr) \
+({ \
+ cfs_free(ptr); \
+ (ptr) = NULL; \
+ 0; \
+})
#define OBD_ALLOC_GFP(ptr, size, gfp_mask) \
do { \
(ptr) = cfs_alloc(size, (gfp_mask)); \
- if ((ptr) == NULL) { \
- CERROR("kmalloc of '" #ptr "' (%d bytes) failed at %s:%d\n", \
- (int)(size), __FILE__, __LINE__); \
- CERROR("%d total bytes allocated by Lustre, %d by Portals\n", \
- atomic_read(&obd_memory), atomic_read(&libcfs_kmemory));\
- } else { \
+ if (likely((ptr) != NULL && \
+ (!HAS_FAIL_ALLOC_FLAG || obd_alloc_fail_rate == 0 || \
+ !obd_alloc_fail(ptr, #ptr, "km", size, \
+ __FILE__, __LINE__) || \
+ OBD_FREE_RTN0(ptr)))){ \
memset(ptr, 0, size); \
atomic_add(size, &obd_memory); \
if (atomic_read(&obd_memory) > obd_memmax) \
(ptr) = (void *)0xdeadbeef; \
} while (0)
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
-# define my_call_rcu(rcu, cb) (cb)(rcu)
+#ifdef HAVE_RCU
+# ifdef HAVE_CALL_RCU_PARAM
+# define my_call_rcu(rcu, cb) call_rcu(rcu, cb, rcu)
+# else
+# define my_call_rcu(rcu, cb) call_rcu(rcu, cb)
+# endif
#else
-# define my_call_rcu(rcu, cb, ...) call_rcu(rcu, cb)
+# define my_call_rcu(rcu, cb) (cb)(rcu)
#endif
#define OBD_FREE_RCU_CB(ptr, size, handle, free_cb) \
/* we memset() the slab object to 0 when allocation succeeds, so DO NOT
* HAVE A CTOR THAT DOES ANYTHING. its work will be cleared here. we'd
* love to assert on that, but slab.c keeps kmem_cache_s all to itself. */
+#define OBD_SLAB_FREE_RTN0(ptr, slab) \
+({ \
+ cfs_mem_cache_free((slab), (ptr)); \
+ (ptr) = NULL; \
+ 0; \
+})
#define OBD_SLAB_ALLOC(ptr, slab, type, size) \
do { \
LASSERT(!in_interrupt()); \
(ptr) = cfs_mem_cache_alloc(slab, (type)); \
- if ((ptr) == NULL) { \
- CERROR("slab-alloc of '"#ptr"' (%d bytes) failed at %s:%d\n", \
- (int)(size), __FILE__, __LINE__); \
- CERROR("%d total bytes allocated by Lustre, %d by Portals\n", \
- atomic_read(&obd_memory), atomic_read(&libcfs_kmemory));\
- } else { \
+ if (likely((ptr) != NULL && \
+ (!HAS_FAIL_ALLOC_FLAG || obd_alloc_fail_rate == 0 || \
+ !obd_alloc_fail(ptr, #ptr, "slab-", size, \
+ __FILE__, __LINE__) || \
+ OBD_SLAB_FREE_RTN0(ptr, slab)))) { \
memset(ptr, 0, size); \
atomic_add(size, &obd_memory); \
if (atomic_read(&obd_memory) > obd_memmax) \
(ptr) = (void *)0xdeadbeef; \
} while (0)
+#define OBD_SLAB_ALLOC_PTR(ptr, slab) \
+ OBD_SLAB_ALLOC((ptr), (slab), CFS_ALLOC_STD, sizeof *(ptr))
+#define OBD_SLAB_FREE_PTR(ptr, slab) \
+ OBD_SLAB_FREE((ptr), (slab), sizeof *(ptr))
+
#define KEY_IS(str) (keylen >= strlen(key) && strcmp(key, str) == 0)
#if defined(__linux__)