diff --git a/cmd/common-main.go b/cmd/common-main.go index c6f2824ad..dc09c992e 100644 --- a/cmd/common-main.go +++ b/cmd/common-main.go @@ -205,6 +205,16 @@ func handleCommonEnvVars() { globalCacheExpiry = expiry } + if maxUseStr := os.Getenv("MINIO_CACHE_MAXUSE"); maxUseStr != "" { + maxUse, err := strconv.Atoi(maxUseStr) + if err != nil { + logger.Fatal(uiErrInvalidCacheMaxUse(err), "Unable to parse MINIO_CACHE_MAXUSE value (`%s`)", maxUseStr) + } + // maxUse should be a valid percentage. + if maxUse > 0 && maxUse <= 100 { + globalCacheMaxUse = maxUse + } + } // In place update is true by default if the MINIO_UPDATE is not set // or is not set to 'off', if MINIO_UPDATE is set to 'off' then // in-place update is off. diff --git a/cmd/config-current.go b/cmd/config-current.go index 713716abe..8ebb9b8c6 100644 --- a/cmd/config-current.go +++ b/cmd/config-current.go @@ -39,9 +39,9 @@ import ( // 6. Make changes in config-current_test.go for any test change // Config version -const serverConfigVersion = "25" +const serverConfigVersion = "26" -type serverConfig = serverConfigV25 +type serverConfig = serverConfigV26 var ( // globalServerConfig server config. @@ -116,10 +116,11 @@ func (s *serverConfig) GetWorm() bool { } // SetCacheConfig sets the current cache config -func (s *serverConfig) SetCacheConfig(drives, exclude []string, expiry int) { +func (s *serverConfig) SetCacheConfig(drives, exclude []string, expiry int, maxuse int) { s.Cache.Drives = drives s.Cache.Exclude = exclude s.Cache.Expiry = expiry + s.Cache.MaxUse = maxuse } // GetCacheConfig gets the current cache config @@ -205,6 +206,7 @@ func newServerConfig() *serverConfig { Drives: []string{}, Exclude: []string{}, Expiry: globalCacheExpiry, + MaxUse: globalCacheMaxUse, }, Notify: notifier{}, } @@ -232,6 +234,7 @@ func newServerConfig() *serverConfig { srvCfg.Cache.Drives = make([]string, 0) srvCfg.Cache.Exclude = make([]string, 0) srvCfg.Cache.Expiry = globalCacheExpiry + srvCfg.Cache.MaxUse = globalCacheMaxUse return srvCfg } @@ -270,7 +273,7 @@ func newConfig() error { } if globalIsDiskCacheEnabled { - srvCfg.SetCacheConfig(globalCacheDrives, globalCacheExcludes, globalCacheExpiry) + srvCfg.SetCacheConfig(globalCacheDrives, globalCacheExcludes, globalCacheExpiry, globalCacheMaxUse) } // hold the mutex lock before a new config is assigned. @@ -358,7 +361,7 @@ func loadConfig() error { } if globalIsDiskCacheEnabled { - srvCfg.SetCacheConfig(globalCacheDrives, globalCacheExcludes, globalCacheExpiry) + srvCfg.SetCacheConfig(globalCacheDrives, globalCacheExcludes, globalCacheExpiry, globalCacheMaxUse) } // hold the mutex lock before a new config is assigned. @@ -387,6 +390,7 @@ func loadConfig() error { globalCacheDrives = cacheConf.Drives globalCacheExcludes = cacheConf.Exclude globalCacheExpiry = cacheConf.Expiry + globalCacheMaxUse = cacheConf.MaxUse } globalServerConfigMu.Unlock() diff --git a/cmd/config-migrate.go b/cmd/config-migrate.go index c2eabf821..b80cc47e9 100644 --- a/cmd/config-migrate.go +++ b/cmd/config-migrate.go @@ -183,6 +183,11 @@ func migrateConfig() error { return err } fallthrough + case "25": + if err = migrateV25ToV26(); err != nil { + return err + } + fallthrough case serverConfigVersion: // No migration needed. this always points to current version. err = nil @@ -2193,3 +2198,122 @@ func migrateV24ToV25() error { logger.Info(configMigrateMSGTemplate, configFile, cv24.Version, srvConfig.Version) return nil } + +func migrateV25ToV26() error { + configFile := getConfigFile() + + cv25 := &serverConfigV25{} + _, err := quick.LoadConfig(configFile, globalEtcdClient, cv25) + if os.IsNotExist(err) { + return nil + } else if err != nil { + return fmt.Errorf("Unable to load config version ‘25’. %v", err) + } + if cv25.Version != "25" { + return nil + } + + // Copy over fields from V25 into V26 config struct + srvConfig := &serverConfigV26{ + Notify: notifier{}, + } + srvConfig.Version = "26" + srvConfig.Credential = cv25.Credential + srvConfig.Region = cv25.Region + if srvConfig.Region == "" { + // Region needs to be set for AWS Signature Version 4. + srvConfig.Region = globalMinioDefaultRegion + } + + if len(cv25.Notify.AMQP) == 0 { + srvConfig.Notify.AMQP = make(map[string]target.AMQPArgs) + srvConfig.Notify.AMQP["1"] = target.AMQPArgs{} + } else { + srvConfig.Notify.AMQP = cv25.Notify.AMQP + } + if len(cv25.Notify.Elasticsearch) == 0 { + srvConfig.Notify.Elasticsearch = make(map[string]target.ElasticsearchArgs) + srvConfig.Notify.Elasticsearch["1"] = target.ElasticsearchArgs{ + Format: event.NamespaceFormat, + } + } else { + srvConfig.Notify.Elasticsearch = cv25.Notify.Elasticsearch + } + if len(cv25.Notify.Redis) == 0 { + srvConfig.Notify.Redis = make(map[string]target.RedisArgs) + srvConfig.Notify.Redis["1"] = target.RedisArgs{ + Format: event.NamespaceFormat, + } + } else { + srvConfig.Notify.Redis = cv25.Notify.Redis + } + if len(cv25.Notify.PostgreSQL) == 0 { + srvConfig.Notify.PostgreSQL = make(map[string]target.PostgreSQLArgs) + srvConfig.Notify.PostgreSQL["1"] = target.PostgreSQLArgs{ + Format: event.NamespaceFormat, + } + } else { + srvConfig.Notify.PostgreSQL = cv25.Notify.PostgreSQL + } + if len(cv25.Notify.Kafka) == 0 { + srvConfig.Notify.Kafka = make(map[string]target.KafkaArgs) + srvConfig.Notify.Kafka["1"] = target.KafkaArgs{} + } else { + srvConfig.Notify.Kafka = cv25.Notify.Kafka + } + if len(cv25.Notify.NATS) == 0 { + srvConfig.Notify.NATS = make(map[string]target.NATSArgs) + srvConfig.Notify.NATS["1"] = target.NATSArgs{} + } else { + srvConfig.Notify.NATS = cv25.Notify.NATS + } + if len(cv25.Notify.Webhook) == 0 { + srvConfig.Notify.Webhook = make(map[string]target.WebhookArgs) + srvConfig.Notify.Webhook["1"] = target.WebhookArgs{} + } else { + srvConfig.Notify.Webhook = cv25.Notify.Webhook + } + if len(cv25.Notify.MySQL) == 0 { + srvConfig.Notify.MySQL = make(map[string]target.MySQLArgs) + srvConfig.Notify.MySQL["1"] = target.MySQLArgs{ + Format: event.NamespaceFormat, + } + } else { + srvConfig.Notify.MySQL = cv25.Notify.MySQL + } + + if len(cv25.Notify.MQTT) == 0 { + srvConfig.Notify.MQTT = make(map[string]target.MQTTArgs) + srvConfig.Notify.MQTT["1"] = target.MQTTArgs{} + } else { + srvConfig.Notify.MQTT = cv25.Notify.MQTT + } + + // Load browser config from existing config in the file. + srvConfig.Browser = cv25.Browser + + // Load worm config from existing config in the file. + srvConfig.Worm = cv25.Worm + + // Load domain config from existing config in the file. + srvConfig.Domain = cv25.Domain + + // Load storage class config from existing storage class config in the file. + srvConfig.StorageClass.RRS = cv25.StorageClass.RRS + srvConfig.StorageClass.Standard = cv25.StorageClass.Standard + + // Load cache config from existing cache config in the file. + srvConfig.Cache.Drives = cv25.Cache.Drives + srvConfig.Cache.Exclude = cv25.Cache.Exclude + srvConfig.Cache.Expiry = cv25.Cache.Expiry + + // Add predefined value to new server config. + srvConfig.Cache.MaxUse = globalCacheMaxUse + + if err = quick.SaveConfig(srvConfig, configFile, globalEtcdClient); err != nil { + return fmt.Errorf("Failed to migrate config from ‘%s’ to ‘%s’. %v", cv25.Version, srvConfig.Version, err) + } + + logger.Info(configMigrateMSGTemplate, configFile, cv25.Version, srvConfig.Version) + return nil +} diff --git a/cmd/config-versions.go b/cmd/config-versions.go index 543814801..ac9aa1241 100644 --- a/cmd/config-versions.go +++ b/cmd/config-versions.go @@ -654,3 +654,30 @@ type serverConfigV25 struct { // Notification queue configuration. Notify notifier `json:"notify"` } + +// serverConfigV26 is just like version '25', stores additionally +// cache max use value in 'CacheConfig'. +// +// IMPORTANT NOTE: When updating this struct make sure that +// serverConfig.ConfigDiff() is updated as necessary. +type serverConfigV26 struct { + quick.Config `json:"-"` // ignore interfaces + + Version string `json:"version"` + + // S3 API configuration. + Credential auth.Credentials `json:"credential"` + Region string `json:"region"` + Browser BoolFlag `json:"browser"` + Worm BoolFlag `json:"worm"` + Domain string `json:"domain"` + + // Storage class configuration + StorageClass storageClassConfig `json:"storageclass"` + + // Cache configuration + Cache CacheConfig `json:"cache"` + + // Notification queue configuration. + Notify notifier `json:"notify"` +} diff --git a/cmd/disk-cache-config.go b/cmd/disk-cache-config.go index 6ef9a43e6..c7ebbd26f 100644 --- a/cmd/disk-cache-config.go +++ b/cmd/disk-cache-config.go @@ -25,6 +25,7 @@ import ( type CacheConfig struct { Drives []string `json:"drives"` Expiry int `json:"expiry"` + MaxUse int `json:"maxuse"` Exclude []string `json:"exclude"` } diff --git a/cmd/disk-cache.go b/cmd/disk-cache.go index f96016524..6a67ebac7 100644 --- a/cmd/disk-cache.go +++ b/cmd/disk-cache.go @@ -44,7 +44,6 @@ const ( // disk cache needs to have cacheSizeMultiplier * object size space free for a cache entry to be created. cacheSizeMultiplier = 100 cacheTrashDir = "trash" - cacheMaxDiskUsagePct = 80 // in % cacheCleanupInterval = 10 // in minutes ) @@ -839,7 +838,7 @@ func newCache(config CacheConfig) (*diskCache, error) { if err := checkAtimeSupport(dir); err != nil { return nil, errors.New("Atime support required for disk caching") } - cache, err := newCacheFSObjects(dir, config.Expiry, cacheMaxDiskUsagePct) + cache, err := newCacheFSObjects(dir, config.Expiry, config.MaxUse) if err != nil { return nil, err } diff --git a/cmd/disk-cache_test.go b/cmd/disk-cache_test.go index a508349ed..e68a7ed23 100644 --- a/cmd/disk-cache_test.go +++ b/cmd/disk-cache_test.go @@ -28,10 +28,10 @@ import ( ) // Initialize cache FS objects. -func initCacheFSObjects(disk string, t *testing.T) (*cacheFSObjects, error) { +func initCacheFSObjects(disk string, cacheMaxUse int, t *testing.T) (*cacheFSObjects, error) { newTestConfig(globalMinioDefaultRegion) var err error - obj, err := newCacheFSObjects(disk, globalCacheExpiry, 100) + obj, err := newCacheFSObjects(disk, globalCacheExpiry, cacheMaxUse) if err != nil { t.Fatal(err) } @@ -39,10 +39,10 @@ func initCacheFSObjects(disk string, t *testing.T) (*cacheFSObjects, error) { } // inits diskCache struct for nDisks -func initDiskCaches(drives []string, t *testing.T) (*diskCache, error) { +func initDiskCaches(drives []string, cacheMaxUse int, t *testing.T) (*diskCache, error) { var cfs []*cacheFSObjects for _, d := range drives { - obj, err := initCacheFSObjects(d, t) + obj, err := initCacheFSObjects(d, cacheMaxUse, t) if err != nil { return nil, err } @@ -59,7 +59,46 @@ func TestGetCacheFS(t *testing.T) { if err != nil { t.Fatal(err) } - d, err := initDiskCaches(fsDirs, t) + d, err := initDiskCaches(fsDirs, 100, t) + if err != nil { + t.Fatal(err) + } + bucketName := "testbucket" + objectName := "testobject" + ctx := context.Background() + // find cache drive where object would be hashed + index := d.hashIndex(bucketName, objectName) + // turn off drive by setting online status to false + d.cfs[index].online = false + cfs, err := d.getCacheFS(ctx, bucketName, objectName) + if n == 1 && err == errDiskNotFound { + continue + } + if err != nil { + t.Fatal(err) + } + i := -1 + for j, f := range d.cfs { + if f == cfs { + i = j + break + } + } + if i != (index+1)%n { + t.Fatalf("expected next cache location to be picked") + } + } +} + +// test whether a drive being offline causes +// getCacheFS to fetch next online drive +func TestGetCacheFSMaxUse(t *testing.T) { + for n := 1; n < 10; n++ { + fsDirs, err := getRandomDisks(n) + if err != nil { + t.Fatal(err) + } + d, err := initDiskCaches(fsDirs, globalCacheMaxUse, t) if err != nil { t.Fatal(err) } @@ -141,7 +180,7 @@ func TestDiskCache(t *testing.T) { if err != nil { t.Fatal(err) } - d, err := initDiskCaches(fsDirs, t) + d, err := initDiskCaches(fsDirs, 100, t) if err != nil { t.Fatal(err) } @@ -209,6 +248,87 @@ func TestDiskCache(t *testing.T) { } } +// Test diskCache with upper bound on max cache use. +func TestDiskCacheMaxUse(t *testing.T) { + fsDirs, err := getRandomDisks(1) + if err != nil { + t.Fatal(err) + } + d, err := initDiskCaches(fsDirs, globalCacheMaxUse, t) + if err != nil { + t.Fatal(err) + } + cache := d.cfs[0] + ctx := context.Background() + bucketName := "testbucket" + objectName := "testobject" + content := "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + etag := "061208c10af71a30c6dcd6cf5d89f0fe" + contentType := "application/zip" + size := len(content) + + httpMeta := make(map[string]string) + httpMeta["etag"] = etag + httpMeta["content-type"] = contentType + + objInfo := ObjectInfo{} + objInfo.Bucket = bucketName + objInfo.Name = objectName + objInfo.Size = int64(size) + objInfo.ContentType = contentType + objInfo.ETag = etag + objInfo.UserDefined = httpMeta + + byteReader := bytes.NewReader([]byte(content)) + hashReader, err := hash.NewReader(byteReader, int64(size), "", "") + if err != nil { + t.Fatal(err) + } + if !cache.diskAvailable(int64(size)) { + err = cache.Put(ctx, bucketName, objectName, hashReader, httpMeta) + if err != errDiskFull { + t.Fatal("Cache max-use limit violated.") + } + } else { + err = cache.Put(ctx, bucketName, objectName, hashReader, httpMeta) + if err != nil { + t.Fatal(err) + } + cachedObjInfo, err := cache.GetObjectInfo(ctx, bucketName, objectName) + if err != nil { + t.Fatal(err) + } + if !cache.Exists(ctx, bucketName, objectName) { + t.Fatal("Expected object to exist on cache") + } + if cachedObjInfo.ETag != objInfo.ETag { + t.Fatal("Expected ETag to match") + } + if cachedObjInfo.Size != objInfo.Size { + t.Fatal("Size mismatch") + } + if cachedObjInfo.ContentType != objInfo.ContentType { + t.Fatal("Cached content-type does not match") + } + writer := bytes.NewBuffer(nil) + err = cache.Get(ctx, bucketName, objectName, 0, int64(size), writer, "") + if err != nil { + t.Fatal(err) + } + if ccontent := writer.Bytes(); !bytes.Equal([]byte(content), ccontent) { + t.Errorf("wrong cached file content") + } + err = cache.Delete(ctx, bucketName, objectName) + if err != nil { + t.Errorf("object missing from cache") + } + online := cache.IsOnline() + if !online { + t.Errorf("expected cache drive to be online") + } + } +} + func TestIsCacheExcludeDirective(t *testing.T) { testCases := []struct { cacheControlOpt string diff --git a/cmd/gateway/azure/gateway-azure.go b/cmd/gateway/azure/gateway-azure.go index 935232b63..d6f8d5f6d 100644 --- a/cmd/gateway/azure/gateway-azure.go +++ b/cmd/gateway/azure/gateway-azure.go @@ -82,6 +82,7 @@ ENVIRONMENT VARIABLES: MINIO_CACHE_DRIVES: List of mounted drives or directories delimited by ";". MINIO_CACHE_EXCLUDE: List of cache exclusion patterns delimited by ";". MINIO_CACHE_EXPIRY: Cache expiry duration in days. + MINIO_CACHE_MAXUSE: Maximum permitted usage of the cache in percentage (0-100). EXAMPLES: 1. Start minio gateway server for Azure Blob Storage backend. @@ -100,6 +101,7 @@ EXAMPLES: $ export MINIO_CACHE_DRIVES="/mnt/drive1;/mnt/drive2;/mnt/drive3;/mnt/drive4" $ export MINIO_CACHE_EXCLUDE="bucket1/*;*.png" $ export MINIO_CACHE_EXPIRY=40 + $ export MINIO_CACHE_MAXUSE=80 $ {{.HelpName}} ` diff --git a/cmd/gateway/b2/gateway-b2.go b/cmd/gateway/b2/gateway-b2.go index 40b05eef9..9368eec67 100644 --- a/cmd/gateway/b2/gateway-b2.go +++ b/cmd/gateway/b2/gateway-b2.go @@ -72,6 +72,7 @@ ENVIRONMENT VARIABLES: MINIO_CACHE_DRIVES: List of mounted drives or directories delimited by ";". MINIO_CACHE_EXCLUDE: List of cache exclusion patterns delimited by ";". MINIO_CACHE_EXPIRY: Cache expiry duration in days. + MINIO_CACHE_MAXUSE: Maximum permitted usage of the cache in percentage (0-100). EXAMPLES: 1. Start minio gateway server for B2 backend. @@ -85,6 +86,7 @@ EXAMPLES: $ export MINIO_CACHE_DRIVES="/mnt/drive1;/mnt/drive2;/mnt/drive3;/mnt/drive4" $ export MINIO_CACHE_EXCLUDE="bucket1/*;*.png" $ export MINIO_CACHE_EXPIRY=40 + $ export MINIO_CACHE_MAXUSE=80 $ {{.HelpName}} ` minio.RegisterGatewayCommand(cli.Command{ diff --git a/cmd/gateway/gcs/gateway-gcs.go b/cmd/gateway/gcs/gateway-gcs.go index 2be8a0681..ad07b3d85 100644 --- a/cmd/gateway/gcs/gateway-gcs.go +++ b/cmd/gateway/gcs/gateway-gcs.go @@ -118,6 +118,7 @@ ENVIRONMENT VARIABLES: MINIO_CACHE_DRIVES: List of mounted drives or directories delimited by ";". MINIO_CACHE_EXCLUDE: List of cache exclusion patterns delimited by ";". MINIO_CACHE_EXPIRY: Cache expiry duration in days. + MINIO_CACHE_MAXUSE: Maximum permitted usage of the cache in percentage (0-100). GCS credentials file: GOOGLE_APPLICATION_CREDENTIALS: Path to credentials.json @@ -137,6 +138,7 @@ EXAMPLES: $ export MINIO_CACHE_DRIVES="/mnt/drive1;/mnt/drive2;/mnt/drive3;/mnt/drive4" $ export MINIO_CACHE_EXCLUDE="bucket1/*;*.png" $ export MINIO_CACHE_EXPIRY=40 + $ export MINIO_CACHE_MAXUSE=80 $ {{.HelpName}} mygcsprojectid ` diff --git a/cmd/gateway/manta/gateway-manta.go b/cmd/gateway/manta/gateway-manta.go index 3ae9692dd..5b63098a7 100644 --- a/cmd/gateway/manta/gateway-manta.go +++ b/cmd/gateway/manta/gateway-manta.go @@ -78,6 +78,7 @@ ENVIRONMENT VARIABLES: MINIO_CACHE_DRIVES: List of mounted drives or directories delimited by ";". MINIO_CACHE_EXCLUDE: List of cache exclusion patterns delimited by ";". MINIO_CACHE_EXPIRY: Cache expiry duration in days. + MINIO_CACHE_MAXUSE: Maximum permitted usage of the cache in percentage (0-100). EXAMPLES: 1. Start minio gateway server for Manta Object Storage backend. @@ -102,6 +103,7 @@ EXAMPLES: $ export MINIO_CACHE_DRIVES="/mnt/drive1;/mnt/drive2;/mnt/drive3;/mnt/drive4" $ export MINIO_CACHE_EXCLUDE="bucket1/*;*.png" $ export MINIO_CACHE_EXPIRY=40 + $ export MINIO_CACHE_MAXUSE=80 $ {{.HelpName}} ` diff --git a/cmd/gateway/nas/gateway-nas.go b/cmd/gateway/nas/gateway-nas.go index 15131201a..7c1fea82b 100644 --- a/cmd/gateway/nas/gateway-nas.go +++ b/cmd/gateway/nas/gateway-nas.go @@ -57,6 +57,7 @@ ENVIRONMENT VARIABLES: MINIO_CACHE_DRIVES: List of mounted drives or directories delimited by ";". MINIO_CACHE_EXCLUDE: List of cache exclusion patterns delimited by ";". MINIO_CACHE_EXPIRY: Cache expiry duration in days. + MINIO_CACHE_MAXUSE: Maximum permitted usage of the cache in percentage (0-100). EXAMPLES: 1. Start minio gateway server for NAS backend. @@ -70,6 +71,7 @@ EXAMPLES: $ export MINIO_CACHE_DRIVES="/mnt/drive1;/mnt/drive2;/mnt/drive3;/mnt/drive4" $ export MINIO_CACHE_EXCLUDE="bucket1/*;*.png" $ export MINIO_CACHE_EXPIRY=40 + $ export MINIO_CACHE_MAXUSE=80 $ {{.HelpName}} /shared/nasvol ` diff --git a/cmd/gateway/oss/gateway-oss.go b/cmd/gateway/oss/gateway-oss.go index 9b29fd3db..34c7e4571 100644 --- a/cmd/gateway/oss/gateway-oss.go +++ b/cmd/gateway/oss/gateway-oss.go @@ -74,6 +74,7 @@ ENVIRONMENT VARIABLES: MINIO_CACHE_DRIVES: List of mounted drives or directories delimited by ";". MINIO_CACHE_EXCLUDE: List of cache exclusion patterns delimited by ";". MINIO_CACHE_EXPIRY: Cache expiry duration in days. + MINIO_CACHE_MAXUSE: Maximum permitted usage of the cache in percentage (0-100). EXAMPLES: 1. Start minio gateway server for Aliyun OSS backend. @@ -92,6 +93,7 @@ EXAMPLES: $ export MINIO_CACHE_DRIVES="/mnt/drive1;/mnt/drive2;/mnt/drive3;/mnt/drive4" $ export MINIO_CACHE_EXCLUDE="bucket1/*;*.png" $ export MINIO_CACHE_EXPIRY=40 + $ export MINIO_CACHE_MAXUSE=80 $ {{.HelpName}} ` diff --git a/cmd/gateway/s3/gateway-s3.go b/cmd/gateway/s3/gateway-s3.go index 4a438a509..02dfba03d 100644 --- a/cmd/gateway/s3/gateway-s3.go +++ b/cmd/gateway/s3/gateway-s3.go @@ -65,6 +65,7 @@ ENVIRONMENT VARIABLES: MINIO_CACHE_DRIVES: List of mounted drives or directories delimited by ";". MINIO_CACHE_EXCLUDE: List of cache exclusion patterns delimited by ";". MINIO_CACHE_EXPIRY: Cache expiry duration in days. + MINIO_CACHE_MAXUSE: Maximum permitted usage of the cache in percentage (0-100). EXAMPLES: 1. Start minio gateway server for AWS S3 backend. @@ -83,6 +84,7 @@ EXAMPLES: $ export MINIO_CACHE_DRIVES="/mnt/drive1;/mnt/drive2;/mnt/drive3;/mnt/drive4" $ export MINIO_CACHE_EXCLUDE="bucket1/*;*.png" $ export MINIO_CACHE_EXPIRY=40 + $ export MINIO_CACHE_MAXUSE=80 $ {{.HelpName}} ` diff --git a/cmd/gateway/sia/gateway-sia.go b/cmd/gateway/sia/gateway-sia.go index f10d19673..5ce0a067c 100644 --- a/cmd/gateway/sia/gateway-sia.go +++ b/cmd/gateway/sia/gateway-sia.go @@ -79,6 +79,7 @@ ENVIRONMENT VARIABLES: (Default values in parenthesis) MINIO_CACHE_DRIVES: List of mounted drives or directories delimited by ";". MINIO_CACHE_EXCLUDE: List of cache exclusion patterns delimited by ";". MINIO_CACHE_EXPIRY: Cache expiry duration in days. + MINIO_CACHE_MAXUSE: Maximum permitted usage of the cache in percentage (0-100). SIA_TEMP_DIR: The name of the local Sia temporary storage directory. (.sia_temp) SIA_API_PASSWORD: API password for Sia daemon. (default is empty) @@ -91,6 +92,7 @@ EXAMPLES: $ export MINIO_CACHE_DRIVES="/mnt/drive1;/mnt/drive2;/mnt/drive3;/mnt/drive4" $ export MINIO_CACHE_EXCLUDE="bucket1/*;*.png" $ export MINIO_CACHE_EXPIRY=40 + $ export MINIO_CACHE_MAXUSE=80 $ {{.HelpName}} ` diff --git a/cmd/globals.go b/cmd/globals.go index cd6304e13..ee8886009 100644 --- a/cmd/globals.go +++ b/cmd/globals.go @@ -194,6 +194,8 @@ var ( // Disk cache expiry globalCacheExpiry = 90 + // Max allowed disk cache percentage + globalCacheMaxUse = 80 // RPC V1 - Initial version // RPC V2 - format.json XL version changed to 2 diff --git a/cmd/server-main.go b/cmd/server-main.go index b9147096d..47cb6e05b 100644 --- a/cmd/server-main.go +++ b/cmd/server-main.go @@ -82,6 +82,7 @@ ENVIRONMENT VARIABLES: MINIO_CACHE_DRIVES: List of mounted drives or directories delimited by ";". MINIO_CACHE_EXCLUDE: List of cache exclusion patterns delimited by ";". MINIO_CACHE_EXPIRY: Cache expiry duration in days. + MINIO_CACHE_MAXUSE: Maximum permitted usage of the cache in percentage (0-100). DOMAIN: MINIO_DOMAIN: To enable virtual-host-style requests, set this value to Minio host domain name. @@ -118,6 +119,7 @@ EXAMPLES: $ export MINIO_CACHE_DRIVES="/mnt/drive1;/mnt/drive2;/mnt/drive3;/mnt/drive4" $ export MINIO_CACHE_EXCLUDE="bucket1/*;*.png" $ export MINIO_CACHE_EXPIRY=40 + $ export MINIO_CACHE_MAXUSE=80 $ {{.HelpName}} /home/shared `, } diff --git a/cmd/ui-errors.go b/cmd/ui-errors.go index ceddf65c5..005243cbd 100644 --- a/cmd/ui-errors.go +++ b/cmd/ui-errors.go @@ -53,6 +53,12 @@ var ( "MINIO_CACHE_EXPIRY: Valid cache expiry duration is in days.", ) + uiErrInvalidCacheMaxUse = newUIErrFn( + "Invalid cache max-use value", + "Please check the passed value", + "MINIO_CACHE_MAXUSE: Valid cache max-use value between 0-100.", + ) + uiErrInvalidCredentials = newUIErrFn( "Invalid credentials", "Please provide correct credentials", diff --git a/docs/disk-caching/DESIGN.md b/docs/disk-caching/DESIGN.md index 706cc56df..2e7b9f3ff 100644 --- a/docs/disk-caching/DESIGN.md +++ b/docs/disk-caching/DESIGN.md @@ -12,6 +12,7 @@ minio server -h MINIO_CACHE_DRIVES: List of mounted cache drives or directories delimited by ";" MINIO_CACHE_EXCLUDE: List of cache exclusion patterns delimited by ";" MINIO_CACHE_EXPIRY: Cache expiry duration in days + MINIO_CACHE_MAXUSE: Maximum permitted usage of the cache in percentage (0-100). ... ... @@ -21,6 +22,7 @@ minio server -h $ export MINIO_CACHE_DRIVES="/mnt/drive1;/mnt/drive2;/mnt/drive3" $ export MINIO_CACHE_EXCLUDE="mybucket/*;*.pdf" $ export MINIO_CACHE_EXPIRY=40 + $ export MINIO_CACHE_MAXUSE=80 $ minio server /home/shared ``` diff --git a/docs/disk-caching/README.md b/docs/disk-caching/README.md index ae46ab38f..778105734 100644 --- a/docs/disk-caching/README.md +++ b/docs/disk-caching/README.md @@ -27,6 +27,7 @@ The cache settings may also be set through environment variables. When set, envi export MINIO_CACHE_DRIVES="/mnt/drive1;/mnt/drive2;/mnt/drive3" export MINIO_CACHE_EXPIRY=90 export MINIO_CACHE_EXCLUDE="*.pdf;mybucket/*" +export MINIO_CACHE_MAXUSE=80 minio server /export{1...24} ```