[haiku-commits] haiku: hrev46442 - in src: system/kernel/fs add-ons/kernel/network/stack

  • From: ingo_weinhold@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Mon, 25 Nov 2013 16:08:31 +0100 (CET)

hrev46442 adds 4 changesets to branch 'master'
old head: 9394e66cbceb75f1f29c62224ced948d62ffda94
new head: f170a888c26756f2a2586630aa280d8bc3d687ee
overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=f170a88+%5E9394e66

----------------------------------------------------------------------------

ed9f471: Fix FIONREAD related issues
  
  * Network stack socket module: socket_control(): The FIONREAD argument
    is int, not ssize_t.
  * Net kit: getsockopt(): R5_SO_FIONREAD: Fix ioctl() argument. Was
    taking a pointer of what already was a pointer to the buffer.
  * libedit: el_gets(): The FIONREAD argument is int, not long.

fd0bfd5: FIFO: More correct locking when accessing file_cookie::open_mode

8019fdb: FIFO: Implement FION{BIO,READ}, B_SET_[NON]BLOCKING_IO ioctls

f170a88: FIFO: Handle user reads/writes more correctly
  
  * Determine whether called from userland or kernel.
  * Check the buffer address via IS_USER_ADDRESS(), if from userland.
  * Simplify things by merging UserRead() with Read() and
    UserWrite() with Write().

                                    [ Ingo Weinhold <ingo_weinhold@xxxxxx> ]

----------------------------------------------------------------------------

4 files changed, 121 insertions(+), 55 deletions(-)
src/add-ons/kernel/network/stack/net_socket.cpp |   9 +-
src/kits/network/socket.cpp                     |   5 +-
src/libs/edit/read.c                            |   2 +-
src/system/kernel/fs/fifo.cpp                   | 160 ++++++++++++++------

############################################################################

Commit:      ed9f4719f7f22477353f0c09c4ed4db8857c6d57
URL:         http://cgit.haiku-os.org/haiku/commit/?id=ed9f471
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Mon Nov 25 14:47:26 2013 UTC

Fix FIONREAD related issues

* Network stack socket module: socket_control(): The FIONREAD argument
  is int, not ssize_t.
* Net kit: getsockopt(): R5_SO_FIONREAD: Fix ioctl() argument. Was
  taking a pointer of what already was a pointer to the buffer.
* libedit: el_gets(): The FIONREAD argument is int, not long.

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/network/stack/net_socket.cpp 
b/src/add-ons/kernel/network/stack/net_socket.cpp
index 9d5cfc9..bc7b8de 100644
--- a/src/add-ons/kernel/network/stack/net_socket.cpp
+++ b/src/add-ons/kernel/network/stack/net_socket.cpp
@@ -550,17 +550,18 @@ socket_control(net_socket* socket, int32 op, void* data, 
size_t length)
                        if (data == NULL)
                                return B_BAD_VALUE;
 
-                       ssize_t available = socket_read_avail(socket);
-                       if (available < B_OK)
+                       int available = (int)socket_read_avail(socket);
+                       if (available < 0)
                                return available;
 
                        if (is_syscall()) {
                                if (!IS_USER_ADDRESS(data)
-                                       || user_memcpy(data, &available, 
sizeof(ssize_t)) != B_OK) {
+                                       || user_memcpy(data, &available, 
sizeof(available))
+                                               != B_OK) {
                                        return B_BAD_ADDRESS;
                                }
                        } else
-                               *(ssize_t *)data = available;
+                               *(int*)data = available;
 
                        return B_OK;
                }
