[lxc-devel] [lxd/master] Handle out-of-space errors gracefully

freeekanayaka on Github lxc-bot at linuxcontainers.org
Mon Dec 9 12:46:25 UTC 2019


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 301 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20191209/feedf468/attachment.bin>
-------------- next part --------------
From 76e00c876d9916b8551e815a3c7e03f7105a502c Mon Sep 17 00:00:00 2001
From: Free Ekanayaka <free.ekanayaka at canonical.com>
Date: Mon, 9 Dec 2019 08:53:23 +0000
Subject: [PATCH 1/3] Rename database_update.sh to database.sh

Signed-off-by: Free Ekanayaka <free.ekanayaka at canonical.com>
---
 test/suites/{database_update.sh => database.sh} | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename test/suites/{database_update.sh => database.sh} (100%)

diff --git a/test/suites/database_update.sh b/test/suites/database.sh
similarity index 100%
rename from test/suites/database_update.sh
rename to test/suites/database.sh

From d883f2e3e4f0ca98265553dd78e49dbbadaeebd9 Mon Sep 17 00:00:00 2001
From: Free Ekanayaka <free.ekanayaka at canonical.com>
Date: Mon, 9 Dec 2019 11:38:44 +0000
Subject: [PATCH 2/3] Don't retry in case of generic I/O errors

Leadership-related errors are propagated by go-dqlite using driver.ErrBadConn,
so this legacy check can be removed, since it would actually make us retry in
case of non-retriable errors such as out-of-disk.

Signed-off-by: Free Ekanayaka <free.ekanayaka at canonical.com>
---
 lxd/db/query/retry.go | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/lxd/db/query/retry.go b/lxd/db/query/retry.go
index 1b288377a4..240f75e1ac 100644
--- a/lxd/db/query/retry.go
+++ b/lxd/db/query/retry.go
@@ -51,10 +51,5 @@ func IsRetriableError(err error) bool {
 		return true
 	}
 
-	// Despite the description this is usually a lost leadership error.
-	if strings.Contains(err.Error(), "disk I/O error") {
-		return true
-	}
-
 	return false
 }

From 2f4f4712299ab9be3722afebfaa2479b37a3121b Mon Sep 17 00:00:00 2001
From: Free Ekanayaka <free.ekanayaka at canonical.com>
Date: Mon, 9 Dec 2019 11:40:49 +0000
Subject: [PATCH 3/3] Add test_database_no_disk_space

Signed-off-by: Free Ekanayaka <free.ekanayaka at canonical.com>
---
 test/main.sh            |  1 +
 test/suites/database.sh | 47 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 48 insertions(+)

diff --git a/test/main.sh b/test/main.sh
index eca30ee99b..b2676b9f56 100755
--- a/test/main.sh
+++ b/test/main.sh
@@ -158,6 +158,7 @@ run_test test_check_deps "checking dependencies"
 run_test test_static_analysis "static analysis"
 run_test test_database_update "database schema updates"
 run_test test_database_restore "database restore"
+run_test test_database_no_disk_space "database out of disk space"
 run_test test_sql "lxd sql"
 run_test test_basic_usage "basic usage"
 run_test test_remote_url "remote url handling"
diff --git a/test/suites/database.sh b/test/suites/database.sh
index 3a93f23f74..fd62774b43 100644
--- a/test/suites/database.sh
+++ b/test/suites/database.sh
@@ -82,3 +82,50 @@ EOF
 
   kill_lxd "${LXD_RESTORE_DIR}"
 }
+
+test_database_no_disk_space(){
+  # shellcheck disable=2039
+  local LXD_DIR
+
+  LXD_NOSPACE_DIR=$(mktemp -d -p "${TEST_DIR}" XXX)
+
+  # Mount a tmpfs with limited space in the global database directory and create
+  # a very big file in it, which will eventually cause database transactions to
+  # fail.
+  GLOBAL_DB_DIR="${LXD_NOSPACE_DIR}/database/global"
+  BIG_FILE="${GLOBAL_DB_DIR}/bigfile"
+  mkdir -p "${GLOBAL_DB_DIR}"
+  mount -t tmpfs -o size=67108864 tmpfs "${GLOBAL_DB_DIR}"
+  dd bs=1024 count=49152 if=/dev/zero of="${BIG_FILE}"
+
+  spawn_lxd "${LXD_NOSPACE_DIR}" true
+
+  (
+    set -e
+    # shellcheck disable=SC2034,SC2030
+    LXD_DIR="${LXD_NOSPACE_DIR}"
+
+    ensure_import_testimage
+    lxc init testimage c
+
+    # Set a custom user property with a big value, so we eventually eat up all
+    # available disk space in the database directory.
+    DATA="$(head -c 65536 < /dev/zero | tr '\0' '\141')"
+    for i in $(seq 40); do
+        if ! lxc config set c "user.prop${i}" "${DATA}"; then
+            break
+        fi
+    done
+
+    # Commands that involve writing to the database keep failing.
+    ! lxc config set c "user.propX" "${DATA}" || false
+    ! lxc config set c "user.propY" "${DATA}" || false
+
+    # Removing the big file makes the database happy again.
+    rm "${BIG_FILE}"
+    lxc config set c "user.propZ" "${DATA}"
+  )
+
+  shutdown_lxd "${LXD_NOSPACE_DIR}"
+  umount "${GLOBAL_DB_DIR}"
+}


More information about the lxc-devel mailing list