Skip to content

Commit 3f2571c

Browse files
jankaratytso
authored andcommitted
ext4: factor out xattr moving
Factor out function for moving xattrs from inode into external xattr block from ext4_expand_extra_isize_ea(). That function is already quite long and factoring out this rather standalone functionality helps readability. Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
1 parent 9440571 commit 3f2571c

File tree

1 file changed

+85
-74
lines changed

1 file changed

+85
-74
lines changed

fs/ext4/xattr.c

Lines changed: 85 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1339,6 +1339,84 @@ static void ext4_xattr_shift_entries(struct ext4_xattr_entry *entry,
13391339
memmove(to, from, n);
13401340
}
13411341

1342+
/*
1343+
* Move xattr pointed to by 'entry' from inode into external xattr block
1344+
*/
1345+
static int ext4_xattr_move_to_block(handle_t *handle, struct inode *inode,
1346+
struct ext4_inode *raw_inode,
1347+
struct ext4_xattr_entry *entry)
1348+
{
1349+
struct ext4_xattr_ibody_find *is = NULL;
1350+
struct ext4_xattr_block_find *bs = NULL;
1351+
char *buffer = NULL, *b_entry_name = NULL;
1352+
size_t value_offs, value_size;
1353+
struct ext4_xattr_info i = {
1354+
.value = NULL,
1355+
.value_len = 0,
1356+
.name_index = entry->e_name_index,
1357+
};
1358+
struct ext4_xattr_ibody_header *header = IHDR(inode, raw_inode);
1359+
int error;
1360+
1361+
value_offs = le16_to_cpu(entry->e_value_offs);
1362+
value_size = le32_to_cpu(entry->e_value_size);
1363+
1364+
is = kzalloc(sizeof(struct ext4_xattr_ibody_find), GFP_NOFS);
1365+
bs = kzalloc(sizeof(struct ext4_xattr_block_find), GFP_NOFS);
1366+
buffer = kmalloc(value_size, GFP_NOFS);
1367+
b_entry_name = kmalloc(entry->e_name_len + 1, GFP_NOFS);
1368+
if (!is || !bs || !buffer || !b_entry_name) {
1369+
error = -ENOMEM;
1370+
goto out;
1371+
}
1372+
1373+
is->s.not_found = -ENODATA;
1374+
bs->s.not_found = -ENODATA;
1375+
is->iloc.bh = NULL;
1376+
bs->bh = NULL;
1377+
1378+
/* Save the entry name and the entry value */
1379+
memcpy(buffer, (void *)IFIRST(header) + value_offs, value_size);
1380+
memcpy(b_entry_name, entry->e_name, entry->e_name_len);
1381+
b_entry_name[entry->e_name_len] = '\0';
1382+
i.name = b_entry_name;
1383+
1384+
error = ext4_get_inode_loc(inode, &is->iloc);
1385+
if (error)
1386+
goto out;
1387+
1388+
error = ext4_xattr_ibody_find(inode, &i, is);
1389+
if (error)
1390+
goto out;
1391+
1392+
/* Remove the chosen entry from the inode */
1393+
error = ext4_xattr_ibody_set(handle, inode, &i, is);
1394+
if (error)
1395+
goto out;
1396+
1397+
i.name = b_entry_name;
1398+
i.value = buffer;
1399+
i.value_len = value_size;
1400+
error = ext4_xattr_block_find(inode, &i, bs);
1401+
if (error)
1402+
goto out;
1403+
1404+
/* Add entry which was removed from the inode into the block */
1405+
error = ext4_xattr_block_set(handle, inode, &i, bs);
1406+
if (error)
1407+
goto out;
1408+
error = 0;
1409+
out:
1410+
kfree(b_entry_name);
1411+
kfree(buffer);
1412+
if (is)
1413+
brelse(is->iloc.bh);
1414+
kfree(is);
1415+
kfree(bs);
1416+
1417+
return error;
1418+
}
1419+
13421420
/*
13431421
* Expand an inode by new_extra_isize bytes when EAs are present.
13441422
* Returns 0 on success or negative error number on failure.
@@ -1349,9 +1427,6 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
13491427
struct ext4_xattr_ibody_header *header;
13501428
struct ext4_xattr_entry *entry, *last, *first;
13511429
struct buffer_head *bh = NULL;
1352-
struct ext4_xattr_ibody_find *is = NULL;
1353-
struct ext4_xattr_block_find *bs = NULL;
1354-
char *buffer = NULL, *b_entry_name = NULL;
13551430
size_t min_offs;
13561431
size_t ifree, bfree;
13571432
int total_ino;
@@ -1427,27 +1502,11 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
14271502
}
14281503

14291504
while (isize_diff > ifree) {
1430-
size_t offs, size, entry_size;
14311505
struct ext4_xattr_entry *small_entry = NULL;
1432-
struct ext4_xattr_info i = {
1433-
.value = NULL,
1434-
.value_len = 0,
1435-
};
1436-
unsigned int total_size; /* EA entry size + value size */
1506+
unsigned int entry_size; /* EA entry size */
1507+
unsigned int total_size; /* EA entry size + value size */
14371508
unsigned int min_total_size = ~0U;
14381509

