2004-03-14 14:07:28

by Wilfried Weissmann

[permalink] [raw]
Subject: [ANNOUNCE] Highpoint-Tech Plugin 0.0.1 for EVMS 2.3.0

diff -Nurp evms-2.3.0/aclocal.m4 evms-2.3.0-bios/aclocal.m4
--- evms-2.3.0/aclocal.m4 2004-02-16 14:47:26.000000000 -0600
+++ evms-2.3.0-bios/aclocal.m4 2004-03-09 21:03:42.000000000 -0600
@@ -126,11 +126,16 @@ AC_ARG_ENABLE([rsct],
[Disable the RSCT plugin]),
[build_rsct="$enableval"],
[build_rsct="yes"])
+ AC_ARG_ENABLE([bios],
+ AC_HELP_STRING([--disable-bios],
+ [Disable the BIOS plugin]),
+ [build_bios="$enableval"],
+ [build_bios="yes"])

# Create the list of plugin directories to build. This is where each plugin
# can specify its dependencies.
plugin_dirs=""
-plugin_distdirs="bbr bbr_seg bsd csm disk dos drivelink ext2 gpt ha jfs lvm mac md multipath ogfs reiser replace rsct s390 snapshot swap xfs"
+plugin_distdirs="bbr bbr_seg bsd csm disk dos drivelink ext2 gpt ha jfs lvm mac md multipath ogfs reiser replace rsct s390 snapshot swap xfs bios"

# BBR
if test "$build_bbr" = "no"; then
@@ -340,6 +345,14 @@ else
AC_MSG_NOTICE([ building xfs])
fi

+# bios
+if test "$build_bios" = "no"; then
+ AC_MSG_NOTICE([ not building bios ... disabled by user])
+else
+ plugin_dirs="$plugin_dirs bios"
+ AC_MSG_NOTICE([ building bios])
+fi
+
AC_SUBST(plugin_dirs)
AC_SUBST(plugin_distdirs)
])
diff -Nurp evms-2.3.0/configure evms-2.3.0-bios/configure
--- evms-2.3.0/configure 2004-03-02 21:19:10.000000000 -0600
+++ evms-2.3.0-bios/configure 2004-03-14 14:38:15.000000000 -0600
@@ -865,6 +865,7 @@ Optional Features:
--disable-ogfs Disable the OpenGFS FSIM
--disable-reiser Disable the ReiserFS FSIM
--disable-xfs Disable the XFS FSIM
+ --disable-bios Disable the BIOS plugin
--disable-swap Disable the Swap FSIM
--disable-replace Disable the Replace plugin
--disable-ha Disable the HA plugin
@@ -10319,6 +10320,13 @@ if test "${enable_xfs+set}" = set; then
else
build_xfs="yes"
fi;
+# Check whether --enable-bios or --disable-bios was given.
+if test "${enable_bios+set}" = set; then
+ enableval="$enable_bios"
+ build_bios="$enableval"
+else
+ build_bios="yes"
+fi;
# Check whether --enable-swap or --disable-swap was given.
if test "${enable_swap+set}" = set; then
enableval="$enable_swap"
@@ -10351,7 +10359,7 @@ fi;
# Create the list of plugin directories to build. This is where each plugin
# can specify its dependencies.
plugin_dirs=""
-plugin_distdirs="bbr bbr_seg bsd csm disk dos drivelink ext2 gpt ha jfs lvm mac md multipath ogfs reiser replace rsct s390 snapshot swap xfs"
+plugin_distdirs="bbr bbr_seg bsd csm disk dos drivelink ext2 gpt ha jfs lvm mac md multipath ogfs reiser replace rsct s390 snapshot swap xfs bios"

# BBR
if test "$build_bbr" = "no"; then
@@ -10619,6 +10627,16 @@ else
echo "$as_me: building xfs" >&6;}
fi

+# BIOS
+if test "$build_bios" = "no"; then
+ { echo "$as_me:$LINENO: not building bios ... disabled by user" >&5
+echo "$as_me: not building bios ... disabled by user" >&6;}
+else
+ plugin_dirs="$plugin_dirs bios"
+ { echo "$as_me:$LINENO: building bios" >&5
+echo "$as_me: building bios" >&6;}
+fi
+



@@ -10724,7 +10742,7 @@ fi



- ac_config_files="$ac_config_files make.rules Makefile engine/Makefile engine/worker/Makefile plugins/Makefile plugins/bbr/Makefile plugins/bbr_seg/Makefile plugins/bsd/Makefile plugins/csm/Makefile plugins/disk/Makefile plugins/dos/Makefile plugins/drivelink/Makefile plugins/ext2/Makefile plugins/gpt/Makefile plugins/ha/Makefile plugins/jfs/Makefile plugins/lvm/Makefile plugins/mac/Makefile plugins/md/Makefile plugins/multipath/Makefile plugins/ogfs/Makefile plugins/reiser/Makefile plugins/replace/Makefile plugins/rsct/Makefile plugins/s390/Makefile plugins/snapshot/Makefile plugins/swap/Makefile plugins/xfs/Makefile ui/Makefile ui/cli/Makefile ui/gtk/Makefile ui/ncurses/Makefile ui/utils/Makefile include/Makefile doc/Makefile doc/man/Makefile tests/Makefile"
+ ac_config_files="$ac_config_files make.rules Makefile engine/Makefile engine/worker/Makefile plugins/Makefile plugins/bbr/Makefile plugins/bbr_seg/Makefile plugins/bsd/Makefile plugins/csm/Makefile plugins/disk/Makefile plugins/dos/Makefile plugins/drivelink/Makefile plugins/ext2/Makefile plugins/gpt/Makefile plugins/ha/Makefile plugins/jfs/Makefile plugins/lvm/Makefile plugins/mac/Makefile plugins/md/Makefile plugins/multipath/Makefile plugins/ogfs/Makefile plugins/reiser/Makefile plugins/replace/Makefile plugins/rsct/Makefile plugins/s390/Makefile plugins/snapshot/Makefile plugins/swap/Makefile plugins/xfs/Makefile plugins/bios/Makefile ui/Makefile ui/cli/Makefile ui/gtk/Makefile ui/ncurses/Makefile ui/utils/Makefile include/Makefile doc/Makefile doc/man/Makefile tests/Makefile"


