* 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);
}
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;
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;
}
}
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];
{
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)));
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;
}
}
-bool set_share_mode(struct share_mode_lock *lck, struct files_struct *fsp,
- uid_t uid, uint64_t mid, uint16_t op_type,
- uint32_t lease_idx)
+bool set_share_mode(struct share_mode_lock *lck,
+ struct files_struct *fsp,
+ uid_t uid,
+ uint64_t mid,
+ uint16_t op_type,
+ const struct GUID *client_guid,
+ const struct smb2_lease_key *lease_key)
{
struct share_mode_data *d = lck->data;
struct share_mode_entry *tmp, *e;
- if ((lease_idx != UINT32_MAX) &&
- (lease_idx >= d->num_leases)) {
- return false;
- }
-
tmp = talloc_realloc(d, d->share_modes, struct share_mode_entry,
d->num_share_modes+1);
if (tmp == NULL) {
e->access_mask = fsp->access_mask;
e->op_mid = mid;
e->op_type = op_type;
- e->lease_idx = lease_idx;
+
+ if (op_type == LEASE_OPLOCK) {
+ uint32_t i;
+
+ e->client_guid = *client_guid;
+ e->lease_key = *lease_key;
+
+ /*
+ * Need to set lease_idx. This is essentially
+ * find_share_mode_lease(), but that will go away
+ * soon. So don't add the dependency here.
+ */
+
+ for (i=0; i<d->num_leases; i++) {
+ struct share_mode_lease *l = &d->leases[i];
+
+ if (smb2_lease_equal(client_guid,
+ lease_key,
+ &l->client_guid,
+ &l->lease_key)) {
+ break;
+ }
+ }
+
+ if (i == d->num_leases) {
+ DBG_WARNING("lease not found\n");
+ d->num_share_modes -= 1;
+ return false;
+ }
+
+ e->lease_idx = i;
+ } else {
+ e->lease_idx = UINT32_MAX;
+ }
+
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;
}
/*******************************************************************
- 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)
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.
****************************************************************************/