mirror of
https://dev.iopsys.eu/feed/iopsys.git
synced 2026-03-14 21:10:11 +01:00
diskmngr: 1.0.0
This commit is contained in:
parent
48ea3e5185
commit
f76992a7ee
6 changed files with 815 additions and 0 deletions
30
diskmngr/Makefile
Normal file
30
diskmngr/Makefile
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=diskmngr
|
||||
PKG_VERSION:=1.0.0
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_LICENSE:=GPL-2.0-only
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include ../bbfdm/bbfdm.mk
|
||||
|
||||
define Package/diskmngr
|
||||
CATEGORY:=Utilities
|
||||
TITLE:=Storage Info
|
||||
DEPENDS+=+libbbfdm-api +libbbfdm-ubus +dm-service
|
||||
MENU:=1
|
||||
endef
|
||||
|
||||
define Package/diskmngr/description
|
||||
Provides TR181 datamodel for Storage devices
|
||||
endef
|
||||
|
||||
TARGET_CFLAGS += -DBBF_VENDOR_PREFIX=\\\"$(CONFIG_BBF_VENDOR_PREFIX)\\\"
|
||||
|
||||
define Package/diskmngr/install
|
||||
$(BBFDM_REGISTER_SERVICES) -v ${CONFIG_BBF_VENDOR_PREFIX} ./bbfdm_service.json $(1) $(PKG_NAME)
|
||||
$(BBFDM_INSTALL_MS_DM) $(PKG_BUILD_DIR)/libdiskmngr.so $(1) $(PKG_NAME)
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,diskmngr))
|
||||
16
diskmngr/bbfdm_service.json
Normal file
16
diskmngr/bbfdm_service.json
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"daemon": {
|
||||
"enable": "1",
|
||||
"service_name": "diskmngr",
|
||||
"unified_daemon": false,
|
||||
"services": [
|
||||
{
|
||||
"parent_dm": "Device.",
|
||||
"object": "{BBF_VENDOR_PREFIX}Storage"
|
||||
}
|
||||
],
|
||||
"config": {
|
||||
"loglevel": "3"
|
||||
}
|
||||
}
|
||||
}
|
||||
29
diskmngr/src/LICENSE
Normal file
29
diskmngr/src/LICENSE
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2023-2026, IOPSYS
|
||||
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.
|
||||
|
||||
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. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS 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.
|
||||
21
diskmngr/src/Makefile
Normal file
21
diskmngr/src/Makefile
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
LIBOUT := libdiskmngr.so
|
||||
|
||||
LIBOBJS := disk.o
|
||||
|
||||
PROG_CFLAGS = $(CFLAGS) -Wall -Werror -fstrict-aliasing -g
|
||||
LIB_LDFLAGS = $(LDFLAGS)
|
||||
|
||||
FPIC := -fPIC
|
||||
|
||||
.PHONY: all
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(PROG_CFLAGS) $(FPIC) -c -o $@ $<
|
||||
|
||||
all: $(LIBOUT)
|
||||
|
||||
$(LIBOUT): $(LIBOBJS)
|
||||
$(CC) $(PROG_CFLAGS) $(LIB_LDFLAGS) -shared -o $@ $^
|
||||
|
||||
clean:
|
||||
rm -f *.o $(LIBOUT)
|
||||
705
diskmngr/src/disk.c
Normal file
705
diskmngr/src/disk.c
Normal file
|
|
@ -0,0 +1,705 @@
|
|||
/*
|
||||
* Copyright (C) 2025 Genexis Sweden AB
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License version 2.1
|
||||
* as published by the Free Software Foundation
|
||||
*
|
||||
*/
|
||||
|
||||
#include <libbbfdm-api/bbfdm_api.h>
|
||||
#include <libbbfdm-api/dmcommon.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <syslog.h>
|
||||
|
||||
typedef struct mount_entry {
|
||||
struct list_head list;
|
||||
char device[256];
|
||||
char mount_point[256];
|
||||
char fs_type[64];
|
||||
} mount_entry;
|
||||
|
||||
typedef struct partition_entry {
|
||||
struct list_head list;
|
||||
char device[256]; /* e.g., /dev/mmcblk0p4 */
|
||||
char mount_point[256]; /* "" if not mounted */
|
||||
char fs_type[64]; /* "" if not mounted */
|
||||
int partition_number;
|
||||
bool is_mounted;
|
||||
/* Space stats cached at enumerate time; 0 if not mounted */
|
||||
unsigned long long capacity;
|
||||
unsigned long long used;
|
||||
unsigned long long available;
|
||||
} partition_entry;
|
||||
|
||||
typedef struct physical_disk_entry {
|
||||
struct list_head list;
|
||||
struct list_head partitions;
|
||||
char device[256]; /* e.g., /dev/mmcblk0 */
|
||||
char model[256];
|
||||
unsigned long long size; /* bytes */
|
||||
int partition_count;
|
||||
} physical_disk_entry;
|
||||
|
||||
static LIST_HEAD(storage_list);
|
||||
static LIST_HEAD(mount_table);
|
||||
|
||||
/*************************************************************
|
||||
* SYSFS HELPERS
|
||||
*************************************************************/
|
||||
static unsigned long long read_sysfs_ull(const char *path)
|
||||
{
|
||||
FILE *fp;
|
||||
unsigned long long val = 0;
|
||||
|
||||
fp = fopen(path, "r");
|
||||
if (fp) {
|
||||
fscanf(fp, "%llu", &val);
|
||||
fclose(fp);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
static void read_sysfs_str(const char *path, char *buf, size_t len)
|
||||
{
|
||||
FILE *fp;
|
||||
char *p;
|
||||
|
||||
buf[0] = '\0';
|
||||
fp = fopen(path, "r");
|
||||
if (!fp)
|
||||
return;
|
||||
if (fgets(buf, len, fp)) {
|
||||
p = buf + strlen(buf) - 1;
|
||||
while (p >= buf && (*p == '\n' || *p == '\r' || *p == ' '))
|
||||
*p-- = '\0';
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
static void get_disk_model(const char *disk_name, char *model, size_t model_size)
|
||||
{
|
||||
char path[256];
|
||||
|
||||
snprintf(path, sizeof(path), "/sys/block/%s/device/model", disk_name);
|
||||
read_sysfs_str(path, model, model_size);
|
||||
if (model[0])
|
||||
return;
|
||||
|
||||
snprintf(path, sizeof(path), "/sys/block/%s/device/name", disk_name);
|
||||
read_sysfs_str(path, model, model_size);
|
||||
if (model[0])
|
||||
return;
|
||||
|
||||
snprintf(model, model_size, "Unknown");
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
* STATVFS HELPER
|
||||
*************************************************************/
|
||||
static int get_disk_stats(const char *mount_point, unsigned long long *capacity,
|
||||
unsigned long long *used, unsigned long long *available)
|
||||
{
|
||||
struct statvfs s;
|
||||
unsigned long long blksize;
|
||||
|
||||
if (statvfs(mount_point, &s) != 0)
|
||||
return -1;
|
||||
|
||||
blksize = s.f_frsize ? s.f_frsize : s.f_bsize;
|
||||
*capacity = s.f_blocks * blksize;
|
||||
*used = (s.f_blocks - s.f_bfree) * blksize;
|
||||
*available = s.f_bavail * blksize;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
* MOUNT TABLE
|
||||
*************************************************************/
|
||||
static void free_mount_table(void)
|
||||
{
|
||||
mount_entry *e, *tmp;
|
||||
|
||||
list_for_each_entry_safe(e, tmp, &mount_table, list) {
|
||||
list_del(&e->list);
|
||||
BBFDM_FREE(e);
|
||||
}
|
||||
}
|
||||
|
||||
static void load_mount_table(void)
|
||||
{
|
||||
FILE *fp;
|
||||
char line[512];
|
||||
|
||||
free_mount_table();
|
||||
|
||||
fp = fopen("/proc/mounts", "r");
|
||||
if (!fp)
|
||||
return;
|
||||
|
||||
while (fgets(line, sizeof(line), fp)) {
|
||||
char device[256] = {0}, mount_point[256] = {0}, fs_type[64] = {0};
|
||||
mount_entry *e;
|
||||
|
||||
if (sscanf(line, "%255s %255s %63s", device, mount_point, fs_type) != 3)
|
||||
continue;
|
||||
/* Accept block devices under /dev/ and UBI volumes (ubiN:volname) */
|
||||
if (strncmp(device, "/dev/", 5) != 0 &&
|
||||
!(strncmp(device, "ubi", 3) == 0 && strchr(device, ':') != NULL))
|
||||
continue;
|
||||
|
||||
e = calloc(1, sizeof(mount_entry));
|
||||
if (!e) {
|
||||
syslog(LOG_ERR, "Storage: Failed to allocate memory for mount entry");
|
||||
continue;
|
||||
}
|
||||
|
||||
strncpy(e->device, device, sizeof(e->device) - 1);
|
||||
strncpy(e->mount_point, mount_point, sizeof(e->mount_point) - 1);
|
||||
strncpy(e->fs_type, fs_type, sizeof(e->fs_type) - 1);
|
||||
list_add_tail(&e->list, &mount_table);
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
static mount_entry *find_mount(const char *device)
|
||||
{
|
||||
mount_entry *e;
|
||||
|
||||
list_for_each_entry(e, &mount_table, list) {
|
||||
if (strcmp(e->device, device) == 0)
|
||||
return e;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
* STORAGE LIST MANAGEMENT
|
||||
*************************************************************/
|
||||
static void free_storage_list(void)
|
||||
{
|
||||
physical_disk_entry *disk, *disk_tmp;
|
||||
partition_entry *part, *part_tmp;
|
||||
|
||||
list_for_each_entry_safe(disk, disk_tmp, &storage_list, list) {
|
||||
list_for_each_entry_safe(part, part_tmp, &disk->partitions, list) {
|
||||
list_del(&part->list);
|
||||
BBFDM_FREE(part);
|
||||
}
|
||||
list_del(&disk->list);
|
||||
BBFDM_FREE(disk);
|
||||
}
|
||||
}
|
||||
|
||||
static bool is_physical_disk(const char *name)
|
||||
{
|
||||
const char *p;
|
||||
|
||||
if (strncmp(name, "mmcblk", 6) == 0) {
|
||||
/* Accept only mmcblkN — reject mmcblkNboot0, mmcblkNrpmb, etc. */
|
||||
p = name + 6;
|
||||
while (*p && isdigit_str(p))
|
||||
p++;
|
||||
return *p == '\0';
|
||||
}
|
||||
|
||||
return strncmp(name, "sd", 2) == 0 ||
|
||||
strncmp(name, "hd", 2) == 0 ||
|
||||
strncmp(name, "vd", 2) == 0 ||
|
||||
strncmp(name, "nvme", 4) == 0;
|
||||
}
|
||||
|
||||
static void enumerate_ubi_devices(void)
|
||||
{
|
||||
DIR *ubi_dir;
|
||||
struct dirent *de;
|
||||
struct dirent **entries = NULL;
|
||||
int n_entries = 0, i;
|
||||
char path[256];
|
||||
|
||||
ubi_dir = opendir("/sys/class/ubi");
|
||||
if (!ubi_dir)
|
||||
return; /* No UBI support on this system */
|
||||
|
||||
/* Collect all directory entries first */
|
||||
while ((de = readdir(ubi_dir)) != NULL) {
|
||||
struct dirent **tmp = realloc(entries, (n_entries + 1) * sizeof(struct dirent *));
|
||||
if (!tmp) {
|
||||
syslog(LOG_ERR, "Storage: Failed to allocate memory for UBI entries");
|
||||
goto cleanup;
|
||||
}
|
||||
entries = tmp;
|
||||
entries[n_entries] = malloc(sizeof(struct dirent));
|
||||
if (!entries[n_entries]) {
|
||||
syslog(LOG_ERR, "Storage: Failed to allocate memory for UBI entry");
|
||||
goto cleanup;
|
||||
}
|
||||
memcpy(entries[n_entries], de, sizeof(struct dirent));
|
||||
n_entries++;
|
||||
}
|
||||
closedir(ubi_dir);
|
||||
|
||||
/* Process UBI devices */
|
||||
for (i = 0; i < n_entries; i++) {
|
||||
const char *ubi_name = entries[i]->d_name;
|
||||
const char *p;
|
||||
physical_disk_entry *disk;
|
||||
unsigned long long total_lebs, leb_size;
|
||||
char vol_prefix[32];
|
||||
int j;
|
||||
|
||||
/* Match ubiN only (not ubiN_M volume entries) */
|
||||
if (strncmp(ubi_name, "ubi", 3) != 0)
|
||||
continue;
|
||||
p = ubi_name + 3;
|
||||
if (!*p || !isdigit((unsigned char)*p))
|
||||
continue;
|
||||
while (*p && isdigit((unsigned char)*p))
|
||||
p++;
|
||||
if (*p != '\0')
|
||||
continue;
|
||||
|
||||
disk = calloc(1, sizeof(physical_disk_entry));
|
||||
if (!disk) {
|
||||
syslog(LOG_ERR, "Storage: Failed to allocate memory for UBI disk %s", ubi_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&disk->partitions);
|
||||
snprintf(disk->device, sizeof(disk->device), "/dev/%s", ubi_name);
|
||||
snprintf(disk->model, sizeof(disk->model), "NAND Flash (UBI)");
|
||||
|
||||
snprintf(path, sizeof(path), "/sys/class/ubi/%s/total_eraseblocks", ubi_name);
|
||||
total_lebs = read_sysfs_ull(path);
|
||||
snprintf(path, sizeof(path), "/sys/class/ubi/%s/eraseblock_size", ubi_name);
|
||||
leb_size = read_sysfs_ull(path);
|
||||
disk->size = total_lebs * leb_size;
|
||||
|
||||
/* Enumerate volumes: ubiN_M entries */
|
||||
snprintf(vol_prefix, sizeof(vol_prefix), "%s_", ubi_name);
|
||||
for (j = 0; j < n_entries; j++) {
|
||||
const char *vol_entry = entries[j]->d_name;
|
||||
char vol_name[128] = {0};
|
||||
char ubi_dev[256];
|
||||
partition_entry *part;
|
||||
mount_entry *mnt;
|
||||
unsigned long long usable_leb, reserved_ebs;
|
||||
|
||||
if (strncmp(vol_entry, vol_prefix, strlen(vol_prefix)) != 0)
|
||||
continue;
|
||||
|
||||
part = calloc(1, sizeof(partition_entry));
|
||||
if (!part) {
|
||||
syslog(LOG_ERR, "Storage: Failed to allocate memory for UBI volume %s", vol_entry);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Volume ID from the suffix after "ubiN_" */
|
||||
part->partition_number = atoi(vol_entry + strlen(vol_prefix));
|
||||
|
||||
/* Volume name from sysfs (e.g., "boarddata") */
|
||||
snprintf(path, sizeof(path), "/sys/class/ubi/%s/name", vol_entry);
|
||||
read_sysfs_str(path, vol_name, sizeof(vol_name));
|
||||
|
||||
/* Ensure volume name is valid to prevent buffer issues */
|
||||
if (vol_name[0] == '\0') {
|
||||
syslog(LOG_WARNING, "Storage: Empty volume name for %s", vol_entry);
|
||||
BBFDM_FREE(part);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Device name as "ubiN:volname" — matches /proc/mounts */
|
||||
snprintf(ubi_dev, sizeof(ubi_dev), "%s:%s", ubi_name, vol_name);
|
||||
snprintf(part->device, sizeof(part->device), "%s", ubi_dev);
|
||||
|
||||
/* Capacity from sysfs */
|
||||
snprintf(path, sizeof(path), "/sys/class/ubi/%s/usable_leb_size", vol_entry);
|
||||
usable_leb = read_sysfs_ull(path);
|
||||
snprintf(path, sizeof(path), "/sys/class/ubi/%s/reserved_ebs", vol_entry);
|
||||
reserved_ebs = read_sysfs_ull(path);
|
||||
part->capacity = usable_leb * reserved_ebs;
|
||||
|
||||
mnt = find_mount(ubi_dev);
|
||||
if (mnt) {
|
||||
part->is_mounted = true;
|
||||
strncpy(part->mount_point, mnt->mount_point,
|
||||
sizeof(part->mount_point) - 1);
|
||||
strncpy(part->fs_type, mnt->fs_type,
|
||||
sizeof(part->fs_type) - 1);
|
||||
/* Override with live statvfs where available */
|
||||
get_disk_stats(part->mount_point, &part->capacity,
|
||||
&part->used, &part->available);
|
||||
} else {
|
||||
/* For static volumes, data_bytes reflects actual content */
|
||||
snprintf(path, sizeof(path), "/sys/class/ubi/%s/data_bytes", vol_entry);
|
||||
part->used = read_sysfs_ull(path);
|
||||
}
|
||||
|
||||
list_add_tail(&part->list, &disk->partitions);
|
||||
disk->partition_count++;
|
||||
}
|
||||
|
||||
list_add_tail(&disk->list, &storage_list);
|
||||
syslog(LOG_DEBUG, "Storage: ubi=%s size=%llu volumes=%d",
|
||||
disk->device, disk->size, disk->partition_count);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
for (i = 0; i < n_entries; i++)
|
||||
free(entries[i]);
|
||||
free(entries);
|
||||
}
|
||||
|
||||
static void enumerate_storage(void)
|
||||
{
|
||||
DIR *block_dir, *disk_dir;
|
||||
struct dirent *disk_de, *part_de;
|
||||
char path[256];
|
||||
|
||||
free_storage_list();
|
||||
load_mount_table();
|
||||
|
||||
block_dir = opendir("/sys/block");
|
||||
if (!block_dir) {
|
||||
syslog(LOG_ERR, "Storage: Failed to open /sys/block");
|
||||
return;
|
||||
}
|
||||
|
||||
while ((disk_de = readdir(block_dir)) != NULL) {
|
||||
const char *disk_name = disk_de->d_name;
|
||||
physical_disk_entry *disk;
|
||||
|
||||
if (!is_physical_disk(disk_name))
|
||||
continue;
|
||||
|
||||
disk = calloc(1, sizeof(physical_disk_entry));
|
||||
if (!disk) {
|
||||
syslog(LOG_ERR, "Storage: Failed to allocate memory for disk %s", disk_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&disk->partitions);
|
||||
snprintf(disk->device, sizeof(disk->device), "/dev/%s", disk_name);
|
||||
|
||||
snprintf(path, sizeof(path), "/sys/block/%s/size", disk_name);
|
||||
disk->size = read_sysfs_ull(path) * 512;
|
||||
|
||||
get_disk_model(disk_name, disk->model, sizeof(disk->model));
|
||||
|
||||
/* Walk /sys/block/<disk>/ for partitions (identified by 'partition' file) */
|
||||
snprintf(path, sizeof(path), "/sys/block/%s", disk_name);
|
||||
disk_dir = opendir(path);
|
||||
if (disk_dir) {
|
||||
while ((part_de = readdir(disk_dir)) != NULL) {
|
||||
const char *part_name = part_de->d_name;
|
||||
char part_sysfs[256];
|
||||
partition_entry *part;
|
||||
mount_entry *mnt;
|
||||
|
||||
/* Partitions start with the disk name */
|
||||
if (strncmp(part_name, disk_name, strlen(disk_name)) != 0)
|
||||
continue;
|
||||
|
||||
/* Confirm it is a partition via the sysfs 'partition' file */
|
||||
snprintf(part_sysfs, sizeof(part_sysfs),
|
||||
"/sys/block/%s/%s/partition", disk_name, part_name);
|
||||
if (!bbfdm_file_exists(part_sysfs))
|
||||
continue;
|
||||
|
||||
part = calloc(1, sizeof(partition_entry));
|
||||
if (!part) {
|
||||
syslog(LOG_ERR, "Storage: Failed to allocate memory for partition %s", part_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
snprintf(part->device, sizeof(part->device), "/dev/%s", part_name);
|
||||
part->partition_number = (int)read_sysfs_ull(part_sysfs);
|
||||
|
||||
mnt = find_mount(part->device);
|
||||
if (mnt) {
|
||||
part->is_mounted = true;
|
||||
strncpy(part->mount_point, mnt->mount_point,
|
||||
sizeof(part->mount_point) - 1);
|
||||
strncpy(part->fs_type, mnt->fs_type,
|
||||
sizeof(part->fs_type) - 1);
|
||||
get_disk_stats(part->mount_point, &part->capacity,
|
||||
&part->used, &part->available);
|
||||
} else {
|
||||
snprintf(part_sysfs, sizeof(part_sysfs),
|
||||
"/sys/block/%s/%s/size", disk_name, part_name);
|
||||
part->capacity = read_sysfs_ull(part_sysfs) * 512;
|
||||
}
|
||||
|
||||
list_add_tail(&part->list, &disk->partitions);
|
||||
disk->partition_count++;
|
||||
}
|
||||
closedir(disk_dir);
|
||||
}
|
||||
|
||||
list_add_tail(&disk->list, &storage_list);
|
||||
syslog(LOG_DEBUG, "Storage: disk=%s model=%s size=%llu partitions=%d",
|
||||
disk->device, disk->model, disk->size, disk->partition_count);
|
||||
}
|
||||
|
||||
closedir(block_dir);
|
||||
|
||||
enumerate_ubi_devices();
|
||||
|
||||
free_mount_table();
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
* GET PARAMS - Storage.{i}.
|
||||
*************************************************************/
|
||||
static int get_storage_name(char *refparam, struct dmctx *ctx, void *data,
|
||||
char *instance, char **value)
|
||||
{
|
||||
physical_disk_entry *e = (physical_disk_entry *)((struct dm_data *)data)->additional_data;
|
||||
*value = e ? dmstrdup(e->device) : dmstrdup("");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_storage_model(char *refparam, struct dmctx *ctx, void *data,
|
||||
char *instance, char **value)
|
||||
{
|
||||
physical_disk_entry *e = (physical_disk_entry *)((struct dm_data *)data)->additional_data;
|
||||
*value = e ? dmstrdup(e->model) : dmstrdup("Unknown");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_storage_capacity(char *refparam, struct dmctx *ctx, void *data,
|
||||
char *instance, char **value)
|
||||
{
|
||||
physical_disk_entry *e = (physical_disk_entry *)((struct dm_data *)data)->additional_data;
|
||||
dmasprintf(value, "%llu", e ? e->size : 0ULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_storage_status(char *refparam, struct dmctx *ctx, void *data,
|
||||
char *instance, char **value)
|
||||
{
|
||||
physical_disk_entry *e = (physical_disk_entry *)((struct dm_data *)data)->additional_data;
|
||||
*value = (e && e->size > 0) ? dmstrdup("Online") : dmstrdup("Offline");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_storage_partition_number_of_entries(char *refparam, struct dmctx *ctx,
|
||||
void *data, char *instance, char **value)
|
||||
{
|
||||
physical_disk_entry *e = (physical_disk_entry *)((struct dm_data *)data)->additional_data;
|
||||
dmasprintf(value, "%d", e ? e->partition_count : 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
* GET PARAMS - Storage.{i}.Partition.{i}.
|
||||
*************************************************************/
|
||||
static int get_partition_name(char *refparam, struct dmctx *ctx, void *data,
|
||||
char *instance, char **value)
|
||||
{
|
||||
partition_entry *e = (partition_entry *)((struct dm_data *)data)->additional_data;
|
||||
*value = e ? dmstrdup(e->device) : dmstrdup("");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_partition_number(char *refparam, struct dmctx *ctx, void *data,
|
||||
char *instance, char **value)
|
||||
{
|
||||
partition_entry *e = (partition_entry *)((struct dm_data *)data)->additional_data;
|
||||
dmasprintf(value, "%d", e ? e->partition_number : 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_partition_filesystem(char *refparam, struct dmctx *ctx, void *data,
|
||||
char *instance, char **value)
|
||||
{
|
||||
partition_entry *e = (partition_entry *)((struct dm_data *)data)->additional_data;
|
||||
*value = e ? dmstrdup(e->fs_type) : dmstrdup("");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_partition_mount_point(char *refparam, struct dmctx *ctx, void *data,
|
||||
char *instance, char **value)
|
||||
{
|
||||
partition_entry *e = (partition_entry *)((struct dm_data *)data)->additional_data;
|
||||
*value = e ? dmstrdup(e->mount_point) : dmstrdup("");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_partition_status(char *refparam, struct dmctx *ctx, void *data,
|
||||
char *instance, char **value)
|
||||
{
|
||||
partition_entry *e = (partition_entry *)((struct dm_data *)data)->additional_data;
|
||||
*value = (e && e->is_mounted) ? dmstrdup("Mounted") : dmstrdup("Unmounted");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_partition_capacity(char *refparam, struct dmctx *ctx, void *data,
|
||||
char *instance, char **value)
|
||||
{
|
||||
partition_entry *e = (partition_entry *)((struct dm_data *)data)->additional_data;
|
||||
dmasprintf(value, "%llu", e ? e->capacity : 0ULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_partition_used_space(char *refparam, struct dmctx *ctx, void *data,
|
||||
char *instance, char **value)
|
||||
{
|
||||
partition_entry *e = (partition_entry *)((struct dm_data *)data)->additional_data;
|
||||
dmasprintf(value, "%llu", e ? e->used : 0ULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_partition_available_space(char *refparam, struct dmctx *ctx, void *data,
|
||||
char *instance, char **value)
|
||||
{
|
||||
partition_entry *e = (partition_entry *)((struct dm_data *)data)->additional_data;
|
||||
dmasprintf(value, "%llu", e ? e->available : 0ULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_partition_used_percentage(char *refparam, struct dmctx *ctx, void *data,
|
||||
char *instance, char **value)
|
||||
{
|
||||
partition_entry *e = (partition_entry *)((struct dm_data *)data)->additional_data;
|
||||
unsigned int pct = 0;
|
||||
|
||||
if (e && e->capacity > 0)
|
||||
pct = (unsigned int)((e->used * 100) / e->capacity);
|
||||
dmasprintf(value, "%u", pct);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
* NUMBER OF ENTRIES
|
||||
*************************************************************/
|
||||
static int get_storage_number_of_entries(char *refparam, struct dmctx *ctx, void *data,
|
||||
char *instance, char **value)
|
||||
{
|
||||
physical_disk_entry *e;
|
||||
int count = 0;
|
||||
|
||||
enumerate_storage();
|
||||
list_for_each_entry(e, &storage_list, list)
|
||||
count++;
|
||||
dmasprintf(value, "%d", count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
* BROWSE
|
||||
*************************************************************/
|
||||
static int browseStorageInst(struct dmctx *dmctx, DMNODE *parent_node,
|
||||
void *prev_data, char *prev_instance)
|
||||
{
|
||||
physical_disk_entry *e;
|
||||
struct dm_data curr_data = {0};
|
||||
char *inst;
|
||||
int id = 0;
|
||||
|
||||
enumerate_storage();
|
||||
|
||||
list_for_each_entry(e, &storage_list, list) {
|
||||
curr_data.additional_data = e;
|
||||
inst = handle_instance_without_section(dmctx, parent_node, ++id);
|
||||
if (DM_LINK_INST_OBJ(dmctx, parent_node, &curr_data, inst) == DM_STOP)
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int browsePartitionInst(struct dmctx *dmctx, DMNODE *parent_node,
|
||||
void *prev_data, char *prev_instance)
|
||||
{
|
||||
physical_disk_entry *disk = (physical_disk_entry *)((struct dm_data *)prev_data)->additional_data;
|
||||
partition_entry *e;
|
||||
struct dm_data curr_data = {0};
|
||||
char *inst;
|
||||
int id = 0;
|
||||
|
||||
if (!disk)
|
||||
return 0;
|
||||
|
||||
list_for_each_entry(e, &disk->partitions, list) {
|
||||
curr_data.additional_data = e;
|
||||
inst = handle_instance_without_section(dmctx, parent_node, ++id);
|
||||
if (DM_LINK_INST_OBJ(dmctx, parent_node, &curr_data, inst) == DM_STOP)
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
* INIT / CLEAN
|
||||
*************************************************************/
|
||||
void sysmngr_disk_init(void)
|
||||
{
|
||||
enumerate_storage();
|
||||
}
|
||||
|
||||
void sysmngr_disk_clean(void)
|
||||
{
|
||||
free_storage_list();
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************
|
||||
* OBJ & LEAF DEFINITION
|
||||
***********************************************************************************************************************************/
|
||||
|
||||
/* *** Device.DeviceInfo.X_*_Storage.{i}.Partition.{i}. *** */
|
||||
DMLEAF tDeviceInfoStoragePartitionParams[] = {
|
||||
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type */
|
||||
{"Name", &DMREAD, DMT_STRING, get_partition_name, NULL, BBFDM_BOTH},
|
||||
{"PartitionNumber", &DMREAD, DMT_UNINT, get_partition_number, NULL, BBFDM_BOTH},
|
||||
{"FileSystem", &DMREAD, DMT_STRING, get_partition_filesystem, NULL, BBFDM_BOTH},
|
||||
{"MountPoint", &DMREAD, DMT_STRING, get_partition_mount_point, NULL, BBFDM_BOTH},
|
||||
{"Status", &DMREAD, DMT_STRING, get_partition_status, NULL, BBFDM_BOTH},
|
||||
{"Capacity", &DMREAD, DMT_UNLONG, get_partition_capacity, NULL, BBFDM_BOTH},
|
||||
{"UsedSpace", &DMREAD, DMT_UNLONG, get_partition_used_space, NULL, BBFDM_BOTH},
|
||||
{"AvailableSpace", &DMREAD, DMT_UNLONG, get_partition_available_space, NULL, BBFDM_BOTH},
|
||||
{"UsedPercentage", &DMREAD, DMT_UNINT, get_partition_used_percentage, NULL, BBFDM_BOTH},
|
||||
{0}
|
||||
};
|
||||
|
||||
/* *** Device.DeviceInfo.X_*_Storage.{i}. *** */
|
||||
DMOBJ tDeviceInfoStorageInstanceObj[] = {
|
||||
/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type */
|
||||
{"Partition", &DMREAD, NULL, NULL, NULL, browsePartitionInst, NULL, NULL, NULL, tDeviceInfoStoragePartitionParams, NULL, BBFDM_BOTH},
|
||||
{0}
|
||||
};
|
||||
|
||||
DMLEAF tDeviceInfoStorageInstanceParams[] = {
|
||||
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type */
|
||||
{"Name", &DMREAD, DMT_STRING, get_storage_name, NULL, BBFDM_BOTH},
|
||||
{"Model", &DMREAD, DMT_STRING, get_storage_model, NULL, BBFDM_BOTH},
|
||||
{"Capacity", &DMREAD, DMT_UNLONG, get_storage_capacity, NULL, BBFDM_BOTH},
|
||||
{"Status", &DMREAD, DMT_STRING, get_storage_status, NULL, BBFDM_BOTH},
|
||||
{"PartitionNumberOfEntries", &DMREAD, DMT_UNINT, get_storage_partition_number_of_entries, NULL, BBFDM_BOTH},
|
||||
{0}
|
||||
};
|
||||
|
||||
/* *** Device.DeviceInfo.X_*_Storage. *** */
|
||||
DMOBJ tDeviceInfoStorageObj[] = {
|
||||
/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type */
|
||||
{"Storage", &DMREAD, NULL, NULL, NULL, browseStorageInst, NULL, NULL, tDeviceInfoStorageInstanceObj, tDeviceInfoStorageInstanceParams, NULL, BBFDM_BOTH},
|
||||
{0}
|
||||
};
|
||||
|
||||
DMLEAF tDeviceInfoStorageParams[] = {
|
||||
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type */
|
||||
{"StorageNumberOfEntries", &DMREAD, DMT_UNINT, get_storage_number_of_entries, NULL, BBFDM_BOTH},
|
||||
{0}
|
||||
};
|
||||
|
||||
DMOBJ tDeviceStorageObj[] = {
|
||||
/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type */
|
||||
{BBF_VENDOR_PREFIX"Storage", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tDeviceInfoStorageObj, tDeviceInfoStorageParams, NULL, BBFDM_BOTH},
|
||||
{0}
|
||||
};
|
||||
|
||||
DM_MAP_OBJ tDynamicObj[] = {
|
||||
/* parentobj, nextobject, parameter */
|
||||
{"Device.", tDeviceStorageObj, NULL},
|
||||
{0}
|
||||
};
|
||||
14
diskmngr/src/disk.h
Normal file
14
diskmngr/src/disk.h
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* Copyright (C) 2025 Genexis Sweden AB
|
||||
*/
|
||||
|
||||
#ifndef __DISK_H
|
||||
#define __DISK_H
|
||||
|
||||
extern DMOBJ tDeviceInfoStorageObj[];
|
||||
extern DMLEAF tDeviceInfoStorageParams[];
|
||||
|
||||
void sysmngr_disk_init(void);
|
||||
void sysmngr_disk_clean(void);
|
||||
|
||||
#endif //__DISK_H
|
||||
Loading…
Add table
Reference in a new issue