forked from Minki/linux
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs
Pull quota and udf updates from Jan Kara: "The pull contains quota changes which complete unification of XFS and VFS quota interfaces (so tools can use either interface to manipulate any filesystem). There's also a patch to support project quotas in VFS quota subsystem from Li Xi. Finally there's a bunch of UDF fixes and cleanups and tiny cleanup in reiserfs & ext3" * 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs: (21 commits) udf: Update ctime and mtime when directory is modified udf: return correct errno for udf_update_inode() ext3: Remove useless condition in if statement. vfs: Add general support to enforce project quota limits reiserfs: fix __RASSERT format string udf: use int for allocated blocks instead of sector_t udf: remove redundant buffer_head.h includes udf: remove else after return in __load_block_bitmap() udf: remove unused variable in udf_table_free_blocks() quota: Fix maximum quota limit settings quota: reorder flags in quota state quota: paranoia: check quota tree root quota: optimize i_dquot access quota: Hook up Q_XSETQLIM for id 0 to ->set_info xfs: Add support for Q_SETINFO quota: Make ->set_info use structure with neccesary info to VFS and XFS quota: Remove ->get_xstate and ->get_xstatev callbacks gfs2: Convert to using ->get_state callback xfs: Convert to using ->get_state callback quota: Wire up Q_GETXSTATE and Q_GETXSTATV calls to work with ->get_state ...
This commit is contained in:
commit
84588e7a5d
@ -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
|
||||
|
@ -546,8 +546,7 @@ ext3_xattr_set_entry(struct ext3_xattr_info *i, struct ext3_xattr_search *s)
|
||||
free += EXT3_XATTR_LEN(name_len);
|
||||
}
|
||||
if (i->value) {
|
||||
if (free < EXT3_XATTR_SIZE(i->value_len) ||
|
||||
free < EXT3_XATTR_LEN(name_len) +
|
||||
if (free < EXT3_XATTR_LEN(name_len) +
|
||||
EXT3_XATTR_SIZE(i->value_len))
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -1494,32 +1494,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;
|
||||
}
|
||||
|
||||
@ -1664,7 +1666,7 @@ out_put:
|
||||
|
||||
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,
|
||||
};
|
||||
|
147
fs/quota/dquot.c
147
fs/quota/dquot.c
@ -900,14 +900,17 @@ static inline struct dquot **i_dquot(struct inode *inode)
|
||||
|
||||
static int dqinit_needed(struct inode *inode, int type)
|
||||
{
|
||||
struct dquot * const *dquots;
|
||||
int cnt;
|
||||
|
||||
if (IS_NOQUOTA(inode))
|
||||
return 0;
|
||||
|
||||
dquots = i_dquot(inode);
|
||||
if (type != -1)
|
||||
return !i_dquot(inode)[type];
|
||||
return !dquots[type];
|
||||
for (cnt = 0; cnt < MAXQUOTAS; cnt++)
|
||||
if (!i_dquot(inode)[cnt])
|
||||
if (!dquots[cnt])
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
@ -970,12 +973,13 @@ static void add_dquot_ref(struct super_block *sb, int type)
|
||||
static void remove_inode_dquot_ref(struct inode *inode, int type,
|
||||
struct list_head *tofree_head)
|
||||
{
|
||||
struct dquot *dquot = i_dquot(inode)[type];
|
||||
struct dquot **dquots = i_dquot(inode);
|
||||
struct dquot *dquot = dquots[type];
|
||||
|
||||
i_dquot(inode)[type] = NULL;
|
||||
if (!dquot)
|
||||
return;
|
||||
|
||||
dquots[type] = NULL;
|
||||
if (list_empty(&dquot->dq_free)) {
|
||||
/*
|
||||
* The inode still has reference to dquot so it can't be in the
|
||||
@ -1159,8 +1163,8 @@ static int need_print_warning(struct dquot_warn *warn)
|
||||
return uid_eq(current_fsuid(), warn->w_dq_id.uid);
|
||||
case GRPQUOTA:
|
||||
return in_group_p(warn->w_dq_id.gid);
|
||||
case PRJQUOTA: /* Never taken... Just make gcc happy */
|
||||
return 0;
|
||||
case PRJQUOTA:
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -1389,16 +1393,21 @@ static int dquot_active(const struct inode *inode)
|
||||
static void __dquot_initialize(struct inode *inode, int type)
|
||||
{
|
||||
int cnt, init_needed = 0;
|
||||
struct dquot *got[MAXQUOTAS];
|
||||
struct dquot **dquots, *got[MAXQUOTAS];
|
||||
struct super_block *sb = inode->i_sb;
|
||||
qsize_t rsv;
|
||||
|
||||
if (!dquot_active(inode))
|
||||
return;
|
||||
|
||||
dquots = i_dquot(inode);
|
||||
|
||||
/* First get references to structures we might need. */
|
||||
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
|
||||
struct kqid qid;
|
||||
kprojid_t projid;
|
||||
int rc;
|
||||
|
||||
got[cnt] = NULL;
|
||||
if (type != -1 && cnt != type)
|
||||
continue;
|
||||
@ -1407,8 +1416,12 @@ static void __dquot_initialize(struct inode *inode, int type)
|
||||
* we check it without locking here to avoid unnecessary
|
||||
* dqget()/dqput() calls.
|
||||
*/
|
||||
if (i_dquot(inode)[cnt])
|
||||
if (dquots[cnt])
|
||||
continue;
|
||||
|
||||
if (!sb_has_quota_active(sb, cnt))
|
||||
continue;
|
||||
|
||||
init_needed = 1;
|
||||
|
||||
switch (cnt) {
|
||||
@ -1418,6 +1431,12 @@ static void __dquot_initialize(struct inode *inode, int type)
|
||||
case GRPQUOTA:
|
||||
qid = make_kqid_gid(inode->i_gid);
|
||||
break;
|
||||
case PRJQUOTA:
|
||||
rc = inode->i_sb->dq_op->get_projid(inode, &projid);
|
||||
if (rc)
|
||||
continue;
|
||||
qid = make_kqid_projid(projid);
|
||||
break;
|
||||
}
|
||||
got[cnt] = dqget(sb, qid);
|
||||
}
|
||||
@ -1438,8 +1457,8 @@ static void __dquot_initialize(struct inode *inode, int type)
|
||||
/* We could race with quotaon or dqget() could have failed */
|
||||
if (!got[cnt])
|
||||
continue;
|
||||
if (!i_dquot(inode)[cnt]) {
|
||||
i_dquot(inode)[cnt] = got[cnt];
|
||||
if (!dquots[cnt]) {
|
||||
dquots[cnt] = got[cnt];
|
||||
got[cnt] = NULL;
|
||||
/*
|
||||
* Make quota reservation system happy if someone
|
||||
@ -1447,7 +1466,7 @@ static void __dquot_initialize(struct inode *inode, int type)
|
||||
*/
|
||||
rsv = inode_get_rsv_space(inode);
|
||||
if (unlikely(rsv))
|
||||
dquot_resv_space(i_dquot(inode)[cnt], rsv);
|
||||
dquot_resv_space(dquots[cnt], rsv);
|
||||
}
|
||||
}
|
||||
out_err:
|
||||
@ -1473,12 +1492,13 @@ EXPORT_SYMBOL(dquot_initialize);
|
||||
static void __dquot_drop(struct inode *inode)
|
||||
{
|
||||
int cnt;
|
||||
struct dquot **dquots = i_dquot(inode);
|
||||
struct dquot *put[MAXQUOTAS];
|
||||
|
||||
spin_lock(&dq_data_lock);
|
||||
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
|
||||
put[cnt] = i_dquot(inode)[cnt];
|
||||
i_dquot(inode)[cnt] = NULL;
|
||||
put[cnt] = dquots[cnt];
|
||||
dquots[cnt] = NULL;
|
||||
}
|
||||
spin_unlock(&dq_data_lock);
|
||||
dqput_all(put);
|
||||
@ -1486,6 +1506,7 @@ static void __dquot_drop(struct inode *inode)
|
||||
|
||||
void dquot_drop(struct inode *inode)
|
||||
{
|
||||
struct dquot * const *dquots;
|
||||
int cnt;
|
||||
|
||||
if (IS_NOQUOTA(inode))
|
||||
@ -1498,8 +1519,9 @@ void dquot_drop(struct inode *inode)
|
||||
* must assure that nobody can come after the DQUOT_DROP and
|
||||
* add quota pointers back anyway.
|
||||
*/
|
||||
dquots = i_dquot(inode);
|
||||
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
|
||||
if (i_dquot(inode)[cnt])
|
||||
if (dquots[cnt])
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1600,8 +1622,8 @@ int __dquot_alloc_space(struct inode *inode, qsize_t number, int flags)
|
||||
{
|
||||
int cnt, ret = 0, index;
|
||||
struct dquot_warn warn[MAXQUOTAS];
|
||||
struct dquot **dquots = i_dquot(inode);
|
||||
int reserve = flags & DQUOT_SPACE_RESERVE;
|
||||
struct dquot **dquots;
|
||||
|
||||
if (!dquot_active(inode)) {
|
||||
inode_incr_space(inode, number, reserve);
|
||||
@ -1611,6 +1633,7 @@ int __dquot_alloc_space(struct inode *inode, qsize_t number, int flags)
|
||||
for (cnt = 0; cnt < MAXQUOTAS; cnt++)
|
||||
warn[cnt].w_type = QUOTA_NL_NOWARN;
|
||||
|
||||
dquots = i_dquot(inode);
|
||||
index = srcu_read_lock(&dquot_srcu);
|
||||
spin_lock(&dq_data_lock);
|
||||
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
|
||||
@ -1652,13 +1675,14 @@ int dquot_alloc_inode(struct inode *inode)
|
||||
{
|
||||
int cnt, ret = 0, index;
|
||||
struct dquot_warn warn[MAXQUOTAS];
|
||||
struct dquot * const *dquots = i_dquot(inode);
|
||||
struct dquot * const *dquots;
|
||||
|
||||
if (!dquot_active(inode))
|
||||
return 0;
|
||||
for (cnt = 0; cnt < MAXQUOTAS; cnt++)
|
||||
warn[cnt].w_type = QUOTA_NL_NOWARN;
|
||||
|
||||
dquots = i_dquot(inode);
|
||||
index = srcu_read_lock(&dquot_srcu);
|
||||
spin_lock(&dq_data_lock);
|
||||
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
|
||||
@ -1690,6 +1714,7 @@ EXPORT_SYMBOL(dquot_alloc_inode);
|
||||
*/
|
||||
int dquot_claim_space_nodirty(struct inode *inode, qsize_t number)
|
||||
{
|
||||
struct dquot **dquots;
|
||||
int cnt, index;
|
||||
|
||||
if (!dquot_active(inode)) {
|
||||
@ -1697,18 +1722,18 @@ int dquot_claim_space_nodirty(struct inode *inode, qsize_t number)
|
||||
return 0;
|
||||
}
|
||||
|
||||
dquots = i_dquot(inode);
|
||||
index = srcu_read_lock(&dquot_srcu);
|
||||
spin_lock(&dq_data_lock);
|
||||
/* Claim reserved quotas to allocated quotas */
|
||||
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
|
||||
if (i_dquot(inode)[cnt])
|
||||
dquot_claim_reserved_space(i_dquot(inode)[cnt],
|
||||
number);
|
||||
if (dquots[cnt])
|
||||
dquot_claim_reserved_space(dquots[cnt], number);
|
||||
}
|
||||
/* Update inode bytes */
|
||||
inode_claim_rsv_space(inode, number);
|
||||
spin_unlock(&dq_data_lock);
|
||||
mark_all_dquot_dirty(i_dquot(inode));
|
||||
mark_all_dquot_dirty(dquots);
|
||||
srcu_read_unlock(&dquot_srcu, index);
|
||||
return 0;
|
||||
}
|
||||
@ -1719,6 +1744,7 @@ EXPORT_SYMBOL(dquot_claim_space_nodirty);
|
||||
*/
|
||||
void dquot_reclaim_space_nodirty(struct inode *inode, qsize_t number)
|
||||
{
|
||||
struct dquot **dquots;
|
||||
int cnt, index;
|
||||
|
||||
if (!dquot_active(inode)) {
|
||||
@ -1726,18 +1752,18 @@ void dquot_reclaim_space_nodirty(struct inode *inode, qsize_t number)
|
||||
return;
|
||||
}
|
||||
|
||||
dquots = i_dquot(inode);
|
||||
index = srcu_read_lock(&dquot_srcu);
|
||||
spin_lock(&dq_data_lock);
|
||||
/* Claim reserved quotas to allocated quotas */
|
||||
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
|
||||
if (i_dquot(inode)[cnt])
|
||||
dquot_reclaim_reserved_space(i_dquot(inode)[cnt],
|
||||
number);
|
||||
if (dquots[cnt])
|
||||
dquot_reclaim_reserved_space(dquots[cnt], number);
|
||||
}
|
||||
/* Update inode bytes */
|
||||
inode_reclaim_rsv_space(inode, number);
|
||||
spin_unlock(&dq_data_lock);
|
||||
mark_all_dquot_dirty(i_dquot(inode));
|
||||
mark_all_dquot_dirty(dquots);
|
||||
srcu_read_unlock(&dquot_srcu, index);
|
||||
return;
|
||||
}
|
||||
@ -1750,7 +1776,7 @@ void __dquot_free_space(struct inode *inode, qsize_t number, int flags)
|
||||
{
|
||||
unsigned int cnt;
|
||||
struct dquot_warn warn[MAXQUOTAS];
|
||||
struct dquot **dquots = i_dquot(inode);
|
||||
struct dquot **dquots;
|
||||
int reserve = flags & DQUOT_SPACE_RESERVE, index;
|
||||
|
||||
if (!dquot_active(inode)) {
|
||||
@ -1758,6 +1784,7 @@ void __dquot_free_space(struct inode *inode, qsize_t number, int flags)
|
||||
return;
|
||||
}
|
||||
|
||||
dquots = i_dquot(inode);
|
||||
index = srcu_read_lock(&dquot_srcu);
|
||||
spin_lock(&dq_data_lock);
|
||||
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
|
||||
@ -1793,12 +1820,13 @@ void dquot_free_inode(struct inode *inode)
|
||||
{
|
||||
unsigned int cnt;
|
||||
struct dquot_warn warn[MAXQUOTAS];
|
||||
struct dquot * const *dquots = i_dquot(inode);
|
||||
struct dquot * const *dquots;
|
||||
int index;
|
||||
|
||||
if (!dquot_active(inode))
|
||||
return;
|
||||
|
||||
dquots = i_dquot(inode);
|
||||
index = srcu_read_lock(&dquot_srcu);
|
||||
spin_lock(&dq_data_lock);
|
||||
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
|
||||
@ -2161,7 +2189,8 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id,
|
||||
error = -EROFS;
|
||||
goto out_fmt;
|
||||
}
|
||||
if (!sb->s_op->quota_write || !sb->s_op->quota_read) {
|
||||
if (!sb->s_op->quota_write || !sb->s_op->quota_read ||
|
||||
(type == PRJQUOTA && sb->dq_op->get_projid == NULL)) {
|
||||
error = -EINVAL;
|
||||
goto out_fmt;
|
||||
}
|
||||
@ -2614,55 +2643,73 @@ out:
|
||||
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);
|
||||
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;
|
||||
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);
|
||||
}
|
||||
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 */
|
||||
@ -2677,7 +2724,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
|
||||
@ -2688,7 +2735,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);
|
||||
}
|
||||
|
@ -349,6 +349,13 @@ static inline int dq_insert_tree(struct qtree_mem_dqinfo *info,
|
||||
struct dquot *dquot)
|
||||
{
|
||||
int tmp = QT_TREEOFF;
|
||||
|
||||
#ifdef __QUOTA_QT_PARANOIA
|
||||
if (info->dqi_blocks <= QT_TREEOFF) {
|
||||
quota_error(dquot->dq_sb, "Quota tree root isn't allocated!");
|
||||
return -EIO;
|
||||
}
|
||||
#endif
|
||||
return do_insert_tree(info, dquot, &tmp, 0);
|
||||
}
|
||||
|
||||
|
@ -117,12 +117,16 @@ static int v2_read_file_info(struct super_block *sb, int type)
|
||||
qinfo = info->dqi_priv;
|
||||
if (version == 0) {
|
||||
/* limits are stored as unsigned 32-bit data */
|
||||
info->dqi_max_spc_limit = 0xffffffffULL << QUOTABLOCK_BITS;
|
||||
info->dqi_max_spc_limit = 0xffffffffLL << QUOTABLOCK_BITS;
|
||||
info->dqi_max_ino_limit = 0xffffffff;
|
||||
} else {
|
||||
/* used space is stored as unsigned 64-bit value in bytes */
|
||||
info->dqi_max_spc_limit = 0xffffffffffffffffULL; /* 2^64-1 */
|
||||
info->dqi_max_ino_limit = 0xffffffffffffffffULL;
|
||||
/*
|
||||
* Used space is stored as unsigned 64-bit value in bytes but
|
||||
* quota core supports only signed 64-bit values so use that
|
||||
* as a limit
|
||||
*/
|
||||
info->dqi_max_spc_limit = 0x7fffffffffffffffLL; /* 2^63-1 */
|
||||
info->dqi_max_ino_limit = 0x7fffffffffffffffLL;
|
||||
}
|
||||
info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
|
||||
info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace);
|
||||
|
@ -13,12 +13,14 @@
|
||||
*/
|
||||
#define V2_INITQMAGICS {\
|
||||
0xd9c01f11, /* USRQUOTA */\
|
||||
0xd9c01927 /* GRPQUOTA */\
|
||||
0xd9c01927, /* GRPQUOTA */\
|
||||
0xd9c03f14, /* PRJQUOTA */\
|
||||
}
|
||||
|
||||
#define V2_INITQVERSIONS {\
|
||||
1, /* USRQUOTA */\
|
||||
1 /* GRPQUOTA */\
|
||||
1, /* GRPQUOTA */\
|
||||
1, /* PRJQUOTA */\
|
||||
}
|
||||
|
||||
/* First generic header */
|
||||
|
@ -910,7 +910,6 @@ do { \
|
||||
if (!(cond)) \
|
||||
reiserfs_panic(NULL, "assertion failure", "(" #cond ") at " \
|
||||
__FILE__ ":%i:%s: " format "\n", \
|
||||
in_interrupt() ? -1 : task_pid_nr(current), \
|
||||
__LINE__, __func__ , ##args); \
|
||||
} while (0)
|
||||
|
||||
|
@ -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,
|
||||
|
@ -21,7 +21,6 @@
|
||||
|
||||
#include "udfdecl.h"
|
||||
|
||||
#include <linux/buffer_head.h>
|
||||
#include <linux/bitops.h>
|
||||
|
||||
#include "udf_i.h"
|
||||
@ -63,15 +62,14 @@ static int __load_block_bitmap(struct super_block *sb,
|
||||
block_group, nr_groups);
|
||||
}
|
||||
|
||||
if (bitmap->s_block_bitmap[block_group]) {
|
||||
if (bitmap->s_block_bitmap[block_group])
|
||||
return block_group;
|
||||
} else {
|
||||
retval = read_block_bitmap(sb, bitmap, block_group,
|
||||
block_group);
|
||||
|
||||
retval = read_block_bitmap(sb, bitmap, block_group, block_group);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
return block_group;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int load_block_bitmap(struct super_block *sb,
|
||||
@ -358,7 +356,6 @@ static void udf_table_free_blocks(struct super_block *sb,
|
||||
struct kernel_lb_addr eloc;
|
||||
struct extent_position oepos, epos;
|
||||
int8_t etype;
|
||||
int i;
|
||||
struct udf_inode_info *iinfo;
|
||||
|
||||
mutex_lock(&sbi->s_alloc_mutex);
|
||||
@ -425,7 +422,6 @@ static void udf_table_free_blocks(struct super_block *sb,
|
||||
}
|
||||
|
||||
if (epos.bh != oepos.bh) {
|
||||
i = -1;
|
||||
oepos.block = epos.block;
|
||||
brelse(oepos.bh);
|
||||
get_bh(epos.bh);
|
||||
@ -762,7 +758,7 @@ inline int udf_prealloc_blocks(struct super_block *sb,
|
||||
uint32_t block_count)
|
||||
{
|
||||
struct udf_part_map *map = &UDF_SB(sb)->s_partmaps[partition];
|
||||
sector_t allocated;
|
||||
int allocated;
|
||||
|
||||
if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP)
|
||||
allocated = udf_bitmap_prealloc_blocks(sb,
|
||||
|
@ -30,7 +30,6 @@
|
||||
#include <linux/errno.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/buffer_head.h>
|
||||
|
||||
#include "udf_i.h"
|
||||
#include "udf_sb.h"
|
||||
|
@ -16,7 +16,6 @@
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/buffer_head.h>
|
||||
|
||||
struct fileIdentDesc *udf_fileident_read(struct inode *dir, loff_t *nf_pos,
|
||||
struct udf_fileident_bh *fibh,
|
||||
|
@ -33,7 +33,6 @@
|
||||
#include <linux/capability.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/buffer_head.h>
|
||||
#include <linux/uio.h>
|
||||
|
||||
#include "udf_i.h"
|
||||
|
@ -33,7 +33,6 @@
|
||||
#include <linux/mm.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/buffer_head.h>
|
||||
#include <linux/writeback.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/crc-itu-t.h>
|
||||
@ -1637,7 +1636,7 @@ static int udf_update_inode(struct inode *inode, int do_sync)
|
||||
udf_get_lb_pblock(inode->i_sb, &iinfo->i_location, 0));
|
||||
if (!bh) {
|
||||
udf_debug("getblk failure\n");
|
||||
return -ENOMEM;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
lock_buffer(bh);
|
||||
|
@ -23,7 +23,6 @@
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/buffer_head.h>
|
||||
#include <linux/crc-itu-t.h>
|
||||
|
||||
#include "udf_i.h"
|
||||
|
@ -27,7 +27,6 @@
|
||||
#include <linux/errno.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/buffer_head.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/crc-itu-t.h>
|
||||
#include <linux/exportfs.h>
|
||||
@ -569,7 +568,7 @@ static int udf_add_nondir(struct dentry *dentry, struct inode *inode)
|
||||
*(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
|
||||
cpu_to_le32(iinfo->i_unique & 0x00000000FFFFFFFFUL);
|
||||
udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
|
||||
if (UDF_I(dir)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
|
||||
dir->i_ctime = dir->i_mtime = current_fs_time(dir->i_sb);
|
||||
mark_inode_dirty(dir);
|
||||
if (fibh.sbh != fibh.ebh)
|
||||
brelse(fibh.ebh);
|
||||
@ -683,6 +682,7 @@ static int udf_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
|
||||
cfi.fileCharacteristics |= FID_FILE_CHAR_DIRECTORY;
|
||||
udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
|
||||
inc_nlink(dir);
|
||||
dir->i_ctime = dir->i_mtime = current_fs_time(dir->i_sb);
|
||||
mark_inode_dirty(dir);
|
||||
unlock_new_inode(inode);
|
||||
d_instantiate(dentry, inode);
|
||||
@ -1024,6 +1024,8 @@ static int udf_link(struct dentry *old_dentry, struct inode *dir,
|
||||
inc_nlink(inode);
|
||||
inode->i_ctime = current_fs_time(inode->i_sb);
|
||||
mark_inode_dirty(inode);
|
||||
dir->i_ctime = dir->i_mtime = current_fs_time(dir->i_sb);
|
||||
mark_inode_dirty(dir);
|
||||
ihold(inode);
|
||||
d_instantiate(dentry, inode);
|
||||
|
||||
@ -1127,7 +1129,9 @@ static int udf_rename(struct inode *old_dir, struct dentry *old_dentry,
|
||||
inode_dec_link_count(new_inode);
|
||||
}
|
||||
old_dir->i_ctime = old_dir->i_mtime = current_fs_time(old_dir->i_sb);
|
||||
new_dir->i_ctime = new_dir->i_mtime = current_fs_time(new_dir->i_sb);
|
||||
mark_inode_dirty(old_dir);
|
||||
mark_inode_dirty(new_dir);
|
||||
|
||||
if (dir_fi) {
|
||||
dir_fi->icb.extLocation = cpu_to_lelb(UDF_I(new_dir)->i_location);
|
||||
|
@ -24,7 +24,6 @@
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/buffer_head.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
uint32_t udf_get_pblock(struct super_block *sb, uint32_t block,
|
||||
|
@ -48,7 +48,6 @@
|
||||
#include <linux/stat.h>
|
||||
#include <linux/cdrom.h>
|
||||
#include <linux/nls.h>
|
||||
#include <linux/buffer_head.h>
|
||||
#include <linux/vfs.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/errno.h>
|
||||
|
@ -27,7 +27,6 @@
|
||||
#include <linux/mm.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/buffer_head.h>
|
||||
#include "udf_i.h"
|
||||
|
||||
static int udf_pc_to_char(struct super_block *sb, unsigned char *from,
|
||||
|
@ -22,7 +22,6 @@
|
||||
#include "udfdecl.h"
|
||||
#include <linux/fs.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/buffer_head.h>
|
||||
|
||||
#include "udf_i.h"
|
||||
#include "udf_sb.h"
|
||||
|
@ -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 @@ out_put:
|
||||
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(
|
||||
#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,
|
||||
struct fs_quota_stat *fqs)
|
||||
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,
|
||||
|
@ -50,6 +50,7 @@
|
||||
|
||||
#undef USRQUOTA
|
||||
#undef GRPQUOTA
|
||||
#undef PRJQUOTA
|
||||
enum quota_type {
|
||||
USRQUOTA = 0, /* element used for user quotas */
|
||||
GRPQUOTA = 1, /* element used for group quotas */
|
||||
@ -319,6 +320,7 @@ struct dquot_operations {
|
||||
/* get reserved quota for delayed alloc, value returned is managed by
|
||||
* quota code only */
|
||||
qsize_t *(*get_reserved_space) (struct inode *);
|
||||
int (*get_projid) (struct inode *, kprojid_t *);/* Get project ID */
|
||||
};
|
||||
|
||||
struct path;
|
||||
@ -344,7 +346,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 +370,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 +423,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);
|
||||
};
|
||||
|
||||
@ -389,7 +437,19 @@ struct quota_format_type {
|
||||
struct quota_format_type *qf_next;
|
||||
};
|
||||
|
||||
/* Quota state flags - they actually come in two flavors - for users and groups */
|
||||
/**
|
||||
* Quota state flags - they actually come in two flavors - for users and groups.
|
||||
*
|
||||
* Actual typed flags layout:
|
||||
* USRQUOTA GRPQUOTA
|
||||
* DQUOT_USAGE_ENABLED 0x0001 0x0002
|
||||
* DQUOT_LIMITS_ENABLED 0x0004 0x0008
|
||||
* DQUOT_SUSPENDED 0x0010 0x0020
|
||||
*
|
||||
* Following bits are used for non-typed flags:
|
||||
* DQUOT_QUOTA_SYS_FILE 0x0040
|
||||
* DQUOT_NEGATIVE_USAGE 0x0080
|
||||
*/
|
||||
enum {
|
||||
_DQUOT_USAGE_ENABLED = 0, /* Track disk usage for users */
|
||||
_DQUOT_LIMITS_ENABLED, /* Enforce quota limits for users */
|
||||
@ -398,9 +458,9 @@ enum {
|
||||
* memory to turn them on */
|
||||
_DQUOT_STATE_FLAGS
|
||||
};
|
||||
#define DQUOT_USAGE_ENABLED (1 << _DQUOT_USAGE_ENABLED)
|
||||
#define DQUOT_LIMITS_ENABLED (1 << _DQUOT_LIMITS_ENABLED)
|
||||
#define DQUOT_SUSPENDED (1 << _DQUOT_SUSPENDED)
|
||||
#define DQUOT_USAGE_ENABLED (1 << _DQUOT_USAGE_ENABLED * MAXQUOTAS)
|
||||
#define DQUOT_LIMITS_ENABLED (1 << _DQUOT_LIMITS_ENABLED * MAXQUOTAS)
|
||||
#define DQUOT_SUSPENDED (1 << _DQUOT_SUSPENDED * MAXQUOTAS)
|
||||
#define DQUOT_STATE_FLAGS (DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED | \
|
||||
DQUOT_SUSPENDED)
|
||||
/* Other quota flags */
|
||||
@ -414,15 +474,21 @@ enum {
|
||||
*/
|
||||
#define DQUOT_NEGATIVE_USAGE (1 << (DQUOT_STATE_LAST + 1))
|
||||
/* Allow negative quota usage */
|
||||
|
||||
static inline unsigned int dquot_state_flag(unsigned int flags, int type)
|
||||
{
|
||||
return flags << _DQUOT_STATE_FLAGS * type;
|
||||
return flags << type;
|
||||
}
|
||||
|
||||
static inline unsigned int dquot_generic_flag(unsigned int flags, int type)
|
||||
{
|
||||
return (flags >> _DQUOT_STATE_FLAGS * type) & DQUOT_STATE_FLAGS;
|
||||
return (flags >> type) & DQUOT_STATE_FLAGS;
|
||||
}
|
||||
|
||||
/* Bitmap of quota types where flag is set in flags */
|
||||
static __always_inline unsigned dquot_state_types(unsigned flags, unsigned flag)
|
||||
{
|
||||
BUILD_BUG_ON_NOT_POWER_OF_2(flag);
|
||||
return (flags / flag) & ((1 << MAXQUOTAS) - 1);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_QUOTA_NETLINK_INTERFACE
|
||||
|
@ -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,
|
||||
@ -134,10 +134,7 @@ static inline bool sb_has_quota_suspended(struct super_block *sb, int type)
|
||||
|
||||
static inline unsigned sb_any_quota_suspended(struct super_block *sb)
|
||||
{
|
||||
unsigned type, tmsk = 0;
|
||||
for (type = 0; type < MAXQUOTAS; type++)
|
||||
tmsk |= sb_has_quota_suspended(sb, type) << type;
|
||||
return tmsk;
|
||||
return dquot_state_types(sb_dqopt(sb)->flags, DQUOT_SUSPENDED);
|
||||
}
|
||||
|
||||
/* Does kernel know about any quota information for given sb + type? */
|
||||
@ -149,10 +146,7 @@ static inline bool sb_has_quota_loaded(struct super_block *sb, int type)
|
||||
|
||||
static inline unsigned sb_any_quota_loaded(struct super_block *sb)
|
||||
{
|
||||
unsigned type, tmsk = 0;
|
||||
for (type = 0; type < MAXQUOTAS; type++)
|
||||
tmsk |= sb_has_quota_loaded(sb, type) << type;
|
||||
return tmsk;
|
||||
return dquot_state_types(sb_dqopt(sb)->flags, DQUOT_USAGE_ENABLED);
|
||||
}
|
||||
|
||||
static inline bool sb_has_quota_active(struct super_block *sb, int type)
|
||||
|
@ -36,11 +36,12 @@
|
||||
#include <linux/errno.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#define __DQUOT_VERSION__ "dquot_6.5.2"
|
||||
#define __DQUOT_VERSION__ "dquot_6.6.0"
|
||||
|
||||
#define MAXQUOTAS 2
|
||||
#define MAXQUOTAS 3
|
||||
#define USRQUOTA 0 /* element used for user quotas */
|
||||
#define GRPQUOTA 1 /* element used for group quotas */
|
||||
#define PRJQUOTA 2 /* element used for project quotas */
|
||||
|
||||
/*
|
||||
* Definitions for the default names of the quotas files.
|
||||
@ -48,6 +49,7 @@
|
||||
#define INITQFNAMES { \
|
||||
"user", /* USRQUOTA */ \
|
||||
"group", /* GRPQUOTA */ \
|
||||
"project", /* PRJQUOTA */ \
|
||||
"undefined", \
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user