From: Niu Yawei Date: Mon, 23 May 2011 12:54:25 +0000 (-0700) Subject: LU-305 Temporarily block 'non-fatal' signals X-Git-Tag: 2.0.62.0~26 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=cdb698a1a036870b6c9d8e51f69809c558d4823a LU-305 Temporarily block 'non-fatal' signals 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 Change-Id: I176530131a5983c19d64d311b100d1b81845164f Reviewed-on: http://review.whamcloud.com/591 Reviewed-by: Jinshan Xiong Tested-by: Hudson Reviewed-by: Oleg Drokin --- diff --git a/libcfs/include/libcfs/libcfs.h b/libcfs/include/libcfs/libcfs.h index 8732d98..4fc0bea9f 100644 --- a/libcfs/include/libcfs/libcfs.h +++ b/libcfs/include/libcfs/libcfs.h @@ -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, diff --git a/libcfs/libcfs/darwin/darwin-prim.c b/libcfs/libcfs/darwin/darwin-prim.c index 5366000..eb8b232 100644 --- a/libcfs/libcfs/darwin/darwin-prim.c +++ b/libcfs/libcfs/darwin/darwin-prim.c @@ -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) { } diff --git a/libcfs/libcfs/linux/linux-prim.c b/libcfs/libcfs/linux/linux-prim.c index 03a83f5..1b59e0b 100644 --- a/libcfs/libcfs/linux/linux-prim.c +++ b/libcfs/libcfs/linux/linux-prim.c @@ -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(¤t->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); diff --git a/libcfs/libcfs/user-prim.c b/libcfs/libcfs/user-prim.c index 825aa70..ca6c661 100644 --- a/libcfs/libcfs/user-prim.c +++ b/libcfs/libcfs/user-prim.c @@ -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); diff --git a/libcfs/libcfs/winnt/winnt-prim.c b/libcfs/libcfs/winnt/winnt-prim.c index ea47f5a..e28b654 100644 --- a/libcfs/libcfs/winnt/winnt-prim.c +++ b/libcfs/libcfs/winnt/winnt-prim.c @@ -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) { } diff --git a/lustre/include/darwin/lustre_lib.h b/lustre/include/darwin/lustre_lib.h index 60cda4b..1b76661 100644 --- a/lustre/include/darwin/lustre_lib.h +++ b/lustre/include/darwin/lustre_lib.h @@ -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 diff --git a/lustre/include/linux/lustre_lib.h b/lustre/include/linux/lustre_lib.h index afb6abd..8c853ed 100644 --- a/lustre/include/linux/lustre_lib.h +++ b/lustre/include/linux/lustre_lib.h @@ -75,22 +75,6 @@ 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(¤t->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) { diff --git a/lustre/include/lustre_lib.h b/lustre/include/lustre_lib.h index cf9d4a7..cdef911 100644 --- a/lustre/include/lustre_lib.h +++ b/lustre/include/lustre_lib.h @@ -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);\ } \ } \ \ diff --git a/lustre/obdclass/cl_lock.c b/lustre/obdclass/cl_lock.c index de487f6..21919b3 100644 --- a/lustre/obdclass/cl_lock.c +++ b/lustre/obdclass/cl_lock.c @@ -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); } diff --git a/lustre/obdclass/obd_mount.c b/lustre/obdclass/obd_mount.c index b270344..a1401bb 100644 --- a/lustre/obdclass/obd_mount.c +++ b/lustre/obdclass/obd_mount.c @@ -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),