1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include "xfs.h"
21#include "xfs_fs.h"
22#include "xfs_format.h"
23#include "xfs_log_format.h"
24#include "xfs_shared.h"
25#include "xfs_trans_resv.h"
26#include "xfs_sb.h"
27#include "xfs_mount.h"
28#include "xfs_alloc.h"
29#include "xfs_extent_busy.h"
30#include "xfs_trace.h"
31#include "xfs_trans.h"
32#include "xfs_log.h"
33
34void
35xfs_extent_busy_insert(
36 struct xfs_trans *tp,
37 xfs_agnumber_t agno,
38 xfs_agblock_t bno,
39 xfs_extlen_t len,
40 unsigned int flags)
41{
42 struct xfs_extent_busy *new;
43 struct xfs_extent_busy *busyp;
44 struct xfs_perag *pag;
45 struct rb_node **rbp;
46 struct rb_node *parent = NULL;
47
48 new = kmem_zalloc(sizeof(struct xfs_extent_busy), KM_MAYFAIL);
49 if (!new) {
50
51
52
53
54
55 trace_xfs_extent_busy_enomem(tp->t_mountp, agno, bno, len);
56 xfs_trans_set_sync(tp);
57 return;
58 }
59
60 new->agno = agno;
61 new->bno = bno;
62 new->length = len;
63 INIT_LIST_HEAD(&new->list);
64 new->flags = flags;
65
66
67 trace_xfs_extent_busy(tp->t_mountp, agno, bno, len);
68
69 pag = xfs_perag_get(tp->t_mountp, new->agno);
70 spin_lock(&pag->pagb_lock);
71 rbp = &pag->pagb_tree.rb_node;
72 while (*rbp) {
73 parent = *rbp;
74 busyp = rb_entry(parent, struct xfs_extent_busy, rb_node);
75
76 if (new->bno < busyp->bno) {
77 rbp = &(*rbp)->rb_left;
78 ASSERT(new->bno + new->length <= busyp->bno);
79 } else if (new->bno > busyp->bno) {
80 rbp = &(*rbp)->rb_right;
81 ASSERT(bno >= busyp->bno + busyp->length);
82 } else {
83 ASSERT(0);
84 }
85 }
86
87 rb_link_node(&new->rb_node, parent, rbp);
88 rb_insert_color(&new->rb_node, &pag->pagb_tree);
89
90 list_add(&new->list, &tp->t_busy);
91 spin_unlock(&pag->pagb_lock);
92 xfs_perag_put(pag);
93}
94
95
96
97
98
99
100
101
102
103
104int
105xfs_extent_busy_search(
106 struct xfs_mount *mp,
107 xfs_agnumber_t agno,
108 xfs_agblock_t bno,
109 xfs_extlen_t len)
110{
111 struct xfs_perag *pag;
112 struct rb_node *rbp;
113 struct xfs_extent_busy *busyp;
114 int match = 0;
115
116 pag = xfs_perag_get(mp, agno);
117 spin_lock(&pag->pagb_lock);
118
119 rbp = pag->pagb_tree.rb_node;
120
121
122 while (rbp) {
123 busyp = rb_entry(rbp, struct xfs_extent_busy, rb_node);
124 if (bno < busyp->bno) {
125
126 if (bno + len > busyp->bno)
127 match = -1;
128 rbp = rbp->rb_left;
129 } else if (bno > busyp->bno) {
130
131 if (bno < busyp->bno + busyp->length)
132 match = -1;
133 rbp = rbp->rb_right;
134 } else {
135
136 match = (busyp->length == len) ? 1 : -1;
137 break;
138 }
139 }
140 spin_unlock(&pag->pagb_lock);
141 xfs_perag_put(pag);
142 return match;
143}
144
145
146
147
148
149
150
151
152
153
154
155
156STATIC bool
157xfs_extent_busy_update_extent(
158 struct xfs_mount *mp,
159 struct xfs_perag *pag,
160 struct xfs_extent_busy *busyp,
161 xfs_agblock_t fbno,
162 xfs_extlen_t flen,
163 bool userdata) __releases(&pag->pagb_lock)
164 __acquires(&pag->pagb_lock)
165{
166 xfs_agblock_t fend = fbno + flen;
167 xfs_agblock_t bbno = busyp->bno;
168 xfs_agblock_t bend = bbno + busyp->length;
169
170
171
172
173
174
175 if (busyp->flags & XFS_EXTENT_BUSY_DISCARDED) {
176 spin_unlock(&pag->pagb_lock);
177 delay(1);
178 spin_lock(&pag->pagb_lock);
179 return false;
180 }
181
182
183
184
185
186
187
188
189
190 if (userdata)
191 goto out_force_log;
192
193 if (bbno < fbno && bend > fend) {
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211 goto out_force_log;
212 } else if (bbno >= fbno && bend <= fend) {
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251 rb_erase(&busyp->rb_node, &pag->pagb_tree);
252 busyp->length = 0;
253 return false;
254 } else if (fend < bend) {
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269 busyp->bno = fend;
270 } else if (bbno < fbno) {
271
272
273
274
275
276
277
278
279
280
281
282
283
284 busyp->length = fbno - busyp->bno;
285 } else {
286 ASSERT(0);
287 }
288
289 trace_xfs_extent_busy_reuse(mp, pag->pag_agno, fbno, flen);
290 return true;
291
292out_force_log:
293 spin_unlock(&pag->pagb_lock);
294 xfs_log_force(mp, XFS_LOG_SYNC);
295 trace_xfs_extent_busy_force(mp, pag->pag_agno, fbno, flen);
296 spin_lock(&pag->pagb_lock);
297 return false;
298}
299
300
301
302
303
304void
305xfs_extent_busy_reuse(
306 struct xfs_mount *mp,
307 xfs_agnumber_t agno,
308 xfs_agblock_t fbno,
309 xfs_extlen_t flen,
310 bool userdata)
311{
312 struct xfs_perag *pag;
313 struct rb_node *rbp;
314
315 ASSERT(flen > 0);
316
317 pag = xfs_perag_get(mp, agno);
318 spin_lock(&pag->pagb_lock);
319restart:
320 rbp = pag->pagb_tree.rb_node;
321 while (rbp) {
322 struct xfs_extent_busy *busyp =
323 rb_entry(rbp, struct xfs_extent_busy, rb_node);
324 xfs_agblock_t bbno = busyp->bno;
325 xfs_agblock_t bend = bbno + busyp->length;
326
327 if (fbno + flen <= bbno) {
328 rbp = rbp->rb_left;
329 continue;
330 } else if (fbno >= bend) {
331 rbp = rbp->rb_right;
332 continue;
333 }
334
335 if (!xfs_extent_busy_update_extent(mp, pag, busyp, fbno, flen,
336 userdata))
337 goto restart;
338 }
339 spin_unlock(&pag->pagb_lock);
340 xfs_perag_put(pag);
341}
342
343
344
345
346
347
348
349void
350xfs_extent_busy_trim(
351 struct xfs_alloc_arg *args,
352 xfs_agblock_t bno,
353 xfs_extlen_t len,
354 xfs_agblock_t *rbno,
355 xfs_extlen_t *rlen)
356{
357 xfs_agblock_t fbno;
358 xfs_extlen_t flen;
359 struct rb_node *rbp;
360
361 ASSERT(len > 0);
362
363 spin_lock(&args->pag->pagb_lock);
364restart:
365 fbno = bno;
366 flen = len;
367 rbp = args->pag->pagb_tree.rb_node;
368 while (rbp && flen >= args->minlen) {
369 struct xfs_extent_busy *busyp =
370 rb_entry(rbp, struct xfs_extent_busy, rb_node);
371 xfs_agblock_t fend = fbno + flen;
372 xfs_agblock_t bbno = busyp->bno;
373 xfs_agblock_t bend = bbno + busyp->length;
374
375 if (fend <= bbno) {
376 rbp = rbp->rb_left;
377 continue;
378 } else if (fbno >= bend) {
379 rbp = rbp->rb_right;
380 continue;
381 }
382
383
384
385
386
387 if (!args->userdata &&
388 !(busyp->flags & XFS_EXTENT_BUSY_DISCARDED)) {
389 if (!xfs_extent_busy_update_extent(args->mp, args->pag,
390 busyp, fbno, flen,
391 false))
392 goto restart;
393 continue;
394 }
395
396 if (bbno <= fbno) {
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426 if (fend <= bend)
427 goto fail;
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446 fbno = bend;
447 } else if (bend >= fend) {
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467 fend = bbno;
468 } else {
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502 if (bbno - fbno >= args->maxlen) {
503
504 fend = bbno;
505 } else if (fend - bend >= args->maxlen * 4) {
506
507 fbno = bend;
508 } else if (bbno - fbno >= args->minlen) {
509
510 fend = bbno;
511 } else {
512 goto fail;
513 }
514 }
515
516 flen = fend - fbno;
517 }
518 spin_unlock(&args->pag->pagb_lock);
519
520 if (fbno != bno || flen != len) {
521 trace_xfs_extent_busy_trim(args->mp, args->agno, bno, len,
522 fbno, flen);
523 }
524 *rbno = fbno;
525 *rlen = flen;
526 return;
527fail:
528
529
530
531
532 spin_unlock(&args->pag->pagb_lock);
533 trace_xfs_extent_busy_trim(args->mp, args->agno, bno, len, fbno, 0);
534 *rbno = fbno;
535 *rlen = 0;
536}
537
538STATIC void
539xfs_extent_busy_clear_one(
540 struct xfs_mount *mp,
541 struct xfs_perag *pag,
542 struct xfs_extent_busy *busyp)
543{
544 if (busyp->length) {
545 trace_xfs_extent_busy_clear(mp, busyp->agno, busyp->bno,
546 busyp->length);
547 rb_erase(&busyp->rb_node, &pag->pagb_tree);
548 }
549
550 list_del_init(&busyp->list);
551 kmem_free(busyp);
552}
553
554
555
556
557
558
559void
560xfs_extent_busy_clear(
561 struct xfs_mount *mp,
562 struct list_head *list,
563 bool do_discard)
564{
565 struct xfs_extent_busy *busyp, *n;
566 struct xfs_perag *pag = NULL;
567 xfs_agnumber_t agno = NULLAGNUMBER;
568
569 list_for_each_entry_safe(busyp, n, list, list) {
570 if (busyp->agno != agno) {
571 if (pag) {
572 spin_unlock(&pag->pagb_lock);
573 xfs_perag_put(pag);
574 }
575 pag = xfs_perag_get(mp, busyp->agno);
576 spin_lock(&pag->pagb_lock);
577 agno = busyp->agno;
578 }
579
580 if (do_discard && busyp->length &&
581 !(busyp->flags & XFS_EXTENT_BUSY_SKIP_DISCARD))
582 busyp->flags = XFS_EXTENT_BUSY_DISCARDED;
583 else
584 xfs_extent_busy_clear_one(mp, pag, busyp);
585 }
586
587 if (pag) {
588 spin_unlock(&pag->pagb_lock);
589 xfs_perag_put(pag);
590 }
591}
592
593
594
595
596int
597xfs_extent_busy_ag_cmp(
598 void *priv,
599 struct list_head *a,
600 struct list_head *b)
601{
602 return container_of(a, struct xfs_extent_busy, list)->agno -
603 container_of(b, struct xfs_extent_busy, list)->agno;
604}
605