|
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 |
|