smbd: Use share_mode_entry's lease data in remove_share_mode_lease()
[gd/samba-autobuild/.git] / source3 / locking / locking.c
index e962fee89abe32e34c87ff16f4887fe8c1f8b99c..db20a5a1c9019e655da493229b7700c164a41397 100644 (file)
@@ -150,6 +150,9 @@ bool strict_lock_check_default(files_struct *fsp, struct lock_struct *plock)
                 * autocleanup. This is the slow path anyway.
                 */
                br_lck = brl_get_locks(talloc_tos(), fsp);
+               if (br_lck == NULL) {
+                       return true;
+               }
                ret = brl_locktest(br_lck, plock);
                TALLOC_FREE(br_lck);
        }
@@ -657,8 +660,6 @@ bool is_valid_share_mode_entry(const struct share_mode_entry *e)
 static void remove_share_mode_lease(struct share_mode_data *d,
                                    struct share_mode_entry *e)
 {
-       struct GUID client_guid;
-       struct smb2_lease_key lease_key;
        uint16_t op_type;
        uint32_t lease_idx;
        uint32_t i;
@@ -681,14 +682,19 @@ static void remove_share_mode_lease(struct share_mode_data *d,
        e->lease_idx = UINT32_MAX;
 
        for (i=0; i<d->num_share_modes; i++) {
-               if (d->share_modes[i].stale) {
+               struct share_mode_entry *e2 = &d->share_modes[i];
+
+               if (e2->stale) {
                        continue;
                }
-               if (e == &d->share_modes[i]) {
+               if (e == e2) {
                        /* Not ourselves. */
                        continue;
                }
-               if (d->share_modes[i].lease_idx == lease_idx) {
+               if (smb2_lease_equal(&e->client_guid,
+                                    &e->lease_key,
+                                    &e2->client_guid,
+                                    &e2->lease_key)) {
                        break;
                }
        }
@@ -699,11 +705,6 @@ static void remove_share_mode_lease(struct share_mode_data *d,
                return;
        }
 
-       memcpy(&client_guid,
-               &d->leases[lease_idx].client_guid,
-               sizeof(client_guid));
-       lease_key = d->leases[lease_idx].lease_key;
-
        d->num_leases -= 1;
        d->leases[lease_idx] = d->leases[d->num_leases];
 
@@ -713,16 +714,15 @@ static void remove_share_mode_lease(struct share_mode_data *d,
        for (i=0; i<d->num_share_modes; i++) {
                if (d->share_modes[i].lease_idx == d->num_leases) {
                        d->share_modes[i].lease_idx = lease_idx;
-                       d->share_modes[i].lease = &d->leases[lease_idx];
                }
        }
 
        {
                NTSTATUS status;
 
-               status = leases_db_del(&client_guid,
-                                       &lease_key,
-                                       &d->id);
+               status = leases_db_del(&e->client_guid,
+                                      &e->lease_key,
+                                      &d->id);
 
                DEBUG(10, ("%s: leases_db_del returned %s\n", __func__,
                           nt_errstr(status)));
@@ -740,8 +740,10 @@ bool share_mode_stale_pid(struct share_mode_data *d, uint32_t idx)
        struct share_mode_entry *e;
 
        if (idx > d->num_share_modes) {
-               DEBUG(1, ("Asking for index %u, only %u around\n",
-                         idx, (unsigned)d->num_share_modes));
+               DBG_WARNING("Asking for index %"PRIu32", "
+                           "only %"PRIu32" around\n",
+                           idx,
+                           d->num_share_modes);
                return false;
        }
        e = &d->share_modes[idx];
@@ -752,36 +754,36 @@ bool share_mode_stale_pid(struct share_mode_data *d, uint32_t idx)
                return true;
        }
        if (serverid_exists(&e->pid)) {
-               DEBUG(10, ("PID %s (index %u out of %u) still exists\n",
-                          server_id_str_buf(e->pid, &tmp), idx,
-                          (unsigned)d->num_share_modes));
+               DBG_DEBUG("PID %s (index %"PRIu32" out of %"PRIu32") "
+                         "still exists\n",
+                         server_id_str_buf(e->pid, &tmp),
+                         idx,
+                         d->num_share_modes);
                return false;
        }
-       DEBUG(10, ("PID %s (index %u out of %u) does not exist anymore\n",
-                  server_id_str_buf(e->pid, &tmp), idx,
-                  (unsigned)d->num_share_modes));
+       DBG_DEBUG("PID %s (index %"PRIu32" out of %"PRIu32") "
+                 "does not exist anymore\n",
+                 server_id_str_buf(e->pid, &tmp),
+                 idx,
+                 d->num_share_modes);
 
        e->stale = true;
 
        if (d->num_delete_tokens != 0) {
-               uint32_t i, num_stale;
-
-               /*
-                * We cannot have any delete tokens
-                * if there are no valid share modes.
-                */
-
-               num_stale = 0;
+               uint32_t i;
 
                for (i=0; i<d->num_share_modes; i++) {
-                       if (d->share_modes[i].stale) {
-                               num_stale += 1;
+                       bool valid = !d->share_modes[i].stale;
+                       if (valid) {
+                               break;
                        }
                }
 
-               if (num_stale == d->num_share_modes) {
+               if (i == d->num_share_modes) {
                        /*
-                        * No non-stale share mode found
+                        * No valid (non-stale) share mode found, all
+                        * who might have set the delete token are
+                        * gone.
                         */
                        TALLOC_FREE(d->delete_tokens);
                        d->num_delete_tokens = 0;
@@ -804,9 +806,9 @@ void remove_stale_share_mode_entries(struct share_mode_data *d)
                        struct share_mode_entry *m = d->share_modes;
                        m[i] = m[d->num_share_modes-1];
                        d->num_share_modes -= 1;
-               } else {
-                       i += 1;
+                       continue;
                }
+               i += 1;
        }
 }
 
@@ -816,14 +818,10 @@ bool set_share_mode(struct share_mode_lock *lck, struct files_struct *fsp,
 {
        struct share_mode_data *d = lck->data;
        struct share_mode_entry *tmp, *e;
-       struct share_mode_lease *lease = NULL;
 
-       if (lease_idx == UINT32_MAX) {
-               lease = NULL;
-       } else if (lease_idx >= d->num_leases) {
+       if ((lease_idx != UINT32_MAX) &&
+           (lease_idx >= d->num_leases)) {
                return false;
-       } else {
-               lease = &d->leases[lease_idx];
        }
 
        tmp = talloc_realloc(d, d->share_modes, struct share_mode_entry,
@@ -844,7 +842,10 @@ bool set_share_mode(struct share_mode_lock *lck, struct files_struct *fsp,
        e->op_mid = mid;
        e->op_type = op_type;
        e->lease_idx = lease_idx;
-       e->lease = lease;
+       if (lease_idx != UINT32_MAX) {
+               e->client_guid = lck->data->leases[lease_idx].client_guid;
+               e->lease_key = lck->data->leases[lease_idx].lease_key;
+       }
        e->time.tv_sec = fsp->open_time.tv_sec;
        e->time.tv_usec = fsp->open_time.tv_usec;
        e->share_file_id = fsp->fh->gen_id;
@@ -883,8 +884,7 @@ struct share_mode_entry *find_share_mode_entry(
 }
 
 /*******************************************************************
- Del the share mode of a file for this process. Return the number of
- entries left.
+ Del the share mode of a file for this process.
 ********************************************************************/
 
 bool del_share_mode(struct share_mode_lock *lck, files_struct *fsp)
@@ -974,86 +974,6 @@ bool downgrade_share_oplock(struct share_mode_lock *lck, files_struct *fsp)
        return True;
 }
 
-NTSTATUS downgrade_share_lease(struct smbd_server_connection *sconn,
-                              struct share_mode_lock *lck,
-                              const struct smb2_lease_key *key,
-                              uint32_t new_lease_state,
-                              struct share_mode_lease **_l)
-{
-       struct share_mode_data *d = lck->data;
-       struct share_mode_lease *l;
-       uint32_t i;
-
-       *_l = NULL;
-
-       for (i=0; i<d->num_leases; i++) {
-               if (smb2_lease_equal(&sconn->client->connections->smb2.client.guid,
-                                    key,
-                                    &d->leases[i].client_guid,
-                                    &d->leases[i].lease_key)) {
-                       break;
-               }
-       }
-       if (i == d->num_leases) {
-               DEBUG(10, ("lease not found\n"));
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       l = &d->leases[i];
-
-       if (!l->breaking) {
-               DEBUG(1, ("Attempt to break from %d to %d - but we're not in breaking state\n",
-                          (int)l->current_state, (int)new_lease_state));
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-
-       /*
-        * Can't upgrade anything: l->breaking_to_requested (and l->current_state)
-        * must be a strict bitwise superset of new_lease_state
-        */
-       if ((new_lease_state & l->breaking_to_requested) != new_lease_state) {
-               DEBUG(1, ("Attempt to upgrade from %d to %d - expected %d\n",
-                          (int)l->current_state, (int)new_lease_state,
-                          (int)l->breaking_to_requested));
-               return NT_STATUS_REQUEST_NOT_ACCEPTED;
-       }
-
-       if (l->current_state != new_lease_state) {
-               l->current_state = new_lease_state;
-               d->modified = true;
-       }
-
-       if ((new_lease_state & ~l->breaking_to_required) != 0) {
-               DEBUG(5, ("lease state %d not fully broken from %d to %d\n",
-                          (int)new_lease_state,
-                          (int)l->current_state,
-                          (int)l->breaking_to_required));
-               l->breaking_to_requested = l->breaking_to_required;
-               if (l->current_state & (~SMB2_LEASE_READ)) {
-                       /*
-                        * Here we break in steps, as windows does
-                        * see the breaking3 and v2_breaking3 tests.
-                        */
-                       l->breaking_to_requested |= SMB2_LEASE_READ;
-               }
-               d->modified = true;
-               *_l = l;
-               return NT_STATUS_OPLOCK_BREAK_IN_PROGRESS;
-       }
-
-       DEBUG(10, ("breaking from %d to %d - expected %d\n",
-                  (int)l->current_state, (int)new_lease_state,
-                  (int)l->breaking_to_requested));
-
-       l->breaking_to_requested = 0;
-       l->breaking_to_required = 0;
-       l->breaking = false;
-
-       d->modified = true;
-
-       return NT_STATUS_OK;
-}
-
 /****************************************************************************
  Adds a delete on close token.
 ****************************************************************************/