summaryrefslogtreecommitdiff
path: root/source4/ntvfs/posix/pvfs_open.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_open.c
parent2b8aa720f47804f783679388f40a9345eff897b9 (diff)
downloadsamba-cf1b85348a0fc5bf4788291109c9dca9e95eb9c2.tar.gz
samba-cf1b85348a0fc5bf4788291109c9dca9e95eb9c2.tar.bz2
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_open.c')
-rw-r--r--source4/ntvfs/posix/pvfs_open.c63
1 files changed, 33 insertions, 30 deletions
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);
}