[PATCH] smb2 FSCTL_SRV_COPYCHUNK support
David Disseldorp
ddiss at suse.de
Mon Mar 12 19:30:05 MDT 2012
Hi Metze,
Thanks for your very thorough feedback, comments in-line...
On Mon, 12 Mar 2012 14:42:22 +0100
"Stefan (metze) Metzmacher" <metze at samba.org> wrote:
> Hi David,
>
> > Did anyone get a chance to look at this round of changes?
>
> https://git.samba.org/?p=ddiss/samba.git;a=commitdiff;h=27ffc797af59a1344f044ebd5fb06f1d3c460320
>
> still doesn't follow what Volker had requested.
>
> struct copy_chunk_state,
> fsctl_srv_copychunk_send()
> vfs_copy_chunk_done(),
> fsctl_srv_copychunk_recv()
> doesn't have the same prefix
Fixed.
>
> +static struct tevent_req *fsctl_srv_copychunk_send(struct
> tevent_context *ev,
> + struct tevent_req *req,
> + struct smbd_smb2_ioctl_state *state)
>
> The first 2 arguments to a _send() function, are *always*
> TALLOC_CTX *mem_ctx, struct tevent_context *ev!
>
> a _send() function should never get a 'req' as argument,
> 'req' is it's internal request handle that it gives to its caller.
Fixed.
> Also 'smbd_smb2_ioctl_state' is the *private* state of the
> smbd_smb2_ioctl_send/recv function, it should be only visiable.
> in smbd_smb2_ioctl_*() functions.
Discussed later...
> + subreq = tevent_req_create(state, &cc_state,
> + struct copy_chunk_state);
> + if (subreq == NULL) {
> + return NULL;
> + }
>
> This should be 'req' instead 'subreq', as from the point of view
> of the current function this is the current request.
Changed.
> Also the state structure needs to match the function name,
> so it should be 'struct fsctl_srv_copychunk_state'.
> The name of the variable is always 'state', which references
> the state of the current function.
> So it should be:
>
> req = tevent_req_create(mem_ctx, &state,
> struct fsctl_srv_copychunk_state);
> if (req == NULL) {
> return NULL;
> }
>
> + if (ndr_ret != NDR_ERR_SUCCESS) {
> + DEBUG(0, ("failed to unmarshall copy chunk req\n"));
> + cc_state->status = NT_STATUS_INVALID_PARAMETER;
> + goto err_post_status;
> + }
> +
>
> Please inline the code without goto here.
>
> + tevent_req_nterror(subreq, NT_STATUS_INVALID_PARAMETER);
> + return tevent_req_post(subreq, ev);
>
> This is important because tevent_req_nterror() records
> the current location using the '__location__' macro.
>
> In gdb 'p req->internal.finish_location' will tell you the file,
> where the function failed.
Changed.
>
> +static void vfs_copy_chunk_done(struct tevent_req *subreq)
>
> This should be named fsctl_srv_copychunk_done()
> or fsctl_srv_copychunk_vfs_done().
Renamed.
> +static void fsctl_srv_copychunk_done(struct tevent_req *subreq)
>
> This has nothing to do with the rest of fsctl_srv_copychunk_*,
> it belongs to the caller! It should have a name that belongs to
> the caller, maybe smb2_ioctl_network_fs_copychunk_done().
> And it should not appear between struct fsctl_srv_copychunk_state
> and fsctl_srv_copychunk_recv() in the sources,
> it should come after the smb2_ioctl_network_fs() function.
Moved below smb2_ioctl_network_fs().
>
> +static NTSTATUS fsctl_srv_copychunk_recv(struct copy_chunk_state *cc_state,
> + struct srv_copychunk_rsp *cc_rsp)
>
> The first argument to the _recv() is *always* 'req' (the one the caller
> got from the _send() function). The caller should never see any reference
> to the internal 'state' structure.
Fixed.
> It's really important to follow the exact rules everywhere
> and implement very strict layering, even if it makes a code a bit more
> verbose and results in more lines of code.
>
> https://git.samba.org/?p=ddiss/samba.git;a=commitdiff;h=abd2051818f1a3c5582b689ae5cf3fbef79053bc
>
> Is an indication that the commit before removed to much.
Yes, it is.
I'm not quite sure what you mean here. I've added a "delegate async/sync
tracking to per ioctl device handlers" commit which removes the need for
state->req_outstanding and places tevent_req_post calls closer to
error detection. Hopefully this addresses these concerns.
>
> subreq = np_write_send(state, ev,
> - fsp->fake_file_handle,
> - in_input.data,
> - in_input.length);
> - if (tevent_req_nomem(subreq, req)) {
> - return tevent_req_post(req, ev);
> + state->fsp->fake_file_handle,
> + state->in_input.data,
> + state->in_input.length);
> + if (subreq == NULL) {
> + status = NT_STATUS_FILE_CLOSED;
> + break;
> }
> tevent_req_set_callback(subreq,
> smbd_smb2_ioctl_pipe_write_done,
> req);
> - return req;
> -
>
> You should try to keep early returns as much as possible.
See above.
> Regarding the other commits, I think "struct smbd_smb2_ioctl_state" should
> state private in the .c file, pass explicit arguments if subfunctions
> need them.
My preference is to keep it exported for use in the main per dev type
handler, as well as smb2_ioctl_network_fs_copychunk_done() and
smbd_smb2_ioctl_pipe_*_done().
I agree that the per operation _send and _recv functions shouldn't be
peeking at struct smbd_smb2_ioctl_state, but I'm not so convinced that
doing so in smb2_ioctl_network_fs_copychunk_done or
smbd_smb2_ioctl_pipe_*_done() is such a layering violation. The _done
function is already responsible for marking the parent smb2 ioctl
request complete. Perhaps I've misunderstood here.
> As I said before on irc, we still need to resolve, the problem,
> the ioctl() code path of SMB 1 and SMB 2 are not in sync anymore.
Yes, further divergence here is not what I'd hoped for. As mentioned,
my preference is to start by plumbing through to the VFS at a per ioctl
level, to initially avoid the headaches of dealing with differing per
protocol version state types.
I've pushed a new branch attempting to address your concerns above to:
https://git.samba.org/?p=ddiss/samba.git;a=shortlog;h=refs/heads/smb2_copychunk_async_rb9_2squash
git://git.samba.org/ddiss/samba.git smb2_copychunk_async_rb9_2squash
The changes have not yet been squashed.
Cheers, David
More information about the samba-technical
mailing list