[gamin] Inotify patch and crash fix



Yo,

Attached is a patch that updates gamin to the new inotify interface.
Because of pressure in the kernel world, we have switched from a char
device to a set of system calls. Changes are minimal, but they are not
API compatible.

The patch includes the removal of 1 assert in gam_node.c. This assert
was causing crashes for me everytime the gtk+ file selector was brought
up.



-- 
John McCutchan <ttb tentacle dhs org>
Index: server/gam_inotify.c
===================================================================
RCS file: /cvs/gnome/gamin/server/gam_inotify.c,v
retrieving revision 1.24
diff -u -r1.24 gam_inotify.c
--- server/gam_inotify.c	13 Jun 2005 09:13:45 -0000	1.24
+++ server/gam_inotify.c	12 Jul 2005 17:47:50 -0000
@@ -27,6 +27,7 @@
 #include <unistd.h>
 #include <sys/ioctl.h>
 #include <stdio.h>
+#include <string.h>
 #include <glib.h>
 #include "gam_error.h"
 #include "gam_poll.h"
@@ -44,15 +45,22 @@
 #include "gam_debugging.h"
 #endif
 
+#include <errno.h>
+
+#define INOTIFY_INIT 291
+#define INOTIFY_ADD 292
+#define INOTIFY_RM 293
+
 typedef struct {
     char *path;
     int wd;
     int refcount;
-    GList *subs;
     int busy;
     gboolean deactivated;
+    gboolean ignored;
     int events;
     int deactivated_events;
+    int ignored_events;
 } inotify_data_t;
 
 static GHashTable *path_hash = NULL;
@@ -77,8 +85,9 @@
         return;
 
     int deactivated = data->deactivated;
+    int ignored = data->ignored;
 
-    GAM_DEBUG(DEBUG_INFO, "isub wd %d refs %d busy %d deactivated %d events (%d:%d): %s\n", data->wd, data->refcount, data->busy, deactivated, data->events, data->deactivated_events, data->path);
+    GAM_DEBUG(DEBUG_INFO, "isub wd %d refs %d busy %d deactivated %d ignored %d events (%d:%d:%d): %s\n", data->wd, data->refcount, data->busy, deactivated, ignored, data->events, data->deactivated_events, data->ignored_events, data->path);
 }
 
 void
@@ -163,13 +172,18 @@
 {
     inotify_data_t *data;
 
+    g_assert (wd >= 0);
+
     data = g_new0(inotify_data_t, 1);
     data->path = g_strdup(path);
     data->wd = wd;
-    data->busy = 0;
     data->refcount = 1;
-    data->deactivated_events = 0;
+    data->busy = 0;
+    data->deactivated = FALSE;
+    data->ignored = FALSE;
     data->events = 0;
+    data->deactivated_events = 0;
+    data->ignored_events = 0;
 
     return data;
 }
