smbd: Add share_mode_forall_entries()
[samba.git] / source3 / locking / locking.c
index 72235113fbb981737a57fa64928e730527f047f3..e8820ee03567effa13fa66f5ff993ad5ab793ff7 100644 (file)
@@ -713,6 +713,30 @@ static void remove_share_mode_lease(struct share_mode_data *d,
        remove_lease_if_stale(d, &e->client_guid, &e->lease_key);
 }
 
+bool share_entry_stale_pid(struct share_mode_entry *e)
+{
+       struct server_id_buf buf;
+       bool exists;
+
+       if (e->stale) {
+               return true;
+       }
+
+       exists = serverid_exists(&e->pid);
+       if (exists) {
+               DBG_DEBUG("PID %s still exists\n",
+                         server_id_str_buf(e->pid, &buf));
+               return false;
+       }
+
+       DBG_DEBUG("PID %s does not exist anymore\n",
+                 server_id_str_buf(e->pid, &buf));
+
+       e->stale = true;
+
+       return true;
+}
+
 /*
  * In case d->share_modes[i] conflicts with something or otherwise is
  * being used, we need to make sure the corresponding process still
@@ -720,8 +744,8 @@ static void remove_share_mode_lease(struct share_mode_data *d,
  */
 bool share_mode_stale_pid(struct share_mode_data *d, uint32_t idx)
 {
-       struct server_id_buf tmp;
        struct share_mode_entry *e;
+       bool stale;
 
        if (idx > d->num_share_modes) {
                DBG_WARNING("Asking for index %"PRIu32", "
@@ -731,27 +755,12 @@ bool share_mode_stale_pid(struct share_mode_data *d, uint32_t idx)
                return false;
        }
        e = &d->share_modes[idx];
-       if (e->stale) {
-               /*
-                * Checked before
-                */
-               return true;
-       }
-       if (serverid_exists(&e->pid)) {
-               DBG_DEBUG("PID %s (index %"PRIu32" out of %"PRIu32") "
-                         "still exists\n",
-                         server_id_str_buf(e->pid, &tmp),
-                         idx,
-                         d->num_share_modes);
+
+       stale = share_entry_stale_pid(e);
+       if (!stale) {
                return false;
        }
-       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;
+       d->modified = true;
 
        if (d->num_delete_tokens != 0) {
                uint32_t i;
@@ -1252,6 +1261,53 @@ bool file_has_open_streams(files_struct *fsp)
        return false;
 }
 
+bool share_mode_forall_entries(
+       struct share_mode_lock *lck,
+       bool (*fn)(struct share_mode_entry *e,
+                  bool *modified,
+                  void *private_data),
+       void *private_data)
+{
+       struct share_mode_data *d = lck->data;
+       uint32_t i;
+
+       for (i=0; i<d->num_share_modes; i++) {
+               struct share_mode_entry *e = &d->share_modes[i];
+               struct server_id pid = e->pid;
+               uint64_t share_file_id = e->share_file_id;
+               bool ok, stop;
+               bool modified = false;
+
+               ok = is_valid_share_mode_entry(e);
+               if (!ok) {
+                       continue;
+               }
+
+               stop = fn(e, &modified, private_data);
+
+               if (modified || e->stale) {
+                       d->modified = true;
+               }
+
+               if (modified) {
+                       /*
+                        * In a later commit we will sort the share
+                        * mode array keyed by pid and
+                        * share_file_id. Make sure that from within
+                        * this routine those values don't change.
+                        */
+                       SMB_ASSERT(server_id_equal(&pid, &e->pid));
+                       SMB_ASSERT(share_file_id == e->share_file_id);
+               }
+
+               if (stop) {
+                       return true;
+               }
+       }
+
+       return true;
+}
+
 /*
  * Walk share mode entries, looking at every lease only once
  */