summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Pitt <martin.pitt@ubuntu.com>2010-03-02 09:58:59 +0100
committerLennart Poettering <lennart@poettering.net>2011-10-11 23:38:52 +0200
commit33742d6e2865e46f0675c84884799d6bfe68b49a (patch)
tree014324a23ac793f83ddcf2792523138927ac9b8e
parent075ac78a8ba52632a46335e45bc02ae0c9736c15 (diff)
Speed up get_overall() and get_bad()
Instead of iterating through all attributes four times for an sk_disk_smart_get_overall() call, just do it once and store the results in SkDisk. This considerably speeds up libatasmart for common operations like smart_get_overall() and smart_get_bad(). https://bugs.freedesktop.org/show_bug.cgi?id=26834
-rw-r--r--atasmart.c97
1 files changed, 44 insertions, 53 deletions
diff --git a/atasmart.c b/atasmart.c
index c0c0ac3..8212059 100644
--- a/atasmart.c
+++ b/atasmart.c
@@ -122,6 +122,15 @@ struct SkDisk {
SkIdentifyParsedData identify_parsed_data;
SkSmartParsedData smart_parsed_data;
+ /* cache for commonly used attributes */
+ SkBool attribute_cache_valid:1;
+ SkBool bad_attribute_now:1;
+ SkBool bad_attribute_in_the_past:1;
+ SkBool reallocated_sector_count_found:1;
+ SkBool current_pending_sector_found:1;
+ uint64_t reallocated_sector_count;
+ uint64_t current_pending_sector;
+
void *blob;
};
@@ -2159,64 +2168,61 @@ int sk_disk_smart_get_power_cycle(SkDisk *d, uint64_t *count) {
return 0;
}
-static void reallocated_cb(SkDisk *d, const SkSmartAttributeParsedData *a, struct attr_helper *ah) {
-
- if (a->pretty_unit != SK_SMART_ATTRIBUTE_UNIT_SECTORS)
- return;
-
- if (!strcmp(a->name, "reallocated-sector-count")) {
+static void fill_cache_cb(SkDisk *d, const SkSmartAttributeParsedData *a, void* userdata) {
- if (!ah->found || a->pretty_value > *ah->value)
- *ah->value = a->pretty_value;
+ if (a->prefailure) {
+ if (a->good_now_valid && !a->good_now)
+ d->bad_attribute_now = TRUE;
- ah->found = TRUE;
+ if (a->good_in_the_past_valid && !a->good_in_the_past)
+ d->bad_attribute_in_the_past = TRUE;
}
-}
-
-static void pending_cb(SkDisk *d, const SkSmartAttributeParsedData *a, struct attr_helper *ah) {
if (a->pretty_unit != SK_SMART_ATTRIBUTE_UNIT_SECTORS)
return;
+ if (!strcmp(a->name, "reallocated-sector-count")) {
+ if (a->pretty_value > d->reallocated_sector_count)
+ d->reallocated_sector_count = a->pretty_value;
+ d->reallocated_sector_count_found = TRUE;
+ }
+
if (!strcmp(a->name, "current-pending-sector")) {
+ if (a->pretty_value > d->current_pending_sector)
+ d->current_pending_sector = a->pretty_value;
+ d->current_pending_sector_found = TRUE;
+ }
+}
- if (!ah->found || a->pretty_value > *ah->value)
- *ah->value = a->pretty_value;
+static int fill_cache(SkDisk *d) {
+ if (d->attribute_cache_valid)
+ return 0;
- ah->found = TRUE;
- }
+ if (sk_disk_smart_parse_attributes(d, (SkSmartAttributeParseCallback) fill_cache_cb, NULL) >= 0) {
+ d->attribute_cache_valid = TRUE;
+ return 0;
+ } else
+ return -1;
}
int sk_disk_smart_get_bad(SkDisk *d, uint64_t *sectors) {
- struct attr_helper ah1, ah2;
- uint64_t sectors1, sectors2;
-
assert(d);
assert(sectors);
- ah1.found = FALSE;
- ah1.value = &sectors1;
-
- if (sk_disk_smart_parse_attributes(d, (SkSmartAttributeParseCallback) reallocated_cb, &ah1) < 0)
+ if (fill_cache (d) < 0)
return -1;
- ah2.found = FALSE;
- ah2.value = &sectors2;
-
- if (sk_disk_smart_parse_attributes(d, (SkSmartAttributeParseCallback) pending_cb, &ah2) < 0)
- return -1;
-
- if (!ah1.found && !ah2.found) {
+ if (!d->reallocated_sector_count_found && !d->current_pending_sector_found) {
errno = ENOENT;
return -1;
}
- if (ah1.found && ah2.found)
- *sectors = sectors1 + sectors2;
- else if (ah1.found)
- *sectors = sectors1;
+ if (d->reallocated_sector_count_found && d->current_pending_sector_found)
+ *sectors = d->reallocated_sector_count + d->current_pending_sector;
+ else if (d->reallocated_sector_count_found)
+ *sectors = d->reallocated_sector_count;
else
- *sectors = sectors2;
+ *sectors = d->current_pending_sector;
return 0;
}
@@ -2240,16 +2246,6 @@ const char* sk_smart_overall_to_string(SkSmartOverall overall) {
return _P(map[overall]);
}
-static void bad_attribute_now_cb(SkDisk *d, const SkSmartAttributeParsedData *a, SkBool *good) {
- if (a->prefailure && a->good_now_valid && !a->good_now)
- *good = FALSE;
-}
-
-static void bad_attribute_in_the_past_cb(SkDisk *d, const SkSmartAttributeParsedData *a, SkBool *good) {
- if (a->prefailure && a->good_in_the_past_valid && !a->good_in_the_past)
- *good = FALSE;
-}
-
static uint64_t u64log2(uint64_t n) {
unsigned r;
@@ -2300,11 +2296,10 @@ int sk_disk_smart_get_overall(SkDisk *d, SkSmartOverall *overall) {
}
/* Third, check if any of the SMART attributes is bad */
- good = TRUE;
- if (sk_disk_smart_parse_attributes(d, (SkSmartAttributeParseCallback) bad_attribute_now_cb, &good) < 0)
+ if (fill_cache (d) < 0)
return -1;
- if (!good) {
+ if (d->bad_attribute_now) {
*overall = SK_SMART_OVERALL_BAD_ATTRIBUTE_NOW;
return 0;
}
@@ -2316,11 +2311,7 @@ int sk_disk_smart_get_overall(SkDisk *d, SkSmartOverall *overall) {
}
/* Fifth, check if any of the SMART attributes ever was bad */
- good = TRUE;
- if (sk_disk_smart_parse_attributes(d, (SkSmartAttributeParseCallback) bad_attribute_in_the_past_cb, &good) < 0)
- return -1;
-
- if (!good) {
+ if (d->bad_attribute_in_the_past) {
*overall = SK_SMART_OVERALL_BAD_ATTRIBUTE_IN_THE_PAST;
return 0;
}