cluster: STABLE3 - rgmanager: Clean up build warnings
by Lon Hohberger
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: e3fdd916da5ad54e37bbc457f336fb482dbe3b14
Parent: 5ed49a26ac09148993799eecae15eaa6d6623984
Author: Lon Hohberger <lhh(a)redhat.com>
AuthorDate: Wed Dec 16 12:56:43 2009 -0500
Committer: Lon Hohberger <lhh(a)redhat.com>
CommitterDate: Fri Feb 19 10:14:28 2010 -0500
rgmanager: Clean up build warnings
Signed-off-by: Lon Hohberger <lhh(a)redhat.com>
---
rgmanager/src/clulib/vft.c | 6 +++---
rgmanager/src/daemons/main.c | 1 -
2 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/rgmanager/src/clulib/vft.c b/rgmanager/src/clulib/vft.c
index 9c78a12..0113bad 100644
--- a/rgmanager/src/clulib/vft.c
+++ b/rgmanager/src/clulib/vft.c
@@ -885,7 +885,7 @@ vf_server(void *arg)
*/
int
vf_init(int my_node_id, uint16_t my_port, vf_vote_cb_t vcb,
- vf_commit_cb_t ccb, int cluster_timeout)
+ vf_commit_cb_t ccb, int _cluster_timeout)
{
struct vf_args *args;
msgctx_t *ctx;
@@ -912,8 +912,8 @@ vf_init(int my_node_id, uint16_t my_port, vf_vote_cb_t vcb,
pthread_mutex_lock(&vf_mutex);
_port = my_port;
_node_id = my_node_id;
- if (cluster_timeout)
- _vf_timeout = cluster_timeout;
+ if (_cluster_timeout)
+ _vf_timeout = _cluster_timeout;
default_vote_cb = vcb;
default_commit_cb = ccb;
pthread_mutex_unlock(&vf_mutex);
diff --git a/rgmanager/src/daemons/main.c b/rgmanager/src/daemons/main.c
index 3b73be8..4e34246 100644
--- a/rgmanager/src/daemons/main.c
+++ b/rgmanager/src/daemons/main.c
@@ -948,7 +948,6 @@ main(int argc, char **argv)
msgctx_t *local_ctx;
pthread_t th;
cman_handle_t clu = NULL;
- int cluster_timeout = 10;
while ((rv = getopt(argc, argv, "wfdN")) != EOF) {
switch (rv) {
14 years, 2 months
cluster: STABLE3 - rgmanager: Make VF timeout scale with token timeout
by Lon Hohberger
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 5ed49a26ac09148993799eecae15eaa6d6623984
Parent: f504ce0183dba5ab86ac70b56ca39399f87eb347
Author: Lon Hohberger <lhh(a)redhat.com>
AuthorDate: Wed Dec 16 12:56:43 2009 -0500
Committer: Lon Hohberger <lhh(a)redhat.com>
CommitterDate: Fri Feb 19 10:14:15 2010 -0500
rgmanager: Make VF timeout scale with token timeout
Rgmanager was not waiting long enough to account for
failures mid-state transition, allowing the possibility
for services to enter the 'failed' state erroneously.
Resolves: rhbz#548133
Signed-off-by: Lon Hohberger <lhh(a)redhat.com>
---
rgmanager/include/vf.h | 2 +-
rgmanager/src/clulib/vft.c | 7 +++++--
rgmanager/src/daemons/main.c | 22 +++++++++++++++++-----
3 files changed, 23 insertions(+), 8 deletions(-)
diff --git a/rgmanager/include/vf.h b/rgmanager/include/vf.h
index 528930c..d57b0cf 100644
--- a/rgmanager/include/vf.h
+++ b/rgmanager/include/vf.h
@@ -152,7 +152,7 @@ typedef struct _key_node {
/*
* VF Stuff. VF only talks to peers.
*/
-int vf_init(int, uint16_t, vf_vote_cb_t, vf_commit_cb_t);
+int vf_init(int, uint16_t, vf_vote_cb_t, vf_commit_cb_t, int);
int vf_invalidate(void);
int vf_shutdown(void);
diff --git a/rgmanager/src/clulib/vft.c b/rgmanager/src/clulib/vft.c
index eefba2f..9c78a12 100644
--- a/rgmanager/src/clulib/vft.c
+++ b/rgmanager/src/clulib/vft.c
@@ -27,6 +27,7 @@
static key_node_t *key_list = NULL; /** List of key nodes. */
static int _node_id = (int)-1;/** Our node ID, set with vf_init. */
static uint16_t _port = 0; /** Our daemon ID, set with vf_init. */
+static int _vf_timeout = 10;
/*
* TODO: We could make it thread safe, but this might be unnecessary work
@@ -884,7 +885,7 @@ vf_server(void *arg)
*/
int
vf_init(int my_node_id, uint16_t my_port, vf_vote_cb_t vcb,
- vf_commit_cb_t ccb)
+ vf_commit_cb_t ccb, int cluster_timeout)
{
struct vf_args *args;
msgctx_t *ctx;
@@ -911,6 +912,8 @@ vf_init(int my_node_id, uint16_t my_port, vf_vote_cb_t vcb,
pthread_mutex_lock(&vf_mutex);
_port = my_port;
_node_id = my_node_id;
+ if (cluster_timeout)
+ _vf_timeout = cluster_timeout;
default_vote_cb = vcb;
default_commit_cb = ccb;
pthread_mutex_unlock(&vf_mutex);
@@ -1223,7 +1226,7 @@ vf_write(cluster_member_list_t *membership, uint32_t flags,
* See if we have a consensus =)
*/
if ((rv = (vf_unanimous(&everyone, trans, remain,
- 5))) == VFR_OK) {
+ _vf_timeout))) == VFR_OK) {
vf_send_commit(&everyone, trans);
#ifdef DEBUG
printf("VF: Consensus reached!\n");
diff --git a/rgmanager/src/daemons/main.c b/rgmanager/src/daemons/main.c
index 885d89d..3b73be8 100644
--- a/rgmanager/src/daemons/main.c
+++ b/rgmanager/src/daemons/main.c
@@ -27,7 +27,7 @@
#ifdef WRAP_THREADS
void dump_thread_states(FILE *);
#endif
-static int configure_rgmanager(int ccsfd, int debug);
+static int configure_rgmanager(int ccsfd, int debug, int *cluster_timeout);
void set_transition_throttling(int);
void flag_shutdown(int sig);
@@ -742,7 +742,7 @@ event_loop(msgctx_t *localctx, msgctx_t *clusterctx)
if (need_reconfigure) {
need_reconfigure = 0;
- configure_rgmanager(-1, 0);
+ configure_rgmanager(-1, 0, NULL);
config_event_q();
return 0;
}
@@ -788,11 +788,12 @@ statedump(int __attribute__ ((unused)) sig)
* Configure logging based on data in cluster.conf
*/
static int
-configure_rgmanager(int ccsfd, int dbg)
+configure_rgmanager(int ccsfd, int dbg, int *token_secs)
{
char *v;
char internal = 0;
int status_child_max = 0;
+ int tmp;
if (ccsfd < 0) {
internal = 1;
@@ -803,6 +804,16 @@ configure_rgmanager(int ccsfd, int dbg)
setup_logging(ccsfd);
+ if (token_secs && ccs_get(ccsfd, "/cluster/totem/@token", &v) == 0) {
+ tmp = atoi(v);
+ if (tmp >= 1000) {
+ *token_secs = tmp / 1000;
+ if (tmp % 1000)
+ ++(*token_secs);
+ }
+ free(v);
+ }
+
if (ccs_get(ccsfd, "/cluster/rm/@transition_throttling", &v) == 0) {
set_transition_throttling(atoi(v));
free(v);
@@ -937,6 +948,7 @@ main(int argc, char **argv)
msgctx_t *local_ctx;
pthread_t th;
cman_handle_t clu = NULL;
+ int cluster_timeout = 10;
while ((rv = getopt(argc, argv, "wfdN")) != EOF) {
switch (rv) {
@@ -1018,7 +1030,7 @@ main(int argc, char **argv)
We know we're quorate. At this point, we need to
read the resource group trees from ccsd.
*/
- configure_rgmanager(-1, debug);
+ configure_rgmanager(-1, debug, &cluster_timeout);
logt_print(LOG_NOTICE, "Resource Group Manager Starting\n");
if (init_resource_groups(0, do_init) != 0) {
@@ -1063,7 +1075,7 @@ main(int argc, char **argv)
ds_key_init("rg_lockdown", 32, 10);
#else
- if (vf_init(me.cn_nodeid, port, NULL, NULL) != 0) {
+ if (vf_init(me.cn_nodeid, port, NULL, NULL, cluster_timeout) != 0) {
logt_print(LOG_CRIT, "#11: Couldn't set up VF listen socket\n");
goto out_ls;
}
14 years, 2 months
cluster: STABLE3 - Revert "qdisk: Autoconfigure default timings"
by Lon Hohberger
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: f504ce0183dba5ab86ac70b56ca39399f87eb347
Parent: 52d28f1887ddb642b316251e22f4359c7ab79302
Author: Lon Hohberger <lhh(a)redhat.com>
AuthorDate: Fri Feb 19 10:13:54 2010 -0500
Committer: Lon Hohberger <lhh(a)redhat.com>
CommitterDate: Fri Feb 19 10:13:54 2010 -0500
Revert "qdisk: Autoconfigure default timings"
This reverts commit 52d28f1887ddb642b316251e22f4359c7ab79302.
---
cman/man/qdisk.5 | 1 -
cman/qdisk/disk.h | 2 +-
cman/qdisk/main.c | 35 ++---------------------------------
3 files changed, 3 insertions(+), 35 deletions(-)
diff --git a/cman/man/qdisk.5 b/cman/man/qdisk.5
index 4d7e8e8..f578e92 100644
--- a/cman/man/qdisk.5
+++ b/cman/man/qdisk.5
@@ -211,7 +211,6 @@ This is the frequency of read/write cycles, in seconds.
\fItko\fP\fB="\fP10\fB"\fP
.in 12
This is the number of cycles a node must miss in order to be declared dead.
-The default for this number is dependent on the configured token timeout.
.in 9
\fItko_up\fP\fB="\fPX\fB"\fP
diff --git a/cman/qdisk/disk.h b/cman/qdisk/disk.h
index 8678ca7..c5b3d18 100644
--- a/cman/qdisk/disk.h
+++ b/cman/qdisk/disk.h
@@ -246,7 +246,7 @@ typedef struct {
int qc_max_error_cycles;
int qc_master; /* Master?! */
int qc_config;
- int qc_token_timeout;
+ int qc_pad;
disk_node_state_t qc_disk_status;
disk_node_state_t qc_status;
run_flag_t qc_flags;
diff --git a/cman/qdisk/main.c b/cman/qdisk/main.c
index b0fa501..eb3ab3c 100644
--- a/cman/qdisk/main.c
+++ b/cman/qdisk/main.c
@@ -24,7 +24,6 @@
#include <ccs.h>
#include <liblogthread.h>
#include "score.h"
-#include "../daemon/cman.h"
#include <sys/syslog.h>
#define LOG_DAEMON_NAME "qdiskd"
@@ -1487,36 +1486,14 @@ get_static_config_data(qd_ctx *ctx, int ccsfd)
if (ctx->qc_interval < 1)
ctx->qc_interval = 1;
}
-
- snprintf(query, sizeof(query), "/cluster/totem/@token");
- if (ccs_get(ccsfd, query, &val) == 0) {
- ctx->qc_token_timeout = atoi(val);
- free(val);
- if (ctx->qc_token_timeout < 10000) {
- logt_print(LOG_DEBUG, "Token timeout %d is too fast "
- "to use with qdiskd!\n",
- ctx->qc_token_timeout);
- }
- } else {
- ctx->qc_token_timeout = DEFAULT_TOKEN_TIMEOUT;
- }
/* Get tko */
snprintf(query, sizeof(query), "/cluster/quorumd/@tko");
if (ccs_get(ccsfd, query, &val) == 0) {
ctx->qc_tko = atoi(val);
free(val);
- } else {
- ctx->qc_tko = ((ctx->qc_token_timeout / 1000) -
- ctx->qc_interval) / 2;
- logt_print(LOG_DEBUG, "Auto-configured TKO as %d based on "
- "token=%d interval=%d\n", ctx->qc_tko,
- ctx->qc_token_timeout, ctx->qc_interval);
- }
-
- if (ctx->qc_tko < 4) {
- logt_print(LOG_ERR, "Quorum disk TKO (%d) is too low!\n",
- ctx->qc_tko);
+ if (ctx->qc_tko < 3)
+ ctx->qc_tko = 3;
}
/* Get up-tko (transition off->online) */
@@ -1550,14 +1527,6 @@ get_static_config_data(qd_ctx *ctx, int ccsfd)
}
if (ctx->qc_master_wait <= ctx->qc_tko_up)
ctx->qc_master_wait = ctx->qc_tko_up + 1;
-
- if ((ctx->qc_interval * (ctx->qc_master_wait +
- ctx->qc_upgrade_wait +
- ctx->qc_tko) * 1000) >=
- ctx->qc_token_timeout) {
- logt_print(LOG_WARNING, "Master failover too slow for "
- "configured token timeout!\n");
- }
/* Get votes */
snprintf(query, sizeof(query), "/cluster/quorumd/@votes");
14 years, 2 months
cluster: STABLE3 - qdisk: Autoconfigure default timings
by Lon Hohberger
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 52d28f1887ddb642b316251e22f4359c7ab79302
Parent: 9ba679c621535abc7fbf626fdff50377a072404d
Author: Lon Hohberger <lhh(a)redhat.com>
AuthorDate: Fri Feb 19 09:45:17 2010 -0500
Committer: Lon Hohberger <lhh(a)redhat.com>
CommitterDate: Fri Feb 19 09:45:17 2010 -0500
qdisk: Autoconfigure default timings
Signed-off-by: Lon Hohberger <lhh(a)redhat.com>
---
cman/man/qdisk.5 | 1 +
cman/qdisk/disk.h | 2 +-
cman/qdisk/main.c | 35 +++++++++++++++++++++++++++++++++--
3 files changed, 35 insertions(+), 3 deletions(-)
diff --git a/cman/man/qdisk.5 b/cman/man/qdisk.5
index f578e92..4d7e8e8 100644
--- a/cman/man/qdisk.5
+++ b/cman/man/qdisk.5
@@ -211,6 +211,7 @@ This is the frequency of read/write cycles, in seconds.
\fItko\fP\fB="\fP10\fB"\fP
.in 12
This is the number of cycles a node must miss in order to be declared dead.
+The default for this number is dependent on the configured token timeout.
.in 9
\fItko_up\fP\fB="\fPX\fB"\fP
diff --git a/cman/qdisk/disk.h b/cman/qdisk/disk.h
index c5b3d18..8678ca7 100644
--- a/cman/qdisk/disk.h
+++ b/cman/qdisk/disk.h
@@ -246,7 +246,7 @@ typedef struct {
int qc_max_error_cycles;
int qc_master; /* Master?! */
int qc_config;
- int qc_pad;
+ int qc_token_timeout;
disk_node_state_t qc_disk_status;
disk_node_state_t qc_status;
run_flag_t qc_flags;
diff --git a/cman/qdisk/main.c b/cman/qdisk/main.c
index eb3ab3c..b0fa501 100644
--- a/cman/qdisk/main.c
+++ b/cman/qdisk/main.c
@@ -24,6 +24,7 @@
#include <ccs.h>
#include <liblogthread.h>
#include "score.h"
+#include "../daemon/cman.h"
#include <sys/syslog.h>
#define LOG_DAEMON_NAME "qdiskd"
@@ -1486,14 +1487,36 @@ get_static_config_data(qd_ctx *ctx, int ccsfd)
if (ctx->qc_interval < 1)
ctx->qc_interval = 1;
}
+
+ snprintf(query, sizeof(query), "/cluster/totem/@token");
+ if (ccs_get(ccsfd, query, &val) == 0) {
+ ctx->qc_token_timeout = atoi(val);
+ free(val);
+ if (ctx->qc_token_timeout < 10000) {
+ logt_print(LOG_DEBUG, "Token timeout %d is too fast "
+ "to use with qdiskd!\n",
+ ctx->qc_token_timeout);
+ }
+ } else {
+ ctx->qc_token_timeout = DEFAULT_TOKEN_TIMEOUT;
+ }
/* Get tko */
snprintf(query, sizeof(query), "/cluster/quorumd/@tko");
if (ccs_get(ccsfd, query, &val) == 0) {
ctx->qc_tko = atoi(val);
free(val);
- if (ctx->qc_tko < 3)
- ctx->qc_tko = 3;
+ } else {
+ ctx->qc_tko = ((ctx->qc_token_timeout / 1000) -
+ ctx->qc_interval) / 2;
+ logt_print(LOG_DEBUG, "Auto-configured TKO as %d based on "
+ "token=%d interval=%d\n", ctx->qc_tko,
+ ctx->qc_token_timeout, ctx->qc_interval);
+ }
+
+ if (ctx->qc_tko < 4) {
+ logt_print(LOG_ERR, "Quorum disk TKO (%d) is too low!\n",
+ ctx->qc_tko);
}
/* Get up-tko (transition off->online) */
@@ -1527,6 +1550,14 @@ get_static_config_data(qd_ctx *ctx, int ccsfd)
}
if (ctx->qc_master_wait <= ctx->qc_tko_up)
ctx->qc_master_wait = ctx->qc_tko_up + 1;
+
+ if ((ctx->qc_interval * (ctx->qc_master_wait +
+ ctx->qc_upgrade_wait +
+ ctx->qc_tko) * 1000) >=
+ ctx->qc_token_timeout) {
+ logt_print(LOG_WARNING, "Master failover too slow for "
+ "configured token timeout!\n");
+ }
/* Get votes */
snprintf(query, sizeof(query), "/cluster/quorumd/@votes");
14 years, 2 months
cluster: STABLE3 - resource agents: Handle multiline pid files
by Marek Grác
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 9ba679c621535abc7fbf626fdff50377a072404d
Parent: 917b27d7ad45e4e4fa22bcc1e5255075aee0b49b
Author: Marek 'marx' Grac <mgrac(a)redhat.com>
AuthorDate: Wed Feb 17 12:23:07 2010 +0100
Committer: Marek 'marx' Grac <mgrac(a)redhat.com>
CommitterDate: Wed Feb 17 12:26:55 2010 +0100
resource agents: Handle multiline pid files
if the pid file contains more than 1 line (like sendmail) the
status_check_pid function returns an error.
Patch by Kaloyan Kovachev
---
rgmanager/src/resources/utils/ra-skelet.sh | 8 +++++++-
1 files changed, 7 insertions(+), 1 deletions(-)
diff --git a/rgmanager/src/resources/utils/ra-skelet.sh b/rgmanager/src/resources/utils/ra-skelet.sh
index e892656..5baaaa9 100644
--- a/rgmanager/src/resources/utils/ra-skelet.sh
+++ b/rgmanager/src/resources/utils/ra-skelet.sh
@@ -14,7 +14,13 @@ status_check_pid()
return $OCF_ERR_GENERIC
fi
- if [ ! -d /proc/`cat "$pid_file"` ]; then
+ read pid < "$pid_file"
+
+ if [ -z "$pid" ]; then
+ return $OCF_ERR_GENERIC
+ fi
+
+ if [ ! -d /proc/$pid ]; then
return $OCF_ERR_GENERIC
fi
14 years, 2 months
resource-agents: master - resource agents: Handle multiline pid files
by Marek Grác
Gitweb: http://git.fedorahosted.org/git/resource-agents.git?p=resource-agents.git...
Commit: e4eece4a2210e7dcd59a8fbc087d5992bc8808b1
Parent: 1004e18909a4a9039de835ee29034ecf42b6157d
Author: Marek 'marx' Grac <mgrac(a)redhat.com>
AuthorDate: Wed Feb 17 12:23:07 2010 +0100
Committer: Marek 'marx' Grac <mgrac(a)redhat.com>
CommitterDate: Wed Feb 17 12:23:07 2010 +0100
resource agents: Handle multiline pid files
if the pid file contains more than 1 line (like sendmail) the
status_check_pid function returns an error.
Patch by Kaloyan Kovachev
---
rgmanager/src/resources/utils/ra-skelet.sh | 8 +++++++-
1 files changed, 7 insertions(+), 1 deletions(-)
diff --git a/rgmanager/src/resources/utils/ra-skelet.sh b/rgmanager/src/resources/utils/ra-skelet.sh
index e892656..5baaaa9 100644
--- a/rgmanager/src/resources/utils/ra-skelet.sh
+++ b/rgmanager/src/resources/utils/ra-skelet.sh
@@ -14,7 +14,13 @@ status_check_pid()
return $OCF_ERR_GENERIC
fi
- if [ ! -d /proc/`cat "$pid_file"` ]; then
+ read pid < "$pid_file"
+
+ if [ -z "$pid" ]; then
+ return $OCF_ERR_GENERIC
+ fi
+
+ if [ ! -d /proc/$pid ]; then
return $OCF_ERR_GENERIC
fi
14 years, 2 months
cluster: STABLE3 - logrotate: fix logrotate default actions and set sane defaults
by Fabio M. Di Nitto
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 917b27d7ad45e4e4fa22bcc1e5255075aee0b49b
Parent: 504c2ce76cf1043a9d5303f32fe52806168d5726
Author: Fabio M. Di Nitto <fdinitto(a)redhat.com>
AuthorDate: Wed Feb 17 09:13:13 2010 +0100
Committer: Fabio M. Di Nitto <fdinitto(a)redhat.com>
CommitterDate: Wed Feb 17 09:13:13 2010 +0100
logrotate: fix logrotate default actions and set sane defaults
Fixes rhbz#565907
Signed-off-by: Fabio M. Di Nitto <fdinitto(a)redhat.com>
---
doc/cluster.logrotate.in | 7 ++++---
1 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/doc/cluster.logrotate.in b/doc/cluster.logrotate.in
index df7d94c..bd55cce 100644
--- a/doc/cluster.logrotate.in
+++ b/doc/cluster.logrotate.in
@@ -1,8 +1,9 @@
@LOGDIR@/*log {
missingok
compress
- notifempty
+ copytruncate
daily
- rotate 7
- create 0600 root root
+ rotate 31
+ minsize 2048
+ notifempty
}
14 years, 2 months
gfs2-utils: master - gfs2_convert: gfs2_convert doesn't convert jdata files correctly
by Abhijith Das
Gitweb: http://git.fedorahosted.org/git/gfs2-utils.git?p=gfs2-utils.git;a=commitd...
Commit: 4cf278d3f53b4330d5aaed82c8d9a004fd7d319e
Parent: 8390aba13d23264c8abefb067d0d640581ed350a
Author: Abhijith Das <adas(a)redhat.com>
AuthorDate: Tue Feb 16 17:32:51 2010 -0600
Committer: Abhijith Das <adas(a)redhat.com>
CommitterDate: Tue Feb 16 17:41:02 2010 -0600
gfs2_convert: gfs2_convert doesn't convert jdata files correctly
This patch implements the conversion of data-journaled
files from gfs1 to gfs2. It reads all the blocks of a
file in memory while it operates and speed of execution
depends on block size of the original fs, how much
memory is on the machine and the number of files and
their sizes
rhbz#545602
---
gfs2/convert/gfs2_convert.c | 292 ++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 287 insertions(+), 5 deletions(-)
diff --git a/gfs2/convert/gfs2_convert.c b/gfs2/convert/gfs2_convert.c
index 3bd42ad..97d00cb 100644
--- a/gfs2/convert/gfs2_convert.c
+++ b/gfs2/convert/gfs2_convert.c
@@ -582,6 +582,282 @@ out:
return error;
}
+static void jdata_mp_gfs1_to_gfs2(struct gfs2_sbd *sbp, int gfs1_h, int gfs2_h,
+ struct metapath *gfs1mp, struct metapath *gfs2mp,
+ unsigned int *len, uint64_t dinode_size)
+{
+ uint64_t offset;
+ int h;
+ uint64_t gfs1factor[GFS2_MAX_META_HEIGHT];
+ uint64_t gfs2factor[GFS2_MAX_META_HEIGHT];
+
+ /* figure out multiplication factors for each height - gfs1 */
+ memset(&gfs1factor, 0, sizeof(gfs1factor));
+ gfs1factor[gfs1_h - 1] = sbp->bsize - sizeof(struct gfs2_meta_header);
+ for (h = gfs1_h - 1; h > 0; h--)
+ gfs1factor[h - 1] = gfs1factor[h] * sbp->sd_inptrs;
+
+ /* figure out multiplication factors for each height - gfs2 */
+ memset(&gfs2factor, 0, sizeof(gfs2factor));
+ gfs2factor[gfs2_h] = 1ull;
+ gfs2factor[gfs2_h - 1] = sbp->bsize;
+ for (h = gfs2_h - 1; h > 0; h--)
+ gfs2factor[h - 1] = gfs2factor[h] * gfs2_inptrs;
+
+ /* Convert from gfs1 to an offset */
+ offset = 0;
+ for (h = 0; h < gfs1_h; h++)
+ offset += (gfs1mp->mp_list[h] * gfs1factor[h]);
+
+ if (dinode_size - offset < *len)
+ *len = dinode_size - offset;
+
+ /* Convert from an offset back to gfs2 */
+ memset(gfs2mp, 0, sizeof(*gfs2mp));
+ for (h = 0; h <= gfs2_h; h++) {
+ /* Can't use do_div here because the factors are too large. */
+ gfs2mp->mp_list[h] = offset / gfs2factor[h];
+ offset %= gfs2factor[h];
+ }
+}
+
+static void fix_jdatatree(struct gfs2_sbd *sbp, struct gfs2_inode *ip,
+ struct blocklist *blk, char *srcptr,
+ unsigned int size)
+{
+ uint64_t block;
+ struct gfs2_buffer_head *bh;
+ unsigned int amount, ptramt;
+ int h, copied = 0, new = 0;
+ struct gfs2_meta_header mh;
+
+ mh.mh_magic = GFS2_MAGIC;
+ mh.mh_type = GFS2_METATYPE_IN;
+ mh.mh_format = GFS2_FORMAT_IN;
+
+ /* This condition should never arise.
+ We're always dealing with unstuffed inodes */
+ if (!ip->i_di.di_height)
+ unstuff_dinode(ip);
+
+ ptramt = blk->mp.mp_list[blk->height];
+ amount = size;
+
+ while (copied < size) {
+ bh = ip->i_bh;
+ /* First, build up the metatree */
+ for (h = 0; h < blk->height; h++) {
+ lookup_block(ip, ip->i_bh, h, &blk->mp, 1, &new,
+ &block);
+ if (bh != ip->i_bh)
+ brelse(bh);
+ if (!block)
+ break;
+
+ bh = bread(sbp, block);
+ if (new)
+ memset(bh->b_data, 0, sbp->bsize);
+ if (h < (blk->height - 1))
+ gfs2_meta_header_out(&mh, bh);
+ }
+
+ if (amount > sbp->bsize - ptramt)
+ amount = sbp->bsize - ptramt;
+
+ memcpy(bh->b_data + ptramt, (char *)srcptr, amount);
+ srcptr += amount;
+ bmodified(bh);
+ if (bh != ip->i_bh)
+ brelse(bh);
+
+ copied += amount;
+
+ if (ptramt + amount >= sbp->bsize) {
+ /* advance to the next metablock */
+ blk->mp.mp_list[blk->height] += amount;
+ for (h = blk->height; h > 0; h--) {
+ if (blk->mp.mp_list[h] >= gfs2_inptrs) {
+ blk->mp.mp_list[h] = 0;
+ blk->mp.mp_list[h - 1]++;
+ continue;
+ }
+ break;
+ }
+ }
+ amount = size - copied;
+ ptramt = 0;
+ }
+}
+
+static int adjust_jdata_inode(struct gfs2_sbd *sbp, struct gfs2_inode *ip)
+{
+ uint32_t gfs2_hgt;
+ struct gfs2_buffer_head *bh;
+ osi_list_t *tmp, *x;
+ int h, header_size, bufsize, ptrnum;
+ uint64_t *ptr1, block;
+ uint64_t dinode_size;
+ int error = 0, di_height;
+ struct blocklist blocks, *blk, *newblk;
+ struct metapath gfs2mp;
+ struct gfs2_buffer_head *dibh = ip->i_bh;
+
+ /* Don't have to worry about things with stuffed inodes */
+ if (ip->i_di.di_height == 0)
+ return 0;
+
+ osi_list_init(&blocks.list);
+
+ /* Add the dinode block to the blocks list */
+ blk = malloc(sizeof(struct blocklist));
+ if (!blk) {
+ log_crit("Error: Can't allocate memory"
+ " for indirect block fix.\n");
+ return -1;
+ }
+ memset(blk, 0, sizeof(*blk));
+ /* allocate a buffer to hold the pointers or data */
+ bufsize = sbp->bsize - sizeof(struct gfs2_meta_header);
+ blk->block = dibh->b_blocknr;
+ /*
+ * blk->ptrbuf either contains
+ * a) diptrs (for height=0)
+ * b) inptrs (for height=1 to di_height - 1)
+ * c) data for height = di_height
+ */
+ blk->ptrbuf = malloc(bufsize);
+ if (!blk->ptrbuf) {
+ log_crit("Error: Can't allocate memory"
+ " for file conversion.\n");
+ free(blk);
+ return -1;
+ }
+ memset(blk->ptrbuf, 0, bufsize);
+ /* Fill in the pointers from the dinode buffer */
+ memcpy(blk->ptrbuf, dibh->b_data + sizeof(struct gfs_dinode),
+ sbp->bsize - sizeof(struct gfs_dinode));
+ /* Zero out the pointers so we can fill them in later. */
+ memset(dibh->b_data + sizeof(struct gfs_dinode), 0,
+ sbp->bsize - sizeof(struct gfs_dinode));
+ osi_list_add_prev(&blk->list, &blocks.list);
+
+ /* Now run the metadata chain and build lists of all data/metadata blocks */
+ osi_list_foreach(tmp, &blocks.list) {
+ blk = osi_list_entry(tmp, struct blocklist, list);
+
+ if (blk->height >= ip->i_di.di_height)
+ continue;
+
+ header_size = (blk->height > 0 ? sizeof(struct gfs_indirect) :
+ sizeof(struct gfs_dinode));
+
+ for (ptr1 = (uint64_t *)blk->ptrbuf, ptrnum = 0;
+ ptrnum < sbp->sd_inptrs; ptr1++, ptrnum++) {
+ if (!*ptr1)
+ continue;
+
+ block = be64_to_cpu(*ptr1);
+
+ newblk = malloc(sizeof(struct blocklist));
+ if (!newblk) {
+ log_crit("Error: Can't allocate memory"
+ " for indirect block fix.\n");
+ error = -1;
+ goto out;
+ }
+ memset(newblk, 0, sizeof(*newblk));
+ newblk->ptrbuf = malloc(bufsize);
+ if (!newblk->ptrbuf) {
+ log_crit("Error: Can't allocate memory"
+ " for file conversion.\n");
+ free(newblk);
+ goto out;
+ }
+ memset(newblk->ptrbuf, 0, bufsize);
+ newblk->block = block;
+ newblk->height = blk->height + 1;
+ /* Build the metapointer list from our predecessors */
+ for (h = 0; h < blk->height; h++)
+ newblk->mp.mp_list[h] = blk->mp.mp_list[h];
+ newblk->mp.mp_list[h] = ptrnum;
+ /* Queue it to be processed later on in the loop. */
+ osi_list_add_prev(&newblk->list, &blocks.list);
+
+ bh = bread(sbp, block);
+ if (newblk->height == ip->i_di.di_height) {
+ /* read in the jdata block */
+ memcpy(newblk->ptrbuf, bh->b_data +
+ sizeof(struct gfs2_meta_header), bufsize);
+ /* Zero the buffer so we can fill it in later */
+ memset(bh->b_data + sizeof(struct gfs2_meta_header), 0,
+ bufsize);
+ } else {
+ /* read the new metadata block's pointers */
+ memcpy(newblk->ptrbuf, bh->b_data +
+ sizeof(struct gfs_indirect),
+ sbp->bsize - sizeof(struct gfs_indirect));
+ /* Zero the buffer so we can fill it in later */
+ memset(bh->b_data + sizeof(struct gfs_indirect), 0,
+ sbp->bsize - sizeof(struct gfs_indirect));
+ }
+ bmodified(bh);
+ brelse(bh);
+ /* Free the block so we can reuse it. This allows us to
+ convert a "full" file system. */
+ ip->i_di.di_blocks--;
+ gfs2_free_block(sbp, block);
+ }
+ }
+ /* The gfs2 height may be different. We need to rebuild the
+ metadata tree to the gfs2 height. */
+ gfs2_hgt = calc_gfs2_tree_height(ip, ip->i_di.di_size);
+ /* Save off the size because we're going to empty the contents
+ and add the data blocks back in later. */
+ dinode_size = ip->i_di.di_size;
+ ip->i_di.di_size = 0ULL;
+ di_height = ip->i_di.di_height;
+ ip->i_di.di_height = 0;
+
+ /* Now run through the block list a second time. If the block
+ is a data block, rewrite the data to the gfs2 offset. */
+ osi_list_foreach_safe(tmp, &blocks.list, x) {
+ unsigned int len;
+
+ blk = osi_list_entry(tmp, struct blocklist, list);
+ /* If it's not a data block at the highest level */
+ if (blk->height != di_height) {
+ osi_list_del(tmp);
+ free(blk->ptrbuf);
+ free(blk);
+ continue;
+ }
+ len = bufsize;
+ jdata_mp_gfs1_to_gfs2(sbp, di_height, gfs2_hgt, &blk->mp, &gfs2mp, &len, dinode_size);
+ memcpy(&blk->mp, &gfs2mp, sizeof(struct metapath));
+ blk->height -= di_height - gfs2_hgt;
+ if (len)
+ fix_jdatatree(sbp, ip, blk, blk->ptrbuf, len);
+ osi_list_del(tmp);
+ free(blk->ptrbuf);
+ free(blk);
+ }
+ ip->i_di.di_size = dinode_size;
+
+ /* Set the new dinode height, which may or may not have changed. */
+ /* The caller will take it from the ip and write it to the buffer */
+ ip->i_di.di_height = gfs2_hgt;
+ return 0;
+
+out:
+ while (!osi_list_empty(&blocks.list)) {
+ blk = osi_list_entry(tmp, struct blocklist, list);
+ osi_list_del(&blocks.list);
+ free(blk->ptrbuf);
+ free(blk);
+ }
+ return error;
+}
+
/* ------------------------------------------------------------------------- */
/* adjust_inode - change an inode from gfs1 to gfs2 */
/* */
@@ -653,13 +929,19 @@ static int adjust_inode(struct gfs2_sbd *sbp, struct gfs2_buffer_head *bh)
/* ----------------------------------------------------------- */
if (inode_was_gfs1) {
struct gfs_dinode *gfs1_dinode_struct;
+ int ret = 0;
gfs1_dinode_struct = (struct gfs_dinode *)&inode->i_di;
inode->i_di.di_goal_meta = inode->i_di.di_goal_data;
inode->i_di.di_goal_data = 0; /* make sure the upper 32b are 0 */
inode->i_di.di_goal_data = gfs1_dinode_struct->di_goal_dblk;
inode->i_di.di_generation = 0;
- if (adjust_indirect_blocks(sbp, inode))
+ if (!(inode->i_di.di_mode & S_IFDIR) &&
+ inode->i_di.di_flags & GFS2_DIF_JDATA)
+ ret = adjust_jdata_inode(sbp, inode);
+ else
+ ret = adjust_indirect_blocks(sbp, inode);
+ if (ret)
return -1;
}
@@ -711,7 +993,7 @@ static int inode_renumber(struct gfs2_sbd *sbp, uint64_t root_inode_addr)
fflush(stdout);
}
/* Get the next metadata block. Break out if we reach the end. */
- /* We have to check all metadata blocks because the bitmap may */
+ /* We have to check all metadata blocks because the bitmap may */
/* be "11" (used meta) for both inodes and indirect blocks. */
/* We need to process the inodes and change the indirect blocks */
/* to have a bitmap type of "01" (data). */
@@ -723,9 +1005,9 @@ static int inode_renumber(struct gfs2_sbd *sbp, uint64_t root_inode_addr)
sbp->sd_sb.sb_root_dir.no_formal_ino = sbp->md.next_inum;
}
bh = bread(sbp, block);
- if (!gfs2_check_meta(bh, GFS_METATYPE_DI)) /* if it is an dinode */
+ if (!gfs2_check_meta(bh, GFS_METATYPE_DI)) {/* if it is an dinode */
error = adjust_inode(sbp, bh);
- else { /* It's metadata, but not an inode, so fix the bitmap. */
+ } else { /* It's metadata, but not an inode, so fix the bitmap. */
int blk, buf_offset;
int bitmap_byte; /* byte within the bitmap to fix */
int byte_bit; /* bit within the byte */
@@ -736,7 +1018,7 @@ static int inode_renumber(struct gfs2_sbd *sbp, uint64_t root_inode_addr)
byte_bit = (block - rgd->ri.ri_data0) % GFS2_NBBY;
/* Now figure out which bitmap block the byte is on */
for (blk = 0; blk < rgd->ri.ri_length; blk++) {
- /* figure out offset of first bitmap byte for this map: */
+ /* figure out offset of first bitmap byte for this map: */
buf_offset = (blk) ? sizeof(struct gfs2_meta_header) :
sizeof(struct gfs2_rgrp);
/* if it's on this page */
14 years, 2 months
cluster: STABLE3 - gfs2_convert: gfs2_convert doesn't convert jdata files correctly
by Abhijith Das
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 504c2ce76cf1043a9d5303f32fe52806168d5726
Parent: c5f279928da14f72fac458bd2439b43ea95e66df
Author: Abhijith Das <adas(a)redhat.com>
AuthorDate: Tue Feb 16 17:32:51 2010 -0600
Committer: Abhijith Das <adas(a)redhat.com>
CommitterDate: Tue Feb 16 17:32:51 2010 -0600
gfs2_convert: gfs2_convert doesn't convert jdata files correctly
This patch implements the conversion of data-journaled
files from gfs1 to gfs2. It reads all the blocks of a
file in memory while it operates and speed of execution
depends on block size of the original fs, how much
memory is on the machine and the number of files and
their sizes
rhbz#545602
---
gfs2/convert/gfs2_convert.c | 292 ++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 287 insertions(+), 5 deletions(-)
diff --git a/gfs2/convert/gfs2_convert.c b/gfs2/convert/gfs2_convert.c
index 819399c..5e3d8f3 100644
--- a/gfs2/convert/gfs2_convert.c
+++ b/gfs2/convert/gfs2_convert.c
@@ -580,6 +580,282 @@ out:
return error;
}
+static void jdata_mp_gfs1_to_gfs2(struct gfs2_sbd *sbp, int gfs1_h, int gfs2_h,
+ struct metapath *gfs1mp, struct metapath *gfs2mp,
+ unsigned int *len, uint64_t dinode_size)
+{
+ uint64_t offset;
+ int h;
+ uint64_t gfs1factor[GFS2_MAX_META_HEIGHT];
+ uint64_t gfs2factor[GFS2_MAX_META_HEIGHT];
+
+ /* figure out multiplication factors for each height - gfs1 */
+ memset(&gfs1factor, 0, sizeof(gfs1factor));
+ gfs1factor[gfs1_h - 1] = sbp->bsize - sizeof(struct gfs2_meta_header);
+ for (h = gfs1_h - 1; h > 0; h--)
+ gfs1factor[h - 1] = gfs1factor[h] * sbp->sd_inptrs;
+
+ /* figure out multiplication factors for each height - gfs2 */
+ memset(&gfs2factor, 0, sizeof(gfs2factor));
+ gfs2factor[gfs2_h] = 1ull;
+ gfs2factor[gfs2_h - 1] = sbp->bsize;
+ for (h = gfs2_h - 1; h > 0; h--)
+ gfs2factor[h - 1] = gfs2factor[h] * gfs2_inptrs;
+
+ /* Convert from gfs1 to an offset */
+ offset = 0;
+ for (h = 0; h < gfs1_h; h++)
+ offset += (gfs1mp->mp_list[h] * gfs1factor[h]);
+
+ if (dinode_size - offset < *len)
+ *len = dinode_size - offset;
+
+ /* Convert from an offset back to gfs2 */
+ memset(gfs2mp, 0, sizeof(*gfs2mp));
+ for (h = 0; h <= gfs2_h; h++) {
+ /* Can't use do_div here because the factors are too large. */
+ gfs2mp->mp_list[h] = offset / gfs2factor[h];
+ offset %= gfs2factor[h];
+ }
+}
+
+static void fix_jdatatree(struct gfs2_sbd *sbp, struct gfs2_inode *ip,
+ struct blocklist *blk, char *srcptr,
+ unsigned int size)
+{
+ uint64_t block;
+ struct gfs2_buffer_head *bh;
+ unsigned int amount, ptramt;
+ int h, copied = 0, new = 0;
+ struct gfs2_meta_header mh;
+
+ mh.mh_magic = GFS2_MAGIC;
+ mh.mh_type = GFS2_METATYPE_IN;
+ mh.mh_format = GFS2_FORMAT_IN;
+
+ /* This condition should never arise.
+ We're always dealing with unstuffed inodes */
+ if (!ip->i_di.di_height)
+ unstuff_dinode(ip);
+
+ ptramt = blk->mp.mp_list[blk->height];
+ amount = size;
+
+ while (copied < size) {
+ bh = ip->i_bh;
+ /* First, build up the metatree */
+ for (h = 0; h < blk->height; h++) {
+ lookup_block(ip, ip->i_bh, h, &blk->mp, 1, &new,
+ &block);
+ if (bh != ip->i_bh)
+ brelse(bh);
+ if (!block)
+ break;
+
+ bh = bread(sbp, block);
+ if (new)
+ memset(bh->b_data, 0, sbp->bsize);
+ if (h < (blk->height - 1))
+ gfs2_meta_header_out(&mh, bh);
+ }
+
+ if (amount > sbp->bsize - ptramt)
+ amount = sbp->bsize - ptramt;
+
+ memcpy(bh->b_data + ptramt, (char *)srcptr, amount);
+ srcptr += amount;
+ bmodified(bh);
+ if (bh != ip->i_bh)
+ brelse(bh);
+
+ copied += amount;
+
+ if (ptramt + amount >= sbp->bsize) {
+ /* advance to the next metablock */
+ blk->mp.mp_list[blk->height] += amount;
+ for (h = blk->height; h > 0; h--) {
+ if (blk->mp.mp_list[h] >= gfs2_inptrs) {
+ blk->mp.mp_list[h] = 0;
+ blk->mp.mp_list[h - 1]++;
+ continue;
+ }
+ break;
+ }
+ }
+ amount = size - copied;
+ ptramt = 0;
+ }
+}
+
+static int adjust_jdata_inode(struct gfs2_sbd *sbp, struct gfs2_inode *ip)
+{
+ uint32_t gfs2_hgt;
+ struct gfs2_buffer_head *bh;
+ osi_list_t *tmp, *x;
+ int h, header_size, bufsize, ptrnum;
+ uint64_t *ptr1, block;
+ uint64_t dinode_size;
+ int error = 0, di_height;
+ struct blocklist blocks, *blk, *newblk;
+ struct metapath gfs2mp;
+ struct gfs2_buffer_head *dibh = ip->i_bh;
+
+ /* Don't have to worry about things with stuffed inodes */
+ if (ip->i_di.di_height == 0)
+ return 0;
+
+ osi_list_init(&blocks.list);
+
+ /* Add the dinode block to the blocks list */
+ blk = malloc(sizeof(struct blocklist));
+ if (!blk) {
+ log_crit("Error: Can't allocate memory"
+ " for indirect block fix.\n");
+ return -1;
+ }
+ memset(blk, 0, sizeof(*blk));
+ /* allocate a buffer to hold the pointers or data */
+ bufsize = sbp->bsize - sizeof(struct gfs2_meta_header);
+ blk->block = dibh->b_blocknr;
+ /*
+ * blk->ptrbuf either contains
+ * a) diptrs (for height=0)
+ * b) inptrs (for height=1 to di_height - 1)
+ * c) data for height = di_height
+ */
+ blk->ptrbuf = malloc(bufsize);
+ if (!blk->ptrbuf) {
+ log_crit("Error: Can't allocate memory"
+ " for file conversion.\n");
+ free(blk);
+ return -1;
+ }
+ memset(blk->ptrbuf, 0, bufsize);
+ /* Fill in the pointers from the dinode buffer */
+ memcpy(blk->ptrbuf, dibh->b_data + sizeof(struct gfs_dinode),
+ sbp->bsize - sizeof(struct gfs_dinode));
+ /* Zero out the pointers so we can fill them in later. */
+ memset(dibh->b_data + sizeof(struct gfs_dinode), 0,
+ sbp->bsize - sizeof(struct gfs_dinode));
+ osi_list_add_prev(&blk->list, &blocks.list);
+
+ /* Now run the metadata chain and build lists of all data/metadata blocks */
+ osi_list_foreach(tmp, &blocks.list) {
+ blk = osi_list_entry(tmp, struct blocklist, list);
+
+ if (blk->height >= ip->i_di.di_height)
+ continue;
+
+ header_size = (blk->height > 0 ? sizeof(struct gfs_indirect) :
+ sizeof(struct gfs_dinode));
+
+ for (ptr1 = (uint64_t *)blk->ptrbuf, ptrnum = 0;
+ ptrnum < sbp->sd_inptrs; ptr1++, ptrnum++) {
+ if (!*ptr1)
+ continue;
+
+ block = be64_to_cpu(*ptr1);
+
+ newblk = malloc(sizeof(struct blocklist));
+ if (!newblk) {
+ log_crit("Error: Can't allocate memory"
+ " for indirect block fix.\n");
+ error = -1;
+ goto out;
+ }
+ memset(newblk, 0, sizeof(*newblk));
+ newblk->ptrbuf = malloc(bufsize);
+ if (!newblk->ptrbuf) {
+ log_crit("Error: Can't allocate memory"
+ " for file conversion.\n");
+ free(newblk);
+ goto out;
+ }
+ memset(newblk->ptrbuf, 0, bufsize);
+ newblk->block = block;
+ newblk->height = blk->height + 1;
+ /* Build the metapointer list from our predecessors */
+ for (h = 0; h < blk->height; h++)
+ newblk->mp.mp_list[h] = blk->mp.mp_list[h];
+ newblk->mp.mp_list[h] = ptrnum;
+ /* Queue it to be processed later on in the loop. */
+ osi_list_add_prev(&newblk->list, &blocks.list);
+
+ bh = bread(sbp, block);
+ if (newblk->height == ip->i_di.di_height) {
+ /* read in the jdata block */
+ memcpy(newblk->ptrbuf, bh->b_data +
+ sizeof(struct gfs2_meta_header), bufsize);
+ /* Zero the buffer so we can fill it in later */
+ memset(bh->b_data + sizeof(struct gfs2_meta_header), 0,
+ bufsize);
+ } else {
+ /* read the new metadata block's pointers */
+ memcpy(newblk->ptrbuf, bh->b_data +
+ sizeof(struct gfs_indirect),
+ sbp->bsize - sizeof(struct gfs_indirect));
+ /* Zero the buffer so we can fill it in later */
+ memset(bh->b_data + sizeof(struct gfs_indirect), 0,
+ sbp->bsize - sizeof(struct gfs_indirect));
+ }
+ bmodified(bh);
+ brelse(bh);
+ /* Free the block so we can reuse it. This allows us to
+ convert a "full" file system. */
+ ip->i_di.di_blocks--;
+ gfs2_free_block(sbp, block);
+ }
+ }
+ /* The gfs2 height may be different. We need to rebuild the
+ metadata tree to the gfs2 height. */
+ gfs2_hgt = calc_gfs2_tree_height(ip, ip->i_di.di_size);
+ /* Save off the size because we're going to empty the contents
+ and add the data blocks back in later. */
+ dinode_size = ip->i_di.di_size;
+ ip->i_di.di_size = 0ULL;
+ di_height = ip->i_di.di_height;
+ ip->i_di.di_height = 0;
+
+ /* Now run through the block list a second time. If the block
+ is a data block, rewrite the data to the gfs2 offset. */
+ osi_list_foreach_safe(tmp, &blocks.list, x) {
+ unsigned int len;
+
+ blk = osi_list_entry(tmp, struct blocklist, list);
+ /* If it's not a data block at the highest level */
+ if (blk->height != di_height) {
+ osi_list_del(tmp);
+ free(blk->ptrbuf);
+ free(blk);
+ continue;
+ }
+ len = bufsize;
+ jdata_mp_gfs1_to_gfs2(sbp, di_height, gfs2_hgt, &blk->mp, &gfs2mp, &len, dinode_size);
+ memcpy(&blk->mp, &gfs2mp, sizeof(struct metapath));
+ blk->height -= di_height - gfs2_hgt;
+ if (len)
+ fix_jdatatree(sbp, ip, blk, blk->ptrbuf, len);
+ osi_list_del(tmp);
+ free(blk->ptrbuf);
+ free(blk);
+ }
+ ip->i_di.di_size = dinode_size;
+
+ /* Set the new dinode height, which may or may not have changed. */
+ /* The caller will take it from the ip and write it to the buffer */
+ ip->i_di.di_height = gfs2_hgt;
+ return 0;
+
+out:
+ while (!osi_list_empty(&blocks.list)) {
+ blk = osi_list_entry(tmp, struct blocklist, list);
+ osi_list_del(&blocks.list);
+ free(blk->ptrbuf);
+ free(blk);
+ }
+ return error;
+}
+
/* ------------------------------------------------------------------------- */
/* adjust_inode - change an inode from gfs1 to gfs2 */
/* */
@@ -651,13 +927,19 @@ static int adjust_inode(struct gfs2_sbd *sbp, struct gfs2_buffer_head *bh)
/* ----------------------------------------------------------- */
if (inode_was_gfs1) {
struct gfs_dinode *gfs1_dinode_struct;
+ int ret = 0;
gfs1_dinode_struct = (struct gfs_dinode *)&inode->i_di;
inode->i_di.di_goal_meta = inode->i_di.di_goal_data;
inode->i_di.di_goal_data = 0; /* make sure the upper 32b are 0 */
inode->i_di.di_goal_data = gfs1_dinode_struct->di_goal_dblk;
inode->i_di.di_generation = 0;
- if (adjust_indirect_blocks(sbp, inode))
+ if (!(inode->i_di.di_mode & S_IFDIR) &&
+ inode->i_di.di_flags & GFS2_DIF_JDATA)
+ ret = adjust_jdata_inode(sbp, inode);
+ else
+ ret = adjust_indirect_blocks(sbp, inode);
+ if (ret)
return -1;
}
@@ -709,7 +991,7 @@ static int inode_renumber(struct gfs2_sbd *sbp, uint64_t root_inode_addr)
fflush(stdout);
}
/* Get the next metadata block. Break out if we reach the end. */
- /* We have to check all metadata blocks because the bitmap may */
+ /* We have to check all metadata blocks because the bitmap may */
/* be "11" (used meta) for both inodes and indirect blocks. */
/* We need to process the inodes and change the indirect blocks */
/* to have a bitmap type of "01" (data). */
@@ -721,9 +1003,9 @@ static int inode_renumber(struct gfs2_sbd *sbp, uint64_t root_inode_addr)
sbp->sd_sb.sb_root_dir.no_formal_ino = sbp->md.next_inum;
}
bh = bread(sbp, block);
- if (!gfs2_check_meta(bh, GFS_METATYPE_DI)) /* if it is an dinode */
+ if (!gfs2_check_meta(bh, GFS_METATYPE_DI)) {/* if it is an dinode */
error = adjust_inode(sbp, bh);
- else { /* It's metadata, but not an inode, so fix the bitmap. */
+ } else { /* It's metadata, but not an inode, so fix the bitmap. */
int blk, buf_offset;
int bitmap_byte; /* byte within the bitmap to fix */
int byte_bit; /* bit within the byte */
@@ -734,7 +1016,7 @@ static int inode_renumber(struct gfs2_sbd *sbp, uint64_t root_inode_addr)
byte_bit = (block - rgd->ri.ri_data0) % GFS2_NBBY;
/* Now figure out which bitmap block the byte is on */
for (blk = 0; blk < rgd->ri.ri_length; blk++) {
- /* figure out offset of first bitmap byte for this map: */
+ /* figure out offset of first bitmap byte for this map: */
buf_offset = (blk) ? sizeof(struct gfs2_meta_header) :
sizeof(struct gfs2_rgrp);
/* if it's on this page */
14 years, 2 months
cluster: RHEL55 - gfs2_convert: gfs2_convert doesn't convert jdata files correctly
by Abhijith Das
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 4089a83a53f71dceb4a7de0487bf00c0e9dfcd42
Parent: 35a706710435104eeb5782658ca15a3179fb3e93
Author: Abhijith Das <adas(a)redhat.com>
AuthorDate: Tue Feb 16 11:57:03 2010 -0600
Committer: Abhijith Das <adas(a)redhat.com>
CommitterDate: Tue Feb 16 11:57:03 2010 -0600
gfs2_convert: gfs2_convert doesn't convert jdata files correctly
This patch implements the conversion of data-journaled
files from gfs1 to gfs2. It reads all the blocks of a
file in memory while it operates and speed of execution
depends on block size of the original fs, how much
memory is on the machine and the number of files and
their sizes
rhbz#545602
---
gfs2/convert/gfs2_convert.c | 289 ++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 284 insertions(+), 5 deletions(-)
diff --git a/gfs2/convert/gfs2_convert.c b/gfs2/convert/gfs2_convert.c
index aa039ef..5223590 100644
--- a/gfs2/convert/gfs2_convert.c
+++ b/gfs2/convert/gfs2_convert.c
@@ -601,6 +601,279 @@ out:
return error;
}
+void jdata_mp_gfs1_to_gfs2(struct gfs2_sbd *sbp, int gfs1_h, int gfs2_h,
+ struct metapath *gfs1mp, struct metapath *gfs2mp,
+ unsigned int *len, uint64_t dinode_size)
+{
+ uint64_t offset;
+ int h;
+ uint64_t gfs1factor[GFS2_MAX_META_HEIGHT];
+ uint64_t gfs2factor[GFS2_MAX_META_HEIGHT];
+
+ /* figure out multiplication factors for each height - gfs1 */
+ memset(&gfs1factor, 0, sizeof(gfs1factor));
+ gfs1factor[gfs1_h - 1] = sbp->bsize - sizeof(struct gfs2_meta_header);
+ for (h = gfs1_h - 1; h > 0; h--)
+ gfs1factor[h - 1] = gfs1factor[h] * sbp->sd_inptrs;
+
+ /* figure out multiplication factors for each height - gfs2 */
+ memset(&gfs2factor, 0, sizeof(gfs2factor));
+ gfs2factor[gfs2_h] = 1ull;
+ gfs2factor[gfs2_h - 1] = sbp->bsize;
+ for (h = gfs2_h - 1; h > 0; h--)
+ gfs2factor[h - 1] = gfs2factor[h] * gfs2_inptrs;
+
+ /* Convert from gfs1 to an offset */
+ offset = 0;
+ for (h = 0; h < gfs1_h; h++)
+ offset += (gfs1mp->mp_list[h] * gfs1factor[h]);
+
+ if (dinode_size - offset < *len)
+ *len = dinode_size - offset;
+
+ /* Convert from an offset back to gfs2 */
+ memset(gfs2mp, 0, sizeof(*gfs2mp));
+ for (h = 0; h <= gfs2_h; h++) {
+ /* Can't use do_div here because the factors are too large. */
+ gfs2mp->mp_list[h] = offset / gfs2factor[h];
+ offset %= gfs2factor[h];
+ }
+}
+
+void fix_jdatatree(struct gfs2_sbd *sbp, struct gfs2_inode *ip,
+ struct blocklist *blk, char *srcptr,
+ unsigned int size)
+{
+ uint64_t block;
+ struct gfs2_buffer_head *bh;
+ unsigned int amount, ptramt;
+ int h, copied = 0, new = 0;
+ struct gfs2_meta_header mh;
+
+ mh.mh_magic = GFS2_MAGIC;
+ mh.mh_type = GFS2_METATYPE_IN;
+ mh.mh_format = GFS2_FORMAT_IN;
+
+ /* This condition should never arise.
+ We're always dealing with unstuffed inodes */
+ if (!ip->i_di.di_height)
+ unstuff_dinode(ip);
+
+ ptramt = blk->mp.mp_list[blk->height];
+ amount = size;
+
+ while (copied < size) {
+ bh = bhold(ip->i_bh);
+
+ /* First, build up the metatree */
+ for (h = 0; h < blk->height; h++) {
+ lookup_block(ip, bh, h, &blk->mp, 1, &new, &block);
+ brelse(bh, updated);
+ if (!block)
+ break;
+
+ bh = bread(&sbp->buf_list, block);
+ if (new)
+ memset(bh->b_data, 0, sbp->bsize);
+ if (h < (blk->height - 1))
+ gfs2_meta_header_out(&mh, bh->b_data);
+ }
+
+ if (amount > sbp->bsize - ptramt)
+ amount = sbp->bsize - ptramt;
+
+ memcpy(bh->b_data + ptramt,
+ (char *)srcptr, amount);
+ srcptr += amount;
+ brelse(bh, updated);
+
+ copied += amount;
+
+ if (ptramt + amount >= sbp->bsize) {
+ /* advance to the next metablock */
+ blk->mp.mp_list[blk->height] += amount;
+ for (h = blk->height; h > 0; h--) {
+ if (blk->mp.mp_list[h] >= gfs2_inptrs) {
+ blk->mp.mp_list[h] = 0;
+ blk->mp.mp_list[h - 1]++;
+ continue;
+ }
+ break;
+ }
+ }
+ amount = size - copied;
+ ptramt = 0;
+ }
+}
+
+int adjust_jdata_inode(struct gfs2_sbd *sbp, struct gfs2_buffer_head *dibh,
+ struct gfs2_inode *ip)
+{
+ uint32_t gfs2_hgt;
+ struct gfs2_buffer_head *bh;
+ osi_list_t *tmp, *x;
+ int h, header_size, bufsize, ptrnum;
+ uint64_t *ptr1, block;
+ uint64_t dinode_size;
+ int error = 0, di_height;
+ struct blocklist blocks, *blk, *newblk;
+ struct metapath gfs2mp;
+
+ /* Don't have to worry about things with stuffed inodes */
+ if (ip->i_di.di_height == 0)
+ return 0;
+
+ osi_list_init(&blocks.list);
+
+ /* Add the dinode block to the blocks list */
+ blk = malloc(sizeof(struct blocklist));
+ if (!blk) {
+ log_crit("Error: Can't allocate memory"
+ " for indirect block fix.\n");
+ return -1;
+ }
+ memset(blk, 0, sizeof(*blk));
+ /* allocate a buffer to hold the pointers or data */
+ bufsize = sbp->bsize - sizeof(struct gfs2_meta_header);
+ blk->block = dibh->b_blocknr;
+ /*
+ * blk->ptrbuf either contains
+ * a) diptrs (for height=0)
+ * b) inptrs (for height=1 to di_height - 1)
+ * c) data for height = di_height
+ */
+ blk->ptrbuf = malloc(bufsize);
+ if (!blk->ptrbuf) {
+ log_crit("Error: Can't allocate memory"
+ " for file conversion.\n");
+ free(blk);
+ return -1;
+ }
+ memset(blk->ptrbuf, 0, bufsize);
+ /* Fill in the pointers from the dinode buffer */
+ memcpy(blk->ptrbuf, dibh->b_data + sizeof(struct gfs_dinode),
+ sbp->bsize - sizeof(struct gfs_dinode));
+ /* Zero out the pointers so we can fill them in later. */
+ memset(dibh->b_data + sizeof(struct gfs_dinode), 0,
+ sbp->bsize - sizeof(struct gfs_dinode));
+ osi_list_add_prev(&blk->list, &blocks.list);
+
+ /* Now run the metadata chain and build lists of all data/metadata blocks */
+ osi_list_foreach(tmp, &blocks.list) {
+ blk = osi_list_entry(tmp, struct blocklist, list);
+
+ if (blk->height >= ip->i_di.di_height)
+ continue;
+
+ header_size = (blk->height > 0 ? sizeof(struct gfs_indirect) :
+ sizeof(struct gfs_dinode));
+
+ for (ptr1 = (uint64_t *)blk->ptrbuf, ptrnum = 0;
+ ptrnum < sbp->sd_inptrs; ptr1++, ptrnum++) {
+ if (!*ptr1)
+ continue;
+
+ block = be64_to_cpu(*ptr1);
+
+ newblk = malloc(sizeof(struct blocklist));
+ if (!newblk) {
+ log_crit("Error: Can't allocate memory"
+ " for indirect block fix.\n");
+ error = -1;
+ goto out;
+ }
+ memset(newblk, 0, sizeof(*newblk));
+ newblk->ptrbuf = malloc(bufsize);
+ if (!newblk->ptrbuf) {
+ log_crit("Error: Can't allocate memory"
+ " for file conversion.\n");
+ free(newblk);
+ goto out;
+ }
+ memset(newblk->ptrbuf, 0, bufsize);
+ newblk->block = block;
+ newblk->height = blk->height + 1;
+ /* Build the metapointer list from our predecessors */
+ for (h = 0; h < blk->height; h++)
+ newblk->mp.mp_list[h] = blk->mp.mp_list[h];
+ newblk->mp.mp_list[h] = ptrnum;
+ /* Queue it to be processed later on in the loop. */
+ osi_list_add_prev(&newblk->list, &blocks.list);
+
+ bh = bread(&sbp->buf_list, block);
+ if (newblk->height == ip->i_di.di_height) {
+ /* read in the jdata block */
+ memcpy(newblk->ptrbuf, bh->b_data +
+ sizeof(struct gfs2_meta_header), bufsize);
+ /* Zero the buffer so we can fill it in later */
+ memset(bh->b_data + sizeof(struct gfs2_meta_header), 0,
+ bufsize);
+ } else {
+ /* read the new metadata block's pointers */
+ memcpy(newblk->ptrbuf, bh->b_data +
+ sizeof(struct gfs_indirect),
+ sbp->bsize - sizeof(struct gfs_indirect));
+ /* Zero the buffer so we can fill it in later */
+ memset(bh->b_data + sizeof(struct gfs_indirect), 0,
+ sbp->bsize - sizeof(struct gfs_indirect));
+ }
+ brelse(bh, updated);
+ /* Free the block so we can reuse it. This allows us to
+ convert a "full" file system. */
+ ip->i_di.di_blocks--;
+ gfs2_free_block(sbp, block);
+ }
+ }
+ /* The gfs2 height may be different. We need to rebuild the
+ metadata tree to the gfs2 height. */
+ gfs2_hgt = calc_gfs2_tree_height(ip, ip->i_di.di_size);
+ /* Save off the size because we're going to empty the contents
+ and add the data blocks back in later. */
+ dinode_size = ip->i_di.di_size;
+ ip->i_di.di_size = 0ULL;
+ di_height = ip->i_di.di_height;
+ ip->i_di.di_height = 0;
+
+ /* Now run through the block list a second time. If the block
+ is a data block, rewrite the data to the gfs2 offset. */
+ osi_list_foreach_safe(tmp, &blocks.list, x) {
+ unsigned int len;
+
+ blk = osi_list_entry(tmp, struct blocklist, list);
+ /* If it's not a data block at the highest level */
+ if (blk->height != di_height) {
+ osi_list_del(tmp);
+ free(blk->ptrbuf);
+ free(blk);
+ continue;
+ }
+ len = bufsize;
+ jdata_mp_gfs1_to_gfs2(sbp, di_height, gfs2_hgt, &blk->mp, &gfs2mp, &len, dinode_size);
+ memcpy(&blk->mp, &gfs2mp, sizeof(struct metapath));
+ blk->height -= di_height - gfs2_hgt;
+ if (len)
+ fix_jdatatree(sbp, ip, blk, blk->ptrbuf, len);
+ osi_list_del(tmp);
+ free(blk->ptrbuf);
+ free(blk);
+ }
+ ip->i_di.di_size = dinode_size;
+
+ /* Set the new dinode height, which may or may not have changed. */
+ /* The caller will take it from the ip and write it to the buffer */
+ ip->i_di.di_height = gfs2_hgt;
+ return 0;
+
+out:
+ while (!osi_list_empty(&blocks.list)) {
+ blk = osi_list_entry(tmp, struct blocklist, list);
+ osi_list_del(&blocks.list);
+ free(blk->ptrbuf);
+ free(blk);
+ }
+ return error;
+}
+
/* ------------------------------------------------------------------------- */
/* adjust_inode - change an inode from gfs1 to gfs2 */
/* */
@@ -672,13 +945,19 @@ int adjust_inode(struct gfs2_sbd *sbp, struct gfs2_buffer_head *bh)
/* ----------------------------------------------------------- */
if (inode_was_gfs1) {
struct gfs_dinode *gfs1_dinode_struct;
+ int ret = 0;
gfs1_dinode_struct = (struct gfs_dinode *)&inode->i_di;
inode->i_di.di_goal_meta = inode->i_di.di_goal_data;
inode->i_di.di_goal_data = 0; /* make sure the upper 32b are 0 */
inode->i_di.di_goal_data = gfs1_dinode_struct->di_goal_dblk;
inode->i_di.di_generation = 0;
- if (adjust_indirect_blocks(sbp, bh, inode))
+ if (!(inode->i_di.di_mode & S_IFDIR) &&
+ inode->i_di.di_flags & GFS2_DIF_JDATA)
+ ret = adjust_jdata_inode(sbp, bh, inode);
+ else
+ ret = adjust_indirect_blocks(sbp, bh, inode);
+ if (ret)
return -1;
}
@@ -733,7 +1012,7 @@ int inode_renumber(struct gfs2_sbd *sbp, uint64_t root_inode_addr)
fflush(stdout);
}
/* Get the next metadata block. Break out if we reach the end. */
- /* We have to check all metadata blocks because the bitmap may */
+ /* We have to check all metadata blocks because the bitmap may */
/* be "11" (used meta) for both inodes and indirect blocks. */
/* We need to process the inodes and change the indirect blocks */
/* to have a bitmap type of "01" (data). */
@@ -745,9 +1024,9 @@ int inode_renumber(struct gfs2_sbd *sbp, uint64_t root_inode_addr)
sbp->sd_sb.sb_root_dir.no_formal_ino = sbp->md.next_inum;
}
bh = bread(&sbp->buf_list, block);
- if (!gfs2_check_meta(bh, GFS_METATYPE_DI)) /* if it is an dinode */
+ if (!gfs2_check_meta(bh, GFS_METATYPE_DI)) {/* if it is an dinode */
error = adjust_inode(sbp, bh);
- else { /* It's metadata, but not an inode, so fix the bitmap. */
+ } else { /* It's metadata, but not an inode, so fix the bitmap. */
int blk, buf_offset;
int bitmap_byte; /* byte within the bitmap to fix */
int byte_bit; /* bit within the byte */
@@ -758,7 +1037,7 @@ int inode_renumber(struct gfs2_sbd *sbp, uint64_t root_inode_addr)
byte_bit = (block - rgd->ri.ri_data0) % GFS2_NBBY;
/* Now figure out which bitmap block the byte is on */
for (blk = 0; blk < rgd->ri.ri_length; blk++) {
- /* figure out offset of first bitmap byte for this map: */
+ /* figure out offset of first bitmap byte for this map: */
buf_offset = (blk) ? sizeof(struct gfs2_meta_header) :
sizeof(struct gfs2_rgrp);
/* if it's on this page */
14 years, 2 months