diff options
author | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2006-09-06 13:04:00 -0400 |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2006-09-17 13:38:14 -0400 |
commit | 9b516010863195ba7db061233a3eeffe779130e8 (patch) | |
tree | 90e2b8a96d8010d350f2a62f676aab0dc6d55a76 /drivers/ieee1394 | |
parent | b809289df06ff9453c1b19df74ea83aba311dfc6 (diff) |
ieee1394: nodemgr: fix rwsem recursion
nodemgr_update_pdrv grabbed an rw semaphore (as reader) which was
already taken by its caller's caller, nodemgr_probe_ne (as reader too).
Reported by Miles Lane, call path pointed out by Arjan van de Ven.
FIXME:
Shouldn't we rather use class->sem there, not class->subsys.rwsem?
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/ieee1394')
-rw-r--r-- | drivers/ieee1394/nodemgr.c | 9 |
1 files changed, 5 insertions, 4 deletions
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index eabc51b23c0b..f087f7e2b691 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c | |||
@@ -1316,6 +1316,7 @@ static void nodemgr_node_scan(struct host_info *hi, int generation) | |||
1316 | } | 1316 | } |
1317 | 1317 | ||
1318 | 1318 | ||
1319 | /* Caller needs to hold nodemgr_ud_class.subsys.rwsem as reader. */ | ||
1319 | static void nodemgr_suspend_ne(struct node_entry *ne) | 1320 | static void nodemgr_suspend_ne(struct node_entry *ne) |
1320 | { | 1321 | { |
1321 | struct class_device *cdev; | 1322 | struct class_device *cdev; |
@@ -1368,15 +1369,14 @@ static void nodemgr_resume_ne(struct node_entry *ne) | |||
1368 | } | 1369 | } |
1369 | 1370 | ||
1370 | 1371 | ||
1372 | /* Caller needs to hold nodemgr_ud_class.subsys.rwsem as reader. */ | ||
1371 | static void nodemgr_update_pdrv(struct node_entry *ne) | 1373 | static void nodemgr_update_pdrv(struct node_entry *ne) |
1372 | { | 1374 | { |
1373 | struct unit_directory *ud; | 1375 | struct unit_directory *ud; |
1374 | struct hpsb_protocol_driver *pdrv; | 1376 | struct hpsb_protocol_driver *pdrv; |
1375 | struct class *class = &nodemgr_ud_class; | ||
1376 | struct class_device *cdev; | 1377 | struct class_device *cdev; |
1377 | 1378 | ||
1378 | down_read(&class->subsys.rwsem); | 1379 | list_for_each_entry(cdev, &nodemgr_ud_class.children, node) { |
1379 | list_for_each_entry(cdev, &class->children, node) { | ||
1380 | ud = container_of(cdev, struct unit_directory, class_dev); | 1380 | ud = container_of(cdev, struct unit_directory, class_dev); |
1381 | if (ud->ne != ne || !ud->device.driver) | 1381 | if (ud->ne != ne || !ud->device.driver) |
1382 | continue; | 1382 | continue; |
@@ -1389,7 +1389,6 @@ static void nodemgr_update_pdrv(struct node_entry *ne) | |||
1389 | up_write(&ud->device.bus->subsys.rwsem); | 1389 | up_write(&ud->device.bus->subsys.rwsem); |
1390 | } | 1390 | } |
1391 | } | 1391 | } |
1392 | up_read(&class->subsys.rwsem); | ||
1393 | } | 1392 | } |
1394 | 1393 | ||
1395 | 1394 | ||
@@ -1420,6 +1419,8 @@ static void nodemgr_irm_write_bc(struct node_entry *ne, int generation) | |||
1420 | } | 1419 | } |
1421 | 1420 | ||
1422 | 1421 | ||
1422 | /* Caller needs to hold nodemgr_ud_class.subsys.rwsem as reader because the | ||
1423 | * calls to nodemgr_update_pdrv() and nodemgr_suspend_ne() here require it. */ | ||
1423 | static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int generation) | 1424 | static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int generation) |
1424 | { | 1425 | { |
1425 | struct device *dev; | 1426 | struct device *dev; |