xref: /aosp_15_r20/external/sg3_utils/src/sg_emc_trespass.c (revision 44704f698541f6367e81f991ef8bb54ccbf3fc18)
1 /* The program allows the user to send a trespass command to change the
2  * LUN ownership from one Service-Processor to this one on an EMC
3  * CLARiiON and potentially other devices.
4  *
5  * Copyright (C) 2004-2018 Lars Marowsky-Bree <[email protected]>
6  *
7  * Based on sg_start.c; credits from there also apply.
8  * Minor modifications for sg_lib, D. Gilbert 2004/10/19
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2, or (at your option)
13  *  any later version.
14  *
15  * SPDX-License-Identifier: GPL-2.0-or-later
16  */
17 
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <unistd.h>
21 #include <stdlib.h>
22 #include <stdarg.h>
23 #include <stdbool.h>
24 #include <string.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <fcntl.h>
28 
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32 #include "sg_lib.h"
33 #include "sg_cmds_basic.h"
34 #include "sg_pr2serr.h"
35 
36 
37 static const char * version_str = "0.23 20180219";
38 
39 static int debug = 0;
40 
41 #define TRESPASS_PAGE           0x22
42 
43 static int
do_trespass(int fd,bool hr,bool short_cmd)44 do_trespass(int fd, bool hr, bool short_cmd)
45 {
46         uint8_t long_trespass_pg[] =
47                 { 0, 0, 0, 0, 0, 0, 0, 0x00,
48                   TRESPASS_PAGE,        /* Page code */
49                   0x09,                 /* Page length - 2 */
50                   0x81,                 /* Trespass code + Honor reservation
51                                          * bit */
52                   0xff, 0xff,           /* Trespass target */
53                   0, 0, 0, 0, 0, 0      /* Reserved bytes / unknown */
54         };
55         uint8_t short_trespass_pg[] =
56                 { 0, 0, 0, 0,
57                   TRESPASS_PAGE,        /* Page code */
58                   0x02,                 /* Page length - 2 */
59                   0x81,                 /* Trespass code + Honor reservation
60                                          * bit */
61                   0xff,                 /* Trespass target */
62         };
63         int res;
64         char b[80];
65 
66         if (hr) {       /* override Trespass code + Honor reservation bit */
67                 short_trespass_pg[6] = 0x01;
68                 long_trespass_pg[10] = 0x01;
69         }
70         if (short_cmd)
71                 res = sg_ll_mode_select6(fd, true /* pf */, false /* sp */,
72                                  short_trespass_pg, sizeof(short_trespass_pg),
73                                  true, (debug ? 2 : 0));
74         else
75                 res = sg_ll_mode_select10(fd, true /* pf */, false /* sp */,
76                                  long_trespass_pg, sizeof(long_trespass_pg),
77                                  true, (debug ? 2 : 0));
78 
79         switch (res) {
80         case 0:
81                 if (debug)
82                         pr2serr("%s trespass successful\n",
83                                 short_cmd ? "short" : "long");
84                 break;
85         case SG_LIB_CAT_INVALID_OP:
86         case SG_LIB_CAT_ILLEGAL_REQ:
87                 pr2serr("%s form trepass page failed, try again %s '-s' "
88                         "option\n", short_cmd ? "short" : "long",
89                         short_cmd ? "without" : "with");
90                 break;
91         case SG_LIB_CAT_NOT_READY:
92                 pr2serr("device not ready\n");
93                 break;
94         case SG_LIB_CAT_UNIT_ATTENTION:
95                 pr2serr("unit attention\n");
96                 break;
97         default:
98                 sg_get_category_sense_str(res, sizeof(b), b, debug);
99                 pr2serr("%s trespass failed: %s\n",
100                         (short_cmd ? "short" : "long"), b);
101                 break;
102         }
103         return res;
104 }
105 
usage()106 void usage ()
107 {
108         pr2serr("Usage:  sg_emc_trespass [-d] [-hr] [-s] [-V] DEVICE\n"
109                 "  Change ownership of a LUN from another SP to this one.\n"
110                 "  EMC CLARiiON CX-/AX-family + FC5300/FC4500/FC4700.\n"
111                 "    -d : output debug\n"
112                 "    -hr: Set Honor Reservation bit\n"
113                 "    -s : Send Short Trespass Command page (default: long)\n"
114                 "         (for FC series)\n"
115                 "    -V: print version string then exit\n"
116                 "     DEVICE   sg or block device (latter in lk 2.6 or lk 3 "
117                 "series)\n"
118                 "        Example: sg_emc_trespass /dev/sda\n");
119         exit (1);
120 }
121 
main(int argc,char * argv[])122 int main(int argc, char * argv[])
123 {
124         char **argptr;
125         char * file_name = 0;
126         int k, fd;
127         bool hr = false;
128         bool short_cmd = false;
129         int ret = 0;
130 
131         if (argc < 2)
132                 usage ();
133 
134         for (k = 1; k < argc; ++k) {
135                 argptr = argv + k;
136                 if (!strcmp (*argptr, "-d"))
137                         ++debug;
138                 else if (!strcmp (*argptr, "-s"))
139                         short_cmd = true;
140                 else if (!strcmp (*argptr, "-hr"))
141                         hr = true;
142                 else if (!strcmp (*argptr, "-V")) {
143                         printf("Version string: %s\n", version_str);
144                         exit(0);
145                 }
146                 else if (*argv[k] == '-') {
147                         pr2serr("Unrecognized switch: %s\n", argv[k]);
148                         file_name = NULL;
149                         break;
150                 }
151                 else if (NULL == file_name)
152                         file_name = argv[k];
153                 else {
154                         pr2serr("too many arguments\n");
155                         file_name = NULL;
156                         break;
157                 }
158         }
159         if (NULL == file_name) {
160                 usage();
161                 return SG_LIB_SYNTAX_ERROR;
162         }
163 
164         fd = open(file_name, O_RDWR | O_NONBLOCK);
165         if (fd < 0) {
166                 pr2serr("Error trying to open %s\n", file_name);
167                 perror("");
168                 usage();
169                 return SG_LIB_FILE_ERROR;
170         }
171 
172         ret = do_trespass(fd, hr, short_cmd);
173 
174         close (fd);
175         return (ret >= 0) ? ret : SG_LIB_CAT_OTHER;
176 }
177