Merge branch 'xfs-4.8-misc-fixes-2' into for-next
This commit is contained in:
@@ -1839,19 +1839,8 @@ void
|
||||
xfs_alloc_compute_maxlevels(
|
||||
xfs_mount_t *mp) /* file system mount structure */
|
||||
{
|
||||
int level;
|
||||
uint maxblocks;
|
||||
uint maxleafents;
|
||||
int minleafrecs;
|
||||
int minnoderecs;
|
||||
|
||||
maxleafents = (mp->m_sb.sb_agblocks + 1) / 2;
|
||||
minleafrecs = mp->m_alloc_mnr[0];
|
||||
minnoderecs = mp->m_alloc_mnr[1];
|
||||
maxblocks = (maxleafents + minleafrecs - 1) / minleafrecs;
|
||||
for (level = 1; maxblocks > 1; level++)
|
||||
maxblocks = (maxblocks + minnoderecs - 1) / minnoderecs;
|
||||
mp->m_ag_maxlevels = level;
|
||||
mp->m_ag_maxlevels = xfs_btree_compute_maxlevels(mp, mp->m_alloc_mnr,
|
||||
(mp->m_sb.sb_agblocks + 1) / 2);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2658,55 +2647,79 @@ error0:
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free an extent.
|
||||
* Just break up the extent address and hand off to xfs_free_ag_extent
|
||||
* after fixing up the freelist.
|
||||
*/
|
||||
int /* error */
|
||||
xfs_free_extent(
|
||||
xfs_trans_t *tp, /* transaction pointer */
|
||||
xfs_fsblock_t bno, /* starting block number of extent */
|
||||
xfs_extlen_t len) /* length of extent */
|
||||
/* Ensure that the freelist is at full capacity. */
|
||||
int
|
||||
xfs_free_extent_fix_freelist(
|
||||
struct xfs_trans *tp,
|
||||
xfs_agnumber_t agno,
|
||||
struct xfs_buf **agbp)
|
||||
{
|
||||
xfs_alloc_arg_t args;
|
||||
int error;
|
||||
struct xfs_alloc_arg args;
|
||||
int error;
|
||||
|
||||
ASSERT(len != 0);
|
||||
memset(&args, 0, sizeof(xfs_alloc_arg_t));
|
||||
memset(&args, 0, sizeof(struct xfs_alloc_arg));
|
||||
args.tp = tp;
|
||||
args.mp = tp->t_mountp;
|
||||
args.agno = agno;
|
||||
|
||||
/*
|
||||
* validate that the block number is legal - the enables us to detect
|
||||
* and handle a silent filesystem corruption rather than crashing.
|
||||
*/
|
||||
args.agno = XFS_FSB_TO_AGNO(args.mp, bno);
|
||||
if (args.agno >= args.mp->m_sb.sb_agcount)
|
||||
return -EFSCORRUPTED;
|
||||
|
||||
args.agbno = XFS_FSB_TO_AGBNO(args.mp, bno);
|
||||
if (args.agbno >= args.mp->m_sb.sb_agblocks)
|
||||
return -EFSCORRUPTED;
|
||||
|
||||
args.pag = xfs_perag_get(args.mp, args.agno);
|
||||
ASSERT(args.pag);
|
||||
|
||||
error = xfs_alloc_fix_freelist(&args, XFS_ALLOC_FLAG_FREEING);
|
||||
if (error)
|
||||
goto error0;
|
||||
goto out;
|
||||
|
||||
/* validate the extent size is legal now we have the agf locked */
|
||||
if (args.agbno + len >
|
||||
be32_to_cpu(XFS_BUF_TO_AGF(args.agbp)->agf_length)) {
|
||||
error = -EFSCORRUPTED;
|
||||
goto error0;
|
||||
}
|
||||
|
||||
error = xfs_free_ag_extent(tp, args.agbp, args.agno, args.agbno, len, 0);
|
||||
if (!error)
|
||||
xfs_extent_busy_insert(tp, args.agno, args.agbno, len, 0);
|
||||
error0:
|
||||
*agbp = args.agbp;
|
||||
out:
|
||||
xfs_perag_put(args.pag);
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free an extent.
|
||||
* Just break up the extent address and hand off to xfs_free_ag_extent
|
||||
* after fixing up the freelist.
|
||||
*/
|
||||
int /* error */
|
||||
xfs_free_extent(
|
||||
struct xfs_trans *tp, /* transaction pointer */
|
||||
xfs_fsblock_t bno, /* starting block number of extent */
|
||||
xfs_extlen_t len) /* length of extent */
|
||||
{
|
||||
struct xfs_mount *mp = tp->t_mountp;
|
||||
struct xfs_buf *agbp;
|
||||
xfs_agnumber_t agno = XFS_FSB_TO_AGNO(mp, bno);
|
||||
xfs_agblock_t agbno = XFS_FSB_TO_AGBNO(mp, bno);
|
||||
int error;
|
||||
|
||||
ASSERT(len != 0);
|
||||
|
||||
error = xfs_free_extent_fix_freelist(tp, agno, &agbp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
XFS_WANT_CORRUPTED_GOTO(mp, agbno < mp->m_sb.sb_agblocks, err);
|
||||
|
||||
/* validate the extent size is legal now we have the agf locked */
|
||||
XFS_WANT_CORRUPTED_GOTO(mp,
|
||||
agbno + len <= be32_to_cpu(XFS_BUF_TO_AGF(agbp)->agf_length),
|
||||
err);
|
||||
|
||||
error = xfs_free_ag_extent(tp, agbp, agno, agbno, len, 0);
|
||||
if (error)
|
||||
goto err;
|
||||
|
||||
xfs_extent_busy_insert(tp, agno, agbno, len, 0);
|
||||
return 0;
|
||||
|
||||
err:
|
||||
xfs_trans_brelse(tp, agbp);
|
||||
return error;
|
||||
}
|
||||
|
@@ -229,5 +229,7 @@ xfs_alloc_get_rec(
|
||||
int xfs_read_agf(struct xfs_mount *mp, struct xfs_trans *tp,
|
||||
xfs_agnumber_t agno, int flags, struct xfs_buf **bpp);
|
||||
int xfs_alloc_fix_freelist(struct xfs_alloc_arg *args, int flags);
|
||||
int xfs_free_extent_fix_freelist(struct xfs_trans *tp, xfs_agnumber_t agno,
|
||||
struct xfs_buf **agbp);
|
||||
|
||||
#endif /* __XFS_ALLOC_H__ */
|
||||
|
@@ -570,14 +570,12 @@ xfs_bmap_validate_ret(
|
||||
*/
|
||||
void
|
||||
xfs_bmap_add_free(
|
||||
struct xfs_mount *mp, /* mount point structure */
|
||||
struct xfs_bmap_free *flist, /* list of extents */
|
||||
xfs_fsblock_t bno, /* fs block number of extent */
|
||||
xfs_filblks_t len, /* length of extent */
|
||||
xfs_bmap_free_t *flist, /* list of extents */
|
||||
xfs_mount_t *mp) /* mount point structure */
|
||||
xfs_filblks_t len) /* length of extent */
|
||||
{
|
||||
xfs_bmap_free_item_t *cur; /* current (next) element */
|
||||
xfs_bmap_free_item_t *new; /* new element */
|
||||
xfs_bmap_free_item_t *prev; /* previous element */
|
||||
struct xfs_bmap_free_item *new; /* new element */
|
||||
#ifdef DEBUG
|
||||
xfs_agnumber_t agno;
|
||||
xfs_agblock_t agbno;
|
||||
@@ -597,17 +595,7 @@ xfs_bmap_add_free(
|
||||
new = kmem_zone_alloc(xfs_bmap_free_item_zone, KM_SLEEP);
|
||||
new->xbfi_startblock = bno;
|
||||
new->xbfi_blockcount = (xfs_extlen_t)len;
|
||||
for (prev = NULL, cur = flist->xbf_first;
|
||||
cur != NULL;
|
||||
prev = cur, cur = cur->xbfi_next) {
|
||||
if (cur->xbfi_startblock >= bno)
|
||||
break;
|
||||
}
|
||||
if (prev)
|
||||
prev->xbfi_next = new;
|
||||
else
|
||||
flist->xbf_first = new;
|
||||
new->xbfi_next = cur;
|
||||
list_add(&new->xbfi_list, &flist->xbf_flist);
|
||||
flist->xbf_count++;
|
||||
}
|
||||
|
||||
@@ -617,14 +605,10 @@ xfs_bmap_add_free(
|
||||
*/
|
||||
void
|
||||
xfs_bmap_del_free(
|
||||
xfs_bmap_free_t *flist, /* free item list header */
|
||||
xfs_bmap_free_item_t *prev, /* previous item on list, if any */
|
||||
xfs_bmap_free_item_t *free) /* list item to be freed */
|
||||
struct xfs_bmap_free *flist, /* free item list header */
|
||||
struct xfs_bmap_free_item *free) /* list item to be freed */
|
||||
{
|
||||
if (prev)
|
||||
prev->xbfi_next = free->xbfi_next;
|
||||
else
|
||||
flist->xbf_first = free->xbfi_next;
|
||||
list_del(&free->xbfi_list);
|
||||
flist->xbf_count--;
|
||||
kmem_zone_free(xfs_bmap_free_item_zone, free);
|
||||
}
|
||||
@@ -634,17 +618,16 @@ xfs_bmap_del_free(
|
||||
*/
|
||||
void
|
||||
xfs_bmap_cancel(
|
||||
xfs_bmap_free_t *flist) /* list of bmap_free_items */
|
||||
struct xfs_bmap_free *flist) /* list of bmap_free_items */
|
||||
{
|
||||
xfs_bmap_free_item_t *free; /* free list item */
|
||||
xfs_bmap_free_item_t *next;
|
||||
struct xfs_bmap_free_item *free; /* free list item */
|
||||
|
||||
if (flist->xbf_count == 0)
|
||||
return;
|
||||
ASSERT(flist->xbf_first != NULL);
|
||||
for (free = flist->xbf_first; free; free = next) {
|
||||
next = free->xbfi_next;
|
||||
xfs_bmap_del_free(flist, NULL, free);
|
||||
while (!list_empty(&flist->xbf_flist)) {
|
||||
free = list_first_entry(&flist->xbf_flist,
|
||||
struct xfs_bmap_free_item, xbfi_list);
|
||||
xfs_bmap_del_free(flist, free);
|
||||
}
|
||||
ASSERT(flist->xbf_count == 0);
|
||||
}
|
||||
@@ -699,7 +682,7 @@ xfs_bmap_btree_to_extents(
|
||||
cblock = XFS_BUF_TO_BLOCK(cbp);
|
||||
if ((error = xfs_btree_check_block(cur, cblock, 0, cbp)))
|
||||
return error;
|
||||
xfs_bmap_add_free(cbno, 1, cur->bc_private.b.flist, mp);
|
||||
xfs_bmap_add_free(mp, cur->bc_private.b.flist, cbno, 1);
|
||||
ip->i_d.di_nblocks--;
|
||||
xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, -1L);
|
||||
xfs_trans_binval(tp, cbp);
|
||||
@@ -5073,8 +5056,8 @@ xfs_bmap_del_extent(
|
||||
* If we need to, add to list of extents to delete.
|
||||
*/
|
||||
if (do_fx)
|
||||
xfs_bmap_add_free(del->br_startblock, del->br_blockcount, flist,
|
||||
mp);
|
||||
xfs_bmap_add_free(mp, flist, del->br_startblock,
|
||||
del->br_blockcount);
|
||||
/*
|
||||
* Adjust inode # blocks in the file.
|
||||
*/
|
||||
|
@@ -62,12 +62,12 @@ struct xfs_bmalloca {
|
||||
* List of extents to be free "later".
|
||||
* The list is kept sorted on xbf_startblock.
|
||||
*/
|
||||
typedef struct xfs_bmap_free_item
|
||||
struct xfs_bmap_free_item
|
||||
{
|
||||
xfs_fsblock_t xbfi_startblock;/* starting fs block number */
|
||||
xfs_extlen_t xbfi_blockcount;/* number of blocks in extent */
|
||||
struct xfs_bmap_free_item *xbfi_next; /* link to next entry */
|
||||
} xfs_bmap_free_item_t;
|
||||
struct list_head xbfi_list;
|
||||
};
|
||||
|
||||
/*
|
||||
* Header for free extent list.
|
||||
@@ -85,7 +85,7 @@ typedef struct xfs_bmap_free_item
|
||||
*/
|
||||
typedef struct xfs_bmap_free
|
||||
{
|
||||
xfs_bmap_free_item_t *xbf_first; /* list of to-be-free extents */
|
||||
struct list_head xbf_flist; /* list of to-be-free extents */
|
||||
int xbf_count; /* count of items on list */
|
||||
int xbf_low; /* alloc in low mode */
|
||||
} xfs_bmap_free_t;
|
||||
@@ -141,8 +141,10 @@ static inline int xfs_bmapi_aflag(int w)
|
||||
|
||||
static inline void xfs_bmap_init(xfs_bmap_free_t *flp, xfs_fsblock_t *fbp)
|
||||
{
|
||||
((flp)->xbf_first = NULL, (flp)->xbf_count = 0, \
|
||||
(flp)->xbf_low = 0, *(fbp) = NULLFSBLOCK);
|
||||
INIT_LIST_HEAD(&flp->xbf_flist);
|
||||
flp->xbf_count = 0;
|
||||
flp->xbf_low = 0;
|
||||
*fbp = NULLFSBLOCK;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -191,8 +193,8 @@ void xfs_bmap_trace_exlist(struct xfs_inode *ip, xfs_extnum_t cnt,
|
||||
|
||||
int xfs_bmap_add_attrfork(struct xfs_inode *ip, int size, int rsvd);
|
||||
void xfs_bmap_local_to_extents_empty(struct xfs_inode *ip, int whichfork);
|
||||
void xfs_bmap_add_free(xfs_fsblock_t bno, xfs_filblks_t len,
|
||||
struct xfs_bmap_free *flist, struct xfs_mount *mp);
|
||||
void xfs_bmap_add_free(struct xfs_mount *mp, struct xfs_bmap_free *flist,
|
||||
xfs_fsblock_t bno, xfs_filblks_t len);
|
||||
void xfs_bmap_cancel(struct xfs_bmap_free *flist);
|
||||
int xfs_bmap_finish(struct xfs_trans **tp, struct xfs_bmap_free *flist,
|
||||
struct xfs_inode *ip);
|
||||
|
@@ -526,7 +526,7 @@ xfs_bmbt_free_block(
|
||||
struct xfs_trans *tp = cur->bc_tp;
|
||||
xfs_fsblock_t fsbno = XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(bp));
|
||||
|
||||
xfs_bmap_add_free(fsbno, 1, cur->bc_private.b.flist, mp);
|
||||
xfs_bmap_add_free(mp, cur->bc_private.b.flist, fsbno, 1);
|
||||
ip->i_d.di_nblocks--;
|
||||
|
||||
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
|
||||
|
@@ -4152,3 +4152,22 @@ xfs_btree_sblock_verify(
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the number of btree levels needed to store a given number of
|
||||
* records in a short-format btree.
|
||||
*/
|
||||
uint
|
||||
xfs_btree_compute_maxlevels(
|
||||
struct xfs_mount *mp,
|
||||
uint *limits,
|
||||
unsigned long len)
|
||||
{
|
||||
uint level;
|
||||
unsigned long maxblocks;
|
||||
|
||||
maxblocks = (len + limits[0] - 1) / limits[0];
|
||||
for (level = 1; maxblocks > 1; level++)
|
||||
maxblocks = (maxblocks + limits[1] - 1) / limits[1];
|
||||
return level;
|
||||
}
|
||||
|
@@ -474,5 +474,7 @@ static inline int xfs_btree_get_level(struct xfs_btree_block *block)
|
||||
|
||||
bool xfs_btree_sblock_v5hdr_verify(struct xfs_buf *bp);
|
||||
bool xfs_btree_sblock_verify(struct xfs_buf *bp, unsigned int max_recs);
|
||||
uint xfs_btree_compute_maxlevels(struct xfs_mount *mp, uint *limits,
|
||||
unsigned long len);
|
||||
|
||||
#endif /* __XFS_BTREE_H__ */
|
||||
|
@@ -1828,9 +1828,8 @@ xfs_difree_inode_chunk(
|
||||
|
||||
if (!xfs_inobt_issparse(rec->ir_holemask)) {
|
||||
/* not sparse, calculate extent info directly */
|
||||
xfs_bmap_add_free(XFS_AGB_TO_FSB(mp, agno,
|
||||
XFS_AGINO_TO_AGBNO(mp, rec->ir_startino)),
|
||||
mp->m_ialloc_blks, flist, mp);
|
||||
xfs_bmap_add_free(mp, flist, XFS_AGB_TO_FSB(mp, agno, sagbno),
|
||||
mp->m_ialloc_blks);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1873,8 +1872,8 @@ xfs_difree_inode_chunk(
|
||||
|
||||
ASSERT(agbno % mp->m_sb.sb_spino_align == 0);
|
||||
ASSERT(contigblk % mp->m_sb.sb_spino_align == 0);
|
||||
xfs_bmap_add_free(XFS_AGB_TO_FSB(mp, agno, agbno), contigblk,
|
||||
flist, mp);
|
||||
xfs_bmap_add_free(mp, flist, XFS_AGB_TO_FSB(mp, agno, agbno),
|
||||
contigblk);
|
||||
|
||||
/* reset range to current bit and carry on... */
|
||||
startidx = endidx = nextbit;
|
||||
@@ -2395,20 +2394,11 @@ void
|
||||
xfs_ialloc_compute_maxlevels(
|
||||
xfs_mount_t *mp) /* file system mount structure */
|
||||
{
|
||||
int level;
|
||||
uint maxblocks;
|
||||
uint maxleafents;
|
||||
int minleafrecs;
|
||||
int minnoderecs;
|
||||
uint inodes;
|
||||
|
||||
maxleafents = (1LL << XFS_INO_AGINO_BITS(mp)) >>
|
||||
XFS_INODES_PER_CHUNK_LOG;
|
||||
minleafrecs = mp->m_inobt_mnr[0];
|
||||
minnoderecs = mp->m_inobt_mnr[1];
|
||||
maxblocks = (maxleafents + minleafrecs - 1) / minleafrecs;
|
||||
for (level = 1; maxblocks > 1; level++)
|
||||
maxblocks = (maxblocks + minnoderecs - 1) / minnoderecs;
|
||||
mp->m_in_maxlevels = level;
|
||||
inodes = (1LL << XFS_INO_AGINO_BITS(mp)) >> XFS_INODES_PER_CHUNK_LOG;
|
||||
mp->m_in_maxlevels = xfs_btree_compute_maxlevels(mp, mp->m_inobt_mnr,
|
||||
inodes);
|
||||
}
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user