diff --git a/src/libnsdb/administrator.c b/src/libnsdb/administrator.c
index 050e2b0..5f0c574 100644
--- a/src/libnsdb/administrator.c
+++ b/src/libnsdb/administrator.c
@@ -47,6 +47,82 @@
 #include "xlog.h"
 
 /**
+ * Invoke ldap_search_ext_s(3), requesting no attributes
+ *
+ * @param func NUL-terminated C string containing name of calling function
+ * @param ld an initialized LDAP server descriptor
+ * @param base NUL-terminated C string containing search base
+ * @param scope LDAP scope
+ * @param filter NUL-terminated C string containing search filter
+ * @param response OUT: list of LDAP responses
+ * @return an LDAP result code
+ *
+ */
+static int
+__nsdb_search_nsdb_none_s(const char *func, LDAP *ld, const char *base,
+		int scope, char *filter, LDAPMessage **response)
+{
+	static char *attrs[] = { LDAP_NO_ATTRS, NULL };
+	char *uri;
+
+	if (ldap_get_option(ld, LDAP_OPT_URI, &uri) == LDAP_OPT_SUCCESS) {
+		xlog(D_CALL, "%s:\n  ldapsearch -H %s -b \"%s\" -s %s '%s'",
+			func, uri, base, nsdb_printable_scope(scope), filter);
+		ldap_memfree(uri);
+	} else {
+		xlog(D_CALL, "%s:\n  ldapsearch -b \"%s\" -s %s '%s'",
+			func, base, nsdb_printable_scope(scope), filter);
+	}
+
+	return ldap_search_ext_s(ld, (char *)base, scope, filter, attrs,
+					0, NULL, NULL, NULL,
+					LDAP_NO_LIMIT, response);
+}
+
+/**
+ * Hide the __func__ argument at call sites
+ */
+#define nsdb_search_nsdb_none_s(ld, base, scope, filter, response) \
+	__nsdb_search_nsdb_none_s(__func__, ld, base, scope, filter, response)
+
+/**
+ * Invoke ldap_search_ext_s(3), requesting no attributes, no filter
+ *
+ * @param func NUL-terminated C string containing name of calling function
+ * @param ld an initialized LDAP server descriptor
+ * @param base NUL-terminated C string containing search base
+ * @param response OUT: list of LDAP responses
+ * @return an LDAP result code
+ *
+ */
+static int
+__nsdb_search_nsdb_nofilter_s(const char *func, LDAP *ld, const char *base,
+		LDAPMessage **response)
+{
+	static char *attrs[] = { LDAP_NO_ATTRS, NULL };
+	char *uri;
+
+	if (ldap_get_option(ld, LDAP_OPT_URI, &uri) == LDAP_OPT_SUCCESS) {
+		xlog(D_CALL, "%s:\n  ldapsearch -H %s -b \"%s\" -s one",
+			func, uri, base);
+		ldap_memfree(uri);
+	} else {
+		xlog(D_CALL, "%s:\n  ldapsearch -b \"%s\" -s one",
+			func, base);
+	}
+
+	return ldap_search_ext_s(ld, (char *)base, LDAP_SCOPE_ONELEVEL, NULL,
+					attrs, 0, NULL, NULL, NULL,
+					LDAP_NO_LIMIT, response);
+}
+
+/**
+ * Hide the __func__ argument at call sites
+ */
+#define nsdb_search_nsdb_nofilter_s(ld, base, response) \
+	__nsdb_search_nsdb_nofilter_s(__func__, ld, base, response)
+
+/**
  * Construct the DN of an FSN entry
  *
  * @param nce NUL-terminated C string containing DN of NSDB container entry
@@ -187,7 +263,6 @@ static FedFsStatus
 nsdb_search_fsn_dn_s(LDAP *ld, const char *nce, const char *fsn_uuid,
 		char **dn, unsigned int *ldap_err)
 {
-	static char *attrs[] = { LDAP_NO_ATTRS, NULL };
 	LDAPMessage *response;
 	FedFsStatus retval;
 	char filter[128];
@@ -201,9 +276,8 @@ nsdb_search_fsn_dn_s(LDAP *ld, const char *nce, const char *fsn_uuid,
 		return FEDFS_ERR_INVAL;
 	}
 
-	rc = ldap_search_ext_s(ld, nce, LDAP_SCOPE_ONELEVEL,
-				filter, attrs, 0, NULL, NULL,
-				NULL, LDAP_NO_LIMIT, &response);
+	rc = nsdb_search_nsdb_none_s(ld, nce, LDAP_SCOPE_ONELEVEL,
+					filter, &response);
 	switch (rc) {
 	case LDAP_SUCCESS:
 		break;
@@ -310,7 +384,6 @@ nsdb_parse_delete_fsn_fsls_entry_s(LDAP *ld, LDAPMessage *entry,
 static FedFsStatus
 nsdb_delete_fsn_fsls_s(LDAP *ld, const char *dn, unsigned int *ldap_err)
 {
-	static char *attrs[] = { LDAP_NO_ATTRS, NULL };
 	LDAPMessage *message, *response;
 	FedFsStatus retval;
 	int entries, rc;
@@ -318,8 +391,7 @@ nsdb_delete_fsn_fsls_s(LDAP *ld, const char *dn, unsigned int *ldap_err)
 	xlog(D_CALL, "%s: searching for children of %s", __func__, dn);
 
 again:
-	rc = ldap_search_ext_s(ld, dn, LDAP_SCOPE_ONELEVEL, NULL, attrs, 0,
-				NULL, NULL, NULL, LDAP_NO_LIMIT, &response);
+	rc = nsdb_search_nsdb_nofilter_s(ld, dn, &response);
 	switch (rc) {
 	case LDAP_SUCCESS:
 	case LDAP_SIZELIMIT_EXCEEDED:
@@ -773,7 +845,6 @@ static FedFsStatus
 nsdb_search_fsl_dn_s(LDAP *ld, const char *nce, const char *fsl_uuid,
 		char **dn, unsigned int *ldap_err)
 {
-	static char *attrs[] = { LDAP_NO_ATTRS, NULL };
 	LDAPMessage *response;
 	FedFsStatus retval;
 	char filter[128];
@@ -787,9 +858,8 @@ nsdb_search_fsl_dn_s(LDAP *ld, const char *nce, const char *fsl_uuid,
 		return FEDFS_ERR_INVAL;
 	}
 
-	rc = ldap_search_ext_s(ld, nce, LDAP_SCOPE_SUBTREE,
-				filter, attrs, 0, NULL, NULL,
-				NULL, LDAP_NO_LIMIT, &response);
+	rc = nsdb_search_nsdb_none_s(ld, nce, LDAP_SCOPE_SUBTREE,
+					filter, &response);
 	switch (rc) {
 	case LDAP_SUCCESS:
 		break;
@@ -1275,7 +1345,6 @@ out:
 static FedFsStatus
 nsdb_delete_nsdb_fsns_s(LDAP *ld, const char *nce, unsigned int *ldap_err)
 {
-	static char *attrs[] = { LDAP_NO_ATTRS, NULL };
 	LDAPMessage *message, *response;
 	FedFsStatus retval;
 	int entries, rc;
@@ -1283,8 +1352,7 @@ nsdb_delete_nsdb_fsns_s(LDAP *ld, const char *nce, unsigned int *ldap_err)
 	xlog(D_CALL, "%s: searching for children of %s", __func__, nce);
 
 again:
-	rc = ldap_search_ext_s(ld, nce, LDAP_SCOPE_ONELEVEL, NULL, attrs, 0,
-				NULL, NULL, NULL, LDAP_NO_LIMIT, &response);
+	rc = nsdb_search_nsdb_nofilter_s(ld, nce, &response);
 	switch (rc) {
 	case LDAP_SUCCESS:
 	case LDAP_SIZELIMIT_EXCEEDED:
diff --git a/src/libnsdb/fileserver.c b/src/libnsdb/fileserver.c
index a047aba..28107c7 100644
--- a/src/libnsdb/fileserver.c
+++ b/src/libnsdb/fileserver.c
@@ -44,9 +44,88 @@
 #include "xlog.h"
 
 /**
- * Default 5 second time out for LDAP requests
+ * Invoke ldap_search_ext_s(3), requesting all attributes
+ *
+ * @param func NUL-terminated C string containing name of calling function
+ * @param ld an initialized LDAP server descriptor
+ * @param base NUL-terminated C string containing search base
+ * @param scope LDAP scope
+ * @param filter NUL-terminated C string containing search filter
+ * @param response OUT: list of LDAP responses
+ * @return an LDAP result code
+ *
+ * A fast timeout is used to prevent hanging the caller.
+ */
+static int
+__nsdb_search_nsdb_all_s(const char *func, LDAP *ld, const char *base,
+		int scope, char *filter, LDAPMessage **response)
+{
+	static char *attrs[] = { LDAP_ALL_USER_ATTRIBUTES, NULL };
+	static struct timeval timeout = { 5, 0 };
+	char *uri;
+
+	if (ldap_get_option(ld, LDAP_OPT_URI, &uri) == LDAP_OPT_SUCCESS) {
+		xlog(D_CALL, "%s:\n  ldapsearch -H %s -b \"%s\" -s %s  '%s' *",
+			func, uri, base, nsdb_printable_scope(scope), filter);
+		ldap_memfree(uri);
+	} else {
+		xlog(D_CALL, "%s:\n  ldapsearch -b \"%s\" -s %s '%s' *",
+			func, base, nsdb_printable_scope(scope), filter);
+	}
+
+	return ldap_search_ext_s(ld, (char *)base, LDAP_SCOPE_SUBTREE, filter,
+					attrs, 0, NULL, NULL, &timeout,
+					LDAP_NO_LIMIT, response);
+}
+
+/**
+ * Hide the __func__ argument at call sites
+ */
+#define nsdb_search_nsdb_all_s(ld, base, scope, filter, response) \
+	__nsdb_search_nsdb_all_s(__func__, ld, base, scope, filter, response)
+
+/**
+ * Invoke ldap_search_ext_s(3), requesting a specific attribute
+ *
+ * @param func NUL-terminated C string containing name of calling function
+ * @param ld an initialized LDAP server descriptor
+ * @param base NUL-terminated C string containing search base
+ * @param filter NUL-terminated C string containing search filter
+ * @param attr NUL-terminated C string containing attribute name
+ * @param response OUT: list of LDAP responses
+ * @return an LDAP result code
+ *
+ * A fast timeout is used to prevent hanging the caller.
  */
