diff options
author | Jan Kara <jack@suse.cz> | 2016-08-29 15:44:11 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2016-08-29 15:44:11 -0400 |
commit | dfa2064b222c901b05c19ec5b7f42a25f7bee0e3 (patch) | |
tree | fe588162ed654fbd32187375771f03e78a50f674 /fs/ext4 | |
parent | 6e0cd088c01023c02b1e887e02c8b6f3f395344f (diff) |
ext4: factor out loop for freeing inode xattr space
Move loop to make enough space in the inode from
ext4_expand_extra_isize_ea() into a separate function to make that
function smaller and better readable and also to avoid delaration of
variables inside a loop block.
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Diffstat (limited to 'fs/ext4')
-rw-r--r-- | fs/ext4/xattr.c | 121 |
1 files changed, 69 insertions, 52 deletions
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index 2ef687620205..c15d63389957 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c | |||
@@ -1417,6 +1417,63 @@ out: | |||
1417 | return error; | 1417 | return error; |
1418 | } | 1418 | } |
1419 | 1419 | ||
1420 | static int ext4_xattr_make_inode_space(handle_t *handle, struct inode *inode, | ||
1421 | struct ext4_inode *raw_inode, | ||
1422 | int isize_diff, size_t ifree, | ||
1423 | size_t bfree, int *total_ino) | ||
1424 | { | ||
1425 | struct ext4_xattr_ibody_header *header = IHDR(inode, raw_inode); | ||
1426 | struct ext4_xattr_entry *small_entry; | ||
1427 | struct ext4_xattr_entry *entry; | ||
1428 | struct ext4_xattr_entry *last; | ||
1429 | unsigned int entry_size; /* EA entry size */ | ||
1430 | unsigned int total_size; /* EA entry size + value size */ | ||
1431 | unsigned int min_total_size; | ||
1432 | int error; | ||
1433 | |||
1434 | while (isize_diff > ifree) { | ||
1435 | entry = NULL; | ||
1436 | small_entry = NULL; | ||
1437 | min_total_size = ~0U; | ||
1438 | last = IFIRST(header); | ||
1439 | /* Find the entry best suited to be pushed into EA block */ | ||
1440 | for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) { | ||
1441 | total_size = | ||
1442 | EXT4_XATTR_SIZE(le32_to_cpu(last->e_value_size)) + | ||
1443 | EXT4_XATTR_LEN(last->e_name_len); | ||
1444 | if (total_size <= bfree && | ||
1445 | total_size < min_total_size) { | ||
1446 | if (total_size + ifree < isize_diff) { | ||
1447 | small_entry = last; | ||
1448 | } else { | ||
1449 | entry = last; | ||
1450 | min_total_size = total_size; | ||
1451 | } | ||
1452 | } | ||
1453 | } | ||
1454 | |||
1455 | if (entry == NULL) { | ||
1456 | if (small_entry == NULL) | ||
1457 | return -ENOSPC; | ||
1458 | entry = small_entry; | ||
1459 | } | ||
1460 | |||
1461 | entry_size = EXT4_XATTR_LEN(entry->e_name_len); | ||
1462 | total_size = entry_size + | ||
1463 | EXT4_XATTR_SIZE(le32_to_cpu(entry->e_value_size)); | ||
1464 | error = ext4_xattr_move_to_block(handle, inode, raw_inode, | ||
1465 | entry); | ||
1466 | if (error) | ||
1467 | return error; | ||
1468 | |||
1469 | *total_ino -= entry_size; | ||
1470 | ifree += total_size; | ||
1471 | bfree -= total_size; | ||
1472 | } | ||
1473 | |||
1474 | return 0; | ||
1475 | } | ||
1476 | |||
1420 | /* | 1477 | /* |
1421 | * Expand an inode by new_extra_isize bytes when EAs are present. | 1478 | * Expand an inode by new_extra_isize bytes when EAs are present. |
1422 | * Returns 0 on success or negative error number on failure. | 1479 | * Returns 0 on success or negative error number on failure. |
@@ -1491,66 +1548,26 @@ retry: | |||
1491 | brelse(bh); | 1548 | brelse(bh); |
1492 | goto retry; | 1549 | goto retry; |
1493 | } | 1550 | } |
1494 | error = -1; | 1551 | error = -ENOSPC; |
1495 | goto cleanup; | 1552 | goto cleanup; |
1496 | } | 1553 | } |
1497 | } else { | 1554 | } else { |
1498 | bfree = inode->i_sb->s_blocksize; | 1555 | bfree = inode->i_sb->s_blocksize; |
1499 | } | 1556 | } |
1500 | 1557 | ||
1501 | while (isize_diff > ifree) { | 1558 | error = ext4_xattr_make_inode_space(handle, inode, raw_inode, |
1502 | struct ext4_xattr_entry *small_entry = NULL, *entry = NULL; | 1559 | isize_diff, ifree, bfree, |
1503 | struct ext4_xattr_entry *last; | 1560 | &total_ino); |
1504 | unsigned int entry_size; /* EA entry size */ | 1561 | if (error) { |
1505 | unsigned int total_size; /* EA entry size + value size */ | 1562 | if (error == -ENOSPC && !tried_min_extra_isize && |
1506 | unsigned int min_total_size = ~0U; | 1563 | s_min_extra_isize) { |
1507 | 1564 | tried_min_extra_isize++; | |
1508 | last = IFIRST(header); | 1565 | new_extra_isize = s_min_extra_isize; |
1509 | /* Find the entry best suited to be pushed into EA block */ | 1566 | brelse(bh); |
1510 | for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) { | 1567 | goto retry; |
1511 | total_size = | ||
1512 | EXT4_XATTR_SIZE(le32_to_cpu(last->e_value_size)) + | ||
1513 | EXT4_XATTR_LEN(last->e_name_len); | ||
1514 | if (total_size <= bfree && | ||
1515 | total_size < min_total_size) { | ||
1516 | if (total_size + ifree < isize_diff) { | ||
1517 | small_entry = last; | ||
1518 | } else { | ||
1519 | entry = last; | ||
1520 | min_total_size = total_size; | ||
1521 | } | ||
1522 | } | ||
1523 | } | ||
1524 | |||
1525 | if (entry == NULL) { | ||
1526 | if (small_entry) { | ||
1527 | entry = small_entry; | ||
1528 | } else { | ||
1529 | if (!tried_min_extra_isize && | ||
1530 | s_min_extra_isize) { | ||
1531 | tried_min_extra_isize++; | ||
1532 | new_extra_isize = s_min_extra_isize; | ||
1533 | brelse(bh); | ||
1534 | goto retry; | ||
1535 | } | ||
1536 | error = -1; | ||
1537 | goto cleanup; | ||
1538 | } | ||
1539 | } | 1568 | } |
1540 | 1569 | goto cleanup; | |
1541 | entry_size = EXT4_XATTR_LEN(entry->e_name_len); | ||
1542 | total_size = entry_size + | ||
1543 | EXT4_XATTR_SIZE(le32_to_cpu(entry->e_value_size)); | ||
1544 | error = ext4_xattr_move_to_block(handle, inode, raw_inode, | ||
1545 | entry); | ||
1546 | if (error) | ||
1547 | goto cleanup; | ||
1548 | |||
1549 | total_ino -= entry_size; | ||
1550 | ifree += total_size; | ||
1551 | bfree -= total_size; | ||
1552 | } | 1570 | } |
1553 | |||
1554 | shift: | 1571 | shift: |
1555 | /* Adjust the offsets and shift the remaining entries ahead */ | 1572 | /* Adjust the offsets and shift the remaining entries ahead */ |
1556 | ext4_xattr_shift_entries(IFIRST(header), EXT4_I(inode)->i_extra_isize | 1573 | ext4_xattr_shift_entries(IFIRST(header), EXT4_I(inode)->i_extra_isize |