xfs_quotaops.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. /*
  2. * Copyright (c) 2008, Christoph Hellwig
  3. * All Rights Reserved.
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it would be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write the Free Software Foundation,
  16. * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  17. */
  18. #include "xfs.h"
  19. #include "xfs_format.h"
  20. #include "xfs_log_format.h"
  21. #include "xfs_trans_resv.h"
  22. #include "xfs_mount.h"
  23. #include "xfs_inode.h"
  24. #include "xfs_quota.h"
  25. #include "xfs_trans.h"
  26. #include "xfs_trace.h"
  27. #include "xfs_icache.h"
  28. #include "xfs_qm.h"
  29. #include <linux/quota.h>
  30. static void
  31. xfs_qm_fill_state(
  32. struct qc_type_state *tstate,
  33. struct xfs_mount *mp,
  34. struct xfs_inode *ip,
  35. xfs_ino_t ino)
  36. {
  37. struct xfs_quotainfo *q = mp->m_quotainfo;
  38. bool tempqip = false;
  39. tstate->ino = ino;
  40. if (!ip && ino == NULLFSINO)
  41. return;
  42. if (!ip) {
  43. if (xfs_iget(mp, NULL, ino, 0, 0, &ip))
  44. return;
  45. tempqip = true;
  46. }
  47. tstate->flags |= QCI_SYSFILE;
  48. tstate->blocks = ip->i_d.di_nblocks;
  49. tstate->nextents = ip->i_d.di_nextents;
  50. tstate->spc_timelimit = q->qi_btimelimit;
  51. tstate->ino_timelimit = q->qi_itimelimit;
  52. tstate->rt_spc_timelimit = q->qi_rtbtimelimit;
  53. tstate->spc_warnlimit = q->qi_bwarnlimit;
  54. tstate->ino_warnlimit = q->qi_iwarnlimit;
  55. tstate->rt_spc_warnlimit = q->qi_rtbwarnlimit;
  56. if (tempqip)
  57. IRELE(ip);
  58. }
  59. /*
  60. * Return quota status information, such as enforcements, quota file inode
  61. * numbers etc.
  62. */
  63. static int
  64. xfs_fs_get_quota_state(
  65. struct super_block *sb,
  66. struct qc_state *state)
  67. {
  68. struct xfs_mount *mp = XFS_M(sb);
  69. struct xfs_quotainfo *q = mp->m_quotainfo;
  70. memset(state, 0, sizeof(*state));
  71. if (!XFS_IS_QUOTA_RUNNING(mp))
  72. return 0;
  73. state->s_incoredqs = q->qi_dquots;
  74. if (XFS_IS_UQUOTA_RUNNING(mp))
  75. state->s_state[USRQUOTA].flags |= QCI_ACCT_ENABLED;
  76. if (XFS_IS_UQUOTA_ENFORCED(mp))
  77. state->s_state[USRQUOTA].flags |= QCI_LIMITS_ENFORCED;
  78. if (XFS_IS_GQUOTA_RUNNING(mp))
  79. state->s_state[GRPQUOTA].flags |= QCI_ACCT_ENABLED;
  80. if (XFS_IS_GQUOTA_ENFORCED(mp))
  81. state->s_state[GRPQUOTA].flags |= QCI_LIMITS_ENFORCED;
  82. if (XFS_IS_PQUOTA_RUNNING(mp))
  83. state->s_state[PRJQUOTA].flags |= QCI_ACCT_ENABLED;
  84. if (XFS_IS_PQUOTA_ENFORCED(mp))
  85. state->s_state[PRJQUOTA].flags |= QCI_LIMITS_ENFORCED;
  86. xfs_qm_fill_state(&state->s_state[USRQUOTA], mp, q->qi_uquotaip,
  87. mp->m_sb.sb_uquotino);
  88. xfs_qm_fill_state(&state->s_state[GRPQUOTA], mp, q->qi_gquotaip,
  89. mp->m_sb.sb_gquotino);
  90. xfs_qm_fill_state(&state->s_state[PRJQUOTA], mp, q->qi_pquotaip,
  91. mp->m_sb.sb_pquotino);
  92. return 0;
  93. }
  94. STATIC int
  95. xfs_quota_type(int type)
  96. {
  97. switch (type) {
  98. case USRQUOTA:
  99. return XFS_DQ_USER;
  100. case GRPQUOTA:
  101. return XFS_DQ_GROUP;
  102. default:
  103. return XFS_DQ_PROJ;
  104. }
  105. }
  106. #define XFS_QC_SETINFO_MASK (QC_TIMER_MASK | QC_WARNS_MASK)
  107. /*
  108. * Adjust quota timers & warnings
  109. */
  110. static int
  111. xfs_fs_set_info(
  112. struct super_block *sb,
  113. int type,
  114. struct qc_info *info)
  115. {
  116. struct xfs_mount *mp = XFS_M(sb);
  117. struct qc_dqblk newlim;
  118. if (sb->s_flags & MS_RDONLY)
  119. return -EROFS;
  120. if (!XFS_IS_QUOTA_RUNNING(mp))
  121. return -ENOSYS;
  122. if (!XFS_IS_QUOTA_ON(mp))
  123. return -ESRCH;
  124. if (info->i_fieldmask & ~XFS_QC_SETINFO_MASK)
  125. return -EINVAL;
  126. if ((info->i_fieldmask & XFS_QC_SETINFO_MASK) == 0)
  127. return 0;
  128. newlim.d_fieldmask = info->i_fieldmask;
  129. newlim.d_spc_timer = info->i_spc_timelimit;
  130. newlim.d_ino_timer = info->i_ino_timelimit;
  131. newlim.d_rt_spc_timer = info->i_rt_spc_timelimit;
  132. newlim.d_ino_warns = info->i_ino_warnlimit;
  133. newlim.d_spc_warns = info->i_spc_warnlimit;
  134. newlim.d_rt_spc_warns = info->i_rt_spc_warnlimit;
  135. return xfs_qm_scall_setqlim(mp, 0, xfs_quota_type(type), &newlim);
  136. }
  137. static unsigned int
  138. xfs_quota_flags(unsigned int uflags)
  139. {
  140. unsigned int flags = 0;
  141. if (uflags & FS_QUOTA_UDQ_ACCT)
  142. flags |= XFS_UQUOTA_ACCT;
  143. if (uflags & FS_QUOTA_PDQ_ACCT)
  144. flags |= XFS_PQUOTA_ACCT;
  145. if (uflags & FS_QUOTA_GDQ_ACCT)
  146. flags |= XFS_GQUOTA_ACCT;
  147. if (uflags & FS_QUOTA_UDQ_ENFD)
  148. flags |= XFS_UQUOTA_ENFD;
  149. if (uflags & FS_QUOTA_GDQ_ENFD)
  150. flags |= XFS_GQUOTA_ENFD;
  151. if (uflags & FS_QUOTA_PDQ_ENFD)
  152. flags |= XFS_PQUOTA_ENFD;
  153. return flags;
  154. }
  155. STATIC int
  156. xfs_quota_enable(
  157. struct super_block *sb,
  158. unsigned int uflags)
  159. {
  160. struct xfs_mount *mp = XFS_M(sb);
  161. if (sb->s_flags & MS_RDONLY)
  162. return -EROFS;
  163. if (!XFS_IS_QUOTA_RUNNING(mp))
  164. return -ENOSYS;
  165. return xfs_qm_scall_quotaon(mp, xfs_quota_flags(uflags));
  166. }
  167. STATIC int
  168. xfs_quota_disable(
  169. struct super_block *sb,
  170. unsigned int uflags)
  171. {
  172. struct xfs_mount *mp = XFS_M(sb);
  173. if (sb->s_flags & MS_RDONLY)
  174. return -EROFS;
  175. if (!XFS_IS_QUOTA_RUNNING(mp))
  176. return -ENOSYS;
  177. if (!XFS_IS_QUOTA_ON(mp))
  178. return -EINVAL;
  179. return xfs_qm_scall_quotaoff(mp, xfs_quota_flags(uflags));
  180. }
  181. STATIC int
  182. xfs_fs_rm_xquota(
  183. struct super_block *sb,
  184. unsigned int uflags)
  185. {
  186. struct xfs_mount *mp = XFS_M(sb);
  187. unsigned int flags = 0;
  188. if (sb->s_flags & MS_RDONLY)
  189. return -EROFS;
  190. if (XFS_IS_QUOTA_ON(mp))
  191. return -EINVAL;
  192. if (uflags & FS_USER_QUOTA)
  193. flags |= XFS_DQ_USER;
  194. if (uflags & FS_GROUP_QUOTA)
  195. flags |= XFS_DQ_GROUP;
  196. if (uflags & FS_PROJ_QUOTA)
  197. flags |= XFS_DQ_PROJ;
  198. return xfs_qm_scall_trunc_qfiles(mp, flags);
  199. }
  200. STATIC int
  201. xfs_fs_get_dqblk(
  202. struct super_block *sb,
  203. struct kqid qid,
  204. struct qc_dqblk *qdq)
  205. {
  206. struct xfs_mount *mp = XFS_M(sb);
  207. if (!XFS_IS_QUOTA_RUNNING(mp))
  208. return -ENOSYS;
  209. if (!XFS_IS_QUOTA_ON(mp))
  210. return -ESRCH;
  211. return xfs_qm_scall_getquota(mp, from_kqid(&init_user_ns, qid),
  212. xfs_quota_type(qid.type), qdq);
  213. }
  214. STATIC int
  215. xfs_fs_set_dqblk(
  216. struct super_block *sb,
  217. struct kqid qid,
  218. struct qc_dqblk *qdq)
  219. {
  220. struct xfs_mount *mp = XFS_M(sb);
  221. if (sb->s_flags & MS_RDONLY)
  222. return -EROFS;
  223. if (!XFS_IS_QUOTA_RUNNING(mp))
  224. return -ENOSYS;
  225. if (!XFS_IS_QUOTA_ON(mp))
  226. return -ESRCH;
  227. return xfs_qm_scall_setqlim(mp, from_kqid(&init_user_ns, qid),
  228. xfs_quota_type(qid.type), qdq);
  229. }
  230. const struct quotactl_ops xfs_quotactl_operations = {
  231. .get_state = xfs_fs_get_quota_state,
  232. .set_info = xfs_fs_set_info,
  233. .quota_enable = xfs_quota_enable,
  234. .quota_disable = xfs_quota_disable,
  235. .rm_xquota = xfs_fs_rm_xquota,
  236. .get_dqblk = xfs_fs_get_dqblk,
  237. .set_dqblk = xfs_fs_set_dqblk,
  238. };