summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2007-01-22 11:46:27 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 14:43:59 -0500
commit87df5a631200a5725618fbe2779ade7066ad084c (patch)
tree33cb258caf3d4095a10da9a7840cf12f2197cf6a
parent44b6652e6ce252cedccdcbba2301261257094203 (diff)
downloadsamba-87df5a631200a5725618fbe2779ade7066ad084c.tar.gz
samba-87df5a631200a5725618fbe2779ade7066ad084c.tar.bz2
samba-87df5a631200a5725618fbe2779ade7066ad084c.zip
r20947: fixed a bug in the unlock logic in the brlock tdb backend
I'm very surprised this didn't show up earlier! (This used to be commit 5d9b1acf4f35d11c4730cbc9cadedb33c6ec08e8)
-rw-r--r--source4/ntvfs/common/brlock_tdb.c72
1 files changed, 44 insertions, 28 deletions
diff --git a/source4/ntvfs/common/brlock_tdb.c b/source4/ntvfs/common/brlock_tdb.c
index ee83008ce2..6fe8cefd34 100644
--- a/source4/ntvfs/common/brlock_tdb.c
+++ b/source4/ntvfs/common/brlock_tdb.c
@@ -423,7 +423,7 @@ static NTSTATUS brl_tdb_unlock(struct brl_context *brl,
{
TDB_DATA kbuf, dbuf;
int count, i;
- struct lock_struct *locks;
+ struct lock_struct *locks, *lock;
struct lock_context context;
NTSTATUS status;
@@ -449,42 +449,58 @@ static NTSTATUS brl_tdb_unlock(struct brl_context *brl,
count = dbuf.dsize / sizeof(*locks);
for (i=0; i<count; i++) {
- struct lock_struct *lock = &locks[i];
-
+ lock = &locks[i];
if (brl_tdb_same_context(&lock->context, &context) &&
lock->ntvfs == brlh->ntvfs &&
lock->start == start &&
lock->size == size &&
- lock->lock_type < PENDING_READ_LOCK) {
- /* found it - delete it */
- if (count == 1) {
- if (tdb_delete(brl->w->tdb, kbuf) != 0) {
- status = NT_STATUS_INTERNAL_DB_CORRUPTION;
- goto fail;
- }
- } else {
- struct lock_struct removed_lock = *lock;
- if (i < count-1) {
- memmove(&locks[i], &locks[i+1],
- sizeof(*locks)*((count-1) - i));
- }
- count--;
-
- /* send notifications for any relevant pending locks */
- brl_tdb_notify_unlock(brl, locks, count, &removed_lock);
+ lock->lock_type == WRITE_LOCK) {
+ break;
+ }
+ }
+ if (i < count) goto found;
- dbuf.dsize = count * sizeof(*locks);
+ for (i=0; i<count; i++) {
+ lock = &locks[i];
+ if (brl_tdb_same_context(&lock->context, &context) &&
+ lock->ntvfs == brlh->ntvfs &&
+ lock->start == start &&
+ lock->size == size &&
+ lock->lock_type < PENDING_READ_LOCK) {
+ break;
+ }
+ }
- if (tdb_store(brl->w->tdb, kbuf, dbuf, TDB_REPLACE) != 0) {
- status = NT_STATUS_INTERNAL_DB_CORRUPTION;
- goto fail;
- }
+found:
+ if (i < count) {
+ /* found it - delete it */
+ if (count == 1) {
+ if (tdb_delete(brl->w->tdb, kbuf) != 0) {
+ status = NT_STATUS_INTERNAL_DB_CORRUPTION;
+ goto fail;
+ }
+ } else {
+ struct lock_struct removed_lock = *lock;
+ if (i < count-1) {
+ memmove(&locks[i], &locks[i+1],
+ sizeof(*locks)*((count-1) - i));
}
+ count--;
- free(dbuf.dptr);
- tdb_chainunlock(brl->w->tdb, kbuf);
- return NT_STATUS_OK;
+ /* send notifications for any relevant pending locks */
+ brl_tdb_notify_unlock(brl, locks, count, &removed_lock);
+
+ dbuf.dsize = count * sizeof(*locks);
+
+ if (tdb_store(brl->w->tdb, kbuf, dbuf, TDB_REPLACE) != 0) {
+ status = NT_STATUS_INTERNAL_DB_CORRUPTION;
+ goto fail;
+ }
}
+
+ free(dbuf.dptr);
+ tdb_chainunlock(brl->w->tdb, kbuf);
+ return NT_STATUS_OK;
}
/* we didn't find it */