DiskInfo
DiskInfo retrives information on block devices available on system
including Hard Disks and partitions on them, and Volume Manager objects
Due to complex logic of Disk Hierarchy and huge number of Volume Managers
(which of them of course has own logic on hierarchy), DiskInfo may look
inconsistent, but it is best what we can do.
NOTE: Currently if pool or volume reside on partition, than partition
would be considered a child to that pool or volume. It also would be child
to disk drive. This rule may change in future releases of HostInfo.
Disk object children are sometimes called "slaves" due to Linux SYSFS naming
scheme.
Linux
Walks /sys/block and searches for dm- or sda/hda devices, identifies their subpartitions
and slaves from SYSFS. Paths are generated as /dev/DEVNAME
For device-mapper devices dm/uuid
is provided as d_id
Provides SCSI host identifier proc_name
as a d_bus_type
(usually set to driver name).
Solaris
Uses libdiskmgt to enumerate disks/partitions. Probes VTOC slices as
disk partitions that could be children of partitions. For disks that provide
WWN, it is saved as d_id
.
For disk drives trailing sX or pX slice/partition identifier is shrinked.
NOTE: It also probes ZFS and SVM, but only adds links if ZFS or SVM device
reside on real disk or partition. If you build SVM pool on top of ZVOL and vice
versa, DiskInfo won't track that relationship.
Windows
Unlike traditional approach which goes from the top by enumerating drive letters from A: to Z:
or using generic \\PhysicalDriveX\
device names, DiskInfo on Windows uses SetupDi APIs to
get PnP device ids. Than using ioctls it iterates its partitions.
However, meaningful disk unit in Windows is Volume, so DiskInfo iterates over available volumes
using FindFirstVolume()
/FindNextVolume()
, collects volume extents and them binds volumes
to disk partitions according block numbers on which they reside. Also, it construct FSInfo
objects from volume information.
NOTE: Currently \\PhysicalDriveX\
device name isn't generated and DiskInfo use PNP
device name. This behavior may change in future versions of DiskInfo.
NOTE: Currently DiskInfo uses generic suffix PartitionX
for partitions which is not useable
in API calls. It is only used for reference.
References:
- Enumdisk1.exe: Enumdisk Sample for Enumerating Disk Devices
- Enumerating and using partitions and volumes in Windows operating system
LVM2
Uses liblvm2app to get information about Logical Volume Manager 2 on Linux
Volume Groups (VGs) are considered as pools, while Logical Volumes (LVs) are
added as volumes.
Hides its objects in namespace lvm2
so naming schema is lvm2:VGNAME[:LVNAME]
.
NOTE: LVM2 resides on top of device mapper which nodes are collected by
generic DiskInfo code. So, dm-X
volumes are bound to real LVM2 volumes
adding extra layer of indirection:
NOTE: Access to /dev/mapper/control
require admin privileges, so it may
fail entire DiskInfo probing. Set hi_linux_lvm2
tunable to false
to disable
LVM2 probing.
ZFS
Uses libzfs to gather information about ZFS on POSIX platforms, which is combined
file system/volume manager.
ZFS names reside in namespace zfs
, so naming schema is zfs:ZPOOLNAME[:ZVOLNAME|VDEVNAME]
Recursively walks over ZPOOL_CONFIG_VDEV_TREE over CHILDREN, SPARES and L2CACHE devices.
Considers VDEVs (except for leaf disk VDEVs) as a subpools, so HI_DSKT_POOL
created
per each VDEV and it is added as a slave to master ZPOOL. For VDEVs d_bus_type
is
set to ZPOOL:VDEV
without specifying real nature of VDEV (log, l2cache, hostspare or data),
while name of VDEV is set to zfs:ZPOOLNAME:VDEVNAME
.
d_path
for pools is set to /dev/zfs
(administration device).
Size of pool/subpool is measured by ZFS internal asize variable. However, it is reference
to allocable size, so for RAID-Zx, copies, compression or dedup, this value doesn't represent
actual amount of user data which could be written on pool. For pool asize
is calculated as
sum of asizes of top-level VDEVs.
Since ZFS is a filesystem, this helper creates FSInfo objects too.
Solaris Volume Manager
Enumerates SVM devices as volumes (some of them like mirrors may reside on top of volumes).
Real type of SVM device is saved in d_bus_type
.
Unfortunately, libmeta supports only 32-bit builds, and also it has very complex API,
so instead of imitating it, we will use direct approach: call metastat -p
which prints
metainit arguments that are easy to parse.
NOTE: SVM helper supports only mirrors, stripes and software paritions in local metaset.
Variables
Disables LVM2 devices probing.
Useful if HostInfo consumer is running from non-root user.
Even if disabled, LVs may be tracked as dm-X devices.
NOTE: disabling it makes LVM2 structure untrackable, thus causing unwanted
consequences, i.e. allowing simpleio
module writing on disk owned by LVM.
boolean_t hi_linux_lvm2
Functions
HI_DSK_FROM_OBJ, HI_DSK_TO_OBJ
Conversion macros
#define HI_DSK_FROM_OBJ(object) #define HI_DSK_TO_OBJ(di)
hi_dsk_dtor
Destroy disk descriptor and free slave handles if needed
void hi_dsk_dtor(hi_object_t* object)
hi_dsk_create
Allocate and initialize disk descriptor hi_dsk_info_t
hi_dsk_info_t* hi_dsk_create(void)
hi_dsk_check_overlap
public
Helper for diskio
workload type -- finds if selected
disk overlaps with pool, volume or filesystem
ARGUMENTS
-
di - chosen disk
RETURN VALUES
disk or filesystem this disk overlaps
NOTES
pools (HI_DSKT_POOL
) are not supported here
LIBEXPORT hi_object_t* hi_dsk_check_overlap(hi_dsk_info_t* di)
hi_dsk_add
public
Add disk descriptor to global list
STATIC_INLINE void hi_dsk_add(hi_dsk_info_t* di)
hi_dsk_attach
public
Attach disk descriptor to parent as a slave
ARGUMENTS
-
di - Slave disk descriptor
-
parent - Parent disk descriptor
STATIC_INLINE void hi_dsk_attach(hi_dsk_info_t* di, hi_dsk_info_t* parent)
hi_dsk_find
public
Find disk by it's name
ARGUMENTS
-
name - - name of disk
RETURN VALUES
disk descriptor or NULL if it wasn't found
STATIC_INLINE hi_dsk_info_t* hi_dsk_find(const char* name)
hi_dsk_list
public
Probe system's disk (if needed) and return pointer
to global disk descriptor list head
ARGUMENTS
-
reprobe - Probe system's disks again
RETURN VALUES
pointer to head or NULL if probe failed
STATIC_INLINE list_head_t* hi_dsk_list(boolean_t reprobe)
Types
typedef enum hi_dsk_type
DiskInfo object type
VALUES
-
HI_DSKT_UNKNOWN - unknown object (shouldn't be exposed, used internally)
-
HI_DSKT_DISK - real or virtual disk drive
-
HI_DSKT_PARTITION - partition on disk drive
-
HI_DSKT_POOL - Volume Manager "pool" -- collection of disks, partitions or whatever. Note that pools haven't real block device corresponding to it, it is used only to show hierarchy
-
HI_DSKT_VOLUME - Logical Volume that resiedes on disks, partitions or inside pools
typedef enum hi_dsk_type { HI_DSKT_UNKNOWN, HI_DSKT_DISK, HI_DSKT_PARTITION, HI_DSKT_POOL, HI_DSKT_VOLUME } hi_dsk_type_t;
typedef struct hi_dsk_info
DiskInfo descriptor
MEMBERS
-
d_hdr - HiObject header
-
d_disk_name - Unique name of disk device. For volume managers symbolic name may be namespaced, i.e. md:d10 or zfs:volume to ensure uniqueness Same as
d_hdr.name
-
d_path - Path to corresponding block device. For devices those not support direct access, this field may contain some meaningful path, which however couldn't be argument to
open()
orCreateFile()
. See platform notes for details. -
d_mode - Access permissions to that disk object.
-
d_size - Size of disk, volume, pool or partition in bytes
-
d_type - Type of that descriptor
-
d_bus_type - (optional) Identifies how this disk plugged into hierarchy. May be name of the bus or a driver handling that bus or contain volume manager name along with volume manager device subtype
-
d_port - (optional) Optional identifier of hardware port where disk is plugged in. Usually it is SCSI host, SCSI target and SCSI LUN
-
d_id - (optional) Identifier provided by lower layer
-
d_model - (optional) For disk drives - vendor and model of disk
typedef struct hi_dsk_info { hi_object_header_t d_hdr; #define d_disk_name d_hdr.name /* Mandatory fields */ AUTOSTRING char* d_path; int d_mode; uint64_t d_size; hi_dsk_type_t d_type; /* Optional fields */ AUTOSTRING char* d_bus_type; AUTOSTRING char* d_port; AUTOSTRING char* d_id; AUTOSTRING char* d_model; } hi_dsk_info_t;