@@ -63,6 +63,8 @@ static errno_t ext4_read_file(ipc_call_t *, aoff64_t, size_t, ext4_instance_t *,
6363 ext4_inode_ref_t * , size_t * );
6464static bool ext4_is_dots (const uint8_t * , size_t );
6565static errno_t ext4_instance_get (service_id_t , ext4_instance_t * * );
66+ static errno_t handle_sparse_or_unallocated_fblock (ext4_filesystem_t * ,
67+ ext4_inode_ref_t * , uint32_t , uint32_t , uint32_t * , int * );
6668
6769/* Forward declarations of ext4 libfs operations. */
6870
@@ -157,10 +159,6 @@ errno_t ext4_global_fini(void)
157159 return EOK ;
158160}
159161
160- /*
161- * Ext4 libfs operations.
162- */
163-
164162/** Get instance from internal table by service_id.
165163 *
166164 * @param service_id Device identifier
@@ -169,7 +167,7 @@ errno_t ext4_global_fini(void)
169167 * @return Error code
170168 *
171169 */
172- errno_t ext4_instance_get (service_id_t service_id , ext4_instance_t * * inst )
170+ static errno_t ext4_instance_get (service_id_t service_id , ext4_instance_t * * inst )
173171{
174172 fibril_mutex_lock (& instance_list_mutex );
175173
@@ -190,6 +188,10 @@ errno_t ext4_instance_get(service_id_t service_id, ext4_instance_t **inst)
190188 return EINVAL ;
191189}
192190
191+ /*
192+ * Ext4 libfs operations.
193+ */
194+
193195/** Get root node of filesystem specified by service_id.
194196 *
195197 * @param rfn Output pointer to loaded node
@@ -1321,48 +1323,14 @@ static errno_t ext4_write(service_id_t service_id, fs_index_t index, aoff64_t po
13211323 goto exit ;
13221324 }
13231325
1324- /* Check for sparse file */
1326+ /* Handle sparse or unallocated block */
13251327 if (fblock == 0 ) {
1326- if ((ext4_superblock_has_feature_incompatible (fs -> superblock ,
1327- EXT4_FEATURE_INCOMPAT_EXTENTS )) &&
1328- (ext4_inode_has_flag (inode_ref -> inode , EXT4_INODE_FLAG_EXTENTS ))) {
1329- uint32_t last_iblock =
1330- ext4_inode_get_size (fs -> superblock , inode_ref -> inode ) /
1331- block_size ;
1332-
1333- while (last_iblock < iblock ) {
1334- rc = ext4_extent_append_block (inode_ref , & last_iblock ,
1335- & fblock , true);
1336- if (rc != EOK ) {
1337- async_answer_0 (& call , rc );
1338- goto exit ;
1339- }
1340- }
1341-
1342- rc = ext4_extent_append_block (inode_ref , & last_iblock ,
1343- & fblock , false);
1344- if (rc != EOK ) {
1345- async_answer_0 (& call , rc );
1346- goto exit ;
1347- }
1348- } else {
1349- rc = ext4_balloc_alloc_block (inode_ref , & fblock );
1350- if (rc != EOK ) {
1351- async_answer_0 (& call , rc );
1352- goto exit ;
1353- }
1354-
1355- rc = ext4_filesystem_set_inode_data_block_index (inode_ref ,
1356- iblock , fblock );
1357- if (rc != EOK ) {
1358- ext4_balloc_free_block (inode_ref , fblock );
1359- async_answer_0 (& call , rc );
1360- goto exit ;
1361- }
1328+ rc = handle_sparse_or_unallocated_fblock (fs , inode_ref ,
1329+ block_size , iblock , & fblock , & flags );
1330+ if (rc != EOK ) {
1331+ async_answer_0 (& call , rc );
1332+ goto exit ;
13621333 }
1363-
1364- flags = BLOCK_FLAGS_NOREAD ;
1365- inode_ref -> dirty = true;
13661334 }
13671335
13681336 /* Load target block */
@@ -1405,6 +1373,62 @@ static errno_t ext4_write(service_id_t service_id, fs_index_t index, aoff64_t po
14051373 return rc == EOK ? rc2 : rc ;
14061374}
14071375
1376+ /** Handle sparse or unallocated block.
1377+ *
1378+ * @param fs Filesystem handle
1379+ * @param inode_ref I-node reference
1380+ * @param block_size Filesystem block size
1381+ * @param iblock Logical block
1382+ * @param fblock Place to store allocated block address
1383+ * @param flags BLOCK_FLAGS to update
1384+ *
1385+ * @return Error code
1386+ *
1387+ */
1388+ static errno_t handle_sparse_or_unallocated_fblock (ext4_filesystem_t * fs ,
1389+ ext4_inode_ref_t * inode_ref , uint32_t block_size , uint32_t iblock ,
1390+ uint32_t * fblock , int * flags )
1391+ {
1392+ errno_t rc ;
1393+
1394+ /* Check for sparse file */
1395+ if ((ext4_superblock_has_feature_incompatible (fs -> superblock ,
1396+ EXT4_FEATURE_INCOMPAT_EXTENTS )) &&
1397+ (ext4_inode_has_flag (inode_ref -> inode , EXT4_INODE_FLAG_EXTENTS ))) {
1398+ uint32_t last_iblock =
1399+ ext4_inode_get_size (fs -> superblock , inode_ref -> inode ) /
1400+ block_size ;
1401+
1402+ while (last_iblock < iblock ) {
1403+ rc = ext4_extent_append_block (inode_ref , & last_iblock ,
1404+ fblock , true);
1405+ if (rc != EOK )
1406+ return rc ;
1407+ }
1408+
1409+ rc = ext4_extent_append_block (inode_ref , & last_iblock , fblock ,
1410+ false);
1411+ if (rc != EOK )
1412+ return rc ;
1413+ } else { /* Allocate new block */
1414+ rc = ext4_balloc_alloc_block (inode_ref , fblock );
1415+ if (rc != EOK )
1416+ return rc ;
1417+
1418+ rc = ext4_filesystem_set_inode_data_block_index (inode_ref ,
1419+ iblock , * fblock );
1420+ if (rc != EOK ) {
1421+ ext4_balloc_free_block (inode_ref , * fblock );
1422+ return rc ;
1423+ }
1424+ }
1425+
1426+ * flags = BLOCK_FLAGS_NOREAD ;
1427+ inode_ref -> dirty = true;
1428+
1429+ return EOK ;
1430+ }
1431+
14081432/** Truncate file.
14091433 *
14101434 * Only the direction to shorter file is supported.
0 commit comments