* [Cluster-devel] [PATCH 00/14] gfs2_grow and libgfs2 rgrp API improvements
@ 2014-04-03 15:12 Andrew Price
2014-04-03 15:12 ` [Cluster-devel] [PATCH 01/14] mkfs.gfs2: Make dev a member of mkfs_opts Andrew Price
` (14 more replies)
0 siblings, 15 replies; 16+ messages in thread
From: Andrew Price @ 2014-04-03 15:12 UTC (permalink / raw)
To: cluster-devel.redhat.com
Hi,
This patch set aims to do three main things:
- Improve and simplify libgfs2's rgrp APIs, bringing them closer to being proper library code
- Improve gfs2_grow using the new rgrp APIs for rgrp alignment and size calculation, larger rgrps by default, etc.
- Fix problems in libgfs2 and the utils uncovered along the way
These patches take us closer to being able to hide the implementation of the rgrp lists (currently using osi_tree.h) within libgfs2 and decoupling so that many resource group sets (lgfs2_rgrps_t's) can be manipulated independently. Bookkeeping will eventually be done by the applications instead of keeping application-specific data in the gfs2_sbd structure so this takes us closer to being able to remove sbd.rgtree and sbd.rgcalc.
Although the net diff is 284 insertions, that will be offset significantly once the old rgrp functions in libgfs2 can be removed (when fsck, convert and edit no longer use them).
I've thrown various tests at this set and added one to the in-tree test suite. Static analysis with coverity shows 1 defect fixed and 0 added.
Please review,
Andy
Andrew Price (14):
mkfs.gfs2: Make dev a member of mkfs_opts
libgfs2: Add lgfs2_space_for_data()
libgfs2: Don't try to read more than IOV_MAX iovecs
mkfs.gfs2: Fix the resource group layout strategy, again
libgfs2: Don't call gfs2_blk2rgrpd in gfs2_set_bitmap
libgfs2: Add abstractions for rgrp tree traversal
libgfs2: Split out the rindex calculation from lgfs2_rgrp_append
libgfs2: Consolidate rgrp_tree and bitstruct allocations
libgfs2: Add a lgfs2_rindex_read_fd() function
libgfs2: Const-ify the 'ri' argument to gfs2_rindex_out
libgfs2: Fix off-by-one in lgfs2_rgrps_plan
libgfs2: Stick to the (rgrp) plan in lgfs2_rindex_entry_new
gfs2_grow: Migrate to the new resource group API
gfs2_grow: Add stripe alignment
gfs2/edit/hexedit.c | 2 +-
gfs2/fsck/metawalk.c | 2 +-
gfs2/fsck/pass5.c | 6 +-
gfs2/libgfs2/buf.c | 57 ++++---
gfs2/libgfs2/fs_bits.c | 5 +-
gfs2/libgfs2/fs_ops.c | 30 +++-
gfs2/libgfs2/libgfs2.h | 31 ++--
gfs2/libgfs2/ondisk.c | 4 +-
gfs2/libgfs2/rgrp.c | 422 +++++++++++++++++++++++++++++++++++--------------
gfs2/mkfs/gfs2_mkfs.h | 1 -
gfs2/mkfs/main_grow.c | 351 +++++++++++++++++++++-------------------
gfs2/mkfs/main_mkfs.c | 227 +++++++++++++++-----------
tests/mkfs.at | 4 +
13 files changed, 713 insertions(+), 429 deletions(-)
--
1.8.5.3
^ permalink raw reply [flat|nested] 16+ messages in thread
* [Cluster-devel] [PATCH 01/14] mkfs.gfs2: Make dev a member of mkfs_opts
2014-04-03 15:12 [Cluster-devel] [PATCH 00/14] gfs2_grow and libgfs2 rgrp API improvements Andrew Price
@ 2014-04-03 15:12 ` Andrew Price
2014-04-03 15:12 ` [Cluster-devel] [PATCH 02/14] libgfs2: Add lgfs2_space_for_data() Andrew Price
` (13 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Andrew Price @ 2014-04-03 15:12 UTC (permalink / raw)
To: cluster-devel.redhat.com
As most of the functions which accept a struct mkfs_dev* also require a
struct mkfs_opts* it makes sense to move the device path string into the
mkfs_dev and add a struct mkfs_dev member to the struct mkfs_opts.
Nothing much to see here, just refactoring.
Signed-off-by: Andrew Price <anprice@redhat.com>
---
gfs2/mkfs/main_mkfs.c | 125 +++++++++++++++++++++++++-------------------------
1 file changed, 62 insertions(+), 63 deletions(-)
diff --git a/gfs2/mkfs/main_mkfs.c b/gfs2/mkfs/main_mkfs.c
index e58de68..40f4766 100644
--- a/gfs2/mkfs/main_mkfs.c
+++ b/gfs2/mkfs/main_mkfs.c
@@ -96,6 +96,28 @@ static void print_ext_opts(void)
}
}
+/**
+ * Values probed by libblkid:
+ * alignment_offset: offset, in bytes, of the start of the dev from its natural alignment
+ * logical_sector_size: smallest addressable unit
+ * minimum_io_size: device's preferred unit of I/O. RAID stripe unit.
+ * optimal_io_size: biggest I/O we can submit without incurring a penalty. RAID stripe width.
+ * physical_sector_size: the smallest unit we can write atomically
+ */
+struct mkfs_dev {
+ int fd;
+ const char *path;
+ struct stat stat;
+ uint64_t size;
+ unsigned long alignment_offset;
+ unsigned long logical_sector_size;
+ unsigned long minimum_io_size;
+ unsigned long optimal_io_size;
+ unsigned long physical_sector_size;
+
+ unsigned int got_topol:1;
+};
+
struct mkfs_opts {
unsigned bsize;
unsigned qcsize;
@@ -107,7 +129,7 @@ struct mkfs_opts {
uint32_t journals;
const char *lockproto;
const char *locktable;
- const char *device;
+ struct mkfs_dev dev;
unsigned discard:1;
unsigned got_bsize:1;
@@ -130,27 +152,6 @@ struct mkfs_opts {
unsigned align:1;
};
-/**
- * Values probed by libblkid:
- * alignment_offset: offset, in bytes, of the start of the dev from its natural alignment
- * logical_sector_size: smallest addressable unit
- * minimum_io_size: device's preferred unit of I/O. RAID stripe unit.
- * optimal_io_size: biggest I/O we can submit without incurring a penalty. RAID stripe width.
- * physical_sector_size: the smallest unit we can write atomically
- */
-struct mkfs_dev {
- int fd;
- struct stat stat;
- uint64_t size;
- unsigned long alignment_offset;
- unsigned long logical_sector_size;
- unsigned long minimum_io_size;
- unsigned long optimal_io_size;
- unsigned long physical_sector_size;
-
- unsigned int got_topol:1;
-};
-
static void opts_init(struct mkfs_opts *opts)
{
memset(opts, 0, sizeof(*opts));
@@ -362,7 +363,7 @@ static void opts_get(int argc, char *argv[], struct mkfs_opts *opts)
if (strcmp(optarg, "gfs2") == 0)
continue;
if (!opts->got_device) {
- opts->device = optarg;
+ opts->dev.path = optarg;
opts->got_device = 1;
} else if (!opts->got_fssize && isdigit(optarg[0])) {
opts->fssize = atol(optarg);
@@ -457,10 +458,11 @@ static void are_you_sure(void)
free(line);
}
-static unsigned choose_blocksize(struct mkfs_opts *opts, const struct mkfs_dev *dev)
+static unsigned choose_blocksize(struct mkfs_opts *opts)
{
unsigned int x;
unsigned int bsize = opts->bsize;
+ struct mkfs_dev *dev = &opts->dev;
if (dev->got_topol && opts->debug) {
printf("alignment_offset: %lu\n", dev->alignment_offset);
@@ -536,15 +538,14 @@ static void opts_check(struct mkfs_opts *opts)
}
}
-static void print_results(struct gfs2_sb *sb, struct mkfs_dev *dev, struct mkfs_opts *opts,
- uint64_t rgrps, uint64_t fssize)
+static void print_results(struct gfs2_sb *sb, struct mkfs_opts *opts, uint64_t rgrps, uint64_t fssize)
{
- printf("%-27s%s\n", _("Device:"), opts->device);
+ printf("%-27s%s\n", _("Device:"), opts->dev.path);
printf("%-27s%u\n", _("Block size:"), sb->sb_bsize);
printf("%-27s%.2f %s (%"PRIu64" %s)\n", _("Device size:"),
/* Translators: "GB" here means "gigabytes" */
- (dev->size / ((float)(1 << 30))), _("GB"),
- (dev->size / sb->sb_bsize), _("blocks"));
+ (opts->dev.size / ((float)(1 << 30))), _("GB"),
+ (opts->dev.size / sb->sb_bsize), _("blocks"));
printf("%-27s%.2f %s (%"PRIu64" %s)\n", _("Filesystem size:"),
(fssize / ((float)(1 << 30)) * sb->sb_bsize), _("GB"), fssize, _("blocks"));
printf("%-27s%u\n", _("Journals:"), opts->journals);
@@ -580,7 +581,7 @@ static void warn_of_destruction(const char *path)
free(abspath);
}
-static lgfs2_rgrps_t rgs_init(struct mkfs_opts *opts, struct mkfs_dev *dev, struct gfs2_sbd *sdp)
+static lgfs2_rgrps_t rgs_init(struct mkfs_opts *opts, struct gfs2_sbd *sdp)
{
uint64_t rgsize = (opts->rgsize << 20) / sdp->bsize;
struct lgfs2_rgrp_align align = {.base = 0, .offset = 0};
@@ -600,10 +601,10 @@ static lgfs2_rgrps_t rgs_init(struct mkfs_opts *opts, struct mkfs_dev *dev, stru
align.offset = opts->sunit / sdp->bsize;
}
} else if (opts->align) {
- if ((dev->minimum_io_size > dev->physical_sector_size) &&
- (dev->optimal_io_size > dev->physical_sector_size)) {
- align.base = dev->optimal_io_size / sdp->bsize;
- align.offset = dev->minimum_io_size / sdp->bsize;
+ if ((opts->dev.minimum_io_size > opts->dev.physical_sector_size) &&
+ (opts->dev.optimal_io_size > opts->dev.physical_sector_size)) {
+ align.base = opts->dev.optimal_io_size / sdp->bsize;
+ align.offset = opts->dev.minimum_io_size / sdp->bsize;
}
}
@@ -624,7 +625,7 @@ static lgfs2_rgrps_t rgs_init(struct mkfs_opts *opts, struct mkfs_dev *dev, stru
return rgs;
}
-static uint64_t place_rgrps(struct gfs2_sbd *sdp, lgfs2_rgrps_t rgs, struct mkfs_opts *opts, const struct mkfs_dev *dev)
+static uint64_t place_rgrps(struct gfs2_sbd *sdp, lgfs2_rgrps_t rgs, struct mkfs_opts *opts)
{
int err = 0;
lgfs2_rgrp_t rg = NULL;
@@ -656,7 +657,7 @@ static uint64_t place_rgrps(struct gfs2_sbd *sdp, lgfs2_rgrps_t rgs, struct mkfs
return ri->ri_data0 + ri->ri_data;
}
-static void sbd_init(struct gfs2_sbd *sdp, struct mkfs_opts *opts, struct mkfs_dev *dev, unsigned bsize)
+static void sbd_init(struct gfs2_sbd *sdp, struct mkfs_opts *opts, unsigned bsize)
{
memset(sdp, 0, sizeof(struct gfs2_sbd));
sdp->time = time(NULL);
@@ -665,20 +666,20 @@ static void sbd_init(struct gfs2_sbd *sdp, struct mkfs_opts *opts, struct mkfs_d
sdp->qcsize = opts->qcsize;
sdp->jsize = opts->jsize;
sdp->md.journals = opts->journals;
- sdp->device_fd = dev->fd;
+ sdp->device_fd = opts->dev.fd;
sdp->bsize = bsize;
if (compute_constants(sdp)) {
perror(_("Failed to compute file system constants"));
exit(1);
}
- sdp->device.length = dev->size / sdp->bsize;
+ sdp->device.length = opts->dev.size / sdp->bsize;
if (opts->got_fssize) {
if (opts->fssize > sdp->device.length) {
fprintf(stderr, _("Specified size is bigger than the device."));
die("%s %.2f %s (%"PRIu64" %s)\n", _("Device size:"),
- dev->size / ((float)(1 << 30)), _("GB"),
- dev->size / sdp->bsize, _("blocks"));
+ opts->dev.size / ((float)(1 << 30)), _("GB"),
+ opts->dev.size / sdp->bsize, _("blocks"));
}
/* TODO: Check if the fssize is too small, somehow */
sdp->device.length = opts->fssize;
@@ -733,20 +734,19 @@ static int probe_contents(struct mkfs_dev *dev)
return 0;
}
-static void open_dev(const char *path, struct mkfs_dev *dev)
+static void open_dev(struct mkfs_dev *dev)
{
int error;
- memset(dev, 0, sizeof(*dev));
- dev->fd = open(path, O_RDWR | O_CLOEXEC);
+ dev->fd = open(dev->path, O_RDWR | O_CLOEXEC);
if (dev->fd < 0) {
- perror(path);
+ perror(dev->path);
exit(1);
}
error = fstat(dev->fd, &dev->stat);
if (error < 0) {
- perror(path);
+ perror(dev->path);
exit(1);
}
@@ -755,11 +755,11 @@ static void open_dev(const char *path, struct mkfs_dev *dev)
} else if (S_ISBLK(dev->stat.st_mode)) {
dev->size = lseek(dev->fd, 0, SEEK_END);
if (dev->size < 1) {
- fprintf(stderr, _("Device '%s' is too small\n"), path);
+ fprintf(stderr, _("Device '%s' is too small\n"), dev->path);
exit(1);
}
} else {
- fprintf(stderr, _("'%s' is not a block device or regular file\n"), path);
+ fprintf(stderr, _("'%s' is not a block device or regular file\n"), dev->path);
exit(1);
}
@@ -773,7 +773,6 @@ void main_mkfs(int argc, char *argv[])
struct gfs2_sbd sbd;
struct gfs2_sb sb;
struct mkfs_opts opts;
- struct mkfs_dev dev;
lgfs2_rgrps_t rgs;
int error;
unsigned bsize;
@@ -782,14 +781,14 @@ void main_mkfs(int argc, char *argv[])
opts_get(argc, argv, &opts);
opts_check(&opts);
- open_dev(opts.device, &dev);
- bsize = choose_blocksize(&opts, &dev);
+ open_dev(&opts.dev);
+ bsize = choose_blocksize(&opts);
- if (S_ISREG(dev.stat.st_mode)) {
+ if (S_ISREG(opts.dev.stat.st_mode)) {
opts.got_bsize = 1; /* Use default block size for regular files */
}
- sbd_init(&sbd, &opts, &dev, bsize);
+ sbd_init(&sbd, &opts, bsize);
lgfs2_sb_init(&sb, bsize);
if (opts.debug) {
printf(_("File system options:\n"));
@@ -804,16 +803,16 @@ void main_mkfs(int argc, char *argv[])
printf(" sunit = %lu\n", opts.sunit);
printf(" swidth = %lu\n", opts.swidth);
}
- rgs = rgs_init(&opts, &dev, &sbd);
- warn_of_destruction(opts.device);
+ rgs = rgs_init(&opts, &sbd);
+ warn_of_destruction(opts.dev.path);
if (opts.confirm && !opts.override)
are_you_sure();
- if (!S_ISREG(dev.stat.st_mode) && opts.discard)
- discard_blocks(dev.fd, dev.size, opts.debug);
+ if (!S_ISREG(opts.dev.stat.st_mode) && opts.discard)
+ discard_blocks(opts.dev.fd, opts.dev.size, opts.debug);
- sbd.fssize = place_rgrps(&sbd, rgs, &opts, &dev);
+ sbd.fssize = place_rgrps(&sbd, rgs, &opts);
if (sbd.fssize == 0) {
fprintf(stderr, _("Failed to build resource groups\n"));
exit(1);
@@ -872,24 +871,24 @@ void main_mkfs(int argc, char *argv[])
gfs2_rgrp_free(&sbd.rgtree);
- error = lgfs2_sb_write(&sb, dev.fd, sbd.bsize);
+ error = lgfs2_sb_write(&sb, opts.dev.fd, sbd.bsize);
if (error) {
perror(_("Failed to write superblock\n"));
exit(EXIT_FAILURE);
}
- error = fsync(dev.fd);
+ error = fsync(opts.dev.fd);
if (error){
- perror(opts.device);
+ perror(opts.dev.path);
exit(EXIT_FAILURE);
}
- error = close(dev.fd);
+ error = close(opts.dev.fd);
if (error){
- perror(opts.device);
+ perror(opts.dev.path);
exit(EXIT_FAILURE);
}
if (!opts.quiet)
- print_results(&sb, &dev, &opts, sbd.rgrps, sbd.fssize);
+ print_results(&sb, &opts, sbd.rgrps, sbd.fssize);
}
--
1.8.5.3
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [Cluster-devel] [PATCH 02/14] libgfs2: Add lgfs2_space_for_data()
2014-04-03 15:12 [Cluster-devel] [PATCH 00/14] gfs2_grow and libgfs2 rgrp API improvements Andrew Price
2014-04-03 15:12 ` [Cluster-devel] [PATCH 01/14] mkfs.gfs2: Make dev a member of mkfs_opts Andrew Price
@ 2014-04-03 15:12 ` Andrew Price
2014-04-03 15:12 ` [Cluster-devel] [PATCH 03/14] libgfs2: Don't try to read more than IOV_MAX iovecs Andrew Price
` (12 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Andrew Price @ 2014-04-03 15:12 UTC (permalink / raw)
To: cluster-devel.redhat.com
Add a function which calculates the total number of blocks required for
a file given the size of its contents.
Signed-off-by: Andrew Price <anprice@redhat.com>
---
gfs2/libgfs2/fs_ops.c | 18 ++++++++++++++++++
gfs2/libgfs2/libgfs2.h | 2 ++
2 files changed, 20 insertions(+)
diff --git a/gfs2/libgfs2/fs_ops.c b/gfs2/libgfs2/fs_ops.c
index 198f6eb..b95f2ed 100644
--- a/gfs2/libgfs2/fs_ops.c
+++ b/gfs2/libgfs2/fs_ops.c
@@ -273,6 +273,24 @@ void unstuff_dinode(struct gfs2_inode *ip)
ip->i_di.di_height = 1;
}
+/**
+ * Calculate the total number of blocks required by a file containing 'bytes' bytes of data.
+ */
+uint64_t lgfs2_space_for_data(const struct gfs2_sbd *sdp, const unsigned bsize, const uint64_t bytes)
+{
+ uint64_t blks = (bytes + bsize - 1) / bsize;
+ uint64_t ptrs = blks;
+
+ if (bytes <= bsize - sizeof(struct gfs2_dinode))
+ return 1;
+
+ while (ptrs > sdp->sd_diptrs) {
+ ptrs = (ptrs + sdp->sd_inptrs - 1) / sdp->sd_inptrs;
+ blks += ptrs;
+ }
+ return blks + 1;
+}
+
unsigned int calc_tree_height(struct gfs2_inode *ip, uint64_t size)
{
struct gfs2_sbd *sdp = ip->i_sbd;
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index 6248e4b..ce51e8c 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -450,6 +450,8 @@ extern void inode_put(struct gfs2_inode **ip);
extern uint64_t data_alloc(struct gfs2_inode *ip);
extern int lgfs2_meta_alloc(struct gfs2_inode *ip, uint64_t *blkno);
extern int lgfs2_dinode_alloc(struct gfs2_sbd *sdp, const uint64_t blksreq, uint64_t *blkno);
+extern uint64_t lgfs2_space_for_data(const struct gfs2_sbd *sdp, unsigned bsize, uint64_t bytes);
+
extern int gfs2_readi(struct gfs2_inode *ip, void *buf, uint64_t offset,
unsigned int size);
#define gfs2_writei(ip, buf, offset, size) \
--
1.8.5.3
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [Cluster-devel] [PATCH 03/14] libgfs2: Don't try to read more than IOV_MAX iovecs
2014-04-03 15:12 [Cluster-devel] [PATCH 00/14] gfs2_grow and libgfs2 rgrp API improvements Andrew Price
2014-04-03 15:12 ` [Cluster-devel] [PATCH 01/14] mkfs.gfs2: Make dev a member of mkfs_opts Andrew Price
2014-04-03 15:12 ` [Cluster-devel] [PATCH 02/14] libgfs2: Add lgfs2_space_for_data() Andrew Price
@ 2014-04-03 15:12 ` Andrew Price
2014-04-03 15:12 ` [Cluster-devel] [PATCH 04/14] mkfs.gfs2: Fix the resource group layout strategy, again Andrew Price
` (11 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Andrew Price @ 2014-04-03 15:12 UTC (permalink / raw)
To: cluster-devel.redhat.com
Reading large collections of blocks, as gfs2_rgrp_read may do with large
rgrps and small block sizes, can cause preadv() to fail with EINVAL in
breadm(). This patch splits large reads into IOV_MAX chunks to avoid
reads failing in that way. It also includes a test to exercise these
changes.
Signed-off-by: Andrew Price <anprice@redhat.com>
---
gfs2/libgfs2/buf.c | 57 ++++++++++++++++++++++++++++++++----------------------
tests/mkfs.at | 4 ++++
2 files changed, 38 insertions(+), 23 deletions(-)
diff --git a/gfs2/libgfs2/buf.c b/gfs2/libgfs2/buf.c
index 6fcdd17..92cd393 100644
--- a/gfs2/libgfs2/buf.c
+++ b/gfs2/libgfs2/buf.c
@@ -15,6 +15,14 @@
#include "libgfs2.h"
+#ifndef IOV_MAX
+ #ifdef UIO_MAXIOV
+ #define IOV_MAX UIO_MAXIOV
+ #else
+ #define IOV_MAX (1024)
+ #endif
+#endif
+
struct gfs2_buffer_head *bget(struct gfs2_sbd *sdp, uint64_t num)
{
struct gfs2_buffer_head *bh;
@@ -34,31 +42,34 @@ struct gfs2_buffer_head *bget(struct gfs2_sbd *sdp, uint64_t num)
int __breadm(struct gfs2_sbd *sdp, struct gfs2_buffer_head **bhs, size_t n,
uint64_t block, int line, const char *caller)
{
- struct iovec *iov = alloca(n * sizeof(struct iovec));
+ size_t v = (n < IOV_MAX) ? n : IOV_MAX;
+ struct iovec *iov = alloca(v * sizeof(struct iovec));
struct iovec *iovbase = iov;
- uint64_t b = block;
- size_t size = 0;
- size_t i;
- int ret;
-
- for (i = 0; i < n; i++) {
- bhs[i] = bget(sdp, b++);
- if (bhs[i] == NULL)
- return -1;
- *iov++ = bhs[i]->iov;
- size += bhs[i]->iov.iov_len;
+ size_t i = 0;
+
+ while (i < n) {
+ int j;
+ ssize_t ret;
+ ssize_t size = 0;
+
+ for (j = 0; (i + j < n) && (j < IOV_MAX); j++) {
+ bhs[i + j] = bget(sdp, block + i + j);
+ if (bhs[i + j] == NULL)
+ return -1;
+ iov[j] = bhs[i + j]->iov;
+ size += bhs[i + j]->iov.iov_len;
+ }
+
+ ret = preadv(sdp->device_fd, iovbase, j, (block + i) * sdp->bsize);
+ if (ret != size) {
+ fprintf(stderr, "bad read: %s from %s:%d: block %llu (0x%llx) "
+ "count: %d size: %zd ret: %zd\n", strerror(errno),
+ caller, line, (unsigned long long)block,
+ (unsigned long long)block, j, size, ret);
+ exit(-1);
+ }
+ i += j;
}
-
- ret = preadv(sdp->device_fd, iovbase, n, block * sdp->bsize);
-
- if (ret != size) {
- fprintf(stderr, "bad read: %s from %s:%d: block "
- "%llu (0x%llx)\n", strerror(errno),
- caller, line, (unsigned long long)block,
- (unsigned long long)block);
- exit(-1);
- }
-
return 0;
}
diff --git a/tests/mkfs.at b/tests/mkfs.at
index 2616109..ff99bb1 100644
--- a/tests/mkfs.at
+++ b/tests/mkfs.at
@@ -54,6 +54,10 @@ AT_SETUP([Min. resource group size])
GFS_FSCK_CHECK([$GFS_MKFS -p lock_nolock -r 32 $GFS_TGT])
AT_CLEANUP
+AT_SETUP([Max. resource group size, min. block size])
+GFS_FSCK_CHECK([$GFS_MKFS -p lock_nolock -r 2048 -b 512 $GFS_TGT])
+AT_CLEANUP
+
AT_SETUP([Max. journal size])
GFS_FSCK_CHECK([$GFS_MKFS -p lock_nolock -J 1024 $GFS_TGT])
AT_CLEANUP
--
1.8.5.3
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [Cluster-devel] [PATCH 04/14] mkfs.gfs2: Fix the resource group layout strategy, again
2014-04-03 15:12 [Cluster-devel] [PATCH 00/14] gfs2_grow and libgfs2 rgrp API improvements Andrew Price
` (2 preceding siblings ...)
2014-04-03 15:12 ` [Cluster-devel] [PATCH 03/14] libgfs2: Don't try to read more than IOV_MAX iovecs Andrew Price
@ 2014-04-03 15:12 ` Andrew Price
2014-04-03 15:12 ` [Cluster-devel] [PATCH 05/14] libgfs2: Don't call gfs2_blk2rgrpd in gfs2_set_bitmap Andrew Price
` (10 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Andrew Price @ 2014-04-03 15:12 UTC (permalink / raw)
To: cluster-devel.redhat.com
The previous attempt at improving the resource group layout and
alignment fell somewhat short of the mark and left some issues, such as
the possibility of leaving a small resource group at the end of the
device which gfs2_grow could wrongly use as the file system's resource
group size.
The core of this patch is the new lgfs2_rgrps_plan() function which
calculates a sensible resource group size given a target maximum (which
we now default to 2GB instead of 256MB). In order to avoid leaving a gap
or a small rgrp at the end of the device, we adjust the rgrp length down
until a further adjustment would leave a gap, then apply a constant
adjustment to the size of a subset of the resource groups.
The rest of the patch aims to clean up libgfs2's resource group API and
give more control to the application rather than storing a lot of the
resource group layout parameters in the lgfs2_rgrps_t. This should make
it easier to use the same functions in gfs2_grow, fsck.gfs2 and any
other tools which might need to manipulate resource groups.
Signed-off-by: Andrew Price <anprice@redhat.com>
---
gfs2/libgfs2/libgfs2.h | 16 ++--
gfs2/libgfs2/rgrp.c | 206 ++++++++++++++++++++++++++++++++++---------------
gfs2/mkfs/main_mkfs.c | 104 +++++++++++++++++--------
3 files changed, 218 insertions(+), 108 deletions(-)
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index ce51e8c..24947c2 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -186,19 +186,16 @@ struct rgrp_tree {
struct gfs2_buffer_head **bh;
};
-struct lgfs2_rgrp_align {
- uint64_t base;
- uint64_t offset;
-};
-
typedef struct rgrp_tree *lgfs2_rgrp_t;
typedef struct _lgfs2_rgrps *lgfs2_rgrps_t;
-extern lgfs2_rgrps_t lgfs2_rgrps_init(unsigned bsize, uint64_t start, uint64_t devlen, uint32_t rglen, struct lgfs2_rgrp_align *al);
+extern lgfs2_rgrps_t lgfs2_rgrps_init(unsigned bsize, uint64_t devlen, uint64_t align, uint64_t offset);
+extern uint64_t lgfs2_rgrp_align_addr(const lgfs2_rgrps_t rgs, uint64_t addr);
+extern uint32_t lgfs2_rgrp_align_len(const lgfs2_rgrps_t rgs, uint32_t len);
extern unsigned lgfs2_rgsize_for_data(uint64_t blksreq, unsigned bsize);
-extern lgfs2_rgrp_t lgfs2_rgrp_append(lgfs2_rgrps_t rgs, uint32_t rglen, int expand);
-extern int lgfs2_rgrp_write(int fd, lgfs2_rgrp_t rg, unsigned bsize);
-extern int lgfs2_rgrps_end(lgfs2_rgrps_t rgs);
+extern uint32_t lgfs2_rgrps_plan(const lgfs2_rgrps_t rgs, uint64_t space, uint32_t tgtsize);
+extern lgfs2_rgrp_t lgfs2_rgrp_append(lgfs2_rgrps_t rgs, uint64_t addr, uint32_t rglen, uint64_t *nextaddr);
+extern int lgfs2_rgrp_write(lgfs2_rgrps_t rgs, int fd, lgfs2_rgrp_t rg);
extern struct gfs2_rindex *lgfs2_rgrp_index(lgfs2_rgrp_t rg);
// Temporary function to aid API migration
extern struct osi_node *lgfs2_rgrps_root(lgfs2_rgrps_t rgs) __attribute__((deprecated));
@@ -350,7 +347,6 @@ struct metapath {
#define GFS2_EXP_MIN_RGSIZE (1)
#define GFS2_MIN_RGSIZE (32)
-/* Look at this! Why can't we go bigger than 2GB? */
#define GFS2_MAX_RGSIZE (2048)
/* meta.c */
diff --git a/gfs2/libgfs2/rgrp.c b/gfs2/libgfs2/rgrp.c
index 0752772..1242385 100644
--- a/gfs2/libgfs2/rgrp.c
+++ b/gfs2/libgfs2/rgrp.c
@@ -223,6 +223,11 @@ void gfs2_rgrp_free(struct osi_root *rgrp_tree)
}
}
+struct rgplan {
+ uint32_t num;
+ uint32_t len;
+};
+
/**
* This structure is defined in libgfs2.h as an opaque type. It stores the
* constants and context required for creating resource groups from any point
@@ -230,17 +235,11 @@ void gfs2_rgrp_free(struct osi_root *rgrp_tree)
*/
struct _lgfs2_rgrps {
struct osi_root root;
- uint64_t nextaddr;
+ struct rgplan plan[2];
unsigned bsize;
unsigned long align;
unsigned long align_off;
- unsigned long curr_offset;
- uint64_t maxrgsz;
- uint64_t minrgsz;
uint64_t devlen;
- uint64_t count;
- uint64_t blks_total;
- uint32_t rgsize;
};
static uint64_t align_block(const uint64_t base, const uint64_t align)
@@ -251,29 +250,121 @@ static uint64_t align_block(const uint64_t base, const uint64_t align)
}
/**
+ * Calculate the aligned block address of a resource group.
+ * rgs: The resource groups handle
+ * base: The base address of the first resource group address, in blocks
+ * Returns the aligned address of the first resource group.
+ */
+uint64_t lgfs2_rgrp_align_addr(const lgfs2_rgrps_t rgs, uint64_t addr)
+{
+ return align_block(addr, rgs->align);
+}
+
+/**
+ * Calculate the aligned relative address of the next resource group (and thus
+ * the aligned length of this one).
+ * rgs: The resource groups handle
+ * base: The base length of the current resource group, in blocks
+ * Returns the length of the resource group (the aligned relative address of
+ * the next one)
+ */
+uint32_t lgfs2_rgrp_align_len(const lgfs2_rgrps_t rgs, uint32_t len)
+{
+ return align_block(len, rgs->align) + rgs->align_off;
+}
+
+/**
+ * Plan the sizes of resource groups for remaining free space, based on a
+ * target maximum size. In order to make best use of the space while keeping
+ * the resource groups aligned appropriately we need to either reduce the
+ * length of every resource group or of a subset of the resource groups, so
+ * we're left with either one or two resource group sizes. We keep track of
+ * both of these and the numbers of each size of resource group inside the
+ * resource groups descriptor.
+ * rgs: The resource groups descriptor
+ * space: The number of remaining blocks to be allocated
+ * tgtsize: The target resource group size in blocks
+ * Returns the larger of the calculated resource group sizes or 0 if the
+ * smaller would be less than GFS2_MIN_RGSIZE.
+ */
+uint32_t lgfs2_rgrps_plan(const lgfs2_rgrps_t rgs, uint64_t space, uint32_t tgtsize)
+{
+ uint32_t maxlen = (GFS2_MAX_RGSIZE << 20) / rgs->bsize;
+ uint32_t minlen = (GFS2_MIN_RGSIZE << 20) / rgs->bsize;
+
+ /* Apps should already have checked that the rg size is <=
+ GFS2_MAX_RGSIZE but just in case alignment pushes it over we clamp
+ it back down while calculating the initial rgrp length. */
+ do {
+ rgs->plan[0].len = lgfs2_rgrp_align_len(rgs, tgtsize);
+ tgtsize -= (rgs->align + 1);
+ } while (rgs->plan[0].len > maxlen);
+
+ rgs->plan[0].num = space / rgs->plan[0].len;
+
+ if ((space - (rgs->plan[0].num * rgs->plan[0].len)) > rgs->align) {
+ unsigned adj = (rgs->align > 0) ? rgs->align : 1;
+
+ /* Spread the adjustment required to fit a new rgrp at the end
+ over all of the rgrps so that we don't end with a single
+ tiny one. */
+ while (((rgs->plan[0].len - adj) * (rgs->plan[0].num + 1)) >= space)
+ rgs->plan[0].len -= adj;
+
+ /* We've adjusted the size of the rgrps down as far as we can
+ without leaving a large gap at the end of the device now,
+ but we still need to reduce the size of some rgrps in order
+ to make everything fit, so we use the second rgplan to
+ specify a second length for a subset of the resource groups.
+ If plan[0].len already divides the space with no remainder,
+ plan[1].num will stay 0 and it won't be used. */
+ rgs->plan[1].len = rgs->plan[0].len - adj;
+ rgs->plan[1].num = 0;
+
+ while (((rgs->plan[0].len * rgs->plan[0].num) +
+ (rgs->plan[1].len * rgs->plan[1].num)) > space) {
+ /* Total number of rgrps stays constant now. We just
+ need to shift some weight around */
+ rgs->plan[0].num--;
+ rgs->plan[1].num++;
+ }
+ }
+
+ /* Once we've reached this point,
+ (plan[0].num * plan[0].len) + (plan[1].num * plan[1].len)
+ will be less than one adjustment smaller than 'space'. */
+
+ if (rgs->plan[0].len < minlen)
+ return 0;
+
+ return rgs->plan[0].len;
+}
+
+/**
* Create and initialise an empty set of resource groups
* bsize: The block size of the fs
- * start: The block address of the first resource group
* devlen: The length of the device, in fs blocks
- * rglen: Default rg size, in blocks
- * al: The required alignment of the resource groups
+ * align: The required stripe alignment of the resource groups. Must be a multiple of 'offset'.
+ * offset: The required stripe offset of the resource groups
* Returns an initialised lgfs2_rgrps_t or NULL if unsuccessful with errno set
*/
-lgfs2_rgrps_t lgfs2_rgrps_init(unsigned bsize, uint64_t start, uint64_t devlen, uint32_t rglen, struct lgfs2_rgrp_align *al)
+lgfs2_rgrps_t lgfs2_rgrps_init(unsigned bsize, uint64_t devlen, uint64_t align, uint64_t offset)
{
- lgfs2_rgrps_t rgs = calloc(1, sizeof(*rgs));
+ lgfs2_rgrps_t rgs;
+
+ errno = EINVAL;
+ if (offset != 0 && (align % offset) != 0)
+ return NULL;
+
+ rgs = calloc(1, sizeof(*rgs));
if (rgs == NULL)
return NULL;
rgs->bsize = bsize;
- rgs->maxrgsz = (GFS2_MAX_RGSIZE << 20) / bsize;
- rgs->minrgsz = (GFS2_MIN_RGSIZE << 20) / bsize;
- rgs->rgsize = rglen;
rgs->devlen = devlen;
- rgs->align = al->base;
- rgs->align_off = al->offset;
+ rgs->align = align;
+ rgs->align_off = offset;
memset(&rgs->root, 0, sizeof(rgs->root));
- rgs->nextaddr = align_block(start, rgs->align);
return rgs;
}
@@ -287,14 +378,6 @@ struct gfs2_rindex *lgfs2_rgrp_index(lgfs2_rgrp_t rg)
}
/**
- * Return non-zero if there is space left for more resource groups or zero if not
- */
-int lgfs2_rgrps_end(lgfs2_rgrps_t rgs)
-{
- return (rgs->nextaddr == 0);
-}
-
-/**
* Returns the total resource group size, in blocks, required to give blksreq data blocks
*/
unsigned lgfs2_rgsize_for_data(uint64_t blksreq, unsigned bsize)
@@ -316,43 +399,38 @@ struct osi_node *lgfs2_rgrps_root(lgfs2_rgrps_t rgs)
/**
* Create a new resource group after the last resource group in a set.
* rgs: The set of resource groups
- * rglen: The required length of the resource group. If its is 0 the default rgsize
- * passed to lgfs2_rgrps_init() is used.
- * expand: Whether to expand the resource group when alignment would leave a gap.
- * Returns the new resource group on success or NULL on failure.
+ * addr: The address at which to place this resource group
+ * rglen: The required length of the resource group, in fs blocks.
+ * Returns the new resource group on success or NULL on failure with errno set.
+ * If errno is ENOSPC on a NULL return from this function, it could be
+ * interpreted as 'finished' unless you expected there to be enough space on
+ * the device for the resource group.
*/
-lgfs2_rgrp_t lgfs2_rgrp_append(lgfs2_rgrps_t rgs, uint32_t rglen, int expand)
+lgfs2_rgrp_t lgfs2_rgrp_append(lgfs2_rgrps_t rgs, uint64_t addr, uint32_t rglen, uint64_t *nextaddr)
{
int err = 0;
- lgfs2_rgrp_t rg = rgrp_insert(&rgs->root, rgs->nextaddr);
- if (rg == NULL)
- return NULL;
-
- rgs->curr_offset += rgs->align_off;
- if (rgs->curr_offset >= rgs->align)
- rgs->curr_offset = 0;
-
- if (rgs->rgsize > rglen)
- rglen = rgs->rgsize;
-
- rgs->nextaddr = align_block(rg->ri.ri_addr + rgs->rgsize, rgs->align) + rgs->curr_offset;
- /* Use up gap left by alignment if possible */
- if (expand && ((rgs->nextaddr - rg->ri.ri_addr) <= rgs->maxrgsz))
- rglen = rgs->nextaddr - rg->ri.ri_addr;
-
- if ((rgs->nextaddr + rgs->rgsize) > rgs->devlen) {
- /* Squeeze the last 1 or 2 rgs into the remaining space */
- if ((rgs->nextaddr < rgs->devlen) && ((rgs->devlen - rgs->nextaddr) >= rgs->minrgsz)) {
- rgs->rgsize = rgs->devlen - rgs->nextaddr;
+ lgfs2_rgrp_t rg;
+
+ if (rglen == 0) {
+ if (rgs->plan[0].num > 0) {
+ rglen = rgs->plan[0].len;
+ rgs->plan[0].num--;
+ } else if (rgs->plan[1].num > 0) {
+ rglen = rgs->plan[1].len;
+ rgs->plan[1].num--;
} else {
- if (rgs->devlen - rg->ri.ri_addr <= rgs->maxrgsz)
- rglen = rgs->devlen - rg->ri.ri_addr;
- else
- rglen = rgs->maxrgsz;
- /* This is the last rg */
- rgs->nextaddr = 0;
+ errno = ENOSPC;
+ return NULL;
}
}
+ if (addr + rglen > rgs->devlen) {
+ errno = ENOSPC;
+ return NULL;
+ }
+
+ rg = rgrp_insert(&rgs->root, addr);
+ if (rg == NULL)
+ return NULL;
rg->ri.ri_length = rgblocks2bitblocks(rgs->bsize, rglen, &rg->ri.ri_data);
rg->ri.ri_data0 = rg->ri.ri_addr + rg->ri.ri_length;
@@ -361,12 +439,12 @@ lgfs2_rgrp_t lgfs2_rgrp_append(lgfs2_rgrps_t rgs, uint32_t rglen, int expand)
rg->rg.rg_header.mh_type = GFS2_METATYPE_RG;
rg->rg.rg_header.mh_format = GFS2_FORMAT_RG;
rg->rg.rg_free = rg->ri.ri_data;
-
err = gfs2_compute_bitstructs(rgs->bsize, rg);
if (err != 0)
return NULL;
- rgs->blks_total += rg->ri.ri_data;
- rgs->count++;
+
+ if (nextaddr)
+ *nextaddr = rg->ri.ri_addr + rglen;
return rg;
}
@@ -374,10 +452,10 @@ lgfs2_rgrp_t lgfs2_rgrp_append(lgfs2_rgrps_t rgs, uint32_t rglen, int expand)
* Write a resource group to a file descriptor.
* Returns 0 on success or non-zero on failure with errno set
*/
-int lgfs2_rgrp_write(int fd, lgfs2_rgrp_t rg, unsigned bsize)
+int lgfs2_rgrp_write(const lgfs2_rgrps_t rgs, int fd, const lgfs2_rgrp_t rg)
{
ssize_t ret = 0;
- size_t len = rg->ri.ri_length * bsize;
+ size_t len = rg->ri.ri_length * rgs->bsize;
unsigned int i;
const struct gfs2_meta_header bmh = {
.mh_magic = GFS2_MAGIC,
@@ -390,9 +468,9 @@ int lgfs2_rgrp_write(int fd, lgfs2_rgrp_t rg, unsigned bsize)
gfs2_rgrp_out(&rg->rg, buff);
for (i = 1; i < rg->ri.ri_length; i++)
- gfs2_meta_header_out(&bmh, buff + (i * bsize));
+ gfs2_meta_header_out(&bmh, buff + (i * rgs->bsize));
- ret = pwrite(fd, buff, len, rg->ri.ri_addr * bsize);
+ ret = pwrite(fd, buff, len, rg->ri.ri_addr * rgs->bsize);
if (ret != len) {
free(buff);
return -1;
diff --git a/gfs2/mkfs/main_mkfs.c b/gfs2/mkfs/main_mkfs.c
index 40f4766..ae82c9f 100644
--- a/gfs2/mkfs/main_mkfs.c
+++ b/gfs2/mkfs/main_mkfs.c
@@ -160,7 +160,7 @@ static void opts_init(struct mkfs_opts *opts)
opts->bsize = GFS2_DEFAULT_BSIZE;
opts->jsize = GFS2_DEFAULT_JSIZE;
opts->qcsize = GFS2_DEFAULT_QCSIZE;
- opts->rgsize = GFS2_DEFAULT_RGSIZE;
+ opts->rgsize = GFS2_MAX_RGSIZE;
opts->lockproto = "lock_dlm";
opts->locktable = "";
opts->confirm = 1;
@@ -583,9 +583,9 @@ static void warn_of_destruction(const char *path)
static lgfs2_rgrps_t rgs_init(struct mkfs_opts *opts, struct gfs2_sbd *sdp)
{
- uint64_t rgsize = (opts->rgsize << 20) / sdp->bsize;
- struct lgfs2_rgrp_align align = {.base = 0, .offset = 0};
lgfs2_rgrps_t rgs;
+ uint64_t al_base = 0;
+ uint64_t al_off = 0;
if (opts->align && opts->got_sunit) {
if ((opts->sunit % sdp->bsize) != 0) {
@@ -597,18 +597,18 @@ static lgfs2_rgrps_t rgs_init(struct mkfs_opts *opts, struct gfs2_sbd *sdp)
opts->swidth, opts->sunit);
exit(1);
} else {
- align.base = opts->swidth / sdp->bsize;
- align.offset = opts->sunit / sdp->bsize;
+ al_base = opts->swidth / sdp->bsize;
+ al_off = opts->sunit / sdp->bsize;
}
} else if (opts->align) {
if ((opts->dev.minimum_io_size > opts->dev.physical_sector_size) &&
(opts->dev.optimal_io_size > opts->dev.physical_sector_size)) {
- align.base = opts->dev.optimal_io_size / sdp->bsize;
- align.offset = opts->dev.minimum_io_size / sdp->bsize;
+ al_base = opts->dev.optimal_io_size / sdp->bsize;
+ al_off = opts->dev.minimum_io_size / sdp->bsize;
}
}
- rgs = lgfs2_rgrps_init(sdp->bsize, sdp->sb_addr + 1, sdp->device.length, rgsize, &align);
+ rgs = lgfs2_rgrps_init(sdp->bsize, sdp->device.length, al_base, al_off);
if (rgs == NULL) {
perror(_("Could not initialise resource groups"));
exit(-1);
@@ -617,7 +617,7 @@ static lgfs2_rgrps_t rgs_init(struct mkfs_opts *opts, struct gfs2_sbd *sdp)
if (opts->debug) {
printf(" rgrp align = ");
if (opts->align)
- printf("%lu+%lu blocks\n", align.base, align.offset);
+ printf("%lu+%lu blocks\n", al_base, al_off);
else
printf("(disabled)\n");
}
@@ -625,36 +625,71 @@ static lgfs2_rgrps_t rgs_init(struct mkfs_opts *opts, struct gfs2_sbd *sdp)
return rgs;
}
-static uint64_t place_rgrps(struct gfs2_sbd *sdp, lgfs2_rgrps_t rgs, struct mkfs_opts *opts)
+static int place_rgrp(struct gfs2_sbd *sdp, lgfs2_rgrps_t rgs, uint64_t rgaddr, uint32_t len, uint64_t *next)
{
int err = 0;
lgfs2_rgrp_t rg = NULL;
struct gfs2_rindex *ri = NULL;
- while (!lgfs2_rgrps_end(rgs)) {
- rg = lgfs2_rgrp_append(rgs, 0, !opts->got_rgsize);
- if (rg == NULL) {
- perror(_("Failed to create resource group"));
- return 0;
- }
- err = lgfs2_rgrp_write(sdp->device_fd, rg, sdp->bsize);
- if (err != 0) {
- perror(_("Failed to write resource group"));
- return 0;
- }
- ri = lgfs2_rgrp_index(rg);
- if (opts->debug) {
- gfs2_rindex_print(ri);
- printf("\n");
- }
- sdp->blks_total += ri->ri_data;
- sdp->rgrps++;
+ rg = lgfs2_rgrp_append(rgs, rgaddr, len, next);
+ if (rg == NULL) {
+ if (errno == ENOSPC)
+ return 1;
+ perror(_("Failed to create resource group"));
+ return -1;
+ }
+ err = lgfs2_rgrp_write(rgs, sdp->device_fd, rg);
+ if (err != 0) {
+ perror(_("Failed to write resource group"));
+ return -1;
+ }
+ ri = lgfs2_rgrp_index(rg);
+ if (sdp->debug) {
+ gfs2_rindex_print(ri);
+ printf("\n");
}
+ sdp->blks_total += ri->ri_data;
+ sdp->fssize = ri->ri_data0 + ri->ri_data;
+ sdp->rgrps++;
+ return 0;
+}
- if (ri == NULL)
- return 0;
- else
- return ri->ri_data0 + ri->ri_data;
+static int place_rgrps(struct gfs2_sbd *sdp, lgfs2_rgrps_t rgs, struct mkfs_opts *opts)
+{
+ uint64_t jfsize = lgfs2_space_for_data(sdp, sdp->bsize, opts->jsize << 20);
+ uint32_t jrgsize = lgfs2_rgsize_for_data(jfsize, sdp->bsize);
+ uint64_t rgaddr = lgfs2_rgrp_align_addr(rgs, sdp->sb_addr + 1);
+ uint32_t rgsize = lgfs2_rgrps_plan(rgs, sdp->device.length - rgaddr, ((opts->rgsize << 20) / sdp->bsize));
+ unsigned j;
+
+ if (rgsize >= jrgsize)
+ jrgsize = rgsize;
+
+ if (rgsize < ((GFS2_MIN_RGSIZE << 20) / sdp->bsize)) {
+ fprintf(stderr, _("Resource group size is too small\n"));
+ return -1;
+ } else if (rgsize < ((GFS2_DEFAULT_RGSIZE << 20) / sdp->bsize)) {
+ fprintf(stderr, _("Warning: small resource group size could impact performance\n"));
+ }
+
+ for (j = 0; j < opts->journals; j++) {
+ int result = place_rgrp(sdp, rgs, rgaddr, jrgsize, NULL);
+ if (result != 0)
+ return result;
+ rgaddr = rgaddr + jrgsize;
+ }
+
+ if (rgsize != jrgsize)
+ lgfs2_rgrps_plan(rgs, sdp->device.length - rgaddr, ((opts->rgsize << 20) / sdp->bsize));
+
+ while (1) {
+ int result = place_rgrp(sdp, rgs, rgaddr, 0, &rgaddr);
+ if (result < 0)
+ return result;
+ if (result > 0)
+ break; /* Done */
+ }
+ return 0;
}
static void sbd_init(struct gfs2_sbd *sdp, struct mkfs_opts *opts, unsigned bsize)
@@ -668,6 +703,7 @@ static void sbd_init(struct gfs2_sbd *sdp, struct mkfs_opts *opts, unsigned bsiz
sdp->md.journals = opts->journals;
sdp->device_fd = opts->dev.fd;
sdp->bsize = bsize;
+ sdp->debug = opts->debug;
if (compute_constants(sdp)) {
perror(_("Failed to compute file system constants"));
@@ -812,8 +848,8 @@ void main_mkfs(int argc, char *argv[])
if (!S_ISREG(opts.dev.stat.st_mode) && opts.discard)
discard_blocks(opts.dev.fd, opts.dev.size, opts.debug);
- sbd.fssize = place_rgrps(&sbd, rgs, &opts);
- if (sbd.fssize == 0) {
+ error = place_rgrps(&sbd, rgs, &opts);
+ if (error) {
fprintf(stderr, _("Failed to build resource groups\n"));
exit(1);
}
--
1.8.5.3
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [Cluster-devel] [PATCH 05/14] libgfs2: Don't call gfs2_blk2rgrpd in gfs2_set_bitmap
2014-04-03 15:12 [Cluster-devel] [PATCH 00/14] gfs2_grow and libgfs2 rgrp API improvements Andrew Price
` (3 preceding siblings ...)
2014-04-03 15:12 ` [Cluster-devel] [PATCH 04/14] mkfs.gfs2: Fix the resource group layout strategy, again Andrew Price
@ 2014-04-03 15:12 ` Andrew Price
2014-04-03 15:12 ` [Cluster-devel] [PATCH 06/14] libgfs2: Add abstractions for rgrp tree traversal Andrew Price
` (9 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Andrew Price @ 2014-04-03 15:12 UTC (permalink / raw)
To: cluster-devel.redhat.com
gfs2_set_bitmap was calling gfs2_blk2rgrpd even when callers already
have the resource group to hand. This changes that function to accept
the resource group instead and calls to gfs2_blk2rgrpd have been moved
outside.
Signed-off-by: Andrew Price <anprice@redhat.com>
---
gfs2/edit/hexedit.c | 2 +-
gfs2/fsck/metawalk.c | 2 +-
gfs2/fsck/pass5.c | 6 ++++--
gfs2/libgfs2/fs_bits.c | 5 +----
gfs2/libgfs2/fs_ops.c | 12 +++++-------
gfs2/libgfs2/libgfs2.h | 2 +-
6 files changed, 13 insertions(+), 16 deletions(-)
diff --git a/gfs2/edit/hexedit.c b/gfs2/edit/hexedit.c
index bc3ca35..53a816d 100644
--- a/gfs2/edit/hexedit.c
+++ b/gfs2/edit/hexedit.c
@@ -2045,7 +2045,7 @@ static void find_change_block_alloc(int *newval)
if (rgd) {
gfs2_rgrp_read(&sbd, rgd);
if (newval) {
- if (gfs2_set_bitmap(&sbd, ablock, *newval))
+ if (gfs2_set_bitmap(rgd, ablock, *newval))
printf("-1 (block invalid or part of an rgrp).\n");
else
printf("%d\n", *newval);
diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c
index 15cba56..594fbfa 100644
--- a/gfs2/fsck/metawalk.c
+++ b/gfs2/fsck/metawalk.c
@@ -73,7 +73,7 @@ int check_n_fix_bitmap(struct gfs2_sbd *sdp, uint64_t blk, int error_on_dinode,
subtract to the free space. If the type changed
from dinode to data or data to dinode, no change in
free space. */
- gfs2_set_bitmap(sdp, blk, new_bitmap_state);
+ gfs2_set_bitmap(rgd, blk, new_bitmap_state);
if (new_bitmap_state == GFS2_BLKST_FREE) {
/* If we're freeing a dinode, get rid of
the hash table entries for it. */
diff --git a/gfs2/fsck/pass5.c b/gfs2/fsck/pass5.c
index 92861a1..49ab682 100644
--- a/gfs2/fsck/pass5.c
+++ b/gfs2/fsck/pass5.c
@@ -148,7 +148,8 @@ static int check_block_status(struct gfs2_sbd *sdp, char *buffer,
(unsigned long long)block);
if (query(_("Do you want to reclaim the block? "
"(y/n) "))) {
- if (gfs2_set_bitmap(sdp, block, block_status))
+ lgfs2_rgrp_t rg = gfs2_blk2rgrpd(sdp, block);
+ if (gfs2_set_bitmap(rg, block, block_status))
log_err(_("Unlinked block %llu "
"(0x%llx) bitmap not fixed."
"\n"),
@@ -182,7 +183,8 @@ static int check_block_status(struct gfs2_sbd *sdp, char *buffer,
if (query(_("Fix bitmap for block %llu (0x%llx) ? (y/n) "),
(unsigned long long)block,
(unsigned long long)block)) {
- if (gfs2_set_bitmap(sdp, block, block_status))
+ lgfs2_rgrp_t rg = gfs2_blk2rgrpd(sdp, block);
+ if (gfs2_set_bitmap(rg, block, block_status))
log_err( _("Repair failed.\n"));
else
log_err( _("Fixed.\n"));
diff --git a/gfs2/libgfs2/fs_bits.c b/gfs2/libgfs2/fs_bits.c
index e4b5505..7194949 100644
--- a/gfs2/libgfs2/fs_bits.c
+++ b/gfs2/libgfs2/fs_bits.c
@@ -124,12 +124,11 @@ int gfs2_check_range(struct gfs2_sbd *sdp, uint64_t blkno)
*
* Returns: 0 on success, -1 on error
*/
-int gfs2_set_bitmap(struct gfs2_sbd *sdp, uint64_t blkno, int state)
+int gfs2_set_bitmap(lgfs2_rgrp_t rgd, uint64_t blkno, int state)
{
int buf;
uint32_t rgrp_block;
struct gfs2_bitmap *bits = NULL;
- struct rgrp_tree *rgd;
unsigned char *byte, cur_state;
unsigned int bit;
@@ -137,8 +136,6 @@ int gfs2_set_bitmap(struct gfs2_sbd *sdp, uint64_t blkno, int state)
if ((state < GFS2_BLKST_FREE) || (state > GFS2_BLKST_DINODE))
return -1;
- rgd = gfs2_blk2rgrpd(sdp, blkno);
-
if(!rgd || blkno < rgd->ri.ri_data0)
return -1;
diff --git a/gfs2/libgfs2/fs_ops.c b/gfs2/libgfs2/fs_ops.c
index b95f2ed..fdd4438 100644
--- a/gfs2/libgfs2/fs_ops.c
+++ b/gfs2/libgfs2/fs_ops.c
@@ -141,7 +141,7 @@ static int blk_alloc_in_rg(struct gfs2_sbd *sdp, unsigned state, struct rgrp_tre
if (blkno == 0)
return -1;
- if (gfs2_set_bitmap(sdp, blkno, state))
+ if (gfs2_set_bitmap(rgd, blkno, state))
return -1;
if (state == GFS2_BLKST_DINODE)
@@ -1763,7 +1763,7 @@ void gfs2_free_block(struct gfs2_sbd *sdp, uint64_t block)
/* Adjust the free space count for the freed block */
rgd = gfs2_blk2rgrpd(sdp, block); /* find the rg for indir block */
if (rgd) {
- gfs2_set_bitmap(sdp, block, GFS2_BLKST_FREE);
+ gfs2_set_bitmap(rgd, block, GFS2_BLKST_FREE);
rgd->rg.rg_free++; /* adjust the free count */
if (sdp->gfs1)
gfs_rgrp_out((struct gfs_rgrp *)&rgd->rg, rgd->bh[0]);
@@ -1826,16 +1826,14 @@ int gfs2_freedi(struct gfs2_sbd *sdp, uint64_t diblock)
}
}
}
- /* Set the bitmap type for inode to free space: */
- gfs2_set_bitmap(sdp, ip->i_di.di_num.no_addr, GFS2_BLKST_FREE);
+ rgd = gfs2_blk2rgrpd(sdp, diblock);
+ gfs2_set_bitmap(rgd, diblock, GFS2_BLKST_FREE);
inode_put(&ip);
/* inode_put deallocated the extra block used by the disk inode, */
/* so adjust it in the superblock struct */
sdp->blks_alloced--;
- /* Now we have to adjust the rg freespace count and inode count: */
- rgd = gfs2_blk2rgrpd(sdp, diblock);
rgd->rg.rg_free++;
- rgd->rg.rg_dinodes--; /* one less inode in use */
+ rgd->rg.rg_dinodes--;
if (sdp->gfs1)
gfs_rgrp_out((struct gfs_rgrp *)&rgd->rg, rgd->bh[0]);
else
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index 24947c2..b2f6bc3 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -418,7 +418,7 @@ extern int gfs2_check_range(struct gfs2_sbd *sdp, uint64_t blkno);
/* functions with blk #'s that are file system relative */
extern int lgfs2_get_bitmap(struct gfs2_sbd *sdp, uint64_t blkno, struct rgrp_tree *rgd);
-extern int gfs2_set_bitmap(struct gfs2_sbd *sdp, uint64_t blkno, int state);
+extern int gfs2_set_bitmap(lgfs2_rgrp_t rg, uint64_t blkno, int state);
/* fs_geometry.c */
extern uint32_t rgblocks2bitblocks(const unsigned int bsize, const uint32_t rgblocks,
--
1.8.5.3
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [Cluster-devel] [PATCH 06/14] libgfs2: Add abstractions for rgrp tree traversal
2014-04-03 15:12 [Cluster-devel] [PATCH 00/14] gfs2_grow and libgfs2 rgrp API improvements Andrew Price
` (4 preceding siblings ...)
2014-04-03 15:12 ` [Cluster-devel] [PATCH 05/14] libgfs2: Don't call gfs2_blk2rgrpd in gfs2_set_bitmap Andrew Price
@ 2014-04-03 15:12 ` Andrew Price
2014-04-03 15:12 ` [Cluster-devel] [PATCH 07/14] libgfs2: Split out the rindex calculation from lgfs2_rgrp_append Andrew Price
` (8 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Andrew Price @ 2014-04-03 15:12 UTC (permalink / raw)
To: cluster-devel.redhat.com
Users of libgfs2 are required to include the gfs2-utils-specific
osi_tree.h in order to make use of the resource groups. With this patch
we introduce functions which wrap the osi_first and osi_next functions
so that we can hide the implementation of the resource group tree behind
the lgfs2_rgrp_t type. Converting users of the osi_tree.h functions to
the new rgrp APIs will be done later and gradually.
Signed-off-by: Andrew Price <anprice@redhat.com>
---
gfs2/libgfs2/libgfs2.h | 3 +++
gfs2/libgfs2/rgrp.c | 15 +++++++++++++++
2 files changed, 18 insertions(+)
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index b2f6bc3..3eeb04d 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -197,6 +197,9 @@ extern uint32_t lgfs2_rgrps_plan(const lgfs2_rgrps_t rgs, uint64_t space, uint32
extern lgfs2_rgrp_t lgfs2_rgrp_append(lgfs2_rgrps_t rgs, uint64_t addr, uint32_t rglen, uint64_t *nextaddr);
extern int lgfs2_rgrp_write(lgfs2_rgrps_t rgs, int fd, lgfs2_rgrp_t rg);
extern struct gfs2_rindex *lgfs2_rgrp_index(lgfs2_rgrp_t rg);
+extern lgfs2_rgrp_t lgfs2_rgrp_first(lgfs2_rgrps_t rgs);
+extern lgfs2_rgrp_t lgfs2_rgrp_last(lgfs2_rgrps_t rgs);
+extern lgfs2_rgrp_t lgfs2_rgrp_next(lgfs2_rgrp_t rg);
// Temporary function to aid API migration
extern struct osi_node *lgfs2_rgrps_root(lgfs2_rgrps_t rgs) __attribute__((deprecated));
diff --git a/gfs2/libgfs2/rgrp.c b/gfs2/libgfs2/rgrp.c
index 1242385..fb2b115 100644
--- a/gfs2/libgfs2/rgrp.c
+++ b/gfs2/libgfs2/rgrp.c
@@ -479,3 +479,18 @@ int lgfs2_rgrp_write(const lgfs2_rgrps_t rgs, int fd, const lgfs2_rgrp_t rg)
free(buff);
return 0;
}
+
+lgfs2_rgrp_t lgfs2_rgrp_first(lgfs2_rgrps_t rgs)
+{
+ return (lgfs2_rgrp_t)osi_first(&rgs->root);
+}
+
+lgfs2_rgrp_t lgfs2_rgrp_next(lgfs2_rgrp_t rg)
+{
+ return (lgfs2_rgrp_t)osi_next(&rg->node);
+}
+
+lgfs2_rgrp_t lgfs2_rgrp_last(lgfs2_rgrps_t rgs)
+{
+ return (lgfs2_rgrp_t)osi_last(&rgs->root);
+}
--
1.8.5.3
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [Cluster-devel] [PATCH 07/14] libgfs2: Split out the rindex calculation from lgfs2_rgrp_append
2014-04-03 15:12 [Cluster-devel] [PATCH 00/14] gfs2_grow and libgfs2 rgrp API improvements Andrew Price
` (5 preceding siblings ...)
2014-04-03 15:12 ` [Cluster-devel] [PATCH 06/14] libgfs2: Add abstractions for rgrp tree traversal Andrew Price
@ 2014-04-03 15:12 ` Andrew Price
2014-04-03 15:12 ` [Cluster-devel] [PATCH 08/14] libgfs2: Consolidate rgrp_tree and bitstruct allocations Andrew Price
` (7 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Andrew Price @ 2014-04-03 15:12 UTC (permalink / raw)
To: cluster-devel.redhat.com
In order to better support gfs2_grow the new resource group API needs to
expose rindex entry calculation and lightweight scanning of existing
resource groups (i.e. only read the rindex and forget each entry when
done). This patch takes care of the former by adding a
lgfs2_rindex_entry_new() function which calculates an rindex entry only
and not the whole lgfs2_rgrp_t structure. Now we can calculate the rgrp
geometry as early as possible and avoid passing around address+length
arguments where a rindex would be more appropriate.
Signed-off-by: Andrew Price <anprice@redhat.com>
---
gfs2/libgfs2/libgfs2.h | 4 ++-
gfs2/libgfs2/rgrp.c | 83 ++++++++++++++++++++++++++++++++------------------
gfs2/mkfs/main_mkfs.c | 26 ++++++++--------
3 files changed, 70 insertions(+), 43 deletions(-)
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index 3eeb04d..99f64fc 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -190,13 +190,15 @@ typedef struct rgrp_tree *lgfs2_rgrp_t;
typedef struct _lgfs2_rgrps *lgfs2_rgrps_t;
extern lgfs2_rgrps_t lgfs2_rgrps_init(unsigned bsize, uint64_t devlen, uint64_t align, uint64_t offset);
+extern uint64_t lgfs2_rindex_entry_new(lgfs2_rgrps_t rgs, struct gfs2_rindex *entry, uint64_t addr, uint32_t len);
extern uint64_t lgfs2_rgrp_align_addr(const lgfs2_rgrps_t rgs, uint64_t addr);
extern uint32_t lgfs2_rgrp_align_len(const lgfs2_rgrps_t rgs, uint32_t len);
extern unsigned lgfs2_rgsize_for_data(uint64_t blksreq, unsigned bsize);
extern uint32_t lgfs2_rgrps_plan(const lgfs2_rgrps_t rgs, uint64_t space, uint32_t tgtsize);
-extern lgfs2_rgrp_t lgfs2_rgrp_append(lgfs2_rgrps_t rgs, uint64_t addr, uint32_t rglen, uint64_t *nextaddr);
+extern lgfs2_rgrp_t lgfs2_rgrps_append(lgfs2_rgrps_t rgs, struct gfs2_rindex *entry);
extern int lgfs2_rgrp_write(lgfs2_rgrps_t rgs, int fd, lgfs2_rgrp_t rg);
extern struct gfs2_rindex *lgfs2_rgrp_index(lgfs2_rgrp_t rg);
+extern struct gfs2_rgrp *lgfs2_rgrp_rgrp(lgfs2_rgrp_t rg);
extern lgfs2_rgrp_t lgfs2_rgrp_first(lgfs2_rgrps_t rgs);
extern lgfs2_rgrp_t lgfs2_rgrp_last(lgfs2_rgrps_t rgs);
extern lgfs2_rgrp_t lgfs2_rgrp_next(lgfs2_rgrp_t rg);
diff --git a/gfs2/libgfs2/rgrp.c b/gfs2/libgfs2/rgrp.c
index fb2b115..2ae3ed6 100644
--- a/gfs2/libgfs2/rgrp.c
+++ b/gfs2/libgfs2/rgrp.c
@@ -370,6 +370,46 @@ lgfs2_rgrps_t lgfs2_rgrps_init(unsigned bsize, uint64_t devlen, uint64_t align,
}
/**
+ * Calculate the fields for a new entry in the resource group index.
+ * ri: A pointer to the resource group index entry to be calculated.
+ * addr: The address at which to place this resource group
+ * len: The required length of the resource group, in fs blocks.
+ * If rglen is 0, geometry previously calculated by lgfs2_rgrps_plan() will be used.
+ * Returns the calculated address of the next resource group or 0 with errno set:
+ * EINVAL - The entry pointer is NULL
+ * ENOSPC - This rgrp would extend past the end of the device
+ */
+uint64_t lgfs2_rindex_entry_new(lgfs2_rgrps_t rgs, struct gfs2_rindex *ri, uint64_t addr, uint32_t len)
+{
+ errno = EINVAL;
+ if (!ri)
+ return 0;
+
+ errno = ENOSPC;
+ if (len == 0) {
+ if (rgs->plan[0].num > 0) {
+ len = rgs->plan[0].len;
+ rgs->plan[0].num--;
+ } else if (rgs->plan[1].num > 0) {
+ len = rgs->plan[1].len;
+ rgs->plan[1].num--;
+ } else
+ return 0;
+ }
+ if (addr + len > rgs->devlen)
+ return 0;
+
+ ri->ri_addr = addr;
+ ri->ri_length = rgblocks2bitblocks(rgs->bsize, len, &ri->ri_data);
+ ri->__pad = 0;
+ ri->ri_data0 = ri->ri_addr + ri->ri_length;
+ ri->ri_bitbytes = ri->ri_data / GFS2_NBBY;
+ memset(&ri->ri_reserved, 0, sizeof(ri->ri_reserved));
+
+ return ri->ri_addr + len;
+}
+
+/**
* Return the rindex structure relating to a a resource group.
*/
struct gfs2_rindex *lgfs2_rgrp_index(lgfs2_rgrp_t rg)
@@ -378,6 +418,14 @@ struct gfs2_rindex *lgfs2_rgrp_index(lgfs2_rgrp_t rg)
}
/**
+ * Return the rgrp structure relating to a a resource group.
+ */
+struct gfs2_rgrp *lgfs2_rgrp_rgrp(lgfs2_rgrp_t rg)
+{
+ return &rg->rg;
+}
+
+/**
* Returns the total resource group size, in blocks, required to give blksreq data blocks
*/
unsigned lgfs2_rgsize_for_data(uint64_t blksreq, unsigned bsize)
@@ -397,44 +445,21 @@ struct osi_node *lgfs2_rgrps_root(lgfs2_rgrps_t rgs)
}
/**
- * Create a new resource group after the last resource group in a set.
+ * Insert a new resource group after the last resource group in a set.
* rgs: The set of resource groups
- * addr: The address at which to place this resource group
- * rglen: The required length of the resource group, in fs blocks.
+ * entry: The entry to be added
* Returns the new resource group on success or NULL on failure with errno set.
- * If errno is ENOSPC on a NULL return from this function, it could be
- * interpreted as 'finished' unless you expected there to be enough space on
- * the device for the resource group.
*/
-lgfs2_rgrp_t lgfs2_rgrp_append(lgfs2_rgrps_t rgs, uint64_t addr, uint32_t rglen, uint64_t *nextaddr)
+lgfs2_rgrp_t lgfs2_rgrps_append(lgfs2_rgrps_t rgs, struct gfs2_rindex *entry)
{
int err = 0;
lgfs2_rgrp_t rg;
- if (rglen == 0) {
- if (rgs->plan[0].num > 0) {
- rglen = rgs->plan[0].len;
- rgs->plan[0].num--;
- } else if (rgs->plan[1].num > 0) {
- rglen = rgs->plan[1].len;
- rgs->plan[1].num--;
- } else {
- errno = ENOSPC;
- return NULL;
- }
- }
- if (addr + rglen > rgs->devlen) {
- errno = ENOSPC;
- return NULL;
- }
-
- rg = rgrp_insert(&rgs->root, addr);
+ rg = rgrp_insert(&rgs->root, entry->ri_addr);
if (rg == NULL)
return NULL;
- rg->ri.ri_length = rgblocks2bitblocks(rgs->bsize, rglen, &rg->ri.ri_data);
- rg->ri.ri_data0 = rg->ri.ri_addr + rg->ri.ri_length;
- rg->ri.ri_bitbytes = rg->ri.ri_data / GFS2_NBBY;
+ memcpy(&rg->ri, entry, sizeof(struct gfs2_rindex));
rg->rg.rg_header.mh_magic = GFS2_MAGIC;
rg->rg.rg_header.mh_type = GFS2_METATYPE_RG;
rg->rg.rg_header.mh_format = GFS2_FORMAT_RG;
@@ -443,8 +468,6 @@ lgfs2_rgrp_t lgfs2_rgrp_append(lgfs2_rgrps_t rgs, uint64_t addr, uint32_t rglen,
if (err != 0)
return NULL;
- if (nextaddr)
- *nextaddr = rg->ri.ri_addr + rglen;
return rg;
}
diff --git a/gfs2/mkfs/main_mkfs.c b/gfs2/mkfs/main_mkfs.c
index ae82c9f..67850c8 100644
--- a/gfs2/mkfs/main_mkfs.c
+++ b/gfs2/mkfs/main_mkfs.c
@@ -625,16 +625,13 @@ static lgfs2_rgrps_t rgs_init(struct mkfs_opts *opts, struct gfs2_sbd *sdp)
return rgs;
}
-static int place_rgrp(struct gfs2_sbd *sdp, lgfs2_rgrps_t rgs, uint64_t rgaddr, uint32_t len, uint64_t *next)
+static int place_rgrp(struct gfs2_sbd *sdp, lgfs2_rgrps_t rgs, struct gfs2_rindex *ri)
{
int err = 0;
lgfs2_rgrp_t rg = NULL;
- struct gfs2_rindex *ri = NULL;
- rg = lgfs2_rgrp_append(rgs, rgaddr, len, next);
+ rg = lgfs2_rgrps_append(rgs, ri);
if (rg == NULL) {
- if (errno == ENOSPC)
- return 1;
perror(_("Failed to create resource group"));
return -1;
}
@@ -643,7 +640,6 @@ static int place_rgrp(struct gfs2_sbd *sdp, lgfs2_rgrps_t rgs, uint64_t rgaddr,
perror(_("Failed to write resource group"));
return -1;
}
- ri = lgfs2_rgrp_index(rg);
if (sdp->debug) {
gfs2_rindex_print(ri);
printf("\n");
@@ -656,6 +652,7 @@ static int place_rgrp(struct gfs2_sbd *sdp, lgfs2_rgrps_t rgs, uint64_t rgaddr,
static int place_rgrps(struct gfs2_sbd *sdp, lgfs2_rgrps_t rgs, struct mkfs_opts *opts)
{
+ struct gfs2_rindex ri;
uint64_t jfsize = lgfs2_space_for_data(sdp, sdp->bsize, opts->jsize << 20);
uint32_t jrgsize = lgfs2_rgsize_for_data(jfsize, sdp->bsize);
uint64_t rgaddr = lgfs2_rgrp_align_addr(rgs, sdp->sb_addr + 1);
@@ -673,21 +670,26 @@ static int place_rgrps(struct gfs2_sbd *sdp, lgfs2_rgrps_t rgs, struct mkfs_opts
}
for (j = 0; j < opts->journals; j++) {
- int result = place_rgrp(sdp, rgs, rgaddr, jrgsize, NULL);
+ int result;
+ rgaddr = lgfs2_rindex_entry_new(rgs, &ri, rgaddr, jrgsize);
+ if (rgaddr == 0) /* Reached the end when we still have journals to write */
+ return 1;
+ result = place_rgrp(sdp, rgs, &ri);
if (result != 0)
return result;
- rgaddr = rgaddr + jrgsize;
}
if (rgsize != jrgsize)
lgfs2_rgrps_plan(rgs, sdp->device.length - rgaddr, ((opts->rgsize << 20) / sdp->bsize));
while (1) {
- int result = place_rgrp(sdp, rgs, rgaddr, 0, &rgaddr);
- if (result < 0)
- return result;
- if (result > 0)
+ int result;
+ rgaddr = lgfs2_rindex_entry_new(rgs, &ri, rgaddr, 0);
+ if (rgaddr == 0)
break; /* Done */
+ result = place_rgrp(sdp, rgs, &ri);
+ if (result)
+ return result;
}
return 0;
}
--
1.8.5.3
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [Cluster-devel] [PATCH 08/14] libgfs2: Consolidate rgrp_tree and bitstruct allocations
2014-04-03 15:12 [Cluster-devel] [PATCH 00/14] gfs2_grow and libgfs2 rgrp API improvements Andrew Price
` (6 preceding siblings ...)
2014-04-03 15:12 ` [Cluster-devel] [PATCH 07/14] libgfs2: Split out the rindex calculation from lgfs2_rgrp_append Andrew Price
@ 2014-04-03 15:12 ` Andrew Price
2014-04-03 15:12 ` [Cluster-devel] [PATCH 09/14] libgfs2: Add a lgfs2_rindex_read_fd() function Andrew Price
` (6 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Andrew Price @ 2014-04-03 15:12 UTC (permalink / raw)
To: cluster-devel.redhat.com
rgrp_insert() and gfs2_compute_bitstructs() allocated separate chunks of
memory for the resource groups (struct rgrp_tree) and the bitmaps and
buffer pointers attached to them. This can be handled more efficiently
by allocating memory for the the whole thing in one go, so we now do
that in lgfs2_rgrps_append(). A new lgfs2_rgrps_free() function has been
added to free the memory allocated in this way. Calculation of the
bitmap structure fields has been simplified and separated out so that
lgfs2_rgrps_append() can share it with gfs2_compute_bitstructs() until
the latter can be removed.
Signed-off-by: Andrew Price <anprice@redhat.com>
---
gfs2/libgfs2/libgfs2.h | 1 +
gfs2/libgfs2/rgrp.c | 143 ++++++++++++++++++++++++++++++-------------------
gfs2/mkfs/main_mkfs.c | 2 +-
3 files changed, 91 insertions(+), 55 deletions(-)
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index 99f64fc..b70c36d 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -190,6 +190,7 @@ typedef struct rgrp_tree *lgfs2_rgrp_t;
typedef struct _lgfs2_rgrps *lgfs2_rgrps_t;
extern lgfs2_rgrps_t lgfs2_rgrps_init(unsigned bsize, uint64_t devlen, uint64_t align, uint64_t offset);
+extern void lgfs2_rgrps_free(lgfs2_rgrps_t *rgs);
extern uint64_t lgfs2_rindex_entry_new(lgfs2_rgrps_t rgs, struct gfs2_rindex *entry, uint64_t addr, uint32_t len);
extern uint64_t lgfs2_rgrp_align_addr(const lgfs2_rgrps_t rgs, uint64_t addr);
extern uint32_t lgfs2_rgrp_align_len(const lgfs2_rgrps_t rgs, uint32_t len);
diff --git a/gfs2/libgfs2/rgrp.c b/gfs2/libgfs2/rgrp.c
index 2ae3ed6..02ab450 100644
--- a/gfs2/libgfs2/rgrp.c
+++ b/gfs2/libgfs2/rgrp.c
@@ -10,6 +10,23 @@
#define RG_SYNC_TOLERANCE 1000
+static void compute_bitmaps(lgfs2_rgrp_t rg, const unsigned bsize)
+{
+ int x;
+
+ rg->bits[0].bi_offset = sizeof(struct gfs2_rgrp);
+ rg->bits[0].bi_start = 0;
+ rg->bits[0].bi_len = bsize - sizeof(struct gfs2_rgrp);
+
+ for (x = 1; x < rg->ri.ri_length; x++) {
+ rg->bits[x].bi_offset = sizeof(struct gfs2_meta_header);
+ rg->bits[x].bi_start = rg->bits[x - 1].bi_start + rg->bits[x - 1].bi_len;
+ rg->bits[x].bi_len = bsize - sizeof(struct gfs2_meta_header);
+ }
+ x--;
+ rg->bits[x].bi_len = rg->ri.ri_bitbytes - rg->bits[x].bi_start;
+}
+
/**
* gfs2_compute_bitstructs - Compute the bitmap sizes
* bsize: Block size
@@ -18,10 +35,9 @@
*/
int gfs2_compute_bitstructs(const uint32_t bsize, struct rgrp_tree *rgd)
{
- struct gfs2_bitmap *bits;
uint32_t length = rgd->ri.ri_length;
- uint32_t bytes_left, bytes;
- int x;
+ uint32_t bytes_left;
+ int ownbits = 0;
/* Max size of an rg is 2GB. A 2GB RG with (minimum) 512-byte blocks
has 4194304 blocks. We can represent 4 blocks in one bitmap byte.
@@ -29,63 +45,38 @@ int gfs2_compute_bitstructs(const uint32_t bsize, struct rgrp_tree *rgd)
Subtract a metadata header for each 512-byte block and we get
488 bytes of bitmap per block. Divide 1048576 by 488 and we can
be assured we should never have more than 2149 of them. */
+ errno = EINVAL;
if (length > 2149 || length == 0)
return -1;
- if(rgd->bits == NULL && !(rgd->bits = (struct gfs2_bitmap *)
- malloc(length * sizeof(struct gfs2_bitmap))))
- return -1;
- if(!memset(rgd->bits, 0, length * sizeof(struct gfs2_bitmap)))
- return -1;
-
- bytes_left = rgd->ri.ri_bitbytes;
- for (x = 0; x < length; x++){
- bits = &rgd->bits[x];
-
- if (length == 1){
- bytes = bytes_left;
- bits->bi_offset = sizeof(struct gfs2_rgrp);
- bits->bi_start = 0;
- bits->bi_len = bytes;
- }
- else if (x == 0){
- bytes = bsize - sizeof(struct gfs2_rgrp);
- bits->bi_offset = sizeof(struct gfs2_rgrp);
- bits->bi_start = 0;
- bits->bi_len = bytes;
- }
- else if (x + 1 == length){
- bytes = bytes_left;
- bits->bi_offset = sizeof(struct gfs2_meta_header);
- bits->bi_start = rgd->ri.ri_bitbytes - bytes_left;
- bits->bi_len = bytes;
- }
- else{
- bytes = bsize - sizeof(struct gfs2_meta_header);
- bits->bi_offset = sizeof(struct gfs2_meta_header);
- bits->bi_start = rgd->ri.ri_bitbytes - bytes_left;
- bits->bi_len = bytes;
- }
-
- bytes_left -= bytes;
+ if(rgd->bits == NULL) {
+ rgd->bits = calloc(length, sizeof(struct gfs2_bitmap));
+ if(rgd->bits == NULL)
+ return -1;
+ ownbits = 1;
}
+ compute_bitmaps(rgd, bsize);
+ bytes_left = rgd->ri.ri_bitbytes - (rgd->bits[rgd->ri.ri_length - 1].bi_start +
+ rgd->bits[rgd->ri.ri_length - 1].bi_len);
+ errno = EINVAL;
if(bytes_left)
- return -1;
+ goto errbits;
if((rgd->bits[length - 1].bi_start +
rgd->bits[length - 1].bi_len) * GFS2_NBBY != rgd->ri.ri_data)
- return -1;
-
- if (rgd->bh) /* If we already have a bh allocated */
- return 0; /* don't want to allocate another */
- if(!(rgd->bh = (struct gfs2_buffer_head **)
- malloc(length * sizeof(struct gfs2_buffer_head *))))
- return -1;
- if(!memset(rgd->bh, 0, length * sizeof(struct gfs2_buffer_head *)))
- return -1;
+ goto errbits;
+ if (rgd->bh == NULL) {
+ rgd->bh = calloc(length, sizeof(struct gfs2_buffer_head *));
+ if (rgd->bh == NULL)
+ goto errbits;
+ }
return 0;
+errbits:
+ if (ownbits)
+ free(rgd->bits);
+ return -1;
}
@@ -370,6 +361,31 @@ lgfs2_rgrps_t lgfs2_rgrps_init(unsigned bsize, uint64_t devlen, uint64_t align,
}
/**
+ * Free a set of resource groups created with lgfs2_rgrps_append() etc. This
+ * does not write any dirty buffers to disk. See lgfs2_rgrp_write().
+ * rgs: A pointer to the set of resource groups to be freed.
+ */
+void lgfs2_rgrps_free(lgfs2_rgrps_t *rgs)
+{
+ lgfs2_rgrp_t rg;
+ struct osi_root *tree = &(*rgs)->root;
+
+ while ((rg = (struct rgrp_tree *)osi_first(tree))) {
+ int i;
+ for (i = 0; i < rg->ri.ri_length; i++) {
+ if (rg->bh[i] != NULL) {
+ free(rg->bh[i]);
+ rg->bh[i] = NULL;
+ }
+ }
+ osi_erase(&rg->node, tree);
+ free(rg);
+ }
+ free(*rgs);
+ *rgs = NULL;
+}
+
+/**
* Calculate the fields for a new entry in the resource group index.
* ri: A pointer to the resource group index entry to be calculated.
* addr: The address at which to place this resource group
@@ -452,22 +468,41 @@ struct osi_node *lgfs2_rgrps_root(lgfs2_rgrps_t rgs)
*/
lgfs2_rgrp_t lgfs2_rgrps_append(lgfs2_rgrps_t rgs, struct gfs2_rindex *entry)
{
- int err = 0;
lgfs2_rgrp_t rg;
+ lgfs2_rgrp_t lastrg = (lgfs2_rgrp_t)osi_last(&rgs->root);
+ struct osi_node **link = &rgs->root.osi_node;
+ struct osi_node *parent = NULL;
+
+ errno = EINVAL;
+ if (entry == NULL)
+ return NULL;
- rg = rgrp_insert(&rgs->root, entry->ri_addr);
+ if (lastrg != NULL) { /* Tree is not empty */
+ if (entry->ri_addr <= lastrg->ri.ri_addr)
+ return NULL; /* Appending with a lower address doesn't make sense */
+ parent = osi_parent(&lastrg->node);
+ link = &lastrg->node.osi_right;
+ }
+
+ rg = calloc(1, sizeof(*rg) +
+ (entry->ri_length * sizeof(struct gfs2_bitmap)) +
+ (entry->ri_length * sizeof(struct gfs2_buffer_head *)));
if (rg == NULL)
return NULL;
+ rg->bits = (struct gfs2_bitmap *)(rg + 1);
+ rg->bh = (struct gfs2_buffer_head **)(rg->bits + entry->ri_length);
+
+ osi_link_node(&rg->node, parent, link);
+ osi_insert_color(&rg->node, &rgs->root);
+
memcpy(&rg->ri, entry, sizeof(struct gfs2_rindex));
rg->rg.rg_header.mh_magic = GFS2_MAGIC;
rg->rg.rg_header.mh_type = GFS2_METATYPE_RG;
rg->rg.rg_header.mh_format = GFS2_FORMAT_RG;
rg->rg.rg_free = rg->ri.ri_data;
- err = gfs2_compute_bitstructs(rgs->bsize, rg);
- if (err != 0)
- return NULL;
+ compute_bitmaps(rg, rgs->bsize);
return rg;
}
diff --git a/gfs2/mkfs/main_mkfs.c b/gfs2/mkfs/main_mkfs.c
index 67850c8..26aeba2 100644
--- a/gfs2/mkfs/main_mkfs.c
+++ b/gfs2/mkfs/main_mkfs.c
@@ -907,7 +907,7 @@ void main_mkfs(int argc, char *argv[])
inode_put(&sbd.md.inum);
inode_put(&sbd.md.statfs);
- gfs2_rgrp_free(&sbd.rgtree);
+ lgfs2_rgrps_free(&rgs);
error = lgfs2_sb_write(&sb, opts.dev.fd, sbd.bsize);
if (error) {
--
1.8.5.3
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [Cluster-devel] [PATCH 09/14] libgfs2: Add a lgfs2_rindex_read_fd() function
2014-04-03 15:12 [Cluster-devel] [PATCH 00/14] gfs2_grow and libgfs2 rgrp API improvements Andrew Price
` (7 preceding siblings ...)
2014-04-03 15:12 ` [Cluster-devel] [PATCH 08/14] libgfs2: Consolidate rgrp_tree and bitstruct allocations Andrew Price
@ 2014-04-03 15:12 ` Andrew Price
2014-04-03 15:12 ` [Cluster-devel] [PATCH 10/14] libgfs2: Const-ify the 'ri' argument to gfs2_rindex_out Andrew Price
` (5 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Andrew Price @ 2014-04-03 15:12 UTC (permalink / raw)
To: cluster-devel.redhat.com
gfs2_grow opens the rindex file through the metafs so it needs a way to
populate a lgfs2_rgrps_t with existing resource groups. Add
lgfs2_rindex_read_fd() to read in the rindex entries from a fd.
Also const-ify the return types of lgfs2_rgrp_index() and
lgfs2_rgrp_rgrp() to warn users that they shouldn't change the contents
of libgfs2-managed data.
Signed-off-by: Andrew Price <anprice@redhat.com>
---
gfs2/libgfs2/libgfs2.h | 5 +++--
gfs2/libgfs2/rgrp.c | 43 +++++++++++++++++++++++++++++++++++++++----
2 files changed, 42 insertions(+), 6 deletions(-)
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index b70c36d..455f01d 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -192,14 +192,15 @@ typedef struct _lgfs2_rgrps *lgfs2_rgrps_t;
extern lgfs2_rgrps_t lgfs2_rgrps_init(unsigned bsize, uint64_t devlen, uint64_t align, uint64_t offset);
extern void lgfs2_rgrps_free(lgfs2_rgrps_t *rgs);
extern uint64_t lgfs2_rindex_entry_new(lgfs2_rgrps_t rgs, struct gfs2_rindex *entry, uint64_t addr, uint32_t len);
+extern unsigned lgfs2_rindex_read_fd(int fd, lgfs2_rgrps_t rgs);
extern uint64_t lgfs2_rgrp_align_addr(const lgfs2_rgrps_t rgs, uint64_t addr);
extern uint32_t lgfs2_rgrp_align_len(const lgfs2_rgrps_t rgs, uint32_t len);
extern unsigned lgfs2_rgsize_for_data(uint64_t blksreq, unsigned bsize);
extern uint32_t lgfs2_rgrps_plan(const lgfs2_rgrps_t rgs, uint64_t space, uint32_t tgtsize);
extern lgfs2_rgrp_t lgfs2_rgrps_append(lgfs2_rgrps_t rgs, struct gfs2_rindex *entry);
extern int lgfs2_rgrp_write(lgfs2_rgrps_t rgs, int fd, lgfs2_rgrp_t rg);
-extern struct gfs2_rindex *lgfs2_rgrp_index(lgfs2_rgrp_t rg);
-extern struct gfs2_rgrp *lgfs2_rgrp_rgrp(lgfs2_rgrp_t rg);
+extern const struct gfs2_rindex *lgfs2_rgrp_index(lgfs2_rgrp_t rg);
+extern const struct gfs2_rgrp *lgfs2_rgrp_rgrp(lgfs2_rgrp_t rg);
extern lgfs2_rgrp_t lgfs2_rgrp_first(lgfs2_rgrps_t rgs);
extern lgfs2_rgrp_t lgfs2_rgrp_last(lgfs2_rgrps_t rgs);
extern lgfs2_rgrp_t lgfs2_rgrp_next(lgfs2_rgrp_t rg);
diff --git a/gfs2/libgfs2/rgrp.c b/gfs2/libgfs2/rgrp.c
index 02ab450..cae7a32 100644
--- a/gfs2/libgfs2/rgrp.c
+++ b/gfs2/libgfs2/rgrp.c
@@ -275,8 +275,8 @@ uint32_t lgfs2_rgrp_align_len(const lgfs2_rgrps_t rgs, uint32_t len)
* rgs: The resource groups descriptor
* space: The number of remaining blocks to be allocated
* tgtsize: The target resource group size in blocks
- * Returns the larger of the calculated resource group sizes or 0 if the
- * smaller would be less than GFS2_MIN_RGSIZE.
+ * Returns the larger of the calculated resource group sizes, in blocks, or 0
+ * if the smaller would be less than GFS2_MIN_RGSIZE.
*/
uint32_t lgfs2_rgrps_plan(const lgfs2_rgrps_t rgs, uint64_t space, uint32_t tgtsize)
{
@@ -361,6 +361,41 @@ lgfs2_rgrps_t lgfs2_rgrps_init(unsigned bsize, uint64_t devlen, uint64_t align,
}
/**
+ * Populate a set of resource groups from a gfs2 rindex file.
+ * fd: An open file descriptor for the rindex file.
+ * rgs: The set of resource groups.
+ * Returns the number of resource groups added to the set or 0 on error with
+ * errno set.
+ */
+unsigned lgfs2_rindex_read_fd(int fd, lgfs2_rgrps_t rgs)
+{
+ unsigned count = 0;
+ char buf[sizeof(struct gfs2_rindex)];
+
+ errno = EINVAL;
+ if (fd < 0 || rgs == NULL)
+ return 0;
+
+ while (1) {
+ lgfs2_rgrp_t rg;
+ struct gfs2_rindex ri;
+ ssize_t ret = read(fd, buf, sizeof(struct gfs2_rindex));
+ if (ret == 0)
+ break;
+
+ if (ret != sizeof(struct gfs2_rindex))
+ return 0;
+
+ gfs2_rindex_in(&ri, buf);
+ rg = lgfs2_rgrps_append(rgs, &ri);
+ if (rg == NULL)
+ return 0;
+ count++;
+ }
+ return count;
+}
+
+/**
* Free a set of resource groups created with lgfs2_rgrps_append() etc. This
* does not write any dirty buffers to disk. See lgfs2_rgrp_write().
* rgs: A pointer to the set of resource groups to be freed.
@@ -428,7 +463,7 @@ uint64_t lgfs2_rindex_entry_new(lgfs2_rgrps_t rgs, struct gfs2_rindex *ri, uint6
/**
* Return the rindex structure relating to a a resource group.
*/
-struct gfs2_rindex *lgfs2_rgrp_index(lgfs2_rgrp_t rg)
+const struct gfs2_rindex *lgfs2_rgrp_index(lgfs2_rgrp_t rg)
{
return &rg->ri;
}
@@ -436,7 +471,7 @@ struct gfs2_rindex *lgfs2_rgrp_index(lgfs2_rgrp_t rg)
/**
* Return the rgrp structure relating to a a resource group.
*/
-struct gfs2_rgrp *lgfs2_rgrp_rgrp(lgfs2_rgrp_t rg)
+const struct gfs2_rgrp *lgfs2_rgrp_rgrp(lgfs2_rgrp_t rg)
{
return &rg->rg;
}
--
1.8.5.3
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [Cluster-devel] [PATCH 10/14] libgfs2: Const-ify the 'ri' argument to gfs2_rindex_out
2014-04-03 15:12 [Cluster-devel] [PATCH 00/14] gfs2_grow and libgfs2 rgrp API improvements Andrew Price
` (8 preceding siblings ...)
2014-04-03 15:12 ` [Cluster-devel] [PATCH 09/14] libgfs2: Add a lgfs2_rindex_read_fd() function Andrew Price
@ 2014-04-03 15:12 ` Andrew Price
2014-04-03 15:12 ` [Cluster-devel] [PATCH 11/14] libgfs2: Fix off-by-one in lgfs2_rgrps_plan Andrew Price
` (4 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Andrew Price @ 2014-04-03 15:12 UTC (permalink / raw)
To: cluster-devel.redhat.com
This function shouldn't modify its ri argument and the const helps when we want
to pass it the return value of one of the newly-const lgfs2_rgrp_{index,rgrp}
functions (the rgrp arg to gfs2_rgrp_out is already const so no change needed).
Signed-off-by: Andrew Price <anprice@redhat.com>
---
gfs2/libgfs2/libgfs2.h | 2 +-
gfs2/libgfs2/ondisk.c | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index 455f01d..3353f5f 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -802,7 +802,7 @@ extern void gfs2_meta_header_out_bh(const struct gfs2_meta_header *mh,
extern void gfs2_sb_in(struct gfs2_sb *sb, struct gfs2_buffer_head *bh);
extern void gfs2_sb_out(const struct gfs2_sb *sb, char *buf);
extern void gfs2_rindex_in(struct gfs2_rindex *ri, char *buf);
-extern void gfs2_rindex_out(struct gfs2_rindex *ri, char *buf);
+extern void gfs2_rindex_out(const struct gfs2_rindex *ri, char *buf);
extern void gfs2_rgrp_in(struct gfs2_rgrp *rg, struct gfs2_buffer_head *bh);
extern void gfs2_rgrp_out(const struct gfs2_rgrp *rg, char *buf);
extern void gfs2_rgrp_out_bh(const struct gfs2_rgrp *rg, struct gfs2_buffer_head *bh);
diff --git a/gfs2/libgfs2/ondisk.c b/gfs2/libgfs2/ondisk.c
index 3fbc63f..1f81b5f 100644
--- a/gfs2/libgfs2/ondisk.c
+++ b/gfs2/libgfs2/ondisk.c
@@ -213,13 +213,13 @@ void gfs2_rindex_in(struct gfs2_rindex *ri, char *buf)
CPIN_08(ri, str, ri_reserved, 64);
}
-void gfs2_rindex_out(struct gfs2_rindex *ri, char *buf)
+void gfs2_rindex_out(const struct gfs2_rindex *ri, char *buf)
{
struct gfs2_rindex *str = (struct gfs2_rindex *)buf;
CPOUT_64(ri, str, ri_addr);
CPOUT_32(ri, str, ri_length);
- ri->__pad = 0;
+ str->__pad = 0;
CPOUT_64(ri, str, ri_data0);
CPOUT_32(ri, str, ri_data);
--
1.8.5.3
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [Cluster-devel] [PATCH 11/14] libgfs2: Fix off-by-one in lgfs2_rgrps_plan
2014-04-03 15:12 [Cluster-devel] [PATCH 00/14] gfs2_grow and libgfs2 rgrp API improvements Andrew Price
` (9 preceding siblings ...)
2014-04-03 15:12 ` [Cluster-devel] [PATCH 10/14] libgfs2: Const-ify the 'ri' argument to gfs2_rindex_out Andrew Price
@ 2014-04-03 15:12 ` Andrew Price
2014-04-03 15:12 ` [Cluster-devel] [PATCH 12/14] libgfs2: Stick to the (rgrp) plan in lgfs2_rindex_entry_new Andrew Price
` (3 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Andrew Price @ 2014-04-03 15:12 UTC (permalink / raw)
To: cluster-devel.redhat.com
We were making plans based on an extra resource group but not adding the extra
one to the count. Make sure the count is incremented appropriately.
Signed-off-by: Andrew Price <anprice@redhat.com>
---
gfs2/libgfs2/rgrp.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/gfs2/libgfs2/rgrp.c b/gfs2/libgfs2/rgrp.c
index cae7a32..d70dfc5 100644
--- a/gfs2/libgfs2/rgrp.c
+++ b/gfs2/libgfs2/rgrp.c
@@ -299,7 +299,8 @@ uint32_t lgfs2_rgrps_plan(const lgfs2_rgrps_t rgs, uint64_t space, uint32_t tgts
/* Spread the adjustment required to fit a new rgrp at the end
over all of the rgrps so that we don't end with a single
tiny one. */
- while (((rgs->plan[0].len - adj) * (rgs->plan[0].num + 1)) >= space)
+ rgs->plan[0].num++;
+ while (((rgs->plan[0].len - adj) * (rgs->plan[0].num)) >= space)
rgs->plan[0].len -= adj;
/* We've adjusted the size of the rgrps down as far as we can
@@ -313,7 +314,7 @@ uint32_t lgfs2_rgrps_plan(const lgfs2_rgrps_t rgs, uint64_t space, uint32_t tgts
rgs->plan[1].num = 0;
while (((rgs->plan[0].len * rgs->plan[0].num) +
- (rgs->plan[1].len * rgs->plan[1].num)) > space) {
+ (rgs->plan[1].len * rgs->plan[1].num)) >= space) {
/* Total number of rgrps stays constant now. We just
need to shift some weight around */
rgs->plan[0].num--;
--
1.8.5.3
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [Cluster-devel] [PATCH 12/14] libgfs2: Stick to the (rgrp) plan in lgfs2_rindex_entry_new
2014-04-03 15:12 [Cluster-devel] [PATCH 00/14] gfs2_grow and libgfs2 rgrp API improvements Andrew Price
` (10 preceding siblings ...)
2014-04-03 15:12 ` [Cluster-devel] [PATCH 11/14] libgfs2: Fix off-by-one in lgfs2_rgrps_plan Andrew Price
@ 2014-04-03 15:12 ` Andrew Price
2014-04-03 15:12 ` [Cluster-devel] [PATCH 13/14] gfs2_grow: Migrate to the new resource group API Andrew Price
` (2 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Andrew Price @ 2014-04-03 15:12 UTC (permalink / raw)
To: cluster-devel.redhat.com
lgfs2_rindex_entry_new() was ignoring the plan any time len was not 0, even if
len matched the next rgrp length in the plan. This was causing problems in mkfs
when the journal-adjusted rgrp size was the same as the normal rgrp size.
Decrement the count of the appropriate rgrp size if the length matches.
Signed-off-by: Andrew Price <anprice@redhat.com>
---
gfs2/libgfs2/rgrp.c | 21 ++++++++++++---------
1 file changed, 12 insertions(+), 9 deletions(-)
diff --git a/gfs2/libgfs2/rgrp.c b/gfs2/libgfs2/rgrp.c
index d70dfc5..901a7bf 100644
--- a/gfs2/libgfs2/rgrp.c
+++ b/gfs2/libgfs2/rgrp.c
@@ -433,21 +433,24 @@ void lgfs2_rgrps_free(lgfs2_rgrps_t *rgs)
*/
uint64_t lgfs2_rindex_entry_new(lgfs2_rgrps_t rgs, struct gfs2_rindex *ri, uint64_t addr, uint32_t len)
{
+ int plan = -1;
errno = EINVAL;
if (!ri)
return 0;
errno = ENOSPC;
- if (len == 0) {
- if (rgs->plan[0].num > 0) {
- len = rgs->plan[0].len;
- rgs->plan[0].num--;
- } else if (rgs->plan[1].num > 0) {
- len = rgs->plan[1].len;
- rgs->plan[1].num--;
- } else
- return 0;
+ if (rgs->plan[0].num > 0)
+ plan = 0;
+ else if (rgs->plan[1].num > 0)
+ plan = 1;
+ else
+ return 0;
+
+ if (plan >= 0 && (len == 0 || len == rgs->plan[plan].len)) {
+ len = rgs->plan[plan].len;
+ rgs->plan[plan].num--;
}
+
if (addr + len > rgs->devlen)
return 0;
--
1.8.5.3
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [Cluster-devel] [PATCH 13/14] gfs2_grow: Migrate to the new resource group API
2014-04-03 15:12 [Cluster-devel] [PATCH 00/14] gfs2_grow and libgfs2 rgrp API improvements Andrew Price
` (11 preceding siblings ...)
2014-04-03 15:12 ` [Cluster-devel] [PATCH 12/14] libgfs2: Stick to the (rgrp) plan in lgfs2_rindex_entry_new Andrew Price
@ 2014-04-03 15:12 ` Andrew Price
2014-04-03 15:12 ` [Cluster-devel] [PATCH 14/14] gfs2_grow: Add stripe alignment Andrew Price
2014-04-07 15:15 ` [Cluster-devel] [PATCH 00/14] gfs2_grow and libgfs2 rgrp API improvements Bob Peterson
14 siblings, 0 replies; 16+ messages in thread
From: Andrew Price @ 2014-04-03 15:12 UTC (permalink / raw)
To: cluster-devel.redhat.com
Now that the foundations are in place, migrate gfs2_grow to the new
resource group API in libgfs2. This fixes the problem of gfs2_grow using
the last existing resource group's size as the size for all of the new
resource groups. It also allows us to remove more direct usage of
osi_tree.h structures and reduce usage of sdp->rgtree and sdp->rgcalc,
which should be removed from that structure at some point.
It should now be trivial to add RAID stripe alignment to gfs2_grow.
Signed-off-by: Andrew Price <anprice@redhat.com>
---
gfs2/mkfs/gfs2_mkfs.h | 1 -
gfs2/mkfs/main_grow.c | 304 +++++++++++++++++++++++---------------------------
2 files changed, 140 insertions(+), 165 deletions(-)
diff --git a/gfs2/mkfs/gfs2_mkfs.h b/gfs2/mkfs/gfs2_mkfs.h
index 231f370..3c63858 100644
--- a/gfs2/mkfs/gfs2_mkfs.h
+++ b/gfs2/mkfs/gfs2_mkfs.h
@@ -8,7 +8,6 @@
/* main_grow */
extern void main_grow(int argc, char *argv[]);
-extern void debug_print_rgrps(struct gfs2_sbd *sdp, struct osi_root *rgtree);
/* main_jadd */
extern void main_jadd(int argc, char *argv[]);
diff --git a/gfs2/mkfs/main_grow.c b/gfs2/mkfs/main_grow.c
index 718bb30..88a7f15 100644
--- a/gfs2/mkfs/main_grow.c
+++ b/gfs2/mkfs/main_grow.c
@@ -133,137 +133,116 @@ static void decode_arguments(int argc, char *argv[], struct gfs2_sbd *sdp)
}
/**
- * filesystem_size - Calculate the size of the filesystem
- *
- * Reads the lists of resource groups in order to
- * work out where the last block of the filesystem is located.
- *
+ * Calculate the size of the filesystem
+ * Reads the lists of resource groups in order to work out where the last block
+ * of the filesystem is located.
* Returns: The calculated size
*/
-
-static uint64_t filesystem_size(struct gfs2_sbd *sdp)
+static uint64_t filesystem_size(lgfs2_rgrps_t rgs)
{
- struct osi_node *n, *next = NULL;
- struct rgrp_tree *rgl;
- uint64_t size = 0, extent;
-
- for (n = osi_first(&sdp->rgtree); n; n = next) {
- next = osi_next(n);
- rgl = (struct rgrp_tree *)n;
- extent = rgl->ri.ri_addr + rgl->ri.ri_length + rgl->ri.ri_data;
- if (extent > size)
- size = extent;
- }
- return size;
+ lgfs2_rgrp_t rg = lgfs2_rgrp_last(rgs);
+ const struct gfs2_rindex *ri = lgfs2_rgrp_index(rg);
+ return ri->ri_data0 + ri->ri_data;
}
/**
- * initialize_new_portion - Write the new rg information to disk buffers.
+ * Write the new rg information to disk.
*/
-static void initialize_new_portion(struct gfs2_sbd *sdp, int *old_rg_count)
+static unsigned initialize_new_portion(struct gfs2_sbd *sdp, lgfs2_rgrps_t rgs)
{
- struct osi_node *n, *next = NULL;
- uint64_t rgrp = 0;
- struct rgrp_tree *rl;
-
- *old_rg_count = 0;
- /* Delete the old RGs from the rglist */
- for (rgrp = 0, n = osi_first(&sdp->rgtree);
- n && rgrp < (sdp->rgrps - sdp->new_rgrps); n = next, rgrp++) {
- next = osi_next(n);
- (*old_rg_count)++;
- rl = (struct rgrp_tree *)n;
- osi_erase(&rl->node, &sdp->rgtree);
- free(rl);
- }
- /* Issue a discard ioctl for the new portion */
- rl = (struct rgrp_tree *)n;
- discard_blocks(sdp->device_fd, rl->start * sdp->bsize,
- (sdp->device.length - rl->start) * sdp->bsize);
+ unsigned rgcount = 0;
+ uint64_t rgaddr = fssize;
+
+ discard_blocks(sdp->device_fd, rgaddr * sdp->bsize, fsgrowth * sdp->bsize);
/* Build the remaining resource groups */
- if (build_rgrps(sdp, !test)) {
- fprintf(stderr, _("Failed to build resource groups\n"));
- exit(-1);
+ while (1) {
+ int err = 0;
+ lgfs2_rgrp_t rg;
+ struct gfs2_rindex ri;
+ rgaddr = lgfs2_rindex_entry_new(rgs, &ri, rgaddr, 0);
+ if (rgaddr == 0)
+ break;
+ rg = lgfs2_rgrps_append(rgs, &ri);
+ if (rg == NULL) {
+ perror(_("Failed to create resource group"));
+ return 0;
+ }
+ if (metafs_interrupted)
+ return 0;
+ if (sdp->debug)
+ printf(_("Writing resource group at %llu with size %"PRIu32"\n"),
+ ri.ri_addr, ri.ri_length + ri.ri_data);
+ if (!test)
+ err = lgfs2_rgrp_write(rgs, sdp->device_fd, rg);
+ if (err != 0) {
+ perror(_("Failed to write resource group"));
+ return 0;
+ }
+ rgcount++;
}
-
- inode_put(&sdp->md.riinode);
- inode_put(&sdp->master_dir);
-
- /* We're done with the libgfs portion, so commit it to disk. */
fsync(sdp->device_fd);
+ return rgcount;
}
-/**
- * fix_rindex - Add the new entries to the end of the rindex file.
- */
-static void fix_rindex(struct gfs2_sbd *sdp, int rindex_fd, int old_rg_count)
+static char *rindex_buffer(lgfs2_rgrps_t rgs, unsigned count)
{
- struct osi_node *n, *next = NULL;
- int count, rg;
- struct rgrp_tree *rl;
- char *buf, *bufptr;
- ssize_t writelen;
- struct stat statbuf;
+ lgfs2_rgrp_t rg;
+ unsigned i = 0;
+ char *buf;
- /* Count the number of new RGs. */
- rg = 0;
- for (n = osi_first(&sdp->rgtree); n; n = next) {
- next = osi_next(n);
- rg++;
- }
- log_info( _("%d new rindex entries.\n"), rg);
- writelen = rg * sizeof(struct gfs2_rindex);
- buf = calloc(1, writelen);
+ buf = calloc(count, sizeof(struct gfs2_rindex));
if (buf == NULL) {
perror(__FUNCTION__);
exit(EXIT_FAILURE);
}
- /* Now add the new rg entries to the rg index. Here we */
- /* need to use the gfs2 kernel code rather than the libgfs2 */
- /* code so we have a live update while mounted. */
- bufptr = buf;
- for (n = osi_first(&sdp->rgtree); n; n = next) {
- next = osi_next(n);
- rg++;
- rl = (struct rgrp_tree *)n;
- gfs2_rindex_out(&rl->ri, bufptr);
- bufptr += sizeof(struct gfs2_rindex);
+ for (rg = lgfs2_rgrp_first(rgs); rg; rg = lgfs2_rgrp_next(rg)) {
+ const struct gfs2_rindex *ri = lgfs2_rgrp_index(rg);
+ gfs2_rindex_out(ri, buf + (sizeof(*ri) * i));
+ i++;
}
- gfs2_rgrp_free(&sdp->rgtree);
- fsync(sdp->device_fd);
+ return buf;
+}
+
+/**
+ * fix_rindex - Add the new entries to the end of the rindex file.
+ */
+static void fix_rindex(int rindex_fd, lgfs2_rgrps_t rgs, unsigned old_rg_count, unsigned rgcount)
+{
+ char *buf;
+ ssize_t count;
+ ssize_t writelen;
+ const size_t entrysize = sizeof(struct gfs2_rindex);
+
+ log_info( _("%d new rindex entries.\n"), rgcount);
+ buf = rindex_buffer(rgs, rgcount);
+ writelen = rgcount * entrysize;
+
if (!test) {
- if (fstat(rindex_fd, &statbuf) != 0) {
- perror("rindex");
- goto out;
- }
- if (statbuf.st_size !=
- old_rg_count * sizeof(struct gfs2_rindex)) {
- log_crit(_("Incorrect rindex size. want %ld(%d resource groups), "
- "have %ld\n"),
- old_rg_count * sizeof(struct gfs2_rindex),
- old_rg_count, statbuf.st_size);
+ off_t rindex_size = lseek(rindex_fd, 0, SEEK_END);
+ if (rindex_size != old_rg_count * entrysize) {
+ log_crit(_("Incorrect rindex size. Want %ld (%d resource groups), have %ld\n"),
+ (old_rg_count * entrysize), old_rg_count, rindex_size);
goto out;
}
- /* Now write the new RGs to the end of the rindex */
- lseek(rindex_fd, 0, SEEK_END);
- count = write(rindex_fd, buf, sizeof(struct gfs2_rindex));
- if (count != sizeof(struct gfs2_rindex)) {
+ /* Write the first entry separately to ensure there's enough
+ space in the fs for the rest */
+ count = write(rindex_fd, buf, entrysize);
+ if (count != entrysize) {
log_crit(_("Error writing first new rindex entry; aborted.\n"));
if (count > 0)
goto trunc;
else
goto out;
}
- count = write(rindex_fd, buf + sizeof(struct gfs2_rindex),
- writelen - sizeof(struct gfs2_rindex));
- if (count != writelen - sizeof(struct gfs2_rindex)) {
+ count = write(rindex_fd, (buf + entrysize), (writelen - entrysize));
+ if (count != (writelen - entrysize)) {
log_crit(_("Error writing new rindex entries; aborted.\n"));
if (count > 0)
goto trunc;
else
goto out;
}
- if (fallocate(rindex_fd, FALLOC_FL_KEEP_SIZE, statbuf.st_size + writelen, sizeof(struct gfs2_rindex)) != 0)
+ if (fallocate(rindex_fd, FALLOC_FL_KEEP_SIZE, (rindex_size + writelen), entrysize) != 0)
perror("fallocate");
fsync(rindex_fd);
}
@@ -284,46 +263,38 @@ trunc:
*/
static void print_info(struct gfs2_sbd *sdp)
{
- log_notice("FS: %-22s%s\n", _("Mount point:"), sdp->path_name);
- log_notice("FS: %-22s%s\n", _("Device:"), sdp->device_name);
- log_notice("FS: %-22s%llu (0x%llx)\n", _("Size:"),
+ log_notice("FS: %-25s%s\n", _("Mount point:"), sdp->path_name);
+ log_notice("FS: %-25s%s\n", _("Device:"), sdp->device_name);
+ log_notice("FS: %-25s%llu (0x%llx)\n", _("Size:"),
(unsigned long long)fssize, (unsigned long long)fssize);
- log_notice("FS: %-22s%u (0x%x)\n", _("Resource group size:"), rgsize, rgsize);
- log_notice("DEV: %-22s%llu (0x%llx)\n", _("Length:"),
+ log_notice("FS: %-25s%u (0x%x)\n", _("New resource group size:"), rgsize, rgsize);
+ log_notice("DEV: %-24s%llu (0x%llx)\n", _("Length:"),
(unsigned long long)sdp->device.length,
(unsigned long long)sdp->device.length);
- log_notice(_("The file system grew by %lluMB.\n"),
- (unsigned long long)fsgrowth / MB);
+ log_notice(_("The file system will grow by %lluMB.\n"),
+ (unsigned long long)(fsgrowth * sdp->bsize) / MB);
}
-void debug_print_rgrps(struct gfs2_sbd *sdp, struct osi_root *rgtree)
+static void debug_print_rgrps(const char *banner, struct gfs2_sbd *sdp, lgfs2_rgrps_t rgs)
{
- struct osi_node *n, *next;
- struct rgrp_tree *rl;
+ lgfs2_rgrp_t r;
if (sdp->debug) {
- log_info("\n");
-
- for (n = osi_first(rgtree); n; n = next) {
- next = osi_next(n);
- rl = (struct rgrp_tree *)n;
- log_info("rg_o = %llu, rg_l = %llu\n",
- (unsigned long long)rl->start,
- (unsigned long long)rl->length);
+ log_info("%s\n", banner);
+
+ for (r = lgfs2_rgrp_first(rgs); r; r = lgfs2_rgrp_next(r)) {
+ const struct gfs2_rindex *ri = lgfs2_rgrp_index(r);
+ log_info("ri_addr = %llu, size = %llu\n",
+ (unsigned long long)ri->ri_addr,
+ (unsigned long long)(ri->ri_data0 + ri->ri_data - ri->ri_addr));
}
}
}
-/**
- * main_grow - do everything
- * @argc:
- * @argv:
- */
-void
-main_grow(int argc, char *argv[])
+void main_grow(int argc, char *argv[])
{
struct gfs2_sbd sbd, *sdp = &sbd;
- int rgcount, rindex_fd;
+ int rindex_fd;
char rindex_name[PATH_MAX];
int error = EXIT_SUCCESS;
int devflags = (test ? O_RDONLY : O_RDWR) | O_CLOEXEC;
@@ -337,9 +308,10 @@ main_grow(int argc, char *argv[])
decode_arguments(argc, argv, sdp);
for(; (argc - optind) > 0; optind++) {
- int sane;
struct mntent *mnt;
- struct rgrp_tree *last_rgrp;
+ unsigned rgcount;
+ unsigned old_rg_count;
+ lgfs2_rgrps_t rgs;
error = lgfs2_open_mnt(argv[optind], O_RDONLY|O_CLOEXEC, &sdp->path_fd,
devflags, &sdp->device_fd, &mnt);
@@ -358,10 +330,6 @@ main_grow(int argc, char *argv[])
perror(sdp->device_name);
exit(EXIT_FAILURE);
}
- log_info( _("Initializing lists...\n"));
- sdp->rgtree.osi_node = NULL;
- sdp->rgcalc.osi_node = NULL;
-
sdp->sd_sb.sb_bsize = GFS2_DEFAULT_BSIZE;
sdp->bsize = sdp->sd_sb.sb_bsize;
if (compute_constants(sdp)) {
@@ -395,59 +363,67 @@ main_grow(int argc, char *argv[])
perror(_("Could not read master directory"));
exit(EXIT_FAILURE);
}
- gfs2_lookupi(sdp->master_dir, "rindex", 6, &sdp->md.riinode);
+ rgs = lgfs2_rgrps_init(sdp->bsize, sdp->device.length, 0, 0);
+ if (rgs == NULL) {
+ perror(_("Could not initialise resource groups"));
+ error = -1;
+ goto out;
+ }
/* Fetch the rindex from disk. We aren't using gfs2 here, */
/* which means that the bitmaps will most likely be cached */
/* and therefore out of date. It shouldn't matter because */
/* we're only going to write out new RG information after */
/* the existing RGs, and only write to the index at EOF. */
- ri_update(sdp, rindex_fd, &rgcount, &sane);
+ log_info(_("Gathering resource group information for %s\n"), argv[optind]);
+ old_rg_count = lgfs2_rindex_read_fd(rindex_fd, rgs);
+ if (old_rg_count == 0) {
+ perror(_("Failed to scan existing resource groups"));
+ error = -EXIT_FAILURE;
+ goto out;
+ }
if (metafs_interrupted)
goto out;
- fssize = filesystem_size(sdp);
- if (!sdp->rgtree.osi_node) {
- log_err(_("Error: No resource groups found.\n"));
- error = -EXIT_FAILURE;
+ fssize = lgfs2_rgrp_align_addr(rgs, filesystem_size(rgs) + 1);
+ debug_print_rgrps(_("Existing resource groups"), sdp, rgs);
+ /* We're done with the old rgs now that we have the fssize and rg count */
+ lgfs2_rgrps_free(&rgs);
+ /* Now lets set up the new ones with alignment and all */
+ rgs = lgfs2_rgrps_init(sdp->bsize, sdp->device.length, 0, 0);
+ if (rgs == NULL) {
+ perror(_("Could not initialise new resource groups"));
+ error = -1;
goto out;
}
- last_rgrp = (struct rgrp_tree *)osi_last(&sdp->rgtree);
- sdp->rgsize = GFS2_DEFAULT_RGSIZE;
- rgsize = rgrp_size(last_rgrp);
- fsgrowth = ((sdp->device.length - fssize) * sdp->bsize);
- if (fsgrowth < rgsize * sdp->bsize) {
- log_err( _("Error: The device has grown by less than "
- "one resource group.\n"));
- log_err( _("The device grew by %lluMB. "),
- (unsigned long long)fsgrowth / MB);
- log_err( _("One resource group is %uMB for this file system.\n"),
- (rgsize * sdp->bsize) / MB);
- error = -EXIT_FAILURE;
+ fsgrowth = (sdp->device.length - fssize);
+ rgsize = lgfs2_rgrps_plan(rgs, fsgrowth, ((GFS2_MAX_RGSIZE << 20) / sdp->bsize));
+ if (rgsize < ((GFS2_MIN_RGSIZE << 20) / sdp->bsize)) {
+ log_err( _("The calculated resource group size is too small.\n"));
+ log_err( _("%s has not grown.\n"), argv[optind]);
+ error = -1;
goto out;
- } else {
- int old_rg_count;
-
- if (metafs_interrupted)
- goto out;
- compute_rgrp_layout(sdp, &sdp->rgtree, TRUE);
- if (metafs_interrupted)
- goto out;
- debug_print_rgrps(sdp, &sdp->rgtree);
- print_info(sdp);
- initialize_new_portion(sdp, &old_rg_count);
- if (metafs_interrupted)
- goto out;
- fix_rindex(sdp, rindex_fd, old_rg_count);
}
+ print_info(sdp);
+ rgcount = initialize_new_portion(sdp, rgs);
+ if (rgcount == 0 || metafs_interrupted)
+ goto out;
+ debug_print_rgrps(_("New resource groups"), sdp, rgs);
+ fsync(sdp->device_fd);
+ fix_rindex(rindex_fd, rgs, old_rg_count, rgcount);
out:
- /* Delete the remaining RGs from the rglist */
- gfs2_rgrp_free(&sdp->rgtree);
+ lgfs2_rgrps_free(&rgs);
close(rindex_fd);
cleanup_metafs(sdp);
close(sdp->device_fd);
+
+ if (metafs_interrupted)
+ break;
}
close(sdp->path_fd);
sync();
- if (!metafs_interrupted)
- log_notice( _("gfs2_grow complete.\n"));
+ if (metafs_interrupted) {
+ log_notice( _("gfs2_grow interrupted.\n"));
+ exit(1);
+ }
+ log_notice( _("gfs2_grow complete.\n"));
exit(error);
}
--
1.8.5.3
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [Cluster-devel] [PATCH 14/14] gfs2_grow: Add stripe alignment
2014-04-03 15:12 [Cluster-devel] [PATCH 00/14] gfs2_grow and libgfs2 rgrp API improvements Andrew Price
` (12 preceding siblings ...)
2014-04-03 15:12 ` [Cluster-devel] [PATCH 13/14] gfs2_grow: Migrate to the new resource group API Andrew Price
@ 2014-04-03 15:12 ` Andrew Price
2014-04-07 15:15 ` [Cluster-devel] [PATCH 00/14] gfs2_grow and libgfs2 rgrp API improvements Bob Peterson
14 siblings, 0 replies; 16+ messages in thread
From: Andrew Price @ 2014-04-03 15:12 UTC (permalink / raw)
To: cluster-devel.redhat.com
Wrap the calls to lgfs2_rgrps_init() in an rgrps_init() function which
uses libblkid to probe the alignment of the device before calling
lgfs2_rgrps_init().
Signed-off-by: Andrew Price <anprice@redhat.com>
---
gfs2/mkfs/main_grow.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 49 insertions(+), 2 deletions(-)
diff --git a/gfs2/mkfs/main_grow.c b/gfs2/mkfs/main_grow.c
index 88a7f15..adceeef 100644
--- a/gfs2/mkfs/main_grow.c
+++ b/gfs2/mkfs/main_grow.c
@@ -19,6 +19,7 @@
#include <stdarg.h>
#include <linux/types.h>
#include <linux/falloc.h>
+#include <blkid.h>
#include <libintl.h>
#define _(String) gettext(String)
@@ -132,6 +133,52 @@ static void decode_arguments(int argc, char *argv[], struct gfs2_sbd *sdp)
}
}
+static lgfs2_rgrps_t rgrps_init(struct gfs2_sbd *sdp)
+{
+ int ret;
+ int error;
+ uint64_t al_base = 0;
+ uint64_t al_off = 0;
+ struct stat st;
+ blkid_probe pr = blkid_new_probe();
+ if (pr == NULL || blkid_probe_set_device(pr, sdp->device_fd, 0, 0) != 0
+ || blkid_probe_enable_superblocks(pr, TRUE) != 0
+ || blkid_probe_enable_partitions(pr, TRUE) != 0) {
+ fprintf(stderr, _("Failed to create probe\n"));
+ return NULL;
+ }
+
+ error = fstat(sdp->device_fd, &st);
+ if (error < 0) {
+ fprintf(stderr, _("fstat failed\n"));
+ return NULL;
+ }
+
+ if (!S_ISREG(st.st_mode) && blkid_probe_enable_topology(pr, TRUE) != 0) {
+ fprintf(stderr, _("Failed to create probe\n"));
+ return NULL;
+ }
+
+ ret = blkid_do_fullprobe(pr);
+ if (ret == 0 && !S_ISREG(st.st_mode)) {
+ blkid_topology tp = blkid_probe_get_topology(pr);
+ if (tp != NULL) {
+ unsigned long min_io_sz = blkid_topology_get_minimum_io_size(tp);
+ unsigned long opt_io_sz = blkid_topology_get_optimal_io_size(tp);
+ unsigned long phy_sector_sz = blkid_topology_get_physical_sector_size(tp);
+ if ((min_io_sz > phy_sector_sz) &&
+ (opt_io_sz > phy_sector_sz)) {
+ al_base = opt_io_sz / sdp->bsize;
+ al_off = min_io_sz / sdp->bsize;
+ }
+
+ }
+ }
+
+ blkid_free_probe(pr);
+ return lgfs2_rgrps_init(sdp->bsize, sdp->device.length, al_base, al_off);
+}
+
/**
* Calculate the size of the filesystem
* Reads the lists of resource groups in order to work out where the last block
@@ -363,7 +410,7 @@ void main_grow(int argc, char *argv[])
perror(_("Could not read master directory"));
exit(EXIT_FAILURE);
}
- rgs = lgfs2_rgrps_init(sdp->bsize, sdp->device.length, 0, 0);
+ rgs = rgrps_init(sdp);
if (rgs == NULL) {
perror(_("Could not initialise resource groups"));
error = -1;
@@ -388,7 +435,7 @@ void main_grow(int argc, char *argv[])
/* We're done with the old rgs now that we have the fssize and rg count */
lgfs2_rgrps_free(&rgs);
/* Now lets set up the new ones with alignment and all */
- rgs = lgfs2_rgrps_init(sdp->bsize, sdp->device.length, 0, 0);
+ rgs = rgrps_init(sdp);
if (rgs == NULL) {
perror(_("Could not initialise new resource groups"));
error = -1;
--
1.8.5.3
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [Cluster-devel] [PATCH 00/14] gfs2_grow and libgfs2 rgrp API improvements
2014-04-03 15:12 [Cluster-devel] [PATCH 00/14] gfs2_grow and libgfs2 rgrp API improvements Andrew Price
` (13 preceding siblings ...)
2014-04-03 15:12 ` [Cluster-devel] [PATCH 14/14] gfs2_grow: Add stripe alignment Andrew Price
@ 2014-04-07 15:15 ` Bob Peterson
14 siblings, 0 replies; 16+ messages in thread
From: Bob Peterson @ 2014-04-07 15:15 UTC (permalink / raw)
To: cluster-devel.redhat.com
----- Original Message -----
> Hi,
>
> This patch set aims to do three main things:
>
> - Improve and simplify libgfs2's rgrp APIs, bringing them closer to being
> proper library code
> - Improve gfs2_grow using the new rgrp APIs for rgrp alignment and size
> calculation, larger rgrps by default, etc.
> - Fix problems in libgfs2 and the utils uncovered along the way
>
> These patches take us closer to being able to hide the implementation of the
> rgrp lists (currently using osi_tree.h) within libgfs2 and decoupling so
> that many resource group sets (lgfs2_rgrps_t's) can be manipulated
> independently. Bookkeeping will eventually be done by the applications
> instead of keeping application-specific data in the gfs2_sbd structure so
> this takes us closer to being able to remove sbd.rgtree and sbd.rgcalc.
>
> Although the net diff is 284 insertions, that will be offset significantly
> once the old rgrp functions in libgfs2 can be removed (when fsck, convert
> and edit no longer use them).
>
> I've thrown various tests at this set and added one to the in-tree test
> suite. Static analysis with coverity shows 1 defect fixed and 0 added.
>
> Please review,
> Andy
>
> Andrew Price (14):
> mkfs.gfs2: Make dev a member of mkfs_opts
> libgfs2: Add lgfs2_space_for_data()
> libgfs2: Don't try to read more than IOV_MAX iovecs
> mkfs.gfs2: Fix the resource group layout strategy, again
> libgfs2: Don't call gfs2_blk2rgrpd in gfs2_set_bitmap
> libgfs2: Add abstractions for rgrp tree traversal
> libgfs2: Split out the rindex calculation from lgfs2_rgrp_append
> libgfs2: Consolidate rgrp_tree and bitstruct allocations
> libgfs2: Add a lgfs2_rindex_read_fd() function
> libgfs2: Const-ify the 'ri' argument to gfs2_rindex_out
> libgfs2: Fix off-by-one in lgfs2_rgrps_plan
> libgfs2: Stick to the (rgrp) plan in lgfs2_rindex_entry_new
> gfs2_grow: Migrate to the new resource group API
> gfs2_grow: Add stripe alignment
>
> gfs2/edit/hexedit.c | 2 +-
> gfs2/fsck/metawalk.c | 2 +-
> gfs2/fsck/pass5.c | 6 +-
> gfs2/libgfs2/buf.c | 57 ++++---
> gfs2/libgfs2/fs_bits.c | 5 +-
> gfs2/libgfs2/fs_ops.c | 30 +++-
> gfs2/libgfs2/libgfs2.h | 31 ++--
> gfs2/libgfs2/ondisk.c | 4 +-
> gfs2/libgfs2/rgrp.c | 422
> +++++++++++++++++++++++++++++++++++--------------
> gfs2/mkfs/gfs2_mkfs.h | 1 -
> gfs2/mkfs/main_grow.c | 351 +++++++++++++++++++++-------------------
> gfs2/mkfs/main_mkfs.c | 227 +++++++++++++++-----------
> tests/mkfs.at | 4 +
> 13 files changed, 713 insertions(+), 429 deletions(-)
>
> --
> 1.8.5.3
>
>
Hi,
I can't say I followed it all, but it looks like a good approach. Good job.
Regards,
Bob Peterson
Red Hat File Systems
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2014-04-07 15:15 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-04-03 15:12 [Cluster-devel] [PATCH 00/14] gfs2_grow and libgfs2 rgrp API improvements Andrew Price
2014-04-03 15:12 ` [Cluster-devel] [PATCH 01/14] mkfs.gfs2: Make dev a member of mkfs_opts Andrew Price
2014-04-03 15:12 ` [Cluster-devel] [PATCH 02/14] libgfs2: Add lgfs2_space_for_data() Andrew Price
2014-04-03 15:12 ` [Cluster-devel] [PATCH 03/14] libgfs2: Don't try to read more than IOV_MAX iovecs Andrew Price
2014-04-03 15:12 ` [Cluster-devel] [PATCH 04/14] mkfs.gfs2: Fix the resource group layout strategy, again Andrew Price
2014-04-03 15:12 ` [Cluster-devel] [PATCH 05/14] libgfs2: Don't call gfs2_blk2rgrpd in gfs2_set_bitmap Andrew Price
2014-04-03 15:12 ` [Cluster-devel] [PATCH 06/14] libgfs2: Add abstractions for rgrp tree traversal Andrew Price
2014-04-03 15:12 ` [Cluster-devel] [PATCH 07/14] libgfs2: Split out the rindex calculation from lgfs2_rgrp_append Andrew Price
2014-04-03 15:12 ` [Cluster-devel] [PATCH 08/14] libgfs2: Consolidate rgrp_tree and bitstruct allocations Andrew Price
2014-04-03 15:12 ` [Cluster-devel] [PATCH 09/14] libgfs2: Add a lgfs2_rindex_read_fd() function Andrew Price
2014-04-03 15:12 ` [Cluster-devel] [PATCH 10/14] libgfs2: Const-ify the 'ri' argument to gfs2_rindex_out Andrew Price
2014-04-03 15:12 ` [Cluster-devel] [PATCH 11/14] libgfs2: Fix off-by-one in lgfs2_rgrps_plan Andrew Price
2014-04-03 15:12 ` [Cluster-devel] [PATCH 12/14] libgfs2: Stick to the (rgrp) plan in lgfs2_rindex_entry_new Andrew Price
2014-04-03 15:12 ` [Cluster-devel] [PATCH 13/14] gfs2_grow: Migrate to the new resource group API Andrew Price
2014-04-03 15:12 ` [Cluster-devel] [PATCH 14/14] gfs2_grow: Add stripe alignment Andrew Price
2014-04-07 15:15 ` [Cluster-devel] [PATCH 00/14] gfs2_grow and libgfs2 rgrp API improvements Bob Peterson
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).