Ignore:
File:
1 edited

Legend:

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

    r4fe94c66 r553492be  
    3838#include <errno.h>
    3939#include <stdlib.h>
    40 #include <str.h>
     40#include <string.h>
    4141#include <assert.h>
    4242#include <bool.h>
    4343#include <fibril.h>
    44 #include <fibril_synch.h>
     44#include <fibril_sync.h>
    4545#include "vfs.h"
    4646
    47 #define VFS_DATA        ((vfs_client_data_t *) async_client_data_get())
    48 #define FILES           (VFS_DATA->files)
    49 
    50 typedef struct {
    51         fibril_mutex_t lock;
    52         vfs_file_t **files;
    53 } vfs_client_data_t;
     47/**
     48 * This is a per-connection table of open files.
     49 * Our assumption is that each client opens only one connection and therefore
     50 * there is one table of open files per task. However, this may not be the case
     51 * and the client can open more connections to VFS. In that case, there will be
     52 * several tables and several file handle name spaces per task. Besides of this,
     53 * the functionality will stay unchanged. So unless the client knows what it is
     54 * doing, it should open one connection to VFS only.
     55 *
     56 * Allocation of the open files table is deferred until the client makes the
     57 * first VFS_OPEN operation.
     58 *
     59 * This resource being per-connection and, in the first place, per-fibril, we
     60 * don't need to protect it by a mutex.
     61 */
     62fibril_local vfs_file_t **files = NULL;
    5463
    5564/** Initialize the table of open files. */
    56 static bool vfs_files_init(void)
     65bool vfs_files_init(void)
    5766{
    58         fibril_mutex_lock(&VFS_DATA->lock);
    59         if (!FILES) {
    60                 FILES = malloc(MAX_OPEN_FILES * sizeof(vfs_file_t *));
    61                 if (!FILES) {
    62                         fibril_mutex_unlock(&VFS_DATA->lock);
     67        if (!files) {
     68                files = malloc(MAX_OPEN_FILES * sizeof(vfs_file_t *));
     69                if (!files)
    6370                        return false;
    64                 }
    65                 memset(FILES, 0, MAX_OPEN_FILES * sizeof(vfs_file_t *));
     71                memset(files, 0, MAX_OPEN_FILES * sizeof(vfs_file_t *));
    6672        }
    67         fibril_mutex_unlock(&VFS_DATA->lock);
    6873        return true;
    6974}
    7075
    71 /** Cleanup the table of open files. */
    72 static void vfs_files_done(void)
    73 {
    74         int i;
    75 
    76         if (!FILES)
    77                 return;
    78 
    79         for (i = 0; i < MAX_OPEN_FILES; i++) {
    80                 if (FILES[i]) {
    81                         (void) vfs_close_internal(FILES[i]);
    82                         (void) vfs_fd_free(i);
    83                 }
    84         }
    85        
    86         free(FILES);
    87 }
    88 
    89 void *vfs_client_data_create(void)
    90 {
    91         vfs_client_data_t *vfs_data;
    92 
    93         vfs_data = malloc(sizeof(vfs_client_data_t));
    94         if (vfs_data) {
    95                 fibril_mutex_initialize(&vfs_data->lock);
    96                 vfs_data->files = NULL;
    97         }
    98        
    99         return vfs_data;
    100 }
    101 
    102 void vfs_client_data_destroy(void *data)
    103 {
    104         vfs_client_data_t *vfs_data = (vfs_client_data_t *) data;
    105 
    106         vfs_files_done();
    107         free(vfs_data);
    108 }
    109 
    110 /** Increment reference count of VFS file structure.
    111  *
    112  * @param file          File structure that will have reference count
    113  *                      incremented.
    114  */
    115 static void vfs_file_addref(vfs_file_t *file)
    116 {
    117         assert(fibril_mutex_is_locked(&VFS_DATA->lock));
    118 
    119         file->refcnt++;
    120 }
    121 
    122 /** Decrement reference count of VFS file structure.
    123  *
    124  * @param file          File structure that will have reference count
    125  *                      decremented.
    126  */
    127 static void vfs_file_delref(vfs_file_t *file)
    128 {
    129         assert(fibril_mutex_is_locked(&VFS_DATA->lock));
    130 
    131         if (file->refcnt-- == 1) {
    132                 /*
    133                  * Lost the last reference to a file, need to drop our reference
    134                  * to the underlying VFS node.
    135                  */
    136                 vfs_node_delref(file->node);
    137                 free(file);
    138         }
    139 }
    140 
    141 
    14276/** Allocate a file descriptor.
    14377 *
    144  * @param desc If true, look for an available file descriptor
    145  *             in a descending order.
    146  *
    147  * @return First available file descriptor or a negative error
    148  *         code.
     78 * @return              First available file descriptor or a negative error
     79 *                      code.
    14980 */
    150 int vfs_fd_alloc(bool desc)
     81int vfs_fd_alloc(void)
    15182{
    15283        if (!vfs_files_init())
     
    15485       
    15586        unsigned int i;
    156         if (desc)
    157                 i = MAX_OPEN_FILES - 1;
    158         else
    159                 i = 0;
    160        
    161         fibril_mutex_lock(&VFS_DATA->lock);
    162         while (true) {
    163                 if (!FILES[i]) {
    164                         FILES[i] = (vfs_file_t *) malloc(sizeof(vfs_file_t));
    165                         if (!FILES[i]) {
    166                                 fibril_mutex_unlock(&VFS_DATA->lock);
     87        for (i = 0; i < MAX_OPEN_FILES; i++) {
     88                if (!files[i]) {
     89                        files[i] = (vfs_file_t *) malloc(sizeof(vfs_file_t));
     90                        if (!files[i])
    16791                                return ENOMEM;
    168                         }
    16992                       
    170                         memset(FILES[i], 0, sizeof(vfs_file_t));
    171                         fibril_mutex_initialize(&FILES[i]->lock);
    172                         vfs_file_addref(FILES[i]);
    173                         fibril_mutex_unlock(&VFS_DATA->lock);
     93                        memset(files[i], 0, sizeof(vfs_file_t));
     94                        fibril_mutex_initialize(&files[i]->lock);
     95                        vfs_file_addref(files[i]);
    17496                        return (int) i;
    17597                }
    176                
    177                 if (desc) {
    178                         if (i == 0)
    179                                 break;
    180                        
    181                         i--;
    182                 } else {
    183                         if (i == MAX_OPEN_FILES - 1)
    184                                 break;
    185                        
    186                         i++;
    187                 }
    18898        }
    189         fibril_mutex_unlock(&VFS_DATA->lock);
    19099       
    191100        return EMFILE;
     
    203112        if (!vfs_files_init())
    204113                return ENOMEM;
    205 
    206         fibril_mutex_lock(&VFS_DATA->lock);     
    207         if ((fd < 0) || (fd >= MAX_OPEN_FILES) || (FILES[fd] == NULL)) {
    208                 fibril_mutex_unlock(&VFS_DATA->lock);
     114       
     115        if ((fd < 0) || (fd >= MAX_OPEN_FILES) || (files[fd] == NULL))
    209116                return EBADF;
    210         }
    211117       
    212         vfs_file_delref(FILES[fd]);
    213         FILES[fd] = NULL;
    214         fibril_mutex_unlock(&VFS_DATA->lock);
     118        vfs_file_delref(files[fd]);
     119        files[fd] = NULL;
    215120       
    216121        return EOK;
    217122}
    218123
    219 /** Assign a file to a file descriptor.
     124/** Increment reference count of VFS file structure.
    220125 *
    221  * @param file File to assign.
    222  * @param fd   File descriptor to assign to.
     126 * @param file          File structure that will have reference count
     127 *                      incremented.
     128 */
     129void vfs_file_addref(vfs_file_t *file)
     130{
     131        /*
     132         * File structures are per-connection, so no-one, except the current
     133         * fibril, should have a reference to them. This is the reason we don't
     134         * do any synchronization here.
     135         */
     136        file->refcnt++;
     137}
     138
     139/** Decrement reference count of VFS file structure.
    223140 *
    224  * @return EOK on success or EINVAL if fd is an invalid or already
    225  *         used file descriptor.
    226  *
     141 * @param file          File structure that will have reference count
     142 *                      decremented.
    227143 */
    228 int vfs_fd_assign(vfs_file_t *file, int fd)
     144void vfs_file_delref(vfs_file_t *file)
    229145{
    230         if (!vfs_files_init())
    231                 return ENOMEM;
    232 
    233         fibril_mutex_lock(&VFS_DATA->lock);     
    234         if ((fd < 0) || (fd >= MAX_OPEN_FILES) || (FILES[fd] != NULL)) {
    235                 fibril_mutex_unlock(&VFS_DATA->lock);
    236                 return EINVAL;
     146        if (file->refcnt-- == 1) {
     147                /*
     148                 * Lost the last reference to a file, need to drop our reference
     149                 * to the underlying VFS node.
     150                 */
     151                vfs_node_delref(file->node);
     152                free(file);
    237153        }
    238        
    239         FILES[fd] = file;
    240         vfs_file_addref(FILES[fd]);
    241         fibril_mutex_unlock(&VFS_DATA->lock);
    242        
    243         return EOK;
    244154}
    245155
     
    255165                return NULL;
    256166       
    257         fibril_mutex_lock(&VFS_DATA->lock);
    258         if ((fd >= 0) && (fd < MAX_OPEN_FILES)) {
    259                 vfs_file_t *file = FILES[fd];
    260                 vfs_file_addref(file);
    261                 fibril_mutex_unlock(&VFS_DATA->lock);
    262                 return file;
    263         }
    264         fibril_mutex_unlock(&VFS_DATA->lock);
     167        if ((fd >= 0) && (fd < MAX_OPEN_FILES))
     168                return files[fd];
    265169       
    266170        return NULL;
    267 }
    268 
    269 /** Stop using a file structure.
    270  *
    271  * @param file          VFS file structure.
    272  */
    273 void vfs_file_put(vfs_file_t *file)
    274 {
    275         fibril_mutex_lock(&VFS_DATA->lock);
    276         vfs_file_delref(file);
    277         fibril_mutex_unlock(&VFS_DATA->lock);
    278171}
    279172
Note: See TracChangeset for help on using the changeset viewer.