1763fae79SScott Long /*-
21de7b4b8SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause
31de7b4b8SPedro F. Giffuni *
4763fae79SScott Long * Copyright (c) 2008, 2009 Yahoo!, Inc.
5763fae79SScott Long * All rights reserved.
6763fae79SScott Long *
7763fae79SScott Long * Redistribution and use in source and binary forms, with or without
8763fae79SScott Long * modification, are permitted provided that the following conditions
9763fae79SScott Long * are met:
10763fae79SScott Long * 1. Redistributions of source code must retain the above copyright
11763fae79SScott Long * notice, this list of conditions and the following disclaimer.
12763fae79SScott Long * 2. Redistributions in binary form must reproduce the above copyright
13763fae79SScott Long * notice, this list of conditions and the following disclaimer in the
14763fae79SScott Long * documentation and/or other materials provided with the distribution.
15763fae79SScott Long * 3. The names of the authors may not be used to endorse or promote
16763fae79SScott Long * products derived from this software without specific prior written
17763fae79SScott Long * permission.
18763fae79SScott Long *
19763fae79SScott Long * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20763fae79SScott Long * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21763fae79SScott Long * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22763fae79SScott Long * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23763fae79SScott Long * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24763fae79SScott Long * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25763fae79SScott Long * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26763fae79SScott Long * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27763fae79SScott Long * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28763fae79SScott Long * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29763fae79SScott Long * SUCH DAMAGE.
30763fae79SScott Long */
31763fae79SScott Long
32763fae79SScott Long #include <sys/types.h>
33763fae79SScott Long #include <sys/errno.h>
34763fae79SScott Long #include <err.h>
35bf4ec4dfSEitan Adler #include <fcntl.h>
36763fae79SScott Long #include <libutil.h>
37763fae79SScott Long #include <stdio.h>
38763fae79SScott Long #include <stdlib.h>
39763fae79SScott Long #include <string.h>
40763fae79SScott Long #include <unistd.h>
41763fae79SScott Long #include "mfiutil.h"
42763fae79SScott Long
43763fae79SScott Long MFI_TABLE(top, volume);
44763fae79SScott Long
45763fae79SScott Long const char *
mfi_ldstate(enum mfi_ld_state state)46763fae79SScott Long mfi_ldstate(enum mfi_ld_state state)
47763fae79SScott Long {
48763fae79SScott Long static char buf[16];
49763fae79SScott Long
50763fae79SScott Long switch (state) {
51763fae79SScott Long case MFI_LD_STATE_OFFLINE:
52763fae79SScott Long return ("OFFLINE");
53763fae79SScott Long case MFI_LD_STATE_PARTIALLY_DEGRADED:
54763fae79SScott Long return ("PARTIALLY DEGRADED");
55763fae79SScott Long case MFI_LD_STATE_DEGRADED:
56763fae79SScott Long return ("DEGRADED");
57763fae79SScott Long case MFI_LD_STATE_OPTIMAL:
58763fae79SScott Long return ("OPTIMAL");
59763fae79SScott Long default:
60763fae79SScott Long sprintf(buf, "LSTATE 0x%02x", state);
61763fae79SScott Long return (buf);
62763fae79SScott Long }
63763fae79SScott Long }
64763fae79SScott Long
65763fae79SScott Long void
mbox_store_ldref(uint8_t * mbox,union mfi_ld_ref * ref)66763fae79SScott Long mbox_store_ldref(uint8_t *mbox, union mfi_ld_ref *ref)
67763fae79SScott Long {
68763fae79SScott Long
69763fae79SScott Long mbox[0] = ref->v.target_id;
70763fae79SScott Long mbox[1] = ref->v.reserved;
71763fae79SScott Long mbox[2] = ref->v.seq & 0xff;
72763fae79SScott Long mbox[3] = ref->v.seq >> 8;
73763fae79SScott Long }
74763fae79SScott Long
75763fae79SScott Long int
mfi_ld_get_list(int fd,struct mfi_ld_list * list,uint8_t * statusp)76763fae79SScott Long mfi_ld_get_list(int fd, struct mfi_ld_list *list, uint8_t *statusp)
77763fae79SScott Long {
78763fae79SScott Long
79763fae79SScott Long return (mfi_dcmd_command(fd, MFI_DCMD_LD_GET_LIST, list,
80763fae79SScott Long sizeof(struct mfi_ld_list), NULL, 0, statusp));
81763fae79SScott Long }
82763fae79SScott Long
83763fae79SScott Long int
mfi_ld_get_info(int fd,uint8_t target_id,struct mfi_ld_info * info,uint8_t * statusp)84763fae79SScott Long mfi_ld_get_info(int fd, uint8_t target_id, struct mfi_ld_info *info,
85763fae79SScott Long uint8_t *statusp)
86763fae79SScott Long {
87763fae79SScott Long uint8_t mbox[1];
88763fae79SScott Long
89763fae79SScott Long mbox[0] = target_id;
90763fae79SScott Long return (mfi_dcmd_command(fd, MFI_DCMD_LD_GET_INFO, info,
91763fae79SScott Long sizeof(struct mfi_ld_info), mbox, 1, statusp));
92763fae79SScott Long }
93763fae79SScott Long
94763fae79SScott Long static int
mfi_ld_get_props(int fd,uint8_t target_id,struct mfi_ld_props * props)95763fae79SScott Long mfi_ld_get_props(int fd, uint8_t target_id, struct mfi_ld_props *props)
96763fae79SScott Long {
97763fae79SScott Long uint8_t mbox[1];
98763fae79SScott Long
99763fae79SScott Long mbox[0] = target_id;
100763fae79SScott Long return (mfi_dcmd_command(fd, MFI_DCMD_LD_GET_PROP, props,
101763fae79SScott Long sizeof(struct mfi_ld_props), mbox, 1, NULL));
102763fae79SScott Long }
103763fae79SScott Long
104763fae79SScott Long static int
mfi_ld_set_props(int fd,struct mfi_ld_props * props)105763fae79SScott Long mfi_ld_set_props(int fd, struct mfi_ld_props *props)
106763fae79SScott Long {
107763fae79SScott Long uint8_t mbox[4];
108763fae79SScott Long
109763fae79SScott Long mbox_store_ldref(mbox, &props->ld);
110763fae79SScott Long return (mfi_dcmd_command(fd, MFI_DCMD_LD_SET_PROP, props,
111763fae79SScott Long sizeof(struct mfi_ld_props), mbox, 4, NULL));
112763fae79SScott Long }
113763fae79SScott Long
114763fae79SScott Long static int
update_cache_policy(int fd,struct mfi_ld_props * old,struct mfi_ld_props * new)1152e5df98aSJohn Baldwin update_cache_policy(int fd, struct mfi_ld_props *old, struct mfi_ld_props *new)
116763fae79SScott Long {
117c02999d9SJohn Baldwin int error;
118763fae79SScott Long uint8_t changes, policy;
119763fae79SScott Long
1202e5df98aSJohn Baldwin if (old->default_cache_policy == new->default_cache_policy &&
1212e5df98aSJohn Baldwin old->disk_cache_policy == new->disk_cache_policy)
122763fae79SScott Long return (0);
1232e5df98aSJohn Baldwin policy = new->default_cache_policy;
1242e5df98aSJohn Baldwin changes = policy ^ old->default_cache_policy;
125763fae79SScott Long if (changes & MR_LD_CACHE_ALLOW_WRITE_CACHE)
126763fae79SScott Long printf("%s caching of I/O writes\n",
127763fae79SScott Long policy & MR_LD_CACHE_ALLOW_WRITE_CACHE ? "Enabling" :
128763fae79SScott Long "Disabling");
129763fae79SScott Long if (changes & MR_LD_CACHE_ALLOW_READ_CACHE)
130763fae79SScott Long printf("%s caching of I/O reads\n",
131763fae79SScott Long policy & MR_LD_CACHE_ALLOW_READ_CACHE ? "Enabling" :
132763fae79SScott Long "Disabling");
133763fae79SScott Long if (changes & MR_LD_CACHE_WRITE_BACK)
134763fae79SScott Long printf("Setting write cache policy to %s\n",
135763fae79SScott Long policy & MR_LD_CACHE_WRITE_BACK ? "write-back" :
136763fae79SScott Long "write-through");
137763fae79SScott Long if (changes & (MR_LD_CACHE_READ_AHEAD | MR_LD_CACHE_READ_ADAPTIVE))
138763fae79SScott Long printf("Setting read ahead policy to %s\n",
139763fae79SScott Long policy & MR_LD_CACHE_READ_AHEAD ?
140763fae79SScott Long (policy & MR_LD_CACHE_READ_ADAPTIVE ?
141763fae79SScott Long "adaptive" : "always") : "none");
1428b22f43dSJohn Baldwin if (changes & MR_LD_CACHE_WRITE_CACHE_BAD_BBU)
1438b22f43dSJohn Baldwin printf("%s write caching with bad BBU\n",
1448b22f43dSJohn Baldwin policy & MR_LD_CACHE_WRITE_CACHE_BAD_BBU ? "Enabling" :
1458b22f43dSJohn Baldwin "Disabling");
1462e5df98aSJohn Baldwin if (old->disk_cache_policy != new->disk_cache_policy) {
1472e5df98aSJohn Baldwin switch (new->disk_cache_policy) {
1482e5df98aSJohn Baldwin case MR_PD_CACHE_ENABLE:
1492e5df98aSJohn Baldwin printf("Enabling write-cache on physical drives\n");
1502e5df98aSJohn Baldwin break;
1512e5df98aSJohn Baldwin case MR_PD_CACHE_DISABLE:
1522e5df98aSJohn Baldwin printf("Disabling write-cache on physical drives\n");
1532e5df98aSJohn Baldwin break;
1542e5df98aSJohn Baldwin case MR_PD_CACHE_UNCHANGED:
1552e5df98aSJohn Baldwin printf("Using default write-cache setting on physical drives\n");
1562e5df98aSJohn Baldwin break;
1572e5df98aSJohn Baldwin }
1582e5df98aSJohn Baldwin }
159763fae79SScott Long
1602e5df98aSJohn Baldwin if (mfi_ld_set_props(fd, new) < 0) {
161c02999d9SJohn Baldwin error = errno;
162763fae79SScott Long warn("Failed to set volume properties");
163c02999d9SJohn Baldwin return (error);
164763fae79SScott Long }
165763fae79SScott Long return (0);
166763fae79SScott Long }
167763fae79SScott Long
1682e5df98aSJohn Baldwin static void
stage_cache_setting(struct mfi_ld_props * props,uint8_t new_policy,uint8_t mask)1692e5df98aSJohn Baldwin stage_cache_setting(struct mfi_ld_props *props, uint8_t new_policy,
1702e5df98aSJohn Baldwin uint8_t mask)
1712e5df98aSJohn Baldwin {
1722e5df98aSJohn Baldwin
1732e5df98aSJohn Baldwin props->default_cache_policy &= ~mask;
1742e5df98aSJohn Baldwin props->default_cache_policy |= new_policy;
1752e5df98aSJohn Baldwin }
1762e5df98aSJohn Baldwin
1772e5df98aSJohn Baldwin /*
1782e5df98aSJohn Baldwin * Parse a single cache directive modifying the passed in policy.
1792e5df98aSJohn Baldwin * Returns -1 on a parse error and the number of arguments consumed
1802e5df98aSJohn Baldwin * on success.
1812e5df98aSJohn Baldwin */
1822e5df98aSJohn Baldwin static int
process_cache_command(int ac,char ** av,struct mfi_ld_props * props)1832e5df98aSJohn Baldwin process_cache_command(int ac, char **av, struct mfi_ld_props *props)
1842e5df98aSJohn Baldwin {
1852e5df98aSJohn Baldwin uint8_t policy;
1862e5df98aSJohn Baldwin
1872e5df98aSJohn Baldwin /* I/O cache settings. */
1882e5df98aSJohn Baldwin if (strcmp(av[0], "all") == 0 || strcmp(av[0], "enable") == 0) {
1892e5df98aSJohn Baldwin stage_cache_setting(props, MR_LD_CACHE_ALLOW_READ_CACHE |
1902e5df98aSJohn Baldwin MR_LD_CACHE_ALLOW_WRITE_CACHE,
1912e5df98aSJohn Baldwin MR_LD_CACHE_ALLOW_READ_CACHE |
1922e5df98aSJohn Baldwin MR_LD_CACHE_ALLOW_WRITE_CACHE);
1932e5df98aSJohn Baldwin return (1);
1942e5df98aSJohn Baldwin }
1952e5df98aSJohn Baldwin if (strcmp(av[0], "none") == 0 || strcmp(av[0], "disable") == 0) {
1962e5df98aSJohn Baldwin stage_cache_setting(props, 0, MR_LD_CACHE_ALLOW_READ_CACHE |
1972e5df98aSJohn Baldwin MR_LD_CACHE_ALLOW_WRITE_CACHE);
1982e5df98aSJohn Baldwin return (1);
1992e5df98aSJohn Baldwin }
2002e5df98aSJohn Baldwin if (strcmp(av[0], "reads") == 0) {
2012e5df98aSJohn Baldwin stage_cache_setting(props, MR_LD_CACHE_ALLOW_READ_CACHE,
2022e5df98aSJohn Baldwin MR_LD_CACHE_ALLOW_READ_CACHE |
2032e5df98aSJohn Baldwin MR_LD_CACHE_ALLOW_WRITE_CACHE);
2042e5df98aSJohn Baldwin return (1);
2052e5df98aSJohn Baldwin }
2062e5df98aSJohn Baldwin if (strcmp(av[0], "writes") == 0) {
2072e5df98aSJohn Baldwin stage_cache_setting(props, MR_LD_CACHE_ALLOW_WRITE_CACHE,
2082e5df98aSJohn Baldwin MR_LD_CACHE_ALLOW_READ_CACHE |
2092e5df98aSJohn Baldwin MR_LD_CACHE_ALLOW_WRITE_CACHE);
2102e5df98aSJohn Baldwin return (1);
2112e5df98aSJohn Baldwin }
2122e5df98aSJohn Baldwin
2132e5df98aSJohn Baldwin /* Write cache behavior. */
2142e5df98aSJohn Baldwin if (strcmp(av[0], "write-back") == 0) {
2152e5df98aSJohn Baldwin stage_cache_setting(props, MR_LD_CACHE_WRITE_BACK,
2162e5df98aSJohn Baldwin MR_LD_CACHE_WRITE_BACK);
2172e5df98aSJohn Baldwin return (1);
2182e5df98aSJohn Baldwin }
2192e5df98aSJohn Baldwin if (strcmp(av[0], "write-through") == 0) {
2202e5df98aSJohn Baldwin stage_cache_setting(props, 0, MR_LD_CACHE_WRITE_BACK);
2212e5df98aSJohn Baldwin return (1);
2222e5df98aSJohn Baldwin }
2232e5df98aSJohn Baldwin if (strcmp(av[0], "bad-bbu-write-cache") == 0) {
2242e5df98aSJohn Baldwin if (ac < 2) {
2252e5df98aSJohn Baldwin warnx("cache: bad BBU setting required");
2262e5df98aSJohn Baldwin return (-1);
2272e5df98aSJohn Baldwin }
2282e5df98aSJohn Baldwin if (strcmp(av[1], "enable") == 0)
2292e5df98aSJohn Baldwin policy = MR_LD_CACHE_WRITE_CACHE_BAD_BBU;
2302e5df98aSJohn Baldwin else if (strcmp(av[1], "disable") == 0)
2312e5df98aSJohn Baldwin policy = 0;
2322e5df98aSJohn Baldwin else {
2332e5df98aSJohn Baldwin warnx("cache: invalid bad BBU setting");
2342e5df98aSJohn Baldwin return (-1);
2352e5df98aSJohn Baldwin }
2362e5df98aSJohn Baldwin stage_cache_setting(props, policy,
2372e5df98aSJohn Baldwin MR_LD_CACHE_WRITE_CACHE_BAD_BBU);
2382e5df98aSJohn Baldwin return (2);
2392e5df98aSJohn Baldwin }
2402e5df98aSJohn Baldwin
2412e5df98aSJohn Baldwin /* Read cache behavior. */
2422e5df98aSJohn Baldwin if (strcmp(av[0], "read-ahead") == 0) {
2432e5df98aSJohn Baldwin if (ac < 2) {
2442e5df98aSJohn Baldwin warnx("cache: read-ahead setting required");
2452e5df98aSJohn Baldwin return (-1);
2462e5df98aSJohn Baldwin }
2472e5df98aSJohn Baldwin if (strcmp(av[1], "none") == 0)
2482e5df98aSJohn Baldwin policy = 0;
2492e5df98aSJohn Baldwin else if (strcmp(av[1], "always") == 0)
2502e5df98aSJohn Baldwin policy = MR_LD_CACHE_READ_AHEAD;
2512e5df98aSJohn Baldwin else if (strcmp(av[1], "adaptive") == 0)
2522e5df98aSJohn Baldwin policy = MR_LD_CACHE_READ_AHEAD |
2532e5df98aSJohn Baldwin MR_LD_CACHE_READ_ADAPTIVE;
2542e5df98aSJohn Baldwin else {
2552e5df98aSJohn Baldwin warnx("cache: invalid read-ahead setting");
2562e5df98aSJohn Baldwin return (-1);
2572e5df98aSJohn Baldwin }
2582e5df98aSJohn Baldwin stage_cache_setting(props, policy, MR_LD_CACHE_READ_AHEAD |
2592e5df98aSJohn Baldwin MR_LD_CACHE_READ_ADAPTIVE);
2602e5df98aSJohn Baldwin return (2);
2612e5df98aSJohn Baldwin }
2622e5df98aSJohn Baldwin
2632e5df98aSJohn Baldwin /* Drive write-cache behavior. */
2642e5df98aSJohn Baldwin if (strcmp(av[0], "write-cache") == 0) {
2652e5df98aSJohn Baldwin if (ac < 2) {
2662e5df98aSJohn Baldwin warnx("cache: write-cache setting required");
2672e5df98aSJohn Baldwin return (-1);
2682e5df98aSJohn Baldwin }
2692e5df98aSJohn Baldwin if (strcmp(av[1], "enable") == 0)
2702e5df98aSJohn Baldwin props->disk_cache_policy = MR_PD_CACHE_ENABLE;
2712e5df98aSJohn Baldwin else if (strcmp(av[1], "disable") == 0)
2722e5df98aSJohn Baldwin props->disk_cache_policy = MR_PD_CACHE_DISABLE;
2732e5df98aSJohn Baldwin else if (strcmp(av[1], "default") == 0)
2742e5df98aSJohn Baldwin props->disk_cache_policy = MR_PD_CACHE_UNCHANGED;
2752e5df98aSJohn Baldwin else {
2762e5df98aSJohn Baldwin warnx("cache: invalid write-cache setting");
2772e5df98aSJohn Baldwin return (-1);
2782e5df98aSJohn Baldwin }
2792e5df98aSJohn Baldwin return (2);
2802e5df98aSJohn Baldwin }
2812e5df98aSJohn Baldwin
2822e5df98aSJohn Baldwin warnx("cache: Invalid command");
2832e5df98aSJohn Baldwin return (-1);
2842e5df98aSJohn Baldwin }
2852e5df98aSJohn Baldwin
286763fae79SScott Long static int
volume_cache(int ac,char ** av)287763fae79SScott Long volume_cache(int ac, char **av)
288763fae79SScott Long {
2892e5df98aSJohn Baldwin struct mfi_ld_props props, new;
2902e5df98aSJohn Baldwin int error, fd, consumed;
2912e5df98aSJohn Baldwin uint8_t target_id;
292763fae79SScott Long
293763fae79SScott Long if (ac < 2) {
294763fae79SScott Long warnx("cache: volume required");
295763fae79SScott Long return (EINVAL);
296763fae79SScott Long }
297763fae79SScott Long
298*7e0f8b79SDoug Ambrisko fd = mfi_open(mfi_device, O_RDWR);
299763fae79SScott Long if (fd < 0) {
300c02999d9SJohn Baldwin error = errno;
301763fae79SScott Long warn("mfi_open");
302c02999d9SJohn Baldwin return (error);
303763fae79SScott Long }
304763fae79SScott Long
305763fae79SScott Long if (mfi_lookup_volume(fd, av[1], &target_id) < 0) {
306c02999d9SJohn Baldwin error = errno;
307763fae79SScott Long warn("Invalid volume: %s", av[1]);
308375c4656SBjoern A. Zeeb close(fd);
309c02999d9SJohn Baldwin return (error);
310763fae79SScott Long }
311763fae79SScott Long
312763fae79SScott Long if (mfi_ld_get_props(fd, target_id, &props) < 0) {
313c02999d9SJohn Baldwin error = errno;
314763fae79SScott Long warn("Failed to fetch volume properties");
315375c4656SBjoern A. Zeeb close(fd);
316c02999d9SJohn Baldwin return (error);
317763fae79SScott Long }
318763fae79SScott Long
319763fae79SScott Long if (ac == 2) {
320*7e0f8b79SDoug Ambrisko printf("%s volume %s cache settings:\n", mfi_device,
321763fae79SScott Long mfi_volume_name(fd, target_id));
322763fae79SScott Long printf(" I/O caching: ");
323763fae79SScott Long switch (props.default_cache_policy &
324763fae79SScott Long (MR_LD_CACHE_ALLOW_WRITE_CACHE |
325763fae79SScott Long MR_LD_CACHE_ALLOW_READ_CACHE)) {
326763fae79SScott Long case 0:
327763fae79SScott Long printf("disabled\n");
328763fae79SScott Long break;
329763fae79SScott Long case MR_LD_CACHE_ALLOW_WRITE_CACHE:
330763fae79SScott Long printf("writes\n");
331763fae79SScott Long break;
332763fae79SScott Long case MR_LD_CACHE_ALLOW_READ_CACHE:
333763fae79SScott Long printf("reads\n");
334763fae79SScott Long break;
335763fae79SScott Long case MR_LD_CACHE_ALLOW_WRITE_CACHE |
336763fae79SScott Long MR_LD_CACHE_ALLOW_READ_CACHE:
337763fae79SScott Long printf("writes and reads\n");
338763fae79SScott Long break;
339763fae79SScott Long }
340763fae79SScott Long printf(" write caching: %s\n",
341763fae79SScott Long props.default_cache_policy & MR_LD_CACHE_WRITE_BACK ?
342763fae79SScott Long "write-back" : "write-through");
3438b22f43dSJohn Baldwin printf("write cache with bad BBU: %s\n",
3448b22f43dSJohn Baldwin props.default_cache_policy &
3458b22f43dSJohn Baldwin MR_LD_CACHE_WRITE_CACHE_BAD_BBU ? "enabled" : "disabled");
346763fae79SScott Long printf(" read ahead: %s\n",
347763fae79SScott Long props.default_cache_policy & MR_LD_CACHE_READ_AHEAD ?
348763fae79SScott Long (props.default_cache_policy & MR_LD_CACHE_READ_ADAPTIVE ?
349763fae79SScott Long "adaptive" : "always") : "none");
350763fae79SScott Long printf(" drive write cache: ");
351763fae79SScott Long switch (props.disk_cache_policy) {
352763fae79SScott Long case MR_PD_CACHE_UNCHANGED:
353763fae79SScott Long printf("default\n");
354763fae79SScott Long break;
355763fae79SScott Long case MR_PD_CACHE_ENABLE:
356763fae79SScott Long printf("enabled\n");
357763fae79SScott Long break;
358763fae79SScott Long case MR_PD_CACHE_DISABLE:
359763fae79SScott Long printf("disabled\n");
360763fae79SScott Long break;
361763fae79SScott Long default:
362763fae79SScott Long printf("??? %d\n", props.disk_cache_policy);
363763fae79SScott Long break;
364763fae79SScott Long }
365763fae79SScott Long if (props.default_cache_policy != props.current_cache_policy)
366dee3e845SMark Johnston printf(
367dee3e845SMark Johnston "Cache disabled due to dead battery or ongoing battery relearn\n");
368763fae79SScott Long error = 0;
369763fae79SScott Long } else {
3702e5df98aSJohn Baldwin new = props;
3712e5df98aSJohn Baldwin av += 2;
3722e5df98aSJohn Baldwin ac -= 2;
3732e5df98aSJohn Baldwin while (ac > 0) {
3742e5df98aSJohn Baldwin consumed = process_cache_command(ac, av, &new);
3752e5df98aSJohn Baldwin if (consumed < 0) {
376375c4656SBjoern A. Zeeb close(fd);
377763fae79SScott Long return (EINVAL);
378763fae79SScott Long }
3792e5df98aSJohn Baldwin av += consumed;
3802e5df98aSJohn Baldwin ac -= consumed;
381763fae79SScott Long }
3822e5df98aSJohn Baldwin error = update_cache_policy(fd, &props, &new);
383763fae79SScott Long }
384763fae79SScott Long close(fd);
385763fae79SScott Long
386763fae79SScott Long return (error);
387763fae79SScott Long }
388763fae79SScott Long MFI_COMMAND(top, cache, volume_cache);
389763fae79SScott Long
390763fae79SScott Long static int
volume_name(int ac,char ** av)391763fae79SScott Long volume_name(int ac, char **av)
392763fae79SScott Long {
393763fae79SScott Long struct mfi_ld_props props;
394c02999d9SJohn Baldwin int error, fd;
395763fae79SScott Long uint8_t target_id;
396763fae79SScott Long
397763fae79SScott Long if (ac != 3) {
398763fae79SScott Long warnx("name: volume and name required");
399763fae79SScott Long return (EINVAL);
400763fae79SScott Long }
401763fae79SScott Long
402763fae79SScott Long if (strlen(av[2]) >= sizeof(props.name)) {
403763fae79SScott Long warnx("name: new name is too long");
404763fae79SScott Long return (ENOSPC);
405763fae79SScott Long }
406763fae79SScott Long
407*7e0f8b79SDoug Ambrisko fd = mfi_open(mfi_device, O_RDWR);
408763fae79SScott Long if (fd < 0) {
409c02999d9SJohn Baldwin error = errno;
410763fae79SScott Long warn("mfi_open");
411c02999d9SJohn Baldwin return (error);
412763fae79SScott Long }
413763fae79SScott Long
414763fae79SScott Long if (mfi_lookup_volume(fd, av[1], &target_id) < 0) {
415c02999d9SJohn Baldwin error = errno;
416763fae79SScott Long warn("Invalid volume: %s", av[1]);
417375c4656SBjoern A. Zeeb close(fd);
418c02999d9SJohn Baldwin return (error);
419763fae79SScott Long }
420763fae79SScott Long
421763fae79SScott Long if (mfi_ld_get_props(fd, target_id, &props) < 0) {
422c02999d9SJohn Baldwin error = errno;
423763fae79SScott Long warn("Failed to fetch volume properties");
424375c4656SBjoern A. Zeeb close(fd);
425c02999d9SJohn Baldwin return (error);
426763fae79SScott Long }
427763fae79SScott Long
428*7e0f8b79SDoug Ambrisko printf("%s volume %s name changed from \"%s\" to \"%s\"\n", mfi_device,
429763fae79SScott Long mfi_volume_name(fd, target_id), props.name, av[2]);
430763fae79SScott Long bzero(props.name, sizeof(props.name));
431763fae79SScott Long strcpy(props.name, av[2]);
432763fae79SScott Long if (mfi_ld_set_props(fd, &props) < 0) {
433c02999d9SJohn Baldwin error = errno;
434763fae79SScott Long warn("Failed to set volume properties");
435375c4656SBjoern A. Zeeb close(fd);
436c02999d9SJohn Baldwin return (error);
437763fae79SScott Long }
438763fae79SScott Long
439763fae79SScott Long close(fd);
440763fae79SScott Long
441763fae79SScott Long return (0);
442763fae79SScott Long }
443763fae79SScott Long MFI_COMMAND(top, name, volume_name);
444763fae79SScott Long
445763fae79SScott Long static int
volume_progress(int ac,char ** av)446763fae79SScott Long volume_progress(int ac, char **av)
447763fae79SScott Long {
448763fae79SScott Long struct mfi_ld_info info;
449c02999d9SJohn Baldwin int error, fd;
450763fae79SScott Long uint8_t target_id;
451763fae79SScott Long
452763fae79SScott Long if (ac != 2) {
453763fae79SScott Long warnx("volume progress: %s", ac > 2 ? "extra arguments" :
454763fae79SScott Long "volume required");
455763fae79SScott Long return (EINVAL);
456763fae79SScott Long }
457763fae79SScott Long
458*7e0f8b79SDoug Ambrisko fd = mfi_open(mfi_device, O_RDONLY);
459763fae79SScott Long if (fd < 0) {
460c02999d9SJohn Baldwin error = errno;
461763fae79SScott Long warn("mfi_open");
462c02999d9SJohn Baldwin return (error);
463763fae79SScott Long }
464763fae79SScott Long
465763fae79SScott Long if (mfi_lookup_volume(fd, av[1], &target_id) < 0) {
466c02999d9SJohn Baldwin error = errno;
467763fae79SScott Long warn("Invalid volume: %s", av[1]);
468375c4656SBjoern A. Zeeb close(fd);
469c02999d9SJohn Baldwin return (error);
470763fae79SScott Long }
471763fae79SScott Long
472763fae79SScott Long /* Get the info for this drive. */
473763fae79SScott Long if (mfi_ld_get_info(fd, target_id, &info, NULL) < 0) {
474c02999d9SJohn Baldwin error = errno;
475763fae79SScott Long warn("Failed to fetch info for volume %s",
476763fae79SScott Long mfi_volume_name(fd, target_id));
477375c4656SBjoern A. Zeeb close(fd);
478c02999d9SJohn Baldwin return (error);
479763fae79SScott Long }
480763fae79SScott Long
481763fae79SScott Long /* Display any of the active events. */
482763fae79SScott Long if (info.progress.active & MFI_LD_PROGRESS_CC)
483763fae79SScott Long mfi_display_progress("Consistency Check", &info.progress.cc);
484763fae79SScott Long if (info.progress.active & MFI_LD_PROGRESS_BGI)
485763fae79SScott Long mfi_display_progress("Background Init", &info.progress.bgi);
486763fae79SScott Long if (info.progress.active & MFI_LD_PROGRESS_FGI)
487763fae79SScott Long mfi_display_progress("Foreground Init", &info.progress.fgi);
488763fae79SScott Long if (info.progress.active & MFI_LD_PROGRESS_RECON)
489763fae79SScott Long mfi_display_progress("Reconstruction", &info.progress.recon);
490763fae79SScott Long if ((info.progress.active & (MFI_LD_PROGRESS_CC | MFI_LD_PROGRESS_BGI |
491763fae79SScott Long MFI_LD_PROGRESS_FGI | MFI_LD_PROGRESS_RECON)) == 0)
492763fae79SScott Long printf("No activity in progress for volume %s.\n",
493763fae79SScott Long mfi_volume_name(fd, target_id));
494763fae79SScott Long close(fd);
495763fae79SScott Long
496763fae79SScott Long return (0);
497763fae79SScott Long }
498763fae79SScott Long MFI_COMMAND(volume, progress, volume_progress);
499