The Samba-Bugzilla – Attachment 5471 Details for
Bug 7223
implementation of rename beyond filesystem boundaries is too limited
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
patch for 3.5.0
samba3-crossrename.patch (text/plain), 16.53 KB, created by
Björn Jacke
on 2010-03-08 11:29:10 UTC
(
hide
)
Description:
patch for 3.5.0
Filename:
MIME Type:
Creator:
Björn Jacke
Created:
2010-03-08 11:29:10 UTC
Size:
16.53 KB
patch
obsolete
>From 433d1b5816a9a2befdf86c806f1ae79f7d35bef4 Mon Sep 17 00:00:00 2001 >From: =?UTF-8?q?Bj=C3=B6rn=20Jacke?= <bj@sernet.de> >Date: Mon, 8 Mar 2010 12:52:13 +0100 >Subject: [PATCH 1/3] s3: remove cross-device rename support from vfs_default > >cross-device rename support has some major limitations: > >- on huge files clients will timeout or hang >- ACLs and EA information is not retained > >Usually a client will have to handle this. A Windows Server with a reparse >point will also just return NT_STATUS_NOT_SAME_DEVICE. We will now by default >do the same. > >I will add a vfs module which will restore the old cross-device renames. >--- > source3/modules/vfs_default.c | 116 ----------------------------------------- > 1 files changed, 0 insertions(+), 116 deletions(-) > >diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c >index 6e2a571..faca292 100644 >--- a/source3/modules/vfs_default.c >+++ b/source3/modules/vfs_default.c >@@ -475,117 +475,6 @@ static ssize_t vfswrap_recvfile(vfs_handle_struct *handle, > return result; > } > >-/********************************************************* >- For rename across filesystems Patch from Warren Birnbaum >- <warrenb@hpcvscdp.cv.hp.com> >-**********************************************************/ >- >-static int copy_reg(const char *source, const char *dest) >-{ >- SMB_STRUCT_STAT source_stats; >- int saved_errno; >- int ifd = -1; >- int ofd = -1; >- >- if (sys_lstat(source, &source_stats, false) == -1) >- return -1; >- >- if (!S_ISREG (source_stats.st_ex_mode)) >- return -1; >- >- if((ifd = sys_open (source, O_RDONLY, 0)) < 0) >- return -1; >- >- if (unlink (dest) && errno != ENOENT) >- return -1; >- >-#ifdef O_NOFOLLOW >- if((ofd = sys_open (dest, O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, 0600)) < 0 ) >-#else >- if((ofd = sys_open (dest, O_WRONLY | O_CREAT | O_TRUNC , 0600)) < 0 ) >-#endif >- goto err; >- >- if (transfer_file(ifd, ofd, (size_t)-1) == -1) >- goto err; >- >- /* >- * Try to preserve ownership. For non-root it might fail, but that's ok. >- * But root probably wants to know, e.g. if NFS disallows it. >- */ >- >-#ifdef HAVE_FCHOWN >- if ((fchown(ofd, source_stats.st_ex_uid, source_stats.st_ex_gid) == -1) && (errno != EPERM)) >-#else >- if ((chown(dest, source_stats.st_ex_uid, source_stats.st_ex_gid) == -1) && (errno != EPERM)) >-#endif >- goto err; >- >- /* >- * fchown turns off set[ug]id bits for non-root, >- * so do the chmod last. >- */ >- >-#if defined(HAVE_FCHMOD) >- if (fchmod (ofd, source_stats.st_ex_mode & 07777)) >-#else >- if (chmod (dest, source_stats.st_ex_mode & 07777)) >-#endif >- goto err; >- >- if (close (ifd) == -1) >- goto err; >- >- if (close (ofd) == -1) >- return -1; >- >- /* Try to copy the old file's modtime and access time. */ >-#if defined(HAVE_UTIMENSAT) >- { >- struct timespec ts[2]; >- >- ts[0] = source_stats.st_ex_atime; >- ts[1] = source_stats.st_ex_mtime; >- utimensat(AT_FDCWD, dest, ts, AT_SYMLINK_NOFOLLOW); >- } >-#elif defined(HAVE_UTIMES) >- { >- struct timeval tv[2]; >- >- tv[0] = convert_timespec_to_timeval(source_stats.st_ex_atime); >- tv[1] = convert_timespec_to_timeval(source_stats.st_ex_mtime); >-#ifdef HAVE_LUTIMES >- lutimes(dest, tv); >-#else >- utimes(dest, tv); >-#endif >- } >-#elif defined(HAVE_UTIME) >- { >- struct utimbuf tv; >- >- tv.actime = convert_timespec_to_time_t(source_stats.st_ex_atime); >- tv.modtime = convert_timespec_to_time_t(source_stats.st_ex_mtime); >- utime(dest, &tv); >- } >-#endif >- >- if (unlink (source) == -1) >- return -1; >- >- return 0; >- >- err: >- >- saved_errno = errno; >- if (ifd != -1) >- close(ifd); >- if (ofd != -1) >- close(ofd); >- errno = saved_errno; >- return -1; >-} >- > static int vfswrap_rename(vfs_handle_struct *handle, > const struct smb_filename *smb_fname_src, > const struct smb_filename *smb_fname_dst) >@@ -600,11 +489,6 @@ static int vfswrap_rename(vfs_handle_struct *handle, > } > > result = rename(smb_fname_src->base_name, smb_fname_dst->base_name); >- if ((result == -1) && (errno == EXDEV)) { >- /* Rename across filesystems needed. */ >- result = copy_reg(smb_fname_src->base_name, >- smb_fname_dst->base_name); >- } > > out: > END_PROFILE(syscall_rename); >-- >1.6.6.1 > > >From 6dc931b27daf06aa1f4cdca19dae44ffef0bc3fb Mon Sep 17 00:00:00 2001 >From: =?UTF-8?q?Bj=C3=B6rn=20Jacke?= <bj@sernet.de> >Date: Mon, 8 Mar 2010 18:18:59 +0100 >Subject: [PATCH 2/3] s3: add vfs_crossrename > >this module adds optional server-side support for limited rename operations >beyond filesystem boundaries, which was the previously the default. >--- > source3/Makefile.in | 5 + > source3/configure.in | 3 +- > source3/modules/vfs_crossrename.c | 200 +++++++++++++++++++++++++++++++++++++ > 3 files changed, 207 insertions(+), 1 deletions(-) > create mode 100644 source3/modules/vfs_crossrename.c > >diff --git a/source3/Makefile.in b/source3/Makefile.in >index f84ed20..2b90958 100644 >--- a/source3/Makefile.in >+++ b/source3/Makefile.in >@@ -741,6 +741,7 @@ PERFCOUNT_ONEFS_OBJ = modules/perfcount_onefs.o > PERFCOUNT_TEST_OBJ = modules/perfcount_test.o > VFS_DIRSORT_OBJ = modules/vfs_dirsort.o > VFS_SCANNEDONLY_OBJ = modules/vfs_scannedonly.o >+VFS_CROSSRENAME_OBJ = modules/vfs_crossrename.o > > PLAINTEXT_AUTH_OBJ = auth/pampass.o auth/pass_check.o > >@@ -2846,6 +2847,10 @@ bin/scannedonly.@SHLIBEXT@: $(BINARY_PREREQS) $(VFS_SCANNEDONLY_OBJ) > @echo "Building plugin $@" > @$(SHLD_MODULE) $(VFS_SCANNEDONLY_OBJ) > >+bin/crossrename.@SHLIBEXT@: $(BINARY_PREREQS) $(VFS_CROSSRENAME_OBJ) >+ @echo "Building plugin $@" >+ @$(SHLD_MODULE) $(VFS_CROSSRENAME_OBJ) >+ > ######################################################### > ## IdMap NSS plugins > >diff --git a/source3/configure.in b/source3/configure.in >index 0529a69..dbbc5be 100644 >--- a/source3/configure.in >+++ b/source3/configure.in >@@ -387,7 +387,7 @@ dnl These have to be built static: > default_static_modules="pdb_smbpasswd pdb_tdbsam pdb_wbc_sam rpc_lsarpc rpc_samr rpc_winreg rpc_initshutdown rpc_dssetup rpc_wkssvc rpc_svcctl rpc_ntsvcs rpc_netlogon rpc_netdfs rpc_srvsvc rpc_spoolss rpc_eventlog auth_sam auth_unix auth_winbind auth_wbc auth_server auth_domain auth_builtin auth_netlogond vfs_default nss_info_template" > > dnl These are preferably build shared, and static if dlopen() is not available >-default_shared_modules="vfs_recycle vfs_audit vfs_extd_audit vfs_full_audit vfs_netatalk vfs_fake_perms vfs_default_quota vfs_readonly vfs_cap vfs_expand_msdfs vfs_shadow_copy vfs_shadow_copy2 charset_CP850 charset_CP437 auth_script vfs_readahead vfs_xattr_tdb vfs_streams_xattr vfs_streams_depot vfs_acl_xattr vfs_acl_tdb vfs_smb_traffic_analyzer vfs_preopen vfs_catia vfs_scannedonly" >+default_shared_modules="vfs_recycle vfs_audit vfs_extd_audit vfs_full_audit vfs_netatalk vfs_fake_perms vfs_default_quota vfs_readonly vfs_cap vfs_expand_msdfs vfs_shadow_copy vfs_shadow_copy2 charset_CP850 charset_CP437 auth_script vfs_readahead vfs_xattr_tdb vfs_streams_xattr vfs_streams_depot vfs_acl_xattr vfs_acl_tdb vfs_smb_traffic_analyzer vfs_preopen vfs_catia vfs_scannedonly vfs_crossrename" > > if test "x$developer" = xyes; then > default_static_modules="$default_static_modules rpc_rpcecho pdb_ads" >@@ -6571,6 +6571,7 @@ SMB_MODULE(vfs_onefs, \$(VFS_ONEFS), "bin/onefs.$SHLIBEXT", VFS) > SMB_MODULE(vfs_onefs_shadow_copy, \$(VFS_ONEFS_SHADOW_COPY), "bin/onefs_shadow_copy.$SHLIBEXT", VFS) > SMB_MODULE(vfs_dirsort, \$(VFS_DIRSORT_OBJ), "bin/dirsort.$SHLIBEXT", VFS) > SMB_MODULE(vfs_scannedonly, \$(VFS_SCANNEDONLY_OBJ), "bin/scannedonly.$SHLIBEXT", VFS) >+SMB_MODULE(vfs_crossrename, \$(VFS_CROSSRENAME_OBJ), "bin/crossrename.$SHLIBEXT", VFS) > > SMB_SUBSYSTEM(VFS,smbd/vfs.o) > >diff --git a/source3/modules/vfs_crossrename.c b/source3/modules/vfs_crossrename.c >new file mode 100644 >index 0000000..323ceb1 >--- /dev/null >+++ b/source3/modules/vfs_crossrename.c >@@ -0,0 +1,200 @@ >+/* >+ * Copyright (c) Björn Jacke 2010 >+ * >+ * 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 "includes.h" >+ >+ >+#define MODULE "crossrename" >+static SMB_OFF_T module_sizelimit; >+ >+static int crossrename_connect( >+ struct vfs_handle_struct * handle, >+ const char * service, >+ const char * user) >+{ >+ int ret = SMB_VFS_NEXT_CONNECT(handle, service, user); >+ >+ if (ret < 0) { >+ return ret; >+ } >+ >+ module_sizelimit = (SMB_OFF_T) lp_parm_int(SNUM(handle->conn), >+ MODULE, "sizelimit", 20); >+ /* convert from MiB to byte: */ >+ module_sizelimit *= 1048576; >+ >+ return 0; >+} >+ >+/********************************************************* >+ For rename across filesystems initial Patch from Warren Birnbaum >+ <warrenb@hpcvscdp.cv.hp.com> >+**********************************************************/ >+ >+static int copy_reg(const char *source, const char *dest) >+{ >+ SMB_STRUCT_STAT source_stats; >+ int saved_errno; >+ int ifd = -1; >+ int ofd = -1; >+ >+ if (sys_lstat(source, &source_stats, false) == -1) >+ return -1; >+ >+ if (!S_ISREG (source_stats.st_ex_mode)) >+ return -1; >+ >+ if (source_stats.st_ex_size > module_sizelimit) { >+ DEBUG(5, >+ ("%s: size of %s larger than sizelimit (%lld > %lld), rename prohititted\n", >+ MODULE, source, >+ (long long)source_stats.st_ex_size, >+ (long long)module_sizelimit)); >+ return -1; >+ } >+ >+ if((ifd = sys_open (source, O_RDONLY, 0)) < 0) >+ return -1; >+ >+ if (unlink (dest) && errno != ENOENT) >+ return -1; >+ >+#ifdef O_NOFOLLOW >+ if((ofd = sys_open (dest, O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, 0600)) < 0 ) >+#else >+ if((ofd = sys_open (dest, O_WRONLY | O_CREAT | O_TRUNC , 0600)) < 0 ) >+#endif >+ goto err; >+ >+ if (transfer_file(ifd, ofd, (size_t)-1) == -1) >+ goto err; >+ >+ /* >+ * Try to preserve ownership. For non-root it might fail, but that's ok. >+ * But root probably wants to know, e.g. if NFS disallows it. >+ */ >+ >+#ifdef HAVE_FCHOWN >+ if ((fchown(ofd, source_stats.st_ex_uid, source_stats.st_ex_gid) == -1) && (errno != EPERM)) >+#else >+ if ((chown(dest, source_stats.st_ex_uid, source_stats.st_ex_gid) == -1) && (errno != EPERM)) >+#endif >+ goto err; >+ >+ /* >+ * fchown turns off set[ug]id bits for non-root, >+ * so do the chmod last. >+ */ >+ >+#if defined(HAVE_FCHMOD) >+ if (fchmod (ofd, source_stats.st_ex_mode & 07777)) >+#else >+ if (chmod (dest, source_stats.st_ex_mode & 07777)) >+#endif >+ goto err; >+ >+ if (close (ifd) == -1) >+ goto err; >+ >+ if (close (ofd) == -1) >+ return -1; >+ >+ /* Try to copy the old file's modtime and access time. */ >+#if defined(HAVE_UTIMENSAT) >+ { >+ struct timespec ts[2]; >+ >+ ts[0] = source_stats.st_ex_atime; >+ ts[1] = source_stats.st_ex_mtime; >+ utimensat(AT_FDCWD, dest, ts, AT_SYMLINK_NOFOLLOW); >+ } >+#elif defined(HAVE_UTIMES) >+ { >+ struct timeval tv[2]; >+ >+ tv[0] = convert_timespec_to_timeval(source_stats.st_ex_atime); >+ tv[1] = convert_timespec_to_timeval(source_stats.st_ex_mtime); >+#ifdef HAVE_LUTIMES >+ lutimes(dest, tv); >+#else >+ utimes(dest, tv); >+#endif >+ } >+#elif defined(HAVE_UTIME) >+ { >+ struct utimbuf tv; >+ >+ tv.actime = convert_timespec_to_time_t(source_stats.st_ex_atime); >+ tv.modtime = convert_timespec_to_time_t(source_stats.st_ex_mtime); >+ utime(dest, &tv); >+ } >+#endif >+ >+ if (unlink (source) == -1) >+ return -1; >+ >+ return 0; >+ >+ err: >+ >+ saved_errno = errno; >+ if (ifd != -1) >+ close(ifd); >+ if (ofd != -1) >+ close(ofd); >+ errno = saved_errno; >+ return -1; >+} >+ >+ >+static int crossrename_rename(vfs_handle_struct *handle, >+ const struct smb_filename *smb_fname_src, >+ const struct smb_filename *smb_fname_dst) >+{ >+ int result = -1; >+ >+ START_PROFILE(syscall_rename); >+ >+ if (smb_fname_src->stream_name || smb_fname_dst->stream_name) { >+ errno = ENOENT; >+ goto out; >+ } >+ >+ result = rename(smb_fname_src->base_name, smb_fname_dst->base_name); >+ if ((result == -1) && (errno == EXDEV)) { >+ /* Rename across filesystems needed. */ >+ result = copy_reg(smb_fname_src->base_name, >+ smb_fname_dst->base_name); >+ } >+ >+ out: >+ END_PROFILE(syscall_rename); >+ return result; >+} >+ >+static struct vfs_fn_pointers vfs_crossrename_fns = { >+ .connect_fn = crossrename_connect, >+ .rename = crossrename_rename >+}; >+ >+NTSTATUS vfs_crossrename_init(void); >+NTSTATUS vfs_crossrename_init(void) >+{ >+ return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, MODULE, >+ &vfs_crossrename_fns); >+} >+ >-- >1.6.6.1 > > >From 555acebc72c2827691e91648f697212ffa6725d4 Mon Sep 17 00:00:00 2001 >From: =?UTF-8?q?Bj=C3=B6rn=20Jacke?= <bj@sernet.de> >Date: Mon, 8 Mar 2010 12:38:38 +0100 >Subject: [PATCH 3/3] s3: add man page for vfs_crossrename > >--- > docs-xml/manpages-3/vfs_crossrename.8.xml | 115 +++++++++++++++++++++++++++++ > 1 files changed, 115 insertions(+), 0 deletions(-) > create mode 100644 docs-xml/manpages-3/vfs_crossrename.8.xml > >diff --git a/docs-xml/manpages-3/vfs_crossrename.8.xml b/docs-xml/manpages-3/vfs_crossrename.8.xml >new file mode 100644 >index 0000000..675c92e >--- /dev/null >+++ b/docs-xml/manpages-3/vfs_crossrename.8.xml >@@ -0,0 +1,115 @@ >+<?xml version="1.0" encoding="iso-8859-1"?> >+<!DOCTYPE refentry PUBLIC "-//Samba-Team//DTD DocBook V4.2-Based Variant V1.0//EN" "http://www.samba.org/samba/DTD/samba-doc"> >+<refentry id="vfs_crossrename.8"> >+ >+<refmeta> >+ <refentrytitle>vfs_crossrename</refentrytitle> >+ <manvolnum>8</manvolnum> >+ <refmiscinfo class="source">Samba</refmiscinfo> >+ <refmiscinfo class="manual">System Administration tools</refmiscinfo> >+ <refmiscinfo class="version">3.6</refmiscinfo> >+</refmeta> >+ >+ >+<refnamediv> >+ <refname>vfs_crossrename</refname> >+ <refpurpose>server side rename files across filesystem boundaries</refpurpose> >+</refnamediv> >+ >+<refsynopsisdiv> >+ <cmdsynopsis> >+ <command>vfs objects = crossrename</command> >+ </cmdsynopsis> >+</refsynopsisdiv> >+ >+<refsect1> >+ <title>DESCRIPTION</title> >+ >+ <para>This VFS module is part of the >+ <citerefentry><refentrytitle>samba</refentrytitle> >+ <manvolnum>7</manvolnum></citerefentry> suite.</para> >+ >+ <para>The <command>vfs_crossrename</command> VFS module allows >+ server side rename operations even if source and target are on >+ differen physical devices. A "move" in Explorer is usually a >+ rename operation if it is inside of a single share or device. >+ Usually such a rename operation returns >+ NT_STATUS_NOT_SAME_DEVICE and the client has to move the file by >+ manual copy and delete operations. If the rename by copy is done by the >+ server this can be much more efficient. vfs_crossrename tries to do >+ this server-side cross-device rename operation. There are however >+ limitations that this module currently does not solve: >+ >+ <variablelist> >+ <varlistentry> >+ the ACLs of files are not preserved >+ </varlistentry> >+ <varlistentry> >+ meta data in EAs are not preserved >+ </varlistentry> >+ <varlistentry> >+ renames of whole subdirectories cannot be done recursively, >+ in that case we still return STATUS_NOT_SAME_DEVICE and >+ let the client decide what to do >+ </varlistentry> >+ <varlistentry> >+ rename operations of huge files can cause hangs on the >+ client because clients expect a rename operation to >+ return fast >+ </varlistentry> >+ </variablelist> >+ </para> >+ >+ <para>This module is stackable.</para> >+ >+</refsect1> >+ >+ >+<refsect1> >+ <title>OPTIONS</title> >+ >+ <variablelist> >+ >+ <varlistentry> >+ <term>crossrename:sizelimit = BYTES</term> >+ <listitem> >+ <para>server-side cross-device-renames are only done >+ for files if the filesize is not larger than the defined >+ size in MiB to prevent timeouts. The default sizelimit is >+ 20 (MiB) >+ </para> >+ </varlistentry> >+ </variablelist> >+</refsect1> >+ >+<refsect1> >+ <title>EXAMPLES</title> >+ >+ <para>To add server-side cross-device renames inside of a share >+ for all files sized up to 50MB:</para> >+ >+<programlisting> >+ <smbconfsection name="[testshare]"/> >+ <smbconfoption name="path">/data/mounts</smbconfoption> >+ <smbconfoption name="vfs objects">crossrename</smbconfoption> >+ <smbconfoption name="crossrename:sizelimit">50</smbconfoption> >+</programlisting> >+</refsect1> >+ >+<refsect1> >+ <title>VERSION</title> >+ <para>This man page is correct for version 3.6.0 of the Samba suite. >+ </para> >+</refsect1> >+ >+<refsect1> >+ <title>AUTHOR</title> >+ >+ <para>The original Samba software and related utilities >+ were created by Andrew Tridgell. Samba is now developed >+ by the Samba Team as an Open Source project similar >+ to the way the Linux kernel is developed.</para> >+ >+</refsect1> >+ >+</refentry> >-- >1.6.6.1 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Flags:
jra
:
review+
Actions:
View
Attachments on
bug 7223
: 5471