From bf40f1d8f7b22d8418f500642269f23c7d1e0f9b Mon Sep 17 00:00:00 2001
From: shadow <shadow>
Date: Thu, 25 Oct 2007 17:37:23 +0000
Subject: [PATCH] interrupt oig_wait can produce painc on resend.

b=13888
i=nikita
i=alex
---
 lustre/ChangeLog            | 11 +++++++++++
 lustre/include/lustre_net.h |  1 -
 lustre/osc/osc_request.c    | 10 +++++++---
 lustre/ptlrpc/ptlrpcd.c     | 28 ++++++++++------------------
 lustre/tests/sanity.sh      | 18 ++++++++++++++++++
 5 files changed, 46 insertions(+), 22 deletions(-)

diff --git a/lustre/ChangeLog b/lustre/ChangeLog
index 08114f249f..04788de1b3 100644
--- a/lustre/ChangeLog
+++ b/lustre/ChangeLog
@@ -12,6 +12,16 @@
        * Recommended e2fsprogs version: 1.40.2-cfs1
        * Note that reiserfs quotas are disabled on SLES 10 in this kernel.
 
+Severity   : normal
+Bugzilla   : 13888
+Description: interrupt oig_wait produce painc on resend.
+Details    : brw_redo_request can be used for resend requests from ptlrpcd and
+	     private set, and this produce situation when rq_ptlrpcd_data not
+	     copyed to new allocated request and triggered LBUG on assert 
+	     req->rq_ptlrpcd_data != NULL. But this member used only for wakeup
+	     ptlrpcd set if request is changed and can be safety changed to use
+	     rq_set directly.
+
 Severity   : normal
 Bugzilla   : 13497
 Description: LASSERT_{REQ,REP}SWAB macros are buggy
@@ -455,6 +465,7 @@ Details    : Remove 2.5.0 check from dcache.c dir.c file.c llite_internal.h
 	     mds_internal.h mds_lib.c mds_open.c mds_reint.c mds_xattr.c
 	     in mds subsystem.
 
+
 --------------------------------------------------------------------------------
 
 2007-08-10         Cluster File Systems, Inc. <info@clusterfs.com>
diff --git a/lustre/include/lustre_net.h b/lustre/include/lustre_net.h
index b91714ccab..b55d69e6e8 100644
--- a/lustre/include/lustre_net.h
+++ b/lustre/include/lustre_net.h
@@ -403,7 +403,6 @@ struct ptlrpc_request {
         struct ptlrpc_request_set *rq_set;
         void *rq_interpret_reply;               /* Async completion handler */
         union ptlrpc_async_args rq_async_args;  /* Async completion context */
-        void *rq_ptlrpcd_data;
         struct ptlrpc_request_pool *rq_pool;    /* Pool if request from
                                                    preallocated list */
         struct lu_context           rq_session;
diff --git a/lustre/osc/osc_request.c b/lustre/osc/osc_request.c
index 795ca4af88..41f368819c 100644
--- a/lustre/osc/osc_request.c
+++ b/lustre/osc/osc_request.c
@@ -1393,12 +1393,16 @@ int osc_brw_redo_request(struct ptlrpc_request *request,
                         oap->oap_request = ptlrpc_request_addref(new_req);
                 }
         }
-        client_obd_list_unlock(&aa->aa_cli->cl_loi_list_lock);
-
-        DEBUG_REQ(D_INFO, new_req, "new request");
 
+        /* use ptlrpc_set_add_req is safe because interpret functions work 
+         * in check_set context. only one way exist with access to request 
+         * from different thread got -EINTR - this way protected with 
+         * cl_loi_list_lock */
         ptlrpc_set_add_req(set, new_req);
 
+        client_obd_list_unlock(&aa->aa_cli->cl_loi_list_lock);
+
+        DEBUG_REQ(D_INFO, new_req, "new request");
         RETURN(0);
 }
 
