Changeset 07b39338 in mainline for uspace/srv/vfs/vfs_file.c


Ignore:
Timestamp:
2011-08-20T18:21:49Z (13 years ago)
Author:
Jiří Zárevúcky <zarevucky.jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
6ab014d
Parents:
0cf27ee (diff), f00af83 (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 libposix.

File:
1 edited

Legend:

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

    r0cf27ee r07b39338  
    4343#include <fibril.h>
    4444#include <fibril_synch.h>
     45#include <adt/list.h>
     46#include <task.h>
    4547#include "vfs.h"
    4648
     
    5052typedef struct {
    5153        fibril_mutex_t lock;
     54        fibril_condvar_t cv;
     55        list_t passed_handles;
    5256        vfs_file_t **files;
    5357} vfs_client_data_t;
    5458
     59typedef struct {
     60        link_t link;
     61        int handle;
     62} vfs_boxed_handle_t;
     63
     64static int _vfs_fd_free(vfs_client_data_t *, int);
     65
    5566/** 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);
     67static 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);
    6374                        return false;
    6475                }
    65                 memset(FILES, 0, MAX_OPEN_FILES * sizeof(vfs_file_t *));
    66         }
    67         fibril_mutex_unlock(&VFS_DATA->lock);
     76                memset(vfs_data->files, 0, MAX_OPEN_FILES * sizeof(vfs_file_t *));
     77        }
     78        fibril_mutex_unlock(&vfs_data->lock);
    6879        return true;
    6980}
    7081
    7182/** Cleanup the table of open files. */
    72 static void vfs_files_done(void)
     83static void vfs_files_done(vfs_client_data_t *vfs_data)
    7384{
    7485        int i;
    7586
    76         if (!FILES)
     87        if (!vfs_data->files)
    7788                return;
    7889
    7990        for (i = 0; i < MAX_OPEN_FILES; i++) {
    80                 if (FILES[i]) {
    81                         (void) vfs_fd_free(i);
    82                 }
    83         }
    84        
    85         free(FILES);
     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        }
    86107}
    87108
     
    93114        if (vfs_data) {
    94115                fibril_mutex_initialize(&vfs_data->lock);
     116                fibril_condvar_initialize(&vfs_data->cv);
     117                list_initialize(&vfs_data->passed_handles);
    95118                vfs_data->files = NULL;
    96119        }
     
    103126        vfs_client_data_t *vfs_data = (vfs_client_data_t *) data;
    104127
    105         vfs_files_done();
     128        vfs_files_done(vfs_data);
    106129        free(vfs_data);
    107130}
     
    131154 *                      incremented.
    132155 */
    133 static void vfs_file_addref(vfs_file_t *file)
    134 {
    135         assert(fibril_mutex_is_locked(&VFS_DATA->lock));
     156static void vfs_file_addref(vfs_client_data_t *vfs_data, vfs_file_t *file)
     157{
     158        assert(fibril_mutex_is_locked(&vfs_data->lock));
    136159
    137160        file->refcnt++;
     
    143166 *                      decremented.
    144167 */
    145 static int vfs_file_delref(vfs_file_t *file)
     168static int vfs_file_delref(vfs_client_data_t *vfs_data, vfs_file_t *file)
    146169{
    147170        int rc = EOK;
    148171
    149         assert(fibril_mutex_is_locked(&VFS_DATA->lock));
     172        assert(fibril_mutex_is_locked(&vfs_data->lock));
    150173
    151174        if (file->refcnt-- == 1) {
     
    162185}
    163186
    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  */
    173 int vfs_fd_alloc(bool desc)
    174 {
    175         if (!vfs_files_init())
     187static int _vfs_fd_alloc(vfs_client_data_t *vfs_data, bool desc)
     188{
     189        if (!vfs_files_init(vfs_data))
    176190                return ENOMEM;
    177191       
     
    182196                i = 0;
    183197       
    184         fibril_mutex_lock(&VFS_DATA->lock);
     198        fibril_mutex_lock(&vfs_data->lock);
    185199        while (true) {
    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);
     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);
    190204                                return ENOMEM;
    191205                        }
    192206                       
    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);
     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);
    197211                        return (int) i;
    198212                }
     
    210224                }
    211225        }
    212         fibril_mutex_unlock(&VFS_DATA->lock);
     226        fibril_mutex_unlock(&vfs_data->lock);
    213227       
    214228        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 */
     239int vfs_fd_alloc(bool desc)
     240{
     241        return _vfs_fd_alloc(VFS_DATA, desc);
     242}
     243
     244static 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;
    215262}
    216263
     
    224271int vfs_fd_free(int fd)
    225272{
    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;
     273        return _vfs_fd_free(VFS_DATA, fd);
    242274}
    243275
     
    253285int vfs_fd_assign(vfs_file_t *file, int fd)
    254286{
    255         if (!vfs_files_init())
     287        if (!vfs_files_init(VFS_DATA))
    256288                return ENOMEM;
    257289
     
    263295       
    264296        FILES[fd] = file;
    265         vfs_file_addref(FILES[fd]);
     297        vfs_file_addref(VFS_DATA, FILES[fd]);
    266298        fibril_mutex_unlock(&VFS_DATA->lock);
    267299       
     
    269301}
    270302
    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  */
    277 vfs_file_t *vfs_file_get(int fd)
    278 {
    279         if (!vfs_files_init())
     303static vfs_file_t *_vfs_file_get(vfs_client_data_t *vfs_data, int fd)
     304{
     305        if (!vfs_files_init(vfs_data))
    280306                return NULL;
    281307       
    282         fibril_mutex_lock(&VFS_DATA->lock);
     308        fibril_mutex_lock(&vfs_data->lock);
    283309        if ((fd >= 0) && (fd < MAX_OPEN_FILES)) {
    284                 vfs_file_t *file = FILES[fd];
     310                vfs_file_t *file = vfs_data->files[fd];
    285311                if (file != NULL) {
    286                         vfs_file_addref(file);
    287                         fibril_mutex_unlock(&VFS_DATA->lock);
     312                        vfs_file_addref(vfs_data, file);
     313                        fibril_mutex_unlock(&vfs_data->lock);
    288314                        return file;
    289315                }
    290316        }
    291         fibril_mutex_unlock(&VFS_DATA->lock);
     317        fibril_mutex_unlock(&vfs_data->lock);
    292318       
    293319        return NULL;
    294320}
    295321
     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 */
     328vfs_file_t *vfs_file_get(int fd)
     329{
     330        return _vfs_file_get(VFS_DATA, fd);
     331}
     332
     333static 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
    296340/** Stop using a file structure.
    297341 *
     
    300344void vfs_file_put(vfs_file_t *file)
    301345{
    302         fibril_mutex_lock(&VFS_DATA->lock);
    303         vfs_file_delref(file);
    304         fibril_mutex_unlock(&VFS_DATA->lock);
     346        _vfs_file_put(VFS_DATA, file);
     347}
     348
     349void 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
     398out:
     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
     415int 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;
    305432}
    306433
Note: See TracChangeset for help on using the changeset viewer.