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_types.h"
23#include "xfs_log.h"
24#include "xfs_trans.h"
25#include "xfs_sb.h"
26#include "xfs_ag.h"
27#include "xfs_mount.h"
28#include "xfs_bmap_btree.h"
29#include "xfs_alloc.h"
30#include "xfs_inode.h"
31#include "xfs_extent_busy.h"
32#include "xfs_trace.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)
164{
165 xfs_agblock_t fend = fbno + flen;
166 xfs_agblock_t bbno = busyp->bno;
167 xfs_agblock_t bend = bbno + busyp->length;
168
169
170
171
172
173
174 if (busyp->flags & XFS_EXTENT_BUSY_DISCARDED) {
175 spin_unlock(&pag->pagb_lock);
176 delay(1);
177 spin_lock(&pag->pagb_lock);
178 return false;
179 }
180
181
182
183
184
185
186
187
188
189 if (userdata)
190 goto out_force_log;
191
192 if (bbno < fbno && bend > fend) {
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210 goto out_force_log;
211 } else if (bbno >= fbno && bend <= fend) {
212
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 rb_erase(&busyp->rb_node, &pag->pagb_tree);
251 busyp->length = 0;
252 return false;
253 } else if (fend < bend) {
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268 busyp->bno = fend;
269 } else if (bbno < fbno) {
270
271
272
273
274
275
276
277
278
279
280
281
282
283 busyp->length = fbno - busyp->bno;
284 } else {
285 ASSERT(0);
286 }
287
288 trace_xfs_extent_busy_reuse(mp, pag->pag_agno, fbno, flen);
289 return true;
290
291out_force_log:
292 spin_unlock(&pag->pagb_lock);
293 xfs_log_force(mp, XFS_LOG_SYNC);
294 trace_xfs_extent_busy_force(mp, pag->pag_agno, fbno, flen);
295 spin_lock(&pag->pagb_lock);
296 return false;
297}
298
299
300
301
302
303void
304xfs_extent_busy_reuse(
305 struct xfs_mount *mp,
306 xfs_agnumber_t agno,
307 xfs_agblock_t fbno,
308 xfs_extlen_t flen,
309 bool userdata)
310{
311 struct xfs_perag *pag;
312 struct rb_node *rbp;
313
314 ASSERT(flen > 0);
315
316 pag = xfs_perag_get(mp, agno);
317 spin_lock(&pag->pagb_lock);
318restart:
319 rbp = pag->pagb_tree.rb_node;
320 while (rbp) {
321 struct xfs_extent_busy *busyp =
322 rb_entry(rbp, struct xfs_extent_busy, rb_node);
323 xfs_agblock_t bbno = busyp->bno;
324 xfs_agblock_t bend = bbno + busyp->length;
325
326 if (fbno + flen <= bbno) {
327 rbp = rbp->rb_left;
328 continue;
329 } else if (fbno >= bend) {
330 rbp = rbp->rb_right;
331 continue;
332 }
333
334 if (!xfs_extent_busy_update_extent(mp, pag, busyp, fbno, flen,
335 userdata))
336 goto restart;
337 }
338 spin_unlock(&pag->pagb_lock);
339 xfs_perag_put(pag);
340}
341
342
343
344
345
346
347
348void
349xfs_extent_busy_trim(
350 struct xfs_alloc_arg *args,
351 xfs_agblock_t bno,
352 xfs_extlen_t len,
353 xfs_agblock_t *rbno,
354 xfs_extlen_t *rlen)
355{
356 xfs_agblock_t fbno;
357 xfs_extlen_t flen;
358 struct rb_node *rbp;
359
360 ASSERT(len > 0);
361
362 spin_lock(&args->pag->pagb_lock);
363restart:
364 fbno = bno;
365 flen = len;
366 rbp = args->pag->pagb_tree.rb_node;
367 while (rbp && flen >= args->minlen) {
368 struct xfs_extent_busy *busyp =
369 rb_entry(rbp, struct xfs_extent_busy, rb_node);
370 xfs_agblock_t fend = fbno + flen;
371 xfs_agblock_t bbno = busyp->bno;
372 xfs_agblock_t bend = bbno + busyp->length;
373
374 if (fend <= bbno) {
375 rbp = rbp->rb_left;
376 continue;
377 } else if (fbno >= bend) {
378 rbp = rbp->rb_right;
379 continue;
380 }
381
382
383
384
385
386 if (!args->userdata &&
387 !(busyp->flags & XFS_EXTENT_BUSY_DISCARDED)) {
388 if (!xfs_extent_busy_update_extent(args->mp, args->pag,
389 busyp, fbno, flen,
390 false))
391 goto restart;
392 continue;
393 }
394
395 if (bbno <= fbno) {
396
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 if (fend <= bend)
426 goto fail;
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445 fbno = bend;
446 } else if (bend >= fend) {
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466 fend = bbno;
467 } else {
468
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 if (bbno - fbno >= args->maxlen) {
502
503 fend = bbno;
504 } else if (fend - bend >= args->maxlen * 4) {
505
506 fbno = bend;
507 } else if (bbno - fbno >= args->minlen) {
508
509 fend = bbno;
510 } else {
511 goto fail;
512 }
513 }
514
515 flen = fend - fbno;
516 }
517 spin_unlock(&args->pag->pagb_lock);
518
519 if (fbno != bno || flen != len) {
520 trace_xfs_extent_busy_trim(args->mp, args->agno, bno, len,
521 fbno, flen);
522 }
523 *rbno = fbno;
524 *rlen = flen;
525 return;
526fail:
527
528
529
530
531 spin_unlock(&args->pag->pagb_lock);
532 trace_xfs_extent_busy_trim(args->mp, args->agno, bno, len, fbno, 0);
533 *rbno = fbno;
534 *rlen = 0;
535}
536
537STATIC void
538xfs_extent_busy_clear_one(
539 struct xfs_mount *mp,
540 struct xfs_perag *pag,
541 struct xfs_extent_busy *busyp)
542{
543 if (busyp->length) {
544 trace_xfs_extent_busy_clear(mp, busyp->agno, busyp->bno,
545 busyp->length);
546 rb_erase(&busyp->rb_node, &pag->pagb_tree);
547 }
548
549 list_del_init(&busyp->list);
550 kmem_free(busyp);
551}
552
553
554
555
556
557
558void
559xfs_extent_busy_clear(
560 struct xfs_mount *mp,
561 struct list_head *list,
562 bool do_discard)
563{
564 struct xfs_extent_busy *busyp, *n;
565 struct xfs_perag *pag = NULL;
566 xfs_agnumber_t agno = NULLAGNUMBER;
567
568 list_for_each_entry_safe(busyp, n, list, list) {
569 if (busyp->agno != agno) {
570 if (pag) {
571 spin_unlock(&pag->pagb_lock);
572 xfs_perag_put(pag);
573 }
574 pag = xfs_perag_get(mp, busyp->agno);
575 spin_lock(&pag->pagb_lock);
576 agno = busyp->agno;
577 }
578
579 if (do_discard && busyp->length &&
580 !(busyp->flags & XFS_EXTENT_BUSY_SKIP_DISCARD))
581 busyp->flags = XFS_EXTENT_BUSY_DISCARDED;
582 else
583 xfs_extent_busy_clear_one(mp, pag, busyp);
584 }
585
586 if (pag) {
587 spin_unlock(&pag->pagb_lock);
588 xfs_perag_put(pag);
589 }
590}
591
592
593
594
595int
596xfs_extent_busy_ag_cmp(
597 void *priv,
598 struct list_head *a,
599 struct list_head *b)
600{
601 return container_of(a, struct xfs_extent_busy, list)->agno -
602 container_of(b, struct xfs_extent_busy, list)->agno;
603}
604