Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f477cedc authored by Dave Chinner's avatar Dave Chinner
Browse files

Merge branch 'xfs-4.8-misc-fixes-2' into for-next

parents 9b7fad20 19b54ee6
Loading
Loading
Loading
Loading
+56 −43
Original line number Original line Diff line number Diff line
@@ -1839,19 +1839,8 @@ void
xfs_alloc_compute_maxlevels(
xfs_alloc_compute_maxlevels(
	xfs_mount_t	*mp)	/* file system mount structure */
	xfs_mount_t	*mp)	/* file system mount structure */
{
{
	int		level;
	mp->m_ag_maxlevels = xfs_btree_compute_maxlevels(mp, mp->m_alloc_mnr,
	uint		maxblocks;
			(mp->m_sb.sb_agblocks + 1) / 2);
	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;
}
}


/*
/*
@@ -2658,55 +2647,79 @@ xfs_alloc_vextent(
	return error;
	return error;
}
}


/*
/* Ensure that the freelist is at full capacity. */
 * Free an extent.
int
 * Just break up the extent address and hand off to xfs_free_ag_extent
xfs_free_extent_fix_freelist(
 * after fixing up the freelist.
	struct xfs_trans	*tp,
 */
	xfs_agnumber_t		agno,
int				/* error */
	struct xfs_buf		**agbp)
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 */
{
{
	xfs_alloc_arg_t	args;
	struct xfs_alloc_arg	args;
	int			error;
	int			error;


	ASSERT(len != 0);
	memset(&args, 0, sizeof(struct xfs_alloc_arg));
	memset(&args, 0, sizeof(xfs_alloc_arg_t));
	args.tp = tp;
	args.tp = tp;
	args.mp = tp->t_mountp;
	args.mp = tp->t_mountp;
	args.agno = agno;


	/*
	/*
	 * validate that the block number is legal - the enables us to detect
	 * validate that the block number is legal - the enables us to detect
	 * and handle a silent filesystem corruption rather than crashing.
	 * 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)
	if (args.agno >= args.mp->m_sb.sb_agcount)
		return -EFSCORRUPTED;
		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);
	args.pag = xfs_perag_get(args.mp, args.agno);
	ASSERT(args.pag);
	ASSERT(args.pag);


	error = xfs_alloc_fix_freelist(&args, XFS_ALLOC_FLAG_FREEING);
	error = xfs_alloc_fix_freelist(&args, XFS_ALLOC_FLAG_FREEING);
	if (error)
	if (error)
		goto error0;
		goto out;


	/* validate the extent size is legal now we have the agf locked */
	*agbp = args.agbp;
	if (args.agbno + len >
out:
			be32_to_cpu(XFS_BUF_TO_AGF(args.agbp)->agf_length)) {
	xfs_perag_put(args.pag);
		error = -EFSCORRUPTED;
	return error;
		goto error0;
}
}


	error = xfs_free_ag_extent(tp, args.agbp, args.agno, args.agbno, len, 0);
/*
	if (!error)
 * Free an extent.
		xfs_extent_busy_insert(tp, args.agno, args.agbno, len, 0);
 * Just break up the extent address and hand off to xfs_free_ag_extent
error0:
 * after fixing up the freelist.
	xfs_perag_put(args.pag);
 */
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;
	return error;
}
}
+2 −0
Original line number Original line Diff line number Diff line
@@ -229,5 +229,7 @@ xfs_alloc_get_rec(
int xfs_read_agf(struct xfs_mount *mp, struct xfs_trans *tp,
int xfs_read_agf(struct xfs_mount *mp, struct xfs_trans *tp,
			xfs_agnumber_t agno, int flags, struct xfs_buf **bpp);
			xfs_agnumber_t agno, int flags, struct xfs_buf **bpp);
int xfs_alloc_fix_freelist(struct xfs_alloc_arg *args, int flags);
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__ */
#endif	/* __XFS_ALLOC_H__ */
+17 −34
Original line number Original line Diff line number Diff line
@@ -570,14 +570,12 @@ xfs_bmap_validate_ret(
 */
 */
void
void
xfs_bmap_add_free(
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_fsblock_t		bno,		/* fs block number of extent */
	xfs_filblks_t		len,		/* length 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_bmap_free_item_t	*cur;		/* current (next) element */
	struct xfs_bmap_free_item	*new;		/* new element */
	xfs_bmap_free_item_t	*new;		/* new element */
	xfs_bmap_free_item_t	*prev;		/* previous element */
#ifdef DEBUG
#ifdef DEBUG
	xfs_agnumber_t		agno;
	xfs_agnumber_t		agno;
	xfs_agblock_t		agbno;
	xfs_agblock_t		agbno;
@@ -597,17 +595,7 @@ xfs_bmap_add_free(
	new = kmem_zone_alloc(xfs_bmap_free_item_zone, KM_SLEEP);
	new = kmem_zone_alloc(xfs_bmap_free_item_zone, KM_SLEEP);
	new->xbfi_startblock = bno;
	new->xbfi_startblock = bno;
	new->xbfi_blockcount = (xfs_extlen_t)len;
	new->xbfi_blockcount = (xfs_extlen_t)len;
	for (prev = NULL, cur = flist->xbf_first;
	list_add(&new->xbfi_list, &flist->xbf_flist);
	     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;
	flist->xbf_count++;
	flist->xbf_count++;
}
}


@@ -617,14 +605,10 @@ xfs_bmap_add_free(
 */
 */
void
void
xfs_bmap_del_free(
xfs_bmap_del_free(
	xfs_bmap_free_t		*flist,	/* free item list header */
	struct xfs_bmap_free		*flist,	/* free item list header */
	xfs_bmap_free_item_t	*prev,	/* previous item on list, if any */
	struct xfs_bmap_free_item	*free)	/* list item to be freed */
	xfs_bmap_free_item_t	*free)	/* list item to be freed */
{
{
	if (prev)
	list_del(&free->xbfi_list);
		prev->xbfi_next = free->xbfi_next;
	else
		flist->xbf_first = free->xbfi_next;
	flist->xbf_count--;
	flist->xbf_count--;
	kmem_zone_free(xfs_bmap_free_item_zone, free);
	kmem_zone_free(xfs_bmap_free_item_zone, free);
}
}
@@ -634,17 +618,16 @@ xfs_bmap_del_free(
 */
 */
void
void
xfs_bmap_cancel(
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 */
	struct xfs_bmap_free_item	*free;	/* free list item */
	xfs_bmap_free_item_t	*next;


	if (flist->xbf_count == 0)
	if (flist->xbf_count == 0)
		return;
		return;
	ASSERT(flist->xbf_first != NULL);
	while (!list_empty(&flist->xbf_flist)) {
	for (free = flist->xbf_first; free; free = next) {
		free = list_first_entry(&flist->xbf_flist,
		next = free->xbfi_next;
				struct xfs_bmap_free_item, xbfi_list);
		xfs_bmap_del_free(flist, NULL, free);
		xfs_bmap_del_free(flist, free);
	}
	}
	ASSERT(flist->xbf_count == 0);
	ASSERT(flist->xbf_count == 0);
}
}
@@ -699,7 +682,7 @@ xfs_bmap_btree_to_extents(
	cblock = XFS_BUF_TO_BLOCK(cbp);
	cblock = XFS_BUF_TO_BLOCK(cbp);
	if ((error = xfs_btree_check_block(cur, cblock, 0, cbp)))
	if ((error = xfs_btree_check_block(cur, cblock, 0, cbp)))
		return error;
		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--;
	ip->i_d.di_nblocks--;
	xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, -1L);
	xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, -1L);
	xfs_trans_binval(tp, cbp);
	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 we need to, add to list of extents to delete.
	 */
	 */
	if (do_fx)
	if (do_fx)
		xfs_bmap_add_free(del->br_startblock, del->br_blockcount, flist,
		xfs_bmap_add_free(mp, flist, del->br_startblock,
			mp);
			del->br_blockcount);
	/*
	/*
	 * Adjust inode # blocks in the file.
	 * Adjust inode # blocks in the file.
	 */
	 */
+10 −8
Original line number Original line Diff line number Diff line
@@ -62,12 +62,12 @@ struct xfs_bmalloca {
 * List of extents to be free "later".
 * List of extents to be free "later".
 * The list is kept sorted on xbf_startblock.
 * 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_fsblock_t		xbfi_startblock;/* starting fs block number */
	xfs_extlen_t		xbfi_blockcount;/* number of blocks in extent */
	xfs_extlen_t		xbfi_blockcount;/* number of blocks in extent */
	struct xfs_bmap_free_item *xbfi_next;	/* link to next entry */
	struct list_head	xbfi_list;
} xfs_bmap_free_item_t;
};


/*
/*
 * Header for free extent list.
 * Header for free extent list.
@@ -85,7 +85,7 @@ typedef struct xfs_bmap_free_item
 */
 */
typedef	struct xfs_bmap_free
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_count;	/* count of items on list */
	int			xbf_low;	/* alloc in low mode */
	int			xbf_low;	/* alloc in low mode */
} xfs_bmap_free_t;
} 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)
static inline void xfs_bmap_init(xfs_bmap_free_t *flp, xfs_fsblock_t *fbp)
{
{
	((flp)->xbf_first = NULL, (flp)->xbf_count = 0, \
	INIT_LIST_HEAD(&flp->xbf_flist);
		(flp)->xbf_low = 0, *(fbp) = NULLFSBLOCK);
	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);
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_local_to_extents_empty(struct xfs_inode *ip, int whichfork);
void	xfs_bmap_add_free(xfs_fsblock_t bno, xfs_filblks_t len,
void	xfs_bmap_add_free(struct xfs_mount *mp, struct xfs_bmap_free *flist,
		struct xfs_bmap_free *flist, struct xfs_mount *mp);
			  xfs_fsblock_t bno, xfs_filblks_t len);
void	xfs_bmap_cancel(struct xfs_bmap_free *flist);
void	xfs_bmap_cancel(struct xfs_bmap_free *flist);
int	xfs_bmap_finish(struct xfs_trans **tp, struct xfs_bmap_free *flist,
int	xfs_bmap_finish(struct xfs_trans **tp, struct xfs_bmap_free *flist,
			struct xfs_inode *ip);
			struct xfs_inode *ip);
+1 −1
Original line number Original line Diff line number Diff line
@@ -526,7 +526,7 @@ xfs_bmbt_free_block(
	struct xfs_trans	*tp = cur->bc_tp;
	struct xfs_trans	*tp = cur->bc_tp;
	xfs_fsblock_t		fsbno = XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(bp));
	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--;
	ip->i_d.di_nblocks--;


	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
Loading