From df5dbaf49b69c3862eb8b7af9b6e29e84d63e4fc Mon Sep 17 00:00:00 2001
From: Nick Craig-Wood <nick@craig-wood.com>
Date: Fri, 3 Jul 2020 17:16:28 +0100
Subject: [PATCH] vfs: writeback: add Rename call for renaming items in the
 writeback queue

---
 vfs/vfscache/writeback/writeback.go      | 22 +++++++++++++++++++
 vfs/vfscache/writeback/writeback_test.go | 28 ++++++++++++++----------
 2 files changed, 39 insertions(+), 11 deletions(-)

diff --git a/vfs/vfscache/writeback/writeback.go b/vfs/vfscache/writeback/writeback.go
index dd5a1fd06..b4e4d9e85 100644
--- a/vfs/vfscache/writeback/writeback.go
+++ b/vfs/vfscache/writeback/writeback.go
@@ -299,6 +299,28 @@ func (wb *WriteBack) Remove(id Handle) (found bool) {
 	return found
 }
 
+// Rename should be called when a file might be uploading and it gains
+// a new name. This will cancel the upload and put it back in the
+// queue.
+func (wb *WriteBack) Rename(id Handle, name string) {
+	wb.mu.Lock()
+	defer wb.mu.Unlock()
+
+	wbItem, ok := wb.lookup[id]
+	if !ok {
+		return
+	}
+	if wbItem.uploading {
+		// We are uploading already so cancel the upload
+		wb._cancelUpload(wbItem)
+	}
+	wbItem.name = name
+	// Kick the timer on
+	wb.items._update(wbItem, wb._newExpiry())
+
+	wb._resetTimer()
+}
+
 // upload the item - called as a goroutine
 //
 // uploading will have been incremented here already
diff --git a/vfs/vfscache/writeback/writeback_test.go b/vfs/vfscache/writeback/writeback_test.go
index 135dd796c..7f23d8559 100644
--- a/vfs/vfscache/writeback/writeback_test.go
+++ b/vfs/vfscache/writeback/writeback_test.go
@@ -540,12 +540,12 @@ func TestWriteBackMaxQueue(t *testing.T) {
 	assert.Equal(t, inProgress, 0)
 }
 
-func TestWriteBackRemove(t *testing.T) {
+func TestWriteBackRename(t *testing.T) {
 	wb, cancel := newTestWriteBack(t)
 	defer cancel()
 
 	// cancel when not in writeback
-	assert.False(t, wb.Remove(1))
+	wb.Rename(1, "nonExistent")
 
 	// add item
 	pi1 := newPutItem(t)
@@ -553,28 +553,34 @@ func TestWriteBackRemove(t *testing.T) {
 	wbItem := wb.lookup[id]
 	checkOnHeap(t, wb, wbItem)
 	checkInLookup(t, wb, wbItem)
+	assert.Equal(t, wbItem.name, "one")
 
-	// cancel when not uploading
-	assert.True(t, wb.Remove(id))
-	checkNotOnHeap(t, wb, wbItem)
-	checkNotInLookup(t, wb, wbItem)
+	// rename when not uploading
+	wb.Rename(id, "two")
+	checkOnHeap(t, wb, wbItem)
+	checkInLookup(t, wb, wbItem)
 	assert.False(t, pi1.cancelled)
+	assert.Equal(t, wbItem.name, "two")
 
 	// add item
 	pi2 := newPutItem(t)
-	id = wb.Add(id, "one", true, pi2.put)
+	id = wb.Add(id, "two", true, pi2.put)
 	wbItem = wb.lookup[id]
 	checkOnHeap(t, wb, wbItem)
 	checkInLookup(t, wb, wbItem)
+	assert.Equal(t, wbItem.name, "two")
 
 	// wait for upload to start
 	<-pi2.started
-
-	// cancel when uploading
-	assert.True(t, wb.Remove(id))
 	checkNotOnHeap(t, wb, wbItem)
-	checkNotInLookup(t, wb, wbItem)
+	checkInLookup(t, wb, wbItem)
+
+	// rename when uploading - goes back on heap
+	wb.Rename(id, "three")
+	checkOnHeap(t, wb, wbItem)
+	checkInLookup(t, wb, wbItem)
 	assert.True(t, pi2.cancelled)
+	assert.Equal(t, wbItem.name, "three")
 }
 
 func TestWriteBackCancelUpload(t *testing.T) {