xfs: introduce per allocation group inumbers
PATCH v2 4/10 xfs: introduce per allocation group inumbers
From: Jie Liu <[email protected]>
Introduce xfs_perag_inumbers(), it could be used to fetch the inode number tables per allocation group via a new ioctl(2) in the future. Also, that would be a net win considering the scalability for a file system with huge number of inodes as multiple allocation groups can be scanned in parallel, refactor xfs_inumbers() with it.
--- fs/xfs/xfs_itable.c | 179 ++++++++++++++++++++++++++++++++-------------------- fs/xfs/xfs_itable.h | 13 +++- 2 files changed, 123 insertions(+), 69 deletions(-)
fs/xfs/xfs_itable.c +112 -67
@@ -570,105 +570,150 @@ xfs_inumbers_fmt( }/* -* Return inode number table for the filesystem. +* Return inode number table in an allocation group. Record how many elements +* have been written out and update the last allocation group inode number on +* success. Otherwise, those values will remain the same and return error. */ -int /* error status */ -xfs_inumbers ( -struct xfs_mount *mp,/* mount point for filesystem */ -xfs_ino_t *lastino,/* last inode returned */ -int *count,/* size of buffer/count returned */ -void __user *ubuffer,/* buffer with inode desc */ +static int +xfs_perag_inumbers ( +struct xfs_mount *mp, +struct xfs_aginumbers *aip, +struct xfs_inogrp *buffer, +int bcount,inumbers_fmt_pf formatter) { -xfs_agnumber_t agno =XFS_INO_TO_AGNO (mp, *lastino); -xfs_agino_t agino =XFS_INO_TO_AGINO (mp, *lastino); -struct xfs_btree_cur *cur =NULL ; -struct xfs_buf *agbp =NULL ; -struct xfs_inogrp *buffer; -int left = *count; -int bcount; -int bufidx; +xfs_agnumber_t agno = aip->ai_agno; +xfs_agino_t agino = *(aip->ai_lastip); +char *ubuffer = aip->ai_ubuffer; +int ubleft = aip->ai_icount; +int bufidx =0 ; +long count =0 ;/* # elements written out */ +struct xfs_agi *agi; +struct xfs_buf *agbp; +struct xfs_btree_cur *cur; +int stat;int error; - *count =0 ; -if (agno >= mp->m_sb.sb_agcount || - *lastino !=XFS_AGINO_TO_INO (mp, agno, agino)) -return 0 ; - - bcount =MIN (left, (int )(PAGE_SIZE /sizeof (*buffer))); - buffer =kmem_alloc (bcount *sizeof (*buffer),KM_SLEEP ); - bufidx = error =0 ; -do { + error =xfs_ialloc_read_agi (mp,NULL , agno, &agbp); +if (error) +return error; + agi =XFS_BUF_TO_AGI (agbp); + cur =xfs_inobt_init_cursor (mp,NULL , agbp, agno); +/* Done if failed to lookup or no inode chuck is found */ + error =xfs_inobt_lookup (cur, agino,XFS_LOOKUP_GE , &stat); +if (error || !stat) + goto error0; + +for (;;) {struct xfs_inobt_rec_incore r; -int stat; - -if (!agbp) { - error =xfs_ialloc_read_agi (mp,NULL , agno, &agbp); -if (error) -break ; - cur =xfs_inobt_init_cursor (mp,NULL , agbp, agno); - error =xfs_inobt_lookup (cur, agino,XFS_LOOKUP_GE , - &stat); -if (error) -break ; -if (!stat) - goto next_ag; - } error =xfs_inobt_get_rec (cur, &r, &stat); -if (error || !stat) +if (error || !stat) { +pr_info ("xfs_inobt_get_rec: stat=%d\n" , stat);break ; + } agino = r.ir_startino +XFS_INODES_PER_CHUNK -1 ; - buffer[bufidx].xi_startino = -XFS_AGINO_TO_INO (mp, agno, r.ir_startino); - buffer[bufidx].xi_alloccount = -XFS_INODES_PER_CHUNK - r.ir_freecount; + buffer[bufidx].xi_startino =XFS_AGINO_TO_INO (mp, agno, + r.ir_startino); + buffer[bufidx].xi_alloccount =XFS_INODES_PER_CHUNK - + r.ir_freecount; buffer[bufidx].xi_allocmask = ~r.ir_free; -if (++bufidx == bcount) { +/* Run out of the given buffer range, it's time to write out */ +if (++bufidx == ubleft) {long written; error =formatter (ubuffer, buffer, bufidx, &written);if (error)break ; - ubuffer += written; - *count += bufidx; + count += bufidx; bufidx =0 ; +break ; } -if (!--left) +if (!--ubleft)break ; +/* Done if failed or there are no rightward entries */ error =xfs_btree_increment (cur,0 , &stat); -if (error) +if (error || !stat)break ; -if (stat) -continue ; - -next_ag: -xfs_btree_del_cursor (cur,XFS_BTREE_NOERROR ); - cur =NULL ; -xfs_buf_relse (agbp); - agbp =NULL ; - agino =0 ; - }while (++agno < mp->m_sb.sb_agcount); + }if (!error) { +/* +* There might have remaining inode number tables reside in +* buffer which have not yet been written out if we iterate +* beyond inode btree. We need to handle them separately. +*/ if (bufidx) {long written; error =formatter (ubuffer, buffer, bufidx, &written); -if (!error) - *count += bufidx; +if (error) + goto error0; + count += bufidx; } - *lastino =XFS_AGINO_TO_INO (mp, agno, agino); +/* Update the last AG inode number */ + *(aip->ai_lastip) = agino; +/* Record how many elements have been written out */ + aip->ai_ocount = count; } -kmem_free (buffer); -if (cur) -xfs_btree_del_cursor (cur, (error ?XFS_BTREE_ERROR : -XFS_BTREE_NOERROR )); -if (agbp) -xfs_buf_relse (agbp); +error0: +xfs_btree_del_cursor (cur, error ?XFS_BTREE_ERROR :XFS_BTREE_NOERROR ); +xfs_buf_relse (agbp); + +return error; +} + +/* Return inode number table for the filesystem */ +int +xfs_inumbers ( +struct xfs_mount *mp,/* mount point for filesystem */ +xfs_ino_t *lastinop,/* last inode returned */ +int *ubcountp,/* size of buffer/count returned */ +void __user *ubuffer,/* buffer with inode desc */ +inumbers_fmt_pf formatter) +{ +xfs_agnumber_t agno =XFS_INO_TO_AGNO (mp, *lastinop); +xfs_agino_t agino =XFS_INO_TO_AGINO (mp, *lastinop); +int ubleft = *ubcountp; +struct xfs_inogrp *buffer; +int count; +int error; + *ubcountp =0 ; +if (agno >= mp->m_sb.sb_agcount || + *lastinop !=XFS_AGINO_TO_INO (mp, agno, agino)) +return 0 ; + + count =MIN (ubleft, (int )(PAGE_SIZE /sizeof (*buffer))); + buffer =kmem_alloc (count *sizeof (*buffer),KM_SLEEP ); +do { +struct xfs_aginumbers ai; + + ai.ai_agno = agno; + ai.ai_lastip = &agino; + ai.ai_icount = ubleft; + ai.ai_ubuffer = ubuffer; + ai.ai_ocount =0 ; + error =xfs_perag_inumbers (mp, &ai, buffer, count, formatter); +if (error) +break ; + + *ubcountp += ai.ai_ocount; + ubleft -= ai.ai_ocount; +ASSERT (ubleft >=0 ); +if (!ubleft) +break ; + + ubuffer = ai.ai_ubuffer; + agino =0 ; + }while (++agno < mp->m_sb.sb_agcount); + +if (!error) + *lastinop =XFS_AGINO_TO_INO (mp, agno, agino); + +kmem_free (buffer);return error; }
fs/xfs/xfs_itable.h +11 -2
@@ -83,17 +83,26 @@ xfs_bulkstat_one(typedef int (*inumbers_fmt_pf )(void __user *ubuffer,/* buffer to write to */ -const xfs_inogrp_t *buffer,/* buffer to read from */ +const struct xfs_inogrp *buffer,/* buffer to read from */ long count,/* # of elements to read */ long *written);/* # of bytes written */ int xfs_inumbers_fmt (void __user *ubuffer,/* buffer to write to */ -const xfs_inogrp_t *buffer,/* buffer to read from */ +const struct xfs_inogrp *buffer,/* buffer to read from */ long count,/* # of elements to read */ long *written);/* # of bytes written */ +/* This structure is used for xfs_inumbers per allocation group */ +struct xfs_aginumbers { +xfs_agnumber_t ai_agno;/* AG number */ +xfs_agino_t *ai_lastip;/* last AG inode number */ +char __user *ai_ubuffer;/* user buffer to write to */ +__uint32_t ai_icount;/* # of elements to read */ +__uint32_t ai_ocount;/* # of elements written */ +}; + int /* error status */ xfs_inumbers( xfs_mount_t *mp, /* mount point for filesystem */
Signature · 6 lines
1.8.3.2 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Quoted 7 lines · Jeff Liu
From: Jie Liu <[email protected]>
Introduce
xfs_perag_inumbers(), it could be used to fetch the inode number tables per allocation group via a new ioctl(2) in the future. Also, that would be a net win considering the scalability for a file system with huge number of inodes as multiple allocation groups can be scanned in parallel, refactorxfs_inumbers()with it.
Given that you don't actually introduce a per-ag inumbers interface in this series I'd prefer if you just refactor the inumbers code to add a helper that operates on an AG with xfs_inumbers moving on to the next one, but not adding the xfs_aginumbers structure that just makes the move less obvious for now.
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Quoted 9 lines · Christoph Hellwig
Quoted 7 lines · Jeff Liu
From: Jie Liu <[email protected]>
Introduce
xfs_perag_inumbers(), it could be used to fetch the inode number tables per allocation group via a new ioctl(2) in the future. Also, that would be a net win considering the scalability for a file system with huge number of inodes as multiple allocation groups can be scanned in parallel, refactorxfs_inumbers()with it.
Quoted 5 lines
Given that you don't actually introduce a per-ag inumbers interface in this series I'd prefer if you just refactor the inumbers code to add a helper that operates on an AG with
xfs_inumbersmoving on to the next one, but not adding thexfs_aginumbersstructure that just makes the move less obvious for now.
Fair enough, I'll take care of it.
Thanks,
-Jeff
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs