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