Remove deprecated GEOM classes

Follow-up on r322318 and r322319 and remove the deprecated modules.

Shift some now-unused kernel files into userspace utilities that incorporate
them.  Remove references to removed GEOM classes in userspace utilities.

Reviewed by:	imp (earlier version)
Sponsored by:	Dell EMC Isilon
Differential Revision:	https://reviews.freebsd.org/D21249
This commit is contained in:
Conrad Meyer 2019-08-13 20:06:55 +00:00
parent ba084c18de
commit ac8e5d02cf
27 changed files with 89 additions and 2545 deletions

View File

@ -381,8 +381,6 @@ static int
writelabel(void)
{
int i, fd, serrno;
struct gctl_req *grq;
char const *errstr;
struct disklabel *lp = &lab;
if (disable_write) {
@ -423,39 +421,8 @@ writelabel(void)
return (1);
}
/* Give up if GEOM_BSD is not available. */
if (geom_class_available("BSD") == 0) {
warnc(serrno, "%s", specname);
return (1);
}
grq = gctl_get_handle();
gctl_ro_param(grq, "verb", -1, "write label");
gctl_ro_param(grq, "class", -1, "BSD");
gctl_ro_param(grq, "geom", -1, pname);
gctl_ro_param(grq, "label", 148+16*8,
bootarea + labeloffset + labelsoffset * lab.d_secsize);
errstr = gctl_issue(grq);
if (errstr != NULL) {
warnx("%s", errstr);
gctl_free(grq);
return(1);
}
gctl_free(grq);
if (installboot) {
grq = gctl_get_handle();
gctl_ro_param(grq, "verb", -1, "write bootcode");
gctl_ro_param(grq, "class", -1, "BSD");
gctl_ro_param(grq, "geom", -1, pname);
gctl_ro_param(grq, "bootcode", BBSIZE, bootarea);
errstr = gctl_issue(grq);
if (errstr != NULL) {
warnx("%s", errstr);
gctl_free(grq);
return (1);
}
gctl_free(grq);
}
warnc(serrno, "%s", specname);
return (1);
} else {
if (write(fd, bootarea, bbsize) != bbsize) {
warn("write %s", specname);

View File

@ -2,12 +2,10 @@
PACKAGE=runtime
PROG= fdisk
SRCS= fdisk.c geom_mbr_enc.c
SRCS= fdisk.c fdisk_mbr_enc.c
WARNS?= 4
MAN= fdisk.8
.PATH: ${SRCTOP}/sys/geom
LIBADD= geom
.include <bsd.prog.mk>

View File

@ -47,6 +47,8 @@ __FBSDID("$FreeBSD$");
#include <string.h>
#include <unistd.h>
#include "fdisk_mbr_enc.h"
static int iotest;
#define NO_DISK_SECTORS ((u_int32_t)-1)
@ -786,47 +788,17 @@ geom_class_available(const char *name)
static int
write_disk(off_t sector, void *buf)
{
struct gctl_req *grq;
const char *errmsg;
char *pname;
int error;
/* Check that GEOM_MBR is available */
if (geom_class_available("MBR") != 0) {
grq = gctl_get_handle();
gctl_ro_param(grq, "verb", -1, "write MBR");
gctl_ro_param(grq, "class", -1, "MBR");
pname = g_providername(fd);
if (pname == NULL) {
warn("Error getting providername for %s", disk);
return (-1);
}
gctl_ro_param(grq, "geom", -1, pname);
gctl_ro_param(grq, "data", secsize, buf);
errmsg = gctl_issue(grq);
free(pname);
if (errmsg == NULL) {
gctl_free(grq);
return(0);
}
if (!q_flag)
warnx("GEOM_MBR: %s", errmsg);
gctl_free(grq);
} else {
/*
* Try to write MBR directly. This may help when disk
* is not in use.
* XXX: hardcoded sectorsize
*/
error = pwrite(fd, buf, secsize, (sector * 512));
if (error == secsize)
return (0);
}
ssize_t wr;
/*
* GEOM_MBR is not available or failed to write MBR.
* Now check that we have GEOM_PART and recommend to use gpart (8).
* Try to write MBR directly. This may help when disk
* is not in use.
* XXX: hardcoded sectorsize
*/
wr = pwrite(fd, buf, secsize, (sector * 512));
if (wr == secsize)
return (0);
if (geom_class_available("PART") != 0)
warnx("Failed to write MBR. Try to use gpart(8).");
else

View File

@ -40,6 +40,8 @@ __FBSDID("$FreeBSD$");
#include <sys/diskmbr.h>
#include <sys/endian.h>
#include "fdisk_mbr_enc.h"
void
dos_partition_dec(void const *pp, struct dos_partition *d)
{

View File

@ -0,0 +1,34 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2019 Conrad Meyer <cem@FreeBSD.org>
*
* 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 AUTHOR 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 AUTHOR 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.
*
* $FreeBSD$
*/
#pragma once
struct dos_partition;
void dos_partition_dec(void const *pp, struct dos_partition *d);
void dos_partition_enc(void *pp, struct dos_partition *d);

View File

@ -1,9 +1,7 @@
# $FreeBSD$
.PATH: ${SRCTOP}/sys/geom
PROG= sunlabel
SRCS= sunlabel.c geom_sunlabel_enc.c
SRCS= sunlabel.c sunlabel_enc.c
MAN= sunlabel.8
.if ${MACHINE_CPUARCH} == "sparc64"

View File

@ -75,7 +75,6 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/disk.h>
#include <sys/ioctl.h>
#include <sys/sun_disklabel.h>
#include <sys/wait.h>
#include <ctype.h>
@ -89,6 +88,8 @@ __FBSDID("$FreeBSD$");
#include <string.h>
#include <unistd.h>
#include "sun_disklabel.h"
#define _PATH_TMPFILE "/tmp/EdDk.XXXXXXXXXX"
#define _PATH_BOOT "/boot/boot1"

View File

@ -39,12 +39,12 @@ __FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/endian.h>
#include <sys/errno.h>
#include <sys/sun_disklabel.h>
#ifdef _KERNEL
#include <sys/systm.h>
#else
#include <string.h>
#endif
#include "sun_disklabel.h"
#define SL_TEXT 0x0
#define SL_TEXT_SIZEOF 0x80

View File

@ -166,7 +166,6 @@ MAN= aac.4 \
gdb.4 \
gem.4 \
geom.4 \
geom_fox.4 \
geom_linux_lvm.4 \
geom_map.4 \
geom_uzip.4 \

View File

@ -34,7 +34,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd April 9, 2018
.Dd August 13, 2019
.Dt GEOM 4
.Os
.Sh NAME
@ -443,24 +443,6 @@ This is unused at this time.
.It 0x80 Pq Dv G_F_CTLDUMP
Dump contents of gctl requests.
.El
.Sh OBSOLETE OPTIONS
.Pp
The following options have been deprecated and will be removed in
.Fx 12 :
.Cd GEOM_BSD ,
.Cd GEOM_FOX ,
.Cd GEOM_MBR ,
.Cd GEOM_SUNLABEL ,
and
.Cd GEOM_VOL .
.Pp
Use
.Cd GEOM_PART_BSD ,
.Cd GEOM_MULTIPATH ,
.Cd GEOM_PART_MBR ,
.Cd GEOM_PART_VTOC8 ,
.Cd GEOM_LABEL
options, respectively, instead.
.Sh SEE ALSO
.Xr libgeom 3 ,
.Xr DECLARE_GEOM_CLASS 9 ,
@ -475,7 +457,7 @@ options, respectively, instead.
.Xr g_provider 9 ,
.Xr g_provider_by_name 9
.Sh HISTORY
This software was developed for the
This software was initially developed for the
.Fx
Project by
.An Poul-Henning Kamp
@ -485,13 +467,38 @@ under DARPA/SPAWAR contract N66001-01-C-8035
as part of the
DARPA CHATS research program.
.Pp
The first precursor for
The following obsolete
.Nm
was a gruesome hack to Minix 1.2 and was
never distributed.
An earlier attempt to implement a less general scheme
in
.Fx
never succeeded.
components were removed in
.Fx 13.0 :
.Bl -bullet -offset indent -compact
.It
.Cd GEOM_BSD ,
.It
.Cd GEOM_FOX ,
.It
.Cd GEOM_MBR ,
.It
.Cd GEOM_SUNLABEL ,
and
.It
.Cd GEOM_VOL .
.El
.Pp
Use
.Bl -bullet -offset indent -compact
.It
.Cd GEOM_PART_BSD ,
.It
.Cd GEOM_MULTIPATH ,
.It
.Cd GEOM_PART_MBR ,
.It
.Cd GEOM_PART_VTOC8 ,
and
.It
.Cd GEOM_LABEL
.El
options, respectively, instead.
.Sh AUTHORS
.An Poul-Henning Kamp Aq Mt phk@FreeBSD.org

View File

@ -1,223 +0,0 @@
.\"
.\" Copyright (c) 2006 Wilko Bulte
.\" 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 AUTHOR 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 AUTHOR 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.
.\"
.\" $FreeBSD$
.\"
.Dd September 12, 2015
.Dt GEOM_FOX 4
.Os
.Sh NAME
.Nm geom_fox
.Nd "GEOM based basic disk multipathing"
.Sh SYNOPSIS
To compile this driver into the kernel,
place the following line in your
kernel configuration file:
.Bd -ragged -offset indent
.Cd "options GEOM_FOX"
.Ed
.Pp
Alternatively, to load the driver as a
module at boot time, place the following line in
.Xr loader.conf 5 :
.Bd -literal -offset indent
geom_fox_load="YES"
.Ed
.Sh DESCRIPTION
.Bf -symbolic
This driver is obsolete.
Users are advised to use
.Xr gmultipath 8
instead.
This driver will be removed in
.Fx 12 .
.Ef
.Pp
The intent of the
.Nm
framework is to provide basic multipathing support to access direct
access devices.
Basic in the above sentence should be read as:
.Nm
only provides path failover functionality, not load balancing over
the available paths etc.
Using suitable hardware like SCSI or FibreChannel disks it is
possible to have multiple (typically 2) host bus adapters access
the same physical disk drive.
.Pp
Without a multipathing driver the
.Fx
kernel would probe the disks multiple times, resulting in the creation of
multiple
.Pa /dev
entries for the same underlying physical device.
A unique label written in the GEOM label area allows
.Nm
to detect multiple paths.
Using this information it creates a unique
.Pa da#.fox
device.
.Pp
The
.Nm
device is subsequently used by the
.Fx
kernel to access the disks.
Multiple physical access paths ensure that even in case of a path failure the
.Fx
kernel can continue to access the data.
.Pp
The
.Nm
driver will disallow write operations to the underlying devices once the
fox device has been opened for writing.
.Sh EXAMPLES
.Bl -bullet -compact
.It
.Nm
needs a label on the disk as follows in order to work properly:
.Bd -literal
"0123456789abcdef0123456789abcdef"
"GEOM::FOX <--unique--id-->"
.Ed
.Pp
For the unique ID 16 bytes are available.
The
.Dq Li GEOM::FOX
is the magic to mark a
.Nm
device.
.Pp
The actual labelling is accomplished by
.Bd -literal
echo "GEOM::FOX someid" | dd of=/dev/da2 conv=sync
.Ed
.Pp
For FibreChannel devices it is suggested to use the Node World Wide
Name (Node WWN) as this is guaranteed by the FibreChannel standard to
be worldwide unique.
The use of the Port WWN not recommended as each port of a given
device has a different WWN, thereby confusing things.
.Pp
The Node WWN can be obtained from a verbose boot as in for example
.Bd -literal
isp1: Target 1 (Loop 0x1) Port ID 0xe8 (role Target) Arrived
Port WWN 0x21000004cfc8aca2
Node WWN 0x20000004cfc8aca2
.Ed
.Pp
This Node WWN would then be used like so:
.Bd -literal
echo "GEOM::FOX 20000004cfc8aca2" | dd of=/dev/da2 conv=sync
.Ed
.Pp
For non-FibreChannel devices you could for example use the serial
number of the device.
Regardless of what you use, make sure the label is unique.
.Pp
Once the labelling has been performed and assuming the
.Nm
module is loaded the kernel will inform you that it has found a new
.Nm
device with a message similar to
.Bd -literal
Creating new fox (da2)
fox da2.fox lock 0xfffffc0000fdba20
.Ed
.Pp
.It
To check which physical devices match a given
.Nm
device:
.Bd -literal -offset indent
# geom fox list
Geom name: da2.fox
Providers:
1. Name: da2.fox
Mediasize: 73407865344 (68G)
Sectorsize: 512
Mode: r0w0e0
Consumers:
1. Name: da2
Mediasize: 73407865856 (68G)
Sectorsize: 512
Mode: r0w0e0
2. Name: da6
Mediasize: 73407865856 (68G)
Sectorsize: 512
Mode: r0w0e0
.Ed
.Pp
.It
To check the status of the
.Nm
components:
.Bd -literal
# geom fox status
Name Status Components
da2.fox N/A da2
da6
.Ed
.El
.Sh SEE ALSO
.Xr GEOM 4 ,
.Xr geom 8 ,
.Xr gmultipath 8
.Sh AUTHORS
.An -nosplit
The
.Nm
driver was written by
.An Poul-Henning Kamp Aq Mt phk@FreeBSD.org .
This manual page was written by
.An Wilko Bulte Aq Mt wilko@FreeBSD.org .
.Sh CAVEATS
The
.Nm
driver depends on the underlying hardware drivers to do the right thing in case
of a path failure.
If for example a hardware driver continues to retry forever,
.Nm
is not able to re-initiate the I/O to an alternative physical path.
.Pp
You have to be very sure to provide a unique label for each of the
.Nm
devices.
Safety belts are not provided.
For FibreChannel devices it is suggested to use the Port WWN of the device.
The World Wide Name is guaranteed to be worldwide unique per the
FibreChannel standard.
.Sh BUGS
The
.Nm
framework has only seen light testing.
There definitely might be dragons here.
.Pp
The name
.Nm
is completely obscure.
Just remember that any sly fox has multiple exits from its hole.
.Pp
The examples provided are too FibreChannel-centric.

View File

@ -156,17 +156,14 @@ options BOOT_TAG=\"\"
options BOOT_TAG_SZ=32
options GEOM_BDE # Disk encryption.
options GEOM_BSD # BSD disklabels (obsolete, gone in 12)
options GEOM_CACHE # Disk cache.
options GEOM_CONCAT # Disk concatenation.
options GEOM_ELI # Disk encryption.
options GEOM_FOX # Redundant path mitigation (obsolete, gone in 12)
options GEOM_GATE # Userland services.
options GEOM_JOURNAL # Journaling.
options GEOM_LABEL # Providers labelization.
options GEOM_LINUX_LVM # Linux LVM2 volumes
options GEOM_MAP # Map based partitioning
options GEOM_MBR # DOS/MBR partitioning (obsolete, gone in 12)
options GEOM_MIRROR # Disk mirroring.
options GEOM_MULTIPATH # Disk multipath
options GEOM_NOP # Test class.
@ -183,11 +180,9 @@ options GEOM_RAID # Soft RAID functionality.
options GEOM_RAID3 # RAID3 functionality.
options GEOM_SHSEC # Shared secret.
options GEOM_STRIPE # Disk striping.
options GEOM_SUNLABEL # Sun/Solaris partitioning (obsolete, gone in 12)
options GEOM_UZIP # Read-only compressed disks
options GEOM_VINUM # Vinum logical volume manager
options GEOM_VIRSTOR # Virtual storage.
options GEOM_VOL # Volume names from UFS superblock (obsolete, gone in 12)
options GEOM_ZERO # Performance testing helper.
#
@ -1260,8 +1255,7 @@ options FFCLOCK
# removed a disk drive, you may have had to rewrite your /etc/fstab
# file, and also that you had to be careful when adding a new disk
# as it may have been probed earlier and moved your device configuration
# around. (See also option GEOM_VOL for a different solution to this
# problem.)
# around.
# This old behavior is maintained as the default behavior. The unit
# assignment begins with the first non-wired down unit for a device

View File

@ -3561,28 +3561,21 @@ geom/eli/g_eli_key_cache.c optional geom_eli
geom/eli/g_eli_privacy.c optional geom_eli
geom/eli/pkcs5v2.c optional geom_eli
geom/gate/g_gate.c optional geom_gate
geom/geom_bsd.c optional geom_bsd
geom/geom_bsd_enc.c optional geom_bsd | geom_part_bsd
geom/geom_bsd_enc.c optional geom_part_bsd
geom/geom_ccd.c optional ccd | geom_ccd
geom/geom_ctl.c standard
geom/geom_dev.c standard
geom/geom_disk.c standard
geom/geom_dump.c standard
geom/geom_event.c standard
geom/geom_fox.c optional geom_fox
geom/geom_flashmap.c optional fdt cfi | fdt mx25l | mmcsd | fdt n25q | fdt at45d
geom/geom_io.c standard
geom/geom_kern.c standard
geom/geom_map.c optional geom_map
geom/geom_mbr.c optional geom_mbr
geom/geom_mbr_enc.c optional geom_mbr
geom/geom_redboot.c optional geom_redboot
geom/geom_slice.c standard
geom/geom_subr.c standard
geom/geom_sunlabel.c optional geom_sunlabel
geom/geom_sunlabel_enc.c optional geom_sunlabel
geom/geom_vfs.c standard
geom/geom_vol_ffs.c optional geom_vol
geom/journal/g_journal.c optional geom_journal
geom/journal/g_journal_ufs.c optional geom_journal
geom/label/g_label.c optional geom_label | geom_label_gpt

View File

@ -106,18 +106,15 @@ GZIO opt_gzio.h
IMAGACT_BINMISC opt_dontuse.h
IPI_PREEMPTION opt_sched.h
GEOM_BDE opt_geom.h
GEOM_BSD opt_geom.h
GEOM_CACHE opt_geom.h
GEOM_CONCAT opt_geom.h
GEOM_ELI opt_geom.h
GEOM_FOX opt_geom.h
GEOM_GATE opt_geom.h
GEOM_JOURNAL opt_geom.h
GEOM_LABEL opt_geom.h
GEOM_LABEL_GPT opt_geom.h
GEOM_LINUX_LVM opt_geom.h
GEOM_MAP opt_geom.h
GEOM_MBR opt_geom.h
GEOM_MIRROR opt_geom.h
GEOM_MOUNTVER opt_geom.h
GEOM_MULTIPATH opt_geom.h
@ -135,12 +132,10 @@ GEOM_RAID opt_geom.h
GEOM_RAID3 opt_geom.h
GEOM_SHSEC opt_geom.h
GEOM_STRIPE opt_geom.h
GEOM_SUNLABEL opt_geom.h
GEOM_UZIP opt_geom.h
GEOM_UZIP_DEBUG opt_geom.h
GEOM_VINUM opt_geom.h
GEOM_VIRSTOR opt_geom.h
GEOM_VOL opt_geom.h
GEOM_ZERO opt_geom.h
IFLIB opt_iflib.h
KDTRACE_HOOKS opt_global.h

View File

@ -1,617 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (c) 2002 Poul-Henning Kamp
* Copyright (c) 2002 Networks Associates Technology, Inc.
* All rights reserved.
*
* This software was developed for the FreeBSD Project by Poul-Henning Kamp
* and NAI Labs, the Security Research Division of Network Associates, Inc.
* under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
* DARPA CHATS research program.
*
* 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.
* 3. The names of the authors may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*/
/*
* This is the method for dealing with BSD disklabels. It has been
* extensively (by my standards at least) commented, in the vain hope that
* it will serve as the source in future copy&paste operations.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/endian.h>
#include <sys/systm.h>
#include <sys/sysctl.h>
#include <sys/kernel.h>
#include <sys/fcntl.h>
#include <sys/conf.h>
#include <sys/bio.h>
#include <sys/malloc.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/md5.h>
#include <sys/errno.h>
#include <sys/disklabel.h>
#include <sys/gpt.h>
#include <sys/proc.h>
#include <sys/sbuf.h>
#include <sys/uuid.h>
#include <geom/geom.h>
#include <geom/geom_slice.h>
FEATURE(geom_bsd, "GEOM BSD disklabels support");
#define BSD_CLASS_NAME "BSD"
#define ALPHA_LABEL_OFFSET 64
#define HISTORIC_LABEL_OFFSET 512
#define LABELSIZE (148 + 16 * MAXPARTITIONS)
static int g_bsd_once;
static void g_bsd_hotwrite(void *arg, int flag);
/*
* Our private data about one instance. All the rest is handled by the
* slice code and stored in its softc, so this is just the stuff
* specific to BSD disklabels.
*/
struct g_bsd_softc {
off_t labeloffset;
off_t mbroffset;
off_t rawoffset;
struct disklabel ondisk;
u_char label[LABELSIZE];
u_char labelsum[16];
};
/*
* Modify our slicer to match proposed disklabel, if possible.
* This is where we make sure we don't do something stupid.
*/
static int
g_bsd_modify(struct g_geom *gp, u_char *label)
{
int i, error;
struct partition *ppp;
struct g_slicer *gsp;
struct g_consumer *cp;
struct g_bsd_softc *ms;
u_int secsize, u;
off_t rawoffset, o;
struct disklabel dl;
MD5_CTX md5sum;
g_topology_assert();
gsp = gp->softc;
ms = gsp->softc;
error = bsd_disklabel_le_dec(label, &dl, MAXPARTITIONS);
if (error) {
return (error);
}
/* Get dimensions of our device. */
cp = LIST_FIRST(&gp->consumer);
secsize = cp->provider->sectorsize;
/* ... or a smaller sector size. */
if (dl.d_secsize < secsize) {
return (EINVAL);
}
/* ... or a non-multiple sector size. */
if (dl.d_secsize % secsize != 0) {
return (EINVAL);
}
/* Historical braindamage... */
rawoffset = (off_t)dl.d_partitions[RAW_PART].p_offset * dl.d_secsize;
for (i = 0; i < dl.d_npartitions; i++) {
ppp = &dl.d_partitions[i];
if (ppp->p_size == 0)
continue;
o = (off_t)ppp->p_offset * dl.d_secsize;
if (o < rawoffset)
rawoffset = 0;
}
if (rawoffset != 0 && (off_t)rawoffset != ms->mbroffset)
printf("WARNING: %s expected rawoffset %jd, found %jd\n",
gp->name,
(intmax_t)ms->mbroffset/dl.d_secsize,
(intmax_t)rawoffset/dl.d_secsize);
/* Don't munge open partitions. */
for (i = 0; i < dl.d_npartitions; i++) {
ppp = &dl.d_partitions[i];
o = (off_t)ppp->p_offset * dl.d_secsize;
if (o == 0)
o = rawoffset;
error = g_slice_config(gp, i, G_SLICE_CONFIG_CHECK,
o - rawoffset,
(off_t)ppp->p_size * dl.d_secsize,
dl.d_secsize,
"%s%c", gp->name, 'a' + i);
if (error)
return (error);
}
/* Look good, go for it... */
for (u = 0; u < gsp->nslice; u++) {
ppp = &dl.d_partitions[u];
o = (off_t)ppp->p_offset * dl.d_secsize;
if (o == 0)
o = rawoffset;
g_slice_config(gp, u, G_SLICE_CONFIG_SET,
o - rawoffset,
(off_t)ppp->p_size * dl.d_secsize,
dl.d_secsize,
"%s%c", gp->name, 'a' + u);
}
/* Update our softc */
ms->ondisk = dl;
if (label != ms->label)
bcopy(label, ms->label, LABELSIZE);
ms->rawoffset = rawoffset;
/*
* In order to avoid recursively attaching to the same
* on-disk label (it's usually visible through the 'c'
* partition) we calculate an MD5 and ask if other BSD's
* below us love that label. If they do, we don't.
*/
MD5Init(&md5sum);
MD5Update(&md5sum, ms->label, sizeof(ms->label));
MD5Final(ms->labelsum, &md5sum);
return (0);
}
/*
* This is an internal helper function, called multiple times from the taste
* function to try to locate a disklabel on the disk. More civilized formats
* will not need this, as there is only one possible place on disk to look
* for the magic spot.
*/
static int
g_bsd_try(struct g_geom *gp, struct g_slicer *gsp, struct g_consumer *cp, int secsize, struct g_bsd_softc *ms, off_t offset)
{
int error;
u_char *buf;
struct disklabel *dl;
off_t secoff;
/*
* We need to read entire aligned sectors, and we assume that the
* disklabel does not span sectors, so one sector is enough.
*/
secoff = offset % secsize;
buf = g_read_data(cp, offset - secoff, secsize, NULL);
if (buf == NULL)
return (ENOENT);
/* Decode into our native format. */
dl = &ms->ondisk;
error = bsd_disklabel_le_dec(buf + secoff, dl, MAXPARTITIONS);
if (!error)
bcopy(buf + secoff, ms->label, LABELSIZE);
/* Remember to free the buffer g_read_data() gave us. */
g_free(buf);
ms->labeloffset = offset;
return (error);
}
/*
* This function writes the current label to disk, possibly updating
* the alpha SRM checksum.
*/
static int
g_bsd_writelabel(struct g_geom *gp, u_char *bootcode)
{
off_t secoff;
u_int secsize;
struct g_consumer *cp;
struct g_slicer *gsp;
struct g_bsd_softc *ms;
u_char *buf;
uint64_t sum;
int error, i;
gsp = gp->softc;
ms = gsp->softc;
cp = LIST_FIRST(&gp->consumer);
/* Get sector size, we need it to read data. */
secsize = cp->provider->sectorsize;
secoff = ms->labeloffset % secsize;
if (bootcode == NULL) {
buf = g_read_data(cp, ms->labeloffset - secoff, secsize, &error);
if (buf == NULL)
return (error);
bcopy(ms->label, buf + secoff, sizeof(ms->label));
} else {
buf = bootcode;
bcopy(ms->label, buf + ms->labeloffset, sizeof(ms->label));
}
if (ms->labeloffset == ALPHA_LABEL_OFFSET) {
sum = 0;
for (i = 0; i < 63; i++)
sum += le64dec(buf + i * 8);
le64enc(buf + 504, sum);
}
if (bootcode == NULL) {
error = g_write_data(cp, ms->labeloffset - secoff, buf, secsize);
g_free(buf);
} else {
error = g_write_data(cp, 0, bootcode, BBSIZE);
}
return(error);
}
/*
* If the user tries to overwrite our disklabel through an open partition
* or via a magicwrite config call, we end up here and try to prevent
* footshooting as best we can.
*/
static void
g_bsd_hotwrite(void *arg, int flag)
{
struct bio *bp;
struct g_geom *gp;
struct g_slicer *gsp;
struct g_slice *gsl;
struct g_bsd_softc *ms;
u_char *p;
int error;
g_topology_assert();
/*
* We should never get canceled, because that would amount to a removal
* of the geom while there was outstanding I/O requests.
*/
KASSERT(flag != EV_CANCEL, ("g_bsd_hotwrite cancelled"));
bp = arg;
gp = bp->bio_to->geom;
gsp = gp->softc;
ms = gsp->softc;
gsl = &gsp->slices[bp->bio_to->index];
p = (u_char*)bp->bio_data + ms->labeloffset -
(bp->bio_offset + gsl->offset);
error = g_bsd_modify(gp, p);
if (error) {
g_io_deliver(bp, EPERM);
return;
}
g_slice_finish_hot(bp);
}
static int
g_bsd_start(struct bio *bp)
{
struct g_geom *gp;
struct g_bsd_softc *ms;
struct g_slicer *gsp;
gp = bp->bio_to->geom;
gsp = gp->softc;
ms = gsp->softc;
if (bp->bio_cmd == BIO_GETATTR) {
if (g_handleattr(bp, "BSD::labelsum", ms->labelsum,
sizeof(ms->labelsum)))
return (1);
}
return (0);
}
/*
* Dump configuration information in XML format.
* Notice that the function is called once for the geom and once for each
* consumer and provider. We let g_slice_dumpconf() do most of the work.
*/
static void
g_bsd_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, struct g_consumer *cp, struct g_provider *pp)
{
struct g_bsd_softc *ms;
struct g_slicer *gsp;
gsp = gp->softc;
ms = gsp->softc;
g_slice_dumpconf(sb, indent, gp, cp, pp);
if (indent != NULL && pp == NULL && cp == NULL) {
sbuf_printf(sb, "%s<labeloffset>%jd</labeloffset>\n",
indent, (intmax_t)ms->labeloffset);
sbuf_printf(sb, "%s<rawoffset>%jd</rawoffset>\n",
indent, (intmax_t)ms->rawoffset);
sbuf_printf(sb, "%s<mbroffset>%jd</mbroffset>\n",
indent, (intmax_t)ms->mbroffset);
} else if (pp != NULL) {
if (indent == NULL)
sbuf_printf(sb, " ty %d",
ms->ondisk.d_partitions[pp->index].p_fstype);
else
sbuf_printf(sb, "%s<type>%d</type>\n", indent,
ms->ondisk.d_partitions[pp->index].p_fstype);
}
}
/*
* The taste function is called from the event-handler, with the topology
* lock already held and a provider to examine. The flags are unused.
*
* If flags == G_TF_NORMAL, the idea is to take a bite of the provider and
* if we find valid, consistent magic on it, build a geom on it.
*
* There may be cases where the operator would like to put a BSD-geom on
* providers which do not meet all of the requirements. This can be done
* by instead passing the G_TF_INSIST flag, which will override these
* checks.
*
* The final flags value is G_TF_TRANSPARENT, which instructs the method
* to put a geom on top of the provider and configure it to be as transparent
* as possible. This is not really relevant to the BSD method and therefore
* not implemented here.
*/
static struct uuid freebsd_slice = GPT_ENT_TYPE_FREEBSD;
static struct g_geom *
g_bsd_taste(struct g_class *mp, struct g_provider *pp, int flags)
{
struct g_geom *gp;
struct g_consumer *cp;
int error, i;
struct g_bsd_softc *ms;
u_int secsize;
struct g_slicer *gsp;
u_char hash[16];
MD5_CTX md5sum;
struct uuid uuid;
g_trace(G_T_TOPOLOGY, "bsd_taste(%s,%s)", mp->name, pp->name);
g_topology_assert();
/* We don't implement transparent inserts. */
if (flags == G_TF_TRANSPARENT)
return (NULL);
/*
* BSD labels are a subclass of the general "slicing" topology so
* a lot of the work can be done by the common "slice" code.
* Create a geom with space for MAXPARTITIONS providers, one consumer
* and a softc structure for us. Specify the provider to attach
* the consumer to and our "start" routine for special requests.
* The provider is opened with mode (1,0,0) so we can do reads
* from it.
*/
gp = g_slice_new(mp, MAXPARTITIONS, pp, &cp, &ms,
sizeof(*ms), g_bsd_start);
if (gp == NULL)
return (NULL);
/* Get the geom_slicer softc from the geom. */
gsp = gp->softc;
/*
* The do...while loop here allows us to have multiple escapes
* using a simple "break". This improves code clarity without
* ending up in deep nesting and without using goto or come from.
*/
do {
/*
* If the provider is an MBR we will only auto attach
* to type 165 slices in the G_TF_NORMAL case. We will
* attach to any other type.
*/
error = g_getattr("MBR::type", cp, &i);
if (!error) {
if (i != 165 && flags == G_TF_NORMAL)
break;
error = g_getattr("MBR::offset", cp, &ms->mbroffset);
if (error)
break;
}
/* Same thing if we are inside a GPT */
error = g_getattr("GPT::type", cp, &uuid);
if (!error) {
if (memcmp(&uuid, &freebsd_slice, sizeof(uuid)) != 0 &&
flags == G_TF_NORMAL)
break;
}
/* Get sector size, we need it to read data. */
secsize = cp->provider->sectorsize;
if (secsize < 512)
break;
/* First look for a label at the start of the second sector. */
error = g_bsd_try(gp, gsp, cp, secsize, ms, secsize);
/*
* If sector size is not 512 the label still can be at
* offset 512, not at the start of the second sector. At least
* it's true for labels created by the FreeBSD's bsdlabel(8).
*/
if (error && secsize != HISTORIC_LABEL_OFFSET)
error = g_bsd_try(gp, gsp, cp, secsize, ms,
HISTORIC_LABEL_OFFSET);
/* Next, look for alpha labels */
if (error)
error = g_bsd_try(gp, gsp, cp, secsize, ms,
ALPHA_LABEL_OFFSET);
/* If we didn't find a label, punt. */
if (error)
break;
/*
* In order to avoid recursively attaching to the same
* on-disk label (it's usually visible through the 'c'
* partition) we calculate an MD5 and ask if other BSD's
* below us love that label. If they do, we don't.
*/
MD5Init(&md5sum);
MD5Update(&md5sum, ms->label, sizeof(ms->label));
MD5Final(ms->labelsum, &md5sum);
error = g_getattr("BSD::labelsum", cp, &hash);
if (!error && !bcmp(ms->labelsum, hash, sizeof(hash)))
break;
/*
* Process the found disklabel, and modify our "slice"
* instance to match it, if possible.
*/
error = g_bsd_modify(gp, ms->label);
} while (0);
/* Success or failure, we can close our provider now. */
g_access(cp, -1, 0, 0);
/* If we have configured any providers, return the new geom. */
if (gsp->nprovider > 0) {
g_slice_conf_hot(gp, 0, ms->labeloffset, LABELSIZE,
G_SLICE_HOT_ALLOW, G_SLICE_HOT_DENY, G_SLICE_HOT_CALL);
gsp->hot = g_bsd_hotwrite;
if (!g_bsd_once) {
g_bsd_once = 1;
printf(
"WARNING: geom_bsd (geom %s) is deprecated, "
"use gpart instead.\n", gp->name);
}
return (gp);
}
/*
* ...else push the "self-destruct" button, by spoiling our own
* consumer. This triggers a call to g_slice_spoiled which will
* dismantle what was setup.
*/
g_slice_spoiled(cp);
return (NULL);
}
struct h0h0 {
struct g_geom *gp;
struct g_bsd_softc *ms;
u_char *label;
int error;
};
static void
g_bsd_callconfig(void *arg, int flag)
{
struct h0h0 *hp;
hp = arg;
hp->error = g_bsd_modify(hp->gp, hp->label);
if (!hp->error)
hp->error = g_bsd_writelabel(hp->gp, NULL);
}
/*
* NB! curthread is user process which GCTL'ed.
*/
static void
g_bsd_config(struct gctl_req *req, struct g_class *mp, char const *verb)
{
u_char *label;
int error;
struct h0h0 h0h0;
struct g_geom *gp;
struct g_slicer *gsp;
struct g_consumer *cp;
struct g_bsd_softc *ms;
g_topology_assert();
gp = gctl_get_geom(req, mp, "geom");
if (gp == NULL)
return;
cp = LIST_FIRST(&gp->consumer);
gsp = gp->softc;
ms = gsp->softc;
if (!strcmp(verb, "read mbroffset")) {
gctl_set_param_err(req, "mbroffset", &ms->mbroffset,
sizeof(ms->mbroffset));
return;
} else if (!strcmp(verb, "write label")) {
label = gctl_get_paraml(req, "label", LABELSIZE);
if (label == NULL)
return;
h0h0.gp = gp;
h0h0.ms = gsp->softc;
h0h0.label = label;
h0h0.error = -1;
/* XXX: Does this reference register with our selfdestruct code ? */
error = g_access(cp, 1, 1, 1);
if (error) {
gctl_error(req, "could not access consumer");
return;
}
g_bsd_callconfig(&h0h0, 0);
error = h0h0.error;
g_access(cp, -1, -1, -1);
} else if (!strcmp(verb, "write bootcode")) {
label = gctl_get_paraml(req, "bootcode", BBSIZE);
if (label == NULL)
return;
/* XXX: Does this reference register with our selfdestruct code ? */
error = g_access(cp, 1, 1, 1);
if (error) {
gctl_error(req, "could not access consumer");
return;
}
error = g_bsd_writelabel(gp, label);
g_access(cp, -1, -1, -1);
} else {
gctl_error(req, "Unknown verb parameter");
}
return;
}
/* Finally, register with GEOM infrastructure. */
static struct g_class g_bsd_class = {
.name = BSD_CLASS_NAME,
.version = G_VERSION,
.taste = g_bsd_taste,
.ctlreq = g_bsd_config,
.dumpconf = g_bsd_dumpconf,
};
DECLARE_GEOM_CLASS(g_bsd_class, g_bsd);
MODULE_VERSION(geom_bsd, 0);

View File

@ -1,488 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (c) 2003 Poul-Henning Kamp
* 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.
* 3. The names of the authors may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $FreeBSD$
*/
/* This is a GEOM module for handling path selection for multi-path
* storage devices. It is named "fox" because it, like they, prefer
* to have multiple exits to choose from.
*
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/sysctl.h>
#include <sys/kernel.h>
#include <sys/conf.h>
#include <sys/bio.h>
#include <sys/malloc.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/libkern.h>
#include <sys/endian.h>
#include <sys/md5.h>
#include <sys/errno.h>
#include <geom/geom.h>
#define FOX_CLASS_NAME "FOX"
#define FOX_MAGIC "GEOM::FOX"
static int g_fox_once;
FEATURE(geom_fox, "GEOM FOX redundant path mitigation support");
struct g_fox_softc {
off_t mediasize;
u_int sectorsize;
TAILQ_HEAD(, bio) queue;
struct mtx lock;
u_char magic[16];
struct g_consumer *path;
struct g_consumer *opath;
int waiting;
int cr, cw, ce;
};
/*
* This function is called whenever we need to select a new path.
*/
static void
g_fox_select_path(void *arg, int flag)
{
struct g_geom *gp;
struct g_fox_softc *sc;
struct g_consumer *cp1;
struct bio *bp;
int error;
g_topology_assert();
if (flag == EV_CANCEL)
return;
gp = arg;
sc = gp->softc;
if (sc->opath != NULL) {
/*
* First, close the old path entirely.
*/
printf("Closing old path (%s) on fox (%s)\n",
sc->opath->provider->name, gp->name);
cp1 = LIST_NEXT(sc->opath, consumer);
g_access(sc->opath, -sc->cr, -sc->cw, -(sc->ce + 1));
/*
* The attempt to reopen it with a exclusive count
*/
error = g_access(sc->opath, 0, 0, 1);
if (error) {
/*
* Ok, ditch this consumer, we can't use it.
*/
printf("Drop old path (%s) on fox (%s)\n",
sc->opath->provider->name, gp->name);
g_detach(sc->opath);
g_destroy_consumer(sc->opath);
if (LIST_EMPTY(&gp->consumer)) {
/* No consumers left */
g_wither_geom(gp, ENXIO);
for (;;) {
bp = TAILQ_FIRST(&sc->queue);
if (bp == NULL)
break;
TAILQ_REMOVE(&sc->queue, bp, bio_queue);
bp->bio_error = ENXIO;
g_std_done(bp);
}
return;
}
} else {
printf("Got e-bit on old path (%s) on fox (%s)\n",
sc->opath->provider->name, gp->name);
}
sc->opath = NULL;
} else {
cp1 = LIST_FIRST(&gp->consumer);
}
if (cp1 == NULL)
cp1 = LIST_FIRST(&gp->consumer);
printf("Open new path (%s) on fox (%s)\n",
cp1->provider->name, gp->name);
error = g_access(cp1, sc->cr, sc->cw, sc->ce);
if (error) {
/*
* If we failed, we take another trip through here
*/
printf("Open new path (%s) on fox (%s) failed, reselect.\n",
cp1->provider->name, gp->name);
sc->opath = cp1;
g_post_event(g_fox_select_path, gp, M_WAITOK, gp, NULL);
} else {
printf("Open new path (%s) on fox (%s) succeeded\n",
cp1->provider->name, gp->name);
mtx_lock(&sc->lock);
sc->path = cp1;
sc->waiting = 0;
for (;;) {
bp = TAILQ_FIRST(&sc->queue);
if (bp == NULL)
break;
TAILQ_REMOVE(&sc->queue, bp, bio_queue);
g_io_request(bp, sc->path);
}
mtx_unlock(&sc->lock);
}
}
static void
g_fox_orphan(struct g_consumer *cp)
{
struct g_geom *gp;
struct g_fox_softc *sc;
int error, mark;
g_topology_assert();
gp = cp->geom;
sc = gp->softc;
printf("Removing path (%s) from fox (%s)\n",
cp->provider->name, gp->name);
mtx_lock(&sc->lock);
if (cp == sc->path) {
sc->opath = NULL;
sc->path = NULL;
sc->waiting = 1;
mark = 1;
} else {
mark = 0;
}
mtx_unlock(&sc->lock);
g_access(cp, -cp->acr, -cp->acw, -cp->ace);
error = cp->provider->error;
g_detach(cp);
g_destroy_consumer(cp);
if (!LIST_EMPTY(&gp->consumer)) {
if (mark)
g_post_event(g_fox_select_path, gp, M_WAITOK, gp, NULL);
return;
}
mtx_destroy(&sc->lock);
g_free(gp->softc);
gp->softc = NULL;
g_wither_geom(gp, ENXIO);
}
static void
g_fox_done(struct bio *bp)
{
struct g_geom *gp;
struct g_fox_softc *sc;
int error;
if (bp->bio_error == 0) {
g_std_done(bp);
return;
}
gp = bp->bio_from->geom;
sc = gp->softc;
if (bp->bio_from != sc->path) {
g_io_request(bp, sc->path);
return;
}
mtx_lock(&sc->lock);
sc->opath = sc->path;
sc->path = NULL;
error = g_post_event(g_fox_select_path, gp, M_NOWAIT, gp, NULL);
if (error) {
bp->bio_error = ENOMEM;
g_std_done(bp);
} else {
sc->waiting = 1;
TAILQ_INSERT_TAIL(&sc->queue, bp, bio_queue);
}
mtx_unlock(&sc->lock);
}
static void
g_fox_start(struct bio *bp)
{
struct g_geom *gp;
struct bio *bp2;
struct g_fox_softc *sc;
int error;
gp = bp->bio_to->geom;
sc = gp->softc;
if (sc == NULL) {
g_io_deliver(bp, ENXIO);
return;
}
switch(bp->bio_cmd) {
case BIO_READ:
case BIO_WRITE:
case BIO_DELETE:
bp2 = g_clone_bio(bp);
if (bp2 == NULL) {
g_io_deliver(bp, ENOMEM);
break;
}
bp2->bio_offset += sc->sectorsize;
bp2->bio_done = g_fox_done;
mtx_lock(&sc->lock);
if (sc->path == NULL || !TAILQ_EMPTY(&sc->queue)) {
if (sc->waiting == 0) {
error = g_post_event(g_fox_select_path, gp,
M_NOWAIT, gp, NULL);
if (error) {
g_destroy_bio(bp2);
bp2 = NULL;
g_io_deliver(bp, error);
} else {
sc->waiting = 1;
}
}
if (bp2 != NULL)
TAILQ_INSERT_TAIL(&sc->queue, bp2,
bio_queue);
} else {
g_io_request(bp2, sc->path);
}
mtx_unlock(&sc->lock);
break;
default:
g_io_deliver(bp, EOPNOTSUPP);
break;
}
return;
}
static int
g_fox_access(struct g_provider *pp, int dr, int dw, int de)
{
struct g_geom *gp;
struct g_fox_softc *sc;
struct g_consumer *cp1;
int error;
g_topology_assert();
gp = pp->geom;
sc = gp->softc;
if (sc == NULL) {
if (dr <= 0 && dw <= 0 && de <= 0)
return (0);
else
return (ENXIO);
}
if (sc->cr == 0 && sc->cw == 0 && sc->ce == 0) {
/*
* First open, open all consumers with an exclusive bit
*/
error = 0;
LIST_FOREACH(cp1, &gp->consumer, consumer) {
error = g_access(cp1, 0, 0, 1);
if (error) {
printf("FOX: access(%s,0,0,1) = %d\n",
cp1->provider->name, error);
break;
}
}
if (error) {
LIST_FOREACH(cp1, &gp->consumer, consumer) {
if (cp1->ace)
g_access(cp1, 0, 0, -1);
}
return (error);
}
}
if (sc->path == NULL)
g_fox_select_path(gp, 0);
if (sc->path == NULL)
error = ENXIO;
else
error = g_access(sc->path, dr, dw, de);
if (error == 0) {
sc->cr += dr;
sc->cw += dw;
sc->ce += de;
if (sc->cr == 0 && sc->cw == 0 && sc->ce == 0) {
/*
* Last close, remove e-bit on all consumers
*/
LIST_FOREACH(cp1, &gp->consumer, consumer)
g_access(cp1, 0, 0, -1);
}
}
return (error);
}
static struct g_geom *
g_fox_taste(struct g_class *mp, struct g_provider *pp, int flags __unused)
{
struct g_geom *gp, *gp2;
struct g_provider *pp2;
struct g_consumer *cp, *cp2;
struct g_fox_softc *sc, *sc2;
int error;
u_int sectorsize;
u_char *buf;
g_trace(G_T_TOPOLOGY, "fox_taste(%s, %s)", mp->name, pp->name);
g_topology_assert();
if (!strcmp(pp->geom->class->name, mp->name))
return (NULL);
gp = g_new_geomf(mp, "%s.fox", pp->name);
gp->softc = g_malloc(sizeof(struct g_fox_softc), M_WAITOK | M_ZERO);
sc = gp->softc;
cp = g_new_consumer(gp);
g_attach(cp, pp);
error = g_access(cp, 1, 0, 0);
if (error) {
g_free(sc);
g_detach(cp);
g_destroy_consumer(cp);
g_destroy_geom(gp);
return(NULL);
}
do {
sectorsize = cp->provider->sectorsize;
g_topology_unlock();
buf = g_read_data(cp, 0, sectorsize, NULL);
g_topology_lock();
if (buf == NULL)
break;
if (memcmp(buf, FOX_MAGIC, strlen(FOX_MAGIC)))
break;
/*
* First we need to see if this a new path for an existing fox.
*/
LIST_FOREACH(gp2, &mp->geom, geom) {
sc2 = gp2->softc;
if (sc2 == NULL)
continue;
if (memcmp(buf + 16, sc2->magic, sizeof sc2->magic))
continue;
break;
}
if (gp2 != NULL) {
/*
* It was. Create a new consumer for that fox,
* attach it, and if the fox is open, open this
* path with an exclusive count of one.
*/
printf("Adding path (%s) to fox (%s)\n",
pp->name, gp2->name);
cp2 = g_new_consumer(gp2);
g_attach(cp2, pp);
pp2 = LIST_FIRST(&gp2->provider);
if (pp2->acr > 0 || pp2->acw > 0 || pp2->ace > 0) {
error = g_access(cp2, 0, 0, 1);
if (error) {
/*
* This is bad, or more likely,
* the user is doing something stupid
*/
printf(
"WARNING: New path (%s) to fox(%s) not added: %s\n%s",
cp2->provider->name, gp2->name,
"Could not get exclusive bit.",
"WARNING: This indicates a risk of data inconsistency."
);
g_detach(cp2);
g_destroy_consumer(cp2);
}
}
break;
}
printf("Creating new fox (%s)\n", pp->name);
sc->path = cp;
memcpy(sc->magic, buf + 16, sizeof sc->magic);
pp2 = g_new_providerf(gp, "%s", gp->name);
pp2->mediasize = sc->mediasize = pp->mediasize - pp->sectorsize;
pp2->sectorsize = sc->sectorsize = pp->sectorsize;
printf("fox %s lock %p\n", gp->name, &sc->lock);
mtx_init(&sc->lock, "fox queue", NULL, MTX_DEF);
TAILQ_INIT(&sc->queue);
g_error_provider(pp2, 0);
} while (0);
if (buf != NULL)
g_free(buf);
g_access(cp, -1, 0, 0);
if (!LIST_EMPTY(&gp->provider)) {
if (!g_fox_once) {
g_fox_once = 1;
printf(
"WARNING: geom_fox (geom %s) is deprecated, "
"use gmultipath instead.\n", gp->name);
}
return (gp);
}
g_free(gp->softc);
g_detach(cp);
g_destroy_consumer(cp);
g_destroy_geom(gp);
return (NULL);
}
static int
g_fox_destroy_geom(struct gctl_req *req, struct g_class *mp, struct g_geom *gp)
{
struct g_fox_softc *sc;
g_topology_assert();
sc = gp->softc;
mtx_destroy(&sc->lock);
g_free(gp->softc);
gp->softc = NULL;
g_wither_geom(gp, ENXIO);
return (0);
}
static struct g_class g_fox_class = {
.name = FOX_CLASS_NAME,
.version = G_VERSION,
.taste = g_fox_taste,
.destroy_geom = g_fox_destroy_geom,
.start = g_fox_start,
.spoiled = g_fox_orphan,
.orphan = g_fox_orphan,
.access= g_fox_access,
};
DECLARE_GEOM_CLASS(g_fox_class, g_fox);
MODULE_VERSION(geom_fox, 0);

View File

@ -1,531 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2002 Poul-Henning Kamp
* Copyright (c) 2002 Networks Associates Technology, Inc.
* All rights reserved.
*
* This software was developed for the FreeBSD Project by Poul-Henning Kamp
* and NAI Labs, the Security Research Division of Network Associates, Inc.
* under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
* DARPA CHATS research program.
*
* 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 AUTHOR 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 AUTHOR 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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/errno.h>
#include <sys/endian.h>
#include <sys/systm.h>
#include <sys/sysctl.h>
#include <sys/kernel.h>
#include <sys/fcntl.h>
#include <sys/malloc.h>
#include <sys/bio.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/md5.h>
#include <sys/proc.h>
#include <sys/diskmbr.h>
#include <sys/sbuf.h>
#include <geom/geom.h>
#include <geom/geom_slice.h>
FEATURE(geom_mbr, "GEOM DOS/MBR partitioning support");
#define MBR_CLASS_NAME "MBR"
#define MBREXT_CLASS_NAME "MBREXT"
static int g_mbr_once = 0;
static struct dos_partition historical_bogus_partition_table[NDOSPART] = {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
{ 0x80, 0, 1, 0, DOSPTYP_386BSD, 255, 255, 255, 0, 50000, },
};
static struct dos_partition historical_bogus_partition_table_fixed[NDOSPART] = {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
{ 0x80, 0, 1, 0, DOSPTYP_386BSD, 254, 255, 255, 0, 50000, },
};
static void
g_mbr_print(int i, struct dos_partition *dp)
{
printf("[%d] f:%02x typ:%d", i, dp->dp_flag, dp->dp_typ);
printf(" s(CHS):%d/%d/%d", DPCYL(dp->dp_scyl, dp->dp_ssect),
dp->dp_shd, DPSECT(dp->dp_ssect));
printf(" e(CHS):%d/%d/%d", DPCYL(dp->dp_ecyl, dp->dp_esect),
dp->dp_ehd, DPSECT(dp->dp_esect));
printf(" s:%d l:%d\n", dp->dp_start, dp->dp_size);
}
struct g_mbr_softc {
int type [NDOSPART];
u_int sectorsize;
u_char sec0[512];
u_char slicesum[16];
};
/*
* XXX: Add gctl_req arg and give good error msgs.
* XXX: Check that length argument does not bring boot code inside any slice.
*/
static int
g_mbr_modify(struct g_geom *gp, struct g_mbr_softc *ms, u_char *sec0, int len __unused)
{
int i, error;
off_t l[NDOSPART];
struct dos_partition ndp[NDOSPART], *dp;
MD5_CTX md5sum;
g_topology_assert();
if (sec0[0x1fe] != 0x55 && sec0[0x1ff] != 0xaa)
return (EBUSY);
dp = ndp;
for (i = 0; i < NDOSPART; i++) {
dos_partition_dec(
sec0 + DOSPARTOFF + i * sizeof(struct dos_partition),
dp + i);
}
if ((!bcmp(dp, historical_bogus_partition_table,
sizeof historical_bogus_partition_table)) ||
(!bcmp(dp, historical_bogus_partition_table_fixed,
sizeof historical_bogus_partition_table_fixed))) {
/*
* We will not allow people to write these from "the inside",
* Since properly selfdestructing takes too much code. If
* people really want to do this, they cannot have any
* providers of this geom open, and in that case they can just
* as easily overwrite the MBR in the parent device.
*/
return(EBUSY);
}
for (i = 0; i < NDOSPART; i++) {
/*
* A Protective MBR (PMBR) has a single partition of
* type 0xEE spanning the whole disk. Such a MBR
* protects a GPT on the disk from MBR tools that
* don't know anything about GPT. We're interpreting
* it a bit more loosely: any partition of type 0xEE
* is to be skipped as it doesn't contain any data
* that we should care about. We still allow other
* partitions to be present in the MBR. A PMBR will
* be handled correctly anyway.
*/
if (dp[i].dp_typ == DOSPTYP_PMBR)
l[i] = 0;
else if (dp[i].dp_flag != 0 && dp[i].dp_flag != 0x80)
l[i] = 0;
else if (dp[i].dp_typ == 0)
l[i] = 0;
else
l[i] = (off_t)dp[i].dp_size * ms->sectorsize;
error = g_slice_config(gp, i, G_SLICE_CONFIG_CHECK,
(off_t)dp[i].dp_start * ms->sectorsize, l[i],
ms->sectorsize, "%ss%d", gp->name, 1 + i);
if (error)
return (error);
}
for (i = 0; i < NDOSPART; i++) {
ms->type[i] = dp[i].dp_typ;
g_slice_config(gp, i, G_SLICE_CONFIG_SET,
(off_t)dp[i].dp_start * ms->sectorsize, l[i],
ms->sectorsize, "%ss%d", gp->name, 1 + i);
}
bcopy(sec0, ms->sec0, 512);
/*
* Calculate MD5 from the first sector and use it for avoiding
* recursive slices creation.
*/
MD5Init(&md5sum);
MD5Update(&md5sum, ms->sec0, sizeof(ms->sec0));
MD5Final(ms->slicesum, &md5sum);
return (0);
}
static int
g_mbr_ioctl(struct g_provider *pp, u_long cmd, void *data, int fflag, struct thread *td)
{
struct g_geom *gp;
struct g_mbr_softc *ms;
struct g_slicer *gsp;
struct g_consumer *cp;
int error, opened;
gp = pp->geom;
gsp = gp->softc;
ms = gsp->softc;
opened = 0;
error = 0;
switch(cmd) {
case DIOCSMBR: {
if (!(fflag & FWRITE))
return (EPERM);
g_topology_lock();
cp = LIST_FIRST(&gp->consumer);
if (cp->acw == 0) {
error = g_access(cp, 0, 1, 0);
if (error == 0)
opened = 1;
}
if (!error)
error = g_mbr_modify(gp, ms, data, 512);
if (!error)
error = g_write_data(cp, 0, data, 512);
if (opened)
g_access(cp, 0, -1 , 0);
g_topology_unlock();
return(error);
}
default:
return (ENOIOCTL);
}
}
static int
g_mbr_start(struct bio *bp)
{
struct g_provider *pp;
struct g_geom *gp;
struct g_mbr_softc *mp;
struct g_slicer *gsp;
int idx;
pp = bp->bio_to;
idx = pp->index;
gp = pp->geom;
gsp = gp->softc;
mp = gsp->softc;
if (bp->bio_cmd == BIO_GETATTR) {
if (g_handleattr_int(bp, "MBR::type", mp->type[idx]))
return (1);
if (g_handleattr_off_t(bp, "MBR::offset",
gsp->slices[idx].offset))
return (1);
if (g_handleattr(bp, "MBR::slicesum", mp->slicesum,
sizeof(mp->slicesum)))
return (1);
}
return (0);
}
static void
g_mbr_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, struct g_consumer *cp __unused, struct g_provider *pp)
{
struct g_mbr_softc *mp;
struct g_slicer *gsp;
gsp = gp->softc;
mp = gsp->softc;
g_slice_dumpconf(sb, indent, gp, cp, pp);
if (pp != NULL) {
if (indent == NULL)
sbuf_printf(sb, " ty %d", mp->type[pp->index]);
else
sbuf_printf(sb, "%s<type>%d</type>\n", indent,
mp->type[pp->index]);
}
}
static struct g_geom *
g_mbr_taste(struct g_class *mp, struct g_provider *pp, int insist)
{
struct g_geom *gp;
struct g_consumer *cp;
int error;
struct g_mbr_softc *ms;
u_int fwsectors, sectorsize;
u_char *buf;
u_char hash[16];
MD5_CTX md5sum;
g_trace(G_T_TOPOLOGY, "mbr_taste(%s,%s)", mp->name, pp->name);
g_topology_assert();
if (!strcmp(pp->geom->class->name, MBR_CLASS_NAME))
return (NULL);
gp = g_slice_new(mp, NDOSPART, pp, &cp, &ms, sizeof *ms, g_mbr_start);
if (gp == NULL)
return (NULL);
g_topology_unlock();
do {
error = g_getattr("GEOM::fwsectors", cp, &fwsectors);
if (error)
fwsectors = 17;
sectorsize = cp->provider->sectorsize;
if (sectorsize < 512)
break;
ms->sectorsize = sectorsize;
buf = g_read_data(cp, 0, sectorsize, NULL);
if (buf == NULL)
break;
/*
* Calculate MD5 from the first sector and use it for avoiding
* recursive slices creation.
*/
bcopy(buf, ms->sec0, 512);
MD5Init(&md5sum);
MD5Update(&md5sum, ms->sec0, sizeof(ms->sec0));
MD5Final(ms->slicesum, &md5sum);
error = g_getattr("MBR::slicesum", cp, &hash);
if (!error && !bcmp(ms->slicesum, hash, sizeof(hash))) {
g_free(buf);
break;
}
g_topology_lock();
g_mbr_modify(gp, ms, buf, 512);
g_topology_unlock();
g_free(buf);
break;
} while (0);
g_topology_lock();
g_access(cp, -1, 0, 0);
if (LIST_EMPTY(&gp->provider)) {
g_slice_spoiled(cp);
return (NULL);
}
if (!g_mbr_once) {
g_mbr_once = 1;
printf(
"WARNING: geom_mbr (geom %s) is deprecated, "
"use gpart instead.\n", gp->name);
}
return (gp);
}
static void
g_mbr_config(struct gctl_req *req, struct g_class *mp, const char *verb)
{
struct g_geom *gp;
struct g_consumer *cp;
struct g_mbr_softc *ms;
struct g_slicer *gsp;
int opened = 0, error = 0;
void *data;
int len;
g_topology_assert();
gp = gctl_get_geom(req, mp, "geom");
if (gp == NULL)
return;
if (strcmp(verb, "write MBR")) {
gctl_error(req, "Unknown verb");
return;
}
gsp = gp->softc;
ms = gsp->softc;
data = gctl_get_param(req, "data", &len);
if (data == NULL)
return;
if (len < 512 || (len % 512)) {
gctl_error(req, "Wrong request length");
return;
}
cp = LIST_FIRST(&gp->consumer);
if (cp->acw == 0) {
error = g_access(cp, 0, 1, 0);
if (error == 0)
opened = 1;
}
if (!error)
error = g_mbr_modify(gp, ms, data, len);
if (error)
gctl_error(req, "conflict with open slices");
if (!error)
error = g_write_data(cp, 0, data, len);
if (error)
gctl_error(req, "sector zero write failed");
if (opened)
g_access(cp, 0, -1 , 0);
return;
}
static struct g_class g_mbr_class = {
.name = MBR_CLASS_NAME,
.version = G_VERSION,
.taste = g_mbr_taste,
.dumpconf = g_mbr_dumpconf,
.ctlreq = g_mbr_config,
.ioctl = g_mbr_ioctl,
};
DECLARE_GEOM_CLASS(g_mbr_class, g_mbr);
#define NDOSEXTPART 32
struct g_mbrext_softc {
int type [NDOSEXTPART];
};
static int
g_mbrext_start(struct bio *bp)
{
struct g_provider *pp;
struct g_geom *gp;
struct g_mbrext_softc *mp;
struct g_slicer *gsp;
int idx;
pp = bp->bio_to;
idx = pp->index;
gp = pp->geom;
gsp = gp->softc;
mp = gsp->softc;
if (bp->bio_cmd == BIO_GETATTR) {
if (g_handleattr_int(bp, "MBR::type", mp->type[idx]))
return (1);
}
return (0);
}
static void
g_mbrext_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, struct g_consumer *cp __unused, struct g_provider *pp)
{
struct g_mbrext_softc *mp;
struct g_slicer *gsp;
g_slice_dumpconf(sb, indent, gp, cp, pp);
gsp = gp->softc;
mp = gsp->softc;
if (pp != NULL) {
if (indent == NULL)
sbuf_printf(sb, " ty %d", mp->type[pp->index]);
else
sbuf_printf(sb, "%s<type>%d</type>\n", indent,
mp->type[pp->index]);
}
}
static struct g_geom *
g_mbrext_taste(struct g_class *mp, struct g_provider *pp, int insist __unused)
{
struct g_geom *gp;
struct g_consumer *cp;
int error, i, slice;
struct g_mbrext_softc *ms;
off_t off;
u_char *buf;
struct dos_partition dp[4];
u_int fwsectors, sectorsize;
g_trace(G_T_TOPOLOGY, "g_mbrext_taste(%s,%s)", mp->name, pp->name);
g_topology_assert();
if (strcmp(pp->geom->class->name, MBR_CLASS_NAME))
return (NULL);
gp = g_slice_new(mp, NDOSEXTPART, pp, &cp, &ms, sizeof *ms,
g_mbrext_start);
if (gp == NULL)
return (NULL);
g_topology_unlock();
off = 0;
slice = 0;
do {
error = g_getattr("MBR::type", cp, &i);
if (error || (i != DOSPTYP_EXT && i != DOSPTYP_EXTLBA))
break;
error = g_getattr("GEOM::fwsectors", cp, &fwsectors);
if (error)
fwsectors = 17;
sectorsize = cp->provider->sectorsize;
if (sectorsize != 512)
break;
for (;;) {
buf = g_read_data(cp, off, sectorsize, NULL);
if (buf == NULL)
break;
if (buf[0x1fe] != 0x55 && buf[0x1ff] != 0xaa) {
g_free(buf);
break;
}
for (i = 0; i < NDOSPART; i++)
dos_partition_dec(
buf + DOSPARTOFF +
i * sizeof(struct dos_partition), dp + i);
g_free(buf);
if (0 && bootverbose) {
printf("MBREXT Slice %d on %s:\n",
slice + 5, gp->name);
g_mbr_print(0, dp);
g_mbr_print(1, dp + 1);
}
if ((dp[0].dp_flag & 0x7f) == 0 &&
dp[0].dp_size != 0 && dp[0].dp_typ != 0) {
g_topology_lock();
g_slice_config(gp, slice, G_SLICE_CONFIG_SET,
(((off_t)dp[0].dp_start) << 9ULL) + off,
((off_t)dp[0].dp_size) << 9ULL,
sectorsize,
"%*.*s%d",
(int)strlen(gp->name) - 1,
(int)strlen(gp->name) - 1,
gp->name,
slice + 5);
g_topology_unlock();
ms->type[slice] = dp[0].dp_typ;
slice++;
}
if (dp[1].dp_flag != 0)
break;
if (dp[1].dp_typ != DOSPTYP_EXT &&
dp[1].dp_typ != DOSPTYP_EXTLBA)
break;
if (dp[1].dp_size == 0)
break;
off = ((off_t)dp[1].dp_start) << 9ULL;
}
break;
} while (0);
g_topology_lock();
g_access(cp, -1, 0, 0);
if (LIST_EMPTY(&gp->provider)) {
g_slice_spoiled(cp);
return (NULL);
}
return (gp);
}
static struct g_class g_mbrext_class = {
.name = MBREXT_CLASS_NAME,
.version = G_VERSION,
.taste = g_mbrext_taste,
.dumpconf = g_mbrext_dumpconf,
};
DECLARE_GEOM_CLASS(g_mbrext_class, g_mbrext);
MODULE_VERSION(geom_mbr, 0);

View File

@ -1,337 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (c) 2002 Poul-Henning Kamp
* Copyright (c) 2002 Networks Associates Technology, Inc.
* All rights reserved.
*
* This software was developed for the FreeBSD Project by Poul-Henning Kamp
* and NAI Labs, the Security Research Division of Network Associates, Inc.
* under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
* DARPA CHATS research program.
*
* 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.
* 3. The names of the authors may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/endian.h>
#include <sys/systm.h>
#include <sys/sysctl.h>
#include <sys/kernel.h>
#include <sys/conf.h>
#include <sys/bio.h>
#include <sys/malloc.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/md5.h>
#include <sys/sbuf.h>
#include <sys/sun_disklabel.h>
#include <geom/geom.h>
#include <geom/geom_slice.h>
#include <machine/endian.h>
FEATURE(geom_sunlabel, "GEOM Sun/Solaris partitioning support");
#define SUNLABEL_CLASS_NAME "SUN"
struct g_sunlabel_softc {
int sectorsize;
int nheads;
int nsects;
int nalt;
u_char labelsum[16];
};
static int g_sunlabel_once = 0;
static int
g_sunlabel_modify(struct g_geom *gp, struct g_sunlabel_softc *ms, u_char *sec0)
{
int i, error;
u_int u, v, csize;
struct sun_disklabel sl;
MD5_CTX md5sum;
error = sunlabel_dec(sec0, &sl);
if (error)
return (error);
csize = sl.sl_ntracks * sl.sl_nsectors;
for (i = 0; i < SUN_NPART; i++) {
v = sl.sl_part[i].sdkp_cyloffset;
u = sl.sl_part[i].sdkp_nsectors;
error = g_slice_config(gp, i, G_SLICE_CONFIG_CHECK,
((off_t)v * csize) << 9ULL,
((off_t)u) << 9ULL,
ms->sectorsize,
"%s%c", gp->name, 'a' + i);
if (error)
return (error);
}
for (i = 0; i < SUN_NPART; i++) {
v = sl.sl_part[i].sdkp_cyloffset;
u = sl.sl_part[i].sdkp_nsectors;
g_slice_config(gp, i, G_SLICE_CONFIG_SET,
((off_t)v * csize) << 9ULL,
((off_t)u) << 9ULL,
ms->sectorsize,
"%s%c", gp->name, 'a' + i);
}
ms->nalt = sl.sl_acylinders;
ms->nheads = sl.sl_ntracks;
ms->nsects = sl.sl_nsectors;
/*
* Calculate MD5 from the first sector and use it for avoiding
* recursive labels creation.
*/
MD5Init(&md5sum);
MD5Update(&md5sum, sec0, ms->sectorsize);
MD5Final(ms->labelsum, &md5sum);
return (0);
}
static void
g_sunlabel_hotwrite(void *arg, int flag)
{
struct bio *bp;
struct g_geom *gp;
struct g_slicer *gsp;
struct g_slice *gsl;
struct g_sunlabel_softc *ms;
u_char *p;
int error;
KASSERT(flag != EV_CANCEL, ("g_sunlabel_hotwrite cancelled"));
bp = arg;
gp = bp->bio_to->geom;
gsp = gp->softc;
ms = gsp->softc;
gsl = &gsp->slices[bp->bio_to->index];
/*
* XXX: For all practical purposes, this whould be equvivalent to
* XXX: "p = (u_char *)bp->bio_data;" because the label is always
* XXX: in the first sector and we refuse sectors smaller than the
* XXX: label.
*/
p = (u_char *)bp->bio_data - (bp->bio_offset + gsl->offset);
error = g_sunlabel_modify(gp, ms, p);
if (error) {
g_io_deliver(bp, EPERM);
return;
}
g_slice_finish_hot(bp);
}
static void
g_sunlabel_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, struct g_consumer *cp __unused, struct g_provider *pp)
{
struct g_slicer *gsp;
struct g_sunlabel_softc *ms;
gsp = gp->softc;
ms = gsp->softc;
g_slice_dumpconf(sb, indent, gp, cp, pp);
if (indent == NULL) {
sbuf_printf(sb, " sc %u hd %u alt %u",
ms->nsects, ms->nheads, ms->nalt);
}
}
struct g_hh01 {
struct g_geom *gp;
struct g_sunlabel_softc *ms;
u_char *label;
int error;
};
static void
g_sunlabel_callconfig(void *arg, int flag)
{
struct g_hh01 *hp;
hp = arg;
hp->error = g_sunlabel_modify(hp->gp, hp->ms, hp->label);
if (!hp->error)
hp->error = g_write_data(LIST_FIRST(&hp->gp->consumer),
0, hp->label, SUN_SIZE);
}
/*
* NB! curthread is user process which GCTL'ed.
*/
static void
g_sunlabel_config(struct gctl_req *req, struct g_class *mp, const char *verb)
{
u_char *label;
int error, i;
struct g_hh01 h0h0;
struct g_slicer *gsp;
struct g_geom *gp;
struct g_consumer *cp;
g_topology_assert();
gp = gctl_get_geom(req, mp, "geom");
if (gp == NULL)
return;
cp = LIST_FIRST(&gp->consumer);
gsp = gp->softc;
if (!strcmp(verb, "write label")) {
label = gctl_get_paraml(req, "label", SUN_SIZE);
if (label == NULL)
return;
h0h0.gp = gp;
h0h0.ms = gsp->softc;
h0h0.label = label;
h0h0.error = -1;
/* XXX: Does this reference register with our selfdestruct code ? */
error = g_access(cp, 1, 1, 1);
if (error) {
gctl_error(req, "could not access consumer");
return;
}
g_sunlabel_callconfig(&h0h0, 0);
g_access(cp, -1, -1, -1);
} else if (!strcmp(verb, "write bootcode")) {
label = gctl_get_paraml(req, "bootcode", SUN_BOOTSIZE);
if (label == NULL)
return;
/* XXX: Does this reference register with our selfdestruct code ? */
error = g_access(cp, 1, 1, 1);
if (error) {
gctl_error(req, "could not access consumer");
return;
}
for (i = 0; i < SUN_NPART; i++) {
if (gsp->slices[i].length <= SUN_BOOTSIZE)
continue;
g_write_data(cp,
gsp->slices[i].offset + SUN_SIZE, label + SUN_SIZE,
SUN_BOOTSIZE - SUN_SIZE);
}
g_access(cp, -1, -1, -1);
} else {
gctl_error(req, "Unknown verb parameter");
}
}
static int
g_sunlabel_start(struct bio *bp)
{
struct g_sunlabel_softc *mp;
struct g_slicer *gsp;
gsp = bp->bio_to->geom->softc;
mp = gsp->softc;
if (bp->bio_cmd == BIO_GETATTR) {
if (g_handleattr(bp, "SUN::labelsum", mp->labelsum,
sizeof(mp->labelsum)))
return (1);
}
return (0);
}
static struct g_geom *
g_sunlabel_taste(struct g_class *mp, struct g_provider *pp, int flags)
{
struct g_geom *gp;
struct g_consumer *cp;
struct g_sunlabel_softc *ms;
struct g_slicer *gsp;
u_char *buf, hash[16];
MD5_CTX md5sum;
int error;
g_trace(G_T_TOPOLOGY, "g_sunlabel_taste(%s,%s)", mp->name, pp->name);
g_topology_assert();
if (flags == G_TF_NORMAL &&
!strcmp(pp->geom->class->name, SUNLABEL_CLASS_NAME))
return (NULL);
gp = g_slice_new(mp, 8, pp, &cp, &ms, sizeof *ms, g_sunlabel_start);
if (gp == NULL)
return (NULL);
gsp = gp->softc;
do {
ms->sectorsize = cp->provider->sectorsize;
if (ms->sectorsize < 512)
break;
g_topology_unlock();
buf = g_read_data(cp, 0, ms->sectorsize, NULL);
g_topology_lock();
if (buf == NULL)
break;
/*
* Calculate MD5 from the first sector and use it for avoiding
* recursive labels creation.
*/
MD5Init(&md5sum);
MD5Update(&md5sum, buf, ms->sectorsize);
MD5Final(ms->labelsum, &md5sum);
error = g_getattr("SUN::labelsum", cp, &hash);
if (!error && !bcmp(ms->labelsum, hash, sizeof(hash))) {
g_free(buf);
break;
}
g_sunlabel_modify(gp, ms, buf);
g_free(buf);
break;
} while (0);
g_access(cp, -1, 0, 0);
if (LIST_EMPTY(&gp->provider)) {
g_slice_spoiled(cp);
return (NULL);
}
g_slice_conf_hot(gp, 0, 0, SUN_SIZE,
G_SLICE_HOT_ALLOW, G_SLICE_HOT_DENY, G_SLICE_HOT_CALL);
gsp->hot = g_sunlabel_hotwrite;
if (!g_sunlabel_once) {
g_sunlabel_once = 1;
printf(
"WARNING: geom_sunlabel (geom %s) is deprecated, "
"use gpart instead.\n", gp->name);
}
return (gp);
}
static struct g_class g_sunlabel_class = {
.name = SUNLABEL_CLASS_NAME,
.version = G_VERSION,
.taste = g_sunlabel_taste,
.ctlreq = g_sunlabel_config,
.dumpconf = g_sunlabel_dumpconf,
};
DECLARE_GEOM_CLASS(g_sunlabel_class, g_sunlabel);
MODULE_VERSION(geom_sunlabel, 0);

