diff options
Diffstat (limited to 'fs/xfs/xfs_qm_syscalls.c')
-rw-r--r-- | fs/xfs/xfs_qm_syscalls.c | 40 |
1 files changed, 23 insertions, 17 deletions
diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c index c41190cad6e9..6cdf6ffc36a1 100644 --- a/fs/xfs/xfs_qm_syscalls.c +++ b/fs/xfs/xfs_qm_syscalls.c | |||
@@ -489,31 +489,36 @@ xfs_qm_scall_setqlim( | |||
489 | if ((newlim->d_fieldmask & XFS_DQ_MASK) == 0) | 489 | if ((newlim->d_fieldmask & XFS_DQ_MASK) == 0) |
490 | return 0; | 490 | return 0; |
491 | 491 | ||
492 | tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SETQLIM); | ||
493 | error = xfs_trans_reserve(tp, 0, XFS_QM_SETQLIM_LOG_RES(mp), | ||
494 | 0, 0, XFS_DEFAULT_LOG_COUNT); | ||
495 | if (error) { | ||
496 | xfs_trans_cancel(tp, 0); | ||
497 | return (error); | ||
498 | } | ||
499 | |||
500 | /* | 492 | /* |
501 | * We don't want to race with a quotaoff so take the quotaoff lock. | 493 | * We don't want to race with a quotaoff so take the quotaoff lock. |
502 | * (We don't hold an inode lock, so there's nothing else to stop | 494 | * We don't hold an inode lock, so there's nothing else to stop |
503 | * a quotaoff from happening). (XXXThis doesn't currently happen | 495 | * a quotaoff from happening. |
504 | * because we take the vfslock before calling xfs_qm_sysent). | ||
505 | */ | 496 | */ |
506 | mutex_lock(&q->qi_quotaofflock); | 497 | mutex_lock(&q->qi_quotaofflock); |
507 | 498 | ||
508 | /* | 499 | /* |
509 | * Get the dquot (locked), and join it to the transaction. | 500 | * Get the dquot (locked) before we start, as we need to do a |
510 | * Allocate the dquot if this doesn't exist. | 501 | * transaction to allocate it if it doesn't exist. Once we have the |
502 | * dquot, unlock it so we can start the next transaction safely. We hold | ||
503 | * a reference to the dquot, so it's safe to do this unlock/lock without | ||
504 | * it being reclaimed in the mean time. | ||
511 | */ | 505 | */ |
512 | if ((error = xfs_qm_dqget(mp, NULL, id, type, XFS_QMOPT_DQALLOC, &dqp))) { | 506 | error = xfs_qm_dqget(mp, NULL, id, type, XFS_QMOPT_DQALLOC, &dqp); |
513 | xfs_trans_cancel(tp, XFS_TRANS_ABORT); | 507 | if (error) { |
514 | ASSERT(error != ENOENT); | 508 | ASSERT(error != ENOENT); |
515 | goto out_unlock; | 509 | goto out_unlock; |
516 | } | 510 | } |
511 | xfs_dqunlock(dqp); | ||
512 | |||
513 | tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SETQLIM); | ||
514 | error = xfs_trans_reserve(tp, 0, XFS_QM_SETQLIM_LOG_RES(mp), | ||
515 | 0, 0, XFS_DEFAULT_LOG_COUNT); | ||
516 | if (error) { | ||
517 | xfs_trans_cancel(tp, 0); | ||
518 | goto out_rele; | ||
519 | } | ||
520 | |||
521 | xfs_dqlock(dqp); | ||
517 | xfs_trans_dqjoin(tp, dqp); | 522 | xfs_trans_dqjoin(tp, dqp); |
518 | ddq = &dqp->q_core; | 523 | ddq = &dqp->q_core; |
519 | 524 | ||
@@ -621,9 +626,10 @@ xfs_qm_scall_setqlim( | |||
621 | xfs_trans_log_dquot(tp, dqp); | 626 | xfs_trans_log_dquot(tp, dqp); |
622 | 627 | ||
623 | error = xfs_trans_commit(tp, 0); | 628 | error = xfs_trans_commit(tp, 0); |
624 | xfs_qm_dqrele(dqp); | ||
625 | 629 | ||
626 | out_unlock: | 630 | out_rele: |
631 | xfs_qm_dqrele(dqp); | ||
632 | out_unlock: | ||
627 | mutex_unlock(&q->qi_quotaofflock); | 633 | mutex_unlock(&q->qi_quotaofflock); |
628 | return error; | 634 | return error; |
629 | } | 635 | } |