The branch, master has been updated
       via  3fef8e2 selftest/Samba3: don't explicitly set 'server max protocol'
       via  196b7f3 docs-xml: change "server max protocol" to "SMB3"
       via  1c9c5c1 s3:param: change "server max protocol" to "SMB3"
       via  9576638 s3:smbd: add basic support for durable handle v2 request 
and reconnect
       via  267b976 s3:smbd: add basic support for durable handle request and 
reconnect
       via  f935ebd s3:smbd: initial durable handle support: special treatment 
of durable handles in close
       via  35260ae s3:vfs: add durable VFS operations
       via  eb1a05f s3:smbd: add disconnected checks to the open code.
       via  42afa59 s3:smbd: also close durable file handles in a tdis
       via  f0a5b79 s3:locking: add brl_mark_disconnected() and 
brl_reconnect_disconnected()
       via  9a81f8e s3:locking: add mark_share_mode_disconnected()
       via  bc29605 s3:smbXsrv_open: add smb2srv_open_recreate() to support 
durable handles
       via  5e63494 s3:smbXsrv.idl: add properties for durable handles to 
smbXsrv_open_global0
      from  c853b68 s3:quota: don't add the string '"' into the argument list

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 3fef8e207c92c7ef9274669cb4cb8b29c2164558
Author: Stefan Metzmacher <me...@samba.org>
Date:   Fri May 18 10:43:18 2012 +0200

    selftest/Samba3: don't explicitly set 'server max protocol'
    
    metze
    
    Autobuild-User(master): Stefan Metzmacher <me...@samba.org>
    Autobuild-Date(master): Sat Sep  8 05:15:00 CEST 2012 on sn-devel-104

commit 196b7f336e93048c2b55c20a2cdd7c903633d174
Author: Stefan Metzmacher <me...@samba.org>
Date:   Sun Jun 3 23:09:33 2012 +0200

    docs-xml: change "server max protocol" to "SMB3"
    
    metze

commit 1c9c5c12761c2a18e7584fce3f40346321c021f6
Author: Stefan Metzmacher <me...@samba.org>
Date:   Sun Jun 3 23:04:44 2012 +0200

    s3:param: change "server max protocol" to "SMB3"
    
    metze

commit 9576638dbacd24183b8715febf50d8be86aa950a
Author: Michael Adam <ob...@samba.org>
Date:   Fri Jun 15 13:37:26 2012 +0200

    s3:smbd: add basic support for durable handle v2 request and reconnect
    
    This does not yet cover persistent handle support which is also
    negotiated through these create request blobs.
    
    Pair-Programmed-With: Stefan Metzmacher <me...@samba.org>

commit 267b976d432f3c21cf1d8352183cd4b308fe726d
Author: Michael Adam <ob...@samba.org>
Date:   Fri Jun 8 17:54:19 2012 +0200

    s3:smbd: add basic support for durable handle request and reconnect
    
    Pair-Programmed-With: Stefan Metzmacher <me...@samba.org>
    Pair-Programmed-With: Volker Lendecke <v...@samba.org>

commit f935ebdf7a2fd084930b33ba8d208d699b37300c
Author: Michael Adam <ob...@samba.org>
Date:   Fri Aug 3 16:47:57 2012 +0200

    s3:smbd: initial durable handle support: special treatment of durable 
handles in close
    
    Pair-Programmed-With: Stefan Metzmacher <me...@samba.org>

commit 35260ae89e2970712e2a141cd034b513076fc1ed
Author: Michael Adam <ob...@samba.org>
Date:   Tue Sep 4 18:04:11 2012 +0200

    s3:vfs: add durable VFS operations
    
    This allows a VFS module to implement durable handles in different ways.
    
    Pair-Programmed-With: Stefan Metzmacher <me...@samba.org>

commit eb1a05f783721247e9e01f4039f36c3d69b2dca7
Author: Stefan Metzmacher <me...@samba.org>
Date:   Sat Aug 4 15:30:11 2012 +0200

    s3:smbd: add disconnected checks to the open code.
    
    (delay_for_batch_oplocks, open_mode_check, and delay_for_exclusive_oplocks)
    
    Pair-Programmed-With: Michael Adam <ob...@samba.org>

commit 42afa596d5e58875944c5429fac4866a5614ebca
Author: Michael Adam <ob...@samba.org>
Date:   Fri Aug 3 16:38:38 2012 +0200

    s3:smbd: also close durable file handles in a tdis
    
    Pair-Programmed-With: Stefan Metzmacher <me...@samba.org>

