Whamcloud - gitweb
LU-9859 libcfs: improve API and implementation of blocking signals. 11/35411/11
authorNeilBrown <neilb@suse.de>
Wed, 11 Mar 2020 13:01:09 +0000 (09:01 -0400)
committerOleg Drokin <green@whamcloud.com>
Tue, 24 Mar 2020 05:16:29 +0000 (05:16 +0000)
According to comment for set_current_blocked() in
kernel/signal.c, changing ->blocked directly is wrong.
sigprocmask() should be called instead.

So change cfs_block_sigsinv() and cfs_restore_sigs()
to use sigprocmask().
For consistency, change them to pass the sigset_t by reference
rather than by value.

Also fix cfs_block_sigsinv() so that it correctly blocks
signals above 32 on a 32bit host.

Linux-commit: 84e07b9d0ac8728b1865b23498d746861a8ab4c2

Change-Id: Iffb8b39ee2b988e9909ceaaba50446eecdf7f249
Signed-off-by: NeilBrown <neilb@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Reviewed-on: https://review.whamcloud.com/35411
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Jian Yu <yujian@whamcloud.com>
Reviewed-by: Shaun Tancheff <shaun.tancheff@hpe.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
libcfs/include/libcfs/libcfs.h
libcfs/include/libcfs/linux/linux-wait.h
libcfs/libcfs/linux/linux-prim.c
lustre/llite/llite_mmap.c
lustre/ptlrpc/client.c

index 3d17af6..b60343b 100644 (file)
@@ -108,8 +108,8 @@ static inline int notifier_from_ioctl_errno(int err)
  * Defined by platform
  */
 int unshare_fs_struct(void);
-sigset_t cfs_block_sigsinv(unsigned long sigs);
-void cfs_restore_sigs(sigset_t);
+void cfs_block_sigsinv(unsigned long sigs, sigset_t *sigset);
+void cfs_restore_sigs(sigset_t *sigset);
 
 int libcfs_ioctl_data_adjust(struct libcfs_ioctl_data *data);
 
index fd154ba..5a3f548 100644 (file)
@@ -208,9 +208,9 @@ __out:      __ret;                                                          \
        wait_queue_entry_t __wq_entry;                                  \
        unsigned long flags;                                            \
        long __ret = ret;       /* explicit shadow */                   \
-       sigset_t __blocked;                                             \
+       sigset_t __old_blocked;                                         \
                                                                        \
-       __blocked = cfs_block_sigsinv(0);                               \
+       cfs_block_sigsinv(0, &__old_blocked);                           \
        init_wait(&__wq_entry);                                         \
        if (exclusive)                                                  \
                __wq_entry.flags = WQ_FLAG_EXCLUSIVE;                   \
@@ -238,7 +238,7 @@ __out:      __ret;                                                          \
                cmd;                                                    \
        }                                                               \
        finish_wait(&wq_head, &__wq_entry);                             \
-       cfs_restore_sigs(__blocked);                                    \
+       cfs_restore_sigs(&__old_blocked);                               \
        __ret;                                                          \
 })
 
@@ -473,9 +473,9 @@ do {                                                                        \
        wait_queue_entry_t __wq_entry;                                  \
        unsigned long flags;                                            \
        long __ret = ret;       /* explicit shadow */                   \
-       sigset_t __blocked;                                             \
+       sigset_t __old_blocked;                                         \
                                                                        \
-       __blocked = cfs_block_sigsinv(0);                               \
+       cfs_block_sigsinv(0, &__old_blocked);                           \
        init_wait(&__wq_entry);                                         \
        __wq_entry.flags = WQ_FLAG_EXCLUSIVE;                           \
        for (;;) {                                                      \
@@ -495,7 +495,7 @@ do {                                                                        \
                }                                                       \
                cmd;                                                    \
        }                                                               \
-       cfs_restore_sigs(__blocked);                                    \
+       cfs_restore_sigs(&__old_blocked);                               \
        finish_wait(&wq_head, &__wq_entry);                             \
        __ret;                                                          \
 })
