@@ -105,6 +105,13 @@ struct nvmet_rdma_queue {
105
105
struct list_head queue_list ;
106
106
};
107
107
108
+ struct nvmet_rdma_port {
109
+ struct nvmet_port * nport ;
110
+ struct sockaddr_storage addr ;
111
+ struct rdma_cm_id * cm_id ;
112
+ struct delayed_work repair_work ;
113
+ };
114
+
108
115
struct nvmet_rdma_device {
109
116
struct ib_device * device ;
110
117
struct ib_pd * pd ;
@@ -917,7 +924,8 @@ static void nvmet_rdma_free_dev(struct kref *ref)
917
924
static struct nvmet_rdma_device *
918
925
nvmet_rdma_find_get_device (struct rdma_cm_id * cm_id )
919
926
{
920
- struct nvmet_port * port = cm_id -> context ;
927
+ struct nvmet_rdma_port * port = cm_id -> context ;
928
+ struct nvmet_port * nport = port -> nport ;
921
929
struct nvmet_rdma_device * ndev ;
922
930
int inline_page_count ;
923
931
int inline_sge_count ;
@@ -934,17 +942,17 @@ nvmet_rdma_find_get_device(struct rdma_cm_id *cm_id)
934
942
if (!ndev )
935
943
goto out_err ;
936
944
937
- inline_page_count = num_pages (port -> inline_data_size );
945
+ inline_page_count = num_pages (nport -> inline_data_size );
938
946
inline_sge_count = max (cm_id -> device -> attrs .max_sge_rd ,
939
947
cm_id -> device -> attrs .max_recv_sge ) - 1 ;
940
948
if (inline_page_count > inline_sge_count ) {
941
949
pr_warn ("inline_data_size %d cannot be supported by device %s. Reducing to %lu.\n" ,
942
- port -> inline_data_size , cm_id -> device -> name ,
950
+ nport -> inline_data_size , cm_id -> device -> name ,
943
951
inline_sge_count * PAGE_SIZE );
944
- port -> inline_data_size = inline_sge_count * PAGE_SIZE ;
952
+ nport -> inline_data_size = inline_sge_count * PAGE_SIZE ;
945
953
inline_page_count = inline_sge_count ;
946
954
}
947
- ndev -> inline_data_size = port -> inline_data_size ;
955
+ ndev -> inline_data_size = nport -> inline_data_size ;
948
956
ndev -> inline_page_count = inline_page_count ;
949
957
ndev -> device = cm_id -> device ;
950
958
kref_init (& ndev -> ref );
@@ -1272,6 +1280,7 @@ static int nvmet_rdma_cm_accept(struct rdma_cm_id *cm_id,
1272
1280
static int nvmet_rdma_queue_connect (struct rdma_cm_id * cm_id ,
1273
1281
struct rdma_cm_event * event )
1274
1282
{
1283
+ struct nvmet_rdma_port * port = cm_id -> context ;
1275
1284
struct nvmet_rdma_device * ndev ;
1276
1285
struct nvmet_rdma_queue * queue ;
1277
1286
int ret = - EINVAL ;
@@ -1287,7 +1296,7 @@ static int nvmet_rdma_queue_connect(struct rdma_cm_id *cm_id,
1287
1296
ret = - ENOMEM ;
1288
1297
goto put_device ;
1289
1298
}
1290
- queue -> port = cm_id -> context ;
1299
+ queue -> port = port -> nport ;
1291
1300
1292
1301
if (queue -> host_qid == 0 ) {
1293
1302
/* Let inflight controller teardown complete */
@@ -1412,7 +1421,7 @@ static void nvmet_rdma_queue_connect_fail(struct rdma_cm_id *cm_id,
1412
1421
static int nvmet_rdma_device_removal (struct rdma_cm_id * cm_id ,
1413
1422
struct nvmet_rdma_queue * queue )
1414
1423
{
1415
- struct nvmet_port * port ;
1424
+ struct nvmet_rdma_port * port ;
1416
1425
1417
1426
if (queue ) {
1418
1427
/*
@@ -1431,7 +1440,7 @@ static int nvmet_rdma_device_removal(struct rdma_cm_id *cm_id,
1431
1440
* cm_id destroy. use atomic xchg to make sure
1432
1441
* we don't compete with remove_port.
1433
1442
*/
1434
- if (xchg (& port -> priv , NULL ) != cm_id )
1443
+ if (xchg (& port -> cm_id , NULL ) != cm_id )
1435
1444
return 0 ;
1436
1445
1437
1446
/*
@@ -1462,6 +1471,13 @@ static int nvmet_rdma_cm_handler(struct rdma_cm_id *cm_id,
1462
1471
nvmet_rdma_queue_established (queue );
1463
1472
break ;
1464
1473
case RDMA_CM_EVENT_ADDR_CHANGE :
1474
+ if (!queue ) {
1475
+ struct nvmet_rdma_port * port = cm_id -> context ;
1476
+
1477
+ schedule_delayed_work (& port -> repair_work , 0 );
1478
+ break ;
1479
+ }
1480
+ /* FALLTHROUGH */
1465
1481
case RDMA_CM_EVENT_DISCONNECTED :
1466
1482
case RDMA_CM_EVENT_TIMEWAIT_EXIT :
1467
1483
nvmet_rdma_queue_disconnect (queue );
@@ -1504,42 +1520,19 @@ static void nvmet_rdma_delete_ctrl(struct nvmet_ctrl *ctrl)
1504
1520
mutex_unlock (& nvmet_rdma_queue_mutex );
1505
1521
}
1506
1522
1507
- static int nvmet_rdma_add_port (struct nvmet_port * port )
1523
+ static void nvmet_rdma_disable_port (struct nvmet_rdma_port * port )
1508
1524
{
1509
- struct rdma_cm_id * cm_id ;
1510
- struct sockaddr_storage addr = { };
1511
- __kernel_sa_family_t af ;
1512
- int ret ;
1513
-
1514
- switch (port -> disc_addr .adrfam ) {
1515
- case NVMF_ADDR_FAMILY_IP4 :
1516
- af = AF_INET ;
1517
- break ;
1518
- case NVMF_ADDR_FAMILY_IP6 :
1519
- af = AF_INET6 ;
1520
- break ;
1521
- default :
1522
- pr_err ("address family %d not supported\n" ,
1523
- port -> disc_addr .adrfam );
1524
- return - EINVAL ;
1525
- }
1525
+ struct rdma_cm_id * cm_id = xchg (& port -> cm_id , NULL );
1526
1526
1527
- if (port -> inline_data_size < 0 ) {
1528
- port -> inline_data_size = NVMET_RDMA_DEFAULT_INLINE_DATA_SIZE ;
1529
- } else if (port -> inline_data_size > NVMET_RDMA_MAX_INLINE_DATA_SIZE ) {
1530
- pr_warn ("inline_data_size %u is too large, reducing to %u\n" ,
1531
- port -> inline_data_size ,
1532
- NVMET_RDMA_MAX_INLINE_DATA_SIZE );
1533
- port -> inline_data_size = NVMET_RDMA_MAX_INLINE_DATA_SIZE ;
1534
- }
1527
+ if (cm_id )
1528
+ rdma_destroy_id (cm_id );
1529
+ }
1535
1530
1536
- ret = inet_pton_with_scope (& init_net , af , port -> disc_addr .traddr ,
1537
- port -> disc_addr .trsvcid , & addr );
1538
- if (ret ) {
1539
- pr_err ("malformed ip/port passed: %s:%s\n" ,
1540
- port -> disc_addr .traddr , port -> disc_addr .trsvcid );
1541
- return ret ;
1542
- }
1531
+ static int nvmet_rdma_enable_port (struct nvmet_rdma_port * port )
1532
+ {
1533
+ struct sockaddr * addr = (struct sockaddr * )& port -> addr ;
1534
+ struct rdma_cm_id * cm_id ;
1535
+ int ret ;
1543
1536
1544
1537
cm_id = rdma_create_id (& init_net , nvmet_rdma_cm_handler , port ,
1545
1538
RDMA_PS_TCP , IB_QPT_RC );
@@ -1558,42 +1551,112 @@ static int nvmet_rdma_add_port(struct nvmet_port *port)
1558
1551
goto out_destroy_id ;
1559
1552
}
1560
1553
1561
- ret = rdma_bind_addr (cm_id , ( struct sockaddr * ) & addr );
1554
+ ret = rdma_bind_addr (cm_id , addr );
1562
1555
if (ret ) {
1563
- pr_err ("binding CM ID to %pISpcs failed (%d)\n" ,
1564
- (struct sockaddr * )& addr , ret );
1556
+ pr_err ("binding CM ID to %pISpcs failed (%d)\n" , addr , ret );
1565
1557
goto out_destroy_id ;
1566
1558
}
1567
1559
1568
1560
ret = rdma_listen (cm_id , 128 );
1569
1561
if (ret ) {
1570
- pr_err ("listening to %pISpcs failed (%d)\n" ,
1571
- (struct sockaddr * )& addr , ret );
1562
+ pr_err ("listening to %pISpcs failed (%d)\n" , addr , ret );
1572
1563
goto out_destroy_id ;
1573
1564
}
1574
1565
1575
- pr_info ("enabling port %d (%pISpcs)\n" ,
1576
- le16_to_cpu (port -> disc_addr .portid ), (struct sockaddr * )& addr );
1577
- port -> priv = cm_id ;
1566
+ port -> cm_id = cm_id ;
1578
1567
return 0 ;
1579
1568
1580
1569
out_destroy_id :
1581
1570
rdma_destroy_id (cm_id );
1582
1571
return ret ;
1583
1572
}
1584
1573
1585
- static void nvmet_rdma_remove_port (struct nvmet_port * port )
1574
+ static void nvmet_rdma_repair_port_work (struct work_struct * w )
1586
1575
{
1587
- struct rdma_cm_id * cm_id = xchg (& port -> priv , NULL );
1576
+ struct nvmet_rdma_port * port = container_of (to_delayed_work (w ),
1577
+ struct nvmet_rdma_port , repair_work );
1578
+ int ret ;
1588
1579
1589
- if (cm_id )
1590
- rdma_destroy_id (cm_id );
1580
+ nvmet_rdma_disable_port (port );
1581
+ ret = nvmet_rdma_enable_port (port );
1582
+ if (ret )
1583
+ schedule_delayed_work (& port -> repair_work , 5 * HZ );
1584
+ }
1585
+
1586
+ static int nvmet_rdma_add_port (struct nvmet_port * nport )
1587
+ {
1588
+ struct nvmet_rdma_port * port ;
1589
+ __kernel_sa_family_t af ;
1590
+ int ret ;
1591
+
1592
+ port = kzalloc (sizeof (* port ), GFP_KERNEL );
1593
+ if (!port )
1594
+ return - ENOMEM ;
1595
+
1596
+ nport -> priv = port ;
1597
+ port -> nport = nport ;
1598
+ INIT_DELAYED_WORK (& port -> repair_work , nvmet_rdma_repair_port_work );
1599
+
1600
+ switch (nport -> disc_addr .adrfam ) {
1601
+ case NVMF_ADDR_FAMILY_IP4 :
1602
+ af = AF_INET ;
1603
+ break ;
1604
+ case NVMF_ADDR_FAMILY_IP6 :
1605
+ af = AF_INET6 ;
1606
+ break ;
1607
+ default :
1608
+ pr_err ("address family %d not supported\n" ,
1609
+ nport -> disc_addr .adrfam );
1610
+ ret = - EINVAL ;
1611
+ goto out_free_port ;
1612
+ }
1613
+
1614
+ if (nport -> inline_data_size < 0 ) {
1615
+ nport -> inline_data_size = NVMET_RDMA_DEFAULT_INLINE_DATA_SIZE ;
1616
+ } else if (nport -> inline_data_size > NVMET_RDMA_MAX_INLINE_DATA_SIZE ) {
1617
+ pr_warn ("inline_data_size %u is too large, reducing to %u\n" ,
1618
+ nport -> inline_data_size ,
1619
+ NVMET_RDMA_MAX_INLINE_DATA_SIZE );
1620
+ nport -> inline_data_size = NVMET_RDMA_MAX_INLINE_DATA_SIZE ;
1621
+ }
1622
+
1623
+ ret = inet_pton_with_scope (& init_net , af , nport -> disc_addr .traddr ,
1624
+ nport -> disc_addr .trsvcid , & port -> addr );
1625
+ if (ret ) {
1626
+ pr_err ("malformed ip/port passed: %s:%s\n" ,
1627
+ nport -> disc_addr .traddr , nport -> disc_addr .trsvcid );
1628
+ goto out_free_port ;
1629
+ }
1630
+
1631
+ ret = nvmet_rdma_enable_port (port );
1632
+ if (ret )
1633
+ goto out_free_port ;
1634
+
1635
+ pr_info ("enabling port %d (%pISpcs)\n" ,
1636
+ le16_to_cpu (nport -> disc_addr .portid ),
1637
+ (struct sockaddr * )& port -> addr );
1638
+
1639
+ return 0 ;
1640
+
1641
+ out_free_port :
1642
+ kfree (port );
1643
+ return ret ;
1644
+ }
1645
+
1646
+ static void nvmet_rdma_remove_port (struct nvmet_port * nport )
1647
+ {
1648
+ struct nvmet_rdma_port * port = nport -> priv ;
1649
+
1650
+ cancel_delayed_work_sync (& port -> repair_work );
1651
+ nvmet_rdma_disable_port (port );
1652
+ kfree (port );
1591
1653
}
1592
1654
1593
1655
static void nvmet_rdma_disc_port_addr (struct nvmet_req * req ,
1594
- struct nvmet_port * port , char * traddr )
1656
+ struct nvmet_port * nport , char * traddr )
1595
1657
{
1596
- struct rdma_cm_id * cm_id = port -> priv ;
1658
+ struct nvmet_rdma_port * port = nport -> priv ;
1659
+ struct rdma_cm_id * cm_id = port -> cm_id ;
1597
1660
1598
1661
if (inet_addr_is_any ((struct sockaddr * )& cm_id -> route .addr .src_addr )) {
1599
1662
struct nvmet_rdma_rsp * rsp =
@@ -1603,7 +1666,7 @@ static void nvmet_rdma_disc_port_addr(struct nvmet_req *req,
1603
1666
1604
1667
sprintf (traddr , "%pISc" , addr );
1605
1668
} else {
1606
- memcpy (traddr , port -> disc_addr .traddr , NVMF_TRADDR_SIZE );
1669
+ memcpy (traddr , nport -> disc_addr .traddr , NVMF_TRADDR_SIZE );
1607
1670
}
1608
1671
}
1609
1672
0 commit comments