commit f0a5b791ae4e64e42270edad7a961aa046efbaac
Author: Stefan Metzmacher <me...@samba.org>
Date:   Sat Jun 30 21:48:43 2012 +0200

    s3:locking: add brl_mark_disconnected() and brl_reconnect_disconnected()
    
    Pair-Programmed-With: Michael Adam <ob...@samba.org>

commit 9a81f8ee1713317262f3fc773dae38cb51816149
Author: Stefan Metzmacher <me...@samba.org>
Date:   Fri Aug 3 16:31:32 2012 +0200

    s3:locking: add mark_share_mode_disconnected()
    
    Pair-Programmed-With: Michael Adam <ob...@samba.org>

commit bc296053cba15869d3417f6089bd2e7e96d42c09
Author: Stefan Metzmacher <me...@samba.org>
Date:   Mon Jun 18 12:46:15 2012 +0200

    s3:smbXsrv_open: add smb2srv_open_recreate() to support durable handles
    
    metze

commit 5e63494508ade5da00ad5ab9db139efe03d39c2e
Author: Stefan Metzmacher <me...@samba.org>
Date:   Fri Jun 29 09:34:56 2012 +0200

    s3:smbXsrv.idl: add properties for durable handles to smbXsrv_open_global0
    
    Pair-Programmed-With: Michael Adam <ob...@samba.org>
    
    metze

-----------------------------------------------------------------------

Summary of changes:
 docs-xml/smbdotconf/protocol/servermaxprotocol.xml |    2 +-
 selftest/target/Samba3.pm                          |    1 -
 source3/include/vfs.h                              |   35 ++
 source3/include/vfs_macros.h                       |   25 ++
 source3/librpc/idl/smbXsrv.idl                     |    8 +
 source3/locking/brlock.c                           |  125 +++++++
 source3/locking/locking.c                          |   38 ++
 source3/locking/proto.h                            |    4 +
 source3/modules/vfs_default.c                      |   35 ++-
 source3/param/loadparm.c                           |    2 +-
 source3/smbd/close.c                               |   44 +++
 source3/smbd/files.c                               |   11 +-
 source3/smbd/globals.h                             |    6 +
 source3/smbd/open.c                                |   31 ++
 source3/smbd/smb2_create.c                         |  376 +++++++++++++++++---
 source3/smbd/smbXsrv_open.c                        |  205 +++++++++++-
 source3/smbd/vfs.c                                 |   34 ++
 17 files changed, 929 insertions(+), 53 deletions(-)


Changeset truncated at 500 lines:

diff --git a/docs-xml/smbdotconf/protocol/servermaxprotocol.xml 
b/docs-xml/smbdotconf/protocol/servermaxprotocol.xml
index 68f2579..57e82d1 100644
--- a/docs-xml/smbdotconf/protocol/servermaxprotocol.xml
+++ b/docs-xml/smbdotconf/protocol/servermaxprotocol.xml
@@ -73,6 +73,6 @@
 <related>server min protocol</related>
 <synonym>max protocol</synonym>
 
-<value type="default">SMB2</value>
+<value type="default">SMB3</value>
 <value type="example">LANMAN1</value>
 </samba:parameter>
diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm
index cb11827..943e922 100755
--- a/selftest/target/Samba3.pm
+++ b/selftest/target/Samba3.pm
@@ -901,7 +901,6 @@ sub provision($$$$$$)
 
 #      min receivefile size = 4000
 
-       server max protocol = SMB3
        read only = no
        server signing = auto
 
