OOM can produce a many issues like requests processing counter.
Change-Id: I8d417d148b589ea6de84c5d16bc2607a59852564
Signed-off-by: Alexey Lyashkov <alexey_lyashkov@xyratex.com>
Reviewed-on: http://review.whamcloud.com/1088
Tested-by: Hudson
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Tested-by: Maloo <whamcloud.maloo@gmail.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
])
])
+AC_DEFUN([LIBCFS_HAVE_OOM_H],
+[LB_CHECK_FILE([$LINUX/include/linux/oom.h], [
+ AC_DEFINE(HAVE_LINUX_OOM_H, 1,
+ [kernel has include/oom.h])
+],[
+ AC_MSG_RESULT([no])
+])
+])
+
+# 2.6.18 store oom parameters in task struct.
+# 2.6.32 store oom parameters in signal struct
+AC_DEFUN([LIBCFS_OOMADJ_IN_SIG],
+[AC_MSG_CHECKING([kernel store oom parameters in task])
+LB_LINUX_TRY_COMPILE([
+ #include <linux/sched.h>
+],[
+ struct signal_struct s;
+
+ s.oom_adj = 0;
+],[
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_OOMADJ_IN_SIG, 1,
+ [kernel store a oom parameters in signal struct])
+],[
+ AC_MSG_RESULT(no)
+])
+])
+
#
# LIBCFS_ADD_WAIT_QUEUE_EXCLUSIVE
#
# 2.6.32
LIBCFS_STACKTRACE_OPS_HAVE_WALK_STACK
LC_SHRINKER_WANT_SHRINK_PTR
+LIBCFS_HAVE_OOM_H
+LIBCFS_OOMADJ_IN_SIG
# 2.6.34
LIBCFS_ADD_WAIT_QUEUE_EXCLUSIVE
])
#define CLONE_SIGNAL (CLONE_SIGHAND | CLONE_THREAD)
-extern int cfs_kernel_thread(cfs_thread_t func, void *arg, int flag);
+#define CFS_DAEMON_FLAGS (CLONE_VM | CLONE_FILES)
+
+extern int cfs_create_thread(cfs_thread_t func, void *arg, unsigned long flag);
/*
/* Kernel thread */
typedef int (*cfs_thread_t)(void *);
-static inline int cfs_kernel_thread(int (*fn)(void *),
- void *arg, unsigned long flags)
-{
- void *orig_info = current->journal_info;
- int rc;
-
- current->journal_info = NULL;
- rc = kernel_thread(fn, arg, flags);
- current->journal_info = orig_info;
- return rc;
-}
-
+#define CFS_DAEMON_FLAGS (CLONE_VM | CLONE_FILES)
+extern int cfs_create_thread(int (*fn)(void *),
+ void *arg, unsigned long flags);
/*
* Task struct
#define cfs_sigfillset(l) do {} while (0)
#define cfs_recalc_sigpending(l) do {} while (0)
/* Fine, crash, but stop giving me compile warnings */
-#define cfs_kernel_thread(l,m,n) (LBUG(), l, 0)
#define cfs_kthread_run(fn,d,fmt,...) LBUG()
+#define CFS_DAEMON_FLAGS 0
+
#ifdef HAVE_LIBPTHREAD
typedef int (*cfs_thread_t)(void *);
-int cfs_create_thread(cfs_thread_t func, void *arg);
+int cfs_create_thread(cfs_thread_t func, void *arg, unsigned long flags);
#else
#define cfs_create_thread(l,m) LBUG()
#endif
void * arg;
} cfs_thread_context_t;
-int cfs_kernel_thread(int (*func)(void *), void *arg, int flag);
+int cfs_create_thread(int (*func)(void *), void *arg, unsigned long flag);
/*
* thread creation flags from Linux, not used in winnt
#define CLONE_SIGNAL (CLONE_SIGHAND | CLONE_THREAD)
+#define CFS_DAEMON_FLAGS (CLONE_VM|CLONE_FILES)
/*
* group_info: linux/sched.h
extern thread_t kernel_thread(task_t task, void (*start)(void));
int
-cfs_kernel_thread(cfs_thread_t func, void *arg, int flag)
+cfs_create_thread(cfs_thread_t func, void *arg, unsigned long flag)
{
int ret = 0;
thread_t th = NULL;
return 1;
else if (is_addr_in_range(addr, trap, syscall_trace))
return 1;
- else if (is_addr_in_range(addr, cfs_thread_agent, cfs_kernel_thread))
+ else if (is_addr_in_range(addr, cfs_thread_agent, cfs_create_thread))
return 1;
else
return 0;
else
cfs_waitq_wait(&wait, CFS_TASK_INTERRUPTIBLE);
- /* be sure to teardown if cfs_kernel_thread() failed */
+ /* be sure to teardown if cfs_create_thread() failed */
cfs_waitq_del(&debug_ctlwq, &wait);
cfs_set_current_state(CFS_TASK_RUNNING);
}
*/
# define DEBUG_SUBSYSTEM S_LNET
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+
+#ifdef HAVE_LINUX_OOM_H
+#include <linux/oom.h>
+#else
+#include <linux/mm.h>
+#endif
+
+int oom_get_adj(struct task_struct *task, int scope)
+{
+
+ int oom_adj;
+#ifdef HAVE_OOMADJ_IN_SIG
+ unsigned long flags;
+
+ spin_lock_irqsave(&task->sighand->siglock, flags);
+ oom_adj = task->signal->oom_adj;
+ task->signal->oom_adj = scope;
+ spin_unlock_irqrestore(&task->sighand->siglock, flags);
+
+#else
+ oom_adj = task->oomkilladj;
+ task->oomkilladj = scope;
+#endif
+ return oom_adj;
+}
+
+int cfs_create_thread(int (*fn)(void *),
+ void *arg, unsigned long flags)
+{
+ void *orig_info = current->journal_info;
+ int rc;
+ int old_oom;
+
+ old_oom = oom_get_adj(current, OOM_DISABLE);
+ current->journal_info = NULL;
+ rc = kernel_thread(fn, arg, flags);
+ current->journal_info = orig_info;
+ oom_get_adj(current, old_oom);
+
+ return rc;
+}
+EXPORT_SYMBOL(cfs_create_thread);
cfs_waitq_init(&tctl->tctl_waitq);
cfs_atomic_set(&tctl->tctl_shutdown, 0);
- if (cfs_kernel_thread(tracefiled, tctl, 0) < 0) {
+ if (cfs_create_thread(tracefiled, tctl, 0) < 0) {
rc = -ECHILD;
goto out;
}
(void)f(arg);
return NULL;
}
-int cfs_create_thread(cfs_thread_t func, void *arg)
+
+int cfs_create_thread(cfs_thread_t func, void *arg, unsigned long flags)
{
pthread_t tid;
pthread_attr_t tattr;
cfs_waitq_init(&lcw_event_waitq);
CDEBUG(D_INFO, "starting dispatch thread\n");
- rc = cfs_kernel_thread(lcw_dispatch_main, NULL, 0);
+ rc = cfs_create_thread(lcw_dispatch_main, NULL, 0);
if (rc < 0) {
CERROR("error spawning watchdog dispatch thread: %d\n", rc);
EXIT;
}
/*
- * cfs_kernel_thread
+ * cfs_create_thread
* Create a system thread to execute the routine specified
*
* Arguments:
* N/A
*/
-int cfs_kernel_thread(int (*func)(void *), void *arg, int flag)
+int cfs_create_thread(int (*func)(void *), void *arg, unsigned long flag)
{
cfs_handle_t thread = NULL;
NTSTATUS status;
cfs_init_event(&ks_data.ksnd_engine_mgr[i].start, TRUE, FALSE);
cfs_init_event(&ks_data.ksnd_engine_mgr[i].exit, TRUE, FALSE);
CFS_INIT_LIST_HEAD(&ks_data.ksnd_engine_mgr[i].list);
- cfs_kernel_thread(KsDeliveryEngineThread, &ks_data.ksnd_engine_mgr[i], 0);
+ cfs_create_thread(KsDeliveryEngineThread, &ks_data.ksnd_engine_mgr[i], 0);
}
/* register pnp handlers to watch network condition */
{
long pid;
- pid = cfs_kernel_thread(func, arg, 0);
+ pid = cfs_create_thread(func, arg, 0);
if (pid < 0)
return (int)pid;
cfs_atomic_inc(&kmxlnd_data.kmx_nthreads);
cfs_init_completion(&kmxlnd_data.kmx_completions[i]);
- pid = cfs_kernel_thread (fn, arg, 0);
+ pid = cfs_create_thread(fn, arg, 0);
if (pid < 0) {
- CERROR("cfs_kernel_thread() failed with %d\n", pid);
+ CERROR("cfs_create_thread() failed with %d\n", pid);
cfs_atomic_dec(&kmxlnd_data.kmx_nthreads);
}
return pid;
int
kiblnd_thread_start (int (*fn)(void *arg), void *arg)
{
- long pid = cfs_kernel_thread (fn, arg, 0);
+ long pid = cfs_create_thread (fn, arg, 0);
if (pid < 0)
return ((int)pid);
cfs_atomic_inc(&kptllnd_data.kptl_nthreads);
- pid = cfs_kernel_thread (fn, arg, 0);
+ pid = cfs_create_thread (fn, arg, 0);
if (pid >= 0)
return 0;
- CERROR("Failed to start cfs_kernel_thread: error %d\n", (int)pid);
+ CERROR("Failed to start thread: error %d\n", (int)pid);
kptllnd_thread_fini();
return (int)pid;
}
cfs_set_current_state(CFS_TASK_INTERRUPTIBLE);
cfs_waitq_add(&ptltrace_debug_ctlwq, &wait);
- rc = cfs_kernel_thread(kptllnd_dump_ptltrace_thread,
+ rc = cfs_create_thread(kptllnd_dump_ptltrace_thread,
(void *)(long)cfs_curproc_pid(),
- CLONE_VM | CLONE_FS | CLONE_FILES);
+ CFS_DAEMON_FLAGS | CLONE_FS);
if (rc < 0) {
CERROR("Error %d starting ptltrace dump thread\n", rc);
} else {
int
kqswnal_thread_start (int (*fn)(void *arg), void *arg)
{
- long pid = cfs_kernel_thread (fn, arg, 0);
+ long pid = cfs_create_thread (fn, arg, 0);
if (pid < 0)
return ((int)pid);
int
kranal_thread_start (int(*fn)(void *arg), void *arg)
{
- long pid = cfs_kernel_thread(fn, arg, 0);
+ long pid = cfs_create_thread(fn, arg, 0);
if (pid < 0)
return(int)pid;
int
ksocknal_thread_start (int (*fn)(void *arg), void *arg)
{
- long pid = cfs_kernel_thread (fn, arg, 0);
+ long pid = cfs_create_thread (fn, arg, 0);
if (pid < 0)
return ((int)pid);
#define cfs_mt_wait_for_completion(c) cfs_wait_for_completion(c)
#define cfs_mt_complete(c) cfs_complete(c)
#define cfs_mt_fini_completion(c) cfs_fini_completion(c)
-#define cfs_create_thread(func, a) cfs_kernel_thread(func, a, 0)
EXPORT_SYMBOL(lnet_acceptor_port);
if (lnet_count_acceptor_nis() == 0) /* not required */
return 0;
- rc2 = cfs_create_thread(lnet_acceptor, (void *)(ulong_ptr_t)secure);
+ rc2 = cfs_create_thread(lnet_acceptor, (void *)(ulong_ptr_t)secure, 0);
if (rc2 < 0) {
CERROR("Can't start acceptor thread: %d\n", rc);
cfs_mt_fini_completion(&lnet_acceptor_state.pta_signal);
int
lnet_configure (void *arg)
{
- /* 'arg' only there so I can be passed to cfs_kernel_thread() */
+ /* 'arg' only there so I can be passed to cfs_create_thread() */
int rc = 0;
LNET_MUTEX_DOWN(&lnet_config_mutex);
if (config_on_load) {
/* Have to schedule a separate thread to avoid deadlocking
* in modload */
- (void) cfs_kernel_thread(lnet_configure, NULL, 0);
+ (void) cfs_create_thread(lnet_configure, NULL, 0);
}
RETURN(0);
the_lnet.ln_rc_state = LNET_RC_STATE_RUNNING;
#ifdef __KERNEL__
- rc = (int)cfs_kernel_thread(lnet_router_checker, NULL, 0);
+ rc = cfs_create_thread(lnet_router_checker, NULL, 0);
if (rc < 0) {
CERROR("Can't start router checker thread: %d\n", rc);
the_lnet.ln_rc_state = LNET_RC_STATE_UNLINKING;
LASSERT (!stt_data.stt_shuttingdown);
- pid = cfs_kernel_thread(stt_timer_main, NULL, 0);
+ pid = cfs_create_thread(stt_timer_main, NULL, 0);
if (pid < 0)
return (int)pid;
/* Spawn poll threads */
for (i = 0; i < usock_data.ud_npollthreads; i++) {
rc = cfs_create_thread(usocklnd_poll_thread,
- &usock_data.ud_pollthreads[i]);
+ &usock_data.ud_pollthreads[i], 0);
if (rc) {
usocklnd_base_shutdown(i);
return rc;
cfs_init_completion(&trd->trd_finishing);
trd->trd_recovery_handler = handler;
- if (cfs_kernel_thread(target_recovery_thread, lut, 0) > 0) {
+ if (cfs_create_thread(target_recovery_thread, lut, 0) > 0) {
cfs_wait_for_completion(&trd->trd_starting);
LASSERT(obd->obd_recovering != 0);
} else
int rc;
cfs_init_completion(&bltd.bltd_comp);
- rc = cfs_kernel_thread(ldlm_bl_thread_main, &bltd, 0);
+ rc = cfs_create_thread(ldlm_bl_thread_main, &bltd, 0);
if (rc < 0) {
CERROR("cannot start LDLM thread ldlm_bl_%02d: rc %d\n",
cfs_atomic_read(&blp->blp_num_threads), rc);
cfs_spin_lock_init(&waiting_locks_spinlock);
cfs_timer_init(&waiting_locks_timer, waiting_locks_callback, 0);
- rc = cfs_kernel_thread(expired_lock_main, NULL, CLONE_VM | CLONE_FILES);
+ rc = cfs_create_thread(expired_lock_main, NULL, CFS_DAEMON_FLAGS);
if (rc < 0) {
CERROR("Cannot start ldlm expired-lock thread: %d\n", rc);
GOTO(out_thread, rc);
* CLONE_VM and CLONE_FILES just avoid a needless copy, because we
* just drop the VM and FILES in cfs_daemonize() right away.
*/
- rc = cfs_kernel_thread(ldlm_pools_thread_main, ldlm_pools_thread,
- CLONE_VM | CLONE_FILES);
+ rc = cfs_create_thread(ldlm_pools_thread_main, ldlm_pools_thread,
+ CFS_DAEMON_FLAGS);
if (rc < 0) {
CERROR("Can't start pool thread, error %d\n",
rc);
cfs_waitq_init(&ll_capa_thread.t_ctl_waitq);
- rc = cfs_kernel_thread(capa_thread_main, NULL, 0);
+ rc = cfs_create_thread(capa_thread_main, NULL, 0);
if (rc < 0) {
CERROR("cannot start expired capa thread: rc %d\n", rc);
RETURN(rc);
cfs_waitq_init(&lcq->lcq_waitq);
cfs_init_completion(&lcq->lcq_comp);
- pid = cfs_kernel_thread(ll_close_thread, lcq, 0);
+ pid = cfs_create_thread(ll_close_thread, lcq, 0);
if (pid < 0) {
OBD_FREE(lcq, sizeof(*lcq));
return pid;
set_blocksize(bdev, lo->lo_blocksize);
- cfs_kernel_thread(loop_thread, lo, CLONE_KERNEL);
+ cfs_create_thread(loop_thread, lo, CLONE_KERNEL);
cfs_down(&lo->lo_sem);
return 0;
}
lli->lli_sai = sai;
- rc = cfs_kernel_thread(ll_statahead_thread, parent, 0);
+ rc = cfs_create_thread(ll_statahead_thread, parent, 0);
if (rc < 0) {
CERROR("can't start ll_sa thread, rc: %d\n", rc);
dput(parent);
/* New thread because we should return to user app before
writing into our pipe */
- rc = cfs_kernel_thread(mdc_changelog_send_thread, cs,
- CLONE_VM | CLONE_FILES);
+ rc = cfs_create_thread(mdc_changelog_send_thread, cs, CFS_DAEMON_FLAGS);
if (rc >= 0) {
CDEBUG(D_CHANGELOG, "start changelog thread: %d\n", rc);
return 0;
if (ev != OBD_NOTIFY_SYNC) {
/* Synchronize in the background */
- rc = cfs_kernel_thread(mds_lov_synchronize, mlsi,
- CLONE_VM | CLONE_FILES);
+ rc = cfs_create_thread(mds_lov_synchronize, mlsi,
+ CFS_DAEMON_FLAGS);
if (rc < 0) {
CERROR("%s: error starting mds_lov_synchronize: %d\n",
obd->obd_name, rc);
int rc;
cfs_waitq_init(&thread->t_ctl_waitq);
- rc = cfs_kernel_thread(mdt_ck_thread_main, mdt,
- (CLONE_VM | CLONE_FILES));
+ rc = cfs_create_thread(mdt_ck_thread_main, mdt, CFS_DAEMON_FLAGS);
if (rc < 0) {
CERROR("cannot start mdt_ck thread, rc = %d\n", rc);
return rc;
LASSERT(rq_state == 0);
rq_state = RQ_RUNNING | (later ? RQ_LATER : RQ_NOW);
cfs_spin_unlock(&config_list_lock);
- rc = cfs_kernel_thread(mgc_requeue_thread, 0,
- CLONE_VM | CLONE_FILES);
+ rc = cfs_create_thread(mgc_requeue_thread, NULL,
+ CFS_DAEMON_FLAGS);
if (rc < 0) {
CERROR("log %s: cannot start requeue thread (%d),"
"no more log updates!\n", cld->cld_logname, rc);
obd_zombie_pid = 0;
#ifdef __KERNEL__
- rc = cfs_kernel_thread(obd_zombie_impexp_thread, NULL, 0);
+ rc = cfs_create_thread(obd_zombie_impexp_thread, NULL, 0);
if (rc < 0)
RETURN(rc);
#ifdef __KERNEL__
cfs_init_completion(&lpi->lpi_completion);
- rc = cfs_kernel_thread(llog_process_thread, lpi, CLONE_VM | CLONE_FILES);
+ rc = cfs_create_thread(llog_process_thread, lpi, CFS_DAEMON_FLAGS);
if (rc < 0) {
CERROR("cannot start thread: %d\n", rc);
OBD_FREE_PTR(lpi);
* invalidate thread without reference to import and import can
* be freed at same time. */
class_import_get(imp);
- rc = cfs_kernel_thread(ptlrpc_invalidate_import_thread, imp,
- CLONE_VM | CLONE_FILES);
+ rc = cfs_create_thread(ptlrpc_invalidate_import_thread, imp,
+ CFS_DAEMON_FLAGS);
if (rc < 0) {
class_import_put(imp);
CERROR("error starting invalidate thread: %d\n", rc);
/* CLONE_VM and CLONE_FILES just avoid a needless copy, because we
* just drop the VM and FILES in cfs_daemonize_ctxt() right away. */
- rc = cfs_kernel_thread(ptlrpc_pinger_main, &d, CLONE_VM | CLONE_FILES);
+ rc = cfs_create_thread(ptlrpc_pinger_main, &d, CFS_DAEMON_FLAGS);
if (rc < 0) {
CERROR("cannot start thread: %d\n", rc);
OBD_FREE(pinger_thread, sizeof(*pinger_thread));
cfs_waitq_init(&pet_waitq);
- rc = cfs_kernel_thread(ping_evictor_main, NULL, CLONE_VM | CLONE_FILES);
+ rc = cfs_create_thread(ping_evictor_main, NULL, CFS_DAEMON_FLAGS);
if (rc < 0) {
pet_refcount--;
CERROR("Cannot start ping evictor thread: %d\n", rc);
}
#ifdef __KERNEL__
- rc = cfs_kernel_thread(ptlrpcd, pc, 0);
+ rc = cfs_create_thread(ptlrpcd, pc, 0);
if (rc < 0) {
lu_context_fini(&pc->pc_env.le_ctx);
ptlrpc_set_destroy(pc->pc_set);
OBD_FREE_PTR(lpca);
RETURN(-ENODEV);
}
- rc = cfs_kernel_thread(llog_cat_process_thread, lpca,
- CLONE_VM | CLONE_FILES);
+ rc = cfs_create_thread(llog_cat_process_thread, lpca, CFS_DAEMON_FLAGS);
if (rc < 0) {
CERROR("Error starting llog_cat_process_thread(): %d\n", rc);
OBD_FREE_PTR(lpca);
memset(&sec_gc_thread, 0, sizeof(sec_gc_thread));
cfs_waitq_init(&sec_gc_thread.t_ctl_waitq);
- rc = cfs_kernel_thread(sec_gc_main, &sec_gc_thread,
- CLONE_VM | CLONE_FILES);
+ rc = cfs_create_thread(sec_gc_main, &sec_gc_thread, CFS_DAEMON_FLAGS);
if (rc < 0) {
CERROR("can't start gc thread: %d\n", rc);
return rc;
args.cpu_index = cpu;
args.hrs = hr;
- rc = cfs_kernel_thread(ptlrpc_hr_main, (void*)&args,
- CLONE_VM|CLONE_FILES);
+ rc = cfs_create_thread(ptlrpc_hr_main, (void*)&args, CFS_DAEMON_FLAGS);
if (rc < 0) {
cfs_complete(&t->hrt_completion);
GOTO(out, rc);
/* CLONE_VM and CLONE_FILES just avoid a needless copy, because we
* just drop the VM and FILES in cfs_daemonize_ctxt() right away.
*/
- rc = cfs_kernel_thread(ptlrpc_main, &d, CLONE_VM | CLONE_FILES);
+ rc = cfs_create_thread(ptlrpc_main, &d, CFS_DAEMON_FLAGS);
if (rc < 0) {
CERROR("cannot start thread '%s': rc %d\n", name, rc);
/* we get ref for exp because target_quotacheck_callback() will use this
* export later b=18126 */
class_export_get(exp);
- rc = cfs_kernel_thread(target_quotacheck_thread, qta,
- CLONE_VM|CLONE_FILES);
+ rc = cfs_create_thread(target_quotacheck_thread, qta,
+ CFS_DAEMON_FLAGS);
if (rc >= 0) {
/* target_quotacheck_thread will drop the ref on exp and release
* obt_quotachecking */
data.qctxt = qctxt;
cfs_init_completion(&data.comp);
- rc = cfs_kernel_thread(qslave_recovery_main, &data,
- CLONE_VM|CLONE_FILES);
+ rc = cfs_create_thread(qslave_recovery_main, &data,
+ CFS_DAEMON_FLAGS);
if (rc < 0) {
CERROR("Cannot start quota recovery thread: rc %d\n", rc);
goto exit;
data.obd = obd;
cfs_init_completion(&data.comp);
- rc = cfs_kernel_thread(qmaster_recovery_main, &data,
- CLONE_VM|CLONE_FILES);
+ rc = cfs_create_thread(qmaster_recovery_main, &data,
+ CFS_DAEMON_FLAGS);
if (rc < 0)
CERROR("%s: cannot start quota recovery thread: rc %d\n",
obd->obd_name, rc);