Ignore:
File:
1 edited

Legend:

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

    re2ab36f1 r6639ae1  
    4343#include <fibril.h>
    4444#include <fibril_synch.h>
    45 #include <adt/list.h>
    46 #include <task.h>
    4745#include "vfs.h"
    4846
    49 #define VFS_DATA        ((vfs_client_data_t *) async_get_client_data())
     47#define VFS_DATA        ((vfs_client_data_t *) async_client_data_get())
    5048#define FILES           (VFS_DATA->files)
    5149
    5250typedef struct {
    5351        fibril_mutex_t lock;
    54         fibril_condvar_t cv;
    55         list_t passed_handles;
    5652        vfs_file_t **files;
    5753} vfs_client_data_t;
    5854
    59 typedef struct {
    60         link_t link;
    61         int handle;
    62 } vfs_boxed_handle_t;
    63 
    64 static int _vfs_fd_free(vfs_client_data_t *, int);
    65 
    6655/** Initialize the table of open files. */
    67 static bool vfs_files_init(vfs_client_data_t *vfs_data)
    68 {
    69         fibril_mutex_lock(&vfs_data->lock);
    70         if (!vfs_data->files) {
    71                 vfs_data->files = malloc(MAX_OPEN_FILES * sizeof(vfs_file_t *));
    72                 if (!vfs_data->files) {
    73                         fibril_mutex_unlock(&vfs_data->lock);
     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);
    7463                        return false;
    7564                }
    76                 memset(vfs_data->files, 0, MAX_OPEN_FILES * sizeof(vfs_file_t *));
    77         }
    78         fibril_mutex_unlock(&vfs_data->lock);
     65                memset(FILES, 0, MAX_OPEN_FILES * sizeof(vfs_file_t *));
     66        }
     67        fibril_mutex_unlock(&VFS_DATA->lock);
    7968        return true;
    8069}
    8170
    8271/** Cleanup the table of open files. */
    83 static void vfs_files_done(vfs_client_data_t *vfs_data)
     72static void vfs_files_done(void)
    8473{
    8574        int i;
    8675
    87         if (!vfs_data->files)
     76        if (!FILES)
    8877                return;
    8978
    9079        for (i = 0; i < MAX_OPEN_FILES; i++) {
    91                 if (vfs_data->files[i])
    92                         (void) _vfs_fd_free(vfs_data, i);
    93         }
    94        
    95         free(vfs_data->files);
    96 
    97         while (!list_empty(&vfs_data->passed_handles)) {
    98                 link_t *lnk;
    99                 vfs_boxed_handle_t *bh;
    100                
    101                 lnk = list_first(&vfs_data->passed_handles);
    102                 list_remove(lnk);
    103 
    104                 bh = list_get_instance(lnk, vfs_boxed_handle_t, link);
    105                 free(bh);
    106         }
     80                if (FILES[i]) {
     81                        (void) vfs_close_internal(FILES[i]);
     82                        (void) vfs_fd_free(i);
     83                }
     84        }
     85       
     86        free(FILES);
    10787}
    10888
     
    11494        if (vfs_data) {
    11595                fibril_mutex_initialize(&vfs_data->lock);
    116                 fibril_condvar_initialize(&vfs_data->cv);
    117                 list_initialize(&vfs_data->passed_handles);
    11896                vfs_data->files = NULL;
    11997        }
     
    126104        vfs_client_data_t *vfs_data = (vfs_client_data_t *) data;
    127105
    128         vfs_files_done(vfs_data);
     106        vfs_files_done();
    129107        free(vfs_data);
    130 }
    131 
    132 /** Close the file in the endpoint FS server. */
    133 static int vfs_file_close_remote(vfs_file_t *file)
    134 {
    135         assert(!file->refcnt);
    136        
    137         async_exch_t *exch = vfs_exchange_grab(file->node->fs_handle);
    138        
    139         ipc_call_t answer;
    140         aid_t msg = async_send_2(exch, VFS_OUT_CLOSE, file->node->service_id,
    141             file->node->index, &answer);
    142        
    143         vfs_exchange_release(exch);
    144        
    145         sysarg_t rc;
    146         async_wait_for(msg, &rc);
    147        
    148         return IPC_GET_ARG1(answer);
    149108}
    150109
     
    154113 *                      incremented.
    155114 */
    156 static void vfs_file_addref(vfs_client_data_t *vfs_data, vfs_file_t *file)
    157 {
    158         assert(fibril_mutex_is_locked(&vfs_data->lock));
     115static void vfs_file_addref(vfs_file_t *file)
     116{
     117        assert(fibril_mutex_is_locked(&VFS_DATA->lock));
    159118
    160119        file->refcnt++;
     
    166125 *                      decremented.
    167126 */
    168 static int vfs_file_delref(vfs_client_data_t *vfs_data, vfs_file_t *file)
    169 {
    170         int rc = EOK;
    171 
    172         assert(fibril_mutex_is_locked(&vfs_data->lock));
     127static void vfs_file_delref(vfs_file_t *file)
     128{
     129        assert(fibril_mutex_is_locked(&VFS_DATA->lock));
    173130
    174131        if (file->refcnt-- == 1) {
    175132                /*
    176                  * Lost the last reference to a file, need to close it in the
    177                  * endpoint FS and drop our reference to the underlying VFS node.
     133                 * Lost the last reference to a file, need to drop our reference
     134                 * to the underlying VFS node.
    178135                 */
    179                 rc = vfs_file_close_remote(file);
    180136                vfs_node_delref(file->node);
    181137                free(file);
    182138        }
    183 
    184         return rc;
    185 }
    186 
    187 static int _vfs_fd_alloc(vfs_client_data_t *vfs_data, bool desc)
    188 {
    189         if (!vfs_files_init(vfs_data))
     139}
     140
     141
     142/** Allocate a file descriptor.
     143 *
     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.
     149 */
     150int vfs_fd_alloc(bool desc)
     151{
     152        if (!vfs_files_init())
    190153                return ENOMEM;
    191154       
     
    196159                i = 0;
    197160       
    198         fibril_mutex_lock(&vfs_data->lock);
     161        fibril_mutex_lock(&VFS_DATA->lock);
    199162        while (true) {
    200                 if (!vfs_data->files[i]) {
    201                         vfs_data->files[i] = (vfs_file_t *) malloc(sizeof(vfs_file_t));
    202                         if (!vfs_data->files[i]) {
    203                                 fibril_mutex_unlock(&vfs_data->lock);
     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);
    204167                                return ENOMEM;
    205168                        }
    206169                       
    207                         memset(vfs_data->files[i], 0, sizeof(vfs_file_t));
    208                         fibril_mutex_initialize(&vfs_data->files[i]->lock);
    209                         vfs_file_addref(vfs_data, vfs_data->files[i]);
    210                         fibril_mutex_unlock(&vfs_data->lock);
     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);
    211174                        return (int) i;
    212175                }
     
    224187                }
    225188        }
    226         fibril_mutex_unlock(&vfs_data->lock);
     189        fibril_mutex_unlock(&VFS_DATA->lock);
    227190       
    228191        return EMFILE;
    229 }
    230 
    231 /** Allocate a file descriptor.
    232  *
    233  * @param desc If true, look for an available file descriptor
    234  *             in a descending order.
    235  *
    236  * @return First available file descriptor or a negative error
    237  *         code.
    238  */
    239 int vfs_fd_alloc(bool desc)
    240 {
    241         return _vfs_fd_alloc(VFS_DATA, desc);
    242 }
    243 
    244 static int _vfs_fd_free(vfs_client_data_t *vfs_data, int fd)
    245 {
    246         int rc;
    247 
    248         if (!vfs_files_init(vfs_data))
    249                 return ENOMEM;
    250 
    251         fibril_mutex_lock(&vfs_data->lock);     
    252         if ((fd < 0) || (fd >= MAX_OPEN_FILES) || !vfs_data->files[fd]) {
    253                 fibril_mutex_unlock(&vfs_data->lock);
    254                 return EBADF;
    255         }
    256        
    257         rc = vfs_file_delref(vfs_data, vfs_data->files[fd]);
    258         vfs_data->files[fd] = NULL;
    259         fibril_mutex_unlock(&vfs_data->lock);
    260        
    261         return rc;
    262192}
    263193
     
    271201int vfs_fd_free(int fd)
    272202{
    273         return _vfs_fd_free(VFS_DATA, fd);
     203        if (!vfs_files_init())
     204                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);
     209                return EBADF;
     210        }
     211       
     212        vfs_file_delref(FILES[fd]);
     213        FILES[fd] = NULL;
     214        fibril_mutex_unlock(&VFS_DATA->lock);
     215       
     216        return EOK;
    274217}
    275218
     
    285228int vfs_fd_assign(vfs_file_t *file, int fd)
    286229{
    287         if (!vfs_files_init(VFS_DATA))
     230        if (!vfs_files_init())
    288231                return ENOMEM;
    289232
     
    295238       
    296239        FILES[fd] = file;
    297         vfs_file_addref(VFS_DATA, FILES[fd]);
     240        vfs_file_addref(FILES[fd]);
    298241        fibril_mutex_unlock(&VFS_DATA->lock);
    299242       
     
    301244}
    302245
    303 static vfs_file_t *_vfs_file_get(vfs_client_data_t *vfs_data, int fd)
    304 {
    305         if (!vfs_files_init(vfs_data))
     246/** Find VFS file structure for a given file descriptor.
     247 *
     248 * @param fd            File descriptor.
     249 *
     250 * @return              VFS file structure corresponding to fd.
     251 */
     252vfs_file_t *vfs_file_get(int fd)
     253{
     254        if (!vfs_files_init())
    306255                return NULL;
    307256       
    308         fibril_mutex_lock(&vfs_data->lock);
     257        fibril_mutex_lock(&VFS_DATA->lock);
    309258        if ((fd >= 0) && (fd < MAX_OPEN_FILES)) {
    310                 vfs_file_t *file = vfs_data->files[fd];
     259                vfs_file_t *file = FILES[fd];
    311260                if (file != NULL) {
    312                         vfs_file_addref(vfs_data, file);
    313                         fibril_mutex_unlock(&vfs_data->lock);
     261                        vfs_file_addref(file);
     262                        fibril_mutex_unlock(&VFS_DATA->lock);
    314263                        return file;
    315264                }
    316265        }
    317         fibril_mutex_unlock(&vfs_data->lock);
     266        fibril_mutex_unlock(&VFS_DATA->lock);
    318267       
    319268        return NULL;
    320269}
    321270
    322 /** Find VFS file structure for a given file descriptor.
    323  *
    324  * @param fd            File descriptor.
    325  *
    326  * @return              VFS file structure corresponding to fd.
    327  */
    328 vfs_file_t *vfs_file_get(int fd)
    329 {
    330         return _vfs_file_get(VFS_DATA, fd);
    331 }
    332 
    333 static void _vfs_file_put(vfs_client_data_t *vfs_data, vfs_file_t *file)
    334 {
    335         fibril_mutex_lock(&vfs_data->lock);
    336         vfs_file_delref(vfs_data, file);
    337         fibril_mutex_unlock(&vfs_data->lock);
    338 }
    339 
    340271/** Stop using a file structure.
    341272 *
     
    344275void vfs_file_put(vfs_file_t *file)
    345276{
    346         _vfs_file_put(VFS_DATA, file);
    347 }
    348 
    349 void vfs_pass_handle(task_id_t donor_id, task_id_t acceptor_id, int donor_fd)
    350 {
    351         vfs_client_data_t *donor_data = NULL;
    352         vfs_client_data_t *acceptor_data = NULL;
    353         vfs_file_t *donor_file = NULL;
    354         vfs_file_t *acceptor_file = NULL;
    355         vfs_boxed_handle_t *bh;
    356         int acceptor_fd;
    357 
    358         acceptor_data = async_get_client_data_by_id(acceptor_id);
    359         if (!acceptor_data)
    360                 return;
    361 
    362         bh = malloc(sizeof(vfs_boxed_handle_t));
    363         assert(bh);
    364 
    365         link_initialize(&bh->link);
    366         bh->handle = -1;
    367 
    368         donor_data = async_get_client_data_by_id(donor_id);
    369         if (!donor_data)
    370                 goto out;
    371 
    372         donor_file = _vfs_file_get(donor_data, donor_fd);
    373         if (!donor_file)
    374                 goto out;
    375 
    376         acceptor_fd = _vfs_fd_alloc(acceptor_data, false);
    377         if (acceptor_fd < 0)
    378                 goto out;
    379 
    380         bh->handle = acceptor_fd;
    381 
    382         /*
    383          * Add a new reference to the underlying VFS node.
    384          */
    385         vfs_node_addref(donor_file->node);
    386         (void) vfs_open_node_remote(donor_file->node);
    387 
    388         acceptor_file = _vfs_file_get(acceptor_data, acceptor_fd);
    389         assert(acceptor_file);
    390 
    391         /*
    392          * Inherit attributes from the donor.
    393          */
    394         acceptor_file->node = donor_file->node;
    395         acceptor_file->append = donor_file->append;
    396         acceptor_file->pos = donor_file->pos;
    397 
    398 out:
    399         fibril_mutex_lock(&acceptor_data->lock);
    400         list_append(&bh->link, &acceptor_data->passed_handles);
    401         fibril_condvar_broadcast(&acceptor_data->cv);
    402         fibril_mutex_unlock(&acceptor_data->lock);
    403 
    404         if (donor_data)
    405                 async_put_client_data_by_id(donor_id);
    406         if (acceptor_data)
    407                 async_put_client_data_by_id(acceptor_id);
    408         if (donor_file)
    409                 _vfs_file_put(donor_data, donor_file);
    410         if (acceptor_file)
    411                 _vfs_file_put(acceptor_data, acceptor_file);
    412 
    413 }
    414 
    415 int vfs_wait_handle_internal(void)
    416 {
    417         vfs_client_data_t *vfs_data = VFS_DATA;
    418         int fd;
    419        
    420         fibril_mutex_lock(&vfs_data->lock);
    421         while (list_empty(&vfs_data->passed_handles))
    422                 fibril_condvar_wait(&vfs_data->cv, &vfs_data->lock);
    423         link_t *lnk = list_first(&vfs_data->passed_handles);
    424         list_remove(lnk);
    425         fibril_mutex_unlock(&vfs_data->lock);
    426 
    427         vfs_boxed_handle_t *bh = list_get_instance(lnk, vfs_boxed_handle_t, link);
    428         fd = bh->handle;
    429         free(bh);
    430 
    431         return fd;
     277        fibril_mutex_lock(&VFS_DATA->lock);
     278        vfs_file_delref(file);
     279        fibril_mutex_unlock(&VFS_DATA->lock);
    432280}
    433281
Note: See TracChangeset for help on using the changeset viewer.