diff --git a/source3/include/vfs.h b/source3/include/vfs.h
index 45895e7..3e4eefe 100644
--- a/source3/include/vfs.h
+++ b/source3/include/vfs.h
@@ -142,6 +142,7 @@
 /* Leave at 29 - not yet released. move to plain off_t - abartlet */
 /* Leave at 29 - not yet released. Remove sys_acl functions other than set and 
get - abartlet */
 /* Leave at 29 - not yet released. Added backup_intent bool to files_struct - 
JRA */
+/* Leave at 29 - not yet released. Add durable handle functions - metze/obnox 
*/
 #define SMB_VFS_INTERFACE_VERSION 29
 
 /*
@@ -712,6 +713,24 @@ struct vfs_fn_pointers {
                           SMB_STRUCT_STAT *sbuf);
        int (*set_offline_fn)(struct vfs_handle_struct *handle,
                           const struct smb_filename *fname);
+
+       /* durable handle operations */
+       NTSTATUS (*durable_cookie_fn)(struct vfs_handle_struct *handle,
+                                     struct files_struct *fsp,
+                                     TALLOC_CTX *mem_ctx,
+                                     DATA_BLOB *cookie);
+       NTSTATUS (*durable_disconnect_fn)(struct vfs_handle_struct *handle,
+                                         struct files_struct *fsp,
+                                         const DATA_BLOB old_cookie,
+                                         TALLOC_CTX *mem_ctx,
+                                         DATA_BLOB *new_cookie);
+       NTSTATUS (*durable_reconnect_fn)(struct vfs_handle_struct *handle,
+                                        struct smb_request *smb1req,
+                                        struct smbXsrv_open *op,
+                                        const DATA_BLOB old_cookie,
+                                        TALLOC_CTX *mem_ctx,
+                                        struct files_struct **fsp,
+                                        DATA_BLOB *new_cookie);
 };
 
 /*
@@ -1108,6 +1127,22 @@ bool smb_vfs_call_is_offline(struct vfs_handle_struct 
*handle,
                             SMB_STRUCT_STAT *sbuf);
 int smb_vfs_call_set_offline(struct vfs_handle_struct *handle,
                             const struct smb_filename *fname);
+NTSTATUS smb_vfs_call_durable_cookie(struct vfs_handle_struct *handle,
+                                    struct files_struct *fsp,
+                                    TALLOC_CTX *mem_ctx,
+                                    DATA_BLOB *cookie);
+NTSTATUS smb_vfs_call_durable_disconnect(struct vfs_handle_struct *handle,
+                                        struct files_struct *fsp,
+                                        const DATA_BLOB old_cookie,
+                                        TALLOC_CTX *mem_ctx,
+                                        DATA_BLOB *new_cookie);
+NTSTATUS smb_vfs_call_durable_reconnect(struct vfs_handle_struct *handle,
+                                       struct smb_request *smb1req,
+                                       struct smbXsrv_open *op,
+                                       const DATA_BLOB old_cookie,
+                                       TALLOC_CTX *mem_ctx,
+                                       struct files_struct **fsp,
+                                       DATA_BLOB *new_cookie);
 
 NTSTATUS smb_register_vfs(int version, const char *name,
                          const struct vfs_fn_pointers *fns);
diff --git a/source3/include/vfs_macros.h b/source3/include/vfs_macros.h
index e577e99..f077a6f 100644
--- a/source3/include/vfs_macros.h
+++ b/source3/include/vfs_macros.h
@@ -509,4 +509,29 @@
 #define SMB_VFS_NEXT_SET_OFFLINE(handle,fname) \
        smb_vfs_call_set_offline((handle)->next, (fname))
 
+/* durable handle operations */
+
+#define SMB_VFS_DURABLE_COOKIE(fsp, mem_ctx, cookie) \
+       smb_vfs_call_durable_cookie((fsp)->conn->vfs_handles, \
+                                   (fsp), (mem_ctx), (cookie))
+#define SMB_VFS_NEXT_DURABLE_COOKIE(handle, fsp, mem_ctx, cookie) \
+       smb_vfs_call_durable_cookie(((handle)->next, \
+                                   (fsp), (mem_ctx), (cookie))
+
+#define SMB_VFS_DURABLE_DISCONNECT(fsp, old_cookie, mem_ctx, new_cookie) \
+       smb_vfs_call_durable_disconnect((fsp)->conn->vfs_handles, \
+                                       (fsp), (old_cookie), (mem_ctx), 
(new_cookie))
+#define SMB_VFS_NEXT_DURABLE_DISCONNECT(handle, fsp, old_cookie, mem_ctx, 
new_cookie) \
+       smb_vfs_call_durable_disconnect((handle)->next, \
+                                       (fsp), (old_cookie), (mem_ctx), 
(new_cookie))
+
+#define SMB_VFS_DURABLE_RECONNECT(conn, smb1req, op, old_cookie, mem_ctx, fsp, 
new_cookie) \
+       smb_vfs_call_durable_reconnect((conn)->vfs_handles, \
+                                      (smb1req), (op), (old_cookie), \
+                                      (mem_ctx), (fsp), (new_cookie))
+#define SMB_VFS_NEXT_DURABLE_RECONNECT(handle, smb1req, op, old_cookie, 
mem_ctx, fsp, new_cookie) \
+       smb_vfs_call_durable_reconnect((handle)->next, \
+                                       (smb1req), (op), (old_cookie), \
+                                       (mem_ctx), (fsp), (new_cookie))
+
 #endif /* _VFS_MACROS_H */
