s3: Add strict lock/unlock calls to the vfs layer to replace is_locked
authorDave Richards <dave.richards@isilon.com>
Fri, 13 Mar 2009 21:15:28 +0000 (14:15 -0700)
committerTim Prouty <tprouty@samba.org>
Fri, 13 Mar 2009 21:16:55 +0000 (14:16 -0700)
source3/include/proto.h
source3/include/smbprofile.h
source3/include/vfs.h
source3/include/vfs_macros.h
source3/locking/locking.c
source3/modules/vfs_default.c
source3/modules/vfs_full_audit.c
source3/smbd/reply.c

index 9badb95a1c2355d97946df50f5b0261eea91b1c9..581157406885bea29bc8642df0b403a3cf530b5b 100644 (file)
@@ -3409,11 +3409,16 @@ void brl_register_msgs(struct messaging_context *msg_ctx);
 
 const char *lock_type_name(enum brl_type lock_type);
 const char *lock_flav_name(enum brl_flavour lock_flav);
-bool is_locked(files_struct *fsp,
-               uint32 smbpid,
-               uint64_t count,
-               uint64_t offset, 
-               enum brl_type lock_type);
+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);
+bool strict_lock_default(files_struct *fsp,
+                               struct lock_struct *plock);
+void strict_unlock_default(files_struct *fsp,
+                               struct lock_struct *plock);
 NTSTATUS query_lock(files_struct *fsp,
                        uint32 *psmbpid,
                        uint64_t *pcount,
index f9a0436546fa52355b43b427d529cec215114750..5b52bad8c1aea5d39b8b635c218a4caf0818f2f1 100644 (file)
@@ -243,6 +243,14 @@ enum profile_stats_values
 #define syscall_brl_cancel_count __profile_stats_value(PR_VALUE_SYSCALL_BRL_CANCEL, count)
 #define syscall_brl_cancel_time __profile_stats_value(PR_VALUE_SYSCALL_BRL_CANCEL, time)
 
+       PR_VALUE_SYSCALL_STRICT_LOCK,
+#define syscall_strict_lock_count __profile_stats_value(PR_VALUE_SYSCALL_STRICT_LOCK, count)
+#define syscall_strict_lock_time __profile_stats_value(PR_VALUE_SYSCALL_STRICT_LOCK, time)
+
+       PR_VALUE_SYSCALL_STRICT_UNLOCK,
+#define syscall_strict_unlock_count __profile_stats_value(PR_VALUE_SYSCALL_STRICT_UNLOCK, count)
+#define syscall_strict_unlock_time __profile_stats_value(PR_VALUE_SYSCALL_STRICT_UNLOCK, time)
+
 /* counters for individual SMB types */
        PR_VALUE_SMBMKDIR,
 #define SMBmkdir_count __profile_stats_value(PR_VALUE_SMBMKDIR, count)
index 0ee7f236b07346d780f1401cbcb3ad78b1cbf9da..0c0e0938bd823fbaee9b43a1461ad79f171b2dcc 100644 (file)
 /* 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. */
+/* Leave at 25 - not yet released. Add strict locking calls. -- drichards. */
 
 #define SMB_VFS_INTERFACE_VERSION 25
 
@@ -223,6 +224,8 @@ typedef enum _vfs_op_type {
        SMB_VFS_OP_BRL_LOCK_WINDOWS,
        SMB_VFS_OP_BRL_UNLOCK_WINDOWS,
        SMB_VFS_OP_BRL_CANCEL_WINDOWS,
+       SMB_VFS_OP_STRICT_LOCK,
+       SMB_VFS_OP_STRICT_UNLOCK,
 
        /* NT ACL operations. */
 
@@ -415,6 +418,14 @@ struct vfs_ops {
                                           struct lock_struct *plock,
                                           struct blocking_lock_record *blr);
 
+               bool (*strict_lock)(struct vfs_handle_struct *handle,
+                                       struct files_struct *fsp,
+                                       struct lock_struct *plock);
+
+               void (*strict_unlock)(struct vfs_handle_struct *handle,
+                                       struct files_struct *fsp,
+                                       struct lock_struct *plock);
+
                /* NT ACL operations. */
 
                NTSTATUS (*fget_nt_acl)(struct vfs_handle_struct *handle,
@@ -556,6 +567,8 @@ struct vfs_ops {
                struct vfs_handle_struct *brl_lock_windows;
                struct vfs_handle_struct *brl_unlock_windows;
                struct vfs_handle_struct *brl_cancel_windows;
+               struct vfs_handle_struct *strict_lock;
+               struct vfs_handle_struct *strict_unlock;
 
                /* NT ACL operations. */
 
index 7dacd2319ab980ee932ba2614582d6975178f535..acb158e3a5a975d46a8b1410d1822cf4bd968ddf 100644 (file)
@@ -91,6 +91,8 @@
 #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)))
+#define SMB_VFS_STRICT_LOCK(conn, fsp, plock) ((conn)->vfs.ops.strict_lock((conn)->vfs.handles.strict_lock, (fsp), (plock)))
+#define SMB_VFS_STRICT_UNLOCK(conn, fsp, plock) ((conn)->vfs.ops.strict_unlock((conn)->vfs.handles.strict_unlock, (fsp), (plock)))
 
 /* 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)))
 #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)))
+#define SMB_VFS_OPAQUE_STRICT_LOCK(conn, fsp, plock) ((conn)->vfs_opaque.ops.strict_lock((conn)->vfs_opaque.handles.strict_lock, (fsp), (plock)))
+#define SMB_VFS_OPAQUE_STRICT_UNLOCK(conn, fsp, plock) ((conn)->vfs_opaque.ops.strict_unlock((conn)->vfs_opaque.handles.strict_unlock, (fsp), (plock)))
 
 /* 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)))
 #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)))
+#define SMB_VFS_NEXT_STRICT_LOCK(handle, fsp, plock) ((handle)->vfs_next.ops.strict_lock((handle)->vfs_next.handles.strict_lock, (fsp), (plock)))
+#define SMB_VFS_NEXT_STRICT_UNLOCK(handle, fsp, plock) ((handle)->vfs_next.ops.strict_unlock((handle)->vfs_next.handles.strict_unlock, (fsp), (plock)))
 
 /* 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)))
index e9a5f757e517f20b65e47ca50812c20f7d7041e3..bafb89522affa7752921145fb829dd2f83b093e1 100644 (file)
@@ -75,69 +75,89 @@ const char *lock_flav_name(enum brl_flavour lock_flav)
  Called in the read/write codepath.
 ****************************************************************************/
 
-bool is_locked(files_struct *fsp,
-               uint32 smbpid,
-               uint64_t count,
-               uint64_t offset, 
-               enum brl_type lock_type)
+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);
-       enum brl_flavour lock_flav = lp_posix_cifsu_locktype(fsp);
-       bool ret = True;
-       
-       if (count == 0) {
-               return False;
+       bool ret = False;
+
+       if (plock->size == 0) {
+               return True;
        }
 
        if (!lp_locking(fsp->conn->params) || !strict_locking) {
-               return False;
+               return True;
        }
 
        if (strict_locking == Auto) {
-               if  (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && (lock_type == READ_LOCK || lock_type == WRITE_LOCK)) {
+               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->fsp_name ));
-                       ret = False;
+                       ret = True;
                } else if ((fsp->oplock_type == LEVEL_II_OPLOCK) &&
-                          (lock_type == READ_LOCK)) {
+                          (plock->lock_type == READ_LOCK)) {
                        DEBUG(10,("is_locked: optimisation - level II oplock on file %s\n", fsp->fsp_name ));
-                       ret = False;
+                       ret = True;
                } else {
                        struct byte_range_lock *br_lck = brl_get_locks_readonly(talloc_tos(), fsp);
                        if (!br_lck) {
-                               return False;
+                               return True;
                        }
-                       ret = !brl_locktest(br_lck,
-                                       smbpid,
-                                       procid_self(),
-                                       offset,
-                                       count,
-                                       lock_type,
-                                       lock_flav);
+                       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 False;
+                       return True;
                }
-               ret = !brl_locktest(br_lck,
-                               smbpid,
-                               procid_self(),
-                               offset,
-                               count,
-                               lock_type,
-                               lock_flav);
+               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,("is_locked: flavour = %s brl start=%.0f len=%.0f %s for fnum %d file %s\n",
-                       lock_flav_name(lock_flav),
-                       (double)offset, (double)count, ret ? "locked" : "unlocked",
-                       fsp->fnum, fsp->fsp_name ));
+       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->fsp_name ));
 
        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.
 ****************************************************************************/
