Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=4e…
Commit: 4e102cbef05a8d57b063b56346ca439cd580c924
Parent: 7a9640a8e3c1c3430f5705affdc38772f0f4a1ab
Author: Abhijith Das <adas(a)redhat.com>
AuthorDate: Fri Apr 30 10:47:09 2010 -0500
Committer: Abhijith Das <adas(a)redhat.com>
CommitterDate: Fri Apr 30 10:47:09 2010 -0500
gfs2_convert: gfs2_convert doesn't convert indirectly-pointed extended attributes correctly
When the extended attributes for a file don't fit
in one fs block, the dinode->di_eattr block becomes
an indirect block that contains pointers to blocks
that actually contain the xattrs. The gfs1 indirect
block header is different (larger) than that of gfs2
and this causes an incorrect conversion. The
resulting gfs2 filesystem cannot display the xattrs
because of leading nulls in the indirect block. This
patch adjusts this correctly.
Resolves: rhbz#576040
Signed-off-by: Abhi Das <adas(a)redhat.com>
---
gfs2/convert/gfs2_convert.c | 45 +++++++++++++++++++++++++++++++++++++++++++
1 files changed, 45 insertions(+), 0 deletions(-)
diff --git a/gfs2/convert/gfs2_convert.c b/gfs2/convert/gfs2_convert.c
index 0379d33..f28aac4 100644
--- a/gfs2/convert/gfs2_convert.c
+++ b/gfs2/convert/gfs2_convert.c
@@ -948,6 +948,45 @@ static int fix_cdpn_symlink(struct gfs2_sbd *sbp, struct gfs2_buffer_head *bh, s
return ret;
}
+
+/*
+ * fix_xattr -
+ * Extended attributes can be either direct (in the ip->i_di.di_eattr block) or
+ * then can be at a maximum of 1 indirect level. Multiple levels of indirection
+ * are not supported. If the di_eattr block contains extended attribute data,
+ * i.e block type = GFS_METATYPE_EA, we ignore it.
+ * If the di_eattr block contains block pointers to extended attributes we need
+ * to fix the header. gfs1 uses gfs_indirect as the header which is 64 bytes
+ * bigger than gfs2_meta_header that gfs2 uses.
+ */
+static int fix_xattr(struct gfs2_sbd *sbp, struct gfs2_buffer_head *bh, struct gfs2_inode *ip)
+{
+ int ret = 0, len, old_hdr_sz, new_hdr_sz;
+ struct gfs2_buffer_head *eabh;
+ char *buf;
+
+ /* Read in the i_di.di_eattr block */
+ eabh = bread(sbp, ip->i_di.di_eattr);
+ if (!gfs2_check_meta(eabh, GFS_METATYPE_IN)) {/* if it is an indirect block */
+ len = sbp->bsize - sizeof(struct gfs_indirect);
+ buf = malloc(len);
+ if (!buf) {
+ log_crit("Error: out of memory.\n");
+ return -1;
+ }
+ old_hdr_sz = sizeof(struct gfs_indirect);
+ new_hdr_sz = sizeof(struct gfs2_meta_header);
+ memcpy(buf, eabh->b_data + old_hdr_sz, sbp->bsize - old_hdr_sz);
+ memset(eabh->b_data + new_hdr_sz, 0, sbp->bsize - new_hdr_sz);
+ memcpy(eabh->b_data + new_hdr_sz, buf, len);
+ free(buf);
+ bmodified(eabh);
+ }
+ brelse(eabh);
+
+ return ret;
+}
+
/* ------------------------------------------------------------------------- */
/* adjust_inode - change an inode from gfs1 to gfs2 */
/* */
@@ -1039,6 +1078,12 @@ static int adjust_inode(struct gfs2_sbd *sbp, struct gfs2_buffer_head *bh)
if (ret)
return -1;
}
+ /* Check for extended attributes */
+ if (inode->i_di.di_eattr) {
+ ret = fix_xattr(sbp, bh, inode);
+ if (ret)
+ return -1;
+ }
}
bmodified(inode->i_bh);
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=e1…
Commit: e16c5e55e999c8f928c398a7afc7f100063d0c7f
Parent: d97b163ff014f1096a32afc908643dfb8dd396ff
Author: Abhijith Das <adas(a)redhat.com>
AuthorDate: Thu Apr 29 21:26:05 2010 -0500
Committer: Abhijith Das <adas(a)redhat.com>
CommitterDate: Thu Apr 29 21:26:05 2010 -0500
gfs2_convert: gfs2_convert segfaults when converting filesystems of blocksize 512 bytes
gfs2_convert segfaults when the jindex inode is unstuffed.
i.e. if the block size is small enough such that the jindex
entries (directly proportional to the number of journals)
don't fit in the disk inode block, the jindex inode is
unstuffed. This is a journaled data file and the structures
are different for such files in gfs1 and gfs2 with respect
to metaheaders. gfs2_convert needs to trick the file
reading code in libgfs2 to think it's dealing with a gfs2
directory (whose structure is similar to a gfs1 jdata inode)
to operate on the file at the right offsets.
Resolves: rhbz#568852
Signed-off-by: Abhi Das <adas(a)redhat.com>
---
gfs2/convert/gfs2_convert.c | 10 ++++++++++
1 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/gfs2/convert/gfs2_convert.c b/gfs2/convert/gfs2_convert.c
index 3a9905e..5a45c96 100644
--- a/gfs2/convert/gfs2_convert.c
+++ b/gfs2/convert/gfs2_convert.c
@@ -1284,6 +1284,7 @@ static int read_gfs1_jiindex(struct gfs2_sbd *sdp)
char buf[sizeof(struct gfs1_jindex)];
unsigned int j;
int error=0;
+ unsigned int tmp_mode = 0;
if(ip->i_di.di_size % sizeof(struct gfs1_jindex) != 0){
log_crit("The size reported in the journal index"
@@ -1299,6 +1300,14 @@ static int read_gfs1_jiindex(struct gfs2_sbd *sdp)
log_crit("Unable to zero journal index\n");
return -1;
}
+ /* ugly hack
+ * Faking the gfs1_jindex inode as a directory to gfs2_readi
+ * so it skips the metaheader struct in the data blocks
+ * in the inode. gfs2_jindex inode doesn't have metaheaders
+ * in the data blocks */
+ tmp_mode = ip->i_di.di_mode;
+ ip->i_di.di_mode &= ~S_IFMT;
+ ip->i_di.di_mode |= S_IFDIR;
for (j = 0; ; j++) {
struct gfs1_jindex *journ;
@@ -1315,6 +1324,7 @@ static int read_gfs1_jiindex(struct gfs2_sbd *sdp)
gfs1_jindex_in(journ, buf);
sdp->jsize = (journ->ji_nsegment * 16 * sdp->bsize) >> 20;
}
+ ip->i_di.di_mode = tmp_mode;
if(j * sizeof(struct gfs1_jindex) != ip->i_di.di_size){
log_crit("journal inode size invalid\n");
goto fail;
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=78…
Commit: 7804e516b06c77cdfb3d5a969018cee6b05b5003
Parent: fee7b0d92edb3ed99bdbd6194b72103c22279e94
Author: Jonathan Brassow <jbrassow(a)redhat.com>
AuthorDate: Thu Apr 29 14:07:04 2010 -0500
Committer: Jonathan Brassow <jbrassow(a)redhat.com>
CommitterDate: Thu Apr 29 14:07:04 2010 -0500
HA LVM: Use CLVM with local machine kernel targets (bz 585229)
When a logical volume is activated in a cluster exclusively,
the kernel targets used are single machine targets. This
means we can use CLVM to protect the LVM metadata and still
better align ourselves with active/passive application stacks.
Making this change also simplifies HA LVM setup. There is no
more setting up tags, volume_list entries, or updating the
initrd.
Updating HA-LVM in this way also addresses the following bugs:
- 509368
- 583769
- 572311
---
rgmanager/src/resources/lvm.sh | 52 ++-----------
rgmanager/src/resources/lvm_by_lv.sh | 75 +++++++++++++++++-
rgmanager/src/resources/lvm_by_vg.sh | 147 +++++++++++++++++++++++++++++++++-
3 files changed, 221 insertions(+), 53 deletions(-)
diff --git a/rgmanager/src/resources/lvm.sh b/rgmanager/src/resources/lvm.sh
index ffb0b21..a972aaf 100755
--- a/rgmanager/src/resources/lvm.sh
+++ b/rgmanager/src/resources/lvm.sh
@@ -36,19 +36,6 @@ export LC_ALL LANG PATH
rv=0
################################################################################
-# clvm_check
-#
-################################################################################
-function clvm_check
-{
- if [[ $(vgs -o attr --noheadings $1) =~ .....c ]]; then
- return 1
- fi
-
- return 0
-}
-
-################################################################################
# ha_lvm_proper_setup_check
#
################################################################################
@@ -106,18 +93,10 @@ function ha_lvm_proper_setup_check
case $1 in
start)
- ##
- # We can safely ignore clustered volume groups (VGs handled by CLVM)
- ##
- if ! clvm_check $OCF_RESKEY_vg_name; then
- ocf_log notice "$OCF_RESKEY_vg_name is a cluster volume. Ignoring..."
- exit 0
+ if ! [[ $(vgs -o attr --noheadings $OCF_RESKEY_vg_name) =~ .....c ]]; then
+ ha_lvm_proper_setup_check || exit 1
fi
- ha_lvm_proper_setup_check || exit 1
-
- rv=0
-
if [ -z $OCF_RESKEY_lv_name ]; then
vg_start || exit 1
else
@@ -133,20 +112,13 @@ status|monitor)
else
lv_status || exit 1
fi
- rv=0
;;
stop)
- ##
- # We can safely ignore clustered volume groups (VGs handled by CLVM)
- ##
- if ! clvm_check $OCF_RESKEY_vg_name; then
- ocf_log notice "$OCF_RESKEY_vg_name is a cluster volume. Ignoring..."
- exit 0
- fi
-
- if ! ha_lvm_proper_setup_check; then
- ocf_log err "WARNING: An improper setup can cause data corruption!"
+ if ! [[ $(vgs -o attr --noheadings $OCF_RESKEY_vg_name) =~ .....c ]]; then
+ if ! ha_lvm_proper_setup_check; then
+ ocf_log err "WARNING: An improper setup can cause data corruption!"
+ fi
fi
if [ -z $OCF_RESKEY_lv_name ]; then
@@ -154,35 +126,23 @@ stop)
else
lv_stop || exit 1
fi
- rv=0
;;
recover|restart)
$0 stop || exit $OCF_ERR_GENERIC
$0 start || exit $OCF_ERR_GENERIC
- rv=0
;;
meta-data)
cat `echo $0 | sed 's/^\(.*\)\.sh$/\1.metadata/'`
- rv=0
;;
validate-all|verify-all)
- ##
- # We can safely ignore clustered volume groups (VGs handled by CLVM)
- ##
- if ! clvm_check $OCF_RESKEY_vg_name; then
- ocf_log notice "$OCF_RESKEY_vg_name is a cluster volume. Ignoring..."
- exit 0
- fi
-
if [ -z $OCF_RESKEY_lv_name ]; then
vg_verify || exit 1
else
lv_verify || exit 1
fi
- rv=0
;;
*)
echo "usage: $0 {start|status|monitor|stop|restart|meta-data|verify-all}"
diff --git a/rgmanager/src/resources/lvm_by_lv.sh b/rgmanager/src/resources/lvm_by_lv.sh
index 1937b9f..da15a15 100644
--- a/rgmanager/src/resources/lvm_by_lv.sh
+++ b/rgmanager/src/resources/lvm_by_lv.sh
@@ -101,10 +101,22 @@ lv_activate_resilient()
fi
}
+lv_status_clustered()
+{
+ #
+ # Check if device is active
+ #
+ if [[ ! $(lvs -o attr --noheadings $lv_path) =~ ....a. ]]; then
+ return $OCF_ERR_GENERIC
+ fi
+
+ return $OCF_SUCCESS
+}
+
# lv_status
#
# Is the LV active?
-lv_status()
+lv_status_single()
{
declare lv_path="$OCF_RESKEY_vg_name/$OCF_RESKEY_lv_name"
declare dev="/dev/$lv_path"
@@ -167,6 +179,16 @@ lv_status()
return $OCF_SUCCESS
}
+function lv_status
+{
+ # We pass in the VG name to see of the logical volume is clustered
+ if [[ $(vgs -o attr --noheadings $OCF_RESKEY_vg_name) =~ .....c ]]; then
+ lv_status_clustered
+ else
+ lv_status_single
+ fi
+}
+
# lv_activate_and_tag
lv_activate_and_tag()
{
@@ -334,7 +356,29 @@ lv_activate()
return $OCF_SUCCESS
}
-function lv_start
+function lv_start_clustered
+{
+ if ! lvchange -aey $OCF_RESKEY_vg_name/$OCF_RESKEY_lv_name; then
+ ocf_log err "Failed to activate logical volume, $OCF_RESKEY_vg_name/$OCF_RESKEY_lv_name"
+ ocf_log notice "Attempting cleanup of $OCF_RESKEY_vg_name/$OCF_RESKEY_lv_name"
+
+ if ! lvconvert --repair --use-policies $OCF_RESKEY_vg_name/$OCF_RESKEY_lv_name; then
+ ocf_log err "Failed to cleanup $OCF_RESKEY_vg_name/$OCF_RESKEY_lv_name"
+ return $OCF_ERR_GENERIC
+ fi
+
+ if ! lvchange -aey $OCF_RESKEY_vg_name/$OCF_RESKEY_lv_name; then
+ ocf_log err "Failed second attempt to activate $OCF_RESKEY_vg_name/$OCF_RESKEY_lv_name"
+ return $OCF_ERR_GENERIC
+ fi
+
+ ocf_log notice "Second attempt to activate $OCF_RESKEY_vg_name/$OCF_RESKEY_lv_name successful"
+ return $OCF_SUCCESS
+ fi
+ return $OCF_SUCCESS
+}
+
+function lv_start_single
{
if ! lvs $OCF_RESKEY_vg_name >& /dev/null; then
lv_count=0
@@ -355,7 +399,22 @@ function lv_start
return 0
}
-function lv_stop
+function lv_start
+{
+ # We pass in the VG name to see of the logical volume is clustered
+ if [[ $(vgs -o attr --noheadings $OCF_RESKEY_vg_name) =~ .....c ]]; then
+ lv_start_clustered
+ else
+ lv_start_single
+ fi
+}
+
+function lv_stop_clustered
+{
+ lvchange -aln $OCF_RESKEY_vg_name/$OCF_RESKEY_lv_name
+}
+
+function lv_stop_single
{
if ! lv_activate stop; then
return 1
@@ -363,3 +422,13 @@ function lv_stop
return 0
}
+
+function lv_stop
+{
+ # We pass in the VG name to see of the logical volume is clustered
+ if [[ $(vgs -o attr --noheadings $OCF_RESKEY_vg_name) =~ .....c ]]; then
+ lv_stop_clustered
+ else
+ lv_stop_single
+ fi
+}
diff --git a/rgmanager/src/resources/lvm_by_vg.sh b/rgmanager/src/resources/lvm_by_vg.sh
index 014dcbf..08d8c98 100755
--- a/rgmanager/src/resources/lvm_by_vg.sh
+++ b/rgmanager/src/resources/lvm_by_vg.sh
@@ -85,14 +85,18 @@ function strip_and_add_tag
return $OCF_SUCCESS
}
+function vg_status_clustered
+{
+ return $OCF_SUCCESS
+}
+
# vg_status
#
# Are all the LVs active?
-function vg_status
+function vg_status_single
{
local i
local dev
- local readdev
local my_name=$(local_node_name)
#
@@ -144,13 +148,88 @@ function vg_status
return $OCF_SUCCESS
}
+##
+# Main status function for volume groups
+##
+function vg_status
+{
+ if [[ $(vgs -o attr --noheadings $OCF_RESKEY_vg_name) =~ .....c ]]; then
+ vg_status_clustered
+ else
+ vg_status_single
+ fi
+}
+
function vg_verify
{
# Anything to verify?
return $OCF_SUCCESS
}
-function vg_start
+function vg_start_clustered
+{
+ local a
+ local results
+ local all_pvs
+ local resilience
+
+ ocf_log info "Starting volume group, $OCF_RESKEY_vg_name"
+
+ if ! vgchange -aey $OCF_RESKEY_vg_name; then
+ ocf_log err "Failed to activate volume group, $OCF_RESKEY_vg_name"
+ ocf_log notice "Attempting cleanup of $OCF_RESKEY_vg_name"
+
+ if ! vgreduce --removemissing $OCF_RESKEY_vg_name; then
+ ocf_log err "Failed to make $OCF_RESKEY_vg_name consistent"
+ return $OCF_ERR_GENERIC
+ fi
+
+ if ! vgchange -aey $OCF_RESKEY_vg_name; then
+ ocf_log err "Failed second attempt to activate $OCF_RESKEY_vg_name"
+ return $OCF_ERR_GENERIC
+ fi
+
+ ocf_log notice "Second attempt to activate $OCF_RESKEY_vg_name successful"
+ return $OCF_SUCCESS
+ else
+ # The activation commands succeeded, but did they do anything?
+ # Make sure all the logical volumes are active
+ results=(`lvs -o name,attr --noheadings 2> /dev/null $OCF_RESKEY_vg_name`)
+ a=0
+ while [ ! -z ${results[$a]} ]; do
+ if [[ ! ${results[$(($a + 1))]} =~ ....a. ]]; then
+ all_pvs=(`pvs --noheadings -o name 2> /dev/null`)
+ resilience=" --config devices{filter=["
+ for i in ${all_pvs[*]}; do
+ resilience=$resilience'"a|'$i'|",'
+ done
+ resilience=$resilience"\"r|.*|\"]}"
+
+ vgchange -aey $OCF_RESKEY_vg_name $resilience
+ break
+ fi
+ a=$(($a + 2))
+ done
+
+ # We need to check the LVs again if we made the command resilient
+ if [ ! -z $resilience ]; then
+ results=(`lvs -o name,attr --noheadings $OCF_RESKEY_vg_name $resilience 2> /dev/null`)
+ a=0
+ while [ ! -z ${results[$a]} ]; do
+ if [[ ! ${results[$(($a + 1))]} =~ ....a. ]]; then
+ ocf_log err "Failed to activate $OCF_RESKEY_vg_name"
+ return $OCF_ERR_GENERIC
+ fi
+ a=$(($a + 2))
+ done
+ ocf_log err "Orphan storage device in $OCF_RESKEY_vg_name slowing operations"
+ fi
+ fi
+
+ return $OCF_SUCCESS
+}
+
+function vg_start_single
{
local a
local results
@@ -238,7 +317,55 @@ function vg_start
return $OCF_SUCCESS
}
-function vg_stop
+##
+# Main start function for volume groups
+##
+function vg_start
+{
+ if [[ $(vgs -o attr --noheadings $OCF_RESKEY_vg_name) =~ .....c ]]; then
+ vg_start_clustered
+ else
+ vg_start_single
+ fi
+}
+
+function vg_stop_clustered
+{
+ local a
+ local results
+ typeset self_fence=""
+
+ case ${OCF_RESKEY_self_fence} in
+ "yes") self_fence=1 ;;
+ 1) self_fence=1 ;;
+ *) self_fence="" ;;
+ esac
+
+ # Shut down the volume group
+ # Do we need to make this resilient?
+ vgchange -aln $OCF_RESKEY_vg_name
+
+ # Make sure all the logical volumes are inactive
+ results=(`lvs -o name,attr --noheadings $OCF_RESKEY_vg_name 2> /dev/null`)
+ a=0
+ while [ ! -z ${results[$a]} ]; do
+ if [[ ${results[$(($a + 1))]} =~ ....a. ]]; then
+ if [ "$self_fence" ]; then
+ ocf_log err "Unable to deactivate $lv_path REBOOT"
+ sync
+ reboot -fn
+ else
+ ocf_log err "Logical volume $OCF_RESKEY_vg_name/${results[$a]} failed to shutdown"
+ fi
+ return $OCF_ERR_GENERIC
+ fi
+ a=$(($a + 2))
+ done
+
+ return $OCF_SUCCESS
+}
+
+function vg_stop_single
{
local a
local results
@@ -279,3 +406,15 @@ function vg_stop
return $OCF_SUCCESS
}
+
+##
+# Main stop function for volume groups
+##
+function vg_stop
+{
+ if [[ $(vgs -o attr --noheadings $OCF_RESKEY_vg_name) =~ .....c ]]; then
+ vg_stop_clustered
+ else
+ vg_stop_single
+ fi
+}