Ignore:
File:
1 edited

Legend:

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

    r5bf76c1 rc2e50d7  
    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);
    48 
     47    fs_index_t index);
    4948static int mfs_node_put(fs_node_t *fsnode);
    5049static int mfs_node_open(fs_node_t *fsnode);
     
    6463static hash_index_t open_nodes_hash(unsigned long key[]);
    6564static int open_nodes_compare(unsigned long key[], hash_count_t keys,
    66                 link_t *item);
     65    link_t *item);
    6766static void open_nodes_remove_cb(link_t *link);
    68 
    6967static int mfs_node_get(fs_node_t **rfn, service_id_t service_id,
    70                         fs_index_t index);
    71 static int
    72 mfs_instance_get(service_id_t service_id, struct mfs_instance **instance);
    73 
     68    fs_index_t index);
     69static int mfs_instance_get(service_id_t service_id,
     70    struct mfs_instance **instance);
     71static int mfs_check_sanity(struct mfs_sb_info *sbi);
     72static bool is_power_of_two(uint32_t n);
    7473
    7574static hash_table_t open_nodes;
     
    9695
    9796/* Hash table interface for open nodes hash table */
    98 static hash_index_t open_nodes_hash(unsigned long key[])
     97static hash_index_t
     98open_nodes_hash(unsigned long key[])
    9999{
    100100        /* TODO: This is very simple and probably can be improved */
     
    102102}
    103103
    104 static int open_nodes_compare(unsigned long key[], hash_count_t keys,
    105                 link_t *item)
     104static int
     105open_nodes_compare(unsigned long key[], hash_count_t keys,
     106    link_t *item)
    106107{
    107108        struct mfs_node *mnode = hash_table_get_instance(item, struct mfs_node, link);
     
    118119}
    119120
    120 static void open_nodes_remove_cb(link_t *link)
     121static void
     122open_nodes_remove_cb(link_t *link)
    121123{
    122124        /* We don't use remove callback for this hash table */
     
    129131};
    130132
    131 int mfs_global_init(void)
     133int
     134mfs_global_init(void)
    132135{
    133136        if (!hash_table_create(&open_nodes, OPEN_NODES_BUCKETS,
    134                         OPEN_NODES_KEYS, &open_nodes_ops)) {
     137            OPEN_NODES_KEYS, &open_nodes_ops)) {
    135138                return ENOMEM;
    136139        }
     
    140143static int
    141144mfs_mounted(service_id_t service_id, const char *opts, fs_index_t *index,
    142                 aoff64_t *size, unsigned *linkcnt)
     145    aoff64_t *size, unsigned *linkcnt)
    143146{
    144147        enum cache_mode cmode;
    145         struct mfs_superblock *sb;
    146         struct mfs3_superblock *sb3;
    147         struct mfs_sb_info *sbi;
    148         struct mfs_instance *instance;
     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;
    149152        bool native, longnames;
    150153        mfs_version_t version;
     
    163166                return rc;
    164167
    165         /*Allocate space for generic MFS superblock*/
     168        /* Allocate space for generic MFS superblock */
    166169        sbi = malloc(sizeof(*sbi));
    167170        if (!sbi) {
    168                 block_fini(service_id);
    169                 return ENOMEM;
    170         }
    171 
    172         /*Allocate space for filesystem instance*/
     171                rc = ENOMEM;
     172                goto out_error;
     173        }
     174
     175        /* Allocate space for filesystem instance */
    173176        instance = malloc(sizeof(*instance));
    174177        if (!instance) {
    175                 free(sbi);
    176                 block_fini(service_id);
    177                 return ENOMEM;
     178                rc = ENOMEM;
     179                goto out_error;
    178180        }
    179181
    180182        sb = malloc(MFS_SUPERBLOCK_SIZE);
    181183        if (!sb) {
    182                 free(instance);
    183                 free(sbi);
    184                 block_fini(service_id);
    185                 return ENOMEM;
     184                rc = ENOMEM;
     185                goto out_error;
    186186        }
    187187
    188188        /* Read the superblock */
    189189        rc = block_read_direct(service_id, MFS_SUPERBLOCK << 1, 2, sb);
    190         if (rc != EOK) {
    191                 free(instance);
    192                 free(sbi);
    193                 free(sb);
    194                 block_fini(service_id);
    195                 return rc;
    196         }
     190        if (rc != EOK)
     191                goto out_error;
    197192
    198193        sb3 = (struct mfs3_superblock *) sb;
    199194
    200195        if (check_magic_number(sb->s_magic, &native, &version, &longnames)) {
    201                 /*This is a V1 or V2 Minix filesystem*/
     196                /* This is a V1 or V2 Minix filesystem */
    202197                magic = sb->s_magic;
    203198        } else if (check_magic_number(sb3->s_magic, &native, &version, &longnames)) {
    204                 /*This is a V3 Minix filesystem*/
     199                /* This is a V3 Minix filesystem */
    205200                magic = sb3->s_magic;
    206201        } else {
    207                 /*Not recognized*/
     202                /* Not recognized */
    208203                mfsdebug("magic number not recognized\n");
    209                 free(instance);
    210                 free(sbi);
    211                 free(sb);
    212                 block_fini(service_id);
    213                 return ENOTSUP;
     204                rc = ENOTSUP;
     205                goto out_error;
    214206        }
    215207
    216208        mfsdebug("magic number recognized = %04x\n", magic);
    217209
    218         /*Fill superblock info structure*/
     210        /* Fill superblock info structure */
    219211
    220212        sbi->fs_version = version;
     
    254246                sbi->dirsize = longnames ? MFSL_DIRSIZE : MFS_DIRSIZE;
    255247                sbi->max_name_len = longnames ? MFS_L_MAX_NAME_LEN :
    256                                     MFS_MAX_NAME_LEN;
    257         }
     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
    258263        sbi->itable_off = 2 + sbi->ibmap_blocks + sbi->zbmap_blocks;
    259 
    260         free(sb);
     264        if ((rc = mfs_check_sanity(sbi)) != EOK) {
     265                fprintf(stderr, "Filesystem corrupted, invalid superblock");
     266                goto out_error;
     267        }
    261268
    262269        rc = block_cache_init(service_id, sbi->block_size, 0, cmode);
    263270        if (rc != EOK) {
    264                 free(instance);
    265                 free(sbi);
    266                 block_cache_fini(service_id);
    267                 block_fini(service_id);
    268271                mfsdebug("block cache initialization failed\n");
    269                 return EINVAL;
    270         }
    271 
    272         /*Initialize the instance structure and remember it*/
     272                rc = EINVAL;
     273                goto out_error;
     274        }
     275
     276        /* Initialize the instance structure and remember it */
    273277        instance->service_id = service_id;
    274278        instance->sbi = sbi;
     
    276280        rc = fs_instance_create(service_id, instance);
    277281        if (rc != EOK) {
    278                 free(instance);
    279                 free(sbi);
    280282                block_cache_fini(service_id);
    281                 block_fini(service_id);
    282283                mfsdebug("fs instance creation failed\n");
    283                 return rc;
     284                goto out_error;
    284285        }
    285286
     
    295296        *linkcnt = 1;
    296297
     298        free(sb);
     299
    297300        return mfs_node_put(fn);
     301
     302out_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;
    298311}
    299312
     
    322335}
    323336
    324 service_id_t mfs_service_get(fs_node_t *fsnode)
     337service_id_t
     338mfs_service_get(fs_node_t *fsnode)
    325339{
    326340        struct mfs_node *node = fsnode->data;
     
    328342}
    329343
    330 static int mfs_create_node(fs_node_t **rfn, service_id_t service_id, int flags)
     344static int
     345mfs_create_node(fs_node_t **rfn, service_id_t service_id, int flags)
    331346{
    332347        int r;
     
    342357                return r;
    343358
    344         /*Alloc a new inode*/
     359        /* Alloc a new inode */
    345360        r = mfs_alloc_inode(inst, &inum);
    346361        if (r != EOK)
     
    369384        if (flags & L_DIRECTORY) {
    370385                ino_i->i_mode = S_IFDIR;
    371                 ino_i->i_nlinks = 2; /*This accounts for the '.' dentry*/
    372         } else {
     386                ino_i->i_nlinks = 1; /* This accounts for the '.' dentry */
     387        } else
    373388                ino_i->i_mode = S_IFREG;
    374                 ino_i->i_nlinks = 1;
    375         }
    376389
    377390        ino_i->i_uid = 0;
     
    422435}
    423436
    424 static int mfs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
     437static int
     438mfs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
    425439{
    426440        struct mfs_node *mnode = pfn->data;
     
    444458
    445459                if (!d_info.d_inum) {
    446                         /*This entry is not used*/
     460                        /* This entry is not used */
    447461                        continue;
    448462                }
     
    451465
    452466                if (comp_size == dentry_name_size &&
    453                         !bcmp(component, d_info.d_name, dentry_name_size)) {
    454                         /*Hit!*/
     467                    !bcmp(component, d_info.d_name, dentry_name_size)) {
     468                        /* Hit! */
    455469                        mfs_node_core_get(rfn, mnode->instance,
    456                                           d_info.d_inum);
     470                            d_info.d_inum);
    457471                        goto found;
    458472                }
     
    463477}
    464478
    465 static aoff64_t mfs_size_get(fs_node_t *node)
     479static aoff64_t
     480mfs_size_get(fs_node_t *node)
    466481{
    467482        const struct mfs_node *mnode = node->data;
     
    471486static int
    472487mfs_node_get(fs_node_t **rfn, service_id_t service_id,
    473                         fs_index_t index)
     488    fs_index_t index)
    474489{
    475490        int rc;
     
    515530}
    516531
    517 static int mfs_node_open(fs_node_t *fsnode)
     532static int
     533mfs_node_open(fs_node_t *fsnode)
    518534{
    519535        /*
     
    524540}
    525541
    526 static fs_index_t mfs_index_get(fs_node_t *fsnode)
     542static fs_index_t
     543mfs_index_get(fs_node_t *fsnode)
    527544{
    528545        struct mfs_node *mnode = fsnode->data;
     
    530547}
    531548
    532 static unsigned mfs_lnkcnt_get(fs_node_t *fsnode)
     549static unsigned
     550mfs_lnkcnt_get(fs_node_t *fsnode)
    533551{
    534552        struct mfs_node *mnode = fsnode->data;
     
    545563}
    546564
    547 static int mfs_node_core_get(fs_node_t **rfn, struct mfs_instance *inst,
    548                              fs_index_t index)
     565static int
     566mfs_node_core_get(fs_node_t **rfn, struct mfs_instance *inst,
     567    fs_index_t index)
    549568{
    550569        fs_node_t *node = NULL;
     
    618637}
    619638
    620 static bool mfs_is_directory(fs_node_t *fsnode)
     639static bool
     640mfs_is_directory(fs_node_t *fsnode)
    621641{
    622642        const struct mfs_node *node = fsnode->data;
     
    624644}
    625645
    626 static bool mfs_is_file(fs_node_t *fsnode)
     646static bool
     647mfs_is_file(fs_node_t *fsnode)
    627648{
    628649        struct mfs_node *node = fsnode->data;
     
    630651}
    631652
    632 static int mfs_root_get(fs_node_t **rfn, service_id_t service_id)
     653static int
     654mfs_root_get(fs_node_t **rfn, service_id_t service_id)
    633655{
    634656        int rc = mfs_node_get(rfn, service_id, MFS_ROOT_INO);
     
    636658}
    637659
    638 static int mfs_link(fs_node_t *pfn, fs_node_t *cfn, const char *name)
     660static int
     661mfs_link(fs_node_t *pfn, fs_node_t *cfn, const char *name)
    639662{
    640663        struct mfs_node *parent = pfn->data;
    641664        struct mfs_node *child = cfn->data;
    642665        struct mfs_sb_info *sbi = parent->instance->sbi;
     666        bool destroy_dentry = false;
    643667
    644668        mfsdebug("%s()\n", __FUNCTION__);
     
    649673        int r = mfs_insert_dentry(parent, name, child->ino_i->index);
    650674        if (r != EOK)
    651                 goto exit_error;
     675                return r;
    652676
    653677        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                }
    654684                r = mfs_insert_dentry(child, ".", child->ino_i->index);
    655                 if (r != EOK)
    656                         goto exit_error;
     685                if (r != EOK) {
     686                        destroy_dentry = true;
     687                        goto exit;
     688                }
    657689
    658690                r = mfs_insert_dentry(child, "..", parent->ino_i->index);
    659                 if (r != EOK)
    660                         goto exit_error;
     691                if (r != EOK) {
     692                        destroy_dentry = true;
     693                        goto exit;
     694                }
    661695
    662696                parent->ino_i->i_nlinks++;
     
    664698        }
    665699
    666 exit_error:
     700exit:
     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        }
    667709        return r;
    668710}
     
    711753}
    712754
    713 static int mfs_has_children(bool *has_children, fs_node_t *fsnode)
     755static int
     756mfs_has_children(bool *has_children, fs_node_t *fsnode)
    714757{
    715758        struct mfs_node *mnode = fsnode->data;
     
    732775
    733776                if (d_info.d_inum) {
    734                         /*A valid entry has been found*/
     777                        /* A valid entry has been found */
    735778                        *has_children = true;
    736779                        break;
     
    744787static int
    745788mfs_read(service_id_t service_id, fs_index_t index, aoff64_t pos,
    746                 size_t *rbytes)
     789    size_t *rbytes)
    747790{
    748791        int rc;
     
    774817
    775818                if (pos < 2) {
    776                         /*Skip the first two dentries ('.' and '..')*/
     819                        /* Skip the first two dentries ('.' and '..') */
    777820                        pos = 2;
    778821                }
     
    784827
    785828                        if (d_info.d_inum) {
    786                                 /*Dentry found!*/
     829                                /* Dentry found! */
    787830                                goto found;
    788831                        }
     
    794837found:
    795838                async_data_read_finalize(callid, d_info.d_name,
    796                                         str_size(d_info.d_name) + 1);
     839                    str_size(d_info.d_name) + 1);
    797840                bytes = ((pos - spos) + 1);
    798841        } else {
     
    800843
    801844                if (pos >= (size_t) ino_i->i_size) {
    802                         /*Trying to read beyond the end of file*/
     845                        /* Trying to read beyond the end of file */
    803846                        bytes = 0;
    804847                        (void) async_data_read_finalize(callid, NULL, 0);
     
    817860
    818861                if (zone == 0) {
    819                         /*sparse file*/
     862                        /* sparse file */
    820863                        uint8_t *buf = malloc(sbi->block_size);
    821864                        if (!buf) {
     
    825868                        memset(buf, 0, sizeof(sbi->block_size));
    826869                        async_data_read_finalize(callid,
    827                                                 buf + pos % sbi->block_size, bytes);
     870                            buf + pos % sbi->block_size, bytes);
    828871                        free(buf);
    829872                        goto out_success;
     
    835878
    836879                async_data_read_finalize(callid, b->data +
    837                                         pos % sbi->block_size, bytes);
     880                    pos % sbi->block_size, bytes);
    838881
    839882                rc = block_put(b);
     
    856899static int
    857900mfs_write(service_id_t service_id, fs_index_t index, aoff64_t pos,
    858                 size_t *wbytes, aoff64_t *nsize)
     901    size_t *wbytes, aoff64_t *nsize)
    859902{
    860903        fs_node_t *fn;
     
    880923        struct mfs_ino_info *ino_i = mnode->ino_i;
    881924        const size_t bs = sbi->block_size;
    882         size_t bytes = min(len, bs - pos % bs);
    883         size_t boundary = ROUND_UP(ino_i->i_size, bs);
     925        size_t bytes = min(len, bs - (pos % bs));
    884926        uint32_t block;
    885927
     
    887929                flags = BLOCK_FLAGS_NOREAD;
    888930
    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 {
     931        r = mfs_read_map(&block, mnode, pos);
     932        if (r != EOK)
     933                goto out_err;
     934
     935        if (block == 0) {
    902936                uint32_t dummy;
    903937
     
    905939                if (r != EOK)
    906940                        goto out_err;
    907 
     941               
    908942                r = mfs_write_map(mnode, pos, block, &dummy);
    909943                if (r != EOK)
    910944                        goto out_err;
     945
     946                flags = BLOCK_FLAGS_NOREAD;
    911947        }
    912948
     
    916952                goto out_err;
    917953
    918         async_data_write_finalize(callid, b->data + pos % bs, bytes);
     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);
    919958        b->dirty = true;
    920959
     
    925964        }
    926965
    927         ino_i->i_size = pos + bytes;
    928         ino_i->dirty = true;
     966        if (pos + bytes > ino_i->i_size) {
     967                ino_i->i_size = pos + bytes;
     968                ino_i->dirty = true;
     969        }
    929970        r = mfs_node_put(fn);
    930         *nsize = pos + bytes;
     971        *nsize = ino_i->i_size;
    931972        *wbytes = bytes;
    932973        return r;
     
    950991                return ENOENT;
    951992
    952         /*Destroy the inode*/
     993        /* Destroy the inode */
    953994        return mfs_destroy_node(fn);
    954995}
     
    9691010        assert(!has_children);
    9701011
    971         /*Free the entire inode content*/
     1012        /* Free the entire inode content */
    9721013        r = mfs_inode_shrink(mnode, mnode->ino_i->i_size);
    9731014        if (r != EOK)
    9741015                goto out;
    9751016
    976         /*Mark the inode as free in the bitmap*/
     1017        /* Mark the inode as free in the bitmap */
    9771018        r = mfs_free_inode(mnode->instance, mnode->ino_i->index);
    9781019
     
    10131054
    10141055        rc = fs_instance_get(service_id, &data);
    1015         if (rc == EOK) {
     1056        if (rc == EOK)
    10161057                *instance = (struct mfs_instance *) data;
    1017         } else {
     1058        else {
    10181059                mfsdebug("instance not found\n");
    10191060        }
     
    10221063}
    10231064
    1024 static bool check_magic_number(uint16_t magic, bool *native,
    1025                                mfs_version_t *version, bool *longfilenames)
     1065static bool
     1066check_magic_number(uint16_t magic, bool *native,
     1067                mfs_version_t *version, bool *longfilenames)
    10261068{
    10271069        bool rc = true;
     
    10511093}
    10521094
     1095/** Filesystem sanity check
     1096 *
     1097 * @param Pointer to the MFS superblock.
     1098 *
     1099 * @return EOK on success, ENOTSUP otherwise.
     1100 */
     1101static int
     1102mfs_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
    10531118static int
    10541119mfs_close(service_id_t service_id, fs_index_t index)
     
    10711136
    10721137        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 */
     1146static bool
     1147is_power_of_two(uint32_t n)
     1148{
     1149        if (n == 0)
     1150                return false;
     1151
     1152        return (n & (n - 1)) == 0;
    10731153}
    10741154
Note: See TracChangeset for help on using the changeset viewer.