Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev Fix ioctl locking. Add dkdriver.



details:   https://anonhg.NetBSD.org/src/rev/6a7a3a199eda
branches:  trunk
changeset: 944674:6a7a3a199eda
user:      mlelstv <mlelstv%NetBSD.org@localhost>
date:      Tue Oct 06 18:45:23 2020 +0000

description:
Fix ioctl locking. Add dkdriver.

diffstat:

 sys/dev/ccd.c |  222 +++++++++++++++++++++++++++++++--------------------------
 1 files changed, 122 insertions(+), 100 deletions(-)

diffs (truncated from 303 to 300 lines):

diff -r 419fb06a7d3c -r 6a7a3a199eda sys/dev/ccd.c
--- a/sys/dev/ccd.c     Tue Oct 06 16:39:23 2020 +0000
+++ b/sys/dev/ccd.c     Tue Oct 06 18:45:23 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ccd.c,v 1.184 2020/06/11 19:20:46 ad Exp $     */
+/*     $NetBSD: ccd.c,v 1.185 2020/10/06 18:45:23 mlelstv Exp $        */
 
 /*-
  * Copyright (c) 1996, 1997, 1998, 1999, 2007, 2009 The NetBSD Foundation, Inc.
@@ -88,7 +88,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ccd.c,v 1.184 2020/06/11 19:20:46 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ccd.c,v 1.185 2020/10/06 18:45:23 mlelstv Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -209,6 +209,11 @@
        .d_flag = D_DISK | D_MPSAFE
 };
 
+static const struct dkdriver ccddkdriver = {
+       .d_strategy = ccdstrategy,
+       .d_minphys = minphys
+}; 
+
 #ifdef DEBUG
 static void printiinfo(struct ccdiinfo *);
 #endif
@@ -229,7 +234,7 @@
        sc->sc_iolock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE);
        cv_init(&sc->sc_stop, "ccdstop");
        cv_init(&sc->sc_push, "ccdthr");
-       disk_init(&sc->sc_dkdev, sc->sc_xname, NULL); /* XXX */
+       disk_init(&sc->sc_dkdev, sc->sc_xname, &ccddkdriver);
        return sc;
 }
 
@@ -1134,8 +1139,6 @@
                        return (EBADF);
        }
 
-       mutex_enter(&cs->sc_dvlock);
-
        /* Must be initialized for these... */
        switch (cmd) {
        case CCDIOCCLR:
@@ -1159,15 +1162,102 @@
        case ODIOCWDINFO:
        case ODIOCGDEFLABEL:
 #endif
-               if ((cs->sc_flags & CCDF_INITED) == 0) {
-                       error = ENXIO;
-                       goto out;
-               }
+               if ((cs->sc_flags & CCDF_INITED) == 0)
+                       return ENXIO;
        }
 
        error = disk_ioctl(&cs->sc_dkdev, dev, cmd, data, flag, l);
        if (error != EPASSTHROUGH)
-               goto out;
+               return error;
+
+       switch (cmd) {
+       case DIOCGSTRATEGY:
+           {
+               struct disk_strategy *dks = (void *)data;
+
+               mutex_enter(cs->sc_iolock);
+               if (cs->sc_bufq != NULL)
+                       strlcpy(dks->dks_name,
+                           bufq_getstrategyname(cs->sc_bufq),
+                           sizeof(dks->dks_name));
+               else
+                       error = EINVAL;
+               mutex_exit(cs->sc_iolock);
+               dks->dks_paramlen = 0;
+               break;
+           }
+
+       case DIOCWDINFO:
+       case DIOCSDINFO:
+#ifdef __HAVE_OLD_DISKLABEL
+       case ODIOCWDINFO:
+       case ODIOCSDINFO:
+#endif
+       {
+               struct disklabel *lp;
+#ifdef __HAVE_OLD_DISKLABEL
+               if (cmd == ODIOCSDINFO || cmd == ODIOCWDINFO) {
+                       memset(&newlabel, 0, sizeof newlabel);
+                       memcpy(&newlabel, data, sizeof (struct olddisklabel));
+                       lp = &newlabel;
+               } else
+#endif
+               lp = (struct disklabel *)data;
+
+               cs->sc_flags |= CCDF_LABELLING;
+
+               error = setdisklabel(cs->sc_dkdev.dk_label,
+                   lp, 0, cs->sc_dkdev.dk_cpulabel);
+               if (error == 0) {
+                       if (cmd == DIOCWDINFO
+#ifdef __HAVE_OLD_DISKLABEL
+                           || cmd == ODIOCWDINFO
+#endif
+                          )
+                               error = writedisklabel(CCDLABELDEV(dev),
+                                   ccdstrategy, cs->sc_dkdev.dk_label,
+                                   cs->sc_dkdev.dk_cpulabel);
+               }
+
+               cs->sc_flags &= ~CCDF_LABELLING;
+               break;
+       }
+
+       case DIOCKLABEL:
+               if (*(int *)data != 0)
+                       cs->sc_flags |= CCDF_KLABEL;
+               else
+                       cs->sc_flags &= ~CCDF_KLABEL;
+               break;
+
+       case DIOCWLABEL:
+               if (*(int *)data != 0)
+                       cs->sc_flags |= CCDF_WLABEL;
+               else
+                       cs->sc_flags &= ~CCDF_WLABEL;
+               break;
+
+       case DIOCGDEFLABEL:
+               ccdgetdefaultlabel(cs, (struct disklabel *)data);
+               break;
+
+#ifdef __HAVE_OLD_DISKLABEL
+       case ODIOCGDEFLABEL:
+               ccdgetdefaultlabel(cs, &newlabel);
+               if (newlabel.d_npartitions > OLDMAXPARTITIONS)
+                       return ENOTTY;
+               memcpy(data, &newlabel, sizeof (struct olddisklabel));
+               break;
+#endif
+       default:
+               error = ENOTTY;
+                       break;
+       }
+
+       if (error != ENOTTY)
+               return error;
+
+       mutex_enter(&cs->sc_dvlock);
 
        error = 0;
        switch (cmd) {
@@ -1233,6 +1323,12 @@
                                    sizeof(*vpp));
                                kmem_free(cpp, ccio->ccio_ndisks *
                                    sizeof(*cpp));