diff --git a/lustre/ptlrpc/ptlrpcd.c b/lustre/ptlrpc/ptlrpcd.c
index 7765faa88a..b000473d2b 100644
--- a/lustre/ptlrpc/ptlrpcd.c
+++ b/lustre/ptlrpc/ptlrpcd.c
@@ -48,8 +48,6 @@ struct ptlrpcd_ctl {
         spinlock_t                pc_lock;
         struct completion         pc_starting;
         struct completion         pc_finishing;
-        struct list_head          pc_req_list;
-        cfs_waitq_t               pc_waitq;
         struct ptlrpc_request_set *pc_set;
         char                      pc_name[16];
 #ifndef __KERNEL__
@@ -68,11 +66,11 @@ static int ptlrpcd_users = 0;
 
 void ptlrpcd_wake(struct ptlrpc_request *req)
 {
-        struct ptlrpcd_ctl *pc = req->rq_ptlrpcd_data;
+        struct ptlrpc_request_set *rq_set = req->rq_set;
 
-        LASSERT(pc != NULL);
+        LASSERT(rq_set != NULL);
 
-        cfs_waitq_signal(&pc->pc_waitq);
+        cfs_waitq_signal(&rq_set->set_waitq);
 }
 
 /* requests that are added to the ptlrpcd queue are sent via
@@ -86,9 +84,8 @@ void ptlrpcd_add_req(struct ptlrpc_request *req)
         else
                 pc = &ptlrpcd_recovery_pc;
 
-        req->rq_ptlrpcd_data = pc;
         ptlrpc_set_add_new_req(pc->pc_set, req);
-        wake_up(&pc->pc_waitq);
+        cfs_waitq_signal(&pc->pc_set->set_waitq);
 }
 
 static int ptlrpcd_check(struct ptlrpcd_ctl *pc)
@@ -162,19 +159,13 @@ static int ptlrpcd(void *arg)
          * on the set's new_req_list and ptlrpcd_check moves them into
          * the set. */
         while (1) {
-                cfs_waitlink_t set_wait;
                 struct l_wait_info lwi;
                 cfs_duration_t timeout;
 
                 timeout = cfs_time_seconds(ptlrpc_set_next_timeout(pc->pc_set));
                 lwi = LWI_TIMEOUT(timeout, ptlrpc_expired_set, pc->pc_set);
 
-                /* ala the pinger, wait on pc's waitqueue and the set's */
-                cfs_waitlink_init(&set_wait);
-                cfs_waitq_add(&pc->pc_set->set_waitq, &set_wait);
-                cfs_waitq_forward(&set_wait, &pc->pc_waitq);
-                l_wait_event(pc->pc_waitq, ptlrpcd_check(pc), &lwi);
-                cfs_waitq_del(&pc->pc_set->set_waitq, &set_wait);
+                l_wait_event(pc->pc_set->set_waitq, ptlrpcd_check(pc), &lwi);
 
                 if (test_bit(LIOD_STOP, &pc->pc_flags))
                         break;
@@ -188,8 +179,11 @@ static int ptlrpcd(void *arg)
 
 static void ptlrpcd_zombie_impexp_notify(void)
 {
-        cfs_waitq_signal(&ptlrpcd_pc.pc_waitq);
+        LASSERT(ptlrpcd_pc.pc_set != NULL); // call before ptlrpcd inited ?
+
+        cfs_waitq_signal(&ptlrpcd_pc.pc_set->set_waitq);
 }
+
 #else
 
 int ptlrpcd_check_async_rpcs(void *arg)
@@ -231,10 +225,8 @@ static int ptlrpcd_start(char *name, struct ptlrpcd_ctl *pc)
         memset(pc, 0, sizeof(*pc));
         init_completion(&pc->pc_starting);
         init_completion(&pc->pc_finishing);
-        cfs_waitq_init(&pc->pc_waitq);
         pc->pc_flags = 0;
         spin_lock_init(&pc->pc_lock);
-        CFS_INIT_LIST_HEAD(&pc->pc_req_list);
         snprintf (pc->pc_name, sizeof (pc->pc_name), name);
 
         pc->pc_set = ptlrpc_prep_set();
@@ -267,7 +259,7 @@ static int ptlrpcd_start(char *name, struct ptlrpcd_ctl *pc)
 static void ptlrpcd_stop(struct ptlrpcd_ctl *pc)
 {
         set_bit(LIOD_STOP, &pc->pc_flags);
-        cfs_waitq_signal(&pc->pc_waitq);
+        cfs_waitq_signal(&pc->pc_set->set_waitq);
 #ifdef __KERNEL__
         obd_zombie_impexp_notify = NULL;
         wait_for_completion(&pc->pc_finishing);
diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh
index 5ad80568bb..c5c48e076d 100644
--- a/lustre/tests/sanity.sh
+++ b/lustre/tests/sanity.sh
@@ -4305,6 +4305,24 @@ test_118j() {
 }
 run_test 118j "Simulate unrecoverable OST side error =========="
 
+test_118k()
+{
+	#define OBD_FAIL_OST_BRW_WRITE_BULK      0x20e
+	do_facet ost sysctl -w lustre.fail_loc=0x20e
+	mkdir -p $DIR/$tdir
+
+        for ((i=0;i<10;i++)); do
+                dd if=/dev/zero of=$DIR/$tdir/$tdir-$i bs=1M count=10 &
+	        SLEEPPID=$!
+                sleep 0.500s
+	        kill $SLEEPPID
+	        wait $SLEEPPID
+        done
+
+        sysctl -w lustre.fail_loc=0
+}
+run_test 118k "bio alloc -ENOMEM and IO TERM handling ========="
+
 test_119a() # bug 11737
 {
         BSIZE=$((512 * 1024))
-- 
GitLab