Whamcloud - gitweb
LU-305 Temporarily block 'non-fatal' signals
authorNiu Yawei <niu@whamcloud.com>
Mon, 23 May 2011 12:54:25 +0000 (05:54 -0700)
committerOleg Drokin <green@whamcloud.com>
Sat, 28 May 2011 03:12:17 +0000 (20:12 -0700)
In cl_lock_state_wait(), to avoid being interrupted by 'non-fatal'
signals (such as SIGCHLD), we'd block them temporarily.

Signed-off-by: Niu Yawei <niu@whamcloud.com>
Change-Id: I176530131a5983c19d64d311b100d1b81845164f
Reviewed-on: http://review.whamcloud.com/591
Reviewed-by: Jinshan Xiong <jay@whamcloud.com>
Tested-by: Hudson
Reviewed-by: Oleg Drokin <green@whamcloud.com>
libcfs/include/libcfs/libcfs.h
libcfs/libcfs/darwin/darwin-prim.c
libcfs/libcfs/linux/linux-prim.c
libcfs/libcfs/user-prim.c
libcfs/libcfs/winnt/winnt-prim.c
lustre/include/darwin/lustre_lib.h
lustre/include/linux/lustre_lib.h
lustre/include/lustre_lib.h
lustre/obdclass/cl_lock.c
lustre/obdclass/obd_mount.c

index 8732d98..4fc0bea 100644 (file)
@@ -224,9 +224,11 @@ int cfs_daemonize_ctxt(char *str);
 cfs_sigset_t cfs_get_blocked_sigs(void);
 cfs_sigset_t cfs_block_allsigs(void);
 cfs_sigset_t cfs_block_sigs(cfs_sigset_t bits);
+cfs_sigset_t cfs_block_sigsinv(unsigned long sigs);
 void cfs_restore_sigs(cfs_sigset_t);
 int cfs_signal_pending(void);
 void cfs_clear_sigpending(void);
+
 /*
  * XXX Liang:
  * these macros should be removed in the future,
index 5366000..eb8b232 100644 (file)
@@ -385,6 +385,14 @@ cfs_sigset_t cfs_block_sigs(sigset_t bit)
         return old;
 }
 
+/* Block all signals except for the @sigs. It's only used in
+ * Linux kernel, just a dummy here. */
+cfs_sigset_t cfs_block_sigsinv(unsigned long sigs)
+{
+        cfs_sigset_t old = 0;
+        return old;
+}
+
 void cfs_restore_sigs(cfs_sigset_t old)
 {
 }
index 03a83f5..1b59e0b 100644 (file)
@@ -324,6 +324,22 @@ cfs_block_sigs(sigset_t bits)
         return old;
 }
 
+/* Block all signals except for the @sigs */
+cfs_sigset_t
+cfs_block_sigsinv(unsigned long sigs)
+{
+        unsigned long flags;
+        cfs_sigset_t old;
+
+        SIGNAL_MASK_LOCK(current, flags);
+        old = current->blocked;
+        siginitsetinv(&current->blocked, sigs);
+        RECALC_SIGPENDING;
+        SIGNAL_MASK_UNLOCK(current, flags);
+
+        return old;
+}
+
 void
 cfs_restore_sigs (cfs_sigset_t old)
 {
@@ -370,6 +386,7 @@ EXPORT_SYMBOL(cfs_daemonize);
 EXPORT_SYMBOL(cfs_daemonize_ctxt);
 EXPORT_SYMBOL(cfs_block_allsigs);
 EXPORT_SYMBOL(cfs_block_sigs);
+EXPORT_SYMBOL(cfs_block_sigsinv);
 EXPORT_SYMBOL(cfs_restore_sigs);
 EXPORT_SYMBOL(cfs_signal_pending);
 EXPORT_SYMBOL(cfs_clear_sigpending);
index 825aa70..ca6c661 100644 (file)
@@ -303,6 +303,20 @@ cfs_sigset_t cfs_block_sigs(cfs_sigset_t blocks)
         return old;
 }
 
+/* Block all signals except for the @sigs. It's only used in
+ * Linux kernel, just a dummy here. */
+cfs_sigset_t cfs_block_sigsinv(unsigned long sigs)
+{
+        cfs_sigset_t old;
+        int rc;
+
+        /* Return old blocked sigs */
+        rc = sigprocmask(SIG_SETMASK, NULL, &old);
+        LASSERT(rc == 0);
+
+        return old;
+}
+
 void cfs_restore_sigs(cfs_sigset_t old)
 {
         int   rc = sigprocmask(SIG_SETMASK, &old, NULL);
index ea47f5a..e28b654 100644 (file)
@@ -557,6 +557,13 @@ cfs_sigset_t cfs_block_sigs(sigset_t bit)
         return 0;
 }
 
+/* Block all signals except for the @sigs. It's only used in
+ * Linux kernel, just a dummy here. */
+cfs_sigset_t cfs_block_sigsinv(unsigned long sigs)
+{
+        return 0;
+}
+
 void cfs_restore_sigs(cfs_sigset_t old)
 {
 }
