]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/geom/geom_disk.c
Merge diff elimination updates from r355953 into vendor/llvm-project.
[FreeBSD/FreeBSD.git] / sys / geom / geom_disk.c
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (c) 2002 Poul-Henning Kamp
5  * Copyright (c) 2002 Networks Associates Technology, Inc.
6  * All rights reserved.
7  *
8  * This software was developed for the FreeBSD Project by Poul-Henning Kamp
9  * and NAI Labs, the Security Research Division of Network Associates, Inc.
10  * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
11  * DARPA CHATS research program.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  *    notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the
20  *    documentation and/or other materials provided with the distribution.
21  * 3. The names of the authors may not be used to endorse or promote
22  *    products derived from this software without specific prior written
23  *    permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  */
37
38 #include <sys/cdefs.h>
39 __FBSDID("$FreeBSD$");
40
41 #include "opt_geom.h"
42
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/kernel.h>
46 #include <sys/sysctl.h>
47 #include <sys/bio.h>
48 #include <sys/bus.h>
49 #include <sys/ctype.h>
50 #include <sys/fcntl.h>
51 #include <sys/malloc.h>
52 #include <sys/sbuf.h>
53 #include <sys/devicestat.h>
54 #include <machine/md_var.h>
55
56 #include <sys/lock.h>
57 #include <sys/mutex.h>
58 #include <geom/geom.h>
59 #include <geom/geom_disk.h>
60 #include <geom/geom_int.h>
61
62 #include <dev/led/led.h>
63
64 #include <machine/bus.h>
65
66 struct g_disk_softc {
67         struct mtx               done_mtx;
68         struct disk             *dp;
69         struct sysctl_ctx_list  sysctl_ctx;
70         struct sysctl_oid       *sysctl_tree;
71         char                    led[64];
72         uint32_t                state;
73         struct mtx               start_mtx;
74 };
75
76 static g_access_t g_disk_access;
77 static g_start_t g_disk_start;
78 static g_ioctl_t g_disk_ioctl;
79 static g_dumpconf_t g_disk_dumpconf;
80 static g_provgone_t g_disk_providergone;
81
82 static int g_disk_sysctl_flags(SYSCTL_HANDLER_ARGS);
83
84 static struct g_class g_disk_class = {
85         .name = G_DISK_CLASS_NAME,
86         .version = G_VERSION,
87         .start = g_disk_start,
88         .access = g_disk_access,
89         .ioctl = g_disk_ioctl,
90         .providergone = g_disk_providergone,
91         .dumpconf = g_disk_dumpconf,
92 };
93
94 SYSCTL_DECL(_kern_geom);
95 static SYSCTL_NODE(_kern_geom, OID_AUTO, disk, CTLFLAG_RW, 0,
96     "GEOM_DISK stuff");
97
98 DECLARE_GEOM_CLASS(g_disk_class, g_disk);
99
100 static int
101 g_disk_access(struct g_provider *pp, int r, int w, int e)
102 {
103         struct disk *dp;
104         struct g_disk_softc *sc;
105         int error;
106
107         g_trace(G_T_ACCESS, "g_disk_access(%s, %d, %d, %d)",
108             pp->name, r, w, e);
109         g_topology_assert();
110         sc = pp->private;
111         if ((dp = sc->dp) == NULL || dp->d_destroyed) {
112                 /*
113                  * Allow decreasing access count even if disk is not
114                  * available anymore.
115                  */
116                 if (r <= 0 && w <= 0 && e <= 0)
117                         return (0);
118                 return (ENXIO);
119         }
120         r += pp->acr;
121         w += pp->acw;
122         e += pp->ace;
123         error = 0;
124         if ((pp->acr + pp->acw + pp->ace) == 0 && (r + w + e) > 0) {
125                 /*
126                  * It would be better to defer this decision to d_open if
127                  * it was able to take flags.
128                  */
129                 if (w > 0 && (dp->d_flags & DISKFLAG_WRITE_PROTECT) != 0)
130                         error = EROFS;
131                 if (error == 0 && dp->d_open != NULL)
132                         error = dp->d_open(dp);
133                 if (bootverbose && error != 0)
134                         printf("Opened disk %s -> %d\n", pp->name, error);
135                 if (error != 0)
136                         return (error);
137                 pp->sectorsize = dp->d_sectorsize;
138                 if (dp->d_maxsize == 0) {
139                         printf("WARNING: Disk drive %s%d has no d_maxsize\n",
140                             dp->d_name, dp->d_unit);
141                         dp->d_maxsize = DFLTPHYS;
142                 }
143                 if (dp->d_delmaxsize == 0) {
144                         if (bootverbose && dp->d_flags & DISKFLAG_CANDELETE) {
145                                 printf("WARNING: Disk drive %s%d has no "
146                                     "d_delmaxsize\n", dp->d_name, dp->d_unit);
147                         }
148                         dp->d_delmaxsize = dp->d_maxsize;
149                 }
150                 pp->stripeoffset = dp->d_stripeoffset;
151                 pp->stripesize = dp->d_stripesize;
152                 dp->d_flags |= DISKFLAG_OPEN;
153                 /*
154                  * Do not invoke resize event when initial size was zero.
155                  * Some disks report its size only after first opening.
156                  */
157                 if (pp->mediasize == 0)
158                         pp->mediasize = dp->d_mediasize;
159                 else
160                         g_resize_provider(pp, dp->d_mediasize);
161         } else if ((pp->acr + pp->acw + pp->ace) > 0 && (r + w + e) == 0) {
162                 if (dp->d_close != NULL) {
163                         error = dp->d_close(dp);
164                         if (error != 0)
165                                 printf("Closed disk %s -> %d\n",
166                                     pp->name, error);
167                 }
168                 sc->state = G_STATE_ACTIVE;
169                 if (sc->led[0] != 0)
170                         led_set(sc->led, "0");
171                 dp->d_flags &= ~DISKFLAG_OPEN;
172         }
173         return (error);
174 }
175
176 static void
177 g_disk_kerneldump(struct bio *bp, struct disk *dp)
178 {
179         struct g_kerneldump *gkd;
180         struct g_geom *gp;
181
182         gkd = (struct g_kerneldump*)bp->bio_data;
183         gp = bp->bio_to->geom;
184         g_trace(G_T_TOPOLOGY, "g_disk_kerneldump(%s, %jd, %jd)",
185                 gp->name, (intmax_t)gkd->offset, (intmax_t)gkd->length);
186         if (dp->d_dump == NULL) {
187                 g_io_deliver(bp, ENODEV);
188                 return;
189         }
190         gkd->di.dumper = dp->d_dump;
191         gkd->di.priv = dp;
192         gkd->di.blocksize = dp->d_sectorsize;
193         gkd->di.maxiosize = dp->d_maxsize;
194         gkd->di.mediaoffset = gkd->offset;
195         if ((gkd->offset + gkd->length) > dp->d_mediasize)
196                 gkd->length = dp->d_mediasize - gkd->offset;
197         gkd->di.mediasize = gkd->length;
198         g_io_deliver(bp, 0);
199 }
200
201 static void
202 g_disk_setstate(struct bio *bp, struct g_disk_softc *sc)
203 {
204         const char *cmd;
205
206         memcpy(&sc->state, bp->bio_data, sizeof(sc->state));
207         if (sc->led[0] != 0) {
208                 switch (sc->state) {
209                 case G_STATE_FAILED:
210                         cmd = "1";
211                         break;
212                 case G_STATE_REBUILD:
213                         cmd = "f5";
214                         break;
215                 case G_STATE_RESYNC:
216                         cmd = "f1";
217                         break;
218                 default:
219                         cmd = "0";
220                         break;
221                 }
222                 led_set(sc->led, cmd);
223         }
224         g_io_deliver(bp, 0);
225 }
226
227 static void
228 g_disk_done(struct bio *bp)
229 {
230         struct bintime now;
231         struct bio *bp2;
232         struct g_disk_softc *sc;
233
234         /* See "notes" for why we need a mutex here */
235         /* XXX: will witness accept a mix of Giant/unGiant drivers here ? */
236         bp2 = bp->bio_parent;
237         sc = bp2->bio_to->private;
238         bp->bio_completed = bp->bio_length - bp->bio_resid;
239         binuptime(&now);
240         mtx_lock(&sc->done_mtx);
241         if (bp2->bio_error == 0)
242                 bp2->bio_error = bp->bio_error;
243         bp2->bio_completed += bp->bio_completed;
244
245         switch (bp->bio_cmd) {
246         case BIO_ZONE:
247                 bcopy(&bp->bio_zone, &bp2->bio_zone, sizeof(bp->bio_zone));
248                 /*FALLTHROUGH*/
249         case BIO_READ:
250         case BIO_WRITE:
251         case BIO_DELETE:
252         case BIO_FLUSH:
253                 devstat_end_transaction_bio_bt(sc->dp->d_devstat, bp, &now);
254                 break;
255         default:
256                 break;
257         }
258         bp2->bio_inbed++;
259         if (bp2->bio_children == bp2->bio_inbed) {
260                 mtx_unlock(&sc->done_mtx);
261                 bp2->bio_resid = bp2->bio_bcount - bp2->bio_completed;
262                 g_io_deliver(bp2, bp2->bio_error);
263         } else
264                 mtx_unlock(&sc->done_mtx);
265         g_destroy_bio(bp);
266 }
267
268 static int
269 g_disk_ioctl(struct g_provider *pp, u_long cmd, void * data, int fflag, struct thread *td)
270 {
271         struct disk *dp;
272         struct g_disk_softc *sc;
273         int error;
274
275         sc = pp->private;
276         dp = sc->dp;
277         KASSERT(dp != NULL && !dp->d_destroyed,
278             ("g_disk_ioctl(%lx) on destroyed disk %s", cmd, pp->name));
279
280         if (dp->d_ioctl == NULL)
281                 return (ENOIOCTL);
282         error = dp->d_ioctl(dp, cmd, data, fflag, td);
283         return (error);
284 }
285
286 static off_t
287 g_disk_maxsize(struct disk *dp, struct bio *bp)
288 {
289         if (bp->bio_cmd == BIO_DELETE)
290                 return (dp->d_delmaxsize);
291         return (dp->d_maxsize);
292 }
293
294 static int
295 g_disk_maxsegs(struct disk *dp, struct bio *bp)
296 {
297         return ((g_disk_maxsize(dp, bp) / PAGE_SIZE) + 1);
298 }
299
300 static void
301 g_disk_advance(struct disk *dp, struct bio *bp, off_t off)
302 {
303
304         bp->bio_offset += off;
305         bp->bio_length -= off;
306
307         if ((bp->bio_flags & BIO_VLIST) != 0) {
308                 bus_dma_segment_t *seg, *end;
309
310                 seg = (bus_dma_segment_t *)bp->bio_data;
311                 end = (bus_dma_segment_t *)bp->bio_data + bp->bio_ma_n;
312                 off += bp->bio_ma_offset;
313                 while (off >= seg->ds_len) {
314                         KASSERT((seg != end),
315                             ("vlist request runs off the end"));
316                         off -= seg->ds_len;
317                         seg++;
318                 }
319                 bp->bio_ma_offset = off;
320                 bp->bio_ma_n = end - seg;
321                 bp->bio_data = (void *)seg;
322         } else if ((bp->bio_flags & BIO_UNMAPPED) != 0) {
323                 bp->bio_ma += off / PAGE_SIZE;
324                 bp->bio_ma_offset += off;
325                 bp->bio_ma_offset %= PAGE_SIZE;
326                 bp->bio_ma_n -= off / PAGE_SIZE;
327         } else {
328                 bp->bio_data += off;
329         }
330 }
331
332 static void
333 g_disk_seg_limit(bus_dma_segment_t *seg, off_t *poffset,
334     off_t *plength, int *ppages)
335 {
336         uintptr_t seg_page_base;
337         uintptr_t seg_page_end;
338         off_t offset;
339         off_t length;
340         int seg_pages;
341
342         offset = *poffset;
343         length = *plength;
344
345         if (length > seg->ds_len - offset)
346                 length = seg->ds_len - offset;
347
348         seg_page_base = trunc_page(seg->ds_addr + offset);
349         seg_page_end  = round_page(seg->ds_addr + offset + length);
350         seg_pages = (seg_page_end - seg_page_base) >> PAGE_SHIFT;
351
352         if (seg_pages > *ppages) {
353                 seg_pages = *ppages;
354                 length = (seg_page_base + (seg_pages << PAGE_SHIFT)) -
355                     (seg->ds_addr + offset);
356         }
357
358         *poffset = 0;
359         *plength -= length;
360         *ppages -= seg_pages;
361 }
362
363 static off_t
364 g_disk_vlist_limit(struct disk *dp, struct bio *bp, bus_dma_segment_t **pendseg)
365 {
366         bus_dma_segment_t *seg, *end;
367         off_t residual;
368         off_t offset;
369         int pages;
370
371         seg = (bus_dma_segment_t *)bp->bio_data;
372         end = (bus_dma_segment_t *)bp->bio_data + bp->bio_ma_n;
373         residual = bp->bio_length;
374         offset = bp->bio_ma_offset;
375         pages = g_disk_maxsegs(dp, bp);
376         while (residual != 0 && pages != 0) {
377                 KASSERT((seg != end),
378                     ("vlist limit runs off the end"));
379                 g_disk_seg_limit(seg, &offset, &residual, &pages);
380                 seg++;
381         }
382         if (pendseg != NULL)
383                 *pendseg = seg;
384         return (residual);
385 }
386
387 static bool
388 g_disk_limit(struct disk *dp, struct bio *bp)
389 {
390         bool limited = false;
391         off_t maxsz;
392
393         maxsz = g_disk_maxsize(dp, bp);
394
395         /*
396          * XXX: If we have a stripesize we should really use it here.
397          *      Care should be taken in the delete case if this is done
398          *      as deletes can be very sensitive to size given how they
399          *      are processed.
400          */
401         if (bp->bio_length > maxsz) {
402                 bp->bio_length = maxsz;
403                 limited = true;
404         }
405
406         if ((bp->bio_flags & BIO_VLIST) != 0) {
407                 bus_dma_segment_t *firstseg, *endseg;
408                 off_t residual;
409
410                 firstseg = (bus_dma_segment_t*)bp->bio_data;
411                 residual = g_disk_vlist_limit(dp, bp, &endseg);
412                 if (residual != 0) {
413                         bp->bio_ma_n = endseg - firstseg;
414                         bp->bio_length -= residual;
415                         limited = true;
416                 }
417         } else if ((bp->bio_flags & BIO_UNMAPPED) != 0) {
418                 bp->bio_ma_n =
419                     howmany(bp->bio_ma_offset + bp->bio_length, PAGE_SIZE);
420         }
421
422         return (limited);
423 }
424
425 static void
426 g_disk_start(struct bio *bp)
427 {
428         struct bio *bp2, *bp3;
429         struct disk *dp;
430         struct g_disk_softc *sc;
431         int error;
432         off_t off;
433
434         biotrack(bp, __func__);
435
436         sc = bp->bio_to->private;
437         dp = sc->dp;
438         KASSERT(dp != NULL && !dp->d_destroyed,
439             ("g_disk_start(%p) on destroyed disk %s", bp, bp->bio_to->name));
440         error = EJUSTRETURN;
441         switch(bp->bio_cmd) {
442         case BIO_DELETE:
443                 if (!(dp->d_flags & DISKFLAG_CANDELETE)) {
444                         error = EOPNOTSUPP;
445                         break;
446                 }
447                 /* fall-through */
448         case BIO_READ:
449         case BIO_WRITE:
450                 KASSERT((dp->d_flags & DISKFLAG_UNMAPPED_BIO) != 0 ||
451                     (bp->bio_flags & BIO_UNMAPPED) == 0,
452                     ("unmapped bio not supported by disk %s", dp->d_name));
453                 off = 0;
454                 bp3 = NULL;
455                 bp2 = g_clone_bio(bp);
456                 if (bp2 == NULL) {
457                         error = ENOMEM;
458                         break;
459                 }
460                 for (;;) {
461                         if (g_disk_limit(dp, bp2)) {
462                                 off += bp2->bio_length;
463
464                                 /*
465                                  * To avoid a race, we need to grab the next bio
466                                  * before we schedule this one.  See "notes".
467                                  */
468                                 bp3 = g_clone_bio(bp);
469                                 if (bp3 == NULL)
470                                         bp->bio_error = ENOMEM;
471                         }
472                         bp2->bio_done = g_disk_done;
473                         bp2->bio_pblkno = bp2->bio_offset / dp->d_sectorsize;
474                         bp2->bio_bcount = bp2->bio_length;
475                         bp2->bio_disk = dp;
476                         mtx_lock(&sc->start_mtx); 
477                         devstat_start_transaction_bio(dp->d_devstat, bp2);
478                         mtx_unlock(&sc->start_mtx); 
479                         dp->d_strategy(bp2);
480
481                         if (bp3 == NULL)
482                                 break;
483
484                         bp2 = bp3;
485                         bp3 = NULL;
486                         g_disk_advance(dp, bp2, off);
487                 }
488                 break;
489         case BIO_GETATTR:
490                 /* Give the driver a chance to override */
491                 if (dp->d_getattr != NULL) {
492                         if (bp->bio_disk == NULL)
493                                 bp->bio_disk = dp;
494                         error = dp->d_getattr(bp);
495                         if (error != -1)
496                                 break;
497                         error = EJUSTRETURN;
498                 }
499                 if (g_handleattr_int(bp, "GEOM::candelete",
500                     (dp->d_flags & DISKFLAG_CANDELETE) != 0))
501                         break;
502                 else if (g_handleattr_int(bp, "GEOM::fwsectors",
503                     dp->d_fwsectors))
504                         break;
505                 else if (g_handleattr_int(bp, "GEOM::fwheads", dp->d_fwheads))
506                         break;
507                 else if (g_handleattr_off_t(bp, "GEOM::frontstuff", 0))
508                         break;
509                 else if (g_handleattr_str(bp, "GEOM::ident", dp->d_ident))
510                         break;
511                 else if (g_handleattr_str(bp, "GEOM::descr", dp->d_descr))
512                         break;
513                 else if (g_handleattr_uint16_t(bp, "GEOM::hba_vendor",
514                     dp->d_hba_vendor))
515                         break;
516                 else if (g_handleattr_uint16_t(bp, "GEOM::hba_device",
517                     dp->d_hba_device))
518                         break;
519                 else if (g_handleattr_uint16_t(bp, "GEOM::hba_subvendor",
520                     dp->d_hba_subvendor))
521                         break;
522                 else if (g_handleattr_uint16_t(bp, "GEOM::hba_subdevice",
523                     dp->d_hba_subdevice))
524                         break;
525                 else if (!strcmp(bp->bio_attribute, "GEOM::kerneldump"))
526                         g_disk_kerneldump(bp, dp);
527                 else if (!strcmp(bp->bio_attribute, "GEOM::setstate"))
528                         g_disk_setstate(bp, sc);
529                 else if (g_handleattr_uint16_t(bp, "GEOM::rotation_rate",
530                     dp->d_rotation_rate))
531                         break;
532                 else if (g_handleattr_str(bp, "GEOM::attachment",
533                     dp->d_attachment))
534                         break;
535                 else
536                         error = ENOIOCTL;
537                 break;
538         case BIO_FLUSH:
539                 g_trace(G_T_BIO, "g_disk_flushcache(%s)",
540                     bp->bio_to->name);
541                 if (!(dp->d_flags & DISKFLAG_CANFLUSHCACHE)) {
542                         error = EOPNOTSUPP;
543                         break;
544                 }
545                 /*FALLTHROUGH*/
546         case BIO_ZONE:
547                 if (bp->bio_cmd == BIO_ZONE) {
548                         if (!(dp->d_flags & DISKFLAG_CANZONE)) {
549                                 error = EOPNOTSUPP;
550                                 break;
551                         }
552                         g_trace(G_T_BIO, "g_disk_zone(%s)",
553                             bp->bio_to->name);
554                 }
555                 bp2 = g_clone_bio(bp);
556                 if (bp2 == NULL) {
557                         g_io_deliver(bp, ENOMEM);
558                         return;
559                 }
560                 bp2->bio_done = g_disk_done;
561                 bp2->bio_disk = dp;
562                 mtx_lock(&sc->start_mtx);
563                 devstat_start_transaction_bio(dp->d_devstat, bp2);
564                 mtx_unlock(&sc->start_mtx);
565                 dp->d_strategy(bp2);
566                 break;
567         default:
568                 error = EOPNOTSUPP;
569                 break;
570         }
571         if (error != EJUSTRETURN)
572                 g_io_deliver(bp, error);
573         return;
574 }
575
576 static void
577 g_disk_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, struct g_consumer *cp, struct g_provider *pp)
578 {
579         struct bio *bp;
580         struct disk *dp;
581         struct g_disk_softc *sc;
582         char *buf;
583         int res = 0;
584
585         sc = gp->softc;
586         if (sc == NULL || (dp = sc->dp) == NULL)
587                 return;
588         if (indent == NULL) {
589                 sbuf_printf(sb, " hd %u", dp->d_fwheads);
590                 sbuf_printf(sb, " sc %u", dp->d_fwsectors);
591                 return;
592         }
593         if (pp != NULL) {
594                 sbuf_printf(sb, "%s<fwheads>%u</fwheads>\n",
595                     indent, dp->d_fwheads);
596                 sbuf_printf(sb, "%s<fwsectors>%u</fwsectors>\n",
597                     indent, dp->d_fwsectors);
598
599                 /*
600                  * "rotationrate" is a little complicated, because the value
601                  * returned by the drive might not be the RPM; 0 and 1 are
602                  * special cases, and there's also a valid range.
603                  */
604                 sbuf_printf(sb, "%s<rotationrate>", indent);
605                 if (dp->d_rotation_rate == DISK_RR_UNKNOWN) /* Old drives */
606                         sbuf_cat(sb, "unknown");        /* don't report RPM. */
607                 else if (dp->d_rotation_rate == DISK_RR_NON_ROTATING)
608                         sbuf_cat(sb, "0");
609                 else if ((dp->d_rotation_rate >= DISK_RR_MIN) &&
610                     (dp->d_rotation_rate <= DISK_RR_MAX))
611                         sbuf_printf(sb, "%u", dp->d_rotation_rate);
612                 else
613                         sbuf_cat(sb, "invalid");
614                 sbuf_cat(sb, "</rotationrate>\n");
615                 if (dp->d_getattr != NULL) {
616                         buf = g_malloc(DISK_IDENT_SIZE, M_WAITOK);
617                         bp = g_alloc_bio();
618                         bp->bio_disk = dp;
619                         bp->bio_attribute = "GEOM::ident";
620                         bp->bio_length = DISK_IDENT_SIZE;
621                         bp->bio_data = buf;
622                         res = dp->d_getattr(bp);
623                         sbuf_printf(sb, "%s<ident>", indent);
624                         g_conf_cat_escaped(sb, res == 0 ? buf : dp->d_ident);
625                         sbuf_cat(sb, "</ident>\n");
626                         bp->bio_attribute = "GEOM::lunid";
627                         bp->bio_length = DISK_IDENT_SIZE;
628                         bp->bio_data = buf;
629                         if (dp->d_getattr(bp) == 0) {
630                                 sbuf_printf(sb, "%s<lunid>", indent);
631                                 g_conf_cat_escaped(sb, buf);
632                                 sbuf_cat(sb, "</lunid>\n");
633                         }
634                         bp->bio_attribute = "GEOM::lunname";
635                         bp->bio_length = DISK_IDENT_SIZE;
636                         bp->bio_data = buf;
637                         if (dp->d_getattr(bp) == 0) {
638                                 sbuf_printf(sb, "%s<lunname>", indent);
639                                 g_conf_cat_escaped(sb, buf);
640                                 sbuf_cat(sb, "</lunname>\n");
641                         }
642                         g_destroy_bio(bp);
643                         g_free(buf);
644                 } else {
645                         sbuf_printf(sb, "%s<ident>", indent);
646                         g_conf_cat_escaped(sb, dp->d_ident);
647                         sbuf_cat(sb, "</ident>\n");
648                 }
649                 sbuf_printf(sb, "%s<descr>", indent);
650                 g_conf_cat_escaped(sb, dp->d_descr);
651                 sbuf_cat(sb, "</descr>\n");
652         }
653 }
654
655 static void
656 g_disk_resize(void *ptr, int flag)
657 {
658         struct disk *dp;
659         struct g_geom *gp;
660         struct g_provider *pp;
661
662         if (flag == EV_CANCEL)
663                 return;
664         g_topology_assert();
665
666         dp = ptr;
667         gp = dp->d_geom;
668
669         if (dp->d_destroyed || gp == NULL)
670                 return;
671
672         LIST_FOREACH(pp, &gp->provider, provider) {
673                 if (pp->sectorsize != 0 &&
674                     pp->sectorsize != dp->d_sectorsize)
675                         g_wither_provider(pp, ENXIO);
676                 else
677                         g_resize_provider(pp, dp->d_mediasize);
678         }
679 }
680
681 static void
682 g_disk_create(void *arg, int flag)
683 {
684         struct g_geom *gp;
685         struct g_provider *pp;
686         struct disk *dp;
687         struct g_disk_softc *sc;
688         struct disk_alias *dap;
689         char tmpstr[80];
690
691         if (flag == EV_CANCEL)
692                 return;
693         g_topology_assert();
694         dp = arg;
695
696         mtx_pool_lock(mtxpool_sleep, dp);
697         dp->d_init_level = DISK_INIT_START;
698
699         /*
700          * If the disk has already gone away, we can just stop here and
701          * call the user's callback to tell him we've cleaned things up.
702          */
703         if (dp->d_goneflag != 0) {
704                 mtx_pool_unlock(mtxpool_sleep, dp);
705                 if (dp->d_gone != NULL)
706                         dp->d_gone(dp);
707                 return;
708         }
709         mtx_pool_unlock(mtxpool_sleep, dp);
710
711         sc = g_malloc(sizeof(*sc), M_WAITOK | M_ZERO);
712         mtx_init(&sc->start_mtx, "g_disk_start", NULL, MTX_DEF);
713         mtx_init(&sc->done_mtx, "g_disk_done", NULL, MTX_DEF);
714         sc->dp = dp;
715         gp = g_new_geomf(&g_disk_class, "%s%d", dp->d_name, dp->d_unit);
716         gp->softc = sc;
717         LIST_FOREACH(dap, &dp->d_aliases, da_next) {
718                 snprintf(tmpstr, sizeof(tmpstr), "%s%d", dap->da_alias, dp->d_unit);
719                 g_geom_add_alias(gp, tmpstr);
720         }
721         pp = g_new_providerf(gp, "%s", gp->name);
722         devstat_remove_entry(pp->stat);
723         pp->stat = NULL;
724         dp->d_devstat->id = pp;
725         pp->mediasize = dp->d_mediasize;
726         pp->sectorsize = dp->d_sectorsize;
727         pp->stripeoffset = dp->d_stripeoffset;
728         pp->stripesize = dp->d_stripesize;
729         if ((dp->d_flags & DISKFLAG_UNMAPPED_BIO) != 0)
730                 pp->flags |= G_PF_ACCEPT_UNMAPPED;
731         if ((dp->d_flags & DISKFLAG_DIRECT_COMPLETION) != 0)
732                 pp->flags |= G_PF_DIRECT_SEND;
733         pp->flags |= G_PF_DIRECT_RECEIVE;
734         if (bootverbose)
735                 printf("GEOM: new disk %s\n", gp->name);
736         sysctl_ctx_init(&sc->sysctl_ctx);
737         snprintf(tmpstr, sizeof(tmpstr), "GEOM disk %s", gp->name);
738         sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx,
739                 SYSCTL_STATIC_CHILDREN(_kern_geom_disk), OID_AUTO, gp->name,
740                 CTLFLAG_RD, 0, tmpstr);
741         if (sc->sysctl_tree != NULL) {
742                 SYSCTL_ADD_STRING(&sc->sysctl_ctx,
743                     SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO, "led",
744                     CTLFLAG_RWTUN, sc->led, sizeof(sc->led),
745                     "LED name");
746                 SYSCTL_ADD_PROC(&sc->sysctl_ctx,
747                     SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO, "flags",
748                     CTLTYPE_STRING | CTLFLAG_RD, dp, 0, g_disk_sysctl_flags,
749                     "A", "Report disk flags");
750         }
751         pp->private = sc;
752         dp->d_geom = gp;
753         g_error_provider(pp, 0);
754
755         mtx_pool_lock(mtxpool_sleep, dp);
756         dp->d_init_level = DISK_INIT_DONE;
757
758         /*
759          * If the disk has gone away at this stage, start the withering
760          * process for it.
761          */
762         if (dp->d_goneflag != 0) {
763                 mtx_pool_unlock(mtxpool_sleep, dp);
764                 g_wither_provider(pp, ENXIO);
765                 return;
766         }
767         mtx_pool_unlock(mtxpool_sleep, dp);
768
769 }
770
771 /*
772  * We get this callback after all of the consumers have gone away, and just
773  * before the provider is freed.  If the disk driver provided a d_gone
774  * callback, let them know that it is okay to free resources -- they won't
775  * be getting any more accesses from GEOM.
776  */
777 static void
778 g_disk_providergone(struct g_provider *pp)
779 {
780         struct disk *dp;
781         struct g_disk_softc *sc;
782
783         sc = (struct g_disk_softc *)pp->private;
784         dp = sc->dp;
785         if (dp != NULL && dp->d_gone != NULL)
786                 dp->d_gone(dp);
787         if (sc->sysctl_tree != NULL) {
788                 sysctl_ctx_free(&sc->sysctl_ctx);
789                 sc->sysctl_tree = NULL;
790         }
791         if (sc->led[0] != 0) {
792                 led_set(sc->led, "0");
793                 sc->led[0] = 0;
794         }
795         pp->private = NULL;
796         pp->geom->softc = NULL;
797         mtx_destroy(&sc->done_mtx);
798         mtx_destroy(&sc->start_mtx);
799         g_free(sc);
800 }
801
802 static void
803 g_disk_destroy(void *ptr, int flag)
804 {
805         struct disk *dp;
806         struct g_geom *gp;
807         struct g_disk_softc *sc;
808         struct disk_alias *dap, *daptmp;
809
810         g_topology_assert();
811         dp = ptr;
812         gp = dp->d_geom;
813         if (gp != NULL) {
814                 sc = gp->softc;
815                 if (sc != NULL)
816                         sc->dp = NULL;
817                 dp->d_geom = NULL;
818                 g_wither_geom(gp, ENXIO);
819         }
820         LIST_FOREACH_SAFE(dap, &dp->d_aliases, da_next, daptmp)
821                 g_free(dap);
822
823         g_free(dp);
824 }
825
826 /*
827  * We only allow printable characters in disk ident,
828  * the rest is converted to 'x<HH>'.
829  */
830 static void
831 g_disk_ident_adjust(char *ident, size_t size)
832 {
833         char *p, tmp[4], newid[DISK_IDENT_SIZE];
834
835         newid[0] = '\0';
836         for (p = ident; *p != '\0'; p++) {
837                 if (isprint(*p)) {
838                         tmp[0] = *p;
839                         tmp[1] = '\0';
840                 } else {
841                         snprintf(tmp, sizeof(tmp), "x%02hhx",
842                             *(unsigned char *)p);
843                 }
844                 if (strlcat(newid, tmp, sizeof(newid)) >= sizeof(newid))
845                         break;
846         }
847         bzero(ident, size);
848         strlcpy(ident, newid, size);
849 }
850
851 struct disk *
852 disk_alloc(void)
853 {
854         struct disk *dp;
855
856         dp = g_malloc(sizeof(struct disk), M_WAITOK | M_ZERO);
857         LIST_INIT(&dp->d_aliases);
858         return (dp);
859 }
860
861 void
862 disk_create(struct disk *dp, int version)
863 {
864
865         if (version != DISK_VERSION) {
866                 printf("WARNING: Attempt to add disk %s%d %s",
867                     dp->d_name, dp->d_unit,
868                     " using incompatible ABI version of disk(9)\n");
869                 printf("WARNING: Ignoring disk %s%d\n",
870                     dp->d_name, dp->d_unit);
871                 return;
872         }
873         if (dp->d_flags & DISKFLAG_RESERVED) {
874                 printf("WARNING: Attempt to add non-MPSAFE disk %s%d\n",
875                     dp->d_name, dp->d_unit);
876                 printf("WARNING: Ignoring disk %s%d\n",
877                     dp->d_name, dp->d_unit);
878                 return;
879         }
880         KASSERT(dp->d_strategy != NULL, ("disk_create need d_strategy"));
881         KASSERT(dp->d_name != NULL, ("disk_create need d_name"));
882         KASSERT(*dp->d_name != 0, ("disk_create need d_name"));
883         KASSERT(strlen(dp->d_name) < SPECNAMELEN - 4, ("disk name too long"));
884         if (dp->d_devstat == NULL)
885                 dp->d_devstat = devstat_new_entry(dp->d_name, dp->d_unit,
886                     dp->d_sectorsize, DEVSTAT_ALL_SUPPORTED,
887                     DEVSTAT_TYPE_DIRECT, DEVSTAT_PRIORITY_MAX);
888         dp->d_geom = NULL;
889
890         dp->d_init_level = DISK_INIT_NONE;
891
892         g_disk_ident_adjust(dp->d_ident, sizeof(dp->d_ident));
893         g_post_event(g_disk_create, dp, M_WAITOK, dp, NULL);
894 }
895
896 void
897 disk_destroy(struct disk *dp)
898 {
899
900         disk_gone(dp);
901         dp->d_destroyed = 1;
902         g_cancel_event(dp);
903         if (dp->d_devstat != NULL)
904                 devstat_remove_entry(dp->d_devstat);
905         g_post_event(g_disk_destroy, dp, M_WAITOK, NULL);
906 }
907
908 void
909 disk_add_alias(struct disk *dp, const char *name)
910 {
911         struct disk_alias *dap;
912
913         dap = (struct disk_alias *)g_malloc(
914                 sizeof(struct disk_alias) + strlen(name) + 1, M_WAITOK);
915         strcpy((char *)(dap + 1), name);
916         dap->da_alias = (const char *)(dap + 1);
917         LIST_INSERT_HEAD(&dp->d_aliases, dap, da_next);
918 }
919
920 void
921 disk_gone(struct disk *dp)
922 {
923         struct g_geom *gp;
924         struct g_provider *pp;
925
926         mtx_pool_lock(mtxpool_sleep, dp);
927
928         /*
929          * Second wither call makes no sense, plus we can not access the list
930          * of providers without topology lock after calling wither once.
931          */
932         if (dp->d_goneflag != 0) {
933                 mtx_pool_unlock(mtxpool_sleep, dp);
934                 return;
935         }
936
937         dp->d_goneflag = 1;
938
939         /*
940          * If we're still in the process of creating this disk (the
941          * g_disk_create() function is still queued, or is in
942          * progress), the init level will not yet be DISK_INIT_DONE.
943          *
944          * If that is the case, g_disk_create() will see d_goneflag
945          * and take care of cleaning things up.
946          *
947          * If the disk has already been created, we default to
948          * withering the provider as usual below.
949          *
950          * If the caller has not set a d_gone() callback, he will
951          * not be any worse off by returning here, because the geom
952          * has not been fully setup in any case.
953          */
954         if (dp->d_init_level < DISK_INIT_DONE) {
955                 mtx_pool_unlock(mtxpool_sleep, dp);
956                 return;
957         }
958         mtx_pool_unlock(mtxpool_sleep, dp);
959
960         gp = dp->d_geom;
961         pp = LIST_FIRST(&gp->provider);
962         if (pp != NULL) {
963                 KASSERT(LIST_NEXT(pp, provider) == NULL,
964                     ("geom %p has more than one provider", gp));
965                 g_wither_provider(pp, ENXIO);
966         }
967 }
968
969 void
970 disk_attr_changed(struct disk *dp, const char *attr, int flag)
971 {
972         struct g_geom *gp;
973         struct g_provider *pp;
974         char devnamebuf[128];
975
976         gp = dp->d_geom;
977         if (gp != NULL)
978                 LIST_FOREACH(pp, &gp->provider, provider)
979                         (void)g_attr_changed(pp, attr, flag);
980         snprintf(devnamebuf, sizeof(devnamebuf), "devname=%s%d", dp->d_name,
981             dp->d_unit);
982         devctl_notify("GEOM", "disk", attr, devnamebuf);
983 }
984
985 void
986 disk_media_changed(struct disk *dp, int flag)
987 {
988         struct g_geom *gp;
989         struct g_provider *pp;
990
991         gp = dp->d_geom;
992         if (gp != NULL) {
993                 pp = LIST_FIRST(&gp->provider);
994                 if (pp != NULL) {
995                         KASSERT(LIST_NEXT(pp, provider) == NULL,
996                             ("geom %p has more than one provider", gp));
997                         g_media_changed(pp, flag);
998                 }
999         }
1000 }
1001
1002 void
1003 disk_media_gone(struct disk *dp, int flag)
1004 {
1005         struct g_geom *gp;
1006         struct g_provider *pp;
1007
1008         gp = dp->d_geom;
1009         if (gp != NULL) {
1010                 pp = LIST_FIRST(&gp->provider);
1011                 if (pp != NULL) {
1012                         KASSERT(LIST_NEXT(pp, provider) == NULL,
1013                             ("geom %p has more than one provider", gp));
1014                         g_media_gone(pp, flag);
1015                 }
1016         }
1017 }
1018
1019 int
1020 disk_resize(struct disk *dp, int flag)
1021 {
1022
1023         if (dp->d_destroyed || dp->d_geom == NULL)
1024                 return (0);
1025
1026         return (g_post_event(g_disk_resize, dp, flag, NULL));
1027 }
1028
1029 static void
1030 g_kern_disks(void *p, int flag __unused)
1031 {
1032         struct sbuf *sb;
1033         struct g_geom *gp;
1034         char *sp;
1035
1036         sb = p;
1037         sp = "";
1038         g_topology_assert();
1039         LIST_FOREACH(gp, &g_disk_class.geom, geom) {
1040                 sbuf_printf(sb, "%s%s", sp, gp->name);
1041                 sp = " ";
1042         }
1043         sbuf_finish(sb);
1044 }
1045
1046 static int
1047 g_disk_sysctl_flags(SYSCTL_HANDLER_ARGS)
1048 {
1049         struct disk *dp;
1050         struct sbuf *sb;
1051         int error;
1052
1053         sb = sbuf_new_auto();
1054         dp = (struct disk *)arg1;
1055         sbuf_printf(sb, "%b", dp->d_flags,
1056                 "\20"
1057                 "\2OPEN"
1058                 "\3CANDELETE"
1059                 "\4CANFLUSHCACHE"
1060                 "\5UNMAPPEDBIO"
1061                 "\6DIRECTCOMPLETION"
1062                 "\10CANZONE"
1063                 "\11WRITEPROTECT");
1064
1065         sbuf_finish(sb);
1066         error = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb) + 1);
1067         sbuf_delete(sb);
1068         return (error);
1069 }
1070
1071 static int
1072 sysctl_disks(SYSCTL_HANDLER_ARGS)
1073 {
1074         int error;
1075         struct sbuf *sb;
1076
1077         sb = sbuf_new_auto();
1078         g_waitfor_event(g_kern_disks, sb, M_WAITOK, NULL);
1079         error = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb) + 1);
1080         sbuf_delete(sb);
1081         return error;
1082 }
1083  
1084 SYSCTL_PROC(_kern, OID_AUTO, disks,
1085     CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0,
1086     sysctl_disks, "A", "names of available disks");