aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorBrian Foster <bfoster@redhat.com>2014-11-27 22:00:53 -0500
committerDave Chinner <david@fromorbit.com>2014-11-27 22:00:53 -0500
commit5d45ee1b41b02269ce04920a48cd2c6b2a458090 (patch)
tree772d6cfe61662d386549004c415eac8713d65b65 /fs/xfs
parent062647a8b41928f4fb97f967b24092be68f5f0f0 (diff)
xfs: fix error handling in xfs_qm_log_quotaoff()
The error handling in xfs_qm_log_quotaoff() has a couple problems. If xfs_trans_commit() fails, we fall through to the error block and call xfs_trans_cancel(). This is incorrect on commit failure. If xfs_trans_reserve() fails, we jump to the error block, cancel the tp and restore the superblock qflags to oldsbqflag. However, oldsbqflag has been initialized to zero and not yet updated from the original flags so we set the flags to zero. Fix up the error handling in xfs_qm_log_quotaoff() to not restore flags if they haven't been modified and not cancel the tp on commit failure. Remove the flag restore code altogether because commit error is the only failure condition and we don't know whether the transaction made it to disk. Reported-by: Dan Carpenter <dan.carpenter@oracle.com> Signed-off-by: Brian Foster <bfoster@redhat.com> Reviewed-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_qm_syscalls.c26
1 files changed, 10 insertions, 16 deletions
diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
index 80f2d77d929a..d1e0ab7a5d12 100644
--- a/fs/xfs/xfs_qm_syscalls.c
+++ b/fs/xfs/xfs_qm_syscalls.c
@@ -784,19 +784,21 @@ xfs_qm_log_quotaoff(
784{ 784{
785 xfs_trans_t *tp; 785 xfs_trans_t *tp;
786 int error; 786 int error;
787 xfs_qoff_logitem_t *qoffi=NULL; 787 xfs_qoff_logitem_t *qoffi;
788 uint oldsbqflag=0; 788
789 *qoffstartp = NULL;
789 790
790 tp = xfs_trans_alloc(mp, XFS_TRANS_QM_QUOTAOFF); 791 tp = xfs_trans_alloc(mp, XFS_TRANS_QM_QUOTAOFF);
791 error = xfs_trans_reserve(tp, &M_RES(mp)->tr_qm_quotaoff, 0, 0); 792 error = xfs_trans_reserve(tp, &M_RES(mp)->tr_qm_quotaoff, 0, 0);
792 if (error) 793 if (error) {
793 goto error0; 794 xfs_trans_cancel(tp, 0);
795 goto out;
796 }
794 797
795 qoffi = xfs_trans_get_qoff_item(tp, NULL, flags & XFS_ALL_QUOTA_ACCT); 798 qoffi = xfs_trans_get_qoff_item(tp, NULL, flags & XFS_ALL_QUOTA_ACCT);
796 xfs_trans_log_quotaoff_item(tp, qoffi); 799 xfs_trans_log_quotaoff_item(tp, qoffi);
797 800
798 spin_lock(&mp->m_sb_lock); 801 spin_lock(&mp->m_sb_lock);
799 oldsbqflag = mp->m_sb.sb_qflags;
800 mp->m_sb.sb_qflags = (mp->m_qflags & ~(flags)) & XFS_MOUNT_QUOTA_ALL; 802 mp->m_sb.sb_qflags = (mp->m_qflags & ~(flags)) & XFS_MOUNT_QUOTA_ALL;
801 spin_unlock(&mp->m_sb_lock); 803 spin_unlock(&mp->m_sb_lock);
802 804
@@ -809,19 +811,11 @@ xfs_qm_log_quotaoff(
809 */ 811 */
810 xfs_trans_set_sync(tp); 812 xfs_trans_set_sync(tp);
811 error = xfs_trans_commit(tp, 0); 813 error = xfs_trans_commit(tp, 0);
814 if (error)
815 goto out;
812 816
813error0:
814 if (error) {
815 xfs_trans_cancel(tp, 0);
816 /*
817 * No one else is modifying sb_qflags, so this is OK.
818 * We still hold the quotaofflock.
819 */
820 spin_lock(&mp->m_sb_lock);
821 mp->m_sb.sb_qflags = oldsbqflag;
822 spin_unlock(&mp->m_sb_lock);
823 }
824 *qoffstartp = qoffi; 817 *qoffstartp = qoffi;
818out:
825 return error; 819 return error;
826} 820}
827 821