)]}'
{
  "commit": "eaf5f9073533cde21c7121c136f1c3f072d9cf59",
  "tree": "db9cb9424fbae04decf7a8281a5180f65e5124b9",
  "parents": [
    "f4947fbce208990266920d51837e4e7ba9779db1"
  ],
  "author": {
    "name": "Miklos Szeredi",
    "email": "miklos@szeredi.hu",
    "time": "Tue Jan 10 18:22:25 2012 +0100"
  },
  "committer": {
    "name": "Al Viro",
    "email": "viro@zeniv.linux.org.uk",
    "time": "Tue Jan 10 13:06:32 2012 -0500"
  },
  "message": "fix shrink_dcache_parent() livelock\n\nTwo (or more) concurrent calls of shrink_dcache_parent() on the same dentry may\ncause shrink_dcache_parent() to loop forever.\n\nHere\u0027s what appears to happen:\n\n1 - CPU0: select_parent(P) finds C and puts it on dispose list, returns 1\n\n2 - CPU1: select_parent(P) locks P-\u003ed_lock\n\n3 - CPU0: shrink_dentry_list() locks C-\u003ed_lock\n   dentry_kill(C) tries to lock P-\u003ed_lock but fails, unlocks C-\u003ed_lock\n\n4 - CPU1: select_parent(P) locks C-\u003ed_lock,\n         moves C from dispose list being processed on CPU0 to the new\ndispose list, returns 1\n\n5 - CPU0: shrink_dentry_list() finds dispose list empty, returns\n\n6 - Goto 2 with CPU0 and CPU1 switched\n\nBasically select_parent() steals the dentry from shrink_dentry_list() and thinks\nit found a new one, causing shrink_dentry_list() to think it\u0027s making progress\nand loop over and over.\n\nOne way to trigger this is to make udev calls stat() on the sysfs file while it\nis going away.\n\nHaving a file in /lib/udev/rules.d/ with only this one rule seems to the trick:\n\nATTR{vendor}\u003d\u003d\"0x8086\", ATTR{device}\u003d\u003d\"0x10ca\", ENV{PCI_SLOT_NAME}\u003d\"%k\", ENV{MATCHADDR}\u003d\"$attr{address}\", RUN+\u003d\"/bin/true\"\n\nThen execute the following loop:\n\nwhile true; do\n        echo -bond0 \u003e /sys/class/net/bonding_masters\n        echo +bond0 \u003e /sys/class/net/bonding_masters\n        echo -bond1 \u003e /sys/class/net/bonding_masters\n        echo +bond1 \u003e /sys/class/net/bonding_masters\ndone\n\nOne fix would be to check all callers and prevent concurrent calls to\nshrink_dcache_parent().  But I think a better solution is to stop the\nstealing behavior.\n\nThis patch adds a new dentry flag that is set when the dentry is added to the\ndispose list.  The flag is cleared in dentry_lru_del() in case the dentry gets a\nnew reference just before being pruned.\n\nIf the dentry has this flag, select_parent() will skip it and let\nshrink_dentry_list() retry pruning it.  With select_parent() skipping those\ndentries there will not be the appearance of progress (new dentries found) when\nthere is none, hence shrink_dcache_parent() will not loop forever.\n\nSet the flag is also set in prune_dcache_sb() for consistency as suggested by\nLinus.\n\nSigned-off-by: Miklos Szeredi \u003cmszeredi@suse.cz\u003e\nCC: stable@vger.kernel.org\nSigned-off-by: Al Viro \u003cviro@zeniv.linux.org.uk\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "3c6d3113a255c7af1519fdb6aa1c211ec092e992",
      "old_mode": 33188,
      "old_path": "fs/dcache.c",
      "new_id": "616fedff011a7080c36b6446a33b3479c9c7e7d9",
      "new_mode": 33188,
      "new_path": "fs/dcache.c"
    },
    {
      "type": "modify",
      "old_id": "a47bda5f76db125288898fb1aea2f098bc2dfa42",
      "old_mode": 33188,
      "old_path": "include/linux/dcache.h",
      "new_id": "31f73220e7d71a888e0fcb895f2de54b25ecea29",
      "new_mode": 33188,
      "new_path": "include/linux/dcache.h"
    }
  ]
}
