Changeset 42a619b in mainline for uspace/srv/vfs/vfs_file.c


Ignore:
Timestamp:
2011-08-19T08:58:50Z (14 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
7dcb7981, 903bac0a, c2cf033
Parents:
ef7052ec (diff), d894fbd (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 from lp:~jakub/helenos/camp2011.

File:
1 edited

Legend:

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

    ref7052ec r42a619b  
    4343#include <fibril.h>
    4444#include <fibril_synch.h>
     45#include <adt/list.h>
    4546#include "vfs.h"
    4647
     
    5051typedef struct {
    5152        fibril_mutex_t lock;
     53        fibril_condvar_t cv;
     54        list_t passed_handles;
    5255        vfs_file_t **files;
    5356} vfs_client_data_t;
    5457
     58typedef struct {
     59        link_t link;
     60        int handle;
     61} vfs_boxed_handle_t;
     62
     63static int _vfs_fd_free(vfs_client_data_t *, int);
     64
    5565/** 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);
     66static bool vfs_files_init(vfs_client_data_t *vfs_data)
     67{
     68        fibril_mutex_lock(&vfs_data->lock);
     69        if (!vfs_data->files) {
     70                vfs_data->files = malloc(MAX_OPEN_FILES * sizeof(vfs_file_t *));
     71                if (!vfs_data->files) {
     72                        fibril_mutex_unlock(&vfs_data->lock);
    6373                        return false;
    6474                }
    65                 memset(FILES, 0, MAX_OPEN_FILES * sizeof(vfs_file_t *));
    66         }
    67         fibril_mutex_unlock(&VFS_DATA->lock);
     75                memset(vfs_data->files, 0, MAX_OPEN_FILES * sizeof(vfs_file_t *));
     76        }
     77        fibril_mutex_unlock(&vfs_data->lock);
    6878        return true;
    6979}
    7080
    7181/** Cleanup the table of open files. */
    72 static void vfs_files_done(void)
     82static void vfs_files_done(vfs_client_data_t *vfs_data)
    7383{
    7484        int i;
    7585
    76         if (!FILES)
     86        if (!vfs_data->files)
    7787                return;
    7888
    7989        for (i = 0; i < MAX_OPEN_FILES; i++) {
    80                 if (FILES[i]) {
    81                         (void) vfs_fd_free(i);
    82                 }
    83         }
    84        
    85         free(FILES);
     90                if (vfs_data->files[i])
     91                        (void) _vfs_fd_free(vfs_data, i);
     92        }
     93       
     94        free(vfs_data->files);
     95
     96        while (!list_empty(&vfs_data->passed_handles)) {
     97                link_t *lnk;
     98                vfs_boxed_handle_t *bh;
     99               
     100                lnk = list_first(&vfs_data->passed_handles);
     101                list_remove(lnk);
     102
     103                bh = list_get_instance(lnk, vfs_boxed_handle_t, link);
     104                free(bh);
     105        }
    86106}
    87107
     
    93113        if (vfs_data) {
    94114                fibril_mutex_initialize(&vfs_data->lock);
     115                fibril_condvar_initialize(&vfs_data->cv);
     116                list_initialize(&vfs_data->passed_handles);
    95117                vfs_data->files = NULL;
    96118        }
     
    103125        vfs_client_data_t *vfs_data = (vfs_client_data_t *) data;
    104126
    105         vfs_files_done();
     127        vfs_files_done(vfs_data);
    106128        free(vfs_data);
    107129}
     
    131153 *                      incremented.
    132154 */
    133 static void vfs_file_addref(vfs_file_t *file)
    134 {
    135         assert(fibril_mutex_is_locked(&VFS_DATA->lock));
     155static void vfs_file_addref(vfs_client_data_t *vfs_data, vfs_file_t *file)
     156{
     157        assert(fibril_mutex_is_locked(&vfs_data->lock));
    136158
    137159        file->refcnt++;
     
    143165 *                      decremented.
    144166 */
    145 static int vfs_file_delref(vfs_file_t *file)
     167static int vfs_file_delref(vfs_client_data_t *vfs_data, vfs_file_t *file)
    146168{
    147169        int rc = EOK;
    148170
    149         assert(fibril_mutex_is_locked(&VFS_DATA->lock));
     171        assert(fibril_mutex_is_locked(&vfs_data->lock));
    150172
    151173        if (file->refcnt-- == 1) {
     
    162184}
    163185
    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())
     186static int _vfs_fd_alloc(vfs_client_data_t *vfs_data, bool desc)
     187{
     188        if (!vfs_files_init(vfs_data))
    176189                return ENOMEM;
    177190       
     
    182195                i = 0;
    183196       
    184         fibril_mutex_lock(&VFS_DATA->lock);
     197        fibril_mutex_lock(&vfs_data->lock);
    185198        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);
     199                if (!vfs_data->files[i]) {
     200                        vfs_data->files[i] = (vfs_file_t *) malloc(sizeof(vfs_file_t));
     201                        if (!vfs_data->files[i]) {
     202                                fibril_mutex_unlock(&vfs_data->lock);
    190203                                return ENOMEM;
    191204                        }
    192205                       
    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);
     206                        memset(vfs_data->files[i], 0, sizeof(vfs_file_t));
     207                        fibril_mutex_initialize(&vfs_data->files[i]->lock);
     208                        vfs_file_addref(vfs_data, vfs_data->files[i]);
     209                        fibril_mutex_unlock(&vfs_data->lock);
    197210                        return (int) i;
    198211                }
     
    210223                }
    211224        }
    212         fibril_mutex_unlock(&VFS_DATA->lock);
     225        fibril_mutex_unlock(&vfs_data->lock);
    213226       
    214227        return EMFILE;
     228}
     229
     230/** Allocate a file descriptor.
     231 *
     232 * @param desc If true, look for an available file descriptor
     233 *             in a descending order.
     234 *
     235 * @return First available file descriptor or a negative error
     236 *         code.
     237 */
     238int vfs_fd_alloc(bool desc)
     239{
     240        return _vfs_fd_alloc(VFS_DATA, desc);
     241}
     242
     243static int _vfs_fd_free(vfs_client_data_t *vfs_data, int fd)
     244{
     245        int rc;
     246
     247        if (!vfs_files_init(vfs_data))
     248                return ENOMEM;
     249
     250        fibril_mutex_lock(&vfs_data->lock);     
     251        if ((fd < 0) || (fd >= MAX_OPEN_FILES) || !vfs_data->files[fd]) {
     252                fibril_mutex_unlock(&vfs_data->lock);
     253                return EBADF;
     254        }
     255       
     256        rc = vfs_file_delref(vfs_data, vfs_data->files[fd]);
     257        vfs_data->files[fd] = NULL;
     258        fibril_mutex_unlock(&vfs_data->lock);
     259       
     260        return rc;
    215261}
    216262
     
    224270int vfs_fd_free(int fd)
    225271{
    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;
     272        return _vfs_fd_free(VFS_DATA, fd);
    242273}
    243274
     
    253284int vfs_fd_assign(vfs_file_t *file, int fd)
    254285{
    255         if (!vfs_files_init())
     286        if (!vfs_files_init(VFS_DATA))
    256287                return ENOMEM;
    257288
     
    263294       
    264295        FILES[fd] = file;
    265         vfs_file_addref(FILES[fd]);
     296        vfs_file_addref(VFS_DATA, FILES[fd]);
    266297        fibril_mutex_unlock(&VFS_DATA->lock);
    267298       
     
    269300}
    270301
    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())
     302static vfs_file_t *_vfs_file_get(vfs_client_data_t *vfs_data, int fd)
     303{
     304        if (!vfs_files_init(vfs_data))
    280305                return NULL;
    281306       
    282         fibril_mutex_lock(&VFS_DATA->lock);
     307        fibril_mutex_lock(&vfs_data->lock);
    283308        if ((fd >= 0) && (fd < MAX_OPEN_FILES)) {
    284                 vfs_file_t *file = FILES[fd];
     309                vfs_file_t *file = vfs_data->files[fd];
    285310                if (file != NULL) {
    286                         vfs_file_addref(file);
    287                         fibril_mutex_unlock(&VFS_DATA->lock);
     311                        vfs_file_addref(vfs_data, file);
     312                        fibril_mutex_unlock(&vfs_data->lock);
    288313                        return file;
    289314                }
    290315        }
    291         fibril_mutex_unlock(&VFS_DATA->lock);
     316        fibril_mutex_unlock(&vfs_data->lock);
    292317       
    293318        return NULL;
    294319}
    295320
     321/** Find VFS file structure for a given file descriptor.
     322 *
     323 * @param fd            File descriptor.
     324 *
     325 * @return              VFS file structure corresponding to fd.
     326 */
     327vfs_file_t *vfs_file_get(int fd)
     328{
     329        return _vfs_file_get(VFS_DATA, fd);
     330}
     331
     332static void _vfs_file_put(vfs_client_data_t *vfs_data, vfs_file_t *file)
     333{
     334        fibril_mutex_lock(&vfs_data->lock);
     335        vfs_file_delref(vfs_data, file);
     336        fibril_mutex_unlock(&vfs_data->lock);
     337}
     338
    296339/** Stop using a file structure.
    297340 *
     
    300343void vfs_file_put(vfs_file_t *file)
    301344{
    302         fibril_mutex_lock(&VFS_DATA->lock);
    303         vfs_file_delref(file);
    304         fibril_mutex_unlock(&VFS_DATA->lock);
     345        _vfs_file_put(VFS_DATA, file);
     346}
     347
     348void vfs_pass_handle(sysarg_t donor_hash, sysarg_t acceptor_hash, int donor_fd)
     349{
     350        vfs_client_data_t *donor_data = NULL;
     351        vfs_client_data_t *acceptor_data = NULL;
     352        vfs_file_t *donor_file = NULL;
     353        vfs_file_t *acceptor_file = NULL;
     354        vfs_boxed_handle_t *bh;
     355        int acceptor_fd;
     356
     357        acceptor_data = async_get_client_data_by_hash(acceptor_hash);
     358        if (!acceptor_data)
     359                return;
     360
     361        bh = malloc(sizeof(vfs_boxed_handle_t));
     362        assert(bh);
     363
     364        link_initialize(&bh->link);
     365        bh->handle = -1;
     366
     367        donor_data = async_get_client_data_by_hash(donor_hash);
     368        if (!donor_data)
     369                goto out;
     370
     371        donor_file = _vfs_file_get(donor_data, donor_fd);
     372        if (!donor_file)
     373                goto out;
     374
     375        acceptor_fd = _vfs_fd_alloc(acceptor_data, false);
     376        if (acceptor_fd < 0)
     377                goto out;
     378
     379        bh->handle = acceptor_fd;
     380
     381        /*
     382         * Add a new reference to the underlying VFS node.
     383         */
     384        vfs_node_addref(donor_file->node);
     385        (void) vfs_open_node_remote(donor_file->node);
     386
     387        acceptor_file = _vfs_file_get(acceptor_data, acceptor_fd);
     388        assert(acceptor_file);
     389
     390        /*
     391         * Inherit attributes from the donor.
     392         */
     393        acceptor_file->node = donor_file->node;
     394        acceptor_file->append = donor_file->append;
     395        acceptor_file->pos = donor_file->pos;
     396
     397out:
     398        fibril_mutex_lock(&acceptor_data->lock);
     399        list_append(&bh->link, &acceptor_data->passed_handles);
     400        fibril_condvar_broadcast(&acceptor_data->cv);
     401        fibril_mutex_unlock(&acceptor_data->lock);
     402
     403        if (donor_data)
     404                async_put_client_data_by_hash(donor_hash);
     405        if (acceptor_data)
     406                async_put_client_data_by_hash(acceptor_hash);
     407        if (donor_file)
     408                _vfs_file_put(donor_data, donor_file);
     409        if (acceptor_file)
     410                _vfs_file_put(acceptor_data, acceptor_file);
     411
     412}
     413
     414int vfs_wait_handle_internal(void)
     415{
     416        vfs_client_data_t *vfs_data = VFS_DATA;
     417        int fd;
     418       
     419        fibril_mutex_lock(&vfs_data->lock);
     420        while (list_empty(&vfs_data->passed_handles))
     421                fibril_condvar_wait(&vfs_data->cv, &vfs_data->lock);
     422        link_t *lnk = list_first(&vfs_data->passed_handles);
     423        list_remove(lnk);
     424        fibril_mutex_unlock(&vfs_data->lock);
     425
     426        vfs_boxed_handle_t *bh = list_get_instance(lnk, vfs_boxed_handle_t, link);
     427        fd = bh->handle;
     428        free(bh);
     429
     430        return fd;
    305431}
    306432
Note: See TracChangeset for help on using the changeset viewer.