From 7769e197e6a6f0b4c080d13d0ce5e74bde724f50 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 27 Feb 2014 16:19:53 -0800 Subject: [PATCH] s3: smbd: Ensure brl_get_locks_internal() always returns a valid struct byte_range_lock even if there are no locks. brl_get_locks_internal() currently returns NULL when it can't find any byte range locks on the file. This is an error - it should return a valid struct byte_range_lock containing num_locks == 0 so it can be cached. Returning NULL when there are no locks causes POSIX lock tests to fail returning NT_STATUS_NO_MEMORY (as it thinks it can't allocate the struct) instead of NT_STATUS_OK. This is a back-port of git commit abf08ed544ce05ea5a6e6ea2e531b6a2d97e15cc that went into master. Fixes bug: Bug 10431 - STATUS_NO_MEMORY response from Query File Posix Lock request https://bugzilla.samba.org/show_bug.cgi?id=10431 Signed-off-by: Jeremy Allison --- source3/locking/brlock.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 865aaca..78c2538 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -1862,12 +1862,14 @@ static void byte_range_lock_flush(struct byte_range_lock *br_lck) } if (br_lck->num_locks == 0) { - /* No locks - delete this entry. */ - NTSTATUS status = dbwrap_record_delete(br_lck->record); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("delete_rec returned %s\n", - nt_errstr(status))); - smb_panic("Could not delete byte range lock entry"); + if (br_lck->record) { + /* No locks and the record existed - delete this entry. */ + NTSTATUS status = dbwrap_record_delete(br_lck->record); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("delete_rec returned %s\n", + nt_errstr(status))); + smb_panic("Could not delete byte range lock entry"); + } } } else { TDB_DATA data; @@ -1932,7 +1934,12 @@ static struct byte_range_lock *brl_get_locks_internal(TALLOC_CTX *mem_ctx, if (do_read_only) { NTSTATUS status; status = dbwrap_fetch(brlock_db, br_lck, key, &data); - if (!NT_STATUS_IS_OK(status)) { + if (NT_STATUS_EQUAL(status,NT_STATUS_NOT_FOUND)) { + /* + * No locks on this file. data should be empty. + */ + ZERO_STRUCT(data); + } else if (!NT_STATUS_IS_OK(status)) { DEBUG(3, ("Could not fetch byte range lock record\n")); TALLOC_FREE(br_lck); return NULL; @@ -1942,12 +1949,15 @@ static struct byte_range_lock *brl_get_locks_internal(TALLOC_CTX *mem_ctx, br_lck->record = dbwrap_fetch_locked(brlock_db, br_lck, key); if (br_lck->record == NULL) { - DEBUG(3, ("Could not lock byte range lock entry\n")); - TALLOC_FREE(br_lck); - return NULL; + /* + * We're going to assume this means no locks on + * the file, not a talloc fail. If it was a talloc + * fail we'll just have to die elsewhere. + */ + ZERO_STRUCT(data); + } else { + data = dbwrap_record_get_value(br_lck->record); } - - data = dbwrap_record_get_value(br_lck->record); } br_lck->read_only = do_read_only; -- 1.9.0.279.gdc9e3eb