diff options
Diffstat (limited to 'source4/ntvfs/posix')
-rw-r--r-- | source4/ntvfs/posix/config.mk | 1 | ||||
-rw-r--r-- | source4/ntvfs/posix/pvfs_lock.c | 64 | ||||
-rw-r--r-- | source4/ntvfs/posix/pvfs_open.c | 63 | ||||
-rw-r--r-- | source4/ntvfs/posix/pvfs_search.c | 93 | ||||
-rw-r--r-- | source4/ntvfs/posix/vfs_posix.c | 15 | ||||
-rw-r--r-- | source4/ntvfs/posix/vfs_posix.h | 28 |
6 files changed, 134 insertions, 130 deletions
diff --git a/source4/ntvfs/posix/config.mk b/source4/ntvfs/posix/config.mk index b6ba073a99..732e896d2b 100644 --- a/source4/ntvfs/posix/config.mk +++ b/source4/ntvfs/posix/config.mk @@ -22,6 +22,7 @@ ADD_OBJ_FILES = \ ntvfs/posix/pvfs_shortname.o \ ntvfs/posix/pvfs_lock.o \ ntvfs/posix/pvfs_wait.o \ + ntvfs/common/idtree.o \ ntvfs/common/brlock.o # End MODULE ntvfs_posix ################################################ diff --git a/source4/ntvfs/posix/pvfs_lock.c b/source4/ntvfs/posix/pvfs_lock.c index e32fcb2e3a..f52e68eeb1 100644 --- a/source4/ntvfs/posix/pvfs_lock.c +++ b/source4/ntvfs/posix/pvfs_lock.c @@ -75,6 +75,7 @@ static void pvfs_lock_async_failed(struct pvfs_state *pvfs, f->fnum, locks[i].offset, locks[i].count); + f->lock_count--; } req->async.status = status; req->async.send_fn(req); @@ -117,6 +118,10 @@ static void pvfs_pending_lock_continue(void *private, BOOL timed_out) locks[pending->pending_lock].count, rw, NULL); + if (NT_STATUS_IS_OK(status)) { + f->lock_count++; + } + /* if we have failed and timed out, or succeeded, then we don't need the pending lock any more */ if (NT_STATUS_IS_OK(status) || timed_out) { @@ -182,6 +187,8 @@ static void pvfs_pending_lock_continue(void *private, BOOL timed_out) pvfs_lock_async_failed(pvfs, req, f, locks, i, status); return; } + + f->lock_count++; } /* we've managed to get all the locks. Tell the client */ @@ -191,26 +198,28 @@ static void pvfs_pending_lock_continue(void *private, BOOL timed_out) /* - called when we close a file that might have pending locks + called when we close a file that might have locks */ -void pvfs_lock_close_pending(struct pvfs_state *pvfs, struct pvfs_file *f) +void pvfs_lock_close(struct pvfs_state *pvfs, struct pvfs_file *f) { struct pvfs_pending_lock *p, *next; - NTSTATUS status; + if (f->lock_count || f->pending_list) { + DEBUG(5,("pvfs_lock: removing %.0f locks on close\n", + (double)f->lock_count)); + brl_close(f->pvfs->brl_context, &f->locking_key, f->fnum); + f->lock_count = 0; + } + + /* reply to all the pending lock requests, telling them the + lock failed */ for (p=f->pending_list;p;p=next) { next = p->next; DLIST_REMOVE(f->pending_list, p); - status = brl_remove_pending(pvfs->brl_context, &f->locking_key, p); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("pvfs_lock_close_pending: failed to remove pending lock - %s\n", - nt_errstr(status))); - } talloc_free(p->wait_handle); p->req->async.status = NT_STATUS_RANGE_NOT_LOCKED; p->req->async.send_fn(p->req); } - } @@ -262,6 +271,7 @@ NTSTATUS pvfs_lock(struct ntvfs_module_context *ntvfs, int i; enum brl_type rw; struct pvfs_pending_lock *pending = NULL; + NTSTATUS status; f = pvfs_find_fd(pvfs, req, lck->generic.in.fnum); if (!f) { @@ -270,21 +280,29 @@ NTSTATUS pvfs_lock(struct ntvfs_module_context *ntvfs, switch (lck->generic.level) { case RAW_LOCK_LOCK: - return brl_lock(pvfs->brl_context, - &f->locking_key, - req->smbpid, - f->fnum, - lck->lock.in.offset, - lck->lock.in.count, - WRITE_LOCK, NULL); - - case RAW_LOCK_UNLOCK: - return brl_unlock(pvfs->brl_context, + status = brl_lock(pvfs->brl_context, &f->locking_key, req->smbpid, f->fnum, lck->lock.in.offset, - lck->lock.in.count); + lck->lock.in.count, + WRITE_LOCK, NULL); + if (NT_STATUS_IS_OK(status)) { + f->lock_count++; + } + return status; + + case RAW_LOCK_UNLOCK: + status = brl_unlock(pvfs->brl_context, + &f->locking_key, + req->smbpid, + f->fnum, + lck->lock.in.offset, + lck->lock.in.count); + if (NT_STATUS_IS_OK(status)) { + f->lock_count--; + } + return status; case RAW_LOCK_GENERIC: return NT_STATUS_INVALID_LEVEL; @@ -337,7 +355,6 @@ NTSTATUS pvfs_lock(struct ntvfs_module_context *ntvfs, locks = lck->lockx.in.locks; for (i=0;i<lck->lockx.in.ulock_cnt;i++) { - NTSTATUS status; status = brl_unlock(pvfs->brl_context, &f->locking_key, locks[i].pid, @@ -347,13 +364,12 @@ NTSTATUS pvfs_lock(struct ntvfs_module_context *ntvfs, if (!NT_STATUS_IS_OK(status)) { return status; } + f->lock_count--; } locks += i; for (i=0;i<lck->lockx.in.lock_cnt;i++) { - NTSTATUS status; - if (pending) { pending->pending_lock = i; } @@ -387,9 +403,11 @@ NTSTATUS pvfs_lock(struct ntvfs_module_context *ntvfs, f->fnum, locks[i].offset, locks[i].count); + f->lock_count--; } return status; } + f->lock_count++; } return NT_STATUS_OK; diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 429f519bca..c255558369 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -31,16 +31,19 @@ struct pvfs_file *pvfs_find_fd(struct pvfs_state *pvfs, struct smbsrv_request *req, uint16_t fnum) { struct pvfs_file *f; - for (f=pvfs->open_files;f;f=f->next) { - if (f->fnum == fnum) { - if (req->session != f->session) { - DEBUG(2,("pvfs_find_fd: attempt to use wrong session for fnum %d\n", fnum)); - return NULL; - } - return f; - } + + f = idr_find(pvfs->idtree_fnum, fnum); + if (f == NULL) { + return NULL; } - return NULL; + + if (req->session != f->session) { + DEBUG(2,("pvfs_find_fd: attempt to use wrong session for fnum %d\n", + fnum)); + return NULL; + } + + return f; } /* @@ -52,14 +55,15 @@ static int pvfs_fd_destructor(void *p) { struct pvfs_file *f = p; - pvfs_lock_close_pending(f->pvfs, f); - - brl_close(f->pvfs->brl_context, &f->locking_key, f->fnum); + pvfs_lock_close(f->pvfs, f); if (f->fd != -1) { close(f->fd); f->fd = -1; } + + idr_remove(f->pvfs->idtree_fnum, f->fnum); + return 0; } @@ -80,6 +84,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, dev_t device; ino_t inode; } lock_context; + int fnum; if (io->generic.level != RAW_OPEN_GENERIC) { return ntvfs_map_open(req, io, ntvfs); @@ -147,6 +152,17 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, } } + f = talloc_p(pvfs, struct pvfs_file); + if (f == NULL) { + return NT_STATUS_NO_MEMORY; + } + + fnum = idr_get_new(pvfs->idtree_fnum, f, 0x10000); + if (fnum == -1) { + talloc_free(f); + return NT_STATUS_TOO_MANY_OPENED_FILES; + } + do_open: fd = open(name->full_name, flags, 0644); if (fd == -1) { @@ -155,25 +171,20 @@ do_open: return pvfs_map_errno(pvfs,errno); } - f = talloc_p(pvfs, struct pvfs_file); - if (f == NULL) { - close(fd); - return NT_STATUS_NO_MEMORY; - } - /* re-resolve the open fd */ status = pvfs_resolve_name_fd(pvfs, fd, name); if (!NT_STATUS_IS_OK(status)) { return status; } - f->fnum = fd; + f->fnum = fnum; f->fd = fd; f->name = talloc_steal(f, name); f->session = req->session; f->smbpid = req->smbpid; f->pvfs = pvfs; f->pending_list = NULL; + f->lock_count = 0; /* we must zero here to take account of padding */ ZERO_STRUCT(lock_context); @@ -223,22 +234,16 @@ NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs, return NT_STATUS_INVALID_HANDLE; } - pvfs_lock_close_pending(pvfs, f); - - status = brl_close(pvfs->brl_context, &f->locking_key, f->fnum); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - if (close(f->fd) != 0) { status = pvfs_map_errno(pvfs, errno); } else { status = NT_STATUS_OK; } - - talloc_set_destructor(f, NULL); + f->fd = -1; DLIST_REMOVE(pvfs->open_files, f); + + /* the destructor takes care of the rest */ talloc_free(f); return status; @@ -257,7 +262,6 @@ NTSTATUS pvfs_logoff(struct ntvfs_module_context *ntvfs, for (f=pvfs->open_files;f;f=next) { next = f->next; if (f->session == req->session) { - talloc_set_destructor(f, NULL); DLIST_REMOVE(pvfs->open_files, f); talloc_free(f); } @@ -279,7 +283,6 @@ NTSTATUS pvfs_exit(struct ntvfs_module_context *ntvfs, for (f=pvfs->open_files;f;f=next) { next = f->next; if (f->smbpid == req->smbpid) { - talloc_set_destructor(f, NULL); DLIST_REMOVE(pvfs->open_files, f); talloc_free(f); } 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; diff --git a/source4/ntvfs/posix/vfs_posix.c b/source4/ntvfs/posix/vfs_posix.c index e989f8de67..8aa028919c 100644 --- a/source4/ntvfs/posix/vfs_posix.c +++ b/source4/ntvfs/posix/vfs_posix.c @@ -61,11 +61,10 @@ static NTSTATUS pvfs_connect(struct ntvfs_module_context *ntvfs, char *base_directory; NTSTATUS status; - pvfs = talloc_p(tcon, struct pvfs_state); + pvfs = talloc_zero_p(tcon, struct pvfs_state); if (pvfs == NULL) { return NT_STATUS_NO_MEMORY; } - ZERO_STRUCTP(pvfs); /* for simplicity of path construction, remove any trailing slash now */ base_directory = talloc_strdup(pvfs, lp_pathname(tcon->service)); @@ -95,6 +94,18 @@ static NTSTATUS pvfs_connect(struct ntvfs_module_context *ntvfs, return NT_STATUS_INTERNAL_DB_CORRUPTION; } + /* allocate the fnum id -> ptr tree */ + pvfs->idtree_fnum = idr_init(pvfs); + if (pvfs->idtree_fnum == NULL) { + return NT_STATUS_NO_MEMORY; + } + + /* allocate the search handle -> ptr tree */ + pvfs->idtree_search = idr_init(pvfs); + if (pvfs->idtree_search == NULL) { + return NT_STATUS_NO_MEMORY; + } + status = pvfs_mangle_init(pvfs); if (!NT_STATUS_IS_OK(status)) { return status; diff --git a/source4/ntvfs/posix/vfs_posix.h b/source4/ntvfs/posix/vfs_posix.h index 6aaa43a213..ae601c60c7 100644 --- a/source4/ntvfs/posix/vfs_posix.h +++ b/source4/ntvfs/posix/vfs_posix.h @@ -32,27 +32,17 @@ struct pvfs_state { const char *share_name; uint_t flags; - struct { - /* a linked list of open searches */ - struct pvfs_search_state *open_searches; - - /* search handles are returned to the clients so they - can continue searches */ - uint16_t next_search_handle; - - /* count of active searches */ - uint_t num_active_searches; - - /* during trans2 search continuations we need to use - the initial search attributes */ - uint16_t search_attrib; - } search; - struct pvfs_file *open_files; struct pvfs_mangle_context *mangle_ctx; void *brl_context; + + /* an id tree mapping open search ID to a pvfs_search_state structure */ + void *idtree_search; + + /* an id tree mapping open file handle -> struct pvfs_file */ + void *idtree_fnum; }; @@ -95,7 +85,7 @@ struct pvfs_dir { /* the state of a search started with pvfs_search_first() */ struct pvfs_search_state { - struct pvfs_search_state *next, *prev; + struct pvfs_state *pvfs; uint16_t handle; uint_t current_index; uint16_t search_attrib; @@ -126,6 +116,10 @@ struct pvfs_file { /* a list of pending locks - used for locking cancel operations */ struct pvfs_pending_lock *pending_list; + + /* a count of active locks - used to avoid calling brl_close on + file close */ + uint64_t lock_count; }; |