diff options
author | Tao Ma <tao.ma@oracle.com> | 2008-08-18 05:38:45 -0400 |
---|---|---|
committer | Mark Fasheh <mfasheh@suse.com> | 2008-10-13 16:57:59 -0400 |
commit | 0eb8d47e69a2211a36643b180f1843ef45f6017d (patch) | |
tree | 745a063238cbcf6af84644bd51d4bfcd592e06a1 | |
parent | e7d4cb6bc19658646357eeff134645cd9bc3479f (diff) |
ocfs2: Make high level btree extend code generic
Factor out the non-inode specifics of ocfs2_do_extend_allocation() into a more generic
function, ocfs2_do_cluster_allocation(). ocfs2_do_extend_allocation calls
ocfs2_do_cluster_allocation() now, but the latter can be used for other
btree types as well.
Signed-off-by: Tao Ma <tao.ma@oracle.com>
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
-rw-r--r-- | fs/ocfs2/alloc.c | 110 | ||||
-rw-r--r-- | fs/ocfs2/alloc.h | 17 | ||||
-rw-r--r-- | fs/ocfs2/aops.c | 8 | ||||
-rw-r--r-- | fs/ocfs2/dir.c | 6 | ||||
-rw-r--r-- | fs/ocfs2/file.c | 136 | ||||
-rw-r--r-- | fs/ocfs2/file.h | 26 | ||||
-rw-r--r-- | fs/ocfs2/namei.c | 8 |
7 files changed, 176 insertions, 135 deletions
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index 579659bae6c5..cacfc118b71c 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c | |||
@@ -4293,6 +4293,116 @@ bail: | |||
4293 | return status; | 4293 | return status; |
4294 | } | 4294 | } |
4295 | 4295 | ||
4296 | /* | ||
4297 | * Allcate and add clusters into the extent b-tree. | ||
4298 | * The new clusters(clusters_to_add) will be inserted at logical_offset. | ||
4299 | * The extent b-tree's root is root_el and it should be in root_bh, and | ||
4300 | * it is not limited to the file storage. Any extent tree can use this | ||
4301 | * function if it implements the proper ocfs2_extent_tree. | ||
4302 | */ | ||
4303 | int ocfs2_add_clusters_in_btree(struct ocfs2_super *osb, | ||
4304 | struct inode *inode, | ||
4305 | u32 *logical_offset, | ||
4306 | u32 clusters_to_add, | ||
4307 | int mark_unwritten, | ||
4308 | struct buffer_head *root_bh, | ||
4309 | struct ocfs2_extent_list *root_el, | ||
4310 | handle_t *handle, | ||
4311 | struct ocfs2_alloc_context *data_ac, | ||
4312 | struct ocfs2_alloc_context *meta_ac, | ||
4313 | enum ocfs2_alloc_restarted *reason_ret, | ||
4314 | enum ocfs2_extent_tree_type type) | ||
4315 | { | ||
4316 | int status = 0; | ||
4317 | int free_extents; | ||
4318 | enum ocfs2_alloc_restarted reason = RESTART_NONE; | ||
4319 | u32 bit_off, num_bits; | ||
4320 | u64 block; | ||
4321 | u8 flags = 0; | ||
4322 | |||
4323 | BUG_ON(!clusters_to_add); | ||
4324 | |||
4325 | if (mark_unwritten) | ||
4326 | flags = OCFS2_EXT_UNWRITTEN; | ||
4327 | |||
4328 | free_extents = ocfs2_num_free_extents(osb, inode, root_bh, type); | ||
4329 | if (free_extents < 0) { | ||
4330 | status = free_extents; | ||
4331 | mlog_errno(status); | ||
4332 | goto leave; | ||
4333 | } | ||
4334 | |||
4335 | /* there are two cases which could cause us to EAGAIN in the | ||
4336 | * we-need-more-metadata case: | ||
4337 | * 1) we haven't reserved *any* | ||
4338 | * 2) we are so fragmented, we've needed to add metadata too | ||
4339 | * many times. */ | ||
4340 | if (!free_extents && !meta_ac) { | ||
4341 | mlog(0, "we haven't reserved any metadata!\n"); | ||
4342 | status = -EAGAIN; | ||
4343 | reason = RESTART_META; | ||
4344 | goto leave; | ||
4345 | } else if ((!free_extents) | ||
4346 | && (ocfs2_alloc_context_bits_left(meta_ac) | ||
4347 | < ocfs2_extend_meta_needed(root_el))) { | ||
4348 | mlog(0, "filesystem is really fragmented...\n"); | ||
4349 | status = -EAGAIN; | ||
4350 | reason = RESTART_META; | ||
4351 | goto leave; | ||
4352 | } | ||
4353 | |||
4354 | status = __ocfs2_claim_clusters(osb, handle, data_ac, 1, | ||
4355 | clusters_to_add, &bit_off, &num_bits); | ||
4356 | if (status < 0) { | ||
4357 | if (status != -ENOSPC) | ||
4358 | mlog_errno(status); | ||
4359 | goto leave; | ||
4360 | } | ||
4361 | |||
4362 | BUG_ON(num_bits > clusters_to_add); | ||
4363 | |||
4364 | /* reserve our write early -- insert_extent may update the inode */ | ||
4365 | status = ocfs2_journal_access(handle, inode, root_bh, | ||
4366 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
4367 | if (status < 0) { | ||
4368 | mlog_errno(status); | ||
4369 | goto leave; | ||
4370 | } | ||
4371 | |||
4372 | block = ocfs2_clusters_to_blocks(osb->sb, bit_off); | ||
4373 | mlog(0, "Allocating %u clusters at block %u for inode %llu\n", | ||
4374 | num_bits, bit_off, (unsigned long long)OCFS2_I(inode)->ip_blkno); | ||
4375 | status = ocfs2_insert_extent(osb, handle, inode, root_bh, | ||
4376 | *logical_offset, block, num_bits, | ||
4377 | flags, meta_ac, type); | ||
4378 | if (status < 0) { | ||
4379 | mlog_errno(status); | ||
4380 | goto leave; | ||
4381 | } | ||
4382 | |||
4383 | status = ocfs2_journal_dirty(handle, root_bh); | ||
4384 | if (status < 0) { | ||
4385 | mlog_errno(status); | ||
4386 | goto leave; | ||
4387 | } | ||
4388 | |||
4389 | clusters_to_add -= num_bits; | ||
4390 | *logical_offset += num_bits; | ||
4391 | |||
4392 | if (clusters_to_add) { | ||
4393 | mlog(0, "need to alloc once more, wanted = %u\n", | ||
4394 | clusters_to_add); | ||
4395 | status = -EAGAIN; | ||
4396 | reason = RESTART_TRANS; | ||
4397 | } | ||
4398 | |||
4399 | leave: | ||
4400 | mlog_exit(status); | ||
4401 | if (reason_ret) | ||
4402 | *reason_ret = reason; | ||
4403 | return status; | ||
4404 | } | ||
4405 | |||
4296 | static void ocfs2_make_right_split_rec(struct super_block *sb, | 4406 | static void ocfs2_make_right_split_rec(struct super_block *sb, |
4297 | struct ocfs2_extent_rec *split_rec, | 4407 | struct ocfs2_extent_rec *split_rec, |
4298 | u32 cpos, | 4408 | u32 cpos, |
diff --git a/fs/ocfs2/alloc.h b/fs/ocfs2/alloc.h index 473c8bcc62fb..5e090c5d8498 100644 --- a/fs/ocfs2/alloc.h +++ b/fs/ocfs2/alloc.h | |||
@@ -41,6 +41,23 @@ int ocfs2_insert_extent(struct ocfs2_super *osb, | |||
41 | u8 flags, | 41 | u8 flags, |
42 | struct ocfs2_alloc_context *meta_ac, | 42 | struct ocfs2_alloc_context *meta_ac, |
43 | enum ocfs2_extent_tree_type et_type); | 43 | enum ocfs2_extent_tree_type et_type); |
44 | enum ocfs2_alloc_restarted { | ||
45 | RESTART_NONE = 0, | ||
46 | RESTART_TRANS, | ||
47 | RESTART_META | ||
48 | }; | ||
49 | int ocfs2_add_clusters_in_btree(struct ocfs2_super *osb, | ||
50 | struct inode *inode, | ||
51 | u32 *logical_offset, | ||
52 | u32 clusters_to_add, | ||
53 | int mark_unwritten, | ||
54 | struct buffer_head *root_bh, | ||
55 | struct ocfs2_extent_list *root_el, | ||
56 | handle_t *handle, | ||
57 | struct ocfs2_alloc_context *data_ac, | ||
58 | struct ocfs2_alloc_context *meta_ac, | ||
59 | enum ocfs2_alloc_restarted *reason_ret, | ||
60 | enum ocfs2_extent_tree_type type); | ||
44 | struct ocfs2_cached_dealloc_ctxt; | 61 | struct ocfs2_cached_dealloc_ctxt; |
45 | int ocfs2_mark_extent_written(struct inode *inode, struct buffer_head *root_bh, | 62 | int ocfs2_mark_extent_written(struct inode *inode, struct buffer_head *root_bh, |
46 | handle_t *handle, u32 cpos, u32 len, u32 phys, | 63 | handle_t *handle, u32 cpos, u32 len, u32 phys, |
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 44ea5eb3fdc4..e7acd2867904 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c | |||
@@ -1255,10 +1255,10 @@ static int ocfs2_write_cluster(struct address_space *mapping, | |||
1255 | * any additional semaphores or cluster locks. | 1255 | * any additional semaphores or cluster locks. |
1256 | */ | 1256 | */ |
1257 | tmp_pos = cpos; | 1257 | tmp_pos = cpos; |
1258 | ret = ocfs2_do_extend_allocation(OCFS2_SB(inode->i_sb), inode, | 1258 | ret = ocfs2_add_inode_data(OCFS2_SB(inode->i_sb), inode, |
1259 | &tmp_pos, 1, 0, wc->w_di_bh, | 1259 | &tmp_pos, 1, 0, wc->w_di_bh, |
1260 | wc->w_handle, data_ac, | 1260 | wc->w_handle, data_ac, |
1261 | meta_ac, NULL); | 1261 | meta_ac, NULL); |
1262 | /* | 1262 | /* |
1263 | * This shouldn't happen because we must have already | 1263 | * This shouldn't happen because we must have already |
1264 | * calculated the correct meta data allocation required. The | 1264 | * calculated the correct meta data allocation required. The |
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index ba0fb9e16264..d17c34b0ac6b 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c | |||
@@ -1383,9 +1383,9 @@ static int ocfs2_do_extend_dir(struct super_block *sb, | |||
1383 | if (extend) { | 1383 | if (extend) { |
1384 | u32 offset = OCFS2_I(dir)->ip_clusters; | 1384 | u32 offset = OCFS2_I(dir)->ip_clusters; |
1385 | 1385 | ||
1386 | status = ocfs2_do_extend_allocation(OCFS2_SB(sb), dir, &offset, | 1386 | status = ocfs2_add_inode_data(OCFS2_SB(sb), dir, &offset, |
1387 | 1, 0, parent_fe_bh, handle, | 1387 | 1, 0, parent_fe_bh, handle, |
1388 | data_ac, meta_ac, NULL); | 1388 | data_ac, meta_ac, NULL); |
1389 | BUG_ON(status == -EAGAIN); | 1389 | BUG_ON(status == -EAGAIN); |
1390 | if (status < 0) { | 1390 | if (status < 0) { |
1391 | mlog_errno(status); | 1391 | mlog_errno(status); |
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index f567cc53d9bc..7bb4fde70054 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
@@ -488,7 +488,7 @@ bail: | |||
488 | } | 488 | } |
489 | 489 | ||
490 | /* | 490 | /* |
491 | * extend allocation only here. | 491 | * extend file allocation only here. |
492 | * we'll update all the disk stuff, and oip->alloc_size | 492 | * we'll update all the disk stuff, and oip->alloc_size |
493 | * | 493 | * |
494 | * expect stuff to be locked, a transaction started and enough data / | 494 | * expect stuff to be locked, a transaction started and enough data / |
@@ -497,107 +497,25 @@ bail: | |||
497 | * Will return -EAGAIN, and a reason if a restart is needed. | 497 | * Will return -EAGAIN, and a reason if a restart is needed. |
498 | * If passed in, *reason will always be set, even in error. | 498 | * If passed in, *reason will always be set, even in error. |
499 | */ | 499 | */ |
500 | int ocfs2_do_extend_allocation(struct ocfs2_super *osb, | 500 | int ocfs2_add_inode_data(struct ocfs2_super *osb, |
501 | struct inode *inode, | 501 | struct inode *inode, |
502 | u32 *logical_offset, | 502 | u32 *logical_offset, |
503 | u32 clusters_to_add, | 503 | u32 clusters_to_add, |
504 | int mark_unwritten, | 504 | int mark_unwritten, |
505 | struct buffer_head *fe_bh, | 505 | struct buffer_head *fe_bh, |
506 | handle_t *handle, | 506 | handle_t *handle, |
507 | struct ocfs2_alloc_context *data_ac, | 507 | struct ocfs2_alloc_context *data_ac, |
508 | struct ocfs2_alloc_context *meta_ac, | 508 | struct ocfs2_alloc_context *meta_ac, |
509 | enum ocfs2_alloc_restarted *reason_ret) | 509 | enum ocfs2_alloc_restarted *reason_ret) |
510 | { | 510 | { |
511 | int status = 0; | ||
512 | int free_extents; | ||
513 | struct ocfs2_dinode *fe = (struct ocfs2_dinode *) fe_bh->b_data; | 511 | struct ocfs2_dinode *fe = (struct ocfs2_dinode *) fe_bh->b_data; |
514 | enum ocfs2_alloc_restarted reason = RESTART_NONE; | 512 | struct ocfs2_extent_list *el = &fe->id2.i_list; |
515 | u32 bit_off, num_bits; | ||
516 | u64 block; | ||
517 | u8 flags = 0; | ||
518 | |||
519 | BUG_ON(!clusters_to_add); | ||
520 | |||
521 | if (mark_unwritten) | ||
522 | flags = OCFS2_EXT_UNWRITTEN; | ||
523 | |||
524 | free_extents = ocfs2_num_free_extents(osb, inode, fe_bh, | ||
525 | OCFS2_DINODE_EXTENT); | ||
526 | if (free_extents < 0) { | ||
527 | status = free_extents; | ||
528 | mlog_errno(status); | ||
529 | goto leave; | ||
530 | } | ||
531 | |||
532 | /* there are two cases which could cause us to EAGAIN in the | ||
533 | * we-need-more-metadata case: | ||
534 | * 1) we haven't reserved *any* | ||
535 | * 2) we are so fragmented, we've needed to add metadata too | ||
536 | * many times. */ | ||
537 | if (!free_extents && !meta_ac) { | ||
538 | mlog(0, "we haven't reserved any metadata!\n"); | ||
539 | status = -EAGAIN; | ||
540 | reason = RESTART_META; | ||
541 | goto leave; | ||
542 | } else if ((!free_extents) | ||
543 | && (ocfs2_alloc_context_bits_left(meta_ac) | ||
544 | < ocfs2_extend_meta_needed(&fe->id2.i_list))) { | ||
545 | mlog(0, "filesystem is really fragmented...\n"); | ||
546 | status = -EAGAIN; | ||
547 | reason = RESTART_META; | ||
548 | goto leave; | ||
549 | } | ||
550 | 513 | ||
551 | status = __ocfs2_claim_clusters(osb, handle, data_ac, 1, | 514 | return ocfs2_add_clusters_in_btree(osb, inode, logical_offset, |
552 | clusters_to_add, &bit_off, &num_bits); | 515 | clusters_to_add, mark_unwritten, |
553 | if (status < 0) { | 516 | fe_bh, el, handle, |
554 | if (status != -ENOSPC) | 517 | data_ac, meta_ac, reason_ret, |
555 | mlog_errno(status); | 518 | OCFS2_DINODE_EXTENT); |
556 | goto leave; | ||
557 | } | ||
558 | |||
559 | BUG_ON(num_bits > clusters_to_add); | ||
560 | |||
561 | /* reserve our write early -- insert_extent may update the inode */ | ||
562 | status = ocfs2_journal_access(handle, inode, fe_bh, | ||
563 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
564 | if (status < 0) { | ||
565 | mlog_errno(status); | ||
566 | goto leave; | ||
567 | } | ||
568 | |||
569 | block = ocfs2_clusters_to_blocks(osb->sb, bit_off); | ||
570 | mlog(0, "Allocating %u clusters at block %u for inode %llu\n", | ||
571 | num_bits, bit_off, (unsigned long long)OCFS2_I(inode)->ip_blkno); | ||
572 | status = ocfs2_insert_extent(osb, handle, inode, fe_bh, | ||
573 | *logical_offset, block, num_bits, | ||
574 | flags, meta_ac, OCFS2_DINODE_EXTENT); | ||
575 | if (status < 0) { | ||
576 | mlog_errno(status); | ||
577 | goto leave; | ||
578 | } | ||
579 | |||
580 | status = ocfs2_journal_dirty(handle, fe_bh); | ||
581 | if (status < 0) { | ||
582 | mlog_errno(status); | ||
583 | goto leave; | ||
584 | } | ||
585 | |||
586 | clusters_to_add -= num_bits; | ||
587 | *logical_offset += num_bits; | ||
588 | |||
589 | if (clusters_to_add) { | ||
590 | mlog(0, "need to alloc once more, clusters = %u, wanted = " | ||
591 | "%u\n", fe->i_clusters, clusters_to_add); | ||
592 | status = -EAGAIN; | ||
593 | reason = RESTART_TRANS; | ||
594 | } | ||
595 | |||
596 | leave: | ||
597 | mlog_exit(status); | ||
598 | if (reason_ret) | ||
599 | *reason_ret = reason; | ||
600 | return status; | ||
601 | } | 519 | } |
602 | 520 | ||
603 | static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start, | 521 | static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start, |
@@ -676,16 +594,16 @@ restarted_transaction: | |||
676 | 594 | ||
677 | prev_clusters = OCFS2_I(inode)->ip_clusters; | 595 | prev_clusters = OCFS2_I(inode)->ip_clusters; |
678 | 596 | ||
679 | status = ocfs2_do_extend_allocation(osb, | 597 | status = ocfs2_add_inode_data(osb, |
680 | inode, | 598 | inode, |
681 | &logical_start, | 599 | &logical_start, |
682 | clusters_to_add, | 600 | clusters_to_add, |
683 | mark_unwritten, | 601 | mark_unwritten, |
684 | bh, | 602 | bh, |
685 | handle, | 603 | handle, |
686 | data_ac, | 604 | data_ac, |
687 | meta_ac, | 605 | meta_ac, |
688 | &why); | 606 | &why); |
689 | if ((status < 0) && (status != -EAGAIN)) { | 607 | if ((status < 0) && (status != -EAGAIN)) { |
690 | if (status != -ENOSPC) | 608 | if (status != -ENOSPC) |
691 | mlog_errno(status); | 609 | mlog_errno(status); |
diff --git a/fs/ocfs2/file.h b/fs/ocfs2/file.h index 18e5c80cc737..e92382cbca5f 100644 --- a/fs/ocfs2/file.h +++ b/fs/ocfs2/file.h | |||
@@ -33,6 +33,7 @@ extern const struct file_operations ocfs2_dops_no_plocks; | |||
33 | extern const struct inode_operations ocfs2_file_iops; | 33 | extern const struct inode_operations ocfs2_file_iops; |
34 | extern const struct inode_operations ocfs2_special_file_iops; | 34 | extern const struct inode_operations ocfs2_special_file_iops; |
35 | struct ocfs2_alloc_context; | 35 | struct ocfs2_alloc_context; |
36 | enum ocfs2_alloc_restarted; | ||
36 | 37 | ||
37 | struct ocfs2_file_private { | 38 | struct ocfs2_file_private { |
38 | struct file *fp_file; | 39 | struct file *fp_file; |
@@ -40,21 +41,16 @@ struct ocfs2_file_private { | |||
40 | struct ocfs2_lock_res fp_flock; | 41 | struct ocfs2_lock_res fp_flock; |
41 | }; | 42 | }; |
42 | 43 | ||
43 | enum ocfs2_alloc_restarted { | 44 | int ocfs2_add_inode_data(struct ocfs2_super *osb, |
44 | RESTART_NONE = 0, | 45 | struct inode *inode, |
45 | RESTART_TRANS, | 46 | u32 *logical_offset, |
46 | RESTART_META | 47 | u32 clusters_to_add, |
47 | }; | 48 | int mark_unwritten, |
48 | int ocfs2_do_extend_allocation(struct ocfs2_super *osb, | 49 | struct buffer_head *fe_bh, |
49 | struct inode *inode, | 50 | handle_t *handle, |
50 | u32 *logical_offset, | 51 | struct ocfs2_alloc_context *data_ac, |
51 | u32 clusters_to_add, | 52 | struct ocfs2_alloc_context *meta_ac, |
52 | int mark_unwritten, | 53 | enum ocfs2_alloc_restarted *reason_ret); |
53 | struct buffer_head *fe_bh, | ||
54 | handle_t *handle, | ||
55 | struct ocfs2_alloc_context *data_ac, | ||
56 | struct ocfs2_alloc_context *meta_ac, | ||
57 | enum ocfs2_alloc_restarted *reason_ret); | ||
58 | int ocfs2_extend_no_holes(struct inode *inode, u64 new_i_size, | 54 | int ocfs2_extend_no_holes(struct inode *inode, u64 new_i_size, |
59 | u64 zero_to); | 55 | u64 zero_to); |
60 | int ocfs2_setattr(struct dentry *dentry, struct iattr *attr); | 56 | int ocfs2_setattr(struct dentry *dentry, struct iattr *attr); |
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index d5d808fe0140..2cd6f501755e 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c | |||
@@ -1598,10 +1598,10 @@ static int ocfs2_symlink(struct inode *dir, | |||
1598 | u32 offset = 0; | 1598 | u32 offset = 0; |
1599 | 1599 | ||
1600 | inode->i_op = &ocfs2_symlink_inode_operations; | 1600 | inode->i_op = &ocfs2_symlink_inode_operations; |
1601 | status = ocfs2_do_extend_allocation(osb, inode, &offset, 1, 0, | 1601 | status = ocfs2_add_inode_data(osb, inode, &offset, 1, 0, |
1602 | new_fe_bh, | 1602 | new_fe_bh, |
1603 | handle, data_ac, NULL, | 1603 | handle, data_ac, NULL, |
1604 | NULL); | 1604 | NULL); |
1605 | if (status < 0) { | 1605 | if (status < 0) { |
1606 | if (status != -ENOSPC && status != -EINTR) { | 1606 | if (status != -ENOSPC && status != -EINTR) { |
1607 | mlog(ML_ERROR, | 1607 | mlog(ML_ERROR, |