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 168 : 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 168 : 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 168 : if (flags & XFS_ALL_QUOTA_ACCT)
40 72 : xfs_info(mp, "disabling of quota accounting not supported.");
41 :
42 168 : mutex_lock(&mp->m_quotainfo->qi_quotaofflock);
43 168 : mp->m_qflags &= ~(flags & XFS_ALL_QUOTA_ENFD);
44 168 : spin_lock(&mp->m_sb_lock);
45 168 : mp->m_sb.sb_qflags = mp->m_qflags;
46 168 : spin_unlock(&mp->m_sb_lock);
47 168 : mutex_unlock(&mp->m_quotainfo->qi_quotaofflock);
48 :
49 : /* XXX what to do if error ? Revert back to old vals incore ? */
50 168 : return xfs_sync_sb(mp, false);
51 : }
52 :
53 : STATIC int
54 72 : xfs_qm_scall_trunc_qfile(
55 : struct xfs_mount *mp,
56 : xfs_ino_t ino)
57 : {
58 72 : struct xfs_inode *ip;
59 72 : struct xfs_trans *tp;
60 72 : int error;
61 :
62 72 : if (ino == NULLFSINO)
63 : return 0;
64 :
65 72 : error = xfs_iget(mp, NULL, ino, 0, 0, &ip);
66 72 : if (error)
67 : return error;
68 :
69 72 : xfs_ilock(ip, XFS_IOLOCK_EXCL);
70 :
71 72 : error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp);
72 72 : if (error) {
73 0 : xfs_iunlock(ip, XFS_IOLOCK_EXCL);
74 0 : goto out_put;
75 : }
76 :
77 72 : xfs_ilock(ip, XFS_ILOCK_EXCL);
78 72 : xfs_trans_ijoin(tp, ip, 0);
79 :
80 72 : ip->i_disk_size = 0;
81 72 : xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
82 :
83 72 : error = xfs_itruncate_extents(&tp, ip, XFS_DATA_FORK, 0);
84 72 : if (error) {
85 0 : xfs_trans_cancel(tp);
86 0 : goto out_unlock;
87 : }
88 :
89 72 : ASSERT(ip->i_df.if_nextents == 0);
90 :
91 72 : xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
92 72 : error = xfs_trans_commit(tp);
93 :
94 72 : out_unlock:
95 72 : xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
96 72 : out_put:
97 72 : xfs_irele(ip);
98 72 : return error;
99 : }
100 :
101 : int
102 78 : xfs_qm_scall_trunc_qfiles(
103 : xfs_mount_t *mp,
104 : uint flags)
105 : {
106 78 : int error = -EINVAL;
107 :
108 78 : if (!xfs_has_quota(mp) || flags == 0 ||
109 72 : (flags & ~XFS_QMOPT_QUOTALL)) {
110 6 : xfs_debug(mp, "%s: flags=%x m_qflags=%x",
111 : __func__, flags, mp->m_qflags);
112 6 : return -EINVAL;
113 : }
114 :
115 72 : if (flags & XFS_QMOPT_UQUOTA) {
116 36 : error = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_uquotino);
117 36 : if (error)
118 : return error;
119 : }
120 72 : if (flags & XFS_QMOPT_GQUOTA) {
121 24 : error = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_gquotino);
122 24 : if (error)
123 : return error;
124 : }
125 72 : if (flags & XFS_QMOPT_PQUOTA)
126 12 : 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 42 : xfs_qm_scall_quotaon(
138 : xfs_mount_t *mp,
139 : uint flags)
140 : {
141 42 : int error;
142 42 : uint qf;
143 :
144 : /*
145 : * Switching on quota accounting must be done at mount time,
146 : * only consider quota enforcement stuff here.
147 : */
148 42 : flags &= XFS_ALL_QUOTA_ENFD;
149 :
150 42 : 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 42 : if (((mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) == 0 &&
162 42 : (flags & XFS_UQUOTA_ENFD)) ||
163 24 : ((mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) == 0 &&
164 42 : (flags & XFS_GQUOTA_ENFD)) ||
165 36 : ((mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) == 0 &&
166 36 : (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 42 : 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 42 : spin_lock(&mp->m_sb_lock);
183 42 : qf = mp->m_sb.sb_qflags;
184 42 : mp->m_sb.sb_qflags = qf | flags;
185 42 : spin_unlock(&mp->m_sb_lock);
186 :
187 : /*
188 : * There's nothing to change if it's the same.
189 : */
190 42 : if ((qf & flags) == flags)
191 : return -EEXIST;
192 :
193 42 : error = xfs_sync_sb(mp, false);
194 42 : if (error)
195 : return error;
196 : /*
197 : * If we aren't trying to switch on quota enforcement, we are done.
198 : */
199 42 : if (((mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) !=
200 42 : (mp->m_qflags & XFS_UQUOTA_ACCT)) ||
201 : ((mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) !=
202 42 : (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 42 : if (!XFS_IS_QUOTA_ON(mp))
208 : return -ESRCH;
209 :
210 : /*
211 : * Switch on quota enforcement in core.
212 : */
213 42 : mutex_lock(&mp->m_quotainfo->qi_quotaofflock);
214 42 : mp->m_qflags |= (flags & XFS_ALL_QUOTA_ENFD);
215 42 : mutex_unlock(&mp->m_quotainfo->qi_quotaofflock);
216 :
217 42 : 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 185697 : 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 185697 : 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 185697 : res->hardlimit = hard;
243 185697 : res->softlimit = soft;
244 185697 : if (qlim) {
245 18261 : qlim->hard = hard;
246 18261 : qlim->soft = soft;
247 : }
248 :
249 : return true;
250 : }
251 :
252 : static inline void
253 17206 : 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 17206 : if (qlim) {
260 : /* Set the length of the default grace period. */
261 16984 : res->timer = xfs_dquot_set_grace_period(timer);
262 16984 : qlim->time = res->timer;
263 : } else {
264 : /* Set the grace period expiration on a quota. */
265 222 : res->timer = xfs_dquot_set_timeout(mp, timer);
266 : }
267 17206 : }
268 :
269 : /*
270 : * Adjust quota limits, and start/stop timers accordingly.
271 : */
272 : int
273 67627 : 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 67627 : struct xfs_quotainfo *q = mp->m_quotainfo;
280 67627 : struct xfs_dquot *dqp;
281 67627 : struct xfs_trans *tp;
282 67627 : struct xfs_def_quota *defq;
283 67627 : struct xfs_dquot_res *res;
284 67627 : struct xfs_quota_limits *qlim;
285 67627 : int error;
286 67627 : xfs_qcnt_t hard, soft;
287 :
288 67627 : if (newlim->d_fieldmask & ~XFS_QC_MASK)
289 : return -EINVAL;
290 67627 : 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 61910 : error = xfs_qm_dqget(mp, id, type, true, &dqp);
301 62104 : if (error) {
302 0 : ASSERT(error != -ENOENT);
303 0 : return error;
304 : }
305 :
306 62104 : defq = xfs_get_defquota(q, xfs_dquot_type(dqp));
307 62100 : xfs_dqunlock(dqp);
308 :
309 62103 : error = xfs_trans_alloc(mp, &M_RES(mp)->tr_qm_setqlim, 0, 0, 0, &tp);
310 61929 : if (error)
311 0 : goto out_rele;
312 :
313 61929 : xfs_dqlock(dqp);
314 62037 : 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 61943 : hard = (newlim->d_fieldmask & QC_SPC_HARD) ?
335 61943 : (xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_spc_hardlimit) :
336 5978 : dqp->q_blk.hardlimit;
337 61943 : soft = (newlim->d_fieldmask & QC_SPC_SOFT) ?
338 61943 : (xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_spc_softlimit) :
339 5986 : dqp->q_blk.softlimit;
340 61943 : res = &dqp->q_blk;
341 61943 : qlim = id == 0 ? &defq->blk : NULL;
342 :
343 61943 : if (xfs_setqlim_limits(mp, res, qlim, hard, soft, "blk"))
344 61928 : xfs_dquot_set_prealloc_limits(dqp);
345 61867 : if (newlim->d_fieldmask & QC_SPC_TIMER)
346 5749 : xfs_setqlim_timer(mp, res, qlim, newlim->d_spc_timer);
347 :
348 : /* Blocks on the realtime device. */
349 61866 : hard = (newlim->d_fieldmask & QC_RT_SPC_HARD) ?
350 61866 : (xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_rt_spc_hardlimit) :
351 61866 : dqp->q_rtb.hardlimit;
352 61866 : soft = (newlim->d_fieldmask & QC_RT_SPC_SOFT) ?
353 61866 : (xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_rt_spc_softlimit) :
354 61866 : dqp->q_rtb.softlimit;
355 61866 : res = &dqp->q_rtb;
356 61866 : qlim = id == 0 ? &defq->rtb : NULL;
357 :
358 61866 : xfs_setqlim_limits(mp, res, qlim, hard, soft, "rtb");
359 61852 : if (newlim->d_fieldmask & QC_RT_SPC_TIMER)
360 5702 : xfs_setqlim_timer(mp, res, qlim, newlim->d_rt_spc_timer);
361 :
362 : /* Inodes */
363 61852 : hard = (newlim->d_fieldmask & QC_INO_HARD) ?
364 61852 : (xfs_qcnt_t) newlim->d_ino_hardlimit :
365 6030 : dqp->q_ino.hardlimit;
366 61852 : soft = (newlim->d_fieldmask & QC_INO_SOFT) ?
367 61852 : (xfs_qcnt_t) newlim->d_ino_softlimit :
368 5970 : dqp->q_ino.softlimit;
369 61852 : res = &dqp->q_ino;
370 61852 : qlim = id == 0 ? &defq->ino : NULL;
371 :
372 61852 : xfs_setqlim_limits(mp, res, qlim, hard, soft, "ino");
373 61924 : if (newlim->d_fieldmask & QC_INO_TIMER)
374 5755 : xfs_setqlim_timer(mp, res, qlim, newlim->d_ino_timer);
375 :
376 61925 : 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 55842 : xfs_qm_adjust_dqtimers(dqp);
385 : }
386 61935 : dqp->q_flags |= XFS_DQFLAG_DIRTY;
387 61935 : xfs_trans_log_dquot(tp, dqp);
388 :
389 62011 : error = xfs_trans_commit(tp);
390 :
391 62053 : out_rele:
392 62053 : xfs_qm_dqrele(dqp);
393 62053 : return error;
394 : }
395 :
396 : /* Fill out the quota context. */
397 : static void
398 317408 : 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 317408 : memset(dst, 0, sizeof(*dst));
405 317408 : dst->d_spc_hardlimit = XFS_FSB_TO_B(mp, dqp->q_blk.hardlimit);
406 317408 : dst->d_spc_softlimit = XFS_FSB_TO_B(mp, dqp->q_blk.softlimit);
407 317408 : dst->d_ino_hardlimit = dqp->q_ino.hardlimit;
408 317408 : dst->d_ino_softlimit = dqp->q_ino.softlimit;
409 317408 : dst->d_space = XFS_FSB_TO_B(mp, dqp->q_blk.reserved);
410 317408 : dst->d_ino_count = dqp->q_ino.reserved;
411 317408 : dst->d_spc_timer = dqp->q_blk.timer;
412 317408 : dst->d_ino_timer = dqp->q_ino.timer;
413 317408 : dst->d_ino_warns = 0;
414 317408 : dst->d_spc_warns = 0;
415 317408 : dst->d_rt_spc_hardlimit = XFS_FSB_TO_B(mp, dqp->q_rtb.hardlimit);
416 317408 : dst->d_rt_spc_softlimit = XFS_FSB_TO_B(mp, dqp->q_rtb.softlimit);
417 317408 : dst->d_rt_space = XFS_FSB_TO_B(mp, dqp->q_rtb.reserved);
418 317408 : dst->d_rt_spc_timer = dqp->q_rtb.timer;
419 317408 : 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 317408 : if (!xfs_dquot_is_enforced(dqp)) {
427 612 : dst->d_spc_timer = 0;
428 612 : dst->d_ino_timer = 0;
429 612 : dst->d_rt_spc_timer = 0;
430 : }
431 :
432 : #ifdef DEBUG
433 317408 : if (xfs_dquot_is_enforced(dqp) && dqp->q_id != 0) {
434 313023 : if ((dst->d_space > dst->d_spc_softlimit) &&
435 : (dst->d_spc_softlimit > 0)) {
436 1002 : ASSERT(dst->d_spc_timer != 0);
437 : }
438 313023 : if ((dst->d_ino_count > dqp->q_ino.softlimit) &&
439 : (dqp->q_ino.softlimit > 0)) {
440 906 : ASSERT(dst->d_ino_timer != 0);
441 : }
442 : }
443 : #endif
444 317408 : }
445 :
446 : /* Return the quota information for the dquot matching id. */
447 : int
448 58523 : 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 58523 : struct xfs_dquot *dqp;
455 58523 : 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 58523 : if (id == 0)
462 452 : 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 58523 : error = xfs_qm_dqget(mp, id, type, false, &dqp);
469 58601 : 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 31876 : if (XFS_IS_DQUOT_UNINITIALIZED(dqp)) {
477 17305 : error = -ENOENT;
478 17305 : goto out_put;
479 : }
480 :
481 14571 : xfs_qm_scall_getquota_fill_qc(mp, type, dqp, dst);
482 :
483 31876 : out_put:
484 31876 : xfs_qm_dqput(dqp);
485 31876 : 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 305761 : 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 305761 : struct xfs_dquot *dqp;
500 305761 : int error;
501 :
502 : /* Flush inodegc work at the start of a quota reporting scan. */
503 305761 : if (*id == 0)
504 3771 : xfs_inodegc_push(mp);
505 :
506 305761 : error = xfs_qm_dqget_next(mp, *id, type, &dqp);
507 305761 : if (error)
508 : return error;
509 :
510 : /* Fill in the ID we actually read from disk */
511 302837 : *id = dqp->q_id;
512 :
513 302837 : xfs_qm_scall_getquota_fill_qc(mp, type, dqp, dst);
514 :
515 302837 : xfs_qm_dqput(dqp);
516 302837 : return error;
517 : }
|