diff options
author | Jan Kara <jack@suse.cz> | 2014-11-19 10:17:45 -0500 |
---|---|---|
committer | Jan Kara <jack@suse.cz> | 2015-03-04 10:06:35 -0500 |
commit | bc230e4a2326e30476092ed967fced0e43667c82 (patch) | |
tree | f66b2e715c43d88af7f3647b50948621012f4deb /fs/quota | |
parent | 0a240339a8deeb13a19043389bba4285a6c0592e (diff) |
quota: Wire up Q_GETXSTATE and Q_GETXSTATV calls to work with ->get_state
Add appropriate conversion functions so that filesystems supporting
->get_state() method can be queried using Q_GETXSTATE and Q_GETXSTATV
calls.
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/quota')
-rw-r--r-- | fs/quota/quota.c | 138 |
1 files changed, 134 insertions, 4 deletions
diff --git a/fs/quota/quota.c b/fs/quota/quota.c index 00d50fca1005..83939ff4c444 100644 --- a/fs/quota/quota.c +++ b/fs/quota/quota.c | |||
@@ -269,25 +269,152 @@ static int quota_disable(struct super_block *sb, void __user *addr) | |||
269 | return sb->s_qcop->quota_disable(sb, flags); | 269 | return sb->s_qcop->quota_disable(sb, flags); |
270 | } | 270 | } |
271 | 271 | ||
272 | static int quota_state_to_flags(struct qc_state *state) | ||
273 | { | ||
274 | int flags = 0; | ||
275 | |||
276 | if (state->s_state[USRQUOTA].flags & QCI_ACCT_ENABLED) | ||
277 | flags |= FS_QUOTA_UDQ_ACCT; | ||
278 | if (state->s_state[USRQUOTA].flags & QCI_LIMITS_ENFORCED) | ||
279 | flags |= FS_QUOTA_UDQ_ENFD; | ||
280 | if (state->s_state[GRPQUOTA].flags & QCI_ACCT_ENABLED) | ||
281 | flags |= FS_QUOTA_GDQ_ACCT; | ||
282 | if (state->s_state[GRPQUOTA].flags & QCI_LIMITS_ENFORCED) | ||
283 | flags |= FS_QUOTA_GDQ_ENFD; | ||
284 | if (state->s_state[PRJQUOTA].flags & QCI_ACCT_ENABLED) | ||
285 | flags |= FS_QUOTA_PDQ_ACCT; | ||
286 | if (state->s_state[PRJQUOTA].flags & QCI_LIMITS_ENFORCED) | ||
287 | flags |= FS_QUOTA_PDQ_ENFD; | ||
288 | return flags; | ||
289 | } | ||
290 | |||
291 | static int quota_getstate(struct super_block *sb, struct fs_quota_stat *fqs) | ||
292 | { | ||
293 | int type; | ||
294 | struct qc_state state; | ||
295 | int ret; | ||
296 | |||
297 | ret = sb->s_qcop->get_state(sb, &state); | ||
298 | if (ret < 0) | ||
299 | return ret; | ||
300 | |||
301 | memset(fqs, 0, sizeof(*fqs)); | ||
302 | fqs->qs_version = FS_QSTAT_VERSION; | ||
303 | fqs->qs_flags = quota_state_to_flags(&state); | ||
304 | /* No quota enabled? */ | ||
305 | if (!fqs->qs_flags) | ||
306 | return -ENOSYS; | ||
307 | fqs->qs_incoredqs = state.s_incoredqs; | ||
308 | /* | ||
309 | * GETXSTATE quotactl has space for just one set of time limits so | ||
310 | * report them for the first enabled quota type | ||
311 | */ | ||
312 | for (type = 0; type < XQM_MAXQUOTAS; type++) | ||
313 | if (state.s_state[type].flags & QCI_ACCT_ENABLED) | ||
314 | break; | ||
315 | BUG_ON(type == XQM_MAXQUOTAS); | ||
316 | fqs->qs_btimelimit = state.s_state[type].spc_timelimit; | ||
317 | fqs->qs_itimelimit = state.s_state[type].ino_timelimit; | ||
318 | fqs->qs_rtbtimelimit = state.s_state[type].rt_spc_timelimit; | ||
319 | fqs->qs_bwarnlimit = state.s_state[type].spc_warnlimit; | ||
320 | fqs->qs_iwarnlimit = state.s_state[type].ino_warnlimit; | ||
321 | if (state.s_state[USRQUOTA].flags & QCI_ACCT_ENABLED) { | ||
322 | fqs->qs_uquota.qfs_ino = state.s_state[USRQUOTA].ino; | ||
323 | fqs->qs_uquota.qfs_nblks = state.s_state[USRQUOTA].blocks; | ||
324 | fqs->qs_uquota.qfs_nextents = state.s_state[USRQUOTA].nextents; | ||
325 | } | ||
326 | if (state.s_state[GRPQUOTA].flags & QCI_ACCT_ENABLED) { | ||
327 | fqs->qs_gquota.qfs_ino = state.s_state[GRPQUOTA].ino; | ||
328 | fqs->qs_gquota.qfs_nblks = state.s_state[GRPQUOTA].blocks; | ||
329 | fqs->qs_gquota.qfs_nextents = state.s_state[GRPQUOTA].nextents; | ||
330 | } | ||
331 | if (state.s_state[PRJQUOTA].flags & QCI_ACCT_ENABLED) { | ||
332 | /* | ||
333 | * Q_XGETQSTAT doesn't have room for both group and project | ||
334 | * quotas. So, allow the project quota values to be copied out | ||
335 | * only if there is no group quota information available. | ||
336 | */ | ||
337 | if (!(state.s_state[GRPQUOTA].flags & QCI_ACCT_ENABLED)) { | ||
338 | fqs->qs_gquota.qfs_ino = state.s_state[PRJQUOTA].ino; | ||
339 | fqs->qs_gquota.qfs_nblks = | ||
340 | state.s_state[PRJQUOTA].blocks; | ||
341 | fqs->qs_gquota.qfs_nextents = | ||
342 | state.s_state[PRJQUOTA].nextents; | ||
343 | } | ||
344 | } | ||
345 | return 0; | ||
346 | } | ||
347 | |||
272 | static int quota_getxstate(struct super_block *sb, void __user *addr) | 348 | static int quota_getxstate(struct super_block *sb, void __user *addr) |
273 | { | 349 | { |
274 | struct fs_quota_stat fqs; | 350 | struct fs_quota_stat fqs; |
275 | int ret; | 351 | int ret; |
276 | 352 | ||
277 | if (!sb->s_qcop->get_xstate) | 353 | if (!sb->s_qcop->get_xstate && !sb->s_qcop->get_state) |
278 | return -ENOSYS; | 354 | return -ENOSYS; |
279 | ret = sb->s_qcop->get_xstate(sb, &fqs); | 355 | if (sb->s_qcop->get_state) |
356 | ret = quota_getstate(sb, &fqs); | ||
357 | else | ||
358 | ret = sb->s_qcop->get_xstate(sb, &fqs); | ||
280 | if (!ret && copy_to_user(addr, &fqs, sizeof(fqs))) | 359 | if (!ret && copy_to_user(addr, &fqs, sizeof(fqs))) |
281 | return -EFAULT; | 360 | return -EFAULT; |
282 | return ret; | 361 | return ret; |
283 | } | 362 | } |
284 | 363 | ||
364 | static int quota_getstatev(struct super_block *sb, struct fs_quota_statv *fqs) | ||
365 | { | ||
366 | int type; | ||
367 | struct qc_state state; | ||
368 | int ret; | ||
369 | |||
370 | ret = sb->s_qcop->get_state(sb, &state); | ||
371 | if (ret < 0) | ||
372 | return ret; | ||
373 | |||
374 | memset(fqs, 0, sizeof(*fqs)); | ||
375 | fqs->qs_version = FS_QSTAT_VERSION; | ||
376 | fqs->qs_flags = quota_state_to_flags(&state); | ||
377 | /* No quota enabled? */ | ||
378 | if (!fqs->qs_flags) | ||
379 | return -ENOSYS; | ||
380 | fqs->qs_incoredqs = state.s_incoredqs; | ||
381 | /* | ||
382 | * GETXSTATV quotactl has space for just one set of time limits so | ||
383 | * report them for the first enabled quota type | ||
384 | */ | ||
385 | for (type = 0; type < XQM_MAXQUOTAS; type++) | ||
386 | if (state.s_state[type].flags & QCI_ACCT_ENABLED) | ||
387 | break; | ||
388 | BUG_ON(type == XQM_MAXQUOTAS); | ||
389 | fqs->qs_btimelimit = state.s_state[type].spc_timelimit; | ||
390 | fqs->qs_itimelimit = state.s_state[type].ino_timelimit; | ||
391 | fqs->qs_rtbtimelimit = state.s_state[type].rt_spc_timelimit; | ||
392 | fqs->qs_bwarnlimit = state.s_state[type].spc_warnlimit; | ||
393 | fqs->qs_iwarnlimit = state.s_state[type].ino_warnlimit; | ||
394 | if (state.s_state[USRQUOTA].flags & QCI_ACCT_ENABLED) { | ||
395 | fqs->qs_uquota.qfs_ino = state.s_state[USRQUOTA].ino; | ||
396 | fqs->qs_uquota.qfs_nblks = state.s_state[USRQUOTA].blocks; | ||
397 | fqs->qs_uquota.qfs_nextents = state.s_state[USRQUOTA].nextents; | ||
398 | } | ||
399 | if (state.s_state[GRPQUOTA].flags & QCI_ACCT_ENABLED) { | ||
400 | fqs->qs_gquota.qfs_ino = state.s_state[GRPQUOTA].ino; | ||
401 | fqs->qs_gquota.qfs_nblks = state.s_state[GRPQUOTA].blocks; | ||
402 | fqs->qs_gquota.qfs_nextents = state.s_state[GRPQUOTA].nextents; | ||
403 | } | ||
404 | if (state.s_state[PRJQUOTA].flags & QCI_ACCT_ENABLED) { | ||
405 | fqs->qs_pquota.qfs_ino = state.s_state[PRJQUOTA].ino; | ||
406 | fqs->qs_pquota.qfs_nblks = state.s_state[PRJQUOTA].blocks; | ||
407 | fqs->qs_pquota.qfs_nextents = state.s_state[PRJQUOTA].nextents; | ||
408 | } | ||
409 | return 0; | ||
410 | } | ||
411 | |||
285 | static int quota_getxstatev(struct super_block *sb, void __user *addr) | 412 | static int quota_getxstatev(struct super_block *sb, void __user *addr) |
286 | { | 413 | { |
287 | struct fs_quota_statv fqs; | 414 | struct fs_quota_statv fqs; |
288 | int ret; | 415 | int ret; |
289 | 416 | ||
290 | if (!sb->s_qcop->get_xstatev) | 417 | if (!sb->s_qcop->get_xstatev && !sb->s_qcop->get_state) |
291 | return -ENOSYS; | 418 | return -ENOSYS; |
292 | 419 | ||
293 | memset(&fqs, 0, sizeof(fqs)); | 420 | memset(&fqs, 0, sizeof(fqs)); |
@@ -301,7 +428,10 @@ static int quota_getxstatev(struct super_block *sb, void __user *addr) | |||
301 | default: | 428 | default: |
302 | return -EINVAL; | 429 | return -EINVAL; |
303 | } | 430 | } |
304 | ret = sb->s_qcop->get_xstatev(sb, &fqs); | 431 | if (sb->s_qcop->get_state) |
432 | ret = quota_getstatev(sb, &fqs); | ||
433 | else | ||
434 | ret = sb->s_qcop->get_xstatev(sb, &fqs); | ||
305 | if (!ret && copy_to_user(addr, &fqs, sizeof(fqs))) | 435 | if (!ret && copy_to_user(addr, &fqs, sizeof(fqs))) |
306 | return -EFAULT; | 436 | return -EFAULT; |
307 | return ret; | 437 | return ret; |