gfs2-utils: master - fsck.gfs2: Don't rely on cluster.conf when rebuilding sb
by Andrew Price
Gitweb: http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=49361e27...
Commit: 49361e27628cf26554c1f690440dfca021713658
Parent: cb94e0a60bf8575d0f84fa2878192b2a761e0781
Author: Andrew Price <anprice(a)redhat.com>
AuthorDate: Wed Jul 17 12:36:40 2013 +0100
Committer: Andrew Price <anprice(a)redhat.com>
CommitterDate: Thu Jul 18 10:08:43 2013 +0100
fsck.gfs2: Don't rely on cluster.conf when rebuilding sb
As cluster.conf no longer exists we can't sniff the locking options from
it when rebuilding the superblock and in any case we shouldn't assume
that fsck.gfs2 is running on the cluster the volume belongs to.
This patch removes the get_lockproto_table function and instead sets the
lock table name to a placeholder ("unknown") and sets lockproto to
"lock_dlm". It warns the user at the end of the run that the locktable
will need to be set before mounting.
Signed-off-by: Andrew Price <anprice(a)redhat.com>
---
gfs2/fsck/initialize.c | 57 +++--------------------------------------------
gfs2/fsck/main.c | 4 +++
2 files changed, 8 insertions(+), 53 deletions(-)
diff --git a/gfs2/fsck/initialize.c b/gfs2/fsck/initialize.c
index b01b240..869d2de 100644
--- a/gfs2/fsck/initialize.c
+++ b/gfs2/fsck/initialize.c
@@ -33,6 +33,7 @@ static int was_mounted_ro = 0;
static uint64_t possible_root = HIGHEST_BLOCK;
static struct master_dir fix_md;
static unsigned long long blks_2free = 0;
+extern int sb_fixed;
/**
* block_mounters
@@ -828,58 +829,6 @@ static int init_system_inodes(struct gfs2_sbd *sdp)
return -1;
}
-static int get_lockproto_table(struct gfs2_sbd *sdp)
-{
- FILE *fp;
- char line[PATH_MAX];
- char *cluname, *end;
- const char *fsname, *cfgfile = "/etc/cluster/cluster.conf";
-
- memset(sdp->lockproto, 0, sizeof(sdp->lockproto));
- memset(sdp->locktable, 0, sizeof(sdp->locktable));
- fp = fopen(cfgfile, "rt");
- if (!fp) {
- /* no cluster.conf; must be a stand-alone file system */
- strcpy(sdp->lockproto, "lock_nolock");
- log_warn(_("Lock protocol determined to be: lock_nolock\n"));
- log_warn(_("Stand-alone file system: No need for a lock "
- "table.\n"));
- return 0;
- }
- /* We found a cluster.conf so assume it's a clustered file system */
- log_warn(_("Lock protocol assumed to be: " GFS2_DEFAULT_LOCKPROTO
- "\n"));
- strcpy(sdp->lockproto, GFS2_DEFAULT_LOCKPROTO);
-
- while (fgets(line, sizeof(line) - 1, fp)) {
- cluname = strstr(line,"<cluster name=");
- if (cluname) {
- cluname += 15;
- end = strchr(cluname,'"');
- if (end)
- *end = '\0';
- break;
- }
- }
- if (cluname == NULL || end == NULL || end - cluname < 1) {
- log_err(_("Error: Unable to determine cluster name from %s\n"),
- cfgfile);
- } else {
- fsname = strrchr(opts.device, '/');
- if (fsname)
- fsname++;
- else
- fsname = "repaired";
- snprintf(sdp->locktable, sizeof(sdp->locktable), "%.*s:%.16s",
- (int)(sizeof(sdp->locktable) - strlen(fsname) - 2),
- cluname, fsname);
- log_warn(_("Lock table determined to be: %s\n"),
- sdp->locktable);
- }
- fclose(fp);
- return 0;
-}
-
/**
* is_journal_copy - Is this a "real" dinode or a copy inside a journal?
* A real dinode will be located at the block number in its no_addr.
@@ -1256,7 +1205,8 @@ static int sb_repair(struct gfs2_sbd *sdp)
}
}
/* Step 3 - Rebuild the lock protocol and file system table name */
- get_lockproto_table(sdp);
+ strcpy(sdp->lockproto, GFS2_DEFAULT_LOCKPROTO);
+ strcpy(sdp->locktable, "unknown");
if (query(_("Okay to fix the GFS2 superblock? (y/n)"))) {
log_info(_("Found system master directory at: 0x%llx\n"),
sdp->sd_sb.sb_master_dir.no_addr);
@@ -1280,6 +1230,7 @@ static int sb_repair(struct gfs2_sbd *sdp)
build_sb(sdp, uuid);
inode_put(&sdp->md.rooti);
inode_put(&sdp->master_dir);
+ sb_fixed = 1;
} else {
log_crit(_("GFS2 superblock not fixed; fsck cannot proceed "
"without a valid superblock.\n"));
diff --git a/gfs2/fsck/main.c b/gfs2/fsck/main.c
index 287404d..b4b1a03 100644
--- a/gfs2/fsck/main.c
+++ b/gfs2/fsck/main.c
@@ -37,6 +37,7 @@ struct osi_root dirtree = (struct osi_root) { NULL, };
struct osi_root inodetree = (struct osi_root) { NULL, };
int dups_found = 0, dups_found_first = 0;
struct gfs_sb *sbd1 = NULL;
+int sb_fixed = 0;
/* This function is for libgfs2's sake. */
void print_it(const char *label, const char *fmt, const char *fmt2, ...)
@@ -316,6 +317,9 @@ int main(int argc, char **argv)
log_notice( _("Writing changes to disk\n"));
fsync(sdp->device_fd);
destroy(sdp);
+ if (sb_fixed)
+ log_warn(_("Superblock was reset. Use tunegfs2 to manually "
+ "set lock table before mounting.\n"));
log_notice( _("gfs2_fsck complete\n"));
if (!error) {
10 years, 9 months
gfs2-utils: master - fsck.gfs2: Don't call gettext a second time in fsck_query()
by Andrew Price
Gitweb: http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=cb94e0a6...
Commit: cb94e0a60bf8575d0f84fa2878192b2a761e0781
Parent: f81ece7e97b66d5d8c3639b2094a31723c2e427b
Author: Andrew Price <anprice(a)redhat.com>
AuthorDate: Mon Jul 15 14:04:13 2013 +0100
Committer: Andrew Price <anprice(a)redhat.com>
CommitterDate: Thu Jul 18 10:08:42 2013 +0100
fsck.gfs2: Don't call gettext a second time in fsck_query()
The format string passed to fsck_query should have been passed through
gettext already, so it makes no sense to do so again.
Signed-off-by: Andrew Price <anprice(a)redhat.com>
---
gfs2/fsck/util.c | 4 +---
1 files changed, 1 insertions(+), 3 deletions(-)
diff --git a/gfs2/fsck/util.c b/gfs2/fsck/util.c
index fd1b292..a701d82 100644
--- a/gfs2/fsck/util.c
+++ b/gfs2/fsck/util.c
@@ -168,7 +168,6 @@ char generic_interrupt(const char *caller, const char *where,
int fsck_query(const char *format, ...)
{
va_list args;
- const char *transform;
char response;
int ret = 0;
@@ -184,8 +183,7 @@ int fsck_query(const char *format, ...)
opts.query = TRUE;
while (1) {
va_start(args, format);
- transform = _(format);
- vprintf(transform, args);
+ vprintf(format, args);
va_end(args);
/* Make sure query is printed out */
10 years, 9 months
fence-agents: master - fence_ovh: New fence agent for OVH
by Marek Grác
Gitweb: http://git.fedorahosted.org/git/?p=fence-agents.git;a=commitdiff;h=c61430...
Commit: c61430f65c843c4e4b7b3487f378d306efe1d52a
Parent: cff73b867e9e39d4161d825192b0d295751ba968
Author: Marek 'marx' Grac <mgrac(a)redhat.com>
AuthorDate: Wed Jul 17 17:42:13 2013 +0200
Committer: Marek 'marx' Grac <mgrac(a)redhat.com>
CommitterDate: Wed Jul 17 17:42:13 2013 +0200
fence_ovh: New fence agent for OVH
Be aware that "off" command represents reboot into rescue mode
---
configure.ac | 1 +
fence/agents/ovh/Makefile.am | 17 +++++
fence/agents/ovh/fence_ovh.py | 136 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 154 insertions(+), 0 deletions(-)
diff --git a/configure.ac b/configure.ac
index f3acb13..910cab8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -278,6 +278,7 @@ AC_CONFIG_FILES([Makefile
fence/agents/mcdata/Makefile
fence/agents/nss_wrapper/Makefile
fence/agents/rackswitch/Makefile
+ fence/agents/ovh/Makefile
fence/agents/rhevm/Makefile
fence/agents/rsa/Makefile
fence/agents/rsb/Makefile
diff --git a/fence/agents/ovh/Makefile.am b/fence/agents/ovh/Makefile.am
new file mode 100644
index 0000000..c6d7d01
--- /dev/null
+++ b/fence/agents/ovh/Makefile.am
@@ -0,0 +1,17 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+TARGET = fence_ovh
+
+SRC = $(TARGET).py
+
+EXTRA_DIST = $(SRC)
+
+sbin_SCRIPTS = $(TARGET)
+
+man_MANS = $(TARGET).8
+
+include $(top_srcdir)/make/fencebuild.mk
+include $(top_srcdir)/make/fenceman.mk
+
+clean-local: clean-man
+ rm -f $(TARGET)
diff --git a/fence/agents/ovh/fence_ovh.py b/fence/agents/ovh/fence_ovh.py
new file mode 100644
index 0000000..881aa90
--- /dev/null
+++ b/fence/agents/ovh/fence_ovh.py
@@ -0,0 +1,136 @@
+#!/usr/bin/python
+# Copyright 2013 Adrian Gibanel Lopez (bTactic)
+# Adrian Gibanel improved this script at 2013 to add verification of success and to output metadata
+
+# Based on:
+# This is a fence agent for use at OVH
+# As there are no other fence devices available, we must use OVH's SOAP API #Quick-and-dirty
+# assemled by Dennis Busch, secofor GmbH, Germany
+# This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
+
+import sys, time
+from datetime import datetime
+from suds.client import Client
+from suds.xsd.doctor import ImportDoctor, Import
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+
+OVH_RESCUE_PRO_NETBOOT_ID = '28'
+OVH_HARD_DISK_NETBOOT_ID = '1'
+
+STATUS_HARD_DISK_SLEEP = 240 # Wait 4 minutes to SO to boot
+STATUS_RESCUE_PRO_SLEEP = 150 # Wait 2 minutes 30 seconds to Rescue-Pro to run
+
+def define_new_opts():
+ all_opt["email"] = {
+ "getopt" : "Z:",
+ "longopt" : "email",
+ "help" : "-Z, --email=<email> email for reboot message: admin(a)domain.com",
+ "required" : "1",
+ "shortdesc" : "Reboot email",
+ "default" : "",
+ "order" : 1 }
+
+def netboot_reboot(options, mode):
+ conn = soap_login(options)
+
+ # dedicatedNetbootModifyById changes the mode of the next reboot
+ conn.service.dedicatedNetbootModifyById(options["session"], options["--plug"], mode, '', options["--email"])
+
+ # dedicatedHardRebootDo initiates a hard reboot on the given node
+ conn.service.dedicatedHardRebootDo(options["session"], options["--plug"], 'Fencing initiated by cluster', '', 'en')
+
+ conn.logout(options["session"])
+
+def reboot_time(options):
+ conn = soap_login(options)
+
+ result = conn.service.dedicatedHardRebootStatus(options["session"], options["--plug"])
+ tmpstart = datetime.strptime(result.start,'%Y-%m-%d %H:%M:%S')
+ tmpend = datetime.strptime(result.end,'%Y-%m-%d %H:%M:%S')
+ result.start = tmpstart
+ result.end = tmpend
+
+ conn.logout(options["session"])
+
+ return result
+
+def soap_login(options):
+ imp = Import('http://schemas.xmlsoap.org/soap/encoding/')
+ url = 'https://www.ovh.com/soapi/soapi-re-1.59.wsdl'
+ imp.filter.add('http://soapi.ovh.com/manager')
+ d = ImportDoctor(imp)
+
+ try:
+ soap = Client(url, doctor=d)
+ session = soap.service.login(options["--username"], options["--password"], 'en', 0)
+ except Exception, ex:
+ fail(EC_LOGIN_DENIED)
+
+ options["session"] = session
+ return soap
+
+def main():
+ device_opt = [ "login", "passwd", "port", "email" ]
+
+ atexit.register(atexit_handler)
+
+ define_new_opts()
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = { }
+ docs["shortdesc"] = "Fence agent for OVH"
+ docs["longdesc"] = "fence_ovh is an Power Fencing agent \
+which can be used within OVH datecentre. \
+Poweroff is simulated with a reboot into rescue-pro mode."
+
+ docs["vendorurl"] = "http://www.ovh.net"
+ show_docs(options, docs)
+
+ if options["--action"] in [ "list", "status"]:
+ fail_usage("Action '" + options["--action"] + "' is not supported in this fence agent")
+
+ if options["--plug"].endswith(".ovh.net") == False:
+ options["--plug"] += ".ovh.net"
+
+ if options.has_key("--email") == False:
+ fail_usage("You have to enter e-mail address which is notified by fence agent")
+
+ # Save datetime just before changing netboot
+ before_netboot_reboot = datetime.now()
+
+ if options["--action"] == 'off':
+ # Reboot in Rescue-pro
+ netboot_reboot(options,OVH_RESCUE_PRO_NETBOOT_ID)
+ time.sleep(STATUS_RESCUE_PRO_SLEEP)
+ elif options["--action"] in ['on', 'reboot' ]:
+ # Reboot from HD
+ netboot_reboot(options,OVH_HARD_DISK_NETBOOT_ID)
+ time.sleep(STATUS_HARD_DISK_SLEEP)
+
+ # Save datetime just after reboot
+ after_netboot_reboot = datetime.now()
+
+ # Verify that action was completed sucesfully
+ reboot_t = reboot_time(options)
+
+ if options.has_key("--verbose"):
+ options["debug_fh"].write("reboot_start_end.start: "+ reboot_t.start.strftime('%Y-%m-%d %H:%M:%S')+"\n")
+ options["debug_fh"].write("before_netboot_reboot: " + before_netboot_reboot.strftime('%Y-%m-%d %H:%M:%S')+"\n")
+ options["debug_fh"].write("reboot_start_end.end: " + reboot_t.end.strftime('%Y-%m-%d %H:%M:%S')+"\n")
+ options["debug_fh"].write("after_netboot_reboot: " + after_netboot_reboot.strftime('%Y-%m-%d %H:%M:%S')+"\n")
+
+ if reboot_t.start < after_netboot_reboot < reboot_t.end:
+ result = 0
+ if options.has_key("--verbose"):
+ options["debug_fh"].write("Netboot reboot went OK.\n")
+ else:
+ result = 1
+ if options.has_key("--verbose"):
+ options["debug_fh"].write("ERROR: Netboot reboot wasn't OK.\n")
+
+ sys.exit(result)
+
+
+if __name__ == "__main__":
+ main()
10 years, 9 months
cluster: RHEL6 - rgmanager: Fix unlikely NULL ptr deref
by Ryan McCabe
Gitweb: http://git.fedorahosted.org/git/?p=cluster.git;a=commitdiff;h=e1aee22c385...
Commit: e1aee22c3853cb218e351c73d44448722a805d68
Parent: 842398a32b2a74631c0a350a3c06794b91e7c34c
Author: Ryan McCabe <rmccabe(a)redhat.com>
AuthorDate: Fri Jul 12 15:46:27 2013 -0400
Committer: Ryan McCabe <rmccabe(a)redhat.com>
CommitterDate: Wed Jul 17 10:49:05 2013 -0400
rgmanager: Fix unlikely NULL ptr deref
Fix a couple of places where a very unlikely null pointer
dereference could occur.
Related: rhbz#983296
Signed-off-by: Ryan McCabe <rmccabe(a)redhat.com>
---
rgmanager/src/clulib/vft.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/rgmanager/src/clulib/vft.c b/rgmanager/src/clulib/vft.c
index ad1f468..80f1e86 100644
--- a/rgmanager/src/clulib/vft.c
+++ b/rgmanager/src/clulib/vft.c
@@ -498,6 +498,9 @@ vf_buffer_join_msg(vf_msg_t *hdr, struct timeval *timeout)
hdr->vm_msg.vf_view,
hdr->vm_msg.vf_data, hdr->vm_msg.vf_datalen);
+ if (!newp)
+ return 0;
+
if (timeout && (timeout->tv_sec || timeout->tv_usec)) {
if (getuptime(&newp->vn_timeout) == -1) {
/* XXX What do we do here? */
@@ -782,6 +785,7 @@ vf_try_commit(key_node_t *key_node)
*/
if (key_node->kn_data == NULL) {
fprintf (stderr, "malloc fail err=%d\n", errno);
+ key_node->kn_datalen = 0;
return -1;
}
10 years, 9 months
cluster: RHEL6 - rgmanger: Don't destroy locked mutexes
by Ryan McCabe
Gitweb: http://git.fedorahosted.org/git/?p=cluster.git;a=commitdiff;h=842398a32b2...
Commit: 842398a32b2a74631c0a350a3c06794b91e7c34c
Parent: 3e62b5680e917955df9bcb2ca627b0a656fe5b52
Author: Ryan McCabe <rmccabe(a)redhat.com>
AuthorDate: Fri Jul 12 15:42:45 2013 -0400
Committer: Ryan McCabe <rmccabe(a)redhat.com>
CommitterDate: Wed Jul 17 10:49:05 2013 -0400
rgmanger: Don't destroy locked mutexes
Unlock locked mutexes before calling pthread_mutex_destroy()
on them.
Related: rhbz#983296
Signed-off-by: Ryan McCabe <rmccabe(a)redhat.com>
---
rgmanager/src/clulib/libcpglock.c | 1 +
rgmanager/src/daemons/rg_thread.c | 18 +++++-------------
2 files changed, 6 insertions(+), 13 deletions(-)
diff --git a/rgmanager/src/clulib/libcpglock.c b/rgmanager/src/clulib/libcpglock.c
index f99edd4..75fc9f6 100644
--- a/rgmanager/src/clulib/libcpglock.c
+++ b/rgmanager/src/clulib/libcpglock.c
@@ -279,6 +279,7 @@ cpg_lock_fin(void *handle)
close(h->fd);
+ pthread_mutex_unlock(&h->mutex);
pthread_mutex_destroy(&h->mutex);
free(h);
return 0;
diff --git a/rgmanager/src/daemons/rg_thread.c b/rgmanager/src/daemons/rg_thread.c
index b888717..c08d8aa 100644
--- a/rgmanager/src/daemons/rg_thread.c
+++ b/rgmanager/src/daemons/rg_thread.c
@@ -530,20 +530,12 @@ resgroup_thread_main(void *arg)
raise(SIGSEGV);
}
+ pthread_mutex_unlock(&my_queue_mutex);
mystatus = pthread_mutex_destroy(&my_queue_mutex);
- if (mystatus != 0)
- {
- if (mystatus == EBUSY) {
- pthread_mutex_unlock(&my_queue_mutex);
- }
-
- mystatus = pthread_mutex_destroy(&my_queue_mutex);
- if (mystatus != 0) {
- fprintf (stderr, "mutex_destroy=%d err=%d %p\n",
- mystatus, errno, &my_queue_mutex);
-
- fflush (stderr);
- }
+ if (mystatus != 0) {
+ fprintf(stderr, "mutex_destroy=%d err=%d %p\n",
+ mystatus, errno, &my_queue_mutex);
+ fflush (stderr);
}
list_remove(&resthread_list, myself);
10 years, 9 months
cluster: RHEL6 - rgmanager: Fix for double pthread_mutex_unlock() calls
by Ryan McCabe
Gitweb: http://git.fedorahosted.org/git/?p=cluster.git;a=commitdiff;h=3e62b5680e9...
Commit: 3e62b5680e917955df9bcb2ca627b0a656fe5b52
Parent: ceb12b85b625d57d0d219e55e2e179192fee53d6
Author: Ryan McCabe <rmccabe(a)redhat.com>
AuthorDate: Fri Jul 12 15:36:35 2013 -0400
Committer: Ryan McCabe <rmccabe(a)redhat.com>
CommitterDate: Wed Jul 17 10:49:05 2013 -0400
rgmanager: Fix for double pthread_mutex_unlock() calls
Fix a few places where pthread_mutex_unlock() could be called
on an unlocked mutex.
Resolves: rhbz#983296
Signed-off-by: Ryan McCabe <rmccabe(a)redhat.com>
---
rgmanager/src/clulib/vft.c | 4 ++--
rgmanager/src/daemons/rg_event.c | 5 ++---
2 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/rgmanager/src/clulib/vft.c b/rgmanager/src/clulib/vft.c
index 0113bad..ad1f468 100644
--- a/rgmanager/src/clulib/vft.c
+++ b/rgmanager/src/clulib/vft.c
@@ -1007,7 +1007,6 @@ vf_key_init_nt(const char *keyid, int timeout, vf_vote_cb_t vote_cb,
newnode = kn_find_key(keyid);
if (newnode) {
printf("Key %s already initialized\n", keyid);
- pthread_mutex_unlock(&key_list_mutex);
return -1;
}
@@ -1015,7 +1014,6 @@ vf_key_init_nt(const char *keyid, int timeout, vf_vote_cb_t vote_cb,
if (newnode == NULL) {
fprintf(stderr, "malloc fail3 err=%d\n", errno);
- pthread_mutex_unlock(&key_list_mutex);
return -1;
}
@@ -1493,6 +1491,8 @@ vf_read(cluster_member_list_t *membership, const char *keyid, uint64_t *view,
pthread_mutex_unlock(&vf_mutex);
return l;
}
+
+ pthread_mutex_lock(&key_list_mutex);
}
*data = malloc(key_node->kn_datalen);
diff --git a/rgmanager/src/daemons/rg_event.c b/rgmanager/src/daemons/rg_event.c
index 6b1023a..4a747e0 100644
--- a/rgmanager/src/daemons/rg_event.c
+++ b/rgmanager/src/daemons/rg_event.c
@@ -332,9 +332,8 @@ event_master(void)
//logt_print(LOG_DEBUG, "%d is master\n", mi->m_nodeid);
goto out;
}
- }
-
- pthread_mutex_unlock(&mi_mutex);
+ } else
+ pthread_mutex_unlock(&mi_mutex);
memset(&_master_lock, 0, sizeof(_master_lock));
if (clu_lock(LKM_EXMODE, &_master_lock, LKF_NOQUEUE,
10 years, 9 months
cluster: RHEL6 - rgmanager: Fix potential unlocked memory access
by Ryan McCabe
Gitweb: http://git.fedorahosted.org/git/?p=cluster.git;a=commitdiff;h=ceb12b85b62...
Commit: ceb12b85b625d57d0d219e55e2e179192fee53d6
Parent: ea7368961f57b06d7553977275beec3f261191a2
Author: Ryan McCabe <rmccabe(a)redhat.com>
AuthorDate: Tue Feb 26 10:57:47 2013 -0500
Committer: Ryan McCabe <rmccabe(a)redhat.com>
CommitterDate: Wed Jul 17 10:49:05 2013 -0400
rgmanager: Fix potential unlocked memory access
Fix a potential unlocked access of the resource list.
Related: rhbz#983296
Signed-off-by: Ryan McCabe <rmccabe(a)redhat.com>
---
rgmanager/src/daemons/groups.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/rgmanager/src/daemons/groups.c b/rgmanager/src/daemons/groups.c
index ee0fc81..e802c2f 100644
--- a/rgmanager/src/daemons/groups.c
+++ b/rgmanager/src/daemons/groups.c
@@ -1750,7 +1750,9 @@ init_resource_groups(int reconfigure, int do_init)
do_condstops();
+ pthread_rwlock_rdlock(&resource_lock);
copy_incarnations(&_resources, &reslist);
+ pthread_rwlock_unlock(&resource_lock);
}
/* Swap in the new configuration */
10 years, 9 months
gfs2-utils: master - fsck.gfs2: Detect and fix duplicate references in hash tables
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=f81ece7e...
Commit: f81ece7e97b66d5d8c3639b2094a31723c2e427b
Parent: ea48ab1de8a5216eb7b5dc6ff7f2c9e19eb44c25
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Mon Jul 15 14:32:20 2013 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Wed Jul 17 07:31:36 2013 -0500
fsck.gfs2: Detect and fix duplicate references in hash tables
This patch checks directory hash tables for multiple occurrences
of the same leaf block. When duplicates are encountered, it checks
to see which reference is appropriate for the hash table location
based on the leaf block's hash value. The appropriate reference is
kept and all duplicates are replaced by newly created leaf blocks.
rhbz#984085
---
gfs2/fsck/pass2.c | 106 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 106 insertions(+), 0 deletions(-)
diff --git a/gfs2/fsck/pass2.c b/gfs2/fsck/pass2.c
index abf5f48..727cc18 100644
--- a/gfs2/fsck/pass2.c
+++ b/gfs2/fsck/pass2.c
@@ -1278,6 +1278,108 @@ static int fix_hashtable(struct gfs2_inode *ip, uint64_t *tbl, unsigned hsize,
return changes;
}
+/* check_hash_tbl_dups - check for the same leaf in multiple places */
+static int check_hash_tbl_dups(struct gfs2_inode *ip, uint64_t *tbl,
+ unsigned hsize, int lindex, int len)
+{
+ int l, len2;
+ uint64_t leafblk, leaf_no;
+ struct gfs2_buffer_head *lbh;
+ struct gfs2_leaf leaf;
+ struct gfs2_dirent dentry, *de;
+ int hash_index; /* index into the hash table based on the hash */
+
+ leafblk = be64_to_cpu(tbl[lindex]);
+ for (l = 0; l < hsize; l++) {
+ if (l == lindex) { /* skip the valid reference */
+ l += len - 1;
+ continue;
+ }
+ if (be64_to_cpu(tbl[l]) != leafblk)
+ continue;
+
+ for (len2 = 0; l + len2 < hsize; len2++) {
+ if (l + len2 == lindex)
+ break;
+ if (be64_to_cpu(tbl[l + len2]) != leafblk)
+ break;
+ }
+ log_err(_("Dinode %llu (0x%llx) has duplicate leaf pointers "
+ "to block %llu (0x%llx) at offsets %u (0x%x) "
+ "(for 0x%x) and %u (0x%x) (for 0x%x)\n"),
+ (unsigned long long)ip->i_di.di_num.no_addr,
+ (unsigned long long)ip->i_di.di_num.no_addr,
+ (unsigned long long)leafblk,
+ (unsigned long long)leafblk, lindex, lindex, len,
+ l, l, len2);
+
+ /* See which set of references is valid: the one passed in
+ or the duplicate we found. */
+ memset(&leaf, 0, sizeof(leaf));
+ leaf_no = leafblk;
+ if (!valid_block(ip->i_sbd, leaf_no)) /* Checked later */
+ continue;
+
+ lbh = bread(ip->i_sbd, leafblk);
+ if (gfs2_check_meta(lbh, GFS2_METATYPE_LF)) { /* Chked later */
+ brelse(lbh);
+ continue;
+ }
+
+ memset(&dentry, 0, sizeof(struct gfs2_dirent));
+ de = (struct gfs2_dirent *)(lbh->b_data +
+ sizeof(struct gfs2_leaf));
+ gfs2_dirent_in(&dentry, (char *)de);
+ hash_index = hash_table_index(dentry.de_hash, ip);
+ brelse(lbh);
+ /* check the duplicate ref first */
+ if (hash_index < l || hash_index > l + len2) {
+ log_err(_("This leaf block has hash index %d, which "
+ "is out of bounds for lindex (%d - %d)\n"),
+ hash_index, l, l + len2);
+ if (!query( _("Fix the hash table? (y/n) "))) {
+ log_err(_("Hash table not fixed.\n"));
+ return 0;
+ }
+ /* Adjust the ondisk block count. The original value
+ may have been correct without the duplicates but
+ pass1 would have counted them and adjusted the
+ count to include them. So we must subtract them. */
+ ip->i_di.di_blocks--;
+ bmodified(ip->i_bh);
+ pad_with_leafblks(ip, tbl, l, len2);
+ } else {
+ log_debug(_("Hash index 0x%x is the proper "
+ "reference to leaf 0x%llx.\n"),
+ l, (unsigned long long)leafblk);
+ }
+ /* Check the original ref: both references might be bad.
+ If both were bad, just return and if we encounter it
+ again, we'll treat it as new. If the original ref is not
+ bad, keep looking for (and fixing) other instances. */
+ if (hash_index < lindex || hash_index > lindex + len) {
+ log_err(_("This leaf block has hash index %d, which "
+ "is out of bounds for lindex (%d - %d).\n"),
+ hash_index, lindex, lindex + len);
+ if (!query( _("Fix the hash table? (y/n) "))) {
+ log_err(_("Hash table not fixed.\n"));
+ return 0;
+ }
+ ip->i_di.di_blocks--;
+ bmodified(ip->i_bh);
+ pad_with_leafblks(ip, tbl, lindex, len);
+ /* At this point we know both copies are bad, so we
+ return to start fresh */
+ return -EFAULT;
+ } else {
+ log_debug(_("Hash index 0x%x is the proper "
+ "reference to leaf 0x%llx.\n"),
+ lindex, (unsigned long long)leafblk);
+ }
+ }
+ return 0;
+}
+
/* check_hash_tbl - check that the hash table is sane
*
* We've got to make sure the hash table is sane. Each leaf needs to
@@ -1372,6 +1474,10 @@ static int check_hash_tbl(struct gfs2_inode *ip, uint64_t *tbl,
lindex += proper_len;
continue;
}
+
+ if (check_hash_tbl_dups(ip, tbl, hsize, lindex, len))
+ continue;
+
/* Make sure they call on proper leaf-split boundaries. This
is the calculation used by the kernel, and dir_split_leaf */
proper_start = (lindex & ~(proper_len - 1));
10 years, 9 months
gfs2-utils: master - fsck.gfs2: avoid negative number in leaf depth
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=ea48ab1d...
Commit: ea48ab1de8a5216eb7b5dc6ff7f2c9e19eb44c25
Parent: 6a5197849a38cfa3430642c758c4bb603713f9c7
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Mon Jul 15 14:25:43 2013 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Wed Jul 17 07:31:36 2013 -0500
fsck.gfs2: avoid negative number in leaf depth
If a leaf block appears many times by mistake in the same hash table,
there's a chance it belongs in a different directory's hash table, and
was put there by mistake. In that case, the leaf depth may be too
big for the directory in which it improperly appears. When that happens,
function check_leaf_depth can come up with a negative number when it
calculates the depth. This patch prevents the negative leaf depth error
by flagging an error when it determines the leaf depth is wrong.
The error causes pass2 to relocate the leaf to lost+found when it returns.
rhbz#984085
---
gfs2/fsck/pass2.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/gfs2/fsck/pass2.c b/gfs2/fsck/pass2.c
index f97e494..abf5f48 100644
--- a/gfs2/fsck/pass2.c
+++ b/gfs2/fsck/pass2.c
@@ -276,6 +276,9 @@ static int check_leaf_depth(struct gfs2_inode *ip, uint64_t leaf_no,
factor++;
divisor >>= 1;
}
+ if (ip->i_di.di_depth < factor) /* can't be fixed--leaf must be on the
+ wrong dinode. */
+ return -1;
correct_depth = ip->i_di.di_depth - factor;
if (cur_depth == correct_depth)
return 0;
10 years, 9 months
gfs2-utils: master - fsck.gfs2: don't check newly created lost+found in pass2
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=6a519784...
Commit: 6a5197849a38cfa3430642c758c4bb603713f9c7
Parent: 3006c68feb0da6f26d00ade419af0b8d3be30ef1
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Mon Jul 15 14:11:34 2013 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Wed Jul 17 07:31:36 2013 -0500
fsck.gfs2: don't check newly created lost+found in pass2
This patch checks whether lost+found was created during the run
and if so, it skips pass2 directory checking for lost+found.
The reason we need to do this is because when lost+found is created,
it sets the directory linkage count to 1. If pass2 checks the
directory, it will add it a second time because it checks it like
every other normal directory. Therefore, the linkage counts get off.
Plus, it's a waste of time to check it, since we just built it.
rhbz#984085
---
gfs2/fsck/fsck.h | 1 +
gfs2/fsck/lost_n_found.c | 1 +
gfs2/fsck/main.c | 1 +
gfs2/fsck/pass2.c | 8 ++++++++
4 files changed, 11 insertions(+), 0 deletions(-)
diff --git a/gfs2/fsck/fsck.h b/gfs2/fsck/fsck.h
index 6d888af..8555e9e 100644
--- a/gfs2/fsck/fsck.h
+++ b/gfs2/fsck/fsck.h
@@ -131,6 +131,7 @@ struct gfs2_options {
extern struct gfs2_options opts;
extern struct gfs2_inode *lf_dip; /* Lost and found directory inode */
+extern int lf_was_created;
extern struct gfs2_bmap *bl;
extern uint64_t last_fs_block, last_reported_block;
extern int64_t last_reported_fblock;
diff --git a/gfs2/fsck/lost_n_found.c b/gfs2/fsck/lost_n_found.c
index 3226ac9..919cb2f 100644
--- a/gfs2/fsck/lost_n_found.c
+++ b/gfs2/fsck/lost_n_found.c
@@ -132,6 +132,7 @@ void make_sure_lf_exists(struct gfs2_inode *ip)
q = block_type(lf_dip->i_di.di_num.no_addr);
if (q != gfs2_inode_dir) {
+ lf_was_created = 1;
/* This is a new lost+found directory, so set its block type
and increment link counts for the directories */
/* FIXME: i'd feel better about this if fs_mkdir returned
diff --git a/gfs2/fsck/main.c b/gfs2/fsck/main.c
index 9c3b06d..287404d 100644
--- a/gfs2/fsck/main.c
+++ b/gfs2/fsck/main.c
@@ -22,6 +22,7 @@
struct gfs2_options opts = {0};
struct gfs2_inode *lf_dip = NULL; /* Lost and found directory inode */
+int lf_was_created = 0;
struct gfs2_bmap *bl = NULL;
uint64_t last_fs_block, last_reported_block = -1;
int64_t last_reported_fblock = -1000000;
diff --git a/gfs2/fsck/pass2.c b/gfs2/fsck/pass2.c
index dabfc13..f97e494 100644
--- a/gfs2/fsck/pass2.c
+++ b/gfs2/fsck/pass2.c
@@ -1683,6 +1683,14 @@ int pass2(struct gfs2_sbd *sdp)
if (q != gfs2_inode_dir)
continue;
+ /* If we created lost+found, its links should have been
+ properly adjusted, so don't check it. */
+ if (lf_was_created &&
+ (dirblk == lf_dip->i_di.di_num.no_addr)) {
+ log_debug(_("Pass2 skipping the new lost+found.\n"));
+ continue;
+ }
+
log_debug( _("Checking directory inode at block %llu (0x%llx)\n"),
(unsigned long long)dirblk, (unsigned long long)dirblk);
10 years, 9 months