+
+                               /*
+                                * No component data is allocated,
+                                * nothing is to be freed.
+                               */
+                               cs->sc_nccdisks = 0;
                                goto out;
                        }
                        ++lookedup;
@@ -1332,43 +1428,31 @@
                            cs->sc_cinfo[i].ci_pathlen);
                }
 
-               /* Free interleave index. */
-               for (i = 0; cs->sc_itable[i].ii_ndisk; ++i) {
-                       kmem_free(cs->sc_itable[i].ii_index,
-                           cs->sc_itable[i].ii_indexsz);
+               if (cs->sc_nccdisks != 0) {
+                       /* Free interleave index. */
+                       for (i = 0; cs->sc_itable[i].ii_ndisk; ++i) {
+                               kmem_free(cs->sc_itable[i].ii_index,
+                                   cs->sc_itable[i].ii_indexsz);
+                       }
+                       /* Free component info and interleave table. */
+                       kmem_free(cs->sc_cinfo, cs->sc_nccdisks *
+                           sizeof(struct ccdcinfo));
+                       kmem_free(cs->sc_itable, (cs->sc_nccdisks + 1) *
+                           sizeof(struct ccdiinfo));
                }
 
-               /* Free component info and interleave table. */
-               kmem_free(cs->sc_cinfo, cs->sc_nccdisks *
-                   sizeof(struct ccdcinfo));
-               kmem_free(cs->sc_itable, (cs->sc_nccdisks + 1) *
-                   sizeof(struct ccdiinfo));
-
                aprint_normal("%s: detached\n", cs->sc_xname);
 
                /* Detach the disk. */
                disk_detach(&cs->sc_dkdev);
                bufq_free(cs->sc_bufq);
+
+               /* also releases dv_lock */
                ccdput(cs);
+
                /* Don't break, otherwise cs is read again. */
                return 0;
 
-       case DIOCGSTRATEGY:
-           {
-               struct disk_strategy *dks = (void *)data;
-
-               mutex_enter(cs->sc_iolock);
-               if (cs->sc_bufq != NULL)
-                       strlcpy(dks->dks_name,
-                           bufq_getstrategyname(cs->sc_bufq),
-                           sizeof(dks->dks_name));
-               else
-                       error = EINVAL;
-               mutex_exit(cs->sc_iolock);
-               dks->dks_paramlen = 0;
-               break;
-           }
-
        case DIOCGCACHE:
            {
                int dkcache = 0;
@@ -1410,73 +1494,11 @@
                }
                break;
 
-       case DIOCWDINFO:
-       case DIOCSDINFO:
-#ifdef __HAVE_OLD_DISKLABEL
-       case ODIOCWDINFO:
-       case ODIOCSDINFO:
-#endif
-       {
-               struct disklabel *lp;
-#ifdef __HAVE_OLD_DISKLABEL
-               if (cmd == ODIOCSDINFO || cmd == ODIOCWDINFO) {
-                       memset(&newlabel, 0, sizeof newlabel);
-                       memcpy(&newlabel, data, sizeof (struct olddisklabel));
-                       lp = &newlabel;
-               } else
-#endif
-               lp = (struct disklabel *)data;
-
-               cs->sc_flags |= CCDF_LABELLING;
-
-               error = setdisklabel(cs->sc_dkdev.dk_label,
-                   lp, 0, cs->sc_dkdev.dk_cpulabel);
-               if (error == 0) {
-                       if (cmd == DIOCWDINFO
-#ifdef __HAVE_OLD_DISKLABEL
-                           || cmd == ODIOCWDINFO
-#endif
-                          )
-                               error = writedisklabel(CCDLABELDEV(dev),
-                                   ccdstrategy, cs->sc_dkdev.dk_label,
-                                   cs->sc_dkdev.dk_cpulabel);
-               }
-
-               cs->sc_flags &= ~CCDF_LABELLING;
+default:
+       error = ENOTTY;
                break;
        }
 
-       case DIOCKLABEL:
-               if (*(int *)data != 0)
-                       cs->sc_flags |= CCDF_KLABEL;
-               else
-                       cs->sc_flags &= ~CCDF_KLABEL;
-               break;
-
-       case DIOCWLABEL:
-               if (*(int *)data != 0)
-                       cs->sc_flags |= CCDF_WLABEL;
-               else
-                       cs->sc_flags &= ~CCDF_WLABEL;
-               break;
-
-       case DIOCGDEFLABEL:
-               ccdgetdefaultlabel(cs, (struct disklabel *)data);
-               break;
-
-#ifdef __HAVE_OLD_DISKLABEL
-       case ODIOCGDEFLABEL:
-               ccdgetdefaultlabel(cs, &newlabel);
-               if (newlabel.d_npartitions > OLDMAXPARTITIONS)
-                       return ENOTTY;
-               memcpy(data, &newlabel, sizeof (struct olddisklabel));
-               break;
-#endif
-
-       default:
-               error = ENOTTY;
-       }
-



Home | Main Index | Thread Index | Old Index