diff options
| author | Volker Lendecke <vl@samba.org> | 2009-04-06 20:41:48 +0200 | 
|---|---|---|
| committer | Volker Lendecke <vl@samba.org> | 2009-04-06 21:32:08 +0200 | 
| commit | 0c353b57113b02bccaaa3ec09ff9fb1fd8542bd4 (patch) | |
| tree | 933a034c3a3cffdbe13e798d746f9e89fbf7b8ec /source3 | |
| parent | 64ce0e4645727be7b493fca54fdf6af91f3f7927 (diff) | |
| download | samba-0c353b57113b02bccaaa3ec09ff9fb1fd8542bd4.tar.gz samba-0c353b57113b02bccaaa3ec09ff9fb1fd8542bd4.tar.bz2 samba-0c353b57113b02bccaaa3ec09ff9fb1fd8542bd4.zip  | |
Make cli_oplock_ack async
Diffstat (limited to 'source3')
| -rw-r--r-- | source3/include/proto.h | 5 | ||||
| -rw-r--r-- | source3/libsmb/clioplock.c | 123 | 
2 files changed, 99 insertions, 29 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h index 514ee68e7a..d76ee08fd2 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -2644,6 +2644,11 @@ bool cli_message_end(struct cli_state *cli, int grp);  /* The following definitions come from libsmb/clioplock.c  */ +struct tevent_req *cli_oplock_ack_send(TALLOC_CTX *mem_ctx, +				       struct tevent_context *ev, +				       struct cli_state *cli, +				       uint16_t fnum, uint8_t level); +NTSTATUS cli_oplock_ack_recv(struct tevent_req *req);  bool cli_oplock_ack(struct cli_state *cli, int fnum, unsigned char level);  void cli_oplock_handler(struct cli_state *cli,   			bool (*handler)(struct cli_state *, int, unsigned char)); diff --git a/source3/libsmb/clioplock.c b/source3/libsmb/clioplock.c index ef8b396461..e3fb66aba0 100644 --- a/source3/libsmb/clioplock.c +++ b/source3/libsmb/clioplock.c @@ -23,38 +23,103 @@  send an ack for an oplock break request  ****************************************************************************/ -bool cli_oplock_ack(struct cli_state *cli, int fnum, unsigned char level) +struct cli_oplock_ack_state { +	uint16_t vwv[8]; +}; + +static void cli_oplock_ack_done(struct tevent_req *subreq); + +struct tevent_req *cli_oplock_ack_send(TALLOC_CTX *mem_ctx, +				       struct tevent_context *ev, +				       struct cli_state *cli, +				       uint16_t fnum, uint8_t level) +{ +	struct tevent_req *req, *subreq; +	struct cli_oplock_ack_state *state; + +	req = tevent_req_create(mem_ctx, &state, struct cli_oplock_ack_state);; +	if (req == NULL) { +		return NULL; +	} +	SCVAL(state->vwv+0, 0, 0xff); +	SCVAL(state->vwv+0, 1, 0); +	SSVAL(state->vwv+1, 0, 0); +	SSVAL(state->vwv+2, 0, fnum); +	SCVAL(state->vwv+3, 0, LOCKING_ANDX_OPLOCK_RELEASE); +	SCVAL(state->vwv+3, 1, level); +	SIVAL(state->vwv+4, 0, 0); /* timeout */ +	SSVAL(state->vwv+6, 0, 0); /* unlockcount */ +	SSVAL(state->vwv+7, 0, 0); /* lockcount */ + +	subreq = cli_smb_send(state, ev, cli, SMBlockingX, 0, 8, state->vwv, +			      0, NULL); +	if (tevent_req_nomem(subreq, req)) { +		return tevent_req_post(req, ev); +	} +	tevent_req_set_callback(subreq, cli_oplock_ack_done, req); +	return req; +} + +static void cli_oplock_ack_done(struct tevent_req *subreq) +{ +	struct tevent_req *req = tevent_req_callback_data( +		subreq, struct tevent_req); +	NTSTATUS status; + +	status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL); +	TALLOC_FREE(subreq); +	if (!NT_STATUS_IS_OK(status)) { +		tevent_req_nterror(req, status); +		return; +	} +	tevent_req_done(req); +} + +NTSTATUS cli_oplock_ack_recv(struct tevent_req *req)  { -	char *oldbuf = cli->outbuf; -	char buf[smb_size+16]; -	bool ret; - -	cli->outbuf = buf; - -        memset(buf,'\0',smb_size); -        cli_set_message(buf,8,0,True); - -        SCVAL(buf,smb_com,SMBlockingX); -	SSVAL(buf,smb_tid, cli->cnum); -        cli_setup_packet(cli); -	SSVAL(buf,smb_vwv0,0xFF); -	SSVAL(buf,smb_vwv1,0); -	SSVAL(buf,smb_vwv2,fnum); -	if (level == 1) -		SSVAL(buf,smb_vwv3,0x102); /* levelII oplock break ack */ -	else -		SSVAL(buf,smb_vwv3,2); /* exclusive oplock break ack */ -	SIVAL(buf,smb_vwv4,0); /* timoeut */ -	SSVAL(buf,smb_vwv6,0); /* unlockcount */ -	SSVAL(buf,smb_vwv7,0); /* lockcount */ - -        ret = cli_send_smb(cli); - -	cli->outbuf = oldbuf; - -	return ret; +	return tevent_req_simple_recv_ntstatus(req);  } +bool cli_oplock_ack(struct cli_state *cli, int fnum, unsigned char level) +{ +	TALLOC_CTX *frame = talloc_stackframe(); +	struct event_context *ev; +	struct tevent_req *req; +	NTSTATUS status = NT_STATUS_OK; + +	if (cli_has_async_calls(cli)) { +		/* +		 * Can't use sync call while an async call is in flight +		 */ +		status = NT_STATUS_INVALID_PARAMETER; +		goto fail; +	} + +	ev = event_context_init(frame); +	if (ev == NULL) { +		status = NT_STATUS_NO_MEMORY; +		goto fail; +	} + +	req = cli_oplock_ack_send(frame, ev, cli, fnum, level); +	if (req == NULL) { +		status = NT_STATUS_NO_MEMORY; +		goto fail; +	} + +	if (!tevent_req_poll(req, ev)) { +		status = map_nt_error_from_unix(errno); +		goto fail; +	} + +	status = cli_oplock_ack_recv(req); + fail: +	TALLOC_FREE(frame); +	if (!NT_STATUS_IS_OK(status)) { +		cli_set_error(cli, status); +	} +	return NT_STATUS_IS_OK(status); +}  /****************************************************************************  set the oplock handler for a connection  | 
