Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/ext4/src/ops.c

    r5e801dc r922427a8  
    6464static bool ext4_is_dots(const uint8_t *, size_t);
    6565static errno_t ext4_instance_get(service_id_t, ext4_instance_t **);
     66static errno_t handle_sparse_or_unallocated_fblock(ext4_filesystem_t *,
     67    ext4_inode_ref_t *, uint32_t, uint32_t, uint32_t *, int *, bool *);
    6668
    6769/* Forward declarations of ext4 libfs operations. */
     
    113115}
    114116
    115 static bool open_nodes_key_equal(const void *key_arg, const ht_link_t *item)
     117static bool open_nodes_key_equal(const void *key_arg, size_t hash, const ht_link_t *item)
    116118{
    117119        const node_key_t *key = key_arg;
     
    122124}
    123125
    124 static hash_table_ops_t open_nodes_ops = {
     126static const hash_table_ops_t open_nodes_ops = {
    125127        .hash = open_nodes_hash,
    126128        .key_hash = open_nodes_key_hash,
     
    158160}
    159161
    160 /*
    161  * Ext4 libfs operations.
    162  */
    163 
    164162/** Get instance from internal table by service_id.
    165163 *
     
    170168 *
    171169 */
    172 errno_t ext4_instance_get(service_id_t service_id, ext4_instance_t **inst)
     170static errno_t ext4_instance_get(service_id_t service_id, ext4_instance_t **inst)
    173171{
    174172        fibril_mutex_lock(&instance_list_mutex);
     
    190188        return EINVAL;
    191189}
     190
     191/*
     192 * Ext4 libfs operations.
     193 */
    192194
    193195/** Get root node of filesystem specified by service_id.
     
    810812}
    811813
    812 /** Extract device identifier from node.
     814/** Get service ID for a service-special file.
    813815 *
    814816 * @param node Node to extract id from
    815817 *
    816  * @return id of device, where is the filesystem
     818 * @return Service ID for a service-special file, zero for a regular file.
    817819 *
    818820 */
    819821service_id_t ext4_service_get(fs_node_t *fn)
    820822{
    821         ext4_node_t *enode = EXT4_NODE(fn);
    822         return enode->instance->service_id;
     823        return 0;
    823824}
    824825
     
    12851286    size_t *wbytes, aoff64_t *nsize)
    12861287{
    1287         fs_node_t *fn;
     1288        fs_node_t *fn = NULL;
    12881289        errno_t rc2;
     1290        bool fblock_allocated = false;
     1291        ext4_inode_ref_t *inode_ref = NULL;
     1292
    12891293        errno_t rc = ext4_node_get(&fn, service_id, index);
    12901294        if (rc != EOK)
     
    13151319
    13161320        /* Load inode */
    1317         ext4_inode_ref_t *inode_ref = enode->inode_ref;
     1321        inode_ref = enode->inode_ref;
    13181322        rc = ext4_filesystem_get_inode_data_block_index(inode_ref, iblock,
    13191323            &fblock);
     
    13231327        }
    13241328
    1325         /* Check for sparse file */
     1329        /* Handle sparse or unallocated block */
    13261330        if (fblock == 0) {
    1327                 if ((ext4_superblock_has_feature_incompatible(fs->superblock,
    1328                     EXT4_FEATURE_INCOMPAT_EXTENTS)) &&
    1329                     (ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS))) {
    1330                         uint32_t last_iblock =
    1331                             ext4_inode_get_size(fs->superblock, inode_ref->inode) /
    1332                             block_size;
    1333 
    1334                         while (last_iblock < iblock) {
    1335                                 rc = ext4_extent_append_block(inode_ref, &last_iblock,
    1336                                     &fblock, true);
    1337                                 if (rc != EOK) {
    1338                                         async_answer_0(&call, rc);
    1339                                         goto exit;
    1340                                 }
    1341                         }
    1342 
    1343                         rc = ext4_extent_append_block(inode_ref, &last_iblock,
    1344                             &fblock, false);
    1345                         if (rc != EOK) {
    1346                                 async_answer_0(&call, rc);
    1347                                 goto exit;
    1348                         }
    1349                 } else {
    1350                         rc = ext4_balloc_alloc_block(inode_ref, &fblock);
    1351                         if (rc != EOK) {
    1352                                 async_answer_0(&call, rc);
    1353                                 goto exit;
    1354                         }
    1355 
    1356                         rc = ext4_filesystem_set_inode_data_block_index(inode_ref,
    1357                             iblock, fblock);
    1358                         if (rc != EOK) {
    1359                                 ext4_balloc_free_block(inode_ref, fblock);
    1360                                 async_answer_0(&call, rc);
    1361                                 goto exit;
    1362                         }
     1331                rc = handle_sparse_or_unallocated_fblock(fs, inode_ref,
     1332                    block_size, iblock, &fblock, &flags, &fblock_allocated);
     1333                if (rc != EOK) {
     1334                        async_answer_0(&call, rc);
     1335                        goto exit;
    13631336                }
    1364 
    1365                 flags = BLOCK_FLAGS_NOREAD;
    1366                 inode_ref->dirty = true;
    13671337        }
    13681338
     
    14031373
    14041374exit:
     1375        if (rc != EOK && fblock_allocated)
     1376                ext4_balloc_free_block(inode_ref, fblock);
     1377
    14051378        rc2 = ext4_node_put(fn);
    14061379        return rc == EOK ? rc2 : rc;
     1380}
     1381
     1382/** Handle sparse or unallocated block.
     1383 *
     1384 * @param fs            Filesystem handle
     1385 * @param inode_ref     I-node reference
     1386 * @param block_size    Filesystem block size
     1387 * @param iblock        Logical block
     1388 * @param fblock        Place to store allocated block address
     1389 * @param flags         BLOCK_FLAGS to update
     1390 * @param allocated     Place to store whether new block was allocated
     1391 *
     1392 * @return Error code
     1393 *
     1394 */
     1395static errno_t handle_sparse_or_unallocated_fblock(ext4_filesystem_t *fs,
     1396    ext4_inode_ref_t *inode_ref, uint32_t block_size, uint32_t iblock,
     1397    uint32_t *fblock, int *flags, bool *allocated)
     1398{
     1399        errno_t rc;
     1400
     1401        /* Check for sparse file */
     1402        if ((ext4_superblock_has_feature_incompatible(fs->superblock,
     1403            EXT4_FEATURE_INCOMPAT_EXTENTS)) &&
     1404            (ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS))) {
     1405                uint32_t last_iblock =
     1406                    ext4_inode_get_size(fs->superblock, inode_ref->inode) /
     1407                    block_size;
     1408
     1409                while (last_iblock < iblock) {
     1410                        rc = ext4_extent_append_block(inode_ref, &last_iblock,
     1411                            fblock, true);
     1412                        if (rc != EOK)
     1413                                return rc;
     1414                }
     1415
     1416                rc = ext4_extent_append_block(inode_ref, &last_iblock, fblock,
     1417                    false);
     1418                if (rc != EOK)
     1419                        return rc;
     1420
     1421                *allocated = false;
     1422        } else { /* Allocate new block */
     1423                rc = ext4_balloc_alloc_block(inode_ref, fblock);
     1424                if (rc != EOK)
     1425                        return rc;
     1426
     1427                rc = ext4_filesystem_set_inode_data_block_index(inode_ref,
     1428                    iblock, *fblock);
     1429                if (rc != EOK) {
     1430                        ext4_balloc_free_block(inode_ref, *fblock);
     1431                        return rc;
     1432                }
     1433
     1434                *allocated = true;
     1435        }
     1436
     1437        *flags = BLOCK_FLAGS_NOREAD;
     1438        inode_ref->dirty = true;
     1439
     1440        return EOK;
    14071441}
    14081442
Note: See TracChangeset for help on using the changeset viewer.