.. | .. |
---|
93 | 93 | #ifdef CONFIG_EXT4_FS_SECURITY |
---|
94 | 94 | [EXT4_XATTR_INDEX_SECURITY] = &ext4_xattr_security_handler, |
---|
95 | 95 | #endif |
---|
| 96 | + [EXT4_XATTR_INDEX_HURD] = &ext4_xattr_hurd_handler, |
---|
96 | 97 | }; |
---|
97 | 98 | |
---|
98 | 99 | const struct xattr_handler *ext4_xattr_handlers[] = { |
---|
.. | .. |
---|
105 | 106 | #ifdef CONFIG_EXT4_FS_SECURITY |
---|
106 | 107 | &ext4_xattr_security_handler, |
---|
107 | 108 | #endif |
---|
| 109 | + &ext4_xattr_hurd_handler, |
---|
108 | 110 | NULL |
---|
109 | 111 | }; |
---|
110 | 112 | |
---|
.. | .. |
---|
245 | 247 | bh->b_data); |
---|
246 | 248 | errout: |
---|
247 | 249 | if (error) |
---|
248 | | - __ext4_error_inode(inode, function, line, 0, |
---|
| 250 | + __ext4_error_inode(inode, function, line, 0, -error, |
---|
249 | 251 | "corrupted xattr block %llu", |
---|
250 | 252 | (unsigned long long) bh->b_blocknr); |
---|
251 | 253 | else |
---|
.. | .. |
---|
269 | 271 | error = ext4_xattr_check_entries(IFIRST(header), end, IFIRST(header)); |
---|
270 | 272 | errout: |
---|
271 | 273 | if (error) |
---|
272 | | - __ext4_error_inode(inode, function, line, 0, |
---|
| 274 | + __ext4_error_inode(inode, function, line, 0, -error, |
---|
273 | 275 | "corrupted in-inode xattr"); |
---|
274 | 276 | return error; |
---|
275 | 277 | } |
---|
.. | .. |
---|
967 | 969 | return credits; |
---|
968 | 970 | } |
---|
969 | 971 | |
---|
970 | | -static int ext4_xattr_ensure_credits(handle_t *handle, struct inode *inode, |
---|
971 | | - int credits, struct buffer_head *bh, |
---|
972 | | - bool dirty, bool block_csum) |
---|
973 | | -{ |
---|
974 | | - int error; |
---|
975 | | - |
---|
976 | | - if (!ext4_handle_valid(handle)) |
---|
977 | | - return 0; |
---|
978 | | - |
---|
979 | | - if (handle->h_buffer_credits >= credits) |
---|
980 | | - return 0; |
---|
981 | | - |
---|
982 | | - error = ext4_journal_extend(handle, credits - handle->h_buffer_credits); |
---|
983 | | - if (!error) |
---|
984 | | - return 0; |
---|
985 | | - if (error < 0) { |
---|
986 | | - ext4_warning(inode->i_sb, "Extend journal (error %d)", error); |
---|
987 | | - return error; |
---|
988 | | - } |
---|
989 | | - |
---|
990 | | - if (bh && dirty) { |
---|
991 | | - if (block_csum) |
---|
992 | | - ext4_xattr_block_csum_set(inode, bh); |
---|
993 | | - error = ext4_handle_dirty_metadata(handle, NULL, bh); |
---|
994 | | - if (error) { |
---|
995 | | - ext4_warning(inode->i_sb, "Handle metadata (error %d)", |
---|
996 | | - error); |
---|
997 | | - return error; |
---|
998 | | - } |
---|
999 | | - } |
---|
1000 | | - |
---|
1001 | | - error = ext4_journal_restart(handle, credits); |
---|
1002 | | - if (error) { |
---|
1003 | | - ext4_warning(inode->i_sb, "Restart journal (error %d)", error); |
---|
1004 | | - return error; |
---|
1005 | | - } |
---|
1006 | | - |
---|
1007 | | - if (bh) { |
---|
1008 | | - error = ext4_journal_get_write_access(handle, bh); |
---|
1009 | | - if (error) { |
---|
1010 | | - ext4_warning(inode->i_sb, |
---|
1011 | | - "Get write access failed (error %d)", |
---|
1012 | | - error); |
---|
1013 | | - return error; |
---|
1014 | | - } |
---|
1015 | | - } |
---|
1016 | | - return 0; |
---|
1017 | | -} |
---|
1018 | | - |
---|
1019 | 972 | static int ext4_xattr_inode_update_ref(handle_t *handle, struct inode *ea_inode, |
---|
1020 | 973 | int ref_change) |
---|
1021 | 974 | { |
---|
.. | .. |
---|
1028 | 981 | inode_lock(ea_inode); |
---|
1029 | 982 | |
---|
1030 | 983 | ret = ext4_reserve_inode_write(handle, ea_inode, &iloc); |
---|
1031 | | - if (ret) { |
---|
1032 | | - iloc.bh = NULL; |
---|
| 984 | + if (ret) |
---|
1033 | 985 | goto out; |
---|
1034 | | - } |
---|
1035 | 986 | |
---|
1036 | 987 | ref_count = ext4_xattr_inode_get_ref(ea_inode); |
---|
1037 | 988 | ref_count += ref_change; |
---|
.. | .. |
---|
1077 | 1028 | } |
---|
1078 | 1029 | |
---|
1079 | 1030 | ret = ext4_mark_iloc_dirty(handle, ea_inode, &iloc); |
---|
1080 | | - iloc.bh = NULL; |
---|
1081 | 1031 | if (ret) |
---|
1082 | 1032 | ext4_warning_inode(ea_inode, |
---|
1083 | 1033 | "ext4_mark_iloc_dirty() failed ret=%d", ret); |
---|
1084 | 1034 | out: |
---|
1085 | | - brelse(iloc.bh); |
---|
1086 | 1035 | inode_unlock(ea_inode); |
---|
1087 | 1036 | return ret; |
---|
1088 | 1037 | } |
---|
.. | .. |
---|
1153 | 1102 | return saved_err; |
---|
1154 | 1103 | } |
---|
1155 | 1104 | |
---|
| 1105 | +static int ext4_xattr_restart_fn(handle_t *handle, struct inode *inode, |
---|
| 1106 | + struct buffer_head *bh, bool block_csum, bool dirty) |
---|
| 1107 | +{ |
---|
| 1108 | + int error; |
---|
| 1109 | + |
---|
| 1110 | + if (bh && dirty) { |
---|
| 1111 | + if (block_csum) |
---|
| 1112 | + ext4_xattr_block_csum_set(inode, bh); |
---|
| 1113 | + error = ext4_handle_dirty_metadata(handle, NULL, bh); |
---|
| 1114 | + if (error) { |
---|
| 1115 | + ext4_warning(inode->i_sb, "Handle metadata (error %d)", |
---|
| 1116 | + error); |
---|
| 1117 | + return error; |
---|
| 1118 | + } |
---|
| 1119 | + } |
---|
| 1120 | + return 0; |
---|
| 1121 | +} |
---|
| 1122 | + |
---|
1156 | 1123 | static void |
---|
1157 | 1124 | ext4_xattr_inode_dec_ref_all(handle_t *handle, struct inode *parent, |
---|
1158 | 1125 | struct buffer_head *bh, |
---|
.. | .. |
---|
1189 | 1156 | continue; |
---|
1190 | 1157 | } |
---|
1191 | 1158 | |
---|
1192 | | - err = ext4_xattr_ensure_credits(handle, parent, credits, bh, |
---|
1193 | | - dirty, block_csum); |
---|
1194 | | - if (err) { |
---|
| 1159 | + err = ext4_journal_ensure_credits_fn(handle, credits, credits, |
---|
| 1160 | + ext4_free_metadata_revoke_credits(parent->i_sb, 1), |
---|
| 1161 | + ext4_xattr_restart_fn(handle, parent, bh, block_csum, |
---|
| 1162 | + dirty)); |
---|
| 1163 | + if (err < 0) { |
---|
1195 | 1164 | ext4_warning_inode(ea_inode, "Ensure credits err=%d", |
---|
1196 | 1165 | err); |
---|
1197 | 1166 | continue; |
---|
| 1167 | + } |
---|
| 1168 | + if (err > 0) { |
---|
| 1169 | + err = ext4_journal_get_write_access(handle, bh); |
---|
| 1170 | + if (err) { |
---|
| 1171 | + ext4_warning_inode(ea_inode, |
---|
| 1172 | + "Re-get write access err=%d", |
---|
| 1173 | + err); |
---|
| 1174 | + continue; |
---|
| 1175 | + } |
---|
1198 | 1176 | } |
---|
1199 | 1177 | |
---|
1200 | 1178 | err = ext4_xattr_inode_dec_ref(handle, ea_inode); |
---|
.. | .. |
---|
1351 | 1329 | int blocksize = ea_inode->i_sb->s_blocksize; |
---|
1352 | 1330 | int max_blocks = (bufsize + blocksize - 1) >> ea_inode->i_blkbits; |
---|
1353 | 1331 | int csize, wsize = 0; |
---|
1354 | | - int ret = 0; |
---|
| 1332 | + int ret = 0, ret2 = 0; |
---|
1355 | 1333 | int retries = 0; |
---|
1356 | 1334 | |
---|
1357 | 1335 | retry: |
---|
.. | .. |
---|
1378 | 1356 | |
---|
1379 | 1357 | block = 0; |
---|
1380 | 1358 | while (wsize < bufsize) { |
---|
1381 | | - if (bh != NULL) |
---|
1382 | | - brelse(bh); |
---|
| 1359 | + brelse(bh); |
---|
1383 | 1360 | csize = (bufsize - wsize) > blocksize ? blocksize : |
---|
1384 | 1361 | bufsize - wsize; |
---|
1385 | 1362 | bh = ext4_getblk(handle, ea_inode, block, 0); |
---|
.. | .. |
---|
1409 | 1386 | ext4_update_i_disksize(ea_inode, wsize); |
---|
1410 | 1387 | inode_unlock(ea_inode); |
---|
1411 | 1388 | |
---|
1412 | | - ext4_mark_inode_dirty(handle, ea_inode); |
---|
| 1389 | + ret2 = ext4_mark_inode_dirty(handle, ea_inode); |
---|
| 1390 | + if (unlikely(ret2 && !ret)) |
---|
| 1391 | + ret = ret2; |
---|
1413 | 1392 | |
---|
1414 | 1393 | out: |
---|
1415 | 1394 | brelse(bh); |
---|
.. | .. |
---|
1483 | 1462 | WARN_ON_ONCE(ext4_handle_valid(journal_current_handle()) && |
---|
1484 | 1463 | !(current->flags & PF_MEMALLOC_NOFS)); |
---|
1485 | 1464 | |
---|
1486 | | - ea_data = ext4_kvmalloc(value_len, GFP_NOFS); |
---|
| 1465 | + ea_data = kvmalloc(value_len, GFP_KERNEL); |
---|
1487 | 1466 | if (!ea_data) { |
---|
1488 | 1467 | mb_cache_entry_put(ea_inode_cache, ce); |
---|
1489 | 1468 | return NULL; |
---|
.. | .. |
---|
2188 | 2167 | struct ext4_inode *raw_inode; |
---|
2189 | 2168 | int error; |
---|
2190 | 2169 | |
---|
2191 | | - if (EXT4_I(inode)->i_extra_isize == 0) |
---|
| 2170 | + if (!EXT4_INODE_HAS_XATTR_SPACE(inode)) |
---|
2192 | 2171 | return 0; |
---|
| 2172 | + |
---|
2193 | 2173 | raw_inode = ext4_raw_inode(&is->iloc); |
---|
2194 | 2174 | header = IHDR(inode, raw_inode); |
---|
2195 | 2175 | is->s.base = is->s.first = IFIRST(header); |
---|
.. | .. |
---|
2217 | 2197 | struct ext4_xattr_search *s = &is->s; |
---|
2218 | 2198 | int error; |
---|
2219 | 2199 | |
---|
2220 | | - if (EXT4_I(inode)->i_extra_isize == 0) |
---|
| 2200 | + if (!EXT4_INODE_HAS_XATTR_SPACE(inode)) |
---|
2221 | 2201 | return -ENOSPC; |
---|
| 2202 | + |
---|
2222 | 2203 | error = ext4_xattr_set_entry(i, s, handle, inode, false /* is_block */); |
---|
2223 | 2204 | if (error) |
---|
2224 | 2205 | return error; |
---|
.. | .. |
---|
2345 | 2326 | flags & XATTR_CREATE); |
---|
2346 | 2327 | brelse(bh); |
---|
2347 | 2328 | |
---|
2348 | | - if (!ext4_handle_has_enough_credits(handle, credits)) { |
---|
| 2329 | + if (jbd2_handle_buffer_credits(handle) < credits) { |
---|
2349 | 2330 | error = -ENOSPC; |
---|
2350 | 2331 | goto cleanup; |
---|
2351 | 2332 | } |
---|
.. | .. |
---|
2444 | 2425 | if (IS_SYNC(inode)) |
---|
2445 | 2426 | ext4_handle_sync(handle); |
---|
2446 | 2427 | } |
---|
| 2428 | + ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_XATTR); |
---|
2447 | 2429 | |
---|
2448 | 2430 | cleanup: |
---|
2449 | 2431 | brelse(is.iloc.bh); |
---|
.. | .. |
---|
2521 | 2503 | if (error == 0) |
---|
2522 | 2504 | error = error2; |
---|
2523 | 2505 | } |
---|
| 2506 | + ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_XATTR); |
---|
2524 | 2507 | |
---|
2525 | 2508 | return error; |
---|
2526 | 2509 | } |
---|
.. | .. |
---|
2873 | 2856 | struct inode *ea_inode; |
---|
2874 | 2857 | int error; |
---|
2875 | 2858 | |
---|
2876 | | - error = ext4_xattr_ensure_credits(handle, inode, extra_credits, |
---|
2877 | | - NULL /* bh */, |
---|
2878 | | - false /* dirty */, |
---|
2879 | | - false /* block_csum */); |
---|
2880 | | - if (error) { |
---|
| 2859 | + error = ext4_journal_ensure_credits(handle, extra_credits, |
---|
| 2860 | + ext4_free_metadata_revoke_credits(inode->i_sb, 1)); |
---|
| 2861 | + if (error < 0) { |
---|
2881 | 2862 | EXT4_ERROR_INODE(inode, "ensure credits (error %d)", error); |
---|
2882 | 2863 | goto cleanup; |
---|
2883 | 2864 | } |
---|
.. | .. |
---|
2912 | 2893 | bh = ext4_sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl, REQ_PRIO); |
---|
2913 | 2894 | if (IS_ERR(bh)) { |
---|
2914 | 2895 | error = PTR_ERR(bh); |
---|
2915 | | - if (error == -EIO) |
---|
2916 | | - EXT4_ERROR_INODE(inode, "block %llu read error", |
---|
2917 | | - EXT4_I(inode)->i_file_acl); |
---|
| 2896 | + if (error == -EIO) { |
---|
| 2897 | + EXT4_ERROR_INODE_ERR(inode, EIO, |
---|
| 2898 | + "block %llu read error", |
---|
| 2899 | + EXT4_I(inode)->i_file_acl); |
---|
| 2900 | + } |
---|
2918 | 2901 | bh = NULL; |
---|
2919 | 2902 | goto cleanup; |
---|
2920 | 2903 | } |
---|
.. | .. |
---|
2953 | 2936 | error); |
---|
2954 | 2937 | goto cleanup; |
---|
2955 | 2938 | } |
---|
| 2939 | + ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_XATTR); |
---|
2956 | 2940 | } |
---|
2957 | 2941 | error = 0; |
---|
2958 | 2942 | cleanup: |
---|