aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/message/i2o
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--drivers/message/i2o/device.c54
-rw-r--r--drivers/message/i2o/i2o_config.c12
2 files changed, 50 insertions, 16 deletions
diff --git a/drivers/message/i2o/device.c b/drivers/message/i2o/device.c
index 489d7c5c4965..8774c670e668 100644
--- a/drivers/message/i2o/device.c
+++ b/drivers/message/i2o/device.c
@@ -243,29 +243,41 @@ static int i2o_device_add(struct i2o_controller *c, i2o_lct_entry *entry)
/* create user entries for this device */
tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid);
- if (tmp && (tmp != i2o_dev))
- sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj,
- "user");
+ if (tmp && (tmp != i2o_dev)) {
+ rc = sysfs_create_link(&i2o_dev->device.kobj,
+ &tmp->device.kobj, "user");
+ if (rc)
+ goto unreg_dev;
+ }
/* create user entries refering to this device */
list_for_each_entry(tmp, &c->devices, list)
if ((tmp->lct_data.user_tid == i2o_dev->lct_data.tid)
- && (tmp != i2o_dev))
- sysfs_create_link(&tmp->device.kobj,
- &i2o_dev->device.kobj, "user");
+ && (tmp != i2o_dev)) {
+ rc = sysfs_create_link(&tmp->device.kobj,
+ &i2o_dev->device.kobj, "user");
+ if (rc)
+ goto rmlink1;
+ }
/* create parent entries for this device */
tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid);
- if (tmp && (tmp != i2o_dev))
- sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj,
- "parent");
+ if (tmp && (tmp != i2o_dev)) {
+ rc = sysfs_create_link(&i2o_dev->device.kobj,
+ &tmp->device.kobj, "parent");
+ if (rc)
+ goto rmlink1;
+ }
/* create parent entries refering to this device */
list_for_each_entry(tmp, &c->devices, list)
if ((tmp->lct_data.parent_tid == i2o_dev->lct_data.tid)
- && (tmp != i2o_dev))
- sysfs_create_link(&tmp->device.kobj,
- &i2o_dev->device.kobj, "parent");
+ && (tmp != i2o_dev)) {
+ rc = sysfs_create_link(&tmp->device.kobj,
+ &i2o_dev->device.kobj, "parent");
+ if (rc)
+ goto rmlink2;
+ }
i2o_driver_notify_device_add_all(i2o_dev);
@@ -273,6 +285,24 @@ static int i2o_device_add(struct i2o_controller *c, i2o_lct_entry *entry)
return 0;
+rmlink2:
+ /* If link creating failed halfway, we loop whole list to cleanup.
+ * And we don't care wrong removing of link, because sysfs_remove_link
+ * will take care of it.
+ */
+ list_for_each_entry(tmp, &c->devices, list) {
+ if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid)
+ sysfs_remove_link(&tmp->device.kobj, "parent");
+ }
+ sysfs_remove_link(&i2o_dev->device.kobj, "parent");
+rmlink1:
+ list_for_each_entry(tmp, &c->devices, list)
+ if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid)
+ sysfs_remove_link(&tmp->device.kobj, "user");
+ sysfs_remove_link(&i2o_dev->device.kobj, "user");
+unreg_dev:
+ list_del(&i2o_dev->list);
+ device_unregister(&i2o_dev->device);
err:
kfree(i2o_dev);
return rc;
diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c
index c0fb77dc19bb..4238de98d4a6 100644
--- a/drivers/message/i2o/i2o_config.c
+++ b/drivers/message/i2o/i2o_config.c
@@ -1061,6 +1061,7 @@ static int cfg_open(struct inode *inode, struct file *file)
if (!tmp)
return -ENOMEM;
+ lock_kernel();
file->private_data = (void *)(i2o_cfg_info_id++);
tmp->fp = file;
tmp->fasync = NULL;
@@ -1074,6 +1075,7 @@ static int cfg_open(struct inode *inode, struct file *file)
spin_lock_irqsave(&i2o_config_lock, flags);
open_files = tmp;
spin_unlock_irqrestore(&i2o_config_lock, flags);
+ unlock_kernel();
return 0;
}
@@ -1082,15 +1084,17 @@ static int cfg_fasync(int fd, struct file *fp, int on)
{
ulong id = (ulong) fp->private_data;
struct i2o_cfg_info *p;
+ int ret = -EBADF;
+ lock_kernel();
for (p = open_files; p; p = p->next)
if (p->q_id == id)
break;
- if (!p)
- return -EBADF;
-
- return fasync_helper(fd, fp, on, &p->fasync);
+ if (p)
+ ret = fasync_helper(fd, fp, on, &p->fasync);
+ unlock_kernel();
+ return ret;
}
static int cfg_release(struct inode *inode, struct file *file)