summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
Diffstat (limited to 'source3')
-rw-r--r--source3/include/locking.h20
-rw-r--r--source3/include/proto.h26
-rw-r--r--source3/include/vfs.h24
-rw-r--r--source3/include/vfs_macros.h9
-rw-r--r--source3/locking/brlock.c66
-rw-r--r--source3/locking/locking.c81
-rw-r--r--source3/modules/vfs_default.c41
-rw-r--r--source3/modules/vfs_full_audit.c73
-rw-r--r--source3/smbd/blocking.c107
-rw-r--r--source3/smbd/reply.c18
-rw-r--r--source3/smbd/trans2.c3
11 files changed, 358 insertions, 110 deletions
diff --git a/source3/include/locking.h b/source3/include/locking.h
index b2b7236721..3fd5b94de7 100644
--- a/source3/include/locking.h
+++ b/source3/include/locking.h
@@ -75,4 +75,24 @@ struct lock_struct {
enum brl_flavour lock_flav;
};
+/****************************************************************************
+ This is the structure to queue to implement blocking locks.
+*****************************************************************************/
+
+struct blocking_lock_record {
+ struct blocking_lock_record *next;
+ struct blocking_lock_record *prev;
+ struct files_struct *fsp;
+ struct timeval expire_time;
+ int lock_num;
+ uint64_t offset;
+ uint64_t count;
+ uint32_t lock_pid;
+ uint32_t blocking_pid; /* PID that blocks us. */
+ enum brl_flavour lock_flav;
+ enum brl_type lock_type;
+ struct smb_request *req;
+ void *blr_private; /* Implementation specific. */
+};
+
#endif /* _LOCKING_H_ */
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 34104727e9..ed2c50af2f 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -3379,8 +3379,14 @@ struct packet_struct *receive_unexpected(enum packet_type packet_type, int id,
bool brl_same_context(const struct lock_context *ctx1,
const struct lock_context *ctx2);
+NTSTATUS brl_lock_failed(files_struct *fsp, const struct lock_struct *lock, bool blocking_lock);
void brl_init(bool read_only);
void brl_shutdown(void);
+
+NTSTATUS brl_lock_windows_default(struct byte_range_lock *br_lck,
+ struct lock_struct *plock,
+ bool blocking_lock);
+
NTSTATUS brl_lock(struct messaging_context *msg_ctx,
struct byte_range_lock *br_lck,
uint32 smbpid,
@@ -3390,7 +3396,8 @@ NTSTATUS brl_lock(struct messaging_context *msg_ctx,
enum brl_type lock_type,
enum brl_flavour lock_flav,
bool blocking_lock,
- uint32 *psmbpid);
+ uint32 *psmbpid,
+ struct blocking_lock_record *blr);
bool brl_unlock(struct messaging_context *msg_ctx,
struct byte_range_lock *br_lck,
uint32 smbpid,
@@ -3398,6 +3405,9 @@ bool brl_unlock(struct messaging_context *msg_ctx,
br_off start,
br_off size,
enum brl_flavour lock_flav);
+bool brl_unlock_windows_default(struct messaging_context *msg_ctx,
+ struct byte_range_lock *br_lck,
+ const struct lock_struct *plock);
bool brl_locktest(struct byte_range_lock *br_lck,
uint32 smbpid,
struct server_id pid,
@@ -3417,7 +3427,10 @@ bool brl_lock_cancel(struct byte_range_lock *br_lck,
struct server_id pid,
br_off start,
br_off size,
- enum brl_flavour lock_flav);
+ enum brl_flavour lock_flav,
+ struct blocking_lock_record *blr);
+bool brl_lock_cancel_default(struct byte_range_lock *br_lck,
+ struct lock_struct *plock);
void brl_close_fnum(struct messaging_context *msg_ctx,
struct byte_range_lock *br_lck);
int brl_forall(void (*fn)(struct file_id id, struct server_id pid,
@@ -3456,7 +3469,8 @@ struct byte_range_lock *do_lock(struct messaging_context *msg_ctx,
enum brl_flavour lock_flav,
bool blocking_lock,
NTSTATUS *perr,
- uint32 *plock_pid);
+ uint32 *plock_pid,
+ struct blocking_lock_record *blr);
NTSTATUS do_unlock(struct messaging_context *msg_ctx,
files_struct *fsp,
uint32 lock_pid,
@@ -3467,7 +3481,8 @@ NTSTATUS do_lock_cancel(files_struct *fsp,
uint32 lock_pid,
uint64_t count,
uint64_t offset,
- enum brl_flavour lock_flav);
+ enum brl_flavour lock_flav,
+ struct blocking_lock_record *blr);
void locking_close_file(struct messaging_context *msg_ctx,
files_struct *fsp);
bool locking_init(void);
@@ -6342,6 +6357,7 @@ void smbd_aio_complete_mid(unsigned int mid);
/* The following definitions come from smbd/blocking.c */
+void process_blocking_lock_queue(void);
bool push_blocking_lock_request( struct byte_range_lock *br_lck,
struct smb_request *req,
files_struct *fsp,
@@ -6356,7 +6372,7 @@ bool push_blocking_lock_request( struct byte_range_lock *br_lck,
void cancel_pending_lock_requests_by_fid(files_struct *fsp, struct byte_range_lock *br_lck);
void remove_pending_lock_requests_by_mid(int mid);
bool blocking_lock_was_deferred(int mid);
-bool blocking_lock_cancel(files_struct *fsp,
+struct blocking_lock_record *blocking_lock_cancel(files_struct *fsp,
uint32 lock_pid,
uint64_t offset,
uint64_t count,
diff --git a/source3/include/vfs.h b/source3/include/vfs.h
index f944c899c6..ffa1a95ed0 100644
--- a/source3/include/vfs.h
+++ b/source3/include/vfs.h
@@ -115,6 +115,7 @@
/* Leave at 25 - not yet released. Add get_alloc_size call. -- tprouty. */
/* Leave at 25 - not yet released. Add SMB_STRUCT_STAT to readdir. - sdann */
/* Leave at 25 - not yet released. Add init_search_op call. - sdann */
+/* Leave at 25 - not yet released. Add locking calls. -- zkirsch. */
#define SMB_VFS_INTERFACE_VERSION 25
@@ -142,6 +143,7 @@ struct vfs_statvfs_struct;
struct smb_request;
struct ea_list;
struct smb_file_time;
+struct blocking_lock_record;
/*
Available VFS operations. These values must be in sync with vfs_ops struct
@@ -218,6 +220,9 @@ typedef enum _vfs_op_type {
SMB_VFS_OP_FILE_ID_CREATE,
SMB_VFS_OP_STREAMINFO,
SMB_VFS_OP_GET_REAL_FILENAME,
+ SMB_VFS_OP_BRL_LOCK_WINDOWS,
+ SMB_VFS_OP_BRL_UNLOCK_WINDOWS,
+ SMB_VFS_OP_BRL_CANCEL_WINDOWS,
/* NT ACL operations. */
@@ -393,6 +398,22 @@ struct vfs_ops {
TALLOC_CTX *mem_ctx,
char **found_name);
+ NTSTATUS (*brl_lock_windows)(struct vfs_handle_struct *handle,
+ struct byte_range_lock *br_lck,
+ struct lock_struct *plock,
+ bool blocking_lock,
+ struct blocking_lock_record *blr);
+
+ bool (*brl_unlock_windows)(struct vfs_handle_struct *handle,
+ struct messaging_context *msg_ctx,
+ struct byte_range_lock *br_lck,
+ const struct lock_struct *plock);
+
+ bool (*brl_cancel_windows)(struct vfs_handle_struct *handle,
+ struct byte_range_lock *br_lck,
+ struct lock_struct *plock,
+ struct blocking_lock_record *blr);
+
/* NT ACL operations. */
NTSTATUS (*fget_nt_acl)(struct vfs_handle_struct *handle,
@@ -531,6 +552,9 @@ struct vfs_ops {
struct vfs_handle_struct *file_id_create;
struct vfs_handle_struct *streaminfo;
struct vfs_handle_struct *get_real_filename;
+ struct vfs_handle_struct *brl_lock_windows;
+ struct vfs_handle_struct *brl_unlock_windows;
+ struct vfs_handle_struct *brl_cancel_windows;
/* NT ACL operations. */
diff --git a/source3/include/vfs_macros.h b/source3/include/vfs_macros.h
index e57cbd2538..dcef63da86 100644
--- a/source3/include/vfs_macros.h
+++ b/source3/include/vfs_macros.h
@@ -88,6 +88,9 @@
#define SMB_VFS_FILE_ID_CREATE(conn, dev, inode) ((conn)->vfs.ops.file_id_create((conn)->vfs.handles.file_id_create, (dev), (inode)))
#define SMB_VFS_STREAMINFO(conn, fsp, fname, mem_ctx, num_streams, streams) ((conn)->vfs.ops.streaminfo((conn)->vfs.handles.streaminfo, (fsp), (fname), (mem_ctx), (num_streams), (streams)))
#define SMB_VFS_GET_REAL_FILENAME(conn, path, name, mem_ctx, found_name) ((conn)->vfs.ops.get_real_filename((conn)->vfs.handles.get_real_filename, (path), (name), (mem_ctx), (found_name)))
+#define SMB_VFS_BRL_LOCK_WINDOWS(conn, br_lck, plock, blocking_lock, blr) ((conn)->vfs.ops.brl_lock_windows((conn)->vfs.handles.brl_lock_windows, (br_lck), (plock), (blocking_lock), (blr)))
+#define SMB_VFS_BRL_UNLOCK_WINDOWS(conn, msg_ctx, br_lck, plock) ((conn)->vfs.ops.brl_unlock_windows((conn)->vfs.handles.brl_unlock_windows, (msg_ctx), (br_lck), (plock)))
+#define SMB_VFS_BRL_CANCEL_WINDOWS(conn, br_lck, plock, blr) ((conn)->vfs.ops.brl_cancel_windows((conn)->vfs.handles.brl_cancel_windows, (br_lck), (plock), (blr)))
/* NT ACL operations. */
#define SMB_VFS_FGET_NT_ACL(fsp, security_info, ppdesc) ((fsp)->conn->vfs.ops.fget_nt_acl((fsp)->conn->vfs.handles.fget_nt_acl, (fsp), (security_info), (ppdesc)))
@@ -217,6 +220,9 @@
#define SMB_VFS_OPAQUE_FILE_ID_CREATE(conn, dev, inode) ((conn)->vfs.ops_opaque.file_id_create((conn)->vfs_opaque.handles.file_id_create, (dev), (inode)))
#define SMB_VFS_OPAQUE_STREAMINFO(conn, fsp, fname, mem_ctx, num_streams, streams) ((conn)->vfs_opaque.ops.streaminfo((conn)->vfs_opaque.handles.streaminfo, (fsp), (fname), (mem_ctx), (num_streams), (streams)))
#define SMB_VFS_OPAQUE_GET_REAL_FILENAME(conn, path, name, mem_ctx, found_name) ((conn)->vfs_opaque.ops.get_real_filename((conn)->vfs_opaque.handles.get_real_filename, (path), (name), (mem_ctx), (found_name)))
+#define SMB_VFS_OPAQUE_BRL_LOCK_WINDOWS(conn, br_lck, plock, blocking_lock, blr) ((conn)->vfs_opaque.ops.brl_lock_windows((conn)->vfs_opaque.handles.brl_lock_windows, (br_lck), (plock), (blocking_lock), (blr)))
+#define SMB_VFS_OPAQUE_BRL_UNLOCK_WINDOWS(conn, msg_ctx, br_lck, plock) ((conn)->vfs_opaque.ops.brl_unlock_windows((conn)->vfs_opaque.handles.brl_unlock_windows, (msg_ctx), (br_lck), (plock)))
+#define SMB_VFS_OPAQUE_BRL_CANCEL_WINDOWS(conn, br_lck, plock, blr) ((conn)->vfs_opaque.ops.brl_cancel_windows((conn)->vfs_opaque.handles.brl_cancel_windows, (br_lck), (plock), (blr)))
/* NT ACL operations. */
#define SMB_VFS_OPAQUE_FGET_NT_ACL(fsp, security_info, ppdesc) ((fsp)->conn->vfs_opaque.ops.fget_nt_acl((fsp)->conn->vfs_opaque.handles.fget_nt_acl, (fsp), (security_info), (ppdesc)))
@@ -347,6 +353,9 @@
#define SMB_VFS_NEXT_FILE_ID_CREATE(handle, dev, inode) ((handle)->vfs_next.ops.file_id_create((handle)->vfs_next.handles.file_id_create, (dev), (inode)))
#define SMB_VFS_NEXT_STREAMINFO(handle, fsp, fname, mem_ctx, num_streams, streams) ((handle)->vfs_next.ops.streaminfo((handle)->vfs_next.handles.streaminfo, (fsp), (fname), (mem_ctx), (num_streams), (streams)))
#define SMB_VFS_NEXT_GET_REAL_FILENAME(handle, path, name, mem_ctx, found_name) ((handle)->vfs_next.ops.get_real_filename((handle)->vfs_next.handles.get_real_filename, (path), (name), (mem_ctx), (found_name)))
+#define SMB_VFS_NEXT_BRL_LOCK_WINDOWS(handle, br_lck, plock, blocking_lock, blr) ((handle)->vfs_next.ops.brl_lock_windows((handle)->vfs_next.handles.brl_lock_windows, (br_lck), (plock), (blocking_lock), (blr)))
+#define SMB_VFS_NEXT_BRL_UNLOCK_WINDOWS(handle, msg_ctx, br_lck, plock) ((handle)->vfs_next.ops.brl_unlock_windows((handle)->vfs_next.handles.brl_unlock_windows, (msg_ctx), (br_lck), (plock)))
+#define SMB_VFS_NEXT_BRL_CANCEL_WINDOWS(handle, br_lck, plock, blr) ((handle)->vfs_next.ops.brl_cancel_windows((handle)->vfs_next.handles.brl_cancel_windows, (br_lck), (plock), (blr)))
/* NT ACL operations. */
#define SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, security_info, ppdesc) ((handle)->vfs_next.ops.fget_nt_acl((handle)->vfs_next.handles.fget_nt_acl, (fsp), (security_info), (ppdesc)))
diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c
index edba4ed30a..d12c4affc3 100644
--- a/source3/locking/brlock.c
+++ b/source3/locking/brlock.c
@@ -228,7 +228,7 @@ static bool brl_pending_overlap(const struct lock_struct *lock, const struct loc
app depends on this ?
****************************************************************************/
-static NTSTATUS brl_lock_failed(files_struct *fsp, const struct lock_struct *lock, bool blocking_lock)
+NTSTATUS brl_lock_failed(files_struct *fsp, const struct lock_struct *lock, bool blocking_lock)
{
if (lock->start >= 0xEF000000 && (lock->start >> 63) == 0) {
/* amazing the little things you learn with a test
@@ -305,14 +305,16 @@ static int lock_compare(const struct lock_struct *lck1,
Lock a range of bytes - Windows lock semantics.
****************************************************************************/
-static NTSTATUS brl_lock_windows(struct byte_range_lock *br_lck,
- struct lock_struct *plock, bool blocking_lock)
+NTSTATUS brl_lock_windows_default(struct byte_range_lock *br_lck,
+ struct lock_struct *plock, bool blocking_lock)
{
unsigned int i;
files_struct *fsp = br_lck->fsp;
struct lock_struct *locks = br_lck->lock_data;
NTSTATUS status;
+ SMB_ASSERT(plock->lock_type != UNLOCK_LOCK);
+
for (i=0; i < br_lck->num_locks; i++) {
/* Do any Windows or POSIX locks conflict ? */
if (brl_conflict(&locks[i], plock)) {
@@ -781,7 +783,8 @@ NTSTATUS brl_lock(struct messaging_context *msg_ctx,
enum brl_type lock_type,
enum brl_flavour lock_flav,
bool blocking_lock,
- uint32 *psmbpid)
+ uint32 *psmbpid,
+ struct blocking_lock_record *blr)
{
NTSTATUS ret;
struct lock_struct lock;
@@ -807,7 +810,8 @@ NTSTATUS brl_lock(struct messaging_context *msg_ctx,
lock.lock_flav = lock_flav;
if (lock_flav == WINDOWS_LOCK) {
- ret = brl_lock_windows(br_lck, &lock, blocking_lock);
+ ret = SMB_VFS_BRL_LOCK_WINDOWS(br_lck->fsp->conn, br_lck,
+ &lock, blocking_lock, blr);
} else {
ret = brl_lock_posix(msg_ctx, br_lck, &lock);
}
@@ -828,7 +832,7 @@ NTSTATUS brl_lock(struct messaging_context *msg_ctx,
Unlock a range of bytes - Windows semantics.
****************************************************************************/
-static bool brl_unlock_windows(struct messaging_context *msg_ctx,
+bool brl_unlock_windows_default(struct messaging_context *msg_ctx,
struct byte_range_lock *br_lck,
const struct lock_struct *plock)
{
@@ -836,6 +840,8 @@ static bool brl_unlock_windows(struct messaging_context *msg_ctx,
struct lock_struct *locks = br_lck->lock_data;
enum brl_type deleted_lock_type = READ_LOCK; /* shut the compiler up.... */
+ SMB_ASSERT(plock->lock_type == UNLOCK_LOCK);
+
#if ZERO_ZERO
/* Delete write locks by preference... The lock list
is sorted in the zero zero case. */
@@ -1130,7 +1136,8 @@ bool brl_unlock(struct messaging_context *msg_ctx,
lock.lock_flav = lock_flav;
if (lock_flav == WINDOWS_LOCK) {
- return brl_unlock_windows(msg_ctx, br_lck, &lock);
+ return SMB_VFS_BRL_UNLOCK_WINDOWS(br_lck->fsp->conn, msg_ctx,
+ br_lck, &lock);
} else {
return brl_unlock_posix(msg_ctx, br_lck, &lock);
}
@@ -1266,32 +1273,54 @@ NTSTATUS brl_lockquery(struct byte_range_lock *br_lck,
/****************************************************************************
Remove a particular pending lock.
****************************************************************************/
-
bool brl_lock_cancel(struct byte_range_lock *br_lck,
uint32 smbpid,
struct server_id pid,
br_off start,
br_off size,
- enum brl_flavour lock_flav)
+ enum brl_flavour lock_flav,
+ struct blocking_lock_record *blr)
+{
+ bool ret;
+ struct lock_struct lock;
+
+ lock.context.smbpid = smbpid;
+ lock.context.pid = pid;
+ lock.context.tid = br_lck->fsp->conn->cnum;
+ lock.start = start;
+ lock.size = size;
+ lock.fnum = br_lck->fsp->fnum;
+ lock.lock_flav = lock_flav;
+ /* lock.lock_type doesn't matter */
+
+ if (lock_flav == WINDOWS_LOCK) {
+ ret = SMB_VFS_BRL_CANCEL_WINDOWS(br_lck->fsp->conn, br_lck,
+ &lock, blr);
+ } else {
+ ret = brl_lock_cancel_default(br_lck, &lock);
+ }
+
+ return ret;
+}
+
+bool brl_lock_cancel_default(struct byte_range_lock *br_lck,
+ struct lock_struct *plock)
{
unsigned int i;
struct lock_struct *locks = br_lck->lock_data;
- struct lock_context context;
- context.smbpid = smbpid;
- context.pid = pid;
- context.tid = br_lck->fsp->conn->cnum;
+ SMB_ASSERT(plock);
for (i = 0; i < br_lck->num_locks; i++) {
struct lock_struct *lock = &locks[i];
/* For pending locks we *always* care about the fnum. */
- if (brl_same_context(&lock->context, &context) &&
- lock->fnum == br_lck->fsp->fnum &&
+ if (brl_same_context(&lock->context, &plock->context) &&
+ lock->fnum == plock->fnum &&
IS_PENDING_LOCK(lock->lock_type) &&
- lock->lock_flav == lock_flav &&
- lock->start == start &&
- lock->size == size) {
+ lock->lock_flav == plock->lock_flav &&
+ lock->start == plock->start &&
+ lock->size == plock->size) {
break;
}
}
@@ -1460,7 +1489,6 @@ void brl_close_fnum(struct messaging_context *msg_ctx,
/****************************************************************************
Ensure this set of lock entries is valid.
****************************************************************************/
-
static bool validate_lock_entries(unsigned int *pnum_entries, struct lock_struct **pplocks)
{
unsigned int i;
diff --git a/source3/locking/locking.c b/source3/locking/locking.c
index b342fa9b1e..902b230e60 100644
--- a/source3/locking/locking.c
+++ b/source3/locking/locking.c
@@ -177,6 +177,34 @@ NTSTATUS query_lock(files_struct *fsp,
return status;
}
+static void increment_current_lock_count(files_struct *fsp,
+ enum brl_flavour lock_flav)
+{
+ if (lock_flav == WINDOWS_LOCK &&
+ fsp->current_lock_count != NO_LOCKING_COUNT) {
+ /* blocking ie. pending, locks also count here,
+ * as this is an efficiency counter to avoid checking
+ * the lock db. on close. JRA. */
+
+ fsp->current_lock_count++;
+ } else {
+ /* Notice that this has had a POSIX lock request.
+ * We can't count locks after this so forget them.
+ */
+ fsp->current_lock_count = NO_LOCKING_COUNT;
+ }
+}
+
+static void decrement_current_lock_count(files_struct *fsp,
+ enum brl_flavour lock_flav)
+{
+ if (lock_flav == WINDOWS_LOCK &&
+ fsp->current_lock_count != NO_LOCKING_COUNT) {
+ SMB_ASSERT(fsp->current_lock_count > 0);
+ fsp->current_lock_count--;
+ }
+}
+
/****************************************************************************
Utility function called by locking requests.
****************************************************************************/
@@ -190,7 +218,8 @@ struct byte_range_lock *do_lock(struct messaging_context *msg_ctx,
enum brl_flavour lock_flav,
bool blocking_lock,
NTSTATUS *perr,
- uint32 *plock_pid)
+ uint32 *plock_pid,
+ struct blocking_lock_record *blr)
{
struct byte_range_lock *br_lck = NULL;
@@ -206,9 +235,11 @@ struct byte_range_lock *do_lock(struct messaging_context *msg_ctx,
/* NOTE! 0 byte long ranges ARE allowed and should be stored */
- DEBUG(10,("do_lock: lock flavour %s lock type %s start=%.0f len=%.0f requested for fnum %d file %s\n",
+ DEBUG(10,("do_lock: lock flavour %s lock type %s start=%.0f len=%.0f "
+ "blocking_lock=%s requested for fnum %d file %s\n",
lock_flav_name(lock_flav), lock_type_name(lock_type),
- (double)offset, (double)count, fsp->fnum, fsp->fsp_name ));
+ (double)offset, (double)count, blocking_lock ? "true" :
+ "false", fsp->fnum, fsp->fsp_name));
br_lck = brl_get_locks(talloc_tos(), fsp);
if (!br_lck) {
@@ -225,22 +256,12 @@ struct byte_range_lock *do_lock(struct messaging_context *msg_ctx,
lock_type,
lock_flav,
blocking_lock,
- plock_pid);
+ plock_pid,
+ blr);
- if (lock_flav == WINDOWS_LOCK &&
- fsp->current_lock_count != NO_LOCKING_COUNT) {
- /* blocking ie. pending, locks also count here,
- * as this is an efficiency counter to avoid checking
- * the lock db. on close. JRA. */
-
- fsp->current_lock_count++;
- } else {
- /* Notice that this has had a POSIX lock request.
- * We can't count locks after this so forget them.
- */
- fsp->current_lock_count = NO_LOCKING_COUNT;
- }
+ DEBUG(10, ("do_lock: returning status=%s\n", nt_errstr(*perr)));
+ increment_current_lock_count(fsp, lock_flav);
return br_lck;
}
@@ -289,12 +310,7 @@ NTSTATUS do_unlock(struct messaging_context *msg_ctx,
return NT_STATUS_RANGE_NOT_LOCKED;
}
- if (lock_flav == WINDOWS_LOCK &&
- fsp->current_lock_count != NO_LOCKING_COUNT) {
- SMB_ASSERT(fsp->current_lock_count > 0);
- fsp->current_lock_count--;
- }
-
+ decrement_current_lock_count(fsp, lock_flav);
return NT_STATUS_OK;
}
@@ -306,11 +322,14 @@ NTSTATUS do_lock_cancel(files_struct *fsp,
uint32 lock_pid,
uint64_t count,
uint64_t offset,
- enum brl_flavour lock_flav)
+ enum brl_flavour lock_flav,
+ struct blocking_lock_record *blr)
{
bool ok = False;
struct byte_range_lock *br_lck = NULL;
-
+
+ SMB_ASSERT(blr);
+
if (!fsp->can_lock) {
return fsp->is_directory ?
NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
@@ -333,8 +352,9 @@ NTSTATUS do_lock_cancel(files_struct *fsp,
procid_self(),
offset,
count,
- lock_flav);
-
+ lock_flav,
+ blr);
+
TALLOC_FREE(br_lck);
if (!ok) {
@@ -342,12 +362,7 @@ NTSTATUS do_lock_cancel(files_struct *fsp,
return NT_STATUS_DOS(ERRDOS, ERRcancelviolation);
}
- if (lock_flav == WINDOWS_LOCK &&
- fsp->current_lock_count != NO_LOCKING_COUNT) {
- SMB_ASSERT(fsp->current_lock_count > 0);
- fsp->current_lock_count--;
- }
-
+ decrement_current_lock_count(fsp, lock_flav);
return NT_STATUS_OK;
}
diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c
index 4b123ab03e..f52ca09c08 100644
--- a/source3/modules/vfs_default.c
+++ b/source3/modules/vfs_default.c
@@ -1113,6 +1113,41 @@ static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
found_name);
}
+static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
+ struct byte_range_lock *br_lck,
+ struct lock_struct *plock,
+ bool blocking_lock,
+ struct blocking_lock_record *blr)
+{
+ SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
+
+ /* Note: blr is not used in the default implementation. */
+ return brl_lock_windows_default(br_lck, plock, blocking_lock);
+}
+
+static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
+ struct messaging_context *msg_ctx,
+ struct byte_range_lock *br_lck,
+ const struct lock_struct *plock)
+{
+ SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
+
+ return brl_unlock_windows_default(msg_ctx, br_lck, plock);
+}
+
+static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
+ struct byte_range_lock *br_lck,
+ struct lock_struct *plock,
+ struct blocking_lock_record *blr)
+{
+ SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
+
+ /* Note: blr is not used in the default implementation. */
+ return brl_lock_cancel_default(br_lck, plock);
+}
+
+/* NT ACL operations. */
+
static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
files_struct *fsp,
uint32 security_info, SEC_DESC **ppdesc)
@@ -1540,6 +1575,12 @@ static vfs_op_tuple vfs_default_ops[] = {
SMB_VFS_LAYER_OPAQUE},
{SMB_VFS_OP(vfswrap_get_real_filename), SMB_VFS_OP_GET_REAL_FILENAME,
SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_brl_lock_windows), SMB_VFS_OP_BRL_LOCK_WINDOWS,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_brl_unlock_windows),SMB_VFS_OP_BRL_UNLOCK_WINDOWS,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_brl_cancel_windows),SMB_VFS_OP_BRL_CANCEL_WINDOWS,
+ SMB_VFS_LAYER_OPAQUE},
/* NT ACL operations. */
diff --git a/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c
index faa91c3a40..15eafc1b56 100644
--- a/source3/modules/vfs_full_audit.c
+++ b/source3/modules/vfs_full_audit.c
@@ -221,6 +221,19 @@ static int smb_full_audit_get_real_filename(struct vfs_handle_struct *handle,
const char *name,
TALLOC_CTX *mem_ctx,
char **found_name);
+static NTSTATUS smb_full_audit_brl_lock_windows(struct vfs_handle_struct *handle,
+ struct byte_range_lock *br_lck,
+ struct lock_struct *plock,
+ bool blocking_lock,
+ struct blocking_lock_record *blr);
+static bool smb_full_audit_brl_unlock_windows(struct vfs_handle_struct *handle,
+ struct messaging_context *msg_ctx,
+ struct byte_range_lock *br_lck,
+ const struct lock_struct *plock);
+static bool smb_full_audit_brl_cancel_windows(struct vfs_handle_struct *handle,
+ struct byte_range_lock *br_lck,
+ struct lock_struct *plock,
+ struct blocking_lock_record *blr);
static NTSTATUS smb_full_audit_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
uint32 security_info,
SEC_DESC **ppdesc);
@@ -464,6 +477,12 @@ static vfs_op_tuple audit_op_tuples[] = {
SMB_VFS_LAYER_LOGGER},
{SMB_VFS_OP(smb_full_audit_get_real_filename), SMB_VFS_OP_GET_REAL_FILENAME,
SMB_VFS_LAYER_LOGGER},
+ {SMB_VFS_OP(smb_full_audit_brl_lock_windows), SMB_VFS_OP_BRL_LOCK_WINDOWS,
+ SMB_VFS_LAYER_LOGGER},
+ {SMB_VFS_OP(smb_full_audit_brl_unlock_windows), SMB_VFS_OP_BRL_UNLOCK_WINDOWS,
+ SMB_VFS_LAYER_LOGGER},
+ {SMB_VFS_OP(smb_full_audit_brl_cancel_windows), SMB_VFS_OP_BRL_CANCEL_WINDOWS,
+ SMB_VFS_LAYER_LOGGER},
/* NT ACL operations. */
@@ -638,6 +657,9 @@ static struct {
{ SMB_VFS_OP_FILE_ID_CREATE, "file_id_create" },
{ SMB_VFS_OP_STREAMINFO, "streaminfo" },
{ SMB_VFS_OP_GET_REAL_FILENAME, "get_real_filename" },
+ { SMB_VFS_OP_BRL_LOCK_WINDOWS, "brl_lock_windows" },
+ { SMB_VFS_OP_BRL_UNLOCK_WINDOWS, "brl_unlock_windows" },
+ { SMB_VFS_OP_BRL_CANCEL_WINDOWS, "brl_cancel_windows" },
{ SMB_VFS_OP_FGET_NT_ACL, "fget_nt_acl" },
{ SMB_VFS_OP_GET_NT_ACL, "get_nt_acl" },
{ SMB_VFS_OP_FSET_NT_ACL, "fset_nt_acl" },
@@ -1693,6 +1715,57 @@ static int smb_full_audit_get_real_filename(struct vfs_handle_struct *handle,
return result;
}
+static NTSTATUS smb_full_audit_brl_lock_windows(struct vfs_handle_struct *handle,
+ struct byte_range_lock *br_lck,
+ struct lock_struct *plock,
+ bool blocking_lock,
+ struct blocking_lock_record *blr)
+{
+ NTSTATUS result;
+
+ result = SMB_VFS_NEXT_BRL_LOCK_WINDOWS(handle, br_lck, plock,
+ blocking_lock, blr);
+
+ do_log(SMB_VFS_OP_BRL_LOCK_WINDOWS, NT_STATUS_IS_OK(result), handle,
+ "%s:%llu-%llu. type=%d. blocking=%d", br_lck->fsp->fsp_name,
+ plock->start, plock->size, plock->lock_type, blocking_lock );
+
+ return result;
+}
+
+static bool smb_full_audit_brl_unlock_windows(struct vfs_handle_struct *handle,
+ struct messaging_context *msg_ctx,
+ struct byte_range_lock *br_lck,
+ const struct lock_struct *plock)
+{
+ bool result;
+
+ result = SMB_VFS_NEXT_BRL_UNLOCK_WINDOWS(handle, msg_ctx, br_lck,
+ plock);
+
+ do_log(SMB_VFS_OP_BRL_UNLOCK_WINDOWS, (result == 0), handle,
+ "%s:%llu-%llu:%d", br_lck->fsp->fsp_name, plock->start,
+ plock->size, plock->lock_type);
+
+ return result;
+}
+
+static bool smb_full_audit_brl_cancel_windows(struct vfs_handle_struct *handle,
+ struct byte_range_lock *br_lck,
+ struct lock_struct *plock,
+ struct blocking_lock_record *blr)
+{
+ bool result;
+
+ result = SMB_VFS_NEXT_BRL_CANCEL_WINDOWS(handle, br_lck, plock, blr);
+
+ do_log(SMB_VFS_OP_BRL_CANCEL_WINDOWS, (result == 0), handle,
+ "%s:%llu-%llu:%d", br_lck->fsp->fsp_name, plock->start,
+ plock->size);
+
+ return result;
+}
+
static NTSTATUS smb_full_audit_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
uint32 security_info,
SEC_DESC **ppdesc)
diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c
index 33aa748cdc..42849931f3 100644
--- a/source3/smbd/blocking.c
+++ b/source3/smbd/blocking.c
@@ -24,26 +24,6 @@
#define DBGC_CLASS DBGC_LOCKING
/****************************************************************************
- This is the structure to queue to implement blocking locks.
- notify. It consists of the requesting SMB and the expiry time.
-*****************************************************************************/
-
-struct blocking_lock_record {
- struct blocking_lock_record *next;
- struct blocking_lock_record *prev;
- files_struct *fsp;
- struct timeval expire_time;
- int lock_num;
- uint64_t offset;
- uint64_t count;
- uint32_t lock_pid;
- uint32_t blocking_pid; /* PID that blocks us. */
- enum brl_flavour lock_flav;
- enum brl_type lock_type;
- struct smb_request *req;
-};
-
-/****************************************************************************
Determine if this is a secondary element of a chained SMB.
**************************************************************************/
@@ -52,7 +32,6 @@ static void received_unlock_msg(struct messaging_context *msg,
uint32_t msg_type,
struct server_id server_id,
DATA_BLOB *data);
-static void process_blocking_lock_queue(void);
static void brl_timeout_fn(struct event_context *event_ctx,
struct timed_event *te,
@@ -82,14 +61,14 @@ static bool recalc_brl_timeout(void)
next_timeout = timeval_zero();
- for (brl = blocking_lock_queue; brl; brl = brl->next) {
- if (timeval_is_zero(&brl->expire_time)) {
+ for (blr = blocking_lock_queue; blr; blr = blr->next) {
+ if (timeval_is_zero(&blr->expire_time)) {
/*
* If we're blocked on pid 0xFFFFFFFF this is
* a POSIX lock, so calculate a timeout of
* 10 seconds into the future.
*/
- if (brl->blocking_pid == 0xFFFFFFFF) {
+ if (blr->blocking_pid == 0xFFFFFFFF) {
struct timeval psx_to = timeval_current_ofs(10, 0);
next_timeout = timeval_min(&next_timeout, &psx_to);
}
@@ -98,18 +77,28 @@ static bool recalc_brl_timeout(void)
}
if (timeval_is_zero(&next_timeout)) {
- next_timeout = brl->expire_time;
+ next_timeout = blr->expire_time;
}
else {
next_timeout = timeval_min(&next_timeout,
- &brl->expire_time);
+ &blr->expire_time);
}
}
if (timeval_is_zero(&next_timeout)) {
+ DEBUG(10, ("Next timeout = Infinite.\n"));
return True;
}
+ if (DEBUGLVL(10)) {
+ struct timeval cur, from_now;
+
+ cur = timeval_current();
+ from_now = timeval_until(&cur, &next_timeout);
+ DEBUG(10, ("Next timeout = %d.%d seconds from now.\n",
+ (int)from_now.tv_sec, (int)from_now.tv_usec));
+ }
+
if (!(brl_timeout = event_add_timed(smbd_event_context(), NULL,
next_timeout,
brl_timeout_fn, NULL))) {
@@ -173,9 +162,13 @@ bool push_blocking_lock_request( struct byte_range_lock *br_lck,
blr->lock_type = lock_type;
blr->offset = offset;
blr->count = count;
+
+ /* Specific brl_lock() implementations can fill this in. */
+ blr->blr_private = NULL;
/* Add a pending lock record for this. */
- status = brl_lock(smbd_messaging_context(), br_lck,
+ status = brl_lock(smbd_messaging_context(),
+ br_lck,
lock_pid,
procid_self(),
offset,
@@ -183,11 +176,11 @@ bool push_blocking_lock_request( struct byte_range_lock *br_lck,
lock_type == READ_LOCK ? PENDING_READ_LOCK : PENDING_WRITE_LOCK,
blr->lock_flav,
lock_timeout ? True : False, /* blocking_lock. */
- NULL);
+ NULL,
+ blr);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("push_blocking_lock_request: failed to add PENDING_LOCK record.\n"));
- DLIST_REMOVE(blocking_lock_queue, blr);
TALLOC_FREE(blr);
return False;
}
@@ -332,6 +325,8 @@ static void reply_lockingX_error(struct blocking_lock_record *blr, NTSTATUS stat
static void blocking_lock_reply_error(struct blocking_lock_record *blr, NTSTATUS status)
{
+ DEBUG(10, ("Replying with error=%s. BLR = %p\n", nt_errstr(status), blr));
+
switch(blr->req->cmd) {
case SMBlockingX:
reply_lockingX_error(blr, status);
@@ -409,7 +404,8 @@ static bool process_lockingX(struct blocking_lock_record *blr)
WINDOWS_LOCK,
True,
&status,
- &blr->blocking_pid);
+ &blr->blocking_pid,
+ blr);
TALLOC_FREE(br_lck);
@@ -470,7 +466,8 @@ static bool process_trans2(struct blocking_lock_record *blr)
blr->lock_flav,
True,
&status,
- &blr->blocking_pid);
+ &blr->blocking_pid,
+ blr);
TALLOC_FREE(br_lck);
if (!NT_STATUS_IS_OK(status)) {
@@ -521,7 +518,7 @@ static bool blocking_lock_record_process(struct blocking_lock_record *blr)
void cancel_pending_lock_requests_by_fid(files_struct *fsp, struct byte_range_lock *br_lck)
{
- struct blocking_lock_record *blr, *next = NULL;
+ struct blocking_lock_record *blr, *blr_cancelled, *next = NULL;
for(blr = blocking_lock_queue; blr; blr = next) {
unsigned char locktype = 0;
@@ -539,14 +536,7 @@ void cancel_pending_lock_requests_by_fid(files_struct *fsp, struct byte_range_lo
"request type %d for file %s fnum = %d\n",
blr->req->cmd, fsp->fsp_name, fsp->fnum));
- brl_lock_cancel(br_lck,
- blr->lock_pid,
- procid_self(),
- blr->offset,
- blr->count,
- blr->lock_flav);
-
- blocking_lock_cancel(fsp,
+ blr_cancelled = blocking_lock_cancel(fsp,
blr->lock_pid,
blr->offset,
blr->count,
@@ -554,6 +544,16 @@ void cancel_pending_lock_requests_by_fid(files_struct *fsp, struct byte_range_lo
locktype,
NT_STATUS_RANGE_NOT_LOCKED);
+ SMB_ASSERT(blr_cancelled == blr);
+
+ brl_lock_cancel(br_lck,
+ blr->lock_pid,
+ procid_self(),
+ blr->offset,
+ blr->count,
+ blr->lock_flav,
+ blr);
+
/* We're closing the file fsp here, so ensure
* we don't have a dangling pointer. */
blr->fsp = NULL;
@@ -592,7 +592,8 @@ void remove_pending_lock_requests_by_mid(int mid)
procid_self(),
blr->offset,
blr->count,
- blr->lock_flav);
+ blr->lock_flav,
+ blr);
TALLOC_FREE(br_lck);
}
@@ -637,7 +638,7 @@ static void received_unlock_msg(struct messaging_context *msg,
Process the blocking lock queue. Note that this is only called as root.
*****************************************************************************/
-static void process_blocking_lock_queue(void)
+void process_blocking_lock_queue(void)
{
struct timeval tv_curr = timeval_current();
struct blocking_lock_record *blr, *next = NULL;
@@ -657,17 +658,23 @@ static void process_blocking_lock_queue(void)
* and False if we still need to wait.
*/
+ DEBUG(10, ("Processing BLR = %p\n", blr));
+
if(blocking_lock_record_process(blr)) {
struct byte_range_lock *br_lck = brl_get_locks(
talloc_tos(), blr->fsp);
+ DEBUG(10, ("BLR_process returned true: cancelling and "
+ "removing lock. BLR = %p\n", blr));
+
if (br_lck) {
brl_lock_cancel(br_lck,
blr->lock_pid,
procid_self(),
blr->offset,
blr->count,
- blr->lock_flav);
+ blr->lock_flav,
+ blr);
TALLOC_FREE(br_lck);
}
@@ -686,6 +693,8 @@ static void process_blocking_lock_queue(void)
struct byte_range_lock *br_lck = brl_get_locks(
talloc_tos(), blr->fsp);
+ DEBUG(10, ("Lock timed out! BLR = %p\n", blr));
+
/*
* Lock expired - throw away all previously
* obtained locks and return lock error.
@@ -702,7 +711,8 @@ static void process_blocking_lock_queue(void)
procid_self(),
blr->offset,
blr->count,
- blr->lock_flav);
+ blr->lock_flav,
+ blr);
TALLOC_FREE(br_lck);
}
@@ -757,9 +767,10 @@ static void process_blocking_lock_cancel_message(struct messaging_context *ctx,
/****************************************************************************
Send ourselves a blocking lock cancelled message. Handled asynchronously above.
+ Returns the blocking_lock_record that is being cancelled.
*****************************************************************************/
-bool blocking_lock_cancel(files_struct *fsp,
+struct blocking_lock_record *blocking_lock_cancel(files_struct *fsp,
uint32 lock_pid,
uint64_t offset,
uint64_t count,
@@ -790,14 +801,14 @@ bool blocking_lock_cancel(files_struct *fsp,
}
if (!blr) {
- return False;
+ return NULL;
}
/* Check the flags are right. */
if (blr->req->cmd == SMBlockingX &&
(locktype & LOCKING_ANDX_LARGE_FILES) !=
(CVAL(blr->req->vwv+3, 0) & LOCKING_ANDX_LARGE_FILES)) {
- return False;
+ return NULL;
}
/* Move to cancelled queue. */
@@ -812,5 +823,5 @@ bool blocking_lock_cancel(files_struct *fsp,
MSG_SMB_BLOCKING_LOCK_CANCEL,
(uint8 *)&msg, sizeof(msg));
- return True;
+ return blr;
}
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 256160c402..1ed5e7229e 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -3040,6 +3040,7 @@ void reply_lockread(struct smb_request *req)
WINDOWS_LOCK,
False, /* Non-blocking lock. */
&status,
+ NULL,
NULL);
TALLOC_FREE(br_lck);
@@ -4514,6 +4515,7 @@ void reply_lock(struct smb_request *req)
WINDOWS_LOCK,
False, /* Non-blocking lock. */
&status,
+ NULL,
NULL);
TALLOC_FREE(br_lck);
@@ -6904,6 +6906,9 @@ void reply_lockingX(struct smb_request *req)
offset,
WINDOWS_LOCK);
+ DEBUG(10, ("reply_lockingX: unlock returned %s\n",
+ nt_errstr(status)));
+
if (NT_STATUS_V(status)) {
END_PROFILE(SMBlockingX);
reply_nterror(req, status);
@@ -6945,19 +6950,22 @@ void reply_lockingX(struct smb_request *req)
fsp->fsp_name, (int)lock_timeout ));
if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
+ struct blocking_lock_record *blr;
+
if (lp_blocking_locks(SNUM(conn))) {
/* Schedule a message to ourselves to
remove the blocking lock record and
return the right error. */
- if (!blocking_lock_cancel(fsp,
+ blr = blocking_lock_cancel(fsp,
lock_pid,
offset,
count,
WINDOWS_LOCK,
locktype,
- NT_STATUS_FILE_LOCK_CONFLICT)) {
+ NT_STATUS_FILE_LOCK_CONFLICT);
+ if (blr == NULL) {
END_PROFILE(SMBlockingX);
reply_nterror(
req,
@@ -6972,7 +6980,8 @@ void reply_lockingX(struct smb_request *req)
lock_pid,
count,
offset,
- WINDOWS_LOCK);
+ WINDOWS_LOCK,
+ blr);
} else {
bool blocking_lock = lock_timeout ? True : False;
bool defer_lock = False;
@@ -6988,7 +6997,8 @@ void reply_lockingX(struct smb_request *req)
WINDOWS_LOCK,
blocking_lock,
&status,
- &block_smbpid);
+ &block_smbpid,
+ NULL);
if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
/* Windows internal resolution for blocking locks seems
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index cea066e97f..759e520866 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -5628,7 +5628,8 @@ static NTSTATUS smb_set_posix_lock(connection_struct *conn,
POSIX_LOCK,
blocking_lock,
&status,
- &block_smbpid);
+ &block_smbpid,
+ NULL);
if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
/*