]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/vfs/vfs_fsevents.c
xnu-792.10.96.tar.gz
[apple/xnu.git] / bsd / vfs / vfs_fsevents.c
index 5949b796ad1790168c259c60d27390feee63332f..3688244efe1c06ac46ee86a50b51cde3feed8515 100644 (file)
@@ -41,7 +41,6 @@
 #include <miscfs/specfs/specdev.h>
 #include <miscfs/devfs/devfs.h>
 #include <sys/filio.h>
-#include <architecture/byte_order.h>
 #include <kern/locks.h>
 #include <libkern/OSAtomic.h>
 
@@ -88,6 +87,7 @@ typedef struct fs_event_watcher {
     int32_t      eventq_size;            // number of event pointers in queue
     int32_t      rd, wr;                 // indices to the event_queue
     int32_t      blockers;
+    int32_t      num_readers;
 } fs_event_watcher;
 
 // fs_event_watcher flags
@@ -249,7 +249,7 @@ add_fsevent(int type, vfs_context_t ctx, ...)
     kfs_event        *kfse;
     fs_event_watcher *watcher;
     va_list           ap;
-    int              error = 0;
+    int              error = 0, base;
     dev_t             dev = 0;
 
     va_start(ap, ctx);
@@ -267,8 +267,9 @@ add_fsevent(int type, vfs_context_t ctx, ...)
     //       the lock is dropped.
     lock_fs_event_buf();
     
+    base = free_event_idx;
     for(i=0; i < MAX_KFS_EVENTS; i++) {
-       if (fs_event_buf[(free_event_idx + i) % MAX_KFS_EVENTS].type == FSE_INVALID) {
+       if (fs_event_buf[(base + i) % MAX_KFS_EVENTS].type == FSE_INVALID) {
            break;
        }
     }
@@ -290,12 +291,12 @@ add_fsevent(int type, vfs_context_t ctx, ...)
        return ENOSPC;
     }
 
-    kfse = &fs_event_buf[(free_event_idx + i) % MAX_KFS_EVENTS];
+    kfse = &fs_event_buf[(base + i) % MAX_KFS_EVENTS];
 
-    free_event_idx++;
+    free_event_idx = ((base + i) % MAX_KFS_EVENTS) + 1;
     
     kfse->type     = type;
-    kfse->refcount = 0;
+    kfse->refcount = 1;
     kfse->pid      = p->p_pid;
 
     unlock_fs_event_buf();  // at this point it's safe to unlock
@@ -462,9 +463,8 @@ add_fsevent(int type, vfs_context_t ctx, ...)
     
   clean_up:
     // just in case no one was interested after all...
-    if (num_deliveries == 0) {
+    if (OSAddAtomic(-1, (SInt32 *)&kfse->refcount) == 1) {
        do_free_event(kfse);
-       free_event_idx = (int)(kfse - &fs_event_buf[0]);
     }  
 
     lck_rw_done(&fsevent_big_lock);
@@ -479,8 +479,10 @@ do_free_event(kfs_event *kfse)
     
     lock_fs_event_buf();
     
-    // mark this fsevent as invalid
-    kfse->type = FSE_INVALID;
+    if (kfse->refcount > 0) {
+       panic("do_free_event: free'ing a kfsevent w/refcount == %d (kfse %p)\n",
+           kfse->refcount, kfse);
+    }
 
     // make a copy of this so we can free things without
     // holding the fs_event_buf lock
@@ -490,6 +492,9 @@ do_free_event(kfs_event *kfse)
     // and just to be anal, set this so that there are no args
     kfse->args[0].type = FSE_ARG_DONE;
     
+    // mark this fsevent as invalid
+    kfse->type = FSE_INVALID;
+
     free_event_idx = (kfse - fs_event_buf);
 
     unlock_fs_event_buf();
@@ -542,6 +547,7 @@ add_watcher(int8_t *event_list, int32_t num_events, int32_t eventq_size, fs_even
     watcher->rd           = 0;
     watcher->wr           = 0;
     watcher->blockers     = 0;
+    watcher->num_readers  = 0;
 
     lock_watch_list();
 
@@ -650,9 +656,15 @@ fmod_watch(fs_event_watcher *watcher, struct uio *uio)
        return EINVAL;
     }
 
+    if (OSAddAtomic(1, (SInt32 *)&watcher->num_readers) != 0) {
+       // don't allow multiple threads to read from the fd at the same time
+       OSAddAtomic(-1, (SInt32 *)&watcher->num_readers);
+       return EAGAIN;
+    }
 
     if (watcher->rd == watcher->wr) {
        if (watcher->flags & WATCHER_CLOSING) {
+           OSAddAtomic(-1, (SInt32 *)&watcher->num_readers);
            return 0;
        }
        OSAddAtomic(1, (SInt32 *)&watcher->blockers);
@@ -663,6 +675,7 @@ fmod_watch(fs_event_watcher *watcher, struct uio *uio)
        OSAddAtomic(-1, (SInt32 *)&watcher->blockers);
 
        if (error != 0 || (watcher->flags & WATCHER_CLOSING)) {
+           OSAddAtomic(-1, (SInt32 *)&watcher->num_readers);
            return error;
        }
     }
@@ -681,6 +694,7 @@ fmod_watch(fs_event_watcher *watcher, struct uio *uio)
        } 
 
        if (error) {
+           OSAddAtomic(-1, (SInt32 *)&watcher->num_readers);
            return error;
        }
        
@@ -850,6 +864,7 @@ fmod_watch(fs_event_watcher *watcher, struct uio *uio)
     }
 
   get_out:
+    OSAddAtomic(-1, (SInt32 *)&watcher->num_readers);
     return error;
 }
 
@@ -902,6 +917,9 @@ fsevent_unmount(struct mount *mp)
 
                        if (vname)
                                vnode_putname(vname);
+
+                       strcpy(pathbuff, "UNKNOWN-FILE");
+                       pathbuff_len = strlen(pathbuff) + 1;
                }
 
                // switch the type of the string