[SCM] Samba Shared Repository - branch master updated

Ralph Böhme slow at samba.org
Tue Aug 20 07:02:01 UTC 2024


The branch, master has been updated
       via  61d9c0d92e8 smbd: add options "fs:[logical|aligned|performance|effective aligned] bytes per sector"
       via  909edd6e8a5 vfs_default: implement FSCTL_DUP_EXTENTS_TO_FILE with copy_reflink()
       via  9ffcfb8c436 libreplace: add rep_copy_reflink()
       via  deeca8ff176 smbd: consolidate fs capabilities code in vfswrap_fs_capabilities()
       via  1c4e2ba842c docs: document SUPPORTS_BLOCK_REFCOUNTING for share:fake_fscaps
      from  f1cd250a6fd s3:libads: Do not print error message for a default configuration

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 61d9c0d92e8c27c8882c47bbd305d9985ea722be
Author: Ralph Boehme <slow at samba.org>
Date:   Fri Apr 5 15:25:03 2024 +0200

    smbd: add options "fs:[logical|aligned|performance|effective aligned] bytes per sector"
    
    In order to support certain Windows applications that make use of copy reflink,
    we need some way to allow configuring these values. According to testing, the
    application somehow uses the value of phys_bytes_per_sector_atomic for some check
    when requesting server-side reflink copies, eg for ZFS the following is needed
    
     block size = 131072
     fs:aligned bytes per sector = 131072
    
    For some reason "block size" must also be set to the value of fs:aligned bytes
    per sector, but fs:logical bytes per sector, which according to the spec should
    match "block size", must stay at the default of 512, otherwise the application
    does not work.
    
    As the whole client behaviour could not be fully understood, I'm proposing to
    introduce these options as undocumented parametric options, so we can at least
    start testing with them.
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: David Disseldorp <ddiss at samba.org>
    
    Autobuild-User(master): Ralph Böhme <slow at samba.org>
    Autobuild-Date(master): Tue Aug 20 07:01:19 UTC 2024 on atb-devel-224

commit 909edd6e8a5222c996553a3565b6d4b20da77e71
Author: Ralph Boehme <slow at samba.org>
Date:   Sun Mar 24 17:40:50 2024 +0100

    vfs_default: implement FSCTL_DUP_EXTENTS_TO_FILE with copy_reflink()
    
    According to MS-FSA 2.1.5.9.4 FSCTL_DUPLICATE_EXTENTS_TO_FILE ReFS on Windows
    does not check for byte range lock conflicts:
    
     * The object store SHOULD<81> check for byte range lock conflicts ...
    
     * <81>: The ReFS file system in Windows Server 2016 and later does not check
     for byte range lock conflicts
    
    To match Windows behaviour we also don't check for conflicts.
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: David Disseldorp <ddiss at samba.org>

commit 9ffcfb8c4361bf1f6a364aa56a6057ed9b7bd247
Author: Ralph Boehme <slow at samba.org>
Date:   Sun Mar 24 17:02:21 2024 +0100

    libreplace: add rep_copy_reflink()
    
    FICLONERANGE was introduced in kernel version 4.5, so I guess we can just assume
    it is present if HAVE_LINUX_IOCTL is defined.
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: David Disseldorp <ddiss at samba.org>

commit deeca8ff176e7e9082cc0fcf48d7f981de2523c5
Author: Ralph Boehme <slow at samba.org>
Date:   Thu Jun 6 15:38:16 2024 +0200

    smbd: consolidate fs capabilities code in vfswrap_fs_capabilities()
    
    This ensures the values we return via SMB_FS_ATTRIBUTE_INFORMATION is the same
    we use internally via conn->fs_capabilities.
    
    This deliberately preserves existing behaviour as much as possible and leaves
    possible improvements as a future excercize. Particularily FILE_VOLUME_QUOTAS is
    already set insided SMB_VFS_STATVFS() depending on backend filesystem flags
    which is probably the correct way to do it instead of just setting the
    capability when Samba was built with quota support.
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: David Disseldorp <ddiss at samba.org>

commit 1c4e2ba842cb379d1cb7c520643e523de711921d
Author: Ralph Boehme <slow at samba.org>
Date:   Wed Jun 5 14:40:15 2024 +0200

    docs: document SUPPORTS_BLOCK_REFCOUNTING for share:fake_fscaps
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: David Disseldorp <ddiss at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 docs-xml/smbdotconf/protocol/sharefakefscaps.xml |  24 +-
 lib/replace/replace.c                            |  28 ++
 lib/replace/replace.h                            |   9 +
 source3/modules/vfs_btrfs.c                      | 393 -----------------------
 source3/modules/vfs_ceph.c                       |   3 +-
 source3/modules/vfs_default.c                    |  83 +++--
 source3/modules/vfs_glusterfs.c                  |   4 +-
 source3/smbd/smb2_trans2.c                       |  45 +--
 8 files changed, 146 insertions(+), 443 deletions(-)


