svn commit: samba r14920 - in branches/SAMBA_4_0/source/ntvfs: common posix sysdep

tridge at samba.org tridge at samba.org
Wed Apr 5 05:54:10 GMT 2006


Author: tridge
Date: 2006-04-05 05:54:10 +0000 (Wed, 05 Apr 2006)
New Revision: 14920

WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=14920

Log:

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.

Modified:
   branches/SAMBA_4_0/source/ntvfs/common/notify.c
   branches/SAMBA_4_0/source/ntvfs/posix/pvfs_notify.c
   branches/SAMBA_4_0/source/ntvfs/sysdep/inotify.c
   branches/SAMBA_4_0/source/ntvfs/sysdep/sys_notify.c
   branches/SAMBA_4_0/source/ntvfs/sysdep/sys_notify.h


Changeset:
Modified: branches/SAMBA_4_0/source/ntvfs/common/notify.c
===================================================================
--- branches/SAMBA_4_0/source/ntvfs/common/notify.c	2006-04-05 05:05:49 UTC (rev 14919)
+++ branches/SAMBA_4_0/source/ntvfs/common/notify.c	2006-04-05 05:54:10 UTC (rev 14920)
@@ -290,10 +290,11 @@
   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 @@
 
 	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 @@
 						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 @@
 
 	/* 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 @@
 			 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 @@
 		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;
 }
 
 

Modified: branches/SAMBA_4_0/source/ntvfs/posix/pvfs_notify.c
===================================================================
--- branches/SAMBA_4_0/source/ntvfs/posix/pvfs_notify.c	2006-04-05 05:05:49 UTC (rev 14919)
+++ branches/SAMBA_4_0/source/ntvfs/posix/pvfs_notify.c	2006-04-05 05:54:10 UTC (rev 14920)
@@ -145,7 +145,11 @@
 
 	e.filter    = filter;
 	e.path      = f->handle->name->full_name;
-	e.recursive = recursive;
+	if (recursive) {
+		e.subdir_filter = filter;
+	} else {
+		e.subdir_filter = 0;
+	}
 
 	status = notify_add(pvfs->notify_context, &e, 
 			    pvfs_notify_callback, f->notify_buffer);

Modified: branches/SAMBA_4_0/source/ntvfs/sysdep/inotify.c
===================================================================
--- branches/SAMBA_4_0/source/ntvfs/sysdep/inotify.c	2006-04-05 05:05:49 UTC (rev 14919)
+++ branches/SAMBA_4_0/source/ntvfs/sysdep/inotify.c	2006-04-05 05:54:10 UTC (rev 14920)
@@ -190,13 +190,15 @@
 
 
 /*
-  map from a change notify mask to a inotify mask. Approximate only :(
+  map from a change notify mask to a inotify mask. Remove any bits
+  which we can handle
 */
 static const struct {
 	uint32_t notify_mask;
 	uint32_t inotify_mask;
 } inotify_mapping[] = {
 	{FILE_NOTIFY_CHANGE_FILE_NAME,  IN_CREATE|IN_DELETE|IN_MOVED_FROM|IN_MOVED_TO},
+	{FILE_NOTIFY_CHANGE_DIR_NAME,   IN_CREATE|IN_DELETE|IN_MOVED_FROM|IN_MOVED_TO},
 	{FILE_NOTIFY_CHANGE_ATTRIBUTES, IN_ATTRIB},
 	{FILE_NOTIFY_CHANGE_SIZE,       IN_MODIFY},
 	{FILE_NOTIFY_CHANGE_LAST_WRITE, IN_ATTRIB},
@@ -204,13 +206,14 @@
 	{FILE_NOTIFY_CHANGE_SECURITY,   IN_ATTRIB}
 };
 
