From aec8eea47f8acbdec20843e7d8e7bc6d4255cce3 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Mon, 3 Aug 2009 21:38:47 -0700 Subject: [PATCH] DEVS - rollup - kernel core * Remove dead code. * Reference count adjustments for devfs. * DEVFS integration into kernel core, including automatic probe/reprobe. * Dummy vnops support for deprecated VCHR and VBLK devices in filesystems. * Silence MBR warnings for VN with DSO_MBRQUIET flag. * Change rootdevnames for CD boot. DEVFS provides e.g. "cd0", "cd0s0". The old compatibility-slice partition "c" names are no longer generated and have been removed. Submitted-by: Alex Hornung , and Matthew Dillon --- sys/kern/kern_conf.c | 64 +++++------- sys/kern/kern_device.c | 75 +------------- sys/kern/subr_disk.c | 194 +++++++++++++++++++++++++----------- sys/kern/subr_disklabel32.c | 11 +- sys/kern/subr_disklabel64.c | 10 +- sys/kern/subr_diskmbr.c | 10 +- sys/kern/subr_diskslice.c | 49 +++++++-- sys/kern/vfs_conf.c | 17 +--- sys/kern/vfs_default.c | 12 +++ sys/kern/vfs_helper.c | 2 +- sys/kern/vfs_mount.c | 12 ++- sys/kern/vfs_subr.c | 17 +--- sys/kern/vfs_synth.c | 2 +- sys/kern/vfs_syscalls.c | 2 +- sys/sys/conf.h | 2 +- sys/sys/device.h | 1 - sys/sys/disk.h | 9 +- sys/sys/diskslice.h | 3 + sys/sys/vnioctl.h | 1 - sys/sys/vnode.h | 5 +- 20 files changed, 264 insertions(+), 234 deletions(-) diff --git a/sys/kern/kern_conf.c b/sys/kern/kern_conf.c index 09538fa796..ebccb53b11 100644 --- a/sys/kern/kern_conf.c +++ b/sys/kern/kern_conf.c @@ -177,7 +177,7 @@ hashdev(struct dev_ops *ops, int x, int y, int allow_intercept) dev_dclone(si); if (ops != &dead_dev_ops) ++ops->head.refs; - if (dev_ref_debug) { + if (dev_ref_debug & 1) { kprintf("create dev %p %s(minor=%08x) refs=%d\n", si, devtoname(si), y, si->si_sysref.refcnt); @@ -295,7 +295,9 @@ make_dev(struct dev_ops *ops, int minor, uid_t uid, gid_t gid, devfs_dev = devfs_new_cdev(ops, minor); memcpy(devfs_dev->si_name, dev_name, i+1); - devfs_debug(DEVFS_DEBUG_INFO, "make_dev called for %s\n", devfs_dev->si_name); + devfs_debug(DEVFS_DEBUG_INFO, + "make_dev called for %s\n", + devfs_dev->si_name); devfs_create_dev(devfs_dev, uid, gid, perms); return (devfs_dev); @@ -366,7 +368,9 @@ make_only_dev(struct dev_ops *ops, int minor, uid_t uid, gid_t gid, void destroy_only_dev(cdev_t dev) { - devfs_destroy_cdev(dev); + release_dev(dev); + release_dev(dev); + release_dev(dev); } @@ -426,40 +430,6 @@ destroy_dev(cdev_t dev) } } -/* - * Destroy all ad-hoc device associations associated with a domain within a - * device switch. Only the minor numbers are included in the mask/match - * values. - * - * Unlike the ops functions whos link structures do not contain - * any major bits, this function scans through the dev list via - * si_umajor/si_uminor. - * - * The caller must not include any major bits in the match value. - */ -void -destroy_all_devs(struct dev_ops *ops, u_int mask, u_int match) -{ - int i; - cdev_t dev; - cdev_t ndev; - - for (i = 0; i < DEVT_HASH; ++i) { - ndev = LIST_FIRST(&dev_hash[i]); - while ((dev = ndev) != NULL) { - ndev = LIST_NEXT(dev, si_hash); - if (dev->si_ops == ops && - ((u_int)dev->si_uminor & mask) == match - ) { - KKASSERT(dev->si_flags & SI_ADHOC); - reference_dev(dev); - destroy_dev(dev); - } - } - } -} - - int make_dev_alias(cdev_t target, const char *fmt, ...) { @@ -494,7 +464,7 @@ reference_dev(cdev_t dev) if (dev != NULL) { sysref_get(&dev->si_sysref); - if (dev_ref_debug) { + if (dev_ref_debug & 2) { kprintf("reference dev %p %s(minor=%08x) refs=%d\n", dev, devtoname(dev), dev->si_uminor, dev->si_sysref.refcnt); @@ -526,7 +496,7 @@ cdev_terminate(struct cdev *dev) { int messedup = 0; - if (dev_ref_debug) { + if (dev_ref_debug & 4) { kprintf("release dev %p %s(minor=%08x) refs=%d\n", dev, devtoname(dev), dev->si_uminor, dev->si_sysref.refcnt); @@ -536,12 +506,26 @@ cdev_terminate(struct cdev *dev) " device %p(%s), the device was never" " destroyed!\n", dev, devtoname(dev)); + if (dev_ref_debug & 0x8000) + Debugger("cdev_terminate"); messedup = 1; } if (dev->si_flags & SI_HASHED) { kprintf("Warning: last release on device, no call" " to destroy_dev() was made! dev %p(%s)\n", dev, devtoname(dev)); + if (dev_ref_debug & 0x8000) + Debugger("cdev_terminate"); + reference_dev(dev); + destroy_dev(dev); + messedup = 1; + } + if (dev->si_flags & SI_DEVFS_LINKED) { + kprintf("Warning: last release on device, still " + "devfs-linked dev %p(%s)\n", + dev, devtoname(dev)); + if (dev_ref_debug & 0x8000) + Debugger("cdev_terminate"); reference_dev(dev); destroy_dev(dev); messedup = 1; @@ -550,6 +534,8 @@ cdev_terminate(struct cdev *dev) kprintf("Warning: last release on device, vnode" " associations still exist! dev %p(%s)\n", dev, devtoname(dev)); + if (dev_ref_debug & 0x8000) + Debugger("cdev_terminate"); messedup = 1; } if (dev->si_ops && dev->si_ops != &dead_dev_ops) { diff --git a/sys/kern/kern_device.c b/sys/kern/kern_device.c index 8c5f869eb3..c87c1c1c0e 100644 --- a/sys/kern/kern_device.c +++ b/sys/kern/kern_device.c @@ -437,83 +437,14 @@ RB_GENERATE2(dev_ops_rb_tree, dev_ops_maj, rbnode, rb_dev_ops_compare, int, maj) struct dev_ops_rb_tree dev_ops_rbhead = RB_INITIALIZER(dev_ops_rbhead); -/* - * Remove all matching dev_ops entries from the dev_ops_array[] major - * array so no new user opens can be performed, and destroy all devices - * installed in the hash table that are associated with this dev_ops. (see - * destroy_all_devs()). - */ int -dev_ops_remove(struct dev_ops *ops, u_int mask, u_int match) -{ - struct dev_ops_maj *rbmaj; - struct dev_ops_link *link; - struct dev_ops_link **plink; - - if (ops != &dead_dev_ops) - destroy_all_devs(ops, mask, match); - - rbmaj = dev_ops_rb_tree_RB_LOOKUP(&dev_ops_rbhead, ops->head.maj); - if (rbmaj == NULL) { - kprintf("double-remove of dev_ops %p for %s(%d)\n", - ops, ops->head.name, ops->head.maj); - return(0); - } - for (plink = &rbmaj->link; (link = *plink) != NULL; - plink = &link->next) { - if (link->mask == mask && link->match == match) { - if (link->ops == ops) - break; - kprintf("%s: ERROR: cannot remove dev_ops, " - "its major number %d was stolen by %s\n", - ops->head.name, ops->head.maj, - link->ops->head.name - ); - } - } - if (link == NULL) { - kprintf("%s(%d)[%08x/%08x]: WARNING: ops removed " - "multiple times!\n", - ops->head.name, ops->head.maj, mask, match); - } else { - *plink = link->next; - --ops->head.refs; /* XXX ops_release() / record refs */ - kfree(link, M_DEVBUF); - } - - /* - * Scrap the RB tree node for the major number if no ops are - * installed any longer. - */ - if (rbmaj->link == NULL) { - dev_ops_rb_tree_RB_REMOVE(&dev_ops_rbhead, rbmaj); - kfree(rbmaj, M_DEVBUF); - } - -#if 0 - /* - * The same ops might be used with multiple devices, so don't - * complain if the ref count is non-zero. - */ - if (ops->head.refs != 0) { - kprintf("%s(%d)[%08x/%08x]: Warning: dev_ops_remove() called " - "while %d device refs still exist!\n", - ops->head.name, ops->head.maj, mask, match, - ops->head.refs); - } else { - if (bootverbose) - kprintf("%s: ops removed\n", ops->head.name); - } -#endif - return 0; -} - -int dev_ops_remove_all(struct dev_ops *ops) +dev_ops_remove_all(struct dev_ops *ops) { return devfs_destroy_dev_by_ops(ops, -1); } -int dev_ops_remove_minor(struct dev_ops *ops, int minor) +int +dev_ops_remove_minor(struct dev_ops *ops, int minor) { return devfs_destroy_dev_by_ops(ops, minor); } diff --git a/sys/kern/subr_disk.c b/sys/kern/subr_disk.c index 610d2249b6..8c35170d25 100644 --- a/sys/kern/subr_disk.c +++ b/sys/kern/subr_disk.c @@ -113,8 +113,9 @@ static MALLOC_DEFINE(M_DISK, "disk", "disk data"); static void disk_msg_autofree_reply(lwkt_port_t, lwkt_msg_t); static void disk_msg_core(void *); -static int disk_probe_slice(struct disk *dp, cdev_t dev, int slice); -static void disk_probe(struct disk *dp); +static int disk_probe_slice(struct disk *dp, cdev_t dev, int slice, int reprobe); +static void disk_probe(struct disk *dp, int reprobe); +static void _setdiskinfo(struct disk *disk, struct disk_info *info); static d_open_t diskopen; static d_close_t diskclose; @@ -149,7 +150,7 @@ static struct lwkt_port disk_msg_port; static int -disk_probe_slice(struct disk *dp, cdev_t dev, int slice) +disk_probe_slice(struct disk *dp, cdev_t dev, int slice, int reprobe) { struct disk_info *info = &dp->d_info; struct diskslice *sp = &dp->d_slice->dss_slices[slice]; @@ -169,8 +170,8 @@ disk_probe_slice(struct disk *dp, cdev_t dev, int slice) msg = ops->op_readdisklabel(dev, sp, &sp->ds_label, info); } devfs_debug(DEVFS_DEBUG_DEBUG, "disk_probe_slice: label: %s\n", (msg)?msg:"is NULL"); - devfs_debug(DEVFS_DEBUG_DEBUG, "disk_probe_slice: found %d partitions in the label\n", ops->op_getnumparts(sp->ds_label)); if (msg == NULL) { + devfs_debug(DEVFS_DEBUG_DEBUG, "disk_probe_slice: found %d partitions in the label\n", ops->op_getnumparts(sp->ds_label)); if (slice != WHOLE_DISK_SLICE) ops->op_adjust_label_reserved(dp->d_slice, slice, sp); else @@ -182,14 +183,24 @@ disk_probe_slice(struct disk *dp, cdev_t dev, int slice) ops->op_loadpartinfo(sp->ds_label, i, &part); devfs_debug(DEVFS_DEBUG_DEBUG, "disk_probe_slice: partinfo says fstype=%d for part %d\n", part.fstype, i); if (part.fstype) { - ndev = make_only_devfs_dev(&disk_ops, - dkmakeminor(dkunit(dp->d_cdev), slice, i), - UID_ROOT, GID_OPERATOR, 0640, - "%s%c", dev->si_name, 'a'+ (char)i); + if (reprobe && + (ndev = devfs_find_device_by_name("%s%c", + dev->si_name, 'a'+ (char)i))) { + /* Device already exists and is still valid */ + devfs_debug(DEVFS_DEBUG_DEBUG, "disk_probe_slice: reprobing and device remained valid, mark it\n"); + ndev->si_flags |= SI_REPROBE_TEST; + } else { + ndev = make_dev(&disk_ops, + dkmakeminor(dkunit(dp->d_cdev), slice, i), + UID_ROOT, GID_OPERATOR, 0640, + "%s%c", dev->si_name, 'a'+ (char)i); #if 0 - make_dev_alias(ndev, "disk-by-id/diskTEST-sliceTEST-part%d", i); + make_dev_alias(ndev, "disk-by-id/diskTEST-sliceTEST-part%d", i); #endif - ndev->si_disk = dp; + ndev->si_disk = dp; + ndev->si_flags |= SI_REPROBE_TEST; + } + devfs_debug(DEVFS_DEBUG_DEBUG, "disk_probe_slice:end: lp.opaque: %x\n", ndev->si_disk->d_slice->dss_slices[slice].ds_label.opaque); } } @@ -215,7 +226,7 @@ disk_probe_slice(struct disk *dp, cdev_t dev, int slice) static void -disk_probe(struct disk *dp) +disk_probe(struct disk *dp, int reprobe) { struct disk_info *info = &dp->d_info; cdev_t dev = dp->d_cdev; @@ -238,33 +249,54 @@ disk_probe(struct disk *dp) if (dp->d_slice->dss_nslices == BASE_SLICE) { dp->d_slice->dss_slices[COMPATIBILITY_SLICE].ds_size = info->d_media_blocks; dp->d_slice->dss_slices[COMPATIBILITY_SLICE].ds_reserved = 0; - ndev = make_only_devfs_dev(&disk_ops, - dkmakewholeslice(dkunit(dev), COMPATIBILITY_SLICE), - UID_ROOT, GID_OPERATOR, 0640, - "%ss%d", dev->si_name, COMPATIBILITY_SLICE); + if (reprobe && + (ndev = devfs_find_device_by_name("%ss%d", + dev->si_name, COMPATIBILITY_SLICE))) { + /* Device already exists and is still valid */ + devfs_debug(DEVFS_DEBUG_DEBUG, "disk_probe: reprobing and device remained valid, mark it\n"); + ndev->si_flags |= SI_REPROBE_TEST; + } else { + ndev = make_dev(&disk_ops, + dkmakewholeslice(dkunit(dev), COMPATIBILITY_SLICE), + UID_ROOT, GID_OPERATOR, 0640, + "%ss%d", dev->si_name, COMPATIBILITY_SLICE); + + ndev->si_disk = dp; + ndev->si_flags |= SI_REPROBE_TEST; + } - ndev->si_disk = dp; dp->d_slice->dss_slices[COMPATIBILITY_SLICE].ds_dev = ndev; devfs_debug(DEVFS_DEBUG_DEBUG, "disk_probe: type of slice is :%x\n", dp->d_slice->dss_slices[COMPATIBILITY_SLICE].ds_type ); - //if (dp->d_slice->dss_slices[COMPATIBILITY_SLICE].ds_type == DOSPTYP_386BSD) { + dp->d_slice->dss_first_bsd_slice = COMPATIBILITY_SLICE; - disk_probe_slice(dp, ndev, COMPATIBILITY_SLICE); - //} + disk_probe_slice(dp, ndev, COMPATIBILITY_SLICE, reprobe); + } for (i = BASE_SLICE; i < dp->d_slice->dss_nslices; i++) { - ndev = make_only_devfs_dev(&disk_ops, - dkmakewholeslice(dkunit(dev), i), - UID_ROOT, GID_OPERATOR, 0640, - "%ss%d", dev->si_name, i-1); - make_dev_alias(ndev, "disk-by-id/diskTEST-slice%d", i-1); - - ndev->si_disk = dp; + if (reprobe && + (ndev = devfs_find_device_by_name("%ss%d", + dev->si_name, i-1))) { + /* Device already exists and is still valid */ + devfs_debug(DEVFS_DEBUG_DEBUG, "disk_probe: reprobing and device remained valid, mark it\n"); + ndev->si_flags |= SI_REPROBE_TEST; + } else { + ndev = make_dev(&disk_ops, + dkmakewholeslice(dkunit(dev), i), + UID_ROOT, GID_OPERATOR, 0640, + "%ss%d", dev->si_name, i-1); +#if 0 + make_dev_alias(ndev, "disk-by-id/diskTEST-slice%d", i-1); +#endif + ndev->si_disk = dp; + ndev->si_flags |= SI_REPROBE_TEST; + } + dp->d_slice->dss_slices[i].ds_reserved = 0; dp->d_slice->dss_slices[i].ds_dev = ndev; devfs_debug(DEVFS_DEBUG_DEBUG, "disk_probe-> type of slice is :%x\n", dp->d_slice->dss_slices[i].ds_type ); if (dp->d_slice->dss_slices[i].ds_type == DOSPTYP_386BSD) { if (!dp->d_slice->dss_first_bsd_slice) dp->d_slice->dss_first_bsd_slice = i; - disk_probe_slice(dp, ndev, i); + disk_probe_slice(dp, ndev, i, reprobe); } } } @@ -291,27 +323,43 @@ disk_msg_core(void *arg) case DISK_DISK_PROBE: dp = (struct disk *)msg->load; - disk_probe(dp); + disk_probe(dp, 0); break; case DISK_DISK_DESTROY: dp = (struct disk *)msg->load; devfs_destroy_subnames(dp->d_cdev->si_name); devfs_destroy_dev(dp->d_cdev); + LIST_REMOVE(dp, d_list); //devfs_destroy_dev(dp->d_rawdev); //XXX: needed? when? break; + case DISK_UNPROBE: + dp = (struct disk *)msg->load; + devfs_destroy_subnames(dp->d_cdev->si_name); + break; + case DISK_SLICE_REPROBE: dp = (struct disk *)msg->load; sp = (struct diskslice *)msg->load2; - devfs_destroy_subnames(sp->ds_dev->si_name); - disk_probe_slice(dp, sp->ds_dev, dkslice(sp->ds_dev)); + devfs_clr_subnames_flag(sp->ds_dev->si_name, SI_REPROBE_TEST); + devfs_debug(DEVFS_DEBUG_DEBUG, + "DISK_SLICE_REPROBE: %s\n", + sp->ds_dev->si_name); + disk_probe_slice(dp, sp->ds_dev, dkslice(sp->ds_dev), 1); + devfs_destroy_subnames_without_flag(sp->ds_dev->si_name, + SI_REPROBE_TEST); break; case DISK_DISK_REPROBE: dp = (struct disk *)msg->load; - devfs_destroy_subnames(dp->d_cdev->si_name); - disk_probe(dp); + devfs_clr_subnames_flag(dp->d_cdev->si_name, SI_REPROBE_TEST); + devfs_debug(DEVFS_DEBUG_DEBUG, + "DISK_DISK_REPROBE: %s\n", + dp->d_cdev->si_name); + disk_probe(dp, 1); + devfs_destroy_subnames_without_flag(dp->d_cdev->si_name, + SI_REPROBE_TEST); break; case DISK_SYNC: @@ -355,6 +403,26 @@ disk_msg_send(uint32_t cmd, void *load, void *load2) lwkt_sendmsg(port, (lwkt_msg_t)disk_msg); } +void +disk_msg_send_sync(uint32_t cmd, void *load, void *load2) +{ + struct lwkt_port rep_port; + disk_msg_t disk_msg = objcache_get(disk_msg_cache, M_WAITOK); + disk_msg_t msg_incoming; + lwkt_port_t port = &disk_msg_port; + + lwkt_initport_thread(&rep_port, curthread); + lwkt_initmsg(&disk_msg->hdr, &rep_port, 0); + + disk_msg->hdr.u.ms_result = cmd; + disk_msg->load = load; + disk_msg->load2 = load2; + + KKASSERT(port); + lwkt_sendmsg(port, (lwkt_msg_t)disk_msg); + msg_incoming = lwkt_waitport(&rep_port, 0); +} + /* * Create a raw device for the dev_ops template (which is returned). Also * create a slice and unit managed disk and overload the user visible @@ -380,28 +448,23 @@ disk_create(int unit, struct disk *dp, struct dev_ops *raw_ops) dp->d_rawdev = rawdev; dp->d_raw_ops = raw_ops; dp->d_dev_ops = &disk_ops; - dp->d_cdev = make_only_devfs_dev(&disk_ops, + dp->d_cdev = make_dev(&disk_ops, dkmakewholedisk(unit), UID_ROOT, GID_OPERATOR, 0640, "%s%d", raw_ops->head.name, unit); dp->d_cdev->si_disk = dp; - disk_ops.head.data = dp; - devfs_debug(DEVFS_DEBUG_DEBUG, "disk_create called for %s\n", dp->d_cdev->si_name); LIST_INSERT_HEAD(&disklist, dp, d_list); return (dp->d_rawdev); } -/* - * Disk drivers must call this routine when media parameters are available - * or have changed. - */ -void -disk_setdiskinfo(struct disk *disk, struct disk_info *info) + +static void +_setdiskinfo(struct disk *disk, struct disk_info *info) { - devfs_debug(DEVFS_DEBUG_DEBUG, "disk_setdiskinfo called for disk -1-: %x\n", disk); + devfs_debug(DEVFS_DEBUG_DEBUG, "_setdiskinfo called for disk -1-: %x\n", disk); bcopy(info, &disk->d_info, sizeof(disk->d_info)); info = &disk->d_info; @@ -427,11 +490,28 @@ disk_setdiskinfo(struct disk *disk, struct disk_info *info) disk->d_cdev->si_bsize_phys = disk->d_rawdev->si_bsize_phys; disk->d_cdev->si_bsize_best = disk->d_rawdev->si_bsize_best; } +} +/* + * Disk drivers must call this routine when media parameters are available + * or have changed. + */ +void +disk_setdiskinfo(struct disk *disk, struct disk_info *info) +{ + _setdiskinfo(disk, info); devfs_debug(DEVFS_DEBUG_DEBUG, "disk_setdiskinfo called for disk -2-: %x\n", disk); disk_msg_send(DISK_DISK_PROBE, disk, NULL); } +void +disk_setdiskinfo_sync(struct disk *disk, struct disk_info *info) +{ + _setdiskinfo(disk, info); + devfs_debug(DEVFS_DEBUG_DEBUG, "disk_setdiskinfo_sync called for disk -2-: %x\n", disk); + disk_msg_send_sync(DISK_DISK_PROBE, disk, NULL); +} + /* * This routine is called when an adapter detaches. The higher level * managed disk device is destroyed while the lower level raw device is @@ -440,7 +520,7 @@ disk_setdiskinfo(struct disk *disk, struct disk_info *info) void disk_destroy(struct disk *disk) { - disk_msg_send(DISK_DISK_DESTROY, disk, NULL); + disk_msg_send_sync(DISK_DISK_DESTROY, disk, NULL); return; } @@ -466,6 +546,15 @@ disk_dumpcheck(cdev_t dev, u_int64_t *count, u_int64_t *blkno, u_int *secsize) return (0); } +void +disk_unprobe(struct disk *disk) +{ + if (disk == NULL) + return; + + disk_msg_send_sync(DISK_UNPROBE, disk, NULL); +} + void disk_invalidate (struct disk *disk) { @@ -712,8 +801,8 @@ diskclone(struct dev_clone_args *ap) { cdev_t dev = ap->a_head.a_dev; struct disk *dp; -//XXX: need changes for devfs - dp = dev->si_ops->head.data; + dp = dev->si_disk; + KKASSERT(dp != NULL); dev->si_disk = dp; dev->si_iosize_max = dp->d_rawdev->si_iosize_max; @@ -726,7 +815,7 @@ int diskdump(struct dev_dump_args *ap) { cdev_t dev = ap->a_head.a_dev; - struct disk *dp = dev->si_ops->head.data; + struct disk *dp = dev->si_disk; int error; error = disk_dumpcheck(dev, &ap->a_count, &ap->a_blkno, &ap->a_secsize); @@ -908,18 +997,7 @@ disk_locate(const char *devname) void disk_config(void *arg) { - struct lwkt_port rep_port; - disk_msg_t disk_msg = objcache_get(disk_msg_cache, M_WAITOK); - disk_msg_t msg_incoming; - lwkt_port_t port = &disk_msg_port; - - lwkt_initport_thread(&rep_port, curthread); - lwkt_initmsg(&disk_msg->hdr, &rep_port, 0); - kprintf("disk_config: sync'ing up\n"); - disk_msg->hdr.u.ms_result = DISK_SYNC; - - lwkt_sendmsg(port, (lwkt_msg_t)disk_msg); - msg_incoming = lwkt_waitport(&rep_port, 0); + disk_msg_send_sync(DISK_SYNC, NULL, NULL); } diff --git a/sys/kern/subr_disklabel32.c b/sys/kern/subr_disklabel32.c index 803c3bbbdd..c12b1e5d90 100644 --- a/sys/kern/subr_disklabel32.c +++ b/sys/kern/subr_disklabel32.c @@ -306,10 +306,6 @@ l32_writedisklabel(cdev_t dev, struct diskslices *ssp, struct diskslice *sp, if (lp->d_partitions[RAW_PART].p_offset != 0) return (EXDEV); /* not quite right */ - kprintf("this is l32_writedisklabel: part: %d, slice: %d\n", dkpart(dev), dkslice(dev)); - kprintf("Avoiding disaster and returning now\n"); - return 0; - bp = geteblk((int)lp->d_secsize); bp->b_bio1.bio_offset = (off_t)LABELSECTOR32 * lp->d_secsize; bp->b_bio1.bio_done = biodone_sync; @@ -326,7 +322,8 @@ l32_writedisklabel(cdev_t dev, struct diskslices *ssp, struct diskslice *sp, */ bp->b_flags &= ~B_INVAL; bp->b_cmd = BUF_CMD_READ; - dev_dstrategy(dkmodpart(dev, WHOLE_SLICE_PART), &bp->b_bio1); + KKASSERT(dkpart(dev) == WHOLE_SLICE_PART); + dev_dstrategy(dev, &bp->b_bio1); error = biowait(&bp->b_bio1, "labrd"); if (error) goto done; @@ -345,8 +342,8 @@ l32_writedisklabel(cdev_t dev, struct diskslices *ssp, struct diskslice *sp, bp->b_cmd = BUF_CMD_WRITE; bp->b_bio1.bio_done = biodone_sync; bp->b_bio1.bio_flags |= BIO_SYNC; - dev_dstrategy(dkmodpart(dev, WHOLE_SLICE_PART), - &bp->b_bio1); + KKASSERT(dkpart(dev) == WHOLE_SLICE_PART); + dev_dstrategy(dev, &bp->b_bio1); error = biowait(&bp->b_bio1, "labwr"); } goto done; diff --git a/sys/kern/subr_disklabel64.c b/sys/kern/subr_disklabel64.c index 46b9a90fd6..a63e8b31a3 100644 --- a/sys/kern/subr_disklabel64.c +++ b/sys/kern/subr_disklabel64.c @@ -294,10 +294,6 @@ l64_writedisklabel(cdev_t dev, struct diskslices *ssp, lp = lpx.lab64; - kprintf("this is l64_writedisklabel: part: %d, slice: %d\n", dkpart(dev), dkslice(dev)); - kprintf("Avoiding disaster and returning now\n"); - return 0; - /* * XXX I/O size is subject to device DMA limitations */ @@ -316,7 +312,8 @@ l64_writedisklabel(cdev_t dev, struct diskslices *ssp, */ bp->b_flags &= ~B_INVAL; bp->b_cmd = BUF_CMD_READ; - dev_dstrategy(dkmodpart(dev, WHOLE_SLICE_PART), &bp->b_bio1); + KKASSERT(dkpart(dev) == WHOLE_SLICE_PART); + dev_dstrategy(dev, &bp->b_bio1); error = biowait(&bp->b_bio1, "labrd"); if (error) goto done; @@ -327,7 +324,8 @@ l64_writedisklabel(cdev_t dev, struct diskslices *ssp, bp->b_cmd = BUF_CMD_WRITE; bp->b_bio1.bio_done = biodone_sync; bp->b_bio1.bio_flags |= BIO_SYNC; - dev_dstrategy(dkmodpart(dev, WHOLE_SLICE_PART), &bp->b_bio1); + KKASSERT(dkpart(dev) == WHOLE_SLICE_PART); + dev_dstrategy(dev, &bp->b_bio1); error = biowait(&bp->b_bio1, "labwr"); done: bp->b_flags |= B_INVAL | B_AGE; diff --git a/sys/kern/subr_diskmbr.c b/sys/kern/subr_diskmbr.c index 4d0c385432..0ac4506594 100644 --- a/sys/kern/subr_diskmbr.c +++ b/sys/kern/subr_diskmbr.c @@ -130,10 +130,12 @@ reread_mbr: bp->b_cmd = BUF_CMD_READ; dev_dstrategy(wdev, &bp->b_bio1); if (biowait(&bp->b_bio1, "mbrrd") != 0) { - diskerr(&bp->b_bio1, wdev, - "reading primary partition table: error", - LOG_PRINTF, 0); - kprintf("\n"); + if ((info->d_dsflags & DSO_MBRQUIET) == 0) { + diskerr(&bp->b_bio1, wdev, + "reading primary partition table: error", + LOG_PRINTF, 0); + kprintf("\n"); + } error = EIO; goto done; } diff --git a/sys/kern/subr_diskslice.c b/sys/kern/subr_diskslice.c index db3c148d12..dfe819c6f0 100644 --- a/sys/kern/subr_diskslice.c +++ b/sys/kern/subr_diskslice.c @@ -178,6 +178,13 @@ doshift: nbio->bio_offset = bio->bio_offset | (u_int64_t)part << 56; return(nbio); + } else { + /* + * If writing to the raw disk request a + * reprobe on the last close. + */ + if (bp->b_cmd == BUF_CMD_WRITE) + sp->ds_flags |= DSF_REPROBE; } /* @@ -219,11 +226,16 @@ doshift: /* * Disallow writes to reserved areas unless ds_wlabel allows it. + * If the reserved area is written to request a reprobe of the + * disklabel when the slice is closed. */ if (slicerel_secno < sp->ds_reserved && nsec && - bp->b_cmd == BUF_CMD_WRITE && sp->ds_wlabel == 0) { - bp->b_error = EROFS; - goto error; + bp->b_cmd == BUF_CMD_WRITE) { + if (sp->ds_wlabel == 0) { + bp->b_error = EROFS; + goto error; + } + sp->ds_flags |= DSF_REPROBE; } /* @@ -302,6 +314,13 @@ done: return (NULL); } +/* + * dsclose() - close a cooked disk slice. + * + * WARNING! The passed diskslices and related diskslice structures may + * be invalidated or replaced by this function, callers must + * reload from the disk structure for continued access. + */ void dsclose(cdev_t dev, int mode, struct diskslices *ssp) { @@ -314,6 +333,19 @@ dsclose(cdev_t dev, int mode, struct diskslices *ssp) if (slice < ssp->dss_nslices) { sp = &ssp->dss_slices[slice]; dsclrmask(sp, part); + if (sp->ds_flags & DSF_REPROBE) { + sp->ds_flags &= ~DSF_REPROBE; + if (slice == WHOLE_DISK_SLICE) { + kprintf("reprobe whole disk\n"); + disk_msg_send_sync(DISK_DISK_REPROBE, + dev->si_disk, NULL); + } else { + kprintf("reprobe slice\n"); + disk_msg_send_sync(DISK_SLICE_REPROBE, + dev->si_disk, sp); + } + /* ssp and sp may both be invalid after reprobe */ + } } } @@ -542,7 +574,7 @@ dsioctl(cdev_t dev, u_long cmd, caddr_t data, int flags, lptmp.opaque = data; error = ops->op_setdisklabel(lp, lptmp, ssp, sp, openmask); //XXX: send reprobe message here. - disk_msg_send(DISK_SLICE_REPROBE, dev->si_disk, sp); + disk_msg_send_sync(DISK_SLICE_REPROBE, dev->si_disk, sp); if (error != 0) { kfree(lp.opaque, M_DEVBUF); return (error); @@ -577,9 +609,9 @@ dsioctl(cdev_t dev, u_long cmd, caddr_t data, int flags, } } - disk_msg_send(DISK_DISK_REPROBE, dev->si_disk, NULL); + disk_msg_send_sync(DISK_DISK_REPROBE, dev->si_disk, NULL); return 0; - +#if 0 /* * Temporarily forget the current slices struct and read * the current one. @@ -620,6 +652,7 @@ dsioctl(cdev_t dev, u_long cmd, caddr_t data, int flags, //XXX: recheck this... dsgone(&ssp); return (0); +#endif case DIOCWDINFO32: case DIOCWDINFO64: @@ -628,6 +661,8 @@ dsioctl(cdev_t dev, u_long cmd, caddr_t data, int flags, data, flags, &ssp, info); if (error == 0 && sp->ds_label.opaque == NULL) error = EINVAL; + if (part != WHOLE_SLICE_PART) + error = EINVAL; if (error != 0) return (error); @@ -640,7 +675,7 @@ dsioctl(cdev_t dev, u_long cmd, caddr_t data, int flags, old_wlabel = sp->ds_wlabel; set_ds_wlabel(ssp, slice, TRUE); error = ops->op_writedisklabel(dev, ssp, sp, sp->ds_label); - disk_msg_send(DISK_SLICE_REPROBE, dev->si_disk, sp); + disk_msg_send_sync(DISK_SLICE_REPROBE, dev->si_disk, sp); set_ds_wlabel(ssp, slice, old_wlabel); /* XXX should invalidate in-core label if write failed. */ return (error); diff --git a/sys/kern/vfs_conf.c b/sys/kern/vfs_conf.c index 8aaf597353..f03ccca41d 100644 --- a/sys/kern/vfs_conf.c +++ b/sys/kern/vfs_conf.c @@ -78,22 +78,13 @@ struct nchandle rootnch; /* * The root specifiers we will try if RB_CDROM is specified. Note that - * the ATA driver will accept acd*a and acd*c, but the SCSI driver - * will only accept cd*c, so use 'c'. - * - * XXX TGEN NATA and, presumably, 'old'ATA will also accept the device name - * without any fake partition, since the major & minor are identical for all - * three (acd*, acd*a and acd*c). However, due to an as-of-yet undiscovered - * bug, acd0c ends up with minor 2 when using NATA and booting cold. Since - * NATA's acd_open() is unable to fulfill mounts on such 'ghost' cdevs, acd0 - * and acd1 have been added to the list of CD-ROM root device names. + * with DEVFS we do not use the compatibility slice's whole-disk 'c' + * partition. Instead we just use the whole disk, e.g. cd0 or cd0s0. */ static char *cdrom_rootdevnames[] = { - "cd9660:cd0c", - "cd9660:acd0c", - "cd9660:cd1c", - "cd9660:acd1c", + "cd9660:cd0", "cd9660:acd0", + "cd9660:cd1", "cd9660:acd1", NULL }; diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c index 1f23f23e73..aae946ad87 100644 --- a/sys/kern/vfs_default.c +++ b/sys/kern/vfs_default.c @@ -1281,6 +1281,18 @@ vop_stdputpages(struct vop_putpages_args *ap) return (error); } +int +vop_stdnoread(struct vop_read_args *ap) +{ + return (EINVAL); +} + +int +vop_stdnowrite(struct vop_write_args *ap) +{ + return (EINVAL); +} + /* * vfs default ops * used to fill the vfs fucntion table to get reasonable default return values. diff --git a/sys/kern/vfs_helper.c b/sys/kern/vfs_helper.c index 9a1808d8aa..6f67ac18a3 100644 --- a/sys/kern/vfs_helper.c +++ b/sys/kern/vfs_helper.c @@ -215,7 +215,7 @@ vop_helper_chmod(struct vnode *vp, mode_t new_mode, struct ucred *cred, */ if (vp->v_type == VCHR && cur_uid == 0) { if ((dev = vp->v_rdev) == NULL) - dev = get_dev(vp->v_umajor, vp->v_uminor); + cur_uid = 0; if (dev) cur_uid = dev->si_uid; } diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c index 2a9976c6d5..4e069a1657 100644 --- a/sys/kern/vfs_mount.c +++ b/sys/kern/vfs_mount.c @@ -1174,17 +1174,23 @@ vflush_scan(struct mount *mp, struct vnode *vp, void *data) /* * If FORCECLOSE is set, forcibly close the vnode. For block - * or character devices, revert to an anonymous device. For - * all other files, just kill them. + * or character devices we just clean and leave the vp + * associated with devfs. For all other files, just kill them. + * + * XXX we need to do something about devfs here, I'd rather not + * blow away device associations. */ if (info->flags & FORCECLOSE) { + vgone_vxlocked(vp); +#if 0 if (vp->v_type != VBLK && vp->v_type != VCHR) { vgone_vxlocked(vp); } else { vclean_vxlocked(vp, 0); - vp->v_ops = &spec_vnode_vops_p; + /*vp->v_ops = &devfs_vnode_dev_vops_p;*/ insmntque(vp, NULL); } +#endif return(0); } #ifdef DIAGNOSTIC diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 56866d49cb..1661b7229f 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -131,8 +131,6 @@ static int vfs_free_netcred (struct radix_node *rn, void *w); static int vfs_hang_addrlist (struct mount *mp, struct netexport *nep, const struct export_args *argp); -extern int dev_ref_debug; - /* * Red black tree functions */ @@ -980,7 +978,8 @@ bdevvp(cdev_t dev, struct vnode **vpp) *vpp = NULLVP; return (ENXIO); } - error = getspecialvnode(VT_NON, NULL, &devfs_vnode_dev_vops_p/*&spec_vnode_vops_p*/, &nvp, 0, 0); + error = getspecialvnode(VT_NON, NULL, &devfs_vnode_dev_vops_p, + &nvp, 0, 0); if (error) { *vpp = NULLVP; return (error); @@ -1005,8 +1004,6 @@ v_associate_rdev(struct vnode *vp, cdev_t dev) if (dev_is_good(dev) == 0) return(ENXIO); KKASSERT(vp->v_rdev == NULL); - if (dev_ref_debug) - kprintf("Z1"); vp->v_rdev = reference_dev(dev); lwkt_gettoken(&ilock, &spechash_token); SLIST_INSERT_HEAD(&dev->si_hlist, vp, v_cdevnext); @@ -1373,16 +1370,6 @@ count_dev(cdev_t dev) return(count); } -int -count_udev(int x, int y) -{ - cdev_t dev; - - if ((dev = get_dev(x, y)) == NULL) - return(0); - return(count_dev(dev)); -} - int vcount(struct vnode *vp) { diff --git a/sys/kern/vfs_synth.c b/sys/kern/vfs_synth.c index e9c9286769..64173f7f26 100644 --- a/sys/kern/vfs_synth.c +++ b/sys/kern/vfs_synth.c @@ -89,7 +89,7 @@ static int synth_inactive(struct vop_inactive_args *ap); static int synth_reclaim(struct vop_reclaim_args *ap); struct vop_ops synth_vnode_vops = { - .vop_default = spec_vnoperate, + .vop_default = vop_defaultop, .vop_inactive = synth_inactive, .vop_reclaim = synth_reclaim }; diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 77a7ea6908..3929ac3c84 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -3647,7 +3647,7 @@ sys_revoke(struct revoke_args *uap) if (error == 0 && cred->cr_uid != vattr.va_uid) error = priv_check_cred(cred, PRIV_VFS_REVOKE, 0); if (error == 0 && (vp->v_type == VCHR || vp->v_type == VBLK)) { - if (count_udev(vp->v_umajor, vp->v_uminor) > 0) + if (vcount(vp) > 0) error = vrevoke(vp, cred); } else if (error == 0) { error = vrevoke(vp, cred); diff --git a/sys/sys/conf.h b/sys/sys/conf.h index 5937d91e27..49de63ecc9 100644 --- a/sys/sys/conf.h +++ b/sys/sys/conf.h @@ -104,6 +104,7 @@ struct cdev { #define SI_ADHOC 0x0004 /* created via make_adhoc_dev() or udev2dev() */ #define SI_INTERCEPTED 0x0008 /* device ops was intercepted */ #define SI_DEVFS_LINKED 0x0010 +#define SI_REPROBE_TEST 0x0020 #define si_tty __si_u.__si_tty.__sit_tty #define si_disk __si_u.__si_disk.__sid_disk @@ -203,7 +204,6 @@ static moduledata_t name##_mod = { \ DECLARE_MODULE(name, name##_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE) int count_dev (cdev_t dev); -int count_udev (int x, int y); void destroy_dev (cdev_t dev); void release_dev (cdev_t dev); cdev_t get_dev (int x, int y); diff --git a/sys/sys/device.h b/sys/sys/device.h index 4daccca725..dbd794d6bc 100644 --- a/sys/sys/device.h +++ b/sys/sys/device.h @@ -359,7 +359,6 @@ void dev_ops_release(struct dev_ops *); struct dev_ops *dev_ops_intercept(cdev_t, struct dev_ops *); void dev_ops_restore(cdev_t, struct dev_ops *); -void destroy_all_devs(struct dev_ops *, u_int mask, u_int match); cdev_t make_dev(struct dev_ops *ops, int minor, uid_t uid, gid_t gid, int perms, const char *fmt, ...) __printflike(6, 7); cdev_t make_adhoc_dev (struct dev_ops *ops, int minor); diff --git a/sys/sys/disk.h b/sys/sys/disk.h index 5c7fbe1db5..c22c290cb0 100644 --- a/sys/sys/disk.h +++ b/sys/sys/disk.h @@ -100,6 +100,9 @@ struct disk_info { * * COMPARTMBR - used by the vn device to request that one sector be * reserved as if an MBR were present even when one isn't. + * + * MBRQUIET - silently ignore MBR probe if unable to read sector 0. + * used by VN. */ #define DSO_NOLABELS 0x0001 #define DSO_ONESLICE 0x0002 @@ -107,6 +110,7 @@ struct disk_info { #define DSO_COMPATPARTA 0x0008 #define DSO_COMPATMBR 0x0010 #define DSO_RAWEXTENSIONS 0x0020 +#define DSO_MBRQUIET 0x0040 /* * Disk management structure - automated disklabel support. @@ -133,12 +137,14 @@ cdev_t disk_create (int unit, struct disk *disk, struct dev_ops *raw_ops); cdev_t disk_locate (const char *devname); void disk_destroy (struct disk *disk); void disk_setdiskinfo (struct disk *disk, struct disk_info *info); +void disk_setdiskinfo_sync(struct disk *disk, struct disk_info *info); int disk_dumpcheck (cdev_t dev, u_int64_t *count, u_int64_t *blkno, u_int *secsize); struct disk *disk_enumerate (struct disk *disk); void disk_invalidate (struct disk *disk); - +void disk_unprobe(struct disk *disk); void disk_msg_send(uint32_t cmd, void *load, void *load2); +void disk_msg_send_sync(uint32_t cmd, void *load, void *load2); void disk_config(void *); typedef struct disk_msg { @@ -152,6 +158,7 @@ typedef struct disk_msg { #define DISK_DISK_DESTROY 0x02 #define DISK_SLICE_REPROBE 0x03 #define DISK_DISK_REPROBE 0x04 +#define DISK_UNPROBE 0x05 #define DISK_SYNC 0x99 diff --git a/sys/sys/diskslice.h b/sys/sys/diskslice.h index dce173c777..9fe748f6a1 100644 --- a/sys/sys/diskslice.h +++ b/sys/sys/diskslice.h @@ -141,6 +141,7 @@ struct diskslice { struct uuid ds_type_uuid; /* slice type uuid */ struct uuid ds_stor_uuid; /* slice storage unique uuid */ int ds_type; /* (foreign) slice type */ + int ds_flags; /* DSF_ flags */ disklabel_t ds_label; /* label, if any */ struct disklabel_ops *ds_ops; /* label ops (probe default) */ //void *ds_dev; /* devfs token for raw whole slice */ @@ -151,6 +152,8 @@ struct diskslice { int ds_ttlopens; /* total opens, incl slice & raw */ }; +#define DSF_REPROBE 0x0001 /* sniffer wants us to reprobe */ + struct diskslices { struct cdevsw *dss_cdevsw; /* for containing device */ int dss_first_bsd_slice; /* COMPATIBILITY_SLICE is mapped here */ diff --git a/sys/sys/vnioctl.h b/sys/sys/vnioctl.h index 3e93e4ba6a..f76ae3b930 100644 --- a/sys/sys/vnioctl.h +++ b/sys/sys/vnioctl.h @@ -111,7 +111,6 @@ struct vn_user { #define VNIOCUCLEAR _IOWR('F', 5, u_long ) /* reset --//-- */ #define VNIOCGET _IOWR('F', 6, struct vn_user) /* get disk info */ -#define VN_LABELS 0x1 /* Use disk(/slice) labels */ #define VN_FOLLOW 0x2 /* Debug flow in vn driver */ #define VN_DEBUG 0x4 /* Debug data in vn driver */ #define VN_IO 0x8 /* Debug I/O in vn driver */ diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index 7dda21e843..229434925a 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -463,7 +463,6 @@ int getnewvnode (enum vtagtype tag, struct mount *mp, int getspecialvnode (enum vtagtype tag, struct mount *mp, struct vop_ops **ops, struct vnode **vpp, int timo, int lkflags); -int spec_vnoperate (struct vop_generic_args *); int speedup_syncer (void); void vattr_null (struct vattr *vap); int vcount (struct vnode *vp); @@ -530,6 +529,8 @@ int vop_stdclose (struct vop_close_args *ap); int vop_stdgetpages(struct vop_getpages_args *ap); int vop_stdputpages(struct vop_putpages_args *ap); int vop_stdmarkatime(struct vop_markatime_args *ap); +int vop_stdnoread(struct vop_read_args *ap); +int vop_stdnowrite(struct vop_write_args *ap); int vop_nopoll (struct vop_poll_args *ap); int vop_stdpathconf (struct vop_pathconf_args *ap); int vop_stdpoll (struct vop_poll_args *ap); @@ -578,11 +579,9 @@ void vn_syncer_add_to_worklist(struct vnode *, int); void vnlru_proc_wait(void); extern struct vop_ops default_vnode_vops; -extern struct vop_ops spec_vnode_vops; extern struct vop_ops dead_vnode_vops; extern struct vop_ops *default_vnode_vops_p; -extern struct vop_ops *spec_vnode_vops_p; extern struct vop_ops *dead_vnode_vops_p; #endif /* _KERNEL */ -- 2.41.0