Merge branch 'quota_interface' into for_next_testing
This commit is contained in:
commit
7dca0548a2
11 changed files with 424 additions and 256 deletions
|
@ -789,7 +789,7 @@ static const struct quotactl_ops ext3_qctl_operations = {
|
|||
.quota_on = ext3_quota_on,
|
||||
.quota_off = dquot_quota_off,
|
||||
.quota_sync = dquot_quota_sync,
|
||||
.get_info = dquot_get_dqinfo,
|
||||
.get_state = dquot_get_state,
|
||||
.set_info = dquot_set_dqinfo,
|
||||
.get_dqblk = dquot_get_dqblk,
|
||||
.set_dqblk = dquot_set_dqblk
|
||||
|
|
|
@ -1076,7 +1076,7 @@ static const struct quotactl_ops ext4_qctl_operations = {
|
|||
.quota_on = ext4_quota_on,
|
||||
.quota_off = ext4_quota_off,
|
||||
.quota_sync = dquot_quota_sync,
|
||||
.get_info = dquot_get_dqinfo,
|
||||
.get_state = dquot_get_state,
|
||||
.set_info = dquot_set_dqinfo,
|
||||
.get_dqblk = dquot_get_dqblk,
|
||||
.set_dqblk = dquot_set_dqblk
|
||||
|
|
|
@ -1468,32 +1468,34 @@ int gfs2_quotad(void *data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int gfs2_quota_get_xstate(struct super_block *sb,
|
||||
struct fs_quota_stat *fqs)
|
||||
static int gfs2_quota_get_state(struct super_block *sb, struct qc_state *state)
|
||||
{
|
||||
struct gfs2_sbd *sdp = sb->s_fs_info;
|
||||
|
||||
memset(fqs, 0, sizeof(struct fs_quota_stat));
|
||||
fqs->qs_version = FS_QSTAT_VERSION;
|
||||
memset(state, 0, sizeof(*state));
|
||||
|
||||
switch (sdp->sd_args.ar_quota) {
|
||||
case GFS2_QUOTA_ON:
|
||||
fqs->qs_flags |= (FS_QUOTA_UDQ_ENFD | FS_QUOTA_GDQ_ENFD);
|
||||
state->s_state[USRQUOTA].flags |= QCI_LIMITS_ENFORCED;
|
||||
state->s_state[GRPQUOTA].flags |= QCI_LIMITS_ENFORCED;
|
||||
/*FALLTHRU*/
|
||||
case GFS2_QUOTA_ACCOUNT:
|
||||
fqs->qs_flags |= (FS_QUOTA_UDQ_ACCT | FS_QUOTA_GDQ_ACCT);
|
||||
state->s_state[USRQUOTA].flags |= QCI_ACCT_ENABLED |
|
||||
QCI_SYSFILE;
|
||||
state->s_state[GRPQUOTA].flags |= QCI_ACCT_ENABLED |
|
||||
QCI_SYSFILE;
|
||||
break;
|
||||
case GFS2_QUOTA_OFF:
|
||||
break;
|
||||
}
|
||||
|
||||
if (sdp->sd_quota_inode) {
|
||||
fqs->qs_uquota.qfs_ino = GFS2_I(sdp->sd_quota_inode)->i_no_addr;
|
||||
fqs->qs_uquota.qfs_nblks = sdp->sd_quota_inode->i_blocks;
|
||||
state->s_state[USRQUOTA].ino =
|
||||
GFS2_I(sdp->sd_quota_inode)->i_no_addr;
|
||||
state->s_state[USRQUOTA].blocks = sdp->sd_quota_inode->i_blocks;
|
||||
}
|
||||
fqs->qs_uquota.qfs_nextents = 1; /* unsupported */
|
||||
fqs->qs_gquota = fqs->qs_uquota; /* its the same inode in both cases */
|
||||
fqs->qs_incoredqs = list_lru_count(&gfs2_qd_lru);
|
||||
state->s_state[USRQUOTA].nextents = 1; /* unsupported */
|
||||
state->s_state[GRPQUOTA] = state->s_state[USRQUOTA];
|
||||
state->s_incoredqs = list_lru_count(&gfs2_qd_lru);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1638,7 +1640,7 @@ static int gfs2_set_dqblk(struct super_block *sb, struct kqid qid,
|
|||
|
||||
const struct quotactl_ops gfs2_quotactl_ops = {
|
||||
.quota_sync = gfs2_quota_sync,
|
||||
.get_xstate = gfs2_quota_get_xstate,
|
||||
.get_state = gfs2_quota_get_state,
|
||||
.get_dqblk = gfs2_get_dqblk,
|
||||
.set_dqblk = gfs2_set_dqblk,
|
||||
};
|
||||
|
|
|
@ -2629,55 +2629,73 @@ int dquot_set_dqblk(struct super_block *sb, struct kqid qid,
|
|||
EXPORT_SYMBOL(dquot_set_dqblk);
|
||||
|
||||
/* Generic routine for getting common part of quota file information */
|
||||
int dquot_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii)
|
||||
int dquot_get_state(struct super_block *sb, struct qc_state *state)
|
||||
{
|
||||
struct mem_dqinfo *mi;
|
||||
struct qc_type_state *tstate;
|
||||
struct quota_info *dqopt = sb_dqopt(sb);
|
||||
int type;
|
||||
|
||||
mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
|
||||
if (!sb_has_quota_active(sb, type)) {
|
||||
mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
|
||||
return -ESRCH;
|
||||
memset(state, 0, sizeof(*state));
|
||||
for (type = 0; type < MAXQUOTAS; type++) {
|
||||
if (!sb_has_quota_active(sb, type))
|
||||
continue;
|
||||
tstate = state->s_state + type;
|
||||
mi = sb_dqopt(sb)->info + type;
|
||||
tstate->flags = QCI_ACCT_ENABLED;
|
||||
spin_lock(&dq_data_lock);
|
||||
if (mi->dqi_flags & DQF_SYS_FILE)
|
||||
tstate->flags |= QCI_SYSFILE;
|
||||
if (mi->dqi_flags & DQF_ROOT_SQUASH)
|
||||
tstate->flags |= QCI_ROOT_SQUASH;
|
||||
if (sb_has_quota_limits_enabled(sb, type))
|
||||
tstate->flags |= QCI_LIMITS_ENFORCED;
|
||||
tstate->spc_timelimit = mi->dqi_bgrace;
|
||||
tstate->ino_timelimit = mi->dqi_igrace;
|
||||
tstate->ino = dqopt->files[type]->i_ino;
|
||||
tstate->blocks = dqopt->files[type]->i_blocks;
|
||||
tstate->nextents = 1; /* We don't know... */
|
||||
spin_unlock(&dq_data_lock);
|
||||
}
|
||||
mi = sb_dqopt(sb)->info + type;
|
||||
spin_lock(&dq_data_lock);
|
||||
ii->dqi_bgrace = mi->dqi_bgrace;
|
||||
ii->dqi_igrace = mi->dqi_igrace;
|
||||
ii->dqi_flags = mi->dqi_flags & DQF_GETINFO_MASK;
|
||||
ii->dqi_valid = IIF_ALL;
|
||||
spin_unlock(&dq_data_lock);
|
||||
mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(dquot_get_dqinfo);
|
||||
EXPORT_SYMBOL(dquot_get_state);
|
||||
|
||||
/* Generic routine for setting common part of quota file information */
|
||||
int dquot_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii)
|
||||
int dquot_set_dqinfo(struct super_block *sb, int type, struct qc_info *ii)
|
||||
{
|
||||
struct mem_dqinfo *mi;
|
||||
int err = 0;
|
||||
|
||||
if ((ii->i_fieldmask & QC_WARNS_MASK) ||
|
||||
(ii->i_fieldmask & QC_RT_SPC_TIMER))
|
||||
return -EINVAL;
|
||||
mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
|
||||
if (!sb_has_quota_active(sb, type)) {
|
||||
err = -ESRCH;
|
||||
goto out;
|
||||
}
|
||||
mi = sb_dqopt(sb)->info + type;
|
||||
if (ii->dqi_valid & IIF_FLAGS) {
|
||||
if (ii->dqi_flags & ~DQF_SETINFO_MASK ||
|
||||
(ii->dqi_flags & DQF_ROOT_SQUASH &&
|
||||
if (ii->i_fieldmask & QC_FLAGS) {
|
||||
if ((ii->i_flags & QCI_ROOT_SQUASH &&
|
||||
mi->dqi_format->qf_fmt_id != QFMT_VFS_OLD)) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
spin_lock(&dq_data_lock);
|
||||
if (ii->dqi_valid & IIF_BGRACE)
|
||||
mi->dqi_bgrace = ii->dqi_bgrace;
|
||||
if (ii->dqi_valid & IIF_IGRACE)
|
||||
mi->dqi_igrace = ii->dqi_igrace;
|
||||
if (ii->dqi_valid & IIF_FLAGS)
|
||||
mi->dqi_flags = (mi->dqi_flags & ~DQF_SETINFO_MASK) |
|
||||
(ii->dqi_flags & DQF_SETINFO_MASK);
|
||||
if (ii->i_fieldmask & QC_SPC_TIMER)
|
||||
mi->dqi_bgrace = ii->i_spc_timelimit;
|
||||
if (ii->i_fieldmask & QC_INO_TIMER)
|
||||
mi->dqi_igrace = ii->i_ino_timelimit;
|
||||
if (ii->i_fieldmask & QC_FLAGS) {
|
||||
if (ii->i_flags & QCI_ROOT_SQUASH)
|
||||
mi->dqi_flags |= DQF_ROOT_SQUASH;
|
||||
else
|
||||
mi->dqi_flags &= ~DQF_ROOT_SQUASH;
|
||||
}
|
||||
spin_unlock(&dq_data_lock);
|
||||
mark_info_dirty(sb, type);
|
||||
/* Force write to disk */
|
||||
|
@ -2692,7 +2710,7 @@ const struct quotactl_ops dquot_quotactl_ops = {
|
|||
.quota_on = dquot_quota_on,
|
||||
.quota_off = dquot_quota_off,
|
||||
.quota_sync = dquot_quota_sync,
|
||||
.get_info = dquot_get_dqinfo,
|
||||
.get_state = dquot_get_state,
|
||||
.set_info = dquot_set_dqinfo,
|
||||
.get_dqblk = dquot_get_dqblk,
|
||||
.set_dqblk = dquot_set_dqblk
|
||||
|
@ -2703,7 +2721,7 @@ const struct quotactl_ops dquot_quotactl_sysfile_ops = {
|
|||
.quota_enable = dquot_quota_enable,
|
||||
.quota_disable = dquot_quota_disable,
|
||||
.quota_sync = dquot_quota_sync,
|
||||
.get_info = dquot_get_dqinfo,
|
||||
.get_state = dquot_get_state,
|
||||
.set_info = dquot_set_dqinfo,
|
||||
.get_dqblk = dquot_get_dqblk,
|
||||
.set_dqblk = dquot_set_dqblk
|
||||
|
|
217
fs/quota/quota.c
217
fs/quota/quota.c
|
@ -118,13 +118,30 @@ static int quota_getfmt(struct super_block *sb, int type, void __user *addr)
|
|||
|
||||
static int quota_getinfo(struct super_block *sb, int type, void __user *addr)
|
||||
{
|
||||
struct if_dqinfo info;
|
||||
struct qc_state state;
|
||||
struct qc_type_state *tstate;
|
||||
struct if_dqinfo uinfo;
|
||||
int ret;
|
||||
|
||||
if (!sb->s_qcop->get_info)
|
||||
/* This checks whether qc_state has enough entries... */
|
||||
BUILD_BUG_ON(MAXQUOTAS > XQM_MAXQUOTAS);
|
||||
if (!sb->s_qcop->get_state)
|
||||
return -ENOSYS;
|
||||
ret = sb->s_qcop->get_info(sb, type, &info);
|
||||
if (!ret && copy_to_user(addr, &info, sizeof(info)))
|
||||
ret = sb->s_qcop->get_state(sb, &state);
|
||||
if (ret)
|
||||
return ret;
|
||||
tstate = state.s_state + type;
|
||||
if (!(tstate->flags & QCI_ACCT_ENABLED))
|
||||
return -ESRCH;
|
||||
memset(&uinfo, 0, sizeof(uinfo));
|
||||
uinfo.dqi_bgrace = tstate->spc_timelimit;
|
||||
uinfo.dqi_igrace = tstate->ino_timelimit;
|
||||
if (tstate->flags & QCI_SYSFILE)
|
||||
uinfo.dqi_flags |= DQF_SYS_FILE;
|
||||
if (tstate->flags & QCI_ROOT_SQUASH)
|
||||
uinfo.dqi_flags |= DQF_ROOT_SQUASH;
|
||||
uinfo.dqi_valid = IIF_ALL;
|
||||
if (!ret && copy_to_user(addr, &uinfo, sizeof(uinfo)))
|
||||
return -EFAULT;
|
||||
return ret;
|
||||
}
|
||||
|
@ -132,12 +149,31 @@ static int quota_getinfo(struct super_block *sb, int type, void __user *addr)
|
|||
static int quota_setinfo(struct super_block *sb, int type, void __user *addr)
|
||||
{
|
||||
struct if_dqinfo info;
|
||||
struct qc_info qinfo;
|
||||
|
||||
if (copy_from_user(&info, addr, sizeof(info)))
|
||||
return -EFAULT;
|
||||
if (!sb->s_qcop->set_info)
|
||||
return -ENOSYS;
|
||||
return sb->s_qcop->set_info(sb, type, &info);
|
||||
if (info.dqi_valid & ~(IIF_FLAGS | IIF_BGRACE | IIF_IGRACE))
|
||||
return -EINVAL;
|
||||
memset(&qinfo, 0, sizeof(qinfo));
|
||||
if (info.dqi_valid & IIF_FLAGS) {
|
||||
if (info.dqi_flags & ~DQF_SETINFO_MASK)
|
||||
return -EINVAL;
|
||||
if (info.dqi_flags & DQF_ROOT_SQUASH)
|
||||
qinfo.i_flags |= QCI_ROOT_SQUASH;
|
||||
qinfo.i_fieldmask |= QC_FLAGS;
|
||||
}
|
||||
if (info.dqi_valid & IIF_BGRACE) {
|
||||
qinfo.i_spc_timelimit = info.dqi_bgrace;
|
||||
qinfo.i_fieldmask |= QC_SPC_TIMER;
|
||||
}
|
||||
if (info.dqi_valid & IIF_IGRACE) {
|
||||
qinfo.i_ino_timelimit = info.dqi_igrace;
|
||||
qinfo.i_fieldmask |= QC_INO_TIMER;
|
||||
}
|
||||
return sb->s_qcop->set_info(sb, type, &qinfo);
|
||||
}
|
||||
|
||||
static inline qsize_t qbtos(qsize_t blocks)
|
||||
|
@ -252,25 +288,149 @@ static int quota_disable(struct super_block *sb, void __user *addr)
|
|||
return sb->s_qcop->quota_disable(sb, flags);
|
||||
}
|
||||
|
||||
static int quota_state_to_flags(struct qc_state *state)
|
||||
{
|
||||
int flags = 0;
|
||||
|
||||
if (state->s_state[USRQUOTA].flags & QCI_ACCT_ENABLED)
|
||||
flags |= FS_QUOTA_UDQ_ACCT;
|
||||
if (state->s_state[USRQUOTA].flags & QCI_LIMITS_ENFORCED)
|
||||
flags |= FS_QUOTA_UDQ_ENFD;
|
||||
if (state->s_state[GRPQUOTA].flags & QCI_ACCT_ENABLED)
|
||||
flags |= FS_QUOTA_GDQ_ACCT;
|
||||
if (state->s_state[GRPQUOTA].flags & QCI_LIMITS_ENFORCED)
|
||||
flags |= FS_QUOTA_GDQ_ENFD;
|
||||
if (state->s_state[PRJQUOTA].flags & QCI_ACCT_ENABLED)
|
||||
flags |= FS_QUOTA_PDQ_ACCT;
|
||||
if (state->s_state[PRJQUOTA].flags & QCI_LIMITS_ENFORCED)
|
||||
flags |= FS_QUOTA_PDQ_ENFD;
|
||||
return flags;
|
||||
}
|
||||
|
||||
static int quota_getstate(struct super_block *sb, struct fs_quota_stat *fqs)
|
||||
{
|
||||
int type;
|
||||
struct qc_state state;
|
||||
int ret;
|
||||
|
||||
ret = sb->s_qcop->get_state(sb, &state);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
memset(fqs, 0, sizeof(*fqs));
|
||||
fqs->qs_version = FS_QSTAT_VERSION;
|
||||
fqs->qs_flags = quota_state_to_flags(&state);
|
||||
/* No quota enabled? */
|
||||
if (!fqs->qs_flags)
|
||||
return -ENOSYS;
|
||||
fqs->qs_incoredqs = state.s_incoredqs;
|
||||
/*
|
||||
* GETXSTATE quotactl has space for just one set of time limits so
|
||||
* report them for the first enabled quota type
|
||||
*/
|
||||
for (type = 0; type < XQM_MAXQUOTAS; type++)
|
||||
if (state.s_state[type].flags & QCI_ACCT_ENABLED)
|
||||
break;
|
||||
BUG_ON(type == XQM_MAXQUOTAS);
|
||||
fqs->qs_btimelimit = state.s_state[type].spc_timelimit;
|
||||
fqs->qs_itimelimit = state.s_state[type].ino_timelimit;
|
||||
fqs->qs_rtbtimelimit = state.s_state[type].rt_spc_timelimit;
|
||||
fqs->qs_bwarnlimit = state.s_state[type].spc_warnlimit;
|
||||
fqs->qs_iwarnlimit = state.s_state[type].ino_warnlimit;
|
||||
if (state.s_state[USRQUOTA].flags & QCI_ACCT_ENABLED) {
|
||||
fqs->qs_uquota.qfs_ino = state.s_state[USRQUOTA].ino;
|
||||
fqs->qs_uquota.qfs_nblks = state.s_state[USRQUOTA].blocks;
|
||||
fqs->qs_uquota.qfs_nextents = state.s_state[USRQUOTA].nextents;
|
||||
}
|
||||
if (state.s_state[GRPQUOTA].flags & QCI_ACCT_ENABLED) {
|
||||
fqs->qs_gquota.qfs_ino = state.s_state[GRPQUOTA].ino;
|
||||
fqs->qs_gquota.qfs_nblks = state.s_state[GRPQUOTA].blocks;
|
||||
fqs->qs_gquota.qfs_nextents = state.s_state[GRPQUOTA].nextents;
|
||||
}
|
||||
if (state.s_state[PRJQUOTA].flags & QCI_ACCT_ENABLED) {
|
||||
/*
|
||||
* Q_XGETQSTAT doesn't have room for both group and project
|
||||
* quotas. So, allow the project quota values to be copied out
|
||||
* only if there is no group quota information available.
|
||||
*/
|
||||
if (!(state.s_state[GRPQUOTA].flags & QCI_ACCT_ENABLED)) {
|
||||
fqs->qs_gquota.qfs_ino = state.s_state[PRJQUOTA].ino;
|
||||
fqs->qs_gquota.qfs_nblks =
|
||||
state.s_state[PRJQUOTA].blocks;
|
||||
fqs->qs_gquota.qfs_nextents =
|
||||
state.s_state[PRJQUOTA].nextents;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int quota_getxstate(struct super_block *sb, void __user *addr)
|
||||
{
|
||||
struct fs_quota_stat fqs;
|
||||
int ret;
|
||||
|
||||
if (!sb->s_qcop->get_xstate)
|
||||
if (!sb->s_qcop->get_state)
|
||||
return -ENOSYS;
|
||||
ret = sb->s_qcop->get_xstate(sb, &fqs);
|
||||
ret = quota_getstate(sb, &fqs);
|
||||
if (!ret && copy_to_user(addr, &fqs, sizeof(fqs)))
|
||||
return -EFAULT;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int quota_getstatev(struct super_block *sb, struct fs_quota_statv *fqs)
|
||||
{
|
||||
int type;
|
||||
struct qc_state state;
|
||||
int ret;
|
||||
|
||||
ret = sb->s_qcop->get_state(sb, &state);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
memset(fqs, 0, sizeof(*fqs));
|
||||
fqs->qs_version = FS_QSTAT_VERSION;
|
||||
fqs->qs_flags = quota_state_to_flags(&state);
|
||||
/* No quota enabled? */
|
||||
if (!fqs->qs_flags)
|
||||
return -ENOSYS;
|
||||
fqs->qs_incoredqs = state.s_incoredqs;
|
||||
/*
|
||||
* GETXSTATV quotactl has space for just one set of time limits so
|
||||
* report them for the first enabled quota type
|
||||
*/
|
||||
for (type = 0; type < XQM_MAXQUOTAS; type++)
|
||||
if (state.s_state[type].flags & QCI_ACCT_ENABLED)
|
||||
break;
|
||||
BUG_ON(type == XQM_MAXQUOTAS);
|
||||
fqs->qs_btimelimit = state.s_state[type].spc_timelimit;
|
||||
fqs->qs_itimelimit = state.s_state[type].ino_timelimit;
|
||||
fqs->qs_rtbtimelimit = state.s_state[type].rt_spc_timelimit;
|
||||
fqs->qs_bwarnlimit = state.s_state[type].spc_warnlimit;
|
||||
fqs->qs_iwarnlimit = state.s_state[type].ino_warnlimit;
|
||||
if (state.s_state[USRQUOTA].flags & QCI_ACCT_ENABLED) {
|
||||
fqs->qs_uquota.qfs_ino = state.s_state[USRQUOTA].ino;
|
||||
fqs->qs_uquota.qfs_nblks = state.s_state[USRQUOTA].blocks;
|
||||
fqs->qs_uquota.qfs_nextents = state.s_state[USRQUOTA].nextents;
|
||||
}
|
||||
if (state.s_state[GRPQUOTA].flags & QCI_ACCT_ENABLED) {
|
||||
fqs->qs_gquota.qfs_ino = state.s_state[GRPQUOTA].ino;
|
||||
fqs->qs_gquota.qfs_nblks = state.s_state[GRPQUOTA].blocks;
|
||||
fqs->qs_gquota.qfs_nextents = state.s_state[GRPQUOTA].nextents;
|
||||
}
|
||||
if (state.s_state[PRJQUOTA].flags & QCI_ACCT_ENABLED) {
|
||||
fqs->qs_pquota.qfs_ino = state.s_state[PRJQUOTA].ino;
|
||||
fqs->qs_pquota.qfs_nblks = state.s_state[PRJQUOTA].blocks;
|
||||
fqs->qs_pquota.qfs_nextents = state.s_state[PRJQUOTA].nextents;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int quota_getxstatev(struct super_block *sb, void __user *addr)
|
||||
{
|
||||
struct fs_quota_statv fqs;
|
||||
int ret;
|
||||
|
||||
if (!sb->s_qcop->get_xstatev)
|
||||
if (!sb->s_qcop->get_state)
|
||||
return -ENOSYS;
|
||||
|
||||
memset(&fqs, 0, sizeof(fqs));
|
||||
|
@ -284,7 +444,7 @@ static int quota_getxstatev(struct super_block *sb, void __user *addr)
|
|||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = sb->s_qcop->get_xstatev(sb, &fqs);
|
||||
ret = quota_getstatev(sb, &fqs);
|
||||
if (!ret && copy_to_user(addr, &fqs, sizeof(fqs)))
|
||||
return -EFAULT;
|
||||
return ret;
|
||||
|
@ -357,6 +517,30 @@ static void copy_from_xfs_dqblk(struct qc_dqblk *dst, struct fs_disk_quota *src)
|
|||
dst->d_fieldmask |= QC_RT_SPACE;
|
||||
}
|
||||
|
||||
static void copy_qcinfo_from_xfs_dqblk(struct qc_info *dst,
|
||||
struct fs_disk_quota *src)
|
||||
{
|
||||
memset(dst, 0, sizeof(*dst));
|
||||
dst->i_spc_timelimit = src->d_btimer;
|
||||
dst->i_ino_timelimit = src->d_itimer;
|
||||
dst->i_rt_spc_timelimit = src->d_rtbtimer;
|
||||
dst->i_ino_warnlimit = src->d_iwarns;
|
||||
dst->i_spc_warnlimit = src->d_bwarns;
|
||||
dst->i_rt_spc_warnlimit = src->d_rtbwarns;
|
||||
if (src->d_fieldmask & FS_DQ_BWARNS)
|
||||
dst->i_fieldmask |= QC_SPC_WARNS;
|
||||
if (src->d_fieldmask & FS_DQ_IWARNS)
|
||||
dst->i_fieldmask |= QC_INO_WARNS;
|
||||
if (src->d_fieldmask & FS_DQ_RTBWARNS)
|
||||
dst->i_fieldmask |= QC_RT_SPC_WARNS;
|
||||
if (src->d_fieldmask & FS_DQ_BTIMER)
|
||||
dst->i_fieldmask |= QC_SPC_TIMER;
|
||||
if (src->d_fieldmask & FS_DQ_ITIMER)
|
||||
dst->i_fieldmask |= QC_INO_TIMER;
|
||||
if (src->d_fieldmask & FS_DQ_RTBTIMER)
|
||||
dst->i_fieldmask |= QC_RT_SPC_TIMER;
|
||||
}
|
||||
|
||||
static int quota_setxquota(struct super_block *sb, int type, qid_t id,
|
||||
void __user *addr)
|
||||
{
|
||||
|
@ -371,6 +555,21 @@ static int quota_setxquota(struct super_block *sb, int type, qid_t id,
|
|||
qid = make_kqid(current_user_ns(), type, id);
|
||||
if (!qid_valid(qid))
|
||||
return -EINVAL;
|
||||
/* Are we actually setting timer / warning limits for all users? */
|
||||
if (from_kqid(&init_user_ns, qid) == 0 &&
|
||||
fdq.d_fieldmask & (FS_DQ_WARNS_MASK | FS_DQ_TIMER_MASK)) {
|
||||
struct qc_info qinfo;
|
||||
int ret;
|
||||
|
||||
if (!sb->s_qcop->set_info)
|
||||
return -EINVAL;
|
||||
copy_qcinfo_from_xfs_dqblk(&qinfo, &fdq);
|
||||
ret = sb->s_qcop->set_info(sb, type, &qinfo);
|
||||
if (ret)
|
||||
return ret;
|
||||
/* These are already done */
|
||||
fdq.d_fieldmask &= ~(FS_DQ_WARNS_MASK | FS_DQ_TIMER_MASK);
|
||||
}
|
||||
copy_from_xfs_dqblk(&qdq, &fdq);
|
||||
return sb->s_qcop->set_dqblk(sb, qid, &qdq);
|
||||
}
|
||||
|
|
|
@ -805,7 +805,7 @@ static const struct quotactl_ops reiserfs_qctl_operations = {
|
|||
.quota_on = reiserfs_quota_on,
|
||||
.quota_off = dquot_quota_off,
|
||||
.quota_sync = dquot_quota_sync,
|
||||
.get_info = dquot_get_dqinfo,
|
||||
.get_state = dquot_get_state,
|
||||
.set_info = dquot_set_dqinfo,
|
||||
.get_dqblk = dquot_get_dqblk,
|
||||
.set_dqblk = dquot_set_dqblk,
|
||||
|
|
|
@ -168,10 +168,6 @@ extern int xfs_qm_scall_getquota(struct xfs_mount *, xfs_dqid_t,
|
|||
uint, struct qc_dqblk *);
|
||||
extern int xfs_qm_scall_setqlim(struct xfs_mount *, xfs_dqid_t, uint,
|
||||
struct qc_dqblk *);
|
||||
extern int xfs_qm_scall_getqstat(struct xfs_mount *,
|
||||
struct fs_quota_stat *);
|
||||
extern int xfs_qm_scall_getqstatv(struct xfs_mount *,
|
||||
struct fs_quota_statv *);
|
||||
extern int xfs_qm_scall_quotaon(struct xfs_mount *, uint);
|
||||
extern int xfs_qm_scall_quotaoff(struct xfs_mount *, uint);
|
||||
|
||||
|
|
|
@ -38,7 +38,6 @@
|
|||
STATIC int xfs_qm_log_quotaoff(xfs_mount_t *, xfs_qoff_logitem_t **, uint);
|
||||
STATIC int xfs_qm_log_quotaoff_end(xfs_mount_t *, xfs_qoff_logitem_t *,
|
||||
uint);
|
||||
STATIC uint xfs_qm_export_flags(uint);
|
||||
|
||||
/*
|
||||
* Turn off quota accounting and/or enforcement for all udquots and/or
|
||||
|
@ -389,159 +388,6 @@ xfs_qm_scall_quotaon(
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return quota status information, such as uquota-off, enforcements, etc.
|
||||
* for Q_XGETQSTAT command.
|
||||
*/
|
||||
int
|
||||
xfs_qm_scall_getqstat(
|
||||
struct xfs_mount *mp,
|
||||
struct fs_quota_stat *out)
|
||||
{
|
||||
struct xfs_quotainfo *q = mp->m_quotainfo;
|
||||
struct xfs_inode *uip = NULL;
|
||||
struct xfs_inode *gip = NULL;
|
||||
struct xfs_inode *pip = NULL;
|
||||
bool tempuqip = false;
|
||||
bool tempgqip = false;
|
||||
bool temppqip = false;
|
||||
|
||||
memset(out, 0, sizeof(fs_quota_stat_t));
|
||||
|
||||
out->qs_version = FS_QSTAT_VERSION;
|
||||
out->qs_flags = (__uint16_t) xfs_qm_export_flags(mp->m_qflags &
|
||||
(XFS_ALL_QUOTA_ACCT|
|
||||
XFS_ALL_QUOTA_ENFD));
|
||||
uip = q->qi_uquotaip;
|
||||
gip = q->qi_gquotaip;
|
||||
pip = q->qi_pquotaip;
|
||||
if (!uip && mp->m_sb.sb_uquotino != NULLFSINO) {
|
||||
if (xfs_iget(mp, NULL, mp->m_sb.sb_uquotino,
|
||||
0, 0, &uip) == 0)
|
||||
tempuqip = true;
|
||||
}
|
||||
if (!gip && mp->m_sb.sb_gquotino != NULLFSINO) {
|
||||
if (xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
|
||||
0, 0, &gip) == 0)
|
||||
tempgqip = true;
|
||||
}
|
||||
/*
|
||||
* Q_XGETQSTAT doesn't have room for both group and project quotas.
|
||||
* So, allow the project quota values to be copied out only if
|
||||
* there is no group quota information available.
|
||||
*/
|
||||
if (!gip) {
|
||||
if (!pip && mp->m_sb.sb_pquotino != NULLFSINO) {
|
||||
if (xfs_iget(mp, NULL, mp->m_sb.sb_pquotino,
|
||||
0, 0, &pip) == 0)
|
||||
temppqip = true;
|
||||
}
|
||||
} else
|
||||
pip = NULL;
|
||||
if (uip) {
|
||||
out->qs_uquota.qfs_ino = mp->m_sb.sb_uquotino;
|
||||
out->qs_uquota.qfs_nblks = uip->i_d.di_nblocks;
|
||||
out->qs_uquota.qfs_nextents = uip->i_d.di_nextents;
|
||||
if (tempuqip)
|
||||
IRELE(uip);
|
||||
}
|
||||
|
||||
if (gip) {
|
||||
out->qs_gquota.qfs_ino = mp->m_sb.sb_gquotino;
|
||||
out->qs_gquota.qfs_nblks = gip->i_d.di_nblocks;
|
||||
out->qs_gquota.qfs_nextents = gip->i_d.di_nextents;
|
||||
if (tempgqip)
|
||||
IRELE(gip);
|
||||
}
|
||||
if (pip) {
|
||||
out->qs_gquota.qfs_ino = mp->m_sb.sb_gquotino;
|
||||
out->qs_gquota.qfs_nblks = pip->i_d.di_nblocks;
|
||||
out->qs_gquota.qfs_nextents = pip->i_d.di_nextents;
|
||||
if (temppqip)
|
||||
IRELE(pip);
|
||||
}
|
||||
out->qs_incoredqs = q->qi_dquots;
|
||||
out->qs_btimelimit = q->qi_btimelimit;
|
||||
out->qs_itimelimit = q->qi_itimelimit;
|
||||
out->qs_rtbtimelimit = q->qi_rtbtimelimit;
|
||||
out->qs_bwarnlimit = q->qi_bwarnlimit;
|
||||
out->qs_iwarnlimit = q->qi_iwarnlimit;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return quota status information, such as uquota-off, enforcements, etc.
|
||||
* for Q_XGETQSTATV command, to support separate project quota field.
|
||||
*/
|
||||
int
|
||||
xfs_qm_scall_getqstatv(
|
||||
struct xfs_mount *mp,
|
||||
struct fs_quota_statv *out)
|
||||
{
|
||||
struct xfs_quotainfo *q = mp->m_quotainfo;
|
||||
struct xfs_inode *uip = NULL;
|
||||
struct xfs_inode *gip = NULL;
|
||||
struct xfs_inode *pip = NULL;
|
||||
bool tempuqip = false;
|
||||
bool tempgqip = false;
|
||||
bool temppqip = false;
|
||||
|
||||
out->qs_flags = (__uint16_t) xfs_qm_export_flags(mp->m_qflags &
|
||||
(XFS_ALL_QUOTA_ACCT|
|
||||
XFS_ALL_QUOTA_ENFD));
|
||||
out->qs_uquota.qfs_ino = mp->m_sb.sb_uquotino;
|
||||
out->qs_gquota.qfs_ino = mp->m_sb.sb_gquotino;
|
||||
out->qs_pquota.qfs_ino = mp->m_sb.sb_pquotino;
|
||||
|
||||
uip = q->qi_uquotaip;
|
||||
gip = q->qi_gquotaip;
|
||||
pip = q->qi_pquotaip;
|
||||
if (!uip && mp->m_sb.sb_uquotino != NULLFSINO) {
|
||||
if (xfs_iget(mp, NULL, mp->m_sb.sb_uquotino,
|
||||
0, 0, &uip) == 0)
|
||||
tempuqip = true;
|
||||
}
|
||||
if (!gip && mp->m_sb.sb_gquotino != NULLFSINO) {
|
||||
if (xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
|
||||
0, 0, &gip) == 0)
|
||||
tempgqip = true;
|
||||
}
|
||||
if (!pip && mp->m_sb.sb_pquotino != NULLFSINO) {
|
||||
if (xfs_iget(mp, NULL, mp->m_sb.sb_pquotino,
|
||||
0, 0, &pip) == 0)
|
||||
temppqip = true;
|
||||
}
|
||||
if (uip) {
|
||||
out->qs_uquota.qfs_nblks = uip->i_d.di_nblocks;
|
||||
out->qs_uquota.qfs_nextents = uip->i_d.di_nextents;
|
||||
if (tempuqip)
|
||||
IRELE(uip);
|
||||
}
|
||||
|
||||
if (gip) {
|
||||
out->qs_gquota.qfs_nblks = gip->i_d.di_nblocks;
|
||||
out->qs_gquota.qfs_nextents = gip->i_d.di_nextents;
|
||||
if (tempgqip)
|
||||
IRELE(gip);
|
||||
}
|
||||
if (pip) {
|
||||
out->qs_pquota.qfs_nblks = pip->i_d.di_nblocks;
|
||||
out->qs_pquota.qfs_nextents = pip->i_d.di_nextents;
|
||||
if (temppqip)
|
||||
IRELE(pip);
|
||||
}
|
||||
out->qs_incoredqs = q->qi_dquots;
|
||||
out->qs_btimelimit = q->qi_btimelimit;
|
||||
out->qs_itimelimit = q->qi_itimelimit;
|
||||
out->qs_rtbtimelimit = q->qi_rtbtimelimit;
|
||||
out->qs_bwarnlimit = q->qi_bwarnlimit;
|
||||
out->qs_iwarnlimit = q->qi_iwarnlimit;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define XFS_QC_MASK \
|
||||
(QC_LIMIT_MASK | QC_TIMER_MASK | QC_WARNS_MASK)
|
||||
|
||||
|
@ -873,28 +719,6 @@ xfs_qm_scall_getquota(
|
|||
return error;
|
||||
}
|
||||
|
||||
STATIC uint
|
||||
xfs_qm_export_flags(
|
||||
uint flags)
|
||||
{
|
||||
uint uflags;
|
||||
|
||||
uflags = 0;
|
||||
if (flags & XFS_UQUOTA_ACCT)
|
||||
uflags |= FS_QUOTA_UDQ_ACCT;
|
||||
if (flags & XFS_GQUOTA_ACCT)
|
||||
uflags |= FS_QUOTA_GDQ_ACCT;
|
||||
if (flags & XFS_PQUOTA_ACCT)
|
||||
uflags |= FS_QUOTA_PDQ_ACCT;
|
||||
if (flags & XFS_UQUOTA_ENFD)
|
||||
uflags |= FS_QUOTA_UDQ_ENFD;
|
||||
if (flags & XFS_GQUOTA_ENFD)
|
||||
uflags |= FS_QUOTA_GDQ_ENFD;
|
||||
if (flags & XFS_PQUOTA_ENFD)
|
||||
uflags |= FS_QUOTA_PDQ_ENFD;
|
||||
return uflags;
|
||||
}
|
||||
|
||||
|
||||
STATIC int
|
||||
xfs_dqrele_inode(
|
||||
|
|
|
@ -23,10 +23,81 @@
|
|||
#include "xfs_inode.h"
|
||||
#include "xfs_quota.h"
|
||||
#include "xfs_trans.h"
|
||||
#include "xfs_trace.h"
|
||||
#include "xfs_icache.h"
|
||||
#include "xfs_qm.h"
|
||||
#include <linux/quota.h>
|
||||
|
||||
|
||||
static void
|
||||
xfs_qm_fill_state(
|
||||
struct qc_type_state *tstate,
|
||||
struct xfs_mount *mp,
|
||||
struct xfs_inode *ip,
|
||||
xfs_ino_t ino)
|
||||
{
|
||||
struct xfs_quotainfo *q = mp->m_quotainfo;
|
||||
bool tempqip = false;
|
||||
|
||||
tstate->ino = ino;
|
||||
if (!ip && ino == NULLFSINO)
|
||||
return;
|
||||
if (!ip) {
|
||||
if (xfs_iget(mp, NULL, ino, 0, 0, &ip))
|
||||
return;
|
||||
tempqip = true;
|
||||
}
|
||||
tstate->flags |= QCI_SYSFILE;
|
||||
tstate->blocks = ip->i_d.di_nblocks;
|
||||
tstate->nextents = ip->i_d.di_nextents;
|
||||
tstate->spc_timelimit = q->qi_btimelimit;
|
||||
tstate->ino_timelimit = q->qi_itimelimit;
|
||||
tstate->rt_spc_timelimit = q->qi_rtbtimelimit;
|
||||
tstate->spc_warnlimit = q->qi_bwarnlimit;
|
||||
tstate->ino_warnlimit = q->qi_iwarnlimit;
|
||||
tstate->rt_spc_warnlimit = q->qi_rtbwarnlimit;
|
||||
if (tempqip)
|
||||
IRELE(ip);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return quota status information, such as enforcements, quota file inode
|
||||
* numbers etc.
|
||||
*/
|
||||
static int
|
||||
xfs_fs_get_quota_state(
|
||||
struct super_block *sb,
|
||||
struct qc_state *state)
|
||||
{
|
||||
struct xfs_mount *mp = XFS_M(sb);
|
||||
struct xfs_quotainfo *q = mp->m_quotainfo;
|
||||
|
||||
memset(state, 0, sizeof(*state));
|
||||
if (!XFS_IS_QUOTA_RUNNING(mp))
|
||||
return 0;
|
||||
state->s_incoredqs = q->qi_dquots;
|
||||
if (XFS_IS_UQUOTA_RUNNING(mp))
|
||||
state->s_state[USRQUOTA].flags |= QCI_ACCT_ENABLED;
|
||||
if (XFS_IS_UQUOTA_ENFORCED(mp))
|
||||
state->s_state[USRQUOTA].flags |= QCI_LIMITS_ENFORCED;
|
||||
if (XFS_IS_GQUOTA_RUNNING(mp))
|
||||
state->s_state[GRPQUOTA].flags |= QCI_ACCT_ENABLED;
|
||||
if (XFS_IS_GQUOTA_ENFORCED(mp))
|
||||
state->s_state[GRPQUOTA].flags |= QCI_LIMITS_ENFORCED;
|
||||
if (XFS_IS_PQUOTA_RUNNING(mp))
|
||||
state->s_state[PRJQUOTA].flags |= QCI_ACCT_ENABLED;
|
||||
if (XFS_IS_PQUOTA_ENFORCED(mp))
|
||||
state->s_state[PRJQUOTA].flags |= QCI_LIMITS_ENFORCED;
|
||||
|
||||
xfs_qm_fill_state(&state->s_state[USRQUOTA], mp, q->qi_uquotaip,
|
||||
mp->m_sb.sb_uquotino);
|
||||
xfs_qm_fill_state(&state->s_state[GRPQUOTA], mp, q->qi_gquotaip,
|
||||
mp->m_sb.sb_gquotino);
|
||||
xfs_qm_fill_state(&state->s_state[PRJQUOTA], mp, q->qi_pquotaip,
|
||||
mp->m_sb.sb_pquotino);
|
||||
return 0;
|
||||
}
|
||||
|
||||
STATIC int
|
||||
xfs_quota_type(int type)
|
||||
{
|
||||
|
@ -40,28 +111,40 @@ xfs_quota_type(int type)
|
|||
}
|
||||
}
|
||||
|
||||
STATIC int
|
||||
xfs_fs_get_xstate(
|
||||
struct super_block *sb,
|
||||
struct fs_quota_stat *fqs)
|
||||
{
|
||||
struct xfs_mount *mp = XFS_M(sb);
|
||||
#define XFS_QC_SETINFO_MASK (QC_TIMER_MASK | QC_WARNS_MASK)
|
||||
|
||||
/*
|
||||
* Adjust quota timers & warnings
|
||||
*/
|
||||
static int
|
||||
xfs_fs_set_info(
|
||||
struct super_block *sb,
|
||||
int type,
|
||||
struct qc_info *info)
|
||||
{
|
||||
struct xfs_mount *mp = XFS_M(sb);
|
||||
struct qc_dqblk newlim;
|
||||
|
||||
if (sb->s_flags & MS_RDONLY)
|
||||
return -EROFS;
|
||||
if (!XFS_IS_QUOTA_RUNNING(mp))
|
||||
return -ENOSYS;
|
||||
return xfs_qm_scall_getqstat(mp, fqs);
|
||||
}
|
||||
if (!XFS_IS_QUOTA_ON(mp))
|
||||
return -ESRCH;
|
||||
if (info->i_fieldmask & ~XFS_QC_SETINFO_MASK)
|
||||
return -EINVAL;
|
||||
if ((info->i_fieldmask & XFS_QC_SETINFO_MASK) == 0)
|
||||
return 0;
|
||||
|
||||
STATIC int
|
||||
xfs_fs_get_xstatev(
|
||||
struct super_block *sb,
|
||||
struct fs_quota_statv *fqs)
|
||||
{
|
||||
struct xfs_mount *mp = XFS_M(sb);
|
||||
newlim.d_fieldmask = info->i_fieldmask;
|
||||
newlim.d_spc_timer = info->i_spc_timelimit;
|
||||
newlim.d_ino_timer = info->i_ino_timelimit;
|
||||
newlim.d_rt_spc_timer = info->i_rt_spc_timelimit;
|
||||
newlim.d_ino_warns = info->i_ino_warnlimit;
|
||||
newlim.d_spc_warns = info->i_spc_warnlimit;
|
||||
newlim.d_rt_spc_warns = info->i_rt_spc_warnlimit;
|
||||
|
||||
if (!XFS_IS_QUOTA_RUNNING(mp))
|
||||
return -ENOSYS;
|
||||
return xfs_qm_scall_getqstatv(mp, fqs);
|
||||
return xfs_qm_scall_setqlim(mp, 0, xfs_quota_type(type), &newlim);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
|
@ -178,8 +261,8 @@ xfs_fs_set_dqblk(
|
|||
}
|
||||
|
||||
const struct quotactl_ops xfs_quotactl_operations = {
|
||||
.get_xstatev = xfs_fs_get_xstatev,
|
||||
.get_xstate = xfs_fs_get_xstate,
|
||||
.get_state = xfs_fs_get_quota_state,
|
||||
.set_info = xfs_fs_set_info,
|
||||
.quota_enable = xfs_quota_enable,
|
||||
.quota_disable = xfs_quota_disable,
|
||||
.rm_xquota = xfs_fs_rm_xquota,
|
||||
|
|
|
@ -344,7 +344,10 @@ struct qc_dqblk {
|
|||
int d_rt_spc_warns; /* # warnings issued wrt RT space */
|
||||
};
|
||||
|
||||
/* Field specifiers for ->set_dqblk() in struct qc_dqblk */
|
||||
/*
|
||||
* Field specifiers for ->set_dqblk() in struct qc_dqblk and also for
|
||||
* ->set_info() in struct qc_info
|
||||
*/
|
||||
#define QC_INO_SOFT (1<<0)
|
||||
#define QC_INO_HARD (1<<1)
|
||||
#define QC_SPC_SOFT (1<<2)
|
||||
|
@ -365,6 +368,51 @@ struct qc_dqblk {
|
|||
#define QC_INO_COUNT (1<<13)
|
||||
#define QC_RT_SPACE (1<<14)
|
||||
#define QC_ACCT_MASK (QC_SPACE | QC_INO_COUNT | QC_RT_SPACE)
|
||||
#define QC_FLAGS (1<<15)
|
||||
|
||||
#define QCI_SYSFILE (1 << 0) /* Quota file is hidden from userspace */
|
||||
#define QCI_ROOT_SQUASH (1 << 1) /* Root squash turned on */
|
||||
#define QCI_ACCT_ENABLED (1 << 2) /* Quota accounting enabled */
|
||||
#define QCI_LIMITS_ENFORCED (1 << 3) /* Quota limits enforced */
|
||||
|
||||
/* Structures for communicating via ->get_state */
|
||||
struct qc_type_state {
|
||||
unsigned int flags; /* Flags QCI_* */
|
||||
unsigned int spc_timelimit; /* Time after which space softlimit is
|
||||
* enforced */
|
||||
unsigned int ino_timelimit; /* Ditto for inode softlimit */
|
||||
unsigned int rt_spc_timelimit; /* Ditto for real-time space */
|
||||
unsigned int spc_warnlimit; /* Limit for number of space warnings */
|
||||
unsigned int ino_warnlimit; /* Ditto for inodes */
|
||||
unsigned int rt_spc_warnlimit; /* Ditto for real-time space */
|
||||
unsigned long long ino; /* Inode number of quota file */
|
||||
blkcnt_t blocks; /* Number of 512-byte blocks in the file */
|
||||
blkcnt_t nextents; /* Number of extents in the file */
|
||||
};
|
||||
|
||||
struct qc_state {
|
||||
unsigned int s_incoredqs; /* Number of dquots in core */
|
||||
/*
|
||||
* Per quota type information. The array should really have
|
||||
* max(MAXQUOTAS, XQM_MAXQUOTAS) entries. BUILD_BUG_ON in
|
||||
* quota_getinfo() makes sure XQM_MAXQUOTAS is large enough. Once VFS
|
||||
* supports project quotas, this can be changed to MAXQUOTAS
|
||||
*/
|
||||
struct qc_type_state s_state[XQM_MAXQUOTAS];
|
||||
};
|
||||
|
||||
/* Structure for communicating via ->set_info */
|
||||
struct qc_info {
|
||||
int i_fieldmask; /* mask of fields to change in ->set_info() */
|
||||
unsigned int i_flags; /* Flags QCI_* */
|
||||
unsigned int i_spc_timelimit; /* Time after which space softlimit is
|
||||
* enforced */
|
||||
unsigned int i_ino_timelimit; /* Ditto for inode softlimit */
|
||||
unsigned int i_rt_spc_timelimit;/* Ditto for real-time space */
|
||||
unsigned int i_spc_warnlimit; /* Limit for number of space warnings */
|
||||
unsigned int i_ino_warnlimit; /* Limit for number of inode warnings */
|
||||
unsigned int i_rt_spc_warnlimit; /* Ditto for real-time space */
|
||||
};
|
||||
|
||||
/* Operations handling requests from userspace */
|
||||
struct quotactl_ops {
|
||||
|
@ -373,12 +421,10 @@ struct quotactl_ops {
|
|||
int (*quota_enable)(struct super_block *, unsigned int);
|
||||
int (*quota_disable)(struct super_block *, unsigned int);
|
||||
int (*quota_sync)(struct super_block *, int);
|
||||
int (*get_info)(struct super_block *, int, struct if_dqinfo *);
|
||||
int (*set_info)(struct super_block *, int, struct if_dqinfo *);
|
||||
int (*set_info)(struct super_block *, int, struct qc_info *);
|
||||
int (*get_dqblk)(struct super_block *, struct kqid, struct qc_dqblk *);
|
||||
int (*set_dqblk)(struct super_block *, struct kqid, struct qc_dqblk *);
|
||||
int (*get_xstate)(struct super_block *, struct fs_quota_stat *);
|
||||
int (*get_xstatev)(struct super_block *, struct fs_quota_statv *);
|
||||
int (*get_state)(struct super_block *, struct qc_state *);
|
||||
int (*rm_xquota)(struct super_block *, unsigned int);
|
||||
};
|
||||
|
||||
|
|
|
@ -95,8 +95,8 @@ int dquot_quota_on_mount(struct super_block *sb, char *qf_name,
|
|||
int dquot_quota_off(struct super_block *sb, int type);
|
||||
int dquot_writeback_dquots(struct super_block *sb, int type);
|
||||
int dquot_quota_sync(struct super_block *sb, int type);
|
||||
int dquot_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
|
||||
int dquot_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
|
||||
int dquot_get_state(struct super_block *sb, struct qc_state *state);
|
||||
int dquot_set_dqinfo(struct super_block *sb, int type, struct qc_info *ii);
|
||||
int dquot_get_dqblk(struct super_block *sb, struct kqid id,
|
||||
struct qc_dqblk *di);
|
||||
int dquot_set_dqblk(struct super_block *sb, struct kqid id,
|
||||
|
|
Loading…
Reference in a new issue