.. | .. |
---|
13 | 13 | #include "xfs_sb.h" |
---|
14 | 14 | #include "xfs_mount.h" |
---|
15 | 15 | #include "xfs_inode.h" |
---|
16 | | -#include "xfs_ialloc.h" |
---|
17 | | -#include "xfs_itable.h" |
---|
| 16 | +#include "xfs_iwalk.h" |
---|
18 | 17 | #include "xfs_quota.h" |
---|
19 | | -#include "xfs_error.h" |
---|
20 | 18 | #include "xfs_bmap.h" |
---|
21 | | -#include "xfs_bmap_btree.h" |
---|
22 | 19 | #include "xfs_bmap_util.h" |
---|
23 | 20 | #include "xfs_trans.h" |
---|
24 | 21 | #include "xfs_trans_space.h" |
---|
25 | 22 | #include "xfs_qm.h" |
---|
26 | 23 | #include "xfs_trace.h" |
---|
27 | 24 | #include "xfs_icache.h" |
---|
28 | | -#include "xfs_cksum.h" |
---|
| 25 | +#include "xfs_error.h" |
---|
29 | 26 | |
---|
30 | 27 | /* |
---|
31 | 28 | * The global quota manager. There is only one of these for the entire |
---|
.. | .. |
---|
33 | 30 | * quota functionality, including maintaining the freelist and hash |
---|
34 | 31 | * tables of dquots. |
---|
35 | 32 | */ |
---|
36 | | -STATIC int xfs_qm_init_quotainos(xfs_mount_t *); |
---|
37 | | -STATIC int xfs_qm_init_quotainfo(xfs_mount_t *); |
---|
| 33 | +STATIC int xfs_qm_init_quotainos(struct xfs_mount *mp); |
---|
| 34 | +STATIC int xfs_qm_init_quotainfo(struct xfs_mount *mp); |
---|
38 | 35 | |
---|
39 | | -STATIC void xfs_qm_destroy_quotainos(xfs_quotainfo_t *qi); |
---|
| 36 | +STATIC void xfs_qm_destroy_quotainos(struct xfs_quotainfo *qi); |
---|
40 | 37 | STATIC void xfs_qm_dqfree_one(struct xfs_dquot *dqp); |
---|
41 | 38 | /* |
---|
42 | 39 | * We use the batch lookup interface to iterate over the dquots as it |
---|
.. | .. |
---|
50 | 47 | STATIC int |
---|
51 | 48 | xfs_qm_dquot_walk( |
---|
52 | 49 | struct xfs_mount *mp, |
---|
53 | | - int type, |
---|
| 50 | + xfs_dqtype_t type, |
---|
54 | 51 | int (*execute)(struct xfs_dquot *dqp, void *data), |
---|
55 | 52 | void *data) |
---|
56 | 53 | { |
---|
.. | .. |
---|
82 | 79 | for (i = 0; i < nr_found; i++) { |
---|
83 | 80 | struct xfs_dquot *dqp = batch[i]; |
---|
84 | 81 | |
---|
85 | | - next_index = be32_to_cpu(dqp->q_core.d_id) + 1; |
---|
| 82 | + next_index = dqp->q_id + 1; |
---|
86 | 83 | |
---|
87 | 84 | error = execute(batch[i], data); |
---|
88 | 85 | if (error == -EAGAIN) { |
---|
.. | .. |
---|
124 | 121 | { |
---|
125 | 122 | struct xfs_mount *mp = dqp->q_mount; |
---|
126 | 123 | struct xfs_quotainfo *qi = mp->m_quotainfo; |
---|
| 124 | + int error = -EAGAIN; |
---|
127 | 125 | |
---|
128 | 126 | xfs_dqlock(dqp); |
---|
129 | | - if ((dqp->dq_flags & XFS_DQ_FREEING) || dqp->q_nrefs != 0) { |
---|
130 | | - xfs_dqunlock(dqp); |
---|
131 | | - return -EAGAIN; |
---|
132 | | - } |
---|
| 127 | + if ((dqp->q_flags & XFS_DQFLAG_FREEING) || dqp->q_nrefs != 0) |
---|
| 128 | + goto out_unlock; |
---|
133 | 129 | |
---|
134 | | - dqp->dq_flags |= XFS_DQ_FREEING; |
---|
| 130 | + dqp->q_flags |= XFS_DQFLAG_FREEING; |
---|
135 | 131 | |
---|
136 | 132 | xfs_dqflock(dqp); |
---|
137 | 133 | |
---|
.. | .. |
---|
142 | 138 | */ |
---|
143 | 139 | if (XFS_DQ_IS_DIRTY(dqp)) { |
---|
144 | 140 | struct xfs_buf *bp = NULL; |
---|
145 | | - int error; |
---|
146 | 141 | |
---|
147 | 142 | /* |
---|
148 | 143 | * We don't care about getting disk errors here. We need |
---|
.. | .. |
---|
152 | 147 | if (!error) { |
---|
153 | 148 | error = xfs_bwrite(bp); |
---|
154 | 149 | xfs_buf_relse(bp); |
---|
| 150 | + } else if (error == -EAGAIN) { |
---|
| 151 | + dqp->q_flags &= ~XFS_DQFLAG_FREEING; |
---|
| 152 | + goto out_unlock; |
---|
155 | 153 | } |
---|
156 | 154 | xfs_dqflock(dqp); |
---|
157 | 155 | } |
---|
.. | .. |
---|
163 | 161 | xfs_dqfunlock(dqp); |
---|
164 | 162 | xfs_dqunlock(dqp); |
---|
165 | 163 | |
---|
166 | | - radix_tree_delete(xfs_dquot_tree(qi, dqp->q_core.d_flags), |
---|
167 | | - be32_to_cpu(dqp->q_core.d_id)); |
---|
| 164 | + radix_tree_delete(xfs_dquot_tree(qi, xfs_dquot_type(dqp)), dqp->q_id); |
---|
168 | 165 | qi->qi_dquots--; |
---|
169 | 166 | |
---|
170 | 167 | /* |
---|
.. | .. |
---|
177 | 174 | |
---|
178 | 175 | xfs_qm_dqdestroy(dqp); |
---|
179 | 176 | return 0; |
---|
| 177 | + |
---|
| 178 | +out_unlock: |
---|
| 179 | + xfs_dqunlock(dqp); |
---|
| 180 | + return error; |
---|
180 | 181 | } |
---|
181 | 182 | |
---|
182 | 183 | /* |
---|
.. | .. |
---|
188 | 189 | uint flags) |
---|
189 | 190 | { |
---|
190 | 191 | if (flags & XFS_QMOPT_UQUOTA) |
---|
191 | | - xfs_qm_dquot_walk(mp, XFS_DQ_USER, xfs_qm_dqpurge, NULL); |
---|
| 192 | + xfs_qm_dquot_walk(mp, XFS_DQTYPE_USER, xfs_qm_dqpurge, NULL); |
---|
192 | 193 | if (flags & XFS_QMOPT_GQUOTA) |
---|
193 | | - xfs_qm_dquot_walk(mp, XFS_DQ_GROUP, xfs_qm_dqpurge, NULL); |
---|
| 194 | + xfs_qm_dquot_walk(mp, XFS_DQTYPE_GROUP, xfs_qm_dqpurge, NULL); |
---|
194 | 195 | if (flags & XFS_QMOPT_PQUOTA) |
---|
195 | | - xfs_qm_dquot_walk(mp, XFS_DQ_PROJ, xfs_qm_dqpurge, NULL); |
---|
| 196 | + xfs_qm_dquot_walk(mp, XFS_DQTYPE_PROJ, xfs_qm_dqpurge, NULL); |
---|
196 | 197 | } |
---|
197 | 198 | |
---|
198 | 199 | /* |
---|
.. | .. |
---|
247 | 248 | |
---|
248 | 249 | STATIC int |
---|
249 | 250 | xfs_qm_dqattach_one( |
---|
250 | | - xfs_inode_t *ip, |
---|
251 | | - xfs_dqid_t id, |
---|
252 | | - uint type, |
---|
253 | | - bool doalloc, |
---|
254 | | - xfs_dquot_t **IO_idqpp) |
---|
| 251 | + struct xfs_inode *ip, |
---|
| 252 | + xfs_dqtype_t type, |
---|
| 253 | + bool doalloc, |
---|
| 254 | + struct xfs_dquot **IO_idqpp) |
---|
255 | 255 | { |
---|
256 | | - xfs_dquot_t *dqp; |
---|
257 | | - int error; |
---|
| 256 | + struct xfs_dquot *dqp; |
---|
| 257 | + int error; |
---|
258 | 258 | |
---|
259 | 259 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); |
---|
260 | 260 | error = 0; |
---|
.. | .. |
---|
329 | 329 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); |
---|
330 | 330 | |
---|
331 | 331 | if (XFS_IS_UQUOTA_ON(mp) && !ip->i_udquot) { |
---|
332 | | - error = xfs_qm_dqattach_one(ip, ip->i_d.di_uid, XFS_DQ_USER, |
---|
| 332 | + error = xfs_qm_dqattach_one(ip, XFS_DQTYPE_USER, |
---|
333 | 333 | doalloc, &ip->i_udquot); |
---|
334 | 334 | if (error) |
---|
335 | 335 | goto done; |
---|
.. | .. |
---|
337 | 337 | } |
---|
338 | 338 | |
---|
339 | 339 | if (XFS_IS_GQUOTA_ON(mp) && !ip->i_gdquot) { |
---|
340 | | - error = xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP, |
---|
| 340 | + error = xfs_qm_dqattach_one(ip, XFS_DQTYPE_GROUP, |
---|
341 | 341 | doalloc, &ip->i_gdquot); |
---|
342 | 342 | if (error) |
---|
343 | 343 | goto done; |
---|
.. | .. |
---|
345 | 345 | } |
---|
346 | 346 | |
---|
347 | 347 | if (XFS_IS_PQUOTA_ON(mp) && !ip->i_pdquot) { |
---|
348 | | - error = xfs_qm_dqattach_one(ip, xfs_get_projid(ip), XFS_DQ_PROJ, |
---|
| 348 | + error = xfs_qm_dqattach_one(ip, XFS_DQTYPE_PROJ, |
---|
349 | 349 | doalloc, &ip->i_pdquot); |
---|
350 | 350 | if (error) |
---|
351 | 351 | goto done; |
---|
.. | .. |
---|
472 | 472 | /* |
---|
473 | 473 | * Prevent lookups now that we are past the point of no return. |
---|
474 | 474 | */ |
---|
475 | | - dqp->dq_flags |= XFS_DQ_FREEING; |
---|
| 475 | + dqp->q_flags |= XFS_DQFLAG_FREEING; |
---|
476 | 476 | xfs_dqunlock(dqp); |
---|
477 | 477 | |
---|
478 | 478 | ASSERT(dqp->q_nrefs == 0); |
---|
.. | .. |
---|
543 | 543 | |
---|
544 | 544 | STATIC void |
---|
545 | 545 | xfs_qm_set_defquota( |
---|
546 | | - xfs_mount_t *mp, |
---|
547 | | - uint type, |
---|
548 | | - xfs_quotainfo_t *qinf) |
---|
| 546 | + struct xfs_mount *mp, |
---|
| 547 | + xfs_dqtype_t type, |
---|
| 548 | + struct xfs_quotainfo *qinf) |
---|
549 | 549 | { |
---|
550 | | - xfs_dquot_t *dqp; |
---|
551 | | - struct xfs_def_quota *defq; |
---|
552 | | - struct xfs_disk_dquot *ddqp; |
---|
| 550 | + struct xfs_dquot *dqp; |
---|
| 551 | + struct xfs_def_quota *defq; |
---|
553 | 552 | int error; |
---|
554 | 553 | |
---|
555 | 554 | error = xfs_qm_dqget_uncached(mp, 0, type, &dqp); |
---|
556 | 555 | if (error) |
---|
557 | 556 | return; |
---|
558 | 557 | |
---|
559 | | - ddqp = &dqp->q_core; |
---|
560 | | - defq = xfs_get_defquota(dqp, qinf); |
---|
| 558 | + defq = xfs_get_defquota(qinf, xfs_dquot_type(dqp)); |
---|
561 | 559 | |
---|
562 | 560 | /* |
---|
563 | 561 | * Timers and warnings have been already set, let's just set the |
---|
564 | 562 | * default limits for this quota type |
---|
565 | 563 | */ |
---|
566 | | - defq->bhardlimit = be64_to_cpu(ddqp->d_blk_hardlimit); |
---|
567 | | - defq->bsoftlimit = be64_to_cpu(ddqp->d_blk_softlimit); |
---|
568 | | - defq->ihardlimit = be64_to_cpu(ddqp->d_ino_hardlimit); |
---|
569 | | - defq->isoftlimit = be64_to_cpu(ddqp->d_ino_softlimit); |
---|
570 | | - defq->rtbhardlimit = be64_to_cpu(ddqp->d_rtb_hardlimit); |
---|
571 | | - defq->rtbsoftlimit = be64_to_cpu(ddqp->d_rtb_softlimit); |
---|
| 564 | + defq->blk.hard = dqp->q_blk.hardlimit; |
---|
| 565 | + defq->blk.soft = dqp->q_blk.softlimit; |
---|
| 566 | + defq->ino.hard = dqp->q_ino.hardlimit; |
---|
| 567 | + defq->ino.soft = dqp->q_ino.softlimit; |
---|
| 568 | + defq->rtb.hard = dqp->q_rtb.hardlimit; |
---|
| 569 | + defq->rtb.soft = dqp->q_rtb.softlimit; |
---|
572 | 570 | xfs_qm_dqdestroy(dqp); |
---|
573 | 571 | } |
---|
574 | 572 | |
---|
.. | .. |
---|
576 | 574 | static void |
---|
577 | 575 | xfs_qm_init_timelimits( |
---|
578 | 576 | struct xfs_mount *mp, |
---|
579 | | - struct xfs_quotainfo *qinf) |
---|
| 577 | + xfs_dqtype_t type) |
---|
580 | 578 | { |
---|
581 | | - struct xfs_disk_dquot *ddqp; |
---|
| 579 | + struct xfs_quotainfo *qinf = mp->m_quotainfo; |
---|
| 580 | + struct xfs_def_quota *defq; |
---|
582 | 581 | struct xfs_dquot *dqp; |
---|
583 | | - uint type; |
---|
584 | 582 | int error; |
---|
585 | 583 | |
---|
586 | | - qinf->qi_btimelimit = XFS_QM_BTIMELIMIT; |
---|
587 | | - qinf->qi_itimelimit = XFS_QM_ITIMELIMIT; |
---|
588 | | - qinf->qi_rtbtimelimit = XFS_QM_RTBTIMELIMIT; |
---|
589 | | - qinf->qi_bwarnlimit = XFS_QM_BWARNLIMIT; |
---|
590 | | - qinf->qi_iwarnlimit = XFS_QM_IWARNLIMIT; |
---|
591 | | - qinf->qi_rtbwarnlimit = XFS_QM_RTBWARNLIMIT; |
---|
| 584 | + defq = xfs_get_defquota(qinf, type); |
---|
| 585 | + |
---|
| 586 | + defq->blk.time = XFS_QM_BTIMELIMIT; |
---|
| 587 | + defq->ino.time = XFS_QM_ITIMELIMIT; |
---|
| 588 | + defq->rtb.time = XFS_QM_RTBTIMELIMIT; |
---|
| 589 | + defq->blk.warn = XFS_QM_BWARNLIMIT; |
---|
| 590 | + defq->ino.warn = XFS_QM_IWARNLIMIT; |
---|
| 591 | + defq->rtb.warn = XFS_QM_RTBWARNLIMIT; |
---|
592 | 592 | |
---|
593 | 593 | /* |
---|
594 | 594 | * We try to get the limits from the superuser's limits fields. |
---|
.. | .. |
---|
596 | 596 | * |
---|
597 | 597 | * Since we may not have done a quotacheck by this point, just read |
---|
598 | 598 | * the dquot without attaching it to any hashtables or lists. |
---|
599 | | - * |
---|
600 | | - * Timers and warnings are globally set by the first timer found in |
---|
601 | | - * user/group/proj quota types, otherwise a default value is used. |
---|
602 | | - * This should be split into different fields per quota type. |
---|
603 | 599 | */ |
---|
604 | | - if (XFS_IS_UQUOTA_RUNNING(mp)) |
---|
605 | | - type = XFS_DQ_USER; |
---|
606 | | - else if (XFS_IS_GQUOTA_RUNNING(mp)) |
---|
607 | | - type = XFS_DQ_GROUP; |
---|
608 | | - else |
---|
609 | | - type = XFS_DQ_PROJ; |
---|
610 | 600 | error = xfs_qm_dqget_uncached(mp, 0, type, &dqp); |
---|
611 | 601 | if (error) |
---|
612 | 602 | return; |
---|
613 | 603 | |
---|
614 | | - ddqp = &dqp->q_core; |
---|
615 | 604 | /* |
---|
616 | 605 | * The warnings and timers set the grace period given to |
---|
617 | 606 | * a user or group before he or she can not perform any |
---|
618 | 607 | * more writing. If it is zero, a default is used. |
---|
619 | 608 | */ |
---|
620 | | - if (ddqp->d_btimer) |
---|
621 | | - qinf->qi_btimelimit = be32_to_cpu(ddqp->d_btimer); |
---|
622 | | - if (ddqp->d_itimer) |
---|
623 | | - qinf->qi_itimelimit = be32_to_cpu(ddqp->d_itimer); |
---|
624 | | - if (ddqp->d_rtbtimer) |
---|
625 | | - qinf->qi_rtbtimelimit = be32_to_cpu(ddqp->d_rtbtimer); |
---|
626 | | - if (ddqp->d_bwarns) |
---|
627 | | - qinf->qi_bwarnlimit = be16_to_cpu(ddqp->d_bwarns); |
---|
628 | | - if (ddqp->d_iwarns) |
---|
629 | | - qinf->qi_iwarnlimit = be16_to_cpu(ddqp->d_iwarns); |
---|
630 | | - if (ddqp->d_rtbwarns) |
---|
631 | | - qinf->qi_rtbwarnlimit = be16_to_cpu(ddqp->d_rtbwarns); |
---|
| 609 | + if (dqp->q_blk.timer) |
---|
| 610 | + defq->blk.time = dqp->q_blk.timer; |
---|
| 611 | + if (dqp->q_ino.timer) |
---|
| 612 | + defq->ino.time = dqp->q_ino.timer; |
---|
| 613 | + if (dqp->q_rtb.timer) |
---|
| 614 | + defq->rtb.time = dqp->q_rtb.timer; |
---|
| 615 | + if (dqp->q_blk.warnings) |
---|
| 616 | + defq->blk.warn = dqp->q_blk.warnings; |
---|
| 617 | + if (dqp->q_ino.warnings) |
---|
| 618 | + defq->ino.warn = dqp->q_ino.warnings; |
---|
| 619 | + if (dqp->q_rtb.warnings) |
---|
| 620 | + defq->rtb.warn = dqp->q_rtb.warnings; |
---|
632 | 621 | |
---|
633 | 622 | xfs_qm_dqdestroy(dqp); |
---|
634 | 623 | } |
---|
.. | .. |
---|
646 | 635 | |
---|
647 | 636 | ASSERT(XFS_IS_QUOTA_RUNNING(mp)); |
---|
648 | 637 | |
---|
649 | | - qinf = mp->m_quotainfo = kmem_zalloc(sizeof(xfs_quotainfo_t), KM_SLEEP); |
---|
| 638 | + qinf = mp->m_quotainfo = kmem_zalloc(sizeof(struct xfs_quotainfo), 0); |
---|
650 | 639 | |
---|
651 | 640 | error = list_lru_init(&qinf->qi_lru); |
---|
652 | 641 | if (error) |
---|
.. | .. |
---|
671 | 660 | /* Precalc some constants */ |
---|
672 | 661 | qinf->qi_dqchunklen = XFS_FSB_TO_BB(mp, XFS_DQUOT_CLUSTER_SIZE_FSB); |
---|
673 | 662 | qinf->qi_dqperchunk = xfs_calc_dquots_per_chunk(qinf->qi_dqchunklen); |
---|
| 663 | + if (xfs_sb_version_hasbigtime(&mp->m_sb)) { |
---|
| 664 | + qinf->qi_expiry_min = |
---|
| 665 | + xfs_dq_bigtime_to_unix(XFS_DQ_BIGTIME_EXPIRY_MIN); |
---|
| 666 | + qinf->qi_expiry_max = |
---|
| 667 | + xfs_dq_bigtime_to_unix(XFS_DQ_BIGTIME_EXPIRY_MAX); |
---|
| 668 | + } else { |
---|
| 669 | + qinf->qi_expiry_min = XFS_DQ_LEGACY_EXPIRY_MIN; |
---|
| 670 | + qinf->qi_expiry_max = XFS_DQ_LEGACY_EXPIRY_MAX; |
---|
| 671 | + } |
---|
| 672 | + trace_xfs_quota_expiry_range(mp, qinf->qi_expiry_min, |
---|
| 673 | + qinf->qi_expiry_max); |
---|
674 | 674 | |
---|
675 | 675 | mp->m_qflags |= (mp->m_sb.sb_qflags & XFS_ALL_QUOTA_CHKD); |
---|
676 | 676 | |
---|
677 | | - xfs_qm_init_timelimits(mp, qinf); |
---|
| 677 | + xfs_qm_init_timelimits(mp, XFS_DQTYPE_USER); |
---|
| 678 | + xfs_qm_init_timelimits(mp, XFS_DQTYPE_GROUP); |
---|
| 679 | + xfs_qm_init_timelimits(mp, XFS_DQTYPE_PROJ); |
---|
678 | 680 | |
---|
679 | 681 | if (XFS_IS_UQUOTA_RUNNING(mp)) |
---|
680 | | - xfs_qm_set_defquota(mp, XFS_DQ_USER, qinf); |
---|
| 682 | + xfs_qm_set_defquota(mp, XFS_DQTYPE_USER, qinf); |
---|
681 | 683 | if (XFS_IS_GQUOTA_RUNNING(mp)) |
---|
682 | | - xfs_qm_set_defquota(mp, XFS_DQ_GROUP, qinf); |
---|
| 684 | + xfs_qm_set_defquota(mp, XFS_DQTYPE_GROUP, qinf); |
---|
683 | 685 | if (XFS_IS_PQUOTA_RUNNING(mp)) |
---|
684 | | - xfs_qm_set_defquota(mp, XFS_DQ_PROJ, qinf); |
---|
| 686 | + xfs_qm_set_defquota(mp, XFS_DQTYPE_PROJ, qinf); |
---|
685 | 687 | |
---|
686 | 688 | qinf->qi_shrinker.count_objects = xfs_qm_shrink_count; |
---|
687 | 689 | qinf->qi_shrinker.scan_objects = xfs_qm_shrink_scan; |
---|
.. | .. |
---|
713 | 715 | */ |
---|
714 | 716 | void |
---|
715 | 717 | xfs_qm_destroy_quotainfo( |
---|
716 | | - xfs_mount_t *mp) |
---|
| 718 | + struct xfs_mount *mp) |
---|
717 | 719 | { |
---|
718 | | - xfs_quotainfo_t *qi; |
---|
| 720 | + struct xfs_quotainfo *qi; |
---|
719 | 721 | |
---|
720 | 722 | qi = mp->m_quotainfo; |
---|
721 | 723 | ASSERT(qi != NULL); |
---|
.. | .. |
---|
758 | 760 | if ((flags & XFS_QMOPT_PQUOTA) && |
---|
759 | 761 | (mp->m_sb.sb_gquotino != NULLFSINO)) { |
---|
760 | 762 | ino = mp->m_sb.sb_gquotino; |
---|
761 | | - ASSERT(mp->m_sb.sb_pquotino == NULLFSINO); |
---|
| 763 | + if (XFS_IS_CORRUPT(mp, |
---|
| 764 | + mp->m_sb.sb_pquotino != NULLFSINO)) |
---|
| 765 | + return -EFSCORRUPTED; |
---|
762 | 766 | } else if ((flags & XFS_QMOPT_GQUOTA) && |
---|
763 | 767 | (mp->m_sb.sb_pquotino != NULLFSINO)) { |
---|
764 | 768 | ino = mp->m_sb.sb_pquotino; |
---|
765 | | - ASSERT(mp->m_sb.sb_gquotino == NULLFSINO); |
---|
| 769 | + if (XFS_IS_CORRUPT(mp, |
---|
| 770 | + mp->m_sb.sb_gquotino != NULLFSINO)) |
---|
| 771 | + return -EFSCORRUPTED; |
---|
766 | 772 | } |
---|
767 | 773 | if (ino != NULLFSINO) { |
---|
768 | 774 | error = xfs_iget(mp, NULL, ino, 0, 0, ip); |
---|
.. | .. |
---|
775 | 781 | } |
---|
776 | 782 | |
---|
777 | 783 | error = xfs_trans_alloc(mp, &M_RES(mp)->tr_create, |
---|
778 | | - XFS_QM_QINOCREATE_SPACE_RES(mp), 0, 0, &tp); |
---|
| 784 | + need_alloc ? XFS_QM_QINOCREATE_SPACE_RES(mp) : 0, |
---|
| 785 | + 0, 0, &tp); |
---|
779 | 786 | if (error) |
---|
780 | 787 | return error; |
---|
781 | 788 | |
---|
.. | .. |
---|
826 | 833 | |
---|
827 | 834 | STATIC void |
---|
828 | 835 | xfs_qm_reset_dqcounts( |
---|
829 | | - xfs_mount_t *mp, |
---|
830 | | - xfs_buf_t *bp, |
---|
831 | | - xfs_dqid_t id, |
---|
832 | | - uint type) |
---|
| 836 | + struct xfs_mount *mp, |
---|
| 837 | + struct xfs_buf *bp, |
---|
| 838 | + xfs_dqid_t id, |
---|
| 839 | + xfs_dqtype_t type) |
---|
833 | 840 | { |
---|
834 | 841 | struct xfs_dqblk *dqb; |
---|
835 | 842 | int j; |
---|
836 | | - xfs_failaddr_t fa; |
---|
837 | 843 | |
---|
838 | 844 | trace_xfs_reset_dqcounts(bp, _RET_IP_); |
---|
839 | 845 | |
---|
.. | .. |
---|
858 | 864 | * find uninitialised dquot blks. See comment in |
---|
859 | 865 | * xfs_dquot_verify. |
---|
860 | 866 | */ |
---|
861 | | - fa = xfs_dqblk_verify(mp, &dqb[j], id + j, type); |
---|
862 | | - if (fa) |
---|
| 867 | + if (xfs_dqblk_verify(mp, &dqb[j], id + j) || |
---|
| 868 | + (dqb[j].dd_diskdq.d_type & XFS_DQTYPE_REC_MASK) != type) |
---|
863 | 869 | xfs_dqblk_repair(mp, &dqb[j], id + j, type); |
---|
864 | 870 | |
---|
865 | 871 | /* |
---|
866 | 872 | * Reset type in case we are reusing group quota file for |
---|
867 | 873 | * project quotas or vice versa |
---|
868 | 874 | */ |
---|
869 | | - ddq->d_flags = type; |
---|
| 875 | + ddq->d_type = type; |
---|
870 | 876 | ddq->d_bcount = 0; |
---|
871 | 877 | ddq->d_icount = 0; |
---|
872 | 878 | ddq->d_rtbcount = 0; |
---|
873 | | - ddq->d_btimer = 0; |
---|
874 | | - ddq->d_itimer = 0; |
---|
875 | | - ddq->d_rtbtimer = 0; |
---|
876 | | - ddq->d_bwarns = 0; |
---|
877 | | - ddq->d_iwarns = 0; |
---|
878 | | - ddq->d_rtbwarns = 0; |
---|
| 879 | + |
---|
| 880 | + /* |
---|
| 881 | + * dquot id 0 stores the default grace period and the maximum |
---|
| 882 | + * warning limit that were set by the administrator, so we |
---|
| 883 | + * should not reset them. |
---|
| 884 | + */ |
---|
| 885 | + if (ddq->d_id != 0) { |
---|
| 886 | + ddq->d_btimer = 0; |
---|
| 887 | + ddq->d_itimer = 0; |
---|
| 888 | + ddq->d_rtbtimer = 0; |
---|
| 889 | + ddq->d_bwarns = 0; |
---|
| 890 | + ddq->d_iwarns = 0; |
---|
| 891 | + ddq->d_rtbwarns = 0; |
---|
| 892 | + if (xfs_sb_version_hasbigtime(&mp->m_sb)) |
---|
| 893 | + ddq->d_type |= XFS_DQTYPE_BIGTIME; |
---|
| 894 | + } |
---|
879 | 895 | |
---|
880 | 896 | if (xfs_sb_version_hascrc(&mp->m_sb)) { |
---|
881 | 897 | xfs_update_cksum((char *)&dqb[j], |
---|
.. | .. |
---|
891 | 907 | xfs_dqid_t firstid, |
---|
892 | 908 | xfs_fsblock_t bno, |
---|
893 | 909 | xfs_filblks_t blkcnt, |
---|
894 | | - uint flags, |
---|
| 910 | + xfs_dqtype_t type, |
---|
895 | 911 | struct list_head *buffer_list) |
---|
896 | 912 | { |
---|
897 | 913 | struct xfs_buf *bp; |
---|
898 | | - int error; |
---|
899 | | - int type; |
---|
| 914 | + int error = 0; |
---|
900 | 915 | |
---|
901 | 916 | ASSERT(blkcnt > 0); |
---|
902 | | - type = flags & XFS_QMOPT_UQUOTA ? XFS_DQ_USER : |
---|
903 | | - (flags & XFS_QMOPT_PQUOTA ? XFS_DQ_PROJ : XFS_DQ_GROUP); |
---|
904 | | - error = 0; |
---|
905 | 917 | |
---|
906 | 918 | /* |
---|
907 | 919 | * Blkcnt arg can be a very big number, and might even be |
---|
.. | .. |
---|
961 | 973 | xfs_qm_reset_dqcounts_buf( |
---|
962 | 974 | struct xfs_mount *mp, |
---|
963 | 975 | struct xfs_inode *qip, |
---|
964 | | - uint flags, |
---|
| 976 | + xfs_dqtype_t type, |
---|
965 | 977 | struct list_head *buffer_list) |
---|
966 | 978 | { |
---|
967 | 979 | struct xfs_bmbt_irec *map; |
---|
.. | .. |
---|
982 | 994 | if (qip->i_d.di_nblocks == 0) |
---|
983 | 995 | return 0; |
---|
984 | 996 | |
---|
985 | | - map = kmem_alloc(XFS_DQITER_MAP_SIZE * sizeof(*map), KM_SLEEP); |
---|
| 997 | + map = kmem_alloc(XFS_DQITER_MAP_SIZE * sizeof(*map), 0); |
---|
986 | 998 | |
---|
987 | 999 | lblkno = 0; |
---|
988 | 1000 | maxlblkcnt = XFS_B_TO_FSB(mp, mp->m_super->s_maxbytes); |
---|
.. | .. |
---|
1037 | 1049 | error = xfs_qm_reset_dqcounts_all(mp, firstid, |
---|
1038 | 1050 | map[i].br_startblock, |
---|
1039 | 1051 | map[i].br_blockcount, |
---|
1040 | | - flags, buffer_list); |
---|
| 1052 | + type, buffer_list); |
---|
1041 | 1053 | if (error) |
---|
1042 | 1054 | goto out; |
---|
1043 | 1055 | } |
---|
.. | .. |
---|
1059 | 1071 | STATIC int |
---|
1060 | 1072 | xfs_qm_quotacheck_dqadjust( |
---|
1061 | 1073 | struct xfs_inode *ip, |
---|
1062 | | - uint type, |
---|
| 1074 | + xfs_dqtype_t type, |
---|
1063 | 1075 | xfs_qcnt_t nblks, |
---|
1064 | 1076 | xfs_qcnt_t rtblks) |
---|
1065 | 1077 | { |
---|
.. | .. |
---|
1085 | 1097 | * Adjust the inode count and the block count to reflect this inode's |
---|
1086 | 1098 | * resource usage. |
---|
1087 | 1099 | */ |
---|
1088 | | - be64_add_cpu(&dqp->q_core.d_icount, 1); |
---|
1089 | | - dqp->q_res_icount++; |
---|
| 1100 | + dqp->q_ino.count++; |
---|
| 1101 | + dqp->q_ino.reserved++; |
---|
1090 | 1102 | if (nblks) { |
---|
1091 | | - be64_add_cpu(&dqp->q_core.d_bcount, nblks); |
---|
1092 | | - dqp->q_res_bcount += nblks; |
---|
| 1103 | + dqp->q_blk.count += nblks; |
---|
| 1104 | + dqp->q_blk.reserved += nblks; |
---|
1093 | 1105 | } |
---|
1094 | 1106 | if (rtblks) { |
---|
1095 | | - be64_add_cpu(&dqp->q_core.d_rtbcount, rtblks); |
---|
1096 | | - dqp->q_res_rtbcount += rtblks; |
---|
| 1107 | + dqp->q_rtb.count += rtblks; |
---|
| 1108 | + dqp->q_rtb.reserved += rtblks; |
---|
1097 | 1109 | } |
---|
1098 | 1110 | |
---|
1099 | 1111 | /* |
---|
.. | .. |
---|
1101 | 1113 | * |
---|
1102 | 1114 | * There are no timers for the default values set in the root dquot. |
---|
1103 | 1115 | */ |
---|
1104 | | - if (dqp->q_core.d_id) { |
---|
1105 | | - xfs_qm_adjust_dqlimits(mp, dqp); |
---|
1106 | | - xfs_qm_adjust_dqtimers(mp, &dqp->q_core); |
---|
| 1116 | + if (dqp->q_id) { |
---|
| 1117 | + xfs_qm_adjust_dqlimits(dqp); |
---|
| 1118 | + xfs_qm_adjust_dqtimers(dqp); |
---|
1107 | 1119 | } |
---|
1108 | 1120 | |
---|
1109 | | - dqp->dq_flags |= XFS_DQ_DIRTY; |
---|
| 1121 | + dqp->q_flags |= XFS_DQFLAG_DIRTY; |
---|
1110 | 1122 | xfs_qm_dqput(dqp); |
---|
1111 | 1123 | return 0; |
---|
1112 | 1124 | } |
---|
.. | .. |
---|
1118 | 1130 | /* ARGSUSED */ |
---|
1119 | 1131 | STATIC int |
---|
1120 | 1132 | xfs_qm_dqusage_adjust( |
---|
1121 | | - xfs_mount_t *mp, /* mount point for filesystem */ |
---|
1122 | | - xfs_ino_t ino, /* inode number to get data for */ |
---|
1123 | | - void __user *buffer, /* not used */ |
---|
1124 | | - int ubsize, /* not used */ |
---|
1125 | | - int *ubused, /* not used */ |
---|
1126 | | - int *res) /* result code value */ |
---|
| 1133 | + struct xfs_mount *mp, |
---|
| 1134 | + struct xfs_trans *tp, |
---|
| 1135 | + xfs_ino_t ino, |
---|
| 1136 | + void *data) |
---|
1127 | 1137 | { |
---|
1128 | | - xfs_inode_t *ip; |
---|
1129 | | - xfs_qcnt_t nblks; |
---|
1130 | | - xfs_filblks_t rtblks = 0; /* total rt blks */ |
---|
1131 | | - int error; |
---|
| 1138 | + struct xfs_inode *ip; |
---|
| 1139 | + xfs_qcnt_t nblks; |
---|
| 1140 | + xfs_filblks_t rtblks = 0; /* total rt blks */ |
---|
| 1141 | + int error; |
---|
1132 | 1142 | |
---|
1133 | 1143 | ASSERT(XFS_IS_QUOTA_RUNNING(mp)); |
---|
1134 | 1144 | |
---|
.. | .. |
---|
1136 | 1146 | * rootino must have its resources accounted for, not so with the quota |
---|
1137 | 1147 | * inodes. |
---|
1138 | 1148 | */ |
---|
1139 | | - if (xfs_is_quota_inode(&mp->m_sb, ino)) { |
---|
1140 | | - *res = BULKSTAT_RV_NOTHING; |
---|
1141 | | - return -EINVAL; |
---|
1142 | | - } |
---|
| 1149 | + if (xfs_is_quota_inode(&mp->m_sb, ino)) |
---|
| 1150 | + return 0; |
---|
1143 | 1151 | |
---|
1144 | 1152 | /* |
---|
1145 | 1153 | * We don't _need_ to take the ilock EXCL here because quotacheck runs |
---|
1146 | 1154 | * at mount time and therefore nobody will be racing chown/chproj. |
---|
1147 | 1155 | */ |
---|
1148 | | - error = xfs_iget(mp, NULL, ino, XFS_IGET_DONTCACHE, 0, &ip); |
---|
1149 | | - if (error) { |
---|
1150 | | - *res = BULKSTAT_RV_NOTHING; |
---|
| 1156 | + error = xfs_iget(mp, tp, ino, XFS_IGET_DONTCACHE, 0, &ip); |
---|
| 1157 | + if (error == -EINVAL || error == -ENOENT) |
---|
| 1158 | + return 0; |
---|
| 1159 | + if (error) |
---|
1151 | 1160 | return error; |
---|
1152 | | - } |
---|
1153 | 1161 | |
---|
1154 | 1162 | ASSERT(ip->i_delayed_blks == 0); |
---|
1155 | 1163 | |
---|
.. | .. |
---|
1157 | 1165 | struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK); |
---|
1158 | 1166 | |
---|
1159 | 1167 | if (!(ifp->if_flags & XFS_IFEXTENTS)) { |
---|
1160 | | - error = xfs_iread_extents(NULL, ip, XFS_DATA_FORK); |
---|
| 1168 | + error = xfs_iread_extents(tp, ip, XFS_DATA_FORK); |
---|
1161 | 1169 | if (error) |
---|
1162 | 1170 | goto error0; |
---|
1163 | 1171 | } |
---|
.. | .. |
---|
1180 | 1188 | * and quotaoffs don't race. (Quotachecks happen at mount time only). |
---|
1181 | 1189 | */ |
---|
1182 | 1190 | if (XFS_IS_UQUOTA_ON(mp)) { |
---|
1183 | | - error = xfs_qm_quotacheck_dqadjust(ip, XFS_DQ_USER, nblks, |
---|
| 1191 | + error = xfs_qm_quotacheck_dqadjust(ip, XFS_DQTYPE_USER, nblks, |
---|
1184 | 1192 | rtblks); |
---|
1185 | 1193 | if (error) |
---|
1186 | 1194 | goto error0; |
---|
1187 | 1195 | } |
---|
1188 | 1196 | |
---|
1189 | 1197 | if (XFS_IS_GQUOTA_ON(mp)) { |
---|
1190 | | - error = xfs_qm_quotacheck_dqadjust(ip, XFS_DQ_GROUP, nblks, |
---|
| 1198 | + error = xfs_qm_quotacheck_dqadjust(ip, XFS_DQTYPE_GROUP, nblks, |
---|
1191 | 1199 | rtblks); |
---|
1192 | 1200 | if (error) |
---|
1193 | 1201 | goto error0; |
---|
1194 | 1202 | } |
---|
1195 | 1203 | |
---|
1196 | 1204 | if (XFS_IS_PQUOTA_ON(mp)) { |
---|
1197 | | - error = xfs_qm_quotacheck_dqadjust(ip, XFS_DQ_PROJ, nblks, |
---|
| 1205 | + error = xfs_qm_quotacheck_dqadjust(ip, XFS_DQTYPE_PROJ, nblks, |
---|
1198 | 1206 | rtblks); |
---|
1199 | 1207 | if (error) |
---|
1200 | 1208 | goto error0; |
---|
1201 | 1209 | } |
---|
1202 | 1210 | |
---|
1203 | | - xfs_irele(ip); |
---|
1204 | | - *res = BULKSTAT_RV_DIDONE; |
---|
1205 | | - return 0; |
---|
1206 | | - |
---|
1207 | 1211 | error0: |
---|
1208 | 1212 | xfs_irele(ip); |
---|
1209 | | - *res = BULKSTAT_RV_GIVEUP; |
---|
1210 | 1213 | return error; |
---|
1211 | 1214 | } |
---|
1212 | 1215 | |
---|
.. | .. |
---|
1221 | 1224 | int error = 0; |
---|
1222 | 1225 | |
---|
1223 | 1226 | xfs_dqlock(dqp); |
---|
1224 | | - if (dqp->dq_flags & XFS_DQ_FREEING) |
---|
| 1227 | + if (dqp->q_flags & XFS_DQFLAG_FREEING) |
---|
1225 | 1228 | goto out_unlock; |
---|
1226 | 1229 | if (!XFS_DQ_IS_DIRTY(dqp)) |
---|
1227 | 1230 | goto out_unlock; |
---|
.. | .. |
---|
1270 | 1273 | xfs_qm_quotacheck( |
---|
1271 | 1274 | xfs_mount_t *mp) |
---|
1272 | 1275 | { |
---|
1273 | | - int done, count, error, error2; |
---|
1274 | | - xfs_ino_t lastino; |
---|
1275 | | - size_t structsz; |
---|
| 1276 | + int error, error2; |
---|
1276 | 1277 | uint flags; |
---|
1277 | 1278 | LIST_HEAD (buffer_list); |
---|
1278 | 1279 | struct xfs_inode *uip = mp->m_quotainfo->qi_uquotaip; |
---|
1279 | 1280 | struct xfs_inode *gip = mp->m_quotainfo->qi_gquotaip; |
---|
1280 | 1281 | struct xfs_inode *pip = mp->m_quotainfo->qi_pquotaip; |
---|
1281 | 1282 | |
---|
1282 | | - count = INT_MAX; |
---|
1283 | | - structsz = 1; |
---|
1284 | | - lastino = 0; |
---|
1285 | 1283 | flags = 0; |
---|
1286 | 1284 | |
---|
1287 | 1285 | ASSERT(uip || gip || pip); |
---|
.. | .. |
---|
1295 | 1293 | * We don't log our changes till later. |
---|
1296 | 1294 | */ |
---|
1297 | 1295 | if (uip) { |
---|
1298 | | - error = xfs_qm_reset_dqcounts_buf(mp, uip, XFS_QMOPT_UQUOTA, |
---|
| 1296 | + error = xfs_qm_reset_dqcounts_buf(mp, uip, XFS_DQTYPE_USER, |
---|
1299 | 1297 | &buffer_list); |
---|
1300 | 1298 | if (error) |
---|
1301 | 1299 | goto error_return; |
---|
.. | .. |
---|
1303 | 1301 | } |
---|
1304 | 1302 | |
---|
1305 | 1303 | if (gip) { |
---|
1306 | | - error = xfs_qm_reset_dqcounts_buf(mp, gip, XFS_QMOPT_GQUOTA, |
---|
| 1304 | + error = xfs_qm_reset_dqcounts_buf(mp, gip, XFS_DQTYPE_GROUP, |
---|
1307 | 1305 | &buffer_list); |
---|
1308 | 1306 | if (error) |
---|
1309 | 1307 | goto error_return; |
---|
.. | .. |
---|
1311 | 1309 | } |
---|
1312 | 1310 | |
---|
1313 | 1311 | if (pip) { |
---|
1314 | | - error = xfs_qm_reset_dqcounts_buf(mp, pip, XFS_QMOPT_PQUOTA, |
---|
| 1312 | + error = xfs_qm_reset_dqcounts_buf(mp, pip, XFS_DQTYPE_PROJ, |
---|
1315 | 1313 | &buffer_list); |
---|
1316 | 1314 | if (error) |
---|
1317 | 1315 | goto error_return; |
---|
1318 | 1316 | flags |= XFS_PQUOTA_CHKD; |
---|
1319 | 1317 | } |
---|
1320 | 1318 | |
---|
1321 | | - do { |
---|
| 1319 | + error = xfs_iwalk_threaded(mp, 0, 0, xfs_qm_dqusage_adjust, 0, true, |
---|
| 1320 | + NULL); |
---|
| 1321 | + if (error) { |
---|
1322 | 1322 | /* |
---|
1323 | | - * Iterate thru all the inodes in the file system, |
---|
1324 | | - * adjusting the corresponding dquot counters in core. |
---|
| 1323 | + * The inode walk may have partially populated the dquot |
---|
| 1324 | + * caches. We must purge them before disabling quota and |
---|
| 1325 | + * tearing down the quotainfo, or else the dquots will leak. |
---|
1325 | 1326 | */ |
---|
1326 | | - error = xfs_bulkstat(mp, &lastino, &count, |
---|
1327 | | - xfs_qm_dqusage_adjust, |
---|
1328 | | - structsz, NULL, &done); |
---|
1329 | | - if (error) |
---|
1330 | | - break; |
---|
1331 | | - |
---|
1332 | | - } while (!done); |
---|
| 1327 | + xfs_qm_dqpurge_all(mp, XFS_QMOPT_QUOTALL); |
---|
| 1328 | + goto error_return; |
---|
| 1329 | + } |
---|
1333 | 1330 | |
---|
1334 | 1331 | /* |
---|
1335 | 1332 | * We've made all the changes that we need to make incore. Flush them |
---|
1336 | 1333 | * down to disk buffers if everything was updated successfully. |
---|
1337 | 1334 | */ |
---|
1338 | 1335 | if (XFS_IS_UQUOTA_ON(mp)) { |
---|
1339 | | - error = xfs_qm_dquot_walk(mp, XFS_DQ_USER, xfs_qm_flush_one, |
---|
| 1336 | + error = xfs_qm_dquot_walk(mp, XFS_DQTYPE_USER, xfs_qm_flush_one, |
---|
1340 | 1337 | &buffer_list); |
---|
1341 | 1338 | } |
---|
1342 | 1339 | if (XFS_IS_GQUOTA_ON(mp)) { |
---|
1343 | | - error2 = xfs_qm_dquot_walk(mp, XFS_DQ_GROUP, xfs_qm_flush_one, |
---|
| 1340 | + error2 = xfs_qm_dquot_walk(mp, XFS_DQTYPE_GROUP, xfs_qm_flush_one, |
---|
1344 | 1341 | &buffer_list); |
---|
1345 | 1342 | if (!error) |
---|
1346 | 1343 | error = error2; |
---|
1347 | 1344 | } |
---|
1348 | 1345 | if (XFS_IS_PQUOTA_ON(mp)) { |
---|
1349 | | - error2 = xfs_qm_dquot_walk(mp, XFS_DQ_PROJ, xfs_qm_flush_one, |
---|
| 1346 | + error2 = xfs_qm_dquot_walk(mp, XFS_DQTYPE_PROJ, xfs_qm_flush_one, |
---|
1350 | 1347 | &buffer_list); |
---|
1351 | 1348 | if (!error) |
---|
1352 | 1349 | error = error2; |
---|
.. | .. |
---|
1585 | 1582 | |
---|
1586 | 1583 | STATIC void |
---|
1587 | 1584 | xfs_qm_destroy_quotainos( |
---|
1588 | | - xfs_quotainfo_t *qi) |
---|
| 1585 | + struct xfs_quotainfo *qi) |
---|
1589 | 1586 | { |
---|
1590 | 1587 | if (qi->qi_uquotaip) { |
---|
1591 | 1588 | xfs_irele(qi->qi_uquotaip); |
---|
.. | .. |
---|
1609 | 1606 | struct xfs_quotainfo *qi = mp->m_quotainfo; |
---|
1610 | 1607 | |
---|
1611 | 1608 | mutex_lock(&qi->qi_tree_lock); |
---|
1612 | | - radix_tree_delete(xfs_dquot_tree(qi, dqp->q_core.d_flags), |
---|
1613 | | - be32_to_cpu(dqp->q_core.d_id)); |
---|
| 1609 | + radix_tree_delete(xfs_dquot_tree(qi, xfs_dquot_type(dqp)), dqp->q_id); |
---|
1614 | 1610 | |
---|
1615 | 1611 | qi->qi_dquots--; |
---|
1616 | 1612 | mutex_unlock(&qi->qi_tree_lock); |
---|
.. | .. |
---|
1634 | 1630 | int |
---|
1635 | 1631 | xfs_qm_vop_dqalloc( |
---|
1636 | 1632 | struct xfs_inode *ip, |
---|
1637 | | - xfs_dqid_t uid, |
---|
1638 | | - xfs_dqid_t gid, |
---|
| 1633 | + kuid_t uid, |
---|
| 1634 | + kgid_t gid, |
---|
1639 | 1635 | prid_t prid, |
---|
1640 | 1636 | uint flags, |
---|
1641 | 1637 | struct xfs_dquot **O_udqpp, |
---|
.. | .. |
---|
1643 | 1639 | struct xfs_dquot **O_pdqpp) |
---|
1644 | 1640 | { |
---|
1645 | 1641 | struct xfs_mount *mp = ip->i_mount; |
---|
| 1642 | + struct inode *inode = VFS_I(ip); |
---|
| 1643 | + struct user_namespace *user_ns = inode->i_sb->s_user_ns; |
---|
1646 | 1644 | struct xfs_dquot *uq = NULL; |
---|
1647 | 1645 | struct xfs_dquot *gq = NULL; |
---|
1648 | 1646 | struct xfs_dquot *pq = NULL; |
---|
.. | .. |
---|
1656 | 1654 | xfs_ilock(ip, lockflags); |
---|
1657 | 1655 | |
---|
1658 | 1656 | if ((flags & XFS_QMOPT_INHERIT) && XFS_INHERIT_GID(ip)) |
---|
1659 | | - gid = ip->i_d.di_gid; |
---|
| 1657 | + gid = inode->i_gid; |
---|
1660 | 1658 | |
---|
1661 | 1659 | /* |
---|
1662 | 1660 | * Attach the dquot(s) to this inode, doing a dquot allocation |
---|
.. | .. |
---|
1671 | 1669 | } |
---|
1672 | 1670 | |
---|
1673 | 1671 | if ((flags & XFS_QMOPT_UQUOTA) && XFS_IS_UQUOTA_ON(mp)) { |
---|
1674 | | - if (ip->i_d.di_uid != uid) { |
---|
| 1672 | + ASSERT(O_udqpp); |
---|
| 1673 | + if (!uid_eq(inode->i_uid, uid)) { |
---|
1675 | 1674 | /* |
---|
1676 | 1675 | * What we need is the dquot that has this uid, and |
---|
1677 | 1676 | * if we send the inode to dqget, the uid of the inode |
---|
.. | .. |
---|
1682 | 1681 | * holding ilock. |
---|
1683 | 1682 | */ |
---|
1684 | 1683 | xfs_iunlock(ip, lockflags); |
---|
1685 | | - error = xfs_qm_dqget(mp, uid, XFS_DQ_USER, true, &uq); |
---|
| 1684 | + error = xfs_qm_dqget(mp, from_kuid(user_ns, uid), |
---|
| 1685 | + XFS_DQTYPE_USER, true, &uq); |
---|
1686 | 1686 | if (error) { |
---|
1687 | 1687 | ASSERT(error != -ENOENT); |
---|
1688 | 1688 | return error; |
---|
.. | .. |
---|
1703 | 1703 | } |
---|
1704 | 1704 | } |
---|
1705 | 1705 | if ((flags & XFS_QMOPT_GQUOTA) && XFS_IS_GQUOTA_ON(mp)) { |
---|
1706 | | - if (ip->i_d.di_gid != gid) { |
---|
| 1706 | + ASSERT(O_gdqpp); |
---|
| 1707 | + if (!gid_eq(inode->i_gid, gid)) { |
---|
1707 | 1708 | xfs_iunlock(ip, lockflags); |
---|
1708 | | - error = xfs_qm_dqget(mp, gid, XFS_DQ_GROUP, true, &gq); |
---|
| 1709 | + error = xfs_qm_dqget(mp, from_kgid(user_ns, gid), |
---|
| 1710 | + XFS_DQTYPE_GROUP, true, &gq); |
---|
1709 | 1711 | if (error) { |
---|
1710 | 1712 | ASSERT(error != -ENOENT); |
---|
1711 | 1713 | goto error_rele; |
---|
.. | .. |
---|
1719 | 1721 | } |
---|
1720 | 1722 | } |
---|
1721 | 1723 | if ((flags & XFS_QMOPT_PQUOTA) && XFS_IS_PQUOTA_ON(mp)) { |
---|
1722 | | - if (xfs_get_projid(ip) != prid) { |
---|
| 1724 | + ASSERT(O_pdqpp); |
---|
| 1725 | + if (ip->i_d.di_projid != prid) { |
---|
1723 | 1726 | xfs_iunlock(ip, lockflags); |
---|
1724 | | - error = xfs_qm_dqget(mp, (xfs_dqid_t)prid, XFS_DQ_PROJ, |
---|
1725 | | - true, &pq); |
---|
| 1727 | + error = xfs_qm_dqget(mp, prid, |
---|
| 1728 | + XFS_DQTYPE_PROJ, true, &pq); |
---|
1726 | 1729 | if (error) { |
---|
1727 | 1730 | ASSERT(error != -ENOENT); |
---|
1728 | 1731 | goto error_rele; |
---|
.. | .. |
---|
1735 | 1738 | pq = xfs_qm_dqhold(ip->i_pdquot); |
---|
1736 | 1739 | } |
---|
1737 | 1740 | } |
---|
1738 | | - if (uq) |
---|
1739 | | - trace_xfs_dquot_dqalloc(ip); |
---|
| 1741 | + trace_xfs_dquot_dqalloc(ip); |
---|
1740 | 1742 | |
---|
1741 | 1743 | xfs_iunlock(ip, lockflags); |
---|
1742 | 1744 | if (O_udqpp) |
---|
.. | .. |
---|
1763 | 1765 | * Actually transfer ownership, and do dquot modifications. |
---|
1764 | 1766 | * These were already reserved. |
---|
1765 | 1767 | */ |
---|
1766 | | -xfs_dquot_t * |
---|
| 1768 | +struct xfs_dquot * |
---|
1767 | 1769 | xfs_qm_vop_chown( |
---|
1768 | | - xfs_trans_t *tp, |
---|
1769 | | - xfs_inode_t *ip, |
---|
1770 | | - xfs_dquot_t **IO_olddq, |
---|
1771 | | - xfs_dquot_t *newdq) |
---|
| 1770 | + struct xfs_trans *tp, |
---|
| 1771 | + struct xfs_inode *ip, |
---|
| 1772 | + struct xfs_dquot **IO_olddq, |
---|
| 1773 | + struct xfs_dquot *newdq) |
---|
1772 | 1774 | { |
---|
1773 | | - xfs_dquot_t *prevdq; |
---|
| 1775 | + struct xfs_dquot *prevdq; |
---|
1774 | 1776 | uint bfield = XFS_IS_REALTIME_INODE(ip) ? |
---|
1775 | 1777 | XFS_TRANS_DQ_RTBCOUNT : XFS_TRANS_DQ_BCOUNT; |
---|
1776 | 1778 | |
---|
.. | .. |
---|
1789 | 1791 | /* the sparkling new dquot */ |
---|
1790 | 1792 | xfs_trans_mod_dquot(tp, newdq, bfield, ip->i_d.di_nblocks); |
---|
1791 | 1793 | xfs_trans_mod_dquot(tp, newdq, XFS_TRANS_DQ_ICOUNT, 1); |
---|
| 1794 | + |
---|
| 1795 | + /* |
---|
| 1796 | + * Back when we made quota reservations for the chown, we reserved the |
---|
| 1797 | + * ondisk blocks + delalloc blocks with the new dquot. Now that we've |
---|
| 1798 | + * switched the dquots, decrease the new dquot's block reservation |
---|
| 1799 | + * (having already bumped up the real counter) so that we don't have |
---|
| 1800 | + * any reservation to give back when we commit. |
---|
| 1801 | + */ |
---|
| 1802 | + xfs_trans_mod_dquot(tp, newdq, XFS_TRANS_DQ_RES_BLKS, |
---|
| 1803 | + -ip->i_delayed_blks); |
---|
| 1804 | + |
---|
| 1805 | + /* |
---|
| 1806 | + * Give the incore reservation for delalloc blocks back to the old |
---|
| 1807 | + * dquot. We don't normally handle delalloc quota reservations |
---|
| 1808 | + * transactionally, so just lock the dquot and subtract from the |
---|
| 1809 | + * reservation. Dirty the transaction because it's too late to turn |
---|
| 1810 | + * back now. |
---|
| 1811 | + */ |
---|
| 1812 | + tp->t_flags |= XFS_TRANS_DIRTY; |
---|
| 1813 | + xfs_dqlock(prevdq); |
---|
| 1814 | + ASSERT(prevdq->q_blk.reserved >= ip->i_delayed_blks); |
---|
| 1815 | + prevdq->q_blk.reserved -= ip->i_delayed_blks; |
---|
| 1816 | + xfs_dqunlock(prevdq); |
---|
1792 | 1817 | |
---|
1793 | 1818 | /* |
---|
1794 | 1819 | * Take an extra reference, because the inode is going to keep |
---|
.. | .. |
---|
1812 | 1837 | uint flags) |
---|
1813 | 1838 | { |
---|
1814 | 1839 | struct xfs_mount *mp = ip->i_mount; |
---|
1815 | | - uint delblks, blkflags, prjflags = 0; |
---|
1816 | | - struct xfs_dquot *udq_unres = NULL; |
---|
1817 | | - struct xfs_dquot *gdq_unres = NULL; |
---|
1818 | | - struct xfs_dquot *pdq_unres = NULL; |
---|
| 1840 | + unsigned int blkflags; |
---|
1819 | 1841 | struct xfs_dquot *udq_delblks = NULL; |
---|
1820 | 1842 | struct xfs_dquot *gdq_delblks = NULL; |
---|
1821 | 1843 | struct xfs_dquot *pdq_delblks = NULL; |
---|
1822 | | - int error; |
---|
1823 | | - |
---|
1824 | 1844 | |
---|
1825 | 1845 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED)); |
---|
1826 | 1846 | ASSERT(XFS_IS_QUOTA_RUNNING(mp)); |
---|
1827 | 1847 | |
---|
1828 | | - delblks = ip->i_delayed_blks; |
---|
1829 | 1848 | blkflags = XFS_IS_REALTIME_INODE(ip) ? |
---|
1830 | 1849 | XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS; |
---|
1831 | 1850 | |
---|
1832 | 1851 | if (XFS_IS_UQUOTA_ON(mp) && udqp && |
---|
1833 | | - ip->i_d.di_uid != be32_to_cpu(udqp->q_core.d_id)) { |
---|
| 1852 | + i_uid_read(VFS_I(ip)) != udqp->q_id) |
---|
1834 | 1853 | udq_delblks = udqp; |
---|
1835 | | - /* |
---|
1836 | | - * If there are delayed allocation blocks, then we have to |
---|
1837 | | - * unreserve those from the old dquot, and add them to the |
---|
1838 | | - * new dquot. |
---|
1839 | | - */ |
---|
1840 | | - if (delblks) { |
---|
1841 | | - ASSERT(ip->i_udquot); |
---|
1842 | | - udq_unres = ip->i_udquot; |
---|
1843 | | - } |
---|
1844 | | - } |
---|
| 1854 | + |
---|
1845 | 1855 | if (XFS_IS_GQUOTA_ON(ip->i_mount) && gdqp && |
---|
1846 | | - ip->i_d.di_gid != be32_to_cpu(gdqp->q_core.d_id)) { |
---|
| 1856 | + i_gid_read(VFS_I(ip)) != gdqp->q_id) |
---|
1847 | 1857 | gdq_delblks = gdqp; |
---|
1848 | | - if (delblks) { |
---|
1849 | | - ASSERT(ip->i_gdquot); |
---|
1850 | | - gdq_unres = ip->i_gdquot; |
---|
1851 | | - } |
---|
1852 | | - } |
---|
1853 | 1858 | |
---|
1854 | 1859 | if (XFS_IS_PQUOTA_ON(ip->i_mount) && pdqp && |
---|
1855 | | - xfs_get_projid(ip) != be32_to_cpu(pdqp->q_core.d_id)) { |
---|
1856 | | - prjflags = XFS_QMOPT_ENOSPC; |
---|
| 1860 | + ip->i_d.di_projid != pdqp->q_id) |
---|
1857 | 1861 | pdq_delblks = pdqp; |
---|
1858 | | - if (delblks) { |
---|
1859 | | - ASSERT(ip->i_pdquot); |
---|
1860 | | - pdq_unres = ip->i_pdquot; |
---|
1861 | | - } |
---|
1862 | | - } |
---|
1863 | | - |
---|
1864 | | - error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount, |
---|
1865 | | - udq_delblks, gdq_delblks, pdq_delblks, |
---|
1866 | | - ip->i_d.di_nblocks, 1, |
---|
1867 | | - flags | blkflags | prjflags); |
---|
1868 | | - if (error) |
---|
1869 | | - return error; |
---|
1870 | 1862 | |
---|
1871 | 1863 | /* |
---|
1872 | | - * Do the delayed blks reservations/unreservations now. Since, these |
---|
1873 | | - * are done without the help of a transaction, if a reservation fails |
---|
1874 | | - * its previous reservations won't be automatically undone by trans |
---|
1875 | | - * code. So, we have to do it manually here. |
---|
| 1864 | + * Reserve enough quota to handle blocks on disk and reserved for a |
---|
| 1865 | + * delayed allocation. We'll actually transfer the delalloc |
---|
| 1866 | + * reservation between dquots at chown time, even though that part is |
---|
| 1867 | + * only semi-transactional. |
---|
1876 | 1868 | */ |
---|
1877 | | - if (delblks) { |
---|
1878 | | - /* |
---|
1879 | | - * Do the reservations first. Unreservation can't fail. |
---|
1880 | | - */ |
---|
1881 | | - ASSERT(udq_delblks || gdq_delblks || pdq_delblks); |
---|
1882 | | - ASSERT(udq_unres || gdq_unres || pdq_unres); |
---|
1883 | | - error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount, |
---|
1884 | | - udq_delblks, gdq_delblks, pdq_delblks, |
---|
1885 | | - (xfs_qcnt_t)delblks, 0, |
---|
1886 | | - flags | blkflags | prjflags); |
---|
1887 | | - if (error) |
---|
1888 | | - return error; |
---|
1889 | | - xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount, |
---|
1890 | | - udq_unres, gdq_unres, pdq_unres, |
---|
1891 | | - -((xfs_qcnt_t)delblks), 0, blkflags); |
---|
1892 | | - } |
---|
1893 | | - |
---|
1894 | | - return 0; |
---|
| 1869 | + return xfs_trans_reserve_quota_bydquots(tp, ip->i_mount, udq_delblks, |
---|
| 1870 | + gdq_delblks, pdq_delblks, |
---|
| 1871 | + ip->i_d.di_nblocks + ip->i_delayed_blks, |
---|
| 1872 | + 1, blkflags | flags); |
---|
1895 | 1873 | } |
---|
1896 | 1874 | |
---|
1897 | 1875 | int |
---|
.. | .. |
---|
1936 | 1914 | return; |
---|
1937 | 1915 | |
---|
1938 | 1916 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); |
---|
1939 | | - ASSERT(XFS_IS_QUOTA_RUNNING(mp)); |
---|
1940 | 1917 | |
---|
1941 | 1918 | if (udqp && XFS_IS_UQUOTA_ON(mp)) { |
---|
1942 | 1919 | ASSERT(ip->i_udquot == NULL); |
---|
1943 | | - ASSERT(ip->i_d.di_uid == be32_to_cpu(udqp->q_core.d_id)); |
---|
| 1920 | + ASSERT(i_uid_read(VFS_I(ip)) == udqp->q_id); |
---|
1944 | 1921 | |
---|
1945 | 1922 | ip->i_udquot = xfs_qm_dqhold(udqp); |
---|
1946 | 1923 | xfs_trans_mod_dquot(tp, udqp, XFS_TRANS_DQ_ICOUNT, 1); |
---|
1947 | 1924 | } |
---|
1948 | 1925 | if (gdqp && XFS_IS_GQUOTA_ON(mp)) { |
---|
1949 | 1926 | ASSERT(ip->i_gdquot == NULL); |
---|
1950 | | - ASSERT(ip->i_d.di_gid == be32_to_cpu(gdqp->q_core.d_id)); |
---|
| 1927 | + ASSERT(i_gid_read(VFS_I(ip)) == gdqp->q_id); |
---|
| 1928 | + |
---|
1951 | 1929 | ip->i_gdquot = xfs_qm_dqhold(gdqp); |
---|
1952 | 1930 | xfs_trans_mod_dquot(tp, gdqp, XFS_TRANS_DQ_ICOUNT, 1); |
---|
1953 | 1931 | } |
---|
1954 | 1932 | if (pdqp && XFS_IS_PQUOTA_ON(mp)) { |
---|
1955 | 1933 | ASSERT(ip->i_pdquot == NULL); |
---|
1956 | | - ASSERT(xfs_get_projid(ip) == be32_to_cpu(pdqp->q_core.d_id)); |
---|
| 1934 | + ASSERT(ip->i_d.di_projid == pdqp->q_id); |
---|
1957 | 1935 | |
---|
1958 | 1936 | ip->i_pdquot = xfs_qm_dqhold(pdqp); |
---|
1959 | 1937 | xfs_trans_mod_dquot(tp, pdqp, XFS_TRANS_DQ_ICOUNT, 1); |
---|