Whamcloud - gitweb
LU-14706 libcfs: ___wait_event() update for older kernels
[fs/lustre-release.git] / libcfs / include / libcfs / linux / linux-wait.h
index ec72376..aa257fc 100644 (file)
@@ -136,6 +136,20 @@ do {                                                                       \
                __ret = __wait_var_event_timeout(var, condition, timeout); \
        __ret;                                                          \
 })
+#else /* !HAVE_WAIT_VAR_EVENT */
+/* linux-3.10.0-1062.el7 defines wait_var_event_timeout() using
+ * __wait_cond_timeout(), but doesn't define __wait_cond_timeout !!!
+ */
+# ifndef __wait_cond_timeout
+# define ___wait_cond_timeout(condition)                               \
+({                                                                     \
+       bool __cond = (condition);                                      \
+       if (__cond && !__ret)                                           \
+               __ret = 1;                                              \
+       __cond || !__ret;                                               \
+})
+# endif /* __wait_cond_timeout */
+
 #endif /* ! HAVE_WAIT_VAR_EVENT */
 
 /*
@@ -176,12 +190,12 @@ static inline void prepare_to_wait_exclusive_head(
 #define ___wait_event(wq_head, condition, state, exclusive, ret, cmd)  \
 ({                                                                     \
        __label__ __out;                                                \
-       wait_queue_entry_ __wq_entry;                                   \
+       wait_queue_entry_t __wq_entry;                                  \
        long __ret = ret;       /* explicit shadow */                   \
                                                                        \
        init_wait(&__wq_entry);                                         \
        if (exclusive)                                                  \
-               __wq_entry.flags = WQ_FLAG_EXCLUSIVE                    \
+               __wq_entry.flags = WQ_FLAG_EXCLUSIVE;                   \
        for (;;) {                                                      \
                long __int = prepare_to_wait_event(&wq_head,            \
                                                  &__wq_entry, state);  \
@@ -203,13 +217,17 @@ __out:    __ret;                                                          \
 
 #ifndef TASK_NOLOAD
 
+#define TASK_IDLE TASK_INTERRUPTIBLE
+
 #define ___wait_event_idle(wq_head, condition, exclusive, ret, cmd)    \
 ({                                                                     \
        wait_queue_entry_t __wq_entry;                                  \
+       unsigned long flags;                                            \
        long __ret = ret;       /* explicit shadow */                   \
-       sigset_t __blocked;                                             \
+       sigset_t __old_blocked, __new_blocked;                          \
                                                                        \
-       __blocked = cfs_block_sigsinv(0);                               \
+       siginitset(&__new_blocked, LUSTRE_FATAL_SIGS);                  \
+       sigprocmask(0, &__new_blocked, &__old_blocked);                 \
        init_wait(&__wq_entry);                                         \
        if (exclusive)                                                  \
                __wq_entry.flags = WQ_FLAG_EXCLUSIVE;                   \
@@ -220,14 +238,24 @@ __out:    __ret;                                                          \
                                                                        \
                if (condition)                                          \
                        break;                                          \
-               /* See justification in __l_wait_event */               \
-               if (signal_pending(current))                            \
-                       cfs_clear_sigpending();                         \
-                                                                       \
+               /* We have to do this here because some signals */      \
+               /* are not blockable - ie from strace(1).       */      \
+               /* In these cases we want to schedule_timeout() */      \
+               /* again, because we don't want that to return  */      \
+               /* -EINTR when the RPC actually succeeded.      */      \
+               /* the recalc_sigpending() below will deliver the */    \
+               /* signal properly.                             */      \
+               if (signal_pending(current)) {                          \
+                       spin_lock_irqsave(&current->sighand->siglock,   \
+                                         flags);                       \
+                       clear_tsk_thread_flag(current, TIF_SIGPENDING); \
+                       spin_unlock_irqrestore(&current->sighand->siglock,\
+                                              flags);                  \
+               }                                                       \
                cmd;                                                    \
        }                                                               \
        finish_wait(&wq_head, &__wq_entry);                             \
-       cfs_restore_sigs(__blocked);                                    \
+       sigprocmask(SIG_SETMASK, &__old_blocked, NULL);                 \
        __ret;                                                          \
 })
 
@@ -270,7 +298,6 @@ do {                                                                        \
                                              cmd1, cmd2)               \
 ({                                                                     \
        long __ret = timeout;                                           \
-       might_sleep();                                                  \
        if (!___wait_cond_timeout1(condition))                          \
                __ret = __wait_event_idle_exclusive_timeout_cmd(        \
                        wq_head, condition, timeout, cmd1, cmd2);       \
@@ -389,7 +416,6 @@ do {                                                                        \
                                              cmd1, cmd2)               \
 ({                                                                     \
        long __ret = timeout;                                           \
-       might_sleep();                                                  \
        if (!___wait_cond_timeout1(condition))                          \
                __ret = __wait_event_idle_exclusive_timeout_cmd(        \
                        wq_head, condition, timeout, cmd1, cmd2);       \
@@ -462,10 +488,12 @@ do {                                                                      \
 #define ___wait_event_lifo(wq_head, condition, ret, cmd)               \
 ({                                                                     \
        wait_queue_entry_t __wq_entry;                                  \
+       unsigned long flags;                                            \
        long __ret = ret;       /* explicit shadow */                   \
-       sigset_t __blocked;                                             \
+       sigset_t __old_blocked, __new_blocked;                          \
                                                                        \
-       __blocked = cfs_block_sigsinv(0);                               \
+       siginitset(&__new_blocked, LUSTRE_FATAL_SIGS);                  \
+       sigprocmask(0, &__new_blocked, &__old_blocked);                 \
        init_wait(&__wq_entry);                                         \
        __wq_entry.flags = WQ_FLAG_EXCLUSIVE;                           \
        for (;;) {                                                      \
@@ -475,13 +503,17 @@ do {                                                                      \
                                                                        \
                if (condition)                                          \
                        break;                                          \
-               /* See justification in __l_wait_event */               \
-               if (signal_pending(current))                            \
-                       cfs_clear_sigpending();                         \
-                                                                       \
+               /* See justification in ___wait_event_idle */           \
+               if (signal_pending(current)) {                          \
+                       spin_lock_irqsave(&current->sighand->siglock,   \
+                                         flags);                       \
+                       clear_tsk_thread_flag(current, TIF_SIGPENDING); \
+                       spin_unlock_irqrestore(&current->sighand->siglock,\
+                                              flags);                  \
+               }                                                       \
                cmd;                                                    \
        }                                                               \
-       cfs_restore_sigs(__blocked);                                    \
+       sigprocmask(SIG_SETMASK, &__old_blocked, NULL);                 \
        finish_wait(&wq_head, &__wq_entry);                             \
        __ret;                                                          \
 })
@@ -551,4 +583,11 @@ do {                                                                       \
        __ret;                                                          \
 })
 
+#ifndef HAVE_WAIT_WOKEN
+#define WQ_FLAG_WOKEN          0x02
+long wait_woken(wait_queue_entry_t *wait, unsigned int mode, long timeout);
+int woken_wake_function(wait_queue_entry_t *wait, unsigned int mode,
+                       int sync, void *key);
+#endif /* HAVE_WAIT_WOKEN */
+
 #endif /* __LICBFS_LINUX_WAIT_BIT_H */