diff options
Diffstat (limited to 'fs/ext4/inline.c')
-rw-r--r-- | fs/ext4/inline.c | 48 |
1 files changed, 43 insertions, 5 deletions
diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c index bf5f77803885..cec651e2646c 100644 --- a/fs/ext4/inline.c +++ b/fs/ext4/inline.c | |||
@@ -207,8 +207,8 @@ out: | |||
207 | /* | 207 | /* |
208 | * write the buffer to the inline inode. | 208 | * write the buffer to the inline inode. |
209 | * If 'create' is set, we don't need to do the extra copy in the xattr | 209 | * If 'create' is set, we don't need to do the extra copy in the xattr |
210 | * value since it is already handled by ext4_xattr_ibody_set. That saves | 210 | * value since it is already handled by ext4_xattr_ibody_inline_set. |
211 | * us one memcpy. | 211 | * That saves us one memcpy. |
212 | */ | 212 | */ |
213 | void ext4_write_inline_data(struct inode *inode, struct ext4_iloc *iloc, | 213 | void ext4_write_inline_data(struct inode *inode, struct ext4_iloc *iloc, |
214 | void *buffer, loff_t pos, unsigned int len) | 214 | void *buffer, loff_t pos, unsigned int len) |
@@ -285,7 +285,7 @@ static int ext4_create_inline_data(handle_t *handle, | |||
285 | 285 | ||
286 | BUG_ON(!is.s.not_found); | 286 | BUG_ON(!is.s.not_found); |
287 | 287 | ||
288 | error = ext4_xattr_ibody_set(handle, inode, &i, &is); | 288 | error = ext4_xattr_ibody_inline_set(handle, inode, &i, &is); |
289 | if (error) { | 289 | if (error) { |
290 | if (error == -ENOSPC) | 290 | if (error == -ENOSPC) |
291 | ext4_clear_inode_state(inode, | 291 | ext4_clear_inode_state(inode, |
@@ -354,7 +354,7 @@ static int ext4_update_inline_data(handle_t *handle, struct inode *inode, | |||
354 | i.value = value; | 354 | i.value = value; |
355 | i.value_len = len; | 355 | i.value_len = len; |
356 | 356 | ||
357 | error = ext4_xattr_ibody_set(handle, inode, &i, &is); | 357 | error = ext4_xattr_ibody_inline_set(handle, inode, &i, &is); |
358 | if (error) | 358 | if (error) |
359 | goto out; | 359 | goto out; |
360 | 360 | ||
@@ -427,7 +427,7 @@ static int ext4_destroy_inline_data_nolock(handle_t *handle, | |||
427 | if (error) | 427 | if (error) |
428 | goto out; | 428 | goto out; |
429 | 429 | ||
430 | error = ext4_xattr_ibody_set(handle, inode, &i, &is); | 430 | error = ext4_xattr_ibody_inline_set(handle, inode, &i, &is); |
431 | if (error) | 431 | if (error) |
432 | goto out; | 432 | goto out; |
433 | 433 | ||
@@ -1715,3 +1715,41 @@ out: | |||
1715 | up_read(&EXT4_I(inode)->xattr_sem); | 1715 | up_read(&EXT4_I(inode)->xattr_sem); |
1716 | return (error < 0 ? error : 0); | 1716 | return (error < 0 ? error : 0); |
1717 | } | 1717 | } |
1718 | |||
1719 | /* | ||
1720 | * Called during xattr set, and if we can sparse space 'needed', | ||
1721 | * just create the extent tree evict the data to the outer block. | ||
1722 | * | ||
1723 | * We use jbd2 instead of page cache to move data to the 1st block | ||
1724 | * so that the whole transaction can be committed as a whole and | ||
1725 | * the data isn't lost because of the delayed page cache write. | ||
1726 | */ | ||
1727 | int ext4_try_to_evict_inline_data(handle_t *handle, | ||
1728 | struct inode *inode, | ||
1729 | int needed) | ||
1730 | { | ||
1731 | int error; | ||
1732 | struct ext4_xattr_entry *entry; | ||
1733 | struct ext4_xattr_ibody_header *header; | ||
1734 | struct ext4_inode *raw_inode; | ||
1735 | struct ext4_iloc iloc; | ||
1736 | |||
1737 | error = ext4_get_inode_loc(inode, &iloc); | ||
1738 | if (error) | ||
1739 | return error; | ||
1740 | |||
1741 | raw_inode = ext4_raw_inode(&iloc); | ||
1742 | header = IHDR(inode, raw_inode); | ||
1743 | entry = (struct ext4_xattr_entry *)((void *)raw_inode + | ||
1744 | EXT4_I(inode)->i_inline_off); | ||
1745 | if (EXT4_XATTR_LEN(entry->e_name_len) + | ||
1746 | EXT4_XATTR_SIZE(le32_to_cpu(entry->e_value_size)) < needed) { | ||
1747 | error = -ENOSPC; | ||
1748 | goto out; | ||
1749 | } | ||
1750 | |||
1751 | error = ext4_convert_inline_data_nolock(handle, inode, &iloc); | ||
1752 | out: | ||
1753 | brelse(iloc.bh); | ||
1754 | return error; | ||
1755 | } | ||