@@ -119,6 +119,27 @@ static int ublk_ctrl_start_dev(struct ublk_dev *dev,
119119 return __ublk_ctrl_cmd (dev , & data );
120120}
121121
122+ static int ublk_ctrl_start_user_recovery (struct ublk_dev * dev )
123+ {
124+ struct ublk_ctrl_cmd_data data = {
125+ .cmd_op = UBLK_U_CMD_START_USER_RECOVERY ,
126+ };
127+
128+ return __ublk_ctrl_cmd (dev , & data );
129+ }
130+
131+ static int ublk_ctrl_end_user_recovery (struct ublk_dev * dev , int daemon_pid )
132+ {
133+ struct ublk_ctrl_cmd_data data = {
134+ .cmd_op = UBLK_U_CMD_END_USER_RECOVERY ,
135+ .flags = CTRL_CMD_HAS_DATA ,
136+ };
137+
138+ dev -> dev_info .ublksrv_pid = data .data [0 ] = daemon_pid ;
139+
140+ return __ublk_ctrl_cmd (dev , & data );
141+ }
142+
122143static int ublk_ctrl_add_dev (struct ublk_dev * dev )
123144{
124145 struct ublk_ctrl_cmd_data data = {
@@ -812,8 +833,12 @@ static int ublk_start_daemon(const struct dev_ctx *ctx, struct ublk_dev *dev)
812833 free (affinity_buf );
813834
814835 /* everything is fine now, start us */
815- ublk_set_parameters (dev );
816- ret = ublk_ctrl_start_dev (dev , getpid ());
836+ if (ctx -> recovery )
837+ ret = ublk_ctrl_end_user_recovery (dev , getpid ());
838+ else {
839+ ublk_set_parameters (dev );
840+ ret = ublk_ctrl_start_dev (dev , getpid ());
841+ }
817842 if (ret < 0 ) {
818843 ublk_err ("%s: ublk_ctrl_start_dev failed: %d\n" , __func__ , ret );
819844 goto fail ;
@@ -988,7 +1013,10 @@ static int __cmd_dev_add(const struct dev_ctx *ctx)
9881013 }
9891014 }
9901015
991- ret = ublk_ctrl_add_dev (dev );
1016+ if (ctx -> recovery )
1017+ ret = ublk_ctrl_start_user_recovery (dev );
1018+ else
1019+ ret = ublk_ctrl_add_dev (dev );
9921020 if (ret < 0 ) {
9931021 ublk_err ("%s: can't add dev id %d, type %s ret %d\n" ,
9941022 __func__ , dev_id , tgt_type , ret );
@@ -1202,12 +1230,14 @@ static int cmd_dev_get_features(void)
12021230 return ret ;
12031231}
12041232
1205- static int cmd_dev_help (char * exe )
1233+ static void __cmd_create_help (char * exe , bool recovery )
12061234{
12071235 int i ;
12081236
1209- printf ("%s add -t [null|loop|stripe] [-q nr_queues] [-d depth] [-n dev_id]\n" , exe );
1210- printf ("\t[--foreground] [--quiet] [-z] [--debug_mask mask]\n" );
1237+ printf ("%s %s -t [null|loop|stripe] [-q nr_queues] [-d depth] [-n dev_id]\n" ,
1238+ exe , recovery ? "recover" : "add" );
1239+ printf ("\t[--foreground] [--quiet] [-z] [--debug_mask mask] [-r 0|1 ] [-g 0|1]\n" );
1240+ printf ("\t[-e 0|1 ] [-i 0|1]\n" );
12111241 printf ("\t[target options] [backfile1] [backfile2] ...\n" );
12121242 printf ("\tdefault: nr_queues=2(max 32), depth=128(max 1024), dev_id=-1(auto allocation)\n" );
12131243
@@ -1217,7 +1247,25 @@ static int cmd_dev_help(char *exe)
12171247 if (ops -> usage )
12181248 ops -> usage (ops );
12191249 }
1250+ }
1251+
1252+ static void cmd_add_help (char * exe )
1253+ {
1254+ __cmd_create_help (exe , false);
1255+ printf ("\n" );
1256+ }
1257+
1258+ static void cmd_recover_help (char * exe )
1259+ {
1260+ __cmd_create_help (exe , true);
1261+ printf ("\tPlease provide exact command line for creating this device with real dev_id\n" );
12201262 printf ("\n" );
1263+ }
1264+
1265+ static int cmd_dev_help (char * exe )
1266+ {
1267+ cmd_add_help (exe );
1268+ cmd_recover_help (exe );
12211269
12221270 printf ("%s del [-n dev_id] -a \n" , exe );
12231271 printf ("\t -a delete all devices -n delete specified device\n\n" );
@@ -1239,6 +1287,10 @@ int main(int argc, char *argv[])
12391287 { "quiet" , 0 , NULL , 0 },
12401288 { "zero_copy" , 0 , NULL , 'z' },
12411289 { "foreground" , 0 , NULL , 0 },
1290+ { "recovery" , 1 , NULL , 'r' },
1291+ { "recovery_fail_io" , 1 , NULL , 'e' },
1292+ { "recovery_reissue" , 1 , NULL , 'i' },
1293+ { "get_data" , 1 , NULL , 'g' },
12421294 { 0 , 0 , 0 , 0 }
12431295 };
12441296 const struct ublk_tgt_ops * ops = NULL ;
@@ -1253,13 +1305,14 @@ int main(int argc, char *argv[])
12531305 int ret = - EINVAL , i ;
12541306 int tgt_argc = 1 ;
12551307 char * tgt_argv [MAX_NR_TGT_ARG ] = { NULL };
1308+ int value ;
12561309
12571310 if (argc == 1 )
12581311 return ret ;
12591312
12601313 opterr = 0 ;
12611314 optind = 2 ;
1262- while ((opt = getopt_long (argc , argv , "t:n:d:q:az" ,
1315+ while ((opt = getopt_long (argc , argv , "t:n:d:q:r:e:i: az" ,
12631316 longopts , & option_idx )) != -1 ) {
12641317 switch (opt ) {
12651318 case 'a' :
@@ -1281,6 +1334,25 @@ int main(int argc, char *argv[])
12811334 case 'z' :
12821335 ctx .flags |= UBLK_F_SUPPORT_ZERO_COPY | UBLK_F_USER_COPY ;
12831336 break ;
1337+ case 'r' :
1338+ value = strtol (optarg , NULL , 10 );
1339+ if (value )
1340+ ctx .flags |= UBLK_F_USER_RECOVERY ;
1341+ break ;
1342+ case 'e' :
1343+ value = strtol (optarg , NULL , 10 );
1344+ if (value )
1345+ ctx .flags |= UBLK_F_USER_RECOVERY | UBLK_F_USER_RECOVERY_FAIL_IO ;
1346+ break ;
1347+ case 'i' :
1348+ value = strtol (optarg , NULL , 10 );
1349+ if (value )
1350+ ctx .flags |= UBLK_F_USER_RECOVERY | UBLK_F_USER_RECOVERY_REISSUE ;
1351+ break ;
1352+ case 'g' :
1353+ value = strtol (optarg , NULL , 10 );
1354+ if (value )
1355+ ctx .flags |= UBLK_F_NEED_GET_DATA ;
12841356 case 0 :
12851357 if (!strcmp (longopts [option_idx ].name , "debug_mask" ))
12861358 ublk_dbg_mask = strtol (optarg , NULL , 16 );
@@ -1326,7 +1398,15 @@ int main(int argc, char *argv[])
13261398
13271399 if (!strcmp (cmd , "add" ))
13281400 ret = cmd_dev_add (& ctx );
1329- else if (!strcmp (cmd , "del" ))
1401+ else if (!strcmp (cmd , "recover" )) {
1402+ if (ctx .dev_id < 0 ) {
1403+ fprintf (stderr , "device id isn't provided for recovering\n" );
1404+ ret = - EINVAL ;
1405+ } else {
1406+ ctx .recovery = 1 ;
1407+ ret = cmd_dev_add (& ctx );
1408+ }
1409+ } else if (!strcmp (cmd , "del" ))
13301410 ret = cmd_dev_del (& ctx );
13311411 else if (!strcmp (cmd , "list" )) {
13321412 ctx .all = 1 ;
0 commit comments