Ignore:
File:
1 edited

Legend:

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

    r1313ee9 red903174  
    4545#include <ipc/services.h>
    4646#include <ipc/devmap.h>
     47#include <macros.h>
    4748#include <async.h>
    4849#include <errno.h>
     
    7980static int fat_has_children(bool *, fs_node_t *);
    8081static fs_index_t fat_index_get(fs_node_t *);
    81 static size_t fat_size_get(fs_node_t *);
     82static aoff64_t fat_size_get(fs_node_t *);
    8283static unsigned fat_lnkcnt_get(fs_node_t *);
    8384static char fat_plb_get_char(unsigned);
     
    137138        rc = block_put(b);
    138139        return rc;
     140}
     141
     142static int fat_node_fini_by_dev_handle(dev_handle_t dev_handle)
     143{
     144        link_t *lnk;
     145        fat_node_t *nodep;
     146        int rc;
     147
     148        /*
     149         * We are called from fat_unmounted() and assume that there are already
     150         * no nodes belonging to this instance with non-zero refcount. Therefore
     151         * it is sufficient to clean up only the FAT free node list.
     152         */
     153
     154restart:
     155        fibril_mutex_lock(&ffn_mutex);
     156        for (lnk = ffn_head.next; lnk != &ffn_head; lnk = lnk->next) {
     157                nodep = list_get_instance(lnk, fat_node_t, ffn_link);
     158                if (!fibril_mutex_trylock(&nodep->lock)) {
     159                        fibril_mutex_unlock(&ffn_mutex);
     160                        goto restart;
     161                }
     162                if (!fibril_mutex_trylock(&nodep->idx->lock)) {
     163                        fibril_mutex_unlock(&nodep->lock);
     164                        fibril_mutex_unlock(&ffn_mutex);
     165                        goto restart;
     166                }
     167                if (nodep->idx->dev_handle != dev_handle) {
     168                        fibril_mutex_unlock(&nodep->idx->lock);
     169                        fibril_mutex_unlock(&nodep->lock);
     170                        continue;
     171                }
     172
     173                list_remove(&nodep->ffn_link);
     174                fibril_mutex_unlock(&ffn_mutex);
     175
     176                /*
     177                 * We can unlock the node and its index structure because we are
     178                 * the last player on this playground and VFS is preventing new
     179                 * players from entering.
     180                 */
     181                fibril_mutex_unlock(&nodep->idx->lock);
     182                fibril_mutex_unlock(&nodep->lock);
     183
     184                if (nodep->dirty) {
     185                        rc = fat_node_sync(nodep);
     186                        if (rc != EOK)
     187                                return rc;
     188                }
     189                nodep->idx->nodep = NULL;
     190                free(nodep->bp);
     191                free(nodep);
     192
     193                /* Need to restart because we changed the ffn_head list. */
     194                goto restart;
     195        }
     196        fibril_mutex_unlock(&ffn_mutex);
     197
     198        return EOK;
    139199}
    140200
     
    663723        fibril_mutex_lock(&childp->idx->lock);
    664724       
    665         /*
    666          * If possible, create the Sub-directory Identifier Entry and the
    667          * Sub-directory Parent Pointer Entry (i.e. "." and ".."). These entries
    668          * are not mandatory according to Standard ECMA-107 and HelenOS VFS does
    669          * not use them anyway, so this is rather a sign of our good will.
    670          */
    671         rc = fat_block_get(&b, bs, childp, 0, BLOCK_FLAGS_NONE);
    672         if (rc != EOK) {
     725        if (childp->type == FAT_DIRECTORY) {
    673726                /*
    674                  * Rather than returning an error, simply skip the creation of
    675                  * these two entries.
     727                 * If possible, create the Sub-directory Identifier Entry and
     728                 * the Sub-directory Parent Pointer Entry (i.e. "." and "..").
     729                 * These entries are not mandatory according to Standard
     730                 * ECMA-107 and HelenOS VFS does not use them anyway, so this is
     731                 * rather a sign of our good will.
    676732                 */
    677                 goto skip_dots;
    678         }
    679         d = (fat_dentry_t *)b->data;
    680         if (fat_classify_dentry(d) == FAT_DENTRY_LAST ||
    681             str_cmp(d->name, FAT_NAME_DOT) == 0) {
    682                 memset(d, 0, sizeof(fat_dentry_t));
    683                 str_cpy(d->name, 8, FAT_NAME_DOT);
    684                 str_cpy(d->ext, 3, FAT_EXT_PAD);
    685                 d->attr = FAT_ATTR_SUBDIR;
    686                 d->firstc = host2uint16_t_le(childp->firstc);
    687                 /* TODO: initialize also the date/time members. */
    688         }
    689         d++;
    690         if (fat_classify_dentry(d) == FAT_DENTRY_LAST ||
    691             str_cmp(d->name, FAT_NAME_DOT_DOT) == 0) {
    692                 memset(d, 0, sizeof(fat_dentry_t));
    693                 str_cpy(d->name, 8, FAT_NAME_DOT_DOT);
    694                 str_cpy(d->ext, 3, FAT_EXT_PAD);
    695                 d->attr = FAT_ATTR_SUBDIR;
    696                 d->firstc = (parentp->firstc == FAT_CLST_ROOT) ?
    697                     host2uint16_t_le(FAT_CLST_RES0) :
    698                     host2uint16_t_le(parentp->firstc);
    699                 /* TODO: initialize also the date/time members. */
    700         }
    701         b->dirty = true;                /* need to sync block */
    702         /*
    703          * Ignore the return value as we would have fallen through on error
    704          * anyway.
    705          */
    706         (void) block_put(b);
     733                rc = fat_block_get(&b, bs, childp, 0, BLOCK_FLAGS_NONE);
     734                if (rc != EOK) {
     735                        /*
     736                         * Rather than returning an error, simply skip the
     737                         * creation of these two entries.
     738                         */
     739                        goto skip_dots;
     740                }
     741                d = (fat_dentry_t *) b->data;
     742                if ((fat_classify_dentry(d) == FAT_DENTRY_LAST) ||
     743                    (str_cmp((char *) d->name, FAT_NAME_DOT)) == 0) {
     744                        memset(d, 0, sizeof(fat_dentry_t));
     745                        str_cpy((char *) d->name, 8, FAT_NAME_DOT);
     746                        str_cpy((char *) d->ext, 3, FAT_EXT_PAD);
     747                        d->attr = FAT_ATTR_SUBDIR;
     748                        d->firstc = host2uint16_t_le(childp->firstc);
     749                        /* TODO: initialize also the date/time members. */
     750                }
     751                d++;
     752                if ((fat_classify_dentry(d) == FAT_DENTRY_LAST) ||
     753                    (str_cmp((char *) d->name, FAT_NAME_DOT_DOT) == 0)) {
     754                        memset(d, 0, sizeof(fat_dentry_t));
     755                        str_cpy((char *) d->name, 8, FAT_NAME_DOT_DOT);
     756                        str_cpy((char *) d->ext, 3, FAT_EXT_PAD);
     757                        d->attr = FAT_ATTR_SUBDIR;
     758                        d->firstc = (parentp->firstc == FAT_CLST_ROOT) ?
     759                            host2uint16_t_le(FAT_CLST_RES0) :
     760                            host2uint16_t_le(parentp->firstc);
     761                        /* TODO: initialize also the date/time members. */
     762                }
     763                b->dirty = true;                /* need to sync block */
     764                /*
     765                 * Ignore the return value as we would have fallen through on error
     766                 * anyway.
     767                 */
     768                (void) block_put(b);
     769        }
    707770skip_dots:
    708771
     
    853916}
    854917
    855 size_t fat_size_get(fs_node_t *fn)
     918aoff64_t fat_size_get(fs_node_t *fn)
    856919{
    857920        return FAT_NODE(fn)->size;
     
    915978        uint16_t bps;
    916979        uint16_t rde;
    917         int rc;
    918 
    919         /* accept the mount options */
    920         ipc_callid_t callid;
    921         size_t size;
    922         if (!async_data_write_receive(&callid, &size)) {
    923                 ipc_answer_0(callid, EINVAL);
    924                 ipc_answer_0(rid, EINVAL);
    925                 return;
    926         }
    927         char *opts = malloc(size + 1);
    928         if (!opts) {
    929                 ipc_answer_0(callid, ENOMEM);
    930                 ipc_answer_0(rid, ENOMEM);
    931                 return;
    932         }
    933         ipcarg_t retval = async_data_write_finalize(callid, opts, size);
    934         if (retval != EOK) {
    935                 ipc_answer_0(rid, retval);
    936                 free(opts);
    937                 return;
    938         }
    939         opts[size] = '\0';
     980       
     981        /* Accept the mount options */
     982        char *opts;
     983        int rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL);
     984       
     985        if (rc != EOK) {
     986                ipc_answer_0(rid, rc);
     987                return;
     988        }
    940989
    941990        /* Check for option enabling write through. */
     
    945994                cmode = CACHE_MODE_WB;
    946995
     996        free(opts);
     997
    947998        /* initialize libblock */
    948999        rc = block_init(dev_handle, BS_SIZE);
     
    9811032        }
    9821033
     1034        /* Do some simple sanity checks on the file system. */
     1035        rc = fat_sanity_check(bs, dev_handle);
     1036        if (rc != EOK) {
     1037                (void) block_cache_fini(dev_handle);
     1038                block_fini(dev_handle);
     1039                ipc_answer_0(rid, rc);
     1040                return;
     1041        }
     1042
    9831043        rc = fat_idx_init_by_dev_handle(dev_handle);
    9841044        if (rc != EOK) {
     1045                (void) block_cache_fini(dev_handle);
    9851046                block_fini(dev_handle);
    9861047                ipc_answer_0(rid, rc);
     
    9911052        fs_node_t *rfn = (fs_node_t *)malloc(sizeof(fs_node_t));
    9921053        if (!rfn) {
     1054                (void) block_cache_fini(dev_handle);
    9931055                block_fini(dev_handle);
    9941056                fat_idx_fini_by_dev_handle(dev_handle);
     
    10001062        if (!rootp) {
    10011063                free(rfn);
     1064                (void) block_cache_fini(dev_handle);
    10021065                block_fini(dev_handle);
    10031066                fat_idx_fini_by_dev_handle(dev_handle);
     
    10111074                free(rfn);
    10121075                free(rootp);
     1076                (void) block_cache_fini(dev_handle);
    10131077                block_fini(dev_handle);
    10141078                fat_idx_fini_by_dev_handle(dev_handle);
     
    10391103}
    10401104
     1105void fat_unmounted(ipc_callid_t rid, ipc_call_t *request)
     1106{
     1107        dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
     1108        fs_node_t *fn;
     1109        fat_node_t *nodep;
     1110        int rc;
     1111
     1112        rc = fat_root_get(&fn, dev_handle);
     1113        if (rc != EOK) {
     1114                ipc_answer_0(rid, rc);
     1115                return;
     1116        }
     1117        nodep = FAT_NODE(fn);
     1118
     1119        /*
     1120         * We expect exactly two references on the root node. One for the
     1121         * fat_root_get() above and one created in fat_mounted().
     1122         */
     1123        if (nodep->refcnt != 2) {
     1124                (void) fat_node_put(fn);
     1125                ipc_answer_0(rid, EBUSY);
     1126                return;
     1127        }
     1128       
     1129        /*
     1130         * Put the root node and force it to the FAT free node list.
     1131         */
     1132        (void) fat_node_put(fn);
     1133        (void) fat_node_put(fn);
     1134
     1135        /*
     1136         * Perform cleanup of the node structures, index structures and
     1137         * associated data. Write back this file system's dirty blocks and
     1138         * stop using libblock for this instance.
     1139         */
     1140        (void) fat_node_fini_by_dev_handle(dev_handle);
     1141        fat_idx_fini_by_dev_handle(dev_handle);
     1142        (void) block_cache_fini(dev_handle);
     1143        block_fini(dev_handle);
     1144
     1145        ipc_answer_0(rid, EOK);
     1146}
     1147
     1148void fat_unmount(ipc_callid_t rid, ipc_call_t *request)
     1149{
     1150        libfs_unmount(&fat_libfs_ops, rid, request);
     1151}
     1152
    10411153void fat_lookup(ipc_callid_t rid, ipc_call_t *request)
    10421154{
     
    10461158void fat_read(ipc_callid_t rid, ipc_call_t *request)
    10471159{
    1048         dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request);
    1049         fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
    1050         off_t pos = (off_t)IPC_GET_ARG3(*request);
     1160        dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
     1161        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
     1162        aoff64_t pos =
     1163            (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
    10511164        fs_node_t *fn;
    10521165        fat_node_t *nodep;
     
    11121225        } else {
    11131226                unsigned bnum;
    1114                 off_t spos = pos;
     1227                aoff64_t spos = pos;
    11151228                char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1];
    11161229                fat_dentry_t *d;
     
    11281241                bnum = (pos * sizeof(fat_dentry_t)) / bps;
    11291242                while (bnum < nodep->size / bps) {
    1130                         off_t o;
     1243                        aoff64_t o;
    11311244
    11321245                        rc = fat_block_get(&b, bs, nodep, bnum,
     
    11841297void fat_write(ipc_callid_t rid, ipc_call_t *request)
    11851298{
    1186         dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request);
    1187         fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
    1188         off_t pos = (off_t)IPC_GET_ARG3(*request);
     1299        dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
     1300        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
     1301        aoff64_t pos =
     1302            (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
    11891303        fs_node_t *fn;
    11901304        fat_node_t *nodep;
     
    11951309        unsigned spc;
    11961310        unsigned bpc;           /* bytes per cluster */
    1197         off_t boundary;
     1311        aoff64_t boundary;
    11981312        int flags = BLOCK_FLAGS_NONE;
    11991313        int rc;
     
    13411455void fat_truncate(ipc_callid_t rid, ipc_call_t *request)
    13421456{
    1343         dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request);
    1344         fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
    1345         size_t size = (off_t)IPC_GET_ARG3(*request);
     1457        dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
     1458        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
     1459        aoff64_t size =
     1460            (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
    13461461        fs_node_t *fn;
    13471462        fat_node_t *nodep;
Note: See TracChangeset for help on using the changeset viewer.