summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOndrej Holy <oholy@redhat.com>2019-08-06 18:02:02 +0200
committerOndrej Holy <oholy@redhat.com>2019-11-05 11:40:00 +0100
commitf581a0aea03844752eff655393c5ddfc0e6d68df (patch)
tree831cd43418a2ea40f648b347435e8438eab5ac68
parente4b39b1b51db2b09bec6b231b0009a3d5b343699 (diff)
downloadgvfs-f581a0aea03844752eff655393c5ddfc0e6d68df.tar.gz
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
-rw-r--r--daemon/gvfsbackendsmb.c45
-rw-r--r--meson.build1
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 ***