0001
0002
0003
0004
0005
0006 #include "xfs.h"
0007 #include "xfs_fs.h"
0008 #include "xfs_shared.h"
0009 #include "xfs_format.h"
0010 #include "xfs_log_format.h"
0011 #include "xfs_trans_resv.h"
0012 #include "xfs_mount.h"
0013 #include "xfs_inode.h"
0014 #include "xfs_trans.h"
0015 #include "xfs_trans_priv.h"
0016 #include "xfs_quota.h"
0017 #include "xfs_qm.h"
0018 #include "xfs_trace.h"
0019 #include "xfs_error.h"
0020
0021 STATIC void xfs_trans_alloc_dqinfo(xfs_trans_t *);
0022
0023
0024
0025
0026
0027
0028 void
0029 xfs_trans_dqjoin(
0030 struct xfs_trans *tp,
0031 struct xfs_dquot *dqp)
0032 {
0033 ASSERT(XFS_DQ_IS_LOCKED(dqp));
0034 ASSERT(dqp->q_logitem.qli_dquot == dqp);
0035
0036
0037
0038
0039 xfs_trans_add_item(tp, &dqp->q_logitem.qli_item);
0040 }
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052 void
0053 xfs_trans_log_dquot(
0054 struct xfs_trans *tp,
0055 struct xfs_dquot *dqp)
0056 {
0057 ASSERT(XFS_DQ_IS_LOCKED(dqp));
0058
0059
0060 if (dqp->q_id != 0 &&
0061 xfs_has_bigtime(tp->t_mountp) &&
0062 !(dqp->q_type & XFS_DQTYPE_BIGTIME))
0063 dqp->q_type |= XFS_DQTYPE_BIGTIME;
0064
0065 tp->t_flags |= XFS_TRANS_DIRTY;
0066 set_bit(XFS_LI_DIRTY, &dqp->q_logitem.qli_item.li_flags);
0067 }
0068
0069
0070
0071
0072
0073 void
0074 xfs_trans_dup_dqinfo(
0075 struct xfs_trans *otp,
0076 struct xfs_trans *ntp)
0077 {
0078 struct xfs_dqtrx *oq, *nq;
0079 int i, j;
0080 struct xfs_dqtrx *oqa, *nqa;
0081 uint64_t blk_res_used;
0082
0083 if (!otp->t_dqinfo)
0084 return;
0085
0086 xfs_trans_alloc_dqinfo(ntp);
0087
0088 for (j = 0; j < XFS_QM_TRANS_DQTYPES; j++) {
0089 oqa = otp->t_dqinfo->dqs[j];
0090 nqa = ntp->t_dqinfo->dqs[j];
0091 for (i = 0; i < XFS_QM_TRANS_MAXDQS; i++) {
0092 blk_res_used = 0;
0093
0094 if (oqa[i].qt_dquot == NULL)
0095 break;
0096 oq = &oqa[i];
0097 nq = &nqa[i];
0098
0099 if (oq->qt_blk_res && oq->qt_bcount_delta > 0)
0100 blk_res_used = oq->qt_bcount_delta;
0101
0102 nq->qt_dquot = oq->qt_dquot;
0103 nq->qt_bcount_delta = nq->qt_icount_delta = 0;
0104 nq->qt_rtbcount_delta = 0;
0105
0106
0107
0108
0109 nq->qt_blk_res = oq->qt_blk_res - blk_res_used;
0110 oq->qt_blk_res = blk_res_used;
0111
0112 nq->qt_rtblk_res = oq->qt_rtblk_res -
0113 oq->qt_rtblk_res_used;
0114 oq->qt_rtblk_res = oq->qt_rtblk_res_used;
0115
0116 nq->qt_ino_res = oq->qt_ino_res - oq->qt_ino_res_used;
0117 oq->qt_ino_res = oq->qt_ino_res_used;
0118
0119 }
0120 }
0121 }
0122
0123
0124
0125
0126 void
0127 xfs_trans_mod_dquot_byino(
0128 xfs_trans_t *tp,
0129 xfs_inode_t *ip,
0130 uint field,
0131 int64_t delta)
0132 {
0133 xfs_mount_t *mp = tp->t_mountp;
0134
0135 if (!XFS_IS_QUOTA_ON(mp) ||
0136 xfs_is_quota_inode(&mp->m_sb, ip->i_ino))
0137 return;
0138
0139 if (XFS_IS_UQUOTA_ON(mp) && ip->i_udquot)
0140 (void) xfs_trans_mod_dquot(tp, ip->i_udquot, field, delta);
0141 if (XFS_IS_GQUOTA_ON(mp) && ip->i_gdquot)
0142 (void) xfs_trans_mod_dquot(tp, ip->i_gdquot, field, delta);
0143 if (XFS_IS_PQUOTA_ON(mp) && ip->i_pdquot)
0144 (void) xfs_trans_mod_dquot(tp, ip->i_pdquot, field, delta);
0145 }
0146
0147 STATIC struct xfs_dqtrx *
0148 xfs_trans_get_dqtrx(
0149 struct xfs_trans *tp,
0150 struct xfs_dquot *dqp)
0151 {
0152 int i;
0153 struct xfs_dqtrx *qa;
0154
0155 switch (xfs_dquot_type(dqp)) {
0156 case XFS_DQTYPE_USER:
0157 qa = tp->t_dqinfo->dqs[XFS_QM_TRANS_USR];
0158 break;
0159 case XFS_DQTYPE_GROUP:
0160 qa = tp->t_dqinfo->dqs[XFS_QM_TRANS_GRP];
0161 break;
0162 case XFS_DQTYPE_PROJ:
0163 qa = tp->t_dqinfo->dqs[XFS_QM_TRANS_PRJ];
0164 break;
0165 default:
0166 return NULL;
0167 }
0168
0169 for (i = 0; i < XFS_QM_TRANS_MAXDQS; i++) {
0170 if (qa[i].qt_dquot == NULL ||
0171 qa[i].qt_dquot == dqp)
0172 return &qa[i];
0173 }
0174
0175 return NULL;
0176 }
0177
0178
0179
0180
0181
0182
0183
0184 void
0185 xfs_trans_mod_dquot(
0186 struct xfs_trans *tp,
0187 struct xfs_dquot *dqp,
0188 uint field,
0189 int64_t delta)
0190 {
0191 struct xfs_dqtrx *qtrx;
0192
0193 ASSERT(tp);
0194 ASSERT(XFS_IS_QUOTA_ON(tp->t_mountp));
0195 qtrx = NULL;
0196
0197 if (!delta)
0198 return;
0199
0200 if (tp->t_dqinfo == NULL)
0201 xfs_trans_alloc_dqinfo(tp);
0202
0203
0204
0205
0206 qtrx = xfs_trans_get_dqtrx(tp, dqp);
0207 ASSERT(qtrx);
0208 if (qtrx->qt_dquot == NULL)
0209 qtrx->qt_dquot = dqp;
0210
0211 trace_xfs_trans_mod_dquot_before(qtrx);
0212 trace_xfs_trans_mod_dquot(tp, dqp, field, delta);
0213
0214 switch (field) {
0215
0216 case XFS_TRANS_DQ_RES_BLKS:
0217 qtrx->qt_blk_res += delta;
0218 break;
0219
0220
0221 case XFS_TRANS_DQ_RES_INOS:
0222 qtrx->qt_ino_res += delta;
0223 break;
0224
0225
0226 case XFS_TRANS_DQ_BCOUNT:
0227 qtrx->qt_bcount_delta += delta;
0228 break;
0229
0230 case XFS_TRANS_DQ_DELBCOUNT:
0231 qtrx->qt_delbcnt_delta += delta;
0232 break;
0233
0234
0235 case XFS_TRANS_DQ_ICOUNT:
0236 if (qtrx->qt_ino_res && delta > 0) {
0237 qtrx->qt_ino_res_used += delta;
0238 ASSERT(qtrx->qt_ino_res >= qtrx->qt_ino_res_used);
0239 }
0240 qtrx->qt_icount_delta += delta;
0241 break;
0242
0243
0244 case XFS_TRANS_DQ_RES_RTBLKS:
0245 qtrx->qt_rtblk_res += delta;
0246 break;
0247
0248
0249 case XFS_TRANS_DQ_RTBCOUNT:
0250 if (qtrx->qt_rtblk_res && delta > 0) {
0251 qtrx->qt_rtblk_res_used += delta;
0252 ASSERT(qtrx->qt_rtblk_res >= qtrx->qt_rtblk_res_used);
0253 }
0254 qtrx->qt_rtbcount_delta += delta;
0255 break;
0256
0257 case XFS_TRANS_DQ_DELRTBCOUNT:
0258 qtrx->qt_delrtb_delta += delta;
0259 break;
0260
0261 default:
0262 ASSERT(0);
0263 }
0264
0265 trace_xfs_trans_mod_dquot_after(qtrx);
0266 }
0267
0268
0269
0270
0271
0272
0273
0274
0275 STATIC void
0276 xfs_trans_dqlockedjoin(
0277 struct xfs_trans *tp,
0278 struct xfs_dqtrx *q)
0279 {
0280 ASSERT(q[0].qt_dquot != NULL);
0281 if (q[1].qt_dquot == NULL) {
0282 xfs_dqlock(q[0].qt_dquot);
0283 xfs_trans_dqjoin(tp, q[0].qt_dquot);
0284 } else {
0285 ASSERT(XFS_QM_TRANS_MAXDQS == 2);
0286 xfs_dqlock2(q[0].qt_dquot, q[1].qt_dquot);
0287 xfs_trans_dqjoin(tp, q[0].qt_dquot);
0288 xfs_trans_dqjoin(tp, q[1].qt_dquot);
0289 }
0290 }
0291
0292
0293 static inline void
0294 xfs_apply_quota_reservation_deltas(
0295 struct xfs_dquot_res *res,
0296 uint64_t reserved,
0297 int64_t res_used,
0298 int64_t count_delta)
0299 {
0300 if (reserved != 0) {
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312 res->reserved -= abs(reserved - res_used);
0313 } else if (count_delta != 0) {
0314
0315
0316
0317
0318
0319
0320 res->reserved += count_delta;
0321 }
0322 }
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332 void
0333 xfs_trans_apply_dquot_deltas(
0334 struct xfs_trans *tp)
0335 {
0336 int i, j;
0337 struct xfs_dquot *dqp;
0338 struct xfs_dqtrx *qtrx, *qa;
0339 int64_t totalbdelta;
0340 int64_t totalrtbdelta;
0341
0342 if (!tp->t_dqinfo)
0343 return;
0344
0345 ASSERT(tp->t_dqinfo);
0346 for (j = 0; j < XFS_QM_TRANS_DQTYPES; j++) {
0347 qa = tp->t_dqinfo->dqs[j];
0348 if (qa[0].qt_dquot == NULL)
0349 continue;
0350
0351
0352
0353
0354 xfs_trans_dqlockedjoin(tp, qa);
0355
0356 for (i = 0; i < XFS_QM_TRANS_MAXDQS; i++) {
0357 uint64_t blk_res_used;
0358
0359 qtrx = &qa[i];
0360
0361
0362
0363
0364 if ((dqp = qtrx->qt_dquot) == NULL)
0365 break;
0366
0367 ASSERT(XFS_DQ_IS_LOCKED(dqp));
0368
0369
0370
0371
0372
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385
0386 totalbdelta = qtrx->qt_bcount_delta +
0387 qtrx->qt_delbcnt_delta;
0388 totalrtbdelta = qtrx->qt_rtbcount_delta +
0389 qtrx->qt_delrtb_delta;
0390
0391 if (totalbdelta != 0 || totalrtbdelta != 0 ||
0392 qtrx->qt_icount_delta != 0) {
0393 trace_xfs_trans_apply_dquot_deltas_before(dqp);
0394 trace_xfs_trans_apply_dquot_deltas(qtrx);
0395 }
0396
0397 #ifdef DEBUG
0398 if (totalbdelta < 0)
0399 ASSERT(dqp->q_blk.count >= -totalbdelta);
0400
0401 if (totalrtbdelta < 0)
0402 ASSERT(dqp->q_rtb.count >= -totalrtbdelta);
0403
0404 if (qtrx->qt_icount_delta < 0)
0405 ASSERT(dqp->q_ino.count >= -qtrx->qt_icount_delta);
0406 #endif
0407 if (totalbdelta)
0408 dqp->q_blk.count += totalbdelta;
0409
0410 if (qtrx->qt_icount_delta)
0411 dqp->q_ino.count += qtrx->qt_icount_delta;
0412
0413 if (totalrtbdelta)
0414 dqp->q_rtb.count += totalrtbdelta;
0415
0416 if (totalbdelta != 0 || totalrtbdelta != 0 ||
0417 qtrx->qt_icount_delta != 0)
0418 trace_xfs_trans_apply_dquot_deltas_after(dqp);
0419
0420
0421
0422
0423
0424 if (dqp->q_id) {
0425 xfs_qm_adjust_dqlimits(dqp);
0426 xfs_qm_adjust_dqtimers(dqp);
0427 }
0428
0429 dqp->q_flags |= XFS_DQFLAG_DIRTY;
0430
0431
0432
0433 xfs_trans_log_dquot(tp, dqp);
0434
0435
0436
0437
0438
0439 blk_res_used = max_t(int64_t, 0, qtrx->qt_bcount_delta);
0440 xfs_apply_quota_reservation_deltas(&dqp->q_blk,
0441 qtrx->qt_blk_res, blk_res_used,
0442 qtrx->qt_bcount_delta);
0443
0444
0445
0446
0447 xfs_apply_quota_reservation_deltas(&dqp->q_rtb,
0448 qtrx->qt_rtblk_res,
0449 qtrx->qt_rtblk_res_used,
0450 qtrx->qt_rtbcount_delta);
0451
0452
0453
0454
0455 ASSERT(qtrx->qt_ino_res >= qtrx->qt_ino_res_used);
0456 xfs_apply_quota_reservation_deltas(&dqp->q_ino,
0457 qtrx->qt_ino_res,
0458 qtrx->qt_ino_res_used,
0459 qtrx->qt_icount_delta);
0460
0461 ASSERT(dqp->q_blk.reserved >= dqp->q_blk.count);
0462 ASSERT(dqp->q_ino.reserved >= dqp->q_ino.count);
0463 ASSERT(dqp->q_rtb.reserved >= dqp->q_rtb.count);
0464 }
0465 }
0466 }
0467
0468
0469
0470
0471
0472
0473
0474
0475 void
0476 xfs_trans_unreserve_and_mod_dquots(
0477 struct xfs_trans *tp)
0478 {
0479 int i, j;
0480 struct xfs_dquot *dqp;
0481 struct xfs_dqtrx *qtrx, *qa;
0482 bool locked;
0483
0484 if (!tp->t_dqinfo)
0485 return;
0486
0487 for (j = 0; j < XFS_QM_TRANS_DQTYPES; j++) {
0488 qa = tp->t_dqinfo->dqs[j];
0489
0490 for (i = 0; i < XFS_QM_TRANS_MAXDQS; i++) {
0491 qtrx = &qa[i];
0492
0493
0494
0495
0496 if ((dqp = qtrx->qt_dquot) == NULL)
0497 break;
0498
0499
0500
0501
0502
0503 locked = false;
0504 if (qtrx->qt_blk_res) {
0505 xfs_dqlock(dqp);
0506 locked = true;
0507 dqp->q_blk.reserved -=
0508 (xfs_qcnt_t)qtrx->qt_blk_res;
0509 }
0510 if (qtrx->qt_ino_res) {
0511 if (!locked) {
0512 xfs_dqlock(dqp);
0513 locked = true;
0514 }
0515 dqp->q_ino.reserved -=
0516 (xfs_qcnt_t)qtrx->qt_ino_res;
0517 }
0518
0519 if (qtrx->qt_rtblk_res) {
0520 if (!locked) {
0521 xfs_dqlock(dqp);
0522 locked = true;
0523 }
0524 dqp->q_rtb.reserved -=
0525 (xfs_qcnt_t)qtrx->qt_rtblk_res;
0526 }
0527 if (locked)
0528 xfs_dqunlock(dqp);
0529
0530 }
0531 }
0532 }
0533
0534 STATIC void
0535 xfs_quota_warn(
0536 struct xfs_mount *mp,
0537 struct xfs_dquot *dqp,
0538 int type)
0539 {
0540 enum quota_type qtype;
0541
0542 switch (xfs_dquot_type(dqp)) {
0543 case XFS_DQTYPE_PROJ:
0544 qtype = PRJQUOTA;
0545 break;
0546 case XFS_DQTYPE_USER:
0547 qtype = USRQUOTA;
0548 break;
0549 case XFS_DQTYPE_GROUP:
0550 qtype = GRPQUOTA;
0551 break;
0552 default:
0553 return;
0554 }
0555
0556 quota_send_warning(make_kqid(&init_user_ns, qtype, dqp->q_id),
0557 mp->m_super->s_dev, type);
0558 }
0559
0560
0561
0562
0563
0564
0565
0566
0567
0568 static inline int
0569 xfs_dqresv_check(
0570 struct xfs_dquot_res *res,
0571 struct xfs_quota_limits *qlim,
0572 int64_t delta,
0573 bool *fatal)
0574 {
0575 xfs_qcnt_t hardlimit = res->hardlimit;
0576 xfs_qcnt_t softlimit = res->softlimit;
0577 xfs_qcnt_t total_count = res->reserved + delta;
0578
0579 BUILD_BUG_ON(QUOTA_NL_BHARDWARN != QUOTA_NL_IHARDWARN + 3);
0580 BUILD_BUG_ON(QUOTA_NL_BSOFTLONGWARN != QUOTA_NL_ISOFTLONGWARN + 3);
0581 BUILD_BUG_ON(QUOTA_NL_BSOFTWARN != QUOTA_NL_ISOFTWARN + 3);
0582
0583 *fatal = false;
0584 if (delta <= 0)
0585 return QUOTA_NL_NOWARN;
0586
0587 if (!hardlimit)
0588 hardlimit = qlim->hard;
0589 if (!softlimit)
0590 softlimit = qlim->soft;
0591
0592 if (hardlimit && total_count > hardlimit) {
0593 *fatal = true;
0594 return QUOTA_NL_IHARDWARN;
0595 }
0596
0597 if (softlimit && total_count > softlimit) {
0598 time64_t now = ktime_get_real_seconds();
0599
0600 if (res->timer != 0 && now > res->timer) {
0601 *fatal = true;
0602 return QUOTA_NL_ISOFTLONGWARN;
0603 }
0604
0605 return QUOTA_NL_ISOFTWARN;
0606 }
0607
0608 return QUOTA_NL_NOWARN;
0609 }
0610
0611
0612
0613
0614
0615
0616
0617 STATIC int
0618 xfs_trans_dqresv(
0619 struct xfs_trans *tp,
0620 struct xfs_mount *mp,
0621 struct xfs_dquot *dqp,
0622 int64_t nblks,
0623 long ninos,
0624 uint flags)
0625 {
0626 struct xfs_quotainfo *q = mp->m_quotainfo;
0627 struct xfs_def_quota *defq;
0628 struct xfs_dquot_res *blkres;
0629 struct xfs_quota_limits *qlim;
0630
0631 xfs_dqlock(dqp);
0632
0633 defq = xfs_get_defquota(q, xfs_dquot_type(dqp));
0634
0635 if (flags & XFS_TRANS_DQ_RES_BLKS) {
0636 blkres = &dqp->q_blk;
0637 qlim = &defq->blk;
0638 } else {
0639 blkres = &dqp->q_rtb;
0640 qlim = &defq->rtb;
0641 }
0642
0643 if ((flags & XFS_QMOPT_FORCE_RES) == 0 && dqp->q_id &&
0644 xfs_dquot_is_enforced(dqp)) {
0645 int quota_nl;
0646 bool fatal;
0647
0648
0649
0650
0651
0652 quota_nl = xfs_dqresv_check(blkres, qlim, nblks, &fatal);
0653 if (quota_nl != QUOTA_NL_NOWARN) {
0654
0655
0656
0657
0658 xfs_quota_warn(mp, dqp, quota_nl + 3);
0659 if (fatal)
0660 goto error_return;
0661 }
0662
0663 quota_nl = xfs_dqresv_check(&dqp->q_ino, &defq->ino, ninos,
0664 &fatal);
0665 if (quota_nl != QUOTA_NL_NOWARN) {
0666 xfs_quota_warn(mp, dqp, quota_nl);
0667 if (fatal)
0668 goto error_return;
0669 }
0670 }
0671
0672
0673
0674
0675
0676 blkres->reserved += (xfs_qcnt_t)nblks;
0677 dqp->q_ino.reserved += (xfs_qcnt_t)ninos;
0678
0679
0680
0681
0682
0683
0684
0685
0686 if (tp) {
0687 ASSERT(flags & XFS_QMOPT_RESBLK_MASK);
0688 xfs_trans_mod_dquot(tp, dqp, flags & XFS_QMOPT_RESBLK_MASK,
0689 nblks);
0690 xfs_trans_mod_dquot(tp, dqp, XFS_TRANS_DQ_RES_INOS, ninos);
0691 }
0692
0693 if (XFS_IS_CORRUPT(mp, dqp->q_blk.reserved < dqp->q_blk.count) ||
0694 XFS_IS_CORRUPT(mp, dqp->q_rtb.reserved < dqp->q_rtb.count) ||
0695 XFS_IS_CORRUPT(mp, dqp->q_ino.reserved < dqp->q_ino.count))
0696 goto error_corrupt;
0697
0698 xfs_dqunlock(dqp);
0699 return 0;
0700
0701 error_return:
0702 xfs_dqunlock(dqp);
0703 if (xfs_dquot_type(dqp) == XFS_DQTYPE_PROJ)
0704 return -ENOSPC;
0705 return -EDQUOT;
0706 error_corrupt:
0707 xfs_dqunlock(dqp);
0708 xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
0709 return -EFSCORRUPTED;
0710 }
0711
0712
0713
0714
0715
0716
0717
0718
0719
0720
0721
0722
0723
0724
0725 int
0726 xfs_trans_reserve_quota_bydquots(
0727 struct xfs_trans *tp,
0728 struct xfs_mount *mp,
0729 struct xfs_dquot *udqp,
0730 struct xfs_dquot *gdqp,
0731 struct xfs_dquot *pdqp,
0732 int64_t nblks,
0733 long ninos,
0734 uint flags)
0735 {
0736 int error;
0737
0738 if (!XFS_IS_QUOTA_ON(mp))
0739 return 0;
0740
0741 ASSERT(flags & XFS_QMOPT_RESBLK_MASK);
0742
0743 if (udqp) {
0744 error = xfs_trans_dqresv(tp, mp, udqp, nblks, ninos, flags);
0745 if (error)
0746 return error;
0747 }
0748
0749 if (gdqp) {
0750 error = xfs_trans_dqresv(tp, mp, gdqp, nblks, ninos, flags);
0751 if (error)
0752 goto unwind_usr;
0753 }
0754
0755 if (pdqp) {
0756 error = xfs_trans_dqresv(tp, mp, pdqp, nblks, ninos, flags);
0757 if (error)
0758 goto unwind_grp;
0759 }
0760
0761
0762
0763
0764 return 0;
0765
0766 unwind_grp:
0767 flags |= XFS_QMOPT_FORCE_RES;
0768 if (gdqp)
0769 xfs_trans_dqresv(tp, mp, gdqp, -nblks, -ninos, flags);
0770 unwind_usr:
0771 flags |= XFS_QMOPT_FORCE_RES;
0772 if (udqp)
0773 xfs_trans_dqresv(tp, mp, udqp, -nblks, -ninos, flags);
0774 return error;
0775 }
0776
0777
0778
0779
0780
0781
0782
0783 int
0784 xfs_trans_reserve_quota_nblks(
0785 struct xfs_trans *tp,
0786 struct xfs_inode *ip,
0787 int64_t dblocks,
0788 int64_t rblocks,
0789 bool force)
0790 {
0791 struct xfs_mount *mp = ip->i_mount;
0792 unsigned int qflags = 0;
0793 int error;
0794
0795 if (!XFS_IS_QUOTA_ON(mp))
0796 return 0;
0797
0798 ASSERT(!xfs_is_quota_inode(&mp->m_sb, ip->i_ino));
0799 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
0800
0801 if (force)
0802 qflags |= XFS_QMOPT_FORCE_RES;
0803
0804
0805 error = xfs_trans_reserve_quota_bydquots(tp, mp, ip->i_udquot,
0806 ip->i_gdquot, ip->i_pdquot, dblocks, 0,
0807 XFS_QMOPT_RES_REGBLKS | qflags);
0808 if (error)
0809 return error;
0810
0811
0812 error = xfs_trans_reserve_quota_bydquots(tp, mp, ip->i_udquot,
0813 ip->i_gdquot, ip->i_pdquot, rblocks, 0,
0814 XFS_QMOPT_RES_RTBLKS | qflags);
0815 if (error) {
0816 xfs_trans_reserve_quota_bydquots(tp, mp, ip->i_udquot,
0817 ip->i_gdquot, ip->i_pdquot, -dblocks, 0,
0818 XFS_QMOPT_RES_REGBLKS);
0819 return error;
0820 }
0821
0822 return 0;
0823 }
0824
0825
0826 int
0827 xfs_trans_reserve_quota_icreate(
0828 struct xfs_trans *tp,
0829 struct xfs_dquot *udqp,
0830 struct xfs_dquot *gdqp,
0831 struct xfs_dquot *pdqp,
0832 int64_t dblocks)
0833 {
0834 struct xfs_mount *mp = tp->t_mountp;
0835
0836 if (!XFS_IS_QUOTA_ON(mp))
0837 return 0;
0838
0839 return xfs_trans_reserve_quota_bydquots(tp, mp, udqp, gdqp, pdqp,
0840 dblocks, 1, XFS_QMOPT_RES_REGBLKS);
0841 }
0842
0843 STATIC void
0844 xfs_trans_alloc_dqinfo(
0845 xfs_trans_t *tp)
0846 {
0847 tp->t_dqinfo = kmem_cache_zalloc(xfs_dqtrx_cache,
0848 GFP_KERNEL | __GFP_NOFAIL);
0849 }
0850
0851 void
0852 xfs_trans_free_dqinfo(
0853 xfs_trans_t *tp)
0854 {
0855 if (!tp->t_dqinfo)
0856 return;
0857 kmem_cache_free(xfs_dqtrx_cache, tp->t_dqinfo);
0858 tp->t_dqinfo = NULL;
0859 }