From 1fcc11ff25f1c3e7586b13b24e5d0eec4ccfaedc Mon Sep 17 00:00:00 2001 From: Dave Richards Date: Fri, 13 Mar 2009 14:15:28 -0700 Subject: s3: Add strict lock/unlock calls to the vfs layer to replace is_locked --- source3/include/proto.h | 15 ++-- source3/include/smbprofile.h | 8 ++ source3/include/vfs.h | 13 +++ source3/include/vfs_macros.h | 6 ++ source3/locking/locking.c | 90 ++++++++++++-------- source3/modules/vfs_default.c | 24 ++++++ source3/modules/vfs_full_audit.c | 40 +++++++++ source3/smbd/reply.c | 179 +++++++++++++++++++++++++-------------- 8 files changed, 272 insertions(+), 103 deletions(-) diff --git a/source3/include/proto.h b/source3/include/proto.h index 9badb95a1c..5811574068 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -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, diff --git a/source3/include/smbprofile.h b/source3/include/smbprofile.h index f9a0436546..5b52bad8c1 100644 --- a/source3/include/smbprofile.h +++ b/source3/include/smbprofile.h @@ -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) diff --git a/source3/include/vfs.h b/source3/include/vfs.h index 0ee7f236b0..0c0e0938bd 100644 --- a/source3/include/vfs.h +++ b/source3/include/vfs.h @@ -116,6 +116,7 @@ /* 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. */ diff --git a/source3/include/vfs_macros.h b/source3/include/vfs_macros.h index 7dacd2319a..acb158e3a5 100644 --- a/source3/include/vfs_macros.h +++ b/source3/include/vfs_macros.h @@ -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))) @@ -223,6 +225,8 @@ #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))) @@ -356,6 +360,8 @@ #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))) diff --git a/source3/locking/locking.c b/source3/locking/locking.c index e9a5f757e5..bafb89522a 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -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. ****************************************************************************/ diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c index 7384268dae..a4973df299 100644 --- a/source3/modules/vfs_default.c +++ b/source3/modules/vfs_default.c @@ -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. */ diff --git a/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c index 3c159f10eb..ebe89ec5fd 100644 --- a/source3/modules/vfs_full_audit.c +++ b/source3/modules/vfs_full_audit.c @@ -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) diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 22e4c1aad7..a743385f7f 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -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; } -- cgit