/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (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 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* This file contains miscellaneous device validation routines.
*/
#include "global.h"
#include <sys/autoconf.h>
#include <signal.h>
#include <malloc.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <libgen.h>
#include <sys/sysmacros.h>
#include <ctype.h>
#include <libdiskmgt.h>
#include <libnvpair.h>
#include "misc.h"
#include "checkdev.h"
#include <sys/efi_partition.h>
/* Function prototypes */
#ifdef __STDC__
static struct swaptable *getswapentries(void);
static void freeswapentries(struct swaptable *);
static int getpartition(char *pathname);
static int checkpartitions(int bm_mounted);
#else /* __STDC__ */
static struct swaptable *getswapentries();
static void freeswapentries();
static int getpartition();
static int checkpartitions();
#endif /* __STDC__ */
extern char *getfullname();
static struct swaptable *
getswapentries(void)
{
int i, num;
/*
* get the number of swap entries
*/
err_print("swapctl error ");
fullabort();
}
if (num == 0)
return (NULL);
== NULL) {
err_print("getswapentries: malloc failed.\n");
fullabort();
}
err_print("getswapentries: malloc failed.\n");
fullabort();
}
}
err_print("swapctl error ");
fullabort();
}
}
}
return (st);
}
static void
{
int i;
}
/*
* function getpartition:
*/
static int
char *pathname;
{
int mfd;
/*
* Map the block device name to the raw device name.
* If it doesn't appear to be a device name, skip it.
*/
return (found);
/*
* Determine if this appears to be a disk device.
* First attempt to open the device. If if fails, skip it.
*/
return (found);
}
/*
* Must be a character device
*/
return (found);
}
/*
* Attempt to read the configuration info on the disk.
*/
return (found);
}
/*
* Finished with the opened device
*/
/*
* If it's not the disk we're interested in, it doesn't apply.
*/
return (found);
}
/*
* Extract the partition that is mounted.
*/
}
/*
* This Routine checks to see if there are partitions used for swapping overlaps
* a given portion of a disk. If the start parameter is < 0, it means
* that the entire disk should be checked
*/
int
{
int i;
int found = 0;
int part;
/*
* If we are only checking part of the disk, the disk must
* have a partition map to check against. If it doesn't,
* we hope for the best.
*/
return (0);
/*
* check for swap entries
*/
st = getswapentries();
/*
* if there are no swap entries return.
*/
return (0);
if (start == UINT_MAX64) {
found = -1;
break;
}
* spc()))) {
continue;
}
found = -1;
break;
};
}
/*
* If we found trouble and we're running from a command file,
* quit before doing something we really regret.
*/
"Operation on disks being used for swapping must be interactive.\n");
}
return (found);
}
/*
* Determines if there are partitions that are a part of an SVM, VxVM, zpool
* volume or a live upgrade device, overlapping a given portion of a disk.
* Mounts and swap devices are checked in legacy format code.
*/
int
int check_label)
{
int error;
int found = 0;
int check = 0;
int i;
int bm_inuse = 0;
int part = 0;
char *usage;
char *name;
/*
* If the user does not want to do in use checking, return immediately.
* Normally, this is handled in libdiskmgt. For format, there is more
* processing required, so we want to bypass the in use checking
* here.
*/
if (NOINUSE_SET)
return (0);
/*
* Skip if it is not a real disk
*
* There could be two kinds of strings in cur_disk_path
* One starts with c?t?d?, while the other is a absolute path of a
* block device file.
*/
if (*cur_disk_path != 'c') {
&majornum);
return (0);
}
/*
* Truncate the characters following "d*", such as "s*" or "p*"
*/
if (name) {
name++;
}
*name = (char)0;
}
/*
* For format, we get basic 'in use' details from libdiskmgt. After
* that we must do the appropriate checking to see if the 'in use'
* details require a bit of additional work.
*/
if (error) {
/*
* If ENODEV, it actually means the device is not in use.
* We will return 0 without displaying error.
*/
err_print("Error occurred with device in use"
return (found);
}
}
return (found);
/*
* If we are checking the whole disk
* then any and all in use data is
* relevant.
*/
if (start == UINT_MAX64) {
err_print("Error occurred with device "
continue;
}
error) {
if (error != 0) {
err_print("Error occurred with "
"device in use checking: "
continue;
}
/*
* If this is a dump device, then it is
* a failure. You cannot format a slice
* that is a dedicated dump device.
*/
if (print) {
}
return (1);
}
/*
* We really found a device that is in use.
* Set 'found' for the return value, and set
* 'check' to indicate below that we must
* get the partition number to set bm_inuse
* in the event we are trying to label this
* device. check_label is set when we are
* checking modifications for in use slices
* on the device.
*/
found ++;
check = 1;
if (print) {
}
}
} else {
/*
* Before getting the in use data, verify that the
* current slice is within the range we are checking.
*/
if (error) {
err_print("Error occurred with device in use "
continue;
}
continue;
}
&slice_start);
&slice_size);
(end < slice_start)) {
continue;
}
err_print("Error occurred with device "
continue;
}
if (error != 0) {
err_print("Error occurred with "
"device in use checking: "
continue;
}
/*
* If this is a dump device, then it is
* a failure. You cannot format a slice
* that is a dedicated dump device.
*/
if (print) {
}
return (1);
}
/*
* We really found a device that is in use.
* Set 'found' for the return value, and set
* 'check' to indicate below that we must
* get the partition number to set bm_inuse
* in the event we are trying to label this
* device. check_label is set when we are
* checking modifications for in use slices
* on the device.
*/
found ++;
check = 1;
if (print) {
}
}
}
/*
* If check is set it means we found a slice(the current slice)
* on this device in use in some way. We potentially want
* to check this slice when labeling is
* requested. We set bm_inuse with this partition value
* for use later if check_label was set when called.
*/
if (check) {
err_print("Error occurred with device "
continue;
}
if (part != -1) {
}
check = 0;
}
/*
* If we have attributes then we have successfully
* found the slice we were looking for and we also
* know this means we are not searching the whole
* disk so break out of the loop
* now.
*/
if (attrs) {
break;
}
}
if (slices) {
}
/*
* The user is trying to label the disk. We have to do special
* checking here to ensure they are not trying to modify a slice
* that is in use in an incompatible way.
*/
if (check_label && bm_inuse) {
/*
* !0 indicates that we found a
* problem. In this case, we have overloaded
* the use of checkpartitions to work for
* in use devices. bm_inuse is representative
* of the slice that is in use, not that
* is mounted as is in the case of the normal
* use of checkpartitions.
*
* The call to checkpartitions will return !0 if
* we are trying to shrink a device that we have found
* to be in use above.
*/
return (checkpartitions(bm_inuse));
}
return (found);
}
/*
* This routine checks to see if there are mounted partitions overlapping
* a given portion of a disk. If the start parameter is < 0, it means
* that the entire disk should be checked.
*/
int
{
int found = 0;
int part;
/*
* If we are only checking part of the disk, the disk must
* have a partition map to check against. If it doesn't,
* we hope for the best.
*/
return (0);
/*
* Lock out interrupts because of the mntent protocol.
*/
/*
* Open the mount table.
*/
err_print("Unable to open mount table.\n");
fullabort();
}
/*
* Loop through the mount table until we run out of entries.
*/
continue;
/*
* It's a mount on the disk we're checking. If we are
* checking whole disk, then we found trouble. We can
* quit searching.
*/
if (start == UINT_MAX64) {
found = -1;
break;
}
/*
* If the partition overlaps the zone we're checking,
* then we found trouble. We can quit searching.
*/
continue;
}
found = -1;
break;
}
/*
* Close down the mount table.
*/
/*
* If we found trouble and we're running from a command file,
* quit before doing something we really regret.
*/
err_print("Operation on mounted disks must be interactive.\n");
}
/*
* Return the result.
*/
return (found);
}
int
{
int i;
int part;
int bm_swap = 0;
/*
* If we are only checking part of the disk, the disk must
* have a partition map to check against. If it doesn't,
* we hope for the best.
*/
return (0); /* Will be checked later */
/*
* Check for swap entries
*/
st = getswapentries();
/*
* if there are no swap entries return.
*/
return (0);
return (checkpartitions(bm_swap));
}
/*
* Check the new label with the existing label on the disk,
* to make sure that any mounted partitions are not being
* affected by writing the new label.
*/
int
{
int part;
int bm_mounted = 0;
/*
* If we are only checking part of the disk, the disk must
* have a partition map to check against. If it doesn't,
* we hope for the best.
*/
return (0); /* Will be checked later */
/*
* Lock out interrupts because of the mntent protocol.
*/
/*
* Open the mount table.
*/
err_print("Unable to open mount table.\n");
fullabort();
}
/*
* Loop through the mount table until we run out of entries.
*/
}
/*
* Close down the mount table.
*/
return (checkpartitions(bm_mounted));
}
/*
* This Routine checks if any partitions specified
* are affected by writing the new label
*/
static int
{
struct dk_map32 *n;
struct dk_map *o;
int i, found = 0;
/*
* Now we need to check that the current partition list and the
* previous partition list (which there must be if we actually
* have partitions mounted) overlap in any way on the mounted
* partitions
*/
/*
* Check if the user wants to online-label an
* existing EFI label.
*/
if (cur_label == L_TYPE_EFI) {
for (i = 0; i < EFI_NUMPAR; i++) {
if (bm_mounted & (1 << i)) {
== -1) {
err_print("Unable to get information "
"for EFI partition %d.\n", i);
return (-1);
}
/*
* Partition can grow or remain same.
*/
continue;
}
found = -1;
}
if (found)
break;
}
} else {
/*
* Get the "real" (on-disk) version of the partition table
*/
err_print("Unable to get current partition map.\n");
return (-1);
}
for (i = 0; i < NDKMAP; i++) {
if (bm_mounted & (1 << i)) {
/*
* This partition is mounted
*/
#ifdef DEBUG
"checkpartitions :checking partition '%c' \n", i + PARTITION_BASE);
#endif
/*
* If partition is identical, we're fine.
* If the partition grows, we're also fine,
* because the routines in partition.c check
* for overflow. It will (ultimately) be up
* to the routines in partition.c to warn
* about creation of overlapping partitions.
*/
#ifdef DEBUG
}
fmt_print("\n");
#endif
continue;
}
#ifdef DEBUG
fmt_print("- changes; old (%d,%d)->new "
#endif
found = -1;
}
if (found)
break;
}
}
/*
* If we found trouble and we're running from a command file,
* quit before doing something we really regret.
*/
err_print("Operation on mounted disks or \
disks currently being used for swapping must be interactive.\n");
}
/*
* Return the result.
*/
return (found);
}