diff options
Diffstat (limited to 'fs/ocfs2')
| -rw-r--r-- | fs/ocfs2/acl.c | 14 | ||||
| -rw-r--r-- | fs/ocfs2/alloc.c | 18 | ||||
| -rw-r--r-- | fs/ocfs2/aops.c | 242 | ||||
| -rw-r--r-- | fs/ocfs2/cluster/tcp.c | 3 | ||||
| -rw-r--r-- | fs/ocfs2/cluster/tcp_internal.h | 12 | ||||
| -rw-r--r-- | fs/ocfs2/dir.c | 10 | ||||
| -rw-r--r-- | fs/ocfs2/dlm/dlmast.c | 6 | ||||
| -rw-r--r-- | fs/ocfs2/dlm/dlmdebug.c | 4 | ||||
| -rw-r--r-- | fs/ocfs2/dlm/dlmdomain.c | 14 | ||||
| -rw-r--r-- | fs/ocfs2/dlm/dlmdomain.h | 1 | ||||
| -rw-r--r-- | fs/ocfs2/dlm/dlmrecovery.c | 12 | ||||
| -rw-r--r-- | fs/ocfs2/dlmfs/dlmfs.c | 14 | ||||
| -rw-r--r-- | fs/ocfs2/dlmglue.c | 3 | ||||
| -rw-r--r-- | fs/ocfs2/file.c | 80 | ||||
| -rw-r--r-- | fs/ocfs2/file.h | 9 | ||||
| -rw-r--r-- | fs/ocfs2/inode.c | 2 | ||||
| -rw-r--r-- | fs/ocfs2/inode.h | 2 | ||||
| -rw-r--r-- | fs/ocfs2/journal.c | 111 | ||||
| -rw-r--r-- | fs/ocfs2/journal.h | 5 | ||||
| -rw-r--r-- | fs/ocfs2/mmap.c | 1 | ||||
| -rw-r--r-- | fs/ocfs2/namei.c | 327 | ||||
| -rw-r--r-- | fs/ocfs2/namei.h | 8 | ||||
| -rw-r--r-- | fs/ocfs2/ocfs2.h | 25 | ||||
| -rw-r--r-- | fs/ocfs2/ocfs2_fs.h | 14 | ||||
| -rw-r--r-- | fs/ocfs2/quota.h | 1 | ||||
| -rw-r--r-- | fs/ocfs2/quota_local.c | 20 | ||||
| -rw-r--r-- | fs/ocfs2/refcounttree.c | 2 | ||||
| -rw-r--r-- | fs/ocfs2/reservations.c | 2 | ||||
| -rw-r--r-- | fs/ocfs2/super.c | 51 | ||||
| -rw-r--r-- | fs/ocfs2/xattr.c | 10 |
30 files changed, 825 insertions, 198 deletions
diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c index 7e8282dcea2a..c58a1bcfda0f 100644 --- a/fs/ocfs2/acl.c +++ b/fs/ocfs2/acl.c | |||
| @@ -245,16 +245,14 @@ int ocfs2_set_acl(handle_t *handle, | |||
| 245 | ret = posix_acl_equiv_mode(acl, &mode); | 245 | ret = posix_acl_equiv_mode(acl, &mode); |
| 246 | if (ret < 0) | 246 | if (ret < 0) |
| 247 | return ret; | 247 | return ret; |
| 248 | else { | ||
| 249 | if (ret == 0) | ||
| 250 | acl = NULL; | ||
| 251 | 248 | ||
| 252 | ret = ocfs2_acl_set_mode(inode, di_bh, | 249 | if (ret == 0) |
| 253 | handle, mode); | 250 | acl = NULL; |
| 254 | if (ret) | ||
| 255 | return ret; | ||
| 256 | 251 | ||
| 257 | } | 252 | ret = ocfs2_acl_set_mode(inode, di_bh, |
| 253 | handle, mode); | ||
| 254 | if (ret) | ||
| 255 | return ret; | ||
| 258 | } | 256 | } |
| 259 | break; | 257 | break; |
| 260 | case ACL_TYPE_DEFAULT: | 258 | case ACL_TYPE_DEFAULT: |
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index fcae9ef1a328..044158bd22be 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c | |||
| @@ -6873,7 +6873,7 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode, | |||
| 6873 | if (IS_ERR(handle)) { | 6873 | if (IS_ERR(handle)) { |
| 6874 | ret = PTR_ERR(handle); | 6874 | ret = PTR_ERR(handle); |
| 6875 | mlog_errno(ret); | 6875 | mlog_errno(ret); |
| 6876 | goto out_unlock; | 6876 | goto out; |
| 6877 | } | 6877 | } |
| 6878 | 6878 | ||
| 6879 | ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), di_bh, | 6879 | ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), di_bh, |
| @@ -6931,7 +6931,7 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode, | |||
| 6931 | if (ret) { | 6931 | if (ret) { |
| 6932 | mlog_errno(ret); | 6932 | mlog_errno(ret); |
| 6933 | need_free = 1; | 6933 | need_free = 1; |
| 6934 | goto out_commit; | 6934 | goto out_unlock; |
| 6935 | } | 6935 | } |
| 6936 | 6936 | ||
| 6937 | page_end = PAGE_CACHE_SIZE; | 6937 | page_end = PAGE_CACHE_SIZE; |
| @@ -6964,12 +6964,16 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode, | |||
| 6964 | if (ret) { | 6964 | if (ret) { |
| 6965 | mlog_errno(ret); | 6965 | mlog_errno(ret); |
| 6966 | need_free = 1; | 6966 | need_free = 1; |
| 6967 | goto out_commit; | 6967 | goto out_unlock; |
| 6968 | } | 6968 | } |
| 6969 | 6969 | ||
| 6970 | inode->i_blocks = ocfs2_inode_sector_count(inode); | 6970 | inode->i_blocks = ocfs2_inode_sector_count(inode); |
| 6971 | } | 6971 | } |
| 6972 | 6972 | ||
| 6973 | out_unlock: | ||
| 6974 | if (pages) | ||
| 6975 | ocfs2_unlock_and_free_pages(pages, num_pages); | ||
| 6976 | |||
| 6973 | out_commit: | 6977 | out_commit: |
| 6974 | if (ret < 0 && did_quota) | 6978 | if (ret < 0 && did_quota) |
| 6975 | dquot_free_space_nodirty(inode, | 6979 | dquot_free_space_nodirty(inode, |
| @@ -6989,15 +6993,11 @@ out_commit: | |||
| 6989 | 6993 | ||
| 6990 | ocfs2_commit_trans(osb, handle); | 6994 | ocfs2_commit_trans(osb, handle); |
| 6991 | 6995 | ||
| 6992 | out_unlock: | 6996 | out: |
| 6993 | if (data_ac) | 6997 | if (data_ac) |
| 6994 | ocfs2_free_alloc_context(data_ac); | 6998 | ocfs2_free_alloc_context(data_ac); |
| 6995 | 6999 | if (pages) | |
| 6996 | out: | ||
| 6997 | if (pages) { | ||
| 6998 | ocfs2_unlock_and_free_pages(pages, num_pages); | ||
| 6999 | kfree(pages); | 7000 | kfree(pages); |
| 7000 | } | ||
| 7001 | 7001 | ||
| 7002 | return ret; | 7002 | return ret; |
| 7003 | } | 7003 | } |
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 46d93e941f3d..44db1808cdb5 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include <linux/pipe_fs_i.h> | 28 | #include <linux/pipe_fs_i.h> |
| 29 | #include <linux/mpage.h> | 29 | #include <linux/mpage.h> |
| 30 | #include <linux/quotaops.h> | 30 | #include <linux/quotaops.h> |
| 31 | #include <linux/blkdev.h> | ||
| 31 | 32 | ||
| 32 | #include <cluster/masklog.h> | 33 | #include <cluster/masklog.h> |
| 33 | 34 | ||
| @@ -47,6 +48,9 @@ | |||
| 47 | #include "ocfs2_trace.h" | 48 | #include "ocfs2_trace.h" |
| 48 | 49 | ||
| 49 | #include "buffer_head_io.h" | 50 | #include "buffer_head_io.h" |
| 51 | #include "dir.h" | ||
| 52 | #include "namei.h" | ||
| 53 | #include "sysfile.h" | ||
| 50 | 54 | ||
| 51 | static int ocfs2_symlink_get_block(struct inode *inode, sector_t iblock, | 55 | static int ocfs2_symlink_get_block(struct inode *inode, sector_t iblock, |
| 52 | struct buffer_head *bh_result, int create) | 56 | struct buffer_head *bh_result, int create) |
| @@ -506,18 +510,21 @@ bail: | |||
| 506 | * | 510 | * |
| 507 | * called like this: dio->get_blocks(dio->inode, fs_startblk, | 511 | * called like this: dio->get_blocks(dio->inode, fs_startblk, |
| 508 | * fs_count, map_bh, dio->rw == WRITE); | 512 | * fs_count, map_bh, dio->rw == WRITE); |
| 509 | * | ||
| 510 | * Note that we never bother to allocate blocks here, and thus ignore the | ||
| 511 | * create argument. | ||
| 512 | */ | 513 | */ |
| 513 | static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock, | 514 | static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock, |
| 514 | struct buffer_head *bh_result, int create) | 515 | struct buffer_head *bh_result, int create) |
| 515 | { | 516 | { |
| 516 | int ret; | 517 | int ret; |
| 518 | u32 cpos = 0; | ||
| 519 | int alloc_locked = 0; | ||
| 517 | u64 p_blkno, inode_blocks, contig_blocks; | 520 | u64 p_blkno, inode_blocks, contig_blocks; |
| 518 | unsigned int ext_flags; | 521 | unsigned int ext_flags; |
| 519 | unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits; | 522 | unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits; |
| 520 | unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits; | 523 | unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits; |
| 524 | unsigned long len = bh_result->b_size; | ||
| 525 | unsigned int clusters_to_alloc = 0; | ||
| 526 | |||
| 527 | cpos = ocfs2_blocks_to_clusters(inode->i_sb, iblock); | ||
| 521 | 528 | ||
| 522 | /* This function won't even be called if the request isn't all | 529 | /* This function won't even be called if the request isn't all |
| 523 | * nicely aligned and of the right size, so there's no need | 530 | * nicely aligned and of the right size, so there's no need |
| @@ -539,6 +546,40 @@ static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock, | |||
| 539 | /* We should already CoW the refcounted extent in case of create. */ | 546 | /* We should already CoW the refcounted extent in case of create. */ |
| 540 | BUG_ON(create && (ext_flags & OCFS2_EXT_REFCOUNTED)); | 547 | BUG_ON(create && (ext_flags & OCFS2_EXT_REFCOUNTED)); |
| 541 | 548 | ||
| 549 | /* allocate blocks if no p_blkno is found, and create == 1 */ | ||
| 550 | if (!p_blkno && create) { | ||
| 551 | ret = ocfs2_inode_lock(inode, NULL, 1); | ||
| 552 | if (ret < 0) { | ||
| 553 | mlog_errno(ret); | ||
| 554 | goto bail; | ||
| 555 | } | ||
| 556 | |||
| 557 | alloc_locked = 1; | ||
| 558 | |||
| 559 | /* fill hole, allocate blocks can't be larger than the size | ||
| 560 | * of the hole */ | ||
| 561 | clusters_to_alloc = ocfs2_clusters_for_bytes(inode->i_sb, len); | ||
| 562 | if (clusters_to_alloc > contig_blocks) | ||
| 563 | clusters_to_alloc = contig_blocks; | ||
| 564 | |||
| 565 | /* allocate extent and insert them into the extent tree */ | ||
| 566 | ret = ocfs2_extend_allocation(inode, cpos, | ||
| 567 | clusters_to_alloc, 0); | ||
| 568 | if (ret < 0) { | ||
| 569 | mlog_errno(ret); | ||
| 570 | goto bail; | ||
| 571 | } | ||
| 572 | |||
| 573 | ret = ocfs2_extent_map_get_blocks(inode, iblock, &p_blkno, | ||
| 574 | &contig_blocks, &ext_flags); | ||
| 575 | if (ret < 0) { | ||
| 576 | mlog(ML_ERROR, "get_blocks() failed iblock=%llu\n", | ||
| 577 | (unsigned long long)iblock); | ||
| 578 | ret = -EIO; | ||
| 579 | goto bail; | ||
| 580 | } | ||
| 581 | } | ||
| 582 | |||
| 542 | /* | 583 | /* |
| 543 | * get_more_blocks() expects us to describe a hole by clearing | 584 | * get_more_blocks() expects us to describe a hole by clearing |
| 544 | * the mapped bit on bh_result(). | 585 | * the mapped bit on bh_result(). |
| @@ -556,6 +597,8 @@ static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock, | |||
| 556 | contig_blocks = max_blocks; | 597 | contig_blocks = max_blocks; |
| 557 | bh_result->b_size = contig_blocks << blocksize_bits; | 598 | bh_result->b_size = contig_blocks << blocksize_bits; |
| 558 | bail: | 599 | bail: |
| 600 | if (alloc_locked) | ||
| 601 | ocfs2_inode_unlock(inode, 1); | ||
| 559 | return ret; | 602 | return ret; |
| 560 | } | 603 | } |
| 561 | 604 | ||
| @@ -597,6 +640,184 @@ static int ocfs2_releasepage(struct page *page, gfp_t wait) | |||
| 597 | return try_to_free_buffers(page); | 640 | return try_to_free_buffers(page); |
| 598 | } | 641 | } |
| 599 | 642 | ||
| 643 | static int ocfs2_is_overwrite(struct ocfs2_super *osb, | ||
| 644 | struct inode *inode, loff_t offset) | ||
| 645 | { | ||
| 646 | int ret = 0; | ||
| 647 | u32 v_cpos = 0; | ||
| 648 | u32 p_cpos = 0; | ||
| 649 | unsigned int num_clusters = 0; | ||
| 650 | unsigned int ext_flags = 0; | ||
| 651 | |||
| 652 | v_cpos = ocfs2_bytes_to_clusters(osb->sb, offset); | ||
| 653 | ret = ocfs2_get_clusters(inode, v_cpos, &p_cpos, | ||
| 654 | &num_clusters, &ext_flags); | ||
| 655 | if (ret < 0) { | ||
| 656 | mlog_errno(ret); | ||
| 657 | return ret; | ||
| 658 | } | ||
| 659 | |||
| 660 | if (p_cpos && !(ext_flags & OCFS2_EXT_UNWRITTEN)) | ||
| 661 | return 1; | ||
| 662 | |||
| 663 | return 0; | ||
| 664 | } | ||
| 665 | |||
| 666 | static ssize_t ocfs2_direct_IO_write(struct kiocb *iocb, | ||
| 667 | struct iov_iter *iter, | ||
| 668 | loff_t offset) | ||
| 669 | { | ||
| 670 | ssize_t ret = 0; | ||
| 671 | ssize_t written = 0; | ||
| 672 | bool orphaned = false; | ||
| 673 | int is_overwrite = 0; | ||
| 674 | struct file *file = iocb->ki_filp; | ||
| 675 | struct inode *inode = file_inode(file)->i_mapping->host; | ||
| 676 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
| 677 | struct buffer_head *di_bh = NULL; | ||
| 678 | size_t count = iter->count; | ||
| 679 | journal_t *journal = osb->journal->j_journal; | ||
| 680 | u32 zero_len; | ||
| 681 | int cluster_align; | ||
| 682 | loff_t final_size = offset + count; | ||
| 683 | int append_write = offset >= i_size_read(inode) ? 1 : 0; | ||
| 684 | unsigned int num_clusters = 0; | ||
| 685 | unsigned int ext_flags = 0; | ||
| 686 | |||
| 687 | { | ||
| 688 | u64 o = offset; | ||
| 689 | |||
| 690 | zero_len = do_div(o, 1 << osb->s_clustersize_bits); | ||
| 691 | cluster_align = !zero_len; | ||
| 692 | } | ||
| 693 | |||
| 694 | /* | ||
| 695 | * when final_size > inode->i_size, inode->i_size will be | ||
| 696 | * updated after direct write, so add the inode to orphan | ||
| 697 | * dir first. | ||
| 698 | */ | ||
| 699 | if (final_size > i_size_read(inode)) { | ||
| 700 | ret = ocfs2_add_inode_to_orphan(osb, inode); | ||
| 701 | if (ret < 0) { | ||
| 702 | mlog_errno(ret); | ||
| 703 | goto out; | ||
| 704 | } | ||
| 705 | orphaned = true; | ||
| 706 | } | ||
| 707 | |||
| 708 | if (append_write) { | ||
| 709 | ret = ocfs2_inode_lock(inode, &di_bh, 1); | ||
| 710 | if (ret < 0) { | ||
| 711 | mlog_errno(ret); | ||
| 712 | goto clean_orphan; | ||
| 713 | } | ||
| 714 | |||
| 715 | if (ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb))) | ||
| 716 | ret = ocfs2_zero_extend(inode, di_bh, offset); | ||
| 717 | else | ||
| 718 | ret = ocfs2_extend_no_holes(inode, di_bh, offset, | ||
| 719 | offset); | ||
| 720 | if (ret < 0) { | ||
| 721 | mlog_errno(ret); | ||
| 722 | ocfs2_inode_unlock(inode, 1); | ||
| 723 | brelse(di_bh); | ||
| 724 | goto clean_orphan; | ||
| 725 | } | ||
| 726 | |||
| 727 | is_overwrite = ocfs2_is_overwrite(osb, inode, offset); | ||
| 728 | if (is_overwrite < 0) { | ||
| 729 | mlog_errno(is_overwrite); | ||
| 730 | ocfs2_inode_unlock(inode, 1); | ||
| 731 | brelse(di_bh); | ||
| 732 | goto clean_orphan; | ||
| 733 | } | ||
| 734 | |||
| 735 | ocfs2_inode_unlock(inode, 1); | ||
| 736 | brelse(di_bh); | ||
| 737 | di_bh = NULL; | ||
| 738 | } | ||
| 739 | |||
| 740 | written = __blockdev_direct_IO(WRITE, iocb, inode, inode->i_sb->s_bdev, | ||
| 741 | iter, offset, | ||
| 742 | ocfs2_direct_IO_get_blocks, | ||
| 743 | ocfs2_dio_end_io, NULL, 0); | ||
| 744 | if (unlikely(written < 0)) { | ||
| 745 | loff_t i_size = i_size_read(inode); | ||
| 746 | |||
| 747 | if (offset + count > i_size) { | ||
| 748 | ret = ocfs2_inode_lock(inode, &di_bh, 1); | ||
| 749 | if (ret < 0) { | ||
| 750 | mlog_errno(ret); | ||
| 751 | goto clean_orphan; | ||
| 752 | } | ||
| 753 | |||
| 754 | if (i_size == i_size_read(inode)) { | ||
| 755 | ret = ocfs2_truncate_file(inode, di_bh, | ||
| 756 | i_size); | ||
| 757 | if (ret < 0) { | ||
| 758 | if (ret != -ENOSPC) | ||
| 759 | mlog_errno(ret); | ||
| 760 | |||
| 761 | ocfs2_inode_unlock(inode, 1); | ||
| 762 | brelse(di_bh); | ||
| 763 | goto clean_orphan; | ||
| 764 | } | ||
| 765 | } | ||
| 766 | |||
| 767 | ocfs2_inode_unlock(inode, 1); | ||
| 768 | brelse(di_bh); | ||
| 769 | |||
| 770 | ret = jbd2_journal_force_commit(journal); | ||
| 771 | if (ret < 0) | ||
| 772 | mlog_errno(ret); | ||
| 773 | } | ||
| 774 | } else if (written < 0 && append_write && !is_overwrite && | ||
| 775 | !cluster_align) { | ||
| 776 | u32 p_cpos = 0; | ||
| 777 | u32 v_cpos = ocfs2_bytes_to_clusters(osb->sb, offset); | ||
| 778 | |||
| 779 | ret = ocfs2_get_clusters(inode, v_cpos, &p_cpos, | ||
| 780 | &num_clusters, &ext_flags); | ||
| 781 | if (ret < 0) { | ||
| 782 | mlog_errno(ret); | ||
| 783 | goto clean_orphan; | ||
| 784 | } | ||
| 785 | |||
| 786 | BUG_ON(!p_cpos || (ext_flags & OCFS2_EXT_UNWRITTEN)); | ||
| 787 | |||
| 788 | ret = blkdev_issue_zeroout(osb->sb->s_bdev, | ||
| 789 | p_cpos << (osb->s_clustersize_bits - 9), | ||
| 790 | zero_len >> 9, GFP_KERNEL, false); | ||
| 791 | if (ret < 0) | ||
| 792 | mlog_errno(ret); | ||
| 793 | } | ||
| 794 | |||
| 795 | clean_orphan: | ||
| 796 | if (orphaned) { | ||
| 797 | int tmp_ret; | ||
| 798 | int update_isize = written > 0 ? 1 : 0; | ||
| 799 | loff_t end = update_isize ? offset + written : 0; | ||
| 800 | |||
| 801 | tmp_ret = ocfs2_del_inode_from_orphan(osb, inode, | ||
| 802 | update_isize, end); | ||
| 803 | if (tmp_ret < 0) { | ||
| 804 | ret = tmp_ret; | ||
| 805 | goto out; | ||
| 806 | } | ||
| 807 | |||
| 808 | tmp_ret = jbd2_journal_force_commit(journal); | ||
| 809 | if (tmp_ret < 0) { | ||
| 810 | ret = tmp_ret; | ||
| 811 | mlog_errno(tmp_ret); | ||
| 812 | } | ||
| 813 | } | ||
| 814 | |||
| 815 | out: | ||
| 816 | if (ret >= 0) | ||
| 817 | ret = written; | ||
| 818 | return ret; | ||
| 819 | } | ||
| 820 | |||
| 600 | static ssize_t ocfs2_direct_IO(int rw, | 821 | static ssize_t ocfs2_direct_IO(int rw, |
| 601 | struct kiocb *iocb, | 822 | struct kiocb *iocb, |
| 602 | struct iov_iter *iter, | 823 | struct iov_iter *iter, |
| @@ -604,6 +825,9 @@ static ssize_t ocfs2_direct_IO(int rw, | |||
| 604 | { | 825 | { |
| 605 | struct file *file = iocb->ki_filp; | 826 | struct file *file = iocb->ki_filp; |
| 606 | struct inode *inode = file_inode(file)->i_mapping->host; | 827 | struct inode *inode = file_inode(file)->i_mapping->host; |
| 828 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
| 829 | int full_coherency = !(osb->s_mount_opt & | ||
| 830 | OCFS2_MOUNT_COHERENCY_BUFFERED); | ||
| 607 | 831 | ||
| 608 | /* | 832 | /* |
| 609 | * Fallback to buffered I/O if we see an inode without | 833 | * Fallback to buffered I/O if we see an inode without |
| @@ -612,14 +836,20 @@ static ssize_t ocfs2_direct_IO(int rw, | |||
| 612 | if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) | 836 | if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) |
| 613 | return 0; | 837 | return 0; |
| 614 | 838 | ||
| 615 | /* Fallback to buffered I/O if we are appending. */ | 839 | /* Fallback to buffered I/O if we are appending and |
| 616 | if (i_size_read(inode) <= offset) | 840 | * concurrent O_DIRECT writes are allowed. |
| 841 | */ | ||
| 842 | if (i_size_read(inode) <= offset && !full_coherency) | ||
| 617 | return 0; | 843 | return 0; |
| 618 | 844 | ||
| 619 | return __blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, | 845 | if (rw == READ) |
| 846 | return __blockdev_direct_IO(rw, iocb, inode, | ||
| 847 | inode->i_sb->s_bdev, | ||
| 620 | iter, offset, | 848 | iter, offset, |
| 621 | ocfs2_direct_IO_get_blocks, | 849 | ocfs2_direct_IO_get_blocks, |
| 622 | ocfs2_dio_end_io, NULL, 0); | 850 | ocfs2_dio_end_io, NULL, 0); |
| 851 | else | ||
| 852 | return ocfs2_direct_IO_write(iocb, iter, offset); | ||
| 623 | } | 853 | } |
| 624 | 854 | ||
| 625 | static void ocfs2_figure_cluster_boundaries(struct ocfs2_super *osb, | 855 | static void ocfs2_figure_cluster_boundaries(struct ocfs2_super *osb, |
diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c index 2e355e0f8335..56c403a563bc 100644 --- a/fs/ocfs2/cluster/tcp.c +++ b/fs/ocfs2/cluster/tcp.c | |||
| @@ -1016,7 +1016,8 @@ void o2net_fill_node_map(unsigned long *map, unsigned bytes) | |||
| 1016 | 1016 | ||
| 1017 | memset(map, 0, bytes); | 1017 | memset(map, 0, bytes); |
| 1018 | for (node = 0; node < O2NM_MAX_NODES; ++node) { | 1018 | for (node = 0; node < O2NM_MAX_NODES; ++node) { |
| 1019 | o2net_tx_can_proceed(o2net_nn_from_num(node), &sc, &ret); | 1019 | if (!o2net_tx_can_proceed(o2net_nn_from_num(node), &sc, &ret)) |
| 1020 | continue; | ||
| 1020 | if (!ret) { | 1021 | if (!ret) { |
| 1021 | set_bit(node, map); | 1022 | set_bit(node, map); |
| 1022 | sc_put(sc); | 1023 | sc_put(sc); |
diff --git a/fs/ocfs2/cluster/tcp_internal.h b/fs/ocfs2/cluster/tcp_internal.h index dc024367110a..b95e7df5b76a 100644 --- a/fs/ocfs2/cluster/tcp_internal.h +++ b/fs/ocfs2/cluster/tcp_internal.h | |||
| @@ -107,12 +107,12 @@ struct o2net_node { | |||
| 107 | struct list_head nn_status_list; | 107 | struct list_head nn_status_list; |
| 108 | 108 | ||
| 109 | /* connects are attempted from when heartbeat comes up until either hb | 109 | /* connects are attempted from when heartbeat comes up until either hb |
| 110 | * goes down, the node is unconfigured, no connect attempts succeed | 110 | * goes down, the node is unconfigured, or a connect succeeds. |
| 111 | * before O2NET_CONN_IDLE_DELAY, or a connect succeeds. connect_work | 111 | * connect_work is queued from set_nn_state both from hb up and from |
| 112 | * is queued from set_nn_state both from hb up and from itself if a | 112 | * itself if a connect attempt fails and so can be self-arming. |
| 113 | * connect attempt fails and so can be self-arming. shutdown is | 113 | * shutdown is careful to first mark the nn such that no connects will |
| 114 | * careful to first mark the nn such that no connects will be attempted | 114 | * be attempted before canceling delayed connect work and flushing the |
| 115 | * before canceling delayed connect work and flushing the queue. */ | 115 | * queue. */ |
| 116 | struct delayed_work nn_connect_work; | 116 | struct delayed_work nn_connect_work; |
| 117 | unsigned long nn_last_connect_attempt; | 117 | unsigned long nn_last_connect_attempt; |
| 118 | 118 | ||
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index 319e786175af..b08050bd3f2e 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c | |||
| @@ -3456,10 +3456,8 @@ static int ocfs2_find_dir_space_el(struct inode *dir, const char *name, | |||
| 3456 | int blocksize = dir->i_sb->s_blocksize; | 3456 | int blocksize = dir->i_sb->s_blocksize; |
| 3457 | 3457 | ||
| 3458 | status = ocfs2_read_dir_block(dir, 0, &bh, 0); | 3458 | status = ocfs2_read_dir_block(dir, 0, &bh, 0); |
| 3459 | if (status) { | 3459 | if (status) |
| 3460 | mlog_errno(status); | ||
| 3461 | goto bail; | 3460 | goto bail; |
| 3462 | } | ||
| 3463 | 3461 | ||
| 3464 | rec_len = OCFS2_DIR_REC_LEN(namelen); | 3462 | rec_len = OCFS2_DIR_REC_LEN(namelen); |
| 3465 | offset = 0; | 3463 | offset = 0; |
| @@ -3480,10 +3478,9 @@ static int ocfs2_find_dir_space_el(struct inode *dir, const char *name, | |||
| 3480 | status = ocfs2_read_dir_block(dir, | 3478 | status = ocfs2_read_dir_block(dir, |
| 3481 | offset >> sb->s_blocksize_bits, | 3479 | offset >> sb->s_blocksize_bits, |
| 3482 | &bh, 0); | 3480 | &bh, 0); |
| 3483 | if (status) { | 3481 | if (status) |
| 3484 | mlog_errno(status); | ||
| 3485 | goto bail; | 3482 | goto bail; |
| 3486 | } | 3483 | |
| 3487 | /* move to next block */ | 3484 | /* move to next block */ |
| 3488 | de = (struct ocfs2_dir_entry *) bh->b_data; | 3485 | de = (struct ocfs2_dir_entry *) bh->b_data; |
| 3489 | } | 3486 | } |
| @@ -3513,7 +3510,6 @@ next: | |||
| 3513 | de = (struct ocfs2_dir_entry *)((char *) de + le16_to_cpu(de->rec_len)); | 3510 | de = (struct ocfs2_dir_entry *)((char *) de + le16_to_cpu(de->rec_len)); |
| 3514 | } | 3511 | } |
| 3515 | 3512 | ||
| 3516 | status = 0; | ||
| 3517 | bail: | 3513 | bail: |
| 3518 | brelse(bh); | 3514 | brelse(bh); |
| 3519 | if (status) | 3515 | if (status) |
diff --git a/fs/ocfs2/dlm/dlmast.c b/fs/ocfs2/dlm/dlmast.c index b46278f9ae44..fd6bbbbd7d78 100644 --- a/fs/ocfs2/dlm/dlmast.c +++ b/fs/ocfs2/dlm/dlmast.c | |||
| @@ -385,8 +385,12 @@ int dlm_proxy_ast_handler(struct o2net_msg *msg, u32 len, void *data, | |||
| 385 | head = &res->granted; | 385 | head = &res->granted; |
| 386 | 386 | ||
| 387 | list_for_each_entry(lock, head, list) { | 387 | list_for_each_entry(lock, head, list) { |
| 388 | if (lock->ml.cookie == cookie) | 388 | /* if lock is found but unlock is pending ignore the bast */ |
| 389 | if (lock->ml.cookie == cookie) { | ||
| 390 | if (lock->unlock_pending) | ||
| 391 | break; | ||
| 389 | goto do_ast; | 392 | goto do_ast; |
| 393 | } | ||
| 390 | } | 394 | } |
| 391 | 395 | ||
| 392 | mlog(0, "Got %sast for unknown lock! cookie=%u:%llu, name=%.*s, " | 396 | mlog(0, "Got %sast for unknown lock! cookie=%u:%llu, name=%.*s, " |
diff --git a/fs/ocfs2/dlm/dlmdebug.c b/fs/ocfs2/dlm/dlmdebug.c index 149eb556b8c6..825136070d2c 100644 --- a/fs/ocfs2/dlm/dlmdebug.c +++ b/fs/ocfs2/dlm/dlmdebug.c | |||
| @@ -406,7 +406,7 @@ static int debug_purgelist_print(struct dlm_ctxt *dlm, char *buf, int len) | |||
| 406 | } | 406 | } |
| 407 | spin_unlock(&dlm->spinlock); | 407 | spin_unlock(&dlm->spinlock); |
| 408 | 408 | ||
| 409 | out += snprintf(buf + out, len - out, "Total on list: %ld\n", total); | 409 | out += snprintf(buf + out, len - out, "Total on list: %lu\n", total); |
| 410 | 410 | ||
| 411 | return out; | 411 | return out; |
| 412 | } | 412 | } |
| @@ -464,7 +464,7 @@ static int debug_mle_print(struct dlm_ctxt *dlm, char *buf, int len) | |||
| 464 | spin_unlock(&dlm->master_lock); | 464 | spin_unlock(&dlm->master_lock); |
| 465 | 465 | ||
| 466 | out += snprintf(buf + out, len - out, | 466 | out += snprintf(buf + out, len - out, |
| 467 | "Total: %ld, Longest: %ld\n", total, longest); | 467 | "Total: %lu, Longest: %lu\n", total, longest); |
| 468 | return out; | 468 | return out; |
| 469 | } | 469 | } |
| 470 | 470 | ||
diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c index 50a59d2337b2..7df88a6dd626 100644 --- a/fs/ocfs2/dlm/dlmdomain.c +++ b/fs/ocfs2/dlm/dlmdomain.c | |||
| @@ -674,20 +674,6 @@ static void dlm_leave_domain(struct dlm_ctxt *dlm) | |||
| 674 | spin_unlock(&dlm->spinlock); | 674 | spin_unlock(&dlm->spinlock); |
| 675 | } | 675 | } |
| 676 | 676 | ||
| 677 | int dlm_joined(struct dlm_ctxt *dlm) | ||
| 678 | { | ||
| 679 | int ret = 0; | ||
| 680 | |||
| 681 | spin_lock(&dlm_domain_lock); | ||
| 682 | |||
| 683 | if (dlm->dlm_state == DLM_CTXT_JOINED) | ||
| 684 | ret = 1; | ||
| 685 | |||
| 686 | spin_unlock(&dlm_domain_lock); | ||
| 687 | |||
| 688 | return ret; | ||
| 689 | } | ||
| 690 | |||
| 691 | int dlm_shutting_down(struct dlm_ctxt *dlm) | 677 | int dlm_shutting_down(struct dlm_ctxt *dlm) |
| 692 | { | 678 | { |
| 693 | int ret = 0; | 679 | int ret = 0; |
diff --git a/fs/ocfs2/dlm/dlmdomain.h b/fs/ocfs2/dlm/dlmdomain.h index 2f7f60bfeb3b..fd6122a38dbd 100644 --- a/fs/ocfs2/dlm/dlmdomain.h +++ b/fs/ocfs2/dlm/dlmdomain.h | |||
| @@ -28,7 +28,6 @@ | |||
| 28 | extern spinlock_t dlm_domain_lock; | 28 | extern spinlock_t dlm_domain_lock; |
| 29 | extern struct list_head dlm_domains; | 29 | extern struct list_head dlm_domains; |
| 30 | 30 | ||
| 31 | int dlm_joined(struct dlm_ctxt *dlm); | ||
| 32 | int dlm_shutting_down(struct dlm_ctxt *dlm); | 31 | int dlm_shutting_down(struct dlm_ctxt *dlm); |
| 33 | void dlm_fire_domain_eviction_callbacks(struct dlm_ctxt *dlm, | 32 | void dlm_fire_domain_eviction_callbacks(struct dlm_ctxt *dlm, |
| 34 | int node_num); | 33 | int node_num); |
diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c index 79b5af5e6a7b..ce12e0b1a31f 100644 --- a/fs/ocfs2/dlm/dlmrecovery.c +++ b/fs/ocfs2/dlm/dlmrecovery.c | |||
| @@ -1070,6 +1070,9 @@ static void dlm_move_reco_locks_to_list(struct dlm_ctxt *dlm, | |||
| 1070 | dead_node, dlm->name); | 1070 | dead_node, dlm->name); |
| 1071 | list_del_init(&lock->list); | 1071 | list_del_init(&lock->list); |
| 1072 | dlm_lock_put(lock); | 1072 | dlm_lock_put(lock); |
| 1073 | /* Can't schedule DLM_UNLOCK_FREE_LOCK | ||
| 1074 | * - do manually */ | ||
| 1075 | dlm_lock_put(lock); | ||
| 1073 | break; | 1076 | break; |
| 1074 | } | 1077 | } |
| 1075 | } | 1078 | } |
| @@ -2023,11 +2026,8 @@ leave: | |||
| 2023 | dlm_lockres_drop_inflight_ref(dlm, res); | 2026 | dlm_lockres_drop_inflight_ref(dlm, res); |
| 2024 | spin_unlock(&res->spinlock); | 2027 | spin_unlock(&res->spinlock); |
| 2025 | 2028 | ||
| 2026 | if (ret < 0) { | 2029 | if (ret < 0) |
| 2027 | mlog_errno(ret); | 2030 | mlog_errno(ret); |
| 2028 | if (newlock) | ||
| 2029 | dlm_lock_put(newlock); | ||
| 2030 | } | ||
| 2031 | 2031 | ||
| 2032 | return ret; | 2032 | return ret; |
| 2033 | } | 2033 | } |
| @@ -2349,6 +2349,10 @@ static void dlm_do_local_recovery_cleanup(struct dlm_ctxt *dlm, u8 dead_node) | |||
| 2349 | dead_node, dlm->name); | 2349 | dead_node, dlm->name); |
| 2350 | list_del_init(&lock->list); | 2350 | list_del_init(&lock->list); |
| 2351 | dlm_lock_put(lock); | 2351 | dlm_lock_put(lock); |
| 2352 | /* Can't schedule | ||
| 2353 | * DLM_UNLOCK_FREE_LOCK | ||
| 2354 | * - do manually */ | ||
| 2355 | dlm_lock_put(lock); | ||
| 2352 | break; | 2356 | break; |
| 2353 | } | 2357 | } |
| 2354 | } | 2358 | } |
diff --git a/fs/ocfs2/dlmfs/dlmfs.c b/fs/ocfs2/dlmfs/dlmfs.c index 57c40e34f56f..061ba6a91bf2 100644 --- a/fs/ocfs2/dlmfs/dlmfs.c +++ b/fs/ocfs2/dlmfs/dlmfs.c | |||
| @@ -390,12 +390,6 @@ clear_fields: | |||
| 390 | ip->ip_conn = NULL; | 390 | ip->ip_conn = NULL; |
| 391 | } | 391 | } |
| 392 | 392 | ||
| 393 | static struct backing_dev_info dlmfs_backing_dev_info = { | ||
| 394 | .name = "ocfs2-dlmfs", | ||
| 395 | .ra_pages = 0, /* No readahead */ | ||
| 396 | .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK, | ||
| 397 | }; | ||
| 398 | |||
| 399 | static struct inode *dlmfs_get_root_inode(struct super_block *sb) | 393 | static struct inode *dlmfs_get_root_inode(struct super_block *sb) |
| 400 | { | 394 | { |
| 401 | struct inode *inode = new_inode(sb); | 395 | struct inode *inode = new_inode(sb); |
| @@ -404,7 +398,6 @@ static struct inode *dlmfs_get_root_inode(struct super_block *sb) | |||
| 404 | if (inode) { | 398 | if (inode) { |
| 405 | inode->i_ino = get_next_ino(); | 399 | inode->i_ino = get_next_ino(); |
| 406 | inode_init_owner(inode, NULL, mode); | 400 | inode_init_owner(inode, NULL, mode); |
| 407 | inode->i_mapping->backing_dev_info = &dlmfs_backing_dev_info; | ||
| 408 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; | 401 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; |
| 409 | inc_nlink(inode); | 402 | inc_nlink(inode); |
| 410 | 403 | ||
| @@ -428,7 +421,6 @@ static struct inode *dlmfs_get_inode(struct inode *parent, | |||
| 428 | 421 | ||
| 429 | inode->i_ino = get_next_ino(); | 422 | inode->i_ino = get_next_ino(); |
| 430 | inode_init_owner(inode, parent, mode); | 423 | inode_init_owner(inode, parent, mode); |
| 431 | inode->i_mapping->backing_dev_info = &dlmfs_backing_dev_info; | ||
| 432 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; | 424 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; |
| 433 | 425 | ||
| 434 | ip = DLMFS_I(inode); | 426 | ip = DLMFS_I(inode); |
| @@ -643,10 +635,6 @@ static int __init init_dlmfs_fs(void) | |||
| 643 | int status; | 635 | int status; |
| 644 | int cleanup_inode = 0, cleanup_worker = 0; | 636 | int cleanup_inode = 0, cleanup_worker = 0; |
| 645 | 637 | ||
| 646 | status = bdi_init(&dlmfs_backing_dev_info); | ||
| 647 | if (status) | ||
| 648 | return status; | ||
| 649 | |||
| 650 | dlmfs_inode_cache = kmem_cache_create("dlmfs_inode_cache", | 638 | dlmfs_inode_cache = kmem_cache_create("dlmfs_inode_cache", |
| 651 | sizeof(struct dlmfs_inode_private), | 639 | sizeof(struct dlmfs_inode_private), |
| 652 | 0, (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT| | 640 | 0, (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT| |
| @@ -673,7 +661,6 @@ bail: | |||
| 673 | kmem_cache_destroy(dlmfs_inode_cache); | 661 | kmem_cache_destroy(dlmfs_inode_cache); |
| 674 | if (cleanup_worker) | 662 | if (cleanup_worker) |
| 675 | destroy_workqueue(user_dlm_worker); | 663 | destroy_workqueue(user_dlm_worker); |
| 676 | bdi_destroy(&dlmfs_backing_dev_info); | ||
| 677 | } else | 664 | } else |
| 678 | printk("OCFS2 User DLM kernel interface loaded\n"); | 665 | printk("OCFS2 User DLM kernel interface loaded\n"); |
| 679 | return status; | 666 | return status; |
| @@ -693,7 +680,6 @@ static void __exit exit_dlmfs_fs(void) | |||
| 693 | rcu_barrier(); | 680 | rcu_barrier(); |
| 694 | kmem_cache_destroy(dlmfs_inode_cache); | 681 | kmem_cache_destroy(dlmfs_inode_cache); |
| 695 | 682 | ||
| 696 | bdi_destroy(&dlmfs_backing_dev_info); | ||
| 697 | } | 683 | } |
| 698 | 684 | ||
| 699 | MODULE_AUTHOR("Oracle"); | 685 | MODULE_AUTHOR("Oracle"); |
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 1c423af04c69..11849a44dc5a 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c | |||
| @@ -3750,6 +3750,9 @@ static int ocfs2_dentry_convert_worker(struct ocfs2_lock_res *lockres, | |||
| 3750 | break; | 3750 | break; |
| 3751 | spin_unlock(&dentry_attach_lock); | 3751 | spin_unlock(&dentry_attach_lock); |
| 3752 | 3752 | ||
| 3753 | if (S_ISDIR(dl->dl_inode->i_mode)) | ||
| 3754 | shrink_dcache_parent(dentry); | ||
| 3755 | |||
| 3753 | mlog(0, "d_delete(%pd);\n", dentry); | 3756 | mlog(0, "d_delete(%pd);\n", dentry); |
| 3754 | 3757 | ||
| 3755 | /* | 3758 | /* |
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 3950693dd0f6..46e0d4e857c7 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
| @@ -295,7 +295,7 @@ out: | |||
| 295 | return ret; | 295 | return ret; |
| 296 | } | 296 | } |
| 297 | 297 | ||
| 298 | static int ocfs2_set_inode_size(handle_t *handle, | 298 | int ocfs2_set_inode_size(handle_t *handle, |
| 299 | struct inode *inode, | 299 | struct inode *inode, |
| 300 | struct buffer_head *fe_bh, | 300 | struct buffer_head *fe_bh, |
| 301 | u64 new_i_size) | 301 | u64 new_i_size) |
| @@ -441,7 +441,7 @@ out: | |||
| 441 | return status; | 441 | return status; |
| 442 | } | 442 | } |
| 443 | 443 | ||
| 444 | static int ocfs2_truncate_file(struct inode *inode, | 444 | int ocfs2_truncate_file(struct inode *inode, |
| 445 | struct buffer_head *di_bh, | 445 | struct buffer_head *di_bh, |
| 446 | u64 new_i_size) | 446 | u64 new_i_size) |
| 447 | { | 447 | { |
| @@ -569,7 +569,7 @@ static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start, | |||
| 569 | handle_t *handle = NULL; | 569 | handle_t *handle = NULL; |
| 570 | struct ocfs2_alloc_context *data_ac = NULL; | 570 | struct ocfs2_alloc_context *data_ac = NULL; |
| 571 | struct ocfs2_alloc_context *meta_ac = NULL; | 571 | struct ocfs2_alloc_context *meta_ac = NULL; |
| 572 | enum ocfs2_alloc_restarted why; | 572 | enum ocfs2_alloc_restarted why = RESTART_NONE; |
| 573 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 573 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
| 574 | struct ocfs2_extent_tree et; | 574 | struct ocfs2_extent_tree et; |
| 575 | int did_quota = 0; | 575 | int did_quota = 0; |
| @@ -709,6 +709,13 @@ leave: | |||
| 709 | return status; | 709 | return status; |
| 710 | } | 710 | } |
| 711 | 711 | ||
| 712 | int ocfs2_extend_allocation(struct inode *inode, u32 logical_start, | ||
| 713 | u32 clusters_to_add, int mark_unwritten) | ||
| 714 | { | ||
| 715 | return __ocfs2_extend_allocation(inode, logical_start, | ||
| 716 | clusters_to_add, mark_unwritten); | ||
| 717 | } | ||
| 718 | |||
| 712 | /* | 719 | /* |
| 713 | * While a write will already be ordering the data, a truncate will not. | 720 | * While a write will already be ordering the data, a truncate will not. |
| 714 | * Thus, we need to explicitly order the zeroed pages. | 721 | * Thus, we need to explicitly order the zeroed pages. |
| @@ -2109,6 +2116,9 @@ static int ocfs2_prepare_inode_for_write(struct file *file, | |||
| 2109 | struct dentry *dentry = file->f_path.dentry; | 2116 | struct dentry *dentry = file->f_path.dentry; |
| 2110 | struct inode *inode = dentry->d_inode; | 2117 | struct inode *inode = dentry->d_inode; |
| 2111 | loff_t saved_pos = 0, end; | 2118 | loff_t saved_pos = 0, end; |
| 2119 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
| 2120 | int full_coherency = !(osb->s_mount_opt & | ||
| 2121 | OCFS2_MOUNT_COHERENCY_BUFFERED); | ||
| 2112 | 2122 | ||
| 2113 | /* | 2123 | /* |
| 2114 | * We start with a read level meta lock and only jump to an ex | 2124 | * We start with a read level meta lock and only jump to an ex |
| @@ -2197,7 +2207,16 @@ static int ocfs2_prepare_inode_for_write(struct file *file, | |||
| 2197 | * one node could wind up truncating another | 2207 | * one node could wind up truncating another |
| 2198 | * nodes writes. | 2208 | * nodes writes. |
| 2199 | */ | 2209 | */ |
| 2200 | if (end > i_size_read(inode)) { | 2210 | if (end > i_size_read(inode) && !full_coherency) { |
| 2211 | *direct_io = 0; | ||
| 2212 | break; | ||
| 2213 | } | ||
| 2214 | |||
| 2215 | /* | ||
| 2216 | * Fallback to old way if the feature bit is not set. | ||
| 2217 | */ | ||
| 2218 | if (end > i_size_read(inode) && | ||
| 2219 | !ocfs2_supports_append_dio(osb)) { | ||
| 2201 | *direct_io = 0; | 2220 | *direct_io = 0; |
| 2202 | break; | 2221 | break; |
| 2203 | } | 2222 | } |
| @@ -2210,7 +2229,13 @@ static int ocfs2_prepare_inode_for_write(struct file *file, | |||
| 2210 | */ | 2229 | */ |
| 2211 | ret = ocfs2_check_range_for_holes(inode, saved_pos, count); | 2230 | ret = ocfs2_check_range_for_holes(inode, saved_pos, count); |
| 2212 | if (ret == 1) { | 2231 | if (ret == 1) { |
| 2213 | *direct_io = 0; | 2232 | /* |
| 2233 | * Fallback to old way if the feature bit is not set. | ||
| 2234 | * Otherwise try dio first and then complete the rest | ||
| 2235 | * request through buffer io. | ||
| 2236 | */ | ||
| 2237 | if (!ocfs2_supports_append_dio(osb)) | ||
| 2238 | *direct_io = 0; | ||
| 2214 | ret = 0; | 2239 | ret = 0; |
| 2215 | } else if (ret < 0) | 2240 | } else if (ret < 0) |
| 2216 | mlog_errno(ret); | 2241 | mlog_errno(ret); |
| @@ -2243,6 +2268,7 @@ static ssize_t ocfs2_file_write_iter(struct kiocb *iocb, | |||
| 2243 | u32 old_clusters; | 2268 | u32 old_clusters; |
| 2244 | struct file *file = iocb->ki_filp; | 2269 | struct file *file = iocb->ki_filp; |
| 2245 | struct inode *inode = file_inode(file); | 2270 | struct inode *inode = file_inode(file); |
| 2271 | struct address_space *mapping = file->f_mapping; | ||
| 2246 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 2272 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
| 2247 | int full_coherency = !(osb->s_mount_opt & | 2273 | int full_coherency = !(osb->s_mount_opt & |
| 2248 | OCFS2_MOUNT_COHERENCY_BUFFERED); | 2274 | OCFS2_MOUNT_COHERENCY_BUFFERED); |
| @@ -2357,13 +2383,53 @@ relock: | |||
| 2357 | 2383 | ||
| 2358 | iov_iter_truncate(from, count); | 2384 | iov_iter_truncate(from, count); |
| 2359 | if (direct_io) { | 2385 | if (direct_io) { |
| 2386 | loff_t endbyte; | ||
| 2387 | ssize_t written_buffered; | ||
| 2360 | written = generic_file_direct_write(iocb, from, *ppos); | 2388 | written = generic_file_direct_write(iocb, from, *ppos); |
| 2361 | if (written < 0) { | 2389 | if (written < 0 || written == count) { |
| 2362 | ret = written; | 2390 | ret = written; |
| 2363 | goto out_dio; | 2391 | goto out_dio; |
| 2364 | } | 2392 | } |
| 2393 | |||
| 2394 | /* | ||
| 2395 | * for completing the rest of the request. | ||
| 2396 | */ | ||
| 2397 | *ppos += written; | ||
| 2398 | count -= written; | ||
| 2399 | written_buffered = generic_perform_write(file, from, *ppos); | ||
| 2400 | /* | ||
| 2401 | * If generic_file_buffered_write() returned a synchronous error | ||
| 2402 | * then we want to return the number of bytes which were | ||
| 2403 | * direct-written, or the error code if that was zero. Note | ||
| 2404 | * that this differs from normal direct-io semantics, which | ||
| 2405 | * will return -EFOO even if some bytes were written. | ||
| 2406 | */ | ||
| 2407 | if (written_buffered < 0) { | ||
| 2408 | ret = written_buffered; | ||
| 2409 | goto out_dio; | ||
| 2410 | } | ||
| 2411 | |||
| 2412 | iocb->ki_pos = *ppos + written_buffered; | ||
| 2413 | /* We need to ensure that the page cache pages are written to | ||
| 2414 | * disk and invalidated to preserve the expected O_DIRECT | ||
| 2415 | * semantics. | ||
| 2416 | */ | ||
| 2417 | endbyte = *ppos + written_buffered - 1; | ||
| 2418 | ret = filemap_write_and_wait_range(file->f_mapping, *ppos, | ||
| 2419 | endbyte); | ||
| 2420 | if (ret == 0) { | ||
| 2421 | written += written_buffered; | ||
| 2422 | invalidate_mapping_pages(mapping, | ||
| 2423 | *ppos >> PAGE_CACHE_SHIFT, | ||
| 2424 | endbyte >> PAGE_CACHE_SHIFT); | ||
| 2425 | } else { | ||
| 2426 | /* | ||
| 2427 | * We don't know how much we wrote, so just return | ||
| 2428 | * the number of bytes which were direct-written | ||
| 2429 | */ | ||
| 2430 | } | ||
| 2365 | } else { | 2431 | } else { |
| 2366 | current->backing_dev_info = file->f_mapping->backing_dev_info; | 2432 | current->backing_dev_info = inode_to_bdi(inode); |
| 2367 | written = generic_perform_write(file, from, *ppos); | 2433 | written = generic_perform_write(file, from, *ppos); |
| 2368 | if (likely(written >= 0)) | 2434 | if (likely(written >= 0)) |
| 2369 | iocb->ki_pos = *ppos + written; | 2435 | iocb->ki_pos = *ppos + written; |
diff --git a/fs/ocfs2/file.h b/fs/ocfs2/file.h index 97bf761c9e7c..e8c62f22215c 100644 --- a/fs/ocfs2/file.h +++ b/fs/ocfs2/file.h | |||
| @@ -51,13 +51,22 @@ int ocfs2_add_inode_data(struct ocfs2_super *osb, | |||
| 51 | struct ocfs2_alloc_context *data_ac, | 51 | struct ocfs2_alloc_context *data_ac, |
| 52 | struct ocfs2_alloc_context *meta_ac, | 52 | struct ocfs2_alloc_context *meta_ac, |
| 53 | enum ocfs2_alloc_restarted *reason_ret); | 53 | enum ocfs2_alloc_restarted *reason_ret); |
| 54 | int ocfs2_set_inode_size(handle_t *handle, | ||
| 55 | struct inode *inode, | ||
| 56 | struct buffer_head *fe_bh, | ||
| 57 | u64 new_i_size); | ||
| 54 | int ocfs2_simple_size_update(struct inode *inode, | 58 | int ocfs2_simple_size_update(struct inode *inode, |
| 55 | struct buffer_head *di_bh, | 59 | struct buffer_head *di_bh, |
| 56 | u64 new_i_size); | 60 | u64 new_i_size); |
| 61 | int ocfs2_truncate_file(struct inode *inode, | ||
| 62 | struct buffer_head *di_bh, | ||
| 63 | u64 new_i_size); | ||
| 57 | int ocfs2_extend_no_holes(struct inode *inode, struct buffer_head *di_bh, | 64 | int ocfs2_extend_no_holes(struct inode *inode, struct buffer_head *di_bh, |
| 58 | u64 new_i_size, u64 zero_to); | 65 | u64 new_i_size, u64 zero_to); |
| 59 | int ocfs2_zero_extend(struct inode *inode, struct buffer_head *di_bh, | 66 | int ocfs2_zero_extend(struct inode *inode, struct buffer_head *di_bh, |
| 60 | loff_t zero_to); | 67 | loff_t zero_to); |
| 68 | int ocfs2_extend_allocation(struct inode *inode, u32 logical_start, | ||
| 69 | u32 clusters_to_add, int mark_unwritten); | ||
| 61 | int ocfs2_setattr(struct dentry *dentry, struct iattr *attr); | 70 | int ocfs2_setattr(struct dentry *dentry, struct iattr *attr); |
| 62 | int ocfs2_getattr(struct vfsmount *mnt, struct dentry *dentry, | 71 | int ocfs2_getattr(struct vfsmount *mnt, struct dentry *dentry, |
| 63 | struct kstat *stat); | 72 | struct kstat *stat); |
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index c8b25de9efbb..3025c0da6b8a 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c | |||
| @@ -648,7 +648,7 @@ static int ocfs2_remove_inode(struct inode *inode, | |||
| 648 | 648 | ||
| 649 | if (!(OCFS2_I(inode)->ip_flags & OCFS2_INODE_SKIP_ORPHAN_DIR)) { | 649 | if (!(OCFS2_I(inode)->ip_flags & OCFS2_INODE_SKIP_ORPHAN_DIR)) { |
| 650 | status = ocfs2_orphan_del(osb, handle, orphan_dir_inode, inode, | 650 | status = ocfs2_orphan_del(osb, handle, orphan_dir_inode, inode, |
| 651 | orphan_dir_bh); | 651 | orphan_dir_bh, false); |
| 652 | if (status < 0) { | 652 | if (status < 0) { |
| 653 | mlog_errno(status); | 653 | mlog_errno(status); |
| 654 | goto bail_commit; | 654 | goto bail_commit; |
diff --git a/fs/ocfs2/inode.h b/fs/ocfs2/inode.h index ca3431ee7f24..5e86b247c821 100644 --- a/fs/ocfs2/inode.h +++ b/fs/ocfs2/inode.h | |||
| @@ -81,6 +81,8 @@ struct ocfs2_inode_info | |||
| 81 | tid_t i_sync_tid; | 81 | tid_t i_sync_tid; |
| 82 | tid_t i_datasync_tid; | 82 | tid_t i_datasync_tid; |
| 83 | 83 | ||
| 84 | wait_queue_head_t append_dio_wq; | ||
| 85 | |||
| 84 | struct dquot *i_dquot[MAXQUOTAS]; | 86 | struct dquot *i_dquot[MAXQUOTAS]; |
| 85 | }; | 87 | }; |
| 86 | 88 | ||
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index 4f502382180f..ff531928269e 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c | |||
| @@ -50,6 +50,8 @@ | |||
| 50 | #include "sysfile.h" | 50 | #include "sysfile.h" |
| 51 | #include "uptodate.h" | 51 | #include "uptodate.h" |
| 52 | #include "quota.h" | 52 | #include "quota.h" |
| 53 | #include "file.h" | ||
| 54 | #include "namei.h" | ||
| 53 | 55 | ||
| 54 | #include "buffer_head_io.h" | 56 | #include "buffer_head_io.h" |
| 55 | #include "ocfs2_trace.h" | 57 | #include "ocfs2_trace.h" |
| @@ -69,13 +71,15 @@ static int ocfs2_journal_toggle_dirty(struct ocfs2_super *osb, | |||
| 69 | static int ocfs2_trylock_journal(struct ocfs2_super *osb, | 71 | static int ocfs2_trylock_journal(struct ocfs2_super *osb, |
| 70 | int slot_num); | 72 | int slot_num); |
| 71 | static int ocfs2_recover_orphans(struct ocfs2_super *osb, | 73 | static int ocfs2_recover_orphans(struct ocfs2_super *osb, |
| 72 | int slot); | 74 | int slot, |
| 75 | enum ocfs2_orphan_reco_type orphan_reco_type); | ||
| 73 | static int ocfs2_commit_thread(void *arg); | 76 | static int ocfs2_commit_thread(void *arg); |
| 74 | static void ocfs2_queue_recovery_completion(struct ocfs2_journal *journal, | 77 | static void ocfs2_queue_recovery_completion(struct ocfs2_journal *journal, |
| 75 | int slot_num, | 78 | int slot_num, |
| 76 | struct ocfs2_dinode *la_dinode, | 79 | struct ocfs2_dinode *la_dinode, |
| 77 | struct ocfs2_dinode *tl_dinode, | 80 | struct ocfs2_dinode *tl_dinode, |
| 78 | struct ocfs2_quota_recovery *qrec); | 81 | struct ocfs2_quota_recovery *qrec, |
| 82 | enum ocfs2_orphan_reco_type orphan_reco_type); | ||
| 79 | 83 | ||
| 80 | static inline int ocfs2_wait_on_mount(struct ocfs2_super *osb) | 84 | static inline int ocfs2_wait_on_mount(struct ocfs2_super *osb) |
| 81 | { | 85 | { |
| @@ -149,7 +153,8 @@ int ocfs2_compute_replay_slots(struct ocfs2_super *osb) | |||
| 149 | return 0; | 153 | return 0; |
| 150 | } | 154 | } |
| 151 | 155 | ||
| 152 | void ocfs2_queue_replay_slots(struct ocfs2_super *osb) | 156 | void ocfs2_queue_replay_slots(struct ocfs2_super *osb, |
| 157 | enum ocfs2_orphan_reco_type orphan_reco_type) | ||
| 153 | { | 158 | { |
| 154 | struct ocfs2_replay_map *replay_map = osb->replay_map; | 159 | struct ocfs2_replay_map *replay_map = osb->replay_map; |
| 155 | int i; | 160 | int i; |
| @@ -163,7 +168,8 @@ void ocfs2_queue_replay_slots(struct ocfs2_super *osb) | |||
| 163 | for (i = 0; i < replay_map->rm_slots; i++) | 168 | for (i = 0; i < replay_map->rm_slots; i++) |
| 164 | if (replay_map->rm_replay_slots[i]) | 169 | if (replay_map->rm_replay_slots[i]) |
| 165 | ocfs2_queue_recovery_completion(osb->journal, i, NULL, | 170 | ocfs2_queue_recovery_completion(osb->journal, i, NULL, |
| 166 | NULL, NULL); | 171 | NULL, NULL, |
| 172 | orphan_reco_type); | ||
| 167 | replay_map->rm_state = REPLAY_DONE; | 173 | replay_map->rm_state = REPLAY_DONE; |
| 168 | } | 174 | } |
| 169 | 175 | ||
| @@ -1174,6 +1180,7 @@ struct ocfs2_la_recovery_item { | |||
| 1174 | struct ocfs2_dinode *lri_la_dinode; | 1180 | struct ocfs2_dinode *lri_la_dinode; |
| 1175 | struct ocfs2_dinode *lri_tl_dinode; | 1181 | struct ocfs2_dinode *lri_tl_dinode; |
| 1176 | struct ocfs2_quota_recovery *lri_qrec; | 1182 | struct ocfs2_quota_recovery *lri_qrec; |
| 1183 | enum ocfs2_orphan_reco_type lri_orphan_reco_type; | ||
| 1177 | }; | 1184 | }; |
| 1178 | 1185 | ||
| 1179 | /* Does the second half of the recovery process. By this point, the | 1186 | /* Does the second half of the recovery process. By this point, the |
| @@ -1195,6 +1202,7 @@ void ocfs2_complete_recovery(struct work_struct *work) | |||
| 1195 | struct ocfs2_dinode *la_dinode, *tl_dinode; | 1202 | struct ocfs2_dinode *la_dinode, *tl_dinode; |
| 1196 | struct ocfs2_la_recovery_item *item, *n; | 1203 | struct ocfs2_la_recovery_item *item, *n; |
| 1197 | struct ocfs2_quota_recovery *qrec; | 1204 | struct ocfs2_quota_recovery *qrec; |
| 1205 | enum ocfs2_orphan_reco_type orphan_reco_type; | ||
| 1198 | LIST_HEAD(tmp_la_list); | 1206 | LIST_HEAD(tmp_la_list); |
| 1199 | 1207 | ||
| 1200 | trace_ocfs2_complete_recovery( | 1208 | trace_ocfs2_complete_recovery( |
| @@ -1212,6 +1220,7 @@ void ocfs2_complete_recovery(struct work_struct *work) | |||
| 1212 | la_dinode = item->lri_la_dinode; | 1220 | la_dinode = item->lri_la_dinode; |
| 1213 | tl_dinode = item->lri_tl_dinode; | 1221 | tl_dinode = item->lri_tl_dinode; |
| 1214 | qrec = item->lri_qrec; | 1222 | qrec = item->lri_qrec; |
| 1223 | orphan_reco_type = item->lri_orphan_reco_type; | ||
| 1215 | 1224 | ||
| 1216 | trace_ocfs2_complete_recovery_slot(item->lri_slot, | 1225 | trace_ocfs2_complete_recovery_slot(item->lri_slot, |
| 1217 | la_dinode ? le64_to_cpu(la_dinode->i_blkno) : 0, | 1226 | la_dinode ? le64_to_cpu(la_dinode->i_blkno) : 0, |
| @@ -1236,7 +1245,8 @@ void ocfs2_complete_recovery(struct work_struct *work) | |||
| 1236 | kfree(tl_dinode); | 1245 | kfree(tl_dinode); |
| 1237 | } | 1246 | } |
| 1238 | 1247 | ||
| 1239 | ret = ocfs2_recover_orphans(osb, item->lri_slot); | 1248 | ret = ocfs2_recover_orphans(osb, item->lri_slot, |
| 1249 | orphan_reco_type); | ||
| 1240 | if (ret < 0) | 1250 | if (ret < 0) |
| 1241 | mlog_errno(ret); | 1251 | mlog_errno(ret); |
| 1242 | 1252 | ||
| @@ -1261,7 +1271,8 @@ static void ocfs2_queue_recovery_completion(struct ocfs2_journal *journal, | |||
| 1261 | int slot_num, | 1271 | int slot_num, |
| 1262 | struct ocfs2_dinode *la_dinode, | 1272 | struct ocfs2_dinode *la_dinode, |
| 1263 | struct ocfs2_dinode *tl_dinode, | 1273 | struct ocfs2_dinode *tl_dinode, |
| 1264 | struct ocfs2_quota_recovery *qrec) | 1274 | struct ocfs2_quota_recovery *qrec, |
| 1275 | enum ocfs2_orphan_reco_type orphan_reco_type) | ||
| 1265 | { | 1276 | { |
| 1266 | struct ocfs2_la_recovery_item *item; | 1277 | struct ocfs2_la_recovery_item *item; |
| 1267 | 1278 | ||
| @@ -1285,6 +1296,7 @@ static void ocfs2_queue_recovery_completion(struct ocfs2_journal *journal, | |||
| 1285 | item->lri_slot = slot_num; | 1296 | item->lri_slot = slot_num; |
| 1286 | item->lri_tl_dinode = tl_dinode; | 1297 | item->lri_tl_dinode = tl_dinode; |
| 1287 | item->lri_qrec = qrec; | 1298 | item->lri_qrec = qrec; |
| 1299 | item->lri_orphan_reco_type = orphan_reco_type; | ||
| 1288 | 1300 | ||
| 1289 | spin_lock(&journal->j_lock); | 1301 | spin_lock(&journal->j_lock); |
| 1290 | list_add_tail(&item->lri_list, &journal->j_la_cleanups); | 1302 | list_add_tail(&item->lri_list, &journal->j_la_cleanups); |
| @@ -1304,7 +1316,8 @@ void ocfs2_complete_mount_recovery(struct ocfs2_super *osb) | |||
| 1304 | /* No need to queue up our truncate_log as regular cleanup will catch | 1316 | /* No need to queue up our truncate_log as regular cleanup will catch |
| 1305 | * that */ | 1317 | * that */ |
| 1306 | ocfs2_queue_recovery_completion(journal, osb->slot_num, | 1318 | ocfs2_queue_recovery_completion(journal, osb->slot_num, |
| 1307 | osb->local_alloc_copy, NULL, NULL); | 1319 | osb->local_alloc_copy, NULL, NULL, |
| 1320 | ORPHAN_NEED_TRUNCATE); | ||
| 1308 | ocfs2_schedule_truncate_log_flush(osb, 0); | 1321 | ocfs2_schedule_truncate_log_flush(osb, 0); |
| 1309 | 1322 | ||
| 1310 | osb->local_alloc_copy = NULL; | 1323 | osb->local_alloc_copy = NULL; |
| @@ -1312,7 +1325,7 @@ void ocfs2_complete_mount_recovery(struct ocfs2_super *osb) | |||
| 1312 | 1325 | ||
| 1313 | /* queue to recover orphan slots for all offline slots */ | 1326 | /* queue to recover orphan slots for all offline slots */ |
| 1314 | ocfs2_replay_map_set_state(osb, REPLAY_NEEDED); | 1327 | ocfs2_replay_map_set_state(osb, REPLAY_NEEDED); |
| 1315 | ocfs2_queue_replay_slots(osb); | 1328 | ocfs2_queue_replay_slots(osb, ORPHAN_NEED_TRUNCATE); |
| 1316 | ocfs2_free_replay_slots(osb); | 1329 | ocfs2_free_replay_slots(osb); |
| 1317 | } | 1330 | } |
| 1318 | 1331 | ||
| @@ -1323,7 +1336,8 @@ void ocfs2_complete_quota_recovery(struct ocfs2_super *osb) | |||
| 1323 | osb->slot_num, | 1336 | osb->slot_num, |
| 1324 | NULL, | 1337 | NULL, |
| 1325 | NULL, | 1338 | NULL, |
| 1326 | osb->quota_rec); | 1339 | osb->quota_rec, |
| 1340 | ORPHAN_NEED_TRUNCATE); | ||
| 1327 | osb->quota_rec = NULL; | 1341 | osb->quota_rec = NULL; |
| 1328 | } | 1342 | } |
| 1329 | } | 1343 | } |
| @@ -1360,7 +1374,7 @@ restart: | |||
| 1360 | 1374 | ||
| 1361 | /* queue recovery for our own slot */ | 1375 | /* queue recovery for our own slot */ |
| 1362 | ocfs2_queue_recovery_completion(osb->journal, osb->slot_num, NULL, | 1376 | ocfs2_queue_recovery_completion(osb->journal, osb->slot_num, NULL, |
| 1363 | NULL, NULL); | 1377 | NULL, NULL, ORPHAN_NO_NEED_TRUNCATE); |
| 1364 | 1378 | ||
| 1365 | spin_lock(&osb->osb_lock); | 1379 | spin_lock(&osb->osb_lock); |
| 1366 | while (rm->rm_used) { | 1380 | while (rm->rm_used) { |
| @@ -1419,13 +1433,14 @@ skip_recovery: | |||
| 1419 | continue; | 1433 | continue; |
| 1420 | } | 1434 | } |
| 1421 | ocfs2_queue_recovery_completion(osb->journal, rm_quota[i], | 1435 | ocfs2_queue_recovery_completion(osb->journal, rm_quota[i], |
| 1422 | NULL, NULL, qrec); | 1436 | NULL, NULL, qrec, |
| 1437 | ORPHAN_NEED_TRUNCATE); | ||
| 1423 | } | 1438 | } |
| 1424 | 1439 | ||
| 1425 | ocfs2_super_unlock(osb, 1); | 1440 | ocfs2_super_unlock(osb, 1); |
| 1426 | 1441 | ||
| 1427 | /* queue recovery for offline slots */ | 1442 | /* queue recovery for offline slots */ |
| 1428 | ocfs2_queue_replay_slots(osb); | 1443 | ocfs2_queue_replay_slots(osb, ORPHAN_NEED_TRUNCATE); |
| 1429 | 1444 | ||
| 1430 | bail: | 1445 | bail: |
| 1431 | mutex_lock(&osb->recovery_lock); | 1446 | mutex_lock(&osb->recovery_lock); |
| @@ -1447,7 +1462,6 @@ bail: | |||
| 1447 | * requires that we call do_exit(). And it isn't exported, but | 1462 | * requires that we call do_exit(). And it isn't exported, but |
| 1448 | * complete_and_exit() seems to be a minimal wrapper around it. */ | 1463 | * complete_and_exit() seems to be a minimal wrapper around it. */ |
| 1449 | complete_and_exit(NULL, status); | 1464 | complete_and_exit(NULL, status); |
| 1450 | return status; | ||
| 1451 | } | 1465 | } |
| 1452 | 1466 | ||
| 1453 | void ocfs2_recovery_thread(struct ocfs2_super *osb, int node_num) | 1467 | void ocfs2_recovery_thread(struct ocfs2_super *osb, int node_num) |
| @@ -1712,7 +1726,7 @@ static int ocfs2_recover_node(struct ocfs2_super *osb, | |||
| 1712 | 1726 | ||
| 1713 | /* This will kfree the memory pointed to by la_copy and tl_copy */ | 1727 | /* This will kfree the memory pointed to by la_copy and tl_copy */ |
| 1714 | ocfs2_queue_recovery_completion(osb->journal, slot_num, la_copy, | 1728 | ocfs2_queue_recovery_completion(osb->journal, slot_num, la_copy, |
| 1715 | tl_copy, NULL); | 1729 | tl_copy, NULL, ORPHAN_NEED_TRUNCATE); |
| 1716 | 1730 | ||
| 1717 | status = 0; | 1731 | status = 0; |
| 1718 | done: | 1732 | done: |
| @@ -1902,7 +1916,7 @@ void ocfs2_queue_orphan_scan(struct ocfs2_super *osb) | |||
| 1902 | 1916 | ||
| 1903 | for (i = 0; i < osb->max_slots; i++) | 1917 | for (i = 0; i < osb->max_slots; i++) |
| 1904 | ocfs2_queue_recovery_completion(osb->journal, i, NULL, NULL, | 1918 | ocfs2_queue_recovery_completion(osb->journal, i, NULL, NULL, |
| 1905 | NULL); | 1919 | NULL, ORPHAN_NO_NEED_TRUNCATE); |
| 1906 | /* | 1920 | /* |
| 1907 | * We queued a recovery on orphan slots, increment the sequence | 1921 | * We queued a recovery on orphan slots, increment the sequence |
| 1908 | * number and update LVB so other node will skip the scan for a while | 1922 | * number and update LVB so other node will skip the scan for a while |
| @@ -2001,6 +2015,13 @@ static int ocfs2_orphan_filldir(struct dir_context *ctx, const char *name, | |||
| 2001 | if (IS_ERR(iter)) | 2015 | if (IS_ERR(iter)) |
| 2002 | return 0; | 2016 | return 0; |
| 2003 | 2017 | ||
| 2018 | /* Skip inodes which are already added to recover list, since dio may | ||
| 2019 | * happen concurrently with unlink/rename */ | ||
| 2020 | if (OCFS2_I(iter)->ip_next_orphan) { | ||
| 2021 | iput(iter); | ||
| 2022 | return 0; | ||
| 2023 | } | ||
| 2024 | |||
| 2004 | trace_ocfs2_orphan_filldir((unsigned long long)OCFS2_I(iter)->ip_blkno); | 2025 | trace_ocfs2_orphan_filldir((unsigned long long)OCFS2_I(iter)->ip_blkno); |
| 2005 | /* No locking is required for the next_orphan queue as there | 2026 | /* No locking is required for the next_orphan queue as there |
| 2006 | * is only ever a single process doing orphan recovery. */ | 2027 | * is only ever a single process doing orphan recovery. */ |
| @@ -2109,7 +2130,8 @@ static void ocfs2_clear_recovering_orphan_dir(struct ocfs2_super *osb, | |||
| 2109 | * advertising our state to ocfs2_delete_inode(). | 2130 | * advertising our state to ocfs2_delete_inode(). |
| 2110 | */ | 2131 | */ |
| 2111 | static int ocfs2_recover_orphans(struct ocfs2_super *osb, | 2132 | static int ocfs2_recover_orphans(struct ocfs2_super *osb, |
| 2112 | int slot) | 2133 | int slot, |
| 2134 | enum ocfs2_orphan_reco_type orphan_reco_type) | ||
| 2113 | { | 2135 | { |
| 2114 | int ret = 0; | 2136 | int ret = 0; |
| 2115 | struct inode *inode = NULL; | 2137 | struct inode *inode = NULL; |
| @@ -2133,13 +2155,60 @@ static int ocfs2_recover_orphans(struct ocfs2_super *osb, | |||
| 2133 | (unsigned long long)oi->ip_blkno); | 2155 | (unsigned long long)oi->ip_blkno); |
| 2134 | 2156 | ||
| 2135 | iter = oi->ip_next_orphan; | 2157 | iter = oi->ip_next_orphan; |
| 2158 | oi->ip_next_orphan = NULL; | ||
| 2159 | |||
| 2160 | /* | ||
| 2161 | * We need to take and drop the inode lock to | ||
| 2162 | * force read inode from disk. | ||
| 2163 | */ | ||
| 2164 | ret = ocfs2_inode_lock(inode, NULL, 0); | ||
| 2165 | if (ret) { | ||
| 2166 | mlog_errno(ret); | ||
| 2167 | goto next; | ||
| 2168 | } | ||
| 2169 | ocfs2_inode_unlock(inode, 0); | ||
| 2170 | |||
| 2171 | if (inode->i_nlink == 0) { | ||
| 2172 | spin_lock(&oi->ip_lock); | ||
| 2173 | /* Set the proper information to get us going into | ||
| 2174 | * ocfs2_delete_inode. */ | ||
| 2175 | oi->ip_flags |= OCFS2_INODE_MAYBE_ORPHANED; | ||
| 2176 | spin_unlock(&oi->ip_lock); | ||
| 2177 | } else if (orphan_reco_type == ORPHAN_NEED_TRUNCATE) { | ||
| 2178 | struct buffer_head *di_bh = NULL; | ||
| 2179 | |||
| 2180 | ret = ocfs2_rw_lock(inode, 1); | ||
| 2181 | if (ret) { | ||
| 2182 | mlog_errno(ret); | ||
| 2183 | goto next; | ||
| 2184 | } | ||
| 2185 | |||
| 2186 | ret = ocfs2_inode_lock(inode, &di_bh, 1); | ||
| 2187 | if (ret < 0) { | ||
| 2188 | ocfs2_rw_unlock(inode, 1); | ||
| 2189 | mlog_errno(ret); | ||
| 2190 | goto next; | ||
| 2191 | } | ||
| 2192 | |||
| 2193 | ret = ocfs2_truncate_file(inode, di_bh, | ||
| 2194 | i_size_read(inode)); | ||
| 2195 | ocfs2_inode_unlock(inode, 1); | ||
| 2196 | ocfs2_rw_unlock(inode, 1); | ||
| 2197 | brelse(di_bh); | ||
| 2198 | if (ret < 0) { | ||
| 2199 | if (ret != -ENOSPC) | ||
| 2200 | mlog_errno(ret); | ||
| 2201 | goto next; | ||
| 2202 | } | ||
| 2203 | |||
| 2204 | ret = ocfs2_del_inode_from_orphan(osb, inode, 0, 0); | ||
| 2205 | if (ret) | ||
| 2206 | mlog_errno(ret); | ||
| 2136 | 2207 | ||
| 2137 | spin_lock(&oi->ip_lock); | 2208 | wake_up(&OCFS2_I(inode)->append_dio_wq); |
| 2138 | /* Set the proper information to get us going into | 2209 | } /* else if ORPHAN_NO_NEED_TRUNCATE, do nothing */ |
| 2139 | * ocfs2_delete_inode. */ | ||
| 2140 | oi->ip_flags |= OCFS2_INODE_MAYBE_ORPHANED; | ||
| 2141 | spin_unlock(&oi->ip_lock); | ||
| 2142 | 2210 | ||
| 2211 | next: | ||
| 2143 | iput(inode); | 2212 | iput(inode); |
| 2144 | 2213 | ||
| 2145 | inode = iter; | 2214 | inode = iter; |
diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h index 7f8cde94abfe..f4cd3c3e9fb7 100644 --- a/fs/ocfs2/journal.h +++ b/fs/ocfs2/journal.h | |||
| @@ -472,6 +472,11 @@ static inline int ocfs2_unlink_credits(struct super_block *sb) | |||
| 472 | * orphan dir index leaf */ | 472 | * orphan dir index leaf */ |
| 473 | #define OCFS2_DELETE_INODE_CREDITS (3 * OCFS2_INODE_UPDATE_CREDITS + 4) | 473 | #define OCFS2_DELETE_INODE_CREDITS (3 * OCFS2_INODE_UPDATE_CREDITS + 4) |
| 474 | 474 | ||
| 475 | /* dinode + orphan dir dinode + extent tree leaf block + orphan dir entry + | ||
| 476 | * orphan dir index root + orphan dir index leaf */ | ||
| 477 | #define OCFS2_INODE_ADD_TO_ORPHAN_CREDITS (2 * OCFS2_INODE_UPDATE_CREDITS + 4) | ||
| 478 | #define OCFS2_INODE_DEL_FROM_ORPHAN_CREDITS OCFS2_INODE_ADD_TO_ORPHAN_CREDITS | ||
| 479 | |||
| 475 | /* dinode update, old dir dinode update, new dir dinode update, old | 480 | /* dinode update, old dir dinode update, new dir dinode update, old |
| 476 | * dir dir entry, new dir dir entry, dir entry update for renaming | 481 | * dir dir entry, new dir dir entry, dir entry update for renaming |
| 477 | * directory + target unlink + 3 x dir index leaves */ | 482 | * directory + target unlink + 3 x dir index leaves */ |
diff --git a/fs/ocfs2/mmap.c b/fs/ocfs2/mmap.c index 10d66c75cecb..9581d190f6e1 100644 --- a/fs/ocfs2/mmap.c +++ b/fs/ocfs2/mmap.c | |||
| @@ -173,7 +173,6 @@ out: | |||
| 173 | static const struct vm_operations_struct ocfs2_file_vm_ops = { | 173 | static const struct vm_operations_struct ocfs2_file_vm_ops = { |
| 174 | .fault = ocfs2_fault, | 174 | .fault = ocfs2_fault, |
| 175 | .page_mkwrite = ocfs2_page_mkwrite, | 175 | .page_mkwrite = ocfs2_page_mkwrite, |
| 176 | .remap_pages = generic_file_remap_pages, | ||
| 177 | }; | 176 | }; |
| 178 | 177 | ||
| 179 | int ocfs2_mmap(struct file *file, struct vm_area_struct *vma) | 178 | int ocfs2_mmap(struct file *file, struct vm_area_struct *vma) |
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index b931e04e3388..b5c3a5ea3ee6 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c | |||
| @@ -79,7 +79,8 @@ static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb, | |||
| 79 | struct inode **ret_orphan_dir, | 79 | struct inode **ret_orphan_dir, |
| 80 | u64 blkno, | 80 | u64 blkno, |
| 81 | char *name, | 81 | char *name, |
| 82 | struct ocfs2_dir_lookup_result *lookup); | 82 | struct ocfs2_dir_lookup_result *lookup, |
| 83 | bool dio); | ||
| 83 | 84 | ||
| 84 | static int ocfs2_orphan_add(struct ocfs2_super *osb, | 85 | static int ocfs2_orphan_add(struct ocfs2_super *osb, |
| 85 | handle_t *handle, | 86 | handle_t *handle, |
| @@ -87,15 +88,26 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb, | |||
| 87 | struct buffer_head *fe_bh, | 88 | struct buffer_head *fe_bh, |
| 88 | char *name, | 89 | char *name, |
| 89 | struct ocfs2_dir_lookup_result *lookup, | 90 | struct ocfs2_dir_lookup_result *lookup, |
| 90 | struct inode *orphan_dir_inode); | 91 | struct inode *orphan_dir_inode, |
| 92 | bool dio); | ||
| 91 | 93 | ||
| 92 | static int ocfs2_create_symlink_data(struct ocfs2_super *osb, | 94 | static int ocfs2_create_symlink_data(struct ocfs2_super *osb, |
| 93 | handle_t *handle, | 95 | handle_t *handle, |
| 94 | struct inode *inode, | 96 | struct inode *inode, |
| 95 | const char *symname); | 97 | const char *symname); |
| 96 | 98 | ||
| 99 | static int ocfs2_double_lock(struct ocfs2_super *osb, | ||
| 100 | struct buffer_head **bh1, | ||
| 101 | struct inode *inode1, | ||
| 102 | struct buffer_head **bh2, | ||
| 103 | struct inode *inode2, | ||
| 104 | int rename); | ||
| 105 | |||
| 106 | static void ocfs2_double_unlock(struct inode *inode1, struct inode *inode2); | ||
| 97 | /* An orphan dir name is an 8 byte value, printed as a hex string */ | 107 | /* An orphan dir name is an 8 byte value, printed as a hex string */ |
| 98 | #define OCFS2_ORPHAN_NAMELEN ((int)(2 * sizeof(u64))) | 108 | #define OCFS2_ORPHAN_NAMELEN ((int)(2 * sizeof(u64))) |
| 109 | #define OCFS2_DIO_ORPHAN_PREFIX "dio-" | ||
| 110 | #define OCFS2_DIO_ORPHAN_PREFIX_LEN 4 | ||
| 99 | 111 | ||
| 100 | static struct dentry *ocfs2_lookup(struct inode *dir, struct dentry *dentry, | 112 | static struct dentry *ocfs2_lookup(struct inode *dir, struct dentry *dentry, |
| 101 | unsigned int flags) | 113 | unsigned int flags) |
| @@ -678,8 +690,10 @@ static int ocfs2_link(struct dentry *old_dentry, | |||
| 678 | { | 690 | { |
| 679 | handle_t *handle; | 691 | handle_t *handle; |
| 680 | struct inode *inode = old_dentry->d_inode; | 692 | struct inode *inode = old_dentry->d_inode; |
| 693 | struct inode *old_dir = old_dentry->d_parent->d_inode; | ||
| 681 | int err; | 694 | int err; |
| 682 | struct buffer_head *fe_bh = NULL; | 695 | struct buffer_head *fe_bh = NULL; |
| 696 | struct buffer_head *old_dir_bh = NULL; | ||
| 683 | struct buffer_head *parent_fe_bh = NULL; | 697 | struct buffer_head *parent_fe_bh = NULL; |
| 684 | struct ocfs2_dinode *fe = NULL; | 698 | struct ocfs2_dinode *fe = NULL; |
| 685 | struct ocfs2_super *osb = OCFS2_SB(dir->i_sb); | 699 | struct ocfs2_super *osb = OCFS2_SB(dir->i_sb); |
| @@ -696,19 +710,33 @@ static int ocfs2_link(struct dentry *old_dentry, | |||
| 696 | 710 | ||
| 697 | dquot_initialize(dir); | 711 | dquot_initialize(dir); |
| 698 | 712 | ||
| 699 | err = ocfs2_inode_lock_nested(dir, &parent_fe_bh, 1, OI_LS_PARENT); | 713 | err = ocfs2_double_lock(osb, &old_dir_bh, old_dir, |
| 714 | &parent_fe_bh, dir, 0); | ||
| 700 | if (err < 0) { | 715 | if (err < 0) { |
| 701 | if (err != -ENOENT) | 716 | if (err != -ENOENT) |
| 702 | mlog_errno(err); | 717 | mlog_errno(err); |
| 703 | return err; | 718 | return err; |
| 704 | } | 719 | } |
| 705 | 720 | ||
| 721 | /* make sure both dirs have bhs | ||
| 722 | * get an extra ref on old_dir_bh if old==new */ | ||
| 723 | if (!parent_fe_bh) { | ||
| 724 | if (old_dir_bh) { | ||
| 725 | parent_fe_bh = old_dir_bh; | ||
| 726 | get_bh(parent_fe_bh); | ||
| 727 | } else { | ||
| 728 | mlog(ML_ERROR, "%s: no old_dir_bh!\n", osb->uuid_str); | ||
| 729 | err = -EIO; | ||
| 730 | goto out; | ||
| 731 | } | ||
| 732 | } | ||
| 733 | |||
| 706 | if (!dir->i_nlink) { | 734 | if (!dir->i_nlink) { |
| 707 | err = -ENOENT; | 735 | err = -ENOENT; |
| 708 | goto out; | 736 | goto out; |
| 709 | } | 737 | } |
| 710 | 738 | ||
| 711 | err = ocfs2_lookup_ino_from_name(dir, old_dentry->d_name.name, | 739 | err = ocfs2_lookup_ino_from_name(old_dir, old_dentry->d_name.name, |
| 712 | old_dentry->d_name.len, &old_de_ino); | 740 | old_dentry->d_name.len, &old_de_ino); |
| 713 | if (err) { | 741 | if (err) { |
| 714 | err = -ENOENT; | 742 | err = -ENOENT; |
| @@ -801,10 +829,11 @@ out_unlock_inode: | |||
| 801 | ocfs2_inode_unlock(inode, 1); | 829 | ocfs2_inode_unlock(inode, 1); |
| 802 | 830 | ||
| 803 | out: | 831 | out: |
| 804 | ocfs2_inode_unlock(dir, 1); | 832 | ocfs2_double_unlock(old_dir, dir); |
| 805 | 833 | ||
| 806 | brelse(fe_bh); | 834 | brelse(fe_bh); |
| 807 | brelse(parent_fe_bh); | 835 | brelse(parent_fe_bh); |
| 836 | brelse(old_dir_bh); | ||
| 808 | 837 | ||
| 809 | ocfs2_free_dir_lookup_result(&lookup); | 838 | ocfs2_free_dir_lookup_result(&lookup); |
| 810 | 839 | ||
| @@ -927,7 +956,8 @@ static int ocfs2_unlink(struct inode *dir, | |||
| 927 | if (ocfs2_inode_is_unlinkable(inode)) { | 956 | if (ocfs2_inode_is_unlinkable(inode)) { |
| 928 | status = ocfs2_prepare_orphan_dir(osb, &orphan_dir, | 957 | status = ocfs2_prepare_orphan_dir(osb, &orphan_dir, |
| 929 | OCFS2_I(inode)->ip_blkno, | 958 | OCFS2_I(inode)->ip_blkno, |
| 930 | orphan_name, &orphan_insert); | 959 | orphan_name, &orphan_insert, |
| 960 | false); | ||
| 931 | if (status < 0) { | 961 | if (status < 0) { |
| 932 | mlog_errno(status); | 962 | mlog_errno(status); |
| 933 | goto leave; | 963 | goto leave; |
| @@ -979,7 +1009,7 @@ static int ocfs2_unlink(struct inode *dir, | |||
| 979 | 1009 | ||
| 980 | if (is_unlinkable) { | 1010 | if (is_unlinkable) { |
| 981 | status = ocfs2_orphan_add(osb, handle, inode, fe_bh, | 1011 | status = ocfs2_orphan_add(osb, handle, inode, fe_bh, |
| 982 | orphan_name, &orphan_insert, orphan_dir); | 1012 | orphan_name, &orphan_insert, orphan_dir, false); |
| 983 | if (status < 0) | 1013 | if (status < 0) |
| 984 | mlog_errno(status); | 1014 | mlog_errno(status); |
| 985 | } | 1015 | } |
| @@ -1072,14 +1102,15 @@ static int ocfs2_check_if_ancestor(struct ocfs2_super *osb, | |||
| 1072 | } | 1102 | } |
| 1073 | 1103 | ||
| 1074 | /* | 1104 | /* |
| 1075 | * The only place this should be used is rename! | 1105 | * The only place this should be used is rename and link! |
| 1076 | * if they have the same id, then the 1st one is the only one locked. | 1106 | * if they have the same id, then the 1st one is the only one locked. |
| 1077 | */ | 1107 | */ |
| 1078 | static int ocfs2_double_lock(struct ocfs2_super *osb, | 1108 | static int ocfs2_double_lock(struct ocfs2_super *osb, |
| 1079 | struct buffer_head **bh1, | 1109 | struct buffer_head **bh1, |
| 1080 | struct inode *inode1, | 1110 | struct inode *inode1, |
| 1081 | struct buffer_head **bh2, | 1111 | struct buffer_head **bh2, |
| 1082 | struct inode *inode2) | 1112 | struct inode *inode2, |
| 1113 | int rename) | ||
| 1083 | { | 1114 | { |
| 1084 | int status; | 1115 | int status; |
| 1085 | int inode1_is_ancestor, inode2_is_ancestor; | 1116 | int inode1_is_ancestor, inode2_is_ancestor; |
| @@ -1127,7 +1158,7 @@ static int ocfs2_double_lock(struct ocfs2_super *osb, | |||
| 1127 | } | 1158 | } |
| 1128 | /* lock id2 */ | 1159 | /* lock id2 */ |
| 1129 | status = ocfs2_inode_lock_nested(inode2, bh2, 1, | 1160 | status = ocfs2_inode_lock_nested(inode2, bh2, 1, |
| 1130 | OI_LS_RENAME1); | 1161 | rename == 1 ? OI_LS_RENAME1 : OI_LS_PARENT); |
| 1131 | if (status < 0) { | 1162 | if (status < 0) { |
| 1132 | if (status != -ENOENT) | 1163 | if (status != -ENOENT) |
| 1133 | mlog_errno(status); | 1164 | mlog_errno(status); |
| @@ -1136,7 +1167,8 @@ static int ocfs2_double_lock(struct ocfs2_super *osb, | |||
| 1136 | } | 1167 | } |
| 1137 | 1168 | ||
| 1138 | /* lock id1 */ | 1169 | /* lock id1 */ |
| 1139 | status = ocfs2_inode_lock_nested(inode1, bh1, 1, OI_LS_RENAME2); | 1170 | status = ocfs2_inode_lock_nested(inode1, bh1, 1, |
| 1171 | rename == 1 ? OI_LS_RENAME2 : OI_LS_PARENT); | ||
| 1140 | if (status < 0) { | 1172 | if (status < 0) { |
| 1141 | /* | 1173 | /* |
| 1142 | * An error return must mean that no cluster locks | 1174 | * An error return must mean that no cluster locks |
| @@ -1252,7 +1284,7 @@ static int ocfs2_rename(struct inode *old_dir, | |||
| 1252 | 1284 | ||
| 1253 | /* if old and new are the same, this'll just do one lock. */ | 1285 | /* if old and new are the same, this'll just do one lock. */ |
| 1254 | status = ocfs2_double_lock(osb, &old_dir_bh, old_dir, | 1286 | status = ocfs2_double_lock(osb, &old_dir_bh, old_dir, |
| 1255 | &new_dir_bh, new_dir); | 1287 | &new_dir_bh, new_dir, 1); |
| 1256 | if (status < 0) { | 1288 | if (status < 0) { |
| 1257 | mlog_errno(status); | 1289 | mlog_errno(status); |
| 1258 | goto bail; | 1290 | goto bail; |
| @@ -1413,7 +1445,8 @@ static int ocfs2_rename(struct inode *old_dir, | |||
| 1413 | if (S_ISDIR(new_inode->i_mode) || (new_inode->i_nlink == 1)) { | 1445 | if (S_ISDIR(new_inode->i_mode) || (new_inode->i_nlink == 1)) { |
| 1414 | status = ocfs2_prepare_orphan_dir(osb, &orphan_dir, | 1446 | status = ocfs2_prepare_orphan_dir(osb, &orphan_dir, |
| 1415 | OCFS2_I(new_inode)->ip_blkno, | 1447 | OCFS2_I(new_inode)->ip_blkno, |
| 1416 | orphan_name, &orphan_insert); | 1448 | orphan_name, &orphan_insert, |
| 1449 | false); | ||
| 1417 | if (status < 0) { | 1450 | if (status < 0) { |
| 1418 | mlog_errno(status); | 1451 | mlog_errno(status); |
| 1419 | goto bail; | 1452 | goto bail; |
| @@ -1480,7 +1513,7 @@ static int ocfs2_rename(struct inode *old_dir, | |||
| 1480 | if (should_add_orphan) { | 1513 | if (should_add_orphan) { |
| 1481 | status = ocfs2_orphan_add(osb, handle, new_inode, | 1514 | status = ocfs2_orphan_add(osb, handle, new_inode, |
| 1482 | newfe_bh, orphan_name, | 1515 | newfe_bh, orphan_name, |
| 1483 | &orphan_insert, orphan_dir); | 1516 | &orphan_insert, orphan_dir, false); |
| 1484 | if (status < 0) { | 1517 | if (status < 0) { |
| 1485 | mlog_errno(status); | 1518 | mlog_errno(status); |
| 1486 | goto bail; | 1519 | goto bail; |
| @@ -2061,12 +2094,28 @@ static int __ocfs2_prepare_orphan_dir(struct inode *orphan_dir_inode, | |||
| 2061 | struct buffer_head *orphan_dir_bh, | 2094 | struct buffer_head *orphan_dir_bh, |
| 2062 | u64 blkno, | 2095 | u64 blkno, |
| 2063 | char *name, | 2096 | char *name, |
| 2064 | struct ocfs2_dir_lookup_result *lookup) | 2097 | struct ocfs2_dir_lookup_result *lookup, |
| 2098 | bool dio) | ||
| 2065 | { | 2099 | { |
| 2066 | int ret; | 2100 | int ret; |
| 2067 | struct ocfs2_super *osb = OCFS2_SB(orphan_dir_inode->i_sb); | 2101 | struct ocfs2_super *osb = OCFS2_SB(orphan_dir_inode->i_sb); |
| 2102 | int namelen = dio ? | ||
| 2103 | (OCFS2_DIO_ORPHAN_PREFIX_LEN + OCFS2_ORPHAN_NAMELEN) : | ||
| 2104 | OCFS2_ORPHAN_NAMELEN; | ||
| 2105 | |||
| 2106 | if (dio) { | ||
| 2107 | ret = snprintf(name, OCFS2_DIO_ORPHAN_PREFIX_LEN + 1, "%s", | ||
| 2108 | OCFS2_DIO_ORPHAN_PREFIX); | ||
| 2109 | if (ret != OCFS2_DIO_ORPHAN_PREFIX_LEN) { | ||
| 2110 | ret = -EINVAL; | ||
| 2111 | mlog_errno(ret); | ||
| 2112 | return ret; | ||
| 2113 | } | ||
| 2068 | 2114 | ||
| 2069 | ret = ocfs2_blkno_stringify(blkno, name); | 2115 | ret = ocfs2_blkno_stringify(blkno, |
| 2116 | name + OCFS2_DIO_ORPHAN_PREFIX_LEN); | ||
| 2117 | } else | ||
| 2118 | ret = ocfs2_blkno_stringify(blkno, name); | ||
| 2070 | if (ret < 0) { | 2119 | if (ret < 0) { |
| 2071 | mlog_errno(ret); | 2120 | mlog_errno(ret); |
| 2072 | return ret; | 2121 | return ret; |
| @@ -2074,7 +2123,7 @@ static int __ocfs2_prepare_orphan_dir(struct inode *orphan_dir_inode, | |||
| 2074 | 2123 | ||
| 2075 | ret = ocfs2_prepare_dir_for_insert(osb, orphan_dir_inode, | 2124 | ret = ocfs2_prepare_dir_for_insert(osb, orphan_dir_inode, |
| 2076 | orphan_dir_bh, name, | 2125 | orphan_dir_bh, name, |
| 2077 | OCFS2_ORPHAN_NAMELEN, lookup); | 2126 | namelen, lookup); |
| 2078 | if (ret < 0) { | 2127 | if (ret < 0) { |
| 2079 | mlog_errno(ret); | 2128 | mlog_errno(ret); |
| 2080 | return ret; | 2129 | return ret; |
| @@ -2101,7 +2150,8 @@ static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb, | |||
| 2101 | struct inode **ret_orphan_dir, | 2150 | struct inode **ret_orphan_dir, |
| 2102 | u64 blkno, | 2151 | u64 blkno, |
| 2103 | char *name, | 2152 | char *name, |
| 2104 | struct ocfs2_dir_lookup_result *lookup) | 2153 | struct ocfs2_dir_lookup_result *lookup, |
| 2154 | bool dio) | ||
| 2105 | { | 2155 | { |
| 2106 | struct inode *orphan_dir_inode = NULL; | 2156 | struct inode *orphan_dir_inode = NULL; |
| 2107 | struct buffer_head *orphan_dir_bh = NULL; | 2157 | struct buffer_head *orphan_dir_bh = NULL; |
| @@ -2115,7 +2165,7 @@ static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb, | |||
| 2115 | } | 2165 | } |
| 2116 | 2166 | ||
| 2117 | ret = __ocfs2_prepare_orphan_dir(orphan_dir_inode, orphan_dir_bh, | 2167 | ret = __ocfs2_prepare_orphan_dir(orphan_dir_inode, orphan_dir_bh, |
| 2118 | blkno, name, lookup); | 2168 | blkno, name, lookup, dio); |
| 2119 | if (ret < 0) { | 2169 | if (ret < 0) { |
| 2120 | mlog_errno(ret); | 2170 | mlog_errno(ret); |
| 2121 | goto out; | 2171 | goto out; |
| @@ -2143,12 +2193,16 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb, | |||
| 2143 | struct buffer_head *fe_bh, | 2193 | struct buffer_head *fe_bh, |
| 2144 | char *name, | 2194 | char *name, |
| 2145 | struct ocfs2_dir_lookup_result *lookup, | 2195 | struct ocfs2_dir_lookup_result *lookup, |
| 2146 | struct inode *orphan_dir_inode) | 2196 | struct inode *orphan_dir_inode, |
| 2197 | bool dio) | ||
| 2147 | { | 2198 | { |
| 2148 | struct buffer_head *orphan_dir_bh = NULL; | 2199 | struct buffer_head *orphan_dir_bh = NULL; |
| 2149 | int status = 0; | 2200 | int status = 0; |
| 2150 | struct ocfs2_dinode *orphan_fe; | 2201 | struct ocfs2_dinode *orphan_fe; |
| 2151 | struct ocfs2_dinode *fe = (struct ocfs2_dinode *) fe_bh->b_data; | 2202 | struct ocfs2_dinode *fe = (struct ocfs2_dinode *) fe_bh->b_data; |
| 2203 | int namelen = dio ? | ||
| 2204 | (OCFS2_DIO_ORPHAN_PREFIX_LEN + OCFS2_ORPHAN_NAMELEN) : | ||
| 2205 | OCFS2_ORPHAN_NAMELEN; | ||
| 2152 | 2206 | ||
| 2153 | trace_ocfs2_orphan_add_begin( | 2207 | trace_ocfs2_orphan_add_begin( |
| 2154 | (unsigned long long)OCFS2_I(inode)->ip_blkno); | 2208 | (unsigned long long)OCFS2_I(inode)->ip_blkno); |
| @@ -2192,7 +2246,7 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb, | |||
| 2192 | ocfs2_journal_dirty(handle, orphan_dir_bh); | 2246 | ocfs2_journal_dirty(handle, orphan_dir_bh); |
| 2193 | 2247 | ||
| 2194 | status = __ocfs2_add_entry(handle, orphan_dir_inode, name, | 2248 | status = __ocfs2_add_entry(handle, orphan_dir_inode, name, |
| 2195 | OCFS2_ORPHAN_NAMELEN, inode, | 2249 | namelen, inode, |
| 2196 | OCFS2_I(inode)->ip_blkno, | 2250 | OCFS2_I(inode)->ip_blkno, |
| 2197 | orphan_dir_bh, lookup); | 2251 | orphan_dir_bh, lookup); |
| 2198 | if (status < 0) { | 2252 | if (status < 0) { |
| @@ -2200,13 +2254,21 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb, | |||
| 2200 | goto rollback; | 2254 | goto rollback; |
| 2201 | } | 2255 | } |
| 2202 | 2256 | ||
| 2203 | fe->i_flags |= cpu_to_le32(OCFS2_ORPHANED_FL); | 2257 | if (dio) { |
| 2204 | OCFS2_I(inode)->ip_flags &= ~OCFS2_INODE_SKIP_ORPHAN_DIR; | 2258 | /* Update flag OCFS2_DIO_ORPHANED_FL and record the orphan |
| 2259 | * slot. | ||
| 2260 | */ | ||
| 2261 | fe->i_flags |= cpu_to_le32(OCFS2_DIO_ORPHANED_FL); | ||
| 2262 | fe->i_dio_orphaned_slot = cpu_to_le16(osb->slot_num); | ||
| 2263 | } else { | ||
| 2264 | fe->i_flags |= cpu_to_le32(OCFS2_ORPHANED_FL); | ||
| 2265 | OCFS2_I(inode)->ip_flags &= ~OCFS2_INODE_SKIP_ORPHAN_DIR; | ||
| 2205 | 2266 | ||
| 2206 | /* Record which orphan dir our inode now resides | 2267 | /* Record which orphan dir our inode now resides |
| 2207 | * in. delete_inode will use this to determine which orphan | 2268 | * in. delete_inode will use this to determine which orphan |
| 2208 | * dir to lock. */ | 2269 | * dir to lock. */ |
| 2209 | fe->i_orphaned_slot = cpu_to_le16(osb->slot_num); | 2270 | fe->i_orphaned_slot = cpu_to_le16(osb->slot_num); |
| 2271 | } | ||
| 2210 | 2272 | ||
| 2211 | ocfs2_journal_dirty(handle, fe_bh); | 2273 | ocfs2_journal_dirty(handle, fe_bh); |
| 2212 | 2274 | ||
| @@ -2231,14 +2293,28 @@ int ocfs2_orphan_del(struct ocfs2_super *osb, | |||
| 2231 | handle_t *handle, | 2293 | handle_t *handle, |
| 2232 | struct inode *orphan_dir_inode, | 2294 | struct inode *orphan_dir_inode, |
| 2233 | struct inode *inode, | 2295 | struct inode *inode, |
| 2234 | struct buffer_head *orphan_dir_bh) | 2296 | struct buffer_head *orphan_dir_bh, |
| 2297 | bool dio) | ||
| 2235 | { | 2298 | { |
| 2236 | char name[OCFS2_ORPHAN_NAMELEN + 1]; | 2299 | const int namelen = OCFS2_DIO_ORPHAN_PREFIX_LEN + OCFS2_ORPHAN_NAMELEN; |
| 2300 | char name[namelen + 1]; | ||
| 2237 | struct ocfs2_dinode *orphan_fe; | 2301 | struct ocfs2_dinode *orphan_fe; |
| 2238 | int status = 0; | 2302 | int status = 0; |
| 2239 | struct ocfs2_dir_lookup_result lookup = { NULL, }; | 2303 | struct ocfs2_dir_lookup_result lookup = { NULL, }; |
| 2240 | 2304 | ||
| 2241 | status = ocfs2_blkno_stringify(OCFS2_I(inode)->ip_blkno, name); | 2305 | if (dio) { |
| 2306 | status = snprintf(name, OCFS2_DIO_ORPHAN_PREFIX_LEN + 1, "%s", | ||
| 2307 | OCFS2_DIO_ORPHAN_PREFIX); | ||
| 2308 | if (status != OCFS2_DIO_ORPHAN_PREFIX_LEN) { | ||
| 2309 | status = -EINVAL; | ||
| 2310 | mlog_errno(status); | ||
| 2311 | return status; | ||
| 2312 | } | ||
| 2313 | |||
| 2314 | status = ocfs2_blkno_stringify(OCFS2_I(inode)->ip_blkno, | ||
| 2315 | name + OCFS2_DIO_ORPHAN_PREFIX_LEN); | ||
| 2316 | } else | ||
| 2317 | status = ocfs2_blkno_stringify(OCFS2_I(inode)->ip_blkno, name); | ||
| 2242 | if (status < 0) { | 2318 | if (status < 0) { |
| 2243 | mlog_errno(status); | 2319 | mlog_errno(status); |
| 2244 | goto leave; | 2320 | goto leave; |
| @@ -2246,10 +2322,10 @@ int ocfs2_orphan_del(struct ocfs2_super *osb, | |||
| 2246 | 2322 | ||
| 2247 | trace_ocfs2_orphan_del( | 2323 | trace_ocfs2_orphan_del( |
| 2248 | (unsigned long long)OCFS2_I(orphan_dir_inode)->ip_blkno, | 2324 | (unsigned long long)OCFS2_I(orphan_dir_inode)->ip_blkno, |
| 2249 | name, OCFS2_ORPHAN_NAMELEN); | 2325 | name, namelen); |
| 2250 | 2326 | ||
| 2251 | /* find it's spot in the orphan directory */ | 2327 | /* find it's spot in the orphan directory */ |
| 2252 | status = ocfs2_find_entry(name, OCFS2_ORPHAN_NAMELEN, orphan_dir_inode, | 2328 | status = ocfs2_find_entry(name, namelen, orphan_dir_inode, |
| 2253 | &lookup); | 2329 | &lookup); |
| 2254 | if (status) { | 2330 | if (status) { |
| 2255 | mlog_errno(status); | 2331 | mlog_errno(status); |
| @@ -2349,7 +2425,8 @@ static int ocfs2_prep_new_orphaned_file(struct inode *dir, | |||
| 2349 | } | 2425 | } |
| 2350 | 2426 | ||
| 2351 | ret = __ocfs2_prepare_orphan_dir(orphan_dir, orphan_dir_bh, | 2427 | ret = __ocfs2_prepare_orphan_dir(orphan_dir, orphan_dir_bh, |
| 2352 | di_blkno, orphan_name, orphan_insert); | 2428 | di_blkno, orphan_name, orphan_insert, |
| 2429 | false); | ||
| 2353 | if (ret < 0) { | 2430 | if (ret < 0) { |
| 2354 | mlog_errno(ret); | 2431 | mlog_errno(ret); |
| 2355 | goto out; | 2432 | goto out; |
| @@ -2455,7 +2532,7 @@ int ocfs2_create_inode_in_orphan(struct inode *dir, | |||
| 2455 | 2532 | ||
| 2456 | di = (struct ocfs2_dinode *)new_di_bh->b_data; | 2533 | di = (struct ocfs2_dinode *)new_di_bh->b_data; |
| 2457 | status = ocfs2_orphan_add(osb, handle, inode, new_di_bh, orphan_name, | 2534 | status = ocfs2_orphan_add(osb, handle, inode, new_di_bh, orphan_name, |
| 2458 | &orphan_insert, orphan_dir); | 2535 | &orphan_insert, orphan_dir, false); |
| 2459 | if (status < 0) { | 2536 | if (status < 0) { |
| 2460 | mlog_errno(status); | 2537 | mlog_errno(status); |
| 2461 | goto leave; | 2538 | goto leave; |
| @@ -2500,6 +2577,186 @@ leave: | |||
| 2500 | return status; | 2577 | return status; |
| 2501 | } | 2578 | } |
| 2502 | 2579 | ||
| 2580 | static int ocfs2_dio_orphan_recovered(struct inode *inode) | ||
| 2581 | { | ||
| 2582 | int ret; | ||
| 2583 | struct buffer_head *di_bh = NULL; | ||
| 2584 | struct ocfs2_dinode *di = NULL; | ||
| 2585 | |||
| 2586 | ret = ocfs2_inode_lock(inode, &di_bh, 1); | ||
| 2587 | if (ret < 0) { | ||
| 2588 | mlog_errno(ret); | ||
| 2589 | return 0; | ||
| 2590 | } | ||
| 2591 | |||
| 2592 | di = (struct ocfs2_dinode *) di_bh->b_data; | ||
| 2593 | ret = !(di->i_flags & cpu_to_le32(OCFS2_DIO_ORPHANED_FL)); | ||
| 2594 | ocfs2_inode_unlock(inode, 1); | ||
| 2595 | brelse(di_bh); | ||
| 2596 | |||
| 2597 | return ret; | ||
| 2598 | } | ||
| 2599 | |||
| 2600 | #define OCFS2_DIO_ORPHANED_FL_CHECK_INTERVAL 10000 | ||
| 2601 | int ocfs2_add_inode_to_orphan(struct ocfs2_super *osb, | ||
| 2602 | struct inode *inode) | ||
| 2603 | { | ||
| 2604 | char orphan_name[OCFS2_DIO_ORPHAN_PREFIX_LEN + OCFS2_ORPHAN_NAMELEN + 1]; | ||
| 2605 | struct inode *orphan_dir_inode = NULL; | ||
| 2606 | struct ocfs2_dir_lookup_result orphan_insert = { NULL, }; | ||
| 2607 | struct buffer_head *di_bh = NULL; | ||
| 2608 | int status = 0; | ||
| 2609 | handle_t *handle = NULL; | ||
| 2610 | struct ocfs2_dinode *di = NULL; | ||
| 2611 | |||
| 2612 | restart: | ||
| 2613 | status = ocfs2_inode_lock(inode, &di_bh, 1); | ||
| 2614 | if (status < 0) { | ||
| 2615 | mlog_errno(status); | ||
| 2616 | goto bail; | ||
| 2617 | } | ||
| 2618 | |||
| 2619 | di = (struct ocfs2_dinode *) di_bh->b_data; | ||
| 2620 | /* | ||
| 2621 | * Another append dio crashed? | ||
| 2622 | * If so, wait for recovery first. | ||
| 2623 | */ | ||
| 2624 | if (unlikely(di->i_flags & cpu_to_le32(OCFS2_DIO_ORPHANED_FL))) { | ||
| 2625 | ocfs2_inode_unlock(inode, 1); | ||
| 2626 | brelse(di_bh); | ||
| 2627 | wait_event_interruptible_timeout(OCFS2_I(inode)->append_dio_wq, | ||
| 2628 | ocfs2_dio_orphan_recovered(inode), | ||
| 2629 | msecs_to_jiffies(OCFS2_DIO_ORPHANED_FL_CHECK_INTERVAL)); | ||
| 2630 | goto restart; | ||
| 2631 | } | ||
| 2632 | |||
| 2633 | status = ocfs2_prepare_orphan_dir(osb, &orphan_dir_inode, | ||
| 2634 | OCFS2_I(inode)->ip_blkno, | ||
| 2635 | orphan_name, | ||
| 2636 | &orphan_insert, | ||
| 2637 | true); | ||
| 2638 | if (status < 0) { | ||
| 2639 | mlog_errno(status); | ||
| 2640 | goto bail_unlock_inode; | ||
| 2641 | } | ||
| 2642 | |||
| 2643 | handle = ocfs2_start_trans(osb, | ||
| 2644 | OCFS2_INODE_ADD_TO_ORPHAN_CREDITS); | ||
| 2645 | if (IS_ERR(handle)) { | ||
| 2646 | status = PTR_ERR(handle); | ||
| 2647 | goto bail_unlock_orphan; | ||
| 2648 | } | ||
| 2649 | |||
| 2650 | status = ocfs2_orphan_add(osb, handle, inode, di_bh, orphan_name, | ||
| 2651 | &orphan_insert, orphan_dir_inode, true); | ||
| 2652 | if (status) | ||
| 2653 | mlog_errno(status); | ||
| 2654 | |||
| 2655 | ocfs2_commit_trans(osb, handle); | ||
| 2656 | |||
| 2657 | bail_unlock_orphan: | ||
| 2658 | ocfs2_inode_unlock(orphan_dir_inode, 1); | ||
| 2659 | mutex_unlock(&orphan_dir_inode->i_mutex); | ||
| 2660 | iput(orphan_dir_inode); | ||
| 2661 | |||
| 2662 | ocfs2_free_dir_lookup_result(&orphan_insert); | ||
| 2663 | |||
| 2664 | bail_unlock_inode: | ||
| 2665 | ocfs2_inode_unlock(inode, 1); | ||
| 2666 | brelse(di_bh); | ||
| 2667 | |||
| 2668 | bail: | ||
| 2669 | return status; | ||
| 2670 | } | ||
| 2671 | |||
| 2672 | int ocfs2_del_inode_from_orphan(struct ocfs2_super *osb, | ||
| 2673 | struct inode *inode, int update_isize, | ||
| 2674 | loff_t end) | ||
| 2675 | { | ||
| 2676 | struct inode *orphan_dir_inode = NULL; | ||
| 2677 | struct buffer_head *orphan_dir_bh = NULL; | ||
| 2678 | struct buffer_head *di_bh = NULL; | ||
| 2679 | struct ocfs2_dinode *di = NULL; | ||
| 2680 | handle_t *handle = NULL; | ||
| 2681 | int status = 0; | ||
| 2682 | |||
| 2683 | status = ocfs2_inode_lock(inode, &di_bh, 1); | ||
| 2684 | if (status < 0) { | ||
| 2685 | mlog_errno(status); | ||
| 2686 | goto bail; | ||
| 2687 | } | ||
| 2688 | di = (struct ocfs2_dinode *) di_bh->b_data; | ||
| 2689 | |||
| 2690 | orphan_dir_inode = ocfs2_get_system_file_inode(osb, | ||
| 2691 | ORPHAN_DIR_SYSTEM_INODE, | ||
| 2692 | le16_to_cpu(di->i_dio_orphaned_slot)); | ||
| 2693 | if (!orphan_dir_inode) { | ||
| 2694 | status = -ENOENT; | ||
| 2695 | mlog_errno(status); | ||
| 2696 | goto bail_unlock_inode; | ||
| 2697 | } | ||
| 2698 | |||
| 2699 | mutex_lock(&orphan_dir_inode->i_mutex); | ||
| 2700 | status = ocfs2_inode_lock(orphan_dir_inode, &orphan_dir_bh, 1); | ||
| 2701 | if (status < 0) { | ||
| 2702 | mutex_unlock(&orphan_dir_inode->i_mutex); | ||
| 2703 | iput(orphan_dir_inode); | ||
| 2704 | mlog_errno(status); | ||
| 2705 | goto bail_unlock_inode; | ||
| 2706 | } | ||
| 2707 | |||
| 2708 | handle = ocfs2_start_trans(osb, | ||
| 2709 | OCFS2_INODE_DEL_FROM_ORPHAN_CREDITS); | ||
| 2710 | if (IS_ERR(handle)) { | ||
| 2711 | status = PTR_ERR(handle); | ||
| 2712 | goto bail_unlock_orphan; | ||
| 2713 | } | ||
| 2714 | |||
| 2715 | BUG_ON(!(di->i_flags & cpu_to_le32(OCFS2_DIO_ORPHANED_FL))); | ||
| 2716 | |||
| 2717 | status = ocfs2_orphan_del(osb, handle, orphan_dir_inode, | ||
| 2718 | inode, orphan_dir_bh, true); | ||
| 2719 | if (status < 0) { | ||
| 2720 | mlog_errno(status); | ||
| 2721 | goto bail_commit; | ||
| 2722 | } | ||
| 2723 | |||
| 2724 | status = ocfs2_journal_access_di(handle, | ||
| 2725 | INODE_CACHE(inode), | ||
| 2726 | di_bh, | ||
| 2727 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
| 2728 | if (status < 0) { | ||
| 2729 | mlog_errno(status); | ||
| 2730 | goto bail_commit; | ||
| 2731 | } | ||
| 2732 | |||
| 2733 | di->i_flags &= ~cpu_to_le32(OCFS2_DIO_ORPHANED_FL); | ||
| 2734 | di->i_dio_orphaned_slot = 0; | ||
| 2735 | |||
| 2736 | if (update_isize) { | ||
| 2737 | status = ocfs2_set_inode_size(handle, inode, di_bh, end); | ||
| 2738 | if (status) | ||
| 2739 | mlog_errno(status); | ||
| 2740 | } else | ||
| 2741 | ocfs2_journal_dirty(handle, di_bh); | ||
| 2742 | |||
| 2743 | bail_commit: | ||
| 2744 | ocfs2_commit_trans(osb, handle); | ||
| 2745 | |||
| 2746 | bail_unlock_orphan: | ||
| 2747 | ocfs2_inode_unlock(orphan_dir_inode, 1); | ||
| 2748 | mutex_unlock(&orphan_dir_inode->i_mutex); | ||
| 2749 | brelse(orphan_dir_bh); | ||
| 2750 | iput(orphan_dir_inode); | ||
| 2751 | |||
| 2752 | bail_unlock_inode: | ||
| 2753 | ocfs2_inode_unlock(inode, 1); | ||
| 2754 | brelse(di_bh); | ||
| 2755 | |||
| 2756 | bail: | ||
| 2757 | return status; | ||
| 2758 | } | ||
| 2759 | |||
| 2503 | int ocfs2_mv_orphaned_inode_to_new(struct inode *dir, | 2760 | int ocfs2_mv_orphaned_inode_to_new(struct inode *dir, |
| 2504 | struct inode *inode, | 2761 | struct inode *inode, |
| 2505 | struct dentry *dentry) | 2762 | struct dentry *dentry) |
| @@ -2588,7 +2845,7 @@ int ocfs2_mv_orphaned_inode_to_new(struct inode *dir, | |||
| 2588 | } | 2845 | } |
| 2589 | 2846 | ||
| 2590 | status = ocfs2_orphan_del(osb, handle, orphan_dir_inode, inode, | 2847 | status = ocfs2_orphan_del(osb, handle, orphan_dir_inode, inode, |
| 2591 | orphan_dir_bh); | 2848 | orphan_dir_bh, false); |
| 2592 | if (status < 0) { | 2849 | if (status < 0) { |
| 2593 | mlog_errno(status); | 2850 | mlog_errno(status); |
| 2594 | goto out_commit; | 2851 | goto out_commit; |
diff --git a/fs/ocfs2/namei.h b/fs/ocfs2/namei.h index e5d059d4f115..5ddecce172fa 100644 --- a/fs/ocfs2/namei.h +++ b/fs/ocfs2/namei.h | |||
| @@ -34,10 +34,16 @@ int ocfs2_orphan_del(struct ocfs2_super *osb, | |||
| 34 | handle_t *handle, | 34 | handle_t *handle, |
| 35 | struct inode *orphan_dir_inode, | 35 | struct inode *orphan_dir_inode, |
| 36 | struct inode *inode, | 36 | struct inode *inode, |
| 37 | struct buffer_head *orphan_dir_bh); | 37 | struct buffer_head *orphan_dir_bh, |
| 38 | bool dio); | ||
| 38 | int ocfs2_create_inode_in_orphan(struct inode *dir, | 39 | int ocfs2_create_inode_in_orphan(struct inode *dir, |
| 39 | int mode, | 40 | int mode, |
| 40 | struct inode **new_inode); | 41 | struct inode **new_inode); |
| 42 | int ocfs2_add_inode_to_orphan(struct ocfs2_super *osb, | ||
| 43 | struct inode *inode); | ||
| 44 | int ocfs2_del_inode_from_orphan(struct ocfs2_super *osb, | ||
| 45 | struct inode *inode, int update_isize, | ||
| 46 | loff_t end); | ||
| 41 | int ocfs2_mv_orphaned_inode_to_new(struct inode *dir, | 47 | int ocfs2_mv_orphaned_inode_to_new(struct inode *dir, |
| 42 | struct inode *new_inode, | 48 | struct inode *new_inode, |
| 43 | struct dentry *new_dentry); | 49 | struct dentry *new_dentry); |
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index 7d6b7d090452..8490c64d34fe 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h | |||
| @@ -209,6 +209,11 @@ struct ocfs2_lock_res { | |||
| 209 | #endif | 209 | #endif |
| 210 | }; | 210 | }; |
| 211 | 211 | ||
| 212 | enum ocfs2_orphan_reco_type { | ||
| 213 | ORPHAN_NO_NEED_TRUNCATE = 0, | ||
| 214 | ORPHAN_NEED_TRUNCATE, | ||
| 215 | }; | ||
| 216 | |||
| 212 | enum ocfs2_orphan_scan_state { | 217 | enum ocfs2_orphan_scan_state { |
| 213 | ORPHAN_SCAN_ACTIVE, | 218 | ORPHAN_SCAN_ACTIVE, |
| 214 | ORPHAN_SCAN_INACTIVE | 219 | ORPHAN_SCAN_INACTIVE |
| @@ -279,6 +284,8 @@ enum ocfs2_mount_options | |||
| 279 | writes */ | 284 | writes */ |
| 280 | OCFS2_MOUNT_HB_NONE = 1 << 13, /* No heartbeat */ | 285 | OCFS2_MOUNT_HB_NONE = 1 << 13, /* No heartbeat */ |
| 281 | OCFS2_MOUNT_HB_GLOBAL = 1 << 14, /* Global heartbeat */ | 286 | OCFS2_MOUNT_HB_GLOBAL = 1 << 14, /* Global heartbeat */ |
| 287 | |||
| 288 | OCFS2_MOUNT_JOURNAL_ASYNC_COMMIT = 1 << 15, /* Journal Async Commit */ | ||
| 282 | }; | 289 | }; |
| 283 | 290 | ||
| 284 | #define OCFS2_OSB_SOFT_RO 0x0001 | 291 | #define OCFS2_OSB_SOFT_RO 0x0001 |
| @@ -493,6 +500,14 @@ static inline int ocfs2_writes_unwritten_extents(struct ocfs2_super *osb) | |||
| 493 | return 0; | 500 | return 0; |
| 494 | } | 501 | } |
| 495 | 502 | ||
| 503 | static inline int ocfs2_supports_append_dio(struct ocfs2_super *osb) | ||
| 504 | { | ||
| 505 | if (osb->s_feature_ro_compat & OCFS2_FEATURE_RO_COMPAT_APPEND_DIO) | ||
| 506 | return 1; | ||
| 507 | return 0; | ||
| 508 | } | ||
| 509 | |||
| 510 | |||
| 496 | static inline int ocfs2_supports_inline_data(struct ocfs2_super *osb) | 511 | static inline int ocfs2_supports_inline_data(struct ocfs2_super *osb) |
| 497 | { | 512 | { |
| 498 | if (osb->s_feature_incompat & OCFS2_FEATURE_INCOMPAT_INLINE_DATA) | 513 | if (osb->s_feature_incompat & OCFS2_FEATURE_INCOMPAT_INLINE_DATA) |
| @@ -724,6 +739,16 @@ static inline unsigned int ocfs2_clusters_for_bytes(struct super_block *sb, | |||
| 724 | return clusters; | 739 | return clusters; |
| 725 | } | 740 | } |
| 726 | 741 | ||
| 742 | static inline unsigned int ocfs2_bytes_to_clusters(struct super_block *sb, | ||
| 743 | u64 bytes) | ||
| 744 | { | ||
| 745 | int cl_bits = OCFS2_SB(sb)->s_clustersize_bits; | ||
| 746 | unsigned int clusters; | ||
| 747 | |||
| 748 | clusters = (unsigned int)(bytes >> cl_bits); | ||
| 749 | return clusters; | ||
| 750 | } | ||
| 751 | |||
| 727 | static inline u64 ocfs2_blocks_for_bytes(struct super_block *sb, | 752 | static inline u64 ocfs2_blocks_for_bytes(struct super_block *sb, |
| 728 | u64 bytes) | 753 | u64 bytes) |
| 729 | { | 754 | { |
diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h index 938387a10d5d..20e37a3ed26f 100644 --- a/fs/ocfs2/ocfs2_fs.h +++ b/fs/ocfs2/ocfs2_fs.h | |||
| @@ -105,7 +105,8 @@ | |||
| 105 | | OCFS2_FEATURE_INCOMPAT_CLUSTERINFO) | 105 | | OCFS2_FEATURE_INCOMPAT_CLUSTERINFO) |
| 106 | #define OCFS2_FEATURE_RO_COMPAT_SUPP (OCFS2_FEATURE_RO_COMPAT_UNWRITTEN \ | 106 | #define OCFS2_FEATURE_RO_COMPAT_SUPP (OCFS2_FEATURE_RO_COMPAT_UNWRITTEN \ |
| 107 | | OCFS2_FEATURE_RO_COMPAT_USRQUOTA \ | 107 | | OCFS2_FEATURE_RO_COMPAT_USRQUOTA \ |
| 108 | | OCFS2_FEATURE_RO_COMPAT_GRPQUOTA) | 108 | | OCFS2_FEATURE_RO_COMPAT_GRPQUOTA \ |
| 109 | | OCFS2_FEATURE_RO_COMPAT_APPEND_DIO) | ||
| 109 | 110 | ||
| 110 | /* | 111 | /* |
| 111 | * Heartbeat-only devices are missing journals and other files. The | 112 | * Heartbeat-only devices are missing journals and other files. The |
| @@ -199,6 +200,11 @@ | |||
| 199 | #define OCFS2_FEATURE_RO_COMPAT_USRQUOTA 0x0002 | 200 | #define OCFS2_FEATURE_RO_COMPAT_USRQUOTA 0x0002 |
| 200 | #define OCFS2_FEATURE_RO_COMPAT_GRPQUOTA 0x0004 | 201 | #define OCFS2_FEATURE_RO_COMPAT_GRPQUOTA 0x0004 |
| 201 | 202 | ||
| 203 | /* | ||
| 204 | * Append Direct IO support | ||
| 205 | */ | ||
| 206 | #define OCFS2_FEATURE_RO_COMPAT_APPEND_DIO 0x0008 | ||
| 207 | |||
| 202 | /* The byte offset of the first backup block will be 1G. | 208 | /* The byte offset of the first backup block will be 1G. |
| 203 | * The following will be 4G, 16G, 64G, 256G and 1T. | 209 | * The following will be 4G, 16G, 64G, 256G and 1T. |
| 204 | */ | 210 | */ |
| @@ -229,6 +235,8 @@ | |||
| 229 | #define OCFS2_CHAIN_FL (0x00000400) /* Chain allocator */ | 235 | #define OCFS2_CHAIN_FL (0x00000400) /* Chain allocator */ |
| 230 | #define OCFS2_DEALLOC_FL (0x00000800) /* Truncate log */ | 236 | #define OCFS2_DEALLOC_FL (0x00000800) /* Truncate log */ |
| 231 | #define OCFS2_QUOTA_FL (0x00001000) /* Quota file */ | 237 | #define OCFS2_QUOTA_FL (0x00001000) /* Quota file */ |
| 238 | #define OCFS2_DIO_ORPHANED_FL (0X00002000) /* On the orphan list especially | ||
| 239 | * for dio */ | ||
| 232 | 240 | ||
| 233 | /* | 241 | /* |
| 234 | * Flags on ocfs2_dinode.i_dyn_features | 242 | * Flags on ocfs2_dinode.i_dyn_features |
| @@ -729,7 +737,9 @@ struct ocfs2_dinode { | |||
| 729 | inode belongs to. Only valid | 737 | inode belongs to. Only valid |
| 730 | if allocated from a | 738 | if allocated from a |
| 731 | discontiguous block group */ | 739 | discontiguous block group */ |
| 732 | /*A0*/ __le64 i_reserved2[3]; | 740 | /*A0*/ __le16 i_dio_orphaned_slot; /* only used for append dio write */ |
| 741 | __le16 i_reserved1[3]; | ||
| 742 | __le64 i_reserved2[2]; | ||
| 733 | /*B8*/ union { | 743 | /*B8*/ union { |
| 734 | __le64 i_pad1; /* Generic way to refer to this | 744 | __le64 i_pad1; /* Generic way to refer to this |
| 735 | 64bit union */ | 745 | 64bit union */ |
diff --git a/fs/ocfs2/quota.h b/fs/ocfs2/quota.h index 1eae330193a6..b6d51333ad02 100644 --- a/fs/ocfs2/quota.h +++ b/fs/ocfs2/quota.h | |||
| @@ -48,6 +48,7 @@ struct ocfs2_quota_recovery { | |||
| 48 | /* In-memory structure with quota header information */ | 48 | /* In-memory structure with quota header information */ |
| 49 | struct ocfs2_mem_dqinfo { | 49 | struct ocfs2_mem_dqinfo { |
| 50 | unsigned int dqi_type; /* Quota type this structure describes */ | 50 | unsigned int dqi_type; /* Quota type this structure describes */ |
| 51 | unsigned int dqi_flags; /* Flags OLQF_* */ | ||
| 51 | unsigned int dqi_chunks; /* Number of chunks in local quota file */ | 52 | unsigned int dqi_chunks; /* Number of chunks in local quota file */ |
| 52 | unsigned int dqi_blocks; /* Number of blocks allocated for local quota file */ | 53 | unsigned int dqi_blocks; /* Number of blocks allocated for local quota file */ |
| 53 | unsigned int dqi_syncms; /* How often should we sync with other nodes */ | 54 | unsigned int dqi_syncms; /* How often should we sync with other nodes */ |
diff --git a/fs/ocfs2/quota_local.c b/fs/ocfs2/quota_local.c index 10b653930ee2..3d0b63d34225 100644 --- a/fs/ocfs2/quota_local.c +++ b/fs/ocfs2/quota_local.c | |||
| @@ -73,12 +73,6 @@ static loff_t ol_dqblk_off(struct super_block *sb, int c, int off) | |||
| 73 | ol_dqblk_block_off(sb, c, off); | 73 | ol_dqblk_block_off(sb, c, off); |
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | /* Compute block number from given offset */ | ||
| 77 | static inline unsigned int ol_dqblk_file_block(struct super_block *sb, loff_t off) | ||
| 78 | { | ||
| 79 | return off >> sb->s_blocksize_bits; | ||
| 80 | } | ||
| 81 | |||
| 82 | static inline unsigned int ol_dqblk_block_offset(struct super_block *sb, loff_t off) | 76 | static inline unsigned int ol_dqblk_block_offset(struct super_block *sb, loff_t off) |
| 83 | { | 77 | { |
| 84 | return off & ((1 << sb->s_blocksize_bits) - 1); | 78 | return off & ((1 << sb->s_blocksize_bits) - 1); |
| @@ -292,7 +286,7 @@ static void olq_update_info(struct buffer_head *bh, void *private) | |||
| 292 | ldinfo = (struct ocfs2_local_disk_dqinfo *)(bh->b_data + | 286 | ldinfo = (struct ocfs2_local_disk_dqinfo *)(bh->b_data + |
| 293 | OCFS2_LOCAL_INFO_OFF); | 287 | OCFS2_LOCAL_INFO_OFF); |
| 294 | spin_lock(&dq_data_lock); | 288 | spin_lock(&dq_data_lock); |
| 295 | ldinfo->dqi_flags = cpu_to_le32(info->dqi_flags & DQF_MASK); | 289 | ldinfo->dqi_flags = cpu_to_le32(oinfo->dqi_flags); |
| 296 | ldinfo->dqi_chunks = cpu_to_le32(oinfo->dqi_chunks); | 290 | ldinfo->dqi_chunks = cpu_to_le32(oinfo->dqi_chunks); |
| 297 | ldinfo->dqi_blocks = cpu_to_le32(oinfo->dqi_blocks); | 291 | ldinfo->dqi_blocks = cpu_to_le32(oinfo->dqi_blocks); |
| 298 | spin_unlock(&dq_data_lock); | 292 | spin_unlock(&dq_data_lock); |
| @@ -701,8 +695,8 @@ static int ocfs2_local_read_info(struct super_block *sb, int type) | |||
| 701 | /* We don't need the lock and we have to acquire quota file locks | 695 | /* We don't need the lock and we have to acquire quota file locks |
| 702 | * which will later depend on this lock */ | 696 | * which will later depend on this lock */ |
| 703 | mutex_unlock(&sb_dqopt(sb)->dqio_mutex); | 697 | mutex_unlock(&sb_dqopt(sb)->dqio_mutex); |
| 704 | info->dqi_maxblimit = 0x7fffffffffffffffLL; | 698 | info->dqi_max_spc_limit = 0x7fffffffffffffffLL; |
| 705 | info->dqi_maxilimit = 0x7fffffffffffffffLL; | 699 | info->dqi_max_ino_limit = 0x7fffffffffffffffLL; |
| 706 | oinfo = kmalloc(sizeof(struct ocfs2_mem_dqinfo), GFP_NOFS); | 700 | oinfo = kmalloc(sizeof(struct ocfs2_mem_dqinfo), GFP_NOFS); |
| 707 | if (!oinfo) { | 701 | if (!oinfo) { |
| 708 | mlog(ML_ERROR, "failed to allocate memory for ocfs2 quota" | 702 | mlog(ML_ERROR, "failed to allocate memory for ocfs2 quota" |
| @@ -737,13 +731,13 @@ static int ocfs2_local_read_info(struct super_block *sb, int type) | |||
| 737 | } | 731 | } |
| 738 | ldinfo = (struct ocfs2_local_disk_dqinfo *)(bh->b_data + | 732 | ldinfo = (struct ocfs2_local_disk_dqinfo *)(bh->b_data + |
| 739 | OCFS2_LOCAL_INFO_OFF); | 733 | OCFS2_LOCAL_INFO_OFF); |
| 740 | info->dqi_flags = le32_to_cpu(ldinfo->dqi_flags); | 734 | oinfo->dqi_flags = le32_to_cpu(ldinfo->dqi_flags); |
| 741 | oinfo->dqi_chunks = le32_to_cpu(ldinfo->dqi_chunks); | 735 | oinfo->dqi_chunks = le32_to_cpu(ldinfo->dqi_chunks); |
| 742 | oinfo->dqi_blocks = le32_to_cpu(ldinfo->dqi_blocks); | 736 | oinfo->dqi_blocks = le32_to_cpu(ldinfo->dqi_blocks); |
| 743 | oinfo->dqi_libh = bh; | 737 | oinfo->dqi_libh = bh; |
| 744 | 738 | ||
| 745 | /* We crashed when using local quota file? */ | 739 | /* We crashed when using local quota file? */ |
| 746 | if (!(info->dqi_flags & OLQF_CLEAN)) { | 740 | if (!(oinfo->dqi_flags & OLQF_CLEAN)) { |
| 747 | rec = OCFS2_SB(sb)->quota_rec; | 741 | rec = OCFS2_SB(sb)->quota_rec; |
| 748 | if (!rec) { | 742 | if (!rec) { |
| 749 | rec = ocfs2_alloc_quota_recovery(); | 743 | rec = ocfs2_alloc_quota_recovery(); |
| @@ -772,7 +766,7 @@ static int ocfs2_local_read_info(struct super_block *sb, int type) | |||
| 772 | } | 766 | } |
| 773 | 767 | ||
| 774 | /* Now mark quota file as used */ | 768 | /* Now mark quota file as used */ |
| 775 | info->dqi_flags &= ~OLQF_CLEAN; | 769 | oinfo->dqi_flags &= ~OLQF_CLEAN; |
| 776 | status = ocfs2_modify_bh(lqinode, bh, olq_update_info, info); | 770 | status = ocfs2_modify_bh(lqinode, bh, olq_update_info, info); |
| 777 | if (status < 0) { | 771 | if (status < 0) { |
| 778 | mlog_errno(status); | 772 | mlog_errno(status); |
| @@ -857,7 +851,7 @@ static int ocfs2_local_free_info(struct super_block *sb, int type) | |||
| 857 | goto out; | 851 | goto out; |
| 858 | 852 | ||
| 859 | /* Mark local file as clean */ | 853 | /* Mark local file as clean */ |
| 860 | info->dqi_flags |= OLQF_CLEAN; | 854 | oinfo->dqi_flags |= OLQF_CLEAN; |
| 861 | status = ocfs2_modify_bh(sb_dqopt(sb)->files[type], | 855 | status = ocfs2_modify_bh(sb_dqopt(sb)->files[type], |
| 862 | oinfo->dqi_libh, | 856 | oinfo->dqi_libh, |
| 863 | olq_update_info, | 857 | olq_update_info, |
diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c index d81f6e2a97f5..ee541f92dab4 100644 --- a/fs/ocfs2/refcounttree.c +++ b/fs/ocfs2/refcounttree.c | |||
| @@ -2428,8 +2428,6 @@ static int ocfs2_calc_refcount_meta_credits(struct super_block *sb, | |||
| 2428 | get_bh(prev_bh); | 2428 | get_bh(prev_bh); |
| 2429 | } | 2429 | } |
| 2430 | 2430 | ||
| 2431 | rb = (struct ocfs2_refcount_block *)ref_leaf_bh->b_data; | ||
| 2432 | |||
| 2433 | trace_ocfs2_calc_refcount_meta_credits_iterate( | 2431 | trace_ocfs2_calc_refcount_meta_credits_iterate( |
| 2434 | recs_add, (unsigned long long)cpos, clusters, | 2432 | recs_add, (unsigned long long)cpos, clusters, |
| 2435 | (unsigned long long)le64_to_cpu(rec.r_cpos), | 2433 | (unsigned long long)le64_to_cpu(rec.r_cpos), |
diff --git a/fs/ocfs2/reservations.c b/fs/ocfs2/reservations.c index 41ffd36c689c..6a348b0294ab 100644 --- a/fs/ocfs2/reservations.c +++ b/fs/ocfs2/reservations.c | |||
| @@ -39,7 +39,7 @@ | |||
| 39 | #define OCFS2_CHECK_RESERVATIONS | 39 | #define OCFS2_CHECK_RESERVATIONS |
| 40 | #endif | 40 | #endif |
| 41 | 41 | ||
| 42 | DEFINE_SPINLOCK(resv_lock); | 42 | static DEFINE_SPINLOCK(resv_lock); |
| 43 | 43 | ||
| 44 | #define OCFS2_MIN_RESV_WINDOW_BITS 8 | 44 | #define OCFS2_MIN_RESV_WINDOW_BITS 8 |
| 45 | #define OCFS2_MAX_RESV_WINDOW_BITS 1024 | 45 | #define OCFS2_MAX_RESV_WINDOW_BITS 1024 |
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 83723179e1ec..26675185b886 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c | |||
| @@ -191,6 +191,7 @@ enum { | |||
| 191 | Opt_coherency_full, | 191 | Opt_coherency_full, |
| 192 | Opt_resv_level, | 192 | Opt_resv_level, |
| 193 | Opt_dir_resv_level, | 193 | Opt_dir_resv_level, |
| 194 | Opt_journal_async_commit, | ||
| 194 | Opt_err, | 195 | Opt_err, |
| 195 | }; | 196 | }; |
| 196 | 197 | ||
| @@ -222,6 +223,7 @@ static const match_table_t tokens = { | |||
| 222 | {Opt_coherency_full, "coherency=full"}, | 223 | {Opt_coherency_full, "coherency=full"}, |
| 223 | {Opt_resv_level, "resv_level=%u"}, | 224 | {Opt_resv_level, "resv_level=%u"}, |
| 224 | {Opt_dir_resv_level, "dir_resv_level=%u"}, | 225 | {Opt_dir_resv_level, "dir_resv_level=%u"}, |
| 226 | {Opt_journal_async_commit, "journal_async_commit"}, | ||
| 225 | {Opt_err, NULL} | 227 | {Opt_err, NULL} |
| 226 | }; | 228 | }; |
| 227 | 229 | ||
| @@ -1000,36 +1002,6 @@ static void ocfs2_disable_quotas(struct ocfs2_super *osb) | |||
| 1000 | } | 1002 | } |
| 1001 | } | 1003 | } |
| 1002 | 1004 | ||
| 1003 | /* Handle quota on quotactl */ | ||
| 1004 | static int ocfs2_quota_on(struct super_block *sb, int type, int format_id) | ||
| 1005 | { | ||
| 1006 | unsigned int feature[OCFS2_MAXQUOTAS] = { | ||
| 1007 | OCFS2_FEATURE_RO_COMPAT_USRQUOTA, | ||
| 1008 | OCFS2_FEATURE_RO_COMPAT_GRPQUOTA}; | ||
| 1009 | |||
| 1010 | if (!OCFS2_HAS_RO_COMPAT_FEATURE(sb, feature[type])) | ||
| 1011 | return -EINVAL; | ||
| 1012 | |||
| 1013 | return dquot_enable(sb_dqopt(sb)->files[type], type, | ||
| 1014 | format_id, DQUOT_LIMITS_ENABLED); | ||
| 1015 | } | ||
| 1016 | |||
| 1017 | /* Handle quota off quotactl */ | ||
| 1018 | static int ocfs2_quota_off(struct super_block *sb, int type) | ||
| 1019 | { | ||
| 1020 | return dquot_disable(sb, type, DQUOT_LIMITS_ENABLED); | ||
| 1021 | } | ||
| 1022 | |||
| 1023 | static const struct quotactl_ops ocfs2_quotactl_ops = { | ||
| 1024 | .quota_on_meta = ocfs2_quota_on, | ||
| 1025 | .quota_off = ocfs2_quota_off, | ||
| 1026 | .quota_sync = dquot_quota_sync, | ||
| 1027 | .get_info = dquot_get_dqinfo, | ||
| 1028 | .set_info = dquot_set_dqinfo, | ||
| 1029 | .get_dqblk = dquot_get_dqblk, | ||
| 1030 | .set_dqblk = dquot_set_dqblk, | ||
| 1031 | }; | ||
| 1032 | |||
| 1033 | static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) | 1005 | static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) |
| 1034 | { | 1006 | { |
| 1035 | struct dentry *root; | 1007 | struct dentry *root; |
| @@ -1500,6 +1472,9 @@ static int ocfs2_parse_options(struct super_block *sb, | |||
| 1500 | option < OCFS2_MAX_RESV_LEVEL) | 1472 | option < OCFS2_MAX_RESV_LEVEL) |
| 1501 | mopt->dir_resv_level = option; | 1473 | mopt->dir_resv_level = option; |
| 1502 | break; | 1474 | break; |
| 1475 | case Opt_journal_async_commit: | ||
| 1476 | mopt->mount_opt |= OCFS2_MOUNT_JOURNAL_ASYNC_COMMIT; | ||
| 1477 | break; | ||
| 1503 | default: | 1478 | default: |
| 1504 | mlog(ML_ERROR, | 1479 | mlog(ML_ERROR, |
| 1505 | "Unrecognized mount option \"%s\" " | 1480 | "Unrecognized mount option \"%s\" " |
| @@ -1606,6 +1581,9 @@ static int ocfs2_show_options(struct seq_file *s, struct dentry *root) | |||
| 1606 | if (osb->osb_dir_resv_level != osb->osb_resv_level) | 1581 | if (osb->osb_dir_resv_level != osb->osb_resv_level) |
| 1607 | seq_printf(s, ",dir_resv_level=%d", osb->osb_resv_level); | 1582 | seq_printf(s, ",dir_resv_level=%d", osb->osb_resv_level); |
| 1608 | 1583 | ||
| 1584 | if (opts & OCFS2_MOUNT_JOURNAL_ASYNC_COMMIT) | ||
| 1585 | seq_printf(s, ",journal_async_commit"); | ||
| 1586 | |||
| 1609 | return 0; | 1587 | return 0; |
| 1610 | } | 1588 | } |
| 1611 | 1589 | ||
| @@ -1768,6 +1746,8 @@ static void ocfs2_inode_init_once(void *data) | |||
| 1768 | ocfs2_lock_res_init_once(&oi->ip_inode_lockres); | 1746 | ocfs2_lock_res_init_once(&oi->ip_inode_lockres); |
| 1769 | ocfs2_lock_res_init_once(&oi->ip_open_lockres); | 1747 | ocfs2_lock_res_init_once(&oi->ip_open_lockres); |
| 1770 | 1748 | ||
| 1749 | init_waitqueue_head(&oi->append_dio_wq); | ||
| 1750 | |||
| 1771 | ocfs2_metadata_cache_init(INODE_CACHE(&oi->vfs_inode), | 1751 | ocfs2_metadata_cache_init(INODE_CACHE(&oi->vfs_inode), |
| 1772 | &ocfs2_inode_caching_ops); | 1752 | &ocfs2_inode_caching_ops); |
| 1773 | 1753 | ||
| @@ -2079,7 +2059,7 @@ static int ocfs2_initialize_super(struct super_block *sb, | |||
| 2079 | sb->s_op = &ocfs2_sops; | 2059 | sb->s_op = &ocfs2_sops; |
| 2080 | sb->s_d_op = &ocfs2_dentry_ops; | 2060 | sb->s_d_op = &ocfs2_dentry_ops; |
| 2081 | sb->s_export_op = &ocfs2_export_ops; | 2061 | sb->s_export_op = &ocfs2_export_ops; |
| 2082 | sb->s_qcop = &ocfs2_quotactl_ops; | 2062 | sb->s_qcop = &dquot_quotactl_sysfile_ops; |
| 2083 | sb->dq_op = &ocfs2_quota_operations; | 2063 | sb->dq_op = &ocfs2_quota_operations; |
| 2084 | sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP; | 2064 | sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP; |
| 2085 | sb->s_xattr = ocfs2_xattr_handlers; | 2065 | sb->s_xattr = ocfs2_xattr_handlers; |
| @@ -2475,6 +2455,15 @@ static int ocfs2_check_volume(struct ocfs2_super *osb) | |||
| 2475 | goto finally; | 2455 | goto finally; |
| 2476 | } | 2456 | } |
| 2477 | 2457 | ||
| 2458 | if (osb->s_mount_opt & OCFS2_MOUNT_JOURNAL_ASYNC_COMMIT) | ||
| 2459 | jbd2_journal_set_features(osb->journal->j_journal, | ||
| 2460 | JBD2_FEATURE_COMPAT_CHECKSUM, 0, | ||
| 2461 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT); | ||
| 2462 | else | ||
| 2463 | jbd2_journal_clear_features(osb->journal->j_journal, | ||
| 2464 | JBD2_FEATURE_COMPAT_CHECKSUM, 0, | ||
| 2465 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT); | ||
| 2466 | |||
| 2478 | if (dirty) { | 2467 | if (dirty) { |
| 2479 | /* recover my local alloc if we didn't unmount cleanly. */ | 2468 | /* recover my local alloc if we didn't unmount cleanly. */ |
| 2480 | status = ocfs2_begin_local_alloc_recovery(osb, | 2469 | status = ocfs2_begin_local_alloc_recovery(osb, |
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index 662f8dee149f..85b190dc132f 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c | |||
| @@ -5334,16 +5334,6 @@ out: | |||
| 5334 | return ret; | 5334 | return ret; |
| 5335 | } | 5335 | } |
| 5336 | 5336 | ||
| 5337 | static inline char *ocfs2_xattr_bucket_get_val(struct inode *inode, | ||
| 5338 | struct ocfs2_xattr_bucket *bucket, | ||
| 5339 | int offs) | ||
| 5340 | { | ||
| 5341 | int block_off = offs >> inode->i_sb->s_blocksize_bits; | ||
| 5342 | |||
| 5343 | offs = offs % inode->i_sb->s_blocksize; | ||
| 5344 | return bucket_block(bucket, block_off) + offs; | ||
| 5345 | } | ||
| 5346 | |||
| 5347 | /* | 5337 | /* |
| 5348 | * Truncate the specified xe_off entry in xattr bucket. | 5338 | * Truncate the specified xe_off entry in xattr bucket. |
| 5349 | * bucket is indicated by header_bh and len is the new length. | 5339 | * bucket is indicated by header_bh and len is the new length. |
