|
@@ -1835,40 +1835,47 @@ xfs_alloc_fix_freelist(
|
|
|
&agbp)))
|
|
|
return error;
|
|
|
if (!pag->pagf_init) {
|
|
|
+ ASSERT(flags & XFS_ALLOC_FLAG_TRYLOCK);
|
|
|
+ ASSERT(!(flags & XFS_ALLOC_FLAG_FREEING));
|
|
|
args->agbp = NULL;
|
|
|
return 0;
|
|
|
}
|
|
|
} else
|
|
|
agbp = NULL;
|
|
|
|
|
|
- /* If this is a metadata preferred pag and we are user data
|
|
|
+ /*
|
|
|
+ * If this is a metadata preferred pag and we are user data
|
|
|
* then try somewhere else if we are not being asked to
|
|
|
* try harder at this point
|
|
|
*/
|
|
|
- if (pag->pagf_metadata && args->userdata && flags) {
|
|
|
+ if (pag->pagf_metadata && args->userdata &&
|
|
|
+ (flags & XFS_ALLOC_FLAG_TRYLOCK)) {
|
|
|
+ ASSERT(!(flags & XFS_ALLOC_FLAG_FREEING));
|
|
|
args->agbp = NULL;
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
- need = XFS_MIN_FREELIST_PAG(pag, mp);
|
|
|
- delta = need > pag->pagf_flcount ? need - pag->pagf_flcount : 0;
|
|
|
- /*
|
|
|
- * If it looks like there isn't a long enough extent, or enough
|
|
|
- * total blocks, reject it.
|
|
|
- */
|
|
|
- longest = (pag->pagf_longest > delta) ?
|
|
|
- (pag->pagf_longest - delta) :
|
|
|
- (pag->pagf_flcount > 0 || pag->pagf_longest > 0);
|
|
|
- if (args->minlen + args->alignment + args->minalignslop - 1 > longest ||
|
|
|
- (!(flags & XFS_ALLOC_FLAG_FREEING) &&
|
|
|
- (int)(pag->pagf_freeblks + pag->pagf_flcount -
|
|
|
- need - args->total) <
|
|
|
- (int)args->minleft)) {
|
|
|
- if (agbp)
|
|
|
- xfs_trans_brelse(tp, agbp);
|
|
|
- args->agbp = NULL;
|
|
|
- return 0;
|
|
|
+ if (!(flags & XFS_ALLOC_FLAG_FREEING)) {
|
|
|
+ need = XFS_MIN_FREELIST_PAG(pag, mp);
|
|
|
+ delta = need > pag->pagf_flcount ? need - pag->pagf_flcount : 0;
|
|
|
+ /*
|
|
|
+ * If it looks like there isn't a long enough extent, or enough
|
|
|
+ * total blocks, reject it.
|
|
|
+ */
|
|
|
+ longest = (pag->pagf_longest > delta) ?
|
|
|
+ (pag->pagf_longest - delta) :
|
|
|
+ (pag->pagf_flcount > 0 || pag->pagf_longest > 0);
|
|
|
+ if ((args->minlen + args->alignment + args->minalignslop - 1) >
|
|
|
+ longest ||
|
|
|
+ ((int)(pag->pagf_freeblks + pag->pagf_flcount -
|
|
|
+ need - args->total) < (int)args->minleft)) {
|
|
|
+ if (agbp)
|
|
|
+ xfs_trans_brelse(tp, agbp);
|
|
|
+ args->agbp = NULL;
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
/*
|
|
|
* Get the a.g. freespace buffer.
|
|
|
* Can fail if we're not blocking on locks, and it's held.
|
|
@@ -1878,6 +1885,8 @@ xfs_alloc_fix_freelist(
|
|
|
&agbp)))
|
|
|
return error;
|
|
|
if (agbp == NULL) {
|
|
|
+ ASSERT(flags & XFS_ALLOC_FLAG_TRYLOCK);
|
|
|
+ ASSERT(!(flags & XFS_ALLOC_FLAG_FREEING));
|
|
|
args->agbp = NULL;
|
|
|
return 0;
|
|
|
}
|
|
@@ -1887,22 +1896,24 @@ xfs_alloc_fix_freelist(
|
|
|
*/
|
|
|
agf = XFS_BUF_TO_AGF(agbp);
|
|
|
need = XFS_MIN_FREELIST(agf, mp);
|
|
|
- delta = need > be32_to_cpu(agf->agf_flcount) ?
|
|
|
- (need - be32_to_cpu(agf->agf_flcount)) : 0;
|
|
|
/*
|
|
|
* If there isn't enough total or single-extent, reject it.
|
|
|
*/
|
|
|
- longest = be32_to_cpu(agf->agf_longest);
|
|
|
- longest = (longest > delta) ? (longest - delta) :
|
|
|
- (be32_to_cpu(agf->agf_flcount) > 0 || longest > 0);
|
|
|
- if (args->minlen + args->alignment + args->minalignslop - 1 > longest ||
|
|
|
- (!(flags & XFS_ALLOC_FLAG_FREEING) &&
|
|
|
- (int)(be32_to_cpu(agf->agf_freeblks) +
|
|
|
- be32_to_cpu(agf->agf_flcount) - need - args->total) <
|
|
|
- (int)args->minleft)) {
|
|
|
- xfs_trans_brelse(tp, agbp);
|
|
|
- args->agbp = NULL;
|
|
|
- return 0;
|
|
|
+ if (!(flags & XFS_ALLOC_FLAG_FREEING)) {
|
|
|
+ delta = need > be32_to_cpu(agf->agf_flcount) ?
|
|
|
+ (need - be32_to_cpu(agf->agf_flcount)) : 0;
|
|
|
+ longest = be32_to_cpu(agf->agf_longest);
|
|
|
+ longest = (longest > delta) ? (longest - delta) :
|
|
|
+ (be32_to_cpu(agf->agf_flcount) > 0 || longest > 0);
|
|
|
+ if ((args->minlen + args->alignment + args->minalignslop - 1) >
|
|
|
+ longest ||
|
|
|
+ ((int)(be32_to_cpu(agf->agf_freeblks) +
|
|
|
+ be32_to_cpu(agf->agf_flcount) - need - args->total) <
|
|
|
+ (int)args->minleft)) {
|
|
|
+ xfs_trans_brelse(tp, agbp);
|
|
|
+ args->agbp = NULL;
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
}
|
|
|
/*
|
|
|
* Make the freelist shorter if it's too long.
|
|
@@ -1950,12 +1961,11 @@ xfs_alloc_fix_freelist(
|
|
|
* on a completely full ag.
|
|
|
*/
|
|
|
if (targs.agbno == NULLAGBLOCK) {
|
|
|
- if (!(flags & XFS_ALLOC_FLAG_FREEING)) {
|
|
|
- xfs_trans_brelse(tp, agflbp);
|
|
|
- args->agbp = NULL;
|
|
|
- return 0;
|
|
|
- }
|
|
|
- break;
|
|
|
+ if (flags & XFS_ALLOC_FLAG_FREEING)
|
|
|
+ break;
|
|
|
+ xfs_trans_brelse(tp, agflbp);
|
|
|
+ args->agbp = NULL;
|
|
|
+ return 0;
|
|
|
}
|
|
|
/*
|
|
|
* Put each allocated block on the list.
|
|
@@ -2442,31 +2452,26 @@ xfs_free_extent(
|
|
|
xfs_fsblock_t bno, /* starting block number of extent */
|
|
|
xfs_extlen_t len) /* length of extent */
|
|
|
{
|
|
|
-#ifdef DEBUG
|
|
|
- xfs_agf_t *agf; /* a.g. freespace header */
|
|
|
-#endif
|
|
|
- xfs_alloc_arg_t args; /* allocation argument structure */
|
|
|
+ xfs_alloc_arg_t args;
|
|
|
int error;
|
|
|
|
|
|
ASSERT(len != 0);
|
|
|
+ memset(&args, 0, sizeof(xfs_alloc_arg_t));
|
|
|
args.tp = tp;
|
|
|
args.mp = tp->t_mountp;
|
|
|
args.agno = XFS_FSB_TO_AGNO(args.mp, bno);
|
|
|
ASSERT(args.agno < args.mp->m_sb.sb_agcount);
|
|
|
args.agbno = XFS_FSB_TO_AGBNO(args.mp, bno);
|
|
|
- args.alignment = 1;
|
|
|
- args.minlen = args.minleft = args.minalignslop = 0;
|
|
|
down_read(&args.mp->m_peraglock);
|
|
|
args.pag = &args.mp->m_perag[args.agno];
|
|
|
if ((error = xfs_alloc_fix_freelist(&args, XFS_ALLOC_FLAG_FREEING)))
|
|
|
goto error0;
|
|
|
#ifdef DEBUG
|
|
|
ASSERT(args.agbp != NULL);
|
|
|
- agf = XFS_BUF_TO_AGF(args.agbp);
|
|
|
- ASSERT(args.agbno + len <= be32_to_cpu(agf->agf_length));
|
|
|
+ ASSERT((args.agbno + len) <=
|
|
|
+ be32_to_cpu(XFS_BUF_TO_AGF(args.agbp)->agf_length));
|
|
|
#endif
|
|
|
- error = xfs_free_ag_extent(tp, args.agbp, args.agno, args.agbno,
|
|
|
- len, 0);
|
|
|
+ error = xfs_free_ag_extent(tp, args.agbp, args.agno, args.agbno, len, 0);
|
|
|
error0:
|
|
|
up_read(&args.mp->m_peraglock);
|
|
|
return error;
|