staging: lustre: race condition for check/use cfs_fail_val
authorFan Yong <fan.yong@intel.com>
Wed, 4 Nov 2015 18:40:04 +0000 (13:40 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 16 Nov 2015 04:02:47 +0000 (20:02 -0800)
There are some race conditions when check/use cfs_fail_val.
For example: when inject failure stub for LFSCK test as following:

764   if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_DELAY2) &&
765       cfs_fail_val > 0) {
766           struct l_wait_info lwi;
767
768           lwi = LWI_TIMEOUT(cfs_time_seconds(cfs_fail_val),
769                             NULL, NULL);
770           l_wait_event(thread->t_ctl_waitq,
771                        !thread_is_running(thread),
772                        &lwi);
773
774           if (unlikely(!thread_is_running(thread))) {
775                   CDEBUG(D_LFSCK, "%s: scan dir exit for engine "
776                          "stop, parent "DFID", cookie "LPX64"n",
777                          lfsck_lfsck2name(lfsck),
778                          PFID(lfsck_dto2fid(dir)),
779                          lfsck->li_cookie_dir);
780                   RETURN(0);
781           }
782   }

The "cfs_fail_val" may be changed as zero by others after the check
at the line 765 but before using it at the line 768. Then the LFSCK
engine will fall into "wait" until someone run "lfsck_stop".

Signed-off-by: Fan Yong <fan.yong@intel.com>
Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6146
Reviewed-on: http://review.whamcloud.com/13481
Reviewed-by: Lai Siyao <lai.siyao@intel.com>
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/lustre/lustre/libcfs/fail.c

index d39fecebd12d0996713b8205dbe6fc7c85133df5..ea059b012a669097a5db7209785ff915944260ae 100644 (file)
@@ -126,7 +126,7 @@ int __cfs_fail_timeout_set(__u32 id, __u32 value, int ms, int set)
        int ret;
 
        ret = __cfs_fail_check_set(id, value, set);
-       if (ret) {
+       if (ret && likely(ms > 0)) {
                CERROR("cfs_fail_timeout id %x sleeping for %dms\n",
                       id, ms);
                set_current_state(TASK_UNINTERRUPTIBLE);