[SCM] Samba Shared Repository - branch v3-4-test updated -
release-4-0-0alpha7-881-ge4628c6
Tim Prouty
tprouty at samba.org
Tue May 5 23:50:14 GMT 2009
The branch, v3-4-test has been updated
via e4628c6fc7348f56666adc69722809ea539c4fe7 (commit)
via 92558a875ebf842e652614a5519ae101dd62ffd1 (commit)
from f4e2f7bc23da5f73311bb7adeab2838af14bdeaf (commit)
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v3-4-test
- Log -----------------------------------------------------------------
commit e4628c6fc7348f56666adc69722809ea539c4fe7
Author: tprouty <tprouty at b72e2a10-2d34-0410-9a71-d3beadf02b57>
Date: Tue May 5 01:17:04 2009 +0000
s3 onefs: Turn up the debug level for non-error cases
commit 92558a875ebf842e652614a5519ae101dd62ffd1
Author: tprouty <tprouty at b72e2a10-2d34-0410-9a71-d3beadf02b57>
Date: Sat May 2 00:28:38 2009 +0000
s3: Fix trans2 path to use case-insensitive stat optimization
Often times before creating a file, a client will first query to see
if it already exists. Since some systems have a case-insensitive stat
that is called from unix_convert, we can definitively return
STATUS_NO_SUCH_FILE to the client without scanning the whole
directory.
This code path is taken from trans2querypathinfo, but trans2findfirst
still does a full directory scan even though the get_real_filename
(the case-insensitive stat vfs call) can prevent this.
This patch adds the get_real_filename call to the trans2find* path,
and also changes the vfs_default behavior for
SMB_VFS_GET_REAL_FILENAME. Previously, in the absence of a
get_real_filename implementation, we would fallback to the full
directory scan. The default behavior now returns -1 and sets errno to
EOPNOTSUPP. This allows SMB_VFS_GET_REALFILENAME to be called from
trans2* and unix_convert.
-----------------------------------------------------------------------
Summary of changes:
source3/modules/onefs_system.c | 6 +++---
source3/modules/vfs_default.c | 8 ++++++--
source3/smbd/dir.c | 17 +++++++++++++++++
source3/smbd/filename.c | 40 ++++++++++++++++++++++++++++++++++------
4 files changed, 60 insertions(+), 11 deletions(-)
Changeset truncated at 500 lines:
diff --git a/source3/modules/onefs_system.c b/source3/modules/onefs_system.c
index bc2ed46..cf99a27 100644
--- a/source3/modules/onefs_system.c
+++ b/source3/modules/onefs_system.c
@@ -580,7 +580,7 @@ ssize_t onefs_sys_recvfile(int fromfd, int tofd, SMB_OFF_T offset,
/* Log if recvfile didn't write everything it read. */
if (total_rbytes != total_wbytes) {
- DEBUG(0, ("partial recvfile: total_rbytes=%llu but "
+ DEBUG(3, ("partial recvfile: total_rbytes=%llu but "
"total_wbytes=%llu, diff = %llu\n", total_rbytes,
total_wbytes, total_rbytes - total_wbytes));
SMB_ASSERT(total_rbytes > total_wbytes);
@@ -591,7 +591,7 @@ ssize_t onefs_sys_recvfile(int fromfd, int tofd, SMB_OFF_T offset,
*/
while (total_rbytes < count) {
- DEBUG(0, ("shallow recvfile (%s), reading %llu\n",
+ DEBUG(3, ("shallow recvfile (%s), reading %llu\n",
strerror(errno), count - total_rbytes));
/*
@@ -628,7 +628,7 @@ ssize_t onefs_sys_recvfile(int fromfd, int tofd, SMB_OFF_T offset,
*/
while (total_wbytes < count) {
- DEBUG(0, ("partial recvfile, writing %llu\n", count - total_wbytes));
+ DEBUG(3, ("partial recvfile, writing %llu\n", count - total_wbytes));
ret = sys_pwrite(tofd, spill_buffer, count - total_wbytes,
offset + total_wbytes);
diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c
index bb01f98..6c1946a 100644
--- a/source3/modules/vfs_default.c
+++ b/source3/modules/vfs_default.c
@@ -1120,8 +1120,12 @@ static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
TALLOC_CTX *mem_ctx,
char **found_name)
{
- return get_real_filename(handle->conn, path, name, mem_ctx,
- found_name);
+ /*
+ * Don't fall back to get_real_filename so callers can differentiate
+ * between a full directory scan and an actual case-insensitive stat.
+ */
+ errno = EOPNOTSUPP;
+ return -1;
}
static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c
index b4a8f94..e790287 100644
--- a/source3/smbd/dir.c
+++ b/source3/smbd/dir.c
@@ -576,6 +576,9 @@ const char *dptr_ReadDirName(TALLOC_CTX *ctx,
{
char *name = NULL;
char *pathreal = NULL;
+ char *found_name = NULL;
+ int ret;
+
SET_STAT_INVALID(*pst);
if (dptr->has_wild || dptr->did_stat) {
@@ -640,6 +643,20 @@ const char *dptr_ReadDirName(TALLOC_CTX *ctx,
goto clean;
}
+ /*
+ * Try case-insensitive stat if the fs has the ability. This avoids
+ * scanning the whole directory.
+ */
+ ret = SMB_VFS_GET_REAL_FILENAME(dptr->conn, dptr->path, dptr->wcard,
+ ctx, &found_name);
+ if (ret == 0) {
+ name = found_name;
+ goto clean;
+ } else if (errno == ENOENT) {
+ /* The case-insensitive lookup was authoritative. */
+ goto clean;
+ }
+
TALLOC_FREE(pathreal);
return dptr_normal_ReadDirName(dptr, poffset, pst);
diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c
index 80722a7..774ab27 100644
--- a/source3/smbd/filename.c
+++ b/source3/smbd/filename.c
@@ -447,9 +447,9 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
*/
if (name_has_wildcard ||
- (SMB_VFS_GET_REAL_FILENAME(
- conn, dirpath, start,
- talloc_tos(), &found_name) == -1)) {
+ (get_real_filename(conn, dirpath, start,
+ talloc_tos(),
+ &found_name) == -1)) {
char *unmangled;
if (end) {
@@ -789,9 +789,9 @@ static bool fname_equal(const char *name1, const char *name2,
If the name looks like a mangled name then try via the mangling functions
****************************************************************************/
-int get_real_filename(connection_struct *conn, const char *path,
- const char *name, TALLOC_CTX *mem_ctx,
- char **found_name)
+static int get_real_filename_full_scan(connection_struct *conn,
+ const char *path, const char *name,
+ TALLOC_CTX *mem_ctx, char **found_name)
{
struct smb_Dir *cur_dir;
const char *dname;
@@ -887,6 +887,34 @@ int get_real_filename(connection_struct *conn, const char *path,
return -1;
}
+/****************************************************************************
+ Wrapper around the vfs get_real_filename and the full directory scan
+ fallback.
+****************************************************************************/
+
+int get_real_filename(connection_struct *conn, const char *path,
+ const char *name, TALLOC_CTX *mem_ctx,
+ char **found_name)
+{
+ int ret;
+
+ /* Try the vfs first to take advantage of case-insensitive stat. */
+ ret = SMB_VFS_GET_REAL_FILENAME(conn, path, name, mem_ctx, found_name);
+
+ /*
+ * If the case-insensitive stat was successful, or returned an error
+ * other than EOPNOTSUPP then there is no need to fall back on the
+ * full directory scan.
+ */
+ if (ret == 0 || (ret == -1 && errno != EOPNOTSUPP)) {
+ return ret;
+ }
+
+ ret = get_real_filename_full_scan(conn, path, name, mem_ctx,
+ found_name);
+ return ret;
+}
+
static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
connection_struct *conn,
const char *orig_path,
--
Samba Shared Repository
More information about the samba-cvs
mailing list