1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-28 01:58:17 +03:00

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)
This commit is contained in:
Andrew Tridgell 2007-01-22 11:46:27 +00:00 committed by Gerald (Jerry) Carter
parent 44b6652e6c
commit 87df5a6312

View File

@ -423,7 +423,7 @@ static NTSTATUS brl_tdb_unlock(struct brl_context *brl,
{ {
TDB_DATA kbuf, dbuf; TDB_DATA kbuf, dbuf;
int count, i; int count, i;
struct lock_struct *locks; struct lock_struct *locks, *lock;
struct lock_context context; struct lock_context context;
NTSTATUS status; NTSTATUS status;
@ -449,44 +449,60 @@ static NTSTATUS brl_tdb_unlock(struct brl_context *brl,
count = dbuf.dsize / sizeof(*locks); count = dbuf.dsize / sizeof(*locks);
for (i=0; i<count; i++) { 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 == WRITE_LOCK) {
break;
}
}
if (i < count) goto found;
for (i=0; i<count; i++) {
lock = &locks[i];
if (brl_tdb_same_context(&lock->context, &context) && if (brl_tdb_same_context(&lock->context, &context) &&
lock->ntvfs == brlh->ntvfs && lock->ntvfs == brlh->ntvfs &&
lock->start == start && lock->start == start &&
lock->size == size && lock->size == size &&
lock->lock_type < PENDING_READ_LOCK) { lock->lock_type < PENDING_READ_LOCK) {
/* found it - delete it */ break;
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);
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;
} }
} }
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--;
/* 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 */ /* we didn't find it */
status = NT_STATUS_RANGE_NOT_LOCKED; status = NT_STATUS_RANGE_NOT_LOCKED;