Changeset truncated at 500 lines:

diff --git a/docs-xml/smbdotconf/protocol/sharefakefscaps.xml b/docs-xml/smbdotconf/protocol/sharefakefscaps.xml
index 31e7ebc0e75..2f90d0be867 100644
--- a/docs-xml/smbdotconf/protocol/sharefakefscaps.xml
+++ b/docs-xml/smbdotconf/protocol/sharefakefscaps.xml
@@ -3,15 +3,25 @@
                  type="string"
                  xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
 <description>
+	<para>
+	  This is needed to support some special applications that makes use of
+	  filesystem specific features like sparse files or block reflink copy.
+	</para>
 
 	<para>
-	This is needed to support some special application that makes
-	QFSINFO calls to check whether we set the SPARSE_FILES bit
-	(0x40). If this bit is not set that particular application
-	refuses to work against
-	Samba. With <smbconfoption name="share:fake_fscaps">64</smbconfoption>
-	the SPARSE_FILES file system capability flag is set. Use other
-	decimal values to specify the bitmask you need to fake.
+	  With <smbconfoption name="share:fake_fscaps">64</smbconfoption>
+	  the SPARSE_FILES (0x40) file system capability flag is set.
+	</para>
+	<para>
+	  With <smbconfoption name="share:fake_fscaps">134217728</smbconfoption>
+	  the SUPPORTS_BLOCK_REFCOUNTING (0x8000000) file system capability flag
+	  is set. As of this writing, filesystems that support this feature are
+	  BTRFS, XFS and ZFS.
+	</para>
+	<para>
+	  The complete list can be found in MS-FSCC 2.5.1
+	  FileFsAttributeInformation. Note that only decimal values can be used
+	  in the configuration.
 	</para>
 
 </description>
diff --git a/lib/replace/replace.c b/lib/replace/replace.c
index 68829f2a3c9..0b4e06d8bd5 100644
--- a/lib/replace/replace.c
+++ b/lib/replace/replace.c
@@ -1083,6 +1083,34 @@ ssize_t rep_copy_file_range(int fd_in,
 }
 #endif /* HAVE_COPY_FILE_RANGE */
 
+#ifdef HAVE_LINUX_IOCTL
+# include <linux/fs.h>
+# include <sys/ioctl.h>
+#endif
+
+ssize_t rep_copy_reflink(int src_fd,
+			 off_t src_off,
+			 int dst_fd,
+			 off_t dst_off,
+			 off_t to_copy)
+{
+#ifdef HAVE_LINUX_IOCTL
+	struct file_clone_range cr;
+
+	cr = (struct file_clone_range) {
+		.src_fd = src_fd,
+		.src_offset = (uint64_t)src_off,
+		.dest_offset = (uint64_t)dst_off,
+		.src_length = (uint64_t)to_copy,
+	};
+
+	return ioctl(dst_fd, FICLONERANGE, &cr);
+#else
+	errno = ENOSYS;
+	return -1;
+#endif
+}
+
 #ifndef HAVE_OPENAT2
 
 /* fallback known wellknown __NR_openat2 values */
diff --git a/lib/replace/replace.h b/lib/replace/replace.h
index 537e61e1e48..586f4e0a575 100644
--- a/lib/replace/replace.h
+++ b/lib/replace/replace.h
@@ -1014,6 +1014,15 @@ ssize_t rep_copy_file_range(int fd_in,
 			    unsigned int flags);
 #endif /* HAVE_COPY_FILE_RANGE */
 
+
+#define copy_reflink rep_copy_reflink
+
+ssize_t rep_copy_reflink(int src_fd,
+			 off_t src_off,
+			 int dst_fd,
+			 off_t dst_off,
+			 off_t to_copy);
+
 #ifndef FALL_THROUGH
 # ifdef HAVE_FALLTHROUGH_ATTRIBUTE
 #  define FALL_THROUGH __attribute__ ((fallthrough))
diff --git a/source3/modules/vfs_btrfs.c b/source3/modules/vfs_btrfs.c
index 90312524287..1c3bcbea971 100644
--- a/source3/modules/vfs_btrfs.c
+++ b/source3/modules/vfs_btrfs.c
@@ -66,401 +66,12 @@ struct btrfs_ioctl_vol_args {
 	char name[BTRFS_PATH_NAME_MAX + 1];
 };
 
