[Cluster-devel] [PATCH 01/14] mkfs.gfs2: Make dev a member of mkfs_opts

2014-04-03 Thread Andrew Price
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 
---
 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

[Cluster-devel] [PATCH 08/14] libgfs2: Consolidate rgrp_tree and bitstruct allocations

2014-04-03 Thread Andrew Price
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 
---
 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)
+  

[Cluster-devel] [PATCH 05/14] libgfs2: Don't call gfs2_blk2rgrpd in gfs2_set_bitmap

2014-04-03 Thread Andrew Price
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 
---
 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_trgrp_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)
/

[Cluster-devel] [PATCH 12/14] libgfs2: Stick to the (rgrp) plan in lgfs2_rindex_entry_new

2014-04-03 Thread Andrew Price
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 
---
 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



[Cluster-devel] [PATCH 09/14] libgfs2: Add a lgfs2_rindex_read_fd() function

2014-04-03 Thread Andrew Price
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 
---
 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



[Cluster-devel] [PATCH 04/14] mkfs.gfs2: Fix the resource group layout strategy, again

2014-04-03 Thread Andrew Price
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 
---
 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->ali

[Cluster-devel] [PATCH 10/14] libgfs2: Const-ify the 'ri' argument to gfs2_rindex_out

2014-04-03 Thread Andrew Price
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 
---
 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



[Cluster-devel] [PATCH 03/14] libgfs2: Don't try to read more than IOV_MAX iovecs

2014-04-03 Thread Andrew Price
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 
---
 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



[Cluster-devel] [PATCH 11/14] libgfs2: Fix off-by-one in lgfs2_rgrps_plan

2014-04-03 Thread Andrew Price
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 
---
 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



[Cluster-devel] [PATCH 13/14] gfs2_grow: Migrate to the new resource group API

2014-04-03 Thread Andrew Price
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 
---
 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

[Cluster-devel] [PATCH 14/14] gfs2_grow: Add stripe alignment

2014-04-03 Thread Andrew Price
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 
---
 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 
 #include 
 #include 
+#include 
 #include 
 #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



[Cluster-devel] [PATCH 02/14] libgfs2: Add lgfs2_space_for_data()

2014-04-03 Thread Andrew Price
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 
---
 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



[Cluster-devel] [PATCH 07/14] libgfs2: Split out the rindex calculation from lgfs2_rgrp_append

2014-04-03 Thread Andrew Price
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 
---
 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 NUL

[Cluster-devel] [PATCH 06/14] libgfs2: Add abstractions for rgrp tree traversal

2014-04-03 Thread Andrew Price
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 
---
 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



[Cluster-devel] [PATCH 00/14] gfs2_grow and libgfs2 rgrp API improvements

2014-04-03 Thread Andrew Price
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



[Cluster-devel] [PATCH] fence_ipmilan: send empty password, if password is not entered

2014-04-03 Thread Ondrej Mular
Previously, agent stuck on password prompt from ipmitool, if password was not 
specified.

Resolves: rhbz#1083600

---
 fence/agents/ipmilan/fence_ipmilan.py | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/fence/agents/ipmilan/fence_ipmilan.py 
b/fence/agents/ipmilan/fence_ipmilan.py
index 1e52ccc..632f13d 100644
--- a/fence/agents/ipmilan/fence_ipmilan.py
+++ b/fence/agents/ipmilan/fence_ipmilan.py
@@ -91,6 +91,8 @@ def create_command(options, action):
# --password / -p
if options.has_key("--password"):
cmd += " -P " + quote(options["--password"])
+   else:
+   cmd += " -P ''"
 
# --cipher / -C
cmd += " -C " + options["--cipher"]
-- 
1.8.3.1



Re: [Cluster-devel] [PATCH] fencing: Replace printing to stderr with proper logging solution

2014-04-03 Thread Fabio M. Di Nitto
On 4/3/2014 10:58 AM, Marek Grac wrote:
> On 04/02/2014 08:14 PM, Fabio M. Di Nitto wrote:
>> On 04/02/2014 05:06 PM, Marek 'marx' Grac wrote:
>>> This patch replaces local solutions by standard python logging 
>>> module. Levels of messages is not final, it just reflects the
>>> previous state. So, debug level is available only with -v /
>>> verbose option.
>> Hi Marek,
>> 
>> are we keeping out-of-tree agents in sync too? specifically
>> fence_virt and fence_sanlock.
> This solution does not change behaviour of fence agents, it is
> more internal thing which is python based so there is no need to
> change anything else.

Right, I understand.

> After we will found out where to add logging and to which levels
> (ERROR, INFO, DEBUG) then it will be good to make other agents work
> in same way.

That´s what I care effectively. Keep it consistent across all agents.

Perhaps we should consider moving fence_sanlock and fence-virt into
fence-agents now that the fence-agents srpm generates many separated
rpm. It will make it easier to keep all features in sync across the board.

Fabio



Re: [Cluster-devel] [PATCH] fencing: Replace printing to stderr with proper logging solution

2014-04-03 Thread Marek Grac

On 04/02/2014 08:14 PM, Fabio M. Di Nitto wrote:

On 04/02/2014 05:06 PM, Marek 'marx' Grac wrote:

This patch replaces local solutions by standard python logging module. Levels 
of messages
is not final, it just reflects the previous state. So, debug level is available 
only with
-v / verbose option.

Hi Marek,

are we keeping out-of-tree agents in sync too? specifically fence_virt
and fence_sanlock.
This solution does not change behaviour of fence agents, it is more 
internal thing which is python based so there is no need to change 
anything else. After we will found out where to add logging and to which 
levels (ERROR, INFO, DEBUG) then it will be good to make other agents 
work in same way.


m,