xref: /linux/fs/xfs/xfs_quotaops.c (revision 0bbdb4258bd116d8cd5d209e8d5b29bae516e5b3)
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_qm.h"
27 #include <linux/quota.h>
28 
29 
30 STATIC int
31 xfs_quota_type(int type)
32 {
33 	switch (type) {
34 	case USRQUOTA:
35 		return XFS_DQ_USER;
36 	case GRPQUOTA:
37 		return XFS_DQ_GROUP;
38 	default:
39 		return XFS_DQ_PROJ;
40 	}
41 }
42 
43 STATIC int
44 xfs_fs_get_xstate(
45 	struct super_block	*sb,
46 	struct fs_quota_stat	*fqs)
47 {
48 	struct xfs_mount	*mp = XFS_M(sb);
49 
50 	if (!XFS_IS_QUOTA_RUNNING(mp))
51 		return -ENOSYS;
52 	return xfs_qm_scall_getqstat(mp, fqs);
53 }
54 
55 STATIC int
56 xfs_fs_get_xstatev(
57 	struct super_block	*sb,
58 	struct fs_quota_statv	*fqs)
59 {
60 	struct xfs_mount	*mp = XFS_M(sb);
61 
62 	if (!XFS_IS_QUOTA_RUNNING(mp))
63 		return -ENOSYS;
64 	return xfs_qm_scall_getqstatv(mp, fqs);
65 }
66 
67 static unsigned int
68 xfs_quota_flags(unsigned int uflags)
69 {
70 	unsigned int flags = 0;
71 
72 	if (uflags & FS_QUOTA_UDQ_ACCT)
73 		flags |= XFS_UQUOTA_ACCT;
74 	if (uflags & FS_QUOTA_PDQ_ACCT)
75 		flags |= XFS_PQUOTA_ACCT;
76 	if (uflags & FS_QUOTA_GDQ_ACCT)
77 		flags |= XFS_GQUOTA_ACCT;
78 	if (uflags & FS_QUOTA_UDQ_ENFD)
79 		flags |= XFS_UQUOTA_ENFD;
80 	if (uflags & FS_QUOTA_GDQ_ENFD)
81 		flags |= XFS_GQUOTA_ENFD;
82 	if (uflags & FS_QUOTA_PDQ_ENFD)
83 		flags |= XFS_PQUOTA_ENFD;
84 
85 	return flags;
86 }
87 
88 STATIC int
89 xfs_quota_enable(
90 	struct super_block	*sb,
91 	unsigned int		uflags)
92 {
93 	struct xfs_mount	*mp = XFS_M(sb);
94 
95 	if (sb->s_flags & MS_RDONLY)
96 		return -EROFS;
97 	if (!XFS_IS_QUOTA_RUNNING(mp))
98 		return -ENOSYS;
99 
100 	return xfs_qm_scall_quotaon(mp, xfs_quota_flags(uflags));
101 }
102 
103 STATIC int
104 xfs_quota_disable(
105 	struct super_block	*sb,
106 	unsigned int		uflags)
107 {
108 	struct xfs_mount	*mp = XFS_M(sb);
109 
110 	if (sb->s_flags & MS_RDONLY)
111 		return -EROFS;
112 	if (!XFS_IS_QUOTA_RUNNING(mp))
113 		return -ENOSYS;
114 	if (!XFS_IS_QUOTA_ON(mp))
115 		return -EINVAL;
116 
117 	return xfs_qm_scall_quotaoff(mp, xfs_quota_flags(uflags));
118 }
119 
120 STATIC int
121 xfs_fs_rm_xquota(
122 	struct super_block	*sb,
123 	unsigned int		uflags)
124 {
125 	struct xfs_mount	*mp = XFS_M(sb);
126 	unsigned int		flags = 0;
127 
128 	if (sb->s_flags & MS_RDONLY)
129 		return -EROFS;
130 
131 	if (XFS_IS_QUOTA_ON(mp))
132 		return -EINVAL;
133 
134 	if (uflags & FS_USER_QUOTA)
135 		flags |= XFS_DQ_USER;
136 	if (uflags & FS_GROUP_QUOTA)
137 		flags |= XFS_DQ_GROUP;
138 	if (uflags & FS_PROJ_QUOTA)
139 		flags |= XFS_DQ_PROJ;
140 
141 	return xfs_qm_scall_trunc_qfiles(mp, flags);
142 }
143 
144 STATIC int
145 xfs_fs_get_dqblk(
146 	struct super_block	*sb,
147 	struct kqid		qid,
148 	struct qc_dqblk		*qdq)
149 {
150 	struct xfs_mount	*mp = XFS_M(sb);
151 
152 	if (!XFS_IS_QUOTA_RUNNING(mp))
153 		return -ENOSYS;
154 	if (!XFS_IS_QUOTA_ON(mp))
155 		return -ESRCH;
156 
157 	return xfs_qm_scall_getquota(mp, from_kqid(&init_user_ns, qid),
158 				      xfs_quota_type(qid.type), qdq);
159 }
160 
161 STATIC int
162 xfs_fs_set_dqblk(
163 	struct super_block	*sb,
164 	struct kqid		qid,
165 	struct qc_dqblk		*qdq)
166 {
167 	struct xfs_mount	*mp = XFS_M(sb);
168 
169 	if (sb->s_flags & MS_RDONLY)
170 		return -EROFS;
171 	if (!XFS_IS_QUOTA_RUNNING(mp))
172 		return -ENOSYS;
173 	if (!XFS_IS_QUOTA_ON(mp))
174 		return -ESRCH;
175 
176 	return xfs_qm_scall_setqlim(mp, from_kqid(&init_user_ns, qid),
177 				     xfs_quota_type(qid.type), qdq);
178 }
179 
180 const struct quotactl_ops xfs_quotactl_operations = {
181 	.get_xstatev		= xfs_fs_get_xstatev,
182 	.get_xstate		= xfs_fs_get_xstate,
183 	.quota_enable		= xfs_quota_enable,
184 	.quota_disable		= xfs_quota_disable,
185 	.rm_xquota		= xfs_fs_rm_xquota,
186 	.get_dqblk		= xfs_fs_get_dqblk,
187 	.set_dqblk		= xfs_fs_set_dqblk,
188 };
189