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 | } |
