1249d29c8SSascha Wildner /*-
2249d29c8SSascha Wildner * Copyright (c) 2008, 2009 Yahoo!, Inc.
3249d29c8SSascha Wildner * All rights reserved.
4249d29c8SSascha Wildner *
5249d29c8SSascha Wildner * Redistribution and use in source and binary forms, with or without
6249d29c8SSascha Wildner * modification, are permitted provided that the following conditions
7249d29c8SSascha Wildner * are met:
8249d29c8SSascha Wildner * 1. Redistributions of source code must retain the above copyright
9249d29c8SSascha Wildner * notice, this list of conditions and the following disclaimer.
10249d29c8SSascha Wildner * 2. Redistributions in binary form must reproduce the above copyright
11249d29c8SSascha Wildner * notice, this list of conditions and the following disclaimer in the
12249d29c8SSascha Wildner * documentation and/or other materials provided with the distribution.
13249d29c8SSascha Wildner * 3. The names of the authors may not be used to endorse or promote
14249d29c8SSascha Wildner * products derived from this software without specific prior written
15249d29c8SSascha Wildner * permission.
16249d29c8SSascha Wildner *
17249d29c8SSascha Wildner * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18249d29c8SSascha Wildner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19249d29c8SSascha Wildner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20249d29c8SSascha Wildner * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21249d29c8SSascha Wildner * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22249d29c8SSascha Wildner * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23249d29c8SSascha Wildner * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24249d29c8SSascha Wildner * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25249d29c8SSascha Wildner * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26249d29c8SSascha Wildner * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27249d29c8SSascha Wildner * SUCH DAMAGE.
28249d29c8SSascha Wildner *
29*f0d8b1f2SSascha Wildner * $FreeBSD: src/usr.sbin/mfiutil/mfi_volume.c,v 1.5 2011/09/02 16:00:51 jhb Exp $
30249d29c8SSascha Wildner */
31249d29c8SSascha Wildner
32249d29c8SSascha Wildner #include <sys/types.h>
33249d29c8SSascha Wildner #include <sys/errno.h>
34249d29c8SSascha Wildner #include <err.h>
35249d29c8SSascha Wildner #include <libutil.h>
36249d29c8SSascha Wildner #include <stdio.h>
37249d29c8SSascha Wildner #include <stdlib.h>
38249d29c8SSascha Wildner #include <string.h>
39249d29c8SSascha Wildner #include <unistd.h>
40249d29c8SSascha Wildner #include "mfiutil.h"
41249d29c8SSascha Wildner
42249d29c8SSascha Wildner MFI_TABLE(top, volume);
43249d29c8SSascha Wildner
44249d29c8SSascha Wildner const char *
mfi_ldstate(enum mfi_ld_state state)45249d29c8SSascha Wildner mfi_ldstate(enum mfi_ld_state state)
46249d29c8SSascha Wildner {
47249d29c8SSascha Wildner static char buf[16];
48249d29c8SSascha Wildner
49249d29c8SSascha Wildner switch (state) {
50249d29c8SSascha Wildner case MFI_LD_STATE_OFFLINE:
51249d29c8SSascha Wildner return ("OFFLINE");
52249d29c8SSascha Wildner case MFI_LD_STATE_PARTIALLY_DEGRADED:
53249d29c8SSascha Wildner return ("PARTIALLY DEGRADED");
54249d29c8SSascha Wildner case MFI_LD_STATE_DEGRADED:
55249d29c8SSascha Wildner return ("DEGRADED");
56249d29c8SSascha Wildner case MFI_LD_STATE_OPTIMAL:
57249d29c8SSascha Wildner return ("OPTIMAL");
58249d29c8SSascha Wildner default:
59249d29c8SSascha Wildner sprintf(buf, "LSTATE 0x%02x", state);
60249d29c8SSascha Wildner return (buf);
61249d29c8SSascha Wildner }
62249d29c8SSascha Wildner }
63249d29c8SSascha Wildner
64249d29c8SSascha Wildner void
mbox_store_ldref(uint8_t * mbox,union mfi_ld_ref * ref)65249d29c8SSascha Wildner mbox_store_ldref(uint8_t *mbox, union mfi_ld_ref *ref)
66249d29c8SSascha Wildner {
67249d29c8SSascha Wildner
68249d29c8SSascha Wildner mbox[0] = ref->v.target_id;
69249d29c8SSascha Wildner mbox[1] = ref->v.reserved;
70249d29c8SSascha Wildner mbox[2] = ref->v.seq & 0xff;
71249d29c8SSascha Wildner mbox[3] = ref->v.seq >> 8;
72249d29c8SSascha Wildner }
73249d29c8SSascha Wildner
74249d29c8SSascha Wildner int
mfi_ld_get_list(int fd,struct mfi_ld_list * list,uint8_t * statusp)75249d29c8SSascha Wildner mfi_ld_get_list(int fd, struct mfi_ld_list *list, uint8_t *statusp)
76249d29c8SSascha Wildner {
77249d29c8SSascha Wildner
78249d29c8SSascha Wildner return (mfi_dcmd_command(fd, MFI_DCMD_LD_GET_LIST, list,
79249d29c8SSascha Wildner sizeof(struct mfi_ld_list), NULL, 0, statusp));
80249d29c8SSascha Wildner }
81249d29c8SSascha Wildner
82249d29c8SSascha Wildner int
mfi_ld_get_info(int fd,uint8_t target_id,struct mfi_ld_info * info,uint8_t * statusp)83249d29c8SSascha Wildner mfi_ld_get_info(int fd, uint8_t target_id, struct mfi_ld_info *info,
84249d29c8SSascha Wildner uint8_t *statusp)
85249d29c8SSascha Wildner {
86249d29c8SSascha Wildner uint8_t mbox[1];
87249d29c8SSascha Wildner
88249d29c8SSascha Wildner mbox[0] = target_id;
89249d29c8SSascha Wildner return (mfi_dcmd_command(fd, MFI_DCMD_LD_GET_INFO, info,
90249d29c8SSascha Wildner sizeof(struct mfi_ld_info), mbox, 1, statusp));
91249d29c8SSascha Wildner }
92249d29c8SSascha Wildner
93249d29c8SSascha Wildner static int
mfi_ld_get_props(int fd,uint8_t target_id,struct mfi_ld_props * props)94249d29c8SSascha Wildner mfi_ld_get_props(int fd, uint8_t target_id, struct mfi_ld_props *props)
95249d29c8SSascha Wildner {
96249d29c8SSascha Wildner uint8_t mbox[1];
97249d29c8SSascha Wildner
98249d29c8SSascha Wildner mbox[0] = target_id;
99249d29c8SSascha Wildner return (mfi_dcmd_command(fd, MFI_DCMD_LD_GET_PROP, props,
100249d29c8SSascha Wildner sizeof(struct mfi_ld_props), mbox, 1, NULL));
101249d29c8SSascha Wildner }
102249d29c8SSascha Wildner
103249d29c8SSascha Wildner static int
mfi_ld_set_props(int fd,struct mfi_ld_props * props)104249d29c8SSascha Wildner mfi_ld_set_props(int fd, struct mfi_ld_props *props)
105249d29c8SSascha Wildner {
106249d29c8SSascha Wildner uint8_t mbox[4];
107249d29c8SSascha Wildner
108249d29c8SSascha Wildner mbox_store_ldref(mbox, &props->ld);
109249d29c8SSascha Wildner return (mfi_dcmd_command(fd, MFI_DCMD_LD_SET_PROP, props,
110249d29c8SSascha Wildner sizeof(struct mfi_ld_props), mbox, 4, NULL));
111249d29c8SSascha Wildner }
112249d29c8SSascha Wildner
113249d29c8SSascha Wildner static int
update_cache_policy(int fd,struct mfi_ld_props * old,struct mfi_ld_props * new)114*f0d8b1f2SSascha Wildner update_cache_policy(int fd, struct mfi_ld_props *old, struct mfi_ld_props *new)
115249d29c8SSascha Wildner {
116249d29c8SSascha Wildner int error;
117249d29c8SSascha Wildner uint8_t changes, policy;
118249d29c8SSascha Wildner
119*f0d8b1f2SSascha Wildner if (old->default_cache_policy == new->default_cache_policy &&
120*f0d8b1f2SSascha Wildner old->disk_cache_policy == new->disk_cache_policy)
121249d29c8SSascha Wildner return (0);
122*f0d8b1f2SSascha Wildner policy = new->default_cache_policy;
123*f0d8b1f2SSascha Wildner changes = policy ^ old->default_cache_policy;
124249d29c8SSascha Wildner if (changes & MR_LD_CACHE_ALLOW_WRITE_CACHE)
125249d29c8SSascha Wildner printf("%s caching of I/O writes\n",
126249d29c8SSascha Wildner policy & MR_LD_CACHE_ALLOW_WRITE_CACHE ? "Enabling" :
127249d29c8SSascha Wildner "Disabling");
128249d29c8SSascha Wildner if (changes & MR_LD_CACHE_ALLOW_READ_CACHE)
129249d29c8SSascha Wildner printf("%s caching of I/O reads\n",
130249d29c8SSascha Wildner policy & MR_LD_CACHE_ALLOW_READ_CACHE ? "Enabling" :
131249d29c8SSascha Wildner "Disabling");
132249d29c8SSascha Wildner if (changes & MR_LD_CACHE_WRITE_BACK)
133249d29c8SSascha Wildner printf("Setting write cache policy to %s\n",
134249d29c8SSascha Wildner policy & MR_LD_CACHE_WRITE_BACK ? "write-back" :
135249d29c8SSascha Wildner "write-through");
136249d29c8SSascha Wildner if (changes & (MR_LD_CACHE_READ_AHEAD | MR_LD_CACHE_READ_ADAPTIVE))
137249d29c8SSascha Wildner printf("Setting read ahead policy to %s\n",
138249d29c8SSascha Wildner policy & MR_LD_CACHE_READ_AHEAD ?
139249d29c8SSascha Wildner (policy & MR_LD_CACHE_READ_ADAPTIVE ?
140249d29c8SSascha Wildner "adaptive" : "always") : "none");
141f26fa772SSascha Wildner if (changes & MR_LD_CACHE_WRITE_CACHE_BAD_BBU)
142f26fa772SSascha Wildner printf("%s write caching with bad BBU\n",
143f26fa772SSascha Wildner policy & MR_LD_CACHE_WRITE_CACHE_BAD_BBU ? "Enabling" :
144f26fa772SSascha Wildner "Disabling");
145*f0d8b1f2SSascha Wildner if (old->disk_cache_policy != new->disk_cache_policy) {
146*f0d8b1f2SSascha Wildner switch (new->disk_cache_policy) {
147*f0d8b1f2SSascha Wildner case MR_PD_CACHE_ENABLE:
148*f0d8b1f2SSascha Wildner printf("Enabling write-cache on physical drives\n");
149*f0d8b1f2SSascha Wildner break;
150*f0d8b1f2SSascha Wildner case MR_PD_CACHE_DISABLE:
151*f0d8b1f2SSascha Wildner printf("Disabling write-cache on physical drives\n");
152*f0d8b1f2SSascha Wildner break;
153*f0d8b1f2SSascha Wildner case MR_PD_CACHE_UNCHANGED:
154*f0d8b1f2SSascha Wildner printf("Using default write-cache setting on physical drives\n");
155*f0d8b1f2SSascha Wildner break;
156*f0d8b1f2SSascha Wildner }
157*f0d8b1f2SSascha Wildner }
158249d29c8SSascha Wildner
159*f0d8b1f2SSascha Wildner if (mfi_ld_set_props(fd, new) < 0) {
160249d29c8SSascha Wildner error = errno;
161249d29c8SSascha Wildner warn("Failed to set volume properties");
162249d29c8SSascha Wildner return (error);
163249d29c8SSascha Wildner }
164249d29c8SSascha Wildner return (0);
165249d29c8SSascha Wildner }
166249d29c8SSascha Wildner
167*f0d8b1f2SSascha Wildner static void
stage_cache_setting(struct mfi_ld_props * props,uint8_t new_policy,uint8_t mask)168*f0d8b1f2SSascha Wildner stage_cache_setting(struct mfi_ld_props *props, uint8_t new_policy,
169*f0d8b1f2SSascha Wildner uint8_t mask)
170*f0d8b1f2SSascha Wildner {
171*f0d8b1f2SSascha Wildner
172*f0d8b1f2SSascha Wildner props->default_cache_policy &= ~mask;
173*f0d8b1f2SSascha Wildner props->default_cache_policy |= new_policy;
174*f0d8b1f2SSascha Wildner }
175*f0d8b1f2SSascha Wildner
176*f0d8b1f2SSascha Wildner /*
177*f0d8b1f2SSascha Wildner * Parse a single cache directive modifying the passed in policy.
178*f0d8b1f2SSascha Wildner * Returns -1 on a parse error and the number of arguments consumed
179*f0d8b1f2SSascha Wildner * on success.
180*f0d8b1f2SSascha Wildner */
181*f0d8b1f2SSascha Wildner static int
process_cache_command(int ac,char ** av,struct mfi_ld_props * props)182*f0d8b1f2SSascha Wildner process_cache_command(int ac, char **av, struct mfi_ld_props *props)
183*f0d8b1f2SSascha Wildner {
184*f0d8b1f2SSascha Wildner uint8_t policy;
185*f0d8b1f2SSascha Wildner
186*f0d8b1f2SSascha Wildner /* I/O cache settings. */
187*f0d8b1f2SSascha Wildner if (strcmp(av[0], "all") == 0 || strcmp(av[0], "enable") == 0) {
188*f0d8b1f2SSascha Wildner stage_cache_setting(props, MR_LD_CACHE_ALLOW_READ_CACHE |
189*f0d8b1f2SSascha Wildner MR_LD_CACHE_ALLOW_WRITE_CACHE,
190*f0d8b1f2SSascha Wildner MR_LD_CACHE_ALLOW_READ_CACHE |
191*f0d8b1f2SSascha Wildner MR_LD_CACHE_ALLOW_WRITE_CACHE);
192*f0d8b1f2SSascha Wildner return (1);
193*f0d8b1f2SSascha Wildner }
194*f0d8b1f2SSascha Wildner if (strcmp(av[0], "none") == 0 || strcmp(av[0], "disable") == 0) {
195*f0d8b1f2SSascha Wildner stage_cache_setting(props, 0, MR_LD_CACHE_ALLOW_READ_CACHE |
196*f0d8b1f2SSascha Wildner MR_LD_CACHE_ALLOW_WRITE_CACHE);
197*f0d8b1f2SSascha Wildner return (1);
198*f0d8b1f2SSascha Wildner }
199*f0d8b1f2SSascha Wildner if (strcmp(av[0], "reads") == 0) {
200*f0d8b1f2SSascha Wildner stage_cache_setting(props, MR_LD_CACHE_ALLOW_READ_CACHE,
201*f0d8b1f2SSascha Wildner MR_LD_CACHE_ALLOW_READ_CACHE |
202*f0d8b1f2SSascha Wildner MR_LD_CACHE_ALLOW_WRITE_CACHE);
203*f0d8b1f2SSascha Wildner return (1);
204*f0d8b1f2SSascha Wildner }
205*f0d8b1f2SSascha Wildner if (strcmp(av[0], "writes") == 0) {
206*f0d8b1f2SSascha Wildner stage_cache_setting(props, MR_LD_CACHE_ALLOW_WRITE_CACHE,
207*f0d8b1f2SSascha Wildner MR_LD_CACHE_ALLOW_READ_CACHE |
208*f0d8b1f2SSascha Wildner MR_LD_CACHE_ALLOW_WRITE_CACHE);
209*f0d8b1f2SSascha Wildner return (1);
210*f0d8b1f2SSascha Wildner }
211*f0d8b1f2SSascha Wildner
212*f0d8b1f2SSascha Wildner /* Write cache behavior. */
213*f0d8b1f2SSascha Wildner if (strcmp(av[0], "write-back") == 0) {
214*f0d8b1f2SSascha Wildner stage_cache_setting(props, MR_LD_CACHE_WRITE_BACK,
215*f0d8b1f2SSascha Wildner MR_LD_CACHE_WRITE_BACK);
216*f0d8b1f2SSascha Wildner return (1);
217*f0d8b1f2SSascha Wildner }
218*f0d8b1f2SSascha Wildner if (strcmp(av[0], "write-through") == 0) {
219*f0d8b1f2SSascha Wildner stage_cache_setting(props, 0, MR_LD_CACHE_WRITE_BACK);
220*f0d8b1f2SSascha Wildner return (1);
221*f0d8b1f2SSascha Wildner }
222*f0d8b1f2SSascha Wildner if (strcmp(av[0], "bad-bbu-write-cache") == 0) {
223*f0d8b1f2SSascha Wildner if (ac < 2) {
224*f0d8b1f2SSascha Wildner warnx("cache: bad BBU setting required");
225*f0d8b1f2SSascha Wildner return (-1);
226*f0d8b1f2SSascha Wildner }
227*f0d8b1f2SSascha Wildner if (strcmp(av[1], "enable") == 0)
228*f0d8b1f2SSascha Wildner policy = MR_LD_CACHE_WRITE_CACHE_BAD_BBU;
229*f0d8b1f2SSascha Wildner else if (strcmp(av[1], "disable") == 0)
230*f0d8b1f2SSascha Wildner policy = 0;
231*f0d8b1f2SSascha Wildner else {
232*f0d8b1f2SSascha Wildner warnx("cache: invalid bad BBU setting");
233*f0d8b1f2SSascha Wildner return (-1);
234*f0d8b1f2SSascha Wildner }
235*f0d8b1f2SSascha Wildner stage_cache_setting(props, policy,
236*f0d8b1f2SSascha Wildner MR_LD_CACHE_WRITE_CACHE_BAD_BBU);
237*f0d8b1f2SSascha Wildner return (2);
238*f0d8b1f2SSascha Wildner }
239*f0d8b1f2SSascha Wildner
240*f0d8b1f2SSascha Wildner /* Read cache behavior. */
241*f0d8b1f2SSascha Wildner if (strcmp(av[0], "read-ahead") == 0) {
242*f0d8b1f2SSascha Wildner if (ac < 2) {
243*f0d8b1f2SSascha Wildner warnx("cache: read-ahead setting required");
244*f0d8b1f2SSascha Wildner return (-1);
245*f0d8b1f2SSascha Wildner }
246*f0d8b1f2SSascha Wildner if (strcmp(av[1], "none") == 0)
247*f0d8b1f2SSascha Wildner policy = 0;
248*f0d8b1f2SSascha Wildner else if (strcmp(av[1], "always") == 0)
249*f0d8b1f2SSascha Wildner policy = MR_LD_CACHE_READ_AHEAD;
250*f0d8b1f2SSascha Wildner else if (strcmp(av[1], "adaptive") == 0)
251*f0d8b1f2SSascha Wildner policy = MR_LD_CACHE_READ_AHEAD |
252*f0d8b1f2SSascha Wildner MR_LD_CACHE_READ_ADAPTIVE;
253*f0d8b1f2SSascha Wildner else {
254*f0d8b1f2SSascha Wildner warnx("cache: invalid read-ahead setting");
255*f0d8b1f2SSascha Wildner return (-1);
256*f0d8b1f2SSascha Wildner }
257*f0d8b1f2SSascha Wildner stage_cache_setting(props, policy, MR_LD_CACHE_READ_AHEAD |
258*f0d8b1f2SSascha Wildner MR_LD_CACHE_READ_ADAPTIVE);
259*f0d8b1f2SSascha Wildner return (2);
260*f0d8b1f2SSascha Wildner }
261*f0d8b1f2SSascha Wildner
262*f0d8b1f2SSascha Wildner /* Drive write-cache behavior. */
263*f0d8b1f2SSascha Wildner if (strcmp(av[0], "write-cache") == 0) {
264*f0d8b1f2SSascha Wildner if (ac < 2) {
265*f0d8b1f2SSascha Wildner warnx("cache: write-cache setting required");
266*f0d8b1f2SSascha Wildner return (-1);
267*f0d8b1f2SSascha Wildner }
268*f0d8b1f2SSascha Wildner if (strcmp(av[1], "enable") == 0)
269*f0d8b1f2SSascha Wildner props->disk_cache_policy = MR_PD_CACHE_ENABLE;
270*f0d8b1f2SSascha Wildner else if (strcmp(av[1], "disable") == 0)
271*f0d8b1f2SSascha Wildner props->disk_cache_policy = MR_PD_CACHE_DISABLE;
272*f0d8b1f2SSascha Wildner else if (strcmp(av[1], "default") == 0)
273*f0d8b1f2SSascha Wildner props->disk_cache_policy = MR_PD_CACHE_UNCHANGED;
274*f0d8b1f2SSascha Wildner else {
275*f0d8b1f2SSascha Wildner warnx("cache: invalid write-cache setting");
276*f0d8b1f2SSascha Wildner return (-1);
277*f0d8b1f2SSascha Wildner }
278*f0d8b1f2SSascha Wildner return (2);
279*f0d8b1f2SSascha Wildner }
280*f0d8b1f2SSascha Wildner
281*f0d8b1f2SSascha Wildner warnx("cache: Invalid command");
282*f0d8b1f2SSascha Wildner return (-1);
283*f0d8b1f2SSascha Wildner }
284*f0d8b1f2SSascha Wildner
285249d29c8SSascha Wildner static int
volume_cache(int ac,char ** av)286249d29c8SSascha Wildner volume_cache(int ac, char **av)
287249d29c8SSascha Wildner {
288*f0d8b1f2SSascha Wildner struct mfi_ld_props props, new;
289*f0d8b1f2SSascha Wildner int error, fd, consumed;
290*f0d8b1f2SSascha Wildner uint8_t target_id;
291249d29c8SSascha Wildner
292249d29c8SSascha Wildner if (ac < 2) {
293249d29c8SSascha Wildner warnx("cache: volume required");
294249d29c8SSascha Wildner return (EINVAL);
295249d29c8SSascha Wildner }
296249d29c8SSascha Wildner
297249d29c8SSascha Wildner fd = mfi_open(mfi_unit);
298249d29c8SSascha Wildner if (fd < 0) {
299249d29c8SSascha Wildner error = errno;
300249d29c8SSascha Wildner warn("mfi_open");
301249d29c8SSascha Wildner return (error);
302249d29c8SSascha Wildner }
303249d29c8SSascha Wildner
304249d29c8SSascha Wildner if (mfi_lookup_volume(fd, av[1], &target_id) < 0) {
305249d29c8SSascha Wildner error = errno;
306249d29c8SSascha Wildner warn("Invalid volume: %s", av[1]);
307f26fa772SSascha Wildner close(fd);
308249d29c8SSascha Wildner return (error);
309249d29c8SSascha Wildner }
310249d29c8SSascha Wildner
311249d29c8SSascha Wildner if (mfi_ld_get_props(fd, target_id, &props) < 0) {
312249d29c8SSascha Wildner error = errno;
313249d29c8SSascha Wildner warn("Failed to fetch volume properties");
314f26fa772SSascha Wildner close(fd);
315249d29c8SSascha Wildner return (error);
316249d29c8SSascha Wildner }
317249d29c8SSascha Wildner
318249d29c8SSascha Wildner if (ac == 2) {
319249d29c8SSascha Wildner printf("mfi%u volume %s cache settings:\n", mfi_unit,
320249d29c8SSascha Wildner mfi_volume_name(fd, target_id));
321249d29c8SSascha Wildner printf(" I/O caching: ");
322249d29c8SSascha Wildner switch (props.default_cache_policy &
323249d29c8SSascha Wildner (MR_LD_CACHE_ALLOW_WRITE_CACHE |
324249d29c8SSascha Wildner MR_LD_CACHE_ALLOW_READ_CACHE)) {
325249d29c8SSascha Wildner case 0:
326249d29c8SSascha Wildner printf("disabled\n");
327249d29c8SSascha Wildner break;
328249d29c8SSascha Wildner case MR_LD_CACHE_ALLOW_WRITE_CACHE:
329249d29c8SSascha Wildner printf("writes\n");
330249d29c8SSascha Wildner break;
331249d29c8SSascha Wildner case MR_LD_CACHE_ALLOW_READ_CACHE:
332249d29c8SSascha Wildner printf("reads\n");
333249d29c8SSascha Wildner break;
334249d29c8SSascha Wildner case MR_LD_CACHE_ALLOW_WRITE_CACHE |
335249d29c8SSascha Wildner MR_LD_CACHE_ALLOW_READ_CACHE:
336249d29c8SSascha Wildner printf("writes and reads\n");
337249d29c8SSascha Wildner break;
338249d29c8SSascha Wildner }
339249d29c8SSascha Wildner printf(" write caching: %s\n",
340249d29c8SSascha Wildner props.default_cache_policy & MR_LD_CACHE_WRITE_BACK ?
341249d29c8SSascha Wildner "write-back" : "write-through");
342f26fa772SSascha Wildner printf("write cache with bad BBU: %s\n",
343f26fa772SSascha Wildner props.default_cache_policy &
344f26fa772SSascha Wildner MR_LD_CACHE_WRITE_CACHE_BAD_BBU ? "enabled" : "disabled");
345249d29c8SSascha Wildner printf(" read ahead: %s\n",
346249d29c8SSascha Wildner props.default_cache_policy & MR_LD_CACHE_READ_AHEAD ?
347249d29c8SSascha Wildner (props.default_cache_policy & MR_LD_CACHE_READ_ADAPTIVE ?
348249d29c8SSascha Wildner "adaptive" : "always") : "none");
349249d29c8SSascha Wildner printf(" drive write cache: ");
350249d29c8SSascha Wildner switch (props.disk_cache_policy) {
351249d29c8SSascha Wildner case MR_PD_CACHE_UNCHANGED:
352249d29c8SSascha Wildner printf("default\n");
353249d29c8SSascha Wildner break;
354249d29c8SSascha Wildner case MR_PD_CACHE_ENABLE:
355249d29c8SSascha Wildner printf("enabled\n");
356249d29c8SSascha Wildner break;
357249d29c8SSascha Wildner case MR_PD_CACHE_DISABLE:
358249d29c8SSascha Wildner printf("disabled\n");
359249d29c8SSascha Wildner break;
360249d29c8SSascha Wildner default:
361249d29c8SSascha Wildner printf("??? %d\n", props.disk_cache_policy);
362249d29c8SSascha Wildner break;
363249d29c8SSascha Wildner }
364249d29c8SSascha Wildner if (props.default_cache_policy != props.current_cache_policy)
365249d29c8SSascha Wildner printf("Cache Disabled Due to Dead Battery\n");
366249d29c8SSascha Wildner error = 0;
367249d29c8SSascha Wildner } else {
368*f0d8b1f2SSascha Wildner new = props;
369*f0d8b1f2SSascha Wildner av += 2;
370*f0d8b1f2SSascha Wildner ac -= 2;
371*f0d8b1f2SSascha Wildner while (ac > 0) {
372*f0d8b1f2SSascha Wildner consumed = process_cache_command(ac, av, &new);
373*f0d8b1f2SSascha Wildner if (consumed < 0) {
374f26fa772SSascha Wildner close(fd);
375249d29c8SSascha Wildner return (EINVAL);
376249d29c8SSascha Wildner }
377*f0d8b1f2SSascha Wildner av += consumed;
378*f0d8b1f2SSascha Wildner ac -= consumed;
379249d29c8SSascha Wildner }
380*f0d8b1f2SSascha Wildner error = update_cache_policy(fd, &props, &new);
381249d29c8SSascha Wildner }
382249d29c8SSascha Wildner close(fd);
383249d29c8SSascha Wildner
384249d29c8SSascha Wildner return (error);
385249d29c8SSascha Wildner }
386249d29c8SSascha Wildner MFI_COMMAND(top, cache, volume_cache);
387249d29c8SSascha Wildner
388249d29c8SSascha Wildner static int
volume_name(int ac,char ** av)389249d29c8SSascha Wildner volume_name(int ac, char **av)
390249d29c8SSascha Wildner {
391249d29c8SSascha Wildner struct mfi_ld_props props;
392249d29c8SSascha Wildner int error, fd;
393249d29c8SSascha Wildner uint8_t target_id;
394249d29c8SSascha Wildner
395249d29c8SSascha Wildner if (ac != 3) {
396249d29c8SSascha Wildner warnx("name: volume and name required");
397249d29c8SSascha Wildner return (EINVAL);
398249d29c8SSascha Wildner }
399249d29c8SSascha Wildner
400249d29c8SSascha Wildner if (strlen(av[2]) >= sizeof(props.name)) {
401249d29c8SSascha Wildner warnx("name: new name is too long");
402249d29c8SSascha Wildner return (ENOSPC);
403249d29c8SSascha Wildner }
404249d29c8SSascha Wildner
405249d29c8SSascha Wildner fd = mfi_open(mfi_unit);
406249d29c8SSascha Wildner if (fd < 0) {
407249d29c8SSascha Wildner error = errno;
408249d29c8SSascha Wildner warn("mfi_open");
409249d29c8SSascha Wildner return (error);
410249d29c8SSascha Wildner }
411249d29c8SSascha Wildner
412249d29c8SSascha Wildner if (mfi_lookup_volume(fd, av[1], &target_id) < 0) {
413249d29c8SSascha Wildner error = errno;
414249d29c8SSascha Wildner warn("Invalid volume: %s", av[1]);
415f26fa772SSascha Wildner close(fd);
416249d29c8SSascha Wildner return (error);
417249d29c8SSascha Wildner }
418249d29c8SSascha Wildner
419249d29c8SSascha Wildner if (mfi_ld_get_props(fd, target_id, &props) < 0) {
420249d29c8SSascha Wildner error = errno;
421249d29c8SSascha Wildner warn("Failed to fetch volume properties");
422f26fa772SSascha Wildner close(fd);
423249d29c8SSascha Wildner return (error);
424249d29c8SSascha Wildner }
425249d29c8SSascha Wildner
426249d29c8SSascha Wildner printf("mfi%u volume %s name changed from \"%s\" to \"%s\"\n", mfi_unit,
427249d29c8SSascha Wildner mfi_volume_name(fd, target_id), props.name, av[2]);
428249d29c8SSascha Wildner bzero(props.name, sizeof(props.name));
429249d29c8SSascha Wildner strcpy(props.name, av[2]);
430249d29c8SSascha Wildner if (mfi_ld_set_props(fd, &props) < 0) {
431249d29c8SSascha Wildner error = errno;
432249d29c8SSascha Wildner warn("Failed to set volume properties");
433f26fa772SSascha Wildner close(fd);
434249d29c8SSascha Wildner return (error);
435249d29c8SSascha Wildner }
436249d29c8SSascha Wildner
437249d29c8SSascha Wildner close(fd);
438249d29c8SSascha Wildner
439249d29c8SSascha Wildner return (0);
440249d29c8SSascha Wildner }
441249d29c8SSascha Wildner MFI_COMMAND(top, name, volume_name);
442249d29c8SSascha Wildner
443249d29c8SSascha Wildner static int
volume_progress(int ac,char ** av)444249d29c8SSascha Wildner volume_progress(int ac, char **av)
445249d29c8SSascha Wildner {
446249d29c8SSascha Wildner struct mfi_ld_info info;
447249d29c8SSascha Wildner int error, fd;
448249d29c8SSascha Wildner uint8_t target_id;
449249d29c8SSascha Wildner
450249d29c8SSascha Wildner if (ac != 2) {
451249d29c8SSascha Wildner warnx("volume progress: %s", ac > 2 ? "extra arguments" :
452249d29c8SSascha Wildner "volume required");
453249d29c8SSascha Wildner return (EINVAL);
454249d29c8SSascha Wildner }
455249d29c8SSascha Wildner
456249d29c8SSascha Wildner fd = mfi_open(mfi_unit);
457249d29c8SSascha Wildner if (fd < 0) {
458249d29c8SSascha Wildner error = errno;
459249d29c8SSascha Wildner warn("mfi_open");
460249d29c8SSascha Wildner return (error);
461249d29c8SSascha Wildner }
462249d29c8SSascha Wildner
463249d29c8SSascha Wildner if (mfi_lookup_volume(fd, av[1], &target_id) < 0) {
464249d29c8SSascha Wildner error = errno;
465249d29c8SSascha Wildner warn("Invalid volume: %s", av[1]);
466f26fa772SSascha Wildner close(fd);
467249d29c8SSascha Wildner return (error);
468249d29c8SSascha Wildner }
469249d29c8SSascha Wildner
470249d29c8SSascha Wildner /* Get the info for this drive. */
471249d29c8SSascha Wildner if (mfi_ld_get_info(fd, target_id, &info, NULL) < 0) {
472249d29c8SSascha Wildner error = errno;
473249d29c8SSascha Wildner warn("Failed to fetch info for volume %s",
474249d29c8SSascha Wildner mfi_volume_name(fd, target_id));
475f26fa772SSascha Wildner close(fd);
476249d29c8SSascha Wildner return (error);
477249d29c8SSascha Wildner }
478249d29c8SSascha Wildner
479249d29c8SSascha Wildner /* Display any of the active events. */
480249d29c8SSascha Wildner if (info.progress.active & MFI_LD_PROGRESS_CC)
481249d29c8SSascha Wildner mfi_display_progress("Consistency Check", &info.progress.cc);
482249d29c8SSascha Wildner if (info.progress.active & MFI_LD_PROGRESS_BGI)
483249d29c8SSascha Wildner mfi_display_progress("Background Init", &info.progress.bgi);
484249d29c8SSascha Wildner if (info.progress.active & MFI_LD_PROGRESS_FGI)
485249d29c8SSascha Wildner mfi_display_progress("Foreground Init", &info.progress.fgi);
486249d29c8SSascha Wildner if (info.progress.active & MFI_LD_PROGRESS_RECON)
487249d29c8SSascha Wildner mfi_display_progress("Reconstruction", &info.progress.recon);
488249d29c8SSascha Wildner if ((info.progress.active & (MFI_LD_PROGRESS_CC | MFI_LD_PROGRESS_BGI |
489249d29c8SSascha Wildner MFI_LD_PROGRESS_FGI | MFI_LD_PROGRESS_RECON)) == 0)
490249d29c8SSascha Wildner printf("No activity in progress for volume %s.\n",
491249d29c8SSascha Wildner mfi_volume_name(fd, target_id));
492249d29c8SSascha Wildner close(fd);
493249d29c8SSascha Wildner
494249d29c8SSascha Wildner return (0);
495249d29c8SSascha Wildner }
496249d29c8SSascha Wildner MFI_COMMAND(volume, progress, volume_progress);
497