Changeset 7a51d75 in mainline for uspace/srv/vfs/vfs_file.c


Ignore:
Timestamp:
2011-01-28T15:30:42Z (13 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
ea991e84
Parents:
c5c003c (diff), 2b96463 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge development/ changes

File:
1 edited

Legend:

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

    rc5c003c r7a51d75  
    4545#include "vfs.h"
    4646
    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  */
    62 fibril_local vfs_file_t **files = NULL;
     47#define VFS_DATA        ((vfs_client_data_t *) async_client_data_get())
     48#define FILES           (VFS_DATA->files)
     49
     50typedef struct {
     51        fibril_mutex_t lock;
     52        vfs_file_t **files;
     53} vfs_client_data_t;
    6354
    6455/** Initialize the table of open files. */
    65 bool vfs_files_init(void)
    66 {
    67         if (!files) {
    68                 files = malloc(MAX_OPEN_FILES * sizeof(vfs_file_t *));
    69                 if (!files)
     56static 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);
    7063                        return false;
    71                 memset(files, 0, MAX_OPEN_FILES * sizeof(vfs_file_t *));
    72         }
     64                }
     65                memset(FILES, 0, MAX_OPEN_FILES * sizeof(vfs_file_t *));
     66        }
     67        fibril_mutex_unlock(&VFS_DATA->lock);
    7368        return true;
    7469}
    7570
    7671/** Cleanup the table of open files. */
    77 void vfs_files_done(void)
     72static void vfs_files_done(void)
    7873{
    7974        int i;
    8075
    81         if (!files)
     76        if (!FILES)
    8277                return;
    8378
    8479        for (i = 0; i < MAX_OPEN_FILES; i++) {
    85                 if (files[i]) {
    86                         (void) vfs_close_internal(files[i]);
     80                if (FILES[i]) {
     81                        (void) vfs_close_internal(FILES[i]);
    8782                        (void) vfs_fd_free(i);
    8883                }
    8984        }
    9085       
    91         free(files);
    92 }
     86        free(FILES);
     87}
     88
     89void *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
     102void 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 */
     115static 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 */
     127static 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
    93141
    94142/** Allocate a file descriptor.
     
    111159                i = 0;
    112160       
     161        fibril_mutex_lock(&VFS_DATA->lock);
    113162        while (true) {
    114                 if (!files[i]) {
    115                         files[i] = (vfs_file_t *) malloc(sizeof(vfs_file_t));
    116                         if (!files[i])
     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);
    117167                                return ENOMEM;
     168                        }
    118169                       
    119                         memset(files[i], 0, sizeof(vfs_file_t));
    120                         fibril_mutex_initialize(&files[i]->lock);
    121                         vfs_file_addref(files[i]);
     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);
    122174                        return (int) i;
    123175                }
     
    135187                }
    136188        }
     189        fibril_mutex_unlock(&VFS_DATA->lock);
    137190       
    138191        return EMFILE;
     
    150203        if (!vfs_files_init())
    151204                return ENOMEM;
    152        
    153         if ((fd < 0) || (fd >= MAX_OPEN_FILES) || (files[fd] == NULL))
     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);
    154209                return EBADF;
    155        
    156         vfs_file_delref(files[fd]);
    157         files[fd] = NULL;
     210        }
     211       
     212        vfs_file_delref(FILES[fd]);
     213        FILES[fd] = NULL;
     214        fibril_mutex_unlock(&VFS_DATA->lock);
    158215       
    159216        return EOK;
     
    173230        if (!vfs_files_init())
    174231                return ENOMEM;
    175        
    176         if ((fd < 0) || (fd >= MAX_OPEN_FILES) || (files[fd] != NULL))
     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);
    177236                return EINVAL;
    178        
    179         files[fd] = file;
    180         vfs_file_addref(files[fd]);
     237        }
     238       
     239        FILES[fd] = file;
     240        vfs_file_addref(FILES[fd]);
     241        fibril_mutex_unlock(&VFS_DATA->lock);
    181242       
    182243        return EOK;
    183244}
    184245
    185 /** Increment reference count of VFS file structure.
    186  *
    187  * @param file          File structure that will have reference count
    188  *                      incremented.
    189  */
    190 void 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  */
    205 void 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 
    217246/** Find VFS file structure for a given file descriptor.
    218247 *
     
    226255                return NULL;
    227256       
    228         if ((fd >= 0) && (fd < MAX_OPEN_FILES))
    229                 return files[fd];
     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);
    230265       
    231266        return NULL;
     267}
     268
     269/** Stop using a file structure.
     270 *
     271 * @param file          VFS file structure.
     272 */
     273void 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);
    232278}
    233279
Note: See TracChangeset for help on using the changeset viewer.