Skip to content

Commit f6549f5

Browse files
committed
ata,scsi: libata-core: Do not leak memory for ata_port struct members
libsas is currently not freeing all the struct ata_port struct members, e.g. ncq_sense_buf for a driver supporting Command Duration Limits (CDL). Add a function, ata_port_free(), that is used to free a ata_port, including its struct members. It makes sense to keep the code related to freeing a ata_port in its own function, which will also free all the struct members of struct ata_port. Fixes: 18bd771 ("scsi: ata: libata: Handle completion of CDL commands using policy 0xD") Reviewed-by: John Garry <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Niklas Cassel <[email protected]>
1 parent 5d92c7c commit f6549f5

File tree

4 files changed

+19
-14
lines changed

4 files changed

+19
-14
lines changed

drivers/ata/libata-core.c

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5489,6 +5489,18 @@ struct ata_port *ata_port_alloc(struct ata_host *host)
54895489
return ap;
54905490
}
54915491

5492+
void ata_port_free(struct ata_port *ap)
5493+
{
5494+
if (!ap)
5495+
return;
5496+
5497+
kfree(ap->pmp_link);
5498+
kfree(ap->slave_link);
5499+
kfree(ap->ncq_sense_buf);
5500+
kfree(ap);
5501+
}
5502+
EXPORT_SYMBOL_GPL(ata_port_free);
5503+
54925504
static void ata_devres_release(struct device *gendev, void *res)
54935505
{
54945506
struct ata_host *host = dev_get_drvdata(gendev);
@@ -5515,15 +5527,7 @@ static void ata_host_release(struct kref *kref)
55155527
int i;
55165528

55175529
for (i = 0; i < host->n_ports; i++) {
5518-
struct ata_port *ap = host->ports[i];
5519-
5520-
if (!ap)
5521-
continue;
5522-
5523-
kfree(ap->pmp_link);
5524-
kfree(ap->slave_link);
5525-
kfree(ap->ncq_sense_buf);
5526-
kfree(ap);
5530+
ata_port_free(host->ports[i]);
55275531
host->ports[i] = NULL;
55285532
}
55295533
kfree(host);
@@ -5906,7 +5910,7 @@ int ata_host_register(struct ata_host *host, const struct scsi_host_template *sh
59065910
* allocation time.
59075911
*/
59085912
for (i = host->n_ports; host->ports[i]; i++)
5909-
kfree(host->ports[i]);
5913+
ata_port_free(host->ports[i]);
59105914

59115915
/* give ports names and add SCSI hosts */
59125916
for (i = 0; i < host->n_ports; i++) {

drivers/scsi/libsas/sas_ata.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -610,15 +610,15 @@ int sas_ata_init(struct domain_device *found_dev)
610610

611611
rc = ata_sas_tport_add(ata_host->dev, ap);
612612
if (rc)
613-
goto destroy_port;
613+
goto free_port;
614614

615615
found_dev->sata_dev.ata_host = ata_host;
616616
found_dev->sata_dev.ap = ap;
617617

618618
return 0;
619619

620-
destroy_port:
621-
kfree(ap);
620+
free_port:
621+
ata_port_free(ap);
622622
free_host:
623623
ata_host_put(ata_host);
624624
return rc;

drivers/scsi/libsas/sas_discover.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ void sas_free_device(struct kref *kref)
301301

302302
if (dev_is_sata(dev) && dev->sata_dev.ap) {
303303
ata_sas_tport_delete(dev->sata_dev.ap);
304-
kfree(dev->sata_dev.ap);
304+
ata_port_free(dev->sata_dev.ap);
305305
ata_host_put(dev->sata_dev.ata_host);
306306
dev->sata_dev.ata_host = NULL;
307307
dev->sata_dev.ap = NULL;

include/linux/libata.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1249,6 +1249,7 @@ extern int ata_slave_link_init(struct ata_port *ap);
12491249
extern struct ata_port *ata_sas_port_alloc(struct ata_host *,
12501250
struct ata_port_info *, struct Scsi_Host *);
12511251
extern void ata_port_probe(struct ata_port *ap);
1252+
extern void ata_port_free(struct ata_port *ap);
12521253
extern int ata_sas_tport_add(struct device *parent, struct ata_port *ap);
12531254
extern void ata_sas_tport_delete(struct ata_port *ap);
12541255
int ata_sas_device_configure(struct scsi_device *sdev, struct queue_limits *lim,

0 commit comments

Comments
 (0)