#endif
};
+struct ptlrpc_thread;
+
+/*
+ * Descriptor of per-thread data.
+ */
+struct ptlrpc_thread_key {
+ void *(*ptk_init)(struct ptlrpc_thread *t);
+ void (*ptk_fini)(struct ptlrpc_thread *t, void *data);
+ int ptk_index;
+};
+
+int ptlrpc_thread_key_register(struct ptlrpc_thread_key *key);
+void *ptlrpc_thread_key_get(struct ptlrpc_thread *t,
+ struct ptlrpc_thread_key *key);
+
struct ptlrpc_thread {
struct list_head t_link; /* active threads for service, from svc->srv_threads */
unsigned int t_id; /* service thread index, from ptlrpc_start_threads */
wait_queue_head_t t_ctl_waitq;
+
+ void **t_key_values;
};
struct ptlrpc_request_buffer_desc {
LASSERT (nbufs > 0);
LASSERT (bufsize >= max_req_size);
-
+
OBD_ALLOC(service, sizeof(*service));
if (service == NULL)
RETURN(NULL);
spin_lock (&ptlrpc_all_services_lock);
list_add (&service->srv_list, &ptlrpc_all_services);
spin_unlock (&ptlrpc_all_services_lock);
-
+
/* Now allocate the request buffers */
rc = ptlrpc_grow_req_bufs(service);
/* We shouldn't be under memory pressure at startup, so
return (-ETIMEDOUT);
}
+enum {
+ /*
+ * Maximal number of tld slots.
+ */
+ PTLRPC_THREAD_KEY_NR = 16
+};
+
+static struct ptlrpc_thread_key *keys[PTLRPC_THREAD_KEY_NR] = { NULL, };
+
+static int keys_nr = 0;
+static spinlock_t keys_guard = SPIN_LOCK_UNLOCKED;
+
+int ptlrpc_thread_key_register(struct ptlrpc_thread_key *key)
+{
+ int result;
+
+ spin_lock(&keys_guard);
+ if (keys_nr < ARRAY_SIZE(keys)) {
+ key->ptk_index = keys_nr;
+ keys[keys_nr] = key;
+ keys_nr++;
+ result = 0;
+ } else
+ result = -ENFILE;
+ spin_unlock(&keys_guard);
+ return result;
+}
+
+void *ptlrpc_thread_key_get(struct ptlrpc_thread *t,
+ struct ptlrpc_thread_key *key)
+{
+ return t->t_key_values[key->ptk_index];
+}
+
+static void keys_fini(struct ptlrpc_thread *t)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(keys); ++i) {
+ if (t->t_key_values[i] != NULL) {
+ LASSERT(keys[i] != NULL);
+ LASSERT(keys[i]->ptk_fini != NULL);
+
+ keys[i]->ptk_fini(t, t->t_key_values[i]);
+ t->t_key_values[i] = NULL;
+ }
+ }
+}
+
+static int keys_init(struct ptlrpc_thread *t)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(keys); ++i) {
+ if (keys[i] != NULL) {
+ void *value;
+
+ LASSERT(keys[i]->ptk_init != NULL);
+ LASSERT(keys[i]->ptk_index == i);
+
+ value = keys[i]->ptk_init(t);
+ if (IS_ERR(value)) {
+ keys_fini(t);
+ return PTR_ERR(value);
+ }
+ t->t_key_values[i] = value;
+ }
+ }
+ return 0;
+}
+
static int ptlrpc_main(void *arg)
{
struct ptlrpc_svc_data *data = (struct ptlrpc_svc_data *)arg;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,4)
struct group_info *ginfo = NULL;
#endif
+
+ void *tld[PTLRPC_THREAD_KEY_NR] = { NULL, };
int rc = 0;
ENTRY;
goto out;
}
+ thread->t_key_values = tld;
+ rc = keys_init(thread);
+ if (rc)
+ goto out_srv_init;
+
/* Alloc reply state structure for this one */
OBD_ALLOC_GFP(rs, svc->srv_max_reply_size, GFP_KERNEL);
if (!rs) {
svc->srv_done(thread);
out:
+ keys_fini(thread);
+
CDEBUG(D_NET, "service thread %d exiting: rc %d\n", thread->t_id, rc);
spin_lock_irqsave(&svc->srv_lock, flags);
* its 'unlink' flag set for each posted rqbd */
list_for_each(tmp, &service->srv_active_rqbds) {
struct ptlrpc_request_buffer_desc *rqbd =
- list_entry(tmp, struct ptlrpc_request_buffer_desc,
+ list_entry(tmp, struct ptlrpc_request_buffer_desc,
rqbd_list);
rc = LNetMDUnlink(rqbd->rqbd_md_h);