r20947: fixed a bug in the unlock logic in the brlock tdb backend
authorAndrew Tridgell <tridge@samba.org>
Mon, 22 Jan 2007 11:46:27 +0000 (11:46 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 19:43:59 +0000 (14:43 -0500)
I'm very surprised this didn't show up earlier!

source/ntvfs/common/brlock_tdb.c

index ee83008ce21f384a5ef238d11f92e9199cf8fd2b..6fe8cefd34463ff4ec2dfb71bb71263cbd0951c4 100644 (file)
@@ -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 */