From f581a0aea03844752eff655393c5ddfc0e6d68df Mon Sep 17 00:00:00 2001 From: Ondrej Holy Date: Tue, 6 Aug 2019 18:02:02 +0200 Subject: smb: Improve enumeration performance The samba backend calls stat for each file during the enumeration job. Unfortunately, this is significantly slower with the recent samba versions. However, smbc_readdirplus2() has been recently added and it can be used to improve the performance as all the necessary info is transferred in one network request. Let's use smbc_readdirplus2() if available. See: https://gitlab.com/samba-team/samba/merge_requests/302 Relates: https://gitlab.gnome.org/GNOME/gvfs/issues/306 --- daemon/gvfsbackendsmb.c | 45 +++++++++++++++++++++++++++++++++++++-------- meson.build | 1 + 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/daemon/gvfsbackendsmb.c b/daemon/gvfsbackendsmb.c index b0bea3eb..01b1de79 100644 --- a/daemon/gvfsbackendsmb.c +++ b/daemon/gvfsbackendsmb.c @@ -1751,25 +1751,34 @@ do_enumerate (GVfsBackend *backend, GFileQueryInfoFlags flags) { GVfsBackendSmb *op_backend = G_VFS_BACKEND_SMB (backend); - struct stat st; - int res; + struct stat st = { 0 }; GError *error; SMBCFILE *dir; - char dirents[1024*4]; - struct smbc_dirent *dirp; GFileInfo *info; GString *uri; - int uri_start_len; smbc_opendir_fn smbc_opendir; + smbc_closedir_fn smbc_closedir; +#ifndef HAVE_SMBC_READDIRPLUS2 + int res; + char dirents[1024*4]; + struct smbc_dirent *dirp; + int uri_start_len; smbc_getdents_fn smbc_getdents; smbc_stat_fn smbc_stat; - smbc_closedir_fn smbc_closedir; +#else + smbc_readdirplus2_fn smbc_readdirplus2; + const struct libsmb_file_info *exstat; +#endif uri = create_smb_uri_string (op_backend->server, op_backend->port, op_backend->share, filename); smbc_opendir = smbc_getFunctionOpendir (op_backend->smb_context); +#ifndef HAVE_SMBC_READDIRPLUS2 smbc_getdents = smbc_getFunctionGetdents (op_backend->smb_context); smbc_stat = smbc_getFunctionStat (op_backend->smb_context); +#else + smbc_readdirplus2 = smbc_getFunctionReaddirPlus2 (op_backend->smb_context); +#endif smbc_closedir = smbc_getFunctionClosedir (op_backend->smb_context); dir = smbc_opendir (op_backend->smb_context, uri->str); @@ -1789,6 +1798,8 @@ do_enumerate (GVfsBackend *backend, if (uri->str[uri->len - 1] != '/') g_string_append_c (uri, '/'); + +#ifndef HAVE_SMBC_READDIRPLUS2 uri_start_len = uri->len; while (TRUE) @@ -1840,9 +1851,27 @@ do_enumerate (GVfsBackend *backend, dirp = (struct smbc_dirent *) (((char *)dirp) + dirlen); res -= dirlen; } + } +#else + while ((exstat = smbc_readdirplus2 (op_backend->smb_context, dir, &st)) != NULL) + { + if ((S_ISREG (st.st_mode) || + S_ISDIR (st.st_mode) || + S_ISLNK (st.st_mode)) && + g_strcmp0 (exstat->name, ".") != 0 && + g_strcmp0 (exstat->name, "..") != 0) + { + info = g_file_info_new (); + set_info_from_stat (op_backend, info, &st, exstat->name, matcher); + g_vfs_job_enumerate_add_info (job, info); + g_object_unref (info); + } + + memset (&st, 0, sizeof (struct stat)); } - - res = smbc_closedir (op_backend->smb_context, dir); +#endif + + smbc_closedir (op_backend->smb_context, dir); g_vfs_job_enumerate_done (job); diff --git a/meson.build b/meson.build index 22b37da4..30b9abec 100644 --- a/meson.build +++ b/meson.build @@ -394,6 +394,7 @@ if enable_samba smbclient_dep = dependency('smbclient') config_h.set('HAVE_SMBC_SETOPTIONPROTOCOLS', cc.has_function('smbc_setOptionProtocols', dependencies: smbclient_dep)) + config_h.set('HAVE_SMBC_READDIRPLUS2', cc.has_function('smbc_readdirplus2', dependencies: smbclient_dep)) endif # *** Check for libarchive *** -- cgit v1.2.1