From af02c3b2a7780e199139f0047bc90e917302af12 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Mon, 25 Sep 2023 11:13:40 +0100 Subject: [PATCH] b2: fix locking window when getting mutipart upload URL Before this change, the lock was held while the upload URL was being fetched from the server. This meant that any other threads were blocked from getting upload URLs unecessarily. It also increased the potential for deadlock. --- backend/b2/upload.go | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/backend/b2/upload.go b/backend/b2/upload.go index 206c7abe4..9fe58295c 100644 --- a/backend/b2/upload.go +++ b/backend/b2/upload.go @@ -169,24 +169,26 @@ func (f *Fs) newLargeUpload(ctx context.Context, o *Object, in io.Reader, src fs // This should be returned with returnUploadURL when finished func (up *largeUpload) getUploadURL(ctx context.Context) (upload *api.GetUploadPartURLResponse, err error) { up.uploadMu.Lock() - defer up.uploadMu.Unlock() - if len(up.uploads) == 0 { - opts := rest.Opts{ - Method: "POST", - Path: "/b2_get_upload_part_url", - } - var request = api.GetUploadPartURLRequest{ - ID: up.id, - } - err := up.f.pacer.Call(func() (bool, error) { - resp, err := up.f.srv.CallJSON(ctx, &opts, &request, &upload) - return up.f.shouldRetry(ctx, resp, err) - }) - if err != nil { - return nil, fmt.Errorf("failed to get upload URL: %w", err) - } - } else { + if len(up.uploads) > 0 { upload, up.uploads = up.uploads[0], up.uploads[1:] + up.uploadMu.Unlock() + return upload, nil + } + up.uploadMu.Unlock() + + opts := rest.Opts{ + Method: "POST", + Path: "/b2_get_upload_part_url", + } + var request = api.GetUploadPartURLRequest{ + ID: up.id, + } + err = up.f.pacer.Call(func() (bool, error) { + resp, err := up.f.srv.CallJSON(ctx, &opts, &request, &upload) + return up.f.shouldRetry(ctx, resp, err) + }) + if err != nil { + return nil, fmt.Errorf("failed to get upload URL: %w", err) } return upload, nil }