From 8d4cc064b3cb48948dc37e0c057d04b77c1ec27d Mon Sep 17 00:00:00 2001
From: Shuo Wu <shuo.wu@suse.com>
Date: Thu, 6 Mar 2025 19:04:33 -0800
Subject: [PATCH] fix: engine unmap uses write lock

Otherwise, there will be a race between unmap and write operations.

Longhorn 6406

Signed-off-by: Shuo Wu <shuo.wu@suse.com>
---
 pkg/controller/control.go | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/pkg/controller/control.go b/pkg/controller/control.go
index 9ef88ab86..0810145f2 100644
--- a/pkg/controller/control.go
+++ b/pkg/controller/control.go
@@ -1118,14 +1118,14 @@ func (c *Controller) ReadAt(b []byte, off int64) (int, error) {
 func (c *Controller) UnmapAt(length uint32, off int64) (int, error) {
 	// TODO: Need to fail unmap requests
 	//  if the volume is purging snapshots or creating backups.
-	c.RLock()
+	c.Lock()
 
 	if off < 0 || off+int64(length) > c.size {
 		// This is a legitimate error (which is handled by tgt/liblonghorn at a higher level). Since tgt/liblonghorn
 		// does not actually print the error, print it here.
 		err := fmt.Errorf("EOF: unmap of %v bytes at offset %v is beyond volume size %v", length, off, c.size)
 		logrus.WithError(err).Error("Failed to unmap")
-		c.RUnlock()
+		c.Unlock()
 		return 0, err
 	}
 	if c.hasWOReplica() {
@@ -1134,7 +1134,7 @@ func (c *Controller) UnmapAt(length uint32, off int64) (int, error) {
 		// will remain paused for the entire duration of the rebuild.
 		err := fmt.Errorf("cannot unmap %v bytes at offset %v while rebuilding is in progress", length, off)
 		logrus.WithError(err).Warn("Failed to unmap")
-		c.RUnlock()
+		c.Unlock()
 		return 0, nil
 	}
 	if c.isExpanding {
@@ -1143,13 +1143,13 @@ func (c *Controller) UnmapAt(length uint32, off int64) (int, error) {
 		// trimmed, so it can try again.
 		err := fmt.Errorf("cannot unmap %v bytes at offset %v while expansion in is progress", length, off)
 		logrus.WithError(err).Error("Failed to unmap")
-		c.RUnlock()
+		c.Unlock()
 		return 0, err
 	}
 
 	// startTime := time.Now()
 	n, err := c.backend.UnmapAt(length, off)
-	c.RUnlock()
+	c.Unlock()
 	if err != nil {
 		return n, c.handleError(err)
 	}