Commit ed09dcc8 authored by Dan Williams's avatar Dan Williams Committed by Christoph Hellwig

ses: close potential registration race

The slot and address fields have a small window of instability when
userspace can read them before initialization. Separate
enclosure_component
allocation from registration.
Signed-off-by: default avatarDan Williams <dan.j.williams@intel.com>
Signed-off-by: default avatarSong Liu <songliubraving@fb.com>
Reviewed-by: default avatarJens Axboe <axboe@fb.com>
Cc: Hannes Reinecke <hare@suse.de>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
parent acd6d738
...@@ -273,27 +273,26 @@ enclosure_component_find_by_name(struct enclosure_device *edev, ...@@ -273,27 +273,26 @@ enclosure_component_find_by_name(struct enclosure_device *edev,
static const struct attribute_group *enclosure_component_groups[]; static const struct attribute_group *enclosure_component_groups[];
/** /**
* enclosure_component_register - add a particular component to an enclosure * enclosure_component_alloc - prepare a new enclosure component
* @edev: the enclosure to add the component * @edev: the enclosure to add the component
* @num: the device number * @num: the device number
* @type: the type of component being added * @type: the type of component being added
* @name: an optional name to appear in sysfs (leave NULL if none) * @name: an optional name to appear in sysfs (leave NULL if none)
* *
* Registers the component. The name is optional for enclosures that * The name is optional for enclosures that give their components a unique
* give their components a unique name. If not, leave the field NULL * name. If not, leave the field NULL and a name will be assigned.
* and a name will be assigned.
* *
* Returns a pointer to the enclosure component or an error. * Returns a pointer to the enclosure component or an error.
*/ */
struct enclosure_component * struct enclosure_component *
enclosure_component_register(struct enclosure_device *edev, enclosure_component_alloc(struct enclosure_device *edev,
unsigned int number, unsigned int number,
enum enclosure_component_type type, enum enclosure_component_type type,
const char *name) const char *name)
{ {
struct enclosure_component *ecomp; struct enclosure_component *ecomp;
struct device *cdev; struct device *cdev;
int err, i; int i;
char newname[COMPONENT_NAME_SIZE]; char newname[COMPONENT_NAME_SIZE];
if (number >= edev->components) if (number >= edev->components)
...@@ -327,14 +326,30 @@ enclosure_component_register(struct enclosure_device *edev, ...@@ -327,14 +326,30 @@ enclosure_component_register(struct enclosure_device *edev,
cdev->release = enclosure_component_release; cdev->release = enclosure_component_release;
cdev->groups = enclosure_component_groups; cdev->groups = enclosure_component_groups;
return ecomp;
}
EXPORT_SYMBOL_GPL(enclosure_component_alloc);
/**
* enclosure_component_register - publishes an initialized enclosure component
* @ecomp: component to add
*
* Returns 0 on successful registration, releases the component otherwise
*/
int enclosure_component_register(struct enclosure_component *ecomp)
{
struct device *cdev;
int err;
cdev = &ecomp->cdev;
err = device_register(cdev); err = device_register(cdev);
if (err) { if (err) {
ecomp->number = -1; ecomp->number = -1;
put_device(cdev); put_device(cdev);
return ERR_PTR(err); return err;
} }
return ecomp; return 0;
} }
EXPORT_SYMBOL_GPL(enclosure_component_register); EXPORT_SYMBOL_GPL(enclosure_component_register);
......
...@@ -423,16 +423,23 @@ static void ses_enclosure_data_process(struct enclosure_device *edev, ...@@ -423,16 +423,23 @@ static void ses_enclosure_data_process(struct enclosure_device *edev,
type_ptr[0] == ENCLOSURE_COMPONENT_ARRAY_DEVICE) { type_ptr[0] == ENCLOSURE_COMPONENT_ARRAY_DEVICE) {
if (create) if (create)
ecomp = enclosure_component_register(edev, ecomp = enclosure_component_alloc(
edev,
components++, components++,
type_ptr[0], type_ptr[0],
name); name);
else else
ecomp = &edev->component[components++]; ecomp = &edev->component[components++];
if (!IS_ERR(ecomp) && addl_desc_ptr) if (!IS_ERR(ecomp)) {
ses_process_descriptor(ecomp, if (addl_desc_ptr)
ses_process_descriptor(
ecomp,
addl_desc_ptr); addl_desc_ptr);
if (create)
enclosure_component_register(
ecomp);
}
} }
if (desc_ptr) if (desc_ptr)
desc_ptr += len; desc_ptr += len;
......
...@@ -120,8 +120,9 @@ enclosure_register(struct device *, const char *, int, ...@@ -120,8 +120,9 @@ enclosure_register(struct device *, const char *, int,
struct enclosure_component_callbacks *); struct enclosure_component_callbacks *);
void enclosure_unregister(struct enclosure_device *); void enclosure_unregister(struct enclosure_device *);
struct enclosure_component * struct enclosure_component *
enclosure_component_register(struct enclosure_device *, unsigned int, enclosure_component_alloc(struct enclosure_device *, unsigned int,
enum enclosure_component_type, const char *); enum enclosure_component_type, const char *);
int enclosure_component_register(struct enclosure_component *);
int enclosure_add_device(struct enclosure_device *enclosure, int component, int enclosure_add_device(struct enclosure_device *enclosure, int component,
struct device *dev); struct device *dev);
int enclosure_remove_device(struct enclosure_device *, struct device *); int enclosure_remove_device(struct enclosure_device *, struct device *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment