Skip to content

Commit 4d2095c

Browse files
hreineckemartinkpetersen
authored andcommitted
scsi: libfc: Revisit kref handling
The kref handling in fc_rport is a mess. This patch updates the kref handling according to the following rules: - Take a reference whenever scheduling a workqueue - Take a reference whenever an ELS command is send - Drop the reference at the end of the workqueue function - Drop the reference at the end of handling ELS replies - Take a reference when allocating an rport - Drop the reference when removing an rport Signed-off-by: Hannes Reinecke <hare@suse.com> Acked-by: Johannes Thumshirn <jth@kernel.org> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent 3bc45af commit 4d2095c

File tree

1 file changed

+101
-30
lines changed

1 file changed

+101
-30
lines changed

drivers/scsi/libfc/fc_rport.c

Lines changed: 101 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,19 @@
4444
* path this potential over-use of the mutex is acceptable.
4545
*/
4646

47+
/*
48+
* RPORT REFERENCE COUNTING
49+
*
50+
* A rport reference should be taken when:
51+
* - an rport is allocated
52+
* - a workqueue item is scheduled
53+
* - an ELS request is send
54+
* The reference should be dropped when:
55+
* - the workqueue function has finished
56+
* - the ELS response is handled
57+
* - an rport is removed
58+
*/
59+
4760
#include <linux/kernel.h>
4861
#include <linux/spinlock.h>
4962
#include <linux/interrupt.h>
@@ -242,6 +255,8 @@ static void fc_rport_state_enter(struct fc_rport_priv *rdata,
242255
/**
243256
* fc_rport_work() - Handler for remote port events in the rport_event_queue
244257
* @work: Handle to the remote port being dequeued
258+
*
259+
* Reference counting: drops kref on return
245260
*/
246261
static void fc_rport_work(struct work_struct *work)
247262
{
@@ -329,7 +344,8 @@ static void fc_rport_work(struct work_struct *work)
329344
FC_RPORT_DBG(rdata, "lld callback ev %d\n", event);
330345
rdata->lld_event_callback(lport, rdata, event);
331346
}
332-
cancel_delayed_work_sync(&rdata->retry_work);
347+
if (cancel_delayed_work_sync(&rdata->retry_work))
348+
kref_put(&rdata->kref, lport->tt.rport_destroy);
333349

334350
/*
335351
* Reset any outstanding exchanges before freeing rport.
@@ -381,6 +397,7 @@ static void fc_rport_work(struct work_struct *work)
381397
mutex_unlock(&rdata->rp_mutex);
382398
break;
383399
}
400+
kref_put(&rdata->kref, lport->tt.rport_destroy);
384401
}
385402

386403
/**
@@ -431,19 +448,26 @@ static int fc_rport_login(struct fc_rport_priv *rdata)
431448
* Set the new event so that the old pending event will not occur.
432449
* Since we have the mutex, even if fc_rport_work() is already started,
433450
* it'll see the new event.
451+
*
452+
* Reference counting: does not modify kref
434453
*/
435454
static void fc_rport_enter_delete(struct fc_rport_priv *rdata,
436455
enum fc_rport_event event)
437456
{
457+
struct fc_lport *lport = rdata->local_port;
458+
438459
if (rdata->rp_state == RPORT_ST_DELETE)
439460
return;
440461

441462
FC_RPORT_DBG(rdata, "Delete port\n");
442463

443464
fc_rport_state_enter(rdata, RPORT_ST_DELETE);
444465

445-
if (rdata->event == RPORT_EV_NONE)
446-
queue_work(rport_event_queue, &rdata->event_work);
466+
kref_get(&rdata->kref);
467+
if (rdata->event == RPORT_EV_NONE &&
468+
!queue_work(rport_event_queue, &rdata->event_work))
469+
kref_put(&rdata->kref, lport->tt.rport_destroy);
470+
447471
rdata->event = event;
448472
}
449473

@@ -496,15 +520,22 @@ static int fc_rport_logoff(struct fc_rport_priv *rdata)
496520
*
497521
* Locking Note: The rport lock is expected to be held before calling
498522
* this routine.
523+
*
524+
* Reference counting: schedules workqueue, does not modify kref
499525
*/
500526
static void fc_rport_enter_ready(struct fc_rport_priv *rdata)
501527
{
528+
struct fc_lport *lport = rdata->local_port;
529+
502530
fc_rport_state_enter(rdata, RPORT_ST_READY);
503531

504532
FC_RPORT_DBG(rdata, "Port is Ready\n");
505533

506-
if (rdata->event == RPORT_EV_NONE)
507-
queue_work(rport_event_queue, &rdata->event_work);
534+
kref_get(&rdata->kref);
535+
if (rdata->event == RPORT_EV_NONE &&
536+
!queue_work(rport_event_queue, &rdata->event_work))
537+
kref_put(&rdata->kref, lport->tt.rport_destroy);
538+
508539
rdata->event = RPORT_EV_READY;
509540
}
510541

@@ -515,11 +546,14 @@ static void fc_rport_enter_ready(struct fc_rport_priv *rdata)
515546
* Locking Note: Called without the rport lock held. This
516547
* function will hold the rport lock, call an _enter_*
517548
* function and then unlock the rport.
549+
*
550+
* Reference counting: Drops kref on return.
518551
*/
519552
static void fc_rport_timeout(struct work_struct *work)
520553
{
521554
struct fc_rport_priv *rdata =
522555
container_of(work, struct fc_rport_priv, retry_work.work);
556+
struct fc_lport *lport = rdata->local_port;
523557

524558
mutex_lock(&rdata->rp_mutex);
525559

@@ -547,6 +581,7 @@ static void fc_rport_timeout(struct work_struct *work)
547581
}
548582

549583
mutex_unlock(&rdata->rp_mutex);
584+
kref_put(&rdata->kref, lport->tt.rport_destroy);
550585
}
551586

552587
/**
@@ -556,6 +591,8 @@ static void fc_rport_timeout(struct work_struct *work)
556591
*
557592
* Locking Note: The rport lock is expected to be held before
558593
* calling this routine
594+
*
595+
* Reference counting: does not modify kref
559596
*/
560597
static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp)
561598
{
@@ -602,11 +639,14 @@ static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp)
602639
*
603640
* Locking Note: The rport lock is expected to be held before
604641
* calling this routine
642+
*
643+
* Reference counting: increments kref when scheduling retry_work
605644
*/
606645
static void fc_rport_error_retry(struct fc_rport_priv *rdata,
607646
struct fc_frame *fp)
608647
{
609648
unsigned long delay = msecs_to_jiffies(FC_DEF_E_D_TOV);
649+
struct fc_lport *lport = rdata->local_port;
610650

611651
/* make sure this isn't an FC_EX_CLOSED error, never retry those */
612652
if (PTR_ERR(fp) == -FC_EX_CLOSED)
@@ -619,7 +659,9 @@ static void fc_rport_error_retry(struct fc_rport_priv *rdata,
619659
/* no additional delay on exchange timeouts */
620660
if (PTR_ERR(fp) == -FC_EX_TIMEOUT)
621661
delay = 0;
622-
schedule_delayed_work(&rdata->retry_work, delay);
662+
kref_get(&rdata->kref);
663+
if (!schedule_delayed_work(&rdata->retry_work, delay))
664+
kref_put(&rdata->kref, lport->tt.rport_destroy);
623665
return;
624666
}
625667

@@ -740,6 +782,8 @@ static void fc_rport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
740782
*
741783
* Locking Note: The rport lock is expected to be held before calling
742784
* this routine.
785+
*
786+
* Reference counting: increments kref when sending ELS
743787
*/
744788
static void fc_rport_enter_flogi(struct fc_rport_priv *rdata)
745789
{
@@ -758,18 +802,21 @@ static void fc_rport_enter_flogi(struct fc_rport_priv *rdata)
758802
if (!fp)
759803
return fc_rport_error_retry(rdata, fp);
760804

805+
kref_get(&rdata->kref);
761806
if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_FLOGI,
762807
fc_rport_flogi_resp, rdata,
763-
2 * lport->r_a_tov))
808+
2 * lport->r_a_tov)) {
764809
fc_rport_error_retry(rdata, NULL);
765-
else
766-
kref_get(&rdata->kref);
810+
kref_put(&rdata->kref, lport->tt.rport_destroy);
811+
}
767812
}
768813

769814
/**
770815
* fc_rport_recv_flogi_req() - Handle Fabric Login (FLOGI) request in p-mp mode
771816
* @lport: The local port that received the PLOGI request
772817
* @rx_fp: The PLOGI request frame
818+
*
819+
* Reference counting: drops kref on return
773820
*/
774821
static void fc_rport_recv_flogi_req(struct fc_lport *lport,
775822
struct fc_frame *rx_fp)
@@ -824,8 +871,7 @@ static void fc_rport_recv_flogi_req(struct fc_lport *lport,
824871
* RPORT wouldn;t have created and 'rport_lookup' would have
825872
* failed anyway in that case.
826873
*/
827-
if (lport->point_to_multipoint)
828-
break;
874+
break;
829875
case RPORT_ST_DELETE:
830876
mutex_unlock(&rdata->rp_mutex);
831877
rjt_data.reason = ELS_RJT_FIP;
@@ -969,6 +1015,8 @@ fc_rport_compatible_roles(struct fc_lport *lport, struct fc_rport_priv *rdata)
9691015
*
9701016
* Locking Note: The rport lock is expected to be held before calling
9711017
* this routine.
1018+
*
1019+
* Reference counting: increments kref when sending ELS
9721020
*/
9731021
static void fc_rport_enter_plogi(struct fc_rport_priv *rdata)
9741022
{
@@ -995,12 +1043,13 @@ static void fc_rport_enter_plogi(struct fc_rport_priv *rdata)
9951043
}
9961044
rdata->e_d_tov = lport->e_d_tov;
9971045

1046+
kref_get(&rdata->kref);
9981047
if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_PLOGI,
9991048
fc_rport_plogi_resp, rdata,
1000-
2 * lport->r_a_tov))
1049+
2 * lport->r_a_tov)) {
10011050
fc_rport_error_retry(rdata, NULL);
1002-
else
1003-
kref_get(&rdata->kref);
1051+
kref_put(&rdata->kref, lport->tt.rport_destroy);
1052+
}
10041053
}
10051054

10061055
/**
@@ -1108,6 +1157,8 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
11081157
*
11091158
* Locking Note: The rport lock is expected to be held before calling
11101159
* this routine.
1160+
*
1161+
* Reference counting: increments kref when sending ELS
11111162
*/
11121163
static void fc_rport_enter_prli(struct fc_rport_priv *rdata)
11131164
{
@@ -1151,11 +1202,12 @@ static void fc_rport_enter_prli(struct fc_rport_priv *rdata)
11511202
fc_host_port_id(lport->host), FC_TYPE_ELS,
11521203
FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0);
11531204

1205+
kref_get(&rdata->kref);
11541206
if (!lport->tt.exch_seq_send(lport, fp, fc_rport_prli_resp,
1155-
NULL, rdata, 2 * lport->r_a_tov))
1207+
NULL, rdata, 2 * lport->r_a_tov)) {
11561208
fc_rport_error_retry(rdata, NULL);
1157-
else
1158-
kref_get(&rdata->kref);
1209+
kref_put(&rdata->kref, lport->tt.rport_destroy);
1210+
}
11591211
}
11601212

11611213
/**
@@ -1230,6 +1282,8 @@ static void fc_rport_rtv_resp(struct fc_seq *sp, struct fc_frame *fp,
12301282
*
12311283
* Locking Note: The rport lock is expected to be held before calling
12321284
* this routine.
1285+
*
1286+
* Reference counting: increments kref when sending ELS
12331287
*/
12341288
static void fc_rport_enter_rtv(struct fc_rport_priv *rdata)
12351289
{
@@ -1247,12 +1301,13 @@ static void fc_rport_enter_rtv(struct fc_rport_priv *rdata)
12471301
return;
12481302
}
12491303

1304+
kref_get(&rdata->kref);
12501305
if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_RTV,
12511306
fc_rport_rtv_resp, rdata,
1252-
2 * lport->r_a_tov))
1307+
2 * lport->r_a_tov)) {
12531308
fc_rport_error_retry(rdata, NULL);
1254-
else
1255-
kref_get(&rdata->kref);
1309+
kref_put(&rdata->kref, lport->tt.rport_destroy);
1310+
}
12561311
}
12571312

12581313
/**
@@ -1262,15 +1317,16 @@ static void fc_rport_enter_rtv(struct fc_rport_priv *rdata)
12621317
* @lport_arg: The local port
12631318
*/
12641319
static void fc_rport_logo_resp(struct fc_seq *sp, struct fc_frame *fp,
1265-
void *lport_arg)
1320+
void *rdata_arg)
12661321
{
1267-
struct fc_lport *lport = lport_arg;
1322+
struct fc_rport_priv *rdata = rdata_arg;
1323+
struct fc_lport *lport = rdata->local_port;
12681324

12691325
FC_RPORT_ID_DBG(lport, fc_seq_exch(sp)->did,
12701326
"Received a LOGO %s\n", fc_els_resp_type(fp));
1271-
if (IS_ERR(fp))
1272-
return;
1273-
fc_frame_free(fp);
1327+
if (!IS_ERR(fp))
1328+
fc_frame_free(fp);
1329+
kref_put(&rdata->kref, lport->tt.rport_destroy);
12741330
}
12751331

12761332
/**
@@ -1279,6 +1335,8 @@ static void fc_rport_logo_resp(struct fc_seq *sp, struct fc_frame *fp,
12791335
*
12801336
* Locking Note: The rport lock is expected to be held before calling
12811337
* this routine.
1338+
*
1339+
* Reference counting: increments kref when sending ELS
12821340
*/
12831341
static void fc_rport_enter_logo(struct fc_rport_priv *rdata)
12841342
{
@@ -1291,8 +1349,10 @@ static void fc_rport_enter_logo(struct fc_rport_priv *rdata)
12911349
fp = fc_frame_alloc(lport, sizeof(struct fc_els_logo));
12921350
if (!fp)
12931351
return;
1294-
(void)lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_LOGO,
1295-
fc_rport_logo_resp, lport, 0);
1352+
kref_get(&rdata->kref);
1353+
if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_LOGO,
1354+
fc_rport_logo_resp, rdata, 0))
1355+
kref_put(&rdata->kref, lport->tt.rport_destroy);
12961356
}
12971357

12981358
/**
@@ -1359,6 +1419,8 @@ static void fc_rport_adisc_resp(struct fc_seq *sp, struct fc_frame *fp,
13591419
*
13601420
* Locking Note: The rport lock is expected to be held before calling
13611421
* this routine.
1422+
*
1423+
* Reference counting: increments kref when sending ELS
13621424
*/
13631425
static void fc_rport_enter_adisc(struct fc_rport_priv *rdata)
13641426
{
@@ -1375,12 +1437,13 @@ static void fc_rport_enter_adisc(struct fc_rport_priv *rdata)
13751437
fc_rport_error_retry(rdata, fp);
13761438
return;
13771439
}
1440+
kref_get(&rdata->kref);
13781441
if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_ADISC,
13791442
fc_rport_adisc_resp, rdata,
1380-
2 * lport->r_a_tov))
1443+
2 * lport->r_a_tov)) {
13811444
fc_rport_error_retry(rdata, NULL);
1382-
else
1383-
kref_get(&rdata->kref);
1445+
kref_put(&rdata->kref, lport->tt.rport_destroy);
1446+
}
13841447
}
13851448

13861449
/**
@@ -1494,6 +1557,8 @@ static void fc_rport_recv_rls_req(struct fc_rport_priv *rdata,
14941557
* The ELS opcode has already been validated by the caller.
14951558
*
14961559
* Locking Note: Called with the lport lock held.
1560+
*
1561+
* Reference counting: does not modify kref
14971562
*/
14981563
static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp)
14991564
{
@@ -1561,6 +1626,8 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp)
15611626
* @fp: The request frame
15621627
*
15631628
* Locking Note: Called with the lport lock held.
1629+
*
1630+
* Reference counting: does not modify kref
15641631
*/
15651632
static void fc_rport_recv_req(struct fc_lport *lport, struct fc_frame *fp)
15661633
{
@@ -1605,6 +1672,8 @@ static void fc_rport_recv_req(struct fc_lport *lport, struct fc_frame *fp)
16051672
* @rx_fp: The PLOGI request frame
16061673
*
16071674
* Locking Note: The rport lock is held before calling this function.
1675+
*
1676+
* Reference counting: increments kref on return
16081677
*/
16091678
static void fc_rport_recv_plogi_req(struct fc_lport *lport,
16101679
struct fc_frame *rx_fp)
@@ -1919,6 +1988,8 @@ static void fc_rport_recv_prlo_req(struct fc_rport_priv *rdata,
19191988
*
19201989
* Locking Note: The rport lock is expected to be held before calling
19211990
* this function.
1991+
*
1992+
* Reference counting: drops kref on return
19221993
*/
19231994
static void fc_rport_recv_logo_req(struct fc_lport *lport, struct fc_frame *fp)
19241995
{

0 commit comments

Comments
 (0)