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:

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

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

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

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

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

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

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;