From: Christoph Hellwig <hch@infradead.org>
To: xfs@oss.sgi.com
Subject: [PATCH 7/7] xfs: merge xfs_ialloc_ag_select into xfs_dialloc
Date: Wed, 04 Jul 2012 10:54:51 -0400 [thread overview]
Message-ID: <20120704145616.894941902@bombadil.infradead.org> (raw)
In-Reply-To: 20120704145444.863203951@bombadil.infradead.org
[-- Attachment #1: xfs-dialloc-factor-ag_selection-2 --]
[-- Type: text/plain, Size: 6489 bytes --]
Both function contain the same basic loop over all AGs. Merge the two
by creating three passes in the loop instead of duplicating the code.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/xfs/xfs_ialloc.c | 179 +++++++++++++++-------------------------------------
1 file changed, 55 insertions(+), 124 deletions(-)
Index: xfs/fs/xfs/xfs_ialloc.c
===================================================================
--- xfs.orig/fs/xfs/xfs_ialloc.c 2012-07-02 12:25:24.365774992 +0200
+++ xfs/fs/xfs/xfs_ialloc.c 2012-07-02 12:26:14.325774734 +0200
@@ -439,114 +439,6 @@ xfs_ialloc_next_ag(
}
/*
- * Select an allocation group to look for a free inode in, based on the parent
- * inode and then mode. Return the allocation group buffer.
- */
-STATIC xfs_agnumber_t
-xfs_ialloc_ag_select(
- xfs_trans_t *tp, /* transaction pointer */
- xfs_ino_t parent, /* parent directory inode number */
- umode_t mode, /* bits set to indicate file type */
- int okalloc) /* ok to allocate more space */
-{
- xfs_agnumber_t agcount; /* number of ag's in the filesystem */
- xfs_agnumber_t agno; /* current ag number */
- int flags; /* alloc buffer locking flags */
- xfs_extlen_t ineed; /* blocks needed for inode allocation */
- xfs_extlen_t longest = 0; /* longest extent available */
- xfs_mount_t *mp; /* mount point structure */
- int needspace; /* file mode implies space allocated */
- xfs_perag_t *pag; /* per allocation group data */
- xfs_agnumber_t pagno; /* parent (starting) ag number */
- int error;
-
- /*
- * Files of these types need at least one block if length > 0
- * (and they won't fit in the inode, but that's hard to figure out).
- */
- needspace = S_ISDIR(mode) || S_ISREG(mode) || S_ISLNK(mode);
- mp = tp->t_mountp;
- agcount = mp->m_maxagi;
- if (S_ISDIR(mode))
- pagno = xfs_ialloc_next_ag(mp);
- else {
- pagno = XFS_INO_TO_AGNO(mp, parent);
- if (pagno >= agcount)
- pagno = 0;
- }
-
- ASSERT(pagno < agcount);
-
- /*
- * Loop through allocation groups, looking for one with a little
- * free space in it. Note we don't look for free inodes, exactly.
- * Instead, we include whether there is a need to allocate inodes
- * to mean that blocks must be allocated for them,
- * if none are currently free.
- */
- agno = pagno;
- flags = XFS_ALLOC_FLAG_TRYLOCK;
- for (;;) {
- pag = xfs_perag_get(mp, agno);
- if (!pag->pagi_inodeok) {
- xfs_ialloc_next_ag(mp);
- goto nextag;
- }
-
- if (!pag->pagi_init) {
- error = xfs_ialloc_pagi_init(mp, tp, agno);
- if (error)
- goto nextag;
- }
-
- if (pag->pagi_freecount) {
- xfs_perag_put(pag);
- return agno;
- }
-
- if (!okalloc)
- goto nextag;
-
- if (!pag->pagf_init) {
- error = xfs_alloc_pagf_init(mp, tp, agno, flags);
- if (error)
- goto nextag;
- }
-
- /*
- * Is there enough free space for the file plus a block of
- * inodes? (if we need to allocate some)?
- */
- ineed = XFS_IALLOC_BLOCKS(mp);
- longest = pag->pagf_longest;
- if (!longest)
- longest = pag->pagf_flcount > 0;
-
- if (pag->pagf_freeblks >= needspace + ineed &&
- longest >= ineed) {
- xfs_perag_put(pag);
- return agno;
- }
-nextag:
- xfs_perag_put(pag);
- /*
- * No point in iterating over the rest, if we're shutting
- * down.
- */
- if (XFS_FORCED_SHUTDOWN(mp))
- return NULLAGNUMBER;
- agno++;
- if (agno >= agcount)
- agno = 0;
- if (agno == pagno) {
- if (flags == 0)
- return NULLAGNUMBER;
- flags = 0;
- }
- }
-}
-
-/*
* Try to retrieve the next record to the left/right from the current one.
*/
STATIC int
@@ -901,10 +793,10 @@ xfs_dialloc(
struct xfs_buf *agbp;
xfs_agnumber_t agno;
int error;
- int ialloced;
int noroom = 0;
xfs_agnumber_t start_agno;
struct xfs_perag *pag;
+ int pass;
if (*IO_agbp) {
/*
@@ -917,16 +809,6 @@ xfs_dialloc(
}
/*
- * We do not have an agbp, so select an initial allocation
- * group for inode allocation.
- */
- start_agno = xfs_ialloc_ag_select(tp, parent, mode, okalloc);
- if (start_agno == NULLAGNUMBER) {
- *inop = NULLFSINO;
- return 0;
- }
-
- /*
* If we have already hit the ceiling of inode blocks then clear
* okalloc so we scan all available agi structures for a free
* inode.
@@ -938,12 +820,31 @@ xfs_dialloc(
}
/*
- * Loop until we find an allocation group that either has free inodes
- * or in which we can allocate some inodes. Iterate through the
- * allocation groups upward, wrapping at the end.
+ * For directories start with a new allocation groups, for other file
+ * types aim to find an inode close to the parent.
*/
+ if (S_ISDIR(mode)) {
+ start_agno = xfs_ialloc_next_ag(mp);
+ ASSERT(start_agno < mp->m_maxagi);
+ } else {
+ start_agno = XFS_INO_TO_AGNO(mp, parent);
+ if (start_agno >= mp->m_maxagi)
+ start_agno = 0;
+ }
+
+ /*
+ * Loop through allocation groups, looking for one with a little
+ * free space in it. Note we don't look for free inodes, exactly.
+ * Instead, we include whether there is a need to allocate inodes
+ * to mean that blocks must be allocated for them, if none are
+ * currently free.
+ */
+ *inop = NULLFSINO;
agno = start_agno;
+ pass = 0;
for (;;) {
+ int ialloced;
+
pag = xfs_perag_get(mp, agno);
if (!pag->pagi_inodeok) {
xfs_ialloc_next_ag(mp);
@@ -980,6 +881,33 @@ xfs_dialloc(
goto nextag;
}
+ if (!pag->pagf_init) {
+ int flags = pass ? 0 : XFS_ALLOC_FLAG_TRYLOCK;
+
+ error = xfs_alloc_pagf_init(mp, tp, agno, flags);
+ if (error)
+ goto out_error;
+ }
+
+ if (pass < 2) {
+ /*
+ * Is there enough free space for the file plus a block
+ * of inodes?
+ */
+ xfs_extlen_t longest = pag->pagf_longest;
+ int needspace =
+ S_ISDIR(mode) || S_ISREG(mode) || S_ISLNK(mode);
+
+ if (!longest)
+ longest = pag->pagf_flcount > 0;
+
+ if (pag->pagf_freeblks <
+ XFS_IALLOC_BLOCKS(mp) + needspace)
+ goto nextag;
+ if (longest < XFS_IALLOC_BLOCKS(mp))
+ goto nextag;
+ }
+
error = xfs_ialloc_ag_alloc(tp, agbp, &ialloced);
if (error) {
xfs_trans_brelse(tp, agbp);
@@ -1012,8 +940,11 @@ nextag:
if (++agno == mp->m_sb.sb_agcount)
agno = 0;
if (agno == start_agno) {
- *inop = NULLFSINO;
- return noroom ? ENOSPC : 0;
+ if (pass == 2) {
+ *inop = NULLFSINO;
+ return noroom ? ENOSPC : 0;
+ }
+ pass++;
}
}
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
next prev parent reply other threads:[~2012-07-04 14:56 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-07-04 14:54 [PATCH 0/7] inode allocator refactoring V2 Christoph Hellwig
2012-07-04 14:54 ` [PATCH 1/7] xfs: remove xfs_ialloc_find_free Christoph Hellwig
2012-07-04 14:54 ` [PATCH 2/7] xfs: split xfs_dialloc Christoph Hellwig
2012-07-29 20:55 ` Ben Myers
2012-07-04 14:54 ` [PATCH 3/7] xfs: remove the alloc_done argument to xfs_dialloc Christoph Hellwig
2012-07-26 17:48 ` Mark Tinguely
2012-07-04 14:54 ` [PATCH 4/7] xfs: add a short cut to xfs_dialloc for the non-NULL agbp case Christoph Hellwig
2012-07-26 17:50 ` Mark Tinguely
2012-07-04 14:54 ` [PATCH 5/7] xfs: refactor xfs_ialloc_ag_select Christoph Hellwig
2012-07-26 17:53 ` Mark Tinguely
2012-07-04 14:54 ` [PATCH 6/7] xfs: do not read the AGI buffer in xfs_dialloc until nessecary Christoph Hellwig
2012-07-26 17:53 ` Mark Tinguely
2012-07-04 14:54 ` Christoph Hellwig [this message]
2012-07-26 17:47 ` [PATCH 7/7] xfs: merge xfs_ialloc_ag_select into xfs_dialloc Mark Tinguely
2012-07-30 17:21 ` Mark Tinguely
-- strict thread matches above, loose matches on Subject: below --
2012-06-05 14:46 [PATCH 0/7] inode allocator refactoring Christoph Hellwig
2012-06-05 14:46 ` [PATCH 7/7] xfs: merge xfs_ialloc_ag_select into xfs_dialloc Christoph Hellwig
2012-06-18 3:10 ` Dave Chinner
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=20120704145616.894941902@bombadil.infradead.org \
--to=hch@infradead.org \
--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.