xfs_qm_syscalls.c 13 KB

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