cluster: STABLE3 - doc: Update autogenerated documentation
by Lon Hohberger
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 4eee6eebae4f4f6c74090dad90bd5c08ad52e0b7
Parent: 1adc2300a6946b98f2051827c0d85b8da5870375
Author: Lon Hohberger <lhh(a)redhat.com>
AuthorDate: Tue Aug 31 10:13:11 2010 -0400
Committer: Lon Hohberger <lhh(a)redhat.com>
CommitterDate: Tue Aug 31 10:13:11 2010 -0400
doc: Update autogenerated documentation
Signed-off-by: Lon Hohberger <lhh(a)redhat.com>
---
doc/cluster_conf.html | 26 ++++++++++++++++++++++----
1 files changed, 22 insertions(+), 4 deletions(-)
diff --git a/doc/cluster_conf.html b/doc/cluster_conf.html
index d3e05b8..0a7c4eb 100644
--- a/doc/cluster_conf.html
+++ b/doc/cluster_conf.html
@@ -396,15 +396,16 @@ Defines the properties of a device used for fencing or unfencing a node. fenced(
<tr><td><b>aptpl</b></td><td></td></tr>
<tr><td><b>auth</b></td><td>For IPMI LAN only. Authentication Type: none, password, md2, or md5</td></tr>
<tr><td><b>channel_address</b></td><td>VM Channel IP address (default=10.0.2.179)</td></tr>
- <tr><td><b>cipher</b></td><td>Ciphersuite to use (same as ipmitool -C parameter)</td></tr>
<tr><td><b>cmd_prompt</b></td><td>Force command prompt</td></tr>
<tr><td><b>community</b></td><td>Set the community string</td></tr>
<tr><td><b>cserver</b></td><td>The hostname (and optionally the username in the form of username@hostname) assigned to the device. Refer to the fence_egenera(8) man page for more information.</td></tr>
<tr><td><b>debug</b></td><td>Specify (stdin) or increment (command line) debug level</td></tr>
+ <tr><td><b>delay</b></td><td>Wait this many seconds before fencing is started. fence_egenera(8)</td></tr>
<tr><td><b>device</b></td><td>The device the switch is connected to on the controlling host.</td></tr>
<tr><td><b>devices</b></td><td>List of devices to fence (separated by commas).</td></tr>
<tr><td><b>domain</b></td><td>Virtual Machine (domain name) to fence (deprecated)</td></tr>
<tr><td><b>drac_version</b></td><td>Force DRAC version to use</td></tr>
+ <tr><td><b>esh</b></td><td>Path to the esh command on the cserver. fence_egenera(8)</td></tr>
<tr><td><b>exec</b></td><td>Command to execute</td></tr>
<tr><td><b>hash</b></td><td>Packet hash strength (none, sha1, [sha256], sha512)</td></tr>
<tr><td><b>help</b></td><td>Display help and exit</td></tr>
@@ -421,8 +422,10 @@ Defines the properties of a device used for fencing or unfencing a node. fenced(
<tr><td><b>lanplus</b></td><td>For IPMI LAN only. Set value to either True or 1; leave out for false.</td></tr>
<tr><td><b>logfile</b></td><td>Location to output logs from fence_scsi.</td></tr>
<tr><td><b>login</b></td><td>The login name used to access the device. </td></tr>
+ <tr><td><b>login_timeout</b></td><td>Wait X seconds for cmd prompt after login</td></tr>
+ <tr><td><b>lpan</b></td><td>The lpan to operate on. fence_egenera(8)</td></tr>
<tr><td><b>managed</b></td><td>Managed system name</td></tr>
- <tr><td><b>method</b></td><td>Method to fence (onoff or cycle)</td></tr>
+ <tr><td><b>missing_as_off</b></td><td>Missing port returns OFF instead of failure</td></tr>
<tr><td><b>module_name</b></td><td>DRAC/MC module name</td></tr>
<tr><td><b>multicast_address</b></td><td>Multicast address (default=225.0.0.12 / ff05::3:1)</td></tr>
<tr><td><b>nodename</b></td><td>Name of the node to be fenced. Refer to fence_scsi(8) for more information.</td></tr>
@@ -431,7 +434,11 @@ Defines the properties of a device used for fencing or unfencing a node. fenced(
<tr><td><b>passwd</b></td><td>The password used to authenticate the connection to the device.</td></tr>
<tr><td><b>passwd_script</b></td><td>The script that supplies a password for access to the fence device. Using this supersedes the Password parameter.</td></tr>
<tr><td><b>port</b></td><td>The switch outlet number.</td></tr>
+ <tr><td><b>power_timeout</b></td><td>Test X seconds for status change after ON/OFF</td></tr>
+ <tr><td><b>power_wait</b></td><td>Wait X seconds after issuing ON/OFF</td></tr>
+ <tr><td><b>pserver</b></td><td>The pserver to operate on. fence_egenera(8)</td></tr>
<tr><td><b>retrans</b></td><td>Multicast retransmit time (in 1/10sec; default=20)</td></tr>
+ <tr><td><b>retry_on</b></td><td>Count of attempts to retry power on</td></tr>
<tr><td><b>ribcl</b></td><td>Force ribcl version to use</td></tr>
<tr><td><b>rpowerpath</b></td><td></td></tr>
<tr><td><b>secure</b></td><td>SSH connection</td></tr>
@@ -439,6 +446,7 @@ Defines the properties of a device used for fencing or unfencing a node. fenced(
<tr><td><b>serial_device</b></td><td>Serial device (default=/dev/ttyS1)</td></tr>
<tr><td><b>serial_params</b></td><td>Serial Parameters (default=115200,8N1)</td></tr>
<tr><td><b>servers</b></td><td>The hostname of each GNBD to disable. For multiple hostnames, separate each hostname with a space.</td></tr>
+ <tr><td><b>shell_timeout</b></td><td>Wait X seconds for cmd promprt after issuing command</td></tr>
<tr><td><b>snmp_auth_prot</b></td><td>Set authentication protocol (MD5|SHA)</td></tr>
<tr><td><b>snmp_priv_passwd</b></td><td>Set privacy protocol password</td></tr>
<tr><td><b>snmp_priv_passwd_script</b></td><td>Script to run to retrieve privacy password</td></tr>
@@ -449,6 +457,7 @@ Defines the properties of a device used for fencing or unfencing a node. fenced(
<tr><td><b>switch</b></td><td>Physical switch number on device</td></tr>
<tr><td><b>timeout</b></td><td>Fencing timeout (in seconds; default=30)</td></tr>
<tr><td><b>udpport</b></td><td>UDP/TCP port to use for connection with device</td></tr>
+ <tr><td><b>user</b></td><td>See fence_egenera(8)</td></tr>
<tr><td><b>use_uuid</b></td><td>Treat [domain] as UUID instead of domain name. This is provided for compatibility with older fence_xvmd installations.</td></tr>
<tr><td><b>verbose</b></td><td>Verbose mode</td></tr>
<tr><td><b>version</b></td><td>Display version information and exit</td></tr>
@@ -546,15 +555,16 @@ Defines fence device properties. fenced(8)<br/>
<tr><td><b>aptpl</b></td><td></td></tr>
<tr><td><b>auth</b></td><td>For IPMI LAN only. Authentication Type: none, password, md2, or md5</td></tr>
<tr><td><b>channel_address</b></td><td>VM Channel IP address (default=10.0.2.179)</td></tr>
- <tr><td><b>cipher</b></td><td>Ciphersuite to use (same as ipmitool -C parameter)</td></tr>
<tr><td><b>cmd_prompt</b></td><td>Force command prompt</td></tr>
<tr><td><b>community</b></td><td>Set the community string</td></tr>
<tr><td><b>cserver</b></td><td>The hostname (and optionally the username in the form of username@hostname) assigned to the device. Refer to the fence_egenera(8) man page for more information.</td></tr>
<tr><td><b>debug</b></td><td>Specify (stdin) or increment (command line) debug level</td></tr>
+ <tr><td><b>delay</b></td><td>Wait this many seconds before fencing is started. fence_egenera(8)</td></tr>
<tr><td><b>device</b></td><td>The device the switch is connected to on the controlling host.</td></tr>
<tr><td><b>devices</b></td><td>List of devices to fence (separated by commas).</td></tr>
<tr><td><b>domain</b></td><td>Virtual Machine (domain name) to fence (deprecated)</td></tr>
<tr><td><b>drac_version</b></td><td>Force DRAC version to use</td></tr>
+ <tr><td><b>esh</b></td><td>Path to the esh command on the cserver. fence_egenera(8)</td></tr>
<tr><td><b>exec</b></td><td>Command to execute</td></tr>
<tr><td><b>hash</b></td><td>Packet hash strength (none, sha1, [sha256], sha512)</td></tr>
<tr><td><b>help</b></td><td>Display help and exit</td></tr>
@@ -571,8 +581,10 @@ Defines fence device properties. fenced(8)<br/>
<tr><td><b>lanplus</b></td><td>For IPMI LAN only. Set value to either True or 1; leave out for false.</td></tr>
<tr><td><b>logfile</b></td><td>Location to output logs from fence_scsi.</td></tr>
<tr><td><b>login</b></td><td>The login name used to access the device. </td></tr>
+ <tr><td><b>login_timeout</b></td><td>Wait X seconds for cmd prompt after login</td></tr>
+ <tr><td><b>lpan</b></td><td>The lpan to operate on. fence_egenera(8)</td></tr>
<tr><td><b>managed</b></td><td>Managed system name</td></tr>
- <tr><td><b>method</b></td><td>Method to fence (onoff or cycle)</td></tr>
+ <tr><td><b>missing_as_off</b></td><td>Missing port returns OFF instead of failure</td></tr>
<tr><td><b>module_name</b></td><td>DRAC/MC module name</td></tr>
<tr><td><b>multicast_address</b></td><td>Multicast address (default=225.0.0.12 / ff05::3:1)</td></tr>
<tr><td><b>nodename</b></td><td>Name of the node to be fenced. Refer to fence_scsi(8) for more information.</td></tr>
@@ -581,7 +593,11 @@ Defines fence device properties. fenced(8)<br/>
<tr><td><b>passwd</b></td><td>The password used to authenticate the connection to the device.</td></tr>
<tr><td><b>passwd_script</b></td><td>The script that supplies a password for access to the fence device. Using this supersedes the Password parameter.</td></tr>
<tr><td><b>port</b></td><td>The switch outlet number.</td></tr>
+ <tr><td><b>power_timeout</b></td><td>Test X seconds for status change after ON/OFF</td></tr>
+ <tr><td><b>power_wait</b></td><td>Wait X seconds after issuing ON/OFF</td></tr>
+ <tr><td><b>pserver</b></td><td>The pserver to operate on. fence_egenera(8)</td></tr>
<tr><td><b>retrans</b></td><td>Multicast retransmit time (in 1/10sec; default=20)</td></tr>
+ <tr><td><b>retry_on</b></td><td>Count of attempts to retry power on</td></tr>
<tr><td><b>ribcl</b></td><td>Force ribcl version to use</td></tr>
<tr><td><b>rpowerpath</b></td><td></td></tr>
<tr><td><b>secure</b></td><td>SSH connection</td></tr>
@@ -589,6 +605,7 @@ Defines fence device properties. fenced(8)<br/>
<tr><td><b>serial_device</b></td><td>Serial device (default=/dev/ttyS1)</td></tr>
<tr><td><b>serial_params</b></td><td>Serial Parameters (default=115200,8N1)</td></tr>
<tr><td><b>servers</b></td><td>The hostname of each GNBD to disable. For multiple hostnames, separate each hostname with a space.</td></tr>
+ <tr><td><b>shell_timeout</b></td><td>Wait X seconds for cmd promprt after issuing command</td></tr>
<tr><td><b>snmp_auth_prot</b></td><td>Set authentication protocol (MD5|SHA)</td></tr>
<tr><td><b>snmp_priv_passwd</b></td><td>Set privacy protocol password</td></tr>
<tr><td><b>snmp_priv_passwd_script</b></td><td>Script to run to retrieve privacy password</td></tr>
@@ -599,6 +616,7 @@ Defines fence device properties. fenced(8)<br/>
<tr><td><b>switch</b></td><td>Physical switch number on device</td></tr>
<tr><td><b>timeout</b></td><td>Fencing timeout (in seconds; default=30)</td></tr>
<tr><td><b>udpport</b></td><td>UDP/TCP port to use for connection with device</td></tr>
+ <tr><td><b>user</b></td><td>See fence_egenera(8)</td></tr>
<tr><td><b>use_uuid</b></td><td>Treat [domain] as UUID instead of domain name. This is provided for compatibility with older fence_xvmd installations.</td></tr>
<tr><td><b>verbose</b></td><td>Verbose mode</td></tr>
<tr><td><b>version</b></td><td>Display version information and exit</td></tr>
13 years, 8 months
cluster: STABLE3 - config: Add fence_egenera options to ldif
by Lon Hohberger
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 1adc2300a6946b98f2051827c0d85b8da5870375
Parent: 536a21273c5cc23421fdb042759e261cdd2fa848
Author: Lon Hohberger <lhh(a)redhat.com>
AuthorDate: Tue Aug 31 10:12:25 2010 -0400
Committer: Lon Hohberger <lhh(a)redhat.com>
CommitterDate: Tue Aug 31 10:12:25 2010 -0400
config: Add fence_egenera options to ldif
Signed-off-by: Lon Hohberger <lhh(a)redhat.com>
---
config/plugins/ldap/99cluster.ldif | 48 ++++++++++++++++++++++++-----------
config/plugins/ldap/ldap-base.csv | 3 +-
2 files changed, 35 insertions(+), 16 deletions(-)
diff --git a/config/plugins/ldap/99cluster.ldif b/config/plugins/ldap/99cluster.ldif
index 31c2894..f66996c 100644
--- a/config/plugins/ldap/99cluster.ldif
+++ b/config/plugins/ldap/99cluster.ldif
@@ -1,4 +1,4 @@
-# Auto-generated @ 2010-08-11 14:59:11
+# Auto-generated @ 2010-08-31 10:12:20
dn: cn=schema
attributeTypes: (
1.3.6.1.4.1.2312.8.1.1.1 NAME 'rhcsConfig-version'
@@ -589,6 +589,36 @@ attributeTypes: (
SINGLE-VALUE
)
attributeTypes: (
+ 1.3.6.1.4.1.2312.8.1.1.226 NAME 'rhcsPserver'
+ EQUALITY caseExactIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+ SINGLE-VALUE
+ )
+attributeTypes: (
+ 1.3.6.1.4.1.2312.8.1.1.225 NAME 'rhcsLpan'
+ EQUALITY caseExactIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+ SINGLE-VALUE
+ )
+attributeTypes: (
+ 1.3.6.1.4.1.2312.8.1.1.288 NAME 'rhcsEsh'
+ EQUALITY caseExactIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+ SINGLE-VALUE
+ )
+attributeTypes: (
+ 1.3.6.1.4.1.2312.8.1.1.219 NAME 'rhcsUser'
+ EQUALITY caseExactIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+ SINGLE-VALUE
+ )
+attributeTypes: (
+ 1.3.6.1.4.1.2312.8.1.1.286 NAME 'rhcsDelay'
+ EQUALITY caseExactIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+ SINGLE-VALUE
+ )
+attributeTypes: (
1.3.6.1.4.1.2312.8.1.1.49 NAME 'rhcsRpowerpath'
EQUALITY caseExactIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
@@ -733,12 +763,6 @@ attributeTypes: (
SINGLE-VALUE
)
attributeTypes: (
- 1.3.6.1.4.1.2312.8.1.1.286 NAME 'rhcsDelay'
- EQUALITY caseExactIA5Match
- SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
- SINGLE-VALUE
- )
-attributeTypes: (
1.3.6.1.4.1.2312.8.1.1.57 NAME 'rhcsPartition'
EQUALITY caseExactIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
@@ -1573,12 +1597,6 @@ attributeTypes: (
SINGLE-VALUE
)
attributeTypes: (
- 1.3.6.1.4.1.2312.8.1.1.219 NAME 'rhcsUser'
- EQUALITY caseExactIA5Match
- SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
- SINGLE-VALUE
- )
-attributeTypes: (
1.3.6.1.4.1.2312.8.1.1.220 NAME 'rhcsHome'
EQUALITY caseExactIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
@@ -1700,7 +1718,7 @@ objectClasses: (
objectClasses: (
1.3.6.1.4.1.2312.8.1.2.5 NAME 'rhcsFencedevice' SUP top STRUCTURAL
MUST ( rhcsAgent $ name )
- MAY ( rhcsRibcl $ rhcsSsl $ rhcsIo-fencing $ rhcsSwitch $ rhcsModule-name $ rhcsDrac-version $ rhcsUdpport $ rhcsSnmp-priv-passwd-script $ rhcsSnmp-priv-passwd $ rhcsSnmp-priv-prot $ rhcsSnmp-sec-level $ rhcsSnmp-auth-prot $ rhcsCommunity $ rhcsSnmp-version $ rhcsMissing-as-off $ rhcsInet6-only $ rhcsInet4-only $ rhcsCmd-prompt $ rhcsHmc-version $ rhcsManaged $ rhcsPartition $ rhcsDelay $ rhcsRetry-on $ rhcsPower-wait $ rhcsLogin-timeout $ rhcsShell-timeout $ rhcsPower-timeout $ rhcsSeparator $ rhcsHelp $ rhcsVersion $ rhcsVerbose $ rhcsVmware-datacenter $ rhcsIdentity-file $ rhcsSecure $ rhcsVmware-type $ rhcsExec $ rhcsChannel-address $ rhcsSerial-params $ rhcsSerial-device $ rhcsTimeout $ rhcsUse-uuid $ rhcsDomain $ rhcsKey-file $ rhcsHash $ rhcsRetrans $ rhcsIpport $ rhcsMulticast-address $ rhcsIp-family $ rhcsDebug $ rhcsOption $ rhcsRpowerpath $ rhcsCserver $ rhcsServers $ rhcsAptpl $ rhcsLogfile $ rhcsAction $ rhcsDevices $ rhcsKey $ rhcsNodename $ rhcsLanplus $ rhcsAuth $ rhcsPasswd-script $ rhcsPasswd $ rhcsLogin $ rhcsIpaddr $ rhcsPort $ rhcsDevice )
+ MAY ( rhcsRibcl $ rhcsSsl $ rhcsIo-fencing $ rhcsSwitch $ rhcsModule-name $ rhcsDrac-version $ rhcsUdpport $ rhcsSnmp-priv-passwd-script $ rhcsSnmp-priv-passwd $ rhcsSnmp-priv-prot $ rhcsSnmp-sec-level $ rhcsSnmp-auth-prot $ rhcsCommunity $ rhcsSnmp-version $ rhcsMissing-as-off $ rhcsInet6-only $ rhcsInet4-only $ rhcsCmd-prompt $ rhcsHmc-version $ rhcsManaged $ rhcsPartition $ rhcsRetry-on $ rhcsPower-wait $ rhcsLogin-timeout $ rhcsShell-timeout $ rhcsPower-timeout $ rhcsSeparator $ rhcsHelp $ rhcsVersion $ rhcsVerbose $ rhcsVmware-datacenter $ rhcsIdentity-file $ rhcsSecure $ rhcsVmware-type $ rhcsExec $ rhcsChannel-address $ rhcsSerial-params $ rhcsSerial-device $ rhcsTimeout $ rhcsUse-uuid $ rhcsDomain $ rhcsKey-file $ rhcsHash $ rhcsRetrans $ rhcsIpport $ rhcsMulticast-address $ rhcsIp-family $ rhcsDebug $ rhcsOption $ rhcsRpowerpath $ rhcsDelay $ rhcsUser $ rhcsEsh $ rhcsLpan $ rhcsPserver $ rhcsCserver $ rhcsServers $ rhcsAptpl $ rhcsLogfile $ rhcsAction $ rhcsDevices $ rhcsKey $ rhcsNodename $ rhcsLanplus $ rhcsAuth $ rhcsPasswd-script $ rhcsPasswd $ rhcsLogin $ rhcsIpaddr $ rhcsPort $ rhcsDevice )
)
objectClasses: (
1.3.6.1.4.1.2312.8.1.2.21 NAME 'rhcsRm' SUP top STRUCTURAL
@@ -1866,5 +1884,5 @@ objectClasses: (
objectClasses: (
1.3.6.1.4.1.2312.8.1.2.6 NAME 'rhcsDevice' SUP top STRUCTURAL
MUST ( name )
- MAY ( rhcsRibcl $ rhcsSsl $ rhcsIo-fencing $ rhcsSwitch $ rhcsModule-name $ rhcsDrac-version $ rhcsUdpport $ rhcsSnmp-priv-passwd-script $ rhcsSnmp-priv-passwd $ rhcsSnmp-priv-prot $ rhcsSnmp-sec-level $ rhcsSnmp-auth-prot $ rhcsCommunity $ rhcsSnmp-version $ rhcsMissing-as-off $ rhcsInet6-only $ rhcsInet4-only $ rhcsCmd-prompt $ rhcsHmc-version $ rhcsManaged $ rhcsPartition $ rhcsDelay $ rhcsRetry-on $ rhcsPower-wait $ rhcsLogin-timeout $ rhcsShell-timeout $ rhcsPower-timeout $ rhcsSeparator $ rhcsHelp $ rhcsVersion $ rhcsVerbose $ rhcsVmware-datacenter $ rhcsIdentity-file $ rhcsSecure $ rhcsVmware-type $ rhcsExec $ rhcsChannel-address $ rhcsSerial-params $ rhcsSerial-device $ rhcsTimeout $ rhcsUse-uuid $ rhcsDomain $ rhcsKey-file $ rhcsHash $ rhcsRetrans $ rhcsIpport $ rhcsMulticast-address $ rhcsIp-family $ rhcsDebug $ rhcsOption $ rhcsRpowerpath $ rhcsCserver $ rhcsServers $ rhcsAptpl $ rhcsLogfile $ rhcsAction $ rhcsDevices $ rhcsKey $ rhcsNodename $ rhcsLanplus $ rhcsAuth $ rhcsPasswd-script $ rhcsPasswd $ rhcsLogin $ rhcsIpaddr $ rhcsPort $ rhcsDevice )
+ MAY ( rhcsRibcl $ rhcsSsl $ rhcsIo-fencing $ rhcsSwitch $ rhcsModule-name $ rhcsDrac-version $ rhcsUdpport $ rhcsSnmp-priv-passwd-script $ rhcsSnmp-priv-passwd $ rhcsSnmp-priv-prot $ rhcsSnmp-sec-level $ rhcsSnmp-auth-prot $ rhcsCommunity $ rhcsSnmp-version $ rhcsMissing-as-off $ rhcsInet6-only $ rhcsInet4-only $ rhcsCmd-prompt $ rhcsHmc-version $ rhcsManaged $ rhcsPartition $ rhcsRetry-on $ rhcsPower-wait $ rhcsLogin-timeout $ rhcsShell-timeout $ rhcsPower-timeout $ rhcsSeparator $ rhcsHelp $ rhcsVersion $ rhcsVerbose $ rhcsVmware-datacenter $ rhcsIdentity-file $ rhcsSecure $ rhcsVmware-type $ rhcsExec $ rhcsChannel-address $ rhcsSerial-params $ rhcsSerial-device $ rhcsTimeout $ rhcsUse-uuid $ rhcsDomain $ rhcsKey-file $ rhcsHash $ rhcsRetrans $ rhcsIpport $ rhcsMulticast-address $ rhcsIp-family $ rhcsDebug $ rhcsOption $ rhcsRpowerpath $ rhcsDelay $ rhcsUser $ rhcsEsh $ rhcsLpan $ rhcsPserver $ rhcsCserver $ rhcsServers $ rhcsAptpl $ rhcsLogfile $ rhcsAction $ rhcsDevices $ rhcsKey $ rhcsNodename $ rhcsLanplus $ rhcsAuth $ rhcsPasswd-script $ rhcsPasswd $ rhcsLogin $ rhcsIpaddr $ rhcsPort $ rhcsDevice )
)
diff --git a/config/plugins/ldap/ldap-base.csv b/config/plugins/ldap/ldap-base.csv
index 2684c32..7e6ccf3 100644
--- a/config/plugins/ldap/ldap-base.csv
+++ b/config/plugins/ldap/ldap-base.csv
@@ -1,4 +1,4 @@
-# Max attribute value: 287
+# Max attribute value: 288
# Max object class value: 61
obj,rhcsCluster,cluster,1
obj,rhcsCman,cman,3
@@ -347,3 +347,4 @@ attr,rhcsPower-wait,power_wait,284
attr,rhcsRetry-on,retry_on,285
attr,rhcsDelay,delay,286
attr,rhcsMissing-as-off,missing_as_off,287
+attr,rhcsEsh,esh,288
13 years, 8 months
cluster: STABLE3 - config: Fix broken fence_egenera options
by Lon Hohberger
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 536a21273c5cc23421fdb042759e261cdd2fa848
Parent: 06db0246dfe847790c7c9800f4f91015cc694a7f
Author: Lon Hohberger <lhh(a)redhat.com>
AuthorDate: Tue Aug 31 10:08:36 2010 -0400
Committer: Lon Hohberger <lhh(a)redhat.com>
CommitterDate: Tue Aug 31 10:12:01 2010 -0400
config: Fix broken fence_egenera options
Signed-off-by: Lon Hohberger <lhh(a)redhat.com>
---
config/tools/xml/cluster.rng.in | 22 +++++++++++++++++++++-
1 files changed, 21 insertions(+), 1 deletions(-)
diff --git a/config/tools/xml/cluster.rng.in b/config/tools/xml/cluster.rng.in
index bb11edf..4c0fef1 100644
--- a/config/tools/xml/cluster.rng.in
+++ b/config/tools/xml/cluster.rng.in
@@ -2322,10 +2322,30 @@ To validate your cluster.conf against this schema, run:
an optional ESH path. Presumably those should be attributes in
the schema. We need more invormation on this. -->
<group>
- <attribute name="cserver" rha:description="The hostname (and
+ <optional>
+ <attribute name="cserver" rha:description="The hostname (and
optionally the username in the form of username@hostname)
assigned to the device. Refer to the fence_egenera(8) man
page for more information." rha:sample=""/>
+ </optional>
+ <optional>
+ <attribute name="pserver" rha:description="The pserver to operate on. fence_egenera(8)" />
+ </optional>
+ <optional>
+ <attribute name="lpan" rha:description="The lpan to operate on. fence_egenera(8)" />
+ </optional>
+ <optional>
+ <attribute name="action" rha:description="The action to perform (reboot, off, on, or status). fence_egenera(8)" />
+ </optional>
+ <optional>
+ <attribute name="esh" rha:description="Path to the esh command on the cserver. fence_egenera(8)" />
+ </optional>
+ <optional>
+ <attribute name="user" rha:description="See fence_egenera(8)" />
+ </optional>
+ <optional>
+ <attribute name="delay" rha:description="Wait this many seconds before fencing is started. fence_egenera(8)" />
+ </optional>
</group>
<!-- FIXME: It appears that xCat is no longer supported. Found no
fence agents for x Cat in RHEL 5.3. -->
13 years, 8 months
cluster: STABLE3 - rgmanager: Present flags in clustat output
by Lon Hohberger
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 06db0246dfe847790c7c9800f4f91015cc694a7f
Parent: 96c846d5aefd74b7a84078987ebb3610180f5925
Author: Lon Hohberger <lhh(a)redhat.com>
AuthorDate: Wed Aug 25 13:41:05 2010 -0400
Committer: Lon Hohberger <lhh(a)redhat.com>
CommitterDate: Tue Aug 31 10:10:49 2010 -0400
rgmanager: Present flags in clustat output
Signed-off-by: Lon Hohberger <lhh(a)redhat.com>
---
rgmanager/src/utils/clustat.c | 31 +++++++++++++++++++++++++++++--
1 files changed, 29 insertions(+), 2 deletions(-)
diff --git a/rgmanager/src/utils/clustat.c b/rgmanager/src/utils/clustat.c
index 2a93659..d400d32 100644
--- a/rgmanager/src/utils/clustat.c
+++ b/rgmanager/src/utils/clustat.c
@@ -454,6 +454,7 @@ _txt_rg_state(rg_state_t *rs, cluster_member_list_t *members, int flags,
int svcsize, int nodesize, int statsize)
{
char owner[MAXHOSTNAMELEN+1];
+ char state_string[255] = "";
char *name = rs->rs_name, *ptr;
int l;
@@ -481,11 +482,22 @@ _txt_rg_state(rg_state_t *rs, cluster_member_list_t *members, int flags,
snprintf(owner, sizeof(owner)-1, "%-.*s", nodesize,
my_memb_id_to_name(members, rs->rs_owner));
}
+
+ /* Show a frozen service */
+ if (rs->rs_flags & RG_FLAG_FROZEN) {
+ snprintf(state_string, sizeof(state_string),
+ "%-*.*s[Z]", statsize-3, statsize-3,
+ rg_state_str(rs->rs_state));
+ } else {
+ snprintf(state_string, sizeof(state_string),
+ "%-*.*s", statsize, statsize,
+ rg_state_str(rs->rs_state));
+ }
printf(" %-*.*s %-*.*s %-*.*s\n",
svcsize, svcsize, rs->rs_name,
nodesize, nodesize, owner,
- statsize, statsize, rg_state_str(rs->rs_state));
+ statsize, statsize, state_string);
}
@@ -493,10 +505,20 @@ static void
_txt_rg_state_v(rg_state_t *rs, cluster_member_list_t *members, int flags)
{
time_t t;
+ char flags_string[255] = "";
+
+ rg_flags_str(flags_string, sizeof(flags_string), rs->rs_flags,
+ (char *)", ");
printf("Service Name : %s\n", rs->rs_name);
printf(" Current State : %s (%d)\n",
rg_state_str(rs->rs_state), rs->rs_state);
+ if (rs->rs_flags)
+ printf(" Flags : %s (%d)\n",
+ flags_string, rs->rs_flags);
+ else
+ printf(" Flags : none (%d)\n",
+ rs->rs_flags);
printf(" Owner : %s\n",
my_memb_id_to_name(members, rs->rs_owner));
printf(" Last Owner : %s\n",
@@ -522,6 +544,7 @@ static void
xml_rg_state(rg_state_t *rs, cluster_member_list_t *members, int flags)
{
char time_str[32];
+ char flags_string[255] = "";
int x;
time_t t;
@@ -535,12 +558,16 @@ xml_rg_state(rg_state_t *rs, cluster_member_list_t *members, int flags)
}
}
- printf(" <group name=\"%s\" state=\"%d\" state_str=\"%s\" "
+ printf(" <group name=\"%s\" state=\"%d\" state_str=\"%s\""
+ " flags=\"%d\" flags_str=\"%s\""
" owner=\"%s\" last_owner=\"%s\" restarts=\"%d\""
" last_transition=\"%llu\" last_transition_str=\"%s\"/>\n",
rs->rs_name,
rs->rs_state,
rg_state_str(rs->rs_state),
+ rs->rs_flags,
+ rg_flags_str(flags_string, sizeof(flags_string),
+ rs->rs_flags, (char *)" "),
my_memb_id_to_name(members, rs->rs_owner),
my_memb_id_to_name(members, rs->rs_last_owner),
rs->rs_restarts,
13 years, 8 months
cluster: RHEL56 - Fix potential I/O hang after cluster mirror creation w/ --nosync
by Jonathan Brassow
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 5cf664ec4f1f08c110e14039b7945ee5d660f8fc
Parent: 95d4db6c9a10517a7ed981be2271e5a602e0bcc2
Author: Jonathan Brassow <jbrassow(a)redhat.com>
AuthorDate: Mon Aug 30 15:59:11 2010 -0500
Committer: Jonathan Brassow <jbrassow(a)redhat.com>
CommitterDate: Mon Aug 30 15:59:11 2010 -0500
Fix potential I/O hang after cluster mirror creation w/ --nosync
This patch fixes an issue where cluster mirror write I/O
can be opprobriously slow if created with '--nosync'.
One of the ways cluster mirrors coordinate I/O and recovery
amoung the different machines is by the use of the log
function 'is_remote_recovering()' which lets node know if
a region they wish to perform a write on is currently being
recovered on another node. If the region is being recovered,
the I/O is delayed.
The 'is_remote_recovering' routine has been optimized to
avoid the deluge of requests that would be issued to the
userspace log server by maintaining a marker of how far
the recovery has gotten. It can then immediately return
'not recovering' if the region being inquired about is
less than this mark. Additionally, if the region of
concern is greater than the mark, the function will
limit the number of transmissions to userspace by assuming
the region /is/ being recovered when skipping the
transmission. This limits the amount of processing
and updates the mark in 1/4 sec time steps.
This patch fixes a problem where 'the mark' is not being
updated because of faulty logic in the userspace log
daemon. When '--nosync' is used to create a cluster
mirror, the userspace log daemon never has a chance
to update the mark in the normal way. The fix is to set
the mark to "complete" if the mirror was created with
the --nosync flag.
---
cmirror/src/functions.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/cmirror/src/functions.c b/cmirror/src/functions.c
index 760a6d0..45dcbb3 100644
--- a/cmirror/src/functions.c
+++ b/cmirror/src/functions.c
@@ -1286,6 +1286,7 @@ static int clog_get_resync_work(struct clog_tfr *tfr)
LOG_SPRINT("GET - SEQ#=%u, UUID=%s, nodeid = %u:: "
"Resync work complete.",
tfr->seq, SHORT_UUID(lc->uuid), tfr->originator);
+ lc->sync_search = lc->region_count + 1;
return 0;
}
13 years, 8 months
cluster: RHEL56 - Fix potential cluster mirror corruption: 456575/471291
by Jonathan Brassow
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 95d4db6c9a10517a7ed981be2271e5a602e0bcc2
Parent: 8e5bfda2ffd80ebfcdc00cadd503bfcfd5422276
Author: Jonathan Brassow <jbrassow(a)redhat.com>
AuthorDate: Mon Aug 30 15:54:38 2010 -0500
Committer: Jonathan Brassow <jbrassow(a)redhat.com>
CommitterDate: Mon Aug 30 15:54:38 2010 -0500
Fix potential cluster mirror corruption: 456575/471291
>From my inline comments:
* If the mirror was successfully recovered, we want to always
* force every machine to write to all devices - otherwise,
* corruption will occur. Here's how:
* Node1 suffers a failure and marks a region out-of-sync
* Node2 attempts a write, gets by is_remote_recovering,
* and queries the sync status of the region - finding
* it out-of-sync.
* Node2 thinks the write should be a nosync write, but it
* hasn't suffered the drive failure that Node1 has yet.
* It then issues a generic_make_request directly to
* the primary image only - which is exactly the device
* that has suffered the failure.
* Node2 suffers a lost write - which completely bypasses the
* mirror layer because it had gone through generic_m_r.
* The file system will likely explode at this point due to
* I/O errors. If it wasn't the primary that failed, it is
* easily possible in this case to issue writes to just one
* of the remaining images - also leaving the mirror inconsistent.
*
* We let in_sync() return 1 in a cluster regardless of what is
* in the bitmap once recovery has successfully completed on a
* mirror. This ensures the mirroring code will continue to
* attempt to write to all mirror images. The worst that can
* happen for reads is that additional read attempts may be
* taken.
---
cmirror/src/functions.c | 44 ++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 42 insertions(+), 2 deletions(-)
diff --git a/cmirror/src/functions.c b/cmirror/src/functions.c
index f7270a6..760a6d0 100644
--- a/cmirror/src/functions.c
+++ b/cmirror/src/functions.c
@@ -53,6 +53,7 @@ struct log_c {
time_t delay; /* limits how fast a resume can happen after suspend */
int touched;
+ int in_sync; /* An in-sync that stays set until suspend/resume */
uint32_t region_size;
uint32_t region_count;
uint64_t sync_count;
@@ -718,6 +719,7 @@ static int clog_resume(struct clog_tfr *tfr)
if (!lc)
return -EINVAL;
+ lc->in_sync = 0;
switch (lc->resume_override) {
case 1000:
LOG_ERROR("[%s] Additional resume issued before suspend",
@@ -971,6 +973,41 @@ static int clog_in_sync(struct clog_tfr *tfr)
return -EINVAL;
*rtn = log_test_bit(lc->sync_bits, region);
+
+ /*
+ * If the mirror was successfully recovered, we want to always
+ * force every machine to write to all devices - otherwise,
+ * corruption will occur. Here's how:
+ * Node1 suffers a failure and marks a region out-of-sync
+ * Node2 attempts a write, gets by is_remote_recovering,
+ * and queries the sync status of the region - finding
+ * it out-of-sync.
+ * Node2 thinks the write should be a nosync write, but it
+ * hasn't suffered the drive failure that Node1 has yet.
+ * It then issues a generic_make_request directly to
+ * the primary image only - which is exactly the device
+ * that has suffered the failure.
+ * Node2 suffers a lost write - which completely bypasses the
+ * mirror layer because it had gone through generic_m_r.
+ * The file system will likely explode at this point due to
+ * I/O errors. If it wasn't the primary that failed, it is
+ * easily possible in this case to issue writes to just one
+ * of the remaining images - also leaving the mirror inconsistent.
+ *
+ * We let in_sync() return 1 in a cluster regardless of what is
+ * in the bitmap once recovery has successfully completed on a
+ * mirror. This ensures the mirroring code will continue to
+ * attempt to write to all mirror images. The worst that can
+ * happen for reads is that additional read attempts may be
+ * taken.
+ *
+ * Futher investigation may be required to determine if there are
+ * similar possible outcomes when the mirror is in the process of
+ * recovering. In that case, lc->in_sync would not have been set
+ * yet.
+ */
+ if (!*rtn && lc->in_sync)
+ *rtn = 1;
if (*rtn)
LOG_DBG("[%s] Region is in-sync: %llu",
SHORT_UUID(lc->uuid), (unsigned long long)region);
@@ -1302,8 +1339,8 @@ static int clog_set_region_sync(struct clog_tfr *tfr)
lc->skip_bit_warning = lc->region_count;
if (pkg->region > (lc->skip_bit_warning + 5)) {
- LOG_ERROR("*** Region #%llu skipped during recovery ***",
- (unsigned long long)lc->skip_bit_warning);
+ LOG_SPRINT("*** Region #%llu skipped during recovery ***",
+ (unsigned long long)lc->skip_bit_warning);
lc->skip_bit_warning = lc->region_count;
#ifdef DEBUG
kill(getpid(), SIGUSR1);
@@ -1344,6 +1381,9 @@ static int clog_set_region_sync(struct clog_tfr *tfr)
"(lc->sync_count > lc->region_count) - this is bad",
tfr->seq, SHORT_UUID(lc->uuid), tfr->originator);
+ if (lc->sync_count == lc->region_count)
+ lc->in_sync = 1;
+
tfr->data_size = 0;
return 0;
}
13 years, 8 months
cluster: RHEL56 - fsck.gfs2 segfaults if journals are missing
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 8e5bfda2ffd80ebfcdc00cadd503bfcfd5422276
Parent: 52b6962e42c46f4344bd94dbd7911a73e6005246
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Wed Aug 18 13:26:10 2010 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Wed Aug 18 13:26:10 2010 -0500
fsck.gfs2 segfaults if journals are missing
This patch makes it possible for fsck.gfs2 to detect missing and damaged
journals and recreate them. Previous versions of fsck.gfs2 would
segfault if journals were missing because it made assumptions about
the jindex file pointing to a valid dinode. Also, I moved function
ji_update which was exclusively used by fsck.gfs2 from libgfs2 to fsck.
rhbz#620384
---
gfs2/convert/gfs2_convert.c | 12 +++--
gfs2/fsck/fs_recovery.c | 58 ++++++++++++++++++++++-
gfs2/fsck/fs_recovery.h | 7 ++-
gfs2/fsck/pass1.c | 109 +++++++++++++++++++++++++++----------------
gfs2/fsck/pass2.c | 2 +-
gfs2/libgfs2/libgfs2.h | 27 +++++------
gfs2/libgfs2/structures.c | 109 ++++++++++++++++++++++++-------------------
gfs2/libgfs2/super.c | 43 +----------------
8 files changed, 213 insertions(+), 154 deletions(-)
diff --git a/gfs2/convert/gfs2_convert.c b/gfs2/convert/gfs2_convert.c
index b8a8cd9..899982d 100644
--- a/gfs2/convert/gfs2_convert.c
+++ b/gfs2/convert/gfs2_convert.c
@@ -1986,22 +1986,24 @@ static void conv_build_jindex(struct gfs2_sbd *sdp)
sdp->md.jiinode = createi(sdp->master_dir, "jindex", S_IFDIR | 0700,
GFS2_DIF_SYSTEM);
+ sdp->md.journal = malloc(sdp->md.journals *
+ sizeof(struct gfs2_inode *));
for (j = 0; j < sdp->md.journals; j++) {
char name[256];
- struct gfs2_inode *ip;
printf("Writing journal #%d...", j + 1);
fflush(stdout);
sprintf(name, "journal%u", j);
- ip = createi(sdp->md.jiinode, name, S_IFREG | 0600,
- GFS2_DIF_SYSTEM);
- write_journal(sdp, ip, j,
+ sdp->md.journal[j] = createi(sdp->md.jiinode, name, S_IFREG |
+ 0600, GFS2_DIF_SYSTEM);
+ write_journal(sdp, j,
sdp->jsize << 20 >> sdp->sd_sb.sb_bsize_shift);
- inode_put(&ip);
+ inode_put(&sdp->md.journal[j]);
printf("done.\n");
fflush(stdout);
}
+ free(sdp->md.journal);
if (sdp->debug) {
printf("\nJindex:\n");
gfs2_dinode_print(&sdp->md.jiinode->i_di);
diff --git a/gfs2/fsck/fs_recovery.c b/gfs2/fsck/fs_recovery.c
index 61262a2..e0706e8 100644
--- a/gfs2/fsck/fs_recovery.c
+++ b/gfs2/fsck/fs_recovery.c
@@ -27,6 +27,7 @@
#include "util.h"
#define RANDOM(values) ((values) * (random() / (RAND_MAX + 1.0)))
+#define JOURNAL_NAME_SIZE 16
unsigned int sd_found_jblocks = 0, sd_replayed_jblocks = 0;
unsigned int sd_found_metablocks = 0, sd_replayed_metablocks = 0;
@@ -553,9 +554,9 @@ out:
log_info( _("jid=%u: Failed\n"), j);
reinit:
if (query( _("Do you want to clear the journal instead? (y/n)")))
- write_journal(sdp, sdp->md.journal[j], j,
- sdp->md.journal[j]->i_di.di_size /
- sdp->sd_sb.sb_bsize);
+ error = write_journal(sdp, j,
+ sdp->md.journal[j]->i_di.di_size /
+ sdp->sd_sb.sb_bsize);
else
log_err( _("jid=%u: journal not cleared.\n"), j);
return error;
@@ -582,6 +583,7 @@ int replay_journals(struct gfs2_sbd *sdp, int preen, int force_check,
*clean_journals = 0;
+ sdp->jsize = GFS2_DEFAULT_JSIZE;
/* Get master dinode */
gfs2_lookupi(sdp->master_dir, "jindex", 6, &sdp->md.jiinode);
@@ -592,7 +594,19 @@ int replay_journals(struct gfs2_sbd *sdp, int preen, int force_check,
}
for(i = 0; i < sdp->md.journals; i++) {
+ if (!sdp->md.journal[i]) {
+ log_err(_("File system journal \"journal%d\" is "
+ "missing: pass1 will try to recreate it.\n"),
+ i);
+ continue;
+ }
if (!error) {
+ uint64_t jsize = sdp->md.journal[i]->i_di.di_size /
+ (1024 * 1024);
+
+ if (sdp->jsize == GFS2_DEFAULT_JSIZE && jsize &&
+ jsize != sdp->jsize)
+ sdp->jsize = jsize;
error = gfs2_recover_journal(sdp->md.journal[i], i,
preen, force_check,
&clean);
@@ -613,3 +627,41 @@ int replay_journals(struct gfs2_sbd *sdp, int preen, int force_check,
fsync(sdp->device_fd);
return error;
}
+
+/*
+ * ji_update - fill in journal info
+ * sdp: the incore superblock pointer
+ *
+ * Given the inode for the journal index, read in all
+ * the journal inodes.
+ *
+ * Returns: 0 on success, -1 on failure
+ */
+int ji_update(struct gfs2_sbd *sdp)
+{
+ struct gfs2_inode *jip, *ip = sdp->md.jiinode;
+ char journal_name[JOURNAL_NAME_SIZE];
+ int i;
+
+ if(!ip) {
+ log_crit("Journal index inode not found.\n");
+ return -1;
+ }
+
+ if(!(sdp->md.journal = calloc(ip->i_di.di_entries - 2, sizeof(struct gfs2_inode *)))) {
+ log_err("Unable to allocate journal index\n");
+ return -1;
+ }
+ sdp->md.journals = 0;
+ memset(journal_name, 0, sizeof(*journal_name));
+ for(i = 0; i < ip->i_di.di_entries - 2; i++) {
+ /* FIXME check snprintf return code */
+ snprintf(journal_name, JOURNAL_NAME_SIZE, "journal%u", i);
+ gfs2_lookupi(sdp->md.jiinode, journal_name, strlen(journal_name),
+ &jip);
+ sdp->md.journal[i] = jip;
+ }
+ sdp->md.journals = ip->i_di.di_entries - 2;
+ return 0;
+
+}
diff --git a/gfs2/fsck/fs_recovery.h b/gfs2/fsck/fs_recovery.h
index c86a85d..8606712 100644
--- a/gfs2/fsck/fs_recovery.h
+++ b/gfs2/fsck/fs_recovery.h
@@ -16,9 +16,10 @@
#include "libgfs2.h"
-int replay_journals(struct gfs2_sbd *sdp, int preen, int force_check,
- int *clean_journals);
-int preen_is_safe(struct gfs2_sbd *sdp, int preen, int force_check);
+extern int replay_journals(struct gfs2_sbd *sdp, int preen, int force_check,
+ int *clean_journals);
+extern int preen_is_safe(struct gfs2_sbd *sdp, int preen, int force_check);
+extern int ji_update(struct gfs2_sbd *sdp);
#endif /* __FS_RECOVERY_H__ */
diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c
index 5f18818..f584aab 100644
--- a/gfs2/fsck/pass1.c
+++ b/gfs2/fsck/pass1.c
@@ -1189,25 +1189,35 @@ static int handle_di(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh)
/* Check system inode and verify it's marked "in use" in the bitmap: */
/* Should work for all system inodes: root, master, jindex, per_node, etc. */
-static int check_system_inode(struct gfs2_inode *sysinode, const char *filename,
- void builder(struct gfs2_sbd *sbp),
- enum gfs2_mark_block mark)
+/* We have to pass the sysinode as ** because the pointer may change out from
+ under the reference by way of the builder() function. */
+static int check_system_inode(struct gfs2_sbd *sdp,
+ struct gfs2_inode **sysinode,
+ const char *filename,
+ int builder(struct gfs2_sbd *sbp),
+ enum gfs2_mark_block mark)
{
uint64_t iblock = 0;
struct dir_status ds = {0};
int error;
log_info( _("Checking system inode '%s'\n"), filename);
- if (sysinode) {
- /* Read in the system inode, look at its dentries, and start
- * reading through them */
- iblock = sysinode->i_di.di_num.no_addr;
+ if (*sysinode) {
+ iblock = (*sysinode)->i_di.di_num.no_addr;
log_info( _("System inode for '%s' is located at block %"
PRIu64 " (0x%" PRIx64 ")\n"), filename,
iblock, iblock);
-
- /* FIXME: check this block's validity */
-
+ if (gfs2_check_meta((*sysinode)->i_bh, GFS2_METATYPE_DI)) {
+ log_err( _("Found invalid system dinode at block #"
+ "%llu (0x%llx)\n"),
+ (unsigned long long)iblock,
+ (unsigned long long)iblock);
+ gfs2_blockmap_set(bl, iblock, gfs2_block_free);
+ check_n_fix_bitmap(sdp, iblock, gfs2_block_free);
+ inode_put(sysinode);
+ }
+ }
+ if (*sysinode) {
ds.q = block_type(iblock);
/* If the inode exists but the block is marked free, we might
be recovering from a corrupt bitmap. In that case, don't
@@ -1216,53 +1226,69 @@ static int check_system_inode(struct gfs2_inode *sysinode, const char *filename,
if (ds.q == gfs2_block_free) {
log_info( _("The inode exists but the block is not "
"marked 'in use'; fixing it.\n"));
- fsck_blockmap_set(sysinode,
- sysinode->i_di.di_num.no_addr,
+ fsck_blockmap_set(*sysinode,
+ (*sysinode)->i_di.di_num.no_addr,
filename, mark);
ds.q = mark;
if (mark == gfs2_inode_dir)
- dirtree_insert(sysinode->i_di.di_num.no_addr);
+ dirtree_insert((*sysinode)->i_di.di_num.no_addr);
}
} else
- log_info( _("System inode for '%s' is missing.\n"), filename);
+ log_info( _("System inode for '%s' is corrupt or missing.\n"),
+ filename);
/* If there are errors with the inode here, we need to create a new
inode and get it all setup - of course, everything will be in
lost+found then, but we *need* our system inodes before we can
do any of that. */
- if(!sysinode || ds.q != mark) {
+ if(!(*sysinode) || ds.q != mark) {
log_err( _("Invalid or missing %s system inode (should be %d, "
"is %d).\n"), filename, mark, ds.q);
if (query(_("Create new %s system inode? (y/n) "), filename)) {
- builder(sysinode->i_sbd);
- fsck_blockmap_set(sysinode,
- sysinode->i_di.di_num.no_addr,
+ log_err( _("Rebuilding system file \"%s\"\n"),
+ filename);
+ error = builder(sdp);
+ if (error) {
+ log_err( _("Error trying to rebuild system "
+ "file %s: Cannot continue\n"),
+ filename);
+ return error;
+ }
+ fsck_blockmap_set(*sysinode,
+ (*sysinode)->i_di.di_num.no_addr,
filename, mark);
ds.q = mark;
if (mark == gfs2_inode_dir)
- dirtree_insert(sysinode->i_di.di_num.no_addr);
+ dirtree_insert((*sysinode)->i_di.di_num.no_addr);
} else {
log_err( _("Cannot continue without valid %s inode\n"),
filename);
return -1;
}
}
- if (S_ISDIR(sysinode->i_di.di_mode)) {
+ if (S_ISDIR((*sysinode)->i_di.di_mode)) {
struct block_count bc = {0};
sysdir_fxns.private = &bc;
- if (sysinode->i_di.di_flags & GFS2_DIF_EXHASH)
- check_metatree(sysinode, &sysdir_fxns);
+ if ((*sysinode)->i_di.di_flags & GFS2_DIF_EXHASH)
+ check_metatree(*sysinode, &sysdir_fxns);
else
- check_linear_dir(sysinode, sysinode->i_bh,
+ check_linear_dir(*sysinode, (*sysinode)->i_bh,
&sysdir_fxns);
}
- error = handle_ip(sysinode->i_sbd, sysinode);
+ error = handle_ip(sdp, *sysinode);
return error;
}
-static void build_a_journal(struct gfs2_sbd *sdp)
+static int build_a_journal(struct gfs2_sbd *sdp)
{
+ char name[256];
+
+ /* First, try to delete the journal if it's in jindex */
+ sprintf(name, "journal%u", sdp->md.journals);
+ gfs2_dirent_del(sdp->md.jiinode, name, strlen(name));
+ /* Now rebuild it */
build_journal(sdp, sdp->md.journals, sdp->md.jiinode);
+ return 0;
}
static int check_system_inodes(struct gfs2_sbd *sdp)
@@ -1272,43 +1298,43 @@ static int check_system_inodes(struct gfs2_sbd *sdp)
/*******************************************************************
******* Check the system inode integrity *************
*******************************************************************/
- if (check_system_inode(sdp->master_dir, "master", build_master,
+ if (check_system_inode(sdp, &sdp->master_dir, "master", build_master,
gfs2_inode_dir)) {
stack;
return -1;
}
- if (check_system_inode(sdp->md.rooti, "root", build_root,
+ if (check_system_inode(sdp, &sdp->md.rooti, "root", build_root,
gfs2_inode_dir)) {
stack;
return -1;
}
- if (check_system_inode(sdp->md.inum, "inum", build_inum,
+ if (check_system_inode(sdp, &sdp->md.inum, "inum", build_inum,
gfs2_inode_file)) {
stack;
return -1;
}
- if (check_system_inode(sdp->md.statfs, "statfs", build_statfs,
+ if (check_system_inode(sdp, &sdp->md.statfs, "statfs", build_statfs,
gfs2_inode_file)) {
stack;
return -1;
}
- if (check_system_inode(sdp->md.jiinode, "jindex", build_jindex,
+ if (check_system_inode(sdp, &sdp->md.jiinode, "jindex", build_jindex,
gfs2_inode_dir)) {
stack;
return -1;
}
- if (check_system_inode(sdp->md.riinode, "rindex", build_rindex,
+ if (check_system_inode(sdp, &sdp->md.riinode, "rindex", build_rindex,
gfs2_inode_file)) {
stack;
return -1;
}
- if (check_system_inode(sdp->md.qinode, "quota", build_quota,
+ if (check_system_inode(sdp, &sdp->md.qinode, "quota", build_quota,
gfs2_inode_file)) {
stack;
return -1;
}
- if (check_system_inode(sdp->md.pinode, "per_node", build_per_node,
- gfs2_inode_dir)) {
+ if (check_system_inode(sdp, &sdp->md.pinode, "per_node",
+ build_per_node, gfs2_inode_dir)) {
stack;
return -1;
}
@@ -1320,7 +1346,7 @@ static int check_system_inodes(struct gfs2_sbd *sdp)
char jname[16];
sprintf(jname, "journal%d", sdp->md.journals);
- if (check_system_inode(sdp->md.journal[sdp->md.journals],
+ if (check_system_inode(sdp, &sdp->md.journal[sdp->md.journals],
jname, build_a_journal,
gfs2_inode_file)) {
stack;
@@ -1413,6 +1439,14 @@ int pass1(struct gfs2_sbd *sbp)
skip_this_pass = FALSE;
fflush(stdout);
}
+ if (fsck_system_inode(sbp, block)) {
+ log_debug(_("Already processed system inode "
+ "%lld (0x%llx)\n"),
+ (unsigned long long)block,
+ (unsigned long long)block);
+ first = 0;
+ continue;
+ }
bh = bread(sbp, block);
/*log_debug( _("Checking metadata block #%" PRIu64
@@ -1431,11 +1465,6 @@ int pass1(struct gfs2_sbd *sbp)
}
check_n_fix_bitmap(sbp, block,
gfs2_block_free);
- } else if (fsck_system_inode(sbp, block)) {
- log_debug(_("Already processed system inode "
- "%lld (0x%llx)\n"),
- (unsigned long long)block,
- (unsigned long long)block);
} else if (handle_di(sbp, bh) < 0) {
stack;
brelse(bh);
diff --git a/gfs2/fsck/pass2.c b/gfs2/fsck/pass2.c
index 2068802..67a121e 100644
--- a/gfs2/fsck/pass2.c
+++ b/gfs2/fsck/pass2.c
@@ -532,7 +532,7 @@ struct metawalk_fxns pass2_fxns = {
/* Check system directory inode */
/* Should work for all system directories: root, master, jindex, per_node */
int check_system_dir(struct gfs2_inode *sysinode, const char *dirname,
- void builder(struct gfs2_sbd *sbp))
+ int builder(struct gfs2_sbd *sbp))
{
uint64_t iblock = 0;
struct dir_status ds = {0};
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index f6cfc1a..cd2042a 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -480,8 +480,8 @@ extern int gfs2_dirent_next(struct gfs2_inode *dip, struct gfs2_buffer_head *bh,
extern void build_height(struct gfs2_inode *ip, int height);
extern void unstuff_dinode(struct gfs2_inode *ip);
extern unsigned int calc_tree_height(struct gfs2_inode *ip, uint64_t size);
-extern void write_journal(struct gfs2_sbd *sdp, struct gfs2_inode *ip,
- unsigned int j, unsigned int blocks);
+extern int write_journal(struct gfs2_sbd *sdp, unsigned int j,
+ unsigned int blocks);
/**
* device_size - figure out a device's size
@@ -669,19 +669,19 @@ extern void gfs2_rgrp_relse(struct rgrp_list *rgd);
extern void gfs2_rgrp_free(osi_list_t *rglist);
/* structures.c */
-extern void build_master(struct gfs2_sbd *sdp);
+extern int build_master(struct gfs2_sbd *sdp);
extern void build_sb(struct gfs2_sbd *sdp, const unsigned char *uuid);
-extern void build_journal(struct gfs2_sbd *sdp, int j,
+extern int build_journal(struct gfs2_sbd *sdp, int j,
struct gfs2_inode *jindex);
-extern void build_jindex(struct gfs2_sbd *sdp);
-extern void build_per_node(struct gfs2_sbd *sdp);
-extern void build_inum(struct gfs2_sbd *sdp);
-extern void build_statfs(struct gfs2_sbd *sdp);
-extern void build_rindex(struct gfs2_sbd *sdp);
-extern void build_quota(struct gfs2_sbd *sdp);
-extern void build_root(struct gfs2_sbd *sdp);
-extern void do_init_inum(struct gfs2_sbd *sdp);
-extern void do_init_statfs(struct gfs2_sbd *sdp);
+extern int build_jindex(struct gfs2_sbd *sdp);
+extern int build_per_node(struct gfs2_sbd *sdp);
+extern int build_inum(struct gfs2_sbd *sdp);
+extern int build_statfs(struct gfs2_sbd *sdp);
+extern int build_rindex(struct gfs2_sbd *sdp);
+extern int build_quota(struct gfs2_sbd *sdp);
+extern int build_root(struct gfs2_sbd *sdp);
+extern int do_init_inum(struct gfs2_sbd *sdp);
+extern int do_init_statfs(struct gfs2_sbd *sdp);
extern int gfs2_check_meta(struct gfs2_buffer_head *bh, int type);
extern int gfs2_next_rg_meta(struct rgrp_list *rgd, uint64_t *block,
int first);
@@ -690,7 +690,6 @@ extern int gfs2_next_rg_metatype(struct gfs2_sbd *sdp, struct rgrp_list *rgd,
/* super.c */
extern int check_sb(struct gfs2_sb *sb);
extern int read_sb(struct gfs2_sbd *sdp);
-extern int ji_update(struct gfs2_sbd *sdp);
extern int rindex_read(struct gfs2_sbd *sdp, int fd, int *count1, int *sane);
extern int ri_update(struct gfs2_sbd *sdp, int fd, int *rgcount, int *sane);
extern int write_sb(struct gfs2_sbd *sdp);
diff --git a/gfs2/libgfs2/structures.c b/gfs2/libgfs2/structures.c
index bbde7ba..bb72e30 100644
--- a/gfs2/libgfs2/structures.c
+++ b/gfs2/libgfs2/structures.c
@@ -25,7 +25,7 @@
#include "libgfs2.h"
-void build_master(struct gfs2_sbd *sdp)
+int build_master(struct gfs2_sbd *sdp)
{
struct gfs2_inum inum;
uint64_t bn;
@@ -44,10 +44,10 @@ void build_master(struct gfs2_sbd *sdp)
gfs2_dinode_print(&sdp->master_dir->i_di);
}
sdp->master_dir->bh_owned = 1;
+ return 0;
}
-void
-build_sb(struct gfs2_sbd *sdp, const unsigned char *uuid)
+void build_sb(struct gfs2_sbd *sdp, const unsigned char *uuid)
{
unsigned int x;
struct gfs2_buffer_head *bh;
@@ -86,8 +86,7 @@ build_sb(struct gfs2_sbd *sdp, const unsigned char *uuid)
}
}
-void write_journal(struct gfs2_sbd *sdp, struct gfs2_inode *ip, unsigned int j,
- unsigned int blocks)
+int write_journal(struct gfs2_sbd *sdp, unsigned int j, unsigned int blocks)
{
struct gfs2_log_header lh;
unsigned int x;
@@ -97,8 +96,9 @@ void write_journal(struct gfs2_sbd *sdp, struct gfs2_inode *ip, unsigned int j,
/* Build the height up so our journal blocks will be contiguous and */
/* not broken up by indirect block pages. */
- height = calc_tree_height(ip, (blocks + 1) * sdp->bsize);
- build_height(ip, height);
+ height = calc_tree_height(sdp->md.journal[j],
+ (blocks + 1) * sdp->bsize);
+ build_height(sdp->md.journal[j], height);
memset(&lh, 0, sizeof(struct gfs2_log_header));
lh.lh_header.mh_magic = GFS2_MAGIC;
@@ -107,16 +107,18 @@ void write_journal(struct gfs2_sbd *sdp, struct gfs2_inode *ip, unsigned int j,
lh.lh_flags = GFS2_LOG_HEAD_UNMOUNT;
for (x = 0; x < blocks; x++) {
- struct gfs2_buffer_head *bh = get_file_buf(ip, x, TRUE);
+ struct gfs2_buffer_head *bh = get_file_buf(sdp->md.journal[j],
+ x, TRUE);
if (!bh)
- die("write_journal\n");
+ return -1;
bmodified(bh);
brelse(bh);
}
for (x = 0; x < blocks; x++) {
- struct gfs2_buffer_head *bh = get_file_buf(ip, x, FALSE);
+ struct gfs2_buffer_head *bh = get_file_buf(sdp->md.journal[j],
+ x, FALSE);
if (!bh)
- die("write_journal\n");
+ return -1;
memset(bh->b_data, 0, sdp->bsize);
lh.lh_sequence = seq;
@@ -134,42 +136,51 @@ void write_journal(struct gfs2_sbd *sdp, struct gfs2_inode *ip, unsigned int j,
if (sdp->debug) {
printf("\nJournal %u:\n", j);
- gfs2_dinode_print(&ip->i_di);
+ gfs2_dinode_print(&sdp->md.journal[j]->i_di);
}
+ return 0;
}
-void build_journal(struct gfs2_sbd *sdp, int j, struct gfs2_inode *jindex)
+int build_journal(struct gfs2_sbd *sdp, int j, struct gfs2_inode *jindex)
{
char name[256];
- struct gfs2_inode *ip;
+ int ret;
sprintf(name, "journal%u", j);
- ip = createi(jindex, name, S_IFREG | 0600, GFS2_DIF_SYSTEM);
- write_journal(sdp, ip, j,
- sdp->jsize << 20 >> sdp->sd_sb.sb_bsize_shift);
- inode_put(&ip);
+ sdp->md.journal[j] = createi(jindex, name, S_IFREG | 0600,
+ GFS2_DIF_SYSTEM);
+ ret = write_journal(sdp, j,
+ sdp->jsize << 20 >> sdp->sd_sb.sb_bsize_shift);
+ return ret;
}
-void build_jindex(struct gfs2_sbd *sdp)
+int build_jindex(struct gfs2_sbd *sdp)
{
struct gfs2_inode *jindex;
unsigned int j;
+ int ret;
jindex = createi(sdp->master_dir, "jindex", S_IFDIR | 0700,
GFS2_DIF_SYSTEM);
-
- for (j = 0; j < sdp->md.journals; j++)
- build_journal(sdp, j, jindex);
+ sdp->md.journal = malloc(sdp->md.journals *
+ sizeof(struct gfs2_inode *));
+ for (j = 0; j < sdp->md.journals; j++) {
+ ret = build_journal(sdp, j, jindex);
+ if (ret)
+ return ret;
+ inode_put(&sdp->md.journal[j]);
+ }
if (sdp->debug) {
printf("\nJindex:\n");
gfs2_dinode_print(&jindex->i_di);
}
+ free(sdp->md.journal);
inode_put(&jindex);
+ return 0;
}
-static void
-build_inum_range(struct gfs2_inode *per_node, unsigned int j)
+static int build_inum_range(struct gfs2_inode *per_node, unsigned int j)
{
struct gfs2_sbd *sdp = per_node->i_sbd;
char name[256];
@@ -187,10 +198,10 @@ build_inum_range(struct gfs2_inode *per_node, unsigned int j)
}
inode_put(&ip);
+ return 0;
}
-static void
-build_statfs_change(struct gfs2_inode *per_node, unsigned int j)
+static void build_statfs_change(struct gfs2_inode *per_node, unsigned int j)
{
struct gfs2_sbd *sdp = per_node->i_sbd;
char name[256];
@@ -210,8 +221,7 @@ build_statfs_change(struct gfs2_inode *per_node, unsigned int j)
inode_put(&ip);
}
-static void
-build_quota_change(struct gfs2_inode *per_node, unsigned int j)
+static int build_quota_change(struct gfs2_inode *per_node, unsigned int j)
{
struct gfs2_sbd *sdp = per_node->i_sbd;
struct gfs2_meta_header mh;
@@ -236,7 +246,7 @@ build_quota_change(struct gfs2_inode *per_node, unsigned int j)
for (x = 0; x < blocks; x++) {
bh = get_file_buf(ip, x, FALSE);
if (!bh)
- die("build_quota_change\n");
+ return -1;
memset(bh->b_data, 0, sdp->bsize);
gfs2_meta_header_out(&mh, bh);
@@ -249,10 +259,10 @@ build_quota_change(struct gfs2_inode *per_node, unsigned int j)
}
inode_put(&ip);
+ return 0;
}
-void
-build_per_node(struct gfs2_sbd *sdp)
+int build_per_node(struct gfs2_sbd *sdp)
{
struct gfs2_inode *per_node;
unsigned int j;
@@ -272,10 +282,10 @@ build_per_node(struct gfs2_sbd *sdp)
}
inode_put(&per_node);
+ return 0;
}
-void
-build_inum(struct gfs2_sbd *sdp)
+int build_inum(struct gfs2_sbd *sdp)
{
struct gfs2_inode *ip;
@@ -288,10 +298,10 @@ build_inum(struct gfs2_sbd *sdp)
}
sdp->md.inum = ip;
+ return 0;
}
-void
-build_statfs(struct gfs2_sbd *sdp)
+int build_statfs(struct gfs2_sbd *sdp)
{
struct gfs2_inode *ip;
@@ -304,10 +314,10 @@ build_statfs(struct gfs2_sbd *sdp)
}
sdp->md.statfs = ip;
+ return 0;
}
-void
-build_rindex(struct gfs2_sbd *sdp)
+int build_rindex(struct gfs2_sbd *sdp)
{
struct gfs2_inode *ip;
osi_list_t *tmp, *head;
@@ -329,7 +339,7 @@ build_rindex(struct gfs2_sbd *sdp)
count = gfs2_writei(ip, buf, ip->i_di.di_size,
sizeof(struct gfs2_rindex));
if (count != sizeof(struct gfs2_rindex))
- die("build_rindex\n");
+ return -1;
}
if (sdp->debug) {
@@ -338,10 +348,10 @@ build_rindex(struct gfs2_sbd *sdp)
}
inode_put(&ip);
+ return 0;
}
-void
-build_quota(struct gfs2_sbd *sdp)
+int build_quota(struct gfs2_sbd *sdp)
{
struct gfs2_inode *ip;
struct gfs2_quota qu;
@@ -359,10 +369,10 @@ build_quota(struct gfs2_sbd *sdp)
count = gfs2_writei(ip, buf, ip->i_di.di_size, sizeof(struct gfs2_quota));
if (count != sizeof(struct gfs2_quota))
- die("do_init (2)\n");
+ return -1;
count = gfs2_writei(ip, buf, ip->i_di.di_size, sizeof(struct gfs2_quota));
if (count != sizeof(struct gfs2_quota))
- die("do_init (3)\n");
+ return -1;
if (sdp->debug) {
printf("\nRoot quota:\n");
@@ -370,10 +380,10 @@ build_quota(struct gfs2_sbd *sdp)
}
inode_put(&ip);
+ return 0;
}
-void
-build_root(struct gfs2_sbd *sdp)
+int build_root(struct gfs2_sbd *sdp)
{
struct gfs2_inum inum;
uint64_t bn;
@@ -391,9 +401,10 @@ build_root(struct gfs2_sbd *sdp)
gfs2_dinode_print(&sdp->md.rooti->i_di);
}
sdp->md.rooti->bh_owned = 1;
+ return 0;
}
-void do_init_inum(struct gfs2_sbd *sdp)
+int do_init_inum(struct gfs2_sbd *sdp)
{
struct gfs2_inode *ip = sdp->md.inum;
uint64_t buf;
@@ -402,14 +413,15 @@ void do_init_inum(struct gfs2_sbd *sdp)
buf = cpu_to_be64(sdp->md.next_inum);
count = gfs2_writei(ip, &buf, 0, sizeof(uint64_t));
if (count != sizeof(uint64_t))
- die("do_init (1)\n");
+ return -1;
if (sdp->debug)
printf("\nNext Inum: %"PRIu64"\n",
sdp->md.next_inum);
+ return 0;
}
-void do_init_statfs(struct gfs2_sbd *sdp)
+int do_init_statfs(struct gfs2_sbd *sdp)
{
struct gfs2_inode *ip = sdp->md.statfs;
struct gfs2_statfs_change sc;
@@ -423,12 +435,13 @@ void do_init_statfs(struct gfs2_sbd *sdp)
gfs2_statfs_change_out(&sc, buf);
count = gfs2_writei(ip, buf, 0, sizeof(struct gfs2_statfs_change));
if (count != sizeof(struct gfs2_statfs_change))
- die("do_init (2)\n");
+ return -1;
if (sdp->debug) {
printf("\nStatfs:\n");
gfs2_statfs_change_print(&sc);
}
+ return 0;
}
int gfs2_check_meta(struct gfs2_buffer_head *bh, int type)
diff --git a/gfs2/libgfs2/super.c b/gfs2/libgfs2/super.c
index c40bd38..1d93e4c 100644
--- a/gfs2/libgfs2/super.c
+++ b/gfs2/libgfs2/super.c
@@ -88,6 +88,9 @@ int read_sb(struct gfs2_sbd *sdp)
(sdp->sd_sb.sb_bsize-sizeof(struct gfs2_meta_header)) /
sizeof(uint64_t);
sdp->sd_jbsize = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_meta_header);
+ sdp->sd_hash_bsize = sdp->bsize / 2;
+ sdp->sd_hash_bsize_shift = sdp->sd_sb.sb_bsize_shift - 1;
+ sdp->sd_hash_ptrs = sdp->sd_hash_bsize / sizeof(uint64_t);
sdp->sd_heightsize[0] = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode);
sdp->sd_heightsize[1] = sdp->sd_sb.sb_bsize * sdp->sd_diptrs;
for (x = 2; ; x++){
@@ -126,46 +129,6 @@ int read_sb(struct gfs2_sbd *sdp)
return error;
}
-#define JOURNAL_NAME_SIZE 16
-
-/*
- * ji_update - fill in journal info
- * sdp: the incore superblock pointer
- *
- * Given the inode for the journal index, read in all
- * the journal inodes.
- *
- * Returns: 0 on success, -1 on failure
- */
-int ji_update(struct gfs2_sbd *sdp)
-{
- struct gfs2_inode *jip, *ip = sdp->md.jiinode;
- char journal_name[JOURNAL_NAME_SIZE];
- int i;
-
- if(!ip) {
- log_crit("Journal index inode not found.\n");
- return -1;
- }
-
- if(!(sdp->md.journal = calloc(ip->i_di.di_entries - 2, sizeof(struct gfs2_inode *)))) {
- log_err("Unable to allocate journal index\n");
- return -1;
- }
- sdp->md.journals = 0;
- memset(journal_name, 0, sizeof(*journal_name));
- for(i = 0; i < ip->i_di.di_entries - 2; i++) {
- /* FIXME check snprintf return code */
- snprintf(journal_name, JOURNAL_NAME_SIZE, "journal%u", i);
- gfs2_lookupi(sdp->md.jiinode, journal_name, strlen(journal_name),
- &jip);
- sdp->md.journal[i] = jip;
- }
- sdp->md.journals = ip->i_di.di_entries - 2;
- return 0;
-
-}
-
/**
* rindex_read - read in the rg index file
* @sdp: the incore superblock pointer
13 years, 9 months
cluster: RHEL6 - fsck.gfs2 segfaults if journals are missing
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: c38bc14a73ac6de7b8839f7eafc6ac6c6179e9be
Parent: d8a76837ecd24a5f7ab9a2ebf72745e6c6752c0b
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Wed Aug 18 13:06:31 2010 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Wed Aug 18 13:18:44 2010 -0500
fsck.gfs2 segfaults if journals are missing
This patch makes it possible for fsck.gfs2 to detect missing and damaged
journals and recreate them. Previous versions of fsck.gfs2 would
segfault if journals were missing because it made assumptions about
the jindex file pointing to a valid dinode. Also, I moved function
ji_update which was exclusively used by fsck.gfs2 from libgfs2 to fsck.
rhbz#622576
---
gfs2/convert/gfs2_convert.c | 12 +++--
gfs2/fsck/fs_recovery.c | 55 ++++++++++++++++++++++-
gfs2/fsck/fs_recovery.h | 7 ++-
gfs2/fsck/pass1.c | 104 +++++++++++++++++++++++++++---------------
gfs2/libgfs2/libgfs2.h | 5 +-
gfs2/libgfs2/structures.c | 32 +++++++------
gfs2/libgfs2/super.c | 43 +----------------
7 files changed, 154 insertions(+), 104 deletions(-)
diff --git a/gfs2/convert/gfs2_convert.c b/gfs2/convert/gfs2_convert.c
index 642d26a..6a754b1 100644
--- a/gfs2/convert/gfs2_convert.c
+++ b/gfs2/convert/gfs2_convert.c
@@ -1987,22 +1987,24 @@ static void conv_build_jindex(struct gfs2_sbd *sdp)
sdp->md.jiinode = createi(sdp->master_dir, "jindex", S_IFDIR | 0700,
GFS2_DIF_SYSTEM);
+ sdp->md.journal = malloc(sdp->md.journals *
+ sizeof(struct gfs2_inode *));
for (j = 0; j < sdp->md.journals; j++) {
char name[256];
- struct gfs2_inode *ip;
printf("Writing journal #%d...", j + 1);
fflush(stdout);
sprintf(name, "journal%u", j);
- ip = createi(sdp->md.jiinode, name, S_IFREG | 0600,
- GFS2_DIF_SYSTEM);
- write_journal(sdp, ip, j,
+ sdp->md.journal[j] = createi(sdp->md.jiinode, name, S_IFREG |
+ 0600, GFS2_DIF_SYSTEM);
+ write_journal(sdp, j,
sdp->jsize << 20 >> sdp->sd_sb.sb_bsize_shift);
- inode_put(&ip);
+ inode_put(&sdp->md.journal[j]);
printf("done.\n");
fflush(stdout);
}
+ free(sdp->md.journal);
if (sdp->debug) {
printf("\nJindex:\n");
gfs2_dinode_print(&sdp->md.jiinode->i_di);
diff --git a/gfs2/fsck/fs_recovery.c b/gfs2/fsck/fs_recovery.c
index d908873..07c1552 100644
--- a/gfs2/fsck/fs_recovery.c
+++ b/gfs2/fsck/fs_recovery.c
@@ -12,6 +12,8 @@
#include "libgfs2.h"
#include "util.h"
+#define JOURNAL_NAME_SIZE 16
+
unsigned int sd_found_jblocks = 0, sd_replayed_jblocks = 0;
unsigned int sd_found_metablocks = 0, sd_replayed_metablocks = 0;
unsigned int sd_found_revokes = 0;
@@ -540,7 +542,7 @@ out:
log_info( _("jid=%u: Failed\n"), j);
reinit:
if (query( _("Do you want to clear the journal instead? (y/n)")))
- error = write_journal(sdp, sdp->md.journal[j], j,
+ error = write_journal(sdp, j,
sdp->md.journal[j]->i_di.di_size /
sdp->sd_sb.sb_bsize);
else
@@ -569,6 +571,7 @@ int replay_journals(struct gfs2_sbd *sdp, int preen, int force_check,
*clean_journals = 0;
+ sdp->jsize = GFS2_DEFAULT_JSIZE;
/* Get master dinode */
gfs2_lookupi(sdp->master_dir, "jindex", 6, &sdp->md.jiinode);
@@ -579,7 +582,19 @@ int replay_journals(struct gfs2_sbd *sdp, int preen, int force_check,
}
for(i = 0; i < sdp->md.journals; i++) {
+ if (!sdp->md.journal[i]) {
+ log_err(_("File system journal \"journal%d\" is "
+ "missing: pass1 will try to recreate it.\n"),
+ i);
+ continue;
+ }
if (!error) {
+ uint64_t jsize = sdp->md.journal[i]->i_di.di_size /
+ (1024 * 1024);
+
+ if (sdp->jsize == GFS2_DEFAULT_JSIZE && jsize &&
+ jsize != sdp->jsize)
+ sdp->jsize = jsize;
error = gfs2_recover_journal(sdp->md.journal[i], i,
preen, force_check,
&clean);
@@ -600,3 +615,41 @@ int replay_journals(struct gfs2_sbd *sdp, int preen, int force_check,
fsync(sdp->device_fd);
return error;
}
+
+/*
+ * ji_update - fill in journal info
+ * sdp: the incore superblock pointer
+ *
+ * Given the inode for the journal index, read in all
+ * the journal inodes.
+ *
+ * Returns: 0 on success, -1 on failure
+ */
+int ji_update(struct gfs2_sbd *sdp)
+{
+ struct gfs2_inode *jip, *ip = sdp->md.jiinode;
+ char journal_name[JOURNAL_NAME_SIZE];
+ int i;
+
+ if(!ip) {
+ log_crit("Journal index inode not found.\n");
+ return -1;
+ }
+
+ if(!(sdp->md.journal = calloc(ip->i_di.di_entries - 2, sizeof(struct gfs2_inode *)))) {
+ log_err("Unable to allocate journal index\n");
+ return -1;
+ }
+ sdp->md.journals = 0;
+ memset(journal_name, 0, sizeof(*journal_name));
+ for(i = 0; i < ip->i_di.di_entries - 2; i++) {
+ /* FIXME check snprintf return code */
+ snprintf(journal_name, JOURNAL_NAME_SIZE, "journal%u", i);
+ gfs2_lookupi(sdp->md.jiinode, journal_name, strlen(journal_name),
+ &jip);
+ sdp->md.journal[i] = jip;
+ }
+ sdp->md.journals = ip->i_di.di_entries - 2;
+ return 0;
+
+}
diff --git a/gfs2/fsck/fs_recovery.h b/gfs2/fsck/fs_recovery.h
index a61884d..1a7aae3 100644
--- a/gfs2/fsck/fs_recovery.h
+++ b/gfs2/fsck/fs_recovery.h
@@ -3,9 +3,10 @@
#include "libgfs2.h"
-int replay_journals(struct gfs2_sbd *sdp, int preen, int force_check,
- int *clean_journals);
-int preen_is_safe(struct gfs2_sbd *sdp, int preen, int force_check);
+extern int replay_journals(struct gfs2_sbd *sdp, int preen, int force_check,
+ int *clean_journals);
+extern int preen_is_safe(struct gfs2_sbd *sdp, int preen, int force_check);
+extern int ji_update(struct gfs2_sbd *sdp);
#endif /* __FS_RECOVERY_H__ */
diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c
index 4fb7abf..17b23df 100644
--- a/gfs2/fsck/pass1.c
+++ b/gfs2/fsck/pass1.c
@@ -1174,25 +1174,37 @@ static int handle_di(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh)
/* Check system inode and verify it's marked "in use" in the bitmap: */
/* Should work for all system inodes: root, master, jindex, per_node, etc. */
-static int check_system_inode(struct gfs2_inode *sysinode, const char *filename,
- int builder(struct gfs2_sbd *sbp),
- enum gfs2_mark_block mark)
+/* We have to pass the sysinode as ** because the pointer may change out from
+ under the reference by way of the builder() function. */
+static int check_system_inode(struct gfs2_sbd *sdp,
+ struct gfs2_inode **sysinode,
+ const char *filename,
+ int builder(struct gfs2_sbd *sbp),
+ enum gfs2_mark_block mark)
{
uint64_t iblock = 0;
struct dir_status ds = {0};
int error;
log_info( _("Checking system inode '%s'\n"), filename);
- if (sysinode) {
+ if (*sysinode) {
/* Read in the system inode, look at its dentries, and start
* reading through them */
- iblock = sysinode->i_di.di_num.no_addr;
+ iblock = (*sysinode)->i_di.di_num.no_addr;
log_info( _("System inode for '%s' is located at block %"
PRIu64 " (0x%" PRIx64 ")\n"), filename,
iblock, iblock);
-
- /* FIXME: check this block's validity */
-
+ if (gfs2_check_meta((*sysinode)->i_bh, GFS2_METATYPE_DI)) {
+ log_err( _("Found invalid system dinode at block #"
+ "%llu (0x%llx)\n"),
+ (unsigned long long)iblock,
+ (unsigned long long)iblock);
+ gfs2_blockmap_set(bl, iblock, gfs2_block_free);
+ check_n_fix_bitmap(sdp, iblock, gfs2_block_free);
+ inode_put(sysinode);
+ }
+ }
+ if (*sysinode) {
ds.q = block_type(iblock);
/* If the inode exists but the block is marked free, we might
be recovering from a corrupt bitmap. In that case, don't
@@ -1201,52 +1213,67 @@ static int check_system_inode(struct gfs2_inode *sysinode, const char *filename,
if (ds.q == gfs2_block_free) {
log_info( _("The inode exists but the block is not "
"marked 'in use'; fixing it.\n"));
- fsck_blockmap_set(sysinode,
- sysinode->i_di.di_num.no_addr,
+ fsck_blockmap_set(*sysinode,
+ (*sysinode)->i_di.di_num.no_addr,
filename, mark);
ds.q = mark;
if (mark == gfs2_inode_dir)
- dirtree_insert(sysinode->i_di.di_num.no_addr);
+ dirtree_insert((*sysinode)->i_di.di_num.no_addr);
}
} else
- log_info( _("System inode for '%s' is missing.\n"), filename);
+ log_info( _("System inode for '%s' is corrupt or missing.\n"),
+ filename);
/* If there are errors with the inode here, we need to create a new
inode and get it all setup - of course, everything will be in
lost+found then, but we *need* our system inodes before we can
do any of that. */
- if(!sysinode || ds.q != mark) {
+ if(!(*sysinode) || ds.q != mark) {
log_err( _("Invalid or missing %s system inode (should be %d, "
"is %d).\n"), filename, mark, ds.q);
if (query(_("Create new %s system inode? (y/n) "), filename)) {
- builder(sysinode->i_sbd);
- fsck_blockmap_set(sysinode,
- sysinode->i_di.di_num.no_addr,
+ log_err( _("Rebuilding system file \"%s\"\n"),
+ filename);
+ error = builder(sdp);
+ if (error) {
+ log_err( _("Error trying to rebuild system "
+ "file %s: Cannot continue\n"),
+ filename);
+ return error;
+ }
+ fsck_blockmap_set(*sysinode,
+ (*sysinode)->i_di.di_num.no_addr,
filename, mark);
ds.q = mark;
if (mark == gfs2_inode_dir)
- dirtree_insert(sysinode->i_di.di_num.no_addr);
+ dirtree_insert((*sysinode)->i_di.di_num.no_addr);
} else {
log_err( _("Cannot continue without valid %s inode\n"),
filename);
return -1;
}
}
- if (S_ISDIR(sysinode->i_di.di_mode)) {
+ if (S_ISDIR((*sysinode)->i_di.di_mode)) {
struct block_count bc = {0};
sysdir_fxns.private = &bc;
- if (sysinode->i_di.di_flags & GFS2_DIF_EXHASH)
- check_metatree(sysinode, &sysdir_fxns);
+ if ((*sysinode)->i_di.di_flags & GFS2_DIF_EXHASH)
+ check_metatree(*sysinode, &sysdir_fxns);
else
- check_linear_dir(sysinode, sysinode->i_bh,
+ check_linear_dir(*sysinode, (*sysinode)->i_bh,
&sysdir_fxns);
}
- error = handle_ip(sysinode->i_sbd, sysinode);
+ error = handle_ip(sdp, *sysinode);
return error;
}
static int build_a_journal(struct gfs2_sbd *sdp)
{
+ char name[256];
+
+ /* First, try to delete the journal if it's in jindex */
+ sprintf(name, "journal%u", sdp->md.journals);
+ gfs2_dirent_del(sdp->md.jiinode, name, strlen(name));
+ /* Now rebuild it */
build_journal(sdp, sdp->md.journals, sdp->md.jiinode);
return 0;
}
@@ -1258,43 +1285,43 @@ static int check_system_inodes(struct gfs2_sbd *sdp)
/*******************************************************************
******* Check the system inode integrity *************
*******************************************************************/
- if (check_system_inode(sdp->master_dir, "master", build_master,
+ if (check_system_inode(sdp, &sdp->master_dir, "master", build_master,
gfs2_inode_dir)) {
stack;
return -1;
}
- if (check_system_inode(sdp->md.rooti, "root", build_root,
+ if (check_system_inode(sdp, &sdp->md.rooti, "root", build_root,
gfs2_inode_dir)) {
stack;
return -1;
}
- if (check_system_inode(sdp->md.inum, "inum", build_inum,
+ if (check_system_inode(sdp, &sdp->md.inum, "inum", build_inum,
gfs2_inode_file)) {
stack;
return -1;
}
- if (check_system_inode(sdp->md.statfs, "statfs", build_statfs,
+ if (check_system_inode(sdp, &sdp->md.statfs, "statfs", build_statfs,
gfs2_inode_file)) {
stack;
return -1;
}
- if (check_system_inode(sdp->md.jiinode, "jindex", build_jindex,
+ if (check_system_inode(sdp, &sdp->md.jiinode, "jindex", build_jindex,
gfs2_inode_dir)) {
stack;
return -1;
}
- if (check_system_inode(sdp->md.riinode, "rindex", build_rindex,
+ if (check_system_inode(sdp, &sdp->md.riinode, "rindex", build_rindex,
gfs2_inode_file)) {
stack;
return -1;
}
- if (check_system_inode(sdp->md.qinode, "quota", build_quota,
+ if (check_system_inode(sdp, &sdp->md.qinode, "quota", build_quota,
gfs2_inode_file)) {
stack;
return -1;
}
- if (check_system_inode(sdp->md.pinode, "per_node", build_per_node,
- gfs2_inode_dir)) {
+ if (check_system_inode(sdp, &sdp->md.pinode, "per_node",
+ build_per_node, gfs2_inode_dir)) {
stack;
return -1;
}
@@ -1306,7 +1333,7 @@ static int check_system_inodes(struct gfs2_sbd *sdp)
char jname[16];
sprintf(jname, "journal%d", sdp->md.journals);
- if (check_system_inode(sdp->md.journal[sdp->md.journals],
+ if (check_system_inode(sdp, &sdp->md.journal[sdp->md.journals],
jname, build_a_journal,
gfs2_inode_file)) {
stack;
@@ -1399,6 +1426,14 @@ int pass1(struct gfs2_sbd *sbp)
skip_this_pass = FALSE;
fflush(stdout);
}
+ if (fsck_system_inode(sbp, block)) {
+ log_debug(_("Already processed system inode "
+ "%lld (0x%llx)\n"),
+ (unsigned long long)block,
+ (unsigned long long)block);
+ first = 0;
+ continue;
+ }
bh = bread(sbp, block);
/*log_debug( _("Checking metadata block #%" PRIu64
@@ -1417,11 +1452,6 @@ int pass1(struct gfs2_sbd *sbp)
}
check_n_fix_bitmap(sbp, block,
gfs2_block_free);
- } else if (fsck_system_inode(sbp, block)) {
- log_debug(_("Already processed system inode "
- "%lld (0x%llx)\n"),
- (unsigned long long)block,
- (unsigned long long)block);
} else if (handle_di(sbp, bh) < 0) {
stack;
brelse(bh);
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index 8835a4f..c798bda 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -472,8 +472,8 @@ extern int gfs2_dirent_next(struct gfs2_inode *dip, struct gfs2_buffer_head *bh,
extern void build_height(struct gfs2_inode *ip, int height);
extern void unstuff_dinode(struct gfs2_inode *ip);
extern unsigned int calc_tree_height(struct gfs2_inode *ip, uint64_t size);
-extern int write_journal(struct gfs2_sbd *sdp, struct gfs2_inode *ip,
- unsigned int j, unsigned int blocks);
+extern int write_journal(struct gfs2_sbd *sdp, unsigned int j,
+ unsigned int blocks);
/**
* device_size - figure out a device's size
@@ -671,7 +671,6 @@ extern int gfs2_next_rg_metatype(struct gfs2_sbd *sdp, struct rgrp_list *rgd,
/* super.c */
extern int check_sb(struct gfs2_sb *sb);
extern int read_sb(struct gfs2_sbd *sdp);
-extern int ji_update(struct gfs2_sbd *sdp);
extern int rindex_read(struct gfs2_sbd *sdp, int fd, int *count1, int *sane);
extern int ri_update(struct gfs2_sbd *sdp, int fd, int *rgcount, int *sane);
extern int write_sb(struct gfs2_sbd *sdp);
diff --git a/gfs2/libgfs2/structures.c b/gfs2/libgfs2/structures.c
index c288abd..66a5733 100644
--- a/gfs2/libgfs2/structures.c
+++ b/gfs2/libgfs2/structures.c
@@ -73,8 +73,7 @@ void build_sb(struct gfs2_sbd *sdp, const unsigned char *uuid)
}
}
-int write_journal(struct gfs2_sbd *sdp, struct gfs2_inode *ip, unsigned int j,
- unsigned int blocks)
+int write_journal(struct gfs2_sbd *sdp, unsigned int j, unsigned int blocks)
{
struct gfs2_log_header lh;
unsigned int x;
@@ -84,8 +83,9 @@ int write_journal(struct gfs2_sbd *sdp, struct gfs2_inode *ip, unsigned int j,
/* Build the height up so our journal blocks will be contiguous and */
/* not broken up by indirect block pages. */
- height = calc_tree_height(ip, (blocks + 1) * sdp->bsize);
- build_height(ip, height);
+ height = calc_tree_height(sdp->md.journal[j],
+ (blocks + 1) * sdp->bsize);
+ build_height(sdp->md.journal[j], height);
memset(&lh, 0, sizeof(struct gfs2_log_header));
lh.lh_header.mh_magic = GFS2_MAGIC;
@@ -94,14 +94,16 @@ int write_journal(struct gfs2_sbd *sdp, struct gfs2_inode *ip, unsigned int j,
lh.lh_flags = GFS2_LOG_HEAD_UNMOUNT;
for (x = 0; x < blocks; x++) {
- struct gfs2_buffer_head *bh = get_file_buf(ip, x, TRUE);
+ struct gfs2_buffer_head *bh = get_file_buf(sdp->md.journal[j],
+ x, TRUE);
if (!bh)
return -1;
bmodified(bh);
brelse(bh);
}
for (x = 0; x < blocks; x++) {
- struct gfs2_buffer_head *bh = get_file_buf(ip, x, FALSE);
+ struct gfs2_buffer_head *bh = get_file_buf(sdp->md.journal[j],
+ x, FALSE);
if (!bh)
return -1;
@@ -121,7 +123,7 @@ int write_journal(struct gfs2_sbd *sdp, struct gfs2_inode *ip, unsigned int j,
if (sdp->debug) {
printf("\nJournal %u:\n", j);
- gfs2_dinode_print(&ip->i_di);
+ gfs2_dinode_print(&sdp->md.journal[j]->i_di);
}
return 0;
}
@@ -129,17 +131,14 @@ int write_journal(struct gfs2_sbd *sdp, struct gfs2_inode *ip, unsigned int j,
int build_journal(struct gfs2_sbd *sdp, int j, struct gfs2_inode *jindex)
{
char name[256];
- struct gfs2_inode *ip;
int ret;
sprintf(name, "journal%u", j);
- ip = createi(jindex, name, S_IFREG | 0600, GFS2_DIF_SYSTEM);
- ret = write_journal(sdp, ip, j,
+ sdp->md.journal[j] = createi(jindex, name, S_IFREG | 0600,
+ GFS2_DIF_SYSTEM);
+ ret = write_journal(sdp, j,
sdp->jsize << 20 >> sdp->sd_sb.sb_bsize_shift);
- if (ret)
- return ret;
- inode_put(&ip);
- return 0;
+ return ret;
}
int build_jindex(struct gfs2_sbd *sdp)
@@ -150,17 +149,20 @@ int build_jindex(struct gfs2_sbd *sdp)
jindex = createi(sdp->master_dir, "jindex", S_IFDIR | 0700,
GFS2_DIF_SYSTEM);
-
+ sdp->md.journal = malloc(sdp->md.journals *
+ sizeof(struct gfs2_inode *));
for (j = 0; j < sdp->md.journals; j++) {
ret = build_journal(sdp, j, jindex);
if (ret)
return ret;
+ inode_put(&sdp->md.journal[j]);
}
if (sdp->debug) {
printf("\nJindex:\n");
gfs2_dinode_print(&jindex->i_di);
}
+ free(sdp->md.journal);
inode_put(&jindex);
return 0;
}
diff --git a/gfs2/libgfs2/super.c b/gfs2/libgfs2/super.c
index c5b5800..5d232a6 100644
--- a/gfs2/libgfs2/super.c
+++ b/gfs2/libgfs2/super.c
@@ -75,6 +75,9 @@ int read_sb(struct gfs2_sbd *sdp)
(sdp->sd_sb.sb_bsize-sizeof(struct gfs2_meta_header)) /
sizeof(uint64_t);
sdp->sd_jbsize = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_meta_header);
+ sdp->sd_hash_bsize = sdp->bsize / 2;
+ sdp->sd_hash_bsize_shift = sdp->sd_sb.sb_bsize_shift - 1;
+ sdp->sd_hash_ptrs = sdp->sd_hash_bsize / sizeof(uint64_t);
sdp->sd_heightsize[0] = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode);
sdp->sd_heightsize[1] = sdp->sd_sb.sb_bsize * sdp->sd_diptrs;
for (x = 2; ; x++){
@@ -113,46 +116,6 @@ int read_sb(struct gfs2_sbd *sdp)
return error;
}
-#define JOURNAL_NAME_SIZE 16
-
-/*
- * ji_update - fill in journal info
- * sdp: the incore superblock pointer
- *
- * Given the inode for the journal index, read in all
- * the journal inodes.
- *
- * Returns: 0 on success, -1 on failure
- */
-int ji_update(struct gfs2_sbd *sdp)
-{
- struct gfs2_inode *jip, *ip = sdp->md.jiinode;
- char journal_name[JOURNAL_NAME_SIZE];
- int i;
-
- if(!ip) {
- log_crit("Journal index inode not found.\n");
- return -1;
- }
-
- if(!(sdp->md.journal = calloc(ip->i_di.di_entries - 2, sizeof(struct gfs2_inode *)))) {
- log_err("Unable to allocate journal index\n");
- return -1;
- }
- sdp->md.journals = 0;
- memset(journal_name, 0, sizeof(*journal_name));
- for(i = 0; i < ip->i_di.di_entries - 2; i++) {
- /* FIXME check snprintf return code */
- snprintf(journal_name, JOURNAL_NAME_SIZE, "journal%u", i);
- gfs2_lookupi(sdp->md.jiinode, journal_name, strlen(journal_name),
- &jip);
- sdp->md.journal[i] = jip;
- }
- sdp->md.journals = ip->i_di.di_entries - 2;
- return 0;
-
-}
-
/**
* rindex_read - read in the rg index file
* @sdp: the incore superblock pointer
13 years, 9 months
cluster: STABLE3 - fsck.gfs2 segfaults if journals are missing
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 96c846d5aefd74b7a84078987ebb3610180f5925
Parent: d22e78f8fc996480d873585ad2939be826343b05
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Wed Aug 18 13:06:31 2010 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Wed Aug 18 13:06:31 2010 -0500
fsck.gfs2 segfaults if journals are missing
This patch makes it possible for fsck.gfs2 to detect missing and damaged
journals and recreate them. Previous versions of fsck.gfs2 would
segfault if journals were missing because it made assumptions about
the jindex file pointing to a valid dinode. Also, I moved function
ji_update which was exclusively used by fsck.gfs2 from libgfs2 to fsck.
rhbz#622576
---
gfs2/convert/gfs2_convert.c | 12 +++--
gfs2/fsck/fs_recovery.c | 55 ++++++++++++++++++++++-
gfs2/fsck/fs_recovery.h | 7 ++-
gfs2/fsck/pass1.c | 104 +++++++++++++++++++++++++++---------------
gfs2/libgfs2/libgfs2.h | 5 +-
gfs2/libgfs2/structures.c | 32 +++++++------
gfs2/libgfs2/super.c | 43 +----------------
7 files changed, 154 insertions(+), 104 deletions(-)
diff --git a/gfs2/convert/gfs2_convert.c b/gfs2/convert/gfs2_convert.c
index 642d26a..6a754b1 100644
--- a/gfs2/convert/gfs2_convert.c
+++ b/gfs2/convert/gfs2_convert.c
@@ -1987,22 +1987,24 @@ static void conv_build_jindex(struct gfs2_sbd *sdp)
sdp->md.jiinode = createi(sdp->master_dir, "jindex", S_IFDIR | 0700,
GFS2_DIF_SYSTEM);
+ sdp->md.journal = malloc(sdp->md.journals *
+ sizeof(struct gfs2_inode *));
for (j = 0; j < sdp->md.journals; j++) {
char name[256];
- struct gfs2_inode *ip;
printf("Writing journal #%d...", j + 1);
fflush(stdout);
sprintf(name, "journal%u", j);
- ip = createi(sdp->md.jiinode, name, S_IFREG | 0600,
- GFS2_DIF_SYSTEM);
- write_journal(sdp, ip, j,
+ sdp->md.journal[j] = createi(sdp->md.jiinode, name, S_IFREG |
+ 0600, GFS2_DIF_SYSTEM);
+ write_journal(sdp, j,
sdp->jsize << 20 >> sdp->sd_sb.sb_bsize_shift);
- inode_put(&ip);
+ inode_put(&sdp->md.journal[j]);
printf("done.\n");
fflush(stdout);
}
+ free(sdp->md.journal);
if (sdp->debug) {
printf("\nJindex:\n");
gfs2_dinode_print(&sdp->md.jiinode->i_di);
diff --git a/gfs2/fsck/fs_recovery.c b/gfs2/fsck/fs_recovery.c
index d908873..07c1552 100644
--- a/gfs2/fsck/fs_recovery.c
+++ b/gfs2/fsck/fs_recovery.c
@@ -12,6 +12,8 @@
#include "libgfs2.h"
#include "util.h"
+#define JOURNAL_NAME_SIZE 16
+
unsigned int sd_found_jblocks = 0, sd_replayed_jblocks = 0;
unsigned int sd_found_metablocks = 0, sd_replayed_metablocks = 0;
unsigned int sd_found_revokes = 0;
@@ -540,7 +542,7 @@ out:
log_info( _("jid=%u: Failed\n"), j);
reinit:
if (query( _("Do you want to clear the journal instead? (y/n)")))
- error = write_journal(sdp, sdp->md.journal[j], j,
+ error = write_journal(sdp, j,
sdp->md.journal[j]->i_di.di_size /
sdp->sd_sb.sb_bsize);
else
@@ -569,6 +571,7 @@ int replay_journals(struct gfs2_sbd *sdp, int preen, int force_check,
*clean_journals = 0;
+ sdp->jsize = GFS2_DEFAULT_JSIZE;
/* Get master dinode */
gfs2_lookupi(sdp->master_dir, "jindex", 6, &sdp->md.jiinode);
@@ -579,7 +582,19 @@ int replay_journals(struct gfs2_sbd *sdp, int preen, int force_check,
}
for(i = 0; i < sdp->md.journals; i++) {
+ if (!sdp->md.journal[i]) {
+ log_err(_("File system journal \"journal%d\" is "
+ "missing: pass1 will try to recreate it.\n"),
+ i);
+ continue;
+ }
if (!error) {
+ uint64_t jsize = sdp->md.journal[i]->i_di.di_size /
+ (1024 * 1024);
+
+ if (sdp->jsize == GFS2_DEFAULT_JSIZE && jsize &&
+ jsize != sdp->jsize)
+ sdp->jsize = jsize;
error = gfs2_recover_journal(sdp->md.journal[i], i,
preen, force_check,
&clean);
@@ -600,3 +615,41 @@ int replay_journals(struct gfs2_sbd *sdp, int preen, int force_check,
fsync(sdp->device_fd);
return error;
}
+
+/*
+ * ji_update - fill in journal info
+ * sdp: the incore superblock pointer
+ *
+ * Given the inode for the journal index, read in all
+ * the journal inodes.
+ *
+ * Returns: 0 on success, -1 on failure
+ */
+int ji_update(struct gfs2_sbd *sdp)
+{
+ struct gfs2_inode *jip, *ip = sdp->md.jiinode;
+ char journal_name[JOURNAL_NAME_SIZE];
+ int i;
+
+ if(!ip) {
+ log_crit("Journal index inode not found.\n");
+ return -1;
+ }
+
+ if(!(sdp->md.journal = calloc(ip->i_di.di_entries - 2, sizeof(struct gfs2_inode *)))) {
+ log_err("Unable to allocate journal index\n");
+ return -1;
+ }
+ sdp->md.journals = 0;
+ memset(journal_name, 0, sizeof(*journal_name));
+ for(i = 0; i < ip->i_di.di_entries - 2; i++) {
+ /* FIXME check snprintf return code */
+ snprintf(journal_name, JOURNAL_NAME_SIZE, "journal%u", i);
+ gfs2_lookupi(sdp->md.jiinode, journal_name, strlen(journal_name),
+ &jip);
+ sdp->md.journal[i] = jip;
+ }
+ sdp->md.journals = ip->i_di.di_entries - 2;
+ return 0;
+
+}
diff --git a/gfs2/fsck/fs_recovery.h b/gfs2/fsck/fs_recovery.h
index a61884d..1a7aae3 100644
--- a/gfs2/fsck/fs_recovery.h
+++ b/gfs2/fsck/fs_recovery.h
@@ -3,9 +3,10 @@
#include "libgfs2.h"
-int replay_journals(struct gfs2_sbd *sdp, int preen, int force_check,
- int *clean_journals);
-int preen_is_safe(struct gfs2_sbd *sdp, int preen, int force_check);
+extern int replay_journals(struct gfs2_sbd *sdp, int preen, int force_check,
+ int *clean_journals);
+extern int preen_is_safe(struct gfs2_sbd *sdp, int preen, int force_check);
+extern int ji_update(struct gfs2_sbd *sdp);
#endif /* __FS_RECOVERY_H__ */
diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c
index 4fb7abf..17b23df 100644
--- a/gfs2/fsck/pass1.c
+++ b/gfs2/fsck/pass1.c
@@ -1174,25 +1174,37 @@ static int handle_di(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh)
/* Check system inode and verify it's marked "in use" in the bitmap: */
/* Should work for all system inodes: root, master, jindex, per_node, etc. */
-static int check_system_inode(struct gfs2_inode *sysinode, const char *filename,
- int builder(struct gfs2_sbd *sbp),
- enum gfs2_mark_block mark)
+/* We have to pass the sysinode as ** because the pointer may change out from
+ under the reference by way of the builder() function. */
+static int check_system_inode(struct gfs2_sbd *sdp,
+ struct gfs2_inode **sysinode,
+ const char *filename,
+ int builder(struct gfs2_sbd *sbp),
+ enum gfs2_mark_block mark)
{
uint64_t iblock = 0;
struct dir_status ds = {0};
int error;
log_info( _("Checking system inode '%s'\n"), filename);
- if (sysinode) {
+ if (*sysinode) {
/* Read in the system inode, look at its dentries, and start
* reading through them */
- iblock = sysinode->i_di.di_num.no_addr;
+ iblock = (*sysinode)->i_di.di_num.no_addr;
log_info( _("System inode for '%s' is located at block %"
PRIu64 " (0x%" PRIx64 ")\n"), filename,
iblock, iblock);
-
- /* FIXME: check this block's validity */
-
+ if (gfs2_check_meta((*sysinode)->i_bh, GFS2_METATYPE_DI)) {
+ log_err( _("Found invalid system dinode at block #"
+ "%llu (0x%llx)\n"),
+ (unsigned long long)iblock,
+ (unsigned long long)iblock);
+ gfs2_blockmap_set(bl, iblock, gfs2_block_free);
+ check_n_fix_bitmap(sdp, iblock, gfs2_block_free);
+ inode_put(sysinode);
+ }
+ }
+ if (*sysinode) {
ds.q = block_type(iblock);
/* If the inode exists but the block is marked free, we might
be recovering from a corrupt bitmap. In that case, don't
@@ -1201,52 +1213,67 @@ static int check_system_inode(struct gfs2_inode *sysinode, const char *filename,
if (ds.q == gfs2_block_free) {
log_info( _("The inode exists but the block is not "
"marked 'in use'; fixing it.\n"));
- fsck_blockmap_set(sysinode,
- sysinode->i_di.di_num.no_addr,
+ fsck_blockmap_set(*sysinode,
+ (*sysinode)->i_di.di_num.no_addr,
filename, mark);
ds.q = mark;
if (mark == gfs2_inode_dir)
- dirtree_insert(sysinode->i_di.di_num.no_addr);
+ dirtree_insert((*sysinode)->i_di.di_num.no_addr);
}
} else
- log_info( _("System inode for '%s' is missing.\n"), filename);
+ log_info( _("System inode for '%s' is corrupt or missing.\n"),
+ filename);
/* If there are errors with the inode here, we need to create a new
inode and get it all setup - of course, everything will be in
lost+found then, but we *need* our system inodes before we can
do any of that. */
- if(!sysinode || ds.q != mark) {
+ if(!(*sysinode) || ds.q != mark) {
log_err( _("Invalid or missing %s system inode (should be %d, "
"is %d).\n"), filename, mark, ds.q);
if (query(_("Create new %s system inode? (y/n) "), filename)) {
- builder(sysinode->i_sbd);
- fsck_blockmap_set(sysinode,
- sysinode->i_di.di_num.no_addr,
+ log_err( _("Rebuilding system file \"%s\"\n"),
+ filename);
+ error = builder(sdp);
+ if (error) {
+ log_err( _("Error trying to rebuild system "
+ "file %s: Cannot continue\n"),
+ filename);
+ return error;
+ }
+ fsck_blockmap_set(*sysinode,
+ (*sysinode)->i_di.di_num.no_addr,
filename, mark);
ds.q = mark;
if (mark == gfs2_inode_dir)
- dirtree_insert(sysinode->i_di.di_num.no_addr);
+ dirtree_insert((*sysinode)->i_di.di_num.no_addr);
} else {
log_err( _("Cannot continue without valid %s inode\n"),
filename);
return -1;
}
}
- if (S_ISDIR(sysinode->i_di.di_mode)) {
+ if (S_ISDIR((*sysinode)->i_di.di_mode)) {
struct block_count bc = {0};
sysdir_fxns.private = &bc;
- if (sysinode->i_di.di_flags & GFS2_DIF_EXHASH)
- check_metatree(sysinode, &sysdir_fxns);
+ if ((*sysinode)->i_di.di_flags & GFS2_DIF_EXHASH)
+ check_metatree(*sysinode, &sysdir_fxns);
else
- check_linear_dir(sysinode, sysinode->i_bh,
+ check_linear_dir(*sysinode, (*sysinode)->i_bh,
&sysdir_fxns);
}
- error = handle_ip(sysinode->i_sbd, sysinode);
+ error = handle_ip(sdp, *sysinode);
return error;
}
static int build_a_journal(struct gfs2_sbd *sdp)
{
+ char name[256];
+
+ /* First, try to delete the journal if it's in jindex */
+ sprintf(name, "journal%u", sdp->md.journals);
+ gfs2_dirent_del(sdp->md.jiinode, name, strlen(name));
+ /* Now rebuild it */
build_journal(sdp, sdp->md.journals, sdp->md.jiinode);
return 0;
}
@@ -1258,43 +1285,43 @@ static int check_system_inodes(struct gfs2_sbd *sdp)
/*******************************************************************
******* Check the system inode integrity *************
*******************************************************************/
- if (check_system_inode(sdp->master_dir, "master", build_master,
+ if (check_system_inode(sdp, &sdp->master_dir, "master", build_master,
gfs2_inode_dir)) {
stack;
return -1;
}
- if (check_system_inode(sdp->md.rooti, "root", build_root,
+ if (check_system_inode(sdp, &sdp->md.rooti, "root", build_root,
gfs2_inode_dir)) {
stack;
return -1;
}
- if (check_system_inode(sdp->md.inum, "inum", build_inum,
+ if (check_system_inode(sdp, &sdp->md.inum, "inum", build_inum,
gfs2_inode_file)) {
stack;
return -1;
}
- if (check_system_inode(sdp->md.statfs, "statfs", build_statfs,
+ if (check_system_inode(sdp, &sdp->md.statfs, "statfs", build_statfs,
gfs2_inode_file)) {
stack;
return -1;
}
- if (check_system_inode(sdp->md.jiinode, "jindex", build_jindex,
+ if (check_system_inode(sdp, &sdp->md.jiinode, "jindex", build_jindex,
gfs2_inode_dir)) {
stack;
return -1;
}
- if (check_system_inode(sdp->md.riinode, "rindex", build_rindex,
+ if (check_system_inode(sdp, &sdp->md.riinode, "rindex", build_rindex,
gfs2_inode_file)) {
stack;
return -1;
}
- if (check_system_inode(sdp->md.qinode, "quota", build_quota,
+ if (check_system_inode(sdp, &sdp->md.qinode, "quota", build_quota,
gfs2_inode_file)) {
stack;
return -1;
}
- if (check_system_inode(sdp->md.pinode, "per_node", build_per_node,
- gfs2_inode_dir)) {
+ if (check_system_inode(sdp, &sdp->md.pinode, "per_node",
+ build_per_node, gfs2_inode_dir)) {
stack;
return -1;
}
@@ -1306,7 +1333,7 @@ static int check_system_inodes(struct gfs2_sbd *sdp)
char jname[16];
sprintf(jname, "journal%d", sdp->md.journals);
- if (check_system_inode(sdp->md.journal[sdp->md.journals],
+ if (check_system_inode(sdp, &sdp->md.journal[sdp->md.journals],
jname, build_a_journal,
gfs2_inode_file)) {
stack;
@@ -1399,6 +1426,14 @@ int pass1(struct gfs2_sbd *sbp)
skip_this_pass = FALSE;
fflush(stdout);
}
+ if (fsck_system_inode(sbp, block)) {
+ log_debug(_("Already processed system inode "
+ "%lld (0x%llx)\n"),
+ (unsigned long long)block,
+ (unsigned long long)block);
+ first = 0;
+ continue;
+ }
bh = bread(sbp, block);
/*log_debug( _("Checking metadata block #%" PRIu64
@@ -1417,11 +1452,6 @@ int pass1(struct gfs2_sbd *sbp)
}
check_n_fix_bitmap(sbp, block,
gfs2_block_free);
- } else if (fsck_system_inode(sbp, block)) {
- log_debug(_("Already processed system inode "
- "%lld (0x%llx)\n"),
- (unsigned long long)block,
- (unsigned long long)block);
} else if (handle_di(sbp, bh) < 0) {
stack;
brelse(bh);
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index 8835a4f..c798bda 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -472,8 +472,8 @@ extern int gfs2_dirent_next(struct gfs2_inode *dip, struct gfs2_buffer_head *bh,
extern void build_height(struct gfs2_inode *ip, int height);
extern void unstuff_dinode(struct gfs2_inode *ip);
extern unsigned int calc_tree_height(struct gfs2_inode *ip, uint64_t size);
-extern int write_journal(struct gfs2_sbd *sdp, struct gfs2_inode *ip,
- unsigned int j, unsigned int blocks);
+extern int write_journal(struct gfs2_sbd *sdp, unsigned int j,
+ unsigned int blocks);
/**
* device_size - figure out a device's size
@@ -671,7 +671,6 @@ extern int gfs2_next_rg_metatype(struct gfs2_sbd *sdp, struct rgrp_list *rgd,
/* super.c */
extern int check_sb(struct gfs2_sb *sb);
extern int read_sb(struct gfs2_sbd *sdp);
-extern int ji_update(struct gfs2_sbd *sdp);
extern int rindex_read(struct gfs2_sbd *sdp, int fd, int *count1, int *sane);
extern int ri_update(struct gfs2_sbd *sdp, int fd, int *rgcount, int *sane);
extern int write_sb(struct gfs2_sbd *sdp);
diff --git a/gfs2/libgfs2/structures.c b/gfs2/libgfs2/structures.c
index c288abd..66a5733 100644
--- a/gfs2/libgfs2/structures.c
+++ b/gfs2/libgfs2/structures.c
@@ -73,8 +73,7 @@ void build_sb(struct gfs2_sbd *sdp, const unsigned char *uuid)
}
}
-int write_journal(struct gfs2_sbd *sdp, struct gfs2_inode *ip, unsigned int j,
- unsigned int blocks)
+int write_journal(struct gfs2_sbd *sdp, unsigned int j, unsigned int blocks)
{
struct gfs2_log_header lh;
unsigned int x;
@@ -84,8 +83,9 @@ int write_journal(struct gfs2_sbd *sdp, struct gfs2_inode *ip, unsigned int j,
/* Build the height up so our journal blocks will be contiguous and */
/* not broken up by indirect block pages. */
- height = calc_tree_height(ip, (blocks + 1) * sdp->bsize);
- build_height(ip, height);
+ height = calc_tree_height(sdp->md.journal[j],
+ (blocks + 1) * sdp->bsize);
+ build_height(sdp->md.journal[j], height);
memset(&lh, 0, sizeof(struct gfs2_log_header));
lh.lh_header.mh_magic = GFS2_MAGIC;
@@ -94,14 +94,16 @@ int write_journal(struct gfs2_sbd *sdp, struct gfs2_inode *ip, unsigned int j,
lh.lh_flags = GFS2_LOG_HEAD_UNMOUNT;
for (x = 0; x < blocks; x++) {
- struct gfs2_buffer_head *bh = get_file_buf(ip, x, TRUE);
+ struct gfs2_buffer_head *bh = get_file_buf(sdp->md.journal[j],
+ x, TRUE);
if (!bh)
return -1;
bmodified(bh);
brelse(bh);
}
for (x = 0; x < blocks; x++) {
- struct gfs2_buffer_head *bh = get_file_buf(ip, x, FALSE);
+ struct gfs2_buffer_head *bh = get_file_buf(sdp->md.journal[j],
+ x, FALSE);
if (!bh)
return -1;
@@ -121,7 +123,7 @@ int write_journal(struct gfs2_sbd *sdp, struct gfs2_inode *ip, unsigned int j,
if (sdp->debug) {
printf("\nJournal %u:\n", j);
- gfs2_dinode_print(&ip->i_di);
+ gfs2_dinode_print(&sdp->md.journal[j]->i_di);
}
return 0;
}
@@ -129,17 +131,14 @@ int write_journal(struct gfs2_sbd *sdp, struct gfs2_inode *ip, unsigned int j,
int build_journal(struct gfs2_sbd *sdp, int j, struct gfs2_inode *jindex)
{
char name[256];
- struct gfs2_inode *ip;
int ret;
sprintf(name, "journal%u", j);
- ip = createi(jindex, name, S_IFREG | 0600, GFS2_DIF_SYSTEM);
- ret = write_journal(sdp, ip, j,
+ sdp->md.journal[j] = createi(jindex, name, S_IFREG | 0600,
+ GFS2_DIF_SYSTEM);
+ ret = write_journal(sdp, j,
sdp->jsize << 20 >> sdp->sd_sb.sb_bsize_shift);
- if (ret)
- return ret;
- inode_put(&ip);
- return 0;
+ return ret;
}
int build_jindex(struct gfs2_sbd *sdp)
@@ -150,17 +149,20 @@ int build_jindex(struct gfs2_sbd *sdp)
jindex = createi(sdp->master_dir, "jindex", S_IFDIR | 0700,
GFS2_DIF_SYSTEM);
-
+ sdp->md.journal = malloc(sdp->md.journals *
+ sizeof(struct gfs2_inode *));
for (j = 0; j < sdp->md.journals; j++) {
ret = build_journal(sdp, j, jindex);
if (ret)
return ret;
+ inode_put(&sdp->md.journal[j]);
}
if (sdp->debug) {
printf("\nJindex:\n");
gfs2_dinode_print(&jindex->i_di);
}
+ free(sdp->md.journal);
inode_put(&jindex);
return 0;
}
diff --git a/gfs2/libgfs2/super.c b/gfs2/libgfs2/super.c
index c5b5800..5d232a6 100644
--- a/gfs2/libgfs2/super.c
+++ b/gfs2/libgfs2/super.c
@@ -75,6 +75,9 @@ int read_sb(struct gfs2_sbd *sdp)
(sdp->sd_sb.sb_bsize-sizeof(struct gfs2_meta_header)) /
sizeof(uint64_t);
sdp->sd_jbsize = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_meta_header);
+ sdp->sd_hash_bsize = sdp->bsize / 2;
+ sdp->sd_hash_bsize_shift = sdp->sd_sb.sb_bsize_shift - 1;
+ sdp->sd_hash_ptrs = sdp->sd_hash_bsize / sizeof(uint64_t);
sdp->sd_heightsize[0] = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode);
sdp->sd_heightsize[1] = sdp->sd_sb.sb_bsize * sdp->sd_diptrs;
for (x = 2; ; x++){
@@ -113,46 +116,6 @@ int read_sb(struct gfs2_sbd *sdp)
return error;
}
-#define JOURNAL_NAME_SIZE 16
-
-/*
- * ji_update - fill in journal info
- * sdp: the incore superblock pointer
- *
- * Given the inode for the journal index, read in all
- * the journal inodes.
- *
- * Returns: 0 on success, -1 on failure
- */
-int ji_update(struct gfs2_sbd *sdp)
-{
- struct gfs2_inode *jip, *ip = sdp->md.jiinode;
- char journal_name[JOURNAL_NAME_SIZE];
- int i;
-
- if(!ip) {
- log_crit("Journal index inode not found.\n");
- return -1;
- }
-
- if(!(sdp->md.journal = calloc(ip->i_di.di_entries - 2, sizeof(struct gfs2_inode *)))) {
- log_err("Unable to allocate journal index\n");
- return -1;
- }
- sdp->md.journals = 0;
- memset(journal_name, 0, sizeof(*journal_name));
- for(i = 0; i < ip->i_di.di_entries - 2; i++) {
- /* FIXME check snprintf return code */
- snprintf(journal_name, JOURNAL_NAME_SIZE, "journal%u", i);
- gfs2_lookupi(sdp->md.jiinode, journal_name, strlen(journal_name),
- &jip);
- sdp->md.journal[i] = jip;
- }
- sdp->md.journals = ip->i_di.di_entries - 2;
- return 0;
-
-}
-
/**
* rindex_read - read in the rg index file
* @sdp: the incore superblock pointer
13 years, 9 months
gfs2-utils: master - fsck.gfs2 segfaults if journals are missing
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/gfs2-utils.git?p=gfs2-utils.git;a=commitd...
Commit: cfbae22fc04d28031669de0a3f3aba5916c90465
Parent: fb5bd562b6768e9110357434f3441e006a795d96
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Wed Aug 18 13:06:31 2010 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Wed Aug 18 13:14:46 2010 -0500
fsck.gfs2 segfaults if journals are missing
This patch makes it possible for fsck.gfs2 to detect missing and damaged
journals and recreate them. Previous versions of fsck.gfs2 would
segfault if journals were missing because it made assumptions about
the jindex file pointing to a valid dinode. Also, I moved function
ji_update which was exclusively used by fsck.gfs2 from libgfs2 to fsck.
rhbz#622576
---
gfs2/convert/gfs2_convert.c | 12 +++--
gfs2/fsck/fs_recovery.c | 55 ++++++++++++++++++++++-
gfs2/fsck/fs_recovery.h | 7 ++-
gfs2/fsck/pass1.c | 104 +++++++++++++++++++++++++++---------------
gfs2/libgfs2/libgfs2.h | 5 +-
gfs2/libgfs2/structures.c | 32 +++++++------
gfs2/libgfs2/super.c | 43 +----------------
7 files changed, 154 insertions(+), 104 deletions(-)
diff --git a/gfs2/convert/gfs2_convert.c b/gfs2/convert/gfs2_convert.c
index 84d2870..659cd4a 100644
--- a/gfs2/convert/gfs2_convert.c
+++ b/gfs2/convert/gfs2_convert.c
@@ -1989,22 +1989,24 @@ static void conv_build_jindex(struct gfs2_sbd *sdp)
sdp->md.jiinode = createi(sdp->master_dir, "jindex", S_IFDIR | 0700,
GFS2_DIF_SYSTEM);
+ sdp->md.journal = malloc(sdp->md.journals *
+ sizeof(struct gfs2_inode *));
for (j = 0; j < sdp->md.journals; j++) {
char name[256];
- struct gfs2_inode *ip;
printf("Writing journal #%d...", j + 1);
fflush(stdout);
sprintf(name, "journal%u", j);
- ip = createi(sdp->md.jiinode, name, S_IFREG | 0600,
- GFS2_DIF_SYSTEM);
- write_journal(sdp, ip, j,
+ sdp->md.journal[j] = createi(sdp->md.jiinode, name, S_IFREG |
+ 0600, GFS2_DIF_SYSTEM);
+ write_journal(sdp, j,
sdp->jsize << 20 >> sdp->sd_sb.sb_bsize_shift);
- inode_put(&ip);
+ inode_put(&sdp->md.journal[j]);
printf("done.\n");
fflush(stdout);
}
+ free(sdp->md.journal);
if (sdp->debug) {
printf("\nJindex:\n");
gfs2_dinode_print(&sdp->md.jiinode->i_di);
diff --git a/gfs2/fsck/fs_recovery.c b/gfs2/fsck/fs_recovery.c
index da03ac4..21f6db1 100644
--- a/gfs2/fsck/fs_recovery.c
+++ b/gfs2/fsck/fs_recovery.c
@@ -14,6 +14,8 @@
#include "libgfs2.h"
#include "util.h"
+#define JOURNAL_NAME_SIZE 16
+
unsigned int sd_found_jblocks = 0, sd_replayed_jblocks = 0;
unsigned int sd_found_metablocks = 0, sd_replayed_metablocks = 0;
unsigned int sd_found_revokes = 0;
@@ -542,7 +544,7 @@ out:
log_info( _("jid=%u: Failed\n"), j);
reinit:
if (query( _("Do you want to clear the journal instead? (y/n)")))
- error = write_journal(sdp, sdp->md.journal[j], j,
+ error = write_journal(sdp, j,
sdp->md.journal[j]->i_di.di_size /
sdp->sd_sb.sb_bsize);
else
@@ -571,6 +573,7 @@ int replay_journals(struct gfs2_sbd *sdp, int preen, int force_check,
*clean_journals = 0;
+ sdp->jsize = GFS2_DEFAULT_JSIZE;
/* Get master dinode */
gfs2_lookupi(sdp->master_dir, "jindex", 6, &sdp->md.jiinode);
@@ -581,7 +584,19 @@ int replay_journals(struct gfs2_sbd *sdp, int preen, int force_check,
}
for(i = 0; i < sdp->md.journals; i++) {
+ if (!sdp->md.journal[i]) {
+ log_err(_("File system journal \"journal%d\" is "
+ "missing: pass1 will try to recreate it.\n"),
+ i);
+ continue;
+ }
if (!error) {
+ uint64_t jsize = sdp->md.journal[i]->i_di.di_size /
+ (1024 * 1024);
+
+ if (sdp->jsize == GFS2_DEFAULT_JSIZE && jsize &&
+ jsize != sdp->jsize)
+ sdp->jsize = jsize;
error = gfs2_recover_journal(sdp->md.journal[i], i,
preen, force_check,
&clean);
@@ -602,3 +617,41 @@ int replay_journals(struct gfs2_sbd *sdp, int preen, int force_check,
fsync(sdp->device_fd);
return error;
}
+
+/*
+ * ji_update - fill in journal info
+ * sdp: the incore superblock pointer
+ *
+ * Given the inode for the journal index, read in all
+ * the journal inodes.
+ *
+ * Returns: 0 on success, -1 on failure
+ */
+int ji_update(struct gfs2_sbd *sdp)
+{
+ struct gfs2_inode *jip, *ip = sdp->md.jiinode;
+ char journal_name[JOURNAL_NAME_SIZE];
+ int i;
+
+ if(!ip) {
+ log_crit("Journal index inode not found.\n");
+ return -1;
+ }
+
+ if(!(sdp->md.journal = calloc(ip->i_di.di_entries - 2, sizeof(struct gfs2_inode *)))) {
+ log_err("Unable to allocate journal index\n");
+ return -1;
+ }
+ sdp->md.journals = 0;
+ memset(journal_name, 0, sizeof(*journal_name));
+ for(i = 0; i < ip->i_di.di_entries - 2; i++) {
+ /* FIXME check snprintf return code */
+ snprintf(journal_name, JOURNAL_NAME_SIZE, "journal%u", i);
+ gfs2_lookupi(sdp->md.jiinode, journal_name, strlen(journal_name),
+ &jip);
+ sdp->md.journal[i] = jip;
+ }
+ sdp->md.journals = ip->i_di.di_entries - 2;
+ return 0;
+
+}
diff --git a/gfs2/fsck/fs_recovery.h b/gfs2/fsck/fs_recovery.h
index a61884d..1a7aae3 100644
--- a/gfs2/fsck/fs_recovery.h
+++ b/gfs2/fsck/fs_recovery.h
@@ -3,9 +3,10 @@
#include "libgfs2.h"
-int replay_journals(struct gfs2_sbd *sdp, int preen, int force_check,
- int *clean_journals);
-int preen_is_safe(struct gfs2_sbd *sdp, int preen, int force_check);
+extern int replay_journals(struct gfs2_sbd *sdp, int preen, int force_check,
+ int *clean_journals);
+extern int preen_is_safe(struct gfs2_sbd *sdp, int preen, int force_check);
+extern int ji_update(struct gfs2_sbd *sdp);
#endif /* __FS_RECOVERY_H__ */
diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c
index 72d35ad..6936d02 100644
--- a/gfs2/fsck/pass1.c
+++ b/gfs2/fsck/pass1.c
@@ -1176,25 +1176,37 @@ static int handle_di(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh)
/* Check system inode and verify it's marked "in use" in the bitmap: */
/* Should work for all system inodes: root, master, jindex, per_node, etc. */
-static int check_system_inode(struct gfs2_inode *sysinode, const char *filename,
- int builder(struct gfs2_sbd *sbp),
- enum gfs2_mark_block mark)
+/* We have to pass the sysinode as ** because the pointer may change out from
+ under the reference by way of the builder() function. */
+static int check_system_inode(struct gfs2_sbd *sdp,
+ struct gfs2_inode **sysinode,
+ const char *filename,
+ int builder(struct gfs2_sbd *sbp),
+ enum gfs2_mark_block mark)
{
uint64_t iblock = 0;
struct dir_status ds = {0};
int error;
log_info( _("Checking system inode '%s'\n"), filename);
- if (sysinode) {
+ if (*sysinode) {
/* Read in the system inode, look at its dentries, and start
* reading through them */
- iblock = sysinode->i_di.di_num.no_addr;
+ iblock = (*sysinode)->i_di.di_num.no_addr;
log_info( _("System inode for '%s' is located at block %"
PRIu64 " (0x%" PRIx64 ")\n"), filename,
iblock, iblock);
-
- /* FIXME: check this block's validity */
-
+ if (gfs2_check_meta((*sysinode)->i_bh, GFS2_METATYPE_DI)) {
+ log_err( _("Found invalid system dinode at block #"
+ "%llu (0x%llx)\n"),
+ (unsigned long long)iblock,
+ (unsigned long long)iblock);
+ gfs2_blockmap_set(bl, iblock, gfs2_block_free);
+ check_n_fix_bitmap(sdp, iblock, gfs2_block_free);
+ inode_put(sysinode);
+ }
+ }
+ if (*sysinode) {
ds.q = block_type(iblock);
/* If the inode exists but the block is marked free, we might
be recovering from a corrupt bitmap. In that case, don't
@@ -1203,52 +1215,67 @@ static int check_system_inode(struct gfs2_inode *sysinode, const char *filename,
if (ds.q == gfs2_block_free) {
log_info( _("The inode exists but the block is not "
"marked 'in use'; fixing it.\n"));
- fsck_blockmap_set(sysinode,
- sysinode->i_di.di_num.no_addr,
+ fsck_blockmap_set(*sysinode,
+ (*sysinode)->i_di.di_num.no_addr,
filename, mark);
ds.q = mark;
if (mark == gfs2_inode_dir)
- dirtree_insert(sysinode->i_di.di_num.no_addr);
+ dirtree_insert((*sysinode)->i_di.di_num.no_addr);
}
} else
- log_info( _("System inode for '%s' is missing.\n"), filename);
+ log_info( _("System inode for '%s' is corrupt or missing.\n"),
+ filename);
/* If there are errors with the inode here, we need to create a new
inode and get it all setup - of course, everything will be in
lost+found then, but we *need* our system inodes before we can
do any of that. */
- if(!sysinode || ds.q != mark) {
+ if(!(*sysinode) || ds.q != mark) {
log_err( _("Invalid or missing %s system inode (should be %d, "
"is %d).\n"), filename, mark, ds.q);
if (query(_("Create new %s system inode? (y/n) "), filename)) {
- builder(sysinode->i_sbd);
- fsck_blockmap_set(sysinode,
- sysinode->i_di.di_num.no_addr,
+ log_err( _("Rebuilding system file \"%s\"\n"),
+ filename);
+ error = builder(sdp);
+ if (error) {
+ log_err( _("Error trying to rebuild system "
+ "file %s: Cannot continue\n"),
+ filename);
+ return error;
+ }
+ fsck_blockmap_set(*sysinode,
+ (*sysinode)->i_di.di_num.no_addr,
filename, mark);
ds.q = mark;
if (mark == gfs2_inode_dir)
- dirtree_insert(sysinode->i_di.di_num.no_addr);
+ dirtree_insert((*sysinode)->i_di.di_num.no_addr);
} else {
log_err( _("Cannot continue without valid %s inode\n"),
filename);
return -1;
}
}
- if (S_ISDIR(sysinode->i_di.di_mode)) {
+ if (S_ISDIR((*sysinode)->i_di.di_mode)) {
struct block_count bc = {0};
sysdir_fxns.private = &bc;
- if (sysinode->i_di.di_flags & GFS2_DIF_EXHASH)
- check_metatree(sysinode, &sysdir_fxns);
+ if ((*sysinode)->i_di.di_flags & GFS2_DIF_EXHASH)
+ check_metatree(*sysinode, &sysdir_fxns);
else
- check_linear_dir(sysinode, sysinode->i_bh,
+ check_linear_dir(*sysinode, (*sysinode)->i_bh,
&sysdir_fxns);
}
- error = handle_ip(sysinode->i_sbd, sysinode);
+ error = handle_ip(sdp, *sysinode);
return error;
}
static int build_a_journal(struct gfs2_sbd *sdp)
{
+ char name[256];
+
+ /* First, try to delete the journal if it's in jindex */
+ sprintf(name, "journal%u", sdp->md.journals);
+ gfs2_dirent_del(sdp->md.jiinode, name, strlen(name));
+ /* Now rebuild it */
build_journal(sdp, sdp->md.journals, sdp->md.jiinode);
return 0;
}
@@ -1260,43 +1287,43 @@ static int check_system_inodes(struct gfs2_sbd *sdp)
/*******************************************************************
******* Check the system inode integrity *************
*******************************************************************/
- if (check_system_inode(sdp->master_dir, "master", build_master,
+ if (check_system_inode(sdp, &sdp->master_dir, "master", build_master,
gfs2_inode_dir)) {
stack;
return -1;
}
- if (check_system_inode(sdp->md.rooti, "root", build_root,
+ if (check_system_inode(sdp, &sdp->md.rooti, "root", build_root,
gfs2_inode_dir)) {
stack;
return -1;
}
- if (check_system_inode(sdp->md.inum, "inum", build_inum,
+ if (check_system_inode(sdp, &sdp->md.inum, "inum", build_inum,
gfs2_inode_file)) {
stack;
return -1;
}
- if (check_system_inode(sdp->md.statfs, "statfs", build_statfs,
+ if (check_system_inode(sdp, &sdp->md.statfs, "statfs", build_statfs,
gfs2_inode_file)) {
stack;
return -1;
}
- if (check_system_inode(sdp->md.jiinode, "jindex", build_jindex,
+ if (check_system_inode(sdp, &sdp->md.jiinode, "jindex", build_jindex,
gfs2_inode_dir)) {
stack;
return -1;
}
- if (check_system_inode(sdp->md.riinode, "rindex", build_rindex,
+ if (check_system_inode(sdp, &sdp->md.riinode, "rindex", build_rindex,
gfs2_inode_file)) {
stack;
return -1;
}
- if (check_system_inode(sdp->md.qinode, "quota", build_quota,
+ if (check_system_inode(sdp, &sdp->md.qinode, "quota", build_quota,
gfs2_inode_file)) {
stack;
return -1;
}
- if (check_system_inode(sdp->md.pinode, "per_node", build_per_node,
- gfs2_inode_dir)) {
+ if (check_system_inode(sdp, &sdp->md.pinode, "per_node",
+ build_per_node, gfs2_inode_dir)) {
stack;
return -1;
}
@@ -1308,7 +1335,7 @@ static int check_system_inodes(struct gfs2_sbd *sdp)
char jname[16];
sprintf(jname, "journal%d", sdp->md.journals);
- if (check_system_inode(sdp->md.journal[sdp->md.journals],
+ if (check_system_inode(sdp, &sdp->md.journal[sdp->md.journals],
jname, build_a_journal,
gfs2_inode_file)) {
stack;
@@ -1401,6 +1428,14 @@ int pass1(struct gfs2_sbd *sbp)
skip_this_pass = FALSE;
fflush(stdout);
}
+ if (fsck_system_inode(sbp, block)) {
+ log_debug(_("Already processed system inode "
+ "%lld (0x%llx)\n"),
+ (unsigned long long)block,
+ (unsigned long long)block);
+ first = 0;
+ continue;
+ }
bh = bread(sbp, block);
/*log_debug( _("Checking metadata block #%" PRIu64
@@ -1419,11 +1454,6 @@ int pass1(struct gfs2_sbd *sbp)
}
check_n_fix_bitmap(sbp, block,
gfs2_block_free);
- } else if (fsck_system_inode(sbp, block)) {
- log_debug(_("Already processed system inode "
- "%lld (0x%llx)\n"),
- (unsigned long long)block,
- (unsigned long long)block);
} else if (handle_di(sbp, bh) < 0) {
stack;
brelse(bh);
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index 8835a4f..c798bda 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -472,8 +472,8 @@ extern int gfs2_dirent_next(struct gfs2_inode *dip, struct gfs2_buffer_head *bh,
extern void build_height(struct gfs2_inode *ip, int height);
extern void unstuff_dinode(struct gfs2_inode *ip);
extern unsigned int calc_tree_height(struct gfs2_inode *ip, uint64_t size);
-extern int write_journal(struct gfs2_sbd *sdp, struct gfs2_inode *ip,
- unsigned int j, unsigned int blocks);
+extern int write_journal(struct gfs2_sbd *sdp, unsigned int j,
+ unsigned int blocks);
/**
* device_size - figure out a device's size
@@ -671,7 +671,6 @@ extern int gfs2_next_rg_metatype(struct gfs2_sbd *sdp, struct rgrp_list *rgd,
/* super.c */
extern int check_sb(struct gfs2_sb *sb);
extern int read_sb(struct gfs2_sbd *sdp);
-extern int ji_update(struct gfs2_sbd *sdp);
extern int rindex_read(struct gfs2_sbd *sdp, int fd, int *count1, int *sane);
extern int ri_update(struct gfs2_sbd *sdp, int fd, int *rgcount, int *sane);
extern int write_sb(struct gfs2_sbd *sdp);
diff --git a/gfs2/libgfs2/structures.c b/gfs2/libgfs2/structures.c
index e798868..a46fb8d 100644
--- a/gfs2/libgfs2/structures.c
+++ b/gfs2/libgfs2/structures.c
@@ -75,8 +75,7 @@ void build_sb(struct gfs2_sbd *sdp, const unsigned char *uuid)
}
}
-int write_journal(struct gfs2_sbd *sdp, struct gfs2_inode *ip, unsigned int j,
- unsigned int blocks)
+int write_journal(struct gfs2_sbd *sdp, unsigned int j, unsigned int blocks)
{
struct gfs2_log_header lh;
unsigned int x;
@@ -86,8 +85,9 @@ int write_journal(struct gfs2_sbd *sdp, struct gfs2_inode *ip, unsigned int j,
/* Build the height up so our journal blocks will be contiguous and */
/* not broken up by indirect block pages. */
- height = calc_tree_height(ip, (blocks + 1) * sdp->bsize);
- build_height(ip, height);
+ height = calc_tree_height(sdp->md.journal[j],
+ (blocks + 1) * sdp->bsize);
+ build_height(sdp->md.journal[j], height);
memset(&lh, 0, sizeof(struct gfs2_log_header));
lh.lh_header.mh_magic = GFS2_MAGIC;
@@ -96,14 +96,16 @@ int write_journal(struct gfs2_sbd *sdp, struct gfs2_inode *ip, unsigned int j,
lh.lh_flags = GFS2_LOG_HEAD_UNMOUNT;
for (x = 0; x < blocks; x++) {
- struct gfs2_buffer_head *bh = get_file_buf(ip, x, TRUE);
+ struct gfs2_buffer_head *bh = get_file_buf(sdp->md.journal[j],
+ x, TRUE);
if (!bh)
return -1;
bmodified(bh);
brelse(bh);
}
for (x = 0; x < blocks; x++) {
- struct gfs2_buffer_head *bh = get_file_buf(ip, x, FALSE);
+ struct gfs2_buffer_head *bh = get_file_buf(sdp->md.journal[j],
+ x, FALSE);
if (!bh)
return -1;
@@ -123,7 +125,7 @@ int write_journal(struct gfs2_sbd *sdp, struct gfs2_inode *ip, unsigned int j,
if (sdp->debug) {
printf("\nJournal %u:\n", j);
- gfs2_dinode_print(&ip->i_di);
+ gfs2_dinode_print(&sdp->md.journal[j]->i_di);
}
return 0;
}
@@ -131,17 +133,14 @@ int write_journal(struct gfs2_sbd *sdp, struct gfs2_inode *ip, unsigned int j,
int build_journal(struct gfs2_sbd *sdp, int j, struct gfs2_inode *jindex)
{
char name[256];
- struct gfs2_inode *ip;
int ret;
sprintf(name, "journal%u", j);
- ip = createi(jindex, name, S_IFREG | 0600, GFS2_DIF_SYSTEM);
- ret = write_journal(sdp, ip, j,
+ sdp->md.journal[j] = createi(jindex, name, S_IFREG | 0600,
+ GFS2_DIF_SYSTEM);
+ ret = write_journal(sdp, j,
sdp->jsize << 20 >> sdp->sd_sb.sb_bsize_shift);
- if (ret)
- return ret;
- inode_put(&ip);
- return 0;
+ return ret;
}
int build_jindex(struct gfs2_sbd *sdp)
@@ -152,17 +151,20 @@ int build_jindex(struct gfs2_sbd *sdp)
jindex = createi(sdp->master_dir, "jindex", S_IFDIR | 0700,
GFS2_DIF_SYSTEM);
-
+ sdp->md.journal = malloc(sdp->md.journals *
+ sizeof(struct gfs2_inode *));
for (j = 0; j < sdp->md.journals; j++) {
ret = build_journal(sdp, j, jindex);
if (ret)
return ret;
+ inode_put(&sdp->md.journal[j]);
}
if (sdp->debug) {
printf("\nJindex:\n");
gfs2_dinode_print(&jindex->i_di);
}
+ free(sdp->md.journal);
inode_put(&jindex);
return 0;
}
diff --git a/gfs2/libgfs2/super.c b/gfs2/libgfs2/super.c
index 961f72d..70e9c82 100644
--- a/gfs2/libgfs2/super.c
+++ b/gfs2/libgfs2/super.c
@@ -77,6 +77,9 @@ int read_sb(struct gfs2_sbd *sdp)
(sdp->sd_sb.sb_bsize-sizeof(struct gfs2_meta_header)) /
sizeof(uint64_t);
sdp->sd_jbsize = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_meta_header);
+ sdp->sd_hash_bsize = sdp->bsize / 2;
+ sdp->sd_hash_bsize_shift = sdp->sd_sb.sb_bsize_shift - 1;
+ sdp->sd_hash_ptrs = sdp->sd_hash_bsize / sizeof(uint64_t);
sdp->sd_heightsize[0] = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode);
sdp->sd_heightsize[1] = sdp->sd_sb.sb_bsize * sdp->sd_diptrs;
for (x = 2; ; x++){
@@ -115,46 +118,6 @@ int read_sb(struct gfs2_sbd *sdp)
return error;
}
-#define JOURNAL_NAME_SIZE 16
-
-/*
- * ji_update - fill in journal info
- * sdp: the incore superblock pointer
- *
- * Given the inode for the journal index, read in all
- * the journal inodes.
- *
- * Returns: 0 on success, -1 on failure
- */
-int ji_update(struct gfs2_sbd *sdp)
-{
- struct gfs2_inode *jip, *ip = sdp->md.jiinode;
- char journal_name[JOURNAL_NAME_SIZE];
- int i;
-
- if(!ip) {
- log_crit("Journal index inode not found.\n");
- return -1;
- }
-
- if(!(sdp->md.journal = calloc(ip->i_di.di_entries - 2, sizeof(struct gfs2_inode *)))) {
- log_err("Unable to allocate journal index\n");
- return -1;
- }
- sdp->md.journals = 0;
- memset(journal_name, 0, sizeof(*journal_name));
- for(i = 0; i < ip->i_di.di_entries - 2; i++) {
- /* FIXME check snprintf return code */
- snprintf(journal_name, JOURNAL_NAME_SIZE, "journal%u", i);
- gfs2_lookupi(sdp->md.jiinode, journal_name, strlen(journal_name),
- &jip);
- sdp->md.journal[i] = jip;
- }
- sdp->md.journals = ip->i_di.di_entries - 2;
- return 0;
-
-}
-
/**
* rindex_read - read in the rg index file
* @sdp: the incore superblock pointer
13 years, 9 months