public inbox for linux-xfs@vger.kernel.org
 help / color / mirror / Atom feed
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

  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