summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
f3332b4)
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>
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_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);
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,
/*
* XXX Liang:
* these macros should be removed in the future,
+/* 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)
{
}
void cfs_restore_sigs(cfs_sigset_t 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)
{
void
cfs_restore_sigs (cfs_sigset_t old)
{
EXPORT_SYMBOL(cfs_daemonize_ctxt);
EXPORT_SYMBOL(cfs_block_allsigs);
EXPORT_SYMBOL(cfs_block_sigs);
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);
EXPORT_SYMBOL(cfs_restore_sigs);
EXPORT_SYMBOL(cfs_signal_pending);
EXPORT_SYMBOL(cfs_clear_sigpending);
+/* 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);
void cfs_restore_sigs(cfs_sigset_t old)
{
int rc = sigprocmask(SIG_SETMASK, &old, NULL);
+/* 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)
{
}
void cfs_restore_sigs(cfs_sigset_t old)
{
}
sigmask(SIGTERM) | sigmask(SIGQUIT) | \
sigmask(SIGALRM) | sigmask(SIGHUP))
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
-
sigmask(SIGALRM))
#ifdef __KERNEL__
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)
{
/* initialize ost_lvb according to inode */
static inline void inode_init_lvb(struct inode *inode, struct ost_lvb *lvb)
{
\
/* Block all signals (just the non-fatal ones if no timeout). */ \
if (info->lwi_on_signal != NULL && (__timeout == 0 || __allow_intr)) \
\
/* 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); \
- __blocked = l_w_e_set_sigs(0); \
+ __blocked = cfs_block_sigsinv(0); \
\
for (;;) { \
unsigned __wstate; \
\
for (;;) { \
unsigned __wstate; \
} \
/* Take signals after the timeout expires. */ \
if (info->lwi_on_signal != NULL) \
} \
/* 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);\
int cl_lock_state_wait(const struct lu_env *env, struct cl_lock *lock)
{
cfs_waitlink_t waiter;
int cl_lock_state_wait(const struct lu_env *env, struct cl_lock *lock)
{
cfs_waitlink_t waiter;
cl_lock_trace(D_DLMTRACE, env, "state wait lock", lock);
result = lock->cll_error;
if (result == 0) {
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);
cfs_waitlink_init(&waiter);
cfs_waitq_add(&lock->cll_wq, &waiter);
cfs_set_current_state(CFS_TASK_INTERRUPTIBLE);
cfs_set_current_state(CFS_TASK_RUNNING);
cfs_waitq_del(&lock->cll_wq, &waiter);
result = cfs_signal_pending() ? -EINTR : 0;
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);
waited);
/* Cannot use l_event_wait() for an interruptible sleep. */
waited += 3;
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),
cfs_waitq_wait_event_interruptible_timeout(
waitq,
(atomic_read(&mnt->mnt_count) == 1),