diff options
Diffstat (limited to 'fs/ocfs2/xattr.c')
-rw-r--r-- | fs/ocfs2/xattr.c | 200 |
1 files changed, 135 insertions, 65 deletions
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index e97b34842cfe..d03469f61801 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c | |||
@@ -709,7 +709,7 @@ static int ocfs2_xattr_extend_allocation(struct inode *inode, | |||
709 | struct ocfs2_xattr_value_buf *vb, | 709 | struct ocfs2_xattr_value_buf *vb, |
710 | struct ocfs2_xattr_set_ctxt *ctxt) | 710 | struct ocfs2_xattr_set_ctxt *ctxt) |
711 | { | 711 | { |
712 | int status = 0; | 712 | int status = 0, credits; |
713 | handle_t *handle = ctxt->handle; | 713 | handle_t *handle = ctxt->handle; |
714 | enum ocfs2_alloc_restarted why; | 714 | enum ocfs2_alloc_restarted why; |
715 | u32 prev_clusters, logical_start = le32_to_cpu(vb->vb_xv->xr_clusters); | 715 | u32 prev_clusters, logical_start = le32_to_cpu(vb->vb_xv->xr_clusters); |
@@ -719,38 +719,54 @@ static int ocfs2_xattr_extend_allocation(struct inode *inode, | |||
719 | 719 | ||
720 | ocfs2_init_xattr_value_extent_tree(&et, INODE_CACHE(inode), vb); | 720 | ocfs2_init_xattr_value_extent_tree(&et, INODE_CACHE(inode), vb); |
721 | 721 | ||
722 | status = vb->vb_access(handle, INODE_CACHE(inode), vb->vb_bh, | 722 | while (clusters_to_add) { |
723 | OCFS2_JOURNAL_ACCESS_WRITE); | 723 | status = vb->vb_access(handle, INODE_CACHE(inode), vb->vb_bh, |
724 | if (status < 0) { | 724 | OCFS2_JOURNAL_ACCESS_WRITE); |
725 | mlog_errno(status); | 725 | if (status < 0) { |
726 | goto leave; | 726 | mlog_errno(status); |
727 | } | 727 | break; |
728 | } | ||
728 | 729 | ||
729 | prev_clusters = le32_to_cpu(vb->vb_xv->xr_clusters); | 730 | prev_clusters = le32_to_cpu(vb->vb_xv->xr_clusters); |
730 | status = ocfs2_add_clusters_in_btree(handle, | 731 | status = ocfs2_add_clusters_in_btree(handle, |
731 | &et, | 732 | &et, |
732 | &logical_start, | 733 | &logical_start, |
733 | clusters_to_add, | 734 | clusters_to_add, |
734 | 0, | 735 | 0, |
735 | ctxt->data_ac, | 736 | ctxt->data_ac, |
736 | ctxt->meta_ac, | 737 | ctxt->meta_ac, |
737 | &why); | 738 | &why); |
738 | if (status < 0) { | 739 | if ((status < 0) && (status != -EAGAIN)) { |
739 | mlog_errno(status); | 740 | if (status != -ENOSPC) |
740 | goto leave; | 741 | mlog_errno(status); |
741 | } | 742 | break; |
743 | } | ||
742 | 744 | ||
743 | ocfs2_journal_dirty(handle, vb->vb_bh); | 745 | ocfs2_journal_dirty(handle, vb->vb_bh); |
744 | 746 | ||
745 | clusters_to_add -= le32_to_cpu(vb->vb_xv->xr_clusters) - prev_clusters; | 747 | clusters_to_add -= le32_to_cpu(vb->vb_xv->xr_clusters) - |
748 | prev_clusters; | ||
746 | 749 | ||
747 | /* | 750 | if (why != RESTART_NONE && clusters_to_add) { |
748 | * We should have already allocated enough space before the transaction, | 751 | /* |
749 | * so no need to restart. | 752 | * We can only fail in case the alloc file doesn't give |
750 | */ | 753 | * up enough clusters. |
751 | BUG_ON(why != RESTART_NONE || clusters_to_add); | 754 | */ |
752 | 755 | BUG_ON(why == RESTART_META); | |
753 | leave: | 756 | |
757 | mlog(0, "restarting xattr value extension for %u" | ||
758 | " clusters,.\n", clusters_to_add); | ||
759 | credits = ocfs2_calc_extend_credits(inode->i_sb, | ||
760 | &vb->vb_xv->xr_list, | ||
761 | clusters_to_add); | ||
762 | status = ocfs2_extend_trans(handle, credits); | ||
763 | if (status < 0) { | ||
764 | status = -ENOMEM; | ||
765 | mlog_errno(status); | ||
766 | break; | ||
767 | } | ||
768 | } | ||
769 | } | ||
754 | 770 | ||
755 | return status; | 771 | return status; |
756 | } | 772 | } |
@@ -6788,16 +6804,15 @@ out: | |||
6788 | return ret; | 6804 | return ret; |
6789 | } | 6805 | } |
6790 | 6806 | ||
6791 | static int ocfs2_reflink_xattr_buckets(handle_t *handle, | 6807 | static int ocfs2_reflink_xattr_bucket(handle_t *handle, |
6792 | u64 blkno, u64 new_blkno, u32 clusters, | 6808 | u64 blkno, u64 new_blkno, u32 clusters, |
6809 | u32 *cpos, int num_buckets, | ||
6793 | struct ocfs2_alloc_context *meta_ac, | 6810 | struct ocfs2_alloc_context *meta_ac, |
6794 | struct ocfs2_alloc_context *data_ac, | 6811 | struct ocfs2_alloc_context *data_ac, |
6795 | struct ocfs2_reflink_xattr_tree_args *args) | 6812 | struct ocfs2_reflink_xattr_tree_args *args) |
6796 | { | 6813 | { |
6797 | int i, j, ret = 0; | 6814 | int i, j, ret = 0; |
6798 | struct super_block *sb = args->reflink->old_inode->i_sb; | 6815 | struct super_block *sb = args->reflink->old_inode->i_sb; |
6799 | u32 bpc = ocfs2_xattr_buckets_per_cluster(OCFS2_SB(sb)); | ||
6800 | u32 num_buckets = clusters * bpc; | ||
6801 | int bpb = args->old_bucket->bu_blocks; | 6816 | int bpb = args->old_bucket->bu_blocks; |
6802 | struct ocfs2_xattr_value_buf vb = { | 6817 | struct ocfs2_xattr_value_buf vb = { |
6803 | .vb_access = ocfs2_journal_access, | 6818 | .vb_access = ocfs2_journal_access, |
@@ -6816,14 +6831,6 @@ static int ocfs2_reflink_xattr_buckets(handle_t *handle, | |||
6816 | break; | 6831 | break; |
6817 | } | 6832 | } |
6818 | 6833 | ||
6819 | /* | ||
6820 | * The real bucket num in this series of blocks is stored | ||
6821 | * in the 1st bucket. | ||
6822 | */ | ||
6823 | if (i == 0) | ||
6824 | num_buckets = le16_to_cpu( | ||
6825 | bucket_xh(args->old_bucket)->xh_num_buckets); | ||
6826 | |||
6827 | ret = ocfs2_xattr_bucket_journal_access(handle, | 6834 | ret = ocfs2_xattr_bucket_journal_access(handle, |
6828 | args->new_bucket, | 6835 | args->new_bucket, |
6829 | OCFS2_JOURNAL_ACCESS_CREATE); | 6836 | OCFS2_JOURNAL_ACCESS_CREATE); |
@@ -6837,6 +6844,18 @@ static int ocfs2_reflink_xattr_buckets(handle_t *handle, | |||
6837 | bucket_block(args->old_bucket, j), | 6844 | bucket_block(args->old_bucket, j), |
6838 | sb->s_blocksize); | 6845 | sb->s_blocksize); |
6839 | 6846 | ||
6847 | /* | ||
6848 | * Record the start cpos so that we can use it to initialize | ||
6849 | * our xattr tree we also set the xh_num_bucket for the new | ||
6850 | * bucket. | ||
6851 | */ | ||
6852 | if (i == 0) { | ||
6853 | *cpos = le32_to_cpu(bucket_xh(args->new_bucket)-> | ||
6854 | xh_entries[0].xe_name_hash); | ||
6855 | bucket_xh(args->new_bucket)->xh_num_buckets = | ||
6856 | cpu_to_le16(num_buckets); | ||
6857 | } | ||
6858 | |||
6840 | ocfs2_xattr_bucket_journal_dirty(handle, args->new_bucket); | 6859 | ocfs2_xattr_bucket_journal_dirty(handle, args->new_bucket); |
6841 | 6860 | ||
6842 | ret = ocfs2_reflink_xattr_header(handle, args->reflink, | 6861 | ret = ocfs2_reflink_xattr_header(handle, args->reflink, |
@@ -6866,6 +6885,7 @@ static int ocfs2_reflink_xattr_buckets(handle_t *handle, | |||
6866 | } | 6885 | } |
6867 | 6886 | ||
6868 | ocfs2_xattr_bucket_journal_dirty(handle, args->new_bucket); | 6887 | ocfs2_xattr_bucket_journal_dirty(handle, args->new_bucket); |
6888 | |||
6869 | ocfs2_xattr_bucket_relse(args->old_bucket); | 6889 | ocfs2_xattr_bucket_relse(args->old_bucket); |
6870 | ocfs2_xattr_bucket_relse(args->new_bucket); | 6890 | ocfs2_xattr_bucket_relse(args->new_bucket); |
6871 | } | 6891 | } |
@@ -6874,6 +6894,75 @@ static int ocfs2_reflink_xattr_buckets(handle_t *handle, | |||
6874 | ocfs2_xattr_bucket_relse(args->new_bucket); | 6894 | ocfs2_xattr_bucket_relse(args->new_bucket); |
6875 | return ret; | 6895 | return ret; |
6876 | } | 6896 | } |
6897 | |||
6898 | static int ocfs2_reflink_xattr_buckets(handle_t *handle, | ||
6899 | struct inode *inode, | ||
6900 | struct ocfs2_reflink_xattr_tree_args *args, | ||
6901 | struct ocfs2_extent_tree *et, | ||
6902 | struct ocfs2_alloc_context *meta_ac, | ||
6903 | struct ocfs2_alloc_context *data_ac, | ||
6904 | u64 blkno, u32 cpos, u32 len) | ||
6905 | { | ||
6906 | int ret, first_inserted = 0; | ||
6907 | u32 p_cluster, num_clusters, reflink_cpos = 0; | ||
6908 | u64 new_blkno; | ||
6909 | unsigned int num_buckets, reflink_buckets; | ||
6910 | unsigned int bpc = | ||
6911 | ocfs2_xattr_buckets_per_cluster(OCFS2_SB(inode->i_sb)); | ||
6912 | |||
6913 | ret = ocfs2_read_xattr_bucket(args->old_bucket, blkno); | ||
6914 | if (ret) { | ||
6915 | mlog_errno(ret); | ||
6916 | goto out; | ||
6917 | } | ||
6918 | num_buckets = le16_to_cpu(bucket_xh(args->old_bucket)->xh_num_buckets); | ||
6919 | ocfs2_xattr_bucket_relse(args->old_bucket); | ||
6920 | |||
6921 | while (len && num_buckets) { | ||
6922 | ret = ocfs2_claim_clusters(handle, data_ac, | ||
6923 | 1, &p_cluster, &num_clusters); | ||
6924 | if (ret) { | ||
6925 | mlog_errno(ret); | ||
6926 | goto out; | ||
6927 | } | ||
6928 | |||
6929 | new_blkno = ocfs2_clusters_to_blocks(inode->i_sb, p_cluster); | ||
6930 | reflink_buckets = min(num_buckets, bpc * num_clusters); | ||
6931 | |||
6932 | ret = ocfs2_reflink_xattr_bucket(handle, blkno, | ||
6933 | new_blkno, num_clusters, | ||
6934 | &reflink_cpos, reflink_buckets, | ||
6935 | meta_ac, data_ac, args); | ||
6936 | if (ret) { | ||
6937 | mlog_errno(ret); | ||
6938 | goto out; | ||
6939 | } | ||
6940 | |||
6941 | /* | ||
6942 | * For the 1st allocated cluster, we make it use the same cpos | ||
6943 | * so that the xattr tree looks the same as the original one | ||
6944 | * in the most case. | ||
6945 | */ | ||
6946 | if (!first_inserted) { | ||
6947 | reflink_cpos = cpos; | ||
6948 | first_inserted = 1; | ||
6949 | } | ||
6950 | ret = ocfs2_insert_extent(handle, et, reflink_cpos, new_blkno, | ||
6951 | num_clusters, 0, meta_ac); | ||
6952 | if (ret) | ||
6953 | mlog_errno(ret); | ||
6954 | |||
6955 | mlog(0, "insert new xattr extent rec start %llu len %u to %u\n", | ||
6956 | (unsigned long long)new_blkno, num_clusters, reflink_cpos); | ||
6957 | |||
6958 | len -= num_clusters; | ||
6959 | blkno += ocfs2_clusters_to_blocks(inode->i_sb, num_clusters); | ||
6960 | num_buckets -= reflink_buckets; | ||
6961 | } | ||
6962 | out: | ||
6963 | return ret; | ||
6964 | } | ||
6965 | |||
6877 | /* | 6966 | /* |
6878 | * Create the same xattr extent record in the new inode's xattr tree. | 6967 | * Create the same xattr extent record in the new inode's xattr tree. |
6879 | */ | 6968 | */ |
@@ -6885,8 +6974,6 @@ static int ocfs2_reflink_xattr_rec(struct inode *inode, | |||
6885 | void *para) | 6974 | void *para) |
6886 | { | 6975 | { |
6887 | int ret, credits = 0; | 6976 | int ret, credits = 0; |
6888 | u32 p_cluster, num_clusters; | ||
6889 | u64 new_blkno; | ||
6890 | handle_t *handle; | 6977 | handle_t *handle; |
6891 | struct ocfs2_reflink_xattr_tree_args *args = | 6978 | struct ocfs2_reflink_xattr_tree_args *args = |
6892 | (struct ocfs2_reflink_xattr_tree_args *)para; | 6979 | (struct ocfs2_reflink_xattr_tree_args *)para; |
@@ -6895,6 +6982,9 @@ static int ocfs2_reflink_xattr_rec(struct inode *inode, | |||
6895 | struct ocfs2_alloc_context *data_ac = NULL; | 6982 | struct ocfs2_alloc_context *data_ac = NULL; |
6896 | struct ocfs2_extent_tree et; | 6983 | struct ocfs2_extent_tree et; |
6897 | 6984 | ||
6985 | mlog(0, "reflink xattr buckets %llu len %u\n", | ||
6986 | (unsigned long long)blkno, len); | ||
6987 | |||
6898 | ocfs2_init_xattr_tree_extent_tree(&et, | 6988 | ocfs2_init_xattr_tree_extent_tree(&et, |
6899 | INODE_CACHE(args->reflink->new_inode), | 6989 | INODE_CACHE(args->reflink->new_inode), |
6900 | args->new_blk_bh); | 6990 | args->new_blk_bh); |
@@ -6914,32 +7004,12 @@ static int ocfs2_reflink_xattr_rec(struct inode *inode, | |||
6914 | goto out; | 7004 | goto out; |
6915 | } | 7005 | } |
6916 | 7006 | ||
6917 | ret = ocfs2_claim_clusters(handle, data_ac, | 7007 | ret = ocfs2_reflink_xattr_buckets(handle, inode, args, &et, |
6918 | len, &p_cluster, &num_clusters); | 7008 | meta_ac, data_ac, |
6919 | if (ret) { | 7009 | blkno, cpos, len); |
6920 | mlog_errno(ret); | ||
6921 | goto out_commit; | ||
6922 | } | ||
6923 | |||
6924 | new_blkno = ocfs2_clusters_to_blocks(osb->sb, p_cluster); | ||
6925 | |||
6926 | mlog(0, "reflink xattr buckets %llu to %llu, len %u\n", | ||
6927 | (unsigned long long)blkno, (unsigned long long)new_blkno, len); | ||
6928 | ret = ocfs2_reflink_xattr_buckets(handle, blkno, new_blkno, len, | ||
6929 | meta_ac, data_ac, args); | ||
6930 | if (ret) { | ||
6931 | mlog_errno(ret); | ||
6932 | goto out_commit; | ||
6933 | } | ||
6934 | |||
6935 | mlog(0, "insert new xattr extent rec start %llu len %u to %u\n", | ||
6936 | (unsigned long long)new_blkno, len, cpos); | ||
6937 | ret = ocfs2_insert_extent(handle, &et, cpos, new_blkno, | ||
6938 | len, 0, meta_ac); | ||
6939 | if (ret) | 7010 | if (ret) |
6940 | mlog_errno(ret); | 7011 | mlog_errno(ret); |
6941 | 7012 | ||
6942 | out_commit: | ||
6943 | ocfs2_commit_trans(osb, handle); | 7013 | ocfs2_commit_trans(osb, handle); |
6944 | 7014 | ||
6945 | out: | 7015 | out: |