From b5adbc477f19b85477cb268eaf1ed362e6790ba7 Mon Sep 17 00:00:00 2001 From: Alex Mazalov Date: Sun, 3 Jan 2021 22:54:22 +0000 Subject: [PATCH 01/10] cmd/geth: monitoring free disk space to avoid db corruption Adding warnings of free disk space left and graceful shutdown when there is not enough space left. --- cmd/utils/cmd.go | 32 ++++++++++++++++++++++----- cmd/utils/diskusage.go | 40 ++++++++++++++++++++++++++++++++++ cmd/utils/diskusage_windows.go | 40 ++++++++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+), 6 deletions(-) create mode 100644 cmd/utils/diskusage.go create mode 100644 cmd/utils/diskusage_windows.go diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go index 869cf90ea57b..bacc9d7e4b2a 100644 --- a/cmd/utils/cmd.go +++ b/cmd/utils/cmd.go @@ -26,6 +26,7 @@ import ( "runtime" "strings" "syscall" + "time" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" @@ -40,7 +41,13 @@ import ( ) const ( - importBatchSize = 2500 + importBatchSize = 2500 + freeDiskSpaceWarning = 1024 * 1024 * 1024 + freeDiskSpaceCritical = 300 * 1024 * 1024 +) + +var ( + sigtermCh = make(chan os.Signal, 1) ) // Fatalf formats a message to standard error and exits the program. @@ -68,14 +75,14 @@ func StartNode(stack *node.Node) { Fatalf("Error starting protocol stack: %v", err) } go func() { - sigc := make(chan os.Signal, 1) - signal.Notify(sigc, syscall.SIGINT, syscall.SIGTERM) - defer signal.Stop(sigc) - <-sigc + signal.Notify(sigtermCh, syscall.SIGINT, syscall.SIGTERM) + defer signal.Stop(sigtermCh) + go monitorFreeDiskSpace(stack.InstanceDir()) + <-sigtermCh log.Info("Got interrupt, shutting down...") go stack.Close() for i := 10; i > 0; i-- { - <-sigc + <-sigtermCh if i > 1 { log.Warn("Already shutting down, interrupt more to panic.", "times", i-1) } @@ -85,6 +92,19 @@ func StartNode(stack *node.Node) { }() } +func monitorFreeDiskSpace(path string) { + for { + freeSpace := getFreeDiskSpace(path) + if freeSpace < freeDiskSpaceCritical { + log.Error("Low disk space. Gracefully shutting down Geth to prevent database corruption.", "available", freeSpace/1024/1024) + sigtermCh <- syscall.SIGTERM + } else if freeSpace < freeDiskSpaceWarning { + log.Warn("Disk space is running low. Geth will shutdown if disk space runs below critical level.", "available", freeSpace/1024/1024, "critical_level", freeDiskSpaceCritical/1024/1024) + } + time.Sleep(5 * time.Second) + } +} + func ImportChain(chain *core.BlockChain, fn string) error { // Watch for Ctrl-C while the import is running. // If a signal is received, the import will stop at the next batch. diff --git a/cmd/utils/diskusage.go b/cmd/utils/diskusage.go new file mode 100644 index 000000000000..88522dbc7982 --- /dev/null +++ b/cmd/utils/diskusage.go @@ -0,0 +1,40 @@ +// Copyright 2020 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// +build !windows + +package utils + +import ( + "github.com/ethereum/go-ethereum/log" + "golang.org/x/sys/unix" + "syscall" +) + +var stat unix.Statfs_t + +func getFreeDiskSpace(path string) uint64 { + + err := unix.Statfs(path, &stat) + if err != nil { + log.Warn("Failed to call Statfs", "path", path, "err", err) + sigtermCh <- syscall.SIGTERM + return 0 + } + + // Available blocks * size per block = available space in bytes + return stat.Bavail * uint64(stat.Bsize) +} diff --git a/cmd/utils/diskusage_windows.go b/cmd/utils/diskusage_windows.go new file mode 100644 index 000000000000..9b1ee233c549 --- /dev/null +++ b/cmd/utils/diskusage_windows.go @@ -0,0 +1,40 @@ +// Copyright 2020 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package utils + +import ( + "github.com/ethereum/go-ethereum/log" + "golang.org/x/sys/windows" + "syscall" +) + +func getFreeDiskSpace(path string) uint64 { + + cwd, err := windows.UTF16PtrFromString(path) + if err != nil { + log.Warn("Failed to call UTF16PtrFromString", "path", path, "err", err) + sigtermCh <- syscall.SIGTERM + } + + var freeBytesAvailableToCaller, totalNumberOfBytes, totalNumberOfFreeBytes uint64 + if err := windows.GetDiskFreeSpaceEx(cwd, &freeBytesAvailableToCaller, &totalNumberOfBytes, &totalNumberOfFreeBytes); err != nil { + log.Warn("Failed to call GetDiskFreeSpaceEx", "path", path, "err", err) + sigtermCh <- syscall.SIGTERM + } + + return freeBytesAvailableToCaller +} From d6a22bfc77a3c42f7392e483c8ece7217c74d804 Mon Sep 17 00:00:00 2001 From: Alex Mazalov Date: Sun, 3 Jan 2021 22:54:22 +0000 Subject: [PATCH 02/10] code formatting --- cmd/utils/diskusage.go | 3 ++- cmd/utils/diskusage_windows.go | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/cmd/utils/diskusage.go b/cmd/utils/diskusage.go index 88522dbc7982..8a3a301bb047 100644 --- a/cmd/utils/diskusage.go +++ b/cmd/utils/diskusage.go @@ -19,9 +19,10 @@ package utils import ( + "syscall" + "github.com/ethereum/go-ethereum/log" "golang.org/x/sys/unix" - "syscall" ) var stat unix.Statfs_t diff --git a/cmd/utils/diskusage_windows.go b/cmd/utils/diskusage_windows.go index 9b1ee233c549..2ccf9200ebce 100644 --- a/cmd/utils/diskusage_windows.go +++ b/cmd/utils/diskusage_windows.go @@ -17,9 +17,10 @@ package utils import ( + "syscall" + "github.com/ethereum/go-ethereum/log" "golang.org/x/sys/windows" - "syscall" ) func getFreeDiskSpace(path string) uint64 { From 0a424629ec40b7c735e3a65ec0aaf2c9dd2c3b65 Mon Sep 17 00:00:00 2001 From: Alex Mazalov Date: Mon, 4 Jan 2021 13:29:36 +0000 Subject: [PATCH 03/10] revert sigterm channel global var --- cmd/utils/cmd.go | 25 +++++++++++++------------ cmd/utils/diskusage.go | 11 ++++------- cmd/utils/diskusage_windows.go | 13 +++++-------- 3 files changed, 22 insertions(+), 27 deletions(-) diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go index bacc9d7e4b2a..339d5cccd117 100644 --- a/cmd/utils/cmd.go +++ b/cmd/utils/cmd.go @@ -46,10 +46,6 @@ const ( freeDiskSpaceCritical = 300 * 1024 * 1024 ) -var ( - sigtermCh = make(chan os.Signal, 1) -) - // Fatalf formats a message to standard error and exits the program. // The message is also printed to standard output if standard error // is redirected to a different file. @@ -75,14 +71,15 @@ func StartNode(stack *node.Node) { Fatalf("Error starting protocol stack: %v", err) } go func() { - signal.Notify(sigtermCh, syscall.SIGINT, syscall.SIGTERM) - defer signal.Stop(sigtermCh) - go monitorFreeDiskSpace(stack.InstanceDir()) - <-sigtermCh + sigc := make(chan os.Signal, 1) + signal.Notify(sigc, syscall.SIGINT, syscall.SIGTERM) + defer signal.Stop(sigc) + go monitorFreeDiskSpace(sigc, stack.InstanceDir()) + <-sigc log.Info("Got interrupt, shutting down...") go stack.Close() for i := 10; i > 0; i-- { - <-sigtermCh + <-sigc if i > 1 { log.Warn("Already shutting down, interrupt more to panic.", "times", i-1) } @@ -92,12 +89,16 @@ func StartNode(stack *node.Node) { }() } -func monitorFreeDiskSpace(path string) { +func monitorFreeDiskSpace(sigc chan os.Signal, path string) { for { - freeSpace := getFreeDiskSpace(path) + freeSpace, err := getFreeDiskSpace(path) + if err != nil { + log.Error("Failed to get free disk space", "path", path, "err", err) + sigc <- syscall.SIGTERM + } if freeSpace < freeDiskSpaceCritical { log.Error("Low disk space. Gracefully shutting down Geth to prevent database corruption.", "available", freeSpace/1024/1024) - sigtermCh <- syscall.SIGTERM + sigc <- syscall.SIGTERM } else if freeSpace < freeDiskSpaceWarning { log.Warn("Disk space is running low. Geth will shutdown if disk space runs below critical level.", "available", freeSpace/1024/1024, "critical_level", freeDiskSpaceCritical/1024/1024) } diff --git a/cmd/utils/diskusage.go b/cmd/utils/diskusage.go index 8a3a301bb047..7f00ef487f58 100644 --- a/cmd/utils/diskusage.go +++ b/cmd/utils/diskusage.go @@ -19,23 +19,20 @@ package utils import ( - "syscall" + "fmt" - "github.com/ethereum/go-ethereum/log" "golang.org/x/sys/unix" ) var stat unix.Statfs_t -func getFreeDiskSpace(path string) uint64 { +func getFreeDiskSpace(path string) (uint64, error) { err := unix.Statfs(path, &stat) if err != nil { - log.Warn("Failed to call Statfs", "path", path, "err", err) - sigtermCh <- syscall.SIGTERM - return 0 + return 0, fmt.Errorf("failed to call Statfs: %v", err) } // Available blocks * size per block = available space in bytes - return stat.Bavail * uint64(stat.Bsize) + return stat.Bavail * uint64(stat.Bsize), nil } diff --git a/cmd/utils/diskusage_windows.go b/cmd/utils/diskusage_windows.go index 2ccf9200ebce..319ba0843a70 100644 --- a/cmd/utils/diskusage_windows.go +++ b/cmd/utils/diskusage_windows.go @@ -17,25 +17,22 @@ package utils import ( - "syscall" + "fmt" - "github.com/ethereum/go-ethereum/log" "golang.org/x/sys/windows" ) -func getFreeDiskSpace(path string) uint64 { +func getFreeDiskSpace(path string) (uint64, error) { cwd, err := windows.UTF16PtrFromString(path) if err != nil { - log.Warn("Failed to call UTF16PtrFromString", "path", path, "err", err) - sigtermCh <- syscall.SIGTERM + return 0, fmt.Errorf("failed to call UTF16PtrFromString: %v", err) } var freeBytesAvailableToCaller, totalNumberOfBytes, totalNumberOfFreeBytes uint64 if err := windows.GetDiskFreeSpaceEx(cwd, &freeBytesAvailableToCaller, &totalNumberOfBytes, &totalNumberOfFreeBytes); err != nil { - log.Warn("Failed to call GetDiskFreeSpaceEx", "path", path, "err", err) - sigtermCh <- syscall.SIGTERM + return 0, fmt.Errorf("failed to call GetDiskFreeSpaceEx: %v", err) } - return freeBytesAvailableToCaller + return freeBytesAvailableToCaller, nil } From ccc95b87f4e6d8a20ef04430e482237addcaa317 Mon Sep 17 00:00:00 2001 From: Alex Mazalov Date: Mon, 4 Jan 2021 13:46:13 +0000 Subject: [PATCH 04/10] prevent duplicate sigterm signals --- cmd/utils/cmd.go | 2 ++ cmd/utils/diskusage.go | 2 +- cmd/utils/diskusage_windows.go | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go index 339d5cccd117..d324d2b75daa 100644 --- a/cmd/utils/cmd.go +++ b/cmd/utils/cmd.go @@ -95,10 +95,12 @@ func monitorFreeDiskSpace(sigc chan os.Signal, path string) { if err != nil { log.Error("Failed to get free disk space", "path", path, "err", err) sigc <- syscall.SIGTERM + break } if freeSpace < freeDiskSpaceCritical { log.Error("Low disk space. Gracefully shutting down Geth to prevent database corruption.", "available", freeSpace/1024/1024) sigc <- syscall.SIGTERM + break } else if freeSpace < freeDiskSpaceWarning { log.Warn("Disk space is running low. Geth will shutdown if disk space runs below critical level.", "available", freeSpace/1024/1024, "critical_level", freeDiskSpaceCritical/1024/1024) } diff --git a/cmd/utils/diskusage.go b/cmd/utils/diskusage.go index 7f00ef487f58..a45fd6a6a9e1 100644 --- a/cmd/utils/diskusage.go +++ b/cmd/utils/diskusage.go @@ -1,4 +1,4 @@ -// Copyright 2020 The go-ethereum Authors +// Copyright 2021 The go-ethereum Authors // This file is part of the go-ethereum library. // // The go-ethereum library is free software: you can redistribute it and/or modify diff --git a/cmd/utils/diskusage_windows.go b/cmd/utils/diskusage_windows.go index 319ba0843a70..9bf7740b9941 100644 --- a/cmd/utils/diskusage_windows.go +++ b/cmd/utils/diskusage_windows.go @@ -1,4 +1,4 @@ -// Copyright 2020 The go-ethereum Authors +// Copyright 2021 The go-ethereum Authors // This file is part of the go-ethereum library. // // The go-ethereum library is free software: you can redistribute it and/or modify From 4aba67052d05b99494a3c9361d8d89587a7f3aea Mon Sep 17 00:00:00 2001 From: Alex Mazalov Date: Mon, 4 Jan 2021 14:08:35 +0000 Subject: [PATCH 05/10] don't terminate geth if getFreeDiskSpace is not working --- cmd/utils/cmd.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go index d324d2b75daa..93e99c8d098f 100644 --- a/cmd/utils/cmd.go +++ b/cmd/utils/cmd.go @@ -93,8 +93,7 @@ func monitorFreeDiskSpace(sigc chan os.Signal, path string) { for { freeSpace, err := getFreeDiskSpace(path) if err != nil { - log.Error("Failed to get free disk space", "path", path, "err", err) - sigc <- syscall.SIGTERM + log.Warn("Failed to get free disk space", "path", path, "err", err) break } if freeSpace < freeDiskSpaceCritical { From d98a93eb8114955277d2ba39701222f743e152a8 Mon Sep 17 00:00:00 2001 From: Alex Mazalov Date: Mon, 4 Jan 2021 14:24:29 +0000 Subject: [PATCH 06/10] Update cmd/utils/diskusage.go code formatting Co-authored-by: Martin Holst Swende --- cmd/utils/diskusage.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cmd/utils/diskusage.go b/cmd/utils/diskusage.go index a45fd6a6a9e1..141b0ead40e5 100644 --- a/cmd/utils/diskusage.go +++ b/cmd/utils/diskusage.go @@ -28,8 +28,7 @@ var stat unix.Statfs_t func getFreeDiskSpace(path string) (uint64, error) { - err := unix.Statfs(path, &stat) - if err != nil { + if err := unix.Statfs(path, &stat); err != nil { return 0, fmt.Errorf("failed to call Statfs: %v", err) } From 17e224af743cc4ea50c304d8aecdea95591d07ef Mon Sep 17 00:00:00 2001 From: Alex Mazalov Date: Mon, 4 Jan 2021 14:31:53 +0000 Subject: [PATCH 07/10] friendly disk space formatting --- cmd/utils/cmd.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go index 93e99c8d098f..05a70f423afb 100644 --- a/cmd/utils/cmd.go +++ b/cmd/utils/cmd.go @@ -97,11 +97,11 @@ func monitorFreeDiskSpace(sigc chan os.Signal, path string) { break } if freeSpace < freeDiskSpaceCritical { - log.Error("Low disk space. Gracefully shutting down Geth to prevent database corruption.", "available", freeSpace/1024/1024) + log.Error("Low disk space. Gracefully shutting down Geth to prevent database corruption.", "available", common.StorageSize(freeSpace)) sigc <- syscall.SIGTERM break } else if freeSpace < freeDiskSpaceWarning { - log.Warn("Disk space is running low. Geth will shutdown if disk space runs below critical level.", "available", freeSpace/1024/1024, "critical_level", freeDiskSpaceCritical/1024/1024) + log.Warn("Disk space is running low. Geth will shutdown if disk space runs below critical level.", "available", common.StorageSize(freeSpace), "critical_level", common.StorageSize(freeDiskSpaceCritical)) } time.Sleep(5 * time.Second) } From bd9963744e169bd1865b1cd7f3817a61fe47c925 Mon Sep 17 00:00:00 2001 From: Alex Mazalov Date: Mon, 4 Jan 2021 18:53:19 +0000 Subject: [PATCH 08/10] monitor free disk space only for mainnet and never in fast sync mode; changing free disk warn level; check free disk space once in a minute --- cmd/geth/main.go | 2 +- cmd/utils/cmd.go | 17 ++++++++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/cmd/geth/main.go b/cmd/geth/main.go index e587a5f86dd6..86c7880fef09 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -366,7 +366,7 @@ func startNode(ctx *cli.Context, stack *node.Node, backend ethapi.Backend) { debug.Memsize.Add("node", stack) // Start up the node itself - utils.StartNode(stack) + utils.StartNode(ctx, stack, backend.ChainConfig().ChainID) // Unlock any account specifically requested unlockAccounts(ctx, stack) diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go index 05a70f423afb..903f5ba7440a 100644 --- a/cmd/utils/cmd.go +++ b/cmd/utils/cmd.go @@ -21,6 +21,7 @@ import ( "compress/gzip" "fmt" "io" + "math/big" "os" "os/signal" "runtime" @@ -33,16 +34,17 @@ import ( "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/internal/debug" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/rlp" + "gopkg.in/urfave/cli.v1" ) const ( importBatchSize = 2500 - freeDiskSpaceWarning = 1024 * 1024 * 1024 freeDiskSpaceCritical = 300 * 1024 * 1024 ) @@ -66,7 +68,7 @@ func Fatalf(format string, args ...interface{}) { os.Exit(1) } -func StartNode(stack *node.Node) { +func StartNode(ctx *cli.Context, stack *node.Node, chainID *big.Int) { if err := stack.Start(); err != nil { Fatalf("Error starting protocol stack: %v", err) } @@ -74,7 +76,12 @@ func StartNode(stack *node.Node) { sigc := make(chan os.Signal, 1) signal.Notify(sigc, syscall.SIGINT, syscall.SIGTERM) defer signal.Stop(sigc) - go monitorFreeDiskSpace(sigc, stack.InstanceDir()) + + syncMode := *GlobalTextMarshaler(ctx, SyncModeFlag.Name).(*downloader.SyncMode) + if chainID.Int64() == 1 && syncMode != downloader.FastSync { + go monitorFreeDiskSpace(sigc, stack.InstanceDir()) + } + <-sigc log.Info("Got interrupt, shutting down...") go stack.Close() @@ -100,10 +107,10 @@ func monitorFreeDiskSpace(sigc chan os.Signal, path string) { log.Error("Low disk space. Gracefully shutting down Geth to prevent database corruption.", "available", common.StorageSize(freeSpace)) sigc <- syscall.SIGTERM break - } else if freeSpace < freeDiskSpaceWarning { + } else if freeSpace < 2*freeDiskSpaceCritical { log.Warn("Disk space is running low. Geth will shutdown if disk space runs below critical level.", "available", common.StorageSize(freeSpace), "critical_level", common.StorageSize(freeDiskSpaceCritical)) } - time.Sleep(5 * time.Second) + time.Sleep(60 * time.Second) } } From b8e1eb1a611d4d8b03f66430ac0ae12bc34c1b05 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Tue, 5 Jan 2021 10:54:03 +0100 Subject: [PATCH 09/10] Update diskusage.go --- cmd/utils/diskusage.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cmd/utils/diskusage.go b/cmd/utils/diskusage.go index 141b0ead40e5..a822118a39a1 100644 --- a/cmd/utils/diskusage.go +++ b/cmd/utils/diskusage.go @@ -24,10 +24,8 @@ import ( "golang.org/x/sys/unix" ) -var stat unix.Statfs_t - func getFreeDiskSpace(path string) (uint64, error) { - + var stat unix.Statfs_t if err := unix.Statfs(path, &stat); err != nil { return 0, fmt.Errorf("failed to call Statfs: %v", err) } From 6bf421c6f283795876511b692bf69b9be97fc225 Mon Sep 17 00:00:00 2001 From: Alex Mazalov Date: Tue, 5 Jan 2021 23:32:28 +0000 Subject: [PATCH 10/10] cmd/geth: datadir.minfreedisk flag --- cmd/geth/main.go | 3 ++- cmd/geth/usage.go | 1 + cmd/utils/cmd.go | 21 ++++++++++++--------- cmd/utils/flags.go | 4 ++++ 4 files changed, 19 insertions(+), 10 deletions(-) diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 86c7880fef09..b55db29386c1 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -65,6 +65,7 @@ var ( utils.LegacyBootnodesV5Flag, utils.DataDirFlag, utils.AncientFlag, + utils.MinFreeDiskSpaceFlag, utils.KeyStoreDirFlag, utils.ExternalSignerFlag, utils.NoUSBFlag, @@ -366,7 +367,7 @@ func startNode(ctx *cli.Context, stack *node.Node, backend ethapi.Backend) { debug.Memsize.Add("node", stack) // Start up the node itself - utils.StartNode(ctx, stack, backend.ChainConfig().ChainID) + utils.StartNode(ctx, stack) // Unlock any account specifically requested unlockAccounts(ctx, stack) diff --git a/cmd/geth/usage.go b/cmd/geth/usage.go index 0e70451ed385..bf3b1b06e764 100644 --- a/cmd/geth/usage.go +++ b/cmd/geth/usage.go @@ -36,6 +36,7 @@ var AppHelpFlagGroups = []flags.FlagGroup{ configFileFlag, utils.DataDirFlag, utils.AncientFlag, + utils.MinFreeDiskSpaceFlag, utils.KeyStoreDirFlag, utils.NoUSBFlag, utils.SmartCardDaemonPathFlag, diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go index 903f5ba7440a..43062168927f 100644 --- a/cmd/utils/cmd.go +++ b/cmd/utils/cmd.go @@ -21,7 +21,6 @@ import ( "compress/gzip" "fmt" "io" - "math/big" "os" "os/signal" "runtime" @@ -34,7 +33,7 @@ import ( "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/eth/downloader" + "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/internal/debug" "github.com/ethereum/go-ethereum/log" @@ -44,8 +43,7 @@ import ( ) const ( - importBatchSize = 2500 - freeDiskSpaceCritical = 300 * 1024 * 1024 + importBatchSize = 2500 ) // Fatalf formats a message to standard error and exits the program. @@ -68,7 +66,7 @@ func Fatalf(format string, args ...interface{}) { os.Exit(1) } -func StartNode(ctx *cli.Context, stack *node.Node, chainID *big.Int) { +func StartNode(ctx *cli.Context, stack *node.Node) { if err := stack.Start(); err != nil { Fatalf("Error starting protocol stack: %v", err) } @@ -77,9 +75,14 @@ func StartNode(ctx *cli.Context, stack *node.Node, chainID *big.Int) { signal.Notify(sigc, syscall.SIGINT, syscall.SIGTERM) defer signal.Stop(sigc) - syncMode := *GlobalTextMarshaler(ctx, SyncModeFlag.Name).(*downloader.SyncMode) - if chainID.Int64() == 1 && syncMode != downloader.FastSync { - go monitorFreeDiskSpace(sigc, stack.InstanceDir()) + minFreeDiskSpace := eth.DefaultConfig.TrieDirtyCache + if ctx.GlobalIsSet(MinFreeDiskSpaceFlag.Name) { + minFreeDiskSpace = ctx.GlobalInt(MinFreeDiskSpaceFlag.Name) + } else if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) { + minFreeDiskSpace = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100 + } + if minFreeDiskSpace > 0 { + go monitorFreeDiskSpace(sigc, stack.InstanceDir(), uint64(minFreeDiskSpace)*1024*1024) } <-sigc @@ -96,7 +99,7 @@ func StartNode(ctx *cli.Context, stack *node.Node, chainID *big.Int) { }() } -func monitorFreeDiskSpace(sigc chan os.Signal, path string) { +func monitorFreeDiskSpace(sigc chan os.Signal, path string, freeDiskSpaceCritical uint64) { for { freeSpace, err := getFreeDiskSpace(path) if err != nil { diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index c51d7916ca80..379d3421c48e 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -113,6 +113,10 @@ var ( Name: "datadir.ancient", Usage: "Data directory for ancient chain segments (default = inside chaindata)", } + MinFreeDiskSpaceFlag = DirectoryFlag{ + Name: "datadir.minfreedisk", + Usage: "Minimum free disk space in MB, once reached triggers auto shut down (default = --cache.gc converted to MB, 0 = disabled)", + } KeyStoreDirFlag = DirectoryFlag{ Name: "keystore", Usage: "Directory for the keystore (default = inside the datadir)",