diff options
author | mananth <mananth> | 2003-10-15 12:22:43 +0000 |
---|---|---|
committer | mananth <mananth> | 2003-10-15 12:22:43 +0000 |
commit | 86c5b90a76fe07731224d3b47c08721c30b41f29 (patch) | |
tree | 1e6c0934c3f3d8a013b710770463536aab8f1d47 /lib | |
parent | 7838df3254db021c96f1c53593c1753cb4315057 (diff) | |
download | sysfsutils-86c5b90a76fe07731224d3b47c08721c30b41f29.tar.gz |
Added sysfs_block.c
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Makefile.am | 2 | ||||
-rw-r--r-- | lib/Makefile.in | 10 | ||||
-rw-r--r-- | lib/sysfs_block.c | 309 | ||||
-rw-r--r-- | lib/sysfs_class.c | 2 | ||||
-rw-r--r-- | lib/sysfs_dir.c | 3 |
5 files changed, 319 insertions, 7 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am index d343f01..2b5049a 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -1,5 +1,5 @@ lib_LIBRARIES = libsysfs.a libsysfs_a_SOURCES = sysfs_utils.c sysfs_dir.c sysfs_bus.c sysfs_class.c \ - sysfs_device.c sysfs_driver.c sysfs.h dlist.c + sysfs_device.c sysfs_driver.c sysfs_block.c sysfs.h dlist.c INCLUDES = -I../include diff --git a/lib/Makefile.in b/lib/Makefile.in index a2e859e..2ecbd5f 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -77,7 +77,7 @@ am__quote = @am__quote@ install_sh = @install_sh@ lib_LIBRARIES = libsysfs.a libsysfs_a_SOURCES = sysfs_utils.c sysfs_dir.c sysfs_bus.c sysfs_class.c \ - sysfs_device.c sysfs_driver.c sysfs.h dlist.c + sysfs_device.c sysfs_driver.c sysfs_block.c sysfs.h dlist.c INCLUDES = -I../include subdir = lib @@ -90,7 +90,8 @@ libsysfs_a_AR = $(AR) cru libsysfs_a_LIBADD = am_libsysfs_a_OBJECTS = sysfs_utils.$(OBJEXT) sysfs_dir.$(OBJEXT) \ sysfs_bus.$(OBJEXT) sysfs_class.$(OBJEXT) \ - sysfs_device.$(OBJEXT) sysfs_driver.$(OBJEXT) dlist.$(OBJEXT) + sysfs_device.$(OBJEXT) sysfs_driver.$(OBJEXT) \ + sysfs_block.$(OBJEXT) dlist.$(OBJEXT) libsysfs_a_OBJECTS = $(am_libsysfs_a_OBJECTS) DEFS = @DEFS@ @@ -100,8 +101,8 @@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles -@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/dlist.Po ./$(DEPDIR)/sysfs_bus.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/sysfs_class.Po \ +@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/dlist.Po ./$(DEPDIR)/sysfs_block.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/sysfs_bus.Po ./$(DEPDIR)/sysfs_class.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/sysfs_device.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/sysfs_dir.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/sysfs_driver.Po \ @@ -168,6 +169,7 @@ distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dlist.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysfs_block.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysfs_bus.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysfs_class.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysfs_device.Po@am__quote@ diff --git a/lib/sysfs_block.c b/lib/sysfs_block.c new file mode 100644 index 0000000..601f575 --- /dev/null +++ b/lib/sysfs_block.c @@ -0,0 +1,309 @@ +/* + * sysfs_block.c + * + * Generic block utility functions for libsysfs + * + * Copyright (C) IBM Corp. 2003 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* + * NOTES: + * Write functions to: + * Device major/minor given a device + * As of now, only the "block" device has writable attribs. + * Library has to take care of navigating to the attribute + * (may be at various directory levels) + */ + +#include "libsysfs.h" +#include "sysfs.h" + +void sysfs_del_partition(void *partition) +{ + sysfs_close_block_partition((struct sysfs_block_partition *)partition); +} + +/** + * sysfs_close_block_partition: closes a block partition + * @partition: sysfs_block_partition to close + */ +void sysfs_close_block_partition(struct sysfs_block_partition *partition) +{ + if (partition != NULL) { + if (partition->directory != NULL) +/* reuse sysfs_dir from the earlier structure - just set it to NULL here + * free it while closing sysfs_block_device->directory + * sysfs_close_directory(partition->directory);*/ + partition->directory = NULL; + } +} + +/** + * sysfs_close_block_device: closes a sysfs_block_device + * @block: sysfs_block_device structure + */ +void sysfs_close_block_device(struct sysfs_block_device *block) +{ + if (block != NULL) { + if (block->directory != NULL) + sysfs_close_directory(block->directory); + if (block->device != NULL) + sysfs_close_device(block->device); + if (block->partitions != NULL) + dlist_destroy(block->partitions); + } +} + +/** + * alloc_block_device: allocate a sysfs_block_device + * returns sysfs_block_device or NULL + */ +static struct sysfs_block_device *alloc_block_device() +{ + return (struct sysfs_block_device *) + calloc(1, sizeof(struct sysfs_block_device)); +} + +/** + * open_block_dir: opens a sysfs block directory + * returns sysfs_directory on success or NULL on error + */ +static struct sysfs_directory *open_block_dir(const unsigned char *name) +{ + unsigned char path[SYSFS_PATH_MAX]; + struct sysfs_directory *directory = NULL; + + if (name == NULL) { + errno = EINVAL; + return NULL; + } + + memset(path, 0, SYSFS_PATH_MAX); + if ((sysfs_get_mnt_path(path, SYSFS_PATH_MAX)) != 0) { + dprintf("Error getting sysfs mount path\n"); + return NULL; + } + + strcat(path, SYSFS_BLOCK_DIR); + strcat(path, "/"); + strcat(path, name); + directory = sysfs_open_directory(path); + if (directory == NULL) { + dprintf("Block device %s not supported on this system", name); + return NULL; + } + if ((sysfs_read_directory(directory)) != 0) { + dprintf("Error reading directory %s\n", directory->path); + sysfs_close_directory(directory); + return NULL; + } + sysfs_read_all_subdirs(directory); + + return directory; +} + +/** + * alloc_block_partition: alloc a sysfs_block_partition structure + */ +static struct sysfs_block_partition *alloc_block_partition(void) +{ + return(struct sysfs_block_partition *) + calloc(1, sizeof(struct sysfs_block_partition)); +} + +/** + * get_all_block_devices: Retrieves details of block directory + * @block: sysfs_block_device for which details are required + * returns 0 on success, -1 on failure + */ +static int get_all_block_devices(struct sysfs_block_device *block) +{ + struct sysfs_directory *cur = NULL; + struct sysfs_block_partition *part = NULL; + + if (block == NULL || block->directory == NULL) { + errno = EINVAL; + return -1; + } + + dlist_for_each_data(block->directory->subdirs, cur, + struct sysfs_directory) { + switch(strcmp(cur->name, SYSFS_QUEUE_NAME)) { + case 0: /* this is the "queue" directory */ + if ((sysfs_read_directory(cur)) < 0) { + dprintf("Error reading directory %s\n", + cur->path); + return -1; + } + break; + default: /* these are the partitions */ + part = alloc_block_partition(); + if (part == NULL) { + perror("calloc"); + return -1; + } + part->directory = cur; + strcpy(part->name, cur->name); + if (block->partitions == NULL) + block->partitions = + dlist_new_with_delete + (sizeof(struct + sysfs_block_partition), + sysfs_del_partition); + dlist_unshift(block->partitions, part); + break; + } + } + return 0; +} + +/** + * sysfs_open_block_device: opens the specific block device and all its related + * details as partitions, etc + * returns sysfs_block_device struct on success and NULL on error + */ +struct sysfs_block_device *sysfs_open_block_device(unsigned char *name) +{ + struct sysfs_block_device *block = NULL; + struct sysfs_directory *blockdir = NULL; + struct sysfs_link *curlink = NULL; + + if (name == NULL) { + errno = EINVAL; + return NULL; + } + + block = alloc_block_device(); + if (block == NULL) { + perror("calloc"); + return NULL; + } + strcpy(block->name, name); + blockdir = open_block_dir(name); + if (blockdir == NULL) { + sysfs_close_block_device(block); + return NULL; + } + strcpy(block->path, blockdir->path); + block->directory = blockdir; + if ((get_all_block_devices(block)) != 0) { + dprintf("Error retrieving devices for block %s\n", name); + sysfs_close_block_device(block); + return NULL; + } + /* check if the "block" device has a link to the physical device */ + if (block->directory->links != NULL) { + dlist_for_each_data(block->directory->links, curlink, + struct sysfs_link) { + block->device = sysfs_open_device(curlink->target); + if (block->device == NULL) { + dprintf("Error opening device at %s\n", + curlink->target); + } + } + } + + return block; +} + +/** + * sysfs_get_blockdev_attributes: returns attributes for the block device + * @block: block device for which attribs are to be returned + */ +struct dlist *sysfs_get_blockdev_attributes(struct sysfs_block_device *block) +{ + if (block == NULL || block->directory == NULL) + return NULL; + + return(block->directory->attributes); +} + +/** + * sysfs_get_partition_attributes: returns attributes for the block + * device partition + * @block: block device partition for which attribs are to be returned + */ +struct dlist *sysfs_get_partition_attributes + (struct sysfs_block_partition *part) +{ + if (part == NULL || part->directory == NULL) + return NULL; + + return(part->directory->attributes); +} + +/** + * sysfs_get_queue_attributes: returns attributes for the block device's + * QUEUE parameters. Used to set #of queued + * requests as well as the choice of IO + * scheduler + * @block: block device for which the attributes are needed. + */ +struct dlist *sysfs_get_queue_attributes(struct sysfs_block_device *block) +{ + struct dlist *list = NULL; + struct sysfs_directory *dir = NULL; + unsigned int found = 0; + + dlist_for_each_data(block->directory->subdirs, dir, + struct sysfs_directory) { + if ((strcmp(dir->name, SYSFS_QUEUE_NAME)) != 0) + continue; + else + return (dir->attributes); + } + return NULL; +} + +/** + * sysfs_get_iosched_attributes: returns attributes for the block device's + * IOSCHED parameters for the given device + * @block: block device for which the attributes are needed + * returns a dlist of iosched attributes. + */ +struct dlist *sysfs_get_iosched_attributes(struct sysfs_block_device *block) +{ + struct dlist *list = NULL; + struct sysfs_directory *dir = NULL, *new = NULL; + unsigned int found = 0; + + dlist_for_each_data(block->directory->subdirs, dir, + struct sysfs_directory) { + if ((strcmp(dir->name, SYSFS_QUEUE_NAME)) != 0) + continue; + else { + found = 1; + break; + } + } + if (found) { + /* + * this is the queue directory - read this and the + * iosched directory too + */ + dlist_for_each_data(dir->subdirs, new, + struct sysfs_directory) { + if ((strcmp(new->name, SYSFS_IOSCHED_NAME)) == 0) + if ((sysfs_read_directory(new)) == 0) + return new->attributes; + } + } + dprintf("IOSCHED attributes not found\n"); + return NULL; +} + diff --git a/lib/sysfs_class.c b/lib/sysfs_class.c index 6c969b5..9172a1e 100644 --- a/lib/sysfs_class.c +++ b/lib/sysfs_class.c @@ -264,7 +264,7 @@ struct sysfs_class *sysfs_open_class(const unsigned char *name) cls = alloc_class(); if (cls == NULL) { - perror("malloc"); + perror("calloc"); return NULL; } strcpy(cls->name, name); diff --git a/lib/sysfs_dir.c b/lib/sysfs_dir.c index 1d730e7..46ebd52 100644 --- a/lib/sysfs_dir.c +++ b/lib/sysfs_dir.c @@ -525,10 +525,11 @@ int sysfs_read_directory(struct sysfs_directory *sysdir) } } - if (sysdir->attributes == NULL) + if (sysdir->attributes == NULL) { sysdir->attributes = dlist_new_with_delete (sizeof(struct sysfs_attribute), sysfs_del_attribute); + } dlist_unshift(sysdir->attributes, attr); } else if (S_ISDIR(astats.st_mode)) { subdir = sysfs_open_directory(file_path); |