-static uint32_t inotify_map(uint32_t mask)
+static uint32_t inotify_map(struct notify_entry *e)
 {
 	int i;
 	uint32_t out=0;
 	for (i=0;i<ARRAY_SIZE(inotify_mapping);i++) {
-		if (inotify_mapping[i].notify_mask & mask) {
+		if (inotify_mapping[i].notify_mask & e->filter) {
 			out |= inotify_mapping[i].inotify_mask;
+			e->filter &= ~inotify_mapping[i].notify_mask;
 		}
 	}
 	return out;
@@ -241,14 +244,15 @@
   add a watch. The watch is removed when the caller calls
   talloc_free() on *handle
 */
-static NTSTATUS inotify_watch(struct sys_notify_context *ctx, const char *dirpath,
-			      uint32_t filter, sys_notify_callback_t callback,
-			      void *private, void **handle)
+static NTSTATUS inotify_watch(struct sys_notify_context *ctx, struct notify_entry *e,
+			      sys_notify_callback_t callback, void *private, 
+			      void **handle)
 {
 	struct inotify_private *in;
 	int wd;
 	uint32_t mask;
 	struct watch_context *w;
+	uint32_t filter = e->filter;
 
 	/* maybe setup the inotify fd */
 	if (ctx->private == NULL) {
@@ -259,7 +263,7 @@
 
 	in = talloc_get_type(ctx->private, struct inotify_private);
 
-	mask = inotify_map(filter);
+	mask = inotify_map(e);
 	if (mask == 0) {
 		/* this filter can't be handled by inotify */
 		return NT_STATUS_INVALID_PARAMETER;
@@ -270,14 +274,16 @@
 	mask |= (IN_MASK_ADD | IN_ONLYDIR);
 
 	/* get a new watch descriptor for this path */
-	wd = inotify_add_watch(in->fd, dirpath, mask);
+	wd = inotify_add_watch(in->fd, e->path, mask);
 	if (wd == -1) {
+		e->filter = filter;
 		return map_nt_error_from_unix(errno);
 	}
 
 	w = talloc(in, struct watch_context);
 	if (w == NULL) {
 		inotify_rm_watch(in->fd, wd);
+		e->filter = filter;
 		return NT_STATUS_NO_MEMORY;
 	}
 

Modified: branches/SAMBA_4_0/source/ntvfs/sysdep/sys_notify.c
===================================================================
--- branches/SAMBA_4_0/source/ntvfs/sysdep/sys_notify.c	2006-04-05 05:05:49 UTC (rev 14919)
+++ branches/SAMBA_4_0/source/ntvfs/sysdep/sys_notify.c	2006-04-05 05:54:10 UTC (rev 14920)
@@ -31,8 +31,8 @@
 
 /* list of registered backends */
 static struct sys_notify_backend *backends;
+static uint32_t num_backends;
 
-
 /*
   initialise a system change notify backend
 */
@@ -43,8 +43,9 @@
 	struct sys_notify_context *ctx;
 	const char *bname;
 	struct sys_notify_backend *b;
+	int i;
 
-	if (backends == NULL) {
+	if (num_backends == 0) {
 		return NULL;
 	}
 
@@ -61,16 +62,16 @@
 
 	bname = lp_parm_string(snum, "notify", "backend");
 	if (!bname) {
-		if (backends) {
-			bname = backends->name;
+		if (num_backends) {
+			bname = backends[0].name;
 		} else {
 			bname = "__unknown__";
 		}
 	}
 
-	for (b=backends;b;b=b->next) {
-		if (strcasecmp(b->name, bname) == 0) {
-			bname = b->name;
+	for (i=0;i<num_backends;i++) {
+		if (strcasecmp(backends[i].name, bname) == 0) {
+			bname = backends[i].name;
 			break;
 		}
 	}
@@ -78,8 +79,8 @@
 	ctx->name = bname;
 	ctx->notify_watch = NULL;
 
-	if (b != NULL) {
-		ctx->notify_watch = b->notify_watch;
+	if (i < num_backends) {
+		ctx->notify_watch = backends[i].notify_watch;
 	}
 
 	return ctx;
@@ -87,15 +88,18 @@
 
 /*
   add a watch
+
+  note that this call must modify the e->filter and e->subdir_filter
+  bits to remove ones handled by this backend. Any remaining bits will
+  be handled by the generic notify layer
 */
-NTSTATUS sys_notify_watch(struct sys_notify_context *ctx, const char *dirpath,
-			  uint32_t filter, sys_notify_callback_t callback,
-			  void *private, void **handle)
+NTSTATUS sys_notify_watch(struct sys_notify_context *ctx, struct notify_entry *e,
+			  sys_notify_callback_t callback, void *private, void **handle)
 {
 	if (!ctx->notify_watch) {
 		return NT_STATUS_NOT_IMPLEMENTED;
 	}
-	return ctx->notify_watch(ctx, dirpath, filter, callback, private, handle);
+	return ctx->notify_watch(ctx, e, callback, private, handle);
 }
 
 /*
@@ -103,6 +107,12 @@
 */
 NTSTATUS sys_notify_register(struct sys_notify_backend *backend)
 {
-	DLIST_ADD(backends, backend);
+	struct sys_notify_backend *b;
+	b = talloc_realloc(talloc_autofree_context(), backends, 
+			   struct sys_notify_backend, num_backends+1);
+	NT_STATUS_HAVE_NO_MEMORY(b);
+	backends = b;
+	backends[num_backends] = *backend;
+	num_backends++;
 	return NT_STATUS_OK;
 }

Modified: branches/SAMBA_4_0/source/ntvfs/sysdep/sys_notify.h
===================================================================
--- branches/SAMBA_4_0/source/ntvfs/sysdep/sys_notify.h	2006-04-05 05:05:49 UTC (rev 14919)
+++ branches/SAMBA_4_0/source/ntvfs/sysdep/sys_notify.h	2006-04-05 05:54:10 UTC (rev 14920)
@@ -25,28 +25,27 @@
 typedef void (*sys_notify_callback_t)(struct sys_notify_context *, 
 				      void *, struct notify_event *ev);
 
+typedef NTSTATUS (*notify_watch_t)(struct sys_notify_context *ctx, 
+				   struct notify_event *e,
+				   sys_notify_callback_t callback, void *private, 
+				   void **handle);
+
 struct sys_notify_context {
 	struct event_context *ev;
 	void *private; /* for use of backend */
-	NTSTATUS (*notify_watch)(struct sys_notify_context *ctx, const char *dirpath,
-				 uint32_t filter, sys_notify_callback_t callback,
-				 void *private, void **handle);
 	const char *name;
+	notify_watch_t notify_watch;
 };
 
 struct sys_notify_backend {
-	struct sys_notify_backend *next, *prev;
 	const char *name;
-	NTSTATUS (*notify_watch)(struct sys_notify_context *ctx, const char *dirpath,
-				 uint32_t filter, sys_notify_callback_t callback,
-				 void *private, void **handle);
+	notify_watch_t notify_watch;
 };
 
 NTSTATUS sys_notify_register(struct sys_notify_backend *backend);
 struct sys_notify_context *sys_notify_init(int snum,
 					   TALLOC_CTX *mem_ctx, 
 					   struct event_context *ev);
-NTSTATUS sys_notify_watch(struct sys_notify_context *ctx, const char *dirpath,
-			  uint32_t filter, sys_notify_callback_t callback,
-			  void *private, void **handle);
-
+NTSTATUS sys_notify_watch(struct sys_notify_context *ctx, struct notify_entry *e,
+			  sys_notify_callback_t callback, void *private, 
+			  void **handle);



More information about the samba-cvs mailing list