index 60cda4b..1b76661 100644 (file)
@@ -68,23 +68,4 @@ struct obd_ioctl_data;
                            sigmask(SIGTERM) | sigmask(SIGQUIT) |               \
                            sigmask(SIGALRM) | sigmask(SIGHUP))
 
-#ifdef __KERNEL__
-static inline sigset_t l_w_e_set_sigs(sigset_t sigs)
-{
-        sigset_t old = 0;
-
-        /* XXX Liang: how to change sigmask in Darwin8.x? 
-         * there is syscall like pthread_sigmask() but we cannot 
-         * use in kernel  */
-#if !defined(__DARWIN8__)
-        struct proc     *p = current_proc();
-        extern int block_procsigmask(struct proc *p,  int bit);
-        old = cfs_current()->uu_sigmask;
-        block_procsigmask(p, ~sigs);
-#endif
-
-        return old;
-}
-#endif
-
 #endif
index afb6abd..8c853ed 100644 (file)
                            sigmask(SIGALRM))
 
 #ifdef __KERNEL__
-static inline sigset_t l_w_e_set_sigs(int sigs)
-{
-        sigset_t old;
-        unsigned long irqflags;
-
-        SIGNAL_MASK_LOCK(current, irqflags);
-        old = current->blocked;
-        siginitsetinv(&current->blocked, sigs);
-        RECALC_SIGPENDING;
-        SIGNAL_MASK_UNLOCK(current, irqflags);
-
-        return old;
-}
-#endif
-
-#ifdef __KERNEL__
 /* initialize ost_lvb according to inode */
 static inline void inode_init_lvb(struct inode *inode, struct ost_lvb *lvb)
 {
index cf9d4a7..cdef911 100644 (file)
@@ -681,9 +681,9 @@ do {                                                                           \
                                                                                \
         /* Block all signals (just the non-fatal ones if no timeout). */       \
         if (info->lwi_on_signal != NULL && (__timeout == 0 || __allow_intr))   \
-                __blocked = l_w_e_set_sigs(LUSTRE_FATAL_SIGS);                 \
+                __blocked = cfs_block_sigsinv(LUSTRE_FATAL_SIGS);              \
         else                                                                   \
-                __blocked = l_w_e_set_sigs(0);                                 \
+                __blocked = cfs_block_sigsinv(0);                              \
                                                                                \
         for (;;) {                                                             \
                 unsigned       __wstate;                                       \
@@ -717,7 +717,7 @@ do {                                                                           \
                                 }                                              \
                                 /* Take signals after the timeout expires. */  \
                                 if (info->lwi_on_signal != NULL)               \
-                                    (void)l_w_e_set_sigs(LUSTRE_FATAL_SIGS);   \
+                                    (void)cfs_block_sigsinv(LUSTRE_FATAL_SIGS);\
                         }                                                      \
                 }                                                              \
                                                                                \
index de487f6..21919b3 100644 (file)
@@ -947,6 +947,7 @@ static void cl_lock_hold_release(const struct lu_env *env, struct cl_lock *lock,
 int cl_lock_state_wait(const struct lu_env *env, struct cl_lock *lock)
 {
         cfs_waitlink_t waiter;
+        cfs_sigset_t blocked;
         int result;
 
         ENTRY;
@@ -958,6 +959,11 @@ int cl_lock_state_wait(const struct lu_env *env, struct cl_lock *lock)
         cl_lock_trace(D_DLMTRACE, env, "state wait lock", lock);
         result = lock->cll_error;
         if (result == 0) {
+                /* To avoid being interrupted by the 'non-fatal' signals
+                 * (SIGCHLD, for instance), we'd block them temporarily.
+                 * LU-305 */
+                blocked = cfs_block_sigsinv(LUSTRE_FATAL_SIGS);
+
                 cfs_waitlink_init(&waiter);
                 cfs_waitq_add(&lock->cll_wq, &waiter);
                 cfs_set_current_state(CFS_TASK_INTERRUPTIBLE);
@@ -970,6 +976,9 @@ int cl_lock_state_wait(const struct lu_env *env, struct cl_lock *lock)
                 cfs_set_current_state(CFS_TASK_RUNNING);
                 cfs_waitq_del(&lock->cll_wq, &waiter);
                 result = cfs_signal_pending() ? -EINTR : 0;
+
+                /* Restore old blocked signals */
+                cfs_restore_sigs(blocked);
         }
         RETURN(result);
 }
index b270344..a1401bb 100644 (file)
@@ -1432,7 +1432,7 @@ static void server_wait_finished(struct vfsmount *mnt)
                                       waited);
                /* Cannot use l_event_wait() for an interruptible sleep. */
                waited += 3;
-               blocked = l_w_e_set_sigs(sigmask(SIGKILL));
+               blocked = cfs_block_sigsinv(sigmask(SIGKILL));
                cfs_waitq_wait_event_interruptible_timeout(
                        waitq,
                        (atomic_read(&mnt->mnt_count) == 1),