]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - usr.sbin/mfiutil/mfi_patrol.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / usr.sbin / mfiutil / mfi_patrol.c
1 /*-
2  * Copyright (c) 2008, 2009 Yahoo!, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. The names of the authors may not be used to endorse or promote
14  *    products derived from this software without specific prior written
15  *    permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * $FreeBSD$
30  */
31
32 #include <sys/types.h>
33 #include <sys/errno.h>
34 #include <err.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <time.h>
39 #include <unistd.h>
40 #include "mfiutil.h"
41
42 static char *
43 adapter_time(time_t now, uint32_t at_now, uint32_t at)
44 {
45         time_t t;
46
47         t = (now - at_now) + at;
48         return (ctime(&t));
49 }
50
51 static void
52 mfi_get_time(int fd, uint32_t *at)
53 {
54
55         if (mfi_dcmd_command(fd, MFI_DCMD_TIME_SECS_GET, at, sizeof(*at), NULL,
56             0, NULL) < 0) {
57                 warn("Couldn't fetch adapter time");
58                 at = 0;
59         }
60 }
61
62 static int
63 patrol_get_props(int fd, struct mfi_pr_properties *prop)
64 {
65
66         if (mfi_dcmd_command(fd, MFI_DCMD_PR_GET_PROPERTIES, prop,
67             sizeof(*prop), NULL, 0, NULL) < 0) {
68                 warn("Failed to get patrol read properties");
69                 return (-1);
70         }
71         return (0);
72 }
73
74 static int
75 show_patrol(int ac, char **av)
76 {
77         struct mfi_pr_properties prop;
78         struct mfi_pr_status status;
79         struct mfi_pd_list *list;
80         struct mfi_pd_info info;
81         char label[16];
82         time_t now;
83         uint32_t at;
84         int fd;
85         u_int i;
86
87         fd = mfi_open(mfi_unit);
88         if (fd < 0) {
89                 warn("mfi_open");
90                 return (errno);
91         }
92
93         time(&now);
94         mfi_get_time(fd, &at);
95         if (patrol_get_props(fd, &prop) < 0)
96                 return (errno);
97         printf("Operation Mode: ");
98         switch (prop.op_mode) {
99         case MFI_PR_OPMODE_AUTO:
100                 printf("auto\n");
101                 break;
102         case MFI_PR_OPMODE_MANUAL:
103                 printf("manual\n");
104                 break;
105         case MFI_PR_OPMODE_DISABLED:
106                 printf("disabled\n");
107                 break;
108         default:
109                 printf("??? (%02x)\n", prop.op_mode);
110                 break;
111         }
112         if (prop.op_mode == MFI_PR_OPMODE_AUTO) {
113                 if (at != 0 && prop.next_exec)
114                         printf("    Next Run Starts: %s", adapter_time(now, at,
115                             prop.next_exec));
116                 if (prop.exec_freq == 0xffffffff)
117                         printf("    Runs Execute Continuously\n");
118                 else if (prop.exec_freq != 0)
119                         printf("    Runs Start Every %u seconds\n",
120                             prop.exec_freq);
121         }
122
123         if (mfi_dcmd_command(fd, MFI_DCMD_PR_GET_STATUS, &status,
124             sizeof(status), NULL, 0, NULL) < 0) {
125                 warn("Failed to get patrol read properties");
126                 return (errno);
127         }
128         printf("Runs Completed: %u\n", status.num_iteration);
129         printf("Current State: ");
130         switch (status.state) {
131         case MFI_PR_STATE_STOPPED:
132                 printf("stopped\n");
133                 break;
134         case MFI_PR_STATE_READY:
135                 printf("ready\n");
136                 break;
137         case MFI_PR_STATE_ACTIVE:
138                 printf("active\n");
139                 break;
140         case MFI_PR_STATE_ABORTED:
141                 printf("aborted\n");
142                 break;
143         default:
144                 printf("??? (%02x)\n", status.state);
145                 break;
146         }
147         if (status.state == MFI_PR_STATE_ACTIVE) {
148                 if (mfi_pd_get_list(fd, &list, NULL) < 0) {
149                         warn("Failed to get drive list");
150                         return (errno);
151                 }
152
153                 for (i = 0; i < list->count; i++) {
154                         if (list->addr[i].scsi_dev_type != 0)
155                                 continue;
156
157                         if (mfi_pd_get_info(fd, list->addr[i].device_id, &info,
158                             NULL) < 0) {
159                                 warn("Failed to fetch info for drive %u",
160                                     list->addr[i].device_id);
161                                 return (errno);
162                         }
163                         if (info.prog_info.active & MFI_PD_PROGRESS_PATROL) {
164                                 snprintf(label, sizeof(label), "    Drive %u",
165                                     list->addr[i].device_id);
166                                 mfi_display_progress(label,
167                                     &info.prog_info.patrol);
168                         }
169                 }
170         }
171
172         close(fd);
173
174         return (0);
175 }
176 MFI_COMMAND(show, patrol, show_patrol);
177
178 static int
179 start_patrol(int ac, char **av)
180 {
181         int fd;
182
183         fd = mfi_open(mfi_unit);
184         if (fd < 0) {
185                 warn("mfi_open");
186                 return (errno);
187         }
188
189         if (mfi_dcmd_command(fd, MFI_DCMD_PR_START, NULL, 0, NULL, 0, NULL) <
190             0) {
191                 warn("Failed to start patrol read");
192                 return (errno);
193         }
194
195         close(fd);
196
197         return (0);
198 }
199 MFI_COMMAND(start, patrol, start_patrol);
200
201 static int
202 stop_patrol(int ac, char **av)
203 {
204         int fd;
205
206         fd = mfi_open(mfi_unit);
207         if (fd < 0) {
208                 warn("mfi_open");
209                 return (errno);
210         }
211
212         if (mfi_dcmd_command(fd, MFI_DCMD_PR_STOP, NULL, 0, NULL, 0, NULL) <
213             0) {
214                 warn("Failed to stop patrol read");
215                 return (errno);
216         }
217
218         close(fd);
219
220         return (0);
221 }
222 MFI_COMMAND(stop, patrol, stop_patrol);
223
224 static int
225 patrol_config(int ac, char **av)
226 {
227         struct mfi_pr_properties prop;
228         long val;
229         time_t now;
230         uint32_t at, next_exec, exec_freq;
231         char *cp;
232         uint8_t op_mode;
233         int fd;
234
235         exec_freq = 0;  /* GCC too stupid */
236         next_exec = 0;
237         if (ac < 2) {
238                 warnx("patrol: command required");
239                 return (EINVAL);
240         }
241         if (strcasecmp(av[1], "auto") == 0) {
242                 op_mode = MFI_PR_OPMODE_AUTO;
243                 if (ac > 2) {
244                         if (strcasecmp(av[2], "continously") == 0)
245                                 exec_freq = 0xffffffff;
246                         else {
247                                 val = strtol(av[2], &cp, 0);
248                                 if (*cp != '\0') {
249                                         warnx("patrol: Invalid interval %s",
250                                             av[2]);
251                                         return (EINVAL);
252                                 }
253                                 exec_freq = val;
254                         }
255                 }
256                 if (ac > 3) {
257                         val = strtol(av[3], &cp, 0);
258                         if (*cp != '\0' || val < 0) {
259                                 warnx("patrol: Invalid start time %s", av[3]);
260                                 return (EINVAL);
261                         }
262                         next_exec = val;
263                 }
264         } else if (strcasecmp(av[1], "manual") == 0)
265                 op_mode = MFI_PR_OPMODE_MANUAL;
266         else if (strcasecmp(av[1], "disable") == 0)
267                 op_mode = MFI_PR_OPMODE_DISABLED;
268         else {
269                 warnx("patrol: Invalid command %s", av[1]);
270                 return (EINVAL);
271         }
272
273         fd = mfi_open(mfi_unit);
274         if (fd < 0) {
275                 warn("mfi_open");
276                 return (errno);
277         }
278
279         if (patrol_get_props(fd, &prop) < 0)
280                 return (errno);
281         prop.op_mode = op_mode;
282         if (op_mode == MFI_PR_OPMODE_AUTO) {
283                 if (ac > 2)
284                         prop.exec_freq = exec_freq;
285                 if (ac > 3) {
286                         time(&now);
287                         mfi_get_time(fd, &at);
288                         if (at == 0)
289                                 return (ENXIO);
290                         prop.next_exec = at + next_exec;
291                         printf("Starting next patrol read at %s",
292                             adapter_time(now, at, prop.next_exec));
293                 }
294         }
295         if (mfi_dcmd_command(fd, MFI_DCMD_PR_SET_PROPERTIES, &prop,
296             sizeof(prop), NULL, 0, NULL) < 0) {
297                 warn("Failed to set patrol read properties");
298                 return (errno);
299         }
300
301         close(fd);
302
303         return (0);
304 }
305 MFI_COMMAND(top, patrol, patrol_config);