|
|
|
@ -172,18 +172,17 @@ xfs_inobt_insert(
|
|
|
|
|
struct xfs_mount *mp,
|
|
|
|
|
struct xfs_trans *tp,
|
|
|
|
|
struct xfs_buf *agbp,
|
|
|
|
|
struct xfs_perag *pag,
|
|
|
|
|
xfs_agino_t newino,
|
|
|
|
|
xfs_agino_t newlen,
|
|
|
|
|
xfs_btnum_t btnum)
|
|
|
|
|
{
|
|
|
|
|
struct xfs_btree_cur *cur;
|
|
|
|
|
struct xfs_agi *agi = agbp->b_addr;
|
|
|
|
|
xfs_agnumber_t agno = be32_to_cpu(agi->agi_seqno);
|
|
|
|
|
xfs_agino_t thisino;
|
|
|
|
|
int i;
|
|
|
|
|
int error;
|
|
|
|
|
|
|
|
|
|
cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, NULL, btnum);
|
|
|
|
|
cur = xfs_inobt_init_cursor(mp, tp, agbp, pag, btnum);
|
|
|
|
|
|
|
|
|
|
for (thisino = newino;
|
|
|
|
|
thisino < newino + newlen;
|
|
|
|
@ -520,18 +519,17 @@ xfs_inobt_insert_sprec(
|
|
|
|
|
struct xfs_mount *mp,
|
|
|
|
|
struct xfs_trans *tp,
|
|
|
|
|
struct xfs_buf *agbp,
|
|
|
|
|
struct xfs_perag *pag,
|
|
|
|
|
int btnum,
|
|
|
|
|
struct xfs_inobt_rec_incore *nrec, /* in/out: new/merged rec. */
|
|
|
|
|
bool merge) /* merge or replace */
|
|
|
|
|
{
|
|
|
|
|
struct xfs_btree_cur *cur;
|
|
|
|
|
struct xfs_agi *agi = agbp->b_addr;
|
|
|
|
|
xfs_agnumber_t agno = be32_to_cpu(agi->agi_seqno);
|
|
|
|
|
int error;
|
|
|
|
|
int i;
|
|
|
|
|
struct xfs_inobt_rec_incore rec;
|
|
|
|
|
|
|
|
|
|
cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, NULL, btnum);
|
|
|
|
|
cur = xfs_inobt_init_cursor(mp, tp, agbp, pag, btnum);
|
|
|
|
|
|
|
|
|
|
/* the new record is pre-aligned so we know where to look */
|
|
|
|
|
error = xfs_inobt_lookup(cur, nrec->ir_startino, XFS_LOOKUP_EQ, &i);
|
|
|
|
@ -578,14 +576,14 @@ xfs_inobt_insert_sprec(
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
trace_xfs_irec_merge_pre(mp, agno, rec.ir_startino,
|
|
|
|
|
trace_xfs_irec_merge_pre(mp, pag->pag_agno, rec.ir_startino,
|
|
|
|
|
rec.ir_holemask, nrec->ir_startino,
|
|
|
|
|
nrec->ir_holemask);
|
|
|
|
|
|
|
|
|
|
/* merge to nrec to output the updated record */
|
|
|
|
|
__xfs_inobt_rec_merge(nrec, &rec);
|
|
|
|
|
|
|
|
|
|
trace_xfs_irec_merge_post(mp, agno, nrec->ir_startino,
|
|
|
|
|
trace_xfs_irec_merge_post(mp, pag->pag_agno, nrec->ir_startino,
|
|
|
|
|
nrec->ir_holemask);
|
|
|
|
|
|
|
|
|
|
error = xfs_inobt_rec_check_count(mp, nrec);
|
|
|
|
@ -613,21 +611,20 @@ error:
|
|
|
|
|
STATIC int
|
|
|
|
|
xfs_ialloc_ag_alloc(
|
|
|
|
|
struct xfs_trans *tp,
|
|
|
|
|
struct xfs_buf *agbp)
|
|
|
|
|
struct xfs_buf *agbp,
|
|
|
|
|
struct xfs_perag *pag)
|
|
|
|
|
{
|
|
|
|
|
struct xfs_agi *agi;
|
|
|
|
|
struct xfs_alloc_arg args;
|
|
|
|
|
xfs_agnumber_t agno;
|
|
|
|
|
int error;
|
|
|
|
|
xfs_agino_t newino; /* new first inode's number */
|
|
|
|
|
xfs_agino_t newlen; /* new number of inodes */
|
|
|
|
|
int isaligned = 0; /* inode allocation at stripe */
|
|
|
|
|
/* unit boundary */
|
|
|
|
|
/* init. to full chunk */
|
|
|
|
|
uint16_t allocmask = (uint16_t) -1;
|
|
|
|
|
struct xfs_inobt_rec_incore rec;
|
|
|
|
|
struct xfs_perag *pag;
|
|
|
|
|
struct xfs_ino_geometry *igeo = M_IGEO(tp->t_mountp);
|
|
|
|
|
uint16_t allocmask = (uint16_t) -1;
|
|
|
|
|
int do_sparse = 0;
|
|
|
|
|
|
|
|
|
|
memset(&args, 0, sizeof(args));
|
|
|
|
@ -660,14 +657,13 @@ xfs_ialloc_ag_alloc(
|
|
|
|
|
*/
|
|
|
|
|
agi = agbp->b_addr;
|
|
|
|
|
newino = be32_to_cpu(agi->agi_newino);
|
|
|
|
|
agno = be32_to_cpu(agi->agi_seqno);
|
|
|
|
|
args.agbno = XFS_AGINO_TO_AGBNO(args.mp, newino) +
|
|
|
|
|
igeo->ialloc_blks;
|
|
|
|
|
if (do_sparse)
|
|
|
|
|
goto sparse_alloc;
|
|
|
|
|
if (likely(newino != NULLAGINO &&
|
|
|
|
|
(args.agbno < be32_to_cpu(agi->agi_length)))) {
|
|
|
|
|
args.fsbno = XFS_AGB_TO_FSB(args.mp, agno, args.agbno);
|
|
|
|
|
args.fsbno = XFS_AGB_TO_FSB(args.mp, pag->pag_agno, args.agbno);
|
|
|
|
|
args.type = XFS_ALLOCTYPE_THIS_BNO;
|
|
|
|
|
args.prod = 1;
|
|
|
|
|
|
|
|
|
@ -727,7 +723,7 @@ xfs_ialloc_ag_alloc(
|
|
|
|
|
* For now, just allocate blocks up front.
|
|
|
|
|
*/
|
|
|
|
|
args.agbno = be32_to_cpu(agi->agi_root);
|
|
|
|
|
args.fsbno = XFS_AGB_TO_FSB(args.mp, agno, args.agbno);
|
|
|
|
|
args.fsbno = XFS_AGB_TO_FSB(args.mp, pag->pag_agno, args.agbno);
|
|
|
|
|
/*
|
|
|
|
|
* Allocate a fixed-size extent of inodes.
|
|
|
|
|
*/
|
|
|
|
@ -748,7 +744,7 @@ xfs_ialloc_ag_alloc(
|
|
|
|
|
if (isaligned && args.fsbno == NULLFSBLOCK) {
|
|
|
|
|
args.type = XFS_ALLOCTYPE_NEAR_BNO;
|
|
|
|
|
args.agbno = be32_to_cpu(agi->agi_root);
|
|
|
|
|
args.fsbno = XFS_AGB_TO_FSB(args.mp, agno, args.agbno);
|
|
|
|
|
args.fsbno = XFS_AGB_TO_FSB(args.mp, pag->pag_agno, args.agbno);
|
|
|
|
|
args.alignment = igeo->cluster_align;
|
|
|
|
|
if ((error = xfs_alloc_vextent(&args)))
|
|
|
|
|
return error;
|
|
|
|
@ -764,7 +760,7 @@ xfs_ialloc_ag_alloc(
|
|
|
|
|
sparse_alloc:
|
|
|
|
|
args.type = XFS_ALLOCTYPE_NEAR_BNO;
|
|
|
|
|
args.agbno = be32_to_cpu(agi->agi_root);
|
|
|
|
|
args.fsbno = XFS_AGB_TO_FSB(args.mp, agno, args.agbno);
|
|
|
|
|
args.fsbno = XFS_AGB_TO_FSB(args.mp, pag->pag_agno, args.agbno);
|
|
|
|
|
args.alignment = args.mp->m_sb.sb_spino_align;
|
|
|
|
|
args.prod = 1;
|
|
|
|
|
|
|
|
|
@ -809,7 +805,7 @@ sparse_alloc:
|
|
|
|
|
* rather than a linear progression to prevent the next generation
|
|
|
|
|
* number from being easily guessable.
|
|
|
|
|
*/
|
|
|
|
|
error = xfs_ialloc_inode_init(args.mp, tp, NULL, newlen, agno,
|
|
|
|
|
error = xfs_ialloc_inode_init(args.mp, tp, NULL, newlen, pag->pag_agno,
|
|
|
|
|
args.agbno, args.len, prandom_u32());
|
|
|
|
|
|
|
|
|
|
if (error)
|
|
|
|
@ -836,12 +832,12 @@ sparse_alloc:
|
|
|
|
|
* if necessary. If a merge does occur, rec is updated to the
|
|
|
|
|
* merged record.
|
|
|
|
|
*/
|
|
|
|
|
error = xfs_inobt_insert_sprec(args.mp, tp, agbp, XFS_BTNUM_INO,
|
|
|
|
|
&rec, true);
|
|
|
|
|
error = xfs_inobt_insert_sprec(args.mp, tp, agbp, pag,
|
|
|
|
|
XFS_BTNUM_INO, &rec, true);
|
|
|
|
|
if (error == -EFSCORRUPTED) {
|
|
|
|
|
xfs_alert(args.mp,
|
|
|
|
|
"invalid sparse inode record: ino 0x%llx holemask 0x%x count %u",
|
|
|
|
|
XFS_AGINO_TO_INO(args.mp, agno,
|
|
|
|
|
XFS_AGINO_TO_INO(args.mp, pag->pag_agno,
|
|
|
|
|
rec.ir_startino),
|
|
|
|
|
rec.ir_holemask, rec.ir_count);
|
|
|
|
|
xfs_force_shutdown(args.mp, SHUTDOWN_CORRUPT_INCORE);
|
|
|
|
@ -861,21 +857,20 @@ sparse_alloc:
|
|
|
|
|
* existing record with this one.
|
|
|
|
|
*/
|
|
|
|
|
if (xfs_sb_version_hasfinobt(&args.mp->m_sb)) {
|
|
|
|
|
error = xfs_inobt_insert_sprec(args.mp, tp, agbp,
|
|
|
|
|
XFS_BTNUM_FINO, &rec,
|
|
|
|
|
false);
|
|
|
|
|
error = xfs_inobt_insert_sprec(args.mp, tp, agbp, pag,
|
|
|
|
|
XFS_BTNUM_FINO, &rec, false);
|
|
|
|
|
if (error)
|
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
/* full chunk - insert new records to both btrees */
|
|
|
|
|
error = xfs_inobt_insert(args.mp, tp, agbp, newino, newlen,
|
|
|
|
|
error = xfs_inobt_insert(args.mp, tp, agbp, pag, newino, newlen,
|
|
|
|
|
XFS_BTNUM_INO);
|
|
|
|
|
if (error)
|
|
|
|
|
return error;
|
|
|
|
|
|
|
|
|
|
if (xfs_sb_version_hasfinobt(&args.mp->m_sb)) {
|
|
|
|
|
error = xfs_inobt_insert(args.mp, tp, agbp, newino,
|
|
|
|
|
error = xfs_inobt_insert(args.mp, tp, agbp, pag, newino,
|
|
|
|
|
newlen, XFS_BTNUM_FINO);
|
|
|
|
|
if (error)
|
|
|
|
|
return error;
|
|
|
|
@ -887,7 +882,6 @@ sparse_alloc:
|
|
|
|
|
*/
|
|
|
|
|
be32_add_cpu(&agi->agi_count, newlen);
|
|
|
|
|
be32_add_cpu(&agi->agi_freecount, newlen);
|
|
|
|
|
pag = agbp->b_pag;
|
|
|
|
|
pag->pagi_freecount += newlen;
|
|
|
|
|
pag->pagi_count += newlen;
|
|
|
|
|
agi->agi_newino = cpu_to_be32(newino);
|
|
|
|
@ -1123,15 +1117,14 @@ STATIC int
|
|
|
|
|
xfs_dialloc_ag_inobt(
|
|
|
|
|
struct xfs_trans *tp,
|
|
|
|
|
struct xfs_buf *agbp,
|
|
|
|
|
struct xfs_perag *pag,
|
|
|
|
|
xfs_ino_t parent,
|
|
|
|
|
xfs_ino_t *inop)
|
|
|
|
|
{
|
|
|
|
|
struct xfs_mount *mp = tp->t_mountp;
|
|
|
|
|
struct xfs_agi *agi = agbp->b_addr;
|
|
|
|
|
xfs_agnumber_t agno = be32_to_cpu(agi->agi_seqno);
|
|
|
|
|
xfs_agnumber_t pagno = XFS_INO_TO_AGNO(mp, parent);
|
|
|
|
|
xfs_agino_t pagino = XFS_INO_TO_AGINO(mp, parent);
|
|
|
|
|
struct xfs_perag *pag = agbp->b_pag;
|
|
|
|
|
struct xfs_btree_cur *cur, *tcur;
|
|
|
|
|
struct xfs_inobt_rec_incore rec, trec;
|
|
|
|
|
xfs_ino_t ino;
|
|
|
|
@ -1145,7 +1138,7 @@ xfs_dialloc_ag_inobt(
|
|
|
|
|
ASSERT(pag->pagi_freecount > 0);
|
|
|
|
|
|
|
|
|
|
restart_pagno:
|
|
|
|
|
cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, NULL, XFS_BTNUM_INO);
|
|
|
|
|
cur = xfs_inobt_init_cursor(mp, tp, agbp, pag, XFS_BTNUM_INO);
|
|
|
|
|
/*
|
|
|
|
|
* If pagino is 0 (this is the root inode allocation) use newino.
|
|
|
|
|
* This must work because we've just allocated some.
|
|
|
|
@ -1160,7 +1153,7 @@ xfs_dialloc_ag_inobt(
|
|
|
|
|
/*
|
|
|
|
|
* If in the same AG as the parent, try to get near the parent.
|
|
|
|
|
*/
|
|
|
|
|
if (pagno == agno) {
|
|
|
|
|
if (pagno == pag->pag_agno) {
|
|
|
|
|
int doneleft; /* done, to the left */
|
|
|
|
|
int doneright; /* done, to the right */
|
|
|
|
|
|
|
|
|
@ -1363,7 +1356,7 @@ alloc_inode:
|
|
|
|
|
ASSERT(offset < XFS_INODES_PER_CHUNK);
|
|
|
|
|
ASSERT((XFS_AGINO_TO_OFFSET(mp, rec.ir_startino) %
|
|
|
|
|
XFS_INODES_PER_CHUNK) == 0);
|
|
|
|
|
ino = XFS_AGINO_TO_INO(mp, agno, rec.ir_startino + offset);
|
|
|
|
|
ino = XFS_AGINO_TO_INO(mp, pag->pag_agno, rec.ir_startino + offset);
|
|
|
|
|
rec.ir_free &= ~XFS_INOBT_MASK(offset);
|
|
|
|
|
rec.ir_freecount--;
|
|
|
|
|
error = xfs_inobt_update(cur, &rec);
|
|
|
|
@ -1577,7 +1570,6 @@ xfs_dialloc_ag(
|
|
|
|
|
{
|
|
|
|
|
struct xfs_mount *mp = tp->t_mountp;
|
|
|
|
|
struct xfs_agi *agi = agbp->b_addr;
|
|
|
|
|
xfs_agnumber_t agno = be32_to_cpu(agi->agi_seqno);
|
|
|
|
|
xfs_agnumber_t pagno = XFS_INO_TO_AGNO(mp, parent);
|
|
|
|
|
xfs_agino_t pagino = XFS_INO_TO_AGINO(mp, parent);
|
|
|
|
|
struct xfs_btree_cur *cur; /* finobt cursor */
|
|
|
|
@ -1587,9 +1579,10 @@ xfs_dialloc_ag(
|
|
|
|
|
int error;
|
|
|
|
|
int offset;
|
|
|
|
|
int i;
|
|
|
|
|
struct xfs_perag *pag = agbp->b_pag;
|
|
|
|
|
|
|
|
|
|
if (!xfs_sb_version_hasfinobt(&mp->m_sb))
|
|
|
|
|
return xfs_dialloc_ag_inobt(tp, agbp, parent, inop);
|
|
|
|
|
return xfs_dialloc_ag_inobt(tp, agbp, pag, parent, inop);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If pagino is 0 (this is the root inode allocation) use newino.
|
|
|
|
@ -1598,7 +1591,7 @@ xfs_dialloc_ag(
|
|
|
|
|
if (!pagino)
|
|
|
|
|
pagino = be32_to_cpu(agi->agi_newino);
|
|
|
|
|
|
|
|
|
|
cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, NULL, XFS_BTNUM_FINO);
|
|
|
|
|
cur = xfs_inobt_init_cursor(mp, tp, agbp, pag, XFS_BTNUM_FINO);
|
|
|
|
|
|
|
|
|
|
error = xfs_check_agi_freecount(cur, agi);
|
|
|
|
|
if (error)
|
|
|
|
@ -1609,7 +1602,7 @@ xfs_dialloc_ag(
|
|
|
|
|
* parent. If so, find the closest available inode to the parent. If
|
|
|
|
|
* not, consider the agi hint or find the first free inode in the AG.
|
|
|
|
|
*/
|
|
|
|
|
if (agno == pagno)
|
|
|
|
|
if (pag->pag_agno == pagno)
|
|
|
|
|
error = xfs_dialloc_ag_finobt_near(pagino, &cur, &rec);
|
|
|
|
|
else
|
|
|
|
|
error = xfs_dialloc_ag_finobt_newino(agi, cur, &rec);
|
|
|
|
@ -1621,7 +1614,7 @@ xfs_dialloc_ag(
|
|
|
|
|
ASSERT(offset < XFS_INODES_PER_CHUNK);
|
|
|
|
|
ASSERT((XFS_AGINO_TO_OFFSET(mp, rec.ir_startino) %
|
|
|
|
|
XFS_INODES_PER_CHUNK) == 0);
|
|
|
|
|
ino = XFS_AGINO_TO_INO(mp, agno, rec.ir_startino + offset);
|
|
|
|
|
ino = XFS_AGINO_TO_INO(mp, pag->pag_agno, rec.ir_startino + offset);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Modify or remove the finobt record.
|
|
|
|
@ -1641,7 +1634,7 @@ xfs_dialloc_ag(
|
|
|
|
|
* the original freecount. If all is well, make the equivalent update to
|
|
|
|
|
* the inobt using the finobt record and offset information.
|
|
|
|
|
*/
|
|
|
|
|
icur = xfs_inobt_init_cursor(mp, tp, agbp, agno, NULL, XFS_BTNUM_INO);
|
|
|
|
|
icur = xfs_inobt_init_cursor(mp, tp, agbp, pag, XFS_BTNUM_INO);
|
|
|
|
|
|
|
|
|
|
error = xfs_check_agi_freecount(icur, agi);
|
|
|
|
|
if (error)
|
|
|
|
@ -1657,7 +1650,7 @@ xfs_dialloc_ag(
|
|
|
|
|
*/
|
|
|
|
|
be32_add_cpu(&agi->agi_freecount, -1);
|
|
|
|
|
xfs_ialloc_log_agi(tp, agbp, XFS_AGI_FREECOUNT);
|
|
|
|
|
agbp->b_pag->pagi_freecount--;
|
|
|
|
|
pag->pagi_freecount--;
|
|
|
|
|
|
|
|
|
|
xfs_trans_mod_sb(tp, XFS_TRANS_SB_IFREE, -1);
|
|
|
|
|
|
|
|
|
@ -1809,7 +1802,7 @@ xfs_dialloc_select_ag(
|
|
|
|
|
if (!okalloc)
|
|
|
|
|
goto nextag_relse_buffer;
|
|
|
|
|
|
|
|
|
|
error = xfs_ialloc_ag_alloc(*tpp, agbp);
|
|
|
|
|
error = xfs_ialloc_ag_alloc(*tpp, agbp, pag);
|
|
|
|
|
if (error < 0) {
|
|
|
|
|
xfs_trans_brelse(*tpp, agbp);
|
|
|
|
|
|
|
|
|
@ -1935,12 +1928,12 @@ xfs_difree_inobt(
|
|
|
|
|
struct xfs_mount *mp,
|
|
|
|
|
struct xfs_trans *tp,
|
|
|
|
|
struct xfs_buf *agbp,
|
|
|
|
|
struct xfs_perag *pag,
|
|
|
|
|
xfs_agino_t agino,
|
|
|
|
|
struct xfs_icluster *xic,
|
|
|
|
|
struct xfs_inobt_rec_incore *orec)
|
|
|
|
|
{
|
|
|
|
|
struct xfs_agi *agi = agbp->b_addr;
|
|
|
|
|
xfs_agnumber_t agno = be32_to_cpu(agi->agi_seqno);
|
|
|
|
|
struct xfs_btree_cur *cur;
|
|
|
|
|
struct xfs_inobt_rec_incore rec;
|
|
|
|
|
int ilen;
|
|
|
|
@ -1954,7 +1947,7 @@ xfs_difree_inobt(
|
|
|
|
|
/*
|
|
|
|
|
* Initialize the cursor.
|
|
|
|
|
*/
|
|
|
|
|
cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, NULL, XFS_BTNUM_INO);
|
|
|
|
|
cur = xfs_inobt_init_cursor(mp, tp, agbp, pag, XFS_BTNUM_INO);
|
|
|
|
|
|
|
|
|
|
error = xfs_check_agi_freecount(cur, agi);
|
|
|
|
|
if (error)
|
|
|
|
@ -2005,7 +1998,8 @@ xfs_difree_inobt(
|
|
|
|
|
struct xfs_perag *pag = agbp->b_pag;
|
|
|
|
|
|
|
|
|
|
xic->deleted = true;
|
|
|
|
|
xic->first_ino = XFS_AGINO_TO_INO(mp, agno, rec.ir_startino);
|
|
|
|
|
xic->first_ino = XFS_AGINO_TO_INO(mp, pag->pag_agno,
|
|
|
|
|
rec.ir_startino);
|
|
|
|
|
xic->alloc = xfs_inobt_irec_to_allocmask(&rec);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@ -2028,7 +2022,7 @@ xfs_difree_inobt(
|
|
|
|
|
goto error0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
xfs_difree_inode_chunk(tp, agno, &rec);
|
|
|
|
|
xfs_difree_inode_chunk(tp, pag->pag_agno, &rec);
|
|
|
|
|
} else {
|
|
|
|
|
xic->deleted = false;
|
|
|
|
|
|
|
|
|
@ -2044,7 +2038,7 @@ xfs_difree_inobt(
|
|
|
|
|
*/
|
|
|
|
|
be32_add_cpu(&agi->agi_freecount, 1);
|
|
|
|
|
xfs_ialloc_log_agi(tp, agbp, XFS_AGI_FREECOUNT);
|
|
|
|
|
agbp->b_pag->pagi_freecount++;
|
|
|
|
|
pag->pagi_freecount++;
|
|
|
|
|
xfs_trans_mod_sb(tp, XFS_TRANS_SB_IFREE, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -2069,18 +2063,18 @@ xfs_difree_finobt(
|
|
|
|
|
struct xfs_mount *mp,
|
|
|
|
|
struct xfs_trans *tp,
|
|
|
|
|
struct xfs_buf *agbp,
|
|
|
|
|
struct xfs_perag *pag,
|
|
|
|
|
xfs_agino_t agino,
|
|
|
|
|
struct xfs_inobt_rec_incore *ibtrec) /* inobt record */
|
|
|
|
|
{
|
|
|
|
|
struct xfs_agi *agi = agbp->b_addr;
|
|
|
|
|
xfs_agnumber_t agno = be32_to_cpu(agi->agi_seqno);
|
|
|
|
|
struct xfs_btree_cur *cur;
|
|
|
|
|
struct xfs_inobt_rec_incore rec;
|
|
|
|
|
int offset = agino - ibtrec->ir_startino;
|
|
|
|
|
int error;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, NULL, XFS_BTNUM_FINO);
|
|
|
|
|
cur = xfs_inobt_init_cursor(mp, tp, agbp, pag, XFS_BTNUM_FINO);
|
|
|
|
|
|
|
|
|
|
error = xfs_inobt_lookup(cur, ibtrec->ir_startino, XFS_LOOKUP_EQ, &i);
|
|
|
|
|
if (error)
|
|
|
|
@ -2188,16 +2182,15 @@ xfs_difree(
|
|
|
|
|
xfs_agino_t agino; /* allocation group inode number */
|
|
|
|
|
xfs_agnumber_t agno; /* allocation group number */
|
|
|
|
|
int error; /* error return value */
|
|
|
|
|
struct xfs_mount *mp; /* mount structure for filesystem */
|
|
|
|
|
struct xfs_mount *mp = tp->t_mountp;
|
|
|
|
|
struct xfs_inobt_rec_incore rec;/* btree record */
|
|
|
|
|
|
|
|
|
|
mp = tp->t_mountp;
|
|
|
|
|
struct xfs_perag *pag;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Break up inode number into its components.
|
|
|
|
|
*/
|
|
|
|
|
agno = XFS_INO_TO_AGNO(mp, inode);
|
|
|
|
|
if (agno >= mp->m_sb.sb_agcount) {
|
|
|
|
|
if (agno >= mp->m_sb.sb_agcount) {
|
|
|
|
|
xfs_warn(mp, "%s: agno >= mp->m_sb.sb_agcount (%d >= %d).",
|
|
|
|
|
__func__, agno, mp->m_sb.sb_agcount);
|
|
|
|
|
ASSERT(0);
|
|
|
|
@ -2231,7 +2224,8 @@ xfs_difree(
|
|
|
|
|
/*
|
|
|
|
|
* Fix up the inode allocation btree.
|
|
|
|
|
*/
|
|
|
|
|
error = xfs_difree_inobt(mp, tp, agbp, agino, xic, &rec);
|
|
|
|
|
pag = agbp->b_pag;
|
|
|
|
|
error = xfs_difree_inobt(mp, tp, agbp, pag, agino, xic, &rec);
|
|
|
|
|
if (error)
|
|
|
|
|
goto error0;
|
|
|
|
|
|
|
|
|
@ -2239,7 +2233,7 @@ xfs_difree(
|
|
|
|
|
* Fix up the free inode btree.
|
|
|
|
|
*/
|
|
|
|
|
if (xfs_sb_version_hasfinobt(&mp->m_sb)) {
|
|
|
|
|
error = xfs_difree_finobt(mp, tp, agbp, agino, &rec);
|
|
|
|
|
error = xfs_difree_finobt(mp, tp, agbp, pag, agino, &rec);
|
|
|
|
|
if (error)
|
|
|
|
|
goto error0;
|
|
|
|
|
}
|
|
|
|
@ -2254,7 +2248,7 @@ STATIC int
|
|
|
|
|
xfs_imap_lookup(
|
|
|
|
|
struct xfs_mount *mp,
|
|
|
|
|
struct xfs_trans *tp,
|
|
|
|
|
xfs_agnumber_t agno,
|
|
|
|
|
struct xfs_perag *pag,
|
|
|
|
|
xfs_agino_t agino,
|
|
|
|
|
xfs_agblock_t agbno,
|
|
|
|
|
xfs_agblock_t *chunk_agbno,
|
|
|
|
@ -2267,11 +2261,11 @@ xfs_imap_lookup(
|
|
|
|
|
int error;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
error = xfs_ialloc_read_agi(mp, tp, agno, &agbp);
|
|
|
|
|
error = xfs_ialloc_read_agi(mp, tp, pag->pag_agno, &agbp);
|
|
|
|
|
if (error) {
|
|
|
|
|
xfs_alert(mp,
|
|
|
|
|
"%s: xfs_ialloc_read_agi() returned error %d, agno %d",
|
|
|
|
|
__func__, error, agno);
|
|
|
|
|
__func__, error, pag->pag_agno);
|
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -2281,7 +2275,7 @@ xfs_imap_lookup(
|
|
|
|
|
* we have a record, we need to ensure it contains the inode number
|
|
|
|
|
* we are looking up.
|
|
|
|
|
*/
|
|
|
|
|
cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, NULL, XFS_BTNUM_INO);
|
|
|
|
|
cur = xfs_inobt_init_cursor(mp, tp, agbp, pag, XFS_BTNUM_INO);
|
|
|
|
|
error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_LE, &i);
|
|
|
|
|
if (!error) {
|
|
|
|
|
if (i)
|
|
|
|
@ -2315,42 +2309,44 @@ xfs_imap_lookup(
|
|
|
|
|
*/
|
|
|
|
|
int
|
|
|
|
|
xfs_imap(
|
|
|
|
|
xfs_mount_t *mp, /* file system mount structure */
|
|
|
|
|
xfs_trans_t *tp, /* transaction pointer */
|
|
|
|
|
xfs_ino_t ino, /* inode to locate */
|
|
|
|
|
struct xfs_imap *imap, /* location map structure */
|
|
|
|
|
uint flags) /* flags for inode btree lookup */
|
|
|
|
|
struct xfs_mount *mp, /* file system mount structure */
|
|
|
|
|
struct xfs_trans *tp, /* transaction pointer */
|
|
|
|
|
xfs_ino_t ino, /* inode to locate */
|
|
|
|
|
struct xfs_imap *imap, /* location map structure */
|
|
|
|
|
uint flags) /* flags for inode btree lookup */
|
|
|
|
|
{
|
|
|
|
|
xfs_agblock_t agbno; /* block number of inode in the alloc group */
|
|
|
|
|
xfs_agino_t agino; /* inode number within alloc group */
|
|
|
|
|
xfs_agnumber_t agno; /* allocation group number */
|
|
|
|
|
xfs_agblock_t chunk_agbno; /* first block in inode chunk */
|
|
|
|
|
xfs_agblock_t cluster_agbno; /* first block in inode cluster */
|
|
|
|
|
int error; /* error code */
|
|
|
|
|
int offset; /* index of inode in its buffer */
|
|
|
|
|
xfs_agblock_t offset_agbno; /* blks from chunk start to inode */
|
|
|
|
|
xfs_agblock_t agbno; /* block number of inode in the alloc group */
|
|
|
|
|
xfs_agino_t agino; /* inode number within alloc group */
|
|
|
|
|
xfs_agblock_t chunk_agbno; /* first block in inode chunk */
|
|
|
|
|
xfs_agblock_t cluster_agbno; /* first block in inode cluster */
|
|
|
|
|
int error; /* error code */
|
|
|
|
|
int offset; /* index of inode in its buffer */
|
|
|
|
|
xfs_agblock_t offset_agbno; /* blks from chunk start to inode */
|
|
|
|
|
struct xfs_perag *pag;
|
|
|
|
|
|
|
|
|
|
ASSERT(ino != NULLFSINO);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Split up the inode number into its parts.
|
|
|
|
|
*/
|
|
|
|
|
agno = XFS_INO_TO_AGNO(mp, ino);
|
|
|
|
|
pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ino));
|
|
|
|
|
agino = XFS_INO_TO_AGINO(mp, ino);
|
|
|
|
|
agbno = XFS_AGINO_TO_AGBNO(mp, agino);
|
|
|
|
|
if (agno >= mp->m_sb.sb_agcount || agbno >= mp->m_sb.sb_agblocks ||
|
|
|
|
|
ino != XFS_AGINO_TO_INO(mp, agno, agino)) {
|
|
|
|
|
if (!pag || agbno >= mp->m_sb.sb_agblocks ||
|
|
|
|
|
ino != XFS_AGINO_TO_INO(mp, pag->pag_agno, agino)) {
|
|
|
|
|
error = -EINVAL;
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
/*
|
|
|
|
|
* Don't output diagnostic information for untrusted inodes
|
|
|
|
|
* as they can be invalid without implying corruption.
|
|
|
|
|
*/
|
|
|
|
|
if (flags & XFS_IGET_UNTRUSTED)
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
if (agno >= mp->m_sb.sb_agcount) {
|
|
|
|
|
goto out_drop;
|
|
|
|
|
if (!pag) {
|
|
|
|
|
xfs_alert(mp,
|
|
|
|
|
"%s: agno (%d) >= mp->m_sb.sb_agcount (%d)",
|
|
|
|
|
__func__, agno, mp->m_sb.sb_agcount);
|
|
|
|
|
__func__, XFS_INO_TO_AGNO(mp, ino),
|
|
|
|
|
mp->m_sb.sb_agcount);
|
|
|
|
|
}
|
|
|
|
|
if (agbno >= mp->m_sb.sb_agblocks) {
|
|
|
|
|
xfs_alert(mp,
|
|
|
|
@ -2358,15 +2354,15 @@ xfs_imap(
|
|
|
|
|
__func__, (unsigned long long)agbno,
|
|
|
|
|
(unsigned long)mp->m_sb.sb_agblocks);
|
|
|
|
|
}
|
|
|
|
|
if (ino != XFS_AGINO_TO_INO(mp, agno, agino)) {
|
|
|
|
|
if (pag && ino != XFS_AGINO_TO_INO(mp, pag->pag_agno, agino)) {
|
|
|
|
|
xfs_alert(mp,
|
|
|
|
|
"%s: ino (0x%llx) != XFS_AGINO_TO_INO() (0x%llx)",
|
|
|
|
|
__func__, ino,
|
|
|
|
|
XFS_AGINO_TO_INO(mp, agno, agino));
|
|
|
|
|
XFS_AGINO_TO_INO(mp, pag->pag_agno, agino));
|
|
|
|
|
}
|
|
|
|
|
xfs_stack_trace();
|
|
|
|
|
#endif /* DEBUG */
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
goto out_drop;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@ -2377,10 +2373,10 @@ xfs_imap(
|
|
|
|
|
* in all cases where an untrusted inode number is passed.
|
|
|
|
|
*/
|
|
|
|
|
if (flags & XFS_IGET_UNTRUSTED) {
|
|
|
|
|
error = xfs_imap_lookup(mp, tp, agno, agino, agbno,
|
|
|
|
|
error = xfs_imap_lookup(mp, tp, pag, agino, agbno,
|
|
|
|
|
&chunk_agbno, &offset_agbno, flags);
|
|
|
|
|
if (error)
|
|
|
|
|
return error;
|
|
|
|
|
goto out_drop;
|
|
|
|
|
goto out_map;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -2392,11 +2388,12 @@ xfs_imap(
|
|
|
|
|
offset = XFS_INO_TO_OFFSET(mp, ino);
|
|
|
|
|
ASSERT(offset < mp->m_sb.sb_inopblock);
|
|
|
|
|
|
|
|
|
|
imap->im_blkno = XFS_AGB_TO_DADDR(mp, agno, agbno);
|
|
|
|
|
imap->im_blkno = XFS_AGB_TO_DADDR(mp, pag->pag_agno, agbno);
|
|
|
|
|
imap->im_len = XFS_FSB_TO_BB(mp, 1);
|
|
|
|
|
imap->im_boffset = (unsigned short)(offset <<
|
|
|
|
|
mp->m_sb.sb_inodelog);
|
|
|
|
|
return 0;
|
|
|
|
|
error = 0;
|
|
|
|
|
goto out_drop;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@ -2408,10 +2405,10 @@ xfs_imap(
|
|
|
|
|
offset_agbno = agbno & M_IGEO(mp)->inoalign_mask;
|
|
|
|
|
chunk_agbno = agbno - offset_agbno;
|
|
|
|
|
} else {
|
|
|
|
|
error = xfs_imap_lookup(mp, tp, agno, agino, agbno,
|
|
|
|
|
error = xfs_imap_lookup(mp, tp, pag, agino, agbno,
|
|
|
|
|
&chunk_agbno, &offset_agbno, flags);
|
|
|
|
|
if (error)
|
|
|
|
|
return error;
|
|
|
|
|
goto out_drop;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
out_map:
|
|
|
|
@ -2422,7 +2419,7 @@ out_map:
|
|
|
|
|
offset = ((agbno - cluster_agbno) * mp->m_sb.sb_inopblock) +
|
|
|
|
|
XFS_INO_TO_OFFSET(mp, ino);
|
|
|
|
|
|
|
|
|
|
imap->im_blkno = XFS_AGB_TO_DADDR(mp, agno, cluster_agbno);
|
|
|
|
|
imap->im_blkno = XFS_AGB_TO_DADDR(mp, pag->pag_agno, cluster_agbno);
|
|
|
|
|
imap->im_len = XFS_FSB_TO_BB(mp, M_IGEO(mp)->blocks_per_cluster);
|
|
|
|
|
imap->im_boffset = (unsigned short)(offset << mp->m_sb.sb_inodelog);
|
|
|
|
|
|
|
|
|
@ -2439,9 +2436,13 @@ out_map:
|
|
|
|
|
__func__, (unsigned long long) imap->im_blkno,
|
|
|
|
|
(unsigned long long) imap->im_len,
|
|
|
|
|
XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks));
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
error = -EINVAL;
|
|
|
|
|
goto out_drop;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
error = 0;
|
|
|
|
|
out_drop:
|
|
|
|
|
xfs_perag_put(pag);
|
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|