aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2015-03-16 05:26:41 -0400
committerJan Kara <jack@suse.cz>2015-03-16 05:26:41 -0400
commit7dca0548a21e5efa445b68a73554ef863e09c623 (patch)
tree816483928c6da02928a256fb64617071f98552ed
parent1be440de2ac5181495a7295fa9a4c8ad0793f056 (diff)
parentc39fb53b48c851b185c22548153581d78f2acc11 (diff)
Merge branch 'quota_interface' into for_next_testing
-rw-r--r--fs/ext3/super.c2
-rw-r--r--fs/ext4/super.c2
-rw-r--r--fs/gfs2/quota.c28
-rw-r--r--fs/quota/dquot.c68
-rw-r--r--fs/quota/quota.c217
-rw-r--r--fs/reiserfs/super.c2
-rw-r--r--fs/xfs/xfs_qm.h4
-rw-r--r--fs/xfs/xfs_qm_syscalls.c176
-rw-r--r--fs/xfs/xfs_quotaops.c117
-rw-r--r--include/linux/quota.h56
-rw-r--r--include/linux/quotaops.h4
11 files changed, 422 insertions, 254 deletions
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index d4dbf3c259b3..f037b4b27300 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -789,7 +789,7 @@ static const struct quotactl_ops ext3_qctl_operations = {
789 .quota_on = ext3_quota_on, 789 .quota_on = ext3_quota_on,
790 .quota_off = dquot_quota_off, 790 .quota_off = dquot_quota_off,
791 .quota_sync = dquot_quota_sync, 791 .quota_sync = dquot_quota_sync,
792 .get_info = dquot_get_dqinfo, 792 .get_state = dquot_get_state,
793 .set_info = dquot_set_dqinfo, 793 .set_info = dquot_set_dqinfo,
794 .get_dqblk = dquot_get_dqblk, 794 .get_dqblk = dquot_get_dqblk,
795 .set_dqblk = dquot_set_dqblk 795 .set_dqblk = dquot_set_dqblk
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index e061e66c8280..d348c7d29d80 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1076,7 +1076,7 @@ static const struct quotactl_ops ext4_qctl_operations = {
1076 .quota_on = ext4_quota_on, 1076 .quota_on = ext4_quota_on,
1077 .quota_off = ext4_quota_off, 1077 .quota_off = ext4_quota_off,
1078 .quota_sync = dquot_quota_sync, 1078 .quota_sync = dquot_quota_sync,
1079 .get_info = dquot_get_dqinfo, 1079 .get_state = dquot_get_state,
1080 .set_info = dquot_set_dqinfo, 1080 .set_info = dquot_set_dqinfo,
1081 .get_dqblk = dquot_get_dqblk, 1081 .get_dqblk = dquot_get_dqblk,
1082 .set_dqblk = dquot_set_dqblk 1082 .set_dqblk = dquot_set_dqblk
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index 3aa17d4d1cfc..fa54cbf4c866 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -1468,32 +1468,34 @@ int gfs2_quotad(void *data)
1468 return 0; 1468 return 0;
1469} 1469}
1470 1470
1471static int gfs2_quota_get_xstate(struct super_block *sb, 1471static int gfs2_quota_get_state(struct super_block *sb, struct qc_state *state)
1472 struct fs_quota_stat *fqs)
1473{ 1472{
1474 struct gfs2_sbd *sdp = sb->s_fs_info; 1473 struct gfs2_sbd *sdp = sb->s_fs_info;
1475 1474
1476 memset(fqs, 0, sizeof(struct fs_quota_stat)); 1475 memset(state, 0, sizeof(*state));
1477 fqs->qs_version = FS_QSTAT_VERSION;
1478 1476
1479 switch (sdp->sd_args.ar_quota) { 1477 switch (sdp->sd_args.ar_quota) {
1480 case GFS2_QUOTA_ON: 1478 case GFS2_QUOTA_ON:
1481 fqs->qs_flags |= (FS_QUOTA_UDQ_ENFD | FS_QUOTA_GDQ_ENFD); 1479 state->s_state[USRQUOTA].flags |= QCI_LIMITS_ENFORCED;
1480 state->s_state[GRPQUOTA].flags |= QCI_LIMITS_ENFORCED;
1482 /*FALLTHRU*/ 1481 /*FALLTHRU*/
1483 case GFS2_QUOTA_ACCOUNT: 1482 case GFS2_QUOTA_ACCOUNT:
1484 fqs->qs_flags |= (FS_QUOTA_UDQ_ACCT | FS_QUOTA_GDQ_ACCT); 1483 state->s_state[USRQUOTA].flags |= QCI_ACCT_ENABLED |
1484 QCI_SYSFILE;
1485 state->s_state[GRPQUOTA].flags |= QCI_ACCT_ENABLED |
1486 QCI_SYSFILE;
1485 break; 1487 break;
1486 case GFS2_QUOTA_OFF: 1488 case GFS2_QUOTA_OFF:
1487 break; 1489 break;
1488 } 1490 }
1489
1490 if (sdp->sd_quota_inode) { 1491 if (sdp->sd_quota_inode) {
1491 fqs->qs_uquota.qfs_ino = GFS2_I(sdp->sd_quota_inode)->i_no_addr; 1492 state->s_state[USRQUOTA].ino =
1492 fqs->qs_uquota.qfs_nblks = sdp->sd_quota_inode->i_blocks; 1493 GFS2_I(sdp->sd_quota_inode)->i_no_addr;
1494 state->s_state[USRQUOTA].blocks = sdp->sd_quota_inode->i_blocks;
1493 } 1495 }
1494 fqs->qs_uquota.qfs_nextents = 1; /* unsupported */ 1496 state->s_state[USRQUOTA].nextents = 1; /* unsupported */
1495 fqs->qs_gquota = fqs->qs_uquota; /* its the same inode in both cases */ 1497 state->s_state[GRPQUOTA] = state->s_state[USRQUOTA];
1496 fqs->qs_incoredqs = list_lru_count(&gfs2_qd_lru); 1498 state->s_incoredqs = list_lru_count(&gfs2_qd_lru);
1497 return 0; 1499 return 0;
1498} 1500}
1499 1501
@@ -1638,7 +1640,7 @@ out_put:
1638 1640
1639const struct quotactl_ops gfs2_quotactl_ops = { 1641const struct quotactl_ops gfs2_quotactl_ops = {
1640 .quota_sync = gfs2_quota_sync, 1642 .quota_sync = gfs2_quota_sync,
1641 .get_xstate = gfs2_quota_get_xstate, 1643 .get_state = gfs2_quota_get_state,
1642 .get_dqblk = gfs2_get_dqblk, 1644 .get_dqblk = gfs2_get_dqblk,
1643 .set_dqblk = gfs2_set_dqblk, 1645 .set_dqblk = gfs2_set_dqblk,
1644}; 1646};
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
index 2112ed33de41..327a58448592 100644
--- a/fs/quota/dquot.c
+++ b/fs/quota/dquot.c
@@ -2629,55 +2629,73 @@ out:
2629EXPORT_SYMBOL(dquot_set_dqblk); 2629EXPORT_SYMBOL(dquot_set_dqblk);
2630 2630
2631/* Generic routine for getting common part of quota file information */ 2631/* Generic routine for getting common part of quota file information */
2632int dquot_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii) 2632int dquot_get_state(struct super_block *sb, struct qc_state *state)
2633{ 2633{
2634 struct mem_dqinfo *mi; 2634 struct mem_dqinfo *mi;
2635 struct qc_type_state *tstate;
2636 struct quota_info *dqopt = sb_dqopt(sb);
2637 int type;
2635 2638
2636 mutex_lock(&sb_dqopt(sb)->dqonoff_mutex); 2639 mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
2637 if (!sb_has_quota_active(sb, type)) { 2640 memset(state, 0, sizeof(*state));
2638 mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex); 2641 for (type = 0; type < MAXQUOTAS; type++) {
2639 return -ESRCH; 2642 if (!sb_has_quota_active(sb, type))
2643 continue;
2644 tstate = state->s_state + type;
2645 mi = sb_dqopt(sb)->info + type;
2646 tstate->flags = QCI_ACCT_ENABLED;
2647 spin_lock(&dq_data_lock);
2648 if (mi->dqi_flags & DQF_SYS_FILE)
2649 tstate->flags |= QCI_SYSFILE;
2650 if (mi->dqi_flags & DQF_ROOT_SQUASH)
2651 tstate->flags |= QCI_ROOT_SQUASH;
2652 if (sb_has_quota_limits_enabled(sb, type))
2653 tstate->flags |= QCI_LIMITS_ENFORCED;
2654 tstate->spc_timelimit = mi->dqi_bgrace;
2655 tstate->ino_timelimit = mi->dqi_igrace;
2656 tstate->ino = dqopt->files[type]->i_ino;
2657 tstate->blocks = dqopt->files[type]->i_blocks;
2658 tstate->nextents = 1; /* We don't know... */
2659 spin_unlock(&dq_data_lock);
2640 } 2660 }
2641 mi = sb_dqopt(sb)->info + type;
2642 spin_lock(&dq_data_lock);
2643 ii->dqi_bgrace = mi->dqi_bgrace;
2644 ii->dqi_igrace = mi->dqi_igrace;
2645 ii->dqi_flags = mi->dqi_flags & DQF_GETINFO_MASK;
2646 ii->dqi_valid = IIF_ALL;
2647 spin_unlock(&dq_data_lock);
2648 mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex); 2661 mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
2649 return 0; 2662 return 0;
2650} 2663}
2651EXPORT_SYMBOL(dquot_get_dqinfo); 2664EXPORT_SYMBOL(dquot_get_state);
2652 2665
2653/* Generic routine for setting common part of quota file information */ 2666/* Generic routine for setting common part of quota file information */
2654int dquot_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii) 2667int dquot_set_dqinfo(struct super_block *sb, int type, struct qc_info *ii)
2655{ 2668{
2656 struct mem_dqinfo *mi; 2669 struct mem_dqinfo *mi;
2657 int err = 0; 2670 int err = 0;
2658 2671
2672 if ((ii->i_fieldmask & QC_WARNS_MASK) ||
2673 (ii->i_fieldmask & QC_RT_SPC_TIMER))
2674 return -EINVAL;
2659 mutex_lock(&sb_dqopt(sb)->dqonoff_mutex); 2675 mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
2660 if (!sb_has_quota_active(sb, type)) { 2676 if (!sb_has_quota_active(sb, type)) {
2661 err = -ESRCH; 2677 err = -ESRCH;
2662 goto out; 2678 goto out;
2663 } 2679 }
2664 mi = sb_dqopt(sb)->info + type; 2680 mi = sb_dqopt(sb)->info + type;
2665 if (ii->dqi_valid & IIF_FLAGS) { 2681 if (ii->i_fieldmask & QC_FLAGS) {
2666 if (ii->dqi_flags & ~DQF_SETINFO_MASK || 2682 if ((ii->i_flags & QCI_ROOT_SQUASH &&
2667 (ii->dqi_flags & DQF_ROOT_SQUASH &&
2668 mi->dqi_format->qf_fmt_id != QFMT_VFS_OLD)) { 2683 mi->dqi_format->qf_fmt_id != QFMT_VFS_OLD)) {
2669 err = -EINVAL; 2684 err = -EINVAL;
2670 goto out; 2685 goto out;
2671 } 2686 }
2672 } 2687 }
2673 spin_lock(&dq_data_lock); 2688 spin_lock(&dq_data_lock);
2674 if (ii->dqi_valid & IIF_BGRACE) 2689 if (ii->i_fieldmask & QC_SPC_TIMER)
2675 mi->dqi_bgrace = ii->dqi_bgrace; 2690 mi->dqi_bgrace = ii->i_spc_timelimit;
2676 if (ii->dqi_valid & IIF_IGRACE) 2691 if (ii->i_fieldmask & QC_INO_TIMER)
2677 mi->dqi_igrace = ii->dqi_igrace; 2692 mi->dqi_igrace = ii->i_ino_timelimit;
2678 if (ii->dqi_valid & IIF_FLAGS) 2693 if (ii->i_fieldmask & QC_FLAGS) {
2679 mi->dqi_flags = (mi->dqi_flags & ~DQF_SETINFO_MASK) | 2694 if (ii->i_flags & QCI_ROOT_SQUASH)
2680 (ii->dqi_flags & DQF_SETINFO_MASK); 2695 mi->dqi_flags |= DQF_ROOT_SQUASH;
2696 else
2697 mi->dqi_flags &= ~DQF_ROOT_SQUASH;
2698 }
2681 spin_unlock(&dq_data_lock); 2699 spin_unlock(&dq_data_lock);
2682 mark_info_dirty(sb, type); 2700 mark_info_dirty(sb, type);
2683 /* Force write to disk */ 2701 /* Force write to disk */
@@ -2692,7 +2710,7 @@ const struct quotactl_ops dquot_quotactl_ops = {
2692 .quota_on = dquot_quota_on, 2710 .quota_on = dquot_quota_on,
2693 .quota_off = dquot_quota_off, 2711 .quota_off = dquot_quota_off,
2694 .quota_sync = dquot_quota_sync, 2712 .quota_sync = dquot_quota_sync,
2695 .get_info = dquot_get_dqinfo, 2713 .get_state = dquot_get_state,
2696 .set_info = dquot_set_dqinfo, 2714 .set_info = dquot_set_dqinfo,
2697 .get_dqblk = dquot_get_dqblk, 2715 .get_dqblk = dquot_get_dqblk,
2698 .set_dqblk = dquot_set_dqblk 2716 .set_dqblk = dquot_set_dqblk
@@ -2703,7 +2721,7 @@ const struct quotactl_ops dquot_quotactl_sysfile_ops = {
2703 .quota_enable = dquot_quota_enable, 2721 .quota_enable = dquot_quota_enable,
2704 .quota_disable = dquot_quota_disable, 2722 .quota_disable = dquot_quota_disable,
2705 .quota_sync = dquot_quota_sync, 2723 .quota_sync = dquot_quota_sync,
2706 .get_info = dquot_get_dqinfo, 2724 .get_state = dquot_get_state,
2707 .set_info = dquot_set_dqinfo, 2725 .set_info = dquot_set_dqinfo,
2708 .get_dqblk = dquot_get_dqblk, 2726 .get_dqblk = dquot_get_dqblk,
2709 .set_dqblk = dquot_set_dqblk 2727 .set_dqblk = dquot_set_dqblk
diff --git a/fs/quota/quota.c b/fs/quota/quota.c
index d14a799c7785..86ded7375c21 100644
--- a/fs/quota/quota.c
+++ b/fs/quota/quota.c
@@ -118,13 +118,30 @@ static int quota_getfmt(struct super_block *sb, int type, void __user *addr)
118 118
119static int quota_getinfo(struct super_block *sb, int type, void __user *addr) 119static int quota_getinfo(struct super_block *sb, int type, void __user *addr)
120{ 120{
121 struct if_dqinfo info; 121 struct qc_state state;
122 struct qc_type_state *tstate;
123 struct if_dqinfo uinfo;
122 int ret; 124 int ret;
123 125
124 if (!sb->s_qcop->get_info) 126 /* This checks whether qc_state has enough entries... */
127 BUILD_BUG_ON(MAXQUOTAS > XQM_MAXQUOTAS);
128 if (!sb->s_qcop->get_state)
125 return -ENOSYS; 129 return -ENOSYS;
126 ret = sb->s_qcop->get_info(sb, type, &info); 130 ret = sb->s_qcop->get_state(sb, &state);
127 if (!ret && copy_to_user(addr, &info, sizeof(info))) 131 if (ret)
132 return ret;
133 tstate = state.s_state + type;
134 if (!(tstate->flags & QCI_ACCT_ENABLED))
135 return -ESRCH;
136 memset(&uinfo, 0, sizeof(uinfo));
137 uinfo.dqi_bgrace = tstate->spc_timelimit;
138 uinfo.dqi_igrace = tstate->ino_timelimit;
139 if (tstate->flags & QCI_SYSFILE)
140 uinfo.dqi_flags |= DQF_SYS_FILE;
141 if (tstate->flags & QCI_ROOT_SQUASH)
142 uinfo.dqi_flags |= DQF_ROOT_SQUASH;
143 uinfo.dqi_valid = IIF_ALL;
144 if (!ret && copy_to_user(addr, &uinfo, sizeof(uinfo)))
128 return -EFAULT; 145 return -EFAULT;
129 return ret; 146 return ret;
130} 147}
@@ -132,12 +149,31 @@ static int quota_getinfo(struct super_block *sb, int type, void __user *addr)
132static int quota_setinfo(struct super_block *sb, int type, void __user *addr) 149static int quota_setinfo(struct super_block *sb, int type, void __user *addr)
133{ 150{
134 struct if_dqinfo info; 151 struct if_dqinfo info;
152 struct qc_info qinfo;
135 153
136 if (copy_from_user(&info, addr, sizeof(info))) 154 if (copy_from_user(&info, addr, sizeof(info)))
137 return -EFAULT; 155 return -EFAULT;
138 if (!sb->s_qcop->set_info) 156 if (!sb->s_qcop->set_info)
139 return -ENOSYS; 157 return -ENOSYS;
140 return sb->s_qcop->set_info(sb, type, &info); 158 if (info.dqi_valid & ~(IIF_FLAGS | IIF_BGRACE | IIF_IGRACE))
159 return -EINVAL;
160 memset(&qinfo, 0, sizeof(qinfo));
161 if (info.dqi_valid & IIF_FLAGS) {
162 if (info.dqi_flags & ~DQF_SETINFO_MASK)
163 return -EINVAL;
164 if (info.dqi_flags & DQF_ROOT_SQUASH)
165 qinfo.i_flags |= QCI_ROOT_SQUASH;
166 qinfo.i_fieldmask |= QC_FLAGS;
167 }
168 if (info.dqi_valid & IIF_BGRACE) {
169 qinfo.i_spc_timelimit = info.dqi_bgrace;
170 qinfo.i_fieldmask |= QC_SPC_TIMER;
171 }
172 if (info.dqi_valid & IIF_IGRACE) {
173 qinfo.i_ino_timelimit = info.dqi_igrace;
174 qinfo.i_fieldmask |= QC_INO_TIMER;
175 }
176 return sb->s_qcop->set_info(sb, type, &qinfo);
141} 177}
142 178
143static inline qsize_t qbtos(qsize_t blocks) 179static inline qsize_t qbtos(qsize_t blocks)
@@ -252,25 +288,149 @@ static int quota_disable(struct super_block *sb, void __user *addr)
252 return sb->s_qcop->quota_disable(sb, flags); 288 return sb->s_qcop->quota_disable(sb, flags);
253} 289}
254 290
291static int quota_state_to_flags(struct qc_state *state)
292{
293 int flags = 0;
294
295 if (state->s_state[USRQUOTA].flags & QCI_ACCT_ENABLED)
296 flags |= FS_QUOTA_UDQ_ACCT;
297 if (state->s_state[USRQUOTA].flags & QCI_LIMITS_ENFORCED)
298 flags |= FS_QUOTA_UDQ_ENFD;
299 if (state->s_state[GRPQUOTA].flags & QCI_ACCT_ENABLED)
300 flags |= FS_QUOTA_GDQ_ACCT;
301 if (state->s_state[GRPQUOTA].flags & QCI_LIMITS_ENFORCED)
302 flags |= FS_QUOTA_GDQ_ENFD;
303 if (state->s_state[PRJQUOTA].flags & QCI_ACCT_ENABLED)
304 flags |= FS_QUOTA_PDQ_ACCT;
305 if (state->s_state[PRJQUOTA].flags & QCI_LIMITS_ENFORCED)
306 flags |= FS_QUOTA_PDQ_ENFD;
307 return flags;
308}
309
310static int quota_getstate(struct super_block *sb, struct fs_quota_stat *fqs)
311{
312 int type;
313 struct qc_state state;
314 int ret;
315
316 ret = sb->s_qcop->get_state(sb, &state);
317 if (ret < 0)
318 return ret;
319
320 memset(fqs, 0, sizeof(*fqs));
321 fqs->qs_version = FS_QSTAT_VERSION;
322 fqs->qs_flags = quota_state_to_flags(&state);
323 /* No quota enabled? */
324 if (!fqs->qs_flags)
325 return -ENOSYS;
326 fqs->qs_incoredqs = state.s_incoredqs;
327 /*
328 * GETXSTATE quotactl has space for just one set of time limits so
329 * report them for the first enabled quota type
330 */
331 for (type = 0; type < XQM_MAXQUOTAS; type++)
332 if (state.s_state[type].flags & QCI_ACCT_ENABLED)
333 break;
334 BUG_ON(type == XQM_MAXQUOTAS);
335 fqs->qs_btimelimit = state.s_state[type].spc_timelimit;
336 fqs->qs_itimelimit = state.s_state[type].ino_timelimit;
337 fqs->qs_rtbtimelimit = state.s_state[type].rt_spc_timelimit;
338 fqs->qs_bwarnlimit = state.s_state[type].spc_warnlimit;
339 fqs->qs_iwarnlimit = state.s_state[type].ino_warnlimit;
340 if (state.s_state[USRQUOTA].flags & QCI_ACCT_ENABLED) {
341 fqs->qs_uquota.qfs_ino = state.s_state[USRQUOTA].ino;
342 fqs->qs_uquota.qfs_nblks = state.s_state[USRQUOTA].blocks;
343 fqs->qs_uquota.qfs_nextents = state.s_state[USRQUOTA].nextents;
344 }
345 if (state.s_state[GRPQUOTA].flags & QCI_ACCT_ENABLED) {
346 fqs->qs_gquota.qfs_ino = state.s_state[GRPQUOTA].ino;
347 fqs->qs_gquota.qfs_nblks = state.s_state[GRPQUOTA].blocks;
348 fqs->qs_gquota.qfs_nextents = state.s_state[GRPQUOTA].nextents;
349 }
350 if (state.s_state[PRJQUOTA].flags & QCI_ACCT_ENABLED) {
351 /*
352 * Q_XGETQSTAT doesn't have room for both group and project
353 * quotas. So, allow the project quota values to be copied out
354 * only if there is no group quota information available.
355 */
356 if (!(state.s_state[GRPQUOTA].flags & QCI_ACCT_ENABLED)) {
357 fqs->qs_gquota.qfs_ino = state.s_state[PRJQUOTA].ino;
358 fqs->qs_gquota.qfs_nblks =
359 state.s_state[PRJQUOTA].blocks;
360 fqs->qs_gquota.qfs_nextents =
361 state.s_state[PRJQUOTA].nextents;
362 }
363 }
364 return 0;
365}
366
255static int quota_getxstate(struct super_block *sb, void __user *addr) 367static int quota_getxstate(struct super_block *sb, void __user *addr)
256{ 368{
257 struct fs_quota_stat fqs; 369 struct fs_quota_stat fqs;
258 int ret; 370 int ret;
259 371
260 if (!sb->s_qcop->get_xstate) 372 if (!sb->s_qcop->get_state)
261 return -ENOSYS; 373 return -ENOSYS;
262 ret = sb->s_qcop->get_xstate(sb, &fqs); 374 ret = quota_getstate(sb, &fqs);
263 if (!ret && copy_to_user(addr, &fqs, sizeof(fqs))) 375 if (!ret && copy_to_user(addr, &fqs, sizeof(fqs)))
264 return -EFAULT; 376 return -EFAULT;
265 return ret; 377 return ret;
266} 378}
267 379
380static int quota_getstatev(struct super_block *sb, struct fs_quota_statv *fqs)
381{
382 int type;
383 struct qc_state state;
384 int ret;
385
386 ret = sb->s_qcop->get_state(sb, &state);
387 if (ret < 0)
388 return ret;
389
390 memset(fqs, 0, sizeof(*fqs));
391 fqs->qs_version = FS_QSTAT_VERSION;
392 fqs->qs_flags = quota_state_to_flags(&state);
393 /* No quota enabled? */
394 if (!fqs->qs_flags)
395 return -ENOSYS;
396 fqs->qs_incoredqs = state.s_incoredqs;
397 /*
398 * GETXSTATV quotactl has space for just one set of time limits so
399 * report them for the first enabled quota type
400 */
401 for (type = 0; type < XQM_MAXQUOTAS; type++)
402 if (state.s_state[type].flags & QCI_ACCT_ENABLED)
403 break;
404 BUG_ON(type == XQM_MAXQUOTAS);
405 fqs->qs_btimelimit = state.s_state[type].spc_timelimit;
406 fqs->qs_itimelimit = state.s_state[type].ino_timelimit;
407 fqs->qs_rtbtimelimit = state.s_state[type].rt_spc_timelimit;
408 fqs->qs_bwarnlimit = state.s_state[type].spc_warnlimit;
409 fqs->qs_iwarnlimit = state.s_state[type].ino_warnlimit;
410 if (state.s_state[USRQUOTA].flags & QCI_ACCT_ENABLED) {
411 fqs->qs_uquota.qfs_ino = state.s_state[USRQUOTA].ino;
412 fqs->qs_uquota.qfs_nblks = state.s_state[USRQUOTA].blocks;
413 fqs->qs_uquota.qfs_nextents = state.s_state[USRQUOTA].nextents;
414 }
415 if (state.s_state[GRPQUOTA].flags & QCI_ACCT_ENABLED) {
416 fqs->qs_gquota.qfs_ino = state.s_state[GRPQUOTA].ino;
417 fqs->qs_gquota.qfs_nblks = state.s_state[GRPQUOTA].blocks;
418 fqs->qs_gquota.qfs_nextents = state.s_state[GRPQUOTA].nextents;
419 }
420 if (state.s_state[PRJQUOTA].flags & QCI_ACCT_ENABLED) {
421 fqs->qs_pquota.qfs_ino = state.s_state[PRJQUOTA].ino;
422 fqs->qs_pquota.qfs_nblks = state.s_state[PRJQUOTA].blocks;
423 fqs->qs_pquota.qfs_nextents = state.s_state[PRJQUOTA].nextents;
424 }
425 return 0;
426}
427
268static int quota_getxstatev(struct super_block *sb, void __user *addr) 428static int quota_getxstatev(struct super_block *sb, void __user *addr)
269{ 429{
270 struct fs_quota_statv fqs; 430 struct fs_quota_statv fqs;
271 int ret; 431 int ret;
272 432
273 if (!sb->s_qcop->get_xstatev) 433 if (!sb->s_qcop->get_state)
274 return -ENOSYS; 434 return -ENOSYS;
275 435
276 memset(&fqs, 0, sizeof(fqs)); 436 memset(&fqs, 0, sizeof(fqs));
@@ -284,7 +444,7 @@ static int quota_getxstatev(struct super_block *sb, void __user *addr)
284 default: 444 default:
285 return -EINVAL; 445 return -EINVAL;
286 } 446 }
287 ret = sb->s_qcop->get_xstatev(sb, &fqs); 447 ret = quota_getstatev(sb, &fqs);
288 if (!ret && copy_to_user(addr, &fqs, sizeof(fqs))) 448 if (!ret && copy_to_user(addr, &fqs, sizeof(fqs)))
289 return -EFAULT; 449 return -EFAULT;
290 return ret; 450 return ret;
@@ -357,6 +517,30 @@ static void copy_from_xfs_dqblk(struct qc_dqblk *dst, struct fs_disk_quota *src)
357 dst->d_fieldmask |= QC_RT_SPACE; 517 dst->d_fieldmask |= QC_RT_SPACE;
358} 518}
359 519
520static void copy_qcinfo_from_xfs_dqblk(struct qc_info *dst,
521 struct fs_disk_quota *src)
522{
523 memset(dst, 0, sizeof(*dst));
524 dst->i_spc_timelimit = src->d_btimer;
525 dst->i_ino_timelimit = src->d_itimer;
526 dst->i_rt_spc_timelimit = src->d_rtbtimer;
527 dst->i_ino_warnlimit = src->d_iwarns;
528 dst->i_spc_warnlimit = src->d_bwarns;
529 dst->i_rt_spc_warnlimit = src->d_rtbwarns;
530 if (src->d_fieldmask & FS_DQ_BWARNS)
531 dst->i_fieldmask |= QC_SPC_WARNS;
532 if (src->d_fieldmask & FS_DQ_IWARNS)
533 dst->i_fieldmask |= QC_INO_WARNS;
534 if (src->d_fieldmask & FS_DQ_RTBWARNS)
535 dst->i_fieldmask |= QC_RT_SPC_WARNS;
536 if (src->d_fieldmask & FS_DQ_BTIMER)
537 dst->i_fieldmask |= QC_SPC_TIMER;
538 if (src->d_fieldmask & FS_DQ_ITIMER)
539 dst->i_fieldmask |= QC_INO_TIMER;
540 if (src->d_fieldmask & FS_DQ_RTBTIMER)
541 dst->i_fieldmask |= QC_RT_SPC_TIMER;
542}
543
360static int quota_setxquota(struct super_block *sb, int type, qid_t id, 544static int quota_setxquota(struct super_block *sb, int type, qid_t id,
361 void __user *addr) 545 void __user *addr)
362{ 546{
@@ -371,6 +555,21 @@ static int quota_setxquota(struct super_block *sb, int type, qid_t id,
371 qid = make_kqid(current_user_ns(), type, id); 555 qid = make_kqid(current_user_ns(), type, id);
372 if (!qid_valid(qid)) 556 if (!qid_valid(qid))
373 return -EINVAL; 557 return -EINVAL;
558 /* Are we actually setting timer / warning limits for all users? */
559 if (from_kqid(&init_user_ns, qid) == 0 &&
560 fdq.d_fieldmask & (FS_DQ_WARNS_MASK | FS_DQ_TIMER_MASK)) {
561 struct qc_info qinfo;
562 int ret;
563
564 if (!sb->s_qcop->set_info)
565 return -EINVAL;
566 copy_qcinfo_from_xfs_dqblk(&qinfo, &fdq);
567 ret = sb->s_qcop->set_info(sb, type, &qinfo);
568 if (ret)
569 return ret;
570 /* These are already done */
571 fdq.d_fieldmask &= ~(FS_DQ_WARNS_MASK | FS_DQ_TIMER_MASK);
572 }
374 copy_from_xfs_dqblk(&qdq, &fdq); 573 copy_from_xfs_dqblk(&qdq, &fdq);
375 return sb->s_qcop->set_dqblk(sb, qid, &qdq); 574 return sb->s_qcop->set_dqblk(sb, qid, &qdq);
376} 575}
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index 71fbbe3e2dab..68b5f182984e 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -805,7 +805,7 @@ static const struct quotactl_ops reiserfs_qctl_operations = {
805 .quota_on = reiserfs_quota_on, 805 .quota_on = reiserfs_quota_on,
806 .quota_off = dquot_quota_off, 806 .quota_off = dquot_quota_off,
807 .quota_sync = dquot_quota_sync, 807 .quota_sync = dquot_quota_sync,
808 .get_info = dquot_get_dqinfo, 808 .get_state = dquot_get_state,
809 .set_info = dquot_set_dqinfo, 809 .set_info = dquot_set_dqinfo,
810 .get_dqblk = dquot_get_dqblk, 810 .get_dqblk = dquot_get_dqblk,
811 .set_dqblk = dquot_set_dqblk, 811 .set_dqblk = dquot_set_dqblk,
diff --git a/fs/xfs/xfs_qm.h b/fs/xfs/xfs_qm.h
index 0d4d3590cf85..996a04064894 100644
--- a/fs/xfs/xfs_qm.h
+++ b/fs/xfs/xfs_qm.h
@@ -168,10 +168,6 @@ extern int xfs_qm_scall_getquota(struct xfs_mount *, xfs_dqid_t,
168 uint, struct qc_dqblk *); 168 uint, struct qc_dqblk *);
169extern int xfs_qm_scall_setqlim(struct xfs_mount *, xfs_dqid_t, uint, 169extern int xfs_qm_scall_setqlim(struct xfs_mount *, xfs_dqid_t, uint,
170 struct qc_dqblk *); 170 struct qc_dqblk *);
171extern int xfs_qm_scall_getqstat(struct xfs_mount *,
172 struct fs_quota_stat *);
173extern int xfs_qm_scall_getqstatv(struct xfs_mount *,
174 struct fs_quota_statv *);
175extern int xfs_qm_scall_quotaon(struct xfs_mount *, uint); 171extern int xfs_qm_scall_quotaon(struct xfs_mount *, uint);
176extern int xfs_qm_scall_quotaoff(struct xfs_mount *, uint); 172extern int xfs_qm_scall_quotaoff(struct xfs_mount *, uint);
177 173
diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
index 9b965db45800..9a25c9275fb3 100644
--- a/fs/xfs/xfs_qm_syscalls.c
+++ b/fs/xfs/xfs_qm_syscalls.c
@@ -38,7 +38,6 @@
38STATIC int xfs_qm_log_quotaoff(xfs_mount_t *, xfs_qoff_logitem_t **, uint); 38STATIC int xfs_qm_log_quotaoff(xfs_mount_t *, xfs_qoff_logitem_t **, uint);
39STATIC int xfs_qm_log_quotaoff_end(xfs_mount_t *, xfs_qoff_logitem_t *, 39STATIC int xfs_qm_log_quotaoff_end(xfs_mount_t *, xfs_qoff_logitem_t *,
40 uint); 40 uint);
41STATIC uint xfs_qm_export_flags(uint);
42 41
43/* 42/*
44 * Turn off quota accounting and/or enforcement for all udquots and/or 43 * Turn off quota accounting and/or enforcement for all udquots and/or
@@ -389,159 +388,6 @@ xfs_qm_scall_quotaon(
389 return 0; 388 return 0;
390} 389}
391 390
392
393/*
394 * Return quota status information, such as uquota-off, enforcements, etc.
395 * for Q_XGETQSTAT command.
396 */
397int
398xfs_qm_scall_getqstat(
399 struct xfs_mount *mp,
400 struct fs_quota_stat *out)
401{
402 struct xfs_quotainfo *q = mp->m_quotainfo;
403 struct xfs_inode *uip = NULL;
404 struct xfs_inode *gip = NULL;
405 struct xfs_inode *pip = NULL;
406 bool tempuqip = false;
407 bool tempgqip = false;
408 bool temppqip = false;
409
410 memset(out, 0, sizeof(fs_quota_stat_t));
411
412 out->qs_version = FS_QSTAT_VERSION;
413 out->qs_flags = (__uint16_t) xfs_qm_export_flags(mp->m_qflags &
414 (XFS_ALL_QUOTA_ACCT|
415 XFS_ALL_QUOTA_ENFD));
416 uip = q->qi_uquotaip;
417 gip = q->qi_gquotaip;
418 pip = q->qi_pquotaip;
419 if (!uip && mp->m_sb.sb_uquotino != NULLFSINO) {
420 if (xfs_iget(mp, NULL, mp->m_sb.sb_uquotino,
421 0, 0, &uip) == 0)
422 tempuqip = true;
423 }
424 if (!gip && mp->m_sb.sb_gquotino != NULLFSINO) {
425 if (xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
426 0, 0, &gip) == 0)
427 tempgqip = true;
428 }
429 /*
430 * Q_XGETQSTAT doesn't have room for both group and project quotas.
431 * So, allow the project quota values to be copied out only if
432 * there is no group quota information available.
433 */
434 if (!gip) {
435 if (!pip && mp->m_sb.sb_pquotino != NULLFSINO) {
436 if (xfs_iget(mp, NULL, mp->m_sb.sb_pquotino,
437 0, 0, &pip) == 0)
438 temppqip = true;
439 }
440 } else
441 pip = NULL;
442 if (uip) {
443 out->qs_uquota.qfs_ino = mp->m_sb.sb_uquotino;
444 out->qs_uquota.qfs_nblks = uip->i_d.di_nblocks;
445 out->qs_uquota.qfs_nextents = uip->i_d.di_nextents;
446 if (tempuqip)
447 IRELE(uip);
448 }
449
450 if (gip) {
451 out->qs_gquota.qfs_ino = mp->m_sb.sb_gquotino;
452 out->qs_gquota.qfs_nblks = gip->i_d.di_nblocks;
453 out->qs_gquota.qfs_nextents = gip->i_d.di_nextents;
454 if (tempgqip)
455 IRELE(gip);
456 }
457 if (pip) {
458 out->qs_gquota.qfs_ino = mp->m_sb.sb_gquotino;
459 out->qs_gquota.qfs_nblks = pip->i_d.di_nblocks;
460 out->qs_gquota.qfs_nextents = pip->i_d.di_nextents;
461 if (temppqip)
462 IRELE(pip);
463 }
464 out->qs_incoredqs = q->qi_dquots;
465 out->qs_btimelimit = q->qi_btimelimit;
466 out->qs_itimelimit = q->qi_itimelimit;
467 out->qs_rtbtimelimit = q->qi_rtbtimelimit;
468 out->qs_bwarnlimit = q->qi_bwarnlimit;
469 out->qs_iwarnlimit = q->qi_iwarnlimit;
470
471 return 0;
472}
473
474/*
475 * Return quota status information, such as uquota-off, enforcements, etc.
476 * for Q_XGETQSTATV command, to support separate project quota field.
477 */
478int
479xfs_qm_scall_getqstatv(
480 struct xfs_mount *mp,
481 struct fs_quota_statv *out)
482{
483 struct xfs_quotainfo *q = mp->m_quotainfo;
484 struct xfs_inode *uip = NULL;
485 struct xfs_inode *gip = NULL;
486 struct xfs_inode *pip = NULL;
487 bool tempuqip = false;
488 bool tempgqip = false;
489 bool temppqip = false;
490
491 out->qs_flags = (__uint16_t) xfs_qm_export_flags(mp->m_qflags &
492 (XFS_ALL_QUOTA_ACCT|
493 XFS_ALL_QUOTA_ENFD));
494 out->qs_uquota.qfs_ino = mp->m_sb.sb_uquotino;
495 out->qs_gquota.qfs_ino = mp->m_sb.sb_gquotino;
496 out->qs_pquota.qfs_ino = mp->m_sb.sb_pquotino;
497
498 uip = q->qi_uquotaip;
499 gip = q->qi_gquotaip;
500 pip = q->qi_pquotaip;
501 if (!uip && mp->m_sb.sb_uquotino != NULLFSINO) {
502 if (xfs_iget(mp, NULL, mp->m_sb.sb_uquotino,
503 0, 0, &uip) == 0)
504 tempuqip = true;
505 }
506 if (!gip && mp->m_sb.sb_gquotino != NULLFSINO) {
507 if (xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
508 0, 0, &gip) == 0)
509 tempgqip = true;
510 }
511 if (!pip && mp->m_sb.sb_pquotino != NULLFSINO) {
512 if (xfs_iget(mp, NULL, mp->m_sb.sb_pquotino,
513 0, 0, &pip) == 0)
514 temppqip = true;
515 }
516 if (uip) {
517 out->qs_uquota.qfs_nblks = uip->i_d.di_nblocks;
518 out->qs_uquota.qfs_nextents = uip->i_d.di_nextents;
519 if (tempuqip)
520 IRELE(uip);
521 }
522
523 if (gip) {
524 out->qs_gquota.qfs_nblks = gip->i_d.di_nblocks;
525 out->qs_gquota.qfs_nextents = gip->i_d.di_nextents;
526 if (tempgqip)
527 IRELE(gip);
528 }
529 if (pip) {
530 out->qs_pquota.qfs_nblks = pip->i_d.di_nblocks;
531 out->qs_pquota.qfs_nextents = pip->i_d.di_nextents;
532 if (temppqip)
533 IRELE(pip);
534 }
535 out->qs_incoredqs = q->qi_dquots;
536 out->qs_btimelimit = q->qi_btimelimit;
537 out->qs_itimelimit = q->qi_itimelimit;
538 out->qs_rtbtimelimit = q->qi_rtbtimelimit;
539 out->qs_bwarnlimit = q->qi_bwarnlimit;
540 out->qs_iwarnlimit = q->qi_iwarnlimit;
541
542 return 0;
543}
544
545#define XFS_QC_MASK \ 391#define XFS_QC_MASK \
546 (QC_LIMIT_MASK | QC_TIMER_MASK | QC_WARNS_MASK) 392 (QC_LIMIT_MASK | QC_TIMER_MASK | QC_WARNS_MASK)
547 393
@@ -873,28 +719,6 @@ out_put:
873 return error; 719 return error;
874} 720}
875 721
876STATIC uint
877xfs_qm_export_flags(
878 uint flags)
879{
880 uint uflags;
881
882 uflags = 0;
883 if (flags & XFS_UQUOTA_ACCT)
884 uflags |= FS_QUOTA_UDQ_ACCT;
885 if (flags & XFS_GQUOTA_ACCT)
886 uflags |= FS_QUOTA_GDQ_ACCT;
887 if (flags & XFS_PQUOTA_ACCT)
888 uflags |= FS_QUOTA_PDQ_ACCT;
889 if (flags & XFS_UQUOTA_ENFD)
890 uflags |= FS_QUOTA_UDQ_ENFD;
891 if (flags & XFS_GQUOTA_ENFD)
892 uflags |= FS_QUOTA_GDQ_ENFD;
893 if (flags & XFS_PQUOTA_ENFD)
894 uflags |= FS_QUOTA_PDQ_ENFD;
895 return uflags;
896}
897
898 722
899STATIC int 723STATIC int
900xfs_dqrele_inode( 724xfs_dqrele_inode(
diff --git a/fs/xfs/xfs_quotaops.c b/fs/xfs/xfs_quotaops.c
index 6923905ab33d..7795e0d01382 100644
--- a/fs/xfs/xfs_quotaops.c
+++ b/fs/xfs/xfs_quotaops.c
@@ -23,10 +23,81 @@
23#include "xfs_inode.h" 23#include "xfs_inode.h"
24#include "xfs_quota.h" 24#include "xfs_quota.h"
25#include "xfs_trans.h" 25#include "xfs_trans.h"
26#include "xfs_trace.h"
27#include "xfs_icache.h"
26#include "xfs_qm.h" 28#include "xfs_qm.h"
27#include <linux/quota.h> 29#include <linux/quota.h>
28 30
29 31
32static void
33xfs_qm_fill_state(
34 struct qc_type_state *tstate,
35 struct xfs_mount *mp,
36 struct xfs_inode *ip,
37 xfs_ino_t ino)
38{
39 struct xfs_quotainfo *q = mp->m_quotainfo;
40 bool tempqip = false;
41
42 tstate->ino = ino;
43 if (!ip && ino == NULLFSINO)
44 return;
45 if (!ip) {
46 if (xfs_iget(mp, NULL, ino, 0, 0, &ip))
47 return;
48 tempqip = true;
49 }
50 tstate->flags |= QCI_SYSFILE;
51 tstate->blocks = ip->i_d.di_nblocks;
52 tstate->nextents = ip->i_d.di_nextents;
53 tstate->spc_timelimit = q->qi_btimelimit;
54 tstate->ino_timelimit = q->qi_itimelimit;
55 tstate->rt_spc_timelimit = q->qi_rtbtimelimit;
56 tstate->spc_warnlimit = q->qi_bwarnlimit;
57 tstate->ino_warnlimit = q->qi_iwarnlimit;
58 tstate->rt_spc_warnlimit = q->qi_rtbwarnlimit;
59 if (tempqip)
60 IRELE(ip);
61}
62
63/*
64 * Return quota status information, such as enforcements, quota file inode
65 * numbers etc.
66 */
67static int
68xfs_fs_get_quota_state(
69 struct super_block *sb,
70 struct qc_state *state)
71{
72 struct xfs_mount *mp = XFS_M(sb);
73 struct xfs_quotainfo *q = mp->m_quotainfo;
74
75 memset(state, 0, sizeof(*state));
76 if (!XFS_IS_QUOTA_RUNNING(mp))
77 return 0;
78 state->s_incoredqs = q->qi_dquots;
79 if (XFS_IS_UQUOTA_RUNNING(mp))
80 state->s_state[USRQUOTA].flags |= QCI_ACCT_ENABLED;
81 if (XFS_IS_UQUOTA_ENFORCED(mp))
82 state->s_state[USRQUOTA].flags |= QCI_LIMITS_ENFORCED;
83 if (XFS_IS_GQUOTA_RUNNING(mp))
84 state->s_state[GRPQUOTA].flags |= QCI_ACCT_ENABLED;
85 if (XFS_IS_GQUOTA_ENFORCED(mp))
86 state->s_state[GRPQUOTA].flags |= QCI_LIMITS_ENFORCED;
87 if (XFS_IS_PQUOTA_RUNNING(mp))
88 state->s_state[PRJQUOTA].flags |= QCI_ACCT_ENABLED;
89 if (XFS_IS_PQUOTA_ENFORCED(mp))
90 state->s_state[PRJQUOTA].flags |= QCI_LIMITS_ENFORCED;
91
92 xfs_qm_fill_state(&state->s_state[USRQUOTA], mp, q->qi_uquotaip,
93 mp->m_sb.sb_uquotino);
94 xfs_qm_fill_state(&state->s_state[GRPQUOTA], mp, q->qi_gquotaip,
95 mp->m_sb.sb_gquotino);
96 xfs_qm_fill_state(&state->s_state[PRJQUOTA], mp, q->qi_pquotaip,
97 mp->m_sb.sb_pquotino);
98 return 0;
99}
100
30STATIC int 101STATIC int
31xfs_quota_type(int type) 102xfs_quota_type(int type)
32{ 103{
@@ -40,28 +111,40 @@ xfs_quota_type(int type)
40 } 111 }
41} 112}
42 113
43STATIC int 114#define XFS_QC_SETINFO_MASK (QC_TIMER_MASK | QC_WARNS_MASK)
44xfs_fs_get_xstate( 115
116/*
117 * Adjust quota timers & warnings
118 */
119static int
120xfs_fs_set_info(
45 struct super_block *sb, 121 struct super_block *sb,
46 struct fs_quota_stat *fqs) 122 int type,
123 struct qc_info *info)
47{ 124{
48 struct xfs_mount *mp = XFS_M(sb); 125 struct xfs_mount *mp = XFS_M(sb);
126 struct qc_dqblk newlim;
49 127
128 if (sb->s_flags & MS_RDONLY)
129 return -EROFS;
50 if (!XFS_IS_QUOTA_RUNNING(mp)) 130 if (!XFS_IS_QUOTA_RUNNING(mp))
51 return -ENOSYS; 131 return -ENOSYS;
52 return xfs_qm_scall_getqstat(mp, fqs); 132 if (!XFS_IS_QUOTA_ON(mp))
53} 133 return -ESRCH;
134 if (info->i_fieldmask & ~XFS_QC_SETINFO_MASK)
135 return -EINVAL;
136 if ((info->i_fieldmask & XFS_QC_SETINFO_MASK) == 0)
137 return 0;
54 138
55STATIC int 139 newlim.d_fieldmask = info->i_fieldmask;
56xfs_fs_get_xstatev( 140 newlim.d_spc_timer = info->i_spc_timelimit;
57 struct super_block *sb, 141 newlim.d_ino_timer = info->i_ino_timelimit;
58 struct fs_quota_statv *fqs) 142 newlim.d_rt_spc_timer = info->i_rt_spc_timelimit;
59{ 143 newlim.d_ino_warns = info->i_ino_warnlimit;
60 struct xfs_mount *mp = XFS_M(sb); 144 newlim.d_spc_warns = info->i_spc_warnlimit;
145 newlim.d_rt_spc_warns = info->i_rt_spc_warnlimit;
61 146
62 if (!XFS_IS_QUOTA_RUNNING(mp)) 147 return xfs_qm_scall_setqlim(mp, 0, xfs_quota_type(type), &newlim);
63 return -ENOSYS;
64 return xfs_qm_scall_getqstatv(mp, fqs);
65} 148}
66 149
67static unsigned int 150static unsigned int
@@ -178,8 +261,8 @@ xfs_fs_set_dqblk(
178} 261}
179 262
180const struct quotactl_ops xfs_quotactl_operations = { 263const struct quotactl_ops xfs_quotactl_operations = {
181 .get_xstatev = xfs_fs_get_xstatev, 264 .get_state = xfs_fs_get_quota_state,
182 .get_xstate = xfs_fs_get_xstate, 265 .set_info = xfs_fs_set_info,
183 .quota_enable = xfs_quota_enable, 266 .quota_enable = xfs_quota_enable,
184 .quota_disable = xfs_quota_disable, 267 .quota_disable = xfs_quota_disable,
185 .rm_xquota = xfs_fs_rm_xquota, 268 .rm_xquota = xfs_fs_rm_xquota,
diff --git a/include/linux/quota.h b/include/linux/quota.h
index a3374dc3a91b..cf910d1f8efa 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -344,7 +344,10 @@ struct qc_dqblk {
344 int d_rt_spc_warns; /* # warnings issued wrt RT space */ 344 int d_rt_spc_warns; /* # warnings issued wrt RT space */
345}; 345};
346 346
347/* Field specifiers for ->set_dqblk() in struct qc_dqblk */ 347/*
348 * Field specifiers for ->set_dqblk() in struct qc_dqblk and also for
349 * ->set_info() in struct qc_info
350 */
348#define QC_INO_SOFT (1<<0) 351#define QC_INO_SOFT (1<<0)
349#define QC_INO_HARD (1<<1) 352#define QC_INO_HARD (1<<1)
350#define QC_SPC_SOFT (1<<2) 353#define QC_SPC_SOFT (1<<2)
@@ -365,6 +368,51 @@ struct qc_dqblk {
365#define QC_INO_COUNT (1<<13) 368#define QC_INO_COUNT (1<<13)
366#define QC_RT_SPACE (1<<14) 369#define QC_RT_SPACE (1<<14)
367#define QC_ACCT_MASK (QC_SPACE | QC_INO_COUNT | QC_RT_SPACE) 370#define QC_ACCT_MASK (QC_SPACE | QC_INO_COUNT | QC_RT_SPACE)
371#define QC_FLAGS (1<<15)
372
373#define QCI_SYSFILE (1 << 0) /* Quota file is hidden from userspace */
374#define QCI_ROOT_SQUASH (1 << 1) /* Root squash turned on */
375#define QCI_ACCT_ENABLED (1 << 2) /* Quota accounting enabled */
376#define QCI_LIMITS_ENFORCED (1 << 3) /* Quota limits enforced */
377
378/* Structures for communicating via ->get_state */
379struct qc_type_state {
380 unsigned int flags; /* Flags QCI_* */
381 unsigned int spc_timelimit; /* Time after which space softlimit is
382 * enforced */
383 unsigned int ino_timelimit; /* Ditto for inode softlimit */
384 unsigned int rt_spc_timelimit; /* Ditto for real-time space */
385 unsigned int spc_warnlimit; /* Limit for number of space warnings */
386 unsigned int ino_warnlimit; /* Ditto for inodes */
387 unsigned int rt_spc_warnlimit; /* Ditto for real-time space */
388 unsigned long long ino; /* Inode number of quota file */
389 blkcnt_t blocks; /* Number of 512-byte blocks in the file */
390 blkcnt_t nextents; /* Number of extents in the file */
391};
392
393struct qc_state {
394 unsigned int s_incoredqs; /* Number of dquots in core */
395 /*
396 * Per quota type information. The array should really have
397 * max(MAXQUOTAS, XQM_MAXQUOTAS) entries. BUILD_BUG_ON in
398 * quota_getinfo() makes sure XQM_MAXQUOTAS is large enough. Once VFS
399 * supports project quotas, this can be changed to MAXQUOTAS
400 */
401 struct qc_type_state s_state[XQM_MAXQUOTAS];
402};
403
404/* Structure for communicating via ->set_info */
405struct qc_info {
406 int i_fieldmask; /* mask of fields to change in ->set_info() */
407 unsigned int i_flags; /* Flags QCI_* */
408 unsigned int i_spc_timelimit; /* Time after which space softlimit is
409 * enforced */
410 unsigned int i_ino_timelimit; /* Ditto for inode softlimit */
411 unsigned int i_rt_spc_timelimit;/* Ditto for real-time space */
412 unsigned int i_spc_warnlimit; /* Limit for number of space warnings */
413 unsigned int i_ino_warnlimit; /* Limit for number of inode warnings */
414 unsigned int i_rt_spc_warnlimit; /* Ditto for real-time space */
415};
368 416
369/* Operations handling requests from userspace */ 417/* Operations handling requests from userspace */
370struct quotactl_ops { 418struct quotactl_ops {
@@ -373,12 +421,10 @@ struct quotactl_ops {
373 int (*quota_enable)(struct super_block *, unsigned int); 421 int (*quota_enable)(struct super_block *, unsigned int);
374 int (*quota_disable)(struct super_block *, unsigned int); 422 int (*quota_disable)(struct super_block *, unsigned int);
375 int (*quota_sync)(struct super_block *, int); 423 int (*quota_sync)(struct super_block *, int);
376 int (*get_info)(struct super_block *, int, struct if_dqinfo *); 424 int (*set_info)(struct super_block *, int, struct qc_info *);
377 int (*set_info)(struct super_block *, int, struct if_dqinfo *);
378 int (*get_dqblk)(struct super_block *, struct kqid, struct qc_dqblk *); 425 int (*get_dqblk)(struct super_block *, struct kqid, struct qc_dqblk *);
379 int (*set_dqblk)(struct super_block *, struct kqid, struct qc_dqblk *); 426 int (*set_dqblk)(struct super_block *, struct kqid, struct qc_dqblk *);
380 int (*get_xstate)(struct super_block *, struct fs_quota_stat *); 427 int (*get_state)(struct super_block *, struct qc_state *);
381 int (*get_xstatev)(struct super_block *, struct fs_quota_statv *);
382 int (*rm_xquota)(struct super_block *, unsigned int); 428 int (*rm_xquota)(struct super_block *, unsigned int);
383}; 429};
384 430
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
index 8778ec4775eb..77ca6601ff25 100644
--- a/include/linux/quotaops.h
+++ b/include/linux/quotaops.h
@@ -95,8 +95,8 @@ int dquot_quota_on_mount(struct super_block *sb, char *qf_name,
95int dquot_quota_off(struct super_block *sb, int type); 95int dquot_quota_off(struct super_block *sb, int type);
96int dquot_writeback_dquots(struct super_block *sb, int type); 96int dquot_writeback_dquots(struct super_block *sb, int type);
97int dquot_quota_sync(struct super_block *sb, int type); 97int dquot_quota_sync(struct super_block *sb, int type);
98int dquot_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii); 98int dquot_get_state(struct super_block *sb, struct qc_state *state);
99int dquot_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii); 99int dquot_set_dqinfo(struct super_block *sb, int type, struct qc_info *ii);
100int dquot_get_dqblk(struct super_block *sb, struct kqid id, 100int dquot_get_dqblk(struct super_block *sb, struct kqid id,
101 struct qc_dqblk *di); 101 struct qc_dqblk *di);
102int dquot_set_dqblk(struct super_block *sb, struct kqid id, 102int dquot_set_dqblk(struct super_block *sb, struct kqid id,