-struct btrfs_ioctl_clone_range_args {
-	int64_t src_fd;
-	uint64_t src_offset;
-	uint64_t src_length;
-	uint64_t dest_offset;
-};
-
 #define BTRFS_IOCTL_MAGIC 0x94
-#define BTRFS_IOC_CLONE_RANGE _IOW(BTRFS_IOCTL_MAGIC, 13, \
-				   struct btrfs_ioctl_clone_range_args)
 #define BTRFS_IOC_SNAP_DESTROY _IOW(BTRFS_IOCTL_MAGIC, 15, \
 				    struct btrfs_ioctl_vol_args)
 #define BTRFS_IOC_SNAP_CREATE_V2 _IOW(BTRFS_IOCTL_MAGIC, 23, \
 				      struct btrfs_ioctl_vol_args_v2)
 
-static struct vfs_offload_ctx *btrfs_offload_ctx;
-
-struct btrfs_offload_read_state {
-	struct vfs_handle_struct *handle;
-	files_struct *fsp;
-	uint32_t flags;
-	uint64_t xferlen;
-	DATA_BLOB token;
-};
-
-static void btrfs_offload_read_done(struct tevent_req *subreq);
-
-static struct tevent_req *btrfs_offload_read_send(
-	TALLOC_CTX *mem_ctx,
-	struct tevent_context *ev,
-	struct vfs_handle_struct *handle,
-	files_struct *fsp,
-	uint32_t fsctl,
-	uint32_t ttl,
-	off_t offset,
-	size_t to_copy)
-{
-	struct tevent_req *req = NULL;
-	struct tevent_req *subreq = NULL;
-	struct btrfs_offload_read_state *state = NULL;
-	NTSTATUS status;
-
-	req = tevent_req_create(mem_ctx, &state,
-				struct btrfs_offload_read_state);
-	if (req == NULL) {
-		return NULL;
-	}
-	*state = (struct btrfs_offload_read_state) {
-		.handle = handle,
-		.fsp = fsp,
-	};
-
-	status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
-					    &btrfs_offload_ctx);
-	if (tevent_req_nterror(req, status)) {
-		return tevent_req_post(req, ev);
-	}
-
-	if (fsctl == FSCTL_DUP_EXTENTS_TO_FILE) {
-		status = vfs_offload_token_create_blob(state, fsp, fsctl,
-						       &state->token);
-		if (tevent_req_nterror(req, status)) {
-			return tevent_req_post(req, ev);
-		}
-
-		status = vfs_offload_token_db_store_fsp(btrfs_offload_ctx, fsp,
-							&state->token);
-		if (tevent_req_nterror(req, status)) {
-			return tevent_req_post(req, ev);
-		}
-		tevent_req_done(req);
-		return tevent_req_post(req, ev);
-	}
-
-	subreq = SMB_VFS_NEXT_OFFLOAD_READ_SEND(mem_ctx, ev, handle, fsp,
-						fsctl, ttl, offset, to_copy);
-	if (tevent_req_nomem(subreq, req)) {
-		return tevent_req_post(req, ev);
-	}
-	tevent_req_set_callback(subreq, btrfs_offload_read_done, req);
-	return req;
-}
-
-static void btrfs_offload_read_done(struct tevent_req *subreq)
-{
-	struct tevent_req *req = tevent_req_callback_data(
-		subreq, struct tevent_req);
-	struct btrfs_offload_read_state *state = tevent_req_data(
-		req, struct btrfs_offload_read_state);
-	NTSTATUS status;
-
-	status = SMB_VFS_NEXT_OFFLOAD_READ_RECV(subreq,
-						state->handle,
-						state,
-						&state->flags,
-						&state->xferlen,
-						&state->token);
-	TALLOC_FREE(subreq);
-	if (tevent_req_nterror(req, status)) {
-		return;
-	}
-
-	status = vfs_offload_token_db_store_fsp(btrfs_offload_ctx,
-						state->fsp,
-						&state->token);
-	if (tevent_req_nterror(req, status)) {
-		return;
-	}
-
-	tevent_req_done(req);
-	return;
-}
-
-static NTSTATUS btrfs_offload_read_recv(struct tevent_req *req,
-					struct vfs_handle_struct *handle,
-					TALLOC_CTX *mem_ctx,
-					uint32_t *flags,
-					uint64_t *xferlen,
-					DATA_BLOB *token)
-{
-	struct btrfs_offload_read_state *state = tevent_req_data(
-		req, struct btrfs_offload_read_state);
-	NTSTATUS status;
-
-	if (tevent_req_is_nterror(req, &status)) {
-		tevent_req_received(req);
-		return status;
-	}
-
-	*flags = state->flags;
-	*xferlen = state->xferlen;
-	token->length = state->token.length;
-	token->data = talloc_move(mem_ctx, &state->token.data);
-
-	tevent_req_received(req);
-	return NT_STATUS_OK;
-}
-
-struct btrfs_offload_write_state {
-	struct vfs_handle_struct *handle;
-	off_t copied;
-	bool need_unbecome_user;
-};
-
-static void btrfs_offload_write_cleanup(struct tevent_req *req,
-					enum tevent_req_state req_state)
-{
-	struct btrfs_offload_write_state *state =
-		tevent_req_data(req,
-		struct btrfs_offload_write_state);
-	bool ok;
-
-	if (!state->need_unbecome_user) {
-		return;
-	}
-
-	ok = unbecome_user_without_service();
-	SMB_ASSERT(ok);
-	state->need_unbecome_user = false;
-}
-
-static void btrfs_offload_write_done(struct tevent_req *subreq);
-
-static struct tevent_req *btrfs_offload_write_send(struct vfs_handle_struct *handle,
-						TALLOC_CTX *mem_ctx,
-						struct tevent_context *ev,
-						uint32_t fsctl,
-						DATA_BLOB *token,
-						off_t transfer_offset,
-						struct files_struct *dest_fsp,
-						off_t dest_off,
-						off_t num)
-{
-	struct tevent_req *req = NULL;
-	struct btrfs_offload_write_state *state = NULL;
-	struct tevent_req *subreq = NULL;
-	struct btrfs_ioctl_clone_range_args cr_args;
-	struct lock_struct src_lck;
-	struct lock_struct dest_lck;
-	off_t src_off = transfer_offset;
-	files_struct *src_fsp = NULL;
-	int ret;
-	bool handle_offload_write = true;
-	bool do_locking = false;
-	NTSTATUS status;
-	bool ok;
-
-	req = tevent_req_create(mem_ctx, &state,
-				struct btrfs_offload_write_state);
-	if (req == NULL) {
-		return NULL;
-	}
-
-	state->handle = handle;
-
-	tevent_req_set_cleanup_fn(req, btrfs_offload_write_cleanup);
-
-	status = vfs_offload_token_db_fetch_fsp(btrfs_offload_ctx,
-						token, &src_fsp);
-	if (tevent_req_nterror(req, status)) {
-		return tevent_req_post(req, ev);
-	}
-
-	switch (fsctl) {
-	case FSCTL_SRV_COPYCHUNK:
-	case FSCTL_SRV_COPYCHUNK_WRITE:
-		do_locking = true;
-		break;
-
-	case FSCTL_DUP_EXTENTS_TO_FILE:
-		/* dup extents does not use locking */
-		break;
-
-	default:
-		handle_offload_write = false;
-		break;
-	}
-
-	if (num == 0) {
-		/*
-		 * With a @src_length of zero, BTRFS_IOC_CLONE_RANGE clones
-		 * all data from @src_offset->EOF! This is certainly not what
-		 * the caller expects, and not what vfs_default does.
-		 */
-		handle_offload_write = false;
-	}
-
-	if (!handle_offload_write) {
-		subreq = SMB_VFS_NEXT_OFFLOAD_WRITE_SEND(handle,
-							 state,
-							 ev,
-							 fsctl,
-							 token,
-							 transfer_offset,
-							 dest_fsp,
-							 dest_off,
-							 num);
-		if (tevent_req_nomem(subreq, req)) {
-			return tevent_req_post(req, ev);
-		}
-		tevent_req_set_callback(subreq,
-					btrfs_offload_write_done,
-					req);
-		return req;
-	}
-
-	status = vfs_offload_token_check_handles(
-		fsctl, src_fsp, dest_fsp);
-	if (!NT_STATUS_IS_OK(status)) {
-		tevent_req_nterror(req, status);
-		return tevent_req_post(req, ev);
-	}
-
-	ok = become_user_without_service_by_fsp(src_fsp);
-	if (!ok) {
-		tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
-		return tevent_req_post(req, ev);
-	}
-	state->need_unbecome_user = true;
-
-	status = vfs_stat_fsp(src_fsp);
-	if (tevent_req_nterror(req, status)) {
-		return tevent_req_post(req, ev);
-	}
-
-	if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
-		/* [MS-SMB2] Handling a Server-Side Data Copy Request */
-		tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
-		return tevent_req_post(req, ev);
-	}
-
-	if (do_locking) {
-		init_strict_lock_struct(src_fsp,
-					src_fsp->op->global->open_persistent_id,
-					src_off,
-					num,
-					READ_LOCK,
-					lp_posix_cifsu_locktype(src_fsp),
-					&src_lck);
-		if (!SMB_VFS_STRICT_LOCK_CHECK(src_fsp->conn, src_fsp, &src_lck)) {
-			tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
-			return tevent_req_post(req, ev);
-		}
-	}
-
-	ok = unbecome_user_without_service();
-	SMB_ASSERT(ok);
-	state->need_unbecome_user = false;
-
-	if (do_locking) {
-		init_strict_lock_struct(dest_fsp,
-					dest_fsp->op->global->open_persistent_id,
-					dest_off,
-					num,
-					WRITE_LOCK,
-					lp_posix_cifsu_locktype(dest_fsp),
-					&dest_lck);
-
-		if (!SMB_VFS_STRICT_LOCK_CHECK(dest_fsp->conn, dest_fsp, &dest_lck)) {
-			tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
-			return tevent_req_post(req, ev);
-		}
-	}
-
-	ZERO_STRUCT(cr_args);
-	cr_args.src_fd = fsp_get_io_fd(src_fsp);
-	cr_args.src_offset = (uint64_t)src_off;
-	cr_args.dest_offset = (uint64_t)dest_off;
-	cr_args.src_length = (uint64_t)num;
-
-	ret = ioctl(fsp_get_io_fd(dest_fsp), BTRFS_IOC_CLONE_RANGE, &cr_args);
-	if (ret < 0) {
-		/*
-		 * BTRFS_IOC_CLONE_RANGE only supports 'sectorsize' aligned
-		 * cloning. Which is 4096 by default, therefore fall back to
-		 * manual read/write on failure.
-		 */
-		DEBUG(5, ("BTRFS_IOC_CLONE_RANGE failed: %s, length %llu, "
-			  "src fd: %lld off: %llu, dest fd: %d off: %llu\n",
-			  strerror(errno),
-			  (unsigned long long)cr_args.src_length,
-			  (long long)cr_args.src_fd,
-			  (unsigned long long)cr_args.src_offset,
-			  fsp_get_io_fd(dest_fsp),
-			  (unsigned long long)cr_args.dest_offset));
-		subreq = SMB_VFS_NEXT_OFFLOAD_WRITE_SEND(handle,
-							 state,
-							 ev,
-							 fsctl,
-							 token,
-							 transfer_offset,
-							 dest_fsp,
-							 dest_off,
-							 num);
-		if (tevent_req_nomem(subreq, req)) {
-			return tevent_req_post(req, ev);
-		}
-		/* wait for subreq completion */
-		tevent_req_set_callback(subreq,
-					btrfs_offload_write_done,
-					req);
-		return req;
-	}
-
-	DEBUG(5, ("BTRFS_IOC_CLONE_RANGE returned %d\n", ret));
-	/* BTRFS_IOC_CLONE_RANGE is all or nothing */
-	state->copied = num;
-	tevent_req_done(req);
-	return tevent_req_post(req, ev);
-}
-
-/* only used if the request is passed through to next VFS module */
-static void btrfs_offload_write_done(struct tevent_req *subreq)
-{
-	struct tevent_req *req =
-		tevent_req_callback_data(subreq,
-		struct tevent_req);
-	struct btrfs_offload_write_state *state =
-		tevent_req_data(req,
-		struct btrfs_offload_write_state);
-	NTSTATUS status;
-
-	status = SMB_VFS_NEXT_OFFLOAD_WRITE_RECV(state->handle,
-						 subreq,
-						 &state->copied);
-	TALLOC_FREE(subreq);
-	if (tevent_req_nterror(req, status)) {
-		return;
-	}
-	tevent_req_done(req);
-}
-
-static NTSTATUS btrfs_offload_write_recv(struct vfs_handle_struct *handle,
-					 struct tevent_req *req,
-					 off_t *copied)
-{
-	struct btrfs_offload_write_state *state =
-		tevent_req_data(req,
-		struct btrfs_offload_write_state);
-	NTSTATUS status;
-
-	if (tevent_req_is_nterror(req, &status)) {
-		DEBUG(4, ("server side copy chunk failed: %s\n",
-			  nt_errstr(status)));
-		tevent_req_received(req);
-		return status;
-	}
-
-	DEBUG(10, ("server side copy chunk copied %llu\n",
-		   (unsigned long long)state->copied));
-	*copied = state->copied;
-	tevent_req_received(req);
-	return NT_STATUS_OK;
-}
-
 static NTSTATUS btrfs_fget_compression(struct vfs_handle_struct *handle,


-- 
Samba Shared Repository



More information about the samba-cvs mailing list