Report stats also for low devices
Some checks are pending
Build / build-mac (push) Waiting to run
Build / build-linux (push) Waiting to run
Build / build-win (push) Waiting to run
CodeQL Advanced / Analyze (c-cpp) (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run

This commit is contained in:
Andrea Mazzoleni 2026-03-03 12:41:16 +01:00
parent 27c44ce56e
commit 75ef786e29
3 changed files with 112 additions and 89 deletions

View file

@ -912,7 +912,30 @@ static void state_stat(struct snapraid_state* state, tommy_list* high)
/* print disk access_stat (not split) */
if (devinfo->split == 0 && devinfo->access_stat != 0) {
log_tag("stat:%s:%" PRIu64 "\n", devinfo->name, devinfo->access_stat);
if (devinfo->name[0])
log_tag("stat:%s:%" PRIu64 "\n", devinfo->name, devinfo->access_stat);
else
log_tag("stat_device:%s:%" PRIu64 "\n", devinfo->file, devinfo->access_stat);
}
}
}
static void state_devices(struct snapraid_state* state, tommy_list* low)
{
tommy_node* i;
(void)state;
for (i = tommy_list_head(low); i != 0; i = i->next) {
devinfo_t* devinfo = i->data;
devinfo_t* parent = devinfo->parent;
if (parent) {
#ifdef _WIN32
printf("%" PRIu64 "\t%s\t%08" PRIx64 "\t%s\t%s\n", devinfo->device, devinfo->wfile, parent->device, parent->wfile, parent->name);
#else
printf("%u:%u\t%s\t%u:%u\t%s\t%s\n", major(devinfo->device), minor(devinfo->device), devinfo->file, major(parent->device), minor(parent->device), parent->file, parent->name);
#endif
}
}
}
@ -1058,7 +1081,7 @@ void state_device(struct snapraid_state* state, int operation, tommy_list* filte
if (state->opt.fake_device) {
ret = devtest(&high, &low, operation);
} else {
int others = operation == DEVICE_SMART || operation == DEVICE_PROBE;
int others = operation == DEVICE_SMART || operation == DEVICE_PROBE || operation == DEVICE_LIST;
ret = devquery(&high, &low, operation, others);
}
@ -1079,19 +1102,8 @@ void state_device(struct snapraid_state* state, int operation, tommy_list* filte
}
log_fatal(ESOFT, "%s is unsupported in this platform.\n", ope);
} else {
if (operation == DEVICE_LIST) {
for (i = tommy_list_head(&low); i != 0; i = i->next) {
devinfo_t* devinfo = i->data;
devinfo_t* parent = devinfo->parent;
#ifdef _WIN32
printf("%" PRIu64 "\t%s\t%08" PRIx64 "\t%s\t%s\n", devinfo->device, devinfo->wfile, parent->device, parent->wfile, parent->name);
#else
printf("%u:%u\t%s\t%u:%u\t%s\t%s\n", major(devinfo->device), minor(devinfo->device), devinfo->file, major(parent->device), minor(parent->device), parent->file, parent->name);
#endif
}
}
state_stat(state, &high);
state_stat(state, &low);
if (operation == DEVICE_SMART)
state_smart(state, state->level + tommy_list_count(&state->disklist), &low);
@ -1101,6 +1113,9 @@ void state_device(struct snapraid_state* state, int operation, tommy_list* filte
if (operation == DEVICE_UP)
state_attr(state, &low);
if (operation == DEVICE_LIST)
state_devices(state, &low);
}
tommy_list_foreach(&high, free);

View file

@ -539,7 +539,7 @@ struct devinfo_struct {
char wfile[PATH_MAX]; /**< File device in Windows format. Like \\.\PhysicalDriveX, or \\?\Volume{X}. */
#endif
struct devinfo_struct* parent; /**< Pointer at the parent if any. */
struct devinfo_struct* split; /**< Pointer at first split if any. */
struct devinfo_struct* split; /**< Pointer at first split if this one is not the first. */
struct smart_attr smart[SMART_COUNT]; /**< All smart values. */
uint64_t info[INFO_COUNT]; /**< Informational attributes not related to SMART telemetry. */
uint64_t access_stat; /**< Access stat info. */

View file

@ -1397,6 +1397,79 @@ static int devtree(devinfo_t* parent, dev_t device, tommy_list* list)
}
#endif
/**
* Compute disk usage by aggregating access statistics.
*/
#if HAVE_LINUX_DEVICE
static int devstat(dev_t device, uint64_t* count)
{
char path[PATH_MAX];
char buf[512];
int token;
int ret;
char* i;
*count = 0;
pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/stat", major(device), minor(device));
ret = sysread(path, buf, sizeof(buf));
if (ret < 0) {
/* LCOV_EXCL_START */
log_fatal(errno, "Failed to read '%s'.\n", path);
return -1;
/* LCOV_EXCL_STOP */
}
if ((size_t)ret + 1 > sizeof(buf)) {
/* LCOV_EXCL_START */
log_fatal(EEXTERNAL, "Too long read '%s'.\n", path);
return -1;
/* LCOV_EXCL_STOP */
}
/* ending 0 */
buf[ret] = 0;
i = buf;
token = 1; /* token number */
while (*i) {
char* n;
char* e;
unsigned long long v;
/* skip spaces */
while (*i && isspace(*i))
++i;
/* read digits */
n = i;
while (*i && isdigit(*i))
++i;
if (i == n) /* if no digit, abort */
break;
if (*i == 0 || !isspace(*i)) /* if no space, abort */
break;
*i++ = 0; /* put a terminator */
v = strtoull(n, &e, 10);
if (*e != 0)
break;
/* sum reads and writes completed */
if (token == 1 || token == 5) {
*count += v;
if (token == 5)
break; /* stop here */
}
++token;
}
return 0;
}
#endif
/**
* Scan all the devices.
*
@ -1469,6 +1542,13 @@ static int devscan(tommy_list* list)
devinfo->device = device;
pathcpy(devinfo->file, sizeof(devinfo->file), path);
/* retrieve access stat for the low level device */
uint64_t access_stat;
if (devstat(device, &access_stat) == 0) {
/* cumulate access stat in the first split */
devinfo->access_stat = access_stat;
}
/* insert in the list */
tommy_list_insert_tail(list, &devinfo->node, devinfo);
}
@ -1559,79 +1639,6 @@ static int devsmart(dev_t device, const char* name, const char* smartctl, struct
}
#endif
/**
* Compute disk usage by aggregating access statistics.
*/
#if HAVE_LINUX_DEVICE
static int devstat(dev_t device, uint64_t* count)
{
char path[PATH_MAX];
char buf[512];
int token;
int ret;
char* i;
*count = 0;
pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/stat", major(device), minor(device));
ret = sysread(path, buf, sizeof(buf));
if (ret < 0) {
/* LCOV_EXCL_START */
log_fatal(errno, "Failed to read '%s'.\n", path);
return -1;
/* LCOV_EXCL_STOP */
}
if ((size_t)ret + 1 > sizeof(buf)) {
/* LCOV_EXCL_START */
log_fatal(EEXTERNAL, "Too long read '%s'.\n", path);
return -1;
/* LCOV_EXCL_STOP */
}
/* ending 0 */
buf[ret] = 0;
i = buf;
token = 1; /* token number */
while (*i) {
char* n;
char* e;
unsigned long long v;
/* skip spaces */
while (*i && isspace(*i))
++i;
/* read digits */
n = i;
while (*i && isdigit(*i))
++i;
if (i == n) /* if no digit, abort */
break;
if (*i == 0 || !isspace(*i)) /* if no space, abort */
break;
*i++ = 0; /* put a terminator */
v = strtoull(n, &e, 10);
if (*e != 0)
break;
/* sum reads and writes completed */
if (token == 1 || token == 5) {
*count += v;
if (token == 5)
break; /* stop here */
}
++token;
}
return 0;
}
#endif
/**
* Get device attributes.
*/
@ -2210,7 +2217,7 @@ int devquery(tommy_list* high, tommy_list* low, int operation, int others)
/* LCOV_EXCL_STOP */
}
/* for each device */
/* for each high device */
for (i = tommy_list_head(high); i != 0; i = i->next) {
devinfo_t* devinfo = i->data;
uint64_t device = devinfo->device;
@ -2273,6 +2280,7 @@ int devquery(tommy_list* high, tommy_list* low, int operation, int others)
/* LCOV_EXCL_STOP */
}
}
#else
(void)high;
(void)others;