.. | .. |
---|
33 | 33 | struct ext4_xattr_ibody_header *header; |
---|
34 | 34 | struct ext4_xattr_entry *entry; |
---|
35 | 35 | struct ext4_inode *raw_inode; |
---|
| 36 | + void *end; |
---|
36 | 37 | int free, min_offs; |
---|
| 38 | + |
---|
| 39 | + if (!EXT4_INODE_HAS_XATTR_SPACE(inode)) |
---|
| 40 | + return 0; |
---|
37 | 41 | |
---|
38 | 42 | min_offs = EXT4_SB(inode->i_sb)->s_inode_size - |
---|
39 | 43 | EXT4_GOOD_OLD_INODE_SIZE - |
---|
.. | .. |
---|
53 | 57 | raw_inode = ext4_raw_inode(iloc); |
---|
54 | 58 | header = IHDR(inode, raw_inode); |
---|
55 | 59 | entry = IFIRST(header); |
---|
| 60 | + end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size; |
---|
56 | 61 | |
---|
57 | 62 | /* Compute min_offs. */ |
---|
58 | | - for (; !IS_LAST_ENTRY(entry); entry = EXT4_XATTR_NEXT(entry)) { |
---|
| 63 | + while (!IS_LAST_ENTRY(entry)) { |
---|
| 64 | + void *next = EXT4_XATTR_NEXT(entry); |
---|
| 65 | + |
---|
| 66 | + if (next >= end) { |
---|
| 67 | + EXT4_ERROR_INODE(inode, |
---|
| 68 | + "corrupt xattr in inline inode"); |
---|
| 69 | + return 0; |
---|
| 70 | + } |
---|
59 | 71 | if (!entry->e_value_inum && entry->e_value_size) { |
---|
60 | 72 | size_t offs = le16_to_cpu(entry->e_value_offs); |
---|
61 | 73 | if (offs < min_offs) |
---|
62 | 74 | min_offs = offs; |
---|
63 | 75 | } |
---|
| 76 | + entry = next; |
---|
64 | 77 | } |
---|
65 | 78 | free = min_offs - |
---|
66 | 79 | ((void *)entry - (void *)IFIRST(header)) - sizeof(__u32); |
---|
.. | .. |
---|
99 | 112 | |
---|
100 | 113 | error = ext4_get_inode_loc(inode, &iloc); |
---|
101 | 114 | if (error) { |
---|
102 | | - ext4_error_inode(inode, __func__, __LINE__, 0, |
---|
103 | | - "can't get inode location %lu", |
---|
104 | | - inode->i_ino); |
---|
| 115 | + ext4_error_inode_err(inode, __func__, __LINE__, 0, -error, |
---|
| 116 | + "can't get inode location %lu", |
---|
| 117 | + inode->i_ino); |
---|
105 | 118 | return 0; |
---|
106 | 119 | } |
---|
107 | 120 | |
---|
.. | .. |
---|
155 | 168 | (void *)ext4_raw_inode(&is.iloc)); |
---|
156 | 169 | EXT4_I(inode)->i_inline_size = EXT4_MIN_INLINE_DATA_SIZE + |
---|
157 | 170 | le32_to_cpu(is.s.here->e_value_size); |
---|
158 | | - ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); |
---|
159 | 171 | } |
---|
160 | 172 | out: |
---|
161 | 173 | brelse(is.iloc.bh); |
---|
.. | .. |
---|
205 | 217 | /* |
---|
206 | 218 | * write the buffer to the inline inode. |
---|
207 | 219 | * If 'create' is set, we don't need to do the extra copy in the xattr |
---|
208 | | - * value since it is already handled by ext4_xattr_ibody_inline_set. |
---|
| 220 | + * value since it is already handled by ext4_xattr_ibody_set. |
---|
209 | 221 | * That saves us one memcpy. |
---|
210 | 222 | */ |
---|
211 | 223 | static void ext4_write_inline_data(struct inode *inode, struct ext4_iloc *iloc, |
---|
.. | .. |
---|
277 | 289 | len = 0; |
---|
278 | 290 | } |
---|
279 | 291 | |
---|
280 | | - /* Insert the the xttr entry. */ |
---|
| 292 | + /* Insert the xttr entry. */ |
---|
281 | 293 | i.value = value; |
---|
282 | 294 | i.value_len = len; |
---|
283 | 295 | |
---|
.. | .. |
---|
287 | 299 | |
---|
288 | 300 | BUG_ON(!is.s.not_found); |
---|
289 | 301 | |
---|
290 | | - error = ext4_xattr_ibody_inline_set(handle, inode, &i, &is); |
---|
| 302 | + error = ext4_xattr_ibody_set(handle, inode, &i, &is); |
---|
291 | 303 | if (error) { |
---|
292 | 304 | if (error == -ENOSPC) |
---|
293 | 305 | ext4_clear_inode_state(inode, |
---|
.. | .. |
---|
347 | 359 | |
---|
348 | 360 | error = ext4_xattr_ibody_get(inode, i.name_index, i.name, |
---|
349 | 361 | value, len); |
---|
350 | | - if (error == -ENODATA) |
---|
| 362 | + if (error < 0) |
---|
351 | 363 | goto out; |
---|
352 | 364 | |
---|
353 | 365 | BUFFER_TRACE(is.iloc.bh, "get_write_access"); |
---|
.. | .. |
---|
355 | 367 | if (error) |
---|
356 | 368 | goto out; |
---|
357 | 369 | |
---|
358 | | - /* Update the xttr entry. */ |
---|
| 370 | + /* Update the xattr entry. */ |
---|
359 | 371 | i.value = value; |
---|
360 | 372 | i.value_len = len; |
---|
361 | 373 | |
---|
362 | | - error = ext4_xattr_ibody_inline_set(handle, inode, &i, &is); |
---|
| 374 | + error = ext4_xattr_ibody_set(handle, inode, &i, &is); |
---|
363 | 375 | if (error) |
---|
364 | 376 | goto out; |
---|
365 | 377 | |
---|
.. | .. |
---|
432 | 444 | if (error) |
---|
433 | 445 | goto out; |
---|
434 | 446 | |
---|
435 | | - error = ext4_xattr_ibody_inline_set(handle, inode, &i, &is); |
---|
| 447 | + error = ext4_xattr_ibody_set(handle, inode, &i, &is); |
---|
436 | 448 | if (error) |
---|
437 | 449 | goto out; |
---|
438 | 450 | |
---|
.. | .. |
---|
747 | 759 | void *kaddr; |
---|
748 | 760 | struct ext4_iloc iloc; |
---|
749 | 761 | |
---|
750 | | - if (unlikely(copied < len)) { |
---|
751 | | - if (!PageUptodate(page)) { |
---|
752 | | - copied = 0; |
---|
753 | | - goto out; |
---|
754 | | - } |
---|
755 | | - } |
---|
| 762 | + if (unlikely(copied < len) && !PageUptodate(page)) |
---|
| 763 | + return 0; |
---|
756 | 764 | |
---|
757 | 765 | ret = ext4_get_inode_loc(inode, &iloc); |
---|
758 | 766 | if (ret) { |
---|
759 | 767 | ext4_std_error(inode->i_sb, ret); |
---|
760 | | - copied = 0; |
---|
761 | | - goto out; |
---|
| 768 | + return ret; |
---|
762 | 769 | } |
---|
763 | 770 | |
---|
764 | 771 | ext4_write_lock_xattr(inode, &no_expand); |
---|
.. | .. |
---|
771 | 778 | (void) ext4_find_inline_data_nolock(inode); |
---|
772 | 779 | |
---|
773 | 780 | kaddr = kmap_atomic(page); |
---|
774 | | - ext4_write_inline_data(inode, &iloc, kaddr, pos, len); |
---|
| 781 | + ext4_write_inline_data(inode, &iloc, kaddr, pos, copied); |
---|
775 | 782 | kunmap_atomic(kaddr); |
---|
776 | 783 | SetPageUptodate(page); |
---|
777 | 784 | /* clear page dirty so that writepages wouldn't work for us. */ |
---|
.. | .. |
---|
780 | 787 | ext4_write_unlock_xattr(inode, &no_expand); |
---|
781 | 788 | brelse(iloc.bh); |
---|
782 | 789 | mark_inode_dirty(inode); |
---|
783 | | -out: |
---|
| 790 | + |
---|
784 | 791 | return copied; |
---|
785 | 792 | } |
---|
786 | 793 | |
---|
.. | .. |
---|
815 | 822 | * clear the inode state safely. |
---|
816 | 823 | * 2. The inode has inline data, then we need to read the data, make it |
---|
817 | 824 | * update and dirty so that ext4_da_writepages can handle it. We don't |
---|
818 | | - * need to start the journal since the file's metatdata isn't changed now. |
---|
| 825 | + * need to start the journal since the file's metadata isn't changed now. |
---|
819 | 826 | */ |
---|
820 | 827 | static int ext4_da_convert_inline_data_to_extent(struct address_space *mapping, |
---|
821 | 828 | struct inode *inode, |
---|
.. | .. |
---|
869 | 876 | |
---|
870 | 877 | /* |
---|
871 | 878 | * Prepare the write for the inline data. |
---|
872 | | - * If the the data can be written into the inode, we just read |
---|
| 879 | + * If the data can be written into the inode, we just read |
---|
873 | 880 | * the page and make it uptodate, and start the journal. |
---|
874 | 881 | * Otherwise read the page, makes it dirty so that it can be |
---|
875 | 882 | * handle in writepages(the i_disksize update is left to the |
---|
.. | .. |
---|
1160 | 1167 | { |
---|
1161 | 1168 | int err, csum_size = 0, header_size = 0; |
---|
1162 | 1169 | struct ext4_dir_entry_2 *de; |
---|
1163 | | - struct ext4_dir_entry_tail *t; |
---|
1164 | 1170 | void *target = dir_block->b_data; |
---|
1165 | 1171 | |
---|
1166 | 1172 | /* |
---|
.. | .. |
---|
1186 | 1192 | inline_size - EXT4_INLINE_DOTDOT_SIZE + header_size, |
---|
1187 | 1193 | inode->i_sb->s_blocksize - csum_size); |
---|
1188 | 1194 | |
---|
1189 | | - if (csum_size) { |
---|
1190 | | - t = EXT4_DIRENT_TAIL(dir_block->b_data, |
---|
1191 | | - inode->i_sb->s_blocksize); |
---|
1192 | | - initialize_dirent_tail(t, inode->i_sb->s_blocksize); |
---|
1193 | | - } |
---|
| 1195 | + if (csum_size) |
---|
| 1196 | + ext4_initialize_dirent_tail(dir_block, |
---|
| 1197 | + inode->i_sb->s_blocksize); |
---|
1194 | 1198 | set_buffer_uptodate(dir_block); |
---|
1195 | | - err = ext4_handle_dirty_dirent_node(handle, inode, dir_block); |
---|
| 1199 | + unlock_buffer(dir_block); |
---|
| 1200 | + err = ext4_handle_dirty_dirblock(handle, inode, dir_block); |
---|
1196 | 1201 | if (err) |
---|
1197 | 1202 | return err; |
---|
1198 | 1203 | set_buffer_verified(dir_block); |
---|
.. | .. |
---|
1265 | 1270 | if (!S_ISDIR(inode->i_mode)) { |
---|
1266 | 1271 | memcpy(data_bh->b_data, buf, inline_size); |
---|
1267 | 1272 | set_buffer_uptodate(data_bh); |
---|
| 1273 | + unlock_buffer(data_bh); |
---|
1268 | 1274 | error = ext4_handle_dirty_metadata(handle, |
---|
1269 | 1275 | inode, data_bh); |
---|
1270 | 1276 | } else { |
---|
.. | .. |
---|
1272 | 1278 | buf, inline_size); |
---|
1273 | 1279 | } |
---|
1274 | 1280 | |
---|
1275 | | - unlock_buffer(data_bh); |
---|
1276 | 1281 | out_restore: |
---|
1277 | 1282 | if (error) |
---|
1278 | 1283 | ext4_restore_inline_data(handle, inode, iloc, buf, inline_size); |
---|
.. | .. |
---|
1291 | 1296 | int ext4_try_add_inline_entry(handle_t *handle, struct ext4_filename *fname, |
---|
1292 | 1297 | struct inode *dir, struct inode *inode) |
---|
1293 | 1298 | { |
---|
1294 | | - int ret, inline_size, no_expand; |
---|
| 1299 | + int ret, ret2, inline_size, no_expand; |
---|
1295 | 1300 | void *inline_start; |
---|
1296 | 1301 | struct ext4_iloc iloc; |
---|
1297 | 1302 | |
---|
.. | .. |
---|
1345 | 1350 | |
---|
1346 | 1351 | out: |
---|
1347 | 1352 | ext4_write_unlock_xattr(dir, &no_expand); |
---|
1348 | | - ext4_mark_inode_dirty(handle, dir); |
---|
| 1353 | + ret2 = ext4_mark_inode_dirty(handle, dir); |
---|
| 1354 | + if (unlikely(ret2 && !ret)) |
---|
| 1355 | + ret = ret2; |
---|
1349 | 1356 | brelse(iloc.bh); |
---|
1350 | 1357 | return ret; |
---|
1351 | 1358 | } |
---|
.. | .. |
---|
1355 | 1362 | * inlined dir. It returns the number directory entries loaded |
---|
1356 | 1363 | * into the tree. If there is an error it is returned in err. |
---|
1357 | 1364 | */ |
---|
1358 | | -int htree_inlinedir_to_tree(struct file *dir_file, |
---|
1359 | | - struct inode *dir, ext4_lblk_t block, |
---|
1360 | | - struct dx_hash_info *hinfo, |
---|
1361 | | - __u32 start_hash, __u32 start_minor_hash, |
---|
1362 | | - int *has_inline_data) |
---|
| 1365 | +int ext4_inlinedir_to_tree(struct file *dir_file, |
---|
| 1366 | + struct inode *dir, ext4_lblk_t block, |
---|
| 1367 | + struct dx_hash_info *hinfo, |
---|
| 1368 | + __u32 start_hash, __u32 start_minor_hash, |
---|
| 1369 | + int *has_inline_data) |
---|
1363 | 1370 | { |
---|
1364 | 1371 | int err = 0, count = 0; |
---|
1365 | 1372 | unsigned int parent_ino; |
---|
.. | .. |
---|
1740 | 1747 | if (err) |
---|
1741 | 1748 | goto out; |
---|
1742 | 1749 | |
---|
1743 | | - err = ext4_generic_delete_entry(handle, dir, de_del, 0, bh, |
---|
| 1750 | + err = ext4_generic_delete_entry(dir, de_del, 0, bh, |
---|
1744 | 1751 | inline_start, inline_size, 0); |
---|
1745 | 1752 | if (err) |
---|
1746 | 1753 | goto out; |
---|
.. | .. |
---|
1793 | 1800 | void *inline_pos; |
---|
1794 | 1801 | unsigned int offset; |
---|
1795 | 1802 | struct ext4_dir_entry_2 *de; |
---|
1796 | | - bool ret = true; |
---|
| 1803 | + bool ret = false; |
---|
1797 | 1804 | |
---|
1798 | 1805 | err = ext4_get_inode_loc(dir, &iloc); |
---|
1799 | 1806 | if (err) { |
---|
1800 | | - EXT4_ERROR_INODE(dir, "error %d getting inode %lu block", |
---|
1801 | | - err, dir->i_ino); |
---|
1802 | | - return true; |
---|
| 1807 | + EXT4_ERROR_INODE_ERR(dir, -err, |
---|
| 1808 | + "error %d getting inode %lu block", |
---|
| 1809 | + err, dir->i_ino); |
---|
| 1810 | + return false; |
---|
1803 | 1811 | } |
---|
1804 | 1812 | |
---|
1805 | 1813 | down_read(&EXT4_I(dir)->xattr_sem); |
---|
1806 | 1814 | if (!ext4_has_inline_data(dir)) { |
---|
1807 | 1815 | *has_inline_data = 0; |
---|
| 1816 | + ret = true; |
---|
1808 | 1817 | goto out; |
---|
1809 | 1818 | } |
---|
1810 | 1819 | |
---|
.. | .. |
---|
1813 | 1822 | ext4_warning(dir->i_sb, |
---|
1814 | 1823 | "bad inline directory (dir #%lu) - no `..'", |
---|
1815 | 1824 | dir->i_ino); |
---|
1816 | | - ret = true; |
---|
1817 | 1825 | goto out; |
---|
1818 | 1826 | } |
---|
1819 | 1827 | |
---|
.. | .. |
---|
1832 | 1840 | dir->i_ino, le32_to_cpu(de->inode), |
---|
1833 | 1841 | le16_to_cpu(de->rec_len), de->name_len, |
---|
1834 | 1842 | inline_size); |
---|
1835 | | - ret = true; |
---|
1836 | 1843 | goto out; |
---|
1837 | 1844 | } |
---|
1838 | 1845 | if (le32_to_cpu(de->inode)) { |
---|
1839 | | - ret = false; |
---|
1840 | 1846 | goto out; |
---|
1841 | 1847 | } |
---|
1842 | 1848 | offset += ext4_rec_len_from_disk(de->rec_len, inline_size); |
---|
1843 | 1849 | } |
---|
1844 | 1850 | |
---|
| 1851 | + ret = true; |
---|
1845 | 1852 | out: |
---|
1846 | 1853 | up_read(&EXT4_I(dir)->xattr_sem); |
---|
1847 | 1854 | brelse(iloc.bh); |
---|
.. | .. |
---|
1889 | 1896 | out: |
---|
1890 | 1897 | up_read(&EXT4_I(inode)->xattr_sem); |
---|
1891 | 1898 | return error; |
---|
1892 | | -} |
---|
1893 | | - |
---|
1894 | | -int ext4_inline_data_fiemap(struct inode *inode, |
---|
1895 | | - struct fiemap_extent_info *fieinfo, |
---|
1896 | | - int *has_inline, __u64 start, __u64 len) |
---|
1897 | | -{ |
---|
1898 | | - __u64 physical = 0; |
---|
1899 | | - __u64 inline_len; |
---|
1900 | | - __u32 flags = FIEMAP_EXTENT_DATA_INLINE | FIEMAP_EXTENT_NOT_ALIGNED | |
---|
1901 | | - FIEMAP_EXTENT_LAST; |
---|
1902 | | - int error = 0; |
---|
1903 | | - struct ext4_iloc iloc; |
---|
1904 | | - |
---|
1905 | | - down_read(&EXT4_I(inode)->xattr_sem); |
---|
1906 | | - if (!ext4_has_inline_data(inode)) { |
---|
1907 | | - *has_inline = 0; |
---|
1908 | | - goto out; |
---|
1909 | | - } |
---|
1910 | | - inline_len = min_t(size_t, ext4_get_inline_size(inode), |
---|
1911 | | - i_size_read(inode)); |
---|
1912 | | - if (start >= inline_len) |
---|
1913 | | - goto out; |
---|
1914 | | - if (start + len < inline_len) |
---|
1915 | | - inline_len = start + len; |
---|
1916 | | - inline_len -= start; |
---|
1917 | | - |
---|
1918 | | - error = ext4_get_inode_loc(inode, &iloc); |
---|
1919 | | - if (error) |
---|
1920 | | - goto out; |
---|
1921 | | - |
---|
1922 | | - physical = (__u64)iloc.bh->b_blocknr << inode->i_sb->s_blocksize_bits; |
---|
1923 | | - physical += (char *)ext4_raw_inode(&iloc) - iloc.bh->b_data; |
---|
1924 | | - physical += offsetof(struct ext4_inode, i_block); |
---|
1925 | | - |
---|
1926 | | - brelse(iloc.bh); |
---|
1927 | | -out: |
---|
1928 | | - up_read(&EXT4_I(inode)->xattr_sem); |
---|
1929 | | - if (physical) |
---|
1930 | | - error = fiemap_fill_next_extent(fieinfo, start, physical, |
---|
1931 | | - inline_len, flags); |
---|
1932 | | - return (error < 0 ? error : 0); |
---|
1933 | 1899 | } |
---|
1934 | 1900 | |
---|
1935 | 1901 | int ext4_inline_data_truncate(struct inode *inode, int *has_inline) |
---|
.. | .. |
---|
1994 | 1960 | i.value = value; |
---|
1995 | 1961 | i.value_len = i_size > EXT4_MIN_INLINE_DATA_SIZE ? |
---|
1996 | 1962 | i_size - EXT4_MIN_INLINE_DATA_SIZE : 0; |
---|
1997 | | - err = ext4_xattr_ibody_inline_set(handle, inode, |
---|
1998 | | - &i, &is); |
---|
| 1963 | + err = ext4_xattr_ibody_set(handle, inode, &i, &is); |
---|
1999 | 1964 | if (err) |
---|
2000 | 1965 | goto out_error; |
---|
2001 | 1966 | } |
---|
.. | .. |
---|
2040 | 2005 | if (!ext4_has_inline_data(inode)) { |
---|
2041 | 2006 | ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); |
---|
2042 | 2007 | return 0; |
---|
| 2008 | + } else if (!ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) { |
---|
| 2009 | + /* |
---|
| 2010 | + * Inode has inline data but EXT4_STATE_MAY_INLINE_DATA is |
---|
| 2011 | + * cleared. This means we are in the middle of moving of |
---|
| 2012 | + * inline data to delay allocated block. Just force writeout |
---|
| 2013 | + * here to finish conversion. |
---|
| 2014 | + */ |
---|
| 2015 | + error = filemap_flush(inode->i_mapping); |
---|
| 2016 | + if (error) |
---|
| 2017 | + return error; |
---|
| 2018 | + if (!ext4_has_inline_data(inode)) |
---|
| 2019 | + return 0; |
---|
2043 | 2020 | } |
---|
2044 | 2021 | |
---|
2045 | 2022 | needed_blocks = ext4_writepage_trans_blocks(inode); |
---|