[lxc-devel] [lxd/master] lxd/daemon: Properly cache the storage information
stgraber on Github
lxc-bot at linuxcontainers.org
Mon Dec 18 06:57:06 UTC 2017
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 502 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20171218/e6167720/attachment.bin>
-------------- next part --------------
From 0d6db8981f2a4bba2b57f6aec419276b09fe454c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Mon, 18 Dec 2017 01:55:32 -0500
Subject: [PATCH] lxd/daemon: Properly cache the storage information
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This moves all the data we need into the cache so that we don't cause
any filesystem related calls when we received "GET /1.0".
Closes #4025
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
lxd/api_1.0.go | 13 +++----------
lxd/storage.go | 42 ++++++++++++++++++++++++++++--------------
lxd/storage_pools_utils.go | 23 +++--------------------
3 files changed, 34 insertions(+), 44 deletions(-)
diff --git a/lxd/api_1.0.go b/lxd/api_1.0.go
index ab48696c8..4c18d2459 100644
--- a/lxd/api_1.0.go
+++ b/lxd/api_1.0.go
@@ -123,13 +123,7 @@ func api10Get(d *Daemon, r *http.Request) Response {
ServerVersion: version.Version}
drivers := readStoragePoolDriversCache()
- for _, driver := range drivers {
- // Initialize a core storage interface for the given driver.
- sCore, err := storageCoreInit(driver)
- if err != nil {
- continue
- }
-
+ for driver, version := range drivers {
if env.Storage != "" {
env.Storage = env.Storage + " | " + driver
} else {
@@ -137,11 +131,10 @@ func api10Get(d *Daemon, r *http.Request) Response {
}
// Get the version of the storage drivers in use.
- sVersion := sCore.GetStorageTypeVersion()
if env.StorageVersion != "" {
- env.StorageVersion = env.StorageVersion + " | " + sVersion
+ env.StorageVersion = env.StorageVersion + " | " + version
} else {
- env.StorageVersion = sVersion
+ env.StorageVersion = version
}
}
diff --git a/lxd/storage.go b/lxd/storage.go
index aaf581c0a..4a651d70e 100644
--- a/lxd/storage.go
+++ b/lxd/storage.go
@@ -63,17 +63,16 @@ func getCustomUmountLockID(poolName string, volumeName string) string {
// Simply cache used to storage the activated drivers on this LXD instance. This
// allows us to avoid querying the database everytime and API call is made.
-var storagePoolDriversCacheInitialized bool
var storagePoolDriversCacheVal atomic.Value
var storagePoolDriversCacheLock sync.Mutex
-func readStoragePoolDriversCache() []string {
+func readStoragePoolDriversCache() map[string]string {
drivers := storagePoolDriversCacheVal.Load()
if drivers == nil {
- return []string{}
+ return map[string]string{}
}
- return drivers.([]string)
+ return drivers.(map[string]string)
}
// storageType defines the type of a storage
@@ -854,6 +853,12 @@ func SetupStorageDriver(s *state.State, forceCheck bool) error {
}
}
+ // Update the storage drivers cache in api_1.0.go.
+ storagePoolDriversCacheUpdate(s.DB)
+ return nil
+}
+
+func storagePoolDriversCacheUpdate(dbNode *db.Node) {
// Get a list of all storage drivers currently in use
// on this LXD instance. Only do this when we do not already have done
// this once to avoid unnecessarily querying the db. All subsequent
@@ -863,18 +868,27 @@ func SetupStorageDriver(s *state.State, forceCheck bool) error {
// copy-on-write semantics without locking in the read case seems
// appropriate. (Should be cheaper then querying the db all the time,
// especially if we keep adding more storage drivers.)
- if !storagePoolDriversCacheInitialized {
- tmp, err := s.DB.StoragePoolsGetDrivers()
- if err != nil && err != db.NoSuchObjectError {
- return nil
- }
- storagePoolDriversCacheLock.Lock()
- storagePoolDriversCacheVal.Store(tmp)
- storagePoolDriversCacheLock.Unlock()
+ drivers, err := dbNode.StoragePoolsGetDrivers()
+ if err != nil && err != db.NoSuchObjectError {
+ return
+ }
+
+ data := map[string]string{}
+ for _, driver := range drivers {
+ // Initialize a core storage interface for the given driver.
+ sCore, err := storageCoreInit(driver)
+ if err != nil {
+ continue
+ }
- storagePoolDriversCacheInitialized = true
+ // Grab the version
+ data[driver] = sCore.GetStorageTypeVersion()
}
- return nil
+ storagePoolDriversCacheLock.Lock()
+ storagePoolDriversCacheVal.Store(data)
+ storagePoolDriversCacheLock.Unlock()
+
+ return
}
diff --git a/lxd/storage_pools_utils.go b/lxd/storage_pools_utils.go
index 1059d3765..6df16c870 100644
--- a/lxd/storage_pools_utils.go
+++ b/lxd/storage_pools_utils.go
@@ -259,13 +259,7 @@ func dbStoragePoolCreateAndUpdateCache(db *db.Node, poolName string, poolDescrip
}
// Update the storage drivers cache in api_1.0.go.
- storagePoolDriversCacheLock.Lock()
- drivers := readStoragePoolDriversCache()
- if !shared.StringInSlice(poolDriver, drivers) {
- drivers = append(drivers, poolDriver)
- }
- storagePoolDriversCacheVal.Store(drivers)
- storagePoolDriversCacheLock.Unlock()
+ storagePoolDriversCacheUpdate(db)
return id, nil
}
@@ -273,24 +267,13 @@ func dbStoragePoolCreateAndUpdateCache(db *db.Node, poolName string, poolDescrip
// Helper around the low-level DB API, which also updates the driver names
// cache.
func dbStoragePoolDeleteAndUpdateCache(db *db.Node, poolName string) error {
- pool, err := db.StoragePoolDelete(poolName)
+ _, err := db.StoragePoolDelete(poolName)
if err != nil {
return err
}
// Update the storage drivers cache in api_1.0.go.
- storagePoolDriversCacheLock.Lock()
- drivers := readStoragePoolDriversCache()
- for i := 0; i < len(drivers); i++ {
- if drivers[i] == pool.Driver {
- drivers[i] = drivers[len(drivers)-1]
- drivers[len(drivers)-1] = ""
- drivers = drivers[:len(drivers)-1]
- break
- }
- }
- storagePoolDriversCacheVal.Store(drivers)
- storagePoolDriversCacheLock.Unlock()
+ storagePoolDriversCacheUpdate(db)
return err
}
More information about the lxc-devel
mailing list