Skip to content

FLOCK on linux with kernel 5.5 on samba share fails #388

@LocutusOfBorg

Description

@LocutusOfBorg

Hello @druzus,
I found your commit 30d0f5b when debugging a session of failures on our SMB-based network implementation.

We use harbour to lock/write dbf/cdx on SMB3.1.1 network mount share.

However after linux 5.5 (commit d0677992d2af3d65f1c1c21de3323d09d4891537) we got a regression on the shared lock, looking like as your statement on

      * src/rtl/filesys.c
        * do not convert exclusive lock to shared one when file is open in
          readonly mode on POSIX system using flock() for DENY_* flag emulation.
          Now HB_USE_BSDLOCKS is enabled only for Linux and it's documented that
          this implementation allow to use shared and exclusive locks regardless of
          file open mode.

is not true anymore.

I did create a simple c program, using old and new kernel to see the differences, and I'm attaching them for reference to this bug report

#include <stdio.h> 
#include <errno.h> 
#include <fcntl.h> 
#include <sys/file.h>

int main()
{
            struct flock64 lock_info;
            int hFileHandle;
	    // OPEN
	    int ret;
            hFileHandle = openat(AT_FDCWD, "/home/user/net/smb.dbf", O_RDWR);
	    printf("\nhFileHandle %d\n", hFileHandle);
            lock_info.l_type   = F_RDLCK;
            lock_info.l_start  = 0x7fffffffUL;
            lock_info.l_len    = 0x1UL;
            lock_info.l_whence = SEEK_SET;   /* start from the beginning of the file */
            lock_info.l_pid    = 0;
	    ret = flock(hFileHandle, LOCK_EX | LOCK_NB);
	    //ret = fcntl( hFileHandle, ( 0 ) ? F_SETLKW64: F_SETLK64, &lock_info );
	    if (ret == -1)
		    printf("fcntl errno: %d\n", errno);
	
	    // LOCK
            lock_info.l_type   = F_WRLCK;
            lock_info.l_start  = 2147483645;
            lock_info.l_len    = 1;
            lock_info.l_whence = SEEK_SET;   /* start from the beginning of the file */
            lock_info.l_pid    = 0;
	    printf("\nhFileHandle %d\n", hFileHandle);
            ret = fcntl( hFileHandle, ( 0 ) ? F_SETLKW64: F_SETLK64, &lock_info );
	    if (ret == -1)
		    printf("fcntl errno: %d\n", errno);
}

logs.tar.gz

with flock/fcntl I get on old kernel:

hFileHandle 3

hFileHandle 3

while with new kernel >5.5 (6.8 on Ubuntu 24.04 in my case, but I did install all the 5.4 and all 5.5 available on launchpad)
with flock:


hFileHandle 3

hFileHandle 3
fcntl errno: 13

with fcntl:


hFileHandle 3

hFileHandle 3

To unblock the current situation, I found that this simple patch fixes the issue for me:

diff --git a/include/hbapifs.h b/include/hbapifs.h
index 828af0e714..ae860e0220 100644
--- a/include/hbapifs.h
+++ b/include/hbapifs.h
@@ -229,16 +229,6 @@ extern HB_EXPORT int        hb_fsCanWrite    ( HB_FHANDLE hFileHandle, HB_MAXINT
 #  define HB_SHARELOCK_SIZE         0x1UL
 #  if defined( HB_USE_BSDLOCKS_OFF )
 #     undef HB_USE_BSDLOCKS
-#  elif defined( HB_OS_LINUX ) && \
-        ! defined( __WATCOMC__ ) && ! defined( HB_USE_BSDLOCKS )
-      /* default usage of BSD locks in *BSD systems for emulating
-       * MS-DOS/Windows DENY_* flags has been disabled because tests
-       * on FreeBSD 6.2 and macOS shows that this implementation
-       * can create self deadlock when used simultaneously with
-       * POSIX locks - thanks to Phil and Lorenzo for locating the
-       * problem and tests [druzus]
-       */
-#     define HB_USE_BSDLOCKS
 #  endif
 #endif

I'm attaching logs and pcaps with all the 4 cases (old/new kernel and old/new lock mechanism).

I'm however wondering if we should just throw away the HB_USE_BSDLOCKS code since it is unused with this patch.

Note: samba server is configured with "veto oplocks" for dbf/cdx files, to allow record locking granularity

Note2: I'm quoting flock manpage

CIFS details
       Up to Linux 5.4, flock() is not propagated over SMB.  A file with
       such locks will not appear locked for remote clients.

       Since Linux 5.5, flock() locks are emulated with SMB byte-range
       locks on the entire file.  Similarly to NFS, this means that
       [fcntl(2)](https://man7.org/linux/man-pages/man2/fcntl.2.html) and flock() locks interact with one another.  Another
       important side-effect is that the locks are not advisory anymore:
       any IO on a locked file will always fail with EACCES when done
       from a separate file descriptor.  This difference originates from
       the design of locks in the SMB protocol, which provides mandatory
       locking semantics.

       Remote and mandatory locking semantics may vary with SMB protocol,
       mount options and server type.  See mount.cifs(8) for additional
       information.

I'm not expert on samba protocol, nor on harbour code, so please forgive me if the analysis looked uncorrect (and this is why I didn't open yet a PR)

Gianfranco

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions