summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVolker Lendecke <vlendec@samba.org>2007-02-02 11:34:16 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 12:17:40 -0500
commitf4c3d1543d94ea0bc6e65c9635ab9250fc9d8921 (patch)
tree5d804e5959602c21ddcf95df234e675352abb0eb
parent52b5ca933bf20b8ad295c837ab00de8bbd6a8e2c (diff)
downloadsamba-f4c3d1543d94ea0bc6e65c9635ab9250fc9d8921.tar.gz
samba-f4c3d1543d94ea0bc6e65c9635ab9250fc9d8921.tar.bz2
samba-f4c3d1543d94ea0bc6e65c9635ab9250fc9d8921.zip
r21120: Make notify a bit more robust: Delete the notify records if we figured out
that the process holding it is not around anymore. Tridge, please review this and possibly also include it in 4. We can discuss the error message for "unknown target" from messaging_send, INVALID_HANDLE seemed to be most appropriate to me. Volker (This used to be commit 3b3ed7429e54b571375914e473eafc9888b5b204)
-rw-r--r--source3/smbd/notify_internal.c48
1 files changed, 34 insertions, 14 deletions
diff --git a/source3/smbd/notify_internal.c b/source3/smbd/notify_internal.c
index afa4e0922b..885c85fbc8 100644
--- a/source3/smbd/notify_internal.c
+++ b/source3/smbd/notify_internal.c
@@ -51,7 +51,8 @@ struct notify_list {
#define NOTIFY_ENABLE "notify:enable"
#define NOTIFY_ENABLE_DEFAULT True
-static NTSTATUS notify_remove_all(struct notify_context *notify);
+static NTSTATUS notify_remove_all(struct notify_context *notify,
+ const struct server_id *server);
static void notify_handler(struct messaging_context *msg_ctx, void *private_data,
uint32_t msg_type, struct server_id server_id, DATA_BLOB *data);
@@ -61,7 +62,11 @@ static void notify_handler(struct messaging_context *msg_ctx, void *private_data
static int notify_destructor(struct notify_context *notify)
{
messaging_deregister(notify->messaging_ctx, MSG_PVFS_NOTIFY, notify);
- notify_remove_all(notify);
+
+ if (notify->list != NULL) {
+ notify_remove_all(notify, &notify->server);
+ }
+
return 0;
}
@@ -164,6 +169,11 @@ static NTSTATUS notify_load(struct notify_context *notify)
status = ndr_pull_struct_blob(&blob, notify->array, notify->array,
(ndr_pull_flags_fn_t)ndr_pull_notify_array);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_DEBUG(notify_array, notify->array);
+ }
+
free(dbuf.dptr);
return status;
@@ -480,17 +490,14 @@ NTSTATUS notify_remove(struct notify_context *notify, void *private_data)
}
/*
- remove all notify watches for this messaging server
+ remove all notify watches for a messaging server
*/
-static NTSTATUS notify_remove_all(struct notify_context *notify)
+static NTSTATUS notify_remove_all(struct notify_context *notify,
+ const struct server_id *server)
{
NTSTATUS status;
int i, depth, del_count=0;
- if (notify->list == NULL) {
- return NT_STATUS_OK;
- }
-
status = notify_lock(notify);
NT_STATUS_NOT_OK_RETURN(status);
@@ -501,11 +508,11 @@ static NTSTATUS notify_remove_all(struct notify_context *notify)
}
/* we have to search for all entries across all depths, looking for matches
- for our server id */
+ for the server id */
for (depth=0;depth<notify->array->num_depths;depth++) {
struct notify_depth *d = &notify->array->depth[depth];
for (i=0;i<d->num_entries;i++) {
- if (cluster_id_equal(&notify->server, &d->entries[i].server)) {
+ if (cluster_id_equal(server, &d->entries[i].server)) {
if (i < d->num_entries-1) {
memmove(&d->entries[i], &d->entries[i+1],
sizeof(d->entries[i])*(d->num_entries-(i+1)));
@@ -530,8 +537,8 @@ static NTSTATUS notify_remove_all(struct notify_context *notify)
/*
send a notify message to another messaging server
*/
-static void notify_send(struct notify_context *notify, struct notify_entry *e,
- const char *path, uint32_t action)
+static NTSTATUS notify_send(struct notify_context *notify, struct notify_entry *e,
+ const char *path, uint32_t action)
{
struct notify_event ev;
DATA_BLOB data;
@@ -548,12 +555,13 @@ static void notify_send(struct notify_context *notify, struct notify_entry *e,
(ndr_push_flags_fn_t)ndr_push_notify_event);
if (!NT_STATUS_IS_OK(status)) {
talloc_free(tmp_ctx);
- return;
+ return status;
}
status = messaging_send(notify->messaging_ctx, e->server,
MSG_PVFS_NOTIFY, &data);
talloc_free(tmp_ctx);
+ return status;
}
@@ -579,6 +587,7 @@ void notify_trigger(struct notify_context *notify,
return;
}
+ again:
status = notify_load(notify);
if (!NT_STATUS_IS_OK(status)) {
return;
@@ -653,7 +662,18 @@ void notify_trigger(struct notify_context *notify,
continue;
}
}
- notify_send(notify, e, path + e->path_len + 1, action);
+ status = notify_send(notify, e, path + e->path_len + 1,
+ action);
+
+ if (NT_STATUS_EQUAL(
+ status, NT_STATUS_INVALID_HANDLE)) {
+
+ DEBUG(10, ("Deleting notify entries for "
+ "process %s because it's gone\n",
+ procid_str_static(&e->server.id)));
+ notify_remove_all(notify, &e->server);
+ goto again;
+ }
}
}
}