Skip to content

Commit

Permalink
[SCSI] Add scsi_dev_info_list_del_keyed()
Browse files Browse the repository at this point in the history
For scsi_dh.c to use devinfo lists, we have to be able to remove entries
before rmmod.

Signed-off-by: James Bottomley <James.Bottomley@suse.de>
  • Loading branch information
Peter Jones authored and James Bottomley committed Jan 24, 2011
1 parent 716163f commit 38a039b
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 0 deletions.
85 changes: 85 additions & 0 deletions drivers/scsi/scsi_devinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,91 @@ int scsi_dev_info_list_add_keyed(int compatible, char *vendor, char *model,
}
EXPORT_SYMBOL(scsi_dev_info_list_add_keyed);

/**
* scsi_dev_info_list_del_keyed - remove one dev_info list entry.
* @vendor: vendor string
* @model: model (product) string
* @key: specify list to use
*
* Description:
* Remove and destroy one dev_info entry for @vendor, @model
* in list specified by @key.
*
* Returns: 0 OK, -error on failure.
**/
int scsi_dev_info_list_del_keyed(char *vendor, char *model, int key)
{
struct scsi_dev_info_list *devinfo, *found = NULL;
struct scsi_dev_info_list_table *devinfo_table =
scsi_devinfo_lookup_by_key(key);

if (IS_ERR(devinfo_table))
return PTR_ERR(devinfo_table);

list_for_each_entry(devinfo, &devinfo_table->scsi_dev_info_list,
dev_info_list) {
if (devinfo->compatible) {
/*
* Behave like the older version of get_device_flags.
*/
size_t max;
/*
* XXX why skip leading spaces? If an odd INQUIRY
* value, that should have been part of the
* scsi_static_device_list[] entry, such as " FOO"
* rather than "FOO". Since this code is already
* here, and we don't know what device it is
* trying to work with, leave it as-is.
*/
max = 8; /* max length of vendor */
while ((max > 0) && *vendor == ' ') {
max--;
vendor++;
}
/*
* XXX removing the following strlen() would be
* good, using it means that for a an entry not in
* the list, we scan every byte of every vendor
* listed in scsi_static_device_list[], and never match
* a single one (and still have to compare at
* least the first byte of each vendor).
*/
if (memcmp(devinfo->vendor, vendor,
min(max, strlen(devinfo->vendor))))
continue;
/*
* Skip spaces again.
*/
max = 16; /* max length of model */
while ((max > 0) && *model == ' ') {
max--;
model++;
}
if (memcmp(devinfo->model, model,
min(max, strlen(devinfo->model))))
continue;
found = devinfo;
} else {
if (!memcmp(devinfo->vendor, vendor,
sizeof(devinfo->vendor)) &&
!memcmp(devinfo->model, model,
sizeof(devinfo->model)))
found = devinfo;
}
if (found)
break;
}

if (found) {
list_del(&found->dev_info_list);
kfree(found);
return 0;
}

return -ENOENT;
}
EXPORT_SYMBOL(scsi_dev_info_list_del_keyed);

/**
* scsi_dev_info_list_add_str - parse dev_list and add to the scsi_dev_info_list.
* @dev_list: string of device flags to add
Expand Down
1 change: 1 addition & 0 deletions drivers/scsi/scsi_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ extern int scsi_get_device_flags_keyed(struct scsi_device *sdev,
extern int scsi_dev_info_list_add_keyed(int compatible, char *vendor,
char *model, char *strflags,
int flags, int key);
extern int scsi_dev_info_list_del_keyed(char *vendor, char *model, int key);
extern int scsi_dev_info_add_list(int key, const char *name);
extern int scsi_dev_info_remove_list(int key);

Expand Down

0 comments on commit 38a039b

Please sign in to comment.