The Samba-Bugzilla – Attachment 8999 Details for
Bug 9930
smbd did not cleanup disonnected durable handles
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Updated patchset for v4-0-test
scavenger-v4-0-test.patchset (text/plain), 61.74 KB, created by
Michael Adam
on 2013-06-26 13:44:45 UTC
(
hide
)
Description:
Updated patchset for v4-0-test
Filename:
MIME Type:
Creator:
Michael Adam
Created:
2013-06-26 13:44:45 UTC
Size:
61.74 KB
patch
obsolete
>From 538b01620893e80cded5df5620dce76425b6c7ec Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 13 Feb 2013 08:26:43 -0500 >Subject: [PATCH 01/18] s3:smbd: use smbXsrv_open_close() instead of > smbXsrv_open_update() > >This makes sure we store the correct disconnect_time for disconnected >durable handles. > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Michael Adam <obnox@samba.org> >(cherry picked from commit f0e6a9be00e441e50f0087c543e1b7c9012d126f) >--- > source3/smbd/close.c | 12 +++++++++++- > 1 file changed, 11 insertions(+), 1 deletion(-) > >diff --git a/source3/smbd/close.c b/source3/smbd/close.c >index 9b988e0..9e7ccc7 100644 >--- a/source3/smbd/close.c >+++ b/source3/smbd/close.c >@@ -769,10 +769,20 @@ static NTSTATUS close_normal_file(struct smb_request *req, files_struct *fsp, > fsp->op, > &new_cookie); > if (NT_STATUS_IS_OK(tmp)) { >+ struct timeval tv; >+ NTTIME now; >+ >+ if (req != NULL) { >+ tv = req->request_time; >+ } else { >+ tv = timeval_current(); >+ } >+ now = timeval_to_nttime(&tv); >+ > data_blob_free(&fsp->op->global->backend_cookie); > fsp->op->global->backend_cookie = new_cookie; > >- tmp = smbXsrv_open_update(fsp->op); >+ tmp = smbXsrv_open_close(fsp->op, now); > } > if (!NT_STATUS_IS_OK(tmp)) { > is_durable = false; >-- >1.7.9.5 > > >From 24f5a98dbea1a839c96ac841e861df558f2b4f76 Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Tue, 12 Feb 2013 17:44:51 +0100 >Subject: [PATCH 02/18] s3:smbd: add debugging to close code (regarding > disconnect of a durable) > >Signed-off-by: Michael Adam <obnox@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> > >Autobuild-User(master): Stefan Metzmacher <metze@samba.org> >Autobuild-Date(master): Mon Feb 18 17:42:45 CET 2013 on sn-devel-104 >(cherry picked from commit cfebce3c56474ac914474b57ed94f93418b0564b) >--- > source3/smbd/close.c | 14 ++++++++++++++ > 1 file changed, 14 insertions(+) > >diff --git a/source3/smbd/close.c b/source3/smbd/close.c >index 9e7ccc7..df3ae23 100644 >--- a/source3/smbd/close.c >+++ b/source3/smbd/close.c >@@ -783,6 +783,17 @@ static NTSTATUS close_normal_file(struct smb_request *req, files_struct *fsp, > fsp->op->global->backend_cookie = new_cookie; > > tmp = smbXsrv_open_close(fsp->op, now); >+ if (!NT_STATUS_IS_OK(tmp)) { >+ DEBUG(1, ("Failed to update smbXsrv_open " >+ "record when disconnecting durable " >+ "handle for file %s: %s - " >+ "proceeding with normal close\n", >+ fsp_str_dbg(fsp), nt_errstr(tmp))); >+ } >+ } else { >+ DEBUG(1, ("Failed to disconnect durable handle for " >+ "file %s: %s - proceeding with normal " >+ "close\n", fsp_str_dbg(fsp), nt_errstr(tmp))); > } > if (!NT_STATUS_IS_OK(tmp)) { > is_durable = false; >@@ -795,6 +806,9 @@ static NTSTATUS close_normal_file(struct smb_request *req, files_struct *fsp, > * a durable handle and closed the underlying file. > * In all other cases, we proceed with a genuine close. > */ >+ DEBUG(10, ("%s disconnected durable handle for file %s\n", >+ conn->session_info->unix_info->unix_name, >+ fsp_str_dbg(fsp))); > file_free(req, fsp); > return NT_STATUS_OK; > } >-- >1.7.9.5 > > >From 912ff863cb71f665ff020ce328e968927c33f983 Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Mon, 18 Feb 2013 23:21:24 +0100 >Subject: [PATCH 03/18] s3:smbd:smb2: fix segfault (access after free) in > durable disconnect code > >Pair-Programmed-With: Stefan Metzmacher <metze@samba.org> > >Signed-off-by: Michael Adam <obnox@samba.org> >Signed-off-by: Stefan Metzmacher <metze@samba.org> > >Autobuild-User(master): Michael Adam <obnox@samba.org> >Autobuild-Date(master): Tue Feb 19 11:12:01 CET 2013 on sn-devel-104 >(cherry picked from commit bdb80aeb11d5458e281483a5cdc57f5481979cc9) >--- > source3/smbd/close.c | 1 + > source3/smbd/smbXsrv_open.c | 1 + > 2 files changed, 2 insertions(+) > >diff --git a/source3/smbd/close.c b/source3/smbd/close.c >index df3ae23..d0c843e 100644 >--- a/source3/smbd/close.c >+++ b/source3/smbd/close.c >@@ -782,6 +782,7 @@ static NTSTATUS close_normal_file(struct smb_request *req, files_struct *fsp, > data_blob_free(&fsp->op->global->backend_cookie); > fsp->op->global->backend_cookie = new_cookie; > >+ fsp->op->compat = NULL; > tmp = smbXsrv_open_close(fsp->op, now); > if (!NT_STATUS_IS_OK(tmp)) { > DEBUG(1, ("Failed to update smbXsrv_open " >diff --git a/source3/smbd/smbXsrv_open.c b/source3/smbd/smbXsrv_open.c >index c1754e8..be39cbc 100644 >--- a/source3/smbd/smbXsrv_open.c >+++ b/source3/smbd/smbXsrv_open.c >@@ -1078,6 +1078,7 @@ NTSTATUS smbXsrv_open_close(struct smbXsrv_open *op, NTTIME now) > op->db_rec = NULL; > > if (op->compat) { >+ op->compat->op = NULL; > file_free(NULL, op->compat); > op->compat = NULL; > } >-- >1.7.9.5 > > >From ff5de935f0e04dd8529a3dd34978379f214a9f32 Mon Sep 17 00:00:00 2001 >From: Andreas Schneider <asn@samba.org> >Date: Tue, 5 Mar 2013 15:54:44 +0100 >Subject: [PATCH 04/18] lib: Add prctl_set_comment to utils. > >Reviewed-by: David Disseldorp <ddiss@samba.org> >(cherry picked from commit f9fb3faaef4c15b7c4c3748b0e93fa3061b573c3) > >Conflicts: > > lib/util/wscript_build >--- > lib/util/util_process.c | 34 ++++++++++++++++++++++++++++++++++ > lib/util/util_process.h | 35 +++++++++++++++++++++++++++++++++++ > lib/util/wscript_build | 3 ++- > source3/Makefile.in | 2 +- > 4 files changed, 72 insertions(+), 2 deletions(-) > create mode 100644 lib/util/util_process.c > create mode 100644 lib/util/util_process.h > >diff --git a/lib/util/util_process.c b/lib/util/util_process.c >new file mode 100644 >index 0000000..6036e27 >--- /dev/null >+++ b/lib/util/util_process.c >@@ -0,0 +1,34 @@ >+/* >+ * Unix SMB/CIFS implementation. >+ * >+ * Process utils. >+ * >+ * Copyright (c) 2013 Andreas Schneider <asn@samba.org> >+ * >+ * This program is free software; you can redistribute it and/or modify >+ * it under the terms of the GNU General Public License as published by >+ * the Free Software Foundation; either version 3 of the License, or >+ * (at your option) any later version. >+ * >+ * This program is distributed in the hope that it will be useful, >+ * but WITHOUT ANY WARRANTY; without even the implied warranty of >+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ * GNU General Public License for more details. >+ * >+ * You should have received a copy of the GNU General Public License >+ * along with this program; if not, see <http://www.gnu.org/licenses/>. >+ */ >+ >+#include "util_process.h" >+ >+#ifdef HAVE_SYS_PRCTL_H >+#include <sys/prctl.h> >+#endif >+ >+int prctl_set_comment(const char *comment) >+{ >+#if defined(HAVE_PRCTL) && defined(PR_SET_NAME) >+ return prctl(PR_SET_NAME, (unsigned long) comment, 0, 0, 0); >+#endif >+ return 0; >+} >diff --git a/lib/util/util_process.h b/lib/util/util_process.h >new file mode 100644 >index 0000000..6e1ef07 >--- /dev/null >+++ b/lib/util/util_process.h >@@ -0,0 +1,35 @@ >+/* >+ * Unix SMB/CIFS implementation. >+ * >+ * Process utils. >+ * >+ * Copyright (c) 2013 Andreas Schneider <asn@samba.org> >+ * >+ * This program is free software; you can redistribute it and/or modify >+ * it under the terms of the GNU General Public License as published by >+ * the Free Software Foundation; either version 3 of the License, or >+ * (at your option) any later version. >+ * >+ * This program is distributed in the hope that it will be useful, >+ * but WITHOUT ANY WARRANTY; without even the implied warranty of >+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ * GNU General Public License for more details. >+ * >+ * You should have received a copy of the GNU General Public License >+ * along with this program; if not, see <http://www.gnu.org/licenses/>. >+ */ >+ >+#ifndef _SAMBA_UTIL_PROCESS_H >+#define _SAMBA_UTIL_PROCESS_H >+ >+/** >+ * @brief Set the process comment name. >+ * >+ * @param[in] comment The comment to set which shouldn't be longer than 16 >+ * 16 characters (including \0). >+ * >+ * @return -1 on error, 0 on success. >+ */ >+int prctl_set_comment(const char *comment); >+ >+#endif >diff --git a/lib/util/wscript_build b/lib/util/wscript_build >index ddaf90f..27c9ec7 100755 >--- a/lib/util/wscript_build >+++ b/lib/util/wscript_build >@@ -7,7 +7,8 @@ bld.SAMBA_LIBRARY('samba-util', > signal.c system.c params.c util.c util_id.c util_net.c > util_strlist.c util_paths.c idtree.c debug.c fault.c base64.c > util_str.c util_str_common.c substitute.c ms_fnmatch.c >- server_id.c dprintf.c parmlist.c bitmap.c pidfile.c''', >+ server_id.c dprintf.c parmlist.c bitmap.c pidfile.c >+ util_process.c''', > deps='DYNCONFIG', > public_deps='talloc execinfo uid_wrapper pthread LIBCRYPTO charset util_setid', > public_headers='debug.h attr.h byteorder.h data_blob.h memory.h safe_string.h time.h talloc_stack.h xfile.h dlinklist.h samba_util.h string_wrappers.h', >diff --git a/source3/Makefile.in b/source3/Makefile.in >index c7c6250..fd6cdab 100644 >--- a/source3/Makefile.in >+++ b/source3/Makefile.in >@@ -431,7 +431,7 @@ UTIL_OBJ = ../lib/util/rbtree.o ../lib/util/signal.o ../lib/util/time.o \ > ../lib/util/genrand.o ../lib/util/util_net.o \ > ../lib/util/become_daemon.o ../lib/util/system.o \ > ../lib/util/tevent_unix.o ../lib/util/tevent_ntstatus.o \ >- ../lib/util/tevent_werror.o \ >+ ../lib/util/tevent_werror.o ../lib/util/util_process.o\ > lib/tevent_barrier.o \ > ../lib/util/smb_threads.o ../lib/util/util_id.o \ > ../lib/util/blocking.o ../lib/util/rfc1738.o \ >-- >1.7.9.5 > > >From ab69636ae701657dfb4804dec71f476cec980f65 Mon Sep 17 00:00:00 2001 >From: Gregor Beck <gbeck@sernet.de> >Date: Wed, 12 Dec 2012 16:06:50 +0100 >Subject: [PATCH 05/18] s3:smbXsrv_open: add smbXsrv_open_global_traverse() > >Signed-off-by: Gregor Beck <gbeck@sernet.de> >Reviewed-by: Michael Adam <obnox@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit d23f19ab00314d773edb07a45e754365db378668) >--- > source3/smbd/globals.h | 4 +++ > source3/smbd/smbXsrv_open.c | 73 +++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 77 insertions(+) > >diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h >index 1182ae9..16b2e8f 100644 >--- a/source3/smbd/globals.h >+++ b/source3/smbd/globals.h >@@ -457,6 +457,10 @@ NTSTATUS smb2srv_open_recreate(struct smbXsrv_connection *conn, > struct GUID create_guid, > NTTIME now, > struct smbXsrv_open **_open); >+struct smbXsrv_open_global0; >+NTSTATUS smbXsrv_open_global_traverse( >+ int (*fn)(struct smbXsrv_open_global0 *, void *), >+ void *private_data); > > struct smbd_smb2_request { > struct smbd_smb2_request *prev, *next; >diff --git a/source3/smbd/smbXsrv_open.c b/source3/smbd/smbXsrv_open.c >index be39cbc..2c2798b 100644 >--- a/source3/smbd/smbXsrv_open.c >+++ b/source3/smbd/smbXsrv_open.c >@@ -1277,3 +1277,76 @@ NTSTATUS smb2srv_open_recreate(struct smbXsrv_connection *conn, > *_open = op; > return NT_STATUS_OK; > } >+ >+ >+struct smbXsrv_open_global_traverse_state { >+ int (*fn)(struct smbXsrv_open_global0 *, void *); >+ void *private_data; >+}; >+ >+static int smbXsrv_open_global_traverse_fn(struct db_record *rec, void *data) >+{ >+ int ret = -1; >+ struct smbXsrv_open_global_traverse_state *state = >+ (struct smbXsrv_open_global_traverse_state*)data; >+ TDB_DATA key = dbwrap_record_get_key(rec); >+ TDB_DATA val = dbwrap_record_get_value(rec); >+ DATA_BLOB blob = data_blob_const(val.dptr, val.dsize); >+ struct smbXsrv_open_globalB global_blob; >+ enum ndr_err_code ndr_err; >+ TALLOC_CTX *frame = talloc_stackframe(); >+ >+ ndr_err = ndr_pull_struct_blob(&blob, frame, &global_blob, >+ (ndr_pull_flags_fn_t)ndr_pull_smbXsrv_open_globalB); >+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { >+ DEBUG(1,("Invalid record in smbXsrv_open_global.tdb:" >+ "key '%s' ndr_pull_struct_blob - %s\n", >+ hex_encode_talloc(frame, key.dptr, key.dsize), >+ ndr_errstr(ndr_err))); >+ goto done; >+ } >+ >+ if (global_blob.version != SMBXSRV_VERSION_0) { >+ DEBUG(1,("Invalid record in smbXsrv_open_global.tdb:" >+ "key '%s' unsuported version - %d\n", >+ hex_encode_talloc(frame, key.dptr, key.dsize), >+ (int)global_blob.version)); >+ goto done; >+ } >+ >+ global_blob.info.info0->db_rec = rec; >+ ret = state->fn(global_blob.info.info0, state->private_data); >+done: >+ TALLOC_FREE(frame); >+ return ret; >+} >+ >+NTSTATUS smbXsrv_open_global_traverse( >+ int (*fn)(struct smbXsrv_open_global0 *, void *), >+ void *private_data) >+{ >+ >+ NTSTATUS status; >+ int count = 0; >+ struct smbXsrv_open_global_traverse_state state = { >+ .fn = fn, >+ .private_data = private_data, >+ }; >+ >+ become_root(); >+ status = smbXsrv_open_global_init(); >+ if (!NT_STATUS_IS_OK(status)) { >+ unbecome_root(); >+ DEBUG(0, ("Failed to initialize open_global: %s\n", >+ nt_errstr(status))); >+ return status; >+ } >+ >+ status = dbwrap_traverse_read(smbXsrv_open_global_db_ctx, >+ smbXsrv_open_global_traverse_fn, >+ &state, >+ &count); >+ unbecome_root(); >+ >+ return status; >+} >-- >1.7.9.5 > > >From 11c8b78f858f4ac62f33ba717a40d33eecb7b06f Mon Sep 17 00:00:00 2001 >From: Gregor Beck <gbeck@sernet.de> >Date: Tue, 12 Mar 2013 13:43:30 +0100 >Subject: [PATCH 06/18] s3:smbXsrv_open: factor out > smbXsrv_open_global_parse_record > >Signed-off-by: Gregor Beck <gbeck@sernet.de> >Reviewed-by: Michael Adam <obnox@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit 9d47dc8958f7fcab77460495bd1ae940122dddd8) >--- > source3/smbd/smbXsrv_open.c | 50 +++++++++++++++++++++++++++++++------------ > 1 file changed, 36 insertions(+), 14 deletions(-) > >diff --git a/source3/smbd/smbXsrv_open.c b/source3/smbd/smbXsrv_open.c >index 2c2798b..97d6cd4 100644 >--- a/source3/smbd/smbXsrv_open.c >+++ b/source3/smbd/smbXsrv_open.c >@@ -1279,21 +1279,16 @@ NTSTATUS smb2srv_open_recreate(struct smbXsrv_connection *conn, > } > > >-struct smbXsrv_open_global_traverse_state { >- int (*fn)(struct smbXsrv_open_global0 *, void *); >- void *private_data; >-}; >- >-static int smbXsrv_open_global_traverse_fn(struct db_record *rec, void *data) >+static NTSTATUS smbXsrv_open_global_parse_record(TALLOC_CTX *mem_ctx, >+ struct db_record *rec, >+ struct smbXsrv_open_global0 **global) > { >- int ret = -1; >- struct smbXsrv_open_global_traverse_state *state = >- (struct smbXsrv_open_global_traverse_state*)data; > TDB_DATA key = dbwrap_record_get_key(rec); > TDB_DATA val = dbwrap_record_get_value(rec); > DATA_BLOB blob = data_blob_const(val.dptr, val.dsize); > struct smbXsrv_open_globalB global_blob; > enum ndr_err_code ndr_err; >+ NTSTATUS status; > TALLOC_CTX *frame = talloc_stackframe(); > > ndr_err = ndr_pull_struct_blob(&blob, frame, &global_blob, >@@ -1303,21 +1298,48 @@ static int smbXsrv_open_global_traverse_fn(struct db_record *rec, void *data) > "key '%s' ndr_pull_struct_blob - %s\n", > hex_encode_talloc(frame, key.dptr, key.dsize), > ndr_errstr(ndr_err))); >+ status = ndr_map_error2ntstatus(ndr_err); > goto done; > } > > if (global_blob.version != SMBXSRV_VERSION_0) { >+ status = NT_STATUS_INTERNAL_DB_CORRUPTION; > DEBUG(1,("Invalid record in smbXsrv_open_global.tdb:" >- "key '%s' unsuported version - %d\n", >+ "key '%s' unsuported version - %d - %s\n", > hex_encode_talloc(frame, key.dptr, key.dsize), >- (int)global_blob.version)); >+ (int)global_blob.version, >+ nt_errstr(status))); > goto done; > } > >- global_blob.info.info0->db_rec = rec; >- ret = state->fn(global_blob.info.info0, state->private_data); >+ *global = talloc_move(mem_ctx, &global_blob.info.info0); >+ status = NT_STATUS_OK; > done: >- TALLOC_FREE(frame); >+ talloc_free(frame); >+ return status; >+} >+ >+struct smbXsrv_open_global_traverse_state { >+ int (*fn)(struct smbXsrv_open_global0 *, void *); >+ void *private_data; >+}; >+ >+static int smbXsrv_open_global_traverse_fn(struct db_record *rec, void *data) >+{ >+ struct smbXsrv_open_global_traverse_state *state = >+ (struct smbXsrv_open_global_traverse_state*)data; >+ struct smbXsrv_open_global0 *global = NULL; >+ NTSTATUS status; >+ int ret = -1; >+ >+ status = smbXsrv_open_global_parse_record(talloc_tos(), rec, &global); >+ if (!NT_STATUS_IS_OK(status)) { >+ return -1; >+ } >+ >+ global->db_rec = rec; >+ ret = state->fn(global, state->private_data); >+ talloc_free(global); > return ret; > } > >-- >1.7.9.5 > > >From 74d9d0f1467450565decf21e3bc60da89a200d07 Mon Sep 17 00:00:00 2001 >From: Gregor Beck <gbeck@sernet.de> >Date: Tue, 12 Mar 2013 14:36:32 +0100 >Subject: [PATCH 07/18] s3:smbXsrv_open: add function smbXsrv_open_cleanup() > >Signed-off-by: Gregor Beck <gbeck@sernet.de> >Reviewed-by: Michael Adam <obnox@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit 941e84dcfe985559e5e75318e7b5dd9d50fcc47b) >--- > source3/smbd/globals.h | 3 ++ > source3/smbd/smbXsrv_open.c | 77 +++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 80 insertions(+) > >diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h >index 16b2e8f..b1f69c8 100644 >--- a/source3/smbd/globals.h >+++ b/source3/smbd/globals.h >@@ -462,6 +462,9 @@ NTSTATUS smbXsrv_open_global_traverse( > int (*fn)(struct smbXsrv_open_global0 *, void *), > void *private_data); > >+NTSTATUS smbXsrv_open_cleanup(uint64_t persistent_id); >+ >+ > struct smbd_smb2_request { > struct smbd_smb2_request *prev, *next; > >diff --git a/source3/smbd/smbXsrv_open.c b/source3/smbd/smbXsrv_open.c >index 97d6cd4..27dd50c 100644 >--- a/source3/smbd/smbXsrv_open.c >+++ b/source3/smbd/smbXsrv_open.c >@@ -1372,3 +1372,80 @@ NTSTATUS smbXsrv_open_global_traverse( > > return status; > } >+ >+NTSTATUS smbXsrv_open_cleanup(uint64_t persistent_id) >+{ >+ NTSTATUS status; >+ TALLOC_CTX *frame = talloc_stackframe(); >+ struct smbXsrv_open_global0 *op = NULL; >+ uint8_t key_buf[SMBXSRV_OPEN_GLOBAL_TDB_KEY_SIZE]; >+ TDB_DATA key; >+ struct db_record *rec; >+ bool delete_open = false; >+ uint32_t global_id = persistent_id & UINT32_MAX; >+ >+ key = smbXsrv_open_global_id_to_key(global_id, key_buf); >+ rec = dbwrap_fetch_locked(smbXsrv_open_global_db_ctx, frame, key); >+ if (rec == NULL) { >+ status = NT_STATUS_NOT_FOUND; >+ DEBUG(1, ("smbXsrv_open_cleanup[global: 0x%08x] " >+ "failed to fetch record from %s - %s\n", >+ global_id, dbwrap_name(smbXsrv_open_global_db_ctx), >+ nt_errstr(status))); >+ goto done; >+ } >+ >+ status = smbXsrv_open_global_parse_record(talloc_tos(), rec, &op); >+ if (!NT_STATUS_IS_OK(status)) { >+ DEBUG(1, ("smbXsrv_open_cleanup[global: 0x%08x] " >+ "failed to read record: %s\n", >+ global_id, nt_errstr(status))); >+ goto done; >+ } >+ >+ if (server_id_is_disconnected(&op->server_id)) { >+ struct timeval now, disconnect_time; >+ int64_t tdiff; >+ now = timeval_current(); >+ nttime_to_timeval(&disconnect_time, op->disconnect_time); >+ tdiff = usec_time_diff(&now, &disconnect_time); >+ delete_open = (tdiff >= 1000*op->durable_timeout_msec); >+ >+ DEBUG(10, ("smbXsrv_open_cleanup[global: 0x%08x] " >+ "disconnected at [%s] %us ago with " >+ "timeout of %us -%s reached\n", >+ global_id, >+ nt_time_string(frame, op->disconnect_time), >+ (unsigned)(tdiff/1000000), >+ op->durable_timeout_msec / 1000, >+ delete_open ? "" : " not")); >+ } else if (!serverid_exists(&op->server_id)) { >+ DEBUG(10, ("smbXsrv_open_cleanup[global: 0x%08x] " >+ "server[%s] does not exist\n", >+ global_id, server_id_str(frame, &op->server_id))); >+ delete_open = true; >+ } >+ >+ if (!delete_open) { >+ goto done; >+ } >+ >+ status = dbwrap_record_delete(rec); >+ if (!NT_STATUS_IS_OK(status)) { >+ DEBUG(1, ("smbXsrv_open_cleanup[global: 0x%08x] " >+ "failed to delete record" >+ "from %s: %s\n", global_id, >+ dbwrap_name(smbXsrv_open_global_db_ctx), >+ nt_errstr(status))); >+ goto done; >+ } >+ >+ DEBUG(10, ("smbXsrv_open_cleanup[global: 0x%08x] " >+ "delete record from %s\n", >+ global_id, >+ dbwrap_name(smbXsrv_open_global_db_ctx))); >+ >+done: >+ talloc_free(frame); >+ return status; >+} >-- >1.7.9.5 > > >From 4aebdaed5e1fabdd2962f815168f25389bff9ebb Mon Sep 17 00:00:00 2001 >From: Gregor Beck <gbeck@sernet.de> >Date: Tue, 5 Mar 2013 14:02:10 +0100 >Subject: [PATCH 08/18] s3:locking:brlock: use serverids_exist to > validate_lock_entries > >...instead of checking each server-id separately which can >be expensive in a cluster. > >Signed-off-by: Gregor Beck <gbeck@sernet.de> >Reviewed-by: Michael Adam <obnox@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit 02cc5a5c6a6b6b2b796abe573a671853d945b22f) >--- > source3/locking/brlock.c | 37 ++++++++++++++++++++++++++++++++++--- > 1 file changed, 34 insertions(+), 3 deletions(-) > >diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c >index b7abaa9..55a1bd0 100644 >--- a/source3/locking/brlock.c >+++ b/source3/locking/brlock.c >@@ -1655,17 +1655,48 @@ static bool validate_lock_entries(unsigned int *pnum_entries, struct lock_struct > unsigned int i; > unsigned int num_valid_entries = 0; > struct lock_struct *locks = *pplocks; >+ TALLOC_CTX *frame = talloc_stackframe(); >+ struct server_id *ids; >+ bool *exists; >+ >+ ids = talloc_array(frame, struct server_id, *pnum_entries); >+ if (ids == NULL) { >+ DEBUG(0, ("validate_lock_entries: " >+ "talloc_array(struct server_id, %u) failed\n", >+ *pnum_entries)); >+ talloc_free(frame); >+ return false; >+ } >+ >+ exists = talloc_array(frame, bool, *pnum_entries); >+ if (exists == NULL) { >+ DEBUG(0, ("validate_lock_entries: " >+ "talloc_array(bool, %u) failed\n", >+ *pnum_entries)); >+ talloc_free(frame); >+ return false; >+ } >+ >+ for (i = 0; i < *pnum_entries; i++) { >+ ids[i] = locks[i].context.pid; >+ } >+ >+ if (!serverids_exist(ids, *pnum_entries, exists)) { >+ DEBUG(3, ("validate_lock_entries: serverids_exists failed\n")); >+ talloc_free(frame); >+ return false; >+ } > > for (i = 0; i < *pnum_entries; i++) { >- struct lock_struct *lock_data = &locks[i]; >- if (!serverid_exists(&lock_data->context.pid)) { >+ if (!exists[i]) { > /* This process no longer exists - mark this > entry as invalid by zeroing it. */ >- ZERO_STRUCTP(lock_data); >+ ZERO_STRUCTP(&locks[i]); > } else { > num_valid_entries++; > } > } >+ TALLOC_FREE(frame); > > if (num_valid_entries != *pnum_entries) { > struct lock_struct *new_lock_data = NULL; >-- >1.7.9.5 > > >From beb6773ed0eef6e58be25656c1cbcf07dee4da85 Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Fri, 12 Apr 2013 11:05:29 +0200 >Subject: [PATCH 09/18] s3:locking:brlock: improve the comment for the brl > self cleaning code > >Signed-off-by: Michael Adam <obnox@samba.org> >Signed-off-by: Gregor Beck <gbeck@sernet.de> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit fe0bf0b6d67a49a30969f922ee65f0af88a952a1) >--- > source3/locking/brlock.c | 9 ++++++--- > 1 file changed, 6 insertions(+), 3 deletions(-) > >diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c >index 55a1bd0..cfdc971 100644 >--- a/source3/locking/brlock.c >+++ b/source3/locking/brlock.c >@@ -1958,9 +1958,12 @@ static struct byte_range_lock *brl_get_locks_internal(TALLOC_CTX *mem_ctx, > if (!fsp->lockdb_clean) { > int orig_num_locks = br_lck->num_locks; > >- /* This is the first time we've accessed this. */ >- /* Go through and ensure all entries exist - remove any that don't. */ >- /* Makes the lockdb self cleaning at low cost. */ >+ /* >+ * This is the first time we access the byte range lock >+ * record with this fsp. Go through and ensure all entries >+ * are valid - remove any that don't. >+ * This makes the lockdb self cleaning at low cost. >+ */ > > if (!validate_lock_entries(&br_lck->num_locks, > &br_lck->lock_data)) { >-- >1.7.9.5 > > >From c3678ce855ec873d055f87d052ac376d673cb97d Mon Sep 17 00:00:00 2001 >From: Gregor Beck <gbeck@sernet.de> >Date: Tue, 5 Mar 2013 14:49:28 +0100 >Subject: [PATCH 10/18] s3:locking:brlock: let validate_lock_entries keep > entries for disconnected servers in traverses > >We should not remove locks of disconnected opens just like that. >When getting the byte range lock record for a newly connected file >handle, we still do the clean up, because in that situation, >disconnected entries are not valid any more. > >Signed-off-by: Gregor Beck <gbeck@sernet.de> >Reviewed-by: Michael Adam <obnox@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit f08bda22dc7a5038fab77ad7dd090a6f72d94c7f) >--- > source3/locking/brlock.c | 31 +++++++++++++++++++++++-------- > 1 file changed, 23 insertions(+), 8 deletions(-) > >diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c >index cfdc971..1469e16 100644 >--- a/source3/locking/brlock.c >+++ b/source3/locking/brlock.c >@@ -1650,7 +1650,8 @@ bool brl_reconnect_disconnected(struct files_struct *fsp) > /**************************************************************************** > Ensure this set of lock entries is valid. > ****************************************************************************/ >-static bool validate_lock_entries(unsigned int *pnum_entries, struct lock_struct **pplocks) >+static bool validate_lock_entries(unsigned int *pnum_entries, struct lock_struct **pplocks, >+ bool keep_disconnected) > { > unsigned int i; > unsigned int num_valid_entries = 0; >@@ -1688,13 +1689,21 @@ static bool validate_lock_entries(unsigned int *pnum_entries, struct lock_struct > } > > for (i = 0; i < *pnum_entries; i++) { >- if (!exists[i]) { >- /* This process no longer exists - mark this >- entry as invalid by zeroing it. */ >- ZERO_STRUCTP(&locks[i]); >- } else { >+ if (exists[i]) { > num_valid_entries++; >+ continue; > } >+ >+ if (keep_disconnected && >+ server_id_is_disconnected(&ids[i])) >+ { >+ num_valid_entries++; >+ continue; >+ } >+ >+ /* This process no longer exists - mark this >+ entry as invalid by zeroing it. */ >+ ZERO_STRUCTP(&locks[i]); > } > TALLOC_FREE(frame); > >@@ -1770,7 +1779,7 @@ static int brl_traverse_fn(struct db_record *rec, void *state) > > /* Ensure the lock db is clean of entries from invalid processes. */ > >- if (!validate_lock_entries(&num_locks, &locks)) { >+ if (!validate_lock_entries(&num_locks, &locks, true)) { > SAFE_FREE(locks); > return -1; /* Terminate traversal */ > } >@@ -1963,10 +1972,16 @@ static struct byte_range_lock *brl_get_locks_internal(TALLOC_CTX *mem_ctx, > * record with this fsp. Go through and ensure all entries > * are valid - remove any that don't. > * This makes the lockdb self cleaning at low cost. >+ * >+ * Note: Disconnected entries belong to disconnected >+ * durable handles. So at this point, we have a new >+ * handle on the file and the disconnected durable has >+ * already been closed (we are not a durable reconnect). >+ * So we need to clean the disconnected brl entry. > */ > > if (!validate_lock_entries(&br_lck->num_locks, >- &br_lck->lock_data)) { >+ &br_lck->lock_data, false)) { > SAFE_FREE(br_lck->lock_data); > TALLOC_FREE(br_lck); > return NULL; >-- >1.7.9.5 > > >From 83b81fce7ba2a6f479d700cb7f4b9abcbfd6d562 Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Fri, 12 Apr 2013 11:13:57 +0200 >Subject: [PATCH 11/18] s3:locking:brlock: explain the lockdb_clean semantic > better in brl_reconnect_disconnected() > >Signed-off-by: Michael Adam <obnox@samba.org> >Signed-off-by: Gregor Beck <gbeck@sernet.de> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit 6ee1555df2e69aead00ee231c990020cc4bf04bc) >--- > source3/locking/brlock.c | 6 +++++- > 1 file changed, 5 insertions(+), 1 deletion(-) > >diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c >index 1469e16..42e6333 100644 >--- a/source3/locking/brlock.c >+++ b/source3/locking/brlock.c >@@ -1595,7 +1595,11 @@ bool brl_reconnect_disconnected(struct files_struct *fsp) > return false; > } > >- /* we want to validate ourself */ >+ /* >+ * When reconnecting, we do not want to validate the brlock entries >+ * and thereby remove our own (disconnected) entries but reactivate >+ * them instead. >+ */ > fsp->lockdb_clean = true; > > br_lck = brl_get_locks(talloc_tos(), fsp); >-- >1.7.9.5 > > >From c2abeab6cbedda551b34457c210cab1cb43bb022 Mon Sep 17 00:00:00 2001 >From: Gregor Beck <gbeck@sernet.de> >Date: Wed, 13 Mar 2013 14:47:18 +0100 >Subject: [PATCH 12/18] s3:locking:brlock: add function > brl_cleanup_disconnected() > >For a given file, clean up brl entries belonging to a given persistent file id. > >Signed-off-by: Gregor Beck <gbeck@sernet.de> >Reviewed-by: Michael Adam <obnox@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit ee81a6e7d0263d263f7d4e7bd5bd9c4156cae8cf) >--- > source3/locking/brlock.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++ > source3/locking/proto.h | 1 + > 2 files changed, 74 insertions(+) > >diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c >index 42e6333..0654209 100644 >--- a/source3/locking/brlock.c >+++ b/source3/locking/brlock.c >@@ -32,6 +32,7 @@ > #include "dbwrap/dbwrap_open.h" > #include "serverid.h" > #include "messages.h" >+#include "util_tdb.h" > > #undef DBGC_CLASS > #define DBGC_CLASS DBGC_LOCKING >@@ -2152,3 +2153,75 @@ void brl_revalidate(struct messaging_context *msg_ctx, > TALLOC_FREE(state); > return; > } >+ >+bool brl_cleanup_disconnected(struct file_id fid, uint64_t open_persistent_id) >+{ >+ bool ret = false; >+ TALLOC_CTX *frame = talloc_stackframe(); >+ TDB_DATA key, val; >+ struct db_record *rec; >+ struct lock_struct *lock; >+ unsigned n, num; >+ NTSTATUS status; >+ >+ key = make_tdb_data((void*)&fid, sizeof(fid)); >+ >+ rec = dbwrap_fetch_locked(brlock_db, frame, key); >+ if (rec == NULL) { >+ DEBUG(5, ("brl_cleanup_disconnected: failed to fetch record " >+ "for file %s\n", file_id_string(frame, &fid))); >+ goto done; >+ } >+ >+ val = dbwrap_record_get_value(rec); >+ lock = (struct lock_struct*)val.dptr; >+ num = val.dsize / sizeof(struct lock_struct); >+ if (lock == NULL) { >+ DEBUG(10, ("brl_cleanup_disconnected: no byte range locks for " >+ "file %s\n", file_id_string(frame, &fid))); >+ ret = true; >+ goto done; >+ } >+ >+ for (n=0; n<num; n++) { >+ struct lock_context *ctx = &lock[n].context; >+ >+ if (!server_id_is_disconnected(&ctx->pid)) { >+ DEBUG(5, ("brl_cleanup_disconnected: byte range lock " >+ "%s used by server %s, do not cleanup\n", >+ file_id_string(frame, &fid), >+ server_id_str(frame, &ctx->pid))); >+ goto done; >+ } >+ >+ if (ctx->smblctx != open_persistent_id) { >+ DEBUG(5, ("brl_cleanup_disconnected: byte range lock " >+ "%s expected smblctx %llu but found %llu" >+ ", do not cleanup\n", >+ file_id_string(frame, &fid), >+ (unsigned long long)open_persistent_id, >+ (unsigned long long)ctx->smblctx)); >+ goto done; >+ } >+ } >+ >+ status = dbwrap_record_delete(rec); >+ if (!NT_STATUS_IS_OK(status)) { >+ DEBUG(5, ("brl_cleanup_disconnected: failed to delete record " >+ "for file %s from %s, open %llu: %s\n", >+ file_id_string(frame, &fid), dbwrap_name(brlock_db), >+ (unsigned long long)open_persistent_id, >+ nt_errstr(status))); >+ goto done; >+ } >+ >+ DEBUG(10, ("brl_cleanup_disconnected: " >+ "file %s cleaned up %u entries from open %llu\n", >+ file_id_string(frame, &fid), num, >+ (unsigned long long)open_persistent_id)); >+ >+ ret = true; >+done: >+ talloc_free(frame); >+ return ret; >+} >diff --git a/source3/locking/proto.h b/source3/locking/proto.h >index c170c73..69c78e3 100644 >--- a/source3/locking/proto.h >+++ b/source3/locking/proto.h >@@ -97,6 +97,7 @@ void brl_revalidate(struct messaging_context *msg_ctx, > uint32_t msg_type, > struct server_id server_id, > DATA_BLOB *data); >+bool brl_cleanup_disconnected(struct file_id fid, uint64_t open_persistent_id); > > /* The following definitions come from locking/locking.c */ > >-- >1.7.9.5 > > >From d7b11f34366bb4dca78e7cb0b857387f7f86d8cd Mon Sep 17 00:00:00 2001 >From: Gregor Beck <gbeck@sernet.de> >Date: Tue, 12 Mar 2013 15:10:51 +0100 >Subject: [PATCH 13/18] s3:locking: no need to make a file_id passed by value > a constant > >Signed-off-by: Gregor Beck <gbeck@sernet.de> >Reviewed-by: Michael Adam <obnox@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit 3d3e7e837a339dfc1aaf4d7fc52f95f3f6a80173) > >Conflicts: > > source3/locking/share_mode_lock.c >--- > source3/locking/proto.h | 6 +++--- > source3/locking/share_mode_lock.c | 17 +++++++---------- > 2 files changed, 10 insertions(+), 13 deletions(-) > >diff --git a/source3/locking/proto.h b/source3/locking/proto.h >index 69c78e3..1d8eb73 100644 >--- a/source3/locking/proto.h >+++ b/source3/locking/proto.h >@@ -150,15 +150,15 @@ bool locking_init_readonly(void); > bool locking_end(void); > char *share_mode_str(TALLOC_CTX *ctx, int num, const struct share_mode_entry *e); > struct share_mode_lock *get_existing_share_mode_lock(TALLOC_CTX *mem_ctx, >- const struct file_id id); >+ struct file_id id); > struct share_mode_lock *get_share_mode_lock( > TALLOC_CTX *mem_ctx, >- const struct file_id id, >+ struct file_id id, > const char *servicepath, > const struct smb_filename *smb_fname, > const struct timespec *old_write_time); > struct share_mode_lock *fetch_share_mode_unlocked(TALLOC_CTX *mem_ctx, >- const struct file_id id); >+ struct file_id id); > bool rename_share_filename(struct messaging_context *msg_ctx, > struct share_mode_lock *lck, > const char *servicepath, >diff --git a/source3/locking/share_mode_lock.c b/source3/locking/share_mode_lock.c >index a82c44e..5766159 100644 >--- a/source3/locking/share_mode_lock.c >+++ b/source3/locking/share_mode_lock.c >@@ -104,10 +104,9 @@ bool locking_end(void) > Form a static locking key for a dev/inode pair. > ******************************************************************/ > >-static TDB_DATA locking_key(const struct file_id *id, struct file_id *tmp) >+static TDB_DATA locking_key(const struct file_id *id) > { >- *tmp = *id; >- return make_tdb_data((const uint8_t *)tmp, sizeof(*tmp)); >+ return make_tdb_data((const uint8_t *)id, sizeof(*id)); > } > > /******************************************************************* >@@ -286,15 +285,14 @@ fail: > ********************************************************************/ > > static struct share_mode_lock *get_share_mode_lock_internal( >- TALLOC_CTX *mem_ctx, const struct file_id id, >+ TALLOC_CTX *mem_ctx, struct file_id id, > const char *servicepath, const struct smb_filename *smb_fname, > const struct timespec *old_write_time) > { > struct share_mode_lock *lck; > struct share_mode_data *d; >- struct file_id tmp; > struct db_record *rec; >- TDB_DATA key = locking_key(&id, &tmp); >+ TDB_DATA key = locking_key(&id); > TDB_DATA value; > > rec = dbwrap_fetch_locked(lock_db, mem_ctx, key); >@@ -351,7 +349,7 @@ static int the_lock_destructor(struct share_mode_lock *l) > > struct share_mode_lock *get_share_mode_lock( > TALLOC_CTX *mem_ctx, >- const struct file_id id, >+ struct file_id id, > const char *servicepath, > const struct smb_filename *smb_fname, > const struct timespec *old_write_time) >@@ -395,11 +393,10 @@ fail: > ********************************************************************/ > > struct share_mode_lock *fetch_share_mode_unlocked(TALLOC_CTX *mem_ctx, >- const struct file_id id) >+ struct file_id id) > { > struct share_mode_lock *lck; >- struct file_id tmp; >- TDB_DATA key = locking_key(&id, &tmp); >+ TDB_DATA key = locking_key(&id); > TDB_DATA data; > NTSTATUS status; > >-- >1.7.9.5 > > >From 2983d750fdef7c6da53d06b193e9fa2e21bdd88b Mon Sep 17 00:00:00 2001 >From: Gregor Beck <gbeck@sernet.de> >Date: Wed, 20 Mar 2013 10:22:06 +0100 >Subject: [PATCH 14/18] s3:locking: improve debug output of > parse_share_modes() > >Signed-off-by: Gregor Beck <gbeck@sernet.de> >Reviewed-by: Michael Adam <obnox@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit 0ac0b35dad796d10cf04ab77a53a926420cc0589) >--- > source3/locking/share_mode_lock.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > >diff --git a/source3/locking/share_mode_lock.c b/source3/locking/share_mode_lock.c >index 5766159..df82b68 100644 >--- a/source3/locking/share_mode_lock.c >+++ b/source3/locking/share_mode_lock.c >@@ -132,7 +132,8 @@ static struct share_mode_data *parse_share_modes(TALLOC_CTX *mem_ctx, > ndr_err = ndr_pull_struct_blob( > &blob, d, d, (ndr_pull_flags_fn_t)ndr_pull_share_mode_data); > if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { >- DEBUG(1, ("ndr_pull_share_mode_lock failed\n")); >+ DEBUG(1, ("ndr_pull_share_mode_lock failed: %s\n", >+ ndr_errstr(ndr_err))); > goto fail; > } > >-- >1.7.9.5 > > >From 97548b93134a982f0550fb30de78f1c9c6f733be Mon Sep 17 00:00:00 2001 >From: Gregor Beck <gbeck@sernet.de> >Date: Wed, 13 Mar 2013 11:35:37 +0100 >Subject: [PATCH 15/18] s3:locking: add function > share_mode_cleanup_disconnected() > >For a given file, clean share mode entries for a given persistent file id. > >Pair-Programmed-With: Michael Adam <obnox@samba.org> >Pair-Programmed-With: Stefan Metzmacher <metze@samba.org> > >Signed-off-by: Gregor Beck <gbeck@sernet.de> >Signed-off-by: Michael Adam <obnox@samba.org> >Signed-off-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit f608bedfca4118b7e3606802df40e266bcc099d8) >--- > source3/locking/proto.h | 3 ++ > source3/locking/share_mode_lock.c | 99 +++++++++++++++++++++++++++++++++++++ > 2 files changed, 102 insertions(+) > >diff --git a/source3/locking/proto.h b/source3/locking/proto.h >index 1d8eb73..bb7255d 100644 >--- a/source3/locking/proto.h >+++ b/source3/locking/proto.h >@@ -202,6 +202,9 @@ bool set_write_time(struct file_id fileid, struct timespec write_time); > int share_mode_forall(void (*fn)(const struct share_mode_entry *, const char *, > const char *, void *), > void *private_data); >+bool share_mode_cleanup_disconnected(struct file_id id, >+ uint64_t open_persistent_id); >+ > > /* The following definitions come from locking/posix.c */ > >diff --git a/source3/locking/share_mode_lock.c b/source3/locking/share_mode_lock.c >index df82b68..266be65 100644 >--- a/source3/locking/share_mode_lock.c >+++ b/source3/locking/share_mode_lock.c >@@ -500,3 +500,102 @@ int share_mode_forall(void (*fn)(const struct share_mode_entry *, const char *, > return count; > } > } >+ >+bool share_mode_cleanup_disconnected(struct file_id fid, >+ uint64_t open_persistent_id) >+{ >+ bool ret = false; >+ TALLOC_CTX *frame = talloc_stackframe(); >+ unsigned n; >+ struct share_mode_data *data; >+ struct share_mode_lock *lck; >+ bool ok; >+ >+ lck = get_existing_share_mode_lock(frame, fid); >+ if (lck == NULL) { >+ DEBUG(5, ("share_mode_cleanup_disconnected: " >+ "Could not fetch share mode entry for %s\n", >+ file_id_string(frame, &fid))); >+ goto done; >+ } >+ data = lck->data; >+ >+ for (n=0; n < data->num_share_modes; n++) { >+ struct share_mode_entry *entry = &data->share_modes[n]; >+ >+ if (!server_id_is_disconnected(&entry->pid)) { >+ DEBUG(5, ("share_mode_cleanup_disconnected: " >+ "file (file-id='%s', servicepath='%s', " >+ "base_name='%s%s%s') " >+ "is used by server %s ==> do not cleanup\n", >+ file_id_string(frame, &fid), >+ data->servicepath, >+ data->base_name, >+ (data->stream_name == NULL) >+ ? "" : "', stream_name='", >+ (data->stream_name == NULL) >+ ? "" : data->stream_name, >+ server_id_str(frame, &entry->pid))); >+ goto done; >+ } >+ if (open_persistent_id != entry->share_file_id) { >+ DEBUG(5, ("share_mode_cleanup_disconnected: " >+ "entry for file " >+ "(file-id='%s', servicepath='%s', " >+ "base_name='%s%s%s') " >+ "has share_file_id %llu but expected %llu" >+ "==> do not cleanup\n", >+ file_id_string(frame, &fid), >+ data->servicepath, >+ data->base_name, >+ (data->stream_name == NULL) >+ ? "" : "', stream_name='", >+ (data->stream_name == NULL) >+ ? "" : data->stream_name, >+ (unsigned long long)entry->share_file_id, >+ (unsigned long long)open_persistent_id)); >+ goto done; >+ } >+ } >+ >+ ok = brl_cleanup_disconnected(fid, open_persistent_id); >+ if (!ok) { >+ DEBUG(10, ("share_mode_cleanup_disconnected: " >+ "failed to clean up byte range locks associated " >+ "with file (file-id='%s', servicepath='%s', " >+ "base_name='%s%s%s') and open_persistent_id %llu " >+ "==> do not cleanup\n", >+ file_id_string(frame, &fid), >+ data->servicepath, >+ data->base_name, >+ (data->stream_name == NULL) >+ ? "" : "', stream_name='", >+ (data->stream_name == NULL) >+ ? "" : data->stream_name, >+ (unsigned long long)open_persistent_id)); >+ goto done; >+ } >+ >+ DEBUG(10, ("share_mode_cleanup_disconnected: " >+ "cleaning up %u entries for file " >+ "(file-id='%s', servicepath='%s', " >+ "base_name='%s%s%s') " >+ "from open_persistent_id %llu\n", >+ data->num_share_modes, >+ file_id_string(frame, &fid), >+ data->servicepath, >+ data->base_name, >+ (data->stream_name == NULL) >+ ? "" : "', stream_name='", >+ (data->stream_name == NULL) >+ ? "" : data->stream_name, >+ (unsigned long long)open_persistent_id)); >+ >+ data->num_share_modes = 0; >+ data->modified = true; >+ >+ ret = true; >+done: >+ talloc_free(frame); >+ return ret; >+} >-- >1.7.9.5 > > >From a5835e24278674a24bcc0f6dff89332236ea39a6 Mon Sep 17 00:00:00 2001 >From: Gregor Beck <gbeck@sernet.de> >Date: Thu, 7 Feb 2013 15:26:37 +0100 >Subject: [PATCH 16/18] s3:smbd: add a scavenger process for disconnected > durable handles > >Pair-Programmed-With: Stefan Metzmacher <metze@samba.org> > >Signed-off-by: Gregor Beck <gbeck@sernet.de> >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Michael Adam <obnox@samba.org> >(cherry picked from commit 1ed22ba4b7998c1fc29476e931bd463f2bc1ba7e) > >Conflicts: > > source3/Makefile.in >--- > lib/util/debug.c | 1 + > lib/util/debug.h | 3 +- > source3/Makefile.in | 1 + > source3/librpc/idl/messaging.idl | 1 + > source3/smbd/scavenger.c | 531 ++++++++++++++++++++++++++++++++++++++ > source3/smbd/scavenger.h | 31 +++ > source3/smbd/server.c | 5 + > source3/wscript_build | 1 + > 8 files changed, 573 insertions(+), 1 deletion(-) > create mode 100644 source3/smbd/scavenger.c > create mode 100644 source3/smbd/scavenger.h > >diff --git a/lib/util/debug.c b/lib/util/debug.c >index 7509f90..6207b61 100644 >--- a/lib/util/debug.c >+++ b/lib/util/debug.c >@@ -176,6 +176,7 @@ static const char *default_classname_table[] = { > "msdfs", /* DBGC_MSDFS */ > "dmapi", /* DBGC_DMAPI */ > "registry", /* DBGC_REGISTRY */ >+ "scavenger", /* DBGC_SCAVENGER */ > NULL > }; > >diff --git a/lib/util/debug.h b/lib/util/debug.h >index 2566418..c61fd13 100644 >--- a/lib/util/debug.h >+++ b/lib/util/debug.h >@@ -79,9 +79,10 @@ bool dbghdr( int level, const char *location, const char *func); > #define DBGC_MSDFS 17 > #define DBGC_DMAPI 18 > #define DBGC_REGISTRY 19 >+#define DBGC_SCAVENGER 20 > > /* Always ensure this is updated when new fixed classes area added, to ensure the array in debug.c is the right size */ >-#define DBGC_MAX_FIXED 19 >+#define DBGC_MAX_FIXED 20 > > /* So you can define DBGC_CLASS before including debug.h */ > #ifndef DBGC_CLASS >diff --git a/source3/Makefile.in b/source3/Makefile.in >index fd6cdab..96727fc 100644 >--- a/source3/Makefile.in >+++ b/source3/Makefile.in >@@ -986,6 +986,7 @@ SMBD_OBJ_SRV = smbd/server_reload.o \ > smbd/smbXsrv_tcon.o \ > smbd/smbXsrv_open.o \ > smbd/durable.o \ >+ smbd/scavenger.o \ > $(MANGLE_OBJ) @VFS_STATIC@ > > SMBD_OBJ_BASE = $(PARAM_WITHOUT_REG_OBJ) $(SMBD_OBJ_SRV) $(LIBSMB_OBJ) \ >diff --git a/source3/librpc/idl/messaging.idl b/source3/librpc/idl/messaging.idl >index df1f321..c262889 100644 >--- a/source3/librpc/idl/messaging.idl >+++ b/source3/librpc/idl/messaging.idl >@@ -87,6 +87,7 @@ interface messaging > > /* Trigger a notify cleanup run */ > MSG_SMB_NOTIFY_CLEANUP = 0x0314, >+ MSG_SMB_SCAVENGER = 0x0315, > > /* winbind messages */ > MSG_WINBIND_FINISHED = 0x0401, >diff --git a/source3/smbd/scavenger.c b/source3/smbd/scavenger.c >new file mode 100644 >index 0000000..fe4e56e >--- /dev/null >+++ b/source3/smbd/scavenger.c >@@ -0,0 +1,531 @@ >+/* >+ Unix SMB/CIFS implementation. >+ smbd scavenger daemon >+ >+ Copyright (C) Gregor Beck 2013 >+ >+ This program is free software; you can redistribute it and/or modify >+ it under the terms of the GNU General Public License as published by >+ the Free Software Foundation; either version 3 of the License, or >+ (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program. If not, see <http://www.gnu.org/licenses/>. >+*/ >+ >+#include "includes.h" >+ >+#include "messages.h" >+#include "serverid.h" >+#include "smbd/globals.h" >+#include "smbd/scavenger.h" >+#include "locking/proto.h" >+#include "lib/util/util_process.h" >+ >+#undef DBGC_CLASS >+#define DBGC_CLASS DBGC_SCAVENGER >+ >+struct smbd_scavenger_state { >+ struct tevent_context *ev; >+ struct messaging_context *msg; >+ struct server_id parent_id; >+ struct server_id *scavenger_id; >+ bool am_scavenger; >+}; >+ >+static struct smbd_scavenger_state *smbd_scavenger_state = NULL; >+ >+struct scavenger_message { >+ struct file_id file_id; >+ uint64_t open_persistent_id; >+ NTTIME until; >+}; >+ >+static int smbd_scavenger_main(struct smbd_scavenger_state *state) >+{ >+ DEBUG(10, ("scavenger: %s started, parent: %s\n", >+ server_id_str(talloc_tos(), state->scavenger_id), >+ server_id_str(talloc_tos(), &state->parent_id))); >+ >+ while (true) { >+ TALLOC_CTX *frame = talloc_stackframe(); >+ int ret; >+ >+ ret = tevent_loop_once(state->ev); >+ if (ret != 0) { >+ DEBUG(2, ("tevent_loop_once failed: %s\n", >+ strerror(errno))); >+ TALLOC_FREE(frame); >+ return 1; >+ } >+ >+ DEBUG(10, ("scavenger: %s event loop iteration\n", >+ server_id_str(talloc_tos(), state->scavenger_id))); >+ TALLOC_FREE(frame); >+ } >+ >+ return 0; >+} >+ >+static void smbd_scavenger_done(struct tevent_context *event_ctx, struct tevent_fd *fde, >+ uint16_t flags, void *private_data) >+{ >+ struct smbd_scavenger_state *state = talloc_get_type_abort( >+ private_data, struct smbd_scavenger_state); >+ >+ DEBUG(2, ("scavenger: %s died\n", >+ server_id_str(talloc_tos(), state->scavenger_id))); >+ >+ TALLOC_FREE(state->scavenger_id); >+} >+ >+static void smbd_scavenger_parent_dead(struct tevent_context *event_ctx, >+ struct tevent_fd *fde, >+ uint16_t flags, void *private_data) >+{ >+ struct smbd_scavenger_state *state = talloc_get_type_abort( >+ private_data, struct smbd_scavenger_state); >+ >+ DEBUG(2, ("scavenger: %s parent %s died\n", >+ server_id_str(talloc_tos(), state->scavenger_id), >+ server_id_str(talloc_tos(), &state->parent_id))); >+ >+ exit_server("smbd_scavenger_parent_dead"); >+} >+ >+static void scavenger_sig_term_handler(struct tevent_context *ev, >+ struct tevent_signal *se, >+ int signum, >+ int count, >+ void *siginfo, >+ void *private_data) >+{ >+ exit_server_cleanly("termination signal"); >+} >+ >+static void scavenger_setup_sig_term_handler(struct tevent_context *ev_ctx) >+{ >+ struct tevent_signal *se; >+ >+ se = tevent_add_signal(ev_ctx, >+ ev_ctx, >+ SIGTERM, 0, >+ scavenger_sig_term_handler, >+ NULL); >+ if (se == NULL) { >+ exit_server("failed to setup SIGTERM handler"); >+ } >+} >+ >+static bool smbd_scavenger_running(struct smbd_scavenger_state *state) >+{ >+ if (state->scavenger_id == NULL) { >+ return false; >+ } >+ >+ return serverid_exists(state->scavenger_id); >+} >+ >+static int smbd_scavenger_server_id_destructor(struct server_id *id) >+{ >+ serverid_deregister(*id); >+ return 0; >+} >+ >+static bool scavenger_say_hello(int fd, struct server_id self) >+{ >+ const uint8_t *msg = (const uint8_t *)&self; >+ size_t remaining = sizeof(self); >+ size_t ofs = 0; >+ >+ while (remaining > 0) { >+ ssize_t ret; >+ >+ ret = sys_write(fd, msg + ofs, remaining); >+ if (ret == -1) { >+ DEBUG(2, ("Failed to write to pipe: %s\n", >+ strerror(errno))); >+ return false; >+ } >+ remaining -= ret; >+ } >+ >+ DEBUG(4, ("scavenger_say_hello: self[%s]\n", >+ server_id_str(talloc_tos(), &self))); >+ return true; >+} >+ >+static bool scavenger_wait_hello(int fd, struct server_id *child) >+{ >+ uint8_t *msg = (uint8_t *)child; >+ size_t remaining = sizeof(*child); >+ size_t ofs = 0; >+ >+ while (remaining > 0) { >+ ssize_t ret; >+ >+ ret = sys_read(fd, msg + ofs, remaining); >+ if (ret == -1) { >+ DEBUG(2, ("Failed to read from pipe: %s\n", >+ strerror(errno))); >+ return false; >+ } >+ remaining -= ret; >+ } >+ >+ DEBUG(4, ("scavenger_say_hello: child[%s]\n", >+ server_id_str(talloc_tos(), child))); >+ return true; >+} >+ >+static bool smbd_scavenger_start(struct smbd_scavenger_state *state) >+{ >+ struct server_id self = messaging_server_id(state->msg); >+ struct tevent_fd *fde = NULL; >+ int fds[2]; >+ int ret; >+ uint64_t unique_id; >+ bool ok; >+ >+ SMB_ASSERT(server_id_equal(&state->parent_id, &self)); >+ >+ if (smbd_scavenger_running(state)) { >+ DEBUG(10, ("scavenger %s already running\n", >+ server_id_str(talloc_tos(), >+ state->scavenger_id))); >+ return true; >+ } >+ >+ if (state->scavenger_id != NULL) { >+ DEBUG(10, ("scavenger zombie %s, cleaning up\n", >+ server_id_str(talloc_tos(), >+ state->scavenger_id))); >+ TALLOC_FREE(state->scavenger_id); >+ } >+ >+ state->scavenger_id = talloc_zero(state, struct server_id); >+ if (state->scavenger_id == NULL) { >+ DEBUG(2, ("Out of memory\n")); >+ goto fail; >+ } >+ talloc_set_destructor(state->scavenger_id, >+ smbd_scavenger_server_id_destructor); >+ >+ ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fds); >+ if (ret == -1) { >+ DEBUG(2, ("socketpair failed: %s", strerror(errno))); >+ goto fail; >+ } >+ >+ smb_set_close_on_exec(fds[0]); >+ smb_set_close_on_exec(fds[1]); >+ >+ unique_id = serverid_get_random_unique_id(); >+ >+ ret = fork(); >+ if (ret == -1) { >+ int err = errno; >+ close(fds[0]); >+ close(fds[1]); >+ DEBUG(0, ("fork failed: %s", strerror(err))); >+ goto fail; >+ } >+ >+ if (ret == 0) { >+ /* child */ >+ >+ NTSTATUS status; >+ >+ close(fds[0]); >+ >+ am_parent = NULL; >+ >+ set_my_unique_id(unique_id); >+ >+ status = reinit_after_fork(state->msg, state->ev, true); >+ if (!NT_STATUS_IS_OK(status)) { >+ DEBUG(2, ("reinit_after_fork failed: %s\n", >+ nt_errstr(status))); >+ exit_server("reinit_after_fork failed"); >+ return false; >+ } >+ >+ prctl_set_comment("smbd-scavenger"); >+ >+ state->am_scavenger = true; >+ *state->scavenger_id = messaging_server_id(state->msg); >+ >+ scavenger_setup_sig_term_handler(state->ev); >+ >+ serverid_register(*state->scavenger_id, FLAG_MSG_GENERAL); >+ >+ ok = scavenger_say_hello(fds[1], *state->scavenger_id); >+ if (!ok) { >+ DEBUG(2, ("scavenger_say_hello failed\n")); >+ exit_server("scavenger_say_hello failed"); >+ return false; >+ } >+ >+ fde = tevent_add_fd(state->ev, state->scavenger_id, >+ fds[1], TEVENT_FD_READ, >+ smbd_scavenger_parent_dead, state); >+ if (fde == NULL) { >+ DEBUG(2, ("tevent_add_fd(smbd_scavenger_parent_dead) " >+ "failed\n")); >+ exit_server("tevent_add_fd(smbd_scavenger_parent_dead) " >+ "failed"); >+ return false; >+ } >+ tevent_fd_set_auto_close(fde); >+ >+ ret = smbd_scavenger_main(state); >+ >+ DEBUG(10, ("scavenger ended: %d\n", ret)); >+ exit_server_cleanly("scavenger ended"); >+ return false; >+ } >+ >+ /* parent */ >+ close(fds[1]); >+ >+ ok = scavenger_wait_hello(fds[0], state->scavenger_id); >+ if (!ok) { >+ close(fds[0]); >+ goto fail; >+ } >+ >+ fde = tevent_add_fd(state->ev, state->scavenger_id, >+ fds[0], TEVENT_FD_READ, >+ smbd_scavenger_done, state); >+ if (fde == NULL) { >+ close(fds[0]); >+ goto fail; >+ } >+ tevent_fd_set_auto_close(fde); >+ >+ return true; >+fail: >+ TALLOC_FREE(state->scavenger_id); >+ return false; >+} >+ >+static void scavenger_add_timer(struct smbd_scavenger_state *state, >+ struct scavenger_message *msg); >+ >+static void smbd_scavenger_msg(struct messaging_context *msg_ctx, >+ void *private_data, >+ uint32_t msg_type, >+ struct server_id src, >+ DATA_BLOB *data) >+{ >+ struct smbd_scavenger_state *state = >+ talloc_get_type_abort(private_data, >+ struct smbd_scavenger_state); >+ TALLOC_CTX *frame = talloc_stackframe(); >+ struct server_id self = messaging_server_id(msg_ctx); >+ struct scavenger_message *msg = NULL; >+ >+ DEBUG(10, ("smbd_scavenger_msg: %s got message from %s\n", >+ server_id_str(talloc_tos(), &self), >+ server_id_str(talloc_tos(), &src))); >+ >+ if (server_id_equal(&state->parent_id, &self)) { >+ NTSTATUS status; >+ >+ if (!smbd_scavenger_running(state) && >+ !smbd_scavenger_start(state)) >+ { >+ DEBUG(2, ("Failed to start scavenger\n")); >+ goto done; >+ } >+ DEBUG(10, ("forwarding message to scavenger\n")); >+ >+ status = messaging_send(msg_ctx, >+ *state->scavenger_id, msg_type, data); >+ if (!NT_STATUS_IS_OK(status)) { >+ DEBUG(2, ("forwarding message to scavenger failed: " >+ "%s\n", nt_errstr(status))); >+ goto done; >+ } >+ goto done; >+ } >+ >+ if (!state->am_scavenger) { >+ DEBUG(10, ("im not the scavenger: ignore message\n")); >+ goto done; >+ } >+ >+ if (!server_id_equal(&state->parent_id, &src)) { >+ DEBUG(10, ("scavenger: ignore spurious message\n")); >+ goto done; >+ } >+ >+ DEBUG(10, ("scavenger: got a message\n")); >+ msg = (struct scavenger_message*)data->data; >+ scavenger_add_timer(state, msg); >+done: >+ talloc_free(frame); >+} >+ >+bool smbd_scavenger_init(TALLOC_CTX *mem_ctx, >+ struct messaging_context *msg, >+ struct tevent_context *ev) >+{ >+ struct smbd_scavenger_state *state; >+ NTSTATUS status; >+ >+ if (smbd_scavenger_state) { >+ DEBUG(10, ("smbd_scavenger_init called again\n")); >+ return true; >+ } >+ >+ state = talloc_zero(mem_ctx, struct smbd_scavenger_state); >+ if (state == NULL) { >+ DEBUG(2, ("Out of memory\n")); >+ return false; >+ } >+ >+ state->msg = msg; >+ state->ev = ev; >+ state->parent_id = messaging_server_id(msg); >+ >+ status = messaging_register(msg, state, MSG_SMB_SCAVENGER, >+ smbd_scavenger_msg); >+ if (!NT_STATUS_IS_OK(status)) { >+ DEBUG(2, ("failed to register message handler: %s\n", >+ nt_errstr(status))); >+ goto fail; >+ } >+ >+ smbd_scavenger_state = state; >+ return true; >+fail: >+ talloc_free(state); >+ return false; >+} >+ >+void scavenger_schedule_disconnected(struct files_struct *fsp) >+{ >+ NTSTATUS status; >+ struct server_id self = messaging_server_id(fsp->conn->sconn->msg_ctx); >+ struct timeval disconnect_time, until; >+ uint64_t timeout_usec; >+ struct scavenger_message msg; >+ DATA_BLOB msg_blob; >+ >+ nttime_to_timeval(&disconnect_time, fsp->op->global->disconnect_time); >+ timeout_usec = 1000 * fsp->op->global->durable_timeout_msec; >+ until = timeval_add(&disconnect_time, >+ timeout_usec / 1000000, >+ timeout_usec % 1000000); >+ >+ ZERO_STRUCT(msg); >+ msg.file_id = fsp->file_id; >+ msg.open_persistent_id = fsp->op->global->open_persistent_id; >+ msg.until = timeval_to_nttime(&until); >+ >+ DEBUG(10, ("smbd: %s mark file %s as disconnected at %s with timeout " >+ "at %s in %fs\n", >+ server_id_str(talloc_tos(), &self), >+ file_id_string_tos(&fsp->file_id), >+ timeval_string(talloc_tos(), &disconnect_time, true), >+ timeval_string(talloc_tos(), &until, true), >+ fsp->op->global->durable_timeout_msec/1000.0)); >+ >+ SMB_ASSERT(server_id_is_disconnected(&fsp->op->global->server_id)); >+ SMB_ASSERT(!server_id_equal(&self, &smbd_scavenger_state->parent_id)); >+ SMB_ASSERT(!smbd_scavenger_state->am_scavenger); >+ >+ msg_blob = data_blob_const(&msg, sizeof(msg)); >+ DEBUG(10, ("send message to scavenger\n")); >+ >+ status = messaging_send(smbd_scavenger_state->msg, >+ smbd_scavenger_state->parent_id, >+ MSG_SMB_SCAVENGER, >+ &msg_blob); >+ if (!NT_STATUS_IS_OK(status)) { >+ DEBUG(2, ("Failed to send message to parent smbd %s " >+ "from %s: %s\n", >+ server_id_str(talloc_tos(), >+ &smbd_scavenger_state->parent_id), >+ server_id_str(talloc_tos(), &self), >+ nt_errstr(status))); >+ } >+} >+ >+struct scavenger_timer_context { >+ struct smbd_scavenger_state *state; >+ struct scavenger_message msg; >+}; >+ >+static void scavenger_timer(struct tevent_context *ev, >+ struct tevent_timer *te, >+ struct timeval t, void *data) >+{ >+ struct scavenger_timer_context *ctx = >+ talloc_get_type_abort(data, struct scavenger_timer_context); >+ NTSTATUS status; >+ bool ok; >+ >+ DEBUG(10, ("scavenger: do cleanup for file %s at %s\n", >+ file_id_string_tos(&ctx->msg.file_id), >+ timeval_string(talloc_tos(), &t, true))); >+ >+ ok = share_mode_cleanup_disconnected(ctx->msg.file_id, >+ ctx->msg.open_persistent_id); >+ if (!ok) { >+ DEBUG(2, ("Failed to cleanup share modes and byte range locks " >+ "for file %s open %lu\n", >+ file_id_string_tos(&ctx->msg.file_id), >+ ctx->msg.open_persistent_id)); >+ } >+ >+ status = smbXsrv_open_cleanup(ctx->msg.open_persistent_id); >+ if (!NT_STATUS_IS_OK(status)) { >+ DEBUG(2, ("Failed to cleanup open global for file %s open %lu:" >+ " %s\n", file_id_string_tos(&ctx->msg.file_id), >+ ctx->msg.open_persistent_id, nt_errstr(status))); >+ } >+} >+ >+static void scavenger_add_timer(struct smbd_scavenger_state *state, >+ struct scavenger_message *msg) >+{ >+ struct tevent_timer *te; >+ struct scavenger_timer_context *ctx; >+ struct timeval until; >+ >+ nttime_to_timeval(&until, msg->until); >+ >+ DEBUG(10, ("scavenger: schedule file %s for cleanup at %s\n", >+ file_id_string_tos(&msg->file_id), >+ timeval_string(talloc_tos(), &until, true))); >+ >+ ctx = talloc_zero(state, struct scavenger_timer_context); >+ if (ctx == NULL) { >+ DEBUG(2, ("Failed to talloc_zero(scavenger_timer_context)\n")); >+ return; >+ } >+ >+ ctx->state = state; >+ ctx->msg = *msg; >+ >+ te = tevent_add_timer(state->ev, >+ state, >+ until, >+ scavenger_timer, >+ ctx); >+ if (te == NULL) { >+ DEBUG(2, ("Failed to add scavenger_timer event\n")); >+ talloc_free(ctx); >+ return; >+ } >+ >+ /* delete context after handler was running */ >+ talloc_steal(te, ctx); >+} >diff --git a/source3/smbd/scavenger.h b/source3/smbd/scavenger.h >new file mode 100644 >index 0000000..966c80d >--- /dev/null >+++ b/source3/smbd/scavenger.h >@@ -0,0 +1,31 @@ >+/* >+ Unix SMB/CIFS implementation. >+ smbd scavenger daemon >+ >+ Copyright (C) Gregor Beck 2013 >+ >+ This program is free software; you can redistribute it and/or modify >+ it under the terms of the GNU General Public License as published by >+ the Free Software Foundation; either version 3 of the License, or >+ (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program. If not, see <http://www.gnu.org/licenses/>. >+*/ >+ >+#ifndef _SCAVENGER_H_ >+#define _SCAVENGER_H_ >+ >+ >+bool smbd_scavenger_init(TALLOC_CTX *mem_ctx, >+ struct messaging_context *msg, >+ struct tevent_context *ev); >+ >+void scavenger_schedule_disconnected(struct files_struct *fsp); >+ >+#endif >diff --git a/source3/smbd/server.c b/source3/smbd/server.c >index 7113eae..e9bf9c9 100644 >--- a/source3/smbd/server.c >+++ b/source3/smbd/server.c >@@ -45,6 +45,7 @@ > #include "lib/conn_tdb.h" > #include "../lib/util/pidfile.h" > #include "lib/smbd_shim.h" >+#include "scavenger.h" > > struct smbd_open_socket; > struct smbd_child_pid; >@@ -1419,6 +1420,10 @@ extern void build_options(bool screen); > exit(1); > } > >+ if (!smbd_scavenger_init(NULL, msg_ctx, ev_ctx)) { >+ exit(1); >+ } >+ > if (!serverid_parent_init(ev_ctx)) { > exit(1); > } >diff --git a/source3/wscript_build b/source3/wscript_build >index 55d8bbd..c626e69 100755 >--- a/source3/wscript_build >+++ b/source3/wscript_build >@@ -382,6 +382,7 @@ SMBD_SRC_SRV = '''smbd/server_reload.c smbd/files.c smbd/connection.c > smbd/smbXsrv_open.c > smbd/server_exit.c > smbd/durable.c >+ smbd/scavenger.c > ${MANGLE_SRC}''' > > SMBD_SRC_BASE = '''${SMBD_SRC_SRV} >-- >1.7.9.5 > > >From 6a2ead8c40d0ba76275df7fa9155e1a44595a778 Mon Sep 17 00:00:00 2001 >From: Gregor Beck <gbeck@sernet.de> >Date: Wed, 20 Mar 2013 10:01:43 +0100 >Subject: [PATCH 17/18] s3:smbd: call scavenger_schedule_disconnected() from > close normal file for durable handles > >Signed-off-by: Gregor Beck <gbeck@sernet.de> >Reviewed-by: Michael Adam <obnox@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit c2ef5182e32fafeb3e279d9fc3a2a409e4aa0543) >--- > source3/smbd/close.c | 2 ++ > 1 file changed, 2 insertions(+) > >diff --git a/source3/smbd/close.c b/source3/smbd/close.c >index d0c843e..5dddf45 100644 >--- a/source3/smbd/close.c >+++ b/source3/smbd/close.c >@@ -24,6 +24,7 @@ > #include "printing.h" > #include "smbd/smbd.h" > #include "smbd/globals.h" >+#include "smbd/scavenger.h" > #include "fake_file.h" > #include "transfer_file.h" > #include "auth.h" >@@ -791,6 +792,7 @@ static NTSTATUS close_normal_file(struct smb_request *req, files_struct *fsp, > "proceeding with normal close\n", > fsp_str_dbg(fsp), nt_errstr(tmp))); > } >+ scavenger_schedule_disconnected(fsp); > } else { > DEBUG(1, ("Failed to disconnect durable handle for " > "file %s: %s - proceeding with normal " >-- >1.7.9.5 > > >From b8186e0d3074ed3a4f8b780e4354e3fae67255f5 Mon Sep 17 00:00:00 2001 >From: Michael Adam <obnox@samba.org> >Date: Thu, 18 Apr 2013 13:11:03 +0200 >Subject: [PATCH 18/18] s3:smbd:smb2: fix setting of scavenge timeout when > reconnecting durable handles > >The bug fixed with this commit led to reconnected durable handles >having a disconnect timeout of 0 msec. This fix re-establishes the >original timeout for the reconnected handle. > >Pair-Programmed-With: Stefan Metzmacher <metze@samba.org> > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Signed-off-by: Michael Adam <obnox@samba.org> >(cherry picked from commit beb9a27180e5570337381d03fac55bbe6d1637e0) >--- > source3/smbd/smb2_create.c | 9 ++++----- > 1 file changed, 4 insertions(+), 5 deletions(-) > >diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c >index ae0cdb3..c88224e 100644 >--- a/source3/smbd/smb2_create.c >+++ b/source3/smbd/smb2_create.c >@@ -839,11 +839,10 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx, > op->status = NT_STATUS_OK; > op->global->disconnect_time = 0; > >- status = smbXsrv_open_update(op); >- if (!NT_STATUS_IS_OK(status)) { >- tevent_req_nterror(req, status); >- return tevent_req_post(req, ev); >- } >+ /* save the timout for later update */ >+ durable_timeout_msec = op->global->durable_timeout_msec; >+ >+ update_open = true; > > info = FILE_WAS_OPENED; > } else { >-- >1.7.9.5 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Flags:
obnox
:
review+
jra
:
review+
Actions:
View
Attachments on
bug 9930
:
8944
|
8995
| 8999