0 | |
From 2b24de1dc2314c28bce6e89050f16aa0dcac8031 Mon Sep 17 00:00:00 2001
|
1 | |
From: Martin Pitt <martin.pitt@ubuntu.com>
|
2 | |
Date: Tue, 2 Mar 2010 09:58:59 +0100
|
3 | |
Subject: [PATCH 1/2] Speed up get_overall() and get_bad()
|
4 | |
|
5 | |
Instead of iterating through all attributes four times for an
|
6 | |
sk_disk_smart_get_overall() call, just do it once and store the results in
|
7 | |
SkDisk. This considerably speeds up libatasmart for common operations like
|
8 | |
smart_get_overall() and smart_get_bad().
|
9 | |
|
10 | |
https://bugs.freedesktop.org/show_bug.cgi?id=26834
|
11 | |
---
|
12 | |
atasmart.c | 97 +++++++++++++++++++++++++++--------------------------------
|
13 | |
1 files changed, 44 insertions(+), 53 deletions(-)
|
14 | |
|
15 | |
diff --git a/atasmart.c b/atasmart.c
|
16 | |
index a4b60c0..13d55ff 100644
|
17 | |
--- a/atasmart.c
|
18 | |
+++ b/atasmart.c
|
19 | |
@@ -122,6 +122,15 @@ struct SkDisk {
|
20 | |
SkIdentifyParsedData identify_parsed_data;
|
21 | |
SkSmartParsedData smart_parsed_data;
|
22 | |
|
23 | |
+ /* cache for commonly used attributes */
|
24 | |
+ SkBool attribute_cache_valid:1;
|
25 | |
+ SkBool bad_attribute_now:1;
|
26 | |
+ SkBool bad_attribute_in_the_past:1;
|
27 | |
+ SkBool reallocated_sector_count_found:1;
|
28 | |
+ SkBool current_pending_sector_found:1;
|
29 | |
+ uint64_t reallocated_sector_count;
|
30 | |
+ uint64_t current_pending_sector;
|
31 | |
+
|
32 | |
void *blob;
|
33 | |
};
|
34 | |
|
35 | |
@@ -2015,64 +2024,61 @@ int sk_disk_smart_get_power_cycle(SkDisk *d, uint64_t *count) {
|
36 | |
return 0;
|
37 | |
}
|
38 | |
|
39 | |
-static void reallocated_cb(SkDisk *d, const SkSmartAttributeParsedData *a, struct attr_helper *ah) {
|
40 | |
-
|
41 | |
- if (a->pretty_unit != SK_SMART_ATTRIBUTE_UNIT_SECTORS)
|
42 | |
- return;
|
43 | |
-
|
44 | |
- if (!strcmp(a->name, "reallocated-sector-count")) {
|
45 | |
+static void fill_cache_cb(SkDisk *d, const SkSmartAttributeParsedData *a, void* userdata) {
|
46 | |
|
47 | |
- if (!ah->found || a->pretty_value > *ah->value)
|
48 | |
- *ah->value = a->pretty_value;
|
49 | |
+ if (a->prefailure) {
|
50 | |
+ if (a->good_now_valid && !a->good_now)
|
51 | |
+ d->bad_attribute_now = TRUE;
|
52 | |
|
53 | |
- ah->found = TRUE;
|
54 | |
+ if (a->good_in_the_past_valid && !a->good_in_the_past)
|
55 | |
+ d->bad_attribute_in_the_past = TRUE;
|
56 | |
}
|
57 | |
-}
|
58 | |
-
|
59 | |
-static void pending_cb(SkDisk *d, const SkSmartAttributeParsedData *a, struct attr_helper *ah) {
|
60 | |
|
61 | |
if (a->pretty_unit != SK_SMART_ATTRIBUTE_UNIT_SECTORS)
|
62 | |
return;
|
63 | |
|
64 | |
+ if (!strcmp(a->name, "reallocated-sector-count")) {
|
65 | |
+ if (a->pretty_value > d->reallocated_sector_count)
|
66 | |
+ d->reallocated_sector_count = a->pretty_value;
|
67 | |
+ d->reallocated_sector_count_found = TRUE;
|
68 | |
+ }
|
69 | |
+
|
70 | |
if (!strcmp(a->name, "current-pending-sector")) {
|
71 | |
+ if (a->pretty_value > d->current_pending_sector)
|
72 | |
+ d->current_pending_sector = a->pretty_value;
|
73 | |
+ d->current_pending_sector_found = TRUE;
|
74 | |
+ }
|
75 | |
+}
|
76 | |
|
77 | |
- if (!ah->found || a->pretty_value > *ah->value)
|
78 | |
- *ah->value = a->pretty_value;
|
79 | |
+static int fill_cache(SkDisk *d) {
|
80 | |
+ if (d->attribute_cache_valid)
|
81 | |
+ return 0;
|
82 | |
|
83 | |
- ah->found = TRUE;
|
84 | |
- }
|
85 | |
+ if (sk_disk_smart_parse_attributes(d, (SkSmartAttributeParseCallback) fill_cache_cb, NULL) >= 0) {
|
86 | |
+ d->attribute_cache_valid = TRUE;
|
87 | |
+ return 0;
|
88 | |
+ } else
|
89 | |
+ return -1;
|
90 | |
}
|
91 | |
|
92 | |
int sk_disk_smart_get_bad(SkDisk *d, uint64_t *sectors) {
|
93 | |
- struct attr_helper ah1, ah2;
|
94 | |
- uint64_t sectors1, sectors2;
|
95 | |
-
|
96 | |
assert(d);
|
97 | |
assert(sectors);
|
98 | |
|
99 | |
- ah1.found = FALSE;
|
100 | |
- ah1.value = §ors1;
|
101 | |
-
|
102 | |
- if (sk_disk_smart_parse_attributes(d, (SkSmartAttributeParseCallback) reallocated_cb, &ah1) < 0)
|
103 | |
+ if (fill_cache (d) < 0)
|
104 | |
return -1;
|
105 | |
|
106 | |
- ah2.found = FALSE;
|
107 | |
- ah2.value = §ors2;
|
108 | |
-
|
109 | |
- if (sk_disk_smart_parse_attributes(d, (SkSmartAttributeParseCallback) pending_cb, &ah2) < 0)
|
110 | |
- return -1;
|
111 | |
-
|
112 | |
- if (!ah1.found && !ah2.found) {
|
113 | |
+ if (!d->reallocated_sector_count_found && !d->current_pending_sector_found) {
|
114 | |
errno = ENOENT;
|
115 | |
return -1;
|
116 | |
}
|
117 | |
|
118 | |
- if (ah1.found && ah2.found)
|
119 | |
- *sectors = sectors1 + sectors2;
|
120 | |
- else if (ah1.found)
|
121 | |
- *sectors = sectors1;
|
122 | |
+ if (d->reallocated_sector_count_found && d->current_pending_sector_found)
|
123 | |
+ *sectors = d->reallocated_sector_count + d->current_pending_sector;
|
124 | |
+ else if (d->reallocated_sector_count_found)
|
125 | |
+ *sectors = d->reallocated_sector_count;
|
126 | |
else
|
127 | |
- *sectors = sectors2;
|
128 | |
+ *sectors = d->current_pending_sector;
|
129 | |
|
130 | |
return 0;
|
131 | |
}
|
132 | |
@@ -2096,16 +2102,6 @@ const char* sk_smart_overall_to_string(SkSmartOverall overall) {
|
133 | |
return _P(map[overall]);
|
134 | |
}
|
135 | |
|
136 | |
-static void bad_attribute_now_cb(SkDisk *d, const SkSmartAttributeParsedData *a, SkBool *good) {
|
137 | |
- if (a->prefailure && a->good_now_valid && !a->good_now)
|
138 | |
- *good = FALSE;
|
139 | |
-}
|
140 | |
-
|
141 | |
-static void bad_attribute_in_the_past_cb(SkDisk *d, const SkSmartAttributeParsedData *a, SkBool *good) {
|
142 | |
- if (a->prefailure && a->good_in_the_past_valid && !a->good_in_the_past)
|
143 | |
- *good = FALSE;
|
144 | |
-}
|
145 | |
-
|
146 | |
static uint64_t u64log2(uint64_t n) {
|
147 | |
unsigned r;
|
148 | |
|
149 | |
@@ -2156,11 +2152,10 @@ int sk_disk_smart_get_overall(SkDisk *d, SkSmartOverall *overall) {
|
150 | |
}
|
151 | |
|
152 | |
/* Third, check if any of the SMART attributes is bad */
|
153 | |
- good = TRUE;
|
154 | |
- if (sk_disk_smart_parse_attributes(d, (SkSmartAttributeParseCallback) bad_attribute_now_cb, &good) < 0)
|
155 | |
+ if (fill_cache (d) < 0)
|
156 | |
return -1;
|
157 | |
|
158 | |
- if (!good) {
|
159 | |
+ if (d->bad_attribute_now) {
|
160 | |
*overall = SK_SMART_OVERALL_BAD_ATTRIBUTE_NOW;
|
161 | |
return 0;
|
162 | |
}
|
163 | |
@@ -2172,11 +2167,7 @@ int sk_disk_smart_get_overall(SkDisk *d, SkSmartOverall *overall) {
|
164 | |
}
|
165 | |
|
166 | |
/* Fifth, check if any of the SMART attributes ever was bad */
|
167 | |
- good = TRUE;
|
168 | |
- if (sk_disk_smart_parse_attributes(d, (SkSmartAttributeParseCallback) bad_attribute_in_the_past_cb, &good) < 0)
|
169 | |
- return -1;
|
170 | |
-
|
171 | |
- if (!good) {
|
172 | |
+ if (d->bad_attribute_in_the_past) {
|
173 | |
*overall = SK_SMART_OVERALL_BAD_ATTRIBUTE_IN_THE_PAST;
|
174 | |
return 0;
|
175 | |
}
|
176 | |
--
|
177 | |
1.7.0
|
178 | |
|