diff --git a/source3/librpc/idl/smbXsrv.idl b/source3/librpc/idl/smbXsrv.idl
index 90572e5..2a6d7b3 100644
--- a/source3/librpc/idl/smbXsrv.idl
+++ b/source3/librpc/idl/smbXsrv.idl
@@ -1,5 +1,6 @@
 #include "idl_types.h"
 
+import "misc.idl";
 import "server_id.idl";
 import "security.idl";
 import "auth.idl";
@@ -267,12 +268,19 @@ interface smbXsrv
                hyper                                   open_volatile_id;
                dom_sid                                 open_owner;
                NTTIME                                  open_time;
+               GUID                                    create_guid;
+               GUID                                    client_guid;
+               GUID                                    app_instance_id;
                /*
                 * TODO: for durable/resilient/persistent handles we need more
                 *       things here. See [MS-SMB2] 3.3.1.10 Per Open
                 *
                 * NOTE: this is still version 0, which is not a stable format!
                 */
+               NTTIME                                  disconnect_time;
+               uint32                                  durable_timeout_msec;
+               boolean8                                durable;
+               DATA_BLOB                               backend_cookie;
        } smbXsrv_open_global0;
 
        typedef union {
diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c
index c03e451..b7abaa9 100644
--- a/source3/locking/brlock.c
+++ b/source3/locking/brlock.c
@@ -1522,6 +1522,131 @@ void brl_close_fnum(struct messaging_context *msg_ctx,
        }
 }
 
+bool brl_mark_disconnected(struct files_struct *fsp)
+{
+       uint32_t tid = fsp->conn->cnum;
+       uint64_t smblctx = fsp->op->global->open_persistent_id;
+       uint64_t fnum = fsp->fnum;
+       unsigned int i;
+       struct server_id self = messaging_server_id(fsp->conn->sconn->msg_ctx);
+       struct byte_range_lock *br_lck = NULL;
+
+       if (!fsp->op->global->durable) {
+               return false;
+       }
+
+       if (fsp->current_lock_count == 0) {
+               return true;
+       }
+
+       br_lck = brl_get_locks(talloc_tos(), fsp);
+       if (br_lck == NULL) {
+               return false;
+       }
+
+       for (i=0; i < br_lck->num_locks; i++) {
+               struct lock_struct *lock = &br_lck->lock_data[i];
+
+               /*
+                * as this is a durable handle, we only expect locks
+                * of the current file handle!
+                */
+
+               if (lock->context.smblctx != smblctx) {
+                       TALLOC_FREE(br_lck);
+                       return false;
+               }
+
+               if (lock->context.tid != tid) {
+                       TALLOC_FREE(br_lck);
+                       return false;
+               }
+
+               if (!serverid_equal(&lock->context.pid, &self)) {
+                       TALLOC_FREE(br_lck);
+                       return false;
+               }
+
+               if (lock->fnum != fnum) {
+                       TALLOC_FREE(br_lck);
+                       return false;
+               }
+
+               server_id_set_disconnected(&lock->context.pid);
+               lock->context.tid = TID_FIELD_INVALID;
+               lock->fnum = FNUM_FIELD_INVALID;
+       }
+
+       br_lck->modified = true;
+       TALLOC_FREE(br_lck);
+       return true;
+}
+
+bool brl_reconnect_disconnected(struct files_struct *fsp)
+{
+       uint32_t tid = fsp->conn->cnum;
+       uint64_t smblctx = fsp->op->global->open_persistent_id;
+       uint64_t fnum = fsp->fnum;
+       unsigned int i;
+       struct server_id self = messaging_server_id(fsp->conn->sconn->msg_ctx);
+       struct byte_range_lock *br_lck = NULL;
+
+       if (!fsp->op->global->durable) {
+               return false;
+       }
+
+       /* we want to validate ourself */
+       fsp->lockdb_clean = true;
+
+       br_lck = brl_get_locks(talloc_tos(), fsp);
+       if (br_lck == NULL) {
+               return false;
+       }
+
+       if (br_lck->num_locks == 0) {
+               TALLOC_FREE(br_lck);
+               return true;
+       }
+
+       for (i=0; i < br_lck->num_locks; i++) {
+               struct lock_struct *lock = &br_lck->lock_data[i];
+
+               /*
+                * as this is a durable handle we only expect locks
+                * of the current file handle!
+                */
+
+               if (lock->context.smblctx != smblctx) {
+                       TALLOC_FREE(br_lck);
+                       return false;
+               }
+
+               if (lock->context.tid != TID_FIELD_INVALID) {
+                       TALLOC_FREE(br_lck);
+                       return false;
+               }
+
+               if (!server_id_is_disconnected(&lock->context.pid)) {
+                       TALLOC_FREE(br_lck);
+                       return false;
+               }
+
+               if (lock->fnum != FNUM_FIELD_INVALID) {
+                       TALLOC_FREE(br_lck);
+                       return false;
+               }
+
+               lock->context.pid = self;
+               lock->context.tid = tid;
+               lock->fnum = fnum;
+       }
+
+       fsp->current_lock_count = br_lck->num_locks;
+       br_lck->modified = true;
+       TALLOC_FREE(br_lck);
+       return true;
+}
+
 /****************************************************************************
  Ensure this set of lock entries is valid.
 ****************************************************************************/
