Commit 92ef9ce3 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs

Pull quota and UDF fix from Jan Kara:
 "A fix for UDF to properly free preallocated blocks and a fix for quota
  so that Q_GETQUOTA quotactl reports correct numbers for XFS filesystem
  (and similarly Q_XGETQUOTA quotactl works properly for other
  filesystems)"

* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs:
  quota: Switch ->get_dqblk() and ->set_dqblk() to use bytes as space units
  udf: Release preallocation on last writeable close
parents 1f59fe76 14bf61ff
...@@ -667,7 +667,7 @@ static void do_qc(struct gfs2_quota_data *qd, s64 change) ...@@ -667,7 +667,7 @@ static void do_qc(struct gfs2_quota_data *qd, s64 change)
static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc, static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc,
s64 change, struct gfs2_quota_data *qd, s64 change, struct gfs2_quota_data *qd,
struct fs_disk_quota *fdq) struct qc_dqblk *fdq)
{ {
struct inode *inode = &ip->i_inode; struct inode *inode = &ip->i_inode;
struct gfs2_sbd *sdp = GFS2_SB(inode); struct gfs2_sbd *sdp = GFS2_SB(inode);
...@@ -697,16 +697,16 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc, ...@@ -697,16 +697,16 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc,
be64_add_cpu(&q.qu_value, change); be64_add_cpu(&q.qu_value, change);
qd->qd_qb.qb_value = q.qu_value; qd->qd_qb.qb_value = q.qu_value;
if (fdq) { if (fdq) {
if (fdq->d_fieldmask & FS_DQ_BSOFT) { if (fdq->d_fieldmask & QC_SPC_SOFT) {
q.qu_warn = cpu_to_be64(fdq->d_blk_softlimit >> sdp->sd_fsb2bb_shift); q.qu_warn = cpu_to_be64(fdq->d_spc_softlimit >> sdp->sd_sb.sb_bsize_shift);
qd->qd_qb.qb_warn = q.qu_warn; qd->qd_qb.qb_warn = q.qu_warn;
} }
if (fdq->d_fieldmask & FS_DQ_BHARD) { if (fdq->d_fieldmask & QC_SPC_HARD) {
q.qu_limit = cpu_to_be64(fdq->d_blk_hardlimit >> sdp->sd_fsb2bb_shift); q.qu_limit = cpu_to_be64(fdq->d_spc_hardlimit >> sdp->sd_sb.sb_bsize_shift);
qd->qd_qb.qb_limit = q.qu_limit; qd->qd_qb.qb_limit = q.qu_limit;
} }
if (fdq->d_fieldmask & FS_DQ_BCOUNT) { if (fdq->d_fieldmask & QC_SPACE) {
q.qu_value = cpu_to_be64(fdq->d_bcount >> sdp->sd_fsb2bb_shift); q.qu_value = cpu_to_be64(fdq->d_space >> sdp->sd_sb.sb_bsize_shift);
qd->qd_qb.qb_value = q.qu_value; qd->qd_qb.qb_value = q.qu_value;
} }
} }
...@@ -1497,7 +1497,7 @@ static int gfs2_quota_get_xstate(struct super_block *sb, ...@@ -1497,7 +1497,7 @@ static int gfs2_quota_get_xstate(struct super_block *sb,
} }
static int gfs2_get_dqblk(struct super_block *sb, struct kqid qid, static int gfs2_get_dqblk(struct super_block *sb, struct kqid qid,
struct fs_disk_quota *fdq) struct qc_dqblk *fdq)
{ {
struct gfs2_sbd *sdp = sb->s_fs_info; struct gfs2_sbd *sdp = sb->s_fs_info;
struct gfs2_quota_lvb *qlvb; struct gfs2_quota_lvb *qlvb;
...@@ -1505,7 +1505,7 @@ static int gfs2_get_dqblk(struct super_block *sb, struct kqid qid, ...@@ -1505,7 +1505,7 @@ static int gfs2_get_dqblk(struct super_block *sb, struct kqid qid,
struct gfs2_holder q_gh; struct gfs2_holder q_gh;
int error; int error;
memset(fdq, 0, sizeof(struct fs_disk_quota)); memset(fdq, 0, sizeof(*fdq));
if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF) if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF)
return -ESRCH; /* Crazy XFS error code */ return -ESRCH; /* Crazy XFS error code */
...@@ -1522,12 +1522,9 @@ static int gfs2_get_dqblk(struct super_block *sb, struct kqid qid, ...@@ -1522,12 +1522,9 @@ static int gfs2_get_dqblk(struct super_block *sb, struct kqid qid,
goto out; goto out;
qlvb = (struct gfs2_quota_lvb *)qd->qd_gl->gl_lksb.sb_lvbptr; qlvb = (struct gfs2_quota_lvb *)qd->qd_gl->gl_lksb.sb_lvbptr;
fdq->d_version = FS_DQUOT_VERSION; fdq->d_spc_hardlimit = be64_to_cpu(qlvb->qb_limit) << sdp->sd_sb.sb_bsize_shift;
fdq->d_flags = (qid.type == USRQUOTA) ? FS_USER_QUOTA : FS_GROUP_QUOTA; fdq->d_spc_softlimit = be64_to_cpu(qlvb->qb_warn) << sdp->sd_sb.sb_bsize_shift;
fdq->d_id = from_kqid_munged(current_user_ns(), qid); fdq->d_space = be64_to_cpu(qlvb->qb_value) << sdp->sd_sb.sb_bsize_shift;
fdq->d_blk_hardlimit = be64_to_cpu(qlvb->qb_limit) << sdp->sd_fsb2bb_shift;
fdq->d_blk_softlimit = be64_to_cpu(qlvb->qb_warn) << sdp->sd_fsb2bb_shift;
fdq->d_bcount = be64_to_cpu(qlvb->qb_value) << sdp->sd_fsb2bb_shift;
gfs2_glock_dq_uninit(&q_gh); gfs2_glock_dq_uninit(&q_gh);
out: out:
...@@ -1536,10 +1533,10 @@ static int gfs2_get_dqblk(struct super_block *sb, struct kqid qid, ...@@ -1536,10 +1533,10 @@ static int gfs2_get_dqblk(struct super_block *sb, struct kqid qid,
} }
/* GFS2 only supports a subset of the XFS fields */ /* GFS2 only supports a subset of the XFS fields */
#define GFS2_FIELDMASK (FS_DQ_BSOFT|FS_DQ_BHARD|FS_DQ_BCOUNT) #define GFS2_FIELDMASK (QC_SPC_SOFT|QC_SPC_HARD|QC_SPACE)
static int gfs2_set_dqblk(struct super_block *sb, struct kqid qid, static int gfs2_set_dqblk(struct super_block *sb, struct kqid qid,
struct fs_disk_quota *fdq) struct qc_dqblk *fdq)
{ {
struct gfs2_sbd *sdp = sb->s_fs_info; struct gfs2_sbd *sdp = sb->s_fs_info;
struct gfs2_inode *ip = GFS2_I(sdp->sd_quota_inode); struct gfs2_inode *ip = GFS2_I(sdp->sd_quota_inode);
...@@ -1583,17 +1580,17 @@ static int gfs2_set_dqblk(struct super_block *sb, struct kqid qid, ...@@ -1583,17 +1580,17 @@ static int gfs2_set_dqblk(struct super_block *sb, struct kqid qid,
goto out_i; goto out_i;
/* If nothing has changed, this is a no-op */ /* If nothing has changed, this is a no-op */
if ((fdq->d_fieldmask & FS_DQ_BSOFT) && if ((fdq->d_fieldmask & QC_SPC_SOFT) &&
((fdq->d_blk_softlimit >> sdp->sd_fsb2bb_shift) == be64_to_cpu(qd->qd_qb.qb_warn))) ((fdq->d_spc_softlimit >> sdp->sd_sb.sb_bsize_shift) == be64_to_cpu(qd->qd_qb.qb_warn)))
fdq->d_fieldmask ^= FS_DQ_BSOFT; fdq->d_fieldmask ^= QC_SPC_SOFT;
if ((fdq->d_fieldmask & FS_DQ_BHARD) && if ((fdq->d_fieldmask & QC_SPC_HARD) &&
((fdq->d_blk_hardlimit >> sdp->sd_fsb2bb_shift) == be64_to_cpu(qd->qd_qb.qb_limit))) ((fdq->d_spc_hardlimit >> sdp->sd_sb.sb_bsize_shift) == be64_to_cpu(qd->qd_qb.qb_limit)))
fdq->d_fieldmask ^= FS_DQ_BHARD; fdq->d_fieldmask ^= QC_SPC_HARD;
if ((fdq->d_fieldmask & FS_DQ_BCOUNT) && if ((fdq->d_fieldmask & QC_SPACE) &&
((fdq->d_bcount >> sdp->sd_fsb2bb_shift) == be64_to_cpu(qd->qd_qb.qb_value))) ((fdq->d_space >> sdp->sd_sb.sb_bsize_shift) == be64_to_cpu(qd->qd_qb.qb_value)))
fdq->d_fieldmask ^= FS_DQ_BCOUNT; fdq->d_fieldmask ^= QC_SPACE;
if (fdq->d_fieldmask == 0) if (fdq->d_fieldmask == 0)
goto out_i; goto out_i;
......
...@@ -2396,30 +2396,25 @@ static inline qsize_t stoqb(qsize_t space) ...@@ -2396,30 +2396,25 @@ static inline qsize_t stoqb(qsize_t space)
} }
/* Generic routine for getting common part of quota structure */ /* Generic routine for getting common part of quota structure */
static void do_get_dqblk(struct dquot *dquot, struct fs_disk_quota *di) static void do_get_dqblk(struct dquot *dquot, struct qc_dqblk *di)
{ {
struct mem_dqblk *dm = &dquot->dq_dqb; struct mem_dqblk *dm = &dquot->dq_dqb;
memset(di, 0, sizeof(*di)); memset(di, 0, sizeof(*di));
di->d_version = FS_DQUOT_VERSION;
di->d_flags = dquot->dq_id.type == USRQUOTA ?
FS_USER_QUOTA : FS_GROUP_QUOTA;
di->d_id = from_kqid_munged(current_user_ns(), dquot->dq_id);
spin_lock(&dq_data_lock); spin_lock(&dq_data_lock);
di->d_blk_hardlimit = stoqb(dm->dqb_bhardlimit); di->d_spc_hardlimit = dm->dqb_bhardlimit;
di->d_blk_softlimit = stoqb(dm->dqb_bsoftlimit); di->d_spc_softlimit = dm->dqb_bsoftlimit;
di->d_ino_hardlimit = dm->dqb_ihardlimit; di->d_ino_hardlimit = dm->dqb_ihardlimit;
di->d_ino_softlimit = dm->dqb_isoftlimit; di->d_ino_softlimit = dm->dqb_isoftlimit;
di->d_bcount = dm->dqb_curspace + dm->dqb_rsvspace; di->d_space = dm->dqb_curspace + dm->dqb_rsvspace;
di->d_icount = dm->dqb_curinodes; di->d_ino_count = dm->dqb_curinodes;
di->d_btimer = dm->dqb_btime; di->d_spc_timer = dm->dqb_btime;
di->d_itimer = dm->dqb_itime; di->d_ino_timer = dm->dqb_itime;
spin_unlock(&dq_data_lock); spin_unlock(&dq_data_lock);
} }
int dquot_get_dqblk(struct super_block *sb, struct kqid qid, int dquot_get_dqblk(struct super_block *sb, struct kqid qid,
struct fs_disk_quota *di) struct qc_dqblk *di)
{ {
struct dquot *dquot; struct dquot *dquot;
...@@ -2433,70 +2428,70 @@ int dquot_get_dqblk(struct super_block *sb, struct kqid qid, ...@@ -2433,70 +2428,70 @@ int dquot_get_dqblk(struct super_block *sb, struct kqid qid,
} }
EXPORT_SYMBOL(dquot_get_dqblk); EXPORT_SYMBOL(dquot_get_dqblk);
#define VFS_FS_DQ_MASK \ #define VFS_QC_MASK \
(FS_DQ_BCOUNT | FS_DQ_BSOFT | FS_DQ_BHARD | \ (QC_SPACE | QC_SPC_SOFT | QC_SPC_HARD | \
FS_DQ_ICOUNT | FS_DQ_ISOFT | FS_DQ_IHARD | \ QC_INO_COUNT | QC_INO_SOFT | QC_INO_HARD | \
FS_DQ_BTIMER | FS_DQ_ITIMER) QC_SPC_TIMER | QC_INO_TIMER)
/* Generic routine for setting common part of quota structure */ /* Generic routine for setting common part of quota structure */
static int do_set_dqblk(struct dquot *dquot, struct fs_disk_quota *di) static int do_set_dqblk(struct dquot *dquot, struct qc_dqblk *di)
{ {
struct mem_dqblk *dm = &dquot->dq_dqb; struct mem_dqblk *dm = &dquot->dq_dqb;
int check_blim = 0, check_ilim = 0; int check_blim = 0, check_ilim = 0;
struct mem_dqinfo *dqi = &sb_dqopt(dquot->dq_sb)->info[dquot->dq_id.type]; struct mem_dqinfo *dqi = &sb_dqopt(dquot->dq_sb)->info[dquot->dq_id.type];
if (di->d_fieldmask & ~VFS_FS_DQ_MASK) if (di->d_fieldmask & ~VFS_QC_MASK)
return -EINVAL; return -EINVAL;
if (((di->d_fieldmask & FS_DQ_BSOFT) && if (((di->d_fieldmask & QC_SPC_SOFT) &&
(di->d_blk_softlimit > dqi->dqi_maxblimit)) || stoqb(di->d_spc_softlimit) > dqi->dqi_maxblimit) ||
((di->d_fieldmask & FS_DQ_BHARD) && ((di->d_fieldmask & QC_SPC_HARD) &&
(di->d_blk_hardlimit > dqi->dqi_maxblimit)) || stoqb(di->d_spc_hardlimit) > dqi->dqi_maxblimit) ||
((di->d_fieldmask & FS_DQ_ISOFT) && ((di->d_fieldmask & QC_INO_SOFT) &&
(di->d_ino_softlimit > dqi->dqi_maxilimit)) || (di->d_ino_softlimit > dqi->dqi_maxilimit)) ||
((di->d_fieldmask & FS_DQ_IHARD) && ((di->d_fieldmask & QC_INO_HARD) &&
(di->d_ino_hardlimit > dqi->dqi_maxilimit))) (di->d_ino_hardlimit > dqi->dqi_maxilimit)))
return -ERANGE; return -ERANGE;
spin_lock(&dq_data_lock); spin_lock(&dq_data_lock);
if (di->d_fieldmask & FS_DQ_BCOUNT) { if (di->d_fieldmask & QC_SPACE) {
dm->dqb_curspace = di->d_bcount - dm->dqb_rsvspace; dm->dqb_curspace = di->d_space - dm->dqb_rsvspace;
check_blim = 1; check_blim = 1;
set_bit(DQ_LASTSET_B + QIF_SPACE_B, &dquot->dq_flags); set_bit(DQ_LASTSET_B + QIF_SPACE_B, &dquot->dq_flags);
} }
if (di->d_fieldmask & FS_DQ_BSOFT) if (di->d_fieldmask & QC_SPC_SOFT)
dm->dqb_bsoftlimit = qbtos(di->d_blk_softlimit); dm->dqb_bsoftlimit = di->d_spc_softlimit;
if (di->d_fieldmask & FS_DQ_BHARD) if (di->d_fieldmask & QC_SPC_HARD)
dm->dqb_bhardlimit = qbtos(di->d_blk_hardlimit); dm->dqb_bhardlimit = di->d_spc_hardlimit;
if (di->d_fieldmask & (FS_DQ_BSOFT | FS_DQ_BHARD)) { if (di->d_fieldmask & (QC_SPC_SOFT | QC_SPC_HARD)) {
check_blim = 1; check_blim = 1;
set_bit(DQ_LASTSET_B + QIF_BLIMITS_B, &dquot->dq_flags); set_bit(DQ_LASTSET_B + QIF_BLIMITS_B, &dquot->dq_flags);
} }
if (di->d_fieldmask & FS_DQ_ICOUNT) { if (di->d_fieldmask & QC_INO_COUNT) {
dm->dqb_curinodes = di->d_icount; dm->dqb_curinodes = di->d_ino_count;
check_ilim = 1; check_ilim = 1;
set_bit(DQ_LASTSET_B + QIF_INODES_B, &dquot->dq_flags); set_bit(DQ_LASTSET_B + QIF_INODES_B, &dquot->dq_flags);
} }
if (di->d_fieldmask & FS_DQ_ISOFT) if (di->d_fieldmask & QC_INO_SOFT)
dm->dqb_isoftlimit = di->d_ino_softlimit; dm->dqb_isoftlimit = di->d_ino_softlimit;
if (di->d_fieldmask & FS_DQ_IHARD) if (di->d_fieldmask & QC_INO_HARD)
dm->dqb_ihardlimit = di->d_ino_hardlimit; dm->dqb_ihardlimit = di->d_ino_hardlimit;
if (di->d_fieldmask & (FS_DQ_ISOFT | FS_DQ_IHARD)) { if (di->d_fieldmask & (QC_INO_SOFT | QC_INO_HARD)) {
check_ilim = 1; check_ilim = 1;
set_bit(DQ_LASTSET_B + QIF_ILIMITS_B, &dquot->dq_flags); set_bit(DQ_LASTSET_B + QIF_ILIMITS_B, &dquot->dq_flags);
} }
if (di->d_fieldmask & FS_DQ_BTIMER) { if (di->d_fieldmask & QC_SPC_TIMER) {
dm->dqb_btime = di->d_btimer; dm->dqb_btime = di->d_spc_timer;
check_blim = 1; check_blim = 1;
set_bit(DQ_LASTSET_B + QIF_BTIME_B, &dquot->dq_flags); set_bit(DQ_LASTSET_B + QIF_BTIME_B, &dquot->dq_flags);
} }
if (di->d_fieldmask & FS_DQ_ITIMER) { if (di->d_fieldmask & QC_INO_TIMER) {
dm->dqb_itime = di->d_itimer; dm->dqb_itime = di->d_ino_timer;
check_ilim = 1; check_ilim = 1;
set_bit(DQ_LASTSET_B + QIF_ITIME_B, &dquot->dq_flags); set_bit(DQ_LASTSET_B + QIF_ITIME_B, &dquot->dq_flags);
} }
...@@ -2506,7 +2501,7 @@ static int do_set_dqblk(struct dquot *dquot, struct fs_disk_quota *di) ...@@ -2506,7 +2501,7 @@ static int do_set_dqblk(struct dquot *dquot, struct fs_disk_quota *di)
dm->dqb_curspace < dm->dqb_bsoftlimit) { dm->dqb_curspace < dm->dqb_bsoftlimit) {
dm->dqb_btime = 0; dm->dqb_btime = 0;
clear_bit(DQ_BLKS_B, &dquot->dq_flags); clear_bit(DQ_BLKS_B, &dquot->dq_flags);
} else if (!(di->d_fieldmask & FS_DQ_BTIMER)) } else if (!(di->d_fieldmask & QC_SPC_TIMER))
/* Set grace only if user hasn't provided his own... */ /* Set grace only if user hasn't provided his own... */
dm->dqb_btime = get_seconds() + dqi->dqi_bgrace; dm->dqb_btime = get_seconds() + dqi->dqi_bgrace;
} }
...@@ -2515,7 +2510,7 @@ static int do_set_dqblk(struct dquot *dquot, struct fs_disk_quota *di) ...@@ -2515,7 +2510,7 @@ static int do_set_dqblk(struct dquot *dquot, struct fs_disk_quota *di)
dm->dqb_curinodes < dm->dqb_isoftlimit) { dm->dqb_curinodes < dm->dqb_isoftlimit) {
dm->dqb_itime = 0; dm->dqb_itime = 0;
clear_bit(DQ_INODES_B, &dquot->dq_flags); clear_bit(DQ_INODES_B, &dquot->dq_flags);
} else if (!(di->d_fieldmask & FS_DQ_ITIMER)) } else if (!(di->d_fieldmask & QC_INO_TIMER))
/* Set grace only if user hasn't provided his own... */ /* Set grace only if user hasn't provided his own... */
dm->dqb_itime = get_seconds() + dqi->dqi_igrace; dm->dqb_itime = get_seconds() + dqi->dqi_igrace;
} }
...@@ -2531,7 +2526,7 @@ static int do_set_dqblk(struct dquot *dquot, struct fs_disk_quota *di) ...@@ -2531,7 +2526,7 @@ static int do_set_dqblk(struct dquot *dquot, struct fs_disk_quota *di)
} }
int dquot_set_dqblk(struct super_block *sb, struct kqid qid, int dquot_set_dqblk(struct super_block *sb, struct kqid qid,
struct fs_disk_quota *di) struct qc_dqblk *di)
{ {
struct dquot *dquot; struct dquot *dquot;
int rc; int rc;
......
...@@ -118,17 +118,27 @@ static int quota_setinfo(struct super_block *sb, int type, void __user *addr) ...@@ -118,17 +118,27 @@ static int quota_setinfo(struct super_block *sb, int type, void __user *addr)
return sb->s_qcop->set_info(sb, type, &info); return sb->s_qcop->set_info(sb, type, &info);
} }
static void copy_to_if_dqblk(struct if_dqblk *dst, struct fs_disk_quota *src) static inline qsize_t qbtos(qsize_t blocks)
{
return blocks << QIF_DQBLKSIZE_BITS;
}
static inline qsize_t stoqb(qsize_t space)
{
return (space + QIF_DQBLKSIZE - 1) >> QIF_DQBLKSIZE_BITS;
}
static void copy_to_if_dqblk(struct if_dqblk *dst, struct qc_dqblk *src)
{ {
memset(dst, 0, sizeof(*dst)); memset(dst, 0, sizeof(*dst));
dst->dqb_bhardlimit = src->d_blk_hardlimit; dst->dqb_bhardlimit = stoqb(src->d_spc_hardlimit);
dst->dqb_bsoftlimit = src->d_blk_softlimit; dst->dqb_bsoftlimit = stoqb(src->d_spc_softlimit);
dst->dqb_curspace = src->d_bcount; dst->dqb_curspace = src->d_space;
dst->dqb_ihardlimit = src->d_ino_hardlimit; dst->dqb_ihardlimit = src->d_ino_hardlimit;
dst->dqb_isoftlimit = src->d_ino_softlimit; dst->dqb_isoftlimit = src->d_ino_softlimit;
dst->dqb_curinodes = src->d_icount; dst->dqb_curinodes = src->d_ino_count;
dst->dqb_btime = src->d_btimer; dst->dqb_btime = src->d_spc_timer;
dst->dqb_itime = src->d_itimer; dst->dqb_itime = src->d_ino_timer;
dst->dqb_valid = QIF_ALL; dst->dqb_valid = QIF_ALL;
} }
...@@ -136,7 +146,7 @@ static int quota_getquota(struct super_block *sb, int type, qid_t id, ...@@ -136,7 +146,7 @@ static int quota_getquota(struct super_block *sb, int type, qid_t id,
void __user *addr) void __user *addr)
{ {
struct kqid qid; struct kqid qid;
struct fs_disk_quota fdq; struct qc_dqblk fdq;
struct if_dqblk idq; struct if_dqblk idq;
int ret; int ret;
...@@ -154,36 +164,36 @@ static int quota_getquota(struct super_block *sb, int type, qid_t id, ...@@ -154,36 +164,36 @@ static int quota_getquota(struct super_block *sb, int type, qid_t id,
return 0; return 0;
} }
static void copy_from_if_dqblk(struct fs_disk_quota *dst, struct if_dqblk *src) static void copy_from_if_dqblk(struct qc_dqblk *dst, struct if_dqblk *src)
{ {
dst->d_blk_hardlimit = src->dqb_bhardlimit; dst->d_spc_hardlimit = qbtos(src->dqb_bhardlimit);
dst->d_blk_softlimit = src->dqb_bsoftlimit; dst->d_spc_softlimit = qbtos(src->dqb_bsoftlimit);
dst->d_bcount = src->dqb_curspace; dst->d_space = src->dqb_curspace;
dst->d_ino_hardlimit = src->dqb_ihardlimit; dst->d_ino_hardlimit = src->dqb_ihardlimit;
dst->d_ino_softlimit = src->dqb_isoftlimit; dst->d_ino_softlimit = src->dqb_isoftlimit;
dst->d_icount = src->dqb_curinodes; dst->d_ino_count = src->dqb_curinodes;
dst->d_btimer = src->dqb_btime; dst->d_spc_timer = src->dqb_btime;
dst->d_itimer = src->dqb_itime; dst->d_ino_timer = src->dqb_itime;
dst->d_fieldmask = 0; dst->d_fieldmask = 0;
if (src->dqb_valid & QIF_BLIMITS) if (src->dqb_valid & QIF_BLIMITS)
dst->d_fieldmask |= FS_DQ_BSOFT | FS_DQ_BHARD; dst->d_fieldmask |= QC_SPC_SOFT | QC_SPC_HARD;
if (src->dqb_valid & QIF_SPACE) if (src->dqb_valid & QIF_SPACE)
dst->d_fieldmask |= FS_DQ_BCOUNT; dst->d_fieldmask |= QC_SPACE;
if (src->dqb_valid & QIF_ILIMITS) if (src->dqb_valid & QIF_ILIMITS)
dst->d_fieldmask |= FS_DQ_ISOFT | FS_DQ_IHARD; dst->d_fieldmask |= QC_INO_SOFT | QC_INO_HARD;
if (src->dqb_valid & QIF_INODES) if (src->dqb_valid & QIF_INODES)
dst->d_fieldmask |= FS_DQ_ICOUNT; dst->d_fieldmask |= QC_INO_COUNT;
if (src->dqb_valid & QIF_BTIME) if (src->dqb_valid & QIF_BTIME)
dst->d_fieldmask |= FS_DQ_BTIMER; dst->d_fieldmask |= QC_SPC_TIMER;
if (src->dqb_valid & QIF_ITIME) if (src->dqb_valid & QIF_ITIME)
dst->d_fieldmask |= FS_DQ_ITIMER; dst->d_fieldmask |= QC_INO_TIMER;
} }
static int quota_setquota(struct super_block *sb, int type, qid_t id, static int quota_setquota(struct super_block *sb, int type, qid_t id,
void __user *addr) void __user *addr)
{ {
struct fs_disk_quota fdq; struct qc_dqblk fdq;
struct if_dqblk idq; struct if_dqblk idq;
struct kqid qid; struct kqid qid;
...@@ -247,10 +257,78 @@ static int quota_getxstatev(struct super_block *sb, void __user *addr) ...@@ -247,10 +257,78 @@ static int quota_getxstatev(struct super_block *sb, void __user *addr)
return ret; return ret;
} }
/*
* XFS defines BBTOB and BTOBB macros inside fs/xfs/ and we cannot move them
* out of there as xfsprogs rely on definitions being in that header file. So
* just define same functions here for quota purposes.
*/
#define XFS_BB_SHIFT 9
static inline u64 quota_bbtob(u64 blocks)
{
return blocks << XFS_BB_SHIFT;
}
static inline u64 quota_btobb(u64 bytes)
{
return (bytes + (1 << XFS_BB_SHIFT) - 1) >> XFS_BB_SHIFT;
}
static void copy_from_xfs_dqblk(struct qc_dqblk *dst, struct fs_disk_quota *src)
{
dst->d_spc_hardlimit = quota_bbtob(src->d_blk_hardlimit);
dst->d_spc_softlimit = quota_bbtob(src->d_blk_softlimit);
dst->d_ino_hardlimit = src->d_ino_hardlimit;
dst->d_ino_softlimit = src->d_ino_softlimit;
dst->d_space = quota_bbtob(src->d_bcount);
dst->d_ino_count = src->d_icount;
dst->d_ino_timer = src->d_itimer;
dst->d_spc_timer = src->d_btimer;
dst->d_ino_warns = src->d_iwarns;
dst->d_spc_warns = src->d_bwarns;
dst->d_rt_spc_hardlimit = quota_bbtob(src->d_rtb_hardlimit);
dst->d_rt_spc_softlimit = quota_bbtob(src->d_rtb_softlimit);
dst->d_rt_space = quota_bbtob(src->d_rtbcount);
dst->d_rt_spc_timer = src->d_rtbtimer;
dst->d_rt_spc_warns = src->d_rtbwarns;
dst->d_fieldmask = 0;
if (src->d_fieldmask & FS_DQ_ISOFT)
dst->d_fieldmask |= QC_INO_SOFT;
if (src->d_fieldmask & FS_DQ_IHARD)
dst->d_fieldmask |= QC_INO_HARD;
if (src->d_fieldmask & FS_DQ_BSOFT)
dst->d_fieldmask |= QC_SPC_SOFT;
if (src->d_fieldmask & FS_DQ_BHARD)
dst->d_fieldmask |= QC_SPC_HARD;
if (src->d_fieldmask & FS_DQ_RTBSOFT)
dst->d_fieldmask |= QC_RT_SPC_SOFT;
if (src->d_fieldmask & FS_DQ_RTBHARD)
dst->d_fieldmask |= QC_RT_SPC_HARD;
if (src->d_fieldmask & FS_DQ_BTIMER)
dst->d_fieldmask |= QC_SPC_TIMER;
if (src->d_fieldmask & FS_DQ_ITIMER)
dst->d_fieldmask |= QC_INO_TIMER;
if (src->d_fieldmask & FS_DQ_RTBTIMER)
dst->d_fieldmask |= QC_RT_SPC_TIMER;
if (src->d_fieldmask & FS_DQ_BWARNS)
dst->d_fieldmask |= QC_SPC_WARNS;
if (src->d_fieldmask & FS_DQ_IWARNS)
dst->d_fieldmask |= QC_INO_WARNS;
if (src->d_fieldmask & FS_DQ_RTBWARNS)
dst->d_fieldmask |= QC_RT_SPC_WARNS;
if (src->d_fieldmask & FS_DQ_BCOUNT)
dst->d_fieldmask |= QC_SPACE;
if (src->d_fieldmask & FS_DQ_ICOUNT)
dst->d_fieldmask |= QC_INO_COUNT;
if (src->d_fieldmask & FS_DQ_RTBCOUNT)
dst->d_fieldmask |= QC_RT_SPACE;
}
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)
{ {
struct fs_disk_quota fdq; struct fs_disk_quota fdq;
struct qc_dqblk qdq;
struct kqid qid; struct kqid qid;
if (copy_from_user(&fdq, addr, sizeof(fdq))) if (copy_from_user(&fdq, addr, sizeof(fdq)))
...@@ -260,13 +338,44 @@ static int quota_setxquota(struct super_block *sb, int type, qid_t id, ...@@ -260,13 +338,44 @@ 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;
return sb->s_qcop->set_dqblk(sb, qid, &fdq); copy_from_xfs_dqblk(&qdq, &fdq);
return sb->s_qcop->set_dqblk(sb, qid, &qdq);
}
static void copy_to_xfs_dqblk(struct fs_disk_quota *dst, struct qc_dqblk *src,
int type, qid_t id)
{
memset(dst, 0, sizeof(*dst));
dst->d_version = FS_DQUOT_VERSION;
dst->d_id = id;
if (type == USRQUOTA)
dst->d_flags = FS_USER_QUOTA;
else if (type == PRJQUOTA)
dst->d_flags = FS_PROJ_QUOTA;
else
dst->d_flags = FS_GROUP_QUOTA;
dst->d_blk_hardlimit = quota_btobb(src->d_spc_hardlimit);
dst->d_blk_softlimit = quota_btobb(src->d_spc_softlimit);
dst->d_ino_hardlimit = src->d_ino_hardlimit;
dst->d_ino_softlimit = src->d_ino_softlimit;
dst->d_bcount = quota_btobb(src->d_space);
dst->d_icount = src->d_ino_count;
dst->d_itimer = src->d_ino_timer;
dst->d_btimer = src->d_spc_timer;
dst->d_iwarns = src->d_ino_warns;
dst->d_bwarns = src->d_spc_warns;
dst->d_rtb_hardlimit = quota_btobb(src->d_rt_spc_hardlimit);
dst->d_rtb_softlimit = quota_btobb(src->d_rt_spc_softlimit);
dst->d_rtbcount = quota_btobb(src->d_rt_space);
dst->d_rtbtimer = src->d_rt_spc_timer;
dst->d_rtbwarns = src->d_rt_spc_warns;
} }
static int quota_getxquota(struct super_block *sb, int type, qid_t id, static int quota_getxquota(struct super_block *sb, int type, qid_t id,
void __user *addr) void __user *addr)
{ {
struct fs_disk_quota fdq; struct fs_disk_quota fdq;
struct qc_dqblk qdq;
struct kqid qid; struct kqid qid;
int ret; int ret;
...@@ -275,8 +384,11 @@ static int quota_getxquota(struct super_block *sb, int type, qid_t id, ...@@ -275,8 +384,11 @@ static int quota_getxquota(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;
ret = sb->s_qcop->get_dqblk(sb, qid, &fdq); ret = sb->s_qcop->get_dqblk(sb, qid, &qdq);
if (!ret && copy_to_user(addr, &fdq, sizeof(fdq))) if (ret)
return ret;
copy_to_xfs_dqblk(&fdq, &qdq, type, id);
if (copy_to_user(addr, &fdq, sizeof(fdq)))
return -EFAULT; return -EFAULT;
return ret; return ret;
} }
......
...@@ -224,7 +224,7 @@ long udf_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ...@@ -224,7 +224,7 @@ long udf_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
static int udf_release_file(struct inode *inode, struct file *filp) static int udf_release_file(struct inode *inode, struct file *filp)
{ {
if (filp->f_mode & FMODE_WRITE && if (filp->f_mode & FMODE_WRITE &&
atomic_read(&inode->i_writecount) > 1) { atomic_read(&inode->i_writecount) == 1) {
/* /*
* Grab i_mutex to avoid races with writes changing i_size * Grab i_mutex to avoid races with writes changing i_size
* while we are running. * while we are running.
......
...@@ -166,9 +166,9 @@ extern void xfs_qm_dqrele_all_inodes(struct xfs_mount *, uint); ...@@ -166,9 +166,9 @@ extern void xfs_qm_dqrele_all_inodes(struct xfs_mount *, uint);
/* quota ops */ /* quota ops */
extern int xfs_qm_scall_trunc_qfiles(struct xfs_mount *, uint); extern int xfs_qm_scall_trunc_qfiles(struct xfs_mount *, uint);
extern int xfs_qm_scall_getquota(struct xfs_mount *, xfs_dqid_t, extern int xfs_qm_scall_getquota(struct xfs_mount *, xfs_dqid_t,
uint, struct fs_disk_quota *); 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 fs_disk_quota *); struct qc_dqblk *);
extern int xfs_qm_scall_getqstat(struct xfs_mount *, extern int xfs_qm_scall_getqstat(struct xfs_mount *,
struct fs_quota_stat *); struct fs_quota_stat *);
extern int xfs_qm_scall_getqstatv(struct xfs_mount *, extern int xfs_qm_scall_getqstatv(struct xfs_mount *,
......
...@@ -39,7 +39,6 @@ STATIC int xfs_qm_log_quotaoff(xfs_mount_t *, xfs_qoff_logitem_t **, uint); ...@@ -39,7 +39,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 *, STATIC int xfs_qm_log_quotaoff_end(xfs_mount_t *, xfs_qoff_logitem_t *,
uint); uint);
STATIC uint xfs_qm_export_flags(uint); STATIC uint xfs_qm_export_flags(uint);
STATIC uint xfs_qm_export_qtype_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
...@@ -573,8 +572,8 @@ xfs_qm_scall_getqstatv( ...@@ -573,8 +572,8 @@ xfs_qm_scall_getqstatv(
return 0; return 0;
} }
#define XFS_DQ_MASK \ #define XFS_QC_MASK \
(FS_DQ_LIMIT_MASK | FS_DQ_TIMER_MASK | FS_DQ_WARNS_MASK) (QC_LIMIT_MASK | QC_TIMER_MASK | QC_WARNS_MASK)
/* /*
* Adjust quota limits, and start/stop timers accordingly. * Adjust quota limits, and start/stop timers accordingly.
...@@ -584,7 +583,7 @@ xfs_qm_scall_setqlim( ...@@ -584,7 +583,7 @@ xfs_qm_scall_setqlim(
struct xfs_mount *mp, struct xfs_mount *mp,
xfs_dqid_t id, xfs_dqid_t id,
uint type, uint type,
fs_disk_quota_t *newlim) struct qc_dqblk *newlim)
{ {
struct xfs_quotainfo *q = mp->m_quotainfo; struct xfs_quotainfo *q = mp->m_quotainfo;
struct xfs_disk_dquot *ddq; struct xfs_disk_dquot *ddq;
...@@ -593,9 +592,9 @@ xfs_qm_scall_setqlim( ...@@ -593,9 +592,9 @@ xfs_qm_scall_setqlim(
int error; int error;
xfs_qcnt_t hard, soft; xfs_qcnt_t hard, soft;
if (newlim->d_fieldmask & ~XFS_DQ_MASK) if (newlim->d_fieldmask & ~XFS_QC_MASK)
return -EINVAL; return -EINVAL;
if ((newlim->d_fieldmask & XFS_DQ_MASK) == 0) if ((newlim->d_fieldmask & XFS_QC_MASK) == 0)
return 0; return 0;
/* /*
...@@ -633,11 +632,11 @@ xfs_qm_scall_setqlim( ...@@ -633,11 +632,11 @@ xfs_qm_scall_setqlim(
/* /*
* Make sure that hardlimits are >= soft limits before changing. * Make sure that hardlimits are >= soft limits before changing.
*/ */
hard = (newlim->d_fieldmask & FS_DQ_BHARD) ? hard = (newlim->d_fieldmask & QC_SPC_HARD) ?
(xfs_qcnt_t) XFS_BB_TO_FSB(mp, newlim->d_blk_hardlimit) : (xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_spc_hardlimit) :
be64_to_cpu(ddq->d_blk_hardlimit); be64_to_cpu(ddq->d_blk_hardlimit);
soft = (newlim->d_fieldmask & FS_DQ_BSOFT) ? soft = (newlim->d_fieldmask & QC_SPC_SOFT) ?
(xfs_qcnt_t) XFS_BB_TO_FSB(mp, newlim->d_blk_softlimit) : (xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_spc_softlimit) :
be64_to_cpu(ddq->d_blk_softlimit); be64_to_cpu(ddq->d_blk_softlimit);
if (hard == 0 || hard >= soft) { if (hard == 0 || hard >= soft) {
ddq->d_blk_hardlimit = cpu_to_be64(hard); ddq->d_blk_hardlimit = cpu_to_be64(hard);
...@@ -650,11 +649,11 @@ xfs_qm_scall_setqlim( ...@@ -650,11 +649,11 @@ xfs_qm_scall_setqlim(
} else { } else {
xfs_debug(mp, "blkhard %Ld < blksoft %Ld", hard, soft); xfs_debug(mp, "blkhard %Ld < blksoft %Ld", hard, soft);
} }
hard = (newlim->d_fieldmask & FS_DQ_RTBHARD) ? hard = (newlim->d_fieldmask & QC_RT_SPC_HARD) ?
(xfs_qcnt_t) XFS_BB_TO_FSB(mp, newlim->d_rtb_hardlimit) : (xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_rt_spc_hardlimit) :
be64_to_cpu(ddq->d_rtb_hardlimit); be64_to_cpu(ddq->d_rtb_hardlimit);
soft = (newlim->d_fieldmask & FS_DQ_RTBSOFT) ? soft = (newlim->d_fieldmask & QC_RT_SPC_SOFT) ?
(xfs_qcnt_t) XFS_BB_TO_FSB(mp, newlim->d_rtb_softlimit) : (xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_rt_spc_softlimit) :
be64_to_cpu(ddq->d_rtb_softlimit); be64_to_cpu(ddq->d_rtb_softlimit);
if (hard == 0 || hard >= soft) { if (hard == 0 || hard >= soft) {
ddq->d_rtb_hardlimit = cpu_to_be64(hard); ddq->d_rtb_hardlimit = cpu_to_be64(hard);
...@@ -667,10 +666,10 @@ xfs_qm_scall_setqlim( ...@@ -667,10 +666,10 @@ xfs_qm_scall_setqlim(
xfs_debug(mp, "rtbhard %Ld < rtbsoft %Ld", hard, soft); xfs_debug(mp, "rtbhard %Ld < rtbsoft %Ld", hard, soft);
} }
hard = (newlim->d_fieldmask & FS_DQ_IHARD) ? hard = (newlim->d_fieldmask & QC_INO_HARD) ?
(xfs_qcnt_t) newlim->d_ino_hardlimit : (xfs_qcnt_t) newlim->d_ino_hardlimit :
be64_to_cpu(ddq->d_ino_hardlimit); be64_to_cpu(ddq->d_ino_hardlimit);
soft = (newlim->d_fieldmask & FS_DQ_ISOFT) ? soft = (newlim->d_fieldmask & QC_INO_SOFT) ?
(xfs_qcnt_t) newlim->d_ino_softlimit : (xfs_qcnt_t) newlim->d_ino_softlimit :
be64_to_cpu(ddq->d_ino_softlimit); be64_to_cpu(ddq->d_ino_softlimit);
if (hard == 0 || hard >= soft) { if (hard == 0 || hard >= soft) {
...@@ -687,12 +686,12 @@ xfs_qm_scall_setqlim( ...@@ -687,12 +686,12 @@ xfs_qm_scall_setqlim(
/* /*
* Update warnings counter(s) if requested * Update warnings counter(s) if requested
*/ */
if (newlim->d_fieldmask & FS_DQ_BWARNS) if (newlim->d_fieldmask & QC_SPC_WARNS)
ddq->d_bwarns = cpu_to_be16(newlim->d_bwarns); ddq->d_bwarns = cpu_to_be16(newlim->d_spc_warns);
if (newlim->d_fieldmask & FS_DQ_IWARNS) if (newlim->d_fieldmask & QC_INO_WARNS)
ddq->d_iwarns = cpu_to_be16(newlim->d_iwarns); ddq->d_iwarns = cpu_to_be16(newlim->d_ino_warns);
if (newlim->d_fieldmask & FS_DQ_RTBWARNS) if (newlim->d_fieldmask & QC_RT_SPC_WARNS)
ddq->d_rtbwarns = cpu_to_be16(newlim->d_rtbwarns); ddq->d_rtbwarns = cpu_to_be16(newlim->d_rt_spc_warns);
if (id == 0) { if (id == 0) {
/* /*
...@@ -702,24 +701,24 @@ xfs_qm_scall_setqlim( ...@@ -702,24 +701,24 @@ xfs_qm_scall_setqlim(
* soft and hard limit values (already done, above), and * soft and hard limit values (already done, above), and
* for warnings. * for warnings.
*/ */
if (newlim->d_fieldmask & FS_DQ_BTIMER) { if (newlim->d_fieldmask & QC_SPC_TIMER) {
q->qi_btimelimit = newlim->d_btimer; q->qi_btimelimit = newlim->d_spc_timer;
ddq->d_btimer = cpu_to_be32(newlim->d_btimer); ddq->d_btimer = cpu_to_be32(newlim->d_spc_timer);
} }
if (newlim->d_fieldmask & FS_DQ_ITIMER) { if (newlim->d_fieldmask & QC_INO_TIMER) {
q->qi_itimelimit = newlim->d_itimer; q->qi_itimelimit = newlim->d_ino_timer;
ddq->d_itimer = cpu_to_be32(newlim->d_itimer); ddq->d_itimer = cpu_to_be32(newlim->d_ino_timer);
} }
if (newlim->d_fieldmask & FS_DQ_RTBTIMER) { if (newlim->d_fieldmask & QC_RT_SPC_TIMER) {
q->qi_rtbtimelimit = newlim->d_rtbtimer; q->qi_rtbtimelimit = newlim->d_rt_spc_timer;
ddq->d_rtbtimer = cpu_to_be32(newlim->d_rtbtimer); ddq->d_rtbtimer = cpu_to_be32(newlim->d_rt_spc_timer);
} }
if (newlim->d_fieldmask & FS_DQ_BWARNS) if (newlim->d_fieldmask & QC_SPC_WARNS)
q->qi_bwarnlimit = newlim->d_bwarns; q->qi_bwarnlimit = newlim->d_spc_warns;
if (newlim->d_fieldmask & FS_DQ_IWARNS) if (newlim->d_fieldmask & QC_INO_WARNS)
q->qi_iwarnlimit = newlim->d_iwarns; q->qi_iwarnlimit = newlim->d_ino_warns;
if (newlim->d_fieldmask & FS_DQ_RTBWARNS) if (newlim->d_fieldmask & QC_RT_SPC_WARNS)
q->qi_rtbwarnlimit = newlim->d_rtbwarns; q->qi_rtbwarnlimit = newlim->d_rt_spc_warns;
} else { } else {
/* /*
* If the user is now over quota, start the timelimit. * If the user is now over quota, start the timelimit.
...@@ -824,7 +823,7 @@ xfs_qm_scall_getquota( ...@@ -824,7 +823,7 @@ xfs_qm_scall_getquota(
struct xfs_mount *mp, struct xfs_mount *mp,
xfs_dqid_t id, xfs_dqid_t id,
uint type, uint type,
struct fs_disk_quota *dst) struct qc_dqblk *dst)
{ {
struct xfs_dquot *dqp; struct xfs_dquot *dqp;
int error; int error;
...@@ -848,28 +847,25 @@ xfs_qm_scall_getquota( ...@@ -848,28 +847,25 @@ xfs_qm_scall_getquota(
} }
memset(dst, 0, sizeof(*dst)); memset(dst, 0, sizeof(*dst));
dst->d_version = FS_DQUOT_VERSION; dst->d_spc_hardlimit =
dst->d_flags = xfs_qm_export_qtype_flags(dqp->q_core.d_flags); XFS_FSB_TO_B(mp, be64_to_cpu(dqp->q_core.d_blk_hardlimit));
dst->d_id = be32_to_cpu(dqp->q_core.d_id); dst->d_spc_softlimit =
dst->d_blk_hardlimit = XFS_FSB_TO_B(mp, be64_to_cpu(dqp->q_core.d_blk_softlimit));
XFS_FSB_TO_BB(mp, be64_to_cpu(dqp->q_core.d_blk_hardlimit));
dst->d_blk_softlimit =
XFS_FSB_TO_BB(mp, be64_to_cpu(dqp->q_core.d_blk_softlimit));
dst->d_ino_hardlimit = be64_to_cpu(dqp->q_core.d_ino_hardlimit); dst->d_ino_hardlimit = be64_to_cpu(dqp->q_core.d_ino_hardlimit);
dst->d_ino_softlimit = be64_to_cpu(dqp->q_core.d_ino_softlimit); dst->d_ino_softlimit = be64_to_cpu(dqp->q_core.d_ino_softlimit);
dst->d_bcount = XFS_FSB_TO_BB(mp, dqp->q_res_bcount); dst->d_space = XFS_FSB_TO_B(mp, dqp->q_res_bcount);
dst->d_icount = dqp->q_res_icount; dst->d_ino_count = dqp->q_res_icount;
dst->d_btimer = be32_to_cpu(dqp->q_core.d_btimer); dst->d_spc_timer = be32_to_cpu(dqp->q_core.d_btimer);
dst->d_itimer = be32_to_cpu(dqp->q_core.d_itimer); dst->d_ino_timer = be32_to_cpu(dqp->q_core.d_itimer);
dst->d_iwarns = be16_to_cpu(dqp->q_core.d_iwarns); dst->d_ino_warns = be16_to_cpu(dqp->q_core.d_iwarns);
dst->d_bwarns = be16_to_cpu(dqp->q_core.d_bwarns); dst->d_spc_warns = be16_to_cpu(dqp->q_core.d_bwarns);
dst->d_rtb_hardlimit = dst->d_rt_spc_hardlimit =
XFS_FSB_TO_BB(mp, be64_to_cpu(dqp->q_core.d_rtb_hardlimit)); XFS_FSB_TO_B(mp, be64_to_cpu(dqp->q_core.d_rtb_hardlimit));
dst->d_rtb_softlimit = dst->d_rt_spc_softlimit =
XFS_FSB_TO_BB(mp, be64_to_cpu(dqp->q_core.d_rtb_softlimit)); XFS_FSB_TO_B(mp, be64_to_cpu(dqp->q_core.d_rtb_softlimit));
dst->d_rtbcount = XFS_FSB_TO_BB(mp, dqp->q_res_rtbcount); dst->d_rt_space = XFS_FSB_TO_B(mp, dqp->q_res_rtbcount);
dst->d_rtbtimer = be32_to_cpu(dqp->q_core.d_rtbtimer); dst->d_rt_spc_timer = be32_to_cpu(dqp->q_core.d_rtbtimer);
dst->d_rtbwarns = be16_to_cpu(dqp->q_core.d_rtbwarns); dst->d_rt_spc_warns = be16_to_cpu(dqp->q_core.d_rtbwarns);
/* /*
* Internally, we don't reset all the timers when quota enforcement * Internally, we don't reset all the timers when quota enforcement
...@@ -882,23 +878,23 @@ xfs_qm_scall_getquota( ...@@ -882,23 +878,23 @@ xfs_qm_scall_getquota(
dqp->q_core.d_flags == XFS_DQ_GROUP) || dqp->q_core.d_flags == XFS_DQ_GROUP) ||
(!XFS_IS_PQUOTA_ENFORCED(mp) && (!XFS_IS_PQUOTA_ENFORCED(mp) &&
dqp->q_core.d_flags == XFS_DQ_PROJ)) { dqp->q_core.d_flags == XFS_DQ_PROJ)) {
dst->d_btimer = 0; dst->d_spc_timer = 0;
dst->d_itimer = 0; dst->d_ino_timer = 0;
dst->d_rtbtimer = 0; dst->d_rt_spc_timer = 0;
} }
#ifdef DEBUG #ifdef DEBUG
if (((XFS_IS_UQUOTA_ENFORCED(mp) && dst->d_flags == FS_USER_QUOTA) || if (((XFS_IS_UQUOTA_ENFORCED(mp) && type == XFS_DQ_USER) ||
(XFS_IS_GQUOTA_ENFORCED(mp) && dst->d_flags == FS_GROUP_QUOTA) || (XFS_IS_GQUOTA_ENFORCED(mp) && type == XFS_DQ_GROUP) ||
(XFS_IS_PQUOTA_ENFORCED(mp) && dst->d_flags == FS_PROJ_QUOTA)) && (XFS_IS_PQUOTA_ENFORCED(mp) && type == XFS_DQ_PROJ)) &&
dst->d_id != 0) { id != 0) {
if ((dst->d_bcount > dst->d_blk_softlimit) && if ((dst->d_space > dst->d_spc_softlimit) &&
(dst->d_blk_softlimit > 0)) { (dst->d_spc_softlimit > 0)) {
ASSERT(dst->d_btimer != 0); ASSERT(dst->d_spc_timer != 0);
} }
if ((dst->d_icount > dst->d_ino_softlimit) && if ((dst->d_ino_count > dst->d_ino_softlimit) &&
(dst->d_ino_softlimit > 0)) { (dst->d_ino_softlimit > 0)) {
ASSERT(dst->d_itimer != 0); ASSERT(dst->d_ino_timer != 0);
} }
} }
#endif #endif
...@@ -907,26 +903,6 @@ xfs_qm_scall_getquota( ...@@ -907,26 +903,6 @@ xfs_qm_scall_getquota(
return error; return error;
} }
STATIC uint
xfs_qm_export_qtype_flags(
uint flags)
{
/*
* Can't be more than one, or none.
*/
ASSERT((flags & (FS_PROJ_QUOTA | FS_USER_QUOTA)) !=
(FS_PROJ_QUOTA | FS_USER_QUOTA));
ASSERT((flags & (FS_PROJ_QUOTA | FS_GROUP_QUOTA)) !=
(FS_PROJ_QUOTA | FS_GROUP_QUOTA));
ASSERT((flags & (FS_USER_QUOTA | FS_GROUP_QUOTA)) !=
(FS_USER_QUOTA | FS_GROUP_QUOTA));
ASSERT((flags & (FS_PROJ_QUOTA|FS_USER_QUOTA|FS_GROUP_QUOTA)) != 0);
return (flags & XFS_DQ_USER) ?
FS_USER_QUOTA : (flags & XFS_DQ_PROJ) ?
FS_PROJ_QUOTA : FS_GROUP_QUOTA;
}
STATIC uint STATIC uint
xfs_qm_export_flags( xfs_qm_export_flags(
uint flags) uint flags)
......
...@@ -131,7 +131,7 @@ STATIC int ...@@ -131,7 +131,7 @@ STATIC int
xfs_fs_get_dqblk( xfs_fs_get_dqblk(
struct super_block *sb, struct super_block *sb,
struct kqid qid, struct kqid qid,
struct fs_disk_quota *fdq) struct qc_dqblk *qdq)
{ {
struct xfs_mount *mp = XFS_M(sb); struct xfs_mount *mp = XFS_M(sb);
...@@ -141,14 +141,14 @@ xfs_fs_get_dqblk( ...@@ -141,14 +141,14 @@ xfs_fs_get_dqblk(
return -ESRCH; return -ESRCH;
return xfs_qm_scall_getquota(mp, from_kqid(&init_user_ns, qid), return xfs_qm_scall_getquota(mp, from_kqid(&init_user_ns, qid),
xfs_quota_type(qid.type), fdq); xfs_quota_type(qid.type), qdq);
} }
STATIC int STATIC int
xfs_fs_set_dqblk( xfs_fs_set_dqblk(
struct super_block *sb, struct super_block *sb,
struct kqid qid, struct kqid qid,
struct fs_disk_quota *fdq) struct qc_dqblk *qdq)
{ {
struct xfs_mount *mp = XFS_M(sb); struct xfs_mount *mp = XFS_M(sb);
...@@ -160,7 +160,7 @@ xfs_fs_set_dqblk( ...@@ -160,7 +160,7 @@ xfs_fs_set_dqblk(
return -ESRCH; return -ESRCH;
return xfs_qm_scall_setqlim(mp, from_kqid(&init_user_ns, qid), return xfs_qm_scall_setqlim(mp, from_kqid(&init_user_ns, qid),
xfs_quota_type(qid.type), fdq); xfs_quota_type(qid.type), qdq);
} }
const struct quotactl_ops xfs_quotactl_operations = { const struct quotactl_ops xfs_quotactl_operations = {
......
...@@ -321,6 +321,49 @@ struct dquot_operations { ...@@ -321,6 +321,49 @@ struct dquot_operations {
struct path; struct path;
/* Structure for communicating via ->get_dqblk() & ->set_dqblk() */
struct qc_dqblk {
int d_fieldmask; /* mask of fields to change in ->set_dqblk() */
u64 d_spc_hardlimit; /* absolute limit on used space */
u64 d_spc_softlimit; /* preferred limit on used space */
u64 d_ino_hardlimit; /* maximum # allocated inodes */
u64 d_ino_softlimit; /* preferred inode limit */
u64 d_space; /* Space owned by the user */
u64 d_ino_count; /* # inodes owned by the user */
s64 d_ino_timer; /* zero if within inode limits */
/* if not, we refuse service */
s64 d_spc_timer; /* similar to above; for space */
int d_ino_warns; /* # warnings issued wrt num inodes */
int d_spc_warns; /* # warnings issued wrt used space */
u64 d_rt_spc_hardlimit; /* absolute limit on realtime space */
u64 d_rt_spc_softlimit; /* preferred limit on RT space */
u64 d_rt_space; /* realtime space owned */
s64 d_rt_spc_timer; /* similar to above; for RT space */
int d_rt_spc_warns; /* # warnings issued wrt RT space */
};
/* Field specifiers for ->set_dqblk() in struct qc_dqblk */
#define QC_INO_SOFT (1<<0)
#define QC_INO_HARD (1<<1)
#define QC_SPC_SOFT (1<<2)
#define QC_SPC_HARD (1<<3)
#define QC_RT_SPC_SOFT (1<<4)
#define QC_RT_SPC_HARD (1<<5)
#define QC_LIMIT_MASK (QC_INO_SOFT | QC_INO_HARD | QC_SPC_SOFT | QC_SPC_HARD | \
QC_RT_SPC_SOFT | QC_RT_SPC_HARD)
#define QC_SPC_TIMER (1<<6)
#define QC_INO_TIMER (1<<7)
#define QC_RT_SPC_TIMER (1<<8)
#define QC_TIMER_MASK (QC_SPC_TIMER | QC_INO_TIMER | QC_RT_SPC_TIMER)
#define QC_SPC_WARNS (1<<9)
#define QC_INO_WARNS (1<<10)
#define QC_RT_SPC_WARNS (1<<11)
#define QC_WARNS_MASK (QC_SPC_WARNS | QC_INO_WARNS | QC_RT_SPC_WARNS)
#define QC_SPACE (1<<12)
#define QC_INO_COUNT (1<<13)
#define QC_RT_SPACE (1<<14)
#define QC_ACCT_MASK (QC_SPACE | QC_INO_COUNT | QC_RT_SPACE)
/* Operations handling requests from userspace */ /* Operations handling requests from userspace */
struct quotactl_ops { struct quotactl_ops {
int (*quota_on)(struct super_block *, int, int, struct path *); int (*quota_on)(struct super_block *, int, int, struct path *);
...@@ -329,8 +372,8 @@ struct quotactl_ops { ...@@ -329,8 +372,8 @@ struct quotactl_ops {
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 (*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 if_dqinfo *);
int (*get_dqblk)(struct super_block *, struct kqid, struct fs_disk_quota *); int (*get_dqblk)(struct super_block *, struct kqid, struct qc_dqblk *);
int (*set_dqblk)(struct super_block *, struct kqid, struct fs_disk_quota *); int (*set_dqblk)(struct super_block *, struct kqid, struct qc_dqblk *);
int (*get_xstate)(struct super_block *, struct fs_quota_stat *); int (*get_xstate)(struct super_block *, struct fs_quota_stat *);
int (*set_xstate)(struct super_block *, unsigned int, int); int (*set_xstate)(struct super_block *, unsigned int, int);
int (*get_xstatev)(struct super_block *, struct fs_quota_statv *); int (*get_xstatev)(struct super_block *, struct fs_quota_statv *);
......
...@@ -98,9 +98,9 @@ int dquot_quota_sync(struct super_block *sb, int type); ...@@ -98,9 +98,9 @@ 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_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_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
int dquot_get_dqblk(struct super_block *sb, struct kqid id, int dquot_get_dqblk(struct super_block *sb, struct kqid id,
struct fs_disk_quota *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,
struct fs_disk_quota *di); struct qc_dqblk *di);
int __dquot_transfer(struct inode *inode, struct dquot **transfer_to); int __dquot_transfer(struct inode *inode, struct dquot **transfer_to);
int dquot_transfer(struct inode *inode, struct iattr *iattr); int dquot_transfer(struct inode *inode, struct iattr *iattr);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment