Changeset 97bc3ee in mainline


Ignore:
Timestamp:
2011-04-09T19:23:12Z (13 years ago)
Author:
Oleg Romanenko <romanenko.oleg@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
d260a95
Parents:
fc35e98
Message:

Full support for FAT12 file system. Correct creating directories and files. Fixing addressing issue.
Type of FAT (12,16,32) is determined only on the basis of the count of clusters(according to Microsoft FAT specification). I.e. FAT
with 4085 clusters or less will be determined as FAT12. FAT16 must contain more than 4085 clusters but less then 65525.

Location:
uspace/srv/fs/fat
Files:
3 edited

Legend:

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

    rfc35e98 r97bc3ee  
    2929/** @addtogroup fs
    3030 * @{
    31  */ 
     31 */
    3232
    3333/**
     
    5353 * primitive boot sector members.
    5454 */
    55 #define RDS(bs)         ((sizeof(fat_dentry_t) * RDE((bs))) / BPS((bs))) + \
    56                         (((sizeof(fat_dentry_t) * RDE((bs))) % BPS((bs))) != 0)
    57 #define SSA(bs)         (RSCNT((bs)) + FATCNT((bs)) * SF((bs)) + RDS(bs))
    58 
    5955#define CLBN2PBN(bs, cl, bn) \
    6056        (SSA((bs)) + ((cl) - FAT_CLST_FIRST) * SPC((bs)) + (bn) % SPC((bs)))
     
    6460 * during allocation of clusters. The lock does not have to be held durring
    6561 * deallocation of clusters.
    66  */ 
     62 */
    6763static FIBRIL_MUTEX_INITIALIZE(fat_alloc_lock);
    6864
     
    7672 * @param numc          If non-NULL, output argument holding the number of
    7773 *                      clusters seen during the walk.
    78  * @param max_clusters  Maximum number of clusters to visit.   
     74 * @param max_clusters  Maximum number of clusters to visit.
    7975 *
    8076 * @return              EOK on success or a negative error code.
    8177 */
    82 int 
     78int
    8379fat_cluster_walk(fat_bs_t *bs, devmap_handle_t devmap_handle, fat_cluster_t firstc,
    8480    fat_cluster_t *lastc, uint16_t *numc, uint16_t max_clusters)
     
    105101
    106102                /* read FAT1 */
    107                 /* We should use fat_get_cluster instead */
    108103                rc = fat_get_cluster(bs, devmap_handle, FAT1, clst, &clst);
    109104                if (rc != EOK)
     
    145140                return ELIMIT;
    146141
    147         if (nodep->firstc == FAT_CLST_ROOT) 
     142        if (nodep->firstc == FAT_CLST_ROOT)
    148143                goto fall_through;
    149144
     
    172167        if (rc != EOK)
    173168                return rc;
    174        
     169
    175170        /*
    176171         * Update the "current" cluster cache.
     
    192187 * @param clp           If not NULL, address where the cluster containing bn
    193188 *                      will be stored.
    194  *                      stored 
     189 *                      stored
    195190 * @param bn            Block number.
    196191 * @param flags         Flags passed to libblock.
     
    269264                        return rc;
    270265        }
    271        
     266
    272267        if (o >= pos)
    273268                return EOK;
    274        
     269
    275270        /* zero out the initial part of the new cluster chain */
    276271        for (o = boundary; o < pos; o += BPS(bs)) {
     
    302297    fat_cluster_t clst, fat_cluster_t *value)
    303298{
    304         block_t *b;
    305         fat_cluster_t *cp;
    306         aoff64_t fsec;  /* sector offset relative to FAT */
    307         unsigned fidx;  /* entry index */
     299        block_t *b, *b1;
     300        aoff64_t offset;
    308301        int rc;
    309302
    310303        assert(fatno < FATCNT(bs));
    311304
    312 
    313305        if (FATTYPE(bs) == 16)
    314         {
    315             fsec = (clst * sizeof(fat_cluster_t)) / BPS(bs);
    316             fidx = clst % (BPS(bs) / sizeof(fat_cluster_t));
     306            offset = (clst * 2);
     307        else
     308            offset = (clst + clst/2);
     309
     310        rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
     311                       offset / BPS(bs), BLOCK_FLAGS_NONE);
     312        if (rc != EOK)
     313                return rc;
     314
     315        /* This cluster access spans a sector boundary. Check only for FAT12 */
     316        if (FATTYPE(bs) == 12 && (offset % BPS(bs)+1 == BPS(bs))) {
     317            /* Is it last sector of FAT? */
     318            if (offset / BPS(bs) < SF(bs)) { /* NO */
     319                /* Reading next sector */
     320                rc = block_get(&b1, devmap_handle, 1+RSCNT(bs)+SF(bs)*fatno +
     321                               offset / BPS(bs), BLOCK_FLAGS_NONE);
     322                if (rc != EOK) {
     323                    block_put(b);
     324                    return rc;
     325                }
     326                /*
     327                 * Combining value with last byte of current sector and
     328                 * first byte of next sector
     329                 */
     330                *value  = *(uint8_t *)(b->data + BPS(bs) - 1);
     331                *value |= *(uint8_t *)(b1->data);
     332
     333                rc = block_put(b1);
     334                if (rc != EOK) {
     335                    block_put(b);
     336                    return rc;
     337                }
     338            }
     339            else {      /* YES */
     340                block_put(b);
     341                return ERANGE;
     342            }
    317343        }
    318344        else
    319         {
    320             fsec = (clst + clst/2) / BPS(bs);
    321             fidx = clst % (2 * BPS(bs) / 3 );
    322         }
    323 
    324         rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
    325                        fsec, BLOCK_FLAGS_NONE);
    326         if (rc != EOK)
    327                 return rc;
    328 
    329         if (FATTYPE(bs) == 16)
    330             cp = &((fat_cluster_t *)b->data)[fidx];
    331         else
    332             cp = (fat_cluster_t *)(b->data + fidx);
    333 
    334         *value = *cp;
    335 
    336         if (FATTYPE(bs) == 12)
    337         {
     345            *value = *(fat_cluster_t *)(b->data + offset % BPS(bs));
     346
     347        if (FATTYPE(bs) == 12) {
    338348            if (clst & 0x0001)
    339349                *value = (*value) >> 4;
     
    344354        *value = uint16_t_le2host(*value);
    345355        rc = block_put(b);
    346        
     356
    347357        return rc;
    348358}
     
    362372    fat_cluster_t clst, fat_cluster_t value)
    363373{
    364         block_t *b;
    365         fat_cluster_t *cp;
    366         int rc;
    367         aoff64_t fsec;  /* sector offset relative to FAT */
    368         unsigned fidx;  /* entry index */
     374        block_t *b, *b1;
     375        aoff64_t offset;
     376        fat_cluster_t *cp, temp;
     377        int rc;
     378        int spans = 0;
    369379
    370380        assert(fatno < FATCNT(bs));
    371381
    372382        if (FATTYPE(bs) == 16)
    373         {
    374             fsec = (clst * sizeof(fat_cluster_t)) / BPS(bs);
    375             fidx = clst % (BPS(bs) / sizeof(fat_cluster_t));
     383            offset = (clst * sizeof(fat_cluster_t));
     384        else
     385            offset = (clst + clst/2);
     386
     387        rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
     388                       offset / BPS(bs), BLOCK_FLAGS_NONE);
     389        if (rc != EOK)
     390                return rc;
     391
     392        /* This cluster access spans a sector boundary. Check only for FAT12 */
     393        if (FATTYPE(bs) == 12 && (offset % BPS(bs)+1 == BPS(bs))) {
     394            /* Is it last sector of FAT? */
     395            if (offset / BPS(bs) < SF(bs)) { /* NO */
     396                /* Reading next sector */
     397                rc = block_get(&b1, devmap_handle, 1+RSCNT(bs)+SF(bs)*fatno +
     398                               offset / BPS(bs), BLOCK_FLAGS_NONE);
     399                if (rc != EOK) {
     400                    block_put(b);
     401                    return rc;
     402                }
     403                /*
     404                 * Combining value with last byte of current sector and
     405                 * first byte of next sector
     406                 */
     407                spans=1;
     408                cp = &temp;
     409                *cp  = *(uint8_t *)(b->data + BPS(bs) - 1);
     410                *cp |= *(uint8_t *)(b1->data);
     411            }
     412            else {      /* YES */
     413                block_put(b);
     414                return ERANGE;
     415            }
    376416        }
    377417        else
    378         {
    379             fsec = (clst + clst/2) / BPS(bs);
    380             fidx = clst % (2 * BPS(bs) / 3 );
    381         }
    382 
    383         rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
    384                        fsec, BLOCK_FLAGS_NONE);
    385         if (rc != EOK)
    386                 return rc;
    387 
    388         if (FATTYPE(bs) == 12)
    389         {
    390             cp = (fat_cluster_t *)(b->data + fidx);
    391             if (clst & 0x0001)
     418            cp = (fat_cluster_t *)(b->data + offset % BPS(bs));
     419
     420        value = host2uint16_t_le(value);
     421        if (FATTYPE(bs) == 12) {
     422            if (clst & 0x0001) {
     423                *cp &= 0x000f;
     424                *cp |= value << 4;
     425            }
     426            else {
     427                *cp &= 0xf000;
     428                *cp |= value & 0x0fff;
     429            }
     430
     431            if (spans)
    392432            {
    393                 *cp &= 0x000f;
    394                 *cp |= host2uint16_t_le(value) << 4;
    395             }
    396             else
    397             {
    398                 *cp &= 0xf000;
    399                 *cp |= host2uint16_t_le(value) & 0x0fff;
     433                *(uint8_t *)(b->data + BPS(bs) - 1) = cp[0];
     434                *(uint8_t *)(b1->data) = cp[1];
     435
     436                b1->dirty = true;
     437                rc = block_put(b1);
     438                if (rc != EOK) {
     439                    block_put(b);
     440                    return rc;
     441                }
    400442            }
    401443        }
    402444        else
    403         {
    404             cp = &((fat_cluster_t *)b->data)[fidx];
    405             *cp = host2uint16_t_le(value);
    406         }
     445            *cp = value;
    407446
    408447        b->dirty = true;                /* need to sync block */
     
    464503        fat_cluster_t *lifo;    /* stack for storing free cluster numbers */
    465504        unsigned found = 0;     /* top of the free cluster number stack */
    466         fat_cluster_t clst, max_clst, value;
     505        fat_cluster_t clst, value;
    467506        int rc = EOK;
    468507        uint16_t clst_last1 = FATTYPE(bs) == 16 ? FAT16_CLST_LAST1 :
    469508                                                  FAT12_CLST_LAST1;
    470509
    471 
    472510        lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t));
    473511        if (!lifo)
    474512                return ENOMEM;
    475 
    476513        /*
    477514         * Search FAT1 for unused clusters.
    478515         */
    479 
    480         if (FATTYPE(bs) == 16)
    481             max_clst = SF(bs) * BPS(bs) / sizeof(fat_cluster_t);
    482         else
    483             max_clst = 2 *SF(bs) * BPS(bs) / 3;
    484 
    485516        fibril_mutex_lock(&fat_alloc_lock);
    486         for (clst=0; clst < max_clst && found < nclsts; clst++)
    487         {
     517        for (clst=FAT_CLST_FIRST; clst < CC(bs)+2 && found < nclsts; clst++) {
    488518            rc = fat_get_cluster(bs, devmap_handle, FAT1, clst, &value);
    489519            if (rc != EOK)
    490520                break;
    491             /*
    492             * Check if the entire cluster is physically there.
    493             * This check becomes necessary when the file system is
    494             * created with fewer total sectors than how many is
    495             * inferred from the size of the file allocation table
    496             * or when the last cluster ends beyond the end of the
    497             * device.
    498             */
    499             if ((clst >= FAT_CLST_FIRST) &&
    500                 CLBN2PBN(bs, clst, SPC(bs) - 1) >= TS(bs)) {
    501                     rc = EIO;
    502                     break;
    503             }
     521
    504522            if (value == FAT_CLST_RES0) {
    505523                /*
     
    518536        }
    519537
    520         if (rc == EOK && found == nclsts)
    521         {
     538        if (rc == EOK && found == nclsts) {
    522539            rc = fat_alloc_shadow_clusters(bs, devmap_handle, lifo, nclsts);
    523             if (rc == EOK)
    524             {
     540            if (rc == EOK) {
    525541                *mcl = lifo[found - 1];
    526542                *lcl = lifo[0];
     
    532548
    533549        /* If something wrong - free the clusters */
    534         if (found > 0)
    535         {
     550        if (found > 0) {
    536551            while (found--) {
    537552                rc = fat_set_cluster(bs, devmap_handle, FAT1, lifo[found],
     
    735750
    736751        if (bs->totsec16 != 0 && bs->totsec32 != 0 &&
    737             bs->totsec16 != bs->totsec32) 
     752            bs->totsec16 != bs->totsec32)
    738753                return ENOTSUP;
    739754
     
    775790                 * set to one.
    776791                 */
    777                 /* Disabled for testing FAT12
    778                 if ((e0 >> 8) != 0xff || e1 != 0xffff)
     792                if (FATTYPE(bs)!=12 && ((e0 >> 8) != 0xff || e1 != 0xffff))
    779793                        return ENOTSUP;
    780                 */
    781794        }
    782795
     
    786799/**
    787800 * @}
    788  */ 
     801 */
  • uspace/srv/fs/fat/fat_fat.h

    rfc35e98 r97bc3ee  
    2929/** @addtogroup fs
    3030 * @{
    31  */ 
     31 */
    3232
    3333#ifndef FAT_FAT_FAT_H_
     
    5656#define FAT_CLST_ROOT           FAT_CLST_RES1
    5757
    58 #define FATTYPE(bs)      (bs)->reserved
     58/*
     59 * Convenience macros for computing some frequently used values from the
     60 * primitive boot sector members.
     61 */
     62#define RDS(bs)         ((sizeof(fat_dentry_t) * RDE((bs))) / BPS((bs))) + \
     63                        (((sizeof(fat_dentry_t) * RDE((bs))) % BPS((bs))) != 0)
     64#define SSA(bs)         (RSCNT((bs)) + FATCNT((bs)) * SF((bs)) + RDS(bs))
     65#define DS(bs)          (TS(bs) - SSA(bs))
     66#define CC(bs)          (DS(bs) / SPC(bs))
     67#define FATTYPE(bs)     (bs)->reserved
    5968
    6069/* forward declarations */
  • uspace/srv/fs/fat/fat_ops.c

    rfc35e98 r97bc3ee  
    2929/** @addtogroup fs
    3030 * @{
    31  */ 
     31 */
    3232
    3333/**
     
    116116        fat_dentry_t *d;
    117117        int rc;
    118        
     118
    119119        assert(node->dirty);
    120120
    121121        bs = block_bb_get(node->idx->devmap_handle);
    122        
     122
    123123        /* Read the block that contains the dentry of interest. */
    124124        rc = _fat_block_get(&b, bs, node->idx->devmap_handle, node->idx->pfc,
     
    136136                d->attr = FAT_ATTR_SUBDIR;
    137137        }
    138        
     138
    139139        /* TODO: update other fields? (e.g time fields) */
    140        
     140
    141141        b->dirty = true;                /* need to sync block */
    142142        rc = block_put(b);
     
    255255        fn->data = nodep;
    256256        nodep->bp = fn;
    257        
     257
    258258        *nodepp = nodep;
    259259        return EOK;
     
    291291         * We must instantiate the node from the file system.
    292292         */
    293        
     293
    294294        assert(idxp->pfc);
    295295
     
    310310        d = ((fat_dentry_t *)b->data) + (idxp->pdi % DPS(bs));
    311311        if (d->attr & FAT_ATTR_SUBDIR) {
    312                 /* 
     312                /*
    313313                 * The only directory which does not have this bit set is the
    314314                 * root directory itself. The root directory node is handled
     
    316316                 */
    317317                nodep->type = FAT_DIRECTORY;
    318                 /*
     318
     319                /*
    319320                 * Unfortunately, the 'size' field of the FAT dentry is not
    320321                 * defined for the directory entry type. We must determine the
     
    334335                nodep->size = uint32_t_le2host(d->size);
    335336        }
    336         nodep->firstc = uint16_t_le2host(d->firstc);
     337
     338        nodep->firstc = uint16_t_le2host(d->firstc);
    337339        nodep->lnkcnt = 1;
    338340        nodep->refcnt = 1;
     
    383385                if (rc != EOK)
    384386                        return rc;
    385                 for (j = 0; j < DPS(bs); j++) { 
     387                for (j = 0; j < DPS(bs); j++) {
    386388                        d = ((fat_dentry_t *)b->data) + j;
    387389                        switch (fat_classify_dentry(d)) {
     
    521523        rc = fat_idx_get_new(&idxp, devmap_handle);
    522524        if (rc != EOK) {
    523                 (void) fat_free_clusters(bs, devmap_handle, mcl);       
     525                (void) fat_free_clusters(bs, devmap_handle, mcl);
    524526                (void) fat_node_put(FS_NODE(nodep));
    525527                return rc;
     
    618620         * a new one.
    619621         */
    620        
     622
    621623        fibril_mutex_lock(&parentp->idx->lock);
    622624        bs = block_bb_get(parentp->idx->devmap_handle);
     
    650652        }
    651653        j = 0;
    652        
     654
    653655        /*
    654656         * We need to grow the parent in order to create a new unused dentry.
     
    697699        rc = block_put(b);
    698700        fibril_mutex_unlock(&parentp->idx->lock);
    699         if (rc != EOK) 
     701        if (rc != EOK)
    700702                return rc;
    701703
    702704        fibril_mutex_lock(&childp->idx->lock);
    703        
     705
    704706        if (childp->type == FAT_DIRECTORY) {
    705707                /*
     
    778780        if (!parentp)
    779781                return EBUSY;
    780        
     782
    781783        rc = fat_has_children(&has_children, cfn);
    782784        if (rc != EOK)
     
    794796            NULL, (childp->idx->pdi * sizeof(fat_dentry_t)) / BPS(bs),
    795797            BLOCK_FLAGS_NONE);
    796         if (rc != EOK) 
     798        if (rc != EOK)
    797799                goto error;
    798800        d = (fat_dentry_t *)b->data +
     
    839841                return EOK;
    840842        }
    841        
     843
    842844        fibril_mutex_lock(&nodep->idx->lock);
    843845        bs = block_bb_get(nodep->idx->devmap_handle);
     
    847849        for (i = 0; i < blocks; i++) {
    848850                fat_dentry_t *d;
    849        
     851
    850852                rc = fat_block_get(&b, bs, nodep, i, BLOCK_FLAGS_NONE);
    851853                if (rc != EOK) {
     
    875877                if (rc != EOK) {
    876878                        fibril_mutex_unlock(&nodep->idx->lock);
    877                         return rc;     
     879                        return rc;
    878880                }
    879881        }
     
    945947 */
    946948
    947 
    948 #define RootDirSectors(bs)      (((RDE(bs)*32) + (BPS(bs)-1)) / BPS(bs))
    949 #define FATSz(bs)               SF(bs) != 0 ? SF(bs) : uint32_t_le2host((bs)->fat32.sectors_per_fat)
    950 #define DataSec(bs)             (TS(bs) - (RSCNT(bs) + (FATCNT(bs) * FATSz(bs)) + RootDirSectors(bs)))
    951 #define CountOfClusters(bs)     (DataSec(bs) / SPC(bs))
    952 
    953949void fat_mounted(ipc_callid_t rid, ipc_call_t *request)
    954950{
     
    956952        enum cache_mode cmode;
    957953        fat_bs_t *bs;
    958        
     954
    959955        /* Accept the mount options */
    960956        char *opts;
    961957        int rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL);
    962        
     958
    963959        if (rc != EOK) {
    964960                async_answer_0(rid, rc);
     
    991987        /* get the buffer with the boot sector */
    992988        bs = block_bb_get(devmap_handle);
    993        
     989
    994990        if (BPS(bs) != BS_SIZE) {
    995991                block_fini(devmap_handle);
     
    10071003
    10081004        /* Storing FAT type (12, 16, 32) in reserved field (bs->reserved) */
    1009         if (CountOfClusters(bs) < 4085) {
     1005        if (CC(bs) < 4085) {
    10101006        /* Volume is FAT12 */
    10111007            printf("Found FAT12 filesystem\n");
    10121008            (bs)->reserved = 12;
    1013         } else if (CountOfClusters(bs) < 65525) {
     1009        } else if (CC(bs) < 65525) {
    10141010        /* Volume is FAT16 */
    10151011            printf("Found FAT16 filesystem\n");
     
    10171013        } else {
    10181014        /* Volume is FAT32 */
    1019             printf("FAT32 is not supported by FAT driver. Sorry\n");
     1015            printf("FAT32 filesystem is not supported by FAT server. Sorry.\n");
    10201016            block_fini(devmap_handle);
    10211017            async_answer_0(rid, ENOTSUP);
     
    10851081        rootp->bp = rfn;
    10861082        rfn->data = rootp;
    1087        
     1083
    10881084        fibril_mutex_unlock(&ridxp->lock);
    10891085
     
    11191115                return;
    11201116        }
    1121        
     1117
    11221118        /*
    11231119         * Put the root node and force it to the FAT free node list.
     
    13001296        int flags = BLOCK_FLAGS_NONE;
    13011297        int rc;
    1302        
     1298
    13031299        rc = fat_node_get(&fn, devmap_handle, index);
    13041300        if (rc != EOK) {
     
    13111307        }
    13121308        nodep = FAT_NODE(fn);
    1313        
     1309
    13141310        ipc_callid_t callid;
    13151311        size_t len;
     
    13281324         * but this one greatly simplifies fat_write(). Note that we can afford
    13291325         * to do this because the client must be ready to handle the return
    1330          * value signalizing a smaller number of bytes written. 
    1331          */ 
     1326         * value signalizing a smaller number of bytes written.
     1327         */
    13321328        bytes = min(len, BPS(bs) - pos % BPS(bs));
    13331329        if (bytes == BPS(bs))
    13341330                flags |= BLOCK_FLAGS_NOREAD;
    1335        
     1331
    13361332        boundary = ROUND_UP(nodep->size, BPC(bs));
    13371333        if (pos < boundary) {
     
    13791375                 */
    13801376                unsigned nclsts;
    1381                 fat_cluster_t mcl, lcl; 
    1382  
     1377                fat_cluster_t mcl, lcl;
     1378
    13831379                nclsts = (ROUND_UP(pos + bytes, BPC(bs)) - boundary) / BPC(bs);
    13841380                /* create an independent chain of nclsts clusters in all FATs */
     
    14761472                nodep->size = size;
    14771473                nodep->dirty = true;            /* need to sync node */
    1478                 rc = EOK;       
     1474                rc = EOK;
    14791475        } else {
    14801476                /*
     
    14971493                nodep->size = size;
    14981494                nodep->dirty = true;            /* need to sync node */
    1499                 rc = EOK;       
     1495                rc = EOK;
    15001496        }
    15011497out:
     
    15531549        devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
    15541550        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
    1555        
     1551
    15561552        fs_node_t *fn;
    15571553        int rc = fat_node_get(&fn, devmap_handle, index);
     
    15641560                return;
    15651561        }
    1566        
     1562
    15671563        fat_node_t *nodep = FAT_NODE(fn);
    1568        
     1564
    15691565        nodep->dirty = true;
    15701566        rc = fat_node_sync(nodep);
    1571        
     1567
    15721568        fat_node_put(fn);
    15731569        async_answer_0(rid, rc);
Note: See TracChangeset for help on using the changeset viewer.