Make event watcher lists volume-specific.
authorcoderain <coderain@sdf.org>
Sun, 23 Jul 2017 04:15:00 +0000 (06:15 +0200)
committercoderain <coderain@sdf.org>
Sun, 23 Jul 2017 04:15:00 +0000 (06:15 +0200)
kernel/include/filesystem.h
kernel/src/filesystem.c

index f104596dba97889387f78ce1d9d2aac2b9b488a5..3ea3fb360401e094d1d75f62bd67887946310764 100644 (file)
@@ -150,6 +150,8 @@ struct mounted_volume
     device_t *device;
     qword_t open_files;
     fs_driver_t *driver;
+    list_entry_t event_watch_list;
+    lock_t event_watch_list_lock;
 };
 
 void register_filesystem_driver(fs_driver_t *driver);
index db5a6875215463093582225842489f433030eba5..97da66002c58d3f8701caf105f16334ceccf3116 100644 (file)
@@ -26,9 +26,7 @@
 
 static DECLARE_LIST(fs_driver_list);
 static DECLARE_LIST(volumes);
-static DECLARE_LIST(event_watch_list);
 lock_t fs_driver_list_lock = 0;
-lock_t event_watch_list_lock = 0;
 resource_t volume_list_res = 0;
 
 static inline int count_delimiters(const char *string)
@@ -38,13 +36,37 @@ static inline int count_delimiters(const char *string)
     return count;
 }
 
+mounted_volume_t *get_volume_from_path(const char *path)
+{
+    mounted_volume_t *volume = NULL;
+    list_entry_t *ptr;
+    acquire_resource_shared(&volume_list_res);
+
+    for (ptr = volumes.next; ptr != &volumes; ptr = ptr->next)
+    {
+        mounted_volume_t *vol = CONTAINER_OF(ptr, mounted_volume_t, list);
+        int length = strlen(vol->mountpoint);
+
+        if (strncmp(path, vol->mountpoint, length) == 0
+            && (path[length] == '\0' || path[length] == PATH_DELIMITER_CHAR))
+        {
+            volume = vol;
+            break;
+        }
+    }
+
+    release_resource(&volume_list_res);
+    return volume;
+}
+
 void report_filesystem_event(const char *path, dword_t type)
 {
     list_entry_t *ptr;
+    mounted_volume_t *volume = get_volume_from_path(path);
     int path_length = strlen(path);
-    acquire_lock(&event_watch_list_lock);
+    acquire_lock(&volume->event_watch_list_lock);
 
-    for (ptr = event_watch_list.next; ptr != &event_watch_list; ptr = ptr->next)
+    for (ptr = volume->event_watch_list.next; ptr != &volume->event_watch_list; ptr = ptr->next)
     {
         event_watch_entry_t *watch = CONTAINER_OF(ptr, event_watch_entry_t, list);
         reference(&watch->directory->header);
@@ -73,7 +95,7 @@ void report_filesystem_event(const char *path, dword_t type)
         dereference(&watch->directory->header);
     }
 
-    release_lock(&event_watch_list_lock);
+    release_lock(&volume->event_watch_list_lock);
 }
 
 void file_cleanup(file_t *file)
@@ -94,9 +116,9 @@ void file_instance_cleanup(file_instance_t *instance)
         ASSERT(file->attributes & FILE_ATTR_DIRECTORY);
         ASSERT(instance->watch->directory == instance);
 
-        acquire_lock(&event_watch_list_lock);
+        acquire_lock(&file->volume->event_watch_list_lock);
         list_remove(&instance->watch->list);
-        release_lock(&event_watch_list_lock);
+        release_lock(&file->volume->event_watch_list_lock);
 
         ASSERT(!instance->watch->lock);
 
@@ -146,6 +168,8 @@ dword_t register_mounted_volume(mounted_volume_t *volume)
 
     volume->resource = 0;
     volume->open_files = 0;
+    list_init(&volume->event_watch_list);
+    volume->event_watch_list_lock = 0;
 
     int delimiters = count_delimiters(volume->mountpoint);
     list_entry_t *ptr;
@@ -175,28 +199,6 @@ dword_t unregister_mounted_volume(mounted_volume_t *volume)
     return ERR_SUCCESS;
 }
 
-mounted_volume_t *get_volume_from_path(const char *path)
-{
-    mounted_volume_t *volume = NULL;
-    list_entry_t *ptr;
-    acquire_resource_shared(&volume_list_res);
-
-    for (ptr = volumes.next; ptr != &volumes; ptr = ptr->next)
-    {
-        mounted_volume_t *vol = CONTAINER_OF(ptr, mounted_volume_t, list);
-
-        if (strstr(path, vol->mountpoint) == path
-            && (path[strlen(vol->mountpoint)] == '\0' || path[strlen(vol->mountpoint)] == PATH_DELIMITER_CHAR))
-        {
-            volume = vol;
-            break;
-        }
-    }
-
-    release_resource(&volume_list_res);
-    return volume;
-}
-
 dword_t normalize_path(const char *path, char *normalized_path)
 {
     static const char *block_dev_prefix = "BlockDevices/";
@@ -728,8 +730,9 @@ dword_t wait_directory_event(handle_t handle, dword_t event_mask, file_event_t *
         init_semaphore(&watch->event_semaphore, 0, EVENT_QUEUE_CAPACITY);
         list_init(&watch->event_queue);
 
-        acquire_lock(&event_watch_list_lock);
-        list_append(&event_watch_list, &watch->list);
+        mounted_volume_t *volume = directory->global->volume;
+        acquire_lock(&volume->event_watch_list_lock);
+        list_append(&volume->event_watch_list, &watch->list);
 
         if (!__sync_bool_compare_and_swap(&directory->watch, NULL, watch))
         {
@@ -737,7 +740,7 @@ dword_t wait_directory_event(handle_t handle, dword_t event_mask, file_event_t *
             free(watch);
         }
 
-        release_lock(&event_watch_list_lock);
+        release_lock(&volume->event_watch_list_lock);
     }
 
     directory->watch->event_mask = event_mask;