diff options
Diffstat (limited to 'fs')
-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) { |