/* ARGSUSED */ int dk_open(struct dk_softc *dksc, dev_t dev, int flags, int fmt, struct lwp *l) { struct disklabel *lp = dksc->sc_dkdev.dk_label; int part = DISKPART(dev); int pmask = 1 << part; int ret = 0; struct disk *dk = &dksc->sc_dkdev; DPRINTF_FOLLOW(("%s(%s, %p, 0x%"PRIx64", 0x%x)\n", __func__, dksc->sc_xname, dksc, dev, flags)); mutex_enter(&dk->dk_openlock); /* * If there are wedges, and this is not RAW_PART, then we * need to fail. */ if (dk->dk_nwedges != 0 && part != RAW_PART) { ret = EBUSY; goto done; } /* * If we're init'ed and there are no other open partitions then * update the in-core disklabel. */ if ((dksc->sc_flags & DKF_INITED)) { if ((dksc->sc_flags & DKF_VLABEL) == 0) { dksc->sc_flags |= DKF_VLABEL; dk_getdisklabel(dksc, dev); } } /* Fail if we can't find the partition. */ if (part != RAW_PART && ((dksc->sc_flags & DKF_VLABEL) == 0 || part >= lp->d_npartitions || lp->d_partitions[part].p_fstype == FS_UNUSED)) { ret = ENXIO; goto done; } /* Mark our unit as open. */ switch (fmt) { case S_IFCHR: dk->dk_copenmask |= pmask; break; case S_IFBLK: dk->dk_bopenmask |= pmask; break; } dk->dk_openmask = dk->dk_copenmask | dk->dk_bopenmask; done: mutex_exit(&dk->dk_openlock); return ret; }
/* ARGSUSED */ static int cgd_ioctl_set(struct cgd_softc *cs, void *data, struct lwp *l) { struct cgd_ioctl *ci = data; struct vnode *vp; int ret; size_t i; size_t keybytes; /* key length in bytes */ const char *cp; struct pathbuf *pb; char *inbuf; struct dk_softc *dksc = &cs->sc_dksc; cp = ci->ci_disk; ret = pathbuf_copyin(ci->ci_disk, &pb); if (ret != 0) { return ret; } ret = dk_lookup(pb, l, &vp); pathbuf_destroy(pb); if (ret != 0) { return ret; } inbuf = malloc(MAX_KEYSIZE, M_TEMP, M_WAITOK); if ((ret = cgdinit(cs, cp, vp, l)) != 0) goto bail; (void)memset(inbuf, 0, MAX_KEYSIZE); ret = copyinstr(ci->ci_alg, inbuf, 256, NULL); if (ret) goto bail; cs->sc_cfuncs = cryptfuncs_find(inbuf); if (!cs->sc_cfuncs) { ret = EINVAL; goto bail; } (void)memset(inbuf, 0, MAX_KEYSIZE); ret = copyinstr(ci->ci_ivmethod, inbuf, MAX_KEYSIZE, NULL); if (ret) goto bail; for (i = 0; i < __arraycount(encblkno); i++) if (strcmp(encblkno[i].n, inbuf) == 0) break; if (i == __arraycount(encblkno)) { ret = EINVAL; goto bail; } keybytes = ci->ci_keylen / 8 + 1; if (keybytes > MAX_KEYSIZE) { ret = EINVAL; goto bail; } (void)memset(inbuf, 0, MAX_KEYSIZE); ret = copyin(ci->ci_key, inbuf, keybytes); if (ret) goto bail; cs->sc_cdata.cf_blocksize = ci->ci_blocksize; cs->sc_cdata.cf_mode = encblkno[i].v; cs->sc_cdata.cf_keylen = ci->ci_keylen; cs->sc_cdata.cf_priv = cs->sc_cfuncs->cf_init(ci->ci_keylen, inbuf, &cs->sc_cdata.cf_blocksize); if (cs->sc_cdata.cf_blocksize > CGD_MAXBLOCKSIZE) { log(LOG_WARNING, "cgd: Disallowed cipher with blocksize %zu > %u\n", cs->sc_cdata.cf_blocksize, CGD_MAXBLOCKSIZE); cs->sc_cdata.cf_priv = NULL; } /* * The blocksize is supposed to be in bytes. Unfortunately originally * it was expressed in bits. For compatibility we maintain encblkno * and encblkno8. */ cs->sc_cdata.cf_blocksize /= encblkno[i].d; (void)explicit_memset(inbuf, 0, MAX_KEYSIZE); if (!cs->sc_cdata.cf_priv) { ret = EINVAL; /* XXX is this the right error? */ goto bail; } free(inbuf, M_TEMP); bufq_alloc(&dksc->sc_bufq, "fcfs", 0); cs->sc_data = malloc(MAXPHYS, M_DEVBUF, M_WAITOK); cs->sc_data_used = 0; /* Attach the disk. */ dk_attach(dksc); disk_attach(&dksc->sc_dkdev); disk_set_info(dksc->sc_dev, &dksc->sc_dkdev, NULL); /* Try and read the disklabel. */ dk_getdisklabel(dksc, 0 /* XXX ? (cause of PR 41704) */); /* Discover wedges on this disk. */ dkwedge_discover(&dksc->sc_dkdev); return 0; bail: free(inbuf, M_TEMP); (void)vn_close(vp, FREAD|FWRITE, l->l_cred); return ret; }