diff options
Diffstat (limited to 'fs/ocfs2')
-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 | ||