2 * Copyright (c) 2008, 2009 Yahoo!, Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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
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
32 #include <sys/types.h>
33 #include <sys/errno.h>
42 MFI_TABLE(top, volume);
45 mfi_ldstate(enum mfi_ld_state state)
50 case MFI_LD_STATE_OFFLINE:
52 case MFI_LD_STATE_PARTIALLY_DEGRADED:
53 return ("PARTIALLY DEGRADED");
54 case MFI_LD_STATE_DEGRADED:
56 case MFI_LD_STATE_OPTIMAL:
59 sprintf(buf, "LSTATE 0x%02x", state);
65 mbox_store_ldref(uint8_t *mbox, union mfi_ld_ref *ref)
68 mbox[0] = ref->v.target_id;
69 mbox[1] = ref->v.reserved;
70 mbox[2] = ref->v.seq & 0xff;
71 mbox[3] = ref->v.seq >> 8;
75 mfi_ld_get_list(int fd, struct mfi_ld_list *list, uint8_t *statusp)
78 return (mfi_dcmd_command(fd, MFI_DCMD_LD_GET_LIST, list,
79 sizeof(struct mfi_ld_list), NULL, 0, statusp));
83 mfi_ld_get_info(int fd, uint8_t target_id, struct mfi_ld_info *info,
89 return (mfi_dcmd_command(fd, MFI_DCMD_LD_GET_INFO, info,
90 sizeof(struct mfi_ld_info), mbox, 1, statusp));
94 mfi_ld_get_props(int fd, uint8_t target_id, struct mfi_ld_props *props)
99 return (mfi_dcmd_command(fd, MFI_DCMD_LD_GET_PROP, props,
100 sizeof(struct mfi_ld_props), mbox, 1, NULL));
104 mfi_ld_set_props(int fd, struct mfi_ld_props *props)
108 mbox_store_ldref(mbox, &props->ld);
109 return (mfi_dcmd_command(fd, MFI_DCMD_LD_SET_PROP, props,
110 sizeof(struct mfi_ld_props), mbox, 4, NULL));
114 update_cache_policy(int fd, struct mfi_ld_props *props, uint8_t new_policy,
118 uint8_t changes, policy;
120 policy = (props->default_cache_policy & ~mask) | new_policy;
121 if (policy == props->default_cache_policy)
123 changes = policy ^ props->default_cache_policy;
124 if (changes & MR_LD_CACHE_ALLOW_WRITE_CACHE)
125 printf("%s caching of I/O writes\n",
126 policy & MR_LD_CACHE_ALLOW_WRITE_CACHE ? "Enabling" :
128 if (changes & MR_LD_CACHE_ALLOW_READ_CACHE)
129 printf("%s caching of I/O reads\n",
130 policy & MR_LD_CACHE_ALLOW_READ_CACHE ? "Enabling" :
132 if (changes & MR_LD_CACHE_WRITE_BACK)
133 printf("Setting write cache policy to %s\n",
134 policy & MR_LD_CACHE_WRITE_BACK ? "write-back" :
136 if (changes & (MR_LD_CACHE_READ_AHEAD | MR_LD_CACHE_READ_ADAPTIVE))
137 printf("Setting read ahead policy to %s\n",
138 policy & MR_LD_CACHE_READ_AHEAD ?
139 (policy & MR_LD_CACHE_READ_ADAPTIVE ?
140 "adaptive" : "always") : "none");
142 props->default_cache_policy = policy;
143 if (mfi_ld_set_props(fd, props) < 0) {
145 warn("Failed to set volume properties");
152 volume_cache(int ac, char **av)
154 struct mfi_ld_props props;
156 uint8_t target_id, policy;
159 warnx("cache: volume required");
163 fd = mfi_open(mfi_unit);
170 if (mfi_lookup_volume(fd, av[1], &target_id) < 0) {
172 warn("Invalid volume: %s", av[1]);
176 if (mfi_ld_get_props(fd, target_id, &props) < 0) {
178 warn("Failed to fetch volume properties");
183 printf("mfi%u volume %s cache settings:\n", mfi_unit,
184 mfi_volume_name(fd, target_id));
185 printf(" I/O caching: ");
186 switch (props.default_cache_policy &
187 (MR_LD_CACHE_ALLOW_WRITE_CACHE |
188 MR_LD_CACHE_ALLOW_READ_CACHE)) {
190 printf("disabled\n");
192 case MR_LD_CACHE_ALLOW_WRITE_CACHE:
195 case MR_LD_CACHE_ALLOW_READ_CACHE:
198 case MR_LD_CACHE_ALLOW_WRITE_CACHE |
199 MR_LD_CACHE_ALLOW_READ_CACHE:
200 printf("writes and reads\n");
203 printf(" write caching: %s\n",
204 props.default_cache_policy & MR_LD_CACHE_WRITE_BACK ?
205 "write-back" : "write-through");
206 printf(" read ahead: %s\n",
207 props.default_cache_policy & MR_LD_CACHE_READ_AHEAD ?
208 (props.default_cache_policy & MR_LD_CACHE_READ_ADAPTIVE ?
209 "adaptive" : "always") : "none");
210 printf("drive write cache: ");
211 switch (props.disk_cache_policy) {
212 case MR_PD_CACHE_UNCHANGED:
215 case MR_PD_CACHE_ENABLE:
218 case MR_PD_CACHE_DISABLE:
219 printf("disabled\n");
222 printf("??? %d\n", props.disk_cache_policy);
225 if (props.default_cache_policy != props.current_cache_policy)
226 printf("Cache Disabled Due to Dead Battery\n");
229 if (strcmp(av[2], "all") == 0 || strcmp(av[2], "enable") == 0)
230 error = update_cache_policy(fd, &props,
231 MR_LD_CACHE_ALLOW_READ_CACHE |
232 MR_LD_CACHE_ALLOW_WRITE_CACHE,
233 MR_LD_CACHE_ALLOW_READ_CACHE |
234 MR_LD_CACHE_ALLOW_WRITE_CACHE);
235 else if (strcmp(av[2], "none") == 0 ||
236 strcmp(av[2], "disable") == 0)
237 error = update_cache_policy(fd, &props, 0,
238 MR_LD_CACHE_ALLOW_READ_CACHE |
239 MR_LD_CACHE_ALLOW_WRITE_CACHE);
240 else if (strcmp(av[2], "reads") == 0)
241 error = update_cache_policy(fd, &props,
242 MR_LD_CACHE_ALLOW_READ_CACHE,
243 MR_LD_CACHE_ALLOW_READ_CACHE |
244 MR_LD_CACHE_ALLOW_WRITE_CACHE);
245 else if (strcmp(av[2], "writes") == 0)
246 error = update_cache_policy(fd, &props,
247 MR_LD_CACHE_ALLOW_WRITE_CACHE,
248 MR_LD_CACHE_ALLOW_READ_CACHE |
249 MR_LD_CACHE_ALLOW_WRITE_CACHE);
250 else if (strcmp(av[2], "write-back") == 0)
251 error = update_cache_policy(fd, &props,
252 MR_LD_CACHE_WRITE_BACK,
253 MR_LD_CACHE_WRITE_BACK);
254 else if (strcmp(av[2], "write-through") == 0)
255 error = update_cache_policy(fd, &props, 0,
256 MR_LD_CACHE_WRITE_BACK);
257 else if (strcmp(av[2], "read-ahead") == 0) {
259 warnx("cache: read-ahead setting required");
262 if (strcmp(av[3], "none") == 0)
264 else if (strcmp(av[3], "always") == 0)
265 policy = MR_LD_CACHE_READ_AHEAD;
266 else if (strcmp(av[3], "adaptive") == 0)
267 policy = MR_LD_CACHE_READ_AHEAD |
268 MR_LD_CACHE_READ_ADAPTIVE;
270 warnx("cache: invalid read-ahead setting");
273 error = update_cache_policy(fd, &props, policy,
274 MR_LD_CACHE_READ_AHEAD |
275 MR_LD_CACHE_READ_ADAPTIVE);
276 } else if (strcmp(av[2], "write-cache") == 0) {
278 warnx("cache: write-cache setting required");
281 if (strcmp(av[3], "enable") == 0)
282 policy = MR_PD_CACHE_ENABLE;
283 else if (strcmp(av[3], "disable") == 0)
284 policy = MR_PD_CACHE_DISABLE;
285 else if (strcmp(av[3], "default") == 0)
286 policy = MR_PD_CACHE_UNCHANGED;
288 warnx("cache: invalid write-cache setting");
292 if (policy != props.disk_cache_policy) {
294 case MR_PD_CACHE_ENABLE:
295 printf("Enabling write-cache on physical drives\n");
297 case MR_PD_CACHE_DISABLE:
298 printf("Disabling write-cache on physical drives\n");
300 case MR_PD_CACHE_UNCHANGED:
301 printf("Using default write-cache setting on physical drives\n");
304 props.disk_cache_policy = policy;
305 if (mfi_ld_set_props(fd, &props) < 0) {
307 warn("Failed to set volume properties");
311 warnx("cache: Invalid command");
319 MFI_COMMAND(top, cache, volume_cache);
322 volume_name(int ac, char **av)
324 struct mfi_ld_props props;
329 warnx("name: volume and name required");
333 if (strlen(av[2]) >= sizeof(props.name)) {
334 warnx("name: new name is too long");
338 fd = mfi_open(mfi_unit);
345 if (mfi_lookup_volume(fd, av[1], &target_id) < 0) {
347 warn("Invalid volume: %s", av[1]);
351 if (mfi_ld_get_props(fd, target_id, &props) < 0) {
353 warn("Failed to fetch volume properties");
357 printf("mfi%u volume %s name changed from \"%s\" to \"%s\"\n", mfi_unit,
358 mfi_volume_name(fd, target_id), props.name, av[2]);
359 bzero(props.name, sizeof(props.name));
360 strcpy(props.name, av[2]);
361 if (mfi_ld_set_props(fd, &props) < 0) {
363 warn("Failed to set volume properties");
371 MFI_COMMAND(top, name, volume_name);
374 volume_progress(int ac, char **av)
376 struct mfi_ld_info info;
381 warnx("volume progress: %s", ac > 2 ? "extra arguments" :
386 fd = mfi_open(mfi_unit);
393 if (mfi_lookup_volume(fd, av[1], &target_id) < 0) {
395 warn("Invalid volume: %s", av[1]);
399 /* Get the info for this drive. */
400 if (mfi_ld_get_info(fd, target_id, &info, NULL) < 0) {
402 warn("Failed to fetch info for volume %s",
403 mfi_volume_name(fd, target_id));
407 /* Display any of the active events. */
408 if (info.progress.active & MFI_LD_PROGRESS_CC)
409 mfi_display_progress("Consistency Check", &info.progress.cc);
410 if (info.progress.active & MFI_LD_PROGRESS_BGI)
411 mfi_display_progress("Background Init", &info.progress.bgi);
412 if (info.progress.active & MFI_LD_PROGRESS_FGI)
413 mfi_display_progress("Foreground Init", &info.progress.fgi);
414 if (info.progress.active & MFI_LD_PROGRESS_RECON)
415 mfi_display_progress("Reconstruction", &info.progress.recon);
416 if ((info.progress.active & (MFI_LD_PROGRESS_CC | MFI_LD_PROGRESS_BGI |
417 MFI_LD_PROGRESS_FGI | MFI_LD_PROGRESS_RECON)) == 0)
418 printf("No activity in progress for volume %s.\n",
419 mfi_volume_name(fd, target_id));
424 MFI_COMMAND(volume, progress, volume_progress);