}
DEBUG(10,("strict_lock_default: flavour = %s brl start=%.0f "
- "len=%.0f %s for fnum %d file %s\n",
+ "len=%.0f %s for fnum %llu file %s\n",
lock_flav_name(plock->lock_flav),
(double)plock->start, (double)plock->size,
ret ? "unlocked" : "locked",
- plock->fnum, fsp_str_dbg(fsp)));
+ (unsigned long long)plock->fnum, fsp_str_dbg(fsp)));
return ret;
}
/* NOTE! 0 byte long ranges ARE allowed and should be stored */
DEBUG(10,("do_lock: lock flavour %s lock type %s start=%.0f len=%.0f "
- "blocking_lock=%s requested for fnum %d file %s\n",
+ "blocking_lock=%s requested for %s file %s\n",
lock_flav_name(lock_flav), lock_type_name(lock_type),
(double)offset, (double)count, blocking_lock ? "true" :
- "false", fsp->fnum, fsp_str_dbg(fsp)));
+ "false", fsp_fnum_dbg(fsp), fsp_str_dbg(fsp)));
br_lck = brl_get_locks(talloc_tos(), fsp);
if (!br_lck) {
return NT_STATUS_OK;
}
- DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for fnum %d file %s\n",
- (double)offset, (double)count, fsp->fnum,
+ DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for %s file %s\n",
+ (double)offset, (double)count, fsp_fnum_dbg(fsp),
fsp_str_dbg(fsp)));
br_lck = brl_get_locks(talloc_tos(), fsp);
return NT_STATUS_DOS(ERRDOS, ERRcancelviolation);
}
- DEBUG(10,("do_lock_cancel: cancel start=%.0f len=%.0f requested for fnum %d file %s\n",
- (double)offset, (double)count, fsp->fnum,
+ DEBUG(10,("do_lock_cancel: cancel start=%.0f len=%.0f requested for %s file %s\n",
+ (double)offset, (double)count, fsp_fnum_dbg(fsp),
fsp_str_dbg(fsp)));
br_lck = brl_get_locks(talloc_tos(), fsp);
return;
}
- /* If we have not outstanding locks or pending
+ /* If we have no outstanding locks or pending
* locks then we don't need to look in the lock db.
*/
int i;
bool strip_two_chars = false;
bool has_stream = smb_fname_dst->stream_name != NULL;
+ struct server_id self_pid = messaging_server_id(msg_ctx);
DEBUG(10, ("rename_share_filename: servicepath %s newname %s\n",
servicepath, smb_fname_dst->base_name));
se->name_hash = new_name_hash;
/* But not to ourselves... */
- if (procid_is_me(&se->pid)) {
+ if (serverid_equal(&se->pid, &self_pid)) {
+ continue;
+ }
+
+ if (share_mode_stale_pid(d, i)) {
continue;
}
{
int num_props = 0;
+ if (e->stale) {
+ return false;
+ }
+
num_props += ((e->op_type == NO_OPLOCK) ? 1 : 0);
num_props += (EXCLUSIVE_OPLOCK_TYPE(e->op_type) ? 1 : 0);
num_props += (LEVEL_II_OPLOCK_TYPE(e->op_type) ? 1 : 0);
- SMB_ASSERT(num_props <= 1);
+ if ((num_props > 1) && serverid_exists(&e->pid)) {
+ smb_panic("Invalid share mode entry");
+ }
return (num_props != 0);
}
-bool is_deferred_open_entry(const struct share_mode_entry *e)
+/*
+ * In case d->share_modes[i] conflicts with something or otherwise is
+ * being used, we need to make sure the corresponding process still
+ * exists.
+ */
+bool share_mode_stale_pid(struct share_mode_data *d, uint32_t idx)
{
- return (e->op_type == DEFERRED_OPEN_ENTRY);
+ 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));
+ return false;
+ }
+ e = &d->share_modes[idx];
+ if (e->stale) {
+ /*
+ * Checked before
+ */
+ return true;
+ }
+ if (serverid_exists(&e->pid)) {
+ DEBUG(10, ("PID %s (index %u out of %u) still exists\n",
+ procid_str_static(&e->pid), idx,
+ (unsigned)d->num_share_modes));
+ return false;
+ }
+ DEBUG(10, ("PID %s (index %u out of %u) does not exist anymore\n",
+ procid_str_static(&e->pid), idx,
+ (unsigned)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;
+
+ for (i=0; i<d->num_share_modes; i++) {
+ if (d->share_modes[i].stale) {
+ num_stale += 1;
+ }
+ }
+
+ if (num_stale == d->num_share_modes) {
+ /*
+ * No non-stale share mode found
+ */
+ TALLOC_FREE(d->delete_tokens);
+ d->num_delete_tokens = 0;
+ }
+ }
+
+ d->modified = true;
+ return true;
}
/*******************************************************************
e->name_hash = fsp->name_hash;
}
-static void fill_deferred_open_entry(struct share_mode_entry *e,
- const struct timeval request_time,
- struct file_id id,
- struct server_id pid,
- uint64_t mid)
-{
- ZERO_STRUCTP(e);
- e->pid = pid;
- e->op_mid = mid;
- e->op_type = DEFERRED_OPEN_ENTRY;
- e->time.tv_sec = request_time.tv_sec;
- e->time.tv_usec = request_time.tv_usec;
- e->id = id;
- e->uid = (uint32)-1;
- e->flags = 0;
-}
-
-static void add_share_mode_entry(struct share_mode_data *d,
+static bool add_share_mode_entry(struct share_mode_data *d,
const struct share_mode_entry *entry)
{
- ADD_TO_ARRAY(d, struct share_mode_entry, *entry,
- &d->share_modes, &d->num_share_modes);
- d->modified = True;
+ struct share_mode_entry *tmp;
+
+ tmp = talloc_realloc(d, d->share_modes, struct share_mode_entry,
+ d->num_share_modes+1);
+ if (tmp == NULL) {
+ return false;
+ }
+ d->share_modes = tmp;
+ d->share_modes[d->num_share_modes] = *entry;
+ d->num_share_modes += 1;
+ d->modified = true;
+ return true;
}
-void set_share_mode(struct share_mode_lock *lck, files_struct *fsp,
+bool set_share_mode(struct share_mode_lock *lck, files_struct *fsp,
uid_t uid, uint64_t mid, uint16 op_type)
{
struct share_mode_entry entry;
fill_share_mode_entry(&entry, fsp, uid, mid, op_type);
- add_share_mode_entry(lck->data, &entry);
+ return add_share_mode_entry(lck->data, &entry);
}
-void add_deferred_open(struct share_mode_lock *lck, uint64_t mid,
- struct timeval request_time,
- struct server_id pid, struct file_id id)
-{
- struct share_mode_entry entry;
- fill_deferred_open_entry(&entry, request_time, id, pid, mid);
- add_share_mode_entry(lck->data, &entry);
-}
-
-/*******************************************************************
- Check if two share mode entries are identical, ignoring oplock
- and mid info and desired_access. (Removed paranoia test - it's
- not automatically a logic error if they are identical. JRA.)
-********************************************************************/
-
-static bool share_modes_identical(struct share_mode_entry *e1,
- struct share_mode_entry *e2)
-{
- /* We used to check for e1->share_access == e2->share_access here
- as well as the other fields but 2 different DOS or FCB opens
- sharing the same share mode entry may validly differ in
- fsp->share_access field. */
-
- return (procid_equal(&e1->pid, &e2->pid) &&
- file_id_equal(&e1->id, &e2->id) &&
- e1->share_file_id == e2->share_file_id );
-}
-
-static bool deferred_open_identical(struct share_mode_entry *e1,
- struct share_mode_entry *e2)
-{
- return (procid_equal(&e1->pid, &e2->pid) &&
- (e1->op_mid == e2->op_mid) &&
- file_id_equal(&e1->id, &e2->id));
-}
-
-static struct share_mode_entry *find_share_mode_entry(struct share_mode_data *d,
- struct share_mode_entry *entry)
+static struct share_mode_entry *find_share_mode_entry(
+ struct share_mode_lock *lck, files_struct *fsp)
{
+ struct share_mode_data *d = lck->data;
+ struct server_id pid;
int i;
+ pid = messaging_server_id(fsp->conn->sconn->msg_ctx);
+
for (i=0; i<d->num_share_modes; i++) {
struct share_mode_entry *e = &d->share_modes[i];
- if (is_valid_share_mode_entry(entry) &&
- is_valid_share_mode_entry(e) &&
- share_modes_identical(e, entry)) {
- return e;
+
+ if (!is_valid_share_mode_entry(e)) {
+ continue;
}
- if (is_deferred_open_entry(entry) &&
- is_deferred_open_entry(e) &&
- deferred_open_identical(e, entry)) {
- return e;
+ if (!serverid_equal(&pid, &e->pid)) {
+ continue;
+ }
+ if (!file_id_equal(&fsp->file_id, &e->id)) {
+ continue;
+ }
+ if (fsp->fh->gen_id != e->share_file_id) {
+ continue;
}
+ return e;
}
return NULL;
}
bool del_share_mode(struct share_mode_lock *lck, files_struct *fsp)
{
- struct share_mode_entry entry, *e;
-
- /* Don't care about the pid owner being correct here - just a search. */
- fill_share_mode_entry(&entry, fsp, (uid_t)-1, 0, NO_OPLOCK);
+ struct share_mode_entry *e;
- e = find_share_mode_entry(lck->data, &entry);
+ e = find_share_mode_entry(lck, fsp);
if (e == NULL) {
return False;
}
return True;
}
-void del_deferred_open_entry(struct share_mode_lock *lck, uint64_t mid,
- struct server_id pid)
+bool mark_share_mode_disconnected(struct share_mode_lock *lck,
+ struct files_struct *fsp)
{
- struct share_mode_entry entry, *e;
+ struct share_mode_entry *e;
- fill_deferred_open_entry(&entry, timeval_zero(),
- lck->data->id, pid, mid);
+ if (lck->data->num_share_modes != 1) {
+ return false;
+ }
- e = find_share_mode_entry(lck->data, &entry);
+ if (fsp->op == NULL) {
+ return false;
+ }
+ if (!fsp->op->global->durable) {
+ return false;
+ }
+
+ e = find_share_mode_entry(lck, fsp);
if (e == NULL) {
- return;
+ return false;
}
- *e = lck->data->share_modes[lck->data->num_share_modes-1];
- lck->data->num_share_modes -= 1;
- lck->data->modified = True;
+
+ DEBUG(10, ("Marking share mode entry disconnected for durable handle\n"));
+
+ server_id_set_disconnected(&e->pid);
+
+ /*
+ * On reopen the caller needs to check that
+ * the client comes with the correct handle.
+ */
+ e->share_file_id = fsp->op->global->open_persistent_id;
+
+ lck->data->modified = true;
+ return true;
}
/*******************************************************************
bool remove_share_oplock(struct share_mode_lock *lck, files_struct *fsp)
{
- struct share_mode_entry entry, *e;
+ struct share_mode_entry *e;
- /* Don't care about the pid owner being correct here - just a search. */
- fill_share_mode_entry(&entry, fsp, (uid_t)-1, 0, NO_OPLOCK);
-
- e = find_share_mode_entry(lck->data, &entry);
+ e = find_share_mode_entry(lck, fsp);
if (e == NULL) {
return False;
}
bool downgrade_share_oplock(struct share_mode_lock *lck, files_struct *fsp)
{
- struct share_mode_entry entry, *e;
-
- /* Don't care about the pid owner being correct here - just a search. */
- fill_share_mode_entry(&entry, fsp, (uid_t)-1, 0, NO_OPLOCK);
+ struct share_mode_entry *e;
- e = find_share_mode_entry(lck->data, &entry);
+ e = find_share_mode_entry(lck, fsp);
if (e == NULL) {
return False;
}
return True;
}
-/*************************************************************************
- Return a talloced copy of a struct security_unix_token. NULL on fail.
- (Should this be in locking.c.... ?).
-*************************************************************************/
-
-static struct security_unix_token *copy_unix_token(TALLOC_CTX *ctx, const struct security_unix_token *tok)
-{
- struct security_unix_token *cpy;
-
- cpy = talloc(ctx, struct security_unix_token);
- if (!cpy) {
- return NULL;
- }
-
- cpy->uid = tok->uid;
- cpy->gid = tok->gid;
- cpy->ngroups = tok->ngroups;
- if (tok->ngroups) {
- /* Make this a talloc child of cpy. */
- cpy->groups = (gid_t *)talloc_memdup(
- cpy, tok->groups, tok->ngroups * sizeof(gid_t));
- if (!cpy->groups) {
- TALLOC_FREE(cpy);
- return NULL;
- }
- }
- return cpy;
-}
-
/****************************************************************************
Adds a delete on close token.
****************************************************************************/
*dt = d->delete_tokens[
d->num_delete_tokens-1];
d->num_delete_tokens -= 1;
- return;
+ } else {
+ /* Replace this token with the
+ given tok. */
+ TALLOC_FREE(dt->delete_nt_token);
+ dt->delete_nt_token = dup_nt_token(dt, nt_tok);
+ SMB_ASSERT(dt->delete_nt_token != NULL);
+ TALLOC_FREE(dt->delete_token);
+ dt->delete_token = copy_unix_token(dt, tok);
+ SMB_ASSERT(dt->delete_token != NULL);
}
- /* Replace this token with the
- given tok. */
- TALLOC_FREE(dt->delete_nt_token);
- dt->delete_nt_token = dup_nt_token(dt, nt_tok);
- SMB_ASSERT(dt->delete_nt_token != NULL);
- TALLOC_FREE(dt->delete_token);
- dt->delete_token = copy_unix_token(dt, tok);
- SMB_ASSERT(dt->delete_token != NULL);
+ return;
}
}
struct share_mode_lock *lck;
DEBUG(10,("set_delete_on_close: %s delete on close flag for "
- "fnum = %d, file %s\n",
- delete_on_close ? "Adding" : "Removing", fsp->fnum,
+ "%s, file %s\n",
+ delete_on_close ? "Adding" : "Removing", fsp_fnum_dbg(fsp),
fsp_str_dbg(fsp)));
lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
return True;
}
+static struct delete_token *find_delete_on_close_token(
+ struct share_mode_data *d, uint32_t name_hash)
+{
+ uint32_t i;
+
+ DEBUG(10, ("find_delete_on_close_token: name_hash = 0x%x\n",
+ (unsigned int)name_hash));
+
+ for (i=0; i<d->num_delete_tokens; i++) {
+ struct delete_token *dt = &d->delete_tokens[i];
+
+ DEBUG(10, ("find__delete_on_close_token: dt->name_hash = 0x%x\n",
+ (unsigned int)dt->name_hash ));
+ if (dt->name_hash == name_hash) {
+ return dt;
+ }
+ }
+ return NULL;
+}
+
/****************************************************************************
Return the NT token and UNIX token if there's a match. Return true if
found, false if not.
const struct security_token **pp_nt_tok,
const struct security_unix_token **pp_tok)
{
- int i;
+ struct delete_token *dt;
- DEBUG(10,("get_delete_on_close_token: name_hash = 0x%x\n",
- (unsigned int)name_hash ));
-
- for (i=0; i<lck->data->num_delete_tokens; i++) {
- struct delete_token *dt = &lck->data->delete_tokens[i];
- DEBUG(10,("get_delete_on_close_token: dtl->name_hash = 0x%x\n",
- (unsigned int)dt->name_hash ));
- if (dt->name_hash == name_hash) {
- if (pp_nt_tok) {
- *pp_nt_tok = dt->delete_nt_token;
- }
- if (pp_tok) {
- *pp_tok = dt->delete_token;
- }
- return true;
- }
+ dt = find_delete_on_close_token(lck->data, name_hash);
+ if (dt == NULL) {
+ return false;
}
- return false;
+ *pp_nt_tok = dt->delete_nt_token;
+ *pp_tok = dt->delete_token;
+ return true;
}
bool is_delete_on_close_set(struct share_mode_lock *lck, uint32_t name_hash)
{
- return get_delete_on_close_token(lck, name_hash, NULL, NULL);
+ return find_delete_on_close_token(lck->data, name_hash) != NULL;
}
bool set_sticky_write_time(struct file_id fileid, struct timespec write_time)