/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdio.h>
#include <meta.h>
#include "meta_repartition.h"
/*
* FUNCTION: meta_replicaslice()
* INPUT: dnp - the name of the drive to check
* OUTPUT: slicep - pointer to slice number
* ep - pointer to an md_error_t structure in which
* to return errors to the caller
* RETURNS: int - 0 - value pointed to by slicep is valid
* -1 - otherwise
*
* PURPOSE: Determine which slice of the specified drive to
* reserve, presumably for metadb replica usage.
*
* NOTE: If slicep is NULL, the return code will indicate
* whether or not the slice number could be determined
*/
int
)
{
int err = 0;
int ioctl_return;
int fd;
char *rname;
char *n;
int open_errno;
open_errno = errno;
Free(n);
if (fd < 0) {
}
}
/*
* if our drivenamep points to a device not supporting
* DKIOCGGEOM, we have an EFI label.
*/
errno = 0;
/*
* If the DKIOCGGEOM ioctl succeeded, then the device has a
* VTOC style label. In this case, we use slice 7.
*/
if (ioctl_return == 0) {
}
return (0);
}
/*
* ENOTSUP indicates an EFI style label, in which case slice 7
* cannot be used because its minor number is reserved. In
* this case, use slice 6.
*/
}
return (0);
}
/*
* Those are the only two cases we know how to deal with;
* either the drivenamep didn't point to a disk, or the ioctl
* failed for some other reason.
*/
}
}
/*
* FUNCTION: meta_repartition_drive()
* INPUT: sp - the set name for the device to check
* dnp - the name of the drive to partition
* options - options (see NOTES)
* OUTPUT: vtocp - pointer to an mdvtoc_t structure in which
* to return the new VTOC to the caller
* ep - pointer to an md_error_t structure in which
* to return errors to the caller
* RETURNS: int - 0 - drive was or can be repartitioned
* -1 - drive could not or should not be
* repartitioned
* PURPOSE: Repartition a disk for use in a disk set or in order
* to create soft partitions on it. Alternatively,
* return the VTOC that the disk would have if it were
* repartitioned without actually repartitioning it.
*
* NOTES:
*
* This routine will repartition a drive to make it suitable for
* inclusion in a diskset. Specifically, it will create a
* proposed VTOC that specifies a replica slice that begins at the
* first valid lba, is large enough to hold a label and a metadb
* replica, does not overlap any other slices, and is unmountable.
* If the current replica slice already satisfies those criteria,
* the routine will neither create a proposed VTOC nor repartition
* the drive unless the MD_REPART_FORCE flag is passed into the
* routine in the options argument. If the routine does create a
* proposed VTOC, it will return the proposed VTOC in *vtocp if
* vtocp isn't NULL.
*
* The slice to be used as the replica slice is determined by the
* function meta_replicaslice().
*
* If the replica slice does not satisfy the above criteria or the
* MD_REPART_FORCE flag is set, the proposed VTOC will specify a
* replica slice that satisfies the above criteria, a slice zero
* that contains the remaining space on the disk, and no other
* slices. If that repartitioning would cause the replica slice
* to move or shrink, and the MD_REPART_LEAVE_REP option is set,
* the routine will return -1 without creating or returning a
* proposed vtoc, and without repartitioning the disk. Otherwise
* the routine will repartition the disk unless the
* MD_REPART_DONT_LABEL flag is set in the options argument.
*
* If the MD_REPART_DONT_LABEL flag is set in the options argument,
* but the routine would otherwise repartition the drive, the
* routine won't repartition the drive, but will create a proposed
* VTOC that satisfies the criteria defined above and return it
* it in *vtocp if vtocp isn't NULL, The MD_REPART_DONT_LABEL
* option allows calling routines to determine what the contents of
* the drive's VTOC would be if the drive were repartitioned without
* actually repartitioning the drive.
*/
int
int options,
)
{
unsigned long long cylsize;
unsigned long long drvsize;
int i;
unsigned long long ressize;
return (-1);
}
/* Don't round for EFI disks */
if (replicaslice == MD_SLICE6)
round_sizes = 0;
/*
* We took as argument a drive name pointer, but we need a
* slice name pointer to retrieve vtoc information. So get
* the name pointer for slice zero first, then use it to get
* the vtoc info for the disk.
*/
return (-1);
return (-1);
/*
* Determine the metadb size.
*/
if (!metaislocalset(sp)) {
return (-1);
if (MD_MNSET_DESC(sd))
}
/* If we've got an efi disk, we better have lba info */
/*
* At this point, ressize is used as a minimum value. Later
* it will be rounded up to a cylinder boundary if
* appropriate. ressize is in units of disk sectors.
*/
/*
* If we're forcing the repartition, we can skip the replica
* slice and overlap tests.
*/
if (options & MD_REPART_FORCE) {
goto do_repartition;
}
/*
* Replica slice tests: it must begin at first_lba, be long
* enough, have the right flags, and not overlap any other
* slices. If any of these conditions is violated, we need to
* repartition the disk.
*/
goto do_repartition;
}
goto do_repartition;
}
goto do_repartition;
}
/*
* Check for overlap: this test should use the actual size of
* the replica slice, as contained in the vtoc, and NOT the
* minimum size calculated above.
*/
if (i != replicaslice) {
goto do_repartition;
}
}
}
/*
* If we passed the above tests, then the disk is already
* partitioned appropriately, and we're not being told to
* force a change.
*/
return (0);
/* Retrieve disk geometry info and round to cylinder sizes */
if (round_sizes != 0) {
return (-1);
/*
* Both cylsize and drvsize are in units of disk
* sectors.
*
* The intended results are of type unsigned long
* long. Since each operand of the first
* multiplication is of type unsigned int, we risk
* overflow by multiplying and then converting the
* result. Therefore we explicitly cast (at least)
* one of the operands, forcing conversion BEFORE
* multiplication, and avoiding overflow. The second
* assignment is OK, since one of the operands is
* already of the desired type.
*/
cylsize =
/*
* How many cylinders must we reserve for the replica
* slice to ensure that it meets the previously
* calculated minimum size?
*/
} else {
}
/* Would this require a forbidden change? */
if (options & MD_REPART_LEAVE_REP) {
}
}
/*
* It seems unlikely that someone would pass us too small a
* disk, but it's still worth checking for...
*/
}
/*
* Create the proposed VTOC. First copy the current VTOC
* into the proposed VTOC to duplicate the values that don't
* need to change. Then change the partition table and set
* the flag value for the replica slice to resflag to reserve it
* for metadata.
*/
proposed_vtoc = *mdvp;
/* We need at least replicaslice partitions in the proposed vtoc */
}
for (i = 0; i < proposed_vtoc.nparts; i++) {
/* don't change the reserved partition of an EFI device */
else
sizeof (proposed_vtoc.parts[i]));
}
if (!(options & MD_REPART_DONT_LABEL)) {
/*
* Label the disk with the proposed VTOC.
*/
*mdvp = proposed_vtoc;
return (-1);
}
}
/*
* Return the proposed VTOC.
*/
*vtocp = proposed_vtoc;
}
return (0);
}