mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 10:42:45 +00:00 
			
		
		
		
	Kernel: Add "child added" and "child removed" InodeWatcher events
The child name is not yet accessible to userspace, but will be in a future patch.
This commit is contained in:
		
							parent
							
								
									ea17d2d3da
								
							
						
					
					
						commit
						0d577ab781
					
				
					 6 changed files with 47 additions and 3 deletions
				
			
		|  | @ -981,6 +981,8 @@ KResult Ext2FSInode::add_child(Inode& child, const StringView& name, mode_t mode | |||
|     bool success = write_directory(entries); | ||||
|     if (success) | ||||
|         m_lookup_cache.set(name, child.index()); | ||||
| 
 | ||||
|     did_add_child(name); | ||||
|     return KSuccess; | ||||
| } | ||||
| 
 | ||||
|  | @ -1022,6 +1024,8 @@ KResult Ext2FSInode::remove_child(const StringView& name) | |||
| 
 | ||||
|     auto child_inode = fs().get_inode(child_id); | ||||
|     child_inode->decrement_link_count(); | ||||
| 
 | ||||
|     did_remove_child(name); | ||||
|     return KSuccess; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -215,6 +215,22 @@ void Inode::set_metadata_dirty(bool metadata_dirty) | |||
|     } | ||||
| } | ||||
| 
 | ||||
| void Inode::did_add_child(const String& name) | ||||
| { | ||||
|     LOCKER(m_lock); | ||||
|     for (auto& watcher : m_watchers) { | ||||
|         watcher->notify_child_added({}, name); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void Inode::did_remove_child(const String& name) | ||||
| { | ||||
|     LOCKER(m_lock); | ||||
|     for (auto& watcher : m_watchers) { | ||||
|         watcher->notify_child_removed({}, name); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| KResult Inode::prepare_to_write_data() | ||||
| { | ||||
|     // FIXME: It's a poor design that filesystems are expected to call this before writing out data.
 | ||||
|  |  | |||
|  | @ -122,6 +122,9 @@ protected: | |||
|     void inode_size_changed(size_t old_size, size_t new_size); | ||||
|     KResult prepare_to_write_data(); | ||||
| 
 | ||||
|     void did_add_child(const String& name); | ||||
|     void did_remove_child(const String& name); | ||||
| 
 | ||||
|     mutable Lock m_lock { "Inode" }; | ||||
| 
 | ||||
| private: | ||||
|  |  | |||
|  | @ -59,6 +59,7 @@ bool InodeWatcher::can_write(const FileDescription&, size_t) const | |||
| 
 | ||||
| ssize_t InodeWatcher::read(FileDescription&, size_t, u8* buffer, ssize_t buffer_size) | ||||
| { | ||||
|     LOCKER(m_lock); | ||||
|     ASSERT(!m_queue.is_empty() || !m_inode); | ||||
| 
 | ||||
|     if (!m_inode) | ||||
|  | @ -85,7 +86,20 @@ String InodeWatcher::absolute_path(const FileDescription&) const | |||
| 
 | ||||
| void InodeWatcher::notify_inode_event(Badge<Inode>, Event::Type event_type) | ||||
| { | ||||
|     m_queue.enqueue({ event_type }); | ||||
|     LOCKER(m_lock); | ||||
|     m_queue.enqueue({ event_type, {} }); | ||||
| } | ||||
| 
 | ||||
| void InodeWatcher::notify_child_added(Badge<Inode>, const String& child_name) | ||||
| { | ||||
|     LOCKER(m_lock); | ||||
|     m_queue.enqueue({ Event::Type::ChildAdded, child_name }); | ||||
| } | ||||
| 
 | ||||
| void InodeWatcher::notify_child_removed(Badge<Inode>, const String& child_name) | ||||
| { | ||||
|     LOCKER(m_lock); | ||||
|     m_queue.enqueue({ Event::Type::ChildRemoved, child_name }); | ||||
| } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -30,6 +30,7 @@ | |||
| #include <AK/CircularQueue.h> | ||||
| #include <AK/WeakPtr.h> | ||||
| #include <Kernel/FileSystem/File.h> | ||||
| #include <Kernel/Lock.h> | ||||
| 
 | ||||
| namespace Kernel { | ||||
| 
 | ||||
|  | @ -44,9 +45,12 @@ public: | |||
|         enum class Type { | ||||
|             Invalid = 0, | ||||
|             Modified, | ||||
|             ChildAdded, | ||||
|             ChildRemoved, | ||||
|         }; | ||||
| 
 | ||||
|         Type type { Type::Invalid }; | ||||
|         String string; | ||||
|     }; | ||||
| 
 | ||||
|     virtual bool can_read(const FileDescription&, size_t) const override; | ||||
|  | @ -57,10 +61,13 @@ public: | |||
|     virtual const char* class_name() const override { return "InodeWatcher"; }; | ||||
| 
 | ||||
|     void notify_inode_event(Badge<Inode>, Event::Type); | ||||
|     void notify_child_added(Badge<Inode>, const String& child_name); | ||||
|     void notify_child_removed(Badge<Inode>, const String& child_name); | ||||
| 
 | ||||
| private: | ||||
|     explicit InodeWatcher(Inode&); | ||||
| 
 | ||||
|     Lock m_lock; | ||||
|     WeakPtr<Inode> m_inode; | ||||
|     CircularQueue<Event, 32> m_queue; | ||||
| }; | ||||
|  |  | |||
|  | @ -297,7 +297,7 @@ KResult TmpFSInode::add_child(Inode& child, const StringView& name, mode_t) | |||
|     FS::DirectoryEntry entry = { owned_name.characters(), owned_name.length(), child.identifier(), 0 }; | ||||
| 
 | ||||
|     m_children.set(owned_name, { entry, static_cast<TmpFSInode&>(child) }); | ||||
|     notify_watchers(); | ||||
|     did_add_child(name); | ||||
|     return KSuccess; | ||||
| } | ||||
| 
 | ||||
|  | @ -313,7 +313,7 @@ KResult TmpFSInode::remove_child(const StringView& name) | |||
|     if (it == m_children.end()) | ||||
|         return KResult(-ENOENT); | ||||
|     m_children.remove(it); | ||||
|     notify_watchers(); | ||||
|     did_remove_child(name); | ||||
|     return KSuccess; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling