FSCTL_DUPLICATE_EXTENTS_TO_FILE should fail if the source is marked
sparse while the target is not:
From: Jeff McCashland
To: David Disseldorp
Subject: RE: FSCTL_DUPLICATE_EXTENTS_TO_FILE questions,
116092214702946
Date: Tue, 27 Dec 2016 18:06:14 +0000
...
We have updated the spec for future release:
Section 2.3.8 FSCTL_DUPLICATE_EXTENTS_TO_FILE Reply
Changed description of STATUS_NOT_SUPPORTED error code to:
"--The source and target destination ranges overlap on the same file.
--Source file is sparse, while -target is a non-sparse file.
--The source range is beyond the source file's allocation size."
Signed-off-by: David Disseldorp <ddiss@samba.org>
Reviewed-by: Ralph Böhme <slow@samba.org>
+static NTSTATUS fsctl_dup_extents_check_sparse(struct files_struct *src_fsp,
+ struct files_struct *dst_fsp)
+{
+ /*
+ * 2.3.8 FSCTL_DUPLICATE_EXTENTS_TO_FILE Reply...
+ * STATUS_NOT_SUPPORTED: Target file is sparse, while source
+ * is a non-sparse file.
+ *
+ * WS2016 has the following behaviour (MS are in the process of fixing
+ * the spec):
+ * STATUS_NOT_SUPPORTED is returned if the source is sparse, while the
+ * target is non-sparse. However, if target is sparse while the source
+ * is non-sparse, then FSCTL_DUPLICATE_EXTENTS_TO_FILE completes
+ * successfully.
+ */
+ if ((src_fsp->is_sparse) && (!dst_fsp->is_sparse)) {
+ return NT_STATUS_NOT_SUPPORTED;
+ }
+
+ return NT_STATUS_OK;
+}
+
struct fsctl_dup_extents_state {
struct tevent_context *ev;
struct connection_struct *conn;
struct fsctl_dup_extents_state {
struct tevent_context *ev;
struct connection_struct *conn;
return tevent_req_post(req, ev);
}
return tevent_req_post(req, ev);
}
+ status = fsctl_dup_extents_check_sparse(src_fsp, dst_fsp);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return tevent_req_post(req, ev);
+ }
+
subreq = SMB_VFS_COPY_CHUNK_SEND(dst_fsp->conn, state, ev,
src_fsp, state->dup_extents.source_off,
dst_fsp, state->dup_extents.target_off,
subreq = SMB_VFS_COPY_CHUNK_SEND(dst_fsp->conn, state, ev,
src_fsp, state->dup_extents.source_off,
dst_fsp, state->dup_extents.target_off,