summaryrefslogtreecommitdiff
path: root/source4/ntvfs/common
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2004-11-03 10:09:48 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:05:23 -0500
commitdde07058075d357cfdc63624c8dcaa67ebd40add (patch)
treec3f29090e37f1bc103a3d6051e708d1ebbe305a5 /source4/ntvfs/common
parent90a8c4acc7e673e6439197776d19cc4b095ac322 (diff)
downloadsamba-dde07058075d357cfdc63624c8dcaa67ebd40add.tar.gz
samba-dde07058075d357cfdc63624c8dcaa67ebd40add.tar.bz2
samba-dde07058075d357cfdc63624c8dcaa67ebd40add.zip
r3507: - added deferred replies on sharing violation in pvfs open. The
deferred reply is short-circuited immediately when the file is closed by another user, allowing it to be opened by the waiting user. - added a sane set of timeval manipulation routines - converted all the events code and code that uses it to use struct timeval instead of time_t, which allows for microsecond resolution instead of 1 second resolution. This was needed for doing the pvfs deferred open code, and is why the patch is so big. (This used to be commit 0d51511d408d91eb5f68a35e980e0875299b1831)
Diffstat (limited to 'source4/ntvfs/common')
-rw-r--r--source4/ntvfs/common/brlock.c7
-rw-r--r--source4/ntvfs/common/opendb.c122
2 files changed, 124 insertions, 5 deletions
diff --git a/source4/ntvfs/common/brlock.c b/source4/ntvfs/common/brlock.c
index d1df0413ce..6fae7c6e4c 100644
--- a/source4/ntvfs/common/brlock.c
+++ b/source4/ntvfs/common/brlock.c
@@ -333,17 +333,14 @@ static void brl_notify_unlock(struct brl_context *brl,
for (i=0;i<count;i++) {
if (locks[i].lock_type >= PENDING_READ_LOCK &&
brl_overlap(&locks[i], removed_lock)) {
- DATA_BLOB data;
-
if (last_notice != -1 && brl_overlap(&locks[i], &locks[last_notice])) {
continue;
}
if (locks[i].lock_type == PENDING_WRITE_LOCK) {
last_notice = i;
}
- data.data = (void *)&locks[i].notify_ptr;
- data.length = sizeof(void *);
- messaging_send(brl->messaging_ctx, locks[i].context.server, MSG_BRL_RETRY, &data);
+ messaging_send_ptr(brl->messaging_ctx, locks[i].context.server,
+ MSG_BRL_RETRY, locks[i].notify_ptr);
}
}
}
diff --git a/source4/ntvfs/common/opendb.c b/source4/ntvfs/common/opendb.c
index 5dc68e5382..39d4f37ec2 100644
--- a/source4/ntvfs/common/opendb.c
+++ b/source4/ntvfs/common/opendb.c
@@ -39,6 +39,7 @@
*/
#include "includes.h"
+#include "messages.h"
struct odb_context {
struct tdb_wrap *w;
@@ -58,6 +59,8 @@ struct odb_entry {
uint32_t share_access;
uint32_t create_options;
uint32_t access_mask;
+ void *notify_ptr;
+ BOOL pending;
};
@@ -152,6 +155,8 @@ static BOOL share_conflict(struct odb_entry *e1, struct odb_entry *e2)
{
#define CHECK_MASK(am, sa, right, share) if (((am) & (right)) && !((sa) & (share))) return True
+ if (e1->pending || e2->pending) return False;
+
/* if either open involves no read.write or delete access then
it can't conflict */
if (!(e1->access_mask & (SA_RIGHT_FILE_WRITE_APPEND |
@@ -219,6 +224,8 @@ NTSTATUS odb_open_file(struct odb_lock *lck, uint16_t fnum,
e.share_access = share_access;
e.create_options = create_options;
e.access_mask = access_mask;
+ e.notify_ptr = NULL;
+ e.pending = False;
/* check the existing file opens to see if they
conflict */
@@ -255,6 +262,56 @@ NTSTATUS odb_open_file(struct odb_lock *lck, uint16_t fnum,
/*
+ register a pending open file in the open files database
+*/
+NTSTATUS odb_open_file_pending(struct odb_lock *lck, void *private)
+{
+ struct odb_context *odb = lck->odb;
+ TDB_DATA dbuf;
+ struct odb_entry e;
+ char *tp;
+ struct odb_entry *elist;
+ int count;
+
+ dbuf = tdb_fetch(odb->w->tdb, lck->key);
+
+ e.server = odb->server;
+ e.tid = odb->tid;
+ e.fnum = 0;
+ e.share_access = 0;
+ e.create_options = 0;
+ e.access_mask = 0;
+ e.notify_ptr = private;
+ e.pending = True;
+
+ /* check the existing file opens to see if they
+ conflict */
+ elist = (struct odb_entry *)dbuf.dptr;
+ count = dbuf.dsize / sizeof(struct odb_entry);
+
+ tp = Realloc(dbuf.dptr, (count+1) * sizeof(struct odb_entry));
+ if (tp == NULL) {
+ if (dbuf.dptr) free(dbuf.dptr);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ dbuf.dptr = tp;
+ dbuf.dsize = (count+1) * sizeof(struct odb_entry);
+
+ memcpy(dbuf.dptr + (count*sizeof(struct odb_entry)),
+ &e, sizeof(struct odb_entry));
+
+ if (tdb_store(odb->w->tdb, lck->key, dbuf, TDB_REPLACE) != 0) {
+ free(dbuf.dptr);
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ free(dbuf.dptr);
+ return NT_STATUS_OK;
+}
+
+
+/*
remove a opendb entry
*/
NTSTATUS odb_close_file(struct odb_lock *lck, uint16_t fnum)
@@ -274,6 +331,15 @@ NTSTATUS odb_close_file(struct odb_lock *lck, uint16_t fnum)
elist = (struct odb_entry *)dbuf.dptr;
count = dbuf.dsize / sizeof(struct odb_entry);
+ /* send any pending notifications */
+ for (i=0;i<count;i++) {
+ if (elist[i].pending) {
+ messaging_send_ptr(odb->messaging_ctx, elist[i].server,
+ MSG_PVFS_RETRY_OPEN, elist[i].notify_ptr);
+
+ }
+ }
+
/* find the entry, and delete it */
for (i=0;i<count;i++) {
if (fnum == elist[i].fnum &&
@@ -309,6 +375,60 @@ NTSTATUS odb_close_file(struct odb_lock *lck, uint16_t fnum)
/*
+ remove a pending opendb entry
+*/
+NTSTATUS odb_remove_pending(struct odb_lock *lck, void *private)
+{
+ struct odb_context *odb = lck->odb;
+ TDB_DATA dbuf;
+ struct odb_entry *elist;
+ int i, count;
+ NTSTATUS status;
+
+ dbuf = tdb_fetch(odb->w->tdb, lck->key);
+
+ if (dbuf.dptr == NULL) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ elist = (struct odb_entry *)dbuf.dptr;
+ count = dbuf.dsize / sizeof(struct odb_entry);
+
+ /* find the entry, and delete it */
+ for (i=0;i<count;i++) {
+ if (private == elist[i].notify_ptr &&
+ odb->server == elist[i].server &&
+ odb->tid == elist[i].tid) {
+ if (i < count-1) {
+ memmove(elist+i, elist+i+1,
+ (count - (i+1)) * sizeof(struct odb_entry));
+ }
+ break;
+ }
+ }
+
+ status = NT_STATUS_OK;
+
+ if (i == count) {
+ status = NT_STATUS_UNSUCCESSFUL;
+ } else if (count == 1) {
+ if (tdb_delete(odb->w->tdb, lck->key) != 0) {
+ status = NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+ } else {
+ dbuf.dsize = (count-1) * sizeof(struct odb_entry);
+ if (tdb_store(odb->w->tdb, lck->key, dbuf, TDB_REPLACE) != 0) {
+ status = NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+ }
+
+ free(dbuf.dptr);
+
+ return status;
+}
+
+
+/*
update create options on an open file
*/
NTSTATUS odb_set_create_options(struct odb_lock *lck,
@@ -386,6 +506,8 @@ NTSTATUS odb_can_open(struct odb_context *odb, DATA_BLOB *key,
e.share_access = share_access;
e.create_options = create_options;
e.access_mask = access_mask;
+ e.notify_ptr = NULL;
+ e.pending = False;
for (i=0;i<count;i++) {
if (share_conflict(elist+i, &e)) {