index 7384268dae405587c9faa21e535760c57be3db82..a4973df2995f4a42f03a16bbbc65e2f526698aa4 100644 (file)
@@ -1157,6 +1157,26 @@ static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
        return brl_lock_cancel_default(br_lck, plock);
 }
 
+static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
+                               files_struct *fsp,
+                               struct lock_struct *plock)
+{
+       SMB_ASSERT(plock->lock_type == READ_LOCK ||
+           plock->lock_type == WRITE_LOCK);
+
+       return strict_lock_default(fsp, plock);
+}
+
+static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
+                               files_struct *fsp,
+                               struct lock_struct *plock)
+{
+       SMB_ASSERT(plock->lock_type == READ_LOCK ||
+           plock->lock_type == WRITE_LOCK);
+
+       return strict_unlock_default(fsp, plock);
+}
+
 /* NT ACL operations. */
 
 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
@@ -1592,6 +1612,10 @@ static vfs_op_tuple vfs_default_ops[] = {
         SMB_VFS_LAYER_OPAQUE},
        {SMB_VFS_OP(vfswrap_brl_cancel_windows),SMB_VFS_OP_BRL_CANCEL_WINDOWS,
         SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_strict_lock),       SMB_VFS_OP_STRICT_LOCK,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_strict_unlock),     SMB_VFS_OP_STRICT_UNLOCK,
