# End
# Checks for the vfs_fileid module
+# Check for btrfs support
+AC_CACHE_CHECK([for btrfs],samba_cv_have_btrfs, [
+ AC_TRY_COMPILE([#include <asm-generic/int-ll64.h>
+ #include <btrfs/btrfs_ioctl.h>],
+ [struct btrfs_ioctl_clone_range_args cr;],
+ samba_cv_have_btrfs=yes,
+ samba_cv_have_btrfs=no)])
+if test x"$samba_cv_have_btrfs" = x"yes"; then
+ AC_DEFINE(HAVE_BTRFS, 1, [If btrfs ioctls are available])
+ default_shared_modules="$default_shared_modules vfs_btrfs"
+fi
+# End btrfs
for i in `echo $default_static_modules | sed -e 's/,/ /g'`
do
SMB_MODULE(vfs_linux_xfs_sgid, \$(VFS_LINUX_XFS_SGID_OBJ), "bin/linux_xfs_sgid.$SHLIBEXT", VFS)
SMB_MODULE(vfs_time_audit, \$(VFS_TIME_AUDIT_OBJ), "bin/time_audit.$SHLIBEXT", VFS)
SMB_MODULE(vfs_media_harmony, \$(VFS_MEDIA_HARMONY_OBJ), "bin/media_harmony.$SHLIBEXT", VFS)
+SMB_MODULE(vfs_btrfs, \$(VFS_BTRFS_OBJ), "bin/btrfs.$SHLIBEXT", VFS)
SMB_SUBSYSTEM(VFS,smbd/vfs.o)
--- /dev/null
+/*
+ * Module to make use of awesome btrfs features
+ *
+ * Copyright (C) David Disseldorp 2011
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <asm-generic/int-ll64.h>
+#include <btrfs/btrfs_ioctl.h>
+#include "includes.h"
+#include "system/filesys.h"
+#include "smbd/smbd.h"
+#include "lib/util/tevent_ntstatus.h"
+
+struct btrfs_cc_state {
+ struct vfs_handle_struct *handle;
+ SMB_OFF_T copied;
+ NTSTATUS status;
+ struct tevent_req *subreq; /* non-null if passed to next VFS fn */
+};
+static void btrfs_copy_chunk_done(struct tevent_req *subreq);
+
+static struct tevent_req *btrfs_copy_chunk_send(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct files_struct *src_fsp,
+ SMB_OFF_T src_off,
+ struct files_struct *dest_fsp,
+ SMB_OFF_T dest_off,
+ SMB_OFF_T num)
+{
+ struct tevent_req *req;
+ struct btrfs_cc_state *cc_state;
+ struct btrfs_ioctl_clone_range_args cr_args;
+ int ret;
+
+ req = tevent_req_create(mem_ctx, &cc_state, struct btrfs_cc_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ cc_state->handle = handle;
+ cc_state->status = NT_STATUS_OK;
+
+ ZERO_STRUCT(cr_args);
+ cr_args.src_fd = src_fsp->fh->fd;
+ 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(dest_fsp->fh->fd, 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), cr_args.src_length,
+ cr_args.src_fd, cr_args.src_offset,
+ dest_fsp->fh->fd, cr_args.dest_offset));
+ cc_state->subreq = SMB_VFS_NEXT_COPY_CHUNK_SEND(handle,
+ cc_state, ev,
+ src_fsp,
+ src_off,
+ dest_fsp,
+ dest_off, num);
+ if (tevent_req_nomem(cc_state->subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ /* wait for subreq completion */
+ tevent_req_set_callback(cc_state->subreq,
+ btrfs_copy_chunk_done,
+ req);
+ return req;
+
+ }
+
+ DEBUG(5, ("BTRFS_IOC_CLONE_RANGE returned %d\n", ret));
+ /* BTRFS_IOC_CLONE_RANGE is all or nothing */
+ cc_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_copy_chunk_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct btrfs_cc_state *cc_state = tevent_req_data(req,
+ struct btrfs_cc_state);
+
+ cc_state->status = SMB_VFS_NEXT_COPY_CHUNK_RECV(cc_state->handle,
+ cc_state->subreq, &cc_state->copied);
+ if (tevent_req_nterror(req, cc_state->status)) {
+ return;
+ }
+ tevent_req_done(req);
+}
+
+static NTSTATUS btrfs_copy_chunk_recv(struct vfs_handle_struct *handle,
+ struct tevent_req *req,
+ SMB_OFF_T *copied)
+{
+ struct btrfs_cc_state *cc_state = tevent_req_data(req,
+ struct btrfs_cc_state);
+
+ DEBUG(10,("server side copy chunk copied %lu\n", cc_state->copied));
+
+ *copied = cc_state->copied;
+ return cc_state->status;
+}
+
+static struct vfs_fn_pointers btrfs_fns = {
+ .copy_chunk_send_fn = btrfs_copy_chunk_send,
+ .copy_chunk_recv_fn = btrfs_copy_chunk_recv,
+};
+
+NTSTATUS vfs_btrfs_init(void);
+NTSTATUS vfs_btrfs_init(void)
+{
+ return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
+ "btrfs", &btrfs_fns);
+}
if conf.CHECK_HEADERS('gpfs_gpl.h'):
conf.DEFINE('HAVE_GPFS', '1')
+ conf.CHECK_CODE('''
+ #include <asm-generic/int-ll64.h>
+ #include <btrfs/btrfs_ioctl.h>
+ struct btrfs_ioctl_clone_range_args cr;
+ ''',
+ 'HAVE_BTRFS',
+ msg='Checking whether btrfs ioctls are available')
+
default_static_modules.extend(TO_LIST('''pdb_smbpasswd pdb_tdbsam pdb_wbc_sam
auth_sam auth_unix auth_winbind auth_wbc
auth_domain auth_builtin vfs_default
if conf.CONFIG_SET('HAVE_GPFS'):
default_shared_modules.extend(TO_LIST('vfs_gpfs'))
+ if conf.CONFIG_SET('HAVE_BTRFS'):
+ default_shared_modules.extend(TO_LIST('vfs_btrfs'))
+
explicit_shared_modules = TO_LIST(Options.options.shared_modules, delimiter=',')
explicit_static_modules = TO_LIST(Options.options.static_modules, delimiter=',')