locking: move share_mode_flags_[gs]et to share_mode_lock.c
authorVolker Lendecke <vl@samba.org>
Thu, 5 Nov 2020 14:39:51 +0000 (15:39 +0100)
committerJeremy Allison <jra@samba.org>
Tue, 10 Nov 2020 19:49:35 +0000 (19:49 +0000)
These routines parse and marshall the uint16 summary flag in
share_mode_data. open_file_ntcreate() and open_directory() are the
only real users of this. The user in oplock.c is just the lazy reset
of the "read lease exists somewhere" after asynchronously breaking
read oplocks after a write request.

This moves handling the flags into locking/ to consolidate data
structure handling of "share_mode_data" there.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
source3/locking/share_mode_lock.c
source3/locking/share_mode_lock.h
source3/smbd/open.c
source3/smbd/oplock.c

index c860810d08693f707cb749c03e237ee660f91a58..c193748e5e8821364582b177f6c9d77d59be85f0 100644 (file)
@@ -1176,6 +1176,85 @@ char *share_mode_data_dump(
        return ret;
 }
 
+void share_mode_flags_get(
+       struct share_mode_lock *lck,
+       uint32_t *access_mask,
+       uint32_t *share_mode,
+       uint32_t *lease_type)
+{
+       uint16_t flags = lck->data->flags;
+
+       if (access_mask != NULL) {
+               *access_mask =
+                       ((flags & SHARE_MODE_ACCESS_READ) ?
+                        FILE_READ_DATA : 0) |
+                       ((flags & SHARE_MODE_ACCESS_WRITE) ?
+                        FILE_WRITE_DATA : 0) |
+                       ((flags & SHARE_MODE_ACCESS_DELETE) ?
+                        DELETE_ACCESS : 0);
+       }
+       if (share_mode != NULL) {
+               *share_mode =
+                       ((flags & SHARE_MODE_SHARE_READ) ?
+                        FILE_SHARE_READ : 0) |
+                       ((flags & SHARE_MODE_SHARE_WRITE) ?
+                        FILE_SHARE_WRITE : 0) |
+                       ((flags & SHARE_MODE_SHARE_DELETE) ?
+                        FILE_SHARE_DELETE : 0);
+       }
+       if (lease_type != NULL) {
+               *lease_type =
+                       ((flags & SHARE_MODE_LEASE_READ) ?
+                        SMB2_LEASE_READ : 0) |
+                       ((flags & SHARE_MODE_LEASE_WRITE) ?
+                        SMB2_LEASE_WRITE : 0) |
+                       ((flags & SHARE_MODE_LEASE_HANDLE) ?
+                        SMB2_LEASE_HANDLE : 0);
+       }
+}
+
+void share_mode_flags_set(
+       struct share_mode_lock *lck,
+       uint32_t access_mask,
+       uint32_t share_mode,
+       uint32_t lease_type,
+       bool *modified)
+{
+       struct share_mode_data *d = lck->data;
+       uint16_t flags = 0;
+
+       flags |= (access_mask & (FILE_READ_DATA | FILE_EXECUTE)) ?
+               SHARE_MODE_ACCESS_READ : 0;
+       flags |= (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) ?
+               SHARE_MODE_ACCESS_WRITE : 0;
+       flags |= (access_mask & (DELETE_ACCESS)) ?
+               SHARE_MODE_ACCESS_DELETE : 0;
+
+       flags |= (share_mode & FILE_SHARE_READ) ?
+               SHARE_MODE_SHARE_READ : 0;
+       flags |= (share_mode & FILE_SHARE_WRITE) ?
+               SHARE_MODE_SHARE_WRITE : 0;
+       flags |= (share_mode & FILE_SHARE_DELETE) ?
+               SHARE_MODE_SHARE_DELETE : 0;
+
+       flags |= (lease_type & SMB2_LEASE_READ) ?
+               SHARE_MODE_LEASE_READ : 0;
+       flags |= (lease_type & SMB2_LEASE_WRITE) ?
+               SHARE_MODE_LEASE_WRITE : 0;
+       flags |= (lease_type & SMB2_LEASE_HANDLE) ?
+               SHARE_MODE_LEASE_HANDLE : 0;
+
+       if (d->flags == flags) {
+               return;
+       }
+
+       if (modified != NULL) {
+               *modified = true;
+       }
+       d->flags = flags;
+       d->modified = true;
+}
+
 struct share_mode_watch_state {
        bool blockerdead;
        struct server_id blocker;
index 4254859ce0a432062f83b4d1d4fed5d69543a2ce..6221a0394915b8e519d1ad74eb08de37ff928ea4 100644 (file)
@@ -104,6 +104,18 @@ char *share_mode_filename(TALLOC_CTX *mem_ctx, struct share_mode_lock *lck);
 char *share_mode_data_dump(
        TALLOC_CTX *mem_ctx, struct share_mode_lock *lck);
 
+void share_mode_flags_get(
+       struct share_mode_lock *lck,
+       uint32_t *access_mask,
+       uint32_t *share_mode,
+       uint32_t *lease_type);
+void share_mode_flags_set(
+       struct share_mode_lock *lck,
+       uint32_t access_mask,
+       uint32_t share_mode,
+       uint32_t lease_type,
+       bool *modified);
+
 struct tevent_req *share_mode_watch_send(
        TALLOC_CTX *mem_ctx,
        struct tevent_context *ev,
index e4a2381def38e3a9c8c22a83cfe5047897bb83a8..95934e2e3211922411d08a1aa1c543f6410b9a85 100644 (file)
@@ -1666,96 +1666,17 @@ static bool has_delete_on_close(struct share_mode_lock *lck,
        return state.ret;
 }
 
-static void share_mode_flags_get(
-       uint16_t flags,
-       uint32_t *access_mask,
-       uint32_t *share_mode,
-       uint32_t *lease_type)
-{
-       if (access_mask != NULL) {
-               *access_mask =
-                       ((flags & SHARE_MODE_ACCESS_READ) ?
-                        FILE_READ_DATA : 0) |
-                       ((flags & SHARE_MODE_ACCESS_WRITE) ?
-                        FILE_WRITE_DATA : 0) |
-                       ((flags & SHARE_MODE_ACCESS_DELETE) ?
-                        DELETE_ACCESS : 0);
-       }
-       if (share_mode != NULL) {
-               *share_mode =
-                       ((flags & SHARE_MODE_SHARE_READ) ?
-                        FILE_SHARE_READ : 0) |
-                       ((flags & SHARE_MODE_SHARE_WRITE) ?
-                        FILE_SHARE_WRITE : 0) |
-                       ((flags & SHARE_MODE_SHARE_DELETE) ?
-                        FILE_SHARE_DELETE : 0);
-       }
-       if (lease_type != NULL) {
-               *lease_type =
-                       ((flags & SHARE_MODE_LEASE_READ) ?
-                        SMB2_LEASE_READ : 0) |
-                       ((flags & SHARE_MODE_LEASE_WRITE) ?
-                        SMB2_LEASE_WRITE : 0) |
-                       ((flags & SHARE_MODE_LEASE_HANDLE) ?
-                        SMB2_LEASE_HANDLE : 0);
-       }
-}
-
-static uint16_t share_mode_flags_set(
-       uint16_t flags,
-       uint32_t access_mask,
-       uint32_t share_mode,
-       uint32_t lease_type)
-{
-       if (access_mask != UINT32_MAX) {
-               flags &= ~(SHARE_MODE_ACCESS_READ|
-                          SHARE_MODE_ACCESS_WRITE|
-                          SHARE_MODE_ACCESS_DELETE);
-               flags |= (access_mask & (FILE_READ_DATA | FILE_EXECUTE)) ?
-                       SHARE_MODE_ACCESS_READ : 0;
-               flags |= (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) ?
-                       SHARE_MODE_ACCESS_WRITE : 0;
-               flags |= (access_mask & (DELETE_ACCESS)) ?
-                       SHARE_MODE_ACCESS_DELETE : 0;
-       }
-       if (share_mode != UINT32_MAX) {
-               flags &= ~(SHARE_MODE_SHARE_READ|
-                          SHARE_MODE_SHARE_WRITE|
-                          SHARE_MODE_SHARE_DELETE);
-               flags |= (share_mode & FILE_SHARE_READ) ?
-                       SHARE_MODE_SHARE_READ : 0;
-               flags |= (share_mode & FILE_SHARE_WRITE) ?
-                       SHARE_MODE_SHARE_WRITE : 0;
-               flags |= (share_mode & FILE_SHARE_DELETE) ?
-                       SHARE_MODE_SHARE_DELETE : 0;
-       }
-       if (lease_type != UINT32_MAX) {
-               flags &= ~(SHARE_MODE_LEASE_READ|
-                          SHARE_MODE_LEASE_WRITE|
-                          SHARE_MODE_LEASE_HANDLE);
-               flags |= (lease_type & SMB2_LEASE_READ) ?
-                       SHARE_MODE_LEASE_READ : 0;
-               flags |= (lease_type & SMB2_LEASE_WRITE) ?
-                       SHARE_MODE_LEASE_WRITE : 0;
-               flags |= (lease_type & SMB2_LEASE_HANDLE) ?
-                       SHARE_MODE_LEASE_HANDLE : 0;
-       }
-
-       return flags;
-}
-
-static uint16_t share_mode_flags_restrict(
-       uint16_t flags,
+static void share_mode_flags_restrict(
+       struct share_mode_lock *lck,
        uint32_t access_mask,
        uint32_t share_mode,
        uint32_t lease_type)
 {
        uint32_t existing_access_mask, existing_share_mode;
        uint32_t existing_lease_type;
-       uint16_t ret;
 
        share_mode_flags_get(
-               flags,
+               lck,
                &existing_access_mask,
                &existing_share_mode,
                &existing_lease_type);
@@ -1766,12 +1687,12 @@ static uint16_t share_mode_flags_restrict(
        }
        existing_lease_type |= lease_type;
 
-       ret = share_mode_flags_set(
-               flags,
+       share_mode_flags_set(
+               lck,
                existing_access_mask,
                existing_share_mode,
-               existing_lease_type);
-       return ret;
+               existing_lease_type,
+               NULL);
 }
 
 /****************************************************************************
@@ -1832,10 +1753,9 @@ static NTSTATUS open_mode_check(connection_struct *conn,
                                uint32_t access_mask,
                                uint32_t share_access)
 {
-       struct share_mode_data *d = lck->data;
        struct open_mode_check_state state;
-       uint16_t new_flags;
        bool ok, conflict, have_share_entries;
+       bool modified = false;
 
        if (is_oplock_stat_open(access_mask)) {
                /* Stat open that doesn't trigger oplock breaks or share mode
@@ -1870,7 +1790,7 @@ static NTSTATUS open_mode_check(connection_struct *conn,
        }
 
        share_mode_flags_get(
-               d->flags, &state.access_mask, &state.share_access, NULL);
+               lck, &state.access_mask, &state.share_access, NULL);
 
        conflict = share_conflict(
                state.access_mask,
@@ -1899,9 +1819,13 @@ static NTSTATUS open_mode_check(connection_struct *conn,
                return NT_STATUS_INTERNAL_ERROR;
        }
 
-       new_flags = share_mode_flags_set(
-               0, state.access_mask, state.share_access, state.lease_type);
-       if (new_flags == d->flags) {
+       share_mode_flags_set(
+               lck,
+               state.access_mask,
+               state.share_access,
+               state.lease_type,
+               &modified);
+       if (!modified) {
                /*
                 * We only end up here if we had a sharing violation
                 * from d->flags and have recalculated it.
@@ -1909,9 +1833,6 @@ static NTSTATUS open_mode_check(connection_struct *conn,
                return NT_STATUS_SHARING_VIOLATION;
        }
 
-       d->flags = new_flags;
-       d->modified = true;
-
        conflict = share_conflict(
                state.access_mask,
                state.share_access,
@@ -2656,10 +2577,11 @@ grant:
                }
        }
 
-       if ((granted & SMB2_LEASE_READ) &&
-           ((lck->data->flags & SHARE_MODE_LEASE_READ) == 0)) {
-               lck->data->flags |= SHARE_MODE_LEASE_READ;
-               lck->data->modified = true;
+       if (granted & SMB2_LEASE_READ) {
+               uint32_t acc, sh, ls;
+               share_mode_flags_get(lck, &acc, &sh, &ls);
+               ls |= SHARE_MODE_LEASE_READ;
+               share_mode_flags_set(lck, acc, sh, ls, NULL);
        }
 
        DBG_DEBUG("oplock type 0x%x on file %s\n",
@@ -3914,16 +3836,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
                return status;
        }
 
-       {
-               struct share_mode_data *d = lck->data;
-               uint16_t new_flags = share_mode_flags_restrict(
-                       d->flags, access_mask, share_access, UINT32_MAX);
-
-               if (new_flags != d->flags) {
-                       d->flags = new_flags;
-                       d->modified = true;
-               }
-       }
+       share_mode_flags_restrict(lck, access_mask, share_access, 0);
 
        ok = set_share_mode(
                lck,
@@ -4600,16 +4513,7 @@ static NTSTATUS open_directory(connection_struct *conn,
                return status;
        }
 
-       {
-               struct share_mode_data *d = lck->data;
-               uint16_t new_flags = share_mode_flags_restrict(
-                       d->flags, access_mask, share_access, UINT32_MAX);
-
-               if (new_flags != d->flags) {
-                       d->flags = new_flags;
-                       d->modified = true;
-               }
-       }
+       share_mode_flags_restrict(lck, access_mask, share_access, 0);
 
        ok = set_share_mode(
                lck,
index 9feda47c922a72081ecbe1681a391242f4e5e5ce..b6ac60fa4e14feec1efe1b9686b62a6760a3b736 100644 (file)
@@ -1282,7 +1282,6 @@ static void contend_level2_oplocks_begin_default(files_struct *fsp,
                .sconn = fsp->conn->sconn, .id = fsp->file_id,
        };
        struct share_mode_lock *lck = NULL;
-       struct share_mode_data *d = NULL;
        bool ok, has_read_lease;
 
        /*
@@ -1321,7 +1320,6 @@ static void contend_level2_oplocks_begin_default(files_struct *fsp,
                            file_id_str_buf(state.id, &idbuf));
                return;
        }
-       d = lck->data;
 
        /*
         * Walk leases and oplocks separately: We have to send one break per
@@ -1345,8 +1343,10 @@ static void contend_level2_oplocks_begin_default(files_struct *fsp,
                 * Lazy update here. It might be that the read lease
                 * has gone in the meantime.
                 */
-               d->flags &= ~SHARE_MODE_LEASE_READ;
-               d->modified = true;
+               uint32_t acc, sh, ls;
+               share_mode_flags_get(lck, &acc, &sh, &ls);
+               ls &= ~SHARE_MODE_LEASE_READ;
+               share_mode_flags_set(lck, acc, sh, ls, NULL);
        }
 
        TALLOC_FREE(lck);