summaryrefslogtreecommitdiff
path: root/source4/ntvfs/common/notify.c
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2006-04-05 05:54:10 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 14:00:17 -0500
commit416d7b421001d00c4d494fceb4f2d0ab3e30cfaf (patch)
tree5551bf9f5e19d758417dff28b6b80fea16ad7b0c /source4/ntvfs/common/notify.c
parentbacf1152fc711560ed141fa8e6e470cbd9de6efc (diff)
downloadsamba-416d7b421001d00c4d494fceb4f2d0ab3e30cfaf.tar.gz
samba-416d7b421001d00c4d494fceb4f2d0ab3e30cfaf.tar.bz2
samba-416d7b421001d00c4d494fceb4f2d0ab3e30cfaf.zip
r14920: allow a notify backend to separately specify if it has handled the
given mask for the current directory and sub-directories. This allows us to setup the less efficient internal handling for subdirectories, while using the kernel inotify service for the current directory if available. It also allows inotify to handle only some of the filter bits, leaving the other filter bits for the user space handler. (This used to be commit 7c3d989fa44c7f57853a825337159f476d7dff80)
Diffstat (limited to 'source4/ntvfs/common/notify.c')
-rw-r--r--source4/ntvfs/common/notify.c61
1 files changed, 40 insertions, 21 deletions
diff --git a/source4/ntvfs/common/notify.c b/source4/ntvfs/common/notify.c
index 9ea024f2fc..e0d48d2b80 100644
--- a/source4/ntvfs/common/notify.c
+++ b/source4/ntvfs/common/notify.c
@@ -290,10 +290,11 @@ static NTSTATUS notify_add_array(struct notify_context *notify, struct notify_en
add a notify watch. This is called when a notify is first setup on a open
directory handle.
*/
-NTSTATUS notify_add(struct notify_context *notify, struct notify_entry *e,
+NTSTATUS notify_add(struct notify_context *notify, struct notify_entry *e0,
void (*callback)(void *, const struct notify_event *),
void *private)
{
+ struct notify_entry e = *e0;
NTSTATUS status;
struct notify_list *listel;
char *path = NULL;
@@ -304,8 +305,7 @@ NTSTATUS notify_add(struct notify_context *notify, struct notify_entry *e,
status = notify_load(notify);
if (!NT_STATUS_IS_OK(status)) {
- notify_unlock(notify);
- return status;
+ goto done;
}
notify->array->entries = talloc_realloc(notify->array, notify->array->entries,
@@ -313,18 +313,25 @@ NTSTATUS notify_add(struct notify_context *notify, struct notify_entry *e,
notify->array->num_entries+1);
if (notify->array->entries == NULL) {
- notify_unlock(notify);
- return NT_STATUS_NO_MEMORY;
+ status = NT_STATUS_NO_MEMORY;
+ goto done;
}
/* cope with /. on the end of the path */
- len = strlen(e->path);
- if (len > 1 && e->path[len-1] == '.' && e->path[len-2] == '/') {
- path = talloc_strndup(notify, e->path, len-2);
+ len = strlen(e.path);
+ if (len > 1 && e.path[len-1] == '.' && e.path[len-2] == '/') {
+ e.path = talloc_strndup(notify, e.path, len-2);
+ if (e.path == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
}
listel = talloc_zero(notify, struct notify_list);
- NT_STATUS_HAVE_NO_MEMORY(listel);
+ if (listel == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
listel->private = private;
listel->callback = callback;
@@ -332,22 +339,31 @@ NTSTATUS notify_add(struct notify_context *notify, struct notify_entry *e,
/* ignore failures from sys_notify */
if (notify->sys_notify_ctx != NULL) {
- status = sys_notify_watch(notify->sys_notify_ctx, e->path, e->filter,
+ /*
+ this call will modify e.filter and e.subdir_filter
+ to remove bits handled by the backend
+ */
+ status = sys_notify_watch(notify->sys_notify_ctx, &e,
sys_notify_callback, listel,
&listel->sys_notify_handle);
if (NT_STATUS_IS_OK(status)) {
- /* if the kernel handler has said it can handle this notify then
- we don't need to add it to the array */
talloc_steal(listel, listel->sys_notify_handle);
- goto done;
}
}
- status = notify_add_array(notify, e, path, private);
+ /* if the system notify handler couldn't handle some of the
+ filter bits, or couldn't handle a request for recursion
+ then we need to install it in the array used for the
+ intra-samba notify handling */
+ if (e.filter != 0 || e.subdir_filter != 0) {
+ status = notify_add_array(notify, &e, path, private);
+ }
done:
notify_unlock(notify);
- talloc_free(path);
+ if (e.path != e0->path) {
+ talloc_free(e.path);
+ }
return status;
}
@@ -483,8 +499,9 @@ static BOOL notify_match(struct notify_context *notify, struct notify_entry *e,
const char *path, uint32_t filter)
{
size_t len;
+ BOOL subdir;
- if (!(filter & e->filter)) {
+ if (!(filter & e->filter) && !(filter & e->subdir_filter)) {
return False;
}
@@ -498,13 +515,15 @@ static BOOL notify_match(struct notify_context *notify, struct notify_entry *e,
return False;
}
- if (!e->recursive) {
- if (strchr(&path[len+1], '/') != NULL) {
- return False;
- }
+ /* the filter and subdir_filter are handled separately, allowing a backend
+ to flexibly choose what it can handle */
+ subdir = (strchr(&path[len+1], '/') != NULL);
+
+ if (subdir) {
+ return (filter & e->subdir_filter) != 0;
}
- return True;
+ return (filter & e->filter) != 0;
}