diff options
author | Jeremy Allison <jra@samba.org> | 2009-07-15 11:49:33 -0700 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2009-07-15 11:49:33 -0700 |
commit | 1f5aec877fc48ff96b14a0e95f01c68a29dd8718 (patch) | |
tree | 4c3ab1b8c1a1b706531ae3d80969f6d00b0fc29a | |
parent | b76ab511f7238820a4e6ac3a2ae17d103f2bf9b9 (diff) | |
download | samba-1f5aec877fc48ff96b14a0e95f01c68a29dd8718.tar.gz samba-1f5aec877fc48ff96b14a0e95f01c68a29dd8718.tar.bz2 samba-1f5aec877fc48ff96b14a0e95f01c68a29dd8718.zip |
Make cli_unlock and cli_unlock64 async. Fix POSIX lock test.
Jeremy.
-rw-r--r-- | source3/include/proto.h | 18 | ||||
-rw-r--r-- | source3/libsmb/clifile.c | 270 | ||||
-rw-r--r-- | source3/torture/locktest.c | 4 | ||||
-rw-r--r-- | source3/torture/locktest2.c | 2 | ||||
-rw-r--r-- | source3/torture/torture.c | 44 |
5 files changed, 247 insertions, 91 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h index 7bbdc04ae7..15e3f325aa 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -2518,10 +2518,24 @@ NTSTATUS cli_locktype(struct cli_state *cli, uint16_t fnum, int timeout, unsigned char locktype); bool cli_lock(struct cli_state *cli, uint16_t fnum, uint32_t offset, uint32_t len, int timeout, enum brl_type lock_type); -bool cli_unlock(struct cli_state *cli, uint16_t fnum, uint32_t offset, uint32_t len); +struct tevent_req *cli_unlock_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + uint16_t fnum, + uint64_t offset, + uint64_t len); +NTSTATUS cli_unlock_recv(struct tevent_req *req); +NTSTATUS cli_unlock(struct cli_state *cli, uint16_t fnum, uint32_t offset, uint32_t len); bool cli_lock64(struct cli_state *cli, uint16_t fnum, uint64_t offset, uint64_t len, int timeout, enum brl_type lock_type); -bool cli_unlock64(struct cli_state *cli, uint16_t fnum, uint64_t offset, uint64_t len); +struct tevent_req *cli_unlock64_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + uint16_t fnum, + uint64_t offset, + uint64_t len); +NTSTATUS cli_unlock64_recv(struct tevent_req *req); +NTSTATUS cli_unlock64(struct cli_state *cli, uint16_t fnum, uint64_t offset, uint64_t len); struct tevent_req *cli_posix_lock_send(TALLOC_CTX *mem_ctx, struct event_context *ev, struct cli_state *cli, diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c index 0e2b3640f2..5ea0579839 100644 --- a/source3/libsmb/clifile.c +++ b/source3/libsmb/clifile.c @@ -1893,7 +1893,6 @@ struct tevent_req *cli_nt_delete_on_close_send(TALLOC_CTX *mem_ctx, SSVAL(&state->setup, 0, TRANSACT2_SETFILEINFO); /* Setup param array. */ - memset(state->param, '\0', 6); SSVAL(state->param,0,fnum); SSVAL(state->param,2,SMB_SET_FILE_DISPOSITION_INFO); @@ -2010,6 +2009,7 @@ struct tevent_req *cli_ntcreate_send(TALLOC_CTX *mem_ctx, if (req == NULL) { return NULL; } + vwv = state->vwv; SCVAL(vwv+0, 0, 0xFF); @@ -2367,6 +2367,7 @@ struct tevent_req *cli_close_create(TALLOC_CTX *mem_ctx, if (req == NULL) { return NULL; } + SSVAL(state->vwv+0, 0, fnum); SIVALS(state->vwv+1, 0, -1); @@ -2708,42 +2709,114 @@ bool cli_lock(struct cli_state *cli, uint16_t fnum, Unlock a file. ****************************************************************************/ -bool cli_unlock(struct cli_state *cli, uint16_t fnum, uint32_t offset, uint32_t len) +struct cli_unlock_state { + uint16_t vwv[8]; + uint8_t data[10]; +}; + +static void cli_unlock_done(struct tevent_req *subreq); + +struct tevent_req *cli_unlock_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + uint16_t fnum, + uint64_t offset, + uint64_t len) + { - char *p; + struct tevent_req *req = NULL, *subreq = NULL; + struct cli_unlock_state *state = NULL; + uint8_t additional_flags = 0; - memset(cli->outbuf,'\0',smb_size); - memset(cli->inbuf,'\0',smb_size); + req = tevent_req_create(mem_ctx, &state, struct cli_unlock_state); + if (req == NULL) { + return NULL; + } - cli_set_message(cli->outbuf,8,0,True); + SCVAL(state->vwv+0, 0, 0xFF); + SSVAL(state->vwv+2, 0, fnum); + SCVAL(state->vwv+3, 0, 0); + SIVALS(state->vwv+4, 0, 0); + SSVAL(state->vwv+6, 0, 1); + SSVAL(state->vwv+7, 0, 0); - SCVAL(cli->outbuf,smb_com,SMBlockingX); - SSVAL(cli->outbuf,smb_tid,cli->cnum); - cli_setup_packet(cli); + SSVAL(state->data, 0, cli->pid); + SIVAL(state->data, 2, offset); + SIVAL(state->data, 6, len); - SCVAL(cli->outbuf,smb_vwv0,0xFF); - SSVAL(cli->outbuf,smb_vwv2,fnum); - SCVAL(cli->outbuf,smb_vwv3,0); - SIVALS(cli->outbuf, smb_vwv4, 0); - SSVAL(cli->outbuf,smb_vwv6,1); - SSVAL(cli->outbuf,smb_vwv7,0); + subreq = cli_smb_send(state, ev, cli, SMBlockingX, additional_flags, + 8, state->vwv, 10, state->data); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, cli_unlock_done, req); + return req; +} - p = smb_buf(cli->outbuf); - SSVAL(p, 0, cli->pid); - SIVAL(p, 2, offset); - SIVAL(p, 6, len); - p += 10; - cli_setup_bcc(cli, p); - cli_send_smb(cli); - if (!cli_receive_smb(cli)) { - return False; +static void cli_unlock_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); +} - if (cli_is_error(cli)) { - return False; +NTSTATUS cli_unlock_recv(struct tevent_req *req) +{ + return tevent_req_simple_recv_ntstatus(req); +} + +NTSTATUS cli_unlock(struct cli_state *cli, + uint16_t fnum, + uint32_t offset, + uint32_t len) +{ + 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; } - return True; + ev = event_context_init(frame); + if (ev == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + req = cli_unlock_send(frame, ev, cli, + fnum, offset, len); + 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_unlock_recv(req); + + fail: + TALLOC_FREE(frame); + if (!NT_STATUS_IS_OK(status)) { + cli_set_error(cli, status); + } + return status; } /**************************************************************************** @@ -2811,46 +2884,118 @@ bool cli_lock64(struct cli_state *cli, uint16_t fnum, Unlock a file with 64 bit offsets. ****************************************************************************/ -bool cli_unlock64(struct cli_state *cli, uint16_t fnum, uint64_t offset, uint64_t len) +struct cli_unlock64_state { + uint16_t vwv[8]; + uint8_t data[20]; +}; + +static void cli_unlock64_done(struct tevent_req *subreq); + +struct tevent_req *cli_unlock64_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + uint16_t fnum, + uint64_t offset, + uint64_t len) + { - char *p; + struct tevent_req *req = NULL, *subreq = NULL; + struct cli_unlock64_state *state = NULL; + uint8_t additional_flags = 0; - if (! (cli->capabilities & CAP_LARGE_FILES)) { - return cli_unlock(cli, fnum, offset, len); + req = tevent_req_create(mem_ctx, &state, struct cli_unlock64_state); + if (req == NULL) { + return NULL; } - memset(cli->outbuf,'\0',smb_size); - memset(cli->inbuf,'\0',smb_size); + SCVAL(state->vwv+0, 0, 0xff); + SSVAL(state->vwv+2, 0, fnum); + SCVAL(state->vwv+3, 0,LOCKING_ANDX_LARGE_FILES); + SIVALS(state->vwv+4, 0, 0); + SSVAL(state->vwv+6, 0, 1); + SSVAL(state->vwv+7, 0, 0); - cli_set_message(cli->outbuf,8,0,True); + SIVAL(state->data, 0, cli->pid); + SOFF_T_R(state->data, 4, offset); + SOFF_T_R(state->data, 12, len); - SCVAL(cli->outbuf,smb_com,SMBlockingX); - SSVAL(cli->outbuf,smb_tid,cli->cnum); - cli_setup_packet(cli); + subreq = cli_smb_send(state, ev, cli, SMBlockingX, additional_flags, + 8, state->vwv, 20, state->data); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, cli_unlock64_done, req); + return req; +} - SCVAL(cli->outbuf,smb_vwv0,0xFF); - SSVAL(cli->outbuf,smb_vwv2,fnum); - SCVAL(cli->outbuf,smb_vwv3,LOCKING_ANDX_LARGE_FILES); - SIVALS(cli->outbuf, smb_vwv4, 0); - SSVAL(cli->outbuf,smb_vwv6,1); - SSVAL(cli->outbuf,smb_vwv7,0); +static void cli_unlock64_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + NTSTATUS status; - p = smb_buf(cli->outbuf); - SIVAL(p, 0, cli->pid); - SOFF_T_R(p, 4, offset); - SOFF_T_R(p, 12, len); - p += 20; - cli_setup_bcc(cli, p); - cli_send_smb(cli); - if (!cli_receive_smb(cli)) { - return False; + 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); +} - if (cli_is_error(cli)) { - return False; +NTSTATUS cli_unlock64_recv(struct tevent_req *req) +{ + return tevent_req_simple_recv_ntstatus(req); +} + +NTSTATUS cli_unlock64(struct cli_state *cli, + uint16_t fnum, + uint64_t offset, + uint64_t len) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct event_context *ev; + struct tevent_req *req; + NTSTATUS status = NT_STATUS_OK; + + if (! (cli->capabilities & CAP_LARGE_FILES)) { + return cli_unlock(cli, fnum, offset, len); } - return True; + 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_unlock64_send(frame, ev, cli, + fnum, offset, len); + 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_unlock64_recv(req); + + fail: + TALLOC_FREE(frame); + if (!NT_STATUS_IS_OK(status)) { + cli_set_error(cli, status); + } + return status; } /**************************************************************************** @@ -3421,7 +3566,7 @@ NTSTATUS cli_getatr(struct cli_state *cli, static void cli_setattrE_done(struct tevent_req *subreq); struct cli_setattrE_state { - int dummy; + uint16_t vwv[7]; }; struct tevent_req *cli_setattrE_send(TALLOC_CTX *mem_ctx, @@ -3435,21 +3580,19 @@ struct tevent_req *cli_setattrE_send(TALLOC_CTX *mem_ctx, struct tevent_req *req = NULL, *subreq = NULL; struct cli_setattrE_state *state = NULL; uint8_t additional_flags = 0; - uint16_t vwv[7]; req = tevent_req_create(mem_ctx, &state, struct cli_setattrE_state); if (req == NULL) { return NULL; } - memset(vwv, '\0', sizeof(vwv)); - SSVAL(vwv+0, 0, fnum); - cli_put_dos_date2(cli, (char *)&vwv[1], 0, change_time); - cli_put_dos_date2(cli, (char *)&vwv[3], 0, access_time); - cli_put_dos_date2(cli, (char *)&vwv[5], 0, write_time); + SSVAL(state->vwv+0, 0, fnum); + cli_put_dos_date2(cli, (char *)&state->vwv[1], 0, change_time); + cli_put_dos_date2(cli, (char *)&state->vwv[3], 0, access_time); + cli_put_dos_date2(cli, (char *)&state->vwv[5], 0, write_time); subreq = cli_smb_send(state, ev, cli, SMBsetattrE, additional_flags, - 7, vwv, 0, NULL); + 7, state->vwv, 0, NULL); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); } @@ -3556,7 +3699,6 @@ struct tevent_req *cli_setatr_send(TALLOC_CTX *mem_ctx, return NULL; } - memset(state->vwv, '\0', sizeof(state->vwv)); SSVAL(state->vwv+0, 0, attr); cli_put_dos_date3(cli, (char *)&state->vwv[1], 0, mtime); diff --git a/source3/torture/locktest.c b/source3/torture/locktest.c index 30b84c073d..a90c2e2dfe 100644 --- a/source3/torture/locktest.c +++ b/source3/torture/locktest.c @@ -341,9 +341,9 @@ static bool test_one(struct cli_state *cli[NSERVERS][NCONNECTIONS], case OP_UNLOCK: /* unset a lock */ for (server=0;server<NSERVERS;server++) { - ret[server] = cli_unlock64(cli[server][conn], + ret[server] = NT_STATUS_IS_OK(cli_unlock64(cli[server][conn], fnum[server][conn][f], - start, len); + start, len)); status[server] = cli_nt_error(cli[server][conn]); } if (showall || diff --git a/source3/torture/locktest2.c b/source3/torture/locktest2.c index 93adcb51a6..5c8a2d8019 100644 --- a/source3/torture/locktest2.c +++ b/source3/torture/locktest2.c @@ -132,7 +132,7 @@ static bool try_unlock(struct cli_state *c, int fstype, switch (fstype) { case FSTYPE_SMB: - return cli_unlock(c, fd, start, len); + return NT_STATUS_IS_OK(cli_unlock(c, fd, start, len)); case FSTYPE_NFS: lock.l_type = F_UNLCK; diff --git a/source3/torture/torture.c b/source3/torture/torture.c index e3c4084e0c..f9192b12b7 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -492,7 +492,7 @@ static bool rw_torture(struct cli_state *c) correct = False; } - if (!cli_unlock(c, fnum2, n*sizeof(int), sizeof(int))) { + if (!NT_STATUS_IS_OK(cli_unlock(c, fnum2, n*sizeof(int), sizeof(int)))) { printf("unlock failed (%s)\n", cli_errstr(c)); correct = False; } @@ -1429,12 +1429,12 @@ static bool run_locktest2(int dummy) printf("lock at 100 failed (%s)\n", cli_errstr(cli)); } cli_setpid(cli, 2); - if (cli_unlock(cli, fnum1, 100, 4)) { + if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) { printf("unlock at 100 succeeded! This is a locking bug\n"); correct = False; } - if (cli_unlock(cli, fnum1, 0, 4)) { + if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 0, 4))) { printf("unlock1 succeeded! This is a locking bug\n"); correct = False; } else { @@ -1443,7 +1443,7 @@ static bool run_locktest2(int dummy) NT_STATUS_RANGE_NOT_LOCKED)) return False; } - if (cli_unlock(cli, fnum1, 0, 8)) { + if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 0, 8))) { printf("unlock2 succeeded! This is a locking bug\n"); correct = False; } else { @@ -1565,14 +1565,14 @@ static bool run_locktest3(int dummy) for (offset=i=0;i<torture_numops;i++) { NEXT_OFFSET; - if (!cli_unlock(cli1, fnum1, offset-1, 1)) { + if (!NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, offset-1, 1))) { printf("unlock1 %d failed (%s)\n", i, cli_errstr(cli1)); return False; } - if (!cli_unlock(cli2, fnum2, offset-2, 1)) { + if (!NT_STATUS_IS_OK(cli_unlock(cli2, fnum2, offset-2, 1))) { printf("unlock2 %d failed (%s)\n", i, cli_errstr(cli1)); @@ -1703,7 +1703,7 @@ static bool run_locktest4(int dummy) ret = cli_lock(cli1, fnum1, 110, 4, 0, READ_LOCK) && cli_lock(cli1, fnum1, 112, 4, 0, READ_LOCK) && - cli_unlock(cli1, fnum1, 110, 6); + NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6)); EXPECTED(ret, False); printf("the same process %s coalesce read locks\n", ret?"can":"cannot"); @@ -1721,30 +1721,30 @@ static bool run_locktest4(int dummy) ret = cli_lock(cli1, fnum1, 140, 4, 0, READ_LOCK) && cli_lock(cli1, fnum1, 140, 4, 0, READ_LOCK) && - cli_unlock(cli1, fnum1, 140, 4) && - cli_unlock(cli1, fnum1, 140, 4); + NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) && + NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)); EXPECTED(ret, True); printf("this server %s do recursive read locking\n", ret?"does":"doesn't"); ret = cli_lock(cli1, fnum1, 150, 4, 0, WRITE_LOCK) && cli_lock(cli1, fnum1, 150, 4, 0, READ_LOCK) && - cli_unlock(cli1, fnum1, 150, 4) && + NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) && (cli_read(cli2, fnum2, buf, 150, 4) == 4) && !(cli_write(cli2, fnum2, 0, buf, 150, 4) == 4) && - cli_unlock(cli1, fnum1, 150, 4); + NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)); EXPECTED(ret, True); printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't"); ret = cli_lock(cli1, fnum1, 160, 4, 0, READ_LOCK) && - cli_unlock(cli1, fnum1, 160, 4) && + NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) && (cli_write(cli2, fnum2, 0, buf, 160, 4) == 4) && (cli_read(cli2, fnum2, buf, 160, 4) == 4); EXPECTED(ret, True); printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot"); ret = cli_lock(cli1, fnum1, 170, 4, 0, WRITE_LOCK) && - cli_unlock(cli1, fnum1, 170, 4) && + NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) && (cli_write(cli2, fnum2, 0, buf, 170, 4) == 4) && (cli_read(cli2, fnum2, buf, 170, 4) == 4); EXPECTED(ret, True); @@ -1752,7 +1752,7 @@ static bool run_locktest4(int dummy) ret = cli_lock(cli1, fnum1, 190, 4, 0, WRITE_LOCK) && cli_lock(cli1, fnum1, 190, 4, 0, READ_LOCK) && - cli_unlock(cli1, fnum1, 190, 4) && + NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) && !(cli_write(cli2, fnum2, 0, buf, 190, 4) == 4) && (cli_read(cli2, fnum2, buf, 190, 4) == 4); EXPECTED(ret, True); @@ -1861,7 +1861,7 @@ static bool run_locktest5(int dummy) /* Unlock the first process lock, then check this was the WRITE lock that was removed. */ - ret = cli_unlock(cli1, fnum1, 0, 4) && + ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) && cli_lock(cli2, fnum2, 0, 4, 0, READ_LOCK); EXPECTED(ret, True); @@ -1872,15 +1872,15 @@ static bool run_locktest5(int dummy) /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */ - ret = cli_unlock(cli1, fnum1, 1, 1) && - cli_unlock(cli1, fnum1, 0, 4) && - cli_unlock(cli1, fnum1, 0, 4); + ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) && + NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) && + NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)); EXPECTED(ret, True); printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot"); /* Ensure the next unlock fails. */ - ret = cli_unlock(cli1, fnum1, 0, 4); + ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)); EXPECTED(ret, False); printf("the same process %s count the lock stack\n", !ret?"can":"cannot"); @@ -4296,14 +4296,14 @@ static bool run_simple_posix_open_test(int dummy) } /* Do a POSIX lock/unlock. */ - if (!NT_STATUS_IS_OK(cli_posix_lock(cli1, fnum1, 0, 100, true, WRITE_LOCK))) { - printf("POSIX lock failed\n"); + if (!NT_STATUS_IS_OK(cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK))) { + printf("POSIX lock failed %s\n", cli_errstr(cli1)); goto out; } /* Punch a hole in the locked area. */ if (!NT_STATUS_IS_OK(cli_posix_unlock(cli1, fnum1, 10, 80))) { - printf("POSIX unlock failed\n"); + printf("POSIX unlock failed %s\n", cli_errstr(cli1)); goto out; } |