diff options
author | Andrew Tridgell <tridge@samba.org> | 2004-12-12 11:30:30 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:07:21 -0500 |
commit | fe01af9fb278a320820b41b7970a1f04b3b696a5 (patch) | |
tree | 1b1416a46983ee4881a0e76d817c3c604785bc21 | |
parent | e60bf04d4f03bf255cd5bb1b761c98fc7779408e (diff) | |
download | samba-fe01af9fb278a320820b41b7970a1f04b3b696a5.tar.gz samba-fe01af9fb278a320820b41b7970a1f04b3b696a5.tar.bz2 samba-fe01af9fb278a320820b41b7970a1f04b3b696a5.zip |
r4165: added a 100 element name cache to cope with some amount of seeking
back to filenames that have been deleted. This fixes the new os/2
delete test.
(This used to be commit 6d471db13ab132655a07e11533a559446e56fc00)
-rw-r--r-- | source4/ntvfs/posix/pvfs_dirlist.c | 63 | ||||
-rw-r--r-- | source4/ntvfs/posix/pvfs_search.c | 10 |
2 files changed, 50 insertions, 23 deletions
diff --git a/source4/ntvfs/posix/pvfs_dirlist.c b/source4/ntvfs/posix/pvfs_dirlist.c index 1ef6e408c3..5c67b2d189 100644 --- a/source4/ntvfs/posix/pvfs_dirlist.c +++ b/source4/ntvfs/posix/pvfs_dirlist.c @@ -25,15 +25,24 @@ #include "vfs_posix.h" #include "system/dir.h" +#define NAME_CACHE_SIZE 100 + +struct name_cache_entry { + char *name; + off_t offset; +}; + struct pvfs_dir { struct pvfs_state *pvfs; BOOL no_wildcard; - char *last_name; + char *single_name; const char *pattern; off_t offset; DIR *dir; const char *unix_path; BOOL end_of_search; + struct name_cache_entry *name_cache; + uint32_t name_cache_index; }; /* @@ -55,8 +64,8 @@ static NTSTATUS pvfs_list_no_wildcard(struct pvfs_state *pvfs, struct pvfs_filen return NT_STATUS_NO_MEMORY; } - dir->last_name = talloc_strdup(dir, pattern); - if (!dir->last_name) { + dir->single_name = talloc_strdup(dir, pattern); + if (!dir->single_name) { return NT_STATUS_NO_MEMORY; } @@ -88,7 +97,7 @@ NTSTATUS pvfs_list_start(struct pvfs_state *pvfs, struct pvfs_filename *name, char *pattern; struct pvfs_dir *dir; - (*dirp) = talloc_p(mem_ctx, struct pvfs_dir); + (*dirp) = talloc_zero_p(mem_ctx, struct pvfs_dir); if (*dirp == NULL) { return NT_STATUS_NO_MEMORY; } @@ -126,9 +135,15 @@ NTSTATUS pvfs_list_start(struct pvfs_state *pvfs, struct pvfs_filename *name, dir->pvfs = pvfs; dir->no_wildcard = False; - dir->last_name = NULL; dir->end_of_search = False; dir->offset = 0; + dir->name_cache = talloc_zero_array_p(dir, + struct name_cache_entry, + NAME_CACHE_SIZE); + if (dir->name_cache == NULL) { + talloc_free(dir); + return NT_STATUS_NO_MEMORY; + } talloc_set_destructor(dir, pvfs_dirlist_destructor); @@ -147,7 +162,7 @@ const char *pvfs_list_next(struct pvfs_dir *dir, uint_t *ofs) dir->end_of_search = True; if (*ofs != 0) return NULL; (*ofs)++; - return dir->last_name; + return dir->single_name; } if (*ofs != dir->offset) { @@ -157,6 +172,7 @@ const char *pvfs_list_next(struct pvfs_dir *dir, uint_t *ofs) while ((de = readdir(dir->dir))) { const char *dname = de->d_name; + struct name_cache_entry *e; if (ms_fnmatch(dir->pattern, dname, dir->pvfs->tcon->smb_conn->negotiate.protocol) != 0) { @@ -173,10 +189,15 @@ const char *pvfs_list_next(struct pvfs_dir *dir, uint_t *ofs) dir->offset = telldir(dir->dir); (*ofs) = dir->offset; - if (dir->last_name) talloc_free(dir->last_name); - dir->last_name = talloc_strdup(dir, de->d_name); + dir->name_cache_index = (dir->name_cache_index+1) % NAME_CACHE_SIZE; + e = &dir->name_cache[dir->name_cache_index]; + + if (e->name) talloc_free(e->name); + + e->name = talloc_strdup(dir, de->d_name); + e->offset = dir->offset; - return dir->last_name; + return e->name; } dir->end_of_search = True; @@ -248,16 +269,26 @@ NTSTATUS pvfs_list_seek(struct pvfs_dir *dir, const char *name, uint_t *ofs) { struct dirent *de; NTSTATUS status; + int i; status = pvfs_list_wakeup(dir, ofs); if (!NT_STATUS_IS_OK(status)) { return status; } - if (dir->last_name && - StrCaseCmp(name, dir->last_name) == 0) { - *ofs = dir->offset; - return NT_STATUS_OK; + for (i=dir->name_cache_index;i>=0;i--) { + struct name_cache_entry *e = &dir->name_cache[i]; + if (e->name && StrCaseCmp(name, e->name) == 0) { + *ofs = e->offset; + return NT_STATUS_OK; + } + } + for (i=NAME_CACHE_SIZE-1;i>dir->name_cache_index;i--) { + struct name_cache_entry *e = &dir->name_cache[i]; + if (e->name && StrCaseCmp(name, e->name) == 0) { + *ofs = e->offset; + return NT_STATUS_OK; + } } rewinddir(dir->dir); @@ -266,8 +297,6 @@ NTSTATUS pvfs_list_seek(struct pvfs_dir *dir, const char *name, uint_t *ofs) if (StrCaseCmp(name, de->d_name) == 0) { dir->offset = telldir(dir->dir); *ofs = dir->offset; - if (dir->last_name) talloc_free(dir->last_name); - dir->last_name = talloc_strdup(dir, de->d_name); return NT_STATUS_OK; } } @@ -276,7 +305,5 @@ NTSTATUS pvfs_list_seek(struct pvfs_dir *dir, const char *name, uint_t *ofs) pvfs_list_hibernate(dir); - /* it is not an error to give a bad name (it may have been deleted). Instead - just continue from end of directory */ - return NT_STATUS_OK; + return NT_STATUS_OBJECT_NAME_NOT_FOUND; } diff --git a/source4/ntvfs/posix/pvfs_search.c b/source4/ntvfs/posix/pvfs_search.c index 1c49701f04..c336035218 100644 --- a/source4/ntvfs/posix/pvfs_search.c +++ b/source4/ntvfs/posix/pvfs_search.c @@ -533,7 +533,11 @@ NTSTATUS pvfs_search_next(struct ntvfs_module_context *ntvfs, if (io->t2fnext.in.last_name && *io->t2fnext.in.last_name) { status = pvfs_list_seek(dir, io->t2fnext.in.last_name, &search->current_index); if (!NT_STATUS_IS_OK(status)) { - return status; + if (io->t2fnext.in.resume_key) { + search->current_index = io->t2fnext.in.resume_key; + } else { + return status; + } } } else if (io->t2fnext.in.flags & FLAG_TRANS2_FIND_CONTINUE) { /* plain continue - nothing to do */ @@ -562,10 +566,6 @@ NTSTATUS pvfs_search_next(struct ntvfs_module_context *ntvfs, talloc_free(search); } - if (reply_count == 0) { - return NT_STATUS_NO_SUCH_FILE; - } - return NT_STATUS_OK; } |