From 16514290411b99b5887653043647429e8c6cba91 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Mon, 4 Apr 2022 09:55:05 +0100 Subject: [PATCH] union: add min_free_space option for lfs/eplfs policies - fixes #6071 --- backend/union/common/options.go | 1 + backend/union/policy/eplfs.go | 19 +++++++++++++------ backend/union/union.go | 8 ++++++++ 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/backend/union/common/options.go b/backend/union/common/options.go index cc275cc37..edc715203 100644 --- a/backend/union/common/options.go +++ b/backend/union/common/options.go @@ -13,4 +13,5 @@ type Options struct { CreatePolicy string `config:"create_policy"` SearchPolicy string `config:"search_policy"` CacheTime int `config:"cache_time"` + MinFreeSpace fs.SizeSuffix `config:"min_free_space"` } diff --git a/backend/union/policy/eplfs.go b/backend/union/policy/eplfs.go index a2788138c..28d84ff5c 100644 --- a/backend/union/policy/eplfs.go +++ b/backend/union/policy/eplfs.go @@ -2,6 +2,7 @@ package policy import ( "context" + "errors" "math" "github.com/rclone/rclone/backend/union/upstream" @@ -18,6 +19,8 @@ type EpLfs struct { EpAll } +var errNoUpstreamsFound = errors.New("no upstreams found with more than min_free_space space spare") + func (p *EpLfs) lfs(upstreams []*upstream.Fs) (*upstream.Fs, error) { var minFreeSpace int64 = math.MaxInt64 var lfsupstream *upstream.Fs @@ -27,31 +30,35 @@ func (p *EpLfs) lfs(upstreams []*upstream.Fs) (*upstream.Fs, error) { fs.LogPrintf(fs.LogLevelNotice, nil, "Free Space is not supported for upstream %s, treating as infinite", u.Name()) } - if space < minFreeSpace { + if space < minFreeSpace && space > int64(u.Opt.MinFreeSpace) { minFreeSpace = space lfsupstream = u } } if lfsupstream == nil { - return nil, fs.ErrorObjectNotFound + return nil, errNoUpstreamsFound } return lfsupstream, nil } func (p *EpLfs) lfsEntries(entries []upstream.Entry) (upstream.Entry, error) { - var minFreeSpace int64 + var minFreeSpace int64 = math.MaxInt64 var lfsEntry upstream.Entry for _, e := range entries { - space, err := e.UpstreamFs().GetFreeSpace() + u := e.UpstreamFs() + space, err := u.GetFreeSpace() if err != nil { fs.LogPrintf(fs.LogLevelNotice, nil, - "Free Space is not supported for upstream %s, treating as infinite", e.UpstreamFs().Name()) + "Free Space is not supported for upstream %s, treating as infinite", u.Name()) } - if space < minFreeSpace { + if space < minFreeSpace && space > int64(u.Opt.MinFreeSpace) { minFreeSpace = space lfsEntry = e } } + if lfsEntry == nil { + return nil, errNoUpstreamsFound + } return lfsEntry, nil } diff --git a/backend/union/union.go b/backend/union/union.go index dc4e2c589..9776c55d2 100644 --- a/backend/union/union.go +++ b/backend/union/union.go @@ -50,6 +50,14 @@ func init() { Name: "cache_time", Help: "Cache time of usage and free space (in seconds).\n\nThis option is only useful when a path preserving policy is used.", Default: 120, + }, { + Name: "min_free_space", + Help: `Minimum viable free space for lfs/eplfs policies. + +If a remote has less than this much free space then it won't be +considered for use in lfs or eplfs policies.`, + Advanced: true, + Default: fs.Gibi, }}, } fs.Register(fsi)