diff options
author | Andrew Tridgell <tridge@samba.org> | 2004-10-27 01:11:44 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:04:48 -0500 |
commit | b9ddb09f03332a9c4442e61bb5c73f7bde04d1d6 (patch) | |
tree | b5d0875e981f6dec57cc06ce98ce3a1428817e86 | |
parent | 05ad898f68a2df1b102af95fdba0704479bde073 (diff) | |
download | samba-b9ddb09f03332a9c4442e61bb5c73f7bde04d1d6.tar.gz samba-b9ddb09f03332a9c4442e61bb5c73f7bde04d1d6.tar.bz2 samba-b9ddb09f03332a9c4442e61bb5c73f7bde04d1d6.zip |
r3276: - allow for more than 256 open old style searches (limit currently set at an arbitrary 5000)
- auto-cleanup old searches that the client forgot to close (common with old searches)
- expanded the RAW-SEARCH test to test more than 256 old searches, and
old search rewind (w2k3 fails this - it appears to not support rewind
on old style searches)
(This used to be commit bc83d823b2140a10007490bf0101843a886f99a6)
-rw-r--r-- | source4/ntvfs/posix/pvfs_search.c | 54 | ||||
-rw-r--r-- | source4/ntvfs/posix/vfs_posix.h | 13 | ||||
-rw-r--r-- | source4/torture/raw/search.c | 180 |
3 files changed, 219 insertions, 28 deletions
diff --git a/source4/ntvfs/posix/pvfs_search.c b/source4/ntvfs/posix/pvfs_search.c index 0df3ebee0f..43d0f946b7 100644 --- a/source4/ntvfs/posix/pvfs_search.c +++ b/source4/ntvfs/posix/pvfs_search.c @@ -24,6 +24,22 @@ #include "vfs_posix.h" +/* the state of a search started with pvfs_search_first() */ +struct pvfs_search_state { + struct pvfs_state *pvfs; + uint16_t handle; + uint_t current_index; + uint16_t search_attrib; + uint16_t must_attrib; + struct pvfs_dir *dir; + time_t last_used; +}; + + +/* place a reasonable limit on old-style searches as clients tend to + not send search close requests */ +#define MAX_OLD_SEARCHES 2000 + /* destroy an open search */ @@ -68,11 +84,11 @@ static NTSTATUS fill_search_info(struct pvfs_state *pvfs, file->search.write_time = nt_time_to_unix(name->dos.write_time); file->search.size = name->st.st_size; file->search.name = shortname; - file->search.id.reserved = 8; + file->search.id.reserved = search->handle >> 8; memset(file->search.id.name, ' ', sizeof(file->search.id.name)); memcpy(file->search.id.name, shortname, MIN(strlen(shortname)+1, sizeof(file->search.id.name))); - file->search.id.handle = search->handle; + file->search.id.handle = search->handle & 0xFF; file->search.id.server_cookie = dir_index; file->search.id.client_cookie = 0; return NT_STATUS_OK; @@ -237,6 +253,29 @@ static NTSTATUS pvfs_search_fill(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } +/* + we've run out of search handles - cleanup those that the client forgot + to close +*/ +static void pvfs_search_cleanup(struct pvfs_state *pvfs) +{ + int i; + time_t t = time(NULL); + + for (i=0;i<MAX_OLD_SEARCHES;i++) { + struct pvfs_search_state *search = idr_find(pvfs->idtree_search, i); + if (search == NULL) return; + if (pvfs_list_eos(search->dir, search->current_index) && + search->last_used != 0 && + t > search->last_used + 30) { + /* its almost certainly been forgotten + about */ + talloc_free(search); + } + } +} + + /* list files in a directory matching a wildcard pattern - old SMBsearch interface */ @@ -284,7 +323,11 @@ 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 */ - id = idr_get_new(pvfs->idtree_search, search, UINT8_MAX); + id = idr_get_new(pvfs->idtree_search, search, MAX_OLD_SEARCHES); + if (id == -1) { + pvfs_search_cleanup(pvfs); + id = idr_get_new(pvfs->idtree_search, search, MAX_OLD_SEARCHES); + } if (id == -1) { return NT_STATUS_INSUFFICIENT_RESOURCES; } @@ -295,6 +338,7 @@ static NTSTATUS pvfs_search_first_old(struct ntvfs_module_context *ntvfs, search->current_index = 0; search->search_attrib = search_attrib & 0xFF; search->must_attrib = (search_attrib>>8) & 0xFF; + search->last_used = time(NULL); talloc_set_destructor(search, pvfs_search_destructor); @@ -329,7 +373,7 @@ static NTSTATUS pvfs_search_next_old(struct ntvfs_module_context *ntvfs, uint16_t handle; NTSTATUS status; - handle = io->search_next.in.id.handle; + handle = io->search_next.in.id.handle | (io->search_next.in.id.reserved<<8); max_count = io->search_next.in.max_count; search = idr_find(pvfs->idtree_search, handle); @@ -339,6 +383,7 @@ static NTSTATUS pvfs_search_next_old(struct ntvfs_module_context *ntvfs, } search->current_index = io->search_next.in.id.server_cookie; + search->last_used = time(NULL); dir = search->dir; status = pvfs_list_wakeup(dir, &search->current_index); @@ -423,6 +468,7 @@ NTSTATUS pvfs_search_first(struct ntvfs_module_context *ntvfs, search->current_index = 0; search->search_attrib = search_attrib; search->must_attrib = 0; + search->last_used = 0; talloc_set_destructor(search, pvfs_search_destructor); diff --git a/source4/ntvfs/posix/vfs_posix.h b/source4/ntvfs/posix/vfs_posix.h index 19408848fd..231d9a2d08 100644 --- a/source4/ntvfs/posix/vfs_posix.h +++ b/source4/ntvfs/posix/vfs_posix.h @@ -75,16 +75,6 @@ struct pvfs_filename { }; -/* the state of a search started with pvfs_search_first() */ -struct pvfs_search_state { - struct pvfs_state *pvfs; - uint16_t handle; - uint_t current_index; - uint16_t search_attrib; - uint16_t must_attrib; - struct pvfs_dir *dir; -}; - /* open file state */ struct pvfs_file { struct pvfs_file *next, *prev; @@ -161,4 +151,7 @@ struct pvfs_mangle_context { #define PVFS_FLAG_STRICT_SYNC (1<<5) #define PVFS_FLAG_STRICT_LOCKING (1<<6) +/* forward declare some anonymous structures */ +struct pvfs_dir; + #endif /* _VFS_POSIX_H_ */ diff --git a/source4/torture/raw/search.c b/source4/torture/raw/search.c index c8f21de8d8..04c1f8db57 100644 --- a/source4/torture/raw/search.c +++ b/source4/torture/raw/search.c @@ -913,37 +913,189 @@ done: } + /* - basic testing of all RAW_SEARCH_* calls using a single file + basic testing of many old style search calls using separate dirs */ -BOOL torture_raw_search(int dummy) +static BOOL test_many_dirs(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) { - struct smbcli_state *cli; + const int num_dirs = 300; + int i, fnum, n; + char *fname, *dname; BOOL ret = True; - TALLOC_CTX *mem_ctx; + NTSTATUS status; + union smb_search_data *file, *file2, *file3; - if (!torture_open_connection(&cli)) { + if (smbcli_deltree(cli->tree, BASEDIR) == -1 || + NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, BASEDIR))) { + printf("Failed to create " BASEDIR " - %s\n", smbcli_errstr(cli->tree)); return False; } - mem_ctx = talloc_init("torture_search"); + printf("Creating %d dirs\n", num_dirs); - if (!test_one_file(cli, mem_ctx)) { - ret = False; + for (i=0;i<num_dirs;i++) { + asprintf(&dname, BASEDIR "\\d%d", i); + status = smbcli_mkdir(cli->tree, dname); + if (!NT_STATUS_IS_OK(status)) { + printf("(%s) Failed to create %s - %s\n", + __location__, dname, nt_errstr(status)); + ret = False; + goto done; + } + + for (n=0;n<3;n++) { + asprintf(&fname, BASEDIR "\\d%d\\f%d-%d.txt", i, i, n); + fnum = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR, DENY_NONE); + if (fnum == -1) { + printf("(%s) Failed to create %s - %s\n", + __location__, fname, smbcli_errstr(cli->tree)); + ret = False; + goto done; + } + free(fname); + } + + free(dname); + smbcli_close(cli->tree, fnum); } - if (!test_many_files(cli, mem_ctx)) { - ret = False; + file = talloc_zero_array_p(mem_ctx, union smb_search_data, num_dirs); + file2 = talloc_zero_array_p(mem_ctx, union smb_search_data, num_dirs); + file3 = talloc_zero_array_p(mem_ctx, union smb_search_data, num_dirs); + + printf("Search first on %d dirs\n", num_dirs); + + for (i=0;i<num_dirs;i++) { + union smb_search_first io; + io.generic.level = RAW_SEARCH_SEARCH; + io.search_first.in.max_count = 1; + io.search_first.in.search_attrib = 0; + io.search_first.in.pattern = talloc_asprintf(mem_ctx, BASEDIR "\\d%d\\*.txt", i); + fname = talloc_asprintf(mem_ctx, "f%d-", i); + + io.search_first.out.count = 0; + + status = smb_raw_search_first(cli->tree, mem_ctx, + &io, (void *)&file[i], single_search_callback); + if (io.search_first.out.count != 1) { + printf("(%s) search first gave %d entries for dir %d - %s\n", + __location__, io.search_first.out.count, i, nt_errstr(status)); + ret = False; + goto done; + } + CHECK_STATUS(status, NT_STATUS_OK); + if (strncasecmp(file[i].search.name, fname, strlen(fname)) != 0) { + printf("(%s) incorrect name '%s' expected '%s'[12].txt\n", + __location__, file[i].search.name, fname); + ret = False; + goto done; + } + + talloc_free(fname); } - if (!test_sorted(cli, mem_ctx)) { - ret = False; + printf("Search next on %d dirs\n", num_dirs); + + for (i=0;i<num_dirs;i++) { + union smb_search_next io2; + + io2.generic.level = RAW_SEARCH_SEARCH; + io2.search_next.in.max_count = 1; + io2.search_next.in.search_attrib = 0; + io2.search_next.in.id = file[i].search.id; + fname = talloc_asprintf(mem_ctx, "f%d-", i); + + io2.search_next.out.count = 0; + + status = smb_raw_search_next(cli->tree, mem_ctx, + &io2, (void *)&file2[i], single_search_callback); + if (io2.search_next.out.count != 1) { + printf("(%s) search next gave %d entries for dir %d - %s\n", + __location__, io2.search_next.out.count, i, nt_errstr(status)); + ret = False; + goto done; + } + CHECK_STATUS(status, NT_STATUS_OK); + if (strncasecmp(file2[i].search.name, fname, strlen(fname)) != 0) { + printf("(%s) incorrect name '%s' expected '%s'[12].txt\n", + __location__, file2[i].search.name, fname); + ret = False; + goto done; + } + + talloc_free(fname); } - if (!test_modify_search(cli, mem_ctx)) { - ret = False; + + printf("Search next (rewind) on %d dirs\n", num_dirs); + + for (i=0;i<num_dirs;i++) { + union smb_search_next io2; + + io2.generic.level = RAW_SEARCH_SEARCH; + io2.search_next.in.max_count = 1; + io2.search_next.in.search_attrib = 0; + io2.search_next.in.id = file[i].search.id; + fname = talloc_asprintf(mem_ctx, "f%d-", i); + io2.search_next.out.count = 0; + + status = smb_raw_search_next(cli->tree, mem_ctx, + &io2, (void *)&file3[i], single_search_callback); + if (io2.search_next.out.count != 1) { + printf("(%s) search next gave %d entries for dir %d - %s\n", + __location__, io2.search_next.out.count, i, nt_errstr(status)); + ret = False; + goto done; + } + CHECK_STATUS(status, NT_STATUS_OK); + + if (strncasecmp(file3[i].search.name, file2[i].search.name, 3) != 0) { + printf("(%s) incorrect name '%s' on rewind at dir %d\n", + __location__, file2[i].search.name, i); + ret = False; + goto done; + } + + if (strcmp(file3[i].search.name, file2[i].search.name) != 0) { + printf("(%s) server did not rewind - got '%s' expected '%s'\n", + __location__, file3[i].search.name, file2[i].search.name); + ret = False; + goto done; + } + + talloc_free(fname); + } + + +done: + smb_raw_exit(cli->session); + smbcli_deltree(cli->tree, BASEDIR); + + return ret; +} + +/* + basic testing of all RAW_SEARCH_* calls using a single file +*/ +BOOL torture_raw_search(int dummy) +{ + struct smbcli_state *cli; + BOOL ret = True; + TALLOC_CTX *mem_ctx; + + if (!torture_open_connection(&cli)) { + return False; } + mem_ctx = talloc_init("torture_search"); + + ret &= test_one_file(cli, mem_ctx); + ret &= test_many_files(cli, mem_ctx); + ret &= test_sorted(cli, mem_ctx); + ret &= test_modify_search(cli, mem_ctx); + ret &= test_many_dirs(cli, mem_ctx); + torture_close_connection(cli); talloc_destroy(mem_ctx); |