Skip to content

Commit

Permalink
ctcm rollback in case of errors
Browse files Browse the repository at this point in the history
Group device now cleanly reacts to failures during channel start and
implements a clean rollback.

Signed-off-by: Einar Lueck <elelueck@de.ibm.com>
Signed-off-by: Ursula Braun <ursula.braun@de.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Einar Lueck authored and David S. Miller committed Oct 18, 2009
1 parent d816d42 commit a1c1f5e
Showing 1 changed file with 42 additions and 17 deletions.
59 changes: 42 additions & 17 deletions drivers/s390/net/ctcm_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1530,11 +1530,16 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev)
struct net_device *dev;
struct ccw_device *cdev0;
struct ccw_device *cdev1;
struct channel *readc;
struct channel *writec;
int ret;
int result;

priv = dev_get_drvdata(&cgdev->dev);
if (!priv)
return -ENODEV;
if (!priv) {
result = -ENODEV;
goto out_err_result;
}

cdev0 = cgdev->cdev[0];
cdev1 = cgdev->cdev[1];
Expand All @@ -1545,31 +1550,40 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev)
snprintf(write_id, CTCM_ID_SIZE, "ch-%s", dev_name(&cdev1->dev));

ret = add_channel(cdev0, type, priv);
if (ret)
return ret;
if (ret) {
result = ret;
goto out_err_result;
}
ret = add_channel(cdev1, type, priv);
if (ret)
return ret;
if (ret) {
result = ret;
goto out_remove_channel1;
}

ret = ccw_device_set_online(cdev0);
if (ret != 0) {
/* may be ok to fail now - can be done later */
CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE,
"%s(%s) set_online rc=%d",
CTCM_FUNTAIL, read_id, ret);
result = -EIO;
goto out_remove_channel2;
}

ret = ccw_device_set_online(cdev1);
if (ret != 0) {
/* may be ok to fail now - can be done later */
CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE,
"%s(%s) set_online rc=%d",
CTCM_FUNTAIL, write_id, ret);

result = -EIO;
goto out_ccw1;
}

dev = ctcm_init_netdevice(priv);
if (dev == NULL)
goto out;
if (dev == NULL) {
result = -ENODEV;
goto out_ccw2;
}

for (direction = READ; direction <= WRITE; direction++) {
priv->channel[direction] =
Expand All @@ -1587,12 +1601,14 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev)
/* sysfs magic */
SET_NETDEV_DEV(dev, &cgdev->dev);

if (register_netdev(dev))
goto out_dev;
if (register_netdev(dev)) {
result = -ENODEV;
goto out_dev;
}

if (ctcm_add_attributes(&cgdev->dev)) {
unregister_netdev(dev);
goto out_dev;
result = -ENODEV;
goto out_unregister;
}

strlcpy(priv->fsm->name, dev->name, sizeof(priv->fsm->name));
Expand All @@ -1608,13 +1624,22 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev)
priv->channel[WRITE]->id, priv->protocol);

return 0;
out_unregister:
unregister_netdev(dev);
out_dev:
ctcm_free_netdevice(dev);
out:
out_ccw2:
ccw_device_set_offline(cgdev->cdev[1]);
out_ccw1:
ccw_device_set_offline(cgdev->cdev[0]);

return -ENODEV;
out_remove_channel2:
readc = channel_get(type, read_id, READ);
channel_remove(readc);
out_remove_channel1:
writec = channel_get(type, write_id, WRITE);
channel_remove(writec);
out_err_result:
return result;
}

/**
Expand Down

0 comments on commit a1c1f5e

Please sign in to comment.