diff --git a/source3/locking/locking.c b/source3/locking/locking.c
index d3ab7f3..a7fc50c 100644
--- a/source3/locking/locking.c
+++ b/source3/locking/locking.c
@@ -811,6 +811,44 @@ bool del_share_mode(struct share_mode_lock *lck, 
files_struct *fsp)
        return True;
 }
 
+bool mark_share_mode_disconnected(struct share_mode_lock *lck,
+                                 struct files_struct *fsp)
+{
+       struct share_mode_entry entry, *e;
+
+       if (lck->data->num_share_modes != 1) {
+               return false;
+       }
+
+       if (fsp->op == NULL) {
+               return false;
+       }
+       if (!fsp->op->global->durable) {
+               return false;
+       }
+
+       /* 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);
+       if (e == NULL) {
+               return false;
+       }
+
+       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;
+}
+
 void del_deferred_open_entry(struct share_mode_lock *lck, uint64_t mid,
                             struct server_id pid)
 {
diff --git a/source3/locking/proto.h b/source3/locking/proto.h
index 74cf323..c170c73 100644
--- a/source3/locking/proto.h
+++ b/source3/locking/proto.h
@@ -79,6 +79,8 @@ bool brl_lock_cancel(struct byte_range_lock *br_lck,
                struct blocking_lock_record *blr);
 bool brl_lock_cancel_default(struct byte_range_lock *br_lck,
                struct lock_struct *plock);
+bool brl_mark_disconnected(struct files_struct *fsp);
+bool brl_reconnect_disconnected(struct files_struct *fsp);
 void brl_close_fnum(struct messaging_context *msg_ctx,
                    struct byte_range_lock *br_lck);
 int brl_forall(void (*fn)(struct file_id id, struct server_id pid,
@@ -175,6 +177,8 @@ void add_deferred_open(struct share_mode_lock *lck, 
uint64_t mid,
                       struct timeval request_time,
                       struct server_id pid, struct file_id id);
 bool del_share_mode(struct share_mode_lock *lck, files_struct *fsp);
+bool mark_share_mode_disconnected(struct share_mode_lock *lck,
+                                 struct files_struct *fsp);
 void del_deferred_open_entry(struct share_mode_lock *lck, uint64_t mid,
                             struct server_id pid);
 bool remove_share_oplock(struct share_mode_lock *lck, files_struct *fsp);
diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c
index 42671a1..427e3af 100644
--- a/source3/modules/vfs_default.c
+++ b/source3/modules/vfs_default.c
@@ -2227,6 +2227,34 @@ static int vfswrap_set_offline(struct vfs_handle_struct 
*handle,
        return -1;
 }
 
+static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
+                                      struct files_struct *fsp,
+                                      TALLOC_CTX *mem_ctx,
+                                      DATA_BLOB *cookie)
+{
+       return NT_STATUS_NOT_SUPPORTED;
+}
+
+static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
+                                          struct files_struct *fsp,
+                                          const DATA_BLOB old_cookie,
+                                          TALLOC_CTX *mem_ctx,
+                                          DATA_BLOB *new_cookie)
+{
+       return NT_STATUS_NOT_SUPPORTED;
+}
+
+static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
+                                         struct smb_request *smb1req,
+                                         struct smbXsrv_open *op,
+                                         const DATA_BLOB old_cookie,
+                                         TALLOC_CTX *mem_ctx,
+                                         struct files_struct **fsp,
+                                         DATA_BLOB *new_cookie)
+{
+       return NT_STATUS_NOT_SUPPORTED;
+}
+
 static struct vfs_fn_pointers vfs_default_fns = {
        /* Disk operations */
 
@@ -2344,7 +2372,12 @@ static struct vfs_fn_pointers vfs_default_fns = {
 
        /* offline operations */
        .is_offline_fn = vfswrap_is_offline,
-       .set_offline_fn = vfswrap_set_offline
+       .set_offline_fn = vfswrap_set_offline,
+
+       /* durable handle operations */
+       .durable_cookie_fn = vfswrap_durable_cookie,
+       .durable_disconnect_fn = vfswrap_durable_disconnect,
+       .durable_reconnect_fn = vfswrap_durable_reconnect,
 };
 
 NTSTATUS vfs_default_init(void);
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index 2c77691..5f00932 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -831,7 +831,7 @@ static void init_globals(bool reinit_globals)
        Globals.max_log_size = 5000;
        Globals.max_open_files = max_open_files();
        Globals.open_files_db_hash_size = SMB_OPEN_DATABASE_TDB_HASH_SIZE;
-       Globals.srv_maxprotocol = PROTOCOL_SMB2_10;
+       Globals.srv_maxprotocol = PROTOCOL_SMB3_00;
        Globals.srv_minprotocol = PROTOCOL_LANMAN1;
        Globals.security = SEC_USER;
        Globals.bEncryptPasswords = true;
diff --git a/source3/smbd/close.c b/source3/smbd/close.c
index 5143232..8bf481d 100644
--- a/source3/smbd/close.c
+++ b/source3/smbd/close.c
@@ -706,6 +706,7 @@ static NTSTATUS close_normal_file(struct smb_request *req, 
files_struct *fsp,
        NTSTATUS status = NT_STATUS_OK;
        NTSTATUS tmp;
        connection_struct *conn = fsp->conn;
+       bool is_durable = false;
 
        if (fsp->num_aio_requests != 0) {
 
@@ -752,6 +753,49 @@ static NTSTATUS close_normal_file(struct smb_request *req, 
files_struct *fsp,
        tmp = close_filestruct(fsp);
        status = ntstatus_keeperror(status, tmp);
 
+       if (NT_STATUS_IS_OK(status) && fsp->op != NULL) {
+               is_durable = fsp->op->global->durable;
+       }
+
+       if (close_type != SHUTDOWN_CLOSE) {
+               is_durable = false;
+       }
+
+       if (is_durable) {
+               DATA_BLOB new_cookie = data_blob_null;
+
+               tmp = SMB_VFS_DURABLE_DISCONNECT(fsp,
+                                       fsp->op->global->backend_cookie,
+                                       fsp->op,
+                                       &new_cookie);
+               if (NT_STATUS_IS_OK(tmp)) {
+                       data_blob_free(&fsp->op->global->backend_cookie);
+                       fsp->op->global->backend_cookie = new_cookie;
+
+                       tmp = smbXsrv_open_update(fsp->op);
+               }
+               if (!NT_STATUS_IS_OK(tmp)) {
+                       is_durable = false;
+               }
+       }
+
+       if (is_durable) {
+               /*
+                * This is the case where we successfully disconnected
+                * a durable handle and closed the underlying file.
+                * In all other cases, we proceed with a genuine close.
+                */
+               file_free(req, fsp);
+               return NT_STATUS_OK;
+       }
+
+       if (fsp->op != NULL) {
+               /*
+                * Make sure the handle is not marked as durable anymore
+                */
+               fsp->op->global->durable = false;
+       }
+
        if (fsp->print_file) {
                /* FIXME: return spool errors */
                print_spool_end(fsp, close_type);
diff --git a/source3/smbd/files.c b/source3/smbd/files.c
index 0550b31..ef229a4 100644
--- a/source3/smbd/files.c
+++ b/source3/smbd/files.c
@@ -151,9 +151,16 @@ void file_close_conn(connection_struct *conn)
 
        for (fsp=conn->sconn->files; fsp; fsp=next) {
                next = fsp->next;
-               if (fsp->conn == conn) {
-                       close_file(NULL, fsp, SHUTDOWN_CLOSE);
+               if (fsp->conn != conn) {
+                       continue;
+               }
+               if (fsp->op != NULL && fsp->op->global->durable) {
+                       /*
+                        * A tree disconnect closes a durable handle


-- 
Samba Shared Repository

Reply via email to