)]}'
{
  "commit": "6cb2a21049b8990df4576c5fce4d48d0206c22d5",
  "tree": "4303438449e0c0d4859e1818115e09d2fd8340ca",
  "parents": [
    "264e3e889d86e552b4191d69bb60f4f3b383135a"
  ],
  "author": {
    "name": "Quentin Barnes",
    "email": "qbarnes+linux@yahoo-inc.com",
    "time": "Wed Mar 19 17:00:39 2008 -0700"
  },
  "committer": {
    "name": "Linus Torvalds",
    "email": "torvalds@linux-foundation.org",
    "time": "Wed Mar 19 18:53:35 2008 -0700"
  },
  "message": "aio: bad AIO race in aio_complete() leads to process hang\n\nMy group ran into a AIO process hang on a 2.6.24 kernel with the process\nsleeping indefinitely in io_getevents(2) waiting for the last wakeup to come\nand it never would.\n\nWe ran the tests on x86_64 SMP.  The hang only occurred on a Xeon box\n(\"Clovertown\") but not a Core2Duo (\"Conroe\").  On the Xeon, the L2 cache isn\u0027t\nshared between all eight processors, but is L2 is shared between between all\ntwo processors on the Core2Duo we use.\n\nMy analysis of the hang is if you go down to the second while-loop\nin read_events(), what happens on processor #1:\n\t1) add_wait_queue_exclusive() adds thread to ctx-\u003ewait\n\t2) aio_read_evt() to check tail\n\t3) if aio_read_evt() returned 0, call [io_]schedule() and sleep\n\nIn aio_complete() with processor #2:\n\tA) info-\u003etail \u003d tail;\n\tB) waitqueue_active(\u0026ctx-\u003ewait)\n\tC) if waitqueue_active() returned non-0, call wake_up()\n\nThe way the code is written, step 1 must be seen by all other processors\nbefore processor 1 checks for pending events in step 2 (that were recorded by\nstep A) and step A by processor 2 must be seen by all other processors\n(checked in step 2) before step B is done.\n\nThe race I believed I was seeing is that steps 1 and 2 were\neffectively swapped due to the __list_add() being delayed by the L2\ncache not shared by some of the other processors.  Imagine:\nproc 2: just before step A\nproc 1, step 1: adds to ctx-\u003ewait, but is not visible by other processors yet\nproc 1, step 2: checks tail and sees no pending events\nproc 2, step A: updates tail\nproc 1, step 3: calls [io_]schedule() and sleeps\nproc 2, step B: checks ctx-\u003ewait, but sees no one waiting, skips wakeup\n                so proc 1 sleeps indefinitely\n\nMy patch adds a memory barrier between steps A and B.  It ensures that the\nupdate in step 1 gets seen on processor 2 before continuing.  If processor 1\nwas just before step 1, the memory barrier makes sure that step A (update\ntail) gets seen by the time processor 1 makes it to step 2 (check tail).\n\nBefore the patch our AIO process would hang virtually 100% of the time.  After\nthe patch, we have yet to see the process ever hang.\n\nSigned-off-by: Quentin Barnes \u003cqbarnes+linux@yahoo-inc.com\u003e\nReviewed-by: Zach Brown \u003czach.brown@oracle.com\u003e\nCc: Benjamin LaHaise \u003cbcrl@kvack.org\u003e\nCc: \u003cstable@kernel.org\u003e\nCc: Nick Piggin \u003cnickpiggin@yahoo.com.au\u003e\nSigned-off-by: Andrew Morton \u003cakpm@linux-foundation.org\u003e\n[ We should probably disallow that \"if (waitqueue_active()) wake_up()\"\n  coding pattern, because it\u0027s so often buggy wrt memory ordering ]\nSigned-off-by: Linus Torvalds \u003ctorvalds@linux-foundation.org\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "b74c567383bc3689412a6195cb5fd4e2520cb724",
      "old_mode": 33188,
      "old_path": "fs/aio.c",
      "new_id": "6af92194062266d842adfd57cf8abff425bd6ec5",
      "new_mode": 33188,
      "new_path": "fs/aio.c"
    }
  ]
}
