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 60 : 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 60 : 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 60 : if (flags & XFS_ALL_QUOTA_ACCT)
42 28 : xfs_info(mp, "disabling of quota accounting not supported.");
43 :
44 60 : mutex_lock(&mp->m_quotainfo->qi_quotaofflock);
45 60 : mp->m_qflags &= ~(flags & XFS_ALL_QUOTA_ENFD);
46 60 : spin_lock(&mp->m_sb_lock);
47 60 : mp->m_sb.sb_qflags = mp->m_qflags;
48 60 : spin_unlock(&mp->m_sb_lock);
49 60 : mutex_unlock(&mp->m_quotainfo->qi_quotaofflock);
50 :
51 : /* XXX what to do if error ? Revert back to old vals incore ? */
52 60 : return xfs_sync_sb(mp, false);
53 : }
54 :
55 : STATIC int
56 24 : xfs_qm_scall_trunc_qfile(
57 : struct xfs_mount *mp,
58 : xfs_ino_t ino)
59 : {
60 24 : struct xfs_inode *ip;
61 24 : struct xfs_trans *tp;
62 24 : int error;
63 :
64 24 : if (ino == NULLFSINO)
65 : return 0;
66 :
67 24 : error = xfs_imeta_iget(mp, ino, XFS_DIR3_FT_REG_FILE, &ip);
68 24 : if (error)
69 : return error;
70 :
71 24 : xfs_ilock(ip, XFS_IOLOCK_EXCL);
72 :
73 24 : error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp);
74 24 : if (error) {
75 0 : xfs_iunlock(ip, XFS_IOLOCK_EXCL);
76 0 : goto out_put;
77 : }
78 :
79 24 : xfs_ilock(ip, XFS_ILOCK_EXCL);
80 24 : xfs_trans_ijoin(tp, ip, 0);
81 :
82 24 : ip->i_disk_size = 0;
83 24 : xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
84 :
85 24 : error = xfs_itruncate_extents(&tp, ip, XFS_DATA_FORK, 0);
86 24 : if (error) {
87 0 : xfs_trans_cancel(tp);
88 0 : goto out_unlock;
89 : }
90 :
91 24 : ASSERT(ip->i_df.if_nextents == 0);
92 :
93 24 : xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
94 24 : error = xfs_trans_commit(tp);
95 :
96 24 : out_unlock:
97 24 : xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
98 24 : out_put:
99 24 : xfs_irele(ip);
100 24 : return error;
101 : }
102 :
103 : int
104 24 : xfs_qm_scall_trunc_qfiles(
105 : xfs_mount_t *mp,
106 : uint flags)
107 : {
108 24 : int error = -EINVAL;
109 :
110 24 : if (!xfs_has_quota(mp) || flags == 0 ||
111 24 : (flags & ~XFS_QMOPT_QUOTALL)) {
112 0 : xfs_debug(mp, "%s: flags=%x m_qflags=%x",
113 : __func__, flags, mp->m_qflags);
114 0 : return -EINVAL;
115 : }
116 :
117 24 : if (flags & XFS_QMOPT_UQUOTA) {
118 12 : error = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_uquotino);
119 12 : if (error)
120 : return error;
121 : }
122 24 : if (flags & XFS_QMOPT_GQUOTA) {
123 8 : error = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_gquotino);
124 8 : if (error)
125 : return error;
126 : }
127 24 : if (flags & XFS_QMOPT_PQUOTA)
128 4 : 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 14 : xfs_qm_scall_quotaon(
140 : xfs_mount_t *mp,
141 : uint flags)
142 : {
143 14 : int error;
144 14 : uint qf;
145 :
146 : /*
147 : * Switching on quota accounting must be done at mount time,
148 : * only consider quota enforcement stuff here.
149 : */
150 14 : flags &= XFS_ALL_QUOTA_ENFD;
151 :
152 14 : 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 14 : if (((mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) == 0 &&
164 14 : (flags & XFS_UQUOTA_ENFD)) ||
165 8 : ((mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) == 0 &&
166 14 : (flags & XFS_GQUOTA_ENFD)) ||
167 12 : ((mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) == 0 &&
168 12 : (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 14 : 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 14 : spin_lock(&mp->m_sb_lock);
185 14 : qf = mp->m_sb.sb_qflags;
186 14 : mp->m_sb.sb_qflags = qf | flags;
187 14 : spin_unlock(&mp->m_sb_lock);
188 :
189 : /*
190 : * There's nothing to change if it's the same.
191 : */
192 14 : if ((qf & flags) == flags)
193 : return -EEXIST;
194 :
195 14 : error = xfs_sync_sb(mp, false);
196 14 : if (error)
197 : return error;
198 : /*
199 : * If we aren't trying to switch on quota enforcement, we are done.
200 : */
201 14 : if (((mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) !=
202 14 : (mp->m_qflags & XFS_UQUOTA_ACCT)) ||
203 : ((mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) !=
204 14 : (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 14 : if (!XFS_IS_QUOTA_ON(mp))
210 : return -ESRCH;
211 :
212 : /*
213 : * Switch on quota enforcement in core.
214 : */
215 14 : mutex_lock(&mp->m_quotainfo->qi_quotaofflock);
216 14 : mp->m_qflags |= (flags & XFS_ALL_QUOTA_ENFD);
217 14 : mutex_unlock(&mp->m_quotainfo->qi_quotaofflock);
218 :
219 14 : 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 61708 : 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 61708 : 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 61708 : res->hardlimit = hard;
245 61708 : res->softlimit = soft;
246 61708 : if (qlim) {
247 6042 : qlim->hard = hard;
248 6042 : qlim->soft = soft;
249 : }
250 :
251 : return true;
252 : }
253 :
254 : static inline void
255 5647 : 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 5647 : if (qlim) {
262 : /* Set the length of the default grace period. */
263 5573 : res->timer = xfs_dquot_set_grace_period(timer);
264 5576 : qlim->time = res->timer;
265 : } else {
266 : /* Set the grace period expiration on a quota. */
267 74 : res->timer = xfs_dquot_set_timeout(mp, timer);
268 : }
269 5650 : }
270 :
271 : /*
272 : * Adjust quota limits, and start/stop timers accordingly.
273 : */
274 : int
275 22551 : 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 22551 : struct xfs_quotainfo *q = mp->m_quotainfo;
282 22551 : struct xfs_dquot *dqp;
283 22551 : struct xfs_trans *tp;
284 22551 : struct xfs_def_quota *defq;
285 22551 : struct xfs_dquot_res *res;
286 22551 : struct xfs_quota_limits *qlim;
287 22551 : int error;
288 22551 : xfs_qcnt_t hard, soft;
289 :
290 22551 : if (newlim->d_fieldmask & ~XFS_QC_MASK)
291 : return -EINVAL;
292 22551 : 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 20683 : error = xfs_qm_dqget(mp, id, type, true, &dqp);
303 20708 : if (error) {
304 0 : ASSERT(error != -ENOENT);
305 0 : return error;
306 : }
307 :
308 20708 : defq = xfs_get_defquota(q, xfs_dquot_type(dqp));
309 20707 : xfs_dqunlock(dqp);
310 :
311 20673 : error = xfs_trans_alloc(mp, &M_RES(mp)->tr_qm_setqlim, 0, 0, 0, &tp);
312 20678 : if (error)
313 0 : goto out_rele;
314 :
315 20678 : xfs_dqlock(dqp);
316 20680 : 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 20571 : hard = (newlim->d_fieldmask & QC_SPC_HARD) ?
337 20571 : (xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_spc_hardlimit) :
338 1963 : dqp->q_blk.hardlimit;
339 20571 : soft = (newlim->d_fieldmask & QC_SPC_SOFT) ?
340 20571 : (xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_spc_softlimit) :
341 1967 : dqp->q_blk.softlimit;
342 20571 : res = &dqp->q_blk;
343 20571 : qlim = id == 0 ? &defq->blk : NULL;
344 :
345 20571 : if (xfs_setqlim_limits(mp, res, qlim, hard, soft, "blk"))
346 20594 : xfs_dquot_set_prealloc_limits(dqp);
347 20585 : if (newlim->d_fieldmask & QC_SPC_TIMER)
348 1888 : xfs_setqlim_timer(mp, res, qlim, newlim->d_spc_timer);
349 :
350 : /* Blocks on the realtime device. */
351 20584 : hard = (newlim->d_fieldmask & QC_RT_SPC_HARD) ?
352 20584 : (xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_rt_spc_hardlimit) :
353 20584 : dqp->q_rtb.hardlimit;
354 20584 : soft = (newlim->d_fieldmask & QC_RT_SPC_SOFT) ?
355 20584 : (xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_rt_spc_softlimit) :
356 20584 : dqp->q_rtb.softlimit;
357 20584 : res = &dqp->q_rtb;
358 20584 : qlim = id == 0 ? &defq->rtb : NULL;
359 :
360 20584 : xfs_setqlim_limits(mp, res, qlim, hard, soft, "rtb");
361 20695 : if (newlim->d_fieldmask & QC_RT_SPC_TIMER)
362 1872 : xfs_setqlim_timer(mp, res, qlim, newlim->d_rt_spc_timer);
363 :
364 : /* Inodes */
365 20695 : hard = (newlim->d_fieldmask & QC_INO_HARD) ?
366 20695 : (xfs_qcnt_t) newlim->d_ino_hardlimit :
367 1987 : dqp->q_ino.hardlimit;
368 20695 : soft = (newlim->d_fieldmask & QC_INO_SOFT) ?
369 20695 : (xfs_qcnt_t) newlim->d_ino_softlimit :
370 1983 : dqp->q_ino.softlimit;
371 20695 : res = &dqp->q_ino;
372 20695 : qlim = id == 0 ? &defq->ino : NULL;
373 :
374 20695 : xfs_setqlim_limits(mp, res, qlim, hard, soft, "ino");
375 20584 : if (newlim->d_fieldmask & QC_INO_TIMER)
376 1889 : xfs_setqlim_timer(mp, res, qlim, newlim->d_ino_timer);
377 :
378 20585 : 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 18552 : xfs_qm_adjust_dqtimers(dqp);
387 : }
388 20595 : dqp->q_flags |= XFS_DQFLAG_DIRTY;
389 20595 : xfs_trans_log_dquot(tp, dqp);
390 :
391 20556 : error = xfs_trans_commit(tp);
392 :
393 20517 : out_rele:
394 20517 : xfs_qm_dqrele(dqp);
395 20517 : return error;
396 : }
397 :
398 : /* Fill out the quota context. */
399 : static void
400 66389 : 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 66389 : memset(dst, 0, sizeof(*dst));
407 66389 : dst->d_spc_hardlimit = XFS_FSB_TO_B(mp, dqp->q_blk.hardlimit);
408 66389 : dst->d_spc_softlimit = XFS_FSB_TO_B(mp, dqp->q_blk.softlimit);
409 66389 : dst->d_ino_hardlimit = dqp->q_ino.hardlimit;
410 66389 : dst->d_ino_softlimit = dqp->q_ino.softlimit;
411 66389 : dst->d_space = XFS_FSB_TO_B(mp, dqp->q_blk.reserved);
412 66389 : dst->d_ino_count = dqp->q_ino.reserved;
413 66389 : dst->d_spc_timer = dqp->q_blk.timer;
414 66389 : dst->d_ino_timer = dqp->q_ino.timer;
415 66389 : dst->d_ino_warns = 0;
416 66389 : dst->d_spc_warns = 0;
417 66389 : dst->d_rt_spc_hardlimit = XFS_FSB_TO_B(mp, dqp->q_rtb.hardlimit);
418 66389 : dst->d_rt_spc_softlimit = XFS_FSB_TO_B(mp, dqp->q_rtb.softlimit);
419 66389 : dst->d_rt_space = XFS_FSB_TO_B(mp, dqp->q_rtb.reserved);
420 66389 : dst->d_rt_spc_timer = dqp->q_rtb.timer;
421 66389 : 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 66389 : if (!xfs_dquot_is_enforced(dqp)) {
429 204 : dst->d_spc_timer = 0;
430 204 : dst->d_ino_timer = 0;
431 204 : dst->d_rt_spc_timer = 0;
432 : }
433 :
434 : #ifdef DEBUG
435 66389 : if (xfs_dquot_is_enforced(dqp) && dqp->q_id != 0) {
436 64780 : if ((dst->d_space > dst->d_spc_softlimit) &&
437 : (dst->d_spc_softlimit > 0)) {
438 335 : ASSERT(dst->d_spc_timer != 0);
439 : }
440 64780 : if ((dst->d_ino_count > dqp->q_ino.softlimit) &&
441 : (dqp->q_ino.softlimit > 0)) {
442 302 : ASSERT(dst->d_ino_timer != 0);
443 : }
444 : }
445 : #endif
446 66389 : }
447 :
448 : /* Return the quota information for the dquot matching id. */
449 : int
450 19438 : 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 19438 : struct xfs_dquot *dqp;
457 19438 : 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 19438 : if (id == 0)
464 173 : 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 19438 : error = xfs_qm_dqget(mp, id, type, false, &dqp);
471 19568 : 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 11183 : if (XFS_IS_DQUOT_UNINITIALIZED(dqp)) {
479 6329 : error = -ENOENT;
480 6329 : goto out_put;
481 : }
482 :
483 4854 : xfs_qm_scall_getquota_fill_qc(mp, type, dqp, dst);
484 :
485 11183 : out_put:
486 11183 : xfs_qm_dqput(dqp);
487 11183 : 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 62631 : 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 62631 : struct xfs_dquot *dqp;
502 62631 : int error;
503 :
504 : /* Flush inodegc work at the start of a quota reporting scan. */
505 62631 : if (*id == 0)
506 1398 : xfs_inodegc_push(mp);
507 :
508 62631 : error = xfs_qm_dqget_next(mp, *id, type, &dqp);
509 62631 : if (error)
510 : return error;
511 :
512 : /* Fill in the ID we actually read from disk */
513 61535 : *id = dqp->q_id;
514 :
515 61535 : xfs_qm_scall_getquota_fill_qc(mp, type, dqp, dst);
516 :
517 61535 : xfs_qm_dqput(dqp);
518 61535 : return error;
519 : }
|