aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2010-05-13 12:05:15 -0400
committerJan Kara <jack@suse.cz>2010-05-21 13:30:48 -0400
commit741e128933448e589a85286e535078b24f4cf568 (patch)
tree40a069e5c7484673529f0747a9995cc7d2a85f00 /fs/ocfs2
parent832d09cf1438bd172f69478bde74f20f05ec0115 (diff)
ocfs2: Fix NULL pointer deref when writing local dquot
commit_dqblk() can write quota info to global file. That is actually a bad thing to do because if we are just modifying local quota file, we are not prepared (do not hold proper locks, do not have transaction credits) to do a modification of the global quota file. So do not use commit_dqblk() and instead call our writing function directly. Acked-by: Joel Becker <Joel.Becker@oracle.com> Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/ocfs2')
-rw-r--r--fs/ocfs2/quota.h1
-rw-r--r--fs/ocfs2/quota_global.c20
-rw-r--r--fs/ocfs2/quota_local.c3
3 files changed, 12 insertions, 12 deletions
diff --git a/fs/ocfs2/quota.h b/fs/ocfs2/quota.h
index 903ffa933d53..196fcb52d95d 100644
--- a/fs/ocfs2/quota.h
+++ b/fs/ocfs2/quota.h
@@ -109,6 +109,7 @@ int ocfs2_read_quota_phys_block(struct inode *inode, u64 p_block,
109 struct buffer_head **bh); 109 struct buffer_head **bh);
110int ocfs2_create_local_dquot(struct dquot *dquot); 110int ocfs2_create_local_dquot(struct dquot *dquot);
111int ocfs2_local_release_dquot(handle_t *handle, struct dquot *dquot); 111int ocfs2_local_release_dquot(handle_t *handle, struct dquot *dquot);
112int ocfs2_local_write_dquot(struct dquot *dquot);
112 113
113extern const struct dquot_operations ocfs2_quota_operations; 114extern const struct dquot_operations ocfs2_quota_operations;
114extern struct quota_format_type ocfs2_quota_format; 115extern struct quota_format_type ocfs2_quota_format;
diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c
index 734995823740..2bb35fe00511 100644
--- a/fs/ocfs2/quota_global.c
+++ b/fs/ocfs2/quota_global.c
@@ -612,14 +612,13 @@ static int ocfs2_sync_dquot_helper(struct dquot *dquot, unsigned long type)
612 } 612 }
613 mutex_lock(&sb_dqopt(sb)->dqio_mutex); 613 mutex_lock(&sb_dqopt(sb)->dqio_mutex);
614 status = ocfs2_sync_dquot(dquot); 614 status = ocfs2_sync_dquot(dquot);
615 mutex_unlock(&sb_dqopt(sb)->dqio_mutex);
616 if (status < 0) 615 if (status < 0)
617 mlog_errno(status); 616 mlog_errno(status);
618 /* We have to write local structure as well... */ 617 /* We have to write local structure as well... */
619 dquot_mark_dquot_dirty(dquot); 618 status = ocfs2_local_write_dquot(dquot);
620 status = dquot_commit(dquot);
621 if (status < 0) 619 if (status < 0)
622 mlog_errno(status); 620 mlog_errno(status);
621 mutex_unlock(&sb_dqopt(sb)->dqio_mutex);
623 ocfs2_commit_trans(osb, handle); 622 ocfs2_commit_trans(osb, handle);
624out_ilock: 623out_ilock:
625 ocfs2_unlock_global_qf(oinfo, 1); 624 ocfs2_unlock_global_qf(oinfo, 1);
@@ -658,7 +657,9 @@ static int ocfs2_write_dquot(struct dquot *dquot)
658 mlog_errno(status); 657 mlog_errno(status);
659 goto out; 658 goto out;
660 } 659 }
661 status = dquot_commit(dquot); 660 mutex_lock(&sb_dqopt(dquot->dq_sb)->dqio_mutex);
661 status = ocfs2_local_write_dquot(dquot);
662 mutex_unlock(&sb_dqopt(dquot->dq_sb)->dqio_mutex);
662 ocfs2_commit_trans(osb, handle); 663 ocfs2_commit_trans(osb, handle);
663out: 664out:
664 mlog_exit(status); 665 mlog_exit(status);
@@ -831,7 +832,6 @@ static int ocfs2_mark_dquot_dirty(struct dquot *dquot)
831 struct ocfs2_super *osb = OCFS2_SB(sb); 832 struct ocfs2_super *osb = OCFS2_SB(sb);
832 833
833 mlog_entry("id=%u, type=%d", dquot->dq_id, type); 834 mlog_entry("id=%u, type=%d", dquot->dq_id, type);
834 dquot_mark_dquot_dirty(dquot);
835 835
836 /* In case user set some limits, sync dquot immediately to global 836 /* In case user set some limits, sync dquot immediately to global
837 * quota file so that information propagates quicker */ 837 * quota file so that information propagates quicker */
@@ -856,14 +856,14 @@ static int ocfs2_mark_dquot_dirty(struct dquot *dquot)
856 } 856 }
857 mutex_lock(&sb_dqopt(sb)->dqio_mutex); 857 mutex_lock(&sb_dqopt(sb)->dqio_mutex);
858 status = ocfs2_sync_dquot(dquot); 858 status = ocfs2_sync_dquot(dquot);
859 mutex_unlock(&sb_dqopt(sb)->dqio_mutex);
860 if (status < 0) { 859 if (status < 0) {
861 mlog_errno(status); 860 mlog_errno(status);
862 goto out_trans; 861 goto out_dlock;
863 } 862 }
864 /* Now write updated local dquot structure */ 863 /* Now write updated local dquot structure */
865 status = dquot_commit(dquot); 864 status = ocfs2_local_write_dquot(dquot);
866out_trans: 865out_dlock:
866 mutex_unlock(&sb_dqopt(sb)->dqio_mutex);
867 ocfs2_commit_trans(osb, handle); 867 ocfs2_commit_trans(osb, handle);
868out_ilock: 868out_ilock:
869 ocfs2_unlock_global_qf(oinfo, 1); 869 ocfs2_unlock_global_qf(oinfo, 1);
@@ -915,7 +915,7 @@ static void ocfs2_destroy_dquot(struct dquot *dquot)
915} 915}
916 916
917const struct dquot_operations ocfs2_quota_operations = { 917const struct dquot_operations ocfs2_quota_operations = {
918 .write_dquot = ocfs2_write_dquot, 918 /* We never make dquot dirty so .write_dquot is never called */
919 .acquire_dquot = ocfs2_acquire_dquot, 919 .acquire_dquot = ocfs2_acquire_dquot,
920 .release_dquot = ocfs2_release_dquot, 920 .release_dquot = ocfs2_release_dquot,
921 .mark_dirty = ocfs2_mark_dquot_dirty, 921 .mark_dirty = ocfs2_mark_dquot_dirty,
diff --git a/fs/ocfs2/quota_local.c b/fs/ocfs2/quota_local.c
index 778947f0e951..551a6bff9f2c 100644
--- a/fs/ocfs2/quota_local.c
+++ b/fs/ocfs2/quota_local.c
@@ -892,7 +892,7 @@ static void olq_set_dquot(struct buffer_head *bh, void *private)
892} 892}
893 893
894/* Write dquot to local quota file */ 894/* Write dquot to local quota file */
895static int ocfs2_local_write_dquot(struct dquot *dquot) 895int ocfs2_local_write_dquot(struct dquot *dquot)
896{ 896{
897 struct super_block *sb = dquot->dq_sb; 897 struct super_block *sb = dquot->dq_sb;
898 struct ocfs2_dquot *od = OCFS2_DQUOT(dquot); 898 struct ocfs2_dquot *od = OCFS2_DQUOT(dquot);
@@ -1309,7 +1309,6 @@ static const struct quota_format_ops ocfs2_format_ops = {
1309 .read_file_info = ocfs2_local_read_info, 1309 .read_file_info = ocfs2_local_read_info,
1310 .write_file_info = ocfs2_global_write_info, 1310 .write_file_info = ocfs2_global_write_info,
1311 .free_file_info = ocfs2_local_free_info, 1311 .free_file_info = ocfs2_local_free_info,
1312 .commit_dqblk = ocfs2_local_write_dquot,
1313}; 1312};
1314 1313
1315struct quota_format_type ocfs2_quota_format = { 1314struct quota_format_type ocfs2_quota_format = {