From: Brian Foster <bfoster@redhat.com>
To: xfs@oss.sgi.com
Subject: [PATCH 09/18] xfs: allocate sparse inode chunks on full chunk allocation failure
Date: Thu, 24 Jul 2014 10:22:59 -0400 [thread overview]
Message-ID: <1406211788-63206-10-git-send-email-bfoster@redhat.com> (raw)
In-Reply-To: <1406211788-63206-1-git-send-email-bfoster@redhat.com>
xfs_ialloc_ag_alloc() makes several attempts to allocate a full inode
chunk. If all else fails, reduce the allocation to inode cluster size
and attempt to allocate a sparse inode chunk.
If sparse chunk allocation succeeds, check whether an inobt record
already exists that can track the chunk. If so, inherit and update the
existing record. Otherwise, insert a new record for the sparse chunk.
Update xfs_inobt_insert_rec() to take the holemask as a parameter and
set the associated field on disk. Convert xfs_inobt_insert() to
xfs_inobt_update_insert() to handle record insertion or update in a
generic fashion. This facilitates the continued use of the same function
for the inobt and finobt.
Signed-off-by: Brian Foster <bfoster@redhat.com>
---
fs/xfs/libxfs/xfs_ialloc.c | 105 +++++++++++++++++++++++++++++++++------------
1 file changed, 77 insertions(+), 28 deletions(-)
diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c
index be57b51..4226b1b 100644
--- a/fs/xfs/libxfs/xfs_ialloc.c
+++ b/fs/xfs/libxfs/xfs_ialloc.c
@@ -121,28 +121,28 @@ xfs_inobt_get_rec(
STATIC int
xfs_inobt_insert_rec(
struct xfs_btree_cur *cur,
+ __uint16_t holemask,
__int32_t freecount,
xfs_inofree_t free,
int *stat)
{
- cur->bc_rec.i.ir_holemask = 0;
+ cur->bc_rec.i.ir_holemask = holemask;
cur->bc_rec.i.ir_freecount = freecount;
cur->bc_rec.i.ir_free = free;
return xfs_btree_insert(cur, stat);
}
/*
- * Insert records describing a newly allocated inode chunk into the inobt.
+ * Update or insert records describing a newly allocated inode chunk into the
+ * specified inobt.
*/
STATIC int
-xfs_inobt_insert(
- struct xfs_mount *mp,
- struct xfs_trans *tp,
- struct xfs_buf *agbp,
- xfs_agino_t newino, /* start inode of record */
- xfs_agino_t count, /* inode count */
- xfs_inofree_t free, /* free mask */
- xfs_btnum_t btnum)
+xfs_inobt_update_insert(
+ struct xfs_mount *mp,
+ struct xfs_trans *tp,
+ struct xfs_buf *agbp,
+ struct xfs_inobt_rec_incore *rec, /* record to update/insert */
+ xfs_btnum_t btnum)
{
struct xfs_btree_cur *cur;
struct xfs_agi *agi = XFS_BUF_TO_AGI(agbp);
@@ -152,23 +152,25 @@ xfs_inobt_insert(
cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, btnum);
- error = xfs_inobt_lookup(cur, newino, XFS_LOOKUP_EQ, &i);
- if (error) {
- xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
- return error;
- }
- ASSERT(i == 0);
-
- error = xfs_inobt_insert_rec(cur, count, free, &i);
- if (error) {
- xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
- return error;
+ error = xfs_inobt_lookup(cur, rec->ir_startino, XFS_LOOKUP_EQ, &i);
+ if (i == 1) {
+ error = xfs_inobt_update(cur, rec);
+ if (error)
+ goto error;
+ } else {
+ error = xfs_inobt_insert_rec(cur, rec->ir_holemask,
+ rec->ir_freecount, rec->ir_free, &i);
+ if (error)
+ goto error;
+ ASSERT(i == 1);
}
- ASSERT(i == 1);
xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
-
return 0;
+
+error:
+ xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
+ return error;
}
/*
@@ -423,6 +425,10 @@ xfs_ialloc_ag_alloc(
xfs_agino_t newlen; /* new number of inodes */
int isaligned = 0; /* inode allocation at stripe unit */
/* boundary */
+ uint16_t allocmask = (uint16_t) -1; /* init. to full chunk */
+ struct xfs_inobt_rec_incore rec;
+ int offset;
+
struct xfs_perag *pag;
memset(&args, 0, sizeof(args));
@@ -538,6 +544,28 @@ xfs_ialloc_ag_alloc(
return error;
}
+ /*
+ * Finally, try a sparse allocation if the filesystem supports it.
+ */
+ if (xfs_sb_version_hassparseinodes(&args.mp->m_sb) &&
+ args.fsbno == NULLFSBLOCK) {
+ args.type = XFS_ALLOCTYPE_NEAR_BNO;
+ args.agbno = be32_to_cpu(agi->agi_root);
+ args.fsbno = XFS_AGB_TO_FSB(args.mp, agno, args.agbno);
+ args.alignment = xfs_ialloc_cluster_alignment(args.mp);
+
+ /* allocate sparse regions in cluster granularity */
+ args.minlen = xfs_ialloc_cluster_alignment(args.mp);
+ args.maxlen = args.minlen;
+
+ error = xfs_alloc_vextent(&args);
+ if (error)
+ return error;
+
+ newlen = args.len << args.mp->m_sb.sb_inopblog;
+ allocmask = (1 << (newlen / XFS_INODES_PER_SPCHUNK)) - 1;
+ }
+
if (args.fsbno == NULLFSBLOCK) {
*alloc = 0;
return 0;
@@ -572,14 +600,34 @@ xfs_ialloc_ag_alloc(
/*
* Insert records describing the new inode chunk into the btrees.
*/
- error = xfs_inobt_insert(args.mp, tp, agbp, newino, newlen,
- XFS_INOBT_ALL_FREE, XFS_BTNUM_INO);
+ error = xfs_spchunk_has_record(args.mp, tp, agbp, newino, newlen,
+ XFS_BTNUM_INO, &rec);
+ if (error)
+ return error;
+ if (rec.ir_startino == NULLAGINO) {
+ /* no existing record, set all fields */
+ rec.ir_startino = newino;
+ rec.ir_holemask = ~allocmask;
+ rec.ir_freecount = newlen;
+ rec.ir_free = XFS_INOBT_ALL_FREE;
+ } else {
+ /* we already have a record, update it */
+ offset = newino - rec.ir_startino;
+ ASSERT(offset % XFS_INODES_PER_SPCHUNK == 0);
+
+ allocmask <<= offset / XFS_INODES_PER_SPCHUNK;
+
+ rec.ir_freecount += newlen;
+ rec.ir_holemask &= ~allocmask;
+ }
+
+ error = xfs_inobt_update_insert(args.mp, tp, agbp, &rec, XFS_BTNUM_INO);
if (error)
return error;
if (xfs_sb_version_hasfinobt(&args.mp->m_sb)) {
- error = xfs_inobt_insert(args.mp, tp, agbp, newino, newlen,
- XFS_INOBT_ALL_FREE, XFS_BTNUM_FINO);
+ error = xfs_inobt_update_insert(args.mp, tp, agbp, &rec,
+ XFS_BTNUM_FINO);
if (error)
return error;
}
@@ -1644,7 +1692,8 @@ xfs_difree_finobt(
*/
XFS_WANT_CORRUPTED_GOTO(ibtrec->ir_freecount == 1, error);
- error = xfs_inobt_insert_rec(cur, ibtrec->ir_freecount,
+ error = xfs_inobt_insert_rec(cur, ibtrec->ir_holemask,
+ ibtrec->ir_freecount,
ibtrec->ir_free, &i);
if (error)
goto error;
--
1.8.3.1
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
next prev parent reply other threads:[~2014-07-24 14:54 UTC|newest]
Thread overview: 50+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-07-24 14:22 [PATCH RFC 00/18] xfs: sparse inode chunks Brian Foster
2014-07-24 14:22 ` [PATCH 01/18] xfs: refactor xfs_inobt_insert() to eliminate loop and support variable count Brian Foster
2014-07-24 22:10 ` Dave Chinner
2014-07-28 16:03 ` Brian Foster
2014-07-28 23:32 ` Dave Chinner
2014-07-29 14:43 ` Brian Foster
2014-07-24 14:22 ` [PATCH 02/18] xfs: pass xfs_mount directly to xfs_ialloc_cluster_alignment() Brian Foster
2014-07-24 14:22 ` [PATCH 03/18] xfs: define sparse inode chunks v5 sb feature bit and helper function Brian Foster
2014-07-24 17:08 ` Mark Tinguely
2014-07-24 17:37 ` Brian Foster
2014-07-24 18:38 ` Mark Tinguely
2014-07-24 19:38 ` Brian Foster
2014-07-24 23:35 ` Dave Chinner
2014-07-24 14:22 ` [PATCH 04/18] xfs: introduce inode record hole mask for sparse inode chunks Brian Foster
2014-07-24 22:14 ` Dave Chinner
2014-07-28 16:16 ` Brian Foster
2014-08-07 15:18 ` Brian Foster
2014-07-24 14:22 ` [PATCH 05/18] xfs: create macros/helpers for dealing with " Brian Foster
2014-07-24 22:13 ` Dave Chinner
2014-07-24 14:22 ` [PATCH 06/18] xfs: pass inode count through ordered icreate log item Brian Foster
2014-07-24 14:22 ` [PATCH 07/18] xfs: handle sparse inode chunks in icreate log recovery Brian Foster
2014-07-24 14:22 ` [PATCH 08/18] xfs: create helper to manage record overlap for sparse inode chunks Brian Foster
2014-07-24 22:41 ` Dave Chinner
2014-07-28 16:19 ` Brian Foster
2014-07-29 0:07 ` Dave Chinner
2014-07-29 15:10 ` Brian Foster
2014-07-24 14:22 ` Brian Foster [this message]
2014-07-24 14:23 ` [PATCH 10/18] xfs: set sparse inodes feature bit when a sparse chunk is allocated Brian Foster
2014-07-24 22:46 ` Dave Chinner
2014-07-28 16:23 ` Brian Foster
2014-07-24 14:23 ` [PATCH 11/18] xfs: reduce min. inode allocation space requirement for sparse inode chunks Brian Foster
2014-07-24 22:50 ` Dave Chinner
2014-07-24 14:23 ` [PATCH 12/18] xfs: helper to convert inobt record holemask to inode alloc. bitmap Brian Foster
2014-07-24 23:21 ` Dave Chinner
2014-07-24 14:23 ` [PATCH 13/18] xfs: filter out sparse regions from individual inode allocation Brian Foster
2014-07-24 14:23 ` [PATCH 14/18] xfs: update free inode record logic to support sparse inode records Brian Foster
2014-07-24 14:23 ` [PATCH 15/18] xfs: only free allocated regions of inode chunks Brian Foster
2014-07-24 23:24 ` Dave Chinner
2014-07-24 14:23 ` [PATCH 16/18] xfs: skip unallocated regions of inode chunks in xfs_ifree_cluster() Brian Foster
2014-07-24 14:23 ` [PATCH 17/18] xfs: use actual inode count for sparse records in bulkstat/inumbers Brian Foster
2014-07-24 23:29 ` Dave Chinner
2014-07-24 14:23 ` [PATCH 18/18] xfs: enable sparse inode chunks for v5 superblocks Brian Foster
2014-07-24 23:34 ` Dave Chinner
2014-07-24 16:28 ` [PATCH RFC 00/18] xfs: sparse inode chunks Brian Foster
2014-07-24 22:32 ` Dave Chinner
2014-07-25 16:30 ` Brian Foster
2014-07-26 0:03 ` Dave Chinner
2014-07-28 12:14 ` Brian Foster
2014-07-29 0:26 ` Dave Chinner
2014-07-29 15:25 ` Brian Foster
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=1406211788-63206-10-git-send-email-bfoster@redhat.com \
--to=bfoster@redhat.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox