Allow cluster to start when only n/2 servers are up (#4066)

Fixes #3234.

Relaxes the quorum requirement to start the object layer, and skips
quick-healing at start-up (as no write quorum is present).
This commit is contained in:
Aditya Manthramurthy 2017-04-09 12:58:27 +05:30 committed by Harshavardhana
parent 6e9ac8db59
commit 604417baf4
2 changed files with 14 additions and 3 deletions

View File

@ -132,13 +132,14 @@ func prepForInitXL(firstDisk bool, sErrs []error, diskCount int) InitActions {
} }
quorum := diskCount/2 + 1 quorum := diskCount/2 + 1
readQuorum := diskCount / 2
disksOffline := errMap[errDiskNotFound] disksOffline := errMap[errDiskNotFound]
disksFormatted := errMap[nil] disksFormatted := errMap[nil]
disksUnformatted := errMap[errUnformattedDisk] disksUnformatted := errMap[errUnformattedDisk]
disksCorrupted := errMap[errCorruptedFormat] disksCorrupted := errMap[errCorruptedFormat]
// No Quorum lots of offline disks, wait for quorum. // No Quorum lots of offline disks, wait for quorum.
if disksOffline >= quorum { if disksOffline > readQuorum {
return WaitForQuorum return WaitForQuorum
} }
@ -168,7 +169,7 @@ func prepForInitXL(firstDisk bool, sErrs []error, diskCount int) InitActions {
} }
// Already formatted and in quorum, proceed to initialization of object layer. // Already formatted and in quorum, proceed to initialization of object layer.
if disksFormatted >= quorum { if disksFormatted >= readQuorum {
if disksFormatted+disksOffline == diskCount { if disksFormatted+disksOffline == diskCount {
return InitObjectLayer return InitObjectLayer
} }
@ -293,7 +294,7 @@ func initStorageDisks(endpoints []*url.URL) ([]StorageAPI, error) {
return storageDisks, nil return storageDisks, nil
} }
// Format disks before initialization object layer. // Format disks before initialization of object layer.
func waitForFormatXLDisks(firstDisk bool, endpoints []*url.URL, storageDisks []StorageAPI) (formattedDisks []StorageAPI, err error) { func waitForFormatXLDisks(firstDisk bool, endpoints []*url.URL, storageDisks []StorageAPI) (formattedDisks []StorageAPI, err error) {
if len(endpoints) == 0 { if len(endpoints) == 0 {
return nil, errInvalidArgument return nil, errInvalidArgument

View File

@ -155,6 +155,16 @@ func newXLObjects(storageDisks []StorageAPI) (ObjectLayer, error) {
xl.readQuorum = readQuorum xl.readQuorum = readQuorum
xl.writeQuorum = writeQuorum xl.writeQuorum = writeQuorum
// If the number of offline servers is equal to the readQuorum
// (i.e. the number of online servers also equals the
// readQuorum), we cannot perform quick-heal (no
// write-quorum). However reads may still be possible, so we
// skip quick-heal in this case, and continue.
offlineCount := len(newStorageDisks) - diskCount(newStorageDisks)
if offlineCount == readQuorum {
return xl, nil
}
// Do a quick heal on the buckets themselves for any discrepancies. // Do a quick heal on the buckets themselves for any discrepancies.
return xl, quickHeal(xl.storageDisks, xl.writeQuorum, xl.readQuorum) return xl, quickHeal(xl.storageDisks, xl.writeQuorum, xl.readQuorum)
} }