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,
117 uint8_t changes, policy;
119 policy = (props->default_cache_policy & ~mask) | new_policy;
120 if (policy == props->default_cache_policy)
122 changes = policy ^ props->default_cache_policy;
123 if (changes & MR_LD_CACHE_ALLOW_WRITE_CACHE)
124 printf("%s caching of I/O writes\n",
125 policy & MR_LD_CACHE_ALLOW_WRITE_CACHE ? "Enabling" :
127 if (changes & MR_LD_CACHE_ALLOW_READ_CACHE)
128 printf("%s caching of I/O reads\n",
129 policy & MR_LD_CACHE_ALLOW_READ_CACHE ? "Enabling" :
131 if (changes & MR_LD_CACHE_WRITE_BACK)
132 printf("Setting write cache policy to %s\n",
133 policy & MR_LD_CACHE_WRITE_BACK ? "write-back" :
135 if (changes & (MR_LD_CACHE_READ_AHEAD | MR_LD_CACHE_READ_ADAPTIVE))
136 printf("Setting read ahead policy to %s\n",
137 policy & MR_LD_CACHE_READ_AHEAD ?
138 (policy & MR_LD_CACHE_READ_ADAPTIVE ?
139 "adaptive" : "always") : "none");
141 props->default_cache_policy = policy;
142 if (mfi_ld_set_props(fd, props) < 0) {
143 warn("Failed to set volume properties");
150 volume_cache(int ac, char **av)
152 struct mfi_ld_props props;
154 uint8_t target_id, policy;
157 warnx("cache: volume required");
161 fd = mfi_open(mfi_unit);
167 if (mfi_lookup_volume(fd, av[1], &target_id) < 0) {
168 warn("Invalid volume: %s", av[1]);
172 if (mfi_ld_get_props(fd, target_id, &props) < 0) {
173 warn("Failed to fetch volume properties");
178 printf("mfi%u volume %s cache settings:\n", mfi_unit,
179 mfi_volume_name(fd, target_id));
180 printf(" I/O caching: ");
181 switch (props.default_cache_policy &
182 (MR_LD_CACHE_ALLOW_WRITE_CACHE |
183 MR_LD_CACHE_ALLOW_READ_CACHE)) {
185 printf("disabled\n");
187 case MR_LD_CACHE_ALLOW_WRITE_CACHE:
190 case MR_LD_CACHE_ALLOW_READ_CACHE:
193 case MR_LD_CACHE_ALLOW_WRITE_CACHE |
194 MR_LD_CACHE_ALLOW_READ_CACHE:
195 printf("writes and reads\n");
198 printf(" write caching: %s\n",
199 props.default_cache_policy & MR_LD_CACHE_WRITE_BACK ?
200 "write-back" : "write-through");
201 printf(" read ahead: %s\n",
202 props.default_cache_policy & MR_LD_CACHE_READ_AHEAD ?
203 (props.default_cache_policy & MR_LD_CACHE_READ_ADAPTIVE ?
204 "adaptive" : "always") : "none");
205 printf("drive write cache: ");
206 switch (props.disk_cache_policy) {
207 case MR_PD_CACHE_UNCHANGED:
210 case MR_PD_CACHE_ENABLE:
213 case MR_PD_CACHE_DISABLE:
214 printf("disabled\n");
217 printf("??? %d\n", props.disk_cache_policy);
220 if (props.default_cache_policy != props.current_cache_policy)
221 printf("Cache Disabled Due to Dead Battery\n");
224 if (strcmp(av[2], "all") == 0 || strcmp(av[2], "enable") == 0)
225 error = update_cache_policy(fd, &props,
226 MR_LD_CACHE_ALLOW_READ_CACHE |
227 MR_LD_CACHE_ALLOW_WRITE_CACHE,
228 MR_LD_CACHE_ALLOW_READ_CACHE |
229 MR_LD_CACHE_ALLOW_WRITE_CACHE);
230 else if (strcmp(av[2], "none") == 0 ||
231 strcmp(av[2], "disable") == 0)
232 error = update_cache_policy(fd, &props, 0,
233 MR_LD_CACHE_ALLOW_READ_CACHE |
234 MR_LD_CACHE_ALLOW_WRITE_CACHE);
235 else if (strcmp(av[2], "reads") == 0)
236 error = update_cache_policy(fd, &props,
237 MR_LD_CACHE_ALLOW_READ_CACHE,
238 MR_LD_CACHE_ALLOW_READ_CACHE |
239 MR_LD_CACHE_ALLOW_WRITE_CACHE);
240 else if (strcmp(av[2], "writes") == 0)
241 error = update_cache_policy(fd, &props,
242 MR_LD_CACHE_ALLOW_WRITE_CACHE,
243 MR_LD_CACHE_ALLOW_READ_CACHE |
244 MR_LD_CACHE_ALLOW_WRITE_CACHE);
245 else if (strcmp(av[2], "write-back") == 0)
246 error = update_cache_policy(fd, &props,
247 MR_LD_CACHE_WRITE_BACK,
248 MR_LD_CACHE_WRITE_BACK);
249 else if (strcmp(av[2], "write-through") == 0)
250 error = update_cache_policy(fd, &props, 0,
251 MR_LD_CACHE_WRITE_BACK);
252 else if (strcmp(av[2], "read-ahead") == 0) {
254 warnx("cache: read-ahead setting required");
257 if (strcmp(av[3], "none") == 0)
259 else if (strcmp(av[3], "always") == 0)
260 policy = MR_LD_CACHE_READ_AHEAD;
261 else if (strcmp(av[3], "adaptive") == 0)
262 policy = MR_LD_CACHE_READ_AHEAD |
263 MR_LD_CACHE_READ_ADAPTIVE;
265 warnx("cache: invalid read-ahead setting");
268 error = update_cache_policy(fd, &props, policy,
269 MR_LD_CACHE_READ_AHEAD |
270 MR_LD_CACHE_READ_ADAPTIVE);
271 } else if (strcmp(av[2], "write-cache") == 0) {
273 warnx("cache: write-cache setting required");
276 if (strcmp(av[3], "enable") == 0)
277 policy = MR_PD_CACHE_ENABLE;
278 else if (strcmp(av[3], "disable") == 0)
279 policy = MR_PD_CACHE_DISABLE;
280 else if (strcmp(av[3], "default") == 0)
281 policy = MR_PD_CACHE_UNCHANGED;
283 warnx("cache: invalid write-cache setting");
287 if (policy != props.disk_cache_policy) {
289 case MR_PD_CACHE_ENABLE:
290 printf("Enabling write-cache on physical drives\n");
292 case MR_PD_CACHE_DISABLE:
293 printf("Disabling write-cache on physical drives\n");
295 case MR_PD_CACHE_UNCHANGED:
296 printf("Using default write-cache setting on physical drives\n");
299 props.disk_cache_policy = policy;
300 if (mfi_ld_set_props(fd, &props) < 0) {
301 warn("Failed to set volume properties");
306 warnx("cache: Invalid command");
314 MFI_COMMAND(top, cache, volume_cache);
317 volume_name(int ac, char **av)
319 struct mfi_ld_props props;
324 warnx("name: volume and name required");
328 if (strlen(av[2]) >= sizeof(props.name)) {
329 warnx("name: new name is too long");
333 fd = mfi_open(mfi_unit);
339 if (mfi_lookup_volume(fd, av[1], &target_id) < 0) {
340 warn("Invalid volume: %s", av[1]);
344 if (mfi_ld_get_props(fd, target_id, &props) < 0) {
345 warn("Failed to fetch volume properties");
349 printf("mfi%u volume %s name changed from \"%s\" to \"%s\"\n", mfi_unit,
350 mfi_volume_name(fd, target_id), props.name, av[2]);
351 bzero(props.name, sizeof(props.name));
352 strcpy(props.name, av[2]);
353 if (mfi_ld_set_props(fd, &props) < 0) {
354 warn("Failed to set volume properties");
362 MFI_COMMAND(top, name, volume_name);
365 volume_progress(int ac, char **av)
367 struct mfi_ld_info info;
372 warnx("volume progress: %s", ac > 2 ? "extra arguments" :
377 fd = mfi_open(mfi_unit);
383 if (mfi_lookup_volume(fd, av[1], &target_id) < 0) {
384 warn("Invalid volume: %s", av[1]);
388 /* Get the info for this drive. */
389 if (mfi_ld_get_info(fd, target_id, &info, NULL) < 0) {
390 warn("Failed to fetch info for volume %s",
391 mfi_volume_name(fd, target_id));
395 /* Display any of the active events. */
396 if (info.progress.active & MFI_LD_PROGRESS_CC)
397 mfi_display_progress("Consistency Check", &info.progress.cc);
398 if (info.progress.active & MFI_LD_PROGRESS_BGI)
399 mfi_display_progress("Background Init", &info.progress.bgi);
400 if (info.progress.active & MFI_LD_PROGRESS_FGI)
401 mfi_display_progress("Foreground Init", &info.progress.fgi);
402 if (info.progress.active & MFI_LD_PROGRESS_RECON)
403 mfi_display_progress("Reconstruction", &info.progress.recon);
404 if ((info.progress.active & (MFI_LD_PROGRESS_CC | MFI_LD_PROGRESS_BGI |
405 MFI_LD_PROGRESS_FGI | MFI_LD_PROGRESS_RECON)) == 0)
406 printf("No activity in progress for volume %s.\n",
407 mfi_volume_name(fd, target_id));
412 MFI_COMMAND(volume, progress, volume_progress);