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