Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0
2 : /*
3 : * Copyright (c) 2000-2005 Silicon Graphics, Inc.
4 : * All Rights Reserved.
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 : #include "xfs_imeta.h"
22 : #include "xfs_da_format.h"
23 :
24 : int
25 328 : xfs_qm_scall_quotaoff(
26 : xfs_mount_t *mp,
27 : uint flags)
28 : {
29 : /*
30 : * No file system can have quotas enabled on disk but not in core.
31 : * Note that quota utilities (like quotaoff) _expect_
32 : * errno == -EEXIST here.
33 : */
34 328 : if ((mp->m_qflags & flags) == 0)
35 : return -EEXIST;
36 :
37 : /*
38 : * We do not support actually turning off quota accounting any more.
39 : * Just log a warning and ignore the accounting related flags.
40 : */
41 328 : if (flags & XFS_ALL_QUOTA_ACCT)
42 152 : xfs_info(mp, "disabling of quota accounting not supported.");
43 :
44 328 : mutex_lock(&mp->m_quotainfo->qi_quotaofflock);
45 328 : mp->m_qflags &= ~(flags & XFS_ALL_QUOTA_ENFD);
46 328 : spin_lock(&mp->m_sb_lock);
47 328 : mp->m_sb.sb_qflags = mp->m_qflags;
48 328 : spin_unlock(&mp->m_sb_lock);
49 328 : mutex_unlock(&mp->m_quotainfo->qi_quotaofflock);
50 :
51 : /* XXX what to do if error ? Revert back to old vals incore ? */
52 328 : return xfs_sync_sb(mp, false);
53 : }
54 :
55 : STATIC int
56 132 : xfs_qm_scall_trunc_qfile(
57 : struct xfs_mount *mp,
58 : xfs_ino_t ino)
59 : {
60 132 : struct xfs_inode *ip;
61 132 : struct xfs_trans *tp;
62 132 : int error;
63 :
64 132 : if (ino == NULLFSINO)
65 : return 0;
66 :
67 132 : error = xfs_imeta_iget(mp, ino, XFS_DIR3_FT_REG_FILE, &ip);
68 132 : if (error)
69 : return error;
70 :
71 132 : xfs_ilock(ip, XFS_IOLOCK_EXCL);
72 :
73 132 : error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp);
74 132 : if (error) {
75 0 : xfs_iunlock(ip, XFS_IOLOCK_EXCL);
76 0 : goto out_put;
77 : }
78 :
79 132 : xfs_ilock(ip, XFS_ILOCK_EXCL);
80 132 : xfs_trans_ijoin(tp, ip, 0);
81 :
82 132 : ip->i_disk_size = 0;
83 132 : xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
84 :
85 132 : error = xfs_itruncate_extents(&tp, ip, XFS_DATA_FORK, 0);
86 132 : if (error) {
87 0 : xfs_trans_cancel(tp);
88 0 : goto out_unlock;
89 : }
90 :
91 132 : ASSERT(ip->i_df.if_nextents == 0);
92 :
93 132 : xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
94 132 : error = xfs_trans_commit(tp);
95 :
96 132 : out_unlock:
97 132 : xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
98 132 : out_put:
99 132 : xfs_irele(ip);
100 132 : return error;
101 : }
102 :
103 : int
104 133 : xfs_qm_scall_trunc_qfiles(
105 : xfs_mount_t *mp,
106 : uint flags)
107 : {
108 133 : int error = -EINVAL;
109 :
110 133 : if (!xfs_has_quota(mp) || flags == 0 ||
111 132 : (flags & ~XFS_QMOPT_QUOTALL)) {
112 1 : xfs_debug(mp, "%s: flags=%x m_qflags=%x",
113 : __func__, flags, mp->m_qflags);
114 1 : return -EINVAL;
115 : }
116 :
117 132 : if (flags & XFS_QMOPT_UQUOTA) {
118 66 : error = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_uquotino);
119 66 : if (error)
120 : return error;
121 : }
122 132 : if (flags & XFS_QMOPT_GQUOTA) {
123 44 : error = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_gquotino);
124 44 : if (error)
125 : return error;
126 : }
127 132 : if (flags & XFS_QMOPT_PQUOTA)
128 22 : error = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_pquotino);
129 :
130 : return error;
131 : }
132 :
133 : /*
134 : * Switch on (a given) quota enforcement for a filesystem. This takes
135 : * effect immediately.
136 : * (Switching on quota accounting must be done at mount time.)
137 : */
138 : int
139 77 : xfs_qm_scall_quotaon(
140 : xfs_mount_t *mp,
141 : uint flags)
142 : {
143 77 : int error;
144 77 : uint qf;
145 :
146 : /*
147 : * Switching on quota accounting must be done at mount time,
148 : * only consider quota enforcement stuff here.
149 : */
150 77 : flags &= XFS_ALL_QUOTA_ENFD;
151 :
152 77 : if (flags == 0) {
153 0 : xfs_debug(mp, "%s: zero flags, m_qflags=%x",
154 : __func__, mp->m_qflags);
155 0 : return -EINVAL;
156 : }
157 :
158 : /*
159 : * Can't enforce without accounting. We check the superblock
160 : * qflags here instead of m_qflags because rootfs can have
161 : * quota acct on ondisk without m_qflags' knowing.
162 : */
163 77 : if (((mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) == 0 &&
164 77 : (flags & XFS_UQUOTA_ENFD)) ||
165 44 : ((mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) == 0 &&
166 77 : (flags & XFS_GQUOTA_ENFD)) ||
167 66 : ((mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) == 0 &&
168 66 : (flags & XFS_PQUOTA_ENFD))) {
169 0 : xfs_debug(mp,
170 : "%s: Can't enforce without acct, flags=%x sbflags=%x",
171 : __func__, flags, mp->m_sb.sb_qflags);
172 0 : return -EINVAL;
173 : }
174 : /*
175 : * If everything's up to-date incore, then don't waste time.
176 : */
177 77 : if ((mp->m_qflags & flags) == flags)
178 : return -EEXIST;
179 :
180 : /*
181 : * Change sb_qflags on disk but not incore mp->qflags
182 : * if this is the root filesystem.
183 : */
184 77 : spin_lock(&mp->m_sb_lock);
185 77 : qf = mp->m_sb.sb_qflags;
186 77 : mp->m_sb.sb_qflags = qf | flags;
187 77 : spin_unlock(&mp->m_sb_lock);
188 :
189 : /*
190 : * There's nothing to change if it's the same.
191 : */
192 77 : if ((qf & flags) == flags)
193 : return -EEXIST;
194 :
195 77 : error = xfs_sync_sb(mp, false);
196 77 : if (error)
197 : return error;
198 : /*
199 : * If we aren't trying to switch on quota enforcement, we are done.
200 : */
201 77 : if (((mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) !=
202 77 : (mp->m_qflags & XFS_UQUOTA_ACCT)) ||
203 : ((mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) !=
204 77 : (mp->m_qflags & XFS_PQUOTA_ACCT)) ||
205 : ((mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) !=
206 : (mp->m_qflags & XFS_GQUOTA_ACCT)))
207 : return 0;
208 :
209 77 : if (!XFS_IS_QUOTA_ON(mp))
210 : return -ESRCH;
211 :
212 : /*
213 : * Switch on quota enforcement in core.
214 : */
215 77 : mutex_lock(&mp->m_quotainfo->qi_quotaofflock);
216 77 : mp->m_qflags |= (flags & XFS_ALL_QUOTA_ENFD);
217 77 : mutex_unlock(&mp->m_quotainfo->qi_quotaofflock);
218 :
219 77 : return 0;
220 : }
221 :
222 : #define XFS_QC_MASK (QC_LIMIT_MASK | QC_TIMER_MASK)
223 :
224 : /*
225 : * Adjust limits of this quota, and the defaults if passed in. Returns true
226 : * if the new limits made sense and were applied, false otherwise.
227 : */
228 : static inline bool
229 340513 : xfs_setqlim_limits(
230 : struct xfs_mount *mp,
231 : struct xfs_dquot_res *res,
232 : struct xfs_quota_limits *qlim,
233 : xfs_qcnt_t hard,
234 : xfs_qcnt_t soft,
235 : const char *tag)
236 : {
237 : /* The hard limit can't be less than the soft limit. */
238 340513 : if (hard != 0 && hard < soft) {
239 0 : xfs_debug(mp, "%shard %lld < %ssoft %lld", tag, hard, tag,
240 : soft);
241 0 : return false;
242 : }
243 :
244 340513 : res->hardlimit = hard;
245 340513 : res->softlimit = soft;
246 340513 : if (qlim) {
247 32719 : qlim->hard = hard;
248 32719 : qlim->soft = soft;
249 : }
250 :
251 : return true;
252 : }
253 :
254 : static inline void
255 30537 : xfs_setqlim_timer(
256 : struct xfs_mount *mp,
257 : struct xfs_dquot_res *res,
258 : struct xfs_quota_limits *qlim,
259 : s64 timer)
260 : {
261 30537 : if (qlim) {
262 : /* Set the length of the default grace period. */
263 30125 : res->timer = xfs_dquot_set_grace_period(timer);
264 30120 : qlim->time = res->timer;
265 : } else {
266 : /* Set the grace period expiration on a quota. */
267 412 : res->timer = xfs_dquot_set_timeout(mp, timer);
268 : }
269 30532 : }
270 :
271 : /*
272 : * Adjust quota limits, and start/stop timers accordingly.
273 : */
274 : int
275 123675 : xfs_qm_scall_setqlim(
276 : struct xfs_mount *mp,
277 : xfs_dqid_t id,
278 : xfs_dqtype_t type,
279 : struct qc_dqblk *newlim)
280 : {
281 123675 : struct xfs_quotainfo *q = mp->m_quotainfo;
282 123675 : struct xfs_dquot *dqp;
283 123675 : struct xfs_trans *tp;
284 123675 : struct xfs_def_quota *defq;
285 123675 : struct xfs_dquot_res *res;
286 123675 : struct xfs_quota_limits *qlim;
287 123675 : int error;
288 123675 : xfs_qcnt_t hard, soft;
289 :
290 123675 : if (newlim->d_fieldmask & ~XFS_QC_MASK)
291 : return -EINVAL;
292 123675 : if ((newlim->d_fieldmask & XFS_QC_MASK) == 0)
293 : return 0;
294 :
295 : /*
296 : * Get the dquot (locked) before we start, as we need to do a
297 : * transaction to allocate it if it doesn't exist. Once we have the
298 : * dquot, unlock it so we can start the next transaction safely. We hold
299 : * a reference to the dquot, so it's safe to do this unlock/lock without
300 : * it being reclaimed in the mean time.
301 : */
302 113530 : error = xfs_qm_dqget(mp, id, type, true, &dqp);
303 113935 : if (error) {
304 0 : ASSERT(error != -ENOENT);
305 0 : return error;
306 : }
307 :
308 113935 : defq = xfs_get_defquota(q, xfs_dquot_type(dqp));
309 113918 : xfs_dqunlock(dqp);
310 :
311 113931 : error = xfs_trans_alloc(mp, &M_RES(mp)->tr_qm_setqlim, 0, 0, 0, &tp);
312 113575 : if (error)
313 0 : goto out_rele;
314 :
315 113575 : xfs_dqlock(dqp);
316 113711 : xfs_trans_dqjoin(tp, dqp);
317 :
318 : /*
319 : * Update quota limits, warnings, and timers, and the defaults
320 : * if we're touching id == 0.
321 : *
322 : * Make sure that hardlimits are >= soft limits before changing.
323 : *
324 : * Update warnings counter(s) if requested.
325 : *
326 : * Timelimits for the super user set the relative time the other users
327 : * can be over quota for this file system. If it is zero a default is
328 : * used. Ditto for the default soft and hard limit values (already
329 : * done, above), and for warnings.
330 : *
331 : * For other IDs, userspace can bump out the grace period if over
332 : * the soft limit.
333 : */
334 :
335 : /* Blocks on the data device. */
336 113651 : hard = (newlim->d_fieldmask & QC_SPC_HARD) ?
337 113651 : (xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_spc_hardlimit) :
338 10663 : dqp->q_blk.hardlimit;
339 113651 : soft = (newlim->d_fieldmask & QC_SPC_SOFT) ?
340 113651 : (xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_spc_softlimit) :
341 10718 : dqp->q_blk.softlimit;
342 113651 : res = &dqp->q_blk;
343 113651 : qlim = id == 0 ? &defq->blk : NULL;
344 :
345 113651 : if (xfs_setqlim_limits(mp, res, qlim, hard, soft, "blk"))
346 113587 : xfs_dquot_set_prealloc_limits(dqp);
347 113497 : if (newlim->d_fieldmask & QC_SPC_TIMER)
348 10195 : xfs_setqlim_timer(mp, res, qlim, newlim->d_spc_timer);
349 :
350 : /* Blocks on the realtime device. */
351 113493 : hard = (newlim->d_fieldmask & QC_RT_SPC_HARD) ?
352 113493 : (xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_rt_spc_hardlimit) :
353 113458 : dqp->q_rtb.hardlimit;
354 113493 : soft = (newlim->d_fieldmask & QC_RT_SPC_SOFT) ?
355 113493 : (xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_rt_spc_softlimit) :
356 113463 : dqp->q_rtb.softlimit;
357 113493 : res = &dqp->q_rtb;
358 113493 : qlim = id == 0 ? &defq->rtb : NULL;
359 :
360 113493 : xfs_setqlim_limits(mp, res, qlim, hard, soft, "rtb");
361 113480 : if (newlim->d_fieldmask & QC_RT_SPC_TIMER)
362 10129 : xfs_setqlim_timer(mp, res, qlim, newlim->d_rt_spc_timer);
363 :
364 : /* Inodes */
365 113480 : hard = (newlim->d_fieldmask & QC_INO_HARD) ?
366 113480 : (xfs_qcnt_t) newlim->d_ino_hardlimit :
367 10797 : dqp->q_ino.hardlimit;
368 113480 : soft = (newlim->d_fieldmask & QC_INO_SOFT) ?
369 113480 : (xfs_qcnt_t) newlim->d_ino_softlimit :
370 10790 : dqp->q_ino.softlimit;
371 113480 : res = &dqp->q_ino;
372 113480 : qlim = id == 0 ? &defq->ino : NULL;
373 :
374 113480 : xfs_setqlim_limits(mp, res, qlim, hard, soft, "ino");
375 113494 : if (newlim->d_fieldmask & QC_INO_TIMER)
376 10214 : xfs_setqlim_timer(mp, res, qlim, newlim->d_ino_timer);
377 :
378 113497 : if (id != 0) {
379 : /*
380 : * If the user is now over quota, start the timelimit.
381 : * The user will not be 'warned'.
382 : * Note that we keep the timers ticking, whether enforcement
383 : * is on or off. We don't really want to bother with iterating
384 : * over all ondisk dquots and turning the timers on/off.
385 : */
386 102613 : xfs_qm_adjust_dqtimers(dqp);
387 : }
388 113583 : dqp->q_flags |= XFS_DQFLAG_DIRTY;
389 113583 : xfs_trans_log_dquot(tp, dqp);
390 :
391 113760 : error = xfs_trans_commit(tp);
392 :
393 113821 : out_rele:
394 113821 : xfs_qm_dqrele(dqp);
395 113821 : return error;
396 : }
397 :
398 : /* Fill out the quota context. */
399 : static void
400 630013 : xfs_qm_scall_getquota_fill_qc(
401 : struct xfs_mount *mp,
402 : xfs_dqtype_t type,
403 : const struct xfs_dquot *dqp,
404 : struct qc_dqblk *dst)
405 : {
406 630013 : memset(dst, 0, sizeof(*dst));
407 630013 : dst->d_spc_hardlimit = XFS_FSB_TO_B(mp, dqp->q_blk.hardlimit);
408 630013 : dst->d_spc_softlimit = XFS_FSB_TO_B(mp, dqp->q_blk.softlimit);
409 630013 : dst->d_ino_hardlimit = dqp->q_ino.hardlimit;
410 630013 : dst->d_ino_softlimit = dqp->q_ino.softlimit;
411 630013 : dst->d_space = XFS_FSB_TO_B(mp, dqp->q_blk.reserved);
412 630013 : dst->d_ino_count = dqp->q_ino.reserved;
413 630013 : dst->d_spc_timer = dqp->q_blk.timer;
414 630013 : dst->d_ino_timer = dqp->q_ino.timer;
415 630013 : dst->d_ino_warns = 0;
416 630013 : dst->d_spc_warns = 0;
417 630013 : dst->d_rt_spc_hardlimit = XFS_FSB_TO_B(mp, dqp->q_rtb.hardlimit);
418 630013 : dst->d_rt_spc_softlimit = XFS_FSB_TO_B(mp, dqp->q_rtb.softlimit);
419 630013 : dst->d_rt_space = XFS_FSB_TO_B(mp, dqp->q_rtb.reserved);
420 630013 : dst->d_rt_spc_timer = dqp->q_rtb.timer;
421 630013 : dst->d_rt_spc_warns = 0;
422 :
423 : /*
424 : * Internally, we don't reset all the timers when quota enforcement
425 : * gets turned off. No need to confuse the user level code,
426 : * so return zeroes in that case.
427 : */
428 630013 : if (!xfs_dquot_is_enforced(dqp)) {
429 1122 : dst->d_spc_timer = 0;
430 1122 : dst->d_ino_timer = 0;
431 1122 : dst->d_rt_spc_timer = 0;
432 : }
433 :
434 : #ifdef DEBUG
435 630013 : if (xfs_dquot_is_enforced(dqp) && dqp->q_id != 0) {
436 621495 : if ((dst->d_space > dst->d_spc_softlimit) &&
437 : (dst->d_spc_softlimit > 0)) {
438 1837 : ASSERT(dst->d_spc_timer != 0);
439 : }
440 621495 : if ((dst->d_ino_count > dqp->q_ino.softlimit) &&
441 : (dqp->q_ino.softlimit > 0)) {
442 1661 : ASSERT(dst->d_ino_timer != 0);
443 : }
444 : }
445 : #endif
446 630013 : }
447 :
448 : /* Return the quota information for the dquot matching id. */
449 : int
450 107915 : xfs_qm_scall_getquota(
451 : struct xfs_mount *mp,
452 : xfs_dqid_t id,
453 : xfs_dqtype_t type,
454 : struct qc_dqblk *dst)
455 : {
456 107915 : struct xfs_dquot *dqp;
457 107915 : int error;
458 :
459 : /*
460 : * Expedite pending inodegc work at the start of a quota reporting
461 : * scan but don't block waiting for it to complete.
462 : */
463 107915 : if (id == 0)
464 989 : xfs_inodegc_push(mp);
465 :
466 : /*
467 : * Try to get the dquot. We don't want it allocated on disk, so don't
468 : * set doalloc. If it doesn't exist, we'll get ENOENT back.
469 : */
470 107916 : error = xfs_qm_dqget(mp, id, type, false, &dqp);
471 108026 : if (error)
472 : return error;
473 :
474 : /*
475 : * If everything's NULL, this dquot doesn't quite exist as far as
476 : * our utility programs are concerned.
477 : */
478 58824 : if (XFS_IS_DQUOT_UNINITIALIZED(dqp)) {
479 31912 : error = -ENOENT;
480 31912 : goto out_put;
481 : }
482 :
483 26912 : xfs_qm_scall_getquota_fill_qc(mp, type, dqp, dst);
484 :
485 58823 : out_put:
486 58823 : xfs_qm_dqput(dqp);
487 58823 : return error;
488 : }
489 :
490 : /*
491 : * Return the quota information for the first initialized dquot whose id
492 : * is at least as high as id.
493 : */
494 : int
495 608839 : xfs_qm_scall_getquota_next(
496 : struct xfs_mount *mp,
497 : xfs_dqid_t *id,
498 : xfs_dqtype_t type,
499 : struct qc_dqblk *dst)
500 : {
501 608839 : struct xfs_dquot *dqp;
502 608839 : int error;
503 :
504 : /* Flush inodegc work at the start of a quota reporting scan. */
505 608839 : if (*id == 0)
506 7319 : xfs_inodegc_push(mp);
507 :
508 608839 : error = xfs_qm_dqget_next(mp, *id, type, &dqp);
509 608839 : if (error)
510 : return error;
511 :
512 : /* Fill in the ID we actually read from disk */
513 603102 : *id = dqp->q_id;
514 :
515 603102 : xfs_qm_scall_getquota_fill_qc(mp, type, dqp, dst);
516 :
517 603102 : xfs_qm_dqput(dqp);
518 603102 : return error;
519 : }
|