Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/fs/mfs/mfs_ops.c

    rc2e50d7 r5bf76c1  
    4343
    4444static bool check_magic_number(uint16_t magic, bool *native,
    45     mfs_version_t *version, bool *longfilenames);
     45                               mfs_version_t *version, bool *longfilenames);
    4646static int mfs_node_core_get(fs_node_t **rfn, struct mfs_instance *inst,
    47     fs_index_t index);
     47                             fs_index_t index);
     48
    4849static int mfs_node_put(fs_node_t *fsnode);
    4950static int mfs_node_open(fs_node_t *fsnode);
     
    6364static hash_index_t open_nodes_hash(unsigned long key[]);
    6465static int open_nodes_compare(unsigned long key[], hash_count_t keys,
    65     link_t *item);
     66                link_t *item);
    6667static void open_nodes_remove_cb(link_t *link);
     68
    6769static int mfs_node_get(fs_node_t **rfn, service_id_t service_id,
    68     fs_index_t index);
    69 static int mfs_instance_get(service_id_t service_id,
    70     struct mfs_instance **instance);
    71 static int mfs_check_sanity(struct mfs_sb_info *sbi);
    72 static bool is_power_of_two(uint32_t n);
     70                        fs_index_t index);
     71static int
     72mfs_instance_get(service_id_t service_id, struct mfs_instance **instance);
     73
    7374
    7475static hash_table_t open_nodes;
     
    9596
    9697/* Hash table interface for open nodes hash table */
    97 static hash_index_t
    98 open_nodes_hash(unsigned long key[])
     98static hash_index_t open_nodes_hash(unsigned long key[])
    9999{
    100100        /* TODO: This is very simple and probably can be improved */
     
    102102}
    103103
    104 static int
    105 open_nodes_compare(unsigned long key[], hash_count_t keys,
    106     link_t *item)
     104static int open_nodes_compare(unsigned long key[], hash_count_t keys,
     105                link_t *item)
    107106{
    108107        struct mfs_node *mnode = hash_table_get_instance(item, struct mfs_node, link);
     
    119118}
    120119
    121 static void
    122 open_nodes_remove_cb(link_t *link)
     120static void open_nodes_remove_cb(link_t *link)
    123121{
    124122        /* We don't use remove callback for this hash table */
     
    131129};
    132130
    133 int
    134 mfs_global_init(void)
     131int mfs_global_init(void)
    135132{
    136133        if (!hash_table_create(&open_nodes, OPEN_NODES_BUCKETS,
    137             OPEN_NODES_KEYS, &open_nodes_ops)) {
     134                        OPEN_NODES_KEYS, &open_nodes_ops)) {
    138135                return ENOMEM;
    139136        }
     
    143140static int
    144141mfs_mounted(service_id_t service_id, const char *opts, fs_index_t *index,
    145     aoff64_t *size, unsigned *linkcnt)
     142                aoff64_t *size, unsigned *linkcnt)
    146143{
    147144        enum cache_mode cmode;
    148         struct mfs_superblock *sb = NULL;
    149         struct mfs3_superblock *sb3 = NULL;
    150         struct mfs_sb_info *sbi = NULL;
    151         struct mfs_instance *instance = NULL;
     145        struct mfs_superblock *sb;
     146        struct mfs3_superblock *sb3;
     147        struct mfs_sb_info *sbi;
     148        struct mfs_instance *instance;
    152149        bool native, longnames;
    153150        mfs_version_t version;
     
    166163                return rc;
    167164
    168         /* Allocate space for generic MFS superblock */
     165        /*Allocate space for generic MFS superblock*/
    169166        sbi = malloc(sizeof(*sbi));
    170167        if (!sbi) {
    171                 rc = ENOMEM;
    172                 goto out_error;
    173         }
    174 
    175         /* Allocate space for filesystem instance */
     168                block_fini(service_id);
     169                return ENOMEM;
     170        }
     171
     172        /*Allocate space for filesystem instance*/
    176173        instance = malloc(sizeof(*instance));
    177174        if (!instance) {
    178                 rc = ENOMEM;
    179                 goto out_error;
     175                free(sbi);
     176                block_fini(service_id);
     177                return ENOMEM;
    180178        }
    181179
    182180        sb = malloc(MFS_SUPERBLOCK_SIZE);
    183181        if (!sb) {
    184                 rc = ENOMEM;
    185                 goto out_error;
     182                free(instance);
     183                free(sbi);
     184                block_fini(service_id);
     185                return ENOMEM;
    186186        }
    187187
    188188        /* Read the superblock */
    189189        rc = block_read_direct(service_id, MFS_SUPERBLOCK << 1, 2, sb);
    190         if (rc != EOK)
    191                 goto out_error;
     190        if (rc != EOK) {
     191                free(instance);
     192                free(sbi);
     193                free(sb);
     194                block_fini(service_id);
     195                return rc;
     196        }
    192197
    193198        sb3 = (struct mfs3_superblock *) sb;
    194199
    195200        if (check_magic_number(sb->s_magic, &native, &version, &longnames)) {
    196                 /* This is a V1 or V2 Minix filesystem */
     201                /*This is a V1 or V2 Minix filesystem*/
    197202                magic = sb->s_magic;
    198203        } else if (check_magic_number(sb3->s_magic, &native, &version, &longnames)) {
    199                 /* This is a V3 Minix filesystem */
     204                /*This is a V3 Minix filesystem*/
    200205                magic = sb3->s_magic;
    201206        } else {
    202                 /* Not recognized */
     207                /*Not recognized*/
    203208                mfsdebug("magic number not recognized\n");
    204                 rc = ENOTSUP;
    205                 goto out_error;
     209                free(instance);
     210                free(sbi);
     211                free(sb);
     212                block_fini(service_id);
     213                return ENOTSUP;
    206214        }
    207215
    208216        mfsdebug("magic number recognized = %04x\n", magic);
    209217
    210         /* Fill superblock info structure */
     218        /*Fill superblock info structure*/
    211219
    212220        sbi->fs_version = version;
     
    246254                sbi->dirsize = longnames ? MFSL_DIRSIZE : MFS_DIRSIZE;
    247255                sbi->max_name_len = longnames ? MFS_L_MAX_NAME_LEN :
    248                     MFS_MAX_NAME_LEN;
    249         }
    250 
    251         if (sbi->log2_zone_size != 0) {
    252                 /* In MFS, file space is allocated per zones.
    253                  * Zones are a collection of consecutive blocks on disk.
    254                  *
    255                  * The current MFS implementation supports only filesystems
    256                  * where the size of a zone is equal to the
    257                  * size of a block.
    258                  */
    259                 rc = ENOTSUP;
    260                 goto out_error;
    261         }
    262 
     256                                    MFS_MAX_NAME_LEN;
     257        }
    263258        sbi->itable_off = 2 + sbi->ibmap_blocks + sbi->zbmap_blocks;
    264         if ((rc = mfs_check_sanity(sbi)) != EOK) {
    265                 fprintf(stderr, "Filesystem corrupted, invalid superblock");
    266                 goto out_error;
    267         }
     259
     260        free(sb);
    268261
    269262        rc = block_cache_init(service_id, sbi->block_size, 0, cmode);
    270263        if (rc != EOK) {
     264                free(instance);
     265                free(sbi);
     266                block_cache_fini(service_id);
     267                block_fini(service_id);
    271268                mfsdebug("block cache initialization failed\n");
    272                 rc = EINVAL;
    273                 goto out_error;
    274         }
    275 
    276         /* Initialize the instance structure and remember it */
     269                return EINVAL;
     270        }
     271
     272        /*Initialize the instance structure and remember it*/
    277273        instance->service_id = service_id;
    278274        instance->sbi = sbi;
     
    280276        rc = fs_instance_create(service_id, instance);
    281277        if (rc != EOK) {
     278                free(instance);
     279                free(sbi);
    282280                block_cache_fini(service_id);
     281                block_fini(service_id);
    283282                mfsdebug("fs instance creation failed\n");
    284                 goto out_error;
     283                return rc;
    285284        }
    286285
     
    296295        *linkcnt = 1;
    297296
    298         free(sb);
    299 
    300297        return mfs_node_put(fn);
    301 
    302 out_error:
    303         block_fini(service_id);
    304         if (sb)
    305                 free(sb);
    306         if (sbi)
    307                 free(sbi);
    308         if(instance)
    309                 free(instance);
    310         return rc;
    311298}
    312299
     
    335322}
    336323
    337 service_id_t
    338 mfs_service_get(fs_node_t *fsnode)
     324service_id_t mfs_service_get(fs_node_t *fsnode)
    339325{
    340326        struct mfs_node *node = fsnode->data;
     
    342328}
    343329
    344 static int
    345 mfs_create_node(fs_node_t **rfn, service_id_t service_id, int flags)
     330static int mfs_create_node(fs_node_t **rfn, service_id_t service_id, int flags)
    346331{
    347332        int r;
     
    357342                return r;
    358343
    359         /* Alloc a new inode */
     344        /*Alloc a new inode*/
    360345        r = mfs_alloc_inode(inst, &inum);
    361346        if (r != EOK)
     
    384369        if (flags & L_DIRECTORY) {
    385370                ino_i->i_mode = S_IFDIR;
    386                 ino_i->i_nlinks = 1; /* This accounts for the '.' dentry */
    387         } else
     371                ino_i->i_nlinks = 2; /*This accounts for the '.' dentry*/
     372        } else {
    388373                ino_i->i_mode = S_IFREG;
     374                ino_i->i_nlinks = 1;
     375        }
    389376
    390377        ino_i->i_uid = 0;
     
    435422}
    436423
    437 static int
    438 mfs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
     424static int mfs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
    439425{
    440426        struct mfs_node *mnode = pfn->data;
     
    458444
    459445                if (!d_info.d_inum) {
    460                         /* This entry is not used */
     446                        /*This entry is not used*/
    461447                        continue;
    462448                }
     
    465451
    466452                if (comp_size == dentry_name_size &&
    467                     !bcmp(component, d_info.d_name, dentry_name_size)) {
    468                         /* Hit! */
     453                        !bcmp(component, d_info.d_name, dentry_name_size)) {
     454                        /*Hit!*/
    469455                        mfs_node_core_get(rfn, mnode->instance,
    470                             d_info.d_inum);
     456                                          d_info.d_inum);
    471457                        goto found;
    472458                }
     
    477463}
    478464
    479 static aoff64_t
    480 mfs_size_get(fs_node_t *node)
     465static aoff64_t mfs_size_get(fs_node_t *node)
    481466{
    482467        const struct mfs_node *mnode = node->data;
     
    486471static int
    487472mfs_node_get(fs_node_t **rfn, service_id_t service_id,
    488     fs_index_t index)
     473                        fs_index_t index)
    489474{
    490475        int rc;
     
    530515}
    531516
    532 static int
    533 mfs_node_open(fs_node_t *fsnode)
     517static int mfs_node_open(fs_node_t *fsnode)
    534518{
    535519        /*
     
    540524}
    541525
    542 static fs_index_t
    543 mfs_index_get(fs_node_t *fsnode)
     526static fs_index_t mfs_index_get(fs_node_t *fsnode)
    544527{
    545528        struct mfs_node *mnode = fsnode->data;
     
    547530}
    548531
    549 static unsigned
    550 mfs_lnkcnt_get(fs_node_t *fsnode)
     532static unsigned mfs_lnkcnt_get(fs_node_t *fsnode)
    551533{
    552534        struct mfs_node *mnode = fsnode->data;
     
    563545}
    564546
    565 static int
    566 mfs_node_core_get(fs_node_t **rfn, struct mfs_instance *inst,
    567     fs_index_t index)
     547static int mfs_node_core_get(fs_node_t **rfn, struct mfs_instance *inst,
     548                             fs_index_t index)
    568549{
    569550        fs_node_t *node = NULL;
     
    637618}
    638619
    639 static bool
    640 mfs_is_directory(fs_node_t *fsnode)
     620static bool mfs_is_directory(fs_node_t *fsnode)
    641621{
    642622        const struct mfs_node *node = fsnode->data;
     
    644624}
    645625
    646 static bool
    647 mfs_is_file(fs_node_t *fsnode)
     626static bool mfs_is_file(fs_node_t *fsnode)
    648627{
    649628        struct mfs_node *node = fsnode->data;
     
    651630}
    652631
    653 static int
    654 mfs_root_get(fs_node_t **rfn, service_id_t service_id)
     632static int mfs_root_get(fs_node_t **rfn, service_id_t service_id)
    655633{
    656634        int rc = mfs_node_get(rfn, service_id, MFS_ROOT_INO);
     
    658636}
    659637
    660 static int
    661 mfs_link(fs_node_t *pfn, fs_node_t *cfn, const char *name)
     638static int mfs_link(fs_node_t *pfn, fs_node_t *cfn, const char *name)
    662639{
    663640        struct mfs_node *parent = pfn->data;
    664641        struct mfs_node *child = cfn->data;
    665642        struct mfs_sb_info *sbi = parent->instance->sbi;
    666         bool destroy_dentry = false;
    667643
    668644        mfsdebug("%s()\n", __FUNCTION__);
     
    673649        int r = mfs_insert_dentry(parent, name, child->ino_i->index);
    674650        if (r != EOK)
    675                 return r;
     651                goto exit_error;
    676652
    677653        if (S_ISDIR(child->ino_i->i_mode)) {
    678                 if (child->ino_i->i_nlinks != 1) {
    679                         /* It's not possible to hardlink directories in MFS */
    680                         destroy_dentry = true;
    681                         r = EMLINK;
    682                         goto exit;
    683                 }
    684654                r = mfs_insert_dentry(child, ".", child->ino_i->index);
    685                 if (r != EOK) {
    686                         destroy_dentry = true;
    687                         goto exit;
    688                 }
     655                if (r != EOK)
     656                        goto exit_error;
    689657
    690658                r = mfs_insert_dentry(child, "..", parent->ino_i->index);
    691                 if (r != EOK) {
    692                         destroy_dentry = true;
    693                         goto exit;
    694                 }
     659                if (r != EOK)
     660                        goto exit_error;
    695661
    696662                parent->ino_i->i_nlinks++;
     
    698664        }
    699665
    700 exit:
    701         if (destroy_dentry) {
    702                 int r2 = mfs_remove_dentry(parent, name);
    703                 if (r2 != EOK)
    704                         r = r2;
    705         } else {
    706                 child->ino_i->i_nlinks++;
    707                 child->ino_i->dirty = true;
    708         }
     666exit_error:
    709667        return r;
    710668}
     
    753711}
    754712
    755 static int
    756 mfs_has_children(bool *has_children, fs_node_t *fsnode)
     713static int mfs_has_children(bool *has_children, fs_node_t *fsnode)
    757714{
    758715        struct mfs_node *mnode = fsnode->data;
     
    775732
    776733                if (d_info.d_inum) {
    777                         /* A valid entry has been found */
     734                        /*A valid entry has been found*/
    778735                        *has_children = true;
    779736                        break;
     
    787744static int
    788745mfs_read(service_id_t service_id, fs_index_t index, aoff64_t pos,
    789     size_t *rbytes)
     746                size_t *rbytes)
    790747{
    791748        int rc;
     
    817774
    818775                if (pos < 2) {
    819                         /* Skip the first two dentries ('.' and '..') */
     776                        /*Skip the first two dentries ('.' and '..')*/
    820777                        pos = 2;
    821778                }
     
    827784
    828785                        if (d_info.d_inum) {
    829                                 /* Dentry found! */
     786                                /*Dentry found!*/
    830787                                goto found;
    831788                        }
     
    837794found:
    838795                async_data_read_finalize(callid, d_info.d_name,
    839                     str_size(d_info.d_name) + 1);
     796                                        str_size(d_info.d_name) + 1);
    840797                bytes = ((pos - spos) + 1);
    841798        } else {
     
    843800
    844801                if (pos >= (size_t) ino_i->i_size) {
    845                         /* Trying to read beyond the end of file */
     802                        /*Trying to read beyond the end of file*/
    846803                        bytes = 0;
    847804                        (void) async_data_read_finalize(callid, NULL, 0);
     
    860817
    861818                if (zone == 0) {
    862                         /* sparse file */
     819                        /*sparse file*/
    863820                        uint8_t *buf = malloc(sbi->block_size);
    864821                        if (!buf) {
     
    868825                        memset(buf, 0, sizeof(sbi->block_size));
    869826                        async_data_read_finalize(callid,
    870                             buf + pos % sbi->block_size, bytes);
     827                                                buf + pos % sbi->block_size, bytes);
    871828                        free(buf);
    872829                        goto out_success;
     
    878835
    879836                async_data_read_finalize(callid, b->data +
    880                     pos % sbi->block_size, bytes);
     837                                        pos % sbi->block_size, bytes);
    881838
    882839                rc = block_put(b);
     
    899856static int
    900857mfs_write(service_id_t service_id, fs_index_t index, aoff64_t pos,
    901     size_t *wbytes, aoff64_t *nsize)
     858                size_t *wbytes, aoff64_t *nsize)
    902859{
    903860        fs_node_t *fn;
     
    923880        struct mfs_ino_info *ino_i = mnode->ino_i;
    924881        const size_t bs = sbi->block_size;
    925         size_t bytes = min(len, bs - (pos % bs));
     882        size_t bytes = min(len, bs - pos % bs);
     883        size_t boundary = ROUND_UP(ino_i->i_size, bs);
    926884        uint32_t block;
    927885
     
    929887                flags = BLOCK_FLAGS_NOREAD;
    930888
    931         r = mfs_read_map(&block, mnode, pos);
    932         if (r != EOK)
    933                 goto out_err;
    934 
    935         if (block == 0) {
     889        if (pos < boundary) {
     890                r = mfs_read_map(&block, mnode, pos);
     891                if (r != EOK)
     892                        goto out_err;
     893
     894                if (block == 0) {
     895                        /*Writing in a sparse block*/
     896                        r = mfs_alloc_zone(mnode->instance, &block);
     897                        if (r != EOK)
     898                                goto out_err;
     899                        flags = BLOCK_FLAGS_NOREAD;
     900                }
     901        } else {
    936902                uint32_t dummy;
    937903
     
    939905                if (r != EOK)
    940906                        goto out_err;
    941                
     907
    942908                r = mfs_write_map(mnode, pos, block, &dummy);
    943909                if (r != EOK)
    944910                        goto out_err;
    945 
    946                 flags = BLOCK_FLAGS_NOREAD;
    947911        }
    948912
     
    952916                goto out_err;
    953917
    954         if (flags == BLOCK_FLAGS_NOREAD)
    955                 memset(b->data, 0, sbi->block_size);
    956 
    957         async_data_write_finalize(callid, b->data + (pos % bs), bytes);
     918        async_data_write_finalize(callid, b->data + pos % bs, bytes);
    958919        b->dirty = true;
    959920
     
    964925        }
    965926
    966         if (pos + bytes > ino_i->i_size) {
    967                 ino_i->i_size = pos + bytes;
    968                 ino_i->dirty = true;
    969         }
     927        ino_i->i_size = pos + bytes;
     928        ino_i->dirty = true;
    970929        r = mfs_node_put(fn);
    971         *nsize = ino_i->i_size;
     930        *nsize = pos + bytes;
    972931        *wbytes = bytes;
    973932        return r;
     
    991950                return ENOENT;
    992951
    993         /* Destroy the inode */
     952        /*Destroy the inode*/
    994953        return mfs_destroy_node(fn);
    995954}
     
    1010969        assert(!has_children);
    1011970
    1012         /* Free the entire inode content */
     971        /*Free the entire inode content*/
    1013972        r = mfs_inode_shrink(mnode, mnode->ino_i->i_size);
    1014973        if (r != EOK)
    1015974                goto out;
    1016975
    1017         /* Mark the inode as free in the bitmap */
     976        /*Mark the inode as free in the bitmap*/
    1018977        r = mfs_free_inode(mnode->instance, mnode->ino_i->index);
    1019978
     
    10541013
    10551014        rc = fs_instance_get(service_id, &data);
    1056         if (rc == EOK)
     1015        if (rc == EOK) {
    10571016                *instance = (struct mfs_instance *) data;
    1058         else {
     1017        } else {
    10591018                mfsdebug("instance not found\n");
    10601019        }
     
    10631022}
    10641023
    1065 static bool
    1066 check_magic_number(uint16_t magic, bool *native,
    1067                 mfs_version_t *version, bool *longfilenames)
     1024static bool check_magic_number(uint16_t magic, bool *native,
     1025                               mfs_version_t *version, bool *longfilenames)
    10681026{
    10691027        bool rc = true;
     
    10931051}
    10941052
    1095 /** Filesystem sanity check
    1096  *
    1097  * @param Pointer to the MFS superblock.
    1098  *
    1099  * @return EOK on success, ENOTSUP otherwise.
    1100  */
    1101 static int
    1102 mfs_check_sanity(struct mfs_sb_info *sbi)
    1103 {
    1104         if (!is_power_of_two(sbi->block_size) ||
    1105             sbi->block_size < MFS_MIN_BLOCKSIZE ||
    1106             sbi->block_size > MFS_MAX_BLOCKSIZE)
    1107                 return ENOTSUP;
    1108         else if (sbi->ibmap_blocks == 0 || sbi->zbmap_blocks == 0)
    1109                 return ENOTSUP;
    1110         else if (sbi->ninodes == 0 || sbi->nzones == 0)
    1111                 return ENOTSUP;
    1112         else if (sbi->firstdatazone == 0)
    1113                 return ENOTSUP;
    1114 
    1115         return EOK;
    1116 }
    1117 
    11181053static int
    11191054mfs_close(service_id_t service_id, fs_index_t index)
     
    11361071
    11371072        return mfs_node_put(fn);
    1138 }
    1139 
    1140 /** Check if a given number is a power of two.
    1141  *
    1142  * @param n     The number to check.
    1143  *
    1144  * @return      true if it is a power of two, false otherwise.
    1145  */
    1146 static bool
    1147 is_power_of_two(uint32_t n)
    1148 {
    1149         if (n == 0)
    1150                 return false;
    1151 
    1152         return (n & (n - 1)) == 0;
    11531073}
    11541074
Note: See TracChangeset for help on using the changeset viewer.