Index: lib/libgeom/Makefile =================================================================== RCS file: /zoo/pjd/repo/src/lib/libgeom/Makefile,v retrieving revision 1.10 diff -u -p -r1.10 Makefile --- lib/libgeom/Makefile 7 Mar 2004 16:07:57 -0000 1.10 +++ lib/libgeom/Makefile 27 Apr 2007 19:07:24 -0000 @@ -6,6 +6,7 @@ SRCS+= geom_getxml.c SRCS+= geom_stats.c SRCS+= geom_xml2tree.c SRCS+= geom_ctl.c +SRCS+= geom_util.c INCS= libgeom.h CFLAGS += -I${.CURDIR} Index: lib/libgeom/geom_util.c =================================================================== RCS file: lib/libgeom/geom_util.c diff -N lib/libgeom/geom_util.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libgeom/geom_util.c 28 Apr 2007 21:15:40 -0000 @@ -0,0 +1,214 @@ +/*- + * Copyright (c) 2007 Pawel Jakub Dawidek + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* + * Open the given provider and at least check if this is a block device. + */ +static int +g_open(const char *name, int write) +{ + char path[MAXPATHLEN]; + struct stat sb; + int fd; + + if (name[0] == '/') + strlcpy(path, name, sizeof(path)); + else + snprintf(path, sizeof(path), "%s%s", _PATH_DEV, name); + + fd = open(path, write ? O_RDWR : O_RDONLY); + if (fd == -1) + return (-1); + if (fstat(fd, &sb) == -1 || !S_ISCHR(sb.st_mode)) { + close(fd); + return (-1); + } + return (fd); +} + +static int +g_close(int fd) +{ + + close(fd); +} + +static int +g_ioctl_arg(const char *name, int write, unsigned long cmd, void *arg) +{ + int fd, ret = -1; + + fd = g_open(name, write); + if (fd >= 0) { + if (arg != NULL) + ret = ioctl(fd, cmd, arg); + else + ret = ioctl(fd, cmd); + g_close(fd); + } + return (ret >= 0 ? 0 : -1); +} + +static int +g_ioctl(const char *name, int write, unsigned long cmd) +{ + + return (g_ioctl_arg(name, write, cmd, NULL)); +} + +/* + * Return media size of the given provider. + */ +off_t +g_mediasize(const char *name) +{ + off_t mediasize; + + if (g_ioctl_arg(name, 0, DIOCGMEDIASIZE, &mediasize) == -1) + mediasize = -1; + return (mediasize); +} + +/* + * Return sector size of the given provider. + */ +ssize_t +g_sectorsize(const char *name) +{ + u_int sectorsize; + + if (g_ioctl_arg(name, 0, DIOCGSECTORSIZE, §orsize) == -1) + return (-1); + return ((ssize_t)sectorsize); +} + +/* + * Call BIO_FLUSH for the given provider. + */ +int +g_flush(const char *name) +{ + + return (g_ioctl(name, 1, DIOCGFLUSH)); +} + +/* + * Call BIO_DELETE for the given range. + */ +int +g_delete(const char *name, off_t offset, off_t length) +{ + off_t arg[2]; + + arg[0] = offset; + arg[1] = length; + return (g_ioctl_arg(name, 1, DIOCGDELETE, arg)); +} + +/* + * Return ID of the given provider. + */ +int +g_name_to_id(const char *name, char *id, size_t size) +{ + char lid[DISK_ID_SIZE]; + + if (g_ioctl_arg(name, 0, DIOCGID, lid) == -1) + return (-1); + if (lid[0] == '\0') { + errno = ENOENT; + return (-1); + } + if (strlcpy(id, lid, size) >= size) { + errno = ENOMEM; + return (-1); + } + return (0); +} + +/* + * Find provider name by the given ID. + */ +int +g_id_to_name(const char *id, char *name, size_t size) +{ + char lid[DISK_ID_SIZE]; + struct gmesh mesh; + struct gclass *mp; + struct ggeom *gp; + struct gprovider *pp; + int error; + + error = geom_gettree(&mesh); + if (error != 0) { + errno = error; + return (-1); + } + + error = ENOENT; + + LIST_FOREACH(mp, &mesh.lg_class, lg_class) { + LIST_FOREACH(gp, &mp->lg_geom, lg_geom) { + LIST_FOREACH(pp, &gp->lg_provider, lg_provider) { + if (g_name_to_id(pp->lg_name, lid, + sizeof(lid)) == -1) { + continue; + } + if (strcmp(id, lid) != 0) + continue; + if (strlcpy(name, pp->lg_name, size) >= size) + error = ENOMEM; + error = 0; + goto end; + } + } + } +end: + geom_deletetree(&mesh); + if (error != 0) { + errno = error; + return (-1); + } + return (0); +} Index: lib/libgeom/libgeom.h =================================================================== RCS file: /zoo/pjd/repo/src/lib/libgeom/libgeom.h,v retrieving revision 1.10 diff -u -p -r1.10 libgeom.h --- lib/libgeom/libgeom.h 9 Mar 2004 21:14:18 -0000 1.10 +++ lib/libgeom/libgeom.h 27 Apr 2007 19:10:19 -0000 @@ -144,6 +144,14 @@ const char *gctl_issue(struct gctl_req * void gctl_ro_param(struct gctl_req *req, const char *name, int len, const void* val); void gctl_rw_param(struct gctl_req *req, const char *name, int len, void* val); +/* geom_util.c */ +off_t g_mediasize(const char *name); +ssize_t g_sectorsize(const char *name); +int g_flush(const char *name); +int g_delete(const char *name, off_t offset, off_t length); +int g_name_to_id(const char *name, char *id, size_t size); +int g_id_to_name(const char *id, char *name, size_t size); + __END_DECLS #endif /* _LIBGEOM_H_ */ Index: sbin/fdisk/fdisk.c =================================================================== RCS file: /zoo/pjd/repo/src/sbin/fdisk/fdisk.c,v retrieving revision 1.82 diff -u -p -r1.82 fdisk.c --- sbin/fdisk/fdisk.c 18 Jun 2006 22:02:22 -0000 1.82 +++ sbin/fdisk/fdisk.c 13 Apr 2007 00:23:38 -0000 @@ -27,6 +27,7 @@ #include __FBSDID("$FreeBSD: src/sbin/fdisk/fdisk.c,v 1.82 2006/06/18 22:02:22 simon Exp $"); +#include #include #include #include Index: sys/dev/ata/ata-disk.c =================================================================== RCS file: /zoo/pjd/repo/src/sys/dev/ata/ata-disk.c,v retrieving revision 1.201 diff -u -p -r1.201 ata-disk.c --- sys/dev/ata/ata-disk.c 21 Feb 2007 19:07:18 -0000 1.201 +++ sys/dev/ata/ata-disk.c 28 Apr 2007 21:20:44 -0000 @@ -161,6 +161,8 @@ ad_attach(device_t dev) adp->disk->d_unit = device_get_unit(dev); if (atadev->param.support.command2 & ATA_SUPPORT_FLUSHCACHE) adp->disk->d_flags = DISKFLAG_CANFLUSHCACHE; + snprintf(adp->disk->d_id, sizeof(adp->disk->d_id), "atadisk:%s", + atadev->param.serial); disk_create(adp->disk, DISK_VERSION); device_add_child(dev, "subdisk", device_get_unit(dev)); ad_firmware_geom_adjust(dev, adp->disk); Index: sys/geom/geom.h =================================================================== RCS file: /zoo/pjd/repo/src/sys/geom/geom.h,v retrieving revision 1.98 diff -u -p -r1.98 geom.h --- sys/geom/geom.h 31 Oct 2006 21:11:20 -0000 1.98 +++ sys/geom/geom.h 27 Apr 2007 12:34:09 -0000 @@ -230,6 +230,7 @@ int g_getattr__(const char *attr, struct int g_handleattr(struct bio *bp, const char *attribute, void *val, int len); int g_handleattr_int(struct bio *bp, const char *attribute, int val); int g_handleattr_off_t(struct bio *bp, const char *attribute, off_t val); +int g_handleattr_str(struct bio *bp, const char *attribute, char *str); struct g_consumer * g_new_consumer(struct g_geom *gp); struct g_geom * g_new_geomf(struct g_class *mp, const char *fmt, ...); struct g_provider * g_new_providerf(struct g_geom *gp, const char *fmt, ...); @@ -274,6 +275,7 @@ struct bio *g_new_bio(void); struct bio *g_alloc_bio(void); void * g_read_data(struct g_consumer *cp, off_t offset, off_t length, int *error); int g_write_data(struct g_consumer *cp, off_t offset, void *ptr, off_t length); +int g_delete_data(struct g_consumer *cp, off_t offset, off_t length); void g_print_bio(struct bio *bp); /* geom_kern.c / geom_kernsim.c */ Index: sys/geom/geom_dev.c =================================================================== RCS file: /zoo/pjd/repo/src/sys/geom/geom_dev.c,v retrieving revision 1.93 diff -u -p -r1.93 geom_dev.c --- sys/geom/geom_dev.c 26 Mar 2007 21:47:03 -0000 1.93 +++ sys/geom/geom_dev.c 28 Apr 2007 21:29:52 -0000 @@ -245,6 +245,7 @@ g_dev_ioctl(struct cdev *dev, u_long cmd struct g_geom *gp; struct g_consumer *cp; struct g_kerneldump kd; + off_t offset, length; int i, error; u_int u; @@ -294,6 +295,25 @@ g_dev_ioctl(struct cdev *dev, u_long cmd if (!error) dev->si_flags |= SI_DUMPDEV; break; + case DIOCGFLUSH: + error = g_io_flush(cp); + break; + case DIOCGDELETE: + offset = ((off_t *)data)[0]; + length = ((off_t *)data)[1]; + if ((offset % cp->provider->sectorsize) != 0 || + (length % cp->provider->sectorsize) != 0 || + length <= 0 || length > MAXPHYS) { + printf("%s: offset=%jd length=%jd\n", __func__, offset, + length); + error = EINVAL; + break; + } + error = g_delete_data(cp, offset, length); + break; + case DIOCGID: + error = g_io_getattr("GEOM::id", cp, &i, data); + break; default: if (cp->provider->geom->ioctl != NULL) { Index: sys/geom/geom_disk.c =================================================================== RCS file: /zoo/pjd/repo/src/sys/geom/geom_disk.c,v retrieving revision 1.101 diff -u -p -r1.101 geom_disk.c --- sys/geom/geom_disk.c 21 Feb 2007 07:45:02 -0000 1.101 +++ sys/geom/geom_disk.c 28 Apr 2007 21:55:02 -0000 @@ -301,6 +301,8 @@ g_disk_start(struct bio *bp) break; else if (g_handleattr_off_t(bp, "GEOM::frontstuff", 0)) break; + else if (g_handleattr_str(bp, "GEOM::id", dp->d_id)) + break; else if (!strcmp(bp->bio_attribute, "GEOM::kerneldump")) g_disk_kerneldump(bp, dp); else @@ -408,7 +410,7 @@ disk_alloc() void disk_create(struct disk *dp, int version) { - if (version != DISK_VERSION_00) { + if (version != DISK_VERSION_00 && version != DISK_VERSION_01) { printf("WARNING: Attempt to add disk %s%d %s", dp->d_name, dp->d_unit, " using incompatible ABI version of disk(9)\n"); Index: sys/geom/geom_disk.h =================================================================== RCS file: /zoo/pjd/repo/src/sys/geom/geom_disk.h,v retrieving revision 1.6 diff -u -p -r1.6 geom_disk.h --- sys/geom/geom_disk.h 31 Oct 2006 21:12:43 -0000 1.6 +++ sys/geom/geom_disk.h 28 Apr 2007 21:53:34 -0000 @@ -42,6 +42,7 @@ #include #include #include +#include struct disk; @@ -83,6 +84,7 @@ struct disk { u_int d_maxsize; u_int d_stripeoffset; u_int d_stripesize; + char d_id[DISK_ID_SIZE]; /* Fields private to the driver */ void *d_drv1; @@ -99,7 +101,8 @@ void disk_destroy(struct disk *disk); void disk_gone(struct disk *disk); #define DISK_VERSION_00 0x58561059 -#define DISK_VERSION DISK_VERSION_00 +#define DISK_VERSION_01 0x5856105a +#define DISK_VERSION DISK_VERSION_01 #endif /* _KERNEL */ #endif /* _GEOM_GEOM_DISK_H_ */ Index: sys/geom/geom_io.c =================================================================== RCS file: /zoo/pjd/repo/src/sys/geom/geom_io.c,v retrieving revision 1.74 diff -u -p -r1.74 geom_io.c --- sys/geom/geom_io.c 27 Feb 2007 17:23:29 -0000 1.74 +++ sys/geom/geom_io.c 13 Apr 2007 00:23:38 -0000 @@ -646,6 +646,28 @@ g_write_data(struct g_consumer *cp, off_ return (error); } +int +g_delete_data(struct g_consumer *cp, off_t offset, off_t length) +{ + struct bio *bp; + int error; + + KASSERT(length > 0 && length >= cp->provider->sectorsize && + length <= MAXPHYS, ("g_delete_data(): invalid length %jd", + (intmax_t)length)); + + bp = g_alloc_bio(); + bp->bio_cmd = BIO_DELETE; + bp->bio_done = NULL; + bp->bio_offset = offset; + bp->bio_length = length; + bp->bio_data = NULL; + g_io_request(bp, cp); + error = biowait(bp, "gdelete"); + g_destroy_bio(bp); + return (error); +} + void g_print_bio(struct bio *bp) { Index: sys/geom/geom_slice.c =================================================================== RCS file: /zoo/pjd/repo/src/sys/geom/geom_slice.c,v retrieving revision 1.61 diff -u -p -r1.61 geom_slice.c --- sys/geom/geom_slice.c 31 Oct 2006 21:23:50 -0000 1.61 +++ sys/geom/geom_slice.c 28 Apr 2007 21:22:12 -0000 @@ -172,6 +172,28 @@ g_slice_finish_hot(struct bio *bp) } static void +g_slice_done(struct bio *bp) +{ + + KASSERT(bp->bio_cmd == BIO_GETATTR && + strcmp(bp->bio_attribute, "GEOM::id") == 0, + ("bio_cmd=0x%x bio_attribute=%s", bp->bio_cmd, bp->bio_attribute)); + + if (bp->bio_error == 0) { + char idx[8]; + + /* Add index to received ID. */ + snprintf(idx, sizeof(idx), "s%d", + bp->bio_parent->bio_to->index); + if (strlcat(bp->bio_data, idx, bp->bio_length) >= + bp->bio_length) { + bp->bio_error = EFAULT; + } + } + g_std_done(bp); +} + +static void g_slice_start(struct bio *bp) { struct bio *bp2; @@ -251,6 +273,16 @@ g_slice_start(struct bio *bp) /* Give the real method a chance to override */ if (gsp->start != NULL && gsp->start(bp)) return; + if (!strcmp("GEOM::id", bp->bio_attribute)) { + bp2 = g_clone_bio(bp); + if (bp2 == NULL) { + g_io_deliver(bp, ENOMEM); + return; + } + bp2->bio_done = g_slice_done; + g_io_request(bp2, cp); + return; + } if (!strcmp("GEOM::kerneldump", bp->bio_attribute)) { struct g_kerneldump *gkd; Index: sys/geom/geom_subr.c =================================================================== RCS file: /zoo/pjd/repo/src/sys/geom/geom_subr.c,v retrieving revision 1.90 diff -u -p -r1.90 geom_subr.c --- sys/geom/geom_subr.c 15 Sep 2006 16:36:45 -0000 1.90 +++ sys/geom/geom_subr.c 28 Apr 2007 20:13:11 -0000 @@ -790,20 +790,35 @@ g_handleattr_off_t(struct bio *bp, const } int +g_handleattr_str(struct bio *bp, const char *attribute, char *str) +{ + + return (g_handleattr(bp, attribute, str, 0)); +} + +int g_handleattr(struct bio *bp, const char *attribute, void *val, int len) { - int error; + int error = 0; if (strcmp(bp->bio_attribute, attribute)) return (0); - if (bp->bio_length != len) { - printf("bio_length %jd len %d -> EFAULT\n", - (intmax_t)bp->bio_length, len); - error = EFAULT; - } else { - error = 0; + if (len == 0) { + bzero(bp->bio_data, bp->bio_length); + if (strlcpy(bp->bio_data, val, bp->bio_length) >= + bp->bio_length) { + printf("%s: %s bio_length %jd len %zu -> EFAULT\n", + __func__, bp->bio_to->name, + (intmax_t)bp->bio_length, strlen(val)); + error = EFAULT; + } + } else if (bp->bio_length == len) { bcopy(val, bp->bio_data, len); bp->bio_completed = len; + } else { + printf("%s: %s bio_length %jd len %d -> EFAULT\n", __func__, + bp->bio_to->name, (intmax_t)bp->bio_length, len); + error = EFAULT; } g_io_deliver(bp, error); return (1); Index: sys/sys/disk.h =================================================================== RCS file: /zoo/pjd/repo/src/sys/sys/disk.h,v retrieving revision 1.41 diff -u -p -r1.41 disk.h --- sys/sys/disk.h 11 Mar 2006 10:24:50 -0000 1.41 +++ sys/sys/disk.h 28 Apr 2007 21:16:25 -0000 @@ -66,4 +66,21 @@ void disk_err(struct bio *bp, const char * which may apply to the device. */ +#define DIOCGFLUSH _IO('d', 135) /* Flush write cache */ + /*- + * Flush write cache of the device. + */ + +#define DIOCGDELETE _IOW('d', 136, off_t[2]) /* Delete data */ + /*- + * Mark data on the device as unused. + */ + +#define DISK_ID_SIZE 64 +#define DIOCGID _IOR('d', 136, char[DISK_ID_SIZE]) + /*- + * Get the ID of the given provider. This value should not change + * between reboots. + */ + #endif /* _SYS_DISK_H_ */ Index: usr.sbin/diskinfo/diskinfo.c =================================================================== RCS file: /zoo/pjd/repo/src/usr.sbin/diskinfo/diskinfo.c,v retrieving revision 1.8 diff -u -p -r1.8 diskinfo.c --- usr.sbin/diskinfo/diskinfo.c 11 Jan 2005 10:53:09 -0000 1.8 +++ usr.sbin/diskinfo/diskinfo.c 28 Apr 2007 17:50:11 -0000 @@ -44,7 +44,7 @@ static void usage(void) { - fprintf(stderr, "usage: diskinfo [-ctv] disk ...\n"); + fprintf(stderr, "usage: diskinfo [-cstv] disk ...\n"); exit (1); } @@ -57,7 +57,7 @@ int main(int argc, char **argv) { int i, ch, fd, error; - char buf[BUFSIZ]; + char buf[BUFSIZ], id[DISK_ID_SIZE]; off_t mediasize; u_int sectorsize, fwsectors, fwheads; @@ -104,6 +104,9 @@ main(int argc, char **argv) error = ioctl(fd, DIOCGFWHEADS, &fwheads); if (error) fwheads = 0; + error = ioctl(fd, DIOCGID, id); + if (error) + id[0] = '\0'; if (!opt_v) { printf("%s", argv[i]); printf("\t%u", sectorsize); @@ -130,6 +133,8 @@ main(int argc, char **argv) printf("\t%-12u\t# Heads according to firmware.\n", fwheads); printf("\t%-12u\t# Sectors according to firmware.\n", fwsectors); } + if (id[0] != '\0') + printf("\t%-12s\t# Disk ID.\n", id); } printf("\n"); if (opt_c)