aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ocfs2/alloc.c110
-rw-r--r--fs/ocfs2/alloc.h17
-rw-r--r--fs/ocfs2/aops.c8
-rw-r--r--fs/ocfs2/dir.c6
-rw-r--r--fs/ocfs2/file.c136
-rw-r--r--fs/ocfs2/file.h26
-rw-r--r--fs/ocfs2/namei.c8
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 */
4303int 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
4399leave:
4400 mlog_exit(status);
4401 if (reason_ret)
4402 *reason_ret = reason;
4403 return status;
4404}
4405
4296static void ocfs2_make_right_split_rec(struct super_block *sb, 4406static 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);
44enum ocfs2_alloc_restarted {
45 RESTART_NONE = 0,
46 RESTART_TRANS,
47 RESTART_META
48};
49int 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);
44struct ocfs2_cached_dealloc_ctxt; 61struct ocfs2_cached_dealloc_ctxt;
45int ocfs2_mark_extent_written(struct inode *inode, struct buffer_head *root_bh, 62int 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 */
500int ocfs2_do_extend_allocation(struct ocfs2_super *osb, 500int 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
596leave:
597 mlog_exit(status);
598 if (reason_ret)
599 *reason_ret = reason;
600 return status;
601} 519}
602 520
603static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start, 521static 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;
33extern const struct inode_operations ocfs2_file_iops; 33extern const struct inode_operations ocfs2_file_iops;
34extern const struct inode_operations ocfs2_special_file_iops; 34extern const struct inode_operations ocfs2_special_file_iops;
35struct ocfs2_alloc_context; 35struct ocfs2_alloc_context;
36enum ocfs2_alloc_restarted;
36 37
37struct ocfs2_file_private { 38struct 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
43enum ocfs2_alloc_restarted { 44int 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,
48int 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);
58int ocfs2_extend_no_holes(struct inode *inode, u64 new_i_size, 54int ocfs2_extend_no_holes(struct inode *inode, u64 new_i_size,
59 u64 zero_to); 55 u64 zero_to);
60int ocfs2_setattr(struct dentry *dentry, struct iattr *attr); 56int 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,