+        SMB_VFS_LAYER_OPAQUE},
 
        /* NT ACL operations. */
 
index 3c159f10eb1ec1369873fe493134ad155e8a382d..ebe89ec5fd82a46aa275722eac44317914c40dc1 100644 (file)
@@ -234,6 +234,12 @@ 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 bool smb_full_audit_strict_lock(struct vfs_handle_struct *handle,
+                                      struct files_struct *fsp,
+                                      struct lock_struct *plock);
+static void smb_full_audit_strict_unlock(struct vfs_handle_struct *handle,
+                                        struct files_struct *fsp,
+                                        struct lock_struct *plock);
 static NTSTATUS smb_full_audit_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
                                uint32 security_info,
                                SEC_DESC **ppdesc);
@@ -483,6 +489,10 @@ static vfs_op_tuple audit_op_tuples[] = {
         SMB_VFS_LAYER_LOGGER},
        {SMB_VFS_OP(smb_full_audit_brl_cancel_windows), SMB_VFS_OP_BRL_CANCEL_WINDOWS,
         SMB_VFS_LAYER_LOGGER},
+       {SMB_VFS_OP(smb_full_audit_strict_lock), SMB_VFS_OP_STRICT_LOCK,
+        SMB_VFS_LAYER_LOGGER},
+       {SMB_VFS_OP(smb_full_audit_strict_unlock), SMB_VFS_OP_STRICT_UNLOCK,
+        SMB_VFS_LAYER_LOGGER},
 
        /* NT ACL operations. */
 