cat >confcache <<\_ACEOF
@@ -11305,6 +11323,7 @@ do
"plugins/snapshot/Makefile" ) CONFIG_FILES="$CONFIG_FILES plugins/snapshot/Makefile" ;;
"plugins/swap/Makefile" ) CONFIG_FILES="$CONFIG_FILES plugins/swap/Makefile" ;;
"plugins/xfs/Makefile" ) CONFIG_FILES="$CONFIG_FILES plugins/xfs/Makefile" ;;
+ "plugins/bios/Makefile" ) CONFIG_FILES="$CONFIG_FILES plugins/bios/Makefile" ;;
"ui/Makefile" ) CONFIG_FILES="$CONFIG_FILES ui/Makefile" ;;
"ui/cli/Makefile" ) CONFIG_FILES="$CONFIG_FILES ui/cli/Makefile" ;;
"ui/gtk/Makefile" ) CONFIG_FILES="$CONFIG_FILES ui/gtk/Makefile" ;;
diff -Nurp evms-2.3.0/plugins/bios/Makefile.in evms-2.3.0-bios/plugins/bios/Makefile.in
--- evms-2.3.0/plugins/bios/Makefile.in 1969-12-31 18:00:00.000000000 -0600
+++ evms-2.3.0-bios/plugins/bios/Makefile.in 2004-03-14 14:38:15.000000000 -0600
@@ -0,0 +1,52 @@
+# Enterprise Volume Management System
+#
+# (C) Copyright IBM Corp. 2003
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+# the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+include @top_srcdir@/make.rules
+
+NAME = bios
+TARGET = $(PLUGIN_TARGET)
+
+MAJOR_VERSION = 0
+MINOR_VERSION = 0
+PATCH_LEVEL = 1
+
+EVMS_DEFS += -D_FILEOFFSET_BITS=64
+
+all: $(TARGET)
+
+$(TARGET): .depend .export $(OBJECTS)
+ $(BUILD_PLUGIN)
+
+install: all
+ $(MKINSTALLDIRS) $(DESTDIR)$(evmspluginsdir)
+ $(INSTALL) -m 755 $(TARGET) $(DESTDIR)$(evmspluginsdir)
+
+uninstall:
+ rm -f $(DESTDIR)$(evmspluginsdir)/$(TARGET)
+
+clean:
+ rm -f .depend .export $(OBJECTS) $(TARGET)
+
+distclean: clean
+ rm -f Makefile
+
+ifeq (.depend, $(wildcard .depend))
+include .depend
+endif
diff -Nurp evms-2.3.0/plugins/bios/bios.c evms-2.3.0-bios/plugins/bios/bios.c
--- evms-2.3.0/plugins/bios/bios.c 1969-12-31 18:00:00.000000000 -0600
+++ evms-2.3.0-bios/plugins/bios/bios.c 2004-03-14 14:38:15.000000000 -0600
@@ -0,0 +1,1323 @@
+/*
+ * (C) Copyright IBM Corp. 2001, 2003
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * BIOS Disk Manager plugin.
+ *
+ * Wilfried Weissmann (c) 2004
+ *
+ */
+
+#define _GNU_SOURCE
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <mntent.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <glob.h>
+
+#include <plugin.h>
+#include <ldm_dpc.h>
+#include "bios.h"
+
+ /* list of the pci ids of the supported controllers */
+struct hptpci_s {
+ u_int16_t vendor;
+ u_int16_t device;
+} static hptpci[] = {
+ { PCI_VENDOR_TRIONES, PCI_DEVICE_HPT370 },
+ { PCI_VENDOR_TRIONES, PCI_DEVICE_HPT372A },
+ { PCI_VENDOR_TRIONES, PCI_DEVICE_HPT302 },
+ { PCI_VENDOR_TRIONES, PCI_DEVICE_HPT371 },
+ { PCI_VENDOR_TRIONES, PCI_DEVICE_HPT374 },
+ { PCI_VENDOR_TRIONES, PCI_DEVICE_HPT372N },
+};
+
+static engine_functions_t * EngFncs = NULL;
+
+static char * sysfs_mount_point; /* FIXME: use sysfs */
+
+static list_anchor_t scanlist=NULL; /* list of disk attached to the hpt37x controller */
+
+static list_anchor_t raidlist=NULL; /* list of detected raid volumes */
+
+/**
+ * isHardDisk
+ * @hd: pathname of HD in proc filesystem
+ *
+ * returns true if the device is a hard disk
+ **/
+static int isHardDisk(const char *hd) {
+ char buffer[50];
+ FILE *fd;
+
+ strncpy(buffer, hd, sizeof(buffer) - 1);
+ strncat(buffer, "/media", sizeof(buffer) - 1);
+
+ fd=fopen(buffer, "r");
+
+ if( !fd ) {
+ return 0;
+ }
+
+ fgets(buffer, sizeof(buffer)-1, fd);
+
+ fclose(fd);
+
+ return strcmp(buffer, "disk\n")?0:1;
+}
+
+/**
+ * loadHPTConf
+ * @disk: disk structure of the harddisk
+ *
+ * loads the raid configuration data into the disk parameter structure
+ **/
+static int loadHPTConf(struct hptdisk * disk) {
+ struct stat stat;
+ int fd=open(disk->devname, O_RDONLY);
+
+ if(fd < 0) {
+ return 0; /* cannot open disk */
+ }
+
+ if(fstat(fd, &stat) == -1) goto err;
+
+ disk->minor=minor(stat.st_rdev);
+ disk->major=major(stat.st_rdev);
+
+ if(ioctl(fd, BLKSSZGET, &(disk->hardsector_size)) == -1) goto err;
+
+ if(ioctl(fd, BLKBSZGET, &(disk->block_size)) == -1) goto err;
+
+ if(lseek(fd, CONFIGOFFSET, SEEK_SET) == -1) goto err;
+
+ if(read(fd, (void *) &disk->superblock, sizeof(struct highpoint_raid_conf)) !=
+ sizeof(struct highpoint_raid_conf)) goto err;
+
+ close(fd);
+ return 1;
+
+err:
+ close(fd);
+ return 0;
+}
+
+static int compare_disk(void *disk1, void *disk2) {
+ return strcmp( ( (struct hptdisk *) disk1 )->devname,
+ ( (struct hptdisk *) disk2 )->devname);
+}
+
+/**
+ * addDisk
+ * @name: device node of the harddisk (without heading "/dev/")
+ *
+ * allocates the disk structure and load the raid configuration data.
+ * if the disk is already in the scanlist then it is discarded.
+ **/
+static void addDisk(const char *name) {
+
+ struct hptdisk * disk=EngFncs->engine_alloc(sizeof(struct hptdisk));
+
+ if(!disk) {
+ return; /* Oops: out of memory! */
+ }
+
+ memset(disk, 0, sizeof(struct hptdisk));
+
+ strcpy(disk->devname, "/dev/");
+ strcat(disk->devname, name);
+
+ if(loadHPTConf(disk) && disk->superblock.magic == 0x5a7816f0 &&
+ !EngFncs->find_in_list(scanlist, disk, compare_disk) ) {
+ EngFncs->insert_thing(scanlist, disk, INSERT_AFTER, NULL);
+ } else {
+ EngFncs->engine_free(disk); /* no config block => remove */
+ }
+}
+
+/**
+ * hpt370xScan
+ * @name: path to the controller directory in proc-fs
+ * @vendor: pci vendor id of the ide controller
+ * @device: pci device id of the ide controller
+ *
+ * scans the attached harddisks of the ide controller
+ **/
+static void hpt37xScan(const char *name, int vendor, int device) {
+ DIR *ctrldir;
+ struct dirent *dir;
+ char buffer[50]=IDEDIR "/";
+ char hdpath[50];
+ boolean ignorepciids;
+ int i;
+
+ /* default is to NOT ignore the PCI IDs */
+ if(EngFncs->get_config_bool(IGNORE_PCI_IDS, &ignorepciids) || !ignorepciids) {
+
+ for(i=0; i < sizeof(hptpci)/sizeof(struct hptpci_s); i++) {
+ if(hptpci[i].vendor == vendor &&
+ hptpci[i].device == device) {
+ break;
+ }
+ }
+
+ if (i >= sizeof(hptpci)/sizeof(struct hptpci_s)) return;
+
+ }
+
+ strncat(buffer, name, sizeof(buffer) - 1);
+
+ ctrldir=opendir(buffer);
+
+ if( !ctrldir ) {
+ perror(buffer);
+ return;
+ }
+
+ while( (dir = readdir(ctrldir)) ) {
+ if( (dir->d_type == DT_DIR) &&
+ !(strncmp(dir->d_name, "hd", 2)) ) {
+
+ strncpy(hdpath, buffer, sizeof(buffer) - 1);
+ strncat(hdpath, "/", sizeof(buffer) - 1);
+ strncat(hdpath, dir->d_name, sizeof(buffer) - 1);
+
+ if(isHardDisk(hdpath)) {
+ addDisk(dir->d_name);
+ }
+ }
+ }
+
+
+ closedir(ctrldir);
+}
+
+/**
+ * findIDECtrl
+ *
+ * scan for supported IDE controllers and datafill the scanlist with
+ * the attached harddisks
+ **/
+static int findIDECtrl() {
+ DIR *idedir;
+ struct dirent * dir;
+
+ idedir = opendir( IDEDIR );
+
+ if( ! idedir ) {
+ perror(IDEDIR);
+ return -1;
+ }
+
+ while( (dir = readdir(idedir)) ) {
+ if( (dir->d_type == DT_DIR) &&
+ !(strncmp(dir->d_name, "ide", 3)) ) {
+
+ char config[50]=IDEDIR "/";
+ FILE *fd;
+ int vendor, device;
+
+ strncat(config, dir->d_name, sizeof(config)-1);
+ strncat(config, "/config", sizeof(config)-1);
+
+ fd=fopen(config, "r");
+
+ if( !fd ) {
+ perror(config);
+ continue;
+ }
+
+ if( fscanf(fd, "pci bus %*i device %*i vendor %x device %x",
+ &vendor, &device) == 2) {
+
+ hpt37xScan(dir->d_name, vendor, device);
+ }
+
+ fclose(fd);
+ }
+ }
+
+ closedir(idedir);
+ return 0;
+}
+
+/**
+ * round_down
+ * @value: Value (in sectors) to be rounded down.
+ * @boundary: Boundary (in bytes) to round-down to.
+ *
+ * Given a value, round it down to be a multiple of the specified boundary size.
+ **/
+static inline sector_count_t round_down(sector_count_t value,
+ u_int32_t boundary)
+{
+ sector_count_t boundary_in_vsectors = ((sector_count_t)boundary) >>
+ EVMS_VSECTOR_SIZE_SHIFT;
+ return (boundary > EVMS_VSECTOR_SIZE) ?
+ (value & ~(boundary_in_vsectors - 1)) : value;
+}
+
+/**
+ * round_up
+ * @value: Value (in sectors) to be rounded up.
+ * @boundary: Boundary (in bytes) to round-up to.
+ *
+ * Given a value, round it up to be a multiple of the specified boundary size.
+ **/
+static inline sector_count_t round_up(sector_count_t value,
+ u_int32_t boundary)
+{
+ sector_count_t boundary_in_vsectors = ((sector_count_t)boundary) >>
+ EVMS_VSECTOR_SIZE_SHIFT;
+ sector_count_t temp_value = value + boundary_in_vsectors - 1;
+ return (boundary > EVMS_VSECTOR_SIZE) ?
+ (temp_value & ~(boundary_in_vsectors - 1)) : value;
+}
+
+/**
+ * where_is_sysfs
+ *
+ * Is sysfs mounted. If so, return the mount point. The caller must free the
+ * returned string.
+ **/
+static boolean where_is_sysfs(char ** mount_name)
+{
+ boolean result = FALSE;
+ FILE * mount_records;
+ struct mntent * mount_entry;
+
+ LOG_ENTRY();
+
+ if (mount_name) {
+ *mount_name = NULL;
+ }
+
+ mount_records = setmntent(MOUNTED, "r");
+ if (mount_records == NULL) {
+ mount_records = setmntent("/proc/mounts", "r");
+ }
+ if (mount_records == NULL) {
+ LOG_ERROR("Could not get list of mounted devices.\n");
+ goto out;
+ }
+
+ while (!result && (mount_entry = getmntent(mount_records)) != NULL) {
+ if (strcmp(mount_entry->mnt_type, "sysfs") == 0) {
+ result = TRUE;
+ if (mount_name) {
+ *mount_name = strdup(mount_entry->mnt_dir);
+ }
+ }
+ }
+
+ endmntent(mount_records);
+
+out:
+ LOG_EXIT_BOOL(result);
+ return result;
+}
+
+static int LD_setup(engine_functions_t * engine_function_table)
+{
+ /* save info we get from the engine */
+ EngFncs = engine_function_table;
+
+ LOG_ENTRY();
+
+ where_is_sysfs(&sysfs_mount_point);
+ scanlist=EngFncs->allocate_list();
+ raidlist=EngFncs->allocate_list();
+
+ LOG_EXIT_INT(0);
+ return 0;
+}
+
+/**
+ * open_dev
+ *
+ * Open the specified disk. Use O_DIRECT to avoid caching. Use O_SYNC in case
+ * the kernel does not honor O_DIRECT. Use the Engine's service so we
+ * automatically get a dev-node in the /dev/evms/.nodes/ tree. Record the
+ * file handle in the disk's private data.
+ **/
+static int open_dev(storage_object_t * disk)
+{
+ int rc = 0;
+ int * fd = &((struct hptraid *)disk->private_data)->fd;
+
+ LOG_ENTRY();
+
+ if (*fd <= 0) {
+ *fd = EngFncs->open_object(disk, O_RDWR | O_DIRECT | O_SYNC);
+ if (*fd < 0) {
+ rc = -*fd;
+ LOG_DEBUG("Error opening disk %s: %d: %s\n",
+ disk->name, rc, strerror(rc));
+ }
+ }
+
+ LOG_EXIT_INT(rc);
+ return rc;
+}
+
+/**
+ * close_dev
+ *
+ * Close the disk and clear the file handle.
+ **/
+static void close_dev(storage_object_t * disk)
+{
+ int * fd = &((struct hptraid *)disk->private_data)->fd;
+ int rc;
+
+ LOG_ENTRY();
+
+ if (*fd >= 0) {
+ rc = EngFncs->close_object(disk, *fd);
+ if (!rc) {
+ *fd = -1;
+ }
+ }
+
+ LOG_EXIT_VOID();
+}
+
+/**
+ * LD_cleanup
+ *
+ * Find any disks and close the device that was opended during discovery.
+ **/
+static void LD_cleanup(void)
+{
+ int rc;
+ list_anchor_t disk_list;
+ list_element_t disk_list_itr;
+ storage_object_t * disk;
+ struct hptraid * raid;
+
+ LOG_ENTRY();
+
+ /* Get a list of disks that are managed by this plug-in. */
+ rc = EngFncs->get_object_list(DISK, 0, my_plugin_record,
+ NULL, 0, &disk_list);
+ if (!rc) {
+ /* Close any dev handles that might be open. */
+ LIST_FOR_EACH(disk_list, disk_list_itr, disk) {
+ raid = (struct hptraid *)disk->private_data;
+ if(raid->status == operational) {
+ EngFncs->dm_deactivate(disk);
+ EngFncs->dm_deallocate_targets(raid->dm_target);
+ close_dev(disk);
+ }
+ EngFncs->engine_free(disk->private_data);
+ }
+ EngFncs->destroy_list(disk_list);
+ }
+
+ EngFncs->destroy_list(raidlist);
+ EngFncs->destroy_list(scanlist);
+
+ if (sysfs_mount_point) {
+ free(sysfs_mount_point);
+ sysfs_mount_point = NULL;
+ }
+
+ LOG_EXIT_VOID();
+}
+
+/**
+ * get_block_size
+ *
+ * Use the BLKBSZGET ioctl to get the block-size for the specified disk.
+ **/
+static int get_block_size(storage_object_t * disk)
+{
+ int fd = ((struct hptraid *)disk->private_data)->fd;
+ int rc, block_size;
+
+ LOG_ENTRY();
+
+ rc = ioctl(fd, BLKBSZGET, &block_size);
+ if (rc) {
+ rc = errno;
+ LOG_ERROR("Error getting block size for disk %s: %d: %s.\n",
+ disk->name, rc, strerror(rc));
+ } else {
+ LOG_DEBUG("Disk %s has block-size %d.\n",
+ disk->name, block_size);
+ disk->geometry.block_size = block_size;
+ }
+
+ LOG_EXIT_INT(rc);
+ return rc;
+}
+
+/**
+ * set_block_size
+ *
+ * Use the BLKBSZSET ioctl to set the disk's block-size.
+ **/
+static int set_block_size(storage_object_t * disk, int block_size)
+{
+ int rc;
+ int fd = ((struct hptraid *)disk->private_data)->fd;
+
+ LOG_ENTRY();
+
+ rc = ioctl(fd, BLKBSZSET, &block_size);
+ if (rc) {
+ rc = errno;
+ LOG_ERROR("Error setting block size (%d) for disk %s: %d: "
+ "%s.\n", block_size, disk->name, rc, strerror(rc));
+ } else {
+ LOG_DEBUG("Setting disk %s block-size to %d.\n",
+ disk->name, block_size);
+ disk->geometry.block_size = block_size;
+ }
+
+ LOG_EXIT_INT(rc);
+ return rc;
+}
+
+/**
+ * create_logical_disk
+ *
+ * Allocate a new disk and initialize all fields.
+ **/
+static storage_object_t * create_logical_disk(struct hptraid * raid)
+{
+ storage_object_t * disk = NULL;
+ int rc;
+
+ LOG_ENTRY();
+
+ rc = EngFncs->allocate_logical_disk(raid->name, &disk);
+ if (rc) {
+ LOG_SERIOUS("Error allocating new disk object for disk %s: %d: "
+ "%s.\n", raid->name, rc, EngFncs->strerror(rc));
+ goto out;
+ }
+
+ disk->data_type = DATA_TYPE;
+ disk->private_data = raid;
+ disk->plugin = my_plugin_record;
+ disk->size=raid->sectors;
+ disk->geometry.cylinders=raid->sectors / ( 255 * 63 );
+ disk->geometry.heads=255;
+ disk->geometry.sectors_per_track=63;
+ disk->geometry.block_size=raid->block_size;
+ disk->geometry.bytes_per_sector=raid->hardsector_size;
+
+out:
+ LOG_EXIT_PTR(disk);
+ return disk;
+}
+
+/**
+ * hptRAIDScan
+ * @index: index number of the raid volume
+ *
+ * scans the "scanlist" of harddisks to detect hpt-raid volumes. return the
+ * allocated and datafilled hptraid structure and adds it to the raidlist.
+ * when no more volumes were found then NULL is returned. this function also
+ * detects "non-operatinal" volumes (e.g.: volumes with too less disks to
+ * become active).
+ **/
+static struct hptraid * hptRAIDScan(int index) {
+ struct hptdisk * current;
+ list_element_t disk_list_itr;
+ struct hptraid * raid=EngFncs->engine_alloc(sizeof(struct hptraid));
+
+ if(!raid) {
+ return NULL;
+ }
+
+ memset(raid, 0, sizeof(struct hptraid));
+
+ sprintf(raid->name, "hptraid%ip", index);
+
+ /* walk the scanlist of attached harddisks */
+ LIST_FOR_EACH(scanlist, disk_list_itr, current) {
+
+ if(current->claimed) continue;
+
+ /* unclaimed disk => scan */
+
+ if(raid->disks) {
+ /* raid is not empty => check magic cookie */
+ if(raid->magic_0 != current->superblock.magic_0) {
+ continue;
+ }
+ }
+ else {
+ /* raid is empty => accept any magic cookie */
+ raid->magic_0 = current->superblock.magic_0;
+ }
+
+ /* check for known raid types */
+ switch(current->superblock.type) {
+ case HPT_T_RAID_0:
+ break;
+ default:
+ continue;
+ }
+
+ if(current->superblock.disk_number > 8) {
+ continue;
+ }
+
+ /* add disk to raid volume */
+ raid->disk[current->superblock.disk_number]=current;
+ /* shift in sectors */
+ raid->stride=1<<current->superblock.raid0_shift;
+ raid->disks=current->superblock.raid_disks;
+ /* superblock contains size in sectors - 1 */
+ raid->sectors=current->superblock.total_secs;
+ raid->magic_1 = current->superblock.magic_1;
+ raid->hardsector_size=current->hardsector_size;
+ raid->block_size=current->block_size;
+
+ /*
+ * FIXME: re-enable to access the last sector
+ *
+ * the device mapper is only happy if
+ * (volume size)%(number of disks) == 0
+ *
+ * maybe we can lie to the device mapper and tell it
+ * that the volume is bigger so that the expression from above
+ * is true. then use the true values for the evms engine to get
+ * the correct volume sizes.
+ */
+#if 0
+ if (EngFncs->is_2_4_kernel()) {
+ /* round down to 1024 bytes boundary */
+#endif
+ raid->sectors += raid->sectors&1?1:0;
+#if 0
+ }
+ else {
+ raid->sectors++;
+ }
+#endif
+
+ current->claimed=1;
+ }
+
+ if(raid->disks == 0) {
+ EngFncs->engine_free(raid);
+ return NULL;
+ }
+
+ EngFncs->insert_thing(raidlist, raid, INSERT_AFTER, NULL);
+
+ return raid;
+}
+
+/**
+ * hptRAIDInit
+ * @raid: raid volume to be activated
+ * @output_list: output list for LD_discover()
+ *
+ * activate the raid volume and add is the the volume output_list
+ **/
+static int hptRAIDInit(struct hptraid * raid, list_anchor_t output_list) {
+ int disks=0, count;
+ storage_object_t * object;
+
+ /* raid is already running */
+ if(raid->status == operational) {
+ return 0;
+ }
+
+ for(count=0; count < 8; count++) {
+ if(raid->disk[count]) {
+ disks++;
+ }
+ }
+
+ if(raid->disks != disks) { /* missing disks */
+ LOG_SERIOUS("Missing disks in %s (%i of %i).\n", raid->name, disks, raid->disks);
+ goto err;
+ }
+
+ /* datafill device mapper structures */
+ raid->dm_target = EngFncs->dm_allocate_target(DM_TARGET_STRIPE, 0,
+ raid->sectors, raid->disks, 0);
+
+ raid->dm_target->data.stripe->chunk_size=raid->stride;
+ raid->dm_target->data.stripe->num_stripes=raid->disks;
+ for(count=0; count < raid->disks; count++) {
+ struct dm_device * dm_device=raid->dm_target->data.stripe->devices+count;
+ struct hptdisk * hptdisk=raid->disk[count];
+ dm_device->major=hptdisk->major;
+ dm_device->minor=hptdisk->minor;
+ dm_device->start=count?10:0;
+ }
+
+ object=create_logical_disk(raid);
+ if(!object) {
+ LOG_SERIOUS("Failed to create %s.\n", raid->name);
+ goto err1;
+ }
+
+ if( EngFncs->dm_activate(object, raid->dm_target) ) {
+ LOG_SERIOUS("Failed to activate %s.\n", object->name);
+ goto err2;
+ }
+
+ LOG_DETAILS("New Logical Disk:\n");
+ LOG_DETAILS(" name: %s\n", object->name);
+ LOG_DETAILS(" size: %"PRIu64"\n", object->size);
+ LOG_DETAILS(" device-number: %x:%x\n", object->dev_major, object->dev_minor);
+ LOG_DETAILS(" geometry:\n");
+ LOG_DETAILS(" cylinders: %"PRIu64"\n", object->geometry.cylinders);
+ LOG_DETAILS(" heads: %d\n", object->geometry.heads);
+ LOG_DETAILS(" sectors: %d\n", object->geometry.sectors_per_track);
+ LOG_DETAILS(" sector size: %d (bytes)\n", object->geometry.bytes_per_sector);
+ LOG_DETAILS(" block size: %"PRIu64" (bytes)\n", object->geometry.block_size);
+
+ open_dev(object);
+
+ /* Insert the new disk into ouput list. */
+ if( ! EngFncs->insert_thing(output_list, object,
+ INSERT_AFTER, NULL) ) {
+ LOG_SERIOUS("Error adding new disk %s to output list. "
+ "Deleting the disk.\n", object->name);
+ close_dev(object);
+ EngFncs->engine_free(object->private_data);
+ EngFncs->free_logical_disk(object);
+ goto err2;
+ }
+
+ raid->status=operational;
+ return 1;
+
+err2:
+ EngFncs->free_logical_disk(object);
+err1:
+ EngFncs->dm_deallocate_targets(raid->dm_target);
+err:
+ raid->status=broken;
+ return 0;
+}
+
+/**
+ * LD_discover
+ **/
+static int LD_discover(list_anchor_t input_list,
+ list_anchor_t output_list,
+ boolean final_call)
+{
+ int i;
+ struct hptraid * raid;
+
+ LOG_ENTRY();
+
+ findIDECtrl(); /* get list of scan devices */
+
+ for(i=0; (raid=hptRAIDScan(i)); i++) {
+ hptRAIDInit(raid, output_list);
+ }
+
+ i = EngFncs->list_count(output_list);
+ LOG_DEBUG("Discovered %d disks.\n", i);
+ LOG_EXIT_INT(0);
+ return 0;
+}
+
+/**
+ * get_alignment_size
+ *
+ * Return the size (in bytes) of the alignment restrictions for O_DIRECT. On
+ * 2.5 kernels, this will be the disk's hard-sector-size. On 2.4 kernels, this
+ * will be the disk's block-size. Since block-size can change at run-time,
+ * always check the current block-size. Also, since we want access to as much
+ * of the disk as possible, try to set the block-size to 1k if it isn't
+ * already.
+ **/
+static int get_alignment_size(storage_object_t * disk)
+{
+ int size;
+ int min_block_size = max(disk->geometry.bytes_per_sector, 1024);
+
+ LOG_ENTRY();
+
+ if (EngFncs->is_2_4_kernel()) {
+ get_block_size(disk);
+ size = disk->geometry.block_size;
+ if (size > min_block_size) {
+ set_block_size(disk, min_block_size);
+ size = disk->geometry.block_size;
+ }
+ } else {
+ size = disk->geometry.bytes_per_sector;
+ }
+
+ LOG_EXIT_INT(size);
+ return size;
+}
+
+/**
+ * get_aligned_buffer
+ * @offset: Starting offset (in sectors) of engine I/O request.
+ * @count: Size (in sectors) of engine I/O request.
+ * @align_size: Size (in bytes) that the I/O must be aligned on.
+ * @local_offset: Aligned starting offset (in sectors).
+ * @local_count: Aligned I/O size (in sectors).
+ * @local_buffer: New data buffer. Not aligned, but need to return this
+ * pointer so it can be freed after using.
+ * @local_buffer_aligned: Aligned data buffer. This points somewhere
+ * within local_buffer.
+ *
+ * To use O_DIRECT, the buffer passed to read() or write() must be aligned on
+ * the device's block/sector size. The size and starting offset of the I/O must
+ * also be a multiple of the block/sector size.
+ **/
+static int get_aligned_buffer(lsn_t offset,
+ sector_count_t count,
+ int align_size,
+ lsn_t * local_offset,
+ sector_count_t * local_count,
+ void ** local_buffer,
+ void ** local_buffer_aligned)
+{
+ u_int32_t offset_diff, offset_diff_bytes;
+ u_int32_t local_buffer_bytes;
+ u_int32_t alignment_base, alignment_diff;
+ int rc = 0;
+
+ LOG_ENTRY();
+
+ /* Round down starting offset to the alignment size. */
+ *local_offset = round_down(offset, align_size);
+
+ /* Difference between real offset and local offset. */
+ offset_diff = offset - *local_offset;
+ offset_diff_bytes = offset_diff << EVMS_VSECTOR_SIZE_SHIFT;
+
+ /* Round up total count of sectors to alignment size. */
+ *local_count = round_up(count + offset_diff, align_size);
+
+ /* Allocate the buffer that will actually perform the I/O. This needs
+ * to allocate enough extra to compensate for the alignment that will
+ * occur next.
+ */
+ local_buffer_bytes = *local_count << EVMS_VSECTOR_SIZE_SHIFT;
+ *local_buffer = EngFncs->engine_alloc(local_buffer_bytes +
+ align_size - 1);
+ if (!*local_buffer) {
+ rc = ENOMEM;
+ goto out;
+ }
+
+ /* Align the buffer on hard-sector-size. */
+ alignment_base = (unsigned long)(*local_buffer) & (align_size - 1);
+ alignment_diff = (alignment_base + align_size - 1) & ~(align_size - 1);
+ alignment_diff -= alignment_base;
+ *local_buffer_aligned = *local_buffer + alignment_diff;
+
+ /* Sanity check */
+ if (((unsigned long)(*local_buffer_aligned) % align_size) != 0) {
+ LOG_ERROR("BUFFER NOT ALIGNED!!: buf: %p, size: %u\n",
+ *local_buffer_aligned, align_size);
+ }
+
+out:
+ LOG_EXIT_INT(rc);
+ return rc;
+}
+
+/**
+ * LD_read
+ **/
+static int LD_read(storage_object_t * disk,
+ lsn_t offset,
+ sector_count_t count,
+ void * buffer)
+{
+ void * local_buffer = NULL, * local_buffer_aligned;
+ lsn_t local_offset;
+ sector_count_t local_count;
+ int fd = ((struct hptraid *)disk->private_data)->fd;
+ int rc, align_size;
+
+ LOG_ENTRY();
+ LOG_DEBUG("Read disk:%s offset:%"PRIu64" count:%"PRIu64"\n",
+ disk->name, offset, count);
+
+ if (offset + count > disk->size) {
+ LOG_ERROR("Read request past end of disk.\n");
+ rc = EINVAL;
+ goto out;
+ }
+
+ /* Make sure the disk is open. */
+ rc = open_dev(disk);
+ if (rc) {
+ goto out;
+ }
+
+ /* Get the alignment restriction for O_DIRECT. */
+ align_size = get_alignment_size(disk);
+
+ /* Get a data buffer aligned with this restriction. */
+ rc = get_aligned_buffer(offset, count, align_size,
+ &local_offset, &local_count,
+ &local_buffer, &local_buffer_aligned);
+ if (rc) {
+ goto out;
+ }
+
+ /* Send the read to the engine. */
+ rc = EngFncs->read_object(disk, fd, local_buffer_aligned,
+ local_count << EVMS_VSECTOR_SIZE_SHIFT,
+ local_offset << EVMS_VSECTOR_SIZE_SHIFT);
+ if (rc < 0) {
+ rc = -rc;
+ goto out;
+ }
+
+ /* Copy the data back to the caller's buffer. */
+ memcpy(buffer, local_buffer_aligned +
+ ((offset - local_offset) << EVMS_VSECTOR_SIZE_SHIFT),
+ count << EVMS_VSECTOR_SIZE_SHIFT);
+
+ rc = 0;
+
+out:
+ EngFncs->engine_free(local_buffer);
+ LOG_EXIT_INT(rc);
+ return rc;
+}
+
+/**
+ * LD_write
+ **/
+static int LD_write(storage_object_t * disk,
+ lsn_t offset,
+ sector_count_t count,
+ void * buffer)
+{
+ void * local_buffer = NULL, * local_buffer_aligned;
+ lsn_t local_offset;
+ sector_count_t local_count;
+ int fd = ((struct hptraid *)disk->private_data)->fd;
+ int rc, align_size;
+
+ LOG_ENTRY();
+ LOG_DEBUG("Write disk:%s offset:%"PRIu64" count:%"PRIu64"\n",
+ disk->name, offset, count);
+
+ if (offset + count > disk->size) {
+ LOG_ERROR("Write request past end of disk.\n");
+ rc = EINVAL;
+ goto out;
+ }
+
+ /* Make sure the disk is open. */
+ rc = open_dev(disk);
+ if (rc) {
+ goto out;
+ }
+
+ /* Get the alignment restriction for O_DIRECT. */
+ align_size = get_alignment_size(disk);
+
+ /* Get a data buffer aligned with this restriction. */
+ rc = get_aligned_buffer(offset, count, align_size,
+ &local_offset, &local_count,
+ &local_buffer, &local_buffer_aligned);
+ if (rc) {
+ goto out;
+ }
+
+ if (local_count != count) {
+ rc = EngFncs->read_object(disk, fd, local_buffer_aligned,
+ local_count << EVMS_VSECTOR_SIZE_SHIFT,
+ local_offset << EVMS_VSECTOR_SIZE_SHIFT);
+ if (rc < 0) {
+ rc = -rc;
+ goto out;
+ }
+ }
+
+ /* Put user data at the right place in the buffer */
+ memcpy(local_buffer_aligned +
+ ((offset - local_offset) << EVMS_VSECTOR_SIZE_SHIFT),
+ buffer, count << EVMS_VSECTOR_SIZE_SHIFT);
+
+ /* Send the write to the engine. */
+ rc = EngFncs->write_object(disk, fd, local_buffer_aligned,
+ local_count << EVMS_VSECTOR_SIZE_SHIFT,
+ local_offset << EVMS_VSECTOR_SIZE_SHIFT);
+ if (rc < 0) {
+ rc = -rc;
+ goto out;
+ }
+
+ rc = 0;
+
+out:
+ EngFncs->engine_free(local_buffer);
+ LOG_EXIT_INT(rc);
+ return rc;
+}
+
+/**
+ * LD_discard
+ *
+ * We don't expect to get called on this API. Just like commit.
+ **/
+static int LD_discard(list_anchor_t disks)
+{
+ LOG_ENTRY();
+ LOG_EXIT_INT(0);
+ return 0;
+}
+
+/**
+ * LD_add_sectors_to_kill_list
+ **/
+static int LD_add_sectors_to_kill_list(storage_object_t * disk,
+ lsn_t lsn,
+ sector_count_t count)
+{
+ int rc;
+ LOG_ENTRY();
+
+ if (lsn + count > disk->size) {
+ LOG_ERROR("Kill-sectors request past end of disk %s.\n",
+ disk->name);
+ rc = EINVAL;
+ } else {
+ rc = EngFncs->add_sectors_to_kill_list(disk, lsn, count);
+ }
+
+ LOG_EXIT_INT(rc);
+ return rc;
+}
+
+/**
+ * LD_commit_changes
+ *
+ * Disk manager doesn't do anything during commit. Just return success.
+ **/
+static int LD_commit_changes(storage_object_t * disk, commit_phase_t phase)
+{
+ LOG_ENTRY();
+ LOG_EXIT_INT(0);
+ return 0;
+}
+
+/**
+ * LD_get_info
+ *
+ * Returns DISK specific information
+ **/
+static int LD_get_info(storage_object_t * disk,
+ char * descriptor_name,
+ extended_info_array_t ** info)
+{
+ extended_info_array_t * Info;
+ int index = 0, rc = EINVAL;
+
+ LOG_ENTRY();
+
+ if (!info) {
+ goto out;
+ }
+ *info = NULL;
+
+ if (descriptor_name) {
+ goto out;
+ }
+
+ Info = EngFncs->engine_alloc(sizeof(extended_info_array_t) +
+ 8 * sizeof(extended_info_t));
+ if (!Info) {
+ rc = ENOMEM;
+ goto out;
+ }
+
+ SET_STRING(Info->info[index].name, "Name");
+ SET_STRING(Info->info[index].title, "Name");
+ SET_STRING(Info->info[index].desc, "EVMS name for the DISK storage object");
+ Info->info[index].type = EVMS_Type_String;
+ SET_STRING(Info->info[index].value.s, disk->name);
+ index++;
+
+ SET_STRING(Info->info[index].name, "Size");
+ SET_STRING(Info->info[index].title, "Size");
+ SET_STRING(Info->info[index].desc, "Size of the disk in sectors");
+ Info->info[index].type = EVMS_Type_Unsigned_Int64;
+ Info->info[index].unit = EVMS_Unit_Sectors;
+ Info->info[index].flags |= EVMS_EINFO_FLAGS_NO_UNIT_CONVERSION;
+ Info->info[index].value.ui64 = disk->size;
+ index++;
+
+ SET_STRING(Info->info[index].name, "Cyl");
+ SET_STRING(Info->info[index].title, "Cylinders");
+ SET_STRING(Info->info[index].desc, "Drive geometry -- number of cylinders");
+ Info->info[index].type = EVMS_Type_Unsigned_Int64;
+ Info->info[index].value.ui64 = disk->geometry.cylinders;
+ index++;
+
+ SET_STRING(Info->info[index].name, "Heads");
+ SET_STRING(Info->info[index].title, "Heads");
+ SET_STRING(Info->info[index].desc, "Drive geometry -- number of heads");
+ Info->info[index].type = EVMS_Type_Unsigned_Int32;
+ Info->info[index].value.ui32 = disk->geometry.heads;
+ index++;
+
+ SET_STRING(Info->info[index].name, "Sectors");
+ SET_STRING(Info->info[index].title, "Sectors");
+ SET_STRING(Info->info[index].desc, "Drive geometry -- sectors per track");
+ Info->info[index].type = EVMS_Type_Unsigned_Int32;
+ Info->info[index].value.ui32 = disk->geometry.sectors_per_track;
+ index++;
+
+ SET_STRING(Info->info[index].name, "SectorSize");
+ SET_STRING(Info->info[index].title, "Sector Size");
+ SET_STRING(Info->info[index].desc, "Number of bytes per sector");
+ Info->info[index].type = EVMS_Type_Unsigned_Int32;
+ Info->info[index].unit = EVMS_Unit_Bytes;
+ Info->info[index].value.ui32 = disk->geometry.bytes_per_sector;
+ index++;
+
+ SET_STRING(Info->info[index].name, "BlockSize");
+ SET_STRING(Info->info[index].title, "Block Size");
+ SET_STRING(Info->info[index].desc, "Number of bytes per block");
+ Info->info[index].type = EVMS_Type_Unsigned_Int64;
+ Info->info[index].unit = EVMS_Unit_Bytes;
+ Info->info[index].value.ui64 = disk->geometry.block_size;
+ index++;
+
+ SET_STRING(Info->info[index].name, "BootLimit");
+ SET_STRING(Info->info[index].title, "Boot Cylinder Limit");
+ SET_STRING(Info->info[index].desc, "LBA of the first sector above the boot cylinder limit for this drive");
+ Info->info[index].type = EVMS_Type_Unsigned_Int64;
+ Info->info[index].value.ui64 = disk->geometry.boot_cylinder_limit;
+ index++;
+
+ SET_STRING(Info->info[index].name, "Segments");
+ SET_STRING(Info->info[index].title, "Segments");
+ SET_STRING(Info->info[index].desc, "Number of segments discovered on the drive (metadata, data, freespace)");
+ Info->info[index].type = EVMS_Type_Unsigned_Int32;
+ Info->info[index].value.ui32 = EngFncs->list_count(disk->parent_objects);
+ index++;
+
+ Info->count = index;
+ *info = Info;
+ rc = 0;
+
+out:
+ LOG_EXIT_INT(rc);
+ return rc;
+}
+
+/**
+ * LD_get_plugin_info
+ *
+ * Returns plug-in specific information
+ **/
+static int LD_get_plugin_info(char * descriptor_name,
+ extended_info_array_t ** info)
+{
+ int rc = EINVAL;
+ extended_info_array_t * Info;
+ char version_string[64];
+ char required_engine_api_version_string[64];
+ char required_plugin_api_version_string[64];
+
+ LOG_ENTRY();
+
+ if (!info) {
+ goto out;
+ }
+ *info = NULL;
+
+ if (descriptor_name) {
+ goto out;
+ }
+
+ Info = EngFncs->engine_alloc(sizeof(extended_info_array_t) +
+ 6 * sizeof(extended_info_t));
+ if (!Info) {
+ rc = ENOMEM;
+ goto out;
+ }
+
+ Info->count = 6;
+
+ sprintf(version_string, "%d.%d.%d",
+ MAJOR_VERSION, MINOR_VERSION, PATCH_LEVEL);
+
+ sprintf(required_engine_api_version_string, "%d.%d.%d",
+ my_plugin_record->required_engine_api_version.major,
+ my_plugin_record->required_engine_api_version.minor,
+ my_plugin_record->required_engine_api_version.patchlevel);
+
+ sprintf(required_plugin_api_version_string, "%d.%d.%d",
+ my_plugin_record->required_plugin_api_version.plugin.major,
+ my_plugin_record->required_plugin_api_version.plugin.minor,
+ my_plugin_record->required_plugin_api_version.plugin.patchlevel);
+
+ SET_STRING(Info->info[0].name, "Short Name");
+ SET_STRING(Info->info[0].title, "Short Name");
+ SET_STRING(Info->info[0].desc, "A short name given to this plugin");
+ Info->info[0].type = EVMS_Type_String;
+ SET_STRING(Info->info[0].value.s, my_plugin_record->short_name);
+
+ SET_STRING(Info->info[1].name, "Long Name");
+ SET_STRING(Info->info[1].title, "Long Name");
+ SET_STRING(Info->info[1].desc, "A long name given to this plugin");
+ Info->info[1].type = EVMS_Type_String;
+ SET_STRING(Info->info[1].value.s, my_plugin_record->long_name);
+
+ SET_STRING(Info->info[2].name, "Type");
+ SET_STRING(Info->info[2].title, "Plug-in Type");
+ SET_STRING(Info->info[2].desc, "There are various types of plugins, each responsible for some kind of storage object.");
+ Info->info[2].type = EVMS_Type_String;
+ SET_STRING(Info->info[2].value.s, "Device Manager");
+
+ SET_STRING(Info->info[3].name, "Version");
+ SET_STRING(Info->info[3].title, "Plugin Version");
+ SET_STRING(Info->info[3].desc, "Version number of this plug-in");
+ Info->info[3].type = EVMS_Type_String;
+ SET_STRING(Info->info[3].value.s, version_string);
+
+ SET_STRING(Info->info[4].name, "Required Engine Services Version");
+ SET_STRING(Info->info[4].title, "Required Engine Services Version");
+ SET_STRING(Info->info[4].desc, "Version of the Engine services that this plug-in requires. It will not run on older versions of the Engine services.");
+ Info->info[4].type = EVMS_Type_String;
+ SET_STRING(Info->info[4].value.s, required_engine_api_version_string);
+
+ SET_STRING(Info->info[5].name, "Required Plug-in API Version");
+ SET_STRING(Info->info[5].title, "Required Plug-in API Version");
+ SET_STRING(Info->info[5].desc, "Version of the Engine plug-in API that this plug-in requires. It will not run on older versions of the Engine plug-in API.");
+ Info->info[5].type = EVMS_Type_String;
+ SET_STRING(Info->info[5].value.s, required_plugin_api_version_string);
+
+ *info = Info;
+ rc = 0;
+
+out:
+ LOG_EXIT_INT(rc);
+ return rc;
+}
+
+/**
+ * LD_direct_plugin_communication
+ *
+ * Device-manager-specific commands for starting and stopping the cache, and
+ * opening and closing a disk.
+ **/
+static int LD_direct_plugin_communication(void * object,
+ void * arg)
+{
+ int rc = 0;
+ storage_object_t * disk = object;
+ ldm_dpc_t * dcp = arg;
+
+ LOG_ENTRY();
+ if (disk) {
+ LOG_DEBUG("Action targeted at %s.\n", disk->name);
+ }
+
+ switch (dcp->function) {
+
+ case START_CACHE:
+ LOG_DEBUG("START_CACHE\n");
+ break;
+
+ case STOP_CACHE:
+ LOG_DEBUG("STOP_CACHE\n");
+ break;
+
+ case LDM_CLOSE_DISK:
+ LOG_DEBUG("LDM_CLOSE_DISK\n");
+ close_dev(disk);
+ break;
+
+ case LDM_OPEN_DISK:
+ LOG_DEBUG("LDM_OPEN_DISK\n");
+ rc = open_dev(disk);
+ break;
+
+ default:
+ LOG_ERROR("%d is not a valid function code.\n", dcp->function);
+ rc = EINVAL;
+ }
+
+ LOG_EXIT_INT(rc);
+ return rc;
+}
+
+static plugin_functions_t ft_sysfs = {
+ .setup_evms_plugin = LD_setup,
+ .cleanup_evms_plugin = LD_cleanup,
+ .discover = LD_discover,
+ .discard = LD_discard,
+ .add_sectors_to_kill_list = LD_add_sectors_to_kill_list,
+ .commit_changes = LD_commit_changes,
+ .get_info = LD_get_info,
+ .get_plugin_info = LD_get_plugin_info,
+ .read = LD_read,
+ .write = LD_write,
+ .direct_plugin_communication = LD_direct_plugin_communication
+};
+
+plugin_record_t LD_Plugin = {
+ /* FIXME: get official evms ids */
+ .id = SetPluginID((EVMS_OEM_IBM+1), EVMS_DEVICE_MANAGER, 3),
+ .version = {
+ .major = MAJOR_VERSION,
+ .minor = MINOR_VERSION,
+ .patchlevel = PATCH_LEVEL
+ },
+ .required_engine_api_version = {
+ .major = 13,
+ .minor = 0,
+ .patchlevel = 0
+ },
+ .required_plugin_api_version = {
+ .plugin = {
+ .major = 11,
+ .minor = 0,
+ .patchlevel = 0
+ }
+ },
+ .short_name = "BIOSDskMgr",
+ .long_name = "BIOS Disk Manager",
+ .oem_name = "IBM",
+ .functions = {
+ .plugin = &ft_sysfs
+ },
+ .container_functions = NULL
+};
+
+plugin_record_t * my_plugin_record = &LD_Plugin;
+
+plugin_record_t * evms_plugin_records[] = { &LD_Plugin,
+ NULL };
+
diff -Nurp evms-2.3.0/plugins/bios/bios.h evms-2.3.0-bios/plugins/bios/bios.h
--- evms-2.3.0/plugins/bios/bios.h 1969-12-31 18:00:00.000000000 -0600
+++ evms-2.3.0-bios/plugins/bios/bios.h 2004-03-13 20:12:32.000000000 -0600
@@ -0,0 +1,188 @@
+/*
+ * (C) Copyright IBM Corp. 2001, 2003
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __BIOS_H__
+#define __BIOS_H__ 1
+
+#ifndef O_DIRECT
+#define O_DIRECT 0
+#endif
+
+#define BLKGETSIZE64 _IOR(0x12,114,size_t)
+#define BLKSSZGET _IO(0x12,104)
+#define BLKBSZGET _IOR(0x12,112,size_t)
+#define BLKBSZSET _IOW(0x12,113,size_t)
+#define HDIO_GETGEO 0x0301
+#define HDIO_GETGEO_BIG 0x0330
+
+#define IGNORE_PCI_IDS "biosraid.ignore_pci_ids"
+
+struct hd_geometry {
+ unsigned char heads;
+ unsigned char sectors;
+ unsigned short cylinders;
+ unsigned long start;
+};
+
+struct hd_big_geometry {
+ unsigned char heads;
+ unsigned char sectors;
+ unsigned int cylinders;
+ unsigned long start;
+};
+
+extern engine_functions_t *EngFncs;
+extern plugin_record_t *my_plugin_record;
+
+/*-
+ * Copyright (c) 2000,2001 S?ren Schmidt <[email protected]>
+ * 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,
+ * without modification, immediately at the beginning of the file.
+ * 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 name of the author 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 `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 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.
+ *
+ */
+
+struct highpoint_raid_conf
+{
+ int8_t filler1[32];
+ u_int32_t magic;
+#define HPT_MAGIC_OK 0x5a7816f0
+#define HPT_MAGIC_BAD 0x5a7816fd
+
+ u_int32_t magic_0;
+ u_int32_t magic_1;
+ u_int32_t order;
+#define HPT_O_MIRROR 0x01
+#define HPT_O_STRIPE 0x02
+#define HPT_O_OK 0x04
+
+ u_int8_t raid_disks;
+ u_int8_t raid0_shift;
+ u_int8_t type;
+#define HPT_T_RAID_0 0x00
+#define HPT_T_RAID_1 0x01
+#define HPT_T_RAID_01_RAID_0 0x02
+#define HPT_T_SPAN 0x03
+#define HPT_T_RAID_3 0x04
+#define HPT_T_RAID_5 0x05
+#define HPT_T_SINGLEDISK 0x06
+#define HPT_T_RAID_01_RAID_1 0x07
+
+ u_int8_t disk_number;
+ u_int32_t total_secs;
+ u_int32_t disk_mode;
+ u_int32_t boot_mode;
+ u_int8_t boot_disk;
+ u_int8_t boot_protect;
+ u_int8_t error_log_entries;
+ u_int8_t error_log_index;
+ struct
+ {
+ u_int32_t timestamp;
+ u_int8_t reason;
+#define HPT_R_REMOVED 0xfe
+#define HPT_R_BROKEN 0xff
+
+ u_int8_t disk;
+ u_int8_t status;
+ u_int8_t sectors;
+ u_int32_t lba;
+ } errorlog[32];
+ u_int8_t filler[60];
+};
+
+#define CONFIGOFFSET 4608
+
+/* HPT IDs from http://pciids.sf.net */
+#define PCI_VENDOR_TRIONES 0x1103
+#define PCI_DEVICE_HPT370 0x0004
+#define PCI_DEVICE_HPT372A 0x0005
+#define PCI_DEVICE_HPT302 0x0006
+#define PCI_DEVICE_HPT371 0x0007
+#define PCI_DEVICE_HPT374 0x0008
+#define PCI_DEVICE_HPT372N 0x0009
+
+#define IDEDIR "/proc/ide"
+
+/**
+ * hptdisk
+ *
+ * structure for defining a disk that is attachted to the HPT37x controller
+ **/
+struct hptdisk {
+ char devname[PATH_MAX]; /* define name of the disk */
+ char claimed; /* set to true if the disk
+ is attachted to a raid volume */
+ struct highpoint_raid_conf superblock;
+ int hardsector_size;
+ int32_t major;
+ int32_t minor;
+ int block_size;
+};
+
+/**
+ * hptraid
+ *
+ * structure for a hpt-raid volume
+ **/
+struct hptraid {
+ char name[PATH_MAX]; /* device name of volume */
+ unsigned int stride; /* stripesize */
+ unsigned int disks; /* number of disks in array */
+ u_int64_t sectors; /* disksize in sectors */
+ u_int32_t magic_0;
+ u_int32_t magic_1;
+ u_int8_t type; /* raid level (raid-0, raid-1, ...) */
+ u_int32_t hardsector_size;
+ int block_size;
+
+ enum {setup=0, operational, broken} status;
+
+ dm_target_t * dm_target; /* data structure for the device
+ mapper */
+
+ struct hptdisk * disk[8]; /* pointers to the disks of the
+ raid volume */
+
+ int fd; /* filedestriptor for open_dev(),
+ LD_read/write(), ... */
+};
+
+#endif
+


Attachments:
evms-2.3.0-bios-0.0.1.patch (48.02 kB)