[PATCH 5/9] vfs_btrfs: add [GET/SET]_COMPRESSION handlers

David Disseldorp ddiss at samba.org
Wed Sep 18 04:42:46 CEST 2013


Translate such requests into FS_IOC_GETFLAGS and FS_IOC_SETFLAGS ioctls
respectively. The module make no distinction between compression types,
only whether or not compression is enabled.

Signed-off-by: David Disseldorp <ddiss at samba.org>
---
 source3/modules/vfs_btrfs.c | 116 ++++++++++++++++++++++++++++++++++++++++++--
 source3/wscript             |   2 +-
 2 files changed, 114 insertions(+), 4 deletions(-)

diff --git a/source3/modules/vfs_btrfs.c b/source3/modules/vfs_btrfs.c
index f854f2a..6a0494b 100644
--- a/source3/modules/vfs_btrfs.c
+++ b/source3/modules/vfs_btrfs.c
@@ -18,11 +18,16 @@
  */
 
 #include <linux/ioctl.h>
+#include <linux/fs.h>
 #include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
 #include "includes.h"
-#include "system/filesys.h"
 #include "smbd/smbd.h"
-#include "../librpc/gen_ndr/smbXsrv.h"
+#include "librpc/gen_ndr/smbXsrv.h"
+#include "librpc/gen_ndr/ioctl.h"
 #include "lib/util/tevent_ntstatus.h"
 
 struct btrfs_ioctl_clone_range_args {
@@ -107,7 +112,7 @@ static struct tevent_req *btrfs_copy_chunk_send(struct vfs_handle_struct *handle
 	cr_args.src_length = (uint64_t)num;
 
 	ret = ioctl(dest_fsp->fh->fd, BTRFS_IOC_CLONE_RANGE, &cr_args);
-	SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &dest_lck);
+	SMB_VFS_STRICT_UNLOCK(src_fsp->conn, dest_fsp, &dest_lck);
 	SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &src_lck);
 	if (ret < 0) {
 		/*
@@ -187,9 +192,114 @@ static NTSTATUS btrfs_copy_chunk_recv(struct vfs_handle_struct *handle,
 	return NT_STATUS_OK;
 }
 
+/*
+ * caller must pass a non-null fsp or smb_fname. If fsp is null, then
+ * fall back to opening the corresponding file to issue the ioctl.
+ */
+static NTSTATUS btrfs_get_compression(struct vfs_handle_struct *handle,
+				      TALLOC_CTX *mem_ctx,
+				      struct files_struct *fsp,
+				      struct smb_filename *smb_fname,
+				      uint16_t *_compression_fmt)
+{
+	int ret;
+	long flags = 0;
+	int fd;
+	bool opened = false;
+	NTSTATUS status;
+
+	if (fsp != NULL) {
+		fd = fsp->fh->fd;
+	} else if (smb_fname != NULL) {
+		if (S_ISDIR(smb_fname->st.st_ex_mode)) {
+			DIR *dir = opendir(smb_fname->base_name);
+			if (dir == NULL) {
+				return NT_STATUS_UNSUCCESSFUL;
+			}
+			fd = dirfd(dir);
+		} else {
+			fd = open(smb_fname->base_name, O_RDONLY);
+		}
+		if (fd < 0) {
+			return NT_STATUS_UNSUCCESSFUL;
+		}
+		opened = true;
+	} else {
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	ret = ioctl(fd, FS_IOC_GETFLAGS, &flags);
+	if (ret < 0) {
+		DEBUG(1, ("FS_IOC_GETFLAGS failed: %s, fd %lld\n",
+			  strerror(errno), (long long)fd));
+		status = map_nt_error_from_unix(errno);
+		goto err_close;
+	}
+	if (flags & FS_COMPR_FL) {
+		*_compression_fmt = COMPRESSION_FORMAT_LZNT1;
+	} else {
+		*_compression_fmt = COMPRESSION_FORMAT_NONE;
+	}
+	status = NT_STATUS_OK;
+err_close:
+	if (opened) {
+		close(fd);
+	}
+
+	return status;
+}
+
+static NTSTATUS btrfs_set_compression(struct vfs_handle_struct *handle,
+				      TALLOC_CTX *mem_ctx,
+				      struct files_struct *fsp,
+				      uint16_t compression_fmt)
+{
+	int ret;
+	long flags = 0;
+	int fd = fsp->fh->fd;
+	NTSTATUS status;
+
+	ret = ioctl(fd, FS_IOC_GETFLAGS, &flags);
+	if (ret < 0) {
+		DEBUG(1, ("FS_IOC_GETFLAGS failed: %s, fd %d\n",
+			  strerror(errno), fd));
+		status = map_nt_error_from_unix(errno);
+		goto err_out;
+	}
+
+	if (compression_fmt == COMPRESSION_FORMAT_NONE) {
+		DEBUG(5, ("setting compression\n"));
+		flags &= (~FS_COMPR_FL);
+	} else if ((compression_fmt == COMPRESSION_FORMAT_DEFAULT)
+		|| (compression_fmt == COMPRESSION_FORMAT_LZNT1)) {
+		DEBUG(5, ("clearing compression\n"));
+		flags |= FS_COMPR_FL;
+	} else {
+		DEBUG(1, ("invalid compression format 0x%x\n",
+			  (int)compression_fmt));
+		status = NT_STATUS_INVALID_PARAMETER;
+		goto err_out;
+	}
+
+	ret = ioctl(fd, FS_IOC_SETFLAGS, &flags);
+	if (ret < 0) {
+		DEBUG(1, ("FS_IOC_SETFLAGS failed: %s, fd %d\n",
+			  strerror(errno), fd));
+		status = map_nt_error_from_unix(errno);
+		goto err_out;
+	}
+	status = NT_STATUS_OK;
+err_out:
+
+	return status;
+}
+
+
 static struct vfs_fn_pointers btrfs_fns = {
 	.copy_chunk_send_fn = btrfs_copy_chunk_send,
 	.copy_chunk_recv_fn = btrfs_copy_chunk_recv,
+	.get_compression_fn = btrfs_get_compression,
+	.set_compression_fn = btrfs_set_compression,
 };
 
 NTSTATUS vfs_btrfs_init(void);
diff --git a/source3/wscript b/source3/wscript
index 271314d..2edf5e8 100644
--- a/source3/wscript
+++ b/source3/wscript
@@ -1727,7 +1727,7 @@ main() {
     if conf.CHECK_HEADERS('gpfs_gpl.h'):
         conf.DEFINE('HAVE_GPFS', '1')
 
-    if conf.CHECK_HEADERS('linux/ioctl.h sys/ioctl.h'):
+    if conf.CHECK_HEADERS('linux/ioctl.h sys/ioctl.h linux/fs.h'):
 	    conf.DEFINE('HAVE_LINUX_IOCTL', '1')
 
     conf.env['CCFLAGS_CEPHFS'] = "-D_FILE_OFFSET_BITS=64"
-- 
1.8.1.4



More information about the samba-technical mailing list