@@ -660,6 +670,8 @@ static struct {
        { 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_STRICT_LOCK, "strict_lock" },
+       { SMB_VFS_OP_STRICT_UNLOCK, "strict_unlock" },
        { 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" },
@@ -1766,6 +1778,34 @@ static bool smb_full_audit_brl_cancel_windows(struct vfs_handle_struct *handle,
        return result;
 }
 
+static bool smb_full_audit_strict_lock(struct vfs_handle_struct *handle,
+                                      struct files_struct *fsp,
+                                      struct lock_struct *plock)
+{
+       bool result;
+
+       result = SMB_VFS_NEXT_STRICT_LOCK(handle, fsp, plock);
+
+       do_log(SMB_VFS_OP_STRICT_LOCK, result, handle,
+           "%s:%llu-%llu:%d", fsp->fsp_name, plock->start,
+           plock->size);
+
+       return result;
+}
+
+static void smb_full_audit_strict_unlock(struct vfs_handle_struct *handle,
+                                        struct files_struct *fsp,
+                                        struct lock_struct *plock)
+{
+       SMB_VFS_NEXT_STRICT_UNLOCK(handle, fsp, plock);
+
+       do_log(SMB_VFS_OP_STRICT_UNLOCK, true, handle,
+           "%s:%llu-%llu:%d", fsp->fsp_name, plock->start,
+           plock->size);
+
+       return;
+}
+
 static NTSTATUS smb_full_audit_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
                                uint32 security_info,
                                SEC_DESC **ppdesc)
index 22e4c1aad7fb6b50ef9f0bb633f9b68e3933f6da..a743385f7f51fa7c454f66875ba4fd7a19ba1104 100644 (file)
@@ -2859,6 +2859,7 @@ void reply_readbraw(struct smb_request *req)
        size_t nread = 0;
        SMB_OFF_T startpos;
        files_struct *fsp;
+       struct lock_struct lock;
        SMB_STRUCT_STAT st;
        SMB_OFF_T size = 0;
 
@@ -2959,10 +2960,11 @@ void reply_readbraw(struct smb_request *req)
        /* ensure we don't overrun the packet size */
        maxcount = MIN(65535,maxcount);
 
-       if (is_locked(fsp,(uint32)req->smbpid,
-                       (uint64_t)maxcount,
-                       (uint64_t)startpos,
-                       READ_LOCK)) {
+       init_strict_lock_struct(fsp, (uint32)req->smbpid,
+           (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
+           &lock);
+
+       if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
                reply_readbraw_error();
                END_PROFILE(SMBreadbraw);
                return;
@@ -2993,7 +2995,11 @@ void reply_readbraw(struct smb_request *req)
        send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
 
        DEBUG(5,("reply_readbraw finished\n"));
+
+       SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
+
        END_PROFILE(SMBreadbraw);
+       return;
 }
 
 #undef DBGC_CLASS
@@ -3121,6 +3127,7 @@ void reply_read(struct smb_request *req)
        SMB_OFF_T startpos;
        int outsize = 0;
        files_struct *fsp;
+       struct lock_struct lock;
 
        START_PROFILE(SMBread);
 
@@ -3162,8 +3169,11 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n",
 
        data = smb_buf(req->outbuf) + 3;
 
-       if (is_locked(fsp, (uint32)req->smbpid, (uint64_t)numtoread,
-                     (uint64_t)startpos, READ_LOCK)) {
+       init_strict_lock_struct(fsp, (uint32)req->smbpid,
+           (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
+           &lock);
+
+       if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
                reply_doserror(req, ERRDOS,ERRlock);
                END_PROFILE(SMBread);
                return;
@@ -3174,8 +3184,7 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n",
 
        if (nread < 0) {
                reply_unixerror(req, ERRDOS,ERRnoaccess);
-               END_PROFILE(SMBread);
-               return;
+               goto strict_unlock;
        }
 
        srv_set_message((char *)req->outbuf, 5, nread+3, False);
@@ -3188,6 +3197,9 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n",
        DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
                fsp->fnum, (int)numtoread, (int)nread ) );
 
+strict_unlock:
+       SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
+
        END_PROFILE(SMBread);
        return;
 }
@@ -3387,6 +3399,7 @@ void reply_read_and_X(struct smb_request *req)
        files_struct *fsp;
        SMB_OFF_T startpos;
        size_t smb_maxcnt;
+       struct lock_struct lock;
        bool big_readX = False;
 #if 0
        size_t smb_mincnt = SVAL(req->vwv+6, 0);
@@ -3474,8 +3487,11 @@ void reply_read_and_X(struct smb_request *req)
 
        }
 
-       if (is_locked(fsp, (uint32)req->smbpid, (uint64_t)smb_maxcnt,
-                     (uint64_t)startpos, READ_LOCK)) {
+       init_strict_lock_struct(fsp, (uint32)req->smbpid,
+           (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
+           &lock);
+
+       if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
                END_PROFILE(SMBreadX);
                reply_doserror(req, ERRDOS, ERRlock);
                return;
@@ -3483,12 +3499,14 @@ void reply_read_and_X(struct smb_request *req)
 
        if (!big_readX &&
            schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
-               END_PROFILE(SMBreadX);
-               return;
+               goto strict_unlock;
        }
 
        send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
 
+strict_unlock:
+       SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
+
        END_PROFILE(SMBreadX);
        return;
 }
@@ -3523,6 +3541,7 @@ void reply_writebraw(struct smb_request *req)
        char *data=NULL;
        bool write_through;
        files_struct *fsp;
+       struct lock_struct lock;
        NTSTATUS status;
 
        START_PROFILE(SMBwritebraw);
@@ -3584,8 +3603,11 @@ void reply_writebraw(struct smb_request *req)
                return;
        }
 
-       if (is_locked(fsp,(uint32)req->smbpid,(uint64_t)tcount,
-                               (uint64_t)startpos, WRITE_LOCK)) {
+       init_strict_lock_struct(fsp, (uint32)req->smbpid,
+           (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
+           &lock);
+
+       if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
                reply_doserror(req, ERRDOS, ERRlock);
                error_to_writebrawerr(req);
                END_PROFILE(SMBwritebraw);
@@ -3604,8 +3626,7 @@ void reply_writebraw(struct smb_request *req)
        if (nwritten < (ssize_t)numtowrite)  {
                reply_unixerror(req, ERRHRD, ERRdiskfull);
                error_to_writebrawerr(req);
-               END_PROFILE(SMBwritebraw);
-               return;
+               goto strict_unlock;
        }
 
        total_written = nwritten;
@@ -3615,8 +3636,7 @@ void reply_writebraw(struct smb_request *req)
        if (!buf) {
                reply_doserror(req, ERRDOS, ERRnomem);
                error_to_writebrawerr(req);
-               END_PROFILE(SMBwritebraw);
-               return;
+               goto strict_unlock;
        }
 
        /* Return a SMBwritebraw message to the redirector to tell
@@ -3674,8 +3694,7 @@ void reply_writebraw(struct smb_request *req)
                        TALLOC_FREE(buf);
                        reply_unixerror(req, ERRHRD, ERRdiskfull);
                        error_to_writebrawerr(req);
-                       END_PROFILE(SMBwritebraw);
-                       return;
+                       goto strict_unlock;
                }
 
                if (nwritten < (ssize_t)numtowrite) {
@@ -3697,8 +3716,7 @@ void reply_writebraw(struct smb_request *req)
                        fsp->fsp_name, nt_errstr(status) ));
                reply_nterror(req, status);
                error_to_writebrawerr(req);
-               END_PROFILE(SMBwritebraw);
-               return;
+               goto strict_unlock;
        }
 
        DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
@@ -3706,6 +3724,8 @@ void reply_writebraw(struct smb_request *req)
                fsp->fnum, (double)startpos, (int)numtowrite,
                (int)total_written));
 
+       SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
+
        /* We won't return a status if write through is not selected - this
         * follows what WfWg does */
        END_PROFILE(SMBwritebraw);
@@ -3726,6 +3746,12 @@ void reply_writebraw(struct smb_request *req)
                TALLOC_FREE(req->outbuf);
        }
        return;
+
+strict_unlock:
+       SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
+
+       END_PROFILE(SMBwritebraw);
+       return;
 }
 
 #undef DBGC_CLASS
@@ -3744,6 +3770,7 @@ void reply_writeunlock(struct smb_request *req)
        const char *data;
        NTSTATUS status = NT_STATUS_OK;
        files_struct *fsp;
+       struct lock_struct lock;
 
        START_PROFILE(SMBwriteunlock);
 
@@ -3770,12 +3797,16 @@ void reply_writeunlock(struct smb_request *req)
        startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
        data = (const char *)req->buf + 3;
 
