On Tue, 13 Mar 2007 11:00:21 -0400 (EDT), Alan Stern <[EMAIL PROTECTED]> wrote:
> The consensus is that we would be better off keeping Oliver's original > patch without your silly change, and instead fixing the particular method > call that deadlocked. Another call that deadlocked with Oliver's patch is ungroup for s390 ccwgroup devices. It can be made to work again with a similar patch. Signed-off-by: Cornelia Huck <[EMAIL PROTECTED]> --- drivers/s390/cio/ccwgroup.c | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) --- linux-2.6.orig/drivers/s390/cio/ccwgroup.c +++ linux-2.6/drivers/s390/cio/ccwgroup.c @@ -67,22 +67,49 @@ __ccwgroup_remove_symlinks(struct ccwgro } +struct ccwgroup_work_struct { + struct ccwgroup_device *gdev; + struct work_struct work; +}; + +static void ccwgroup_ungroup_work(struct work_struct *work) +{ + struct ccwgroup_work_struct *ungroup_work + = container_of(work, struct ccwgroup_work_struct, work); + + __ccwgroup_remove_symlinks(ungroup_work->gdev); + device_unregister(&ungroup_work->gdev->dev); + put_device(&ungroup_work->gdev->dev); + kfree(ungroup_work); +} + /* * Provide an 'ungroup' attribute so the user can remove group devices no * longer needed or accidentially created. Saves memory :) + * Note that we cannot unregister the device from one of its attribute + * methods, so we have to delay it. */ -static ssize_t -ccwgroup_ungroup_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +static ssize_t ccwgroup_ungroup_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { struct ccwgroup_device *gdev; + struct ccwgroup_work_struct *ungroup_work; gdev = to_ccwgroupdev(dev); if (gdev->state != CCWGROUP_OFFLINE) return -EINVAL; - __ccwgroup_remove_symlinks(gdev); - device_unregister(dev); + ungroup_work = kmalloc(sizeof(*ungroup_work), GFP_KERNEL); + if (!ungroup_work) + return -ENOMEM; + ungroup_work->gdev = gdev; + INIT_WORK(&ungroup_work->work, ccwgroup_ungroup_work); + if (!get_device(&gdev->dev)) + kfree(ungroup_work); + else + schedule_work(&ungroup_work->work); return count; } - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/