Broken filelocks/uploads after update from 11.0.2 to 12.0.5

Hey guys,

I need your help with a strange behaviour I just discovered while testing an upgraded Nextcloud installation. Under certain circumstances it is impossible to upload a file or create a new directory inside of a shared folder.

The progress bar won’t disappear until I reload the page. In case of trying to create a new folder, a message “Unable to create folder foobar” will pop up at the top of the page.

However new files and folders are visible for the current user and for the share-owner aswell after refreshing the website. But they can’t be access, downloaded or deleted because they are still locked.

Disabling transactional file locking fixes the access/delete problem but the upload progress bar still won’t finish properly.

This seems to apply only to non-admin users (sharees) and only if the shared folder is a subdirectory of another shared folder which has been shared with atleast one different user or group. So I guess it’s some kind of permission issue regarding upload/locking mechanism.

Nextcloud version: 12.0.5
Operating system and version: CentOS 7.4
Apache or nginx version: Apache 2.4.6
PHP version: 7.1.8

The issue you are facing:

Unable to upload/create files or folder inside of a shared folder when the current user is not member of admin group or the parent folder of the shared folder is also shared to some third party users/groups. The upload won’t finish gracefully and will leave the new object with an active file lock. There are multiple locks in MariaDB oc_file_locks with lock values of 1, -1 and 4.

Steps to replicate it:

  1. As admin, create a folder “foo” and share it with some user/group
  2. Inside of “foo”, create another folder “bar” and share it with user A
  3. As user A try to upload a file into shared folder “bar”
  4. Watch the upload progress bar not disappear until F5
  5. Try to access/delete the file as user A or as admin and fail because of the lock

The output of your Nextcloud log in Admin > Logging:

OCA\DAV\Connector\Sabre\Exception\FileLocked: "dir/subdir/subdir/file" is locked

    /nextcloud-root/3rdparty/sabre/dav/lib/DAV/CorePlugin.php - line 85: OCA\DAV\Connector\Sabre\File->get()
    [internal function] Sabre\DAV\CorePlugin->httpGet(Object(Sabre\HTTP\Request), Object(Sabre\HTTP\Response))
    /nextcloud-root/3rdparty/sabre/event/lib/EventEmitterTrait.php - line 105: call_user_func_array(Array, Array)
    /nextcloud-root/3rdparty/sabre/dav/lib/DAV/Server.php - line 479: Sabre\Event\EventEmitter->emit('method GET', Array)
    /nextcloud-root/3rdparty/sabre/dav/lib/DAV/Server.php - line 254: Sabre\DAV\Server->invokeMethod(Object(Sabre\HTTP\Request), Object(Sabre\HTTP\Response))
    /nextcloud-root/apps/dav/appinfo/v1/webdav.php - line 76: Sabre\DAV\Server->exec()
    /nextcloud-root/remote.php - line 162: require_once('/nextcloud-root...')
    {main}

OCP\Lock\LockedException: "dir/subdir/subdir/file.txt" is locked

    /nextcloud-root/lib/private/Files/View.php - line 2041: OC\Files\View->lockPath('/files/dir/s...', 1, false)
    /nextcloud-root/lib/private/Files/View.php - line 1145: OC\Files\View->lockFile('/files/dir/s...', 1)
    /nextcloud-root/lib/private/Files/View.php - line 998: OC\Files\View->basicOperation('fopen', '/files/dir/s...', Array, 'r')
    /nextcloud-root/lib/private/Preview/TXT.php - line 48: OC\Files\View->fopen('/files/dir/s...', 'r')
    /nextcloud-root/lib/private/Preview/GeneratorHelper.php - line 54: OC\Preview\TXT->getThumbnail('/files/dir/s...', 2048, 2048, false, Object(OC\Files\View))
    /nextcloud-root/lib/private/Preview/Generator.php - line 166: OC\Preview\GeneratorHelper->getThumbnail(Object(OC\Preview\TXT), Object(OC\Files\Node\File), 2048, 2048)
    /nextcloud-root/lib/private/Preview/Generator.php - line 110: OC\Preview\Generator->getMaxPreview(Object(OC\Files\SimpleFS\SimpleFolder), Object(OC\Files\Node\File), 'text/plain')
    /nextcloud-root/lib/private/PreviewManager.php - line 201: OC\Preview\Generator->getPreview(Object(OC\Files\Node\File), 32, 32, true, 'fill', 'text/plain')
    /nextcloud-root/core/Controller/PreviewController.php - line 113: OC\PreviewManager->getPreview(Object(OC\Files\Node\File), 32, 32, true, 'fill')
    [internal function] OC\Core\Controller\PreviewController->getPreview(Object(OC\Files\Node\File), 32, 32, false, false, 'fill')
    /nextcloud-root/lib/private/AppFramework/Http/Dispatcher.php - line 160: call_user_func_array(Array, Array)
    /nextcloud-root/lib/private/AppFramework/Http/Dispatcher.php - line 90: OC\AppFramework\Http\Dispatcher->executeController(Object(OC\Core\Controller\PreviewController), 'getPreview')
    /nextcloud-root/lib/private/AppFramework/App.php - line 114: OC\AppFramework\Http\Dispatcher->dispatch(Object(OC\Core\Controller\PreviewController), 'getPreview')
    /nextcloud-root/lib/private/AppFramework/Routing/RouteActionHandler.php - line 47: OC\AppFramework\App main('OC\\Core\\Control...', 'getPreview', Object(OC\AppFramework\DependencyInjection\DIContainer), Array)
    [internal function] OC\AppFramework\Routing\RouteActionHandler->__invoke(Array)
    /nextcloud-root/lib/private/Route/Router.php - line 299: call_user_func(Object(OC\AppFramework\Routing\RouteActionHandler), Array)
    /nextcloud-root/lib/base.php - line 1004: OC\Route\Router->match('/core/preview.p...')
    /nextcloud-root/index.php - line 48: OC handleRequest()
    {main}

I just added some OCP\ILogger output for each function in /nextcloud-root/lib/private/Lock/DBLockingProvider.php to see what happens. Apparently, after creating a new directory in a shared folder as described above, the system hangs in a infinite loop with the functions acquireLock, isLocallyLocked, initLockField and markAcquire until I restart apache (which takes 1-2 minutes…).