@@ -108,6 +108,15 @@ static int ublk_ctrl_stop_dev(struct ublk_dev *dev)
108108 return __ublk_ctrl_cmd (dev , & data );
109109}
110110
111+ static int ublk_ctrl_try_stop_dev (struct ublk_dev * dev )
112+ {
113+ struct ublk_ctrl_cmd_data data = {
114+ .cmd_op = UBLK_U_CMD_TRY_STOP_DEV ,
115+ };
116+
117+ return __ublk_ctrl_cmd (dev , & data );
118+ }
119+
111120static int ublk_ctrl_start_dev (struct ublk_dev * dev ,
112121 int daemon_pid )
113122{
@@ -1424,6 +1433,42 @@ static int cmd_dev_del(struct dev_ctx *ctx)
14241433 return 0 ;
14251434}
14261435
1436+ static int cmd_dev_stop (struct dev_ctx * ctx )
1437+ {
1438+ int number = ctx -> dev_id ;
1439+ struct ublk_dev * dev ;
1440+ int ret ;
1441+
1442+ if (number < 0 ) {
1443+ ublk_err ("%s: device id is required\n" , __func__ );
1444+ return - EINVAL ;
1445+ }
1446+
1447+ dev = ublk_ctrl_init ();
1448+ dev -> dev_info .dev_id = number ;
1449+
1450+ ret = ublk_ctrl_get_info (dev );
1451+ if (ret < 0 )
1452+ goto fail ;
1453+
1454+ if (ctx -> safe_stop ) {
1455+ ret = ublk_ctrl_try_stop_dev (dev );
1456+ if (ret < 0 )
1457+ ublk_err ("%s: try_stop dev %d failed ret %d\n" ,
1458+ __func__ , number , ret );
1459+ } else {
1460+ ret = ublk_ctrl_stop_dev (dev );
1461+ if (ret < 0 )
1462+ ublk_err ("%s: stop dev %d failed ret %d\n" ,
1463+ __func__ , number , ret );
1464+ }
1465+
1466+ fail :
1467+ ublk_ctrl_deinit (dev );
1468+
1469+ return ret ;
1470+ }
1471+
14271472static int __cmd_dev_list (struct dev_ctx * ctx )
14281473{
14291474 struct ublk_dev * dev = ublk_ctrl_init ();
@@ -1487,6 +1532,7 @@ static int cmd_dev_get_features(void)
14871532 FEAT_NAME (UBLK_F_PER_IO_DAEMON ),
14881533 FEAT_NAME (UBLK_F_BUF_REG_OFF_DAEMON ),
14891534 FEAT_NAME (UBLK_F_INTEGRITY ),
1535+ FEAT_NAME (UBLK_F_SAFE_STOP_DEV )
14901536 };
14911537 struct ublk_dev * dev ;
14921538 __u64 features = 0 ;
@@ -1616,6 +1662,8 @@ static int cmd_dev_help(char *exe)
16161662
16171663 printf ("%s del [-n dev_id] -a \n" , exe );
16181664 printf ("\t -a delete all devices -n delete specified device\n\n" );
1665+ printf ("%s stop -n dev_id [--safe]\n" , exe );
1666+ printf ("\t --safe only stop if device has no active openers\n\n" );
16191667 printf ("%s list [-n dev_id] -a \n" , exe );
16201668 printf ("\t -a list all devices, -n list specified device, default -a \n\n" );
16211669 printf ("%s features\n" , exe );
@@ -1653,6 +1701,7 @@ int main(int argc, char *argv[])
16531701 { "pi_offset" , 1 , NULL , 0 },
16541702 { "csum_type" , 1 , NULL , 0 },
16551703 { "tag_size" , 1 , NULL , 0 },
1704+ { "safe" , 0 , NULL , 0 },
16561705 { 0 , 0 , 0 , 0 }
16571706 };
16581707 const struct ublk_tgt_ops * ops = NULL ;
@@ -1760,6 +1809,8 @@ int main(int argc, char *argv[])
17601809 }
17611810 if (!strcmp (longopts [option_idx ].name , "tag_size" ))
17621811 ctx .tag_size = strtoul (optarg , NULL , 0 );
1812+ if (!strcmp (longopts [option_idx ].name , "safe" ))
1813+ ctx .safe_stop = 1 ;
17631814 break ;
17641815 case '?' :
17651816 /*
@@ -1842,6 +1893,8 @@ int main(int argc, char *argv[])
18421893 }
18431894 } else if (!strcmp (cmd , "del" ))
18441895 ret = cmd_dev_del (& ctx );
1896+ else if (!strcmp (cmd , "stop" ))
1897+ ret = cmd_dev_stop (& ctx );
18451898 else if (!strcmp (cmd , "list" )) {
18461899 ctx .all = 1 ;
18471900 ret = cmd_dev_list (& ctx );
0 commit comments