)]}'
{
  "commit": "b89deed32ccc96098bd6bc953c64bba6b847774f",
  "tree": "7a5963bbc5203cfdb39bf2fb1204764df39c71db",
  "parents": [
    "fc2e4d70410546307344821eed6fd23803a45286"
  ],
  "author": {
    "name": "Oleg Nesterov",
    "email": "oleg@tv-sign.ru",
    "time": "Wed May 09 02:33:52 2007 -0700"
  },
  "committer": {
    "name": "Linus Torvalds",
    "email": "torvalds@woody.linux-foundation.org",
    "time": "Wed May 09 12:30:50 2007 -0700"
  },
  "message": "implement flush_work()\n\nA basic problem with flush_scheduled_work() is that it blocks behind _all_\npresently-queued works, rather than just the work whcih the caller wants to\nflush.  If the caller holds some lock, and if one of the queued work happens\nto want that lock as well then accidental deadlocks can occur.\n\nOne example of this is the phy layer: it wants to flush work while holding\nrtnl_lock().  But if a linkwatch event happens to be queued, the phy code will\ndeadlock because the linkwatch callback function takes rtnl_lock.\n\nSo we implement a new function which will flush a *single* work - just the one\nwhich the caller wants to free up.  Thus we avoid the accidental deadlocks\nwhich can arise from unrelated subsystems\u0027 callbacks taking shared locks.\n\nflush_work() non-blockingly dequeues the work_struct which we want to kill,\nthen it waits for its handler to complete on all CPUs.\n\nAdd -\u003ecurrent_work to the \"struct cpu_workqueue_struct\", it points to\ncurrently running \"struct work_struct\". When flush_work(work) detects\n-\u003ecurrent_work \u003d\u003d work, it inserts a barrier at the _head_ of -\u003eworklist\n(and thus right _after_ that work) and waits for completition. This means\nthat the next work fired on that CPU will be this barrier, or another\nbarrier queued by concurrent flush_work(), so the caller of flush_work()\nwill be woken before any \"regular\" work has a chance to run.\n\nWhen wait_on_work() unlocks workqueue_mutex (or whatever we choose to protect\nagainst CPU hotplug), CPU may go away. But in that case take_over_work() will\nmove a barrier we queued to another CPU, it will be fired sometime, and\nwait_on_work() will be woken.\n\nActually, we are doing cleanup_workqueue_thread()-\u003ekthread_stop() before\ntake_over_work(), so cwq-\u003ethread should complete its -\u003eworklist (and thus\nthe barrier), because currently we don\u0027t check kthread_should_stop() in\nrun_workqueue(). But even if we did, everything should be ok.\n\n[akpm@osdl.org: cleanup]\n[akpm@osdl.org: add flush_work_keventd() wrapper]\nSigned-off-by: Oleg Nesterov \u003coleg@tv-sign.ru\u003e\nSigned-off-by: Andrew Morton \u003cakpm@linux-foundation.org\u003e\nSigned-off-by: Linus Torvalds \u003ctorvalds@linux-foundation.org\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "f16ba1e0687d8d14e8e1ecd345e4d7648f8920d3",
      "old_mode": 33188,
      "old_path": "include/linux/workqueue.h",
      "new_id": "26a70992dec80b03466b2491c2c1893632fe3c19",
      "new_mode": 33188,
      "new_path": "include/linux/workqueue.h"
    },
    {
      "type": "modify",
      "old_id": "b7bb37ab03bcfe0bc47c44a2b339c162c8e806ba",
      "old_mode": 33188,
      "old_path": "kernel/workqueue.c",
      "new_id": "918d55267a12a98c43aa1c9ee43e17644712af8d",
      "new_mode": 33188,
      "new_path": "kernel/workqueue.c"
    }
  ]
}
