]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/geom/geom_dev.c
fs/msdosfs fatblock: use ulmin() rather than min()
[FreeBSD/FreeBSD.git] / sys / geom / geom_dev.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/param.h>
39 #include <sys/systm.h>
40 #include <sys/malloc.h>
41 #include <sys/kernel.h>
42 #include <sys/conf.h>
43 #include <sys/ctype.h>
44 #include <sys/bio.h>
45 #include <sys/devctl.h>
46 #include <sys/lock.h>
47 #include <sys/mutex.h>
48 #include <sys/proc.h>
49 #include <sys/errno.h>
50 #include <sys/time.h>
51 #include <sys/disk.h>
52 #include <sys/fcntl.h>
53 #include <sys/limits.h>
54 #include <sys/selinfo.h>
55 #include <sys/sysctl.h>
56 #include <geom/geom.h>
57 #include <geom/geom_int.h>
58 #include <machine/stdarg.h>
59
60 struct g_dev_softc {
61         struct mtx       sc_mtx;
62         struct cdev     *sc_dev;
63         struct cdev     *sc_alias;
64         int              sc_open;
65         u_int            sc_active;
66         struct selinfo   sc_selinfo;
67 #define SC_A_DESTROY    (1 << 31)
68 #define SC_A_OPEN       (1 << 30)
69 #define SC_A_ACTIVE     (SC_A_OPEN - 1)
70 };
71
72 static d_open_t         g_dev_open;
73 static d_close_t        g_dev_close;
74 static d_strategy_t     g_dev_strategy;
75 static d_ioctl_t        g_dev_ioctl;
76 static d_kqfilter_t     g_dev_kqfilter;
77
78 static void             gdev_filter_detach(struct knote *kn);
79 static int              gdev_filter_vnode(struct knote *kn, long hint);
80
81 static struct filterops gdev_filterops_vnode = {
82         .f_isfd = 1,
83         .f_detach = gdev_filter_detach,
84         .f_event = gdev_filter_vnode,
85 };
86
87 static struct cdevsw g_dev_cdevsw = {
88         .d_version =    D_VERSION,
89         .d_open =       g_dev_open,
90         .d_close =      g_dev_close,
91         .d_read =       physread,
92         .d_write =      physwrite,
93         .d_ioctl =      g_dev_ioctl,
94         .d_strategy =   g_dev_strategy,
95         .d_name =       "g_dev",
96         .d_flags =      D_DISK | D_TRACKCLOSE,
97         .d_kqfilter =   g_dev_kqfilter,
98 };
99
100 static g_init_t g_dev_init;
101 static g_fini_t g_dev_fini;
102 static g_taste_t g_dev_taste;
103 static g_orphan_t g_dev_orphan;
104 static g_attrchanged_t g_dev_attrchanged;
105 static g_resize_t g_dev_resize;
106
107 static struct g_class g_dev_class       = {
108         .name = "DEV",
109         .version = G_VERSION,
110         .init = g_dev_init,
111         .fini = g_dev_fini,
112         .taste = g_dev_taste,
113         .orphan = g_dev_orphan,
114         .attrchanged = g_dev_attrchanged,
115         .resize = g_dev_resize
116 };
117
118 /*
119  * We target 262144 (8 x 32768) sectors by default as this significantly
120  * increases the throughput on commonly used SSD's with a marginal
121  * increase in non-interruptible request latency.
122  */
123 static uint64_t g_dev_del_max_sectors = 262144;
124 SYSCTL_DECL(_kern_geom);
125 SYSCTL_NODE(_kern_geom, OID_AUTO, dev, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
126     "GEOM_DEV stuff");
127 SYSCTL_QUAD(_kern_geom_dev, OID_AUTO, delete_max_sectors, CTLFLAG_RW,
128     &g_dev_del_max_sectors, 0, "Maximum number of sectors in a single "
129     "delete request sent to the provider. Larger requests are chunked "
130     "so they can be interrupted. (0 = disable chunking)");
131
132 static char *dumpdev = NULL;
133 static void
134 g_dev_init(struct g_class *mp)
135 {
136
137         dumpdev = kern_getenv("dumpdev");
138 }
139
140 static void
141 g_dev_fini(struct g_class *mp)
142 {
143
144         freeenv(dumpdev);
145         dumpdev = NULL;
146 }
147
148 static int
149 g_dev_setdumpdev(struct cdev *dev, struct diocskerneldump_arg *kda)
150 {
151         struct g_kerneldump kd;
152         struct g_consumer *cp;
153         int error, len;
154
155         MPASS(dev != NULL && kda != NULL);
156         MPASS(kda->kda_index != KDA_REMOVE);
157
158         cp = dev->si_drv2;
159         len = sizeof(kd);
160         memset(&kd, 0, len);
161         kd.offset = 0;
162         kd.length = OFF_MAX;
163         error = g_io_getattr("GEOM::kerneldump", cp, &len, &kd);
164         if (error != 0)
165                 return (error);
166
167         error = dumper_insert(&kd.di, devtoname(dev), kda);
168         if (error == 0)
169                 dev->si_flags |= SI_DUMPDEV;
170
171         return (error);
172 }
173
174 static int
175 init_dumpdev(struct cdev *dev)
176 {
177         struct diocskerneldump_arg kda;
178         struct g_consumer *cp;
179         const char *devprefix = _PATH_DEV, *devname;
180         int error;
181         size_t len;
182
183         bzero(&kda, sizeof(kda));
184         kda.kda_index = KDA_APPEND;
185
186         if (dumpdev == NULL)
187                 return (0);
188
189         len = strlen(devprefix);
190         devname = devtoname(dev);
191         if (strcmp(devname, dumpdev) != 0 &&
192            (strncmp(dumpdev, devprefix, len) != 0 ||
193             strcmp(devname, dumpdev + len) != 0))
194                 return (0);
195
196         cp = (struct g_consumer *)dev->si_drv2;
197         error = g_access(cp, 1, 0, 0);
198         if (error != 0)
199                 return (error);
200
201         error = g_dev_setdumpdev(dev, &kda);
202         if (error == 0) {
203                 freeenv(dumpdev);
204                 dumpdev = NULL;
205         }
206
207         (void)g_access(cp, -1, 0, 0);
208
209         return (error);
210 }
211
212 static void
213 g_dev_destroy(void *arg, int flags __unused)
214 {
215         struct g_consumer *cp;
216         struct g_geom *gp;
217         struct g_dev_softc *sc;
218         char buf[SPECNAMELEN + 6];
219
220         g_topology_assert();
221         cp = arg;
222         gp = cp->geom;
223         sc = cp->private;
224         g_trace(G_T_TOPOLOGY, "g_dev_destroy(%p(%s))", cp, gp->name);
225         snprintf(buf, sizeof(buf), "cdev=%s", gp->name);
226         devctl_notify("GEOM", "DEV", "DESTROY", buf);
227         knlist_clear(&sc->sc_selinfo.si_note, 0);
228         knlist_destroy(&sc->sc_selinfo.si_note);
229         if (cp->acr > 0 || cp->acw > 0 || cp->ace > 0)
230                 g_access(cp, -cp->acr, -cp->acw, -cp->ace);
231         g_detach(cp);
232         g_destroy_consumer(cp);
233         g_destroy_geom(gp);
234         mtx_destroy(&sc->sc_mtx);
235         g_free(sc);
236 }
237
238 void
239 g_dev_print(void)
240 {
241         struct g_geom *gp;
242         char const *p = "";
243
244         LIST_FOREACH(gp, &g_dev_class.geom, geom) {
245                 printf("%s%s", p, gp->name);
246                 p = " ";
247         }
248         printf("\n");
249 }
250
251 static void
252 g_dev_set_physpath(struct g_consumer *cp)
253 {
254         struct g_dev_softc *sc;
255         char *physpath;
256         int error, physpath_len;
257
258         if (g_access(cp, 1, 0, 0) != 0)
259                 return;
260
261         sc = cp->private;
262         physpath_len = MAXPATHLEN;
263         physpath = g_malloc(physpath_len, M_WAITOK|M_ZERO);
264         error = g_io_getattr("GEOM::physpath", cp, &physpath_len, physpath);
265         g_access(cp, -1, 0, 0);
266         if (error == 0 && strlen(physpath) != 0) {
267                 struct cdev *dev, *old_alias_dev;
268                 struct cdev **alias_devp;
269
270                 dev = sc->sc_dev;
271                 old_alias_dev = sc->sc_alias;
272                 alias_devp = (struct cdev **)&sc->sc_alias;
273                 make_dev_physpath_alias(MAKEDEV_WAITOK | MAKEDEV_CHECKNAME,
274                     alias_devp, dev, old_alias_dev, physpath);
275         } else if (sc->sc_alias) {
276                 destroy_dev((struct cdev *)sc->sc_alias);
277                 sc->sc_alias = NULL;
278         }
279         g_free(physpath);
280 }
281
282 static void
283 g_dev_set_media(struct g_consumer *cp)
284 {
285         struct g_dev_softc *sc;
286         struct cdev *dev;
287         char buf[SPECNAMELEN + 6];
288
289         sc = cp->private;
290         dev = sc->sc_dev;
291         snprintf(buf, sizeof(buf), "cdev=%s", dev->si_name);
292         devctl_notify("DEVFS", "CDEV", "MEDIACHANGE", buf);
293         devctl_notify("GEOM", "DEV", "MEDIACHANGE", buf);
294         dev = sc->sc_alias;
295         if (dev != NULL) {
296                 snprintf(buf, sizeof(buf), "cdev=%s", dev->si_name);
297                 devctl_notify("DEVFS", "CDEV", "MEDIACHANGE", buf);
298                 devctl_notify("GEOM", "DEV", "MEDIACHANGE", buf);
299         }
300 }
301
302 static void
303 g_dev_attrchanged(struct g_consumer *cp, const char *attr)
304 {
305
306         if (strcmp(attr, "GEOM::media") == 0) {
307                 g_dev_set_media(cp);
308                 return;
309         }
310
311         if (strcmp(attr, "GEOM::physpath") == 0) {
312                 g_dev_set_physpath(cp);
313                 return;
314         }
315 }
316
317 static void
318 g_dev_resize(struct g_consumer *cp)
319 {
320         struct g_dev_softc *sc;
321         char buf[SPECNAMELEN + 6];
322
323         sc = cp->private;
324         KNOTE_UNLOCKED(&sc->sc_selinfo.si_note, NOTE_ATTRIB);
325
326         snprintf(buf, sizeof(buf), "cdev=%s", cp->provider->name);
327         devctl_notify("GEOM", "DEV", "SIZECHANGE", buf);
328 }
329
330 struct g_provider *
331 g_dev_getprovider(struct cdev *dev)
332 {
333         struct g_consumer *cp;
334
335         g_topology_assert();
336         if (dev == NULL)
337                 return (NULL);
338         if (dev->si_devsw != &g_dev_cdevsw)
339                 return (NULL);
340         cp = dev->si_drv2;
341         return (cp->provider);
342 }
343
344 static struct g_geom *
345 g_dev_taste(struct g_class *mp, struct g_provider *pp, int insist __unused)
346 {
347         struct g_geom *gp;
348         struct g_geom_alias *gap;
349         struct g_consumer *cp;
350         struct g_dev_softc *sc;
351         int error;
352         struct cdev *dev, *adev;
353         char buf[SPECNAMELEN + 6];
354         struct make_dev_args args;
355
356         g_trace(G_T_TOPOLOGY, "dev_taste(%s,%s)", mp->name, pp->name);
357         g_topology_assert();
358         gp = g_new_geomf(mp, "%s", pp->name);
359         sc = g_malloc(sizeof(*sc), M_WAITOK | M_ZERO);
360         mtx_init(&sc->sc_mtx, "g_dev", NULL, MTX_DEF);
361         cp = g_new_consumer(gp);
362         cp->private = sc;
363         cp->flags |= G_CF_DIRECT_SEND | G_CF_DIRECT_RECEIVE;
364         error = g_attach(cp, pp);
365         if (error != 0) {
366                 printf("%s: g_dev_taste(%s) failed to g_attach, error=%d\n",
367                     __func__, pp->name, error);
368                 g_destroy_consumer(cp);
369                 g_destroy_geom(gp);
370                 mtx_destroy(&sc->sc_mtx);
371                 g_free(sc);
372                 return (NULL);
373         }
374         make_dev_args_init(&args);
375         args.mda_flags = MAKEDEV_CHECKNAME | MAKEDEV_WAITOK;
376         args.mda_devsw = &g_dev_cdevsw;
377         args.mda_cr = NULL;
378         args.mda_uid = UID_ROOT;
379         args.mda_gid = GID_OPERATOR;
380         args.mda_mode = 0640;
381         args.mda_si_drv1 = sc;
382         args.mda_si_drv2 = cp;
383         error = make_dev_s(&args, &sc->sc_dev, "%s", gp->name);
384         if (error != 0) {
385                 printf("%s: make_dev_p() failed (gp->name=%s, error=%d)\n",
386                     __func__, gp->name, error);
387                 g_detach(cp);
388                 g_destroy_consumer(cp);
389                 g_destroy_geom(gp);
390                 mtx_destroy(&sc->sc_mtx);
391                 g_free(sc);
392                 return (NULL);
393         }
394         dev = sc->sc_dev;
395         dev->si_flags |= SI_UNMAPPED;
396         dev->si_iosize_max = maxphys;
397         knlist_init_mtx(&sc->sc_selinfo.si_note, &sc->sc_mtx);
398         error = init_dumpdev(dev);
399         if (error != 0)
400                 printf("%s: init_dumpdev() failed (gp->name=%s, error=%d)\n",
401                     __func__, gp->name, error);
402
403         g_dev_attrchanged(cp, "GEOM::physpath");
404         snprintf(buf, sizeof(buf), "cdev=%s", gp->name);
405         devctl_notify("GEOM", "DEV", "CREATE", buf);
406         /*
407          * Now add all the aliases for this drive
408          */
409         LIST_FOREACH(gap, &pp->aliases, ga_next) {
410                 error = make_dev_alias_p(MAKEDEV_CHECKNAME | MAKEDEV_WAITOK, &adev, dev,
411                     "%s", gap->ga_alias);
412                 if (error) {
413                         printf("%s: make_dev_alias_p() failed (name=%s, error=%d)\n",
414                             __func__, gap->ga_alias, error);
415                         continue;
416                 }
417                 snprintf(buf, sizeof(buf), "cdev=%s", gap->ga_alias);
418                 devctl_notify("GEOM", "DEV", "CREATE", buf);
419         }
420
421         return (gp);
422 }
423
424 static int
425 g_dev_open(struct cdev *dev, int flags, int fmt, struct thread *td)
426 {
427         struct g_consumer *cp;
428         struct g_dev_softc *sc;
429         int error, r, w, e;
430
431         cp = dev->si_drv2;
432         g_trace(G_T_ACCESS, "g_dev_open(%s, %d, %d, %p)",
433             cp->geom->name, flags, fmt, td);
434
435         r = flags & FREAD ? 1 : 0;
436         w = flags & FWRITE ? 1 : 0;
437 #ifdef notyet
438         e = flags & O_EXCL ? 1 : 0;
439 #else
440         e = 0;
441 #endif
442
443         /*
444          * This happens on attempt to open a device node with O_EXEC.
445          */
446         if (r + w + e == 0)
447                 return (EINVAL);
448
449         if (w) {
450                 /*
451                  * When running in very secure mode, do not allow
452                  * opens for writing of any disks.
453                  */
454                 error = securelevel_ge(td->td_ucred, 2);
455                 if (error)
456                         return (error);
457         }
458         g_topology_lock();
459         error = g_access(cp, r, w, e);
460         g_topology_unlock();
461         if (error == 0) {
462                 sc = dev->si_drv1;
463                 mtx_lock(&sc->sc_mtx);
464                 if (sc->sc_open == 0 && (sc->sc_active & SC_A_ACTIVE) != 0)
465                         wakeup(&sc->sc_active);
466                 sc->sc_open += r + w + e;
467                 if (sc->sc_open == 0)
468                         atomic_clear_int(&sc->sc_active, SC_A_OPEN);
469                 else
470                         atomic_set_int(&sc->sc_active, SC_A_OPEN);
471                 KNOTE_LOCKED(&sc->sc_selinfo.si_note, NOTE_OPEN);
472                 mtx_unlock(&sc->sc_mtx);
473         }
474         return (error);
475 }
476
477 static int
478 g_dev_close(struct cdev *dev, int flags, int fmt, struct thread *td)
479 {
480         struct g_consumer *cp;
481         struct g_dev_softc *sc;
482         int error, r, w, e;
483
484         cp = dev->si_drv2;
485         g_trace(G_T_ACCESS, "g_dev_close(%s, %d, %d, %p)",
486             cp->geom->name, flags, fmt, td);
487
488         r = flags & FREAD ? -1 : 0;
489         w = flags & FWRITE ? -1 : 0;
490 #ifdef notyet
491         e = flags & O_EXCL ? -1 : 0;
492 #else
493         e = 0;
494 #endif
495
496         /*
497          * The vgonel(9) - caused by eg. forced unmount of devfs - calls
498          * VOP_CLOSE(9) on devfs vnode without any FREAD or FWRITE flags,
499          * which would result in zero deltas, which in turn would cause
500          * panic in g_access(9).
501          *
502          * Note that we cannot zero the counters (ie. do "r = cp->acr"
503          * etc) instead, because the consumer might be opened in another
504          * devfs instance.
505          */
506         if (r + w + e == 0)
507                 return (EINVAL);
508
509         sc = dev->si_drv1;
510         mtx_lock(&sc->sc_mtx);
511         sc->sc_open += r + w + e;
512         if (sc->sc_open == 0)
513                 atomic_clear_int(&sc->sc_active, SC_A_OPEN);
514         else
515                 atomic_set_int(&sc->sc_active, SC_A_OPEN);
516         while (sc->sc_open == 0 && (sc->sc_active & SC_A_ACTIVE) != 0)
517                 msleep(&sc->sc_active, &sc->sc_mtx, 0, "g_dev_close", hz / 10);
518         KNOTE_LOCKED(&sc->sc_selinfo.si_note, NOTE_CLOSE | (w ? NOTE_CLOSE_WRITE : 0));
519         mtx_unlock(&sc->sc_mtx);
520         g_topology_lock();
521         error = g_access(cp, r, w, e);
522         g_topology_unlock();
523         return (error);
524 }
525
526 static int
527 g_dev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
528 {
529         struct g_consumer *cp;
530         struct g_provider *pp;
531         off_t offset, length, chunk, odd;
532         int i, error;
533
534         cp = dev->si_drv2;
535         pp = cp->provider;
536
537         /* If consumer or provider is dying, don't disturb. */
538         if (cp->flags & G_CF_ORPHAN)
539                 return (ENXIO);
540         if (pp->error)
541                 return (pp->error);
542
543         error = 0;
544         KASSERT(cp->acr || cp->acw,
545             ("Consumer with zero access count in g_dev_ioctl"));
546
547         i = IOCPARM_LEN(cmd);
548         switch (cmd) {
549         case DIOCGSECTORSIZE:
550                 *(u_int *)data = pp->sectorsize;
551                 if (*(u_int *)data == 0)
552                         error = ENOENT;
553                 break;
554         case DIOCGMEDIASIZE:
555                 *(off_t *)data = pp->mediasize;
556                 if (*(off_t *)data == 0)
557                         error = ENOENT;
558                 break;
559         case DIOCGFWSECTORS:
560                 error = g_io_getattr("GEOM::fwsectors", cp, &i, data);
561                 if (error == 0 && *(u_int *)data == 0)
562                         error = ENOENT;
563                 break;
564         case DIOCGFWHEADS:
565                 error = g_io_getattr("GEOM::fwheads", cp, &i, data);
566                 if (error == 0 && *(u_int *)data == 0)
567                         error = ENOENT;
568                 break;
569         case DIOCSKERNELDUMP:
570             {
571                 struct diocskerneldump_arg *kda;
572                 uint8_t *encryptedkey;
573
574                 kda = (struct diocskerneldump_arg *)data;
575                 if (kda->kda_index == KDA_REMOVE_ALL ||
576                     kda->kda_index == KDA_REMOVE_DEV ||
577                     kda->kda_index == KDA_REMOVE) {
578                         error = dumper_remove(devtoname(dev), kda);
579                         explicit_bzero(kda, sizeof(*kda));
580                         break;
581                 }
582
583                 if (kda->kda_encryption != KERNELDUMP_ENC_NONE) {
584                         if (kda->kda_encryptedkeysize == 0 ||
585                             kda->kda_encryptedkeysize >
586                             KERNELDUMP_ENCKEY_MAX_SIZE) {
587                                 explicit_bzero(kda, sizeof(*kda));
588                                 return (EINVAL);
589                         }
590                         encryptedkey = malloc(kda->kda_encryptedkeysize, M_TEMP,
591                             M_WAITOK);
592                         error = copyin(kda->kda_encryptedkey, encryptedkey,
593                             kda->kda_encryptedkeysize);
594                 } else {
595                         encryptedkey = NULL;
596                 }
597                 if (error == 0) {
598                         kda->kda_encryptedkey = encryptedkey;
599                         error = g_dev_setdumpdev(dev, kda);
600                 }
601                 zfree(encryptedkey, M_TEMP);
602                 explicit_bzero(kda, sizeof(*kda));
603                 break;
604             }
605         case DIOCGFLUSH:
606                 error = g_io_flush(cp);
607                 break;
608         case DIOCGDELETE:
609                 offset = ((off_t *)data)[0];
610                 length = ((off_t *)data)[1];
611                 if ((offset % pp->sectorsize) != 0 ||
612                     (length % pp->sectorsize) != 0 || length <= 0) {
613                         printf("%s: offset=%jd length=%jd\n", __func__, offset,
614                             length);
615                         error = EINVAL;
616                         break;
617                 }
618                 while (length > 0) {
619                         chunk = length;
620                         if (g_dev_del_max_sectors != 0 &&
621                             chunk > g_dev_del_max_sectors * pp->sectorsize) {
622                                 chunk = g_dev_del_max_sectors * pp->sectorsize;
623                                 if (pp->stripesize > 0) {
624                                         odd = (offset + chunk +
625                                             pp->stripeoffset) % pp->stripesize;
626                                         if (chunk > odd)
627                                                 chunk -= odd;
628                                 }
629                         }
630                         error = g_delete_data(cp, offset, chunk);
631                         length -= chunk;
632                         offset += chunk;
633                         if (error)
634                                 break;
635                         /*
636                          * Since the request size can be large, the service
637                          * time can be is likewise.  We make this ioctl
638                          * interruptible by checking for signals for each bio.
639                          */
640                         if (SIGPENDING(td))
641                                 break;
642                 }
643                 break;
644         case DIOCGIDENT:
645                 error = g_io_getattr("GEOM::ident", cp, &i, data);
646                 break;
647         case DIOCGPROVIDERNAME:
648                 strlcpy(data, pp->name, i);
649                 break;
650         case DIOCGSTRIPESIZE:
651                 *(off_t *)data = pp->stripesize;
652                 break;
653         case DIOCGSTRIPEOFFSET:
654                 *(off_t *)data = pp->stripeoffset;
655                 break;
656         case DIOCGPHYSPATH:
657                 error = g_io_getattr("GEOM::physpath", cp, &i, data);
658                 if (error == 0 && *(char *)data == '\0')
659                         error = ENOENT;
660                 break;
661         case DIOCGATTR: {
662                 struct diocgattr_arg *arg = (struct diocgattr_arg *)data;
663
664                 if (arg->len > sizeof(arg->value)) {
665                         error = EINVAL;
666                         break;
667                 }
668                 error = g_io_getattr(arg->name, cp, &arg->len, &arg->value);
669                 break;
670         }
671         case DIOCZONECMD: {
672                 struct disk_zone_args *zone_args =(struct disk_zone_args *)data;
673                 struct disk_zone_rep_entry *new_entries, *old_entries;
674                 struct disk_zone_report *rep;
675                 size_t alloc_size;
676
677                 old_entries = NULL;
678                 new_entries = NULL;
679                 rep = NULL;
680                 alloc_size = 0;
681
682                 if (zone_args->zone_cmd == DISK_ZONE_REPORT_ZONES) {
683                         rep = &zone_args->zone_params.report;
684 #define MAXENTRIES      (maxphys / sizeof(struct disk_zone_rep_entry))
685                         if (rep->entries_allocated > MAXENTRIES)
686                                 rep->entries_allocated = MAXENTRIES;
687                         alloc_size = rep->entries_allocated *
688                             sizeof(struct disk_zone_rep_entry);
689                         if (alloc_size != 0)
690                                 new_entries = g_malloc(alloc_size,
691                                     M_WAITOK | M_ZERO);
692                         old_entries = rep->entries;
693                         rep->entries = new_entries;
694                 }
695                 error = g_io_zonecmd(zone_args, cp);
696                 if (zone_args->zone_cmd == DISK_ZONE_REPORT_ZONES &&
697                     alloc_size != 0 && error == 0)
698                         error = copyout(new_entries, old_entries, alloc_size);
699                 if (old_entries != NULL && rep != NULL)
700                         rep->entries = old_entries;
701                 g_free(new_entries);
702                 break;
703         }
704         default:
705                 if (pp->geom->ioctl != NULL) {
706                         error = pp->geom->ioctl(pp, cmd, data, fflag, td);
707                 } else {
708                         error = ENOIOCTL;
709                 }
710         }
711
712         return (error);
713 }
714
715 static void
716 g_dev_done(struct bio *bp2)
717 {
718         struct g_consumer *cp;
719         struct g_dev_softc *sc;
720         struct bio *bp;
721         int active;
722
723         cp = bp2->bio_from;
724         sc = cp->private;
725         bp = bp2->bio_parent;
726         bp->bio_error = bp2->bio_error;
727         bp->bio_completed = bp2->bio_completed;
728         bp->bio_resid = bp->bio_length - bp2->bio_completed;
729         if (bp2->bio_cmd == BIO_ZONE)
730                 bcopy(&bp2->bio_zone, &bp->bio_zone, sizeof(bp->bio_zone));
731
732         if (bp2->bio_error != 0) {
733                 g_trace(G_T_BIO, "g_dev_done(%p) had error %d",
734                     bp2, bp2->bio_error);
735                 bp->bio_flags |= BIO_ERROR;
736         } else {
737                 if (bp->bio_cmd == BIO_READ)
738                         KNOTE_UNLOCKED(&sc->sc_selinfo.si_note, NOTE_READ);
739                 if (bp->bio_cmd == BIO_WRITE)
740                         KNOTE_UNLOCKED(&sc->sc_selinfo.si_note, NOTE_WRITE);
741                 g_trace(G_T_BIO, "g_dev_done(%p/%p) resid %ld completed %jd",
742                     bp2, bp, bp2->bio_resid, (intmax_t)bp2->bio_completed);
743         }
744         g_destroy_bio(bp2);
745         active = atomic_fetchadd_int(&sc->sc_active, -1) - 1;
746         if ((active & SC_A_ACTIVE) == 0) {
747                 if ((active & SC_A_OPEN) == 0)
748                         wakeup(&sc->sc_active);
749                 if (active & SC_A_DESTROY)
750                         g_post_event(g_dev_destroy, cp, M_NOWAIT, NULL);
751         }
752         biodone(bp);
753 }
754
755 static void
756 g_dev_strategy(struct bio *bp)
757 {
758         struct g_consumer *cp;
759         struct bio *bp2;
760         struct cdev *dev;
761         struct g_dev_softc *sc;
762
763         KASSERT(bp->bio_cmd == BIO_READ ||
764                 bp->bio_cmd == BIO_WRITE ||
765                 bp->bio_cmd == BIO_DELETE ||
766                 bp->bio_cmd == BIO_FLUSH ||
767                 bp->bio_cmd == BIO_ZONE,
768                 ("Wrong bio_cmd bio=%p cmd=%d", bp, bp->bio_cmd));
769         dev = bp->bio_dev;
770         cp = dev->si_drv2;
771         KASSERT(cp->acr || cp->acw,
772             ("Consumer with zero access count in g_dev_strategy"));
773         biotrack(bp, __func__);
774 #ifdef INVARIANTS
775         if ((bp->bio_offset % cp->provider->sectorsize) != 0 ||
776             (bp->bio_bcount % cp->provider->sectorsize) != 0) {
777                 bp->bio_resid = bp->bio_bcount;
778                 biofinish(bp, NULL, EINVAL);
779                 return;
780         }
781 #endif
782         sc = dev->si_drv1;
783         KASSERT(sc->sc_open > 0, ("Closed device in g_dev_strategy"));
784         atomic_add_int(&sc->sc_active, 1);
785
786         for (;;) {
787                 /*
788                  * XXX: This is not an ideal solution, but I believe it to
789                  * XXX: deadlock safely, all things considered.
790                  */
791                 bp2 = g_clone_bio(bp);
792                 if (bp2 != NULL)
793                         break;
794                 pause("gdstrat", hz / 10);
795         }
796         KASSERT(bp2 != NULL, ("XXX: ENOMEM in a bad place"));
797         bp2->bio_done = g_dev_done;
798         g_trace(G_T_BIO,
799             "g_dev_strategy(%p/%p) offset %jd length %jd data %p cmd %d",
800             bp, bp2, (intmax_t)bp->bio_offset, (intmax_t)bp2->bio_length,
801             bp2->bio_data, bp2->bio_cmd);
802         g_io_request(bp2, cp);
803         KASSERT(cp->acr || cp->acw,
804             ("g_dev_strategy raced with g_dev_close and lost"));
805
806 }
807
808 /*
809  * g_dev_callback()
810  *
811  * Called by devfs when asynchronous device destruction is completed.
812  * - Mark that we have no attached device any more.
813  * - If there are no outstanding requests, schedule geom destruction.
814  *   Otherwise destruction will be scheduled later by g_dev_done().
815  */
816
817 static void
818 g_dev_callback(void *arg)
819 {
820         struct g_consumer *cp;
821         struct g_dev_softc *sc;
822         int active;
823
824         cp = arg;
825         sc = cp->private;
826         g_trace(G_T_TOPOLOGY, "g_dev_callback(%p(%s))", cp, cp->geom->name);
827
828         sc->sc_dev = NULL;
829         sc->sc_alias = NULL;
830         active = atomic_fetchadd_int(&sc->sc_active, SC_A_DESTROY);
831         if ((active & SC_A_ACTIVE) == 0)
832                 g_post_event(g_dev_destroy, cp, M_WAITOK, NULL);
833 }
834
835 /*
836  * g_dev_orphan()
837  *
838  * Called from below when the provider orphaned us.
839  * - Clear any dump settings.
840  * - Request asynchronous device destruction to prevent any more requests
841  *   from coming in.  The provider is already marked with an error, so
842  *   anything which comes in the interim will be returned immediately.
843  */
844
845 static void
846 g_dev_orphan(struct g_consumer *cp)
847 {
848         struct cdev *dev;
849         struct g_dev_softc *sc;
850
851         g_topology_assert();
852         sc = cp->private;
853         dev = sc->sc_dev;
854         g_trace(G_T_TOPOLOGY, "g_dev_orphan(%p(%s))", cp, cp->geom->name);
855
856         /* Reset any dump-area set on this device */
857         if (dev->si_flags & SI_DUMPDEV) {
858                 struct diocskerneldump_arg kda;
859
860                 bzero(&kda, sizeof(kda));
861                 kda.kda_index = KDA_REMOVE_DEV;
862                 (void)dumper_remove(devtoname(dev), &kda);
863         }
864
865         /* Destroy the struct cdev *so we get no more requests */
866         delist_dev(dev);
867         destroy_dev_sched_cb(dev, g_dev_callback, cp);
868 }
869
870 static void
871 gdev_filter_detach(struct knote *kn)
872 {
873         struct g_dev_softc *sc;
874
875         sc = kn->kn_hook;
876
877         knlist_remove(&sc->sc_selinfo.si_note, kn, 0);
878 }
879
880 static int
881 gdev_filter_vnode(struct knote *kn, long hint)
882 {
883         kn->kn_fflags |= kn->kn_sfflags & hint;
884
885         return (kn->kn_fflags != 0);
886 }
887
888 static int
889 g_dev_kqfilter(struct cdev *dev, struct knote *kn)
890 {
891         struct g_dev_softc *sc;
892
893         sc = dev->si_drv1;
894
895         if (kn->kn_filter != EVFILT_VNODE)
896                 return (EINVAL);
897
898 #define SUPPORTED_EVENTS (NOTE_ATTRIB | NOTE_OPEN | NOTE_CLOSE | \
899     NOTE_CLOSE_WRITE | NOTE_READ | NOTE_WRITE)
900         if (kn->kn_sfflags & ~SUPPORTED_EVENTS)
901                 return (EOPNOTSUPP);
902
903         kn->kn_fop = &gdev_filterops_vnode;
904         kn->kn_hook = sc;
905         knlist_add(&sc->sc_selinfo.si_note, kn, 0);
906
907         return (0);
908 }
909
910 DECLARE_GEOM_CLASS(g_dev_class, g_dev);