1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2004-2006 Pawel Jakub Dawidek <pjd@FreeBSD.org>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD$");
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/kernel.h>
35#include <sys/module.h>
36#include <sys/lock.h>
37#include <sys/mutex.h>
38#include <sys/bio.h>
39#include <sys/sysctl.h>
40#include <sys/malloc.h>
41#include <sys/bitstring.h>
42#include <vm/uma.h>
43#include <machine/atomic.h>
44#include <geom/geom.h>
45#include <sys/proc.h>
46#include <sys/kthread.h>
47#include <geom/raid3/g_raid3.h>
48
49static struct g_raid3_softc *
50g_raid3_find_device(struct g_class *mp, const char *name)
51{
52	struct g_raid3_softc *sc;
53	struct g_geom *gp;
54
55	g_topology_lock();
56	LIST_FOREACH(gp, &mp->geom, geom) {
57		sc = gp->softc;
58		if (sc == NULL)
59			continue;
60		if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_DESTROY) != 0)
61			continue;
62		if (strcmp(gp->name, name) == 0 ||
63		    strcmp(sc->sc_name, name) == 0) {
64			g_topology_unlock();
65			sx_xlock(&sc->sc_lock);
66			return (sc);
67		}
68	}
69	g_topology_unlock();
70	return (NULL);
71}
72
73static struct g_raid3_disk *
74g_raid3_find_disk(struct g_raid3_softc *sc, const char *name)
75{
76	struct g_raid3_disk *disk;
77	u_int n;
78
79	sx_assert(&sc->sc_lock, SX_XLOCKED);
80	if (strncmp(name, _PATH_DEV, 5) == 0)
81		name += 5;
82	for (n = 0; n < sc->sc_ndisks; n++) {
83		disk = &sc->sc_disks[n];
84		if (disk->d_state == G_RAID3_DISK_STATE_NODISK)
85			continue;
86		if (disk->d_consumer == NULL)
87			continue;
88		if (disk->d_consumer->provider == NULL)
89			continue;
90		if (strcmp(disk->d_consumer->provider->name, name) == 0)
91			return (disk);
92	}
93	return (NULL);
94}
95
96static void
97g_raid3_ctl_configure(struct gctl_req *req, struct g_class *mp)
98{
99	struct g_raid3_softc *sc;
100	struct g_raid3_disk *disk;
101	const char *name;
102	int *nargs, do_sync = 0, dirty = 1;
103	int *autosync, *noautosync;
104	int *failsync, *nofailsync;
105	int *round_robin, *noround_robin;
106	int *verify, *noverify;
107	u_int n;
108
109	nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
110	if (nargs == NULL) {
111		gctl_error(req, "No '%s' argument.", "nargs");
112		return;
113	}
114	if (*nargs != 1) {
115		gctl_error(req, "Invalid number of arguments.");
116		return;
117	}
118	autosync = gctl_get_paraml(req, "autosync", sizeof(*autosync));
119	if (autosync == NULL) {
120		gctl_error(req, "No '%s' argument.", "autosync");
121		return;
122	}
123	noautosync = gctl_get_paraml(req, "noautosync", sizeof(*noautosync));
124	if (noautosync == NULL) {
125		gctl_error(req, "No '%s' argument.", "noautosync");
126		return;
127	}
128	if (*autosync && *noautosync) {
129		gctl_error(req, "'%s' and '%s' specified.", "autosync",
130		    "noautosync");
131		return;
132	}
133	failsync = gctl_get_paraml(req, "failsync", sizeof(*failsync));
134	if (failsync == NULL) {
135		gctl_error(req, "No '%s' argument.", "failsync");
136		return;
137	}
138	nofailsync = gctl_get_paraml(req, "nofailsync", sizeof(*nofailsync));
139	if (nofailsync == NULL) {
140		gctl_error(req, "No '%s' argument.", "nofailsync");
141		return;
142	}
143	if (*failsync && *nofailsync) {
144		gctl_error(req, "'%s' and '%s' specified.", "failsync",
145		    "nofailsync");
146		return;
147	}
148	round_robin = gctl_get_paraml(req, "round_robin", sizeof(*round_robin));
149	if (round_robin == NULL) {
150		gctl_error(req, "No '%s' argument.", "round_robin");
151		return;
152	}
153	noround_robin = gctl_get_paraml(req, "noround_robin",
154	    sizeof(*noround_robin));
155	if (noround_robin == NULL) {
156		gctl_error(req, "No '%s' argument.", "noround_robin");
157		return;
158	}
159	if (*round_robin && *noround_robin) {
160		gctl_error(req, "'%s' and '%s' specified.", "round_robin",
161		    "noround_robin");
162		return;
163	}
164	verify = gctl_get_paraml(req, "verify", sizeof(*verify));
165	if (verify == NULL) {
166		gctl_error(req, "No '%s' argument.", "verify");
167		return;
168	}
169	noverify = gctl_get_paraml(req, "noverify", sizeof(*noverify));
170	if (noverify == NULL) {
171		gctl_error(req, "No '%s' argument.", "noverify");
172		return;
173	}
174	if (*verify && *noverify) {
175		gctl_error(req, "'%s' and '%s' specified.", "verify",
176		    "noverify");
177		return;
178	}
179	if (!*autosync && !*noautosync && !*failsync && !*nofailsync &&
180	    !*round_robin && !*noround_robin && !*verify && !*noverify) {
181		gctl_error(req, "Nothing has changed.");
182		return;
183	}
184	name = gctl_get_asciiparam(req, "arg0");
185	if (name == NULL) {
186		gctl_error(req, "No 'arg%u' argument.", 0);
187		return;
188	}
189	sc = g_raid3_find_device(mp, name);
190	if (sc == NULL) {
191		gctl_error(req, "No such device: %s.", name);
192		return;
193	}
194	if (g_raid3_ndisks(sc, -1) < sc->sc_ndisks) {
195		gctl_error(req, "Not all disks connected.");
196		sx_xunlock(&sc->sc_lock);
197		return;
198	}
199	if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_NOAUTOSYNC) != 0) {
200		if (*autosync) {
201			sc->sc_flags &= ~G_RAID3_DEVICE_FLAG_NOAUTOSYNC;
202			do_sync = 1;
203		}
204	} else {
205		if (*noautosync)
206			sc->sc_flags |= G_RAID3_DEVICE_FLAG_NOAUTOSYNC;
207	}
208	if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_NOFAILSYNC) != 0) {
209		if (*failsync)
210			sc->sc_flags &= ~G_RAID3_DEVICE_FLAG_NOFAILSYNC;
211	} else {
212		if (*nofailsync) {
213			sc->sc_flags |= G_RAID3_DEVICE_FLAG_NOFAILSYNC;
214			dirty = 0;
215		}
216	}
217	if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_VERIFY) != 0) {
218		if (*noverify)
219			sc->sc_flags &= ~G_RAID3_DEVICE_FLAG_VERIFY;
220	} else {
221		if (*verify)
222			sc->sc_flags |= G_RAID3_DEVICE_FLAG_VERIFY;
223	}
224	if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_ROUND_ROBIN) != 0) {
225		if (*noround_robin)
226			sc->sc_flags &= ~G_RAID3_DEVICE_FLAG_ROUND_ROBIN;
227	} else {
228		if (*round_robin)
229			sc->sc_flags |= G_RAID3_DEVICE_FLAG_ROUND_ROBIN;
230	}
231	if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_VERIFY) != 0 &&
232	    (sc->sc_flags & G_RAID3_DEVICE_FLAG_ROUND_ROBIN) != 0) {
233		/*
234		 * VERIFY and ROUND-ROBIN options are mutally exclusive.
235		 */
236		sc->sc_flags &= ~G_RAID3_DEVICE_FLAG_ROUND_ROBIN;
237	}
238	for (n = 0; n < sc->sc_ndisks; n++) {
239		disk = &sc->sc_disks[n];
240		if (do_sync) {
241			if (disk->d_state == G_RAID3_DISK_STATE_SYNCHRONIZING)
242				disk->d_flags &= ~G_RAID3_DISK_FLAG_FORCE_SYNC;
243		}
244		if (!dirty)
245			disk->d_flags &= ~G_RAID3_DISK_FLAG_DIRTY;
246		g_raid3_update_metadata(disk);
247		if (do_sync) {
248			if (disk->d_state == G_RAID3_DISK_STATE_STALE) {
249				/*
250				 * XXX: This is probably possible that this
251				 *      component will not be retasted.
252				 */
253				g_raid3_event_send(disk,
254				    G_RAID3_DISK_STATE_DISCONNECTED,
255				    G_RAID3_EVENT_DONTWAIT);
256			}
257		}
258	}
259	sx_xunlock(&sc->sc_lock);
260}
261
262static void
263g_raid3_ctl_rebuild(struct gctl_req *req, struct g_class *mp)
264{
265	struct g_raid3_metadata md;
266	struct g_raid3_softc *sc;
267	struct g_raid3_disk *disk;
268	struct g_provider *pp;
269	const char *name;
270	int error, *nargs;
271
272	nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
273	if (nargs == NULL) {
274		gctl_error(req, "No '%s' argument.", "nargs");
275		return;
276	}
277	if (*nargs != 2) {
278		gctl_error(req, "Invalid number of arguments.");
279		return;
280	}
281	name = gctl_get_asciiparam(req, "arg0");
282	if (name == NULL) {
283		gctl_error(req, "No 'arg%u' argument.", 0);
284		return;
285	}
286	sc = g_raid3_find_device(mp, name);
287	if (sc == NULL) {
288		gctl_error(req, "No such device: %s.", name);
289		return;
290	}
291	name = gctl_get_asciiparam(req, "arg1");
292	if (name == NULL) {
293		gctl_error(req, "No 'arg%u' argument.", 1);
294		sx_xunlock(&sc->sc_lock);
295		return;
296	}
297	disk = g_raid3_find_disk(sc, name);
298	if (disk == NULL) {
299		gctl_error(req, "No such provider: %s.", name);
300		sx_xunlock(&sc->sc_lock);
301		return;
302	}
303	if (disk->d_state == G_RAID3_DISK_STATE_ACTIVE &&
304	    g_raid3_ndisks(sc, G_RAID3_DISK_STATE_ACTIVE) < sc->sc_ndisks) {
305		gctl_error(req, "There is one stale disk already.");
306		sx_xunlock(&sc->sc_lock);
307		return;
308	}
309	/*
310	 * Do rebuild by resetting syncid and disconnecting disk.
311	 * It'll be retasted, connected to the device and synchronized.
312	 */
313	disk->d_sync.ds_syncid = 0;
314	if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_NOAUTOSYNC) != 0)
315		disk->d_flags |= G_RAID3_DISK_FLAG_FORCE_SYNC;
316	g_raid3_update_metadata(disk);
317	pp = disk->d_consumer->provider;
318	g_topology_lock();
319	error = g_raid3_read_metadata(disk->d_consumer, &md);
320	g_topology_unlock();
321	g_raid3_event_send(disk, G_RAID3_DISK_STATE_DISCONNECTED,
322	    G_RAID3_EVENT_WAIT);
323	if (error != 0) {
324		gctl_error(req, "Cannot read metadata from %s.", pp->name);
325		sx_xunlock(&sc->sc_lock);
326		return;
327	}
328	error = g_raid3_add_disk(sc, pp, &md);
329	if (error != 0)
330		gctl_error(req, "Cannot reconnect component %s.", pp->name);
331	sx_xunlock(&sc->sc_lock);
332}
333
334static void
335g_raid3_ctl_stop(struct gctl_req *req, struct g_class *mp)
336{
337	struct g_raid3_softc *sc;
338	int *force, *nargs, error;
339	const char *name;
340	char param[16];
341	u_int i;
342	int how;
343
344	nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
345	if (nargs == NULL) {
346		gctl_error(req, "No '%s' argument.", "nargs");
347		return;
348	}
349	if (*nargs < 1) {
350		gctl_error(req, "Missing device(s).");
351		return;
352	}
353	force = gctl_get_paraml(req, "force", sizeof(*force));
354	if (force == NULL) {
355		gctl_error(req, "No '%s' argument.", "force");
356		return;
357	}
358	if (*force)
359		how = G_RAID3_DESTROY_HARD;
360	else
361		how = G_RAID3_DESTROY_SOFT;
362
363	for (i = 0; i < (u_int)*nargs; i++) {
364		snprintf(param, sizeof(param), "arg%u", i);
365		name = gctl_get_asciiparam(req, param);
366		if (name == NULL) {
367			gctl_error(req, "No 'arg%u' argument.", i);
368			return;
369		}
370		sc = g_raid3_find_device(mp, name);
371		if (sc == NULL) {
372			gctl_error(req, "No such device: %s.", name);
373			return;
374		}
375		g_cancel_event(sc);
376		error = g_raid3_destroy(sc, how);
377		if (error != 0) {
378			gctl_error(req, "Cannot destroy device %s (error=%d).",
379			    sc->sc_geom->name, error);
380			sx_xunlock(&sc->sc_lock);
381			return;
382		}
383		/* No need to unlock, because lock is already dead. */
384	}
385}
386
387static void
388g_raid3_ctl_insert_orphan(struct g_consumer *cp)
389{
390
391	KASSERT(1 == 0, ("%s called while inserting %s.", __func__,
392	    cp->provider->name));
393}
394
395static void
396g_raid3_ctl_insert(struct gctl_req *req, struct g_class *mp)
397{
398	struct g_raid3_metadata md;
399	struct g_raid3_softc *sc;
400	struct g_raid3_disk *disk;
401	struct g_geom *gp;
402	struct g_provider *pp;
403	struct g_consumer *cp;
404	const char *name;
405	u_char *sector;
406	off_t compsize;
407	intmax_t *no;
408	int *hardcode, *nargs, error, autono;
409
410	nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
411	if (nargs == NULL) {
412		gctl_error(req, "No '%s' argument.", "nargs");
413		return;
414	}
415	if (*nargs != 2) {
416		gctl_error(req, "Invalid number of arguments.");
417		return;
418	}
419	hardcode = gctl_get_paraml(req, "hardcode", sizeof(*hardcode));
420	if (hardcode == NULL) {
421		gctl_error(req, "No '%s' argument.", "hardcode");
422		return;
423	}
424	pp = gctl_get_provider(req, "arg1");
425	if (pp == NULL)
426		return;
427	if (gctl_get_param(req, "number", NULL) != NULL)
428		no = gctl_get_paraml(req, "number", sizeof(*no));
429	else
430		no = NULL;
431	gp = g_new_geomf(mp, "raid3:insert");
432	gp->orphan = g_raid3_ctl_insert_orphan;
433	cp = g_new_consumer(gp);
434	error = g_attach(cp, pp);
435	if (error != 0) {
436		g_topology_unlock();
437		gctl_error(req, "Cannot attach to %s.", pp->name);
438		goto end;
439	}
440	error = g_access(cp, 0, 1, 1);
441	if (error != 0) {
442		g_topology_unlock();
443		gctl_error(req, "Cannot access %s.", pp->name);
444		goto end;
445	}
446	g_topology_unlock();
447	name = gctl_get_asciiparam(req, "arg0");
448	if (name == NULL) {
449		gctl_error(req, "No 'arg%u' argument.", 0);
450		goto end;
451	}
452	sc = g_raid3_find_device(mp, name);
453	if (sc == NULL) {
454		gctl_error(req, "No such device: %s.", name);
455		goto end;
456	}
457	if (no != NULL) {
458		if (*no < 0 || *no >= sc->sc_ndisks) {
459			sx_xunlock(&sc->sc_lock);
460			gctl_error(req, "Invalid component number.");
461			goto end;
462		}
463		disk = &sc->sc_disks[*no];
464		if (disk->d_state != G_RAID3_DISK_STATE_NODISK) {
465			sx_xunlock(&sc->sc_lock);
466			gctl_error(req, "Component %jd is already connected.",
467			    *no);
468			goto end;
469		}
470	} else {
471		disk = NULL;
472		for (autono = 0; autono < sc->sc_ndisks && disk == NULL; autono++)
473			if (sc->sc_disks[autono].d_state ==
474			    G_RAID3_DISK_STATE_NODISK)
475				disk = &sc->sc_disks[autono];
476		if (disk == NULL) {
477			sx_xunlock(&sc->sc_lock);
478			gctl_error(req, "No disconnected components.");
479			goto end;
480		}
481	}
482	if (((sc->sc_sectorsize / (sc->sc_ndisks - 1)) % pp->sectorsize) != 0) {
483		sx_xunlock(&sc->sc_lock);
484		gctl_error(req,
485		    "Cannot insert provider %s, because of its sector size.",
486		    pp->name);
487		goto end;
488	}
489	compsize = sc->sc_mediasize / (sc->sc_ndisks - 1);
490	if (compsize > pp->mediasize - pp->sectorsize) {
491		sx_xunlock(&sc->sc_lock);
492		gctl_error(req, "Provider %s too small.", pp->name);
493		goto end;
494	}
495	if (compsize < pp->mediasize - pp->sectorsize) {
496		gctl_error(req,
497		    "warning: %s: only %jd bytes from %jd bytes used.",
498		    pp->name, (intmax_t)compsize,
499		    (intmax_t)(pp->mediasize - pp->sectorsize));
500	}
501	g_raid3_fill_metadata(disk, &md);
502	sx_xunlock(&sc->sc_lock);
503	md.md_syncid = 0;
504	md.md_dflags = 0;
505	if (*hardcode)
506		strlcpy(md.md_provider, pp->name, sizeof(md.md_provider));
507	else
508		bzero(md.md_provider, sizeof(md.md_provider));
509	md.md_provsize = pp->mediasize;
510	sector = g_malloc(pp->sectorsize, M_WAITOK);
511	raid3_metadata_encode(&md, sector);
512	error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector,
513	    pp->sectorsize);
514	g_free(sector);
515	if (error != 0)
516		gctl_error(req, "Cannot store metadata on %s.", pp->name);
517end:
518	g_topology_lock();
519	if (cp->acw > 0)
520		g_access(cp, 0, -1, -1);
521	if (cp->provider != NULL)
522		g_detach(cp);
523	g_destroy_consumer(cp);
524	g_destroy_geom(gp);
525	g_topology_unlock();
526}
527
528static void
529g_raid3_ctl_remove(struct gctl_req *req, struct g_class *mp)
530{
531	struct g_raid3_softc *sc;
532	struct g_raid3_disk *disk;
533	const char *name;
534	intmax_t *no;
535	int *nargs;
536
537	nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
538	if (nargs == NULL) {
539		gctl_error(req, "No '%s' argument.", "nargs");
540		return;
541	}
542	if (*nargs != 1) {
543		gctl_error(req, "Invalid number of arguments.");
544		return;
545	}
546	no = gctl_get_paraml(req, "number", sizeof(*no));
547	if (no == NULL) {
548		gctl_error(req, "No '%s' argument.", "no");
549		return;
550	}
551	name = gctl_get_asciiparam(req, "arg0");
552	if (name == NULL) {
553		gctl_error(req, "No 'arg%u' argument.", 0);
554		return;
555	}
556	sc = g_raid3_find_device(mp, name);
557	if (sc == NULL) {
558		gctl_error(req, "No such device: %s.", name);
559		return;
560	}
561	if (*no >= sc->sc_ndisks) {
562		sx_xunlock(&sc->sc_lock);
563		gctl_error(req, "Invalid component number.");
564		return;
565	}
566	disk = &sc->sc_disks[*no];
567	switch (disk->d_state) {
568	case G_RAID3_DISK_STATE_ACTIVE:
569		/*
570		 * When replacing ACTIVE component, all the rest has to be also
571		 * ACTIVE.
572		 */
573		if (g_raid3_ndisks(sc, G_RAID3_DISK_STATE_ACTIVE) <
574		    sc->sc_ndisks) {
575			gctl_error(req, "Cannot replace component number %jd.",
576			    *no);
577			break;
578		}
579		/* FALLTHROUGH */
580	case G_RAID3_DISK_STATE_STALE:
581	case G_RAID3_DISK_STATE_SYNCHRONIZING:
582		if (g_raid3_clear_metadata(disk) != 0) {
583			gctl_error(req, "Cannot clear metadata on %s.",
584			    g_raid3_get_diskname(disk));
585		} else {
586			g_raid3_event_send(disk,
587			    G_RAID3_DISK_STATE_DISCONNECTED,
588			    G_RAID3_EVENT_DONTWAIT);
589		}
590		break;
591	case G_RAID3_DISK_STATE_NODISK:
592		break;
593	default:
594		gctl_error(req, "Cannot replace component number %jd.", *no);
595		break;
596	}
597	sx_xunlock(&sc->sc_lock);
598}
599
600void
601g_raid3_config(struct gctl_req *req, struct g_class *mp, const char *verb)
602{
603	uint32_t *version;
604
605	g_topology_assert();
606
607	version = gctl_get_paraml(req, "version", sizeof(*version));
608	if (version == NULL) {
609		gctl_error(req, "No '%s' argument.", "version");
610		return;
611	}
612	if (*version != G_RAID3_VERSION) {
613		gctl_error(req, "Userland and kernel parts are out of sync.");
614		return;
615	}
616
617	g_topology_unlock();
618	if (strcmp(verb, "configure") == 0)
619		g_raid3_ctl_configure(req, mp);
620	else if (strcmp(verb, "insert") == 0)
621		g_raid3_ctl_insert(req, mp);
622	else if (strcmp(verb, "rebuild") == 0)
623		g_raid3_ctl_rebuild(req, mp);
624	else if (strcmp(verb, "remove") == 0)
625		g_raid3_ctl_remove(req, mp);
626	else if (strcmp(verb, "stop") == 0)
627		g_raid3_ctl_stop(req, mp);
628	else
629		gctl_error(req, "Unknown verb.");
630	g_topology_lock();
631}
632