Changeset 05b9912 in mainline


Ignore:
Timestamp:
2009-06-03T18:54:49Z (15 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
17fd1d4
Parents:
215abc1
Message:

VFS rewrite:

  • add new VFS methods
    • VFS_NODE for getting VFS node for a file descriptor
    • VFS_OPEN_NODE for opening an i-node directly
    • VFS_DEVICE for getting the underlying device of a file (if any)
    • VFS_SYNC for syncing buffers
  • L_OPEN flag is set to underlying filesystem in VFS_LOOKUP when opening a file to support initialization (if any)
  • VFS_CLOSE is now propagated to underlying filesystem to support cleanup (if any)
Location:
uspace/srv/vfs
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/vfs/vfs.c

    r215abc1 r05b9912  
    9595                        vfs_open(callid, &call);
    9696                        break;
     97                case VFS_OPEN_NODE:
     98                        vfs_open_node(callid, &call);
     99                        break;
    97100                case VFS_CLOSE:
    98101                        vfs_close(callid, &call);
     
    118121                case VFS_RENAME:
    119122                        vfs_rename(callid, &call);
     123                        break;
     124                case VFS_DEVICE:
     125                        vfs_device(callid, &call);
     126                        break;
     127                case VFS_SYNC:
     128                        vfs_sync(callid, &call);
     129                        break;
     130                case VFS_NODE:
     131                        vfs_node(callid, &call);
    120132                        break;
    121133                default:
     
    165177         * Set a connectio handling function/fibril.
    166178         */
     179        async_set_pending(vfs_process_pending_mount);
    167180        async_set_client_connection(vfs_connection);
    168181       
  • uspace/srv/vfs/vfs.h

    r215abc1 r05b9912  
    2929/** @addtogroup fs
    3030 * @{
    31  */ 
     31 */
    3232
    3333#ifndef VFS_VFS_H_
     
    4141#include <devmap.h>
    4242#include <bool.h>
     43#include <ipc/vfs.h>
    4344
    4445// FIXME: according to CONFIG_DEBUG
    45 // #define dprintf(...) printf(__VA_ARGS__)
     46// #define dprintf(...)  printf(__VA_ARGS__)
    4647
    4748#define dprintf(...)
    48 
    49 #define VFS_FIRST       IPC_FIRST_USER_METHOD
    50 
    51 /* Basic types. */
    52 typedef int16_t fs_handle_t;
    53 typedef uint32_t fs_index_t;
    54 
    55 typedef enum {
    56         VFS_READ = VFS_FIRST,
    57         VFS_WRITE,
    58         VFS_TRUNCATE,
    59         VFS_MOUNT,
    60         VFS_UNMOUNT,
    61         VFS_LAST_CMN,   /* keep this the last member of this enum */
    62 } vfs_request_cmn_t;
    63 
    64 typedef enum {
    65         VFS_LOOKUP = VFS_LAST_CMN,
    66         VFS_MOUNTED,
    67         VFS_DESTROY,
    68         VFS_LAST_CLNT,  /* keep this the last member of this enum */
    69 } vfs_request_clnt_t;
    70 
    71 typedef enum {
    72         VFS_REGISTER = VFS_LAST_CMN,
    73         VFS_OPEN,
    74         VFS_CLOSE,
    75         VFS_SEEK,
    76         VFS_MKDIR,
    77         VFS_UNLINK,
    78         VFS_RENAME,
    79         VFS_LAST_SRV,   /* keep this the last member of this enum */
    80 } vfs_request_srv_t;
    81 
    82 #define FS_NAME_MAXLEN  20
    83 
    84 /**
    85  * A structure like this is passed to VFS by each individual FS upon its
    86  * registration. It assosiates a human-readable identifier with each
    87  * registered FS.
    88  */
    89 typedef struct {
    90         /** Unique identifier of the fs. */
    91         char name[FS_NAME_MAXLEN + 1];
    92 } vfs_info_t;
    9349
    9450/**
     
    10662 * VFS_PAIR uniquely represents a file system instance.
    10763 */
    108 #define VFS_PAIR                \
    109         fs_handle_t fs_handle;  \
     64#define VFS_PAIR \
     65        fs_handle_t fs_handle; \
    11066        dev_handle_t dev_handle;
    11167
     
    11773 *              IPC reply.
    11874 */
    119 #define VFS_TRIPLET     \
    120         VFS_PAIR;       \
     75#define VFS_TRIPLET \
     76        VFS_PAIR; \
    12177        fs_index_t index;
    12278
     
    12884        VFS_TRIPLET;
    12985} vfs_triplet_t;
    130 
    131 /*
    132  * Lookup flags.
    133  */
    134 /**
    135  * No lookup flags used.
    136  */
    137 #define L_NONE          0
    138 /**
    139  * Lookup will succeed only if the object is a regular file.  If L_CREATE is
    140  * specified, an empty file will be created. This flag is mutually exclusive
    141  * with L_DIRECTORY.
    142  */
    143 #define L_FILE          1
    144 /**
    145  * Lookup wil succeed only if the object is a directory. If L_CREATE is
    146  * specified, an empty directory will be created. This flag is mutually
    147  * exclusive with L_FILE.
    148  */
    149 #define L_DIRECTORY     2
    150 /**
    151  * When used with L_CREATE, L_EXCLUSIVE will cause the lookup to fail if the
    152  * object already exists. L_EXCLUSIVE is implied when L_DIRECTORY is used.
    153  */
    154 #define L_EXCLUSIVE     4
    155 /**
    156  * L_CREATE is used for creating both regular files and directories.
    157  */
    158 #define L_CREATE        8
    159 /**
    160  * L_LINK is used for linking to an already existing nodes.
    161  */
    162 #define L_LINK          16
    163 /**
    164  * L_UNLINK is used to remove leaves from the file system namespace. This flag
    165  * cannot be passed directly by the client, but will be set by VFS during
    166  * VFS_UNLINK.
    167  */
    168 #define L_UNLINK        32     
    16986
    17087typedef enum vfs_node_type {
     
    235152extern vfs_pair_t rootfs;       /**< Root file system. */
    236153
    237 #define MAX_PATH_LEN            (64 * 1024)
    238 
    239 #define PLB_SIZE                (2 * MAX_PATH_LEN)
    240 
    241154/** Each instance of this type describes one path lookup in progress. */
    242155typedef struct {
     
    260173extern fs_handle_t fs_name_to_handle(char *, bool);
    261174
    262 extern int vfs_lookup_internal(char *, int, vfs_lookup_res_t *, vfs_pair_t *,
    263     ...);
     175extern int vfs_lookup_internal(char *, int, vfs_lookup_res_t *,
     176    vfs_pair_t *, ...);
     177extern int vfs_open_node_internal(vfs_lookup_res_t *);
    264178
    265179extern bool vfs_nodes_init(void);
     
    284198extern void vfs_mount(ipc_callid_t, ipc_call_t *);
    285199extern void vfs_open(ipc_callid_t, ipc_call_t *);
     200extern void vfs_open_node(ipc_callid_t, ipc_call_t *);
     201extern void vfs_device(ipc_callid_t, ipc_call_t *);
     202extern void vfs_sync(ipc_callid_t, ipc_call_t *);
     203extern void vfs_node(ipc_callid_t, ipc_call_t *);
    286204extern void vfs_close(ipc_callid_t, ipc_call_t *);
    287205extern void vfs_read(ipc_callid_t, ipc_call_t *);
  • uspace/srv/vfs/vfs_lookup.c

    r215abc1 r05b9912  
    2929/** @addtogroup fs
    3030 * @{
    31  */ 
     31 */
    3232
    3333/**
    34  * @file        vfs_lookup.c
     34 * @file vfs_lookup.c
    3535 * @brief
    3636 */
     
    4747#include <vfs/canonify.h>
    4848
    49 #define min(a, b)       ((a) < (b) ? (a) : (b))
     49#define min(a, b)  ((a) < (b) ? (a) : (b))
    5050
    5151futex_t plb_futex = FUTEX_INITIALIZER;
    52 link_t plb_head;        /**< PLB entry ring buffer. */
     52link_t plb_head;  /**< PLB entry ring buffer. */
    5353uint8_t *plb = NULL;
    5454
    5555/** Perform a path lookup.
    5656 *
    57  * @param path          Path to be resolved; it must be a NULL-terminated
    58  *                      string.
    59  * @param lflag         Flags to be used during lookup.
    60  * @param result        Empty structure where the lookup result will be stored.
    61  *                      Can be NULL.
    62  * @param altroot       If non-empty, will be used instead of rootfs as the root
    63  *                      of the whole VFS tree.
    64  *
    65  * @return              EOK on success or an error code from errno.h.
     57 * @param path    Path to be resolved; it must be a NULL-terminated
     58 *                string.
     59 * @param lflag   Flags to be used during lookup.
     60 * @param result  Empty structure where the lookup result will be stored.
     61 *                Can be NULL.
     62 * @param altroot If non-empty, will be used instead of rootfs as the root
     63 *                of the whole VFS tree.
     64 *
     65 * @return EOK on success or an error code from errno.h.
     66 *
    6667 */
    6768int vfs_lookup_internal(char *path, int lflag, vfs_lookup_res_t *result,
     
    179180        futex_up(&plb_futex);
    180181
    181         if ((rc == EOK) && result) {
     182        if ((rc == EOK) && (result)) {
    182183                result->triplet.fs_handle = (fs_handle_t) IPC_GET_ARG1(answer);
    183184                result->triplet.dev_handle = (dev_handle_t) IPC_GET_ARG2(answer);
     
    196197}
    197198
     199/** Perform a node open operation.
     200 *
     201 * @return EOK on success or an error code from errno.h.
     202 *
     203 */
     204int vfs_open_node_internal(vfs_lookup_res_t *result)
     205{
     206        int phone = vfs_grab_phone(result->triplet.fs_handle);
     207       
     208        ipc_call_t answer;
     209        aid_t req = async_send_2(phone, VFS_OPEN_NODE,
     210            (ipcarg_t) result->triplet.dev_handle,
     211            (ipcarg_t) result->triplet.index, &answer);
     212       
     213        vfs_release_phone(phone);
     214       
     215        async_serialize_start();
     216        ipcarg_t rc;
     217        async_wait_for(req, &rc);
     218        async_serialize_end();
     219       
     220        if (rc == EOK) {
     221                result->size = (size_t) IPC_GET_ARG1(answer);
     222                result->lnkcnt = (unsigned) IPC_GET_ARG2(answer);
     223                if (IPC_GET_ARG3(answer) & L_FILE)
     224                        result->type = VFS_NODE_FILE;
     225                else if (IPC_GET_ARG3(answer) & L_DIRECTORY)
     226                        result->type = VFS_NODE_DIRECTORY;
     227                else
     228                        result->type = VFS_NODE_UNKNOWN;
     229        }
     230       
     231        return rc;
     232}
     233
    198234/**
    199235 * @}
  • uspace/srv/vfs/vfs_node.c

    r215abc1 r05b9912  
    181181                hash_table_insert(&nodes, key, &node->nh_link);
    182182        } else {
    183                 node = hash_table_get_instance(tmp, vfs_node_t, nh_link);       
     183                node = hash_table_get_instance(tmp, vfs_node_t, nh_link);
    184184                if (node->type == VFS_NODE_UNKNOWN &&
    185185                    result->type != VFS_NODE_UNKNOWN) {
     
    234234/**
    235235 * @}
    236  */ 
     236 */
  • uspace/srv/vfs/vfs_ops.c

    r215abc1 r05b9912  
    9494        aid_t msg;
    9595        ipc_call_t answer;
    96                        
     96       
    9797        /* Resolve the path to the mountpoint. */
    9898        rwlock_write_lock(&namespace_rwlock);
     
    491491                return;
    492492        }
    493 
     493       
    494494        /*
    495495         * The POSIX interface is open(path, oflag, mode).
     
    504504        int mode = IPC_GET_ARG3(*request);
    505505        size_t len;
    506 
     506       
    507507        /*
    508508         * Make sure that we are called with exactly one of L_FILE and
    509          * L_DIRECTORY.
    510          */
    511         if ((lflag & (L_FILE | L_DIRECTORY)) == 0 ||
    512             (lflag & (L_FILE | L_DIRECTORY)) == (L_FILE | L_DIRECTORY)) {
    513                 ipc_answer_0(rid, EINVAL);
    514                 return;
    515         }
    516 
     509         * L_DIRECTORY. Make sure that the user does not pass L_OPEN.
     510         */
     511        if (((lflag & (L_FILE | L_DIRECTORY)) == 0)
     512            || ((lflag & (L_FILE | L_DIRECTORY)) == (L_FILE | L_DIRECTORY))
     513            || ((lflag & L_OPEN) != 0)) {
     514                ipc_answer_0(rid, EINVAL);
     515                return;
     516        }
     517       
    517518        if (oflag & O_CREAT)
    518519                lflag |= L_CREATE;
    519520        if (oflag & O_EXCL)
    520521                lflag |= L_EXCLUSIVE;
    521 
     522       
    522523        ipc_callid_t callid;
    523 
    524524        if (!ipc_data_write_receive(&callid, &len)) {
    525525                ipc_answer_0(callid, EINVAL);
     
    527527                return;
    528528        }
     529       
    529530        char *path = malloc(len + 1);
    530531        if (!path) {
     
    533534                return;
    534535        }
     536       
    535537        int rc;
    536538        if ((rc = ipc_data_write_finalize(callid, path, len))) {
     
    550552        else
    551553                rwlock_read_lock(&namespace_rwlock);
    552 
     554       
    553555        /* The path is now populated and we can call vfs_lookup_internal(). */
    554556        vfs_lookup_res_t lr;
    555         rc = vfs_lookup_internal(path, lflag, &lr, NULL);
    556         if (rc) {
     557        rc = vfs_lookup_internal(path, lflag | L_OPEN, &lr, NULL);
     558        if (rc != EOK) {
    557559                if (lflag & L_CREATE)
    558560                        rwlock_write_unlock(&namespace_rwlock);
     
    563565                return;
    564566        }
    565 
     567       
    566568        /* Path is no longer needed. */
    567569        free(path);
    568 
     570       
    569571        vfs_node_t *node = vfs_node_get(&lr);
    570572        if (lflag & L_CREATE)
     
    572574        else
    573575                rwlock_read_unlock(&namespace_rwlock);
    574 
     576       
    575577        /* Truncate the file if requested and if necessary. */
    576578        if (oflag & O_TRUNC) {
     
    589591                rwlock_write_unlock(&node->contents_rwlock);
    590592        }
    591 
     593       
    592594        /*
    593595         * Get ourselves a file descriptor and the corresponding vfs_file_t
     
    602604        vfs_file_t *file = vfs_file_get(fd);
    603605        file->node = node;
    604         if (oflag & O_APPEND) 
     606        if (oflag & O_APPEND)
    605607                file->append = true;
    606 
     608       
    607609        /*
    608610         * The following increase in reference count is for the fact that the
     
    614616        vfs_node_addref(node);
    615617        vfs_node_put(node);
    616 
     618       
    617619        /* Success! Return the new file descriptor to the client. */
    618620        ipc_answer_1(rid, EOK, fd);
    619621}
    620622
     623void vfs_open_node(ipc_callid_t rid, ipc_call_t *request)
     624{
     625        // FIXME: check for sanity of the supplied fs, dev and index
     626       
     627        if (!vfs_files_init()) {
     628                ipc_answer_0(rid, ENOMEM);
     629                return;
     630        }
     631       
     632        /*
     633         * The interface is open_node(fs, dev, index, oflag).
     634         */
     635        vfs_lookup_res_t lr;
     636       
     637        lr.triplet.fs_handle = IPC_GET_ARG1(*request);
     638        lr.triplet.dev_handle = IPC_GET_ARG2(*request);
     639        lr.triplet.index = IPC_GET_ARG3(*request);
     640        int oflag = IPC_GET_ARG4(*request);
     641       
     642        rwlock_read_lock(&namespace_rwlock);
     643       
     644        int rc = vfs_open_node_internal(&lr);
     645        if (rc != EOK) {
     646                rwlock_read_unlock(&namespace_rwlock);
     647                ipc_answer_0(rid, rc);
     648                return;
     649        }
     650       
     651        vfs_node_t *node = vfs_node_get(&lr);
     652        rwlock_read_unlock(&namespace_rwlock);
     653       
     654        /* Truncate the file if requested and if necessary. */
     655        if (oflag & O_TRUNC) {
     656                rwlock_write_lock(&node->contents_rwlock);
     657                if (node->size) {
     658                        rc = vfs_truncate_internal(node->fs_handle,
     659                            node->dev_handle, node->index, 0);
     660                        if (rc) {
     661                                rwlock_write_unlock(&node->contents_rwlock);
     662                                vfs_node_put(node);
     663                                ipc_answer_0(rid, rc);
     664                                return;
     665                        }
     666                        node->size = 0;
     667                }
     668                rwlock_write_unlock(&node->contents_rwlock);
     669        }
     670       
     671        /*
     672         * Get ourselves a file descriptor and the corresponding vfs_file_t
     673         * structure.
     674         */
     675        int fd = vfs_fd_alloc();
     676        if (fd < 0) {
     677                vfs_node_put(node);
     678                ipc_answer_0(rid, fd);
     679                return;
     680        }
     681        vfs_file_t *file = vfs_file_get(fd);
     682        file->node = node;
     683        if (oflag & O_APPEND)
     684                file->append = true;
     685       
     686        /*
     687         * The following increase in reference count is for the fact that the
     688         * file is being opened and that a file structure is pointing to it.
     689         * It is necessary so that the file will not disappear when
     690         * vfs_node_put() is called. The reference will be dropped by the
     691         * respective VFS_CLOSE.
     692         */
     693        vfs_node_addref(node);
     694        vfs_node_put(node);
     695       
     696        /* Success! Return the new file descriptor to the client. */
     697        ipc_answer_1(rid, EOK, fd);
     698}
     699
     700void vfs_node(ipc_callid_t rid, ipc_call_t *request)
     701{
     702        int fd = IPC_GET_ARG1(*request);
     703       
     704        /* Lookup the file structure corresponding to the file descriptor. */
     705        vfs_file_t *file = vfs_file_get(fd);
     706        if (!file) {
     707                ipc_answer_0(rid, ENOENT);
     708                return;
     709        }
     710       
     711        ipc_answer_3(rid, EOK, file->node->fs_handle,
     712            file->node->dev_handle, file->node->index);
     713}
     714
     715void vfs_device(ipc_callid_t rid, ipc_call_t *request)
     716{
     717        int fd = IPC_GET_ARG1(*request);
     718       
     719        /* Lookup the file structure corresponding to the file descriptor. */
     720        vfs_file_t *file = vfs_file_get(fd);
     721        if (!file) {
     722                ipc_answer_0(rid, ENOENT);
     723                return;
     724        }
     725       
     726        /*
     727         * Lock the open file structure so that no other thread can manipulate
     728         * the same open file at a time.
     729         */
     730        futex_down(&file->lock);
     731        int fs_phone = vfs_grab_phone(file->node->fs_handle);
     732       
     733        /* Make a VFS_DEVICE request at the destination FS server. */
     734        aid_t msg;
     735        ipc_call_t answer;
     736        msg = async_send_2(fs_phone, IPC_GET_METHOD(*request),
     737            file->node->dev_handle, file->node->index, &answer);
     738       
     739        /* Wait for reply from the FS server. */
     740        ipcarg_t rc;
     741        async_wait_for(msg, &rc);
     742       
     743        vfs_release_phone(fs_phone);
     744        futex_up(&file->lock);
     745       
     746        ipc_answer_1(rid, EOK, IPC_GET_ARG1(answer));
     747}
     748
     749void vfs_sync(ipc_callid_t rid, ipc_call_t *request)
     750{
     751        int fd = IPC_GET_ARG1(*request);
     752       
     753        /* Lookup the file structure corresponding to the file descriptor. */
     754        vfs_file_t *file = vfs_file_get(fd);
     755        if (!file) {
     756                ipc_answer_0(rid, ENOENT);
     757                return;
     758        }
     759       
     760        /*
     761         * Lock the open file structure so that no other thread can manipulate
     762         * the same open file at a time.
     763         */
     764        futex_down(&file->lock);
     765        int fs_phone = vfs_grab_phone(file->node->fs_handle);
     766       
     767        /* Make a VFS_SYMC request at the destination FS server. */
     768        aid_t msg;
     769        ipc_call_t answer;
     770        msg = async_send_2(fs_phone, IPC_GET_METHOD(*request),
     771            file->node->dev_handle, file->node->index, &answer);
     772       
     773        /* Wait for reply from the FS server. */
     774        ipcarg_t rc;
     775        async_wait_for(msg, &rc);
     776       
     777        vfs_release_phone(fs_phone);
     778        futex_up(&file->lock);
     779       
     780        ipc_answer_0(rid, rc);
     781}
     782
    621783void vfs_close(ipc_callid_t rid, ipc_call_t *request)
    622784{
    623785        int fd = IPC_GET_ARG1(*request);
    624         int rc = vfs_fd_free(fd);
    625         ipc_answer_0(rid, rc);
     786       
     787        /* Lookup the file structure corresponding to the file descriptor. */
     788        vfs_file_t *file = vfs_file_get(fd);
     789        if (!file) {
     790                ipc_answer_0(rid, ENOENT);
     791                return;
     792        }
     793       
     794        /*
     795         * Lock the open file structure so that no other thread can manipulate
     796         * the same open file at a time.
     797         */
     798        futex_down(&file->lock);
     799       
     800        int fs_phone = vfs_grab_phone(file->node->fs_handle);
     801       
     802        /* Make a VFS_CLOSE request at the destination FS server. */
     803        aid_t msg;
     804        ipc_call_t answer;
     805        msg = async_send_2(fs_phone, IPC_GET_METHOD(*request),
     806            file->node->dev_handle, file->node->index, &answer);
     807       
     808        /* Wait for reply from the FS server. */
     809        ipcarg_t rc;
     810        async_wait_for(msg, &rc);
     811       
     812        vfs_release_phone(fs_phone);
     813        futex_up(&file->lock);
     814       
     815        int retval = IPC_GET_ARG1(answer);
     816        if (retval != EOK)
     817                ipc_answer_0(rid, retval);
     818       
     819        retval = vfs_fd_free(fd);
     820        ipc_answer_0(rid, retval);
    626821}
    627822
     
    706901        ipc_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
    707902       
    708         vfs_release_phone(fs_phone);
    709        
    710903        /* Wait for reply from the FS server. */
    711904        ipcarg_t rc;
    712905        async_wait_for(msg, &rc);
     906       
     907        vfs_release_phone(fs_phone);
     908       
    713909        size_t bytes = IPC_GET_ARG1(answer);
    714910
     
    11171313/**
    11181314 * @}
    1119  */ 
     1315 */
  • uspace/srv/vfs/vfs_register.c

    r215abc1 r05b9912  
    279279        dprintf("\"%.*s\" filesystem successfully registered, handle=%d.\n",
    280280            FS_NAME_MAXLEN, fs_info->vfs_info.name, fs_info->fs_handle);
    281        
    282         /* Process pending mount requests possibly waiting
    283          * for this filesystem implementation.
    284          */
    285         vfs_process_pending_mount();
    286281}
    287282
     
    321316                         */
    322317                        fibril_inc_sercount();
    323                         return fs->phone; 
     318                        return fs->phone;
    324319                }
    325320        }
Note: See TracChangeset for help on using the changeset viewer.