Module Name: src Committed By: mlelstv Date: Tue Oct 6 18:45:24 UTC 2020
Modified Files: src/sys/dev: ccd.c Log Message: Fix ioctl locking. Add dkdriver. To generate a diff of this commit: cvs rdiff -u -r1.184 -r1.185 src/sys/dev/ccd.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/ccd.c diff -u src/sys/dev/ccd.c:1.184 src/sys/dev/ccd.c:1.185 --- src/sys/dev/ccd.c:1.184 Thu Jun 11 19:20:46 2020 +++ src/sys/dev/ccd.c Tue Oct 6 18:45:23 2020 @@ -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 @@ const struct cdevsw ccd_cdevsw = { .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 @@ ccdcreate(int unit) { 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 @@ ccdioctl(dev_t dev, u_long cmd, void *da return (EBADF); } - mutex_enter(&cs->sc_dvlock); - /* Must be initialized for these... */ switch (cmd) { case CCDIOCCLR: @@ -1159,15 +1162,102 @@ ccdioctl(dev_t dev, u_long cmd, void *da 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 @@ ccdioctl(dev_t dev, u_long cmd, void *da 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 @@ ccdioctl(dev_t dev, u_long cmd, void *da 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 @@ ccdioctl(dev_t dev, u_long cmd, void *da } 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; - } - out: mutex_exit(&cs->sc_dvlock); return (error);