Whamcloud - gitweb
LU-8760 lib: avoid unexpected out of order execution
[fs/lustre-release.git] / lustre / include / lustre_lib.h
index d2d5f31..325fc9b 100644 (file)
  *
  * You should have received a copy of the GNU General Public License
  * version 2 along with this program; If not, see
- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
+ * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * GPL HEADER END
  */
  * @{
  */
 
-#include <linux/signal.h>
 #include <libcfs/libcfs.h>
 #include <lustre/lustre_idl.h>
 #include <lustre_ver.h>
-#include <lustre_cfg.h>
+#include <uapi/linux/lustre_cfg.h>
 
 /* target.c */
 struct ptlrpc_request;
@@ -69,8 +64,6 @@ struct l_wait_info;
 #define LP_POISON ((void *)LL_POISON)
 
 #ifdef HAVE_SERVER_SUPPORT
-void target_client_add_cb(struct obd_device *obd, __u64 transno, void *cb_data,
-                         int error);
 int rev_import_init(struct obd_export *exp);
 int target_handle_connect(struct ptlrpc_request *req);
 int target_handle_disconnect(struct ptlrpc_request *req);
@@ -281,6 +274,30 @@ do {                                                                           \
        for (;;) {                                                             \
                set_current_state(TASK_INTERRUPTIBLE);                         \
                                                                               \
+               /* To guarantee that the condition check will be done */       \
+               /* after setting the thread state as TASK_INTERRUPTIBLE. */    \
+               /* Otherwise, out-of-order execution may cause some race. */   \
+               /* Consider the following real execution order: */             \
+                                                                              \
+               /* 1. Thread1 checks condition on CPU1, gets false. */         \
+               /* 2. Thread2 sets condition on CPU2. */                       \
+               /* 3. Thread2 calls wake_up() on CPU2 to wake the threads */   \
+               /*    with state TASK_INTERRUPTIBLE | TASK_UNINTERRUPTIBLE. */ \
+               /*    But the Thread1's state is TASK_RUNNING at that time. */ \
+               /* 4. Thread1 sets its state as TASK_INTERRUPTIBLE on CPU1, */ \
+               /*    then schedule. */                                        \
+                                                                              \
+               /* If the '__timeout' variable is zero, the Thread1 will */    \
+               /* have no chance to check the condition again. */             \
+                                                                              \
+               /* Generally, the interval between out-of-ordered step1 and */ \
+               /* step4 is very tiny, as to above step2 and step3 cannot */   \
+               /* happen. On some degree, it can explain why we seldom hit */ \
+               /* related trouble. But such race really exists, especially */ \
+               /* consider that the step1 and step4 can be interruptible. */  \
+               /* So add barrier to avoid Thread1 out-of-order execution. */  \
+               smp_mb();                                                      \
+                                                                              \
                if (condition)                                                 \
                        break;                                                 \
                                                                               \