1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include "xfs.h"
19#include "xfs_fs.h"
20#include "xfs_types.h"
21#include "xfs_bit.h"
22#include "xfs_log.h"
23#include "xfs_inum.h"
24#include "xfs_trans.h"
25#include "xfs_sb.h"
26#include "xfs_ag.h"
27#include "xfs_dir2.h"
28#include "xfs_dmapi.h"
29#include "xfs_mount.h"
30#include "xfs_bmap_btree.h"
31#include "xfs_alloc_btree.h"
32#include "xfs_ialloc_btree.h"
33#include "xfs_dir2_sf.h"
34#include "xfs_attr_sf.h"
35#include "xfs_dinode.h"
36#include "xfs_inode.h"
37#include "xfs_btree.h"
38#include "xfs_ialloc.h"
39#include "xfs_alloc.h"
40#include "xfs_error.h"
41
42
43#define XFS_ABSDIFF(a,b) (((a) <= (b)) ? ((b) - (a)) : ((a) - (b)))
44
45#define XFSA_FIXUP_BNO_OK 1
46#define XFSA_FIXUP_CNT_OK 2
47
48STATIC int
49xfs_alloc_search_busy(xfs_trans_t *tp,
50 xfs_agnumber_t agno,
51 xfs_agblock_t bno,
52 xfs_extlen_t len);
53
54#if defined(XFS_ALLOC_TRACE)
55ktrace_t *xfs_alloc_trace_buf;
56
57#define TRACE_ALLOC(s,a) \
58 xfs_alloc_trace_alloc(fname, s, a, __LINE__)
59#define TRACE_FREE(s,a,b,x,f) \
60 xfs_alloc_trace_free(fname, s, mp, a, b, x, f, __LINE__)
61#define TRACE_MODAGF(s,a,f) \
62 xfs_alloc_trace_modagf(fname, s, mp, a, f, __LINE__)
63#define TRACE_BUSY(fname,s,ag,agb,l,sl,tp) \
64 xfs_alloc_trace_busy(fname, s, mp, ag, agb, l, sl, tp, XFS_ALLOC_KTRACE_BUSY, __LINE__)
65#define TRACE_UNBUSY(fname,s,ag,sl,tp) \
66 xfs_alloc_trace_busy(fname, s, mp, ag, -1, -1, sl, tp, XFS_ALLOC_KTRACE_UNBUSY, __LINE__)
67#define TRACE_BUSYSEARCH(fname,s,ag,agb,l,sl,tp) \
68 xfs_alloc_trace_busy(fname, s, mp, ag, agb, l, sl, tp, XFS_ALLOC_KTRACE_BUSYSEARCH, __LINE__)
69#else
70#define TRACE_ALLOC(s,a)
71#define TRACE_FREE(s,a,b,x,f)
72#define TRACE_MODAGF(s,a,f)
73#define TRACE_BUSY(s,a,ag,agb,l,sl,tp)
74#define TRACE_UNBUSY(fname,s,ag,sl,tp)
75#define TRACE_BUSYSEARCH(fname,s,ag,agb,l,sl,tp)
76#endif
77
78
79
80
81
82STATIC int xfs_alloc_ag_vextent_exact(xfs_alloc_arg_t *);
83STATIC int xfs_alloc_ag_vextent_near(xfs_alloc_arg_t *);
84STATIC int xfs_alloc_ag_vextent_size(xfs_alloc_arg_t *);
85STATIC int xfs_alloc_ag_vextent_small(xfs_alloc_arg_t *,
86 xfs_btree_cur_t *, xfs_agblock_t *, xfs_extlen_t *, int *);
87
88
89
90
91
92
93
94
95
96STATIC int
97xfs_alloc_compute_aligned(
98 xfs_agblock_t foundbno,
99 xfs_extlen_t foundlen,
100 xfs_extlen_t alignment,
101 xfs_extlen_t minlen,
102 xfs_agblock_t *resbno,
103 xfs_extlen_t *reslen)
104{
105 xfs_agblock_t bno;
106 xfs_extlen_t diff;
107 xfs_extlen_t len;
108
109 if (alignment > 1 && foundlen >= minlen) {
110 bno = roundup(foundbno, alignment);
111 diff = bno - foundbno;
112 len = diff >= foundlen ? 0 : foundlen - diff;
113 } else {
114 bno = foundbno;
115 len = foundlen;
116 }
117 *resbno = bno;
118 *reslen = len;
119 return len >= minlen;
120}
121
122
123
124
125
126STATIC xfs_extlen_t
127xfs_alloc_compute_diff(
128 xfs_agblock_t wantbno,
129 xfs_extlen_t wantlen,
130 xfs_extlen_t alignment,
131 xfs_agblock_t freebno,
132 xfs_extlen_t freelen,
133 xfs_agblock_t *newbnop)
134{
135 xfs_agblock_t freeend;
136 xfs_agblock_t newbno1;
137 xfs_agblock_t newbno2;
138 xfs_extlen_t newlen1=0;
139 xfs_extlen_t newlen2=0;
140 xfs_agblock_t wantend;
141
142 ASSERT(freelen >= wantlen);
143 freeend = freebno + freelen;
144 wantend = wantbno + wantlen;
145 if (freebno >= wantbno) {
146 if ((newbno1 = roundup(freebno, alignment)) >= freeend)
147 newbno1 = NULLAGBLOCK;
148 } else if (freeend >= wantend && alignment > 1) {
149 newbno1 = roundup(wantbno, alignment);
150 newbno2 = newbno1 - alignment;
151 if (newbno1 >= freeend)
152 newbno1 = NULLAGBLOCK;
153 else
154 newlen1 = XFS_EXTLEN_MIN(wantlen, freeend - newbno1);
155 if (newbno2 < freebno)
156 newbno2 = NULLAGBLOCK;
157 else
158 newlen2 = XFS_EXTLEN_MIN(wantlen, freeend - newbno2);
159 if (newbno1 != NULLAGBLOCK && newbno2 != NULLAGBLOCK) {
160 if (newlen1 < newlen2 ||
161 (newlen1 == newlen2 &&
162 XFS_ABSDIFF(newbno1, wantbno) >
163 XFS_ABSDIFF(newbno2, wantbno)))
164 newbno1 = newbno2;
165 } else if (newbno2 != NULLAGBLOCK)
166 newbno1 = newbno2;
167 } else if (freeend >= wantend) {
168 newbno1 = wantbno;
169 } else if (alignment > 1) {
170 newbno1 = roundup(freeend - wantlen, alignment);
171 if (newbno1 > freeend - wantlen &&
172 newbno1 - alignment >= freebno)
173 newbno1 -= alignment;
174 else if (newbno1 >= freeend)
175 newbno1 = NULLAGBLOCK;
176 } else
177 newbno1 = freeend - wantlen;
178 *newbnop = newbno1;
179 return newbno1 == NULLAGBLOCK ? 0 : XFS_ABSDIFF(newbno1, wantbno);
180}
181
182
183
184
185
186
187
188STATIC void
189xfs_alloc_fix_len(
190 xfs_alloc_arg_t *args)
191{
192 xfs_extlen_t k;
193 xfs_extlen_t rlen;
194
195 ASSERT(args->mod < args->prod);
196 rlen = args->len;
197 ASSERT(rlen >= args->minlen);
198 ASSERT(rlen <= args->maxlen);
199 if (args->prod <= 1 || rlen < args->mod || rlen == args->maxlen ||
200 (args->mod == 0 && rlen < args->prod))
201 return;
202 k = rlen % args->prod;
203 if (k == args->mod)
204 return;
205 if (k > args->mod) {
206 if ((int)(rlen = rlen - k - args->mod) < (int)args->minlen)
207 return;
208 } else {
209 if ((int)(rlen = rlen - args->prod - (args->mod - k)) <
210 (int)args->minlen)
211 return;
212 }
213 ASSERT(rlen >= args->minlen);
214 ASSERT(rlen <= args->maxlen);
215 args->len = rlen;
216}
217
218
219
220
221
222STATIC int
223xfs_alloc_fix_minleft(
224 xfs_alloc_arg_t *args)
225{
226 xfs_agf_t *agf;
227 int diff;
228
229 if (args->minleft == 0)
230 return 1;
231 agf = XFS_BUF_TO_AGF(args->agbp);
232 diff = be32_to_cpu(agf->agf_freeblks)
233 + be32_to_cpu(agf->agf_flcount)
234 - args->len - args->minleft;
235 if (diff >= 0)
236 return 1;
237 args->len += diff;
238 if (args->len >= args->minlen)
239 return 1;
240 args->agbno = NULLAGBLOCK;
241 return 0;
242}
243
244
245
246
247
248
249
250
251STATIC int
252xfs_alloc_fixup_trees(
253 xfs_btree_cur_t *cnt_cur,
254 xfs_btree_cur_t *bno_cur,
255 xfs_agblock_t fbno,
256 xfs_extlen_t flen,
257 xfs_agblock_t rbno,
258 xfs_extlen_t rlen,
259 int flags)
260{
261 int error;
262 int i;
263 xfs_agblock_t nfbno1;
264 xfs_agblock_t nfbno2;
265 xfs_extlen_t nflen1=0;
266 xfs_extlen_t nflen2=0;
267
268
269
270
271 if (flags & XFSA_FIXUP_CNT_OK) {
272#ifdef DEBUG
273 if ((error = xfs_alloc_get_rec(cnt_cur, &nfbno1, &nflen1, &i)))
274 return error;
275 XFS_WANT_CORRUPTED_RETURN(
276 i == 1 && nfbno1 == fbno && nflen1 == flen);
277#endif
278 } else {
279 if ((error = xfs_alloc_lookup_eq(cnt_cur, fbno, flen, &i)))
280 return error;
281 XFS_WANT_CORRUPTED_RETURN(i == 1);
282 }
283
284
285
286 if (flags & XFSA_FIXUP_BNO_OK) {
287#ifdef DEBUG
288 if ((error = xfs_alloc_get_rec(bno_cur, &nfbno1, &nflen1, &i)))
289 return error;
290 XFS_WANT_CORRUPTED_RETURN(
291 i == 1 && nfbno1 == fbno && nflen1 == flen);
292#endif
293 } else {
294 if ((error = xfs_alloc_lookup_eq(bno_cur, fbno, flen, &i)))
295 return error;
296 XFS_WANT_CORRUPTED_RETURN(i == 1);
297 }
298#ifdef DEBUG
299 {
300 xfs_alloc_block_t *bnoblock;
301 xfs_alloc_block_t *cntblock;
302
303 if (bno_cur->bc_nlevels == 1 &&
304 cnt_cur->bc_nlevels == 1) {
305 bnoblock = XFS_BUF_TO_ALLOC_BLOCK(bno_cur->bc_bufs[0]);
306 cntblock = XFS_BUF_TO_ALLOC_BLOCK(cnt_cur->bc_bufs[0]);
307 XFS_WANT_CORRUPTED_RETURN(
308 be16_to_cpu(bnoblock->bb_numrecs) ==
309 be16_to_cpu(cntblock->bb_numrecs));
310 }
311 }
312#endif
313
314
315
316
317
318 if (rbno == fbno && rlen == flen)
319 nfbno1 = nfbno2 = NULLAGBLOCK;
320 else if (rbno == fbno) {
321 nfbno1 = rbno + rlen;
322 nflen1 = flen - rlen;
323 nfbno2 = NULLAGBLOCK;
324 } else if (rbno + rlen == fbno + flen) {
325 nfbno1 = fbno;
326 nflen1 = flen - rlen;
327 nfbno2 = NULLAGBLOCK;
328 } else {
329 nfbno1 = fbno;
330 nflen1 = rbno - fbno;
331 nfbno2 = rbno + rlen;
332 nflen2 = (fbno + flen) - nfbno2;
333 }
334
335
336
337 if ((error = xfs_alloc_delete(cnt_cur, &i)))
338 return error;
339 XFS_WANT_CORRUPTED_RETURN(i == 1);
340
341
342
343 if (nfbno1 != NULLAGBLOCK) {
344 if ((error = xfs_alloc_lookup_eq(cnt_cur, nfbno1, nflen1, &i)))
345 return error;
346 XFS_WANT_CORRUPTED_RETURN(i == 0);
347 if ((error = xfs_alloc_insert(cnt_cur, &i)))
348 return error;
349 XFS_WANT_CORRUPTED_RETURN(i == 1);
350 }
351 if (nfbno2 != NULLAGBLOCK) {
352 if ((error = xfs_alloc_lookup_eq(cnt_cur, nfbno2, nflen2, &i)))
353 return error;
354 XFS_WANT_CORRUPTED_RETURN(i == 0);
355 if ((error = xfs_alloc_insert(cnt_cur, &i)))
356 return error;
357 XFS_WANT_CORRUPTED_RETURN(i == 1);
358 }
359
360
361
362 if (nfbno1 == NULLAGBLOCK) {
363
364
365
366 if ((error = xfs_alloc_delete(bno_cur, &i)))
367 return error;
368 XFS_WANT_CORRUPTED_RETURN(i == 1);
369 } else {
370
371
372
373 if ((error = xfs_alloc_update(bno_cur, nfbno1, nflen1)))
374 return error;
375 }
376 if (nfbno2 != NULLAGBLOCK) {
377
378
379
380 if ((error = xfs_alloc_lookup_eq(bno_cur, nfbno2, nflen2, &i)))
381 return error;
382 XFS_WANT_CORRUPTED_RETURN(i == 0);
383 if ((error = xfs_alloc_insert(bno_cur, &i)))
384 return error;
385 XFS_WANT_CORRUPTED_RETURN(i == 1);
386 }
387 return 0;
388}
389
390
391
392
393STATIC int
394xfs_alloc_read_agfl(
395 xfs_mount_t *mp,
396 xfs_trans_t *tp,
397 xfs_agnumber_t agno,
398 xfs_buf_t **bpp)
399{
400 xfs_buf_t *bp;
401 int error;
402
403 ASSERT(agno != NULLAGNUMBER);
404 error = xfs_trans_read_buf(
405 mp, tp, mp->m_ddev_targp,
406 XFS_AG_DADDR(mp, agno, XFS_AGFL_DADDR(mp)),
407 XFS_FSS_TO_BB(mp, 1), 0, &bp);
408 if (error)
409 return error;
410 ASSERT(bp);
411 ASSERT(!XFS_BUF_GETERROR(bp));
412 XFS_BUF_SET_VTYPE_REF(bp, B_FS_AGFL, XFS_AGFL_REF);
413 *bpp = bp;
414 return 0;
415}
416
417#if defined(XFS_ALLOC_TRACE)
418
419
420
421STATIC void
422xfs_alloc_trace_alloc(
423 char *name,
424 char *str,
425 xfs_alloc_arg_t *args,
426 int line)
427{
428 ktrace_enter(xfs_alloc_trace_buf,
429 (void *)(__psint_t)(XFS_ALLOC_KTRACE_ALLOC | (line << 16)),
430 (void *)name,
431 (void *)str,
432 (void *)args->mp,
433 (void *)(__psunsigned_t)args->agno,
434 (void *)(__psunsigned_t)args->agbno,
435 (void *)(__psunsigned_t)args->minlen,
436 (void *)(__psunsigned_t)args->maxlen,
437 (void *)(__psunsigned_t)args->mod,
438 (void *)(__psunsigned_t)args->prod,
439 (void *)(__psunsigned_t)args->minleft,
440 (void *)(__psunsigned_t)args->total,
441 (void *)(__psunsigned_t)args->alignment,
442 (void *)(__psunsigned_t)args->len,
443 (void *)((((__psint_t)args->type) << 16) |
444 (__psint_t)args->otype),
445 (void *)(__psint_t)((args->wasdel << 3) |
446 (args->wasfromfl << 2) |
447 (args->isfl << 1) |
448 (args->userdata << 0)));
449}
450
451
452
453
454STATIC void
455xfs_alloc_trace_free(
456 char *name,
457 char *str,
458 xfs_mount_t *mp,
459 xfs_agnumber_t agno,
460 xfs_agblock_t agbno,
461 xfs_extlen_t len,
462 int isfl,
463 int line)
464{
465 ktrace_enter(xfs_alloc_trace_buf,
466 (void *)(__psint_t)(XFS_ALLOC_KTRACE_FREE | (line << 16)),
467 (void *)name,
468 (void *)str,
469 (void *)mp,
470 (void *)(__psunsigned_t)agno,
471 (void *)(__psunsigned_t)agbno,
472 (void *)(__psunsigned_t)len,
473 (void *)(__psint_t)isfl,
474 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
475}
476
477
478
479
480STATIC void
481xfs_alloc_trace_modagf(
482 char *name,
483 char *str,
484 xfs_mount_t *mp,
485 xfs_agf_t *agf,
486 int flags,
487 int line)
488{
489 ktrace_enter(xfs_alloc_trace_buf,
490 (void *)(__psint_t)(XFS_ALLOC_KTRACE_MODAGF | (line << 16)),
491 (void *)name,
492 (void *)str,
493 (void *)mp,
494 (void *)(__psint_t)flags,
495 (void *)(__psunsigned_t)be32_to_cpu(agf->agf_seqno),
496 (void *)(__psunsigned_t)be32_to_cpu(agf->agf_length),
497 (void *)(__psunsigned_t)be32_to_cpu(agf->agf_roots[XFS_BTNUM_BNO]),
498 (void *)(__psunsigned_t)be32_to_cpu(agf->agf_roots[XFS_BTNUM_CNT]),
499 (void *)(__psunsigned_t)be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]),
500 (void *)(__psunsigned_t)be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]),
501 (void *)(__psunsigned_t)be32_to_cpu(agf->agf_flfirst),
502 (void *)(__psunsigned_t)be32_to_cpu(agf->agf_fllast),
503 (void *)(__psunsigned_t)be32_to_cpu(agf->agf_flcount),
504 (void *)(__psunsigned_t)be32_to_cpu(agf->agf_freeblks),
505 (void *)(__psunsigned_t)be32_to_cpu(agf->agf_longest));
506}
507
508STATIC void
509xfs_alloc_trace_busy(
510 char *name,
511 char *str,
512 xfs_mount_t *mp,
513 xfs_agnumber_t agno,
514 xfs_agblock_t agbno,
515 xfs_extlen_t len,
516 int slot,
517 xfs_trans_t *tp,
518 int trtype,
519 int line)
520{
521 ktrace_enter(xfs_alloc_trace_buf,
522 (void *)(__psint_t)(trtype | (line << 16)),
523 (void *)name,
524 (void *)str,
525 (void *)mp,
526 (void *)(__psunsigned_t)agno,
527 (void *)(__psunsigned_t)agbno,
528 (void *)(__psunsigned_t)len,
529 (void *)(__psint_t)slot,
530 (void *)tp,
531 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
532}
533#endif
534
535
536
537
538
539
540
541
542
543
544
545
546
547STATIC int
548xfs_alloc_ag_vextent(
549 xfs_alloc_arg_t *args)
550{
551 int error=0;
552#ifdef XFS_ALLOC_TRACE
553 static char fname[] = "xfs_alloc_ag_vextent";
554#endif
555
556 ASSERT(args->minlen > 0);
557 ASSERT(args->maxlen > 0);
558 ASSERT(args->minlen <= args->maxlen);
559 ASSERT(args->mod < args->prod);
560 ASSERT(args->alignment > 0);
561
562
563
564 args->wasfromfl = 0;
565 switch (args->type) {
566 case XFS_ALLOCTYPE_THIS_AG:
567 error = xfs_alloc_ag_vextent_size(args);
568 break;
569 case XFS_ALLOCTYPE_NEAR_BNO:
570 error = xfs_alloc_ag_vextent_near(args);
571 break;
572 case XFS_ALLOCTYPE_THIS_BNO:
573 error = xfs_alloc_ag_vextent_exact(args);
574 break;
575 default:
576 ASSERT(0);
577
578 }
579 if (error)
580 return error;
581
582
583
584
585 if (args->agbno != NULLAGBLOCK) {
586 xfs_agf_t *agf;
587#ifdef XFS_ALLOC_TRACE
588 xfs_mount_t *mp = args->mp;
589#endif
590 long slen = (long)args->len;
591
592 ASSERT(args->len >= args->minlen && args->len <= args->maxlen);
593 ASSERT(!(args->wasfromfl) || !args->isfl);
594 ASSERT(args->agbno % args->alignment == 0);
595 if (!(args->wasfromfl)) {
596
597 agf = XFS_BUF_TO_AGF(args->agbp);
598 be32_add(&agf->agf_freeblks, -(args->len));
599 xfs_trans_agblocks_delta(args->tp,
600 -((long)(args->len)));
601 args->pag->pagf_freeblks -= args->len;
602 ASSERT(be32_to_cpu(agf->agf_freeblks) <=
603 be32_to_cpu(agf->agf_length));
604 TRACE_MODAGF(NULL, agf, XFS_AGF_FREEBLKS);
605 xfs_alloc_log_agf(args->tp, args->agbp,
606 XFS_AGF_FREEBLKS);
607
608 xfs_alloc_search_busy(args->tp, args->agno,
609 args->agbno, args->len);
610 }
611 if (!args->isfl)
612 xfs_trans_mod_sb(args->tp,
613 args->wasdel ? XFS_TRANS_SB_RES_FDBLOCKS :
614 XFS_TRANS_SB_FDBLOCKS, -slen);
615 XFS_STATS_INC(xs_allocx);
616 XFS_STATS_ADD(xs_allocb, args->len);
617 }
618 return 0;
619}
620
621
622
623
624
625
626
627STATIC int
628xfs_alloc_ag_vextent_exact(
629 xfs_alloc_arg_t *args)
630{
631 xfs_btree_cur_t *bno_cur;
632 xfs_btree_cur_t *cnt_cur;
633 xfs_agblock_t end;
634 int error;
635 xfs_agblock_t fbno;
636 xfs_agblock_t fend;
637 xfs_extlen_t flen;
638#ifdef XFS_ALLOC_TRACE
639 static char fname[] = "xfs_alloc_ag_vextent_exact";
640#endif
641 int i;
642 xfs_agblock_t maxend;
643 xfs_agblock_t minend;
644 xfs_extlen_t rlen;
645
646 ASSERT(args->alignment == 1);
647
648
649
650 bno_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp,
651 args->agno, XFS_BTNUM_BNO, NULL, 0);
652
653
654
655
656
657 if ((error = xfs_alloc_lookup_le(bno_cur, args->agbno, args->minlen, &i)))
658 goto error0;
659 if (!i) {
660
661
662
663 xfs_btree_del_cursor(bno_cur, XFS_BTREE_NOERROR);
664 args->agbno = NULLAGBLOCK;
665 return 0;
666 }
667
668
669
670 if ((error = xfs_alloc_get_rec(bno_cur, &fbno, &flen, &i)))
671 goto error0;
672 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
673 ASSERT(fbno <= args->agbno);
674 minend = args->agbno + args->minlen;
675 maxend = args->agbno + args->maxlen;
676 fend = fbno + flen;
677
678
679
680 if (fend < minend) {
681 xfs_btree_del_cursor(bno_cur, XFS_BTREE_NOERROR);
682 args->agbno = NULLAGBLOCK;
683 return 0;
684 }
685
686
687
688
689 end = XFS_AGBLOCK_MIN(fend, maxend);
690
691
692
693 args->len = end - args->agbno;
694 xfs_alloc_fix_len(args);
695 if (!xfs_alloc_fix_minleft(args)) {
696 xfs_btree_del_cursor(bno_cur, XFS_BTREE_NOERROR);
697 return 0;
698 }
699 rlen = args->len;
700 ASSERT(args->agbno + rlen <= fend);
701 end = args->agbno + rlen;
702
703
704
705
706 cnt_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp,
707 args->agno, XFS_BTNUM_CNT, NULL, 0);
708 ASSERT(args->agbno + args->len <=
709 be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length));
710 if ((error = xfs_alloc_fixup_trees(cnt_cur, bno_cur, fbno, flen,
711 args->agbno, args->len, XFSA_FIXUP_BNO_OK))) {
712 xfs_btree_del_cursor(cnt_cur, XFS_BTREE_ERROR);
713 goto error0;
714 }
715 xfs_btree_del_cursor(bno_cur, XFS_BTREE_NOERROR);
716 xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR);
717 TRACE_ALLOC("normal", args);
718 args->wasfromfl = 0;
719 return 0;
720
721error0:
722 xfs_btree_del_cursor(bno_cur, XFS_BTREE_ERROR);
723 TRACE_ALLOC("error", args);
724 return error;
725}
726
727
728
729
730
731
732
733STATIC int
734xfs_alloc_ag_vextent_near(
735 xfs_alloc_arg_t *args)
736{
737 xfs_btree_cur_t *bno_cur_gt;
738 xfs_btree_cur_t *bno_cur_lt;
739 xfs_btree_cur_t *cnt_cur;
740#ifdef XFS_ALLOC_TRACE
741 static char fname[] = "xfs_alloc_ag_vextent_near";
742#endif
743 xfs_agblock_t gtbno;
744 xfs_agblock_t gtbnoa;
745 xfs_extlen_t gtdiff;
746 xfs_extlen_t gtlen;
747 xfs_extlen_t gtlena;
748 xfs_agblock_t gtnew;
749 int error;
750 int i;
751 int j;
752 xfs_agblock_t ltbno;
753 xfs_agblock_t ltbnoa;
754 xfs_extlen_t ltdiff;
755
756 xfs_agblock_t ltend;
757 xfs_extlen_t ltlen;
758 xfs_extlen_t ltlena;
759 xfs_agblock_t ltnew;
760 xfs_extlen_t rlen;
761#if defined(DEBUG) && defined(__KERNEL__)
762
763
764
765 int dofirst;
766
767 dofirst = random() & 1;
768#endif
769
770
771
772 cnt_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp,
773 args->agno, XFS_BTNUM_CNT, NULL, 0);
774 ltlen = 0;
775 bno_cur_lt = bno_cur_gt = NULL;
776
777
778
779 if ((error = xfs_alloc_lookup_ge(cnt_cur, 0, args->maxlen, &i)))
780 goto error0;
781
782
783
784
785 if (!i) {
786 if ((error = xfs_alloc_ag_vextent_small(args, cnt_cur, <bno,
787 <len, &i)))
788 goto error0;
789 if (i == 0 || ltlen == 0) {
790 xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR);
791 return 0;
792 }
793 ASSERT(i == 1);
794 }
795 args->wasfromfl = 0;
796
797
798
799
800
801
802
803
804
805
806 while (xfs_btree_islastblock(cnt_cur, 0)) {
807 xfs_extlen_t bdiff;
808 int besti=0;
809 xfs_extlen_t blen=0;
810 xfs_agblock_t bnew=0;
811
812#if defined(DEBUG) && defined(__KERNEL__)
813 if (!dofirst)
814 break;
815#endif
816
817
818
819
820
821
822 if (ltlen || args->alignment > 1) {
823 cnt_cur->bc_ptrs[0] = 1;
824 do {
825 if ((error = xfs_alloc_get_rec(cnt_cur, <bno,
826 <len, &i)))
827 goto error0;
828 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
829 if (ltlen >= args->minlen)
830 break;
831 if ((error = xfs_alloc_increment(cnt_cur, 0, &i)))
832 goto error0;
833 } while (i);
834 ASSERT(ltlen >= args->minlen);
835 if (!i)
836 break;
837 }
838 i = cnt_cur->bc_ptrs[0];
839 for (j = 1, blen = 0, bdiff = 0;
840 !error && j && (blen < args->maxlen || bdiff > 0);
841 error = xfs_alloc_increment(cnt_cur, 0, &j)) {
842
843
844
845
846 if ((error = xfs_alloc_get_rec(cnt_cur, <bno, <len, &i)))
847 goto error0;
848 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
849 if (!xfs_alloc_compute_aligned(ltbno, ltlen,
850 args->alignment, args->minlen,
851 <bnoa, <lena))
852 continue;
853 args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen);
854 xfs_alloc_fix_len(args);
855 ASSERT(args->len >= args->minlen);
856 if (args->len < blen)
857 continue;
858 ltdiff = xfs_alloc_compute_diff(args->agbno, args->len,
859 args->alignment, ltbno, ltlen, <new);
860 if (ltnew != NULLAGBLOCK &&
861 (args->len > blen || ltdiff < bdiff)) {
862 bdiff = ltdiff;
863 bnew = ltnew;
864 blen = args->len;
865 besti = cnt_cur->bc_ptrs[0];
866 }
867 }
868
869
870
871
872 if (blen == 0)
873 break;
874
875
876
877 cnt_cur->bc_ptrs[0] = besti;
878 if ((error = xfs_alloc_get_rec(cnt_cur, <bno, <len, &i)))
879 goto error0;
880 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
881 ltend = ltbno + ltlen;
882 ASSERT(ltend <= be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length));
883 args->len = blen;
884 if (!xfs_alloc_fix_minleft(args)) {
885 xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR);
886 TRACE_ALLOC("nominleft", args);
887 return 0;
888 }
889 blen = args->len;
890
891
892
893 args->agbno = bnew;
894 ASSERT(bnew >= ltbno);
895 ASSERT(bnew + blen <= ltend);
896
897
898
899 bno_cur_lt = xfs_btree_init_cursor(args->mp, args->tp,
900 args->agbp, args->agno, XFS_BTNUM_BNO, NULL, 0);
901
902
903
904 if ((error = xfs_alloc_fixup_trees(cnt_cur, bno_cur_lt, ltbno,
905 ltlen, bnew, blen, XFSA_FIXUP_CNT_OK)))
906 goto error0;
907 xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR);
908 xfs_btree_del_cursor(bno_cur_lt, XFS_BTREE_NOERROR);
909 TRACE_ALLOC("first", args);
910 return 0;
911 }
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927 bno_cur_lt = xfs_btree_init_cursor(args->mp, args->tp, args->agbp,
928 args->agno, XFS_BTNUM_BNO, NULL, 0);
929
930
931
932 if ((error = xfs_alloc_lookup_le(bno_cur_lt, args->agbno, args->maxlen, &i)))
933 goto error0;
934 if (!i) {
935
936
937
938
939 bno_cur_gt = bno_cur_lt;
940 bno_cur_lt = NULL;
941 }
942
943
944
945 else if ((error = xfs_btree_dup_cursor(bno_cur_lt, &bno_cur_gt)))
946 goto error0;
947
948
949
950
951 if ((error = xfs_alloc_increment(bno_cur_gt, 0, &i)))
952 goto error0;
953 if (!i) {
954
955
956
957 xfs_btree_del_cursor(bno_cur_gt, XFS_BTREE_NOERROR);
958 bno_cur_gt = NULL;
959 }
960
961
962
963
964
965 do {
966 if (bno_cur_lt) {
967 if ((error = xfs_alloc_get_rec(bno_cur_lt, <bno, <len, &i)))
968 goto error0;
969 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
970 if (xfs_alloc_compute_aligned(ltbno, ltlen,
971 args->alignment, args->minlen,
972 <bnoa, <lena))
973 break;
974 if ((error = xfs_alloc_decrement(bno_cur_lt, 0, &i)))
975 goto error0;
976 if (!i) {
977 xfs_btree_del_cursor(bno_cur_lt,
978 XFS_BTREE_NOERROR);
979 bno_cur_lt = NULL;
980 }
981 }
982 if (bno_cur_gt) {
983 if ((error = xfs_alloc_get_rec(bno_cur_gt, >bno, >len, &i)))
984 goto error0;
985 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
986 if (xfs_alloc_compute_aligned(gtbno, gtlen,
987 args->alignment, args->minlen,
988 >bnoa, >lena))
989 break;
990 if ((error = xfs_alloc_increment(bno_cur_gt, 0, &i)))
991 goto error0;
992 if (!i) {
993 xfs_btree_del_cursor(bno_cur_gt,
994 XFS_BTREE_NOERROR);
995 bno_cur_gt = NULL;
996 }
997 }
998 } while (bno_cur_lt || bno_cur_gt);
999
1000
1001
1002 if (bno_cur_lt && bno_cur_gt) {
1003
1004
1005
1006 if (ltlena >= args->minlen) {
1007
1008
1009
1010 args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen);
1011 xfs_alloc_fix_len(args);
1012 rlen = args->len;
1013 ltdiff = xfs_alloc_compute_diff(args->agbno, rlen,
1014 args->alignment, ltbno, ltlen, <new);
1015
1016
1017
1018 if (ltdiff) {
1019
1020
1021
1022
1023 while (bno_cur_lt && bno_cur_gt) {
1024 if ((error = xfs_alloc_get_rec(
1025 bno_cur_gt, >bno,
1026 >len, &i)))
1027 goto error0;
1028 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
1029 xfs_alloc_compute_aligned(gtbno, gtlen,
1030 args->alignment, args->minlen,
1031 >bnoa, >lena);
1032
1033
1034
1035 if (gtbnoa >= args->agbno + ltdiff) {
1036 xfs_btree_del_cursor(
1037 bno_cur_gt,
1038 XFS_BTREE_NOERROR);
1039 bno_cur_gt = NULL;
1040 break;
1041 }
1042
1043
1044
1045
1046 if (gtlena >= args->minlen) {
1047 args->len =
1048 XFS_EXTLEN_MIN(gtlena,
1049 args->maxlen);
1050 xfs_alloc_fix_len(args);
1051 rlen = args->len;
1052 gtdiff = xfs_alloc_compute_diff(
1053 args->agbno, rlen,
1054 args->alignment,
1055 gtbno, gtlen, >new);
1056
1057
1058
1059 if (gtdiff < ltdiff) {
1060 xfs_btree_del_cursor(
1061 bno_cur_lt,
1062 XFS_BTREE_NOERROR);
1063 bno_cur_lt = NULL;
1064 }
1065
1066
1067
1068 else {
1069 xfs_btree_del_cursor(
1070 bno_cur_gt,
1071 XFS_BTREE_NOERROR);
1072 bno_cur_gt = NULL;
1073 }
1074 break;
1075 }
1076
1077
1078
1079 if ((error = xfs_alloc_increment(
1080 bno_cur_gt, 0, &i)))
1081 goto error0;
1082 if (!i) {
1083 xfs_btree_del_cursor(
1084 bno_cur_gt,
1085 XFS_BTREE_NOERROR);
1086 bno_cur_gt = NULL;
1087 break;
1088 }
1089 }
1090 }
1091
1092
1093
1094 else {
1095 xfs_btree_del_cursor(bno_cur_gt,
1096 XFS_BTREE_NOERROR);
1097 bno_cur_gt = NULL;
1098 }
1099 }
1100
1101
1102
1103 else {
1104
1105
1106
1107 args->len = XFS_EXTLEN_MIN(gtlena, args->maxlen);
1108 xfs_alloc_fix_len(args);
1109 rlen = args->len;
1110 gtdiff = xfs_alloc_compute_diff(args->agbno, rlen,
1111 args->alignment, gtbno, gtlen, >new);
1112
1113
1114
1115 if (gtdiff) {
1116
1117
1118
1119
1120 while (bno_cur_lt && bno_cur_gt) {
1121 if ((error = xfs_alloc_get_rec(
1122 bno_cur_lt, <bno,
1123 <len, &i)))
1124 goto error0;
1125 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
1126 xfs_alloc_compute_aligned(ltbno, ltlen,
1127 args->alignment, args->minlen,
1128 <bnoa, <lena);
1129
1130
1131
1132 if (ltbnoa <= args->agbno - gtdiff) {
1133 xfs_btree_del_cursor(
1134 bno_cur_lt,
1135 XFS_BTREE_NOERROR);
1136 bno_cur_lt = NULL;
1137 break;
1138 }
1139
1140
1141
1142
1143 if (ltlena >= args->minlen) {
1144 args->len = XFS_EXTLEN_MIN(
1145 ltlena, args->maxlen);
1146 xfs_alloc_fix_len(args);
1147 rlen = args->len;
1148 ltdiff = xfs_alloc_compute_diff(
1149 args->agbno, rlen,
1150 args->alignment,
1151 ltbno, ltlen, <new);
1152
1153
1154
1155 if (ltdiff < gtdiff) {
1156 xfs_btree_del_cursor(
1157 bno_cur_gt,
1158 XFS_BTREE_NOERROR);
1159 bno_cur_gt = NULL;
1160 }
1161
1162
1163
1164 else {
1165 xfs_btree_del_cursor(
1166 bno_cur_lt,
1167 XFS_BTREE_NOERROR);
1168 bno_cur_lt = NULL;
1169 }
1170 break;
1171 }
1172
1173
1174
1175 if ((error = xfs_alloc_decrement(
1176 bno_cur_lt, 0, &i)))
1177 goto error0;
1178 if (!i) {
1179 xfs_btree_del_cursor(bno_cur_lt,
1180 XFS_BTREE_NOERROR);
1181 bno_cur_lt = NULL;
1182 break;
1183 }
1184 }
1185 }
1186
1187
1188
1189 else {
1190 xfs_btree_del_cursor(bno_cur_lt,
1191 XFS_BTREE_NOERROR);
1192 bno_cur_lt = NULL;
1193 }
1194 }
1195 }
1196
1197
1198
1199 if (bno_cur_lt == NULL && bno_cur_gt == NULL) {
1200 TRACE_ALLOC("neither", args);
1201 args->agbno = NULLAGBLOCK;
1202 return 0;
1203 }
1204
1205
1206
1207
1208
1209
1210 if (bno_cur_gt) {
1211 bno_cur_lt = bno_cur_gt;
1212 bno_cur_gt = NULL;
1213 ltbno = gtbno;
1214 ltbnoa = gtbnoa;
1215 ltlen = gtlen;
1216 ltlena = gtlena;
1217 j = 1;
1218 } else
1219 j = 0;
1220
1221
1222
1223 ltend = ltbno + ltlen;
1224 args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen);
1225 xfs_alloc_fix_len(args);
1226 if (!xfs_alloc_fix_minleft(args)) {
1227 TRACE_ALLOC("nominleft", args);
1228 xfs_btree_del_cursor(bno_cur_lt, XFS_BTREE_NOERROR);
1229 xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR);
1230 return 0;
1231 }
1232 rlen = args->len;
1233 (void)xfs_alloc_compute_diff(args->agbno, rlen, args->alignment, ltbno,
1234 ltlen, <new);
1235 ASSERT(ltnew >= ltbno);
1236 ASSERT(ltnew + rlen <= ltend);
1237 ASSERT(ltnew + rlen <= be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length));
1238 args->agbno = ltnew;
1239 if ((error = xfs_alloc_fixup_trees(cnt_cur, bno_cur_lt, ltbno, ltlen,
1240 ltnew, rlen, XFSA_FIXUP_BNO_OK)))
1241 goto error0;
1242 TRACE_ALLOC(j ? "gt" : "lt", args);
1243 xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR);
1244 xfs_btree_del_cursor(bno_cur_lt, XFS_BTREE_NOERROR);
1245 return 0;
1246
1247 error0:
1248 TRACE_ALLOC("error", args);
1249 if (cnt_cur != NULL)
1250 xfs_btree_del_cursor(cnt_cur, XFS_BTREE_ERROR);
1251 if (bno_cur_lt != NULL)
1252 xfs_btree_del_cursor(bno_cur_lt, XFS_BTREE_ERROR);
1253 if (bno_cur_gt != NULL)
1254 xfs_btree_del_cursor(bno_cur_gt, XFS_BTREE_ERROR);
1255 return error;
1256}
1257
1258
1259
1260
1261
1262
1263
1264STATIC int
1265xfs_alloc_ag_vextent_size(
1266 xfs_alloc_arg_t *args)
1267{
1268 xfs_btree_cur_t *bno_cur;
1269 xfs_btree_cur_t *cnt_cur;
1270 int error;
1271 xfs_agblock_t fbno;
1272 xfs_extlen_t flen;
1273#ifdef XFS_ALLOC_TRACE
1274 static char fname[] = "xfs_alloc_ag_vextent_size";
1275#endif
1276 int i;
1277 xfs_agblock_t rbno;
1278 xfs_extlen_t rlen;
1279
1280
1281
1282
1283 cnt_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp,
1284 args->agno, XFS_BTNUM_CNT, NULL, 0);
1285 bno_cur = NULL;
1286
1287
1288
1289 if ((error = xfs_alloc_lookup_ge(cnt_cur, 0,
1290 args->maxlen + args->alignment - 1, &i)))
1291 goto error0;
1292
1293
1294
1295
1296 if (!i) {
1297 if ((error = xfs_alloc_ag_vextent_small(args, cnt_cur, &fbno,
1298 &flen, &i)))
1299 goto error0;
1300 if (i == 0 || flen == 0) {
1301 xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR);
1302 TRACE_ALLOC("noentry", args);
1303 return 0;
1304 }
1305 ASSERT(i == 1);
1306 }
1307
1308
1309
1310 else {
1311 if ((error = xfs_alloc_get_rec(cnt_cur, &fbno, &flen, &i)))
1312 goto error0;
1313 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
1314 }
1315
1316
1317
1318
1319
1320
1321 xfs_alloc_compute_aligned(fbno, flen, args->alignment, args->minlen,
1322 &rbno, &rlen);
1323 rlen = XFS_EXTLEN_MIN(args->maxlen, rlen);
1324 XFS_WANT_CORRUPTED_GOTO(rlen == 0 ||
1325 (rlen <= flen && rbno + rlen <= fbno + flen), error0);
1326 if (rlen < args->maxlen) {
1327 xfs_agblock_t bestfbno;
1328 xfs_extlen_t bestflen;
1329 xfs_agblock_t bestrbno;
1330 xfs_extlen_t bestrlen;
1331
1332 bestrlen = rlen;
1333 bestrbno = rbno;
1334 bestflen = flen;
1335 bestfbno = fbno;
1336 for (;;) {
1337 if ((error = xfs_alloc_decrement(cnt_cur, 0, &i)))
1338 goto error0;
1339 if (i == 0)
1340 break;
1341 if ((error = xfs_alloc_get_rec(cnt_cur, &fbno, &flen,
1342 &i)))
1343 goto error0;
1344 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
1345 if (flen < bestrlen)
1346 break;
1347 xfs_alloc_compute_aligned(fbno, flen, args->alignment,
1348 args->minlen, &rbno, &rlen);
1349 rlen = XFS_EXTLEN_MIN(args->maxlen, rlen);
1350 XFS_WANT_CORRUPTED_GOTO(rlen == 0 ||
1351 (rlen <= flen && rbno + rlen <= fbno + flen),
1352 error0);
1353 if (rlen > bestrlen) {
1354 bestrlen = rlen;
1355 bestrbno = rbno;
1356 bestflen = flen;
1357 bestfbno = fbno;
1358 if (rlen == args->maxlen)
1359 break;
1360 }
1361 }
1362 if ((error = xfs_alloc_lookup_eq(cnt_cur, bestfbno, bestflen,
1363 &i)))
1364 goto error0;
1365 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
1366 rlen = bestrlen;
1367 rbno = bestrbno;
1368 flen = bestflen;
1369 fbno = bestfbno;
1370 }
1371 args->wasfromfl = 0;
1372
1373
1374
1375 args->len = rlen;
1376 xfs_alloc_fix_len(args);
1377 if (rlen < args->minlen || !xfs_alloc_fix_minleft(args)) {
1378 xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR);
1379 TRACE_ALLOC("nominleft", args);
1380 args->agbno = NULLAGBLOCK;
1381 return 0;
1382 }
1383 rlen = args->len;
1384 XFS_WANT_CORRUPTED_GOTO(rlen <= flen, error0);
1385
1386
1387
1388 bno_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp,
1389 args->agno, XFS_BTNUM_BNO, NULL, 0);
1390 if ((error = xfs_alloc_fixup_trees(cnt_cur, bno_cur, fbno, flen,
1391 rbno, rlen, XFSA_FIXUP_CNT_OK)))
1392 goto error0;
1393 xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR);
1394 xfs_btree_del_cursor(bno_cur, XFS_BTREE_NOERROR);
1395 cnt_cur = bno_cur = NULL;
1396 args->len = rlen;
1397 args->agbno = rbno;
1398 XFS_WANT_CORRUPTED_GOTO(
1399 args->agbno + args->len <=
1400 be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length),
1401 error0);
1402 TRACE_ALLOC("normal", args);
1403 return 0;
1404
1405error0:
1406 TRACE_ALLOC("error", args);
1407 if (cnt_cur)
1408 xfs_btree_del_cursor(cnt_cur, XFS_BTREE_ERROR);
1409 if (bno_cur)
1410 xfs_btree_del_cursor(bno_cur, XFS_BTREE_ERROR);
1411 return error;
1412}
1413
1414
1415
1416
1417
1418
1419STATIC int
1420xfs_alloc_ag_vextent_small(
1421 xfs_alloc_arg_t *args,
1422 xfs_btree_cur_t *ccur,
1423 xfs_agblock_t *fbnop,
1424 xfs_extlen_t *flenp,
1425 int *stat)
1426{
1427 int error;
1428 xfs_agblock_t fbno;
1429 xfs_extlen_t flen;
1430#ifdef XFS_ALLOC_TRACE
1431 static char fname[] = "xfs_alloc_ag_vextent_small";
1432#endif
1433 int i;
1434
1435 if ((error = xfs_alloc_decrement(ccur, 0, &i)))
1436 goto error0;
1437 if (i) {
1438 if ((error = xfs_alloc_get_rec(ccur, &fbno, &flen, &i)))
1439 goto error0;
1440 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
1441 }
1442
1443
1444
1445
1446
1447 else if (args->minlen == 1 && args->alignment == 1 && !args->isfl &&
1448 (be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_flcount)
1449 > args->minleft)) {
1450 if ((error = xfs_alloc_get_freelist(args->tp, args->agbp, &fbno)))
1451 goto error0;
1452 if (fbno != NULLAGBLOCK) {
1453 if (args->userdata) {
1454 xfs_buf_t *bp;
1455
1456 bp = xfs_btree_get_bufs(args->mp, args->tp,
1457 args->agno, fbno, 0);
1458 xfs_trans_binval(args->tp, bp);
1459 }
1460 args->len = 1;
1461 args->agbno = fbno;
1462 XFS_WANT_CORRUPTED_GOTO(
1463 args->agbno + args->len <=
1464 be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length),
1465 error0);
1466 args->wasfromfl = 1;
1467 TRACE_ALLOC("freelist", args);
1468 *stat = 0;
1469 return 0;
1470 }
1471
1472
1473
1474 else
1475 flen = 0;
1476 }
1477
1478
1479
1480 else
1481 flen = 0;
1482
1483
1484
1485 if (flen < args->minlen) {
1486 args->agbno = NULLAGBLOCK;
1487 TRACE_ALLOC("notenough", args);
1488 flen = 0;
1489 }
1490 *fbnop = fbno;
1491 *flenp = flen;
1492 *stat = 1;
1493 TRACE_ALLOC("normal", args);
1494 return 0;
1495
1496error0:
1497 TRACE_ALLOC("error", args);
1498 return error;
1499}
1500
1501
1502
1503
1504STATIC int
1505xfs_free_ag_extent(
1506 xfs_trans_t *tp,
1507 xfs_buf_t *agbp,
1508 xfs_agnumber_t agno,
1509 xfs_agblock_t bno,
1510 xfs_extlen_t len,
1511 int isfl)
1512{
1513 xfs_btree_cur_t *bno_cur;
1514 xfs_btree_cur_t *cnt_cur;
1515 int error;
1516#ifdef XFS_ALLOC_TRACE
1517 static char fname[] = "xfs_free_ag_extent";
1518#endif
1519 xfs_agblock_t gtbno;
1520 xfs_extlen_t gtlen;
1521 int haveleft;
1522 int haveright;
1523 int i;
1524 xfs_agblock_t ltbno;
1525 xfs_extlen_t ltlen;
1526 xfs_mount_t *mp;
1527 xfs_agblock_t nbno;
1528 xfs_extlen_t nlen;
1529
1530 mp = tp->t_mountp;
1531
1532
1533
1534 bno_cur = xfs_btree_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_BNO, NULL,
1535 0);
1536 cnt_cur = NULL;
1537
1538
1539
1540
1541 if ((error = xfs_alloc_lookup_le(bno_cur, bno, len, &haveleft)))
1542 goto error0;
1543 if (haveleft) {
1544
1545
1546
1547 if ((error = xfs_alloc_get_rec(bno_cur, <bno, <len, &i)))
1548 goto error0;
1549 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
1550
1551
1552
1553 if (ltbno + ltlen < bno)
1554 haveleft = 0;
1555 else {
1556
1557
1558
1559
1560
1561 XFS_WANT_CORRUPTED_GOTO(ltbno + ltlen <= bno, error0);
1562 }
1563 }
1564
1565
1566
1567
1568 if ((error = xfs_alloc_increment(bno_cur, 0, &haveright)))
1569 goto error0;
1570 if (haveright) {
1571
1572
1573
1574 if ((error = xfs_alloc_get_rec(bno_cur, >bno, >len, &i)))
1575 goto error0;
1576 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
1577
1578
1579
1580 if (bno + len < gtbno)
1581 haveright = 0;
1582 else {
1583
1584
1585
1586
1587
1588 XFS_WANT_CORRUPTED_GOTO(gtbno >= bno + len, error0);
1589 }
1590 }
1591
1592
1593
1594 cnt_cur = xfs_btree_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_CNT, NULL,
1595 0);
1596
1597
1598
1599
1600 if (haveleft && haveright) {
1601
1602
1603
1604 if ((error = xfs_alloc_lookup_eq(cnt_cur, ltbno, ltlen, &i)))
1605 goto error0;
1606 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
1607 if ((error = xfs_alloc_delete(cnt_cur, &i)))
1608 goto error0;
1609 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
1610
1611
1612
1613 if ((error = xfs_alloc_lookup_eq(cnt_cur, gtbno, gtlen, &i)))
1614 goto error0;
1615 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
1616 if ((error = xfs_alloc_delete(cnt_cur, &i)))
1617 goto error0;
1618 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
1619
1620
1621
1622 if ((error = xfs_alloc_delete(bno_cur, &i)))
1623 goto error0;
1624 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
1625
1626
1627
1628 if ((error = xfs_alloc_decrement(bno_cur, 0, &i)))
1629 goto error0;
1630 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
1631#ifdef DEBUG
1632
1633
1634
1635
1636 {
1637 xfs_agblock_t xxbno;
1638 xfs_extlen_t xxlen;
1639
1640 if ((error = xfs_alloc_get_rec(bno_cur, &xxbno, &xxlen,
1641 &i)))
1642 goto error0;
1643 XFS_WANT_CORRUPTED_GOTO(
1644 i == 1 && xxbno == ltbno && xxlen == ltlen,
1645 error0);
1646 }
1647#endif
1648
1649
1650
1651 nbno = ltbno;
1652 nlen = len + ltlen + gtlen;
1653 if ((error = xfs_alloc_update(bno_cur, nbno, nlen)))
1654 goto error0;
1655 }
1656
1657
1658
1659
1660 else if (haveleft) {
1661
1662
1663
1664 if ((error = xfs_alloc_lookup_eq(cnt_cur, ltbno, ltlen, &i)))
1665 goto error0;
1666 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
1667 if ((error = xfs_alloc_delete(cnt_cur, &i)))
1668 goto error0;
1669 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
1670
1671
1672
1673
1674 if ((error = xfs_alloc_decrement(bno_cur, 0, &i)))
1675 goto error0;
1676 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
1677 nbno = ltbno;
1678 nlen = len + ltlen;
1679 if ((error = xfs_alloc_update(bno_cur, nbno, nlen)))
1680 goto error0;
1681 }
1682
1683
1684
1685
1686 else if (haveright) {
1687
1688
1689
1690 if ((error = xfs_alloc_lookup_eq(cnt_cur, gtbno, gtlen, &i)))
1691 goto error0;
1692 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
1693 if ((error = xfs_alloc_delete(cnt_cur, &i)))
1694 goto error0;
1695 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
1696
1697
1698
1699
1700 nbno = bno;
1701 nlen = len + gtlen;
1702 if ((error = xfs_alloc_update(bno_cur, nbno, nlen)))
1703 goto error0;
1704 }
1705
1706
1707
1708
1709 else {
1710 nbno = bno;
1711 nlen = len;
1712 if ((error = xfs_alloc_insert(bno_cur, &i)))
1713 goto error0;
1714 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
1715 }
1716 xfs_btree_del_cursor(bno_cur, XFS_BTREE_NOERROR);
1717 bno_cur = NULL;
1718
1719
1720
1721 if ((error = xfs_alloc_lookup_eq(cnt_cur, nbno, nlen, &i)))
1722 goto error0;
1723 XFS_WANT_CORRUPTED_GOTO(i == 0, error0);
1724 if ((error = xfs_alloc_insert(cnt_cur, &i)))
1725 goto error0;
1726 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
1727 xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR);
1728 cnt_cur = NULL;
1729
1730
1731
1732 {
1733 xfs_agf_t *agf;
1734 xfs_perag_t *pag;
1735
1736 agf = XFS_BUF_TO_AGF(agbp);
1737 pag = &mp->m_perag[agno];
1738 be32_add(&agf->agf_freeblks, len);
1739 xfs_trans_agblocks_delta(tp, len);
1740 pag->pagf_freeblks += len;
1741 XFS_WANT_CORRUPTED_GOTO(
1742 be32_to_cpu(agf->agf_freeblks) <=
1743 be32_to_cpu(agf->agf_length),
1744 error0);
1745 TRACE_MODAGF(NULL, agf, XFS_AGF_FREEBLKS);
1746 xfs_alloc_log_agf(tp, agbp, XFS_AGF_FREEBLKS);
1747 if (!isfl)
1748 xfs_trans_mod_sb(tp, XFS_TRANS_SB_FDBLOCKS, (long)len);
1749 XFS_STATS_INC(xs_freex);
1750 XFS_STATS_ADD(xs_freeb, len);
1751 }
1752 TRACE_FREE(haveleft ?
1753 (haveright ? "both" : "left") :
1754 (haveright ? "right" : "none"),
1755 agno, bno, len, isfl);
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768 xfs_alloc_mark_busy(tp, agno, bno, len);
1769 return 0;
1770
1771 error0:
1772 TRACE_FREE("error", agno, bno, len, isfl);
1773 if (bno_cur)
1774 xfs_btree_del_cursor(bno_cur, XFS_BTREE_ERROR);
1775 if (cnt_cur)
1776 xfs_btree_del_cursor(cnt_cur, XFS_BTREE_ERROR);
1777 return error;
1778}
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788void
1789xfs_alloc_compute_maxlevels(
1790 xfs_mount_t *mp)
1791{
1792 int level;
1793 uint maxblocks;
1794 uint maxleafents;
1795 int minleafrecs;
1796 int minnoderecs;
1797
1798 maxleafents = (mp->m_sb.sb_agblocks + 1) / 2;
1799 minleafrecs = mp->m_alloc_mnr[0];
1800 minnoderecs = mp->m_alloc_mnr[1];
1801 maxblocks = (maxleafents + minleafrecs - 1) / minleafrecs;
1802 for (level = 1; maxblocks > 1; level++)
1803 maxblocks = (maxblocks + minnoderecs - 1) / minnoderecs;
1804 mp->m_ag_maxlevels = level;
1805}
1806
1807
1808
1809
1810
1811STATIC int
1812xfs_alloc_fix_freelist(
1813 xfs_alloc_arg_t *args,
1814 int flags)
1815{
1816 xfs_buf_t *agbp;
1817 xfs_agf_t *agf;
1818 xfs_buf_t *agflbp;
1819 xfs_agblock_t bno;
1820 xfs_extlen_t delta;
1821 int error;
1822 xfs_extlen_t longest;
1823 xfs_mount_t *mp;
1824 xfs_extlen_t need;
1825 xfs_perag_t *pag;
1826 xfs_alloc_arg_t targs;
1827 xfs_trans_t *tp;
1828
1829 mp = args->mp;
1830
1831 pag = args->pag;
1832 tp = args->tp;
1833 if (!pag->pagf_init) {
1834 if ((error = xfs_alloc_read_agf(mp, tp, args->agno, flags,
1835 &agbp)))
1836 return error;
1837 if (!pag->pagf_init) {
1838 ASSERT(flags & XFS_ALLOC_FLAG_TRYLOCK);
1839 ASSERT(!(flags & XFS_ALLOC_FLAG_FREEING));
1840 args->agbp = NULL;
1841 return 0;
1842 }
1843 } else
1844 agbp = NULL;
1845
1846
1847
1848
1849
1850
1851 if (pag->pagf_metadata && args->userdata &&
1852 (flags & XFS_ALLOC_FLAG_TRYLOCK)) {
1853 ASSERT(!(flags & XFS_ALLOC_FLAG_FREEING));
1854 args->agbp = NULL;
1855 return 0;
1856 }
1857
1858 if (!(flags & XFS_ALLOC_FLAG_FREEING)) {
1859 need = XFS_MIN_FREELIST_PAG(pag, mp);
1860 delta = need > pag->pagf_flcount ? need - pag->pagf_flcount : 0;
1861
1862
1863
1864
1865 longest = (pag->pagf_longest > delta) ?
1866 (pag->pagf_longest - delta) :
1867 (pag->pagf_flcount > 0 || pag->pagf_longest > 0);
1868 if ((args->minlen + args->alignment + args->minalignslop - 1) >
1869 longest ||
1870 ((int)(pag->pagf_freeblks + pag->pagf_flcount -
1871 need - args->total) < (int)args->minleft)) {
1872 if (agbp)
1873 xfs_trans_brelse(tp, agbp);
1874 args->agbp = NULL;
1875 return 0;
1876 }
1877 }
1878
1879
1880
1881
1882
1883 if (agbp == NULL) {
1884 if ((error = xfs_alloc_read_agf(mp, tp, args->agno, flags,
1885 &agbp)))
1886 return error;
1887 if (agbp == NULL) {
1888 ASSERT(flags & XFS_ALLOC_FLAG_TRYLOCK);
1889 ASSERT(!(flags & XFS_ALLOC_FLAG_FREEING));
1890 args->agbp = NULL;
1891 return 0;
1892 }
1893 }
1894
1895
1896
1897 agf = XFS_BUF_TO_AGF(agbp);
1898 need = XFS_MIN_FREELIST(agf, mp);
1899
1900
1901
1902 if (!(flags & XFS_ALLOC_FLAG_FREEING)) {
1903 delta = need > be32_to_cpu(agf->agf_flcount) ?
1904 (need - be32_to_cpu(agf->agf_flcount)) : 0;
1905 longest = be32_to_cpu(agf->agf_longest);
1906 longest = (longest > delta) ? (longest - delta) :
1907 (be32_to_cpu(agf->agf_flcount) > 0 || longest > 0);
1908 if ((args->minlen + args->alignment + args->minalignslop - 1) >
1909 longest ||
1910 ((int)(be32_to_cpu(agf->agf_freeblks) +
1911 be32_to_cpu(agf->agf_flcount) - need - args->total) <
1912 (int)args->minleft)) {
1913 xfs_trans_brelse(tp, agbp);
1914 args->agbp = NULL;
1915 return 0;
1916 }
1917 }
1918
1919
1920
1921 while (be32_to_cpu(agf->agf_flcount) > need) {
1922 xfs_buf_t *bp;
1923
1924 if ((error = xfs_alloc_get_freelist(tp, agbp, &bno)))
1925 return error;
1926 if ((error = xfs_free_ag_extent(tp, agbp, args->agno, bno, 1, 1)))
1927 return error;
1928 bp = xfs_btree_get_bufs(mp, tp, args->agno, bno, 0);
1929 xfs_trans_binval(tp, bp);
1930 }
1931
1932
1933
1934 targs.tp = tp;
1935 targs.mp = mp;
1936 targs.agbp = agbp;
1937 targs.agno = args->agno;
1938 targs.mod = targs.minleft = targs.wasdel = targs.userdata =
1939 targs.minalignslop = 0;
1940 targs.alignment = targs.minlen = targs.prod = targs.isfl = 1;
1941 targs.type = XFS_ALLOCTYPE_THIS_AG;
1942 targs.pag = pag;
1943 if ((error = xfs_alloc_read_agfl(mp, tp, targs.agno, &agflbp)))
1944 return error;
1945
1946
1947
1948 while (be32_to_cpu(agf->agf_flcount) < need) {
1949 targs.agbno = 0;
1950 targs.maxlen = need - be32_to_cpu(agf->agf_flcount);
1951
1952
1953
1954 if ((error = xfs_alloc_ag_vextent(&targs))) {
1955 xfs_trans_brelse(tp, agflbp);
1956 return error;
1957 }
1958
1959
1960
1961
1962
1963 if (targs.agbno == NULLAGBLOCK) {
1964 if (flags & XFS_ALLOC_FLAG_FREEING)
1965 break;
1966 xfs_trans_brelse(tp, agflbp);
1967 args->agbp = NULL;
1968 return 0;
1969 }
1970
1971
1972
1973 for (bno = targs.agbno; bno < targs.agbno + targs.len; bno++) {
1974 if ((error = xfs_alloc_put_freelist(tp, agbp, agflbp,
1975 bno)))
1976 return error;
1977 }
1978 }
1979 xfs_trans_brelse(tp, agflbp);
1980 args->agbp = agbp;
1981 return 0;
1982}
1983
1984
1985
1986
1987
1988int
1989xfs_alloc_get_freelist(
1990 xfs_trans_t *tp,
1991 xfs_buf_t *agbp,
1992 xfs_agblock_t *bnop)
1993{
1994 xfs_agf_t *agf;
1995 xfs_agfl_t *agfl;
1996 xfs_buf_t *agflbp;
1997 xfs_agblock_t bno;
1998 int error;
1999#ifdef XFS_ALLOC_TRACE
2000 static char fname[] = "xfs_alloc_get_freelist";
2001#endif
2002 xfs_mount_t *mp;
2003 xfs_perag_t *pag;
2004
2005 agf = XFS_BUF_TO_AGF(agbp);
2006
2007
2008
2009 if (!agf->agf_flcount) {
2010 *bnop = NULLAGBLOCK;
2011 return 0;
2012 }
2013
2014
2015
2016 mp = tp->t_mountp;
2017 if ((error = xfs_alloc_read_agfl(mp, tp,
2018 be32_to_cpu(agf->agf_seqno), &agflbp)))
2019 return error;
2020 agfl = XFS_BUF_TO_AGFL(agflbp);
2021
2022
2023
2024 bno = INT_GET(agfl->agfl_bno[be32_to_cpu(agf->agf_flfirst)], ARCH_CONVERT);
2025 be32_add(&agf->agf_flfirst, 1);
2026 xfs_trans_brelse(tp, agflbp);
2027 if (be32_to_cpu(agf->agf_flfirst) == XFS_AGFL_SIZE(mp))
2028 agf->agf_flfirst = 0;
2029 pag = &mp->m_perag[be32_to_cpu(agf->agf_seqno)];
2030 be32_add(&agf->agf_flcount, -1);
2031 xfs_trans_agflist_delta(tp, -1);
2032 pag->pagf_flcount--;
2033 TRACE_MODAGF(NULL, agf, XFS_AGF_FLFIRST | XFS_AGF_FLCOUNT);
2034 xfs_alloc_log_agf(tp, agbp, XFS_AGF_FLFIRST | XFS_AGF_FLCOUNT);
2035 *bnop = bno;
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045 xfs_alloc_search_busy(tp, be32_to_cpu(agf->agf_seqno), bno, 1);
2046 return 0;
2047}
2048
2049
2050
2051
2052void
2053xfs_alloc_log_agf(
2054 xfs_trans_t *tp,
2055 xfs_buf_t *bp,
2056 int fields)
2057{
2058 int first;
2059 int last;
2060 static const short offsets[] = {
2061 offsetof(xfs_agf_t, agf_magicnum),
2062 offsetof(xfs_agf_t, agf_versionnum),
2063 offsetof(xfs_agf_t, agf_seqno),
2064 offsetof(xfs_agf_t, agf_length),
2065 offsetof(xfs_agf_t, agf_roots[0]),
2066 offsetof(xfs_agf_t, agf_levels[0]),
2067 offsetof(xfs_agf_t, agf_flfirst),
2068 offsetof(xfs_agf_t, agf_fllast),
2069 offsetof(xfs_agf_t, agf_flcount),
2070 offsetof(xfs_agf_t, agf_freeblks),
2071 offsetof(xfs_agf_t, agf_longest),
2072 sizeof(xfs_agf_t)
2073 };
2074
2075 xfs_btree_offsets(fields, offsets, XFS_AGF_NUM_BITS, &first, &last);
2076 xfs_trans_log_buf(tp, bp, (uint)first, (uint)last);
2077}
2078
2079
2080
2081
2082int
2083xfs_alloc_pagf_init(
2084 xfs_mount_t *mp,
2085 xfs_trans_t *tp,
2086 xfs_agnumber_t agno,
2087 int flags)
2088{
2089 xfs_buf_t *bp;
2090 int error;
2091
2092 if ((error = xfs_alloc_read_agf(mp, tp, agno, flags, &bp)))
2093 return error;
2094 if (bp)
2095 xfs_trans_brelse(tp, bp);
2096 return 0;
2097}
2098
2099
2100
2101
2102int
2103xfs_alloc_put_freelist(
2104 xfs_trans_t *tp,
2105 xfs_buf_t *agbp,
2106 xfs_buf_t *agflbp,
2107 xfs_agblock_t bno)
2108{
2109 xfs_agf_t *agf;
2110 xfs_agfl_t *agfl;
2111 xfs_agblock_t *blockp;
2112 int error;
2113#ifdef XFS_ALLOC_TRACE
2114 static char fname[] = "xfs_alloc_put_freelist";
2115#endif
2116 xfs_mount_t *mp;
2117 xfs_perag_t *pag;
2118
2119 agf = XFS_BUF_TO_AGF(agbp);
2120 mp = tp->t_mountp;
2121
2122 if (!agflbp && (error = xfs_alloc_read_agfl(mp, tp,
2123 be32_to_cpu(agf->agf_seqno), &agflbp)))
2124 return error;
2125 agfl = XFS_BUF_TO_AGFL(agflbp);
2126 be32_add(&agf->agf_fllast, 1);
2127 if (be32_to_cpu(agf->agf_fllast) == XFS_AGFL_SIZE(mp))
2128 agf->agf_fllast = 0;
2129 pag = &mp->m_perag[be32_to_cpu(agf->agf_seqno)];
2130 be32_add(&agf->agf_flcount, 1);
2131 xfs_trans_agflist_delta(tp, 1);
2132 pag->pagf_flcount++;
2133 ASSERT(be32_to_cpu(agf->agf_flcount) <= XFS_AGFL_SIZE(mp));
2134 blockp = &agfl->agfl_bno[be32_to_cpu(agf->agf_fllast)];
2135 INT_SET(*blockp, ARCH_CONVERT, bno);
2136 TRACE_MODAGF(NULL, agf, XFS_AGF_FLLAST | XFS_AGF_FLCOUNT);
2137 xfs_alloc_log_agf(tp, agbp, XFS_AGF_FLLAST | XFS_AGF_FLCOUNT);
2138 xfs_trans_log_buf(tp, agflbp,
2139 (int)((xfs_caddr_t)blockp - (xfs_caddr_t)agfl),
2140 (int)((xfs_caddr_t)blockp - (xfs_caddr_t)agfl +
2141 sizeof(xfs_agblock_t) - 1));
2142 return 0;
2143}
2144
2145
2146
2147
2148int
2149xfs_alloc_read_agf(
2150 xfs_mount_t *mp,
2151 xfs_trans_t *tp,
2152 xfs_agnumber_t agno,
2153 int flags,
2154 xfs_buf_t **bpp)
2155{
2156 xfs_agf_t *agf;
2157 int agf_ok;
2158 xfs_buf_t *bp;
2159 xfs_perag_t *pag;
2160 int error;
2161
2162 ASSERT(agno != NULLAGNUMBER);
2163 error = xfs_trans_read_buf(
2164 mp, tp, mp->m_ddev_targp,
2165 XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)),
2166 XFS_FSS_TO_BB(mp, 1),
2167 (flags & XFS_ALLOC_FLAG_TRYLOCK) ? XFS_BUF_TRYLOCK : 0U,
2168 &bp);
2169 if (error)
2170 return error;
2171 ASSERT(!bp || !XFS_BUF_GETERROR(bp));
2172 if (!bp) {
2173 *bpp = NULL;
2174 return 0;
2175 }
2176
2177
2178
2179 agf = XFS_BUF_TO_AGF(bp);
2180 agf_ok =
2181 be32_to_cpu(agf->agf_magicnum) == XFS_AGF_MAGIC &&
2182 XFS_AGF_GOOD_VERSION(be32_to_cpu(agf->agf_versionnum)) &&
2183 be32_to_cpu(agf->agf_freeblks) <= be32_to_cpu(agf->agf_length) &&
2184 be32_to_cpu(agf->agf_flfirst) < XFS_AGFL_SIZE(mp) &&
2185 be32_to_cpu(agf->agf_fllast) < XFS_AGFL_SIZE(mp) &&
2186 be32_to_cpu(agf->agf_flcount) <= XFS_AGFL_SIZE(mp);
2187 if (unlikely(XFS_TEST_ERROR(!agf_ok, mp, XFS_ERRTAG_ALLOC_READ_AGF,
2188 XFS_RANDOM_ALLOC_READ_AGF))) {
2189 XFS_CORRUPTION_ERROR("xfs_alloc_read_agf",
2190 XFS_ERRLEVEL_LOW, mp, agf);
2191 xfs_trans_brelse(tp, bp);
2192 return XFS_ERROR(EFSCORRUPTED);
2193 }
2194 pag = &mp->m_perag[agno];
2195 if (!pag->pagf_init) {
2196 pag->pagf_freeblks = be32_to_cpu(agf->agf_freeblks);
2197 pag->pagf_flcount = be32_to_cpu(agf->agf_flcount);
2198 pag->pagf_longest = be32_to_cpu(agf->agf_longest);
2199 pag->pagf_levels[XFS_BTNUM_BNOi] =
2200 be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNOi]);
2201 pag->pagf_levels[XFS_BTNUM_CNTi] =
2202 be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNTi]);
2203 spinlock_init(&pag->pagb_lock, "xfspagb");
2204 pag->pagb_list = kmem_zalloc(XFS_PAGB_NUM_SLOTS *
2205 sizeof(xfs_perag_busy_t), KM_SLEEP);
2206 pag->pagf_init = 1;
2207 }
2208#ifdef DEBUG
2209 else if (!XFS_FORCED_SHUTDOWN(mp)) {
2210 ASSERT(pag->pagf_freeblks == be32_to_cpu(agf->agf_freeblks));
2211 ASSERT(pag->pagf_flcount == be32_to_cpu(agf->agf_flcount));
2212 ASSERT(pag->pagf_longest == be32_to_cpu(agf->agf_longest));
2213 ASSERT(pag->pagf_levels[XFS_BTNUM_BNOi] ==
2214 be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNOi]));
2215 ASSERT(pag->pagf_levels[XFS_BTNUM_CNTi] ==
2216 be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNTi]));
2217 }
2218#endif
2219 XFS_BUF_SET_VTYPE_REF(bp, B_FS_AGF, XFS_AGF_REF);
2220 *bpp = bp;
2221 return 0;
2222}
2223
2224
2225
2226
2227
2228
2229int
2230xfs_alloc_vextent(
2231 xfs_alloc_arg_t *args)
2232{
2233 xfs_agblock_t agsize;
2234 int error;
2235 int flags;
2236#ifdef XFS_ALLOC_TRACE
2237 static char fname[] = "xfs_alloc_vextent";
2238#endif
2239 xfs_extlen_t minleft;
2240 xfs_mount_t *mp;
2241 xfs_agnumber_t sagno;
2242 xfs_alloctype_t type;
2243 int bump_rotor = 0;
2244 int no_min = 0;
2245 xfs_agnumber_t rotorstep = xfs_rotorstep;
2246
2247 mp = args->mp;
2248 type = args->otype = args->type;
2249 args->agbno = NULLAGBLOCK;
2250
2251
2252
2253
2254
2255 agsize = mp->m_sb.sb_agblocks;
2256 if (args->maxlen > agsize)
2257 args->maxlen = agsize;
2258 if (args->alignment == 0)
2259 args->alignment = 1;
2260 ASSERT(XFS_FSB_TO_AGNO(mp, args->fsbno) < mp->m_sb.sb_agcount);
2261 ASSERT(XFS_FSB_TO_AGBNO(mp, args->fsbno) < agsize);
2262 ASSERT(args->minlen <= args->maxlen);
2263 ASSERT(args->minlen <= agsize);
2264 ASSERT(args->mod < args->prod);
2265 if (XFS_FSB_TO_AGNO(mp, args->fsbno) >= mp->m_sb.sb_agcount ||
2266 XFS_FSB_TO_AGBNO(mp, args->fsbno) >= agsize ||
2267 args->minlen > args->maxlen || args->minlen > agsize ||
2268 args->mod >= args->prod) {
2269 args->fsbno = NULLFSBLOCK;
2270 TRACE_ALLOC("badargs", args);
2271 return 0;
2272 }
2273 minleft = args->minleft;
2274
2275 switch (type) {
2276 case XFS_ALLOCTYPE_THIS_AG:
2277 case XFS_ALLOCTYPE_NEAR_BNO:
2278 case XFS_ALLOCTYPE_THIS_BNO:
2279
2280
2281
2282 args->agno = XFS_FSB_TO_AGNO(mp, args->fsbno);
2283 down_read(&mp->m_peraglock);
2284 args->pag = &mp->m_perag[args->agno];
2285 args->minleft = 0;
2286 error = xfs_alloc_fix_freelist(args, 0);
2287 args->minleft = minleft;
2288 if (error) {
2289 TRACE_ALLOC("nofix", args);
2290 goto error0;
2291 }
2292 if (!args->agbp) {
2293 up_read(&mp->m_peraglock);
2294 TRACE_ALLOC("noagbp", args);
2295 break;
2296 }
2297 args->agbno = XFS_FSB_TO_AGBNO(mp, args->fsbno);
2298 if ((error = xfs_alloc_ag_vextent(args)))
2299 goto error0;
2300 up_read(&mp->m_peraglock);
2301 break;
2302 case XFS_ALLOCTYPE_START_BNO:
2303
2304
2305
2306
2307 if ((args->userdata == XFS_ALLOC_INITIAL_USER_DATA) &&
2308 (mp->m_flags & XFS_MOUNT_32BITINODES)) {
2309 args->fsbno = XFS_AGB_TO_FSB(mp,
2310 ((mp->m_agfrotor / rotorstep) %
2311 mp->m_sb.sb_agcount), 0);
2312 bump_rotor = 1;
2313 }
2314 args->agbno = XFS_FSB_TO_AGBNO(mp, args->fsbno);
2315 args->type = XFS_ALLOCTYPE_NEAR_BNO;
2316
2317 case XFS_ALLOCTYPE_ANY_AG:
2318 case XFS_ALLOCTYPE_START_AG:
2319 case XFS_ALLOCTYPE_FIRST_AG:
2320
2321
2322
2323 if (type == XFS_ALLOCTYPE_ANY_AG) {
2324
2325
2326
2327 args->agno = sagno = (mp->m_agfrotor / rotorstep) %
2328 mp->m_sb.sb_agcount;
2329 args->type = XFS_ALLOCTYPE_THIS_AG;
2330 flags = XFS_ALLOC_FLAG_TRYLOCK;
2331 } else if (type == XFS_ALLOCTYPE_FIRST_AG) {
2332
2333
2334
2335 args->agno = XFS_FSB_TO_AGNO(mp, args->fsbno);
2336 args->type = XFS_ALLOCTYPE_THIS_AG;
2337 sagno = 0;
2338 flags = 0;
2339 } else {
2340 if (type == XFS_ALLOCTYPE_START_AG)
2341 args->type = XFS_ALLOCTYPE_THIS_AG;
2342
2343
2344
2345 args->agno = sagno = XFS_FSB_TO_AGNO(mp, args->fsbno);
2346 flags = XFS_ALLOC_FLAG_TRYLOCK;
2347 }
2348
2349
2350
2351
2352 down_read(&mp->m_peraglock);
2353 for (;;) {
2354 args->pag = &mp->m_perag[args->agno];
2355 if (no_min) args->minleft = 0;
2356 error = xfs_alloc_fix_freelist(args, flags);
2357 args->minleft = minleft;
2358 if (error) {
2359 TRACE_ALLOC("nofix", args);
2360 goto error0;
2361 }
2362
2363
2364
2365 if (args->agbp) {
2366 if ((error = xfs_alloc_ag_vextent(args)))
2367 goto error0;
2368 break;
2369 }
2370 TRACE_ALLOC("loopfailed", args);
2371
2372
2373
2374 if (args->agno == sagno &&
2375 type == XFS_ALLOCTYPE_START_BNO)
2376 args->type = XFS_ALLOCTYPE_THIS_AG;
2377
2378
2379
2380
2381
2382
2383
2384 if (++(args->agno) == mp->m_sb.sb_agcount) {
2385 if (args->firstblock != NULLFSBLOCK)
2386 args->agno = sagno;
2387 else
2388 args->agno = 0;
2389 }
2390
2391
2392
2393
2394 if (args->agno == sagno) {
2395 if (no_min == 1) {
2396 args->agbno = NULLAGBLOCK;
2397 TRACE_ALLOC("allfailed", args);
2398 break;
2399 }
2400 if (flags == 0) {
2401 no_min = 1;
2402 } else {
2403 flags = 0;
2404 if (type == XFS_ALLOCTYPE_START_BNO) {
2405 args->agbno = XFS_FSB_TO_AGBNO(mp,
2406 args->fsbno);
2407 args->type = XFS_ALLOCTYPE_NEAR_BNO;
2408 }
2409 }
2410 }
2411 }
2412 up_read(&mp->m_peraglock);
2413 if (bump_rotor || (type == XFS_ALLOCTYPE_ANY_AG)) {
2414 if (args->agno == sagno)
2415 mp->m_agfrotor = (mp->m_agfrotor + 1) %
2416 (mp->m_sb.sb_agcount * rotorstep);
2417 else
2418 mp->m_agfrotor = (args->agno * rotorstep + 1) %
2419 (mp->m_sb.sb_agcount * rotorstep);
2420 }
2421 break;
2422 default:
2423 ASSERT(0);
2424
2425 }
2426 if (args->agbno == NULLAGBLOCK)
2427 args->fsbno = NULLFSBLOCK;
2428 else {
2429 args->fsbno = XFS_AGB_TO_FSB(mp, args->agno, args->agbno);
2430#ifdef DEBUG
2431 ASSERT(args->len >= args->minlen);
2432 ASSERT(args->len <= args->maxlen);
2433 ASSERT(args->agbno % args->alignment == 0);
2434 XFS_AG_CHECK_DADDR(mp, XFS_FSB_TO_DADDR(mp, args->fsbno),
2435 args->len);
2436#endif
2437 }
2438 return 0;
2439error0:
2440 up_read(&mp->m_peraglock);
2441 return error;
2442}
2443
2444
2445
2446
2447
2448
2449int
2450xfs_free_extent(
2451 xfs_trans_t *tp,
2452 xfs_fsblock_t bno,
2453 xfs_extlen_t len)
2454{
2455 xfs_alloc_arg_t args;
2456 int error;
2457
2458 ASSERT(len != 0);
2459 memset(&args, 0, sizeof(xfs_alloc_arg_t));
2460 args.tp = tp;
2461 args.mp = tp->t_mountp;
2462 args.agno = XFS_FSB_TO_AGNO(args.mp, bno);
2463 ASSERT(args.agno < args.mp->m_sb.sb_agcount);
2464 args.agbno = XFS_FSB_TO_AGBNO(args.mp, bno);
2465 down_read(&args.mp->m_peraglock);
2466 args.pag = &args.mp->m_perag[args.agno];
2467 if ((error = xfs_alloc_fix_freelist(&args, XFS_ALLOC_FLAG_FREEING)))
2468 goto error0;
2469#ifdef DEBUG
2470 ASSERT(args.agbp != NULL);
2471 ASSERT((args.agbno + len) <=
2472 be32_to_cpu(XFS_BUF_TO_AGF(args.agbp)->agf_length));
2473#endif
2474 error = xfs_free_ag_extent(tp, args.agbp, args.agno, args.agbno, len, 0);
2475error0:
2476 up_read(&args.mp->m_peraglock);
2477 return error;
2478}
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491void
2492xfs_alloc_mark_busy(xfs_trans_t *tp,
2493 xfs_agnumber_t agno,
2494 xfs_agblock_t bno,
2495 xfs_extlen_t len)
2496{
2497 xfs_mount_t *mp;
2498 xfs_perag_busy_t *bsy;
2499 int n;
2500 SPLDECL(s);
2501
2502 mp = tp->t_mountp;
2503 s = mutex_spinlock(&mp->m_perag[agno].pagb_lock);
2504
2505
2506 for (bsy = mp->m_perag[agno].pagb_list, n = 0;
2507 n < XFS_PAGB_NUM_SLOTS;
2508 bsy++, n++) {
2509 if (bsy->busy_tp == NULL) {
2510 break;
2511 }
2512 }
2513
2514 if (n < XFS_PAGB_NUM_SLOTS) {
2515 bsy = &mp->m_perag[agno].pagb_list[n];
2516 mp->m_perag[agno].pagb_count++;
2517 TRACE_BUSY("xfs_alloc_mark_busy", "got", agno, bno, len, n, tp);
2518 bsy->busy_start = bno;
2519 bsy->busy_length = len;
2520 bsy->busy_tp = tp;
2521 xfs_trans_add_busy(tp, agno, n);
2522 } else {
2523 TRACE_BUSY("xfs_alloc_mark_busy", "FULL", agno, bno, len, -1, tp);
2524
2525
2526
2527
2528
2529
2530 xfs_trans_set_sync(tp);
2531 }
2532
2533 mutex_spinunlock(&mp->m_perag[agno].pagb_lock, s);
2534}
2535
2536void
2537xfs_alloc_clear_busy(xfs_trans_t *tp,
2538 xfs_agnumber_t agno,
2539 int idx)
2540{
2541 xfs_mount_t *mp;
2542 xfs_perag_busy_t *list;
2543 SPLDECL(s);
2544
2545 mp = tp->t_mountp;
2546
2547 s = mutex_spinlock(&mp->m_perag[agno].pagb_lock);
2548 list = mp->m_perag[agno].pagb_list;
2549
2550 ASSERT(idx < XFS_PAGB_NUM_SLOTS);
2551 if (list[idx].busy_tp == tp) {
2552 TRACE_UNBUSY("xfs_alloc_clear_busy", "found", agno, idx, tp);
2553 list[idx].busy_tp = NULL;
2554 mp->m_perag[agno].pagb_count--;
2555 } else {
2556 TRACE_UNBUSY("xfs_alloc_clear_busy", "missing", agno, idx, tp);
2557 }
2558
2559 mutex_spinunlock(&mp->m_perag[agno].pagb_lock, s);
2560}
2561
2562
2563
2564
2565
2566STATIC int
2567xfs_alloc_search_busy(xfs_trans_t *tp,
2568 xfs_agnumber_t agno,
2569 xfs_agblock_t bno,
2570 xfs_extlen_t len)
2571{
2572 xfs_mount_t *mp;
2573 xfs_perag_busy_t *bsy;
2574 int n;
2575 xfs_agblock_t uend, bend;
2576 xfs_lsn_t lsn;
2577 int cnt;
2578 SPLDECL(s);
2579
2580 mp = tp->t_mountp;
2581
2582 s = mutex_spinlock(&mp->m_perag[agno].pagb_lock);
2583 cnt = mp->m_perag[agno].pagb_count;
2584
2585 uend = bno + len - 1;
2586
2587
2588 for (bsy = mp->m_perag[agno].pagb_list, n = 0;
2589 cnt; bsy++, n++) {
2590
2591
2592
2593
2594 if (bsy->busy_tp != NULL) {
2595 bend = bsy->busy_start + bsy->busy_length - 1;
2596 if ((bno > bend) ||
2597 (uend < bsy->busy_start)) {
2598 cnt--;
2599 } else {
2600 TRACE_BUSYSEARCH("xfs_alloc_search_busy",
2601 "found1", agno, bno, len, n,
2602 tp);
2603 break;
2604 }
2605 }
2606 }
2607
2608
2609
2610
2611
2612 if (cnt) {
2613 TRACE_BUSYSEARCH("xfs_alloc_search_busy", "found", agno, bno, len, n, tp);
2614 lsn = bsy->busy_tp->t_commit_lsn;
2615 mutex_spinunlock(&mp->m_perag[agno].pagb_lock, s);
2616 xfs_log_force(mp, lsn, XFS_LOG_FORCE|XFS_LOG_SYNC);
2617 } else {
2618 TRACE_BUSYSEARCH("xfs_alloc_search_busy", "not-found", agno, bno, len, n, tp);
2619 n = -1;
2620 mutex_spinunlock(&mp->m_perag[agno].pagb_lock, s);
2621 }
2622
2623 return n;
2624}
2625