-       if (numtowrite
-           && is_locked(fsp, (uint32)req->smbpid, (uint64_t)numtowrite,
-                        (uint64_t)startpos, WRITE_LOCK)) {
-               reply_doserror(req, ERRDOS, ERRlock);
-               END_PROFILE(SMBwriteunlock);
-               return;
+       if (numtowrite) {
+               init_strict_lock_struct(fsp, (uint32)req->smbpid,
+                   (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
+                   &lock);
+
+               if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
+                       reply_doserror(req, ERRDOS, ERRlock);
+                       END_PROFILE(SMBwriteunlock);
+                       return;
+               }
        }
 
        /* The special X/Open SMB protocol handling of
@@ -3792,14 +3823,12 @@ void reply_writeunlock(struct smb_request *req)
                DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
                        fsp->fsp_name, nt_errstr(status) ));
                reply_nterror(req, status);
-               END_PROFILE(SMBwriteunlock);
-               return;
+               goto strict_unlock;
        }
 
        if(((nwritten < numtowrite) && (numtowrite != 0))||(nwritten < 0)) {
                reply_unixerror(req, ERRHRD, ERRdiskfull);
-               END_PROFILE(SMBwriteunlock);
-               return;
+               goto strict_unlock;
        }
 
        if (numtowrite) {
@@ -3812,8 +3841,7 @@ void reply_writeunlock(struct smb_request *req)
 
                if (NT_STATUS_V(status)) {
                        reply_nterror(req, status);
-                       END_PROFILE(SMBwriteunlock);
-                       return;
+                       goto strict_unlock;
                }
        }
 
@@ -3824,6 +3852,11 @@ void reply_writeunlock(struct smb_request *req)
        DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
                 fsp->fnum, (int)numtowrite, (int)nwritten));
 
+strict_unlock:
+       if (numtowrite) {
+               SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
+       }
+
        END_PROFILE(SMBwriteunlock);
        return;
 }
@@ -3843,6 +3876,7 @@ void reply_write(struct smb_request *req)
        SMB_OFF_T startpos;
        const char *data;
        files_struct *fsp;
+       struct lock_struct lock;
        NTSTATUS status;
 
        START_PROFILE(SMBwrite);
@@ -3877,8 +3911,11 @@ void reply_write(struct smb_request *req)
        startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
        data = (const char *)req->buf + 3;
 
-       if (is_locked(fsp, (uint32)req->smbpid, (uint64_t)numtowrite,
-                     (uint64_t)startpos, WRITE_LOCK)) {
+       init_strict_lock_struct(fsp, (uint32)req->smbpid,
+           (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
+           &lock);
+
+       if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
                reply_doserror(req, ERRDOS, ERRlock);
                END_PROFILE(SMBwrite);
                return;
@@ -3897,14 +3934,12 @@ void reply_write(struct smb_request *req)
                nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
                if (nwritten < 0) {
                        reply_nterror(req, NT_STATUS_DISK_FULL);
-                       END_PROFILE(SMBwrite);
-                       return;
+                       goto strict_unlock;
                }
                nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
                if (nwritten < 0) {
                        reply_nterror(req, NT_STATUS_DISK_FULL);
-                       END_PROFILE(SMBwrite);
-                       return;
+                       goto strict_unlock;
                }
                trigger_write_time_update_immediate(fsp);
        } else {
@@ -3916,14 +3951,12 @@ void reply_write(struct smb_request *req)
                DEBUG(5,("reply_write: sync_file for %s returned %s\n",
                        fsp->fsp_name, nt_errstr(status) ));
                reply_nterror(req, status);
-               END_PROFILE(SMBwrite);
-               return;
+               goto strict_unlock;
        }
 
        if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
                reply_unixerror(req, ERRHRD, ERRdiskfull);
-               END_PROFILE(SMBwrite);
-               return;
+               goto strict_unlock;
        }
 
        reply_outbuf(req, 1, 0);
@@ -3937,6 +3970,9 @@ void reply_write(struct smb_request *req)
 
        DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
 
+strict_unlock:
+       SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
+
        END_PROFILE(SMBwrite);
        return;
 }
@@ -4034,6 +4070,7 @@ void reply_write_and_X(struct smb_request *req)
 {
        connection_struct *conn = req->conn;
        files_struct *fsp;
+       struct lock_struct lock;
        SMB_OFF_T startpos;
        size_t numtowrite;
        bool write_through;
@@ -4136,9 +4173,11 @@ void reply_write_and_X(struct smb_request *req)
 #endif /* LARGE_SMB_OFF_T */
        }
 
