Skip to content

Commit f62c901

Browse files
committed
ext4: write: sparse/unallocated block helper fcn
1 parent 61f28c4 commit f62c901

File tree

1 file changed

+69
-45
lines changed

1 file changed

+69
-45
lines changed

uspace/lib/ext4/src/ops.c

Lines changed: 69 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -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 *);
6464
static bool ext4_is_dots(const uint8_t *, size_t);
6565
static 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

Comments
 (0)