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:
parent
d3067c6e6a
commit
ee40fecafe
@ -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);
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
34
sbin/fdisk/fdisk_mbr_enc.h
Normal file
34
sbin/fdisk/fdisk_mbr_enc.h
Normal 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);
|
@ -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"
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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
|
@ -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 \
|
||||
|
@ -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
|
||||
|
@ -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.
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
@ -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);
|
@ -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);
|
@ -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);
|
@ -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);
|
@ -1,8 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${SRCTOP}/sys/geom
|
||||
|
||||
KMOD= geom_bsd
|
||||
SRCS= geom_bsd.c geom_bsd_enc.c
|
||||
|
||||
.include <bsd.kmod.mk>
|
@ -1,8 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${SRCTOP}/sys/geom
|
||||
|
||||
KMOD= geom_fox
|
||||
SRCS= geom_fox.c
|
||||
|
||||
.include <bsd.kmod.mk>
|
@ -1,8 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${SRCTOP}/sys/geom
|
||||
|
||||
KMOD= geom_mbr
|
||||
SRCS= geom_mbr.c geom_mbr_enc.c
|
||||
|
||||
.include <bsd.kmod.mk>
|
@ -1,8 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${SRCTOP}/sys/geom
|
||||
|
||||
KMOD= geom_sunlabel
|
||||
SRCS= geom_sunlabel.c geom_sunlabel_enc.c
|
||||
|
||||
.include <bsd.kmod.mk>
|
@ -1,8 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${SRCTOP}/sys/geom
|
||||
|
||||
KMOD= geom_vol_ffs
|
||||
SRCS= geom_vol_ffs.c
|
||||
|
||||
.include <bsd.kmod.mk>
|
@ -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_ */
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user