-static struct timeval nsdb_ldap_timeout = { 5, 0 };
+static int
+__nsdb_search_nsdb_attr_s(const char *func, LDAP *ld, const char *base,
+		char *filter, char *attr, LDAPMessage **response)
+{
+	static struct timeval timeout = { 5, 0 };
+	char *uri, *attrs[2];
+
+	attrs[0] = attr;
+	attrs[1] = NULL;
+
+	if (ldap_get_option(ld, LDAP_OPT_URI, &uri) == LDAP_OPT_SUCCESS) {
+		xlog(D_CALL, "%s:\n  ldapsearch -H %s -b \"%s\" -s base '%s' %s",
+			func, uri, filter, attr);
+		ldap_memfree(uri);
+	} else {
+		xlog(D_CALL, "%s:\n  ldapsearch -b \"%s\" -s base '%s' %s",
+			func, filter, attr);
+	}
+
+	return ldap_search_ext_s(ld, (char *)base, LDAP_SCOPE_BASE, filter,
+					attrs, 0, NULL, NULL, &timeout,
+					LDAP_NO_LIMIT, response);
+}
+
+/**
+ * Hide the __func__ argument at call sites
+ */
+#define nsdb_search_nsdb_attr_s(ld, base, filter, attr, response) \
+	__nsdb_search_nsdb_attr_s(__func__, ld, base, filter, attr, response)
 
 /**
  * Free a single struct fedfs_fsn
@@ -297,9 +376,9 @@ nsdb_get_ncedn_s(nsdb_t host, const char *naming_context, char **dn,
 		unsigned int *ldap_err)
 {
 	LDAPMessage *response, *message;
-	char *attrs[2], *tmp = NULL;
 	LDAP *ld = host->fn_ldap;
 	FedFsStatus retval;
+	char *tmp = NULL;
 	int rc;
 
 	if (host->fn_ldap == NULL) {
@@ -312,12 +391,8 @@ nsdb_get_ncedn_s(nsdb_t host, const char *naming_context, char **dn,
 		return FEDFS_ERR_INVAL;
 	}
 
-	attrs[0] = "fedfsNceDN";
-	attrs[1] = NULL;
-	rc = ldap_search_ext_s(ld, naming_context, LDAP_SCOPE_BASE,
-				"(objectClass=*)", attrs, 0, NULL,
-				NULL, &nsdb_ldap_timeout,
-				LDAP_NO_LIMIT, &response);
+	rc = nsdb_search_nsdb_attr_s(ld, naming_context, "(objectClass=*)",
+						"fedfsNceDN", &response);
 	switch (rc) {
 	case LDAP_SUCCESS:
 		break;
@@ -492,8 +567,8 @@ nsdb_get_naming_contexts_s(nsdb_t host, char ***contexts,
 {
 	LDAPMessage *response, *message;
 	LDAP *ld = host->fn_ldap;
-	char *attrs[2], **tmp;
 	FedFsStatus retval;
+	char **tmp;
 	int rc;
 
 	if (host->fn_ldap == NULL) {
@@ -506,12 +581,8 @@ nsdb_get_naming_contexts_s(nsdb_t host, char ***contexts,
 		return FEDFS_ERR_INVAL;
 	}
 
-	attrs[0] = "namingContexts";
-	attrs[1] = NULL;
-	rc = ldap_search_ext_s(ld, "", LDAP_SCOPE_BASE,
-				"(objectClass=*)", attrs, 0, NULL,
-				NULL, &nsdb_ldap_timeout,
-				LDAP_NO_LIMIT, &response);
+	rc = nsdb_search_nsdb_attr_s(ld, LDAP_ROOT_DSE, "(objectClass=*)",
+					"namingContexts", &response);
 	switch (rc) {
 	case LDAP_SUCCESS:
 		break;
@@ -853,9 +924,8 @@ nsdb_resolve_fsn_find_entry_s(LDAP *ld, const char *nce, const char *fsn_uuid,
 		return FEDFS_ERR_INVAL;
 	}
 
-	rc = ldap_search_ext_s(ld, nce, LDAP_SCOPE_SUBTREE,
-				filter, NULL, 0, NULL, NULL,
-				NULL, LDAP_NO_LIMIT, &response);
+	rc = nsdb_search_nsdb_all_s(ld, nce, LDAP_SCOPE_SUBTREE,
+						filter, &response);
 	switch (rc) {
 	case LDAP_SUCCESS:
 		break;
@@ -1168,9 +1238,8 @@ nsdb_get_fsn_find_entry_s(LDAP *ld, const char *nce, const char *fsn_uuid,
 		return FEDFS_ERR_INVAL;
 	}
 
-	rc = ldap_search_ext_s(ld, nce, LDAP_SCOPE_ONE,
-				filter, NULL, 0, NULL, NULL,
-				NULL, LDAP_NO_LIMIT, &response);
+	rc = nsdb_search_nsdb_all_s(ld, nce, LDAP_SCOPE_ONE,
+						filter, &response);
 	switch (rc) {
 	case LDAP_SUCCESS:
 		break;
@@ -1420,9 +1489,8 @@ nsdb_list_find_entries_s(LDAP *ld, const char *nce, char ***fsns,
 	char **tmp;
 	int rc;
 
-	rc = ldap_search_ext_s(ld, nce, LDAP_SCOPE_SUBTREE,
-				"(objectClass=fedfsFsn)", NULL, 0, NULL,
-				NULL, NULL, LDAP_NO_LIMIT, &response);
+	rc = nsdb_search_nsdb_all_s(ld, nce, LDAP_SCOPE_ONE,
+					"(objectClass=fedfsFsn)", &response);
 	switch (rc) {
 	case LDAP_SUCCESS:
 		break;
@@ -1560,8 +1628,8 @@ nsdb_list_s(nsdb_t host, const char *nce, char ***fsns, unsigned int *ldap_err)
 
 	for (j = 0; nce_list[j] != NULL; j++) {
 		retval = nsdb_list_find_entries_s(host->fn_ldap,
-						nce_list[j],
-						fsns, ldap_err);
+							nce_list[j],
+							fsns, ldap_err);
 		if (retval == FEDFS_OK)
 			break;
 	}
diff --git a/src/libnsdb/ldap.c b/src/libnsdb/ldap.c
index 404f6d1..f2a47c4 100644
--- a/src/libnsdb/ldap.c
+++ b/src/libnsdb/ldap.c
@@ -44,6 +44,28 @@
 #include "xlog.h"
 
 /**
+ * Map scope to a printable string
+ *
+ * @param scope LDAP scope
+ * @return static NUL-terminated C string containing scope name
+ */
+const char *
+nsdb_printable_scope(int scope)
+{
+	switch (scope) {
+	case LDAP_SCOPE_BASE:
+		return "base";
+	case LDAP_SCOPE_ONE:
+		return "one";
+	case LDAP_SCOPE_SUB:
+		return "sub";
+	case LDAP_SCOPE_CHILDREN:
+		return "children";
+	}
+	return "default";
+}
+
+/**
  * Read a password from stdin, disabling character echo
  *
  * @return a NUL-terminated C string containing the typed-in password.  Caller must free the string with free(3)
diff --git a/src/libnsdb/nsdb-internal.h b/src/libnsdb/nsdb-internal.h
index 7defe6d..09c3d03 100644
--- a/src/libnsdb/nsdb-internal.h
+++ b/src/libnsdb/nsdb-internal.h
@@ -51,6 +51,8 @@ struct fedfs_nsdb {
  ** Private LDAP-related APIs (ldap.c)
  **/
 
+const char *	 nsdb_printable_scope(int scope);
+
 void		 nsdb_init_add_attribute(LDAPMod *mod,
 				const char *attribute, char **bv,
 				const char *value);