View File

@ -1,167 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2002, 2003 Gordon Tetlow
* 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 AUTHOR 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 AUTHOR 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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/errno.h>
#include <sys/systm.h>
#include <sys/sysctl.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/bio.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
#include <geom/geom.h>
#include <geom/geom_slice.h>
FEATURE(geom_vol, "GEOM support for volume names from UFS superblock");
#define VOL_FFS_CLASS_NAME "VOL_FFS"
static int superblocks[] = SBLOCKSEARCH;
static int g_vol_ffs_once;
struct g_vol_ffs_softc {
char * vol;
};
static int
g_vol_ffs_start(struct bio *bp __unused)
{
return(0);
}
static struct g_geom *
g_vol_ffs_taste(struct g_class *mp, struct g_provider *pp, int flags)
{
struct g_geom *gp;
struct g_consumer *cp;
struct g_vol_ffs_softc *ms;
int sb, superblock;
struct fs *fs;
g_trace(G_T_TOPOLOGY, "vol_taste(%s,%s)", mp->name, pp->name);
g_topology_assert();
/*
* XXX This is a really weak way to make sure we don't recurse.
* Probably ought to use BIO_GETATTR to check for this.
*/
if (flags == G_TF_NORMAL &&
!strcmp(pp->geom->class->name, VOL_FFS_CLASS_NAME))
return (NULL);
gp = g_slice_new(mp, 1, pp, &cp, &ms, sizeof(*ms), g_vol_ffs_start);
if (gp == NULL)
return (NULL);
g_topology_unlock();
/*
* Walk through the standard places that superblocks hide and look
* for UFS magic. If we find magic, then check that the size in the
* superblock corresponds to the size of the underlying provider.
* Finally, look for a volume label and create an appropriate
* provider based on that.
*/
for (sb=0; (superblock = superblocks[sb]) != -1; sb++) {
/*
* Take care not to issue an invalid I/O request. The
* offset and size of the superblock candidate must be
* multiples of the provider's sector size, otherwise an
* FFS can't exist on the provider anyway.
*/
if (superblock % cp->provider->sectorsize != 0 ||
SBLOCKSIZE % cp->provider->sectorsize != 0)
continue;
fs = (struct fs *) g_read_data(cp, superblock,
SBLOCKSIZE, NULL);
if (fs == NULL)
continue;
/* Check for magic and make sure things are the right size */
if (fs->fs_magic == FS_UFS1_MAGIC) {
if (fs->fs_old_size * fs->fs_fsize !=
(int32_t) pp->mediasize) {
g_free(fs);
continue;
}
} else if (fs->fs_magic == FS_UFS2_MAGIC) {
if (fs->fs_size * fs->fs_fsize !=
(int64_t) pp->mediasize) {
g_free(fs);
continue;
}
} else {
g_free(fs);
continue;
}
/* Check for volume label */
if (fs->fs_volname[0] == '\0') {
g_free(fs);
continue;
}
/* XXX We need to check for namespace conflicts. */
/* XXX How do you handle a mirror set? */
/* XXX We don't validate the volume name. */
g_topology_lock();
/* Alright, we have a label and a volume name, reconfig. */
g_slice_config(gp, 0, G_SLICE_CONFIG_SET, (off_t) 0,
pp->mediasize, pp->sectorsize, "vol/%s",
fs->fs_volname);
g_free(fs);
g_topology_unlock();
break;
}
g_topology_lock();
g_access(cp, -1, 0, 0);
if (LIST_EMPTY(&gp->provider)) {
g_slice_spoiled(cp);
return (NULL);
}
if (!g_vol_ffs_once) {
g_vol_ffs_once = 1;
printf(
"WARNING: geom_vol_Ffs (geom %s) is deprecated, "
"use glabel instead.\n", gp->name);
}
return (gp);
}
static struct g_class g_vol_ffs_class = {
.name = VOL_FFS_CLASS_NAME,
.version = G_VERSION,
.taste = g_vol_ffs_taste,
};
DECLARE_GEOM_CLASS(g_vol_ffs_class, g_vol_ffs);
MODULE_VERSION(geom_vol_ffs, 0);

