Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/fs/fat/fat_ops.c

    rdfddfcd r472c09d  
    5252#include <adt/list.h>
    5353#include <assert.h>
    54 #include <fibril_sync.h>
     54#include <fibril_synch.h>
    5555#include <sys/mman.h>
    5656#include <align.h>
     
    7171static int fat_match(fs_node_t **, fs_node_t *, const char *);
    7272static int fat_node_get(fs_node_t **, dev_handle_t, fs_index_t);
     73static int fat_node_open(fs_node_t *);
    7374static int fat_node_put(fs_node_t *);
    7475static int fat_create_node(fs_node_t **, dev_handle_t, int);
     
    8384static bool fat_is_directory(fs_node_t *);
    8485static bool fat_is_file(fs_node_t *node);
     86static dev_handle_t fat_device_get(fs_node_t *node);
    8587
    8688/*
     
    135137        rc = block_put(b);
    136138        return rc;
     139}
     140
     141static int fat_node_fini_by_dev_handle(dev_handle_t dev_handle)
     142{
     143        link_t *lnk;
     144        fat_node_t *nodep;
     145        int rc;
     146
     147        /*
     148         * We are called from fat_unmounted() and assume that there are already
     149         * no nodes belonging to this instance with non-zero refcount. Therefore
     150         * it is sufficient to clean up only the FAT free node list.
     151         */
     152
     153restart:
     154        fibril_mutex_lock(&ffn_mutex);
     155        for (lnk = ffn_head.next; lnk != &ffn_head; lnk = lnk->next) {
     156                nodep = list_get_instance(lnk, fat_node_t, ffn_link);
     157                if (!fibril_mutex_trylock(&nodep->lock)) {
     158                        fibril_mutex_unlock(&ffn_mutex);
     159                        goto restart;
     160                }
     161                if (!fibril_mutex_trylock(&nodep->idx->lock)) {
     162                        fibril_mutex_unlock(&nodep->lock);
     163                        fibril_mutex_unlock(&ffn_mutex);
     164                        goto restart;
     165                }
     166                if (nodep->idx->dev_handle != dev_handle) {
     167                        fibril_mutex_unlock(&nodep->idx->lock);
     168                        fibril_mutex_unlock(&nodep->lock);
     169                        continue;
     170                }
     171
     172                list_remove(&nodep->ffn_link);
     173                fibril_mutex_unlock(&ffn_mutex);
     174
     175                /*
     176                 * We can unlock the node and its index structure because we are
     177                 * the last player on this playground and VFS is preventing new
     178                 * players from entering.
     179                 */
     180                fibril_mutex_unlock(&nodep->idx->lock);
     181                fibril_mutex_unlock(&nodep->lock);
     182
     183                if (nodep->dirty) {
     184                        rc = fat_node_sync(nodep);
     185                        if (rc != EOK)
     186                                return rc;
     187                }
     188                nodep->idx->nodep = NULL;
     189                free(nodep->bp);
     190                free(nodep);
     191
     192                /* Need to restart because we changed the ffn_head list. */
     193                goto restart;
     194        }
     195        fibril_mutex_unlock(&ffn_mutex);
     196
     197        return EOK;
    137198}
    138199
     
    407468}
    408469
     470int fat_node_open(fs_node_t *fn)
     471{
     472        /*
     473         * Opening a file is stateless, nothing
     474         * to be done here.
     475         */
     476        return EOK;
     477}
     478
    409479int fat_node_put(fs_node_t *fn)
    410480{
     
    867937}
    868938
     939dev_handle_t fat_device_get(fs_node_t *node)
     940{
     941        return 0;
     942}
     943
    869944/** libfs operations */
    870945libfs_ops_t fat_libfs_ops = {
     
    872947        .match = fat_match,
    873948        .node_get = fat_node_get,
     949        .node_open = fat_node_open,
    874950        .node_put = fat_node_put,
    875951        .create = fat_create_node,
     
    881957        .size_get = fat_size_get,
    882958        .lnkcnt_get = fat_lnkcnt_get,
    883         .plb_get_char = fat_plb_get_char,
     959        .plb_get_char = fat_plb_get_char,
    884960        .is_directory = fat_is_directory,
    885         .is_file = fat_is_file
     961        .is_file = fat_is_file,
     962        .device_get = fat_device_get
    886963};
    887964
     
    897974        uint16_t bps;
    898975        uint16_t rde;
    899         int rc;
    900 
    901         /* accept the mount options */
    902         ipc_callid_t callid;
    903         size_t size;
    904         if (!async_data_write_receive(&callid, &size)) {
    905                 ipc_answer_0(callid, EINVAL);
    906                 ipc_answer_0(rid, EINVAL);
    907                 return;
    908         }
    909         char *opts = malloc(size + 1);
    910         if (!opts) {
    911                 ipc_answer_0(callid, ENOMEM);
    912                 ipc_answer_0(rid, ENOMEM);
    913                 return;
    914         }
    915         ipcarg_t retval = async_data_write_finalize(callid, opts, size);
    916         if (retval != EOK) {
    917                 ipc_answer_0(rid, retval);
    918                 free(opts);
    919                 return;
    920         }
    921         opts[size] = '\0';
     976       
     977        /* Accept the mount options */
     978        char *opts;
     979        int rc = async_string_receive(&opts, 0, NULL);
     980       
     981        if (rc != EOK) {
     982                ipc_answer_0(rid, rc);
     983                return;
     984        }
    922985
    923986        /* Check for option enabling write through. */
     
    927990                cmode = CACHE_MODE_WB;
    928991
     992        free(opts);
     993
    929994        /* initialize libblock */
    930995        rc = block_init(dev_handle, BS_SIZE);
     
    9631028        }
    9641029
     1030        /* Do some simple sanity checks on the file system. */
     1031        rc = fat_sanity_check(bs, dev_handle);
     1032        if (rc != EOK) {
     1033                (void) block_cache_fini(dev_handle);
     1034                block_fini(dev_handle);
     1035                ipc_answer_0(rid, rc);
     1036                return;
     1037        }
     1038
    9651039        rc = fat_idx_init_by_dev_handle(dev_handle);
    9661040        if (rc != EOK) {
     1041                (void) block_cache_fini(dev_handle);
    9671042                block_fini(dev_handle);
    9681043                ipc_answer_0(rid, rc);
     
    9731048        fs_node_t *rfn = (fs_node_t *)malloc(sizeof(fs_node_t));
    9741049        if (!rfn) {
     1050                (void) block_cache_fini(dev_handle);
    9751051                block_fini(dev_handle);
    9761052                fat_idx_fini_by_dev_handle(dev_handle);
     
    9821058        if (!rootp) {
    9831059                free(rfn);
     1060                (void) block_cache_fini(dev_handle);
    9841061                block_fini(dev_handle);
    9851062                fat_idx_fini_by_dev_handle(dev_handle);
     
    9931070                free(rfn);
    9941071                free(rootp);
     1072                (void) block_cache_fini(dev_handle);
    9951073                block_fini(dev_handle);
    9961074                fat_idx_fini_by_dev_handle(dev_handle);
     
    10191097{
    10201098        libfs_mount(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
     1099}
     1100
     1101void fat_unmounted(ipc_callid_t rid, ipc_call_t *request)
     1102{
     1103        dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
     1104        fs_node_t *fn;
     1105        fat_node_t *nodep;
     1106        int rc;
     1107
     1108        rc = fat_root_get(&fn, dev_handle);
     1109        if (rc != EOK) {
     1110                ipc_answer_0(rid, rc);
     1111                return;
     1112        }
     1113        nodep = FAT_NODE(fn);
     1114
     1115        /*
     1116         * We expect exactly two references on the root node. One for the
     1117         * fat_root_get() above and one created in fat_mounted().
     1118         */
     1119        if (nodep->refcnt != 2) {
     1120                (void) fat_node_put(fn);
     1121                ipc_answer_0(rid, EBUSY);
     1122                return;
     1123        }
     1124       
     1125        /*
     1126         * Put the root node and force it to the FAT free node list.
     1127         */
     1128        (void) fat_node_put(fn);
     1129        (void) fat_node_put(fn);
     1130
     1131        /*
     1132         * Perform cleanup of the node structures, index structures and
     1133         * associated data. Write back this file system's dirty blocks and
     1134         * stop using libblock for this instance.
     1135         */
     1136        (void) fat_node_fini_by_dev_handle(dev_handle);
     1137        fat_idx_fini_by_dev_handle(dev_handle);
     1138        (void) block_cache_fini(dev_handle);
     1139        block_fini(dev_handle);
     1140
     1141        ipc_answer_0(rid, EOK);
     1142}
     1143
     1144void fat_unmount(ipc_callid_t rid, ipc_call_t *request)
     1145{
     1146        libfs_unmount(&fat_libfs_ops, rid, request);
    10211147}
    10221148
Note: See TracChangeset for help on using the changeset viewer.