Skip to content

Conversation

@jvsalo
Copy link
Contributor

@jvsalo jvsalo commented May 24, 2020

This patch makes MemcacheLockingProvider handle multiple releases of the same shared lock gracefully.

Previously, the lock will get negative values that cause problems as seen in #21073

During PUT requests,

$node->releaseLock(ILockingProvider::LOCK_SHARED);
releases a lock once, and
$node->releaseLock(ILockingProvider::LOCK_SHARED);
releases the same lock again (see the issue); LockPlugin never acquired the lock.

MemcacheLockingProvider already had some logic to handle multiple releases (negative going lock values), but it was subject to a race condition.

@jvsalo jvsalo force-pushed the shared-lock-multi-release branch 3 times, most recently from b2f4e92 to cf05823 Compare May 24, 2020 00:51
@kesselb kesselb requested review from icewind1991 and rullzer May 24, 2020 13:48
@kesselb kesselb added 3. to review Waiting for reviews bug labels May 24, 2020
@kesselb kesselb linked an issue May 24, 2020 that may be closed by this pull request
@kesselb
Copy link
Contributor

kesselb commented May 24, 2020

Thanks for your patch 🎉

If the LockPlugin already obtains the lock why not remove the shared lock in createFile? 🤔

@jvsalo
Copy link
Contributor Author

jvsalo commented May 24, 2020

If the LockPlugin already obtains the lock why not remove the shared lock in createFile?

Thanks for the quick response! In my debug session, I found that LockPlugin::getLock() (beforeMethod handler) doesn't get a Node from getNodeForPath(), and as such cannot call acquireLock(). However, upon exiting the request (afterMethod handler), LockPlugin::releaseLock() does get the Node and will indeed call releaseLock().

Since it's a PUT request for a new file, perhaps it makes some sense that initially the Node is not found? But I'm very new to the codebase so I only have little idea what I'm talking about, but this I discovered by instrumenting the code yesterday.

@kesselb
Copy link
Contributor

kesselb commented May 24, 2020

Since it's a PUT request for a new file, perhaps it makes some sense that initially the Node is not found?

That makes sense. So it's maybe enough to remove the lock release from createFile?

But making the locking provider more stable is also a good thing. I'm just trying to understand why a code path runs twice.

@jvsalo
Copy link
Contributor Author

jvsalo commented May 24, 2020

So it's maybe enough to remove the lock release from createFile?

In the current code I like that it's clear what part is responsible for releasing each lock - it's literally all in the same file/function.

If Directory::createFile() lock is released in LockPlugin::releaseLock(), it may be surprising to someone studying/extending the locking code?

I find it a bit confusing that LockPlugin maybe acquires some lock and maybe releases it. Perhaps LockPlugin should remember if it actually got the lock, and only try to release if it actually did get it? AFAIK this should avoid double-locking completely in the "PUT new file" case. I suppose for updating a file, double-lock would still be taken.

It seems a bit scary to me that if LockPlugin fails to get (or release) a lock, it's "ok" in all cases without printing a warning.

@jvsalo jvsalo force-pushed the shared-lock-multi-release branch 2 times, most recently from ce3adb1 to a279736 Compare May 24, 2020 17:26
When uploading new files, getNodeForPath() will not succeed
yet so the lock cannot be acquired.

In that case, don't try to unlock it either.

Signed-off-by: Jaakko Salo <[email protected]>
@jvsalo jvsalo force-pushed the shared-lock-multi-release branch from a279736 to 6886b46 Compare May 24, 2020 17:26
Copy link
Member

@MorrisJobke MorrisJobke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code looks good 👍

@MorrisJobke MorrisJobke merged commit e878c0a into nextcloud:master Jul 6, 2020
@welcome
Copy link

welcome bot commented Jul 6, 2020

Thanks for your first pull request and welcome to the community! Feel free to keep them coming! If you are looking for issues to tackle then have a look at this selection: https://github.com/nextcloud/server/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22

@MorrisJobke MorrisJobke added this to the Nextcloud 20 milestone Jul 6, 2020
@MorrisJobke
Copy link
Member

/backport to stable19

@MorrisJobke
Copy link
Member

/backport to stable18

@MorrisJobke
Copy link
Member

/backport to stable17

@MorrisJobke
Copy link
Member

I closed the ones to 17 and 18, because they do not apply clean.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

3. to review Waiting for reviews bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Double release of memcache locks causes PUT requests to fail

4 participants