xfs: implement xfs_perag_inumbers
PATCH 4/10 xfs: implement xfs_perag_inumbers
From: Jie Liu <[email protected]>
Introduce xfs_perag_inumbers(), it could be used to fetch inode 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 | 175 +++++++++++++++++++++++++++++++++------------------- fs/xfs/xfs_itable.h | 13 +++- 2 files changed, 121 insertions(+), 67 deletions(-)
fs/xfs/xfs_itable.c +110 -65
@@ -569,51 +569,42 @@ 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); -int left = *count; -struct xfs_btree_cur *cur =NULL ; -struct xfs_buf *agbp =NULL ; -struct xfs_inogrp *buffer; -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 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); +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); - } +/* Done if failed to lookup or no inode chuck is found */ error =xfs_inobt_lookup (cur, agino,XFS_LOOKUP_GE , &stat); - if (error) +if (error || stat ==0 )break ; - if (!stat) { - /* Done, proceed to look up the next AG */ - goto next_ag; - } error =xfs_inobt_get_rec (cur, &r, &stat);if (error)
@@ -621,59 +612,113 @@ xfs_inumbers(XFS_WANT_CORRUPTED_GOTO (stat ==1 , error0); 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 ; } -if (!--left) +if (!--ubleft)break ; error =xfs_btree_increment (cur,0 , &stat); -if (error) +if (error || stat ==0 ) { +/* Done if failed or there are no rightward entries */ break ; -if (stat) { -/* -* The agino value has already been bumped, just try -* to skip up to it. -*/ - agino +=XFS_INODES_PER_CHUNK ; -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); +/* +* The agino value has already been bumped. Just try to skip +* up to it. +*/ + agino +=XFS_INODES_PER_CHUNK ; + }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; } 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); -if (cur) -xfs_btree_del_cursor (cur, (error ?XFS_BTREE_ERROR : -XFS_BTREE_NOERROR )); -if (agbp) -xfs_buf_relse (agbp);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
As per the discussion with Brain in "[PATCH 3/10] xfs: consolidate xfs_inumbers",
Please ignore this patch since it need a distinct fix.
Thanks,
-Jeff
Quoted 266 lines · Jeff Liu
From: Jie Liu <[email protected]>
Introduce
xfs_perag_inumbers(), it could be used to fetch inode 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.Signed-off-by Jie Liu <[email protected]>--- fs/xfs/xfs_itable.c | 175 +++++++++++++++++++++++++++++++++------------------- fs/xfs/xfs_itable.h | 13 +++- 2 files changed, 121 insertions(+), 67 deletions(-)fs/xfs/xfs_itable.c +110
-65@@ -569,51 +569,42 @@ 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); -int left = *count; -struct xfs_btree_cur *cur =NULL ; -struct xfs_buf *agbp =NULL ; -struct xfs_inogrp *buffer; -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 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); +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); - } +/* Done if failed to lookup or no inode chuck is found */ error =xfs_inobt_lookup (cur, agino,XFS_LOOKUP_GE , &stat); - if (error) +if (error || stat ==0 )break ; - if (!stat) { - /* Done, proceed to look up the next AG */ - goto next_ag; - } error =xfs_inobt_get_rec (cur, &r, &stat);if (error)@@ -621,59 +612,113 @@ xfs_inumbers(XFS_WANT_CORRUPTED_GOTO (stat ==1 , error0); 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 ; } -if (!--left) +if (!--ubleft)break ; error =xfs_btree_increment (cur,0 , &stat); -if (error) +if (error || stat ==0 ) { +/* Done if failed or there are no rightward entries */ break ; -if (stat) { -/* -* The agino value has already been bumped, just try -* to skip up to it. -*/ - agino +=XFS_INODES_PER_CHUNK ; -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); +/* +* The agino value has already been bumped. Just try to skip +* up to it. +*/ + agino +=XFS_INODES_PER_CHUNK ; + }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; } 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); -if (cur) -xfs_btree_del_cursor (cur, (error ?XFS_BTREE_ERROR : -XFS_BTREE_NOERROR )); -if (agbp) -xfs_buf_relse (agbp);return error; }fs/xfs/xfs_itable.h +4
-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 {
fs/xfs/xfs_itable.h xfs_bulkstat_one( · line 108
Quoted 10 lines
fs/xfs/xfs_itable.h +7
-0+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 */
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs