disable disk-usage when export is root mount path (#6091)

disk usage crawling is not needed when a tenant
is not sharing the same disk for multiple other
tenants. This PR adds an optimization when we
see a setup uses entire disk, we simply rely on
statvfs() to give us total usage.

This PR also additionally adds low priority
scheduling for usage check routine, such that
other go-routines blocked will be automatically
unblocked and prioritized before usage.
This commit is contained in:
Harshavardhana
2018-06-27 18:59:38 -07:00
committed by Dee Koder
parent abf209b1dd
commit 25de775560
6 changed files with 168 additions and 17 deletions

View File

@@ -34,6 +34,7 @@ import (
"github.com/minio/minio/pkg/lock"
"github.com/minio/minio/pkg/madmin"
"github.com/minio/minio/pkg/mimedb"
"github.com/minio/minio/pkg/mountinfo"
"github.com/minio/minio/pkg/policy"
)
@@ -64,6 +65,8 @@ type FSObjects struct {
// ListObjects pool management.
listPool *treeWalkPool
diskMount bool
appendFileMap map[string]*fsAppendFile
appendFileMapMu sync.Mutex
@@ -138,6 +141,7 @@ func NewFSObjectLayer(fsPath string) (ObjectLayer, error) {
nsMutex: newNSLock(false),
listPool: newTreeWalkPool(globalLookupTimeout),
appendFileMap: make(map[string]*fsAppendFile),
diskMount: mountinfo.IsLikelyMountPoint(fsPath),
}
// Once the filesystem has initialized hold the read lock for
@@ -156,7 +160,10 @@ func NewFSObjectLayer(fsPath string) (ObjectLayer, error) {
return nil, uiErrUnableToReadFromBackend(err).Msg("Unable to initialize policy system")
}
go fs.diskUsage(globalServiceDoneCh)
if !fs.diskMount {
go fs.diskUsage(globalServiceDoneCh)
}
go fs.cleanupStaleMultipartUploads(ctx, globalMultipartCleanupInterval, globalMultipartExpiry, globalServiceDoneCh)
// Return successfully initialized object layer.
@@ -177,17 +184,29 @@ func (fs *FSObjects) diskUsage(doneCh chan struct{}) {
defer ticker.Stop()
usageFn := func(ctx context.Context, entry string) error {
var fi os.FileInfo
var err error
if hasSuffix(entry, slashSeparator) {
fi, err = fsStatDir(ctx, entry)
} else {
fi, err = fsStatFile(ctx, entry)
if globalHTTPServer != nil {
// Any requests in progress, delay the usage.
for globalHTTPServer.GetRequestCount() > 0 {
time.Sleep(1 * time.Second)
}
}
if err != nil {
return err
select {
case <-doneCh:
return errWalkAbort
default:
var fi os.FileInfo
var err error
if hasSuffix(entry, slashSeparator) {
fi, err = fsStatDir(ctx, entry)
} else {
fi, err = fsStatFile(ctx, entry)
}
if err != nil {
return err
}
atomic.AddUint64(&fs.totalUsed, uint64(fi.Size()))
}
atomic.AddUint64(&fs.totalUsed, uint64(fi.Size()))
return nil
}
@@ -216,6 +235,13 @@ func (fs *FSObjects) diskUsage(doneCh chan struct{}) {
var usage uint64
usageFn = func(ctx context.Context, entry string) error {
if globalHTTPServer != nil {
// Any requests in progress, delay the usage.
for globalHTTPServer.GetRequestCount() > 0 {
time.Sleep(1 * time.Second)
}
}
var fi os.FileInfo
var err error
if hasSuffix(entry, slashSeparator) {
@@ -243,8 +269,16 @@ func (fs *FSObjects) diskUsage(doneCh chan struct{}) {
// StorageInfo - returns underlying storage statistics.
func (fs *FSObjects) StorageInfo(ctx context.Context) StorageInfo {
di, err := getDiskInfo(fs.fsPath)
if err != nil {
return StorageInfo{}
}
used := di.Total - di.Free
if !fs.diskMount {
used = atomic.LoadUint64(&fs.totalUsed)
}
storageInfo := StorageInfo{
Used: atomic.LoadUint64(&fs.totalUsed),
Used: used,
}
storageInfo.Backend.Type = FS
return storageInfo

View File

@@ -59,7 +59,12 @@ type Server struct {
listenerMutex *sync.Mutex // to guard 'listener' field.
listener *httpListener // HTTP listener for all 'Addrs' field.
inShutdown uint32 // indicates whether the server is in shutdown or not
requestCount int32 // counter holds no. of request in process.
requestCount int32 // counter holds no. of request in progress.
}
// GetRequestCount - returns number of request in progress.
func (srv *Server) GetRequestCount() int32 {
return atomic.LoadInt32(&srv.requestCount)
}
// Start - start HTTP server

View File

@@ -34,6 +34,7 @@ import (
humanize "github.com/dustin/go-humanize"
"github.com/minio/minio/cmd/logger"
"github.com/minio/minio/pkg/disk"
"github.com/minio/minio/pkg/mountinfo"
)
const (
@@ -69,6 +70,8 @@ type posix struct {
pool sync.Pool
connected bool
diskMount bool // indicates if the path is an actual mount.
// Disk usage metrics
stopUsageCh chan struct{}
}
@@ -183,9 +186,12 @@ func newPosix(path string) (*posix, error) {
},
},
stopUsageCh: make(chan struct{}),
diskMount: mountinfo.IsLikelyMountPoint(path),
}
go p.diskUsage(globalServiceDoneCh)
if !p.diskMount {
go p.diskUsage(globalServiceDoneCh)
}
// Success.
return p, nil
@@ -293,10 +299,14 @@ func (s *posix) DiskInfo() (info DiskInfo, err error) {
if err != nil {
return info, err
}
used := di.Total - di.Free
if !s.diskMount {
used = atomic.LoadUint64(&s.totalUsed)
}
return DiskInfo{
Total: di.Total,
Free: di.Free,
Used: atomic.LoadUint64(&s.totalUsed),
Used: used,
}, nil
}
@@ -336,7 +346,16 @@ func (s *posix) diskUsage(doneCh chan struct{}) {
defer ticker.Stop()
usageFn := func(ctx context.Context, entry string) error {
if globalHTTPServer != nil {
// Any requests in progress, delay the usage.
for globalHTTPServer.GetRequestCount() > 0 {
time.Sleep(1 * time.Second)
}
}
select {
case <-doneCh:
return errWalkAbort
case <-s.stopUsageCh:
return errWalkAbort
default:
@@ -377,6 +396,13 @@ func (s *posix) diskUsage(doneCh chan struct{}) {
var usage uint64
usageFn = func(ctx context.Context, entry string) error {
if globalHTTPServer != nil {
// Any requests in progress, delay the usage.
for globalHTTPServer.GetRequestCount() > 0 {
time.Sleep(1 * time.Second)
}
}
select {
case <-s.stopUsageCh:
return errWalkAbort