diff options
| -rw-r--r-- | source3/include/proto.h | 15 | ||||
| -rw-r--r-- | source3/include/smbprofile.h | 8 | ||||
| -rw-r--r-- | source3/include/vfs.h | 13 | ||||
| -rw-r--r-- | source3/include/vfs_macros.h | 6 | ||||
| -rw-r--r-- | source3/locking/locking.c | 90 | ||||
| -rw-r--r-- | source3/modules/vfs_default.c | 24 | ||||
| -rw-r--r-- | source3/modules/vfs_full_audit.c | 40 | ||||
| -rw-r--r-- | 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;  }  | 
