When converting to thread safe implementation, I missed the need for
the conn mutex to trylock because we may be holding the kgn_peer_conn
lock.
Change conn mutex to use a trylock in kgnilnd_sendmsg_trylock().
Add the module parameter thread_safe.
Disable thread safe on gemini.
In kgnilnd_create_conn(), use NOFS flag when vmalloc the tx_ref_table
to avoid possible hangs because of OOM condition.
Clean up info message for down event.
Signed-off-by: Chris Horn <hornc@cray.com>
Change-Id: I1896c12b421ae35f65d1816bbe3eb5599b664498
Reviewed-on: http://review.whamcloud.com/15434
Tested-by: Jenkins
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: James Simmons <uja.ornl@yahoo.com>
Reviewed-by: James Shimek <jshimek@cray.com>
Reviewed-by: Doug Oucharek <doug.s.oucharek@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
- LIBCFS_ALLOC(conn->gnc_tx_ref_table, GNILND_MAX_MSG_ID * sizeof(void *));
+ conn->gnc_tx_ref_table =
+ kgnilnd_vmalloc(GNILND_MAX_MSG_ID * sizeof(void *));
if (conn->gnc_tx_ref_table == NULL) {
CERROR("Can't allocate conn tx_ref_table\n");
GOTO(failed, rc = -ENOMEM);
if (conn->gnc_tx_ref_table == NULL) {
CERROR("Can't allocate conn tx_ref_table\n");
GOTO(failed, rc = -ENOMEM);
*/
kgnilnd_txlist_done(&zombies, -ENETRESET);
kgnilnd_peer_notify(peer, -ECONNRESET, 0);
*/
kgnilnd_txlist_done(&zombies, -ENETRESET);
kgnilnd_peer_notify(peer, -ECONNRESET, 0);
- LCONSOLE_INFO("Recieved down event for nid %lld\n", nid);
+ LCONSOLE_INFO("Received down event for nid %d\n",
+ LNET_NIDADDR(nid));
int *kgn_efault_lbug; /* LBUG on receiving an EFAULT */
int *kgn_max_purgatory; /* # conns/peer to keep in purgatory */
int *kgn_thread_affinity; /* bind scheduler threads to cpus */
int *kgn_efault_lbug; /* LBUG on receiving an EFAULT */
int *kgn_max_purgatory; /* # conns/peer to keep in purgatory */
int *kgn_thread_affinity; /* bind scheduler threads to cpus */
+ int *kgn_thread_safe; /* use thread safe kgni API */
#if CONFIG_SYSCTL && !CFS_SYSFS_MODULE_PARM
cfs_sysctl_table_header_t *kgn_sysctl; /* sysctl interface */
#endif
#if CONFIG_SYSCTL && !CFS_SYSFS_MODULE_PARM
cfs_sysctl_table_header_t *kgn_sysctl; /* sysctl interface */
#endif
atomic_dec(&kgnilnd_data.kgn_nthreads);
}
atomic_dec(&kgnilnd_data.kgn_nthreads);
}
-static inline int kgnilnd_gl_mutex_trylock(struct mutex *lock)
-{
- if (kgnilnd_data.kgn_enable_gl_mutex)
- return mutex_trylock(lock);
- else
- return 1;
-}
-
static inline void kgnilnd_gl_mutex_lock(struct mutex *lock)
{
if (kgnilnd_data.kgn_enable_gl_mutex)
static inline void kgnilnd_gl_mutex_lock(struct mutex *lock)
{
if (kgnilnd_data.kgn_enable_gl_mutex)
* This function must not be used in interrupt context. The
* mutex must be released by the same task that acquired it.
*/
* This function must not be used in interrupt context. The
* mutex must be released by the same task that acquired it.
*/
-static inline int kgnilnd_mutex_trylock(struct mutex *lock)
+static inline int __kgnilnd_mutex_trylock(struct mutex *lock)
{
int ret;
unsigned long timeout;
{
int ret;
unsigned long timeout;
- if (!kgnilnd_data.kgn_enable_gl_mutex)
- return 1;
-
LASSERT(!in_interrupt());
for (timeout = jiffies + 1; time_before(jiffies, timeout);) {
LASSERT(!in_interrupt());
for (timeout = jiffies + 1; time_before(jiffies, timeout);) {
+static inline int kgnilnd_mutex_trylock(struct mutex *lock)
+{
+ if (!kgnilnd_data.kgn_enable_gl_mutex)
+ return 1;
+
+ return __kgnilnd_mutex_trylock(lock);
+}
+
+static inline int kgnilnd_trylock(struct mutex *cq_lock,
+ struct mutex *c_lock)
+{
+ if (kgnilnd_data.kgn_enable_gl_mutex)
+ return __kgnilnd_mutex_trylock(cq_lock);
+ else
+ return __kgnilnd_mutex_trylock(c_lock);
+}
+
+static inline void *kgnilnd_vmalloc(int size)
+{
+ void *ret = __vmalloc(size, __GFP_HIGHMEM | GFP_NOFS, PAGE_KERNEL);
+ LIBCFS_ALLOC_POST(ret, size);
+ return ret;
+}
+
/* Copied from DEBUG_REQ in Lustre - the dance is needed to save stack space */
extern void
/* Copied from DEBUG_REQ in Lustre - the dance is needed to save stack space */
extern void
}
symbol_put(kgni_driver_version);
}
symbol_put(kgni_driver_version);
+
+ if (!*kgnilnd_tunables.kgn_thread_safe) {
+ return;
+ }
+
/* Use thread-safe locking */
kgnilnd_data.kgn_enable_gl_mutex = 0;
}
/* Use thread-safe locking */
kgnilnd_data.kgn_enable_gl_mutex = 0;
}
/* Thread-safe kgni implemented in minor ver 45, code rev 0xb9 */
#define GNILND_KGNI_TS_MINOR_VER 0x45
/* Thread-safe kgni implemented in minor ver 45, code rev 0xb9 */
#define GNILND_KGNI_TS_MINOR_VER 0x45
+#define GNILND_TS_ENABLE 1
/* plug in our functions for use on the simulator */
#if !defined(GNILND_USE_RCA)
/* plug in our functions for use on the simulator */
#if !defined(GNILND_USE_RCA)
*/
msg->gnm_connstamp = conn->gnc_my_connstamp;
msg->gnm_payload_len = immediatenob;
*/
msg->gnm_connstamp = conn->gnc_my_connstamp;
msg->gnm_payload_len = immediatenob;
- kgnilnd_conn_mutex_lock(&conn->gnc_smsg_mutex);
msg->gnm_seq = atomic_read(&conn->gnc_tx_seq);
/* always init here - kgn_checksum is a /sys module tunable
msg->gnm_seq = atomic_read(&conn->gnc_tx_seq);
/* always init here - kgn_checksum is a /sys module tunable
timestamp = jiffies;
kgnilnd_gl_mutex_lock(&dev->gnd_cq_mutex);
timestamp = jiffies;
kgnilnd_gl_mutex_lock(&dev->gnd_cq_mutex);
+ kgnilnd_conn_mutex_lock(&tx->tx_conn->gnc_smsg_mutex);
/* delay in jiffies - we are really concerned only with things that
* result in a schedule() or really holding this off for long times .
* NB - mutex_lock could spin for 2 jiffies before going to sleep to wait */
/* delay in jiffies - we are really concerned only with things that
* result in a schedule() or really holding this off for long times .
* NB - mutex_lock could spin for 2 jiffies before going to sleep to wait */
rc = 0;
} else {
atomic_inc(&conn->gnc_device->gnd_fast_try);
rc = 0;
} else {
atomic_inc(&conn->gnc_device->gnd_fast_try);
- rc = kgnilnd_gl_mutex_trylock(&conn->gnc_device->gnd_cq_mutex);
+ rc = kgnilnd_trylock(&conn->gnc_device->gnd_cq_mutex,
+ &conn->gnc_smsg_mutex);
}
if (!rc) {
rc = -EAGAIN;
}
if (!rc) {
rc = -EAGAIN;
/* Thread-safe kgni implemented in minor ver 44, code rev 0xb9 */
#define GNILND_KGNI_TS_MINOR_VER 0x44
/* Thread-safe kgni implemented in minor ver 44, code rev 0xb9 */
#define GNILND_KGNI_TS_MINOR_VER 0x44
+#define GNILND_TS_ENABLE 0
#endif /* _GNILND_GEMINI_H */
#endif /* _GNILND_GEMINI_H */
static int thread_affinity = 0;
CFS_MODULE_PARM(thread_affinity, "i", int, 0444,
static int thread_affinity = 0;
CFS_MODULE_PARM(thread_affinity, "i", int, 0444,
- "scheduler thread affinity default 0 (diabled)");
+ "scheduler thread affinity default 0 (disabled)");
+
+static int thread_safe = GNILND_TS_ENABLE;
+CFS_MODULE_PARM(thread_safe, "i", int, 0444,
+ "Use kgni thread safe API if available");
kgn_tunables_t kgnilnd_tunables = {
.kgn_min_reconnect_interval = &min_reconnect_interval,
kgn_tunables_t kgnilnd_tunables = {
.kgn_min_reconnect_interval = &min_reconnect_interval,
.kgn_fast_reconn = &fast_reconn,
.kgn_efault_lbug = &efault_lbug,
.kgn_thread_affinity = &thread_affinity,
.kgn_fast_reconn = &fast_reconn,
.kgn_efault_lbug = &efault_lbug,
.kgn_thread_affinity = &thread_affinity,
+ .kgn_thread_safe = &thread_safe,
.kgn_max_purgatory = &max_conn_purg
};
.kgn_max_purgatory = &max_conn_purg
};
+ .procname = "thread_safe"
+ .data = &thread_safe,
+ .maxlen = sizeof(int),
+ .mode = 0444,
+ .proc_handler = &proc_dointvec
+ },
+ {
+ INIT_CTL_NAME
.procname = "max_conn_purg"
.data = &max_conn_purg,
.maxlen = sizeof(int),
.procname = "max_conn_purg"
.data = &max_conn_purg,
.maxlen = sizeof(int),