Received: with ECARTIS (v1.0.0; list linux-xfs); Mon, 05 Sep 2005 16:23:04 -0700 (PDT) Received: from astra.simleu.ro ([80.97.44.14]) by oss.sgi.com (8.12.10/8.12.10/SuSE Linux 0.7) with ESMTP id j85NMtiL006971 for ; Mon, 5 Sep 2005 16:22:56 -0700 Received: from saytrin.hq.k1024.org (unknown [62.217.245.194]) by astra.simleu.ro (Postfix) with ESMTP id 4C29E50 for ; Tue, 6 Sep 2005 02:20:14 +0300 (EEST) Received: by saytrin.hq.k1024.org (Postfix, from userid 4004) id 7FEE81800AC; Tue, 6 Sep 2005 02:21:26 +0300 (EEST) Date: Tue, 6 Sep 2005 02:21:26 +0300 From: Iustin Pop To: linux-xfs@oss.sgi.com Subject: Re: Where/how to submit for review patch for shrink support? Message-ID: <20050905232126.GA4979@saytrin.hq.k1024.org> Mail-Followup-To: linux-xfs@oss.sgi.com References: <20050905185221.GA5209@saytrin.hq.k1024.org> <20050905191031.GB18315@infradead.org> Mime-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="E39vaYmALEf/7YXx" Content-Disposition: inline In-Reply-To: <20050905191031.GB18315@infradead.org> X-Linux: This message was written on Linux X-Header: /usr/include gives great headers User-Agent: Mutt/1.5.10i X-archive-position: 6069 X-ecartis-version: Ecartis v1.0.0 Sender: linux-xfs-bounce@oss.sgi.com Errors-to: linux-xfs-bounce@oss.sgi.com X-original-sender: iusty@k1024.org Precedence: bulk X-list: linux-xfs Content-Length: 22941 Lines: 699 --E39vaYmALEf/7YXx Content-Type: multipart/mixed; boundary="OXfL5xGRrasGEqWY" Content-Disposition: inline --OXfL5xGRrasGEqWY Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Mon, Sep 05, 2005 at 08:10:31PM +0100, Christoph Hellwig wrote: >=20 > Please try to rediff it against the CVS tree at oss.sgi.com (there's not > much differences, it's just the development tree), and then submit it to > the list. Ok, done (I hope the format is ok). Notes about the patch: - I left the printk's I used in place, maybe they help with understanding the code; - the xfs_inobtsize and xfs_alloc_btsize are called recursivelly, I don't know if this can be a problem with stack usage; however, it was the simplest way at the moment and the max depth is equal to the max depth of the btrees; - almost all the code is based on guesswork and looking at the xfs kernel & userspace code; I have the most doubts about the usage of xfs_alloc_vextent and the parameters I filled its argument with; If anything is unclear, please ask for more information. > Yeah, that sounds a little fishy. I'll take a look at the patch once > you'll post it. Ok, thanks a lot! Iustin --OXfL5xGRrasGEqWY Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="cvs.diff" Content-Transfer-Encoding: quoted-printable diff -urN -x xfs_ialloc_btree.h.orig -x xfs_trans.c.orig -x Entries.Log -x = Entries linux-2.6-xfs.orig/fs/xfs/xfs_alloc_btree.c linux-2.6-xfs/fs/xfs/xf= s_alloc_btree.c --- linux-2.6-xfs.orig/fs/xfs/xfs_alloc_btree.c 2005-01-14 13:57:33.0000000= 00 +0200 +++ linux-2.6-xfs/fs/xfs/xfs_alloc_btree.c 2005-09-06 02:01:39.024407208 +0= 300 @@ -1773,6 +1773,82 @@ */ =20 /* + * Compute the size (in blocks) of the btree in the given level/block numb= er + */ +int /* error */ +xfs_alloc_btsize( + struct xfs_btree_cur *cur, /* btree cursor */ + int level, /* current level */ + xfs_agblock_t agbno, /* a.g. relative btree block number */ + int *result)/* pointer to variable to be incremented */ +{ + xfs_agnumber_t agno; + xfs_alloc_block_t *block=3DNULL; /* current btree block */ + int error; /* error return value */ + int ptrno; /* current key number */ + xfs_daddr_t d; /* disk address of btree block */ + xfs_buf_t *bp; /* buffer pointer for btree block */ + + XFS_STATS_INC(xs_abt_lookup); + + if(level =3D=3D 0) { /* level =3D=3D 0 means no childs and thus one block= usage */ + (*result)++; + return 0; + } + + { + xfs_agf_t *agf; /* a.g. freespace header */ + + agf =3D XFS_BUF_TO_AGF(cur->bc_private.a.agbp); + agno =3D INT_GET(agf->agf_seqno, ARCH_CONVERT); + } + + + d =3D XFS_AGB_TO_DADDR(cur->bc_mp, agno, agbno); + printk("btsize agno=3D%d agbno=3D%d diskaddr=3D%lld level=3D%d result=3D%= d\n", agno, agbno, d, level, *result); + bp =3D cur->bc_bufs[level]; + if (bp && XFS_BUF_ADDR(bp) !=3D d) + bp =3D (xfs_buf_t *)0; + if (!bp) { + /* + * Need to get a new buffer. Read it, then + * set it in the cursor, releasing the old one. + */ + if ((error =3D xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp, agno, + agbno, 0, &bp, XFS_ALLOC_BTREE_REF))) + return error; + xfs_btree_setbuf(cur, level, bp); + /* + * Point to the btree block, now that we have the buffer + */ + block =3D XFS_BUF_TO_ALLOC_BLOCK(bp); + if ((error =3D xfs_btree_check_sblock(cur, block, level, + bp))) + return error; + } else + block =3D XFS_BUF_TO_ALLOC_BLOCK(bp); +=20=20=20=20=20=20=20=20 + /* + * Iterate over each child in this non-leaf block + */ + for (ptrno =3D 0; ptrno < INT_GET(block->bb_numrecs, ARCH_CONVERT); ptrno= ++) { + xfs_alloc_ptr_t *child; + xfs_agblock_t newbno; + + child =3D XFS_ALLOC_PTR_ADDR(block, ptrno + 1, cur); + newbno =3D INT_GET(*child, ARCH_CONVERT); + + printk("\twill enter ptrno=3D%d (of %d) agbno=3D%d\n", ptrno, INT_GET(bl= ock->bb_numrecs, ARCH_CONVERT), newbno); + + if((error =3D xfs_alloc_btsize(cur, level - 1, newbno, result))) + return error; +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20 + } + (*result)++; + return 0; +} + +/* * Decrement cursor by one record at the level. * For nonzero levels the leaf-ward information is untouched. */ diff -urN -x xfs_ialloc_btree.h.orig -x xfs_trans.c.orig -x Entries.Log -x = Entries linux-2.6-xfs.orig/fs/xfs/xfs_alloc_btree.h linux-2.6-xfs/fs/xfs/xf= s_alloc_btree.h --- linux-2.6-xfs.orig/fs/xfs/xfs_alloc_btree.h 2003-06-27 21:04:26.0000000= 00 +0300 +++ linux-2.6-xfs/fs/xfs/xfs_alloc_btree.h 2005-09-06 02:01:39.025407056 +0= 300 @@ -164,6 +164,16 @@ */ =20 /* + * Compute the size (in blocks) of the btree in the given level/block numb= er + */ +int /* error */ +xfs_alloc_btsize( + struct xfs_btree_cur *cur, /* btree cursor */ + int level, /* current level */ + xfs_agblock_t agbno, /* a.g. relative btree block number */ + int *result); /* pointer to variable to be incremente= d */ + +/* * Decrement cursor by one record at the level. * For nonzero levels the leaf-ward information is untouched. */ diff -urN -x xfs_ialloc_btree.h.orig -x xfs_trans.c.orig -x Entries.Log -x = Entries linux-2.6-xfs.orig/fs/xfs/xfs_fsops.c linux-2.6-xfs/fs/xfs/xfs_fsop= s.c --- linux-2.6-xfs.orig/fs/xfs/xfs_fsops.c 2005-05-18 12:18:24.000000000 +03= 00 +++ linux-2.6-xfs/fs/xfs/xfs_fsops.c 2005-09-06 02:01:39.026406904 +0300 @@ -66,6 +66,8 @@ * File system operations */ =20 +static int xfs_shrink_data_private(xfs_mount_t *mp, xfs_growfs_data_t *in); + int xfs_fs_geometry( xfs_mount_t *mp, @@ -153,7 +155,9 @@ =20 nb =3D in->newblocks; pct =3D in->imaxpct; - if (nb < mp->m_sb.sb_dblocks || pct < 0 || pct > 100) + if (nb < mp->m_sb.sb_dblocks) + return xfs_shrink_data_private(mp, in); + if (pct < 0 || pct > 100) return XFS_ERROR(EINVAL); dpct =3D pct - mp->m_sb.sb_imax_pct; error =3D xfs_read_buf(mp, mp->m_ddev_targp, @@ -416,6 +420,318 @@ } =20 static int +xfs_shrink_data_private( + xfs_mount_t *mp, /* mount point for filesystem */ + xfs_growfs_data_t *in) /* growfs data input struct */ +{ + xfs_agf_t *agf; + xfs_agi_t *agi; + xfs_agnumber_t agno; + xfs_buf_t *bp; + int dpct; + int error; + xfs_agnumber_t nagcount; /* new number of a.g. */ + xfs_agnumber_t nagimax =3D 0; + xfs_rfsblock_t nb, nb_mod; + xfs_rfsblock_t new; + xfs_rfsblock_t nfree; + xfs_agnumber_t oagcount; + int pct; + xfs_sb_t *sbp; + xfs_trans_t *tp; + xfs_alloc_arg_t allocarg; + long icount =3D 0; /* sum of total inode count deleted by shrink */ + long ifree =3D 0; /* sum of free inode count deleted by shrink */ + long inofree =3D 0; /* space used by inodes and inode btree */ + + nb =3D in->newblocks; + pct =3D in->imaxpct; + if (nb > mp->m_sb.sb_dblocks || pct < 0 || pct > 100)=20 + return XFS_ERROR(EINVAL); + dpct =3D pct - mp->m_sb.sb_imax_pct; + error =3D xfs_read_buf(mp, mp->m_ddev_targp, + XFS_FSB_TO_BB(mp, nb) - XFS_FSS_TO_BB(mp, 1), + XFS_FSS_TO_BB(mp, 1), 0, &bp); + if (error) + return error; + ASSERT(bp); + xfs_buf_relse(bp); + + new =3D nb; /* use new as a temporary here */ + nb_mod =3D do_div(new, mp->m_sb.sb_agblocks); + printk("Cur ag=3D%d, cur blocks=3D%d\n", mp->m_sb.sb_agcount, mp->m_sb.sb= _dblocks); + nagcount =3D new + (nb_mod !=3D 0); + printk("New ag=3D%d, new blocks=3D%d, nb_mod=3D%d\n", new, nb, nb_mod); + if (nb_mod && nb_mod < XFS_MIN_AG_BLOCKS) { + printk("nb_mod (%d) < XFS_MIN_AG_BLOCKS (%d)\n", nb_mod, XFS_MIN_AG_BLOC= KS); + nagcount--; + nb =3D nagcount * mp->m_sb.sb_agblocks; + printk("ne2 ag=3D%d, ne2 blocks=3D%d\n", nagcount, nb); + if (nb >=3D mp->m_sb.sb_dblocks) + return XFS_ERROR(EINVAL); + } + printk("Will resize from %d to %d, delta is %d\n", mp->m_sb.sb_dblocks, n= b, mp->m_sb.sb_dblocks - nb); + /* Check to see if we trip over the log section */ + printk("logstart=3D%ld logblocks=3D%ld\n", mp->m_sb.sb_logstart, mp->m_sb= .sb_logblocks); + if (nb < mp->m_sb.sb_logstart + mp->m_sb.sb_logblocks) + return XFS_ERROR(EINVAL); + new =3D nb - mp->m_sb.sb_dblocks; + oagcount =3D mp->m_sb.sb_agcount; + tp =3D xfs_trans_alloc(mp, XFS_TRANS_GROWFS); + printk("reserving %d\n", XFS_GROWFS_SPACE_RES(mp) + (-new)); + if ((error =3D xfs_trans_reserve(tp, XFS_GROWFS_SPACE_RES(mp) + (-new), + XFS_GROWDATA_LOG_RES(mp), 0, 0, 0))) { + xfs_trans_cancel(tp, 0); + return error; + } + + nfree =3D 0; + for(agno =3D oagcount - 1; agno >=3D nagcount; agno--) { + xfs_extlen_t usedblks; /* total used blocks in this a.g. */ + xfs_extlen_t freeblks; /* free blocks in this a.g. */ + xfs_extlen_t metaused; /* blocks used by metadata */ + xfs_agblock_t aglen; + xfs_btree_cur_t *cur; /* cursor used for btree iteration */ + xfs_extlen_t sizeibt; /* blocks used by inode btree */ + xfs_extlen_t sizeino; /* blocks used by inode chunks */ + xfs_extlen_t sizebno; /* blocks used by by-number btree */ + xfs_extlen_t sizecnt; /* blocks used by by-count btree */ + printk("doing agno=3D%d\n", agno); + + /* + * Check the inodes and get ino btree usage + */ + error =3D xfs_ialloc_read_agi(mp, tp, agno, &bp); + if (error) { + goto error0; + } + ASSERT(bp); + agi =3D XFS_BUF_TO_AGI(bp); + /* This a.g. has inodes in use, can't shrink */ + if(INT_GET(agi->agi_count, ARCH_CONVERT) !=3D INT_GET(agi->agi_freecount= , ARCH_CONVERT)) { + printk("agi %d has %d inodes in use\n", agno, INT_GET(agi->agi_count, A= RCH_CONVERT) - INT_GET(agi->agi_freecount, ARCH_CONVERT)); + error =3D XFS_ERROR(ENOSPC); + goto error0; + } + /* Record the number of inodes (total and free) + * to substract from the superblock + */ + icount -=3D INT_GET(agi->agi_count, ARCH_CONVERT); + ifree -=3D INT_GET(agi->agi_freecount, ARCH_CONVERT); + + /* Compute the number of blocks used by inode chunks + * in this a.g. + */ + cur =3D xfs_btree_init_cursor(mp, tp, bp, agno, XFS_BTNUM_INO, NULL, 0); + sizeibt =3D sizeino =3D 0; + error =3D xfs_inobtsize(cur, cur->bc_nlevels - 1, INT_GET(agi->agi_root,= ARCH_CONVERT), &sizeibt, &sizeino); + xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); + if(error) { + goto error0; + } + printk("agi %d shows %d block in use by ino btree, %d blocks by inodes\n= ", agno, sizeibt, sizeino); + + /* Compute number of blocks used by the freelist and free btrees in this= a.g. */ + error =3D xfs_alloc_read_agf(mp, tp, agno, 0, &bp); + if (error) { + goto error0; + } + ASSERT(bp); + agf =3D XFS_BUF_TO_AGF(bp); +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20 + freeblks =3D INT_GET(agf->agf_freeblks, ARCH_CONVERT); + printk("Usage: %d prealloc, %d flcount\n", XFS_PREALLOC_BLOCKS(mp), INT_= GET(agf->agf_flcount, ARCH_CONVERT)); + /* BNO btree processing */ + sizebno =3D 0; + cur =3D xfs_btree_init_cursor(mp, tp, bp, agno, XFS_BTNUM_BNO, NULL, 0); + error =3D xfs_alloc_btsize(cur, cur->bc_nlevels - 1, INT_GET(agf->agf_ro= ots[XFS_BTNUM_BNO], ARCH_CONVERT), &sizebno); + xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); + if(error) { + goto error0; + } + printk("agf %d shows %d block in use by bno btree\n", agno, sizebno); + /* CNT btree processing */ + sizecnt =3D 0; + cur =3D xfs_btree_init_cursor(mp, tp, bp, agno, XFS_BTNUM_CNT, NULL, 0); + error =3D xfs_alloc_btsize(cur, cur->bc_nlevels - 1, INT_GET(agf->agf_ro= ots[XFS_BTNUM_CNT], ARCH_CONVERT), &sizecnt); + xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); + if(error) { + goto error0; + } + printk("agf %d shows %d block in use by cnt btree\n", agno, sizecnt); +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20 + /* Done gathering data, check sizes */ + /* We don't add here the sizebno and sizecnt since + * it appears they are not computed as 'used' space + */ + metaused =3D sizeino + sizeibt - 1; + + usedblks =3D XFS_PREALLOC_BLOCKS(mp) + \ + INT_GET(agf->agf_flcount, ARCH_CONVERT) + \ + metaused + sizebno - 1 + sizecnt - 1; + aglen =3D INT_GET(agf->agf_length, ARCH_CONVERT); + printk("agno=3D%d agf_length=3D%d computed used=3D%d known free=3D%d\n",= agno, aglen, usedblks, INT_GET(agf->agf_freeblks, ARCH_CONVERT)); + if(usedblks + freeblks !=3D aglen) { + printk("agno %d is not free (%d blocks allocated)\n", agno, aglen-usedb= lks-freeblks); + error =3D XFS_ERROR(ENOSPC); + goto error0; + } + new +=3D aglen; + printk("will lower with %d\n", aglen - XFS_PREALLOC_BLOCKS(mp) - metause= d); + nfree -=3D aglen - XFS_PREALLOC_BLOCKS(mp); + /* add not substract because previously these were counted as used + * think of it as first free'ing the inodes and the inode btree + * and then chopping all the other blocks from the fdblocks + */ + inofree +=3D metaused; + } + /* + * There are new blocks in the old last a.g. + */ + if (new) { + printk("Shrinking last a.g. with %d blocks\n", new); + memset(&allocarg, 0, sizeof(allocarg)); + error =3D xfs_alloc_read_agf(mp, tp, agno, 0, &bp); + if (error) { + goto error0; + } + ASSERT(bp); + agf =3D XFS_BUF_TO_AGF(bp); + allocarg.tp =3D tp; + allocarg.mp =3D mp; + allocarg.agbp =3D bp; + allocarg.agno =3D agno; + allocarg.agbno =3D INT_GET(agf->agf_length, ARCH_CONVERT) + new; + allocarg.fsbno =3D XFS_AGB_TO_FSB(mp, agno, allocarg.agbno); + allocarg.minlen =3D -new; + allocarg.maxlen =3D -new; + allocarg.prod =3D -new; + allocarg.mod =3D 0; + allocarg.minleft =3D 0; + allocarg.total =3D -new; + allocarg.type =3D XFS_ALLOCTYPE_THIS_BNO; + allocarg.alignment =3D 1; + printk("agf_free before=3D%d\n", INT_GET(agf->agf_freeblks, ARCH_CONVERT= )); + error =3D xfs_alloc_vextent(&allocarg); + if (error) { + printk("error in alloc extent\n"); + goto error0; + } + if(allocarg.agbno =3D=3D NULLAGBLOCK) { + error =3D XFS_ERROR(ENOSPC); + goto error0; + } + printk("agf_free after=3D%d\n", INT_GET(agf->agf_freeblks, ARCH_CONVERT)= ); + //nfree +=3D new; /* + because new is already negative */ + /* + * Change the agi length. + */ + error =3D xfs_ialloc_read_agi(mp, tp, agno, &bp); + if (error) { + goto error0; + } + ASSERT(bp); + agi =3D XFS_BUF_TO_AGI(bp); + INT_MOD(agi->agi_length, ARCH_CONVERT, new); + printk("agno=3D%d agi_length=3D%ld\n", agno, INT_GET(agi->agi_length, AR= CH_CONVERT)); + + xfs_ialloc_log_agi(tp, bp, XFS_AGI_LENGTH); + /* + * Change agf length. + */ + INT_MOD(agf->agf_length, ARCH_CONVERT, new); + printk("agno=3D%d agf_length=3D%ld\n", agno, INT_GET(agf->agf_length, AR= CH_CONVERT)); + ASSERT(INT_GET(agf->agf_length, ARCH_CONVERT) =3D=3D + INT_GET(agi->agi_length, ARCH_CONVERT)); + } + printk("nfree value: %d, oagcount=3D%d, nagcount=3D%d\n", nfree, oagcount= , nagcount); + xfs_trans_agblocks_delta(tp, nfree); + xfs_trans_agblocks_delta(tp, inofree); + + if (nagcount < oagcount) + xfs_trans_mod_sb(tp, XFS_TRANS_SB_AGCOUNT, nagcount - oagcount); + if (nb < mp->m_sb.sb_dblocks) + xfs_trans_mod_sb(tp, XFS_TRANS_SB_DBLOCKS, + nb - mp->m_sb.sb_dblocks); + if (nfree) + xfs_trans_mod_sb(tp, XFS_TRANS_SB_FDBLOCKS, nfree); + if (inofree) + xfs_trans_mod_sb(tp, XFS_TRANS_SB_FDBLOCKS, inofree); + if (icount) + xfs_trans_mod_sb(tp, XFS_TRANS_SB_ICOUNT, icount); + if (ifree) + xfs_trans_mod_sb(tp, XFS_TRANS_SB_IFREE, ifree); + if (dpct) + xfs_trans_mod_sb(tp, XFS_TRANS_SB_IMAXPCT, dpct); + error =3D xfs_trans_commit(tp, 0, NULL); + if (error) { + return error; + } + /* Free memory if the number of a.g. has changed */ + if (nagcount < oagcount) { + down_write(&mp->m_peraglock); + for (agno =3D nagcount; agno < oagcount; agno++) + if (mp->m_perag[agno].pagb_list) + kmem_free(mp->m_perag[agno].pagb_list, + sizeof(xfs_perag_busy_t) * + XFS_PAGB_NUM_SLOTS); +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20 + mp->m_perag =3D kmem_realloc(mp->m_perag, + sizeof(xfs_perag_t) * nagcount, + sizeof(xfs_perag_t) * oagcount, + KM_SLEEP); + /* FIXME: here we could instead just lower + * nagimax to nagcount; is it better this way? + */ + mp->m_flags |=3D XFS_MOUNT_32BITINODES; + nagimax =3D xfs_initialize_perag(mp, nagcount); + up_write(&mp->m_peraglock); + } + + /* New allocation groups fully initialized, so update mount struct */ + if (nagimax) + mp->m_maxagi =3D nagimax; + if (mp->m_sb.sb_imax_pct) { + __uint64_t icount =3D mp->m_sb.sb_dblocks * mp->m_sb.sb_imax_pct; + do_div(icount, 100); + mp->m_maxicount =3D icount << mp->m_sb.sb_inopblog; + } else + mp->m_maxicount =3D 0; + for (agno =3D 1; agno < nagcount; agno++) { + error =3D xfs_read_buf(mp, mp->m_ddev_targp, + XFS_AGB_TO_DADDR(mp, agno, XFS_SB_BLOCK(mp)), + XFS_FSS_TO_BB(mp, 1), 0, &bp); + if (error) { + xfs_fs_cmn_err(CE_WARN, mp, + "error %d reading secondary superblock for ag %d", + error, agno); + break; + } + sbp =3D XFS_BUF_TO_SBP(bp); + xfs_xlatesb(sbp, &mp->m_sb, -1, XFS_SB_ALL_BITS); + /* + * If we get an error writing out the alternate superblocks, + * just issue a warning and continue. The real work is + * already done and committed. + */ + if (!(error =3D xfs_bwrite(mp, bp))) { + continue; + } else { + xfs_fs_cmn_err(CE_WARN, mp, + "write error %d updating secondary superblock for ag %d", + error, agno); + break; /* no point in continuing */ + } + } + return 0; + + error0: + xfs_trans_cancel(tp, XFS_TRANS_ABORT); + return error; +} + + +static int xfs_growfs_log_private( xfs_mount_t *mp, /* mount point for filesystem */ xfs_growfs_log_t *in) /* growfs log input struct */ diff -urN -x xfs_ialloc_btree.h.orig -x xfs_trans.c.orig -x Entries.Log -x = Entries linux-2.6-xfs.orig/fs/xfs/xfs_ialloc_btree.c linux-2.6-xfs/fs/xfs/x= fs_ialloc_btree.c --- linux-2.6-xfs.orig/fs/xfs/xfs_ialloc_btree.c 2005-01-13 00:38:29.000000= 000 +0200 +++ linux-2.6-xfs/fs/xfs/xfs_ialloc_btree.c 2005-09-06 02:01:39.029406448 += 0300 @@ -1672,6 +1672,95 @@ */ =20 /* + * Compute the size (in blocks) of the btree in the given level/block numb= er + */ +int /* error */ +xfs_inobtsize( + struct xfs_btree_cur *cur, /* btree cursor */ + int level, /* current level */ + xfs_agblock_t agbno, /* a.g. relative btree block number */ + int *btsize,/* pointer to btree size, to be incremented */ + int *inosize) /* pointer to inode blocks, to be incremented */ +{ + xfs_agnumber_t agno; + xfs_alloc_block_t *block=3DNULL; /* current btree block */ + int error; /* error return value */ + int ptrno; /* current key number */ + xfs_daddr_t d; /* disk address of btree block */ + xfs_buf_t *bp; /* buffer pointer for btree block */ + + { + xfs_agi_t *agi; /* a.g. inode header */ + + agi =3D XFS_BUF_TO_AGI(cur->bc_private.i.agbp); + agno =3D INT_GET(agi->agi_seqno, ARCH_CONVERT); + } + + + d =3D XFS_AGB_TO_DADDR(cur->bc_mp, agno, agbno); + printk("inobtsize agno=3D%d agbno=3D%d diskaddr=3D%lld level=3D%d bt=3D%d= ino=3D%d\n", agno, agbno, d, level, *btsize, *inosize); + bp =3D cur->bc_bufs[level]; + if (bp && XFS_BUF_ADDR(bp) !=3D d) + bp =3D (xfs_buf_t *)0; + if (!bp) { + /* + * Need to get a new buffer. Read it, then + * set it in the cursor, releasing the old one. + */ + if ((error =3D xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp, agno, + agbno, 0, &bp, XFS_INO_BTREE_REF))) + return error; + xfs_btree_setbuf(cur, level, bp); + /* + * Point to the btree block, now that we have the buffer + */ + block =3D XFS_BUF_TO_INOBT_BLOCK(bp); + if ((error =3D xfs_btree_check_sblock(cur, block, level, + bp))) + return error; + } else + block =3D XFS_BUF_TO_INOBT_BLOCK(bp); + + if(level =3D=3D 0) { + printk("numrecs=3D%d\n", INT_GET(block->bb_numrecs, ARCH_CONVERT)); + for( ptrno =3D 0; ptrno < INT_GET(block->bb_numrecs, ARCH_CONVERT); ptrn= o++) { + xfs_inobt_rec_t *rec; + xfs_agino_t istart, istop; + xfs_agblock_t bstart, bstop; + + rec =3D XFS_INOBT_REC_ADDR(block, ptrno + 1, cur); + istart =3D INT_GET(rec->ir_startino, ARCH_CONVERT); + istop =3D istart + XFS_INODES_PER_CHUNK - 1; + bstart =3D XFS_AGINO_TO_AGBNO(cur->bc_mp, istart); + bstop =3D XFS_AGINO_TO_AGBNO(cur->bc_mp, istop); + printk("level0, recno %d, start inode %d, stop inode %d, start block %d= , stop block %d, used blocks %d\n", + ptrno, istart, istop, bstart, bstop, bstop - bstart + 1); + (*inosize) +=3D bstop - bstart + 1; + } + (*btsize)++; + return 0; + } + + /* + * Iterate over each child in this non-leaf block + */ + for (ptrno =3D 0; ptrno < INT_GET(block->bb_numrecs, ARCH_CONVERT); ptrno= ++) { + xfs_inobt_ptr_t *ptr; + xfs_agblock_t newbno; + + ptr =3D XFS_INOBT_PTR_ADDR(block, ptrno + 1, cur); + newbno =3D INT_GET(*ptr, ARCH_CONVERT); + printk("\twill enter ptrno=3D%d (of %d) agbno=3D%d\n", ptrno, INT_GET(bl= ock->bb_numrecs, ARCH_CONVERT), newbno); + + if((error =3D xfs_inobtsize(cur, level - 1, newbno, btsize, inosize))) + return error; + + } + (*btsize)++; + return 0; +} + +/* * Decrement cursor by one record at the level. * For nonzero levels the leaf-ward information is untouched. */ diff -urN -x xfs_ialloc_btree.h.orig -x xfs_trans.c.orig -x Entries.Log -x = Entries linux-2.6-xfs.orig/fs/xfs/xfs_ialloc_btree.h linux-2.6-xfs/fs/xfs/x= fs_ialloc_btree.h --- linux-2.6-xfs.orig/fs/xfs/xfs_ialloc_btree.h 2005-06-07 17:39:14.000000= 000 +0300 +++ linux-2.6-xfs/fs/xfs/xfs_ialloc_btree.h 2005-09-06 02:01:39.040404776 += 0300 @@ -219,6 +219,17 @@ */ =20 /* + * Compute the size (in blocks) of the btree in the given level/block numb= er + */ +int /* error */ +xfs_inobtsize( + struct xfs_btree_cur *cur, /* btree cursor */ + int level, + xfs_agblock_t agbno, /* a.g. relative btree block number */ + int *btsize,/* pointer to btree size, to be incremented */ + int *inosize); /* pointer to inode blocks, to be incremented */ + +/* * Decrement cursor by one record at the level. * For nonzero levels the leaf-ward information is untouched. */ diff -urN -x xfs_ialloc_btree.h.orig -x xfs_trans.c.orig -x Entries.Log -x = Entries linux-2.6-xfs.orig/fs/xfs/xfs_trans.c linux-2.6-xfs/fs/xfs/xfs_tran= s.c --- linux-2.6-xfs.orig/fs/xfs/xfs_trans.c 2005-07-13 06:43:58.000000000 +03= 00 +++ linux-2.6-xfs/fs/xfs/xfs_trans.c 2005-09-06 02:01:39.041404624 +0300 @@ -396,11 +396,9 @@ tp->t_res_frextents_delta +=3D delta; break; case XFS_TRANS_SB_DBLOCKS: - ASSERT(delta > 0); tp->t_dblocks_delta +=3D delta; break; case XFS_TRANS_SB_AGCOUNT: - ASSERT(delta > 0); tp->t_agcount_delta +=3D delta; break; case XFS_TRANS_SB_IMAXPCT: --OXfL5xGRrasGEqWY-- --E39vaYmALEf/7YXx Content-Type: application/pgp-signature; name="signature.asc" Content-Description: Digital signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.1 (GNU/Linux) iD8DBQFDHNL24mx23Z34NMIRAgssAKDPfHPAGt6rVX9vI+t+vcB59XWObQCfUoNk Px+nUhlItl/dpUx4EhWs6/Q= =a4jF -----END PGP SIGNATURE----- --E39vaYmALEf/7YXx--