diff options
author | Joel Becker <Joel.Becker@oracle.com> | 2008-11-25 09:31:27 -0500 |
---|---|---|
committer | Mark Fasheh <mfasheh@suse.com> | 2009-01-05 11:40:24 -0500 |
commit | 85eb8b73d66530bb7b931789ae7a5ec9744eed34 (patch) | |
tree | 4590be147364e0437f23a0d6bf72ccc900852eb9 /fs | |
parent | 57a09a7b3d9445a17c78d544f1e49d4d7d61705a (diff) |
ocfs2: Fix ocfs2_read_quota_block() error handling.
ocfs2_bread() has become ocfs2_read_virt_blocks(), with a prototype to
match ocfs2_read_blocks(). The quota code, converting from
ocfs2_bread(), wraps the call to ocfs2_read_virt_blocks() in
ocfs2_read_quota_block(). Unfortunately, the prototype of
ocfs2_read_quota_block() matches the old prototype of ocfs2_bread().
The problem is that ocfs2_bread() returned the buffer head, and callers
assumed that a NULL pointer was indicative of error. It wasn't. This
is why ocfs2_bread() took an int*err argument as well.
The new prototype of ocfs2_read_virt_blocks() avoids this error handling
confusion. Let's change ocfs2_read_quota_block() to match.
Signed-off-by: Joel Becker <joel.becker@oracle.com>
Acked-by: Jan Kara <jack@suse.cz>
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ocfs2/dlmglue.c | 6 | ||||
-rw-r--r-- | fs/ocfs2/quota.h | 4 | ||||
-rw-r--r-- | fs/ocfs2/quota_global.c | 34 | ||||
-rw-r--r-- | fs/ocfs2/quota_local.c | 64 |
4 files changed, 60 insertions, 48 deletions
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 058aa86490ae..b1c75911d8ad 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c | |||
@@ -3519,7 +3519,7 @@ static int ocfs2_refresh_qinfo(struct ocfs2_mem_dqinfo *oinfo) | |||
3519 | oinfo->dqi_gi.dqi_type); | 3519 | oinfo->dqi_gi.dqi_type); |
3520 | struct ocfs2_lock_res *lockres = &oinfo->dqi_gqlock; | 3520 | struct ocfs2_lock_res *lockres = &oinfo->dqi_gqlock; |
3521 | struct ocfs2_qinfo_lvb *lvb = ocfs2_dlm_lvb(&lockres->l_lksb); | 3521 | struct ocfs2_qinfo_lvb *lvb = ocfs2_dlm_lvb(&lockres->l_lksb); |
3522 | struct buffer_head *bh; | 3522 | struct buffer_head *bh = NULL; |
3523 | struct ocfs2_global_disk_dqinfo *gdinfo; | 3523 | struct ocfs2_global_disk_dqinfo *gdinfo; |
3524 | int status = 0; | 3524 | int status = 0; |
3525 | 3525 | ||
@@ -3532,8 +3532,8 @@ static int ocfs2_refresh_qinfo(struct ocfs2_mem_dqinfo *oinfo) | |||
3532 | oinfo->dqi_gi.dqi_free_entry = | 3532 | oinfo->dqi_gi.dqi_free_entry = |
3533 | be32_to_cpu(lvb->lvb_free_entry); | 3533 | be32_to_cpu(lvb->lvb_free_entry); |
3534 | } else { | 3534 | } else { |
3535 | bh = ocfs2_read_quota_block(oinfo->dqi_gqinode, 0, &status); | 3535 | status = ocfs2_read_quota_block(oinfo->dqi_gqinode, 0, &bh); |
3536 | if (!bh) { | 3536 | if (status) { |
3537 | mlog_errno(status); | 3537 | mlog_errno(status); |
3538 | goto bail; | 3538 | goto bail; |
3539 | } | 3539 | } |
diff --git a/fs/ocfs2/quota.h b/fs/ocfs2/quota.h index 04872b45b990..7365e2e08706 100644 --- a/fs/ocfs2/quota.h +++ b/fs/ocfs2/quota.h | |||
@@ -107,8 +107,8 @@ static inline int ocfs2_global_release_dquot(struct dquot *dquot) | |||
107 | 107 | ||
108 | int ocfs2_lock_global_qf(struct ocfs2_mem_dqinfo *oinfo, int ex); | 108 | int ocfs2_lock_global_qf(struct ocfs2_mem_dqinfo *oinfo, int ex); |
109 | void ocfs2_unlock_global_qf(struct ocfs2_mem_dqinfo *oinfo, int ex); | 109 | void ocfs2_unlock_global_qf(struct ocfs2_mem_dqinfo *oinfo, int ex); |
110 | struct buffer_head *ocfs2_read_quota_block(struct inode *inode, | 110 | int ocfs2_read_quota_block(struct inode *inode, u64 v_block, |
111 | int block, int *err); | 111 | struct buffer_head **bh); |
112 | 112 | ||
113 | extern struct dquot_operations ocfs2_quota_operations; | 113 | extern struct dquot_operations ocfs2_quota_operations; |
114 | extern struct quota_format_type ocfs2_quota_format; | 114 | extern struct quota_format_type ocfs2_quota_format; |
diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c index 10ecb33298d8..2bdcddd3f1c4 100644 --- a/fs/ocfs2/quota_global.c +++ b/fs/ocfs2/quota_global.c | |||
@@ -87,16 +87,21 @@ struct qtree_fmt_operations ocfs2_global_ops = { | |||
87 | .is_id = ocfs2_global_is_id, | 87 | .is_id = ocfs2_global_is_id, |
88 | }; | 88 | }; |
89 | 89 | ||
90 | struct buffer_head *ocfs2_read_quota_block(struct inode *inode, | 90 | int ocfs2_read_quota_block(struct inode *inode, u64 v_block, |
91 | int block, int *err) | 91 | struct buffer_head **bh) |
92 | { | 92 | { |
93 | struct buffer_head *tmp = NULL; | 93 | int rc = 0; |
94 | struct buffer_head *tmp = *bh; | ||
94 | 95 | ||
95 | *err = ocfs2_read_virt_blocks(inode, block, 1, &tmp, 0, NULL); | 96 | rc = ocfs2_read_virt_blocks(inode, v_block, 1, &tmp, 0, NULL); |
96 | if (*err) | 97 | if (rc) |
97 | mlog_errno(*err); | 98 | mlog_errno(rc); |
99 | |||
100 | /* If ocfs2_read_virt_blocks() got us a new bh, pass it up. */ | ||
101 | if (!rc && !*bh) | ||
102 | *bh = tmp; | ||
98 | 103 | ||
99 | return tmp; | 104 | return rc; |
100 | } | 105 | } |
101 | 106 | ||
102 | static struct buffer_head *ocfs2_get_quota_block(struct inode *inode, | 107 | static struct buffer_head *ocfs2_get_quota_block(struct inode *inode, |
@@ -143,8 +148,9 @@ ssize_t ocfs2_quota_read(struct super_block *sb, int type, char *data, | |||
143 | toread = len; | 148 | toread = len; |
144 | while (toread > 0) { | 149 | while (toread > 0) { |
145 | tocopy = min((size_t)(sb->s_blocksize - offset), toread); | 150 | tocopy = min((size_t)(sb->s_blocksize - offset), toread); |
146 | bh = ocfs2_read_quota_block(gqinode, blk, &err); | 151 | bh = NULL; |
147 | if (!bh) { | 152 | err = ocfs2_read_quota_block(gqinode, blk, &bh); |
153 | if (err) { | ||
148 | mlog_errno(err); | 154 | mlog_errno(err); |
149 | return err; | 155 | return err; |
150 | } | 156 | } |
@@ -169,7 +175,7 @@ ssize_t ocfs2_quota_write(struct super_block *sb, int type, | |||
169 | int offset = off & (sb->s_blocksize - 1); | 175 | int offset = off & (sb->s_blocksize - 1); |
170 | sector_t blk = off >> sb->s_blocksize_bits; | 176 | sector_t blk = off >> sb->s_blocksize_bits; |
171 | int err = 0, new = 0; | 177 | int err = 0, new = 0; |
172 | struct buffer_head *bh; | 178 | struct buffer_head *bh = NULL; |
173 | handle_t *handle = journal_current_handle(); | 179 | handle_t *handle = journal_current_handle(); |
174 | 180 | ||
175 | if (!handle) { | 181 | if (!handle) { |
@@ -200,13 +206,13 @@ ssize_t ocfs2_quota_write(struct super_block *sb, int type, | |||
200 | /* Not rewriting whole block? */ | 206 | /* Not rewriting whole block? */ |
201 | if ((offset || len < sb->s_blocksize - OCFS2_QBLK_RESERVED_SPACE) && | 207 | if ((offset || len < sb->s_blocksize - OCFS2_QBLK_RESERVED_SPACE) && |
202 | !new) { | 208 | !new) { |
203 | bh = ocfs2_read_quota_block(gqinode, blk, &err); | 209 | err = ocfs2_read_quota_block(gqinode, blk, &bh); |
204 | if (!bh) { | 210 | if (err) { |
205 | mlog_errno(err); | 211 | mlog_errno(err); |
206 | return err; | 212 | return err; |
207 | } | 213 | } |
208 | err = ocfs2_journal_access(handle, gqinode, bh, | 214 | err = ocfs2_journal_access(handle, gqinode, bh, |
209 | OCFS2_JOURNAL_ACCESS_WRITE); | 215 | OCFS2_JOURNAL_ACCESS_WRITE); |
210 | } else { | 216 | } else { |
211 | bh = ocfs2_get_quota_block(gqinode, blk, &err); | 217 | bh = ocfs2_get_quota_block(gqinode, blk, &err); |
212 | if (!bh) { | 218 | if (!bh) { |
@@ -214,7 +220,7 @@ ssize_t ocfs2_quota_write(struct super_block *sb, int type, | |||
214 | return err; | 220 | return err; |
215 | } | 221 | } |
216 | err = ocfs2_journal_access(handle, gqinode, bh, | 222 | err = ocfs2_journal_access(handle, gqinode, bh, |
217 | OCFS2_JOURNAL_ACCESS_CREATE); | 223 | OCFS2_JOURNAL_ACCESS_CREATE); |
218 | } | 224 | } |
219 | if (err < 0) { | 225 | if (err < 0) { |
220 | brelse(bh); | 226 | brelse(bh); |
diff --git a/fs/ocfs2/quota_local.c b/fs/ocfs2/quota_local.c index b98562174cd0..7053664f66a6 100644 --- a/fs/ocfs2/quota_local.c +++ b/fs/ocfs2/quota_local.c | |||
@@ -139,15 +139,15 @@ static int ocfs2_local_check_quota_file(struct super_block *sb, int type) | |||
139 | unsigned int gversions[MAXQUOTAS] = OCFS2_GLOBAL_QVERSIONS; | 139 | unsigned int gversions[MAXQUOTAS] = OCFS2_GLOBAL_QVERSIONS; |
140 | unsigned int ino[MAXQUOTAS] = { USER_QUOTA_SYSTEM_INODE, | 140 | unsigned int ino[MAXQUOTAS] = { USER_QUOTA_SYSTEM_INODE, |
141 | GROUP_QUOTA_SYSTEM_INODE }; | 141 | GROUP_QUOTA_SYSTEM_INODE }; |
142 | struct buffer_head *bh; | 142 | struct buffer_head *bh = NULL; |
143 | struct inode *linode = sb_dqopt(sb)->files[type]; | 143 | struct inode *linode = sb_dqopt(sb)->files[type]; |
144 | struct inode *ginode = NULL; | 144 | struct inode *ginode = NULL; |
145 | struct ocfs2_disk_dqheader *dqhead; | 145 | struct ocfs2_disk_dqheader *dqhead; |
146 | int status, ret = 0; | 146 | int status, ret = 0; |
147 | 147 | ||
148 | /* First check whether we understand local quota file */ | 148 | /* First check whether we understand local quota file */ |
149 | bh = ocfs2_read_quota_block(linode, 0, &status); | 149 | status = ocfs2_read_quota_block(linode, 0, &bh); |
150 | if (!bh) { | 150 | if (status) { |
151 | mlog_errno(status); | 151 | mlog_errno(status); |
152 | mlog(ML_ERROR, "failed to read quota file header (type=%d)\n", | 152 | mlog(ML_ERROR, "failed to read quota file header (type=%d)\n", |
153 | type); | 153 | type); |
@@ -178,8 +178,8 @@ static int ocfs2_local_check_quota_file(struct super_block *sb, int type) | |||
178 | goto out_err; | 178 | goto out_err; |
179 | } | 179 | } |
180 | /* Since the header is read only, we don't care about locking */ | 180 | /* Since the header is read only, we don't care about locking */ |
181 | bh = ocfs2_read_quota_block(ginode, 0, &status); | 181 | status = ocfs2_read_quota_block(ginode, 0, &bh); |
182 | if (!bh) { | 182 | if (status) { |
183 | mlog_errno(status); | 183 | mlog_errno(status); |
184 | mlog(ML_ERROR, "failed to read global quota file header " | 184 | mlog(ML_ERROR, "failed to read global quota file header " |
185 | "(type=%d)\n", type); | 185 | "(type=%d)\n", type); |
@@ -235,10 +235,11 @@ static int ocfs2_load_local_quota_bitmaps(struct inode *inode, | |||
235 | return -ENOMEM; | 235 | return -ENOMEM; |
236 | } | 236 | } |
237 | newchunk->qc_num = i; | 237 | newchunk->qc_num = i; |
238 | newchunk->qc_headerbh = ocfs2_read_quota_block(inode, | 238 | newchunk->qc_headerbh = NULL; |
239 | status = ocfs2_read_quota_block(inode, | ||
239 | ol_quota_chunk_block(inode->i_sb, i), | 240 | ol_quota_chunk_block(inode->i_sb, i), |
240 | &status); | 241 | &newchunk->qc_headerbh); |
241 | if (!newchunk->qc_headerbh) { | 242 | if (status) { |
242 | mlog_errno(status); | 243 | mlog_errno(status); |
243 | kmem_cache_free(ocfs2_qf_chunk_cachep, newchunk); | 244 | kmem_cache_free(ocfs2_qf_chunk_cachep, newchunk); |
244 | ocfs2_release_local_quota_bitmaps(head); | 245 | ocfs2_release_local_quota_bitmaps(head); |
@@ -320,10 +321,11 @@ static int ocfs2_recovery_load_quota(struct inode *lqinode, | |||
320 | int status = 0; | 321 | int status = 0; |
321 | 322 | ||
322 | for (i = 0; i < chunks; i++) { | 323 | for (i = 0; i < chunks; i++) { |
323 | hbh = ocfs2_read_quota_block(lqinode, | 324 | hbh = NULL; |
324 | ol_quota_chunk_block(sb, i), | 325 | status = ocfs2_read_quota_block(lqinode, |
325 | &status); | 326 | ol_quota_chunk_block(sb, i), |
326 | if (!hbh) { | 327 | &hbh); |
328 | if (status) { | ||
327 | mlog_errno(status); | 329 | mlog_errno(status); |
328 | break; | 330 | break; |
329 | } | 331 | } |
@@ -392,8 +394,9 @@ struct ocfs2_quota_recovery *ocfs2_begin_quota_recovery( | |||
392 | goto out_put; | 394 | goto out_put; |
393 | } | 395 | } |
394 | /* Now read local header */ | 396 | /* Now read local header */ |
395 | bh = ocfs2_read_quota_block(lqinode, 0, &status); | 397 | bh = NULL; |
396 | if (!bh) { | 398 | status = ocfs2_read_quota_block(lqinode, 0, &bh); |
399 | if (status) { | ||
397 | mlog_errno(status); | 400 | mlog_errno(status); |
398 | mlog(ML_ERROR, "failed to read quota file info header " | 401 | mlog(ML_ERROR, "failed to read quota file info header " |
399 | "(slot=%d type=%d)\n", slot_num, type); | 402 | "(slot=%d type=%d)\n", slot_num, type); |
@@ -447,19 +450,21 @@ static int ocfs2_recover_local_quota_file(struct inode *lqinode, | |||
447 | 450 | ||
448 | list_for_each_entry_safe(rchunk, next, &(rec->r_list[type]), rc_list) { | 451 | list_for_each_entry_safe(rchunk, next, &(rec->r_list[type]), rc_list) { |
449 | chunk = rchunk->rc_chunk; | 452 | chunk = rchunk->rc_chunk; |
450 | hbh = ocfs2_read_quota_block(lqinode, | 453 | hbh = NULL; |
451 | ol_quota_chunk_block(sb, chunk), | 454 | status = ocfs2_read_quota_block(lqinode, |
452 | &status); | 455 | ol_quota_chunk_block(sb, chunk), |
453 | if (!hbh) { | 456 | &hbh); |
457 | if (status) { | ||
454 | mlog_errno(status); | 458 | mlog_errno(status); |
455 | break; | 459 | break; |
456 | } | 460 | } |
457 | dchunk = (struct ocfs2_local_disk_chunk *)hbh->b_data; | 461 | dchunk = (struct ocfs2_local_disk_chunk *)hbh->b_data; |
458 | for_each_bit(bit, rchunk->rc_bitmap, ol_chunk_entries(sb)) { | 462 | for_each_bit(bit, rchunk->rc_bitmap, ol_chunk_entries(sb)) { |
459 | qbh = ocfs2_read_quota_block(lqinode, | 463 | qbh = NULL; |
464 | status = ocfs2_read_quota_block(lqinode, | ||
460 | ol_dqblk_block(sb, chunk, bit), | 465 | ol_dqblk_block(sb, chunk, bit), |
461 | &status); | 466 | &qbh); |
462 | if (!qbh) { | 467 | if (status) { |
463 | mlog_errno(status); | 468 | mlog_errno(status); |
464 | break; | 469 | break; |
465 | } | 470 | } |
@@ -581,8 +586,9 @@ int ocfs2_finish_quota_recovery(struct ocfs2_super *osb, | |||
581 | goto out_put; | 586 | goto out_put; |
582 | } | 587 | } |
583 | /* Now read local header */ | 588 | /* Now read local header */ |
584 | bh = ocfs2_read_quota_block(lqinode, 0, &status); | 589 | bh = NULL; |
585 | if (!bh) { | 590 | status = ocfs2_read_quota_block(lqinode, 0, &bh); |
591 | if (status) { | ||
586 | mlog_errno(status); | 592 | mlog_errno(status); |
587 | mlog(ML_ERROR, "failed to read quota file info header " | 593 | mlog(ML_ERROR, "failed to read quota file info header " |
588 | "(slot=%d type=%d)\n", slot_num, type); | 594 | "(slot=%d type=%d)\n", slot_num, type); |
@@ -676,8 +682,8 @@ static int ocfs2_local_read_info(struct super_block *sb, int type) | |||
676 | locked = 1; | 682 | locked = 1; |
677 | 683 | ||
678 | /* Now read local header */ | 684 | /* Now read local header */ |
679 | bh = ocfs2_read_quota_block(lqinode, 0, &status); | 685 | status = ocfs2_read_quota_block(lqinode, 0, &bh); |
680 | if (!bh) { | 686 | if (status) { |
681 | mlog_errno(status); | 687 | mlog_errno(status); |
682 | mlog(ML_ERROR, "failed to read quota file info header " | 688 | mlog(ML_ERROR, "failed to read quota file info header " |
683 | "(type=%d)\n", type); | 689 | "(type=%d)\n", type); |
@@ -850,13 +856,13 @@ static int ocfs2_local_write_dquot(struct dquot *dquot) | |||
850 | { | 856 | { |
851 | struct super_block *sb = dquot->dq_sb; | 857 | struct super_block *sb = dquot->dq_sb; |
852 | struct ocfs2_dquot *od = OCFS2_DQUOT(dquot); | 858 | struct ocfs2_dquot *od = OCFS2_DQUOT(dquot); |
853 | struct buffer_head *bh; | 859 | struct buffer_head *bh = NULL; |
854 | int status; | 860 | int status; |
855 | 861 | ||
856 | bh = ocfs2_read_quota_block(sb_dqopt(sb)->files[dquot->dq_type], | 862 | status = ocfs2_read_quota_block(sb_dqopt(sb)->files[dquot->dq_type], |
857 | ol_dqblk_file_block(sb, od->dq_local_off), | 863 | ol_dqblk_file_block(sb, od->dq_local_off), |
858 | &status); | 864 | &bh); |
859 | if (!bh) { | 865 | if (status) { |
860 | mlog_errno(status); | 866 | mlog_errno(status); |
861 | goto out; | 867 | goto out; |
862 | } | 868 | } |