Changeset 2b88074b in mainline for uspace/srv


Ignore:
Timestamp:
2009-10-29T22:06:46Z (16 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
2e983c7
Parents:
14ecd6c
Message:

vfs: file descriptors housekeeping changes

  • add support for allocating new file descriptors from the end of the fd range (O_DESC)
  • add support for assigning of an already opened file to a free file descriptor

vfs: VFS_OUT_CLOSE is called only when the file reference count is about to drop to zero
vfs: implement VFS_IN_DUP

libc: optimize current working directory housekeeping

  • using opendir() was an overkill
  • allocate current working directory file descriptor from the end of the fd range using O_DESC (so it doesn't mess with the well-known descriptors 0, 1 and 2)

libc: implement dup2() (via VFS_IN_DUP)

getvc: change stdin/stdout/stderr by a slightly more elegant way (using dup2())

Location:
uspace/srv/vfs
Files:
4 edited

Legend:

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

    r14ecd6c r2b88074b  
    126126                        vfs_sync(callid, &call);
    127127                        break;
     128                case VFS_IN_DUP:
     129                        vfs_dup(callid, &call);
    128130                default:
    129131                        ipc_answer_0(callid, ENOTSUP);
  • uspace/srv/vfs/vfs.h

    r14ecd6c r2b88074b  
    186186extern bool vfs_files_init(void);
    187187extern vfs_file_t *vfs_file_get(int);
    188 extern int vfs_fd_alloc(void);
     188extern int vfs_fd_assign(vfs_file_t *file, int fd);
     189extern int vfs_fd_alloc(bool desc);
    189190extern int vfs_fd_free(int);
    190191
     
    200201extern void vfs_open_node(ipc_callid_t, ipc_call_t *);
    201202extern void vfs_sync(ipc_callid_t, ipc_call_t *);
     203extern void vfs_dup(ipc_callid_t, ipc_call_t *);
    202204extern void vfs_close(ipc_callid_t, ipc_call_t *);
    203205extern void vfs_read(ipc_callid_t, ipc_call_t *);
  • uspace/srv/vfs/vfs_file.c

    r14ecd6c r2b88074b  
    7676/** Allocate a file descriptor.
    7777 *
    78  * @return              First available file descriptor or a negative error
    79  *                      code.
    80  */
    81 int vfs_fd_alloc(void)
     78 * @param desc If true, look for an available file descriptor
     79 *             in a descending order.
     80 *
     81 * @return First available file descriptor or a negative error
     82 *         code.
     83 */
     84int vfs_fd_alloc(bool desc)
    8285{
    8386        if (!vfs_files_init())
     
    8588       
    8689        unsigned int i;
    87         for (i = 0; i < MAX_OPEN_FILES; i++) {
     90        if (desc)
     91                i = MAX_OPEN_FILES;
     92        else
     93                i = 0;
     94       
     95        while (true) {
    8896                if (!files[i]) {
    8997                        files[i] = (vfs_file_t *) malloc(sizeof(vfs_file_t));
     
    96104                        return (int) i;
    97105                }
     106               
     107                if (desc) {
     108                        if (i == 0)
     109                                break;
     110                       
     111                        i--;
     112                } else {
     113                        if (i == MAX_OPEN_FILES)
     114                                break;
     115                       
     116                        i++;
     117                }
    98118        }
    99119       
     
    118138        vfs_file_delref(files[fd]);
    119139        files[fd] = NULL;
     140       
     141        return EOK;
     142}
     143
     144/** Assign a file to a file descriptor.
     145 *
     146 * @param file File to assign.
     147 * @param fd   File descriptor to assign to.
     148 *
     149 * @return EOK on success or EINVAL if fd is an invalid or already
     150 *         used file descriptor.
     151 *
     152 */
     153int vfs_fd_assign(vfs_file_t *file, int fd)
     154{
     155        if (!vfs_files_init())
     156                return ENOMEM;
     157       
     158        if ((fd < 0) || (fd >= MAX_OPEN_FILES) || (files[fd] != NULL))
     159                return EINVAL;
     160       
     161        files[fd] = file;
     162        vfs_file_addref(files[fd]);
    120163       
    121164        return EOK;
  • uspace/srv/vfs/vfs_ops.c

    r14ecd6c r2b88074b  
    543543         * structure.
    544544         */
    545         int fd = vfs_fd_alloc();
     545        int fd = vfs_fd_alloc((oflag & O_DESC) != 0);
    546546        if (fd < 0) {
    547547                vfs_node_put(node);
     
    620620         * structure.
    621621         */
    622         int fd = vfs_fd_alloc();
     622        int fd = vfs_fd_alloc((oflag & O_DESC) != 0);
    623623        if (fd < 0) {
    624624                vfs_node_put(node);
     
    679679}
    680680
     681static int vfs_close_internal(vfs_file_t *file)
     682{
     683        /*
     684         * Lock the open file structure so that no other thread can manipulate
     685         * the same open file at a time.
     686         */
     687        fibril_mutex_lock(&file->lock);
     688       
     689        if (file->refcnt <= 1) {
     690                /* Only close the file on the destination FS server
     691                   if there are no more file descriptors (except the
     692                   present one) pointing to this file. */
     693               
     694                int fs_phone = vfs_grab_phone(file->node->fs_handle);
     695               
     696                /* Make a VFS_OUT_CLOSE request at the destination FS server. */
     697                aid_t msg;
     698                ipc_call_t answer;
     699                msg = async_send_2(fs_phone, VFS_OUT_CLOSE, file->node->dev_handle,
     700                    file->node->index, &answer);
     701               
     702                /* Wait for reply from the FS server. */
     703                ipcarg_t rc;
     704                async_wait_for(msg, &rc);
     705               
     706                vfs_release_phone(fs_phone);
     707                fibril_mutex_unlock(&file->lock);
     708               
     709                return IPC_GET_ARG1(answer);
     710        }
     711       
     712        fibril_mutex_unlock(&file->lock);
     713        return EOK;
     714}
     715
    681716void vfs_close(ipc_callid_t rid, ipc_call_t *request)
    682717{
     
    690725        }
    691726       
    692         /*
    693          * Lock the open file structure so that no other thread can manipulate
    694          * the same open file at a time.
    695          */
    696         fibril_mutex_lock(&file->lock);
    697         int fs_phone = vfs_grab_phone(file->node->fs_handle);
    698        
    699         /* Make a VFS_OUT_CLOSE request at the destination FS server. */
    700         aid_t msg;
    701         ipc_call_t answer;
    702         msg = async_send_2(fs_phone, VFS_OUT_CLOSE, file->node->dev_handle,
    703             file->node->index, &answer);
    704 
    705         /* Wait for reply from the FS server. */
    706         ipcarg_t rc;
    707         async_wait_for(msg, &rc);
    708 
    709         vfs_release_phone(fs_phone);
    710         fibril_mutex_unlock(&file->lock);
    711        
    712         int retval = IPC_GET_ARG1(answer);
    713         if (retval != EOK)
    714                 ipc_answer_0(rid, retval);
    715        
    716         retval = vfs_fd_free(fd);
    717         ipc_answer_0(rid, retval);
     727        int ret = vfs_close_internal(file);
     728        if (ret != EOK)
     729                ipc_answer_0(rid, ret);
     730       
     731        ret = vfs_fd_free(fd);
     732        ipc_answer_0(rid, ret);
    718733}
    719734
     
    13101325}
    13111326
     1327void vfs_dup(ipc_callid_t rid, ipc_call_t *request)
     1328{
     1329        int oldfd = IPC_GET_ARG1(*request);
     1330        int newfd = IPC_GET_ARG2(*request);
     1331       
     1332        /* Lookup the file structure corresponding to oldfd. */
     1333        vfs_file_t *oldfile = vfs_file_get(oldfd);
     1334        if (!oldfile) {
     1335                ipc_answer_0(rid, EBADF);
     1336                return;
     1337        }
     1338       
     1339        /* If the file descriptors are the same, do nothing. */
     1340        if (oldfd == newfd) {
     1341                ipc_answer_1(rid, EOK, newfd);
     1342                return;
     1343        }
     1344       
     1345        /*
     1346         * Lock the open file structure so that no other thread can manipulate
     1347         * the same open file at a time.
     1348         */
     1349        fibril_mutex_lock(&oldfile->lock);
     1350       
     1351        /* Lookup an open file structure possibly corresponding to newfd. */
     1352        vfs_file_t *newfile = vfs_file_get(newfd);
     1353        if (newfile) {
     1354                /* Close the originally opened file. */
     1355                int ret = vfs_close_internal(newfile);
     1356                if (ret != EOK) {
     1357                        ipc_answer_0(rid, ret);
     1358                        return;
     1359                }
     1360               
     1361                ret = vfs_fd_free(newfd);
     1362                if (ret != EOK) {
     1363                        ipc_answer_0(rid, ret);
     1364                        return;
     1365                }
     1366        }
     1367       
     1368        /* Assign the old file to newfd. */
     1369        int ret = vfs_fd_assign(oldfile, newfd);
     1370        fibril_mutex_unlock(&oldfile->lock);
     1371       
     1372        if (ret != EOK)
     1373                ipc_answer_0(rid, ret);
     1374        else
     1375                ipc_answer_1(rid, EOK, newfd);
     1376}
     1377
    13121378/**
    13131379 * @}
Note: See TracChangeset for help on using the changeset viewer.