]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s3/brlock: update brlock cleanup for Persistent Handles
authorRalph Boehme <slow@samba.org>
Fri, 29 Aug 2025 13:44:16 +0000 (15:44 +0200)
committerRalph Boehme <slow@samba.org>
Fri, 17 Jul 2026 10:18:37 +0000 (10:18 +0000)
Durable Handles don't allow byte-range locks from other opens on a file, but
Persistent Handles do allow this. Adapt brl_cleanup_disconnected() to
deal with locks from different handles.

Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Anoop C S <anoopcs@samba.org>
source3/locking/brlock.c

index f02689680812791a200c8315bbbb49205ee7b05a..47df257b5ec247184e01c70d042c6ca83085128e 100644 (file)
@@ -1899,63 +1899,59 @@ bool brl_cleanup_disconnected(struct file_id fid, uint64_t open_persistent_id)
 {
        bool ret = false;
        TALLOC_CTX *frame = talloc_stackframe();
-       TDB_DATA key, val;
-       struct db_record *rec;
-       struct lock_struct *lock;
+       struct byte_range_lock *br_lck = NULL;
+       struct lock_struct *locks = NULL;
        unsigned n, num;
        struct file_id_buf buf;
-       NTSTATUS status;
-
-       key = make_tdb_data((void*)&fid, sizeof(fid));
 
-       rec = dbwrap_fetch_locked(brlock_db, frame, key);
-       if (rec == NULL) {
-               DBG_INFO("failed to fetch record for file %s\n",
-                        file_id_str_buf(fid, &buf));
-               goto done;
+       br_lck = brl_get_locks_for_cleanup(frame, &fid);
+       if (br_lck == NULL) {
+               return false;
        }
 
-       val = dbwrap_record_get_value(rec);
-       lock = (struct lock_struct*)val.dptr;
-       num = val.dsize / sizeof(struct lock_struct);
-       if (lock == NULL) {
-               DBG_DEBUG("no byte range locks for file %s\n",
-                         file_id_str_buf(fid, &buf));
-               ret = true;
-               goto done;
-       }
+       locks = br_lck->lock_data;
 
-       for (n=0; n<num; n++) {
-               struct lock_context *ctx = &lock[n].context;
+       for (n = 0, num = 0; n < br_lck->num_locks; n++) {
+               struct lock_struct *lock = &locks[n];
+               struct lock_context *ctx = &lock->context;
 
-               if (!server_id_is_disconnected(&ctx->pid)) {
-                       struct server_id_buf tmp;
-                       DBG_INFO("byte range lock "
-                                "%s used by server %s, do not cleanup\n",
-                                file_id_str_buf(fid, &buf),
-                                server_id_str_buf(ctx->pid, &tmp));
-                       goto done;
+               if (ctx->smblctx != open_persistent_id) {
+                       DBG_DEBUG("byte range lock %s, "
+                                 "cleanup smblctx %"PRIu64", "
+                                 "found %"PRIu64", do not cleanup\n",
+                                 file_id_str_buf(fid, &buf),
+                                 open_persistent_id,
+                                 ctx->smblctx);
+                       continue;
                }
 
-               if (ctx->smblctx != open_persistent_id) {
-                       DBG_INFO("byte range lock %s expected smblctx %"PRIu64" "
-                                "but found %"PRIu64", do not cleanup\n",
-                                file_id_str_buf(fid, &buf),
-                                open_persistent_id,
-                                ctx->smblctx);
-                       goto done;
+               if (lock->persistent) {
+                       if (serverid_exists(&ctx->pid)) {
+                               struct server_id_buf tmp;
+                               DBG_WARNING("byte range lock %s used by "
+                                           "server %s, do not cleanup\n",
+                                           file_id_str_buf(fid, &buf),
+                                           server_id_str_buf(ctx->pid, &tmp));
+                               continue;
+                       }
+               } else {
+                       if (!server_id_is_disconnected(&ctx->pid)) {
+                               struct server_id_buf tmp;
+                               DBG_WARNING("byte range lock %s used by "
+                                           "server %s, do not cleanup\n",
+                                           file_id_str_buf(fid, &buf),
+                                           server_id_str_buf(ctx->pid, &tmp));
+                               continue;
+                       }
                }
-       }
 
-       status = dbwrap_record_delete(rec);
-       if (!NT_STATUS_IS_OK(status)) {
-               DBG_INFO("failed to delete record "
-                        "for file %s from %s, open %"PRIu64": %s\n",
-                        file_id_str_buf(fid, &buf),
-                        dbwrap_name(brlock_db),
-                        open_persistent_id,
-                        nt_errstr(status));
-               goto done;
+               /*
+                * Set lock pid holder to 0, triggers lock deletion in
+                * byte_range_lock_flush().
+                */
+               lock->context.pid.pid = 0;
+               br_lck->modified = true;
+               num++;
        }
 
        DBG_DEBUG("file %s cleaned up %u entries from open %"PRIu64"\n",
@@ -1964,7 +1960,7 @@ bool brl_cleanup_disconnected(struct file_id fid, uint64_t open_persistent_id)
                  open_persistent_id);
 
        ret = true;
-done:
+
        talloc_free(frame);
        return ret;
 }