Ignore:
File:
1 edited

Legend:

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

    r6639ae1 r19f857a  
    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)
    57 {
    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);
     65bool vfs_files_init(void)
     66{
     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 *));
    66         }
    67         fibril_mutex_unlock(&VFS_DATA->lock);
     71                memset(files, 0, MAX_OPEN_FILES * sizeof(vfs_file_t *));
     72        }
    6873        return true;
    6974}
    7075
    7176/** Cleanup the table of open files. */
    72 static void vfs_files_done(void)
     77void vfs_files_done(void)
    7378{
    7479        int i;
    7580
    76         if (!FILES)
     81        if (!files)
    7782                return;
    7883
    7984        for (i = 0; i < MAX_OPEN_FILES; i++) {
    80                 if (FILES[i]) {
    81                         (void) vfs_close_internal(FILES[i]);
     85                if (files[i]) {
     86                        (void) vfs_close_internal(files[i]);
    8287                        (void) vfs_fd_free(i);
    8388                }
    8489        }
    8590       
    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 
     91        free(files);
     92}
    14193
    14294/** Allocate a file descriptor.
     
    159111                i = 0;
    160112       
    161         fibril_mutex_lock(&VFS_DATA->lock);
    162113        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);
     114                if (!files[i]) {
     115                        files[i] = (vfs_file_t *) malloc(sizeof(vfs_file_t));
     116                        if (!files[i])
    167117                                return ENOMEM;
    168                         }
    169118                       
    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);
     119                        memset(files[i], 0, sizeof(vfs_file_t));
     120                        fibril_mutex_initialize(&files[i]->lock);
     121                        vfs_file_addref(files[i]);
    174122                        return (int) i;
    175123                }
     
    187135                }
    188136        }
    189         fibril_mutex_unlock(&VFS_DATA->lock);
    190137       
    191138        return EMFILE;
     
    203150        if (!vfs_files_init())
    204151                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);
     152       
     153        if ((fd < 0) || (fd >= MAX_OPEN_FILES) || (files[fd] == NULL))
    209154                return EBADF;
    210         }
    211        
    212         vfs_file_delref(FILES[fd]);
    213         FILES[fd] = NULL;
    214         fibril_mutex_unlock(&VFS_DATA->lock);
     155       
     156        vfs_file_delref(files[fd]);
     157        files[fd] = NULL;
    215158       
    216159        return EOK;
     
    230173        if (!vfs_files_init())
    231174                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);
     175       
     176        if ((fd < 0) || (fd >= MAX_OPEN_FILES) || (files[fd] != NULL))
    236177                return EINVAL;
    237         }
    238        
    239         FILES[fd] = file;
    240         vfs_file_addref(FILES[fd]);
    241         fibril_mutex_unlock(&VFS_DATA->lock);
     178       
     179        files[fd] = file;
     180        vfs_file_addref(files[fd]);
    242181       
    243182        return EOK;
    244183}
    245184
     185/** Increment reference count of VFS file structure.
     186 *
     187 * @param file          File structure that will have reference count
     188 *                      incremented.
     189 */
     190void vfs_file_addref(vfs_file_t *file)
     191{
     192        /*
     193         * File structures are per-connection, so no-one, except the current
     194         * fibril, should have a reference to them. This is the reason we don't
     195         * do any synchronization here.
     196         */
     197        file->refcnt++;
     198}
     199
     200/** Decrement reference count of VFS file structure.
     201 *
     202 * @param file          File structure that will have reference count
     203 *                      decremented.
     204 */
     205void vfs_file_delref(vfs_file_t *file)
     206{
     207        if (file->refcnt-- == 1) {
     208                /*
     209                 * Lost the last reference to a file, need to drop our reference
     210                 * to the underlying VFS node.
     211                 */
     212                vfs_node_delref(file->node);
     213                free(file);
     214        }
     215}
     216
    246217/** Find VFS file structure for a given file descriptor.
    247218 *
     
    255226                return NULL;
    256227       
    257         fibril_mutex_lock(&VFS_DATA->lock);
    258         if ((fd >= 0) && (fd < MAX_OPEN_FILES)) {
    259                 vfs_file_t *file = FILES[fd];
    260                 if (file != NULL) {
    261                         vfs_file_addref(file);
    262                         fibril_mutex_unlock(&VFS_DATA->lock);
    263                         return file;
    264                 }
    265         }
    266         fibril_mutex_unlock(&VFS_DATA->lock);
     228        if ((fd >= 0) && (fd < MAX_OPEN_FILES))
     229                return files[fd];
    267230       
    268231        return NULL;
    269 }
    270 
    271 /** Stop using a file structure.
    272  *
    273  * @param file          VFS file structure.
    274  */
    275 void vfs_file_put(vfs_file_t *file)
    276 {
    277         fibril_mutex_lock(&VFS_DATA->lock);
    278         vfs_file_delref(file);
    279         fibril_mutex_unlock(&VFS_DATA->lock);
    280232}
    281233
Note: See TracChangeset for help on using the changeset viewer.