| .. | .. | 
|---|
| 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: | 
|---|