View File

@ -1,8 +0,0 @@
# $FreeBSD$
.PATH: ${SRCTOP}/sys/geom
KMOD= geom_bsd
SRCS= geom_bsd.c geom_bsd_enc.c
.include <bsd.kmod.mk>

View File

@ -1,8 +0,0 @@
# $FreeBSD$
.PATH: ${SRCTOP}/sys/geom
KMOD= geom_fox
SRCS= geom_fox.c
.include <bsd.kmod.mk>

View File

@ -1,8 +0,0 @@
# $FreeBSD$
.PATH: ${SRCTOP}/sys/geom
KMOD= geom_mbr
SRCS= geom_mbr.c geom_mbr_enc.c
.include <bsd.kmod.mk>

View File

@ -1,8 +0,0 @@
# $FreeBSD$
.PATH: ${SRCTOP}/sys/geom
KMOD= geom_sunlabel
SRCS= geom_sunlabel.c geom_sunlabel_enc.c
.include <bsd.kmod.mk>

View File

@ -1,8 +0,0 @@
# $FreeBSD$
.PATH: ${SRCTOP}/sys/geom
KMOD= geom_vol_ffs
SRCS= geom_vol_ffs.c
.include <bsd.kmod.mk>

View File

@ -38,9 +38,6 @@
#include <sys/disk/mbr.h>
#include <sys/ioccom.h>
void dos_partition_dec(void const *pp, struct dos_partition *d);
void dos_partition_enc(void *pp, struct dos_partition *d);
#define DIOCSMBR _IOW('M', 129, u_char[512])
#endif /* !_SYS_DISKMBR_H_ */

View File

@ -426,16 +426,6 @@ write_mbr(const char *fname, int flags, u_int8_t *mbr, int mbr_size,
errx(1, "GEOM_PART: write bootcode to %s failed: %s",
fname, errmsg);
gctl_free(grq);
} else if (geom_class_available("MBR") != 0) {
grq = gctl_get_handle();
gctl_ro_param(grq, "verb", -1, "write MBR");
gctl_ro_param(grq, "class", -1, "MBR");
gctl_ro_param(grq, "geom", -1, pname);
gctl_ro_param(grq, "data", mbr_size, mbr);
errmsg = gctl_issue(grq);
if (errmsg != NULL)
err(1, "GEOM_MBR: write MBR to %s failed", fname);
gctl_free(grq);
} else
errx(1, "can't write MBR to %s", fname);
free(pname);