diff --git a/src/kits/network/socket.cpp b/src/kits/network/socket.cpp
index 9daf8ec..7829f20 100644
--- a/src/kits/network/socket.cpp
+++ b/src/kits/network/socket.cpp
@@ -315,9 +315,10 @@ getsockopt(int socket, int level, int option, void *value, 
socklen_t *_length)
 {
        if (check_r5_compatibility()) {
                if (option == R5_SO_FIONREAD) {
-                       // there is no SO_FIONREAD in our stack; we're using 
FIONREAD instead
+                       // there is no SO_FIONREAD in our stack; we're using 
FIONREAD
+                       // instead
                        *_length = sizeof(int);
-                       return ioctl(socket, FIONREAD, &value);
+                       return ioctl(socket, FIONREAD, value);
                }
 
                convert_from_r5_sockopt(level, option);
diff --git a/src/libs/edit/read.c b/src/libs/edit/read.c
index cfc5cbf..8ce1667 100644
--- a/src/libs/edit/read.c
+++ b/src/libs/edit/read.c
@@ -419,7 +419,7 @@ el_gets(EditLine *el, int *nread)
 
 #ifdef FIONREAD
        if (el->el_tty.t_mode == EX_IO && ma->level < 0) {
-               long chrs = 0;
+               int chrs = 0;
 
                (void) ioctl(el->el_infd, FIONREAD, (ioctl_t) & chrs);
                if (chrs == 0) {

############################################################################

Commit:      fd0bfd5593f3abb48b1038112d7d85bbb1f4094c
URL:         http://cgit.haiku-os.org/haiku/commit/?id=fd0bfd5
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Mon Nov 25 14:49:24 2013 UTC

FIFO: More correct locking when accessing file_cookie::open_mode

----------------------------------------------------------------------------

diff --git a/src/system/kernel/fs/fifo.cpp b/src/system/kernel/fs/fifo.cpp
index b24e258..2b403bd 100644
--- a/src/system/kernel/fs/fifo.cpp
+++ b/src/system/kernel/fs/fifo.cpp
@@ -188,7 +188,7 @@ public:
                        void                            NotifyEndClosed(bool 
writer);
 
                        void                            Open(int openMode);
-                       void                            Close(int openMode, 
file_cookie* cookie);
+                       void                            Close(file_cookie* 
cookie);
                        int32                           ReaderCount() const { 
return fReaderCount; }
                        int32                           WriterCount() const { 
return fWriterCount; }
 
@@ -239,7 +239,8 @@ private:
 
 
 struct file_cookie {
-       int                             open_mode;
+       int     open_mode;
+                       // guarded by Inode::fRequestLock
 };
 
 
@@ -654,12 +655,14 @@ Inode::Open(int openMode)
 
 
 void
-Inode::Close(int openMode, file_cookie* cookie)
+Inode::Close(file_cookie* cookie)
 {
        TRACE("Inode %p::Close(openMode = %d)\n", this, openMode);
 
        MutexLocker locker(RequestLock());
 
+       int openMode = cookie->open_mode;
+
        // Notify all currently reading file descriptors
        ReadRequestList::Iterator iterator = fReadRequests.GetIterator();
        while (ReadRequest* request = iterator.Next()) {
@@ -898,7 +901,7 @@ fifo_close(fs_volume* volume, fs_vnode* vnode, void* 
_cookie)
        file_cookie* cookie = (file_cookie*)_cookie;
        FIFOInode* fifo = (FIFOInode*)vnode->private_node;
 
-       fifo->Close(cookie->open_mode, cookie);
+       fifo->Close(cookie);
 
        return B_OK;
 }
@@ -934,11 +937,11 @@ fifo_read(fs_volume* _volume, fs_vnode* _node, void* 
_cookie,
        TRACE("fifo_read(vnode = %p, cookie = %p, length = %lu, mode = %d)\n",
                inode, cookie, *_length, cookie->open_mode);
 
+       MutexLocker locker(inode->RequestLock());
+
        if ((cookie->open_mode & O_RWMASK) != O_RDONLY)
                return B_NOT_ALLOWED;
 
-       MutexLocker locker(inode->RequestLock());
-
        if (inode->IsActive() && inode->WriterCount() == 0) {
                // as long there is no writer, and the pipe is empty,
                // we always just return 0 to indicate end of file
@@ -982,11 +985,11 @@ fifo_write(fs_volume* _volume, fs_vnode* _node, void* 
_cookie,
        TRACE("fifo_write(vnode = %p, cookie = %p, length = %lu)\n",
                _node, cookie, *_length);
 
+       MutexLocker locker(inode->RequestLock());
+
        if ((cookie->open_mode & O_RWMASK) != O_WRONLY)
                return B_NOT_ALLOWED;
 
-       MutexLocker locker(inode->RequestLock());
-
        size_t length = *_length;
        if (length == 0)
                return B_OK;
@@ -1067,12 +1070,15 @@ fifo_ioctl(fs_volume* _volume, fs_vnode* _vnode, void* 
_cookie, uint32 op,
 
 
 static status_t
-fifo_set_flags(fs_volume* _volume, fs_vnode* _vnode, void* _cookie,
+fifo_set_flags(fs_volume* _volume, fs_vnode* _node, void* _cookie,
        int flags)
 {
+       Inode* inode = (Inode*)_node->private_node;
        file_cookie* cookie = (file_cookie*)_cookie;
 
        TRACE("fifo_set_flags(vnode = %p, flags = %x)\n", _vnode, flags);
+
+       MutexLocker locker(inode->RequestLock());
        cookie->open_mode = (cookie->open_mode & ~(O_APPEND | O_NONBLOCK)) | 
flags;
        return B_OK;
 }

############################################################################

Commit:      8019fdbab89c0b320e8f70583182eae2189bc913
URL:         http://cgit.haiku-os.org/haiku/commit/?id=8019fdb
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Mon Nov 25 14:50:26 2013 UTC

FIFO: Implement FION{BIO,READ}, B_SET_[NON]BLOCKING_IO ioctls

----------------------------------------------------------------------------

diff --git a/src/system/kernel/fs/fifo.cpp b/src/system/kernel/fs/fifo.cpp
index 2b403bd..bf42d02 100644
--- a/src/system/kernel/fs/fifo.cpp
+++ b/src/system/kernel/fs/fifo.cpp
@@ -11,6 +11,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/ioctl.h>
 #include <sys/stat.h>
 
 #include <new>
@@ -24,6 +25,7 @@
 #include <khash.h>
 #include <lock.h>
 #include <select_sync_pool.h>
+#include <syscall_restart.h>
 #include <team.h>
 #include <thread.h>
 #include <util/DoublyLinkedList.h>
@@ -241,6 +243,14 @@ private:
 struct file_cookie {
        int     open_mode;
                        // guarded by Inode::fRequestLock
+
+       void SetNonBlocking(bool nonBlocking)
+       {
+               if (nonBlocking)
+                       open_mode |= O_NONBLOCK;
+               else
+                       open_mode &= ~(int)O_NONBLOCK;
+       }
 };
 
 
@@ -1059,12 +1069,65 @@ fifo_write_stat(fs_volume* volume, fs_vnode* vnode, 
const struct ::stat* st,
 
 
 static status_t
-fifo_ioctl(fs_volume* _volume, fs_vnode* _vnode, void* _cookie, uint32 op,
+fifo_ioctl(fs_volume* _volume, fs_vnode* _node, void* _cookie, uint32 op,
        void* buffer, size_t length)
 {
+       file_cookie* cookie = (file_cookie*)_cookie;
+       Inode* inode = (Inode*)_node->private_node;
+
        TRACE("fifo_ioctl: vnode %p, cookie %p, op %ld, buf %p, len %ld\n",
                _vnode, _cookie, op, buffer, length);
 
+       switch (op) {
+               case FIONBIO:
+               {
+                       if (buffer == NULL)
+                               return B_BAD_VALUE;
+
+                       int value;
+                       if (is_called_via_syscall()) {
+                               if (!IS_USER_ADDRESS(buffer)
+                                       || user_memcpy(&value, buffer, 
sizeof(int)) != B_OK) {
+                                       return B_BAD_ADDRESS;
+                               }
+                       } else
+                               value = *(int*)buffer;
+
+                       MutexLocker locker(inode->RequestLock());
+                       cookie->SetNonBlocking(value != 0);
+                       return B_OK;
+               }
+
+               case FIONREAD:
+               {
+                       if (buffer == NULL)
+                               return B_BAD_VALUE;
+
+                       MutexLocker locker(inode->RequestLock());
+                       int available = (int)inode->BytesAvailable();
+                       locker.Unlock();
+
+                       if (is_called_via_syscall()) {
+                               if (!IS_USER_ADDRESS(buffer)
+                                       || user_memcpy(buffer, &available, 
sizeof(available))
+                                               != B_OK) {
+                                       return B_BAD_ADDRESS;
+                               }
+                       } else
+                               *(int*)buffer = available;
+
+                       return B_OK;
+               }
+
+               case B_SET_BLOCKING_IO:
+               case B_SET_NONBLOCKING_IO:
+               {
+                       MutexLocker locker(inode->RequestLock());
+                       cookie->SetNonBlocking(op == B_SET_NONBLOCKING_IO);
+                       return B_OK;
+               }
+       }
+
        return EINVAL;
 }
 

############################################################################

Revision:    hrev46442
Commit:      f170a888c26756f2a2586630aa280d8bc3d687ee
URL:         http://cgit.haiku-os.org/haiku/commit/?id=f170a88
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Mon Nov 25 15:06:45 2013 UTC

FIFO: Handle user reads/writes more correctly

* Determine whether called from userland or kernel.
* Check the buffer address via IS_USER_ADDRESS(), if from userland.
* Simplify things by merging UserRead() with Read() and
  UserWrite() with Write().

----------------------------------------------------------------------------

diff --git a/src/system/kernel/fs/fifo.cpp b/src/system/kernel/fs/fifo.cpp
index bf42d02..09d2e3f 100644
--- a/src/system/kernel/fs/fifo.cpp
+++ b/src/system/kernel/fs/fifo.cpp
@@ -62,12 +62,11 @@ public:
                        status_t                        CreateBuffer();
                        void                            DeleteBuffer();
 
-                       ssize_t                         Write(const void* 
buffer, size_t length);
-                       ssize_t                         Read(void* buffer, 
size_t length);
+                       ssize_t                         Write(const void* 
buffer, size_t length,
+                                                                       bool 
isUser);
+                       ssize_t                         Read(void* buffer, 
size_t length, bool isUser);
                        ssize_t                         Peek(size_t offset, 
void* buffer,
                                                                        size_t 
length) const;
-                       ssize_t                         UserWrite(const void* 
buffer, ssize_t length);
-                       ssize_t                         UserRead(void* buffer, 
ssize_t length);
 
                        size_t                          Readable() const;
                        size_t                          Writable() const;
@@ -172,9 +171,11 @@ public:
                        mutex*                          RequestLock() { return 
&fRequestLock; }
 
                        status_t                        WriteDataToBuffer(const 
void* data,
-                                                                       size_t* 
_length, bool nonBlocking);
+                                                                       size_t* 
_length, bool nonBlocking,
+                                                                       bool 
isUser);
                        status_t                        
ReadDataFromBuffer(void* data, size_t* _length,
-                                                                       bool 
nonBlocking, ReadRequest& request);
+                                                                       bool 
nonBlocking, bool isUser,
+                                                                       
ReadRequest& request);
                        size_t                          BytesAvailable() const
                                                                        { 
return fBuffer.Readable(); }
                        size_t                          BytesWritable() const
@@ -292,22 +293,30 @@ RingBuffer::DeleteBuffer()
 
 
 inline ssize_t
-RingBuffer::Write(const void* buffer, size_t length)
+RingBuffer::Write(const void* buffer, size_t length, bool isUser)
 {
        if (fBuffer == NULL)
                return B_NO_MEMORY;
+       if (isUser && !IS_USER_ADDRESS(buffer))
+               return B_BAD_ADDRESS;
 
-       return ring_buffer_write(fBuffer, (const uint8*)buffer, length);
+       return isUser
+               ? ring_buffer_user_write(fBuffer, (const uint8*)buffer, length)
+               : ring_buffer_write(fBuffer, (const uint8*)buffer, length);
 }
 
 
 inline ssize_t
-RingBuffer::Read(void* buffer, size_t length)
+RingBuffer::Read(void* buffer, size_t length, bool isUser)
 {
        if (fBuffer == NULL)
                return B_NO_MEMORY;
+       if (isUser && !IS_USER_ADDRESS(buffer))
+               return B_BAD_ADDRESS;
 
-       return ring_buffer_read(fBuffer, (uint8*)buffer, length);
+       return isUser
+               ? ring_buffer_user_read(fBuffer, (uint8*)buffer, length)
+               : ring_buffer_read(fBuffer, (uint8*)buffer, length);
 }
 
 
@@ -321,26 +330,6 @@ RingBuffer::Peek(size_t offset, void* buffer, size_t 
length) const
 }
 
 
-inline ssize_t
-RingBuffer::UserWrite(const void* buffer, ssize_t length)
-{
-       if (fBuffer == NULL)
-               return B_NO_MEMORY;
-
-       return ring_buffer_user_write(fBuffer, (const uint8*)buffer, length);
-}
-
-
-inline ssize_t
-RingBuffer::UserRead(void* buffer, ssize_t length)
-{
-       if (fBuffer == NULL)
-               return B_NO_MEMORY;
-
-       return ring_buffer_user_read(fBuffer, (uint8*)buffer, length);
-}
-
-
 inline size_t
 RingBuffer::Readable() const
 {
@@ -400,7 +389,8 @@ Inode::InitCheck()
        the returned length is > 0, the returned error code can be ignored.
 */
 status_t
-Inode::WriteDataToBuffer(const void* _data, size_t* _length, bool nonBlocking)
+Inode::WriteDataToBuffer(const void* _data, size_t* _length, bool nonBlocking,
+       bool isUser)
 {
        const uint8* data = (const uint8*)_data;
        size_t dataSize = *_length;
@@ -452,8 +442,11 @@ Inode::WriteDataToBuffer(const void* _data, size_t* 
_length, bool nonBlocking)
                if (toWrite > dataSize)
                        toWrite = dataSize;
 
-               if (toWrite > 0 && fBuffer.UserWrite(data, toWrite) < 0)
-                       return B_BAD_ADDRESS;
+               if (toWrite > 0) {
+                       ssize_t bytesWritten = fBuffer.Write(data, toWrite, 
isUser);
+                       if (bytesWritten < 0)
+                               return bytesWritten;
+               }
 
                data += toWrite;
                dataSize -= toWrite;
@@ -468,7 +461,7 @@ Inode::WriteDataToBuffer(const void* _data, size_t* 
_length, bool nonBlocking)
 
 status_t
 Inode::ReadDataFromBuffer(void* data, size_t* _length, bool nonBlocking,
-       ReadRequest& request)
+       bool isUser, ReadRequest& request)
 {
        size_t dataSize = *_length;
        *_length = 0;
@@ -508,8 +501,9 @@ Inode::ReadDataFromBuffer(void* data, size_t* _length, bool 
nonBlocking,
        if (toRead > dataSize)
                toRead = dataSize;
 
-       if (fBuffer.UserRead(data, toRead) < 0)
-               return B_BAD_ADDRESS;
+       ssize_t bytesRead = fBuffer.Read(data, toRead, isUser);
+       if (bytesRead < 0)
+               return bytesRead;
 
        NotifyBytesRead(toRead);
 
@@ -970,7 +964,8 @@ fifo_read(fs_volume* _volume, fs_vnode* _node, void* 
_cookie,
 
        size_t length = *_length;
        status_t status = inode->ReadDataFromBuffer(buffer, &length,
-               (cookie->open_mode & O_NONBLOCK) != 0, request);
+               (cookie->open_mode & O_NONBLOCK) != 0, is_called_via_syscall(),
+               request);
 
        inode->RemoveReadRequest(request);
        inode->NotifyReadDone();
@@ -1006,7 +1001,7 @@ fifo_write(fs_volume* _volume, fs_vnode* _node, void* 
_cookie,
 
        // copy data into ring buffer
        status_t status = inode->WriteDataToBuffer(buffer, &length,
-               (cookie->open_mode & O_NONBLOCK) != 0);
+               (cookie->open_mode & O_NONBLOCK) != 0, is_called_via_syscall());
 
        if (length > 0)
                status = B_OK;


Other related posts:

  • » [haiku-commits] haiku: hrev46442 - in src: system/kernel/fs add-ons/kernel/network/stack - ingo_weinhold