summaryrefslogtreecommitdiffstats
path: root/source4/ntvfs/posix/pvfs_search.c
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2004-10-19 06:39:51 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:01:54 -0500
commitcf1b85348a0fc5bf4788291109c9dca9e95eb9c2 (patch)
tree4ddd852640cc81c255677a7a6057a6d84b692a45 /source4/ntvfs/posix/pvfs_search.c
parent2b8aa720f47804f783679388f40a9345eff897b9 (diff)
downloadsamba-cf1b85348a0fc5bf4788291109c9dca9e95eb9c2.tar.gz
samba-cf1b85348a0fc5bf4788291109c9dca9e95eb9c2.tar.xz
samba-cf1b85348a0fc5bf4788291109c9dca9e95eb9c2.zip
r3056: added a id -> pointer data structure (a type of radix tree). This is
an extremely efficient way of mapping from an integer handle (such as an open file handle) to a pointer (such as the structure containing the open file information). The code is taken from lib/idr.c in the 2.6 Linux kernel, and is very fast and space efficient. By using talloc it even has auto cleanup. This commit converts the handling of open file handles and open directory search handles to use the idtree routines. In combination with talloc destructors, this simplifies the structure handling in the pvfs backend a lot. For example, we no longer need to keep a linked list of open directory searches at all, and we no longer need to do linear scans of the list of open files on most operations. The end result is that the pvfs code is now extremely scalable. You can have 10s of thousands of open files and open searches and the code still runs very fast. I have also added a small optimisation into the file close path, to avoid looking in the byte range locking database if we know that there are no locks outstanding. (This used to be commit 16835a0ef91a16fa01145b773aad8d43da215dbf)
Diffstat (limited to 'source4/ntvfs/posix/pvfs_search.c')
-rw-r--r--source4/ntvfs/posix/pvfs_search.c93
1 files changed, 35 insertions, 58 deletions
diff --git a/source4/ntvfs/posix/pvfs_search.c b/source4/ntvfs/posix/pvfs_search.c
index 07f2a0f127..7b0da321d3 100644
--- a/source4/ntvfs/posix/pvfs_search.c
+++ b/source4/ntvfs/posix/pvfs_search.c
@@ -23,6 +23,17 @@
#include "include/includes.h"
#include "vfs_posix.h"
+
+/*
+ destroy an open search
+*/
+static int pvfs_search_destructor(void *ptr)
+{
+ struct pvfs_search_state *search = ptr;
+ idr_remove(search->pvfs->idtree_search, search->handle);
+ return 0;
+}
+
/*
fill in a single search result for a given info level
*/
@@ -224,32 +235,6 @@ static NTSTATUS pvfs_search_fill(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx,
return NT_STATUS_OK;
}
-/*
- return the next available search handle
-*/
-static NTSTATUS pvfs_next_search_handle(struct pvfs_state *pvfs, uint16_t *handle,
- uint_t max_handles)
-{
- struct pvfs_search_state *search;
-
- if (pvfs->search.num_active_searches >= max_handles) {
- return NT_STATUS_INSUFFICIENT_RESOURCES;
- }
-
- (*handle) = (pvfs->search.next_search_handle) & (max_handles-1);
-again:
- for (search=pvfs->search.open_searches;search;search=search->next) {
- if (*handle == search->handle) {
- *handle = ((*handle)+1) & (max_handles-1);
- goto again;
- }
- }
- pvfs->search.next_search_handle = ((*handle)+1) & (max_handles-1);
-
- return NT_STATUS_OK;
-}
-
-
/*
list files in a directory matching a wildcard pattern - old SMBsearch interface
*/
@@ -266,6 +251,7 @@ static NTSTATUS pvfs_search_first_old(struct ntvfs_module_context *ntvfs,
const char *pattern;
NTSTATUS status;
struct pvfs_filename *name;
+ int id;
search_attrib = io->search_first.in.search_attrib;
pattern = io->search_first.in.pattern;
@@ -301,15 +287,19 @@ static NTSTATUS pvfs_search_first_old(struct ntvfs_module_context *ntvfs,
/* we need to give a handle back to the client so it
can continue a search */
- status = pvfs_next_search_handle(pvfs, &search->handle, 0x100);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
+ id = idr_get_new(pvfs->idtree_search, search, 0x100);
+ if (id == -1) {
+ return NT_STATUS_INSUFFICIENT_RESOURCES;
}
-
+
+ search->pvfs = pvfs;
+ search->handle = id;
search->dir = dir;
search->current_index = 0;
search->search_attrib = search_attrib;
+ talloc_set_destructor(search, pvfs_search_destructor);
+
status = pvfs_search_fill(pvfs, req, io->search_first.in.max_count, search, io->generic.level,
&reply_count, search_private, callback);
if (!NT_STATUS_IS_OK(status)) {
@@ -323,9 +313,7 @@ static NTSTATUS pvfs_search_first_old(struct ntvfs_module_context *ntvfs,
return STATUS_NO_MORE_FILES;
}
- pvfs->search.num_active_searches++;
talloc_steal(pvfs, search);
- DLIST_ADD(pvfs->search.open_searches, search);
return NT_STATUS_OK;
}
@@ -346,11 +334,8 @@ static NTSTATUS pvfs_search_next_old(struct ntvfs_module_context *ntvfs,
handle = io->search_next.in.id.handle;
max_count = io->search_next.in.max_count;
- for (search=pvfs->search.open_searches; search; search = search->next) {
- if (search->handle == handle) break;
- }
-
- if (!search) {
+ search = idr_find(pvfs->idtree_search, handle);
+ if (search == NULL) {
/* we didn't find the search handle */
return NT_STATUS_INVALID_HANDLE;
}
@@ -369,7 +354,6 @@ static NTSTATUS pvfs_search_next_old(struct ntvfs_module_context *ntvfs,
/* not matching any entries means end of search */
if (reply_count == 0) {
- DLIST_REMOVE(pvfs->search.open_searches, search);
talloc_free(search);
}
@@ -392,6 +376,7 @@ NTSTATUS pvfs_search_first(struct ntvfs_module_context *ntvfs,
const char *pattern;
NTSTATUS status;
struct pvfs_filename *name;
+ int id;
if (io->generic.level >= RAW_SEARCH_SEARCH) {
return pvfs_search_first_old(ntvfs, req, io, search_private, callback);
@@ -430,17 +415,19 @@ NTSTATUS pvfs_search_first(struct ntvfs_module_context *ntvfs,
return status;
}
- /* we need to give a handle back to the client so it
- can continue a search */
- status = pvfs_next_search_handle(pvfs, &search->handle, 0x10000);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
+ id = idr_get_new(pvfs->idtree_search, search, 0x10000);
+ if (id == -1) {
+ return NT_STATUS_INSUFFICIENT_RESOURCES;
}
-
+
+ search->pvfs = pvfs;
+ search->handle = id;
search->dir = dir;
search->current_index = 0;
search->search_attrib = search_attrib;
+ talloc_set_destructor(search, pvfs_search_destructor);
+
status = pvfs_search_fill(pvfs, req, max_count, search, io->generic.level,
&reply_count, search_private, callback);
if (!NT_STATUS_IS_OK(status)) {
@@ -463,9 +450,7 @@ NTSTATUS pvfs_search_first(struct ntvfs_module_context *ntvfs,
io->t2ffirst.out.end_of_search)) {
talloc_free(search);
} else {
- pvfs->search.num_active_searches++;
talloc_steal(pvfs, search);
- DLIST_ADD(pvfs->search.open_searches, search);
}
return NT_STATUS_OK;
@@ -491,11 +476,8 @@ NTSTATUS pvfs_search_next(struct ntvfs_module_context *ntvfs,
handle = io->t2fnext.in.handle;
- for (search=pvfs->search.open_searches; search; search = search->next) {
- if (search->handle == handle) break;
- }
-
- if (!search) {
+ search = idr_find(pvfs->idtree_search, handle);
+ if (search == NULL) {
/* we didn't find the search handle */
return NT_STATUS_INVALID_HANDLE;
}
@@ -544,7 +526,6 @@ found:
if ((io->t2fnext.in.flags & FLAG_TRANS2_FIND_CLOSE) ||
((io->t2fnext.in.flags & FLAG_TRANS2_FIND_CLOSE_IF_END) &&
io->t2fnext.out.end_of_search)) {
- DLIST_REMOVE(pvfs->search.open_searches, search);
talloc_free(search);
}
@@ -565,16 +546,12 @@ NTSTATUS pvfs_search_close(struct ntvfs_module_context *ntvfs,
handle = io->findclose.in.handle;
}
- for (search=pvfs->search.open_searches; search; search = search->next) {
- if (search->handle == handle) break;
- }
-
- if (!search) {
+ search = idr_find(pvfs->idtree_search, handle);
+ if (search == NULL) {
/* we didn't find the search handle */
return NT_STATUS_INVALID_HANDLE;
}
- DLIST_REMOVE(pvfs->search.open_searches, search);
talloc_free(search);
return NT_STATUS_OK;