How to Clear Stale Samba File Locks After Client Disconnection in Windows Profile Environments


3 views

When managing Windows XP profiles on a Debian Samba server, one particularly frustrating issue occurs when clients disconnect improperly - stale file locks remain in place. These locks, often created by applications like Thunderbird and Firefox, persist in Samba's locking table even after the client connection terminates.

# smbstatus -L | grep DENY_ALL
Pid          Uid        DenyMode   Access      R/W        Oplock           SharePath   Name   Time
15494        10345      DENY_ALL   0x3019f     RDWR       EXCLUSIVE+BATCH  /home/CORP/user1   app.profile/user1.thunderbird/parent.lock

Windows applications frequently use DENY_ALL locks to prevent other processes from accessing files. When the client crashes or disconnects abruptly, Samba maintains these locks by default, following the CIFS/SMB protocol specifications.

Here are several approaches to handle stale locks while maintaining proper locking functionality:

1. Adjusting Samba's Oplock Configuration

Modify your smb.conf to implement more aggressive lock timeouts:

[global]
    oplocks = yes
    kernel oplocks = no
    strict locking = yes
    smb2 leases = no
    deadtime = 15
    keepalive = 60

2. Implementing a Lock Cleanup Script

Create a cron job to periodically clear stale locks:

#!/bin/bash
# Cleanup stale Samba locks
for lock in $(smbstatus -L | grep "DENY_ALL" | awk '{print $1}'); do
    smbcontrol smbd close-share "$lock"
done

3. Client-Side Profile Configuration

Configure Windows clients to handle profile files more gracefully:

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Winlogon]
"SlowLinkProfileDefault"=dword:00000001
"ProfileDlgTimeOut"=dword:0000001e

For enterprise environments, consider implementing a custom VFS module:

vfs objects = preopen
preopen:names = /etc/samba/preopen.conf
preopen:check_parent = yes

Create /etc/samba/preopen.conf with patterns for problematic files:

*.thunderbird/*.lock
*.firefox/*.lock

Implement regular monitoring of your lock situation:

# Daily lock report
smbstatus -L > /var/log/samba/lock_report_$(date +%Y%m%d).log

Combine this with logrotate to maintain historical data while preventing log files from growing too large.


When running Windows profiles directly from Samba shares (common in corporate environments), we frequently encounter situations where client disconnections leave stale file locks. This occurs particularly with applications like Thunderbird and Firefox that aggressively maintain profile locks. Examining the locking table reveals entries like:

Pid          Uid        DenyMode   Access      R/W        Oplock           SharePath   Name   Time
15494        10345      DENY_ALL   0x3019f     RDWR       EXCLUSIVE+BATCH  /home/CORP/user1   profile/user1.thunderbird/parent.lock

While completely disabling file locking (kernel oplocks = no in smb.conf) would technically solve the issue, it's not viable for production environments where file integrity matters. The challenge is maintaining locking functionality while automatically cleaning up stale locks.

These smb.conf parameters help mitigate the problem:

[global]
    kernel change notify = no
    oplock break wait time = 60
    deadtime = 30
    keepalive = 60
    smb2 leases = yes
    veto oplock files = /*.lock/*.LOCK/

For persistent cases, implement a cron job that identifies and clears stale locks:

#!/bin/bash
SMBCLIENT="/usr/bin/smbclient"
LOCKFILE="/var/run/samba/lock_cleanup.pid"

# Prevent multiple instances
if [ -f "$LOCKFILE" ]; then
    exit 0
fi
echo $$ > "$LOCKFILE"

# Find stale locks older than 2 hours
STALE_LOCKS=$(smbstatus -L | awk '$6 ~ /DENY_ALL/ && $9 ~ /Thunderbird|Firefox/ {
    cmd = "ps -p " $1 " >/dev/null 2>&1"
    if (system(cmd) != 0) {
        print $1, $7 "/" $8
    }
}')

while read -r pid path; do
    echo "Clearing stale lock from PID $pid on $path"
    smbcontrol smbd close-share "$path"
done <<< "$STALE_LOCKS"

rm -f "$LOCKFILE"

Complement server-side changes with these client registry modifications to prevent aggressive locking:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\MRxSmb\Parameters]
"SessionTimeout"=dword:0000003c
"OpportunisticLocking"=dword:00000000

Implement monitoring to track lock persistence:

# Nagios plugin to check for stale locks
#!/bin/bash
WARNING_THRESHOLD=10
CRITICAL_THRESHOLD=30

STALE_COUNT=$(smbstatus -L | grep DENY_ALL | awk -v now=$(date +%s) '{
    locktime = $NF; gsub(/-|:/," ",locktime);
    lock_epoch = mktime(locktime);
    if ((now - lock_epoch) > 7200) print $0;
}' | wc -l)

if [ "$STALE_COUNT" -ge "$CRITICAL_THRESHOLD" ]; then
    echo "CRITICAL: $STALE_COUNT stale locks detected"
    exit 2
elif [ "$STALE_COUNT" -ge "$WARNING_THRESHOLD" ]; then
    echo "WARNING: $STALE_COUNT stale locks detected"
    exit 1
else
    echo "OK: $STALE_COUNT stale locks detected"
    exit 0
fi