From: Jeff Liu <jeff.liu@oracle.com>
To: "xfs@oss.sgi.com" <xfs@oss.sgi.com>
Subject: [PATCH v2 04/10] xfs: introduce per allocation group inumbers
Date: Fri, 18 Apr 2014 08:58:29 +0800 [thread overview]
Message-ID: <535078B5.4010700@oracle.com> (raw)
From: Jie Liu <jeff.liu@oracle.com>
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.
Signed-off-by: Jie Liu <jeff.liu@oracle.com>
---
fs/xfs/xfs_itable.c | 179 ++++++++++++++++++++++++++++++++--------------------
fs/xfs/xfs_itable.h | 13 +++-
2 files changed, 123 insertions(+), 69 deletions(-)
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index 2025bd0..62cf2f8 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -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;
}
diff --git a/fs/xfs/xfs_itable.h b/fs/xfs/xfs_itable.h
index 21dbbd7..9c3e535 100644
--- a/fs/xfs/xfs_itable.h
+++ b/fs/xfs/xfs_itable.h
@@ -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 */
--
1.8.3.2
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
next reply other threads:[~2014-04-18 0:58 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-04-18 0:58 Jeff Liu [this message]
2014-04-25 6:43 ` [PATCH v2 04/10] xfs: introduce per allocation group inumbers Christoph Hellwig
2014-04-25 7:14 ` Jeff Liu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=535078B5.4010700@oracle.com \
--to=jeff.liu@oracle.com \
--cc=xfs@oss.sgi.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.