1439-
is = kzalloc(sizeof(struct ext4_xattr_ibody_find), GFP_NOFS);
1440-
bs = kzalloc(sizeof(struct ext4_xattr_block_find), GFP_NOFS);
1441-
if (!is || !bs) {
1442-
error = -ENOMEM;
1443-
goto cleanup;
1444-
}
1445-
1446-
is->s.not_found = -ENODATA;
1447-
bs->s.not_found = -ENODATA;
1448-
is->iloc.bh = NULL;
1449-
bs->bh = NULL;
1450-
14511510
last = IFIRST(header);
14521511
/* Find the entry best suited to be pushed into EA block */
14531512
entry = NULL;
@@ -1474,67 +1533,25 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
14741533
s_min_extra_isize) {
14751534
tried_min_extra_isize++;
14761535
new_extra_isize = s_min_extra_isize;
1477-
kfree(is); is = NULL;
1478-
kfree(bs); bs = NULL;
14791536
brelse(bh);
14801537
goto retry;
14811538
}
14821539
error = -1;
14831540
goto cleanup;
14841541
}
14851542
}
1486-
offs = le16_to_cpu(entry->e_value_offs);
1487-
size = le32_to_cpu(entry->e_value_size);
1488-
entry_size = EXT4_XATTR_LEN(entry->e_name_len);
1489-
total_size = entry_size + EXT4_XATTR_SIZE(size);
1490-
i.name_index = entry->e_name_index,
1491-
buffer = kmalloc(EXT4_XATTR_SIZE(size), GFP_NOFS);
1492-
b_entry_name = kmalloc(entry->e_name_len + 1, GFP_NOFS);
1493-
if (!buffer || !b_entry_name) {
1494-
error = -ENOMEM;
1495-
goto cleanup;
1496-
}
1497-
/* Save the entry name and the entry value */
1498-
memcpy(buffer, (void *)IFIRST(header) + offs,
1499-
EXT4_XATTR_SIZE(size));
1500-
memcpy(b_entry_name, entry->e_name, entry->e_name_len);
1501-
b_entry_name[entry->e_name_len] = '\0';
1502-
i.name = b_entry_name;
1503-
1504-
error = ext4_get_inode_loc(inode, &is->iloc);
1505-
if (error)
1506-
goto cleanup;
15071543

1508-
error = ext4_xattr_ibody_find(inode, &i, is);
1544+
entry_size = EXT4_XATTR_LEN(entry->e_name_len);
1545+
total_size = entry_size +
1546+
EXT4_XATTR_SIZE(le32_to_cpu(entry->e_value_size));
1547+
error = ext4_xattr_move_to_block(handle, inode, raw_inode,
1548+
entry);
15091549
if (error)
15101550
goto cleanup;
15111551

1512-
/* Remove the chosen entry from the inode */
1513-
error = ext4_xattr_ibody_set(handle, inode, &i, is);
1514-
if (error)
1515-
goto cleanup;
15161552
total_ino -= entry_size;
15171553
ifree += total_size;
15181554
bfree -= total_size;
1519-
1520-
i.name = b_entry_name;
1521-
i.value = buffer;
1522-
i.value_len = size;
1523-
error = ext4_xattr_block_find(inode, &i, bs);
1524-
if (error)
1525-
goto cleanup;
1526-
1527-
/* Add entry which was removed from the inode into the block */
1528-
error = ext4_xattr_block_set(handle, inode, &i, bs);
1529-
if (error)
1530-
goto cleanup;
1531-
kfree(b_entry_name);
1532-
kfree(buffer);
1533-
b_entry_name = NULL;
1534-
buffer = NULL;
1535-
brelse(is->iloc.bh);
1536-
kfree(is);
1537-
kfree(bs);
15381555
}
15391556

15401557
shift:
@@ -1552,12 +1569,6 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
15521569
return 0;
15531570

15541571
cleanup:
1555-
kfree(b_entry_name);
1556-
kfree(buffer);
1557-
if (is)
1558-
brelse(is->iloc.bh);
1559-
kfree(is);
1560-
kfree(bs);
15611572
brelse(bh);
15621573
/*
15631574
* We deliberately leave EXT4_STATE_NO_EXPAND set here since inode

0 commit comments

Comments
 (0)