Ignore:
File:
1 edited

Legend:

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

    re2ab36f1 r79ae36dd  
    4343#include <fibril.h>
    4444#include <fibril_synch.h>
    45 #include <adt/list.h>
    46 #include <task.h>
    4745#include "vfs.h"
    4846
     
    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_fd_free(i);
     82                }
     83        }
     84       
     85        free(FILES);
    10786}
    10887
     
    11493        if (vfs_data) {
    11594                fibril_mutex_initialize(&vfs_data->lock);
    116                 fibril_condvar_initialize(&vfs_data->cv);
    117                 list_initialize(&vfs_data->passed_handles);
    11895                vfs_data->files = NULL;
    11996        }
     
    126103        vfs_client_data_t *vfs_data = (vfs_client_data_t *) data;
    127104
    128         vfs_files_done(vfs_data);
     105        vfs_files_done();
    129106        free(vfs_data);
    130107}
     
    138115       
    139116        ipc_call_t answer;
    140         aid_t msg = async_send_2(exch, VFS_OUT_CLOSE, file->node->service_id,
     117        aid_t msg = async_send_2(exch, VFS_OUT_CLOSE, file->node->devmap_handle,
    141118            file->node->index, &answer);
    142119       
     
    154131 *                      incremented.
    155132 */
    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));
     133static void vfs_file_addref(vfs_file_t *file)
     134{
     135        assert(fibril_mutex_is_locked(&VFS_DATA->lock));
    159136
    160137        file->refcnt++;
     
    166143 *                      decremented.
    167144 */
    168 static int vfs_file_delref(vfs_client_data_t *vfs_data, vfs_file_t *file)
     145static int vfs_file_delref(vfs_file_t *file)
    169146{
    170147        int rc = EOK;
    171148
    172         assert(fibril_mutex_is_locked(&vfs_data->lock));
     149        assert(fibril_mutex_is_locked(&VFS_DATA->lock));
    173150
    174151        if (file->refcnt-- == 1) {
     
    185162}
    186163
    187 static int _vfs_fd_alloc(vfs_client_data_t *vfs_data, bool desc)
    188 {
    189         if (!vfs_files_init(vfs_data))
     164
     165/** Allocate a file descriptor.
     166 *
     167 * @param desc If true, look for an available file descriptor
     168 *             in a descending order.
     169 *
     170 * @return First available file descriptor or a negative error
     171 *         code.
     172 */
     173int vfs_fd_alloc(bool desc)
     174{
     175        if (!vfs_files_init())
    190176                return ENOMEM;
    191177       
     
    196182                i = 0;
    197183       
    198         fibril_mutex_lock(&vfs_data->lock);
     184        fibril_mutex_lock(&VFS_DATA->lock);
    199185        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);
     186                if (!FILES[i]) {
     187                        FILES[i] = (vfs_file_t *) malloc(sizeof(vfs_file_t));
     188                        if (!FILES[i]) {
     189                                fibril_mutex_unlock(&VFS_DATA->lock);
    204190                                return ENOMEM;
    205191                        }
    206192                       
    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);
     193                        memset(FILES[i], 0, sizeof(vfs_file_t));
     194                        fibril_mutex_initialize(&FILES[i]->lock);
     195                        vfs_file_addref(FILES[i]);
     196                        fibril_mutex_unlock(&VFS_DATA->lock);
    211197                        return (int) i;
    212198                }
     
    224210                }
    225211        }
    226         fibril_mutex_unlock(&vfs_data->lock);
     212        fibril_mutex_unlock(&VFS_DATA->lock);
    227213       
    228214        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;
    262215}
    263216
     
    271224int vfs_fd_free(int fd)
    272225{
    273         return _vfs_fd_free(VFS_DATA, fd);
     226        int rc;
     227
     228        if (!vfs_files_init())
     229                return ENOMEM;
     230
     231        fibril_mutex_lock(&VFS_DATA->lock);     
     232        if ((fd < 0) || (fd >= MAX_OPEN_FILES) || (FILES[fd] == NULL)) {
     233                fibril_mutex_unlock(&VFS_DATA->lock);
     234                return EBADF;
     235        }
     236       
     237        rc = vfs_file_delref(FILES[fd]);
     238        FILES[fd] = NULL;
     239        fibril_mutex_unlock(&VFS_DATA->lock);
     240       
     241        return rc;
    274242}
    275243
     
    285253int vfs_fd_assign(vfs_file_t *file, int fd)
    286254{
    287         if (!vfs_files_init(VFS_DATA))
     255        if (!vfs_files_init())
    288256                return ENOMEM;
    289257
     
    295263       
    296264        FILES[fd] = file;
    297         vfs_file_addref(VFS_DATA, FILES[fd]);
     265        vfs_file_addref(FILES[fd]);
    298266        fibril_mutex_unlock(&VFS_DATA->lock);
    299267       
     
    301269}
    302270
    303 static vfs_file_t *_vfs_file_get(vfs_client_data_t *vfs_data, int fd)
    304 {
    305         if (!vfs_files_init(vfs_data))
     271/** Find VFS file structure for a given file descriptor.
     272 *
     273 * @param fd            File descriptor.
     274 *
     275 * @return              VFS file structure corresponding to fd.
     276 */
     277vfs_file_t *vfs_file_get(int fd)
     278{
     279        if (!vfs_files_init())
    306280                return NULL;
    307281       
    308         fibril_mutex_lock(&vfs_data->lock);
     282        fibril_mutex_lock(&VFS_DATA->lock);
    309283        if ((fd >= 0) && (fd < MAX_OPEN_FILES)) {
    310                 vfs_file_t *file = vfs_data->files[fd];
     284                vfs_file_t *file = FILES[fd];
    311285                if (file != NULL) {
    312                         vfs_file_addref(vfs_data, file);
    313                         fibril_mutex_unlock(&vfs_data->lock);
     286                        vfs_file_addref(file);
     287                        fibril_mutex_unlock(&VFS_DATA->lock);
    314288                        return file;
    315289                }
    316290        }
    317         fibril_mutex_unlock(&vfs_data->lock);
     291        fibril_mutex_unlock(&VFS_DATA->lock);
    318292       
    319293        return NULL;
    320294}
    321295
    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 
    340296/** Stop using a file structure.
    341297 *
     
    344300void vfs_file_put(vfs_file_t *file)
    345301{
    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;
     302        fibril_mutex_lock(&VFS_DATA->lock);
     303        vfs_file_delref(file);
     304        fibril_mutex_unlock(&VFS_DATA->lock);
    432305}
    433306
Note: See TracChangeset for help on using the changeset viewer.