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:
Коммит
84588e7a5d
|
@ -789,7 +789,7 @@ static const struct quotactl_ops ext3_qctl_operations = {
|
||||||
.quota_on = ext3_quota_on,
|
.quota_on = ext3_quota_on,
|
||||||
.quota_off = dquot_quota_off,
|
.quota_off = dquot_quota_off,
|
||||||
.quota_sync = dquot_quota_sync,
|
.quota_sync = dquot_quota_sync,
|
||||||
.get_info = dquot_get_dqinfo,
|
.get_state = dquot_get_state,
|
||||||
.set_info = dquot_set_dqinfo,
|
.set_info = dquot_set_dqinfo,
|
||||||
.get_dqblk = dquot_get_dqblk,
|
.get_dqblk = dquot_get_dqblk,
|
||||||
.set_dqblk = dquot_set_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);
|
free += EXT3_XATTR_LEN(name_len);
|
||||||
}
|
}
|
||||||
if (i->value) {
|
if (i->value) {
|
||||||
if (free < EXT3_XATTR_SIZE(i->value_len) ||
|
if (free < EXT3_XATTR_LEN(name_len) +
|
||||||
free < EXT3_XATTR_LEN(name_len) +
|
|
||||||
EXT3_XATTR_SIZE(i->value_len))
|
EXT3_XATTR_SIZE(i->value_len))
|
||||||
return -ENOSPC;
|
return -ENOSPC;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1076,7 +1076,7 @@ static const struct quotactl_ops ext4_qctl_operations = {
|
||||||
.quota_on = ext4_quota_on,
|
.quota_on = ext4_quota_on,
|
||||||
.quota_off = ext4_quota_off,
|
.quota_off = ext4_quota_off,
|
||||||
.quota_sync = dquot_quota_sync,
|
.quota_sync = dquot_quota_sync,
|
||||||
.get_info = dquot_get_dqinfo,
|
.get_state = dquot_get_state,
|
||||||
.set_info = dquot_set_dqinfo,
|
.set_info = dquot_set_dqinfo,
|
||||||
.get_dqblk = dquot_get_dqblk,
|
.get_dqblk = dquot_get_dqblk,
|
||||||
.set_dqblk = dquot_set_dqblk
|
.set_dqblk = dquot_set_dqblk
|
||||||
|
|
|
@ -1494,32 +1494,34 @@ int gfs2_quotad(void *data)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int gfs2_quota_get_xstate(struct super_block *sb,
|
static int gfs2_quota_get_state(struct super_block *sb, struct qc_state *state)
|
||||||
struct fs_quota_stat *fqs)
|
|
||||||
{
|
{
|
||||||
struct gfs2_sbd *sdp = sb->s_fs_info;
|
struct gfs2_sbd *sdp = sb->s_fs_info;
|
||||||
|
|
||||||
memset(fqs, 0, sizeof(struct fs_quota_stat));
|
memset(state, 0, sizeof(*state));
|
||||||
fqs->qs_version = FS_QSTAT_VERSION;
|
|
||||||
|
|
||||||
switch (sdp->sd_args.ar_quota) {
|
switch (sdp->sd_args.ar_quota) {
|
||||||
case GFS2_QUOTA_ON:
|
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*/
|
/*FALLTHRU*/
|
||||||
case GFS2_QUOTA_ACCOUNT:
|
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;
|
break;
|
||||||
case GFS2_QUOTA_OFF:
|
case GFS2_QUOTA_OFF:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sdp->sd_quota_inode) {
|
if (sdp->sd_quota_inode) {
|
||||||
fqs->qs_uquota.qfs_ino = GFS2_I(sdp->sd_quota_inode)->i_no_addr;
|
state->s_state[USRQUOTA].ino =
|
||||||
fqs->qs_uquota.qfs_nblks = sdp->sd_quota_inode->i_blocks;
|
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 */
|
state->s_state[USRQUOTA].nextents = 1; /* unsupported */
|
||||||
fqs->qs_gquota = fqs->qs_uquota; /* its the same inode in both cases */
|
state->s_state[GRPQUOTA] = state->s_state[USRQUOTA];
|
||||||
fqs->qs_incoredqs = list_lru_count(&gfs2_qd_lru);
|
state->s_incoredqs = list_lru_count(&gfs2_qd_lru);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1664,7 +1666,7 @@ out_put:
|
||||||
|
|
||||||
const struct quotactl_ops gfs2_quotactl_ops = {
|
const struct quotactl_ops gfs2_quotactl_ops = {
|
||||||
.quota_sync = gfs2_quota_sync,
|
.quota_sync = gfs2_quota_sync,
|
||||||
.get_xstate = gfs2_quota_get_xstate,
|
.get_state = gfs2_quota_get_state,
|
||||||
.get_dqblk = gfs2_get_dqblk,
|
.get_dqblk = gfs2_get_dqblk,
|
||||||
.set_dqblk = gfs2_set_dqblk,
|
.set_dqblk = gfs2_set_dqblk,
|
||||||
};
|
};
|
||||||
|
|
151
fs/quota/dquot.c
151
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)
|
static int dqinit_needed(struct inode *inode, int type)
|
||||||
{
|
{
|
||||||
|
struct dquot * const *dquots;
|
||||||
int cnt;
|
int cnt;
|
||||||
|
|
||||||
if (IS_NOQUOTA(inode))
|
if (IS_NOQUOTA(inode))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
dquots = i_dquot(inode);
|
||||||
if (type != -1)
|
if (type != -1)
|
||||||
return !i_dquot(inode)[type];
|
return !dquots[type];
|
||||||
for (cnt = 0; cnt < MAXQUOTAS; cnt++)
|
for (cnt = 0; cnt < MAXQUOTAS; cnt++)
|
||||||
if (!i_dquot(inode)[cnt])
|
if (!dquots[cnt])
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
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,
|
static void remove_inode_dquot_ref(struct inode *inode, int type,
|
||||||
struct list_head *tofree_head)
|
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)
|
if (!dquot)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
dquots[type] = NULL;
|
||||||
if (list_empty(&dquot->dq_free)) {
|
if (list_empty(&dquot->dq_free)) {
|
||||||
/*
|
/*
|
||||||
* The inode still has reference to dquot so it can't be in the
|
* 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);
|
return uid_eq(current_fsuid(), warn->w_dq_id.uid);
|
||||||
case GRPQUOTA:
|
case GRPQUOTA:
|
||||||
return in_group_p(warn->w_dq_id.gid);
|
return in_group_p(warn->w_dq_id.gid);
|
||||||
case PRJQUOTA: /* Never taken... Just make gcc happy */
|
case PRJQUOTA:
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1389,16 +1393,21 @@ static int dquot_active(const struct inode *inode)
|
||||||
static void __dquot_initialize(struct inode *inode, int type)
|
static void __dquot_initialize(struct inode *inode, int type)
|
||||||
{
|
{
|
||||||
int cnt, init_needed = 0;
|
int cnt, init_needed = 0;
|
||||||
struct dquot *got[MAXQUOTAS];
|
struct dquot **dquots, *got[MAXQUOTAS];
|
||||||
struct super_block *sb = inode->i_sb;
|
struct super_block *sb = inode->i_sb;
|
||||||
qsize_t rsv;
|
qsize_t rsv;
|
||||||
|
|
||||||
if (!dquot_active(inode))
|
if (!dquot_active(inode))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
dquots = i_dquot(inode);
|
||||||
|
|
||||||
/* First get references to structures we might need. */
|
/* First get references to structures we might need. */
|
||||||
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
|
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
|
||||||
struct kqid qid;
|
struct kqid qid;
|
||||||
|
kprojid_t projid;
|
||||||
|
int rc;
|
||||||
|
|
||||||
got[cnt] = NULL;
|
got[cnt] = NULL;
|
||||||
if (type != -1 && cnt != type)
|
if (type != -1 && cnt != type)
|
||||||
continue;
|
continue;
|
||||||
|
@ -1407,8 +1416,12 @@ static void __dquot_initialize(struct inode *inode, int type)
|
||||||
* we check it without locking here to avoid unnecessary
|
* we check it without locking here to avoid unnecessary
|
||||||
* dqget()/dqput() calls.
|
* dqget()/dqput() calls.
|
||||||
*/
|
*/
|
||||||
if (i_dquot(inode)[cnt])
|
if (dquots[cnt])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (!sb_has_quota_active(sb, cnt))
|
||||||
|
continue;
|
||||||
|
|
||||||
init_needed = 1;
|
init_needed = 1;
|
||||||
|
|
||||||
switch (cnt) {
|
switch (cnt) {
|
||||||
|
@ -1418,6 +1431,12 @@ static void __dquot_initialize(struct inode *inode, int type)
|
||||||
case GRPQUOTA:
|
case GRPQUOTA:
|
||||||
qid = make_kqid_gid(inode->i_gid);
|
qid = make_kqid_gid(inode->i_gid);
|
||||||
break;
|
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);
|
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 */
|
/* We could race with quotaon or dqget() could have failed */
|
||||||
if (!got[cnt])
|
if (!got[cnt])
|
||||||
continue;
|
continue;
|
||||||
if (!i_dquot(inode)[cnt]) {
|
if (!dquots[cnt]) {
|
||||||
i_dquot(inode)[cnt] = got[cnt];
|
dquots[cnt] = got[cnt];
|
||||||
got[cnt] = NULL;
|
got[cnt] = NULL;
|
||||||
/*
|
/*
|
||||||
* Make quota reservation system happy if someone
|
* 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);
|
rsv = inode_get_rsv_space(inode);
|
||||||
if (unlikely(rsv))
|
if (unlikely(rsv))
|
||||||
dquot_resv_space(i_dquot(inode)[cnt], rsv);
|
dquot_resv_space(dquots[cnt], rsv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out_err:
|
out_err:
|
||||||
|
@ -1473,12 +1492,13 @@ EXPORT_SYMBOL(dquot_initialize);
|
||||||
static void __dquot_drop(struct inode *inode)
|
static void __dquot_drop(struct inode *inode)
|
||||||
{
|
{
|
||||||
int cnt;
|
int cnt;
|
||||||
|
struct dquot **dquots = i_dquot(inode);
|
||||||
struct dquot *put[MAXQUOTAS];
|
struct dquot *put[MAXQUOTAS];
|
||||||
|
|
||||||
spin_lock(&dq_data_lock);
|
spin_lock(&dq_data_lock);
|
||||||
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
|
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
|
||||||
put[cnt] = i_dquot(inode)[cnt];
|
put[cnt] = dquots[cnt];
|
||||||
i_dquot(inode)[cnt] = NULL;
|
dquots[cnt] = NULL;
|
||||||
}
|
}
|
||||||
spin_unlock(&dq_data_lock);
|
spin_unlock(&dq_data_lock);
|
||||||
dqput_all(put);
|
dqput_all(put);
|
||||||
|
@ -1486,6 +1506,7 @@ static void __dquot_drop(struct inode *inode)
|
||||||
|
|
||||||
void dquot_drop(struct inode *inode)
|
void dquot_drop(struct inode *inode)
|
||||||
{
|
{
|
||||||
|
struct dquot * const *dquots;
|
||||||
int cnt;
|
int cnt;
|
||||||
|
|
||||||
if (IS_NOQUOTA(inode))
|
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
|
* must assure that nobody can come after the DQUOT_DROP and
|
||||||
* add quota pointers back anyway.
|
* add quota pointers back anyway.
|
||||||
*/
|
*/
|
||||||
|
dquots = i_dquot(inode);
|
||||||
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
|
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
|
||||||
if (i_dquot(inode)[cnt])
|
if (dquots[cnt])
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1600,8 +1622,8 @@ int __dquot_alloc_space(struct inode *inode, qsize_t number, int flags)
|
||||||
{
|
{
|
||||||
int cnt, ret = 0, index;
|
int cnt, ret = 0, index;
|
||||||
struct dquot_warn warn[MAXQUOTAS];
|
struct dquot_warn warn[MAXQUOTAS];
|
||||||
struct dquot **dquots = i_dquot(inode);
|
|
||||||
int reserve = flags & DQUOT_SPACE_RESERVE;
|
int reserve = flags & DQUOT_SPACE_RESERVE;
|
||||||
|
struct dquot **dquots;
|
||||||
|
|
||||||
if (!dquot_active(inode)) {
|
if (!dquot_active(inode)) {
|
||||||
inode_incr_space(inode, number, reserve);
|
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++)
|
for (cnt = 0; cnt < MAXQUOTAS; cnt++)
|
||||||
warn[cnt].w_type = QUOTA_NL_NOWARN;
|
warn[cnt].w_type = QUOTA_NL_NOWARN;
|
||||||
|
|
||||||
|
dquots = i_dquot(inode);
|
||||||
index = srcu_read_lock(&dquot_srcu);
|
index = srcu_read_lock(&dquot_srcu);
|
||||||
spin_lock(&dq_data_lock);
|
spin_lock(&dq_data_lock);
|
||||||
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
|
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
|
||||||
|
@ -1652,13 +1675,14 @@ int dquot_alloc_inode(struct inode *inode)
|
||||||
{
|
{
|
||||||
int cnt, ret = 0, index;
|
int cnt, ret = 0, index;
|
||||||
struct dquot_warn warn[MAXQUOTAS];
|
struct dquot_warn warn[MAXQUOTAS];
|
||||||
struct dquot * const *dquots = i_dquot(inode);
|
struct dquot * const *dquots;
|
||||||
|
|
||||||
if (!dquot_active(inode))
|
if (!dquot_active(inode))
|
||||||
return 0;
|
return 0;
|
||||||
for (cnt = 0; cnt < MAXQUOTAS; cnt++)
|
for (cnt = 0; cnt < MAXQUOTAS; cnt++)
|
||||||
warn[cnt].w_type = QUOTA_NL_NOWARN;
|
warn[cnt].w_type = QUOTA_NL_NOWARN;
|
||||||
|
|
||||||
|
dquots = i_dquot(inode);
|
||||||
index = srcu_read_lock(&dquot_srcu);
|
index = srcu_read_lock(&dquot_srcu);
|
||||||
spin_lock(&dq_data_lock);
|
spin_lock(&dq_data_lock);
|
||||||
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
|
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)
|
int dquot_claim_space_nodirty(struct inode *inode, qsize_t number)
|
||||||
{
|
{
|
||||||
|
struct dquot **dquots;
|
||||||
int cnt, index;
|
int cnt, index;
|
||||||
|
|
||||||
if (!dquot_active(inode)) {
|
if (!dquot_active(inode)) {
|
||||||
|
@ -1697,18 +1722,18 @@ int dquot_claim_space_nodirty(struct inode *inode, qsize_t number)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dquots = i_dquot(inode);
|
||||||
index = srcu_read_lock(&dquot_srcu);
|
index = srcu_read_lock(&dquot_srcu);
|
||||||
spin_lock(&dq_data_lock);
|
spin_lock(&dq_data_lock);
|
||||||
/* Claim reserved quotas to allocated quotas */
|
/* Claim reserved quotas to allocated quotas */
|
||||||
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
|
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
|
||||||
if (i_dquot(inode)[cnt])
|
if (dquots[cnt])
|
||||||
dquot_claim_reserved_space(i_dquot(inode)[cnt],
|
dquot_claim_reserved_space(dquots[cnt], number);
|
||||||
number);
|
|
||||||
}
|
}
|
||||||
/* Update inode bytes */
|
/* Update inode bytes */
|
||||||
inode_claim_rsv_space(inode, number);
|
inode_claim_rsv_space(inode, number);
|
||||||
spin_unlock(&dq_data_lock);
|
spin_unlock(&dq_data_lock);
|
||||||
mark_all_dquot_dirty(i_dquot(inode));
|
mark_all_dquot_dirty(dquots);
|
||||||
srcu_read_unlock(&dquot_srcu, index);
|
srcu_read_unlock(&dquot_srcu, index);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1719,6 +1744,7 @@ EXPORT_SYMBOL(dquot_claim_space_nodirty);
|
||||||
*/
|
*/
|
||||||
void dquot_reclaim_space_nodirty(struct inode *inode, qsize_t number)
|
void dquot_reclaim_space_nodirty(struct inode *inode, qsize_t number)
|
||||||
{
|
{
|
||||||
|
struct dquot **dquots;
|
||||||
int cnt, index;
|
int cnt, index;
|
||||||
|
|
||||||
if (!dquot_active(inode)) {
|
if (!dquot_active(inode)) {
|
||||||
|
@ -1726,18 +1752,18 @@ void dquot_reclaim_space_nodirty(struct inode *inode, qsize_t number)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dquots = i_dquot(inode);
|
||||||
index = srcu_read_lock(&dquot_srcu);
|
index = srcu_read_lock(&dquot_srcu);
|
||||||
spin_lock(&dq_data_lock);
|
spin_lock(&dq_data_lock);
|
||||||
/* Claim reserved quotas to allocated quotas */
|
/* Claim reserved quotas to allocated quotas */
|
||||||
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
|
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
|
||||||
if (i_dquot(inode)[cnt])
|
if (dquots[cnt])
|
||||||
dquot_reclaim_reserved_space(i_dquot(inode)[cnt],
|
dquot_reclaim_reserved_space(dquots[cnt], number);
|
||||||
number);
|
|
||||||
}
|
}
|
||||||
/* Update inode bytes */
|
/* Update inode bytes */
|
||||||
inode_reclaim_rsv_space(inode, number);
|
inode_reclaim_rsv_space(inode, number);
|
||||||
spin_unlock(&dq_data_lock);
|
spin_unlock(&dq_data_lock);
|
||||||
mark_all_dquot_dirty(i_dquot(inode));
|
mark_all_dquot_dirty(dquots);
|
||||||
srcu_read_unlock(&dquot_srcu, index);
|
srcu_read_unlock(&dquot_srcu, index);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1750,7 +1776,7 @@ void __dquot_free_space(struct inode *inode, qsize_t number, int flags)
|
||||||
{
|
{
|
||||||
unsigned int cnt;
|
unsigned int cnt;
|
||||||
struct dquot_warn warn[MAXQUOTAS];
|
struct dquot_warn warn[MAXQUOTAS];
|
||||||
struct dquot **dquots = i_dquot(inode);
|
struct dquot **dquots;
|
||||||
int reserve = flags & DQUOT_SPACE_RESERVE, index;
|
int reserve = flags & DQUOT_SPACE_RESERVE, index;
|
||||||
|
|
||||||
if (!dquot_active(inode)) {
|
if (!dquot_active(inode)) {
|
||||||
|
@ -1758,6 +1784,7 @@ void __dquot_free_space(struct inode *inode, qsize_t number, int flags)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dquots = i_dquot(inode);
|
||||||
index = srcu_read_lock(&dquot_srcu);
|
index = srcu_read_lock(&dquot_srcu);
|
||||||
spin_lock(&dq_data_lock);
|
spin_lock(&dq_data_lock);
|
||||||
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
|
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
|
||||||
|
@ -1793,12 +1820,13 @@ void dquot_free_inode(struct inode *inode)
|
||||||
{
|
{
|
||||||
unsigned int cnt;
|
unsigned int cnt;
|
||||||
struct dquot_warn warn[MAXQUOTAS];
|
struct dquot_warn warn[MAXQUOTAS];
|
||||||
struct dquot * const *dquots = i_dquot(inode);
|
struct dquot * const *dquots;
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
if (!dquot_active(inode))
|
if (!dquot_active(inode))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
dquots = i_dquot(inode);
|
||||||
index = srcu_read_lock(&dquot_srcu);
|
index = srcu_read_lock(&dquot_srcu);
|
||||||
spin_lock(&dq_data_lock);
|
spin_lock(&dq_data_lock);
|
||||||
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
|
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;
|
error = -EROFS;
|
||||||
goto out_fmt;
|
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;
|
error = -EINVAL;
|
||||||
goto out_fmt;
|
goto out_fmt;
|
||||||
}
|
}
|
||||||
|
@ -2614,55 +2643,73 @@ out:
|
||||||
EXPORT_SYMBOL(dquot_set_dqblk);
|
EXPORT_SYMBOL(dquot_set_dqblk);
|
||||||
|
|
||||||
/* Generic routine for getting common part of quota file information */
|
/* 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 mem_dqinfo *mi;
|
||||||
|
struct qc_type_state *tstate;
|
||||||
|
struct quota_info *dqopt = sb_dqopt(sb);
|
||||||
|
int type;
|
||||||
|
|
||||||
mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
|
mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
|
||||||
if (!sb_has_quota_active(sb, type)) {
|
memset(state, 0, sizeof(*state));
|
||||||
mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
|
for (type = 0; type < MAXQUOTAS; type++) {
|
||||||
return -ESRCH;
|
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);
|
mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(dquot_get_dqinfo);
|
EXPORT_SYMBOL(dquot_get_state);
|
||||||
|
|
||||||
/* Generic routine for setting common part of quota file information */
|
/* 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;
|
struct mem_dqinfo *mi;
|
||||||
int err = 0;
|
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);
|
mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
|
||||||
if (!sb_has_quota_active(sb, type)) {
|
if (!sb_has_quota_active(sb, type)) {
|
||||||
err = -ESRCH;
|
err = -ESRCH;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
mi = sb_dqopt(sb)->info + type;
|
mi = sb_dqopt(sb)->info + type;
|
||||||
if (ii->dqi_valid & IIF_FLAGS) {
|
if (ii->i_fieldmask & QC_FLAGS) {
|
||||||
if (ii->dqi_flags & ~DQF_SETINFO_MASK ||
|
if ((ii->i_flags & QCI_ROOT_SQUASH &&
|
||||||
(ii->dqi_flags & DQF_ROOT_SQUASH &&
|
|
||||||
mi->dqi_format->qf_fmt_id != QFMT_VFS_OLD)) {
|
mi->dqi_format->qf_fmt_id != QFMT_VFS_OLD)) {
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
spin_lock(&dq_data_lock);
|
spin_lock(&dq_data_lock);
|
||||||
if (ii->dqi_valid & IIF_BGRACE)
|
if (ii->i_fieldmask & QC_SPC_TIMER)
|
||||||
mi->dqi_bgrace = ii->dqi_bgrace;
|
mi->dqi_bgrace = ii->i_spc_timelimit;
|
||||||
if (ii->dqi_valid & IIF_IGRACE)
|
if (ii->i_fieldmask & QC_INO_TIMER)
|
||||||
mi->dqi_igrace = ii->dqi_igrace;
|
mi->dqi_igrace = ii->i_ino_timelimit;
|
||||||
if (ii->dqi_valid & IIF_FLAGS)
|
if (ii->i_fieldmask & QC_FLAGS) {
|
||||||
mi->dqi_flags = (mi->dqi_flags & ~DQF_SETINFO_MASK) |
|
if (ii->i_flags & QCI_ROOT_SQUASH)
|
||||||
(ii->dqi_flags & DQF_SETINFO_MASK);
|
mi->dqi_flags |= DQF_ROOT_SQUASH;
|
||||||
|
else
|
||||||
|
mi->dqi_flags &= ~DQF_ROOT_SQUASH;
|
||||||
|
}
|
||||||
spin_unlock(&dq_data_lock);
|
spin_unlock(&dq_data_lock);
|
||||||
mark_info_dirty(sb, type);
|
mark_info_dirty(sb, type);
|
||||||
/* Force write to disk */
|
/* Force write to disk */
|
||||||
|
@ -2677,7 +2724,7 @@ const struct quotactl_ops dquot_quotactl_ops = {
|
||||||
.quota_on = dquot_quota_on,
|
.quota_on = dquot_quota_on,
|
||||||
.quota_off = dquot_quota_off,
|
.quota_off = dquot_quota_off,
|
||||||
.quota_sync = dquot_quota_sync,
|
.quota_sync = dquot_quota_sync,
|
||||||
.get_info = dquot_get_dqinfo,
|
.get_state = dquot_get_state,
|
||||||
.set_info = dquot_set_dqinfo,
|
.set_info = dquot_set_dqinfo,
|
||||||
.get_dqblk = dquot_get_dqblk,
|
.get_dqblk = dquot_get_dqblk,
|
||||||
.set_dqblk = dquot_set_dqblk
|
.set_dqblk = dquot_set_dqblk
|
||||||
|
@ -2688,7 +2735,7 @@ const struct quotactl_ops dquot_quotactl_sysfile_ops = {
|
||||||
.quota_enable = dquot_quota_enable,
|
.quota_enable = dquot_quota_enable,
|
||||||
.quota_disable = dquot_quota_disable,
|
.quota_disable = dquot_quota_disable,
|
||||||
.quota_sync = dquot_quota_sync,
|
.quota_sync = dquot_quota_sync,
|
||||||
.get_info = dquot_get_dqinfo,
|
.get_state = dquot_get_state,
|
||||||
.set_info = dquot_set_dqinfo,
|
.set_info = dquot_set_dqinfo,
|
||||||
.get_dqblk = dquot_get_dqblk,
|
.get_dqblk = dquot_get_dqblk,
|
||||||
.set_dqblk = dquot_set_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)
|
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;
|
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;
|
return -ENOSYS;
|
||||||
ret = sb->s_qcop->get_info(sb, type, &info);
|
ret = sb->s_qcop->get_state(sb, &state);
|
||||||
if (!ret && copy_to_user(addr, &info, sizeof(info)))
|
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 -EFAULT;
|
||||||
return ret;
|
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)
|
static int quota_setinfo(struct super_block *sb, int type, void __user *addr)
|
||||||
{
|
{
|
||||||
struct if_dqinfo info;
|
struct if_dqinfo info;
|
||||||
|
struct qc_info qinfo;
|
||||||
|
|
||||||
if (copy_from_user(&info, addr, sizeof(info)))
|
if (copy_from_user(&info, addr, sizeof(info)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
if (!sb->s_qcop->set_info)
|
if (!sb->s_qcop->set_info)
|
||||||
return -ENOSYS;
|
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)
|
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);
|
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)
|
static int quota_getxstate(struct super_block *sb, void __user *addr)
|
||||||
{
|
{
|
||||||
struct fs_quota_stat fqs;
|
struct fs_quota_stat fqs;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!sb->s_qcop->get_xstate)
|
if (!sb->s_qcop->get_state)
|
||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
ret = sb->s_qcop->get_xstate(sb, &fqs);
|
ret = quota_getstate(sb, &fqs);
|
||||||
if (!ret && copy_to_user(addr, &fqs, sizeof(fqs)))
|
if (!ret && copy_to_user(addr, &fqs, sizeof(fqs)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
return ret;
|
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)
|
static int quota_getxstatev(struct super_block *sb, void __user *addr)
|
||||||
{
|
{
|
||||||
struct fs_quota_statv fqs;
|
struct fs_quota_statv fqs;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!sb->s_qcop->get_xstatev)
|
if (!sb->s_qcop->get_state)
|
||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
|
|
||||||
memset(&fqs, 0, sizeof(fqs));
|
memset(&fqs, 0, sizeof(fqs));
|
||||||
|
@ -284,7 +444,7 @@ static int quota_getxstatev(struct super_block *sb, void __user *addr)
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
ret = sb->s_qcop->get_xstatev(sb, &fqs);
|
ret = quota_getstatev(sb, &fqs);
|
||||||
if (!ret && copy_to_user(addr, &fqs, sizeof(fqs)))
|
if (!ret && copy_to_user(addr, &fqs, sizeof(fqs)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
return ret;
|
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;
|
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,
|
static int quota_setxquota(struct super_block *sb, int type, qid_t id,
|
||||||
void __user *addr)
|
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);
|
qid = make_kqid(current_user_ns(), type, id);
|
||||||
if (!qid_valid(qid))
|
if (!qid_valid(qid))
|
||||||
return -EINVAL;
|
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);
|
copy_from_xfs_dqblk(&qdq, &fdq);
|
||||||
return sb->s_qcop->set_dqblk(sb, qid, &qdq);
|
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)
|
struct dquot *dquot)
|
||||||
{
|
{
|
||||||
int tmp = QT_TREEOFF;
|
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);
|
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;
|
qinfo = info->dqi_priv;
|
||||||
if (version == 0) {
|
if (version == 0) {
|
||||||
/* limits are stored as unsigned 32-bit data */
|
/* 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;
|
info->dqi_max_ino_limit = 0xffffffff;
|
||||||
} else {
|
} else {
|
||||||
/* used space is stored as unsigned 64-bit value in bytes */
|
/*
|
||||||
info->dqi_max_spc_limit = 0xffffffffffffffffULL; /* 2^64-1 */
|
* Used space is stored as unsigned 64-bit value in bytes but
|
||||||
info->dqi_max_ino_limit = 0xffffffffffffffffULL;
|
* 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_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
|
||||||
info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace);
|
info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace);
|
||||||
|
|
|
@ -13,12 +13,14 @@
|
||||||
*/
|
*/
|
||||||
#define V2_INITQMAGICS {\
|
#define V2_INITQMAGICS {\
|
||||||
0xd9c01f11, /* USRQUOTA */\
|
0xd9c01f11, /* USRQUOTA */\
|
||||||
0xd9c01927 /* GRPQUOTA */\
|
0xd9c01927, /* GRPQUOTA */\
|
||||||
|
0xd9c03f14, /* PRJQUOTA */\
|
||||||
}
|
}
|
||||||
|
|
||||||
#define V2_INITQVERSIONS {\
|
#define V2_INITQVERSIONS {\
|
||||||
1, /* USRQUOTA */\
|
1, /* USRQUOTA */\
|
||||||
1 /* GRPQUOTA */\
|
1, /* GRPQUOTA */\
|
||||||
|
1, /* PRJQUOTA */\
|
||||||
}
|
}
|
||||||
|
|
||||||
/* First generic header */
|
/* First generic header */
|
||||||
|
|
|
@ -910,7 +910,6 @@ do { \
|
||||||
if (!(cond)) \
|
if (!(cond)) \
|
||||||
reiserfs_panic(NULL, "assertion failure", "(" #cond ") at " \
|
reiserfs_panic(NULL, "assertion failure", "(" #cond ") at " \
|
||||||
__FILE__ ":%i:%s: " format "\n", \
|
__FILE__ ":%i:%s: " format "\n", \
|
||||||
in_interrupt() ? -1 : task_pid_nr(current), \
|
|
||||||
__LINE__, __func__ , ##args); \
|
__LINE__, __func__ , ##args); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|
|
@ -805,7 +805,7 @@ static const struct quotactl_ops reiserfs_qctl_operations = {
|
||||||
.quota_on = reiserfs_quota_on,
|
.quota_on = reiserfs_quota_on,
|
||||||
.quota_off = dquot_quota_off,
|
.quota_off = dquot_quota_off,
|
||||||
.quota_sync = dquot_quota_sync,
|
.quota_sync = dquot_quota_sync,
|
||||||
.get_info = dquot_get_dqinfo,
|
.get_state = dquot_get_state,
|
||||||
.set_info = dquot_set_dqinfo,
|
.set_info = dquot_set_dqinfo,
|
||||||
.get_dqblk = dquot_get_dqblk,
|
.get_dqblk = dquot_get_dqblk,
|
||||||
.set_dqblk = dquot_set_dqblk,
|
.set_dqblk = dquot_set_dqblk,
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
|
|
||||||
#include "udfdecl.h"
|
#include "udfdecl.h"
|
||||||
|
|
||||||
#include <linux/buffer_head.h>
|
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
|
|
||||||
#include "udf_i.h"
|
#include "udf_i.h"
|
||||||
|
@ -63,15 +62,14 @@ static int __load_block_bitmap(struct super_block *sb,
|
||||||
block_group, nr_groups);
|
block_group, nr_groups);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bitmap->s_block_bitmap[block_group]) {
|
if (bitmap->s_block_bitmap[block_group])
|
||||||
return block_group;
|
return block_group;
|
||||||
} else {
|
|
||||||
retval = read_block_bitmap(sb, bitmap, block_group,
|
retval = read_block_bitmap(sb, bitmap, block_group, block_group);
|
||||||
block_group);
|
if (retval < 0)
|
||||||
if (retval < 0)
|
return retval;
|
||||||
return retval;
|
|
||||||
return block_group;
|
return block_group;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int load_block_bitmap(struct super_block *sb,
|
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 kernel_lb_addr eloc;
|
||||||
struct extent_position oepos, epos;
|
struct extent_position oepos, epos;
|
||||||
int8_t etype;
|
int8_t etype;
|
||||||
int i;
|
|
||||||
struct udf_inode_info *iinfo;
|
struct udf_inode_info *iinfo;
|
||||||
|
|
||||||
mutex_lock(&sbi->s_alloc_mutex);
|
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) {
|
if (epos.bh != oepos.bh) {
|
||||||
i = -1;
|
|
||||||
oepos.block = epos.block;
|
oepos.block = epos.block;
|
||||||
brelse(oepos.bh);
|
brelse(oepos.bh);
|
||||||
get_bh(epos.bh);
|
get_bh(epos.bh);
|
||||||
|
@ -762,7 +758,7 @@ inline int udf_prealloc_blocks(struct super_block *sb,
|
||||||
uint32_t block_count)
|
uint32_t block_count)
|
||||||
{
|
{
|
||||||
struct udf_part_map *map = &UDF_SB(sb)->s_partmaps[partition];
|
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)
|
if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP)
|
||||||
allocated = udf_bitmap_prealloc_blocks(sb,
|
allocated = udf_bitmap_prealloc_blocks(sb,
|
||||||
|
|
|
@ -30,7 +30,6 @@
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/buffer_head.h>
|
|
||||||
|
|
||||||
#include "udf_i.h"
|
#include "udf_i.h"
|
||||||
#include "udf_sb.h"
|
#include "udf_sb.h"
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
|
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <linux/buffer_head.h>
|
|
||||||
|
|
||||||
struct fileIdentDesc *udf_fileident_read(struct inode *dir, loff_t *nf_pos,
|
struct fileIdentDesc *udf_fileident_read(struct inode *dir, loff_t *nf_pos,
|
||||||
struct udf_fileident_bh *fibh,
|
struct udf_fileident_bh *fibh,
|
||||||
|
|
|
@ -33,7 +33,6 @@
|
||||||
#include <linux/capability.h>
|
#include <linux/capability.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/pagemap.h>
|
#include <linux/pagemap.h>
|
||||||
#include <linux/buffer_head.h>
|
|
||||||
#include <linux/uio.h>
|
#include <linux/uio.h>
|
||||||
|
|
||||||
#include "udf_i.h"
|
#include "udf_i.h"
|
||||||
|
|
|
@ -33,7 +33,6 @@
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/pagemap.h>
|
#include <linux/pagemap.h>
|
||||||
#include <linux/buffer_head.h>
|
|
||||||
#include <linux/writeback.h>
|
#include <linux/writeback.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/crc-itu-t.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));
|
udf_get_lb_pblock(inode->i_sb, &iinfo->i_location, 0));
|
||||||
if (!bh) {
|
if (!bh) {
|
||||||
udf_debug("getblk failure\n");
|
udf_debug("getblk failure\n");
|
||||||
return -ENOMEM;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
lock_buffer(bh);
|
lock_buffer(bh);
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
|
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <linux/buffer_head.h>
|
|
||||||
#include <linux/crc-itu-t.h>
|
#include <linux/crc-itu-t.h>
|
||||||
|
|
||||||
#include "udf_i.h"
|
#include "udf_i.h"
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/buffer_head.h>
|
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/crc-itu-t.h>
|
#include <linux/crc-itu-t.h>
|
||||||
#include <linux/exportfs.h>
|
#include <linux/exportfs.h>
|
||||||
|
@ -569,8 +568,8 @@ static int udf_add_nondir(struct dentry *dentry, struct inode *inode)
|
||||||
*(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
|
*(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
|
||||||
cpu_to_le32(iinfo->i_unique & 0x00000000FFFFFFFFUL);
|
cpu_to_le32(iinfo->i_unique & 0x00000000FFFFFFFFUL);
|
||||||
udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
|
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);
|
mark_inode_dirty(dir);
|
||||||
if (fibh.sbh != fibh.ebh)
|
if (fibh.sbh != fibh.ebh)
|
||||||
brelse(fibh.ebh);
|
brelse(fibh.ebh);
|
||||||
brelse(fibh.sbh);
|
brelse(fibh.sbh);
|
||||||
|
@ -683,6 +682,7 @@ static int udf_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
|
||||||
cfi.fileCharacteristics |= FID_FILE_CHAR_DIRECTORY;
|
cfi.fileCharacteristics |= FID_FILE_CHAR_DIRECTORY;
|
||||||
udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
|
udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
|
||||||
inc_nlink(dir);
|
inc_nlink(dir);
|
||||||
|
dir->i_ctime = dir->i_mtime = current_fs_time(dir->i_sb);
|
||||||
mark_inode_dirty(dir);
|
mark_inode_dirty(dir);
|
||||||
unlock_new_inode(inode);
|
unlock_new_inode(inode);
|
||||||
d_instantiate(dentry, inode);
|
d_instantiate(dentry, inode);
|
||||||
|
@ -1024,6 +1024,8 @@ static int udf_link(struct dentry *old_dentry, struct inode *dir,
|
||||||
inc_nlink(inode);
|
inc_nlink(inode);
|
||||||
inode->i_ctime = current_fs_time(inode->i_sb);
|
inode->i_ctime = current_fs_time(inode->i_sb);
|
||||||
mark_inode_dirty(inode);
|
mark_inode_dirty(inode);
|
||||||
|
dir->i_ctime = dir->i_mtime = current_fs_time(dir->i_sb);
|
||||||
|
mark_inode_dirty(dir);
|
||||||
ihold(inode);
|
ihold(inode);
|
||||||
d_instantiate(dentry, 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);
|
inode_dec_link_count(new_inode);
|
||||||
}
|
}
|
||||||
old_dir->i_ctime = old_dir->i_mtime = current_fs_time(old_dir->i_sb);
|
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(old_dir);
|
||||||
|
mark_inode_dirty(new_dir);
|
||||||
|
|
||||||
if (dir_fi) {
|
if (dir_fi) {
|
||||||
dir_fi->icb.extLocation = cpu_to_lelb(UDF_I(new_dir)->i_location);
|
dir_fi->icb.extLocation = cpu_to_lelb(UDF_I(new_dir)->i_location);
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
|
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <linux/buffer_head.h>
|
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
|
|
||||||
uint32_t udf_get_pblock(struct super_block *sb, uint32_t block,
|
uint32_t udf_get_pblock(struct super_block *sb, uint32_t block,
|
||||||
|
|
|
@ -48,7 +48,6 @@
|
||||||
#include <linux/stat.h>
|
#include <linux/stat.h>
|
||||||
#include <linux/cdrom.h>
|
#include <linux/cdrom.h>
|
||||||
#include <linux/nls.h>
|
#include <linux/nls.h>
|
||||||
#include <linux/buffer_head.h>
|
|
||||||
#include <linux/vfs.h>
|
#include <linux/vfs.h>
|
||||||
#include <linux/vmalloc.h>
|
#include <linux/vmalloc.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/stat.h>
|
#include <linux/stat.h>
|
||||||
#include <linux/pagemap.h>
|
#include <linux/pagemap.h>
|
||||||
#include <linux/buffer_head.h>
|
|
||||||
#include "udf_i.h"
|
#include "udf_i.h"
|
||||||
|
|
||||||
static int udf_pc_to_char(struct super_block *sb, unsigned char *from,
|
static int udf_pc_to_char(struct super_block *sb, unsigned char *from,
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
#include "udfdecl.h"
|
#include "udfdecl.h"
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/buffer_head.h>
|
|
||||||
|
|
||||||
#include "udf_i.h"
|
#include "udf_i.h"
|
||||||
#include "udf_sb.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 *);
|
uint, struct qc_dqblk *);
|
||||||
extern int xfs_qm_scall_setqlim(struct xfs_mount *, xfs_dqid_t, uint,
|
extern int xfs_qm_scall_setqlim(struct xfs_mount *, xfs_dqid_t, uint,
|
||||||
struct qc_dqblk *);
|
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_quotaon(struct xfs_mount *, uint);
|
||||||
extern int xfs_qm_scall_quotaoff(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(xfs_mount_t *, xfs_qoff_logitem_t **, uint);
|
||||||
STATIC int xfs_qm_log_quotaoff_end(xfs_mount_t *, xfs_qoff_logitem_t *,
|
STATIC int xfs_qm_log_quotaoff_end(xfs_mount_t *, xfs_qoff_logitem_t *,
|
||||||
uint);
|
uint);
|
||||||
STATIC uint xfs_qm_export_flags(uint);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Turn off quota accounting and/or enforcement for all udquots and/or
|
* Turn off quota accounting and/or enforcement for all udquots and/or
|
||||||
|
@ -389,159 +388,6 @@ xfs_qm_scall_quotaon(
|
||||||
return 0;
|
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 \
|
#define XFS_QC_MASK \
|
||||||
(QC_LIMIT_MASK | QC_TIMER_MASK | QC_WARNS_MASK)
|
(QC_LIMIT_MASK | QC_TIMER_MASK | QC_WARNS_MASK)
|
||||||
|
|
||||||
|
@ -873,28 +719,6 @@ out_put:
|
||||||
return error;
|
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
|
STATIC int
|
||||||
xfs_dqrele_inode(
|
xfs_dqrele_inode(
|
||||||
|
|
|
@ -23,10 +23,81 @@
|
||||||
#include "xfs_inode.h"
|
#include "xfs_inode.h"
|
||||||
#include "xfs_quota.h"
|
#include "xfs_quota.h"
|
||||||
#include "xfs_trans.h"
|
#include "xfs_trans.h"
|
||||||
|
#include "xfs_trace.h"
|
||||||
|
#include "xfs_icache.h"
|
||||||
#include "xfs_qm.h"
|
#include "xfs_qm.h"
|
||||||
#include <linux/quota.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
|
STATIC int
|
||||||
xfs_quota_type(int type)
|
xfs_quota_type(int type)
|
||||||
{
|
{
|
||||||
|
@ -40,28 +111,40 @@ xfs_quota_type(int type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC int
|
#define XFS_QC_SETINFO_MASK (QC_TIMER_MASK | QC_WARNS_MASK)
|
||||||
xfs_fs_get_xstate(
|
|
||||||
struct super_block *sb,
|
|
||||||
struct fs_quota_stat *fqs)
|
|
||||||
{
|
|
||||||
struct xfs_mount *mp = XFS_M(sb);
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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))
|
if (!XFS_IS_QUOTA_RUNNING(mp))
|
||||||
return -ENOSYS;
|
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
|
newlim.d_fieldmask = info->i_fieldmask;
|
||||||
xfs_fs_get_xstatev(
|
newlim.d_spc_timer = info->i_spc_timelimit;
|
||||||
struct super_block *sb,
|
newlim.d_ino_timer = info->i_ino_timelimit;
|
||||||
struct fs_quota_statv *fqs)
|
newlim.d_rt_spc_timer = info->i_rt_spc_timelimit;
|
||||||
{
|
newlim.d_ino_warns = info->i_ino_warnlimit;
|
||||||
struct xfs_mount *mp = XFS_M(sb);
|
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 xfs_qm_scall_setqlim(mp, 0, xfs_quota_type(type), &newlim);
|
||||||
return -ENOSYS;
|
|
||||||
return xfs_qm_scall_getqstatv(mp, fqs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int
|
static unsigned int
|
||||||
|
@ -178,8 +261,8 @@ xfs_fs_set_dqblk(
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct quotactl_ops xfs_quotactl_operations = {
|
const struct quotactl_ops xfs_quotactl_operations = {
|
||||||
.get_xstatev = xfs_fs_get_xstatev,
|
.get_state = xfs_fs_get_quota_state,
|
||||||
.get_xstate = xfs_fs_get_xstate,
|
.set_info = xfs_fs_set_info,
|
||||||
.quota_enable = xfs_quota_enable,
|
.quota_enable = xfs_quota_enable,
|
||||||
.quota_disable = xfs_quota_disable,
|
.quota_disable = xfs_quota_disable,
|
||||||
.rm_xquota = xfs_fs_rm_xquota,
|
.rm_xquota = xfs_fs_rm_xquota,
|
||||||
|
|
|
@ -50,6 +50,7 @@
|
||||||
|
|
||||||
#undef USRQUOTA
|
#undef USRQUOTA
|
||||||
#undef GRPQUOTA
|
#undef GRPQUOTA
|
||||||
|
#undef PRJQUOTA
|
||||||
enum quota_type {
|
enum quota_type {
|
||||||
USRQUOTA = 0, /* element used for user quotas */
|
USRQUOTA = 0, /* element used for user quotas */
|
||||||
GRPQUOTA = 1, /* element used for group 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
|
/* get reserved quota for delayed alloc, value returned is managed by
|
||||||
* quota code only */
|
* quota code only */
|
||||||
qsize_t *(*get_reserved_space) (struct inode *);
|
qsize_t *(*get_reserved_space) (struct inode *);
|
||||||
|
int (*get_projid) (struct inode *, kprojid_t *);/* Get project ID */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct path;
|
struct path;
|
||||||
|
@ -344,7 +346,10 @@ struct qc_dqblk {
|
||||||
int d_rt_spc_warns; /* # warnings issued wrt RT space */
|
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_SOFT (1<<0)
|
||||||
#define QC_INO_HARD (1<<1)
|
#define QC_INO_HARD (1<<1)
|
||||||
#define QC_SPC_SOFT (1<<2)
|
#define QC_SPC_SOFT (1<<2)
|
||||||
|
@ -365,6 +370,51 @@ struct qc_dqblk {
|
||||||
#define QC_INO_COUNT (1<<13)
|
#define QC_INO_COUNT (1<<13)
|
||||||
#define QC_RT_SPACE (1<<14)
|
#define QC_RT_SPACE (1<<14)
|
||||||
#define QC_ACCT_MASK (QC_SPACE | QC_INO_COUNT | QC_RT_SPACE)
|
#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 */
|
/* Operations handling requests from userspace */
|
||||||
struct quotactl_ops {
|
struct quotactl_ops {
|
||||||
|
@ -373,12 +423,10 @@ struct quotactl_ops {
|
||||||
int (*quota_enable)(struct super_block *, unsigned int);
|
int (*quota_enable)(struct super_block *, unsigned int);
|
||||||
int (*quota_disable)(struct super_block *, unsigned int);
|
int (*quota_disable)(struct super_block *, unsigned int);
|
||||||
int (*quota_sync)(struct super_block *, 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 qc_info *);
|
||||||
int (*set_info)(struct super_block *, int, struct if_dqinfo *);
|
|
||||||
int (*get_dqblk)(struct super_block *, struct kqid, struct qc_dqblk *);
|
int (*get_dqblk)(struct super_block *, struct kqid, struct qc_dqblk *);
|
||||||
int (*set_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_state)(struct super_block *, struct qc_state *);
|
||||||
int (*get_xstatev)(struct super_block *, struct fs_quota_statv *);
|
|
||||||
int (*rm_xquota)(struct super_block *, unsigned int);
|
int (*rm_xquota)(struct super_block *, unsigned int);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -389,7 +437,19 @@ struct quota_format_type {
|
||||||
struct quota_format_type *qf_next;
|
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 {
|
enum {
|
||||||
_DQUOT_USAGE_ENABLED = 0, /* Track disk usage for users */
|
_DQUOT_USAGE_ENABLED = 0, /* Track disk usage for users */
|
||||||
_DQUOT_LIMITS_ENABLED, /* Enforce quota limits for users */
|
_DQUOT_LIMITS_ENABLED, /* Enforce quota limits for users */
|
||||||
|
@ -398,9 +458,9 @@ enum {
|
||||||
* memory to turn them on */
|
* memory to turn them on */
|
||||||
_DQUOT_STATE_FLAGS
|
_DQUOT_STATE_FLAGS
|
||||||
};
|
};
|
||||||
#define DQUOT_USAGE_ENABLED (1 << _DQUOT_USAGE_ENABLED)
|
#define DQUOT_USAGE_ENABLED (1 << _DQUOT_USAGE_ENABLED * MAXQUOTAS)
|
||||||
#define DQUOT_LIMITS_ENABLED (1 << _DQUOT_LIMITS_ENABLED)
|
#define DQUOT_LIMITS_ENABLED (1 << _DQUOT_LIMITS_ENABLED * MAXQUOTAS)
|
||||||
#define DQUOT_SUSPENDED (1 << _DQUOT_SUSPENDED)
|
#define DQUOT_SUSPENDED (1 << _DQUOT_SUSPENDED * MAXQUOTAS)
|
||||||
#define DQUOT_STATE_FLAGS (DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED | \
|
#define DQUOT_STATE_FLAGS (DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED | \
|
||||||
DQUOT_SUSPENDED)
|
DQUOT_SUSPENDED)
|
||||||
/* Other quota flags */
|
/* Other quota flags */
|
||||||
|
@ -414,15 +474,21 @@ enum {
|
||||||
*/
|
*/
|
||||||
#define DQUOT_NEGATIVE_USAGE (1 << (DQUOT_STATE_LAST + 1))
|
#define DQUOT_NEGATIVE_USAGE (1 << (DQUOT_STATE_LAST + 1))
|
||||||
/* Allow negative quota usage */
|
/* Allow negative quota usage */
|
||||||
|
|
||||||
static inline unsigned int dquot_state_flag(unsigned int flags, int type)
|
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)
|
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
|
#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_quota_off(struct super_block *sb, int type);
|
||||||
int dquot_writeback_dquots(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_quota_sync(struct super_block *sb, int type);
|
||||||
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);
|
||||||
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);
|
||||||
int dquot_get_dqblk(struct super_block *sb, struct kqid id,
|
int dquot_get_dqblk(struct super_block *sb, struct kqid id,
|
||||||
struct qc_dqblk *di);
|
struct qc_dqblk *di);
|
||||||
int dquot_set_dqblk(struct super_block *sb, struct kqid id,
|
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)
|
static inline unsigned sb_any_quota_suspended(struct super_block *sb)
|
||||||
{
|
{
|
||||||
unsigned type, tmsk = 0;
|
return dquot_state_types(sb_dqopt(sb)->flags, DQUOT_SUSPENDED);
|
||||||
for (type = 0; type < MAXQUOTAS; type++)
|
|
||||||
tmsk |= sb_has_quota_suspended(sb, type) << type;
|
|
||||||
return tmsk;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Does kernel know about any quota information for given sb + type? */
|
/* 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)
|
static inline unsigned sb_any_quota_loaded(struct super_block *sb)
|
||||||
{
|
{
|
||||||
unsigned type, tmsk = 0;
|
return dquot_state_types(sb_dqopt(sb)->flags, DQUOT_USAGE_ENABLED);
|
||||||
for (type = 0; type < MAXQUOTAS; type++)
|
|
||||||
tmsk |= sb_has_quota_loaded(sb, type) << type;
|
|
||||||
return tmsk;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool sb_has_quota_active(struct super_block *sb, int type)
|
static inline bool sb_has_quota_active(struct super_block *sb, int type)
|
||||||
|
|
|
@ -36,11 +36,12 @@
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/types.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 USRQUOTA 0 /* element used for user quotas */
|
||||||
#define GRPQUOTA 1 /* element used for group 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.
|
* Definitions for the default names of the quotas files.
|
||||||
|
@ -48,6 +49,7 @@
|
||||||
#define INITQFNAMES { \
|
#define INITQFNAMES { \
|
||||||
"user", /* USRQUOTA */ \
|
"user", /* USRQUOTA */ \
|
||||||
"group", /* GRPQUOTA */ \
|
"group", /* GRPQUOTA */ \
|
||||||
|
"project", /* PRJQUOTA */ \
|
||||||
"undefined", \
|
"undefined", \
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче