xfs: fix data corruption w/ unaligned reflink ranges
[sfrench/cifs-2.6.git] / fs / xfs / xfs_quotaops.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2008, Christoph Hellwig
4  * All Rights Reserved.
5  */
6 #include "xfs.h"
7 #include "xfs_format.h"
8 #include "xfs_log_format.h"
9 #include "xfs_trans_resv.h"
10 #include "xfs_mount.h"
11 #include "xfs_inode.h"
12 #include "xfs_quota.h"
13 #include "xfs_trans.h"
14 #include "xfs_trace.h"
15 #include "xfs_icache.h"
16 #include "xfs_qm.h"
17 #include <linux/quota.h>
18
19
20 static void
21 xfs_qm_fill_state(
22         struct qc_type_state    *tstate,
23         struct xfs_mount        *mp,
24         struct xfs_inode        *ip,
25         xfs_ino_t               ino)
26 {
27         struct xfs_quotainfo *q = mp->m_quotainfo;
28         bool tempqip = false;
29
30         tstate->ino = ino;
31         if (!ip && ino == NULLFSINO)
32                 return;
33         if (!ip) {
34                 if (xfs_iget(mp, NULL, ino, 0, 0, &ip))
35                         return;
36                 tempqip = true;
37         }
38         tstate->flags |= QCI_SYSFILE;
39         tstate->blocks = ip->i_d.di_nblocks;
40         tstate->nextents = ip->i_d.di_nextents;
41         tstate->spc_timelimit = q->qi_btimelimit;
42         tstate->ino_timelimit = q->qi_itimelimit;
43         tstate->rt_spc_timelimit = q->qi_rtbtimelimit;
44         tstate->spc_warnlimit = q->qi_bwarnlimit;
45         tstate->ino_warnlimit = q->qi_iwarnlimit;
46         tstate->rt_spc_warnlimit = q->qi_rtbwarnlimit;
47         if (tempqip)
48                 xfs_irele(ip);
49 }
50
51 /*
52  * Return quota status information, such as enforcements, quota file inode
53  * numbers etc.
54  */
55 static int
56 xfs_fs_get_quota_state(
57         struct super_block      *sb,
58         struct qc_state         *state)
59 {
60         struct xfs_mount *mp = XFS_M(sb);
61         struct xfs_quotainfo *q = mp->m_quotainfo;
62
63         memset(state, 0, sizeof(*state));
64         if (!XFS_IS_QUOTA_RUNNING(mp))
65                 return 0;
66         state->s_incoredqs = q->qi_dquots;
67         if (XFS_IS_UQUOTA_RUNNING(mp))
68                 state->s_state[USRQUOTA].flags |= QCI_ACCT_ENABLED;
69         if (XFS_IS_UQUOTA_ENFORCED(mp))
70                 state->s_state[USRQUOTA].flags |= QCI_LIMITS_ENFORCED;
71         if (XFS_IS_GQUOTA_RUNNING(mp))
72                 state->s_state[GRPQUOTA].flags |= QCI_ACCT_ENABLED;
73         if (XFS_IS_GQUOTA_ENFORCED(mp))
74                 state->s_state[GRPQUOTA].flags |= QCI_LIMITS_ENFORCED;
75         if (XFS_IS_PQUOTA_RUNNING(mp))
76                 state->s_state[PRJQUOTA].flags |= QCI_ACCT_ENABLED;
77         if (XFS_IS_PQUOTA_ENFORCED(mp))
78                 state->s_state[PRJQUOTA].flags |= QCI_LIMITS_ENFORCED;
79
80         xfs_qm_fill_state(&state->s_state[USRQUOTA], mp, q->qi_uquotaip,
81                           mp->m_sb.sb_uquotino);
82         xfs_qm_fill_state(&state->s_state[GRPQUOTA], mp, q->qi_gquotaip,
83                           mp->m_sb.sb_gquotino);
84         xfs_qm_fill_state(&state->s_state[PRJQUOTA], mp, q->qi_pquotaip,
85                           mp->m_sb.sb_pquotino);
86         return 0;
87 }
88
89 STATIC int
90 xfs_quota_type(int type)
91 {
92         switch (type) {
93         case USRQUOTA:
94                 return XFS_DQ_USER;
95         case GRPQUOTA:
96                 return XFS_DQ_GROUP;
97         default:
98                 return XFS_DQ_PROJ;
99         }
100 }
101
102 #define XFS_QC_SETINFO_MASK (QC_TIMER_MASK | QC_WARNS_MASK)
103
104 /*
105  * Adjust quota timers & warnings
106  */
107 static int
108 xfs_fs_set_info(
109         struct super_block      *sb,
110         int                     type,
111         struct qc_info          *info)
112 {
113         struct xfs_mount *mp = XFS_M(sb);
114         struct qc_dqblk newlim;
115
116         if (sb_rdonly(sb))
117                 return -EROFS;
118         if (!XFS_IS_QUOTA_RUNNING(mp))
119                 return -ENOSYS;
120         if (!XFS_IS_QUOTA_ON(mp))
121                 return -ESRCH;
122         if (info->i_fieldmask & ~XFS_QC_SETINFO_MASK)
123                 return -EINVAL;
124         if ((info->i_fieldmask & XFS_QC_SETINFO_MASK) == 0)
125                 return 0;
126
127         newlim.d_fieldmask = info->i_fieldmask;
128         newlim.d_spc_timer = info->i_spc_timelimit;
129         newlim.d_ino_timer = info->i_ino_timelimit;
130         newlim.d_rt_spc_timer = info->i_rt_spc_timelimit;
131         newlim.d_ino_warns = info->i_ino_warnlimit;
132         newlim.d_spc_warns = info->i_spc_warnlimit;
133         newlim.d_rt_spc_warns = info->i_rt_spc_warnlimit;
134
135         return xfs_qm_scall_setqlim(mp, 0, xfs_quota_type(type), &newlim);
136 }
137
138 static unsigned int
139 xfs_quota_flags(unsigned int uflags)
140 {
141         unsigned int flags = 0;
142
143         if (uflags & FS_QUOTA_UDQ_ACCT)
144                 flags |= XFS_UQUOTA_ACCT;
145         if (uflags & FS_QUOTA_PDQ_ACCT)
146                 flags |= XFS_PQUOTA_ACCT;
147         if (uflags & FS_QUOTA_GDQ_ACCT)
148                 flags |= XFS_GQUOTA_ACCT;
149         if (uflags & FS_QUOTA_UDQ_ENFD)
150                 flags |= XFS_UQUOTA_ENFD;
151         if (uflags & FS_QUOTA_GDQ_ENFD)
152                 flags |= XFS_GQUOTA_ENFD;
153         if (uflags & FS_QUOTA_PDQ_ENFD)
154                 flags |= XFS_PQUOTA_ENFD;
155
156         return flags;
157 }
158
159 STATIC int
160 xfs_quota_enable(
161         struct super_block      *sb,
162         unsigned int            uflags)
163 {
164         struct xfs_mount        *mp = XFS_M(sb);
165
166         if (sb_rdonly(sb))
167                 return -EROFS;
168         if (!XFS_IS_QUOTA_RUNNING(mp))
169                 return -ENOSYS;
170
171         return xfs_qm_scall_quotaon(mp, xfs_quota_flags(uflags));
172 }
173
174 STATIC int
175 xfs_quota_disable(
176         struct super_block      *sb,
177         unsigned int            uflags)
178 {
179         struct xfs_mount        *mp = XFS_M(sb);
180
181         if (sb_rdonly(sb))
182                 return -EROFS;
183         if (!XFS_IS_QUOTA_RUNNING(mp))
184                 return -ENOSYS;
185         if (!XFS_IS_QUOTA_ON(mp))
186                 return -EINVAL;
187
188         return xfs_qm_scall_quotaoff(mp, xfs_quota_flags(uflags));
189 }
190
191 STATIC int
192 xfs_fs_rm_xquota(
193         struct super_block      *sb,
194         unsigned int            uflags)
195 {
196         struct xfs_mount        *mp = XFS_M(sb);
197         unsigned int            flags = 0;
198
199         if (sb_rdonly(sb))
200                 return -EROFS;
201
202         if (XFS_IS_QUOTA_ON(mp))
203                 return -EINVAL;
204
205         if (uflags & FS_USER_QUOTA)
206                 flags |= XFS_DQ_USER;
207         if (uflags & FS_GROUP_QUOTA)
208                 flags |= XFS_DQ_GROUP;
209         if (uflags & FS_PROJ_QUOTA)
210                 flags |= XFS_DQ_PROJ;
211
212         return xfs_qm_scall_trunc_qfiles(mp, flags);
213 }
214
215 STATIC int
216 xfs_fs_get_dqblk(
217         struct super_block      *sb,
218         struct kqid             qid,
219         struct qc_dqblk         *qdq)
220 {
221         struct xfs_mount        *mp = XFS_M(sb);
222         xfs_dqid_t              id;
223
224         if (!XFS_IS_QUOTA_RUNNING(mp))
225                 return -ENOSYS;
226         if (!XFS_IS_QUOTA_ON(mp))
227                 return -ESRCH;
228
229         id = from_kqid(&init_user_ns, qid);
230         return xfs_qm_scall_getquota(mp, id, xfs_quota_type(qid.type), qdq);
231 }
232
233 /* Return quota info for active quota >= this qid */
234 STATIC int
235 xfs_fs_get_nextdqblk(
236         struct super_block      *sb,
237         struct kqid             *qid,
238         struct qc_dqblk         *qdq)
239 {
240         int                     ret;
241         struct xfs_mount        *mp = XFS_M(sb);
242         xfs_dqid_t              id;
243
244         if (!XFS_IS_QUOTA_RUNNING(mp))
245                 return -ENOSYS;
246         if (!XFS_IS_QUOTA_ON(mp))
247                 return -ESRCH;
248
249         id = from_kqid(&init_user_ns, *qid);
250         ret = xfs_qm_scall_getquota_next(mp, &id, xfs_quota_type(qid->type),
251                         qdq);
252         if (ret)
253                 return ret;
254
255         /* ID may be different, so convert back what we got */
256         *qid = make_kqid(current_user_ns(), qid->type, id);
257         return 0;
258 }
259
260 STATIC int
261 xfs_fs_set_dqblk(
262         struct super_block      *sb,
263         struct kqid             qid,
264         struct qc_dqblk         *qdq)
265 {
266         struct xfs_mount        *mp = XFS_M(sb);
267
268         if (sb_rdonly(sb))
269                 return -EROFS;
270         if (!XFS_IS_QUOTA_RUNNING(mp))
271                 return -ENOSYS;
272         if (!XFS_IS_QUOTA_ON(mp))
273                 return -ESRCH;
274
275         return xfs_qm_scall_setqlim(mp, from_kqid(&init_user_ns, qid),
276                                      xfs_quota_type(qid.type), qdq);
277 }
278
279 const struct quotactl_ops xfs_quotactl_operations = {
280         .get_state              = xfs_fs_get_quota_state,
281         .set_info               = xfs_fs_set_info,
282         .quota_enable           = xfs_quota_enable,
283         .quota_disable          = xfs_quota_disable,
284         .rm_xquota              = xfs_fs_rm_xquota,
285         .get_dqblk              = xfs_fs_get_dqblk,
286         .get_nextdqblk          = xfs_fs_get_nextdqblk,
287         .set_dqblk              = xfs_fs_set_dqblk,
288 };