cluster-devel.redhat.com archive mirror
 help / color / mirror / Atom feed
From: Andrew Price <anprice@redhat.com>
To: cluster-devel.redhat.com
Subject: [Cluster-devel] [PATCH 14/19] libgfs2: Write file metadata sequentially
Date: Tue,  2 Sep 2014 13:07:31 +0100	[thread overview]
Message-ID: <1409659656-23051-15-git-send-email-anprice@redhat.com> (raw)
In-Reply-To: <1409659656-23051-1-git-send-email-anprice@redhat.com>

Until now the journal creation functions built up the height of the
journal metadata using incremental allocation and the build_height
function which grows a file naively. Two things are about to change:

1. We will guarantee that a journal will occupy a single extent.
2. Journals will be written out sequentially and will only required one
   write of the resource group header, before the journal is written.

Since we know the size of the extent and can predict the layout of the
journal's metadata tree, it is possible to generate and write the
metadata blocks in sequence. This patch adds an lgfs2_write_filemeta()
function which does just that.

Signed-off-by: Andrew Price <anprice@redhat.com>
---
 gfs2/libgfs2/fs_ops.c  | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++
 gfs2/libgfs2/libgfs2.h |  1 +
 2 files changed, 70 insertions(+)

diff --git a/gfs2/libgfs2/fs_ops.c b/gfs2/libgfs2/fs_ops.c
index 98db34d..9c9cc82 100644
--- a/gfs2/libgfs2/fs_ops.c
+++ b/gfs2/libgfs2/fs_ops.c
@@ -1412,6 +1412,75 @@ int init_dinode(struct gfs2_sbd *sdp, struct gfs2_buffer_head **bhp, struct gfs2
 	return __init_dinode(sdp, bhp, inum, mode, flags, parent, 0);
 }
 
+static void lgfs2_fill_indir(char *start, char *end, uint64_t ptr0, unsigned n, unsigned *p)
+{
+	char *bp;
+	memset(start, 0, end - start);
+	for (bp = start; bp < end && *p < n; bp += sizeof(uint64_t)) {
+		uint64_t pn = ptr0 + *p;
+		*(uint64_t *)bp = cpu_to_be64(pn);
+		(*p)++;
+	}
+}
+
+/**
+ * Calculate and write the indirect blocks for a single-extent file of a given
+ * size.
+ * ip: The inode for which to write indirect blocks, with fields already set
+ *     appropriately (see lgfs2_file_alloc).
+ * Returns 0 on success or non-zero with errno set on failure.
+ */
+int lgfs2_write_filemeta(struct gfs2_inode *ip)
+{
+	unsigned height = 0;
+	struct metapath mp;
+	struct gfs2_sbd *sdp = ip->i_sbd;
+	uint64_t dblocks = (ip->i_di.di_size + sdp->bsize - 1) / sdp->bsize;
+	uint64_t ptr0 = ip->i_di.di_num.no_addr + 1;
+	unsigned ptrs = 1;
+	struct gfs2_meta_header mh = {
+		.mh_magic = GFS2_MAGIC,
+		.mh_type = GFS2_METATYPE_IN,
+		.mh_format = GFS2_FORMAT_IN,
+	};
+	struct gfs2_buffer_head *bh = bget(sdp, ip->i_di.di_num.no_addr);
+	if (bh == NULL)
+		return 1;
+
+	/* Using find_metapath() to find the last data block in the file will
+	   effectively give a remainder for the number of pointers at each
+	   height. Just need to add 1 to convert ptr index to quantity later. */
+	find_metapath(ip, dblocks - 1, &mp);
+
+	for (height = 0; height < ip->i_di.di_height; height++) {
+		unsigned p;
+		/* The number of pointers in this height will be the number of
+		   full indirect blocks pointed to by the previous height
+		   multiplied by the pointer capacity of an indirect block,
+		   plus the remainder which find_metapath() gave us. */
+		ptrs = ((ptrs - 1) * sdp->sd_inptrs) + mp.mp_list[height] + 1;
+
+		for (p = 0; p < ptrs; bh->b_blocknr++) {
+			char *start = bh->b_data;
+			if (height == 0) {
+				start += sizeof(struct gfs2_dinode);
+				gfs2_dinode_out(&ip->i_di, bh);
+			} else {
+				start += sizeof(struct gfs2_meta_header);
+				gfs2_meta_header_out(&mh, bh->b_data);
+			}
+			lgfs2_fill_indir(start, bh->b_data + sdp->bsize, ptr0, ptrs, &p);
+			if(bwrite(bh)) {
+				free(bh);
+				return 1;
+			}
+		}
+		ptr0 += ptrs;
+	}
+	free(bh);
+	return 0;
+}
+
 static struct gfs2_inode *__createi(struct gfs2_inode *dip,
 				    const char *filename, unsigned int mode,
 				    uint32_t flags, int if_gfs1)
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index d683dc7..c7adbc1 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -500,6 +500,7 @@ extern void build_height(struct gfs2_inode *ip, int height);
 extern void unstuff_dinode(struct gfs2_inode *ip);
 extern unsigned int calc_tree_height(struct gfs2_inode *ip, uint64_t size);
 extern int write_journal(struct gfs2_inode *jnl, unsigned bsize, unsigned blocks);
+extern int lgfs2_write_filemeta(struct gfs2_inode *ip);
 
 /* gfs1.c - GFS1 backward compatibility structures and functions */
 
-- 
1.9.3



  parent reply	other threads:[~2014-09-02 12:07 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-09-02 12:07 [Cluster-devel] [PATCH 00/19] gfs2-utils: Introduce extent allocation and speed up journal creation Andrew Price
2014-09-02 12:07 ` [Cluster-devel] [PATCH 01/19] libgfs2: Keep a pointer to the sbd in lgfs2_rgrps_t Andrew Price
2014-09-02 12:07 ` [Cluster-devel] [PATCH 02/19] libgfs2: Move bitmap buffers inside struct gfs2_bitmap Andrew Price
2014-09-02 12:07 ` [Cluster-devel] [PATCH 03/19] libgfs2: Fix an impossible loop condition in gfs2_rgrp_read Andrew Price
2014-09-02 12:07 ` [Cluster-devel] [PATCH 04/19] libgfs2: Introduce struct lgfs2_rbm Andrew Price
2014-09-02 12:07 ` [Cluster-devel] [PATCH 05/19] libgfs2: Move struct _lgfs2_rgrps into rgrp.h Andrew Price
2014-09-02 12:07 ` [Cluster-devel] [PATCH 06/19] libgfs2: Add functions for finding free extents Andrew Price
2014-09-03 10:17   ` Steven Whitehouse
2014-09-03 12:13     ` Andrew Price
2014-09-03 12:24       ` Steven Whitehouse
2014-09-02 12:07 ` [Cluster-devel] [PATCH 07/19] tests: Add unit tests for the new extent search functions Andrew Price
2014-09-02 12:07 ` [Cluster-devel] [PATCH 08/19] libgfs2: Ignore an empty rgrp plan if a length is specified Andrew Price
2014-09-02 12:07 ` [Cluster-devel] [PATCH 09/19] libgfs2: Add back-pointer to rgrps in lgfs2_rgrp_t Andrew Price
2014-09-02 12:07 ` [Cluster-devel] [PATCH 10/19] libgfs2: Const-ify the parameters of print functions Andrew Price
2014-09-02 12:07 ` [Cluster-devel] [PATCH 11/19] libgfs2: Allow init_dinode to accept a preallocated bh Andrew Price
2014-09-02 12:07 ` [Cluster-devel] [PATCH 12/19] libgfs2: Add extent allocation functions Andrew Price
2014-09-02 12:07 ` [Cluster-devel] [PATCH 13/19] libgfs2: Add support for allocating entire rgrp headers Andrew Price
2014-09-02 12:07 ` Andrew Price [this message]
2014-09-02 12:07 ` [Cluster-devel] [PATCH 15/19] libgfs2: Fix alignment in lgfs2_rgsize_for_data Andrew Price
2014-09-02 12:07 ` [Cluster-devel] [PATCH 16/19] libgfs2: Handle non-zero bitmaps in lgfs2_rgrp_write Andrew Price
2014-09-02 12:07 ` [Cluster-devel] [PATCH 17/19] libgfs2: Add a speedier journal data block writing function Andrew Price
2014-09-02 12:07 ` [Cluster-devel] [PATCH 18/19] libgfs2: Create jindex directory separately from journals Andrew Price
2014-09-02 12:07 ` [Cluster-devel] [PATCH 19/19] mkfs.gfs2: Improve journal creation performance Andrew Price
2014-09-02 14:06 ` [Cluster-devel] [PATCH 00/19] gfs2-utils: Introduce extent allocation and speed up journal creation Bob Peterson
2014-09-03 10:20 ` Steven Whitehouse

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=1409659656-23051-15-git-send-email-anprice@redhat.com \
    --to=anprice@redhat.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;
as well as URLs for NNTP newsgroup(s).