diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-16 15:11:57 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-16 15:11:57 -0400 |
| commit | 300df7dc89cc276377fc020704e34875d5c473b6 (patch) | |
| tree | 6b280000815b0562255cecf3da1a8c9597bce702 | |
| parent | 661adc423d70203a56723701aaf255e16950dfdb (diff) | |
| parent | 9af0b38ff3f4f79c62dd909405b113bf7c1a23aa (diff) | |
Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jlbec/ocfs2
* 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jlbec/ocfs2:
ocfs2/net: Use wait_event() in o2net_send_message_vec()
ocfs2: Adjust rightmost path in ocfs2_add_branch.
ocfs2: fdatasync should skip unimportant metadata writeout
ocfs2: Remove redundant gotos in ocfs2_mount_volume()
ocfs2: Add statistics for the checksum and ecc operations.
ocfs2 patch to track delayed orphan scan timer statistics
ocfs2: timer to queue scan of all orphan slots
ocfs2: Correct ordering of ip_alloc_sem and localloc locks for directories
ocfs2: Fix possible deadlock in quota recovery
ocfs2: Fix possible deadlock with quotas in ocfs2_setattr()
ocfs2: Fix lock inversion in ocfs2_local_read_info()
ocfs2: Fix possible deadlock in ocfs2_global_read_dquot()
ocfs2: update comments in masklog.h
ocfs2: Don't printk the error when listing too many xattrs.
| -rw-r--r-- | fs/ocfs2/alloc.c | 80 | ||||
| -rw-r--r-- | fs/ocfs2/blockcheck.c | 184 | ||||
| -rw-r--r-- | fs/ocfs2/blockcheck.h | 29 | ||||
| -rw-r--r-- | fs/ocfs2/cluster/masklog.h | 35 | ||||
| -rw-r--r-- | fs/ocfs2/cluster/tcp.c | 7 | ||||
| -rw-r--r-- | fs/ocfs2/dir.c | 21 | ||||
| -rw-r--r-- | fs/ocfs2/dlmglue.c | 51 | ||||
| -rw-r--r-- | fs/ocfs2/dlmglue.h | 11 | ||||
| -rw-r--r-- | fs/ocfs2/file.c | 56 | ||||
| -rw-r--r-- | fs/ocfs2/journal.c | 111 | ||||
| -rw-r--r-- | fs/ocfs2/journal.h | 4 | ||||
| -rw-r--r-- | fs/ocfs2/ocfs2.h | 16 | ||||
| -rw-r--r-- | fs/ocfs2/ocfs2_lockid.h | 5 | ||||
| -rw-r--r-- | fs/ocfs2/quota_global.c | 4 | ||||
| -rw-r--r-- | fs/ocfs2/quota_local.c | 21 | ||||
| -rw-r--r-- | fs/ocfs2/super.c | 66 | ||||
| -rw-r--r-- | fs/ocfs2/xattr.c | 5 |
17 files changed, 610 insertions, 96 deletions
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index 678a067d9251..9edcde4974aa 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c | |||
| @@ -475,6 +475,12 @@ struct ocfs2_path { | |||
| 475 | #define path_leaf_el(_path) ((_path)->p_node[(_path)->p_tree_depth].el) | 475 | #define path_leaf_el(_path) ((_path)->p_node[(_path)->p_tree_depth].el) |
| 476 | #define path_num_items(_path) ((_path)->p_tree_depth + 1) | 476 | #define path_num_items(_path) ((_path)->p_tree_depth + 1) |
| 477 | 477 | ||
| 478 | static int ocfs2_find_path(struct inode *inode, struct ocfs2_path *path, | ||
| 479 | u32 cpos); | ||
| 480 | static void ocfs2_adjust_rightmost_records(struct inode *inode, | ||
| 481 | handle_t *handle, | ||
| 482 | struct ocfs2_path *path, | ||
| 483 | struct ocfs2_extent_rec *insert_rec); | ||
| 478 | /* | 484 | /* |
| 479 | * Reset the actual path elements so that we can re-use the structure | 485 | * Reset the actual path elements so that we can re-use the structure |
| 480 | * to build another path. Generally, this involves freeing the buffer | 486 | * to build another path. Generally, this involves freeing the buffer |
| @@ -1013,6 +1019,54 @@ static inline u32 ocfs2_sum_rightmost_rec(struct ocfs2_extent_list *el) | |||
| 1013 | } | 1019 | } |
| 1014 | 1020 | ||
| 1015 | /* | 1021 | /* |
| 1022 | * Change range of the branches in the right most path according to the leaf | ||
| 1023 | * extent block's rightmost record. | ||
| 1024 | */ | ||
| 1025 | static int ocfs2_adjust_rightmost_branch(handle_t *handle, | ||
| 1026 | struct inode *inode, | ||
| 1027 | struct ocfs2_extent_tree *et) | ||
| 1028 | { | ||
| 1029 | int status; | ||
| 1030 | struct ocfs2_path *path = NULL; | ||
| 1031 | struct ocfs2_extent_list *el; | ||
| 1032 | struct ocfs2_extent_rec *rec; | ||
| 1033 | |||
| 1034 | path = ocfs2_new_path_from_et(et); | ||
| 1035 | if (!path) { | ||
| 1036 | status = -ENOMEM; | ||
| 1037 | return status; | ||
| 1038 | } | ||
| 1039 | |||
| 1040 | status = ocfs2_find_path(inode, path, UINT_MAX); | ||
| 1041 | if (status < 0) { | ||
| 1042 | mlog_errno(status); | ||
| 1043 | goto out; | ||
| 1044 | } | ||
| 1045 | |||
| 1046 | status = ocfs2_extend_trans(handle, path_num_items(path) + | ||
| 1047 | handle->h_buffer_credits); | ||
| 1048 | if (status < 0) { | ||
| 1049 | mlog_errno(status); | ||
| 1050 | goto out; | ||
| 1051 | } | ||
| 1052 | |||
| 1053 | status = ocfs2_journal_access_path(inode, handle, path); | ||
| 1054 | if (status < 0) { | ||
| 1055 | mlog_errno(status); | ||
| 1056 | goto out; | ||
| 1057 | } | ||
| 1058 | |||
| 1059 | el = path_leaf_el(path); | ||
| 1060 | rec = &el->l_recs[le32_to_cpu(el->l_next_free_rec) - 1]; | ||
| 1061 | |||
| 1062 | ocfs2_adjust_rightmost_records(inode, handle, path, rec); | ||
| 1063 | |||
| 1064 | out: | ||
| 1065 | ocfs2_free_path(path); | ||
| 1066 | return status; | ||
| 1067 | } | ||
| 1068 | |||
| 1069 | /* | ||
| 1016 | * Add an entire tree branch to our inode. eb_bh is the extent block | 1070 | * Add an entire tree branch to our inode. eb_bh is the extent block |
| 1017 | * to start at, if we don't want to start the branch at the dinode | 1071 | * to start at, if we don't want to start the branch at the dinode |
| 1018 | * structure. | 1072 | * structure. |
| @@ -1038,7 +1092,7 @@ static int ocfs2_add_branch(struct ocfs2_super *osb, | |||
| 1038 | struct ocfs2_extent_block *eb; | 1092 | struct ocfs2_extent_block *eb; |
| 1039 | struct ocfs2_extent_list *eb_el; | 1093 | struct ocfs2_extent_list *eb_el; |
| 1040 | struct ocfs2_extent_list *el; | 1094 | struct ocfs2_extent_list *el; |
| 1041 | u32 new_cpos; | 1095 | u32 new_cpos, root_end; |
| 1042 | 1096 | ||
| 1043 | mlog_entry_void(); | 1097 | mlog_entry_void(); |
| 1044 | 1098 | ||
| @@ -1055,6 +1109,27 @@ static int ocfs2_add_branch(struct ocfs2_super *osb, | |||
| 1055 | 1109 | ||
| 1056 | new_blocks = le16_to_cpu(el->l_tree_depth); | 1110 | new_blocks = le16_to_cpu(el->l_tree_depth); |
| 1057 | 1111 | ||
| 1112 | eb = (struct ocfs2_extent_block *)(*last_eb_bh)->b_data; | ||
| 1113 | new_cpos = ocfs2_sum_rightmost_rec(&eb->h_list); | ||
| 1114 | root_end = ocfs2_sum_rightmost_rec(et->et_root_el); | ||
| 1115 | |||
| 1116 | /* | ||
| 1117 | * If there is a gap before the root end and the real end | ||
| 1118 | * of the righmost leaf block, we need to remove the gap | ||
| 1119 | * between new_cpos and root_end first so that the tree | ||
| 1120 | * is consistent after we add a new branch(it will start | ||
| 1121 | * from new_cpos). | ||
| 1122 | */ | ||
| 1123 | if (root_end > new_cpos) { | ||
| 1124 | mlog(0, "adjust the cluster end from %u to %u\n", | ||
| 1125 | root_end, new_cpos); | ||
| 1126 | status = ocfs2_adjust_rightmost_branch(handle, inode, et); | ||
| 1127 | if (status) { | ||
| 1128 | mlog_errno(status); | ||
| 1129 | goto bail; | ||
| 1130 | } | ||
| 1131 | } | ||
| 1132 | |||
| 1058 | /* allocate the number of new eb blocks we need */ | 1133 | /* allocate the number of new eb blocks we need */ |
| 1059 | new_eb_bhs = kcalloc(new_blocks, sizeof(struct buffer_head *), | 1134 | new_eb_bhs = kcalloc(new_blocks, sizeof(struct buffer_head *), |
| 1060 | GFP_KERNEL); | 1135 | GFP_KERNEL); |
| @@ -1071,9 +1146,6 @@ static int ocfs2_add_branch(struct ocfs2_super *osb, | |||
| 1071 | goto bail; | 1146 | goto bail; |
| 1072 | } | 1147 | } |
| 1073 | 1148 | ||
| 1074 | eb = (struct ocfs2_extent_block *)(*last_eb_bh)->b_data; | ||
| 1075 | new_cpos = ocfs2_sum_rightmost_rec(&eb->h_list); | ||
| 1076 | |||
| 1077 | /* Note: new_eb_bhs[new_blocks - 1] is the guy which will be | 1149 | /* Note: new_eb_bhs[new_blocks - 1] is the guy which will be |
| 1078 | * linked with the rest of the tree. | 1150 | * linked with the rest of the tree. |
| 1079 | * conversly, new_eb_bhs[0] is the new bottommost leaf. | 1151 | * conversly, new_eb_bhs[0] is the new bottommost leaf. |
diff --git a/fs/ocfs2/blockcheck.c b/fs/ocfs2/blockcheck.c index 2a947c44e594..a1163b8b417c 100644 --- a/fs/ocfs2/blockcheck.c +++ b/fs/ocfs2/blockcheck.c | |||
| @@ -22,6 +22,9 @@ | |||
| 22 | #include <linux/crc32.h> | 22 | #include <linux/crc32.h> |
| 23 | #include <linux/buffer_head.h> | 23 | #include <linux/buffer_head.h> |
| 24 | #include <linux/bitops.h> | 24 | #include <linux/bitops.h> |
| 25 | #include <linux/debugfs.h> | ||
| 26 | #include <linux/module.h> | ||
| 27 | #include <linux/fs.h> | ||
| 25 | #include <asm/byteorder.h> | 28 | #include <asm/byteorder.h> |
| 26 | 29 | ||
| 27 | #include <cluster/masklog.h> | 30 | #include <cluster/masklog.h> |
| @@ -222,6 +225,155 @@ void ocfs2_hamming_fix_block(void *data, unsigned int blocksize, | |||
| 222 | ocfs2_hamming_fix(data, blocksize * 8, 0, fix); | 225 | ocfs2_hamming_fix(data, blocksize * 8, 0, fix); |
| 223 | } | 226 | } |
| 224 | 227 | ||
| 228 | |||
| 229 | /* | ||
| 230 | * Debugfs handling. | ||
| 231 | */ | ||
| 232 | |||
| 233 | #ifdef CONFIG_DEBUG_FS | ||
| 234 | |||
| 235 | static int blockcheck_u64_get(void *data, u64 *val) | ||
| 236 | { | ||
| 237 | *val = *(u64 *)data; | ||
| 238 | return 0; | ||
| 239 | } | ||
| 240 | DEFINE_SIMPLE_ATTRIBUTE(blockcheck_fops, blockcheck_u64_get, NULL, "%llu\n"); | ||
| 241 | |||
| 242 | static struct dentry *blockcheck_debugfs_create(const char *name, | ||
| 243 | struct dentry *parent, | ||
| 244 | u64 *value) | ||
| 245 | { | ||
| 246 | return debugfs_create_file(name, S_IFREG | S_IRUSR, parent, value, | ||
| 247 | &blockcheck_fops); | ||
| 248 | } | ||
| 249 | |||
| 250 | static void ocfs2_blockcheck_debug_remove(struct ocfs2_blockcheck_stats *stats) | ||
| 251 | { | ||
| 252 | if (stats) { | ||
| 253 | debugfs_remove(stats->b_debug_check); | ||
| 254 | stats->b_debug_check = NULL; | ||
| 255 | debugfs_remove(stats->b_debug_failure); | ||
| 256 | stats->b_debug_failure = NULL; | ||
| 257 | debugfs_remove(stats->b_debug_recover); | ||
| 258 | stats->b_debug_recover = NULL; | ||
| 259 | debugfs_remove(stats->b_debug_dir); | ||
| 260 | stats->b_debug_dir = NULL; | ||
| 261 | } | ||
| 262 | } | ||
| 263 | |||
| 264 | static int ocfs2_blockcheck_debug_install(struct ocfs2_blockcheck_stats *stats, | ||
| 265 | struct dentry *parent) | ||
| 266 | { | ||
| 267 | int rc = -EINVAL; | ||
| 268 | |||
| 269 | if (!stats) | ||
| 270 | goto out; | ||
| 271 | |||
| 272 | stats->b_debug_dir = debugfs_create_dir("blockcheck", parent); | ||
| 273 | if (!stats->b_debug_dir) | ||
| 274 | goto out; | ||
| 275 | |||
| 276 | stats->b_debug_check = | ||
| 277 | blockcheck_debugfs_create("blocks_checked", | ||
| 278 | stats->b_debug_dir, | ||
| 279 | &stats->b_check_count); | ||
| 280 | |||
| 281 | stats->b_debug_failure = | ||
| 282 | blockcheck_debugfs_create("checksums_failed", | ||
| 283 | stats->b_debug_dir, | ||
| 284 | &stats->b_failure_count); | ||
| 285 | |||
| 286 | stats->b_debug_recover = | ||
| 287 | blockcheck_debugfs_create("ecc_recoveries", | ||
| 288 | stats->b_debug_dir, | ||
| 289 | &stats->b_recover_count); | ||
| 290 | if (stats->b_debug_check && stats->b_debug_failure && | ||
| 291 | stats->b_debug_recover) | ||
| 292 | rc = 0; | ||
| 293 | |||
| 294 | out: | ||
| 295 | if (rc) | ||
| 296 | ocfs2_blockcheck_debug_remove(stats); | ||
| 297 | return rc; | ||
| 298 | } | ||
| 299 | #else | ||
| 300 | static inline int ocfs2_blockcheck_debug_install(struct ocfs2_blockcheck_stats *stats, | ||
| 301 | struct dentry *parent) | ||
| 302 | { | ||
| 303 | return 0; | ||
| 304 | } | ||
| 305 | |||
| 306 | static inline void ocfs2_blockcheck_debug_remove(struct ocfs2_blockcheck_stats *stats) | ||
| 307 | { | ||
| 308 | } | ||
| 309 | #endif /* CONFIG_DEBUG_FS */ | ||
| 310 | |||
| 311 | /* Always-called wrappers for starting and stopping the debugfs files */ | ||
| 312 | int ocfs2_blockcheck_stats_debugfs_install(struct ocfs2_blockcheck_stats *stats, | ||
| 313 | struct dentry *parent) | ||
| 314 | { | ||
| 315 | return ocfs2_blockcheck_debug_install(stats, parent); | ||
| 316 | } | ||
| 317 | |||
| 318 | void ocfs2_blockcheck_stats_debugfs_remove(struct ocfs2_blockcheck_stats *stats) | ||
| 319 | { | ||
| 320 | ocfs2_blockcheck_debug_remove(stats); | ||
| 321 | } | ||
| 322 | |||
| 323 | static void ocfs2_blockcheck_inc_check(struct ocfs2_blockcheck_stats *stats) | ||
| 324 | { | ||
| 325 | u64 new_count; | ||
| 326 | |||
| 327 | if (!stats) | ||
| 328 | return; | ||
| 329 | |||
| 330 | spin_lock(&stats->b_lock); | ||
| 331 | stats->b_check_count++; | ||
| 332 | new_count = stats->b_check_count; | ||
| 333 | spin_unlock(&stats->b_lock); | ||
| 334 | |||
| 335 | if (!new_count) | ||
| 336 | mlog(ML_NOTICE, "Block check count has wrapped\n"); | ||
| 337 | } | ||
| 338 | |||
| 339 | static void ocfs2_blockcheck_inc_failure(struct ocfs2_blockcheck_stats *stats) | ||
| 340 | { | ||
| 341 | u64 new_count; | ||
| 342 | |||
| 343 | if (!stats) | ||
| 344 | return; | ||
| 345 | |||
| 346 | spin_lock(&stats->b_lock); | ||
| 347 | stats->b_failure_count++; | ||
| 348 | new_count = stats->b_failure_count; | ||
| 349 | spin_unlock(&stats->b_lock); | ||
| 350 | |||
| 351 | if (!new_count) | ||
| 352 | mlog(ML_NOTICE, "Checksum failure count has wrapped\n"); | ||
| 353 | } | ||
| 354 | |||
| 355 | static void ocfs2_blockcheck_inc_recover(struct ocfs2_blockcheck_stats *stats) | ||
| 356 | { | ||
| 357 | u64 new_count; | ||
| 358 | |||
| 359 | if (!stats) | ||
| 360 | return; | ||
| 361 | |||
| 362 | spin_lock(&stats->b_lock); | ||
| 363 | stats->b_recover_count++; | ||
| 364 | new_count = stats->b_recover_count; | ||
| 365 | spin_unlock(&stats->b_lock); | ||
| 366 | |||
| 367 | if (!new_count) | ||
| 368 | mlog(ML_NOTICE, "ECC recovery count has wrapped\n"); | ||
| 369 | } | ||
| 370 | |||
| 371 | |||
| 372 | |||
| 373 | /* | ||
| 374 | * These are the low-level APIs for using the ocfs2_block_check structure. | ||
| 375 | */ | ||
| 376 | |||
| 225 | /* | 377 | /* |
| 226 | * This function generates check information for a block. | 378 | * This function generates check information for a block. |
| 227 | * data is the block to be checked. bc is a pointer to the | 379 | * data is the block to be checked. bc is a pointer to the |
| @@ -266,12 +418,15 @@ void ocfs2_block_check_compute(void *data, size_t blocksize, | |||
| 266 | * Again, the data passed in should be the on-disk endian. | 418 | * Again, the data passed in should be the on-disk endian. |
| 267 | */ | 419 | */ |
| 268 | int ocfs2_block_check_validate(void *data, size_t blocksize, | 420 | int ocfs2_block_check_validate(void *data, size_t blocksize, |
| 269 | struct ocfs2_block_check *bc) | 421 | struct ocfs2_block_check *bc, |
| 422 | struct ocfs2_blockcheck_stats *stats) | ||
| 270 | { | 423 | { |
| 271 | int rc = 0; | 424 | int rc = 0; |
| 272 | struct ocfs2_block_check check; | 425 | struct ocfs2_block_check check; |
| 273 | u32 crc, ecc; | 426 | u32 crc, ecc; |
| 274 | 427 | ||
| 428 | ocfs2_blockcheck_inc_check(stats); | ||
| 429 | |||
| 275 | check.bc_crc32e = le32_to_cpu(bc->bc_crc32e); | 430 | check.bc_crc32e = le32_to_cpu(bc->bc_crc32e); |
| 276 | check.bc_ecc = le16_to_cpu(bc->bc_ecc); | 431 | check.bc_ecc = le16_to_cpu(bc->bc_ecc); |
| 277 | 432 | ||
| @@ -282,6 +437,7 @@ int ocfs2_block_check_validate(void *data, size_t blocksize, | |||
| 282 | if (crc == check.bc_crc32e) | 437 | if (crc == check.bc_crc32e) |
| 283 | goto out; | 438 | goto out; |
| 284 | 439 | ||
| 440 | ocfs2_blockcheck_inc_failure(stats); | ||
| 285 | mlog(ML_ERROR, | 441 | mlog(ML_ERROR, |
| 286 | "CRC32 failed: stored: %u, computed %u. Applying ECC.\n", | 442 | "CRC32 failed: stored: %u, computed %u. Applying ECC.\n", |
| 287 | (unsigned int)check.bc_crc32e, (unsigned int)crc); | 443 | (unsigned int)check.bc_crc32e, (unsigned int)crc); |
| @@ -292,8 +448,10 @@ int ocfs2_block_check_validate(void *data, size_t blocksize, | |||
| 292 | 448 | ||
| 293 | /* And check the crc32 again */ | 449 | /* And check the crc32 again */ |
| 294 | crc = crc32_le(~0, data, blocksize); | 450 | crc = crc32_le(~0, data, blocksize); |
| 295 | if (crc == check.bc_crc32e) | 451 | if (crc == check.bc_crc32e) { |
| 452 | ocfs2_blockcheck_inc_recover(stats); | ||
| 296 | goto out; | 453 | goto out; |
| 454 | } | ||
| 297 | 455 | ||
| 298 | mlog(ML_ERROR, "Fixed CRC32 failed: stored: %u, computed %u\n", | 456 | mlog(ML_ERROR, "Fixed CRC32 failed: stored: %u, computed %u\n", |
| 299 | (unsigned int)check.bc_crc32e, (unsigned int)crc); | 457 | (unsigned int)check.bc_crc32e, (unsigned int)crc); |
| @@ -366,7 +524,8 @@ void ocfs2_block_check_compute_bhs(struct buffer_head **bhs, int nr, | |||
| 366 | * Again, the data passed in should be the on-disk endian. | 524 | * Again, the data passed in should be the on-disk endian. |
| 367 | */ | 525 | */ |
| 368 | int ocfs2_block_check_validate_bhs(struct buffer_head **bhs, int nr, | 526 | int ocfs2_block_check_validate_bhs(struct buffer_head **bhs, int nr, |
| 369 | struct ocfs2_block_check *bc) | 527 | struct ocfs2_block_check *bc, |
| 528 | struct ocfs2_blockcheck_stats *stats) | ||
| 370 | { | 529 | { |
| 371 | int i, rc = 0; | 530 | int i, rc = 0; |
| 372 | struct ocfs2_block_check check; | 531 | struct ocfs2_block_check check; |
| @@ -377,6 +536,8 @@ int ocfs2_block_check_validate_bhs(struct buffer_head **bhs, int nr, | |||
| 377 | if (!nr) | 536 | if (!nr) |
| 378 | return 0; | 537 | return 0; |
| 379 | 538 | ||
| 539 | ocfs2_blockcheck_inc_check(stats); | ||
| 540 | |||
| 380 | check.bc_crc32e = le32_to_cpu(bc->bc_crc32e); | 541 | check.bc_crc32e = le32_to_cpu(bc->bc_crc32e); |
| 381 | check.bc_ecc = le16_to_cpu(bc->bc_ecc); | 542 | check.bc_ecc = le16_to_cpu(bc->bc_ecc); |
| 382 | 543 | ||
| @@ -388,6 +549,7 @@ int ocfs2_block_check_validate_bhs(struct buffer_head **bhs, int nr, | |||
| 388 | if (crc == check.bc_crc32e) | 549 | if (crc == check.bc_crc32e) |
| 389 | goto out; | 550 | goto out; |
| 390 | 551 | ||
| 552 | ocfs2_blockcheck_inc_failure(stats); | ||
| 391 | mlog(ML_ERROR, | 553 | mlog(ML_ERROR, |
| 392 | "CRC32 failed: stored: %u, computed %u. Applying ECC.\n", | 554 | "CRC32 failed: stored: %u, computed %u. Applying ECC.\n", |
| 393 | (unsigned int)check.bc_crc32e, (unsigned int)crc); | 555 | (unsigned int)check.bc_crc32e, (unsigned int)crc); |
| @@ -416,8 +578,10 @@ int ocfs2_block_check_validate_bhs(struct buffer_head **bhs, int nr, | |||
| 416 | /* And check the crc32 again */ | 578 | /* And check the crc32 again */ |
| 417 | for (i = 0, crc = ~0; i < nr; i++) | 579 | for (i = 0, crc = ~0; i < nr; i++) |
| 418 | crc = crc32_le(crc, bhs[i]->b_data, bhs[i]->b_size); | 580 | crc = crc32_le(crc, bhs[i]->b_data, bhs[i]->b_size); |
| 419 | if (crc == check.bc_crc32e) | 581 | if (crc == check.bc_crc32e) { |
| 582 | ocfs2_blockcheck_inc_recover(stats); | ||
| 420 | goto out; | 583 | goto out; |
| 584 | } | ||
| 421 | 585 | ||
| 422 | mlog(ML_ERROR, "Fixed CRC32 failed: stored: %u, computed %u\n", | 586 | mlog(ML_ERROR, "Fixed CRC32 failed: stored: %u, computed %u\n", |
| 423 | (unsigned int)check.bc_crc32e, (unsigned int)crc); | 587 | (unsigned int)check.bc_crc32e, (unsigned int)crc); |
| @@ -448,9 +612,11 @@ int ocfs2_validate_meta_ecc(struct super_block *sb, void *data, | |||
| 448 | struct ocfs2_block_check *bc) | 612 | struct ocfs2_block_check *bc) |
| 449 | { | 613 | { |
| 450 | int rc = 0; | 614 | int rc = 0; |
| 615 | struct ocfs2_super *osb = OCFS2_SB(sb); | ||
| 451 | 616 | ||
| 452 | if (ocfs2_meta_ecc(OCFS2_SB(sb))) | 617 | if (ocfs2_meta_ecc(osb)) |
| 453 | rc = ocfs2_block_check_validate(data, sb->s_blocksize, bc); | 618 | rc = ocfs2_block_check_validate(data, sb->s_blocksize, bc, |
| 619 | &osb->osb_ecc_stats); | ||
| 454 | 620 | ||
| 455 | return rc; | 621 | return rc; |
| 456 | } | 622 | } |
| @@ -468,9 +634,11 @@ int ocfs2_validate_meta_ecc_bhs(struct super_block *sb, | |||
| 468 | struct ocfs2_block_check *bc) | 634 | struct ocfs2_block_check *bc) |
| 469 | { | 635 | { |
| 470 | int rc = 0; | 636 | int rc = 0; |
| 637 | struct ocfs2_super *osb = OCFS2_SB(sb); | ||
| 471 | 638 | ||
| 472 | if (ocfs2_meta_ecc(OCFS2_SB(sb))) | 639 | if (ocfs2_meta_ecc(osb)) |
| 473 | rc = ocfs2_block_check_validate_bhs(bhs, nr, bc); | 640 | rc = ocfs2_block_check_validate_bhs(bhs, nr, bc, |
| 641 | &osb->osb_ecc_stats); | ||
| 474 | 642 | ||
| 475 | return rc; | 643 | return rc; |
| 476 | } | 644 | } |
diff --git a/fs/ocfs2/blockcheck.h b/fs/ocfs2/blockcheck.h index 70ec3feda32f..d4b69febf70a 100644 --- a/fs/ocfs2/blockcheck.h +++ b/fs/ocfs2/blockcheck.h | |||
| @@ -21,6 +21,24 @@ | |||
| 21 | #define OCFS2_BLOCKCHECK_H | 21 | #define OCFS2_BLOCKCHECK_H |
| 22 | 22 | ||
| 23 | 23 | ||
| 24 | /* Count errors and error correction from blockcheck.c */ | ||
| 25 | struct ocfs2_blockcheck_stats { | ||
| 26 | spinlock_t b_lock; | ||
| 27 | u64 b_check_count; /* Number of blocks we've checked */ | ||
| 28 | u64 b_failure_count; /* Number of failed checksums */ | ||
| 29 | u64 b_recover_count; /* Number of blocks fixed by ecc */ | ||
| 30 | |||
| 31 | /* | ||
| 32 | * debugfs entries, used if this is passed to | ||
| 33 | * ocfs2_blockcheck_stats_debugfs_install() | ||
| 34 | */ | ||
| 35 | struct dentry *b_debug_dir; /* Parent of the debugfs files */ | ||
| 36 | struct dentry *b_debug_check; /* Exposes b_check_count */ | ||
| 37 | struct dentry *b_debug_failure; /* Exposes b_failure_count */ | ||
| 38 | struct dentry *b_debug_recover; /* Exposes b_recover_count */ | ||
| 39 | }; | ||
| 40 | |||
| 41 | |||
| 24 | /* High level block API */ | 42 | /* High level block API */ |
| 25 | void ocfs2_compute_meta_ecc(struct super_block *sb, void *data, | 43 | void ocfs2_compute_meta_ecc(struct super_block *sb, void *data, |
| 26 | struct ocfs2_block_check *bc); | 44 | struct ocfs2_block_check *bc); |
| @@ -37,11 +55,18 @@ int ocfs2_validate_meta_ecc_bhs(struct super_block *sb, | |||
| 37 | void ocfs2_block_check_compute(void *data, size_t blocksize, | 55 | void ocfs2_block_check_compute(void *data, size_t blocksize, |
| 38 | struct ocfs2_block_check *bc); | 56 | struct ocfs2_block_check *bc); |
| 39 | int ocfs2_block_check_validate(void *data, size_t blocksize, | 57 | int ocfs2_block_check_validate(void *data, size_t blocksize, |
| 40 | struct ocfs2_block_check *bc); | 58 | struct ocfs2_block_check *bc, |
| 59 | struct ocfs2_blockcheck_stats *stats); | ||
| 41 | void ocfs2_block_check_compute_bhs(struct buffer_head **bhs, int nr, | 60 | void ocfs2_block_check_compute_bhs(struct buffer_head **bhs, int nr, |
| 42 | struct ocfs2_block_check *bc); | 61 | struct ocfs2_block_check *bc); |
| 43 | int ocfs2_block_check_validate_bhs(struct buffer_head **bhs, int nr, | 62 | int ocfs2_block_check_validate_bhs(struct buffer_head **bhs, int nr, |
| 44 | struct ocfs2_block_check *bc); | 63 | struct ocfs2_block_check *bc, |
| 64 | struct ocfs2_blockcheck_stats *stats); | ||
| 65 | |||
| 66 | /* Debug Initialization */ | ||
| 67 | int ocfs2_blockcheck_stats_debugfs_install(struct ocfs2_blockcheck_stats *stats, | ||
| 68 | struct dentry *parent); | ||
| 69 | void ocfs2_blockcheck_stats_debugfs_remove(struct ocfs2_blockcheck_stats *stats); | ||
| 45 | 70 | ||
| 46 | /* | 71 | /* |
| 47 | * Hamming code functions | 72 | * Hamming code functions |
diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index 7e72a81bc2d4..696c32e50716 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h | |||
| @@ -48,34 +48,33 @@ | |||
| 48 | * only emit the appropriage printk() when the caller passes in a constant | 48 | * only emit the appropriage printk() when the caller passes in a constant |
| 49 | * mask, as is almost always the case. | 49 | * mask, as is almost always the case. |
| 50 | * | 50 | * |
| 51 | * All this bitmask nonsense is hidden from the /proc interface so that Joel | 51 | * All this bitmask nonsense is managed from the files under |
| 52 | * doesn't have an aneurism. Reading the file gives a straight forward | 52 | * /sys/fs/o2cb/logmask/. Reading the files gives a straightforward |
| 53 | * indication of which bits are on or off: | 53 | * indication of which bits are allowed (allow) or denied (off/deny). |
| 54 | * ENTRY off | 54 | * ENTRY deny |
| 55 | * EXIT off | 55 | * EXIT deny |
| 56 | * TCP off | 56 | * TCP off |
| 57 | * MSG off | 57 | * MSG off |
| 58 | * SOCKET off | 58 | * SOCKET off |
| 59 | * ERROR off | 59 | * ERROR allow |
| 60 | * NOTICE on | 60 | * NOTICE allow |
| 61 | * | 61 | * |
| 62 | * Writing changes the state of a given bit and requires a strictly formatted | 62 | * Writing changes the state of a given bit and requires a strictly formatted |
| 63 | * single write() call: | 63 | * single write() call: |
| 64 | * | 64 | * |
| 65 | * write(fd, "ENTRY on", 8); | 65 | * write(fd, "allow", 5); |
| 66 | * | 66 | * |
| 67 | * would turn the entry bit on. "1" is also accepted in the place of "on", and | 67 | * Echoing allow/deny/off string into the logmask files can flip the bits |
| 68 | * "off" and "0" behave as expected. | 68 | * on or off as expected; here is the bash script for example: |
| 69 | * | 69 | * |
| 70 | * Some trivial shell can flip all the bits on or off: | 70 | * log_mask="/sys/fs/o2cb/log_mask" |
| 71 | * for node in ENTRY EXIT TCP MSG SOCKET ERROR NOTICE; do | ||
| 72 | * echo allow >"$log_mask"/"$node" | ||
| 73 | * done | ||
| 71 | * | 74 | * |
| 72 | * log_mask="/proc/fs/ocfs2_nodemanager/log_mask" | 75 | * The debugfs.ocfs2 tool can also flip the bits with the -l option: |
| 73 | * cat $log_mask | ( | 76 | * |
| 74 | * while read bit status; do | 77 | * debugfs.ocfs2 -l TCP allow |
| 75 | * # $1 is "on" or "off", say | ||
| 76 | * echo "$bit $1" > $log_mask | ||
| 77 | * done | ||
| 78 | * ) | ||
| 79 | */ | 78 | */ |
| 80 | 79 | ||
| 81 | /* for task_struct */ | 80 | /* for task_struct */ |
diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c index 9fbe849f6344..334f231a422c 100644 --- a/fs/ocfs2/cluster/tcp.c +++ b/fs/ocfs2/cluster/tcp.c | |||
| @@ -974,7 +974,7 @@ static int o2net_tx_can_proceed(struct o2net_node *nn, | |||
| 974 | int o2net_send_message_vec(u32 msg_type, u32 key, struct kvec *caller_vec, | 974 | int o2net_send_message_vec(u32 msg_type, u32 key, struct kvec *caller_vec, |
| 975 | size_t caller_veclen, u8 target_node, int *status) | 975 | size_t caller_veclen, u8 target_node, int *status) |
| 976 | { | 976 | { |
| 977 | int ret, error = 0; | 977 | int ret; |
| 978 | struct o2net_msg *msg = NULL; | 978 | struct o2net_msg *msg = NULL; |
| 979 | size_t veclen, caller_bytes = 0; | 979 | size_t veclen, caller_bytes = 0; |
| 980 | struct kvec *vec = NULL; | 980 | struct kvec *vec = NULL; |
| @@ -1015,10 +1015,7 @@ int o2net_send_message_vec(u32 msg_type, u32 key, struct kvec *caller_vec, | |||
| 1015 | 1015 | ||
| 1016 | o2net_set_nst_sock_time(&nst); | 1016 | o2net_set_nst_sock_time(&nst); |
| 1017 | 1017 | ||
| 1018 | ret = wait_event_interruptible(nn->nn_sc_wq, | 1018 | wait_event(nn->nn_sc_wq, o2net_tx_can_proceed(nn, &sc, &ret)); |
| 1019 | o2net_tx_can_proceed(nn, &sc, &error)); | ||
| 1020 | if (!ret && error) | ||
| 1021 | ret = error; | ||
| 1022 | if (ret) | 1019 | if (ret) |
| 1023 | goto out; | 1020 | goto out; |
| 1024 | 1021 | ||
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index c5752305627c..b358f3bf896d 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c | |||
| @@ -2900,6 +2900,8 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh, | |||
| 2900 | alloc = ocfs2_clusters_for_bytes(sb, bytes); | 2900 | alloc = ocfs2_clusters_for_bytes(sb, bytes); |
| 2901 | dx_alloc = 0; | 2901 | dx_alloc = 0; |
| 2902 | 2902 | ||
| 2903 | down_write(&oi->ip_alloc_sem); | ||
| 2904 | |||
| 2903 | if (ocfs2_supports_indexed_dirs(osb)) { | 2905 | if (ocfs2_supports_indexed_dirs(osb)) { |
| 2904 | credits += ocfs2_add_dir_index_credits(sb); | 2906 | credits += ocfs2_add_dir_index_credits(sb); |
| 2905 | 2907 | ||
| @@ -2940,8 +2942,6 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh, | |||
| 2940 | goto out; | 2942 | goto out; |
| 2941 | } | 2943 | } |
| 2942 | 2944 | ||
| 2943 | down_write(&oi->ip_alloc_sem); | ||
| 2944 | |||
| 2945 | /* | 2945 | /* |
| 2946 | * Prepare for worst case allocation scenario of two separate | 2946 | * Prepare for worst case allocation scenario of two separate |
| 2947 | * extents in the unindexed tree. | 2947 | * extents in the unindexed tree. |
| @@ -2953,7 +2953,7 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh, | |||
| 2953 | if (IS_ERR(handle)) { | 2953 | if (IS_ERR(handle)) { |
| 2954 | ret = PTR_ERR(handle); | 2954 | ret = PTR_ERR(handle); |
| 2955 | mlog_errno(ret); | 2955 | mlog_errno(ret); |
| 2956 | goto out_sem; | 2956 | goto out; |
| 2957 | } | 2957 | } |
| 2958 | 2958 | ||
| 2959 | if (vfs_dq_alloc_space_nodirty(dir, | 2959 | if (vfs_dq_alloc_space_nodirty(dir, |
| @@ -3172,10 +3172,8 @@ out_commit: | |||
| 3172 | 3172 | ||
| 3173 | ocfs2_commit_trans(osb, handle); | 3173 | ocfs2_commit_trans(osb, handle); |
| 3174 | 3174 | ||
| 3175 | out_sem: | ||
| 3176 | up_write(&oi->ip_alloc_sem); | ||
| 3177 | |||
| 3178 | out: | 3175 | out: |
| 3176 | up_write(&oi->ip_alloc_sem); | ||
| 3179 | if (data_ac) | 3177 | if (data_ac) |
| 3180 | ocfs2_free_alloc_context(data_ac); | 3178 | ocfs2_free_alloc_context(data_ac); |
| 3181 | if (meta_ac) | 3179 | if (meta_ac) |
| @@ -3322,11 +3320,15 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb, | |||
| 3322 | brelse(new_bh); | 3320 | brelse(new_bh); |
| 3323 | new_bh = NULL; | 3321 | new_bh = NULL; |
| 3324 | 3322 | ||
| 3323 | down_write(&OCFS2_I(dir)->ip_alloc_sem); | ||
| 3324 | drop_alloc_sem = 1; | ||
| 3325 | dir_i_size = i_size_read(dir); | 3325 | dir_i_size = i_size_read(dir); |
| 3326 | credits = OCFS2_SIMPLE_DIR_EXTEND_CREDITS; | 3326 | credits = OCFS2_SIMPLE_DIR_EXTEND_CREDITS; |
| 3327 | goto do_extend; | 3327 | goto do_extend; |
| 3328 | } | 3328 | } |
| 3329 | 3329 | ||
| 3330 | down_write(&OCFS2_I(dir)->ip_alloc_sem); | ||
| 3331 | drop_alloc_sem = 1; | ||
| 3330 | dir_i_size = i_size_read(dir); | 3332 | dir_i_size = i_size_read(dir); |
| 3331 | mlog(0, "extending dir %llu (i_size = %lld)\n", | 3333 | mlog(0, "extending dir %llu (i_size = %lld)\n", |
| 3332 | (unsigned long long)OCFS2_I(dir)->ip_blkno, dir_i_size); | 3334 | (unsigned long long)OCFS2_I(dir)->ip_blkno, dir_i_size); |
| @@ -3370,9 +3372,6 @@ do_extend: | |||
| 3370 | credits++; /* For attaching the new dirent block to the | 3372 | credits++; /* For attaching the new dirent block to the |
| 3371 | * dx_root */ | 3373 | * dx_root */ |
| 3372 | 3374 | ||
| 3373 | down_write(&OCFS2_I(dir)->ip_alloc_sem); | ||
| 3374 | drop_alloc_sem = 1; | ||
| 3375 | |||
| 3376 | handle = ocfs2_start_trans(osb, credits); | 3375 | handle = ocfs2_start_trans(osb, credits); |
| 3377 | if (IS_ERR(handle)) { | 3376 | if (IS_ERR(handle)) { |
| 3378 | status = PTR_ERR(handle); | 3377 | status = PTR_ERR(handle); |
| @@ -3435,10 +3434,10 @@ bail_bh: | |||
| 3435 | *new_de_bh = new_bh; | 3434 | *new_de_bh = new_bh; |
| 3436 | get_bh(*new_de_bh); | 3435 | get_bh(*new_de_bh); |
| 3437 | bail: | 3436 | bail: |
| 3438 | if (drop_alloc_sem) | ||
| 3439 | up_write(&OCFS2_I(dir)->ip_alloc_sem); | ||
| 3440 | if (handle) | 3437 | if (handle) |
| 3441 | ocfs2_commit_trans(osb, handle); | 3438 | ocfs2_commit_trans(osb, handle); |
| 3439 | if (drop_alloc_sem) | ||
| 3440 | up_write(&OCFS2_I(dir)->ip_alloc_sem); | ||
| 3442 | 3441 | ||
| 3443 | if (data_ac) | 3442 | if (data_ac) |
| 3444 | ocfs2_free_alloc_context(data_ac); | 3443 | ocfs2_free_alloc_context(data_ac); |
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index e15fc7d50827..6cdeaa76f27f 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c | |||
| @@ -248,6 +248,10 @@ static struct ocfs2_lock_res_ops ocfs2_nfs_sync_lops = { | |||
| 248 | .flags = 0, | 248 | .flags = 0, |
| 249 | }; | 249 | }; |
| 250 | 250 | ||
| 251 | static struct ocfs2_lock_res_ops ocfs2_orphan_scan_lops = { | ||
| 252 | .flags = LOCK_TYPE_REQUIRES_REFRESH|LOCK_TYPE_USES_LVB, | ||
| 253 | }; | ||
| 254 | |||
| 251 | static struct ocfs2_lock_res_ops ocfs2_dentry_lops = { | 255 | static struct ocfs2_lock_res_ops ocfs2_dentry_lops = { |
| 252 | .get_osb = ocfs2_get_dentry_osb, | 256 | .get_osb = ocfs2_get_dentry_osb, |
| 253 | .post_unlock = ocfs2_dentry_post_unlock, | 257 | .post_unlock = ocfs2_dentry_post_unlock, |
| @@ -637,6 +641,19 @@ static void ocfs2_nfs_sync_lock_res_init(struct ocfs2_lock_res *res, | |||
| 637 | &ocfs2_nfs_sync_lops, osb); | 641 | &ocfs2_nfs_sync_lops, osb); |
| 638 | } | 642 | } |
| 639 | 643 | ||
| 644 | static void ocfs2_orphan_scan_lock_res_init(struct ocfs2_lock_res *res, | ||
| 645 | struct ocfs2_super *osb) | ||
| 646 | { | ||
| 647 | struct ocfs2_orphan_scan_lvb *lvb; | ||
| 648 | |||
| 649 | ocfs2_lock_res_init_once(res); | ||
| 650 | ocfs2_build_lock_name(OCFS2_LOCK_TYPE_ORPHAN_SCAN, 0, 0, res->l_name); | ||
| 651 | ocfs2_lock_res_init_common(osb, res, OCFS2_LOCK_TYPE_ORPHAN_SCAN, | ||
| 652 | &ocfs2_orphan_scan_lops, osb); | ||
| 653 | lvb = ocfs2_dlm_lvb(&res->l_lksb); | ||
| 654 | lvb->lvb_version = OCFS2_ORPHAN_LVB_VERSION; | ||
| 655 | } | ||
| 656 | |||
| 640 | void ocfs2_file_lock_res_init(struct ocfs2_lock_res *lockres, | 657 | void ocfs2_file_lock_res_init(struct ocfs2_lock_res *lockres, |
| 641 | struct ocfs2_file_private *fp) | 658 | struct ocfs2_file_private *fp) |
| 642 | { | 659 | { |
| @@ -2352,6 +2369,37 @@ void ocfs2_inode_unlock(struct inode *inode, | |||
| 2352 | mlog_exit_void(); | 2369 | mlog_exit_void(); |
| 2353 | } | 2370 | } |
| 2354 | 2371 | ||
| 2372 | int ocfs2_orphan_scan_lock(struct ocfs2_super *osb, u32 *seqno, int ex) | ||
| 2373 | { | ||
| 2374 | struct ocfs2_lock_res *lockres; | ||
| 2375 | struct ocfs2_orphan_scan_lvb *lvb; | ||
| 2376 | int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR; | ||
| 2377 | int status = 0; | ||
| 2378 | |||
| 2379 | lockres = &osb->osb_orphan_scan.os_lockres; | ||
| 2380 | status = ocfs2_cluster_lock(osb, lockres, level, 0, 0); | ||
| 2381 | if (status < 0) | ||
| 2382 | return status; | ||
| 2383 | |||
| 2384 | lvb = ocfs2_dlm_lvb(&lockres->l_lksb); | ||
| 2385 | if (lvb->lvb_version == OCFS2_ORPHAN_LVB_VERSION) | ||
| 2386 | *seqno = be32_to_cpu(lvb->lvb_os_seqno); | ||
| 2387 | return status; | ||
| 2388 | } | ||
| 2389 | |||
| 2390 | void ocfs2_orphan_scan_unlock(struct ocfs2_super *osb, u32 seqno, int ex) | ||
| 2391 | { | ||
| 2392 | struct ocfs2_lock_res *lockres; | ||
| 2393 | struct ocfs2_orphan_scan_lvb *lvb; | ||
| 2394 | int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR; | ||
| 2395 | |||
| 2396 | lockres = &osb->osb_orphan_scan.os_lockres; | ||
| 2397 | lvb = ocfs2_dlm_lvb(&lockres->l_lksb); | ||
| 2398 | lvb->lvb_version = OCFS2_ORPHAN_LVB_VERSION; | ||
| 2399 | lvb->lvb_os_seqno = cpu_to_be32(seqno); | ||
| 2400 | ocfs2_cluster_unlock(osb, lockres, level); | ||
| 2401 | } | ||
| 2402 | |||
| 2355 | int ocfs2_super_lock(struct ocfs2_super *osb, | 2403 | int ocfs2_super_lock(struct ocfs2_super *osb, |
| 2356 | int ex) | 2404 | int ex) |
| 2357 | { | 2405 | { |
| @@ -2842,6 +2890,7 @@ local: | |||
| 2842 | ocfs2_super_lock_res_init(&osb->osb_super_lockres, osb); | 2890 | ocfs2_super_lock_res_init(&osb->osb_super_lockres, osb); |
| 2843 | ocfs2_rename_lock_res_init(&osb->osb_rename_lockres, osb); | 2891 | ocfs2_rename_lock_res_init(&osb->osb_rename_lockres, osb); |
| 2844 | ocfs2_nfs_sync_lock_res_init(&osb->osb_nfs_sync_lockres, osb); | 2892 | ocfs2_nfs_sync_lock_res_init(&osb->osb_nfs_sync_lockres, osb); |
| 2893 | ocfs2_orphan_scan_lock_res_init(&osb->osb_orphan_scan.os_lockres, osb); | ||
| 2845 | 2894 | ||
| 2846 | osb->cconn = conn; | 2895 | osb->cconn = conn; |
| 2847 | 2896 | ||
| @@ -2878,6 +2927,7 @@ void ocfs2_dlm_shutdown(struct ocfs2_super *osb, | |||
| 2878 | ocfs2_lock_res_free(&osb->osb_super_lockres); | 2927 | ocfs2_lock_res_free(&osb->osb_super_lockres); |
| 2879 | ocfs2_lock_res_free(&osb->osb_rename_lockres); | 2928 | ocfs2_lock_res_free(&osb->osb_rename_lockres); |
| 2880 | ocfs2_lock_res_free(&osb->osb_nfs_sync_lockres); | 2929 | ocfs2_lock_res_free(&osb->osb_nfs_sync_lockres); |
| 2930 | ocfs2_lock_res_free(&osb->osb_orphan_scan.os_lockres); | ||
| 2881 | 2931 | ||
| 2882 | ocfs2_cluster_disconnect(osb->cconn, hangup_pending); | 2932 | ocfs2_cluster_disconnect(osb->cconn, hangup_pending); |
| 2883 | osb->cconn = NULL; | 2933 | osb->cconn = NULL; |
| @@ -3061,6 +3111,7 @@ static void ocfs2_drop_osb_locks(struct ocfs2_super *osb) | |||
| 3061 | ocfs2_simple_drop_lockres(osb, &osb->osb_super_lockres); | 3111 | ocfs2_simple_drop_lockres(osb, &osb->osb_super_lockres); |
| 3062 | ocfs2_simple_drop_lockres(osb, &osb->osb_rename_lockres); | 3112 | ocfs2_simple_drop_lockres(osb, &osb->osb_rename_lockres); |
| 3063 | ocfs2_simple_drop_lockres(osb, &osb->osb_nfs_sync_lockres); | 3113 | ocfs2_simple_drop_lockres(osb, &osb->osb_nfs_sync_lockres); |
| 3114 | ocfs2_simple_drop_lockres(osb, &osb->osb_orphan_scan.os_lockres); | ||
| 3064 | } | 3115 | } |
| 3065 | 3116 | ||
| 3066 | int ocfs2_drop_inode_locks(struct inode *inode) | 3117 | int ocfs2_drop_inode_locks(struct inode *inode) |
diff --git a/fs/ocfs2/dlmglue.h b/fs/ocfs2/dlmglue.h index e1fd5721cd7f..31b90d7b8f51 100644 --- a/fs/ocfs2/dlmglue.h +++ b/fs/ocfs2/dlmglue.h | |||
| @@ -62,6 +62,14 @@ struct ocfs2_qinfo_lvb { | |||
| 62 | __be32 lvb_free_entry; | 62 | __be32 lvb_free_entry; |
| 63 | }; | 63 | }; |
| 64 | 64 | ||
| 65 | #define OCFS2_ORPHAN_LVB_VERSION 1 | ||
| 66 | |||
| 67 | struct ocfs2_orphan_scan_lvb { | ||
| 68 | __u8 lvb_version; | ||
| 69 | __u8 lvb_reserved[3]; | ||
| 70 | __be32 lvb_os_seqno; | ||
| 71 | }; | ||
| 72 | |||
| 65 | /* ocfs2_inode_lock_full() 'arg_flags' flags */ | 73 | /* ocfs2_inode_lock_full() 'arg_flags' flags */ |
| 66 | /* don't wait on recovery. */ | 74 | /* don't wait on recovery. */ |
| 67 | #define OCFS2_META_LOCK_RECOVERY (0x01) | 75 | #define OCFS2_META_LOCK_RECOVERY (0x01) |
| @@ -113,6 +121,9 @@ int ocfs2_super_lock(struct ocfs2_super *osb, | |||
| 113 | int ex); | 121 | int ex); |
| 114 | void ocfs2_super_unlock(struct ocfs2_super *osb, | 122 | void ocfs2_super_unlock(struct ocfs2_super *osb, |
| 115 | int ex); | 123 | int ex); |
| 124 | int ocfs2_orphan_scan_lock(struct ocfs2_super *osb, u32 *seqno, int ex); | ||
| 125 | void ocfs2_orphan_scan_unlock(struct ocfs2_super *osb, u32 seqno, int ex); | ||
| 126 | |||
| 116 | int ocfs2_rename_lock(struct ocfs2_super *osb); | 127 | int ocfs2_rename_lock(struct ocfs2_super *osb); |
| 117 | void ocfs2_rename_unlock(struct ocfs2_super *osb); | 128 | void ocfs2_rename_unlock(struct ocfs2_super *osb); |
| 118 | int ocfs2_nfs_sync_lock(struct ocfs2_super *osb, int ex); | 129 | int ocfs2_nfs_sync_lock(struct ocfs2_super *osb, int ex); |
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index c2a87c885b73..07267e0da909 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
| @@ -187,6 +187,9 @@ static int ocfs2_sync_file(struct file *file, | |||
| 187 | if (err) | 187 | if (err) |
| 188 | goto bail; | 188 | goto bail; |
| 189 | 189 | ||
| 190 | if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) | ||
| 191 | goto bail; | ||
| 192 | |||
| 190 | journal = osb->journal->j_journal; | 193 | journal = osb->journal->j_journal; |
| 191 | err = jbd2_journal_force_commit(journal); | 194 | err = jbd2_journal_force_commit(journal); |
| 192 | 195 | ||
| @@ -894,9 +897,9 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) | |||
| 894 | struct ocfs2_super *osb = OCFS2_SB(sb); | 897 | struct ocfs2_super *osb = OCFS2_SB(sb); |
| 895 | struct buffer_head *bh = NULL; | 898 | struct buffer_head *bh = NULL; |
| 896 | handle_t *handle = NULL; | 899 | handle_t *handle = NULL; |
| 897 | int locked[MAXQUOTAS] = {0, 0}; | 900 | int qtype; |
| 898 | int credits, qtype; | 901 | struct dquot *transfer_from[MAXQUOTAS] = { }; |
| 899 | struct ocfs2_mem_dqinfo *oinfo; | 902 | struct dquot *transfer_to[MAXQUOTAS] = { }; |
| 900 | 903 | ||
| 901 | mlog_entry("(0x%p, '%.*s')\n", dentry, | 904 | mlog_entry("(0x%p, '%.*s')\n", dentry, |
| 902 | dentry->d_name.len, dentry->d_name.name); | 905 | dentry->d_name.len, dentry->d_name.name); |
| @@ -969,30 +972,37 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) | |||
| 969 | 972 | ||
| 970 | if ((attr->ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) || | 973 | if ((attr->ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) || |
| 971 | (attr->ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) { | 974 | (attr->ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) { |
| 972 | credits = OCFS2_INODE_UPDATE_CREDITS; | 975 | /* |
| 976 | * Gather pointers to quota structures so that allocation / | ||
| 977 | * freeing of quota structures happens here and not inside | ||
| 978 | * vfs_dq_transfer() where we have problems with lock ordering | ||
| 979 | */ | ||
| 973 | if (attr->ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid | 980 | if (attr->ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid |
| 974 | && OCFS2_HAS_RO_COMPAT_FEATURE(sb, | 981 | && OCFS2_HAS_RO_COMPAT_FEATURE(sb, |
| 975 | OCFS2_FEATURE_RO_COMPAT_USRQUOTA)) { | 982 | OCFS2_FEATURE_RO_COMPAT_USRQUOTA)) { |
| 976 | oinfo = sb_dqinfo(sb, USRQUOTA)->dqi_priv; | 983 | transfer_to[USRQUOTA] = dqget(sb, attr->ia_uid, |
| 977 | status = ocfs2_lock_global_qf(oinfo, 1); | 984 | USRQUOTA); |
| 978 | if (status < 0) | 985 | transfer_from[USRQUOTA] = dqget(sb, inode->i_uid, |
| 986 | USRQUOTA); | ||
| 987 | if (!transfer_to[USRQUOTA] || !transfer_from[USRQUOTA]) { | ||
| 988 | status = -ESRCH; | ||
| 979 | goto bail_unlock; | 989 | goto bail_unlock; |
| 980 | credits += ocfs2_calc_qinit_credits(sb, USRQUOTA) + | 990 | } |
| 981 | ocfs2_calc_qdel_credits(sb, USRQUOTA); | ||
| 982 | locked[USRQUOTA] = 1; | ||
| 983 | } | 991 | } |
| 984 | if (attr->ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid | 992 | if (attr->ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid |
| 985 | && OCFS2_HAS_RO_COMPAT_FEATURE(sb, | 993 | && OCFS2_HAS_RO_COMPAT_FEATURE(sb, |
| 986 | OCFS2_FEATURE_RO_COMPAT_GRPQUOTA)) { | 994 | OCFS2_FEATURE_RO_COMPAT_GRPQUOTA)) { |
| 987 | oinfo = sb_dqinfo(sb, GRPQUOTA)->dqi_priv; | 995 | transfer_to[GRPQUOTA] = dqget(sb, attr->ia_gid, |
| 988 | status = ocfs2_lock_global_qf(oinfo, 1); | 996 | GRPQUOTA); |
| 989 | if (status < 0) | 997 | transfer_from[GRPQUOTA] = dqget(sb, inode->i_gid, |
| 998 | GRPQUOTA); | ||
| 999 | if (!transfer_to[GRPQUOTA] || !transfer_from[GRPQUOTA]) { | ||
| 1000 | status = -ESRCH; | ||
| 990 | goto bail_unlock; | 1001 | goto bail_unlock; |
| 991 | credits += ocfs2_calc_qinit_credits(sb, GRPQUOTA) + | 1002 | } |
| 992 | ocfs2_calc_qdel_credits(sb, GRPQUOTA); | ||
| 993 | locked[GRPQUOTA] = 1; | ||
| 994 | } | 1003 | } |
| 995 | handle = ocfs2_start_trans(osb, credits); | 1004 | handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS + |
| 1005 | 2 * ocfs2_quota_trans_credits(sb)); | ||
| 996 | if (IS_ERR(handle)) { | 1006 | if (IS_ERR(handle)) { |
| 997 | status = PTR_ERR(handle); | 1007 | status = PTR_ERR(handle); |
| 998 | mlog_errno(status); | 1008 | mlog_errno(status); |
| @@ -1030,12 +1040,6 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) | |||
| 1030 | bail_commit: | 1040 | bail_commit: |
| 1031 | ocfs2_commit_trans(osb, handle); | 1041 | ocfs2_commit_trans(osb, handle); |
| 1032 | bail_unlock: | 1042 | bail_unlock: |
| 1033 | for (qtype = 0; qtype < MAXQUOTAS; qtype++) { | ||
| 1034 | if (!locked[qtype]) | ||
| 1035 | continue; | ||
| 1036 | oinfo = sb_dqinfo(sb, qtype)->dqi_priv; | ||
| 1037 | ocfs2_unlock_global_qf(oinfo, 1); | ||
| 1038 | } | ||
| 1039 | ocfs2_inode_unlock(inode, 1); | 1043 | ocfs2_inode_unlock(inode, 1); |
| 1040 | bail_unlock_rw: | 1044 | bail_unlock_rw: |
| 1041 | if (size_change) | 1045 | if (size_change) |
| @@ -1043,6 +1047,12 @@ bail_unlock_rw: | |||
| 1043 | bail: | 1047 | bail: |
| 1044 | brelse(bh); | 1048 | brelse(bh); |
| 1045 | 1049 | ||
| 1050 | /* Release quota pointers in case we acquired them */ | ||
| 1051 | for (qtype = 0; qtype < MAXQUOTAS; qtype++) { | ||
| 1052 | dqput(transfer_to[qtype]); | ||
| 1053 | dqput(transfer_from[qtype]); | ||
| 1054 | } | ||
| 1055 | |||
| 1046 | if (!status && attr->ia_valid & ATTR_MODE) { | 1056 | if (!status && attr->ia_valid & ATTR_MODE) { |
| 1047 | status = ocfs2_acl_chmod(inode); | 1057 | status = ocfs2_acl_chmod(inode); |
| 1048 | if (status < 0) | 1058 | if (status < 0) |
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index a20a0f1e37fd..4a3b9e6b31ad 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c | |||
| @@ -28,6 +28,8 @@ | |||
| 28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
| 29 | #include <linux/highmem.h> | 29 | #include <linux/highmem.h> |
| 30 | #include <linux/kthread.h> | 30 | #include <linux/kthread.h> |
| 31 | #include <linux/time.h> | ||
| 32 | #include <linux/random.h> | ||
| 31 | 33 | ||
| 32 | #define MLOG_MASK_PREFIX ML_JOURNAL | 34 | #define MLOG_MASK_PREFIX ML_JOURNAL |
| 33 | #include <cluster/masklog.h> | 35 | #include <cluster/masklog.h> |
| @@ -52,6 +54,8 @@ | |||
| 52 | 54 | ||
| 53 | DEFINE_SPINLOCK(trans_inc_lock); | 55 | DEFINE_SPINLOCK(trans_inc_lock); |
| 54 | 56 | ||
| 57 | #define ORPHAN_SCAN_SCHEDULE_TIMEOUT 300000 | ||
| 58 | |||
| 55 | static int ocfs2_force_read_journal(struct inode *inode); | 59 | static int ocfs2_force_read_journal(struct inode *inode); |
| 56 | static int ocfs2_recover_node(struct ocfs2_super *osb, | 60 | static int ocfs2_recover_node(struct ocfs2_super *osb, |
| 57 | int node_num, int slot_num); | 61 | int node_num, int slot_num); |
| @@ -1841,6 +1845,113 @@ bail: | |||
| 1841 | return status; | 1845 | return status; |
| 1842 | } | 1846 | } |
| 1843 | 1847 | ||
| 1848 | /* | ||
| 1849 | * Scan timer should get fired every ORPHAN_SCAN_SCHEDULE_TIMEOUT. Add some | ||
| 1850 | * randomness to the timeout to minimize multple nodes firing the timer at the | ||
| 1851 | * same time. | ||
| 1852 | */ | ||
| 1853 | static inline unsigned long ocfs2_orphan_scan_timeout(void) | ||
| 1854 | { | ||
| 1855 | unsigned long time; | ||
| 1856 | |||
| 1857 | get_random_bytes(&time, sizeof(time)); | ||
| 1858 | time = ORPHAN_SCAN_SCHEDULE_TIMEOUT + (time % 5000); | ||
| 1859 | return msecs_to_jiffies(time); | ||
| 1860 | } | ||
| 1861 | |||
| 1862 | /* | ||
| 1863 | * ocfs2_queue_orphan_scan calls ocfs2_queue_recovery_completion for | ||
| 1864 | * every slot, queuing a recovery of the slot on the ocfs2_wq thread. This | ||
| 1865 | * is done to catch any orphans that are left over in orphan directories. | ||
| 1866 | * | ||
| 1867 | * ocfs2_queue_orphan_scan gets called every ORPHAN_SCAN_SCHEDULE_TIMEOUT | ||
| 1868 | * seconds. It gets an EX lock on os_lockres and checks sequence number | ||
| 1869 | * stored in LVB. If the sequence number has changed, it means some other | ||
| 1870 | * node has done the scan. This node skips the scan and tracks the | ||
| 1871 | * sequence number. If the sequence number didn't change, it means a scan | ||
| 1872 | * hasn't happened. The node queues a scan and increments the | ||
| 1873 | * sequence number in the LVB. | ||
| 1874 | */ | ||
| 1875 | void ocfs2_queue_orphan_scan(struct ocfs2_super *osb) | ||
| 1876 | { | ||
| 1877 | struct ocfs2_orphan_scan *os; | ||
| 1878 | int status, i; | ||
| 1879 | u32 seqno = 0; | ||
| 1880 | |||
| 1881 | os = &osb->osb_orphan_scan; | ||
| 1882 | |||
| 1883 | status = ocfs2_orphan_scan_lock(osb, &seqno, DLM_LOCK_EX); | ||
| 1884 | if (status < 0) { | ||
| 1885 | if (status != -EAGAIN) | ||
| 1886 | mlog_errno(status); | ||
| 1887 | goto out; | ||
| 1888 | } | ||
| 1889 | |||
| 1890 | if (os->os_seqno != seqno) { | ||
| 1891 | os->os_seqno = seqno; | ||
| 1892 | goto unlock; | ||
| 1893 | } | ||
| 1894 | |||
| 1895 | for (i = 0; i < osb->max_slots; i++) | ||
| 1896 | ocfs2_queue_recovery_completion(osb->journal, i, NULL, NULL, | ||
| 1897 | NULL); | ||
| 1898 | /* | ||
| 1899 | * We queued a recovery on orphan slots, increment the sequence | ||
| 1900 | * number and update LVB so other node will skip the scan for a while | ||
| 1901 | */ | ||
| 1902 | seqno++; | ||
| 1903 | os->os_count++; | ||
| 1904 | os->os_scantime = CURRENT_TIME; | ||
| 1905 | unlock: | ||
| 1906 | ocfs2_orphan_scan_unlock(osb, seqno, DLM_LOCK_EX); | ||
| 1907 | out: | ||
| 1908 | return; | ||
| 1909 | } | ||
| 1910 | |||
| 1911 | /* Worker task that gets fired every ORPHAN_SCAN_SCHEDULE_TIMEOUT millsec */ | ||
| 1912 | void ocfs2_orphan_scan_work(struct work_struct *work) | ||
| 1913 | { | ||
| 1914 | struct ocfs2_orphan_scan *os; | ||
| 1915 | struct ocfs2_super *osb; | ||
| 1916 | |||
| 1917 | os = container_of(work, struct ocfs2_orphan_scan, | ||
| 1918 | os_orphan_scan_work.work); | ||
| 1919 | osb = os->os_osb; | ||
| 1920 | |||
| 1921 | mutex_lock(&os->os_lock); | ||
| 1922 | ocfs2_queue_orphan_scan(osb); | ||
| 1923 | schedule_delayed_work(&os->os_orphan_scan_work, | ||
| 1924 | ocfs2_orphan_scan_timeout()); | ||
| 1925 | mutex_unlock(&os->os_lock); | ||
| 1926 | } | ||
| 1927 | |||
| 1928 | void ocfs2_orphan_scan_stop(struct ocfs2_super *osb) | ||
| 1929 | { | ||
| 1930 | struct ocfs2_orphan_scan *os; | ||
| 1931 | |||
| 1932 | os = &osb->osb_orphan_scan; | ||
| 1933 | mutex_lock(&os->os_lock); | ||
| 1934 | cancel_delayed_work(&os->os_orphan_scan_work); | ||
| 1935 | mutex_unlock(&os->os_lock); | ||
| 1936 | } | ||
| 1937 | |||
| 1938 | int ocfs2_orphan_scan_init(struct ocfs2_super *osb) | ||
| 1939 | { | ||
| 1940 | struct ocfs2_orphan_scan *os; | ||
| 1941 | |||
| 1942 | os = &osb->osb_orphan_scan; | ||
| 1943 | os->os_osb = osb; | ||
| 1944 | os->os_count = 0; | ||
| 1945 | os->os_scantime = CURRENT_TIME; | ||
| 1946 | mutex_init(&os->os_lock); | ||
| 1947 | |||
| 1948 | INIT_DELAYED_WORK(&os->os_orphan_scan_work, | ||
| 1949 | ocfs2_orphan_scan_work); | ||
| 1950 | schedule_delayed_work(&os->os_orphan_scan_work, | ||
| 1951 | ocfs2_orphan_scan_timeout()); | ||
| 1952 | return 0; | ||
| 1953 | } | ||
| 1954 | |||
| 1844 | struct ocfs2_orphan_filldir_priv { | 1955 | struct ocfs2_orphan_filldir_priv { |
| 1845 | struct inode *head; | 1956 | struct inode *head; |
| 1846 | struct ocfs2_super *osb; | 1957 | struct ocfs2_super *osb; |
diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h index eb7b76331eb7..61045eeb3f6e 100644 --- a/fs/ocfs2/journal.h +++ b/fs/ocfs2/journal.h | |||
| @@ -144,6 +144,10 @@ static inline void ocfs2_inode_set_new(struct ocfs2_super *osb, | |||
| 144 | } | 144 | } |
| 145 | 145 | ||
| 146 | /* Exported only for the journal struct init code in super.c. Do not call. */ | 146 | /* Exported only for the journal struct init code in super.c. Do not call. */ |
| 147 | int ocfs2_orphan_scan_init(struct ocfs2_super *osb); | ||
| 148 | void ocfs2_orphan_scan_stop(struct ocfs2_super *osb); | ||
| 149 | void ocfs2_orphan_scan_exit(struct ocfs2_super *osb); | ||
| 150 | |||
| 147 | void ocfs2_complete_recovery(struct work_struct *work); | 151 | void ocfs2_complete_recovery(struct work_struct *work); |
| 148 | void ocfs2_wait_for_recovery(struct ocfs2_super *osb); | 152 | void ocfs2_wait_for_recovery(struct ocfs2_super *osb); |
| 149 | 153 | ||
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index 1386281950db..18c1d9ec1c93 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h | |||
| @@ -47,6 +47,9 @@ | |||
| 47 | #include "ocfs2_fs.h" | 47 | #include "ocfs2_fs.h" |
| 48 | #include "ocfs2_lockid.h" | 48 | #include "ocfs2_lockid.h" |
| 49 | 49 | ||
| 50 | /* For struct ocfs2_blockcheck_stats */ | ||
| 51 | #include "blockcheck.h" | ||
| 52 | |||
| 50 | /* Most user visible OCFS2 inodes will have very few pieces of | 53 | /* Most user visible OCFS2 inodes will have very few pieces of |
| 51 | * metadata, but larger files (including bitmaps, etc) must be taken | 54 | * metadata, but larger files (including bitmaps, etc) must be taken |
| 52 | * into account when designing an access scheme. We allow a small | 55 | * into account when designing an access scheme. We allow a small |
| @@ -151,6 +154,16 @@ struct ocfs2_lock_res { | |||
| 151 | #endif | 154 | #endif |
| 152 | }; | 155 | }; |
| 153 | 156 | ||
| 157 | struct ocfs2_orphan_scan { | ||
| 158 | struct mutex os_lock; | ||
| 159 | struct ocfs2_super *os_osb; | ||
| 160 | struct ocfs2_lock_res os_lockres; /* lock to synchronize scans */ | ||
| 161 | struct delayed_work os_orphan_scan_work; | ||
| 162 | struct timespec os_scantime; /* time this node ran the scan */ | ||
| 163 | u32 os_count; /* tracks node specific scans */ | ||
| 164 | u32 os_seqno; /* tracks cluster wide scans */ | ||
| 165 | }; | ||
| 166 | |||
| 154 | struct ocfs2_dlm_debug { | 167 | struct ocfs2_dlm_debug { |
| 155 | struct kref d_refcnt; | 168 | struct kref d_refcnt; |
| 156 | struct dentry *d_locking_state; | 169 | struct dentry *d_locking_state; |
| @@ -295,6 +308,7 @@ struct ocfs2_super | |||
| 295 | struct ocfs2_dinode *local_alloc_copy; | 308 | struct ocfs2_dinode *local_alloc_copy; |
| 296 | struct ocfs2_quota_recovery *quota_rec; | 309 | struct ocfs2_quota_recovery *quota_rec; |
| 297 | 310 | ||
| 311 | struct ocfs2_blockcheck_stats osb_ecc_stats; | ||
| 298 | struct ocfs2_alloc_stats alloc_stats; | 312 | struct ocfs2_alloc_stats alloc_stats; |
| 299 | char dev_str[20]; /* "major,minor" of the device */ | 313 | char dev_str[20]; /* "major,minor" of the device */ |
| 300 | 314 | ||
| @@ -341,6 +355,8 @@ struct ocfs2_super | |||
| 341 | unsigned int *osb_orphan_wipes; | 355 | unsigned int *osb_orphan_wipes; |
| 342 | wait_queue_head_t osb_wipe_event; | 356 | wait_queue_head_t osb_wipe_event; |
| 343 | 357 | ||
| 358 | struct ocfs2_orphan_scan osb_orphan_scan; | ||
| 359 | |||
| 344 | /* used to protect metaecc calculation check of xattr. */ | 360 | /* used to protect metaecc calculation check of xattr. */ |
| 345 | spinlock_t osb_xattr_lock; | 361 | spinlock_t osb_xattr_lock; |
| 346 | 362 | ||
diff --git a/fs/ocfs2/ocfs2_lockid.h b/fs/ocfs2/ocfs2_lockid.h index a53ce87481bf..fcdba091af3d 100644 --- a/fs/ocfs2/ocfs2_lockid.h +++ b/fs/ocfs2/ocfs2_lockid.h | |||
| @@ -48,6 +48,7 @@ enum ocfs2_lock_type { | |||
| 48 | OCFS2_LOCK_TYPE_FLOCK, | 48 | OCFS2_LOCK_TYPE_FLOCK, |
| 49 | OCFS2_LOCK_TYPE_QINFO, | 49 | OCFS2_LOCK_TYPE_QINFO, |
| 50 | OCFS2_LOCK_TYPE_NFS_SYNC, | 50 | OCFS2_LOCK_TYPE_NFS_SYNC, |
| 51 | OCFS2_LOCK_TYPE_ORPHAN_SCAN, | ||
| 51 | OCFS2_NUM_LOCK_TYPES | 52 | OCFS2_NUM_LOCK_TYPES |
| 52 | }; | 53 | }; |
| 53 | 54 | ||
| @@ -85,6 +86,9 @@ static inline char ocfs2_lock_type_char(enum ocfs2_lock_type type) | |||
| 85 | case OCFS2_LOCK_TYPE_NFS_SYNC: | 86 | case OCFS2_LOCK_TYPE_NFS_SYNC: |
| 86 | c = 'Y'; | 87 | c = 'Y'; |
| 87 | break; | 88 | break; |
| 89 | case OCFS2_LOCK_TYPE_ORPHAN_SCAN: | ||
| 90 | c = 'P'; | ||
| 91 | break; | ||
| 88 | default: | 92 | default: |
| 89 | c = '\0'; | 93 | c = '\0'; |
| 90 | } | 94 | } |
| @@ -104,6 +108,7 @@ static char *ocfs2_lock_type_strings[] = { | |||
| 104 | [OCFS2_LOCK_TYPE_OPEN] = "Open", | 108 | [OCFS2_LOCK_TYPE_OPEN] = "Open", |
| 105 | [OCFS2_LOCK_TYPE_FLOCK] = "Flock", | 109 | [OCFS2_LOCK_TYPE_FLOCK] = "Flock", |
| 106 | [OCFS2_LOCK_TYPE_QINFO] = "Quota", | 110 | [OCFS2_LOCK_TYPE_QINFO] = "Quota", |
| 111 | [OCFS2_LOCK_TYPE_ORPHAN_SCAN] = "OrphanScan", | ||
| 107 | }; | 112 | }; |
| 108 | 113 | ||
| 109 | static inline const char *ocfs2_lock_type_string(enum ocfs2_lock_type type) | 114 | static inline const char *ocfs2_lock_type_string(enum ocfs2_lock_type type) |
diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c index 1ed0f7c86869..edfa60cd155c 100644 --- a/fs/ocfs2/quota_global.c +++ b/fs/ocfs2/quota_global.c | |||
| @@ -421,6 +421,7 @@ int ocfs2_global_read_dquot(struct dquot *dquot) | |||
| 421 | OCFS2_DQUOT(dquot)->dq_originodes = dquot->dq_dqb.dqb_curinodes; | 421 | OCFS2_DQUOT(dquot)->dq_originodes = dquot->dq_dqb.dqb_curinodes; |
| 422 | if (!dquot->dq_off) { /* No real quota entry? */ | 422 | if (!dquot->dq_off) { /* No real quota entry? */ |
| 423 | /* Upgrade to exclusive lock for allocation */ | 423 | /* Upgrade to exclusive lock for allocation */ |
| 424 | ocfs2_qinfo_unlock(info, 0); | ||
| 424 | err = ocfs2_qinfo_lock(info, 1); | 425 | err = ocfs2_qinfo_lock(info, 1); |
| 425 | if (err < 0) | 426 | if (err < 0) |
| 426 | goto out_qlock; | 427 | goto out_qlock; |
| @@ -435,7 +436,8 @@ int ocfs2_global_read_dquot(struct dquot *dquot) | |||
| 435 | out_qlock: | 436 | out_qlock: |
| 436 | if (ex) | 437 | if (ex) |
| 437 | ocfs2_qinfo_unlock(info, 1); | 438 | ocfs2_qinfo_unlock(info, 1); |
| 438 | ocfs2_qinfo_unlock(info, 0); | 439 | else |
| 440 | ocfs2_qinfo_unlock(info, 0); | ||
| 439 | out: | 441 | out: |
| 440 | if (err < 0) | 442 | if (err < 0) |
| 441 | mlog_errno(err); | 443 | mlog_errno(err); |
diff --git a/fs/ocfs2/quota_local.c b/fs/ocfs2/quota_local.c index 07deec5e9721..5a460fa82553 100644 --- a/fs/ocfs2/quota_local.c +++ b/fs/ocfs2/quota_local.c | |||
| @@ -444,10 +444,6 @@ static int ocfs2_recover_local_quota_file(struct inode *lqinode, | |||
| 444 | 444 | ||
| 445 | mlog_entry("ino=%lu type=%u", (unsigned long)lqinode->i_ino, type); | 445 | mlog_entry("ino=%lu type=%u", (unsigned long)lqinode->i_ino, type); |
| 446 | 446 | ||
| 447 | status = ocfs2_lock_global_qf(oinfo, 1); | ||
| 448 | if (status < 0) | ||
| 449 | goto out; | ||
| 450 | |||
| 451 | list_for_each_entry_safe(rchunk, next, &(rec->r_list[type]), rc_list) { | 447 | list_for_each_entry_safe(rchunk, next, &(rec->r_list[type]), rc_list) { |
| 452 | chunk = rchunk->rc_chunk; | 448 | chunk = rchunk->rc_chunk; |
| 453 | hbh = NULL; | 449 | hbh = NULL; |
| @@ -480,12 +476,18 @@ static int ocfs2_recover_local_quota_file(struct inode *lqinode, | |||
| 480 | type); | 476 | type); |
| 481 | goto out_put_bh; | 477 | goto out_put_bh; |
| 482 | } | 478 | } |
| 479 | status = ocfs2_lock_global_qf(oinfo, 1); | ||
| 480 | if (status < 0) { | ||
| 481 | mlog_errno(status); | ||
| 482 | goto out_put_dquot; | ||
| 483 | } | ||
| 484 | |||
| 483 | handle = ocfs2_start_trans(OCFS2_SB(sb), | 485 | handle = ocfs2_start_trans(OCFS2_SB(sb), |
| 484 | OCFS2_QSYNC_CREDITS); | 486 | OCFS2_QSYNC_CREDITS); |
| 485 | if (IS_ERR(handle)) { | 487 | if (IS_ERR(handle)) { |
| 486 | status = PTR_ERR(handle); | 488 | status = PTR_ERR(handle); |
| 487 | mlog_errno(status); | 489 | mlog_errno(status); |
| 488 | goto out_put_dquot; | 490 | goto out_drop_lock; |
| 489 | } | 491 | } |
| 490 | mutex_lock(&sb_dqopt(sb)->dqio_mutex); | 492 | mutex_lock(&sb_dqopt(sb)->dqio_mutex); |
| 491 | spin_lock(&dq_data_lock); | 493 | spin_lock(&dq_data_lock); |
| @@ -523,6 +525,8 @@ static int ocfs2_recover_local_quota_file(struct inode *lqinode, | |||
| 523 | out_commit: | 525 | out_commit: |
| 524 | mutex_unlock(&sb_dqopt(sb)->dqio_mutex); | 526 | mutex_unlock(&sb_dqopt(sb)->dqio_mutex); |
| 525 | ocfs2_commit_trans(OCFS2_SB(sb), handle); | 527 | ocfs2_commit_trans(OCFS2_SB(sb), handle); |
| 528 | out_drop_lock: | ||
| 529 | ocfs2_unlock_global_qf(oinfo, 1); | ||
| 526 | out_put_dquot: | 530 | out_put_dquot: |
| 527 | dqput(dquot); | 531 | dqput(dquot); |
| 528 | out_put_bh: | 532 | out_put_bh: |
| @@ -537,8 +541,6 @@ out_put_bh: | |||
| 537 | if (status < 0) | 541 | if (status < 0) |
| 538 | break; | 542 | break; |
| 539 | } | 543 | } |
| 540 | ocfs2_unlock_global_qf(oinfo, 1); | ||
| 541 | out: | ||
| 542 | if (status < 0) | 544 | if (status < 0) |
| 543 | free_recovery_list(&(rec->r_list[type])); | 545 | free_recovery_list(&(rec->r_list[type])); |
| 544 | mlog_exit(status); | 546 | mlog_exit(status); |
| @@ -655,6 +657,9 @@ static int ocfs2_local_read_info(struct super_block *sb, int type) | |||
| 655 | struct ocfs2_quota_recovery *rec; | 657 | struct ocfs2_quota_recovery *rec; |
| 656 | int locked = 0; | 658 | int locked = 0; |
| 657 | 659 | ||
| 660 | /* We don't need the lock and we have to acquire quota file locks | ||
| 661 | * which will later depend on this lock */ | ||
| 662 | mutex_unlock(&sb_dqopt(sb)->dqio_mutex); | ||
| 658 | info->dqi_maxblimit = 0x7fffffffffffffffLL; | 663 | info->dqi_maxblimit = 0x7fffffffffffffffLL; |
| 659 | info->dqi_maxilimit = 0x7fffffffffffffffLL; | 664 | info->dqi_maxilimit = 0x7fffffffffffffffLL; |
| 660 | oinfo = kmalloc(sizeof(struct ocfs2_mem_dqinfo), GFP_NOFS); | 665 | oinfo = kmalloc(sizeof(struct ocfs2_mem_dqinfo), GFP_NOFS); |
| @@ -733,6 +738,7 @@ static int ocfs2_local_read_info(struct super_block *sb, int type) | |||
| 733 | goto out_err; | 738 | goto out_err; |
| 734 | } | 739 | } |
| 735 | 740 | ||
| 741 | mutex_lock(&sb_dqopt(sb)->dqio_mutex); | ||
| 736 | return 0; | 742 | return 0; |
| 737 | out_err: | 743 | out_err: |
| 738 | if (oinfo) { | 744 | if (oinfo) { |
| @@ -746,6 +752,7 @@ out_err: | |||
| 746 | kfree(oinfo); | 752 | kfree(oinfo); |
| 747 | } | 753 | } |
| 748 | brelse(bh); | 754 | brelse(bh); |
| 755 | mutex_lock(&sb_dqopt(sb)->dqio_mutex); | ||
| 749 | return -1; | 756 | return -1; |
| 750 | } | 757 | } |
| 751 | 758 | ||
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 201b40a441fe..d33767f17ba3 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c | |||
| @@ -119,10 +119,12 @@ static void ocfs2_release_system_inodes(struct ocfs2_super *osb); | |||
| 119 | static int ocfs2_check_volume(struct ocfs2_super *osb); | 119 | static int ocfs2_check_volume(struct ocfs2_super *osb); |
| 120 | static int ocfs2_verify_volume(struct ocfs2_dinode *di, | 120 | static int ocfs2_verify_volume(struct ocfs2_dinode *di, |
| 121 | struct buffer_head *bh, | 121 | struct buffer_head *bh, |
| 122 | u32 sectsize); | 122 | u32 sectsize, |
| 123 | struct ocfs2_blockcheck_stats *stats); | ||
| 123 | static int ocfs2_initialize_super(struct super_block *sb, | 124 | static int ocfs2_initialize_super(struct super_block *sb, |
| 124 | struct buffer_head *bh, | 125 | struct buffer_head *bh, |
| 125 | int sector_size); | 126 | int sector_size, |
| 127 | struct ocfs2_blockcheck_stats *stats); | ||
| 126 | static int ocfs2_get_sector(struct super_block *sb, | 128 | static int ocfs2_get_sector(struct super_block *sb, |
| 127 | struct buffer_head **bh, | 129 | struct buffer_head **bh, |
| 128 | int block, | 130 | int block, |
| @@ -207,6 +209,7 @@ static int ocfs2_osb_dump(struct ocfs2_super *osb, char *buf, int len) | |||
| 207 | int i; | 209 | int i; |
| 208 | struct ocfs2_cluster_connection *cconn = osb->cconn; | 210 | struct ocfs2_cluster_connection *cconn = osb->cconn; |
| 209 | struct ocfs2_recovery_map *rm = osb->recovery_map; | 211 | struct ocfs2_recovery_map *rm = osb->recovery_map; |
| 212 | struct ocfs2_orphan_scan *os; | ||
| 210 | 213 | ||
| 211 | out += snprintf(buf + out, len - out, | 214 | out += snprintf(buf + out, len - out, |
| 212 | "%10s => Id: %-s Uuid: %-s Gen: 0x%X Label: %-s\n", | 215 | "%10s => Id: %-s Uuid: %-s Gen: 0x%X Label: %-s\n", |
| @@ -308,6 +311,13 @@ static int ocfs2_osb_dump(struct ocfs2_super *osb, char *buf, int len) | |||
| 308 | i, osb->slot_recovery_generations[i]); | 311 | i, osb->slot_recovery_generations[i]); |
| 309 | } | 312 | } |
| 310 | 313 | ||
| 314 | os = &osb->osb_orphan_scan; | ||
| 315 | out += snprintf(buf + out, len - out, "Orphan Scan=> "); | ||
| 316 | out += snprintf(buf + out, len - out, "Local: %u Global: %u ", | ||
| 317 | os->os_count, os->os_seqno); | ||
| 318 | out += snprintf(buf + out, len - out, " Last Scan: %lu seconds ago\n", | ||
| 319 | (get_seconds() - os->os_scantime.tv_sec)); | ||
| 320 | |||
| 311 | return out; | 321 | return out; |
| 312 | } | 322 | } |
| 313 | 323 | ||
| @@ -693,7 +703,8 @@ out: | |||
| 693 | 703 | ||
| 694 | static int ocfs2_sb_probe(struct super_block *sb, | 704 | static int ocfs2_sb_probe(struct super_block *sb, |
| 695 | struct buffer_head **bh, | 705 | struct buffer_head **bh, |
| 696 | int *sector_size) | 706 | int *sector_size, |
| 707 | struct ocfs2_blockcheck_stats *stats) | ||
| 697 | { | 708 | { |
| 698 | int status, tmpstat; | 709 | int status, tmpstat; |
| 699 | struct ocfs1_vol_disk_hdr *hdr; | 710 | struct ocfs1_vol_disk_hdr *hdr; |
| @@ -759,7 +770,8 @@ static int ocfs2_sb_probe(struct super_block *sb, | |||
| 759 | goto bail; | 770 | goto bail; |
| 760 | } | 771 | } |
| 761 | di = (struct ocfs2_dinode *) (*bh)->b_data; | 772 | di = (struct ocfs2_dinode *) (*bh)->b_data; |
| 762 | status = ocfs2_verify_volume(di, *bh, blksize); | 773 | memset(stats, 0, sizeof(struct ocfs2_blockcheck_stats)); |
| 774 | status = ocfs2_verify_volume(di, *bh, blksize, stats); | ||
| 763 | if (status >= 0) | 775 | if (status >= 0) |
| 764 | goto bail; | 776 | goto bail; |
| 765 | brelse(*bh); | 777 | brelse(*bh); |
| @@ -965,6 +977,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) | |||
| 965 | struct ocfs2_super *osb = NULL; | 977 | struct ocfs2_super *osb = NULL; |
| 966 | struct buffer_head *bh = NULL; | 978 | struct buffer_head *bh = NULL; |
| 967 | char nodestr[8]; | 979 | char nodestr[8]; |
| 980 | struct ocfs2_blockcheck_stats stats; | ||
| 968 | 981 | ||
| 969 | mlog_entry("%p, %p, %i", sb, data, silent); | 982 | mlog_entry("%p, %p, %i", sb, data, silent); |
| 970 | 983 | ||
| @@ -974,13 +987,13 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) | |||
| 974 | } | 987 | } |
| 975 | 988 | ||
| 976 | /* probe for superblock */ | 989 | /* probe for superblock */ |
| 977 | status = ocfs2_sb_probe(sb, &bh, §or_size); | 990 | status = ocfs2_sb_probe(sb, &bh, §or_size, &stats); |
| 978 | if (status < 0) { | 991 | if (status < 0) { |
| 979 | mlog(ML_ERROR, "superblock probe failed!\n"); | 992 | mlog(ML_ERROR, "superblock probe failed!\n"); |
| 980 | goto read_super_error; | 993 | goto read_super_error; |
| 981 | } | 994 | } |
| 982 | 995 | ||
| 983 | status = ocfs2_initialize_super(sb, bh, sector_size); | 996 | status = ocfs2_initialize_super(sb, bh, sector_size, &stats); |
| 984 | osb = OCFS2_SB(sb); | 997 | osb = OCFS2_SB(sb); |
| 985 | if (status < 0) { | 998 | if (status < 0) { |
| 986 | mlog_errno(status); | 999 | mlog_errno(status); |
| @@ -1090,6 +1103,18 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) | |||
| 1090 | goto read_super_error; | 1103 | goto read_super_error; |
| 1091 | } | 1104 | } |
| 1092 | 1105 | ||
| 1106 | if (ocfs2_meta_ecc(osb)) { | ||
| 1107 | status = ocfs2_blockcheck_stats_debugfs_install( | ||
| 1108 | &osb->osb_ecc_stats, | ||
| 1109 | osb->osb_debug_root); | ||
| 1110 | if (status) { | ||
| 1111 | mlog(ML_ERROR, | ||
| 1112 | "Unable to create blockcheck statistics " | ||
| 1113 | "files\n"); | ||
| 1114 | goto read_super_error; | ||
| 1115 | } | ||
| 1116 | } | ||
| 1117 | |||
| 1093 | status = ocfs2_mount_volume(sb); | 1118 | status = ocfs2_mount_volume(sb); |
| 1094 | if (osb->root_inode) | 1119 | if (osb->root_inode) |
| 1095 | inode = igrab(osb->root_inode); | 1120 | inode = igrab(osb->root_inode); |
| @@ -1760,13 +1785,8 @@ static int ocfs2_mount_volume(struct super_block *sb) | |||
| 1760 | } | 1785 | } |
| 1761 | 1786 | ||
| 1762 | status = ocfs2_truncate_log_init(osb); | 1787 | status = ocfs2_truncate_log_init(osb); |
| 1763 | if (status < 0) { | 1788 | if (status < 0) |
| 1764 | mlog_errno(status); | 1789 | mlog_errno(status); |
| 1765 | goto leave; | ||
| 1766 | } | ||
| 1767 | |||
| 1768 | if (ocfs2_mount_local(osb)) | ||
| 1769 | goto leave; | ||
| 1770 | 1790 | ||
| 1771 | leave: | 1791 | leave: |
| 1772 | if (unlock_super) | 1792 | if (unlock_super) |
| @@ -1796,6 +1816,8 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err) | |||
| 1796 | 1816 | ||
| 1797 | ocfs2_truncate_log_shutdown(osb); | 1817 | ocfs2_truncate_log_shutdown(osb); |
| 1798 | 1818 | ||
| 1819 | ocfs2_orphan_scan_stop(osb); | ||
| 1820 | |||
| 1799 | /* This will disable recovery and flush any recovery work. */ | 1821 | /* This will disable recovery and flush any recovery work. */ |
| 1800 | ocfs2_recovery_exit(osb); | 1822 | ocfs2_recovery_exit(osb); |
| 1801 | 1823 | ||
| @@ -1833,6 +1855,7 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err) | |||
| 1833 | if (osb->cconn) | 1855 | if (osb->cconn) |
| 1834 | ocfs2_dlm_shutdown(osb, hangup_needed); | 1856 | ocfs2_dlm_shutdown(osb, hangup_needed); |
| 1835 | 1857 | ||
| 1858 | ocfs2_blockcheck_stats_debugfs_remove(&osb->osb_ecc_stats); | ||
| 1836 | debugfs_remove(osb->osb_debug_root); | 1859 | debugfs_remove(osb->osb_debug_root); |
| 1837 | 1860 | ||
| 1838 | if (hangup_needed) | 1861 | if (hangup_needed) |
| @@ -1880,7 +1903,8 @@ static int ocfs2_setup_osb_uuid(struct ocfs2_super *osb, const unsigned char *uu | |||
| 1880 | 1903 | ||
| 1881 | static int ocfs2_initialize_super(struct super_block *sb, | 1904 | static int ocfs2_initialize_super(struct super_block *sb, |
| 1882 | struct buffer_head *bh, | 1905 | struct buffer_head *bh, |
| 1883 | int sector_size) | 1906 | int sector_size, |
| 1907 | struct ocfs2_blockcheck_stats *stats) | ||
| 1884 | { | 1908 | { |
| 1885 | int status; | 1909 | int status; |
| 1886 | int i, cbits, bbits; | 1910 | int i, cbits, bbits; |
| @@ -1939,6 +1963,9 @@ static int ocfs2_initialize_super(struct super_block *sb, | |||
| 1939 | atomic_set(&osb->alloc_stats.bg_allocs, 0); | 1963 | atomic_set(&osb->alloc_stats.bg_allocs, 0); |
| 1940 | atomic_set(&osb->alloc_stats.bg_extends, 0); | 1964 | atomic_set(&osb->alloc_stats.bg_extends, 0); |
| 1941 | 1965 | ||
| 1966 | /* Copy the blockcheck stats from the superblock probe */ | ||
| 1967 | osb->osb_ecc_stats = *stats; | ||
| 1968 | |||
| 1942 | ocfs2_init_node_maps(osb); | 1969 | ocfs2_init_node_maps(osb); |
| 1943 | 1970 | ||
| 1944 | snprintf(osb->dev_str, sizeof(osb->dev_str), "%u,%u", | 1971 | snprintf(osb->dev_str, sizeof(osb->dev_str), "%u,%u", |
| @@ -1951,6 +1978,13 @@ static int ocfs2_initialize_super(struct super_block *sb, | |||
| 1951 | goto bail; | 1978 | goto bail; |
| 1952 | } | 1979 | } |
| 1953 | 1980 | ||
| 1981 | status = ocfs2_orphan_scan_init(osb); | ||
| 1982 | if (status) { | ||
| 1983 | mlog(ML_ERROR, "Unable to initialize delayed orphan scan\n"); | ||
| 1984 | mlog_errno(status); | ||
| 1985 | goto bail; | ||
| 1986 | } | ||
| 1987 | |||
| 1954 | init_waitqueue_head(&osb->checkpoint_event); | 1988 | init_waitqueue_head(&osb->checkpoint_event); |
| 1955 | atomic_set(&osb->needs_checkpoint, 0); | 1989 | atomic_set(&osb->needs_checkpoint, 0); |
| 1956 | 1990 | ||
| @@ -2169,7 +2203,8 @@ bail: | |||
| 2169 | */ | 2203 | */ |
| 2170 | static int ocfs2_verify_volume(struct ocfs2_dinode *di, | 2204 | static int ocfs2_verify_volume(struct ocfs2_dinode *di, |
| 2171 | struct buffer_head *bh, | 2205 | struct buffer_head *bh, |
| 2172 | u32 blksz) | 2206 | u32 blksz, |
| 2207 | struct ocfs2_blockcheck_stats *stats) | ||
| 2173 | { | 2208 | { |
| 2174 | int status = -EAGAIN; | 2209 | int status = -EAGAIN; |
| 2175 | 2210 | ||
| @@ -2182,7 +2217,8 @@ static int ocfs2_verify_volume(struct ocfs2_dinode *di, | |||
| 2182 | OCFS2_FEATURE_INCOMPAT_META_ECC) { | 2217 | OCFS2_FEATURE_INCOMPAT_META_ECC) { |
| 2183 | status = ocfs2_block_check_validate(bh->b_data, | 2218 | status = ocfs2_block_check_validate(bh->b_data, |
| 2184 | bh->b_size, | 2219 | bh->b_size, |
| 2185 | &di->i_check); | 2220 | &di->i_check, |
| 2221 | stats); | ||
| 2186 | if (status) | 2222 | if (status) |
| 2187 | goto out; | 2223 | goto out; |
| 2188 | } | 2224 | } |
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index 15631019dc63..ba320e250747 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c | |||
| @@ -3154,7 +3154,7 @@ static int ocfs2_iterate_xattr_buckets(struct inode *inode, | |||
| 3154 | le32_to_cpu(bucket_xh(bucket)->xh_entries[0].xe_name_hash)); | 3154 | le32_to_cpu(bucket_xh(bucket)->xh_entries[0].xe_name_hash)); |
| 3155 | if (func) { | 3155 | if (func) { |
| 3156 | ret = func(inode, bucket, para); | 3156 | ret = func(inode, bucket, para); |
| 3157 | if (ret) | 3157 | if (ret && ret != -ERANGE) |
| 3158 | mlog_errno(ret); | 3158 | mlog_errno(ret); |
| 3159 | /* Fall through to bucket_relse() */ | 3159 | /* Fall through to bucket_relse() */ |
| 3160 | } | 3160 | } |
| @@ -3261,7 +3261,8 @@ static int ocfs2_xattr_tree_list_index_block(struct inode *inode, | |||
| 3261 | ocfs2_list_xattr_bucket, | 3261 | ocfs2_list_xattr_bucket, |
| 3262 | &xl); | 3262 | &xl); |
| 3263 | if (ret) { | 3263 | if (ret) { |
| 3264 | mlog_errno(ret); | 3264 | if (ret != -ERANGE) |
| 3265 | mlog_errno(ret); | ||
| 3265 | goto out; | 3266 | goto out; |
| 3266 | } | 3267 | } |
| 3267 | 3268 | ||
