diff options
author | Horst Hummel <horst.hummel@de.ibm.com> | 2006-08-10 09:45:16 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2006-08-10 09:45:16 -0400 |
commit | d0710c7c9eea2145a0614f39dbe9dc8cb4ae14da (patch) | |
tree | 6d89207033a0a4a9e0c02b507a7f4745d40d4a9d /drivers/s390/block | |
parent | ebc4599990898ecaaace7ed40dfad6d8d9f2a24a (diff) |
[S390] dasd calls kzalloc while holding a spinlock.
The dasd function dasd_set_uid calls kzalloc while holding the
dasd_devmap_lock. Rearrange the code to do the memory allocation
outside the lock.
Signed-off-by: Horst Hummel <horst.hummel@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/block')
-rw-r--r-- | drivers/s390/block/dasd_devmap.c | 65 | ||||
-rw-r--r-- | drivers/s390/block/dasd_eckd.c | 8 |
2 files changed, 32 insertions, 41 deletions
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index 7f6fdac74706..6fcb28d55a9d 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c | |||
@@ -89,7 +89,7 @@ static char *dasd[256]; | |||
89 | module_param_array(dasd, charp, NULL, 0); | 89 | module_param_array(dasd, charp, NULL, 0); |
90 | 90 | ||
91 | /* | 91 | /* |
92 | * Single spinlock to protect devmap structures and lists. | 92 | * Single spinlock to protect devmap and servermap structures and lists. |
93 | */ | 93 | */ |
94 | static DEFINE_SPINLOCK(dasd_devmap_lock); | 94 | static DEFINE_SPINLOCK(dasd_devmap_lock); |
95 | 95 | ||
@@ -859,39 +859,6 @@ static struct attribute_group dasd_attr_group = { | |||
859 | }; | 859 | }; |
860 | 860 | ||
861 | /* | 861 | /* |
862 | * Check if the related storage server is already contained in the | ||
863 | * dasd_serverlist. If server is not contained, create new entry. | ||
864 | * Return 0 if server was already in serverlist, | ||
865 | * 1 if the server was added successfully | ||
866 | * <0 in case of error. | ||
867 | */ | ||
868 | static int | ||
869 | dasd_add_server(struct dasd_uid *uid) | ||
870 | { | ||
871 | struct dasd_servermap *new, *tmp; | ||
872 | |||
873 | /* check if server is already contained */ | ||
874 | list_for_each_entry(tmp, &dasd_serverlist, list) | ||
875 | // normale cmp? | ||
876 | if (strncmp(tmp->sid.vendor, uid->vendor, | ||
877 | sizeof(tmp->sid.vendor)) == 0 | ||
878 | && strncmp(tmp->sid.serial, uid->serial, | ||
879 | sizeof(tmp->sid.serial)) == 0) | ||
880 | return 0; | ||
881 | |||
882 | new = (struct dasd_servermap *) | ||
883 | kzalloc(sizeof(struct dasd_servermap), GFP_KERNEL); | ||
884 | if (!new) | ||
885 | return -ENOMEM; | ||
886 | |||
887 | strncpy(new->sid.vendor, uid->vendor, sizeof(new->sid.vendor)); | ||
888 | strncpy(new->sid.serial, uid->serial, sizeof(new->sid.serial)); | ||
889 | list_add(&new->list, &dasd_serverlist); | ||
890 | return 1; | ||
891 | } | ||
892 | |||
893 | |||
894 | /* | ||
895 | * Return copy of the device unique identifier. | 862 | * Return copy of the device unique identifier. |
896 | */ | 863 | */ |
897 | int | 864 | int |
@@ -910,6 +877,8 @@ dasd_get_uid(struct ccw_device *cdev, struct dasd_uid *uid) | |||
910 | 877 | ||
911 | /* | 878 | /* |
912 | * Register the given device unique identifier into devmap struct. | 879 | * Register the given device unique identifier into devmap struct. |
880 | * In addition check if the related storage server is already contained in the | ||
881 | * dasd_serverlist. If server is not contained, create new entry. | ||
913 | * Return 0 if server was already in serverlist, | 882 | * Return 0 if server was already in serverlist, |
914 | * 1 if the server was added successful | 883 | * 1 if the server was added successful |
915 | * <0 in case of error. | 884 | * <0 in case of error. |
@@ -918,16 +887,38 @@ int | |||
918 | dasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid) | 887 | dasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid) |
919 | { | 888 | { |
920 | struct dasd_devmap *devmap; | 889 | struct dasd_devmap *devmap; |
921 | int rc; | 890 | struct dasd_servermap *srv, *tmp; |
922 | 891 | ||
923 | devmap = dasd_find_busid(cdev->dev.bus_id); | 892 | devmap = dasd_find_busid(cdev->dev.bus_id); |
924 | if (IS_ERR(devmap)) | 893 | if (IS_ERR(devmap)) |
925 | return PTR_ERR(devmap); | 894 | return PTR_ERR(devmap); |
895 | |||
896 | /* generate entry for servermap */ | ||
897 | srv = (struct dasd_servermap *) | ||
898 | kzalloc(sizeof(struct dasd_servermap), GFP_KERNEL); | ||
899 | if (!srv) | ||
900 | return -ENOMEM; | ||
901 | strncpy(srv->sid.vendor, uid->vendor, sizeof(srv->sid.vendor) - 1); | ||
902 | strncpy(srv->sid.serial, uid->serial, sizeof(srv->sid.serial) - 1); | ||
903 | |||
904 | /* server is already contained ? */ | ||
926 | spin_lock(&dasd_devmap_lock); | 905 | spin_lock(&dasd_devmap_lock); |
927 | devmap->uid = *uid; | 906 | devmap->uid = *uid; |
928 | rc = dasd_add_server(uid); | 907 | list_for_each_entry(tmp, &dasd_serverlist, list) { |
908 | if (!memcmp(&srv->sid, &tmp->sid, | ||
909 | sizeof(struct dasd_servermap))) { | ||
910 | kfree(srv); | ||
911 | srv = NULL; | ||
912 | break; | ||
913 | } | ||
914 | } | ||
915 | |||
916 | /* add servermap to serverlist */ | ||
917 | if (srv) | ||
918 | list_add(&srv->list, &dasd_serverlist); | ||
929 | spin_unlock(&dasd_devmap_lock); | 919 | spin_unlock(&dasd_devmap_lock); |
930 | return rc; | 920 | |
921 | return (srv ? 1 : 0); | ||
931 | } | 922 | } |
932 | EXPORT_SYMBOL_GPL(dasd_set_uid); | 923 | EXPORT_SYMBOL_GPL(dasd_set_uid); |
933 | 924 | ||
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 39c2281371b5..957ed5db98e4 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
@@ -468,11 +468,11 @@ dasd_eckd_generate_uid(struct dasd_device *device, struct dasd_uid *uid) | |||
468 | return -ENODEV; | 468 | return -ENODEV; |
469 | 469 | ||
470 | memset(uid, 0, sizeof(struct dasd_uid)); | 470 | memset(uid, 0, sizeof(struct dasd_uid)); |
471 | strncpy(uid->vendor, confdata->ned1.HDA_manufacturer, | 471 | memcpy(uid->vendor, confdata->ned1.HDA_manufacturer, |
472 | sizeof(uid->vendor) - 1); | 472 | sizeof(uid->vendor) - 1); |
473 | EBCASC(uid->vendor, sizeof(uid->vendor) - 1); | 473 | EBCASC(uid->vendor, sizeof(uid->vendor) - 1); |
474 | strncpy(uid->serial, confdata->ned1.HDA_location, | 474 | memcpy(uid->serial, confdata->ned1.HDA_location, |
475 | sizeof(uid->serial) - 1); | 475 | sizeof(uid->serial) - 1); |
476 | EBCASC(uid->serial, sizeof(uid->serial) - 1); | 476 | EBCASC(uid->serial, sizeof(uid->serial) - 1); |
477 | uid->ssid = confdata->neq.subsystemID; | 477 | uid->ssid = confdata->neq.subsystemID; |
478 | if (confdata->ned2.sneq.flags == 0x40) { | 478 | if (confdata->ned2.sneq.flags == 0x40) { |