This source file includes following definitions.
- rf_CheckCvscanState
- rf_PriorityInsert
- rf_ReqInsert
- rf_ReqDequeue
- rf_ReBalance
- rf_Transfer
- rf_RealEnqueue
- rf_CvscanEnqueue
- rf_CvscanDequeue
- rf_CvscanPeek
- rf_CvscanConfigure
- rf_CvscanCreate
- rf_PrintCvscanQueue
- rf_CvscanPromote
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 #include "rf_types.h"
40 #include "rf_alloclist.h"
41 #include "rf_stripelocks.h"
42 #include "rf_layout.h"
43 #include "rf_diskqueue.h"
44 #include "rf_cvscan.h"
45 #include "rf_debugMem.h"
46 #include "rf_general.h"
47
48 void rf_CheckCvscanState(RF_CvscanHeader_t *, char *, int);
49 void rf_PriorityInsert(RF_DiskQueueData_t **, RF_DiskQueueData_t *);
50 void rf_ReqInsert(RF_DiskQueueData_t **, RF_DiskQueueData_t *,
51 RF_CvscanArmDir_t);
52 RF_DiskQueueData_t *rf_ReqDequeue(RF_DiskQueueData_t **);
53 void rf_ReBalance(RF_CvscanHeader_t *);
54 void rf_Transfer(RF_DiskQueueData_t **, RF_DiskQueueData_t **);
55 void rf_RealEnqueue(RF_CvscanHeader_t *, RF_DiskQueueData_t *);
56
57 #define DO_CHECK_STATE(_hdr_) rf_CheckCvscanState((_hdr_), __FILE__, __LINE__)
58
59 #define pri_ok(p) (((p) == RF_IO_NORMAL_PRIORITY) || \
60 ((p) == RF_IO_LOW_PRIORITY))
61
62
63 void
64 rf_CheckCvscanState(RF_CvscanHeader_t *hdr, char *file, int line)
65 {
66 long i, key;
67 RF_DiskQueueData_t *tmp;
68
69 if (hdr->left != (RF_DiskQueueData_t *) NULL)
70 RF_ASSERT(hdr->left->sectorOffset < hdr->cur_block);
71 for (key = hdr->cur_block, i = 0, tmp = hdr->left;
72 tmp != (RF_DiskQueueData_t *) NULL;
73 key = tmp->sectorOffset, i++, tmp = tmp->next)
74 RF_ASSERT(tmp->sectorOffset <= key
75 && tmp->priority == hdr->nxt_priority &&
76 pri_ok(tmp->priority));
77 RF_ASSERT(i == hdr->left_cnt);
78
79 for (key = hdr->cur_block, i = 0, tmp = hdr->right;
80 tmp != (RF_DiskQueueData_t *) NULL;
81 key = tmp->sectorOffset, i++, tmp = tmp->next) {
82 RF_ASSERT(key <= tmp->sectorOffset);
83 RF_ASSERT(tmp->priority == hdr->nxt_priority);
84 RF_ASSERT(pri_ok(tmp->priority));
85 }
86 RF_ASSERT(i == hdr->right_cnt);
87
88 for (key = hdr->nxt_priority - 1, tmp = hdr->burner;
89 tmp != (RF_DiskQueueData_t *) NULL;
90 key = tmp->priority, tmp = tmp->next) {
91 RF_ASSERT(tmp);
92 RF_ASSERT(hdr);
93 RF_ASSERT(pri_ok(tmp->priority));
94 RF_ASSERT(key >= tmp->priority);
95 RF_ASSERT(tmp->priority < hdr->nxt_priority);
96 }
97 }
98
99
100 void
101 rf_PriorityInsert(RF_DiskQueueData_t **list_ptr, RF_DiskQueueData_t *req)
102 {
103
104
105
106
107
108
109 for (; (*list_ptr) != (RF_DiskQueueData_t *) NULL &&
110 (*list_ptr)->priority > req->priority;
111 list_ptr = &((*list_ptr)->next)) {
112 }
113 req->next = (*list_ptr);
114 (*list_ptr) = req;
115 }
116
117
118 void
119 rf_ReqInsert(RF_DiskQueueData_t **list_ptr, RF_DiskQueueData_t *req,
120 RF_CvscanArmDir_t order)
121 {
122
123
124
125
126
127
128 for (; (*list_ptr) != (RF_DiskQueueData_t *) NULL &&
129 ((order == rf_cvscan_RIGHT && (*list_ptr)->sectorOffset <=
130 req->sectorOffset) || (order == rf_cvscan_LEFT &&
131 (*list_ptr)->sectorOffset > req->sectorOffset));
132 list_ptr = &((*list_ptr)->next)) {
133 }
134 req->next = (*list_ptr);
135 (*list_ptr) = req;
136 }
137
138
139 RF_DiskQueueData_t *
140 rf_ReqDequeue(RF_DiskQueueData_t **list_ptr)
141 {
142 RF_DiskQueueData_t *ret = (*list_ptr);
143 if ((*list_ptr) != (RF_DiskQueueData_t *) NULL) {
144 (*list_ptr) = (*list_ptr)->next;
145 }
146 return (ret);
147 }
148
149
150 void
151 rf_ReBalance(RF_CvscanHeader_t *hdr)
152 {
153
154 while (hdr->right != (RF_DiskQueueData_t *) NULL
155 && hdr->right->sectorOffset < hdr->cur_block) {
156 hdr->right_cnt--;
157 hdr->left_cnt++;
158 rf_ReqInsert(&hdr->left, rf_ReqDequeue(&hdr->right),
159 rf_cvscan_LEFT);
160 }
161
162 }
163
164
165 void
166 rf_Transfer(RF_DiskQueueData_t **to_list_ptr, RF_DiskQueueData_t **from_list_ptr)
167 {
168 RF_DiskQueueData_t *gp;
169 for (gp = (*from_list_ptr); gp != (RF_DiskQueueData_t *) NULL;) {
170 RF_DiskQueueData_t *p = gp->next;
171 rf_PriorityInsert(to_list_ptr, gp);
172 gp = p;
173 }
174 (*from_list_ptr) = (RF_DiskQueueData_t *) NULL;
175 }
176
177
178 void
179 rf_RealEnqueue(RF_CvscanHeader_t *hdr, RF_DiskQueueData_t *req)
180 {
181 RF_ASSERT(req->priority == RF_IO_NORMAL_PRIORITY ||
182 req->priority == RF_IO_LOW_PRIORITY);
183
184 DO_CHECK_STATE(hdr);
185 if (hdr->left_cnt == 0 && hdr->right_cnt == 0) {
186 hdr->nxt_priority = req->priority;
187 }
188 if (req->priority > hdr->nxt_priority) {
189
190
191
192 rf_Transfer(&hdr->burner, &hdr->left);
193 rf_Transfer(&hdr->burner, &hdr->right);
194 hdr->left_cnt = 0;
195 hdr->right_cnt = 0;
196 hdr->nxt_priority = req->priority;
197 }
198 if (req->priority < hdr->nxt_priority) {
199
200
201
202 rf_PriorityInsert(&hdr->burner, req);
203 } else {
204 if (req->sectorOffset < hdr->cur_block) {
205
206 rf_ReqInsert(&hdr->left, req, rf_cvscan_LEFT);
207 hdr->left_cnt++;
208 } else {
209
210 rf_ReqInsert(&hdr->right, req, rf_cvscan_RIGHT);
211 hdr->right_cnt++;
212 }
213 }
214 DO_CHECK_STATE(hdr);
215 }
216
217
218 void
219 rf_CvscanEnqueue(void *q_in, RF_DiskQueueData_t *elem, int priority)
220 {
221 RF_CvscanHeader_t *hdr = (RF_CvscanHeader_t *) q_in;
222 rf_RealEnqueue(hdr, elem );
223 }
224
225
226 RF_DiskQueueData_t *
227 rf_CvscanDequeue(void *q_in)
228 {
229 RF_CvscanHeader_t *hdr = (RF_CvscanHeader_t *) q_in;
230 long range, i, sum_dist_left, sum_dist_right;
231 RF_DiskQueueData_t *ret;
232 RF_DiskQueueData_t *tmp;
233
234 DO_CHECK_STATE(hdr);
235
236 if (hdr->left_cnt == 0 && hdr->right_cnt == 0)
237 return ((RF_DiskQueueData_t *) NULL);
238
239 range = RF_MIN(hdr->range_for_avg, RF_MIN(hdr->left_cnt,
240 hdr->right_cnt));
241 for (i = 0, tmp = hdr->left, sum_dist_left =
242 ((hdr->direction == rf_cvscan_RIGHT) ?
243 range * hdr->change_penalty : 0);
244 tmp != (RF_DiskQueueData_t *) NULL && i < range;
245 tmp = tmp->next, i++) {
246 sum_dist_left += hdr->cur_block - tmp->sectorOffset;
247 }
248 for (i = 0, tmp = hdr->right, sum_dist_right =
249 ((hdr->direction == rf_cvscan_LEFT) ?
250 range * hdr->change_penalty : 0);
251 tmp != (RF_DiskQueueData_t *) NULL && i < range;
252 tmp = tmp->next, i++) {
253 sum_dist_right += tmp->sectorOffset - hdr->cur_block;
254 }
255
256 if (hdr->right_cnt == 0 || sum_dist_left < sum_dist_right) {
257 hdr->direction = rf_cvscan_LEFT;
258 hdr->cur_block = hdr->left->sectorOffset + hdr->left->numSector;
259 hdr->left_cnt = RF_MAX(hdr->left_cnt - 1, 0);
260 tmp = hdr->left;
261 ret = (rf_ReqDequeue(&hdr->left)) ;
262 } else {
263 hdr->direction = rf_cvscan_RIGHT;
264 hdr->cur_block = hdr->right->sectorOffset +
265 hdr->right->numSector;
266 hdr->right_cnt = RF_MAX(hdr->right_cnt - 1, 0);
267 tmp = hdr->right;
268 ret = (rf_ReqDequeue(&hdr->right)) ;
269 }
270 rf_ReBalance(hdr);
271
272 if (hdr->left_cnt == 0 && hdr->right_cnt == 0
273 && hdr->burner != (RF_DiskQueueData_t *) NULL) {
274
275
276
277 RF_DiskQueueData_t *burner = hdr->burner;
278 hdr->nxt_priority = burner->priority;
279 while (burner != (RF_DiskQueueData_t *) NULL &&
280 burner->priority == hdr->nxt_priority) {
281 RF_DiskQueueData_t *next = burner->next;
282 rf_RealEnqueue(hdr, burner);
283 burner = next;
284 }
285 hdr->burner = burner;
286 }
287 DO_CHECK_STATE(hdr);
288 return (ret);
289 }
290
291
292 RF_DiskQueueData_t *
293 rf_CvscanPeek(void *q_in)
294 {
295 RF_CvscanHeader_t *hdr = (RF_CvscanHeader_t *) q_in;
296 long range, i, sum_dist_left, sum_dist_right;
297 RF_DiskQueueData_t *tmp, *headElement;
298
299 DO_CHECK_STATE(hdr);
300
301 if (hdr->left_cnt == 0 && hdr->right_cnt == 0)
302 headElement = NULL;
303 else {
304 range = RF_MIN(hdr->range_for_avg, RF_MIN(hdr->left_cnt,
305 hdr->right_cnt));
306 for (i = 0, tmp = hdr->left, sum_dist_left =
307 ((hdr->direction == rf_cvscan_RIGHT) ?
308 range * hdr->change_penalty : 0);
309 tmp != (RF_DiskQueueData_t *) NULL && i < range;
310 tmp = tmp->next, i++) {
311 sum_dist_left += hdr->cur_block - tmp->sectorOffset;
312 }
313 for (i = 0, tmp = hdr->right, sum_dist_right =
314 ((hdr->direction == rf_cvscan_LEFT) ?
315 range * hdr->change_penalty : 0);
316 tmp != (RF_DiskQueueData_t *) NULL && i < range;
317 tmp = tmp->next, i++) {
318 sum_dist_right += tmp->sectorOffset - hdr->cur_block;
319 }
320
321 if (hdr->right_cnt == 0 || sum_dist_left < sum_dist_right)
322 headElement = hdr->left;
323 else
324 headElement = hdr->right;
325 }
326 return (headElement);
327 }
328
329
330
331
332
333
334
335
336
337
338 int
339 rf_CvscanConfigure(void)
340 {
341 return (0);
342 }
343
344
345 void *
346 rf_CvscanCreate(RF_SectorCount_t sectPerDisk, RF_AllocListElem_t *clList,
347 RF_ShutdownList_t **listp)
348 {
349 RF_CvscanHeader_t *hdr;
350 long range = 2;
351 long penalty = sectPerDisk / 5;
352
353 RF_MallocAndAdd(hdr, sizeof(RF_CvscanHeader_t), (RF_CvscanHeader_t *),
354 clList);
355 bzero((char *) hdr, sizeof(RF_CvscanHeader_t));
356 hdr->range_for_avg = RF_MAX(range, 1);
357 hdr->change_penalty = RF_MAX(penalty, 0);
358 hdr->direction = rf_cvscan_RIGHT;
359 hdr->cur_block = 0;
360 hdr->left_cnt = hdr->right_cnt = 0;
361 hdr->left = hdr->right = (RF_DiskQueueData_t *) NULL;
362 hdr->burner = (RF_DiskQueueData_t *) NULL;
363 DO_CHECK_STATE(hdr);
364
365 return ((void *) hdr);
366 }
367
368
369 #if (defined(__NetBSD__) || defined(__OpenBSD__)) && defined(_KERNEL)
370
371 #else
372 void
373 rf_PrintCvscanQueue(RF_CvscanHeader_t *hdr)
374 {
375 RF_DiskQueueData_t *tmp;
376
377 printf("CVSCAN(%d,%d) at %d going %s\n",
378 (int) hdr->range_for_avg,
379 (int) hdr->change_penalty,
380 (int) hdr->cur_block,
381 (hdr->direction == rf_cvscan_LEFT) ? "LEFT" : "RIGHT");
382 printf("\tLeft(%d): ", hdr->left_cnt);
383 for (tmp = hdr->left; tmp != (RF_DiskQueueData_t *) NULL;
384 tmp = tmp->next)
385 printf("(%d,%ld,%d) ",
386 (int) tmp->sectorOffset,
387 (long) (tmp->sectorOffset + tmp->numSector),
388 tmp->priority);
389 printf("\n");
390 printf("\tRight(%d): ", hdr->right_cnt);
391 for (tmp = hdr->right; tmp != (RF_DiskQueueData_t *) NULL;
392 tmp = tmp->next)
393 printf("(%d,%ld,%d) ",
394 (int) tmp->sectorOffset,
395 (long) (tmp->sectorOffset + tmp->numSector),
396 tmp->priority);
397 printf("\n");
398 printf("\tBurner: ");
399 for (tmp = hdr->burner; tmp != (RF_DiskQueueData_t *) NULL;
400 tmp = tmp->next)
401 printf("(%d,%ld,%d) ",
402 (int) tmp->sectorOffset,
403 (long) (tmp->sectorOffset + tmp->numSector),
404 tmp->priority);
405 printf("\n");
406 }
407 #endif
408
409
410
411
412
413
414
415
416 int
417 rf_CvscanPromote(void *q_in, RF_StripeNum_t parityStripeID,
418 RF_ReconUnitNum_t which_ru)
419 {
420 RF_CvscanHeader_t *hdr = (RF_CvscanHeader_t *) q_in;
421 RF_DiskQueueData_t *trailer = NULL, *tmp = hdr->burner, *tlist = NULL;
422 int retval = 0;
423
424 DO_CHECK_STATE(hdr);
425 while (tmp) {
426 if (tmp->parityStripeID == parityStripeID &&
427 tmp->which_ru == which_ru) {
428 hdr->burner = tmp->next;
429 tmp->priority = RF_IO_NORMAL_PRIORITY;
430 tmp->next = tlist;
431 tlist = tmp;
432 tmp = hdr->burner;
433 } else
434 break;
435 }
436 if (tmp) {
437 trailer = tmp;
438 tmp = tmp->next;
439 }
440 while (tmp) {
441 if (tmp->parityStripeID == parityStripeID &&
442 tmp->which_ru == which_ru) {
443 trailer->next = tmp->next;
444 tmp->priority = RF_IO_NORMAL_PRIORITY;
445 tmp->next = tlist;
446 tlist = tmp;
447 tmp = trailer->next;
448 } else {
449 trailer = tmp;
450 tmp = tmp->next;
451 }
452 }
453 while (tlist) {
454 retval++;
455 tmp = tlist->next;
456 rf_RealEnqueue(hdr, tlist);
457 tlist = tmp;
458 }
459 RF_ASSERT(retval == 0 || retval == 1);
460 DO_CHECK_STATE((RF_CvscanHeader_t *) q_in);
461 return (retval);
462 }