Bladeren bron

Kernel: Handle OOM from DoubleBuffer creation in FIFO creation

Brian Gianforcaro 3 jaren geleden
bovenliggende
commit
8d3b819daf
4 gewijzigde bestanden met toevoegingen van 25 en 16 verwijderingen
  1. 14 10
      Kernel/FileSystem/FIFO.cpp
  2. 3 3
      Kernel/FileSystem/FIFO.h
  3. 5 2
      Kernel/FileSystem/Inode.cpp
  4. 3 1
      Kernel/Syscalls/pipe.cpp

+ 14 - 10
Kernel/FileSystem/FIFO.cpp

@@ -24,9 +24,12 @@ static Lockable<HashTable<FIFO*>>& all_fifos()
 
 static int s_next_fifo_id = 1;
 
-NonnullRefPtr<FIFO> FIFO::create(uid_t uid)
+RefPtr<FIFO> FIFO::try_create(uid_t uid)
 {
-    return adopt_ref(*new FIFO(uid));
+    auto buffer = DoubleBuffer::try_create();
+    if (buffer)
+        return adopt_ref_if_nonnull(new (nothrow) FIFO(uid, buffer.release_nonnull()));
+    return {};
 }
 
 KResultOr<NonnullRefPtr<FileDescription>> FIFO::open_direction(FIFO::Direction direction)
@@ -70,15 +73,16 @@ KResultOr<NonnullRefPtr<FileDescription>> FIFO::open_direction_blocking(FIFO::Di
     return description;
 }
 
-FIFO::FIFO(uid_t uid)
-    : m_uid(uid)
+FIFO::FIFO(uid_t uid, NonnullOwnPtr<DoubleBuffer> buffer)
+    : m_buffer(move(buffer))
+    , m_uid(uid)
 {
     MutexLocker locker(all_fifos().lock());
     all_fifos().resource().set(this);
     m_fifo_id = ++s_next_fifo_id;
 
     // Use the same block condition for read and write
-    m_buffer.set_unblock_callback([this]() {
+    m_buffer->set_unblock_callback([this]() {
         evaluate_block_conditions();
     });
 }
@@ -115,19 +119,19 @@ void FIFO::detach(Direction direction)
 
 bool FIFO::can_read(const FileDescription&, size_t) const
 {
-    return !m_buffer.is_empty() || !m_writers;
+    return !m_buffer->is_empty() || !m_writers;
 }
 
 bool FIFO::can_write(const FileDescription&, size_t) const
 {
-    return m_buffer.space_for_writing() || !m_readers;
+    return m_buffer->space_for_writing() || !m_readers;
 }
 
 KResultOr<size_t> FIFO::read(FileDescription&, u64, UserOrKernelBuffer& buffer, size_t size)
 {
-    if (!m_writers && m_buffer.is_empty())
+    if (!m_writers && m_buffer->is_empty())
         return 0;
-    return m_buffer.read(buffer, size);
+    return m_buffer->read(buffer, size);
 }
 
 KResultOr<size_t> FIFO::write(FileDescription&, u64, const UserOrKernelBuffer& buffer, size_t size)
@@ -137,7 +141,7 @@ KResultOr<size_t> FIFO::write(FileDescription&, u64, const UserOrKernelBuffer& b
         return EPIPE;
     }
 
-    return m_buffer.write(buffer, size);
+    return m_buffer->write(buffer, size);
 }
 
 String FIFO::absolute_path(const FileDescription&) const

+ 3 - 3
Kernel/FileSystem/FIFO.h

@@ -24,7 +24,7 @@ public:
         Writer
     };
 
-    static NonnullRefPtr<FIFO> create(uid_t);
+    static RefPtr<FIFO> try_create(uid_t);
     virtual ~FIFO() override;
 
     uid_t uid() const { return m_uid; }
@@ -49,11 +49,11 @@ private:
     virtual StringView class_name() const override { return "FIFO"; }
     virtual bool is_fifo() const override { return true; }
 
-    explicit FIFO(uid_t);
+    explicit FIFO(uid_t, NonnullOwnPtr<DoubleBuffer> buffer);
 
     unsigned m_writers { 0 };
     unsigned m_readers { 0 };
-    DoubleBuffer m_buffer;
+    NonnullOwnPtr<DoubleBuffer> m_buffer;
 
     uid_t m_uid { 0 };
 

+ 5 - 2
Kernel/FileSystem/Inode.cpp

@@ -185,8 +185,11 @@ NonnullRefPtr<FIFO> Inode::fifo()
     VERIFY(metadata().is_fifo());
 
     // FIXME: Release m_fifo when it is closed by all readers and writers
-    if (!m_fifo)
-        m_fifo = FIFO::create(metadata().uid);
+    if (!m_fifo) {
+        m_fifo = FIFO::try_create(metadata().uid);
+        // FIXME: We need to be able to observe OOM here.
+        VERIFY(!m_fifo.is_null());
+    }
 
     VERIFY(m_fifo);
     return *m_fifo;

+ 3 - 1
Kernel/Syscalls/pipe.cpp

@@ -20,7 +20,9 @@ KResultOr<FlatPtr> Process::sys$pipe(int pipefd[2], int flags)
         return EINVAL;
 
     u32 fd_flags = (flags & O_CLOEXEC) ? FD_CLOEXEC : 0;
-    auto fifo = FIFO::create(uid());
+    auto fifo = FIFO::try_create(uid());
+    if (!fifo)
+        return ENOMEM;
 
     auto open_reader_result = fifo->open_direction(FIFO::Direction::Reader);
     if (open_reader_result.is_error())