[RFC PATCH] smbd: resilient file handle support
Michael Adam
obnox at samba.org
Thu Feb 11 22:38:07 UTC 2016
On 2016-02-11 at 23:42 +0200, Uri Simchoni wrote:
> Hi,
>
> Attached pls find a patch for supporting resilient file
> handles. Comments are welcome. It doesn't include tests yet,
> but I would appreciate technical feedback and any other
> feedback.
Cool!
A few comments up front before digging deeper into the
actual patches.
Note the hacked up implementation (by metze) in the
master-multi-channel-obnox branch:
https://git.samba.org/?p=obnox/samba/samba-obnox.git;a=commitdiff;h=8e68d390dc640ceb3aa9594c9d18d5d3d01c24f2
samba.org/?p=obnox/samba/samba-obnox.git;a=shortlog;h=refs/heads/master-multi-channel-obnox
> By and large, this patch stands on the shoulders of the durable
> handles implementation. Same restrictions as with durable
> handles apply (durable handles must be enabled, kernel oplocks,
> posix locks and kernel share modes must be disabled).
>
> I didn't plan this. The driver for doing this was that we've
> just found out that Windows backup engine doesn't work with
> Samba and SMB dialect > 2.0.2 (see
> https://bugzilla.samba.org/show_bug.cgi?id=10159).
>
> I don't know if I'm stepping on any toes here - I know
> resilient were low priority because persistent handles are the
> "real deal", but it appears that Windows backup requests
> resilient handles, at least when persistent handles are not
> supported.
Sure, we eventually want all of it!
> On to the technical stuff.
>
> The patch implements resilient handles with the omission of
> lock sequence verification ([MS-SMB2] 3.3.5.14), a mechanism
> used for preventing the server from doing the same lock twice
> if it failed to ack the first lock request because of
> disconnect.
Patches for lock sequence checking have recently been
proposed to this list by Günther, based on previous work
by Metze and me. Including a few tests. So we have that.
> From my reading of [MS-SMB2], it looks like resilient handles
> are very similar to durable handles. They serve the same
> purpose, namely to allow seamless (transparent to the
> application) immediate reconnect by a client if the connection
> breaks, while keeping locks/oplocks/share modes intact.
>
> The main difference between durable and resilient is in how
> they are being set up, namely that durable handles get created
> by create context, and failure to make the handle durable does
> not fail the open, whereas resilient handles get created by an
> IOCTL, and failure is a failure of the IOCTL, which perhaps
> provides better feedback to the application.
One main difference is that while durable handles are purely
best effort, i.e. when a second client tries to open a file
with a disconnected durable handle, that handle is closed
and the original opener can not reconnect it. For resilient
handles, there are iirc (need to look up the exact details),
certain weak guarantees where new openers are blocked for
a short disconnected time. The same is true for persistent
handles, but with stronger guarantees and you can also get
them without oplocks, on a scale-out share.
I think implementing these guarantees is the major challenge
in implementing resilient and durable handles.
The other aspect as you mentiond: On the requesting side,
durable handles (and persistent handles) are not exposed
to the application. The redirector takes care of them.
Resilient handles instead are explicitly requested by the
client application. I think that this was later considered
a bad choice since not all applications can benefit from that.
Maybe the increased level of control can indeed be a plus
for aware applications.
More comments later (not today...) when I've managed to
look thoroughly at the patches.
Cheers - Michael
> Data Model
> ===========
> [MS-SMB2] describes "durability" and "resiliency" of a file handle as two
> distinct properties, but it immediately becomes apparent that they are
> mutually exclusive - enabling Open.IsResilient automatically disables
> Open.IsDurable (3.3.5.15.9). Therefore it would seem beneficial to treat
> a resilient file handle as a special type of durable handle, and observe
> the difference. From my reading, the functional differences amount to the
> following:
>
> a. When an oplock or lease breaks on a disconnected durable handle, the
> handle must be deleted, whereas a resilient handle is not deleted. From
> functional point of view it means a reconnect after oplock break fails on
> a durable handle but not on a resilient handle.
>
> b. If the dialect is SMB2.1, lock sequence verification is done only on
> resilient handles.
>
> c. When a disconnect happens, resilient handles are always being
> preserved, whereas durable handles must be preserved only if specific
> types of oplock or lease are granted.
>
> With respect to a), it seems that current Samba code does not delete
> durable handles on oplock break.
>
> With respect to b), the patch does not implement lock sequence checking
> at all.
>
> With respect to c), it seems like Samba implements this by only marking a
> handle as durable if it has a handle lease, but upon disconnect, it
> unconditionally preserves durable handles.
>
> It follows that no significant change is required to implement resilient
> handles - the only required thing is to handle the IOCTL and "durablize"
> the handle, with the timeout of the resiliency request. I could add a
> "resilient" variable that would tell the difference but at this stage
> this would be a write-only variable.
>
> Conformance with [MS-SMB2]
> ====================
> Following are places in which Open.IsResilient is mentioned and how it's
> being covered.
>
> 3.3.4.6 - not delete a disconnected resilient handle on oplock break - we
> never delete it.
>
> 3.3.4.7 - not delete a disconnected resilient handle on lease break - we
> never delete it.
>
> 3.3.5.6 - not delete a resilient handle on logoff - covered by marking
> the handle as durable.
>
> 3.3.5.9 - on CREATE, set Open.DurableFileId to a unique value - a handle
> can only be resilient at create time if it's a reconnect, and in that
> case the Open.DurableFileId has already been set.
>
> 3.3.5.9.7 - Handling of reconnect - same as durable.
>
> 3.3.5.9.12 - Handling of reconnectV2 - same as durable.
>
> 3.3.5.14 - Lock sequence verification - not implemented (that's a SHOULD)
>
> 3.3.5.14.1 - Updating the lock sequence array on Unlock - not implemented
> (not needed since we don't verify sequence)
>
> 3.3.5.14.2 - Updating the lock sequence array on Lock - not implemented
> (not needed since we don't verify sequence)
>
> 3.3.5.15.9 - Handling the resiliency request - that's the meat of this
> patch, code can be carefully compared to the spec. The code essentially
> "durablize" the handle, with the requested timeout.
>
> 3.3.6.4 - Resilient Open Scavenger Timer - The spec of what to do when a
> handle expires is identical to durable handles. The difference is in how
> timeouts are set. Our implementation of durable open scavenger is
> compatible, timing-wise, with the spec.
>
> 3.3.7.1 - loss of connection, preserving a handle for reconnect -
> resilient handles must be preserved. Durable handles must be preserved
> only if Open.OplockLevel is equal to SMB2_OPLOCK_LEVEL_BATCH and
> Open.OplockState is equal to Held. However, it seems like our code always
> preserves durable handles, so the resilient==durable design holds here
> too.
>
> 3.3.7.1 - triggering the scavenger time on loss of connection - same as
> durable.
>
> Thanks,
> Uri.
>
> From 1b4255b67034d7b9945814bf65364773118d44b3 Mon Sep 17 00:00:00 2001
> From: Uri Simchoni <uri at samba.org>
> Date: Thu, 11 Feb 2016 13:56:04 +0200
> Subject: [PATCH] smbd: add support for resilent file handles
>
> Add support for resilient file handles, with the same
> restrictions as those for durable handles, and the following
> omission:
>
> 1. Verifying lock sequence [MS-SMB2] 3.3.5.14 - this is listed
> as SHOULD
>
> This patch uses the durable file handle infrastructure, and
> internally makes no distinction between durable and resilient
> file handles - the difference is in how they are being set up.
>
> This is so because in MS-SMB2, a handle can be durable or
> resilient, but not both (see 3.3.5.15.9 - when resiliency
> request is received, IsResilient is set to TRUE and IsDurable
> is set to FALSE). The functional differences once the
> handle is set up are:
>
> 1. When an oplock or lease breaks on a disconnected, durable
> handle, the handle must be deleted, whereas a resilient
> disconnected handle is not deleted (3.3.4.6 and
> 3.3.4.7) - in Samba a durable handle is not deleted
> by an oplock break.
>
> 2. If the dialect is SMB2.1, lock sequence verification is done
> only on resilient handles - at this stage lock sequence
> verification is not implemented.
>
> 3. Upon disconnect, durable handles are preserved only if certain
> types of oplocks/leases were granted, and resilient handles are
> always preserved. Here Samba only marks a handle as durable
> if it has a handle lease, but upon disconnect it
> unconditionally preserves durable handles.
>
> It follows that after Samba sets up a handle as durable, it also meets
> the resilient handle spec.
> ---
> source3/smbd/smb2_ioctl_network_fs.c | 69 ++++++++++++++++++++++++++++++++++++
> 1 file changed, 69 insertions(+)
>
> diff --git a/source3/smbd/smb2_ioctl_network_fs.c b/source3/smbd/smb2_ioctl_network_fs.c
> index d8590de..0af6c83 100644
> --- a/source3/smbd/smb2_ioctl_network_fs.c
> +++ b/source3/smbd/smb2_ioctl_network_fs.c
> @@ -620,6 +620,67 @@ static NTSTATUS fsctl_srv_req_resume_key(TALLOC_CTX *mem_ctx,
> return NT_STATUS_OK;
> }
>
> +static NTSTATUS fsctl_request_resiliency(struct smbXsrv_connection *conn,
> + struct files_struct *fsp,
> + DATA_BLOB *in_input)
> +{
> + NTSTATUS status;
> + uint32_t timeout = 0;
> + struct smbXsrv_open *op = fsp->op;
> +
> + /* Should we check whether fsp is NULL? */
> +
> + timeout = IVAL(in_input->data, 0x00);
> + /*
> + * Maximum value should be configurable -
> + * MaxResiliencyTimeout, with a default in
> + * Windows of 300 sec according to [MS-SMB2] 3.3.3
> + */
> + if (timeout > 300 * 1000) {
> + return NT_STATUS_INVALID_PARAMETER;
> + }
> +
> + if (op->global->backend_cookie.length == 0) {
> + status = SMB_VFS_DURABLE_COOKIE(fsp, op,
> + &op->global->backend_cookie);
> + if (!NT_STATUS_IS_OK(status)) {
> + return status;
> + }
> + }
> +
> + op->global->durable = true;
> +
> + if (timeout == 0) {
> + /* Default - 120 sec as per Server 2012 and later
> + * according to [MS-SMB2] 3.3.5.15.9
> + */
> + timeout = 120 * 1000;
> + }
> +
> + /* [MS-SMB2] defines different state variables for durable
> + * and resilient, but at the same time durable and resilient
> + * are mutually-exclusive, and the scavenging algorithm is
> + * identical.
> + * Therefore we keep the timeout in durable_timeout_msec.
> + */
> + op->global->durable_timeout_msec = timeout;
> +
> + /* no need to handle durable owner - it's recorded
> + * on every open even if the handle is not durable
> + * or resilient.
> + */
> +
> + status = smbXsrv_open_update(op);
> + DBG_DEBUG("smb2_create_send: smbXsrv_open_update "
> + "returned %s\n",
> + nt_errstr(status));
> + if (!NT_STATUS_IS_OK(status)) {
> + return status;
> + }
> +
> + return NT_STATUS_OK;
> +}
> +
> static void smb2_ioctl_network_fs_copychunk_done(struct tevent_req *subreq);
>
> struct tevent_req *smb2_ioctl_network_fs(uint32_t ctl_code,
> @@ -698,6 +759,14 @@ struct tevent_req *smb2_ioctl_network_fs(uint32_t ctl_code,
> }
> return tevent_req_post(req, ev);
> break;
> + case FSCTL_LMR_REQ_RESILIENCY:
> + status = fsctl_request_resiliency(state->smbreq->xconn,
> + state->fsp, &state->in_input);
> + if (!tevent_req_nterror(req, status)) {
> + tevent_req_done(req);
> + }
> + return tevent_req_post(req, ev);
> + break;
> default: {
> uint8_t *out_data = NULL;
> uint32_t out_data_len = 0;
> --
> 2.5.0
>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: not available
URL: <http://lists.samba.org/pipermail/samba-technical/attachments/20160211/cc8fe902/signature.sig>
More information about the samba-technical
mailing list