)]}'
{
  "commit": "c93f7669098eb97c5376e5396e3dfb734c17df4f",
  "tree": "0c17f812277320fcefd4f441e1db7a7f862752a5",
  "parents": [
    "63299f057fbce47da895e8865cba7e9c3eb01a20"
  ],
  "author": {
    "name": "Paul Mackerras",
    "email": "paulus@samba.org",
    "time": "Thu May 28 22:18:17 2009 +1000"
  },
  "committer": {
    "name": "Ingo Molnar",
    "email": "mingo@elte.hu",
    "time": "Thu May 28 15:03:50 2009 +0200"
  },
  "message": "perf_counter: Fix race in attaching counters to tasks and exiting\n\nCommit 564c2b21 (\"perf_counter: Optimize context switch between\nidentical inherited contexts\") introduced a race where it is possible\nthat a counter being attached to a task could get attached to the\nwrong task, if the task is one that has inherited its context from\nanother task via fork.  This happens because the optimized context\nswitch could switch the context to another task after find_get_context\nhas read task-\u003eperf_counter_ctxp.  In fact, it\u0027s possible that the\ncontext could then get freed, if the other task then exits.\n\nThis fixes the problem by protecting both the context switch and the\ncritical code in find_get_context with spinlocks.  The context switch\nlocks the cxt-\u003elock of both the outgoing and incoming contexts before\nswapping them.  That means that once code such as find_get_context\nhas obtained the spinlock for the context associated with a task,\nthe context can\u0027t get swapped to another task.  However, the context\nmay have been swapped in the interval between reading\ntask-\u003eperf_counter_ctxp and getting the lock, so it is necessary to\ncheck and retry.\n\nTo make sure that none of the contexts being looked at in\nfind_get_context can get freed, this changes the context freeing code\nto use RCU.  Thus an rcu_read_lock() is sufficient to ensure that no\ncontexts can get freed.  This part of the patch is lifted from a patch\nposted by Peter Zijlstra.\n\nThis also adds a check to make sure that we can\u0027t add a counter to a\ntask that is exiting.\n\nThere is also a race between perf_counter_exit_task and\nfind_get_context; this solves the race by moving the get_ctx that\nwas in perf_counter_alloc into the locked region in find_get_context,\nso that once find_get_context has got the context for a task, it\nwon\u0027t get freed even if the task calls perf_counter_exit_task.  It\ndoesn\u0027t matter if new top-level (non-inherited) counters get attached\nto the context after perf_counter_exit_task has detached the context\nfrom the task.  They will just stay there and never get scheduled in\nuntil the counters\u0027 fds get closed, and then perf_release will remove\nthem from the context and eventually free the context.\n\nWith this, we are now doing the unclone in find_get_context rather\nthan when a counter was added to or removed from a context (actually,\nwe were missing the unclone_ctx() call when adding a counter to a\ncontext).  We don\u0027t need to unclone when removing a counter from a\ncontext because we have no way to remove a counter from a cloned\ncontext.\n\nThis also takes out the smp_wmb() in find_get_context, which Peter\nZijlstra pointed out was unnecessary because the cmpxchg implies a\nfull barrier anyway.\n\nSigned-off-by: Paul Mackerras \u003cpaulus@samba.org\u003e\nAcked-by: Peter Zijlstra \u003ca.p.zijlstra@chello.nl\u003e\nCc: Corey Ashford \u003ccjashfor@linux.vnet.ibm.com\u003e\nCc: Mike Galbraith \u003cefault@gmx.de\u003e\nCc: Marcelo Tosatti \u003cmtosatti@redhat.com\u003e\nCc: Arnaldo Carvalho de Melo \u003cacme@redhat.com\u003e\nCc: John Kacur \u003cjkacur@redhat.com\u003e\nLKML-Reference: \u003c18974.33033.667187.273886@cargo.ozlabs.ibm.com\u003e\nSigned-off-by: Ingo Molnar \u003cmingo@elte.hu\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "a65ddc580514d9260959298d05595970701ebfa1",
      "old_mode": 33188,
      "old_path": "include/linux/perf_counter.h",
      "new_id": "717bf3b59ba4058839ad14b8f7c58e2a3a8e786c",
      "new_mode": 33188,
      "new_path": "include/linux/perf_counter.h"
    },
    {
      "type": "modify",
      "old_id": "367299f91aaff21fe9948035a43f27bd5ee7a4b5",
      "old_mode": 33188,
      "old_path": "kernel/perf_counter.c",
      "new_id": "52e5a15321d80b1d19fb324c90d8a5a01be3927d",
      "new_mode": 33188,
      "new_path": "kernel/perf_counter.c"
    }
  ]
}
