diff options
| -rw-r--r-- | fs/ocfs2/quota_local.c | 98 |
1 files changed, 83 insertions, 15 deletions
diff --git a/fs/ocfs2/quota_local.c b/fs/ocfs2/quota_local.c index b624f9bc9281..9d2993de1082 100644 --- a/fs/ocfs2/quota_local.c +++ b/fs/ocfs2/quota_local.c | |||
| @@ -941,7 +941,7 @@ static struct ocfs2_quota_chunk *ocfs2_local_quota_add_chunk( | |||
| 941 | struct ocfs2_local_disk_chunk *dchunk; | 941 | struct ocfs2_local_disk_chunk *dchunk; |
| 942 | int status; | 942 | int status; |
| 943 | handle_t *handle; | 943 | handle_t *handle; |
| 944 | struct buffer_head *bh = NULL; | 944 | struct buffer_head *bh = NULL, *dbh = NULL; |
| 945 | u64 p_blkno; | 945 | u64 p_blkno; |
| 946 | 946 | ||
| 947 | /* We are protected by dqio_sem so no locking needed */ | 947 | /* We are protected by dqio_sem so no locking needed */ |
| @@ -965,34 +965,32 @@ static struct ocfs2_quota_chunk *ocfs2_local_quota_add_chunk( | |||
| 965 | mlog_errno(status); | 965 | mlog_errno(status); |
| 966 | goto out; | 966 | goto out; |
| 967 | } | 967 | } |
| 968 | handle = ocfs2_start_trans(OCFS2_SB(sb), 3); | ||
| 969 | if (IS_ERR(handle)) { | ||
| 970 | status = PTR_ERR(handle); | ||
| 971 | mlog_errno(status); | ||
| 972 | goto out; | ||
| 973 | } | ||
| 968 | 974 | ||
| 975 | /* Initialize chunk header */ | ||
| 969 | down_read(&OCFS2_I(lqinode)->ip_alloc_sem); | 976 | down_read(&OCFS2_I(lqinode)->ip_alloc_sem); |
| 970 | status = ocfs2_extent_map_get_blocks(lqinode, oinfo->dqi_blocks, | 977 | status = ocfs2_extent_map_get_blocks(lqinode, oinfo->dqi_blocks, |
| 971 | &p_blkno, NULL, NULL); | 978 | &p_blkno, NULL, NULL); |
| 972 | up_read(&OCFS2_I(lqinode)->ip_alloc_sem); | 979 | up_read(&OCFS2_I(lqinode)->ip_alloc_sem); |
| 973 | if (status < 0) { | 980 | if (status < 0) { |
| 974 | mlog_errno(status); | 981 | mlog_errno(status); |
| 975 | goto out; | 982 | goto out_trans; |
| 976 | } | 983 | } |
| 977 | bh = sb_getblk(sb, p_blkno); | 984 | bh = sb_getblk(sb, p_blkno); |
| 978 | if (!bh) { | 985 | if (!bh) { |
| 979 | status = -ENOMEM; | 986 | status = -ENOMEM; |
| 980 | mlog_errno(status); | 987 | mlog_errno(status); |
| 981 | goto out; | 988 | goto out_trans; |
| 982 | } | 989 | } |
| 983 | ocfs2_set_new_buffer_uptodate(lqinode, bh); | ||
| 984 | |||
| 985 | dchunk = (struct ocfs2_local_disk_chunk *)bh->b_data; | 990 | dchunk = (struct ocfs2_local_disk_chunk *)bh->b_data; |
| 986 | 991 | ocfs2_set_new_buffer_uptodate(lqinode, bh); | |
| 987 | handle = ocfs2_start_trans(OCFS2_SB(sb), 2); | ||
| 988 | if (IS_ERR(handle)) { | ||
| 989 | status = PTR_ERR(handle); | ||
| 990 | mlog_errno(status); | ||
| 991 | goto out; | ||
| 992 | } | ||
| 993 | |||
| 994 | status = ocfs2_journal_access_dq(handle, lqinode, bh, | 992 | status = ocfs2_journal_access_dq(handle, lqinode, bh, |
| 995 | OCFS2_JOURNAL_ACCESS_WRITE); | 993 | OCFS2_JOURNAL_ACCESS_CREATE); |
| 996 | if (status < 0) { | 994 | if (status < 0) { |
| 997 | mlog_errno(status); | 995 | mlog_errno(status); |
| 998 | goto out_trans; | 996 | goto out_trans; |
| @@ -1009,6 +1007,38 @@ static struct ocfs2_quota_chunk *ocfs2_local_quota_add_chunk( | |||
| 1009 | goto out_trans; | 1007 | goto out_trans; |
| 1010 | } | 1008 | } |
| 1011 | 1009 | ||
| 1010 | /* Initialize new block with structures */ | ||
| 1011 | down_read(&OCFS2_I(lqinode)->ip_alloc_sem); | ||
| 1012 | status = ocfs2_extent_map_get_blocks(lqinode, oinfo->dqi_blocks + 1, | ||
| 1013 | &p_blkno, NULL, NULL); | ||
| 1014 | up_read(&OCFS2_I(lqinode)->ip_alloc_sem); | ||
| 1015 | if (status < 0) { | ||
| 1016 | mlog_errno(status); | ||
| 1017 | goto out_trans; | ||
| 1018 | } | ||
| 1019 | dbh = sb_getblk(sb, p_blkno); | ||
| 1020 | if (!dbh) { | ||
| 1021 | status = -ENOMEM; | ||
| 1022 | mlog_errno(status); | ||
| 1023 | goto out_trans; | ||
| 1024 | } | ||
| 1025 | ocfs2_set_new_buffer_uptodate(lqinode, dbh); | ||
| 1026 | status = ocfs2_journal_access_dq(handle, lqinode, dbh, | ||
| 1027 | OCFS2_JOURNAL_ACCESS_CREATE); | ||
| 1028 | if (status < 0) { | ||
| 1029 | mlog_errno(status); | ||
| 1030 | goto out_trans; | ||
| 1031 | } | ||
| 1032 | lock_buffer(dbh); | ||
| 1033 | memset(dbh->b_data, 0, sb->s_blocksize - OCFS2_QBLK_RESERVED_SPACE); | ||
| 1034 | unlock_buffer(dbh); | ||
| 1035 | status = ocfs2_journal_dirty(handle, dbh); | ||
| 1036 | if (status < 0) { | ||
| 1037 | mlog_errno(status); | ||
| 1038 | goto out_trans; | ||
| 1039 | } | ||
| 1040 | |||
| 1041 | /* Update local quotafile info */ | ||
| 1012 | oinfo->dqi_blocks += 2; | 1042 | oinfo->dqi_blocks += 2; |
| 1013 | oinfo->dqi_chunks++; | 1043 | oinfo->dqi_chunks++; |
| 1014 | status = ocfs2_local_write_info(sb, type); | 1044 | status = ocfs2_local_write_info(sb, type); |
| @@ -1033,6 +1063,7 @@ out_trans: | |||
| 1033 | ocfs2_commit_trans(OCFS2_SB(sb), handle); | 1063 | ocfs2_commit_trans(OCFS2_SB(sb), handle); |
| 1034 | out: | 1064 | out: |
| 1035 | brelse(bh); | 1065 | brelse(bh); |
| 1066 | brelse(dbh); | ||
| 1036 | kmem_cache_free(ocfs2_qf_chunk_cachep, chunk); | 1067 | kmem_cache_free(ocfs2_qf_chunk_cachep, chunk); |
| 1037 | return ERR_PTR(status); | 1068 | return ERR_PTR(status); |
| 1038 | } | 1069 | } |
| @@ -1050,6 +1081,8 @@ static struct ocfs2_quota_chunk *ocfs2_extend_local_quota_file( | |||
| 1050 | struct ocfs2_local_disk_chunk *dchunk; | 1081 | struct ocfs2_local_disk_chunk *dchunk; |
| 1051 | int epb = ol_quota_entries_per_block(sb); | 1082 | int epb = ol_quota_entries_per_block(sb); |
| 1052 | unsigned int chunk_blocks; | 1083 | unsigned int chunk_blocks; |
| 1084 | struct buffer_head *bh; | ||
| 1085 | u64 p_blkno; | ||
| 1053 | int status; | 1086 | int status; |
| 1054 | handle_t *handle; | 1087 | handle_t *handle; |
| 1055 | 1088 | ||
| @@ -1077,12 +1110,46 @@ static struct ocfs2_quota_chunk *ocfs2_extend_local_quota_file( | |||
| 1077 | mlog_errno(status); | 1110 | mlog_errno(status); |
| 1078 | goto out; | 1111 | goto out; |
| 1079 | } | 1112 | } |
| 1080 | handle = ocfs2_start_trans(OCFS2_SB(sb), 2); | 1113 | |
| 1114 | /* Get buffer from the just added block */ | ||
| 1115 | down_read(&OCFS2_I(lqinode)->ip_alloc_sem); | ||
| 1116 | status = ocfs2_extent_map_get_blocks(lqinode, oinfo->dqi_blocks, | ||
| 1117 | &p_blkno, NULL, NULL); | ||
| 1118 | up_read(&OCFS2_I(lqinode)->ip_alloc_sem); | ||
| 1119 | if (status < 0) { | ||
| 1120 | mlog_errno(status); | ||
| 1121 | goto out; | ||
| 1122 | } | ||
| 1123 | bh = sb_getblk(sb, p_blkno); | ||
| 1124 | if (!bh) { | ||
| 1125 | status = -ENOMEM; | ||
| 1126 | mlog_errno(status); | ||
| 1127 | goto out; | ||
| 1128 | } | ||
| 1129 | ocfs2_set_new_buffer_uptodate(lqinode, bh); | ||
| 1130 | |||
| 1131 | handle = ocfs2_start_trans(OCFS2_SB(sb), 3); | ||
| 1081 | if (IS_ERR(handle)) { | 1132 | if (IS_ERR(handle)) { |
| 1082 | status = PTR_ERR(handle); | 1133 | status = PTR_ERR(handle); |
| 1083 | mlog_errno(status); | 1134 | mlog_errno(status); |
| 1084 | goto out; | 1135 | goto out; |
| 1085 | } | 1136 | } |
| 1137 | /* Zero created block */ | ||
| 1138 | status = ocfs2_journal_access_dq(handle, lqinode, bh, | ||
| 1139 | OCFS2_JOURNAL_ACCESS_CREATE); | ||
| 1140 | if (status < 0) { | ||
| 1141 | mlog_errno(status); | ||
| 1142 | goto out_trans; | ||
| 1143 | } | ||
| 1144 | lock_buffer(bh); | ||
| 1145 | memset(bh->b_data, 0, sb->s_blocksize); | ||
| 1146 | unlock_buffer(bh); | ||
| 1147 | status = ocfs2_journal_dirty(handle, bh); | ||
| 1148 | if (status < 0) { | ||
| 1149 | mlog_errno(status); | ||
| 1150 | goto out_trans; | ||
| 1151 | } | ||
| 1152 | /* Update chunk header */ | ||
| 1086 | status = ocfs2_journal_access_dq(handle, lqinode, chunk->qc_headerbh, | 1153 | status = ocfs2_journal_access_dq(handle, lqinode, chunk->qc_headerbh, |
| 1087 | OCFS2_JOURNAL_ACCESS_WRITE); | 1154 | OCFS2_JOURNAL_ACCESS_WRITE); |
| 1088 | if (status < 0) { | 1155 | if (status < 0) { |
| @@ -1099,6 +1166,7 @@ static struct ocfs2_quota_chunk *ocfs2_extend_local_quota_file( | |||
| 1099 | mlog_errno(status); | 1166 | mlog_errno(status); |
| 1100 | goto out_trans; | 1167 | goto out_trans; |
| 1101 | } | 1168 | } |
| 1169 | /* Update file header */ | ||
| 1102 | oinfo->dqi_blocks++; | 1170 | oinfo->dqi_blocks++; |
| 1103 | status = ocfs2_local_write_info(sb, type); | 1171 | status = ocfs2_local_write_info(sb, type); |
| 1104 | if (status < 0) { | 1172 | if (status < 0) { |
