summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVolker Lendecke <vl@samba.org>2013-12-06 14:34:05 +0000
committerStefan Metzmacher <metze@samba.org>2013-12-14 11:21:32 +0100
commit5baa7402ba8eebd9b2ddc6b259ae9bb2852b4bb1 (patch)
tree15e03048d58e05fb65e19a9b4cbd5d7d0b2da6b1
parent7a06b1661c1423780f05bc35ea435003712ca4b5 (diff)
downloadsamba-5baa7402ba8eebd9b2ddc6b259ae9bb2852b4bb1.tar.gz
samba-5baa7402ba8eebd9b2ddc6b259ae9bb2852b4bb1.tar.xz
samba-5baa7402ba8eebd9b2ddc6b259ae9bb2852b4bb1.zip
smbd: Implement and use full_path_tos
Yes, this looks like a hack, but talloc_asprintf does show up high in profiles called from these routines Signed-off-by: Volker Lendecke <vl@samba.org> Reviewed-by: Stefan Metzmacher <metze@samba.org>
-rw-r--r--source3/smbd/files.c58
-rw-r--r--source3/smbd/notify.c14
-rw-r--r--source3/smbd/proto.h3
3 files changed, 60 insertions, 15 deletions
diff --git a/source3/smbd/files.c b/source3/smbd/files.c
index c64c84173cf..ba24eda27f3 100644
--- a/source3/smbd/files.c
+++ b/source3/smbd/files.c
@@ -688,6 +688,45 @@ NTSTATUS dup_file_fsp(struct smb_request *req, files_struct *from,
return fsp_set_smb_fname(to, from->fsp_name);
}
+/*
+ * This routine improves performance for operations temporarily acting on a
+ * full path. It is equivalent to the much more expensive
+ *
+ * talloc_asprintf(talloc_tos(), "%s/%s", dir, name)
+ *
+ * This actually does make a difference in metadata-heavy workloads (i.e. the
+ * "standard" client.txt nbench run.
+ */
+
+ssize_t full_path_tos(const char *dir, const char *name,
+ char *tmpbuf, size_t tmpbuf_len,
+ char **pdst, char **to_free)
+{
+ size_t dirlen, namelen, len;
+ char *dst;
+
+ dirlen = strlen(dir);
+ namelen = strlen(name);
+ len = dirlen + namelen + 1;
+
+ if (len < tmpbuf_len) {
+ dst = tmpbuf;
+ *to_free = NULL;
+ } else {
+ dst = talloc_array(talloc_tos(), char, len+1);
+ if (dst == NULL) {
+ return -1;
+ }
+ *to_free = dst;
+ }
+
+ memcpy(dst, dir, dirlen);
+ dst[dirlen] = '/';
+ memcpy(dst+dirlen+1, name, namelen+1);
+ *pdst = dst;
+ return len;
+}
+
/**
* Return a jenkins hash of a pathname on a connection.
*/
@@ -695,23 +734,24 @@ NTSTATUS dup_file_fsp(struct smb_request *req, files_struct *from,
NTSTATUS file_name_hash(connection_struct *conn,
const char *name, uint32_t *p_name_hash)
{
- char *fullpath = NULL;
+ char tmpbuf[1024];
+ char *fullpath, *to_free;
+ size_t len;
/* Set the hash of the full pathname. */
- fullpath = talloc_asprintf(talloc_tos(),
- "%s/%s",
- conn->connectpath,
- name);
- if (!fullpath) {
+
+ len = full_path_tos(conn->connectpath, name, tmpbuf, sizeof(tmpbuf),
+ &fullpath, &to_free);
+ if (len == -1) {
return NT_STATUS_NO_MEMORY;
}
- *p_name_hash = hash(fullpath, talloc_get_size(fullpath), 0);
+ *p_name_hash = hash(fullpath, len+1, 0);
DEBUG(10,("file_name_hash: %s hash 0x%x\n",
- fullpath,
+ fullpath,
(unsigned int)*p_name_hash ));
- TALLOC_FREE(fullpath);
+ TALLOC_FREE(to_free);
return NT_STATUS_OK;
}
diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c
index 4842d6f2fcb..078bc996601 100644
--- a/source3/smbd/notify.c
+++ b/source3/smbd/notify.c
@@ -418,19 +418,21 @@ void notify_fname(connection_struct *conn, uint32 action, uint32 filter,
const char *path)
{
struct notify_context *notify_ctx = conn->sconn->notify_ctx;
- char *fullpath;
+ char *fullpath, *to_free;
+ char tmpbuf[1024];
+ ssize_t len;
if (path[0] == '.' && path[1] == '/') {
path += 2;
}
- fullpath = talloc_asprintf(talloc_tos(), "%s/%s", conn->connectpath,
- path);
- if (fullpath == NULL) {
- DEBUG(0, ("asprintf failed\n"));
+ len = full_path_tos(conn->connectpath, path, tmpbuf, sizeof(tmpbuf),
+ &fullpath, &to_free);
+ if (len == -1) {
+ DEBUG(0, ("full_path_tos failed\n"));
return;
}
notify_trigger(notify_ctx, action, filter, fullpath);
- TALLOC_FREE(fullpath);
+ TALLOC_FREE(to_free);
}
static void notify_fsp(files_struct *fsp, uint32 action, const char *name)
diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h
index a550dd7743d..36012e60d6a 100644
--- a/source3/smbd/proto.h
+++ b/source3/smbd/proto.h
@@ -397,6 +397,9 @@ NTSTATUS file_name_hash(connection_struct *conn,
const char *name, uint32_t *p_name_hash);
NTSTATUS fsp_set_smb_fname(struct files_struct *fsp,
const struct smb_filename *smb_fname_in);
+ssize_t full_path_tos(const char *dir, const char *name,
+ char *tmpbuf, size_t tmpbuf_len,
+ char **pdst, char **to_free);
/* The following definitions come from smbd/ipc.c */