-       if (is_locked(fsp,(uint32)req->smbpid,
-                     (uint64_t)numtowrite,
-                     (uint64_t)startpos, WRITE_LOCK)) {
+       init_strict_lock_struct(fsp, (uint32)req->smbpid,
+           (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
+           &lock);
+
+       if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
                reply_doserror(req, ERRDOS, ERRlock);
                END_PROFILE(SMBwriteX);
                return;
@@ -4156,8 +4195,7 @@ void reply_write_and_X(struct smb_request *req)
                if ((req->unread_bytes == 0) &&
                    schedule_aio_write_and_X(conn, req, fsp, data, startpos,
                                             numtowrite)) {
-                       END_PROFILE(SMBwriteX);
-                       return;
+                       goto strict_unlock;
                }
 
                nwritten = write_file(req,fsp,data,startpos,numtowrite);
@@ -4165,8 +4203,7 @@ void reply_write_and_X(struct smb_request *req)
 
        if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
                reply_unixerror(req, ERRHRD, ERRdiskfull);
-               END_PROFILE(SMBwriteX);
-               return;
+               goto strict_unlock;
        }
 
        reply_outbuf(req, 6, 0);
@@ -4186,13 +4223,20 @@ void reply_write_and_X(struct smb_request *req)
                DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
                        fsp->fsp_name, nt_errstr(status) ));
                reply_nterror(req, status);
-               END_PROFILE(SMBwriteX);
-               return;
+               goto strict_unlock;
        }
 
+       SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
+
        END_PROFILE(SMBwriteX);
        chain_reply(req);
        return;
+
+strict_unlock:
+       SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
+
+       END_PROFILE(SMBwriteX);
+       return;
 }
 
 /****************************************************************************
@@ -4432,6 +4476,7 @@ void reply_writeclose(struct smb_request *req)
        const char *data;
        struct timespec mtime;
        files_struct *fsp;
+       struct lock_struct lock;
 
        START_PROFILE(SMBwriteclose);
 
@@ -4458,12 +4503,16 @@ void reply_writeclose(struct smb_request *req)
        mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
        data = (const char *)req->buf + 1;
 
-       if (numtowrite
-           && is_locked(fsp, (uint32)req->smbpid, (uint64_t)numtowrite,
-                        (uint64_t)startpos, WRITE_LOCK)) {
-               reply_doserror(req, ERRDOS,ERRlock);
-               END_PROFILE(SMBwriteclose);
-               return;
+       if (numtowrite) {
+               init_strict_lock_struct(fsp, (uint32)req->smbpid,
+                   (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
+                   &lock);
+
+               if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
+                       reply_doserror(req, ERRDOS,ERRlock);
+                       END_PROFILE(SMBwriteclose);
+                       return;
+               }
        }
 
        nwritten = write_file(req,fsp,data,startpos,numtowrite);
@@ -4487,19 +4536,23 @@ void reply_writeclose(struct smb_request *req)
 
        if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
                reply_doserror(req, ERRHRD, ERRdiskfull);
-               END_PROFILE(SMBwriteclose);
-               return;
+               goto strict_unlock;
        }
 
        if(!NT_STATUS_IS_OK(close_status)) {
                reply_nterror(req, close_status);
-               END_PROFILE(SMBwriteclose);
-               return;
+               goto strict_unlock;
        }
 
        reply_outbuf(req, 1, 0);
 
        SSVAL(req->outbuf,smb_vwv0,nwritten);
+
+strict_unlock:
+       if (numtowrite) {
+               SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
+       }
+
        END_PROFILE(SMBwriteclose);
        return;
 }