/*
Unix SMB/CIFS implementation.
Locking functions
Copyright (C) Andrew Tridgell 1992-2000
Copyright (C) Jeremy Allison 1992-2006
Copyright (C) Volker Lendecke 2005
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Revision History:
12 aug 96: Erik.Devriendt@te6.siemens.be
added support for shared memory implementation of share mode locking
May 1997. Jeremy Allison (jallison@whistle.com). Modified share mode
locking to deal with multiple share modes per open file.
September 1997. Jeremy Allison (jallison@whistle.com). Added oplock
support.
rewrtten completely to use new tdb code. Tridge, Dec '99
Added POSIX locking support. Jeremy Allison (jeremy@valinux.com), Apr. 2000.
Added Unix Extensions POSIX locking support. Jeremy Allison Mar 2006.
*/
#include "includes.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_LOCKING
#define NO_LOCKING_COUNT (-1)
/* the locking database handle */
static struct db_context *lock_db;
/****************************************************************************
Debugging aids :-).
****************************************************************************/
const char *lock_type_name(enum brl_type lock_type)
{
switch (lock_type) {
case READ_LOCK:
return "READ";
case WRITE_LOCK:
return "WRITE";
case PENDING_READ_LOCK:
return "PENDING_READ";
case PENDING_WRITE_LOCK:
return "PENDING_WRITE";
default:
return "other";
}
}
const char *lock_flav_name(enum brl_flavour lock_flav)
{
return (lock_flav == WINDOWS_LOCK) ? "WINDOWS_LOCK" : "POSIX_LOCK";
}
/****************************************************************************
Utility function called to see if a file region is locked.
Called in the read/write codepath.
****************************************************************************/
void init_strict_lock_struct(files_struct *fsp,
uint32 smbpid,
br_off start,
br_off size,
enum brl_type lock_type,
struct lock_struct *plock)
{
SMB_ASSERT(lock_type == READ_LOCK || lock_type == WRITE_LOCK);
plock->context.smbpid = smbpid;
plock->context.tid = fsp->conn->cnum;
plock->context.pid = procid_self();
plock->start = start;
plock->size = size;
plock->fnum = fsp->fnum;
plock->lock_type = lock_type;
plock->lock_flav = lp_posix_cifsu_locktype(fsp);
}
bool strict_lock_default(files_struct *fsp, struct lock_struct *plock)
{
int strict_locking = lp_strict_locking(fsp->conn->params);
bool ret = False;
if (plock->size == 0) {
return True;
}
if (!lp_locking(fsp->conn->params) || !strict_locking) {
return True;
}
if (strict_locking == Auto) {
if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && (plock->lock_type == READ_LOCK || plock->lock_type == WRITE_LOCK)) {
DEBUG(10,("is_locked: optimisation - exclusive oplock on file %s\n", fsp_str_dbg(fsp)));
ret = True;
} else if ((fsp->oplock_type == LEVEL_II_OPLOCK) &&
(plock->lock_type == READ_LOCK)) {
DEBUG(10,("is_locked: optimisation - level II oplock on file %s\n", fsp_str_dbg(fsp)));
ret = True;
} else {
struct byte_range_lock *br_lck = brl_get_locks_readonly(talloc_tos(), fsp);
if (!br_lck) {
return True;
}
ret = brl_locktest(br_lck,
plock->context.smbpid,
plock->context.pid,
plock->start,
plock->size,
plock->lock_type,
plock->lock_flav);
TALLOC_FREE(br_lck);
}
} else {
struct byte_range_lock *br_lck = brl_get_locks_readonly(talloc_tos(), fsp);
if (!br_lck) {
return True;
}
ret = brl_locktest(br_lck,
plock->context.smbpid,
plock->context.pid,
plock->start,
plock->size,
plock->lock_type,
plock->lock_flav);
TALLOC_FREE(br_lck);
}
DEBUG(10,("strict_lock_default: flavour = %s brl start=%.0f "
"len=%.0f %s for fnum %d file %s\n",
lock_flav_name(plock->lock_flav),
(double)plock->start, (double)plock->size,
ret ? "unlocked" : "locked",
plock->fnum, fsp_str_dbg(fsp)));
return ret;
}
void strict_unlock_default(files_struct *fsp, struct lock_struct *plock)
{
}
/****************************************************************************
Find out if a lock could be granted - return who is blocking us if we can't.
****************************************************************************/
NTSTATUS query_lock(files_struct *fsp,
uint32 *psmbpid,
|