mirror of
https://github.com/torvalds/linux.git
synced 2024-11-02 02:01:29 +00:00
xfs: factor out xfs_da_grow_inode_int
xfs_da_grow_inode and xfs_dir2_grow_inode are mostly duplicate code. Factor the meat of those two functions into a new common helper. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Alex Elder <aelder@sgi.com> Reviewed-by: Dave Chinner <dchinner@redhat.com>
This commit is contained in:
parent
a230a1df40
commit
77936d0280
@ -1543,79 +1543,62 @@ const struct xfs_nameops xfs_default_nameops = {
|
|||||||
.compname = xfs_da_compname
|
.compname = xfs_da_compname
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
* Add a block to the btree ahead of the file.
|
|
||||||
* Return the new block number to the caller.
|
|
||||||
*/
|
|
||||||
int
|
int
|
||||||
xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno)
|
xfs_da_grow_inode_int(
|
||||||
|
struct xfs_da_args *args,
|
||||||
|
xfs_fileoff_t *bno,
|
||||||
|
int count)
|
||||||
{
|
{
|
||||||
xfs_fileoff_t bno, b;
|
struct xfs_trans *tp = args->trans;
|
||||||
xfs_bmbt_irec_t map;
|
struct xfs_inode *dp = args->dp;
|
||||||
xfs_bmbt_irec_t *mapp;
|
int w = args->whichfork;
|
||||||
xfs_inode_t *dp;
|
xfs_drfsbno_t nblks = dp->i_d.di_nblocks;
|
||||||
int nmap, error, w, count, c, got, i, mapi;
|
struct xfs_bmbt_irec map, *mapp;
|
||||||
xfs_trans_t *tp;
|
int nmap, error, got, i, mapi;
|
||||||
xfs_mount_t *mp;
|
|
||||||
xfs_drfsbno_t nblks;
|
|
||||||
|
|
||||||
dp = args->dp;
|
|
||||||
mp = dp->i_mount;
|
|
||||||
w = args->whichfork;
|
|
||||||
tp = args->trans;
|
|
||||||
nblks = dp->i_d.di_nblocks;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* For new directories adjust the file offset and block count.
|
|
||||||
*/
|
|
||||||
if (w == XFS_DATA_FORK) {
|
|
||||||
bno = mp->m_dirleafblk;
|
|
||||||
count = mp->m_dirblkfsbs;
|
|
||||||
} else {
|
|
||||||
bno = 0;
|
|
||||||
count = 1;
|
|
||||||
}
|
|
||||||
/*
|
/*
|
||||||
* Find a spot in the file space to put the new block.
|
* Find a spot in the file space to put the new block.
|
||||||
*/
|
*/
|
||||||
if ((error = xfs_bmap_first_unused(tp, dp, count, &bno, w)))
|
error = xfs_bmap_first_unused(tp, dp, count, bno, w);
|
||||||
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
if (w == XFS_DATA_FORK)
|
|
||||||
ASSERT(bno >= mp->m_dirleafblk && bno < mp->m_dirfreeblk);
|
|
||||||
/*
|
/*
|
||||||
* Try mapping it in one filesystem block.
|
* Try mapping it in one filesystem block.
|
||||||
*/
|
*/
|
||||||
nmap = 1;
|
nmap = 1;
|
||||||
ASSERT(args->firstblock != NULL);
|
ASSERT(args->firstblock != NULL);
|
||||||
if ((error = xfs_bmapi(tp, dp, bno, count,
|
error = xfs_bmapi(tp, dp, *bno, count,
|
||||||
xfs_bmapi_aflag(w)|XFS_BMAPI_WRITE|XFS_BMAPI_METADATA|
|
xfs_bmapi_aflag(w)|XFS_BMAPI_WRITE|XFS_BMAPI_METADATA|
|
||||||
XFS_BMAPI_CONTIG,
|
XFS_BMAPI_CONTIG,
|
||||||
args->firstblock, args->total, &map, &nmap,
|
args->firstblock, args->total, &map, &nmap,
|
||||||
args->flist))) {
|
args->flist);
|
||||||
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
}
|
|
||||||
ASSERT(nmap <= 1);
|
ASSERT(nmap <= 1);
|
||||||
if (nmap == 1) {
|
if (nmap == 1) {
|
||||||
mapp = ↦
|
mapp = ↦
|
||||||
mapi = 1;
|
mapi = 1;
|
||||||
}
|
} else if (nmap == 0 && count > 1) {
|
||||||
/*
|
xfs_fileoff_t b;
|
||||||
* If we didn't get it and the block might work if fragmented,
|
int c;
|
||||||
* try without the CONTIG flag. Loop until we get it all.
|
|
||||||
*/
|
/*
|
||||||
else if (nmap == 0 && count > 1) {
|
* If we didn't get it and the block might work if fragmented,
|
||||||
|
* try without the CONTIG flag. Loop until we get it all.
|
||||||
|
*/
|
||||||
mapp = kmem_alloc(sizeof(*mapp) * count, KM_SLEEP);
|
mapp = kmem_alloc(sizeof(*mapp) * count, KM_SLEEP);
|
||||||
for (b = bno, mapi = 0; b < bno + count; ) {
|
for (b = *bno, mapi = 0; b < *bno + count; ) {
|
||||||
nmap = MIN(XFS_BMAP_MAX_NMAP, count);
|
nmap = MIN(XFS_BMAP_MAX_NMAP, count);
|
||||||
c = (int)(bno + count - b);
|
c = (int)(*bno + count - b);
|
||||||
if ((error = xfs_bmapi(tp, dp, b, c,
|
error = xfs_bmapi(tp, dp, b, c,
|
||||||
xfs_bmapi_aflag(w)|XFS_BMAPI_WRITE|
|
xfs_bmapi_aflag(w)|XFS_BMAPI_WRITE|
|
||||||
XFS_BMAPI_METADATA,
|
XFS_BMAPI_METADATA,
|
||||||
args->firstblock, args->total,
|
args->firstblock, args->total,
|
||||||
&mapp[mapi], &nmap, args->flist))) {
|
&mapp[mapi], &nmap, args->flist);
|
||||||
kmem_free(mapp);
|
if (error)
|
||||||
return error;
|
goto out_free_map;
|
||||||
}
|
|
||||||
if (nmap < 1)
|
if (nmap < 1)
|
||||||
break;
|
break;
|
||||||
mapi += nmap;
|
mapi += nmap;
|
||||||
@ -1626,24 +1609,53 @@ xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno)
|
|||||||
mapi = 0;
|
mapi = 0;
|
||||||
mapp = NULL;
|
mapp = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Count the blocks we got, make sure it matches the total.
|
* Count the blocks we got, make sure it matches the total.
|
||||||
*/
|
*/
|
||||||
for (i = 0, got = 0; i < mapi; i++)
|
for (i = 0, got = 0; i < mapi; i++)
|
||||||
got += mapp[i].br_blockcount;
|
got += mapp[i].br_blockcount;
|
||||||
if (got != count || mapp[0].br_startoff != bno ||
|
if (got != count || mapp[0].br_startoff != *bno ||
|
||||||
mapp[mapi - 1].br_startoff + mapp[mapi - 1].br_blockcount !=
|
mapp[mapi - 1].br_startoff + mapp[mapi - 1].br_blockcount !=
|
||||||
bno + count) {
|
*bno + count) {
|
||||||
if (mapp != &map)
|
error = XFS_ERROR(ENOSPC);
|
||||||
kmem_free(mapp);
|
goto out_free_map;
|
||||||
return XFS_ERROR(ENOSPC);
|
|
||||||
}
|
}
|
||||||
if (mapp != &map)
|
|
||||||
kmem_free(mapp);
|
|
||||||
/* account for newly allocated blocks in reserved blocks total */
|
/* account for newly allocated blocks in reserved blocks total */
|
||||||
args->total -= dp->i_d.di_nblocks - nblks;
|
args->total -= dp->i_d.di_nblocks - nblks;
|
||||||
*new_blkno = (xfs_dablk_t)bno;
|
|
||||||
return 0;
|
out_free_map:
|
||||||
|
if (mapp != &map)
|
||||||
|
kmem_free(mapp);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add a block to the btree ahead of the file.
|
||||||
|
* Return the new block number to the caller.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
xfs_da_grow_inode(
|
||||||
|
struct xfs_da_args *args,
|
||||||
|
xfs_dablk_t *new_blkno)
|
||||||
|
{
|
||||||
|
xfs_fileoff_t bno;
|
||||||
|
int count;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
if (args->whichfork == XFS_DATA_FORK) {
|
||||||
|
bno = args->dp->i_mount->m_dirleafblk;
|
||||||
|
count = args->dp->i_mount->m_dirblkfsbs;
|
||||||
|
} else {
|
||||||
|
bno = 0;
|
||||||
|
count = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
error = xfs_da_grow_inode_int(args, &bno, count);
|
||||||
|
if (!error)
|
||||||
|
*new_blkno = (xfs_dablk_t)bno;
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -248,6 +248,8 @@ int xfs_da_blk_link(xfs_da_state_t *state, xfs_da_state_blk_t *old_blk,
|
|||||||
* Utility routines.
|
* Utility routines.
|
||||||
*/
|
*/
|
||||||
int xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno);
|
int xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno);
|
||||||
|
int xfs_da_grow_inode_int(struct xfs_da_args *args, xfs_fileoff_t *bno,
|
||||||
|
int count);
|
||||||
int xfs_da_get_buf(struct xfs_trans *trans, struct xfs_inode *dp,
|
int xfs_da_get_buf(struct xfs_trans *trans, struct xfs_inode *dp,
|
||||||
xfs_dablk_t bno, xfs_daddr_t mappedbno,
|
xfs_dablk_t bno, xfs_daddr_t mappedbno,
|
||||||
xfs_dabuf_t **bp, int whichfork);
|
xfs_dabuf_t **bp, int whichfork);
|
||||||
|
@ -497,129 +497,34 @@ xfs_dir_canenter(
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Add a block to the directory.
|
* Add a block to the directory.
|
||||||
* This routine is for data and free blocks, not leaf/node blocks
|
*
|
||||||
* which are handled by xfs_da_grow_inode.
|
* This routine is for data and free blocks, not leaf/node blocks which are
|
||||||
|
* handled by xfs_da_grow_inode.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
xfs_dir2_grow_inode(
|
xfs_dir2_grow_inode(
|
||||||
xfs_da_args_t *args,
|
struct xfs_da_args *args,
|
||||||
int space, /* v2 dir's space XFS_DIR2_xxx_SPACE */
|
int space, /* v2 dir's space XFS_DIR2_xxx_SPACE */
|
||||||
xfs_dir2_db_t *dbp) /* out: block number added */
|
xfs_dir2_db_t *dbp) /* out: block number added */
|
||||||
{
|
{
|
||||||
xfs_fileoff_t bno; /* directory offset of new block */
|
struct xfs_inode *dp = args->dp;
|
||||||
int count; /* count of filesystem blocks */
|
struct xfs_mount *mp = dp->i_mount;
|
||||||
xfs_inode_t *dp; /* incore directory inode */
|
xfs_fileoff_t bno; /* directory offset of new block */
|
||||||
int error;
|
int count; /* count of filesystem blocks */
|
||||||
int got; /* blocks actually mapped */
|
int error;
|
||||||
int i;
|
|
||||||
xfs_bmbt_irec_t map; /* single structure for bmap */
|
|
||||||
int mapi; /* mapping index */
|
|
||||||
xfs_bmbt_irec_t *mapp; /* bmap mapping structure(s) */
|
|
||||||
xfs_mount_t *mp;
|
|
||||||
int nmap; /* number of bmap entries */
|
|
||||||
xfs_trans_t *tp;
|
|
||||||
xfs_drfsbno_t nblks;
|
|
||||||
|
|
||||||
trace_xfs_dir2_grow_inode(args, space);
|
trace_xfs_dir2_grow_inode(args, space);
|
||||||
|
|
||||||
dp = args->dp;
|
|
||||||
tp = args->trans;
|
|
||||||
mp = dp->i_mount;
|
|
||||||
nblks = dp->i_d.di_nblocks;
|
|
||||||
/*
|
/*
|
||||||
* Set lowest possible block in the space requested.
|
* Set lowest possible block in the space requested.
|
||||||
*/
|
*/
|
||||||
bno = XFS_B_TO_FSBT(mp, space * XFS_DIR2_SPACE_SIZE);
|
bno = XFS_B_TO_FSBT(mp, space * XFS_DIR2_SPACE_SIZE);
|
||||||
count = mp->m_dirblkfsbs;
|
count = mp->m_dirblkfsbs;
|
||||||
/*
|
|
||||||
* Find the first hole for our block.
|
error = xfs_da_grow_inode_int(args, &bno, count);
|
||||||
*/
|
if (error)
|
||||||
if ((error = xfs_bmap_first_unused(tp, dp, count, &bno, XFS_DATA_FORK)))
|
|
||||||
return error;
|
return error;
|
||||||
nmap = 1;
|
|
||||||
ASSERT(args->firstblock != NULL);
|
|
||||||
/*
|
|
||||||
* Try mapping the new block contiguously (one extent).
|
|
||||||
*/
|
|
||||||
if ((error = xfs_bmapi(tp, dp, bno, count,
|
|
||||||
XFS_BMAPI_WRITE|XFS_BMAPI_METADATA|XFS_BMAPI_CONTIG,
|
|
||||||
args->firstblock, args->total, &map, &nmap,
|
|
||||||
args->flist)))
|
|
||||||
return error;
|
|
||||||
ASSERT(nmap <= 1);
|
|
||||||
if (nmap == 1) {
|
|
||||||
mapp = ↦
|
|
||||||
mapi = 1;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Didn't work and this is a multiple-fsb directory block.
|
|
||||||
* Try again with contiguous flag turned on.
|
|
||||||
*/
|
|
||||||
else if (nmap == 0 && count > 1) {
|
|
||||||
xfs_fileoff_t b; /* current file offset */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Space for maximum number of mappings.
|
|
||||||
*/
|
|
||||||
mapp = kmem_alloc(sizeof(*mapp) * count, KM_SLEEP);
|
|
||||||
/*
|
|
||||||
* Iterate until we get to the end of our block.
|
|
||||||
*/
|
|
||||||
for (b = bno, mapi = 0; b < bno + count; ) {
|
|
||||||
int c; /* current fsb count */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Can't map more than MAX_NMAP at once.
|
|
||||||
*/
|
|
||||||
nmap = MIN(XFS_BMAP_MAX_NMAP, count);
|
|
||||||
c = (int)(bno + count - b);
|
|
||||||
if ((error = xfs_bmapi(tp, dp, b, c,
|
|
||||||
XFS_BMAPI_WRITE|XFS_BMAPI_METADATA,
|
|
||||||
args->firstblock, args->total,
|
|
||||||
&mapp[mapi], &nmap, args->flist))) {
|
|
||||||
kmem_free(mapp);
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
if (nmap < 1)
|
|
||||||
break;
|
|
||||||
/*
|
|
||||||
* Add this bunch into our table, go to the next offset.
|
|
||||||
*/
|
|
||||||
mapi += nmap;
|
|
||||||
b = mapp[mapi - 1].br_startoff +
|
|
||||||
mapp[mapi - 1].br_blockcount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Didn't work.
|
|
||||||
*/
|
|
||||||
else {
|
|
||||||
mapi = 0;
|
|
||||||
mapp = NULL;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* See how many fsb's we got.
|
|
||||||
*/
|
|
||||||
for (i = 0, got = 0; i < mapi; i++)
|
|
||||||
got += mapp[i].br_blockcount;
|
|
||||||
/*
|
|
||||||
* Didn't get enough fsb's, or the first/last block's are wrong.
|
|
||||||
*/
|
|
||||||
if (got != count || mapp[0].br_startoff != bno ||
|
|
||||||
mapp[mapi - 1].br_startoff + mapp[mapi - 1].br_blockcount !=
|
|
||||||
bno + count) {
|
|
||||||
if (mapp != &map)
|
|
||||||
kmem_free(mapp);
|
|
||||||
return XFS_ERROR(ENOSPC);
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Done with the temporary mapping table.
|
|
||||||
*/
|
|
||||||
if (mapp != &map)
|
|
||||||
kmem_free(mapp);
|
|
||||||
|
|
||||||
/* account for newly allocated blocks in reserved blocks total */
|
|
||||||
args->total -= dp->i_d.di_nblocks - nblks;
|
|
||||||
*dbp = xfs_dir2_da_to_db(mp, (xfs_dablk_t)bno);
|
*dbp = xfs_dir2_da_to_db(mp, (xfs_dablk_t)bno);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -631,7 +536,7 @@ xfs_dir2_grow_inode(
|
|||||||
size = XFS_FSB_TO_B(mp, bno + count);
|
size = XFS_FSB_TO_B(mp, bno + count);
|
||||||
if (size > dp->i_d.di_size) {
|
if (size > dp->i_d.di_size) {
|
||||||
dp->i_d.di_size = size;
|
dp->i_d.di_size = size;
|
||||||
xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
|
xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user