-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
+/*
* GPL HEADER START
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* GPL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright (c) 2012, Intel Corporation.
*/
/*
* This file is part of Lustre, http://www.lustre.org/
#error This include is only for kernel use.
#endif
-#ifndef AUTOCONF_INCLUDED
-#include <linux/config.h>
-#endif
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/timer.h>
#include <linux/signal.h>
#include <linux/sched.h>
-
+#include <linux/kthread.h>
+#ifdef HAVE_LINUX_RANDOM_H
+#include <linux/random.h>
+#endif
+#ifdef HAVE_UIDGID_HEADER
+#include <linux/uidgid.h>
+#endif
+#include <linux/user_namespace.h>
#include <linux/miscdevice.h>
#include <libcfs/linux/portals_compat25.h>
#include <asm/div64.h>
#include <libcfs/linux/linux-time.h>
-/*
- * Pseudo device register
- */
-typedef struct miscdevice cfs_psdev_t;
-#define cfs_psdev_register(dev) misc_register(dev)
-#define cfs_psdev_deregister(dev) misc_deregister(dev)
/*
- * Sysctl register
+ * CPU
*/
-typedef struct ctl_table cfs_sysctl_table_t;
-typedef struct ctl_table_header cfs_sysctl_table_header_t;
-
-#ifdef HAVE_2ARGS_REGISTER_SYSCTL
-#define cfs_register_sysctl_table(t, a) register_sysctl_table(t, a)
-#else
-#define cfs_register_sysctl_table(t, a) register_sysctl_table(t)
+#ifdef for_each_possible_cpu
+#define cfs_for_each_possible_cpu(cpu) for_each_possible_cpu(cpu)
+#elif defined(for_each_cpu)
+#define cfs_for_each_possible_cpu(cpu) for_each_cpu(cpu)
#endif
-#define cfs_unregister_sysctl_table(t) unregister_sysctl_table(t)
-/*
- * Symbol register
- */
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
-#define cfs_symbol_register(s, p) inter_module_register(s, THIS_MODULE, p)
-#define cfs_symbol_unregister(s) inter_module_unregister(s)
-#define cfs_symbol_get(s) inter_module_get(s)
-#define cfs_symbol_put(s) inter_module_put(s)
-#define cfs_module_get() MOD_INC_USE_COUNT
-#define cfs_module_put() MOD_DEC_USE_COUNT
-#else
-#define cfs_symbol_register(s, p) do {} while(0)
-#define cfs_symbol_unregister(s) do {} while(0)
-#define cfs_symbol_get(s) symbol_get(s)
-#define cfs_symbol_put(s) symbol_put(s)
-#define cfs_module_get() try_module_get(THIS_MODULE)
-#define cfs_module_put() module_put(THIS_MODULE)
+#ifndef NR_CPUS
+#define NR_CPUS 1
#endif
+#define DECLARE_PROC_HANDLER(name) \
+static int \
+LL_PROC_PROTO(name) \
+{ \
+ return proc_call_handler(table->data, write, \
+ ppos, buffer, lenp, \
+ __##name); \
+}
+
/*
* Proc file system APIs
*/
-typedef read_proc_t cfs_read_proc_t;
-typedef write_proc_t cfs_write_proc_t;
typedef struct proc_dir_entry cfs_proc_dir_entry_t;
#define cfs_create_proc_entry(n, m, p) create_proc_entry(n, m, p)
#define cfs_free_proc_entry(e) free_proc_entry(e)
/*
* Wait Queue
*/
-#define CFS_TASK_INTERRUPTIBLE TASK_INTERRUPTIBLE
-#define CFS_TASK_UNINT TASK_UNINTERRUPTIBLE
-#define CFS_TASK_RUNNING TASK_RUNNING
-typedef wait_queue_t cfs_waitlink_t;
-typedef wait_queue_head_t cfs_waitq_t;
-typedef long cfs_task_state_t;
-/* Kernel thread */
-typedef int (*cfs_thread_t)(void *);
+#define CFS_DECL_WAITQ(wq) DECLARE_WAIT_QUEUE_HEAD(wq)
+
+#define LIBCFS_WQITQ_MACROS 1
+#define init_waitqueue_entry_current(w) init_waitqueue_entry(w, current)
+#define waitq_wait(w, s) schedule()
+#define waitq_timedwait(w, s, t) schedule_timeout(t)
-static inline int cfs_kernel_thread(int (*fn)(void *),
- void *arg, unsigned long flags)
+#ifndef HAVE___ADD_WAIT_QUEUE_EXCLUSIVE
+static inline void __add_wait_queue_exclusive(wait_queue_head_t *q,
+ wait_queue_t *wait)
{
- void *orig_info = current->journal_info;
- int rc;
+ wait->flags |= WQ_FLAG_EXCLUSIVE;
+ __add_wait_queue(q, wait);
+}
+#endif /* HAVE___ADD_WAIT_QUEUE_EXCLUSIVE */
+
+/**
+ * wait_queue_t of Linux (version < 2.6.34) is a FIFO list for exclusively
+ * waiting threads, which is not always desirable because all threads will
+ * be waken up again and again, even user only needs a few of them to be
+ * active most time. This is not good for performance because cache can
+ * be polluted by different threads.
+ *
+ * LIFO list can resolve this problem because we always wakeup the most
+ * recent active thread by default.
+ *
+ * NB: please don't call non-exclusive & exclusive wait on the same
+ * waitq if add_wait_queue_exclusive_head is used.
+ */
+#define add_wait_queue_exclusive_head(waitq, link) \
+{ \
+ unsigned long flags; \
+ \
+ spin_lock_irqsave(&((waitq)->lock), flags); \
+ __add_wait_queue_exclusive(waitq, link); \
+ spin_unlock_irqrestore(&((waitq)->lock), flags); \
+}
- current->journal_info = NULL;
- rc = kernel_thread(fn, arg, flags);
- current->journal_info = orig_info;
- return rc;
+#define schedule_timeout_and_set_state(state, timeout) \
+{ \
+ set_current_state(state); \
+ schedule_timeout(timeout); \
}
+/* deschedule for a bit... */
+#define cfs_pause(ticks) \
+{ \
+ set_current_state(TASK_UNINTERRUPTIBLE); \
+ schedule_timeout(ticks); \
+}
-/*
- * Task struct
- */
-typedef struct task_struct cfs_task_t;
-#define cfs_current() current
-#define cfs_task_lock(t) task_lock(t)
-#define cfs_task_unlock(t) task_unlock(t)
-#define CFS_DECL_JOURNAL_DATA void *journal_info
-#define CFS_PUSH_JOURNAL do { \
+#define DECL_JOURNAL_DATA void *journal_info
+#define PUSH_JOURNAL do { \
journal_info = current->journal_info; \
current->journal_info = NULL; \
} while(0)
-#define CFS_POP_JOURNAL do { \
+#define POP_JOURNAL do { \
current->journal_info = journal_info; \
} while(0)
/* Module interfaces */
#define cfs_module(name, version, init, fini) \
-module_init(init); \
-module_exit(fini)
-
-/*
- * Signal
- */
-typedef sigset_t cfs_sigset_t;
-
-/*
- * Timer
- */
-typedef struct timer_list cfs_timer_t;
-
-
-#ifndef wait_event_timeout /* Only for RHEL3 2.4.21 kernel */
-#define __wait_event_timeout(wq, condition, timeout, ret) \
-do { \
- int __ret = 0; \
- if (!(condition)) { \
- wait_queue_t __wait; \
- unsigned long expire; \
- \
- init_waitqueue_entry(&__wait, current); \
- expire = timeout + jiffies; \
- add_wait_queue(&wq, &__wait); \
- for (;;) { \
- set_current_state(TASK_UNINTERRUPTIBLE); \
- if (condition) \
- break; \
- if (jiffies > expire) { \
- ret = jiffies - expire; \
- break; \
- } \
- schedule_timeout(timeout); \
- } \
- current->state = TASK_RUNNING; \
- remove_wait_queue(&wq, &__wait); \
- } \
-} while (0)
-/*
- retval == 0; condition met; we're good.
- retval > 0; timed out.
-*/
-#define cfs_waitq_wait_event_timeout(wq, condition, timeout, ret) \
-do { \
- ret = 0; \
- if (!(condition)) \
- __wait_event_timeout(wq, condition, timeout, ret); \
-} while (0)
-#else
-#define cfs_waitq_wait_event_timeout(wq, condition, timeout, ret) \
- ret = wait_event_timeout(wq, condition, timeout)
-#endif
-
-#ifndef wait_event_interruptible_timeout /* Only for RHEL3 2.4.21 kernel */
-#define __wait_event_interruptible_timeout(wq, condition, timeout, ret) \
-do { \
- int __ret = 0; \
- if (!(condition)) { \
- wait_queue_t __wait; \
- unsigned long expire; \
- \
- init_waitqueue_entry(&__wait, current); \
- expire = timeout + jiffies; \
- add_wait_queue(&wq, &__wait); \
- for (;;) { \
- set_current_state(TASK_INTERRUPTIBLE); \
- if (condition) \
- break; \
- if (jiffies > expire) { \
- ret = jiffies - expire; \
- break; \
- } \
- if (!signal_pending(current)) { \
- schedule_timeout(timeout); \
- continue; \
- } \
- ret = -ERESTARTSYS; \
- break; \
- } \
- current->state = TASK_RUNNING; \
- remove_wait_queue(&wq, &__wait); \
- } \
-} while (0)
-
-/*
- retval == 0; condition met; we're good.
- retval < 0; interrupted by signal.
- retval > 0; timed out.
-*/
-#define cfs_waitq_wait_event_interruptible_timeout(wq, condition, timeout, ret)\
-do { \
- ret = 0; \
- if (!(condition)) \
- __wait_event_interruptible_timeout(wq, condition, \
- timeout, ret); \
-} while (0)
-#else
-#define cfs_waitq_wait_event_interruptible_timeout(wq, c, timeout, ret) \
- ret = wait_event_interruptible_timeout(wq, c, timeout)
-#endif
+ module_init(init); \
+ module_exit(fini)
#endif