quota.c (0c49cd295d42d0032af11d55e2140dbec11dc8d0) quota.c (14bf61ffe6ac54afcd1e888a4407fe16054483db)
1/*
2 * Quota code necessary even when VFS quota support is not compiled
3 * into the kernel. The interesting stuff is over in dquot.c, here
4 * we have symbols for initial quotactl(2) handling, the sysctl(2)
5 * variables, etc - things needed even when quota support disabled.
6 */
7
8#include <linux/fs.h>

--- 104 unchanged lines hidden (view full) ---

113
114 if (copy_from_user(&info, addr, sizeof(info)))
115 return -EFAULT;
116 if (!sb->s_qcop->set_info)
117 return -ENOSYS;
118 return sb->s_qcop->set_info(sb, type, &info);
119}
120
1/*
2 * Quota code necessary even when VFS quota support is not compiled
3 * into the kernel. The interesting stuff is over in dquot.c, here
4 * we have symbols for initial quotactl(2) handling, the sysctl(2)
5 * variables, etc - things needed even when quota support disabled.
6 */
7
8#include <linux/fs.h>

--- 104 unchanged lines hidden (view full) ---

113
114 if (copy_from_user(&info, addr, sizeof(info)))
115 return -EFAULT;
116 if (!sb->s_qcop->set_info)
117 return -ENOSYS;
118 return sb->s_qcop->set_info(sb, type, &info);
119}
120
121static void copy_to_if_dqblk(struct if_dqblk *dst, struct fs_disk_quota *src)
121static inline qsize_t qbtos(qsize_t blocks)
122{
122{
123 return blocks << QIF_DQBLKSIZE_BITS;
124}
125
126static inline qsize_t stoqb(qsize_t space)
127{
128 return (space + QIF_DQBLKSIZE - 1) >> QIF_DQBLKSIZE_BITS;
129}
130
131static void copy_to_if_dqblk(struct if_dqblk *dst, struct qc_dqblk *src)
132{
123 memset(dst, 0, sizeof(*dst));
133 memset(dst, 0, sizeof(*dst));
124 dst->dqb_bhardlimit = src->d_blk_hardlimit;
125 dst->dqb_bsoftlimit = src->d_blk_softlimit;
126 dst->dqb_curspace = src->d_bcount;
134 dst->dqb_bhardlimit = stoqb(src->d_spc_hardlimit);
135 dst->dqb_bsoftlimit = stoqb(src->d_spc_softlimit);
136 dst->dqb_curspace = src->d_space;
127 dst->dqb_ihardlimit = src->d_ino_hardlimit;
128 dst->dqb_isoftlimit = src->d_ino_softlimit;
137 dst->dqb_ihardlimit = src->d_ino_hardlimit;
138 dst->dqb_isoftlimit = src->d_ino_softlimit;
129 dst->dqb_curinodes = src->d_icount;
130 dst->dqb_btime = src->d_btimer;
131 dst->dqb_itime = src->d_itimer;
139 dst->dqb_curinodes = src->d_ino_count;
140 dst->dqb_btime = src->d_spc_timer;
141 dst->dqb_itime = src->d_ino_timer;
132 dst->dqb_valid = QIF_ALL;
133}
134
135static int quota_getquota(struct super_block *sb, int type, qid_t id,
136 void __user *addr)
137{
138 struct kqid qid;
142 dst->dqb_valid = QIF_ALL;
143}
144
145static int quota_getquota(struct super_block *sb, int type, qid_t id,
146 void __user *addr)
147{
148 struct kqid qid;
139 struct fs_disk_quota fdq;
149 struct qc_dqblk fdq;
140 struct if_dqblk idq;
141 int ret;
142
143 if (!sb->s_qcop->get_dqblk)
144 return -ENOSYS;
145 qid = make_kqid(current_user_ns(), type, id);
146 if (!qid_valid(qid))
147 return -EINVAL;
148 ret = sb->s_qcop->get_dqblk(sb, qid, &fdq);
149 if (ret)
150 return ret;
151 copy_to_if_dqblk(&idq, &fdq);
152 if (copy_to_user(addr, &idq, sizeof(idq)))
153 return -EFAULT;
154 return 0;
155}
156
150 struct if_dqblk idq;
151 int ret;
152
153 if (!sb->s_qcop->get_dqblk)
154 return -ENOSYS;
155 qid = make_kqid(current_user_ns(), type, id);
156 if (!qid_valid(qid))
157 return -EINVAL;
158 ret = sb->s_qcop->get_dqblk(sb, qid, &fdq);
159 if (ret)
160 return ret;
161 copy_to_if_dqblk(&idq, &fdq);
162 if (copy_to_user(addr, &idq, sizeof(idq)))
163 return -EFAULT;
164 return 0;
165}
166
157static void copy_from_if_dqblk(struct fs_disk_quota *dst, struct if_dqblk *src)
167static void copy_from_if_dqblk(struct qc_dqblk *dst, struct if_dqblk *src)
158{
168{
159 dst->d_blk_hardlimit = src->dqb_bhardlimit;
160 dst->d_blk_softlimit = src->dqb_bsoftlimit;
161 dst->d_bcount = src->dqb_curspace;
169 dst->d_spc_hardlimit = qbtos(src->dqb_bhardlimit);
170 dst->d_spc_softlimit = qbtos(src->dqb_bsoftlimit);
171 dst->d_space = src->dqb_curspace;
162 dst->d_ino_hardlimit = src->dqb_ihardlimit;
163 dst->d_ino_softlimit = src->dqb_isoftlimit;
172 dst->d_ino_hardlimit = src->dqb_ihardlimit;
173 dst->d_ino_softlimit = src->dqb_isoftlimit;
164 dst->d_icount = src->dqb_curinodes;
165 dst->d_btimer = src->dqb_btime;
166 dst->d_itimer = src->dqb_itime;
174 dst->d_ino_count = src->dqb_curinodes;
175 dst->d_spc_timer = src->dqb_btime;
176 dst->d_ino_timer = src->dqb_itime;
167
168 dst->d_fieldmask = 0;
169 if (src->dqb_valid & QIF_BLIMITS)
177
178 dst->d_fieldmask = 0;
179 if (src->dqb_valid & QIF_BLIMITS)
170 dst->d_fieldmask |= FS_DQ_BSOFT | FS_DQ_BHARD;
180 dst->d_fieldmask |= QC_SPC_SOFT | QC_SPC_HARD;
171 if (src->dqb_valid & QIF_SPACE)
181 if (src->dqb_valid & QIF_SPACE)
172 dst->d_fieldmask |= FS_DQ_BCOUNT;
182 dst->d_fieldmask |= QC_SPACE;
173 if (src->dqb_valid & QIF_ILIMITS)
183 if (src->dqb_valid & QIF_ILIMITS)
174 dst->d_fieldmask |= FS_DQ_ISOFT | FS_DQ_IHARD;
184 dst->d_fieldmask |= QC_INO_SOFT | QC_INO_HARD;
175 if (src->dqb_valid & QIF_INODES)
185 if (src->dqb_valid & QIF_INODES)
176 dst->d_fieldmask |= FS_DQ_ICOUNT;
186 dst->d_fieldmask |= QC_INO_COUNT;
177 if (src->dqb_valid & QIF_BTIME)
187 if (src->dqb_valid & QIF_BTIME)
178 dst->d_fieldmask |= FS_DQ_BTIMER;
188 dst->d_fieldmask |= QC_SPC_TIMER;
179 if (src->dqb_valid & QIF_ITIME)
189 if (src->dqb_valid & QIF_ITIME)
180 dst->d_fieldmask |= FS_DQ_ITIMER;
190 dst->d_fieldmask |= QC_INO_TIMER;
181}
182
183static int quota_setquota(struct super_block *sb, int type, qid_t id,
184 void __user *addr)
185{
191}
192
193static int quota_setquota(struct super_block *sb, int type, qid_t id,
194 void __user *addr)
195{
186 struct fs_disk_quota fdq;
196 struct qc_dqblk fdq;
187 struct if_dqblk idq;
188 struct kqid qid;
189
190 if (copy_from_user(&idq, addr, sizeof(idq)))
191 return -EFAULT;
192 if (!sb->s_qcop->set_dqblk)
193 return -ENOSYS;
194 qid = make_kqid(current_user_ns(), type, id);

--- 47 unchanged lines hidden (view full) ---

242 return -EINVAL;
243 }
244 ret = sb->s_qcop->get_xstatev(sb, &fqs);
245 if (!ret && copy_to_user(addr, &fqs, sizeof(fqs)))
246 return -EFAULT;
247 return ret;
248}
249
197 struct if_dqblk idq;
198 struct kqid qid;
199
200 if (copy_from_user(&idq, addr, sizeof(idq)))
201 return -EFAULT;
202 if (!sb->s_qcop->set_dqblk)
203 return -ENOSYS;
204 qid = make_kqid(current_user_ns(), type, id);

