TODO smbd: allow durable opens together with stat opens
authorStefan Metzmacher <metze@samba.org>
Thu, 16 Aug 2018 08:14:20 +0000 (10:14 +0200)
committerStefan Metzmacher <metze@samba.org>
Thu, 16 Aug 2018 08:14:20 +0000 (10:14 +0200)
TODO: explicit tests

source3/locking/locking.c
source3/locking/proto.h
source3/smbd/durable.c

index 208f7e2081d0fee4a76c2c8920739a226fe7b16c..833734cd37fa0a4c3a0ad1eec2ab12b4c0ef44bf 100644 (file)
@@ -876,6 +876,29 @@ struct share_mode_entry *find_share_mode_entry(
        return NULL;
 }
 
+struct share_mode_entry *find_share_mode_entry_durable(
+       struct share_mode_lock *lck, uint64_t persistent_fid)
+{
+       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];
+
+               if (!server_id_is_disconnected(&e->pid)) {
+                       continue;
+               }
+               if (!is_valid_share_mode_entry(e)) {
+                       continue;
+               }
+               if (persistent_fid != e->share_file_id) {
+                       continue;
+               }
+               return e;
+       }
+       return NULL;
+}
+
 /*******************************************************************
  Del the share mode of a file for this process. Return the number of
  entries left.
@@ -901,10 +924,6 @@ bool mark_share_mode_disconnected(struct share_mode_lock *lck,
 {
        struct share_mode_entry *e;
 
-       if (lck->data->num_share_modes != 1) {
-               return false;
-       }
-
        if (fsp->op == NULL) {
                return false;
        }
index b615a4ae6d0b41ea9f917ae41d75fe486307b5dc..1e8ae049704ea22103158c60342457abd85a1dc0 100644 (file)
@@ -178,6 +178,8 @@ bool set_share_mode(struct share_mode_lock *lck, struct files_struct *fsp,
                    uint32_t lease_idx);
 struct share_mode_entry *find_share_mode_entry(struct share_mode_lock *lck,
                                               files_struct *fsp);
+struct share_mode_entry *find_share_mode_entry_durable(
+       struct share_mode_lock *lck, uint64_t persistent_fid);
 void remove_stale_share_mode_entries(struct share_mode_data *d);
 bool del_share_mode(struct share_mode_lock *lck, files_struct *fsp);
 bool mark_share_mode_disconnected(struct share_mode_lock *lck,
index 80392e2c6dbbdd30eefe2404e437172265de209d..2a309a2aedd2152df1fa035e1e0a937735ede2c8 100644 (file)
@@ -617,33 +617,10 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn,
                return NT_STATUS_INTERNAL_DB_ERROR;
        }
 
-       if (lck->data->num_share_modes > 1) {
-               /*
-                * It can't be durable if there is more than one handle
-                * on the file.
-                */
-               DEBUG(5, ("vfs_default_durable_reconnect: more than one "
-                         "share-mode entry - can not be durable\n"));
-               TALLOC_FREE(lck);
-               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
-       }
-
-       e = &lck->data->share_modes[0];
-
-       if (!server_id_is_disconnected(&e->pid)) {
-               DEBUG(5, ("vfs_default_durable_reconnect: denying durable "
-                         "reconnect for handle that was not marked "
-                         "disconnected (e.g. smbd or cluster node died)\n"));
-               TALLOC_FREE(lck);
-               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
-       }
-
-       if (e->share_file_id != op->global->open_persistent_id) {
+       e = find_share_mode_entry_durable(lck, op->global->open_persistent_id);
+       if (e == NULL) {
                DEBUG(5, ("vfs_default_durable_reconnect: denying durable "
-                         "share_file_id changed %llu != %llu"
-                         "(e.g. another client had opened the file)\n",
-                         (unsigned long long)e->share_file_id,
-                         (unsigned long long)op->global->open_persistent_id));
+                         "reconnect for handle - share mode not found\n"));
                TALLOC_FREE(lck);
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
        }