diff options
author | Tao Ma <boyu.mt@taobao.com> | 2012-12-10 14:06:02 -0500 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2012-12-10 14:06:02 -0500 |
commit | aef1c8513c1f8ae076e22ea2a57eff5835578e75 (patch) | |
tree | 0738a2b503b1d7c6a43138bd87095901867e412e /fs/ext4 | |
parent | 0d812f77b36c16dff692390508155de2c7f95ea3 (diff) |
ext4: let ext4_truncate handle inline data correctly
Signed-off-by: Robin Dong <sanbai@taobao.com>
Signed-off-by: Tao Ma <boyu.mt@taobao.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4')
-rw-r--r-- | fs/ext4/inline.c | 90 | ||||
-rw-r--r-- | fs/ext4/inode.c | 8 | ||||
-rw-r--r-- | fs/ext4/xattr.h | 9 |
3 files changed, 107 insertions, 0 deletions
diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c index cec651e2646c..727edb8d57e0 100644 --- a/fs/ext4/inline.c +++ b/fs/ext4/inline.c | |||
@@ -1753,3 +1753,93 @@ out: | |||
1753 | brelse(iloc.bh); | 1753 | brelse(iloc.bh); |
1754 | return error; | 1754 | return error; |
1755 | } | 1755 | } |
1756 | |||
1757 | void ext4_inline_data_truncate(struct inode *inode, int *has_inline) | ||
1758 | { | ||
1759 | handle_t *handle; | ||
1760 | int inline_size, value_len, needed_blocks; | ||
1761 | size_t i_size; | ||
1762 | void *value = NULL; | ||
1763 | struct ext4_xattr_ibody_find is = { | ||
1764 | .s = { .not_found = -ENODATA, }, | ||
1765 | }; | ||
1766 | struct ext4_xattr_info i = { | ||
1767 | .name_index = EXT4_XATTR_INDEX_SYSTEM, | ||
1768 | .name = EXT4_XATTR_SYSTEM_DATA, | ||
1769 | }; | ||
1770 | |||
1771 | |||
1772 | needed_blocks = ext4_writepage_trans_blocks(inode); | ||
1773 | handle = ext4_journal_start(inode, needed_blocks); | ||
1774 | if (IS_ERR(handle)) | ||
1775 | return; | ||
1776 | |||
1777 | down_write(&EXT4_I(inode)->xattr_sem); | ||
1778 | if (!ext4_has_inline_data(inode)) { | ||
1779 | *has_inline = 0; | ||
1780 | ext4_journal_stop(handle); | ||
1781 | return; | ||
1782 | } | ||
1783 | |||
1784 | if (ext4_orphan_add(handle, inode)) | ||
1785 | goto out; | ||
1786 | |||
1787 | if (ext4_get_inode_loc(inode, &is.iloc)) | ||
1788 | goto out; | ||
1789 | |||
1790 | down_write(&EXT4_I(inode)->i_data_sem); | ||
1791 | i_size = inode->i_size; | ||
1792 | inline_size = ext4_get_inline_size(inode); | ||
1793 | EXT4_I(inode)->i_disksize = i_size; | ||
1794 | |||
1795 | if (i_size < inline_size) { | ||
1796 | /* Clear the content in the xattr space. */ | ||
1797 | if (inline_size > EXT4_MIN_INLINE_DATA_SIZE) { | ||
1798 | if (ext4_xattr_ibody_find(inode, &i, &is)) | ||
1799 | goto out_error; | ||
1800 | |||
1801 | BUG_ON(is.s.not_found); | ||
1802 | |||
1803 | value_len = le32_to_cpu(is.s.here->e_value_size); | ||
1804 | value = kmalloc(value_len, GFP_NOFS); | ||
1805 | if (!value) | ||
1806 | goto out_error; | ||
1807 | |||
1808 | if (ext4_xattr_ibody_get(inode, i.name_index, i.name, | ||
1809 | value, value_len)) | ||
1810 | goto out_error; | ||
1811 | |||
1812 | i.value = value; | ||
1813 | i.value_len = i_size > EXT4_MIN_INLINE_DATA_SIZE ? | ||
1814 | i_size - EXT4_MIN_INLINE_DATA_SIZE : 0; | ||
1815 | if (ext4_xattr_ibody_inline_set(handle, inode, &i, &is)) | ||
1816 | goto out_error; | ||
1817 | } | ||
1818 | |||
1819 | /* Clear the content within i_blocks. */ | ||
1820 | if (i_size < EXT4_MIN_INLINE_DATA_SIZE) | ||
1821 | memset(ext4_raw_inode(&is.iloc)->i_block + i_size, 0, | ||
1822 | EXT4_MIN_INLINE_DATA_SIZE - i_size); | ||
1823 | |||
1824 | EXT4_I(inode)->i_inline_size = i_size < | ||
1825 | EXT4_MIN_INLINE_DATA_SIZE ? | ||
1826 | EXT4_MIN_INLINE_DATA_SIZE : i_size; | ||
1827 | } | ||
1828 | |||
1829 | out_error: | ||
1830 | up_write(&EXT4_I(inode)->i_data_sem); | ||
1831 | out: | ||
1832 | brelse(is.iloc.bh); | ||
1833 | up_write(&EXT4_I(inode)->xattr_sem); | ||
1834 | kfree(value); | ||
1835 | if (inode->i_nlink) | ||
1836 | ext4_orphan_del(handle, inode); | ||
1837 | |||
1838 | inode->i_mtime = inode->i_ctime = ext4_current_time(inode); | ||
1839 | ext4_mark_inode_dirty(handle, inode); | ||
1840 | if (IS_SYNC(inode)) | ||
1841 | ext4_handle_sync(handle); | ||
1842 | |||
1843 | ext4_journal_stop(handle); | ||
1844 | return; | ||
1845 | } | ||
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index f16ae02599cd..cb1c1ab2720b 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -3594,6 +3594,14 @@ void ext4_truncate(struct inode *inode) | |||
3594 | if (inode->i_size == 0 && !test_opt(inode->i_sb, NO_AUTO_DA_ALLOC)) | 3594 | if (inode->i_size == 0 && !test_opt(inode->i_sb, NO_AUTO_DA_ALLOC)) |
3595 | ext4_set_inode_state(inode, EXT4_STATE_DA_ALLOC_CLOSE); | 3595 | ext4_set_inode_state(inode, EXT4_STATE_DA_ALLOC_CLOSE); |
3596 | 3596 | ||
3597 | if (ext4_has_inline_data(inode)) { | ||
3598 | int has_inline = 1; | ||
3599 | |||
3600 | ext4_inline_data_truncate(inode, &has_inline); | ||
3601 | if (has_inline) | ||
3602 | return; | ||
3603 | } | ||
3604 | |||
3597 | if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) | 3605 | if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) |
3598 | ext4_ext_truncate(inode); | 3606 | ext4_ext_truncate(inode); |
3599 | else | 3607 | else |
diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h index 1be243aab01b..1a71a97e14ad 100644 --- a/fs/ext4/xattr.h +++ b/fs/ext4/xattr.h | |||
@@ -190,6 +190,8 @@ extern int ext4_inline_data_fiemap(struct inode *inode, | |||
190 | extern int ext4_try_to_evict_inline_data(handle_t *handle, | 190 | extern int ext4_try_to_evict_inline_data(handle_t *handle, |
191 | struct inode *inode, | 191 | struct inode *inode, |
192 | int needed); | 192 | int needed); |
193 | extern void ext4_inline_data_truncate(struct inode *inode, int *has_inline); | ||
194 | |||
193 | # else /* CONFIG_EXT4_FS_XATTR */ | 195 | # else /* CONFIG_EXT4_FS_XATTR */ |
194 | 196 | ||
195 | static inline int | 197 | static inline int |
@@ -411,6 +413,13 @@ static inline int ext4_inline_data_fiemap(struct inode *inode, | |||
411 | { | 413 | { |
412 | return 0; | 414 | return 0; |
413 | } | 415 | } |
416 | |||
417 | static inline void ext4_inline_data_truncate(struct inode *inode, | ||
418 | int *has_inline) | ||
419 | { | ||
420 | return; | ||
421 | } | ||
422 | |||
414 | # endif /* CONFIG_EXT4_FS_XATTR */ | 423 | # endif /* CONFIG_EXT4_FS_XATTR */ |
415 | 424 | ||
416 | #ifdef CONFIG_EXT4_FS_SECURITY | 425 | #ifdef CONFIG_EXT4_FS_SECURITY |