@@ -187,8 +201,7 @@
 gam_inotify_directory_handler_internal(const char *path, pollHandlerMode mode)
 {
     inotify_data_t *data;
-    int path_fd, path_wd;
-    struct inotify_watch_request iwr;
+    int path_wd = -1;
     switch (mode) {
         case GAMIN_ACTIVATE:
 	    GAM_DEBUG(DEBUG_INFO, "Adding %s to inotify\n", path);
@@ -211,7 +224,6 @@
     G_LOCK(inotify);
 
     if (mode == GAMIN_ACTIVATE) {
-
         if ((data = g_hash_table_lookup(path_hash, path)) != NULL) {
             data->refcount++;
 	    GAM_DEBUG(DEBUG_INFO, "  found incremented refcount: %d\n",
@@ -224,17 +236,15 @@
             return;
         }
 
-        path_fd = open(path, O_RDONLY);
+	path_wd = syscall (INOTIFY_ADD, inotify_device_fd, path, should_poll_mask);
 
-        if (path_fd < 0) {
-            G_UNLOCK(inotify);
-            return;
-        }
-
-	iwr.fd = path_fd;
-	iwr.mask = should_poll_mask;
-	path_wd = ioctl (inotify_device_fd, INOTIFY_WATCH, &iwr);
-	close (path_fd);
+	if (path_wd < 0) {
+		int e = errno;
+		GAM_DEBUG(DEBUG_INFO, "INOTIFY_ADD failed for %s\n", path);
+		GAM_DEBUG(DEBUG_INFO, "Error = %s\n", strerror(e));
+		G_UNLOCK(inotify);
+		return;
+	}
 
         data = gam_inotify_data_new(path, path_wd);
         g_hash_table_insert(wd_hash, GINT_TO_POINTER(data->wd), data);
@@ -260,17 +270,31 @@
 
         if (data->refcount == 0) {
 	    int wd = data->wd;
+	    g_assert (data->wd >= 0);
 	    GAM_DEBUG(DEBUG_INFO, "removed inotify watch for %s\n", 
                     data->path);
 	    g_hash_table_remove(path_hash, data->path);
 	    g_hash_table_remove(wd_hash, GINT_TO_POINTER(data->wd));
-	    gam_inotify_data_free(data);
-	    if (ioctl (inotify_device_fd, INOTIFY_IGNORE, &wd) < 0) {
-		GAM_DEBUG (DEBUG_INFO, "INOTIFY_IGNORE failed for %s (wd = %d)\n", data->path, data->wd);
+
+	    if (data->ignored) {
+		    GAM_DEBUG(DEBUG_INFO, "INOTIFY_IGNORE IGNORED for %s (wd = %d)\n", data->path, data->wd);
+	    }
+	    if (data->deactivated == FALSE) {
+		    if (syscall (INOTIFY_RM, inotify_device_fd, wd) < 0) {
+			int e = errno;
+			GAM_DEBUG (DEBUG_INFO, "INOTIFY_IGNORE failed for %s (wd = %d)\n", data->path, data->wd);
+
+			GAM_DEBUG(DEBUG_INFO, "reason = %s\n", strerror (e));
+		    } else {
+			GAM_DEBUG (DEBUG_INFO, "INOTIFY_IGNORE success for %s (wd = %d)\n", data->path, data->wd);
+		    }
+	    } else {
+		    GAM_DEBUG (DEBUG_INFO, "removed deactivated inotify watch for %s\n", data->path);
 	    }
 #ifdef GAMIN_DEBUG_API
 	    gam_debug_report(GAMinotifyDelete, data->path, 0);
 #endif
+	    gam_inotify_data_free(data);
         } else {
 	    GAM_DEBUG(DEBUG_INFO, "  found decremented refcount: %d\n",
 	              data->refcount);
@@ -283,16 +307,19 @@
         data = g_hash_table_lookup(path_hash, path);
         if (!data) {
             GAM_DEBUG(DEBUG_INFO, "  not found !!!\n");
-
             G_UNLOCK(inotify);
             return;
         }
         if (data != NULL) {
 	    if (mode == GAMIN_FLOWCONTROLSTART) {
 		GAM_DEBUG(DEBUG_INFO, "inotify: GAMIN_FLOWCONTROLSTART for %s\n", data->path);
-		if (data->wd >= 0) {
-		    if (ioctl (inotify_device_fd, INOTIFY_IGNORE, &data->wd) < 0) {
+		if (!data->deactivated) {
+		    if (syscall (INOTIFY_RM, inotify_device_fd, data->wd) < 0) {
+			int e = errno;
 			GAM_DEBUG (DEBUG_INFO, "INOTIFY_IGNORE failed for %s (wd = %d)\n", data->path, data->wd);
+			GAM_DEBUG(DEBUG_INFO, "reason = %s\n", strerror (e));
+		    } else {
+			GAM_DEBUG (DEBUG_INFO, "INOTIFY_IGNORE success for %s (wd = %d)\n", data->path, data->wd);
 		    }
 		    data->deactivated = TRUE;
 		    GAM_DEBUG(DEBUG_INFO, "deactivated inotify for %s\n",
@@ -300,6 +327,8 @@
 #ifdef GAMIN_DEBUG_API
 		    gam_debug_report(GAMinotifyFlowOn, data->path, 0);
 #endif
+		} else {
+			GAM_DEBUG(DEBUG_INFO, "inotify: GAMIN_FLOWCONTROLSTART for %s -- AGAIN!!!!\n", data->path);
 		}
 		data->busy++;
 	    } else {
@@ -309,24 +338,24 @@
 		    data->busy--;
 		    if (data->busy == 0) {
 			GAM_DEBUG(DEBUG_INFO, "inotify: data->busy == 0 for %s\n", data->path);
-			path_fd = open(data->path, O_RDONLY);
-			if (path_fd < 0) {
+
+			path_wd = syscall (INOTIFY_ADD, inotify_device_fd, data->path, should_poll_mask);
+
+			if (path_wd < 0) {
+			    int e = errno;
 			    G_UNLOCK(inotify);
 			    GAM_DEBUG(DEBUG_INFO,
 			              "failed to reactivate inotify for %s\n",
 				      data->path);
+			    GAM_DEBUG(DEBUG_INFO, "reason = %s\n", strerror (e));
 
                             return;
 			}
-
-			iwr.fd = path_fd;
-			iwr.mask = should_poll_mask;
-			path_wd = ioctl (inotify_device_fd, INOTIFY_WATCH, &iwr);
-			close (path_fd);
+			g_assert (data->wd >= 0);
+			g_assert (path_wd >= 0);
 
 			/* Remove the old wd from the hash table */
 			g_hash_table_remove(wd_hash, GINT_TO_POINTER(data->wd));
-
 			data->wd = path_wd;
 			data->deactivated = FALSE;
 
@@ -419,21 +448,13 @@
 	} else if (data->deactivated) {
 	    GAM_DEBUG(DEBUG_INFO, "inotify: ignoring event on temporarily deactivated watch %s\n", data->path);
             data->deactivated_events++;
-	} else {
+	} else if (data->ignored) {
+            GAM_DEBUG(DEBUG_INFO, "inotify: got event on ignored watch %s\n", data->path);
+        } else {
 	    if (event->mask == IN_IGNORED) {
-		GList *l;
-
 		GAM_DEBUG(DEBUG_INFO, "inotify: IN_IGNORE on wd=%d\n", event->wd);
-		GAM_DEBUG(DEBUG_INFO, "inotify: removing all subscriptions for %s\n", data->path);
-
-                data->events++;
-
-		l = data->subs;
-		data->subs = NULL;
-		for (l = l; l; l = l->next) {
-		    GamSubscription *sub = l->data;
-		    gam_inotify_remove_subscription (sub);
-		}
+                data->ignored = TRUE;
+                data->ignored_events++;
 	    } else if (event->mask != IN_Q_OVERFLOW) {
 		if (event->mask & should_poll_mask) {
 		    GAM_DEBUG(DEBUG_INFO, "inotify requesting poll for %s\n", data->path);
@@ -513,10 +534,11 @@
 
     g_return_val_if_fail(gam_poll_init_full(FALSE), FALSE);
 
-    inotify_device_fd = open("/dev/inotify", O_RDONLY);
+    inotify_device_fd = syscall(INOTIFY_INIT);
 
     if (inotify_device_fd < 0) {
         GAM_DEBUG(DEBUG_INFO, "Could not open /dev/inotify\n");
+	GAM_DEBUG(DEBUG_INFO, "fd = %d\n", inotify_device_fd);
         return FALSE;
     }
 
Index: server/gam_node.c
===================================================================
RCS file: /cvs/gnome/gamin/server/gam_node.c,v
retrieving revision 1.12
diff -u -r1.12 gam_node.c
--- server/gam_node.c	13 Jun 2005 14:58:07 -0000	1.12
+++ server/gam_node.c	12 Jul 2005 17:47:50 -0000
@@ -189,7 +189,9 @@
 gam_node_remove_subscription(GamNode * node, GamSubscription * sub)
 {
     g_assert(node);
-    g_assert(g_list_find(node->subs, sub));
+
+    if (!g_list_find (node->subs, sub))
+	    return TRUE;
 
     node->subs = g_list_remove_all(node->subs, sub);
 
Index: server/local_inotify.h
===================================================================
RCS file: /cvs/gnome/gamin/server/local_inotify.h,v
retrieving revision 1.8
diff -u -r1.8 local_inotify.h
--- server/local_inotify.h	10 May 2005 09:29:52 -0000	1.8
+++ server/local_inotify.h	12 Jul 2005 17:47:50 -0000
@@ -23,16 +23,6 @@
 	char		name[0];	/* stub for possible name */
 };
 
-/*
- * struct inotify_watch_request - represents a watch request
- *
- * Pass to the inotify device via the INOTIFY_WATCH ioctl
- */
-struct inotify_watch_request {
-	int		fd;		/* fd of filename to watch */
-	__u32		mask;		/* event mask */
-};
-
 /* the following are legal, implemented events that user-space can watch for */
 #define IN_ACCESS		0x00000001	/* File was accessed */
 #define IN_MODIFY		0x00000002	/* File was modified */
@@ -68,12 +58,6 @@
 			 IN_CLOSE_NOWRITE | IN_OPEN | IN_MOVED_FROM | \
 			 IN_MOVED_TO | IN_DELETE | IN_CREATE | IN_DELETE_SELF)
 
-#define INOTIFY_IOCTL_MAGIC	'Q'
-#define INOTIFY_IOCTL_MAXNR	2
-
-#define INOTIFY_WATCH  		_IOR(INOTIFY_IOCTL_MAGIC, 1, struct inotify_watch_request)
-#define INOTIFY_IGNORE 		_IOR(INOTIFY_IOCTL_MAGIC, 2, int)
-
 #ifdef __KERNEL__
 
 #include <linux/dcache.h>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]