mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 10:51:54 -04:00
Make the stat tag a disk level
This commit is contained in:
parent
672b881df3
commit
524733a6db
6 changed files with 67 additions and 140 deletions
|
|
@ -558,8 +558,6 @@ static void state_info_log(devinfo_t* devinfo)
|
|||
log_tag("attr:%s:%s:size:%" PRIu64 "\n", devinfo->file, devinfo->name, devinfo->info[INFO_SIZE]);
|
||||
if (devinfo->info[INFO_ROTATION_RATE] != SMART_UNASSIGNED)
|
||||
log_tag("attr:%s:%s:rotationrate:%" PRIu64 "\n", devinfo->file, devinfo->name, devinfo->info[INFO_ROTATION_RATE]);
|
||||
if (devinfo->access_stat != 0)
|
||||
log_tag("attr:%s:%s:stat:%" PRIu64 "\n", devinfo->file, devinfo->name, devinfo->access_stat);
|
||||
}
|
||||
|
||||
static void state_smart_log(devinfo_t* devinfo, double afr)
|
||||
|
|
@ -854,6 +852,23 @@ static void state_probe(struct snapraid_state* state, tommy_list* low)
|
|||
printf("\n");
|
||||
}
|
||||
|
||||
static void state_stat(struct snapraid_state* state, tommy_list* high)
|
||||
{
|
||||
tommy_node* i;
|
||||
|
||||
(void)state;
|
||||
|
||||
/* compute lengths for padding */
|
||||
for (i = tommy_list_head(high); i != 0; i = i->next) {
|
||||
devinfo_t* devinfo = i->data;
|
||||
|
||||
/* print disk access_stat (not splitted) */
|
||||
if (devinfo->split == 0 && devinfo->access_stat != 0) {
|
||||
log_tag("stat:%s:%" PRIu64 "\n", devinfo->name, devinfo->access_stat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int devtest(tommy_list* high, tommy_list* low, int operation)
|
||||
{
|
||||
tommy_node* i;
|
||||
|
|
@ -955,6 +970,7 @@ void state_device(struct snapraid_state* state, int operation, tommy_list* filte
|
|||
/* for all parities */
|
||||
for (j = 0; j < state->level; ++j) {
|
||||
devinfo_t* entry;
|
||||
devinfo_t* split;
|
||||
unsigned s;
|
||||
|
||||
if (filterlist_disk != 0 && filter_path(filterlist_disk, 0, lev_config_name(j), 0) != 0)
|
||||
|
|
@ -963,6 +979,12 @@ void state_device(struct snapraid_state* state, int operation, tommy_list* filte
|
|||
for (s = 0; s < state->parity[j].split_mac; ++s) {
|
||||
entry = calloc_nofail(1, sizeof(devinfo_t));
|
||||
|
||||
/* keep track of the first split */
|
||||
if (s == 0)
|
||||
split = entry;
|
||||
else
|
||||
entry->split = split;
|
||||
|
||||
entry->device = state->parity[j].split_map[s].device;
|
||||
device_name_set(entry, lev_config_name(j), s);
|
||||
pathcpy(entry->mount, sizeof(entry->mount), state->parity[j].split_map[s].path);
|
||||
|
|
@ -1010,6 +1032,8 @@ void state_device(struct snapraid_state* state, int operation, tommy_list* filte
|
|||
}
|
||||
}
|
||||
|
||||
state_stat(state, &high);
|
||||
|
||||
if (operation == DEVICE_SMART)
|
||||
state_smart(state, state->level + tommy_list_count(&state->disklist), &low);
|
||||
|
||||
|
|
|
|||
|
|
@ -518,9 +518,10 @@ 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. */
|
||||
uint64_t smart[SMART_COUNT]; /**< SMART attributes. */
|
||||
uint64_t info[INFO_COUNT]; /**< Info attributes. */
|
||||
uint64_t access_stat; /**< Access stat. */
|
||||
uint64_t access_stat; /**< Access stat info. */
|
||||
char serial[SMART_MAX]; /**< Serial number. */
|
||||
char family[SMART_MAX]; /**< Family. */
|
||||
char model[SMART_MAX]; /**< Model. */
|
||||
|
|
|
|||
137
cmdline/unix.c
137
cmdline/unix.c
|
|
@ -1276,124 +1276,17 @@ static int devsmart(dev_t device, const char* name, const char* smartctl, uint64
|
|||
|
||||
/**
|
||||
* Compute disk usage by aggregating access statistics.
|
||||
*
|
||||
* This function determines whether a disk has been used by summing read
|
||||
* and write access counters from all related partitions and device holders.
|
||||
* Disk-level statistics are not used directly, as they may include
|
||||
* kernel-generated fake accesses that do not reflect real I/O activity.
|
||||
*
|
||||
* By walking the device hierarchy and accumulating per-device statistics,
|
||||
* the function provides a reliable measure of actual disk usage between
|
||||
* sampling points.
|
||||
*/
|
||||
#if HAVE_LINUX_DEVICE
|
||||
static int devstat_recurse(dev_t device, uint64_t* count)
|
||||
static int devstat(dev_t device, uint64_t* count)
|
||||
{
|
||||
char device_path[PATH_MAX];
|
||||
char path[PATH_MAX];
|
||||
char buf[512];
|
||||
char* device_file;
|
||||
int device_len;
|
||||
DIR* d;
|
||||
struct dirent* dd;
|
||||
int holders = 0;
|
||||
int partitions = 0;
|
||||
int token;
|
||||
int ret;
|
||||
char* i;
|
||||
|
||||
/* get the device name */
|
||||
if (devresolve(device, device_path, sizeof(device_path)) != 0)
|
||||
return -1;
|
||||
|
||||
device_len = strlen(device_path);
|
||||
if (device_len <= 5)
|
||||
return -1;
|
||||
device_file = device_path + 5; /* skip /dev/ */
|
||||
device_len -= 5;
|
||||
|
||||
pathprint(path, sizeof(path), "/sys/dev/block/%u:%u", major(device), minor(device));
|
||||
|
||||
/* check if there are partitions */
|
||||
d = opendir(path);
|
||||
if (d == 0)
|
||||
return -1;
|
||||
|
||||
while ((dd = readdir(d)) != 0) {
|
||||
dev_t subdev;
|
||||
|
||||
if (dd->d_name[0] == '.')
|
||||
continue;
|
||||
|
||||
if (strncmp(device_file, dd->d_name, device_len) != 0)
|
||||
continue;
|
||||
|
||||
pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/%s/dev", major(device), minor(device), dd->d_name);
|
||||
|
||||
subdev = devread(path);
|
||||
if (!subdev) {
|
||||
/* LCOV_EXCL_START */
|
||||
closedir(d);
|
||||
return -1;
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
if (devstat_recurse(subdev, count) != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
closedir(d);
|
||||
return -1;
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
++partitions;
|
||||
}
|
||||
|
||||
closedir(d);
|
||||
|
||||
/* stop if processed partitions */
|
||||
if (partitions != 0)
|
||||
return 0;
|
||||
|
||||
pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/holders", major(device), minor(device));
|
||||
|
||||
/* check if there are holders */
|
||||
d = opendir(path);
|
||||
if (d == 0)
|
||||
return -1;
|
||||
|
||||
while ((dd = readdir(d)) != 0) {
|
||||
dev_t subdev;
|
||||
|
||||
if (dd->d_name[0] == '.')
|
||||
continue;
|
||||
|
||||
|
||||
/* for each slave, expand the full potential tree */
|
||||
pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/holders/%s/dev", major(device), minor(device), dd->d_name);
|
||||
|
||||
subdev = devread(path);
|
||||
if (!subdev) {
|
||||
/* LCOV_EXCL_START */
|
||||
closedir(d);
|
||||
return -1;
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
if (devstat_recurse(subdev, count) != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
closedir(d);
|
||||
return -1;
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
++holders;
|
||||
}
|
||||
|
||||
closedir(d);
|
||||
|
||||
/* stop if processed holders */
|
||||
if (holders != 0)
|
||||
return 0;
|
||||
*count = 0;
|
||||
|
||||
pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/stat", major(device), minor(device));
|
||||
|
||||
|
|
@ -1452,12 +1345,6 @@ static int devstat_recurse(dev_t device, uint64_t* count)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int devstat(dev_t device, uint64_t* count)
|
||||
{
|
||||
*count = 0;
|
||||
return devstat_recurse(device, count);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
|
@ -1893,11 +1780,6 @@ static void* thread_smart(void* arg)
|
|||
*/
|
||||
devattr(devinfo->device, devinfo->info, devinfo->serial, devinfo->family, devinfo->model);
|
||||
|
||||
/*
|
||||
* Retrieve access stat for the device
|
||||
*/
|
||||
devstat(devinfo->device, &devinfo->access_stat);
|
||||
|
||||
return 0;
|
||||
#else
|
||||
(void)arg;
|
||||
|
|
@ -1927,11 +1809,6 @@ static void* thread_probe(void* arg)
|
|||
*/
|
||||
devattr(devinfo->device, devinfo->info, devinfo->serial, devinfo->family, devinfo->model);
|
||||
|
||||
/*
|
||||
* Retrieve access stat for the device
|
||||
*/
|
||||
devstat(devinfo->device, &devinfo->access_stat);
|
||||
|
||||
return 0;
|
||||
#else
|
||||
(void)arg;
|
||||
|
|
@ -2004,6 +1881,7 @@ int devquery(tommy_list* high, tommy_list* low, int operation, int others)
|
|||
for (i = tommy_list_head(high); i != 0; i = i->next) {
|
||||
devinfo_t* devinfo = i->data;
|
||||
uint64_t device = devinfo->device;
|
||||
uint64_t access_stat;
|
||||
|
||||
/* if the major is the null device, find the real one */
|
||||
if (major(device) == 0) {
|
||||
|
|
@ -2016,6 +1894,15 @@ int devquery(tommy_list* high, tommy_list* low, int operation, int others)
|
|||
}
|
||||
}
|
||||
|
||||
/* retrieve access stat for the high level device */
|
||||
if (devstat(device, &access_stat) == 0) {
|
||||
/* cumulate access stat in the first split */
|
||||
if (devinfo->split)
|
||||
devinfo->split->access_stat += access_stat;
|
||||
else
|
||||
devinfo->access_stat += access_stat;
|
||||
}
|
||||
|
||||
/* get the device file */
|
||||
if (devresolve(device, devinfo->file, sizeof(devinfo->file)) != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
|
|
|
|||
|
|
@ -1444,8 +1444,11 @@ attributes, but with the risk of spinning up all disks.
|
|||
.PP
|
||||
Note that a \`<disk_name>\` may be associated with more \`<device_file>\`,
|
||||
in case the logical disk uses more physical disks. In such a case,
|
||||
you\'ll see multiple tags for the same \`<disk_name>\` but with different
|
||||
\`<device_file>\`.
|
||||
you\'ll see multiple \`<attr>\` and \`<smart>\` tags for the same
|
||||
\`<disk_name>\` but with different \`<device_file>\`. The exception is the
|
||||
\`stat\` attrbute that is cumulative for all the devices part of the
|
||||
disk.
|
||||
.PP
|
||||
In case of split parity, the parity name is followed by \`/N\` to indicate
|
||||
the split index, where N starts from 0. The \`/0\` is always omitted.
|
||||
.SS Attributes
|
||||
|
|
@ -1597,8 +1600,10 @@ read.
|
|||
Logs a successful spin\-down operation initiated via the
|
||||
smartctl command.
|
||||
.TP
|
||||
.B attr:<device_file>:<disk_name>[/<split_index>]:stat:<access_number>
|
||||
Logs the total number of read and write accesses done on the disk.
|
||||
.B stat:<disk_name>:<access_number>
|
||||
Logs the total number of read and write accesses done on the
|
||||
disk. This is a cumulative value that include all the devices
|
||||
and split of the disk.
|
||||
Comparing this number at different times, you can detect if the
|
||||
disk was used during that time.
|
||||
.RS 4
|
||||
|
|
|
|||
|
|
@ -926,8 +926,11 @@ Command Smart And Probe Tags
|
|||
|
||||
Note that a `<disk_name>` may be associated with more `<device_file>`,
|
||||
in case the logical disk uses more physical disks. In such a case,
|
||||
you'll see multiple tags for the same `<disk_name>` but with different
|
||||
`<device_file>`.
|
||||
you'll see multiple `<attr>` and `<smart>` tags for the same
|
||||
`<disk_name>` but with different `<device_file>`. The exception is the
|
||||
`stat` attrbute that is cumulative for all the devices part of the
|
||||
disk.
|
||||
|
||||
In case of split parity, the parity name is followed by `/N` to indicate
|
||||
the split index, where N starts from 0. The `/0` is always omitted.
|
||||
|
||||
|
|
@ -1020,8 +1023,10 @@ Command Smart And Probe Tags
|
|||
Logs a successful spin-down operation initiated via the
|
||||
smartctl command.
|
||||
|
||||
=attr:<device_file>:<disk_name>[/<split_index>]:stat:<access_number>
|
||||
Logs the total number of read and write accesses done on the disk.
|
||||
=stat:<disk_name>:<access_number>
|
||||
Logs the total number of read and write accesses done on the
|
||||
disk. This is a cumulative value that include all the devices
|
||||
and split of the disk.
|
||||
Comparing this number at different times, you can detect if the
|
||||
disk was used during that time.
|
||||
|
||||
|
|
|
|||
|
|
@ -968,8 +968,11 @@ attributes, but with the risk of spinning up all disks.
|
|||
|
||||
Note that a `<disk_name>` may be associated with more `<device_file>`,
|
||||
in case the logical disk uses more physical disks. In such a case,
|
||||
you'll see multiple tags for the same `<disk_name>` but with different
|
||||
`<device_file>`.
|
||||
you'll see multiple `<attr>` and `<smart>` tags for the same
|
||||
`<disk_name>` but with different `<device_file>`. The exception is the
|
||||
`stat` attrbute that is cumulative for all the devices part of the
|
||||
disk.
|
||||
|
||||
In case of split parity, the parity name is followed by `/N` to indicate
|
||||
the split index, where N starts from 0. The `/0` is always omitted.
|
||||
|
||||
|
|
@ -1062,8 +1065,10 @@ Tags logging specific disk identification and attribute values.
|
|||
Logs a successful spin-down operation initiated via the
|
||||
smartctl command.
|
||||
|
||||
attr:<device_file>:<disk_name>[/<split_index>]:stat:<access_number>
|
||||
Logs the total number of read and write accesses done on the disk.
|
||||
stat:<disk_name>:<access_number>
|
||||
Logs the total number of read and write accesses done on the
|
||||
disk. This is a cumulative value that include all the devices
|
||||
and split of the disk.
|
||||
Comparing this number at different times, you can detect if the
|
||||
disk was used during that time.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue