| .. | .. |
|---|
| 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); |
|---|