Skip to content

Commit 6c74340

Browse files
author
Stefan Richter
committed
firewire: sbp2: fix memory leak in sbp2_cancel_orbs or at send error
When an ORB was canceled (Command ORB i.e. SCSI request timed out, or Management ORB timed out), or there was a send error in the initial transaction, we missed to drop one of the ORB's references and thus leaked memory. Background: In total, we hold 3 references to each Operation Request Block: - 1 during sbp2_scsi_queuecommand() or sbp2_send_management_orb() respectively, - 1 for the duration of the write transaction to the ORB_Pointer or Management_Agent register of the target, - 1 for as long as the ORB stays within the lu->orb_list, until the ORB is unlinked from the list and the orb->callback was executed. The latter one of these 3 references is finished - normally by sbp2_status_write() when the target wrote status for a pending ORB, - or by sbp2_cancel_orbs() in case of an ORB time-out, - or by complete_transaction() in case of a send error. Of them, the latter two lacked the kref_put. Add the missing kref_put()s. Add comments to the gets and puts of references for transaction callbacks and ORB callbacks so that it is easier to see what is supposed to happen. Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
1 parent 840fe63 commit 6c74340

File tree

1 file changed

+7
-5
lines changed

1 file changed

+7
-5
lines changed

drivers/firewire/sbp2.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,7 @@ static void sbp2_status_write(struct fw_card *card, struct fw_request *request,
450450

451451
if (&orb->link != &lu->orb_list) {
452452
orb->callback(orb, &status);
453-
kref_put(&orb->kref, free_orb);
453+
kref_put(&orb->kref, free_orb); /* orb callback reference */
454454
} else {
455455
fw_error("status write for unknown orb\n");
456456
}
@@ -480,12 +480,14 @@ static void complete_transaction(struct fw_card *card, int rcode,
480480
if (orb->rcode != RCODE_COMPLETE) {
481481
list_del(&orb->link);
482482
spin_unlock_irqrestore(&card->lock, flags);
483+
483484
orb->callback(orb, NULL);
485+
kref_put(&orb->kref, free_orb); /* orb callback reference */
484486
} else {
485487
spin_unlock_irqrestore(&card->lock, flags);
486488
}
487489

488-
kref_put(&orb->kref, free_orb);
490+
kref_put(&orb->kref, free_orb); /* transaction callback reference */
489491
}
490492

491493
static void sbp2_send_orb(struct sbp2_orb *orb, struct sbp2_logical_unit *lu,
@@ -501,9 +503,8 @@ static void sbp2_send_orb(struct sbp2_orb *orb, struct sbp2_logical_unit *lu,
501503
list_add_tail(&orb->link, &lu->orb_list);
502504
spin_unlock_irqrestore(&device->card->lock, flags);
503505

504-
/* Take a ref for the orb list and for the transaction callback. */
505-
kref_get(&orb->kref);
506-
kref_get(&orb->kref);
506+
kref_get(&orb->kref); /* transaction callback reference */
507+
kref_get(&orb->kref); /* orb callback reference */
507508

508509
fw_send_request(device->card, &orb->t, TCODE_WRITE_BLOCK_REQUEST,
509510
node_id, generation, device->max_speed, offset,
@@ -530,6 +531,7 @@ static int sbp2_cancel_orbs(struct sbp2_logical_unit *lu)
530531

531532
orb->rcode = RCODE_CANCELLED;
532533
orb->callback(orb, NULL);
534+
kref_put(&orb->kref, free_orb); /* orb callback reference */
533535
}
534536

535537
return retval;

0 commit comments

Comments
 (0)