1
2
3
4
5
6
7
8#include "xfs.h"
9#include "xfs_fs.h"
10#include "xfs_shared.h"
11#include "xfs_format.h"
12#include "xfs_log_format.h"
13#include "xfs_trans_resv.h"
14#include "xfs_sb.h"
15#include "xfs_mount.h"
16#include "xfs_inode.h"
17#include "xfs_trans.h"
18#include "xfs_quota.h"
19#include "xfs_qm.h"
20#include "xfs_icache.h"
21
22STATIC int
23xfs_qm_log_quotaoff(
24 struct xfs_mount *mp,
25 struct xfs_qoff_logitem **qoffstartp,
26 uint flags)
27{
28 struct xfs_trans *tp;
29 int error;
30 struct xfs_qoff_logitem *qoffi;
31
32 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_qm_quotaoff, 0, 0, 0, &tp);
33 if (error)
34 goto out;
35
36 qoffi = xfs_trans_get_qoff_item(tp, NULL, flags & XFS_ALL_QUOTA_ACCT);
37 xfs_trans_log_quotaoff_item(tp, qoffi);
38
39 spin_lock(&mp->m_sb_lock);
40 mp->m_sb.sb_qflags = (mp->m_qflags & ~(flags)) & XFS_MOUNT_QUOTA_ALL;
41 spin_unlock(&mp->m_sb_lock);
42
43 xfs_log_sb(tp);
44
45
46
47
48
49
50 xfs_trans_set_sync(tp);
51 error = xfs_trans_commit(tp);
52 if (error)
53 goto out;
54
55 *qoffstartp = qoffi;
56out:
57 return error;
58}
59
60STATIC int
61xfs_qm_log_quotaoff_end(
62 struct xfs_mount *mp,
63 struct xfs_qoff_logitem **startqoff,
64 uint flags)
65{
66 struct xfs_trans *tp;
67 int error;
68 struct xfs_qoff_logitem *qoffi;
69
70 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_qm_equotaoff, 0, 0, 0, &tp);
71 if (error)
72 return error;
73
74 qoffi = xfs_trans_get_qoff_item(tp, *startqoff,
75 flags & XFS_ALL_QUOTA_ACCT);
76 xfs_trans_log_quotaoff_item(tp, qoffi);
77 *startqoff = NULL;
78
79
80
81
82
83
84 xfs_trans_set_sync(tp);
85 return xfs_trans_commit(tp);
86}
87
88
89
90
91
92
93
94
95
96int
97xfs_qm_scall_quotaoff(
98 xfs_mount_t *mp,
99 uint flags)
100{
101 struct xfs_quotainfo *q = mp->m_quotainfo;
102 uint dqtype;
103 int error;
104 uint inactivate_flags;
105 struct xfs_qoff_logitem *qoffstart = NULL;
106
107
108
109
110
111
112 if ((mp->m_qflags & flags) == 0)
113 return -EEXIST;
114 error = 0;
115
116 flags &= (XFS_ALL_QUOTA_ACCT | XFS_ALL_QUOTA_ENFD);
117
118
119
120
121
122
123
124 ASSERT(q);
125 mutex_lock(&q->qi_quotaofflock);
126
127
128
129
130 if ((flags & XFS_ALL_QUOTA_ACCT) == 0) {
131 mp->m_qflags &= ~(flags);
132
133 spin_lock(&mp->m_sb_lock);
134 mp->m_sb.sb_qflags = mp->m_qflags;
135 spin_unlock(&mp->m_sb_lock);
136 mutex_unlock(&q->qi_quotaofflock);
137
138
139 return xfs_sync_sb(mp, false);
140 }
141
142 dqtype = 0;
143 inactivate_flags = 0;
144
145
146
147
148
149 if (flags & XFS_UQUOTA_ACCT) {
150 dqtype |= XFS_QMOPT_UQUOTA;
151 flags |= (XFS_UQUOTA_CHKD | XFS_UQUOTA_ENFD);
152 inactivate_flags |= XFS_UQUOTA_ACTIVE;
153 }
154 if (flags & XFS_GQUOTA_ACCT) {
155 dqtype |= XFS_QMOPT_GQUOTA;
156 flags |= (XFS_GQUOTA_CHKD | XFS_GQUOTA_ENFD);
157 inactivate_flags |= XFS_GQUOTA_ACTIVE;
158 }
159 if (flags & XFS_PQUOTA_ACCT) {
160 dqtype |= XFS_QMOPT_PQUOTA;
161 flags |= (XFS_PQUOTA_CHKD | XFS_PQUOTA_ENFD);
162 inactivate_flags |= XFS_PQUOTA_ACTIVE;
163 }
164
165
166
167
168
169 if ((mp->m_qflags & flags) == 0)
170 goto out_unlock;
171
172
173
174
175
176
177 error = xfs_qm_log_quotaoff(mp, &qoffstart, flags);
178 if (error)
179 goto out_unlock;
180
181
182
183
184
185
186
187
188
189
190
191
192 mp->m_qflags &= ~inactivate_flags;
193
194
195
196
197
198
199
200
201
202
203
204 xfs_qm_dqrele_all_inodes(mp, flags);
205
206
207
208
209
210
211 mp->m_qflags &= ~flags;
212
213
214
215
216
217 xfs_qm_dqpurge_all(mp, dqtype);
218
219
220
221
222
223
224
225
226
227
228
229
230 error = xfs_qm_log_quotaoff_end(mp, &qoffstart, flags);
231 if (error) {
232
233 xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
234 goto out_unlock;
235 }
236
237
238
239
240 if (mp->m_qflags == 0) {
241 mutex_unlock(&q->qi_quotaofflock);
242 xfs_qm_destroy_quotainfo(mp);
243 return 0;
244 }
245
246
247
248
249 if ((dqtype & XFS_QMOPT_UQUOTA) && q->qi_uquotaip) {
250 xfs_irele(q->qi_uquotaip);
251 q->qi_uquotaip = NULL;
252 }
253 if ((dqtype & XFS_QMOPT_GQUOTA) && q->qi_gquotaip) {
254 xfs_irele(q->qi_gquotaip);
255 q->qi_gquotaip = NULL;
256 }
257 if ((dqtype & XFS_QMOPT_PQUOTA) && q->qi_pquotaip) {
258 xfs_irele(q->qi_pquotaip);
259 q->qi_pquotaip = NULL;
260 }
261
262out_unlock:
263 if (error && qoffstart)
264 xfs_qm_qoff_logitem_relse(qoffstart);
265 mutex_unlock(&q->qi_quotaofflock);
266 return error;
267}
268
269STATIC int
270xfs_qm_scall_trunc_qfile(
271 struct xfs_mount *mp,
272 xfs_ino_t ino)
273{
274 struct xfs_inode *ip;
275 struct xfs_trans *tp;
276 int error;
277
278 if (ino == NULLFSINO)
279 return 0;
280
281 error = xfs_iget(mp, NULL, ino, 0, 0, &ip);
282 if (error)
283 return error;
284
285 xfs_ilock(ip, XFS_IOLOCK_EXCL);
286
287 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp);
288 if (error) {
289 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
290 goto out_put;
291 }
292
293 xfs_ilock(ip, XFS_ILOCK_EXCL);
294 xfs_trans_ijoin(tp, ip, 0);
295
296 ip->i_d.di_size = 0;
297 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
298
299 error = xfs_itruncate_extents(&tp, ip, XFS_DATA_FORK, 0);
300 if (error) {
301 xfs_trans_cancel(tp);
302 goto out_unlock;
303 }
304
305 ASSERT(ip->i_df.if_nextents == 0);
306
307 xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
308 error = xfs_trans_commit(tp);
309
310out_unlock:
311 xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
312out_put:
313 xfs_irele(ip);
314 return error;
315}
316
317int
318xfs_qm_scall_trunc_qfiles(
319 xfs_mount_t *mp,
320 uint flags)
321{
322 int error = -EINVAL;
323
324 if (!xfs_sb_version_hasquota(&mp->m_sb) || flags == 0 ||
325 (flags & ~XFS_QMOPT_QUOTALL)) {
326 xfs_debug(mp, "%s: flags=%x m_qflags=%x",
327 __func__, flags, mp->m_qflags);
328 return -EINVAL;
329 }
330
331 if (flags & XFS_QMOPT_UQUOTA) {
332 error = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_uquotino);
333 if (error)
334 return error;
335 }
336 if (flags & XFS_QMOPT_GQUOTA) {
337 error = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_gquotino);
338 if (error)
339 return error;
340 }
341 if (flags & XFS_QMOPT_PQUOTA)
342 error = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_pquotino);
343
344 return error;
345}
346
347
348
349
350
351
352int
353xfs_qm_scall_quotaon(
354 xfs_mount_t *mp,
355 uint flags)
356{
357 int error;
358 uint qf;
359
360
361
362
363
364 flags &= XFS_ALL_QUOTA_ENFD;
365
366 if (flags == 0) {
367 xfs_debug(mp, "%s: zero flags, m_qflags=%x",
368 __func__, mp->m_qflags);
369 return -EINVAL;
370 }
371
372
373
374
375
376
377 if (((mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) == 0 &&
378 (flags & XFS_UQUOTA_ENFD)) ||
379 ((mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) == 0 &&
380 (flags & XFS_GQUOTA_ENFD)) ||
381 ((mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) == 0 &&
382 (flags & XFS_PQUOTA_ENFD))) {
383 xfs_debug(mp,
384 "%s: Can't enforce without acct, flags=%x sbflags=%x",
385 __func__, flags, mp->m_sb.sb_qflags);
386 return -EINVAL;
387 }
388
389
390
391 if ((mp->m_qflags & flags) == flags)
392 return -EEXIST;
393
394
395
396
397
398 spin_lock(&mp->m_sb_lock);
399 qf = mp->m_sb.sb_qflags;
400 mp->m_sb.sb_qflags = qf | flags;
401 spin_unlock(&mp->m_sb_lock);
402
403
404
405
406 if ((qf & flags) == flags)
407 return -EEXIST;
408
409 error = xfs_sync_sb(mp, false);
410 if (error)
411 return error;
412
413
414
415 if (((mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) !=
416 (mp->m_qflags & XFS_UQUOTA_ACCT)) ||
417 ((mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) !=
418 (mp->m_qflags & XFS_PQUOTA_ACCT)) ||
419 ((mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) !=
420 (mp->m_qflags & XFS_GQUOTA_ACCT)))
421 return 0;
422
423 if (! XFS_IS_QUOTA_RUNNING(mp))
424 return -ESRCH;
425
426
427
428
429 mutex_lock(&mp->m_quotainfo->qi_quotaofflock);
430 mp->m_qflags |= (flags & XFS_ALL_QUOTA_ENFD);
431 mutex_unlock(&mp->m_quotainfo->qi_quotaofflock);
432
433 return 0;
434}
435
436#define XFS_QC_MASK \
437 (QC_LIMIT_MASK | QC_TIMER_MASK | QC_WARNS_MASK)
438
439
440
441
442
443static inline bool
444xfs_setqlim_limits(
445 struct xfs_mount *mp,
446 struct xfs_dquot_res *res,
447 struct xfs_quota_limits *qlim,
448 xfs_qcnt_t hard,
449 xfs_qcnt_t soft,
450 const char *tag)
451{
452
453 if (hard != 0 && hard < soft) {
454 xfs_debug(mp, "%shard %lld < %ssoft %lld", tag, hard, tag,
455 soft);
456 return false;
457 }
458
459 res->hardlimit = hard;
460 res->softlimit = soft;
461 if (qlim) {
462 qlim->hard = hard;
463 qlim->soft = soft;
464 }
465
466 return true;
467}
468
469static inline void
470xfs_setqlim_warns(
471 struct xfs_dquot_res *res,
472 struct xfs_quota_limits *qlim,
473 int warns)
474{
475 res->warnings = warns;
476 if (qlim)
477 qlim->warn = warns;
478}
479
480static inline void
481xfs_setqlim_timer(
482 struct xfs_mount *mp,
483 struct xfs_dquot_res *res,
484 struct xfs_quota_limits *qlim,
485 s64 timer)
486{
487 if (qlim) {
488
489 res->timer = xfs_dquot_set_grace_period(timer);
490 qlim->time = res->timer;
491 } else {
492
493 res->timer = xfs_dquot_set_timeout(mp, timer);
494 }
495}
496
497
498
499
500int
501xfs_qm_scall_setqlim(
502 struct xfs_mount *mp,
503 xfs_dqid_t id,
504 xfs_dqtype_t type,
505 struct qc_dqblk *newlim)
506{
507 struct xfs_quotainfo *q = mp->m_quotainfo;
508 struct xfs_dquot *dqp;
509 struct xfs_trans *tp;
510 struct xfs_def_quota *defq;
511 struct xfs_dquot_res *res;
512 struct xfs_quota_limits *qlim;
513 int error;
514 xfs_qcnt_t hard, soft;
515
516 if (newlim->d_fieldmask & ~XFS_QC_MASK)
517 return -EINVAL;
518 if ((newlim->d_fieldmask & XFS_QC_MASK) == 0)
519 return 0;
520
521
522
523
524
525
526 mutex_lock(&q->qi_quotaofflock);
527
528
529
530
531
532
533
534
535 error = xfs_qm_dqget(mp, id, type, true, &dqp);
536 if (error) {
537 ASSERT(error != -ENOENT);
538 goto out_unlock;
539 }
540
541 defq = xfs_get_defquota(q, xfs_dquot_type(dqp));
542 xfs_dqunlock(dqp);
543
544 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_qm_setqlim, 0, 0, 0, &tp);
545 if (error)
546 goto out_rele;
547
548 xfs_dqlock(dqp);
549 xfs_trans_dqjoin(tp, dqp);
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569 hard = (newlim->d_fieldmask & QC_SPC_HARD) ?
570 (xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_spc_hardlimit) :
571 dqp->q_blk.hardlimit;
572 soft = (newlim->d_fieldmask & QC_SPC_SOFT) ?
573 (xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_spc_softlimit) :
574 dqp->q_blk.softlimit;
575 res = &dqp->q_blk;
576 qlim = id == 0 ? &defq->blk : NULL;
577
578 if (xfs_setqlim_limits(mp, res, qlim, hard, soft, "blk"))
579 xfs_dquot_set_prealloc_limits(dqp);
580 if (newlim->d_fieldmask & QC_SPC_WARNS)
581 xfs_setqlim_warns(res, qlim, newlim->d_spc_warns);
582 if (newlim->d_fieldmask & QC_SPC_TIMER)
583 xfs_setqlim_timer(mp, res, qlim, newlim->d_spc_timer);
584
585
586 hard = (newlim->d_fieldmask & QC_RT_SPC_HARD) ?
587 (xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_rt_spc_hardlimit) :
588 dqp->q_rtb.hardlimit;
589 soft = (newlim->d_fieldmask & QC_RT_SPC_SOFT) ?
590 (xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_rt_spc_softlimit) :
591 dqp->q_rtb.softlimit;
592 res = &dqp->q_rtb;
593 qlim = id == 0 ? &defq->rtb : NULL;
594
595 xfs_setqlim_limits(mp, res, qlim, hard, soft, "rtb");
596 if (newlim->d_fieldmask & QC_RT_SPC_WARNS)
597 xfs_setqlim_warns(res, qlim, newlim->d_rt_spc_warns);
598 if (newlim->d_fieldmask & QC_RT_SPC_TIMER)
599 xfs_setqlim_timer(mp, res, qlim, newlim->d_rt_spc_timer);
600
601
602 hard = (newlim->d_fieldmask & QC_INO_HARD) ?
603 (xfs_qcnt_t) newlim->d_ino_hardlimit :
604 dqp->q_ino.hardlimit;
605 soft = (newlim->d_fieldmask & QC_INO_SOFT) ?
606 (xfs_qcnt_t) newlim->d_ino_softlimit :
607 dqp->q_ino.softlimit;
608 res = &dqp->q_ino;
609 qlim = id == 0 ? &defq->ino : NULL;
610
611 xfs_setqlim_limits(mp, res, qlim, hard, soft, "ino");
612 if (newlim->d_fieldmask & QC_INO_WARNS)
613 xfs_setqlim_warns(res, qlim, newlim->d_ino_warns);
614 if (newlim->d_fieldmask & QC_INO_TIMER)
615 xfs_setqlim_timer(mp, res, qlim, newlim->d_ino_timer);
616
617 if (id != 0) {
618
619
620
621
622
623
624
625 xfs_qm_adjust_dqtimers(dqp);
626 }
627 dqp->q_flags |= XFS_DQFLAG_DIRTY;
628 xfs_trans_log_dquot(tp, dqp);
629
630 error = xfs_trans_commit(tp);
631
632out_rele:
633 xfs_qm_dqrele(dqp);
634out_unlock:
635 mutex_unlock(&q->qi_quotaofflock);
636 return error;
637}
638
639
640static void
641xfs_qm_scall_getquota_fill_qc(
642 struct xfs_mount *mp,
643 xfs_dqtype_t type,
644 const struct xfs_dquot *dqp,
645 struct qc_dqblk *dst)
646{
647 memset(dst, 0, sizeof(*dst));
648 dst->d_spc_hardlimit = XFS_FSB_TO_B(mp, dqp->q_blk.hardlimit);
649 dst->d_spc_softlimit = XFS_FSB_TO_B(mp, dqp->q_blk.softlimit);
650 dst->d_ino_hardlimit = dqp->q_ino.hardlimit;
651 dst->d_ino_softlimit = dqp->q_ino.softlimit;
652 dst->d_space = XFS_FSB_TO_B(mp, dqp->q_blk.reserved);
653 dst->d_ino_count = dqp->q_ino.reserved;
654 dst->d_spc_timer = dqp->q_blk.timer;
655 dst->d_ino_timer = dqp->q_ino.timer;
656 dst->d_ino_warns = dqp->q_ino.warnings;
657 dst->d_spc_warns = dqp->q_blk.warnings;
658 dst->d_rt_spc_hardlimit = XFS_FSB_TO_B(mp, dqp->q_rtb.hardlimit);
659 dst->d_rt_spc_softlimit = XFS_FSB_TO_B(mp, dqp->q_rtb.softlimit);
660 dst->d_rt_space = XFS_FSB_TO_B(mp, dqp->q_rtb.reserved);
661 dst->d_rt_spc_timer = dqp->q_rtb.timer;
662 dst->d_rt_spc_warns = dqp->q_rtb.warnings;
663
664
665
666
667
668
669 if (!xfs_dquot_is_enforced(dqp)) {
670 dst->d_spc_timer = 0;
671 dst->d_ino_timer = 0;
672 dst->d_rt_spc_timer = 0;
673 }
674
675#ifdef DEBUG
676 if (xfs_dquot_is_enforced(dqp) && dqp->q_id != 0) {
677 if ((dst->d_space > dst->d_spc_softlimit) &&
678 (dst->d_spc_softlimit > 0)) {
679 ASSERT(dst->d_spc_timer != 0);
680 }
681 if ((dst->d_ino_count > dqp->q_ino.softlimit) &&
682 (dqp->q_ino.softlimit > 0)) {
683 ASSERT(dst->d_ino_timer != 0);
684 }
685 }
686#endif
687}
688
689
690int
691xfs_qm_scall_getquota(
692 struct xfs_mount *mp,
693 xfs_dqid_t id,
694 xfs_dqtype_t type,
695 struct qc_dqblk *dst)
696{
697 struct xfs_dquot *dqp;
698 int error;
699
700
701
702
703
704 error = xfs_qm_dqget(mp, id, type, false, &dqp);
705 if (error)
706 return error;
707
708
709
710
711
712 if (XFS_IS_DQUOT_UNINITIALIZED(dqp)) {
713 error = -ENOENT;
714 goto out_put;
715 }
716
717 xfs_qm_scall_getquota_fill_qc(mp, type, dqp, dst);
718
719out_put:
720 xfs_qm_dqput(dqp);
721 return error;
722}
723
724
725
726
727
728int
729xfs_qm_scall_getquota_next(
730 struct xfs_mount *mp,
731 xfs_dqid_t *id,
732 xfs_dqtype_t type,
733 struct qc_dqblk *dst)
734{
735 struct xfs_dquot *dqp;
736 int error;
737
738 error = xfs_qm_dqget_next(mp, *id, type, &dqp);
739 if (error)
740 return error;
741
742
743 *id = dqp->q_id;
744
745 xfs_qm_scall_getquota_fill_qc(mp, type, dqp, dst);
746
747 xfs_qm_dqput(dqp);
748 return error;
749}
750
751STATIC int
752xfs_dqrele_inode(
753 struct xfs_inode *ip,
754 void *args)
755{
756 uint *flags = args;
757
758
759 if (ip == ip->i_mount->m_quotainfo->qi_uquotaip ||
760 ip == ip->i_mount->m_quotainfo->qi_gquotaip ||
761 ip == ip->i_mount->m_quotainfo->qi_pquotaip) {
762 ASSERT(ip->i_udquot == NULL);
763 ASSERT(ip->i_gdquot == NULL);
764 ASSERT(ip->i_pdquot == NULL);
765 return 0;
766 }
767
768 xfs_ilock(ip, XFS_ILOCK_EXCL);
769 if ((*flags & XFS_UQUOTA_ACCT) && ip->i_udquot) {
770 xfs_qm_dqrele(ip->i_udquot);
771 ip->i_udquot = NULL;
772 }
773 if ((*flags & XFS_GQUOTA_ACCT) && ip->i_gdquot) {
774 xfs_qm_dqrele(ip->i_gdquot);
775 ip->i_gdquot = NULL;
776 }
777 if ((*flags & XFS_PQUOTA_ACCT) && ip->i_pdquot) {
778 xfs_qm_dqrele(ip->i_pdquot);
779 ip->i_pdquot = NULL;
780 }
781 xfs_iunlock(ip, XFS_ILOCK_EXCL);
782 return 0;
783}
784
785
786
787
788
789
790
791
792void
793xfs_qm_dqrele_all_inodes(
794 struct xfs_mount *mp,
795 uint flags)
796{
797 ASSERT(mp->m_quotainfo);
798 xfs_inode_walk(mp, XFS_INODE_WALK_INEW_WAIT, xfs_dqrele_inode,
799 &flags, XFS_ICI_NO_TAG);
800}
801