smbd: Implement and use full_path_tos
authorVolker Lendecke <vl@samba.org>
Fri, 6 Dec 2013 14:34:05 +0000 (14:34 +0000)
committerStefan Metzmacher <metze@samba.org>
Sat, 14 Dec 2013 10:21:32 +0000 (11:21 +0100)
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>
source3/smbd/files.c
source3/smbd/notify.c
source3/smbd/proto.h

index c64c84173cfcc10119418f6091801c13d578e980..ba24eda27f3d555b99cfa91df6617bef0c80e1d3 100644 (file)
@@ -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;
 }
 
index 4842d6f2fcb33b4a1ba34e404fa6a6666cb87c76..078bc996601221e590ce1e9a5ae0531861b560e4 100644 (file)
@@ -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)
index a550dd7743dae67315e1e5c24cb8b7dc8e08f547..36012e60d6aadfc50993222a866be1c2044a4f37 100644 (file)
@@ -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  */