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
29 * $FreeBSD: src/usr.sbin/mfiutil/mfi_volume.c,v 1.4 2011/06/09 19:52:28 bz Exp $
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");
141 if (changes & MR_LD_CACHE_WRITE_CACHE_BAD_BBU)
142 printf("%s write caching with bad BBU\n",
143 policy & MR_LD_CACHE_WRITE_CACHE_BAD_BBU ? "Enabling" :
146 props->default_cache_policy = policy;
147 if (mfi_ld_set_props(fd, props) < 0) {
149 warn("Failed to set volume properties");
156 volume_cache(int ac, char **av)
158 struct mfi_ld_props props;
160 uint8_t target_id, policy;
163 warnx("cache: volume required");
167 fd = mfi_open(mfi_unit);
174 if (mfi_lookup_volume(fd, av[1], &target_id) < 0) {
176 warn("Invalid volume: %s", av[1]);
181 if (mfi_ld_get_props(fd, target_id, &props) < 0) {
183 warn("Failed to fetch volume properties");
189 printf("mfi%u volume %s cache settings:\n", mfi_unit,
190 mfi_volume_name(fd, target_id));
191 printf(" I/O caching: ");
192 switch (props.default_cache_policy &
193 (MR_LD_CACHE_ALLOW_WRITE_CACHE |
194 MR_LD_CACHE_ALLOW_READ_CACHE)) {
196 printf("disabled\n");
198 case MR_LD_CACHE_ALLOW_WRITE_CACHE:
201 case MR_LD_CACHE_ALLOW_READ_CACHE:
204 case MR_LD_CACHE_ALLOW_WRITE_CACHE |
205 MR_LD_CACHE_ALLOW_READ_CACHE:
206 printf("writes and reads\n");
209 printf(" write caching: %s\n",
210 props.default_cache_policy & MR_LD_CACHE_WRITE_BACK ?
211 "write-back" : "write-through");
212 printf("write cache with bad BBU: %s\n",
213 props.default_cache_policy &
214 MR_LD_CACHE_WRITE_CACHE_BAD_BBU ? "enabled" : "disabled");
215 printf(" read ahead: %s\n",
216 props.default_cache_policy & MR_LD_CACHE_READ_AHEAD ?
217 (props.default_cache_policy & MR_LD_CACHE_READ_ADAPTIVE ?
218 "adaptive" : "always") : "none");
219 printf(" drive write cache: ");
220 switch (props.disk_cache_policy) {
221 case MR_PD_CACHE_UNCHANGED:
224 case MR_PD_CACHE_ENABLE:
227 case MR_PD_CACHE_DISABLE:
228 printf("disabled\n");
231 printf("??? %d\n", props.disk_cache_policy);
234 if (props.default_cache_policy != props.current_cache_policy)
235 printf("Cache Disabled Due to Dead Battery\n");
238 if (strcmp(av[2], "all") == 0 || strcmp(av[2], "enable") == 0)
239 error = update_cache_policy(fd, &props,
240 MR_LD_CACHE_ALLOW_READ_CACHE |
241 MR_LD_CACHE_ALLOW_WRITE_CACHE,
242 MR_LD_CACHE_ALLOW_READ_CACHE |
243 MR_LD_CACHE_ALLOW_WRITE_CACHE);
244 else if (strcmp(av[2], "none") == 0 ||
245 strcmp(av[2], "disable") == 0)
246 error = update_cache_policy(fd, &props, 0,
247 MR_LD_CACHE_ALLOW_READ_CACHE |
248 MR_LD_CACHE_ALLOW_WRITE_CACHE);
249 else if (strcmp(av[2], "reads") == 0)
250 error = update_cache_policy(fd, &props,
251 MR_LD_CACHE_ALLOW_READ_CACHE,
252 MR_LD_CACHE_ALLOW_READ_CACHE |
253 MR_LD_CACHE_ALLOW_WRITE_CACHE);
254 else if (strcmp(av[2], "writes") == 0)
255 error = update_cache_policy(fd, &props,
256 MR_LD_CACHE_ALLOW_WRITE_CACHE,
257 MR_LD_CACHE_ALLOW_READ_CACHE |
258 MR_LD_CACHE_ALLOW_WRITE_CACHE);
259 else if (strcmp(av[2], "write-back") == 0)
260 error = update_cache_policy(fd, &props,
261 MR_LD_CACHE_WRITE_BACK,
262 MR_LD_CACHE_WRITE_BACK);
263 else if (strcmp(av[2], "write-through") == 0)
264 error = update_cache_policy(fd, &props, 0,
265 MR_LD_CACHE_WRITE_BACK);
266 else if (strcmp(av[2], "read-ahead") == 0) {
268 warnx("cache: read-ahead setting required");
272 if (strcmp(av[3], "none") == 0)
274 else if (strcmp(av[3], "always") == 0)
275 policy = MR_LD_CACHE_READ_AHEAD;
276 else if (strcmp(av[3], "adaptive") == 0)
277 policy = MR_LD_CACHE_READ_AHEAD |
278 MR_LD_CACHE_READ_ADAPTIVE;
280 warnx("cache: invalid read-ahead setting");
284 error = update_cache_policy(fd, &props, policy,
285 MR_LD_CACHE_READ_AHEAD |
286 MR_LD_CACHE_READ_ADAPTIVE);
287 } else if (strcmp(av[2], "bad-bbu-write-cache") == 0) {
289 warnx("cache: bad BBU setting required");
293 if (strcmp(av[3], "enable") == 0)
294 policy = MR_LD_CACHE_WRITE_CACHE_BAD_BBU;
295 else if (strcmp(av[3], "disable") == 0)
298 warnx("cache: invalid bad BBU setting");
302 error = update_cache_policy(fd, &props, policy,
303 MR_LD_CACHE_WRITE_CACHE_BAD_BBU);
304 } else if (strcmp(av[2], "write-cache") == 0) {
306 warnx("cache: write-cache setting required");
310 if (strcmp(av[3], "enable") == 0)
311 policy = MR_PD_CACHE_ENABLE;
312 else if (strcmp(av[3], "disable") == 0)
313 policy = MR_PD_CACHE_DISABLE;
314 else if (strcmp(av[3], "default") == 0)
315 policy = MR_PD_CACHE_UNCHANGED;
317 warnx("cache: invalid write-cache setting");
322 if (policy != props.disk_cache_policy) {
324 case MR_PD_CACHE_ENABLE:
325 printf("Enabling write-cache on physical drives\n");
327 case MR_PD_CACHE_DISABLE:
328 printf("Disabling write-cache on physical drives\n");
330 case MR_PD_CACHE_UNCHANGED:
331 printf("Using default write-cache setting on physical drives\n");
334 props.disk_cache_policy = policy;
335 if (mfi_ld_set_props(fd, &props) < 0) {
337 warn("Failed to set volume properties");
341 warnx("cache: Invalid command");
350 MFI_COMMAND(top, cache, volume_cache);
353 volume_name(int ac, char **av)
355 struct mfi_ld_props props;
360 warnx("name: volume and name required");
364 if (strlen(av[2]) >= sizeof(props.name)) {
365 warnx("name: new name is too long");
369 fd = mfi_open(mfi_unit);
376 if (mfi_lookup_volume(fd, av[1], &target_id) < 0) {
378 warn("Invalid volume: %s", av[1]);
383 if (mfi_ld_get_props(fd, target_id, &props) < 0) {
385 warn("Failed to fetch volume properties");
390 printf("mfi%u volume %s name changed from \"%s\" to \"%s\"\n", mfi_unit,
391 mfi_volume_name(fd, target_id), props.name, av[2]);
392 bzero(props.name, sizeof(props.name));
393 strcpy(props.name, av[2]);
394 if (mfi_ld_set_props(fd, &props) < 0) {
396 warn("Failed to set volume properties");
405 MFI_COMMAND(top, name, volume_name);
408 volume_progress(int ac, char **av)
410 struct mfi_ld_info info;
415 warnx("volume progress: %s", ac > 2 ? "extra arguments" :
420 fd = mfi_open(mfi_unit);
427 if (mfi_lookup_volume(fd, av[1], &target_id) < 0) {
429 warn("Invalid volume: %s", av[1]);
434 /* Get the info for this drive. */
435 if (mfi_ld_get_info(fd, target_id, &info, NULL) < 0) {
437 warn("Failed to fetch info for volume %s",
438 mfi_volume_name(fd, target_id));
443 /* Display any of the active events. */
444 if (info.progress.active & MFI_LD_PROGRESS_CC)
445 mfi_display_progress("Consistency Check", &info.progress.cc);
446 if (info.progress.active & MFI_LD_PROGRESS_BGI)
447 mfi_display_progress("Background Init", &info.progress.bgi);
448 if (info.progress.active & MFI_LD_PROGRESS_FGI)
449 mfi_display_progress("Foreground Init", &info.progress.fgi);
450 if (info.progress.active & MFI_LD_PROGRESS_RECON)
451 mfi_display_progress("Reconstruction", &info.progress.recon);
452 if ((info.progress.active & (MFI_LD_PROGRESS_CC | MFI_LD_PROGRESS_BGI |
453 MFI_LD_PROGRESS_FGI | MFI_LD_PROGRESS_RECON)) == 0)
454 printf("No activity in progress for volume %s.\n",
455 mfi_volume_name(fd, target_id));
460 MFI_COMMAND(volume, progress, volume_progress);