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:
parent
44b6652e6c
commit
87df5a6312
@ -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;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user