--- 47 unchanged lines hidden (view full) ---

252 return -EINVAL;
253 }
254 ret = sb->s_qcop->get_xstatev(sb, &fqs);
255 if (!ret && copy_to_user(addr, &fqs, sizeof(fqs)))
256 return -EFAULT;
257 return ret;
258}
259
260/*
261 * XFS defines BBTOB and BTOBB macros inside fs/xfs/ and we cannot move them
262 * out of there as xfsprogs rely on definitions being in that header file. So
263 * just define same functions here for quota purposes.
264 */
265#define XFS_BB_SHIFT 9
266
267static inline u64 quota_bbtob(u64 blocks)
268{
269 return blocks << XFS_BB_SHIFT;
270}
271
272static inline u64 quota_btobb(u64 bytes)
273{
274 return (bytes + (1 << XFS_BB_SHIFT) - 1) >> XFS_BB_SHIFT;
275}
276
277static void copy_from_xfs_dqblk(struct qc_dqblk *dst, struct fs_disk_quota *src)
278{
279 dst->d_spc_hardlimit = quota_bbtob(src->d_blk_hardlimit);
280 dst->d_spc_softlimit = quota_bbtob(src->d_blk_softlimit);
281 dst->d_ino_hardlimit = src->d_ino_hardlimit;
282 dst->d_ino_softlimit = src->d_ino_softlimit;
283 dst->d_space = quota_bbtob(src->d_bcount);
284 dst->d_ino_count = src->d_icount;
285 dst->d_ino_timer = src->d_itimer;
286 dst->d_spc_timer = src->d_btimer;
287 dst->d_ino_warns = src->d_iwarns;
288 dst->d_spc_warns = src->d_bwarns;
289 dst->d_rt_spc_hardlimit = quota_bbtob(src->d_rtb_hardlimit);
290 dst->d_rt_spc_softlimit = quota_bbtob(src->d_rtb_softlimit);
291 dst->d_rt_space = quota_bbtob(src->d_rtbcount);
292 dst->d_rt_spc_timer = src->d_rtbtimer;
293 dst->d_rt_spc_warns = src->d_rtbwarns;
294 dst->d_fieldmask = 0;
295 if (src->d_fieldmask & FS_DQ_ISOFT)
296 dst->d_fieldmask |= QC_INO_SOFT;
297 if (src->d_fieldmask & FS_DQ_IHARD)
298 dst->d_fieldmask |= QC_INO_HARD;
299 if (src->d_fieldmask & FS_DQ_BSOFT)
300 dst->d_fieldmask |= QC_SPC_SOFT;
301 if (src->d_fieldmask & FS_DQ_BHARD)
302 dst->d_fieldmask |= QC_SPC_HARD;
303 if (src->d_fieldmask & FS_DQ_RTBSOFT)
304 dst->d_fieldmask |= QC_RT_SPC_SOFT;
305 if (src->d_fieldmask & FS_DQ_RTBHARD)
306 dst->d_fieldmask |= QC_RT_SPC_HARD;
307 if (src->d_fieldmask & FS_DQ_BTIMER)
308 dst->d_fieldmask |= QC_SPC_TIMER;
309 if (src->d_fieldmask & FS_DQ_ITIMER)
310 dst->d_fieldmask |= QC_INO_TIMER;
311 if (src->d_fieldmask & FS_DQ_RTBTIMER)
312 dst->d_fieldmask |= QC_RT_SPC_TIMER;
313 if (src->d_fieldmask & FS_DQ_BWARNS)
314 dst->d_fieldmask |= QC_SPC_WARNS;
315 if (src->d_fieldmask & FS_DQ_IWARNS)
316 dst->d_fieldmask |= QC_INO_WARNS;
317 if (src->d_fieldmask & FS_DQ_RTBWARNS)
318 dst->d_fieldmask |= QC_RT_SPC_WARNS;
319 if (src->d_fieldmask & FS_DQ_BCOUNT)
320 dst->d_fieldmask |= QC_SPACE;
321 if (src->d_fieldmask & FS_DQ_ICOUNT)
322 dst->d_fieldmask |= QC_INO_COUNT;
323 if (src->d_fieldmask & FS_DQ_RTBCOUNT)
324 dst->d_fieldmask |= QC_RT_SPACE;
325}
326
250static int quota_setxquota(struct super_block *sb, int type, qid_t id,
251 void __user *addr)
252{
253 struct fs_disk_quota fdq;
327static int quota_setxquota(struct super_block *sb, int type, qid_t id,
328 void __user *addr)
329{
330 struct fs_disk_quota fdq;
331 struct qc_dqblk qdq;
254 struct kqid qid;
255
256 if (copy_from_user(&fdq, addr, sizeof(fdq)))
257 return -EFAULT;
258 if (!sb->s_qcop->set_dqblk)
259 return -ENOSYS;
260 qid = make_kqid(current_user_ns(), type, id);
261 if (!qid_valid(qid))
262 return -EINVAL;
332 struct kqid qid;
333
334 if (copy_from_user(&fdq, addr, sizeof(fdq)))
335 return -EFAULT;
336 if (!sb->s_qcop->set_dqblk)
337 return -ENOSYS;
338 qid = make_kqid(current_user_ns(), type, id);
339 if (!qid_valid(qid))
340 return -EINVAL;
263 return sb->s_qcop->set_dqblk(sb, qid, &fdq);
341 copy_from_xfs_dqblk(&qdq, &fdq);
342 return sb->s_qcop->set_dqblk(sb, qid, &qdq);
264}
265
343}
344
345static void copy_to_xfs_dqblk(struct fs_disk_quota *dst, struct qc_dqblk *src,
346 int type, qid_t id)
347{
348 memset(dst, 0, sizeof(*dst));
349 dst->d_version = FS_DQUOT_VERSION;
350 dst->d_id = id;
351 if (type == USRQUOTA)
352 dst->d_flags = FS_USER_QUOTA;
353 else if (type == PRJQUOTA)
354 dst->d_flags = FS_PROJ_QUOTA;
355 else
356 dst->d_flags = FS_GROUP_QUOTA;
357 dst->d_blk_hardlimit = quota_btobb(src->d_spc_hardlimit);
358 dst->d_blk_softlimit = quota_btobb(src->d_spc_softlimit);
359 dst->d_ino_hardlimit = src->d_ino_hardlimit;
360 dst->d_ino_softlimit = src->d_ino_softlimit;
361 dst->d_bcount = quota_btobb(src->d_space);
362 dst->d_icount = src->d_ino_count;
363 dst->d_itimer = src->d_ino_timer;
364 dst->d_btimer = src->d_spc_timer;
365 dst->d_iwarns = src->d_ino_warns;
366 dst->d_bwarns = src->d_spc_warns;
367 dst->d_rtb_hardlimit = quota_btobb(src->d_rt_spc_hardlimit);
368 dst->d_rtb_softlimit = quota_btobb(src->d_rt_spc_softlimit);
369 dst->d_rtbcount = quota_btobb(src->d_rt_space);
370 dst->d_rtbtimer = src->d_rt_spc_timer;
371 dst->d_rtbwarns = src->d_rt_spc_warns;
372}
373
266static int quota_getxquota(struct super_block *sb, int type, qid_t id,
267 void __user *addr)
268{
269 struct fs_disk_quota fdq;
374static int quota_getxquota(struct super_block *sb, int type, qid_t id,
375 void __user *addr)
376{
377 struct fs_disk_quota fdq;
378 struct qc_dqblk qdq;
270 struct kqid qid;
271 int ret;
272
273 if (!sb->s_qcop->get_dqblk)
274 return -ENOSYS;
275 qid = make_kqid(current_user_ns(), type, id);
276 if (!qid_valid(qid))
277 return -EINVAL;
379 struct kqid qid;
380 int ret;
381
382 if (!sb->s_qcop->get_dqblk)
383 return -ENOSYS;
384 qid = make_kqid(current_user_ns(), type, id);
385 if (!qid_valid(qid))
386 return -EINVAL;
278 ret = sb->s_qcop->get_dqblk(sb, qid, &fdq);
279 if (!ret && copy_to_user(addr, &fdq, sizeof(fdq)))
387 ret = sb->s_qcop->get_dqblk(sb, qid, &qdq);
388 if (ret)
389 return ret;
390 copy_to_xfs_dqblk(&fdq, &qdq, type, id);
391 if (copy_to_user(addr, &fdq, sizeof(fdq)))
280 return -EFAULT;
281 return ret;
282}
283
284static int quota_rmxquota(struct super_block *sb, void __user *addr)
285{
286 __u32 flags;
287

--- 178 unchanged lines hidden ---
392 return -EFAULT;
393 return ret;
394}
395
396static int quota_rmxquota(struct super_block *sb, void __user *addr)
397{
398 __u32 flags;
399

--- 178 unchanged lines hidden ---