index a8ca37e..9c65e7e 100644 (file)
@@ -196,28 +196,19 @@ EXPORT_SYMBOL(kstrtobool_from_user);
 #endif /* !HAVE_KSTRTOBOOL_FROM_USER */
 
 /* Block all signals except for the @sigs */
-sigset_t cfs_block_sigsinv(unsigned long sigs)
+void cfs_block_sigsinv(unsigned long sigs, sigset_t *old)
 {
-       unsigned long flags;
-       sigset_t old;
-
-       spin_lock_irqsave(&current->sighand->siglock, flags);
-       old = current->blocked;
-       sigaddsetmask(&current->blocked, ~sigs);
-       recalc_sigpending();
-       spin_unlock_irqrestore(&current->sighand->siglock, flags);
-       return old;
+       sigset_t new;
+
+       siginitsetinv(&new, sigs);
+       sigorsets(&new, &current->blocked, &new);
+       sigprocmask(SIG_BLOCK, &new, old);
 }
 EXPORT_SYMBOL(cfs_block_sigsinv);
 
 void
-cfs_restore_sigs(sigset_t old)
+cfs_restore_sigs(sigset_t *old)
 {
-       unsigned long  flags;
-
-       spin_lock_irqsave(&current->sighand->siglock, flags);
-       current->blocked = old;
-       recalc_sigpending();
-       spin_unlock_irqrestore(&current->sighand->siglock, flags);
+       sigprocmask(SIG_SETMASK, old, NULL);
 }
 EXPORT_SYMBOL(cfs_restore_sigs);
index 673ff2c..0a943d3 100644 (file)
@@ -173,14 +173,14 @@ static int ll_page_mkwrite0(struct vm_area_struct *vma, struct page *vmpage,
        vio->u.fault.ft_vma    = vma;
        vio->u.fault.ft_vmpage = vmpage;
 
-       set = cfs_block_sigsinv(sigmask(SIGKILL) | sigmask(SIGTERM));
+       cfs_block_sigsinv(sigmask(SIGKILL) | sigmask(SIGTERM), &set);
 
        inode = vvp_object_inode(io->ci_obj);
        lli = ll_i2info(inode);
 
        result = cl_io_loop(env, io);
 
-       cfs_restore_sigs(set);
+       cfs_restore_sigs(&set);
 
         if (result == 0) {
                 lock_page(vmpage);
@@ -361,7 +361,7 @@ static vm_fault_t ll_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
        /* Only SIGKILL and SIGTERM is allowed for fault/nopage/mkwrite
         * so that it can be killed by admin but not cause segfault by
         * other signals. */
-       set = cfs_block_sigsinv(sigmask(SIGKILL) | sigmask(SIGTERM));
+       cfs_block_sigsinv(sigmask(SIGKILL) | sigmask(SIGTERM), &set);
 
        /* make sure offset is not a negative number */
        if (vmf->pgoff > (MAX_LFS_FILESIZE >> PAGE_SHIFT))
@@ -390,7 +390,7 @@ restart:
 
                result |= VM_FAULT_LOCKED;
        }
-       cfs_restore_sigs(set);
+       cfs_restore_sigs(&set);
 
 out:
        if (vmf->page && result == VM_FAULT_LOCKED) {
index 758d86e..5602b58 100644 (file)
@@ -2477,9 +2477,10 @@ int ptlrpc_set_wait(const struct lu_env *env, struct ptlrpc_request_set *set)
                         */
                        if (rc == -ETIMEDOUT &&
                            signal_pending(current)) {
-                               sigset_t blocked_sigs =
-                                       cfs_block_sigsinv(LUSTRE_FATAL_SIGS);
+                               sigset_t blocked_sigs;
 
+                               cfs_block_sigsinv(LUSTRE_FATAL_SIGS,
+                                                 &blocked_sigs);
                                /*
                                 * In fact we only interrupt for the
                                 * "fatal" signals like SIGINT or
@@ -2490,7 +2491,7 @@ int ptlrpc_set_wait(const struct lu_env *env, struct ptlrpc_request_set *set)
                                 */
                                if (signal_pending(current))
                                        ptlrpc_interrupted_set(set);
-                               cfs_restore_sigs(blocked_sigs);
+                               cfs_restore_sigs(&blocked_sigs);
                        }
                }