Go to the FreeLists Home Page Home Signup Help Login
 



[openbeosstorage] || [Date Prev] [02-2002 Date Index] [Date Next] || [Thread Prev] [02-2002 Thread Index] [Thread Next]

[openbeosstorage] Re: Kernel Interface Design

  • From: Keith Poole <keef@xxxxxxxxxxxxxxx>
  • To: openbeosstorage@xxxxxxxxxxxxx
  • Date: Tue, 12 Feb 2002 00:36:14 +0000
My attempt at the emulator code (haven't had chance to try it under BeOS 
yet - but it compiles under gcc).  Any comments on this one?

I think Tyler's right about throwing exceptions - this version doesn't, 
but it would make the code clearer if it did.

Data types - open modes are ints if you use open rather than fopen 
(O_CREAT, etc) - see the attached example

        Keith

Tyler Dauwalder wrote:

>Hey folks, 
>
>Sorry for being a bit quiet over the past couple of days; I
>went to visit my mom over the weekend and got absolutely 
>nothing done whatsoever.
>
>I think it's time we started planning out what I'm going to 
>from here out refer to as our "kernel interface". By that I
>mean our bottom-level C functions that we'll initially implement
>with POSIX and later implement with syscalls.
>
>(one short note here: I'm calling them C functions, but I
>don't see any reason we would be restricted to using pure C)
>
>I made up a quick header and cpp pair with rough POSIX 
>implementations of open() and close() to try and get a sense 
>of some of the issues we're going to need to address in our 
>design. There in CVS at:
>
>/storage_kit/source/lib/kernel_interface.h
>/storage_kit/source/lib/kernel_interface.POSIX.cpp
>
>Please note that I haven't tried compiling these, I just
>needed a place to start.
>
>
>----------------------------------------------------------------------
>1. Interface portability
>----------------------------------------------------------------------
>
>First and formost, we want to design our interface to be
>as portable as possible, meaning we don't want it to work
>fine with POSIX but then have to be changed when we
>rewrite it to use syscalls. To that degree, I've started a
>brief function dependency document in CVS at:
>
>/storage_kit/docs/kernel_interface/FunctionDependencyReference.html
>
>All I've done is list the NewOS and POSIX calls that each function
>will depend on. This helps to give a sense of how each function will
>need to be designed in order for it to work as an interface to both
>the kernel and POSIX.
>
>For calls that are not yet implemented in the kernel, we're
>just going to have to make educated guesses based on
>the calls that *are* implemented.
>
>One thing I'd like everybody to do is just pick a few functions,
>look up the user_* equivalent in the NewOS kernel (vfs.h) or
>extrapolate a reasonable guess as to what it might look like if
>it doesn't exist, figure out which POSIX functions and headers
>are involved, and add said info to the list.
>
>As I've mentioned before, the set of functions in our interface will
>need to be basically identical to the set of functions in the vfs add-on
>layer we documented. So use that list of functions as a base for
>which functions we need to have in our interface that aren't currently 
>supported in the kernel.
>
>I guess just pick a few functions at a time, email the list saying
>you're going to work on those, and do your thing. There are templates
>in comments in the HTML file for the various sections you'll need
>to update.
>
>
>----------------------------------------------------------------------
>2. Error handling
>----------------------------------------------------------------------
>
>We're going to want/need a uniform method of error handling.
>We can either use exceptions or something depending on 
>return values and/or output parameters. My vote's for exceptions
>unless someone thinks that's a really bad idea.
>
>
>----------------------------------------------------------------------
>3. Data types
>----------------------------------------------------------------------
>
>There's not a lot of consistency between POSIX and the kernel API
>as far as data types go. For example, open modes in POSIX are 
>character strings, but in the kernel they're ints. I propose we create 
>our own set of data types as needed specifically for this interface. 
>These will end up being the data types we use throughout the entire 
>Storage Kit, and I think having a well thought out set of types to work 
>with will make our job easier and make our code cleaner. 
>
>In some cases, we're not going to be able or want to change
>data structures around too much. There's proabably no good
>reason for a file descriptor to be anything but an int. Directory
>functions are probably going to work with dirents. In other cases,
>like open modes, defining our own enum of values will probably
>be useful.
>
>I'm also thinking it might eventually be a good idea to go through 
>the Storage Kit and make up a dependency reference similar to 
>the one for the kernel interface. Something a little more in depth
>that lists off the kind of functionality each class provides and what 
>sorts of data types it will need to sling around in order to accomplish 
>what it's supposed to accomplish. We don't need to jump on that
>just yet though. 
>
>
>
>I think those are the main issues I wanted to address (it's really late,
>so I may have overlooked some...). Look through the kernel_interface.* 
>code and see what you think of the examples in there, and write up
>a couple of dependencies as you're able. :-)
>
>-Tyler
>
>
>
>
>
>



-- Attached file included as plaintext by Listar --
-- File: kernel_interface.POSIX.cpp

//----------------------------------------------------------------------
// kernel_interface.POSIX.cpp
// Initial implementation of our kernel interface with calls to 
// POSIX api. This will later be replaced with a version that
// makes syscalls into the actual kernel
//----------------------------------------------------------------------

#include "kernel_interface.h"

#include <fcntl.h>
#include <dirent.h>
#include <unistd.h>

typedef struct {
        stream_type st;
        DIR*    dir;
        int     file;
} fd_struct;

const int MAX_DESC = 256;
static fd_struct our_fds[MAX_DESC];
static int highest_fd = -1;


// The following two functions allocate and free file descriptors
// to make this emulation layer thread safe, they should have
// some kind of semaphore around them.
static int storage_kit::alloc_fd()
{
        // Allocate a file descriptor
        for (int i = 0; i < highest_fd; i++) {
                if (our_fds[i].st == STREAM_TYPE_ANY) {
                        // Free one - use it
                        return i;
                }
        }
        // Fell through = use next in list
        if (highest_fd < MAX_DESC) {
                return ++highest_fd;
        } else {
                return ERR_VFS_FD_TABLE_FULL;           // or throw
        }
}


static void storage_kit::free_fd(int fd)
{
        our_fds[fd].st = STREAM_TYPE_ANY;
}

// End of thread unsafe code

int storage_kit::open(const char *path, stream_type st, int omode)
{
        // Open a file or directory
        int fd = storage_kit::alloc_fd();
        if (fd >= 0) {
                // Which type of stream are we opening?
                switch (st) {
                case STREAM_TYPE_ANY:
                case STREAM_TYPE_DEVICE:
                default:
                        storage_kit::free_fd(fd);
                        fd = ERR_VFS_WRONG_STREAM_TYPE;
                        break;

                case STREAM_TYPE_FILE:
                        our_fds[fd].st = st;
                        our_fds[fd].file = ::open(path, omode, 0777);
                        if (our_fds[fd].file < 0) {
                                storage_kit::free_fd(fd);
                                fd = ERR_VFS_PATH_NOT_FOUND;            // 
Dodgy code
                        }
                        break;
                case STREAM_TYPE_DIR:
                        our_fds[fd].st = st;
                        our_fds[fd].dir = ::opendir(path);
                        if (our_fds[fd].dir == NULL) {
                                storage_kit::free_fd(fd);
                                fd = ERR_VFS_PATH_NOT_FOUND;            // Only 
error in posix docs
                        }
                        break;
                }
        }
        return fd;
}

int storage_kit::close(int fd)
{
        // Which type of stream are we opening?
        int err = NO_ERROR;
        switch (our_fds[fd].st) {
        case STREAM_TYPE_ANY:
        case STREAM_TYPE_DEVICE:
        default:
                return ERR_VFS_INVALID_FS;              // fd table corruption!

        case STREAM_TYPE_FILE:
                if(::close(our_fds[fd].file) < 0) {
                        err = ERR_VFS_INVALID_FS;
                }
                break;
        case STREAM_TYPE_DIR:
                ::closedir(our_fds[fd].dir);
                break;
        }
        return fd;
}

size_t storage_kit::read(int fd, void *buf, off_t pos, ssize_t len)
{
        // Get some data frm a file (or directory)
        int err = NO_ERROR;
        size_t data_read;
        switch (our_fds[fd].st) {
        case STREAM_TYPE_ANY:
        case STREAM_TYPE_DEVICE:
        default:
                return ERR_VFS_INVALID_FS;              // fd table corruption!

        case STREAM_TYPE_FILE:
                if(pos < 0) {
                        // Use current position
                        data_read = ::read(our_fds[fd].file, buf, len);
                } else {
                        // Positional read
                        ::lseek(our_fds[fd].file, pos, SEEK_CUR);
                        data_read = ::read(our_fds[fd].file, buf, len);
                }
                break;
        case STREAM_TYPE_DIR:
                struct dirent *dp = ::readdir(our_fds[fd].dir);
                if (dp == NULL) {
                        data_read = 0;
                } else {
                        if (strlen(dp->d_name) > len) {
                                // Not enough room
                                *((char*)buf) = '\0';
                                data_read = ERR_VFS_INSUFFICIENT_BUF;
                        } else {
                                strcpy((char*)buf, dp->d_name);
                                data_read = strlen(dp->d_name);
                        }
                }
                break;
        }
        return data_read;
}



-- Attached file included as plaintext by Listar --
-- File: kernel_interface.h

//----------------------------------------------------------------------
// kernel_interface.h
// This is the internal interface used by the storage kit to 
// communicate with the kernel
//----------------------------------------------------------------------
#ifndef _sk_kernel_interface_h_
#define _sk_kernel_interface_h_

//#include <SupportKit.h>       
#include <sys/types.h>
#include <sys/stat.h>


// stolen from the NewOS kernel
typedef enum {
        STREAM_TYPE_ANY = 0,
        STREAM_TYPE_FILE,
        STREAM_TYPE_DIR,
        STREAM_TYPE_DEVICE
} stream_type;

typedef enum {
        SEEK_SET = 0,
        SEEK_CUR,
        SEEK_END
} seek_type;

/* VFS errors */
#define ERR_VFS_GENERAL          -3072
#define ERR_VFS_INVALID_FS       ERR_VFS_GENERAL-1
#define ERR_VFS_NOT_MOUNTPOINT   ERR_VFS_GENERAL-2
#define ERR_VFS_PATH_NOT_FOUND   ERR_VFS_GENERAL-3
#define ERR_VFS_INSUFFICIENT_BUF ERR_VFS_GENERAL-4
#define ERR_VFS_READONLY_FS      ERR_VFS_GENERAL-5
#define ERR_VFS_ALREADY_EXISTS   ERR_VFS_GENERAL-6
#define ERR_VFS_FS_BUSY          ERR_VFS_GENERAL-7
#define ERR_VFS_FD_TABLE_FULL    ERR_VFS_GENERAL-8
#define ERR_VFS_CROSS_FS_RENAME  ERR_VFS_GENERAL-9
#define ERR_VFS_DIR_NOT_EMPTY    ERR_VFS_GENERAL-10
#define ERR_VFS_NOT_DIR          ERR_VFS_GENERAL-11
#define ERR_VFS_WRONG_STREAM_TYPE   ERR_VFS_GENERAL-12
#define ERR_VFS_ALREADY_MOUNTPOINT ERR_VFS_GENERAL-13
/* General errors */
#define NO_ERROR                 0
#define ERR_GENERAL              -1
#define ERR_NO_MEMORY            ERR_GENERAL-1
#define ERR_IO_ERROR             ERR_GENERAL-2
#define ERR_INVALID_ARGS         ERR_GENERAL-3
#define ERR_TIMED_OUT            ERR_GENERAL-4
#define ERR_NOT_ALLOWED          ERR_GENERAL-5
#define ERR_PERMISSION_DENIED    ERR_GENERAL-6
#define ERR_INVALID_BINARY       ERR_GENERAL-7
#define ERR_INVALID_HANDLE       ERR_GENERAL-8
#define ERR_NO_MORE_HANDLES      ERR_GENERAL-9
#define ERR_UNIMPLEMENTED        ERR_GENERAL-10
#define ERR_TOO_BIG              ERR_GENERAL-11
#define ERR_NOT_FOUND            ERR_GENERAL-12
#define ERR_NOT_IMPLEMENTED_YET  ERR_GENERAL-13
#define ERR_NOMORE_HANDLES       ERR_GENERAL-14


//----------------------------------------------------------------------
// user_* functions pulled from NewOS's vfs.h (with the "user_" part removed)
//----------------------------------------------------------------------
//int mount(const char *path, const char *device, const char *fs_name, void 
*args);
//int unmount(const char *path);
//int sync(void); 
//int open(const char *path, stream_type st, int omode);
//int close(int fd);
//int fsync(int fd);
//ssize_t read(int fd, void *buf, off_t pos, ssize_t len);
//ssize_t write(int fd, const void *buf, off_t pos, ssize_t len);
//int seek(int fd, off_t pos, seek_type seek_type);
//int ioctl(int fd, int op, void *buf, size_t len);
//int create(const char *path, stream_type stream_type);
//int unlink(const char *path);
//int rename(const char *oldpath, const char *newpath);
//int rstat(const char *path, struct file_stat *stat);
//int wstat(const char *path, struct file_stat *stat, int stat_mask);
//int getcwd(char *buf, size_t size);
//int setcwd(const char* path);
//int dup(int fd);
//int dup2(int ofd, int nfd);
//----------------------------------------------------------------------

namespace storage_kit {

int open(const char *path, stream_type st, int omode);
int close(int fd);
size_t read(int fd, void *buf, off_t pos, ssize_t len);
size_t write(int fd, const void *buf, off_t pos, ssize_t len);
int alloc_fd();
void free_fd(int fd);


}

#endif







[ Home | Signup | Help | Login | Archives | Lists ]

All trademarks and copyrights within the FreeLists archives are owned by their respective owners.
Everything else ©2007 Avenir Technologies, LLC.