cluster: RHEL511 - GFS: write vfs inode attributes to disk
by Benjamin Marzinski
Gitweb: http://git.fedorahosted.org/git/?p=cluster.git;a=commitdiff;h=b9dd9ffc8fd...
Commit: b9dd9ffc8fd3bf6baf43c2672a795a46557ad292
Parent: ffdb4297ccaf21dac543f7059c3e0208993c7f21
Author: Benjamin Marzinski <bmarzins(a)redhat.com>
AuthorDate: Thu May 29 20:05:14 2014 -0500
Committer: Benjamin Marzinski <bmarzins(a)redhat.com>
CommitterDate: Thu May 29 20:05:14 2014 -0500
GFS: write vfs inode attributes to disk
GFS wasn't ever updating mtime during mmaps to a file. This patch makes
gfs_write_inode write the vfs inode attributes out to disk, so that they
get updated when the mmap data is written back to disk. It also makes
sure that the updated vfs timestamps don't get overwritten by older gfs
ones before they can be written out.
---
gfs-kernel/src/gfs/inode.c | 15 ++++++++-----
gfs-kernel/src/gfs/ops_super.c | 43 ++++++++++++++++++++++++++++++++++++++-
2 files changed, 50 insertions(+), 8 deletions(-)
diff --git a/gfs-kernel/src/gfs/inode.c b/gfs-kernel/src/gfs/inode.c
index 454366a..52b0819 100644
--- a/gfs-kernel/src/gfs/inode.c
+++ b/gfs-kernel/src/gfs/inode.c
@@ -46,7 +46,7 @@
*/
static void
-inode_attr_in(struct gfs_inode *ip, struct inode *inode)
+inode_attr_in(struct gfs_inode *ip, struct inode *inode, int force)
{
unsigned int mode;
@@ -93,9 +93,12 @@ inode_attr_in(struct gfs_inode *ip, struct inode *inode)
inode->i_uid = ip->i_di.di_uid;
inode->i_gid = ip->i_di.di_gid;
i_size_write(inode, ip->i_di.di_size);
- inode->i_atime.tv_sec = ip->i_di.di_atime;
- inode->i_mtime.tv_sec = ip->i_di.di_mtime;
- inode->i_ctime.tv_sec = ip->i_di.di_ctime;
+ if (force || ip->i_di.di_atime > inode->i_atime.tv_sec)
+ inode->i_atime.tv_sec = ip->i_di.di_atime;
+ if (force || ip->i_di.di_mtime > inode->i_mtime.tv_sec)
+ inode->i_mtime.tv_sec = ip->i_di.di_mtime;
+ if (force || ip->i_di.di_ctime > inode->i_ctime.tv_sec)
+ inode->i_ctime.tv_sec = ip->i_di.di_ctime;
inode->i_atime.tv_nsec = inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = 0;
inode->i_blocks = ip->i_di.di_blocks <<
(ip->i_sbd->sd_sb.sb_bsize_shift - GFS_BASIC_BLOCK_SHIFT);
@@ -125,7 +128,7 @@ gfs_inode_attr_in(struct gfs_inode *ip)
inode = gfs_iget(ip, NO_CREATE);
if (inode) {
- inode_attr_in(ip, inode);
+ inode_attr_in(ip, inode, 0);
iput(inode);
}
@@ -185,7 +188,7 @@ gfs_iget(struct gfs_inode *ip, int create)
if (!tmp)
return NULL;
- inode_attr_in(ip, tmp);
+ inode_attr_in(ip, tmp, 1);
/* Attach GFS-specific ops vectors */
if (ip->i_di.di_type == GFS_FILE_REG) {
diff --git a/gfs-kernel/src/gfs/ops_super.c b/gfs-kernel/src/gfs/ops_super.c
index c111a2e..10dbff7 100644
--- a/gfs-kernel/src/gfs/ops_super.c
+++ b/gfs-kernel/src/gfs/ops_super.c
@@ -39,6 +39,7 @@
#include "super.h"
#include "sys.h"
#include "mount.h"
+#include "trans.h"
/**
* gfs_write_inode - Make sure the inode is stable on the disk
@@ -51,14 +52,52 @@
static int
gfs_write_inode(struct inode *inode, int sync)
{
+ int ret = 0;
struct gfs_inode *ip = get_v2ip(inode);
+ struct buffer_head *dibh;
+ struct gfs_holder i_gh;
+ int need_unlock = 0;
+
+ if (!ip)
+ return 0;
atomic_inc(&ip->i_sbd->sd_ops_super);
- if (ip && sync)
+ if (current->flags & PF_MEMALLOC || get_transaction)
+ goto do_flush;
+
+ if (!gfs_glock_is_locked_by_me(ip->i_gl)) {
+ ret = gfs_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh);
+ if (ret)
+ goto do_flush;
+ need_unlock = 1;
+ }
+ else if (!gfs_glock_is_held_excl(ip->i_gl))
+ goto do_flush;
+ /* Trans may require:
+ one dinode block. */
+ ret = gfs_trans_begin(ip->i_sbd, 1, 0);
+ if (ret)
+ goto do_unlock;
+
+ ret = gfs_get_inode_buffer(ip, &dibh);
+ if (ret == 0) {
+ gfs_inode_attr_out(ip);
+ gfs_trans_add_bh(ip->i_gl, dibh);
+ gfs_dinode_out(&ip->i_di, dibh->b_data);
+ brelse(dibh);
+ }
+
+ gfs_trans_end(ip->i_sbd);
+
+do_unlock:
+ if (need_unlock)
+ gfs_glock_dq_uninit(&i_gh);
+do_flush:
+ if (sync)
gfs_log_flush_glock(ip->i_gl, 0);
- return 0;
+ return ret;
}
/**
9 years, 10 months
cluster: RHEL6 - gfs2_edit: Add a savemeta file metadata header
by Andrew Price
Gitweb: http://git.fedorahosted.org/git/?p=cluster.git;a=commitdiff;h=a0e022ff141...
Commit: a0e022ff14116bc6323222a8acd3ca9a894b4974
Parent: 3edb19cd844028885baa643d7b118860b2e7a186
Author: Andrew Price <anprice(a)redhat.com>
AuthorDate: Fri May 16 23:46:12 2014 +0100
Committer: Andrew Price <anprice(a)redhat.com>
CommitterDate: Tue May 27 14:22:23 2014 +0100
gfs2_edit: Add a savemeta file metadata header
Previously 'gfs2_edit savemeta' just saved blocks into the file and any
characterisation of the contents had to be calculated by reading the
gfs2 structures out of it. Add a metadata header to savemeta output
files which initially holds the original fs size and a file creation
time, leaving some room to spare for future fields to be added.
Resolves: rhbz#1081523
Signed-off-by: Andrew Price <anprice(a)redhat.com>
---
gfs2/edit/savemeta.c | 97 ++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 87 insertions(+), 10 deletions(-)
diff --git a/gfs2/edit/savemeta.c b/gfs2/edit/savemeta.c
index 30320f0..27480cb 100644
--- a/gfs2/edit/savemeta.c
+++ b/gfs2/edit/savemeta.c
@@ -17,6 +17,7 @@
#include <sys/time.h>
#include <linux/gfs2_ondisk.h>
#include <zlib.h>
+#include <time.h>
#include "osi_list.h"
#include "gfs2hex.h"
@@ -27,6 +28,17 @@
#define DFT_SAVE_FILE "/tmp/gfsmeta.XXXXXX"
#define MAX_JOURNALS_SAVED 256
+/* Header for the savemeta output file */
+struct savemeta_header {
+#define SAVEMETA_MAGIC (0x01171970)
+ uint32_t sh_magic;
+#define SAVEMETA_FORMAT (1)
+ uint32_t sh_format; /* In case we want to change the layout */
+ uint64_t sh_time; /* When savemeta was run */
+ uint64_t sh_fs_bytes; /* Size of the fs */
+ uint8_t __reserved[104];
+};
+
struct saved_metablock {
uint64_t blk;
uint16_t siglen; /* significant data length */
@@ -633,6 +645,51 @@ static int next_rg_freemeta(struct gfs2_sbd *sdp, struct rgrp_tree *rgd,
return 0;
}
+static int save_header(struct metafd *mfd, uint64_t fsbytes)
+{
+ struct savemeta_header smh = {
+ .sh_magic = cpu_to_be32(SAVEMETA_MAGIC),
+ .sh_format = cpu_to_be32(SAVEMETA_FORMAT),
+ .sh_time = cpu_to_be64(time(NULL)),
+ .sh_fs_bytes = cpu_to_be64(fsbytes)
+ };
+
+ if (savemetawrite(mfd, (char *)(&smh), sizeof(smh)) != sizeof(smh))
+ return -1;
+ return 0;
+}
+
+static int read_header(gzFile gzin_fd, struct savemeta_header *smh)
+{
+ size_t rs;
+ struct savemeta_header smh_be = {0};
+
+ rs = gzread(gzin_fd, &smh_be, sizeof(smh_be));
+ if (rs == -1) {
+ perror("Failed to read savemeta file header");
+ return -1;
+ }
+ if (rs != sizeof(smh_be))
+ return 1;
+
+ smh->sh_magic = be32_to_cpu(smh_be.sh_magic);
+ smh->sh_format = be32_to_cpu(smh_be.sh_format);
+ smh->sh_time = be64_to_cpu(smh_be.sh_time);
+ smh->sh_fs_bytes = be64_to_cpu(smh_be.sh_fs_bytes);
+
+ return 0;
+}
+
+static int check_header(struct savemeta_header *smh)
+{
+ if (smh->sh_magic != SAVEMETA_MAGIC || smh->sh_format > SAVEMETA_FORMAT)
+ return -1;
+ printf("Savemeta file format %"PRIu32"\n", smh->sh_format);
+ printf("Created %s\n", ctime((time_t *)&smh->sh_time));
+ printf("File system size %s\n", anthropomorphize(smh->sh_fs_bytes));
+ return 0;
+}
+
void savemeta(char *out_fn, int saveoption, int gziplevel)
{
int rgcount;
@@ -641,6 +698,7 @@ void savemeta(char *out_fn, int saveoption, int gziplevel)
struct metafd mfd;
int sane;
struct osi_node *n, *next = NULL;
+ int err = 0;
sbd.md.journals = 1;
@@ -704,8 +762,14 @@ void savemeta(char *out_fn, int saveoption, int gziplevel)
fflush(stdout);
get_journal_inode_blocks();
+ /* Write the savemeta file header */
+ err = save_header(&mfd, sbd.fssize * sbd.bsize);
+ if (err) {
+ perror("Failed to write metadata file header");
+ exit(1);
+ }
/* Save off the superblock */
- save_block(sbd.device_fd, &mfd, 0x10 * (4096 / sbd.bsize));
+ save_block(sbd.device_fd, &mfd, GFS2_SB_ADDR * GFS2_BASIC_BLOCK / sbd.bsize);
/* If this is gfs1, save off the rindex because it's not
part of the file system as it is in gfs2. */
if (sbd.gfs1) {
@@ -785,8 +849,8 @@ void savemeta(char *out_fn, int saveoption, int gziplevel)
exit(0);
}
-static int restore_data(int fd, gzFile *gzin_fd, int printblocksonly,
- int find_highblk)
+static int restore_data(int fd, gzFile gzin_fd, int printblocksonly,
+ int find_highblk, const int startpos)
{
size_t rs;
uint64_t buf64, writes = 0, highest_valid_block = 0;
@@ -798,21 +862,21 @@ static int restore_data(int fd, gzFile *gzin_fd, int printblocksonly,
if (!printblocksonly)
lseek(fd, 0, SEEK_SET);
- gzseek(gzin_fd, 0, SEEK_SET);
+ gzseek(gzin_fd, startpos, SEEK_SET);
rs = gzread(gzin_fd, rdbuf, sizeof(rdbuf));
if (rs != sizeof(rdbuf)) {
fprintf(stderr, "Error: File is too small.\n");
return -1;
}
- for (pos = 0; pos < sizeof(rdbuf) - sizeof(uint64_t) - sizeof(uint16_t);
+ for (pos = startpos; pos < startpos + sizeof(rdbuf) - sizeof(uint64_t) - sizeof(uint16_t);
pos++) {
if (!memcmp(&rdbuf[pos + sizeof(uint64_t) + sizeof(uint16_t)],
gfs_superblock_id, sizeof(gfs_superblock_id))) {
break;
}
}
- if (pos == sizeof(rdbuf) - sizeof(uint64_t) - sizeof(uint16_t))
- pos = 0;
+ if (pos == startpos + sizeof(rdbuf) - sizeof(uint64_t) - sizeof(uint16_t))
+ pos = startpos;
if (gzseek(gzin_fd, pos, SEEK_SET) != pos) {
fprintf(stderr, "bad seek: %s from %s:%d: "
"offset %lld (0x%llx)\n", strerror(errno),
@@ -952,7 +1016,7 @@ static int restore_data(int fd, gzFile *gzin_fd, int printblocksonly,
}
if (!printblocksonly && !find_highblk)
warm_fuzzy_stuff(sbd.fssize, TRUE);
- if (find_highblk) {
+ if (find_highblk && startpos == 0) {
printf("File system size: %lld (0x%llx) blocks, aka %sB\n",
(unsigned long long)highest_valid_block,
(unsigned long long)highest_valid_block,
@@ -974,6 +1038,8 @@ void restoremeta(const char *in_fn, const char *out_device,
{
int error;
gzFile gzfd;
+ int startpos = 0;
+ struct savemeta_header smh = {0};
termlines = 0;
if (!in_fn)
@@ -997,9 +1063,20 @@ void restoremeta(const char *in_fn, const char *out_device,
if (!savedata)
die("Can't allocate memory for the restore operation.\n");
+ gzseek(gzfd, 0, SEEK_SET);
+ error = read_header(gzfd, &smh);
+ if (error < 0) {
+ exit(1);
+ } else if (check_header(&smh) != 0) {
+ printf("No valid file header found. Falling back to old format...\n");
+ gzseek(gzfd, 0, SEEK_SET);
+ } else if (error == 0) {
+ startpos = sizeof(smh);
+ }
+
blks_saved = 0;
- restore_data(sbd.device_fd, gzfd, printblocksonly, 1);
- error = restore_data(sbd.device_fd, gzfd, printblocksonly, 0);
+ restore_data(sbd.device_fd, gzfd, printblocksonly, 1, startpos);
+ error = restore_data(sbd.device_fd, gzfd, printblocksonly, 0, startpos);
printf("File %s %s %s.\n", in_fn,
(printblocksonly ? "print" : "restore"),
(error ? "error" : "successful"));
9 years, 10 months
cluster: RHEL510 - gfs2_edit: Add a savemeta file metadata header
by Andrew Price
Gitweb: http://git.fedorahosted.org/git/?p=cluster.git;a=commitdiff;h=9b8c4c92602...
Commit: 9b8c4c9260218d63e453a1b39ac7a4402cf4c208
Parent: 0654d2fe9d7d23c716c2ef5b272659aa646af1aa
Author: Andrew Price <anprice(a)redhat.com>
AuthorDate: Fri May 16 23:46:12 2014 +0100
Committer: Andrew Price <anprice(a)redhat.com>
CommitterDate: Fri May 23 14:47:48 2014 +0100
gfs2_edit: Add a savemeta file metadata header
Previously 'gfs2_edit savemeta' just saved blocks into the file and any
characterisation of the contents had to be calculated by reading the
gfs2 structures out of it. Add a metadata header to savemeta output
files which initially holds the original fs size and a file creation
time, leaving some room to spare for future fields to be added.
Resolves: rhbz#1100803
Signed-off-by: Andrew Price <anprice(a)redhat.com>
---
gfs2/edit/savemeta.c | 99 +++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 89 insertions(+), 10 deletions(-)
diff --git a/gfs2/edit/savemeta.c b/gfs2/edit/savemeta.c
index 337d98a..9dac8a8 100644
--- a/gfs2/edit/savemeta.c
+++ b/gfs2/edit/savemeta.c
@@ -30,6 +30,7 @@
#include <sys/time.h>
#include <linux/gfs2_ondisk.h>
#include <zlib.h>
+#include <time.h>
#include "osi_list.h"
#include "gfs2hex.h"
@@ -40,6 +41,17 @@
#define DFT_SAVE_FILE "/tmp/gfsmeta.XXXXXX"
#define MAX_JOURNALS_SAVED 256
+/* Header for the savemeta output file */
+struct savemeta_header {
+#define SAVEMETA_MAGIC (0x01171970)
+ uint32_t sh_magic;
+#define SAVEMETA_FORMAT (1)
+ uint32_t sh_format; /* In case we want to change the layout */
+ uint64_t sh_time; /* When savemeta was run */
+ uint64_t sh_fs_bytes; /* Size of the fs */
+ uint8_t __reserved[104];
+};
+
struct saved_metablock {
uint64_t blk;
uint16_t siglen; /* significant data length */
@@ -639,6 +651,51 @@ static int next_rg_freemeta(struct gfs2_sbd *sdp, struct rgrp_tree *rgd,
return 0;
}
+static int save_header(struct metafd *mfd, uint64_t fsbytes)
+{
+ struct savemeta_header smh = {
+ .sh_magic = cpu_to_be32(SAVEMETA_MAGIC),
+ .sh_format = cpu_to_be32(SAVEMETA_FORMAT),
+ .sh_time = cpu_to_be64(time(NULL)),
+ .sh_fs_bytes = cpu_to_be64(fsbytes)
+ };
+
+ if (savemetawrite(mfd, (char *)(&smh), sizeof(smh)) != sizeof(smh))
+ return -1;
+ return 0;
+}
+
+static int read_header(gzFile gzin_fd, struct savemeta_header *smh)
+{
+ size_t rs;
+ struct savemeta_header smh_be = {0};
+
+ rs = gzread(gzin_fd, &smh_be, sizeof(smh_be));
+ if (rs == -1) {
+ perror("Failed to read savemeta file header");
+ return -1;
+ }
+ if (rs != sizeof(smh_be))
+ return 1;
+
+ smh->sh_magic = be32_to_cpu(smh_be.sh_magic);
+ smh->sh_format = be32_to_cpu(smh_be.sh_format);
+ smh->sh_time = be64_to_cpu(smh_be.sh_time);
+ smh->sh_fs_bytes = be64_to_cpu(smh_be.sh_fs_bytes);
+
+ return 0;
+}
+
+static int check_header(struct savemeta_header *smh)
+{
+ if (smh->sh_magic != SAVEMETA_MAGIC || smh->sh_format > SAVEMETA_FORMAT)
+ return -1;
+ printf("Savemeta file format %"PRIu32"\n", smh->sh_format);
+ printf("Created %s\n", ctime((time_t *)&smh->sh_time));
+ printf("File system size %s\n", anthropomorphize(smh->sh_fs_bytes));
+ return 0;
+}
+
void savemeta(char *out_fn, int saveoption, int gziplevel)
{
int slow;
@@ -647,6 +704,9 @@ void savemeta(char *out_fn, int saveoption, int gziplevel)
struct gfs2_buffer_head *lbh;
struct rgrp_tree *last_rgd, *prev_rgd;
struct metafd mfd;
+ int sane;
+ struct osi_node *n, *next = NULL;
+ int err = 0;
slow = (saveoption == 1);
sbd.md.journals = 1;
@@ -739,8 +799,14 @@ void savemeta(char *out_fn, int saveoption, int gziplevel)
if (!slow) {
struct osi_node *n, *next = NULL;
+ /* Write the savemeta file header */
+ err = save_header(&mfd, sbd.fssize * sbd.bsize);
+ if (err) {
+ perror("Failed to write metadata file header");
+ exit(1);
+ }
/* Save off the superblock */
- save_block(sbd.device_fd, &mfd, 0x10 * (4096 / sbd.bsize));
+ save_block(sbd.device_fd, &mfd, GFS2_SB_ADDR * GFS2_BASIC_BLOCK / sbd.bsize);
/* If this is gfs1, save off the rindex because it's not
part of the file system as it is in gfs2. */
if (gfs1) {
@@ -827,8 +893,8 @@ void savemeta(char *out_fn, int saveoption, int gziplevel)
exit(0);
}
-static int restore_data(int fd, gzFile *gzin_fd, int printblocksonly,
- int find_highblk)
+static int restore_data(int fd, gzFile gzin_fd, int printblocksonly,
+ int find_highblk, const int startpos)
{
size_t rs;
uint64_t buf64, writes = 0, highest_valid_block = 0;
@@ -840,21 +906,21 @@ static int restore_data(int fd, gzFile *gzin_fd, int printblocksonly,
if (!printblocksonly)
do_lseek(fd, 0);
- gzseek(gzin_fd, 0, SEEK_SET);
+ gzseek(gzin_fd, startpos, SEEK_SET);
rs = gzread(gzin_fd, rdbuf, sizeof(rdbuf));
if (rs != sizeof(rdbuf)) {
fprintf(stderr, "Error: File is too small.\n");
return -1;
}
- for (pos = 0; pos < sizeof(rdbuf) - sizeof(uint64_t) - sizeof(uint16_t);
+ for (pos = startpos; pos < startpos + sizeof(rdbuf) - sizeof(uint64_t) - sizeof(uint16_t);
pos++) {
if (!memcmp(&rdbuf[pos + sizeof(uint64_t) + sizeof(uint16_t)],
gfs_superblock_id, sizeof(gfs_superblock_id))) {
break;
}
}
- if (pos == sizeof(rdbuf) - sizeof(uint64_t) - sizeof(uint16_t))
- pos = 0;
+ if (pos == startpos + sizeof(rdbuf) - sizeof(uint64_t) - sizeof(uint16_t))
+ pos = startpos;
if (gzseek(gzin_fd, pos, SEEK_SET) != pos) {
fprintf(stderr, "bad seek: %s from %s:%d: "
"offset %lld (0x%llx)\n", strerror(errno),
@@ -994,7 +1060,7 @@ static int restore_data(int fd, gzFile *gzin_fd, int printblocksonly,
}
if (!printblocksonly && !find_highblk)
warm_fuzzy_stuff(last_fs_block, TRUE);
- if (find_highblk) {
+ if (find_highblk && startpos == 0) {
printf("File system size: %lld (0x%llx) blocks, aka %sB\n",
(unsigned long long)highest_valid_block,
(unsigned long long)highest_valid_block,
@@ -1016,6 +1082,8 @@ void restoremeta(const char *in_fn, const char *out_device,
{
int error;
gzFile gzfd;
+ int startpos = 0;
+ struct savemeta_header smh = {0};
termlines = 0;
if (!in_fn)
@@ -1039,9 +1107,20 @@ void restoremeta(const char *in_fn, const char *out_device,
if (!savedata)
die("Can't allocate memory for the restore operation.\n");
+ gzseek(gzfd, 0, SEEK_SET);
+ error = read_header(gzfd, &smh);
+ if (error < 0) {
+ exit(1);
+ } else if (check_header(&smh) != 0) {
+ printf("No valid file header found. Falling back to old format...\n");
+ gzseek(gzfd, 0, SEEK_SET);
+ } else if (error == 0) {
+ startpos = sizeof(smh);
+ }
+
blks_saved = 0;
- restore_data(sbd.device_fd, gzfd, printblocksonly, 1);
- error = restore_data(sbd.device_fd, gzfd, printblocksonly, 0);
+ restore_data(sbd.device_fd, gzfd, printblocksonly, 1, startpos);
+ error = restore_data(sbd.device_fd, gzfd, printblocksonly, 0, startpos);
printf("File %s %s %s.\n", in_fn,
(printblocksonly ? "print" : "restore"),
(error ? "error" : "successful"));
9 years, 10 months
cluster: RHEL511 - gfs2_edit: Add a savemeta file metadata header
by Andrew Price
Gitweb: http://git.fedorahosted.org/git/?p=cluster.git;a=commitdiff;h=ffdb4297cca...
Commit: ffdb4297ccaf21dac543f7059c3e0208993c7f21
Parent: a5e527aff7b29382a546137f5eb8b48bf68b7355
Author: Andrew Price <anprice(a)redhat.com>
AuthorDate: Fri May 16 23:46:12 2014 +0100
Committer: Andrew Price <anprice(a)redhat.com>
CommitterDate: Fri May 23 11:57:40 2014 +0100
gfs2_edit: Add a savemeta file metadata header
Previously 'gfs2_edit savemeta' just saved blocks into the file and any
characterisation of the contents had to be calculated by reading the
gfs2 structures out of it. Add a metadata header to savemeta output
files which initially holds the original fs size and a file creation
time, leaving some room to spare for future fields to be added.
Resolves: rhbz#1097349
Signed-off-by: Andrew Price <anprice(a)redhat.com>
---
gfs2/edit/savemeta.c | 99 +++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 89 insertions(+), 10 deletions(-)
diff --git a/gfs2/edit/savemeta.c b/gfs2/edit/savemeta.c
index 337d98a..9dac8a8 100644
--- a/gfs2/edit/savemeta.c
+++ b/gfs2/edit/savemeta.c
@@ -30,6 +30,7 @@
#include <sys/time.h>
#include <linux/gfs2_ondisk.h>
#include <zlib.h>
+#include <time.h>
#include "osi_list.h"
#include "gfs2hex.h"
@@ -40,6 +41,17 @@
#define DFT_SAVE_FILE "/tmp/gfsmeta.XXXXXX"
#define MAX_JOURNALS_SAVED 256
+/* Header for the savemeta output file */
+struct savemeta_header {
+#define SAVEMETA_MAGIC (0x01171970)
+ uint32_t sh_magic;
+#define SAVEMETA_FORMAT (1)
+ uint32_t sh_format; /* In case we want to change the layout */
+ uint64_t sh_time; /* When savemeta was run */
+ uint64_t sh_fs_bytes; /* Size of the fs */
+ uint8_t __reserved[104];
+};
+
struct saved_metablock {
uint64_t blk;
uint16_t siglen; /* significant data length */
@@ -639,6 +651,51 @@ static int next_rg_freemeta(struct gfs2_sbd *sdp, struct rgrp_tree *rgd,
return 0;
}
+static int save_header(struct metafd *mfd, uint64_t fsbytes)
+{
+ struct savemeta_header smh = {
+ .sh_magic = cpu_to_be32(SAVEMETA_MAGIC),
+ .sh_format = cpu_to_be32(SAVEMETA_FORMAT),
+ .sh_time = cpu_to_be64(time(NULL)),
+ .sh_fs_bytes = cpu_to_be64(fsbytes)
+ };
+
+ if (savemetawrite(mfd, (char *)(&smh), sizeof(smh)) != sizeof(smh))
+ return -1;
+ return 0;
+}
+
+static int read_header(gzFile gzin_fd, struct savemeta_header *smh)
+{
+ size_t rs;
+ struct savemeta_header smh_be = {0};
+
+ rs = gzread(gzin_fd, &smh_be, sizeof(smh_be));
+ if (rs == -1) {
+ perror("Failed to read savemeta file header");
+ return -1;
+ }
+ if (rs != sizeof(smh_be))
+ return 1;
+
+ smh->sh_magic = be32_to_cpu(smh_be.sh_magic);
+ smh->sh_format = be32_to_cpu(smh_be.sh_format);
+ smh->sh_time = be64_to_cpu(smh_be.sh_time);
+ smh->sh_fs_bytes = be64_to_cpu(smh_be.sh_fs_bytes);
+
+ return 0;
+}
+
+static int check_header(struct savemeta_header *smh)
+{
+ if (smh->sh_magic != SAVEMETA_MAGIC || smh->sh_format > SAVEMETA_FORMAT)
+ return -1;
+ printf("Savemeta file format %"PRIu32"\n", smh->sh_format);
+ printf("Created %s\n", ctime((time_t *)&smh->sh_time));
+ printf("File system size %s\n", anthropomorphize(smh->sh_fs_bytes));
+ return 0;
+}
+
void savemeta(char *out_fn, int saveoption, int gziplevel)
{
int slow;
@@ -647,6 +704,9 @@ void savemeta(char *out_fn, int saveoption, int gziplevel)
struct gfs2_buffer_head *lbh;
struct rgrp_tree *last_rgd, *prev_rgd;
struct metafd mfd;
+ int sane;
+ struct osi_node *n, *next = NULL;
+ int err = 0;
slow = (saveoption == 1);
sbd.md.journals = 1;
@@ -739,8 +799,14 @@ void savemeta(char *out_fn, int saveoption, int gziplevel)
if (!slow) {
struct osi_node *n, *next = NULL;
+ /* Write the savemeta file header */
+ err = save_header(&mfd, sbd.fssize * sbd.bsize);
+ if (err) {
+ perror("Failed to write metadata file header");
+ exit(1);
+ }
/* Save off the superblock */
- save_block(sbd.device_fd, &mfd, 0x10 * (4096 / sbd.bsize));
+ save_block(sbd.device_fd, &mfd, GFS2_SB_ADDR * GFS2_BASIC_BLOCK / sbd.bsize);
/* If this is gfs1, save off the rindex because it's not
part of the file system as it is in gfs2. */
if (gfs1) {
@@ -827,8 +893,8 @@ void savemeta(char *out_fn, int saveoption, int gziplevel)
exit(0);
}
-static int restore_data(int fd, gzFile *gzin_fd, int printblocksonly,
- int find_highblk)
+static int restore_data(int fd, gzFile gzin_fd, int printblocksonly,
+ int find_highblk, const int startpos)
{
size_t rs;
uint64_t buf64, writes = 0, highest_valid_block = 0;
@@ -840,21 +906,21 @@ static int restore_data(int fd, gzFile *gzin_fd, int printblocksonly,
if (!printblocksonly)
do_lseek(fd, 0);
- gzseek(gzin_fd, 0, SEEK_SET);
+ gzseek(gzin_fd, startpos, SEEK_SET);
rs = gzread(gzin_fd, rdbuf, sizeof(rdbuf));
if (rs != sizeof(rdbuf)) {
fprintf(stderr, "Error: File is too small.\n");
return -1;
}
- for (pos = 0; pos < sizeof(rdbuf) - sizeof(uint64_t) - sizeof(uint16_t);
+ for (pos = startpos; pos < startpos + sizeof(rdbuf) - sizeof(uint64_t) - sizeof(uint16_t);
pos++) {
if (!memcmp(&rdbuf[pos + sizeof(uint64_t) + sizeof(uint16_t)],
gfs_superblock_id, sizeof(gfs_superblock_id))) {
break;
}
}
- if (pos == sizeof(rdbuf) - sizeof(uint64_t) - sizeof(uint16_t))
- pos = 0;
+ if (pos == startpos + sizeof(rdbuf) - sizeof(uint64_t) - sizeof(uint16_t))
+ pos = startpos;
if (gzseek(gzin_fd, pos, SEEK_SET) != pos) {
fprintf(stderr, "bad seek: %s from %s:%d: "
"offset %lld (0x%llx)\n", strerror(errno),
@@ -994,7 +1060,7 @@ static int restore_data(int fd, gzFile *gzin_fd, int printblocksonly,
}
if (!printblocksonly && !find_highblk)
warm_fuzzy_stuff(last_fs_block, TRUE);
- if (find_highblk) {
+ if (find_highblk && startpos == 0) {
printf("File system size: %lld (0x%llx) blocks, aka %sB\n",
(unsigned long long)highest_valid_block,
(unsigned long long)highest_valid_block,
@@ -1016,6 +1082,8 @@ void restoremeta(const char *in_fn, const char *out_device,
{
int error;
gzFile gzfd;
+ int startpos = 0;
+ struct savemeta_header smh = {0};
termlines = 0;
if (!in_fn)
@@ -1039,9 +1107,20 @@ void restoremeta(const char *in_fn, const char *out_device,
if (!savedata)
die("Can't allocate memory for the restore operation.\n");
+ gzseek(gzfd, 0, SEEK_SET);
+ error = read_header(gzfd, &smh);
+ if (error < 0) {
+ exit(1);
+ } else if (check_header(&smh) != 0) {
+ printf("No valid file header found. Falling back to old format...\n");
+ gzseek(gzfd, 0, SEEK_SET);
+ } else if (error == 0) {
+ startpos = sizeof(smh);
+ }
+
blks_saved = 0;
- restore_data(sbd.device_fd, gzfd, printblocksonly, 1);
- error = restore_data(sbd.device_fd, gzfd, printblocksonly, 0);
+ restore_data(sbd.device_fd, gzfd, printblocksonly, 1, startpos);
+ error = restore_data(sbd.device_fd, gzfd, printblocksonly, 0, startpos);
printf("File %s %s %s.\n", in_fn,
(printblocksonly ? "print" : "restore"),
(error ? "error" : "successful"));
9 years, 10 months
gfs2-utils: master - gfs2_edit: Fix parsing the savemeta -z option
by Andrew Price
Gitweb: http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=a96c74f4...
Commit: a96c74f47ec41e85a5cd6eef969d7231831a2c37
Parent: fb76fa5d14ef8e8ae77af36a20dbfa84ea29579b
Author: Andrew Price <anprice(a)redhat.com>
AuthorDate: Mon May 19 15:40:49 2014 +0100
Committer: Andrew Price <anprice(a)redhat.com>
CommitterDate: Mon May 19 15:47:29 2014 +0100
gfs2_edit: Fix parsing the savemeta -z option
Specifying -z0 instead of -z 0 could confuse gfs2_edit to the point
where it would call ftruncate on the filesystem instead of the output
file. Fix up the -z parsing function to recognise when the space is
omitted and avoid calling ftruncate on the wrong file.
Signed-off-by: Andrew Price <anprice(a)redhat.com>
---
gfs2/edit/hexedit.c | 26 ++++++++++++++++----------
tests/edit.at | 7 +++++++
2 files changed, 23 insertions(+), 10 deletions(-)
diff --git a/gfs2/edit/hexedit.c b/gfs2/edit/hexedit.c
index 53a816d..0982f7b 100644
--- a/gfs2/edit/hexedit.c
+++ b/gfs2/edit/hexedit.c
@@ -2608,19 +2608,25 @@ static void usage(void)
*/
static void getgziplevel(char *argv[], int *i)
{
+ char *opt, *arg;
char *endptr;
- (*i)++;
- if (!strcasecmp(argv[*i], "-z")) {
- (*i)++;
- errno = 0;
- gziplevel = strtol(argv[*i], &endptr, 10);
- if (errno || endptr == argv[*i] || gziplevel < 0 || gziplevel > 9) {
- fprintf(stderr, "Compression level out of range: %s\n", argv[*i]);
- exit(-1);
- }
+
+ arg = argv[1 + *i];
+ if (strncmp(arg, "-z", 2)) {
+ return;
+ } else if (arg[2] != '\0') {
+ opt = &arg[2];
} else {
- (*i)--;
+ (*i)++;
+ opt = argv[1 + *i];
+ }
+ errno = 0;
+ gziplevel = strtol(opt, &endptr, 10);
+ if (errno || endptr == opt || gziplevel < 0 || gziplevel > 9) {
+ fprintf(stderr, "Compression level out of range: %s\n", opt);
+ exit(-1);
}
+ (*i)++;
}
/* ------------------------------------------------------------------------ */
diff --git a/tests/edit.at b/tests/edit.at
index 3428d64..e2a702c 100644
--- a/tests/edit.at
+++ b/tests/edit.at
@@ -11,5 +11,12 @@ Reading resource groups...Done. File system size: 4.1023GB
GFS_TGT_REGEN
AT_CHECK([gfs2_edit restoremeta test.meta $GFS_TGT], 0, [ignore], [ignore])
AT_CHECK([fsck.gfs2 -n $GFS_TGT], 0, [ignore], [ignore])
+AT_CLEANUP
+AT_SETUP([Savemeta/restoremeta, no compression])
+GFS_TGT_REGEN
+AT_CHECK([$GFS_MKFS -p lock_nolock $GFS_TGT $(($(gfs_max_blocks 4096)/2))], 0, [ignore], [ignore])
+AT_CHECK([gfs2_edit savemeta -z0 $GFS_TGT test.meta], 0, [ignore], [ignore])
+AT_CHECK([gfs2_edit restoremeta test.meta $GFS_TGT], 0, [ignore], [ignore])
+AT_CHECK([fsck.gfs2 -n $GFS_TGT], 0, [ignore], [ignore])
AT_CLEANUP
9 years, 10 months
gfs2-utils: master - gfs2_edit: savemeta and restoremeta improvements
by Andrew Price
Gitweb: http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=fb76fa5d...
Commit: fb76fa5d14ef8e8ae77af36a20dbfa84ea29579b
Parent: e441038d5f506efe5989cd4415fdc5857ea6f033
Author: Andrew Price <anprice(a)redhat.com>
AuthorDate: Mon May 19 11:57:08 2014 +0100
Committer: Andrew Price <anprice(a)redhat.com>
CommitterDate: Mon May 19 12:07:39 2014 +0100
gfs2_edit: savemeta and restoremeta improvements
This adds various improvements to savemeta and restoremeta including:
- Made the saved_metablock buffer a flexible array to make better use of
sizeof() etc.
- Read/write saved_metablock structures with one read/write call instead
of one per field (gives a small perf improvement).
- Factor out the block restore code and split the "find highest block"
code out of restore_data.
- Print more, clearer information relating to the metadata file,
progress made and errors.
- Made global variables static, removed unused ones.
- Improved code clarity, separation of concerns.
Signed-off-by: Andrew Price <anprice(a)redhat.com>
---
gfs2/edit/savemeta.c | 474 +++++++++++++++++++++++++++-----------------------
tests/edit.at | 2 +-
2 files changed, 255 insertions(+), 221 deletions(-)
diff --git a/gfs2/edit/savemeta.c b/gfs2/edit/savemeta.c
index a10da19..e336100 100644
--- a/gfs2/edit/savemeta.c
+++ b/gfs2/edit/savemeta.c
@@ -27,7 +27,6 @@
#include "hexedit.h"
#include "libgfs2.h"
-#define BUFSIZE (4096)
#define DFT_SAVE_FILE "/tmp/gfsmeta.XXXXXX"
#define MAX_JOURNALS_SAVED 256
@@ -45,8 +44,11 @@ struct savemeta_header {
struct saved_metablock {
uint64_t blk;
uint16_t siglen; /* significant data length */
- char buf[BUFSIZE];
-};
+ char buf[];
+/* This needs to be packed because old versions of gfs2_edit read and write the
+ individual fields separately, so the hole after siglen must be eradicated
+ before the struct reflects what's on disk. */
+} __attribute__((__packed__));
struct metafd {
int fd;
@@ -55,15 +57,12 @@ struct metafd {
int gziplevel;
};
-struct saved_metablock *savedata;
-uint64_t last_reported_block, blks_saved, total_out, pct;
-uint64_t journal_blocks[MAX_JOURNALS_SAVED];
-uint64_t gfs1_journal_size = 0; /* in blocks */
-int journals_found = 0;
+static uint64_t blks_saved;
+static uint64_t journal_blocks[MAX_JOURNALS_SAVED];
+static uint64_t gfs1_journal_size = 0; /* in blocks */
+static int journals_found = 0;
int print_level = MSG_NOTICE;
-extern void read_superblock(void);
-
static int block_is_a_journal(void)
{
int j;
@@ -121,7 +120,7 @@ static const char *anthropomorphize(unsigned long long inhuman_value)
remainder = val % 1024;
val /= 1024;
}
- sprintf(out_val, "%llu.%llu%c", val, remainder, symbols[i]);
+ sprintf(out_val, "%llu.%llu%cB", val, remainder, symbols[i]);
return out_val;
}
@@ -223,8 +222,7 @@ static void warm_fuzzy_stuff(uint64_t wfsblock, int force)
{
static struct timeval tv;
static uint32_t seconds = 0;
-
- last_reported_block = wfsblock;
+
gettimeofday(&tv, NULL);
if (!seconds)
seconds = tv.tv_sec;
@@ -235,8 +233,7 @@ static void warm_fuzzy_stuff(uint64_t wfsblock, int force)
if (sbd.fssize) {
printf("\r");
percent = (wfsblock * 100) / sbd.fssize;
- printf("%llu inodes processed, %llu blocks saved "
- "(%llu%%) processed, ",
+ printf("%llu blocks processed, %llu saved (%llu%%)",
(unsigned long long)wfsblock,
(unsigned long long)blks_saved,
(unsigned long long)percent);
@@ -339,10 +336,10 @@ static int savemetaclose(struct metafd *mfd)
static int save_block(int fd, struct metafd *mfd, uint64_t blk)
{
- int blktype, blklen, outsz;
- uint16_t trailing0;
- char *p;
+ int blktype, blklen;
+ size_t outsz;
struct gfs2_buffer_head *savebh;
+ struct saved_metablock *savedata;
if (gfs2_check_range(&sbd, blk) && blk != sbd.sb_addr) {
fprintf(stderr, "\nWarning: bad block pointer '0x%llx' "
@@ -351,9 +348,7 @@ static int save_block(int fd, struct metafd *mfd, uint64_t blk)
(unsigned long long)block, (unsigned long long)block);
return 0;
}
- memset(savedata, 0, sizeof(struct saved_metablock));
savebh = bread(&sbd, blk);
- memcpy(&savedata->buf, savebh->b_data, sbd.bsize);
/* If this isn't metadata and isn't a system file, we don't want it.
Note that we're checking "block" here rather than blk. That's
@@ -365,43 +360,34 @@ static int save_block(int fd, struct metafd *mfd, uint64_t blk)
brelse(savebh);
return 0; /* Not metadata, and not system file, so skip it */
}
- trailing0 = 0;
- p = &savedata->buf[blklen - 1];
- while (*p=='\0' && trailing0 < sbd.bsize) {
- trailing0++;
- p--;
+
+ /* No need to save trailing zeroes */
+ for (; blklen > 0 && savebh->b_data[blklen - 1] == '\0'; blklen--);
+
+ if (blklen == 0) /* No significant data; skip. */
+ return 0;
+
+ outsz = sizeof(*savedata) + blklen;
+ savedata = calloc(1, outsz);
+ if (savedata == NULL) {
+ perror("Failed to save block");
+ exit(1);
}
savedata->blk = cpu_to_be64(blk);
- if (savemetawrite(mfd, &savedata->blk, sizeof(savedata->blk)) !=
- sizeof(savedata->blk)) {
- fprintf(stderr, "write error: %s from %s:%d: "
- "block %lld (0x%llx)\n", strerror(errno),
- __FUNCTION__, __LINE__,
- (unsigned long long)savedata->blk,
- (unsigned long long)savedata->blk);
- exit(-1);
- }
- outsz = blklen - trailing0;
- savedata->siglen = cpu_to_be16(outsz);
- if (savemetawrite(mfd, &savedata->siglen, sizeof(savedata->siglen)) !=
- sizeof(savedata->siglen)) {
- fprintf(stderr, "write error: %s from %s:%d: "
- "block %lld (0x%llx)\n", strerror(errno),
- __FUNCTION__, __LINE__,
- (unsigned long long)savedata->blk,
- (unsigned long long)savedata->blk);
- exit(-1);
- }
- if (savemetawrite(mfd, savedata->buf, outsz) != outsz) {
- fprintf(stderr, "write error: %s from %s:%d: "
- "block %lld (0x%llx)\n", strerror(errno),
- __FUNCTION__, __LINE__,
+ savedata->siglen = cpu_to_be16(blklen);
+ memcpy(savedata->buf, savebh->b_data, blklen);
+
+ if (savemetawrite(mfd, savedata, outsz) != outsz) {
+ fprintf(stderr, "write error: %s from %s:%d: block %lld (0x%llx)\n",
+ strerror(errno), __FUNCTION__, __LINE__,
(unsigned long long)savedata->blk,
(unsigned long long)savedata->blk);
+ free(savedata);
exit(-1);
}
- total_out += sizeof(savedata->blk) + sizeof(savedata->siglen) + outsz;
+
blks_saved++;
+ free(savedata);
brelse(savebh);
return blktype;
}
@@ -701,6 +687,7 @@ static int read_header(gzFile gzin_fd, struct savemeta_header *smh)
size_t rs;
struct savemeta_header smh_be = {0};
+ gzseek(gzin_fd, 0, SEEK_SET);
rs = gzread(gzin_fd, &smh_be, sizeof(smh_be));
if (rs == -1) {
perror("Failed to read savemeta file header");
@@ -721,8 +708,7 @@ static int check_header(struct savemeta_header *smh)
{
if (smh->sh_magic != SAVEMETA_MAGIC || smh->sh_format > SAVEMETA_FORMAT)
return -1;
- printf("Savemeta file format %"PRIu32"\n", smh->sh_format);
- printf("Created %s\n", ctime((time_t *)&smh->sh_time));
+ printf("Metadata saved at %s", ctime((time_t *)&smh->sh_time)); /* ctime() adds \n */
printf("File system size %s\n", anthropomorphize(smh->sh_fs_bytes));
return 0;
}
@@ -741,14 +727,10 @@ void savemeta(char *out_fn, int saveoption, int gziplevel)
mfd = savemetaopen(out_fn, gziplevel);
- savedata = malloc(sizeof(struct saved_metablock));
- if (!savedata)
- die("Can't allocate memory for the operation.\n");
-
lseek(sbd.device_fd, 0, SEEK_SET);
- blks_saved = total_out = last_reported_block = 0;
+ blks_saved = 0;
if (!sbd.gfs1)
- sbd.bsize = BUFSIZE;
+ sbd.bsize = GFS2_DEFAULT_BSIZE;
if (lgfs2_get_dev_info(sbd.device_fd, &sbd.dinfo)) {
perror(sbd.device_name);
exit(-1);
@@ -864,7 +846,6 @@ void savemeta(char *out_fn, int saveoption, int gziplevel)
} else {
printf("(uncompressed).\n");
}
- free(savedata);
savemetaclose(&mfd);
close(sbd.device_fd);
free(indirect);
@@ -872,174 +853,227 @@ void savemeta(char *out_fn, int saveoption, int gziplevel)
exit(0);
}
-static int restore_data(int fd, gzFile gzin_fd, int printblocksonly,
- int find_highblk, const int startpos)
+static off_t restore_init(gzFile gzfd, struct savemeta_header *smh)
{
+ int err;
+ unsigned i;
size_t rs;
- uint64_t buf64, writes = 0, highest_valid_block = 0;
- uint16_t buf16;
- int first = 1, pos, gzerr;
- char rdbuf[256];
- char gfs_superblock_id[8] = {0x01, 0x16, 0x19, 0x70,
- 0x00, 0x00, 0x00, 0x01};
-
- if (!printblocksonly)
- lseek(fd, 0, SEEK_SET);
- gzseek(gzin_fd, startpos, SEEK_SET);
- rs = gzread(gzin_fd, rdbuf, sizeof(rdbuf));
- if (rs != sizeof(rdbuf)) {
+ char buf[256];
+ off_t startpos = 0;
+ struct saved_metablock *svb;
+ struct gfs2_meta_header *sbmh;
+
+ err = read_header(gzfd, smh);
+ if (err < 0) {
+ exit(1);
+ } else if (check_header(smh) != 0) {
+ printf("No valid file header found. Falling back to old format...\n");
+ } else if (err == 0) {
+ startpos = sizeof(*smh);
+ }
+
+ gzseek(gzfd, startpos, SEEK_SET);
+ rs = gzread(gzfd, buf, sizeof(buf));
+ if (rs != sizeof(buf)) {
fprintf(stderr, "Error: File is too small.\n");
- return -1;
+ exit(1);
}
- for (pos = startpos; pos < startpos + sizeof(rdbuf) - sizeof(uint64_t) - sizeof(uint16_t);
- pos++) {
- if (!memcmp(&rdbuf[pos + sizeof(uint64_t) + sizeof(uint16_t)],
- gfs_superblock_id, sizeof(gfs_superblock_id))) {
+ /* Scan for the beginning of the file body. Required to support old formats(?). */
+ for (i = 0; i < (256 - sizeof(*svb) - sizeof(*sbmh)); i++) {
+ svb = (struct saved_metablock *)&buf[i];
+ sbmh = (struct gfs2_meta_header *)svb->buf;
+ if (sbmh->mh_magic == cpu_to_be32(GFS2_MAGIC) &&
+ sbmh->mh_type == cpu_to_be32(GFS2_METATYPE_SB))
break;
+ }
+ if (i == (sizeof(buf) - sizeof(*svb) - sizeof(*sbmh)))
+ i = 0;
+ return startpos + i; /* File offset of saved sb */
+}
+
+
+static int restore_block(gzFile gzfd, struct saved_metablock *svb, uint16_t maxlen)
+{
+ int gzerr;
+ int ret;
+ uint16_t checklen;
+ const char *errstr;
+
+ ret = gzread(gzfd, svb, sizeof(*svb));
+ if (ret < sizeof(*svb)) {
+ goto gzread_err;
+ }
+ svb->blk = be64_to_cpu(svb->blk);
+ svb->siglen = be16_to_cpu(svb->siglen);
+
+ if (sbd.fssize && svb->blk >= sbd.fssize) {
+ fprintf(stderr, "Error: File system is too small to restore this metadata.\n");
+ fprintf(stderr, "File system is %llu blocks. Restore block = %llu\n",
+ (unsigned long long)sbd.fssize, (unsigned long long)svb->blk);
+ return -1;
+ }
+
+ if (maxlen)
+ checklen = maxlen;
+ else
+ checklen = sbd.bsize;
+
+ if (checklen && svb->siglen > checklen) {
+ fprintf(stderr, "Bad record length: %u for block %"PRIu64" (0x%"PRIx64").\n",
+ svb->siglen, svb->blk, svb->blk);
+ return -1;
+ }
+
+ if (maxlen) {
+ ret = gzread(gzfd, svb + 1, svb->siglen);
+ if (ret < svb->siglen) {
+ goto gzread_err;
}
}
- if (pos == startpos + sizeof(rdbuf) - sizeof(uint64_t) - sizeof(uint16_t))
- pos = startpos;
- if (gzseek(gzin_fd, pos, SEEK_SET) != pos) {
- fprintf(stderr, "bad seek: %s from %s:%d: "
- "offset %lld (0x%llx)\n", strerror(errno),
- __FUNCTION__, __LINE__, (unsigned long long)pos,
- (unsigned long long)pos);
- exit(-1);
+
+ return 0;
+
+gzread_err:
+ if (gzeof(gzfd))
+ return 1;
+
+ errstr = gzerror(gzfd, &gzerr);
+ if (gzerr == Z_ERRNO)
+ errstr = strerror(errno);
+ fprintf(stderr, "Failed to restore block: %s\n", errstr);
+ return -1;
+}
+
+static int restore_super(gzFile gzfd, off_t pos)
+{
+ int ret;
+ struct saved_metablock *svb;
+ struct gfs2_buffer_head dummy_bh;
+ size_t len = sizeof(*svb) + sizeof(struct gfs2_sb);
+
+ svb = calloc(1, len);
+ if (svb == NULL) {
+ perror("Failed to restore super block");
+ exit(1);
}
- blks_saved = total_out = 0;
- while (TRUE) {
- struct gfs2_buffer_head dummy_bh;
+ gzseek(gzfd, pos, SEEK_SET);
+ ret = restore_block(gzfd, svb, sizeof(struct gfs2_sb));
+ if (ret == 1) {
+ fprintf(stderr, "Reached end of file while restoring superblock\n");
+ goto err;
+ } else if (ret != 0) {
+ goto err;
+ }
+
+ dummy_bh.b_data = (char *)svb->buf;
+ gfs2_sb_in(&sbd.sd_sb, &dummy_bh);
+ sbd1 = (struct gfs_sb *)&sbd.sd_sb;
+ ret = check_sb(&sbd.sd_sb);
+ if (ret < 0) {
+ fprintf(stderr,"Error: Invalid superblock data.\n");
+ goto err;
+ }
+ if (ret == 1)
+ sbd.gfs1 = 1;
+ sbd.bsize = sbd.sd_sb.sb_bsize;
+ free(svb);
+ printf("Block size is %uB\n", sbd.bsize);
+ return 0;
+err:
+ free(svb);
+ return -1;
+}
+
+static int find_highest_block(gzFile gzfd, off_t pos, uint64_t fssize)
+{
+ int err = 0;
+ uint64_t highest = 0;
+ struct saved_metablock svb = {0};
- memset(savedata, 0, sizeof(struct saved_metablock));
- rs = gzread(gzin_fd, &buf64, sizeof(uint64_t));
- if (!rs)
+ while (1) {
+ gzseek(gzfd, pos, SEEK_SET);
+ err = restore_block(gzfd, &svb, 0);
+ if (err == 1)
break;
- if (rs != sizeof(uint64_t)) {
- fprintf(stderr, "Error reading from file.\n");
- return -1;
- }
- total_out += sbd.bsize;
- savedata->blk = be64_to_cpu(buf64);
- if (!printblocksonly &&
- sbd.fssize && savedata->blk >= sbd.fssize) {
- fprintf(stderr, "Error: File system is too small to "
- "restore this metadata.\n");
- fprintf(stderr, "File system is %llu blocks, ",
- (unsigned long long)sbd.fssize);
- fprintf(stderr, "Restore block = %llu\n",
- (unsigned long long)savedata->blk);
+ if (err != 0)
return -1;
- }
- if (gzread(gzin_fd, &buf16, sizeof(uint16_t)) !=
- sizeof(uint16_t)) {
- fprintf(stderr, "read error: %s from %s:%d: "
- "block %lld (0x%llx)\n",
- gzerror(gzin_fd, &gzerr), __FUNCTION__, __LINE__,
- (unsigned long long)savedata->blk,
- (unsigned long long)savedata->blk);
- exit(-1);
- }
- savedata->siglen = be16_to_cpu(buf16);
- if (savedata->siglen > sizeof(savedata->buf)) {
- fprintf(stderr, "\nBad record length: %d for block #%llu"
- " (0x%llx).\n", savedata->siglen,
- (unsigned long long)savedata->blk,
- (unsigned long long)savedata->blk);
+
+ if (svb.blk > highest)
+ highest = svb.blk;
+ pos += sizeof(svb) + svb.siglen;
+ }
+
+ if (fssize > 0) {
+ printf("Saved file system size is %"PRIu64" (0x%"PRIx64") blocks, %s\n",
+ fssize, fssize, anthropomorphize(fssize * sbd.bsize));
+ sbd.fssize = fssize;
+ } else {
+ sbd.fssize = highest + 1;
+ }
+
+ printf("Highest saved block is %"PRIu64" (0x%"PRIx64")\n", highest, highest);
+ return 0;
+}
+
+static int restore_data(int fd, gzFile gzin_fd, off_t pos, int printonly)
+{
+ struct saved_metablock *savedata;
+ size_t insz = sizeof(*savedata) + sbd.bsize;
+ uint64_t writes = 0;
+
+ savedata = calloc(1, insz);
+ if (savedata == NULL) {
+ perror("Failed to restore data");
+ exit(1);
+ }
+
+ gzseek(gzin_fd, pos, SEEK_SET);
+ blks_saved = 0;
+ while (TRUE) {
+ int err;
+ err = restore_block(gzin_fd, savedata, sbd.bsize);
+ if (err == 1)
+ break;
+ if (err != 0) {
+ free(savedata);
return -1;
}
- if (savedata->siglen &&
- gzread(gzin_fd, savedata->buf, savedata->siglen) !=
- savedata->siglen) {
- fprintf(stderr, "read error: %s from %s:%d: "
- "block %lld (0x%llx)\n",
- gzerror(gzin_fd, &gzerr), __FUNCTION__, __LINE__,
- (unsigned long long)savedata->blk,
- (unsigned long long)savedata->blk);
- exit(-1);
- }
- if (first) {
- struct gfs2_sb bufsb;
- int ret;
-
- dummy_bh.b_data = (char *)&bufsb;
- memcpy(&bufsb, savedata->buf, sizeof(bufsb));
- gfs2_sb_in(&sbd.sd_sb, &dummy_bh);
- sbd1 = (struct gfs_sb *)&sbd.sd_sb;
- ret = check_sb(&sbd.sd_sb);
- if (ret < 0) {
- fprintf(stderr,"Error: Invalid superblock data.\n");
- return -1;
- }
- if (ret == 1)
- sbd.gfs1 = TRUE;
- sbd.bsize = sbd.sd_sb.sb_bsize;
- if (find_highblk)
- ;
- else if (!printblocksonly) {
- sbd.fssize =
- lseek(fd, 0, SEEK_END) / sbd.bsize;
- printf("There are %llu blocks of %u bytes in "
- "the destination device.\n\n",
- (unsigned long long)sbd.fssize, sbd.bsize);
- } else {
- printf("This is %s metadata\n", sbd.gfs1 ?
- "gfs (not gfs2)" : "gfs2");
- }
- first = 0;
- }
- bh = &dummy_bh;
- bh->b_data = savedata->buf;
- if (savedata->blk > highest_valid_block)
- highest_valid_block = savedata->blk;
- if (find_highblk)
- ;
- else if (printblocksonly) {
+
+ if (printonly) {
+ struct gfs2_buffer_head dummy_bh;
+ dummy_bh.b_data = savedata->buf;
+ bh = &dummy_bh;
block = savedata->blk;
- if (printblocksonly > 1 && printblocksonly == block) {
+ if (printonly > 1 && printonly == block) {
block_in_mem = block;
display(0, 0, 0, 0);
bh = NULL;
- return 0;
- } else if (printblocksonly == 1) {
- print_gfs2("%d (l=0x%x): ", blks_saved,
- savedata->siglen);
+ break;
+ } else if (printonly == 1) {
+ print_gfs2("%d (l=0x%x): ", blks_saved, savedata->siglen);
display_block_type(TRUE);
}
+ bh = NULL;
} else {
warm_fuzzy_stuff(savedata->blk, FALSE);
- if (savedata->blk >= sbd.fssize) {
- printf("\nOut of space on the destination "
- "device; quitting.\n");
- bh = NULL;
- break;
- }
+ memset(savedata->buf + savedata->siglen, 0, sbd.bsize - savedata->siglen);
if (pwrite(fd, savedata->buf, sbd.bsize, savedata->blk * sbd.bsize) != sbd.bsize) {
- fprintf(stderr, "write error: %s from "
- "%s:%d: block %lld (0x%llx)\n",
- strerror(errno), __FUNCTION__,
- __LINE__,
+ fprintf(stderr, "write error: %s from %s:%d: block %lld (0x%llx)\n",
+ strerror(errno), __FUNCTION__, __LINE__,
(unsigned long long)savedata->blk,
(unsigned long long)savedata->blk);
- exit(-1);
+ free(savedata);
+ return -1;
}
writes++;
if (writes % 1000 == 0)
fsync(fd);
}
blks_saved++;
- /* Don't leave a dangling reference to our local dummy_bh */
- bh = NULL;
- }
- if (!printblocksonly && !find_highblk)
- warm_fuzzy_stuff(sbd.fssize, TRUE);
- if (find_highblk && startpos == 0) {
- printf("File system size: %lld (0x%llx) blocks, aka %sB\n",
- (unsigned long long)highest_valid_block,
- (unsigned long long)highest_valid_block,
- anthropomorphize(highest_valid_block * sbd.bsize));
- sbd.fssize = highest_valid_block;
}
+ if (!printonly)
+ warm_fuzzy_stuff(sbd.fssize, 1);
+ free(savedata);
return 0;
}
@@ -1050,56 +1084,56 @@ static void complain(const char *complaint)
"<dest file system>\n");
}
-void restoremeta(const char *in_fn, const char *out_device,
- uint64_t printblocksonly)
+void restoremeta(const char *in_fn, const char *out_device, uint64_t printonly)
{
int error;
gzFile gzfd;
- int startpos = 0;
+ off_t pos = 0;
struct savemeta_header smh = {0};
termlines = 0;
if (!in_fn)
complain("No source file specified.");
- if (!printblocksonly && !out_device)
+ if (!printonly && !out_device)
complain("No destination file system specified.");
+
gzfd = gzopen(in_fn, "rb");
if (!gzfd)
die("Can't open source file %s: %s\n",
in_fn, strerror(errno));
- if (!printblocksonly) {
+ if (!printonly) {
sbd.device_fd = open(out_device, O_RDWR);
if (sbd.device_fd < 0)
die("Can't open destination file system %s: %s\n",
out_device, strerror(errno));
} else if (out_device) /* for printsavedmeta, the out_device is an
optional block no */
- printblocksonly = check_keywords(out_device);
- savedata = malloc(sizeof(struct saved_metablock));
- if (!savedata)
- die("Can't allocate memory for the restore operation.\n");
-
- gzseek(gzfd, 0, SEEK_SET);
- error = read_header(gzfd, &smh);
- if (error < 0) {
+ printonly = check_keywords(out_device);
+
+ pos = restore_init(gzfd, &smh);
+ error = restore_super(gzfd, pos);
+ if (error)
exit(1);
- } else if (check_header(&smh) != 0) {
- printf("No valid file header found. Falling back to old format...\n");
- gzseek(gzfd, 0, SEEK_SET);
- } else if (error == 0) {
- startpos = sizeof(smh);
+
+ printf("This is gfs%c metadata.\n", sbd.gfs1 ? '1': '2');
+
+ if (!printonly) {
+ uint64_t space = lseek(sbd.device_fd, 0, SEEK_END) / sbd.bsize;
+ printf("There are %"PRIu64" free blocks on the destination device.\n", space);
}
- blks_saved = 0;
- restore_data(sbd.device_fd, gzfd, printblocksonly, 1, startpos);
- error = restore_data(sbd.device_fd, gzfd, printblocksonly, 0, startpos);
+ error = find_highest_block(gzfd, pos, sbd.fssize);
+ if (error)
+ exit(1);
+
+ error = restore_data(sbd.device_fd, gzfd, pos, printonly);
printf("File %s %s %s.\n", in_fn,
- (printblocksonly ? "print" : "restore"),
+ (printonly ? "print" : "restore"),
(error ? "error" : "successful"));
- free(savedata);
+
gzclose(gzfd);
- if (!printblocksonly)
+ if (!printonly)
close(sbd.device_fd);
free(indirect);
exit(error);
diff --git a/tests/edit.at b/tests/edit.at
index 014d118..3428d64 100644
--- a/tests/edit.at
+++ b/tests/edit.at
@@ -6,7 +6,7 @@ GFS_TGT_REGEN
AT_CHECK([$GFS_MKFS -p lock_nolock $GFS_TGT $(($(gfs_max_blocks 4096)/2))], 0, [ignore], [ignore])
AT_CHECK([gfs2_edit savemeta $GFS_TGT test.meta > savemeta.log], 0, [ignore], [ignore])
AT_CHECK([head -2 savemeta.log], 0, [There are 2621440 blocks of 4096 bytes in the destination device.
-Reading resource groups...Done. File system size: 4.1023G
+Reading resource groups...Done. File system size: 4.1023GB
], [ignore])
GFS_TGT_REGEN
AT_CHECK([gfs2_edit restoremeta test.meta $GFS_TGT], 0, [ignore], [ignore])
9 years, 10 months
gfs2-utils: master - gfs2_edit: Add a savemeta file metadata header
by Andrew Price
Gitweb: http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=e441038d...
Commit: e441038d5f506efe5989cd4415fdc5857ea6f033
Parent: 2d5ba02f1c22e22a502b7fe3bc06bb73da52cfcf
Author: Andrew Price <anprice(a)redhat.com>
AuthorDate: Fri May 16 23:46:12 2014 +0100
Committer: Andrew Price <anprice(a)redhat.com>
CommitterDate: Fri May 16 23:46:12 2014 +0100
gfs2_edit: Add a savemeta file metadata header
Previously 'gfs2_edit savemeta' just saved blocks into the file and any
characterisation of the contents had to be calculated by reading the
gfs2 structures out of it. Add a metadata header to savemeta output
files which initially holds the original fs size and a file creation
time, leaving some room to spare for future fields to be added.
Signed-off-by: Andrew Price <anprice(a)redhat.com>
---
gfs2/edit/savemeta.c | 95 +++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 86 insertions(+), 9 deletions(-)
diff --git a/gfs2/edit/savemeta.c b/gfs2/edit/savemeta.c
index ab7f86f..a10da19 100644
--- a/gfs2/edit/savemeta.c
+++ b/gfs2/edit/savemeta.c
@@ -19,6 +19,7 @@
#include <sys/time.h>
#include <linux/gfs2_ondisk.h>
#include <zlib.h>
+#include <time.h>
#include <logging.h>
#include "osi_list.h"
@@ -30,6 +31,17 @@
#define DFT_SAVE_FILE "/tmp/gfsmeta.XXXXXX"
#define MAX_JOURNALS_SAVED 256
+/* Header for the savemeta output file */
+struct savemeta_header {
+#define SAVEMETA_MAGIC (0x01171970)
+ uint32_t sh_magic;
+#define SAVEMETA_FORMAT (1)
+ uint32_t sh_format; /* In case we want to change the layout */
+ uint64_t sh_time; /* When savemeta was run */
+ uint64_t sh_fs_bytes; /* Size of the fs */
+ uint8_t __reserved[104];
+};
+
struct saved_metablock {
uint64_t blk;
uint16_t siglen; /* significant data length */
@@ -670,6 +682,51 @@ static void save_allocated(struct rgrp_tree *rgd, struct metafd *mfd)
free(ibuf);
}
+static int save_header(struct metafd *mfd, uint64_t fsbytes)
+{
+ struct savemeta_header smh = {
+ .sh_magic = cpu_to_be32(SAVEMETA_MAGIC),
+ .sh_format = cpu_to_be32(SAVEMETA_FORMAT),
+ .sh_time = cpu_to_be64(time(NULL)),
+ .sh_fs_bytes = cpu_to_be64(fsbytes)
+ };
+
+ if (savemetawrite(mfd, (char *)(&smh), sizeof(smh)) != sizeof(smh))
+ return -1;
+ return 0;
+}
+
+static int read_header(gzFile gzin_fd, struct savemeta_header *smh)
+{
+ size_t rs;
+ struct savemeta_header smh_be = {0};
+
+ rs = gzread(gzin_fd, &smh_be, sizeof(smh_be));
+ if (rs == -1) {
+ perror("Failed to read savemeta file header");
+ return -1;
+ }
+ if (rs != sizeof(smh_be))
+ return 1;
+
+ smh->sh_magic = be32_to_cpu(smh_be.sh_magic);
+ smh->sh_format = be32_to_cpu(smh_be.sh_format);
+ smh->sh_time = be64_to_cpu(smh_be.sh_time);
+ smh->sh_fs_bytes = be64_to_cpu(smh_be.sh_fs_bytes);
+
+ return 0;
+}
+
+static int check_header(struct savemeta_header *smh)
+{
+ if (smh->sh_magic != SAVEMETA_MAGIC || smh->sh_format > SAVEMETA_FORMAT)
+ return -1;
+ printf("Savemeta file format %"PRIu32"\n", smh->sh_format);
+ printf("Created %s\n", ctime((time_t *)&smh->sh_time));
+ printf("File system size %s\n", anthropomorphize(smh->sh_fs_bytes));
+ return 0;
+}
+
void savemeta(char *out_fn, int saveoption, int gziplevel)
{
int rgcount;
@@ -678,6 +735,7 @@ void savemeta(char *out_fn, int saveoption, int gziplevel)
struct metafd mfd;
int sane;
struct osi_node *n, *next = NULL;
+ int err = 0;
sbd.md.journals = 1;
@@ -746,8 +804,14 @@ void savemeta(char *out_fn, int saveoption, int gziplevel)
get_journal_inode_blocks();
+ /* Write the savemeta file header */
+ err = save_header(&mfd, sbd.fssize * sbd.bsize);
+ if (err) {
+ perror("Failed to write metadata file header");
+ exit(1);
+ }
/* Save off the superblock */
- save_block(sbd.device_fd, &mfd, 0x10 * (4096 / sbd.bsize));
+ save_block(sbd.device_fd, &mfd, GFS2_SB_ADDR * GFS2_BASIC_BLOCK / sbd.bsize);
/* If this is gfs1, save off the rindex because it's not
part of the file system as it is in gfs2. */
if (sbd.gfs1) {
@@ -809,7 +873,7 @@ void savemeta(char *out_fn, int saveoption, int gziplevel)
}
static int restore_data(int fd, gzFile gzin_fd, int printblocksonly,
- int find_highblk)
+ int find_highblk, const int startpos)
{
size_t rs;
uint64_t buf64, writes = 0, highest_valid_block = 0;
@@ -821,21 +885,21 @@ static int restore_data(int fd, gzFile gzin_fd, int printblocksonly,
if (!printblocksonly)
lseek(fd, 0, SEEK_SET);
- gzseek(gzin_fd, 0, SEEK_SET);
+ gzseek(gzin_fd, startpos, SEEK_SET);
rs = gzread(gzin_fd, rdbuf, sizeof(rdbuf));
if (rs != sizeof(rdbuf)) {
fprintf(stderr, "Error: File is too small.\n");
return -1;
}
- for (pos = 0; pos < sizeof(rdbuf) - sizeof(uint64_t) - sizeof(uint16_t);
+ for (pos = startpos; pos < startpos + sizeof(rdbuf) - sizeof(uint64_t) - sizeof(uint16_t);
pos++) {
if (!memcmp(&rdbuf[pos + sizeof(uint64_t) + sizeof(uint16_t)],
gfs_superblock_id, sizeof(gfs_superblock_id))) {
break;
}
}
- if (pos == sizeof(rdbuf) - sizeof(uint64_t) - sizeof(uint16_t))
- pos = 0;
+ if (pos == startpos + sizeof(rdbuf) - sizeof(uint64_t) - sizeof(uint16_t))
+ pos = startpos;
if (gzseek(gzin_fd, pos, SEEK_SET) != pos) {
fprintf(stderr, "bad seek: %s from %s:%d: "
"offset %lld (0x%llx)\n", strerror(errno),
@@ -969,7 +1033,7 @@ static int restore_data(int fd, gzFile gzin_fd, int printblocksonly,
}
if (!printblocksonly && !find_highblk)
warm_fuzzy_stuff(sbd.fssize, TRUE);
- if (find_highblk) {
+ if (find_highblk && startpos == 0) {
printf("File system size: %lld (0x%llx) blocks, aka %sB\n",
(unsigned long long)highest_valid_block,
(unsigned long long)highest_valid_block,
@@ -991,6 +1055,8 @@ void restoremeta(const char *in_fn, const char *out_device,
{
int error;
gzFile gzfd;
+ int startpos = 0;
+ struct savemeta_header smh = {0};
termlines = 0;
if (!in_fn)
@@ -1014,9 +1080,20 @@ void restoremeta(const char *in_fn, const char *out_device,
if (!savedata)
die("Can't allocate memory for the restore operation.\n");
+ gzseek(gzfd, 0, SEEK_SET);
+ error = read_header(gzfd, &smh);
+ if (error < 0) {
+ exit(1);
+ } else if (check_header(&smh) != 0) {
+ printf("No valid file header found. Falling back to old format...\n");
+ gzseek(gzfd, 0, SEEK_SET);
+ } else if (error == 0) {
+ startpos = sizeof(smh);
+ }
+
blks_saved = 0;
- restore_data(sbd.device_fd, gzfd, printblocksonly, 1);
- error = restore_data(sbd.device_fd, gzfd, printblocksonly, 0);
+ restore_data(sbd.device_fd, gzfd, printblocksonly, 1, startpos);
+ error = restore_data(sbd.device_fd, gzfd, printblocksonly, 0, startpos);
printf("File %s %s %s.\n", in_fn,
(printblocksonly ? "print" : "restore"),
(error ? "error" : "successful"));
9 years, 10 months
fence-agents: master - testing: Update XML metadata for fence_zvmip
by Marek Grác
Gitweb: http://git.fedorahosted.org/git/?p=fence-agents.git;a=commitdiff;h=5a4903...
Commit: 5a490358e2b3ab10da9de3f2a20f6725c87f0476
Parent: 1d1838f4d8da8a59a9b7ad29030b3d69bc4ac07d
Author: Marek 'marx' Grac <mgrac(a)redhat.com>
AuthorDate: Wed May 21 15:37:56 2014 +0200
Committer: Marek 'marx' Grac <mgrac(a)redhat.com>
CommitterDate: Wed May 21 15:37:56 2014 +0200
testing: Update XML metadata for fence_zvmip
---
tests/data/metadata/fence_zvmip.xml | 11 +++++++----
1 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/tests/data/metadata/fence_zvmip.xml b/tests/data/metadata/fence_zvmip.xml
index 0ffab1f..e28bc1c 100644
--- a/tests/data/metadata/fence_zvmip.xml
+++ b/tests/data/metadata/fence_zvmip.xml
@@ -15,20 +15,23 @@
<parameter name="login" unique="1" required="1">
<getopt mixed="-u, --username" />
<content type="string" />
- <shortdesc lang="en">Name of authorized SMAPI user
-</shortdesc>
+ <shortdesc lang="en">Name of authorized SMAPI user</shortdesc>
</parameter>
<parameter name="passwd" unique="1" required="1">
<getopt mixed="-p, --password" />
<content type="string" />
- <shortdesc lang="en">Password of authorized SMAPI user
-</shortdesc>
+ <shortdesc lang="en">Password of authorized SMAPI user</shortdesc>
</parameter>
<parameter name="action" unique="1" required="0">
<getopt mixed="-o, --action" />
<content type="string" default="off" />
<shortdesc lang="en">Fencing action</shortdesc>
</parameter>
+ <parameter name="delay" unique="1" required="0">
+ <getopt mixed="--delay" />
+ <content type="string" default="0" />
+ <shortdesc lang="en">Time to delay fencing action in seconds</shortdesc>
+ </parameter>
<parameter name="usage" unique="1" required="0">
<getopt mixed="-h, --help" />
<content type="boolean" />
9 years, 10 months
fence-agents: master - testing: fence_zvm agent is tested for working delay function
by Marek Grác
Gitweb: http://git.fedorahosted.org/git/?p=fence-agents.git;a=commitdiff;h=1d1838...
Commit: 1d1838f4d8da8a59a9b7ad29030b3d69bc4ac07d
Parent: 260bc9c02dd7f46271dc0df438194d20656a6a5a
Author: Marek 'marx' Grac <mgrac(a)redhat.com>
AuthorDate: Wed May 21 15:35:53 2014 +0200
Committer: Marek 'marx' Grac <mgrac(a)redhat.com>
CommitterDate: Wed May 21 15:35:53 2014 +0200
testing: fence_zvm agent is tested for working delay function
also adds support for checking --delay for every C-based fence agent
---
fence/agents/zvm/Makefile.am | 4 +++-
make/agentccheck.mk | 8 ++++++++
2 files changed, 11 insertions(+), 1 deletions(-)
diff --git a/fence/agents/zvm/Makefile.am b/fence/agents/zvm/Makefile.am
index 01d551f..2439985 100644
--- a/fence/agents/zvm/Makefile.am
+++ b/fence/agents/zvm/Makefile.am
@@ -12,7 +12,9 @@ fence_zvmip_CFLAGS = -D_GNU_SOURCE
dist_man_MANS = fence_zvm.8 fence_zvmip.8
+FENCE_TEST_ARGS = -n test -a test -p test -u test
+
include $(top_srcdir)/make/agentccheck.mk
# we do not test fence_zvm because it can be compiled only on specific architecture
-check: xml-check.fence_zvmip
\ No newline at end of file
+check: xml-check.fence_zvmip delay-check.fence_zvmip
\ No newline at end of file
diff --git a/make/agentccheck.mk b/make/agentccheck.mk
index 2de9b7a..32dc160 100644
--- a/make/agentccheck.mk
+++ b/make/agentccheck.mk
@@ -12,3 +12,11 @@ xml-check.%: %
xml-upload.%: %
$(eval INPUT=$(subst xml-upload.,,$@))
./$(INPUT) -o metadata > $(DATADIR)/$(INPUT).xml
+
+# If test will fail, rerun fence agents to show problems
+delay-check.%: %
+ $(eval INPUT=$(subst delay-check.,,$@))
+ test `/usr/bin/time -f "%e" ./$(INPUT) --delay 10 $(FENCE_TEST_ARGS) -- 2>&1 |\
+ sed 's/\.//' | tail -n 1` -ge 1000 || \
+ /usr/bin/time -f "%e" ./$(INPUT) --delay 0 $(FENCE_TEST_ARGS) --
+
9 years, 10 months
fence-agents: master - fence_zvm: Add support for --delay in fence_zvm
by Marek Grác
Gitweb: http://git.fedorahosted.org/git/?p=fence-agents.git;a=commitdiff;h=260bc9...
Commit: 260bc9c02dd7f46271dc0df438194d20656a6a5a
Parent: 09ced953ea11599d3b59ebf0c038c04f82a14d18
Author: Marek 'marx' Grac <mgrac(a)redhat.com>
AuthorDate: Wed May 21 15:25:59 2014 +0200
Committer: Marek 'marx' Grac <mgrac(a)redhat.com>
CommitterDate: Wed May 21 15:25:59 2014 +0200
fence_zvm: Add support for --delay in fence_zvm
Patch by: Neale Ferguson
---
fence/agents/zvm/fence_zvm.8 | 5 ++++-
fence/agents/zvm/fence_zvm.c | 38 ++++++++++++++++++++++++++++++++++++--
fence/agents/zvm/fence_zvm.h | 1 +
fence/agents/zvm/fence_zvmip.8 | 3 +++
fence/agents/zvm/fence_zvmip.c | 26 ++++++++++++++++++++++++++
5 files changed, 70 insertions(+), 3 deletions(-)
diff --git a/fence/agents/zvm/fence_zvm.8 b/fence/agents/zvm/fence_zvm.8
index 2c54e75..0b34e2c 100644
--- a/fence/agents/zvm/fence_zvm.8
+++ b/fence/agents/zvm/fence_zvm.8
@@ -24,6 +24,9 @@ Vendor URL: http://www.sinenomine.net
\fB-o --action\fP
Fencing action: "off" - fence off device; "metadata" - display device metadata
.TP
+\fB--delay\fP \fIseconds\fP
+Time to delay fencing action in seconds
+.TP
\fB-n --plug\fP \fItarget\fP
Name of virtual machine to recycle.
.TP
@@ -31,7 +34,7 @@ Name of virtual machine to recycle.
Print out a help message describing available options, then exit.
.TP
\fB-a --ip\fP \fIsmapi Server\fP
-\fBName\fP of SMAPI server virtual machine. To be consistent with other fence agents thisname is a little misleading: it is the name of the virtual machine not its IP address or hostname.
+\fBName\fP of SMAPI server virtual machine. To be consistent with other fence agents this name is a little misleading: it is the name of the virtual machine not its IP address or hostname.
.TP
\fB--zvmsys\fP \fIz/VM System\fP
\fBName\fP of z/VM on which the SMAPI server virtual machine resides. Optional - defaults to system on which the node is running.
diff --git a/fence/agents/zvm/fence_zvm.c b/fence/agents/zvm/fence_zvm.c
index 6fbbb12..d2fb4a9 100644
--- a/fence/agents/zvm/fence_zvm.c
+++ b/fence/agents/zvm/fence_zvm.c
@@ -49,11 +49,13 @@
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#define DEFAULT_TIMEOUT 300
+#define DEFAULT_DELAY 0
static int zvm_smapi_reportError(void *, void *);
static struct option longopts[] = {
{"action", required_argument, NULL, 'o'},
+ {"delay", required_argument, NULL, 'h'},
{"help", no_argument, NULL, 'h'},
{"ip", required_argument, NULL, 'a'},
{"plug", required_argument, NULL, 'n'},
@@ -136,6 +138,12 @@ zvm_smapi_imageRecycle(zvm_driver_t *zvm)
uint32_t reqId;
int rc;
+ /*
+ * Implement any delay
+ */
+ if (zvm->delay > 0)
+ sleep(zvm->delay);
+
lInPlist = sizeof(*inPlist) + strlen(zvm->target);
inPlist = malloc(lInPlist);
if (inPlist != NULL) {
@@ -388,6 +396,13 @@ zvm_metadata()
"Fencing action");
fprintf (stdout, "\t</parameter>\n");
+ fprintf (stdout, "\t<parameter name=\"delay\" unique=\"1\" required=\"0\">\n");
+ fprintf (stdout, "\t\t<getopt mixed=\"--delay\" />\n");
+ fprintf (stdout, "\t\t<content type=\"string\" default=\"0\" />\n");
+ fprintf (stdout, "\t\t<shortdesc lang=\"en\">%s</shortdesc>\n",
+ "Time to delay fencing action in seconds");
+ fprintf (stdout, "\t</parameter>\n");
+
fprintf (stdout, "\t<parameter name=\"usage\" unique=\"1\" required=\"0\">\n");
fprintf (stdout, "\t\t<getopt mixed=\"-h, --help\" />\n");
fprintf (stdout, "\t\t<content type=\"boolean\" />\n");
@@ -466,13 +481,21 @@ get_options_stdin (zvm_driver_t *zvm)
if (*endPtr != 0) {
syslog(LOG_WARNING, "Invalid timeout value specified %s "
"defaulting to %d",
- arg, DEFAULT_TIMEOUT);
- zvm->timeOut = DEFAULT_TIMEOUT;
+ arg, DEFAULT_DELAY);
+ zvm->timeOut = DEFAULT_DELAY;
}
} else if (!strcasecmp (opt, "zvmsys")) {
lSrvNode = MIN(strlen(arg), sizeof(zvm->node));
memcpy(zvm->node, arg, lSrvNode);
continue;
+ } else if (!strcasecmp (opt, "delay")) {
+ zvm->delay = strtoul(arg, &endPtr, 10);
+ if (*endPtr != 0) {
+ syslog(LOG_WARNING, "Invalid delay value specified %s "
+ "defaulting to %d",
+ arg, DEFAULT_DELAY);
+ zvm->delay = DEFAULT_DELAY;
+ }
} else if (!strcasecmp (opt, "help")) {
fence = 2;
}
@@ -525,6 +548,15 @@ get_options(int argc, char **argv, zvm_driver_t *zvm)
zvm->timeOut = DEFAULT_TIMEOUT;
}
break;
+ case 'd' :
+ zvm->delay = strtoul(optarg, &endPtr, 10);
+ if (*endPtr != 0) {
+ syslog(LOG_WARNING, "Invalid delay value specified: %s - "
+ "defaulting to %d",
+ optarg, DEFAULT_DELAY);
+ zvm->delay = DEFAULT_DELAY;
+ }
+ break;
case 'z' :
lSrvNode = MIN(strlen(optarg), sizeof(zvm->node));
memcpy(zvm->node, optarg, lSrvNode);
@@ -546,6 +578,7 @@ usage()
fprintf(stderr,"Usage: fence_zvm [options]\n\n"
"\tWhere [options] =\n"
"\t-o --action [action] - \"off\", \"metadata\"\n"
+ "\t--delay [seconds] - Time to delay fencing action in seconds\n"
"\t-n --plug [target] - Name of virtual machine to fence\n"
"\t-a --ip [server] - Name of SMAPI IUCV Request server\n"
"\t-T --timeout [secs] - Time to wait for fence in seconds - currently ignored\n"
@@ -588,6 +621,7 @@ main(int argc, char **argv)
openlog ("fence_zvm", LOG_CONS|LOG_PID, LOG_DAEMON);
memset(&zvm, 0, sizeof(zvm));
zvm.timeOut = DEFAULT_TIMEOUT;
+ zvm.delay = DEFAULT_DELAY;
if (argc > 1)
fence = get_options(argc, argv, &zvm);
diff --git a/fence/agents/zvm/fence_zvm.h b/fence/agents/zvm/fence_zvm.h
index 0a86af3..6178fa5 100644
--- a/fence/agents/zvm/fence_zvm.h
+++ b/fence/agents/zvm/fence_zvm.h
@@ -562,6 +562,7 @@ typedef struct {
int sd;
int reason;
uint32_t timeOut;
+ uint32_t delay;
char target[9];
char authUser[9];
char authPass[9];
diff --git a/fence/agents/zvm/fence_zvmip.8 b/fence/agents/zvm/fence_zvmip.8
index 222b483..0bf91ae 100644
--- a/fence/agents/zvm/fence_zvmip.8
+++ b/fence/agents/zvm/fence_zvmip.8
@@ -24,6 +24,9 @@ Vendor URL: http://www.sinenomine.net
\fB-o --action\fP
Fencing action: "off" - fence off device; "metadata" - display device metadata
.TP
+\fB--delay\fP \fIseconds\fP
+Time to delay fencing action in seconds
+.TP
\fB-n --plug\fP \fItarget\fP
Name of target virtual machine to fence
.TP
diff --git a/fence/agents/zvm/fence_zvmip.c b/fence/agents/zvm/fence_zvmip.c
index 28c9726..f4dcd1c 100644
--- a/fence/agents/zvm/fence_zvmip.c
+++ b/fence/agents/zvm/fence_zvmip.c
@@ -48,11 +48,13 @@
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#define DEFAULT_TIMEOUT 300
+#define DEFAULT_DELAY 0
static int zvm_smapi_reportError(void *, void *);
static struct option longopts[] = {
{"action", required_argument, NULL, 'o'},
+ {"delay", required_argument, NULL, 'd'},
{"help", no_argument, NULL, 'h'},
{"ipaddr", required_argument, NULL, 'a'},
{"password", required_argument, NULL, 'p'},
@@ -142,6 +144,12 @@ zvm_smapi_imageRecycle(zvm_driver_t *zvm)
uint32_t reqId;
int rc;
+ /*
+ * Implement any delay
+ */
+ if (zvm->delay > 0)
+ sleep(zvm->delay);
+
lInPlist = sizeof(*inPlist) + sizeof(*authUser) + strlen(zvm->authUser) +
sizeof(*authPass) + strlen(zvm->authPass) + sizeof(*image) +
+ strlen(zvm->target);
@@ -487,6 +495,15 @@ get_options(int argc, char **argv, zvm_driver_t *zvm)
zvm->timeOut = DEFAULT_TIMEOUT;
}
break;
+ case 'd' :
+ zvm->delay = strtoul(optarg, &endPtr, 10);
+ if (*endPtr != 0) {
+ syslog(LOG_WARNING, "Invalid delay value specified: %s - "
+ "defaulting to %d",
+ optarg, DEFAULT_DELAY);
+ zvm->delay = DEFAULT_DELAY;
+ }
+ break;
default :
fence = 2;
}
@@ -546,6 +563,13 @@ zvm_metadata()
"Fencing action");
fprintf (stdout, "\t</parameter>\n");
+ fprintf (stdout, "\t<parameter name=\"delay\" unique=\"1\" required=\"0\">\n");
+ fprintf (stdout, "\t\t<getopt mixed=\"--delay\" />\n");
+ fprintf (stdout, "\t\t<content type=\"string\" default=\"0\" />\n");
+ fprintf (stdout, "\t\t<shortdesc lang=\"en\">%s</shortdesc>\n",
+ "Time to delay fencing action in seconds");
+ fprintf (stdout, "\t</parameter>\n");
+
fprintf (stdout, "\t<parameter name=\"usage\" unique=\"1\" required=\"0\">\n");
fprintf (stdout, "\t\t<getopt mixed=\"-h, --help\" />\n");
fprintf (stdout, "\t\t<content type=\"boolean\" />\n");
@@ -576,6 +600,7 @@ usage()
fprintf(stderr,"Usage: fence_zvmip [options]\n\n"
"\tWhere [options] =\n"
"\t-o --action [action] - \"off\", \"metadata\"\n"
+ "\t--delay [seconds] - Time to delay fencing action in seconds\n"
"\t-n --plug [target] - Name of virtual machine to fence\n"
"\t-a --ip [server] - IP Name/Address of SMAPI Server\n"
"\t-u --username [user] - Name of autorized SMAPI user\n"
@@ -629,6 +654,7 @@ main(int argc, char **argv)
openlog ("fence_zvmip", LOG_CONS|LOG_PID, LOG_DAEMON);
memset(&zvm, 0, sizeof(zvm));
zvm.timeOut = DEFAULT_TIMEOUT;
+ zvm.delay = DEFAULT_DELAY;
if (argc > 1)
fence = get_options(argc, argv, &zvm);
9 years, 10 months