From fa231b8c56eb688a49f7342b6e25804bbb2768e6 Mon Sep 17 00:00:00 2001
From: Pavel Karpy <carpawell@nspcc.ru>
Date: Tue, 15 Nov 2022 15:33:48 +0300
Subject: [PATCH] [#2057] blobstor: Block operations on a mode change

Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
---
 pkg/local_object_storage/blobstor/delete.go    | 3 +++
 pkg/local_object_storage/blobstor/exists.go    | 3 +++
 pkg/local_object_storage/blobstor/get.go       | 3 +++
 pkg/local_object_storage/blobstor/get_range.go | 3 +++
 pkg/local_object_storage/blobstor/info.go      | 3 +++
 pkg/local_object_storage/blobstor/iterate.go   | 3 +++
 pkg/local_object_storage/blobstor/put.go       | 3 +++
 7 files changed, 21 insertions(+)

diff --git a/pkg/local_object_storage/blobstor/delete.go b/pkg/local_object_storage/blobstor/delete.go
index f47eeb1ae..5b8ecaec8 100644
--- a/pkg/local_object_storage/blobstor/delete.go
+++ b/pkg/local_object_storage/blobstor/delete.go
@@ -8,6 +8,9 @@ import (
 )
 
 func (b *BlobStor) Delete(prm common.DeletePrm) (common.DeleteRes, error) {
+	b.modeMtx.RLock()
+	defer b.modeMtx.RUnlock()
+
 	if prm.StorageID == nil {
 		for i := range b.storage {
 			res, err := b.storage[i].Storage.Delete(prm)
diff --git a/pkg/local_object_storage/blobstor/exists.go b/pkg/local_object_storage/blobstor/exists.go
index ea28a944d..0868a9454 100644
--- a/pkg/local_object_storage/blobstor/exists.go
+++ b/pkg/local_object_storage/blobstor/exists.go
@@ -10,6 +10,9 @@ import (
 // Returns any error encountered that did not allow
 // to completely check object existence.
 func (b *BlobStor) Exists(prm common.ExistsPrm) (common.ExistsRes, error) {
+	b.modeMtx.RLock()
+	defer b.modeMtx.RUnlock()
+
 	// If there was an error during existence check below,
 	// it will be returned unless object was found in blobovnicza.
 	// Otherwise, it is logged and the latest error is returned.
diff --git a/pkg/local_object_storage/blobstor/get.go b/pkg/local_object_storage/blobstor/get.go
index 692038de1..72b51a246 100644
--- a/pkg/local_object_storage/blobstor/get.go
+++ b/pkg/local_object_storage/blobstor/get.go
@@ -12,6 +12,9 @@ import (
 // If the descriptor is present, only one sub-storage is tried,
 // Otherwise, each sub-storage is tried in order.
 func (b *BlobStor) Get(prm common.GetPrm) (common.GetRes, error) {
+	b.modeMtx.RLock()
+	defer b.modeMtx.RUnlock()
+
 	if prm.StorageID == nil {
 		for i := range b.storage {
 			res, err := b.storage[i].Storage.Get(prm)
diff --git a/pkg/local_object_storage/blobstor/get_range.go b/pkg/local_object_storage/blobstor/get_range.go
index 1d37cf862..ede6efec8 100644
--- a/pkg/local_object_storage/blobstor/get_range.go
+++ b/pkg/local_object_storage/blobstor/get_range.go
@@ -12,6 +12,9 @@ import (
 // If the descriptor is present, only one sub-storage is tried,
 // Otherwise, each sub-storage is tried in order.
 func (b *BlobStor) GetRange(prm common.GetRangePrm) (common.GetRangeRes, error) {
+	b.modeMtx.RLock()
+	defer b.modeMtx.RUnlock()
+
 	if prm.StorageID == nil {
 		for i := range b.storage {
 			res, err := b.storage[i].Storage.GetRange(prm)
diff --git a/pkg/local_object_storage/blobstor/info.go b/pkg/local_object_storage/blobstor/info.go
index e3e790ebc..2fd62af81 100644
--- a/pkg/local_object_storage/blobstor/info.go
+++ b/pkg/local_object_storage/blobstor/info.go
@@ -2,6 +2,9 @@ package blobstor
 
 // DumpInfo returns information about blob stor.
 func (b *BlobStor) DumpInfo() Info {
+	b.modeMtx.RLock()
+	defer b.modeMtx.RUnlock()
+
 	sub := make([]SubStorageInfo, len(b.storage))
 	for i := range b.storage {
 		sub[i].Path = b.storage[i].Storage.Path()
diff --git a/pkg/local_object_storage/blobstor/iterate.go b/pkg/local_object_storage/blobstor/iterate.go
index 81cd31d0b..b5d14e77c 100644
--- a/pkg/local_object_storage/blobstor/iterate.go
+++ b/pkg/local_object_storage/blobstor/iterate.go
@@ -16,6 +16,9 @@ import (
 //
 // If handler returns an error, method wraps and returns it immediately.
 func (b *BlobStor) Iterate(prm common.IteratePrm) (common.IterateRes, error) {
+	b.modeMtx.RLock()
+	defer b.modeMtx.RUnlock()
+
 	for i := range b.storage {
 		_, err := b.storage[i].Storage.Iterate(prm)
 		if err != nil && !prm.IgnoreErrors {
diff --git a/pkg/local_object_storage/blobstor/put.go b/pkg/local_object_storage/blobstor/put.go
index 4ace6e1b1..0bf244d3b 100644
--- a/pkg/local_object_storage/blobstor/put.go
+++ b/pkg/local_object_storage/blobstor/put.go
@@ -22,6 +22,9 @@ var ErrNoPlaceFound = logicerr.New("couldn't find a place to store an object")
 // Returns any error encountered that
 // did not allow to completely save the object.
 func (b *BlobStor) Put(prm common.PutPrm) (common.PutRes, error) {
+	b.modeMtx.RLock()
+	defer b.modeMtx.RUnlock()
+
 	if prm.Object != nil {
 		prm.Address = object.AddressOf(prm.Object)
 	}